[Go to site: main page, start]

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