LLDB mainline
PdbUtil.cpp
Go to the documentation of this file.
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
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
23#include "lldb/Symbol/Block.h"
27
28using namespace lldb_private;
29using namespace lldb_private::npdb;
30using namespace llvm::codeview;
31using namespace llvm::pdb;
32
33// The returned range list is guaranteed to be sorted and no overlaps between
34// adjacent ranges because fields in LocalVariableAddrGap are unsigned integers.
36MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
37 llvm::ArrayRef<LocalVariableAddrGap> gaps) {
38 lldb::addr_t start =
39 index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
40 if (start == LLDB_INVALID_ADDRESS)
41 return {};
42 lldb::addr_t end = start + range.Range;
43
45 while (!gaps.empty()) {
46 const LocalVariableAddrGap &gap = gaps.front();
47 lldb::addr_t gap_start = start + gap.GapStartOffset;
48 result.Append(start, gap_start - start);
49 start = gap_start + gap.Range;
50 gaps = gaps.drop_front();
51 }
52
53 result.Append(start, end - start);
54 return result;
55}
56
57namespace {
58struct MemberLocations {
59 std::map<uint64_t, MemberValLocation> offset_to_location;
60 DWARFExpression expr;
61 bool is_dwarf = false;
62
63 MemberLocations() = default;
64 MemberLocations(const DWARFExpression &expr) : expr(expr), is_dwarf(true) {}
65 MemberLocations(uint64_t offset, const MemberValLocation &member_loc) {
66 insert(offset, member_loc);
67 }
68
69 void insert(uint64_t offset, const MemberValLocation &member_loc) {
70 offset_to_location[offset] = member_loc;
71 }
72
73 struct Comparator {
74 public:
75 bool operator()(const MemberLocations &, const MemberLocations &) const {
76 return false;
77 }
78 };
79};
80
81// A range map with address ranges to a map of pair of offset and locaitons.
82typedef RangeDataVector<lldb::addr_t, lldb::addr_t, MemberLocations, 0,
83 MemberLocations::Comparator>
84 RangeMap;
85
86void AddMemberLocationRanges(RangeMap &location_map, uint64_t offset,
87 MemberValLocation member_loc,
88 const Variable::RangeList &ranges) {
89 RangeMap new_location_map;
90 auto add_overlap_region = [&](lldb::addr_t base, lldb::addr_t end,
91 RangeMap::Entry *entry) {
92 RangeMap::Entry overlap_region = {base, end - base, entry->data};
93 overlap_region.data.insert(offset, member_loc);
94 new_location_map.Append(overlap_region);
95 };
96
97 for (const auto &range : ranges) {
98 lldb::addr_t base = range.GetRangeBase();
99 lldb::addr_t end = range.GetRangeEnd();
100 uint32_t base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
101 while (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
102 if (base >= end || entry->base >= end)
103 break;
104 if (entry->data.is_dwarf)
105 base = entry->GetRangeEnd();
106 else {
107 lldb::addr_t entry_end = entry->GetRangeEnd();
108 if (base > entry->base) {
109 if (end < entry_end)
110 new_location_map.Append({end, entry_end - end, entry->data});
111 add_overlap_region(base, end < entry_end ? end : entry_end, entry);
112 entry->SetRangeEnd(base);
113 } else if (base < entry->base) {
114 new_location_map.Append(
115 {base, entry->base - base, {offset, member_loc}});
116 if (entry_end == end)
117 entry->data.insert(offset, member_loc);
118 else {
119 add_overlap_region(entry->base, end, entry);
120 entry->ShrinkFront(end - entry->base);
121 }
122 } else {
123 if (end < entry_end) {
124 new_location_map.Append({end, entry_end, entry->data});
125 entry->SetRangeEnd(end);
126 }
127 entry->data.insert(offset, member_loc);
128 }
129 base = entry_end;
130 }
131 ++base_idx;
132 }
133 if (base >= end)
134 continue;
135 new_location_map.Append({base, end - base, {offset, member_loc}});
136 }
137 for (const auto &entry : new_location_map)
138 location_map.Append(entry);
139 if (!new_location_map.IsEmpty())
140 location_map.Sort();
141}
142
143void AddDwarfRange(RangeMap &location_map, const DWARFExpression &expr,
144 const Variable::RangeList &ranges) {
145 if (!expr.IsValid())
146 return;
147 RangeMap new_location_map;
148 for (const auto &range : ranges) {
149 lldb::addr_t base = range.GetRangeBase();
150 lldb::addr_t end = range.GetRangeEnd();
151 uint32_t base_idx = location_map.FindEntryIndexThatContains(base);
152 uint32_t end_idx = location_map.FindEntryIndexThatContains(end - 1);
153 // range is within an entry.
154 if (base_idx == end_idx && base_idx != UINT32_MAX) {
155 auto *entry = location_map.GetMutableEntryAtIndex(base_idx);
156 if (base > entry->base) {
157 new_location_map.Append({entry->base, base - entry->base, entry->data});
158 entry->ShrinkFront(base - entry->base);
159 }
160 if (end == entry->GetRangeEnd())
161 entry->data = expr;
162 else {
163 entry->ShrinkFront(end - base);
164 new_location_map.Append({base, end - base, expr});
165 }
166 continue;
167 }
168 base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
169 if (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
170 if (entry->Contains(base) && entry->base != base) {
171 entry->SetRangeEnd(base);
172 ++base_idx;
173 }
174 }
175 end_idx = location_map.FindEntryIndexThatContainsOrFollows(end - 1);
176 if (auto *entry = location_map.GetMutableEntryAtIndex(end_idx)) {
177 if (entry->Contains(end - 1)) {
178 if (entry->GetRangeEnd() == end)
179 ++end_idx;
180 else
181 entry->ShrinkFront(end - entry->base);
182 }
183 }
184
185 if (end_idx == UINT32_MAX)
186 end_idx = location_map.GetSize();
187 // Erase existing ranges covered by new range.
188 location_map.Erase(base_idx, end_idx);
189 new_location_map.Append({base, end - base, expr});
190 }
191
192 for (const auto &entry : new_location_map)
193 location_map.Append(entry);
194 location_map.Sort();
195}
196} // namespace
197
199 assert(IsTagRecord(type) && "type is not a tag record!");
200 switch (type.kind()) {
201 case LF_CLASS:
202 case LF_STRUCTURE:
203 case LF_INTERFACE: {
204 ClassRecord cr;
205 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));
206 return CVTagRecord(std::move(cr));
207 }
208 case LF_UNION: {
209 UnionRecord ur;
210 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));
211 return CVTagRecord(std::move(ur));
212 }
213 case LF_ENUM: {
214 EnumRecord er;
215 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));
216 return CVTagRecord(std::move(er));
217 }
218 default:
219 llvm_unreachable("Unreachable!");
220 }
221}
222
223CVTagRecord::CVTagRecord(ClassRecord &&c)
224 : cvclass(std::move(c)),
225 m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
226CVTagRecord::CVTagRecord(UnionRecord &&u)
227 : cvunion(std::move(u)), m_kind(Union) {}
228CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
229
230PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
231 switch (kind) {
232 case S_COMPILE3:
233 case S_OBJNAME:
234 return PDB_SymType::CompilandDetails;
235 case S_ENVBLOCK:
236 return PDB_SymType::CompilandEnv;
237 case S_THUNK32:
238 case S_TRAMPOLINE:
239 return PDB_SymType::Thunk;
240 case S_COFFGROUP:
241 return PDB_SymType::CoffGroup;
242 case S_EXPORT:
243 return PDB_SymType::Export;
244 case S_LPROC32:
245 case S_GPROC32:
246 case S_LPROC32_DPC:
247 return PDB_SymType::Function;
248 case S_PUB32:
249 return PDB_SymType::PublicSymbol;
250 case S_INLINESITE:
251 return PDB_SymType::InlineSite;
252 case S_LOCAL:
253 case S_BPREL32:
254 case S_REGREL32:
255 case S_REGREL32_INDIR:
256 case S_MANCONSTANT:
257 case S_CONSTANT:
258 case S_LDATA32:
259 case S_GDATA32:
260 case S_LMANDATA:
261 case S_GMANDATA:
262 case S_LTHREAD32:
263 case S_GTHREAD32:
264 return PDB_SymType::Data;
265 case S_BLOCK32:
266 return PDB_SymType::Block;
267 case S_LABEL32:
268 return PDB_SymType::Label;
269 case S_CALLSITEINFO:
270 return PDB_SymType::CallSite;
271 case S_HEAPALLOCSITE:
272 return PDB_SymType::HeapAllocationSite;
273 case S_CALLEES:
274 return PDB_SymType::Callee;
275 case S_CALLERS:
276 return PDB_SymType::Caller;
277 default:
278 lldbassert(false && "Invalid symbol record kind!");
279 }
280 return PDB_SymType::None;
281}
282
283PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
284 switch (kind) {
285 case LF_ARRAY:
286 return PDB_SymType::ArrayType;
287 case LF_ARGLIST:
288 return PDB_SymType::FunctionSig;
289 case LF_BCLASS:
290 return PDB_SymType::BaseClass;
291 case LF_BINTERFACE:
292 return PDB_SymType::BaseInterface;
293 case LF_CLASS:
294 case LF_STRUCTURE:
295 case LF_INTERFACE:
296 case LF_UNION:
297 return PDB_SymType::UDT;
298 case LF_POINTER:
299 return PDB_SymType::PointerType;
300 case LF_ENUM:
301 return PDB_SymType::Enum;
302 case LF_PROCEDURE:
303 return PDB_SymType::FunctionSig;
304 case LF_BITFIELD:
305 return PDB_SymType::BuiltinType;
306 default:
307 lldbassert(false && "Invalid type record kind!");
308 }
309 return PDB_SymType::None;
310}
311
312bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
313 switch (sym.kind()) {
314 case S_GPROC32:
315 case S_LPROC32:
316 case S_GPROC32_ID:
317 case S_LPROC32_ID:
318 case S_LPROC32_DPC:
319 case S_LPROC32_DPC_ID:
320 case S_THUNK32:
321 case S_TRAMPOLINE:
322 case S_COFFGROUP:
323 case S_BLOCK32:
324 case S_LABEL32:
325 case S_CALLSITEINFO:
326 case S_HEAPALLOCSITE:
327 case S_LDATA32:
328 case S_GDATA32:
329 case S_LMANDATA:
330 case S_GMANDATA:
331 case S_LTHREAD32:
332 case S_GTHREAD32:
333 return true;
334 default:
335 return false;
336 }
337}
338
339bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
340 switch (sym.kind()) {
341 case S_GPROC32:
342 case S_LPROC32:
343 case S_GPROC32_ID:
344 case S_LPROC32_ID:
345 case S_LPROC32_DPC:
346 case S_LPROC32_DPC_ID:
347 case S_THUNK32:
348 case S_TRAMPOLINE:
349 case S_COFFGROUP:
350 case S_BLOCK32:
351 return true;
352 default:
353 return false;
354 }
355}
356
357template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
358 RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
359 cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
360 return record;
361}
362
363template <typename RecordT>
364static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
365 RecordT record = createRecord<RecordT>(sym);
366 return {record.Segment, record.CodeOffset};
367}
368
369template <>
371 TrampolineSym record = createRecord<TrampolineSym>(sym);
372 return {record.ThunkSection, record.ThunkOffset};
373}
374
375template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
376 Thunk32Sym record = createRecord<Thunk32Sym>(sym);
377 return {record.Segment, record.Offset};
378}
379
380template <>
382 CoffGroupSym record = createRecord<CoffGroupSym>(sym);
383 return {record.Segment, record.Offset};
384}
385
386template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
387 DataSym record = createRecord<DataSym>(sym);
388 return {record.Segment, record.DataOffset};
389}
390
391template <>
393 ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
394 return {record.Segment, record.DataOffset};
395}
396
398 switch (sym.kind()) {
399 case S_GPROC32:
400 case S_LPROC32:
401 case S_GPROC32_ID:
402 case S_LPROC32_ID:
403 case S_LPROC32_DPC:
404 case S_LPROC32_DPC_ID:
405 return ::GetSegmentAndOffset<ProcSym>(sym);
406 case S_THUNK32:
407 return ::GetSegmentAndOffset<Thunk32Sym>(sym);
408 break;
409 case S_TRAMPOLINE:
410 return ::GetSegmentAndOffset<TrampolineSym>(sym);
411 break;
412 case S_COFFGROUP:
413 return ::GetSegmentAndOffset<CoffGroupSym>(sym);
414 break;
415 case S_BLOCK32:
416 return ::GetSegmentAndOffset<BlockSym>(sym);
417 break;
418 case S_LABEL32:
419 return ::GetSegmentAndOffset<LabelSym>(sym);
420 break;
421 case S_CALLSITEINFO:
422 return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
423 break;
424 case S_HEAPALLOCSITE:
425 return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
426 break;
427 case S_LDATA32:
428 case S_GDATA32:
429 case S_LMANDATA:
430 case S_GMANDATA:
431 return ::GetSegmentAndOffset<DataSym>(sym);
432 break;
433 case S_LTHREAD32:
434 case S_GTHREAD32:
435 return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
436 break;
437 default:
438 lldbassert(false && "Record does not have a segment/offset!");
439 }
440 return {0, 0};
441}
442
443template <typename RecordT>
445 RecordT record = createRecord<RecordT>(sym);
446 return {record.Segment, record.CodeOffset, record.CodeSize};
447}
448
449template <>
451GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
452 TrampolineSym record = createRecord<TrampolineSym>(sym);
453 return {record.ThunkSection, record.ThunkOffset, record.Size};
454}
455
456template <>
458 Thunk32Sym record = createRecord<Thunk32Sym>(sym);
459 return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
460}
461
462template <>
464GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
465 CoffGroupSym record = createRecord<CoffGroupSym>(sym);
466 return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
467}
468
471 switch (sym.kind()) {
472 case S_GPROC32:
473 case S_LPROC32:
474 case S_GPROC32_ID:
475 case S_LPROC32_ID:
476 case S_LPROC32_DPC:
477 case S_LPROC32_DPC_ID:
478 return ::GetSegmentOffsetAndLength<ProcSym>(sym);
479 case S_THUNK32:
480 return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
481 break;
482 case S_TRAMPOLINE:
483 return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
484 break;
485 case S_COFFGROUP:
486 return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
487 break;
488 case S_BLOCK32:
489 return ::GetSegmentOffsetAndLength<BlockSym>(sym);
490 break;
491 default:
492 lldbassert(false && "Record does not have a segment/offset/length triple!");
493 }
494 return {0, 0, 0};
495}
496
498 ClassRecord cr;
499 UnionRecord ur;
500 EnumRecord er;
501 switch (cvt.kind()) {
502 case LF_CLASS:
503 case LF_STRUCTURE:
504 case LF_INTERFACE:
505 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
506 return cr.isForwardRef();
507 case LF_UNION:
508 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
509 return ur.isForwardRef();
510 case LF_ENUM:
511 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
512 return er.isForwardRef();
513 default:
514 return false;
515 }
516}
517
518bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {
519 switch (cvt.kind()) {
520 case LF_CLASS:
521 case LF_STRUCTURE:
522 case LF_UNION:
523 case LF_ENUM:
524 return true;
525 default:
526 return false;
527 }
528}
529
530bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {
531 switch (cvt.kind()) {
532 case LF_CLASS:
533 case LF_STRUCTURE:
534 case LF_UNION:
535 return true;
536 default:
537 return false;
538 }
539}
540
542 TpiStream &tpi) {
543 if (id.is_ipi || id.index.isSimple())
544 return false;
545 return IsForwardRefUdt(tpi.getType(id.index));
546}
547
548bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {
549 if (id.is_ipi || id.index.isSimple())
550 return false;
551 return IsTagRecord(tpi.getType(id.index));
552}
553
556 switch (access) {
557 case MemberAccess::Private:
559 case MemberAccess::Protected:
561 case MemberAccess::Public:
562 return lldb::eAccessPublic;
563 case MemberAccess::None:
564 return lldb::eAccessNone;
565 }
566 llvm_unreachable("unreachable");
567}
568
569TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
570 switch (cvt.kind()) {
571 case LF_CLASS:
572 case LF_STRUCTURE:
573 case LF_INTERFACE: {
574 ClassRecord cr;
575 cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
576 return cr.FieldList;
577 }
578 case LF_UNION: {
579 UnionRecord ur;
580 cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
581 return ur.FieldList;
582 }
583 case LF_ENUM: {
584 EnumRecord er;
585 cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
586 return er.FieldList;
587 }
588 default:
589 llvm_unreachable("Unreachable!");
590 }
591}
592
593TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
594 lldbassert(modifier.kind() == LF_MODIFIER);
595 ModifierRecord mr;
596 llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
597 return mr.ModifiedType;
598}
599
600llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
602}
603
605 VariableInfo result = {};
606
607 if (sym.kind() == S_REGREL32) {
608 RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
609 cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
610 result.type = reg.Type;
611 result.name = reg.Name;
612 return result;
613 }
614
615 if (sym.kind() == S_REGREL32_INDIR) {
616 RegRelativeIndirSym reg(SymbolRecordKind::RegRelativeIndirSym);
617 cantFail(SymbolDeserializer::deserializeAs<RegRelativeIndirSym>(sym, reg));
618 result.type = reg.Type;
619 result.name = reg.Name;
620 return result;
621 }
622
623 if (sym.kind() == S_REGISTER) {
624 RegisterSym reg(SymbolRecordKind::RegisterSym);
625 cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
626 result.type = reg.Index;
627 result.name = reg.Name;
628 return result;
629 }
630
631 if (sym.kind() == S_LOCAL) {
632 LocalSym local(SymbolRecordKind::LocalSym);
633 cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
634 result.type = local.Type;
635 result.name = local.Name;
636 result.is_param =
637 ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);
638 return result;
639 }
640
641 if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {
642 DataSym data(SymbolRecordKind::DataSym);
643 cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data));
644 result.type = data.Type;
645 result.name = data.Name;
646 return result;
647 }
648
649 if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {
650 ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);
651 cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data));
652 result.type = data.Type;
653 result.name = data.Name;
654 return result;
655 }
656
657 if (sym.kind() == S_CONSTANT) {
658 ConstantSym constant(SymbolRecordKind::ConstantSym);
659 cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));
660 result.type = constant.Type;
661 result.name = constant.Name;
662 return result;
663 }
664
665 lldbassert(false && "Invalid variable record kind!");
666 return {};
667}
668
669static llvm::FixedStreamArray<FrameData>::Iterator
671 const DebugFrameDataSubsectionRef &fpo_data,
672 const Variable::RangeList &ranges) {
673 lldbassert(!ranges.IsEmpty());
674
675 // assume that all variable ranges correspond to one frame data
676 using RangeListEntry = Variable::RangeList::Entry;
677 const RangeListEntry &range = ranges.GetEntryRef(0);
678
679 auto it = fpo_data.begin();
680
681 // start by searching first frame data range containing variable range
682 for (; it != fpo_data.end(); ++it) {
683 RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
684
685 if (fd_range.Contains(range)) {
686 break;
687 }
688 }
689
690 // then first most nested entry that still contains variable range
691 auto found = it;
692 for (; it != fpo_data.end(); ++it) {
693 RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
694
695 if (!fd_range.Contains(range)) {
696 break;
697 }
698 found = it;
699 }
700
701 return found;
702}
703
704static bool GetFrameDataProgram(PdbIndex &index,
705 const Variable::RangeList &ranges,
706 llvm::StringRef &out_program) {
707 const DebugFrameDataSubsectionRef &new_fpo_data =
708 index.dbi().getNewFpoRecords();
709
710 auto frame_data_it =
711 GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges);
712 if (frame_data_it == new_fpo_data.end())
713 return false;
714
715 auto strings = index.pdb().getStringTable();
716 if (!strings) {
717 consumeError(strings.takeError());
718 return false;
719 }
720 out_program = cantFail(strings->getStringForID(frame_data_it->FrameFunc));
721 return true;
722}
723
724static RegisterId GetBaseFrameRegister(PdbIndex &index,
725 PdbCompilandSymId frame_proc_id,
726 bool is_parameter) {
727 CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);
728 if (frame_proc_cvs.kind() != S_FRAMEPROC)
729 return RegisterId::NONE;
730
731 FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);
732 cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,
733 frame_proc));
734
735 CPUType cpu_type = index.compilands()
736 .GetCompiland(frame_proc_id.modi)
737 ->m_compile_opts->Machine;
738
739 return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type)
740 : frame_proc.getLocalFramePtrReg(cpu_type);
741}
742
744 PdbIndex &index, PdbCompilandSymId var_id, Block &func_block,
745 lldb::ModuleSP module) {
746
747 CVSymbol sym = index.ReadSymbolRecord(var_id);
748
749 VariableInfo result = GetVariableNameInfo(sym);
750
751 if (sym.kind() == S_REGREL32) {
752 RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
753 cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
755 module, MakeRegRelLocationExpression(reg.Register, reg.Offset, module),
756 nullptr);
757 return result;
758 }
759
760 if (sym.kind() == S_REGREL32_INDIR) {
761 RegRelativeIndirSym reg(SymbolRecordKind::RegRelativeIndirSym);
762 cantFail(SymbolDeserializer::deserializeAs<RegRelativeIndirSym>(sym, reg));
764 module,
765 MakeRegRelIndirLocationExpression(reg.Register, reg.Offset,
766 reg.OffsetInUdt, module),
767 nullptr);
768 return result;
769 }
770
771 if (sym.kind() == S_REGISTER) {
772 RegisterSym reg(SymbolRecordKind::RegisterSym);
773 cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
775 module, MakeEnregisteredLocationExpression(reg.Register, module),
776 nullptr);
777 return result;
778 }
779
780 if (sym.kind() == S_LOCAL) {
781 LocalSym local(SymbolRecordKind::LocalSym);
782 if (llvm::Error error =
783 SymbolDeserializer::deserializeAs<LocalSym>(sym, local)) {
784 llvm::consumeError(std::move(error));
785 return result;
786 }
787
788 PdbCompilandSymId loc_specifier_id(var_id.modi,
789 var_id.offset + sym.RecordData.size());
790 CVSymbol loc_specifier_cvs;
791 // Only used for S_DEFRANGE_FRAMEPOINTER_REL.
792 RegisterId base_reg = RegisterId::NONE;
793 size_t type_size = GetSizeOfType(result.type, index.tpi());
794 // A map from offset of a field in parent to size of the field.
795 std::map<uint64_t, size_t> offset_to_size;
796
797 // When overlaps happens, always prefer the one that doesn't split the value
798 // into multiple locations and the location parsed first is perfered.
799 RangeMap location_map;
800
801 // Iterate through all location records after S_LOCAL. They describe the
802 // value of this variable at different locations.
803 bool finished = false;
804 while (!finished) {
805 loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
806 switch (loc_specifier_cvs.kind()) {
807 case S_DEFRANGE_FRAMEPOINTER_REL: {
808 DefRangeFramePointerRelSym loc(
809 SymbolRecordKind::DefRangeFramePointerRelSym);
810 if (llvm::Error error =
811 SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
812 loc_specifier_cvs, loc)) {
813 llvm::consumeError(std::move(error));
814 return result;
815 }
816 Variable::RangeList raw_ranges =
817 MakeRangeList(index, loc.Range, loc.Gaps);
818 if (base_reg == RegisterId::NONE) {
819 PdbCompilandSymId func_scope_id =
820 PdbSymUid(func_block.GetID()).asCompilandSym();
821 CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
822 lldbassert(func_block_cvs.kind() == S_GPROC32 ||
823 func_block_cvs.kind() == S_LPROC32);
824 PdbCompilandSymId frame_proc_id(func_scope_id.modi,
825 func_scope_id.offset +
826 func_block_cvs.length());
827 base_reg =
828 GetBaseFrameRegister(index, frame_proc_id, result.is_param);
829 if (base_reg == RegisterId::NONE)
830 break;
831 }
832 DWARFExpression expr;
833 if (base_reg == RegisterId::VFRAME) {
834 llvm::StringRef program;
835 if (GetFrameDataProgram(index, raw_ranges, program))
836 expr = MakeVFrameRelLocationExpression(program, loc.Hdr.Offset,
837 module);
838 else {
839 // invalid variable
840 }
841 } else
842 expr = MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
843 AddDwarfRange(location_map, expr, raw_ranges);
844 break;
845 }
846 case S_DEFRANGE_REGISTER: {
847 DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);
848 if (llvm::Error error =
849 SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(
850 loc_specifier_cvs, loc)) {
851 llvm::consumeError(std::move(error));
852 return result;
853 }
854 RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
855 Variable::RangeList raw_ranges =
856 MakeRangeList(index, loc.Range, loc.Gaps);
857 DWARFExpression expr =
859 AddDwarfRange(location_map, expr, raw_ranges);
860 break;
861 }
862 case S_DEFRANGE_REGISTER_REL: {
863 DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
864 if (llvm::Error error =
865 SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
866 loc_specifier_cvs, loc)) {
867 llvm::consumeError(std::move(error));
868 return result;
869 }
870 Variable::RangeList raw_ranges =
871 MakeRangeList(index, loc.Range, loc.Gaps);
872 RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
873 DWARFExpression expr;
874 if (reg_id == RegisterId::VFRAME) {
875 llvm::StringRef program;
876 if (GetFrameDataProgram(index, raw_ranges, program))
878 program, loc.Hdr.BasePointerOffset, module);
879 else {
880 // invalid variable
881 }
882 } else {
883 expr = MakeRegRelLocationExpression(reg_id, loc.Hdr.BasePointerOffset,
884 module);
885 }
886 // FIXME: If it's UDT, we need to know the size of the value in byte.
887 if (!loc.hasSpilledUDTMember())
888 AddDwarfRange(location_map, expr, raw_ranges);
889 break;
890 }
891 case S_DEFRANGE_SUBFIELD_REGISTER: {
892 DefRangeSubfieldRegisterSym loc(
893 SymbolRecordKind::DefRangeSubfieldRegisterSym);
894 if (llvm::Error error =
895 SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(
896 loc_specifier_cvs, loc)) {
897 llvm::consumeError(std::move(error));
898 return result;
899 }
900
901 Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
902 uint32_t reg_size =
903 GetRegisterSize((RegisterId)(uint16_t)loc.Hdr.Register);
904 if (reg_size == 0)
905 break;
906 offset_to_size[loc.Hdr.OffsetInParent] = reg_size;
907 AddMemberLocationRanges(location_map, loc.Hdr.OffsetInParent,
908 {loc.Hdr.Register, 0, true}, ranges);
909 break;
910 }
911 // FIXME: Handle other kinds. LLVM only generates the 4 types of records
912 // above. MSVC generates other location types.
913 case S_DEFRANGE:
914 case S_DEFRANGE_SUBFIELD:
915 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
916 break;
917 default:
918 finished = true;
919 break;
920 }
921 loc_specifier_id = PdbCompilandSymId(
922 loc_specifier_id.modi,
923 loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());
924 }
925 for (const auto &entry : location_map) {
926 DWARFExpression dwarf_expr =
927 entry.data.is_dwarf ? entry.data.expr
929 entry.data.offset_to_location,
930 offset_to_size, type_size, module);
931
932 result.location.AddExpression(entry.GetRangeBase(), entry.GetRangeEnd(),
933 dwarf_expr);
934 }
935 return result;
936 }
937 llvm_unreachable("Symbol is not a local variable!");
938 return result;
939}
940
943 switch (kind) {
944 case SimpleTypeKind::Boolean128:
945 case SimpleTypeKind::Boolean16:
946 case SimpleTypeKind::Boolean32:
947 case SimpleTypeKind::Boolean64:
948 case SimpleTypeKind::Boolean8:
950 case SimpleTypeKind::Byte:
951 case SimpleTypeKind::UnsignedCharacter:
953 case SimpleTypeKind::NarrowCharacter:
955 case SimpleTypeKind::SignedCharacter:
956 case SimpleTypeKind::SByte:
958 case SimpleTypeKind::Character16:
960 case SimpleTypeKind::Character32:
962 case SimpleTypeKind::Character8:
964 case SimpleTypeKind::Complex80:
966 case SimpleTypeKind::Complex64:
968 case SimpleTypeKind::Complex32:
969 case SimpleTypeKind::Complex32PartialPrecision:
971 case SimpleTypeKind::Float80:
973 case SimpleTypeKind::Float128:
975 case SimpleTypeKind::Float64:
977 case SimpleTypeKind::Float32:
978 case SimpleTypeKind::Float32PartialPrecision:
980 case SimpleTypeKind::Float16:
982 case SimpleTypeKind::Int128:
983 case SimpleTypeKind::Int128Oct:
985 case SimpleTypeKind::Int64:
986 case SimpleTypeKind::Int64Quad:
988 case SimpleTypeKind::Int32:
989 return lldb::eBasicTypeInt;
990 case SimpleTypeKind::Int16:
991 case SimpleTypeKind::Int16Short:
993 case SimpleTypeKind::UInt128:
994 case SimpleTypeKind::UInt128Oct:
996 case SimpleTypeKind::UInt64:
997 case SimpleTypeKind::UInt64Quad:
999 case SimpleTypeKind::HResult:
1000 case SimpleTypeKind::UInt32:
1002 case SimpleTypeKind::UInt16:
1003 case SimpleTypeKind::UInt16Short:
1005 case SimpleTypeKind::Int32Long:
1006 return lldb::eBasicTypeLong;
1007 case SimpleTypeKind::UInt32Long:
1009 case SimpleTypeKind::Void:
1010 return lldb::eBasicTypeVoid;
1011 case SimpleTypeKind::WideCharacter:
1012 return lldb::eBasicTypeWChar;
1013
1014 // Not supported.
1015 case SimpleTypeKind::Float48:
1016 case SimpleTypeKind::Complex16:
1017 case SimpleTypeKind::Complex48:
1018 case SimpleTypeKind::Complex128:
1019 case SimpleTypeKind::NotTranslated:
1020 case SimpleTypeKind::None:
1022 }
1024}
1025
1026size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {
1027 switch (kind) {
1028 case SimpleTypeKind::Boolean128:
1029 case SimpleTypeKind::Complex128:
1030 case SimpleTypeKind::Int128:
1031 case SimpleTypeKind::Int128Oct:
1032 case SimpleTypeKind::UInt128:
1033 case SimpleTypeKind::UInt128Oct:
1034 case SimpleTypeKind::Float128:
1035 return 16;
1036 case SimpleTypeKind::Complex80:
1037 case SimpleTypeKind::Float80:
1038 return 10;
1039 case SimpleTypeKind::Boolean64:
1040 case SimpleTypeKind::Complex64:
1041 case SimpleTypeKind::UInt64:
1042 case SimpleTypeKind::UInt64Quad:
1043 case SimpleTypeKind::Float64:
1044 case SimpleTypeKind::Int64:
1045 case SimpleTypeKind::Int64Quad:
1046 return 8;
1047 case SimpleTypeKind::Complex48:
1048 case SimpleTypeKind::Float48:
1049 return 6;
1050 case SimpleTypeKind::Boolean32:
1051 case SimpleTypeKind::Character32:
1052 case SimpleTypeKind::Complex32:
1053 case SimpleTypeKind::Complex32PartialPrecision:
1054 case SimpleTypeKind::Float32:
1055 case SimpleTypeKind::Float32PartialPrecision:
1056 case SimpleTypeKind::Int32:
1057 case SimpleTypeKind::Int32Long:
1058 case SimpleTypeKind::UInt32Long:
1059 case SimpleTypeKind::HResult:
1060 case SimpleTypeKind::UInt32:
1061 return 4;
1062 case SimpleTypeKind::Boolean16:
1063 case SimpleTypeKind::Character16:
1064 case SimpleTypeKind::Complex16:
1065 case SimpleTypeKind::Float16:
1066 case SimpleTypeKind::Int16:
1067 case SimpleTypeKind::Int16Short:
1068 case SimpleTypeKind::UInt16:
1069 case SimpleTypeKind::UInt16Short:
1070 case SimpleTypeKind::WideCharacter:
1071 return 2;
1072 case SimpleTypeKind::Boolean8:
1073 case SimpleTypeKind::Byte:
1074 case SimpleTypeKind::UnsignedCharacter:
1075 case SimpleTypeKind::NarrowCharacter:
1076 case SimpleTypeKind::SignedCharacter:
1077 case SimpleTypeKind::SByte:
1078 case SimpleTypeKind::Character8:
1079 return 1;
1080
1081 case SimpleTypeKind::Void:
1082 case SimpleTypeKind::None:
1083 case SimpleTypeKind::NotTranslated:
1084 return 0;
1085 }
1086 return 0;
1087}
1088
1090 TpiStream &tpi) {
1091 if (id.index.isSimple())
1092 return id;
1093
1094 CVType cvt = tpi.getType(id.index);
1095
1096 // Only tag records have a best and a worst record.
1097 if (!IsTagRecord(cvt))
1098 return id;
1099
1100 // Tag records that are not forward decls are full decls, hence they are the
1101 // best.
1102 if (!IsForwardRefUdt(cvt))
1103 return id;
1104
1105 return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));
1106}
1107
1108template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {
1109 RecordType record;
1110 llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));
1111 return record.getSize();
1112}
1113
1115 llvm::pdb::TpiStream &tpi) {
1116 if (id.index.isSimple()) {
1117 switch (id.index.getSimpleMode()) {
1118 case SimpleTypeMode::Direct:
1119 return GetTypeSizeForSimpleKind(id.index.getSimpleKind());
1120 case SimpleTypeMode::NearPointer32:
1121 case SimpleTypeMode::FarPointer32:
1122 return 4;
1123 case SimpleTypeMode::NearPointer64:
1124 return 8;
1125 case SimpleTypeMode::NearPointer128:
1126 return 16;
1127 default:
1128 break;
1129 }
1130 return 0;
1131 }
1132
1133 TypeIndex index = id.index;
1134 if (IsForwardRefUdt(index, tpi))
1135 index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));
1136
1137 CVType cvt = tpi.getType(index);
1138 switch (cvt.kind()) {
1139 case LF_MODIFIER:
1140 return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);
1141 case LF_ENUM: {
1142 EnumRecord record;
1143 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));
1144 return GetSizeOfType({record.UnderlyingType}, tpi);
1145 }
1146 case LF_POINTER:
1148 case LF_ARRAY:
1150 case LF_CLASS:
1151 case LF_STRUCTURE:
1152 case LF_INTERFACE:
1154 case LF_UNION:
1156 case LF_BITFIELD: {
1157 BitFieldRecord record;
1158 llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, record));
1159 return GetSizeOfType({record.Type}, tpi);
1160 }
1161 default:
1162 break;
1163 }
1164 return 0;
1165}
static const size_t reg_size
static llvm::raw_ostream & error(Stream &strm)
#define lldbassert(x)
Definition LLDBAssert.h:16
SegmentOffsetLength GetSegmentOffsetAndLength< CoffGroupSym >(const CVSymbol &sym)
Definition PdbUtil.cpp:464
static llvm::FixedStreamArray< FrameData >::Iterator GetCorrespondingFrameData(lldb::addr_t load_addr, const DebugFrameDataSubsectionRef &fpo_data, const Variable::RangeList &ranges)
Definition PdbUtil.cpp:670
SegmentOffset GetSegmentAndOffset< TrampolineSym >(const CVSymbol &sym)
Definition PdbUtil.cpp:370
SegmentOffset GetSegmentAndOffset< CoffGroupSym >(const CVSymbol &sym)
Definition PdbUtil.cpp:381
SegmentOffset GetSegmentAndOffset< Thunk32Sym >(const CVSymbol &sym)
Definition PdbUtil.cpp:375
SegmentOffset GetSegmentAndOffset< DataSym >(const CVSymbol &sym)
Definition PdbUtil.cpp:386
static size_t GetSizeOfTypeInternal(CVType cvt)
Definition PdbUtil.cpp:1108
SegmentOffsetLength GetSegmentOffsetAndLength< TrampolineSym >(const CVSymbol &sym)
Definition PdbUtil.cpp:451
RecordT createRecord(const CVSymbol &sym)
Definition PdbUtil.cpp:357
SegmentOffset GetSegmentAndOffset< ThreadLocalDataSym >(const CVSymbol &sym)
Definition PdbUtil.cpp:392
static bool GetFrameDataProgram(PdbIndex &index, const Variable::RangeList &ranges, llvm::StringRef &out_program)
Definition PdbUtil.cpp:704
SegmentOffsetLength GetSegmentOffsetAndLength< Thunk32Sym >(const CVSymbol &sym)
Definition PdbUtil.cpp:457
static Variable::RangeList MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range, llvm::ArrayRef< LocalVariableAddrGap > gaps)
Definition PdbUtil.cpp:36
static RegisterId GetBaseFrameRegister(PdbIndex &index, PdbCompilandSymId frame_proc_id, bool is_parameter)
Definition PdbUtil.cpp:724
static llvm::StringRef DropScope(llvm::StringRef name)
A class that describes a single lexical block.
Definition Block.h:41
"lldb/Expression/DWARFExpressionList.h" Encapsulates a range map from file address range to a single ...
bool AddExpression(lldb::addr_t base, lldb::addr_t end, DWARFExpression expr)
"lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location expression and interprets it.
bool IsValid() const
Return true if the location expression contains data.
Entry & GetEntryRef(size_t i)
Definition RangeMap.h:303
void Append(const Entry &entry)
Definition RangeMap.h:179
Range< lldb::addr_t, lldb::addr_t > Entry
Definition RangeMap.h:140
RangeVector< lldb::addr_t, lldb::addr_t > RangeList
Definition Variable.h:27
const CompilandIndexItem * GetCompiland(uint16_t modi) const
PdbIndex - Lazy access to the important parts of a PDB file.
Definition PdbIndex.h:47
CompileUnitIndex & compilands()
Definition PdbIndex.h:142
llvm::pdb::DbiStream & dbi()
Definition PdbIndex.h:121
llvm::codeview::CVSymbol ReadSymbolRecord(PdbCompilandSymId cu_sym) const
Definition PdbIndex.cpp:187
lldb::addr_t GetLoadAddress() const
Definition PdbIndex.h:115
llvm::pdb::PDBFile & pdb()
Definition PdbIndex.h:118
lldb::addr_t MakeVirtualAddress(uint16_t segment, uint32_t offset) const
Definition PdbIndex.cpp:62
llvm::pdb::TpiStream & tpi()
Definition PdbIndex.h:124
PdbCompilandSymId asCompilandSym() const
#define LLDB_INVALID_ADDRESS
#define UINT32_MAX
bool SymbolHasAddress(const llvm::codeview::CVSymbol &sym)
DWARFExpression MakeRegRelIndirLocationExpression(llvm::codeview::RegisterId reg, int32_t offset, int32_t offset_in_udt, lldb::ModuleSP module)
llvm::StringRef DropNameScope(llvm::StringRef name)
Definition PdbUtil.cpp:600
DWARFExpression MakeRegRelLocationExpression(llvm::codeview::RegisterId reg, int32_t offset, lldb::ModuleSP module)
llvm::pdb::PDB_SymType CVTypeToPDBType(llvm::codeview::TypeLeafKind kind)
size_t GetTypeSizeForSimpleKind(llvm::codeview::SimpleTypeKind kind)
DWARFExpression MakeVFrameRelLocationExpression(llvm::StringRef fpo_program, int32_t offset, lldb::ModuleSP module)
SegmentOffset GetSegmentAndOffset(const llvm::codeview::CVSymbol &sym)
lldb::BasicType GetCompilerTypeForSimpleKind(llvm::codeview::SimpleTypeKind kind)
VariableInfo GetVariableNameInfo(llvm::codeview::CVSymbol symbol)
SegmentOffsetLength GetSegmentOffsetAndLength(const llvm::codeview::CVSymbol &sym)
bool IsTagRecord(llvm::codeview::CVType cvt)
Definition PdbUtil.cpp:518
llvm::codeview::TypeIndex LookThroughModifierRecord(llvm::codeview::CVType modifier)
DWARFExpression MakeEnregisteredLocationExpressionForComposite(const std::map< uint64_t, MemberValLocation > &offset_to_location, std::map< uint64_t, size_t > &offset_to_size, size_t total_size, lldb::ModuleSP module)
VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id, Block &func_block, lldb::ModuleSP module)
Definition PdbUtil.cpp:743
bool IsForwardRefUdt(llvm::codeview::CVType cvt)
lldb::AccessType TranslateMemberAccess(llvm::codeview::MemberAccess access)
llvm::codeview::TypeIndex GetFieldListIndex(llvm::codeview::CVType cvt)
DWARFExpression MakeEnregisteredLocationExpression(llvm::codeview::RegisterId reg, lldb::ModuleSP module)
llvm::pdb::PDB_SymType CVSymToPDBSym(llvm::codeview::SymbolKind kind)
size_t GetSizeOfType(PdbTypeSymId id, llvm::pdb::TpiStream &tpi)
Definition PdbUtil.cpp:1114
uint32_t GetRegisterSize(llvm::codeview::RegisterId register_id)
PdbTypeSymId GetBestPossibleDecl(PdbTypeSymId id, llvm::pdb::TpiStream &tpi)
bool IsClassStructUnion(llvm::codeview::CVType cvt)
Definition PdbUtil.cpp:530
bool SymbolIsCode(const llvm::codeview::CVSymbol &sym)
A class that represents a running process on the host machine.
BasicType
Basic types enumeration for the public API SBType::GetBasicType().
@ eBasicTypeUnsignedShort
@ eBasicTypeSignedChar
@ eBasicTypeUnsignedInt128
@ eBasicTypeFloatComplex
@ eBasicTypeUnsignedLong
@ eBasicTypeLongDoubleComplex
@ eBasicTypeUnsignedChar
@ eBasicTypeUnsignedLongLong
@ eBasicTypeDoubleComplex
@ eBasicTypeLongDouble
@ eBasicTypeUnsignedInt
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::Module > ModuleSP
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition UserID.h:47
static CVTagRecord create(llvm::codeview::CVType type)
Definition PdbUtil.cpp:198
CVTagRecord(llvm::codeview::ClassRecord &&c)
std::optional< llvm::codeview::Compile3Sym > m_compile_opts
DWARFExpressionList location
Definition PdbUtil.h:115
llvm::codeview::TypeIndex type
Definition PdbUtil.h:114