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