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