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