xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- SymbolFileNativePDB.cpp -------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "SymbolFileNativePDB.h"
10061da546Spatrick 
11dda28197Spatrick #include "Plugins/ExpressionParser/Clang/ClangUtil.h"
12061da546Spatrick #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
13be691f3bSpatrick #include "Plugins/ObjectFile/PDB/ObjectFilePDB.h"
14dda28197Spatrick #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
15061da546Spatrick #include "lldb/Core/Module.h"
16061da546Spatrick #include "lldb/Core/PluginManager.h"
17061da546Spatrick #include "lldb/Core/StreamBuffer.h"
18061da546Spatrick #include "lldb/Core/StreamFile.h"
19061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
20061da546Spatrick #include "lldb/Symbol/LineTable.h"
21061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
22061da546Spatrick #include "lldb/Symbol/SymbolContext.h"
23061da546Spatrick #include "lldb/Symbol/SymbolVendor.h"
24061da546Spatrick #include "lldb/Symbol/Variable.h"
25061da546Spatrick #include "lldb/Symbol/VariableList.h"
26*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
27061da546Spatrick #include "lldb/Utility/Log.h"
28061da546Spatrick 
29061da546Spatrick #include "llvm/DebugInfo/CodeView/CVRecord.h"
30061da546Spatrick #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
31061da546Spatrick #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
32061da546Spatrick #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
33061da546Spatrick #include "llvm/DebugInfo/CodeView/RecordName.h"
34061da546Spatrick #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
35061da546Spatrick #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
36061da546Spatrick #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
37061da546Spatrick #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
38061da546Spatrick #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
39061da546Spatrick #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
40061da546Spatrick #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
41be691f3bSpatrick #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
42061da546Spatrick #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
43061da546Spatrick #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
44061da546Spatrick #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
45be691f3bSpatrick #include "llvm/DebugInfo/PDB/PDB.h"
46061da546Spatrick #include "llvm/DebugInfo/PDB/PDBTypes.h"
47061da546Spatrick #include "llvm/Demangle/MicrosoftDemangle.h"
48061da546Spatrick #include "llvm/Object/COFF.h"
49061da546Spatrick #include "llvm/Support/Allocator.h"
50061da546Spatrick #include "llvm/Support/BinaryStreamReader.h"
51061da546Spatrick #include "llvm/Support/Error.h"
52061da546Spatrick #include "llvm/Support/ErrorOr.h"
53061da546Spatrick #include "llvm/Support/MemoryBuffer.h"
54061da546Spatrick 
55061da546Spatrick #include "DWARFLocationExpression.h"
56061da546Spatrick #include "PdbSymUid.h"
57061da546Spatrick #include "PdbUtil.h"
58061da546Spatrick #include "UdtRecordCompleter.h"
59*f6aab3d8Srobert #include <optional>
60061da546Spatrick 
61061da546Spatrick using namespace lldb;
62061da546Spatrick using namespace lldb_private;
63061da546Spatrick using namespace npdb;
64061da546Spatrick using namespace llvm::codeview;
65061da546Spatrick using namespace llvm::pdb;
66061da546Spatrick 
67061da546Spatrick char SymbolFileNativePDB::ID;
68061da546Spatrick 
TranslateLanguage(PDB_Lang lang)69061da546Spatrick static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
70061da546Spatrick   switch (lang) {
71061da546Spatrick   case PDB_Lang::Cpp:
72061da546Spatrick     return lldb::LanguageType::eLanguageTypeC_plus_plus;
73061da546Spatrick   case PDB_Lang::C:
74061da546Spatrick     return lldb::LanguageType::eLanguageTypeC;
75061da546Spatrick   case PDB_Lang::Swift:
76061da546Spatrick     return lldb::LanguageType::eLanguageTypeSwift;
77*f6aab3d8Srobert   case PDB_Lang::Rust:
78*f6aab3d8Srobert     return lldb::LanguageType::eLanguageTypeRust;
79061da546Spatrick   default:
80061da546Spatrick     return lldb::LanguageType::eLanguageTypeUnknown;
81061da546Spatrick   }
82061da546Spatrick }
83061da546Spatrick 
84061da546Spatrick static std::unique_ptr<PDBFile>
loadMatchingPDBFile(std::string exe_path,llvm::BumpPtrAllocator & allocator)85061da546Spatrick loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
86061da546Spatrick   // Try to find a matching PDB for an EXE.
87061da546Spatrick   using namespace llvm::object;
88061da546Spatrick   auto expected_binary = createBinary(exe_path);
89061da546Spatrick 
90061da546Spatrick   // If the file isn't a PE/COFF executable, fail.
91061da546Spatrick   if (!expected_binary) {
92061da546Spatrick     llvm::consumeError(expected_binary.takeError());
93061da546Spatrick     return nullptr;
94061da546Spatrick   }
95061da546Spatrick   OwningBinary<Binary> binary = std::move(*expected_binary);
96061da546Spatrick 
97061da546Spatrick   // TODO: Avoid opening the PE/COFF binary twice by reading this information
98061da546Spatrick   // directly from the lldb_private::ObjectFile.
99061da546Spatrick   auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary());
100061da546Spatrick   if (!obj)
101061da546Spatrick     return nullptr;
102061da546Spatrick   const llvm::codeview::DebugInfo *pdb_info = nullptr;
103061da546Spatrick 
104061da546Spatrick   // If it doesn't have a debug directory, fail.
105061da546Spatrick   llvm::StringRef pdb_file;
106dda28197Spatrick   if (llvm::Error e = obj->getDebugPDBInfo(pdb_info, pdb_file)) {
107dda28197Spatrick     consumeError(std::move(e));
108061da546Spatrick     return nullptr;
109dda28197Spatrick   }
110061da546Spatrick 
111be691f3bSpatrick   // If the file doesn't exist, perhaps the path specified at build time
112be691f3bSpatrick   // doesn't match the PDB's current location, so check the location of the
113be691f3bSpatrick   // executable.
114be691f3bSpatrick   if (!FileSystem::Instance().Exists(pdb_file)) {
115be691f3bSpatrick     const auto exe_dir = FileSpec(exe_path).CopyByRemovingLastPathComponent();
116be691f3bSpatrick     const auto pdb_name = FileSpec(pdb_file).GetFilename().GetCString();
117*f6aab3d8Srobert     pdb_file = exe_dir.CopyByAppendingPathComponent(pdb_name).GetPathAsConstString().GetStringRef();
118be691f3bSpatrick   }
119be691f3bSpatrick 
120be691f3bSpatrick   // If the file is not a PDB or if it doesn't have a matching GUID, fail.
121be691f3bSpatrick   auto pdb = ObjectFilePDB::loadPDBFile(std::string(pdb_file), allocator);
122061da546Spatrick   if (!pdb)
123061da546Spatrick     return nullptr;
124061da546Spatrick 
125061da546Spatrick   auto expected_info = pdb->getPDBInfoStream();
126061da546Spatrick   if (!expected_info) {
127061da546Spatrick     llvm::consumeError(expected_info.takeError());
128061da546Spatrick     return nullptr;
129061da546Spatrick   }
130061da546Spatrick   llvm::codeview::GUID guid;
131061da546Spatrick   memcpy(&guid, pdb_info->PDB70.Signature, 16);
132061da546Spatrick 
133061da546Spatrick   if (expected_info->getGuid() != guid)
134061da546Spatrick     return nullptr;
135061da546Spatrick   return pdb;
136061da546Spatrick }
137061da546Spatrick 
IsFunctionPrologue(const CompilandIndexItem & cci,lldb::addr_t addr)138061da546Spatrick static bool IsFunctionPrologue(const CompilandIndexItem &cci,
139061da546Spatrick                                lldb::addr_t addr) {
140061da546Spatrick   // FIXME: Implement this.
141061da546Spatrick   return false;
142061da546Spatrick }
143061da546Spatrick 
IsFunctionEpilogue(const CompilandIndexItem & cci,lldb::addr_t addr)144061da546Spatrick static bool IsFunctionEpilogue(const CompilandIndexItem &cci,
145061da546Spatrick                                lldb::addr_t addr) {
146061da546Spatrick   // FIXME: Implement this.
147061da546Spatrick   return false;
148061da546Spatrick }
149061da546Spatrick 
GetSimpleTypeName(SimpleTypeKind kind)150061da546Spatrick static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) {
151061da546Spatrick   switch (kind) {
152061da546Spatrick   case SimpleTypeKind::Boolean128:
153061da546Spatrick   case SimpleTypeKind::Boolean16:
154061da546Spatrick   case SimpleTypeKind::Boolean32:
155061da546Spatrick   case SimpleTypeKind::Boolean64:
156061da546Spatrick   case SimpleTypeKind::Boolean8:
157061da546Spatrick     return "bool";
158061da546Spatrick   case SimpleTypeKind::Byte:
159061da546Spatrick   case SimpleTypeKind::UnsignedCharacter:
160061da546Spatrick     return "unsigned char";
161061da546Spatrick   case SimpleTypeKind::NarrowCharacter:
162061da546Spatrick     return "char";
163061da546Spatrick   case SimpleTypeKind::SignedCharacter:
164061da546Spatrick   case SimpleTypeKind::SByte:
165061da546Spatrick     return "signed char";
166061da546Spatrick   case SimpleTypeKind::Character16:
167061da546Spatrick     return "char16_t";
168061da546Spatrick   case SimpleTypeKind::Character32:
169061da546Spatrick     return "char32_t";
170*f6aab3d8Srobert   case SimpleTypeKind::Character8:
171*f6aab3d8Srobert     return "char8_t";
172061da546Spatrick   case SimpleTypeKind::Complex80:
173061da546Spatrick   case SimpleTypeKind::Complex64:
174061da546Spatrick   case SimpleTypeKind::Complex32:
175061da546Spatrick     return "complex";
176061da546Spatrick   case SimpleTypeKind::Float128:
177061da546Spatrick   case SimpleTypeKind::Float80:
178061da546Spatrick     return "long double";
179061da546Spatrick   case SimpleTypeKind::Float64:
180061da546Spatrick     return "double";
181061da546Spatrick   case SimpleTypeKind::Float32:
182061da546Spatrick     return "float";
183061da546Spatrick   case SimpleTypeKind::Float16:
184061da546Spatrick     return "single";
185061da546Spatrick   case SimpleTypeKind::Int128:
186061da546Spatrick     return "__int128";
187061da546Spatrick   case SimpleTypeKind::Int64:
188061da546Spatrick   case SimpleTypeKind::Int64Quad:
189061da546Spatrick     return "int64_t";
190061da546Spatrick   case SimpleTypeKind::Int32:
191061da546Spatrick     return "int";
192061da546Spatrick   case SimpleTypeKind::Int16:
193061da546Spatrick     return "short";
194061da546Spatrick   case SimpleTypeKind::UInt128:
195061da546Spatrick     return "unsigned __int128";
196061da546Spatrick   case SimpleTypeKind::UInt64:
197061da546Spatrick   case SimpleTypeKind::UInt64Quad:
198061da546Spatrick     return "uint64_t";
199061da546Spatrick   case SimpleTypeKind::HResult:
200061da546Spatrick     return "HRESULT";
201061da546Spatrick   case SimpleTypeKind::UInt32:
202061da546Spatrick     return "unsigned";
203061da546Spatrick   case SimpleTypeKind::UInt16:
204061da546Spatrick   case SimpleTypeKind::UInt16Short:
205061da546Spatrick     return "unsigned short";
206061da546Spatrick   case SimpleTypeKind::Int32Long:
207061da546Spatrick     return "long";
208061da546Spatrick   case SimpleTypeKind::UInt32Long:
209061da546Spatrick     return "unsigned long";
210061da546Spatrick   case SimpleTypeKind::Void:
211061da546Spatrick     return "void";
212061da546Spatrick   case SimpleTypeKind::WideCharacter:
213061da546Spatrick     return "wchar_t";
214061da546Spatrick   default:
215061da546Spatrick     return "";
216061da546Spatrick   }
217061da546Spatrick }
218061da546Spatrick 
IsClassRecord(TypeLeafKind kind)219061da546Spatrick static bool IsClassRecord(TypeLeafKind kind) {
220061da546Spatrick   switch (kind) {
221061da546Spatrick   case LF_STRUCTURE:
222061da546Spatrick   case LF_CLASS:
223061da546Spatrick   case LF_INTERFACE:
224061da546Spatrick     return true;
225061da546Spatrick   default:
226061da546Spatrick     return false;
227061da546Spatrick   }
228061da546Spatrick }
229061da546Spatrick 
230*f6aab3d8Srobert static std::optional<CVTagRecord>
GetNestedTagDefinition(const NestedTypeRecord & Record,const CVTagRecord & parent,TpiStream & tpi)231*f6aab3d8Srobert GetNestedTagDefinition(const NestedTypeRecord &Record,
232*f6aab3d8Srobert                        const CVTagRecord &parent, TpiStream &tpi) {
233*f6aab3d8Srobert   // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it
234*f6aab3d8Srobert   // is also used to indicate the primary definition of a nested class.  That is
235*f6aab3d8Srobert   // to say, if you have:
236*f6aab3d8Srobert   // struct A {
237*f6aab3d8Srobert   //   struct B {};
238*f6aab3d8Srobert   //   using C = B;
239*f6aab3d8Srobert   // };
240*f6aab3d8Srobert   // Then in the debug info, this will appear as:
241*f6aab3d8Srobert   // LF_STRUCTURE `A::B` [type index = N]
242*f6aab3d8Srobert   // LF_STRUCTURE `A`
243*f6aab3d8Srobert   //   LF_NESTTYPE [name = `B`, index = N]
244*f6aab3d8Srobert   //   LF_NESTTYPE [name = `C`, index = N]
245*f6aab3d8Srobert   // In order to accurately reconstruct the decl context hierarchy, we need to
246*f6aab3d8Srobert   // know which ones are actual definitions and which ones are just aliases.
247*f6aab3d8Srobert 
248*f6aab3d8Srobert   // If it's a simple type, then this is something like `using foo = int`.
249*f6aab3d8Srobert   if (Record.Type.isSimple())
250*f6aab3d8Srobert     return std::nullopt;
251*f6aab3d8Srobert 
252*f6aab3d8Srobert   CVType cvt = tpi.getType(Record.Type);
253*f6aab3d8Srobert 
254*f6aab3d8Srobert   if (!IsTagRecord(cvt))
255*f6aab3d8Srobert     return std::nullopt;
256*f6aab3d8Srobert 
257*f6aab3d8Srobert   // If it's an inner definition, then treat whatever name we have here as a
258*f6aab3d8Srobert   // single component of a mangled name.  So we can inject it into the parent's
259*f6aab3d8Srobert   // mangled name to see if it matches.
260*f6aab3d8Srobert   CVTagRecord child = CVTagRecord::create(cvt);
261*f6aab3d8Srobert   std::string qname = std::string(parent.asTag().getUniqueName());
262*f6aab3d8Srobert   if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4)
263*f6aab3d8Srobert     return std::nullopt;
264*f6aab3d8Srobert 
265*f6aab3d8Srobert   // qname[3] is the tag type identifier (struct, class, union, etc).  Since the
266*f6aab3d8Srobert   // inner tag type is not necessarily the same as the outer tag type, re-write
267*f6aab3d8Srobert   // it to match the inner tag type.
268*f6aab3d8Srobert   qname[3] = child.asTag().getUniqueName()[3];
269*f6aab3d8Srobert   std::string piece;
270*f6aab3d8Srobert   if (qname[3] == 'W')
271*f6aab3d8Srobert     piece = "4";
272*f6aab3d8Srobert   piece += Record.Name;
273*f6aab3d8Srobert   piece.push_back('@');
274*f6aab3d8Srobert   qname.insert(4, std::move(piece));
275*f6aab3d8Srobert   if (qname != child.asTag().UniqueName)
276*f6aab3d8Srobert     return std::nullopt;
277*f6aab3d8Srobert 
278*f6aab3d8Srobert   return std::move(child);
279*f6aab3d8Srobert }
280*f6aab3d8Srobert 
Initialize()281061da546Spatrick void SymbolFileNativePDB::Initialize() {
282061da546Spatrick   PluginManager::RegisterPlugin(GetPluginNameStatic(),
283061da546Spatrick                                 GetPluginDescriptionStatic(), CreateInstance,
284061da546Spatrick                                 DebuggerInitialize);
285061da546Spatrick }
286061da546Spatrick 
Terminate()287061da546Spatrick void SymbolFileNativePDB::Terminate() {
288061da546Spatrick   PluginManager::UnregisterPlugin(CreateInstance);
289061da546Spatrick }
290061da546Spatrick 
DebuggerInitialize(Debugger & debugger)291061da546Spatrick void SymbolFileNativePDB::DebuggerInitialize(Debugger &debugger) {}
292061da546Spatrick 
GetPluginDescriptionStatic()293*f6aab3d8Srobert llvm::StringRef SymbolFileNativePDB::GetPluginDescriptionStatic() {
294061da546Spatrick   return "Microsoft PDB debug symbol cross-platform file reader.";
295061da546Spatrick }
296061da546Spatrick 
CreateInstance(ObjectFileSP objfile_sp)297061da546Spatrick SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFileSP objfile_sp) {
298061da546Spatrick   return new SymbolFileNativePDB(std::move(objfile_sp));
299061da546Spatrick }
300061da546Spatrick 
SymbolFileNativePDB(ObjectFileSP objfile_sp)301061da546Spatrick SymbolFileNativePDB::SymbolFileNativePDB(ObjectFileSP objfile_sp)
302*f6aab3d8Srobert     : SymbolFileCommon(std::move(objfile_sp)) {}
303061da546Spatrick 
304be691f3bSpatrick SymbolFileNativePDB::~SymbolFileNativePDB() = default;
305061da546Spatrick 
CalculateAbilities()306061da546Spatrick uint32_t SymbolFileNativePDB::CalculateAbilities() {
307061da546Spatrick   uint32_t abilities = 0;
308061da546Spatrick   if (!m_objfile_sp)
309061da546Spatrick     return 0;
310061da546Spatrick 
311061da546Spatrick   if (!m_index) {
312061da546Spatrick     // Lazily load and match the PDB file, but only do this once.
313be691f3bSpatrick     PDBFile *pdb_file;
314be691f3bSpatrick     if (auto *pdb = llvm::dyn_cast<ObjectFilePDB>(m_objfile_sp.get())) {
315be691f3bSpatrick       pdb_file = &pdb->GetPDBFile();
316be691f3bSpatrick     } else {
317be691f3bSpatrick       m_file_up = loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(),
318be691f3bSpatrick                                       m_allocator);
319be691f3bSpatrick       pdb_file = m_file_up.get();
320061da546Spatrick     }
321061da546Spatrick 
322be691f3bSpatrick     if (!pdb_file)
323061da546Spatrick       return 0;
324061da546Spatrick 
325be691f3bSpatrick     auto expected_index = PdbIndex::create(pdb_file);
326061da546Spatrick     if (!expected_index) {
327061da546Spatrick       llvm::consumeError(expected_index.takeError());
328061da546Spatrick       return 0;
329061da546Spatrick     }
330061da546Spatrick     m_index = std::move(*expected_index);
331061da546Spatrick   }
332061da546Spatrick   if (!m_index)
333061da546Spatrick     return 0;
334061da546Spatrick 
335061da546Spatrick   // We don't especially have to be precise here.  We only distinguish between
336061da546Spatrick   // stripped and not stripped.
337061da546Spatrick   abilities = kAllAbilities;
338061da546Spatrick 
339061da546Spatrick   if (m_index->dbi().isStripped())
340061da546Spatrick     abilities &= ~(Blocks | LocalVariables);
341061da546Spatrick   return abilities;
342061da546Spatrick }
343061da546Spatrick 
InitializeObject()344061da546Spatrick void SymbolFileNativePDB::InitializeObject() {
345be691f3bSpatrick   m_obj_load_address = m_objfile_sp->GetModule()
346be691f3bSpatrick                            ->GetObjectFile()
347be691f3bSpatrick                            ->GetBaseAddress()
348be691f3bSpatrick                            .GetFileAddress();
349061da546Spatrick   m_index->SetLoadAddress(m_obj_load_address);
350061da546Spatrick   m_index->ParseSectionContribs();
351061da546Spatrick 
352061da546Spatrick   auto ts_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage(
353061da546Spatrick       lldb::eLanguageTypeC_plus_plus);
354061da546Spatrick   if (auto err = ts_or_err.takeError()) {
355*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
356*f6aab3d8Srobert                    "Failed to initialize");
357061da546Spatrick   } else {
358*f6aab3d8Srobert     if (auto ts = *ts_or_err)
359*f6aab3d8Srobert       ts->SetSymbolFile(this);
360*f6aab3d8Srobert     BuildParentMap();
361061da546Spatrick   }
362061da546Spatrick }
363061da546Spatrick 
CalculateNumCompileUnits()364061da546Spatrick uint32_t SymbolFileNativePDB::CalculateNumCompileUnits() {
365061da546Spatrick   const DbiModuleList &modules = m_index->dbi().modules();
366061da546Spatrick   uint32_t count = modules.getModuleCount();
367061da546Spatrick   if (count == 0)
368061da546Spatrick     return count;
369061da546Spatrick 
370061da546Spatrick   // The linker can inject an additional "dummy" compilation unit into the
371061da546Spatrick   // PDB. Ignore this special compile unit for our purposes, if it is there.
372061da546Spatrick   // It is always the last one.
373061da546Spatrick   DbiModuleDescriptor last = modules.getModuleDescriptor(count - 1);
374061da546Spatrick   if (last.getModuleName() == "* Linker *")
375061da546Spatrick     --count;
376061da546Spatrick   return count;
377061da546Spatrick }
378061da546Spatrick 
CreateBlock(PdbCompilandSymId block_id)379061da546Spatrick Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
380061da546Spatrick   CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
381061da546Spatrick   CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
382061da546Spatrick   CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
383*f6aab3d8Srobert   lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id);
384*f6aab3d8Srobert   BlockSP child_block = std::make_shared<Block>(opaque_block_uid);
385*f6aab3d8Srobert   auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
386*f6aab3d8Srobert   if (auto err = ts_or_err.takeError())
387*f6aab3d8Srobert     return *child_block;
388*f6aab3d8Srobert   auto ts = *ts_or_err;
389*f6aab3d8Srobert   if (!ts)
390*f6aab3d8Srobert     return *child_block;
391*f6aab3d8Srobert   PdbAstBuilder* ast_builder = ts->GetNativePDBParser();
392*f6aab3d8Srobert 
393*f6aab3d8Srobert   switch (sym.kind()) {
394*f6aab3d8Srobert   case S_GPROC32:
395*f6aab3d8Srobert   case S_LPROC32: {
396*f6aab3d8Srobert     // This is a function.  It must be global.  Creating the Function entry
397*f6aab3d8Srobert     // for it automatically creates a block for it.
398*f6aab3d8Srobert     FunctionSP func = GetOrCreateFunction(block_id, *comp_unit);
399*f6aab3d8Srobert     if (func) {
400*f6aab3d8Srobert       Block &block = func->GetBlock(false);
401*f6aab3d8Srobert       if (block.GetNumRanges() == 0)
402*f6aab3d8Srobert         block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize()));
403*f6aab3d8Srobert       return block;
404061da546Spatrick     }
405*f6aab3d8Srobert     break;
406*f6aab3d8Srobert   }
407*f6aab3d8Srobert   case S_BLOCK32: {
408061da546Spatrick     // This is a block.  Its parent is either a function or another block.  In
409*f6aab3d8Srobert     // either case, its parent can be viewed as a block (e.g. a function
410*f6aab3d8Srobert     // contains 1 big block.  So just get the parent block and add this block
411*f6aab3d8Srobert     // to it.
412061da546Spatrick     BlockSym block(static_cast<SymbolRecordKind>(sym.kind()));
413061da546Spatrick     cantFail(SymbolDeserializer::deserializeAs<BlockSym>(sym, block));
414061da546Spatrick     lldbassert(block.Parent != 0);
415061da546Spatrick     PdbCompilandSymId parent_id(block_id.modi, block.Parent);
416061da546Spatrick     Block &parent_block = GetOrCreateBlock(parent_id);
417*f6aab3d8Srobert     Function *func = parent_block.CalculateSymbolContextFunction();
418*f6aab3d8Srobert     lldbassert(func);
419*f6aab3d8Srobert     lldb::addr_t block_base =
420*f6aab3d8Srobert         m_index->MakeVirtualAddress(block.Segment, block.CodeOffset);
421*f6aab3d8Srobert     lldb::addr_t func_base =
422*f6aab3d8Srobert         func->GetAddressRange().GetBaseAddress().GetFileAddress();
423*f6aab3d8Srobert     if (block_base >= func_base)
424*f6aab3d8Srobert       child_block->AddRange(Block::Range(block_base - func_base, block.CodeSize));
425*f6aab3d8Srobert     else {
426*f6aab3d8Srobert       GetObjectFile()->GetModule()->ReportError(
427*f6aab3d8Srobert           "S_BLOCK32 at modi: {0:d} offset: {1:d}: adding range "
428*f6aab3d8Srobert           "[{2:x16}-{3:x16}) which has a base that is less than the "
429*f6aab3d8Srobert           "function's "
430*f6aab3d8Srobert           "low PC 0x%" PRIx64 ". Please file a bug and attach the file at the "
431*f6aab3d8Srobert           "start of this error message",
432*f6aab3d8Srobert           block_id.modi, block_id.offset, block_base,
433*f6aab3d8Srobert           block_base + block.CodeSize, func_base);
434*f6aab3d8Srobert     }
435061da546Spatrick     parent_block.AddChild(child_block);
436*f6aab3d8Srobert     ast_builder->GetOrCreateBlockDecl(block_id);
437061da546Spatrick     m_blocks.insert({opaque_block_uid, child_block});
438*f6aab3d8Srobert     break;
439*f6aab3d8Srobert   }
440*f6aab3d8Srobert   case S_INLINESITE: {
441*f6aab3d8Srobert     // This ensures line table is parsed first so we have inline sites info.
442*f6aab3d8Srobert     comp_unit->GetLineTable();
443*f6aab3d8Srobert 
444*f6aab3d8Srobert     std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid];
445*f6aab3d8Srobert     Block &parent_block = GetOrCreateBlock(inline_site->parent_id);
446*f6aab3d8Srobert     parent_block.AddChild(child_block);
447*f6aab3d8Srobert     ast_builder->GetOrCreateInlinedFunctionDecl(block_id);
448*f6aab3d8Srobert     // Copy ranges from InlineSite to Block.
449*f6aab3d8Srobert     for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) {
450*f6aab3d8Srobert       auto *entry = inline_site->ranges.GetEntryAtIndex(i);
451*f6aab3d8Srobert       child_block->AddRange(
452*f6aab3d8Srobert           Block::Range(entry->GetRangeBase(), entry->GetByteSize()));
453*f6aab3d8Srobert     }
454*f6aab3d8Srobert     child_block->FinalizeRanges();
455*f6aab3d8Srobert 
456*f6aab3d8Srobert     // Get the inlined function callsite info.
457*f6aab3d8Srobert     Declaration &decl = inline_site->inline_function_info->GetDeclaration();
458*f6aab3d8Srobert     Declaration &callsite = inline_site->inline_function_info->GetCallSite();
459*f6aab3d8Srobert     child_block->SetInlinedFunctionInfo(
460*f6aab3d8Srobert         inline_site->inline_function_info->GetName().GetCString(), nullptr,
461*f6aab3d8Srobert         &decl, &callsite);
462*f6aab3d8Srobert     m_blocks.insert({opaque_block_uid, child_block});
463*f6aab3d8Srobert     break;
464*f6aab3d8Srobert   }
465*f6aab3d8Srobert   default:
466*f6aab3d8Srobert     lldbassert(false && "Symbol is not a block!");
467*f6aab3d8Srobert   }
468*f6aab3d8Srobert 
469061da546Spatrick   return *child_block;
470061da546Spatrick }
471061da546Spatrick 
CreateFunction(PdbCompilandSymId func_id,CompileUnit & comp_unit)472061da546Spatrick lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
473061da546Spatrick                                                      CompileUnit &comp_unit) {
474061da546Spatrick   const CompilandIndexItem *cci =
475061da546Spatrick       m_index->compilands().GetCompiland(func_id.modi);
476061da546Spatrick   lldbassert(cci);
477061da546Spatrick   CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);
478061da546Spatrick 
479061da546Spatrick   lldbassert(sym_record.kind() == S_LPROC32 || sym_record.kind() == S_GPROC32);
480061da546Spatrick   SegmentOffsetLength sol = GetSegmentOffsetAndLength(sym_record);
481061da546Spatrick 
482*f6aab3d8Srobert   auto file_vm_addr =
483*f6aab3d8Srobert       m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);
484061da546Spatrick   if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
485061da546Spatrick     return nullptr;
486061da546Spatrick 
487061da546Spatrick   AddressRange func_range(file_vm_addr, sol.length,
488061da546Spatrick                           comp_unit.GetModule()->GetSectionList());
489061da546Spatrick   if (!func_range.GetBaseAddress().IsValid())
490061da546Spatrick     return nullptr;
491061da546Spatrick 
492061da546Spatrick   ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
493061da546Spatrick   cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));
494061da546Spatrick   if (proc.FunctionType == TypeIndex::None())
495061da546Spatrick     return nullptr;
496061da546Spatrick   TypeSP func_type = GetOrCreateType(proc.FunctionType);
497061da546Spatrick   if (!func_type)
498061da546Spatrick     return nullptr;
499061da546Spatrick 
500061da546Spatrick   PdbTypeSymId sig_id(proc.FunctionType, false);
501061da546Spatrick   Mangled mangled(proc.Name);
502061da546Spatrick   FunctionSP func_sp = std::make_shared<Function>(
503061da546Spatrick       &comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled,
504061da546Spatrick       func_type.get(), func_range);
505061da546Spatrick 
506061da546Spatrick   comp_unit.AddFunction(func_sp);
507061da546Spatrick 
508*f6aab3d8Srobert   auto ts_or_err = GetTypeSystemForLanguage(comp_unit.GetLanguage());
509*f6aab3d8Srobert   if (auto err = ts_or_err.takeError())
510*f6aab3d8Srobert     return func_sp;
511*f6aab3d8Srobert   auto ts = *ts_or_err;
512*f6aab3d8Srobert   if (!ts)
513*f6aab3d8Srobert     return func_sp;
514*f6aab3d8Srobert   ts->GetNativePDBParser()->GetOrCreateFunctionDecl(func_id);
515061da546Spatrick 
516061da546Spatrick   return func_sp;
517061da546Spatrick }
518061da546Spatrick 
519061da546Spatrick CompUnitSP
CreateCompileUnit(const CompilandIndexItem & cci)520061da546Spatrick SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) {
521061da546Spatrick   lldb::LanguageType lang =
522061da546Spatrick       cci.m_compile_opts ? TranslateLanguage(cci.m_compile_opts->getLanguage())
523061da546Spatrick                          : lldb::eLanguageTypeUnknown;
524061da546Spatrick 
525061da546Spatrick   LazyBool optimized = eLazyBoolNo;
526061da546Spatrick   if (cci.m_compile_opts && cci.m_compile_opts->hasOptimizations())
527061da546Spatrick     optimized = eLazyBoolYes;
528061da546Spatrick 
529061da546Spatrick   llvm::SmallString<64> source_file_name =
530061da546Spatrick       m_index->compilands().GetMainSourceFile(cci);
531*f6aab3d8Srobert   FileSpec fs(llvm::sys::path::convert_to_slash(
532*f6aab3d8Srobert       source_file_name, llvm::sys::path::Style::windows_backslash));
533061da546Spatrick 
534061da546Spatrick   CompUnitSP cu_sp =
535061da546Spatrick       std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), nullptr, fs,
536061da546Spatrick                                     toOpaqueUid(cci.m_id), lang, optimized);
537061da546Spatrick 
538061da546Spatrick   SetCompileUnitAtIndex(cci.m_id.modi, cu_sp);
539061da546Spatrick   return cu_sp;
540061da546Spatrick }
541061da546Spatrick 
CreateModifierType(PdbTypeSymId type_id,const ModifierRecord & mr,CompilerType ct)542061da546Spatrick lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id,
543061da546Spatrick                                                      const ModifierRecord &mr,
544061da546Spatrick                                                      CompilerType ct) {
545061da546Spatrick   TpiStream &stream = m_index->tpi();
546061da546Spatrick 
547061da546Spatrick   std::string name;
548061da546Spatrick   if (mr.ModifiedType.isSimple())
549dda28197Spatrick     name = std::string(GetSimpleTypeName(mr.ModifiedType.getSimpleKind()));
550061da546Spatrick   else
551061da546Spatrick     name = computeTypeName(stream.typeCollection(), mr.ModifiedType);
552061da546Spatrick   Declaration decl;
553061da546Spatrick   lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType);
554061da546Spatrick 
555*f6aab3d8Srobert   return MakeType(toOpaqueUid(type_id), ConstString(name),
556be691f3bSpatrick                   modified_type->GetByteSize(nullptr), nullptr,
557*f6aab3d8Srobert                   LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
558*f6aab3d8Srobert                   Type::ResolveState::Full);
559061da546Spatrick }
560061da546Spatrick 
561061da546Spatrick lldb::TypeSP
CreatePointerType(PdbTypeSymId type_id,const llvm::codeview::PointerRecord & pr,CompilerType ct)562061da546Spatrick SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id,
563061da546Spatrick                                        const llvm::codeview::PointerRecord &pr,
564061da546Spatrick                                        CompilerType ct) {
565061da546Spatrick   TypeSP pointee = GetOrCreateType(pr.ReferentType);
566061da546Spatrick   if (!pointee)
567061da546Spatrick     return nullptr;
568061da546Spatrick 
569061da546Spatrick   if (pr.isPointerToMember()) {
570061da546Spatrick     MemberPointerInfo mpi = pr.getMemberInfo();
571061da546Spatrick     GetOrCreateType(mpi.ContainingType);
572061da546Spatrick   }
573061da546Spatrick 
574061da546Spatrick   Declaration decl;
575*f6aab3d8Srobert   return MakeType(toOpaqueUid(type_id), ConstString(), pr.getSize(), nullptr,
576*f6aab3d8Srobert                   LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
577061da546Spatrick                   Type::ResolveState::Full);
578061da546Spatrick }
579061da546Spatrick 
CreateSimpleType(TypeIndex ti,CompilerType ct)580061da546Spatrick lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
581061da546Spatrick                                                    CompilerType ct) {
582061da546Spatrick   uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false));
583061da546Spatrick   if (ti == TypeIndex::NullptrT()) {
584061da546Spatrick     Declaration decl;
585*f6aab3d8Srobert     return MakeType(uid, ConstString("std::nullptr_t"), 0, nullptr,
586*f6aab3d8Srobert                     LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
587*f6aab3d8Srobert                     Type::ResolveState::Full);
588061da546Spatrick   }
589061da546Spatrick 
590061da546Spatrick   if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
591061da546Spatrick     TypeSP direct_sp = GetOrCreateType(ti.makeDirect());
592061da546Spatrick     uint32_t pointer_size = 0;
593061da546Spatrick     switch (ti.getSimpleMode()) {
594061da546Spatrick     case SimpleTypeMode::FarPointer32:
595061da546Spatrick     case SimpleTypeMode::NearPointer32:
596061da546Spatrick       pointer_size = 4;
597061da546Spatrick       break;
598061da546Spatrick     case SimpleTypeMode::NearPointer64:
599061da546Spatrick       pointer_size = 8;
600061da546Spatrick       break;
601061da546Spatrick     default:
602061da546Spatrick       // 128-bit and 16-bit pointers unsupported.
603061da546Spatrick       return nullptr;
604061da546Spatrick     }
605061da546Spatrick     Declaration decl;
606*f6aab3d8Srobert     return MakeType(uid, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,
607061da546Spatrick                     Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
608061da546Spatrick   }
609061da546Spatrick 
610061da546Spatrick   if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
611061da546Spatrick     return nullptr;
612061da546Spatrick 
613061da546Spatrick   size_t size = GetTypeSizeForSimpleKind(ti.getSimpleKind());
614061da546Spatrick   llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind());
615061da546Spatrick 
616061da546Spatrick   Declaration decl;
617*f6aab3d8Srobert   return MakeType(uid, ConstString(type_name), size, nullptr, LLDB_INVALID_UID,
618*f6aab3d8Srobert                   Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
619061da546Spatrick }
620061da546Spatrick 
GetUnqualifiedTypeName(const TagRecord & record)621061da546Spatrick static std::string GetUnqualifiedTypeName(const TagRecord &record) {
622061da546Spatrick   if (!record.hasUniqueName()) {
623061da546Spatrick     MSVCUndecoratedNameParser parser(record.Name);
624061da546Spatrick     llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
625061da546Spatrick 
626dda28197Spatrick     return std::string(specs.back().GetBaseName());
627061da546Spatrick   }
628061da546Spatrick 
629061da546Spatrick   llvm::ms_demangle::Demangler demangler;
630061da546Spatrick   StringView sv(record.UniqueName.begin(), record.UniqueName.size());
631061da546Spatrick   llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
632061da546Spatrick   if (demangler.Error)
633dda28197Spatrick     return std::string(record.Name);
634061da546Spatrick 
635061da546Spatrick   llvm::ms_demangle::IdentifierNode *idn =
636061da546Spatrick       ttn->QualifiedName->getUnqualifiedIdentifier();
637061da546Spatrick   return idn->toString();
638061da546Spatrick }
639061da546Spatrick 
640061da546Spatrick lldb::TypeSP
CreateClassStructUnion(PdbTypeSymId type_id,const TagRecord & record,size_t size,CompilerType ct)641061da546Spatrick SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id,
642061da546Spatrick                                             const TagRecord &record,
643061da546Spatrick                                             size_t size, CompilerType ct) {
644061da546Spatrick 
645061da546Spatrick   std::string uname = GetUnqualifiedTypeName(record);
646061da546Spatrick 
647061da546Spatrick   // FIXME: Search IPI stream for LF_UDT_MOD_SRC_LINE.
648061da546Spatrick   Declaration decl;
649*f6aab3d8Srobert   return MakeType(toOpaqueUid(type_id), ConstString(uname), size, nullptr,
650*f6aab3d8Srobert                   LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,
651061da546Spatrick                   Type::ResolveState::Forward);
652061da546Spatrick }
653061da546Spatrick 
CreateTagType(PdbTypeSymId type_id,const ClassRecord & cr,CompilerType ct)654061da546Spatrick lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
655061da546Spatrick                                                 const ClassRecord &cr,
656061da546Spatrick                                                 CompilerType ct) {
657061da546Spatrick   return CreateClassStructUnion(type_id, cr, cr.getSize(), ct);
658061da546Spatrick }
659061da546Spatrick 
CreateTagType(PdbTypeSymId type_id,const UnionRecord & ur,CompilerType ct)660061da546Spatrick lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
661061da546Spatrick                                                 const UnionRecord &ur,
662061da546Spatrick                                                 CompilerType ct) {
663061da546Spatrick   return CreateClassStructUnion(type_id, ur, ur.getSize(), ct);
664061da546Spatrick }
665061da546Spatrick 
CreateTagType(PdbTypeSymId type_id,const EnumRecord & er,CompilerType ct)666061da546Spatrick lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
667061da546Spatrick                                                 const EnumRecord &er,
668061da546Spatrick                                                 CompilerType ct) {
669061da546Spatrick   std::string uname = GetUnqualifiedTypeName(er);
670061da546Spatrick 
671061da546Spatrick   Declaration decl;
672061da546Spatrick   TypeSP underlying_type = GetOrCreateType(er.UnderlyingType);
673061da546Spatrick 
674*f6aab3d8Srobert   return MakeType(toOpaqueUid(type_id), ConstString(uname),
675*f6aab3d8Srobert                   underlying_type->GetByteSize(nullptr), nullptr,
676*f6aab3d8Srobert                   LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
677*f6aab3d8Srobert                   ct, lldb_private::Type::ResolveState::Forward);
678061da546Spatrick }
679061da546Spatrick 
CreateArrayType(PdbTypeSymId type_id,const ArrayRecord & ar,CompilerType ct)680061da546Spatrick TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
681061da546Spatrick                                             const ArrayRecord &ar,
682061da546Spatrick                                             CompilerType ct) {
683061da546Spatrick   TypeSP element_type = GetOrCreateType(ar.ElementType);
684061da546Spatrick 
685061da546Spatrick   Declaration decl;
686*f6aab3d8Srobert   TypeSP array_sp =
687*f6aab3d8Srobert       MakeType(toOpaqueUid(type_id), ConstString(), ar.Size, nullptr,
688061da546Spatrick                LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,
689061da546Spatrick                lldb_private::Type::ResolveState::Full);
690061da546Spatrick   array_sp->SetEncodingType(element_type.get());
691061da546Spatrick   return array_sp;
692061da546Spatrick }
693061da546Spatrick 
CreateFunctionType(PdbTypeSymId type_id,const MemberFunctionRecord & mfr,CompilerType ct)694061da546Spatrick TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id,
695061da546Spatrick                                                const MemberFunctionRecord &mfr,
696061da546Spatrick                                                CompilerType ct) {
697061da546Spatrick   Declaration decl;
698*f6aab3d8Srobert   return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
699*f6aab3d8Srobert                   LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
700*f6aab3d8Srobert                   ct, lldb_private::Type::ResolveState::Full);
701061da546Spatrick }
702061da546Spatrick 
CreateProcedureType(PdbTypeSymId type_id,const ProcedureRecord & pr,CompilerType ct)703061da546Spatrick TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,
704061da546Spatrick                                                 const ProcedureRecord &pr,
705061da546Spatrick                                                 CompilerType ct) {
706061da546Spatrick   Declaration decl;
707*f6aab3d8Srobert   return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,
708*f6aab3d8Srobert                   LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
709*f6aab3d8Srobert                   ct, lldb_private::Type::ResolveState::Full);
710061da546Spatrick }
711061da546Spatrick 
CreateType(PdbTypeSymId type_id,CompilerType ct)712061da546Spatrick TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) {
713061da546Spatrick   if (type_id.index.isSimple())
714061da546Spatrick     return CreateSimpleType(type_id.index, ct);
715061da546Spatrick 
716061da546Spatrick   TpiStream &stream = type_id.is_ipi ? m_index->ipi() : m_index->tpi();
717061da546Spatrick   CVType cvt = stream.getType(type_id.index);
718061da546Spatrick 
719061da546Spatrick   if (cvt.kind() == LF_MODIFIER) {
720061da546Spatrick     ModifierRecord modifier;
721061da546Spatrick     llvm::cantFail(
722061da546Spatrick         TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier));
723061da546Spatrick     return CreateModifierType(type_id, modifier, ct);
724061da546Spatrick   }
725061da546Spatrick 
726061da546Spatrick   if (cvt.kind() == LF_POINTER) {
727061da546Spatrick     PointerRecord pointer;
728061da546Spatrick     llvm::cantFail(
729061da546Spatrick         TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer));
730061da546Spatrick     return CreatePointerType(type_id, pointer, ct);
731061da546Spatrick   }
732061da546Spatrick 
733061da546Spatrick   if (IsClassRecord(cvt.kind())) {
734061da546Spatrick     ClassRecord cr;
735061da546Spatrick     llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
736061da546Spatrick     return CreateTagType(type_id, cr, ct);
737061da546Spatrick   }
738061da546Spatrick 
739061da546Spatrick   if (cvt.kind() == LF_ENUM) {
740061da546Spatrick     EnumRecord er;
741061da546Spatrick     llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
742061da546Spatrick     return CreateTagType(type_id, er, ct);
743061da546Spatrick   }
744061da546Spatrick 
745061da546Spatrick   if (cvt.kind() == LF_UNION) {
746061da546Spatrick     UnionRecord ur;
747061da546Spatrick     llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
748061da546Spatrick     return CreateTagType(type_id, ur, ct);
749061da546Spatrick   }
750061da546Spatrick 
751061da546Spatrick   if (cvt.kind() == LF_ARRAY) {
752061da546Spatrick     ArrayRecord ar;
753061da546Spatrick     llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar));
754061da546Spatrick     return CreateArrayType(type_id, ar, ct);
755061da546Spatrick   }
756061da546Spatrick 
757061da546Spatrick   if (cvt.kind() == LF_PROCEDURE) {
758061da546Spatrick     ProcedureRecord pr;
759061da546Spatrick     llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));
760061da546Spatrick     return CreateProcedureType(type_id, pr, ct);
761061da546Spatrick   }
762061da546Spatrick   if (cvt.kind() == LF_MFUNCTION) {
763061da546Spatrick     MemberFunctionRecord mfr;
764061da546Spatrick     llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr));
765061da546Spatrick     return CreateFunctionType(type_id, mfr, ct);
766061da546Spatrick   }
767061da546Spatrick 
768061da546Spatrick   return nullptr;
769061da546Spatrick }
770061da546Spatrick 
CreateAndCacheType(PdbTypeSymId type_id)771061da546Spatrick TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) {
772061da546Spatrick   // If they search for a UDT which is a forward ref, try and resolve the full
773061da546Spatrick   // decl and just map the forward ref uid to the full decl record.
774*f6aab3d8Srobert   std::optional<PdbTypeSymId> full_decl_uid;
775061da546Spatrick   if (IsForwardRefUdt(type_id, m_index->tpi())) {
776061da546Spatrick     auto expected_full_ti =
777061da546Spatrick         m_index->tpi().findFullDeclForForwardRef(type_id.index);
778061da546Spatrick     if (!expected_full_ti)
779061da546Spatrick       llvm::consumeError(expected_full_ti.takeError());
780061da546Spatrick     else if (*expected_full_ti != type_id.index) {
781061da546Spatrick       full_decl_uid = PdbTypeSymId(*expected_full_ti, false);
782061da546Spatrick 
783061da546Spatrick       // It's possible that a lookup would occur for the full decl causing it
784061da546Spatrick       // to be cached, then a second lookup would occur for the forward decl.
785061da546Spatrick       // We don't want to create a second full decl, so make sure the full
786061da546Spatrick       // decl hasn't already been cached.
787061da546Spatrick       auto full_iter = m_types.find(toOpaqueUid(*full_decl_uid));
788061da546Spatrick       if (full_iter != m_types.end()) {
789061da546Spatrick         TypeSP result = full_iter->second;
790061da546Spatrick         // Map the forward decl to the TypeSP for the full decl so we can take
791061da546Spatrick         // the fast path next time.
792061da546Spatrick         m_types[toOpaqueUid(type_id)] = result;
793061da546Spatrick         return result;
794061da546Spatrick       }
795061da546Spatrick     }
796061da546Spatrick   }
797061da546Spatrick 
798061da546Spatrick   PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id;
799*f6aab3d8Srobert   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
800*f6aab3d8Srobert   if (auto err = ts_or_err.takeError())
801*f6aab3d8Srobert     return nullptr;
802*f6aab3d8Srobert   auto ts = *ts_or_err;
803*f6aab3d8Srobert   if (!ts)
804*f6aab3d8Srobert     return nullptr;
805061da546Spatrick 
806*f6aab3d8Srobert   PdbAstBuilder* ast_builder = ts->GetNativePDBParser();
807*f6aab3d8Srobert   clang::QualType qt = ast_builder->GetOrCreateType(best_decl_id);
808*f6aab3d8Srobert   if (qt.isNull())
809*f6aab3d8Srobert     return nullptr;
810061da546Spatrick 
811*f6aab3d8Srobert   TypeSP result = CreateType(best_decl_id, ast_builder->ToCompilerType(qt));
812061da546Spatrick   if (!result)
813061da546Spatrick     return nullptr;
814061da546Spatrick 
815061da546Spatrick   uint64_t best_uid = toOpaqueUid(best_decl_id);
816061da546Spatrick   m_types[best_uid] = result;
817061da546Spatrick   // If we had both a forward decl and a full decl, make both point to the new
818061da546Spatrick   // type.
819061da546Spatrick   if (full_decl_uid)
820061da546Spatrick     m_types[toOpaqueUid(type_id)] = result;
821061da546Spatrick 
822061da546Spatrick   return result;
823061da546Spatrick }
824061da546Spatrick 
GetOrCreateType(PdbTypeSymId type_id)825061da546Spatrick TypeSP SymbolFileNativePDB::GetOrCreateType(PdbTypeSymId type_id) {
826061da546Spatrick   // We can't use try_emplace / overwrite here because the process of creating
827061da546Spatrick   // a type could create nested types, which could invalidate iterators.  So
828061da546Spatrick   // we have to do a 2-phase lookup / insert.
829061da546Spatrick   auto iter = m_types.find(toOpaqueUid(type_id));
830061da546Spatrick   if (iter != m_types.end())
831061da546Spatrick     return iter->second;
832061da546Spatrick 
833061da546Spatrick   TypeSP type = CreateAndCacheType(type_id);
834061da546Spatrick   if (type)
835061da546Spatrick     GetTypeList().Insert(type);
836061da546Spatrick   return type;
837061da546Spatrick }
838061da546Spatrick 
CreateGlobalVariable(PdbGlobalSymId var_id)839061da546Spatrick VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
840061da546Spatrick   CVSymbol sym = m_index->symrecords().readRecord(var_id.offset);
841061da546Spatrick   if (sym.kind() == S_CONSTANT)
842061da546Spatrick     return CreateConstantSymbol(var_id, sym);
843061da546Spatrick 
844061da546Spatrick   lldb::ValueType scope = eValueTypeInvalid;
845061da546Spatrick   TypeIndex ti;
846061da546Spatrick   llvm::StringRef name;
847061da546Spatrick   lldb::addr_t addr = 0;
848061da546Spatrick   uint16_t section = 0;
849061da546Spatrick   uint32_t offset = 0;
850061da546Spatrick   bool is_external = false;
851061da546Spatrick   switch (sym.kind()) {
852061da546Spatrick   case S_GDATA32:
853061da546Spatrick     is_external = true;
854*f6aab3d8Srobert     [[fallthrough]];
855061da546Spatrick   case S_LDATA32: {
856061da546Spatrick     DataSym ds(sym.kind());
857061da546Spatrick     llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, ds));
858061da546Spatrick     ti = ds.Type;
859061da546Spatrick     scope = (sym.kind() == S_GDATA32) ? eValueTypeVariableGlobal
860061da546Spatrick                                       : eValueTypeVariableStatic;
861061da546Spatrick     name = ds.Name;
862061da546Spatrick     section = ds.Segment;
863061da546Spatrick     offset = ds.DataOffset;
864061da546Spatrick     addr = m_index->MakeVirtualAddress(ds.Segment, ds.DataOffset);
865061da546Spatrick     break;
866061da546Spatrick   }
867061da546Spatrick   case S_GTHREAD32:
868061da546Spatrick     is_external = true;
869*f6aab3d8Srobert     [[fallthrough]];
870061da546Spatrick   case S_LTHREAD32: {
871061da546Spatrick     ThreadLocalDataSym tlds(sym.kind());
872061da546Spatrick     llvm::cantFail(
873061da546Spatrick         SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, tlds));
874061da546Spatrick     ti = tlds.Type;
875061da546Spatrick     name = tlds.Name;
876061da546Spatrick     section = tlds.Segment;
877061da546Spatrick     offset = tlds.DataOffset;
878061da546Spatrick     addr = m_index->MakeVirtualAddress(tlds.Segment, tlds.DataOffset);
879061da546Spatrick     scope = eValueTypeVariableThreadLocal;
880061da546Spatrick     break;
881061da546Spatrick   }
882061da546Spatrick   default:
883061da546Spatrick     llvm_unreachable("unreachable!");
884061da546Spatrick   }
885061da546Spatrick 
886061da546Spatrick   CompUnitSP comp_unit;
887*f6aab3d8Srobert   std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr);
888*f6aab3d8Srobert   if (!modi) {
889*f6aab3d8Srobert     return nullptr;
890*f6aab3d8Srobert   }
891*f6aab3d8Srobert 
892061da546Spatrick   CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(*modi);
893061da546Spatrick   comp_unit = GetOrCreateCompileUnit(cci);
894061da546Spatrick 
895061da546Spatrick   Declaration decl;
896061da546Spatrick   PdbTypeSymId tid(ti, false);
897061da546Spatrick   SymbolFileTypeSP type_sp =
898061da546Spatrick       std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
899061da546Spatrick   Variable::RangeList ranges;
900*f6aab3d8Srobert   auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());
901*f6aab3d8Srobert   if (auto err = ts_or_err.takeError())
902*f6aab3d8Srobert     return nullptr;
903*f6aab3d8Srobert   auto ts = *ts_or_err;
904*f6aab3d8Srobert   if (!ts)
905*f6aab3d8Srobert     return nullptr;
906061da546Spatrick 
907*f6aab3d8Srobert   ts->GetNativePDBParser()->GetOrCreateVariableDecl(var_id);
908061da546Spatrick 
909*f6aab3d8Srobert   ModuleSP module_sp = GetObjectFile()->GetModule();
910*f6aab3d8Srobert   DWARFExpressionList location(
911*f6aab3d8Srobert       module_sp, MakeGlobalLocationExpression(section, offset, module_sp),
912*f6aab3d8Srobert       nullptr);
913061da546Spatrick 
914061da546Spatrick   std::string global_name("::");
915061da546Spatrick   global_name += name;
916be691f3bSpatrick   bool artificial = false;
917be691f3bSpatrick   bool location_is_constant_data = false;
918be691f3bSpatrick   bool static_member = false;
919061da546Spatrick   VariableSP var_sp = std::make_shared<Variable>(
920061da546Spatrick       toOpaqueUid(var_id), name.str().c_str(), global_name.c_str(), type_sp,
921be691f3bSpatrick       scope, comp_unit.get(), ranges, &decl, location, is_external, artificial,
922be691f3bSpatrick       location_is_constant_data, static_member);
923061da546Spatrick 
924061da546Spatrick   return var_sp;
925061da546Spatrick }
926061da546Spatrick 
927061da546Spatrick lldb::VariableSP
CreateConstantSymbol(PdbGlobalSymId var_id,const CVSymbol & cvs)928061da546Spatrick SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id,
929061da546Spatrick                                           const CVSymbol &cvs) {
930061da546Spatrick   TpiStream &tpi = m_index->tpi();
931061da546Spatrick   ConstantSym constant(cvs.kind());
932061da546Spatrick 
933061da546Spatrick   llvm::cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(cvs, constant));
934061da546Spatrick   std::string global_name("::");
935061da546Spatrick   global_name += constant.Name;
936061da546Spatrick   PdbTypeSymId tid(constant.Type, false);
937061da546Spatrick   SymbolFileTypeSP type_sp =
938061da546Spatrick       std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
939061da546Spatrick 
940061da546Spatrick   Declaration decl;
941061da546Spatrick   Variable::RangeList ranges;
942061da546Spatrick   ModuleSP module = GetObjectFile()->GetModule();
943*f6aab3d8Srobert   DWARFExpressionList location(module,
944*f6aab3d8Srobert                                MakeConstantLocationExpression(
945*f6aab3d8Srobert                                    constant.Type, tpi, constant.Value, module),
946*f6aab3d8Srobert                                nullptr);
947061da546Spatrick 
948be691f3bSpatrick   bool external = false;
949be691f3bSpatrick   bool artificial = false;
950be691f3bSpatrick   bool location_is_constant_data = true;
951be691f3bSpatrick   bool static_member = false;
952061da546Spatrick   VariableSP var_sp = std::make_shared<Variable>(
953061da546Spatrick       toOpaqueUid(var_id), constant.Name.str().c_str(), global_name.c_str(),
954061da546Spatrick       type_sp, eValueTypeVariableGlobal, module.get(), ranges, &decl, location,
955be691f3bSpatrick       external, artificial, location_is_constant_data, static_member);
956061da546Spatrick   return var_sp;
957061da546Spatrick }
958061da546Spatrick 
959061da546Spatrick VariableSP
GetOrCreateGlobalVariable(PdbGlobalSymId var_id)960061da546Spatrick SymbolFileNativePDB::GetOrCreateGlobalVariable(PdbGlobalSymId var_id) {
961061da546Spatrick   auto emplace_result = m_global_vars.try_emplace(toOpaqueUid(var_id), nullptr);
962*f6aab3d8Srobert   if (emplace_result.second) {
963*f6aab3d8Srobert     if (VariableSP var_sp = CreateGlobalVariable(var_id))
964*f6aab3d8Srobert       emplace_result.first->second = var_sp;
965*f6aab3d8Srobert     else
966*f6aab3d8Srobert       return nullptr;
967*f6aab3d8Srobert   }
968061da546Spatrick 
969061da546Spatrick   return emplace_result.first->second;
970061da546Spatrick }
971061da546Spatrick 
GetOrCreateType(TypeIndex ti)972061da546Spatrick lldb::TypeSP SymbolFileNativePDB::GetOrCreateType(TypeIndex ti) {
973061da546Spatrick   return GetOrCreateType(PdbTypeSymId(ti, false));
974061da546Spatrick }
975061da546Spatrick 
GetOrCreateFunction(PdbCompilandSymId func_id,CompileUnit & comp_unit)976061da546Spatrick FunctionSP SymbolFileNativePDB::GetOrCreateFunction(PdbCompilandSymId func_id,
977061da546Spatrick                                                     CompileUnit &comp_unit) {
978061da546Spatrick   auto emplace_result = m_functions.try_emplace(toOpaqueUid(func_id), nullptr);
979061da546Spatrick   if (emplace_result.second)
980061da546Spatrick     emplace_result.first->second = CreateFunction(func_id, comp_unit);
981061da546Spatrick 
982061da546Spatrick   return emplace_result.first->second;
983061da546Spatrick }
984061da546Spatrick 
985061da546Spatrick CompUnitSP
GetOrCreateCompileUnit(const CompilandIndexItem & cci)986061da546Spatrick SymbolFileNativePDB::GetOrCreateCompileUnit(const CompilandIndexItem &cci) {
987061da546Spatrick 
988061da546Spatrick   auto emplace_result =
989061da546Spatrick       m_compilands.try_emplace(toOpaqueUid(cci.m_id), nullptr);
990061da546Spatrick   if (emplace_result.second)
991061da546Spatrick     emplace_result.first->second = CreateCompileUnit(cci);
992061da546Spatrick 
993061da546Spatrick   lldbassert(emplace_result.first->second);
994061da546Spatrick   return emplace_result.first->second;
995061da546Spatrick }
996061da546Spatrick 
GetOrCreateBlock(PdbCompilandSymId block_id)997061da546Spatrick Block &SymbolFileNativePDB::GetOrCreateBlock(PdbCompilandSymId block_id) {
998061da546Spatrick   auto iter = m_blocks.find(toOpaqueUid(block_id));
999061da546Spatrick   if (iter != m_blocks.end())
1000061da546Spatrick     return *iter->second;
1001061da546Spatrick 
1002061da546Spatrick   return CreateBlock(block_id);
1003061da546Spatrick }
1004061da546Spatrick 
ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx)1005061da546Spatrick void SymbolFileNativePDB::ParseDeclsForContext(
1006061da546Spatrick     lldb_private::CompilerDeclContext decl_ctx) {
1007*f6aab3d8Srobert   TypeSystem* ts_or_err = decl_ctx.GetTypeSystem();
1008*f6aab3d8Srobert   if (!ts_or_err)
1009*f6aab3d8Srobert     return;
1010*f6aab3d8Srobert   PdbAstBuilder* ast_builder = ts_or_err->GetNativePDBParser();
1011*f6aab3d8Srobert   clang::DeclContext *context = ast_builder->FromCompilerDeclContext(decl_ctx);
1012061da546Spatrick   if (!context)
1013061da546Spatrick     return;
1014*f6aab3d8Srobert   ast_builder->ParseDeclsForContext(*context);
1015061da546Spatrick }
1016061da546Spatrick 
ParseCompileUnitAtIndex(uint32_t index)1017061da546Spatrick lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) {
1018061da546Spatrick   if (index >= GetNumCompileUnits())
1019061da546Spatrick     return CompUnitSP();
1020061da546Spatrick   lldbassert(index < UINT16_MAX);
1021061da546Spatrick   if (index >= UINT16_MAX)
1022061da546Spatrick     return nullptr;
1023061da546Spatrick 
1024061da546Spatrick   CompilandIndexItem &item = m_index->compilands().GetOrCreateCompiland(index);
1025061da546Spatrick 
1026061da546Spatrick   return GetOrCreateCompileUnit(item);
1027061da546Spatrick }
1028061da546Spatrick 
ParseLanguage(CompileUnit & comp_unit)1029061da546Spatrick lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) {
1030061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1031061da546Spatrick   PdbSymUid uid(comp_unit.GetID());
1032061da546Spatrick   lldbassert(uid.kind() == PdbSymUidKind::Compiland);
1033061da546Spatrick 
1034061da546Spatrick   CompilandIndexItem *item =
1035061da546Spatrick       m_index->compilands().GetCompiland(uid.asCompiland().modi);
1036061da546Spatrick   lldbassert(item);
1037061da546Spatrick   if (!item->m_compile_opts)
1038061da546Spatrick     return lldb::eLanguageTypeUnknown;
1039061da546Spatrick 
1040061da546Spatrick   return TranslateLanguage(item->m_compile_opts->getLanguage());
1041061da546Spatrick }
1042061da546Spatrick 
AddSymbols(Symtab & symtab)1043*f6aab3d8Srobert void SymbolFileNativePDB::AddSymbols(Symtab &symtab) {}
1044061da546Spatrick 
ParseFunctions(CompileUnit & comp_unit)1045061da546Spatrick size_t SymbolFileNativePDB::ParseFunctions(CompileUnit &comp_unit) {
1046061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1047061da546Spatrick   PdbSymUid uid{comp_unit.GetID()};
1048061da546Spatrick   lldbassert(uid.kind() == PdbSymUidKind::Compiland);
1049061da546Spatrick   uint16_t modi = uid.asCompiland().modi;
1050061da546Spatrick   CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(modi);
1051061da546Spatrick 
1052061da546Spatrick   size_t count = comp_unit.GetNumFunctions();
1053061da546Spatrick   const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
1054061da546Spatrick   for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
1055061da546Spatrick     if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32)
1056061da546Spatrick       continue;
1057061da546Spatrick 
1058061da546Spatrick     PdbCompilandSymId sym_id{modi, iter.offset()};
1059061da546Spatrick 
1060061da546Spatrick     FunctionSP func = GetOrCreateFunction(sym_id, comp_unit);
1061061da546Spatrick   }
1062061da546Spatrick 
1063061da546Spatrick   size_t new_count = comp_unit.GetNumFunctions();
1064061da546Spatrick   lldbassert(new_count >= count);
1065061da546Spatrick   return new_count - count;
1066061da546Spatrick }
1067061da546Spatrick 
NeedsResolvedCompileUnit(uint32_t resolve_scope)1068061da546Spatrick static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) {
1069061da546Spatrick   // If any of these flags are set, we need to resolve the compile unit.
1070061da546Spatrick   uint32_t flags = eSymbolContextCompUnit;
1071061da546Spatrick   flags |= eSymbolContextVariable;
1072061da546Spatrick   flags |= eSymbolContextFunction;
1073061da546Spatrick   flags |= eSymbolContextBlock;
1074061da546Spatrick   flags |= eSymbolContextLineEntry;
1075061da546Spatrick   return (resolve_scope & flags) != 0;
1076061da546Spatrick }
1077061da546Spatrick 
ResolveSymbolContext(const Address & addr,SymbolContextItem resolve_scope,SymbolContext & sc)1078061da546Spatrick uint32_t SymbolFileNativePDB::ResolveSymbolContext(
1079061da546Spatrick     const Address &addr, SymbolContextItem resolve_scope, SymbolContext &sc) {
1080061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1081061da546Spatrick   uint32_t resolved_flags = 0;
1082061da546Spatrick   lldb::addr_t file_addr = addr.GetFileAddress();
1083061da546Spatrick 
1084061da546Spatrick   if (NeedsResolvedCompileUnit(resolve_scope)) {
1085*f6aab3d8Srobert     std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr);
1086061da546Spatrick     if (!modi)
1087061da546Spatrick       return 0;
1088*f6aab3d8Srobert     CompUnitSP cu_sp = GetCompileUnitAtIndex(*modi);
1089*f6aab3d8Srobert     if (!cu_sp)
1090061da546Spatrick       return 0;
1091061da546Spatrick 
1092*f6aab3d8Srobert     sc.comp_unit = cu_sp.get();
1093061da546Spatrick     resolved_flags |= eSymbolContextCompUnit;
1094061da546Spatrick   }
1095061da546Spatrick 
1096061da546Spatrick   if (resolve_scope & eSymbolContextFunction ||
1097061da546Spatrick       resolve_scope & eSymbolContextBlock) {
1098061da546Spatrick     lldbassert(sc.comp_unit);
1099061da546Spatrick     std::vector<SymbolAndUid> matches = m_index->FindSymbolsByVa(file_addr);
1100061da546Spatrick     // Search the matches in reverse.  This way if there are multiple matches
1101061da546Spatrick     // (for example we are 3 levels deep in a nested scope) it will find the
1102061da546Spatrick     // innermost one first.
1103061da546Spatrick     for (const auto &match : llvm::reverse(matches)) {
1104061da546Spatrick       if (match.uid.kind() != PdbSymUidKind::CompilandSym)
1105061da546Spatrick         continue;
1106061da546Spatrick 
1107061da546Spatrick       PdbCompilandSymId csid = match.uid.asCompilandSym();
1108061da546Spatrick       CVSymbol cvs = m_index->ReadSymbolRecord(csid);
1109061da546Spatrick       PDB_SymType type = CVSymToPDBSym(cvs.kind());
1110061da546Spatrick       if (type != PDB_SymType::Function && type != PDB_SymType::Block)
1111061da546Spatrick         continue;
1112061da546Spatrick       if (type == PDB_SymType::Function) {
1113061da546Spatrick         sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get();
1114*f6aab3d8Srobert         if (sc.function) {
1115*f6aab3d8Srobert           Block &block = sc.function->GetBlock(true);
1116*f6aab3d8Srobert           addr_t func_base =
1117*f6aab3d8Srobert               sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
1118*f6aab3d8Srobert           addr_t offset = file_addr - func_base;
1119*f6aab3d8Srobert           sc.block = block.FindInnermostBlockByOffset(offset);
1120*f6aab3d8Srobert         }
1121061da546Spatrick       }
1122061da546Spatrick 
1123061da546Spatrick       if (type == PDB_SymType::Block) {
1124*f6aab3d8Srobert         Block &block = GetOrCreateBlock(csid);
1125*f6aab3d8Srobert         sc.function = block.CalculateSymbolContextFunction();
1126*f6aab3d8Srobert         if (sc.function) {
1127*f6aab3d8Srobert           sc.function->GetBlock(true);
1128*f6aab3d8Srobert           addr_t func_base =
1129*f6aab3d8Srobert               sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
1130*f6aab3d8Srobert           addr_t offset = file_addr - func_base;
1131*f6aab3d8Srobert           sc.block = block.FindInnermostBlockByOffset(offset);
1132061da546Spatrick         }
1133*f6aab3d8Srobert       }
1134*f6aab3d8Srobert       if (sc.function)
1135061da546Spatrick         resolved_flags |= eSymbolContextFunction;
1136*f6aab3d8Srobert       if (sc.block)
1137061da546Spatrick         resolved_flags |= eSymbolContextBlock;
1138061da546Spatrick       break;
1139061da546Spatrick     }
1140061da546Spatrick   }
1141061da546Spatrick 
1142061da546Spatrick   if (resolve_scope & eSymbolContextLineEntry) {
1143061da546Spatrick     lldbassert(sc.comp_unit);
1144061da546Spatrick     if (auto *line_table = sc.comp_unit->GetLineTable()) {
1145061da546Spatrick       if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
1146061da546Spatrick         resolved_flags |= eSymbolContextLineEntry;
1147061da546Spatrick     }
1148061da546Spatrick   }
1149061da546Spatrick 
1150061da546Spatrick   return resolved_flags;
1151061da546Spatrick }
1152061da546Spatrick 
ResolveSymbolContext(const SourceLocationSpec & src_location_spec,lldb::SymbolContextItem resolve_scope,SymbolContextList & sc_list)1153061da546Spatrick uint32_t SymbolFileNativePDB::ResolveSymbolContext(
1154be691f3bSpatrick     const SourceLocationSpec &src_location_spec,
1155061da546Spatrick     lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
1156*f6aab3d8Srobert   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1157*f6aab3d8Srobert   const uint32_t prev_size = sc_list.GetSize();
1158*f6aab3d8Srobert   if (resolve_scope & eSymbolContextCompUnit) {
1159*f6aab3d8Srobert     for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus;
1160*f6aab3d8Srobert          ++cu_idx) {
1161*f6aab3d8Srobert       CompileUnit *cu = ParseCompileUnitAtIndex(cu_idx).get();
1162*f6aab3d8Srobert       if (!cu)
1163*f6aab3d8Srobert         continue;
1164*f6aab3d8Srobert 
1165*f6aab3d8Srobert       bool file_spec_matches_cu_file_spec = FileSpec::Match(
1166*f6aab3d8Srobert           src_location_spec.GetFileSpec(), cu->GetPrimaryFile());
1167*f6aab3d8Srobert       if (file_spec_matches_cu_file_spec) {
1168*f6aab3d8Srobert         cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);
1169*f6aab3d8Srobert         break;
1170061da546Spatrick       }
1171061da546Spatrick     }
1172*f6aab3d8Srobert   }
1173*f6aab3d8Srobert   return sc_list.GetSize() - prev_size;
1174061da546Spatrick }
1175061da546Spatrick 
ParseLineTable(CompileUnit & comp_unit)1176061da546Spatrick bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) {
1177061da546Spatrick   // Unfortunately LLDB is set up to parse the entire compile unit line table
1178061da546Spatrick   // all at once, even if all it really needs is line info for a specific
1179061da546Spatrick   // function.  In the future it would be nice if it could set the sc.m_function
1180061da546Spatrick   // member, and we could only get the line info for the function in question.
1181061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1182061da546Spatrick   PdbSymUid cu_id(comp_unit.GetID());
1183061da546Spatrick   lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);
1184*f6aab3d8Srobert   uint16_t modi = cu_id.asCompiland().modi;
1185*f6aab3d8Srobert   CompilandIndexItem *cii = m_index->compilands().GetCompiland(modi);
1186*f6aab3d8Srobert   lldbassert(cii);
1187*f6aab3d8Srobert 
1188*f6aab3d8Srobert   // Parse DEBUG_S_LINES subsections first, then parse all S_INLINESITE records
1189*f6aab3d8Srobert   // in this CU. Add line entries into the set first so that if there are line
1190*f6aab3d8Srobert   // entries with same addres, the later is always more accurate than the
1191*f6aab3d8Srobert   // former.
1192*f6aab3d8Srobert   std::set<LineTable::Entry, LineTableEntryComparator> line_set;
1193061da546Spatrick 
1194061da546Spatrick   // This is basically a copy of the .debug$S subsections from all original COFF
1195061da546Spatrick   // object files merged together with address relocations applied.  We are
1196061da546Spatrick   // looking for all DEBUG_S_LINES subsections.
1197061da546Spatrick   for (const DebugSubsectionRecord &dssr :
1198*f6aab3d8Srobert        cii->m_debug_stream.getSubsectionsArray()) {
1199061da546Spatrick     if (dssr.kind() != DebugSubsectionKind::Lines)
1200061da546Spatrick       continue;
1201061da546Spatrick 
1202061da546Spatrick     DebugLinesSubsectionRef lines;
1203061da546Spatrick     llvm::BinaryStreamReader reader(dssr.getRecordData());
1204061da546Spatrick     if (auto EC = lines.initialize(reader)) {
1205061da546Spatrick       llvm::consumeError(std::move(EC));
1206061da546Spatrick       return false;
1207061da546Spatrick     }
1208061da546Spatrick 
1209061da546Spatrick     const LineFragmentHeader *lfh = lines.header();
1210061da546Spatrick     uint64_t virtual_addr =
1211061da546Spatrick         m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset);
1212*f6aab3d8Srobert     if (virtual_addr == LLDB_INVALID_ADDRESS)
1213*f6aab3d8Srobert       continue;
1214061da546Spatrick 
1215061da546Spatrick     for (const LineColumnEntry &group : lines) {
1216*f6aab3d8Srobert       llvm::Expected<uint32_t> file_index_or_err =
1217*f6aab3d8Srobert           GetFileIndex(*cii, group.NameIndex);
1218*f6aab3d8Srobert       if (!file_index_or_err)
1219061da546Spatrick         continue;
1220*f6aab3d8Srobert       uint32_t file_index = file_index_or_err.get();
1221061da546Spatrick       lldbassert(!group.LineNumbers.empty());
1222*f6aab3d8Srobert       CompilandIndexItem::GlobalLineTable::Entry line_entry(
1223*f6aab3d8Srobert           LLDB_INVALID_ADDRESS, 0);
1224061da546Spatrick       for (const LineNumberEntry &entry : group.LineNumbers) {
1225*f6aab3d8Srobert         LineInfo cur_info(entry.Flags);
1226*f6aab3d8Srobert 
1227*f6aab3d8Srobert         if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto())
1228*f6aab3d8Srobert           continue;
1229*f6aab3d8Srobert 
1230*f6aab3d8Srobert         uint64_t addr = virtual_addr + entry.Offset;
1231*f6aab3d8Srobert 
1232*f6aab3d8Srobert         bool is_statement = cur_info.isStatement();
1233*f6aab3d8Srobert         bool is_prologue = IsFunctionPrologue(*cii, addr);
1234*f6aab3d8Srobert         bool is_epilogue = IsFunctionEpilogue(*cii, addr);
1235*f6aab3d8Srobert 
1236*f6aab3d8Srobert         uint32_t lno = cur_info.getStartLine();
1237*f6aab3d8Srobert 
1238*f6aab3d8Srobert         LineTable::Entry new_entry(addr, lno, 0, file_index, is_statement, false,
1239*f6aab3d8Srobert                                  is_prologue, is_epilogue, false);
1240*f6aab3d8Srobert         // Terminal entry has lower precedence than new entry.
1241*f6aab3d8Srobert         auto iter = line_set.find(new_entry);
1242*f6aab3d8Srobert         if (iter != line_set.end() && iter->is_terminal_entry)
1243*f6aab3d8Srobert           line_set.erase(iter);
1244*f6aab3d8Srobert         line_set.insert(new_entry);
1245*f6aab3d8Srobert 
1246*f6aab3d8Srobert         if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {
1247*f6aab3d8Srobert           line_entry.SetRangeEnd(addr);
1248*f6aab3d8Srobert           cii->m_global_line_table.Append(line_entry);
1249*f6aab3d8Srobert         }
1250*f6aab3d8Srobert         line_entry.SetRangeBase(addr);
1251*f6aab3d8Srobert         line_entry.data = {file_index, lno};
1252061da546Spatrick       }
1253061da546Spatrick       LineInfo last_line(group.LineNumbers.back().Flags);
1254*f6aab3d8Srobert       line_set.emplace(virtual_addr + lfh->CodeSize, last_line.getEndLine(), 0,
1255*f6aab3d8Srobert                        file_index, false, false, false, false, true);
1256*f6aab3d8Srobert 
1257*f6aab3d8Srobert       if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {
1258*f6aab3d8Srobert         line_entry.SetRangeEnd(virtual_addr + lfh->CodeSize);
1259*f6aab3d8Srobert         cii->m_global_line_table.Append(line_entry);
1260061da546Spatrick       }
1261061da546Spatrick     }
1262*f6aab3d8Srobert   }
1263*f6aab3d8Srobert 
1264*f6aab3d8Srobert   cii->m_global_line_table.Sort();
1265*f6aab3d8Srobert 
1266*f6aab3d8Srobert   // Parse all S_INLINESITE in this CU.
1267*f6aab3d8Srobert   const CVSymbolArray &syms = cii->m_debug_stream.getSymbolArray();
1268*f6aab3d8Srobert   for (auto iter = syms.begin(); iter != syms.end();) {
1269*f6aab3d8Srobert     if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) {
1270*f6aab3d8Srobert       ++iter;
1271*f6aab3d8Srobert       continue;
1272*f6aab3d8Srobert     }
1273*f6aab3d8Srobert 
1274*f6aab3d8Srobert     uint32_t record_offset = iter.offset();
1275*f6aab3d8Srobert     CVSymbol func_record =
1276*f6aab3d8Srobert         cii->m_debug_stream.readSymbolAtOffset(record_offset);
1277*f6aab3d8Srobert     SegmentOffsetLength sol = GetSegmentOffsetAndLength(func_record);
1278*f6aab3d8Srobert     addr_t file_vm_addr =
1279*f6aab3d8Srobert         m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);
1280*f6aab3d8Srobert     if (file_vm_addr == LLDB_INVALID_ADDRESS)
1281*f6aab3d8Srobert       continue;
1282*f6aab3d8Srobert 
1283*f6aab3d8Srobert     AddressRange func_range(file_vm_addr, sol.length,
1284*f6aab3d8Srobert                             comp_unit.GetModule()->GetSectionList());
1285*f6aab3d8Srobert     Address func_base = func_range.GetBaseAddress();
1286*f6aab3d8Srobert     PdbCompilandSymId func_id{modi, record_offset};
1287*f6aab3d8Srobert 
1288*f6aab3d8Srobert     // Iterate all S_INLINESITEs in the function.
1289*f6aab3d8Srobert     auto parse_inline_sites = [&](SymbolKind kind, PdbCompilandSymId id) {
1290*f6aab3d8Srobert       if (kind != S_INLINESITE)
1291*f6aab3d8Srobert         return false;
1292*f6aab3d8Srobert 
1293*f6aab3d8Srobert       ParseInlineSite(id, func_base);
1294*f6aab3d8Srobert 
1295*f6aab3d8Srobert       for (const auto &line_entry :
1296*f6aab3d8Srobert            m_inline_sites[toOpaqueUid(id)]->line_entries) {
1297*f6aab3d8Srobert         // If line_entry is not terminal entry, remove previous line entry at
1298*f6aab3d8Srobert         // the same address and insert new one. Terminal entry inside an inline
1299*f6aab3d8Srobert         // site might not be terminal entry for its parent.
1300*f6aab3d8Srobert         if (!line_entry.is_terminal_entry)
1301*f6aab3d8Srobert           line_set.erase(line_entry);
1302*f6aab3d8Srobert         line_set.insert(line_entry);
1303*f6aab3d8Srobert       }
1304*f6aab3d8Srobert       // No longer useful after adding to line_set.
1305*f6aab3d8Srobert       m_inline_sites[toOpaqueUid(id)]->line_entries.clear();
1306*f6aab3d8Srobert       return true;
1307*f6aab3d8Srobert     };
1308*f6aab3d8Srobert     ParseSymbolArrayInScope(func_id, parse_inline_sites);
1309*f6aab3d8Srobert     // Jump to the end of the function record.
1310*f6aab3d8Srobert     iter = syms.at(getScopeEndOffset(func_record));
1311*f6aab3d8Srobert   }
1312*f6aab3d8Srobert 
1313*f6aab3d8Srobert   cii->m_global_line_table.Clear();
1314*f6aab3d8Srobert 
1315*f6aab3d8Srobert   // Add line entries in line_set to line_table.
1316*f6aab3d8Srobert   auto line_table = std::make_unique<LineTable>(&comp_unit);
1317*f6aab3d8Srobert   std::unique_ptr<LineSequence> sequence(
1318*f6aab3d8Srobert       line_table->CreateLineSequenceContainer());
1319*f6aab3d8Srobert   for (const auto &line_entry : line_set) {
1320*f6aab3d8Srobert     line_table->AppendLineEntryToSequence(
1321*f6aab3d8Srobert         sequence.get(), line_entry.file_addr, line_entry.line,
1322*f6aab3d8Srobert         line_entry.column, line_entry.file_idx,
1323*f6aab3d8Srobert         line_entry.is_start_of_statement, line_entry.is_start_of_basic_block,
1324*f6aab3d8Srobert         line_entry.is_prologue_end, line_entry.is_epilogue_begin,
1325*f6aab3d8Srobert         line_entry.is_terminal_entry);
1326*f6aab3d8Srobert   }
1327*f6aab3d8Srobert   line_table->InsertSequence(sequence.get());
1328061da546Spatrick 
1329061da546Spatrick   if (line_table->GetSize() == 0)
1330061da546Spatrick     return false;
1331061da546Spatrick 
1332061da546Spatrick   comp_unit.SetLineTable(line_table.release());
1333061da546Spatrick   return true;
1334061da546Spatrick }
1335061da546Spatrick 
ParseDebugMacros(CompileUnit & comp_unit)1336061da546Spatrick bool SymbolFileNativePDB::ParseDebugMacros(CompileUnit &comp_unit) {
1337061da546Spatrick   // PDB doesn't contain information about macros
1338061da546Spatrick   return false;
1339061da546Spatrick }
1340061da546Spatrick 
1341*f6aab3d8Srobert llvm::Expected<uint32_t>
GetFileIndex(const CompilandIndexItem & cii,uint32_t file_id)1342*f6aab3d8Srobert SymbolFileNativePDB::GetFileIndex(const CompilandIndexItem &cii,
1343*f6aab3d8Srobert                                   uint32_t file_id) {
1344*f6aab3d8Srobert   const auto &checksums = cii.m_strings.checksums().getArray();
1345*f6aab3d8Srobert   const auto &strings = cii.m_strings.strings();
1346*f6aab3d8Srobert   // Indices in this structure are actually offsets of records in the
1347*f6aab3d8Srobert   // DEBUG_S_FILECHECKSUMS subsection.  Those entries then have an index
1348*f6aab3d8Srobert   // into the global PDB string table.
1349*f6aab3d8Srobert   auto iter = checksums.at(file_id);
1350*f6aab3d8Srobert   if (iter == checksums.end())
1351*f6aab3d8Srobert     return llvm::make_error<RawError>(raw_error_code::no_entry);
1352*f6aab3d8Srobert 
1353*f6aab3d8Srobert   llvm::Expected<llvm::StringRef> efn = strings.getString(iter->FileNameOffset);
1354*f6aab3d8Srobert   if (!efn) {
1355*f6aab3d8Srobert     return efn.takeError();
1356*f6aab3d8Srobert   }
1357*f6aab3d8Srobert 
1358*f6aab3d8Srobert   // LLDB wants the index of the file in the list of support files.
1359*f6aab3d8Srobert   auto fn_iter = llvm::find(cii.m_file_list, *efn);
1360*f6aab3d8Srobert   if (fn_iter != cii.m_file_list.end())
1361*f6aab3d8Srobert     return std::distance(cii.m_file_list.begin(), fn_iter);
1362*f6aab3d8Srobert   return llvm::make_error<RawError>(raw_error_code::no_entry);
1363*f6aab3d8Srobert }
1364*f6aab3d8Srobert 
ParseSupportFiles(CompileUnit & comp_unit,FileSpecList & support_files)1365061da546Spatrick bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit,
1366061da546Spatrick                                             FileSpecList &support_files) {
1367061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1368061da546Spatrick   PdbSymUid cu_id(comp_unit.GetID());
1369061da546Spatrick   lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);
1370061da546Spatrick   CompilandIndexItem *cci =
1371061da546Spatrick       m_index->compilands().GetCompiland(cu_id.asCompiland().modi);
1372061da546Spatrick   lldbassert(cci);
1373061da546Spatrick 
1374061da546Spatrick   for (llvm::StringRef f : cci->m_file_list) {
1375061da546Spatrick     FileSpec::Style style =
1376061da546Spatrick         f.startswith("/") ? FileSpec::Style::posix : FileSpec::Style::windows;
1377061da546Spatrick     FileSpec spec(f, style);
1378061da546Spatrick     support_files.Append(spec);
1379061da546Spatrick   }
1380061da546Spatrick   return true;
1381061da546Spatrick }
1382061da546Spatrick 
ParseImportedModules(const SymbolContext & sc,std::vector<SourceModule> & imported_modules)1383061da546Spatrick bool SymbolFileNativePDB::ParseImportedModules(
1384061da546Spatrick     const SymbolContext &sc, std::vector<SourceModule> &imported_modules) {
1385061da546Spatrick   // PDB does not yet support module debug info
1386061da546Spatrick   return false;
1387061da546Spatrick }
1388061da546Spatrick 
ParseInlineSite(PdbCompilandSymId id,Address func_addr)1389*f6aab3d8Srobert void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id,
1390*f6aab3d8Srobert                                           Address func_addr) {
1391*f6aab3d8Srobert   lldb::user_id_t opaque_uid = toOpaqueUid(id);
1392*f6aab3d8Srobert   if (m_inline_sites.find(opaque_uid) != m_inline_sites.end())
1393*f6aab3d8Srobert     return;
1394*f6aab3d8Srobert 
1395*f6aab3d8Srobert   addr_t func_base = func_addr.GetFileAddress();
1396*f6aab3d8Srobert   CompilandIndexItem *cii = m_index->compilands().GetCompiland(id.modi);
1397*f6aab3d8Srobert   CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(id.offset);
1398*f6aab3d8Srobert   CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
1399*f6aab3d8Srobert 
1400*f6aab3d8Srobert   InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind()));
1401*f6aab3d8Srobert   cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site));
1402*f6aab3d8Srobert   PdbCompilandSymId parent_id(id.modi, inline_site.Parent);
1403*f6aab3d8Srobert 
1404*f6aab3d8Srobert   std::shared_ptr<InlineSite> inline_site_sp =
1405*f6aab3d8Srobert       std::make_shared<InlineSite>(parent_id);
1406*f6aab3d8Srobert 
1407*f6aab3d8Srobert   // Get the inlined function declaration info.
1408*f6aab3d8Srobert   auto iter = cii->m_inline_map.find(inline_site.Inlinee);
1409*f6aab3d8Srobert   if (iter == cii->m_inline_map.end())
1410*f6aab3d8Srobert     return;
1411*f6aab3d8Srobert   InlineeSourceLine inlinee_line = iter->second;
1412*f6aab3d8Srobert 
1413*f6aab3d8Srobert   const FileSpecList &files = comp_unit->GetSupportFiles();
1414*f6aab3d8Srobert   FileSpec decl_file;
1415*f6aab3d8Srobert   llvm::Expected<uint32_t> file_index_or_err =
1416*f6aab3d8Srobert       GetFileIndex(*cii, inlinee_line.Header->FileID);
1417*f6aab3d8Srobert   if (!file_index_or_err)
1418*f6aab3d8Srobert     return;
1419*f6aab3d8Srobert   uint32_t file_offset = file_index_or_err.get();
1420*f6aab3d8Srobert   decl_file = files.GetFileSpecAtIndex(file_offset);
1421*f6aab3d8Srobert   uint32_t decl_line = inlinee_line.Header->SourceLineNum;
1422*f6aab3d8Srobert   std::unique_ptr<Declaration> decl_up =
1423*f6aab3d8Srobert       std::make_unique<Declaration>(decl_file, decl_line);
1424*f6aab3d8Srobert 
1425*f6aab3d8Srobert   // Parse range and line info.
1426*f6aab3d8Srobert   uint32_t code_offset = 0;
1427*f6aab3d8Srobert   int32_t line_offset = 0;
1428*f6aab3d8Srobert   std::optional<uint32_t> code_offset_base;
1429*f6aab3d8Srobert   std::optional<uint32_t> code_offset_end;
1430*f6aab3d8Srobert   std::optional<int32_t> cur_line_offset;
1431*f6aab3d8Srobert   std::optional<int32_t> next_line_offset;
1432*f6aab3d8Srobert   std::optional<uint32_t> next_file_offset;
1433*f6aab3d8Srobert 
1434*f6aab3d8Srobert   bool is_terminal_entry = false;
1435*f6aab3d8Srobert   bool is_start_of_statement = true;
1436*f6aab3d8Srobert   // The first instruction is the prologue end.
1437*f6aab3d8Srobert   bool is_prologue_end = true;
1438*f6aab3d8Srobert 
1439*f6aab3d8Srobert   auto update_code_offset = [&](uint32_t code_delta) {
1440*f6aab3d8Srobert     if (!code_offset_base)
1441*f6aab3d8Srobert       code_offset_base = code_offset;
1442*f6aab3d8Srobert     else if (!code_offset_end)
1443*f6aab3d8Srobert       code_offset_end = *code_offset_base + code_delta;
1444*f6aab3d8Srobert   };
1445*f6aab3d8Srobert   auto update_line_offset = [&](int32_t line_delta) {
1446*f6aab3d8Srobert     line_offset += line_delta;
1447*f6aab3d8Srobert     if (!code_offset_base || !cur_line_offset)
1448*f6aab3d8Srobert       cur_line_offset = line_offset;
1449*f6aab3d8Srobert     else
1450*f6aab3d8Srobert       next_line_offset = line_offset;
1451*f6aab3d8Srobert     ;
1452*f6aab3d8Srobert   };
1453*f6aab3d8Srobert   auto update_file_offset = [&](uint32_t offset) {
1454*f6aab3d8Srobert     if (!code_offset_base)
1455*f6aab3d8Srobert       file_offset = offset;
1456*f6aab3d8Srobert     else
1457*f6aab3d8Srobert       next_file_offset = offset;
1458*f6aab3d8Srobert   };
1459*f6aab3d8Srobert 
1460*f6aab3d8Srobert   for (auto &annot : inline_site.annotations()) {
1461*f6aab3d8Srobert     switch (annot.OpCode) {
1462*f6aab3d8Srobert     case BinaryAnnotationsOpCode::CodeOffset:
1463*f6aab3d8Srobert     case BinaryAnnotationsOpCode::ChangeCodeOffset:
1464*f6aab3d8Srobert     case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
1465*f6aab3d8Srobert       code_offset += annot.U1;
1466*f6aab3d8Srobert       update_code_offset(annot.U1);
1467*f6aab3d8Srobert       break;
1468*f6aab3d8Srobert     case BinaryAnnotationsOpCode::ChangeLineOffset:
1469*f6aab3d8Srobert       update_line_offset(annot.S1);
1470*f6aab3d8Srobert       break;
1471*f6aab3d8Srobert     case BinaryAnnotationsOpCode::ChangeCodeLength:
1472*f6aab3d8Srobert       update_code_offset(annot.U1);
1473*f6aab3d8Srobert       code_offset += annot.U1;
1474*f6aab3d8Srobert       is_terminal_entry = true;
1475*f6aab3d8Srobert       break;
1476*f6aab3d8Srobert     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:
1477*f6aab3d8Srobert       code_offset += annot.U1;
1478*f6aab3d8Srobert       update_code_offset(annot.U1);
1479*f6aab3d8Srobert       update_line_offset(annot.S1);
1480*f6aab3d8Srobert       break;
1481*f6aab3d8Srobert     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:
1482*f6aab3d8Srobert       code_offset += annot.U2;
1483*f6aab3d8Srobert       update_code_offset(annot.U2);
1484*f6aab3d8Srobert       update_code_offset(annot.U1);
1485*f6aab3d8Srobert       code_offset += annot.U1;
1486*f6aab3d8Srobert       is_terminal_entry = true;
1487*f6aab3d8Srobert       break;
1488*f6aab3d8Srobert     case BinaryAnnotationsOpCode::ChangeFile:
1489*f6aab3d8Srobert       update_file_offset(annot.U1);
1490*f6aab3d8Srobert       break;
1491*f6aab3d8Srobert     default:
1492*f6aab3d8Srobert       break;
1493061da546Spatrick     }
1494061da546Spatrick 
1495*f6aab3d8Srobert     // Add range if current range is finished.
1496*f6aab3d8Srobert     if (code_offset_base && code_offset_end && cur_line_offset) {
1497*f6aab3d8Srobert       inline_site_sp->ranges.Append(RangeSourceLineVector::Entry(
1498*f6aab3d8Srobert           *code_offset_base, *code_offset_end - *code_offset_base,
1499*f6aab3d8Srobert           decl_line + *cur_line_offset));
1500*f6aab3d8Srobert       // Set base, end, file offset and line offset for next range.
1501*f6aab3d8Srobert       if (next_file_offset)
1502*f6aab3d8Srobert         file_offset = *next_file_offset;
1503*f6aab3d8Srobert       if (next_line_offset) {
1504*f6aab3d8Srobert         cur_line_offset = next_line_offset;
1505*f6aab3d8Srobert         next_line_offset = std::nullopt;
1506*f6aab3d8Srobert       }
1507*f6aab3d8Srobert       code_offset_base = is_terminal_entry ? std::nullopt : code_offset_end;
1508*f6aab3d8Srobert       code_offset_end = next_file_offset = std::nullopt;
1509*f6aab3d8Srobert     }
1510*f6aab3d8Srobert     if (code_offset_base && cur_line_offset) {
1511*f6aab3d8Srobert       if (is_terminal_entry) {
1512*f6aab3d8Srobert         LineTable::Entry line_entry(
1513*f6aab3d8Srobert             func_base + *code_offset_base, decl_line + *cur_line_offset, 0,
1514*f6aab3d8Srobert             file_offset, false, false, false, false, true);
1515*f6aab3d8Srobert         inline_site_sp->line_entries.push_back(line_entry);
1516*f6aab3d8Srobert       } else {
1517*f6aab3d8Srobert         LineTable::Entry line_entry(func_base + *code_offset_base,
1518*f6aab3d8Srobert                                     decl_line + *cur_line_offset, 0,
1519*f6aab3d8Srobert                                     file_offset, is_start_of_statement, false,
1520*f6aab3d8Srobert                                     is_prologue_end, false, false);
1521*f6aab3d8Srobert         inline_site_sp->line_entries.push_back(line_entry);
1522*f6aab3d8Srobert         is_prologue_end = false;
1523*f6aab3d8Srobert         is_start_of_statement = false;
1524*f6aab3d8Srobert       }
1525*f6aab3d8Srobert     }
1526*f6aab3d8Srobert     if (is_terminal_entry)
1527*f6aab3d8Srobert       is_start_of_statement = true;
1528*f6aab3d8Srobert     is_terminal_entry = false;
1529*f6aab3d8Srobert   }
1530*f6aab3d8Srobert 
1531*f6aab3d8Srobert   inline_site_sp->ranges.Sort();
1532*f6aab3d8Srobert 
1533*f6aab3d8Srobert   // Get the inlined function callsite info.
1534*f6aab3d8Srobert   std::unique_ptr<Declaration> callsite_up;
1535*f6aab3d8Srobert   if (!inline_site_sp->ranges.IsEmpty()) {
1536*f6aab3d8Srobert     auto *entry = inline_site_sp->ranges.GetEntryAtIndex(0);
1537*f6aab3d8Srobert     addr_t base_offset = entry->GetRangeBase();
1538*f6aab3d8Srobert     if (cii->m_debug_stream.readSymbolAtOffset(parent_id.offset).kind() ==
1539*f6aab3d8Srobert         S_INLINESITE) {
1540*f6aab3d8Srobert       // Its parent is another inline site, lookup parent site's range vector
1541*f6aab3d8Srobert       // for callsite line.
1542*f6aab3d8Srobert       ParseInlineSite(parent_id, func_base);
1543*f6aab3d8Srobert       std::shared_ptr<InlineSite> parent_site =
1544*f6aab3d8Srobert           m_inline_sites[toOpaqueUid(parent_id)];
1545*f6aab3d8Srobert       FileSpec &parent_decl_file =
1546*f6aab3d8Srobert           parent_site->inline_function_info->GetDeclaration().GetFile();
1547*f6aab3d8Srobert       if (auto *parent_entry =
1548*f6aab3d8Srobert               parent_site->ranges.FindEntryThatContains(base_offset)) {
1549*f6aab3d8Srobert         callsite_up =
1550*f6aab3d8Srobert             std::make_unique<Declaration>(parent_decl_file, parent_entry->data);
1551*f6aab3d8Srobert       }
1552*f6aab3d8Srobert     } else {
1553*f6aab3d8Srobert       // Its parent is a function, lookup global line table for callsite.
1554*f6aab3d8Srobert       if (auto *entry = cii->m_global_line_table.FindEntryThatContains(
1555*f6aab3d8Srobert               func_base + base_offset)) {
1556*f6aab3d8Srobert         const FileSpec &callsite_file =
1557*f6aab3d8Srobert             files.GetFileSpecAtIndex(entry->data.first);
1558*f6aab3d8Srobert         callsite_up =
1559*f6aab3d8Srobert             std::make_unique<Declaration>(callsite_file, entry->data.second);
1560*f6aab3d8Srobert       }
1561*f6aab3d8Srobert     }
1562*f6aab3d8Srobert   }
1563*f6aab3d8Srobert 
1564*f6aab3d8Srobert   // Get the inlined function name.
1565*f6aab3d8Srobert   CVType inlinee_cvt = m_index->ipi().getType(inline_site.Inlinee);
1566*f6aab3d8Srobert   std::string inlinee_name;
1567*f6aab3d8Srobert   if (inlinee_cvt.kind() == LF_MFUNC_ID) {
1568*f6aab3d8Srobert     MemberFuncIdRecord mfr;
1569*f6aab3d8Srobert     cantFail(
1570*f6aab3d8Srobert         TypeDeserializer::deserializeAs<MemberFuncIdRecord>(inlinee_cvt, mfr));
1571*f6aab3d8Srobert     LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
1572*f6aab3d8Srobert     inlinee_name.append(std::string(types.getTypeName(mfr.ClassType)));
1573*f6aab3d8Srobert     inlinee_name.append("::");
1574*f6aab3d8Srobert     inlinee_name.append(mfr.getName().str());
1575*f6aab3d8Srobert   } else if (inlinee_cvt.kind() == LF_FUNC_ID) {
1576*f6aab3d8Srobert     FuncIdRecord fir;
1577*f6aab3d8Srobert     cantFail(TypeDeserializer::deserializeAs<FuncIdRecord>(inlinee_cvt, fir));
1578*f6aab3d8Srobert     TypeIndex parent_idx = fir.getParentScope();
1579*f6aab3d8Srobert     if (!parent_idx.isNoneType()) {
1580*f6aab3d8Srobert       LazyRandomTypeCollection &ids = m_index->ipi().typeCollection();
1581*f6aab3d8Srobert       inlinee_name.append(std::string(ids.getTypeName(parent_idx)));
1582*f6aab3d8Srobert       inlinee_name.append("::");
1583*f6aab3d8Srobert     }
1584*f6aab3d8Srobert     inlinee_name.append(fir.getName().str());
1585*f6aab3d8Srobert   }
1586*f6aab3d8Srobert   inline_site_sp->inline_function_info = std::make_shared<InlineFunctionInfo>(
1587*f6aab3d8Srobert       inlinee_name.c_str(), llvm::StringRef(), decl_up.get(),
1588*f6aab3d8Srobert       callsite_up.get());
1589*f6aab3d8Srobert 
1590*f6aab3d8Srobert   m_inline_sites[opaque_uid] = inline_site_sp;
1591*f6aab3d8Srobert }
1592*f6aab3d8Srobert 
ParseBlocksRecursive(Function & func)1593*f6aab3d8Srobert size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) {
1594*f6aab3d8Srobert   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1595*f6aab3d8Srobert   PdbCompilandSymId func_id = PdbSymUid(func.GetID()).asCompilandSym();
1596*f6aab3d8Srobert   // After we iterate through inline sites inside the function, we already get
1597*f6aab3d8Srobert   // all the info needed, removing from the map to save memory.
1598*f6aab3d8Srobert   std::set<uint64_t> remove_uids;
1599*f6aab3d8Srobert   auto parse_blocks = [&](SymbolKind kind, PdbCompilandSymId id) {
1600*f6aab3d8Srobert     if (kind == S_GPROC32 || kind == S_LPROC32 || kind == S_BLOCK32 ||
1601*f6aab3d8Srobert         kind == S_INLINESITE) {
1602*f6aab3d8Srobert       GetOrCreateBlock(id);
1603*f6aab3d8Srobert       if (kind == S_INLINESITE)
1604*f6aab3d8Srobert         remove_uids.insert(toOpaqueUid(id));
1605*f6aab3d8Srobert       return true;
1606*f6aab3d8Srobert     }
1607*f6aab3d8Srobert     return false;
1608*f6aab3d8Srobert   };
1609*f6aab3d8Srobert   size_t count = ParseSymbolArrayInScope(func_id, parse_blocks);
1610*f6aab3d8Srobert   for (uint64_t uid : remove_uids) {
1611*f6aab3d8Srobert     m_inline_sites.erase(uid);
1612*f6aab3d8Srobert   }
1613*f6aab3d8Srobert   return count;
1614*f6aab3d8Srobert }
1615*f6aab3d8Srobert 
ParseSymbolArrayInScope(PdbCompilandSymId parent_id,llvm::function_ref<bool (SymbolKind,PdbCompilandSymId)> fn)1616*f6aab3d8Srobert size_t SymbolFileNativePDB::ParseSymbolArrayInScope(
1617*f6aab3d8Srobert     PdbCompilandSymId parent_id,
1618*f6aab3d8Srobert     llvm::function_ref<bool(SymbolKind, PdbCompilandSymId)> fn) {
1619*f6aab3d8Srobert   CompilandIndexItem *cii = m_index->compilands().GetCompiland(parent_id.modi);
1620*f6aab3d8Srobert   CVSymbolArray syms =
1621*f6aab3d8Srobert       cii->m_debug_stream.getSymbolArrayForScope(parent_id.offset);
1622*f6aab3d8Srobert 
1623*f6aab3d8Srobert   size_t count = 1;
1624*f6aab3d8Srobert   for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
1625*f6aab3d8Srobert     PdbCompilandSymId child_id(parent_id.modi, iter.offset());
1626*f6aab3d8Srobert     if (fn(iter->kind(), child_id))
1627*f6aab3d8Srobert       ++count;
1628*f6aab3d8Srobert   }
1629*f6aab3d8Srobert 
1630*f6aab3d8Srobert   return count;
1631*f6aab3d8Srobert }
1632*f6aab3d8Srobert 
DumpClangAST(Stream & s)1633*f6aab3d8Srobert void SymbolFileNativePDB::DumpClangAST(Stream &s) {
1634*f6aab3d8Srobert   auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
1635*f6aab3d8Srobert   if (!ts_or_err)
1636*f6aab3d8Srobert     return;
1637*f6aab3d8Srobert   auto ts = *ts_or_err;
1638*f6aab3d8Srobert   TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
1639*f6aab3d8Srobert   if (!clang)
1640*f6aab3d8Srobert     return;
1641*f6aab3d8Srobert   clang->GetNativePDBParser()->Dump(s);
1642*f6aab3d8Srobert }
1643061da546Spatrick 
FindGlobalVariables(ConstString name,const CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,VariableList & variables)1644061da546Spatrick void SymbolFileNativePDB::FindGlobalVariables(
1645dda28197Spatrick     ConstString name, const CompilerDeclContext &parent_decl_ctx,
1646061da546Spatrick     uint32_t max_matches, VariableList &variables) {
1647061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1648061da546Spatrick   using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
1649061da546Spatrick 
1650061da546Spatrick   std::vector<SymbolAndOffset> results = m_index->globals().findRecordsByName(
1651061da546Spatrick       name.GetStringRef(), m_index->symrecords());
1652061da546Spatrick   for (const SymbolAndOffset &result : results) {
1653061da546Spatrick     switch (result.second.kind()) {
1654061da546Spatrick     case SymbolKind::S_GDATA32:
1655061da546Spatrick     case SymbolKind::S_LDATA32:
1656061da546Spatrick     case SymbolKind::S_GTHREAD32:
1657061da546Spatrick     case SymbolKind::S_LTHREAD32:
1658061da546Spatrick     case SymbolKind::S_CONSTANT: {
1659061da546Spatrick       PdbGlobalSymId global(result.first, false);
1660*f6aab3d8Srobert       if (VariableSP var = GetOrCreateGlobalVariable(global))
1661061da546Spatrick         variables.AddVariable(var);
1662061da546Spatrick       break;
1663061da546Spatrick     }
1664061da546Spatrick     default:
1665061da546Spatrick       continue;
1666061da546Spatrick     }
1667061da546Spatrick   }
1668061da546Spatrick }
1669061da546Spatrick 
FindFunctions(const Module::LookupInfo & lookup_info,const CompilerDeclContext & parent_decl_ctx,bool include_inlines,SymbolContextList & sc_list)1670061da546Spatrick void SymbolFileNativePDB::FindFunctions(
1671*f6aab3d8Srobert     const Module::LookupInfo &lookup_info,
1672*f6aab3d8Srobert     const CompilerDeclContext &parent_decl_ctx, bool include_inlines,
1673061da546Spatrick     SymbolContextList &sc_list) {
1674061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1675*f6aab3d8Srobert   ConstString name = lookup_info.GetLookupName();
1676*f6aab3d8Srobert   FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
1677*f6aab3d8Srobert   if (name_type_mask & eFunctionNameTypeFull)
1678*f6aab3d8Srobert     name = lookup_info.GetName();
1679*f6aab3d8Srobert 
1680*f6aab3d8Srobert   // For now we only support lookup by method name or full name.
1681*f6aab3d8Srobert   if (!(name_type_mask & eFunctionNameTypeFull ||
1682*f6aab3d8Srobert         name_type_mask & eFunctionNameTypeMethod))
1683061da546Spatrick     return;
1684061da546Spatrick 
1685061da546Spatrick   using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
1686061da546Spatrick 
1687061da546Spatrick   std::vector<SymbolAndOffset> matches = m_index->globals().findRecordsByName(
1688061da546Spatrick       name.GetStringRef(), m_index->symrecords());
1689061da546Spatrick   for (const SymbolAndOffset &match : matches) {
1690061da546Spatrick     if (match.second.kind() != S_PROCREF && match.second.kind() != S_LPROCREF)
1691061da546Spatrick       continue;
1692061da546Spatrick     ProcRefSym proc(match.second.kind());
1693061da546Spatrick     cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(match.second, proc));
1694061da546Spatrick 
1695061da546Spatrick     if (!IsValidRecord(proc))
1696061da546Spatrick       continue;
1697061da546Spatrick 
1698061da546Spatrick     CompilandIndexItem &cci =
1699061da546Spatrick         m_index->compilands().GetOrCreateCompiland(proc.modi());
1700061da546Spatrick     SymbolContext sc;
1701061da546Spatrick 
1702061da546Spatrick     sc.comp_unit = GetOrCreateCompileUnit(cci).get();
1703061da546Spatrick     PdbCompilandSymId func_id(proc.modi(), proc.SymOffset);
1704061da546Spatrick     sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get();
1705061da546Spatrick 
1706061da546Spatrick     sc_list.Append(sc);
1707061da546Spatrick   }
1708061da546Spatrick }
1709061da546Spatrick 
FindFunctions(const RegularExpression & regex,bool include_inlines,SymbolContextList & sc_list)1710061da546Spatrick void SymbolFileNativePDB::FindFunctions(const RegularExpression &regex,
1711061da546Spatrick                                         bool include_inlines,
1712061da546Spatrick                                         SymbolContextList &sc_list) {}
1713061da546Spatrick 
FindTypes(ConstString name,const CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,llvm::DenseSet<SymbolFile * > & searched_symbol_files,TypeMap & types)1714061da546Spatrick void SymbolFileNativePDB::FindTypes(
1715dda28197Spatrick     ConstString name, const CompilerDeclContext &parent_decl_ctx,
1716061da546Spatrick     uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files,
1717061da546Spatrick     TypeMap &types) {
1718061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1719061da546Spatrick   if (!name)
1720061da546Spatrick     return;
1721061da546Spatrick 
1722061da546Spatrick   searched_symbol_files.clear();
1723061da546Spatrick   searched_symbol_files.insert(this);
1724061da546Spatrick 
1725061da546Spatrick   // There is an assumption 'name' is not a regex
1726061da546Spatrick   FindTypesByName(name.GetStringRef(), max_matches, types);
1727061da546Spatrick }
1728061da546Spatrick 
FindTypes(llvm::ArrayRef<CompilerContext> pattern,LanguageSet languages,llvm::DenseSet<SymbolFile * > & searched_symbol_files,TypeMap & types)1729061da546Spatrick void SymbolFileNativePDB::FindTypes(
1730061da546Spatrick     llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
1731061da546Spatrick     llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {}
1732061da546Spatrick 
FindTypesByName(llvm::StringRef name,uint32_t max_matches,TypeMap & types)1733061da546Spatrick void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name,
1734061da546Spatrick                                           uint32_t max_matches,
1735061da546Spatrick                                           TypeMap &types) {
1736061da546Spatrick 
1737061da546Spatrick   std::vector<TypeIndex> matches = m_index->tpi().findRecordsByName(name);
1738061da546Spatrick   if (max_matches > 0 && max_matches < matches.size())
1739061da546Spatrick     matches.resize(max_matches);
1740061da546Spatrick 
1741061da546Spatrick   for (TypeIndex ti : matches) {
1742061da546Spatrick     TypeSP type = GetOrCreateType(ti);
1743061da546Spatrick     if (!type)
1744061da546Spatrick       continue;
1745061da546Spatrick 
1746061da546Spatrick     types.Insert(type);
1747061da546Spatrick   }
1748061da546Spatrick }
1749061da546Spatrick 
ParseTypes(CompileUnit & comp_unit)1750061da546Spatrick size_t SymbolFileNativePDB::ParseTypes(CompileUnit &comp_unit) {
1751061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1752061da546Spatrick   // Only do the full type scan the first time.
1753061da546Spatrick   if (m_done_full_type_scan)
1754061da546Spatrick     return 0;
1755061da546Spatrick 
1756061da546Spatrick   const size_t old_count = GetTypeList().GetSize();
1757061da546Spatrick   LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
1758061da546Spatrick 
1759061da546Spatrick   // First process the entire TPI stream.
1760061da546Spatrick   for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
1761061da546Spatrick     TypeSP type = GetOrCreateType(*ti);
1762061da546Spatrick     if (type)
1763061da546Spatrick       (void)type->GetFullCompilerType();
1764061da546Spatrick   }
1765061da546Spatrick 
1766061da546Spatrick   // Next look for S_UDT records in the globals stream.
1767061da546Spatrick   for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
1768061da546Spatrick     PdbGlobalSymId global{gid, false};
1769061da546Spatrick     CVSymbol sym = m_index->ReadSymbolRecord(global);
1770061da546Spatrick     if (sym.kind() != S_UDT)
1771061da546Spatrick       continue;
1772061da546Spatrick 
1773061da546Spatrick     UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
1774061da546Spatrick     bool is_typedef = true;
1775061da546Spatrick     if (IsTagRecord(PdbTypeSymId{udt.Type, false}, m_index->tpi())) {
1776061da546Spatrick       CVType cvt = m_index->tpi().getType(udt.Type);
1777061da546Spatrick       llvm::StringRef name = CVTagRecord::create(cvt).name();
1778061da546Spatrick       if (name == udt.Name)
1779061da546Spatrick         is_typedef = false;
1780061da546Spatrick     }
1781061da546Spatrick 
1782061da546Spatrick     if (is_typedef)
1783061da546Spatrick       GetOrCreateTypedef(global);
1784061da546Spatrick   }
1785061da546Spatrick 
1786061da546Spatrick   const size_t new_count = GetTypeList().GetSize();
1787061da546Spatrick 
1788061da546Spatrick   m_done_full_type_scan = true;
1789061da546Spatrick 
1790061da546Spatrick   return new_count - old_count;
1791061da546Spatrick }
1792061da546Spatrick 
1793061da546Spatrick size_t
ParseVariablesForCompileUnit(CompileUnit & comp_unit,VariableList & variables)1794061da546Spatrick SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit,
1795061da546Spatrick                                                   VariableList &variables) {
1796061da546Spatrick   PdbSymUid sym_uid(comp_unit.GetID());
1797061da546Spatrick   lldbassert(sym_uid.kind() == PdbSymUidKind::Compiland);
1798061da546Spatrick   return 0;
1799061da546Spatrick }
1800061da546Spatrick 
CreateLocalVariable(PdbCompilandSymId scope_id,PdbCompilandSymId var_id,bool is_param)1801061da546Spatrick VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
1802061da546Spatrick                                                     PdbCompilandSymId var_id,
1803061da546Spatrick                                                     bool is_param) {
1804061da546Spatrick   ModuleSP module = GetObjectFile()->GetModule();
1805061da546Spatrick   Block &block = GetOrCreateBlock(scope_id);
1806*f6aab3d8Srobert   // Get function block.
1807*f6aab3d8Srobert   Block *func_block = &block;
1808*f6aab3d8Srobert   while (func_block->GetParent()) {
1809*f6aab3d8Srobert     func_block = func_block->GetParent();
1810*f6aab3d8Srobert   }
1811*f6aab3d8Srobert   Address addr;
1812*f6aab3d8Srobert   func_block->GetStartAddress(addr);
1813061da546Spatrick   VariableInfo var_info =
1814*f6aab3d8Srobert       GetVariableLocationInfo(*m_index, var_id, *func_block, module);
1815*f6aab3d8Srobert   Function *func = func_block->CalculateSymbolContextFunction();
1816*f6aab3d8Srobert   if (!func)
1817061da546Spatrick     return nullptr;
1818*f6aab3d8Srobert   // Use empty dwarf expr if optimized away so that it won't be filtered out
1819*f6aab3d8Srobert   // when lookuping local variables in this scope.
1820*f6aab3d8Srobert   if (!var_info.location.IsValid())
1821*f6aab3d8Srobert     var_info.location = DWARFExpressionList(module, DWARFExpression(), nullptr);
1822*f6aab3d8Srobert   var_info.location.SetFuncFileAddress(
1823*f6aab3d8Srobert       func->GetAddressRange().GetBaseAddress().GetFileAddress());
1824061da546Spatrick   CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
1825061da546Spatrick   CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
1826061da546Spatrick   TypeSP type_sp = GetOrCreateType(var_info.type);
1827*f6aab3d8Srobert   if (!type_sp)
1828*f6aab3d8Srobert     return nullptr;
1829061da546Spatrick   std::string name = var_info.name.str();
1830061da546Spatrick   Declaration decl;
1831061da546Spatrick   SymbolFileTypeSP sftype =
1832061da546Spatrick       std::make_shared<SymbolFileType>(*this, type_sp->GetID());
1833061da546Spatrick 
1834*f6aab3d8Srobert   is_param |= var_info.is_param;
1835061da546Spatrick   ValueType var_scope =
1836061da546Spatrick       is_param ? eValueTypeVariableArgument : eValueTypeVariableLocal;
1837be691f3bSpatrick   bool external = false;
1838be691f3bSpatrick   bool artificial = false;
1839be691f3bSpatrick   bool location_is_constant_data = false;
1840be691f3bSpatrick   bool static_member = false;
1841*f6aab3d8Srobert   Variable::RangeList scope_ranges;
1842061da546Spatrick   VariableSP var_sp = std::make_shared<Variable>(
1843061da546Spatrick       toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope,
1844*f6aab3d8Srobert       &block, scope_ranges, &decl, var_info.location, external, artificial,
1845*f6aab3d8Srobert       location_is_constant_data, static_member);
1846*f6aab3d8Srobert   if (!is_param) {
1847*f6aab3d8Srobert     auto ts_or_err = GetTypeSystemForLanguage(comp_unit_sp->GetLanguage());
1848*f6aab3d8Srobert     if (auto err = ts_or_err.takeError())
1849*f6aab3d8Srobert       return nullptr;
1850*f6aab3d8Srobert     auto ts = *ts_or_err;
1851*f6aab3d8Srobert     if (!ts)
1852*f6aab3d8Srobert       return nullptr;
1853061da546Spatrick 
1854*f6aab3d8Srobert     ts->GetNativePDBParser()->GetOrCreateVariableDecl(scope_id, var_id);
1855*f6aab3d8Srobert   }
1856061da546Spatrick   m_local_variables[toOpaqueUid(var_id)] = var_sp;
1857061da546Spatrick   return var_sp;
1858061da546Spatrick }
1859061da546Spatrick 
GetOrCreateLocalVariable(PdbCompilandSymId scope_id,PdbCompilandSymId var_id,bool is_param)1860061da546Spatrick VariableSP SymbolFileNativePDB::GetOrCreateLocalVariable(
1861061da546Spatrick     PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param) {
1862061da546Spatrick   auto iter = m_local_variables.find(toOpaqueUid(var_id));
1863061da546Spatrick   if (iter != m_local_variables.end())
1864061da546Spatrick     return iter->second;
1865061da546Spatrick 
1866061da546Spatrick   return CreateLocalVariable(scope_id, var_id, is_param);
1867061da546Spatrick }
1868061da546Spatrick 
CreateTypedef(PdbGlobalSymId id)1869061da546Spatrick TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
1870061da546Spatrick   CVSymbol sym = m_index->ReadSymbolRecord(id);
1871061da546Spatrick   lldbassert(sym.kind() == SymbolKind::S_UDT);
1872061da546Spatrick 
1873061da546Spatrick   UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
1874061da546Spatrick 
1875061da546Spatrick   TypeSP target_type = GetOrCreateType(udt.Type);
1876061da546Spatrick 
1877*f6aab3d8Srobert   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
1878*f6aab3d8Srobert   if (auto err = ts_or_err.takeError())
1879*f6aab3d8Srobert     return nullptr;
1880*f6aab3d8Srobert   auto ts = *ts_or_err;
1881*f6aab3d8Srobert   if (!ts)
1882*f6aab3d8Srobert     return nullptr;
1883*f6aab3d8Srobert 
1884*f6aab3d8Srobert   ts->GetNativePDBParser()->GetOrCreateTypedefDecl(id);
1885061da546Spatrick 
1886061da546Spatrick   Declaration decl;
1887*f6aab3d8Srobert   return MakeType(
1888*f6aab3d8Srobert       toOpaqueUid(id), ConstString(udt.Name), target_type->GetByteSize(nullptr),
1889*f6aab3d8Srobert       nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID,
1890*f6aab3d8Srobert       decl, target_type->GetForwardCompilerType(),
1891061da546Spatrick       lldb_private::Type::ResolveState::Forward);
1892061da546Spatrick }
1893061da546Spatrick 
GetOrCreateTypedef(PdbGlobalSymId id)1894061da546Spatrick TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) {
1895061da546Spatrick   auto iter = m_types.find(toOpaqueUid(id));
1896061da546Spatrick   if (iter != m_types.end())
1897061da546Spatrick     return iter->second;
1898061da546Spatrick 
1899061da546Spatrick   return CreateTypedef(id);
1900061da546Spatrick }
1901061da546Spatrick 
ParseVariablesForBlock(PdbCompilandSymId block_id)1902061da546Spatrick size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) {
1903061da546Spatrick   Block &block = GetOrCreateBlock(block_id);
1904061da546Spatrick 
1905061da546Spatrick   size_t count = 0;
1906061da546Spatrick 
1907061da546Spatrick   CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
1908061da546Spatrick   CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
1909061da546Spatrick   uint32_t params_remaining = 0;
1910061da546Spatrick   switch (sym.kind()) {
1911061da546Spatrick   case S_GPROC32:
1912061da546Spatrick   case S_LPROC32: {
1913061da546Spatrick     ProcSym proc(static_cast<SymbolRecordKind>(sym.kind()));
1914061da546Spatrick     cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym, proc));
1915061da546Spatrick     CVType signature = m_index->tpi().getType(proc.FunctionType);
1916*f6aab3d8Srobert     if (signature.kind() == LF_PROCEDURE) {
1917061da546Spatrick       ProcedureRecord sig;
1918*f6aab3d8Srobert       if (llvm::Error e = TypeDeserializer::deserializeAs<ProcedureRecord>(
1919*f6aab3d8Srobert               signature, sig)) {
1920*f6aab3d8Srobert         llvm::consumeError(std::move(e));
1921*f6aab3d8Srobert         return 0;
1922*f6aab3d8Srobert       }
1923061da546Spatrick       params_remaining = sig.getParameterCount();
1924*f6aab3d8Srobert     } else if (signature.kind() == LF_MFUNCTION) {
1925*f6aab3d8Srobert       MemberFunctionRecord sig;
1926*f6aab3d8Srobert       if (llvm::Error e = TypeDeserializer::deserializeAs<MemberFunctionRecord>(
1927*f6aab3d8Srobert               signature, sig)) {
1928*f6aab3d8Srobert         llvm::consumeError(std::move(e));
1929*f6aab3d8Srobert         return 0;
1930*f6aab3d8Srobert       }
1931*f6aab3d8Srobert       params_remaining = sig.getParameterCount();
1932*f6aab3d8Srobert     } else
1933*f6aab3d8Srobert       return 0;
1934061da546Spatrick     break;
1935061da546Spatrick   }
1936061da546Spatrick   case S_BLOCK32:
1937061da546Spatrick     break;
1938*f6aab3d8Srobert   case S_INLINESITE:
1939*f6aab3d8Srobert     break;
1940061da546Spatrick   default:
1941061da546Spatrick     lldbassert(false && "Symbol is not a block!");
1942061da546Spatrick     return 0;
1943061da546Spatrick   }
1944061da546Spatrick 
1945061da546Spatrick   VariableListSP variables = block.GetBlockVariableList(false);
1946061da546Spatrick   if (!variables) {
1947061da546Spatrick     variables = std::make_shared<VariableList>();
1948061da546Spatrick     block.SetVariableList(variables);
1949061da546Spatrick   }
1950061da546Spatrick 
1951061da546Spatrick   CVSymbolArray syms = limitSymbolArrayToScope(
1952061da546Spatrick       cii->m_debug_stream.getSymbolArray(), block_id.offset);
1953061da546Spatrick 
1954061da546Spatrick   // Skip the first record since it's a PROC32 or BLOCK32, and there's
1955061da546Spatrick   // no point examining it since we know it's not a local variable.
1956061da546Spatrick   syms.drop_front();
1957061da546Spatrick   auto iter = syms.begin();
1958061da546Spatrick   auto end = syms.end();
1959061da546Spatrick 
1960061da546Spatrick   while (iter != end) {
1961061da546Spatrick     uint32_t record_offset = iter.offset();
1962061da546Spatrick     CVSymbol variable_cvs = *iter;
1963061da546Spatrick     PdbCompilandSymId child_sym_id(block_id.modi, record_offset);
1964061da546Spatrick     ++iter;
1965061da546Spatrick 
1966*f6aab3d8Srobert     // If this is a block or inline site, recurse into its children and then
1967*f6aab3d8Srobert     // skip it.
1968*f6aab3d8Srobert     if (variable_cvs.kind() == S_BLOCK32 ||
1969*f6aab3d8Srobert         variable_cvs.kind() == S_INLINESITE) {
1970061da546Spatrick       uint32_t block_end = getScopeEndOffset(variable_cvs);
1971061da546Spatrick       count += ParseVariablesForBlock(child_sym_id);
1972061da546Spatrick       iter = syms.at(block_end);
1973061da546Spatrick       continue;
1974061da546Spatrick     }
1975061da546Spatrick 
1976061da546Spatrick     bool is_param = params_remaining > 0;
1977061da546Spatrick     VariableSP variable;
1978061da546Spatrick     switch (variable_cvs.kind()) {
1979061da546Spatrick     case S_REGREL32:
1980061da546Spatrick     case S_REGISTER:
1981061da546Spatrick     case S_LOCAL:
1982061da546Spatrick       variable = GetOrCreateLocalVariable(block_id, child_sym_id, is_param);
1983061da546Spatrick       if (is_param)
1984061da546Spatrick         --params_remaining;
1985061da546Spatrick       if (variable)
1986061da546Spatrick         variables->AddVariableIfUnique(variable);
1987061da546Spatrick       break;
1988061da546Spatrick     default:
1989061da546Spatrick       break;
1990061da546Spatrick     }
1991061da546Spatrick   }
1992061da546Spatrick 
1993061da546Spatrick   // Pass false for set_children, since we call this recursively so that the
1994061da546Spatrick   // children will call this for themselves.
1995061da546Spatrick   block.SetDidParseVariables(true, false);
1996061da546Spatrick 
1997061da546Spatrick   return count;
1998061da546Spatrick }
1999061da546Spatrick 
ParseVariablesForContext(const SymbolContext & sc)2000061da546Spatrick size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) {
2001061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2002061da546Spatrick   lldbassert(sc.function || sc.comp_unit);
2003061da546Spatrick 
2004061da546Spatrick   VariableListSP variables;
2005061da546Spatrick   if (sc.block) {
2006061da546Spatrick     PdbSymUid block_id(sc.block->GetID());
2007061da546Spatrick 
2008061da546Spatrick     size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
2009061da546Spatrick     return count;
2010061da546Spatrick   }
2011061da546Spatrick 
2012061da546Spatrick   if (sc.function) {
2013061da546Spatrick     PdbSymUid block_id(sc.function->GetID());
2014061da546Spatrick 
2015061da546Spatrick     size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
2016061da546Spatrick     return count;
2017061da546Spatrick   }
2018061da546Spatrick 
2019061da546Spatrick   if (sc.comp_unit) {
2020061da546Spatrick     variables = sc.comp_unit->GetVariableList(false);
2021061da546Spatrick     if (!variables) {
2022061da546Spatrick       variables = std::make_shared<VariableList>();
2023061da546Spatrick       sc.comp_unit->SetVariableList(variables);
2024061da546Spatrick     }
2025061da546Spatrick     return ParseVariablesForCompileUnit(*sc.comp_unit, *variables);
2026061da546Spatrick   }
2027061da546Spatrick 
2028061da546Spatrick   llvm_unreachable("Unreachable!");
2029061da546Spatrick }
2030061da546Spatrick 
GetDeclForUID(lldb::user_id_t uid)2031061da546Spatrick CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) {
2032*f6aab3d8Srobert   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
2033*f6aab3d8Srobert   if (auto err = ts_or_err.takeError())
2034*f6aab3d8Srobert     return CompilerDecl();
2035*f6aab3d8Srobert   auto ts = *ts_or_err;
2036*f6aab3d8Srobert   if (!ts)
2037*f6aab3d8Srobert     return {};
2038*f6aab3d8Srobert 
2039*f6aab3d8Srobert   if (auto decl = ts->GetNativePDBParser()->GetOrCreateDeclForUid(uid))
2040*f6aab3d8Srobert     return *decl;
2041061da546Spatrick   return CompilerDecl();
2042061da546Spatrick }
2043061da546Spatrick 
2044061da546Spatrick CompilerDeclContext
GetDeclContextForUID(lldb::user_id_t uid)2045061da546Spatrick SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) {
2046*f6aab3d8Srobert   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
2047*f6aab3d8Srobert   if (auto err = ts_or_err.takeError())
2048*f6aab3d8Srobert     return {};
2049*f6aab3d8Srobert   auto ts = *ts_or_err;
2050*f6aab3d8Srobert   if (!ts)
2051*f6aab3d8Srobert     return {};
2052*f6aab3d8Srobert 
2053*f6aab3d8Srobert   PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
2054061da546Spatrick   clang::DeclContext *context =
2055*f6aab3d8Srobert       ast_builder->GetOrCreateDeclContextForUid(PdbSymUid(uid));
2056061da546Spatrick   if (!context)
2057061da546Spatrick     return {};
2058061da546Spatrick 
2059*f6aab3d8Srobert   return ast_builder->ToCompilerDeclContext(*context);
2060061da546Spatrick }
2061061da546Spatrick 
2062061da546Spatrick CompilerDeclContext
GetDeclContextContainingUID(lldb::user_id_t uid)2063061da546Spatrick SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
2064*f6aab3d8Srobert   auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
2065*f6aab3d8Srobert   if (auto err = ts_or_err.takeError())
2066*f6aab3d8Srobert     return CompilerDeclContext();
2067*f6aab3d8Srobert   auto ts = *ts_or_err;
2068*f6aab3d8Srobert   if (!ts)
2069*f6aab3d8Srobert     return {};
2070*f6aab3d8Srobert 
2071*f6aab3d8Srobert   PdbAstBuilder *ast_builder = ts->GetNativePDBParser();
2072*f6aab3d8Srobert   clang::DeclContext *context = ast_builder->GetParentDeclContext(PdbSymUid(uid));
2073*f6aab3d8Srobert   if (!context)
2074*f6aab3d8Srobert     return CompilerDeclContext();
2075*f6aab3d8Srobert   return ast_builder->ToCompilerDeclContext(*context);
2076061da546Spatrick }
2077061da546Spatrick 
ResolveTypeUID(lldb::user_id_t type_uid)2078061da546Spatrick Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
2079061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2080061da546Spatrick   auto iter = m_types.find(type_uid);
2081061da546Spatrick   // lldb should not be passing us non-sensical type uids.  the only way it
2082061da546Spatrick   // could have a type uid in the first place is if we handed it out, in which
2083061da546Spatrick   // case we should know about the type.  However, that doesn't mean we've
2084061da546Spatrick   // instantiated it yet.  We can vend out a UID for a future type.  So if the
2085061da546Spatrick   // type doesn't exist, let's instantiate it now.
2086061da546Spatrick   if (iter != m_types.end())
2087061da546Spatrick     return &*iter->second;
2088061da546Spatrick 
2089061da546Spatrick   PdbSymUid uid(type_uid);
2090061da546Spatrick   lldbassert(uid.kind() == PdbSymUidKind::Type);
2091061da546Spatrick   PdbTypeSymId type_id = uid.asTypeSym();
2092061da546Spatrick   if (type_id.index.isNoneType())
2093061da546Spatrick     return nullptr;
2094061da546Spatrick 
2095061da546Spatrick   TypeSP type_sp = CreateAndCacheType(type_id);
2096*f6aab3d8Srobert   if (!type_sp)
2097*f6aab3d8Srobert     return nullptr;
2098061da546Spatrick   return &*type_sp;
2099061da546Spatrick }
2100061da546Spatrick 
2101*f6aab3d8Srobert std::optional<SymbolFile::ArrayInfo>
GetDynamicArrayInfoForUID(lldb::user_id_t type_uid,const lldb_private::ExecutionContext * exe_ctx)2102061da546Spatrick SymbolFileNativePDB::GetDynamicArrayInfoForUID(
2103061da546Spatrick     lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
2104*f6aab3d8Srobert   return std::nullopt;
2105061da546Spatrick }
2106061da546Spatrick 
CompleteType(CompilerType & compiler_type)2107061da546Spatrick bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) {
2108*f6aab3d8Srobert   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
2109*f6aab3d8Srobert   auto ts = compiler_type.GetTypeSystem();
2110*f6aab3d8Srobert   auto clang_type_system = ts.dyn_cast_or_null<TypeSystemClang>();
2111*f6aab3d8Srobert   if (!clang_type_system)
2112*f6aab3d8Srobert     return false;
2113*f6aab3d8Srobert 
2114*f6aab3d8Srobert   PdbAstBuilder *ast_builder =
2115*f6aab3d8Srobert       static_cast<PdbAstBuilder *>(clang_type_system->GetNativePDBParser());
2116*f6aab3d8Srobert   if (ast_builder &&
2117*f6aab3d8Srobert       ast_builder->GetClangASTImporter().CanImport(compiler_type))
2118*f6aab3d8Srobert     return ast_builder->GetClangASTImporter().CompleteType(compiler_type);
2119061da546Spatrick   clang::QualType qt =
2120061da546Spatrick       clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType());
2121061da546Spatrick 
2122*f6aab3d8Srobert   return ast_builder->CompleteType(qt);
2123061da546Spatrick }
2124061da546Spatrick 
GetTypes(lldb_private::SymbolContextScope * sc_scope,TypeClass type_mask,lldb_private::TypeList & type_list)2125061da546Spatrick void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
2126061da546Spatrick                                    TypeClass type_mask,
2127061da546Spatrick                                    lldb_private::TypeList &type_list) {}
2128061da546Spatrick 
2129061da546Spatrick CompilerDeclContext
FindNamespace(ConstString name,const CompilerDeclContext & parent_decl_ctx)2130061da546Spatrick SymbolFileNativePDB::FindNamespace(ConstString name,
2131dda28197Spatrick                                    const CompilerDeclContext &parent_decl_ctx) {
2132061da546Spatrick   return {};
2133061da546Spatrick }
2134061da546Spatrick 
2135*f6aab3d8Srobert llvm::Expected<lldb::TypeSystemSP>
GetTypeSystemForLanguage(lldb::LanguageType language)2136061da546Spatrick SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
2137061da546Spatrick   auto type_system_or_err =
2138061da546Spatrick       m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language);
2139*f6aab3d8Srobert   if (type_system_or_err)
2140*f6aab3d8Srobert     if (auto ts = *type_system_or_err)
2141*f6aab3d8Srobert       ts->SetSymbolFile(this);
2142061da546Spatrick   return type_system_or_err;
2143061da546Spatrick }
2144061da546Spatrick 
GetDebugInfoSize()2145*f6aab3d8Srobert uint64_t SymbolFileNativePDB::GetDebugInfoSize() {
2146*f6aab3d8Srobert   // PDB files are a separate file that contains all debug info.
2147*f6aab3d8Srobert   return m_index->pdb().getFileSize();
2148061da546Spatrick }
2149061da546Spatrick 
BuildParentMap()2150*f6aab3d8Srobert void SymbolFileNativePDB::BuildParentMap() {
2151*f6aab3d8Srobert   LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
2152*f6aab3d8Srobert 
2153*f6aab3d8Srobert   llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full;
2154*f6aab3d8Srobert   llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward;
2155*f6aab3d8Srobert 
2156*f6aab3d8Srobert   struct RecordIndices {
2157*f6aab3d8Srobert     TypeIndex forward;
2158*f6aab3d8Srobert     TypeIndex full;
2159*f6aab3d8Srobert   };
2160*f6aab3d8Srobert 
2161*f6aab3d8Srobert   llvm::StringMap<RecordIndices> record_indices;
2162*f6aab3d8Srobert 
2163*f6aab3d8Srobert   for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
2164*f6aab3d8Srobert     CVType type = types.getType(*ti);
2165*f6aab3d8Srobert     if (!IsTagRecord(type))
2166*f6aab3d8Srobert       continue;
2167*f6aab3d8Srobert 
2168*f6aab3d8Srobert     CVTagRecord tag = CVTagRecord::create(type);
2169*f6aab3d8Srobert 
2170*f6aab3d8Srobert     RecordIndices &indices = record_indices[tag.asTag().getUniqueName()];
2171*f6aab3d8Srobert     if (tag.asTag().isForwardRef())
2172*f6aab3d8Srobert       indices.forward = *ti;
2173*f6aab3d8Srobert     else
2174*f6aab3d8Srobert       indices.full = *ti;
2175*f6aab3d8Srobert 
2176*f6aab3d8Srobert     if (indices.full != TypeIndex::None() &&
2177*f6aab3d8Srobert         indices.forward != TypeIndex::None()) {
2178*f6aab3d8Srobert       forward_to_full[indices.forward] = indices.full;
2179*f6aab3d8Srobert       full_to_forward[indices.full] = indices.forward;
2180*f6aab3d8Srobert     }
2181*f6aab3d8Srobert 
2182*f6aab3d8Srobert     // We're looking for LF_NESTTYPE records in the field list, so ignore
2183*f6aab3d8Srobert     // forward references (no field list), and anything without a nested class
2184*f6aab3d8Srobert     // (since there won't be any LF_NESTTYPE records).
2185*f6aab3d8Srobert     if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass())
2186*f6aab3d8Srobert       continue;
2187*f6aab3d8Srobert 
2188*f6aab3d8Srobert     struct ProcessTpiStream : public TypeVisitorCallbacks {
2189*f6aab3d8Srobert       ProcessTpiStream(PdbIndex &index, TypeIndex parent,
2190*f6aab3d8Srobert                        const CVTagRecord &parent_cvt,
2191*f6aab3d8Srobert                        llvm::DenseMap<TypeIndex, TypeIndex> &parents)
2192*f6aab3d8Srobert           : index(index), parents(parents), parent(parent),
2193*f6aab3d8Srobert             parent_cvt(parent_cvt) {}
2194*f6aab3d8Srobert 
2195*f6aab3d8Srobert       PdbIndex &index;
2196*f6aab3d8Srobert       llvm::DenseMap<TypeIndex, TypeIndex> &parents;
2197*f6aab3d8Srobert 
2198*f6aab3d8Srobert       unsigned unnamed_type_index = 1;
2199*f6aab3d8Srobert       TypeIndex parent;
2200*f6aab3d8Srobert       const CVTagRecord &parent_cvt;
2201*f6aab3d8Srobert 
2202*f6aab3d8Srobert       llvm::Error visitKnownMember(CVMemberRecord &CVR,
2203*f6aab3d8Srobert                                    NestedTypeRecord &Record) override {
2204*f6aab3d8Srobert         std::string unnamed_type_name;
2205*f6aab3d8Srobert         if (Record.Name.empty()) {
2206*f6aab3d8Srobert           unnamed_type_name =
2207*f6aab3d8Srobert               llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str();
2208*f6aab3d8Srobert           Record.Name = unnamed_type_name;
2209*f6aab3d8Srobert           ++unnamed_type_index;
2210*f6aab3d8Srobert         }
2211*f6aab3d8Srobert         std::optional<CVTagRecord> tag =
2212*f6aab3d8Srobert             GetNestedTagDefinition(Record, parent_cvt, index.tpi());
2213*f6aab3d8Srobert         if (!tag)
2214*f6aab3d8Srobert           return llvm::ErrorSuccess();
2215*f6aab3d8Srobert 
2216*f6aab3d8Srobert         parents[Record.Type] = parent;
2217*f6aab3d8Srobert         return llvm::ErrorSuccess();
2218*f6aab3d8Srobert       }
2219*f6aab3d8Srobert     };
2220*f6aab3d8Srobert 
2221*f6aab3d8Srobert     CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList);
2222*f6aab3d8Srobert     ProcessTpiStream process(*m_index, *ti, tag, m_parent_types);
2223*f6aab3d8Srobert     FieldListRecord field_list;
2224*f6aab3d8Srobert     if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
2225*f6aab3d8Srobert             field_list_cvt, field_list))
2226*f6aab3d8Srobert       llvm::consumeError(std::move(error));
2227*f6aab3d8Srobert     if (llvm::Error error = visitMemberRecordStream(field_list.Data, process))
2228*f6aab3d8Srobert       llvm::consumeError(std::move(error));
2229*f6aab3d8Srobert   }
2230*f6aab3d8Srobert 
2231*f6aab3d8Srobert   // Now that we know the forward -> full mapping of all type indices, we can
2232*f6aab3d8Srobert   // re-write all the indices.  At the end of this process, we want a mapping
2233*f6aab3d8Srobert   // consisting of fwd -> full and full -> full for all child -> parent indices.
2234*f6aab3d8Srobert   // We can re-write the values in place, but for the keys, we must save them
2235*f6aab3d8Srobert   // off so that we don't modify the map in place while also iterating it.
2236*f6aab3d8Srobert   std::vector<TypeIndex> full_keys;
2237*f6aab3d8Srobert   std::vector<TypeIndex> fwd_keys;
2238*f6aab3d8Srobert   for (auto &entry : m_parent_types) {
2239*f6aab3d8Srobert     TypeIndex key = entry.first;
2240*f6aab3d8Srobert     TypeIndex value = entry.second;
2241*f6aab3d8Srobert 
2242*f6aab3d8Srobert     auto iter = forward_to_full.find(value);
2243*f6aab3d8Srobert     if (iter != forward_to_full.end())
2244*f6aab3d8Srobert       entry.second = iter->second;
2245*f6aab3d8Srobert 
2246*f6aab3d8Srobert     iter = forward_to_full.find(key);
2247*f6aab3d8Srobert     if (iter != forward_to_full.end())
2248*f6aab3d8Srobert       fwd_keys.push_back(key);
2249*f6aab3d8Srobert     else
2250*f6aab3d8Srobert       full_keys.push_back(key);
2251*f6aab3d8Srobert   }
2252*f6aab3d8Srobert   for (TypeIndex fwd : fwd_keys) {
2253*f6aab3d8Srobert     TypeIndex full = forward_to_full[fwd];
2254*f6aab3d8Srobert     m_parent_types[full] = m_parent_types[fwd];
2255*f6aab3d8Srobert   }
2256*f6aab3d8Srobert   for (TypeIndex full : full_keys) {
2257*f6aab3d8Srobert     TypeIndex fwd = full_to_forward[full];
2258*f6aab3d8Srobert     m_parent_types[fwd] = m_parent_types[full];
2259*f6aab3d8Srobert   }
2260*f6aab3d8Srobert }
2261*f6aab3d8Srobert 
2262*f6aab3d8Srobert std::optional<PdbCompilandSymId>
FindSymbolScope(PdbCompilandSymId id)2263*f6aab3d8Srobert SymbolFileNativePDB::FindSymbolScope(PdbCompilandSymId id) {
2264*f6aab3d8Srobert   CVSymbol sym = m_index->ReadSymbolRecord(id);
2265*f6aab3d8Srobert   if (symbolOpensScope(sym.kind())) {
2266*f6aab3d8Srobert     // If this exact symbol opens a scope, we can just directly access its
2267*f6aab3d8Srobert     // parent.
2268*f6aab3d8Srobert     id.offset = getScopeParentOffset(sym);
2269*f6aab3d8Srobert     // Global symbols have parent offset of 0.  Return std::nullopt to indicate
2270*f6aab3d8Srobert     // this.
2271*f6aab3d8Srobert     if (id.offset == 0)
2272*f6aab3d8Srobert       return std::nullopt;
2273*f6aab3d8Srobert     return id;
2274*f6aab3d8Srobert   }
2275*f6aab3d8Srobert 
2276*f6aab3d8Srobert   // Otherwise we need to start at the beginning and iterate forward until we
2277*f6aab3d8Srobert   // reach (or pass) this particular symbol
2278*f6aab3d8Srobert   CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(id.modi);
2279*f6aab3d8Srobert   const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
2280*f6aab3d8Srobert 
2281*f6aab3d8Srobert   auto begin = syms.begin();
2282*f6aab3d8Srobert   auto end = syms.at(id.offset);
2283*f6aab3d8Srobert   std::vector<PdbCompilandSymId> scope_stack;
2284*f6aab3d8Srobert 
2285*f6aab3d8Srobert   while (begin != end) {
2286*f6aab3d8Srobert     if (begin.offset() > id.offset) {
2287*f6aab3d8Srobert       // We passed it.  We couldn't even find this symbol record.
2288*f6aab3d8Srobert       lldbassert(false && "Invalid compiland symbol id!");
2289*f6aab3d8Srobert       return std::nullopt;
2290*f6aab3d8Srobert     }
2291*f6aab3d8Srobert 
2292*f6aab3d8Srobert     // We haven't found the symbol yet.  Check if we need to open or close the
2293*f6aab3d8Srobert     // scope stack.
2294*f6aab3d8Srobert     if (symbolOpensScope(begin->kind())) {
2295*f6aab3d8Srobert       // We can use the end offset of the scope to determine whether or not
2296*f6aab3d8Srobert       // we can just outright skip this entire scope.
2297*f6aab3d8Srobert       uint32_t scope_end = getScopeEndOffset(*begin);
2298*f6aab3d8Srobert       if (scope_end < id.offset) {
2299*f6aab3d8Srobert         begin = syms.at(scope_end);
2300*f6aab3d8Srobert       } else {
2301*f6aab3d8Srobert         // The symbol we're looking for is somewhere in this scope.
2302*f6aab3d8Srobert         scope_stack.emplace_back(id.modi, begin.offset());
2303*f6aab3d8Srobert       }
2304*f6aab3d8Srobert     } else if (symbolEndsScope(begin->kind())) {
2305*f6aab3d8Srobert       scope_stack.pop_back();
2306*f6aab3d8Srobert     }
2307*f6aab3d8Srobert     ++begin;
2308*f6aab3d8Srobert   }
2309*f6aab3d8Srobert   if (scope_stack.empty())
2310*f6aab3d8Srobert     return std::nullopt;
2311*f6aab3d8Srobert   // We have a match!  Return the top of the stack
2312*f6aab3d8Srobert   return scope_stack.back();
2313*f6aab3d8Srobert }
2314*f6aab3d8Srobert 
2315*f6aab3d8Srobert std::optional<llvm::codeview::TypeIndex>
GetParentType(llvm::codeview::TypeIndex ti)2316*f6aab3d8Srobert SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) {
2317*f6aab3d8Srobert   auto parent_iter = m_parent_types.find(ti);
2318*f6aab3d8Srobert   if (parent_iter == m_parent_types.end())
2319*f6aab3d8Srobert     return std::nullopt;
2320*f6aab3d8Srobert   return parent_iter->second;
2321*f6aab3d8Srobert }
2322