xref: /src/contrib/llvm-project/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1cfca06d7SDimitry Andric //===-- SymbolFileNativePDB.cpp -------------------------------------------===//
294994d37SDimitry Andric //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
694994d37SDimitry Andric //
794994d37SDimitry Andric //===----------------------------------------------------------------------===//
894994d37SDimitry Andric 
994994d37SDimitry Andric #include "SymbolFileNativePDB.h"
1094994d37SDimitry Andric 
11cfca06d7SDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangUtil.h"
1294994d37SDimitry Andric #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
13b60736ecSDimitry Andric #include "Plugins/ObjectFile/PDB/ObjectFilePDB.h"
14cfca06d7SDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
1594994d37SDimitry Andric #include "lldb/Core/Module.h"
1694994d37SDimitry Andric #include "lldb/Core/PluginManager.h"
1794994d37SDimitry Andric #include "lldb/Symbol/CompileUnit.h"
1894994d37SDimitry Andric #include "lldb/Symbol/LineTable.h"
1994994d37SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
2094994d37SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
2194994d37SDimitry Andric #include "lldb/Symbol/SymbolVendor.h"
2294994d37SDimitry Andric #include "lldb/Symbol/Variable.h"
2394994d37SDimitry Andric #include "lldb/Symbol/VariableList.h"
24145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
25ead24645SDimitry Andric #include "lldb/Utility/Log.h"
2694994d37SDimitry Andric 
2794994d37SDimitry Andric #include "llvm/DebugInfo/CodeView/CVRecord.h"
2894994d37SDimitry Andric #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
2994994d37SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
3094994d37SDimitry Andric #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
3194994d37SDimitry Andric #include "llvm/DebugInfo/CodeView/RecordName.h"
3294994d37SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
3394994d37SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
3494994d37SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
3594994d37SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
3694994d37SDimitry Andric #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
3794994d37SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
3894994d37SDimitry Andric #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
39b60736ecSDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
4094994d37SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
4194994d37SDimitry Andric #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
4294994d37SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
43b60736ecSDimitry Andric #include "llvm/DebugInfo/PDB/PDB.h"
4494994d37SDimitry Andric #include "llvm/DebugInfo/PDB/PDBTypes.h"
4594994d37SDimitry Andric #include "llvm/Demangle/MicrosoftDemangle.h"
4694994d37SDimitry Andric #include "llvm/Object/COFF.h"
4794994d37SDimitry Andric #include "llvm/Support/Allocator.h"
4894994d37SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
4994994d37SDimitry Andric #include "llvm/Support/Error.h"
5094994d37SDimitry Andric #include "llvm/Support/ErrorOr.h"
5194994d37SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
5294994d37SDimitry Andric 
5394994d37SDimitry Andric #include "DWARFLocationExpression.h"
5494994d37SDimitry Andric #include "PdbSymUid.h"
5594994d37SDimitry Andric #include "PdbUtil.h"
5694994d37SDimitry Andric #include "UdtRecordCompleter.h"
57e3b55780SDimitry Andric #include <optional>
587fa27ce4SDimitry Andric #include <string_view>
5994994d37SDimitry Andric 
6094994d37SDimitry Andric using namespace lldb;
6194994d37SDimitry Andric using namespace lldb_private;
6294994d37SDimitry Andric using namespace npdb;
6394994d37SDimitry Andric using namespace llvm::codeview;
6494994d37SDimitry Andric using namespace llvm::pdb;
6594994d37SDimitry Andric 
66706b4fc4SDimitry Andric char SymbolFileNativePDB::ID;
67706b4fc4SDimitry Andric 
TranslateLanguage(PDB_Lang lang)6894994d37SDimitry Andric static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
6994994d37SDimitry Andric   switch (lang) {
7094994d37SDimitry Andric   case PDB_Lang::Cpp:
7194994d37SDimitry Andric     return lldb::LanguageType::eLanguageTypeC_plus_plus;
7294994d37SDimitry Andric   case PDB_Lang::C:
7394994d37SDimitry Andric     return lldb::LanguageType::eLanguageTypeC;
745f29bb8aSDimitry Andric   case PDB_Lang::Swift:
755f29bb8aSDimitry Andric     return lldb::LanguageType::eLanguageTypeSwift;
76145449b1SDimitry Andric   case PDB_Lang::Rust:
77145449b1SDimitry Andric     return lldb::LanguageType::eLanguageTypeRust;
787fa27ce4SDimitry Andric   case PDB_Lang::ObjC:
797fa27ce4SDimitry Andric     return lldb::LanguageType::eLanguageTypeObjC;
807fa27ce4SDimitry Andric   case PDB_Lang::ObjCpp:
817fa27ce4SDimitry Andric     return lldb::LanguageType::eLanguageTypeObjC_plus_plus;
8294994d37SDimitry Andric   default:
8394994d37SDimitry Andric     return lldb::LanguageType::eLanguageTypeUnknown;
8494994d37SDimitry Andric   }
8594994d37SDimitry Andric }
8694994d37SDimitry Andric 
8794994d37SDimitry Andric static std::unique_ptr<PDBFile>
loadMatchingPDBFile(std::string exe_path,llvm::BumpPtrAllocator & allocator)8894994d37SDimitry Andric loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
8994994d37SDimitry Andric   // Try to find a matching PDB for an EXE.
9094994d37SDimitry Andric   using namespace llvm::object;
9194994d37SDimitry Andric   auto expected_binary = createBinary(exe_path);
9294994d37SDimitry Andric 
9394994d37SDimitry Andric   // If the file isn't a PE/COFF executable, fail.
9494994d37SDimitry Andric   if (!expected_binary) {
9594994d37SDimitry Andric     llvm::consumeError(expected_binary.takeError());
9694994d37SDimitry Andric     return nullptr;
9794994d37SDimitry Andric   }
9894994d37SDimitry Andric   OwningBinary<Binary> binary = std::move(*expected_binary);
9994994d37SDimitry Andric 
100ead24645SDimitry Andric   // TODO: Avoid opening the PE/COFF binary twice by reading this information
101ead24645SDimitry Andric   // directly from the lldb_private::ObjectFile.
10294994d37SDimitry Andric   auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary());
10394994d37SDimitry Andric   if (!obj)
10494994d37SDimitry Andric     return nullptr;
10594994d37SDimitry Andric   const llvm::codeview::DebugInfo *pdb_info = nullptr;
10694994d37SDimitry Andric 
10794994d37SDimitry Andric   // If it doesn't have a debug directory, fail.
10894994d37SDimitry Andric   llvm::StringRef pdb_file;
109cfca06d7SDimitry Andric   if (llvm::Error e = obj->getDebugPDBInfo(pdb_info, pdb_file)) {
110cfca06d7SDimitry Andric     consumeError(std::move(e));
11194994d37SDimitry Andric     return nullptr;
112cfca06d7SDimitry Andric   }
11394994d37SDimitry Andric 
114b60736ecSDimitry Andric   // If the file doesn't exist, perhaps the path specified at build time
115b60736ecSDimitry Andric   // doesn't match the PDB's current location, so check the location of the
116b60736ecSDimitry Andric   // executable.
117b60736ecSDimitry Andric   if (!FileSystem::Instance().Exists(pdb_file)) {
118b60736ecSDimitry Andric     const auto exe_dir = FileSpec(exe_path).CopyByRemovingLastPathComponent();
119b60736ecSDimitry Andric     const auto pdb_name = FileSpec(pdb_file).GetFilename().GetCString();
120e3b55780SDimitry Andric     pdb_file = exe_dir.CopyByAppendingPathComponent(pdb_name).GetPathAsConstString().GetStringRef();
121b60736ecSDimitry Andric   }
122b60736ecSDimitry Andric 
123b60736ecSDimitry Andric   // If the file is not a PDB or if it doesn't have a matching GUID, fail.
124b60736ecSDimitry Andric   auto pdb = ObjectFilePDB::loadPDBFile(std::string(pdb_file), allocator);
12594994d37SDimitry Andric   if (!pdb)
12694994d37SDimitry Andric     return nullptr;
12794994d37SDimitry Andric 
12894994d37SDimitry Andric   auto expected_info = pdb->getPDBInfoStream();
12994994d37SDimitry Andric   if (!expected_info) {
13094994d37SDimitry Andric     llvm::consumeError(expected_info.takeError());
13194994d37SDimitry Andric     return nullptr;
13294994d37SDimitry Andric   }
13394994d37SDimitry Andric   llvm::codeview::GUID guid;
13494994d37SDimitry Andric   memcpy(&guid, pdb_info->PDB70.Signature, 16);
13594994d37SDimitry Andric 
13694994d37SDimitry Andric   if (expected_info->getGuid() != guid)
13794994d37SDimitry Andric     return nullptr;
13894994d37SDimitry Andric   return pdb;
13994994d37SDimitry Andric }
14094994d37SDimitry Andric 
IsFunctionPrologue(const CompilandIndexItem & cci,lldb::addr_t addr)14194994d37SDimitry Andric static bool IsFunctionPrologue(const CompilandIndexItem &cci,
14294994d37SDimitry Andric                                lldb::addr_t addr) {
14394994d37SDimitry Andric   // FIXME: Implement this.
14494994d37SDimitry Andric   return false;
14594994d37SDimitry Andric }
14694994d37SDimitry Andric 
IsFunctionEpilogue(const CompilandIndexItem & cci,lldb::addr_t addr)14794994d37SDimitry Andric static bool IsFunctionEpilogue(const CompilandIndexItem &cci,
14894994d37SDimitry Andric                                lldb::addr_t addr) {
14994994d37SDimitry Andric   // FIXME: Implement this.
15094994d37SDimitry Andric   return false;
15194994d37SDimitry Andric }
15294994d37SDimitry Andric 
GetSimpleTypeName(SimpleTypeKind kind)15394994d37SDimitry Andric static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) {
15494994d37SDimitry Andric   switch (kind) {
15594994d37SDimitry Andric   case SimpleTypeKind::Boolean128:
15694994d37SDimitry Andric   case SimpleTypeKind::Boolean16:
15794994d37SDimitry Andric   case SimpleTypeKind::Boolean32:
15894994d37SDimitry Andric   case SimpleTypeKind::Boolean64:
15994994d37SDimitry Andric   case SimpleTypeKind::Boolean8:
16094994d37SDimitry Andric     return "bool";
16194994d37SDimitry Andric   case SimpleTypeKind::Byte:
16294994d37SDimitry Andric   case SimpleTypeKind::UnsignedCharacter:
16394994d37SDimitry Andric     return "unsigned char";
16494994d37SDimitry Andric   case SimpleTypeKind::NarrowCharacter:
16594994d37SDimitry Andric     return "char";
16694994d37SDimitry Andric   case SimpleTypeKind::SignedCharacter:
16794994d37SDimitry Andric   case SimpleTypeKind::SByte:
16894994d37SDimitry Andric     return "signed char";
16994994d37SDimitry Andric   case SimpleTypeKind::Character16:
17094994d37SDimitry Andric     return "char16_t";
17194994d37SDimitry Andric   case SimpleTypeKind::Character32:
17294994d37SDimitry Andric     return "char32_t";
173145449b1SDimitry Andric   case SimpleTypeKind::Character8:
174145449b1SDimitry Andric     return "char8_t";
17594994d37SDimitry Andric   case SimpleTypeKind::Complex80:
17694994d37SDimitry Andric   case SimpleTypeKind::Complex64:
17794994d37SDimitry Andric   case SimpleTypeKind::Complex32:
17894994d37SDimitry Andric     return "complex";
17994994d37SDimitry Andric   case SimpleTypeKind::Float128:
18094994d37SDimitry Andric   case SimpleTypeKind::Float80:
18194994d37SDimitry Andric     return "long double";
18294994d37SDimitry Andric   case SimpleTypeKind::Float64:
18394994d37SDimitry Andric     return "double";
18494994d37SDimitry Andric   case SimpleTypeKind::Float32:
18594994d37SDimitry Andric     return "float";
18694994d37SDimitry Andric   case SimpleTypeKind::Float16:
18794994d37SDimitry Andric     return "single";
18894994d37SDimitry Andric   case SimpleTypeKind::Int128:
18994994d37SDimitry Andric     return "__int128";
19094994d37SDimitry Andric   case SimpleTypeKind::Int64:
19194994d37SDimitry Andric   case SimpleTypeKind::Int64Quad:
19294994d37SDimitry Andric     return "int64_t";
19394994d37SDimitry Andric   case SimpleTypeKind::Int32:
19494994d37SDimitry Andric     return "int";
19594994d37SDimitry Andric   case SimpleTypeKind::Int16:
19694994d37SDimitry Andric     return "short";
19794994d37SDimitry Andric   case SimpleTypeKind::UInt128:
19894994d37SDimitry Andric     return "unsigned __int128";
19994994d37SDimitry Andric   case SimpleTypeKind::UInt64:
20094994d37SDimitry Andric   case SimpleTypeKind::UInt64Quad:
20194994d37SDimitry Andric     return "uint64_t";
20294994d37SDimitry Andric   case SimpleTypeKind::HResult:
20394994d37SDimitry Andric     return "HRESULT";
20494994d37SDimitry Andric   case SimpleTypeKind::UInt32:
20594994d37SDimitry Andric     return "unsigned";
20694994d37SDimitry Andric   case SimpleTypeKind::UInt16:
20794994d37SDimitry Andric   case SimpleTypeKind::UInt16Short:
20894994d37SDimitry Andric     return "unsigned short";
20994994d37SDimitry Andric   case SimpleTypeKind::Int32Long:
21094994d37SDimitry Andric     return "long";
21194994d37SDimitry Andric   case SimpleTypeKind::UInt32Long:
21294994d37SDimitry Andric     return "unsigned long";
21394994d37SDimitry Andric   case SimpleTypeKind::Void:
21494994d37SDimitry Andric     return "void";
21594994d37SDimitry Andric   case SimpleTypeKind::WideCharacter:
21694994d37SDimitry Andric     return "wchar_t";
21794994d37SDimitry Andric   default:
21894994d37SDimitry Andric     return "";
21994994d37SDimitry Andric   }
22094994d37SDimitry Andric }
22194994d37SDimitry Andric 
IsClassRecord(TypeLeafKind kind)22294994d37SDimitry Andric static bool IsClassRecord(TypeLeafKind kind) {
22394994d37SDimitry Andric   switch (kind) {
22494994d37SDimitry Andric   case LF_STRUCTURE:
22594994d37SDimitry Andric   case LF_CLASS:
22694994d37SDimitry Andric   case LF_INTERFACE:
22794994d37SDimitry Andric     return true;
22894994d37SDimitry Andric   default:
22994994d37SDimitry Andric     return false;
23094994d37SDimitry Andric   }
23194994d37SDimitry Andric }
23294994d37SDimitry Andric 
233e3b55780SDimitry Andric static std::optional<CVTagRecord>
GetNestedTagDefinition(const NestedTypeRecord & Record,const CVTagRecord & parent,TpiStream & tpi)234e3b55780SDimitry Andric GetNestedTagDefinition(const NestedTypeRecord &Record,
235e3b55780SDimitry Andric                        const CVTagRecord &parent, TpiStream &tpi) {
236e3b55780SDimitry Andric   // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it
237e3b55780SDimitry Andric   // is also used to indicate the primary definition of a nested class.  That is
238e3b55780SDimitry Andric   // to say, if you have:
239e3b55780SDimitry Andric   // struct A {
240e3b55780SDimitry Andric   //   struct B {};
241e3b55780SDimitry Andric   //   using C = B;
242e3b55780SDimitry Andric   // };
243e3b55780SDimitry Andric   // Then in the debug info, this will appear as:
244e3b55780SDimitry Andric   // LF_STRUCTURE `A::B` [type index = N]
245e3b55780SDimitry Andric   // LF_STRUCTURE `A`
246e3b55780SDimitry Andric   //   LF_NESTTYPE [name = `B`, index = N]
247e3b55780SDimitry Andric   //   LF_NESTTYPE [name = `C`, index = N]
248e3b55780SDimitry Andric   // In order to accurately reconstruct the decl context hierarchy, we need to
249e3b55780SDimitry Andric   // know which ones are actual definitions and which ones are just aliases.
250e3b55780SDimitry Andric 
251e3b55780SDimitry Andric   // If it's a simple type, then this is something like `using foo = int`.
252e3b55780SDimitry Andric   if (Record.Type.isSimple())
253e3b55780SDimitry Andric     return std::nullopt;
254e3b55780SDimitry Andric 
255e3b55780SDimitry Andric   CVType cvt = tpi.getType(Record.Type);
256e3b55780SDimitry Andric 
257e3b55780SDimitry Andric   if (!IsTagRecord(cvt))
258e3b55780SDimitry Andric     return std::nullopt;
259e3b55780SDimitry Andric 
260e3b55780SDimitry Andric   // If it's an inner definition, then treat whatever name we have here as a
261e3b55780SDimitry Andric   // single component of a mangled name.  So we can inject it into the parent's
262e3b55780SDimitry Andric   // mangled name to see if it matches.
263e3b55780SDimitry Andric   CVTagRecord child = CVTagRecord::create(cvt);
264e3b55780SDimitry Andric   std::string qname = std::string(parent.asTag().getUniqueName());
265e3b55780SDimitry Andric   if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4)
266e3b55780SDimitry Andric     return std::nullopt;
267e3b55780SDimitry Andric 
268e3b55780SDimitry Andric   // qname[3] is the tag type identifier (struct, class, union, etc).  Since the
269e3b55780SDimitry Andric   // inner tag type is not necessarily the same as the outer tag type, re-write
270e3b55780SDimitry Andric   // it to match the inner tag type.
271e3b55780SDimitry Andric   qname[3] = child.asTag().getUniqueName()[3];
272e3b55780SDimitry Andric   std::string piece;
273e3b55780SDimitry Andric   if (qname[3] == 'W')
274e3b55780SDimitry Andric     piece = "4";
275e3b55780SDimitry Andric   piece += Record.Name;
276e3b55780SDimitry Andric   piece.push_back('@');
277e3b55780SDimitry Andric   qname.insert(4, std::move(piece));
278e3b55780SDimitry Andric   if (qname != child.asTag().UniqueName)
279e3b55780SDimitry Andric     return std::nullopt;
280e3b55780SDimitry Andric 
281e3b55780SDimitry Andric   return std::move(child);
282e3b55780SDimitry Andric }
283e3b55780SDimitry Andric 
Initialize()28494994d37SDimitry Andric void SymbolFileNativePDB::Initialize() {
28594994d37SDimitry Andric   PluginManager::RegisterPlugin(GetPluginNameStatic(),
28694994d37SDimitry Andric                                 GetPluginDescriptionStatic(), CreateInstance,
28794994d37SDimitry Andric                                 DebuggerInitialize);
28894994d37SDimitry Andric }
28994994d37SDimitry Andric 
Terminate()29094994d37SDimitry Andric void SymbolFileNativePDB::Terminate() {
29194994d37SDimitry Andric   PluginManager::UnregisterPlugin(CreateInstance);
29294994d37SDimitry Andric }
29394994d37SDimitry Andric 
DebuggerInitialize(Debugger & debugger)29494994d37SDimitry Andric void SymbolFileNativePDB::DebuggerInitialize(Debugger &debugger) {}
29594994d37SDimitry Andric 
GetPluginDescriptionStatic()296c0981da4SDimitry Andric llvm::StringRef SymbolFileNativePDB::GetPluginDescriptionStatic() {
29794994d37SDimitry Andric   return "Microsoft PDB debug symbol cross-platform file reader.";
29894994d37SDimitry Andric }
29994994d37SDimitry Andric 
CreateInstance(ObjectFileSP objfile_sp)300ead24645SDimitry Andric SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFileSP objfile_sp) {
301ead24645SDimitry Andric   return new SymbolFileNativePDB(std::move(objfile_sp));
30294994d37SDimitry Andric }
30394994d37SDimitry Andric 
SymbolFileNativePDB(ObjectFileSP objfile_sp)304ead24645SDimitry Andric SymbolFileNativePDB::SymbolFileNativePDB(ObjectFileSP objfile_sp)
305145449b1SDimitry Andric     : SymbolFileCommon(std::move(objfile_sp)) {}
30694994d37SDimitry Andric 
307344a3780SDimitry Andric SymbolFileNativePDB::~SymbolFileNativePDB() = default;
30894994d37SDimitry Andric 
CalculateAbilities()30994994d37SDimitry Andric uint32_t SymbolFileNativePDB::CalculateAbilities() {
31094994d37SDimitry Andric   uint32_t abilities = 0;
311ead24645SDimitry Andric   if (!m_objfile_sp)
31294994d37SDimitry Andric     return 0;
31394994d37SDimitry Andric 
31494994d37SDimitry Andric   if (!m_index) {
31594994d37SDimitry Andric     // Lazily load and match the PDB file, but only do this once.
316b60736ecSDimitry Andric     PDBFile *pdb_file;
317b60736ecSDimitry Andric     if (auto *pdb = llvm::dyn_cast<ObjectFilePDB>(m_objfile_sp.get())) {
318b60736ecSDimitry Andric       pdb_file = &pdb->GetPDBFile();
319b60736ecSDimitry Andric     } else {
320b60736ecSDimitry Andric       m_file_up = loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(),
321b60736ecSDimitry Andric                                       m_allocator);
322b60736ecSDimitry Andric       pdb_file = m_file_up.get();
32394994d37SDimitry Andric     }
32494994d37SDimitry Andric 
325b60736ecSDimitry Andric     if (!pdb_file)
32694994d37SDimitry Andric       return 0;
32794994d37SDimitry Andric 
328b60736ecSDimitry Andric     auto expected_index = PdbIndex::create(pdb_file);
32994994d37SDimitry Andric     if (!expected_index) {
33094994d37SDimitry Andric       llvm::consumeError(expected_index.takeError());
33194994d37SDimitry Andric       return 0;
33294994d37SDimitry Andric     }
33394994d37SDimitry Andric     m_index = std::move(*expected_index);
33494994d37SDimitry Andric   }
33594994d37SDimitry Andric   if (!m_index)
33694994d37SDimitry Andric     return 0;
33794994d37SDimitry Andric 
33894994d37SDimitry Andric   // We don't especially have to be precise here.  We only distinguish between
33994994d37SDimitry Andric   // stripped and not stripped.
34094994d37SDimitry Andric   abilities = kAllAbilities;
34194994d37SDimitry Andric 
34294994d37SDimitry Andric   if (m_index->dbi().isStripped())
34394994d37SDimitry Andric     abilities &= ~(Blocks | LocalVariables);
34494994d37SDimitry Andric   return abilities;
34594994d37SDimitry Andric }
34694994d37SDimitry Andric 
InitializeObject()34794994d37SDimitry Andric void SymbolFileNativePDB::InitializeObject() {
348b60736ecSDimitry Andric   m_obj_load_address = m_objfile_sp->GetModule()
349b60736ecSDimitry Andric                            ->GetObjectFile()
350b60736ecSDimitry Andric                            ->GetBaseAddress()
351b60736ecSDimitry Andric                            .GetFileAddress();
35294994d37SDimitry Andric   m_index->SetLoadAddress(m_obj_load_address);
35394994d37SDimitry Andric   m_index->ParseSectionContribs();
35494994d37SDimitry Andric 
355ead24645SDimitry Andric   auto ts_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage(
35694994d37SDimitry Andric       lldb::eLanguageTypeC_plus_plus);
357ead24645SDimitry Andric   if (auto err = ts_or_err.takeError()) {
358145449b1SDimitry Andric     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
3597fa27ce4SDimitry Andric                    "Failed to initialize: {0}");
360ead24645SDimitry Andric   } else {
361e3b55780SDimitry Andric     if (auto ts = *ts_or_err)
362e3b55780SDimitry Andric       ts->SetSymbolFile(this);
363e3b55780SDimitry Andric     BuildParentMap();
364ead24645SDimitry Andric   }
36594994d37SDimitry Andric }
36694994d37SDimitry Andric 
CalculateNumCompileUnits()367ead24645SDimitry Andric uint32_t SymbolFileNativePDB::CalculateNumCompileUnits() {
36894994d37SDimitry Andric   const DbiModuleList &modules = m_index->dbi().modules();
36994994d37SDimitry Andric   uint32_t count = modules.getModuleCount();
37094994d37SDimitry Andric   if (count == 0)
37194994d37SDimitry Andric     return count;
37294994d37SDimitry Andric 
37394994d37SDimitry Andric   // The linker can inject an additional "dummy" compilation unit into the
37494994d37SDimitry Andric   // PDB. Ignore this special compile unit for our purposes, if it is there.
37594994d37SDimitry Andric   // It is always the last one.
37694994d37SDimitry Andric   DbiModuleDescriptor last = modules.getModuleDescriptor(count - 1);
37794994d37SDimitry Andric   if (last.getModuleName() == "* Linker *")
37894994d37SDimitry Andric     --count;
37994994d37SDimitry Andric   return count;
38094994d37SDimitry Andric }
38194994d37SDimitry Andric 
CreateBlock(PdbCompilandSymId block_id)38294994d37SDimitry Andric Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
38394994d37SDimitry Andric   CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
38494994d37SDimitry Andric   CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
38594994d37SDimitry Andric   CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
3866f8fc217SDimitry Andric   lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id);
3876f8fc217SDimitry Andric   BlockSP child_block = std::make_shared<Block>(opaque_block_uid);
388e3b55780SDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
389e3b55780SDimitry Andric   if (auto err = ts_or_err.takeError())
390e3b55780SDimitry Andric     return *child_block;
391e3b55780SDimitry Andric   auto ts = *ts_or_err;
392e3b55780SDimitry Andric   if (!ts)
393e3b55780SDimitry Andric     return *child_block;
394e3b55780SDimitry Andric   PdbAstBuilder* ast_builder = ts->GetNativePDBParser();
3956f8fc217SDimitry Andric 
3966f8fc217SDimitry Andric   switch (sym.kind()) {
3976f8fc217SDimitry Andric   case S_GPROC32:
3986f8fc217SDimitry Andric   case S_LPROC32: {
3996f8fc217SDimitry Andric     // This is a function.  It must be global.  Creating the Function entry
4006f8fc217SDimitry Andric     // for it automatically creates a block for it.
4016f8fc217SDimitry Andric     FunctionSP func = GetOrCreateFunction(block_id, *comp_unit);
402e3b55780SDimitry Andric     if (func) {
4036f8fc217SDimitry Andric       Block &block = func->GetBlock(false);
4046f8fc217SDimitry Andric       if (block.GetNumRanges() == 0)
4056f8fc217SDimitry Andric         block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize()));
4066f8fc217SDimitry Andric       return block;
40794994d37SDimitry Andric     }
408e3b55780SDimitry Andric     break;
409e3b55780SDimitry Andric   }
4106f8fc217SDimitry Andric   case S_BLOCK32: {
41194994d37SDimitry Andric     // This is a block.  Its parent is either a function or another block.  In
4126f8fc217SDimitry Andric     // either case, its parent can be viewed as a block (e.g. a function
4136f8fc217SDimitry Andric     // contains 1 big block.  So just get the parent block and add this block
4146f8fc217SDimitry Andric     // to it.
41594994d37SDimitry Andric     BlockSym block(static_cast<SymbolRecordKind>(sym.kind()));
41694994d37SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<BlockSym>(sym, block));
41794994d37SDimitry Andric     lldbassert(block.Parent != 0);
41894994d37SDimitry Andric     PdbCompilandSymId parent_id(block_id.modi, block.Parent);
41994994d37SDimitry Andric     Block &parent_block = GetOrCreateBlock(parent_id);
420e3b55780SDimitry Andric     Function *func = parent_block.CalculateSymbolContextFunction();
421e3b55780SDimitry Andric     lldbassert(func);
422e3b55780SDimitry Andric     lldb::addr_t block_base =
423e3b55780SDimitry Andric         m_index->MakeVirtualAddress(block.Segment, block.CodeOffset);
424e3b55780SDimitry Andric     lldb::addr_t func_base =
425e3b55780SDimitry Andric         func->GetAddressRange().GetBaseAddress().GetFileAddress();
426e3b55780SDimitry Andric     if (block_base >= func_base)
427e3b55780SDimitry Andric       child_block->AddRange(Block::Range(block_base - func_base, block.CodeSize));
428e3b55780SDimitry Andric     else {
429e3b55780SDimitry Andric       GetObjectFile()->GetModule()->ReportError(
430e3b55780SDimitry Andric           "S_BLOCK32 at modi: {0:d} offset: {1:d}: adding range "
431e3b55780SDimitry Andric           "[{2:x16}-{3:x16}) which has a base that is less than the "
432e3b55780SDimitry Andric           "function's "
433e3b55780SDimitry Andric           "low PC 0x%" PRIx64 ". Please file a bug and attach the file at the "
434e3b55780SDimitry Andric           "start of this error message",
435e3b55780SDimitry Andric           block_id.modi, block_id.offset, block_base,
436e3b55780SDimitry Andric           block_base + block.CodeSize, func_base);
437e3b55780SDimitry Andric     }
4386f8fc217SDimitry Andric     parent_block.AddChild(child_block);
439e3b55780SDimitry Andric     ast_builder->GetOrCreateBlockDecl(block_id);
4406f8fc217SDimitry Andric     m_blocks.insert({opaque_block_uid, child_block});
4416f8fc217SDimitry Andric     break;
4426f8fc217SDimitry Andric   }
4436f8fc217SDimitry Andric   case S_INLINESITE: {
4446f8fc217SDimitry Andric     // This ensures line table is parsed first so we have inline sites info.
4456f8fc217SDimitry Andric     comp_unit->GetLineTable();
4466f8fc217SDimitry Andric 
4476f8fc217SDimitry Andric     std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid];
4486f8fc217SDimitry Andric     Block &parent_block = GetOrCreateBlock(inline_site->parent_id);
44994994d37SDimitry Andric     parent_block.AddChild(child_block);
450e3b55780SDimitry Andric     ast_builder->GetOrCreateInlinedFunctionDecl(block_id);
4516f8fc217SDimitry Andric     // Copy ranges from InlineSite to Block.
4526f8fc217SDimitry Andric     for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) {
4536f8fc217SDimitry Andric       auto *entry = inline_site->ranges.GetEntryAtIndex(i);
4546f8fc217SDimitry Andric       child_block->AddRange(
4556f8fc217SDimitry Andric           Block::Range(entry->GetRangeBase(), entry->GetByteSize()));
4566f8fc217SDimitry Andric     }
4576f8fc217SDimitry Andric     child_block->FinalizeRanges();
45894994d37SDimitry Andric 
4596f8fc217SDimitry Andric     // Get the inlined function callsite info.
4606f8fc217SDimitry Andric     Declaration &decl = inline_site->inline_function_info->GetDeclaration();
4616f8fc217SDimitry Andric     Declaration &callsite = inline_site->inline_function_info->GetCallSite();
4626f8fc217SDimitry Andric     child_block->SetInlinedFunctionInfo(
4636f8fc217SDimitry Andric         inline_site->inline_function_info->GetName().GetCString(), nullptr,
4646f8fc217SDimitry Andric         &decl, &callsite);
46594994d37SDimitry Andric     m_blocks.insert({opaque_block_uid, child_block});
4666f8fc217SDimitry Andric     break;
4676f8fc217SDimitry Andric   }
4686f8fc217SDimitry Andric   default:
4696f8fc217SDimitry Andric     lldbassert(false && "Symbol is not a block!");
4706f8fc217SDimitry Andric   }
4716f8fc217SDimitry Andric 
47294994d37SDimitry Andric   return *child_block;
47394994d37SDimitry Andric }
47494994d37SDimitry Andric 
CreateFunction(PdbCompilandSymId func_id,CompileUnit & comp_unit)47594994d37SDimitry Andric lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
47694994d37SDimitry Andric                                                      CompileUnit &comp_unit) {
47794994d37SDimitry Andric   const CompilandIndexItem *cci =
47894994d37SDimitry Andric       m_index->compilands().GetCompiland(func_id.modi);
47994994d37SDimitry Andric   lldbassert(cci);
48094994d37SDimitry Andric   CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);
48194994d37SDimitry Andric 
48294994d37SDimitry Andric   lldbassert(sym_record.kind() == S_LPROC32 || sym_record.kind() == S_GPROC32);
48394994d37SDimitry Andric   SegmentOffsetLength sol = GetSegmentOffsetAndLength(sym_record);
48494994d37SDimitry Andric 
485145449b1SDimitry Andric   auto file_vm_addr =
486145449b1SDimitry Andric       m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);
48794994d37SDimitry Andric   if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
48894994d37SDimitry Andric     return nullptr;
48994994d37SDimitry Andric 
49094994d37SDimitry Andric   AddressRange func_range(file_vm_addr, sol.length,
49194994d37SDimitry Andric                           comp_unit.GetModule()->GetSectionList());
49294994d37SDimitry Andric   if (!func_range.GetBaseAddress().IsValid())
49394994d37SDimitry Andric     return nullptr;
49494994d37SDimitry Andric 
49594994d37SDimitry Andric   ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
49694994d37SDimitry Andric   cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));
49794994d37SDimitry Andric   if (proc.FunctionType == TypeIndex::None())
49894994d37SDimitry Andric     return nullptr;
49994994d37SDimitry Andric   TypeSP func_type = GetOrCreateType(proc.FunctionType);
50094994d37SDimitry Andric   if (!func_type)
50194994d37SDimitry Andric     return nullptr;
50294994d37SDimitry Andric 
50394994d37SDimitry Andric   PdbTypeSymId sig_id(proc.FunctionType, false);
50494994d37SDimitry Andric   Mangled mangled(proc.Name);
50594994d37SDimitry Andric   FunctionSP func_sp = std::make_shared<Function>(
50694994d37SDimitry Andric       &comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled,
50794994d37SDimitry Andric       func_type.get(), func_range);
50894994d37SDimitry Andric 
50994994d37SDimitry Andric   comp_unit.AddFunction(func_sp);
51094994d37SDimitry Andric 
511e3b55780SDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(comp_unit.GetLanguage());
512e3b55780SDimitry Andric   if (auto err = ts_or_err.takeError())
513e3b55780SDimitry Andric     return func_sp;
514e3b55780SDimitry Andric   auto ts = *ts_or_err;
515e3b55780SDimitry Andric   if (!ts)
516e3b55780SDimitry Andric     return func_sp;
517e3b55780SDimitry Andric   ts->GetNativePDBParser()->GetOrCreateFunctionDecl(func_id);
51894994d37SDimitry Andric 
51994994d37SDimitry Andric   return func_sp;
52094994d37SDimitry Andric }
52194994d37SDimitry Andric 
52294994d37SDimitry Andric CompUnitSP
CreateCompileUnit(const CompilandIndexItem & cci)52394994d37SDimitry Andric SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) {
52494994d37SDimitry Andric   lldb::LanguageType lang =
52594994d37SDimitry Andric       cci.m_compile_opts ? TranslateLanguage(cci.m_compile_opts->getLanguage())
52694994d37SDimitry Andric                          : lldb::eLanguageTypeUnknown;
52794994d37SDimitry Andric 
52894994d37SDimitry Andric   LazyBool optimized = eLazyBoolNo;
52994994d37SDimitry Andric   if (cci.m_compile_opts && cci.m_compile_opts->hasOptimizations())
53094994d37SDimitry Andric     optimized = eLazyBoolYes;
53194994d37SDimitry Andric 
53294994d37SDimitry Andric   llvm::SmallString<64> source_file_name =
53394994d37SDimitry Andric       m_index->compilands().GetMainSourceFile(cci);
534145449b1SDimitry Andric   FileSpec fs(llvm::sys::path::convert_to_slash(
535145449b1SDimitry Andric       source_file_name, llvm::sys::path::Style::windows_backslash));
53694994d37SDimitry Andric 
5374df029ccSDimitry Andric   CompUnitSP cu_sp = std::make_shared<CompileUnit>(
5384df029ccSDimitry Andric       m_objfile_sp->GetModule(), nullptr, std::make_shared<SupportFile>(fs),
53994994d37SDimitry Andric       toOpaqueUid(cci.m_id), lang, optimized);
54094994d37SDimitry Andric 
541ead24645SDimitry Andric   SetCompileUnitAtIndex(cci.m_id.modi, cu_sp);
54294994d37SDimitry Andric   return cu_sp;
54394994d37SDimitry Andric }
54494994d37SDimitry Andric 
CreateModifierType(PdbTypeSymId type_id,const ModifierRecord & mr,CompilerType ct)54594994d37SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id,
54694994d37SDimitry Andric                                                      const ModifierRecord &mr,
54794994d37SDimitry Andric                                                      CompilerType ct) {
54894994d37SDimitry Andric   TpiStream &stream = m_index->tpi();
54994994d37SDimitry Andric 
55094994d37SDimitry Andric   std::string name;
55194994d37SDimitry Andric   if (mr.ModifiedType.isSimple())
552cfca06d7SDimitry Andric     name = std::string(GetSimpleTypeName(mr.ModifiedType.getSimpleKind()));
55394994d37SDimitry Andric   else
55494994d37SDimitry Andric     name = computeTypeName(stream.typeCollection(), mr.ModifiedType);
55594994d37SDimitry Andric   Declaration decl;
55694994d37SDimitry Andric   lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType);
55794994d37SDimitry Andric 
558e3b55780SDimitry Andric   return MakeType(toOpaqueUid(type_id), ConstString(name),
559b60736ecSDimitry Andric                   modified_type->GetByteSize(nullptr), nullptr,
560e3b55780SDimitry Andric                   LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
561e3b55780SDimitry Andric                   Type::ResolveState::Full);
56294994d37SDimitry Andric }
56394994d37SDimitry Andric 
56494994d37SDimitry Andric lldb::TypeSP
CreatePointerType(PdbTypeSymId type_id,const llvm::codeview::PointerRecord & pr,CompilerType ct)56594994d37SDimitry Andric SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id,
56694994d37SDimitry Andric                                        const llvm::codeview::PointerRecord &pr,
56794994d37SDimitry Andric                                        CompilerType ct) {
56894994d37SDimitry Andric   TypeSP pointee = GetOrCreateType(pr.ReferentType);
56994994d37SDimitry Andric   if (!pointee)
57094994d37SDimitry Andric     return nullptr;
57194994d37SDimitry Andric 
57294994d37SDimitry Andric   if (pr.isPointerToMember()) {
57394994d37SDimitry Andric     MemberPointerInfo mpi = pr.getMemberInfo();
57494994d37SDimitry Andric     GetOrCreateType(mpi.ContainingType);
57594994d37SDimitry Andric   }
57694994d37SDimitry Andric 
57794994d37SDimitry Andric   Declaration decl;
578e3b55780SDimitry Andric   return MakeType(toOpaqueUid(type_id), ConstString(), pr.getSize(), nullptr,
579e3b55780SDimitry Andric                   LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
580706b4fc4SDimitry Andric                   Type::ResolveState::Full);
58194994d37SDimitry Andric }
58294994d37SDimitry Andric 
CreateSimpleType(TypeIndex ti,CompilerType ct)58394994d37SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
58494994d37SDimitry Andric                                                    CompilerType ct) {
58594994d37SDimitry Andric   uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false));
58694994d37SDimitry Andric   if (ti == TypeIndex::NullptrT()) {
58794994d37SDimitry Andric     Declaration decl;
588e3b55780SDimitry Andric     return MakeType(uid, ConstString("std::nullptr_t"), 0, nullptr,
589e3b55780SDimitry Andric                     LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
590e3b55780SDimitry Andric                     Type::ResolveState::Full);
59194994d37SDimitry Andric   }
59294994d37SDimitry Andric 
59394994d37SDimitry Andric   if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
59494994d37SDimitry Andric     TypeSP direct_sp = GetOrCreateType(ti.makeDirect());
59594994d37SDimitry Andric     uint32_t pointer_size = 0;
59694994d37SDimitry Andric     switch (ti.getSimpleMode()) {
59794994d37SDimitry Andric     case SimpleTypeMode::FarPointer32:
59894994d37SDimitry Andric     case SimpleTypeMode::NearPointer32:
59994994d37SDimitry Andric       pointer_size = 4;
60094994d37SDimitry Andric       break;
60194994d37SDimitry Andric     case SimpleTypeMode::NearPointer64:
60294994d37SDimitry Andric       pointer_size = 8;
60394994d37SDimitry Andric       break;
60494994d37SDimitry Andric     default:
60594994d37SDimitry Andric       // 128-bit and 16-bit pointers unsupported.
60694994d37SDimitry Andric       return nullptr;
60794994d37SDimitry Andric     }
60894994d37SDimitry Andric     Declaration decl;
609e3b55780SDimitry Andric     return MakeType(uid, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,
610706b4fc4SDimitry Andric                     Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
61194994d37SDimitry Andric   }
61294994d37SDimitry Andric 
61394994d37SDimitry Andric   if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
61494994d37SDimitry Andric     return nullptr;
61594994d37SDimitry Andric 
61694994d37SDimitry Andric   size_t size = GetTypeSizeForSimpleKind(ti.getSimpleKind());
61794994d37SDimitry Andric   llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind());
61894994d37SDimitry Andric 
61994994d37SDimitry Andric   Declaration decl;
620e3b55780SDimitry Andric   return MakeType(uid, ConstString(type_name), size, nullptr, LLDB_INVALID_UID,
621e3b55780SDimitry Andric                   Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
62294994d37SDimitry Andric }
62394994d37SDimitry Andric 
GetUnqualifiedTypeName(const TagRecord & record)62494994d37SDimitry Andric static std::string GetUnqualifiedTypeName(const TagRecord &record) {
62594994d37SDimitry Andric   if (!record.hasUniqueName()) {
62694994d37SDimitry Andric     MSVCUndecoratedNameParser parser(record.Name);
62794994d37SDimitry Andric     llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
62894994d37SDimitry Andric 
629cfca06d7SDimitry Andric     return std::string(specs.back().GetBaseName());
63094994d37SDimitry Andric   }
63194994d37SDimitry Andric 
63294994d37SDimitry Andric   llvm::ms_demangle::Demangler demangler;
6337fa27ce4SDimitry Andric   std::string_view sv(record.UniqueName.begin(), record.UniqueName.size());
63494994d37SDimitry Andric   llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
63594994d37SDimitry Andric   if (demangler.Error)
636cfca06d7SDimitry Andric     return std::string(record.Name);
63794994d37SDimitry Andric 
63894994d37SDimitry Andric   llvm::ms_demangle::IdentifierNode *idn =
63994994d37SDimitry Andric       ttn->QualifiedName->getUnqualifiedIdentifier();
64094994d37SDimitry Andric   return idn->toString();
64194994d37SDimitry Andric }
64294994d37SDimitry Andric 
64394994d37SDimitry Andric lldb::TypeSP
CreateClassStructUnion(PdbTypeSymId type_id,const TagRecord & record,size_t size,CompilerType ct)64494994d37SDimitry Andric SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id,
64594994d37SDimitry Andric                                             const TagRecord &record,
64694994d37SDimitry Andric                                             size_t size, CompilerType ct) {
64794994d37SDimitry Andric 
64894994d37SDimitry Andric   std::string uname = GetUnqualifiedTypeName(record);
64994994d37SDimitry Andric 
65094994d37SDimitry Andric   // FIXME: Search IPI stream for LF_UDT_MOD_SRC_LINE.
65194994d37SDimitry Andric   Declaration decl;
652e3b55780SDimitry Andric   return MakeType(toOpaqueUid(type_id), ConstString(uname), size, nullptr,
653e3b55780SDimitry Andric                   LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
654706b4fc4SDimitry Andric                   Type::ResolveState::Forward);
65594994d37SDimitry Andric }
65694994d37SDimitry Andric 
CreateTagType(PdbTypeSymId type_id,const ClassRecord & cr,CompilerType ct)65794994d37SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
65894994d37SDimitry Andric                                                 const ClassRecord &cr,
65994994d37SDimitry Andric                                                 CompilerType ct) {
66094994d37SDimitry Andric   return CreateClassStructUnion(type_id, cr, cr.getSize(), ct);
66194994d37SDimitry Andric }
66294994d37SDimitry Andric 
CreateTagType(PdbTypeSymId type_id,const UnionRecord & ur,CompilerType ct)66394994d37SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
66494994d37SDimitry Andric                                                 const UnionRecord &ur,
66594994d37SDimitry Andric                                                 CompilerType ct) {
66694994d37SDimitry Andric   return CreateClassStructUnion(type_id, ur, ur.getSize(), ct);
66794994d37SDimitry Andric }
66894994d37SDimitry Andric 
CreateTagType(PdbTypeSymId type_id,const EnumRecord & er,CompilerType ct)66994994d37SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
67094994d37SDimitry Andric                                                 const EnumRecord &er,
67194994d37SDimitry Andric                                                 CompilerType ct) {
67294994d37SDimitry Andric   std::string uname = GetUnqualifiedTypeName(er);
67394994d37SDimitry Andric 
67494994d37SDimitry Andric   Declaration decl;
67594994d37SDimitry Andric   TypeSP underlying_type = GetOrCreateType(er.UnderlyingType);
67694994d37SDimitry Andric 
677e3b55780SDimitry Andric   return MakeType(toOpaqueUid(type_id), ConstString(uname),
678e3b55780SDimitry Andric                   underlying_type->GetByteSize(nullptr), nullptr,
679e3b55780SDimitry Andric                   LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
680e3b55780SDimitry Andric                   ct, lldb_private::Type::ResolveState::Forward);
68194994d37SDimitry Andric }
68294994d37SDimitry Andric 
CreateArrayType(PdbTypeSymId type_id,const ArrayRecord & ar,CompilerType ct)68394994d37SDimitry Andric TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
68494994d37SDimitry Andric                                             const ArrayRecord &ar,
68594994d37SDimitry Andric                                             CompilerType ct) {
68694994d37SDimitry Andric   TypeSP element_type = GetOrCreateType(ar.ElementType);
68794994d37SDimitry Andric 
68894994d37SDimitry Andric   Declaration decl;
689e3b55780SDimitry Andric   TypeSP array_sp =
690e3b55780SDimitry Andric       MakeType(toOpaqueUid(type_id), ConstString(), ar.Size, nullptr,
69194994d37SDimitry Andric                LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,
692706b4fc4SDimitry Andric                lldb_private::Type::ResolveState::Full);
69394994d37SDimitry Andric   array_sp->SetEncodingType(element_type.get());
69494994d37SDimitry Andric   return array_sp;
69594994d37SDimitry Andric }
69694994d37SDimitry Andric 
CreateFunctionType(PdbTypeSymId type_id,const MemberFunctionRecord & mfr,CompilerType ct)6975f29bb8aSDimitry Andric TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id,
6985f29bb8aSDimitry Andric                                                const MemberFunctionRecord &mfr,
6995f29bb8aSDimitry Andric                                                CompilerType ct) {
7005f29bb8aSDimitry Andric   Declaration decl;
701e3b55780SDimitry Andric   return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
702e3b55780SDimitry Andric                   LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
703e3b55780SDimitry Andric                   ct, lldb_private::Type::ResolveState::Full);
7045f29bb8aSDimitry Andric }
7055f29bb8aSDimitry Andric 
CreateProcedureType(PdbTypeSymId type_id,const ProcedureRecord & pr,CompilerType ct)70694994d37SDimitry Andric TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,
70794994d37SDimitry Andric                                                 const ProcedureRecord &pr,
70894994d37SDimitry Andric                                                 CompilerType ct) {
70994994d37SDimitry Andric   Declaration decl;
710e3b55780SDimitry Andric   return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
711e3b55780SDimitry Andric                   LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
712e3b55780SDimitry Andric                   ct, lldb_private::Type::ResolveState::Full);
71394994d37SDimitry Andric }
71494994d37SDimitry Andric 
CreateType(PdbTypeSymId type_id,CompilerType ct)71594994d37SDimitry Andric TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) {
71694994d37SDimitry Andric   if (type_id.index.isSimple())
71794994d37SDimitry Andric     return CreateSimpleType(type_id.index, ct);
71894994d37SDimitry Andric 
71994994d37SDimitry Andric   TpiStream &stream = type_id.is_ipi ? m_index->ipi() : m_index->tpi();
72094994d37SDimitry Andric   CVType cvt = stream.getType(type_id.index);
72194994d37SDimitry Andric 
72294994d37SDimitry Andric   if (cvt.kind() == LF_MODIFIER) {
72394994d37SDimitry Andric     ModifierRecord modifier;
72494994d37SDimitry Andric     llvm::cantFail(
72594994d37SDimitry Andric         TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier));
72694994d37SDimitry Andric     return CreateModifierType(type_id, modifier, ct);
72794994d37SDimitry Andric   }
72894994d37SDimitry Andric 
72994994d37SDimitry Andric   if (cvt.kind() == LF_POINTER) {
73094994d37SDimitry Andric     PointerRecord pointer;
73194994d37SDimitry Andric     llvm::cantFail(
73294994d37SDimitry Andric         TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer));
73394994d37SDimitry Andric     return CreatePointerType(type_id, pointer, ct);
73494994d37SDimitry Andric   }
73594994d37SDimitry Andric 
73694994d37SDimitry Andric   if (IsClassRecord(cvt.kind())) {
73794994d37SDimitry Andric     ClassRecord cr;
73894994d37SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
73994994d37SDimitry Andric     return CreateTagType(type_id, cr, ct);
74094994d37SDimitry Andric   }
74194994d37SDimitry Andric 
74294994d37SDimitry Andric   if (cvt.kind() == LF_ENUM) {
74394994d37SDimitry Andric     EnumRecord er;
74494994d37SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
74594994d37SDimitry Andric     return CreateTagType(type_id, er, ct);
74694994d37SDimitry Andric   }
74794994d37SDimitry Andric 
74894994d37SDimitry Andric   if (cvt.kind() == LF_UNION) {
74994994d37SDimitry Andric     UnionRecord ur;
75094994d37SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
75194994d37SDimitry Andric     return CreateTagType(type_id, ur, ct);
75294994d37SDimitry Andric   }
75394994d37SDimitry Andric 
75494994d37SDimitry Andric   if (cvt.kind() == LF_ARRAY) {
75594994d37SDimitry Andric     ArrayRecord ar;
75694994d37SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar));
75794994d37SDimitry Andric     return CreateArrayType(type_id, ar, ct);
75894994d37SDimitry Andric   }
75994994d37SDimitry Andric 
76094994d37SDimitry Andric   if (cvt.kind() == LF_PROCEDURE) {
76194994d37SDimitry Andric     ProcedureRecord pr;
76294994d37SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));
76394994d37SDimitry Andric     return CreateProcedureType(type_id, pr, ct);
76494994d37SDimitry Andric   }
7655f29bb8aSDimitry Andric   if (cvt.kind() == LF_MFUNCTION) {
7665f29bb8aSDimitry Andric     MemberFunctionRecord mfr;
7675f29bb8aSDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr));
7685f29bb8aSDimitry Andric     return CreateFunctionType(type_id, mfr, ct);
7695f29bb8aSDimitry Andric   }
77094994d37SDimitry Andric 
77194994d37SDimitry Andric   return nullptr;
77294994d37SDimitry Andric }
77394994d37SDimitry Andric 
CreateAndCacheType(PdbTypeSymId type_id)77494994d37SDimitry Andric TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) {
77594994d37SDimitry Andric   // If they search for a UDT which is a forward ref, try and resolve the full
77694994d37SDimitry Andric   // decl and just map the forward ref uid to the full decl record.
777e3b55780SDimitry Andric   std::optional<PdbTypeSymId> full_decl_uid;
77894994d37SDimitry Andric   if (IsForwardRefUdt(type_id, m_index->tpi())) {
77994994d37SDimitry Andric     auto expected_full_ti =
78094994d37SDimitry Andric         m_index->tpi().findFullDeclForForwardRef(type_id.index);
78194994d37SDimitry Andric     if (!expected_full_ti)
78294994d37SDimitry Andric       llvm::consumeError(expected_full_ti.takeError());
78394994d37SDimitry Andric     else if (*expected_full_ti != type_id.index) {
78494994d37SDimitry Andric       full_decl_uid = PdbTypeSymId(*expected_full_ti, false);
78594994d37SDimitry Andric 
78694994d37SDimitry Andric       // It's possible that a lookup would occur for the full decl causing it
78794994d37SDimitry Andric       // to be cached, then a second lookup would occur for the forward decl.
78894994d37SDimitry Andric       // We don't want to create a second full decl, so make sure the full
78994994d37SDimitry Andric       // decl hasn't already been cached.
79094994d37SDimitry Andric       auto full_iter = m_types.find(toOpaqueUid(*full_decl_uid));
79194994d37SDimitry Andric       if (full_iter != m_types.end()) {
79294994d37SDimitry Andric         TypeSP result = full_iter->second;
79394994d37SDimitry Andric         // Map the forward decl to the TypeSP for the full decl so we can take
79494994d37SDimitry Andric         // the fast path next time.
79594994d37SDimitry Andric         m_types[toOpaqueUid(type_id)] = result;
79694994d37SDimitry Andric         return result;
79794994d37SDimitry Andric       }
79894994d37SDimitry Andric     }
79994994d37SDimitry Andric   }
80094994d37SDimitry Andric 
80194994d37SDimitry Andric   PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id;
802e3b55780SDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
803e3b55780SDimitry Andric   if (auto err = ts_or_err.takeError())
804e3b55780SDimitry Andric     return nullptr;
805e3b55780SDimitry Andric   auto ts = *ts_or_err;
806e3b55780SDimitry Andric   if (!ts)
807e3b55780SDimitry Andric     return nullptr;
80894994d37SDimitry Andric 
809e3b55780SDimitry Andric   PdbAstBuilder* ast_builder = ts->GetNativePDBParser();
810e3b55780SDimitry Andric   clang::QualType qt = ast_builder->GetOrCreateType(best_decl_id);
811145449b1SDimitry Andric   if (qt.isNull())
812145449b1SDimitry Andric     return nullptr;
81394994d37SDimitry Andric 
814e3b55780SDimitry Andric   TypeSP result = CreateType(best_decl_id, ast_builder->ToCompilerType(qt));
81594994d37SDimitry Andric   if (!result)
81694994d37SDimitry Andric     return nullptr;
81794994d37SDimitry Andric 
81894994d37SDimitry Andric   uint64_t best_uid = toOpaqueUid(best_decl_id);
81994994d37SDimitry Andric   m_types[best_uid] = result;
82094994d37SDimitry Andric   // If we had both a forward decl and a full decl, make both point to the new
82194994d37SDimitry Andric   // type.
82294994d37SDimitry Andric   if (full_decl_uid)
82394994d37SDimitry Andric     m_types[toOpaqueUid(type_id)] = result;
82494994d37SDimitry Andric 
82594994d37SDimitry Andric   return result;
82694994d37SDimitry Andric }
82794994d37SDimitry Andric 
GetOrCreateType(PdbTypeSymId type_id)82894994d37SDimitry Andric TypeSP SymbolFileNativePDB::GetOrCreateType(PdbTypeSymId type_id) {
82994994d37SDimitry Andric   // We can't use try_emplace / overwrite here because the process of creating
83094994d37SDimitry Andric   // a type could create nested types, which could invalidate iterators.  So
83194994d37SDimitry Andric   // we have to do a 2-phase lookup / insert.
83294994d37SDimitry Andric   auto iter = m_types.find(toOpaqueUid(type_id));
83394994d37SDimitry Andric   if (iter != m_types.end())
83494994d37SDimitry Andric     return iter->second;
83594994d37SDimitry Andric 
83694994d37SDimitry Andric   TypeSP type = CreateAndCacheType(type_id);
83794994d37SDimitry Andric   if (type)
838ead24645SDimitry Andric     GetTypeList().Insert(type);
83994994d37SDimitry Andric   return type;
84094994d37SDimitry Andric }
84194994d37SDimitry Andric 
CreateGlobalVariable(PdbGlobalSymId var_id)84294994d37SDimitry Andric VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
84394994d37SDimitry Andric   CVSymbol sym = m_index->symrecords().readRecord(var_id.offset);
84494994d37SDimitry Andric   if (sym.kind() == S_CONSTANT)
84594994d37SDimitry Andric     return CreateConstantSymbol(var_id, sym);
84694994d37SDimitry Andric 
84794994d37SDimitry Andric   lldb::ValueType scope = eValueTypeInvalid;
84894994d37SDimitry Andric   TypeIndex ti;
84994994d37SDimitry Andric   llvm::StringRef name;
85094994d37SDimitry Andric   lldb::addr_t addr = 0;
85194994d37SDimitry Andric   uint16_t section = 0;
85294994d37SDimitry Andric   uint32_t offset = 0;
85394994d37SDimitry Andric   bool is_external = false;
85494994d37SDimitry Andric   switch (sym.kind()) {
85594994d37SDimitry Andric   case S_GDATA32:
85694994d37SDimitry Andric     is_external = true;
857e3b55780SDimitry Andric     [[fallthrough]];
85894994d37SDimitry Andric   case S_LDATA32: {
85994994d37SDimitry Andric     DataSym ds(sym.kind());
86094994d37SDimitry Andric     llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, ds));
86194994d37SDimitry Andric     ti = ds.Type;
86294994d37SDimitry Andric     scope = (sym.kind() == S_GDATA32) ? eValueTypeVariableGlobal
86394994d37SDimitry Andric                                       : eValueTypeVariableStatic;
86494994d37SDimitry Andric     name = ds.Name;
86594994d37SDimitry Andric     section = ds.Segment;
86694994d37SDimitry Andric     offset = ds.DataOffset;
86794994d37SDimitry Andric     addr = m_index->MakeVirtualAddress(ds.Segment, ds.DataOffset);
86894994d37SDimitry Andric     break;
86994994d37SDimitry Andric   }
87094994d37SDimitry Andric   case S_GTHREAD32:
87194994d37SDimitry Andric     is_external = true;
872e3b55780SDimitry Andric     [[fallthrough]];
87394994d37SDimitry Andric   case S_LTHREAD32: {
87494994d37SDimitry Andric     ThreadLocalDataSym tlds(sym.kind());
87594994d37SDimitry Andric     llvm::cantFail(
87694994d37SDimitry Andric         SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, tlds));
87794994d37SDimitry Andric     ti = tlds.Type;
87894994d37SDimitry Andric     name = tlds.Name;
87994994d37SDimitry Andric     section = tlds.Segment;
88094994d37SDimitry Andric     offset = tlds.DataOffset;
88194994d37SDimitry Andric     addr = m_index->MakeVirtualAddress(tlds.Segment, tlds.DataOffset);
88294994d37SDimitry Andric     scope = eValueTypeVariableThreadLocal;
88394994d37SDimitry Andric     break;
88494994d37SDimitry Andric   }
88594994d37SDimitry Andric   default:
88694994d37SDimitry Andric     llvm_unreachable("unreachable!");
88794994d37SDimitry Andric   }
88894994d37SDimitry Andric 
88994994d37SDimitry Andric   CompUnitSP comp_unit;
890e3b55780SDimitry Andric   std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr);
891145449b1SDimitry Andric   if (!modi) {
892145449b1SDimitry Andric     return nullptr;
893145449b1SDimitry Andric   }
894145449b1SDimitry Andric 
89594994d37SDimitry Andric   CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(*modi);
89694994d37SDimitry Andric   comp_unit = GetOrCreateCompileUnit(cci);
89794994d37SDimitry Andric 
89894994d37SDimitry Andric   Declaration decl;
89994994d37SDimitry Andric   PdbTypeSymId tid(ti, false);
90094994d37SDimitry Andric   SymbolFileTypeSP type_sp =
90194994d37SDimitry Andric       std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
90294994d37SDimitry Andric   Variable::RangeList ranges;
903e3b55780SDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
904e3b55780SDimitry Andric   if (auto err = ts_or_err.takeError())
905e3b55780SDimitry Andric     return nullptr;
906e3b55780SDimitry Andric   auto ts = *ts_or_err;
907e3b55780SDimitry Andric   if (!ts)
908e3b55780SDimitry Andric     return nullptr;
90994994d37SDimitry Andric 
910e3b55780SDimitry Andric   ts->GetNativePDBParser()->GetOrCreateVariableDecl(var_id);
91194994d37SDimitry Andric 
9121f917f69SDimitry Andric   ModuleSP module_sp = GetObjectFile()->GetModule();
9131f917f69SDimitry Andric   DWARFExpressionList location(
9141f917f69SDimitry Andric       module_sp, MakeGlobalLocationExpression(section, offset, module_sp),
9151f917f69SDimitry Andric       nullptr);
91694994d37SDimitry Andric 
91794994d37SDimitry Andric   std::string global_name("::");
91894994d37SDimitry Andric   global_name += name;
919b60736ecSDimitry Andric   bool artificial = false;
920b60736ecSDimitry Andric   bool location_is_constant_data = false;
921b60736ecSDimitry Andric   bool static_member = false;
92294994d37SDimitry Andric   VariableSP var_sp = std::make_shared<Variable>(
92394994d37SDimitry Andric       toOpaqueUid(var_id), name.str().c_str(), global_name.c_str(), type_sp,
924b60736ecSDimitry Andric       scope, comp_unit.get(), ranges, &decl, location, is_external, artificial,
925b60736ecSDimitry Andric       location_is_constant_data, static_member);
92694994d37SDimitry Andric 
92794994d37SDimitry Andric   return var_sp;
92894994d37SDimitry Andric }
92994994d37SDimitry Andric 
93094994d37SDimitry Andric lldb::VariableSP
CreateConstantSymbol(PdbGlobalSymId var_id,const CVSymbol & cvs)93194994d37SDimitry Andric SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id,
93294994d37SDimitry Andric                                           const CVSymbol &cvs) {
93394994d37SDimitry Andric   TpiStream &tpi = m_index->tpi();
93494994d37SDimitry Andric   ConstantSym constant(cvs.kind());
93594994d37SDimitry Andric 
93694994d37SDimitry Andric   llvm::cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(cvs, constant));
93794994d37SDimitry Andric   std::string global_name("::");
93894994d37SDimitry Andric   global_name += constant.Name;
93994994d37SDimitry Andric   PdbTypeSymId tid(constant.Type, false);
94094994d37SDimitry Andric   SymbolFileTypeSP type_sp =
94194994d37SDimitry Andric       std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
94294994d37SDimitry Andric 
94394994d37SDimitry Andric   Declaration decl;
94494994d37SDimitry Andric   Variable::RangeList ranges;
94594994d37SDimitry Andric   ModuleSP module = GetObjectFile()->GetModule();
9461f917f69SDimitry Andric   DWARFExpressionList location(module,
9471f917f69SDimitry Andric                                MakeConstantLocationExpression(
9481f917f69SDimitry Andric                                    constant.Type, tpi, constant.Value, module),
9491f917f69SDimitry Andric                                nullptr);
95094994d37SDimitry Andric 
951b60736ecSDimitry Andric   bool external = false;
952b60736ecSDimitry Andric   bool artificial = false;
953b60736ecSDimitry Andric   bool location_is_constant_data = true;
954b60736ecSDimitry Andric   bool static_member = false;
95594994d37SDimitry Andric   VariableSP var_sp = std::make_shared<Variable>(
95694994d37SDimitry Andric       toOpaqueUid(var_id), constant.Name.str().c_str(), global_name.c_str(),
95794994d37SDimitry Andric       type_sp, eValueTypeVariableGlobal, module.get(), ranges, &decl, location,
958b60736ecSDimitry Andric       external, artificial, location_is_constant_data, static_member);
95994994d37SDimitry Andric   return var_sp;
96094994d37SDimitry Andric }
96194994d37SDimitry Andric 
96294994d37SDimitry Andric VariableSP
GetOrCreateGlobalVariable(PdbGlobalSymId var_id)96394994d37SDimitry Andric SymbolFileNativePDB::GetOrCreateGlobalVariable(PdbGlobalSymId var_id) {
96494994d37SDimitry Andric   auto emplace_result = m_global_vars.try_emplace(toOpaqueUid(var_id), nullptr);
965145449b1SDimitry Andric   if (emplace_result.second) {
966145449b1SDimitry Andric     if (VariableSP var_sp = CreateGlobalVariable(var_id))
967145449b1SDimitry Andric       emplace_result.first->second = var_sp;
968145449b1SDimitry Andric     else
969145449b1SDimitry Andric       return nullptr;
970145449b1SDimitry Andric   }
97194994d37SDimitry Andric 
97294994d37SDimitry Andric   return emplace_result.first->second;
97394994d37SDimitry Andric }
97494994d37SDimitry Andric 
GetOrCreateType(TypeIndex ti)97594994d37SDimitry Andric lldb::TypeSP SymbolFileNativePDB::GetOrCreateType(TypeIndex ti) {
97694994d37SDimitry Andric   return GetOrCreateType(PdbTypeSymId(ti, false));
97794994d37SDimitry Andric }
97894994d37SDimitry Andric 
GetOrCreateFunction(PdbCompilandSymId func_id,CompileUnit & comp_unit)97994994d37SDimitry Andric FunctionSP SymbolFileNativePDB::GetOrCreateFunction(PdbCompilandSymId func_id,
98094994d37SDimitry Andric                                                     CompileUnit &comp_unit) {
98194994d37SDimitry Andric   auto emplace_result = m_functions.try_emplace(toOpaqueUid(func_id), nullptr);
98294994d37SDimitry Andric   if (emplace_result.second)
98394994d37SDimitry Andric     emplace_result.first->second = CreateFunction(func_id, comp_unit);
98494994d37SDimitry Andric 
98594994d37SDimitry Andric   return emplace_result.first->second;
98694994d37SDimitry Andric }
98794994d37SDimitry Andric 
98894994d37SDimitry Andric CompUnitSP
GetOrCreateCompileUnit(const CompilandIndexItem & cci)98994994d37SDimitry Andric SymbolFileNativePDB::GetOrCreateCompileUnit(const CompilandIndexItem &cci) {
99094994d37SDimitry Andric 
99194994d37SDimitry Andric   auto emplace_result =
99294994d37SDimitry Andric       m_compilands.try_emplace(toOpaqueUid(cci.m_id), nullptr);
99394994d37SDimitry Andric   if (emplace_result.second)
99494994d37SDimitry Andric     emplace_result.first->second = CreateCompileUnit(cci);
99594994d37SDimitry Andric 
99694994d37SDimitry Andric   lldbassert(emplace_result.first->second);
99794994d37SDimitry Andric   return emplace_result.first->second;
99894994d37SDimitry Andric }
99994994d37SDimitry Andric 
GetOrCreateBlock(PdbCompilandSymId block_id)100094994d37SDimitry Andric Block &SymbolFileNativePDB::GetOrCreateBlock(PdbCompilandSymId block_id) {
100194994d37SDimitry Andric   auto iter = m_blocks.find(toOpaqueUid(block_id));
100294994d37SDimitry Andric   if (iter != m_blocks.end())
100394994d37SDimitry Andric     return *iter->second;
100494994d37SDimitry Andric 
100594994d37SDimitry Andric   return CreateBlock(block_id);
100694994d37SDimitry Andric }
100794994d37SDimitry Andric 
ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx)100894994d37SDimitry Andric void SymbolFileNativePDB::ParseDeclsForContext(
100994994d37SDimitry Andric     lldb_private::CompilerDeclContext decl_ctx) {
1010e3b55780SDimitry Andric   TypeSystem* ts_or_err = decl_ctx.GetTypeSystem();
1011e3b55780SDimitry Andric   if (!ts_or_err)
1012e3b55780SDimitry Andric     return;
1013e3b55780SDimitry Andric   PdbAstBuilder* ast_builder = ts_or_err->GetNativePDBParser();
1014e3b55780SDimitry Andric   clang::DeclContext *context = ast_builder->FromCompilerDeclContext(decl_ctx);
101594994d37SDimitry Andric   if (!context)
101694994d37SDimitry Andric     return;
1017e3b55780SDimitry Andric   ast_builder->ParseDeclsForContext(*context);
101894994d37SDimitry Andric }
101994994d37SDimitry Andric 
ParseCompileUnitAtIndex(uint32_t index)102094994d37SDimitry Andric lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) {
102194994d37SDimitry Andric   if (index >= GetNumCompileUnits())
102294994d37SDimitry Andric     return CompUnitSP();
102394994d37SDimitry Andric   lldbassert(index < UINT16_MAX);
102494994d37SDimitry Andric   if (index >= UINT16_MAX)
102594994d37SDimitry Andric     return nullptr;
102694994d37SDimitry Andric 
102794994d37SDimitry Andric   CompilandIndexItem &item = m_index->compilands().GetOrCreateCompiland(index);
102894994d37SDimitry Andric 
102994994d37SDimitry Andric   return GetOrCreateCompileUnit(item);
103094994d37SDimitry Andric }
103194994d37SDimitry Andric 
ParseLanguage(CompileUnit & comp_unit)103294994d37SDimitry Andric lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) {
1033ead24645SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
103494994d37SDimitry Andric   PdbSymUid uid(comp_unit.GetID());
103594994d37SDimitry Andric   lldbassert(uid.kind() == PdbSymUidKind::Compiland);
103694994d37SDimitry Andric 
103794994d37SDimitry Andric   CompilandIndexItem *item =
103894994d37SDimitry Andric       m_index->compilands().GetCompiland(uid.asCompiland().modi);
103994994d37SDimitry Andric   lldbassert(item);
104094994d37SDimitry Andric   if (!item->m_compile_opts)
104194994d37SDimitry Andric     return lldb::eLanguageTypeUnknown;
104294994d37SDimitry Andric 
104394994d37SDimitry Andric   return TranslateLanguage(item->m_compile_opts->getLanguage());
104494994d37SDimitry Andric }
104594994d37SDimitry Andric 
AddSymbols(Symtab & symtab)104677fc4c14SDimitry Andric void SymbolFileNativePDB::AddSymbols(Symtab &symtab) {}
104794994d37SDimitry Andric 
ParseFunctions(CompileUnit & comp_unit)104894994d37SDimitry Andric size_t SymbolFileNativePDB::ParseFunctions(CompileUnit &comp_unit) {
1049ead24645SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
105094994d37SDimitry Andric   PdbSymUid uid{comp_unit.GetID()};
105194994d37SDimitry Andric   lldbassert(uid.kind() == PdbSymUidKind::Compiland);
105294994d37SDimitry Andric   uint16_t modi = uid.asCompiland().modi;
105394994d37SDimitry Andric   CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(modi);
105494994d37SDimitry Andric 
105594994d37SDimitry Andric   size_t count = comp_unit.GetNumFunctions();
105694994d37SDimitry Andric   const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
105794994d37SDimitry Andric   for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
105894994d37SDimitry Andric     if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32)
105994994d37SDimitry Andric       continue;
106094994d37SDimitry Andric 
106194994d37SDimitry Andric     PdbCompilandSymId sym_id{modi, iter.offset()};
106294994d37SDimitry Andric 
106394994d37SDimitry Andric     FunctionSP func = GetOrCreateFunction(sym_id, comp_unit);
106494994d37SDimitry Andric   }
106594994d37SDimitry Andric 
106694994d37SDimitry Andric   size_t new_count = comp_unit.GetNumFunctions();
106794994d37SDimitry Andric   lldbassert(new_count >= count);
106894994d37SDimitry Andric   return new_count - count;
106994994d37SDimitry Andric }
107094994d37SDimitry Andric 
NeedsResolvedCompileUnit(uint32_t resolve_scope)107194994d37SDimitry Andric static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) {
107294994d37SDimitry Andric   // If any of these flags are set, we need to resolve the compile unit.
107394994d37SDimitry Andric   uint32_t flags = eSymbolContextCompUnit;
107494994d37SDimitry Andric   flags |= eSymbolContextVariable;
107594994d37SDimitry Andric   flags |= eSymbolContextFunction;
107694994d37SDimitry Andric   flags |= eSymbolContextBlock;
107794994d37SDimitry Andric   flags |= eSymbolContextLineEntry;
107894994d37SDimitry Andric   return (resolve_scope & flags) != 0;
107994994d37SDimitry Andric }
108094994d37SDimitry Andric 
ResolveSymbolContext(const Address & addr,SymbolContextItem resolve_scope,SymbolContext & sc)108194994d37SDimitry Andric uint32_t SymbolFileNativePDB::ResolveSymbolContext(
108294994d37SDimitry Andric     const Address &addr, SymbolContextItem resolve_scope, SymbolContext &sc) {
1083ead24645SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
108494994d37SDimitry Andric   uint32_t resolved_flags = 0;
108594994d37SDimitry Andric   lldb::addr_t file_addr = addr.GetFileAddress();
108694994d37SDimitry Andric 
108794994d37SDimitry Andric   if (NeedsResolvedCompileUnit(resolve_scope)) {
1088e3b55780SDimitry Andric     std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr);
108994994d37SDimitry Andric     if (!modi)
109094994d37SDimitry Andric       return 0;
1091145449b1SDimitry Andric     CompUnitSP cu_sp = GetCompileUnitAtIndex(*modi);
1092c0981da4SDimitry Andric     if (!cu_sp)
109394994d37SDimitry Andric       return 0;
109494994d37SDimitry Andric 
1095c0981da4SDimitry Andric     sc.comp_unit = cu_sp.get();
109694994d37SDimitry Andric     resolved_flags |= eSymbolContextCompUnit;
109794994d37SDimitry Andric   }
109894994d37SDimitry Andric 
109994994d37SDimitry Andric   if (resolve_scope & eSymbolContextFunction ||
110094994d37SDimitry Andric       resolve_scope & eSymbolContextBlock) {
110194994d37SDimitry Andric     lldbassert(sc.comp_unit);
110294994d37SDimitry Andric     std::vector<SymbolAndUid> matches = m_index->FindSymbolsByVa(file_addr);
110394994d37SDimitry Andric     // Search the matches in reverse.  This way if there are multiple matches
110494994d37SDimitry Andric     // (for example we are 3 levels deep in a nested scope) it will find the
110594994d37SDimitry Andric     // innermost one first.
110694994d37SDimitry Andric     for (const auto &match : llvm::reverse(matches)) {
110794994d37SDimitry Andric       if (match.uid.kind() != PdbSymUidKind::CompilandSym)
110894994d37SDimitry Andric         continue;
110994994d37SDimitry Andric 
111094994d37SDimitry Andric       PdbCompilandSymId csid = match.uid.asCompilandSym();
111194994d37SDimitry Andric       CVSymbol cvs = m_index->ReadSymbolRecord(csid);
111294994d37SDimitry Andric       PDB_SymType type = CVSymToPDBSym(cvs.kind());
111394994d37SDimitry Andric       if (type != PDB_SymType::Function && type != PDB_SymType::Block)
111494994d37SDimitry Andric         continue;
111594994d37SDimitry Andric       if (type == PDB_SymType::Function) {
111694994d37SDimitry Andric         sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get();
1117e3b55780SDimitry Andric         if (sc.function) {
11186f8fc217SDimitry Andric           Block &block = sc.function->GetBlock(true);
11196f8fc217SDimitry Andric           addr_t func_base =
11206f8fc217SDimitry Andric               sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
11216f8fc217SDimitry Andric           addr_t offset = file_addr - func_base;
11226f8fc217SDimitry Andric           sc.block = block.FindInnermostBlockByOffset(offset);
112394994d37SDimitry Andric         }
1124e3b55780SDimitry Andric       }
112594994d37SDimitry Andric 
112694994d37SDimitry Andric       if (type == PDB_SymType::Block) {
1127e3b55780SDimitry Andric         Block &block = GetOrCreateBlock(csid);
1128e3b55780SDimitry Andric         sc.function = block.CalculateSymbolContextFunction();
1129e3b55780SDimitry Andric         if (sc.function) {
1130e3b55780SDimitry Andric           sc.function->GetBlock(true);
1131e3b55780SDimitry Andric           addr_t func_base =
1132e3b55780SDimitry Andric               sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
1133e3b55780SDimitry Andric           addr_t offset = file_addr - func_base;
1134e3b55780SDimitry Andric           sc.block = block.FindInnermostBlockByOffset(offset);
1135e3b55780SDimitry Andric         }
113694994d37SDimitry Andric       }
11376f8fc217SDimitry Andric       if (sc.function)
113894994d37SDimitry Andric         resolved_flags |= eSymbolContextFunction;
11396f8fc217SDimitry Andric       if (sc.block)
114094994d37SDimitry Andric         resolved_flags |= eSymbolContextBlock;
114194994d37SDimitry Andric       break;
114294994d37SDimitry Andric     }
114394994d37SDimitry Andric   }
114494994d37SDimitry Andric 
114594994d37SDimitry Andric   if (resolve_scope & eSymbolContextLineEntry) {
114694994d37SDimitry Andric     lldbassert(sc.comp_unit);
114794994d37SDimitry Andric     if (auto *line_table = sc.comp_unit->GetLineTable()) {
114894994d37SDimitry Andric       if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
114994994d37SDimitry Andric         resolved_flags |= eSymbolContextLineEntry;
115094994d37SDimitry Andric     }
115194994d37SDimitry Andric   }
115294994d37SDimitry Andric 
115394994d37SDimitry Andric   return resolved_flags;
115494994d37SDimitry Andric }
115594994d37SDimitry Andric 
ResolveSymbolContext(const SourceLocationSpec & src_location_spec,lldb::SymbolContextItem resolve_scope,SymbolContextList & sc_list)115694994d37SDimitry Andric uint32_t SymbolFileNativePDB::ResolveSymbolContext(
1157344a3780SDimitry Andric     const SourceLocationSpec &src_location_spec,
115894994d37SDimitry Andric     lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
11596f8fc217SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
11606f8fc217SDimitry Andric   const uint32_t prev_size = sc_list.GetSize();
11616f8fc217SDimitry Andric   if (resolve_scope & eSymbolContextCompUnit) {
11626f8fc217SDimitry Andric     for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus;
11636f8fc217SDimitry Andric          ++cu_idx) {
11646f8fc217SDimitry Andric       CompileUnit *cu = ParseCompileUnitAtIndex(cu_idx).get();
11656f8fc217SDimitry Andric       if (!cu)
11666f8fc217SDimitry Andric         continue;
11676f8fc217SDimitry Andric 
11686f8fc217SDimitry Andric       bool file_spec_matches_cu_file_spec = FileSpec::Match(
11696f8fc217SDimitry Andric           src_location_spec.GetFileSpec(), cu->GetPrimaryFile());
11706f8fc217SDimitry Andric       if (file_spec_matches_cu_file_spec) {
11716f8fc217SDimitry Andric         cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);
11726f8fc217SDimitry Andric         break;
117394994d37SDimitry Andric       }
117494994d37SDimitry Andric     }
11756f8fc217SDimitry Andric   }
11766f8fc217SDimitry Andric   return sc_list.GetSize() - prev_size;
117794994d37SDimitry Andric }
117894994d37SDimitry Andric 
ParseLineTable(CompileUnit & comp_unit)117994994d37SDimitry Andric bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) {
118094994d37SDimitry Andric   // Unfortunately LLDB is set up to parse the entire compile unit line table
118194994d37SDimitry Andric   // all at once, even if all it really needs is line info for a specific
118294994d37SDimitry Andric   // function.  In the future it would be nice if it could set the sc.m_function
118394994d37SDimitry Andric   // member, and we could only get the line info for the function in question.
1184ead24645SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
118594994d37SDimitry Andric   PdbSymUid cu_id(comp_unit.GetID());
118694994d37SDimitry Andric   lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);
11876f8fc217SDimitry Andric   uint16_t modi = cu_id.asCompiland().modi;
11886f8fc217SDimitry Andric   CompilandIndexItem *cii = m_index->compilands().GetCompiland(modi);
11896f8fc217SDimitry Andric   lldbassert(cii);
11906f8fc217SDimitry Andric 
11916f8fc217SDimitry Andric   // Parse DEBUG_S_LINES subsections first, then parse all S_INLINESITE records
11926f8fc217SDimitry Andric   // in this CU. Add line entries into the set first so that if there are line
11936f8fc217SDimitry Andric   // entries with same addres, the later is always more accurate than the
11946f8fc217SDimitry Andric   // former.
11956f8fc217SDimitry Andric   std::set<LineTable::Entry, LineTableEntryComparator> line_set;
119694994d37SDimitry Andric 
119794994d37SDimitry Andric   // This is basically a copy of the .debug$S subsections from all original COFF
119894994d37SDimitry Andric   // object files merged together with address relocations applied.  We are
119994994d37SDimitry Andric   // looking for all DEBUG_S_LINES subsections.
120094994d37SDimitry Andric   for (const DebugSubsectionRecord &dssr :
12016f8fc217SDimitry Andric        cii->m_debug_stream.getSubsectionsArray()) {
120294994d37SDimitry Andric     if (dssr.kind() != DebugSubsectionKind::Lines)
120394994d37SDimitry Andric       continue;
120494994d37SDimitry Andric 
120594994d37SDimitry Andric     DebugLinesSubsectionRef lines;
120694994d37SDimitry Andric     llvm::BinaryStreamReader reader(dssr.getRecordData());
120794994d37SDimitry Andric     if (auto EC = lines.initialize(reader)) {
120894994d37SDimitry Andric       llvm::consumeError(std::move(EC));
120994994d37SDimitry Andric       return false;
121094994d37SDimitry Andric     }
121194994d37SDimitry Andric 
121294994d37SDimitry Andric     const LineFragmentHeader *lfh = lines.header();
121394994d37SDimitry Andric     uint64_t virtual_addr =
121494994d37SDimitry Andric         m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset);
1215145449b1SDimitry Andric     if (virtual_addr == LLDB_INVALID_ADDRESS)
1216145449b1SDimitry Andric       continue;
121794994d37SDimitry Andric 
121894994d37SDimitry Andric     for (const LineColumnEntry &group : lines) {
12196f8fc217SDimitry Andric       llvm::Expected<uint32_t> file_index_or_err =
12206f8fc217SDimitry Andric           GetFileIndex(*cii, group.NameIndex);
12216f8fc217SDimitry Andric       if (!file_index_or_err)
122294994d37SDimitry Andric         continue;
12236f8fc217SDimitry Andric       uint32_t file_index = file_index_or_err.get();
122494994d37SDimitry Andric       lldbassert(!group.LineNumbers.empty());
12256f8fc217SDimitry Andric       CompilandIndexItem::GlobalLineTable::Entry line_entry(
12266f8fc217SDimitry Andric           LLDB_INVALID_ADDRESS, 0);
122794994d37SDimitry Andric       for (const LineNumberEntry &entry : group.LineNumbers) {
12286f8fc217SDimitry Andric         LineInfo cur_info(entry.Flags);
12296f8fc217SDimitry Andric 
12306f8fc217SDimitry Andric         if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto())
12316f8fc217SDimitry Andric           continue;
12326f8fc217SDimitry Andric 
12336f8fc217SDimitry Andric         uint64_t addr = virtual_addr + entry.Offset;
12346f8fc217SDimitry Andric 
12356f8fc217SDimitry Andric         bool is_statement = cur_info.isStatement();
12366f8fc217SDimitry Andric         bool is_prologue = IsFunctionPrologue(*cii, addr);
12376f8fc217SDimitry Andric         bool is_epilogue = IsFunctionEpilogue(*cii, addr);
12386f8fc217SDimitry Andric 
12396f8fc217SDimitry Andric         uint32_t lno = cur_info.getStartLine();
12406f8fc217SDimitry Andric 
1241145449b1SDimitry Andric         LineTable::Entry new_entry(addr, lno, 0, file_index, is_statement, false,
12426f8fc217SDimitry Andric                                  is_prologue, is_epilogue, false);
1243145449b1SDimitry Andric         // Terminal entry has lower precedence than new entry.
1244145449b1SDimitry Andric         auto iter = line_set.find(new_entry);
1245145449b1SDimitry Andric         if (iter != line_set.end() && iter->is_terminal_entry)
1246145449b1SDimitry Andric           line_set.erase(iter);
1247145449b1SDimitry Andric         line_set.insert(new_entry);
12486f8fc217SDimitry Andric 
12496f8fc217SDimitry Andric         if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {
12506f8fc217SDimitry Andric           line_entry.SetRangeEnd(addr);
12516f8fc217SDimitry Andric           cii->m_global_line_table.Append(line_entry);
12526f8fc217SDimitry Andric         }
12536f8fc217SDimitry Andric         line_entry.SetRangeBase(addr);
12546f8fc217SDimitry Andric         line_entry.data = {file_index, lno};
125594994d37SDimitry Andric       }
125694994d37SDimitry Andric       LineInfo last_line(group.LineNumbers.back().Flags);
12576f8fc217SDimitry Andric       line_set.emplace(virtual_addr + lfh->CodeSize, last_line.getEndLine(), 0,
12586f8fc217SDimitry Andric                        file_index, false, false, false, false, true);
12596f8fc217SDimitry Andric 
12606f8fc217SDimitry Andric       if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {
12616f8fc217SDimitry Andric         line_entry.SetRangeEnd(virtual_addr + lfh->CodeSize);
12626f8fc217SDimitry Andric         cii->m_global_line_table.Append(line_entry);
126394994d37SDimitry Andric       }
126494994d37SDimitry Andric     }
12656f8fc217SDimitry Andric   }
12666f8fc217SDimitry Andric 
12676f8fc217SDimitry Andric   cii->m_global_line_table.Sort();
12686f8fc217SDimitry Andric 
12696f8fc217SDimitry Andric   // Parse all S_INLINESITE in this CU.
12706f8fc217SDimitry Andric   const CVSymbolArray &syms = cii->m_debug_stream.getSymbolArray();
12716f8fc217SDimitry Andric   for (auto iter = syms.begin(); iter != syms.end();) {
12726f8fc217SDimitry Andric     if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) {
12736f8fc217SDimitry Andric       ++iter;
12746f8fc217SDimitry Andric       continue;
12756f8fc217SDimitry Andric     }
12766f8fc217SDimitry Andric 
12776f8fc217SDimitry Andric     uint32_t record_offset = iter.offset();
12786f8fc217SDimitry Andric     CVSymbol func_record =
12796f8fc217SDimitry Andric         cii->m_debug_stream.readSymbolAtOffset(record_offset);
12806f8fc217SDimitry Andric     SegmentOffsetLength sol = GetSegmentOffsetAndLength(func_record);
1281145449b1SDimitry Andric     addr_t file_vm_addr =
1282145449b1SDimitry Andric         m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);
1283145449b1SDimitry Andric     if (file_vm_addr == LLDB_INVALID_ADDRESS)
1284145449b1SDimitry Andric       continue;
1285145449b1SDimitry Andric 
12866f8fc217SDimitry Andric     AddressRange func_range(file_vm_addr, sol.length,
12876f8fc217SDimitry Andric                             comp_unit.GetModule()->GetSectionList());
12886f8fc217SDimitry Andric     Address func_base = func_range.GetBaseAddress();
12896f8fc217SDimitry Andric     PdbCompilandSymId func_id{modi, record_offset};
12906f8fc217SDimitry Andric 
12916f8fc217SDimitry Andric     // Iterate all S_INLINESITEs in the function.
12926f8fc217SDimitry Andric     auto parse_inline_sites = [&](SymbolKind kind, PdbCompilandSymId id) {
12936f8fc217SDimitry Andric       if (kind != S_INLINESITE)
12946f8fc217SDimitry Andric         return false;
12956f8fc217SDimitry Andric 
12966f8fc217SDimitry Andric       ParseInlineSite(id, func_base);
12976f8fc217SDimitry Andric 
12986f8fc217SDimitry Andric       for (const auto &line_entry :
12996f8fc217SDimitry Andric            m_inline_sites[toOpaqueUid(id)]->line_entries) {
13006f8fc217SDimitry Andric         // If line_entry is not terminal entry, remove previous line entry at
13016f8fc217SDimitry Andric         // the same address and insert new one. Terminal entry inside an inline
13026f8fc217SDimitry Andric         // site might not be terminal entry for its parent.
13036f8fc217SDimitry Andric         if (!line_entry.is_terminal_entry)
13046f8fc217SDimitry Andric           line_set.erase(line_entry);
13056f8fc217SDimitry Andric         line_set.insert(line_entry);
13066f8fc217SDimitry Andric       }
13076f8fc217SDimitry Andric       // No longer useful after adding to line_set.
13086f8fc217SDimitry Andric       m_inline_sites[toOpaqueUid(id)]->line_entries.clear();
13096f8fc217SDimitry Andric       return true;
13106f8fc217SDimitry Andric     };
13116f8fc217SDimitry Andric     ParseSymbolArrayInScope(func_id, parse_inline_sites);
13126f8fc217SDimitry Andric     // Jump to the end of the function record.
13136f8fc217SDimitry Andric     iter = syms.at(getScopeEndOffset(func_record));
13146f8fc217SDimitry Andric   }
13156f8fc217SDimitry Andric 
13166f8fc217SDimitry Andric   cii->m_global_line_table.Clear();
13176f8fc217SDimitry Andric 
13186f8fc217SDimitry Andric   // Add line entries in line_set to line_table.
13196f8fc217SDimitry Andric   auto line_table = std::make_unique<LineTable>(&comp_unit);
13206f8fc217SDimitry Andric   std::unique_ptr<LineSequence> sequence(
13216f8fc217SDimitry Andric       line_table->CreateLineSequenceContainer());
13226f8fc217SDimitry Andric   for (const auto &line_entry : line_set) {
13236f8fc217SDimitry Andric     line_table->AppendLineEntryToSequence(
13246f8fc217SDimitry Andric         sequence.get(), line_entry.file_addr, line_entry.line,
13256f8fc217SDimitry Andric         line_entry.column, line_entry.file_idx,
13266f8fc217SDimitry Andric         line_entry.is_start_of_statement, line_entry.is_start_of_basic_block,
13276f8fc217SDimitry Andric         line_entry.is_prologue_end, line_entry.is_epilogue_begin,
13286f8fc217SDimitry Andric         line_entry.is_terminal_entry);
13296f8fc217SDimitry Andric   }
13306f8fc217SDimitry Andric   line_table->InsertSequence(sequence.get());
133194994d37SDimitry Andric 
133294994d37SDimitry Andric   if (line_table->GetSize() == 0)
133394994d37SDimitry Andric     return false;
133494994d37SDimitry Andric 
133594994d37SDimitry Andric   comp_unit.SetLineTable(line_table.release());
133694994d37SDimitry Andric   return true;
133794994d37SDimitry Andric }
133894994d37SDimitry Andric 
ParseDebugMacros(CompileUnit & comp_unit)133994994d37SDimitry Andric bool SymbolFileNativePDB::ParseDebugMacros(CompileUnit &comp_unit) {
134094994d37SDimitry Andric   // PDB doesn't contain information about macros
134194994d37SDimitry Andric   return false;
134294994d37SDimitry Andric }
134394994d37SDimitry Andric 
13446f8fc217SDimitry Andric llvm::Expected<uint32_t>
GetFileIndex(const CompilandIndexItem & cii,uint32_t file_id)13456f8fc217SDimitry Andric SymbolFileNativePDB::GetFileIndex(const CompilandIndexItem &cii,
13466f8fc217SDimitry Andric                                   uint32_t file_id) {
13477fa27ce4SDimitry Andric   if (!cii.m_strings.hasChecksums() || !cii.m_strings.hasStrings())
13487fa27ce4SDimitry Andric     return llvm::make_error<RawError>(raw_error_code::no_entry);
13497fa27ce4SDimitry Andric 
13506f8fc217SDimitry Andric   const auto &checksums = cii.m_strings.checksums().getArray();
13516f8fc217SDimitry Andric   const auto &strings = cii.m_strings.strings();
13526f8fc217SDimitry Andric   // Indices in this structure are actually offsets of records in the
13536f8fc217SDimitry Andric   // DEBUG_S_FILECHECKSUMS subsection.  Those entries then have an index
13546f8fc217SDimitry Andric   // into the global PDB string table.
13556f8fc217SDimitry Andric   auto iter = checksums.at(file_id);
13566f8fc217SDimitry Andric   if (iter == checksums.end())
13576f8fc217SDimitry Andric     return llvm::make_error<RawError>(raw_error_code::no_entry);
13586f8fc217SDimitry Andric 
13596f8fc217SDimitry Andric   llvm::Expected<llvm::StringRef> efn = strings.getString(iter->FileNameOffset);
13606f8fc217SDimitry Andric   if (!efn) {
13616f8fc217SDimitry Andric     return efn.takeError();
13626f8fc217SDimitry Andric   }
13636f8fc217SDimitry Andric 
13646f8fc217SDimitry Andric   // LLDB wants the index of the file in the list of support files.
13656f8fc217SDimitry Andric   auto fn_iter = llvm::find(cii.m_file_list, *efn);
1366145449b1SDimitry Andric   if (fn_iter != cii.m_file_list.end())
1367145449b1SDimitry Andric     return std::distance(cii.m_file_list.begin(), fn_iter);
1368145449b1SDimitry Andric   return llvm::make_error<RawError>(raw_error_code::no_entry);
13696f8fc217SDimitry Andric }
13706f8fc217SDimitry Andric 
ParseSupportFiles(CompileUnit & comp_unit,SupportFileList & support_files)137194994d37SDimitry Andric bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit,
1372aca2e42cSDimitry Andric                                             SupportFileList &support_files) {
1373ead24645SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
137494994d37SDimitry Andric   PdbSymUid cu_id(comp_unit.GetID());
137594994d37SDimitry Andric   lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);
137694994d37SDimitry Andric   CompilandIndexItem *cci =
137794994d37SDimitry Andric       m_index->compilands().GetCompiland(cu_id.asCompiland().modi);
137894994d37SDimitry Andric   lldbassert(cci);
137994994d37SDimitry Andric 
138094994d37SDimitry Andric   for (llvm::StringRef f : cci->m_file_list) {
138194994d37SDimitry Andric     FileSpec::Style style =
1382312c0ed1SDimitry Andric         f.starts_with("/") ? FileSpec::Style::posix : FileSpec::Style::windows;
138394994d37SDimitry Andric     FileSpec spec(f, style);
138494994d37SDimitry Andric     support_files.Append(spec);
138594994d37SDimitry Andric   }
138694994d37SDimitry Andric   return true;
138794994d37SDimitry Andric }
138894994d37SDimitry Andric 
ParseImportedModules(const SymbolContext & sc,std::vector<SourceModule> & imported_modules)138994994d37SDimitry Andric bool SymbolFileNativePDB::ParseImportedModules(
13905f29bb8aSDimitry Andric     const SymbolContext &sc, std::vector<SourceModule> &imported_modules) {
139194994d37SDimitry Andric   // PDB does not yet support module debug info
139294994d37SDimitry Andric   return false;
139394994d37SDimitry Andric }
139494994d37SDimitry Andric 
ParseInlineSite(PdbCompilandSymId id,Address func_addr)13956f8fc217SDimitry Andric void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id,
13966f8fc217SDimitry Andric                                           Address func_addr) {
13976f8fc217SDimitry Andric   lldb::user_id_t opaque_uid = toOpaqueUid(id);
13987fa27ce4SDimitry Andric   if (m_inline_sites.contains(opaque_uid))
13996f8fc217SDimitry Andric     return;
14006f8fc217SDimitry Andric 
14016f8fc217SDimitry Andric   addr_t func_base = func_addr.GetFileAddress();
14026f8fc217SDimitry Andric   CompilandIndexItem *cii = m_index->compilands().GetCompiland(id.modi);
14036f8fc217SDimitry Andric   CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(id.offset);
14046f8fc217SDimitry Andric   CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
14056f8fc217SDimitry Andric 
14066f8fc217SDimitry Andric   InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind()));
14076f8fc217SDimitry Andric   cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site));
14086f8fc217SDimitry Andric   PdbCompilandSymId parent_id(id.modi, inline_site.Parent);
14096f8fc217SDimitry Andric 
14106f8fc217SDimitry Andric   std::shared_ptr<InlineSite> inline_site_sp =
14116f8fc217SDimitry Andric       std::make_shared<InlineSite>(parent_id);
14126f8fc217SDimitry Andric 
14136f8fc217SDimitry Andric   // Get the inlined function declaration info.
14146f8fc217SDimitry Andric   auto iter = cii->m_inline_map.find(inline_site.Inlinee);
14156f8fc217SDimitry Andric   if (iter == cii->m_inline_map.end())
14166f8fc217SDimitry Andric     return;
14176f8fc217SDimitry Andric   InlineeSourceLine inlinee_line = iter->second;
14186f8fc217SDimitry Andric 
1419aca2e42cSDimitry Andric   const SupportFileList &files = comp_unit->GetSupportFiles();
14206f8fc217SDimitry Andric   FileSpec decl_file;
14216f8fc217SDimitry Andric   llvm::Expected<uint32_t> file_index_or_err =
14226f8fc217SDimitry Andric       GetFileIndex(*cii, inlinee_line.Header->FileID);
14236f8fc217SDimitry Andric   if (!file_index_or_err)
14246f8fc217SDimitry Andric     return;
1425145449b1SDimitry Andric   uint32_t file_offset = file_index_or_err.get();
1426145449b1SDimitry Andric   decl_file = files.GetFileSpecAtIndex(file_offset);
14276f8fc217SDimitry Andric   uint32_t decl_line = inlinee_line.Header->SourceLineNum;
14286f8fc217SDimitry Andric   std::unique_ptr<Declaration> decl_up =
14296f8fc217SDimitry Andric       std::make_unique<Declaration>(decl_file, decl_line);
14306f8fc217SDimitry Andric 
14316f8fc217SDimitry Andric   // Parse range and line info.
14326f8fc217SDimitry Andric   uint32_t code_offset = 0;
14336f8fc217SDimitry Andric   int32_t line_offset = 0;
1434e3b55780SDimitry Andric   std::optional<uint32_t> code_offset_base;
1435e3b55780SDimitry Andric   std::optional<uint32_t> code_offset_end;
1436e3b55780SDimitry Andric   std::optional<int32_t> cur_line_offset;
1437e3b55780SDimitry Andric   std::optional<int32_t> next_line_offset;
1438e3b55780SDimitry Andric   std::optional<uint32_t> next_file_offset;
14396f8fc217SDimitry Andric 
1440145449b1SDimitry Andric   bool is_terminal_entry = false;
1441145449b1SDimitry Andric   bool is_start_of_statement = true;
14426f8fc217SDimitry Andric   // The first instruction is the prologue end.
14436f8fc217SDimitry Andric   bool is_prologue_end = true;
14446f8fc217SDimitry Andric 
1445145449b1SDimitry Andric   auto update_code_offset = [&](uint32_t code_delta) {
1446145449b1SDimitry Andric     if (!code_offset_base)
1447145449b1SDimitry Andric       code_offset_base = code_offset;
1448145449b1SDimitry Andric     else if (!code_offset_end)
1449145449b1SDimitry Andric       code_offset_end = *code_offset_base + code_delta;
14506f8fc217SDimitry Andric   };
1451145449b1SDimitry Andric   auto update_line_offset = [&](int32_t line_delta) {
14526f8fc217SDimitry Andric     line_offset += line_delta;
1453145449b1SDimitry Andric     if (!code_offset_base || !cur_line_offset)
1454145449b1SDimitry Andric       cur_line_offset = line_offset;
1455145449b1SDimitry Andric     else
1456145449b1SDimitry Andric       next_line_offset = line_offset;
1457145449b1SDimitry Andric     ;
1458145449b1SDimitry Andric   };
1459145449b1SDimitry Andric   auto update_file_offset = [&](uint32_t offset) {
1460145449b1SDimitry Andric     if (!code_offset_base)
1461145449b1SDimitry Andric       file_offset = offset;
1462145449b1SDimitry Andric     else
1463145449b1SDimitry Andric       next_file_offset = offset;
14646f8fc217SDimitry Andric   };
14656f8fc217SDimitry Andric 
14666f8fc217SDimitry Andric   for (auto &annot : inline_site.annotations()) {
14676f8fc217SDimitry Andric     switch (annot.OpCode) {
14686f8fc217SDimitry Andric     case BinaryAnnotationsOpCode::CodeOffset:
14696f8fc217SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeOffset:
14706f8fc217SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
1471145449b1SDimitry Andric       code_offset += annot.U1;
1472145449b1SDimitry Andric       update_code_offset(annot.U1);
14736f8fc217SDimitry Andric       break;
14746f8fc217SDimitry Andric     case BinaryAnnotationsOpCode::ChangeLineOffset:
1475145449b1SDimitry Andric       update_line_offset(annot.S1);
14766f8fc217SDimitry Andric       break;
14776f8fc217SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeLength:
1478145449b1SDimitry Andric       update_code_offset(annot.U1);
14796f8fc217SDimitry Andric       code_offset += annot.U1;
1480145449b1SDimitry Andric       is_terminal_entry = true;
14816f8fc217SDimitry Andric       break;
14826f8fc217SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
1483145449b1SDimitry Andric       code_offset += annot.U1;
1484145449b1SDimitry Andric       update_code_offset(annot.U1);
1485145449b1SDimitry Andric       update_line_offset(annot.S1);
14866f8fc217SDimitry Andric       break;
14876f8fc217SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
1488145449b1SDimitry Andric       code_offset += annot.U2;
1489145449b1SDimitry Andric       update_code_offset(annot.U2);
1490145449b1SDimitry Andric       update_code_offset(annot.U1);
1491145449b1SDimitry Andric       code_offset += annot.U1;
1492145449b1SDimitry Andric       is_terminal_entry = true;
1493145449b1SDimitry Andric       break;
1494145449b1SDimitry Andric     case BinaryAnnotationsOpCode::ChangeFile:
1495145449b1SDimitry Andric       update_file_offset(annot.U1);
14966f8fc217SDimitry Andric       break;
14976f8fc217SDimitry Andric     default:
14986f8fc217SDimitry Andric       break;
14996f8fc217SDimitry Andric     }
1500145449b1SDimitry Andric 
1501145449b1SDimitry Andric     // Add range if current range is finished.
1502145449b1SDimitry Andric     if (code_offset_base && code_offset_end && cur_line_offset) {
1503145449b1SDimitry Andric       inline_site_sp->ranges.Append(RangeSourceLineVector::Entry(
1504145449b1SDimitry Andric           *code_offset_base, *code_offset_end - *code_offset_base,
1505145449b1SDimitry Andric           decl_line + *cur_line_offset));
1506145449b1SDimitry Andric       // Set base, end, file offset and line offset for next range.
1507145449b1SDimitry Andric       if (next_file_offset)
1508145449b1SDimitry Andric         file_offset = *next_file_offset;
1509145449b1SDimitry Andric       if (next_line_offset) {
1510145449b1SDimitry Andric         cur_line_offset = next_line_offset;
1511e3b55780SDimitry Andric         next_line_offset = std::nullopt;
1512145449b1SDimitry Andric       }
1513e3b55780SDimitry Andric       code_offset_base = is_terminal_entry ? std::nullopt : code_offset_end;
1514e3b55780SDimitry Andric       code_offset_end = next_file_offset = std::nullopt;
1515145449b1SDimitry Andric     }
1516145449b1SDimitry Andric     if (code_offset_base && cur_line_offset) {
1517145449b1SDimitry Andric       if (is_terminal_entry) {
1518145449b1SDimitry Andric         LineTable::Entry line_entry(
1519145449b1SDimitry Andric             func_base + *code_offset_base, decl_line + *cur_line_offset, 0,
1520145449b1SDimitry Andric             file_offset, false, false, false, false, true);
1521145449b1SDimitry Andric         inline_site_sp->line_entries.push_back(line_entry);
1522145449b1SDimitry Andric       } else {
1523145449b1SDimitry Andric         LineTable::Entry line_entry(func_base + *code_offset_base,
1524145449b1SDimitry Andric                                     decl_line + *cur_line_offset, 0,
1525145449b1SDimitry Andric                                     file_offset, is_start_of_statement, false,
1526145449b1SDimitry Andric                                     is_prologue_end, false, false);
1527145449b1SDimitry Andric         inline_site_sp->line_entries.push_back(line_entry);
1528145449b1SDimitry Andric         is_prologue_end = false;
1529145449b1SDimitry Andric         is_start_of_statement = false;
1530145449b1SDimitry Andric       }
1531145449b1SDimitry Andric     }
1532145449b1SDimitry Andric     if (is_terminal_entry)
1533145449b1SDimitry Andric       is_start_of_statement = true;
1534145449b1SDimitry Andric     is_terminal_entry = false;
15356f8fc217SDimitry Andric   }
15366f8fc217SDimitry Andric 
15376f8fc217SDimitry Andric   inline_site_sp->ranges.Sort();
15386f8fc217SDimitry Andric 
15396f8fc217SDimitry Andric   // Get the inlined function callsite info.
15406f8fc217SDimitry Andric   std::unique_ptr<Declaration> callsite_up;
15416f8fc217SDimitry Andric   if (!inline_site_sp->ranges.IsEmpty()) {
15426f8fc217SDimitry Andric     auto *entry = inline_site_sp->ranges.GetEntryAtIndex(0);
15436f8fc217SDimitry Andric     addr_t base_offset = entry->GetRangeBase();
15446f8fc217SDimitry Andric     if (cii->m_debug_stream.readSymbolAtOffset(parent_id.offset).kind() ==
15456f8fc217SDimitry Andric         S_INLINESITE) {
15466f8fc217SDimitry Andric       // Its parent is another inline site, lookup parent site's range vector
15476f8fc217SDimitry Andric       // for callsite line.
15486f8fc217SDimitry Andric       ParseInlineSite(parent_id, func_base);
15496f8fc217SDimitry Andric       std::shared_ptr<InlineSite> parent_site =
15506f8fc217SDimitry Andric           m_inline_sites[toOpaqueUid(parent_id)];
15516f8fc217SDimitry Andric       FileSpec &parent_decl_file =
15526f8fc217SDimitry Andric           parent_site->inline_function_info->GetDeclaration().GetFile();
15536f8fc217SDimitry Andric       if (auto *parent_entry =
15546f8fc217SDimitry Andric               parent_site->ranges.FindEntryThatContains(base_offset)) {
15556f8fc217SDimitry Andric         callsite_up =
15566f8fc217SDimitry Andric             std::make_unique<Declaration>(parent_decl_file, parent_entry->data);
15576f8fc217SDimitry Andric       }
15586f8fc217SDimitry Andric     } else {
15596f8fc217SDimitry Andric       // Its parent is a function, lookup global line table for callsite.
15606f8fc217SDimitry Andric       if (auto *entry = cii->m_global_line_table.FindEntryThatContains(
15616f8fc217SDimitry Andric               func_base + base_offset)) {
15626f8fc217SDimitry Andric         const FileSpec &callsite_file =
15636f8fc217SDimitry Andric             files.GetFileSpecAtIndex(entry->data.first);
15646f8fc217SDimitry Andric         callsite_up =
15656f8fc217SDimitry Andric             std::make_unique<Declaration>(callsite_file, entry->data.second);
15666f8fc217SDimitry Andric       }
15676f8fc217SDimitry Andric     }
15686f8fc217SDimitry Andric   }
15696f8fc217SDimitry Andric 
15706f8fc217SDimitry Andric   // Get the inlined function name.
15716f8fc217SDimitry Andric   CVType inlinee_cvt = m_index->ipi().getType(inline_site.Inlinee);
15726f8fc217SDimitry Andric   std::string inlinee_name;
15736f8fc217SDimitry Andric   if (inlinee_cvt.kind() == LF_MFUNC_ID) {
15746f8fc217SDimitry Andric     MemberFuncIdRecord mfr;
15756f8fc217SDimitry Andric     cantFail(
15766f8fc217SDimitry Andric         TypeDeserializer::deserializeAs<MemberFuncIdRecord>(inlinee_cvt, mfr));
15776f8fc217SDimitry Andric     LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
15786f8fc217SDimitry Andric     inlinee_name.append(std::string(types.getTypeName(mfr.ClassType)));
15796f8fc217SDimitry Andric     inlinee_name.append("::");
15806f8fc217SDimitry Andric     inlinee_name.append(mfr.getName().str());
15816f8fc217SDimitry Andric   } else if (inlinee_cvt.kind() == LF_FUNC_ID) {
15826f8fc217SDimitry Andric     FuncIdRecord fir;
15836f8fc217SDimitry Andric     cantFail(TypeDeserializer::deserializeAs<FuncIdRecord>(inlinee_cvt, fir));
15846f8fc217SDimitry Andric     TypeIndex parent_idx = fir.getParentScope();
15856f8fc217SDimitry Andric     if (!parent_idx.isNoneType()) {
15866f8fc217SDimitry Andric       LazyRandomTypeCollection &ids = m_index->ipi().typeCollection();
15876f8fc217SDimitry Andric       inlinee_name.append(std::string(ids.getTypeName(parent_idx)));
15886f8fc217SDimitry Andric       inlinee_name.append("::");
15896f8fc217SDimitry Andric     }
15906f8fc217SDimitry Andric     inlinee_name.append(fir.getName().str());
15916f8fc217SDimitry Andric   }
15926f8fc217SDimitry Andric   inline_site_sp->inline_function_info = std::make_shared<InlineFunctionInfo>(
15936f8fc217SDimitry Andric       inlinee_name.c_str(), llvm::StringRef(), decl_up.get(),
15946f8fc217SDimitry Andric       callsite_up.get());
15956f8fc217SDimitry Andric 
15966f8fc217SDimitry Andric   m_inline_sites[opaque_uid] = inline_site_sp;
15976f8fc217SDimitry Andric }
15986f8fc217SDimitry Andric 
ParseBlocksRecursive(Function & func)159994994d37SDimitry Andric size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) {
1600ead24645SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
16016f8fc217SDimitry Andric   PdbCompilandSymId func_id = PdbSymUid(func.GetID()).asCompilandSym();
16026f8fc217SDimitry Andric   // After we iterate through inline sites inside the function, we already get
16036f8fc217SDimitry Andric   // all the info needed, removing from the map to save memory.
16046f8fc217SDimitry Andric   std::set<uint64_t> remove_uids;
16056f8fc217SDimitry Andric   auto parse_blocks = [&](SymbolKind kind, PdbCompilandSymId id) {
16066f8fc217SDimitry Andric     if (kind == S_GPROC32 || kind == S_LPROC32 || kind == S_BLOCK32 ||
16076f8fc217SDimitry Andric         kind == S_INLINESITE) {
16086f8fc217SDimitry Andric       GetOrCreateBlock(id);
16096f8fc217SDimitry Andric       if (kind == S_INLINESITE)
16106f8fc217SDimitry Andric         remove_uids.insert(toOpaqueUid(id));
16116f8fc217SDimitry Andric       return true;
16126f8fc217SDimitry Andric     }
16136f8fc217SDimitry Andric     return false;
16146f8fc217SDimitry Andric   };
16156f8fc217SDimitry Andric   size_t count = ParseSymbolArrayInScope(func_id, parse_blocks);
16166f8fc217SDimitry Andric   for (uint64_t uid : remove_uids) {
16176f8fc217SDimitry Andric     m_inline_sites.erase(uid);
16186f8fc217SDimitry Andric   }
16196f8fc217SDimitry Andric   return count;
16206f8fc217SDimitry Andric }
16216f8fc217SDimitry Andric 
ParseSymbolArrayInScope(PdbCompilandSymId parent_id,llvm::function_ref<bool (SymbolKind,PdbCompilandSymId)> fn)16226f8fc217SDimitry Andric size_t SymbolFileNativePDB::ParseSymbolArrayInScope(
16236f8fc217SDimitry Andric     PdbCompilandSymId parent_id,
16246f8fc217SDimitry Andric     llvm::function_ref<bool(SymbolKind, PdbCompilandSymId)> fn) {
16256f8fc217SDimitry Andric   CompilandIndexItem *cii = m_index->compilands().GetCompiland(parent_id.modi);
16266f8fc217SDimitry Andric   CVSymbolArray syms =
16276f8fc217SDimitry Andric       cii->m_debug_stream.getSymbolArrayForScope(parent_id.offset);
16286f8fc217SDimitry Andric 
16296f8fc217SDimitry Andric   size_t count = 1;
16306f8fc217SDimitry Andric   for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
16316f8fc217SDimitry Andric     PdbCompilandSymId child_id(parent_id.modi, iter.offset());
16326f8fc217SDimitry Andric     if (fn(iter->kind(), child_id))
16336f8fc217SDimitry Andric       ++count;
16346f8fc217SDimitry Andric   }
16356f8fc217SDimitry Andric 
16366f8fc217SDimitry Andric   return count;
163794994d37SDimitry Andric }
163894994d37SDimitry Andric 
DumpClangAST(Stream & s)1639e3b55780SDimitry Andric void SymbolFileNativePDB::DumpClangAST(Stream &s) {
1640e3b55780SDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
1641e3b55780SDimitry Andric   if (!ts_or_err)
1642e3b55780SDimitry Andric     return;
1643e3b55780SDimitry Andric   auto ts = *ts_or_err;
1644e3b55780SDimitry Andric   TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
1645e3b55780SDimitry Andric   if (!clang)
1646e3b55780SDimitry Andric     return;
1647e3b55780SDimitry Andric   clang->GetNativePDBParser()->Dump(s);
1648e3b55780SDimitry Andric }
164994994d37SDimitry Andric 
FindGlobalVariables(ConstString name,const CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,VariableList & variables)1650ead24645SDimitry Andric void SymbolFileNativePDB::FindGlobalVariables(
1651cfca06d7SDimitry Andric     ConstString name, const CompilerDeclContext &parent_decl_ctx,
165294994d37SDimitry Andric     uint32_t max_matches, VariableList &variables) {
1653ead24645SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
165494994d37SDimitry Andric   using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
165594994d37SDimitry Andric 
165694994d37SDimitry Andric   std::vector<SymbolAndOffset> results = m_index->globals().findRecordsByName(
165794994d37SDimitry Andric       name.GetStringRef(), m_index->symrecords());
165894994d37SDimitry Andric   for (const SymbolAndOffset &result : results) {
165994994d37SDimitry Andric     switch (result.second.kind()) {
166094994d37SDimitry Andric     case SymbolKind::S_GDATA32:
166194994d37SDimitry Andric     case SymbolKind::S_LDATA32:
166294994d37SDimitry Andric     case SymbolKind::S_GTHREAD32:
166394994d37SDimitry Andric     case SymbolKind::S_LTHREAD32:
166494994d37SDimitry Andric     case SymbolKind::S_CONSTANT: {
166594994d37SDimitry Andric       PdbGlobalSymId global(result.first, false);
1666145449b1SDimitry Andric       if (VariableSP var = GetOrCreateGlobalVariable(global))
166794994d37SDimitry Andric         variables.AddVariable(var);
166894994d37SDimitry Andric       break;
166994994d37SDimitry Andric     }
167094994d37SDimitry Andric     default:
167194994d37SDimitry Andric       continue;
167294994d37SDimitry Andric     }
167394994d37SDimitry Andric   }
167494994d37SDimitry Andric }
167594994d37SDimitry Andric 
FindFunctions(const Module::LookupInfo & lookup_info,const CompilerDeclContext & parent_decl_ctx,bool include_inlines,SymbolContextList & sc_list)1676ead24645SDimitry Andric void SymbolFileNativePDB::FindFunctions(
1677e3b55780SDimitry Andric     const Module::LookupInfo &lookup_info,
1678e3b55780SDimitry Andric     const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
167994994d37SDimitry Andric     SymbolContextList &sc_list) {
1680ead24645SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1681e3b55780SDimitry Andric   ConstString name = lookup_info.GetLookupName();
1682e3b55780SDimitry Andric   FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
1683e3b55780SDimitry Andric   if (name_type_mask & eFunctionNameTypeFull)
1684e3b55780SDimitry Andric     name = lookup_info.GetName();
1685e3b55780SDimitry Andric 
1686f65dcba8SDimitry Andric   // For now we only support lookup by method name or full name.
1687f65dcba8SDimitry Andric   if (!(name_type_mask & eFunctionNameTypeFull ||
1688f65dcba8SDimitry Andric         name_type_mask & eFunctionNameTypeMethod))
1689ead24645SDimitry Andric     return;
169094994d37SDimitry Andric 
169194994d37SDimitry Andric   using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
169294994d37SDimitry Andric 
169394994d37SDimitry Andric   std::vector<SymbolAndOffset> matches = m_index->globals().findRecordsByName(
169494994d37SDimitry Andric       name.GetStringRef(), m_index->symrecords());
169594994d37SDimitry Andric   for (const SymbolAndOffset &match : matches) {
169694994d37SDimitry Andric     if (match.second.kind() != S_PROCREF && match.second.kind() != S_LPROCREF)
169794994d37SDimitry Andric       continue;
169894994d37SDimitry Andric     ProcRefSym proc(match.second.kind());
169994994d37SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(match.second, proc));
170094994d37SDimitry Andric 
170194994d37SDimitry Andric     if (!IsValidRecord(proc))
170294994d37SDimitry Andric       continue;
170394994d37SDimitry Andric 
170494994d37SDimitry Andric     CompilandIndexItem &cci =
170594994d37SDimitry Andric         m_index->compilands().GetOrCreateCompiland(proc.modi());
170694994d37SDimitry Andric     SymbolContext sc;
170794994d37SDimitry Andric 
170894994d37SDimitry Andric     sc.comp_unit = GetOrCreateCompileUnit(cci).get();
170994994d37SDimitry Andric     PdbCompilandSymId func_id(proc.modi(), proc.SymOffset);
171094994d37SDimitry Andric     sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get();
171194994d37SDimitry Andric 
171294994d37SDimitry Andric     sc_list.Append(sc);
171394994d37SDimitry Andric   }
171494994d37SDimitry Andric }
171594994d37SDimitry Andric 
FindFunctions(const RegularExpression & regex,bool include_inlines,SymbolContextList & sc_list)1716ead24645SDimitry Andric void SymbolFileNativePDB::FindFunctions(const RegularExpression &regex,
1717ead24645SDimitry Andric                                         bool include_inlines,
1718ead24645SDimitry Andric                                         SymbolContextList &sc_list) {}
171994994d37SDimitry Andric 
FindTypes(const lldb_private::TypeQuery & query,lldb_private::TypeResults & results)1720312c0ed1SDimitry Andric void SymbolFileNativePDB::FindTypes(const lldb_private::TypeQuery &query,
1721312c0ed1SDimitry Andric                                     lldb_private::TypeResults &results) {
1722312c0ed1SDimitry Andric 
1723312c0ed1SDimitry Andric   // Make sure we haven't already searched this SymbolFile before.
1724312c0ed1SDimitry Andric   if (results.AlreadySearched(this))
1725ead24645SDimitry Andric     return;
172694994d37SDimitry Andric 
1727312c0ed1SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
172894994d37SDimitry Andric 
1729312c0ed1SDimitry Andric   std::vector<TypeIndex> matches =
1730312c0ed1SDimitry Andric       m_index->tpi().findRecordsByName(query.GetTypeBasename().GetStringRef());
1731312c0ed1SDimitry Andric 
1732312c0ed1SDimitry Andric   for (TypeIndex type_idx : matches) {
1733312c0ed1SDimitry Andric     TypeSP type_sp = GetOrCreateType(type_idx);
1734312c0ed1SDimitry Andric     if (!type_sp)
1735312c0ed1SDimitry Andric       continue;
1736312c0ed1SDimitry Andric 
1737312c0ed1SDimitry Andric     // We resolved a type. Get the fully qualified name to ensure it matches.
1738312c0ed1SDimitry Andric     ConstString name = type_sp->GetQualifiedName();
1739312c0ed1SDimitry Andric     TypeQuery type_match(name.GetStringRef(), TypeQueryOptions::e_exact_match);
1740312c0ed1SDimitry Andric     if (query.ContextMatches(type_match.GetContextRef())) {
1741312c0ed1SDimitry Andric       results.InsertUnique(type_sp);
1742312c0ed1SDimitry Andric       if (results.Done(query))
1743312c0ed1SDimitry Andric         return;
174494994d37SDimitry Andric     }
1745312c0ed1SDimitry Andric   }
1746312c0ed1SDimitry Andric }
174794994d37SDimitry Andric 
FindTypesByName(llvm::StringRef name,uint32_t max_matches,TypeMap & types)1748ead24645SDimitry Andric void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name,
174994994d37SDimitry Andric                                           uint32_t max_matches,
175094994d37SDimitry Andric                                           TypeMap &types) {
175194994d37SDimitry Andric 
175294994d37SDimitry Andric   std::vector<TypeIndex> matches = m_index->tpi().findRecordsByName(name);
175394994d37SDimitry Andric   if (max_matches > 0 && max_matches < matches.size())
175494994d37SDimitry Andric     matches.resize(max_matches);
175594994d37SDimitry Andric 
175694994d37SDimitry Andric   for (TypeIndex ti : matches) {
175794994d37SDimitry Andric     TypeSP type = GetOrCreateType(ti);
175894994d37SDimitry Andric     if (!type)
175994994d37SDimitry Andric       continue;
176094994d37SDimitry Andric 
176194994d37SDimitry Andric     types.Insert(type);
176294994d37SDimitry Andric   }
176394994d37SDimitry Andric }
176494994d37SDimitry Andric 
ParseTypes(CompileUnit & comp_unit)176594994d37SDimitry Andric size_t SymbolFileNativePDB::ParseTypes(CompileUnit &comp_unit) {
1766ead24645SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
176794994d37SDimitry Andric   // Only do the full type scan the first time.
176894994d37SDimitry Andric   if (m_done_full_type_scan)
176994994d37SDimitry Andric     return 0;
177094994d37SDimitry Andric 
1771ead24645SDimitry Andric   const size_t old_count = GetTypeList().GetSize();
177294994d37SDimitry Andric   LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
177394994d37SDimitry Andric 
177494994d37SDimitry Andric   // First process the entire TPI stream.
177594994d37SDimitry Andric   for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
177694994d37SDimitry Andric     TypeSP type = GetOrCreateType(*ti);
177794994d37SDimitry Andric     if (type)
177894994d37SDimitry Andric       (void)type->GetFullCompilerType();
177994994d37SDimitry Andric   }
178094994d37SDimitry Andric 
178194994d37SDimitry Andric   // Next look for S_UDT records in the globals stream.
178294994d37SDimitry Andric   for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
178394994d37SDimitry Andric     PdbGlobalSymId global{gid, false};
178494994d37SDimitry Andric     CVSymbol sym = m_index->ReadSymbolRecord(global);
178594994d37SDimitry Andric     if (sym.kind() != S_UDT)
178694994d37SDimitry Andric       continue;
178794994d37SDimitry Andric 
178894994d37SDimitry Andric     UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
178994994d37SDimitry Andric     bool is_typedef = true;
179094994d37SDimitry Andric     if (IsTagRecord(PdbTypeSymId{udt.Type, false}, m_index->tpi())) {
179194994d37SDimitry Andric       CVType cvt = m_index->tpi().getType(udt.Type);
179294994d37SDimitry Andric       llvm::StringRef name = CVTagRecord::create(cvt).name();
179394994d37SDimitry Andric       if (name == udt.Name)
179494994d37SDimitry Andric         is_typedef = false;
179594994d37SDimitry Andric     }
179694994d37SDimitry Andric 
179794994d37SDimitry Andric     if (is_typedef)
179894994d37SDimitry Andric       GetOrCreateTypedef(global);
179994994d37SDimitry Andric   }
180094994d37SDimitry Andric 
1801ead24645SDimitry Andric   const size_t new_count = GetTypeList().GetSize();
180294994d37SDimitry Andric 
180394994d37SDimitry Andric   m_done_full_type_scan = true;
180494994d37SDimitry Andric 
180594994d37SDimitry Andric   return new_count - old_count;
180694994d37SDimitry Andric }
180794994d37SDimitry Andric 
180894994d37SDimitry Andric size_t
ParseVariablesForCompileUnit(CompileUnit & comp_unit,VariableList & variables)180994994d37SDimitry Andric SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit,
181094994d37SDimitry Andric                                                   VariableList &variables) {
181194994d37SDimitry Andric   PdbSymUid sym_uid(comp_unit.GetID());
181294994d37SDimitry Andric   lldbassert(sym_uid.kind() == PdbSymUidKind::Compiland);
181394994d37SDimitry Andric   return 0;
181494994d37SDimitry Andric }
181594994d37SDimitry Andric 
CreateLocalVariable(PdbCompilandSymId scope_id,PdbCompilandSymId var_id,bool is_param)181694994d37SDimitry Andric VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
181794994d37SDimitry Andric                                                     PdbCompilandSymId var_id,
181894994d37SDimitry Andric                                                     bool is_param) {
181994994d37SDimitry Andric   ModuleSP module = GetObjectFile()->GetModule();
18205f29bb8aSDimitry Andric   Block &block = GetOrCreateBlock(scope_id);
18211f917f69SDimitry Andric   // Get function block.
18221f917f69SDimitry Andric   Block *func_block = &block;
18231f917f69SDimitry Andric   while (func_block->GetParent()) {
18241f917f69SDimitry Andric     func_block = func_block->GetParent();
18251f917f69SDimitry Andric   }
18261f917f69SDimitry Andric   Address addr;
18271f917f69SDimitry Andric   func_block->GetStartAddress(addr);
18285f29bb8aSDimitry Andric   VariableInfo var_info =
18291f917f69SDimitry Andric       GetVariableLocationInfo(*m_index, var_id, *func_block, module);
1830e3b55780SDimitry Andric   Function *func = func_block->CalculateSymbolContextFunction();
1831e3b55780SDimitry Andric   if (!func)
183294994d37SDimitry Andric     return nullptr;
1833e3b55780SDimitry Andric   // Use empty dwarf expr if optimized away so that it won't be filtered out
1834e3b55780SDimitry Andric   // when lookuping local variables in this scope.
1835e3b55780SDimitry Andric   if (!var_info.location.IsValid())
1836e3b55780SDimitry Andric     var_info.location = DWARFExpressionList(module, DWARFExpression(), nullptr);
1837e3b55780SDimitry Andric   var_info.location.SetFuncFileAddress(
1838e3b55780SDimitry Andric       func->GetAddressRange().GetBaseAddress().GetFileAddress());
183994994d37SDimitry Andric   CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
184094994d37SDimitry Andric   CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
184194994d37SDimitry Andric   TypeSP type_sp = GetOrCreateType(var_info.type);
1842e3b55780SDimitry Andric   if (!type_sp)
1843e3b55780SDimitry Andric     return nullptr;
184494994d37SDimitry Andric   std::string name = var_info.name.str();
184594994d37SDimitry Andric   Declaration decl;
184694994d37SDimitry Andric   SymbolFileTypeSP sftype =
184794994d37SDimitry Andric       std::make_shared<SymbolFileType>(*this, type_sp->GetID());
184894994d37SDimitry Andric 
1849145449b1SDimitry Andric   is_param |= var_info.is_param;
185094994d37SDimitry Andric   ValueType var_scope =
185194994d37SDimitry Andric       is_param ? eValueTypeVariableArgument : eValueTypeVariableLocal;
1852b60736ecSDimitry Andric   bool external = false;
1853b60736ecSDimitry Andric   bool artificial = false;
1854b60736ecSDimitry Andric   bool location_is_constant_data = false;
1855b60736ecSDimitry Andric   bool static_member = false;
1856e3b55780SDimitry Andric   Variable::RangeList scope_ranges;
185794994d37SDimitry Andric   VariableSP var_sp = std::make_shared<Variable>(
185894994d37SDimitry Andric       toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope,
1859e3b55780SDimitry Andric       &block, scope_ranges, &decl, var_info.location, external, artificial,
18601f917f69SDimitry Andric       location_is_constant_data, static_member);
1861e3b55780SDimitry Andric   if (!is_param) {
1862e3b55780SDimitry Andric     auto ts_or_err = GetTypeSystemForLanguage(comp_unit_sp->GetLanguage());
1863e3b55780SDimitry Andric     if (auto err = ts_or_err.takeError())
1864e3b55780SDimitry Andric       return nullptr;
1865e3b55780SDimitry Andric     auto ts = *ts_or_err;
1866e3b55780SDimitry Andric     if (!ts)
1867e3b55780SDimitry Andric       return nullptr;
186894994d37SDimitry Andric 
1869e3b55780SDimitry Andric     ts->GetNativePDBParser()->GetOrCreateVariableDecl(scope_id, var_id);
1870e3b55780SDimitry Andric   }
187194994d37SDimitry Andric   m_local_variables[toOpaqueUid(var_id)] = var_sp;
187294994d37SDimitry Andric   return var_sp;
187394994d37SDimitry Andric }
187494994d37SDimitry Andric 
GetOrCreateLocalVariable(PdbCompilandSymId scope_id,PdbCompilandSymId var_id,bool is_param)187594994d37SDimitry Andric VariableSP SymbolFileNativePDB::GetOrCreateLocalVariable(
187694994d37SDimitry Andric     PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param) {
187794994d37SDimitry Andric   auto iter = m_local_variables.find(toOpaqueUid(var_id));
187894994d37SDimitry Andric   if (iter != m_local_variables.end())
187994994d37SDimitry Andric     return iter->second;
188094994d37SDimitry Andric 
188194994d37SDimitry Andric   return CreateLocalVariable(scope_id, var_id, is_param);
188294994d37SDimitry Andric }
188394994d37SDimitry Andric 
CreateTypedef(PdbGlobalSymId id)188494994d37SDimitry Andric TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
188594994d37SDimitry Andric   CVSymbol sym = m_index->ReadSymbolRecord(id);
188694994d37SDimitry Andric   lldbassert(sym.kind() == SymbolKind::S_UDT);
188794994d37SDimitry Andric 
188894994d37SDimitry Andric   UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
188994994d37SDimitry Andric 
189094994d37SDimitry Andric   TypeSP target_type = GetOrCreateType(udt.Type);
189194994d37SDimitry Andric 
1892e3b55780SDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
1893e3b55780SDimitry Andric   if (auto err = ts_or_err.takeError())
1894e3b55780SDimitry Andric     return nullptr;
1895e3b55780SDimitry Andric   auto ts = *ts_or_err;
1896e3b55780SDimitry Andric   if (!ts)
1897e3b55780SDimitry Andric     return nullptr;
1898e3b55780SDimitry Andric 
1899e3b55780SDimitry Andric   ts->GetNativePDBParser()->GetOrCreateTypedefDecl(id);
190094994d37SDimitry Andric 
190194994d37SDimitry Andric   Declaration decl;
1902e3b55780SDimitry Andric   return MakeType(
1903e3b55780SDimitry Andric       toOpaqueUid(id), ConstString(udt.Name), target_type->GetByteSize(nullptr),
1904e3b55780SDimitry Andric       nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID,
1905e3b55780SDimitry Andric       decl, target_type->GetForwardCompilerType(),
1906706b4fc4SDimitry Andric       lldb_private::Type::ResolveState::Forward);
190794994d37SDimitry Andric }
190894994d37SDimitry Andric 
GetOrCreateTypedef(PdbGlobalSymId id)190994994d37SDimitry Andric TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) {
191094994d37SDimitry Andric   auto iter = m_types.find(toOpaqueUid(id));
191194994d37SDimitry Andric   if (iter != m_types.end())
191294994d37SDimitry Andric     return iter->second;
191394994d37SDimitry Andric 
191494994d37SDimitry Andric   return CreateTypedef(id);
191594994d37SDimitry Andric }
191694994d37SDimitry Andric 
ParseVariablesForBlock(PdbCompilandSymId block_id)191794994d37SDimitry Andric size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) {
191894994d37SDimitry Andric   Block &block = GetOrCreateBlock(block_id);
191994994d37SDimitry Andric 
192094994d37SDimitry Andric   size_t count = 0;
192194994d37SDimitry Andric 
192294994d37SDimitry Andric   CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
192394994d37SDimitry Andric   CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
192494994d37SDimitry Andric   uint32_t params_remaining = 0;
192594994d37SDimitry Andric   switch (sym.kind()) {
192694994d37SDimitry Andric   case S_GPROC32:
192794994d37SDimitry Andric   case S_LPROC32: {
192894994d37SDimitry Andric     ProcSym proc(static_cast<SymbolRecordKind>(sym.kind()));
192994994d37SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym, proc));
193094994d37SDimitry Andric     CVType signature = m_index->tpi().getType(proc.FunctionType);
1931e3b55780SDimitry Andric     if (signature.kind() == LF_PROCEDURE) {
193294994d37SDimitry Andric       ProcedureRecord sig;
1933e3b55780SDimitry Andric       if (llvm::Error e = TypeDeserializer::deserializeAs<ProcedureRecord>(
1934e3b55780SDimitry Andric               signature, sig)) {
1935e3b55780SDimitry Andric         llvm::consumeError(std::move(e));
1936e3b55780SDimitry Andric         return 0;
1937e3b55780SDimitry Andric       }
193894994d37SDimitry Andric       params_remaining = sig.getParameterCount();
1939e3b55780SDimitry Andric     } else if (signature.kind() == LF_MFUNCTION) {
1940e3b55780SDimitry Andric       MemberFunctionRecord sig;
1941e3b55780SDimitry Andric       if (llvm::Error e = TypeDeserializer::deserializeAs<MemberFunctionRecord>(
1942e3b55780SDimitry Andric               signature, sig)) {
1943e3b55780SDimitry Andric         llvm::consumeError(std::move(e));
1944e3b55780SDimitry Andric         return 0;
1945e3b55780SDimitry Andric       }
1946e3b55780SDimitry Andric       params_remaining = sig.getParameterCount();
1947e3b55780SDimitry Andric     } else
1948e3b55780SDimitry Andric       return 0;
194994994d37SDimitry Andric     break;
195094994d37SDimitry Andric   }
195194994d37SDimitry Andric   case S_BLOCK32:
195294994d37SDimitry Andric     break;
19536f8fc217SDimitry Andric   case S_INLINESITE:
1954145449b1SDimitry Andric     break;
195594994d37SDimitry Andric   default:
195694994d37SDimitry Andric     lldbassert(false && "Symbol is not a block!");
195794994d37SDimitry Andric     return 0;
195894994d37SDimitry Andric   }
195994994d37SDimitry Andric 
196094994d37SDimitry Andric   VariableListSP variables = block.GetBlockVariableList(false);
196194994d37SDimitry Andric   if (!variables) {
196294994d37SDimitry Andric     variables = std::make_shared<VariableList>();
196394994d37SDimitry Andric     block.SetVariableList(variables);
196494994d37SDimitry Andric   }
196594994d37SDimitry Andric 
196694994d37SDimitry Andric   CVSymbolArray syms = limitSymbolArrayToScope(
196794994d37SDimitry Andric       cii->m_debug_stream.getSymbolArray(), block_id.offset);
196894994d37SDimitry Andric 
196994994d37SDimitry Andric   // Skip the first record since it's a PROC32 or BLOCK32, and there's
197094994d37SDimitry Andric   // no point examining it since we know it's not a local variable.
197194994d37SDimitry Andric   syms.drop_front();
197294994d37SDimitry Andric   auto iter = syms.begin();
197394994d37SDimitry Andric   auto end = syms.end();
197494994d37SDimitry Andric 
197594994d37SDimitry Andric   while (iter != end) {
197694994d37SDimitry Andric     uint32_t record_offset = iter.offset();
197794994d37SDimitry Andric     CVSymbol variable_cvs = *iter;
197894994d37SDimitry Andric     PdbCompilandSymId child_sym_id(block_id.modi, record_offset);
197994994d37SDimitry Andric     ++iter;
198094994d37SDimitry Andric 
1981145449b1SDimitry Andric     // If this is a block or inline site, recurse into its children and then
1982145449b1SDimitry Andric     // skip it.
1983145449b1SDimitry Andric     if (variable_cvs.kind() == S_BLOCK32 ||
1984145449b1SDimitry Andric         variable_cvs.kind() == S_INLINESITE) {
198594994d37SDimitry Andric       uint32_t block_end = getScopeEndOffset(variable_cvs);
198694994d37SDimitry Andric       count += ParseVariablesForBlock(child_sym_id);
198794994d37SDimitry Andric       iter = syms.at(block_end);
198894994d37SDimitry Andric       continue;
198994994d37SDimitry Andric     }
199094994d37SDimitry Andric 
199194994d37SDimitry Andric     bool is_param = params_remaining > 0;
199294994d37SDimitry Andric     VariableSP variable;
199394994d37SDimitry Andric     switch (variable_cvs.kind()) {
199494994d37SDimitry Andric     case S_REGREL32:
199594994d37SDimitry Andric     case S_REGISTER:
199694994d37SDimitry Andric     case S_LOCAL:
199794994d37SDimitry Andric       variable = GetOrCreateLocalVariable(block_id, child_sym_id, is_param);
199894994d37SDimitry Andric       if (is_param)
199994994d37SDimitry Andric         --params_remaining;
200094994d37SDimitry Andric       if (variable)
200194994d37SDimitry Andric         variables->AddVariableIfUnique(variable);
200294994d37SDimitry Andric       break;
200394994d37SDimitry Andric     default:
200494994d37SDimitry Andric       break;
200594994d37SDimitry Andric     }
200694994d37SDimitry Andric   }
200794994d37SDimitry Andric 
200894994d37SDimitry Andric   // Pass false for set_children, since we call this recursively so that the
200994994d37SDimitry Andric   // children will call this for themselves.
201094994d37SDimitry Andric   block.SetDidParseVariables(true, false);
201194994d37SDimitry Andric 
201294994d37SDimitry Andric   return count;
201394994d37SDimitry Andric }
201494994d37SDimitry Andric 
ParseVariablesForContext(const SymbolContext & sc)201594994d37SDimitry Andric size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) {
2016ead24645SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
201794994d37SDimitry Andric   lldbassert(sc.function || sc.comp_unit);
201894994d37SDimitry Andric 
201994994d37SDimitry Andric   VariableListSP variables;
202094994d37SDimitry Andric   if (sc.block) {
202194994d37SDimitry Andric     PdbSymUid block_id(sc.block->GetID());
202294994d37SDimitry Andric 
202394994d37SDimitry Andric     size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
202494994d37SDimitry Andric     return count;
202594994d37SDimitry Andric   }
202694994d37SDimitry Andric 
202794994d37SDimitry Andric   if (sc.function) {
202894994d37SDimitry Andric     PdbSymUid block_id(sc.function->GetID());
202994994d37SDimitry Andric 
203094994d37SDimitry Andric     size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
203194994d37SDimitry Andric     return count;
203294994d37SDimitry Andric   }
203394994d37SDimitry Andric 
203494994d37SDimitry Andric   if (sc.comp_unit) {
203594994d37SDimitry Andric     variables = sc.comp_unit->GetVariableList(false);
203694994d37SDimitry Andric     if (!variables) {
203794994d37SDimitry Andric       variables = std::make_shared<VariableList>();
203894994d37SDimitry Andric       sc.comp_unit->SetVariableList(variables);
203994994d37SDimitry Andric     }
204094994d37SDimitry Andric     return ParseVariablesForCompileUnit(*sc.comp_unit, *variables);
204194994d37SDimitry Andric   }
204294994d37SDimitry Andric 
204394994d37SDimitry Andric   llvm_unreachable("Unreachable!");
204494994d37SDimitry Andric }
204594994d37SDimitry Andric 
GetDeclForUID(lldb::user_id_t uid)204694994d37SDimitry Andric CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) {
2047e3b55780SDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
2048e3b55780SDimitry Andric   if (auto err = ts_or_err.takeError())
2049e3b55780SDimitry Andric     return CompilerDecl();
2050e3b55780SDimitry Andric   auto ts = *ts_or_err;
2051e3b55780SDimitry Andric   if (!ts)
2052e3b55780SDimitry Andric     return {};
2053e3b55780SDimitry Andric 
2054e3b55780SDimitry Andric   if (auto decl = ts->GetNativePDBParser()->GetOrCreateDeclForUid(uid))
2055145449b1SDimitry Andric     return *decl;
2056ead24645SDimitry Andric   return CompilerDecl();
205794994d37SDimitry Andric }
205894994d37SDimitry Andric 
205994994d37SDimitry Andric CompilerDeclContext
GetDeclContextForUID(lldb::user_id_t uid)206094994d37SDimitry Andric SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) {
2061e3b55780SDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
2062e3b55780SDimitry Andric   if (auto err = ts_or_err.takeError())
2063e3b55780SDimitry Andric     return {};
2064e3b55780SDimitry Andric   auto ts = *ts_or_err;
2065e3b55780SDimitry Andric   if (!ts)
2066e3b55780SDimitry Andric     return {};
2067e3b55780SDimitry Andric 
2068e3b55780SDimitry Andric   PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
206994994d37SDimitry Andric   clang::DeclContext *context =
2070e3b55780SDimitry Andric       ast_builder->GetOrCreateDeclContextForUid(PdbSymUid(uid));
207194994d37SDimitry Andric   if (!context)
207294994d37SDimitry Andric     return {};
207394994d37SDimitry Andric 
2074e3b55780SDimitry Andric   return ast_builder->ToCompilerDeclContext(*context);
207594994d37SDimitry Andric }
207694994d37SDimitry Andric 
207794994d37SDimitry Andric CompilerDeclContext
GetDeclContextContainingUID(lldb::user_id_t uid)207894994d37SDimitry Andric SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
2079e3b55780SDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
2080e3b55780SDimitry Andric   if (auto err = ts_or_err.takeError())
2081e3b55780SDimitry Andric     return CompilerDeclContext();
2082e3b55780SDimitry Andric   auto ts = *ts_or_err;
2083e3b55780SDimitry Andric   if (!ts)
2084e3b55780SDimitry Andric     return {};
2085e3b55780SDimitry Andric 
2086e3b55780SDimitry Andric   PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
2087e3b55780SDimitry Andric   clang::DeclContext *context = ast_builder->GetParentDeclContext(PdbSymUid(uid));
2088e3b55780SDimitry Andric   if (!context)
2089e3b55780SDimitry Andric     return CompilerDeclContext();
2090e3b55780SDimitry Andric   return ast_builder->ToCompilerDeclContext(*context);
209194994d37SDimitry Andric }
209294994d37SDimitry Andric 
ResolveTypeUID(lldb::user_id_t type_uid)209394994d37SDimitry Andric Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
2094ead24645SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
209594994d37SDimitry Andric   auto iter = m_types.find(type_uid);
209694994d37SDimitry Andric   // lldb should not be passing us non-sensical type uids.  the only way it
209794994d37SDimitry Andric   // could have a type uid in the first place is if we handed it out, in which
209894994d37SDimitry Andric   // case we should know about the type.  However, that doesn't mean we've
209994994d37SDimitry Andric   // instantiated it yet.  We can vend out a UID for a future type.  So if the
210094994d37SDimitry Andric   // type doesn't exist, let's instantiate it now.
210194994d37SDimitry Andric   if (iter != m_types.end())
210294994d37SDimitry Andric     return &*iter->second;
210394994d37SDimitry Andric 
210494994d37SDimitry Andric   PdbSymUid uid(type_uid);
210594994d37SDimitry Andric   lldbassert(uid.kind() == PdbSymUidKind::Type);
210694994d37SDimitry Andric   PdbTypeSymId type_id = uid.asTypeSym();
210794994d37SDimitry Andric   if (type_id.index.isNoneType())
210894994d37SDimitry Andric     return nullptr;
210994994d37SDimitry Andric 
211094994d37SDimitry Andric   TypeSP type_sp = CreateAndCacheType(type_id);
2111e3b55780SDimitry Andric   if (!type_sp)
2112e3b55780SDimitry Andric     return nullptr;
211394994d37SDimitry Andric   return &*type_sp;
211494994d37SDimitry Andric }
211594994d37SDimitry Andric 
2116e3b55780SDimitry Andric std::optional<SymbolFile::ArrayInfo>
GetDynamicArrayInfoForUID(lldb::user_id_t type_uid,const lldb_private::ExecutionContext * exe_ctx)211794994d37SDimitry Andric SymbolFileNativePDB::GetDynamicArrayInfoForUID(
211894994d37SDimitry Andric     lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
2119e3b55780SDimitry Andric   return std::nullopt;
212094994d37SDimitry Andric }
212194994d37SDimitry Andric 
CompleteType(CompilerType & compiler_type)212294994d37SDimitry Andric bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) {
2123e3b55780SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2124e3b55780SDimitry Andric   auto ts = compiler_type.GetTypeSystem();
2125e3b55780SDimitry Andric   auto clang_type_system = ts.dyn_cast_or_null<TypeSystemClang>();
2126e3b55780SDimitry Andric   if (!clang_type_system)
2127e3b55780SDimitry Andric     return false;
2128e3b55780SDimitry Andric 
2129e3b55780SDimitry Andric   PdbAstBuilder *ast_builder =
2130e3b55780SDimitry Andric       static_cast<PdbAstBuilder *>(clang_type_system->GetNativePDBParser());
2131e3b55780SDimitry Andric   if (ast_builder &&
2132e3b55780SDimitry Andric       ast_builder->GetClangASTImporter().CanImport(compiler_type))
2133e3b55780SDimitry Andric     return ast_builder->GetClangASTImporter().CompleteType(compiler_type);
213494994d37SDimitry Andric   clang::QualType qt =
213594994d37SDimitry Andric       clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType());
213694994d37SDimitry Andric 
2137e3b55780SDimitry Andric   return ast_builder->CompleteType(qt);
213894994d37SDimitry Andric }
213994994d37SDimitry Andric 
GetTypes(lldb_private::SymbolContextScope * sc_scope,TypeClass type_mask,lldb_private::TypeList & type_list)2140ead24645SDimitry Andric void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
214194994d37SDimitry Andric                                    TypeClass type_mask,
2142ead24645SDimitry Andric                                    lldb_private::TypeList &type_list) {}
214394994d37SDimitry Andric 
FindNamespace(ConstString name,const CompilerDeclContext & parent_decl_ctx,bool)21447fa27ce4SDimitry Andric CompilerDeclContext SymbolFileNativePDB::FindNamespace(
21457fa27ce4SDimitry Andric     ConstString name, const CompilerDeclContext &parent_decl_ctx, bool) {
214694994d37SDimitry Andric   return {};
214794994d37SDimitry Andric }
214894994d37SDimitry Andric 
2149e3b55780SDimitry Andric llvm::Expected<lldb::TypeSystemSP>
GetTypeSystemForLanguage(lldb::LanguageType language)215094994d37SDimitry Andric SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
2151ead24645SDimitry Andric   auto type_system_or_err =
2152ead24645SDimitry Andric       m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language);
2153e3b55780SDimitry Andric   if (type_system_or_err)
2154e3b55780SDimitry Andric     if (auto ts = *type_system_or_err)
2155e3b55780SDimitry Andric       ts->SetSymbolFile(this);
2156ead24645SDimitry Andric   return type_system_or_err;
215794994d37SDimitry Andric }
215894994d37SDimitry Andric 
GetDebugInfoSize(bool load_all_debug_info)2159ac9a064cSDimitry Andric uint64_t SymbolFileNativePDB::GetDebugInfoSize(bool load_all_debug_info) {
2160c0981da4SDimitry Andric   // PDB files are a separate file that contains all debug info.
2161c0981da4SDimitry Andric   return m_index->pdb().getFileSize();
216294994d37SDimitry Andric }
2163e3b55780SDimitry Andric 
BuildParentMap()2164e3b55780SDimitry Andric void SymbolFileNativePDB::BuildParentMap() {
2165e3b55780SDimitry Andric   LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
2166e3b55780SDimitry Andric 
2167e3b55780SDimitry Andric   llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full;
2168e3b55780SDimitry Andric   llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward;
2169e3b55780SDimitry Andric 
2170e3b55780SDimitry Andric   struct RecordIndices {
2171e3b55780SDimitry Andric     TypeIndex forward;
2172e3b55780SDimitry Andric     TypeIndex full;
2173e3b55780SDimitry Andric   };
2174e3b55780SDimitry Andric 
2175e3b55780SDimitry Andric   llvm::StringMap<RecordIndices> record_indices;
2176e3b55780SDimitry Andric 
2177e3b55780SDimitry Andric   for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
2178e3b55780SDimitry Andric     CVType type = types.getType(*ti);
2179e3b55780SDimitry Andric     if (!IsTagRecord(type))
2180e3b55780SDimitry Andric       continue;
2181e3b55780SDimitry Andric 
2182e3b55780SDimitry Andric     CVTagRecord tag = CVTagRecord::create(type);
2183e3b55780SDimitry Andric 
2184e3b55780SDimitry Andric     RecordIndices &indices = record_indices[tag.asTag().getUniqueName()];
2185e3b55780SDimitry Andric     if (tag.asTag().isForwardRef())
2186e3b55780SDimitry Andric       indices.forward = *ti;
2187e3b55780SDimitry Andric     else
2188e3b55780SDimitry Andric       indices.full = *ti;
2189e3b55780SDimitry Andric 
2190e3b55780SDimitry Andric     if (indices.full != TypeIndex::None() &&
2191e3b55780SDimitry Andric         indices.forward != TypeIndex::None()) {
2192e3b55780SDimitry Andric       forward_to_full[indices.forward] = indices.full;
2193e3b55780SDimitry Andric       full_to_forward[indices.full] = indices.forward;
2194e3b55780SDimitry Andric     }
2195e3b55780SDimitry Andric 
2196e3b55780SDimitry Andric     // We're looking for LF_NESTTYPE records in the field list, so ignore
2197e3b55780SDimitry Andric     // forward references (no field list), and anything without a nested class
2198e3b55780SDimitry Andric     // (since there won't be any LF_NESTTYPE records).
2199e3b55780SDimitry Andric     if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass())
2200e3b55780SDimitry Andric       continue;
2201e3b55780SDimitry Andric 
2202e3b55780SDimitry Andric     struct ProcessTpiStream : public TypeVisitorCallbacks {
2203e3b55780SDimitry Andric       ProcessTpiStream(PdbIndex &index, TypeIndex parent,
2204e3b55780SDimitry Andric                        const CVTagRecord &parent_cvt,
2205e3b55780SDimitry Andric                        llvm::DenseMap<TypeIndex, TypeIndex> &parents)
2206e3b55780SDimitry Andric           : index(index), parents(parents), parent(parent),
2207e3b55780SDimitry Andric             parent_cvt(parent_cvt) {}
2208e3b55780SDimitry Andric 
2209e3b55780SDimitry Andric       PdbIndex &index;
2210e3b55780SDimitry Andric       llvm::DenseMap<TypeIndex, TypeIndex> &parents;
2211e3b55780SDimitry Andric 
2212e3b55780SDimitry Andric       unsigned unnamed_type_index = 1;
2213e3b55780SDimitry Andric       TypeIndex parent;
2214e3b55780SDimitry Andric       const CVTagRecord &parent_cvt;
2215e3b55780SDimitry Andric 
2216e3b55780SDimitry Andric       llvm::Error visitKnownMember(CVMemberRecord &CVR,
2217e3b55780SDimitry Andric                                    NestedTypeRecord &Record) override {
2218e3b55780SDimitry Andric         std::string unnamed_type_name;
2219e3b55780SDimitry Andric         if (Record.Name.empty()) {
2220e3b55780SDimitry Andric           unnamed_type_name =
2221e3b55780SDimitry Andric               llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str();
2222e3b55780SDimitry Andric           Record.Name = unnamed_type_name;
2223e3b55780SDimitry Andric           ++unnamed_type_index;
2224e3b55780SDimitry Andric         }
2225e3b55780SDimitry Andric         std::optional<CVTagRecord> tag =
2226e3b55780SDimitry Andric             GetNestedTagDefinition(Record, parent_cvt, index.tpi());
2227e3b55780SDimitry Andric         if (!tag)
2228e3b55780SDimitry Andric           return llvm::ErrorSuccess();
2229e3b55780SDimitry Andric 
2230e3b55780SDimitry Andric         parents[Record.Type] = parent;
2231e3b55780SDimitry Andric         return llvm::ErrorSuccess();
2232e3b55780SDimitry Andric       }
2233e3b55780SDimitry Andric     };
2234e3b55780SDimitry Andric 
2235e3b55780SDimitry Andric     CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList);
2236e3b55780SDimitry Andric     ProcessTpiStream process(*m_index, *ti, tag, m_parent_types);
2237e3b55780SDimitry Andric     FieldListRecord field_list;
2238e3b55780SDimitry Andric     if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
2239e3b55780SDimitry Andric             field_list_cvt, field_list))
2240e3b55780SDimitry Andric       llvm::consumeError(std::move(error));
2241e3b55780SDimitry Andric     if (llvm::Error error = visitMemberRecordStream(field_list.Data, process))
2242e3b55780SDimitry Andric       llvm::consumeError(std::move(error));
2243e3b55780SDimitry Andric   }
2244e3b55780SDimitry Andric 
2245e3b55780SDimitry Andric   // Now that we know the forward -> full mapping of all type indices, we can
2246e3b55780SDimitry Andric   // re-write all the indices.  At the end of this process, we want a mapping
2247e3b55780SDimitry Andric   // consisting of fwd -> full and full -> full for all child -> parent indices.
2248e3b55780SDimitry Andric   // We can re-write the values in place, but for the keys, we must save them
2249e3b55780SDimitry Andric   // off so that we don't modify the map in place while also iterating it.
2250e3b55780SDimitry Andric   std::vector<TypeIndex> full_keys;
2251e3b55780SDimitry Andric   std::vector<TypeIndex> fwd_keys;
2252e3b55780SDimitry Andric   for (auto &entry : m_parent_types) {
2253e3b55780SDimitry Andric     TypeIndex key = entry.first;
2254e3b55780SDimitry Andric     TypeIndex value = entry.second;
2255e3b55780SDimitry Andric 
2256e3b55780SDimitry Andric     auto iter = forward_to_full.find(value);
2257e3b55780SDimitry Andric     if (iter != forward_to_full.end())
2258e3b55780SDimitry Andric       entry.second = iter->second;
2259e3b55780SDimitry Andric 
2260e3b55780SDimitry Andric     iter = forward_to_full.find(key);
2261e3b55780SDimitry Andric     if (iter != forward_to_full.end())
2262e3b55780SDimitry Andric       fwd_keys.push_back(key);
2263e3b55780SDimitry Andric     else
2264e3b55780SDimitry Andric       full_keys.push_back(key);
2265e3b55780SDimitry Andric   }
2266e3b55780SDimitry Andric   for (TypeIndex fwd : fwd_keys) {
2267e3b55780SDimitry Andric     TypeIndex full = forward_to_full[fwd];
2268aca2e42cSDimitry Andric     TypeIndex parent_idx = m_parent_types[fwd];
2269aca2e42cSDimitry Andric     m_parent_types[full] = parent_idx;
2270e3b55780SDimitry Andric   }
2271e3b55780SDimitry Andric   for (TypeIndex full : full_keys) {
2272e3b55780SDimitry Andric     TypeIndex fwd = full_to_forward[full];
2273e3b55780SDimitry Andric     m_parent_types[fwd] = m_parent_types[full];
2274e3b55780SDimitry Andric   }
2275e3b55780SDimitry Andric }
2276e3b55780SDimitry Andric 
2277e3b55780SDimitry Andric std::optional<PdbCompilandSymId>
FindSymbolScope(PdbCompilandSymId id)2278e3b55780SDimitry Andric SymbolFileNativePDB::FindSymbolScope(PdbCompilandSymId id) {
2279e3b55780SDimitry Andric   CVSymbol sym = m_index->ReadSymbolRecord(id);
2280e3b55780SDimitry Andric   if (symbolOpensScope(sym.kind())) {
2281e3b55780SDimitry Andric     // If this exact symbol opens a scope, we can just directly access its
2282e3b55780SDimitry Andric     // parent.
2283e3b55780SDimitry Andric     id.offset = getScopeParentOffset(sym);
2284e3b55780SDimitry Andric     // Global symbols have parent offset of 0.  Return std::nullopt to indicate
2285e3b55780SDimitry Andric     // this.
2286e3b55780SDimitry Andric     if (id.offset == 0)
2287e3b55780SDimitry Andric       return std::nullopt;
2288e3b55780SDimitry Andric     return id;
2289e3b55780SDimitry Andric   }
2290e3b55780SDimitry Andric 
2291e3b55780SDimitry Andric   // Otherwise we need to start at the beginning and iterate forward until we
2292e3b55780SDimitry Andric   // reach (or pass) this particular symbol
2293e3b55780SDimitry Andric   CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(id.modi);
2294e3b55780SDimitry Andric   const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
2295e3b55780SDimitry Andric 
2296e3b55780SDimitry Andric   auto begin = syms.begin();
2297e3b55780SDimitry Andric   auto end = syms.at(id.offset);
2298e3b55780SDimitry Andric   std::vector<PdbCompilandSymId> scope_stack;
2299e3b55780SDimitry Andric 
2300e3b55780SDimitry Andric   while (begin != end) {
2301e3b55780SDimitry Andric     if (begin.offset() > id.offset) {
2302e3b55780SDimitry Andric       // We passed it.  We couldn't even find this symbol record.
2303e3b55780SDimitry Andric       lldbassert(false && "Invalid compiland symbol id!");
2304e3b55780SDimitry Andric       return std::nullopt;
2305e3b55780SDimitry Andric     }
2306e3b55780SDimitry Andric 
2307e3b55780SDimitry Andric     // We haven't found the symbol yet.  Check if we need to open or close the
2308e3b55780SDimitry Andric     // scope stack.
2309e3b55780SDimitry Andric     if (symbolOpensScope(begin->kind())) {
2310e3b55780SDimitry Andric       // We can use the end offset of the scope to determine whether or not
2311e3b55780SDimitry Andric       // we can just outright skip this entire scope.
2312e3b55780SDimitry Andric       uint32_t scope_end = getScopeEndOffset(*begin);
2313e3b55780SDimitry Andric       if (scope_end < id.offset) {
2314e3b55780SDimitry Andric         begin = syms.at(scope_end);
2315e3b55780SDimitry Andric       } else {
2316e3b55780SDimitry Andric         // The symbol we're looking for is somewhere in this scope.
2317e3b55780SDimitry Andric         scope_stack.emplace_back(id.modi, begin.offset());
2318e3b55780SDimitry Andric       }
2319e3b55780SDimitry Andric     } else if (symbolEndsScope(begin->kind())) {
2320e3b55780SDimitry Andric       scope_stack.pop_back();
2321e3b55780SDimitry Andric     }
2322e3b55780SDimitry Andric     ++begin;
2323e3b55780SDimitry Andric   }
2324e3b55780SDimitry Andric   if (scope_stack.empty())
2325e3b55780SDimitry Andric     return std::nullopt;
2326e3b55780SDimitry Andric   // We have a match!  Return the top of the stack
2327e3b55780SDimitry Andric   return scope_stack.back();
2328e3b55780SDimitry Andric }
2329e3b55780SDimitry Andric 
2330e3b55780SDimitry Andric std::optional<llvm::codeview::TypeIndex>
GetParentType(llvm::codeview::TypeIndex ti)2331e3b55780SDimitry Andric SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) {
2332e3b55780SDimitry Andric   auto parent_iter = m_parent_types.find(ti);
2333e3b55780SDimitry Andric   if (parent_iter == m_parent_types.end())
2334e3b55780SDimitry Andric     return std::nullopt;
2335e3b55780SDimitry Andric   return parent_iter->second;
2336e3b55780SDimitry Andric }
2337