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 #include "PdbSymUid.h"
12 
13 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
14 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
15 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
16 
17 #include "lldb/Utility/LLDBAssert.h"
18 
19 #include "lldb/lldb-enumerations.h"
20 
21 using namespace lldb_private;
22 using namespace lldb_private::npdb;
23 using namespace llvm::codeview;
24 using namespace llvm::pdb;
25 
26 CVTagRecord CVTagRecord::create(CVType type) {
27   assert(IsTagRecord(type) && "type is not a tag record!");
28   switch (type.kind()) {
29   case LF_CLASS:
30   case LF_STRUCTURE:
31   case LF_INTERFACE: {
32     ClassRecord cr;
33     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));
34     return CVTagRecord(std::move(cr));
35   }
36   case LF_UNION: {
37     UnionRecord ur;
38     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));
39     return CVTagRecord(std::move(ur));
40   }
41   case LF_ENUM: {
42     EnumRecord er;
43     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));
44     return CVTagRecord(std::move(er));
45   }
46   default:
47     llvm_unreachable("Unreachable!");
48   }
49 }
50 
51 CVTagRecord::CVTagRecord(ClassRecord &&c)
52     : cvclass(std::move(c)),
53       m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
54 CVTagRecord::CVTagRecord(UnionRecord &&u)
55     : cvunion(std::move(u)), m_kind(Union) {}
56 CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
57 
58 PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
59   switch (kind) {
60   case S_COMPILE3:
61   case S_OBJNAME:
62     return PDB_SymType::CompilandDetails;
63   case S_ENVBLOCK:
64     return PDB_SymType::CompilandEnv;
65   case S_THUNK32:
66   case S_TRAMPOLINE:
67     return PDB_SymType::Thunk;
68   case S_COFFGROUP:
69     return PDB_SymType::CoffGroup;
70   case S_EXPORT:
71     return PDB_SymType::Export;
72   case S_LPROC32:
73   case S_GPROC32:
74   case S_LPROC32_DPC:
75     return PDB_SymType::Function;
76   case S_PUB32:
77     return PDB_SymType::PublicSymbol;
78   case S_INLINESITE:
79     return PDB_SymType::InlineSite;
80   case S_LOCAL:
81   case S_BPREL32:
82   case S_REGREL32:
83   case S_MANCONSTANT:
84   case S_CONSTANT:
85   case S_LDATA32:
86   case S_GDATA32:
87   case S_LMANDATA:
88   case S_GMANDATA:
89   case S_LTHREAD32:
90   case S_GTHREAD32:
91     return PDB_SymType::Data;
92   case S_BLOCK32:
93     return PDB_SymType::Block;
94   case S_LABEL32:
95     return PDB_SymType::Label;
96   case S_CALLSITEINFO:
97     return PDB_SymType::CallSite;
98   case S_HEAPALLOCSITE:
99     return PDB_SymType::HeapAllocationSite;
100   case S_CALLEES:
101     return PDB_SymType::Callee;
102   case S_CALLERS:
103     return PDB_SymType::Caller;
104   default:
105     lldbassert(false && "Invalid symbol record kind!");
106   }
107   return PDB_SymType::None;
108 }
109 
110 PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
111   switch (kind) {
112   case LF_ARRAY:
113     return PDB_SymType::ArrayType;
114   case LF_ARGLIST:
115     return PDB_SymType::FunctionSig;
116   case LF_BCLASS:
117     return PDB_SymType::BaseClass;
118   case LF_BINTERFACE:
119     return PDB_SymType::BaseInterface;
120   case LF_CLASS:
121   case LF_STRUCTURE:
122   case LF_INTERFACE:
123   case LF_UNION:
124     return PDB_SymType::UDT;
125   case LF_POINTER:
126     return PDB_SymType::PointerType;
127   case LF_ENUM:
128     return PDB_SymType::Enum;
129   case LF_PROCEDURE:
130     return PDB_SymType::FunctionSig;
131   case LF_BITFIELD:
132     return PDB_SymType::BuiltinType;
133   default:
134     lldbassert(false && "Invalid type record kind!");
135   }
136   return PDB_SymType::None;
137 }
138 
139 bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
140   switch (sym.kind()) {
141   case S_GPROC32:
142   case S_LPROC32:
143   case S_GPROC32_ID:
144   case S_LPROC32_ID:
145   case S_LPROC32_DPC:
146   case S_LPROC32_DPC_ID:
147   case S_THUNK32:
148   case S_TRAMPOLINE:
149   case S_COFFGROUP:
150   case S_BLOCK32:
151   case S_LABEL32:
152   case S_CALLSITEINFO:
153   case S_HEAPALLOCSITE:
154   case S_LDATA32:
155   case S_GDATA32:
156   case S_LMANDATA:
157   case S_GMANDATA:
158   case S_LTHREAD32:
159   case S_GTHREAD32:
160     return true;
161   default:
162     return false;
163   }
164 }
165 
166 bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
167   switch (sym.kind()) {
168   case S_GPROC32:
169   case S_LPROC32:
170   case S_GPROC32_ID:
171   case S_LPROC32_ID:
172   case S_LPROC32_DPC:
173   case S_LPROC32_DPC_ID:
174   case S_THUNK32:
175   case S_TRAMPOLINE:
176   case S_COFFGROUP:
177   case S_BLOCK32:
178     return true;
179   default:
180     return false;
181   }
182 }
183 
184 template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
185   RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
186   cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
187   return record;
188 }
189 
190 template <typename RecordT>
191 static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
192   RecordT record = createRecord<RecordT>(sym);
193   return {record.Segment, record.CodeOffset};
194 }
195 
196 template <>
197 SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
198   TrampolineSym record = createRecord<TrampolineSym>(sym);
199   return {record.ThunkSection, record.ThunkOffset};
200 }
201 
202 template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
203   Thunk32Sym record = createRecord<Thunk32Sym>(sym);
204   return {record.Segment, record.Offset};
205 }
206 
207 template <>
208 SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
209   CoffGroupSym record = createRecord<CoffGroupSym>(sym);
210   return {record.Segment, record.Offset};
211 }
212 
213 template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
214   DataSym record = createRecord<DataSym>(sym);
215   return {record.Segment, record.DataOffset};
216 }
217 
218 template <>
219 SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
220   ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
221   return {record.Segment, record.DataOffset};
222 }
223 
224 SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
225   switch (sym.kind()) {
226   case S_GPROC32:
227   case S_LPROC32:
228   case S_GPROC32_ID:
229   case S_LPROC32_ID:
230   case S_LPROC32_DPC:
231   case S_LPROC32_DPC_ID:
232     return ::GetSegmentAndOffset<ProcSym>(sym);
233   case S_THUNK32:
234     return ::GetSegmentAndOffset<Thunk32Sym>(sym);
235     break;
236   case S_TRAMPOLINE:
237     return ::GetSegmentAndOffset<TrampolineSym>(sym);
238     break;
239   case S_COFFGROUP:
240     return ::GetSegmentAndOffset<CoffGroupSym>(sym);
241     break;
242   case S_BLOCK32:
243     return ::GetSegmentAndOffset<BlockSym>(sym);
244     break;
245   case S_LABEL32:
246     return ::GetSegmentAndOffset<LabelSym>(sym);
247     break;
248   case S_CALLSITEINFO:
249     return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
250     break;
251   case S_HEAPALLOCSITE:
252     return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
253     break;
254   case S_LDATA32:
255   case S_GDATA32:
256   case S_LMANDATA:
257   case S_GMANDATA:
258     return ::GetSegmentAndOffset<DataSym>(sym);
259     break;
260   case S_LTHREAD32:
261   case S_GTHREAD32:
262     return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
263     break;
264   default:
265     lldbassert(false && "Record does not have a segment/offset!");
266   }
267   return {0, 0};
268 }
269 
270 template <typename RecordT>
271 SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
272   RecordT record = createRecord<RecordT>(sym);
273   return {record.Segment, record.CodeOffset, record.CodeSize};
274 }
275 
276 template <>
277 SegmentOffsetLength
278 GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
279   TrampolineSym record = createRecord<TrampolineSym>(sym);
280   return {record.ThunkSection, record.ThunkOffset, record.Size};
281 }
282 
283 template <>
284 SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
285   Thunk32Sym record = createRecord<Thunk32Sym>(sym);
286   return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
287 }
288 
289 template <>
290 SegmentOffsetLength
291 GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
292   CoffGroupSym record = createRecord<CoffGroupSym>(sym);
293   return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
294 }
295 
296 SegmentOffsetLength
297 lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
298   switch (sym.kind()) {
299   case S_GPROC32:
300   case S_LPROC32:
301   case S_GPROC32_ID:
302   case S_LPROC32_ID:
303   case S_LPROC32_DPC:
304   case S_LPROC32_DPC_ID:
305     return ::GetSegmentOffsetAndLength<ProcSym>(sym);
306   case S_THUNK32:
307     return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
308     break;
309   case S_TRAMPOLINE:
310     return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
311     break;
312   case S_COFFGROUP:
313     return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
314     break;
315   case S_BLOCK32:
316     return ::GetSegmentOffsetAndLength<BlockSym>(sym);
317     break;
318   default:
319     lldbassert(false && "Record does not have a segment/offset/length triple!");
320   }
321   return {0, 0, 0};
322 }
323 
324 bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
325   ClassRecord cr;
326   UnionRecord ur;
327   EnumRecord er;
328   switch (cvt.kind()) {
329   case LF_CLASS:
330   case LF_STRUCTURE:
331   case LF_INTERFACE:
332     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
333     return cr.isForwardRef();
334   case LF_UNION:
335     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
336     return ur.isForwardRef();
337   case LF_ENUM:
338     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
339     return er.isForwardRef();
340   default:
341     return false;
342   }
343 }
344 
345 bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {
346   switch (cvt.kind()) {
347   case LF_CLASS:
348   case LF_STRUCTURE:
349   case LF_UNION:
350   case LF_ENUM:
351     return true;
352   default:
353     return false;
354   }
355 }
356 
357 bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
358                                          TpiStream &tpi) {
359   if (id.is_ipi || id.index.isSimple())
360     return false;
361   return IsForwardRefUdt(tpi.getType(id.index));
362 }
363 
364 bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {
365   if (id.is_ipi || id.index.isSimple())
366     return false;
367   return IsTagRecord(tpi.getType(id.index));
368 }
369 
370 lldb::AccessType
371 lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
372   switch (access) {
373   case MemberAccess::Private:
374     return lldb::eAccessPrivate;
375   case MemberAccess::Protected:
376     return lldb::eAccessProtected;
377   case MemberAccess::Public:
378     return lldb::eAccessPublic;
379   case MemberAccess::None:
380     return lldb::eAccessNone;
381   }
382   llvm_unreachable("unreachable");
383 }
384 
385 TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
386   switch (cvt.kind()) {
387   case LF_CLASS:
388   case LF_STRUCTURE:
389   case LF_INTERFACE: {
390     ClassRecord cr;
391     cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
392     return cr.FieldList;
393   }
394   case LF_UNION: {
395     UnionRecord ur;
396     cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
397     return ur.FieldList;
398   }
399   case LF_ENUM: {
400     EnumRecord er;
401     cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
402     return er.FieldList;
403   }
404   default:
405     llvm_unreachable("Unreachable!");
406   }
407 }
408 
409 TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
410   lldbassert(modifier.kind() == LF_MODIFIER);
411   ModifierRecord mr;
412   llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
413   return mr.ModifiedType;
414 }
415 
416 llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
417   // Not all PDB names can be parsed with CPlusPlusNameParser.
418   // E.g. it fails on names containing `anonymous namespace'.
419   // So we simply drop everything before '::'
420 
421   auto offset = name.rfind("::");
422   if (offset == llvm::StringRef::npos)
423     return name;
424   assert(offset + 2 <= name.size());
425 
426   return name.substr(offset + 2);
427 }
428 
429 lldb::BasicType
430 lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {
431   switch (kind) {
432   case SimpleTypeKind::Boolean128:
433   case SimpleTypeKind::Boolean16:
434   case SimpleTypeKind::Boolean32:
435   case SimpleTypeKind::Boolean64:
436   case SimpleTypeKind::Boolean8:
437     return lldb::eBasicTypeBool;
438   case SimpleTypeKind::Byte:
439   case SimpleTypeKind::UnsignedCharacter:
440     return lldb::eBasicTypeUnsignedChar;
441   case SimpleTypeKind::NarrowCharacter:
442     return lldb::eBasicTypeChar;
443   case SimpleTypeKind::SignedCharacter:
444   case SimpleTypeKind::SByte:
445     return lldb::eBasicTypeSignedChar;
446   case SimpleTypeKind::Character16:
447     return lldb::eBasicTypeChar16;
448   case SimpleTypeKind::Character32:
449     return lldb::eBasicTypeChar32;
450   case SimpleTypeKind::Complex80:
451     return lldb::eBasicTypeLongDoubleComplex;
452   case SimpleTypeKind::Complex64:
453     return lldb::eBasicTypeDoubleComplex;
454   case SimpleTypeKind::Complex32:
455     return lldb::eBasicTypeFloatComplex;
456   case SimpleTypeKind::Float128:
457   case SimpleTypeKind::Float80:
458     return lldb::eBasicTypeLongDouble;
459   case SimpleTypeKind::Float64:
460     return lldb::eBasicTypeDouble;
461   case SimpleTypeKind::Float32:
462     return lldb::eBasicTypeFloat;
463   case SimpleTypeKind::Float16:
464     return lldb::eBasicTypeHalf;
465   case SimpleTypeKind::Int128:
466     return lldb::eBasicTypeInt128;
467   case SimpleTypeKind::Int64:
468   case SimpleTypeKind::Int64Quad:
469     return lldb::eBasicTypeLongLong;
470   case SimpleTypeKind::Int32:
471     return lldb::eBasicTypeInt;
472   case SimpleTypeKind::Int16:
473   case SimpleTypeKind::Int16Short:
474     return lldb::eBasicTypeShort;
475   case SimpleTypeKind::UInt128:
476     return lldb::eBasicTypeUnsignedInt128;
477   case SimpleTypeKind::UInt64:
478   case SimpleTypeKind::UInt64Quad:
479     return lldb::eBasicTypeUnsignedLongLong;
480   case SimpleTypeKind::HResult:
481   case SimpleTypeKind::UInt32:
482     return lldb::eBasicTypeUnsignedInt;
483   case SimpleTypeKind::UInt16:
484   case SimpleTypeKind::UInt16Short:
485     return lldb::eBasicTypeUnsignedShort;
486   case SimpleTypeKind::Int32Long:
487     return lldb::eBasicTypeLong;
488   case SimpleTypeKind::UInt32Long:
489     return lldb::eBasicTypeUnsignedLong;
490   case SimpleTypeKind::Void:
491     return lldb::eBasicTypeVoid;
492   case SimpleTypeKind::WideCharacter:
493     return lldb::eBasicTypeWChar;
494   default:
495     return lldb::eBasicTypeInvalid;
496   }
497 }
498 
499 size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {
500   switch (kind) {
501   case SimpleTypeKind::Boolean128:
502   case SimpleTypeKind::Int128:
503   case SimpleTypeKind::UInt128:
504   case SimpleTypeKind::Float128:
505     return 16;
506   case SimpleTypeKind::Complex80:
507   case SimpleTypeKind::Float80:
508     return 10;
509   case SimpleTypeKind::Boolean64:
510   case SimpleTypeKind::Complex64:
511   case SimpleTypeKind::UInt64:
512   case SimpleTypeKind::UInt64Quad:
513   case SimpleTypeKind::Float64:
514   case SimpleTypeKind::Int64:
515   case SimpleTypeKind::Int64Quad:
516     return 8;
517   case SimpleTypeKind::Boolean32:
518   case SimpleTypeKind::Character32:
519   case SimpleTypeKind::Complex32:
520   case SimpleTypeKind::Float32:
521   case SimpleTypeKind::Int32:
522   case SimpleTypeKind::Int32Long:
523   case SimpleTypeKind::UInt32Long:
524   case SimpleTypeKind::HResult:
525   case SimpleTypeKind::UInt32:
526     return 4;
527   case SimpleTypeKind::Boolean16:
528   case SimpleTypeKind::Character16:
529   case SimpleTypeKind::Float16:
530   case SimpleTypeKind::Int16:
531   case SimpleTypeKind::Int16Short:
532   case SimpleTypeKind::UInt16:
533   case SimpleTypeKind::UInt16Short:
534   case SimpleTypeKind::WideCharacter:
535     return 2;
536   case SimpleTypeKind::Boolean8:
537   case SimpleTypeKind::Byte:
538   case SimpleTypeKind::UnsignedCharacter:
539   case SimpleTypeKind::NarrowCharacter:
540   case SimpleTypeKind::SignedCharacter:
541   case SimpleTypeKind::SByte:
542     return 1;
543   case SimpleTypeKind::Void:
544   default:
545     return 0;
546   }
547 }
548