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