1 //===-- PdbUtil.cpp -------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "PdbUtil.h"
10 
11 #include "DWARFLocationExpression.h"
12 #include "PdbIndex.h"
13 #include "PdbSymUid.h"
14 
15 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
16 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
17 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
18 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
19 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
20 
21 #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
22 #include "lldb/Symbol/Block.h"
23 #include "lldb/Utility/LLDBAssert.h"
24 #include "lldb/Utility/LLDBLog.h"
25 #include "lldb/lldb-enumerations.h"
26 
27 using namespace lldb_private;
28 using namespace lldb_private::npdb;
29 using namespace llvm::codeview;
30 using namespace llvm::pdb;
31 
32 static Variable::RangeList
33 MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
34               llvm::ArrayRef<LocalVariableAddrGap> gaps) {
35   lldb::addr_t start =
36       index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
37   lldb::addr_t end = start + range.Range;
38 
39   Variable::RangeList result;
40   while (!gaps.empty()) {
41     const LocalVariableAddrGap &gap = gaps.front();
42     lldb::addr_t gap_start = start + gap.GapStartOffset;
43     result.Append(start, gap_start - start);
44     start = gap_start + gap.Range;
45     gaps = gaps.drop_front();
46   }
47 
48   result.Append(start, end - start);
49   return result;
50 }
51 
52 namespace {
53 struct FindMembersSize : public TypeVisitorCallbacks {
54   FindMembersSize(
55       llvm::SmallVectorImpl<std::pair<RegisterId, uint32_t>> &members_info,
56       TpiStream &tpi)
57       : members_info(members_info), tpi(tpi) {}
58   llvm::SmallVectorImpl<std::pair<RegisterId, uint32_t>> &members_info;
59   TpiStream &tpi;
60   llvm::Error visitKnownMember(CVMemberRecord &cvr,
61                                DataMemberRecord &member) override {
62     members_info.emplace_back(llvm::codeview::RegisterId::NONE,
63                               GetSizeOfType(member.Type, tpi));
64     return llvm::Error::success();
65   }
66 };
67 } // namespace
68 
69 CVTagRecord CVTagRecord::create(CVType type) {
70   assert(IsTagRecord(type) && "type is not a tag record!");
71   switch (type.kind()) {
72   case LF_CLASS:
73   case LF_STRUCTURE:
74   case LF_INTERFACE: {
75     ClassRecord cr;
76     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));
77     return CVTagRecord(std::move(cr));
78   }
79   case LF_UNION: {
80     UnionRecord ur;
81     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));
82     return CVTagRecord(std::move(ur));
83   }
84   case LF_ENUM: {
85     EnumRecord er;
86     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));
87     return CVTagRecord(std::move(er));
88   }
89   default:
90     llvm_unreachable("Unreachable!");
91   }
92 }
93 
94 CVTagRecord::CVTagRecord(ClassRecord &&c)
95     : cvclass(std::move(c)),
96       m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
97 CVTagRecord::CVTagRecord(UnionRecord &&u)
98     : cvunion(std::move(u)), m_kind(Union) {}
99 CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
100 
101 PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
102   switch (kind) {
103   case S_COMPILE3:
104   case S_OBJNAME:
105     return PDB_SymType::CompilandDetails;
106   case S_ENVBLOCK:
107     return PDB_SymType::CompilandEnv;
108   case S_THUNK32:
109   case S_TRAMPOLINE:
110     return PDB_SymType::Thunk;
111   case S_COFFGROUP:
112     return PDB_SymType::CoffGroup;
113   case S_EXPORT:
114     return PDB_SymType::Export;
115   case S_LPROC32:
116   case S_GPROC32:
117   case S_LPROC32_DPC:
118     return PDB_SymType::Function;
119   case S_PUB32:
120     return PDB_SymType::PublicSymbol;
121   case S_INLINESITE:
122     return PDB_SymType::InlineSite;
123   case S_LOCAL:
124   case S_BPREL32:
125   case S_REGREL32:
126   case S_MANCONSTANT:
127   case S_CONSTANT:
128   case S_LDATA32:
129   case S_GDATA32:
130   case S_LMANDATA:
131   case S_GMANDATA:
132   case S_LTHREAD32:
133   case S_GTHREAD32:
134     return PDB_SymType::Data;
135   case S_BLOCK32:
136     return PDB_SymType::Block;
137   case S_LABEL32:
138     return PDB_SymType::Label;
139   case S_CALLSITEINFO:
140     return PDB_SymType::CallSite;
141   case S_HEAPALLOCSITE:
142     return PDB_SymType::HeapAllocationSite;
143   case S_CALLEES:
144     return PDB_SymType::Callee;
145   case S_CALLERS:
146     return PDB_SymType::Caller;
147   default:
148     lldbassert(false && "Invalid symbol record kind!");
149   }
150   return PDB_SymType::None;
151 }
152 
153 PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
154   switch (kind) {
155   case LF_ARRAY:
156     return PDB_SymType::ArrayType;
157   case LF_ARGLIST:
158     return PDB_SymType::FunctionSig;
159   case LF_BCLASS:
160     return PDB_SymType::BaseClass;
161   case LF_BINTERFACE:
162     return PDB_SymType::BaseInterface;
163   case LF_CLASS:
164   case LF_STRUCTURE:
165   case LF_INTERFACE:
166   case LF_UNION:
167     return PDB_SymType::UDT;
168   case LF_POINTER:
169     return PDB_SymType::PointerType;
170   case LF_ENUM:
171     return PDB_SymType::Enum;
172   case LF_PROCEDURE:
173     return PDB_SymType::FunctionSig;
174   case LF_BITFIELD:
175     return PDB_SymType::BuiltinType;
176   default:
177     lldbassert(false && "Invalid type record kind!");
178   }
179   return PDB_SymType::None;
180 }
181 
182 bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
183   switch (sym.kind()) {
184   case S_GPROC32:
185   case S_LPROC32:
186   case S_GPROC32_ID:
187   case S_LPROC32_ID:
188   case S_LPROC32_DPC:
189   case S_LPROC32_DPC_ID:
190   case S_THUNK32:
191   case S_TRAMPOLINE:
192   case S_COFFGROUP:
193   case S_BLOCK32:
194   case S_LABEL32:
195   case S_CALLSITEINFO:
196   case S_HEAPALLOCSITE:
197   case S_LDATA32:
198   case S_GDATA32:
199   case S_LMANDATA:
200   case S_GMANDATA:
201   case S_LTHREAD32:
202   case S_GTHREAD32:
203     return true;
204   default:
205     return false;
206   }
207 }
208 
209 bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
210   switch (sym.kind()) {
211   case S_GPROC32:
212   case S_LPROC32:
213   case S_GPROC32_ID:
214   case S_LPROC32_ID:
215   case S_LPROC32_DPC:
216   case S_LPROC32_DPC_ID:
217   case S_THUNK32:
218   case S_TRAMPOLINE:
219   case S_COFFGROUP:
220   case S_BLOCK32:
221     return true;
222   default:
223     return false;
224   }
225 }
226 
227 template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
228   RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
229   cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
230   return record;
231 }
232 
233 template <typename RecordT>
234 static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
235   RecordT record = createRecord<RecordT>(sym);
236   return {record.Segment, record.CodeOffset};
237 }
238 
239 template <>
240 SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
241   TrampolineSym record = createRecord<TrampolineSym>(sym);
242   return {record.ThunkSection, record.ThunkOffset};
243 }
244 
245 template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
246   Thunk32Sym record = createRecord<Thunk32Sym>(sym);
247   return {record.Segment, record.Offset};
248 }
249 
250 template <>
251 SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
252   CoffGroupSym record = createRecord<CoffGroupSym>(sym);
253   return {record.Segment, record.Offset};
254 }
255 
256 template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
257   DataSym record = createRecord<DataSym>(sym);
258   return {record.Segment, record.DataOffset};
259 }
260 
261 template <>
262 SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
263   ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
264   return {record.Segment, record.DataOffset};
265 }
266 
267 SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
268   switch (sym.kind()) {
269   case S_GPROC32:
270   case S_LPROC32:
271   case S_GPROC32_ID:
272   case S_LPROC32_ID:
273   case S_LPROC32_DPC:
274   case S_LPROC32_DPC_ID:
275     return ::GetSegmentAndOffset<ProcSym>(sym);
276   case S_THUNK32:
277     return ::GetSegmentAndOffset<Thunk32Sym>(sym);
278     break;
279   case S_TRAMPOLINE:
280     return ::GetSegmentAndOffset<TrampolineSym>(sym);
281     break;
282   case S_COFFGROUP:
283     return ::GetSegmentAndOffset<CoffGroupSym>(sym);
284     break;
285   case S_BLOCK32:
286     return ::GetSegmentAndOffset<BlockSym>(sym);
287     break;
288   case S_LABEL32:
289     return ::GetSegmentAndOffset<LabelSym>(sym);
290     break;
291   case S_CALLSITEINFO:
292     return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
293     break;
294   case S_HEAPALLOCSITE:
295     return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
296     break;
297   case S_LDATA32:
298   case S_GDATA32:
299   case S_LMANDATA:
300   case S_GMANDATA:
301     return ::GetSegmentAndOffset<DataSym>(sym);
302     break;
303   case S_LTHREAD32:
304   case S_GTHREAD32:
305     return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
306     break;
307   default:
308     lldbassert(false && "Record does not have a segment/offset!");
309   }
310   return {0, 0};
311 }
312 
313 template <typename RecordT>
314 SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
315   RecordT record = createRecord<RecordT>(sym);
316   return {record.Segment, record.CodeOffset, record.CodeSize};
317 }
318 
319 template <>
320 SegmentOffsetLength
321 GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
322   TrampolineSym record = createRecord<TrampolineSym>(sym);
323   return {record.ThunkSection, record.ThunkOffset, record.Size};
324 }
325 
326 template <>
327 SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
328   Thunk32Sym record = createRecord<Thunk32Sym>(sym);
329   return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
330 }
331 
332 template <>
333 SegmentOffsetLength
334 GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
335   CoffGroupSym record = createRecord<CoffGroupSym>(sym);
336   return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
337 }
338 
339 SegmentOffsetLength
340 lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
341   switch (sym.kind()) {
342   case S_GPROC32:
343   case S_LPROC32:
344   case S_GPROC32_ID:
345   case S_LPROC32_ID:
346   case S_LPROC32_DPC:
347   case S_LPROC32_DPC_ID:
348     return ::GetSegmentOffsetAndLength<ProcSym>(sym);
349   case S_THUNK32:
350     return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
351     break;
352   case S_TRAMPOLINE:
353     return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
354     break;
355   case S_COFFGROUP:
356     return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
357     break;
358   case S_BLOCK32:
359     return ::GetSegmentOffsetAndLength<BlockSym>(sym);
360     break;
361   default:
362     lldbassert(false && "Record does not have a segment/offset/length triple!");
363   }
364   return {0, 0, 0};
365 }
366 
367 bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
368   ClassRecord cr;
369   UnionRecord ur;
370   EnumRecord er;
371   switch (cvt.kind()) {
372   case LF_CLASS:
373   case LF_STRUCTURE:
374   case LF_INTERFACE:
375     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
376     return cr.isForwardRef();
377   case LF_UNION:
378     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
379     return ur.isForwardRef();
380   case LF_ENUM:
381     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
382     return er.isForwardRef();
383   default:
384     return false;
385   }
386 }
387 
388 bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {
389   switch (cvt.kind()) {
390   case LF_CLASS:
391   case LF_STRUCTURE:
392   case LF_UNION:
393   case LF_ENUM:
394     return true;
395   default:
396     return false;
397   }
398 }
399 
400 bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {
401   switch (cvt.kind()) {
402   case LF_CLASS:
403   case LF_STRUCTURE:
404   case LF_UNION:
405     return true;
406   default:
407     return false;
408   }
409 }
410 
411 bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
412                                          TpiStream &tpi) {
413   if (id.is_ipi || id.index.isSimple())
414     return false;
415   return IsForwardRefUdt(tpi.getType(id.index));
416 }
417 
418 bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {
419   if (id.is_ipi || id.index.isSimple())
420     return false;
421   return IsTagRecord(tpi.getType(id.index));
422 }
423 
424 lldb::AccessType
425 lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
426   switch (access) {
427   case MemberAccess::Private:
428     return lldb::eAccessPrivate;
429   case MemberAccess::Protected:
430     return lldb::eAccessProtected;
431   case MemberAccess::Public:
432     return lldb::eAccessPublic;
433   case MemberAccess::None:
434     return lldb::eAccessNone;
435   }
436   llvm_unreachable("unreachable");
437 }
438 
439 TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
440   switch (cvt.kind()) {
441   case LF_CLASS:
442   case LF_STRUCTURE:
443   case LF_INTERFACE: {
444     ClassRecord cr;
445     cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
446     return cr.FieldList;
447   }
448   case LF_UNION: {
449     UnionRecord ur;
450     cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
451     return ur.FieldList;
452   }
453   case LF_ENUM: {
454     EnumRecord er;
455     cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
456     return er.FieldList;
457   }
458   default:
459     llvm_unreachable("Unreachable!");
460   }
461 }
462 
463 TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
464   lldbassert(modifier.kind() == LF_MODIFIER);
465   ModifierRecord mr;
466   llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
467   return mr.ModifiedType;
468 }
469 
470 llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
471   return MSVCUndecoratedNameParser::DropScope(name);
472 }
473 
474 VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
475   VariableInfo result;
476 
477   if (sym.kind() == S_REGREL32) {
478     RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
479     cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
480     result.type = reg.Type;
481     result.name = reg.Name;
482     return result;
483   }
484 
485   if (sym.kind() == S_REGISTER) {
486     RegisterSym reg(SymbolRecordKind::RegisterSym);
487     cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
488     result.type = reg.Index;
489     result.name = reg.Name;
490     return result;
491   }
492 
493   if (sym.kind() == S_LOCAL) {
494     LocalSym local(SymbolRecordKind::LocalSym);
495     cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
496     result.type = local.Type;
497     result.name = local.Name;
498     result.is_param =
499         ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);
500     return result;
501   }
502 
503   if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {
504     DataSym data(SymbolRecordKind::DataSym);
505     cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data));
506     result.type = data.Type;
507     result.name = data.Name;
508     return result;
509   }
510 
511   if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {
512     ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);
513     cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data));
514     result.type = data.Type;
515     result.name = data.Name;
516     return result;
517   }
518 
519   if (sym.kind() == S_CONSTANT) {
520     ConstantSym constant(SymbolRecordKind::ConstantSym);
521     cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));
522     result.type = constant.Type;
523     result.name = constant.Name;
524     return result;
525   }
526 
527   lldbassert(false && "Invalid variable record kind!");
528   return {};
529 }
530 
531 static llvm::FixedStreamArray<FrameData>::Iterator
532 GetCorrespondingFrameData(lldb::addr_t load_addr,
533                           const DebugFrameDataSubsectionRef &fpo_data,
534                           const Variable::RangeList &ranges) {
535   lldbassert(!ranges.IsEmpty());
536 
537   // assume that all variable ranges correspond to one frame data
538   using RangeListEntry = Variable::RangeList::Entry;
539   const RangeListEntry &range = ranges.GetEntryRef(0);
540 
541   auto it = fpo_data.begin();
542 
543   // start by searching first frame data range containing variable range
544   for (; it != fpo_data.end(); ++it) {
545     RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
546 
547     if (fd_range.Contains(range)) {
548       break;
549     }
550   }
551 
552   // then first most nested entry that still contains variable range
553   auto found = it;
554   for (; it != fpo_data.end(); ++it) {
555     RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
556 
557     if (!fd_range.Contains(range)) {
558       break;
559     }
560     found = it;
561   }
562 
563   return found;
564 }
565 
566 static bool GetFrameDataProgram(PdbIndex &index,
567                                 const Variable::RangeList &ranges,
568                                 llvm::StringRef &out_program) {
569   const DebugFrameDataSubsectionRef &new_fpo_data =
570       index.dbi().getNewFpoRecords();
571 
572   auto frame_data_it =
573       GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges);
574   if (frame_data_it == new_fpo_data.end())
575     return false;
576 
577   PDBStringTable &strings = cantFail(index.pdb().getStringTable());
578   out_program = cantFail(strings.getStringForID(frame_data_it->FrameFunc));
579   return true;
580 }
581 
582 static RegisterId GetBaseFrameRegister(PdbIndex &index,
583                                        PdbCompilandSymId frame_proc_id,
584                                        bool is_parameter) {
585   CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);
586   lldbassert(frame_proc_cvs.kind() == S_FRAMEPROC);
587 
588   FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);
589   cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,
590                                                            frame_proc));
591 
592   CPUType cpu_type = index.compilands()
593                          .GetCompiland(frame_proc_id.modi)
594                          ->m_compile_opts->Machine;
595 
596   return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type)
597                       : frame_proc.getLocalFramePtrReg(cpu_type);
598 }
599 
600 VariableInfo lldb_private::npdb::GetVariableLocationInfo(
601     PdbIndex &index, PdbCompilandSymId var_id, Block &block,
602     lldb::ModuleSP module) {
603 
604   CVSymbol sym = index.ReadSymbolRecord(var_id);
605 
606   VariableInfo result = GetVariableNameInfo(sym);
607 
608   if (sym.kind() == S_REGREL32) {
609     RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
610     cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
611     result.location =
612         MakeRegRelLocationExpression(reg.Register, reg.Offset, module);
613     result.ranges.emplace();
614     return result;
615   }
616 
617   if (sym.kind() == S_REGISTER) {
618     RegisterSym reg(SymbolRecordKind::RegisterSym);
619     cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
620     result.location = MakeEnregisteredLocationExpression(reg.Register, module);
621     result.ranges.emplace();
622     return result;
623   }
624 
625   if (sym.kind() == S_LOCAL) {
626     LocalSym local(SymbolRecordKind::LocalSym);
627     cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
628 
629     PdbCompilandSymId loc_specifier_id(var_id.modi,
630                                        var_id.offset + sym.RecordData.size());
631     CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
632     switch(loc_specifier_cvs.kind()) {
633     case S_DEFRANGE_FRAMEPOINTER_REL: {
634       DefRangeFramePointerRelSym loc(
635           SymbolRecordKind::DefRangeFramePointerRelSym);
636       cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
637           loc_specifier_cvs, loc));
638 
639       Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
640 
641       // TODO: may be better to pass function scope and not lookup it every
642       // time? find nearest parent function block
643       Block *cur = &block;
644       while (cur->GetParent()) {
645         cur = cur->GetParent();
646       }
647       PdbCompilandSymId func_scope_id =
648           PdbSymUid(cur->GetID()).asCompilandSym();
649       CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
650       lldbassert(func_block_cvs.kind() == S_GPROC32 ||
651                  func_block_cvs.kind() == S_LPROC32);
652 
653       PdbCompilandSymId frame_proc_id(
654           func_scope_id.modi, func_scope_id.offset + func_block_cvs.length());
655 
656       RegisterId base_reg =
657           GetBaseFrameRegister(index, frame_proc_id, result.is_param);
658 
659       if (base_reg == RegisterId::VFRAME) {
660         llvm::StringRef program;
661         if (GetFrameDataProgram(index, ranges, program)) {
662           result.location =
663               MakeVFrameRelLocationExpression(program, loc.Hdr.Offset, module);
664           result.ranges = std::move(ranges);
665         } else {
666           // invalid variable
667         }
668       } else {
669         result.location =
670             MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
671         result.ranges = std::move(ranges);
672       }
673       break;
674     }
675     case S_DEFRANGE_REGISTER_REL: {
676       DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
677       cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
678           loc_specifier_cvs, loc));
679 
680       Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
681 
682       RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register;
683 
684       if (base_reg == RegisterId::VFRAME) {
685         llvm::StringRef program;
686         if (GetFrameDataProgram(index, ranges, program)) {
687           result.location = MakeVFrameRelLocationExpression(
688               program, loc.Hdr.BasePointerOffset, module);
689           result.ranges = std::move(ranges);
690         } else {
691           // invalid variable
692         }
693       } else {
694         result.location = MakeRegRelLocationExpression(
695             base_reg, loc.Hdr.BasePointerOffset, module);
696         result.ranges = std::move(ranges);
697       }
698       break;
699     }
700     case S_DEFRANGE_REGISTER: {
701       DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);
702       cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(
703           loc_specifier_cvs, loc));
704 
705       RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register;
706       result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
707       result.location = MakeEnregisteredLocationExpression(base_reg, module);
708       break;
709     }
710     case S_DEFRANGE_SUBFIELD_REGISTER: {
711       // A vector of register id and member size pairs. If the variable is a
712       // simple type, then we don't know the number of subfields. Otherwise, the
713       // vector size will be the number of subfields in the udt type.
714       llvm::SmallVector<std::pair<RegisterId, uint32_t>> members_info;
715       bool is_simple_type = result.type.isSimple();
716       if (!is_simple_type) {
717         CVType class_cvt = index.tpi().getType(result.type);
718         ClassRecord class_record = CVTagRecord::create(class_cvt).asClass();
719         CVType field_list = index.tpi().getType(class_record.FieldList);
720         FindMembersSize find_members_size(members_info, index.tpi());
721         if (llvm::Error err =
722                 visitMemberRecordStream(field_list.data(), find_members_size)) {
723           llvm::consumeError(std::move(err));
724           break;
725         }
726       }
727 
728       uint32_t prev_offset = 0;
729       uint32_t cur_offset = 0;
730       size_t member_idx = 0;
731       // Assuming S_DEFRANGE_SUBFIELD_REGISTER is followed only by
732       // S_DEFRANGE_SUBFIELD_REGISTER, need to verify.
733       while (loc_specifier_cvs.kind() == S_DEFRANGE_SUBFIELD_REGISTER) {
734         if (!is_simple_type && member_idx >= members_info.size())
735           break;
736 
737         DefRangeSubfieldRegisterSym loc(
738             SymbolRecordKind::DefRangeSubfieldRegisterSym);
739         cantFail(SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(
740             loc_specifier_cvs, loc));
741 
742         if (result.ranges) {
743           result.ranges = Variable::RangeList::GetOverlaps(
744               *result.ranges, MakeRangeList(index, loc.Range, loc.Gaps));
745         } else {
746           result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
747           result.ranges->Sort();
748         }
749 
750         if (is_simple_type) {
751           // Fix last member's size.
752           if (!members_info.empty())
753             members_info.back().second =
754                 loc.Hdr.OffsetInParent - prev_offset;
755           members_info.emplace_back((RegisterId)(uint16_t)loc.Hdr.Register, 0);
756           prev_offset = loc.Hdr.OffsetInParent;
757         } else {
758           // Some fields maybe optimized away and have no
759           // S_DEFRANGE_SUBFIELD_REGISTER to describe them. Skip them.
760           while (loc.Hdr.OffsetInParent != cur_offset &&
761                  member_idx < members_info.size()) {
762             cur_offset += members_info[member_idx].second;
763             ++member_idx;
764           }
765           if (member_idx < members_info.size()) {
766             members_info[member_idx].first =
767                 (RegisterId)(uint16_t)loc.Hdr.Register;
768             cur_offset += members_info[member_idx].second;
769             ++member_idx;
770           }
771         }
772         // Go to next S_DEFRANGE_SUBFIELD_REGISTER.
773         loc_specifier_id = PdbCompilandSymId(
774             loc_specifier_id.modi,
775             loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());
776         loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
777       }
778       if (is_simple_type && !members_info.empty())
779         members_info.back().second =
780             GetTypeSizeForSimpleKind(result.type.getSimpleKind()) - prev_offset;
781       auto member_info_ref = llvm::makeArrayRef(members_info);
782       result.location =
783           MakeEnregisteredLocationExpressionForClass(member_info_ref, module);
784       break;
785     }
786     default:
787       // FIXME: Handle other kinds. LLVM only generates the 4 types of records
788       // above.
789       break;
790     }
791     return result;
792   }
793   llvm_unreachable("Symbol is not a local variable!");
794   return result;
795 }
796 
797 lldb::BasicType
798 lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {
799   switch (kind) {
800   case SimpleTypeKind::Boolean128:
801   case SimpleTypeKind::Boolean16:
802   case SimpleTypeKind::Boolean32:
803   case SimpleTypeKind::Boolean64:
804   case SimpleTypeKind::Boolean8:
805     return lldb::eBasicTypeBool;
806   case SimpleTypeKind::Byte:
807   case SimpleTypeKind::UnsignedCharacter:
808     return lldb::eBasicTypeUnsignedChar;
809   case SimpleTypeKind::NarrowCharacter:
810     return lldb::eBasicTypeChar;
811   case SimpleTypeKind::SignedCharacter:
812   case SimpleTypeKind::SByte:
813     return lldb::eBasicTypeSignedChar;
814   case SimpleTypeKind::Character16:
815     return lldb::eBasicTypeChar16;
816   case SimpleTypeKind::Character32:
817     return lldb::eBasicTypeChar32;
818   case SimpleTypeKind::Character8:
819     return lldb::eBasicTypeChar8;
820   case SimpleTypeKind::Complex80:
821     return lldb::eBasicTypeLongDoubleComplex;
822   case SimpleTypeKind::Complex64:
823     return lldb::eBasicTypeDoubleComplex;
824   case SimpleTypeKind::Complex32:
825     return lldb::eBasicTypeFloatComplex;
826   case SimpleTypeKind::Float128:
827   case SimpleTypeKind::Float80:
828     return lldb::eBasicTypeLongDouble;
829   case SimpleTypeKind::Float64:
830     return lldb::eBasicTypeDouble;
831   case SimpleTypeKind::Float32:
832     return lldb::eBasicTypeFloat;
833   case SimpleTypeKind::Float16:
834     return lldb::eBasicTypeHalf;
835   case SimpleTypeKind::Int128:
836     return lldb::eBasicTypeInt128;
837   case SimpleTypeKind::Int64:
838   case SimpleTypeKind::Int64Quad:
839     return lldb::eBasicTypeLongLong;
840   case SimpleTypeKind::Int32:
841     return lldb::eBasicTypeInt;
842   case SimpleTypeKind::Int16:
843   case SimpleTypeKind::Int16Short:
844     return lldb::eBasicTypeShort;
845   case SimpleTypeKind::UInt128:
846     return lldb::eBasicTypeUnsignedInt128;
847   case SimpleTypeKind::UInt64:
848   case SimpleTypeKind::UInt64Quad:
849     return lldb::eBasicTypeUnsignedLongLong;
850   case SimpleTypeKind::HResult:
851   case SimpleTypeKind::UInt32:
852     return lldb::eBasicTypeUnsignedInt;
853   case SimpleTypeKind::UInt16:
854   case SimpleTypeKind::UInt16Short:
855     return lldb::eBasicTypeUnsignedShort;
856   case SimpleTypeKind::Int32Long:
857     return lldb::eBasicTypeLong;
858   case SimpleTypeKind::UInt32Long:
859     return lldb::eBasicTypeUnsignedLong;
860   case SimpleTypeKind::Void:
861     return lldb::eBasicTypeVoid;
862   case SimpleTypeKind::WideCharacter:
863     return lldb::eBasicTypeWChar;
864   default:
865     return lldb::eBasicTypeInvalid;
866   }
867 }
868 
869 size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {
870   switch (kind) {
871   case SimpleTypeKind::Boolean128:
872   case SimpleTypeKind::Int128:
873   case SimpleTypeKind::UInt128:
874   case SimpleTypeKind::Float128:
875     return 16;
876   case SimpleTypeKind::Complex80:
877   case SimpleTypeKind::Float80:
878     return 10;
879   case SimpleTypeKind::Boolean64:
880   case SimpleTypeKind::Complex64:
881   case SimpleTypeKind::UInt64:
882   case SimpleTypeKind::UInt64Quad:
883   case SimpleTypeKind::Float64:
884   case SimpleTypeKind::Int64:
885   case SimpleTypeKind::Int64Quad:
886     return 8;
887   case SimpleTypeKind::Boolean32:
888   case SimpleTypeKind::Character32:
889   case SimpleTypeKind::Complex32:
890   case SimpleTypeKind::Float32:
891   case SimpleTypeKind::Int32:
892   case SimpleTypeKind::Int32Long:
893   case SimpleTypeKind::UInt32Long:
894   case SimpleTypeKind::HResult:
895   case SimpleTypeKind::UInt32:
896     return 4;
897   case SimpleTypeKind::Boolean16:
898   case SimpleTypeKind::Character16:
899   case SimpleTypeKind::Float16:
900   case SimpleTypeKind::Int16:
901   case SimpleTypeKind::Int16Short:
902   case SimpleTypeKind::UInt16:
903   case SimpleTypeKind::UInt16Short:
904   case SimpleTypeKind::WideCharacter:
905     return 2;
906   case SimpleTypeKind::Boolean8:
907   case SimpleTypeKind::Byte:
908   case SimpleTypeKind::UnsignedCharacter:
909   case SimpleTypeKind::NarrowCharacter:
910   case SimpleTypeKind::SignedCharacter:
911   case SimpleTypeKind::SByte:
912   case SimpleTypeKind::Character8:
913     return 1;
914   case SimpleTypeKind::Void:
915   default:
916     return 0;
917   }
918 }
919 
920 PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,
921                                                      TpiStream &tpi) {
922   if (id.index.isSimple())
923     return id;
924 
925   CVType cvt = tpi.getType(id.index);
926 
927   // Only tag records have a best and a worst record.
928   if (!IsTagRecord(cvt))
929     return id;
930 
931   // Tag records that are not forward decls are full decls, hence they are the
932   // best.
933   if (!IsForwardRefUdt(cvt))
934     return id;
935 
936   return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));
937 }
938 
939 template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {
940   RecordType record;
941   llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));
942   return record.getSize();
943 }
944 
945 size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,
946                                          llvm::pdb::TpiStream &tpi) {
947   if (id.index.isSimple()) {
948     switch (id.index.getSimpleMode()) {
949     case SimpleTypeMode::Direct:
950       return GetTypeSizeForSimpleKind(id.index.getSimpleKind());
951     case SimpleTypeMode::NearPointer32:
952     case SimpleTypeMode::FarPointer32:
953       return 4;
954     case SimpleTypeMode::NearPointer64:
955       return 8;
956     case SimpleTypeMode::NearPointer128:
957       return 16;
958     default:
959       break;
960     }
961     return 0;
962   }
963 
964   TypeIndex index = id.index;
965   if (IsForwardRefUdt(index, tpi))
966     index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));
967 
968   CVType cvt = tpi.getType(index);
969   switch (cvt.kind()) {
970   case LF_MODIFIER:
971     return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);
972   case LF_ENUM: {
973     EnumRecord record;
974     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));
975     return GetSizeOfType({record.UnderlyingType}, tpi);
976   }
977   case LF_POINTER:
978     return GetSizeOfTypeInternal<PointerRecord>(cvt);
979   case LF_ARRAY:
980     return GetSizeOfTypeInternal<ArrayRecord>(cvt);
981   case LF_CLASS:
982   case LF_STRUCTURE:
983   case LF_INTERFACE:
984     return GetSizeOfTypeInternal<ClassRecord>(cvt);
985   case LF_UNION:
986     return GetSizeOfTypeInternal<UnionRecord>(cvt);
987   default:
988     break;
989   }
990   return 0;
991 }
992