LLDB  mainline
PdbUtil.cpp
Go to the documentation of this file.
1 //===-- PdbUtil.cpp ---------------------------------------------*- C++ -*-===//
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 
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 
21 #include "lldb/Symbol/Block.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 
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 
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 
76 CVTagRecord::CVTagRecord(ClassRecord &&c)
77  : cvclass(std::move(c)),
78  m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
79 CVTagRecord::CVTagRecord(UnionRecord &&u)
80  : cvunion(std::move(u)), m_kind(Union) {}
81 CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
82 
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 
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 
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 
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 
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>
216 static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
217  RecordT record = createRecord<RecordT>(sym);
218  return {record.Segment, record.CodeOffset};
219 }
220 
221 template <>
223  TrampolineSym record = createRecord<TrampolineSym>(sym);
224  return {record.ThunkSection, record.ThunkOffset};
225 }
226 
227 template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
228  Thunk32Sym record = createRecord<Thunk32Sym>(sym);
229  return {record.Segment, record.Offset};
230 }
231 
232 template <>
234  CoffGroupSym record = createRecord<CoffGroupSym>(sym);
235  return {record.Segment, record.Offset};
236 }
237 
238 template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
239  DataSym record = createRecord<DataSym>(sym);
240  return {record.Segment, record.DataOffset};
241 }
242 
243 template <>
245  ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
246  return {record.Segment, record.DataOffset};
247 }
248 
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:
260  break;
261  case S_TRAMPOLINE:
263  break;
264  case S_COFFGROUP:
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:
284  break;
285  case S_LTHREAD32:
286  case S_GTHREAD32:
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>
297  RecordT record = createRecord<RecordT>(sym);
298  return {record.Segment, record.CodeOffset, record.CodeSize};
299 }
300 
301 template <>
304  TrampolineSym record = createRecord<TrampolineSym>(sym);
305  return {record.ThunkSection, record.ThunkOffset, record.Size};
306 }
307 
308 template <>
310  Thunk32Sym record = createRecord<Thunk32Sym>(sym);
311  return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
312 }
313 
314 template <>
317  CoffGroupSym record = createRecord<CoffGroupSym>(sym);
318  return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
319 }
320 
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:
333  break;
334  case S_TRAMPOLINE:
336  break;
337  case S_COFFGROUP:
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 
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 
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 
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 
394  TpiStream &tpi) {
395  if (id.is_ipi || id.index.isSimple())
396  return false;
397  return IsForwardRefUdt(tpi.getType(id.index));
398 }
399 
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 
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 
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 
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 
452 llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
454 }
455 
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
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 
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 
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 
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 = &block;
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.Offset, module);
645  result.ranges = std::move(ranges);
646  } else {
647  // invalid variable
648  }
649  } else {
650  result.location =
651  MakeRegRelLocationExpression(base_reg, loc.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)) {
667  program, loc.Hdr.BasePointerOffset, module);
668  result.ranges = std::move(ranges);
669  } else {
670  // invalid variable
671  }
672  } else {
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 
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:
698  case SimpleTypeKind::NarrowCharacter:
699  return lldb::eBasicTypeChar;
700  case SimpleTypeKind::SignedCharacter:
701  case SimpleTypeKind::SByte:
703  case SimpleTypeKind::Character16:
704  return lldb::eBasicTypeChar16;
705  case SimpleTypeKind::Character32:
706  return lldb::eBasicTypeChar32;
707  case SimpleTypeKind::Complex80:
709  case SimpleTypeKind::Complex64:
711  case SimpleTypeKind::Complex32:
713  case SimpleTypeKind::Float128:
714  case SimpleTypeKind::Float80:
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:
727  case SimpleTypeKind::Int32:
728  return lldb::eBasicTypeInt;
729  case SimpleTypeKind::Int16:
730  case SimpleTypeKind::Int16Short:
731  return lldb::eBasicTypeShort;
732  case SimpleTypeKind::UInt128:
734  case SimpleTypeKind::UInt64:
735  case SimpleTypeKind::UInt64Quad:
737  case SimpleTypeKind::HResult:
738  case SimpleTypeKind::UInt32:
740  case SimpleTypeKind::UInt16:
741  case SimpleTypeKind::UInt16Short:
743  case SimpleTypeKind::Int32Long:
744  return lldb::eBasicTypeLong;
745  case SimpleTypeKind::UInt32Long:
747  case SimpleTypeKind::Void:
748  return lldb::eBasicTypeVoid;
749  case SimpleTypeKind::WideCharacter:
750  return lldb::eBasicTypeWChar;
751  default:
753  }
754 }
755 
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 
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 
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 
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 }
bool IsTagRecord(llvm::codeview::CVType cvt)
Definition: PdbUtil.cpp:370
size_t GetSizeOfType(PdbTypeSymId id, llvm::pdb::TpiStream &tpi)
Definition: PdbUtil.cpp:831
SegmentOffsetLength GetSegmentOffsetAndLength(const llvm::codeview::CVSymbol &sym)
llvm::codeview::TypeIndex type
Definition: PdbUtil.h:105
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
SegmentOffsetLength GetSegmentOffsetAndLength< Thunk32Sym >(const CVSymbol &sym)
Definition: PdbUtil.cpp:309
SegmentOffset GetSegmentAndOffset(const llvm::codeview::CVSymbol &sym)
VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id, Block &block, lldb::ModuleSP module)
Definition: PdbUtil.cpp:580
Block * GetParent() const
Get the parent block.
Definition: Block.cpp:192
#define lldbassert(x)
Definition: LLDBAssert.h:15
SegmentOffset GetSegmentAndOffset< TrampolineSym >(const CVSymbol &sym)
Definition: PdbUtil.cpp:222
llvm::Optional< llvm::codeview::Compile3Sym > m_compile_opts
SegmentOffset GetSegmentAndOffset< Thunk32Sym >(const CVSymbol &sym)
Definition: PdbUtil.cpp:227
bool SymbolIsCode(const llvm::codeview::CVSymbol &sym)
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition: UserID.h:49
static llvm::StringRef DropScope(llvm::StringRef name)
lldb::AccessType TranslateMemberAccess(llvm::codeview::MemberAccess access)
Entry & GetEntryRef(size_t i)
Definition: RangeMap.h:483
PdbIndex - Lazy access to the important parts of a PDB file.
Definition: PdbIndex.h:48
A class that describes a single lexical block.
Definition: Block.h:41
llvm::codeview::TypeIndex LookThroughModifierRecord(llvm::codeview::CVType modifier)
bool IsForwardRefUdt(llvm::codeview::CVType cvt)
Range< lldb::addr_t, lldb::addr_t > Entry
Definition: RangeMap.h:336
RecordT createRecord(const CVSymbol &sym)
Definition: PdbUtil.cpp:209
llvm::codeview::CVSymbol ReadSymbolRecord(PdbCompilandSymId cu_sym) const
Definition: PdbIndex.cpp:187
llvm::StringRef DropNameScope(llvm::StringRef name)
Definition: PdbUtil.cpp:452
llvm::Optional< DWARFExpression > location
Definition: PdbUtil.h:106
DWARFExpression MakeEnregisteredLocationExpression(llvm::codeview::RegisterId reg, lldb::ModuleSP module)
SegmentOffsetLength GetSegmentOffsetAndLength< TrampolineSym >(const CVSymbol &sym)
Definition: PdbUtil.cpp:303
llvm::pdb::PDBFile & pdb()
Definition: PdbIndex.h:120
PdbTypeSymId GetBestPossibleDecl(PdbTypeSymId id, llvm::pdb::TpiStream &tpi)
SegmentOffset GetSegmentAndOffset< DataSym >(const CVSymbol &sym)
Definition: PdbUtil.cpp:238
static RegisterId GetBaseFrameRegister(PdbIndex &index, PdbCompilandSymId frame_proc_id, bool is_parameter)
Definition: PdbUtil.cpp:562
lldb::addr_t MakeVirtualAddress(uint16_t segment, uint32_t offset) const
Definition: PdbIndex.cpp:61
llvm::Optional< Variable::RangeList > ranges
Definition: PdbUtil.h:107
bool SymbolHasAddress(const llvm::codeview::CVSymbol &sym)
lldb::BasicType GetCompilerTypeForSimpleKind(llvm::codeview::SimpleTypeKind kind)
static llvm::FixedStreamArray< FrameData >::Iterator GetCorrespondingFrameData(lldb::addr_t load_addr, const DebugFrameDataSubsectionRef &fpo_data, const Variable::RangeList &ranges)
Definition: PdbUtil.cpp:512
DWARFExpression MakeVFrameRelLocationExpression(llvm::StringRef fpo_program, int32_t offset, lldb::ModuleSP module)
SegmentOffsetLength GetSegmentOffsetAndLength< CoffGroupSym >(const CVSymbol &sym)
Definition: PdbUtil.cpp:316
VariableInfo GetVariableNameInfo(llvm::codeview::CVSymbol symbol)
uint64_t addr_t
Definition: lldb-types.h:83
const CompilandIndexItem * GetCompiland(uint16_t modi) const
DWARFExpression MakeRegRelLocationExpression(llvm::codeview::RegisterId reg, int32_t offset, lldb::ModuleSP module)
SegmentOffset GetSegmentAndOffset< CoffGroupSym >(const CVSymbol &sym)
Definition: PdbUtil.cpp:233
bool IsClassStructUnion(llvm::codeview::CVType cvt)
Definition: PdbUtil.cpp:382
bool IsEmpty() const
Definition: RangeMap.h:473
void Append(const Entry &entry)
Definition: RangeMap.h:343
llvm::pdb::DbiStream & dbi()
Definition: PdbIndex.h:123
static size_t GetSizeOfTypeInternal(CVType cvt)
Definition: PdbUtil.cpp:825
lldb::addr_t GetLoadAddress() const
Definition: PdbIndex.h:117
static CVTagRecord create(llvm::codeview::CVType type)
Definition: PdbUtil.cpp:51
CompileUnitIndex & compilands()
Definition: PdbIndex.h:144
llvm::pdb::PDB_SymType CVTypeToPDBType(llvm::codeview::TypeLeafKind kind)
size_t GetTypeSizeForSimpleKind(llvm::codeview::SimpleTypeKind kind)
llvm::codeview::TypeIndex GetFieldListIndex(llvm::codeview::CVType cvt)
static bool GetFrameDataProgram(PdbIndex &index, const Variable::RangeList &ranges, llvm::StringRef &out_program)
Definition: PdbUtil.cpp:546
llvm::pdb::PDB_SymType CVSymToPDBSym(llvm::codeview::SymbolKind kind)
static Variable::RangeList MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range, llvm::ArrayRef< LocalVariableAddrGap > gaps)
Definition: PdbUtil.cpp:31
SegmentOffset GetSegmentAndOffset< ThreadLocalDataSym >(const CVSymbol &sym)
Definition: PdbUtil.cpp:244