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