15ffd83dbSDimitry Andric //===-- SymbolFileNativePDB.cpp -------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "SymbolFileNativePDB.h"
100b57cec5SDimitry Andric 
115ffd83dbSDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangUtil.h"
120b57cec5SDimitry Andric #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
13e8d8bef9SDimitry Andric #include "Plugins/ObjectFile/PDB/ObjectFilePDB.h"
145ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
150b57cec5SDimitry Andric #include "lldb/Core/Module.h"
160b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h"
170b57cec5SDimitry Andric #include "lldb/Core/StreamBuffer.h"
180b57cec5SDimitry Andric #include "lldb/Core/StreamFile.h"
190b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h"
200b57cec5SDimitry Andric #include "lldb/Symbol/LineTable.h"
210b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
220b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
230b57cec5SDimitry Andric #include "lldb/Symbol/SymbolVendor.h"
240b57cec5SDimitry Andric #include "lldb/Symbol/Variable.h"
250b57cec5SDimitry Andric #include "lldb/Symbol/VariableList.h"
2681ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
279dba64beSDimitry Andric #include "lldb/Utility/Log.h"
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/CVRecord.h"
300b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
310b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
320b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
330b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/RecordName.h"
340b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
350b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
360b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
370b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
380b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
390b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
400b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
41e8d8bef9SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
420b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
430b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
440b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
45e8d8bef9SDimitry Andric #include "llvm/DebugInfo/PDB/PDB.h"
460b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBTypes.h"
470b57cec5SDimitry Andric #include "llvm/Demangle/MicrosoftDemangle.h"
480b57cec5SDimitry Andric #include "llvm/Object/COFF.h"
490b57cec5SDimitry Andric #include "llvm/Support/Allocator.h"
500b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
510b57cec5SDimitry Andric #include "llvm/Support/Error.h"
520b57cec5SDimitry Andric #include "llvm/Support/ErrorOr.h"
530b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric #include "DWARFLocationExpression.h"
560b57cec5SDimitry Andric #include "PdbSymUid.h"
570b57cec5SDimitry Andric #include "PdbUtil.h"
580b57cec5SDimitry Andric #include "UdtRecordCompleter.h"
59bdd1243dSDimitry Andric #include <optional>
6006c3fb27SDimitry Andric #include <string_view>
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric using namespace lldb;
630b57cec5SDimitry Andric using namespace lldb_private;
640b57cec5SDimitry Andric using namespace npdb;
650b57cec5SDimitry Andric using namespace llvm::codeview;
660b57cec5SDimitry Andric using namespace llvm::pdb;
670b57cec5SDimitry Andric 
68480093f4SDimitry Andric char SymbolFileNativePDB::ID;
69480093f4SDimitry Andric 
700b57cec5SDimitry Andric static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
710b57cec5SDimitry Andric   switch (lang) {
720b57cec5SDimitry Andric   case PDB_Lang::Cpp:
730b57cec5SDimitry Andric     return lldb::LanguageType::eLanguageTypeC_plus_plus;
740b57cec5SDimitry Andric   case PDB_Lang::C:
750b57cec5SDimitry Andric     return lldb::LanguageType::eLanguageTypeC;
760b57cec5SDimitry Andric   case PDB_Lang::Swift:
770b57cec5SDimitry Andric     return lldb::LanguageType::eLanguageTypeSwift;
7881ad6265SDimitry Andric   case PDB_Lang::Rust:
7981ad6265SDimitry Andric     return lldb::LanguageType::eLanguageTypeRust;
8006c3fb27SDimitry Andric   case PDB_Lang::ObjC:
8106c3fb27SDimitry Andric     return lldb::LanguageType::eLanguageTypeObjC;
8206c3fb27SDimitry Andric   case PDB_Lang::ObjCpp:
8306c3fb27SDimitry Andric     return lldb::LanguageType::eLanguageTypeObjC_plus_plus;
840b57cec5SDimitry Andric   default:
850b57cec5SDimitry Andric     return lldb::LanguageType::eLanguageTypeUnknown;
860b57cec5SDimitry Andric   }
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric static std::unique_ptr<PDBFile>
900b57cec5SDimitry Andric loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
910b57cec5SDimitry Andric   // Try to find a matching PDB for an EXE.
920b57cec5SDimitry Andric   using namespace llvm::object;
930b57cec5SDimitry Andric   auto expected_binary = createBinary(exe_path);
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // If the file isn't a PE/COFF executable, fail.
960b57cec5SDimitry Andric   if (!expected_binary) {
970b57cec5SDimitry Andric     llvm::consumeError(expected_binary.takeError());
980b57cec5SDimitry Andric     return nullptr;
990b57cec5SDimitry Andric   }
1000b57cec5SDimitry Andric   OwningBinary<Binary> binary = std::move(*expected_binary);
1010b57cec5SDimitry Andric 
1029dba64beSDimitry Andric   // TODO: Avoid opening the PE/COFF binary twice by reading this information
1039dba64beSDimitry Andric   // directly from the lldb_private::ObjectFile.
1040b57cec5SDimitry Andric   auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary());
1050b57cec5SDimitry Andric   if (!obj)
1060b57cec5SDimitry Andric     return nullptr;
1070b57cec5SDimitry Andric   const llvm::codeview::DebugInfo *pdb_info = nullptr;
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   // If it doesn't have a debug directory, fail.
1100b57cec5SDimitry Andric   llvm::StringRef pdb_file;
1115ffd83dbSDimitry Andric   if (llvm::Error e = obj->getDebugPDBInfo(pdb_info, pdb_file)) {
1125ffd83dbSDimitry Andric     consumeError(std::move(e));
1130b57cec5SDimitry Andric     return nullptr;
1145ffd83dbSDimitry Andric   }
1150b57cec5SDimitry Andric 
116e8d8bef9SDimitry Andric   // If the file doesn't exist, perhaps the path specified at build time
117e8d8bef9SDimitry Andric   // doesn't match the PDB's current location, so check the location of the
118e8d8bef9SDimitry Andric   // executable.
119e8d8bef9SDimitry Andric   if (!FileSystem::Instance().Exists(pdb_file)) {
120e8d8bef9SDimitry Andric     const auto exe_dir = FileSpec(exe_path).CopyByRemovingLastPathComponent();
121e8d8bef9SDimitry Andric     const auto pdb_name = FileSpec(pdb_file).GetFilename().GetCString();
122bdd1243dSDimitry Andric     pdb_file = exe_dir.CopyByAppendingPathComponent(pdb_name).GetPathAsConstString().GetStringRef();
123e8d8bef9SDimitry Andric   }
124e8d8bef9SDimitry Andric 
125e8d8bef9SDimitry Andric   // If the file is not a PDB or if it doesn't have a matching GUID, fail.
126e8d8bef9SDimitry Andric   auto pdb = ObjectFilePDB::loadPDBFile(std::string(pdb_file), allocator);
1270b57cec5SDimitry Andric   if (!pdb)
1280b57cec5SDimitry Andric     return nullptr;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   auto expected_info = pdb->getPDBInfoStream();
1310b57cec5SDimitry Andric   if (!expected_info) {
1320b57cec5SDimitry Andric     llvm::consumeError(expected_info.takeError());
1330b57cec5SDimitry Andric     return nullptr;
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric   llvm::codeview::GUID guid;
1360b57cec5SDimitry Andric   memcpy(&guid, pdb_info->PDB70.Signature, 16);
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   if (expected_info->getGuid() != guid)
1390b57cec5SDimitry Andric     return nullptr;
1400b57cec5SDimitry Andric   return pdb;
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric static bool IsFunctionPrologue(const CompilandIndexItem &cci,
1440b57cec5SDimitry Andric                                lldb::addr_t addr) {
1450b57cec5SDimitry Andric   // FIXME: Implement this.
1460b57cec5SDimitry Andric   return false;
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric static bool IsFunctionEpilogue(const CompilandIndexItem &cci,
1500b57cec5SDimitry Andric                                lldb::addr_t addr) {
1510b57cec5SDimitry Andric   // FIXME: Implement this.
1520b57cec5SDimitry Andric   return false;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) {
1560b57cec5SDimitry Andric   switch (kind) {
1570b57cec5SDimitry Andric   case SimpleTypeKind::Boolean128:
1580b57cec5SDimitry Andric   case SimpleTypeKind::Boolean16:
1590b57cec5SDimitry Andric   case SimpleTypeKind::Boolean32:
1600b57cec5SDimitry Andric   case SimpleTypeKind::Boolean64:
1610b57cec5SDimitry Andric   case SimpleTypeKind::Boolean8:
1620b57cec5SDimitry Andric     return "bool";
1630b57cec5SDimitry Andric   case SimpleTypeKind::Byte:
1640b57cec5SDimitry Andric   case SimpleTypeKind::UnsignedCharacter:
1650b57cec5SDimitry Andric     return "unsigned char";
1660b57cec5SDimitry Andric   case SimpleTypeKind::NarrowCharacter:
1670b57cec5SDimitry Andric     return "char";
1680b57cec5SDimitry Andric   case SimpleTypeKind::SignedCharacter:
1690b57cec5SDimitry Andric   case SimpleTypeKind::SByte:
1700b57cec5SDimitry Andric     return "signed char";
1710b57cec5SDimitry Andric   case SimpleTypeKind::Character16:
1720b57cec5SDimitry Andric     return "char16_t";
1730b57cec5SDimitry Andric   case SimpleTypeKind::Character32:
1740b57cec5SDimitry Andric     return "char32_t";
17581ad6265SDimitry Andric   case SimpleTypeKind::Character8:
17681ad6265SDimitry Andric     return "char8_t";
1770b57cec5SDimitry Andric   case SimpleTypeKind::Complex80:
1780b57cec5SDimitry Andric   case SimpleTypeKind::Complex64:
1790b57cec5SDimitry Andric   case SimpleTypeKind::Complex32:
1800b57cec5SDimitry Andric     return "complex";
1810b57cec5SDimitry Andric   case SimpleTypeKind::Float128:
1820b57cec5SDimitry Andric   case SimpleTypeKind::Float80:
1830b57cec5SDimitry Andric     return "long double";
1840b57cec5SDimitry Andric   case SimpleTypeKind::Float64:
1850b57cec5SDimitry Andric     return "double";
1860b57cec5SDimitry Andric   case SimpleTypeKind::Float32:
1870b57cec5SDimitry Andric     return "float";
1880b57cec5SDimitry Andric   case SimpleTypeKind::Float16:
1890b57cec5SDimitry Andric     return "single";
1900b57cec5SDimitry Andric   case SimpleTypeKind::Int128:
1910b57cec5SDimitry Andric     return "__int128";
1920b57cec5SDimitry Andric   case SimpleTypeKind::Int64:
1930b57cec5SDimitry Andric   case SimpleTypeKind::Int64Quad:
1940b57cec5SDimitry Andric     return "int64_t";
1950b57cec5SDimitry Andric   case SimpleTypeKind::Int32:
1960b57cec5SDimitry Andric     return "int";
1970b57cec5SDimitry Andric   case SimpleTypeKind::Int16:
1980b57cec5SDimitry Andric     return "short";
1990b57cec5SDimitry Andric   case SimpleTypeKind::UInt128:
2000b57cec5SDimitry Andric     return "unsigned __int128";
2010b57cec5SDimitry Andric   case SimpleTypeKind::UInt64:
2020b57cec5SDimitry Andric   case SimpleTypeKind::UInt64Quad:
2030b57cec5SDimitry Andric     return "uint64_t";
2040b57cec5SDimitry Andric   case SimpleTypeKind::HResult:
2050b57cec5SDimitry Andric     return "HRESULT";
2060b57cec5SDimitry Andric   case SimpleTypeKind::UInt32:
2070b57cec5SDimitry Andric     return "unsigned";
2080b57cec5SDimitry Andric   case SimpleTypeKind::UInt16:
2090b57cec5SDimitry Andric   case SimpleTypeKind::UInt16Short:
2100b57cec5SDimitry Andric     return "unsigned short";
2110b57cec5SDimitry Andric   case SimpleTypeKind::Int32Long:
2120b57cec5SDimitry Andric     return "long";
2130b57cec5SDimitry Andric   case SimpleTypeKind::UInt32Long:
2140b57cec5SDimitry Andric     return "unsigned long";
2150b57cec5SDimitry Andric   case SimpleTypeKind::Void:
2160b57cec5SDimitry Andric     return "void";
2170b57cec5SDimitry Andric   case SimpleTypeKind::WideCharacter:
2180b57cec5SDimitry Andric     return "wchar_t";
2190b57cec5SDimitry Andric   default:
2200b57cec5SDimitry Andric     return "";
2210b57cec5SDimitry Andric   }
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric static bool IsClassRecord(TypeLeafKind kind) {
2250b57cec5SDimitry Andric   switch (kind) {
2260b57cec5SDimitry Andric   case LF_STRUCTURE:
2270b57cec5SDimitry Andric   case LF_CLASS:
2280b57cec5SDimitry Andric   case LF_INTERFACE:
2290b57cec5SDimitry Andric     return true;
2300b57cec5SDimitry Andric   default:
2310b57cec5SDimitry Andric     return false;
2320b57cec5SDimitry Andric   }
2330b57cec5SDimitry Andric }
2340b57cec5SDimitry Andric 
235bdd1243dSDimitry Andric static std::optional<CVTagRecord>
236bdd1243dSDimitry Andric GetNestedTagDefinition(const NestedTypeRecord &Record,
237bdd1243dSDimitry Andric                        const CVTagRecord &parent, TpiStream &tpi) {
238bdd1243dSDimitry Andric   // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it
239bdd1243dSDimitry Andric   // is also used to indicate the primary definition of a nested class.  That is
240bdd1243dSDimitry Andric   // to say, if you have:
241bdd1243dSDimitry Andric   // struct A {
242bdd1243dSDimitry Andric   //   struct B {};
243bdd1243dSDimitry Andric   //   using C = B;
244bdd1243dSDimitry Andric   // };
245bdd1243dSDimitry Andric   // Then in the debug info, this will appear as:
246bdd1243dSDimitry Andric   // LF_STRUCTURE `A::B` [type index = N]
247bdd1243dSDimitry Andric   // LF_STRUCTURE `A`
248bdd1243dSDimitry Andric   //   LF_NESTTYPE [name = `B`, index = N]
249bdd1243dSDimitry Andric   //   LF_NESTTYPE [name = `C`, index = N]
250bdd1243dSDimitry Andric   // In order to accurately reconstruct the decl context hierarchy, we need to
251bdd1243dSDimitry Andric   // know which ones are actual definitions and which ones are just aliases.
252bdd1243dSDimitry Andric 
253bdd1243dSDimitry Andric   // If it's a simple type, then this is something like `using foo = int`.
254bdd1243dSDimitry Andric   if (Record.Type.isSimple())
255bdd1243dSDimitry Andric     return std::nullopt;
256bdd1243dSDimitry Andric 
257bdd1243dSDimitry Andric   CVType cvt = tpi.getType(Record.Type);
258bdd1243dSDimitry Andric 
259bdd1243dSDimitry Andric   if (!IsTagRecord(cvt))
260bdd1243dSDimitry Andric     return std::nullopt;
261bdd1243dSDimitry Andric 
262bdd1243dSDimitry Andric   // If it's an inner definition, then treat whatever name we have here as a
263bdd1243dSDimitry Andric   // single component of a mangled name.  So we can inject it into the parent's
264bdd1243dSDimitry Andric   // mangled name to see if it matches.
265bdd1243dSDimitry Andric   CVTagRecord child = CVTagRecord::create(cvt);
266bdd1243dSDimitry Andric   std::string qname = std::string(parent.asTag().getUniqueName());
267bdd1243dSDimitry Andric   if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4)
268bdd1243dSDimitry Andric     return std::nullopt;
269bdd1243dSDimitry Andric 
270bdd1243dSDimitry Andric   // qname[3] is the tag type identifier (struct, class, union, etc).  Since the
271bdd1243dSDimitry Andric   // inner tag type is not necessarily the same as the outer tag type, re-write
272bdd1243dSDimitry Andric   // it to match the inner tag type.
273bdd1243dSDimitry Andric   qname[3] = child.asTag().getUniqueName()[3];
274bdd1243dSDimitry Andric   std::string piece;
275bdd1243dSDimitry Andric   if (qname[3] == 'W')
276bdd1243dSDimitry Andric     piece = "4";
277bdd1243dSDimitry Andric   piece += Record.Name;
278bdd1243dSDimitry Andric   piece.push_back('@');
279bdd1243dSDimitry Andric   qname.insert(4, std::move(piece));
280bdd1243dSDimitry Andric   if (qname != child.asTag().UniqueName)
281bdd1243dSDimitry Andric     return std::nullopt;
282bdd1243dSDimitry Andric 
283bdd1243dSDimitry Andric   return std::move(child);
284bdd1243dSDimitry Andric }
285bdd1243dSDimitry Andric 
2860b57cec5SDimitry Andric void SymbolFileNativePDB::Initialize() {
2870b57cec5SDimitry Andric   PluginManager::RegisterPlugin(GetPluginNameStatic(),
2880b57cec5SDimitry Andric                                 GetPluginDescriptionStatic(), CreateInstance,
2890b57cec5SDimitry Andric                                 DebuggerInitialize);
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric void SymbolFileNativePDB::Terminate() {
2930b57cec5SDimitry Andric   PluginManager::UnregisterPlugin(CreateInstance);
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric void SymbolFileNativePDB::DebuggerInitialize(Debugger &debugger) {}
2970b57cec5SDimitry Andric 
298349cc55cSDimitry Andric llvm::StringRef SymbolFileNativePDB::GetPluginDescriptionStatic() {
2990b57cec5SDimitry Andric   return "Microsoft PDB debug symbol cross-platform file reader.";
3000b57cec5SDimitry Andric }
3010b57cec5SDimitry Andric 
3029dba64beSDimitry Andric SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFileSP objfile_sp) {
3039dba64beSDimitry Andric   return new SymbolFileNativePDB(std::move(objfile_sp));
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric 
3069dba64beSDimitry Andric SymbolFileNativePDB::SymbolFileNativePDB(ObjectFileSP objfile_sp)
30781ad6265SDimitry Andric     : SymbolFileCommon(std::move(objfile_sp)) {}
3080b57cec5SDimitry Andric 
309fe6060f1SDimitry Andric SymbolFileNativePDB::~SymbolFileNativePDB() = default;
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric uint32_t SymbolFileNativePDB::CalculateAbilities() {
3120b57cec5SDimitry Andric   uint32_t abilities = 0;
3139dba64beSDimitry Andric   if (!m_objfile_sp)
3140b57cec5SDimitry Andric     return 0;
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric   if (!m_index) {
3170b57cec5SDimitry Andric     // Lazily load and match the PDB file, but only do this once.
318e8d8bef9SDimitry Andric     PDBFile *pdb_file;
319e8d8bef9SDimitry Andric     if (auto *pdb = llvm::dyn_cast<ObjectFilePDB>(m_objfile_sp.get())) {
320e8d8bef9SDimitry Andric       pdb_file = &pdb->GetPDBFile();
321e8d8bef9SDimitry Andric     } else {
322e8d8bef9SDimitry Andric       m_file_up = loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(),
323e8d8bef9SDimitry Andric                                       m_allocator);
324e8d8bef9SDimitry Andric       pdb_file = m_file_up.get();
3250b57cec5SDimitry Andric     }
3260b57cec5SDimitry Andric 
327e8d8bef9SDimitry Andric     if (!pdb_file)
3280b57cec5SDimitry Andric       return 0;
3290b57cec5SDimitry Andric 
330e8d8bef9SDimitry Andric     auto expected_index = PdbIndex::create(pdb_file);
3310b57cec5SDimitry Andric     if (!expected_index) {
3320b57cec5SDimitry Andric       llvm::consumeError(expected_index.takeError());
3330b57cec5SDimitry Andric       return 0;
3340b57cec5SDimitry Andric     }
3350b57cec5SDimitry Andric     m_index = std::move(*expected_index);
3360b57cec5SDimitry Andric   }
3370b57cec5SDimitry Andric   if (!m_index)
3380b57cec5SDimitry Andric     return 0;
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   // We don't especially have to be precise here.  We only distinguish between
3410b57cec5SDimitry Andric   // stripped and not stripped.
3420b57cec5SDimitry Andric   abilities = kAllAbilities;
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   if (m_index->dbi().isStripped())
3450b57cec5SDimitry Andric     abilities &= ~(Blocks | LocalVariables);
3460b57cec5SDimitry Andric   return abilities;
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric void SymbolFileNativePDB::InitializeObject() {
350e8d8bef9SDimitry Andric   m_obj_load_address = m_objfile_sp->GetModule()
351e8d8bef9SDimitry Andric                            ->GetObjectFile()
352e8d8bef9SDimitry Andric                            ->GetBaseAddress()
353e8d8bef9SDimitry Andric                            .GetFileAddress();
3540b57cec5SDimitry Andric   m_index->SetLoadAddress(m_obj_load_address);
3550b57cec5SDimitry Andric   m_index->ParseSectionContribs();
3560b57cec5SDimitry Andric 
3579dba64beSDimitry Andric   auto ts_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage(
3580b57cec5SDimitry Andric       lldb::eLanguageTypeC_plus_plus);
3599dba64beSDimitry Andric   if (auto err = ts_or_err.takeError()) {
36081ad6265SDimitry Andric     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
36106c3fb27SDimitry Andric                    "Failed to initialize: {0}");
3629dba64beSDimitry Andric   } else {
363bdd1243dSDimitry Andric     if (auto ts = *ts_or_err)
364bdd1243dSDimitry Andric       ts->SetSymbolFile(this);
365bdd1243dSDimitry Andric     BuildParentMap();
3669dba64beSDimitry Andric   }
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric 
3699dba64beSDimitry Andric uint32_t SymbolFileNativePDB::CalculateNumCompileUnits() {
3700b57cec5SDimitry Andric   const DbiModuleList &modules = m_index->dbi().modules();
3710b57cec5SDimitry Andric   uint32_t count = modules.getModuleCount();
3720b57cec5SDimitry Andric   if (count == 0)
3730b57cec5SDimitry Andric     return count;
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   // The linker can inject an additional "dummy" compilation unit into the
3760b57cec5SDimitry Andric   // PDB. Ignore this special compile unit for our purposes, if it is there.
3770b57cec5SDimitry Andric   // It is always the last one.
3780b57cec5SDimitry Andric   DbiModuleDescriptor last = modules.getModuleDescriptor(count - 1);
3790b57cec5SDimitry Andric   if (last.getModuleName() == "* Linker *")
3800b57cec5SDimitry Andric     --count;
3810b57cec5SDimitry Andric   return count;
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
3850b57cec5SDimitry Andric   CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
3860b57cec5SDimitry Andric   CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
3870b57cec5SDimitry Andric   CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
38804eeddc0SDimitry Andric   lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id);
38904eeddc0SDimitry Andric   BlockSP child_block = std::make_shared<Block>(opaque_block_uid);
390bdd1243dSDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
391bdd1243dSDimitry Andric   if (auto err = ts_or_err.takeError())
392bdd1243dSDimitry Andric     return *child_block;
393bdd1243dSDimitry Andric   auto ts = *ts_or_err;
394bdd1243dSDimitry Andric   if (!ts)
395bdd1243dSDimitry Andric     return *child_block;
396bdd1243dSDimitry Andric   PdbAstBuilder* ast_builder = ts->GetNativePDBParser();
39704eeddc0SDimitry Andric 
39804eeddc0SDimitry Andric   switch (sym.kind()) {
39904eeddc0SDimitry Andric   case S_GPROC32:
40004eeddc0SDimitry Andric   case S_LPROC32: {
40104eeddc0SDimitry Andric     // This is a function.  It must be global.  Creating the Function entry
40204eeddc0SDimitry Andric     // for it automatically creates a block for it.
40304eeddc0SDimitry Andric     FunctionSP func = GetOrCreateFunction(block_id, *comp_unit);
404bdd1243dSDimitry Andric     if (func) {
40504eeddc0SDimitry Andric       Block &block = func->GetBlock(false);
40604eeddc0SDimitry Andric       if (block.GetNumRanges() == 0)
40704eeddc0SDimitry Andric         block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize()));
40804eeddc0SDimitry Andric       return block;
4090b57cec5SDimitry Andric     }
410bdd1243dSDimitry Andric     break;
411bdd1243dSDimitry Andric   }
41204eeddc0SDimitry Andric   case S_BLOCK32: {
4130b57cec5SDimitry Andric     // This is a block.  Its parent is either a function or another block.  In
41404eeddc0SDimitry Andric     // either case, its parent can be viewed as a block (e.g. a function
41504eeddc0SDimitry Andric     // contains 1 big block.  So just get the parent block and add this block
41604eeddc0SDimitry Andric     // to it.
4170b57cec5SDimitry Andric     BlockSym block(static_cast<SymbolRecordKind>(sym.kind()));
4180b57cec5SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<BlockSym>(sym, block));
4190b57cec5SDimitry Andric     lldbassert(block.Parent != 0);
4200b57cec5SDimitry Andric     PdbCompilandSymId parent_id(block_id.modi, block.Parent);
4210b57cec5SDimitry Andric     Block &parent_block = GetOrCreateBlock(parent_id);
422bdd1243dSDimitry Andric     Function *func = parent_block.CalculateSymbolContextFunction();
423bdd1243dSDimitry Andric     lldbassert(func);
424bdd1243dSDimitry Andric     lldb::addr_t block_base =
425bdd1243dSDimitry Andric         m_index->MakeVirtualAddress(block.Segment, block.CodeOffset);
426bdd1243dSDimitry Andric     lldb::addr_t func_base =
427bdd1243dSDimitry Andric         func->GetAddressRange().GetBaseAddress().GetFileAddress();
428bdd1243dSDimitry Andric     if (block_base >= func_base)
429bdd1243dSDimitry Andric       child_block->AddRange(Block::Range(block_base - func_base, block.CodeSize));
430bdd1243dSDimitry Andric     else {
431bdd1243dSDimitry Andric       GetObjectFile()->GetModule()->ReportError(
432bdd1243dSDimitry Andric           "S_BLOCK32 at modi: {0:d} offset: {1:d}: adding range "
433bdd1243dSDimitry Andric           "[{2:x16}-{3:x16}) which has a base that is less than the "
434bdd1243dSDimitry Andric           "function's "
435bdd1243dSDimitry Andric           "low PC 0x%" PRIx64 ". Please file a bug and attach the file at the "
436bdd1243dSDimitry Andric           "start of this error message",
437bdd1243dSDimitry Andric           block_id.modi, block_id.offset, block_base,
438bdd1243dSDimitry Andric           block_base + block.CodeSize, func_base);
439bdd1243dSDimitry Andric     }
44004eeddc0SDimitry Andric     parent_block.AddChild(child_block);
441bdd1243dSDimitry Andric     ast_builder->GetOrCreateBlockDecl(block_id);
44204eeddc0SDimitry Andric     m_blocks.insert({opaque_block_uid, child_block});
44304eeddc0SDimitry Andric     break;
44404eeddc0SDimitry Andric   }
44504eeddc0SDimitry Andric   case S_INLINESITE: {
44604eeddc0SDimitry Andric     // This ensures line table is parsed first so we have inline sites info.
44704eeddc0SDimitry Andric     comp_unit->GetLineTable();
44804eeddc0SDimitry Andric 
44904eeddc0SDimitry Andric     std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid];
45004eeddc0SDimitry Andric     Block &parent_block = GetOrCreateBlock(inline_site->parent_id);
4510b57cec5SDimitry Andric     parent_block.AddChild(child_block);
452bdd1243dSDimitry Andric     ast_builder->GetOrCreateInlinedFunctionDecl(block_id);
45304eeddc0SDimitry Andric     // Copy ranges from InlineSite to Block.
45404eeddc0SDimitry Andric     for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) {
45504eeddc0SDimitry Andric       auto *entry = inline_site->ranges.GetEntryAtIndex(i);
45604eeddc0SDimitry Andric       child_block->AddRange(
45704eeddc0SDimitry Andric           Block::Range(entry->GetRangeBase(), entry->GetByteSize()));
45804eeddc0SDimitry Andric     }
45904eeddc0SDimitry Andric     child_block->FinalizeRanges();
4600b57cec5SDimitry Andric 
46104eeddc0SDimitry Andric     // Get the inlined function callsite info.
46204eeddc0SDimitry Andric     Declaration &decl = inline_site->inline_function_info->GetDeclaration();
46304eeddc0SDimitry Andric     Declaration &callsite = inline_site->inline_function_info->GetCallSite();
46404eeddc0SDimitry Andric     child_block->SetInlinedFunctionInfo(
46504eeddc0SDimitry Andric         inline_site->inline_function_info->GetName().GetCString(), nullptr,
46604eeddc0SDimitry Andric         &decl, &callsite);
4670b57cec5SDimitry Andric     m_blocks.insert({opaque_block_uid, child_block});
46804eeddc0SDimitry Andric     break;
46904eeddc0SDimitry Andric   }
47004eeddc0SDimitry Andric   default:
47104eeddc0SDimitry Andric     lldbassert(false && "Symbol is not a block!");
47204eeddc0SDimitry Andric   }
47304eeddc0SDimitry Andric 
4740b57cec5SDimitry Andric   return *child_block;
4750b57cec5SDimitry Andric }
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
4780b57cec5SDimitry Andric                                                      CompileUnit &comp_unit) {
4790b57cec5SDimitry Andric   const CompilandIndexItem *cci =
4800b57cec5SDimitry Andric       m_index->compilands().GetCompiland(func_id.modi);
4810b57cec5SDimitry Andric   lldbassert(cci);
4820b57cec5SDimitry Andric   CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric   lldbassert(sym_record.kind() == S_LPROC32 || sym_record.kind() == S_GPROC32);
4850b57cec5SDimitry Andric   SegmentOffsetLength sol = GetSegmentOffsetAndLength(sym_record);
4860b57cec5SDimitry Andric 
48781ad6265SDimitry Andric   auto file_vm_addr =
48881ad6265SDimitry Andric       m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);
4890b57cec5SDimitry Andric   if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
4900b57cec5SDimitry Andric     return nullptr;
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric   AddressRange func_range(file_vm_addr, sol.length,
4930b57cec5SDimitry Andric                           comp_unit.GetModule()->GetSectionList());
4940b57cec5SDimitry Andric   if (!func_range.GetBaseAddress().IsValid())
4950b57cec5SDimitry Andric     return nullptr;
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
4980b57cec5SDimitry Andric   cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));
4990b57cec5SDimitry Andric   if (proc.FunctionType == TypeIndex::None())
5000b57cec5SDimitry Andric     return nullptr;
5010b57cec5SDimitry Andric   TypeSP func_type = GetOrCreateType(proc.FunctionType);
5020b57cec5SDimitry Andric   if (!func_type)
5030b57cec5SDimitry Andric     return nullptr;
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric   PdbTypeSymId sig_id(proc.FunctionType, false);
5060b57cec5SDimitry Andric   Mangled mangled(proc.Name);
5070b57cec5SDimitry Andric   FunctionSP func_sp = std::make_shared<Function>(
5080b57cec5SDimitry Andric       &comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled,
5090b57cec5SDimitry Andric       func_type.get(), func_range);
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric   comp_unit.AddFunction(func_sp);
5120b57cec5SDimitry Andric 
513bdd1243dSDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(comp_unit.GetLanguage());
514bdd1243dSDimitry Andric   if (auto err = ts_or_err.takeError())
515bdd1243dSDimitry Andric     return func_sp;
516bdd1243dSDimitry Andric   auto ts = *ts_or_err;
517bdd1243dSDimitry Andric   if (!ts)
518bdd1243dSDimitry Andric     return func_sp;
519bdd1243dSDimitry Andric   ts->GetNativePDBParser()->GetOrCreateFunctionDecl(func_id);
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric   return func_sp;
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric CompUnitSP
5250b57cec5SDimitry Andric SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) {
5260b57cec5SDimitry Andric   lldb::LanguageType lang =
5270b57cec5SDimitry Andric       cci.m_compile_opts ? TranslateLanguage(cci.m_compile_opts->getLanguage())
5280b57cec5SDimitry Andric                          : lldb::eLanguageTypeUnknown;
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   LazyBool optimized = eLazyBoolNo;
5310b57cec5SDimitry Andric   if (cci.m_compile_opts && cci.m_compile_opts->hasOptimizations())
5320b57cec5SDimitry Andric     optimized = eLazyBoolYes;
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric   llvm::SmallString<64> source_file_name =
5350b57cec5SDimitry Andric       m_index->compilands().GetMainSourceFile(cci);
53681ad6265SDimitry Andric   FileSpec fs(llvm::sys::path::convert_to_slash(
53781ad6265SDimitry Andric       source_file_name, llvm::sys::path::Style::windows_backslash));
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   CompUnitSP cu_sp =
5409dba64beSDimitry Andric       std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), nullptr, fs,
5410b57cec5SDimitry Andric                                     toOpaqueUid(cci.m_id), lang, optimized);
5420b57cec5SDimitry Andric 
5439dba64beSDimitry Andric   SetCompileUnitAtIndex(cci.m_id.modi, cu_sp);
5440b57cec5SDimitry Andric   return cu_sp;
5450b57cec5SDimitry Andric }
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id,
5480b57cec5SDimitry Andric                                                      const ModifierRecord &mr,
5490b57cec5SDimitry Andric                                                      CompilerType ct) {
5500b57cec5SDimitry Andric   TpiStream &stream = m_index->tpi();
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   std::string name;
5530b57cec5SDimitry Andric   if (mr.ModifiedType.isSimple())
5545ffd83dbSDimitry Andric     name = std::string(GetSimpleTypeName(mr.ModifiedType.getSimpleKind()));
5550b57cec5SDimitry Andric   else
5560b57cec5SDimitry Andric     name = computeTypeName(stream.typeCollection(), mr.ModifiedType);
5570b57cec5SDimitry Andric   Declaration decl;
5580b57cec5SDimitry Andric   lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType);
5590b57cec5SDimitry Andric 
560bdd1243dSDimitry Andric   return MakeType(toOpaqueUid(type_id), ConstString(name),
561e8d8bef9SDimitry Andric                   modified_type->GetByteSize(nullptr), nullptr,
562bdd1243dSDimitry Andric                   LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
563bdd1243dSDimitry Andric                   Type::ResolveState::Full);
5640b57cec5SDimitry Andric }
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric lldb::TypeSP
5670b57cec5SDimitry Andric SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id,
5680b57cec5SDimitry Andric                                        const llvm::codeview::PointerRecord &pr,
5690b57cec5SDimitry Andric                                        CompilerType ct) {
5700b57cec5SDimitry Andric   TypeSP pointee = GetOrCreateType(pr.ReferentType);
5710b57cec5SDimitry Andric   if (!pointee)
5720b57cec5SDimitry Andric     return nullptr;
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   if (pr.isPointerToMember()) {
5750b57cec5SDimitry Andric     MemberPointerInfo mpi = pr.getMemberInfo();
5760b57cec5SDimitry Andric     GetOrCreateType(mpi.ContainingType);
5770b57cec5SDimitry Andric   }
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric   Declaration decl;
580bdd1243dSDimitry Andric   return MakeType(toOpaqueUid(type_id), ConstString(), pr.getSize(), nullptr,
581bdd1243dSDimitry Andric                   LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
582480093f4SDimitry Andric                   Type::ResolveState::Full);
5830b57cec5SDimitry Andric }
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
5860b57cec5SDimitry Andric                                                    CompilerType ct) {
5870b57cec5SDimitry Andric   uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false));
5880b57cec5SDimitry Andric   if (ti == TypeIndex::NullptrT()) {
5890b57cec5SDimitry Andric     Declaration decl;
590bdd1243dSDimitry Andric     return MakeType(uid, ConstString("std::nullptr_t"), 0, nullptr,
591bdd1243dSDimitry Andric                     LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
592bdd1243dSDimitry Andric                     Type::ResolveState::Full);
5930b57cec5SDimitry Andric   }
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
5960b57cec5SDimitry Andric     TypeSP direct_sp = GetOrCreateType(ti.makeDirect());
5970b57cec5SDimitry Andric     uint32_t pointer_size = 0;
5980b57cec5SDimitry Andric     switch (ti.getSimpleMode()) {
5990b57cec5SDimitry Andric     case SimpleTypeMode::FarPointer32:
6000b57cec5SDimitry Andric     case SimpleTypeMode::NearPointer32:
6010b57cec5SDimitry Andric       pointer_size = 4;
6020b57cec5SDimitry Andric       break;
6030b57cec5SDimitry Andric     case SimpleTypeMode::NearPointer64:
6040b57cec5SDimitry Andric       pointer_size = 8;
6050b57cec5SDimitry Andric       break;
6060b57cec5SDimitry Andric     default:
6070b57cec5SDimitry Andric       // 128-bit and 16-bit pointers unsupported.
6080b57cec5SDimitry Andric       return nullptr;
6090b57cec5SDimitry Andric     }
6100b57cec5SDimitry Andric     Declaration decl;
611bdd1243dSDimitry Andric     return MakeType(uid, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,
612480093f4SDimitry Andric                     Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
6130b57cec5SDimitry Andric   }
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric   if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
6160b57cec5SDimitry Andric     return nullptr;
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric   size_t size = GetTypeSizeForSimpleKind(ti.getSimpleKind());
6190b57cec5SDimitry Andric   llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind());
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric   Declaration decl;
622bdd1243dSDimitry Andric   return MakeType(uid, ConstString(type_name), size, nullptr, LLDB_INVALID_UID,
623bdd1243dSDimitry Andric                   Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
6240b57cec5SDimitry Andric }
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric static std::string GetUnqualifiedTypeName(const TagRecord &record) {
6270b57cec5SDimitry Andric   if (!record.hasUniqueName()) {
6280b57cec5SDimitry Andric     MSVCUndecoratedNameParser parser(record.Name);
6290b57cec5SDimitry Andric     llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
6300b57cec5SDimitry Andric 
6315ffd83dbSDimitry Andric     return std::string(specs.back().GetBaseName());
6320b57cec5SDimitry Andric   }
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric   llvm::ms_demangle::Demangler demangler;
63506c3fb27SDimitry Andric   std::string_view sv(record.UniqueName.begin(), record.UniqueName.size());
6360b57cec5SDimitry Andric   llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
6370b57cec5SDimitry Andric   if (demangler.Error)
6385ffd83dbSDimitry Andric     return std::string(record.Name);
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric   llvm::ms_demangle::IdentifierNode *idn =
6410b57cec5SDimitry Andric       ttn->QualifiedName->getUnqualifiedIdentifier();
6420b57cec5SDimitry Andric   return idn->toString();
6430b57cec5SDimitry Andric }
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric lldb::TypeSP
6460b57cec5SDimitry Andric SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id,
6470b57cec5SDimitry Andric                                             const TagRecord &record,
6480b57cec5SDimitry Andric                                             size_t size, CompilerType ct) {
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric   std::string uname = GetUnqualifiedTypeName(record);
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric   // FIXME: Search IPI stream for LF_UDT_MOD_SRC_LINE.
6530b57cec5SDimitry Andric   Declaration decl;
654bdd1243dSDimitry Andric   return MakeType(toOpaqueUid(type_id), ConstString(uname), size, nullptr,
655bdd1243dSDimitry Andric                   LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
656480093f4SDimitry Andric                   Type::ResolveState::Forward);
6570b57cec5SDimitry Andric }
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
6600b57cec5SDimitry Andric                                                 const ClassRecord &cr,
6610b57cec5SDimitry Andric                                                 CompilerType ct) {
6620b57cec5SDimitry Andric   return CreateClassStructUnion(type_id, cr, cr.getSize(), ct);
6630b57cec5SDimitry Andric }
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
6660b57cec5SDimitry Andric                                                 const UnionRecord &ur,
6670b57cec5SDimitry Andric                                                 CompilerType ct) {
6680b57cec5SDimitry Andric   return CreateClassStructUnion(type_id, ur, ur.getSize(), ct);
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
6720b57cec5SDimitry Andric                                                 const EnumRecord &er,
6730b57cec5SDimitry Andric                                                 CompilerType ct) {
6740b57cec5SDimitry Andric   std::string uname = GetUnqualifiedTypeName(er);
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric   Declaration decl;
6770b57cec5SDimitry Andric   TypeSP underlying_type = GetOrCreateType(er.UnderlyingType);
6780b57cec5SDimitry Andric 
679bdd1243dSDimitry Andric   return MakeType(toOpaqueUid(type_id), ConstString(uname),
680bdd1243dSDimitry Andric                   underlying_type->GetByteSize(nullptr), nullptr,
681bdd1243dSDimitry Andric                   LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
682bdd1243dSDimitry Andric                   ct, lldb_private::Type::ResolveState::Forward);
6830b57cec5SDimitry Andric }
6840b57cec5SDimitry Andric 
6850b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
6860b57cec5SDimitry Andric                                             const ArrayRecord &ar,
6870b57cec5SDimitry Andric                                             CompilerType ct) {
6880b57cec5SDimitry Andric   TypeSP element_type = GetOrCreateType(ar.ElementType);
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric   Declaration decl;
691bdd1243dSDimitry Andric   TypeSP array_sp =
692bdd1243dSDimitry Andric       MakeType(toOpaqueUid(type_id), ConstString(), ar.Size, nullptr,
6930b57cec5SDimitry Andric                LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,
694480093f4SDimitry Andric                lldb_private::Type::ResolveState::Full);
6950b57cec5SDimitry Andric   array_sp->SetEncodingType(element_type.get());
6960b57cec5SDimitry Andric   return array_sp;
6970b57cec5SDimitry Andric }
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id,
7000b57cec5SDimitry Andric                                                const MemberFunctionRecord &mfr,
7010b57cec5SDimitry Andric                                                CompilerType ct) {
7020b57cec5SDimitry Andric   Declaration decl;
703bdd1243dSDimitry Andric   return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
704bdd1243dSDimitry Andric                   LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
705bdd1243dSDimitry Andric                   ct, lldb_private::Type::ResolveState::Full);
7060b57cec5SDimitry Andric }
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,
7090b57cec5SDimitry Andric                                                 const ProcedureRecord &pr,
7100b57cec5SDimitry Andric                                                 CompilerType ct) {
7110b57cec5SDimitry Andric   Declaration decl;
712bdd1243dSDimitry Andric   return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
713bdd1243dSDimitry Andric                   LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
714bdd1243dSDimitry Andric                   ct, lldb_private::Type::ResolveState::Full);
7150b57cec5SDimitry Andric }
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) {
7180b57cec5SDimitry Andric   if (type_id.index.isSimple())
7190b57cec5SDimitry Andric     return CreateSimpleType(type_id.index, ct);
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric   TpiStream &stream = type_id.is_ipi ? m_index->ipi() : m_index->tpi();
7220b57cec5SDimitry Andric   CVType cvt = stream.getType(type_id.index);
7230b57cec5SDimitry Andric 
7240b57cec5SDimitry Andric   if (cvt.kind() == LF_MODIFIER) {
7250b57cec5SDimitry Andric     ModifierRecord modifier;
7260b57cec5SDimitry Andric     llvm::cantFail(
7270b57cec5SDimitry Andric         TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier));
7280b57cec5SDimitry Andric     return CreateModifierType(type_id, modifier, ct);
7290b57cec5SDimitry Andric   }
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric   if (cvt.kind() == LF_POINTER) {
7320b57cec5SDimitry Andric     PointerRecord pointer;
7330b57cec5SDimitry Andric     llvm::cantFail(
7340b57cec5SDimitry Andric         TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer));
7350b57cec5SDimitry Andric     return CreatePointerType(type_id, pointer, ct);
7360b57cec5SDimitry Andric   }
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric   if (IsClassRecord(cvt.kind())) {
7390b57cec5SDimitry Andric     ClassRecord cr;
7400b57cec5SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
7410b57cec5SDimitry Andric     return CreateTagType(type_id, cr, ct);
7420b57cec5SDimitry Andric   }
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric   if (cvt.kind() == LF_ENUM) {
7450b57cec5SDimitry Andric     EnumRecord er;
7460b57cec5SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
7470b57cec5SDimitry Andric     return CreateTagType(type_id, er, ct);
7480b57cec5SDimitry Andric   }
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric   if (cvt.kind() == LF_UNION) {
7510b57cec5SDimitry Andric     UnionRecord ur;
7520b57cec5SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
7530b57cec5SDimitry Andric     return CreateTagType(type_id, ur, ct);
7540b57cec5SDimitry Andric   }
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric   if (cvt.kind() == LF_ARRAY) {
7570b57cec5SDimitry Andric     ArrayRecord ar;
7580b57cec5SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar));
7590b57cec5SDimitry Andric     return CreateArrayType(type_id, ar, ct);
7600b57cec5SDimitry Andric   }
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric   if (cvt.kind() == LF_PROCEDURE) {
7630b57cec5SDimitry Andric     ProcedureRecord pr;
7640b57cec5SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));
7650b57cec5SDimitry Andric     return CreateProcedureType(type_id, pr, ct);
7660b57cec5SDimitry Andric   }
7670b57cec5SDimitry Andric   if (cvt.kind() == LF_MFUNCTION) {
7680b57cec5SDimitry Andric     MemberFunctionRecord mfr;
7690b57cec5SDimitry Andric     llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr));
7700b57cec5SDimitry Andric     return CreateFunctionType(type_id, mfr, ct);
7710b57cec5SDimitry Andric   }
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric   return nullptr;
7740b57cec5SDimitry Andric }
7750b57cec5SDimitry Andric 
7760b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) {
7770b57cec5SDimitry Andric   // If they search for a UDT which is a forward ref, try and resolve the full
7780b57cec5SDimitry Andric   // decl and just map the forward ref uid to the full decl record.
779bdd1243dSDimitry Andric   std::optional<PdbTypeSymId> full_decl_uid;
7800b57cec5SDimitry Andric   if (IsForwardRefUdt(type_id, m_index->tpi())) {
7810b57cec5SDimitry Andric     auto expected_full_ti =
7820b57cec5SDimitry Andric         m_index->tpi().findFullDeclForForwardRef(type_id.index);
7830b57cec5SDimitry Andric     if (!expected_full_ti)
7840b57cec5SDimitry Andric       llvm::consumeError(expected_full_ti.takeError());
7850b57cec5SDimitry Andric     else if (*expected_full_ti != type_id.index) {
7860b57cec5SDimitry Andric       full_decl_uid = PdbTypeSymId(*expected_full_ti, false);
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric       // It's possible that a lookup would occur for the full decl causing it
7890b57cec5SDimitry Andric       // to be cached, then a second lookup would occur for the forward decl.
7900b57cec5SDimitry Andric       // We don't want to create a second full decl, so make sure the full
7910b57cec5SDimitry Andric       // decl hasn't already been cached.
7920b57cec5SDimitry Andric       auto full_iter = m_types.find(toOpaqueUid(*full_decl_uid));
7930b57cec5SDimitry Andric       if (full_iter != m_types.end()) {
7940b57cec5SDimitry Andric         TypeSP result = full_iter->second;
7950b57cec5SDimitry Andric         // Map the forward decl to the TypeSP for the full decl so we can take
7960b57cec5SDimitry Andric         // the fast path next time.
7970b57cec5SDimitry Andric         m_types[toOpaqueUid(type_id)] = result;
7980b57cec5SDimitry Andric         return result;
7990b57cec5SDimitry Andric       }
8000b57cec5SDimitry Andric     }
8010b57cec5SDimitry Andric   }
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric   PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id;
804bdd1243dSDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
805bdd1243dSDimitry Andric   if (auto err = ts_or_err.takeError())
806bdd1243dSDimitry Andric     return nullptr;
807bdd1243dSDimitry Andric   auto ts = *ts_or_err;
808bdd1243dSDimitry Andric   if (!ts)
809bdd1243dSDimitry Andric     return nullptr;
8100b57cec5SDimitry Andric 
811bdd1243dSDimitry Andric   PdbAstBuilder* ast_builder = ts->GetNativePDBParser();
812bdd1243dSDimitry Andric   clang::QualType qt = ast_builder->GetOrCreateType(best_decl_id);
81381ad6265SDimitry Andric   if (qt.isNull())
81481ad6265SDimitry Andric     return nullptr;
8150b57cec5SDimitry Andric 
816bdd1243dSDimitry Andric   TypeSP result = CreateType(best_decl_id, ast_builder->ToCompilerType(qt));
8170b57cec5SDimitry Andric   if (!result)
8180b57cec5SDimitry Andric     return nullptr;
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric   uint64_t best_uid = toOpaqueUid(best_decl_id);
8210b57cec5SDimitry Andric   m_types[best_uid] = result;
8220b57cec5SDimitry Andric   // If we had both a forward decl and a full decl, make both point to the new
8230b57cec5SDimitry Andric   // type.
8240b57cec5SDimitry Andric   if (full_decl_uid)
8250b57cec5SDimitry Andric     m_types[toOpaqueUid(type_id)] = result;
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric   return result;
8280b57cec5SDimitry Andric }
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::GetOrCreateType(PdbTypeSymId type_id) {
8310b57cec5SDimitry Andric   // We can't use try_emplace / overwrite here because the process of creating
8320b57cec5SDimitry Andric   // a type could create nested types, which could invalidate iterators.  So
8330b57cec5SDimitry Andric   // we have to do a 2-phase lookup / insert.
8340b57cec5SDimitry Andric   auto iter = m_types.find(toOpaqueUid(type_id));
8350b57cec5SDimitry Andric   if (iter != m_types.end())
8360b57cec5SDimitry Andric     return iter->second;
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric   TypeSP type = CreateAndCacheType(type_id);
8390b57cec5SDimitry Andric   if (type)
8409dba64beSDimitry Andric     GetTypeList().Insert(type);
8410b57cec5SDimitry Andric   return type;
8420b57cec5SDimitry Andric }
8430b57cec5SDimitry Andric 
8440b57cec5SDimitry Andric VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
8450b57cec5SDimitry Andric   CVSymbol sym = m_index->symrecords().readRecord(var_id.offset);
8460b57cec5SDimitry Andric   if (sym.kind() == S_CONSTANT)
8470b57cec5SDimitry Andric     return CreateConstantSymbol(var_id, sym);
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric   lldb::ValueType scope = eValueTypeInvalid;
8500b57cec5SDimitry Andric   TypeIndex ti;
8510b57cec5SDimitry Andric   llvm::StringRef name;
8520b57cec5SDimitry Andric   lldb::addr_t addr = 0;
8530b57cec5SDimitry Andric   uint16_t section = 0;
8540b57cec5SDimitry Andric   uint32_t offset = 0;
8550b57cec5SDimitry Andric   bool is_external = false;
8560b57cec5SDimitry Andric   switch (sym.kind()) {
8570b57cec5SDimitry Andric   case S_GDATA32:
8580b57cec5SDimitry Andric     is_external = true;
859bdd1243dSDimitry Andric     [[fallthrough]];
8600b57cec5SDimitry Andric   case S_LDATA32: {
8610b57cec5SDimitry Andric     DataSym ds(sym.kind());
8620b57cec5SDimitry Andric     llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, ds));
8630b57cec5SDimitry Andric     ti = ds.Type;
8640b57cec5SDimitry Andric     scope = (sym.kind() == S_GDATA32) ? eValueTypeVariableGlobal
8650b57cec5SDimitry Andric                                       : eValueTypeVariableStatic;
8660b57cec5SDimitry Andric     name = ds.Name;
8670b57cec5SDimitry Andric     section = ds.Segment;
8680b57cec5SDimitry Andric     offset = ds.DataOffset;
8690b57cec5SDimitry Andric     addr = m_index->MakeVirtualAddress(ds.Segment, ds.DataOffset);
8700b57cec5SDimitry Andric     break;
8710b57cec5SDimitry Andric   }
8720b57cec5SDimitry Andric   case S_GTHREAD32:
8730b57cec5SDimitry Andric     is_external = true;
874bdd1243dSDimitry Andric     [[fallthrough]];
8750b57cec5SDimitry Andric   case S_LTHREAD32: {
8760b57cec5SDimitry Andric     ThreadLocalDataSym tlds(sym.kind());
8770b57cec5SDimitry Andric     llvm::cantFail(
8780b57cec5SDimitry Andric         SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, tlds));
8790b57cec5SDimitry Andric     ti = tlds.Type;
8800b57cec5SDimitry Andric     name = tlds.Name;
8810b57cec5SDimitry Andric     section = tlds.Segment;
8820b57cec5SDimitry Andric     offset = tlds.DataOffset;
8830b57cec5SDimitry Andric     addr = m_index->MakeVirtualAddress(tlds.Segment, tlds.DataOffset);
8840b57cec5SDimitry Andric     scope = eValueTypeVariableThreadLocal;
8850b57cec5SDimitry Andric     break;
8860b57cec5SDimitry Andric   }
8870b57cec5SDimitry Andric   default:
8880b57cec5SDimitry Andric     llvm_unreachable("unreachable!");
8890b57cec5SDimitry Andric   }
8900b57cec5SDimitry Andric 
8910b57cec5SDimitry Andric   CompUnitSP comp_unit;
892bdd1243dSDimitry Andric   std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr);
89381ad6265SDimitry Andric   if (!modi) {
89481ad6265SDimitry Andric     return nullptr;
89581ad6265SDimitry Andric   }
89681ad6265SDimitry Andric 
8970b57cec5SDimitry Andric   CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(*modi);
8980b57cec5SDimitry Andric   comp_unit = GetOrCreateCompileUnit(cci);
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric   Declaration decl;
9010b57cec5SDimitry Andric   PdbTypeSymId tid(ti, false);
9020b57cec5SDimitry Andric   SymbolFileTypeSP type_sp =
9030b57cec5SDimitry Andric       std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
9040b57cec5SDimitry Andric   Variable::RangeList ranges;
905bdd1243dSDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
906bdd1243dSDimitry Andric   if (auto err = ts_or_err.takeError())
907bdd1243dSDimitry Andric     return nullptr;
908bdd1243dSDimitry Andric   auto ts = *ts_or_err;
909bdd1243dSDimitry Andric   if (!ts)
910bdd1243dSDimitry Andric     return nullptr;
9110b57cec5SDimitry Andric 
912bdd1243dSDimitry Andric   ts->GetNativePDBParser()->GetOrCreateVariableDecl(var_id);
9130b57cec5SDimitry Andric 
914753f127fSDimitry Andric   ModuleSP module_sp = GetObjectFile()->GetModule();
915753f127fSDimitry Andric   DWARFExpressionList location(
916753f127fSDimitry Andric       module_sp, MakeGlobalLocationExpression(section, offset, module_sp),
917753f127fSDimitry Andric       nullptr);
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric   std::string global_name("::");
9200b57cec5SDimitry Andric   global_name += name;
921e8d8bef9SDimitry Andric   bool artificial = false;
922e8d8bef9SDimitry Andric   bool location_is_constant_data = false;
923e8d8bef9SDimitry Andric   bool static_member = false;
9240b57cec5SDimitry Andric   VariableSP var_sp = std::make_shared<Variable>(
9250b57cec5SDimitry Andric       toOpaqueUid(var_id), name.str().c_str(), global_name.c_str(), type_sp,
926e8d8bef9SDimitry Andric       scope, comp_unit.get(), ranges, &decl, location, is_external, artificial,
927e8d8bef9SDimitry Andric       location_is_constant_data, static_member);
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric   return var_sp;
9300b57cec5SDimitry Andric }
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric lldb::VariableSP
9330b57cec5SDimitry Andric SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id,
9340b57cec5SDimitry Andric                                           const CVSymbol &cvs) {
9350b57cec5SDimitry Andric   TpiStream &tpi = m_index->tpi();
9360b57cec5SDimitry Andric   ConstantSym constant(cvs.kind());
9370b57cec5SDimitry Andric 
9380b57cec5SDimitry Andric   llvm::cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(cvs, constant));
9390b57cec5SDimitry Andric   std::string global_name("::");
9400b57cec5SDimitry Andric   global_name += constant.Name;
9410b57cec5SDimitry Andric   PdbTypeSymId tid(constant.Type, false);
9420b57cec5SDimitry Andric   SymbolFileTypeSP type_sp =
9430b57cec5SDimitry Andric       std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric   Declaration decl;
9460b57cec5SDimitry Andric   Variable::RangeList ranges;
9470b57cec5SDimitry Andric   ModuleSP module = GetObjectFile()->GetModule();
948753f127fSDimitry Andric   DWARFExpressionList location(module,
949753f127fSDimitry Andric                                MakeConstantLocationExpression(
950753f127fSDimitry Andric                                    constant.Type, tpi, constant.Value, module),
951753f127fSDimitry Andric                                nullptr);
9520b57cec5SDimitry Andric 
953e8d8bef9SDimitry Andric   bool external = false;
954e8d8bef9SDimitry Andric   bool artificial = false;
955e8d8bef9SDimitry Andric   bool location_is_constant_data = true;
956e8d8bef9SDimitry Andric   bool static_member = false;
9570b57cec5SDimitry Andric   VariableSP var_sp = std::make_shared<Variable>(
9580b57cec5SDimitry Andric       toOpaqueUid(var_id), constant.Name.str().c_str(), global_name.c_str(),
9590b57cec5SDimitry Andric       type_sp, eValueTypeVariableGlobal, module.get(), ranges, &decl, location,
960e8d8bef9SDimitry Andric       external, artificial, location_is_constant_data, static_member);
9610b57cec5SDimitry Andric   return var_sp;
9620b57cec5SDimitry Andric }
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric VariableSP
9650b57cec5SDimitry Andric SymbolFileNativePDB::GetOrCreateGlobalVariable(PdbGlobalSymId var_id) {
9660b57cec5SDimitry Andric   auto emplace_result = m_global_vars.try_emplace(toOpaqueUid(var_id), nullptr);
96781ad6265SDimitry Andric   if (emplace_result.second) {
96881ad6265SDimitry Andric     if (VariableSP var_sp = CreateGlobalVariable(var_id))
96981ad6265SDimitry Andric       emplace_result.first->second = var_sp;
97081ad6265SDimitry Andric     else
97181ad6265SDimitry Andric       return nullptr;
97281ad6265SDimitry Andric   }
9730b57cec5SDimitry Andric 
9740b57cec5SDimitry Andric   return emplace_result.first->second;
9750b57cec5SDimitry Andric }
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::GetOrCreateType(TypeIndex ti) {
9780b57cec5SDimitry Andric   return GetOrCreateType(PdbTypeSymId(ti, false));
9790b57cec5SDimitry Andric }
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric FunctionSP SymbolFileNativePDB::GetOrCreateFunction(PdbCompilandSymId func_id,
9820b57cec5SDimitry Andric                                                     CompileUnit &comp_unit) {
9830b57cec5SDimitry Andric   auto emplace_result = m_functions.try_emplace(toOpaqueUid(func_id), nullptr);
9840b57cec5SDimitry Andric   if (emplace_result.second)
9850b57cec5SDimitry Andric     emplace_result.first->second = CreateFunction(func_id, comp_unit);
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric   return emplace_result.first->second;
9880b57cec5SDimitry Andric }
9890b57cec5SDimitry Andric 
9900b57cec5SDimitry Andric CompUnitSP
9910b57cec5SDimitry Andric SymbolFileNativePDB::GetOrCreateCompileUnit(const CompilandIndexItem &cci) {
9920b57cec5SDimitry Andric 
9930b57cec5SDimitry Andric   auto emplace_result =
9940b57cec5SDimitry Andric       m_compilands.try_emplace(toOpaqueUid(cci.m_id), nullptr);
9950b57cec5SDimitry Andric   if (emplace_result.second)
9960b57cec5SDimitry Andric     emplace_result.first->second = CreateCompileUnit(cci);
9970b57cec5SDimitry Andric 
9980b57cec5SDimitry Andric   lldbassert(emplace_result.first->second);
9990b57cec5SDimitry Andric   return emplace_result.first->second;
10000b57cec5SDimitry Andric }
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric Block &SymbolFileNativePDB::GetOrCreateBlock(PdbCompilandSymId block_id) {
10030b57cec5SDimitry Andric   auto iter = m_blocks.find(toOpaqueUid(block_id));
10040b57cec5SDimitry Andric   if (iter != m_blocks.end())
10050b57cec5SDimitry Andric     return *iter->second;
10060b57cec5SDimitry Andric 
10070b57cec5SDimitry Andric   return CreateBlock(block_id);
10080b57cec5SDimitry Andric }
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric void SymbolFileNativePDB::ParseDeclsForContext(
10110b57cec5SDimitry Andric     lldb_private::CompilerDeclContext decl_ctx) {
1012bdd1243dSDimitry Andric   TypeSystem* ts_or_err = decl_ctx.GetTypeSystem();
1013bdd1243dSDimitry Andric   if (!ts_or_err)
1014bdd1243dSDimitry Andric     return;
1015bdd1243dSDimitry Andric   PdbAstBuilder* ast_builder = ts_or_err->GetNativePDBParser();
1016bdd1243dSDimitry Andric   clang::DeclContext *context = ast_builder->FromCompilerDeclContext(decl_ctx);
10170b57cec5SDimitry Andric   if (!context)
10180b57cec5SDimitry Andric     return;
1019bdd1243dSDimitry Andric   ast_builder->ParseDeclsForContext(*context);
10200b57cec5SDimitry Andric }
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) {
10230b57cec5SDimitry Andric   if (index >= GetNumCompileUnits())
10240b57cec5SDimitry Andric     return CompUnitSP();
10250b57cec5SDimitry Andric   lldbassert(index < UINT16_MAX);
10260b57cec5SDimitry Andric   if (index >= UINT16_MAX)
10270b57cec5SDimitry Andric     return nullptr;
10280b57cec5SDimitry Andric 
10290b57cec5SDimitry Andric   CompilandIndexItem &item = m_index->compilands().GetOrCreateCompiland(index);
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric   return GetOrCreateCompileUnit(item);
10320b57cec5SDimitry Andric }
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) {
10359dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
10360b57cec5SDimitry Andric   PdbSymUid uid(comp_unit.GetID());
10370b57cec5SDimitry Andric   lldbassert(uid.kind() == PdbSymUidKind::Compiland);
10380b57cec5SDimitry Andric 
10390b57cec5SDimitry Andric   CompilandIndexItem *item =
10400b57cec5SDimitry Andric       m_index->compilands().GetCompiland(uid.asCompiland().modi);
10410b57cec5SDimitry Andric   lldbassert(item);
10420b57cec5SDimitry Andric   if (!item->m_compile_opts)
10430b57cec5SDimitry Andric     return lldb::eLanguageTypeUnknown;
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric   return TranslateLanguage(item->m_compile_opts->getLanguage());
10460b57cec5SDimitry Andric }
10470b57cec5SDimitry Andric 
10480eae32dcSDimitry Andric void SymbolFileNativePDB::AddSymbols(Symtab &symtab) {}
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseFunctions(CompileUnit &comp_unit) {
10519dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
10520b57cec5SDimitry Andric   PdbSymUid uid{comp_unit.GetID()};
10530b57cec5SDimitry Andric   lldbassert(uid.kind() == PdbSymUidKind::Compiland);
10540b57cec5SDimitry Andric   uint16_t modi = uid.asCompiland().modi;
10550b57cec5SDimitry Andric   CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(modi);
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric   size_t count = comp_unit.GetNumFunctions();
10580b57cec5SDimitry Andric   const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
10590b57cec5SDimitry Andric   for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
10600b57cec5SDimitry Andric     if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32)
10610b57cec5SDimitry Andric       continue;
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric     PdbCompilandSymId sym_id{modi, iter.offset()};
10640b57cec5SDimitry Andric 
10650b57cec5SDimitry Andric     FunctionSP func = GetOrCreateFunction(sym_id, comp_unit);
10660b57cec5SDimitry Andric   }
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric   size_t new_count = comp_unit.GetNumFunctions();
10690b57cec5SDimitry Andric   lldbassert(new_count >= count);
10700b57cec5SDimitry Andric   return new_count - count;
10710b57cec5SDimitry Andric }
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) {
10740b57cec5SDimitry Andric   // If any of these flags are set, we need to resolve the compile unit.
10750b57cec5SDimitry Andric   uint32_t flags = eSymbolContextCompUnit;
10760b57cec5SDimitry Andric   flags |= eSymbolContextVariable;
10770b57cec5SDimitry Andric   flags |= eSymbolContextFunction;
10780b57cec5SDimitry Andric   flags |= eSymbolContextBlock;
10790b57cec5SDimitry Andric   flags |= eSymbolContextLineEntry;
10800b57cec5SDimitry Andric   return (resolve_scope & flags) != 0;
10810b57cec5SDimitry Andric }
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric uint32_t SymbolFileNativePDB::ResolveSymbolContext(
10840b57cec5SDimitry Andric     const Address &addr, SymbolContextItem resolve_scope, SymbolContext &sc) {
10859dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
10860b57cec5SDimitry Andric   uint32_t resolved_flags = 0;
10870b57cec5SDimitry Andric   lldb::addr_t file_addr = addr.GetFileAddress();
10880b57cec5SDimitry Andric 
10890b57cec5SDimitry Andric   if (NeedsResolvedCompileUnit(resolve_scope)) {
1090bdd1243dSDimitry Andric     std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr);
10910b57cec5SDimitry Andric     if (!modi)
10920b57cec5SDimitry Andric       return 0;
109381ad6265SDimitry Andric     CompUnitSP cu_sp = GetCompileUnitAtIndex(*modi);
1094349cc55cSDimitry Andric     if (!cu_sp)
10950b57cec5SDimitry Andric       return 0;
10960b57cec5SDimitry Andric 
1097349cc55cSDimitry Andric     sc.comp_unit = cu_sp.get();
10980b57cec5SDimitry Andric     resolved_flags |= eSymbolContextCompUnit;
10990b57cec5SDimitry Andric   }
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric   if (resolve_scope & eSymbolContextFunction ||
11020b57cec5SDimitry Andric       resolve_scope & eSymbolContextBlock) {
11030b57cec5SDimitry Andric     lldbassert(sc.comp_unit);
11040b57cec5SDimitry Andric     std::vector<SymbolAndUid> matches = m_index->FindSymbolsByVa(file_addr);
11050b57cec5SDimitry Andric     // Search the matches in reverse.  This way if there are multiple matches
11060b57cec5SDimitry Andric     // (for example we are 3 levels deep in a nested scope) it will find the
11070b57cec5SDimitry Andric     // innermost one first.
11080b57cec5SDimitry Andric     for (const auto &match : llvm::reverse(matches)) {
11090b57cec5SDimitry Andric       if (match.uid.kind() != PdbSymUidKind::CompilandSym)
11100b57cec5SDimitry Andric         continue;
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric       PdbCompilandSymId csid = match.uid.asCompilandSym();
11130b57cec5SDimitry Andric       CVSymbol cvs = m_index->ReadSymbolRecord(csid);
11140b57cec5SDimitry Andric       PDB_SymType type = CVSymToPDBSym(cvs.kind());
11150b57cec5SDimitry Andric       if (type != PDB_SymType::Function && type != PDB_SymType::Block)
11160b57cec5SDimitry Andric         continue;
11170b57cec5SDimitry Andric       if (type == PDB_SymType::Function) {
11180b57cec5SDimitry Andric         sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get();
1119bdd1243dSDimitry Andric         if (sc.function) {
112004eeddc0SDimitry Andric           Block &block = sc.function->GetBlock(true);
112104eeddc0SDimitry Andric           addr_t func_base =
112204eeddc0SDimitry Andric               sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
112304eeddc0SDimitry Andric           addr_t offset = file_addr - func_base;
112404eeddc0SDimitry Andric           sc.block = block.FindInnermostBlockByOffset(offset);
11250b57cec5SDimitry Andric         }
1126bdd1243dSDimitry Andric       }
11270b57cec5SDimitry Andric 
11280b57cec5SDimitry Andric       if (type == PDB_SymType::Block) {
1129bdd1243dSDimitry Andric         Block &block = GetOrCreateBlock(csid);
1130bdd1243dSDimitry Andric         sc.function = block.CalculateSymbolContextFunction();
1131bdd1243dSDimitry Andric         if (sc.function) {
1132bdd1243dSDimitry Andric           sc.function->GetBlock(true);
1133bdd1243dSDimitry Andric           addr_t func_base =
1134bdd1243dSDimitry Andric               sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
1135bdd1243dSDimitry Andric           addr_t offset = file_addr - func_base;
1136bdd1243dSDimitry Andric           sc.block = block.FindInnermostBlockByOffset(offset);
1137bdd1243dSDimitry Andric         }
11380b57cec5SDimitry Andric       }
113904eeddc0SDimitry Andric       if (sc.function)
11400b57cec5SDimitry Andric         resolved_flags |= eSymbolContextFunction;
114104eeddc0SDimitry Andric       if (sc.block)
11420b57cec5SDimitry Andric         resolved_flags |= eSymbolContextBlock;
11430b57cec5SDimitry Andric       break;
11440b57cec5SDimitry Andric     }
11450b57cec5SDimitry Andric   }
11460b57cec5SDimitry Andric 
11470b57cec5SDimitry Andric   if (resolve_scope & eSymbolContextLineEntry) {
11480b57cec5SDimitry Andric     lldbassert(sc.comp_unit);
11490b57cec5SDimitry Andric     if (auto *line_table = sc.comp_unit->GetLineTable()) {
11500b57cec5SDimitry Andric       if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
11510b57cec5SDimitry Andric         resolved_flags |= eSymbolContextLineEntry;
11520b57cec5SDimitry Andric     }
11530b57cec5SDimitry Andric   }
11540b57cec5SDimitry Andric 
11550b57cec5SDimitry Andric   return resolved_flags;
11560b57cec5SDimitry Andric }
11570b57cec5SDimitry Andric 
11580b57cec5SDimitry Andric uint32_t SymbolFileNativePDB::ResolveSymbolContext(
1159fe6060f1SDimitry Andric     const SourceLocationSpec &src_location_spec,
11600b57cec5SDimitry Andric     lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
116104eeddc0SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
116204eeddc0SDimitry Andric   const uint32_t prev_size = sc_list.GetSize();
116304eeddc0SDimitry Andric   if (resolve_scope & eSymbolContextCompUnit) {
116404eeddc0SDimitry Andric     for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus;
116504eeddc0SDimitry Andric          ++cu_idx) {
116604eeddc0SDimitry Andric       CompileUnit *cu = ParseCompileUnitAtIndex(cu_idx).get();
116704eeddc0SDimitry Andric       if (!cu)
116804eeddc0SDimitry Andric         continue;
116904eeddc0SDimitry Andric 
117004eeddc0SDimitry Andric       bool file_spec_matches_cu_file_spec = FileSpec::Match(
117104eeddc0SDimitry Andric           src_location_spec.GetFileSpec(), cu->GetPrimaryFile());
117204eeddc0SDimitry Andric       if (file_spec_matches_cu_file_spec) {
117304eeddc0SDimitry Andric         cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);
117404eeddc0SDimitry Andric         break;
11750b57cec5SDimitry Andric       }
11760b57cec5SDimitry Andric     }
117704eeddc0SDimitry Andric   }
117804eeddc0SDimitry Andric   return sc_list.GetSize() - prev_size;
11790b57cec5SDimitry Andric }
11800b57cec5SDimitry Andric 
11810b57cec5SDimitry Andric bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) {
11820b57cec5SDimitry Andric   // Unfortunately LLDB is set up to parse the entire compile unit line table
11830b57cec5SDimitry Andric   // all at once, even if all it really needs is line info for a specific
11840b57cec5SDimitry Andric   // function.  In the future it would be nice if it could set the sc.m_function
11850b57cec5SDimitry Andric   // member, and we could only get the line info for the function in question.
11869dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
11870b57cec5SDimitry Andric   PdbSymUid cu_id(comp_unit.GetID());
11880b57cec5SDimitry Andric   lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);
118904eeddc0SDimitry Andric   uint16_t modi = cu_id.asCompiland().modi;
119004eeddc0SDimitry Andric   CompilandIndexItem *cii = m_index->compilands().GetCompiland(modi);
119104eeddc0SDimitry Andric   lldbassert(cii);
119204eeddc0SDimitry Andric 
119304eeddc0SDimitry Andric   // Parse DEBUG_S_LINES subsections first, then parse all S_INLINESITE records
119404eeddc0SDimitry Andric   // in this CU. Add line entries into the set first so that if there are line
119504eeddc0SDimitry Andric   // entries with same addres, the later is always more accurate than the
119604eeddc0SDimitry Andric   // former.
119704eeddc0SDimitry Andric   std::set<LineTable::Entry, LineTableEntryComparator> line_set;
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric   // This is basically a copy of the .debug$S subsections from all original COFF
12000b57cec5SDimitry Andric   // object files merged together with address relocations applied.  We are
12010b57cec5SDimitry Andric   // looking for all DEBUG_S_LINES subsections.
12020b57cec5SDimitry Andric   for (const DebugSubsectionRecord &dssr :
120304eeddc0SDimitry Andric        cii->m_debug_stream.getSubsectionsArray()) {
12040b57cec5SDimitry Andric     if (dssr.kind() != DebugSubsectionKind::Lines)
12050b57cec5SDimitry Andric       continue;
12060b57cec5SDimitry Andric 
12070b57cec5SDimitry Andric     DebugLinesSubsectionRef lines;
12080b57cec5SDimitry Andric     llvm::BinaryStreamReader reader(dssr.getRecordData());
12090b57cec5SDimitry Andric     if (auto EC = lines.initialize(reader)) {
12100b57cec5SDimitry Andric       llvm::consumeError(std::move(EC));
12110b57cec5SDimitry Andric       return false;
12120b57cec5SDimitry Andric     }
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric     const LineFragmentHeader *lfh = lines.header();
12150b57cec5SDimitry Andric     uint64_t virtual_addr =
12160b57cec5SDimitry Andric         m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset);
121781ad6265SDimitry Andric     if (virtual_addr == LLDB_INVALID_ADDRESS)
121881ad6265SDimitry Andric       continue;
12190b57cec5SDimitry Andric 
12200b57cec5SDimitry Andric     for (const LineColumnEntry &group : lines) {
122104eeddc0SDimitry Andric       llvm::Expected<uint32_t> file_index_or_err =
122204eeddc0SDimitry Andric           GetFileIndex(*cii, group.NameIndex);
122304eeddc0SDimitry Andric       if (!file_index_or_err)
12240b57cec5SDimitry Andric         continue;
122504eeddc0SDimitry Andric       uint32_t file_index = file_index_or_err.get();
12260b57cec5SDimitry Andric       lldbassert(!group.LineNumbers.empty());
122704eeddc0SDimitry Andric       CompilandIndexItem::GlobalLineTable::Entry line_entry(
122804eeddc0SDimitry Andric           LLDB_INVALID_ADDRESS, 0);
12290b57cec5SDimitry Andric       for (const LineNumberEntry &entry : group.LineNumbers) {
123004eeddc0SDimitry Andric         LineInfo cur_info(entry.Flags);
123104eeddc0SDimitry Andric 
123204eeddc0SDimitry Andric         if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto())
123304eeddc0SDimitry Andric           continue;
123404eeddc0SDimitry Andric 
123504eeddc0SDimitry Andric         uint64_t addr = virtual_addr + entry.Offset;
123604eeddc0SDimitry Andric 
123704eeddc0SDimitry Andric         bool is_statement = cur_info.isStatement();
123804eeddc0SDimitry Andric         bool is_prologue = IsFunctionPrologue(*cii, addr);
123904eeddc0SDimitry Andric         bool is_epilogue = IsFunctionEpilogue(*cii, addr);
124004eeddc0SDimitry Andric 
124104eeddc0SDimitry Andric         uint32_t lno = cur_info.getStartLine();
124204eeddc0SDimitry Andric 
124381ad6265SDimitry Andric         LineTable::Entry new_entry(addr, lno, 0, file_index, is_statement, false,
124404eeddc0SDimitry Andric                                  is_prologue, is_epilogue, false);
124581ad6265SDimitry Andric         // Terminal entry has lower precedence than new entry.
124681ad6265SDimitry Andric         auto iter = line_set.find(new_entry);
124781ad6265SDimitry Andric         if (iter != line_set.end() && iter->is_terminal_entry)
124881ad6265SDimitry Andric           line_set.erase(iter);
124981ad6265SDimitry Andric         line_set.insert(new_entry);
125004eeddc0SDimitry Andric 
125104eeddc0SDimitry Andric         if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {
125204eeddc0SDimitry Andric           line_entry.SetRangeEnd(addr);
125304eeddc0SDimitry Andric           cii->m_global_line_table.Append(line_entry);
125404eeddc0SDimitry Andric         }
125504eeddc0SDimitry Andric         line_entry.SetRangeBase(addr);
125604eeddc0SDimitry Andric         line_entry.data = {file_index, lno};
12570b57cec5SDimitry Andric       }
12580b57cec5SDimitry Andric       LineInfo last_line(group.LineNumbers.back().Flags);
125904eeddc0SDimitry Andric       line_set.emplace(virtual_addr + lfh->CodeSize, last_line.getEndLine(), 0,
126004eeddc0SDimitry Andric                        file_index, false, false, false, false, true);
126104eeddc0SDimitry Andric 
126204eeddc0SDimitry Andric       if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {
126304eeddc0SDimitry Andric         line_entry.SetRangeEnd(virtual_addr + lfh->CodeSize);
126404eeddc0SDimitry Andric         cii->m_global_line_table.Append(line_entry);
12650b57cec5SDimitry Andric       }
12660b57cec5SDimitry Andric     }
126704eeddc0SDimitry Andric   }
126804eeddc0SDimitry Andric 
126904eeddc0SDimitry Andric   cii->m_global_line_table.Sort();
127004eeddc0SDimitry Andric 
127104eeddc0SDimitry Andric   // Parse all S_INLINESITE in this CU.
127204eeddc0SDimitry Andric   const CVSymbolArray &syms = cii->m_debug_stream.getSymbolArray();
127304eeddc0SDimitry Andric   for (auto iter = syms.begin(); iter != syms.end();) {
127404eeddc0SDimitry Andric     if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) {
127504eeddc0SDimitry Andric       ++iter;
127604eeddc0SDimitry Andric       continue;
127704eeddc0SDimitry Andric     }
127804eeddc0SDimitry Andric 
127904eeddc0SDimitry Andric     uint32_t record_offset = iter.offset();
128004eeddc0SDimitry Andric     CVSymbol func_record =
128104eeddc0SDimitry Andric         cii->m_debug_stream.readSymbolAtOffset(record_offset);
128204eeddc0SDimitry Andric     SegmentOffsetLength sol = GetSegmentOffsetAndLength(func_record);
128381ad6265SDimitry Andric     addr_t file_vm_addr =
128481ad6265SDimitry Andric         m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);
128581ad6265SDimitry Andric     if (file_vm_addr == LLDB_INVALID_ADDRESS)
128681ad6265SDimitry Andric       continue;
128781ad6265SDimitry Andric 
128804eeddc0SDimitry Andric     AddressRange func_range(file_vm_addr, sol.length,
128904eeddc0SDimitry Andric                             comp_unit.GetModule()->GetSectionList());
129004eeddc0SDimitry Andric     Address func_base = func_range.GetBaseAddress();
129104eeddc0SDimitry Andric     PdbCompilandSymId func_id{modi, record_offset};
129204eeddc0SDimitry Andric 
129304eeddc0SDimitry Andric     // Iterate all S_INLINESITEs in the function.
129404eeddc0SDimitry Andric     auto parse_inline_sites = [&](SymbolKind kind, PdbCompilandSymId id) {
129504eeddc0SDimitry Andric       if (kind != S_INLINESITE)
129604eeddc0SDimitry Andric         return false;
129704eeddc0SDimitry Andric 
129804eeddc0SDimitry Andric       ParseInlineSite(id, func_base);
129904eeddc0SDimitry Andric 
130004eeddc0SDimitry Andric       for (const auto &line_entry :
130104eeddc0SDimitry Andric            m_inline_sites[toOpaqueUid(id)]->line_entries) {
130204eeddc0SDimitry Andric         // If line_entry is not terminal entry, remove previous line entry at
130304eeddc0SDimitry Andric         // the same address and insert new one. Terminal entry inside an inline
130404eeddc0SDimitry Andric         // site might not be terminal entry for its parent.
130504eeddc0SDimitry Andric         if (!line_entry.is_terminal_entry)
130604eeddc0SDimitry Andric           line_set.erase(line_entry);
130704eeddc0SDimitry Andric         line_set.insert(line_entry);
130804eeddc0SDimitry Andric       }
130904eeddc0SDimitry Andric       // No longer useful after adding to line_set.
131004eeddc0SDimitry Andric       m_inline_sites[toOpaqueUid(id)]->line_entries.clear();
131104eeddc0SDimitry Andric       return true;
131204eeddc0SDimitry Andric     };
131304eeddc0SDimitry Andric     ParseSymbolArrayInScope(func_id, parse_inline_sites);
131404eeddc0SDimitry Andric     // Jump to the end of the function record.
131504eeddc0SDimitry Andric     iter = syms.at(getScopeEndOffset(func_record));
131604eeddc0SDimitry Andric   }
131704eeddc0SDimitry Andric 
131804eeddc0SDimitry Andric   cii->m_global_line_table.Clear();
131904eeddc0SDimitry Andric 
132004eeddc0SDimitry Andric   // Add line entries in line_set to line_table.
132104eeddc0SDimitry Andric   auto line_table = std::make_unique<LineTable>(&comp_unit);
132204eeddc0SDimitry Andric   std::unique_ptr<LineSequence> sequence(
132304eeddc0SDimitry Andric       line_table->CreateLineSequenceContainer());
132404eeddc0SDimitry Andric   for (const auto &line_entry : line_set) {
132504eeddc0SDimitry Andric     line_table->AppendLineEntryToSequence(
132604eeddc0SDimitry Andric         sequence.get(), line_entry.file_addr, line_entry.line,
132704eeddc0SDimitry Andric         line_entry.column, line_entry.file_idx,
132804eeddc0SDimitry Andric         line_entry.is_start_of_statement, line_entry.is_start_of_basic_block,
132904eeddc0SDimitry Andric         line_entry.is_prologue_end, line_entry.is_epilogue_begin,
133004eeddc0SDimitry Andric         line_entry.is_terminal_entry);
133104eeddc0SDimitry Andric   }
133204eeddc0SDimitry Andric   line_table->InsertSequence(sequence.get());
13330b57cec5SDimitry Andric 
13340b57cec5SDimitry Andric   if (line_table->GetSize() == 0)
13350b57cec5SDimitry Andric     return false;
13360b57cec5SDimitry Andric 
13370b57cec5SDimitry Andric   comp_unit.SetLineTable(line_table.release());
13380b57cec5SDimitry Andric   return true;
13390b57cec5SDimitry Andric }
13400b57cec5SDimitry Andric 
13410b57cec5SDimitry Andric bool SymbolFileNativePDB::ParseDebugMacros(CompileUnit &comp_unit) {
13420b57cec5SDimitry Andric   // PDB doesn't contain information about macros
13430b57cec5SDimitry Andric   return false;
13440b57cec5SDimitry Andric }
13450b57cec5SDimitry Andric 
134604eeddc0SDimitry Andric llvm::Expected<uint32_t>
134704eeddc0SDimitry Andric SymbolFileNativePDB::GetFileIndex(const CompilandIndexItem &cii,
134804eeddc0SDimitry Andric                                   uint32_t file_id) {
134906c3fb27SDimitry Andric   if (!cii.m_strings.hasChecksums() || !cii.m_strings.hasStrings())
135006c3fb27SDimitry Andric     return llvm::make_error<RawError>(raw_error_code::no_entry);
135106c3fb27SDimitry Andric 
135204eeddc0SDimitry Andric   const auto &checksums = cii.m_strings.checksums().getArray();
135304eeddc0SDimitry Andric   const auto &strings = cii.m_strings.strings();
135404eeddc0SDimitry Andric   // Indices in this structure are actually offsets of records in the
135504eeddc0SDimitry Andric   // DEBUG_S_FILECHECKSUMS subsection.  Those entries then have an index
135604eeddc0SDimitry Andric   // into the global PDB string table.
135704eeddc0SDimitry Andric   auto iter = checksums.at(file_id);
135804eeddc0SDimitry Andric   if (iter == checksums.end())
135904eeddc0SDimitry Andric     return llvm::make_error<RawError>(raw_error_code::no_entry);
136004eeddc0SDimitry Andric 
136104eeddc0SDimitry Andric   llvm::Expected<llvm::StringRef> efn = strings.getString(iter->FileNameOffset);
136204eeddc0SDimitry Andric   if (!efn) {
136304eeddc0SDimitry Andric     return efn.takeError();
136404eeddc0SDimitry Andric   }
136504eeddc0SDimitry Andric 
136604eeddc0SDimitry Andric   // LLDB wants the index of the file in the list of support files.
136704eeddc0SDimitry Andric   auto fn_iter = llvm::find(cii.m_file_list, *efn);
136881ad6265SDimitry Andric   if (fn_iter != cii.m_file_list.end())
136981ad6265SDimitry Andric     return std::distance(cii.m_file_list.begin(), fn_iter);
137081ad6265SDimitry Andric   return llvm::make_error<RawError>(raw_error_code::no_entry);
137104eeddc0SDimitry Andric }
137204eeddc0SDimitry Andric 
13730b57cec5SDimitry Andric bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit,
13740b57cec5SDimitry Andric                                             FileSpecList &support_files) {
13759dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
13760b57cec5SDimitry Andric   PdbSymUid cu_id(comp_unit.GetID());
13770b57cec5SDimitry Andric   lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);
13780b57cec5SDimitry Andric   CompilandIndexItem *cci =
13790b57cec5SDimitry Andric       m_index->compilands().GetCompiland(cu_id.asCompiland().modi);
13800b57cec5SDimitry Andric   lldbassert(cci);
13810b57cec5SDimitry Andric 
13820b57cec5SDimitry Andric   for (llvm::StringRef f : cci->m_file_list) {
13830b57cec5SDimitry Andric     FileSpec::Style style =
13840b57cec5SDimitry Andric         f.startswith("/") ? FileSpec::Style::posix : FileSpec::Style::windows;
13850b57cec5SDimitry Andric     FileSpec spec(f, style);
13860b57cec5SDimitry Andric     support_files.Append(spec);
13870b57cec5SDimitry Andric   }
13880b57cec5SDimitry Andric   return true;
13890b57cec5SDimitry Andric }
13900b57cec5SDimitry Andric 
13910b57cec5SDimitry Andric bool SymbolFileNativePDB::ParseImportedModules(
13920b57cec5SDimitry Andric     const SymbolContext &sc, std::vector<SourceModule> &imported_modules) {
13930b57cec5SDimitry Andric   // PDB does not yet support module debug info
13940b57cec5SDimitry Andric   return false;
13950b57cec5SDimitry Andric }
13960b57cec5SDimitry Andric 
139704eeddc0SDimitry Andric void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id,
139804eeddc0SDimitry Andric                                           Address func_addr) {
139904eeddc0SDimitry Andric   lldb::user_id_t opaque_uid = toOpaqueUid(id);
140006c3fb27SDimitry Andric   if (m_inline_sites.contains(opaque_uid))
140104eeddc0SDimitry Andric     return;
140204eeddc0SDimitry Andric 
140304eeddc0SDimitry Andric   addr_t func_base = func_addr.GetFileAddress();
140404eeddc0SDimitry Andric   CompilandIndexItem *cii = m_index->compilands().GetCompiland(id.modi);
140504eeddc0SDimitry Andric   CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(id.offset);
140604eeddc0SDimitry Andric   CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
140704eeddc0SDimitry Andric 
140804eeddc0SDimitry Andric   InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind()));
140904eeddc0SDimitry Andric   cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site));
141004eeddc0SDimitry Andric   PdbCompilandSymId parent_id(id.modi, inline_site.Parent);
141104eeddc0SDimitry Andric 
141204eeddc0SDimitry Andric   std::shared_ptr<InlineSite> inline_site_sp =
141304eeddc0SDimitry Andric       std::make_shared<InlineSite>(parent_id);
141404eeddc0SDimitry Andric 
141504eeddc0SDimitry Andric   // Get the inlined function declaration info.
141604eeddc0SDimitry Andric   auto iter = cii->m_inline_map.find(inline_site.Inlinee);
141704eeddc0SDimitry Andric   if (iter == cii->m_inline_map.end())
141804eeddc0SDimitry Andric     return;
141904eeddc0SDimitry Andric   InlineeSourceLine inlinee_line = iter->second;
142004eeddc0SDimitry Andric 
142104eeddc0SDimitry Andric   const FileSpecList &files = comp_unit->GetSupportFiles();
142204eeddc0SDimitry Andric   FileSpec decl_file;
142304eeddc0SDimitry Andric   llvm::Expected<uint32_t> file_index_or_err =
142404eeddc0SDimitry Andric       GetFileIndex(*cii, inlinee_line.Header->FileID);
142504eeddc0SDimitry Andric   if (!file_index_or_err)
142604eeddc0SDimitry Andric     return;
142781ad6265SDimitry Andric   uint32_t file_offset = file_index_or_err.get();
142881ad6265SDimitry Andric   decl_file = files.GetFileSpecAtIndex(file_offset);
142904eeddc0SDimitry Andric   uint32_t decl_line = inlinee_line.Header->SourceLineNum;
143004eeddc0SDimitry Andric   std::unique_ptr<Declaration> decl_up =
143104eeddc0SDimitry Andric       std::make_unique<Declaration>(decl_file, decl_line);
143204eeddc0SDimitry Andric 
143304eeddc0SDimitry Andric   // Parse range and line info.
143404eeddc0SDimitry Andric   uint32_t code_offset = 0;
143504eeddc0SDimitry Andric   int32_t line_offset = 0;
1436bdd1243dSDimitry Andric   std::optional<uint32_t> code_offset_base;
1437bdd1243dSDimitry Andric   std::optional<uint32_t> code_offset_end;
1438bdd1243dSDimitry Andric   std::optional<int32_t> cur_line_offset;
1439bdd1243dSDimitry Andric   std::optional<int32_t> next_line_offset;
1440bdd1243dSDimitry Andric   std::optional<uint32_t> next_file_offset;
144104eeddc0SDimitry Andric 
144281ad6265SDimitry Andric   bool is_terminal_entry = false;
144381ad6265SDimitry Andric   bool is_start_of_statement = true;
144404eeddc0SDimitry Andric   // The first instruction is the prologue end.
144504eeddc0SDimitry Andric   bool is_prologue_end = true;
144604eeddc0SDimitry Andric 
144781ad6265SDimitry Andric   auto update_code_offset = [&](uint32_t code_delta) {
144881ad6265SDimitry Andric     if (!code_offset_base)
144981ad6265SDimitry Andric       code_offset_base = code_offset;
145081ad6265SDimitry Andric     else if (!code_offset_end)
145181ad6265SDimitry Andric       code_offset_end = *code_offset_base + code_delta;
145204eeddc0SDimitry Andric   };
145381ad6265SDimitry Andric   auto update_line_offset = [&](int32_t line_delta) {
145404eeddc0SDimitry Andric     line_offset += line_delta;
145581ad6265SDimitry Andric     if (!code_offset_base || !cur_line_offset)
145681ad6265SDimitry Andric       cur_line_offset = line_offset;
145781ad6265SDimitry Andric     else
145881ad6265SDimitry Andric       next_line_offset = line_offset;
145981ad6265SDimitry Andric     ;
146081ad6265SDimitry Andric   };
146181ad6265SDimitry Andric   auto update_file_offset = [&](uint32_t offset) {
146281ad6265SDimitry Andric     if (!code_offset_base)
146381ad6265SDimitry Andric       file_offset = offset;
146481ad6265SDimitry Andric     else
146581ad6265SDimitry Andric       next_file_offset = offset;
146604eeddc0SDimitry Andric   };
146704eeddc0SDimitry Andric 
146804eeddc0SDimitry Andric   for (auto &annot : inline_site.annotations()) {
146904eeddc0SDimitry Andric     switch (annot.OpCode) {
147004eeddc0SDimitry Andric     case BinaryAnnotationsOpCode::CodeOffset:
147104eeddc0SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeOffset:
147204eeddc0SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
147381ad6265SDimitry Andric       code_offset += annot.U1;
147481ad6265SDimitry Andric       update_code_offset(annot.U1);
147504eeddc0SDimitry Andric       break;
147604eeddc0SDimitry Andric     case BinaryAnnotationsOpCode::ChangeLineOffset:
147781ad6265SDimitry Andric       update_line_offset(annot.S1);
147804eeddc0SDimitry Andric       break;
147904eeddc0SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeLength:
148081ad6265SDimitry Andric       update_code_offset(annot.U1);
148104eeddc0SDimitry Andric       code_offset += annot.U1;
148281ad6265SDimitry Andric       is_terminal_entry = true;
148304eeddc0SDimitry Andric       break;
148404eeddc0SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
148581ad6265SDimitry Andric       code_offset += annot.U1;
148681ad6265SDimitry Andric       update_code_offset(annot.U1);
148781ad6265SDimitry Andric       update_line_offset(annot.S1);
148804eeddc0SDimitry Andric       break;
148904eeddc0SDimitry Andric     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
149081ad6265SDimitry Andric       code_offset += annot.U2;
149181ad6265SDimitry Andric       update_code_offset(annot.U2);
149281ad6265SDimitry Andric       update_code_offset(annot.U1);
149381ad6265SDimitry Andric       code_offset += annot.U1;
149481ad6265SDimitry Andric       is_terminal_entry = true;
149581ad6265SDimitry Andric       break;
149681ad6265SDimitry Andric     case BinaryAnnotationsOpCode::ChangeFile:
149781ad6265SDimitry Andric       update_file_offset(annot.U1);
149804eeddc0SDimitry Andric       break;
149904eeddc0SDimitry Andric     default:
150004eeddc0SDimitry Andric       break;
150104eeddc0SDimitry Andric     }
150281ad6265SDimitry Andric 
150381ad6265SDimitry Andric     // Add range if current range is finished.
150481ad6265SDimitry Andric     if (code_offset_base && code_offset_end && cur_line_offset) {
150581ad6265SDimitry Andric       inline_site_sp->ranges.Append(RangeSourceLineVector::Entry(
150681ad6265SDimitry Andric           *code_offset_base, *code_offset_end - *code_offset_base,
150781ad6265SDimitry Andric           decl_line + *cur_line_offset));
150881ad6265SDimitry Andric       // Set base, end, file offset and line offset for next range.
150981ad6265SDimitry Andric       if (next_file_offset)
151081ad6265SDimitry Andric         file_offset = *next_file_offset;
151181ad6265SDimitry Andric       if (next_line_offset) {
151281ad6265SDimitry Andric         cur_line_offset = next_line_offset;
1513bdd1243dSDimitry Andric         next_line_offset = std::nullopt;
151481ad6265SDimitry Andric       }
1515bdd1243dSDimitry Andric       code_offset_base = is_terminal_entry ? std::nullopt : code_offset_end;
1516bdd1243dSDimitry Andric       code_offset_end = next_file_offset = std::nullopt;
151781ad6265SDimitry Andric     }
151881ad6265SDimitry Andric     if (code_offset_base && cur_line_offset) {
151981ad6265SDimitry Andric       if (is_terminal_entry) {
152081ad6265SDimitry Andric         LineTable::Entry line_entry(
152181ad6265SDimitry Andric             func_base + *code_offset_base, decl_line + *cur_line_offset, 0,
152281ad6265SDimitry Andric             file_offset, false, false, false, false, true);
152381ad6265SDimitry Andric         inline_site_sp->line_entries.push_back(line_entry);
152481ad6265SDimitry Andric       } else {
152581ad6265SDimitry Andric         LineTable::Entry line_entry(func_base + *code_offset_base,
152681ad6265SDimitry Andric                                     decl_line + *cur_line_offset, 0,
152781ad6265SDimitry Andric                                     file_offset, is_start_of_statement, false,
152881ad6265SDimitry Andric                                     is_prologue_end, false, false);
152981ad6265SDimitry Andric         inline_site_sp->line_entries.push_back(line_entry);
153081ad6265SDimitry Andric         is_prologue_end = false;
153181ad6265SDimitry Andric         is_start_of_statement = false;
153281ad6265SDimitry Andric       }
153381ad6265SDimitry Andric     }
153481ad6265SDimitry Andric     if (is_terminal_entry)
153581ad6265SDimitry Andric       is_start_of_statement = true;
153681ad6265SDimitry Andric     is_terminal_entry = false;
153704eeddc0SDimitry Andric   }
153804eeddc0SDimitry Andric 
153904eeddc0SDimitry Andric   inline_site_sp->ranges.Sort();
154004eeddc0SDimitry Andric 
154104eeddc0SDimitry Andric   // Get the inlined function callsite info.
154204eeddc0SDimitry Andric   std::unique_ptr<Declaration> callsite_up;
154304eeddc0SDimitry Andric   if (!inline_site_sp->ranges.IsEmpty()) {
154404eeddc0SDimitry Andric     auto *entry = inline_site_sp->ranges.GetEntryAtIndex(0);
154504eeddc0SDimitry Andric     addr_t base_offset = entry->GetRangeBase();
154604eeddc0SDimitry Andric     if (cii->m_debug_stream.readSymbolAtOffset(parent_id.offset).kind() ==
154704eeddc0SDimitry Andric         S_INLINESITE) {
154804eeddc0SDimitry Andric       // Its parent is another inline site, lookup parent site's range vector
154904eeddc0SDimitry Andric       // for callsite line.
155004eeddc0SDimitry Andric       ParseInlineSite(parent_id, func_base);
155104eeddc0SDimitry Andric       std::shared_ptr<InlineSite> parent_site =
155204eeddc0SDimitry Andric           m_inline_sites[toOpaqueUid(parent_id)];
155304eeddc0SDimitry Andric       FileSpec &parent_decl_file =
155404eeddc0SDimitry Andric           parent_site->inline_function_info->GetDeclaration().GetFile();
155504eeddc0SDimitry Andric       if (auto *parent_entry =
155604eeddc0SDimitry Andric               parent_site->ranges.FindEntryThatContains(base_offset)) {
155704eeddc0SDimitry Andric         callsite_up =
155804eeddc0SDimitry Andric             std::make_unique<Declaration>(parent_decl_file, parent_entry->data);
155904eeddc0SDimitry Andric       }
156004eeddc0SDimitry Andric     } else {
156104eeddc0SDimitry Andric       // Its parent is a function, lookup global line table for callsite.
156204eeddc0SDimitry Andric       if (auto *entry = cii->m_global_line_table.FindEntryThatContains(
156304eeddc0SDimitry Andric               func_base + base_offset)) {
156404eeddc0SDimitry Andric         const FileSpec &callsite_file =
156504eeddc0SDimitry Andric             files.GetFileSpecAtIndex(entry->data.first);
156604eeddc0SDimitry Andric         callsite_up =
156704eeddc0SDimitry Andric             std::make_unique<Declaration>(callsite_file, entry->data.second);
156804eeddc0SDimitry Andric       }
156904eeddc0SDimitry Andric     }
157004eeddc0SDimitry Andric   }
157104eeddc0SDimitry Andric 
157204eeddc0SDimitry Andric   // Get the inlined function name.
157304eeddc0SDimitry Andric   CVType inlinee_cvt = m_index->ipi().getType(inline_site.Inlinee);
157404eeddc0SDimitry Andric   std::string inlinee_name;
157504eeddc0SDimitry Andric   if (inlinee_cvt.kind() == LF_MFUNC_ID) {
157604eeddc0SDimitry Andric     MemberFuncIdRecord mfr;
157704eeddc0SDimitry Andric     cantFail(
157804eeddc0SDimitry Andric         TypeDeserializer::deserializeAs<MemberFuncIdRecord>(inlinee_cvt, mfr));
157904eeddc0SDimitry Andric     LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
158004eeddc0SDimitry Andric     inlinee_name.append(std::string(types.getTypeName(mfr.ClassType)));
158104eeddc0SDimitry Andric     inlinee_name.append("::");
158204eeddc0SDimitry Andric     inlinee_name.append(mfr.getName().str());
158304eeddc0SDimitry Andric   } else if (inlinee_cvt.kind() == LF_FUNC_ID) {
158404eeddc0SDimitry Andric     FuncIdRecord fir;
158504eeddc0SDimitry Andric     cantFail(TypeDeserializer::deserializeAs<FuncIdRecord>(inlinee_cvt, fir));
158604eeddc0SDimitry Andric     TypeIndex parent_idx = fir.getParentScope();
158704eeddc0SDimitry Andric     if (!parent_idx.isNoneType()) {
158804eeddc0SDimitry Andric       LazyRandomTypeCollection &ids = m_index->ipi().typeCollection();
158904eeddc0SDimitry Andric       inlinee_name.append(std::string(ids.getTypeName(parent_idx)));
159004eeddc0SDimitry Andric       inlinee_name.append("::");
159104eeddc0SDimitry Andric     }
159204eeddc0SDimitry Andric     inlinee_name.append(fir.getName().str());
159304eeddc0SDimitry Andric   }
159404eeddc0SDimitry Andric   inline_site_sp->inline_function_info = std::make_shared<InlineFunctionInfo>(
159504eeddc0SDimitry Andric       inlinee_name.c_str(), llvm::StringRef(), decl_up.get(),
159604eeddc0SDimitry Andric       callsite_up.get());
159704eeddc0SDimitry Andric 
159804eeddc0SDimitry Andric   m_inline_sites[opaque_uid] = inline_site_sp;
159904eeddc0SDimitry Andric }
160004eeddc0SDimitry Andric 
16010b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) {
16029dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
160304eeddc0SDimitry Andric   PdbCompilandSymId func_id = PdbSymUid(func.GetID()).asCompilandSym();
160404eeddc0SDimitry Andric   // After we iterate through inline sites inside the function, we already get
160504eeddc0SDimitry Andric   // all the info needed, removing from the map to save memory.
160604eeddc0SDimitry Andric   std::set<uint64_t> remove_uids;
160704eeddc0SDimitry Andric   auto parse_blocks = [&](SymbolKind kind, PdbCompilandSymId id) {
160804eeddc0SDimitry Andric     if (kind == S_GPROC32 || kind == S_LPROC32 || kind == S_BLOCK32 ||
160904eeddc0SDimitry Andric         kind == S_INLINESITE) {
161004eeddc0SDimitry Andric       GetOrCreateBlock(id);
161104eeddc0SDimitry Andric       if (kind == S_INLINESITE)
161204eeddc0SDimitry Andric         remove_uids.insert(toOpaqueUid(id));
161304eeddc0SDimitry Andric       return true;
161404eeddc0SDimitry Andric     }
161504eeddc0SDimitry Andric     return false;
161604eeddc0SDimitry Andric   };
161704eeddc0SDimitry Andric   size_t count = ParseSymbolArrayInScope(func_id, parse_blocks);
161804eeddc0SDimitry Andric   for (uint64_t uid : remove_uids) {
161904eeddc0SDimitry Andric     m_inline_sites.erase(uid);
162004eeddc0SDimitry Andric   }
162104eeddc0SDimitry Andric   return count;
162204eeddc0SDimitry Andric }
162304eeddc0SDimitry Andric 
162404eeddc0SDimitry Andric size_t SymbolFileNativePDB::ParseSymbolArrayInScope(
162504eeddc0SDimitry Andric     PdbCompilandSymId parent_id,
162604eeddc0SDimitry Andric     llvm::function_ref<bool(SymbolKind, PdbCompilandSymId)> fn) {
162704eeddc0SDimitry Andric   CompilandIndexItem *cii = m_index->compilands().GetCompiland(parent_id.modi);
162804eeddc0SDimitry Andric   CVSymbolArray syms =
162904eeddc0SDimitry Andric       cii->m_debug_stream.getSymbolArrayForScope(parent_id.offset);
163004eeddc0SDimitry Andric 
163104eeddc0SDimitry Andric   size_t count = 1;
163204eeddc0SDimitry Andric   for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
163304eeddc0SDimitry Andric     PdbCompilandSymId child_id(parent_id.modi, iter.offset());
163404eeddc0SDimitry Andric     if (fn(iter->kind(), child_id))
163504eeddc0SDimitry Andric       ++count;
163604eeddc0SDimitry Andric   }
163704eeddc0SDimitry Andric 
163804eeddc0SDimitry Andric   return count;
16390b57cec5SDimitry Andric }
16400b57cec5SDimitry Andric 
1641bdd1243dSDimitry Andric void SymbolFileNativePDB::DumpClangAST(Stream &s) {
1642bdd1243dSDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
1643bdd1243dSDimitry Andric   if (!ts_or_err)
1644bdd1243dSDimitry Andric     return;
1645bdd1243dSDimitry Andric   auto ts = *ts_or_err;
1646bdd1243dSDimitry Andric   TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
1647bdd1243dSDimitry Andric   if (!clang)
1648bdd1243dSDimitry Andric     return;
1649bdd1243dSDimitry Andric   clang->GetNativePDBParser()->Dump(s);
1650bdd1243dSDimitry Andric }
16510b57cec5SDimitry Andric 
16529dba64beSDimitry Andric void SymbolFileNativePDB::FindGlobalVariables(
16535ffd83dbSDimitry Andric     ConstString name, const CompilerDeclContext &parent_decl_ctx,
16540b57cec5SDimitry Andric     uint32_t max_matches, VariableList &variables) {
16559dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
16560b57cec5SDimitry Andric   using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
16570b57cec5SDimitry Andric 
16580b57cec5SDimitry Andric   std::vector<SymbolAndOffset> results = m_index->globals().findRecordsByName(
16590b57cec5SDimitry Andric       name.GetStringRef(), m_index->symrecords());
16600b57cec5SDimitry Andric   for (const SymbolAndOffset &result : results) {
16610b57cec5SDimitry Andric     switch (result.second.kind()) {
16620b57cec5SDimitry Andric     case SymbolKind::S_GDATA32:
16630b57cec5SDimitry Andric     case SymbolKind::S_LDATA32:
16640b57cec5SDimitry Andric     case SymbolKind::S_GTHREAD32:
16650b57cec5SDimitry Andric     case SymbolKind::S_LTHREAD32:
16660b57cec5SDimitry Andric     case SymbolKind::S_CONSTANT: {
16670b57cec5SDimitry Andric       PdbGlobalSymId global(result.first, false);
166881ad6265SDimitry Andric       if (VariableSP var = GetOrCreateGlobalVariable(global))
16690b57cec5SDimitry Andric         variables.AddVariable(var);
16700b57cec5SDimitry Andric       break;
16710b57cec5SDimitry Andric     }
16720b57cec5SDimitry Andric     default:
16730b57cec5SDimitry Andric       continue;
16740b57cec5SDimitry Andric     }
16750b57cec5SDimitry Andric   }
16760b57cec5SDimitry Andric }
16770b57cec5SDimitry Andric 
16789dba64beSDimitry Andric void SymbolFileNativePDB::FindFunctions(
1679bdd1243dSDimitry Andric     const Module::LookupInfo &lookup_info,
1680bdd1243dSDimitry Andric     const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
16810b57cec5SDimitry Andric     SymbolContextList &sc_list) {
16829dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1683bdd1243dSDimitry Andric   ConstString name = lookup_info.GetLookupName();
1684bdd1243dSDimitry Andric   FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
1685bdd1243dSDimitry Andric   if (name_type_mask & eFunctionNameTypeFull)
1686bdd1243dSDimitry Andric     name = lookup_info.GetName();
1687bdd1243dSDimitry Andric 
16884824e7fdSDimitry Andric   // For now we only support lookup by method name or full name.
16894824e7fdSDimitry Andric   if (!(name_type_mask & eFunctionNameTypeFull ||
16904824e7fdSDimitry Andric         name_type_mask & eFunctionNameTypeMethod))
16919dba64beSDimitry Andric     return;
16920b57cec5SDimitry Andric 
16930b57cec5SDimitry Andric   using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
16940b57cec5SDimitry Andric 
16950b57cec5SDimitry Andric   std::vector<SymbolAndOffset> matches = m_index->globals().findRecordsByName(
16960b57cec5SDimitry Andric       name.GetStringRef(), m_index->symrecords());
16970b57cec5SDimitry Andric   for (const SymbolAndOffset &match : matches) {
16980b57cec5SDimitry Andric     if (match.second.kind() != S_PROCREF && match.second.kind() != S_LPROCREF)
16990b57cec5SDimitry Andric       continue;
17000b57cec5SDimitry Andric     ProcRefSym proc(match.second.kind());
17010b57cec5SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(match.second, proc));
17020b57cec5SDimitry Andric 
17030b57cec5SDimitry Andric     if (!IsValidRecord(proc))
17040b57cec5SDimitry Andric       continue;
17050b57cec5SDimitry Andric 
17060b57cec5SDimitry Andric     CompilandIndexItem &cci =
17070b57cec5SDimitry Andric         m_index->compilands().GetOrCreateCompiland(proc.modi());
17080b57cec5SDimitry Andric     SymbolContext sc;
17090b57cec5SDimitry Andric 
17100b57cec5SDimitry Andric     sc.comp_unit = GetOrCreateCompileUnit(cci).get();
17110b57cec5SDimitry Andric     PdbCompilandSymId func_id(proc.modi(), proc.SymOffset);
17120b57cec5SDimitry Andric     sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get();
17130b57cec5SDimitry Andric 
17140b57cec5SDimitry Andric     sc_list.Append(sc);
17150b57cec5SDimitry Andric   }
17160b57cec5SDimitry Andric }
17170b57cec5SDimitry Andric 
17189dba64beSDimitry Andric void SymbolFileNativePDB::FindFunctions(const RegularExpression &regex,
17199dba64beSDimitry Andric                                         bool include_inlines,
17209dba64beSDimitry Andric                                         SymbolContextList &sc_list) {}
17210b57cec5SDimitry Andric 
17229dba64beSDimitry Andric void SymbolFileNativePDB::FindTypes(
17235ffd83dbSDimitry Andric     ConstString name, const CompilerDeclContext &parent_decl_ctx,
17249dba64beSDimitry Andric     uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files,
17259dba64beSDimitry Andric     TypeMap &types) {
17269dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
17270b57cec5SDimitry Andric   if (!name)
17289dba64beSDimitry Andric     return;
17290b57cec5SDimitry Andric 
17300b57cec5SDimitry Andric   searched_symbol_files.clear();
17310b57cec5SDimitry Andric   searched_symbol_files.insert(this);
17320b57cec5SDimitry Andric 
17330b57cec5SDimitry Andric   // There is an assumption 'name' is not a regex
17349dba64beSDimitry Andric   FindTypesByName(name.GetStringRef(), max_matches, types);
17350b57cec5SDimitry Andric }
17360b57cec5SDimitry Andric 
1737480093f4SDimitry Andric void SymbolFileNativePDB::FindTypes(
1738480093f4SDimitry Andric     llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
1739480093f4SDimitry Andric     llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {}
17400b57cec5SDimitry Andric 
17419dba64beSDimitry Andric void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name,
17420b57cec5SDimitry Andric                                           uint32_t max_matches,
17430b57cec5SDimitry Andric                                           TypeMap &types) {
17440b57cec5SDimitry Andric 
17450b57cec5SDimitry Andric   std::vector<TypeIndex> matches = m_index->tpi().findRecordsByName(name);
17460b57cec5SDimitry Andric   if (max_matches > 0 && max_matches < matches.size())
17470b57cec5SDimitry Andric     matches.resize(max_matches);
17480b57cec5SDimitry Andric 
17490b57cec5SDimitry Andric   for (TypeIndex ti : matches) {
17500b57cec5SDimitry Andric     TypeSP type = GetOrCreateType(ti);
17510b57cec5SDimitry Andric     if (!type)
17520b57cec5SDimitry Andric       continue;
17530b57cec5SDimitry Andric 
17540b57cec5SDimitry Andric     types.Insert(type);
17550b57cec5SDimitry Andric   }
17560b57cec5SDimitry Andric }
17570b57cec5SDimitry Andric 
17580b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseTypes(CompileUnit &comp_unit) {
17599dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
17600b57cec5SDimitry Andric   // Only do the full type scan the first time.
17610b57cec5SDimitry Andric   if (m_done_full_type_scan)
17620b57cec5SDimitry Andric     return 0;
17630b57cec5SDimitry Andric 
17649dba64beSDimitry Andric   const size_t old_count = GetTypeList().GetSize();
17650b57cec5SDimitry Andric   LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
17660b57cec5SDimitry Andric 
17670b57cec5SDimitry Andric   // First process the entire TPI stream.
17680b57cec5SDimitry Andric   for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
17690b57cec5SDimitry Andric     TypeSP type = GetOrCreateType(*ti);
17700b57cec5SDimitry Andric     if (type)
17710b57cec5SDimitry Andric       (void)type->GetFullCompilerType();
17720b57cec5SDimitry Andric   }
17730b57cec5SDimitry Andric 
17740b57cec5SDimitry Andric   // Next look for S_UDT records in the globals stream.
17750b57cec5SDimitry Andric   for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
17760b57cec5SDimitry Andric     PdbGlobalSymId global{gid, false};
17770b57cec5SDimitry Andric     CVSymbol sym = m_index->ReadSymbolRecord(global);
17780b57cec5SDimitry Andric     if (sym.kind() != S_UDT)
17790b57cec5SDimitry Andric       continue;
17800b57cec5SDimitry Andric 
17810b57cec5SDimitry Andric     UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
17820b57cec5SDimitry Andric     bool is_typedef = true;
17830b57cec5SDimitry Andric     if (IsTagRecord(PdbTypeSymId{udt.Type, false}, m_index->tpi())) {
17840b57cec5SDimitry Andric       CVType cvt = m_index->tpi().getType(udt.Type);
17850b57cec5SDimitry Andric       llvm::StringRef name = CVTagRecord::create(cvt).name();
17860b57cec5SDimitry Andric       if (name == udt.Name)
17870b57cec5SDimitry Andric         is_typedef = false;
17880b57cec5SDimitry Andric     }
17890b57cec5SDimitry Andric 
17900b57cec5SDimitry Andric     if (is_typedef)
17910b57cec5SDimitry Andric       GetOrCreateTypedef(global);
17920b57cec5SDimitry Andric   }
17930b57cec5SDimitry Andric 
17949dba64beSDimitry Andric   const size_t new_count = GetTypeList().GetSize();
17950b57cec5SDimitry Andric 
17960b57cec5SDimitry Andric   m_done_full_type_scan = true;
17970b57cec5SDimitry Andric 
17980b57cec5SDimitry Andric   return new_count - old_count;
17990b57cec5SDimitry Andric }
18000b57cec5SDimitry Andric 
18010b57cec5SDimitry Andric size_t
18020b57cec5SDimitry Andric SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit,
18030b57cec5SDimitry Andric                                                   VariableList &variables) {
18040b57cec5SDimitry Andric   PdbSymUid sym_uid(comp_unit.GetID());
18050b57cec5SDimitry Andric   lldbassert(sym_uid.kind() == PdbSymUidKind::Compiland);
18060b57cec5SDimitry Andric   return 0;
18070b57cec5SDimitry Andric }
18080b57cec5SDimitry Andric 
18090b57cec5SDimitry Andric VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
18100b57cec5SDimitry Andric                                                     PdbCompilandSymId var_id,
18110b57cec5SDimitry Andric                                                     bool is_param) {
18120b57cec5SDimitry Andric   ModuleSP module = GetObjectFile()->GetModule();
18130b57cec5SDimitry Andric   Block &block = GetOrCreateBlock(scope_id);
1814753f127fSDimitry Andric   // Get function block.
1815753f127fSDimitry Andric   Block *func_block = &block;
1816753f127fSDimitry Andric   while (func_block->GetParent()) {
1817753f127fSDimitry Andric     func_block = func_block->GetParent();
1818753f127fSDimitry Andric   }
1819753f127fSDimitry Andric   Address addr;
1820753f127fSDimitry Andric   func_block->GetStartAddress(addr);
18210b57cec5SDimitry Andric   VariableInfo var_info =
1822753f127fSDimitry Andric       GetVariableLocationInfo(*m_index, var_id, *func_block, module);
1823bdd1243dSDimitry Andric   Function *func = func_block->CalculateSymbolContextFunction();
1824bdd1243dSDimitry Andric   if (!func)
18250b57cec5SDimitry Andric     return nullptr;
1826bdd1243dSDimitry Andric   // Use empty dwarf expr if optimized away so that it won't be filtered out
1827bdd1243dSDimitry Andric   // when lookuping local variables in this scope.
1828bdd1243dSDimitry Andric   if (!var_info.location.IsValid())
1829bdd1243dSDimitry Andric     var_info.location = DWARFExpressionList(module, DWARFExpression(), nullptr);
1830bdd1243dSDimitry Andric   var_info.location.SetFuncFileAddress(
1831bdd1243dSDimitry Andric       func->GetAddressRange().GetBaseAddress().GetFileAddress());
18320b57cec5SDimitry Andric   CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
18330b57cec5SDimitry Andric   CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
18340b57cec5SDimitry Andric   TypeSP type_sp = GetOrCreateType(var_info.type);
1835bdd1243dSDimitry Andric   if (!type_sp)
1836bdd1243dSDimitry Andric     return nullptr;
18370b57cec5SDimitry Andric   std::string name = var_info.name.str();
18380b57cec5SDimitry Andric   Declaration decl;
18390b57cec5SDimitry Andric   SymbolFileTypeSP sftype =
18400b57cec5SDimitry Andric       std::make_shared<SymbolFileType>(*this, type_sp->GetID());
18410b57cec5SDimitry Andric 
184281ad6265SDimitry Andric   is_param |= var_info.is_param;
18430b57cec5SDimitry Andric   ValueType var_scope =
18440b57cec5SDimitry Andric       is_param ? eValueTypeVariableArgument : eValueTypeVariableLocal;
1845e8d8bef9SDimitry Andric   bool external = false;
1846e8d8bef9SDimitry Andric   bool artificial = false;
1847e8d8bef9SDimitry Andric   bool location_is_constant_data = false;
1848e8d8bef9SDimitry Andric   bool static_member = false;
1849bdd1243dSDimitry Andric   Variable::RangeList scope_ranges;
18500b57cec5SDimitry Andric   VariableSP var_sp = std::make_shared<Variable>(
18510b57cec5SDimitry Andric       toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope,
1852bdd1243dSDimitry Andric       &block, scope_ranges, &decl, var_info.location, external, artificial,
1853753f127fSDimitry Andric       location_is_constant_data, static_member);
1854bdd1243dSDimitry Andric   if (!is_param) {
1855bdd1243dSDimitry Andric     auto ts_or_err = GetTypeSystemForLanguage(comp_unit_sp->GetLanguage());
1856bdd1243dSDimitry Andric     if (auto err = ts_or_err.takeError())
1857bdd1243dSDimitry Andric       return nullptr;
1858bdd1243dSDimitry Andric     auto ts = *ts_or_err;
1859bdd1243dSDimitry Andric     if (!ts)
1860bdd1243dSDimitry Andric       return nullptr;
18610b57cec5SDimitry Andric 
1862bdd1243dSDimitry Andric     ts->GetNativePDBParser()->GetOrCreateVariableDecl(scope_id, var_id);
1863bdd1243dSDimitry Andric   }
18640b57cec5SDimitry Andric   m_local_variables[toOpaqueUid(var_id)] = var_sp;
18650b57cec5SDimitry Andric   return var_sp;
18660b57cec5SDimitry Andric }
18670b57cec5SDimitry Andric 
18680b57cec5SDimitry Andric VariableSP SymbolFileNativePDB::GetOrCreateLocalVariable(
18690b57cec5SDimitry Andric     PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param) {
18700b57cec5SDimitry Andric   auto iter = m_local_variables.find(toOpaqueUid(var_id));
18710b57cec5SDimitry Andric   if (iter != m_local_variables.end())
18720b57cec5SDimitry Andric     return iter->second;
18730b57cec5SDimitry Andric 
18740b57cec5SDimitry Andric   return CreateLocalVariable(scope_id, var_id, is_param);
18750b57cec5SDimitry Andric }
18760b57cec5SDimitry Andric 
18770b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
18780b57cec5SDimitry Andric   CVSymbol sym = m_index->ReadSymbolRecord(id);
18790b57cec5SDimitry Andric   lldbassert(sym.kind() == SymbolKind::S_UDT);
18800b57cec5SDimitry Andric 
18810b57cec5SDimitry Andric   UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
18820b57cec5SDimitry Andric 
18830b57cec5SDimitry Andric   TypeSP target_type = GetOrCreateType(udt.Type);
18840b57cec5SDimitry Andric 
1885bdd1243dSDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
1886bdd1243dSDimitry Andric   if (auto err = ts_or_err.takeError())
1887bdd1243dSDimitry Andric     return nullptr;
1888bdd1243dSDimitry Andric   auto ts = *ts_or_err;
1889bdd1243dSDimitry Andric   if (!ts)
1890bdd1243dSDimitry Andric     return nullptr;
1891bdd1243dSDimitry Andric 
1892bdd1243dSDimitry Andric   ts->GetNativePDBParser()->GetOrCreateTypedefDecl(id);
18930b57cec5SDimitry Andric 
18940b57cec5SDimitry Andric   Declaration decl;
1895bdd1243dSDimitry Andric   return MakeType(
1896bdd1243dSDimitry Andric       toOpaqueUid(id), ConstString(udt.Name), target_type->GetByteSize(nullptr),
1897bdd1243dSDimitry Andric       nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID,
1898bdd1243dSDimitry Andric       decl, target_type->GetForwardCompilerType(),
1899480093f4SDimitry Andric       lldb_private::Type::ResolveState::Forward);
19000b57cec5SDimitry Andric }
19010b57cec5SDimitry Andric 
19020b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) {
19030b57cec5SDimitry Andric   auto iter = m_types.find(toOpaqueUid(id));
19040b57cec5SDimitry Andric   if (iter != m_types.end())
19050b57cec5SDimitry Andric     return iter->second;
19060b57cec5SDimitry Andric 
19070b57cec5SDimitry Andric   return CreateTypedef(id);
19080b57cec5SDimitry Andric }
19090b57cec5SDimitry Andric 
19100b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) {
19110b57cec5SDimitry Andric   Block &block = GetOrCreateBlock(block_id);
19120b57cec5SDimitry Andric 
19130b57cec5SDimitry Andric   size_t count = 0;
19140b57cec5SDimitry Andric 
19150b57cec5SDimitry Andric   CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
19160b57cec5SDimitry Andric   CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
19170b57cec5SDimitry Andric   uint32_t params_remaining = 0;
19180b57cec5SDimitry Andric   switch (sym.kind()) {
19190b57cec5SDimitry Andric   case S_GPROC32:
19200b57cec5SDimitry Andric   case S_LPROC32: {
19210b57cec5SDimitry Andric     ProcSym proc(static_cast<SymbolRecordKind>(sym.kind()));
19220b57cec5SDimitry Andric     cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym, proc));
19230b57cec5SDimitry Andric     CVType signature = m_index->tpi().getType(proc.FunctionType);
1924bdd1243dSDimitry Andric     if (signature.kind() == LF_PROCEDURE) {
19250b57cec5SDimitry Andric       ProcedureRecord sig;
1926bdd1243dSDimitry Andric       if (llvm::Error e = TypeDeserializer::deserializeAs<ProcedureRecord>(
1927bdd1243dSDimitry Andric               signature, sig)) {
1928bdd1243dSDimitry Andric         llvm::consumeError(std::move(e));
1929bdd1243dSDimitry Andric         return 0;
1930bdd1243dSDimitry Andric       }
19310b57cec5SDimitry Andric       params_remaining = sig.getParameterCount();
1932bdd1243dSDimitry Andric     } else if (signature.kind() == LF_MFUNCTION) {
1933bdd1243dSDimitry Andric       MemberFunctionRecord sig;
1934bdd1243dSDimitry Andric       if (llvm::Error e = TypeDeserializer::deserializeAs<MemberFunctionRecord>(
1935bdd1243dSDimitry Andric               signature, sig)) {
1936bdd1243dSDimitry Andric         llvm::consumeError(std::move(e));
1937bdd1243dSDimitry Andric         return 0;
1938bdd1243dSDimitry Andric       }
1939bdd1243dSDimitry Andric       params_remaining = sig.getParameterCount();
1940bdd1243dSDimitry Andric     } else
1941bdd1243dSDimitry Andric       return 0;
19420b57cec5SDimitry Andric     break;
19430b57cec5SDimitry Andric   }
19440b57cec5SDimitry Andric   case S_BLOCK32:
19450b57cec5SDimitry Andric     break;
194604eeddc0SDimitry Andric   case S_INLINESITE:
194781ad6265SDimitry Andric     break;
19480b57cec5SDimitry Andric   default:
19490b57cec5SDimitry Andric     lldbassert(false && "Symbol is not a block!");
19500b57cec5SDimitry Andric     return 0;
19510b57cec5SDimitry Andric   }
19520b57cec5SDimitry Andric 
19530b57cec5SDimitry Andric   VariableListSP variables = block.GetBlockVariableList(false);
19540b57cec5SDimitry Andric   if (!variables) {
19550b57cec5SDimitry Andric     variables = std::make_shared<VariableList>();
19560b57cec5SDimitry Andric     block.SetVariableList(variables);
19570b57cec5SDimitry Andric   }
19580b57cec5SDimitry Andric 
19590b57cec5SDimitry Andric   CVSymbolArray syms = limitSymbolArrayToScope(
19600b57cec5SDimitry Andric       cii->m_debug_stream.getSymbolArray(), block_id.offset);
19610b57cec5SDimitry Andric 
19620b57cec5SDimitry Andric   // Skip the first record since it's a PROC32 or BLOCK32, and there's
19630b57cec5SDimitry Andric   // no point examining it since we know it's not a local variable.
19640b57cec5SDimitry Andric   syms.drop_front();
19650b57cec5SDimitry Andric   auto iter = syms.begin();
19660b57cec5SDimitry Andric   auto end = syms.end();
19670b57cec5SDimitry Andric 
19680b57cec5SDimitry Andric   while (iter != end) {
19690b57cec5SDimitry Andric     uint32_t record_offset = iter.offset();
19700b57cec5SDimitry Andric     CVSymbol variable_cvs = *iter;
19710b57cec5SDimitry Andric     PdbCompilandSymId child_sym_id(block_id.modi, record_offset);
19720b57cec5SDimitry Andric     ++iter;
19730b57cec5SDimitry Andric 
197481ad6265SDimitry Andric     // If this is a block or inline site, recurse into its children and then
197581ad6265SDimitry Andric     // skip it.
197681ad6265SDimitry Andric     if (variable_cvs.kind() == S_BLOCK32 ||
197781ad6265SDimitry Andric         variable_cvs.kind() == S_INLINESITE) {
19780b57cec5SDimitry Andric       uint32_t block_end = getScopeEndOffset(variable_cvs);
19790b57cec5SDimitry Andric       count += ParseVariablesForBlock(child_sym_id);
19800b57cec5SDimitry Andric       iter = syms.at(block_end);
19810b57cec5SDimitry Andric       continue;
19820b57cec5SDimitry Andric     }
19830b57cec5SDimitry Andric 
19840b57cec5SDimitry Andric     bool is_param = params_remaining > 0;
19850b57cec5SDimitry Andric     VariableSP variable;
19860b57cec5SDimitry Andric     switch (variable_cvs.kind()) {
19870b57cec5SDimitry Andric     case S_REGREL32:
19880b57cec5SDimitry Andric     case S_REGISTER:
19890b57cec5SDimitry Andric     case S_LOCAL:
19900b57cec5SDimitry Andric       variable = GetOrCreateLocalVariable(block_id, child_sym_id, is_param);
19910b57cec5SDimitry Andric       if (is_param)
19920b57cec5SDimitry Andric         --params_remaining;
19930b57cec5SDimitry Andric       if (variable)
19940b57cec5SDimitry Andric         variables->AddVariableIfUnique(variable);
19950b57cec5SDimitry Andric       break;
19960b57cec5SDimitry Andric     default:
19970b57cec5SDimitry Andric       break;
19980b57cec5SDimitry Andric     }
19990b57cec5SDimitry Andric   }
20000b57cec5SDimitry Andric 
20010b57cec5SDimitry Andric   // Pass false for set_children, since we call this recursively so that the
20020b57cec5SDimitry Andric   // children will call this for themselves.
20030b57cec5SDimitry Andric   block.SetDidParseVariables(true, false);
20040b57cec5SDimitry Andric 
20050b57cec5SDimitry Andric   return count;
20060b57cec5SDimitry Andric }
20070b57cec5SDimitry Andric 
20080b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) {
20099dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
20100b57cec5SDimitry Andric   lldbassert(sc.function || sc.comp_unit);
20110b57cec5SDimitry Andric 
20120b57cec5SDimitry Andric   VariableListSP variables;
20130b57cec5SDimitry Andric   if (sc.block) {
20140b57cec5SDimitry Andric     PdbSymUid block_id(sc.block->GetID());
20150b57cec5SDimitry Andric 
20160b57cec5SDimitry Andric     size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
20170b57cec5SDimitry Andric     return count;
20180b57cec5SDimitry Andric   }
20190b57cec5SDimitry Andric 
20200b57cec5SDimitry Andric   if (sc.function) {
20210b57cec5SDimitry Andric     PdbSymUid block_id(sc.function->GetID());
20220b57cec5SDimitry Andric 
20230b57cec5SDimitry Andric     size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
20240b57cec5SDimitry Andric     return count;
20250b57cec5SDimitry Andric   }
20260b57cec5SDimitry Andric 
20270b57cec5SDimitry Andric   if (sc.comp_unit) {
20280b57cec5SDimitry Andric     variables = sc.comp_unit->GetVariableList(false);
20290b57cec5SDimitry Andric     if (!variables) {
20300b57cec5SDimitry Andric       variables = std::make_shared<VariableList>();
20310b57cec5SDimitry Andric       sc.comp_unit->SetVariableList(variables);
20320b57cec5SDimitry Andric     }
20330b57cec5SDimitry Andric     return ParseVariablesForCompileUnit(*sc.comp_unit, *variables);
20340b57cec5SDimitry Andric   }
20350b57cec5SDimitry Andric 
20360b57cec5SDimitry Andric   llvm_unreachable("Unreachable!");
20370b57cec5SDimitry Andric }
20380b57cec5SDimitry Andric 
20390b57cec5SDimitry Andric CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) {
2040bdd1243dSDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
2041bdd1243dSDimitry Andric   if (auto err = ts_or_err.takeError())
2042bdd1243dSDimitry Andric     return CompilerDecl();
2043bdd1243dSDimitry Andric   auto ts = *ts_or_err;
2044bdd1243dSDimitry Andric   if (!ts)
2045bdd1243dSDimitry Andric     return {};
2046bdd1243dSDimitry Andric 
2047bdd1243dSDimitry Andric   if (auto decl = ts->GetNativePDBParser()->GetOrCreateDeclForUid(uid))
204881ad6265SDimitry Andric     return *decl;
20499dba64beSDimitry Andric   return CompilerDecl();
20500b57cec5SDimitry Andric }
20510b57cec5SDimitry Andric 
20520b57cec5SDimitry Andric CompilerDeclContext
20530b57cec5SDimitry Andric SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) {
2054bdd1243dSDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
2055bdd1243dSDimitry Andric   if (auto err = ts_or_err.takeError())
2056bdd1243dSDimitry Andric     return {};
2057bdd1243dSDimitry Andric   auto ts = *ts_or_err;
2058bdd1243dSDimitry Andric   if (!ts)
2059bdd1243dSDimitry Andric     return {};
2060bdd1243dSDimitry Andric 
2061bdd1243dSDimitry Andric   PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
20620b57cec5SDimitry Andric   clang::DeclContext *context =
2063bdd1243dSDimitry Andric       ast_builder->GetOrCreateDeclContextForUid(PdbSymUid(uid));
20640b57cec5SDimitry Andric   if (!context)
20650b57cec5SDimitry Andric     return {};
20660b57cec5SDimitry Andric 
2067bdd1243dSDimitry Andric   return ast_builder->ToCompilerDeclContext(*context);
20680b57cec5SDimitry Andric }
20690b57cec5SDimitry Andric 
20700b57cec5SDimitry Andric CompilerDeclContext
20710b57cec5SDimitry Andric SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
2072bdd1243dSDimitry Andric   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
2073bdd1243dSDimitry Andric   if (auto err = ts_or_err.takeError())
2074bdd1243dSDimitry Andric     return CompilerDeclContext();
2075bdd1243dSDimitry Andric   auto ts = *ts_or_err;
2076bdd1243dSDimitry Andric   if (!ts)
2077bdd1243dSDimitry Andric     return {};
2078bdd1243dSDimitry Andric 
2079bdd1243dSDimitry Andric   PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
2080bdd1243dSDimitry Andric   clang::DeclContext *context = ast_builder->GetParentDeclContext(PdbSymUid(uid));
2081bdd1243dSDimitry Andric   if (!context)
2082bdd1243dSDimitry Andric     return CompilerDeclContext();
2083bdd1243dSDimitry Andric   return ast_builder->ToCompilerDeclContext(*context);
20840b57cec5SDimitry Andric }
20850b57cec5SDimitry Andric 
20860b57cec5SDimitry Andric Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
20879dba64beSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
20880b57cec5SDimitry Andric   auto iter = m_types.find(type_uid);
20890b57cec5SDimitry Andric   // lldb should not be passing us non-sensical type uids.  the only way it
20900b57cec5SDimitry Andric   // could have a type uid in the first place is if we handed it out, in which
20910b57cec5SDimitry Andric   // case we should know about the type.  However, that doesn't mean we've
20920b57cec5SDimitry Andric   // instantiated it yet.  We can vend out a UID for a future type.  So if the
20930b57cec5SDimitry Andric   // type doesn't exist, let's instantiate it now.
20940b57cec5SDimitry Andric   if (iter != m_types.end())
20950b57cec5SDimitry Andric     return &*iter->second;
20960b57cec5SDimitry Andric 
20970b57cec5SDimitry Andric   PdbSymUid uid(type_uid);
20980b57cec5SDimitry Andric   lldbassert(uid.kind() == PdbSymUidKind::Type);
20990b57cec5SDimitry Andric   PdbTypeSymId type_id = uid.asTypeSym();
21000b57cec5SDimitry Andric   if (type_id.index.isNoneType())
21010b57cec5SDimitry Andric     return nullptr;
21020b57cec5SDimitry Andric 
21030b57cec5SDimitry Andric   TypeSP type_sp = CreateAndCacheType(type_id);
2104bdd1243dSDimitry Andric   if (!type_sp)
2105bdd1243dSDimitry Andric     return nullptr;
21060b57cec5SDimitry Andric   return &*type_sp;
21070b57cec5SDimitry Andric }
21080b57cec5SDimitry Andric 
2109bdd1243dSDimitry Andric std::optional<SymbolFile::ArrayInfo>
21100b57cec5SDimitry Andric SymbolFileNativePDB::GetDynamicArrayInfoForUID(
21110b57cec5SDimitry Andric     lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
2112bdd1243dSDimitry Andric   return std::nullopt;
21130b57cec5SDimitry Andric }
21140b57cec5SDimitry Andric 
21150b57cec5SDimitry Andric bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) {
2116bdd1243dSDimitry Andric   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2117bdd1243dSDimitry Andric   auto ts = compiler_type.GetTypeSystem();
2118bdd1243dSDimitry Andric   auto clang_type_system = ts.dyn_cast_or_null<TypeSystemClang>();
2119bdd1243dSDimitry Andric   if (!clang_type_system)
2120bdd1243dSDimitry Andric     return false;
2121bdd1243dSDimitry Andric 
2122bdd1243dSDimitry Andric   PdbAstBuilder *ast_builder =
2123bdd1243dSDimitry Andric       static_cast<PdbAstBuilder *>(clang_type_system->GetNativePDBParser());
2124bdd1243dSDimitry Andric   if (ast_builder &&
2125bdd1243dSDimitry Andric       ast_builder->GetClangASTImporter().CanImport(compiler_type))
2126bdd1243dSDimitry Andric     return ast_builder->GetClangASTImporter().CompleteType(compiler_type);
21270b57cec5SDimitry Andric   clang::QualType qt =
21280b57cec5SDimitry Andric       clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType());
21290b57cec5SDimitry Andric 
2130bdd1243dSDimitry Andric   return ast_builder->CompleteType(qt);
21310b57cec5SDimitry Andric }
21320b57cec5SDimitry Andric 
21339dba64beSDimitry Andric void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
21340b57cec5SDimitry Andric                                    TypeClass type_mask,
21359dba64beSDimitry Andric                                    lldb_private::TypeList &type_list) {}
21360b57cec5SDimitry Andric 
213706c3fb27SDimitry Andric CompilerDeclContext SymbolFileNativePDB::FindNamespace(
213806c3fb27SDimitry Andric     ConstString name, const CompilerDeclContext &parent_decl_ctx, bool) {
21390b57cec5SDimitry Andric   return {};
21400b57cec5SDimitry Andric }
21410b57cec5SDimitry Andric 
2142bdd1243dSDimitry Andric llvm::Expected<lldb::TypeSystemSP>
21430b57cec5SDimitry Andric SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
21449dba64beSDimitry Andric   auto type_system_or_err =
21459dba64beSDimitry Andric       m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language);
2146bdd1243dSDimitry Andric   if (type_system_or_err)
2147bdd1243dSDimitry Andric     if (auto ts = *type_system_or_err)
2148bdd1243dSDimitry Andric       ts->SetSymbolFile(this);
21499dba64beSDimitry Andric   return type_system_or_err;
21500b57cec5SDimitry Andric }
21510b57cec5SDimitry Andric 
2152349cc55cSDimitry Andric uint64_t SymbolFileNativePDB::GetDebugInfoSize() {
2153349cc55cSDimitry Andric   // PDB files are a separate file that contains all debug info.
2154349cc55cSDimitry Andric   return m_index->pdb().getFileSize();
21550b57cec5SDimitry Andric }
2156bdd1243dSDimitry Andric 
2157bdd1243dSDimitry Andric void SymbolFileNativePDB::BuildParentMap() {
2158bdd1243dSDimitry Andric   LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
2159bdd1243dSDimitry Andric 
2160bdd1243dSDimitry Andric   llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full;
2161bdd1243dSDimitry Andric   llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward;
2162bdd1243dSDimitry Andric 
2163bdd1243dSDimitry Andric   struct RecordIndices {
2164bdd1243dSDimitry Andric     TypeIndex forward;
2165bdd1243dSDimitry Andric     TypeIndex full;
2166bdd1243dSDimitry Andric   };
2167bdd1243dSDimitry Andric 
2168bdd1243dSDimitry Andric   llvm::StringMap<RecordIndices> record_indices;
2169bdd1243dSDimitry Andric 
2170bdd1243dSDimitry Andric   for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
2171bdd1243dSDimitry Andric     CVType type = types.getType(*ti);
2172bdd1243dSDimitry Andric     if (!IsTagRecord(type))
2173bdd1243dSDimitry Andric       continue;
2174bdd1243dSDimitry Andric 
2175bdd1243dSDimitry Andric     CVTagRecord tag = CVTagRecord::create(type);
2176bdd1243dSDimitry Andric 
2177bdd1243dSDimitry Andric     RecordIndices &indices = record_indices[tag.asTag().getUniqueName()];
2178bdd1243dSDimitry Andric     if (tag.asTag().isForwardRef())
2179bdd1243dSDimitry Andric       indices.forward = *ti;
2180bdd1243dSDimitry Andric     else
2181bdd1243dSDimitry Andric       indices.full = *ti;
2182bdd1243dSDimitry Andric 
2183bdd1243dSDimitry Andric     if (indices.full != TypeIndex::None() &&
2184bdd1243dSDimitry Andric         indices.forward != TypeIndex::None()) {
2185bdd1243dSDimitry Andric       forward_to_full[indices.forward] = indices.full;
2186bdd1243dSDimitry Andric       full_to_forward[indices.full] = indices.forward;
2187bdd1243dSDimitry Andric     }
2188bdd1243dSDimitry Andric 
2189bdd1243dSDimitry Andric     // We're looking for LF_NESTTYPE records in the field list, so ignore
2190bdd1243dSDimitry Andric     // forward references (no field list), and anything without a nested class
2191bdd1243dSDimitry Andric     // (since there won't be any LF_NESTTYPE records).
2192bdd1243dSDimitry Andric     if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass())
2193bdd1243dSDimitry Andric       continue;
2194bdd1243dSDimitry Andric 
2195bdd1243dSDimitry Andric     struct ProcessTpiStream : public TypeVisitorCallbacks {
2196bdd1243dSDimitry Andric       ProcessTpiStream(PdbIndex &index, TypeIndex parent,
2197bdd1243dSDimitry Andric                        const CVTagRecord &parent_cvt,
2198bdd1243dSDimitry Andric                        llvm::DenseMap<TypeIndex, TypeIndex> &parents)
2199bdd1243dSDimitry Andric           : index(index), parents(parents), parent(parent),
2200bdd1243dSDimitry Andric             parent_cvt(parent_cvt) {}
2201bdd1243dSDimitry Andric 
2202bdd1243dSDimitry Andric       PdbIndex &index;
2203bdd1243dSDimitry Andric       llvm::DenseMap<TypeIndex, TypeIndex> &parents;
2204bdd1243dSDimitry Andric 
2205bdd1243dSDimitry Andric       unsigned unnamed_type_index = 1;
2206bdd1243dSDimitry Andric       TypeIndex parent;
2207bdd1243dSDimitry Andric       const CVTagRecord &parent_cvt;
2208bdd1243dSDimitry Andric 
2209bdd1243dSDimitry Andric       llvm::Error visitKnownMember(CVMemberRecord &CVR,
2210bdd1243dSDimitry Andric                                    NestedTypeRecord &Record) override {
2211bdd1243dSDimitry Andric         std::string unnamed_type_name;
2212bdd1243dSDimitry Andric         if (Record.Name.empty()) {
2213bdd1243dSDimitry Andric           unnamed_type_name =
2214bdd1243dSDimitry Andric               llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str();
2215bdd1243dSDimitry Andric           Record.Name = unnamed_type_name;
2216bdd1243dSDimitry Andric           ++unnamed_type_index;
2217bdd1243dSDimitry Andric         }
2218bdd1243dSDimitry Andric         std::optional<CVTagRecord> tag =
2219bdd1243dSDimitry Andric             GetNestedTagDefinition(Record, parent_cvt, index.tpi());
2220bdd1243dSDimitry Andric         if (!tag)
2221bdd1243dSDimitry Andric           return llvm::ErrorSuccess();
2222bdd1243dSDimitry Andric 
2223bdd1243dSDimitry Andric         parents[Record.Type] = parent;
2224bdd1243dSDimitry Andric         return llvm::ErrorSuccess();
2225bdd1243dSDimitry Andric       }
2226bdd1243dSDimitry Andric     };
2227bdd1243dSDimitry Andric 
2228bdd1243dSDimitry Andric     CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList);
2229bdd1243dSDimitry Andric     ProcessTpiStream process(*m_index, *ti, tag, m_parent_types);
2230bdd1243dSDimitry Andric     FieldListRecord field_list;
2231bdd1243dSDimitry Andric     if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
2232bdd1243dSDimitry Andric             field_list_cvt, field_list))
2233bdd1243dSDimitry Andric       llvm::consumeError(std::move(error));
2234bdd1243dSDimitry Andric     if (llvm::Error error = visitMemberRecordStream(field_list.Data, process))
2235bdd1243dSDimitry Andric       llvm::consumeError(std::move(error));
2236bdd1243dSDimitry Andric   }
2237bdd1243dSDimitry Andric 
2238bdd1243dSDimitry Andric   // Now that we know the forward -> full mapping of all type indices, we can
2239bdd1243dSDimitry Andric   // re-write all the indices.  At the end of this process, we want a mapping
2240bdd1243dSDimitry Andric   // consisting of fwd -> full and full -> full for all child -> parent indices.
2241bdd1243dSDimitry Andric   // We can re-write the values in place, but for the keys, we must save them
2242bdd1243dSDimitry Andric   // off so that we don't modify the map in place while also iterating it.
2243bdd1243dSDimitry Andric   std::vector<TypeIndex> full_keys;
2244bdd1243dSDimitry Andric   std::vector<TypeIndex> fwd_keys;
2245bdd1243dSDimitry Andric   for (auto &entry : m_parent_types) {
2246bdd1243dSDimitry Andric     TypeIndex key = entry.first;
2247bdd1243dSDimitry Andric     TypeIndex value = entry.second;
2248bdd1243dSDimitry Andric 
2249bdd1243dSDimitry Andric     auto iter = forward_to_full.find(value);
2250bdd1243dSDimitry Andric     if (iter != forward_to_full.end())
2251bdd1243dSDimitry Andric       entry.second = iter->second;
2252bdd1243dSDimitry Andric 
2253bdd1243dSDimitry Andric     iter = forward_to_full.find(key);
2254bdd1243dSDimitry Andric     if (iter != forward_to_full.end())
2255bdd1243dSDimitry Andric       fwd_keys.push_back(key);
2256bdd1243dSDimitry Andric     else
2257bdd1243dSDimitry Andric       full_keys.push_back(key);
2258bdd1243dSDimitry Andric   }
2259bdd1243dSDimitry Andric   for (TypeIndex fwd : fwd_keys) {
2260bdd1243dSDimitry Andric     TypeIndex full = forward_to_full[fwd];
2261bdd1243dSDimitry Andric     m_parent_types[full] = m_parent_types[fwd];
2262bdd1243dSDimitry Andric   }
2263bdd1243dSDimitry Andric   for (TypeIndex full : full_keys) {
2264bdd1243dSDimitry Andric     TypeIndex fwd = full_to_forward[full];
2265bdd1243dSDimitry Andric     m_parent_types[fwd] = m_parent_types[full];
2266bdd1243dSDimitry Andric   }
2267bdd1243dSDimitry Andric }
2268bdd1243dSDimitry Andric 
2269bdd1243dSDimitry Andric std::optional<PdbCompilandSymId>
2270bdd1243dSDimitry Andric SymbolFileNativePDB::FindSymbolScope(PdbCompilandSymId id) {
2271bdd1243dSDimitry Andric   CVSymbol sym = m_index->ReadSymbolRecord(id);
2272bdd1243dSDimitry Andric   if (symbolOpensScope(sym.kind())) {
2273bdd1243dSDimitry Andric     // If this exact symbol opens a scope, we can just directly access its
2274bdd1243dSDimitry Andric     // parent.
2275bdd1243dSDimitry Andric     id.offset = getScopeParentOffset(sym);
2276bdd1243dSDimitry Andric     // Global symbols have parent offset of 0.  Return std::nullopt to indicate
2277bdd1243dSDimitry Andric     // this.
2278bdd1243dSDimitry Andric     if (id.offset == 0)
2279bdd1243dSDimitry Andric       return std::nullopt;
2280bdd1243dSDimitry Andric     return id;
2281bdd1243dSDimitry Andric   }
2282bdd1243dSDimitry Andric 
2283bdd1243dSDimitry Andric   // Otherwise we need to start at the beginning and iterate forward until we
2284bdd1243dSDimitry Andric   // reach (or pass) this particular symbol
2285bdd1243dSDimitry Andric   CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(id.modi);
2286bdd1243dSDimitry Andric   const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
2287bdd1243dSDimitry Andric 
2288bdd1243dSDimitry Andric   auto begin = syms.begin();
2289bdd1243dSDimitry Andric   auto end = syms.at(id.offset);
2290bdd1243dSDimitry Andric   std::vector<PdbCompilandSymId> scope_stack;
2291bdd1243dSDimitry Andric 
2292bdd1243dSDimitry Andric   while (begin != end) {
2293bdd1243dSDimitry Andric     if (begin.offset() > id.offset) {
2294bdd1243dSDimitry Andric       // We passed it.  We couldn't even find this symbol record.
2295bdd1243dSDimitry Andric       lldbassert(false && "Invalid compiland symbol id!");
2296bdd1243dSDimitry Andric       return std::nullopt;
2297bdd1243dSDimitry Andric     }
2298bdd1243dSDimitry Andric 
2299bdd1243dSDimitry Andric     // We haven't found the symbol yet.  Check if we need to open or close the
2300bdd1243dSDimitry Andric     // scope stack.
2301bdd1243dSDimitry Andric     if (symbolOpensScope(begin->kind())) {
2302bdd1243dSDimitry Andric       // We can use the end offset of the scope to determine whether or not
2303bdd1243dSDimitry Andric       // we can just outright skip this entire scope.
2304bdd1243dSDimitry Andric       uint32_t scope_end = getScopeEndOffset(*begin);
2305bdd1243dSDimitry Andric       if (scope_end < id.offset) {
2306bdd1243dSDimitry Andric         begin = syms.at(scope_end);
2307bdd1243dSDimitry Andric       } else {
2308bdd1243dSDimitry Andric         // The symbol we're looking for is somewhere in this scope.
2309bdd1243dSDimitry Andric         scope_stack.emplace_back(id.modi, begin.offset());
2310bdd1243dSDimitry Andric       }
2311bdd1243dSDimitry Andric     } else if (symbolEndsScope(begin->kind())) {
2312bdd1243dSDimitry Andric       scope_stack.pop_back();
2313bdd1243dSDimitry Andric     }
2314bdd1243dSDimitry Andric     ++begin;
2315bdd1243dSDimitry Andric   }
2316bdd1243dSDimitry Andric   if (scope_stack.empty())
2317bdd1243dSDimitry Andric     return std::nullopt;
2318bdd1243dSDimitry Andric   // We have a match!  Return the top of the stack
2319bdd1243dSDimitry Andric   return scope_stack.back();
2320bdd1243dSDimitry Andric }
2321bdd1243dSDimitry Andric 
2322bdd1243dSDimitry Andric std::optional<llvm::codeview::TypeIndex>
2323bdd1243dSDimitry Andric SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) {
2324bdd1243dSDimitry Andric   auto parent_iter = m_parent_types.find(ti);
2325bdd1243dSDimitry Andric   if (parent_iter == m_parent_types.end())
2326bdd1243dSDimitry Andric     return std::nullopt;
2327bdd1243dSDimitry Andric   return parent_iter->second;
2328bdd1243dSDimitry Andric }
2329