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
MakeRangeList(const PdbIndex & index,const LocalVariableAddrRange & range,llvm::ArrayRef<LocalVariableAddrGap> gaps)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
create(CVType type)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
CVTagRecord(ClassRecord && c)76 CVTagRecord::CVTagRecord(ClassRecord &&c)
77 : cvclass(std::move(c)),
78 m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
CVTagRecord(UnionRecord && u)79 CVTagRecord::CVTagRecord(UnionRecord &&u)
80 : cvunion(std::move(u)), m_kind(Union) {}
CVTagRecord(EnumRecord && e)81 CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
82
CVSymToPDBSym(SymbolKind kind)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
CVTypeToPDBType(TypeLeafKind kind)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
SymbolHasAddress(const CVSymbol & sym)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
SymbolIsCode(const CVSymbol & sym)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
createRecord(const CVSymbol & sym)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>
GetSegmentAndOffset(const CVSymbol & sym)216 static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
217 RecordT record = createRecord<RecordT>(sym);
218 return {record.Segment, record.CodeOffset};
219 }
220
221 template <>
GetSegmentAndOffset(const CVSymbol & sym)222 SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
223 TrampolineSym record = createRecord<TrampolineSym>(sym);
224 return {record.ThunkSection, record.ThunkOffset};
225 }
226
GetSegmentAndOffset(const CVSymbol & sym)227 template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
228 Thunk32Sym record = createRecord<Thunk32Sym>(sym);
229 return {record.Segment, record.Offset};
230 }
231
232 template <>
GetSegmentAndOffset(const CVSymbol & sym)233 SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
234 CoffGroupSym record = createRecord<CoffGroupSym>(sym);
235 return {record.Segment, record.Offset};
236 }
237
GetSegmentAndOffset(const CVSymbol & sym)238 template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
239 DataSym record = createRecord<DataSym>(sym);
240 return {record.Segment, record.DataOffset};
241 }
242
243 template <>
GetSegmentAndOffset(const CVSymbol & sym)244 SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
245 ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
246 return {record.Segment, record.DataOffset};
247 }
248
GetSegmentAndOffset(const CVSymbol & sym)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>
GetSegmentOffsetAndLength(const CVSymbol & sym)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
GetSegmentOffsetAndLength(const CVSymbol & sym)303 GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
304 TrampolineSym record = createRecord<TrampolineSym>(sym);
305 return {record.ThunkSection, record.ThunkOffset, record.Size};
306 }
307
308 template <>
GetSegmentOffsetAndLength(const CVSymbol & sym)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
GetSegmentOffsetAndLength(const CVSymbol & sym)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
GetSegmentOffsetAndLength(const CVSymbol & sym)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
IsForwardRefUdt(CVType cvt)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
IsTagRecord(llvm::codeview::CVType cvt)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
IsClassStructUnion(llvm::codeview::CVType cvt)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
IsForwardRefUdt(const PdbTypeSymId & id,TpiStream & tpi)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
IsTagRecord(const PdbTypeSymId & id,TpiStream & tpi)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
TranslateMemberAccess(MemberAccess access)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
GetFieldListIndex(CVType cvt)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
LookThroughModifierRecord(CVType modifier)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
DropNameScope(llvm::StringRef name)452 llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
453 return MSVCUndecoratedNameParser::DropScope(name);
454 }
455
GetVariableNameInfo(CVSymbol sym)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
GetCorrespondingFrameData(lldb::addr_t load_addr,const DebugFrameDataSubsectionRef & fpo_data,const Variable::RangeList & ranges)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
GetFrameDataProgram(PdbIndex & index,const Variable::RangeList & ranges,llvm::StringRef & out_program)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
GetBaseFrameRegister(PdbIndex & index,PdbCompilandSymId frame_proc_id,bool is_parameter)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
GetVariableLocationInfo(PdbIndex & index,PdbCompilandSymId var_id,Block & block,lldb::ModuleSP module)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 = █
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
GetCompilerTypeForSimpleKind(SimpleTypeKind kind)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
GetTypeSizeForSimpleKind(SimpleTypeKind kind)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
GetBestPossibleDecl(PdbTypeSymId id,TpiStream & tpi)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
GetSizeOfTypeInternal(CVType cvt)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
GetSizeOfType(PdbTypeSymId id,llvm::pdb::TpiStream & tpi)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