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
MakeRangeList(const PdbIndex & index,const LocalVariableAddrRange & range,llvm::ArrayRef<LocalVariableAddrGap> gaps)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 {
FindMembersSize__anon204fc7730111::FindMembersSize56 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;
visitKnownMember__anon204fc7730111::FindMembersSize62 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
create(CVType type)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
CVTagRecord(ClassRecord && c)97 CVTagRecord::CVTagRecord(ClassRecord &&c)
98 : cvclass(std::move(c)),
99 m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
CVTagRecord(UnionRecord && u)100 CVTagRecord::CVTagRecord(UnionRecord &&u)
101 : cvunion(std::move(u)), m_kind(Union) {}
CVTagRecord(EnumRecord && e)102 CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
103
CVSymToPDBSym(SymbolKind kind)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
CVTypeToPDBType(TypeLeafKind kind)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
SymbolHasAddress(const CVSymbol & sym)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
SymbolIsCode(const CVSymbol & sym)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
createRecord(const CVSymbol & sym)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>
GetSegmentAndOffset(const CVSymbol & sym)237 static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
238 RecordT record = createRecord<RecordT>(sym);
239 return {record.Segment, record.CodeOffset};
240 }
241
242 template <>
GetSegmentAndOffset(const CVSymbol & sym)243 SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
244 TrampolineSym record = createRecord<TrampolineSym>(sym);
245 return {record.ThunkSection, record.ThunkOffset};
246 }
247
GetSegmentAndOffset(const CVSymbol & sym)248 template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
249 Thunk32Sym record = createRecord<Thunk32Sym>(sym);
250 return {record.Segment, record.Offset};
251 }
252
253 template <>
GetSegmentAndOffset(const CVSymbol & sym)254 SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
255 CoffGroupSym record = createRecord<CoffGroupSym>(sym);
256 return {record.Segment, record.Offset};
257 }
258
GetSegmentAndOffset(const CVSymbol & sym)259 template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
260 DataSym record = createRecord<DataSym>(sym);
261 return {record.Segment, record.DataOffset};
262 }
263
264 template <>
GetSegmentAndOffset(const CVSymbol & sym)265 SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
266 ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
267 return {record.Segment, record.DataOffset};
268 }
269
GetSegmentAndOffset(const CVSymbol & sym)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>
GetSegmentOffsetAndLength(const CVSymbol & sym)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
GetSegmentOffsetAndLength(const CVSymbol & sym)324 GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
325 TrampolineSym record = createRecord<TrampolineSym>(sym);
326 return {record.ThunkSection, record.ThunkOffset, record.Size};
327 }
328
329 template <>
GetSegmentOffsetAndLength(const CVSymbol & sym)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
GetSegmentOffsetAndLength(const CVSymbol & sym)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
GetSegmentOffsetAndLength(const CVSymbol & sym)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
IsForwardRefUdt(CVType cvt)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
IsTagRecord(llvm::codeview::CVType cvt)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
IsClassStructUnion(llvm::codeview::CVType cvt)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
IsForwardRefUdt(const PdbTypeSymId & id,TpiStream & tpi)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
IsTagRecord(const PdbTypeSymId & id,TpiStream & tpi)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
TranslateMemberAccess(MemberAccess access)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
GetFieldListIndex(CVType cvt)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
LookThroughModifierRecord(CVType modifier)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
DropNameScope(llvm::StringRef name)473 llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
474 return MSVCUndecoratedNameParser::DropScope(name);
475 }
476
GetVariableNameInfo(CVSymbol sym)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
GetCorrespondingFrameData(lldb::addr_t load_addr,const DebugFrameDataSubsectionRef & fpo_data,const Variable::RangeList & ranges)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
GetFrameDataProgram(PdbIndex & index,const Variable::RangeList & ranges,llvm::StringRef & out_program)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
GetBaseFrameRegister(PdbIndex & index,PdbCompilandSymId frame_proc_id,bool is_parameter)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
GetVariableLocationInfo(PdbIndex & index,PdbCompilandSymId var_id,Block & func_block,lldb::ModuleSP module)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
GetCompilerTypeForSimpleKind(SimpleTypeKind kind)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
GetTypeSizeForSimpleKind(SimpleTypeKind kind)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
GetBestPossibleDecl(PdbTypeSymId id,TpiStream & tpi)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
GetSizeOfTypeInternal(CVType cvt)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
GetSizeOfType(PdbTypeSymId id,llvm::pdb::TpiStream & tpi)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