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/SymbolFileNativePDB.cpp
39644 views
1
//===-- SymbolFileNativePDB.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 "SymbolFileNativePDB.h"
10
11
#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
12
#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
13
#include "Plugins/ObjectFile/PDB/ObjectFilePDB.h"
14
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
15
#include "lldb/Core/Module.h"
16
#include "lldb/Core/PluginManager.h"
17
#include "lldb/Symbol/CompileUnit.h"
18
#include "lldb/Symbol/LineTable.h"
19
#include "lldb/Symbol/ObjectFile.h"
20
#include "lldb/Symbol/SymbolContext.h"
21
#include "lldb/Symbol/SymbolVendor.h"
22
#include "lldb/Symbol/Variable.h"
23
#include "lldb/Symbol/VariableList.h"
24
#include "lldb/Utility/LLDBLog.h"
25
#include "lldb/Utility/Log.h"
26
27
#include "llvm/DebugInfo/CodeView/CVRecord.h"
28
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
29
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
30
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
31
#include "llvm/DebugInfo/CodeView/RecordName.h"
32
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
33
#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
34
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
35
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
36
#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
37
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
38
#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
39
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
40
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
41
#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
42
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
43
#include "llvm/DebugInfo/PDB/PDB.h"
44
#include "llvm/DebugInfo/PDB/PDBTypes.h"
45
#include "llvm/Demangle/MicrosoftDemangle.h"
46
#include "llvm/Object/COFF.h"
47
#include "llvm/Support/Allocator.h"
48
#include "llvm/Support/BinaryStreamReader.h"
49
#include "llvm/Support/Error.h"
50
#include "llvm/Support/ErrorOr.h"
51
#include "llvm/Support/MemoryBuffer.h"
52
53
#include "DWARFLocationExpression.h"
54
#include "PdbSymUid.h"
55
#include "PdbUtil.h"
56
#include "UdtRecordCompleter.h"
57
#include <optional>
58
#include <string_view>
59
60
using namespace lldb;
61
using namespace lldb_private;
62
using namespace npdb;
63
using namespace llvm::codeview;
64
using namespace llvm::pdb;
65
66
char SymbolFileNativePDB::ID;
67
68
static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
69
switch (lang) {
70
case PDB_Lang::Cpp:
71
return lldb::LanguageType::eLanguageTypeC_plus_plus;
72
case PDB_Lang::C:
73
return lldb::LanguageType::eLanguageTypeC;
74
case PDB_Lang::Swift:
75
return lldb::LanguageType::eLanguageTypeSwift;
76
case PDB_Lang::Rust:
77
return lldb::LanguageType::eLanguageTypeRust;
78
case PDB_Lang::ObjC:
79
return lldb::LanguageType::eLanguageTypeObjC;
80
case PDB_Lang::ObjCpp:
81
return lldb::LanguageType::eLanguageTypeObjC_plus_plus;
82
default:
83
return lldb::LanguageType::eLanguageTypeUnknown;
84
}
85
}
86
87
static std::unique_ptr<PDBFile>
88
loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
89
// Try to find a matching PDB for an EXE.
90
using namespace llvm::object;
91
auto expected_binary = createBinary(exe_path);
92
93
// If the file isn't a PE/COFF executable, fail.
94
if (!expected_binary) {
95
llvm::consumeError(expected_binary.takeError());
96
return nullptr;
97
}
98
OwningBinary<Binary> binary = std::move(*expected_binary);
99
100
// TODO: Avoid opening the PE/COFF binary twice by reading this information
101
// directly from the lldb_private::ObjectFile.
102
auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary());
103
if (!obj)
104
return nullptr;
105
const llvm::codeview::DebugInfo *pdb_info = nullptr;
106
107
// If it doesn't have a debug directory, fail.
108
llvm::StringRef pdb_file;
109
if (llvm::Error e = obj->getDebugPDBInfo(pdb_info, pdb_file)) {
110
consumeError(std::move(e));
111
return nullptr;
112
}
113
114
// If the file doesn't exist, perhaps the path specified at build time
115
// doesn't match the PDB's current location, so check the location of the
116
// executable.
117
if (!FileSystem::Instance().Exists(pdb_file)) {
118
const auto exe_dir = FileSpec(exe_path).CopyByRemovingLastPathComponent();
119
const auto pdb_name = FileSpec(pdb_file).GetFilename().GetCString();
120
pdb_file = exe_dir.CopyByAppendingPathComponent(pdb_name).GetPathAsConstString().GetStringRef();
121
}
122
123
// If the file is not a PDB or if it doesn't have a matching GUID, fail.
124
auto pdb = ObjectFilePDB::loadPDBFile(std::string(pdb_file), allocator);
125
if (!pdb)
126
return nullptr;
127
128
auto expected_info = pdb->getPDBInfoStream();
129
if (!expected_info) {
130
llvm::consumeError(expected_info.takeError());
131
return nullptr;
132
}
133
llvm::codeview::GUID guid;
134
memcpy(&guid, pdb_info->PDB70.Signature, 16);
135
136
if (expected_info->getGuid() != guid)
137
return nullptr;
138
return pdb;
139
}
140
141
static bool IsFunctionPrologue(const CompilandIndexItem &cci,
142
lldb::addr_t addr) {
143
// FIXME: Implement this.
144
return false;
145
}
146
147
static bool IsFunctionEpilogue(const CompilandIndexItem &cci,
148
lldb::addr_t addr) {
149
// FIXME: Implement this.
150
return false;
151
}
152
153
static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) {
154
switch (kind) {
155
case SimpleTypeKind::Boolean128:
156
case SimpleTypeKind::Boolean16:
157
case SimpleTypeKind::Boolean32:
158
case SimpleTypeKind::Boolean64:
159
case SimpleTypeKind::Boolean8:
160
return "bool";
161
case SimpleTypeKind::Byte:
162
case SimpleTypeKind::UnsignedCharacter:
163
return "unsigned char";
164
case SimpleTypeKind::NarrowCharacter:
165
return "char";
166
case SimpleTypeKind::SignedCharacter:
167
case SimpleTypeKind::SByte:
168
return "signed char";
169
case SimpleTypeKind::Character16:
170
return "char16_t";
171
case SimpleTypeKind::Character32:
172
return "char32_t";
173
case SimpleTypeKind::Character8:
174
return "char8_t";
175
case SimpleTypeKind::Complex80:
176
case SimpleTypeKind::Complex64:
177
case SimpleTypeKind::Complex32:
178
return "complex";
179
case SimpleTypeKind::Float128:
180
case SimpleTypeKind::Float80:
181
return "long double";
182
case SimpleTypeKind::Float64:
183
return "double";
184
case SimpleTypeKind::Float32:
185
return "float";
186
case SimpleTypeKind::Float16:
187
return "single";
188
case SimpleTypeKind::Int128:
189
return "__int128";
190
case SimpleTypeKind::Int64:
191
case SimpleTypeKind::Int64Quad:
192
return "int64_t";
193
case SimpleTypeKind::Int32:
194
return "int";
195
case SimpleTypeKind::Int16:
196
return "short";
197
case SimpleTypeKind::UInt128:
198
return "unsigned __int128";
199
case SimpleTypeKind::UInt64:
200
case SimpleTypeKind::UInt64Quad:
201
return "uint64_t";
202
case SimpleTypeKind::HResult:
203
return "HRESULT";
204
case SimpleTypeKind::UInt32:
205
return "unsigned";
206
case SimpleTypeKind::UInt16:
207
case SimpleTypeKind::UInt16Short:
208
return "unsigned short";
209
case SimpleTypeKind::Int32Long:
210
return "long";
211
case SimpleTypeKind::UInt32Long:
212
return "unsigned long";
213
case SimpleTypeKind::Void:
214
return "void";
215
case SimpleTypeKind::WideCharacter:
216
return "wchar_t";
217
default:
218
return "";
219
}
220
}
221
222
static bool IsClassRecord(TypeLeafKind kind) {
223
switch (kind) {
224
case LF_STRUCTURE:
225
case LF_CLASS:
226
case LF_INTERFACE:
227
return true;
228
default:
229
return false;
230
}
231
}
232
233
static std::optional<CVTagRecord>
234
GetNestedTagDefinition(const NestedTypeRecord &Record,
235
const CVTagRecord &parent, TpiStream &tpi) {
236
// An LF_NESTTYPE is essentially a nested typedef / using declaration, but it
237
// is also used to indicate the primary definition of a nested class. That is
238
// to say, if you have:
239
// struct A {
240
// struct B {};
241
// using C = B;
242
// };
243
// Then in the debug info, this will appear as:
244
// LF_STRUCTURE `A::B` [type index = N]
245
// LF_STRUCTURE `A`
246
// LF_NESTTYPE [name = `B`, index = N]
247
// LF_NESTTYPE [name = `C`, index = N]
248
// In order to accurately reconstruct the decl context hierarchy, we need to
249
// know which ones are actual definitions and which ones are just aliases.
250
251
// If it's a simple type, then this is something like `using foo = int`.
252
if (Record.Type.isSimple())
253
return std::nullopt;
254
255
CVType cvt = tpi.getType(Record.Type);
256
257
if (!IsTagRecord(cvt))
258
return std::nullopt;
259
260
// If it's an inner definition, then treat whatever name we have here as a
261
// single component of a mangled name. So we can inject it into the parent's
262
// mangled name to see if it matches.
263
CVTagRecord child = CVTagRecord::create(cvt);
264
std::string qname = std::string(parent.asTag().getUniqueName());
265
if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4)
266
return std::nullopt;
267
268
// qname[3] is the tag type identifier (struct, class, union, etc). Since the
269
// inner tag type is not necessarily the same as the outer tag type, re-write
270
// it to match the inner tag type.
271
qname[3] = child.asTag().getUniqueName()[3];
272
std::string piece;
273
if (qname[3] == 'W')
274
piece = "4";
275
piece += Record.Name;
276
piece.push_back('@');
277
qname.insert(4, std::move(piece));
278
if (qname != child.asTag().UniqueName)
279
return std::nullopt;
280
281
return std::move(child);
282
}
283
284
void SymbolFileNativePDB::Initialize() {
285
PluginManager::RegisterPlugin(GetPluginNameStatic(),
286
GetPluginDescriptionStatic(), CreateInstance,
287
DebuggerInitialize);
288
}
289
290
void SymbolFileNativePDB::Terminate() {
291
PluginManager::UnregisterPlugin(CreateInstance);
292
}
293
294
void SymbolFileNativePDB::DebuggerInitialize(Debugger &debugger) {}
295
296
llvm::StringRef SymbolFileNativePDB::GetPluginDescriptionStatic() {
297
return "Microsoft PDB debug symbol cross-platform file reader.";
298
}
299
300
SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFileSP objfile_sp) {
301
return new SymbolFileNativePDB(std::move(objfile_sp));
302
}
303
304
SymbolFileNativePDB::SymbolFileNativePDB(ObjectFileSP objfile_sp)
305
: SymbolFileCommon(std::move(objfile_sp)) {}
306
307
SymbolFileNativePDB::~SymbolFileNativePDB() = default;
308
309
uint32_t SymbolFileNativePDB::CalculateAbilities() {
310
uint32_t abilities = 0;
311
if (!m_objfile_sp)
312
return 0;
313
314
if (!m_index) {
315
// Lazily load and match the PDB file, but only do this once.
316
PDBFile *pdb_file;
317
if (auto *pdb = llvm::dyn_cast<ObjectFilePDB>(m_objfile_sp.get())) {
318
pdb_file = &pdb->GetPDBFile();
319
} else {
320
m_file_up = loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(),
321
m_allocator);
322
pdb_file = m_file_up.get();
323
}
324
325
if (!pdb_file)
326
return 0;
327
328
auto expected_index = PdbIndex::create(pdb_file);
329
if (!expected_index) {
330
llvm::consumeError(expected_index.takeError());
331
return 0;
332
}
333
m_index = std::move(*expected_index);
334
}
335
if (!m_index)
336
return 0;
337
338
// We don't especially have to be precise here. We only distinguish between
339
// stripped and not stripped.
340
abilities = kAllAbilities;
341
342
if (m_index->dbi().isStripped())
343
abilities &= ~(Blocks | LocalVariables);
344
return abilities;
345
}
346
347
void SymbolFileNativePDB::InitializeObject() {
348
m_obj_load_address = m_objfile_sp->GetModule()
349
->GetObjectFile()
350
->GetBaseAddress()
351
.GetFileAddress();
352
m_index->SetLoadAddress(m_obj_load_address);
353
m_index->ParseSectionContribs();
354
355
auto ts_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage(
356
lldb::eLanguageTypeC_plus_plus);
357
if (auto err = ts_or_err.takeError()) {
358
LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
359
"Failed to initialize: {0}");
360
} else {
361
if (auto ts = *ts_or_err)
362
ts->SetSymbolFile(this);
363
BuildParentMap();
364
}
365
}
366
367
uint32_t SymbolFileNativePDB::CalculateNumCompileUnits() {
368
const DbiModuleList &modules = m_index->dbi().modules();
369
uint32_t count = modules.getModuleCount();
370
if (count == 0)
371
return count;
372
373
// The linker can inject an additional "dummy" compilation unit into the
374
// PDB. Ignore this special compile unit for our purposes, if it is there.
375
// It is always the last one.
376
DbiModuleDescriptor last = modules.getModuleDescriptor(count - 1);
377
if (last.getModuleName() == "* Linker *")
378
--count;
379
return count;
380
}
381
382
Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
383
CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
384
CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
385
CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
386
lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id);
387
BlockSP child_block = std::make_shared<Block>(opaque_block_uid);
388
auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
389
if (auto err = ts_or_err.takeError())
390
return *child_block;
391
auto ts = *ts_or_err;
392
if (!ts)
393
return *child_block;
394
PdbAstBuilder* ast_builder = ts->GetNativePDBParser();
395
396
switch (sym.kind()) {
397
case S_GPROC32:
398
case S_LPROC32: {
399
// This is a function. It must be global. Creating the Function entry
400
// for it automatically creates a block for it.
401
FunctionSP func = GetOrCreateFunction(block_id, *comp_unit);
402
if (func) {
403
Block &block = func->GetBlock(false);
404
if (block.GetNumRanges() == 0)
405
block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize()));
406
return block;
407
}
408
break;
409
}
410
case S_BLOCK32: {
411
// This is a block. Its parent is either a function or another block. In
412
// either case, its parent can be viewed as a block (e.g. a function
413
// contains 1 big block. So just get the parent block and add this block
414
// to it.
415
BlockSym block(static_cast<SymbolRecordKind>(sym.kind()));
416
cantFail(SymbolDeserializer::deserializeAs<BlockSym>(sym, block));
417
lldbassert(block.Parent != 0);
418
PdbCompilandSymId parent_id(block_id.modi, block.Parent);
419
Block &parent_block = GetOrCreateBlock(parent_id);
420
Function *func = parent_block.CalculateSymbolContextFunction();
421
lldbassert(func);
422
lldb::addr_t block_base =
423
m_index->MakeVirtualAddress(block.Segment, block.CodeOffset);
424
lldb::addr_t func_base =
425
func->GetAddressRange().GetBaseAddress().GetFileAddress();
426
if (block_base >= func_base)
427
child_block->AddRange(Block::Range(block_base - func_base, block.CodeSize));
428
else {
429
GetObjectFile()->GetModule()->ReportError(
430
"S_BLOCK32 at modi: {0:d} offset: {1:d}: adding range "
431
"[{2:x16}-{3:x16}) which has a base that is less than the "
432
"function's "
433
"low PC 0x%" PRIx64 ". Please file a bug and attach the file at the "
434
"start of this error message",
435
block_id.modi, block_id.offset, block_base,
436
block_base + block.CodeSize, func_base);
437
}
438
parent_block.AddChild(child_block);
439
ast_builder->GetOrCreateBlockDecl(block_id);
440
m_blocks.insert({opaque_block_uid, child_block});
441
break;
442
}
443
case S_INLINESITE: {
444
// This ensures line table is parsed first so we have inline sites info.
445
comp_unit->GetLineTable();
446
447
std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid];
448
Block &parent_block = GetOrCreateBlock(inline_site->parent_id);
449
parent_block.AddChild(child_block);
450
ast_builder->GetOrCreateInlinedFunctionDecl(block_id);
451
// Copy ranges from InlineSite to Block.
452
for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) {
453
auto *entry = inline_site->ranges.GetEntryAtIndex(i);
454
child_block->AddRange(
455
Block::Range(entry->GetRangeBase(), entry->GetByteSize()));
456
}
457
child_block->FinalizeRanges();
458
459
// Get the inlined function callsite info.
460
Declaration &decl = inline_site->inline_function_info->GetDeclaration();
461
Declaration &callsite = inline_site->inline_function_info->GetCallSite();
462
child_block->SetInlinedFunctionInfo(
463
inline_site->inline_function_info->GetName().GetCString(), nullptr,
464
&decl, &callsite);
465
m_blocks.insert({opaque_block_uid, child_block});
466
break;
467
}
468
default:
469
lldbassert(false && "Symbol is not a block!");
470
}
471
472
return *child_block;
473
}
474
475
lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
476
CompileUnit &comp_unit) {
477
const CompilandIndexItem *cci =
478
m_index->compilands().GetCompiland(func_id.modi);
479
lldbassert(cci);
480
CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);
481
482
lldbassert(sym_record.kind() == S_LPROC32 || sym_record.kind() == S_GPROC32);
483
SegmentOffsetLength sol = GetSegmentOffsetAndLength(sym_record);
484
485
auto file_vm_addr =
486
m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);
487
if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
488
return nullptr;
489
490
AddressRange func_range(file_vm_addr, sol.length,
491
comp_unit.GetModule()->GetSectionList());
492
if (!func_range.GetBaseAddress().IsValid())
493
return nullptr;
494
495
ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
496
cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));
497
if (proc.FunctionType == TypeIndex::None())
498
return nullptr;
499
TypeSP func_type = GetOrCreateType(proc.FunctionType);
500
if (!func_type)
501
return nullptr;
502
503
PdbTypeSymId sig_id(proc.FunctionType, false);
504
Mangled mangled(proc.Name);
505
FunctionSP func_sp = std::make_shared<Function>(
506
&comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled,
507
func_type.get(), func_range);
508
509
comp_unit.AddFunction(func_sp);
510
511
auto ts_or_err = GetTypeSystemForLanguage(comp_unit.GetLanguage());
512
if (auto err = ts_or_err.takeError())
513
return func_sp;
514
auto ts = *ts_or_err;
515
if (!ts)
516
return func_sp;
517
ts->GetNativePDBParser()->GetOrCreateFunctionDecl(func_id);
518
519
return func_sp;
520
}
521
522
CompUnitSP
523
SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) {
524
lldb::LanguageType lang =
525
cci.m_compile_opts ? TranslateLanguage(cci.m_compile_opts->getLanguage())
526
: lldb::eLanguageTypeUnknown;
527
528
LazyBool optimized = eLazyBoolNo;
529
if (cci.m_compile_opts && cci.m_compile_opts->hasOptimizations())
530
optimized = eLazyBoolYes;
531
532
llvm::SmallString<64> source_file_name =
533
m_index->compilands().GetMainSourceFile(cci);
534
FileSpec fs(llvm::sys::path::convert_to_slash(
535
source_file_name, llvm::sys::path::Style::windows_backslash));
536
537
CompUnitSP cu_sp = std::make_shared<CompileUnit>(
538
m_objfile_sp->GetModule(), nullptr, std::make_shared<SupportFile>(fs),
539
toOpaqueUid(cci.m_id), lang, optimized);
540
541
SetCompileUnitAtIndex(cci.m_id.modi, cu_sp);
542
return cu_sp;
543
}
544
545
lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id,
546
const ModifierRecord &mr,
547
CompilerType ct) {
548
TpiStream &stream = m_index->tpi();
549
550
std::string name;
551
if (mr.ModifiedType.isSimple())
552
name = std::string(GetSimpleTypeName(mr.ModifiedType.getSimpleKind()));
553
else
554
name = computeTypeName(stream.typeCollection(), mr.ModifiedType);
555
Declaration decl;
556
lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType);
557
558
return MakeType(toOpaqueUid(type_id), ConstString(name),
559
modified_type->GetByteSize(nullptr), nullptr,
560
LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
561
Type::ResolveState::Full);
562
}
563
564
lldb::TypeSP
565
SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id,
566
const llvm::codeview::PointerRecord &pr,
567
CompilerType ct) {
568
TypeSP pointee = GetOrCreateType(pr.ReferentType);
569
if (!pointee)
570
return nullptr;
571
572
if (pr.isPointerToMember()) {
573
MemberPointerInfo mpi = pr.getMemberInfo();
574
GetOrCreateType(mpi.ContainingType);
575
}
576
577
Declaration decl;
578
return MakeType(toOpaqueUid(type_id), ConstString(), pr.getSize(), nullptr,
579
LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
580
Type::ResolveState::Full);
581
}
582
583
lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
584
CompilerType ct) {
585
uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false));
586
if (ti == TypeIndex::NullptrT()) {
587
Declaration decl;
588
return MakeType(uid, ConstString("std::nullptr_t"), 0, nullptr,
589
LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
590
Type::ResolveState::Full);
591
}
592
593
if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
594
TypeSP direct_sp = GetOrCreateType(ti.makeDirect());
595
uint32_t pointer_size = 0;
596
switch (ti.getSimpleMode()) {
597
case SimpleTypeMode::FarPointer32:
598
case SimpleTypeMode::NearPointer32:
599
pointer_size = 4;
600
break;
601
case SimpleTypeMode::NearPointer64:
602
pointer_size = 8;
603
break;
604
default:
605
// 128-bit and 16-bit pointers unsupported.
606
return nullptr;
607
}
608
Declaration decl;
609
return MakeType(uid, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,
610
Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
611
}
612
613
if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
614
return nullptr;
615
616
size_t size = GetTypeSizeForSimpleKind(ti.getSimpleKind());
617
llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind());
618
619
Declaration decl;
620
return MakeType(uid, ConstString(type_name), size, nullptr, LLDB_INVALID_UID,
621
Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
622
}
623
624
static std::string GetUnqualifiedTypeName(const TagRecord &record) {
625
if (!record.hasUniqueName()) {
626
MSVCUndecoratedNameParser parser(record.Name);
627
llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
628
629
return std::string(specs.back().GetBaseName());
630
}
631
632
llvm::ms_demangle::Demangler demangler;
633
std::string_view sv(record.UniqueName.begin(), record.UniqueName.size());
634
llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
635
if (demangler.Error)
636
return std::string(record.Name);
637
638
llvm::ms_demangle::IdentifierNode *idn =
639
ttn->QualifiedName->getUnqualifiedIdentifier();
640
return idn->toString();
641
}
642
643
lldb::TypeSP
644
SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id,
645
const TagRecord &record,
646
size_t size, CompilerType ct) {
647
648
std::string uname = GetUnqualifiedTypeName(record);
649
650
// FIXME: Search IPI stream for LF_UDT_MOD_SRC_LINE.
651
Declaration decl;
652
return MakeType(toOpaqueUid(type_id), ConstString(uname), size, nullptr,
653
LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
654
Type::ResolveState::Forward);
655
}
656
657
lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
658
const ClassRecord &cr,
659
CompilerType ct) {
660
return CreateClassStructUnion(type_id, cr, cr.getSize(), ct);
661
}
662
663
lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
664
const UnionRecord &ur,
665
CompilerType ct) {
666
return CreateClassStructUnion(type_id, ur, ur.getSize(), ct);
667
}
668
669
lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
670
const EnumRecord &er,
671
CompilerType ct) {
672
std::string uname = GetUnqualifiedTypeName(er);
673
674
Declaration decl;
675
TypeSP underlying_type = GetOrCreateType(er.UnderlyingType);
676
677
return MakeType(toOpaqueUid(type_id), ConstString(uname),
678
underlying_type->GetByteSize(nullptr), nullptr,
679
LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
680
ct, lldb_private::Type::ResolveState::Forward);
681
}
682
683
TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
684
const ArrayRecord &ar,
685
CompilerType ct) {
686
TypeSP element_type = GetOrCreateType(ar.ElementType);
687
688
Declaration decl;
689
TypeSP array_sp =
690
MakeType(toOpaqueUid(type_id), ConstString(), ar.Size, nullptr,
691
LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,
692
lldb_private::Type::ResolveState::Full);
693
array_sp->SetEncodingType(element_type.get());
694
return array_sp;
695
}
696
697
TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id,
698
const MemberFunctionRecord &mfr,
699
CompilerType ct) {
700
Declaration decl;
701
return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
702
LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
703
ct, lldb_private::Type::ResolveState::Full);
704
}
705
706
TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,
707
const ProcedureRecord &pr,
708
CompilerType ct) {
709
Declaration decl;
710
return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
711
LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
712
ct, lldb_private::Type::ResolveState::Full);
713
}
714
715
TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) {
716
if (type_id.index.isSimple())
717
return CreateSimpleType(type_id.index, ct);
718
719
TpiStream &stream = type_id.is_ipi ? m_index->ipi() : m_index->tpi();
720
CVType cvt = stream.getType(type_id.index);
721
722
if (cvt.kind() == LF_MODIFIER) {
723
ModifierRecord modifier;
724
llvm::cantFail(
725
TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier));
726
return CreateModifierType(type_id, modifier, ct);
727
}
728
729
if (cvt.kind() == LF_POINTER) {
730
PointerRecord pointer;
731
llvm::cantFail(
732
TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer));
733
return CreatePointerType(type_id, pointer, ct);
734
}
735
736
if (IsClassRecord(cvt.kind())) {
737
ClassRecord cr;
738
llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
739
return CreateTagType(type_id, cr, ct);
740
}
741
742
if (cvt.kind() == LF_ENUM) {
743
EnumRecord er;
744
llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
745
return CreateTagType(type_id, er, ct);
746
}
747
748
if (cvt.kind() == LF_UNION) {
749
UnionRecord ur;
750
llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
751
return CreateTagType(type_id, ur, ct);
752
}
753
754
if (cvt.kind() == LF_ARRAY) {
755
ArrayRecord ar;
756
llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar));
757
return CreateArrayType(type_id, ar, ct);
758
}
759
760
if (cvt.kind() == LF_PROCEDURE) {
761
ProcedureRecord pr;
762
llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));
763
return CreateProcedureType(type_id, pr, ct);
764
}
765
if (cvt.kind() == LF_MFUNCTION) {
766
MemberFunctionRecord mfr;
767
llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr));
768
return CreateFunctionType(type_id, mfr, ct);
769
}
770
771
return nullptr;
772
}
773
774
TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) {
775
// If they search for a UDT which is a forward ref, try and resolve the full
776
// decl and just map the forward ref uid to the full decl record.
777
std::optional<PdbTypeSymId> full_decl_uid;
778
if (IsForwardRefUdt(type_id, m_index->tpi())) {
779
auto expected_full_ti =
780
m_index->tpi().findFullDeclForForwardRef(type_id.index);
781
if (!expected_full_ti)
782
llvm::consumeError(expected_full_ti.takeError());
783
else if (*expected_full_ti != type_id.index) {
784
full_decl_uid = PdbTypeSymId(*expected_full_ti, false);
785
786
// It's possible that a lookup would occur for the full decl causing it
787
// to be cached, then a second lookup would occur for the forward decl.
788
// We don't want to create a second full decl, so make sure the full
789
// decl hasn't already been cached.
790
auto full_iter = m_types.find(toOpaqueUid(*full_decl_uid));
791
if (full_iter != m_types.end()) {
792
TypeSP result = full_iter->second;
793
// Map the forward decl to the TypeSP for the full decl so we can take
794
// the fast path next time.
795
m_types[toOpaqueUid(type_id)] = result;
796
return result;
797
}
798
}
799
}
800
801
PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id;
802
auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
803
if (auto err = ts_or_err.takeError())
804
return nullptr;
805
auto ts = *ts_or_err;
806
if (!ts)
807
return nullptr;
808
809
PdbAstBuilder* ast_builder = ts->GetNativePDBParser();
810
clang::QualType qt = ast_builder->GetOrCreateType(best_decl_id);
811
if (qt.isNull())
812
return nullptr;
813
814
TypeSP result = CreateType(best_decl_id, ast_builder->ToCompilerType(qt));
815
if (!result)
816
return nullptr;
817
818
uint64_t best_uid = toOpaqueUid(best_decl_id);
819
m_types[best_uid] = result;
820
// If we had both a forward decl and a full decl, make both point to the new
821
// type.
822
if (full_decl_uid)
823
m_types[toOpaqueUid(type_id)] = result;
824
825
return result;
826
}
827
828
TypeSP SymbolFileNativePDB::GetOrCreateType(PdbTypeSymId type_id) {
829
// We can't use try_emplace / overwrite here because the process of creating
830
// a type could create nested types, which could invalidate iterators. So
831
// we have to do a 2-phase lookup / insert.
832
auto iter = m_types.find(toOpaqueUid(type_id));
833
if (iter != m_types.end())
834
return iter->second;
835
836
TypeSP type = CreateAndCacheType(type_id);
837
if (type)
838
GetTypeList().Insert(type);
839
return type;
840
}
841
842
VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
843
CVSymbol sym = m_index->symrecords().readRecord(var_id.offset);
844
if (sym.kind() == S_CONSTANT)
845
return CreateConstantSymbol(var_id, sym);
846
847
lldb::ValueType scope = eValueTypeInvalid;
848
TypeIndex ti;
849
llvm::StringRef name;
850
lldb::addr_t addr = 0;
851
uint16_t section = 0;
852
uint32_t offset = 0;
853
bool is_external = false;
854
switch (sym.kind()) {
855
case S_GDATA32:
856
is_external = true;
857
[[fallthrough]];
858
case S_LDATA32: {
859
DataSym ds(sym.kind());
860
llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, ds));
861
ti = ds.Type;
862
scope = (sym.kind() == S_GDATA32) ? eValueTypeVariableGlobal
863
: eValueTypeVariableStatic;
864
name = ds.Name;
865
section = ds.Segment;
866
offset = ds.DataOffset;
867
addr = m_index->MakeVirtualAddress(ds.Segment, ds.DataOffset);
868
break;
869
}
870
case S_GTHREAD32:
871
is_external = true;
872
[[fallthrough]];
873
case S_LTHREAD32: {
874
ThreadLocalDataSym tlds(sym.kind());
875
llvm::cantFail(
876
SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, tlds));
877
ti = tlds.Type;
878
name = tlds.Name;
879
section = tlds.Segment;
880
offset = tlds.DataOffset;
881
addr = m_index->MakeVirtualAddress(tlds.Segment, tlds.DataOffset);
882
scope = eValueTypeVariableThreadLocal;
883
break;
884
}
885
default:
886
llvm_unreachable("unreachable!");
887
}
888
889
CompUnitSP comp_unit;
890
std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr);
891
if (!modi) {
892
return nullptr;
893
}
894
895
CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(*modi);
896
comp_unit = GetOrCreateCompileUnit(cci);
897
898
Declaration decl;
899
PdbTypeSymId tid(ti, false);
900
SymbolFileTypeSP type_sp =
901
std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
902
Variable::RangeList ranges;
903
auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
904
if (auto err = ts_or_err.takeError())
905
return nullptr;
906
auto ts = *ts_or_err;
907
if (!ts)
908
return nullptr;
909
910
ts->GetNativePDBParser()->GetOrCreateVariableDecl(var_id);
911
912
ModuleSP module_sp = GetObjectFile()->GetModule();
913
DWARFExpressionList location(
914
module_sp, MakeGlobalLocationExpression(section, offset, module_sp),
915
nullptr);
916
917
std::string global_name("::");
918
global_name += name;
919
bool artificial = false;
920
bool location_is_constant_data = false;
921
bool static_member = false;
922
VariableSP var_sp = std::make_shared<Variable>(
923
toOpaqueUid(var_id), name.str().c_str(), global_name.c_str(), type_sp,
924
scope, comp_unit.get(), ranges, &decl, location, is_external, artificial,
925
location_is_constant_data, static_member);
926
927
return var_sp;
928
}
929
930
lldb::VariableSP
931
SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id,
932
const CVSymbol &cvs) {
933
TpiStream &tpi = m_index->tpi();
934
ConstantSym constant(cvs.kind());
935
936
llvm::cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(cvs, constant));
937
std::string global_name("::");
938
global_name += constant.Name;
939
PdbTypeSymId tid(constant.Type, false);
940
SymbolFileTypeSP type_sp =
941
std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
942
943
Declaration decl;
944
Variable::RangeList ranges;
945
ModuleSP module = GetObjectFile()->GetModule();
946
DWARFExpressionList location(module,
947
MakeConstantLocationExpression(
948
constant.Type, tpi, constant.Value, module),
949
nullptr);
950
951
bool external = false;
952
bool artificial = false;
953
bool location_is_constant_data = true;
954
bool static_member = false;
955
VariableSP var_sp = std::make_shared<Variable>(
956
toOpaqueUid(var_id), constant.Name.str().c_str(), global_name.c_str(),
957
type_sp, eValueTypeVariableGlobal, module.get(), ranges, &decl, location,
958
external, artificial, location_is_constant_data, static_member);
959
return var_sp;
960
}
961
962
VariableSP
963
SymbolFileNativePDB::GetOrCreateGlobalVariable(PdbGlobalSymId var_id) {
964
auto emplace_result = m_global_vars.try_emplace(toOpaqueUid(var_id), nullptr);
965
if (emplace_result.second) {
966
if (VariableSP var_sp = CreateGlobalVariable(var_id))
967
emplace_result.first->second = var_sp;
968
else
969
return nullptr;
970
}
971
972
return emplace_result.first->second;
973
}
974
975
lldb::TypeSP SymbolFileNativePDB::GetOrCreateType(TypeIndex ti) {
976
return GetOrCreateType(PdbTypeSymId(ti, false));
977
}
978
979
FunctionSP SymbolFileNativePDB::GetOrCreateFunction(PdbCompilandSymId func_id,
980
CompileUnit &comp_unit) {
981
auto emplace_result = m_functions.try_emplace(toOpaqueUid(func_id), nullptr);
982
if (emplace_result.second)
983
emplace_result.first->second = CreateFunction(func_id, comp_unit);
984
985
return emplace_result.first->second;
986
}
987
988
CompUnitSP
989
SymbolFileNativePDB::GetOrCreateCompileUnit(const CompilandIndexItem &cci) {
990
991
auto emplace_result =
992
m_compilands.try_emplace(toOpaqueUid(cci.m_id), nullptr);
993
if (emplace_result.second)
994
emplace_result.first->second = CreateCompileUnit(cci);
995
996
lldbassert(emplace_result.first->second);
997
return emplace_result.first->second;
998
}
999
1000
Block &SymbolFileNativePDB::GetOrCreateBlock(PdbCompilandSymId block_id) {
1001
auto iter = m_blocks.find(toOpaqueUid(block_id));
1002
if (iter != m_blocks.end())
1003
return *iter->second;
1004
1005
return CreateBlock(block_id);
1006
}
1007
1008
void SymbolFileNativePDB::ParseDeclsForContext(
1009
lldb_private::CompilerDeclContext decl_ctx) {
1010
TypeSystem* ts_or_err = decl_ctx.GetTypeSystem();
1011
if (!ts_or_err)
1012
return;
1013
PdbAstBuilder* ast_builder = ts_or_err->GetNativePDBParser();
1014
clang::DeclContext *context = ast_builder->FromCompilerDeclContext(decl_ctx);
1015
if (!context)
1016
return;
1017
ast_builder->ParseDeclsForContext(*context);
1018
}
1019
1020
lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) {
1021
if (index >= GetNumCompileUnits())
1022
return CompUnitSP();
1023
lldbassert(index < UINT16_MAX);
1024
if (index >= UINT16_MAX)
1025
return nullptr;
1026
1027
CompilandIndexItem &item = m_index->compilands().GetOrCreateCompiland(index);
1028
1029
return GetOrCreateCompileUnit(item);
1030
}
1031
1032
lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) {
1033
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1034
PdbSymUid uid(comp_unit.GetID());
1035
lldbassert(uid.kind() == PdbSymUidKind::Compiland);
1036
1037
CompilandIndexItem *item =
1038
m_index->compilands().GetCompiland(uid.asCompiland().modi);
1039
lldbassert(item);
1040
if (!item->m_compile_opts)
1041
return lldb::eLanguageTypeUnknown;
1042
1043
return TranslateLanguage(item->m_compile_opts->getLanguage());
1044
}
1045
1046
void SymbolFileNativePDB::AddSymbols(Symtab &symtab) {}
1047
1048
size_t SymbolFileNativePDB::ParseFunctions(CompileUnit &comp_unit) {
1049
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1050
PdbSymUid uid{comp_unit.GetID()};
1051
lldbassert(uid.kind() == PdbSymUidKind::Compiland);
1052
uint16_t modi = uid.asCompiland().modi;
1053
CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(modi);
1054
1055
size_t count = comp_unit.GetNumFunctions();
1056
const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
1057
for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
1058
if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32)
1059
continue;
1060
1061
PdbCompilandSymId sym_id{modi, iter.offset()};
1062
1063
FunctionSP func = GetOrCreateFunction(sym_id, comp_unit);
1064
}
1065
1066
size_t new_count = comp_unit.GetNumFunctions();
1067
lldbassert(new_count >= count);
1068
return new_count - count;
1069
}
1070
1071
static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) {
1072
// If any of these flags are set, we need to resolve the compile unit.
1073
uint32_t flags = eSymbolContextCompUnit;
1074
flags |= eSymbolContextVariable;
1075
flags |= eSymbolContextFunction;
1076
flags |= eSymbolContextBlock;
1077
flags |= eSymbolContextLineEntry;
1078
return (resolve_scope & flags) != 0;
1079
}
1080
1081
uint32_t SymbolFileNativePDB::ResolveSymbolContext(
1082
const Address &addr, SymbolContextItem resolve_scope, SymbolContext &sc) {
1083
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1084
uint32_t resolved_flags = 0;
1085
lldb::addr_t file_addr = addr.GetFileAddress();
1086
1087
if (NeedsResolvedCompileUnit(resolve_scope)) {
1088
std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr);
1089
if (!modi)
1090
return 0;
1091
CompUnitSP cu_sp = GetCompileUnitAtIndex(*modi);
1092
if (!cu_sp)
1093
return 0;
1094
1095
sc.comp_unit = cu_sp.get();
1096
resolved_flags |= eSymbolContextCompUnit;
1097
}
1098
1099
if (resolve_scope & eSymbolContextFunction ||
1100
resolve_scope & eSymbolContextBlock) {
1101
lldbassert(sc.comp_unit);
1102
std::vector<SymbolAndUid> matches = m_index->FindSymbolsByVa(file_addr);
1103
// Search the matches in reverse. This way if there are multiple matches
1104
// (for example we are 3 levels deep in a nested scope) it will find the
1105
// innermost one first.
1106
for (const auto &match : llvm::reverse(matches)) {
1107
if (match.uid.kind() != PdbSymUidKind::CompilandSym)
1108
continue;
1109
1110
PdbCompilandSymId csid = match.uid.asCompilandSym();
1111
CVSymbol cvs = m_index->ReadSymbolRecord(csid);
1112
PDB_SymType type = CVSymToPDBSym(cvs.kind());
1113
if (type != PDB_SymType::Function && type != PDB_SymType::Block)
1114
continue;
1115
if (type == PDB_SymType::Function) {
1116
sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get();
1117
if (sc.function) {
1118
Block &block = sc.function->GetBlock(true);
1119
addr_t func_base =
1120
sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
1121
addr_t offset = file_addr - func_base;
1122
sc.block = block.FindInnermostBlockByOffset(offset);
1123
}
1124
}
1125
1126
if (type == PDB_SymType::Block) {
1127
Block &block = GetOrCreateBlock(csid);
1128
sc.function = block.CalculateSymbolContextFunction();
1129
if (sc.function) {
1130
sc.function->GetBlock(true);
1131
addr_t func_base =
1132
sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
1133
addr_t offset = file_addr - func_base;
1134
sc.block = block.FindInnermostBlockByOffset(offset);
1135
}
1136
}
1137
if (sc.function)
1138
resolved_flags |= eSymbolContextFunction;
1139
if (sc.block)
1140
resolved_flags |= eSymbolContextBlock;
1141
break;
1142
}
1143
}
1144
1145
if (resolve_scope & eSymbolContextLineEntry) {
1146
lldbassert(sc.comp_unit);
1147
if (auto *line_table = sc.comp_unit->GetLineTable()) {
1148
if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
1149
resolved_flags |= eSymbolContextLineEntry;
1150
}
1151
}
1152
1153
return resolved_flags;
1154
}
1155
1156
uint32_t SymbolFileNativePDB::ResolveSymbolContext(
1157
const SourceLocationSpec &src_location_spec,
1158
lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
1159
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1160
const uint32_t prev_size = sc_list.GetSize();
1161
if (resolve_scope & eSymbolContextCompUnit) {
1162
for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus;
1163
++cu_idx) {
1164
CompileUnit *cu = ParseCompileUnitAtIndex(cu_idx).get();
1165
if (!cu)
1166
continue;
1167
1168
bool file_spec_matches_cu_file_spec = FileSpec::Match(
1169
src_location_spec.GetFileSpec(), cu->GetPrimaryFile());
1170
if (file_spec_matches_cu_file_spec) {
1171
cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);
1172
break;
1173
}
1174
}
1175
}
1176
return sc_list.GetSize() - prev_size;
1177
}
1178
1179
bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) {
1180
// Unfortunately LLDB is set up to parse the entire compile unit line table
1181
// all at once, even if all it really needs is line info for a specific
1182
// function. In the future it would be nice if it could set the sc.m_function
1183
// member, and we could only get the line info for the function in question.
1184
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1185
PdbSymUid cu_id(comp_unit.GetID());
1186
lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);
1187
uint16_t modi = cu_id.asCompiland().modi;
1188
CompilandIndexItem *cii = m_index->compilands().GetCompiland(modi);
1189
lldbassert(cii);
1190
1191
// Parse DEBUG_S_LINES subsections first, then parse all S_INLINESITE records
1192
// in this CU. Add line entries into the set first so that if there are line
1193
// entries with same addres, the later is always more accurate than the
1194
// former.
1195
std::set<LineTable::Entry, LineTableEntryComparator> line_set;
1196
1197
// This is basically a copy of the .debug$S subsections from all original COFF
1198
// object files merged together with address relocations applied. We are
1199
// looking for all DEBUG_S_LINES subsections.
1200
for (const DebugSubsectionRecord &dssr :
1201
cii->m_debug_stream.getSubsectionsArray()) {
1202
if (dssr.kind() != DebugSubsectionKind::Lines)
1203
continue;
1204
1205
DebugLinesSubsectionRef lines;
1206
llvm::BinaryStreamReader reader(dssr.getRecordData());
1207
if (auto EC = lines.initialize(reader)) {
1208
llvm::consumeError(std::move(EC));
1209
return false;
1210
}
1211
1212
const LineFragmentHeader *lfh = lines.header();
1213
uint64_t virtual_addr =
1214
m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset);
1215
if (virtual_addr == LLDB_INVALID_ADDRESS)
1216
continue;
1217
1218
for (const LineColumnEntry &group : lines) {
1219
llvm::Expected<uint32_t> file_index_or_err =
1220
GetFileIndex(*cii, group.NameIndex);
1221
if (!file_index_or_err)
1222
continue;
1223
uint32_t file_index = file_index_or_err.get();
1224
lldbassert(!group.LineNumbers.empty());
1225
CompilandIndexItem::GlobalLineTable::Entry line_entry(
1226
LLDB_INVALID_ADDRESS, 0);
1227
for (const LineNumberEntry &entry : group.LineNumbers) {
1228
LineInfo cur_info(entry.Flags);
1229
1230
if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto())
1231
continue;
1232
1233
uint64_t addr = virtual_addr + entry.Offset;
1234
1235
bool is_statement = cur_info.isStatement();
1236
bool is_prologue = IsFunctionPrologue(*cii, addr);
1237
bool is_epilogue = IsFunctionEpilogue(*cii, addr);
1238
1239
uint32_t lno = cur_info.getStartLine();
1240
1241
LineTable::Entry new_entry(addr, lno, 0, file_index, is_statement, false,
1242
is_prologue, is_epilogue, false);
1243
// Terminal entry has lower precedence than new entry.
1244
auto iter = line_set.find(new_entry);
1245
if (iter != line_set.end() && iter->is_terminal_entry)
1246
line_set.erase(iter);
1247
line_set.insert(new_entry);
1248
1249
if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {
1250
line_entry.SetRangeEnd(addr);
1251
cii->m_global_line_table.Append(line_entry);
1252
}
1253
line_entry.SetRangeBase(addr);
1254
line_entry.data = {file_index, lno};
1255
}
1256
LineInfo last_line(group.LineNumbers.back().Flags);
1257
line_set.emplace(virtual_addr + lfh->CodeSize, last_line.getEndLine(), 0,
1258
file_index, false, false, false, false, true);
1259
1260
if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {
1261
line_entry.SetRangeEnd(virtual_addr + lfh->CodeSize);
1262
cii->m_global_line_table.Append(line_entry);
1263
}
1264
}
1265
}
1266
1267
cii->m_global_line_table.Sort();
1268
1269
// Parse all S_INLINESITE in this CU.
1270
const CVSymbolArray &syms = cii->m_debug_stream.getSymbolArray();
1271
for (auto iter = syms.begin(); iter != syms.end();) {
1272
if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) {
1273
++iter;
1274
continue;
1275
}
1276
1277
uint32_t record_offset = iter.offset();
1278
CVSymbol func_record =
1279
cii->m_debug_stream.readSymbolAtOffset(record_offset);
1280
SegmentOffsetLength sol = GetSegmentOffsetAndLength(func_record);
1281
addr_t file_vm_addr =
1282
m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);
1283
if (file_vm_addr == LLDB_INVALID_ADDRESS)
1284
continue;
1285
1286
AddressRange func_range(file_vm_addr, sol.length,
1287
comp_unit.GetModule()->GetSectionList());
1288
Address func_base = func_range.GetBaseAddress();
1289
PdbCompilandSymId func_id{modi, record_offset};
1290
1291
// Iterate all S_INLINESITEs in the function.
1292
auto parse_inline_sites = [&](SymbolKind kind, PdbCompilandSymId id) {
1293
if (kind != S_INLINESITE)
1294
return false;
1295
1296
ParseInlineSite(id, func_base);
1297
1298
for (const auto &line_entry :
1299
m_inline_sites[toOpaqueUid(id)]->line_entries) {
1300
// If line_entry is not terminal entry, remove previous line entry at
1301
// the same address and insert new one. Terminal entry inside an inline
1302
// site might not be terminal entry for its parent.
1303
if (!line_entry.is_terminal_entry)
1304
line_set.erase(line_entry);
1305
line_set.insert(line_entry);
1306
}
1307
// No longer useful after adding to line_set.
1308
m_inline_sites[toOpaqueUid(id)]->line_entries.clear();
1309
return true;
1310
};
1311
ParseSymbolArrayInScope(func_id, parse_inline_sites);
1312
// Jump to the end of the function record.
1313
iter = syms.at(getScopeEndOffset(func_record));
1314
}
1315
1316
cii->m_global_line_table.Clear();
1317
1318
// Add line entries in line_set to line_table.
1319
auto line_table = std::make_unique<LineTable>(&comp_unit);
1320
std::unique_ptr<LineSequence> sequence(
1321
line_table->CreateLineSequenceContainer());
1322
for (const auto &line_entry : line_set) {
1323
line_table->AppendLineEntryToSequence(
1324
sequence.get(), line_entry.file_addr, line_entry.line,
1325
line_entry.column, line_entry.file_idx,
1326
line_entry.is_start_of_statement, line_entry.is_start_of_basic_block,
1327
line_entry.is_prologue_end, line_entry.is_epilogue_begin,
1328
line_entry.is_terminal_entry);
1329
}
1330
line_table->InsertSequence(sequence.get());
1331
1332
if (line_table->GetSize() == 0)
1333
return false;
1334
1335
comp_unit.SetLineTable(line_table.release());
1336
return true;
1337
}
1338
1339
bool SymbolFileNativePDB::ParseDebugMacros(CompileUnit &comp_unit) {
1340
// PDB doesn't contain information about macros
1341
return false;
1342
}
1343
1344
llvm::Expected<uint32_t>
1345
SymbolFileNativePDB::GetFileIndex(const CompilandIndexItem &cii,
1346
uint32_t file_id) {
1347
if (!cii.m_strings.hasChecksums() || !cii.m_strings.hasStrings())
1348
return llvm::make_error<RawError>(raw_error_code::no_entry);
1349
1350
const auto &checksums = cii.m_strings.checksums().getArray();
1351
const auto &strings = cii.m_strings.strings();
1352
// Indices in this structure are actually offsets of records in the
1353
// DEBUG_S_FILECHECKSUMS subsection. Those entries then have an index
1354
// into the global PDB string table.
1355
auto iter = checksums.at(file_id);
1356
if (iter == checksums.end())
1357
return llvm::make_error<RawError>(raw_error_code::no_entry);
1358
1359
llvm::Expected<llvm::StringRef> efn = strings.getString(iter->FileNameOffset);
1360
if (!efn) {
1361
return efn.takeError();
1362
}
1363
1364
// LLDB wants the index of the file in the list of support files.
1365
auto fn_iter = llvm::find(cii.m_file_list, *efn);
1366
if (fn_iter != cii.m_file_list.end())
1367
return std::distance(cii.m_file_list.begin(), fn_iter);
1368
return llvm::make_error<RawError>(raw_error_code::no_entry);
1369
}
1370
1371
bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit,
1372
SupportFileList &support_files) {
1373
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1374
PdbSymUid cu_id(comp_unit.GetID());
1375
lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);
1376
CompilandIndexItem *cci =
1377
m_index->compilands().GetCompiland(cu_id.asCompiland().modi);
1378
lldbassert(cci);
1379
1380
for (llvm::StringRef f : cci->m_file_list) {
1381
FileSpec::Style style =
1382
f.starts_with("/") ? FileSpec::Style::posix : FileSpec::Style::windows;
1383
FileSpec spec(f, style);
1384
support_files.Append(spec);
1385
}
1386
return true;
1387
}
1388
1389
bool SymbolFileNativePDB::ParseImportedModules(
1390
const SymbolContext &sc, std::vector<SourceModule> &imported_modules) {
1391
// PDB does not yet support module debug info
1392
return false;
1393
}
1394
1395
void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id,
1396
Address func_addr) {
1397
lldb::user_id_t opaque_uid = toOpaqueUid(id);
1398
if (m_inline_sites.contains(opaque_uid))
1399
return;
1400
1401
addr_t func_base = func_addr.GetFileAddress();
1402
CompilandIndexItem *cii = m_index->compilands().GetCompiland(id.modi);
1403
CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(id.offset);
1404
CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
1405
1406
InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind()));
1407
cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site));
1408
PdbCompilandSymId parent_id(id.modi, inline_site.Parent);
1409
1410
std::shared_ptr<InlineSite> inline_site_sp =
1411
std::make_shared<InlineSite>(parent_id);
1412
1413
// Get the inlined function declaration info.
1414
auto iter = cii->m_inline_map.find(inline_site.Inlinee);
1415
if (iter == cii->m_inline_map.end())
1416
return;
1417
InlineeSourceLine inlinee_line = iter->second;
1418
1419
const SupportFileList &files = comp_unit->GetSupportFiles();
1420
FileSpec decl_file;
1421
llvm::Expected<uint32_t> file_index_or_err =
1422
GetFileIndex(*cii, inlinee_line.Header->FileID);
1423
if (!file_index_or_err)
1424
return;
1425
uint32_t file_offset = file_index_or_err.get();
1426
decl_file = files.GetFileSpecAtIndex(file_offset);
1427
uint32_t decl_line = inlinee_line.Header->SourceLineNum;
1428
std::unique_ptr<Declaration> decl_up =
1429
std::make_unique<Declaration>(decl_file, decl_line);
1430
1431
// Parse range and line info.
1432
uint32_t code_offset = 0;
1433
int32_t line_offset = 0;
1434
std::optional<uint32_t> code_offset_base;
1435
std::optional<uint32_t> code_offset_end;
1436
std::optional<int32_t> cur_line_offset;
1437
std::optional<int32_t> next_line_offset;
1438
std::optional<uint32_t> next_file_offset;
1439
1440
bool is_terminal_entry = false;
1441
bool is_start_of_statement = true;
1442
// The first instruction is the prologue end.
1443
bool is_prologue_end = true;
1444
1445
auto update_code_offset = [&](uint32_t code_delta) {
1446
if (!code_offset_base)
1447
code_offset_base = code_offset;
1448
else if (!code_offset_end)
1449
code_offset_end = *code_offset_base + code_delta;
1450
};
1451
auto update_line_offset = [&](int32_t line_delta) {
1452
line_offset += line_delta;
1453
if (!code_offset_base || !cur_line_offset)
1454
cur_line_offset = line_offset;
1455
else
1456
next_line_offset = line_offset;
1457
;
1458
};
1459
auto update_file_offset = [&](uint32_t offset) {
1460
if (!code_offset_base)
1461
file_offset = offset;
1462
else
1463
next_file_offset = offset;
1464
};
1465
1466
for (auto &annot : inline_site.annotations()) {
1467
switch (annot.OpCode) {
1468
case BinaryAnnotationsOpCode::CodeOffset:
1469
case BinaryAnnotationsOpCode::ChangeCodeOffset:
1470
case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
1471
code_offset += annot.U1;
1472
update_code_offset(annot.U1);
1473
break;
1474
case BinaryAnnotationsOpCode::ChangeLineOffset:
1475
update_line_offset(annot.S1);
1476
break;
1477
case BinaryAnnotationsOpCode::ChangeCodeLength:
1478
update_code_offset(annot.U1);
1479
code_offset += annot.U1;
1480
is_terminal_entry = true;
1481
break;
1482
case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
1483
code_offset += annot.U1;
1484
update_code_offset(annot.U1);
1485
update_line_offset(annot.S1);
1486
break;
1487
case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
1488
code_offset += annot.U2;
1489
update_code_offset(annot.U2);
1490
update_code_offset(annot.U1);
1491
code_offset += annot.U1;
1492
is_terminal_entry = true;
1493
break;
1494
case BinaryAnnotationsOpCode::ChangeFile:
1495
update_file_offset(annot.U1);
1496
break;
1497
default:
1498
break;
1499
}
1500
1501
// Add range if current range is finished.
1502
if (code_offset_base && code_offset_end && cur_line_offset) {
1503
inline_site_sp->ranges.Append(RangeSourceLineVector::Entry(
1504
*code_offset_base, *code_offset_end - *code_offset_base,
1505
decl_line + *cur_line_offset));
1506
// Set base, end, file offset and line offset for next range.
1507
if (next_file_offset)
1508
file_offset = *next_file_offset;
1509
if (next_line_offset) {
1510
cur_line_offset = next_line_offset;
1511
next_line_offset = std::nullopt;
1512
}
1513
code_offset_base = is_terminal_entry ? std::nullopt : code_offset_end;
1514
code_offset_end = next_file_offset = std::nullopt;
1515
}
1516
if (code_offset_base && cur_line_offset) {
1517
if (is_terminal_entry) {
1518
LineTable::Entry line_entry(
1519
func_base + *code_offset_base, decl_line + *cur_line_offset, 0,
1520
file_offset, false, false, false, false, true);
1521
inline_site_sp->line_entries.push_back(line_entry);
1522
} else {
1523
LineTable::Entry line_entry(func_base + *code_offset_base,
1524
decl_line + *cur_line_offset, 0,
1525
file_offset, is_start_of_statement, false,
1526
is_prologue_end, false, false);
1527
inline_site_sp->line_entries.push_back(line_entry);
1528
is_prologue_end = false;
1529
is_start_of_statement = false;
1530
}
1531
}
1532
if (is_terminal_entry)
1533
is_start_of_statement = true;
1534
is_terminal_entry = false;
1535
}
1536
1537
inline_site_sp->ranges.Sort();
1538
1539
// Get the inlined function callsite info.
1540
std::unique_ptr<Declaration> callsite_up;
1541
if (!inline_site_sp->ranges.IsEmpty()) {
1542
auto *entry = inline_site_sp->ranges.GetEntryAtIndex(0);
1543
addr_t base_offset = entry->GetRangeBase();
1544
if (cii->m_debug_stream.readSymbolAtOffset(parent_id.offset).kind() ==
1545
S_INLINESITE) {
1546
// Its parent is another inline site, lookup parent site's range vector
1547
// for callsite line.
1548
ParseInlineSite(parent_id, func_base);
1549
std::shared_ptr<InlineSite> parent_site =
1550
m_inline_sites[toOpaqueUid(parent_id)];
1551
FileSpec &parent_decl_file =
1552
parent_site->inline_function_info->GetDeclaration().GetFile();
1553
if (auto *parent_entry =
1554
parent_site->ranges.FindEntryThatContains(base_offset)) {
1555
callsite_up =
1556
std::make_unique<Declaration>(parent_decl_file, parent_entry->data);
1557
}
1558
} else {
1559
// Its parent is a function, lookup global line table for callsite.
1560
if (auto *entry = cii->m_global_line_table.FindEntryThatContains(
1561
func_base + base_offset)) {
1562
const FileSpec &callsite_file =
1563
files.GetFileSpecAtIndex(entry->data.first);
1564
callsite_up =
1565
std::make_unique<Declaration>(callsite_file, entry->data.second);
1566
}
1567
}
1568
}
1569
1570
// Get the inlined function name.
1571
CVType inlinee_cvt = m_index->ipi().getType(inline_site.Inlinee);
1572
std::string inlinee_name;
1573
if (inlinee_cvt.kind() == LF_MFUNC_ID) {
1574
MemberFuncIdRecord mfr;
1575
cantFail(
1576
TypeDeserializer::deserializeAs<MemberFuncIdRecord>(inlinee_cvt, mfr));
1577
LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
1578
inlinee_name.append(std::string(types.getTypeName(mfr.ClassType)));
1579
inlinee_name.append("::");
1580
inlinee_name.append(mfr.getName().str());
1581
} else if (inlinee_cvt.kind() == LF_FUNC_ID) {
1582
FuncIdRecord fir;
1583
cantFail(TypeDeserializer::deserializeAs<FuncIdRecord>(inlinee_cvt, fir));
1584
TypeIndex parent_idx = fir.getParentScope();
1585
if (!parent_idx.isNoneType()) {
1586
LazyRandomTypeCollection &ids = m_index->ipi().typeCollection();
1587
inlinee_name.append(std::string(ids.getTypeName(parent_idx)));
1588
inlinee_name.append("::");
1589
}
1590
inlinee_name.append(fir.getName().str());
1591
}
1592
inline_site_sp->inline_function_info = std::make_shared<InlineFunctionInfo>(
1593
inlinee_name.c_str(), llvm::StringRef(), decl_up.get(),
1594
callsite_up.get());
1595
1596
m_inline_sites[opaque_uid] = inline_site_sp;
1597
}
1598
1599
size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) {
1600
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1601
PdbCompilandSymId func_id = PdbSymUid(func.GetID()).asCompilandSym();
1602
// After we iterate through inline sites inside the function, we already get
1603
// all the info needed, removing from the map to save memory.
1604
std::set<uint64_t> remove_uids;
1605
auto parse_blocks = [&](SymbolKind kind, PdbCompilandSymId id) {
1606
if (kind == S_GPROC32 || kind == S_LPROC32 || kind == S_BLOCK32 ||
1607
kind == S_INLINESITE) {
1608
GetOrCreateBlock(id);
1609
if (kind == S_INLINESITE)
1610
remove_uids.insert(toOpaqueUid(id));
1611
return true;
1612
}
1613
return false;
1614
};
1615
size_t count = ParseSymbolArrayInScope(func_id, parse_blocks);
1616
for (uint64_t uid : remove_uids) {
1617
m_inline_sites.erase(uid);
1618
}
1619
return count;
1620
}
1621
1622
size_t SymbolFileNativePDB::ParseSymbolArrayInScope(
1623
PdbCompilandSymId parent_id,
1624
llvm::function_ref<bool(SymbolKind, PdbCompilandSymId)> fn) {
1625
CompilandIndexItem *cii = m_index->compilands().GetCompiland(parent_id.modi);
1626
CVSymbolArray syms =
1627
cii->m_debug_stream.getSymbolArrayForScope(parent_id.offset);
1628
1629
size_t count = 1;
1630
for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
1631
PdbCompilandSymId child_id(parent_id.modi, iter.offset());
1632
if (fn(iter->kind(), child_id))
1633
++count;
1634
}
1635
1636
return count;
1637
}
1638
1639
void SymbolFileNativePDB::DumpClangAST(Stream &s) {
1640
auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
1641
if (!ts_or_err)
1642
return;
1643
auto ts = *ts_or_err;
1644
TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
1645
if (!clang)
1646
return;
1647
clang->GetNativePDBParser()->Dump(s);
1648
}
1649
1650
void SymbolFileNativePDB::FindGlobalVariables(
1651
ConstString name, const CompilerDeclContext &parent_decl_ctx,
1652
uint32_t max_matches, VariableList &variables) {
1653
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1654
using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
1655
1656
std::vector<SymbolAndOffset> results = m_index->globals().findRecordsByName(
1657
name.GetStringRef(), m_index->symrecords());
1658
for (const SymbolAndOffset &result : results) {
1659
switch (result.second.kind()) {
1660
case SymbolKind::S_GDATA32:
1661
case SymbolKind::S_LDATA32:
1662
case SymbolKind::S_GTHREAD32:
1663
case SymbolKind::S_LTHREAD32:
1664
case SymbolKind::S_CONSTANT: {
1665
PdbGlobalSymId global(result.first, false);
1666
if (VariableSP var = GetOrCreateGlobalVariable(global))
1667
variables.AddVariable(var);
1668
break;
1669
}
1670
default:
1671
continue;
1672
}
1673
}
1674
}
1675
1676
void SymbolFileNativePDB::FindFunctions(
1677
const Module::LookupInfo &lookup_info,
1678
const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
1679
SymbolContextList &sc_list) {
1680
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1681
ConstString name = lookup_info.GetLookupName();
1682
FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
1683
if (name_type_mask & eFunctionNameTypeFull)
1684
name = lookup_info.GetName();
1685
1686
// For now we only support lookup by method name or full name.
1687
if (!(name_type_mask & eFunctionNameTypeFull ||
1688
name_type_mask & eFunctionNameTypeMethod))
1689
return;
1690
1691
using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
1692
1693
std::vector<SymbolAndOffset> matches = m_index->globals().findRecordsByName(
1694
name.GetStringRef(), m_index->symrecords());
1695
for (const SymbolAndOffset &match : matches) {
1696
if (match.second.kind() != S_PROCREF && match.second.kind() != S_LPROCREF)
1697
continue;
1698
ProcRefSym proc(match.second.kind());
1699
cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(match.second, proc));
1700
1701
if (!IsValidRecord(proc))
1702
continue;
1703
1704
CompilandIndexItem &cci =
1705
m_index->compilands().GetOrCreateCompiland(proc.modi());
1706
SymbolContext sc;
1707
1708
sc.comp_unit = GetOrCreateCompileUnit(cci).get();
1709
PdbCompilandSymId func_id(proc.modi(), proc.SymOffset);
1710
sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get();
1711
1712
sc_list.Append(sc);
1713
}
1714
}
1715
1716
void SymbolFileNativePDB::FindFunctions(const RegularExpression &regex,
1717
bool include_inlines,
1718
SymbolContextList &sc_list) {}
1719
1720
void SymbolFileNativePDB::FindTypes(const lldb_private::TypeQuery &query,
1721
lldb_private::TypeResults &results) {
1722
1723
// Make sure we haven't already searched this SymbolFile before.
1724
if (results.AlreadySearched(this))
1725
return;
1726
1727
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1728
1729
std::vector<TypeIndex> matches =
1730
m_index->tpi().findRecordsByName(query.GetTypeBasename().GetStringRef());
1731
1732
for (TypeIndex type_idx : matches) {
1733
TypeSP type_sp = GetOrCreateType(type_idx);
1734
if (!type_sp)
1735
continue;
1736
1737
// We resolved a type. Get the fully qualified name to ensure it matches.
1738
ConstString name = type_sp->GetQualifiedName();
1739
TypeQuery type_match(name.GetStringRef(), TypeQueryOptions::e_exact_match);
1740
if (query.ContextMatches(type_match.GetContextRef())) {
1741
results.InsertUnique(type_sp);
1742
if (results.Done(query))
1743
return;
1744
}
1745
}
1746
}
1747
1748
void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name,
1749
uint32_t max_matches,
1750
TypeMap &types) {
1751
1752
std::vector<TypeIndex> matches = m_index->tpi().findRecordsByName(name);
1753
if (max_matches > 0 && max_matches < matches.size())
1754
matches.resize(max_matches);
1755
1756
for (TypeIndex ti : matches) {
1757
TypeSP type = GetOrCreateType(ti);
1758
if (!type)
1759
continue;
1760
1761
types.Insert(type);
1762
}
1763
}
1764
1765
size_t SymbolFileNativePDB::ParseTypes(CompileUnit &comp_unit) {
1766
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1767
// Only do the full type scan the first time.
1768
if (m_done_full_type_scan)
1769
return 0;
1770
1771
const size_t old_count = GetTypeList().GetSize();
1772
LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
1773
1774
// First process the entire TPI stream.
1775
for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
1776
TypeSP type = GetOrCreateType(*ti);
1777
if (type)
1778
(void)type->GetFullCompilerType();
1779
}
1780
1781
// Next look for S_UDT records in the globals stream.
1782
for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
1783
PdbGlobalSymId global{gid, false};
1784
CVSymbol sym = m_index->ReadSymbolRecord(global);
1785
if (sym.kind() != S_UDT)
1786
continue;
1787
1788
UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
1789
bool is_typedef = true;
1790
if (IsTagRecord(PdbTypeSymId{udt.Type, false}, m_index->tpi())) {
1791
CVType cvt = m_index->tpi().getType(udt.Type);
1792
llvm::StringRef name = CVTagRecord::create(cvt).name();
1793
if (name == udt.Name)
1794
is_typedef = false;
1795
}
1796
1797
if (is_typedef)
1798
GetOrCreateTypedef(global);
1799
}
1800
1801
const size_t new_count = GetTypeList().GetSize();
1802
1803
m_done_full_type_scan = true;
1804
1805
return new_count - old_count;
1806
}
1807
1808
size_t
1809
SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit,
1810
VariableList &variables) {
1811
PdbSymUid sym_uid(comp_unit.GetID());
1812
lldbassert(sym_uid.kind() == PdbSymUidKind::Compiland);
1813
return 0;
1814
}
1815
1816
VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
1817
PdbCompilandSymId var_id,
1818
bool is_param) {
1819
ModuleSP module = GetObjectFile()->GetModule();
1820
Block &block = GetOrCreateBlock(scope_id);
1821
// Get function block.
1822
Block *func_block = &block;
1823
while (func_block->GetParent()) {
1824
func_block = func_block->GetParent();
1825
}
1826
Address addr;
1827
func_block->GetStartAddress(addr);
1828
VariableInfo var_info =
1829
GetVariableLocationInfo(*m_index, var_id, *func_block, module);
1830
Function *func = func_block->CalculateSymbolContextFunction();
1831
if (!func)
1832
return nullptr;
1833
// Use empty dwarf expr if optimized away so that it won't be filtered out
1834
// when lookuping local variables in this scope.
1835
if (!var_info.location.IsValid())
1836
var_info.location = DWARFExpressionList(module, DWARFExpression(), nullptr);
1837
var_info.location.SetFuncFileAddress(
1838
func->GetAddressRange().GetBaseAddress().GetFileAddress());
1839
CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
1840
CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
1841
TypeSP type_sp = GetOrCreateType(var_info.type);
1842
if (!type_sp)
1843
return nullptr;
1844
std::string name = var_info.name.str();
1845
Declaration decl;
1846
SymbolFileTypeSP sftype =
1847
std::make_shared<SymbolFileType>(*this, type_sp->GetID());
1848
1849
is_param |= var_info.is_param;
1850
ValueType var_scope =
1851
is_param ? eValueTypeVariableArgument : eValueTypeVariableLocal;
1852
bool external = false;
1853
bool artificial = false;
1854
bool location_is_constant_data = false;
1855
bool static_member = false;
1856
Variable::RangeList scope_ranges;
1857
VariableSP var_sp = std::make_shared<Variable>(
1858
toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope,
1859
&block, scope_ranges, &decl, var_info.location, external, artificial,
1860
location_is_constant_data, static_member);
1861
if (!is_param) {
1862
auto ts_or_err = GetTypeSystemForLanguage(comp_unit_sp->GetLanguage());
1863
if (auto err = ts_or_err.takeError())
1864
return nullptr;
1865
auto ts = *ts_or_err;
1866
if (!ts)
1867
return nullptr;
1868
1869
ts->GetNativePDBParser()->GetOrCreateVariableDecl(scope_id, var_id);
1870
}
1871
m_local_variables[toOpaqueUid(var_id)] = var_sp;
1872
return var_sp;
1873
}
1874
1875
VariableSP SymbolFileNativePDB::GetOrCreateLocalVariable(
1876
PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param) {
1877
auto iter = m_local_variables.find(toOpaqueUid(var_id));
1878
if (iter != m_local_variables.end())
1879
return iter->second;
1880
1881
return CreateLocalVariable(scope_id, var_id, is_param);
1882
}
1883
1884
TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
1885
CVSymbol sym = m_index->ReadSymbolRecord(id);
1886
lldbassert(sym.kind() == SymbolKind::S_UDT);
1887
1888
UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
1889
1890
TypeSP target_type = GetOrCreateType(udt.Type);
1891
1892
auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
1893
if (auto err = ts_or_err.takeError())
1894
return nullptr;
1895
auto ts = *ts_or_err;
1896
if (!ts)
1897
return nullptr;
1898
1899
ts->GetNativePDBParser()->GetOrCreateTypedefDecl(id);
1900
1901
Declaration decl;
1902
return MakeType(
1903
toOpaqueUid(id), ConstString(udt.Name), target_type->GetByteSize(nullptr),
1904
nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID,
1905
decl, target_type->GetForwardCompilerType(),
1906
lldb_private::Type::ResolveState::Forward);
1907
}
1908
1909
TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) {
1910
auto iter = m_types.find(toOpaqueUid(id));
1911
if (iter != m_types.end())
1912
return iter->second;
1913
1914
return CreateTypedef(id);
1915
}
1916
1917
size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) {
1918
Block &block = GetOrCreateBlock(block_id);
1919
1920
size_t count = 0;
1921
1922
CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
1923
CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
1924
uint32_t params_remaining = 0;
1925
switch (sym.kind()) {
1926
case S_GPROC32:
1927
case S_LPROC32: {
1928
ProcSym proc(static_cast<SymbolRecordKind>(sym.kind()));
1929
cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym, proc));
1930
CVType signature = m_index->tpi().getType(proc.FunctionType);
1931
if (signature.kind() == LF_PROCEDURE) {
1932
ProcedureRecord sig;
1933
if (llvm::Error e = TypeDeserializer::deserializeAs<ProcedureRecord>(
1934
signature, sig)) {
1935
llvm::consumeError(std::move(e));
1936
return 0;
1937
}
1938
params_remaining = sig.getParameterCount();
1939
} else if (signature.kind() == LF_MFUNCTION) {
1940
MemberFunctionRecord sig;
1941
if (llvm::Error e = TypeDeserializer::deserializeAs<MemberFunctionRecord>(
1942
signature, sig)) {
1943
llvm::consumeError(std::move(e));
1944
return 0;
1945
}
1946
params_remaining = sig.getParameterCount();
1947
} else
1948
return 0;
1949
break;
1950
}
1951
case S_BLOCK32:
1952
break;
1953
case S_INLINESITE:
1954
break;
1955
default:
1956
lldbassert(false && "Symbol is not a block!");
1957
return 0;
1958
}
1959
1960
VariableListSP variables = block.GetBlockVariableList(false);
1961
if (!variables) {
1962
variables = std::make_shared<VariableList>();
1963
block.SetVariableList(variables);
1964
}
1965
1966
CVSymbolArray syms = limitSymbolArrayToScope(
1967
cii->m_debug_stream.getSymbolArray(), block_id.offset);
1968
1969
// Skip the first record since it's a PROC32 or BLOCK32, and there's
1970
// no point examining it since we know it's not a local variable.
1971
syms.drop_front();
1972
auto iter = syms.begin();
1973
auto end = syms.end();
1974
1975
while (iter != end) {
1976
uint32_t record_offset = iter.offset();
1977
CVSymbol variable_cvs = *iter;
1978
PdbCompilandSymId child_sym_id(block_id.modi, record_offset);
1979
++iter;
1980
1981
// If this is a block or inline site, recurse into its children and then
1982
// skip it.
1983
if (variable_cvs.kind() == S_BLOCK32 ||
1984
variable_cvs.kind() == S_INLINESITE) {
1985
uint32_t block_end = getScopeEndOffset(variable_cvs);
1986
count += ParseVariablesForBlock(child_sym_id);
1987
iter = syms.at(block_end);
1988
continue;
1989
}
1990
1991
bool is_param = params_remaining > 0;
1992
VariableSP variable;
1993
switch (variable_cvs.kind()) {
1994
case S_REGREL32:
1995
case S_REGISTER:
1996
case S_LOCAL:
1997
variable = GetOrCreateLocalVariable(block_id, child_sym_id, is_param);
1998
if (is_param)
1999
--params_remaining;
2000
if (variable)
2001
variables->AddVariableIfUnique(variable);
2002
break;
2003
default:
2004
break;
2005
}
2006
}
2007
2008
// Pass false for set_children, since we call this recursively so that the
2009
// children will call this for themselves.
2010
block.SetDidParseVariables(true, false);
2011
2012
return count;
2013
}
2014
2015
size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) {
2016
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2017
lldbassert(sc.function || sc.comp_unit);
2018
2019
VariableListSP variables;
2020
if (sc.block) {
2021
PdbSymUid block_id(sc.block->GetID());
2022
2023
size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
2024
return count;
2025
}
2026
2027
if (sc.function) {
2028
PdbSymUid block_id(sc.function->GetID());
2029
2030
size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
2031
return count;
2032
}
2033
2034
if (sc.comp_unit) {
2035
variables = sc.comp_unit->GetVariableList(false);
2036
if (!variables) {
2037
variables = std::make_shared<VariableList>();
2038
sc.comp_unit->SetVariableList(variables);
2039
}
2040
return ParseVariablesForCompileUnit(*sc.comp_unit, *variables);
2041
}
2042
2043
llvm_unreachable("Unreachable!");
2044
}
2045
2046
CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) {
2047
auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
2048
if (auto err = ts_or_err.takeError())
2049
return CompilerDecl();
2050
auto ts = *ts_or_err;
2051
if (!ts)
2052
return {};
2053
2054
if (auto decl = ts->GetNativePDBParser()->GetOrCreateDeclForUid(uid))
2055
return *decl;
2056
return CompilerDecl();
2057
}
2058
2059
CompilerDeclContext
2060
SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) {
2061
auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
2062
if (auto err = ts_or_err.takeError())
2063
return {};
2064
auto ts = *ts_or_err;
2065
if (!ts)
2066
return {};
2067
2068
PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
2069
clang::DeclContext *context =
2070
ast_builder->GetOrCreateDeclContextForUid(PdbSymUid(uid));
2071
if (!context)
2072
return {};
2073
2074
return ast_builder->ToCompilerDeclContext(*context);
2075
}
2076
2077
CompilerDeclContext
2078
SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
2079
auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
2080
if (auto err = ts_or_err.takeError())
2081
return CompilerDeclContext();
2082
auto ts = *ts_or_err;
2083
if (!ts)
2084
return {};
2085
2086
PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
2087
clang::DeclContext *context = ast_builder->GetParentDeclContext(PdbSymUid(uid));
2088
if (!context)
2089
return CompilerDeclContext();
2090
return ast_builder->ToCompilerDeclContext(*context);
2091
}
2092
2093
Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
2094
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2095
auto iter = m_types.find(type_uid);
2096
// lldb should not be passing us non-sensical type uids. the only way it
2097
// could have a type uid in the first place is if we handed it out, in which
2098
// case we should know about the type. However, that doesn't mean we've
2099
// instantiated it yet. We can vend out a UID for a future type. So if the
2100
// type doesn't exist, let's instantiate it now.
2101
if (iter != m_types.end())
2102
return &*iter->second;
2103
2104
PdbSymUid uid(type_uid);
2105
lldbassert(uid.kind() == PdbSymUidKind::Type);
2106
PdbTypeSymId type_id = uid.asTypeSym();
2107
if (type_id.index.isNoneType())
2108
return nullptr;
2109
2110
TypeSP type_sp = CreateAndCacheType(type_id);
2111
if (!type_sp)
2112
return nullptr;
2113
return &*type_sp;
2114
}
2115
2116
std::optional<SymbolFile::ArrayInfo>
2117
SymbolFileNativePDB::GetDynamicArrayInfoForUID(
2118
lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
2119
return std::nullopt;
2120
}
2121
2122
bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) {
2123
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2124
auto ts = compiler_type.GetTypeSystem();
2125
auto clang_type_system = ts.dyn_cast_or_null<TypeSystemClang>();
2126
if (!clang_type_system)
2127
return false;
2128
2129
PdbAstBuilder *ast_builder =
2130
static_cast<PdbAstBuilder *>(clang_type_system->GetNativePDBParser());
2131
if (ast_builder &&
2132
ast_builder->GetClangASTImporter().CanImport(compiler_type))
2133
return ast_builder->GetClangASTImporter().CompleteType(compiler_type);
2134
clang::QualType qt =
2135
clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType());
2136
2137
return ast_builder->CompleteType(qt);
2138
}
2139
2140
void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
2141
TypeClass type_mask,
2142
lldb_private::TypeList &type_list) {}
2143
2144
CompilerDeclContext SymbolFileNativePDB::FindNamespace(
2145
ConstString name, const CompilerDeclContext &parent_decl_ctx, bool) {
2146
return {};
2147
}
2148
2149
llvm::Expected<lldb::TypeSystemSP>
2150
SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
2151
auto type_system_or_err =
2152
m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language);
2153
if (type_system_or_err)
2154
if (auto ts = *type_system_or_err)
2155
ts->SetSymbolFile(this);
2156
return type_system_or_err;
2157
}
2158
2159
uint64_t SymbolFileNativePDB::GetDebugInfoSize(bool load_all_debug_info) {
2160
// PDB files are a separate file that contains all debug info.
2161
return m_index->pdb().getFileSize();
2162
}
2163
2164
void SymbolFileNativePDB::BuildParentMap() {
2165
LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
2166
2167
llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full;
2168
llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward;
2169
2170
struct RecordIndices {
2171
TypeIndex forward;
2172
TypeIndex full;
2173
};
2174
2175
llvm::StringMap<RecordIndices> record_indices;
2176
2177
for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
2178
CVType type = types.getType(*ti);
2179
if (!IsTagRecord(type))
2180
continue;
2181
2182
CVTagRecord tag = CVTagRecord::create(type);
2183
2184
RecordIndices &indices = record_indices[tag.asTag().getUniqueName()];
2185
if (tag.asTag().isForwardRef())
2186
indices.forward = *ti;
2187
else
2188
indices.full = *ti;
2189
2190
if (indices.full != TypeIndex::None() &&
2191
indices.forward != TypeIndex::None()) {
2192
forward_to_full[indices.forward] = indices.full;
2193
full_to_forward[indices.full] = indices.forward;
2194
}
2195
2196
// We're looking for LF_NESTTYPE records in the field list, so ignore
2197
// forward references (no field list), and anything without a nested class
2198
// (since there won't be any LF_NESTTYPE records).
2199
if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass())
2200
continue;
2201
2202
struct ProcessTpiStream : public TypeVisitorCallbacks {
2203
ProcessTpiStream(PdbIndex &index, TypeIndex parent,
2204
const CVTagRecord &parent_cvt,
2205
llvm::DenseMap<TypeIndex, TypeIndex> &parents)
2206
: index(index), parents(parents), parent(parent),
2207
parent_cvt(parent_cvt) {}
2208
2209
PdbIndex &index;
2210
llvm::DenseMap<TypeIndex, TypeIndex> &parents;
2211
2212
unsigned unnamed_type_index = 1;
2213
TypeIndex parent;
2214
const CVTagRecord &parent_cvt;
2215
2216
llvm::Error visitKnownMember(CVMemberRecord &CVR,
2217
NestedTypeRecord &Record) override {
2218
std::string unnamed_type_name;
2219
if (Record.Name.empty()) {
2220
unnamed_type_name =
2221
llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str();
2222
Record.Name = unnamed_type_name;
2223
++unnamed_type_index;
2224
}
2225
std::optional<CVTagRecord> tag =
2226
GetNestedTagDefinition(Record, parent_cvt, index.tpi());
2227
if (!tag)
2228
return llvm::ErrorSuccess();
2229
2230
parents[Record.Type] = parent;
2231
return llvm::ErrorSuccess();
2232
}
2233
};
2234
2235
CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList);
2236
ProcessTpiStream process(*m_index, *ti, tag, m_parent_types);
2237
FieldListRecord field_list;
2238
if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
2239
field_list_cvt, field_list))
2240
llvm::consumeError(std::move(error));
2241
if (llvm::Error error = visitMemberRecordStream(field_list.Data, process))
2242
llvm::consumeError(std::move(error));
2243
}
2244
2245
// Now that we know the forward -> full mapping of all type indices, we can
2246
// re-write all the indices. At the end of this process, we want a mapping
2247
// consisting of fwd -> full and full -> full for all child -> parent indices.
2248
// We can re-write the values in place, but for the keys, we must save them
2249
// off so that we don't modify the map in place while also iterating it.
2250
std::vector<TypeIndex> full_keys;
2251
std::vector<TypeIndex> fwd_keys;
2252
for (auto &entry : m_parent_types) {
2253
TypeIndex key = entry.first;
2254
TypeIndex value = entry.second;
2255
2256
auto iter = forward_to_full.find(value);
2257
if (iter != forward_to_full.end())
2258
entry.second = iter->second;
2259
2260
iter = forward_to_full.find(key);
2261
if (iter != forward_to_full.end())
2262
fwd_keys.push_back(key);
2263
else
2264
full_keys.push_back(key);
2265
}
2266
for (TypeIndex fwd : fwd_keys) {
2267
TypeIndex full = forward_to_full[fwd];
2268
TypeIndex parent_idx = m_parent_types[fwd];
2269
m_parent_types[full] = parent_idx;
2270
}
2271
for (TypeIndex full : full_keys) {
2272
TypeIndex fwd = full_to_forward[full];
2273
m_parent_types[fwd] = m_parent_types[full];
2274
}
2275
}
2276
2277
std::optional<PdbCompilandSymId>
2278
SymbolFileNativePDB::FindSymbolScope(PdbCompilandSymId id) {
2279
CVSymbol sym = m_index->ReadSymbolRecord(id);
2280
if (symbolOpensScope(sym.kind())) {
2281
// If this exact symbol opens a scope, we can just directly access its
2282
// parent.
2283
id.offset = getScopeParentOffset(sym);
2284
// Global symbols have parent offset of 0. Return std::nullopt to indicate
2285
// this.
2286
if (id.offset == 0)
2287
return std::nullopt;
2288
return id;
2289
}
2290
2291
// Otherwise we need to start at the beginning and iterate forward until we
2292
// reach (or pass) this particular symbol
2293
CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(id.modi);
2294
const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
2295
2296
auto begin = syms.begin();
2297
auto end = syms.at(id.offset);
2298
std::vector<PdbCompilandSymId> scope_stack;
2299
2300
while (begin != end) {
2301
if (begin.offset() > id.offset) {
2302
// We passed it. We couldn't even find this symbol record.
2303
lldbassert(false && "Invalid compiland symbol id!");
2304
return std::nullopt;
2305
}
2306
2307
// We haven't found the symbol yet. Check if we need to open or close the
2308
// scope stack.
2309
if (symbolOpensScope(begin->kind())) {
2310
// We can use the end offset of the scope to determine whether or not
2311
// we can just outright skip this entire scope.
2312
uint32_t scope_end = getScopeEndOffset(*begin);
2313
if (scope_end < id.offset) {
2314
begin = syms.at(scope_end);
2315
} else {
2316
// The symbol we're looking for is somewhere in this scope.
2317
scope_stack.emplace_back(id.modi, begin.offset());
2318
}
2319
} else if (symbolEndsScope(begin->kind())) {
2320
scope_stack.pop_back();
2321
}
2322
++begin;
2323
}
2324
if (scope_stack.empty())
2325
return std::nullopt;
2326
// We have a match! Return the top of the stack
2327
return scope_stack.back();
2328
}
2329
2330
std::optional<llvm::codeview::TypeIndex>
2331
SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) {
2332
auto parent_iter = m_parent_types.find(ti);
2333
if (parent_iter == m_parent_types.end())
2334
return std::nullopt;
2335
return parent_iter->second;
2336
}
2337
2338