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 ®ex,
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 = █
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