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