Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
39644 views
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
28
using namespace lldb_private;
29
using namespace lldb_private::npdb;
30
using namespace llvm::codeview;
31
using 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.
35
static Variable::RangeList
36
MakeRangeList(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
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(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
57
namespace {
58
struct 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.
82
typedef RangeDataVector<lldb::addr_t, lldb::addr_t, MemberLocations, 0,
83
MemberLocations::Comparator>
84
RangeMap;
85
86
void 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
143
void 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
198
CVTagRecord 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(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
223
CVTagRecord::CVTagRecord(ClassRecord &&c)
224
: cvclass(std::move(c)),
225
m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
226
CVTagRecord::CVTagRecord(UnionRecord &&u)
227
: cvunion(std::move(u)), m_kind(Union) {}
228
CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
229
230
PDB_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
282
PDB_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
311
bool 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
338
bool 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
356
template <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
362
template <typename RecordT>
363
static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
364
RecordT record = createRecord<RecordT>(sym);
365
return {record.Segment, record.CodeOffset};
366
}
367
368
template <>
369
SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
370
TrampolineSym record = createRecord<TrampolineSym>(sym);
371
return {record.ThunkSection, record.ThunkOffset};
372
}
373
374
template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
375
Thunk32Sym record = createRecord<Thunk32Sym>(sym);
376
return {record.Segment, record.Offset};
377
}
378
379
template <>
380
SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
381
CoffGroupSym record = createRecord<CoffGroupSym>(sym);
382
return {record.Segment, record.Offset};
383
}
384
385
template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
386
DataSym record = createRecord<DataSym>(sym);
387
return {record.Segment, record.DataOffset};
388
}
389
390
template <>
391
SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
392
ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
393
return {record.Segment, record.DataOffset};
394
}
395
396
SegmentOffset 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
442
template <typename RecordT>
443
SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
444
RecordT record = createRecord<RecordT>(sym);
445
return {record.Segment, record.CodeOffset, record.CodeSize};
446
}
447
448
template <>
449
SegmentOffsetLength
450
GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
451
TrampolineSym record = createRecord<TrampolineSym>(sym);
452
return {record.ThunkSection, record.ThunkOffset, record.Size};
453
}
454
455
template <>
456
SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
457
Thunk32Sym record = createRecord<Thunk32Sym>(sym);
458
return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
459
}
460
461
template <>
462
SegmentOffsetLength
463
GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
464
CoffGroupSym record = createRecord<CoffGroupSym>(sym);
465
return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
466
}
467
468
SegmentOffsetLength
469
lldb_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
496
bool 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(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
517
bool 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
529
bool 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
540
bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
541
TpiStream &tpi) {
542
if (id.is_ipi || id.index.isSimple())
543
return false;
544
return IsForwardRefUdt(tpi.getType(id.index));
545
}
546
547
bool 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
553
lldb::AccessType
554
lldb_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
568
TypeIndex 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
592
TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
593
lldbassert(modifier.kind() == LF_MODIFIER);
594
ModifierRecord mr;
595
llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
596
return mr.ModifiedType;
597
}
598
599
llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
600
return MSVCUndecoratedNameParser::DropScope(name);
601
}
602
603
VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
604
VariableInfo result = {};
605
606
if (sym.kind() == S_REGREL32) {
607
RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
608
cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, 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(SymbolDeserializer::deserializeAs<RegisterSym>(sym, 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(SymbolDeserializer::deserializeAs<LocalSym>(sym, 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(SymbolDeserializer::deserializeAs<DataSym>(sym, 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(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, 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(SymbolDeserializer::deserializeAs<ConstantSym>(sym, 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
660
static llvm::FixedStreamArray<FrameData>::Iterator
661
GetCorrespondingFrameData(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(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
695
static 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(index.GetLoadAddress(), 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(strings.takeError());
709
return false;
710
}
711
out_program = cantFail(strings->getStringForID(frame_data_it->FrameFunc));
712
return true;
713
}
714
715
static RegisterId GetBaseFrameRegister(PdbIndex &index,
716
PdbCompilandSymId frame_proc_id,
717
bool is_parameter) {
718
CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);
719
if (frame_proc_cvs.kind() != S_FRAMEPROC)
720
return RegisterId::NONE;
721
722
FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);
723
cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,
724
frame_proc));
725
726
CPUType cpu_type = index.compilands()
727
.GetCompiland(frame_proc_id.modi)
728
->m_compile_opts->Machine;
729
730
return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type)
731
: frame_proc.getLocalFramePtrReg(cpu_type);
732
}
733
734
VariableInfo lldb_private::npdb::GetVariableLocationInfo(
735
PdbIndex &index, PdbCompilandSymId var_id, Block &func_block,
736
lldb::ModuleSP module) {
737
738
CVSymbol sym = index.ReadSymbolRecord(var_id);
739
740
VariableInfo result = GetVariableNameInfo(sym);
741
742
if (sym.kind() == S_REGREL32) {
743
RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
744
cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
745
result.location = DWARFExpressionList(
746
module, MakeRegRelLocationExpression(reg.Register, reg.Offset, module),
747
nullptr);
748
return result;
749
}
750
751
if (sym.kind() == S_REGISTER) {
752
RegisterSym reg(SymbolRecordKind::RegisterSym);
753
cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
754
result.location = DWARFExpressionList(
755
module, MakeEnregisteredLocationExpression(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>(sym, local)) {
764
llvm::consumeError(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(result.type, 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(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
loc_specifier_cvs, loc)) {
793
llvm::consumeError(std::move(error));
794
return result;
795
}
796
Variable::RangeList raw_ranges =
797
MakeRangeList(index, loc.Range, 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(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, 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, raw_ranges, program))
816
expr = MakeVFrameRelLocationExpression(program, loc.Hdr.Offset,
817
module);
818
else {
819
// invalid variable
820
}
821
} else
822
expr = MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
823
AddDwarfRange(location_map, expr, 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
loc_specifier_cvs, loc)) {
831
llvm::consumeError(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, loc.Range, loc.Gaps);
837
DWARFExpression expr =
838
MakeEnregisteredLocationExpression(reg_id, module);
839
AddDwarfRange(location_map, expr, 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
loc_specifier_cvs, loc)) {
847
llvm::consumeError(std::move(error));
848
return result;
849
}
850
Variable::RangeList raw_ranges =
851
MakeRangeList(index, loc.Range, 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, raw_ranges, program))
857
expr = MakeVFrameRelLocationExpression(
858
program, loc.Hdr.BasePointerOffset, module);
859
else {
860
// invalid variable
861
}
862
} else {
863
expr = MakeRegRelLocationExpression(reg_id, 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, 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
loc_specifier_cvs, loc)) {
877
llvm::consumeError(std::move(error));
878
return result;
879
}
880
881
Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
882
uint32_t reg_size =
883
GetRegisterSize((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, loc.Hdr.OffsetInParent,
888
{loc.Hdr.Register, 0, 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
entry.data.offset_to_location,
910
offset_to_size, type_size, module);
911
912
result.location.AddExpression(entry.GetRangeBase(), entry.GetRangeEnd(),
913
dwarf_expr);
914
}
915
return result;
916
}
917
llvm_unreachable("Symbol is not a local variable!");
918
return result;
919
}
920
921
lldb::BasicType
922
lldb_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
993
size_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
1044
PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,
1045
TpiStream &tpi) {
1046
if (id.index.isSimple())
1047
return id;
1048
1049
CVType cvt = tpi.getType(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(tpi.findFullDeclForForwardRef(id.index));
1061
}
1062
1063
template <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
1069
size_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(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(index, tpi))
1090
index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));
1091
1092
CVType cvt = tpi.getType(index);
1093
switch (cvt.kind()) {
1094
case LF_MODIFIER:
1095
return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);
1096
case LF_ENUM: {
1097
EnumRecord record;
1098
llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));
1099
return GetSizeOfType({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(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, record));
1114
return GetSizeOfType({record.Type}, tpi);
1115
}
1116
default:
1117
break;
1118
}
1119
return 0;
1120
}
1121
1122