1343181Sdim//===-- PdbUtil.cpp ---------------------------------------------*- C++ -*-===//
2343181Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6343181Sdim//
7343181Sdim//===----------------------------------------------------------------------===//
8343181Sdim
9343181Sdim#include "PdbUtil.h"
10343181Sdim
11343181Sdim#include "DWARFLocationExpression.h"
12343181Sdim#include "PdbIndex.h"
13343181Sdim#include "PdbSymUid.h"
14343181Sdim
15343181Sdim#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
16343181Sdim#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
17353358Sdim#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
18343181Sdim#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
19343181Sdim
20343181Sdim#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
21353358Sdim#include "lldb/Symbol/Block.h"
22343181Sdim#include "lldb/Utility/LLDBAssert.h"
23343181Sdim#include "lldb/lldb-enumerations.h"
24343181Sdim
25343181Sdimusing namespace lldb_private;
26343181Sdimusing namespace lldb_private::npdb;
27343181Sdimusing namespace llvm::codeview;
28343181Sdimusing namespace llvm::pdb;
29343181Sdim
30343181Sdimstatic Variable::RangeList
31343181SdimMakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
32343181Sdim              llvm::ArrayRef<LocalVariableAddrGap> gaps) {
33343181Sdim  lldb::addr_t start =
34343181Sdim      index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
35343181Sdim  lldb::addr_t end = start + range.Range;
36343181Sdim
37343181Sdim  Variable::RangeList result;
38343181Sdim  while (!gaps.empty()) {
39343181Sdim    const LocalVariableAddrGap &gap = gaps.front();
40343181Sdim
41343181Sdim    lldb::addr_t size = gap.GapStartOffset - start;
42343181Sdim    result.Append(start, size);
43343181Sdim    start += gap.Range;
44343181Sdim    gaps = gaps.drop_front();
45343181Sdim  }
46343181Sdim
47353358Sdim  result.Append(start, end - start);
48343181Sdim  return result;
49343181Sdim}
50343181Sdim
51343181SdimCVTagRecord CVTagRecord::create(CVType type) {
52343181Sdim  assert(IsTagRecord(type) && "type is not a tag record!");
53343181Sdim  switch (type.kind()) {
54343181Sdim  case LF_CLASS:
55343181Sdim  case LF_STRUCTURE:
56343181Sdim  case LF_INTERFACE: {
57343181Sdim    ClassRecord cr;
58343181Sdim    llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));
59343181Sdim    return CVTagRecord(std::move(cr));
60343181Sdim  }
61343181Sdim  case LF_UNION: {
62343181Sdim    UnionRecord ur;
63343181Sdim    llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));
64343181Sdim    return CVTagRecord(std::move(ur));
65343181Sdim  }
66343181Sdim  case LF_ENUM: {
67343181Sdim    EnumRecord er;
68343181Sdim    llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));
69343181Sdim    return CVTagRecord(std::move(er));
70343181Sdim  }
71343181Sdim  default:
72343181Sdim    llvm_unreachable("Unreachable!");
73343181Sdim  }
74343181Sdim}
75343181Sdim
76343181SdimCVTagRecord::CVTagRecord(ClassRecord &&c)
77343181Sdim    : cvclass(std::move(c)),
78343181Sdim      m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
79343181SdimCVTagRecord::CVTagRecord(UnionRecord &&u)
80343181Sdim    : cvunion(std::move(u)), m_kind(Union) {}
81343181SdimCVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
82343181Sdim
83343181SdimPDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
84343181Sdim  switch (kind) {
85343181Sdim  case S_COMPILE3:
86343181Sdim  case S_OBJNAME:
87343181Sdim    return PDB_SymType::CompilandDetails;
88343181Sdim  case S_ENVBLOCK:
89343181Sdim    return PDB_SymType::CompilandEnv;
90343181Sdim  case S_THUNK32:
91343181Sdim  case S_TRAMPOLINE:
92343181Sdim    return PDB_SymType::Thunk;
93343181Sdim  case S_COFFGROUP:
94343181Sdim    return PDB_SymType::CoffGroup;
95343181Sdim  case S_EXPORT:
96343181Sdim    return PDB_SymType::Export;
97343181Sdim  case S_LPROC32:
98343181Sdim  case S_GPROC32:
99343181Sdim  case S_LPROC32_DPC:
100343181Sdim    return PDB_SymType::Function;
101343181Sdim  case S_PUB32:
102343181Sdim    return PDB_SymType::PublicSymbol;
103343181Sdim  case S_INLINESITE:
104343181Sdim    return PDB_SymType::InlineSite;
105343181Sdim  case S_LOCAL:
106343181Sdim  case S_BPREL32:
107343181Sdim  case S_REGREL32:
108343181Sdim  case S_MANCONSTANT:
109343181Sdim  case S_CONSTANT:
110343181Sdim  case S_LDATA32:
111343181Sdim  case S_GDATA32:
112343181Sdim  case S_LMANDATA:
113343181Sdim  case S_GMANDATA:
114343181Sdim  case S_LTHREAD32:
115343181Sdim  case S_GTHREAD32:
116343181Sdim    return PDB_SymType::Data;
117343181Sdim  case S_BLOCK32:
118343181Sdim    return PDB_SymType::Block;
119343181Sdim  case S_LABEL32:
120343181Sdim    return PDB_SymType::Label;
121343181Sdim  case S_CALLSITEINFO:
122343181Sdim    return PDB_SymType::CallSite;
123343181Sdim  case S_HEAPALLOCSITE:
124343181Sdim    return PDB_SymType::HeapAllocationSite;
125343181Sdim  case S_CALLEES:
126343181Sdim    return PDB_SymType::Callee;
127343181Sdim  case S_CALLERS:
128343181Sdim    return PDB_SymType::Caller;
129343181Sdim  default:
130343181Sdim    lldbassert(false && "Invalid symbol record kind!");
131343181Sdim  }
132343181Sdim  return PDB_SymType::None;
133343181Sdim}
134343181Sdim
135343181SdimPDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
136343181Sdim  switch (kind) {
137343181Sdim  case LF_ARRAY:
138343181Sdim    return PDB_SymType::ArrayType;
139343181Sdim  case LF_ARGLIST:
140343181Sdim    return PDB_SymType::FunctionSig;
141343181Sdim  case LF_BCLASS:
142343181Sdim    return PDB_SymType::BaseClass;
143343181Sdim  case LF_BINTERFACE:
144343181Sdim    return PDB_SymType::BaseInterface;
145343181Sdim  case LF_CLASS:
146343181Sdim  case LF_STRUCTURE:
147343181Sdim  case LF_INTERFACE:
148343181Sdim  case LF_UNION:
149343181Sdim    return PDB_SymType::UDT;
150343181Sdim  case LF_POINTER:
151343181Sdim    return PDB_SymType::PointerType;
152343181Sdim  case LF_ENUM:
153343181Sdim    return PDB_SymType::Enum;
154343181Sdim  case LF_PROCEDURE:
155343181Sdim    return PDB_SymType::FunctionSig;
156343181Sdim  case LF_BITFIELD:
157343181Sdim    return PDB_SymType::BuiltinType;
158343181Sdim  default:
159343181Sdim    lldbassert(false && "Invalid type record kind!");
160343181Sdim  }
161343181Sdim  return PDB_SymType::None;
162343181Sdim}
163343181Sdim
164343181Sdimbool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
165343181Sdim  switch (sym.kind()) {
166343181Sdim  case S_GPROC32:
167343181Sdim  case S_LPROC32:
168343181Sdim  case S_GPROC32_ID:
169343181Sdim  case S_LPROC32_ID:
170343181Sdim  case S_LPROC32_DPC:
171343181Sdim  case S_LPROC32_DPC_ID:
172343181Sdim  case S_THUNK32:
173343181Sdim  case S_TRAMPOLINE:
174343181Sdim  case S_COFFGROUP:
175343181Sdim  case S_BLOCK32:
176343181Sdim  case S_LABEL32:
177343181Sdim  case S_CALLSITEINFO:
178343181Sdim  case S_HEAPALLOCSITE:
179343181Sdim  case S_LDATA32:
180343181Sdim  case S_GDATA32:
181343181Sdim  case S_LMANDATA:
182343181Sdim  case S_GMANDATA:
183343181Sdim  case S_LTHREAD32:
184343181Sdim  case S_GTHREAD32:
185343181Sdim    return true;
186343181Sdim  default:
187343181Sdim    return false;
188343181Sdim  }
189343181Sdim}
190343181Sdim
191343181Sdimbool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
192343181Sdim  switch (sym.kind()) {
193343181Sdim  case S_GPROC32:
194343181Sdim  case S_LPROC32:
195343181Sdim  case S_GPROC32_ID:
196343181Sdim  case S_LPROC32_ID:
197343181Sdim  case S_LPROC32_DPC:
198343181Sdim  case S_LPROC32_DPC_ID:
199343181Sdim  case S_THUNK32:
200343181Sdim  case S_TRAMPOLINE:
201343181Sdim  case S_COFFGROUP:
202343181Sdim  case S_BLOCK32:
203343181Sdim    return true;
204343181Sdim  default:
205343181Sdim    return false;
206343181Sdim  }
207343181Sdim}
208343181Sdim
209343181Sdimtemplate <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
210343181Sdim  RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
211343181Sdim  cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
212343181Sdim  return record;
213343181Sdim}
214343181Sdim
215343181Sdimtemplate <typename RecordT>
216343181Sdimstatic SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
217343181Sdim  RecordT record = createRecord<RecordT>(sym);
218343181Sdim  return {record.Segment, record.CodeOffset};
219343181Sdim}
220343181Sdim
221343181Sdimtemplate <>
222343181SdimSegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
223343181Sdim  TrampolineSym record = createRecord<TrampolineSym>(sym);
224343181Sdim  return {record.ThunkSection, record.ThunkOffset};
225343181Sdim}
226343181Sdim
227343181Sdimtemplate <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
228343181Sdim  Thunk32Sym record = createRecord<Thunk32Sym>(sym);
229343181Sdim  return {record.Segment, record.Offset};
230343181Sdim}
231343181Sdim
232343181Sdimtemplate <>
233343181SdimSegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
234343181Sdim  CoffGroupSym record = createRecord<CoffGroupSym>(sym);
235343181Sdim  return {record.Segment, record.Offset};
236343181Sdim}
237343181Sdim
238343181Sdimtemplate <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
239343181Sdim  DataSym record = createRecord<DataSym>(sym);
240343181Sdim  return {record.Segment, record.DataOffset};
241343181Sdim}
242343181Sdim
243343181Sdimtemplate <>
244343181SdimSegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
245343181Sdim  ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
246343181Sdim  return {record.Segment, record.DataOffset};
247343181Sdim}
248343181Sdim
249343181SdimSegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
250343181Sdim  switch (sym.kind()) {
251343181Sdim  case S_GPROC32:
252343181Sdim  case S_LPROC32:
253343181Sdim  case S_GPROC32_ID:
254343181Sdim  case S_LPROC32_ID:
255343181Sdim  case S_LPROC32_DPC:
256343181Sdim  case S_LPROC32_DPC_ID:
257343181Sdim    return ::GetSegmentAndOffset<ProcSym>(sym);
258343181Sdim  case S_THUNK32:
259343181Sdim    return ::GetSegmentAndOffset<Thunk32Sym>(sym);
260343181Sdim    break;
261343181Sdim  case S_TRAMPOLINE:
262343181Sdim    return ::GetSegmentAndOffset<TrampolineSym>(sym);
263343181Sdim    break;
264343181Sdim  case S_COFFGROUP:
265343181Sdim    return ::GetSegmentAndOffset<CoffGroupSym>(sym);
266343181Sdim    break;
267343181Sdim  case S_BLOCK32:
268343181Sdim    return ::GetSegmentAndOffset<BlockSym>(sym);
269343181Sdim    break;
270343181Sdim  case S_LABEL32:
271343181Sdim    return ::GetSegmentAndOffset<LabelSym>(sym);
272343181Sdim    break;
273343181Sdim  case S_CALLSITEINFO:
274343181Sdim    return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
275343181Sdim    break;
276343181Sdim  case S_HEAPALLOCSITE:
277343181Sdim    return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
278343181Sdim    break;
279343181Sdim  case S_LDATA32:
280343181Sdim  case S_GDATA32:
281343181Sdim  case S_LMANDATA:
282343181Sdim  case S_GMANDATA:
283343181Sdim    return ::GetSegmentAndOffset<DataSym>(sym);
284343181Sdim    break;
285343181Sdim  case S_LTHREAD32:
286343181Sdim  case S_GTHREAD32:
287343181Sdim    return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
288343181Sdim    break;
289343181Sdim  default:
290343181Sdim    lldbassert(false && "Record does not have a segment/offset!");
291343181Sdim  }
292343181Sdim  return {0, 0};
293343181Sdim}
294343181Sdim
295343181Sdimtemplate <typename RecordT>
296343181SdimSegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
297343181Sdim  RecordT record = createRecord<RecordT>(sym);
298343181Sdim  return {record.Segment, record.CodeOffset, record.CodeSize};
299343181Sdim}
300343181Sdim
301343181Sdimtemplate <>
302343181SdimSegmentOffsetLength
303343181SdimGetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
304343181Sdim  TrampolineSym record = createRecord<TrampolineSym>(sym);
305343181Sdim  return {record.ThunkSection, record.ThunkOffset, record.Size};
306343181Sdim}
307343181Sdim
308343181Sdimtemplate <>
309343181SdimSegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
310343181Sdim  Thunk32Sym record = createRecord<Thunk32Sym>(sym);
311343181Sdim  return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
312343181Sdim}
313343181Sdim
314343181Sdimtemplate <>
315343181SdimSegmentOffsetLength
316343181SdimGetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
317343181Sdim  CoffGroupSym record = createRecord<CoffGroupSym>(sym);
318343181Sdim  return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
319343181Sdim}
320343181Sdim
321343181SdimSegmentOffsetLength
322343181Sdimlldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
323343181Sdim  switch (sym.kind()) {
324343181Sdim  case S_GPROC32:
325343181Sdim  case S_LPROC32:
326343181Sdim  case S_GPROC32_ID:
327343181Sdim  case S_LPROC32_ID:
328343181Sdim  case S_LPROC32_DPC:
329343181Sdim  case S_LPROC32_DPC_ID:
330343181Sdim    return ::GetSegmentOffsetAndLength<ProcSym>(sym);
331343181Sdim  case S_THUNK32:
332343181Sdim    return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
333343181Sdim    break;
334343181Sdim  case S_TRAMPOLINE:
335343181Sdim    return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
336343181Sdim    break;
337343181Sdim  case S_COFFGROUP:
338343181Sdim    return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
339343181Sdim    break;
340343181Sdim  case S_BLOCK32:
341343181Sdim    return ::GetSegmentOffsetAndLength<BlockSym>(sym);
342343181Sdim    break;
343343181Sdim  default:
344343181Sdim    lldbassert(false && "Record does not have a segment/offset/length triple!");
345343181Sdim  }
346343181Sdim  return {0, 0, 0};
347343181Sdim}
348343181Sdim
349343181Sdimbool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
350343181Sdim  ClassRecord cr;
351343181Sdim  UnionRecord ur;
352343181Sdim  EnumRecord er;
353343181Sdim  switch (cvt.kind()) {
354343181Sdim  case LF_CLASS:
355343181Sdim  case LF_STRUCTURE:
356343181Sdim  case LF_INTERFACE:
357343181Sdim    llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
358343181Sdim    return cr.isForwardRef();
359343181Sdim  case LF_UNION:
360343181Sdim    llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
361343181Sdim    return ur.isForwardRef();
362343181Sdim  case LF_ENUM:
363343181Sdim    llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
364343181Sdim    return er.isForwardRef();
365343181Sdim  default:
366343181Sdim    return false;
367343181Sdim  }
368343181Sdim}
369343181Sdim
370343181Sdimbool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {
371343181Sdim  switch (cvt.kind()) {
372343181Sdim  case LF_CLASS:
373343181Sdim  case LF_STRUCTURE:
374343181Sdim  case LF_UNION:
375343181Sdim  case LF_ENUM:
376343181Sdim    return true;
377343181Sdim  default:
378343181Sdim    return false;
379343181Sdim  }
380343181Sdim}
381343181Sdim
382343181Sdimbool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {
383343181Sdim  switch (cvt.kind()) {
384343181Sdim  case LF_CLASS:
385343181Sdim  case LF_STRUCTURE:
386343181Sdim  case LF_UNION:
387343181Sdim    return true;
388343181Sdim  default:
389343181Sdim    return false;
390343181Sdim  }
391343181Sdim}
392343181Sdim
393343181Sdimbool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
394343181Sdim                                         TpiStream &tpi) {
395343181Sdim  if (id.is_ipi || id.index.isSimple())
396343181Sdim    return false;
397343181Sdim  return IsForwardRefUdt(tpi.getType(id.index));
398343181Sdim}
399343181Sdim
400343181Sdimbool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {
401343181Sdim  if (id.is_ipi || id.index.isSimple())
402343181Sdim    return false;
403343181Sdim  return IsTagRecord(tpi.getType(id.index));
404343181Sdim}
405343181Sdim
406343181Sdimlldb::AccessType
407343181Sdimlldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
408343181Sdim  switch (access) {
409343181Sdim  case MemberAccess::Private:
410343181Sdim    return lldb::eAccessPrivate;
411343181Sdim  case MemberAccess::Protected:
412343181Sdim    return lldb::eAccessProtected;
413343181Sdim  case MemberAccess::Public:
414343181Sdim    return lldb::eAccessPublic;
415343181Sdim  case MemberAccess::None:
416343181Sdim    return lldb::eAccessNone;
417343181Sdim  }
418343181Sdim  llvm_unreachable("unreachable");
419343181Sdim}
420343181Sdim
421343181SdimTypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
422343181Sdim  switch (cvt.kind()) {
423343181Sdim  case LF_CLASS:
424343181Sdim  case LF_STRUCTURE:
425343181Sdim  case LF_INTERFACE: {
426343181Sdim    ClassRecord cr;
427343181Sdim    cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
428343181Sdim    return cr.FieldList;
429343181Sdim  }
430343181Sdim  case LF_UNION: {
431343181Sdim    UnionRecord ur;
432343181Sdim    cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
433343181Sdim    return ur.FieldList;
434343181Sdim  }
435343181Sdim  case LF_ENUM: {
436343181Sdim    EnumRecord er;
437343181Sdim    cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
438343181Sdim    return er.FieldList;
439343181Sdim  }
440343181Sdim  default:
441343181Sdim    llvm_unreachable("Unreachable!");
442343181Sdim  }
443343181Sdim}
444343181Sdim
445343181SdimTypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
446343181Sdim  lldbassert(modifier.kind() == LF_MODIFIER);
447343181Sdim  ModifierRecord mr;
448343181Sdim  llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
449343181Sdim  return mr.ModifiedType;
450343181Sdim}
451343181Sdim
452343181Sdimllvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
453343181Sdim  return MSVCUndecoratedNameParser::DropScope(name);
454343181Sdim}
455343181Sdim
456343181SdimVariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
457343181Sdim  VariableInfo result;
458343181Sdim
459343181Sdim  if (sym.kind() == S_REGREL32) {
460343181Sdim    RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
461343181Sdim    cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
462343181Sdim    result.type = reg.Type;
463343181Sdim    result.name = reg.Name;
464343181Sdim    return result;
465343181Sdim  }
466343181Sdim
467343181Sdim  if (sym.kind() == S_REGISTER) {
468343181Sdim    RegisterSym reg(SymbolRecordKind::RegisterSym);
469343181Sdim    cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
470343181Sdim    result.type = reg.Index;
471343181Sdim    result.name = reg.Name;
472343181Sdim    return result;
473343181Sdim  }
474343181Sdim
475343181Sdim  if (sym.kind() == S_LOCAL) {
476343181Sdim    LocalSym local(SymbolRecordKind::LocalSym);
477343181Sdim    cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
478343181Sdim    result.type = local.Type;
479343181Sdim    result.name = local.Name;
480343181Sdim    return result;
481343181Sdim  }
482343181Sdim
483343181Sdim  if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {
484343181Sdim    DataSym data(SymbolRecordKind::DataSym);
485343181Sdim    cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data));
486343181Sdim    result.type = data.Type;
487343181Sdim    result.name = data.Name;
488343181Sdim    return result;
489343181Sdim  }
490343181Sdim
491343181Sdim  if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {
492343181Sdim    ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);
493343181Sdim    cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data));
494343181Sdim    result.type = data.Type;
495343181Sdim    result.name = data.Name;
496343181Sdim    return result;
497343181Sdim  }
498343181Sdim
499343181Sdim  if (sym.kind() == S_CONSTANT) {
500343181Sdim    ConstantSym constant(SymbolRecordKind::ConstantSym);
501343181Sdim    cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));
502343181Sdim    result.type = constant.Type;
503343181Sdim    result.name = constant.Name;
504343181Sdim    return result;
505343181Sdim  }
506343181Sdim
507343181Sdim  lldbassert(false && "Invalid variable record kind!");
508343181Sdim  return {};
509343181Sdim}
510343181Sdim
511353358Sdimstatic llvm::FixedStreamArray<FrameData>::Iterator
512353358SdimGetCorrespondingFrameData(lldb::addr_t load_addr,
513353358Sdim                          const DebugFrameDataSubsectionRef &fpo_data,
514353358Sdim                          const Variable::RangeList &ranges) {
515353358Sdim  lldbassert(!ranges.IsEmpty());
516353358Sdim
517353358Sdim  // assume that all variable ranges correspond to one frame data
518353358Sdim  using RangeListEntry = Variable::RangeList::Entry;
519353358Sdim  const RangeListEntry &range = ranges.GetEntryRef(0);
520353358Sdim
521353358Sdim  auto it = fpo_data.begin();
522353358Sdim
523353358Sdim  // start by searching first frame data range containing variable range
524353358Sdim  for (; it != fpo_data.end(); ++it) {
525353358Sdim    RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
526353358Sdim
527353358Sdim    if (fd_range.Contains(range)) {
528353358Sdim      break;
529353358Sdim    }
530353358Sdim  }
531353358Sdim
532353358Sdim  // then first most nested entry that still contains variable range
533353358Sdim  auto found = it;
534353358Sdim  for (; it != fpo_data.end(); ++it) {
535353358Sdim    RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
536353358Sdim
537353358Sdim    if (!fd_range.Contains(range)) {
538353358Sdim      break;
539353358Sdim    }
540353358Sdim    found = it;
541353358Sdim  }
542353358Sdim
543353358Sdim  return found;
544353358Sdim}
545353358Sdim
546353358Sdimstatic bool GetFrameDataProgram(PdbIndex &index,
547353358Sdim                                const Variable::RangeList &ranges,
548353358Sdim                                llvm::StringRef &out_program) {
549353358Sdim  const DebugFrameDataSubsectionRef &new_fpo_data =
550353358Sdim      index.dbi().getNewFpoRecords();
551353358Sdim
552353358Sdim  auto frame_data_it =
553353358Sdim      GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges);
554353358Sdim  if (frame_data_it == new_fpo_data.end())
555353358Sdim    return false;
556353358Sdim
557353358Sdim  PDBStringTable &strings = cantFail(index.pdb().getStringTable());
558353358Sdim  out_program = cantFail(strings.getStringForID(frame_data_it->FrameFunc));
559353358Sdim  return true;
560353358Sdim}
561353358Sdim
562353358Sdimstatic RegisterId GetBaseFrameRegister(PdbIndex &index,
563353358Sdim                                       PdbCompilandSymId frame_proc_id,
564353358Sdim                                       bool is_parameter) {
565353358Sdim  CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);
566353358Sdim  lldbassert(frame_proc_cvs.kind() == S_FRAMEPROC);
567353358Sdim
568353358Sdim  FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);
569353358Sdim  cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,
570353358Sdim                                                           frame_proc));
571353358Sdim
572353358Sdim  CPUType cpu_type = index.compilands()
573353358Sdim                         .GetCompiland(frame_proc_id.modi)
574353358Sdim                         ->m_compile_opts->Machine;
575353358Sdim
576353358Sdim  return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type)
577353358Sdim                      : frame_proc.getLocalFramePtrReg(cpu_type);
578353358Sdim}
579353358Sdim
580343181SdimVariableInfo lldb_private::npdb::GetVariableLocationInfo(
581353358Sdim    PdbIndex &index, PdbCompilandSymId var_id, Block &block,
582353358Sdim    lldb::ModuleSP module) {
583343181Sdim
584343181Sdim  CVSymbol sym = index.ReadSymbolRecord(var_id);
585343181Sdim
586343181Sdim  VariableInfo result = GetVariableNameInfo(sym);
587343181Sdim
588343181Sdim  if (sym.kind() == S_REGREL32) {
589343181Sdim    RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
590343181Sdim    cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
591343181Sdim    result.location =
592343181Sdim        MakeRegRelLocationExpression(reg.Register, reg.Offset, module);
593343181Sdim    result.ranges.emplace();
594343181Sdim    return result;
595343181Sdim  }
596343181Sdim
597343181Sdim  if (sym.kind() == S_REGISTER) {
598343181Sdim    RegisterSym reg(SymbolRecordKind::RegisterSym);
599343181Sdim    cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
600343181Sdim    result.location = MakeEnregisteredLocationExpression(reg.Register, module);
601343181Sdim    result.ranges.emplace();
602343181Sdim    return result;
603343181Sdim  }
604343181Sdim
605343181Sdim  if (sym.kind() == S_LOCAL) {
606343181Sdim    LocalSym local(SymbolRecordKind::LocalSym);
607343181Sdim    cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
608343181Sdim
609343181Sdim    PdbCompilandSymId loc_specifier_id(var_id.modi,
610343181Sdim                                       var_id.offset + sym.RecordData.size());
611343181Sdim    CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
612343181Sdim    if (loc_specifier_cvs.kind() == S_DEFRANGE_FRAMEPOINTER_REL) {
613343181Sdim      DefRangeFramePointerRelSym loc(
614343181Sdim          SymbolRecordKind::DefRangeFramePointerRelSym);
615343181Sdim      cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
616343181Sdim          loc_specifier_cvs, loc));
617353358Sdim
618353358Sdim      Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
619353358Sdim
620353358Sdim      // TODO: may be better to pass function scope and not lookup it every
621353358Sdim      // time? find nearest parent function block
622353358Sdim      Block *cur = &block;
623353358Sdim      while (cur->GetParent()) {
624353358Sdim        cur = cur->GetParent();
625353358Sdim      }
626353358Sdim      PdbCompilandSymId func_scope_id =
627353358Sdim          PdbSymUid(cur->GetID()).asCompilandSym();
628353358Sdim      CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
629353358Sdim      lldbassert(func_block_cvs.kind() == S_GPROC32 ||
630353358Sdim                 func_block_cvs.kind() == S_LPROC32);
631353358Sdim
632353358Sdim      PdbCompilandSymId frame_proc_id(
633353358Sdim          func_scope_id.modi, func_scope_id.offset + func_block_cvs.length());
634353358Sdim
635353358Sdim      bool is_parameter =
636353358Sdim          ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);
637353358Sdim      RegisterId base_reg =
638353358Sdim          GetBaseFrameRegister(index, frame_proc_id, is_parameter);
639353358Sdim
640353358Sdim      if (base_reg == RegisterId::VFRAME) {
641353358Sdim        llvm::StringRef program;
642353358Sdim        if (GetFrameDataProgram(index, ranges, program)) {
643353358Sdim          result.location =
644360784Sdim              MakeVFrameRelLocationExpression(program, loc.Hdr.Offset, module);
645353358Sdim          result.ranges = std::move(ranges);
646353358Sdim        } else {
647353358Sdim          // invalid variable
648353358Sdim        }
649353358Sdim      } else {
650353358Sdim        result.location =
651360784Sdim            MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
652353358Sdim        result.ranges = std::move(ranges);
653353358Sdim      }
654353358Sdim    } else if (loc_specifier_cvs.kind() == S_DEFRANGE_REGISTER_REL) {
655353358Sdim      DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
656353358Sdim      cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
657353358Sdim          loc_specifier_cvs, loc));
658353358Sdim
659353358Sdim      Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
660353358Sdim
661353358Sdim      RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register;
662353358Sdim
663353358Sdim      if (base_reg == RegisterId::VFRAME) {
664353358Sdim        llvm::StringRef program;
665353358Sdim        if (GetFrameDataProgram(index, ranges, program)) {
666353358Sdim          result.location = MakeVFrameRelLocationExpression(
667353358Sdim              program, loc.Hdr.BasePointerOffset, module);
668353358Sdim          result.ranges = std::move(ranges);
669353358Sdim        } else {
670353358Sdim          // invalid variable
671353358Sdim        }
672353358Sdim      } else {
673353358Sdim        result.location = MakeRegRelLocationExpression(
674353358Sdim            base_reg, loc.Hdr.BasePointerOffset, module);
675353358Sdim        result.ranges = std::move(ranges);
676353358Sdim      }
677343181Sdim    }
678353358Sdim
679353358Sdim    // FIXME: Handle other kinds
680343181Sdim    return result;
681343181Sdim  }
682343181Sdim  llvm_unreachable("Symbol is not a local variable!");
683343181Sdim  return result;
684343181Sdim}
685343181Sdim
686343181Sdimlldb::BasicType
687343181Sdimlldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {
688343181Sdim  switch (kind) {
689343181Sdim  case SimpleTypeKind::Boolean128:
690343181Sdim  case SimpleTypeKind::Boolean16:
691343181Sdim  case SimpleTypeKind::Boolean32:
692343181Sdim  case SimpleTypeKind::Boolean64:
693343181Sdim  case SimpleTypeKind::Boolean8:
694343181Sdim    return lldb::eBasicTypeBool;
695343181Sdim  case SimpleTypeKind::Byte:
696343181Sdim  case SimpleTypeKind::UnsignedCharacter:
697343181Sdim    return lldb::eBasicTypeUnsignedChar;
698343181Sdim  case SimpleTypeKind::NarrowCharacter:
699343181Sdim    return lldb::eBasicTypeChar;
700343181Sdim  case SimpleTypeKind::SignedCharacter:
701343181Sdim  case SimpleTypeKind::SByte:
702343181Sdim    return lldb::eBasicTypeSignedChar;
703343181Sdim  case SimpleTypeKind::Character16:
704343181Sdim    return lldb::eBasicTypeChar16;
705343181Sdim  case SimpleTypeKind::Character32:
706343181Sdim    return lldb::eBasicTypeChar32;
707343181Sdim  case SimpleTypeKind::Complex80:
708343181Sdim    return lldb::eBasicTypeLongDoubleComplex;
709343181Sdim  case SimpleTypeKind::Complex64:
710343181Sdim    return lldb::eBasicTypeDoubleComplex;
711343181Sdim  case SimpleTypeKind::Complex32:
712343181Sdim    return lldb::eBasicTypeFloatComplex;
713343181Sdim  case SimpleTypeKind::Float128:
714343181Sdim  case SimpleTypeKind::Float80:
715343181Sdim    return lldb::eBasicTypeLongDouble;
716343181Sdim  case SimpleTypeKind::Float64:
717343181Sdim    return lldb::eBasicTypeDouble;
718343181Sdim  case SimpleTypeKind::Float32:
719343181Sdim    return lldb::eBasicTypeFloat;
720343181Sdim  case SimpleTypeKind::Float16:
721343181Sdim    return lldb::eBasicTypeHalf;
722343181Sdim  case SimpleTypeKind::Int128:
723343181Sdim    return lldb::eBasicTypeInt128;
724343181Sdim  case SimpleTypeKind::Int64:
725343181Sdim  case SimpleTypeKind::Int64Quad:
726343181Sdim    return lldb::eBasicTypeLongLong;
727343181Sdim  case SimpleTypeKind::Int32:
728343181Sdim    return lldb::eBasicTypeInt;
729343181Sdim  case SimpleTypeKind::Int16:
730343181Sdim  case SimpleTypeKind::Int16Short:
731343181Sdim    return lldb::eBasicTypeShort;
732343181Sdim  case SimpleTypeKind::UInt128:
733343181Sdim    return lldb::eBasicTypeUnsignedInt128;
734343181Sdim  case SimpleTypeKind::UInt64:
735343181Sdim  case SimpleTypeKind::UInt64Quad:
736343181Sdim    return lldb::eBasicTypeUnsignedLongLong;
737343181Sdim  case SimpleTypeKind::HResult:
738343181Sdim  case SimpleTypeKind::UInt32:
739343181Sdim    return lldb::eBasicTypeUnsignedInt;
740343181Sdim  case SimpleTypeKind::UInt16:
741343181Sdim  case SimpleTypeKind::UInt16Short:
742343181Sdim    return lldb::eBasicTypeUnsignedShort;
743343181Sdim  case SimpleTypeKind::Int32Long:
744343181Sdim    return lldb::eBasicTypeLong;
745343181Sdim  case SimpleTypeKind::UInt32Long:
746343181Sdim    return lldb::eBasicTypeUnsignedLong;
747343181Sdim  case SimpleTypeKind::Void:
748343181Sdim    return lldb::eBasicTypeVoid;
749343181Sdim  case SimpleTypeKind::WideCharacter:
750343181Sdim    return lldb::eBasicTypeWChar;
751343181Sdim  default:
752343181Sdim    return lldb::eBasicTypeInvalid;
753343181Sdim  }
754343181Sdim}
755343181Sdim
756343181Sdimsize_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {
757343181Sdim  switch (kind) {
758343181Sdim  case SimpleTypeKind::Boolean128:
759343181Sdim  case SimpleTypeKind::Int128:
760343181Sdim  case SimpleTypeKind::UInt128:
761343181Sdim  case SimpleTypeKind::Float128:
762343181Sdim    return 16;
763343181Sdim  case SimpleTypeKind::Complex80:
764343181Sdim  case SimpleTypeKind::Float80:
765343181Sdim    return 10;
766343181Sdim  case SimpleTypeKind::Boolean64:
767343181Sdim  case SimpleTypeKind::Complex64:
768343181Sdim  case SimpleTypeKind::UInt64:
769343181Sdim  case SimpleTypeKind::UInt64Quad:
770343181Sdim  case SimpleTypeKind::Float64:
771343181Sdim  case SimpleTypeKind::Int64:
772343181Sdim  case SimpleTypeKind::Int64Quad:
773343181Sdim    return 8;
774343181Sdim  case SimpleTypeKind::Boolean32:
775343181Sdim  case SimpleTypeKind::Character32:
776343181Sdim  case SimpleTypeKind::Complex32:
777343181Sdim  case SimpleTypeKind::Float32:
778343181Sdim  case SimpleTypeKind::Int32:
779343181Sdim  case SimpleTypeKind::Int32Long:
780343181Sdim  case SimpleTypeKind::UInt32Long:
781343181Sdim  case SimpleTypeKind::HResult:
782343181Sdim  case SimpleTypeKind::UInt32:
783343181Sdim    return 4;
784343181Sdim  case SimpleTypeKind::Boolean16:
785343181Sdim  case SimpleTypeKind::Character16:
786343181Sdim  case SimpleTypeKind::Float16:
787343181Sdim  case SimpleTypeKind::Int16:
788343181Sdim  case SimpleTypeKind::Int16Short:
789343181Sdim  case SimpleTypeKind::UInt16:
790343181Sdim  case SimpleTypeKind::UInt16Short:
791343181Sdim  case SimpleTypeKind::WideCharacter:
792343181Sdim    return 2;
793343181Sdim  case SimpleTypeKind::Boolean8:
794343181Sdim  case SimpleTypeKind::Byte:
795343181Sdim  case SimpleTypeKind::UnsignedCharacter:
796343181Sdim  case SimpleTypeKind::NarrowCharacter:
797343181Sdim  case SimpleTypeKind::SignedCharacter:
798343181Sdim  case SimpleTypeKind::SByte:
799343181Sdim    return 1;
800343181Sdim  case SimpleTypeKind::Void:
801343181Sdim  default:
802343181Sdim    return 0;
803343181Sdim  }
804343181Sdim}
805343181Sdim
806343181SdimPdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,
807343181Sdim                                                     TpiStream &tpi) {
808343181Sdim  if (id.index.isSimple())
809343181Sdim    return id;
810343181Sdim
811343181Sdim  CVType cvt = tpi.getType(id.index);
812343181Sdim
813343181Sdim  // Only tag records have a best and a worst record.
814343181Sdim  if (!IsTagRecord(cvt))
815343181Sdim    return id;
816343181Sdim
817343181Sdim  // Tag records that are not forward decls are full decls, hence they are the
818343181Sdim  // best.
819343181Sdim  if (!IsForwardRefUdt(cvt))
820343181Sdim    return id;
821343181Sdim
822343181Sdim  return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));
823343181Sdim}
824343181Sdim
825343181Sdimtemplate <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {
826343181Sdim  RecordType record;
827343181Sdim  llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));
828343181Sdim  return record.getSize();
829343181Sdim}
830343181Sdim
831343181Sdimsize_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,
832343181Sdim                                         llvm::pdb::TpiStream &tpi) {
833343181Sdim  if (id.index.isSimple()) {
834343181Sdim    switch (id.index.getSimpleMode()) {
835343181Sdim    case SimpleTypeMode::Direct:
836343181Sdim      return GetTypeSizeForSimpleKind(id.index.getSimpleKind());
837343181Sdim    case SimpleTypeMode::NearPointer32:
838343181Sdim    case SimpleTypeMode::FarPointer32:
839343181Sdim      return 4;
840343181Sdim    case SimpleTypeMode::NearPointer64:
841343181Sdim      return 8;
842343181Sdim    case SimpleTypeMode::NearPointer128:
843343181Sdim      return 16;
844343181Sdim    default:
845343181Sdim      break;
846343181Sdim    }
847343181Sdim    return 0;
848343181Sdim  }
849343181Sdim
850343181Sdim  TypeIndex index = id.index;
851343181Sdim  if (IsForwardRefUdt(index, tpi))
852343181Sdim    index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));
853343181Sdim
854343181Sdim  CVType cvt = tpi.getType(index);
855343181Sdim  switch (cvt.kind()) {
856343181Sdim  case LF_MODIFIER:
857343181Sdim    return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);
858343181Sdim  case LF_ENUM: {
859343181Sdim    EnumRecord record;
860343181Sdim    llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));
861343181Sdim    return GetSizeOfType({record.UnderlyingType}, tpi);
862343181Sdim  }
863343181Sdim  case LF_POINTER:
864343181Sdim    return GetSizeOfTypeInternal<PointerRecord>(cvt);
865343181Sdim  case LF_ARRAY:
866343181Sdim    return GetSizeOfTypeInternal<ArrayRecord>(cvt);
867343181Sdim  case LF_CLASS:
868343181Sdim  case LF_STRUCTURE:
869343181Sdim  case LF_INTERFACE:
870343181Sdim    return GetSizeOfTypeInternal<ClassRecord>(cvt);
871343181Sdim  case LF_UNION:
872343181Sdim    return GetSizeOfTypeInternal<UnionRecord>(cvt);
873343181Sdim  default:
874343181Sdim    break;
875343181Sdim  }
876343181Sdim  return 0;
877343181Sdim}
878