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
11#include "DWARFLocationExpression.h"
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
21#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
22#include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h"
23#include "lldb/Symbol/Block.h"
24#include "lldb/Utility/LLDBAssert.h"
25#include "lldb/Utility/LLDBLog.h"
26#include "lldb/lldb-enumerations.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.
35static Variable::RangeList
36MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
37 llvm::ArrayRef<LocalVariableAddrGap> gaps) {
38 lldb::addr_t start =
39 index.MakeVirtualAddress(segment: range.ISectStart, offset: range.OffsetStart);
40 if (start == LLDB_INVALID_ADDRESS)
41 return {};
42 lldb::addr_t end = start + range.Range;
43
44 Variable::RangeList result;
45 while (!gaps.empty()) {
46 const LocalVariableAddrGap &gap = gaps.front();
47 lldb::addr_t gap_start = start + gap.GapStartOffset;
48 result.Append(base: start, size: gap_start - start);
49 start = gap_start + gap.Range;
50 gaps = gaps.drop_front();
51 }
52
53 result.Append(base: start, size: 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(entry: 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(addr: base);
101 while (auto *entry = location_map.GetMutableEntryAtIndex(i: 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(entry: {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 entry: {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(s: end - entry->base);
121 }
122 } else {
123 if (end < entry_end) {
124 new_location_map.Append(entry: {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(entry: {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(addr: base);
152 uint32_t end_idx = location_map.FindEntryIndexThatContains(addr: end - 1);
153 // range is within an entry.
154 if (base_idx == end_idx && base_idx != UINT32_MAX) {
155 auto *entry = location_map.GetMutableEntryAtIndex(i: base_idx);
156 if (base > entry->base) {
157 new_location_map.Append(entry: {entry->base, base - entry->base, entry->data});
158 entry->ShrinkFront(s: base - entry->base);
159 }
160 if (end == entry->GetRangeEnd())
161 entry->data = expr;
162 else {
163 entry->ShrinkFront(s: end - base);
164 new_location_map.Append(entry: {base, end - base, expr});
165 }
166 continue;
167 }
168 base_idx = location_map.FindEntryIndexThatContainsOrFollows(addr: base);
169 if (auto *entry = location_map.GetMutableEntryAtIndex(i: base_idx)) {
170 if (entry->Contains(r: base) && entry->base != base) {
171 entry->SetRangeEnd(base);
172 ++base_idx;
173 }
174 }
175 end_idx = location_map.FindEntryIndexThatContainsOrFollows(addr: end - 1);
176 if (auto *entry = location_map.GetMutableEntryAtIndex(i: end_idx)) {
177 if (entry->Contains(r: end - 1)) {
178 if (entry->GetRangeEnd() == end)
179 ++end_idx;
180 else
181 entry->ShrinkFront(s: 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(start: base_idx, end: end_idx);
189 new_location_map.Append(entry: {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
198CVTagRecord CVTagRecord::create(CVType type) {
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(Err: TypeDeserializer::deserializeAs<ClassRecord>(CVT&: type, Record&: cr));
206 return CVTagRecord(std::move(cr));
207 }
208 case LF_UNION: {
209 UnionRecord ur;
210 llvm::cantFail(Err: TypeDeserializer::deserializeAs<UnionRecord>(CVT&: type, Record&: ur));
211 return CVTagRecord(std::move(ur));
212 }
213 case LF_ENUM: {
214 EnumRecord er;
215 llvm::cantFail(Err: TypeDeserializer::deserializeAs<EnumRecord>(CVT&: type, Record&: 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_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 lldbassert(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 lldbassert(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 <>
369SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
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 <>
380SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
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 <>
391SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
392 ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
393 return {record.Segment, record.DataOffset};
394}
395
396SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
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 lldbassert(false && "Record does not have a segment/offset!");
438 }
439 return {0, 0};
440}
441
442template <typename RecordT>
443SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
444 RecordT record = createRecord<RecordT>(sym);
445 return {record.Segment, record.CodeOffset, record.CodeSize};
446}
447
448template <>
449SegmentOffsetLength
450GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
451 TrampolineSym record = createRecord<TrampolineSym>(sym);
452 return {record.ThunkSection, record.ThunkOffset, record.Size};
453}
454
455template <>
456SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
457 Thunk32Sym record = createRecord<Thunk32Sym>(sym);
458 return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
459}
460
461template <>
462SegmentOffsetLength
463GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
464 CoffGroupSym record = createRecord<CoffGroupSym>(sym);
465 return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
466}
467
468SegmentOffsetLength
469lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
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 lldbassert(false && "Record does not have a segment/offset/length triple!");
492 }
493 return {0, 0, 0};
494}
495
496bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
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(Err: TypeDeserializer::deserializeAs<ClassRecord>(CVT&: cvt, Record&: cr));
505 return cr.isForwardRef();
506 case LF_UNION:
507 llvm::cantFail(Err: TypeDeserializer::deserializeAs<UnionRecord>(CVT&: cvt, Record&: ur));
508 return ur.isForwardRef();
509 case LF_ENUM:
510 llvm::cantFail(Err: TypeDeserializer::deserializeAs<EnumRecord>(CVT&: cvt, Record&: 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
540bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
541 TpiStream &tpi) {
542 if (id.is_ipi || id.index.isSimple())
543 return false;
544 return IsForwardRefUdt(cvt: tpi.getType(Index: 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(cvt: tpi.getType(Index: id.index));
551}
552
553lldb::AccessType
554lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
555 switch (access) {
556 case MemberAccess::Private:
557 return lldb::eAccessPrivate;
558 case MemberAccess::Protected:
559 return lldb::eAccessProtected;
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(Err: TypeDeserializer::deserializeAs<ClassRecord>(CVT&: cvt, Record&: cr));
575 return cr.FieldList;
576 }
577 case LF_UNION: {
578 UnionRecord ur;
579 cantFail(Err: TypeDeserializer::deserializeAs<UnionRecord>(CVT&: cvt, Record&: ur));
580 return ur.FieldList;
581 }
582 case LF_ENUM: {
583 EnumRecord er;
584 cantFail(Err: TypeDeserializer::deserializeAs<EnumRecord>(CVT&: cvt, Record&: er));
585 return er.FieldList;
586 }
587 default:
588 llvm_unreachable("Unreachable!");
589 }
590}
591
592TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
593 lldbassert(modifier.kind() == LF_MODIFIER);
594 ModifierRecord mr;
595 llvm::cantFail(Err: TypeDeserializer::deserializeAs<ModifierRecord>(CVT&: modifier, Record&: mr));
596 return mr.ModifiedType;
597}
598
599llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
600 return MSVCUndecoratedNameParser::DropScope(name);
601}
602
603VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
604 VariableInfo result = {};
605
606 if (sym.kind() == S_REGREL32) {
607 RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
608 cantFail(Err: SymbolDeserializer::deserializeAs<RegRelativeSym>(Symbol: sym, Record&: reg));
609 result.type = reg.Type;
610 result.name = reg.Name;
611 return result;
612 }
613
614 if (sym.kind() == S_REGISTER) {
615 RegisterSym reg(SymbolRecordKind::RegisterSym);
616 cantFail(Err: SymbolDeserializer::deserializeAs<RegisterSym>(Symbol: sym, Record&: reg));
617 result.type = reg.Index;
618 result.name = reg.Name;
619 return result;
620 }
621
622 if (sym.kind() == S_LOCAL) {
623 LocalSym local(SymbolRecordKind::LocalSym);
624 cantFail(Err: SymbolDeserializer::deserializeAs<LocalSym>(Symbol: sym, Record&: local));
625 result.type = local.Type;
626 result.name = local.Name;
627 result.is_param =
628 ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);
629 return result;
630 }
631
632 if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {
633 DataSym data(SymbolRecordKind::DataSym);
634 cantFail(Err: SymbolDeserializer::deserializeAs<DataSym>(Symbol: sym, Record&: data));
635 result.type = data.Type;
636 result.name = data.Name;
637 return result;
638 }
639
640 if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {
641 ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);
642 cantFail(Err: SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(Symbol: sym, Record&: data));
643 result.type = data.Type;
644 result.name = data.Name;
645 return result;
646 }
647
648 if (sym.kind() == S_CONSTANT) {
649 ConstantSym constant(SymbolRecordKind::ConstantSym);
650 cantFail(Err: SymbolDeserializer::deserializeAs<ConstantSym>(Symbol: sym, Record&: constant));
651 result.type = constant.Type;
652 result.name = constant.Name;
653 return result;
654 }
655
656 lldbassert(false && "Invalid variable record kind!");
657 return {};
658}
659
660static llvm::FixedStreamArray<FrameData>::Iterator
661GetCorrespondingFrameData(lldb::addr_t load_addr,
662 const DebugFrameDataSubsectionRef &fpo_data,
663 const Variable::RangeList &ranges) {
664 lldbassert(!ranges.IsEmpty());
665
666 // assume that all variable ranges correspond to one frame data
667 using RangeListEntry = Variable::RangeList::Entry;
668 const RangeListEntry &range = ranges.GetEntryRef(i: 0);
669
670 auto it = fpo_data.begin();
671
672 // start by searching first frame data range containing variable range
673 for (; it != fpo_data.end(); ++it) {
674 RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
675
676 if (fd_range.Contains(range)) {
677 break;
678 }
679 }
680
681 // then first most nested entry that still contains variable range
682 auto found = it;
683 for (; it != fpo_data.end(); ++it) {
684 RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
685
686 if (!fd_range.Contains(range)) {
687 break;
688 }
689 found = it;
690 }
691
692 return found;
693}
694
695static bool GetFrameDataProgram(PdbIndex &index,
696 const Variable::RangeList &ranges,
697 llvm::StringRef &out_program) {
698 const DebugFrameDataSubsectionRef &new_fpo_data =
699 index.dbi().getNewFpoRecords();
700
701 auto frame_data_it =
702 GetCorrespondingFrameData(load_addr: index.GetLoadAddress(), fpo_data: new_fpo_data, ranges);
703 if (frame_data_it == new_fpo_data.end())
704 return false;
705
706 auto strings = index.pdb().getStringTable();
707 if (!strings) {
708 consumeError(Err: strings.takeError());
709 return false;
710 }
711 out_program = cantFail(ValOrErr: strings->getStringForID(ID: frame_data_it->FrameFunc));
712 return true;
713}
714
715static RegisterId GetBaseFrameRegister(PdbIndex &index,
716 PdbCompilandSymId frame_proc_id,
717 bool is_parameter) {
718 CVSymbol frame_proc_cvs = index.ReadSymbolRecord(cu_sym: frame_proc_id);
719 if (frame_proc_cvs.kind() != S_FRAMEPROC)
720 return RegisterId::NONE;
721
722 FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);
723 cantFail(Err: SymbolDeserializer::deserializeAs<FrameProcSym>(Symbol: frame_proc_cvs,
724 Record&: frame_proc));
725
726 CPUType cpu_type = index.compilands()
727 .GetCompiland(modi: frame_proc_id.modi)
728 ->m_compile_opts->Machine;
729
730 return is_parameter ? frame_proc.getParamFramePtrReg(CPU: cpu_type)
731 : frame_proc.getLocalFramePtrReg(CPU: cpu_type);
732}
733
734VariableInfo lldb_private::npdb::GetVariableLocationInfo(
735 PdbIndex &index, PdbCompilandSymId var_id, Block &func_block,
736 lldb::ModuleSP module) {
737
738 CVSymbol sym = index.ReadSymbolRecord(cu_sym: var_id);
739
740 VariableInfo result = GetVariableNameInfo(sym);
741
742 if (sym.kind() == S_REGREL32) {
743 RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
744 cantFail(Err: SymbolDeserializer::deserializeAs<RegRelativeSym>(Symbol: sym, Record&: reg));
745 result.location = DWARFExpressionList(
746 module, MakeRegRelLocationExpression(reg: reg.Register, offset: reg.Offset, module),
747 nullptr);
748 return result;
749 }
750
751 if (sym.kind() == S_REGISTER) {
752 RegisterSym reg(SymbolRecordKind::RegisterSym);
753 cantFail(Err: SymbolDeserializer::deserializeAs<RegisterSym>(Symbol: sym, Record&: reg));
754 result.location = DWARFExpressionList(
755 module, MakeEnregisteredLocationExpression(reg: reg.Register, module),
756 nullptr);
757 return result;
758 }
759
760 if (sym.kind() == S_LOCAL) {
761 LocalSym local(SymbolRecordKind::LocalSym);
762 if (llvm::Error error =
763 SymbolDeserializer::deserializeAs<LocalSym>(Symbol: sym, Record&: local)) {
764 llvm::consumeError(Err: std::move(error));
765 return result;
766 }
767
768 PdbCompilandSymId loc_specifier_id(var_id.modi,
769 var_id.offset + sym.RecordData.size());
770 CVSymbol loc_specifier_cvs;
771 // Only used for S_DEFRANGE_FRAMEPOINTER_REL.
772 RegisterId base_reg = RegisterId::NONE;
773 size_t type_size = GetSizeOfType(id: result.type, tpi&: index.tpi());
774 // A map from offset of a field in parent to size of the field.
775 std::map<uint64_t, size_t> offset_to_size;
776
777 // When overlaps happens, always prefer the one that doesn't split the value
778 // into multiple locations and the location parsed first is perfered.
779 RangeMap location_map;
780
781 // Iterate through all location records after S_LOCAL. They describe the
782 // value of this variable at different locations.
783 bool finished = false;
784 while (!finished) {
785 loc_specifier_cvs = index.ReadSymbolRecord(cu_sym: loc_specifier_id);
786 switch (loc_specifier_cvs.kind()) {
787 case S_DEFRANGE_FRAMEPOINTER_REL: {
788 DefRangeFramePointerRelSym loc(
789 SymbolRecordKind::DefRangeFramePointerRelSym);
790 if (llvm::Error error =
791 SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
792 Symbol: loc_specifier_cvs, Record&: loc)) {
793 llvm::consumeError(Err: std::move(error));
794 return result;
795 }
796 Variable::RangeList raw_ranges =
797 MakeRangeList(index, range: loc.Range, gaps: loc.Gaps);
798 if (base_reg == RegisterId::NONE) {
799 PdbCompilandSymId func_scope_id =
800 PdbSymUid(func_block.GetID()).asCompilandSym();
801 CVSymbol func_block_cvs = index.ReadSymbolRecord(cu_sym: func_scope_id);
802 lldbassert(func_block_cvs.kind() == S_GPROC32 ||
803 func_block_cvs.kind() == S_LPROC32);
804 PdbCompilandSymId frame_proc_id(func_scope_id.modi,
805 func_scope_id.offset +
806 func_block_cvs.length());
807 base_reg =
808 GetBaseFrameRegister(index, frame_proc_id, is_parameter: result.is_param);
809 if (base_reg == RegisterId::NONE)
810 break;
811 }
812 DWARFExpression expr;
813 if (base_reg == RegisterId::VFRAME) {
814 llvm::StringRef program;
815 if (GetFrameDataProgram(index, ranges: raw_ranges, out_program&: program))
816 expr = MakeVFrameRelLocationExpression(fpo_program: program, offset: loc.Hdr.Offset,
817 module);
818 else {
819 // invalid variable
820 }
821 } else
822 expr = MakeRegRelLocationExpression(reg: base_reg, offset: loc.Hdr.Offset, module);
823 AddDwarfRange(location_map, expr, ranges: raw_ranges);
824 break;
825 }
826 case S_DEFRANGE_REGISTER: {
827 DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);
828 if (llvm::Error error =
829 SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(
830 Symbol: loc_specifier_cvs, Record&: loc)) {
831 llvm::consumeError(Err: std::move(error));
832 return result;
833 }
834 RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
835 Variable::RangeList raw_ranges =
836 MakeRangeList(index, range: loc.Range, gaps: loc.Gaps);
837 DWARFExpression expr =
838 MakeEnregisteredLocationExpression(reg: reg_id, module);
839 AddDwarfRange(location_map, expr, ranges: raw_ranges);
840 break;
841 }
842 case S_DEFRANGE_REGISTER_REL: {
843 DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
844 if (llvm::Error error =
845 SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
846 Symbol: loc_specifier_cvs, Record&: loc)) {
847 llvm::consumeError(Err: std::move(error));
848 return result;
849 }
850 Variable::RangeList raw_ranges =
851 MakeRangeList(index, range: loc.Range, gaps: loc.Gaps);
852 RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
853 DWARFExpression expr;
854 if (reg_id == RegisterId::VFRAME) {
855 llvm::StringRef program;
856 if (GetFrameDataProgram(index, ranges: raw_ranges, out_program&: program))
857 expr = MakeVFrameRelLocationExpression(
858 fpo_program: program, offset: loc.Hdr.BasePointerOffset, module);
859 else {
860 // invalid variable
861 }
862 } else {
863 expr = MakeRegRelLocationExpression(reg: reg_id, offset: loc.Hdr.BasePointerOffset,
864 module);
865 }
866 // FIXME: If it's UDT, we need to know the size of the value in byte.
867 if (!loc.hasSpilledUDTMember())
868 AddDwarfRange(location_map, expr, ranges: raw_ranges);
869 break;
870 }
871 case S_DEFRANGE_SUBFIELD_REGISTER: {
872 DefRangeSubfieldRegisterSym loc(
873 SymbolRecordKind::DefRangeSubfieldRegisterSym);
874 if (llvm::Error error =
875 SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(
876 Symbol: loc_specifier_cvs, Record&: loc)) {
877 llvm::consumeError(Err: std::move(error));
878 return result;
879 }
880
881 Variable::RangeList ranges = MakeRangeList(index, range: loc.Range, gaps: loc.Gaps);
882 uint32_t reg_size =
883 GetRegisterSize(register_id: (RegisterId)(uint16_t)loc.Hdr.Register);
884 if (reg_size == 0)
885 break;
886 offset_to_size[loc.Hdr.OffsetInParent] = reg_size;
887 AddMemberLocationRanges(location_map, offset: loc.Hdr.OffsetInParent,
888 member_loc: {.reg_id: loc.Hdr.Register, .reg_offset: 0, .is_at_reg: true}, ranges);
889 break;
890 }
891 // FIXME: Handle other kinds. LLVM only generates the 4 types of records
892 // above. MSVC generates other location types.
893 case S_DEFRANGE:
894 case S_DEFRANGE_SUBFIELD:
895 case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
896 break;
897 default:
898 finished = true;
899 break;
900 }
901 loc_specifier_id = PdbCompilandSymId(
902 loc_specifier_id.modi,
903 loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());
904 }
905 for (const auto &entry : location_map) {
906 DWARFExpression dwarf_expr =
907 entry.data.is_dwarf ? entry.data.expr
908 : MakeEnregisteredLocationExpressionForComposite(
909 offset_to_location: entry.data.offset_to_location,
910 offset_to_size, total_size: type_size, module);
911
912 result.location.AddExpression(base: entry.GetRangeBase(), end: entry.GetRangeEnd(),
913 expr: dwarf_expr);
914 }
915 return result;
916 }
917 llvm_unreachable("Symbol is not a local variable!");
918 return result;
919}
920
921lldb::BasicType
922lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {
923 switch (kind) {
924 case SimpleTypeKind::Boolean128:
925 case SimpleTypeKind::Boolean16:
926 case SimpleTypeKind::Boolean32:
927 case SimpleTypeKind::Boolean64:
928 case SimpleTypeKind::Boolean8:
929 return lldb::eBasicTypeBool;
930 case SimpleTypeKind::Byte:
931 case SimpleTypeKind::UnsignedCharacter:
932 return lldb::eBasicTypeUnsignedChar;
933 case SimpleTypeKind::NarrowCharacter:
934 return lldb::eBasicTypeChar;
935 case SimpleTypeKind::SignedCharacter:
936 case SimpleTypeKind::SByte:
937 return lldb::eBasicTypeSignedChar;
938 case SimpleTypeKind::Character16:
939 return lldb::eBasicTypeChar16;
940 case SimpleTypeKind::Character32:
941 return lldb::eBasicTypeChar32;
942 case SimpleTypeKind::Character8:
943 return lldb::eBasicTypeChar8;
944 case SimpleTypeKind::Complex80:
945 return lldb::eBasicTypeLongDoubleComplex;
946 case SimpleTypeKind::Complex64:
947 return lldb::eBasicTypeDoubleComplex;
948 case SimpleTypeKind::Complex32:
949 return lldb::eBasicTypeFloatComplex;
950 case SimpleTypeKind::Float128:
951 case SimpleTypeKind::Float80:
952 return lldb::eBasicTypeLongDouble;
953 case SimpleTypeKind::Float64:
954 return lldb::eBasicTypeDouble;
955 case SimpleTypeKind::Float32:
956 return lldb::eBasicTypeFloat;
957 case SimpleTypeKind::Float16:
958 return lldb::eBasicTypeHalf;
959 case SimpleTypeKind::Int128:
960 return lldb::eBasicTypeInt128;
961 case SimpleTypeKind::Int64:
962 case SimpleTypeKind::Int64Quad:
963 return lldb::eBasicTypeLongLong;
964 case SimpleTypeKind::Int32:
965 return lldb::eBasicTypeInt;
966 case SimpleTypeKind::Int16:
967 case SimpleTypeKind::Int16Short:
968 return lldb::eBasicTypeShort;
969 case SimpleTypeKind::UInt128:
970 return lldb::eBasicTypeUnsignedInt128;
971 case SimpleTypeKind::UInt64:
972 case SimpleTypeKind::UInt64Quad:
973 return lldb::eBasicTypeUnsignedLongLong;
974 case SimpleTypeKind::HResult:
975 case SimpleTypeKind::UInt32:
976 return lldb::eBasicTypeUnsignedInt;
977 case SimpleTypeKind::UInt16:
978 case SimpleTypeKind::UInt16Short:
979 return lldb::eBasicTypeUnsignedShort;
980 case SimpleTypeKind::Int32Long:
981 return lldb::eBasicTypeLong;
982 case SimpleTypeKind::UInt32Long:
983 return lldb::eBasicTypeUnsignedLong;
984 case SimpleTypeKind::Void:
985 return lldb::eBasicTypeVoid;
986 case SimpleTypeKind::WideCharacter:
987 return lldb::eBasicTypeWChar;
988 default:
989 return lldb::eBasicTypeInvalid;
990 }
991}
992
993size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {
994 switch (kind) {
995 case SimpleTypeKind::Boolean128:
996 case SimpleTypeKind::Int128:
997 case SimpleTypeKind::UInt128:
998 case SimpleTypeKind::Float128:
999 return 16;
1000 case SimpleTypeKind::Complex80:
1001 case SimpleTypeKind::Float80:
1002 return 10;
1003 case SimpleTypeKind::Boolean64:
1004 case SimpleTypeKind::Complex64:
1005 case SimpleTypeKind::UInt64:
1006 case SimpleTypeKind::UInt64Quad:
1007 case SimpleTypeKind::Float64:
1008 case SimpleTypeKind::Int64:
1009 case SimpleTypeKind::Int64Quad:
1010 return 8;
1011 case SimpleTypeKind::Boolean32:
1012 case SimpleTypeKind::Character32:
1013 case SimpleTypeKind::Complex32:
1014 case SimpleTypeKind::Float32:
1015 case SimpleTypeKind::Int32:
1016 case SimpleTypeKind::Int32Long:
1017 case SimpleTypeKind::UInt32Long:
1018 case SimpleTypeKind::HResult:
1019 case SimpleTypeKind::UInt32:
1020 return 4;
1021 case SimpleTypeKind::Boolean16:
1022 case SimpleTypeKind::Character16:
1023 case SimpleTypeKind::Float16:
1024 case SimpleTypeKind::Int16:
1025 case SimpleTypeKind::Int16Short:
1026 case SimpleTypeKind::UInt16:
1027 case SimpleTypeKind::UInt16Short:
1028 case SimpleTypeKind::WideCharacter:
1029 return 2;
1030 case SimpleTypeKind::Boolean8:
1031 case SimpleTypeKind::Byte:
1032 case SimpleTypeKind::UnsignedCharacter:
1033 case SimpleTypeKind::NarrowCharacter:
1034 case SimpleTypeKind::SignedCharacter:
1035 case SimpleTypeKind::SByte:
1036 case SimpleTypeKind::Character8:
1037 return 1;
1038 case SimpleTypeKind::Void:
1039 default:
1040 return 0;
1041 }
1042}
1043
1044PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,
1045 TpiStream &tpi) {
1046 if (id.index.isSimple())
1047 return id;
1048
1049 CVType cvt = tpi.getType(Index: id.index);
1050
1051 // Only tag records have a best and a worst record.
1052 if (!IsTagRecord(cvt))
1053 return id;
1054
1055 // Tag records that are not forward decls are full decls, hence they are the
1056 // best.
1057 if (!IsForwardRefUdt(cvt))
1058 return id;
1059
1060 return llvm::cantFail(ValOrErr: tpi.findFullDeclForForwardRef(ForwardRefTI: id.index));
1061}
1062
1063template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {
1064 RecordType record;
1065 llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));
1066 return record.getSize();
1067}
1068
1069size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,
1070 llvm::pdb::TpiStream &tpi) {
1071 if (id.index.isSimple()) {
1072 switch (id.index.getSimpleMode()) {
1073 case SimpleTypeMode::Direct:
1074 return GetTypeSizeForSimpleKind(kind: id.index.getSimpleKind());
1075 case SimpleTypeMode::NearPointer32:
1076 case SimpleTypeMode::FarPointer32:
1077 return 4;
1078 case SimpleTypeMode::NearPointer64:
1079 return 8;
1080 case SimpleTypeMode::NearPointer128:
1081 return 16;
1082 default:
1083 break;
1084 }
1085 return 0;
1086 }
1087
1088 TypeIndex index = id.index;
1089 if (IsForwardRefUdt(id: index, tpi))
1090 index = llvm::cantFail(ValOrErr: tpi.findFullDeclForForwardRef(ForwardRefTI: index));
1091
1092 CVType cvt = tpi.getType(Index: index);
1093 switch (cvt.kind()) {
1094 case LF_MODIFIER:
1095 return GetSizeOfType(id: {LookThroughModifierRecord(modifier: cvt)}, tpi);
1096 case LF_ENUM: {
1097 EnumRecord record;
1098 llvm::cantFail(Err: TypeDeserializer::deserializeAs<EnumRecord>(CVT&: cvt, Record&: record));
1099 return GetSizeOfType(id: {record.UnderlyingType}, tpi);
1100 }
1101 case LF_POINTER:
1102 return GetSizeOfTypeInternal<PointerRecord>(cvt);
1103 case LF_ARRAY:
1104 return GetSizeOfTypeInternal<ArrayRecord>(cvt);
1105 case LF_CLASS:
1106 case LF_STRUCTURE:
1107 case LF_INTERFACE:
1108 return GetSizeOfTypeInternal<ClassRecord>(cvt);
1109 case LF_UNION:
1110 return GetSizeOfTypeInternal<UnionRecord>(cvt);
1111 case LF_BITFIELD: {
1112 BitFieldRecord record;
1113 llvm::cantFail(Err: TypeDeserializer::deserializeAs<BitFieldRecord>(CVT&: cvt, Record&: record));
1114 return GetSizeOfType(id: {record.Type}, tpi);
1115 }
1116 default:
1117 break;
1118 }
1119 return 0;
1120}
1121

source code of lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp