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