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
16#include "lldb/Core/Module.h"
26#include "lldb/Utility/Log.h"
27
28#include "llvm/ADT/DenseMap.h"
29#include "llvm/ADT/STLExtras.h"
30#include "llvm/ADT/SmallVector.h"
31#include "llvm/DebugInfo/CodeView/CVRecord.h"
32#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
33#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
34#include "llvm/DebugInfo/CodeView/Formatters.h"
35#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
36#include "llvm/DebugInfo/CodeView/RecordName.h"
37#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
38#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
39#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
40#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
41#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
42#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
43#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
44#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
45#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
46#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
47#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
48#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
49#include "llvm/DebugInfo/PDB/PDB.h"
50#include "llvm/DebugInfo/PDB/PDBTypes.h"
51#include "llvm/Demangle/MicrosoftDemangle.h"
52#include "llvm/Object/COFF.h"
53#include "llvm/Support/Allocator.h"
54#include "llvm/Support/BinaryStreamReader.h"
55#include "llvm/Support/Error.h"
56#include "llvm/Support/ErrorOr.h"
57#include "llvm/Support/MemoryBuffer.h"
58
60#include "PdbSymUid.h"
61#include "PdbUtil.h"
62#include "UdtRecordCompleter.h"
63#include <optional>
64#include <string_view>
65
66using namespace lldb;
67using namespace lldb_private;
68using namespace npdb;
69using namespace llvm::codeview;
70using namespace llvm::pdb;
71
73
75 switch (lang) {
76 case PDB_Lang::Cpp:
78 case PDB_Lang::C:
80 case PDB_Lang::Swift:
82 case PDB_Lang::Rust:
84 case PDB_Lang::ObjC:
86 case PDB_Lang::ObjCpp:
88 default:
90 }
91}
92
93static std::optional<std::string>
94findMatchingPDBFilePath(llvm::StringRef original_pdb_path,
95 llvm::StringRef exe_path) {
96 const FileSystem &fs = FileSystem::Instance();
97
98 if (fs.Exists(original_pdb_path))
99 return std::string(original_pdb_path);
100
101 const auto exe_dir = FileSpec(exe_path).CopyByRemovingLastPathComponent();
102 // While the exe_path uses the native style, the exe might be compiled on a
103 // different OS, so try to guess the style used.
104 const FileSpec original_pdb_spec(original_pdb_path,
105 FileSpec::GuessPathStyle(original_pdb_path)
106 .value_or(FileSpec::Style::native));
107 const llvm::StringRef pdb_filename = original_pdb_spec.GetFilename();
108
109 // If the file doesn't exist, perhaps the path specified at build time
110 // doesn't match the PDB's current location, so check the location of the
111 // executable.
112 const FileSpec local_pdb = exe_dir.CopyByAppendingPathComponent(pdb_filename);
113 if (fs.Exists(local_pdb))
114 return local_pdb.GetPath();
115
116 // Otherwise, search for one in target.debug-file-search-paths
118 for (const FileSpec &search_dir : search_paths) {
119 FileSpec pdb_path = search_dir.CopyByAppendingPathComponent(pdb_filename);
120 if (fs.Exists(pdb_path))
121 return pdb_path.GetPath();
122 }
123
124 return std::nullopt;
125}
126
127static std::unique_ptr<PDBFile>
128loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
129 // Try to find a matching PDB for an EXE.
130 using namespace llvm::object;
131 auto expected_binary = createBinary(exe_path);
132
133 // If the file isn't a PE/COFF executable, fail.
134 if (!expected_binary) {
135 llvm::consumeError(expected_binary.takeError());
136 return nullptr;
137 }
138 OwningBinary<Binary> binary = std::move(*expected_binary);
139
140 // TODO: Avoid opening the PE/COFF binary twice by reading this information
141 // directly from the lldb_private::ObjectFile.
142 auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary());
143 if (!obj)
144 return nullptr;
145 const llvm::codeview::DebugInfo *pdb_info = nullptr;
146
147 // If it doesn't have a debug directory, fail.
148 llvm::StringRef pdb_file;
149 if (llvm::Error e = obj->getDebugPDBInfo(pdb_info, pdb_file)) {
150 consumeError(std::move(e));
151 return nullptr;
152 }
153
154 std::optional<std::string> resolved_pdb_path =
155 findMatchingPDBFilePath(pdb_file, exe_path);
156 if (!resolved_pdb_path)
157 return nullptr;
158
159 // If the file is not a PDB or if it doesn't have a matching GUID, fail.
160 auto pdb =
161 ObjectFilePDB::loadPDBFile(*std::move(resolved_pdb_path), allocator);
162 if (!pdb)
163 return nullptr;
164
165 auto expected_info = pdb->getPDBInfoStream();
166 if (!expected_info) {
167 llvm::consumeError(expected_info.takeError());
168 return nullptr;
169 }
170 llvm::codeview::GUID guid;
171 memcpy(&guid, pdb_info->PDB70.Signature, 16);
172
173 if (expected_info->getGuid() != guid)
174 return nullptr;
175
176 return pdb;
177}
178
180 lldb::addr_t addr) {
181 // FIXME: Implement this.
182 return false;
183}
184
186 lldb::addr_t addr) {
187 // FIXME: Implement this.
188 return false;
189}
190
191// See llvm::codeview::TypeIndex::simpleTypeName as well as strForPrimitiveTi
192// from the original pdbdump:
193// https://github.com/microsoft/microsoft-pdb/blob/805655a28bd8198004be2ac27e6e0290121a5e89/pdbdump/pdbdump.cpp#L1896-L1974
194//
195// For 64bit integers we use "long long" like DIA instead of "__int64".
196static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) {
197 switch (kind) {
198 case SimpleTypeKind::Boolean128:
199 return "__bool128";
200 case SimpleTypeKind::Boolean64:
201 return "__bool64";
202 case SimpleTypeKind::Boolean32:
203 return "__bool32";
204 case SimpleTypeKind::Boolean16:
205 return "__bool16";
206 case SimpleTypeKind::Boolean8:
207 return "bool";
208
209 case SimpleTypeKind::Byte:
210 case SimpleTypeKind::UnsignedCharacter:
211 return "unsigned char";
212 case SimpleTypeKind::NarrowCharacter:
213 return "char";
214 case SimpleTypeKind::SignedCharacter:
215 case SimpleTypeKind::SByte:
216 return "signed char";
217 case SimpleTypeKind::Character32:
218 return "char32_t";
219 case SimpleTypeKind::Character16:
220 return "char16_t";
221 case SimpleTypeKind::Character8:
222 return "char8_t";
223
224 case SimpleTypeKind::Complex128:
225 return "_Complex __float128";
226 case SimpleTypeKind::Complex80:
227 return "_Complex long double";
228 case SimpleTypeKind::Complex64:
229 return "_Complex double";
230 case SimpleTypeKind::Complex48:
231 return "_Complex __float48";
232 case SimpleTypeKind::Complex32:
233 case SimpleTypeKind::Complex32PartialPrecision:
234 return "_Complex float";
235 case SimpleTypeKind::Complex16:
236 return "_Complex _Float16";
237
238 case SimpleTypeKind::Float128:
239 return "__float128";
240 case SimpleTypeKind::Float80:
241 return "long double";
242 case SimpleTypeKind::Float64:
243 return "double";
244 case SimpleTypeKind::Float48:
245 return "__float48";
246 case SimpleTypeKind::Float32:
247 case SimpleTypeKind::Float32PartialPrecision:
248 return "float";
249 case SimpleTypeKind::Float16:
250 return "_Float16";
251
252 case SimpleTypeKind::Int128Oct:
253 case SimpleTypeKind::Int128:
254 return "__int128";
255 case SimpleTypeKind::Int64:
256 case SimpleTypeKind::Int64Quad:
257 return "long long";
258 case SimpleTypeKind::Int32Long:
259 return "long";
260 case SimpleTypeKind::Int32:
261 return "int";
262 case SimpleTypeKind::Int16:
263 case SimpleTypeKind::Int16Short:
264 return "short";
265
266 case SimpleTypeKind::UInt128Oct:
267 case SimpleTypeKind::UInt128:
268 return "unsigned __int128";
269 case SimpleTypeKind::UInt64:
270 case SimpleTypeKind::UInt64Quad:
271 return "unsigned long long";
272 case SimpleTypeKind::UInt32:
273 return "unsigned";
274 case SimpleTypeKind::UInt16:
275 case SimpleTypeKind::UInt16Short:
276 return "unsigned short";
277 case SimpleTypeKind::UInt32Long:
278 return "unsigned long";
279
280 case SimpleTypeKind::HResult:
281 return "HRESULT";
282 case SimpleTypeKind::Void:
283 return "void";
284 case SimpleTypeKind::WideCharacter:
285 return "wchar_t";
286
287 case SimpleTypeKind::None:
288 case SimpleTypeKind::NotTranslated:
289 return "";
290 }
291 return "";
292}
293
294static bool IsClassRecord(TypeLeafKind kind) {
295 switch (kind) {
296 case LF_STRUCTURE:
297 case LF_CLASS:
298 case LF_INTERFACE:
299 return true;
300 default:
301 return false;
302 }
303}
304
305static std::optional<CVTagRecord>
306GetNestedTagDefinition(const NestedTypeRecord &Record,
307 const CVTagRecord &parent, TpiStream &tpi) {
308 // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it
309 // is also used to indicate the primary definition of a nested class. That is
310 // to say, if you have:
311 // struct A {
312 // struct B {};
313 // using C = B;
314 // };
315 // Then in the debug info, this will appear as:
316 // LF_STRUCTURE `A::B` [type index = N]
317 // LF_STRUCTURE `A`
318 // LF_NESTTYPE [name = `B`, index = N]
319 // LF_NESTTYPE [name = `C`, index = N]
320 // In order to accurately reconstruct the decl context hierarchy, we need to
321 // know which ones are actual definitions and which ones are just aliases.
322
323 // If it's a simple type, then this is something like `using foo = int`.
324 if (Record.Type.isSimple())
325 return std::nullopt;
326
327 CVType cvt = tpi.getType(Record.Type);
328
329 if (!IsTagRecord(cvt))
330 return std::nullopt;
331
332 // If it's an inner definition, then treat whatever name we have here as a
333 // single component of a mangled name. So we can inject it into the parent's
334 // mangled name to see if it matches.
335 CVTagRecord child = CVTagRecord::create(cvt);
336 std::string qname = std::string(parent.asTag().getUniqueName());
337 if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4)
338 return std::nullopt;
339
340 // qname[3] is the tag type identifier (struct, class, union, etc). Since the
341 // inner tag type is not necessarily the same as the outer tag type, re-write
342 // it to match the inner tag type.
343 qname[3] = child.asTag().getUniqueName()[3];
344 std::string piece;
345 if (qname[3] == 'W')
346 piece = "4";
347 piece += Record.Name;
348 piece.push_back('@');
349 qname.insert(4, std::move(piece));
350 if (qname != child.asTag().UniqueName)
351 return std::nullopt;
352
353 return std::move(child);
354}
355
361
365
367
369 return "Microsoft PDB debug symbol cross-platform file reader.";
370}
371
374 return nullptr;
375
376 return new SymbolFileNativePDB(std::move(objfile_sp));
377}
378
381
383
385 uint32_t abilities = 0;
386 if (!m_objfile_sp)
387 return 0;
388
389 if (!m_index) {
390 // Lazily load and match the PDB file, but only do this once.
391 PDBFile *pdb_file;
392 if (auto *pdb = llvm::dyn_cast<ObjectFilePDB>(m_objfile_sp.get())) {
393 pdb_file = &pdb->GetPDBFile();
394 } else {
395 m_file_up = loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(),
397 pdb_file = m_file_up.get();
398 }
399
400 if (!pdb_file)
401 return 0;
402
403 LLDB_LOG(
404 GetLog(LLDBLog::Symbols), "Loading {0} for {1}",
405 pdb_file->getFilePath(),
406 m_objfile_sp->GetModule()->GetObjectFile()->GetFileSpec().GetPath());
407
408 auto expected_index = PdbIndex::create(pdb_file);
409 if (!expected_index) {
410 llvm::consumeError(expected_index.takeError());
411 return 0;
412 }
413 m_index = std::move(*expected_index);
414 }
415 if (!m_index)
416 return 0;
417
418 // We don't especially have to be precise here. We only distinguish between
419 // stripped and not stripped.
420 abilities = kAllAbilities;
421
422 if (m_index->dbi().isStripped())
423 abilities &= ~(Blocks | LocalVariables);
424 return abilities;
425}
426
428 m_obj_load_address = m_objfile_sp->GetModule()
429 ->GetObjectFile()
430 ->GetBaseAddress()
431 .GetFileAddress();
432 m_index->SetLoadAddress(m_obj_load_address);
433 m_index->ParseSectionContribs();
434
435 auto ts_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage(
437 if (auto err = ts_or_err.takeError()) {
438 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
439 "Failed to initialize: {0}");
440 } else {
441 if (auto ts = *ts_or_err)
442 ts->SetSymbolFile(this);
443 }
444}
445
447 const DbiModuleList &modules = m_index->dbi().modules();
448 uint32_t count = modules.getModuleCount();
449 if (count == 0)
450 return count;
451
452 // The linker can inject an additional "dummy" compilation unit into the
453 // PDB. Ignore this special compile unit for our purposes, if it is there.
454 // It is always the last one.
455 DbiModuleDescriptor last = modules.getModuleDescriptor(count - 1);
456 if (last.getModuleName() == "* Linker *")
457 --count;
458 return count;
459}
460
462 CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
463 CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
464 CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
465 lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id);
466 auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
467 if (auto err = ts_or_err.takeError())
468 return nullptr;
469 auto ts = *ts_or_err;
470 if (!ts)
471 return nullptr;
472 PdbAstBuilder* ast_builder = ts->GetNativePDBParser();
473
474 switch (sym.kind()) {
475 case S_GPROC32:
476 case S_LPROC32:
477 // This is a function. It must be global. Creating the Function entry
478 // for it automatically creates a block for it.
479 if (FunctionSP func = GetOrCreateFunction(block_id, *comp_unit))
480 return &func->GetBlock(false);
481 break;
482 case S_BLOCK32: {
483 // This is a block. Its parent is either a function or another block. In
484 // either case, its parent can be viewed as a block (e.g. a function
485 // contains 1 big block. So just get the parent block and add this block
486 // to it.
487 BlockSym block(static_cast<SymbolRecordKind>(sym.kind()));
488 if (auto err = SymbolDeserializer::deserializeAs<BlockSym>(sym, block)) {
489 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
490 "Failed to deserialize BlockSym record: {0}");
491 return nullptr;
492 }
493 if (block.Parent == 0) {
494 LLDB_LOG(GetLog(LLDBLog::Symbols), "BlockSym record ({0}) with parent=0",
495 block_id);
496 return nullptr;
497 }
498 PdbCompilandSymId parent_id(block_id.modi, block.Parent);
499 Block *parent_block = GetOrCreateBlock(parent_id);
500 if (!parent_block)
501 return nullptr;
502 Function *func = parent_block->CalculateSymbolContextFunction();
503 if (!func) {
504 LLDB_LOG(GetLog(LLDBLog::Symbols), "parent of {0} is not a function",
505 parent_id);
506 return nullptr;
507 }
508 lldb::addr_t block_base =
509 m_index->MakeVirtualAddress(block.Segment, block.CodeOffset);
510 lldb::addr_t func_base = func->GetAddress().GetFileAddress();
511 BlockSP child_block = parent_block->CreateChild(opaque_block_uid);
512 if (block_base >= func_base)
513 child_block->AddRange(Block::Range(block_base - func_base, block.CodeSize));
514 else {
515 GetObjectFile()->GetModule()->ReportError(
516 "S_BLOCK32 at modi: {0:d} offset: {1:d}: adding range "
517 "[{2:x16}-{3:x16}) which has a base that is less than the "
518 "function's "
519 "low PC 0x%" PRIx64 ". Please file a bug and attach the file at the "
520 "start of this error message",
521 block_id.modi, block_id.offset, block_base,
522 block_base + block.CodeSize, func_base);
523 }
524 if (ast_builder)
525 ast_builder->EnsureBlock(block_id);
526 m_blocks.insert({opaque_block_uid, child_block});
527 break;
528 }
529 case S_INLINESITE: {
530 // This ensures line table is parsed first so we have inline sites info.
531 comp_unit->GetLineTable();
532
533 std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid];
534 Block *parent_block = GetOrCreateBlock(inline_site->parent_id);
535 if (!parent_block)
536 return nullptr;
537 BlockSP child_block = parent_block->CreateChild(opaque_block_uid);
538 if (ast_builder)
539 ast_builder->EnsureInlinedFunction(block_id);
540 // Copy ranges from InlineSite to Block.
541 for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) {
542 auto *entry = inline_site->ranges.GetEntryAtIndex(i);
543 child_block->AddRange(
544 Block::Range(entry->GetRangeBase(), entry->GetByteSize()));
545 }
546 child_block->FinalizeRanges();
547
548 // Get the inlined function callsite info.
549 Declaration &decl = inline_site->inline_function_info->GetDeclaration();
550 Declaration &callsite = inline_site->inline_function_info->GetCallSite();
551 child_block->SetInlinedFunctionInfo(
552 inline_site->inline_function_info->GetName().GetCString(), nullptr,
553 &decl, &callsite);
554 m_blocks.insert({opaque_block_uid, child_block});
555 break;
556 }
557 default:
558 LLDB_LOG(GetLog(LLDBLog::Symbols), "{0} is not a block", block_id);
559 return nullptr;
560 }
561
562 return nullptr;
563}
564
566 CompileUnit &comp_unit) {
567 const CompilandIndexItem *cci =
568 m_index->compilands().GetCompiland(func_id.modi);
569 if (!cci) {
570 LLDB_LOG(GetLog(LLDBLog::Symbols), "missing compiland {0}", func_id.modi);
571 return nullptr;
572 }
573
574 CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);
575 if (sym_record.kind() != S_LPROC32 && sym_record.kind() != S_GPROC32) {
576 LLDB_LOG(GetLog(LLDBLog::Symbols), "{0} is not a function", func_id);
577 return nullptr;
578 }
579
581
582 auto file_vm_addr =
583 m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);
584 if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
585 return nullptr;
586
587 Address func_addr(file_vm_addr, comp_unit.GetModule()->GetSectionList());
588 if (!func_addr.IsValid())
589 return nullptr;
590
591 ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
592 if (auto err = SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc)) {
593 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
594 "Failed to deserialize ProcSym record: {0}");
595 return nullptr;
596 }
597 if (proc.FunctionType == TypeIndex::None())
598 return nullptr;
599 TypeSP func_type = GetOrCreateType(proc.FunctionType);
600 if (!func_type)
601 return nullptr;
602
603 PdbTypeSymId sig_id(proc.FunctionType, false);
604
605 std::optional<llvm::StringRef> mangled_opt = FindMangledSymbol(
606 SegmentOffset(proc.Segment, proc.CodeOffset), proc.FunctionType);
607 Mangled mangled(mangled_opt.value_or(proc.Name));
608
609 FunctionSP func_sp = std::make_shared<Function>(
610 &comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled,
611 func_type.get(), func_addr,
612 AddressRanges{AddressRange(func_addr, sol.length)});
613
614 comp_unit.AddFunction(func_sp);
615
616 auto ts_or_err = GetTypeSystemForLanguage(comp_unit.GetLanguage());
617 if (auto err = ts_or_err.takeError())
618 return func_sp;
619 auto ts = *ts_or_err;
620 if (ts) {
621 if (PdbAstBuilder *ast_builder = ts->GetNativePDBParser())
622 ast_builder->EnsureFunction(func_id);
623 }
624
625 return func_sp;
626}
627
630 lldb::LanguageType lang =
631 cci.m_compile_opts ? TranslateLanguage(cci.m_compile_opts->getLanguage())
633
634 LazyBool optimized = eLazyBoolNo;
635 if (cci.m_compile_opts && cci.m_compile_opts->hasOptimizations())
636 optimized = eLazyBoolYes;
637
638 llvm::SmallString<64> source_file_name;
639 if (auto main_file_or_err = m_index->compilands().GetMainSourceFile(cci)) {
640 source_file_name = std::move(*main_file_or_err);
641 } else {
642 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), main_file_or_err.takeError(),
643 "Failed to determine main source file: {0}");
644 }
645 FileSpec fs(llvm::sys::path::convert_to_slash(
646 source_file_name, llvm::sys::path::Style::windows_backslash));
647
648 CompUnitSP cu_sp = std::make_shared<CompileUnit>(
649 m_objfile_sp->GetModule(), nullptr, std::make_shared<SupportFile>(fs),
650 toOpaqueUid(cci.m_id), lang, optimized);
651
652 SetCompileUnitAtIndex(cci.m_id.modi, cu_sp);
653 return cu_sp;
654}
655
657 const ModifierRecord &mr,
658 CompilerType ct) {
659 TpiStream &stream = m_index->tpi();
660
661 std::string name;
662
663 if ((mr.Modifiers & ModifierOptions::Const) != ModifierOptions::None)
664 name += "const ";
665 if ((mr.Modifiers & ModifierOptions::Volatile) != ModifierOptions::None)
666 name += "volatile ";
667 if ((mr.Modifiers & ModifierOptions::Unaligned) != ModifierOptions::None)
668 name += "__unaligned ";
669
670 if (mr.ModifiedType.isSimple())
671 name += GetSimpleTypeName(mr.ModifiedType.getSimpleKind());
672 else
673 name += computeTypeName(stream.typeCollection(), mr.ModifiedType);
674 Declaration decl;
675 lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType);
676
677 return MakeType(toOpaqueUid(type_id), ConstString(name),
678 llvm::expectedToOptional(modified_type->GetByteSize(nullptr)),
679 nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
681}
682
685 const llvm::codeview::PointerRecord &pr,
686 CompilerType ct) {
687 TypeSP pointee = GetOrCreateType(pr.ReferentType);
688 if (!pointee)
689 return nullptr;
690
691 if (pr.isPointerToMember()) {
692 MemberPointerInfo mpi = pr.getMemberInfo();
693 GetOrCreateType(mpi.ContainingType);
694 }
695
696 Declaration decl;
697 return MakeType(toOpaqueUid(type_id), ConstString(), pr.getSize(), nullptr,
700}
701
703 CompilerType ct) {
704 uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false));
705 if (ti == TypeIndex::NullptrT()) {
706 Declaration decl;
707 return MakeType(uid, ConstString("decltype(nullptr)"), std::nullopt,
708 nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
710 }
711
712 if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
713 TypeSP direct_sp = GetOrCreateType(ti.makeDirect());
714 uint32_t pointer_size = 0;
715 switch (ti.getSimpleMode()) {
716 case SimpleTypeMode::FarPointer32:
717 case SimpleTypeMode::NearPointer32:
718 pointer_size = 4;
719 break;
720 case SimpleTypeMode::NearPointer64:
721 pointer_size = 8;
722 break;
723 default:
724 // 128-bit and 16-bit pointers unsupported.
725 return nullptr;
726 }
727 Declaration decl;
728 return MakeType(uid, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,
730 }
731
732 if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
733 return nullptr;
734
735 size_t size = GetTypeSizeForSimpleKind(ti.getSimpleKind());
736 llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind());
737
738 Declaration decl;
739 return MakeType(uid, ConstString(type_name), size, nullptr, LLDB_INVALID_UID,
741}
742
743static std::string GetUnqualifiedTypeName(const TagRecord &record) {
744 if (!record.hasUniqueName())
745 return std::string(MSVCUndecoratedNameParser::DropScope(record.Name));
746
747 llvm::ms_demangle::Demangler demangler;
748 std::string_view sv(record.UniqueName.begin(), record.UniqueName.size());
749 llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
750 if (demangler.Error)
751 return std::string(MSVCUndecoratedNameParser::DropScope(record.Name));
752
753 llvm::ms_demangle::IdentifierNode *idn =
754 ttn->QualifiedName->getUnqualifiedIdentifier();
755 return idn->toString();
756}
757
760 const TagRecord &record,
761 size_t size, CompilerType ct) {
762
763 std::string uname = GetUnqualifiedTypeName(record);
764
765 llvm::Expected<Declaration> maybeDecl = ResolveUdtDeclaration(type_id);
766 Declaration decl;
767 if (maybeDecl)
768 decl = std::move(*maybeDecl);
769 else
770 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), maybeDecl.takeError(),
771 "Failed to resolve declaration for '{1}': {0}", uname);
772
773 return MakeType(toOpaqueUid(type_id), ConstString(uname), size, nullptr,
776}
777
779 const ClassRecord &cr,
780 CompilerType ct) {
781 return CreateClassStructUnion(type_id, cr, cr.getSize(), ct);
782}
783
785 const UnionRecord &ur,
786 CompilerType ct) {
787 return CreateClassStructUnion(type_id, ur, ur.getSize(), ct);
788}
789
791 const EnumRecord &er,
792 CompilerType ct) {
793 std::string uname = GetUnqualifiedTypeName(er);
794
795 llvm::Expected<Declaration> maybeDecl = ResolveUdtDeclaration(type_id);
796 Declaration decl;
797 if (maybeDecl)
798 decl = std::move(*maybeDecl);
799 else
800 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), maybeDecl.takeError(),
801 "Failed to resolve declaration for '{1}': {0}", uname);
802
803 TypeSP underlying_type = GetOrCreateType(er.UnderlyingType);
804
805 return MakeType(
806 toOpaqueUid(type_id), ConstString(uname),
807 llvm::expectedToOptional(underlying_type->GetByteSize(nullptr)), nullptr,
810}
811
813 const ArrayRecord &ar,
814 CompilerType ct) {
815 TypeSP element_type = GetOrCreateType(ar.ElementType);
816
817 Declaration decl;
818 TypeSP array_sp =
819 MakeType(toOpaqueUid(type_id), ConstString(), ar.Size, nullptr,
822 array_sp->SetEncodingType(element_type.get());
823 return array_sp;
824}
825
827 const MemberFunctionRecord &mfr,
828 CompilerType ct) {
829 if (mfr.ReturnType.isSimple())
830 GetOrCreateType(mfr.ReturnType);
831 CreateSimpleArgumentListTypes(mfr.ArgumentList);
832
833 Declaration decl;
834 return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
837}
838
840 const ProcedureRecord &pr,
841 CompilerType ct) {
842 if (pr.ReturnType.isSimple())
843 GetOrCreateType(pr.ReturnType);
844 CreateSimpleArgumentListTypes(pr.ArgumentList);
845
846 Declaration decl;
847 return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
850}
851
853 llvm::codeview::TypeIndex arglist_ti) {
854 if (arglist_ti.isNoneType())
855 return;
856
857 CVType arglist_cvt = m_index->tpi().getType(arglist_ti);
858 if (arglist_cvt.kind() != LF_ARGLIST)
859 return; // invalid debug info
860
861 ArgListRecord alr;
862 if (auto err =
863 TypeDeserializer::deserializeAs<ArgListRecord>(arglist_cvt, alr)) {
864 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
865 "Failed to deserialize ArgListRecord record ({1}): {0}",
866 arglist_ti);
867 return;
868 }
869 for (TypeIndex id : alr.getIndices())
870 if (!id.isNoneType() && id.isSimple())
871 GetOrCreateType(id);
872}
873
875 if (type_id.index.isSimple())
876 return CreateSimpleType(type_id.index, ct);
877
878 TpiStream &stream = type_id.is_ipi ? m_index->ipi() : m_index->tpi();
879 CVType cvt = stream.getType(type_id.index);
880
881 if (cvt.kind() == LF_MODIFIER) {
882 ModifierRecord modifier;
883 if (auto err =
884 TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier)) {
885 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
886 "Failed to deserialize ModifierRecord record ({1}): {0}",
887 type_id.index);
888 return nullptr;
889 }
890 return CreateModifierType(type_id, modifier, ct);
891 }
892
893 if (cvt.kind() == LF_POINTER) {
894 PointerRecord pointer;
895 if (auto err =
896 TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer)) {
897 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
898 "Failed to deserialize PointerRecord record ({1}): {0}",
899 type_id.index);
900 return nullptr;
901 }
902 return CreatePointerType(type_id, pointer, ct);
903 }
904
905 if (IsClassRecord(cvt.kind())) {
906 ClassRecord cr;
907 if (auto err = TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr)) {
908 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
909 "Failed to deserialize ClassRecord record ({1}): {0}",
910 type_id.index);
911 return nullptr;
912 }
913 return CreateTagType(type_id, cr, ct);
914 }
915
916 if (cvt.kind() == LF_ENUM) {
917 EnumRecord er;
918 if (auto err = TypeDeserializer::deserializeAs<EnumRecord>(cvt, er)) {
919 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
920 "Failed to deserialize EnumRecord record ({1}): {0}",
921 type_id.index);
922 return nullptr;
923 }
924 return CreateTagType(type_id, er, ct);
925 }
926
927 if (cvt.kind() == LF_UNION) {
928 UnionRecord ur;
929 if (auto err = TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur)) {
930 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
931 "Failed to deserialize UnionRecord record ({1}): {0}",
932 type_id.index);
933 return nullptr;
934 }
935 return CreateTagType(type_id, ur, ct);
936 }
937
938 if (cvt.kind() == LF_ARRAY) {
939 ArrayRecord ar;
940 if (auto err = TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar)) {
941 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
942 "Failed to deserialize ArrayRecord record ({1}): {0}",
943 type_id.index);
944 return nullptr;
945 }
946 return CreateArrayType(type_id, ar, ct);
947 }
948
949 if (cvt.kind() == LF_PROCEDURE) {
950 ProcedureRecord pr;
951 if (auto err = TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr)) {
952 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
953 "Failed to deserialize ProcedureRecord record ({1}): {0}",
954 type_id.index);
955 return nullptr;
956 }
957 return CreateProcedureType(type_id, pr, ct);
958 }
959 if (cvt.kind() == LF_MFUNCTION) {
960 MemberFunctionRecord mfr;
961 if (auto err =
962 TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr)) {
964 GetLog(LLDBLog::Symbols), std::move(err),
965 "Failed to deserialize MemberFunctionRecord record ({1}): {0}",
966 type_id.index);
967 return nullptr;
968 }
969 return CreateFunctionType(type_id, mfr, ct);
970 }
971
972 return nullptr;
973}
974
976 // If they search for a UDT which is a forward ref, try and resolve the full
977 // decl and just map the forward ref uid to the full decl record.
978 std::optional<PdbTypeSymId> full_decl_uid;
979 if (IsForwardRefUdt(type_id, m_index->tpi())) {
980 auto expected_full_ti =
981 m_index->tpi().findFullDeclForForwardRef(type_id.index);
982 if (!expected_full_ti)
983 llvm::consumeError(expected_full_ti.takeError());
984 else if (*expected_full_ti != type_id.index) {
985 full_decl_uid = PdbTypeSymId(*expected_full_ti, false);
986
987 // It's possible that a lookup would occur for the full decl causing it
988 // to be cached, then a second lookup would occur for the forward decl.
989 // We don't want to create a second full decl, so make sure the full
990 // decl hasn't already been cached.
991 auto full_iter = m_types.find(toOpaqueUid(*full_decl_uid));
992 if (full_iter != m_types.end()) {
993 TypeSP result = full_iter->second;
994 // Map the forward decl to the TypeSP for the full decl so we can take
995 // the fast path next time.
996 m_types[toOpaqueUid(type_id)] = result;
997 return result;
998 }
999 }
1000 }
1001
1002 PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id;
1004 if (auto err = ts_or_err.takeError())
1005 return nullptr;
1006 auto ts = *ts_or_err;
1007 if (!ts)
1008 return nullptr;
1009 PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
1010 if (!ast_builder)
1011 return nullptr;
1012 CompilerType ct = ast_builder->GetOrCreateType(best_decl_id);
1013 if (!ct)
1014 return nullptr;
1015
1016 TypeSP result = CreateType(best_decl_id, ct);
1017 if (!result)
1018 return nullptr;
1019
1020 uint64_t best_uid = toOpaqueUid(best_decl_id);
1021 m_types[best_uid] = result;
1022 // If we had both a forward decl and a full decl, make both point to the new
1023 // type.
1024 if (full_decl_uid)
1025 m_types[toOpaqueUid(type_id)] = result;
1026
1027 return result;
1028}
1029
1031 // We can't use try_emplace / overwrite here because the process of creating
1032 // a type could create nested types, which could invalidate iterators. So
1033 // we have to do a 2-phase lookup / insert.
1034 auto iter = m_types.find(toOpaqueUid(type_id));
1035 if (iter != m_types.end())
1036 return iter->second;
1037
1038 TypeSP type = CreateAndCacheType(type_id);
1039 if (type)
1040 GetTypeList().Insert(type);
1041 return type;
1042}
1043
1045 CVSymbol sym = m_index->symrecords().readRecord(var_id.offset);
1046 if (sym.kind() == S_CONSTANT)
1047 return CreateConstantSymbol(var_id, sym);
1048
1050 TypeIndex ti;
1051 llvm::StringRef name;
1052 lldb::addr_t addr = 0;
1053 uint16_t section = 0;
1054 uint32_t offset = 0;
1055 bool is_external = false;
1056 switch (sym.kind()) {
1057 case S_GDATA32:
1058 is_external = true;
1059 [[fallthrough]];
1060 case S_LDATA32: {
1061 DataSym ds(sym.kind());
1062 if (auto err = SymbolDeserializer::deserializeAs<DataSym>(sym, ds)) {
1063 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
1064 "Failed to deserialize DataSym record: {0}");
1065 return nullptr;
1066 }
1067 ti = ds.Type;
1068 scope = (sym.kind() == S_GDATA32) ? eValueTypeVariableGlobal
1070 name = ds.Name;
1071 section = ds.Segment;
1072 offset = ds.DataOffset;
1073 addr = m_index->MakeVirtualAddress(ds.Segment, ds.DataOffset);
1074 break;
1075 }
1076 case S_GTHREAD32:
1077 is_external = true;
1078 [[fallthrough]];
1079 case S_LTHREAD32: {
1080 ThreadLocalDataSym tlds(sym.kind());
1081 if (auto err =
1082 SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, tlds)) {
1083 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
1084 "Failed to deserialize ThreadLocalDataSym record: {0}");
1085 return nullptr;
1086 }
1087 ti = tlds.Type;
1088 name = tlds.Name;
1089 section = tlds.Segment;
1090 offset = tlds.DataOffset;
1091 addr = m_index->MakeVirtualAddress(tlds.Segment, tlds.DataOffset);
1093 break;
1094 }
1095 default:
1096 llvm_unreachable("unreachable!");
1097 }
1098
1099 CompUnitSP comp_unit;
1100 std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr);
1101 // Some globals has modi points to the linker module, ignore them.
1102 if (!modi || modi >= GetNumCompileUnits())
1103 return nullptr;
1104
1105 CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(*modi);
1106 comp_unit = GetOrCreateCompileUnit(cci);
1107
1108 Declaration decl;
1109 PdbTypeSymId tid(ti, false);
1110 SymbolFileTypeSP type_sp =
1111 std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
1112 Variable::RangeList ranges;
1113 auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
1114 if (auto err = ts_or_err.takeError())
1115 return nullptr;
1116 auto ts = *ts_or_err;
1117 if (ts) {
1118 if (PdbAstBuilder *ast_builder = ts->GetNativePDBParser())
1119 ast_builder->EnsureVariable(var_id);
1120 }
1121
1122 ModuleSP module_sp = GetObjectFile()->GetModule();
1123 DWARFExpressionList location(
1124 module_sp, MakeGlobalLocationExpression(section, offset, module_sp),
1125 nullptr);
1126
1127 std::string global_name("::");
1128 global_name += name;
1129 bool artificial = false;
1130 bool location_is_constant_data = false;
1131 bool static_member = false;
1132 VariableSP var_sp = std::make_shared<Variable>(
1133 toOpaqueUid(var_id), name.str().c_str(), global_name.c_str(), type_sp,
1134 scope, comp_unit.get(), ranges, &decl, location, is_external, artificial,
1135 location_is_constant_data, static_member);
1136
1137 return var_sp;
1138}
1139
1142 const CVSymbol &cvs) {
1143 TpiStream &tpi = m_index->tpi();
1144 ConstantSym constant(cvs.kind());
1145
1146 if (cvs.kind() != S_CONSTANT)
1147 return nullptr;
1148
1149 if (auto err =
1150 SymbolDeserializer::deserializeAs<ConstantSym>(cvs, constant)) {
1151 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
1152 "Failed to deserialize ConstantSym record: {0}");
1153 return nullptr;
1154 }
1155 std::string global_name("::");
1156 global_name += constant.Name;
1157 PdbTypeSymId tid(constant.Type, false);
1158 SymbolFileTypeSP type_sp =
1159 std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
1160
1161 Declaration decl;
1162 Variable::RangeList ranges;
1163 ModuleSP module = GetObjectFile()->GetModule();
1164 auto location_or_err = MakeConstantLocationExpression(constant.Type, tpi,
1165 constant.Value, module);
1166 if (!location_or_err) {
1167 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), location_or_err.takeError(),
1168 "Failed to make constant location expression for {1}: {0}",
1169 constant.Name);
1170 return nullptr;
1171 }
1172 DWARFExpressionList location(module, std::move(*location_or_err), nullptr);
1173
1174 bool external = false;
1175 bool artificial = false;
1176 bool location_is_constant_data = true;
1177 bool static_member = false;
1178 VariableSP var_sp = std::make_shared<Variable>(
1179 toOpaqueUid(var_id), constant.Name.str().c_str(), global_name.c_str(),
1180 type_sp, eValueTypeVariableGlobal, module.get(), ranges, &decl, location,
1181 external, artificial, location_is_constant_data, static_member);
1182 return var_sp;
1183}
1184
1187 auto emplace_result = m_global_vars.try_emplace(toOpaqueUid(var_id), nullptr);
1188 if (emplace_result.second) {
1189 if (VariableSP var_sp = CreateGlobalVariable(var_id))
1190 emplace_result.first->second = var_sp;
1191 else
1192 return nullptr;
1193 }
1194
1195 return emplace_result.first->second;
1196}
1197
1199 return GetOrCreateType(PdbTypeSymId(ti, false));
1200}
1201
1203 CompileUnit &comp_unit) {
1204 auto emplace_result = m_functions.try_emplace(toOpaqueUid(func_id), nullptr);
1205 if (emplace_result.second)
1206 emplace_result.first->second = CreateFunction(func_id, comp_unit);
1207
1208 return emplace_result.first->second;
1209}
1210
1213
1214 auto emplace_result =
1215 m_compilands.try_emplace(toOpaqueUid(cci.m_id), nullptr);
1216 if (emplace_result.second) {
1217 emplace_result.first->second = CreateCompileUnit(cci);
1218 LLDB_LOG(GetLog(LLDBLog::Symbols), "failed to create compile unit for {0}",
1219 cci.m_id.modi);
1220 }
1221
1222 return emplace_result.first->second;
1223}
1224
1226 auto iter = m_blocks.find(toOpaqueUid(block_id));
1227 if (iter != m_blocks.end())
1228 return iter->second.get();
1229
1230 return CreateBlock(block_id);
1231}
1232
1235 TypeSystem *ts = decl_ctx.GetTypeSystem();
1236 if (!ts)
1237 return;
1238 PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
1239 if (!ast_builder)
1240 return;
1241 ast_builder->ParseDeclsForContext(decl_ctx);
1242}
1243
1245 if (index >= GetNumCompileUnits())
1246 return CompUnitSP();
1247 assert(index < UINT16_MAX && "Invalid compile unit index");
1248 if (index >= UINT16_MAX)
1249 return nullptr;
1250
1251 CompilandIndexItem &item = m_index->compilands().GetOrCreateCompiland(index);
1252
1253 return GetOrCreateCompileUnit(item);
1254}
1255
1257 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1258 PdbSymUid uid(comp_unit.GetID());
1259 if (uid.kind() != PdbSymUidKind::Compiland) {
1260 assert(false && "uid of compile unit not a compiland");
1262 }
1263
1264 CompilandIndexItem *item =
1265 m_index->compilands().GetCompiland(uid.asCompiland().modi);
1266 assert(item);
1267 if (!item || !item->m_compile_opts)
1269
1270 return TranslateLanguage(item->m_compile_opts->getLanguage());
1271}
1272
1274 auto *section_list =
1275 m_objfile_sp->GetModule()->GetObjectFile()->GetSectionList();
1276 if (!section_list)
1277 return;
1278
1279 llvm::DenseMap<lldb::addr_t, llvm::SmallVector<uint32_t, 1>> symbols_by_addr;
1280 for (uint32_t i = 0, n = symtab.GetNumSymbols(); i < n; ++i) {
1281 Symbol *sym = symtab.SymbolAtIndex(i);
1282 if (sym && sym->ValueIsAddress())
1283 symbols_by_addr[sym->GetAddressRef().GetFileAddress()].push_back(i);
1284 }
1285
1286 PublicSym32 last_sym;
1287 size_t last_sym_idx = 0;
1288 lldb::SectionSP section_sp;
1289
1290 // To estimate the size of a symbol, we use the difference to the next symbol.
1291 // If there's no next symbol or the section/segment changed, the symbol will
1292 // take the remaining space. The estimate can be too high in case there's
1293 // padding between symbols. This similar to the algorithm used by the DIA
1294 // SDK.
1295 auto finish_last_symbol = [&](const PublicSym32 *next) {
1296 if (!section_sp)
1297 return;
1298 Symbol *last = symtab.SymbolAtIndex(last_sym_idx);
1299 if (!last)
1300 return;
1301
1302 if (next && last_sym.Segment == next->Segment) {
1303 if (next->Offset < last_sym.Offset) {
1305 "Ignoring size estimate for '{0}': segment {1} offset {2} is "
1306 "greater than the following offset {3}",
1307 last_sym.Name, last_sym.Segment, last_sym.Offset,
1308 next->Offset);
1309 return;
1310 }
1311 last->SetByteSize(next->Offset - last_sym.Offset);
1312 } else {
1313 // the last symbol was the last in its section
1314 if (section_sp->GetByteSize() < last_sym.Offset) {
1316 "Ignoring size estimate for '{0}': segment {1} offset {2} is "
1317 "past the end of section '{3}' (size {4})",
1318 last_sym.Name, last_sym.Segment, last_sym.Offset,
1319 section_sp->GetName(), section_sp->GetByteSize());
1320 return;
1321 }
1322 last->SetByteSize(section_sp->GetByteSize() - last_sym.Offset);
1323 }
1324 };
1325
1326 // The address map is sorted by the address of a symbol.
1327 for (auto pid : m_index->publics().getAddressMap()) {
1328 PdbGlobalSymId global{pid, true};
1329 CVSymbol sym = m_index->ReadSymbolRecord(global);
1330 auto kind = sym.kind();
1331 if (kind != S_PUB32)
1332 continue;
1333 auto pub_or_err = SymbolDeserializer::deserializeAs<PublicSym32>(sym);
1334 if (!pub_or_err) {
1335 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), pub_or_err.takeError(),
1336 "Failed to deserialize PublicSym32 record: {0}");
1337 continue;
1338 }
1339 PublicSym32 pub = std::move(*pub_or_err);
1340 finish_last_symbol(&pub);
1341
1342 if (!section_sp || last_sym.Segment != pub.Segment)
1343 section_sp = section_list->FindSectionByID(pub.Segment);
1344
1345 if (!section_sp)
1346 continue;
1347
1349 if ((pub.Flags & PublicSymFlags::Function) != PublicSymFlags::None ||
1350 (pub.Flags & PublicSymFlags::Code) != PublicSymFlags::None)
1351 type = eSymbolTypeCode;
1352
1353 Symbol pub_symbol(/*symID=*/pid,
1354 /*name=*/pub.Name,
1355 /*type=*/type,
1356 /*external=*/true,
1357 /*is_debug=*/true,
1358 /*is_trampoline=*/false,
1359 /*is_artificial=*/false,
1360 /*section_sp=*/section_sp,
1361 /*value=*/pub.Offset,
1362 /*size=*/0,
1363 /*size_is_valid=*/false,
1364 /*contains_linker_annotations=*/false,
1365 /*flags=*/0);
1366
1367 auto it = symbols_by_addr.find(pub_symbol.GetAddressRef().GetFileAddress());
1368 if (it != symbols_by_addr.end() &&
1369 llvm::any_of(it->second, [&](uint32_t idx) {
1370 Symbol *sym = symtab.SymbolAtIndex(idx);
1371 return sym && sym->GetMangled() == pub_symbol.GetMangled();
1372 }))
1374
1375 last_sym_idx = symtab.AddSymbol(pub_symbol);
1376 last_sym = pub;
1377 }
1378
1379 finish_last_symbol(nullptr);
1380}
1381
1383 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1384 PdbSymUid uid{comp_unit.GetID()};
1385 if (uid.kind() != PdbSymUidKind::Compiland) {
1386 assert(false && "uid of compile unit not a compiland");
1387 return 0;
1388 }
1389 uint16_t modi = uid.asCompiland().modi;
1390 CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(modi);
1391
1392 size_t count = comp_unit.GetNumFunctions();
1393 const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
1394 for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
1395 if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32)
1396 continue;
1397
1398 PdbCompilandSymId sym_id{modi, iter.offset()};
1399
1400 FunctionSP func = GetOrCreateFunction(sym_id, comp_unit);
1401 }
1402
1403 size_t new_count = comp_unit.GetNumFunctions();
1404 if (new_count < count) {
1405 assert(false && "less functions after parsing than before");
1406 return 0;
1407 }
1408 return new_count - count;
1409}
1410
1411static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) {
1412 // If any of these flags are set, we need to resolve the compile unit.
1413 uint32_t flags = eSymbolContextCompUnit;
1414 flags |= eSymbolContextVariable;
1415 flags |= eSymbolContextFunction;
1416 flags |= eSymbolContextBlock;
1417 flags |= eSymbolContextLineEntry;
1418 return (resolve_scope & flags) != 0;
1419}
1420
1422 const Address &addr, SymbolContextItem resolve_scope, SymbolContext &sc) {
1423 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1424 uint32_t resolved_flags = 0;
1425 lldb::addr_t file_addr = addr.GetFileAddress();
1426
1427 if (NeedsResolvedCompileUnit(resolve_scope)) {
1428 std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr);
1429 if (!modi)
1430 return 0;
1431 CompUnitSP cu_sp = GetCompileUnitAtIndex(*modi);
1432 if (!cu_sp)
1433 return 0;
1434
1435 sc.comp_unit = cu_sp.get();
1436 resolved_flags |= eSymbolContextCompUnit;
1437 }
1438
1439 if (resolve_scope & eSymbolContextFunction ||
1440 resolve_scope & eSymbolContextBlock) {
1441 if (!sc.comp_unit) {
1443 "missing compile unit for symbol at address {0:x}", file_addr);
1444 return 0;
1445 }
1446 std::vector<SymbolAndUid> matches = m_index->FindSymbolsByVa(file_addr);
1447 // Search the matches in reverse. This way if there are multiple matches
1448 // (for example we are 3 levels deep in a nested scope) it will find the
1449 // innermost one first.
1450 for (const auto &match : llvm::reverse(matches)) {
1451 if (match.uid.kind() != PdbSymUidKind::CompilandSym)
1452 continue;
1453
1454 PdbCompilandSymId csid = match.uid.asCompilandSym();
1455 CVSymbol cvs = m_index->ReadSymbolRecord(csid);
1456 PDB_SymType type = CVSymToPDBSym(cvs.kind());
1457 if (type != PDB_SymType::Function && type != PDB_SymType::Block)
1458 continue;
1459 if (type == PDB_SymType::Function) {
1460 sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get();
1461 if (sc.function) {
1462 Block &block = sc.function->GetBlock(true);
1463 addr_t func_base = sc.function->GetAddress().GetFileAddress();
1464 addr_t offset = file_addr - func_base;
1465 sc.block = block.FindInnermostBlockByOffset(offset);
1466 }
1467 }
1468
1469 if (type == PDB_SymType::Block) {
1470 Block *block = GetOrCreateBlock(csid);
1471 if (!block)
1472 continue;
1474 if (sc.function) {
1475 sc.function->GetBlock(true);
1476 addr_t func_base = sc.function->GetAddress().GetFileAddress();
1477 addr_t offset = file_addr - func_base;
1478 sc.block = block->FindInnermostBlockByOffset(offset);
1479 }
1480 }
1481 if (sc.function)
1482 resolved_flags |= eSymbolContextFunction;
1483 if (sc.block)
1484 resolved_flags |= eSymbolContextBlock;
1485 break;
1486 }
1487 }
1488
1489 if (resolve_scope & eSymbolContextLineEntry) {
1490 if (!sc.comp_unit) {
1492 "missing compile unit for symbol at address {0:x}", file_addr);
1493 return 0;
1494 }
1495 if (auto *line_table = sc.comp_unit->GetLineTable()) {
1496 if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
1497 resolved_flags |= eSymbolContextLineEntry;
1498 }
1499 }
1500
1501 return resolved_flags;
1502}
1503
1505 const SourceLocationSpec &src_location_spec,
1506 lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
1507 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1508 const uint32_t prev_size = sc_list.GetSize();
1509 if (resolve_scope & eSymbolContextCompUnit) {
1510 for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus;
1511 ++cu_idx) {
1512 CompileUnit *cu = ParseCompileUnitAtIndex(cu_idx).get();
1513 if (!cu)
1514 continue;
1515
1516 bool file_spec_matches_cu_file_spec = FileSpec::Match(
1517 src_location_spec.GetFileSpec(), cu->GetPrimaryFile());
1518 if (file_spec_matches_cu_file_spec) {
1519 cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);
1520 break;
1521 }
1522 }
1523 }
1524 return sc_list.GetSize() - prev_size;
1525}
1526
1528 // Unfortunately LLDB is set up to parse the entire compile unit line table
1529 // all at once, even if all it really needs is line info for a specific
1530 // function. In the future it would be nice if it could set the sc.m_function
1531 // member, and we could only get the line info for the function in question.
1532 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1533 PdbSymUid cu_id(comp_unit.GetID());
1534 if (cu_id.kind() != PdbSymUidKind::Compiland) {
1535 assert(false && "uid of compile unit not a compiland");
1536 return false;
1537 }
1538 uint16_t modi = cu_id.asCompiland().modi;
1539 CompilandIndexItem *cii = m_index->compilands().GetCompiland(modi);
1540 if (!cii) {
1541 LLDB_LOG(GetLog(LLDBLog::Symbols), "missing compiland for modi={0}", modi);
1542 return false;
1543 }
1544
1545 // Parse DEBUG_S_LINES subsections first, then parse all S_INLINESITE records
1546 // in this CU. Add line entries into the set first so that if there are line
1547 // entries with same addres, the later is always more accurate than the
1548 // former.
1549 std::set<LineTable::Entry, LineTableEntryComparator> line_set;
1550
1551 // This is basically a copy of the .debug$S subsections from all original COFF
1552 // object files merged together with address relocations applied. We are
1553 // looking for all DEBUG_S_LINES subsections.
1554 for (const DebugSubsectionRecord &dssr :
1555 cii->m_debug_stream.getSubsectionsArray()) {
1556 if (dssr.kind() != DebugSubsectionKind::Lines)
1557 continue;
1558
1559 DebugLinesSubsectionRef lines;
1560 llvm::BinaryStreamReader reader(dssr.getRecordData());
1561 if (auto EC = lines.initialize(reader)) {
1562 llvm::consumeError(std::move(EC));
1563 return false;
1564 }
1565
1566 const LineFragmentHeader *lfh = lines.header();
1567 uint64_t virtual_addr =
1568 m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset);
1569 if (virtual_addr == LLDB_INVALID_ADDRESS)
1570 continue;
1571
1572 for (const LineColumnEntry &group : lines) {
1573 llvm::Expected<uint32_t> file_index_or_err =
1574 GetFileIndex(*cii, group.NameIndex);
1575 if (!file_index_or_err) {
1576 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), file_index_or_err.takeError(),
1577 "failed to get file index for line entry: {0}");
1578 continue;
1579 }
1580 uint32_t file_index = file_index_or_err.get();
1581 if (group.LineNumbers.empty()) {
1583 "no line numbers for {0} in modi={1}", group.NameIndex, modi);
1584 continue;
1585 }
1588 for (const LineNumberEntry &entry : group.LineNumbers) {
1589 LineInfo cur_info(entry.Flags);
1590
1591 if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto())
1592 continue;
1593
1594 uint64_t addr = virtual_addr + entry.Offset;
1595
1596 bool is_statement = cur_info.isStatement();
1597 bool is_prologue = IsFunctionPrologue(*cii, addr);
1598 bool is_epilogue = IsFunctionEpilogue(*cii, addr);
1599
1600 uint32_t lno = cur_info.getStartLine();
1601
1602 LineTable::Entry new_entry(addr, lno, 0, file_index, is_statement, false,
1603 is_prologue, is_epilogue, false);
1604 // Terminal entry has lower precedence than new entry.
1605 auto iter = line_set.find(new_entry);
1606 if (iter != line_set.end() && iter->is_terminal_entry)
1607 line_set.erase(iter);
1608 line_set.insert(new_entry);
1609
1610 if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {
1611 line_entry.SetRangeEnd(addr);
1612 cii->m_global_line_table.Append(line_entry);
1613 }
1614 line_entry.SetRangeBase(addr);
1615 line_entry.data = {file_index, lno};
1616 }
1617 LineInfo last_line(group.LineNumbers.back().Flags);
1618 line_set.emplace(virtual_addr + lfh->CodeSize, last_line.getEndLine(), 0,
1619 file_index, false, false, false, false, true);
1620
1621 if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {
1622 line_entry.SetRangeEnd(virtual_addr + lfh->CodeSize);
1623 cii->m_global_line_table.Append(line_entry);
1624 }
1625 }
1626 }
1627
1629
1630 // Parse all S_INLINESITE in this CU.
1631 const CVSymbolArray &syms = cii->m_debug_stream.getSymbolArray();
1632 for (auto iter = syms.begin(); iter != syms.end();) {
1633 if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) {
1634 ++iter;
1635 continue;
1636 }
1637
1638 uint32_t record_offset = iter.offset();
1639 CVSymbol func_record =
1640 cii->m_debug_stream.readSymbolAtOffset(record_offset);
1642 addr_t file_vm_addr =
1643 m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);
1644 if (file_vm_addr == LLDB_INVALID_ADDRESS)
1645 continue;
1646
1647 Address func_base(file_vm_addr, comp_unit.GetModule()->GetSectionList());
1648 PdbCompilandSymId func_id{modi, record_offset};
1649
1650 // Iterate all S_INLINESITEs in the function.
1651 auto parse_inline_sites = [&](SymbolKind kind, PdbCompilandSymId id) {
1652 if (kind != S_INLINESITE)
1653 return false;
1654
1655 ParseInlineSite(id, func_base);
1656
1657 for (const auto &line_entry :
1658 m_inline_sites[toOpaqueUid(id)]->line_entries) {
1659 // If line_entry is not terminal entry, remove previous line entry at
1660 // the same address and insert new one. Terminal entry inside an inline
1661 // site might not be terminal entry for its parent.
1662 if (!line_entry.is_terminal_entry)
1663 line_set.erase(line_entry);
1664 line_set.insert(line_entry);
1665 }
1666 // No longer useful after adding to line_set.
1667 m_inline_sites[toOpaqueUid(id)]->line_entries.clear();
1668 return true;
1669 };
1670 ParseSymbolArrayInScope(func_id, parse_inline_sites);
1671 // Jump to the end of the function record.
1672 iter = syms.at(getScopeEndOffset(func_record));
1673 }
1674
1676
1677 // Add line entries in line_set to line_table.
1678 std::vector<LineTable::Sequence> sequence(1);
1679 for (const auto &line_entry : line_set) {
1681 sequence.back(), line_entry.file_addr, line_entry.line,
1682 line_entry.column, line_entry.file_idx,
1683 line_entry.is_start_of_statement, line_entry.is_start_of_basic_block,
1684 line_entry.is_prologue_end, line_entry.is_epilogue_begin,
1685 line_entry.is_terminal_entry);
1686 }
1687 auto line_table =
1688 std::make_unique<LineTable>(&comp_unit, std::move(sequence));
1689
1690 if (line_table->GetSize() == 0)
1691 return false;
1692
1693 comp_unit.SetLineTable(line_table.release());
1694 return true;
1695}
1696
1698 // PDB doesn't contain information about macros
1699 return false;
1700}
1701
1702llvm::Expected<uint32_t>
1704 uint32_t file_id) {
1705 if (!cii.m_strings.hasChecksums() || !cii.m_strings.hasStrings())
1706 return llvm::make_error<RawError>(raw_error_code::no_entry);
1707
1708 const auto &checksums = cii.m_strings.checksums().getArray();
1709 const auto &strings = cii.m_strings.strings();
1710 // Indices in this structure are actually offsets of records in the
1711 // DEBUG_S_FILECHECKSUMS subsection. Those entries then have an index
1712 // into the global PDB string table.
1713 auto iter = checksums.at(file_id);
1714 if (iter == checksums.end())
1715 return llvm::make_error<RawError>(raw_error_code::no_entry);
1716
1717 llvm::Expected<llvm::StringRef> efn = strings.getString(iter->FileNameOffset);
1718 if (!efn) {
1719 return efn.takeError();
1720 }
1721
1722 // LLDB wants the index of the file in the list of support files.
1723 auto fn_iter = llvm::find(cii.m_file_list, *efn);
1724 if (fn_iter != cii.m_file_list.end())
1725 return std::distance(cii.m_file_list.begin(), fn_iter);
1726 return llvm::make_error<RawError>(raw_error_code::no_entry);
1727}
1728
1730 SupportFileList &support_files) {
1731 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1732 PdbSymUid cu_id(comp_unit.GetID());
1733 if (cu_id.kind() != PdbSymUidKind::Compiland) {
1734 assert(false && "uid of compile unit not a compiland");
1735 return false;
1736 }
1737 CompilandIndexItem *cci =
1738 m_index->compilands().GetCompiland(cu_id.asCompiland().modi);
1739 if (!cci) {
1740 LLDB_LOG(GetLog(LLDBLog::Symbols), "missing compiland for modi={0}",
1741 cu_id.asCompiland().modi);
1742 return false;
1743 }
1744
1745 for (llvm::StringRef f : cci->m_file_list) {
1746 FileSpec::Style style =
1747 f.starts_with("/") ? FileSpec::Style::posix : FileSpec::Style::windows;
1748 FileSpec spec(f, style);
1749 support_files.Append(spec);
1750 }
1751 return true;
1752}
1753
1755 const SymbolContext &sc, std::vector<SourceModule> &imported_modules) {
1756 // PDB does not yet support module debug info
1757 return false;
1758}
1759
1761 Address func_addr) {
1762 lldb::user_id_t opaque_uid = toOpaqueUid(id);
1763 if (m_inline_sites.contains(opaque_uid))
1764 return;
1765
1766 addr_t func_base = func_addr.GetFileAddress();
1767 CompilandIndexItem *cii = m_index->compilands().GetCompiland(id.modi);
1768 CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(id.offset);
1769 CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
1770 if (sym.kind() != S_INLINESITE)
1771 return;
1772
1773 InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind()));
1774 if (auto err =
1775 SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site)) {
1776 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
1777 "Failed to deserialize InlineSiteSym record: {0}");
1778 return;
1779 }
1780 PdbCompilandSymId parent_id(id.modi, inline_site.Parent);
1781
1782 std::shared_ptr<InlineSite> inline_site_sp =
1783 std::make_shared<InlineSite>(parent_id);
1784
1785 // Get the inlined function declaration info.
1786 auto iter = cii->m_inline_map.find(inline_site.Inlinee);
1787 if (iter == cii->m_inline_map.end())
1788 return;
1789 InlineeSourceLine inlinee_line = iter->second;
1790
1791 const SupportFileList &files = comp_unit->GetSupportFiles();
1792 FileSpec decl_file;
1793 llvm::Expected<uint32_t> file_index_or_err =
1794 GetFileIndex(*cii, inlinee_line.Header->FileID);
1795 if (!file_index_or_err) {
1796 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), file_index_or_err.takeError(),
1797 "failed to get file index for inline site: {0}");
1798 return;
1799 }
1800 uint32_t file_offset = file_index_or_err.get();
1801 decl_file = files.GetFileSpecAtIndex(file_offset);
1802 uint32_t decl_line = inlinee_line.Header->SourceLineNum;
1803 std::unique_ptr<Declaration> decl_up =
1804 std::make_unique<Declaration>(decl_file, decl_line);
1805
1806 // Parse range and line info.
1807 uint32_t code_offset = 0;
1808 int32_t line_offset = 0;
1809 std::optional<uint32_t> code_offset_base;
1810 std::optional<uint32_t> code_offset_end;
1811 std::optional<int32_t> cur_line_offset;
1812 std::optional<int32_t> next_line_offset;
1813 std::optional<uint32_t> next_file_offset;
1814
1815 bool is_terminal_entry = false;
1816 bool is_start_of_statement = true;
1817 // The first instruction is the prologue end.
1818 bool is_prologue_end = true;
1819
1820 auto update_code_offset = [&](uint32_t code_delta) {
1821 if (!code_offset_base)
1822 code_offset_base = code_offset;
1823 else if (!code_offset_end)
1824 code_offset_end = *code_offset_base + code_delta;
1825 };
1826 auto update_line_offset = [&](int32_t line_delta) {
1827 line_offset += line_delta;
1828 if (!code_offset_base || !cur_line_offset)
1829 cur_line_offset = line_offset;
1830 else
1831 next_line_offset = line_offset;
1832 ;
1833 };
1834 auto update_file_offset = [&](uint32_t offset) {
1835 if (!code_offset_base)
1836 file_offset = offset;
1837 else
1838 next_file_offset = offset;
1839 };
1840
1841 for (auto &annot : inline_site.annotations()) {
1842 switch (annot.OpCode) {
1843 case BinaryAnnotationsOpCode::CodeOffset:
1844 case BinaryAnnotationsOpCode::ChangeCodeOffset:
1845 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
1846 code_offset += annot.U1;
1847 update_code_offset(annot.U1);
1848 break;
1849 case BinaryAnnotationsOpCode::ChangeLineOffset:
1850 update_line_offset(annot.S1);
1851 break;
1852 case BinaryAnnotationsOpCode::ChangeCodeLength:
1853 update_code_offset(annot.U1);
1854 code_offset += annot.U1;
1855 is_terminal_entry = true;
1856 break;
1857 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
1858 code_offset += annot.U1;
1859 update_code_offset(annot.U1);
1860 update_line_offset(annot.S1);
1861 break;
1862 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
1863 code_offset += annot.U2;
1864 update_code_offset(annot.U2);
1865 update_code_offset(annot.U1);
1866 code_offset += annot.U1;
1867 is_terminal_entry = true;
1868 break;
1869 case BinaryAnnotationsOpCode::ChangeFile:
1870 update_file_offset(annot.U1);
1871 break;
1872 default:
1873 break;
1874 }
1875
1876 // Add range if current range is finished.
1877 if (code_offset_base && code_offset_end && cur_line_offset) {
1878 inline_site_sp->ranges.Append(RangeSourceLineVector::Entry(
1879 *code_offset_base, *code_offset_end - *code_offset_base,
1880 decl_line + *cur_line_offset));
1881 // Set base, end, file offset and line offset for next range.
1882 if (next_file_offset)
1883 file_offset = *next_file_offset;
1884 if (next_line_offset) {
1885 cur_line_offset = next_line_offset;
1886 next_line_offset = std::nullopt;
1887 }
1888 code_offset_base = is_terminal_entry ? std::nullopt : code_offset_end;
1889 code_offset_end = next_file_offset = std::nullopt;
1890 }
1891 if (code_offset_base && cur_line_offset) {
1892 if (is_terminal_entry) {
1893 LineTable::Entry line_entry(
1894 func_base + *code_offset_base, decl_line + *cur_line_offset, 0,
1895 file_offset, false, false, false, false, true);
1896 inline_site_sp->line_entries.push_back(line_entry);
1897 } else {
1898 LineTable::Entry line_entry(func_base + *code_offset_base,
1899 decl_line + *cur_line_offset, 0,
1900 file_offset, is_start_of_statement, false,
1901 is_prologue_end, false, false);
1902 inline_site_sp->line_entries.push_back(line_entry);
1903 is_prologue_end = false;
1904 is_start_of_statement = false;
1905 }
1906 }
1907 if (is_terminal_entry)
1908 is_start_of_statement = true;
1909 is_terminal_entry = false;
1910 }
1911
1912 inline_site_sp->ranges.Sort();
1913
1914 // Get the inlined function callsite info.
1915 std::unique_ptr<Declaration> callsite_up;
1916 if (!inline_site_sp->ranges.IsEmpty()) {
1917 auto *entry = inline_site_sp->ranges.GetEntryAtIndex(0);
1918 addr_t base_offset = entry->GetRangeBase();
1919 if (cii->m_debug_stream.readSymbolAtOffset(parent_id.offset).kind() ==
1920 S_INLINESITE) {
1921 // Its parent is another inline site, lookup parent site's range vector
1922 // for callsite line.
1923 ParseInlineSite(parent_id, Address(func_base));
1924 std::shared_ptr<InlineSite> parent_site =
1925 m_inline_sites[toOpaqueUid(parent_id)];
1926 FileSpec &parent_decl_file =
1927 parent_site->inline_function_info->GetDeclaration().GetFile();
1928 if (auto *parent_entry =
1929 parent_site->ranges.FindEntryThatContains(base_offset)) {
1930 callsite_up =
1931 std::make_unique<Declaration>(parent_decl_file, parent_entry->data);
1932 }
1933 } else {
1934 // Its parent is a function, lookup global line table for callsite.
1935 if (auto *entry = cii->m_global_line_table.FindEntryThatContains(
1936 func_base + base_offset)) {
1937 const FileSpec &callsite_file =
1938 files.GetFileSpecAtIndex(entry->data.first);
1939 callsite_up =
1940 std::make_unique<Declaration>(callsite_file, entry->data.second);
1941 }
1942 }
1943 }
1944
1945 // Get the inlined function name.
1946 std::string inlinee_name;
1947 llvm::Expected<CVType> inlinee_cvt =
1948 m_index->ipi().typeCollection().getTypeOrError(inline_site.Inlinee);
1949 if (!inlinee_cvt) {
1950 inlinee_name = "[error reading function name: " +
1951 llvm::toString(inlinee_cvt.takeError()) + "]";
1952 } else if (inlinee_cvt->kind() == LF_MFUNC_ID) {
1953 MemberFuncIdRecord mfr;
1954 if (auto err = TypeDeserializer::deserializeAs<MemberFuncIdRecord>(
1955 *inlinee_cvt, mfr)) {
1956 inlinee_name =
1957 "[error reading function name: " + llvm::toString(std::move(err)) +
1958 "]";
1959 } else {
1960 LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
1961 inlinee_name.append(std::string(types.getTypeName(mfr.ClassType)));
1962 inlinee_name.append("::");
1963 inlinee_name.append(mfr.getName().str());
1964 }
1965 } else if (inlinee_cvt->kind() == LF_FUNC_ID) {
1966 FuncIdRecord fir;
1967 if (auto err =
1968 TypeDeserializer::deserializeAs<FuncIdRecord>(*inlinee_cvt, fir)) {
1969 inlinee_name =
1970 "[error reading function name: " + llvm::toString(std::move(err)) +
1971 "]";
1972 } else {
1973 TypeIndex parent_idx = fir.getParentScope();
1974 if (!parent_idx.isNoneType()) {
1975 LazyRandomTypeCollection &ids = m_index->ipi().typeCollection();
1976 inlinee_name.append(std::string(ids.getTypeName(parent_idx)));
1977 inlinee_name.append("::");
1978 }
1979 inlinee_name.append(fir.getName().str());
1980 }
1981 }
1982 inline_site_sp->inline_function_info = std::make_shared<InlineFunctionInfo>(
1983 inlinee_name.c_str(), llvm::StringRef(), decl_up.get(),
1984 callsite_up.get());
1985
1986 m_inline_sites[opaque_uid] = inline_site_sp;
1987}
1988
1990 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1991 PdbCompilandSymId func_id = PdbSymUid(func.GetID()).asCompilandSym();
1992 // After we iterate through inline sites inside the function, we already get
1993 // all the info needed, removing from the map to save memory.
1994 std::set<uint64_t> remove_uids;
1995 auto parse_blocks = [&](SymbolKind kind, PdbCompilandSymId id) {
1996 if (kind == S_GPROC32 || kind == S_LPROC32 || kind == S_BLOCK32 ||
1997 kind == S_INLINESITE) {
1998 GetOrCreateBlock(id);
1999 if (kind == S_INLINESITE)
2000 remove_uids.insert(toOpaqueUid(id));
2001 return true;
2002 }
2003 return false;
2004 };
2005 size_t count = ParseSymbolArrayInScope(func_id, parse_blocks);
2006 for (uint64_t uid : remove_uids) {
2007 m_inline_sites.erase(uid);
2008 }
2009
2010 func.GetBlock(false).SetBlockInfoHasBeenParsed(true, true);
2011 return count;
2012}
2013
2015 PdbCompilandSymId parent_id,
2016 llvm::function_ref<bool(SymbolKind, PdbCompilandSymId)> fn) {
2017 CompilandIndexItem *cii = m_index->compilands().GetCompiland(parent_id.modi);
2018 CVSymbolArray syms =
2019 cii->m_debug_stream.getSymbolArrayForScope(parent_id.offset);
2020
2021 size_t count = 1;
2022 for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
2023 PdbCompilandSymId child_id(parent_id.modi, iter.offset());
2024 if (fn(iter->kind(), child_id))
2025 ++count;
2026 }
2027
2028 return count;
2029}
2030
2031void SymbolFileNativePDB::DumpClangAST(Stream &s, llvm::StringRef filter,
2032 bool show_color) {
2034 if (!ts_or_err) {
2035 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), ts_or_err.takeError(),
2036 "failed to get C++ type system: {0}");
2037 return;
2038 }
2039 auto ts = *ts_or_err;
2040 TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
2041 if (!clang)
2042 return;
2043 PdbAstBuilder *ast_builder = clang->GetNativePDBParser();
2044 if (!ast_builder)
2045 return;
2046 ast_builder->Dump(s, filter, show_color);
2047}
2048
2050 if (!m_func_full_names.IsEmpty() || !m_global_variable_base_names.IsEmpty())
2051 return;
2052
2053 // (segment, code offset) -> gid
2054 std::map<std::pair<uint16_t, uint32_t>, uint32_t> func_addr_ids;
2055
2056 // First, look through all items in the globals table.
2057 for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
2058 CVSymbol sym = m_index->symrecords().readRecord(gid);
2059 auto kind = sym.kind();
2060
2061 // If this is a global variable, we only need to look at the name
2062 llvm::StringRef name;
2063 switch (kind) {
2064 case SymbolKind::S_GDATA32:
2065 case SymbolKind::S_LDATA32: {
2066 auto data_or_err = SymbolDeserializer::deserializeAs<DataSym>(sym);
2067 if (!data_or_err) {
2068 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), data_or_err.takeError(),
2069 "Failed to deserialize DataSym record: {0}");
2070 continue;
2071 }
2072 name = data_or_err->Name;
2073 break;
2074 }
2075 case SymbolKind::S_GTHREAD32:
2076 case SymbolKind::S_LTHREAD32: {
2077 auto data_or_err =
2078 SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym);
2079 if (!data_or_err) {
2080 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), data_or_err.takeError(),
2081 "Failed to deserialize ThreadLocalDataSym record: {0}");
2082 continue;
2083 }
2084 name = data_or_err->Name;
2085 break;
2086 }
2087 case SymbolKind::S_CONSTANT: {
2088 auto data_or_err = SymbolDeserializer::deserializeAs<ConstantSym>(sym);
2089 if (!data_or_err) {
2090 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), data_or_err.takeError(),
2091 "Failed to deserialize ConstantSym record: {0}");
2092 continue;
2093 }
2094 name = data_or_err->Name;
2095 break;
2096 }
2097 default:
2098 break;
2099 }
2100
2101 if (!name.empty()) {
2102 llvm::StringRef base = MSVCUndecoratedNameParser::DropScope(name);
2103 if (base.empty())
2104 base = name;
2105
2106 m_global_variable_base_names.Append(ConstString(base), gid);
2107 continue;
2108 }
2109
2110 if (kind != S_PROCREF && kind != S_LPROCREF)
2111 continue;
2112
2113 // For functions, we need to follow the reference to the procedure and look
2114 // at the type
2115
2116 auto ref_or_err = SymbolDeserializer::deserializeAs<ProcRefSym>(sym);
2117 if (!ref_or_err) {
2118 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), ref_or_err.takeError(),
2119 "Failed to deserialize ProcRefSym record: {0}");
2120 continue;
2121 }
2122 ProcRefSym ref = std::move(*ref_or_err);
2123 if (ref.Name.empty())
2124 continue;
2125
2126 // Find the function this is referencing.
2127 CompilandIndexItem &cci =
2128 m_index->compilands().GetOrCreateCompiland(ref.modi());
2129 auto iter = cci.m_debug_stream.getSymbolArray().at(ref.SymOffset);
2130 if (iter == cci.m_debug_stream.getSymbolArray().end())
2131 continue;
2132 kind = iter->kind();
2133 if (kind != S_GPROC32 && kind != S_LPROC32)
2134 continue;
2135
2136 auto proc_or_err = SymbolDeserializer::deserializeAs<ProcSym>(*iter);
2137 if (!proc_or_err) {
2138 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), proc_or_err.takeError(),
2139 "Failed to deserialize ProcSym record: {0}");
2140 continue;
2141 }
2142 ProcSym proc = std::move(*proc_or_err);
2143 if ((proc.Flags & ProcSymFlags::IsUnreachable) != ProcSymFlags::None)
2144 continue;
2145 if (proc.Name.empty() || proc.FunctionType.isSimple())
2146 continue;
2147
2148 // The function/procedure symbol only contains the demangled name.
2149 // The mangled names are in the publics table. Save the address of this
2150 // function to lookup the mangled name later.
2151 func_addr_ids.emplace(std::make_pair(proc.Segment, proc.CodeOffset), gid);
2152
2153 llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(proc.Name);
2154 if (basename.empty())
2155 basename = proc.Name;
2156
2157 m_func_base_names.Append(ConstString(basename), gid);
2158 m_func_full_names.Append(ConstString(proc.Name), gid);
2159
2160 // To see if this is a member function, check the type.
2161 auto type = m_index->tpi().getType(proc.FunctionType);
2162 if (type.kind() == LF_MFUNCTION) {
2163 MemberFunctionRecord mfr;
2164 if (auto err = TypeDeserializer::deserializeAs<MemberFunctionRecord>(
2165 type, mfr)) {
2167 GetLog(LLDBLog::Symbols), std::move(err),
2168 "Failed to deserialize MemberFunctionRecord record ({1}): {0}",
2169 proc.FunctionType);
2170 } else if (!mfr.getThisType().isNoneType())
2171 m_func_method_names.Append(ConstString(basename), gid);
2172 }
2173 }
2174
2175 // The publics stream contains all mangled function names and their address.
2176 for (auto pid : m_index->publics().getPublicsTable()) {
2177 PdbGlobalSymId global{pid, true};
2178 CVSymbol sym = m_index->ReadSymbolRecord(global);
2179 auto kind = sym.kind();
2180 if (kind != S_PUB32)
2181 continue;
2182 auto pub_or_err = SymbolDeserializer::deserializeAs<PublicSym32>(sym);
2183 if (!pub_or_err) {
2184 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), pub_or_err.takeError(),
2185 "Failed to deserialize PublicSym32 record: {0}");
2186 continue;
2187 }
2188 PublicSym32 pub = std::move(*pub_or_err);
2189 // We only care about mangled names - if the name isn't mangled, it's
2190 // already in the full name map.
2191 if (!Mangled::IsMangledName(pub.Name))
2192 continue;
2193
2194 // Check if this symbol is for one of our functions.
2195 auto it = func_addr_ids.find({pub.Segment, pub.Offset});
2196 if (it != func_addr_ids.end())
2197 m_func_full_names.Append(ConstString(pub.Name), it->second);
2198 }
2199
2200 // Sort them before value searching is working properly.
2201 m_func_full_names.Sort(std::less<uint32_t>());
2202 m_func_full_names.SizeToFit();
2203 m_func_method_names.Sort(std::less<uint32_t>());
2204 m_func_method_names.SizeToFit();
2205 m_func_base_names.Sort(std::less<uint32_t>());
2206 m_func_base_names.SizeToFit();
2207 m_global_variable_base_names.Sort(std::less<uint32_t>());
2208 m_global_variable_base_names.SizeToFit();
2209}
2210
2212 ConstString name, const CompilerDeclContext &parent_decl_ctx,
2213 uint32_t max_matches, VariableList &variables) {
2214 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2215
2217
2218 std::vector<uint32_t> results;
2219 m_global_variable_base_names.GetValues(name, results);
2220
2221 size_t n_matches = 0;
2222 for (uint32_t gid : results) {
2223 PdbGlobalSymId global(gid, false);
2224
2225 if (parent_decl_ctx.IsValid() &&
2226 GetDeclContextContainingUID(toOpaqueUid(global)) != parent_decl_ctx)
2227 continue;
2228
2230 if (!var)
2231 continue;
2232 variables.AddVariable(var);
2233
2234 if (++n_matches >= max_matches)
2235 break;
2236 }
2237}
2238
2240 const Module::LookupInfo &lookup_info,
2241 const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
2242 SymbolContextList &sc_list) {
2243 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2244 ConstString name = lookup_info.GetLookupName();
2245 FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
2246 if (name_type_mask & eFunctionNameTypeFull)
2247 name = lookup_info.GetName();
2248
2249 if (!(name_type_mask & eFunctionNameTypeFull ||
2250 name_type_mask & eFunctionNameTypeBase ||
2251 name_type_mask & eFunctionNameTypeMethod))
2252 return;
2254
2255 std::set<uint32_t> resolved_ids; // avoid duplicate lookups
2256 auto resolve_from = [&](UniqueCStringMap<uint32_t> &Names) {
2257 std::vector<uint32_t> ids;
2258 if (!Names.GetValues(name, ids))
2259 return;
2260
2261 for (uint32_t id : ids) {
2262 if (!resolved_ids.insert(id).second)
2263 continue;
2264
2265 PdbGlobalSymId global{id, false};
2266 if (parent_decl_ctx.IsValid() &&
2267 GetDeclContextContainingUID(toOpaqueUid(global)) != parent_decl_ctx)
2268 continue;
2269
2270 CVSymbol sym = m_index->ReadSymbolRecord(global);
2271 auto kind = sym.kind();
2272 if (kind != S_PROCREF && kind != S_LPROCREF) {
2273 LLDB_LOG(GetLog(LLDBLog::Symbols), "{0} is not a proc reference",
2274 global);
2275 continue;
2276 }
2277
2278 auto proc_or_err = SymbolDeserializer::deserializeAs<ProcRefSym>(sym);
2279 if (!proc_or_err) {
2280 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), proc_or_err.takeError(),
2281 "Failed to deserialize ProcRefSym record: {0}");
2282 continue;
2283 }
2284 ProcRefSym proc = std::move(*proc_or_err);
2285
2286 if (!IsValidRecord(proc))
2287 continue;
2288
2289 CompilandIndexItem &cci =
2290 m_index->compilands().GetOrCreateCompiland(proc.modi());
2291 SymbolContext sc;
2292
2293 sc.comp_unit = GetOrCreateCompileUnit(cci).get();
2294 if (!sc.comp_unit)
2295 continue;
2296
2297 PdbCompilandSymId func_id(proc.modi(), proc.SymOffset);
2298 sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get();
2299 if (!sc.function)
2300 continue;
2301
2302 sc_list.Append(sc);
2303 }
2304 };
2305
2306 if (name_type_mask & eFunctionNameTypeFull)
2307 resolve_from(m_func_full_names);
2308 if (name_type_mask & eFunctionNameTypeBase)
2309 resolve_from(m_func_base_names);
2310 if (name_type_mask & eFunctionNameTypeMethod)
2311 resolve_from(m_func_method_names);
2312}
2313
2315 bool include_inlines,
2316 SymbolContextList &sc_list) {}
2317
2319 lldb_private::TypeResults &results) {
2320
2321 // Make sure we haven't already searched this SymbolFile before.
2322 if (results.AlreadySearched(this))
2323 return;
2324
2325 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2326
2328
2329 // We can't query for the full name because the type might reside
2330 // in an anonymous namespace. Search for the basename in our map and check the
2331 // matching types afterwards.
2332 std::vector<uint32_t> matches;
2333 m_type_base_names.GetValues(query.GetTypeBasename(), matches);
2334
2335 for (uint32_t match_idx : matches) {
2336 std::vector context = GetContextForType(TypeIndex(match_idx));
2337 if (context.empty())
2338 continue;
2339
2340 if (query.ContextMatches(context)) {
2341 TypeSP type_sp = GetOrCreateType(TypeIndex(match_idx));
2342 if (!type_sp)
2343 continue;
2344
2345 results.InsertUnique(type_sp);
2346 if (results.Done(query))
2347 return;
2348 }
2349 }
2350}
2351
2353 uint32_t max_matches,
2354 TypeMap &types) {
2355
2356 std::vector<TypeIndex> matches = m_index->tpi().findRecordsByName(name);
2357 if (max_matches > 0 && max_matches < matches.size())
2358 matches.resize(max_matches);
2359
2360 for (TypeIndex ti : matches) {
2361 TypeSP type = GetOrCreateType(ti);
2362 if (!type)
2363 continue;
2364
2365 types.Insert(type);
2366 }
2367}
2368
2370 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2371 // Only do the full type scan the first time.
2373 return 0;
2374
2375 const size_t old_count = GetTypeList().GetSize();
2376 LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
2377
2378 // First process the entire TPI stream.
2379 for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
2380 TypeSP type = GetOrCreateType(*ti);
2381 if (type)
2382 (void)type->GetFullCompilerType();
2383 }
2384
2385 // Next look for S_UDT records in the globals stream.
2386 for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
2387 PdbGlobalSymId global{gid, false};
2388 CVSymbol sym = m_index->ReadSymbolRecord(global);
2389 if (sym.kind() != S_UDT)
2390 continue;
2391
2392 auto udt_or_err = SymbolDeserializer::deserializeAs<UDTSym>(sym);
2393 if (!udt_or_err) {
2394 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), udt_or_err.takeError(),
2395 "Failed to deserialize UDTSym record: {0}");
2396 continue;
2397 }
2398 UDTSym udt = std::move(*udt_or_err);
2399 bool is_typedef = true;
2400 if (IsTagRecord(PdbTypeSymId{udt.Type, false}, m_index->tpi())) {
2401 CVType cvt = m_index->tpi().getType(udt.Type);
2402 llvm::StringRef name = CVTagRecord::create(cvt).name();
2403 if (name == udt.Name)
2404 is_typedef = false;
2405 }
2406
2407 if (is_typedef)
2408 GetOrCreateTypedef(global);
2409 }
2410
2411 const size_t new_count = GetTypeList().GetSize();
2412
2413 m_done_full_type_scan = true;
2414
2415 return new_count - old_count;
2416}
2417
2418size_t
2420 VariableList &variables) {
2421 for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
2422 PdbGlobalSymId global{gid, false};
2423 CVSymbol sym = m_index->ReadSymbolRecord(global);
2424 // TODO: S_CONSTANT is not handled here to prevent a possible crash in
2425 // lldb_private::npdb::MakeConstantLocationExpression when it's a record
2426 // type (e.g. std::strong_ordering::equal). That function needs to be
2427 // updated to handle this case when we add S_CONSTANT case here.
2428 switch (sym.kind()) {
2429 case SymbolKind::S_GDATA32:
2430 case SymbolKind::S_LDATA32:
2431 case SymbolKind::S_GTHREAD32:
2432 case SymbolKind::S_LTHREAD32: {
2433 if (VariableSP var = GetOrCreateGlobalVariable(global))
2434 variables.AddVariable(var);
2435 break;
2436 }
2437 default:
2438 break;
2439 }
2440 }
2441 return variables.GetSize();
2442}
2443
2445 PdbCompilandSymId var_id,
2446 bool is_param,
2447 bool is_constant) {
2448 ModuleSP module = GetObjectFile()->GetModule();
2449 Block *block = GetOrCreateBlock(scope_id);
2450 if (!block)
2451 return nullptr;
2452
2453 CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
2454 if (!cii)
2455 return nullptr;
2456 CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
2457
2458 VariableInfo var_info;
2459 bool location_is_constant_data = is_constant;
2460
2461 if (is_constant) {
2462 CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(var_id.offset);
2463 if (sym.kind() != S_CONSTANT)
2464 return nullptr;
2465 ConstantSym constant(sym.kind());
2466 if (auto err =
2467 SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant)) {
2468 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
2469 "Failed to deserialize ConstantSym record: {0}");
2470 return nullptr;
2471 }
2472
2473 var_info.name = constant.Name;
2474 var_info.type = constant.Type;
2475 auto location_or_err = MakeConstantLocationExpression(
2476 constant.Type, m_index->tpi(), constant.Value, module);
2477 if (!location_or_err) {
2478 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), location_or_err.takeError(),
2479 "Failed to make constant location expression for {1}: {0}",
2480 constant.Name);
2481 return nullptr;
2482 }
2483 var_info.location =
2484 DWARFExpressionList(module, std::move(*location_or_err), nullptr);
2485 } else {
2486 // Get function block.
2487 Block *func_block = block;
2488 while (func_block->GetParent())
2489 func_block = func_block->GetParent();
2490
2491 Address addr;
2492 func_block->GetStartAddress(addr);
2493 var_info = GetVariableLocationInfo(*m_index, var_id, *func_block, module);
2494 Function *func = func_block->CalculateSymbolContextFunction();
2495 if (!func)
2496 return nullptr;
2497 // Use empty dwarf expr if optimized away so that it won't be filtered out
2498 // when lookuping local variables in this scope.
2499 if (!var_info.location.IsValid())
2500 var_info.location =
2501 DWARFExpressionList(module, DWARFExpression(), nullptr);
2503 }
2504
2505 TypeSP type_sp = GetOrCreateType(var_info.type);
2506 if (!type_sp)
2507 return nullptr;
2508 std::string name = var_info.name.str();
2509 Declaration decl;
2510 SymbolFileTypeSP sftype =
2511 std::make_shared<SymbolFileType>(*this, type_sp->GetID());
2512
2513 is_param |= var_info.is_param;
2514 ValueType var_scope =
2516 bool external = false;
2517 bool artificial = false;
2518 bool static_member = false;
2519 Variable::RangeList scope_ranges;
2520 VariableSP var_sp = std::make_shared<Variable>(
2521 toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope, block,
2522 scope_ranges, &decl, var_info.location, external, artificial,
2523 location_is_constant_data, static_member);
2524 if (!is_param) {
2525 auto ts_or_err = GetTypeSystemForLanguage(comp_unit_sp->GetLanguage());
2526 if (auto err = ts_or_err.takeError())
2527 return nullptr;
2528 auto ts = *ts_or_err;
2529 if (ts) {
2530 if (PdbAstBuilder *ast_builder = ts->GetNativePDBParser())
2531 ast_builder->EnsureVariable(scope_id, var_id);
2532 }
2533 }
2534 m_local_variables[toOpaqueUid(var_id)] = var_sp;
2535 return var_sp;
2536}
2537
2540 PdbCompilandSymId var_id,
2541 bool is_param, bool is_constant) {
2542 auto iter = m_local_variables.find(toOpaqueUid(var_id));
2543 if (iter != m_local_variables.end())
2544 return iter->second;
2545
2546 return CreateLocalVariable(scope_id, var_id, is_param, is_constant);
2547}
2548
2550 CVSymbol sym = m_index->ReadSymbolRecord(id);
2551 if (sym.kind() != S_UDT) {
2552 LLDB_LOG(GetLog(LLDBLog::Symbols), "{0} is not an S_UDT", id);
2553 return nullptr;
2554 }
2555
2556 auto udt_or_err = SymbolDeserializer::deserializeAs<UDTSym>(sym);
2557 if (!udt_or_err) {
2558 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), udt_or_err.takeError(),
2559 "Failed to deserialize UDTSym record: {0}");
2560 return nullptr;
2561 }
2562 UDTSym udt = std::move(*udt_or_err);
2563
2564 TypeSP target_type = GetOrCreateType(udt.Type);
2565
2567 if (auto err = ts_or_err.takeError())
2568 return nullptr;
2569 auto ts = *ts_or_err;
2570 if (!ts)
2571 return nullptr;
2572 PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
2573 if (!ast_builder)
2574 return nullptr;
2575 CompilerType ct = ast_builder->GetOrCreateTypedefType(id);
2576 if (!ct)
2577 ct = target_type->GetForwardCompilerType();
2578
2579 Declaration decl;
2580 return MakeType(toOpaqueUid(id), ConstString(udt.Name),
2581 llvm::expectedToOptional(target_type->GetByteSize(nullptr)),
2582 nullptr, target_type->GetID(),
2585}
2586
2588 auto iter = m_types.find(toOpaqueUid(id));
2589 if (iter != m_types.end())
2590 return iter->second;
2591
2592 return CreateTypedef(id);
2593}
2594
2596 Block *block = GetOrCreateBlock(block_id);
2597 if (!block)
2598 return 0;
2599
2600 size_t count = 0;
2601
2602 CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
2603 CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
2604 uint32_t params_remaining = 0;
2605 switch (sym.kind()) {
2606 case S_GPROC32:
2607 case S_LPROC32: {
2608 ProcSym proc(static_cast<SymbolRecordKind>(sym.kind()));
2609 if (auto err = SymbolDeserializer::deserializeAs<ProcSym>(sym, proc)) {
2610 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
2611 "Failed to deserialize ProcSym record: {0}");
2612 return 0;
2613 }
2614 CVType signature = m_index->tpi().getType(proc.FunctionType);
2615 if (signature.kind() == LF_PROCEDURE) {
2616 ProcedureRecord sig;
2617 if (llvm::Error e = TypeDeserializer::deserializeAs<ProcedureRecord>(
2618 signature, sig)) {
2619 llvm::consumeError(std::move(e));
2620 return 0;
2621 }
2622 params_remaining = sig.getParameterCount();
2623 } else if (signature.kind() == LF_MFUNCTION) {
2624 MemberFunctionRecord sig;
2625 if (llvm::Error e = TypeDeserializer::deserializeAs<MemberFunctionRecord>(
2626 signature, sig)) {
2627 llvm::consumeError(std::move(e));
2628 return 0;
2629 }
2630 params_remaining = sig.getParameterCount();
2631 } else
2632 return 0;
2633 break;
2634 }
2635 case S_BLOCK32:
2636 break;
2637 case S_INLINESITE:
2638 break;
2639 default:
2640 LLDB_LOG(GetLog(LLDBLog::Symbols), "{0} is not a block", block_id);
2641 return 0;
2642 }
2643
2644 VariableListSP variables = block->GetBlockVariableList(false);
2645 if (!variables) {
2646 variables = std::make_shared<VariableList>();
2647 block->SetVariableList(variables);
2648 }
2649
2650 CVSymbolArray syms = limitSymbolArrayToScope(
2651 cii->m_debug_stream.getSymbolArray(), block_id.offset);
2652
2653 // Skip the first record since it's a PROC32 or BLOCK32, and there's
2654 // no point examining it since we know it's not a local variable.
2655 syms.drop_front();
2656 auto iter = syms.begin();
2657 auto end = syms.end();
2658
2659 while (iter != end) {
2660 uint32_t record_offset = iter.offset();
2661 CVSymbol variable_cvs = *iter;
2662 PdbCompilandSymId child_sym_id(block_id.modi, record_offset);
2663 ++iter;
2664
2665 // If this is a block or inline site, recurse into its children and then
2666 // skip it.
2667 if (variable_cvs.kind() == S_BLOCK32 ||
2668 variable_cvs.kind() == S_INLINESITE) {
2669 uint32_t block_end = getScopeEndOffset(variable_cvs);
2670 count += ParseVariablesForBlock(child_sym_id);
2671 iter = syms.at(block_end);
2672 continue;
2673 }
2674
2675 bool is_param = params_remaining > 0;
2676 VariableSP variable;
2677 switch (variable_cvs.kind()) {
2678 case S_REGREL32:
2679 case S_REGREL32_INDIR:
2680 case S_REGISTER:
2681 case S_LOCAL:
2682 variable = GetOrCreateLocalVariable(block_id, child_sym_id, is_param);
2683 if (is_param)
2684 --params_remaining;
2685 if (variable)
2686 variables->AddVariableIfUnique(variable);
2687 break;
2688 case S_CONSTANT:
2689 variable = GetOrCreateLocalVariable(block_id, child_sym_id,
2690 /*is_param=*/false,
2691 /*is_constant=*/true);
2692 if (variable)
2693 variables->AddVariableIfUnique(variable);
2694 break;
2695 default:
2696 break;
2697 }
2698 }
2699
2700 // Pass false for set_children, since we call this recursively so that the
2701 // children will call this for themselves.
2702 block->SetDidParseVariables(true, false);
2703
2704 return count;
2705}
2706
2708 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2709
2710 if (sc.block) {
2711 PdbSymUid block_id(sc.block->GetID());
2712
2713 size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
2714 return count;
2715 }
2716
2717 if (sc.function) {
2718 PdbSymUid block_id(sc.function->GetID());
2719
2720 size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
2721 return count;
2722 }
2723
2724 if (sc.comp_unit) {
2725 VariableListSP variables = sc.comp_unit->GetVariableList(false);
2726 if (!variables) {
2727 variables = std::make_shared<VariableList>();
2728 sc.comp_unit->SetVariableList(variables);
2729 }
2730 return ParseVariablesForCompileUnit(*sc.comp_unit, *variables);
2731 }
2732
2734 "missing missing block, function, or module for symbol context");
2735 return 0;
2736}
2737
2740 if (auto err = ts_or_err.takeError())
2741 return CompilerDecl();
2742 auto ts = *ts_or_err;
2743 if (!ts)
2744 return {};
2745 PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
2746 if (!ast_builder)
2747 return {};
2748 return ast_builder->GetOrCreateDeclForUid(uid);
2749}
2750
2754 if (auto err = ts_or_err.takeError())
2755 return {};
2756 auto ts = *ts_or_err;
2757 if (!ts)
2758 return {};
2759 PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
2760 if (!ast_builder)
2761 return {};
2762 return ast_builder->GetOrCreateDeclContextForUid(PdbSymUid(uid));
2763}
2764
2768 if (auto err = ts_or_err.takeError())
2769 return CompilerDeclContext();
2770 auto ts = *ts_or_err;
2771 if (!ts)
2772 return {};
2773 PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
2774 if (!ast_builder)
2775 return {};
2776 return ast_builder->GetParentDeclContext(PdbSymUid(uid));
2777}
2778
2780 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2781 auto iter = m_types.find(type_uid);
2782 // lldb should not be passing us non-sensical type uids. the only way it
2783 // could have a type uid in the first place is if we handed it out, in which
2784 // case we should know about the type. However, that doesn't mean we've
2785 // instantiated it yet. We can vend out a UID for a future type. So if the
2786 // type doesn't exist, let's instantiate it now.
2787 if (iter != m_types.end())
2788 return &*iter->second;
2789
2790 PdbSymUid uid(type_uid);
2791 if (uid.kind() != PdbSymUidKind::Type) {
2792 assert(false && "uid is not a type index");
2793 return nullptr;
2794 }
2795 PdbTypeSymId type_id = uid.asTypeSym();
2796 if (type_id.index.isNoneType())
2797 return nullptr;
2798
2799 TypeSP type_sp = CreateAndCacheType(type_id);
2800 if (!type_sp)
2801 return nullptr;
2802 return &*type_sp;
2803}
2804
2805std::optional<SymbolFile::ArrayInfo>
2807 lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
2808 return std::nullopt;
2809}
2810
2812 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2813 auto ts = compiler_type.GetTypeSystem();
2814 if (!ts)
2815 return false;
2816
2817 PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
2818 if (!ast_builder)
2819 return false;
2820 return ast_builder->CompleteType(compiler_type);
2821}
2822
2824 TypeClass type_mask,
2825 lldb_private::TypeList &type_list) {}
2826
2829 const CompilerDeclContext &parent_decl_ctx,
2830 bool /* only_root_namespaces */) {
2831 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2833 if (auto err = ts_or_err.takeError())
2834 return {};
2835 auto ts = *ts_or_err;
2836 if (!ts)
2837 return {};
2838 auto *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
2839 if (!clang)
2840 return {};
2841
2842 PdbAstBuilder *ast_builder = clang->GetNativePDBParser();
2843 if (!ast_builder)
2844 return {};
2845
2846 return ast_builder->FindNamespaceDecl(parent_decl_ctx, name.GetStringRef());
2847}
2848
2849llvm::Expected<lldb::TypeSystemSP>
2851 auto type_system_or_err =
2852 m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language);
2853 if (type_system_or_err)
2854 if (auto ts = *type_system_or_err)
2855 ts->SetSymbolFile(this);
2856 return type_system_or_err;
2857}
2858
2859uint64_t SymbolFileNativePDB::GetDebugInfoSize(bool load_all_debug_info) {
2860 // PDB files are a separate file that contains all debug info.
2861 return m_index->pdb().getFileSize();
2862}
2863
2866 return;
2867 m_parent_map_built = true;
2868
2869 LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
2870
2871 llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full;
2872 llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward;
2873
2874 struct RecordIndices {
2875 TypeIndex forward;
2876 TypeIndex full;
2877 };
2878
2879 llvm::StringMap<RecordIndices> record_indices;
2880
2881 for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
2882 CVType type = types.getType(*ti);
2883 if (!IsTagRecord(type))
2884 continue;
2885
2886 CVTagRecord tag = CVTagRecord::create(type);
2887
2888 RecordIndices &indices = record_indices[tag.asTag().getUniqueName()];
2889 if (tag.asTag().isForwardRef()) {
2890 indices.forward = *ti;
2891 } else {
2892 indices.full = *ti;
2893
2894 auto base_name = MSVCUndecoratedNameParser::DropScope(tag.name());
2895 m_type_base_names.Append(ConstString(base_name), ti->getIndex());
2896 }
2897
2898 if (indices.full != TypeIndex::None() &&
2899 indices.forward != TypeIndex::None()) {
2900 forward_to_full[indices.forward] = indices.full;
2901 full_to_forward[indices.full] = indices.forward;
2902 }
2903
2904 // We're looking for LF_NESTTYPE records in the field list, so ignore
2905 // forward references (no field list), and anything without a nested class
2906 // (since there won't be any LF_NESTTYPE records).
2907 if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass())
2908 continue;
2909
2910 struct ProcessTpiStream : public TypeVisitorCallbacks {
2911 ProcessTpiStream(PdbIndex &index, TypeIndex parent,
2912 const CVTagRecord &parent_cvt,
2913 llvm::DenseMap<TypeIndex, TypeIndex> &parents)
2914 : index(index), parents(parents), parent(parent),
2915 parent_cvt(parent_cvt) {}
2916
2917 PdbIndex &index;
2918 llvm::DenseMap<TypeIndex, TypeIndex> &parents;
2919
2920 unsigned unnamed_type_index = 1;
2921 TypeIndex parent;
2922 const CVTagRecord &parent_cvt;
2923
2924 llvm::Error visitKnownMember(CVMemberRecord &CVR,
2925 NestedTypeRecord &Record) override {
2926 std::string unnamed_type_name;
2927 if (Record.Name.empty()) {
2928 unnamed_type_name =
2929 llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str();
2930 Record.Name = unnamed_type_name;
2931 ++unnamed_type_index;
2932 }
2933 std::optional<CVTagRecord> tag =
2934 GetNestedTagDefinition(Record, parent_cvt, index.tpi());
2935 if (!tag)
2936 return llvm::ErrorSuccess();
2937
2938 parents[Record.Type] = parent;
2939 return llvm::ErrorSuccess();
2940 }
2941 };
2942
2943 CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList);
2944 if (field_list_cvt.kind() != LF_FIELDLIST)
2945 continue; // Invalid reference to a field list.
2946
2947 ProcessTpiStream process(*m_index, *ti, tag, m_parent_types);
2948 FieldListRecord field_list;
2949 if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
2950 field_list_cvt, field_list))
2951 llvm::consumeError(std::move(error));
2952 if (llvm::Error error = visitMemberRecordStream(field_list.Data, process))
2953 llvm::consumeError(std::move(error));
2954 }
2955
2956 // After calling Append(), the type-name map needs to be sorted again to be
2957 // able to look up a type by its name.
2958 m_type_base_names.Sort(std::less<uint32_t>());
2959
2960 // Now that we know the forward -> full mapping of all type indices, we can
2961 // re-write all the indices. At the end of this process, we want a mapping
2962 // consisting of fwd -> full and full -> full for all child -> parent indices.
2963 // We can re-write the values in place, but for the keys, we must save them
2964 // off so that we don't modify the map in place while also iterating it.
2965 std::vector<TypeIndex> full_keys;
2966 std::vector<TypeIndex> fwd_keys;
2967 for (auto &entry : m_parent_types) {
2968 TypeIndex key = entry.first;
2969 TypeIndex value = entry.second;
2970
2971 auto iter = forward_to_full.find(value);
2972 if (iter != forward_to_full.end())
2973 entry.second = iter->second;
2974
2975 iter = forward_to_full.find(key);
2976 if (iter != forward_to_full.end())
2977 fwd_keys.push_back(key);
2978 else
2979 full_keys.push_back(key);
2980 }
2981 for (TypeIndex fwd : fwd_keys) {
2982 TypeIndex full = forward_to_full[fwd];
2983 TypeIndex parent_idx = m_parent_types[fwd];
2984 m_parent_types[full] = parent_idx;
2985 }
2986 for (TypeIndex full : full_keys) {
2987 TypeIndex fwd = full_to_forward[full];
2988 m_parent_types[fwd] = m_parent_types[full];
2989 }
2990}
2991
2992std::optional<PdbCompilandSymId>
2994 CVSymbol sym = m_index->ReadSymbolRecord(id);
2995 if (symbolOpensScope(sym.kind())) {
2996 // If this exact symbol opens a scope, we can just directly access its
2997 // parent.
2998 id.offset = getScopeParentOffset(sym);
2999 // Global symbols have parent offset of 0. Return std::nullopt to indicate
3000 // this.
3001 if (id.offset == 0)
3002 return std::nullopt;
3003 return id;
3004 }
3005
3006 // Otherwise we need to start at the beginning and iterate forward until we
3007 // reach (or pass) this particular symbol
3008 CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(id.modi);
3009 const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
3010
3011 auto begin = syms.begin();
3012 auto end = syms.at(id.offset);
3013 std::vector<PdbCompilandSymId> scope_stack;
3014
3015 while (begin != end) {
3016 if (begin.offset() > id.offset) {
3017 // We passed it. We couldn't even find this symbol record.
3018 LLDB_LOG(GetLog(LLDBLog::Symbols), "invalid compiland symbol id: {0}",
3019 id);
3020 return std::nullopt;
3021 }
3022
3023 // We haven't found the symbol yet. Check if we need to open or close the
3024 // scope stack.
3025 if (symbolOpensScope(begin->kind())) {
3026 // We can use the end offset of the scope to determine whether or not
3027 // we can just outright skip this entire scope.
3028 uint32_t scope_end = getScopeEndOffset(*begin);
3029 if (scope_end < id.offset) {
3030 begin = syms.at(scope_end);
3031 } else {
3032 // The symbol we're looking for is somewhere in this scope.
3033 scope_stack.emplace_back(id.modi, begin.offset());
3034 }
3035 } else if (symbolEndsScope(begin->kind())) {
3036 scope_stack.pop_back();
3037 }
3038 ++begin;
3039 }
3040 if (scope_stack.empty())
3041 return std::nullopt;
3042 // We have a match! Return the top of the stack
3043 return scope_stack.back();
3044}
3045
3046std::optional<llvm::codeview::TypeIndex>
3047SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) {
3049 auto parent_iter = m_parent_types.find(ti);
3050 if (parent_iter == m_parent_types.end())
3051 return std::nullopt;
3052 return parent_iter->second;
3053}
3054
3055std::vector<CompilerContext>
3057 CVType type = m_index->tpi().getType(ti);
3058 if (!IsTagRecord(type))
3059 return {};
3060
3061 CVTagRecord tag = CVTagRecord::create(type);
3062
3063 std::optional<Type::ParsedName> parsed_name =
3065 if (!parsed_name)
3066 return {{tag.contextKind(), ConstString(tag.name())}};
3067
3068 std::vector<CompilerContext> ctx;
3069 // assume everything is a namespace at first
3070 for (llvm::StringRef scope : parsed_name->scope) {
3071 ctx.emplace_back(CompilerContextKind::Namespace, ConstString(scope));
3072 }
3073 // we know the kind of our own type
3074 ctx.emplace_back(tag.contextKind(), ConstString(parsed_name->basename));
3075
3076 // try to find the kind of parents
3077 for (auto &el : llvm::reverse(llvm::drop_end(ctx))) {
3078 std::optional<TypeIndex> parent = GetParentType(ti);
3079 if (!parent)
3080 break;
3081
3082 ti = *parent;
3083 type = m_index->tpi().getType(ti);
3084 switch (type.kind()) {
3085 case LF_CLASS:
3086 case LF_STRUCTURE:
3087 case LF_INTERFACE:
3089 continue;
3090 case LF_UNION:
3092 continue;
3093 case LF_ENUM:
3094 el.kind = CompilerContextKind::Enum;
3095 continue;
3096 default:
3097 break;
3098 }
3099 break;
3100 }
3101 return ctx;
3102}
3103
3104std::optional<llvm::StringRef>
3106 const CompilandIndexItem *cci =
3107 m_index->compilands().GetCompiland(func_id.modi);
3108 if (!cci)
3109 return std::nullopt;
3110
3111 CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);
3112 if (sym_record.kind() != S_LPROC32 && sym_record.kind() != S_GPROC32)
3113 return std::nullopt;
3114
3115 ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
3116 if (auto err = SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc)) {
3117 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
3118 "Failed to deserialize ProcSym record: {0}");
3119 return std::nullopt;
3120 }
3121
3122 return FindMangledSymbol(SegmentOffset(proc.Segment, proc.CodeOffset),
3123 proc.FunctionType);
3124}
3125
3126std::optional<llvm::StringRef>
3128 TypeIndex function_type) {
3129 auto symbol = m_index->publics().findByAddress(m_index->symrecords(),
3130 so.segment, so.offset);
3131 if (!symbol)
3132 return std::nullopt;
3133
3134 llvm::StringRef name = symbol->first.Name;
3135 // For functions, we might need to strip the mangled name. See
3136 // StripMangledFunctionName for more info.
3137 if (!function_type.isNoneType() &&
3138 (symbol->first.Flags & PublicSymFlags::Function) != PublicSymFlags::None)
3139 name = StripMangledFunctionName(name, function_type);
3140
3141 return name;
3142}
3143
3144llvm::StringRef
3146 PdbTypeSymId func_ty) {
3147 // "In non-64 bit environments" (on x86 in pactice), __cdecl functions get
3148 // prefixed with an underscore. For compilers using LLVM, this happens in LLVM
3149 // (as opposed to the compiler frontend). Because of this, DWARF doesn't
3150 // contain the "full" mangled name in DW_AT_linkage_name for these functions.
3151 // We strip the mangling here for compatibility with DWARF. See
3152 // llvm.org/pr161676 and
3153 // https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names#FormatC
3154
3155 if (!mangled.starts_with('_') ||
3156 m_index->dbi().getMachineType() != PDB_Machine::x86)
3157 return mangled;
3158
3159 CVType cvt = m_index->tpi().getType(func_ty.index);
3160 PDB_CallingConv cc = PDB_CallingConv::NearC;
3161 if (cvt.kind() == LF_PROCEDURE) {
3162 ProcedureRecord proc;
3163 if (llvm::Error error =
3164 TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, proc))
3165 llvm::consumeError(std::move(error));
3166 cc = proc.CallConv;
3167 } else if (cvt.kind() == LF_MFUNCTION) {
3168 MemberFunctionRecord mfunc;
3169 if (llvm::Error error =
3170 TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfunc))
3171 llvm::consumeError(std::move(error));
3172 cc = mfunc.CallConv;
3173 } else {
3174 LLDB_LOG(GetLog(LLDBLog::Symbols), "Unexpected function type, got {0}",
3175 cvt.kind());
3176 return mangled;
3177 }
3178
3179 if (cc == PDB_CallingConv::NearC || cc == PDB_CallingConv::FarC)
3180 return mangled.drop_front();
3181
3182 return mangled;
3183}
3184
3186 for (CVType cvt : m_index->ipi().typeArray()) {
3187 switch (cvt.kind()) {
3188 case LF_UDT_SRC_LINE: {
3189 UdtSourceLineRecord udt_src;
3190 if (auto err = TypeDeserializer::deserializeAs(cvt, udt_src)) {
3191 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
3192 "Failed to deserialize UdtSourceLineRecord record: {0}");
3193 continue;
3194 }
3195 m_udt_declarations.try_emplace(
3196 udt_src.UDT, UdtDeclaration{/*FileNameIndex=*/udt_src.SourceFile,
3197 /*IsIpiIndex=*/true,
3198 /*Line=*/udt_src.LineNumber});
3199 } break;
3200 case LF_UDT_MOD_SRC_LINE: {
3201 UdtModSourceLineRecord udt_mod_src;
3202 if (auto err = TypeDeserializer::deserializeAs(cvt, udt_mod_src)) {
3204 GetLog(LLDBLog::Symbols), std::move(err),
3205 "Failed to deserialize UdtModSourceLineRecord record: {0}");
3206 continue;
3207 }
3208 // Some types might be contributed by multiple modules. We assume that
3209 // they all point to the same file and line because we can only provide
3210 // one location.
3211 m_udt_declarations.try_emplace(
3212 udt_mod_src.UDT,
3213 UdtDeclaration{/*FileNameIndex=*/udt_mod_src.SourceFile,
3214 /*IsIpiIndex=*/false,
3215 /*Line=*/udt_mod_src.LineNumber});
3216 } break;
3217 default:
3218 break;
3219 }
3220 }
3221}
3222
3223llvm::Expected<Declaration>
3225 std::call_once(m_cached_udt_declarations, [this] { CacheUdtDeclarations(); });
3226
3227 auto it = m_udt_declarations.find(type_id.index);
3228 if (it == m_udt_declarations.end())
3229 return llvm::createStringError("no UDT declaration found");
3230
3231 llvm::StringRef file_name;
3232 if (it->second.IsIpiIndex) {
3233 CVType cvt = m_index->ipi().getType(it->second.FileNameIndex);
3234 if (cvt.kind() != LF_STRING_ID)
3235 return llvm::createStringError("file name was not a LF_STRING_ID");
3236
3237 StringIdRecord sid;
3238 if (auto err = TypeDeserializer::deserializeAs(cvt, sid))
3239 return std::move(err);
3240 file_name = sid.String;
3241 } else {
3242 // The file name index is an index into the string table
3243 auto string_table = m_index->pdb().getStringTable();
3244 if (!string_table)
3245 return string_table.takeError();
3246
3247 llvm::Expected<llvm::StringRef> string =
3248 string_table->getStringTable().getString(
3249 it->second.FileNameIndex.getIndex());
3250 if (!string)
3251 return string.takeError();
3252 file_name = *string;
3253 }
3254
3255 // rustc sets the filename to "<unknown>" for some files
3256 if (file_name == "\\<unknown>")
3257 return Declaration();
3258
3259 return Declaration(FileSpec(file_name), it->second.Line);
3260}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:405
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 std::optional< std::string > findMatchingPDBFilePath(llvm::StringRef original_pdb_path, llvm::StringRef exe_path)
static bool IsFunctionPrologue(const CompilandIndexItem &cci, lldb::addr_t addr)
static llvm::StringRef DropScope(llvm::StringRef name)
static bool UseNativePDB()
A section + offset based address class.
Definition Address.h:62
lldb::addr_t GetFileAddress() const
Get the file address.
Definition Address.cpp:283
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
RangeList::Entry Range
Definition Block.h:44
lldb::VariableListSP GetBlockVariableList(bool can_create)
Get the variable list for this block only.
Definition Block.cpp:382
Block * FindInnermostBlockByOffset(const lldb::addr_t offset)
Definition Block.cpp:127
void SetBlockInfoHasBeenParsed(bool b, bool set_children)
Definition Block.cpp:469
lldb::BlockSP CreateChild(lldb::user_id_t uid)
Creates a block with the specified UID uid.
Definition Block.cpp:370
Function * CalculateSymbolContextFunction() override
Definition Block.cpp:150
void SetVariableList(lldb::VariableListSP &variable_list_sp)
Set accessor for the variable list.
Definition Block.h:310
Block * GetParent() const
Get the parent block.
Definition Block.cpp:202
bool GetStartAddress(Address &addr)
Definition Block.cpp:317
void SetDidParseVariables(bool b, bool set_children)
Definition Block.cpp:479
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.
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.
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.
Generic representation of a type in a programming language.
TypeSystemSPWrapper GetTypeSystem() const
Accessors.
A uniqued constant string class.
Definition ConstString.h:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
"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:100
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 collection class.
A file utility class.
Definition FileSpec.h:56
FileSpec CopyByAppendingPathComponent(llvm::StringRef component) const
Definition FileSpec.cpp:425
static std::optional< Style > GuessPathStyle(llvm::StringRef absolute_path)
Attempt to guess path style for a given path string.
Definition FileSpec.cpp:326
static bool Match(const FileSpec &pattern, const FileSpec &file)
Match FileSpec pattern against FileSpec file.
Definition FileSpec.cpp:317
llvm::StringRef GetFilename() const
Filename string const get accessor.
Definition FileSpec.h:248
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:380
FileSpec CopyByRemovingLastPathComponent() const
Definition FileSpec.cpp:431
llvm::sys::path::Style Style
Definition FileSpec.h:58
bool Exists(const FileSpec &file_spec) const
Returns whether the given file exists.
static FileSystem & Instance()
A class that describes a function.
Definition Function.h:386
const Address & GetAddress() const
Return the address of the function (its entry point).
Definition Function.h:439
Block & GetBlock(bool can_create)
Get accessor for the block list.
Definition Function.cpp:401
static void AppendLineEntryToSequence(Sequence &sequence, lldb::addr_t file_addr, uint32_t line, uint16_t column, uint16_t file_idx, bool is_start_of_statement, bool is_start_of_basic_block, bool is_prologue_end, bool is_epilogue_begin, bool is_terminal_entry)
Definition LineTable.cpp:59
A class that handles mangled names.
Definition Mangled.h:34
static bool IsMangledName(llvm::StringRef name)
Definition Mangled.cpp:39
lldb::ModuleSP GetModule() const
Get const accessor for the module pointer.
A class that encapsulates name lookup information.
Definition Module.h:935
lldb::FunctionNameType GetNameTypeMask() const
Definition Module.h:976
ConstString GetLookupName() const
Definition Module.h:974
ConstString GetName() const
Definition Module.h:972
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)
RangeData< lldb::addr_t, uint32_t, std::pair< uint32_t, uint32_t > > Entry
Definition RangeMap.h:462
void Append(const Entry &entry)
Definition RangeMap.h:474
Entry * FindEntryThatContains(B addr)
Definition RangeMap.h:583
"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.
const FileSpec & GetFileSpecAtIndex(size_t idx) const
void Append(const FileSpec &file)
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.
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.
lldb::CompUnitSP GetCompileUnitAtIndex(uint32_t idx) override
ObjectFile * GetObjectFile() override
Definition SymbolFile.h:590
virtual TypeList & GetTypeList()
Definition SymbolFile.h:663
lldb::ObjectFileSP m_objfile_sp
Definition SymbolFile.h:666
void SetCompileUnitAtIndex(uint32_t idx, const lldb::CompUnitSP &cu_sp)
SymbolFileCommon(lldb::ObjectFileSP objfile_sp)
Definition SymbolFile.h:575
uint32_t GetNumCompileUnits() override
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:634
virtual std::recursive_mutex & GetModuleMutex() const
Symbols file subclasses should override this to return the Module that owns the TypeSystem that this ...
bool ValueIsAddress() const
Definition Symbol.cpp:191
void SetType(lldb::SymbolType type)
Definition Symbol.h:199
Address & GetAddressRef()
Definition Symbol.h:78
void SetByteSize(lldb::addr_t size)
Definition Symbol.h:241
Symbol * SymbolAtIndex(size_t idx)
Definition Symtab.cpp:225
uint32_t AddSymbol(const Symbol &symbol)
Definition Symtab.cpp:61
size_t GetNumSymbols() const
Definition Symtab.cpp:74
static FileSpecList GetDefaultDebugFileSearchPaths()
Definition Target.cpp:2925
uint32_t GetSize() const
Definition TypeList.cpp:36
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
ConstString GetTypeBasename() const
Get the type basename to use when searching the type indexes in each SymbolFile object.
Definition Type.cpp:114
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:130
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:195
bool Done(const TypeQuery &query) const
Check if the type matching has found all of the matches that it needs.
Definition Type.cpp:201
bool AlreadySearched(lldb_private::SymbolFile *sym_file)
Check if a SymbolFile object has already been searched by this type match object.
Definition Type.cpp:191
A TypeSystem implementation based on Clang.
Interface for representing a type system.
Definition TypeSystem.h:72
virtual npdb::PdbAstBuilder * GetNativePDBParser()
Definition TypeSystem.h:94
@ 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
static std::optional< ParsedName > GetTypeScopeAndBasename(llvm::StringRef name)
Definition Type.cpp:801
void AddVariable(const lldb::VariableSP &var_sp)
RangeVector< lldb::addr_t, lldb::addr_t > RangeList
Definition Variable.h:27
virtual CompilerType GetOrCreateTypedefType(PdbGlobalSymId id)=0
virtual void Dump(Stream &stream, llvm::StringRef filter, bool show_color)=0
virtual CompilerDeclContext FindNamespaceDecl(CompilerDeclContext parent_ctx, llvm::StringRef name)=0
virtual bool CompleteType(CompilerType ct)=0
virtual void EnsureBlock(PdbCompilandSymId block_id)=0
virtual CompilerDeclContext GetParentDeclContext(PdbSymUid uid)=0
virtual CompilerType GetOrCreateType(PdbTypeSymId type)=0
virtual CompilerDecl GetOrCreateDeclForUid(PdbSymUid uid)=0
virtual void EnsureInlinedFunction(PdbCompilandSymId inlinesite_id)=0
virtual void ParseDeclsForContext(CompilerDeclContext context)=0
virtual CompilerDeclContext GetOrCreateDeclContextForUid(PdbSymUid uid)=0
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:42
llvm::pdb::TpiStream & tpi()
Definition PdbIndex.h:124
PdbCompilandId asCompiland() const
PdbCompilandSymId asCompilandSym() const
PdbTypeSymId asTypeSym() const
PdbSymUidKind kind() const
void CreateSimpleArgumentListTypes(llvm::codeview::TypeIndex arglist_ti)
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.
void CacheGlobalBaseNames()
Caches the basenames of symbols found in the globals stream.
llvm::Expected< Declaration > ResolveUdtDeclaration(PdbTypeSymId type_id)
lldb::VariableSP CreateGlobalVariable(PdbGlobalSymId var_id)
llvm::Expected< lldb::TypeSystemSP > GetTypeSystemForLanguage(lldb::LanguageType language) override
void InitializeObject() override
Initialize the SymbolFile object.
lldb_private::UniqueCStringMap< uint32_t > m_func_base_names
basename -> Global ID(s)
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
void DumpClangAST(Stream &s, llvm::StringRef filter, bool show_color) override
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
std::optional< llvm::StringRef > FindMangledFunctionName(PdbCompilandSymId id)
Find the mangled name for a function.
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)
lldb_private::UniqueCStringMap< uint32_t > m_func_method_names
method basename -> Global ID(s)
std::optional< llvm::codeview::TypeIndex > GetParentType(llvm::codeview::TypeIndex ti)
lldb_private::UniqueCStringMap< uint32_t > m_global_variable_base_names
global variable basename -> Global ID(s)
void FindFunctions(const Module::LookupInfo &lookup_info, const CompilerDeclContext &parent_decl_ctx, bool include_inlines, SymbolContextList &sc_list) override
std::unique_ptr< llvm::pdb::PDBFile > m_file_up
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.
std::optional< llvm::StringRef > FindMangledSymbol(SegmentOffset so, llvm::codeview::TypeIndex function_type=llvm::codeview::TypeIndex())
Find a symbol name at a specific address (so).
size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override
Block * GetOrCreateBlock(PdbCompilandSymId block_id)
lldb::VariableSP GetOrCreateLocalVariable(PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param, bool is_constant=false)
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)
std::vector< CompilerContext > GetContextForType(llvm::codeview::TypeIndex ti)
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
llvm::StringRef StripMangledFunctionName(llvm::StringRef mangled, PdbTypeSymId func_ty)
static void DebuggerInitialize(Debugger &debugger)
lldb::VariableSP CreateLocalVariable(PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param, bool is_constant=false)
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
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_private::UniqueCStringMap< uint32_t > m_func_full_names
mangled name/full function name -> Global ID(s)
lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override
lldb::TypeSP CreateFunctionType(PdbTypeSymId type_id, const llvm::codeview::MemberFunctionRecord &pr, CompilerType ct)
lldb_private::UniqueCStringMap< uint32_t > m_type_base_names
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)
llvm::DenseMap< llvm::codeview::TypeIndex, UdtDeclaration > m_udt_declarations
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
#define LLDB_INVALID_ADDRESS
uint64_t toOpaqueUid(const T &cid)
Definition PdbSymUid.h:111
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:129
llvm::Expected< DWARFExpression > MakeConstantLocationExpression(llvm::codeview::TypeIndex underlying_ti, llvm::pdb::TpiStream &tpi, const llvm::APSInt &constant, lldb::ModuleSP module)
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:746
bool IsForwardRefUdt(llvm::codeview::CVType cvt)
llvm::pdb::PDB_SymType CVSymToPDBSym(llvm::codeview::SymbolKind kind)
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:338
std::shared_ptr< lldb_private::Function > FunctionSP
std::shared_ptr< lldb_private::Block > BlockSP
std::shared_ptr< lldb_private::ObjectFile > ObjectFileSP
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
SymbolType
Symbol types.
@ eSymbolTypeAdditional
When symbols take more than one entry, the extra entries get this type.
std::shared_ptr< lldb_private::VariableList > VariableListSP
std::shared_ptr< lldb_private::SymbolFileType > SymbolFileTypeSP
std::shared_ptr< lldb_private::Variable > VariableSP
@ eValueTypeVariableGlobal
globals variable
@ eValueTypeVariableLocal
function local variables
@ eValueTypeVariableArgument
function argument variables
@ eValueTypeVariableStatic
static variable
@ eValueTypeVariableThreadLocal
thread local storage variable
uint64_t user_id_t
Definition lldb-types.h:83
std::shared_ptr< lldb_private::Section > SectionSP
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::Module > ModuleSP
std::shared_ptr< lldb_private::CompileUnit > CompUnitSP
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
CompilerContextKind contextKind() const
Definition PdbUtil.h:75
static CVTagRecord create(llvm::codeview::CVType type)
Definition PdbUtil.cpp:197
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:73
DWARFExpressionList location
Definition PdbUtil.h:115
llvm::codeview::TypeIndex type
Definition PdbUtil.h:114