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