xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- SymbolFilePDB.cpp -------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "SymbolFilePDB.h"
10061da546Spatrick 
11061da546Spatrick #include "PDBASTParser.h"
12061da546Spatrick #include "PDBLocationToDWARFExpression.h"
13061da546Spatrick 
14061da546Spatrick #include "clang/Lex/Lexer.h"
15061da546Spatrick 
16dda28197Spatrick #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
17061da546Spatrick #include "lldb/Core/Module.h"
18061da546Spatrick #include "lldb/Core/PluginManager.h"
19061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
20061da546Spatrick #include "lldb/Symbol/LineTable.h"
21061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
22061da546Spatrick #include "lldb/Symbol/SymbolContext.h"
23061da546Spatrick #include "lldb/Symbol/SymbolVendor.h"
24061da546Spatrick #include "lldb/Symbol/TypeList.h"
25061da546Spatrick #include "lldb/Symbol/TypeMap.h"
26061da546Spatrick #include "lldb/Symbol/Variable.h"
27*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
28061da546Spatrick #include "lldb/Utility/Log.h"
29061da546Spatrick #include "lldb/Utility/RegularExpression.h"
30061da546Spatrick 
31*f6aab3d8Srobert #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
32061da546Spatrick #include "llvm/DebugInfo/PDB/GenericError.h"
33061da546Spatrick #include "llvm/DebugInfo/PDB/IPDBDataStream.h"
34061da546Spatrick #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
35061da546Spatrick #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
36061da546Spatrick #include "llvm/DebugInfo/PDB/IPDBSectionContrib.h"
37061da546Spatrick #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
38061da546Spatrick #include "llvm/DebugInfo/PDB/IPDBTable.h"
39061da546Spatrick #include "llvm/DebugInfo/PDB/PDBSymbol.h"
40061da546Spatrick #include "llvm/DebugInfo/PDB/PDBSymbolBlock.h"
41061da546Spatrick #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
42061da546Spatrick #include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
43061da546Spatrick #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
44061da546Spatrick #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
45061da546Spatrick #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
46061da546Spatrick #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
47061da546Spatrick #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
48061da546Spatrick #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
49*f6aab3d8Srobert #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
50061da546Spatrick #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
51*f6aab3d8Srobert #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
52061da546Spatrick #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
53061da546Spatrick #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
54061da546Spatrick 
55061da546Spatrick #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
56061da546Spatrick #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
57061da546Spatrick #include "Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h"
58061da546Spatrick 
59*f6aab3d8Srobert #if defined(_WIN32)
60*f6aab3d8Srobert #include "llvm/Config/llvm-config.h"
61*f6aab3d8Srobert #include <optional>
62*f6aab3d8Srobert #endif
63*f6aab3d8Srobert 
64061da546Spatrick using namespace lldb;
65061da546Spatrick using namespace lldb_private;
66061da546Spatrick using namespace llvm::pdb;
67061da546Spatrick 
68dda28197Spatrick LLDB_PLUGIN_DEFINE(SymbolFilePDB)
69dda28197Spatrick 
70061da546Spatrick char SymbolFilePDB::ID;
71061da546Spatrick 
72061da546Spatrick namespace {
TranslateLanguage(PDB_Lang lang)73061da546Spatrick lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
74061da546Spatrick   switch (lang) {
75061da546Spatrick   case PDB_Lang::Cpp:
76061da546Spatrick     return lldb::LanguageType::eLanguageTypeC_plus_plus;
77061da546Spatrick   case PDB_Lang::C:
78061da546Spatrick     return lldb::LanguageType::eLanguageTypeC;
79061da546Spatrick   case PDB_Lang::Swift:
80061da546Spatrick     return lldb::LanguageType::eLanguageTypeSwift;
81*f6aab3d8Srobert   case PDB_Lang::Rust:
82*f6aab3d8Srobert     return lldb::LanguageType::eLanguageTypeRust;
83061da546Spatrick   default:
84061da546Spatrick     return lldb::LanguageType::eLanguageTypeUnknown;
85061da546Spatrick   }
86061da546Spatrick }
87061da546Spatrick 
ShouldAddLine(uint32_t requested_line,uint32_t actual_line,uint32_t addr_length)88061da546Spatrick bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line,
89061da546Spatrick                    uint32_t addr_length) {
90061da546Spatrick   return ((requested_line == 0 || actual_line == requested_line) &&
91061da546Spatrick           addr_length > 0);
92061da546Spatrick }
93061da546Spatrick } // namespace
94061da546Spatrick 
ShouldUseNativeReader()95061da546Spatrick static bool ShouldUseNativeReader() {
96061da546Spatrick #if defined(_WIN32)
97*f6aab3d8Srobert #if LLVM_ENABLE_DIA_SDK
98061da546Spatrick   llvm::StringRef use_native = ::getenv("LLDB_USE_NATIVE_PDB_READER");
99*f6aab3d8Srobert   if (!use_native.equals_insensitive("on") &&
100*f6aab3d8Srobert       !use_native.equals_insensitive("yes") &&
101*f6aab3d8Srobert       !use_native.equals_insensitive("1") &&
102*f6aab3d8Srobert       !use_native.equals_insensitive("true"))
103*f6aab3d8Srobert     return false;
104061da546Spatrick #endif
105*f6aab3d8Srobert #endif
106*f6aab3d8Srobert   return true;
107061da546Spatrick }
108061da546Spatrick 
Initialize()109061da546Spatrick void SymbolFilePDB::Initialize() {
110061da546Spatrick   if (ShouldUseNativeReader()) {
111061da546Spatrick     npdb::SymbolFileNativePDB::Initialize();
112061da546Spatrick   } else {
113061da546Spatrick     PluginManager::RegisterPlugin(GetPluginNameStatic(),
114061da546Spatrick                                   GetPluginDescriptionStatic(), CreateInstance,
115061da546Spatrick                                   DebuggerInitialize);
116061da546Spatrick   }
117061da546Spatrick }
118061da546Spatrick 
Terminate()119061da546Spatrick void SymbolFilePDB::Terminate() {
120061da546Spatrick   if (ShouldUseNativeReader()) {
121061da546Spatrick     npdb::SymbolFileNativePDB::Terminate();
122061da546Spatrick   } else {
123061da546Spatrick     PluginManager::UnregisterPlugin(CreateInstance);
124061da546Spatrick   }
125061da546Spatrick }
126061da546Spatrick 
DebuggerInitialize(lldb_private::Debugger & debugger)127061da546Spatrick void SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger) {}
128061da546Spatrick 
GetPluginDescriptionStatic()129*f6aab3d8Srobert llvm::StringRef SymbolFilePDB::GetPluginDescriptionStatic() {
130061da546Spatrick   return "Microsoft PDB debug symbol file reader.";
131061da546Spatrick }
132061da546Spatrick 
133061da546Spatrick lldb_private::SymbolFile *
CreateInstance(ObjectFileSP objfile_sp)134061da546Spatrick SymbolFilePDB::CreateInstance(ObjectFileSP objfile_sp) {
135061da546Spatrick   return new SymbolFilePDB(std::move(objfile_sp));
136061da546Spatrick }
137061da546Spatrick 
SymbolFilePDB(lldb::ObjectFileSP objfile_sp)138061da546Spatrick SymbolFilePDB::SymbolFilePDB(lldb::ObjectFileSP objfile_sp)
139*f6aab3d8Srobert     : SymbolFileCommon(std::move(objfile_sp)), m_session_up(), m_global_scope_up() {}
140061da546Spatrick 
141be691f3bSpatrick SymbolFilePDB::~SymbolFilePDB() = default;
142061da546Spatrick 
CalculateAbilities()143061da546Spatrick uint32_t SymbolFilePDB::CalculateAbilities() {
144061da546Spatrick   uint32_t abilities = 0;
145061da546Spatrick   if (!m_objfile_sp)
146061da546Spatrick     return 0;
147061da546Spatrick 
148061da546Spatrick   if (!m_session_up) {
149061da546Spatrick     // Lazily load and match the PDB file, but only do this once.
150061da546Spatrick     std::string exePath = m_objfile_sp->GetFileSpec().GetPath();
151061da546Spatrick     auto error = loadDataForEXE(PDB_ReaderType::DIA, llvm::StringRef(exePath),
152061da546Spatrick                                 m_session_up);
153061da546Spatrick     if (error) {
154061da546Spatrick       llvm::consumeError(std::move(error));
155061da546Spatrick       auto module_sp = m_objfile_sp->GetModule();
156061da546Spatrick       if (!module_sp)
157061da546Spatrick         return 0;
158061da546Spatrick       // See if any symbol file is specified through `--symfile` option.
159061da546Spatrick       FileSpec symfile = module_sp->GetSymbolFileFileSpec();
160061da546Spatrick       if (!symfile)
161061da546Spatrick         return 0;
162061da546Spatrick       error = loadDataForPDB(PDB_ReaderType::DIA,
163061da546Spatrick                              llvm::StringRef(symfile.GetPath()), m_session_up);
164061da546Spatrick       if (error) {
165061da546Spatrick         llvm::consumeError(std::move(error));
166061da546Spatrick         return 0;
167061da546Spatrick       }
168061da546Spatrick     }
169061da546Spatrick   }
170061da546Spatrick   if (!m_session_up)
171061da546Spatrick     return 0;
172061da546Spatrick 
173061da546Spatrick   auto enum_tables_up = m_session_up->getEnumTables();
174061da546Spatrick   if (!enum_tables_up)
175061da546Spatrick     return 0;
176061da546Spatrick   while (auto table_up = enum_tables_up->getNext()) {
177061da546Spatrick     if (table_up->getItemCount() == 0)
178061da546Spatrick       continue;
179061da546Spatrick     auto type = table_up->getTableType();
180061da546Spatrick     switch (type) {
181061da546Spatrick     case PDB_TableType::Symbols:
182061da546Spatrick       // This table represents a store of symbols with types listed in
183061da546Spatrick       // PDBSym_Type
184061da546Spatrick       abilities |= (CompileUnits | Functions | Blocks | GlobalVariables |
185061da546Spatrick                     LocalVariables | VariableTypes);
186061da546Spatrick       break;
187061da546Spatrick     case PDB_TableType::LineNumbers:
188061da546Spatrick       abilities |= LineTables;
189061da546Spatrick       break;
190061da546Spatrick     default:
191061da546Spatrick       break;
192061da546Spatrick     }
193061da546Spatrick   }
194061da546Spatrick   return abilities;
195061da546Spatrick }
196061da546Spatrick 
InitializeObject()197061da546Spatrick void SymbolFilePDB::InitializeObject() {
198061da546Spatrick   lldb::addr_t obj_load_address =
199061da546Spatrick       m_objfile_sp->GetBaseAddress().GetFileAddress();
200061da546Spatrick   lldbassert(obj_load_address && obj_load_address != LLDB_INVALID_ADDRESS);
201061da546Spatrick   m_session_up->setLoadAddress(obj_load_address);
202061da546Spatrick   if (!m_global_scope_up)
203061da546Spatrick     m_global_scope_up = m_session_up->getGlobalScope();
204061da546Spatrick   lldbassert(m_global_scope_up.get());
205061da546Spatrick }
206061da546Spatrick 
CalculateNumCompileUnits()207061da546Spatrick uint32_t SymbolFilePDB::CalculateNumCompileUnits() {
208061da546Spatrick   auto compilands = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
209061da546Spatrick   if (!compilands)
210061da546Spatrick     return 0;
211061da546Spatrick 
212061da546Spatrick   // The linker could link *.dll (compiland language = LINK), or import
213061da546Spatrick   // *.dll. For example, a compiland with name `Import:KERNEL32.dll` could be
214061da546Spatrick   // found as a child of the global scope (PDB executable). Usually, such
215061da546Spatrick   // compilands contain `thunk` symbols in which we are not interested for
216061da546Spatrick   // now. However we still count them in the compiland list. If we perform
217061da546Spatrick   // any compiland related activity, like finding symbols through
218061da546Spatrick   // llvm::pdb::IPDBSession methods, such compilands will all be searched
219061da546Spatrick   // automatically no matter whether we include them or not.
220061da546Spatrick   uint32_t compile_unit_count = compilands->getChildCount();
221061da546Spatrick 
222061da546Spatrick   // The linker can inject an additional "dummy" compilation unit into the
223061da546Spatrick   // PDB. Ignore this special compile unit for our purposes, if it is there.
224061da546Spatrick   // It is always the last one.
225061da546Spatrick   auto last_compiland_up = compilands->getChildAtIndex(compile_unit_count - 1);
226061da546Spatrick   lldbassert(last_compiland_up.get());
227061da546Spatrick   std::string name = last_compiland_up->getName();
228061da546Spatrick   if (name == "* Linker *")
229061da546Spatrick     --compile_unit_count;
230061da546Spatrick   return compile_unit_count;
231061da546Spatrick }
232061da546Spatrick 
GetCompileUnitIndex(const llvm::pdb::PDBSymbolCompiland & pdb_compiland,uint32_t & index)233061da546Spatrick void SymbolFilePDB::GetCompileUnitIndex(
234061da546Spatrick     const llvm::pdb::PDBSymbolCompiland &pdb_compiland, uint32_t &index) {
235061da546Spatrick   auto results_up = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
236061da546Spatrick   if (!results_up)
237061da546Spatrick     return;
238061da546Spatrick   auto uid = pdb_compiland.getSymIndexId();
239061da546Spatrick   for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) {
240061da546Spatrick     auto compiland_up = results_up->getChildAtIndex(cu_idx);
241061da546Spatrick     if (!compiland_up)
242061da546Spatrick       continue;
243061da546Spatrick     if (compiland_up->getSymIndexId() == uid) {
244061da546Spatrick       index = cu_idx;
245061da546Spatrick       return;
246061da546Spatrick     }
247061da546Spatrick   }
248061da546Spatrick   index = UINT32_MAX;
249061da546Spatrick }
250061da546Spatrick 
251061da546Spatrick std::unique_ptr<llvm::pdb::PDBSymbolCompiland>
GetPDBCompilandByUID(uint32_t uid)252061da546Spatrick SymbolFilePDB::GetPDBCompilandByUID(uint32_t uid) {
253061da546Spatrick   return m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(uid);
254061da546Spatrick }
255061da546Spatrick 
ParseCompileUnitAtIndex(uint32_t index)256061da546Spatrick lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) {
257061da546Spatrick   if (index >= GetNumCompileUnits())
258061da546Spatrick     return CompUnitSP();
259061da546Spatrick 
260061da546Spatrick   // Assuming we always retrieve same compilands listed in same order through
261061da546Spatrick   // `PDBSymbolExe::findAllChildren` method, otherwise using `index` to get a
262061da546Spatrick   // compile unit makes no sense.
263061da546Spatrick   auto results = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
264061da546Spatrick   if (!results)
265061da546Spatrick     return CompUnitSP();
266061da546Spatrick   auto compiland_up = results->getChildAtIndex(index);
267061da546Spatrick   if (!compiland_up)
268061da546Spatrick     return CompUnitSP();
269061da546Spatrick   return ParseCompileUnitForUID(compiland_up->getSymIndexId(), index);
270061da546Spatrick }
271061da546Spatrick 
ParseLanguage(CompileUnit & comp_unit)272061da546Spatrick lldb::LanguageType SymbolFilePDB::ParseLanguage(CompileUnit &comp_unit) {
273061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
274061da546Spatrick   auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID());
275061da546Spatrick   if (!compiland_up)
276061da546Spatrick     return lldb::eLanguageTypeUnknown;
277061da546Spatrick   auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>();
278061da546Spatrick   if (!details)
279061da546Spatrick     return lldb::eLanguageTypeUnknown;
280061da546Spatrick   return TranslateLanguage(details->getLanguage());
281061da546Spatrick }
282061da546Spatrick 
283061da546Spatrick lldb_private::Function *
ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc & pdb_func,CompileUnit & comp_unit)284061da546Spatrick SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc &pdb_func,
285061da546Spatrick                                                   CompileUnit &comp_unit) {
286061da546Spatrick   if (FunctionSP result = comp_unit.FindFunctionByUID(pdb_func.getSymIndexId()))
287061da546Spatrick     return result.get();
288061da546Spatrick 
289061da546Spatrick   auto file_vm_addr = pdb_func.getVirtualAddress();
290061da546Spatrick   if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
291061da546Spatrick     return nullptr;
292061da546Spatrick 
293061da546Spatrick   auto func_length = pdb_func.getLength();
294061da546Spatrick   AddressRange func_range =
295061da546Spatrick       AddressRange(file_vm_addr, func_length,
296061da546Spatrick                    GetObjectFile()->GetModule()->GetSectionList());
297061da546Spatrick   if (!func_range.GetBaseAddress().IsValid())
298061da546Spatrick     return nullptr;
299061da546Spatrick 
300061da546Spatrick   lldb_private::Type *func_type = ResolveTypeUID(pdb_func.getSymIndexId());
301061da546Spatrick   if (!func_type)
302061da546Spatrick     return nullptr;
303061da546Spatrick 
304061da546Spatrick   user_id_t func_type_uid = pdb_func.getSignatureId();
305061da546Spatrick 
306061da546Spatrick   Mangled mangled = GetMangledForPDBFunc(pdb_func);
307061da546Spatrick 
308061da546Spatrick   FunctionSP func_sp =
309061da546Spatrick       std::make_shared<Function>(&comp_unit, pdb_func.getSymIndexId(),
310061da546Spatrick                                  func_type_uid, mangled, func_type, func_range);
311061da546Spatrick 
312061da546Spatrick   comp_unit.AddFunction(func_sp);
313061da546Spatrick 
314061da546Spatrick   LanguageType lang = ParseLanguage(comp_unit);
315061da546Spatrick   auto type_system_or_err = GetTypeSystemForLanguage(lang);
316061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
317*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
318*f6aab3d8Srobert                    "Unable to parse PDBFunc");
319061da546Spatrick     return nullptr;
320061da546Spatrick   }
321061da546Spatrick 
322*f6aab3d8Srobert   auto ts = *type_system_or_err;
323dda28197Spatrick   TypeSystemClang *clang_type_system =
324*f6aab3d8Srobert     llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
325061da546Spatrick   if (!clang_type_system)
326061da546Spatrick     return nullptr;
327061da546Spatrick   clang_type_system->GetPDBParser()->GetDeclForSymbol(pdb_func);
328061da546Spatrick 
329061da546Spatrick   return func_sp.get();
330061da546Spatrick }
331061da546Spatrick 
ParseFunctions(CompileUnit & comp_unit)332061da546Spatrick size_t SymbolFilePDB::ParseFunctions(CompileUnit &comp_unit) {
333061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
334061da546Spatrick   size_t func_added = 0;
335061da546Spatrick   auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID());
336061da546Spatrick   if (!compiland_up)
337061da546Spatrick     return 0;
338061da546Spatrick   auto results_up = compiland_up->findAllChildren<PDBSymbolFunc>();
339061da546Spatrick   if (!results_up)
340061da546Spatrick     return 0;
341061da546Spatrick   while (auto pdb_func_up = results_up->getNext()) {
342061da546Spatrick     auto func_sp = comp_unit.FindFunctionByUID(pdb_func_up->getSymIndexId());
343061da546Spatrick     if (!func_sp) {
344061da546Spatrick       if (ParseCompileUnitFunctionForPDBFunc(*pdb_func_up, comp_unit))
345061da546Spatrick         ++func_added;
346061da546Spatrick     }
347061da546Spatrick   }
348061da546Spatrick   return func_added;
349061da546Spatrick }
350061da546Spatrick 
ParseLineTable(CompileUnit & comp_unit)351061da546Spatrick bool SymbolFilePDB::ParseLineTable(CompileUnit &comp_unit) {
352061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
353061da546Spatrick   if (comp_unit.GetLineTable())
354061da546Spatrick     return true;
355061da546Spatrick   return ParseCompileUnitLineTable(comp_unit, 0);
356061da546Spatrick }
357061da546Spatrick 
ParseDebugMacros(CompileUnit & comp_unit)358061da546Spatrick bool SymbolFilePDB::ParseDebugMacros(CompileUnit &comp_unit) {
359061da546Spatrick   // PDB doesn't contain information about macros
360061da546Spatrick   return false;
361061da546Spatrick }
362061da546Spatrick 
ParseSupportFiles(CompileUnit & comp_unit,lldb_private::FileSpecList & support_files)363061da546Spatrick bool SymbolFilePDB::ParseSupportFiles(
364061da546Spatrick     CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) {
365061da546Spatrick 
366061da546Spatrick   // In theory this is unnecessary work for us, because all of this information
367061da546Spatrick   // is easily (and quickly) accessible from DebugInfoPDB, so caching it a
368061da546Spatrick   // second time seems like a waste.  Unfortunately, there's no good way around
369061da546Spatrick   // this short of a moderate refactor since SymbolVendor depends on being able
370061da546Spatrick   // to cache this list.
371061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
372061da546Spatrick   auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID());
373061da546Spatrick   if (!compiland_up)
374061da546Spatrick     return false;
375061da546Spatrick   auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
376061da546Spatrick   if (!files || files->getChildCount() == 0)
377061da546Spatrick     return false;
378061da546Spatrick 
379061da546Spatrick   while (auto file = files->getNext()) {
380061da546Spatrick     FileSpec spec(file->getFileName(), FileSpec::Style::windows);
381061da546Spatrick     support_files.AppendIfUnique(spec);
382061da546Spatrick   }
383061da546Spatrick 
384061da546Spatrick   return true;
385061da546Spatrick }
386061da546Spatrick 
ParseImportedModules(const lldb_private::SymbolContext & sc,std::vector<SourceModule> & imported_modules)387061da546Spatrick bool SymbolFilePDB::ParseImportedModules(
388061da546Spatrick     const lldb_private::SymbolContext &sc,
389061da546Spatrick     std::vector<SourceModule> &imported_modules) {
390061da546Spatrick   // PDB does not yet support module debug info
391061da546Spatrick   return false;
392061da546Spatrick }
393061da546Spatrick 
ParseFunctionBlocksForPDBSymbol(uint64_t func_file_vm_addr,const llvm::pdb::PDBSymbol * pdb_symbol,lldb_private::Block * parent_block,bool is_top_parent)394061da546Spatrick static size_t ParseFunctionBlocksForPDBSymbol(
395061da546Spatrick     uint64_t func_file_vm_addr, const llvm::pdb::PDBSymbol *pdb_symbol,
396061da546Spatrick     lldb_private::Block *parent_block, bool is_top_parent) {
397061da546Spatrick   assert(pdb_symbol && parent_block);
398061da546Spatrick 
399061da546Spatrick   size_t num_added = 0;
400061da546Spatrick   switch (pdb_symbol->getSymTag()) {
401061da546Spatrick   case PDB_SymType::Block:
402061da546Spatrick   case PDB_SymType::Function: {
403061da546Spatrick     Block *block = nullptr;
404061da546Spatrick     auto &raw_sym = pdb_symbol->getRawSymbol();
405061da546Spatrick     if (auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(pdb_symbol)) {
406061da546Spatrick       if (pdb_func->hasNoInlineAttribute())
407061da546Spatrick         break;
408061da546Spatrick       if (is_top_parent)
409061da546Spatrick         block = parent_block;
410061da546Spatrick       else
411061da546Spatrick         break;
412*f6aab3d8Srobert     } else if (llvm::isa<PDBSymbolBlock>(pdb_symbol)) {
413061da546Spatrick       auto uid = pdb_symbol->getSymIndexId();
414061da546Spatrick       if (parent_block->FindBlockByID(uid))
415061da546Spatrick         break;
416061da546Spatrick       if (raw_sym.getVirtualAddress() < func_file_vm_addr)
417061da546Spatrick         break;
418061da546Spatrick 
419061da546Spatrick       auto block_sp = std::make_shared<Block>(pdb_symbol->getSymIndexId());
420061da546Spatrick       parent_block->AddChild(block_sp);
421061da546Spatrick       block = block_sp.get();
422061da546Spatrick     } else
423061da546Spatrick       llvm_unreachable("Unexpected PDB symbol!");
424061da546Spatrick 
425061da546Spatrick     block->AddRange(Block::Range(
426061da546Spatrick         raw_sym.getVirtualAddress() - func_file_vm_addr, raw_sym.getLength()));
427061da546Spatrick     block->FinalizeRanges();
428061da546Spatrick     ++num_added;
429061da546Spatrick 
430061da546Spatrick     auto results_up = pdb_symbol->findAllChildren();
431061da546Spatrick     if (!results_up)
432061da546Spatrick       break;
433061da546Spatrick     while (auto symbol_up = results_up->getNext()) {
434061da546Spatrick       num_added += ParseFunctionBlocksForPDBSymbol(
435061da546Spatrick           func_file_vm_addr, symbol_up.get(), block, false);
436061da546Spatrick     }
437061da546Spatrick   } break;
438061da546Spatrick   default:
439061da546Spatrick     break;
440061da546Spatrick   }
441061da546Spatrick   return num_added;
442061da546Spatrick }
443061da546Spatrick 
ParseBlocksRecursive(Function & func)444061da546Spatrick size_t SymbolFilePDB::ParseBlocksRecursive(Function &func) {
445061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
446061da546Spatrick   size_t num_added = 0;
447061da546Spatrick   auto uid = func.GetID();
448061da546Spatrick   auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid);
449061da546Spatrick   if (!pdb_func_up)
450061da546Spatrick     return 0;
451061da546Spatrick   Block &parent_block = func.GetBlock(false);
452061da546Spatrick   num_added = ParseFunctionBlocksForPDBSymbol(
453061da546Spatrick       pdb_func_up->getVirtualAddress(), pdb_func_up.get(), &parent_block, true);
454061da546Spatrick   return num_added;
455061da546Spatrick }
456061da546Spatrick 
ParseTypes(CompileUnit & comp_unit)457061da546Spatrick size_t SymbolFilePDB::ParseTypes(CompileUnit &comp_unit) {
458061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
459061da546Spatrick 
460061da546Spatrick   size_t num_added = 0;
461061da546Spatrick   auto compiland = GetPDBCompilandByUID(comp_unit.GetID());
462061da546Spatrick   if (!compiland)
463061da546Spatrick     return 0;
464061da546Spatrick 
465061da546Spatrick   auto ParseTypesByTagFn = [&num_added, this](const PDBSymbol &raw_sym) {
466061da546Spatrick     std::unique_ptr<IPDBEnumSymbols> results;
467061da546Spatrick     PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef,
468061da546Spatrick                                     PDB_SymType::UDT};
469061da546Spatrick     for (auto tag : tags_to_search) {
470061da546Spatrick       results = raw_sym.findAllChildren(tag);
471061da546Spatrick       if (!results || results->getChildCount() == 0)
472061da546Spatrick         continue;
473061da546Spatrick       while (auto symbol = results->getNext()) {
474061da546Spatrick         switch (symbol->getSymTag()) {
475061da546Spatrick         case PDB_SymType::Enum:
476061da546Spatrick         case PDB_SymType::UDT:
477061da546Spatrick         case PDB_SymType::Typedef:
478061da546Spatrick           break;
479061da546Spatrick         default:
480061da546Spatrick           continue;
481061da546Spatrick         }
482061da546Spatrick 
483061da546Spatrick         // This should cause the type to get cached and stored in the `m_types`
484061da546Spatrick         // lookup.
485061da546Spatrick         if (auto type = ResolveTypeUID(symbol->getSymIndexId())) {
486061da546Spatrick           // Resolve the type completely to avoid a completion
487061da546Spatrick           // (and so a list change, which causes an iterators invalidation)
488061da546Spatrick           // during a TypeList dumping
489061da546Spatrick           type->GetFullCompilerType();
490061da546Spatrick           ++num_added;
491061da546Spatrick         }
492061da546Spatrick       }
493061da546Spatrick     }
494061da546Spatrick   };
495061da546Spatrick 
496061da546Spatrick   ParseTypesByTagFn(*compiland);
497061da546Spatrick 
498061da546Spatrick   // Also parse global types particularly coming from this compiland.
499061da546Spatrick   // Unfortunately, PDB has no compiland information for each global type. We
500061da546Spatrick   // have to parse them all. But ensure we only do this once.
501061da546Spatrick   static bool parse_all_global_types = false;
502061da546Spatrick   if (!parse_all_global_types) {
503061da546Spatrick     ParseTypesByTagFn(*m_global_scope_up);
504061da546Spatrick     parse_all_global_types = true;
505061da546Spatrick   }
506061da546Spatrick   return num_added;
507061da546Spatrick }
508061da546Spatrick 
509061da546Spatrick size_t
ParseVariablesForContext(const lldb_private::SymbolContext & sc)510061da546Spatrick SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) {
511061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
512061da546Spatrick   if (!sc.comp_unit)
513061da546Spatrick     return 0;
514061da546Spatrick 
515061da546Spatrick   size_t num_added = 0;
516061da546Spatrick   if (sc.function) {
517061da546Spatrick     auto pdb_func = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(
518061da546Spatrick         sc.function->GetID());
519061da546Spatrick     if (!pdb_func)
520061da546Spatrick       return 0;
521061da546Spatrick 
522061da546Spatrick     num_added += ParseVariables(sc, *pdb_func);
523061da546Spatrick     sc.function->GetBlock(false).SetDidParseVariables(true, true);
524061da546Spatrick   } else if (sc.comp_unit) {
525061da546Spatrick     auto compiland = GetPDBCompilandByUID(sc.comp_unit->GetID());
526061da546Spatrick     if (!compiland)
527061da546Spatrick       return 0;
528061da546Spatrick 
529061da546Spatrick     if (sc.comp_unit->GetVariableList(false))
530061da546Spatrick       return 0;
531061da546Spatrick 
532061da546Spatrick     auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
533061da546Spatrick     if (results && results->getChildCount()) {
534061da546Spatrick       while (auto result = results->getNext()) {
535061da546Spatrick         auto cu_id = GetCompilandId(*result);
536061da546Spatrick         // FIXME: We are not able to determine variable's compile unit.
537061da546Spatrick         if (cu_id == 0)
538061da546Spatrick           continue;
539061da546Spatrick 
540061da546Spatrick         if (cu_id == sc.comp_unit->GetID())
541061da546Spatrick           num_added += ParseVariables(sc, *result);
542061da546Spatrick       }
543061da546Spatrick     }
544061da546Spatrick 
545061da546Spatrick     // FIXME: A `file static` or `global constant` variable appears both in
546061da546Spatrick     // compiland's children and global scope's children with unexpectedly
547061da546Spatrick     // different symbol's Id making it ambiguous.
548061da546Spatrick 
549061da546Spatrick     // FIXME: 'local constant', for example, const char var[] = "abc", declared
550061da546Spatrick     // in a function scope, can't be found in PDB.
551061da546Spatrick 
552061da546Spatrick     // Parse variables in this compiland.
553061da546Spatrick     num_added += ParseVariables(sc, *compiland);
554061da546Spatrick   }
555061da546Spatrick 
556061da546Spatrick   return num_added;
557061da546Spatrick }
558061da546Spatrick 
ResolveTypeUID(lldb::user_id_t type_uid)559061da546Spatrick lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
560061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
561061da546Spatrick   auto find_result = m_types.find(type_uid);
562061da546Spatrick   if (find_result != m_types.end())
563061da546Spatrick     return find_result->second.get();
564061da546Spatrick 
565061da546Spatrick   auto type_system_or_err =
566061da546Spatrick       GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
567061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
568*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
569*f6aab3d8Srobert                    "Unable to ResolveTypeUID");
570061da546Spatrick     return nullptr;
571061da546Spatrick   }
572061da546Spatrick 
573*f6aab3d8Srobert   auto ts = *type_system_or_err;
574dda28197Spatrick   TypeSystemClang *clang_type_system =
575*f6aab3d8Srobert       llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
576061da546Spatrick   if (!clang_type_system)
577061da546Spatrick     return nullptr;
578061da546Spatrick   PDBASTParser *pdb = clang_type_system->GetPDBParser();
579061da546Spatrick   if (!pdb)
580061da546Spatrick     return nullptr;
581061da546Spatrick 
582061da546Spatrick   auto pdb_type = m_session_up->getSymbolById(type_uid);
583061da546Spatrick   if (pdb_type == nullptr)
584061da546Spatrick     return nullptr;
585061da546Spatrick 
586061da546Spatrick   lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type);
587061da546Spatrick   if (result) {
588061da546Spatrick     m_types.insert(std::make_pair(type_uid, result));
589061da546Spatrick   }
590061da546Spatrick   return result.get();
591061da546Spatrick }
592061da546Spatrick 
GetDynamicArrayInfoForUID(lldb::user_id_t type_uid,const lldb_private::ExecutionContext * exe_ctx)593*f6aab3d8Srobert std::optional<SymbolFile::ArrayInfo> SymbolFilePDB::GetDynamicArrayInfoForUID(
594061da546Spatrick     lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
595*f6aab3d8Srobert   return std::nullopt;
596061da546Spatrick }
597061da546Spatrick 
CompleteType(lldb_private::CompilerType & compiler_type)598061da546Spatrick bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) {
599061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(
600061da546Spatrick       GetObjectFile()->GetModule()->GetMutex());
601061da546Spatrick 
602061da546Spatrick   auto type_system_or_err =
603061da546Spatrick       GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
604061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
605*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
606*f6aab3d8Srobert                    "Unable to get dynamic array info for UID");
607061da546Spatrick     return false;
608061da546Spatrick   }
609*f6aab3d8Srobert   auto ts = *type_system_or_err;
610dda28197Spatrick   TypeSystemClang *clang_ast_ctx =
611*f6aab3d8Srobert       llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
612061da546Spatrick 
613061da546Spatrick   if (!clang_ast_ctx)
614061da546Spatrick     return false;
615061da546Spatrick 
616061da546Spatrick   PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
617061da546Spatrick   if (!pdb)
618061da546Spatrick     return false;
619061da546Spatrick 
620061da546Spatrick   return pdb->CompleteTypeFromPDB(compiler_type);
621061da546Spatrick }
622061da546Spatrick 
GetDeclForUID(lldb::user_id_t uid)623061da546Spatrick lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) {
624061da546Spatrick   auto type_system_or_err =
625061da546Spatrick       GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
626061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
627*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
628*f6aab3d8Srobert                    "Unable to get decl for UID");
629061da546Spatrick     return CompilerDecl();
630061da546Spatrick   }
631*f6aab3d8Srobert   auto ts = *type_system_or_err;
632dda28197Spatrick   TypeSystemClang *clang_ast_ctx =
633*f6aab3d8Srobert       llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
634061da546Spatrick   if (!clang_ast_ctx)
635061da546Spatrick     return CompilerDecl();
636061da546Spatrick 
637061da546Spatrick   PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
638061da546Spatrick   if (!pdb)
639061da546Spatrick     return CompilerDecl();
640061da546Spatrick 
641061da546Spatrick   auto symbol = m_session_up->getSymbolById(uid);
642061da546Spatrick   if (!symbol)
643061da546Spatrick     return CompilerDecl();
644061da546Spatrick 
645061da546Spatrick   auto decl = pdb->GetDeclForSymbol(*symbol);
646061da546Spatrick   if (!decl)
647061da546Spatrick     return CompilerDecl();
648061da546Spatrick 
649dda28197Spatrick   return clang_ast_ctx->GetCompilerDecl(decl);
650061da546Spatrick }
651061da546Spatrick 
652061da546Spatrick lldb_private::CompilerDeclContext
GetDeclContextForUID(lldb::user_id_t uid)653061da546Spatrick SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) {
654061da546Spatrick   auto type_system_or_err =
655061da546Spatrick       GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
656061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
657*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
658*f6aab3d8Srobert                    "Unable to get DeclContext for UID");
659061da546Spatrick     return CompilerDeclContext();
660061da546Spatrick   }
661061da546Spatrick 
662*f6aab3d8Srobert   auto ts = *type_system_or_err;
663dda28197Spatrick   TypeSystemClang *clang_ast_ctx =
664*f6aab3d8Srobert       llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
665061da546Spatrick   if (!clang_ast_ctx)
666061da546Spatrick     return CompilerDeclContext();
667061da546Spatrick 
668061da546Spatrick   PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
669061da546Spatrick   if (!pdb)
670061da546Spatrick     return CompilerDeclContext();
671061da546Spatrick 
672061da546Spatrick   auto symbol = m_session_up->getSymbolById(uid);
673061da546Spatrick   if (!symbol)
674061da546Spatrick     return CompilerDeclContext();
675061da546Spatrick 
676061da546Spatrick   auto decl_context = pdb->GetDeclContextForSymbol(*symbol);
677061da546Spatrick   if (!decl_context)
678061da546Spatrick     return GetDeclContextContainingUID(uid);
679061da546Spatrick 
680061da546Spatrick   return clang_ast_ctx->CreateDeclContext(decl_context);
681061da546Spatrick }
682061da546Spatrick 
683061da546Spatrick lldb_private::CompilerDeclContext
GetDeclContextContainingUID(lldb::user_id_t uid)684061da546Spatrick SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
685061da546Spatrick   auto type_system_or_err =
686061da546Spatrick       GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
687061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
688*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
689*f6aab3d8Srobert                    "Unable to get DeclContext containing UID");
690061da546Spatrick     return CompilerDeclContext();
691061da546Spatrick   }
692061da546Spatrick 
693*f6aab3d8Srobert   auto ts = *type_system_or_err;
694dda28197Spatrick   TypeSystemClang *clang_ast_ctx =
695*f6aab3d8Srobert       llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
696061da546Spatrick   if (!clang_ast_ctx)
697061da546Spatrick     return CompilerDeclContext();
698061da546Spatrick 
699061da546Spatrick   PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
700061da546Spatrick   if (!pdb)
701061da546Spatrick     return CompilerDeclContext();
702061da546Spatrick 
703061da546Spatrick   auto symbol = m_session_up->getSymbolById(uid);
704061da546Spatrick   if (!symbol)
705061da546Spatrick     return CompilerDeclContext();
706061da546Spatrick 
707061da546Spatrick   auto decl_context = pdb->GetDeclContextContainingSymbol(*symbol);
708061da546Spatrick   assert(decl_context);
709061da546Spatrick 
710061da546Spatrick   return clang_ast_ctx->CreateDeclContext(decl_context);
711061da546Spatrick }
712061da546Spatrick 
ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx)713061da546Spatrick void SymbolFilePDB::ParseDeclsForContext(
714061da546Spatrick     lldb_private::CompilerDeclContext decl_ctx) {
715061da546Spatrick   auto type_system_or_err =
716061da546Spatrick       GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
717061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
718*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
719*f6aab3d8Srobert                    "Unable to parse decls for context");
720061da546Spatrick     return;
721061da546Spatrick   }
722061da546Spatrick 
723*f6aab3d8Srobert   auto ts = *type_system_or_err;
724dda28197Spatrick   TypeSystemClang *clang_ast_ctx =
725*f6aab3d8Srobert       llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
726061da546Spatrick   if (!clang_ast_ctx)
727061da546Spatrick     return;
728061da546Spatrick 
729061da546Spatrick   PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
730061da546Spatrick   if (!pdb)
731061da546Spatrick     return;
732061da546Spatrick 
733061da546Spatrick   pdb->ParseDeclsForDeclContext(
734061da546Spatrick       static_cast<clang::DeclContext *>(decl_ctx.GetOpaqueDeclContext()));
735061da546Spatrick }
736061da546Spatrick 
737061da546Spatrick uint32_t
ResolveSymbolContext(const lldb_private::Address & so_addr,SymbolContextItem resolve_scope,lldb_private::SymbolContext & sc)738061da546Spatrick SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
739061da546Spatrick                                     SymbolContextItem resolve_scope,
740061da546Spatrick                                     lldb_private::SymbolContext &sc) {
741061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
742061da546Spatrick   uint32_t resolved_flags = 0;
743061da546Spatrick   if (resolve_scope & eSymbolContextCompUnit ||
744061da546Spatrick       resolve_scope & eSymbolContextVariable ||
745061da546Spatrick       resolve_scope & eSymbolContextFunction ||
746061da546Spatrick       resolve_scope & eSymbolContextBlock ||
747061da546Spatrick       resolve_scope & eSymbolContextLineEntry) {
748061da546Spatrick     auto cu_sp = GetCompileUnitContainsAddress(so_addr);
749061da546Spatrick     if (!cu_sp) {
750061da546Spatrick       if (resolved_flags & eSymbolContextVariable) {
751061da546Spatrick         // TODO: Resolve variables
752061da546Spatrick       }
753061da546Spatrick       return 0;
754061da546Spatrick     }
755061da546Spatrick     sc.comp_unit = cu_sp.get();
756061da546Spatrick     resolved_flags |= eSymbolContextCompUnit;
757061da546Spatrick     lldbassert(sc.module_sp == cu_sp->GetModule());
758061da546Spatrick   }
759061da546Spatrick 
760061da546Spatrick   if (resolve_scope & eSymbolContextFunction ||
761061da546Spatrick       resolve_scope & eSymbolContextBlock) {
762061da546Spatrick     addr_t file_vm_addr = so_addr.GetFileAddress();
763061da546Spatrick     auto symbol_up =
764061da546Spatrick         m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::Function);
765061da546Spatrick     if (symbol_up) {
766061da546Spatrick       auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get());
767061da546Spatrick       assert(pdb_func);
768061da546Spatrick       auto func_uid = pdb_func->getSymIndexId();
769061da546Spatrick       sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get();
770061da546Spatrick       if (sc.function == nullptr)
771061da546Spatrick         sc.function =
772061da546Spatrick             ParseCompileUnitFunctionForPDBFunc(*pdb_func, *sc.comp_unit);
773061da546Spatrick       if (sc.function) {
774061da546Spatrick         resolved_flags |= eSymbolContextFunction;
775061da546Spatrick         if (resolve_scope & eSymbolContextBlock) {
776061da546Spatrick           auto block_symbol = m_session_up->findSymbolByAddress(
777061da546Spatrick               file_vm_addr, PDB_SymType::Block);
778061da546Spatrick           auto block_id = block_symbol ? block_symbol->getSymIndexId()
779061da546Spatrick                                        : sc.function->GetID();
780061da546Spatrick           sc.block = sc.function->GetBlock(true).FindBlockByID(block_id);
781061da546Spatrick           if (sc.block)
782061da546Spatrick             resolved_flags |= eSymbolContextBlock;
783061da546Spatrick         }
784061da546Spatrick       }
785061da546Spatrick     }
786061da546Spatrick   }
787061da546Spatrick 
788061da546Spatrick   if (resolve_scope & eSymbolContextLineEntry) {
789061da546Spatrick     if (auto *line_table = sc.comp_unit->GetLineTable()) {
790061da546Spatrick       Address addr(so_addr);
791061da546Spatrick       if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
792061da546Spatrick         resolved_flags |= eSymbolContextLineEntry;
793061da546Spatrick     }
794061da546Spatrick   }
795061da546Spatrick 
796061da546Spatrick   return resolved_flags;
797061da546Spatrick }
798061da546Spatrick 
ResolveSymbolContext(const lldb_private::SourceLocationSpec & src_location_spec,SymbolContextItem resolve_scope,lldb_private::SymbolContextList & sc_list)799061da546Spatrick uint32_t SymbolFilePDB::ResolveSymbolContext(
800be691f3bSpatrick     const lldb_private::SourceLocationSpec &src_location_spec,
801061da546Spatrick     SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) {
802061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
803061da546Spatrick   const size_t old_size = sc_list.GetSize();
804be691f3bSpatrick   const FileSpec &file_spec = src_location_spec.GetFileSpec();
805*f6aab3d8Srobert   const uint32_t line = src_location_spec.GetLine().value_or(0);
806061da546Spatrick   if (resolve_scope & lldb::eSymbolContextCompUnit) {
807061da546Spatrick     // Locate all compilation units with line numbers referencing the specified
808061da546Spatrick     // file.  For example, if `file_spec` is <vector>, then this should return
809061da546Spatrick     // all source files and header files that reference <vector>, either
810061da546Spatrick     // directly or indirectly.
811061da546Spatrick     auto compilands = m_session_up->findCompilandsForSourceFile(
812061da546Spatrick         file_spec.GetPath(), PDB_NameSearchFlags::NS_CaseInsensitive);
813061da546Spatrick 
814061da546Spatrick     if (!compilands)
815061da546Spatrick       return 0;
816061da546Spatrick 
817061da546Spatrick     // For each one, either find its previously parsed data or parse it afresh
818061da546Spatrick     // and add it to the symbol context list.
819061da546Spatrick     while (auto compiland = compilands->getNext()) {
820061da546Spatrick       // If we're not checking inlines, then don't add line information for
821061da546Spatrick       // this file unless the FileSpec matches. For inline functions, we don't
822061da546Spatrick       // have to match the FileSpec since they could be defined in headers
823061da546Spatrick       // other than file specified in FileSpec.
824be691f3bSpatrick       if (!src_location_spec.GetCheckInlines()) {
825061da546Spatrick         std::string source_file = compiland->getSourceFileFullPath();
826061da546Spatrick         if (source_file.empty())
827061da546Spatrick           continue;
828061da546Spatrick         FileSpec this_spec(source_file, FileSpec::Style::windows);
829061da546Spatrick         bool need_full_match = !file_spec.GetDirectory().IsEmpty();
830061da546Spatrick         if (FileSpec::Compare(file_spec, this_spec, need_full_match) != 0)
831061da546Spatrick           continue;
832061da546Spatrick       }
833061da546Spatrick 
834061da546Spatrick       SymbolContext sc;
835061da546Spatrick       auto cu = ParseCompileUnitForUID(compiland->getSymIndexId());
836061da546Spatrick       if (!cu)
837061da546Spatrick         continue;
838061da546Spatrick       sc.comp_unit = cu.get();
839061da546Spatrick       sc.module_sp = cu->GetModule();
840061da546Spatrick 
841061da546Spatrick       // If we were asked to resolve line entries, add all entries to the line
842061da546Spatrick       // table that match the requested line (or all lines if `line` == 0).
843061da546Spatrick       if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock |
844061da546Spatrick                            eSymbolContextLineEntry)) {
845061da546Spatrick         bool has_line_table = ParseCompileUnitLineTable(*sc.comp_unit, line);
846061da546Spatrick 
847061da546Spatrick         if ((resolve_scope & eSymbolContextLineEntry) && !has_line_table) {
848061da546Spatrick           // The query asks for line entries, but we can't get them for the
849061da546Spatrick           // compile unit. This is not normal for `line` = 0. So just assert
850061da546Spatrick           // it.
851061da546Spatrick           assert(line && "Couldn't get all line entries!\n");
852061da546Spatrick 
853061da546Spatrick           // Current compiland does not have the requested line. Search next.
854061da546Spatrick           continue;
855061da546Spatrick         }
856061da546Spatrick 
857061da546Spatrick         if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) {
858061da546Spatrick           if (!has_line_table)
859061da546Spatrick             continue;
860061da546Spatrick 
861061da546Spatrick           auto *line_table = sc.comp_unit->GetLineTable();
862061da546Spatrick           lldbassert(line_table);
863061da546Spatrick 
864061da546Spatrick           uint32_t num_line_entries = line_table->GetSize();
865061da546Spatrick           // Skip the terminal line entry.
866061da546Spatrick           --num_line_entries;
867061da546Spatrick 
868061da546Spatrick           // If `line `!= 0, see if we can resolve function for each line entry
869061da546Spatrick           // in the line table.
870061da546Spatrick           for (uint32_t line_idx = 0; line && line_idx < num_line_entries;
871061da546Spatrick                ++line_idx) {
872061da546Spatrick             if (!line_table->GetLineEntryAtIndex(line_idx, sc.line_entry))
873061da546Spatrick               continue;
874061da546Spatrick 
875061da546Spatrick             auto file_vm_addr =
876061da546Spatrick                 sc.line_entry.range.GetBaseAddress().GetFileAddress();
877061da546Spatrick             if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
878061da546Spatrick               continue;
879061da546Spatrick 
880061da546Spatrick             auto symbol_up = m_session_up->findSymbolByAddress(
881061da546Spatrick                 file_vm_addr, PDB_SymType::Function);
882061da546Spatrick             if (symbol_up) {
883061da546Spatrick               auto func_uid = symbol_up->getSymIndexId();
884061da546Spatrick               sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get();
885061da546Spatrick               if (sc.function == nullptr) {
886061da546Spatrick                 auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get());
887061da546Spatrick                 assert(pdb_func);
888061da546Spatrick                 sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func,
889061da546Spatrick                                                                  *sc.comp_unit);
890061da546Spatrick               }
891061da546Spatrick               if (sc.function && (resolve_scope & eSymbolContextBlock)) {
892061da546Spatrick                 Block &block = sc.function->GetBlock(true);
893061da546Spatrick                 sc.block = block.FindBlockByID(sc.function->GetID());
894061da546Spatrick               }
895061da546Spatrick             }
896061da546Spatrick             sc_list.Append(sc);
897061da546Spatrick           }
898061da546Spatrick         } else if (has_line_table) {
899061da546Spatrick           // We can parse line table for the compile unit. But no query to
900061da546Spatrick           // resolve function or block. We append `sc` to the list anyway.
901061da546Spatrick           sc_list.Append(sc);
902061da546Spatrick         }
903061da546Spatrick       } else {
904061da546Spatrick         // No query for line entry, function or block. But we have a valid
905061da546Spatrick         // compile unit, append `sc` to the list.
906061da546Spatrick         sc_list.Append(sc);
907061da546Spatrick       }
908061da546Spatrick     }
909061da546Spatrick   }
910061da546Spatrick   return sc_list.GetSize() - old_size;
911061da546Spatrick }
912061da546Spatrick 
GetMangledForPDBData(const PDBSymbolData & pdb_data)913061da546Spatrick std::string SymbolFilePDB::GetMangledForPDBData(const PDBSymbolData &pdb_data) {
914061da546Spatrick   // Cache public names at first
915061da546Spatrick   if (m_public_names.empty())
916061da546Spatrick     if (auto result_up =
917061da546Spatrick             m_global_scope_up->findAllChildren(PDB_SymType::PublicSymbol))
918061da546Spatrick       while (auto symbol_up = result_up->getNext())
919061da546Spatrick         if (auto addr = symbol_up->getRawSymbol().getVirtualAddress())
920061da546Spatrick           m_public_names[addr] = symbol_up->getRawSymbol().getName();
921061da546Spatrick 
922061da546Spatrick   // Look up the name in the cache
923061da546Spatrick   return m_public_names.lookup(pdb_data.getVirtualAddress());
924061da546Spatrick }
925061da546Spatrick 
ParseVariableForPDBData(const lldb_private::SymbolContext & sc,const llvm::pdb::PDBSymbolData & pdb_data)926061da546Spatrick VariableSP SymbolFilePDB::ParseVariableForPDBData(
927061da546Spatrick     const lldb_private::SymbolContext &sc,
928061da546Spatrick     const llvm::pdb::PDBSymbolData &pdb_data) {
929061da546Spatrick   VariableSP var_sp;
930061da546Spatrick   uint32_t var_uid = pdb_data.getSymIndexId();
931061da546Spatrick   auto result = m_variables.find(var_uid);
932061da546Spatrick   if (result != m_variables.end())
933061da546Spatrick     return result->second;
934061da546Spatrick 
935061da546Spatrick   ValueType scope = eValueTypeInvalid;
936061da546Spatrick   bool is_static_member = false;
937061da546Spatrick   bool is_external = false;
938061da546Spatrick   bool is_artificial = false;
939061da546Spatrick 
940061da546Spatrick   switch (pdb_data.getDataKind()) {
941061da546Spatrick   case PDB_DataKind::Global:
942061da546Spatrick     scope = eValueTypeVariableGlobal;
943061da546Spatrick     is_external = true;
944061da546Spatrick     break;
945061da546Spatrick   case PDB_DataKind::Local:
946061da546Spatrick     scope = eValueTypeVariableLocal;
947061da546Spatrick     break;
948061da546Spatrick   case PDB_DataKind::FileStatic:
949061da546Spatrick     scope = eValueTypeVariableStatic;
950061da546Spatrick     break;
951061da546Spatrick   case PDB_DataKind::StaticMember:
952061da546Spatrick     is_static_member = true;
953061da546Spatrick     scope = eValueTypeVariableStatic;
954061da546Spatrick     break;
955061da546Spatrick   case PDB_DataKind::Member:
956061da546Spatrick     scope = eValueTypeVariableStatic;
957061da546Spatrick     break;
958061da546Spatrick   case PDB_DataKind::Param:
959061da546Spatrick     scope = eValueTypeVariableArgument;
960061da546Spatrick     break;
961061da546Spatrick   case PDB_DataKind::Constant:
962061da546Spatrick     scope = eValueTypeConstResult;
963061da546Spatrick     break;
964061da546Spatrick   default:
965061da546Spatrick     break;
966061da546Spatrick   }
967061da546Spatrick 
968061da546Spatrick   switch (pdb_data.getLocationType()) {
969061da546Spatrick   case PDB_LocType::TLS:
970061da546Spatrick     scope = eValueTypeVariableThreadLocal;
971061da546Spatrick     break;
972061da546Spatrick   case PDB_LocType::RegRel: {
973061da546Spatrick     // It is a `this` pointer.
974061da546Spatrick     if (pdb_data.getDataKind() == PDB_DataKind::ObjectPtr) {
975061da546Spatrick       scope = eValueTypeVariableArgument;
976061da546Spatrick       is_artificial = true;
977061da546Spatrick     }
978061da546Spatrick   } break;
979061da546Spatrick   default:
980061da546Spatrick     break;
981061da546Spatrick   }
982061da546Spatrick 
983061da546Spatrick   Declaration decl;
984061da546Spatrick   if (!is_artificial && !pdb_data.isCompilerGenerated()) {
985061da546Spatrick     if (auto lines = pdb_data.getLineNumbers()) {
986061da546Spatrick       if (auto first_line = lines->getNext()) {
987061da546Spatrick         uint32_t src_file_id = first_line->getSourceFileId();
988061da546Spatrick         auto src_file = m_session_up->getSourceFileById(src_file_id);
989061da546Spatrick         if (src_file) {
990061da546Spatrick           FileSpec spec(src_file->getFileName());
991061da546Spatrick           decl.SetFile(spec);
992061da546Spatrick           decl.SetColumn(first_line->getColumnNumber());
993061da546Spatrick           decl.SetLine(first_line->getLineNumber());
994061da546Spatrick         }
995061da546Spatrick       }
996061da546Spatrick     }
997061da546Spatrick   }
998061da546Spatrick 
999061da546Spatrick   Variable::RangeList ranges;
1000061da546Spatrick   SymbolContextScope *context_scope = sc.comp_unit;
1001061da546Spatrick   if (scope == eValueTypeVariableLocal || scope == eValueTypeVariableArgument) {
1002061da546Spatrick     if (sc.function) {
1003061da546Spatrick       Block &function_block = sc.function->GetBlock(true);
1004061da546Spatrick       Block *block =
1005061da546Spatrick           function_block.FindBlockByID(pdb_data.getLexicalParentId());
1006061da546Spatrick       if (!block)
1007061da546Spatrick         block = &function_block;
1008061da546Spatrick 
1009061da546Spatrick       context_scope = block;
1010061da546Spatrick 
1011061da546Spatrick       for (size_t i = 0, num_ranges = block->GetNumRanges(); i < num_ranges;
1012061da546Spatrick            ++i) {
1013061da546Spatrick         AddressRange range;
1014061da546Spatrick         if (!block->GetRangeAtIndex(i, range))
1015061da546Spatrick           continue;
1016061da546Spatrick 
1017061da546Spatrick         ranges.Append(range.GetBaseAddress().GetFileAddress(),
1018061da546Spatrick                       range.GetByteSize());
1019061da546Spatrick       }
1020061da546Spatrick     }
1021061da546Spatrick   }
1022061da546Spatrick 
1023061da546Spatrick   SymbolFileTypeSP type_sp =
1024061da546Spatrick       std::make_shared<SymbolFileType>(*this, pdb_data.getTypeId());
1025061da546Spatrick 
1026061da546Spatrick   auto var_name = pdb_data.getName();
1027061da546Spatrick   auto mangled = GetMangledForPDBData(pdb_data);
1028061da546Spatrick   auto mangled_cstr = mangled.empty() ? nullptr : mangled.c_str();
1029061da546Spatrick 
1030061da546Spatrick   bool is_constant;
1031*f6aab3d8Srobert   ModuleSP module_sp = GetObjectFile()->GetModule();
1032*f6aab3d8Srobert   DWARFExpressionList location(module_sp,
1033*f6aab3d8Srobert                                ConvertPDBLocationToDWARFExpression(
1034*f6aab3d8Srobert                                    module_sp, pdb_data, ranges, is_constant),
1035*f6aab3d8Srobert                                nullptr);
1036061da546Spatrick 
1037061da546Spatrick   var_sp = std::make_shared<Variable>(
1038061da546Spatrick       var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope,
1039be691f3bSpatrick       ranges, &decl, location, is_external, is_artificial, is_constant,
1040be691f3bSpatrick       is_static_member);
1041061da546Spatrick 
1042061da546Spatrick   m_variables.insert(std::make_pair(var_uid, var_sp));
1043061da546Spatrick   return var_sp;
1044061da546Spatrick }
1045061da546Spatrick 
1046061da546Spatrick size_t
ParseVariables(const lldb_private::SymbolContext & sc,const llvm::pdb::PDBSymbol & pdb_symbol,lldb_private::VariableList * variable_list)1047061da546Spatrick SymbolFilePDB::ParseVariables(const lldb_private::SymbolContext &sc,
1048061da546Spatrick                               const llvm::pdb::PDBSymbol &pdb_symbol,
1049061da546Spatrick                               lldb_private::VariableList *variable_list) {
1050061da546Spatrick   size_t num_added = 0;
1051061da546Spatrick 
1052061da546Spatrick   if (auto pdb_data = llvm::dyn_cast<PDBSymbolData>(&pdb_symbol)) {
1053061da546Spatrick     VariableListSP local_variable_list_sp;
1054061da546Spatrick 
1055061da546Spatrick     auto result = m_variables.find(pdb_data->getSymIndexId());
1056061da546Spatrick     if (result != m_variables.end()) {
1057061da546Spatrick       if (variable_list)
1058061da546Spatrick         variable_list->AddVariableIfUnique(result->second);
1059061da546Spatrick     } else {
1060061da546Spatrick       // Prepare right VariableList for this variable.
1061061da546Spatrick       if (auto lexical_parent = pdb_data->getLexicalParent()) {
1062061da546Spatrick         switch (lexical_parent->getSymTag()) {
1063061da546Spatrick         case PDB_SymType::Exe:
1064061da546Spatrick           assert(sc.comp_unit);
1065*f6aab3d8Srobert           [[fallthrough]];
1066061da546Spatrick         case PDB_SymType::Compiland: {
1067061da546Spatrick           if (sc.comp_unit) {
1068061da546Spatrick             local_variable_list_sp = sc.comp_unit->GetVariableList(false);
1069061da546Spatrick             if (!local_variable_list_sp) {
1070061da546Spatrick               local_variable_list_sp = std::make_shared<VariableList>();
1071061da546Spatrick               sc.comp_unit->SetVariableList(local_variable_list_sp);
1072061da546Spatrick             }
1073061da546Spatrick           }
1074061da546Spatrick         } break;
1075061da546Spatrick         case PDB_SymType::Block:
1076061da546Spatrick         case PDB_SymType::Function: {
1077061da546Spatrick           if (sc.function) {
1078061da546Spatrick             Block *block = sc.function->GetBlock(true).FindBlockByID(
1079061da546Spatrick                 lexical_parent->getSymIndexId());
1080061da546Spatrick             if (block) {
1081061da546Spatrick               local_variable_list_sp = block->GetBlockVariableList(false);
1082061da546Spatrick               if (!local_variable_list_sp) {
1083061da546Spatrick                 local_variable_list_sp = std::make_shared<VariableList>();
1084061da546Spatrick                 block->SetVariableList(local_variable_list_sp);
1085061da546Spatrick               }
1086061da546Spatrick             }
1087061da546Spatrick           }
1088061da546Spatrick         } break;
1089061da546Spatrick         default:
1090061da546Spatrick           break;
1091061da546Spatrick         }
1092061da546Spatrick       }
1093061da546Spatrick 
1094061da546Spatrick       if (local_variable_list_sp) {
1095061da546Spatrick         if (auto var_sp = ParseVariableForPDBData(sc, *pdb_data)) {
1096061da546Spatrick           local_variable_list_sp->AddVariableIfUnique(var_sp);
1097061da546Spatrick           if (variable_list)
1098061da546Spatrick             variable_list->AddVariableIfUnique(var_sp);
1099061da546Spatrick           ++num_added;
1100061da546Spatrick           PDBASTParser *ast = GetPDBAstParser();
1101061da546Spatrick           if (ast)
1102061da546Spatrick             ast->GetDeclForSymbol(*pdb_data);
1103061da546Spatrick         }
1104061da546Spatrick       }
1105061da546Spatrick     }
1106061da546Spatrick   }
1107061da546Spatrick 
1108061da546Spatrick   if (auto results = pdb_symbol.findAllChildren()) {
1109061da546Spatrick     while (auto result = results->getNext())
1110061da546Spatrick       num_added += ParseVariables(sc, *result, variable_list);
1111061da546Spatrick   }
1112061da546Spatrick 
1113061da546Spatrick   return num_added;
1114061da546Spatrick }
1115061da546Spatrick 
FindGlobalVariables(lldb_private::ConstString name,const CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,lldb_private::VariableList & variables)1116061da546Spatrick void SymbolFilePDB::FindGlobalVariables(
1117dda28197Spatrick     lldb_private::ConstString name, const CompilerDeclContext &parent_decl_ctx,
1118061da546Spatrick     uint32_t max_matches, lldb_private::VariableList &variables) {
1119061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1120061da546Spatrick   if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
1121061da546Spatrick     return;
1122061da546Spatrick   if (name.IsEmpty())
1123061da546Spatrick     return;
1124061da546Spatrick 
1125061da546Spatrick   auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
1126061da546Spatrick   if (!results)
1127061da546Spatrick     return;
1128061da546Spatrick 
1129061da546Spatrick   uint32_t matches = 0;
1130061da546Spatrick   size_t old_size = variables.GetSize();
1131061da546Spatrick   while (auto result = results->getNext()) {
1132061da546Spatrick     auto pdb_data = llvm::dyn_cast<PDBSymbolData>(result.get());
1133061da546Spatrick     if (max_matches > 0 && matches >= max_matches)
1134061da546Spatrick       break;
1135061da546Spatrick 
1136061da546Spatrick     SymbolContext sc;
1137061da546Spatrick     sc.module_sp = m_objfile_sp->GetModule();
1138061da546Spatrick     lldbassert(sc.module_sp.get());
1139061da546Spatrick 
1140061da546Spatrick     if (!name.GetStringRef().equals(
1141061da546Spatrick             MSVCUndecoratedNameParser::DropScope(pdb_data->getName())))
1142061da546Spatrick       continue;
1143061da546Spatrick 
1144061da546Spatrick     sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get();
1145061da546Spatrick     // FIXME: We are not able to determine the compile unit.
1146061da546Spatrick     if (sc.comp_unit == nullptr)
1147061da546Spatrick       continue;
1148061da546Spatrick 
1149dda28197Spatrick     if (parent_decl_ctx.IsValid() &&
1150dda28197Spatrick         GetDeclContextContainingUID(result->getSymIndexId()) != parent_decl_ctx)
1151061da546Spatrick       continue;
1152061da546Spatrick 
1153061da546Spatrick     ParseVariables(sc, *pdb_data, &variables);
1154061da546Spatrick     matches = variables.GetSize() - old_size;
1155061da546Spatrick   }
1156061da546Spatrick }
1157061da546Spatrick 
FindGlobalVariables(const lldb_private::RegularExpression & regex,uint32_t max_matches,lldb_private::VariableList & variables)1158061da546Spatrick void SymbolFilePDB::FindGlobalVariables(
1159061da546Spatrick     const lldb_private::RegularExpression &regex, uint32_t max_matches,
1160061da546Spatrick     lldb_private::VariableList &variables) {
1161061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1162061da546Spatrick   if (!regex.IsValid())
1163061da546Spatrick     return;
1164061da546Spatrick   auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
1165061da546Spatrick   if (!results)
1166061da546Spatrick     return;
1167061da546Spatrick 
1168061da546Spatrick   uint32_t matches = 0;
1169061da546Spatrick   size_t old_size = variables.GetSize();
1170061da546Spatrick   while (auto pdb_data = results->getNext()) {
1171061da546Spatrick     if (max_matches > 0 && matches >= max_matches)
1172061da546Spatrick       break;
1173061da546Spatrick 
1174061da546Spatrick     auto var_name = pdb_data->getName();
1175061da546Spatrick     if (var_name.empty())
1176061da546Spatrick       continue;
1177061da546Spatrick     if (!regex.Execute(var_name))
1178061da546Spatrick       continue;
1179061da546Spatrick     SymbolContext sc;
1180061da546Spatrick     sc.module_sp = m_objfile_sp->GetModule();
1181061da546Spatrick     lldbassert(sc.module_sp.get());
1182061da546Spatrick 
1183061da546Spatrick     sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get();
1184061da546Spatrick     // FIXME: We are not able to determine the compile unit.
1185061da546Spatrick     if (sc.comp_unit == nullptr)
1186061da546Spatrick       continue;
1187061da546Spatrick 
1188061da546Spatrick     ParseVariables(sc, *pdb_data, &variables);
1189061da546Spatrick     matches = variables.GetSize() - old_size;
1190061da546Spatrick   }
1191061da546Spatrick }
1192061da546Spatrick 
ResolveFunction(const llvm::pdb::PDBSymbolFunc & pdb_func,bool include_inlines,lldb_private::SymbolContextList & sc_list)1193061da546Spatrick bool SymbolFilePDB::ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func,
1194061da546Spatrick                                     bool include_inlines,
1195061da546Spatrick                                     lldb_private::SymbolContextList &sc_list) {
1196061da546Spatrick   lldb_private::SymbolContext sc;
1197061da546Spatrick   sc.comp_unit = ParseCompileUnitForUID(pdb_func.getCompilandId()).get();
1198061da546Spatrick   if (!sc.comp_unit)
1199061da546Spatrick     return false;
1200061da546Spatrick   sc.module_sp = sc.comp_unit->GetModule();
1201061da546Spatrick   sc.function = ParseCompileUnitFunctionForPDBFunc(pdb_func, *sc.comp_unit);
1202061da546Spatrick   if (!sc.function)
1203061da546Spatrick     return false;
1204061da546Spatrick 
1205061da546Spatrick   sc_list.Append(sc);
1206061da546Spatrick   return true;
1207061da546Spatrick }
1208061da546Spatrick 
ResolveFunction(uint32_t uid,bool include_inlines,lldb_private::SymbolContextList & sc_list)1209061da546Spatrick bool SymbolFilePDB::ResolveFunction(uint32_t uid, bool include_inlines,
1210061da546Spatrick                                     lldb_private::SymbolContextList &sc_list) {
1211061da546Spatrick   auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid);
1212061da546Spatrick   if (!pdb_func_up && !(include_inlines && pdb_func_up->hasInlineAttribute()))
1213061da546Spatrick     return false;
1214061da546Spatrick   return ResolveFunction(*pdb_func_up, include_inlines, sc_list);
1215061da546Spatrick }
1216061da546Spatrick 
CacheFunctionNames()1217061da546Spatrick void SymbolFilePDB::CacheFunctionNames() {
1218061da546Spatrick   if (!m_func_full_names.IsEmpty())
1219061da546Spatrick     return;
1220061da546Spatrick 
1221061da546Spatrick   std::map<uint64_t, uint32_t> addr_ids;
1222061da546Spatrick 
1223061da546Spatrick   if (auto results_up = m_global_scope_up->findAllChildren<PDBSymbolFunc>()) {
1224061da546Spatrick     while (auto pdb_func_up = results_up->getNext()) {
1225061da546Spatrick       if (pdb_func_up->isCompilerGenerated())
1226061da546Spatrick         continue;
1227061da546Spatrick 
1228061da546Spatrick       auto name = pdb_func_up->getName();
1229061da546Spatrick       auto demangled_name = pdb_func_up->getUndecoratedName();
1230061da546Spatrick       if (name.empty() && demangled_name.empty())
1231061da546Spatrick         continue;
1232061da546Spatrick 
1233061da546Spatrick       auto uid = pdb_func_up->getSymIndexId();
1234061da546Spatrick       if (!demangled_name.empty() && pdb_func_up->getVirtualAddress())
1235061da546Spatrick         addr_ids.insert(std::make_pair(pdb_func_up->getVirtualAddress(), uid));
1236061da546Spatrick 
1237061da546Spatrick       if (auto parent = pdb_func_up->getClassParent()) {
1238061da546Spatrick 
1239061da546Spatrick         // PDB have symbols for class/struct methods or static methods in Enum
1240061da546Spatrick         // Class. We won't bother to check if the parent is UDT or Enum here.
1241061da546Spatrick         m_func_method_names.Append(ConstString(name), uid);
1242061da546Spatrick 
1243061da546Spatrick         // To search a method name, like NS::Class:MemberFunc, LLDB searches
1244061da546Spatrick         // its base name, i.e. MemberFunc by default. Since PDBSymbolFunc does
1245dda28197Spatrick         // not have information of this, we extract base names and cache them
1246061da546Spatrick         // by our own effort.
1247061da546Spatrick         llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(name);
1248061da546Spatrick         if (!basename.empty())
1249061da546Spatrick           m_func_base_names.Append(ConstString(basename), uid);
1250061da546Spatrick         else {
1251061da546Spatrick           m_func_base_names.Append(ConstString(name), uid);
1252061da546Spatrick         }
1253061da546Spatrick 
1254061da546Spatrick         if (!demangled_name.empty())
1255061da546Spatrick           m_func_full_names.Append(ConstString(demangled_name), uid);
1256061da546Spatrick 
1257061da546Spatrick       } else {
1258061da546Spatrick         // Handle not-method symbols.
1259061da546Spatrick 
1260061da546Spatrick         // The function name might contain namespace, or its lexical scope.
1261061da546Spatrick         llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(name);
1262061da546Spatrick         if (!basename.empty())
1263061da546Spatrick           m_func_base_names.Append(ConstString(basename), uid);
1264061da546Spatrick         else
1265061da546Spatrick           m_func_base_names.Append(ConstString(name), uid);
1266061da546Spatrick 
1267061da546Spatrick         if (name == "main") {
1268061da546Spatrick           m_func_full_names.Append(ConstString(name), uid);
1269061da546Spatrick 
1270061da546Spatrick           if (!demangled_name.empty() && name != demangled_name) {
1271061da546Spatrick             m_func_full_names.Append(ConstString(demangled_name), uid);
1272061da546Spatrick             m_func_base_names.Append(ConstString(demangled_name), uid);
1273061da546Spatrick           }
1274061da546Spatrick         } else if (!demangled_name.empty()) {
1275061da546Spatrick           m_func_full_names.Append(ConstString(demangled_name), uid);
1276061da546Spatrick         } else {
1277061da546Spatrick           m_func_full_names.Append(ConstString(name), uid);
1278061da546Spatrick         }
1279061da546Spatrick       }
1280061da546Spatrick     }
1281061da546Spatrick   }
1282061da546Spatrick 
1283061da546Spatrick   if (auto results_up =
1284061da546Spatrick           m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>()) {
1285061da546Spatrick     while (auto pub_sym_up = results_up->getNext()) {
1286061da546Spatrick       if (!pub_sym_up->isFunction())
1287061da546Spatrick         continue;
1288061da546Spatrick       auto name = pub_sym_up->getName();
1289061da546Spatrick       if (name.empty())
1290061da546Spatrick         continue;
1291061da546Spatrick 
1292061da546Spatrick       if (CPlusPlusLanguage::IsCPPMangledName(name.c_str())) {
1293061da546Spatrick         auto vm_addr = pub_sym_up->getVirtualAddress();
1294061da546Spatrick 
1295061da546Spatrick         // PDB public symbol has mangled name for its associated function.
1296061da546Spatrick         if (vm_addr && addr_ids.find(vm_addr) != addr_ids.end()) {
1297061da546Spatrick           // Cache mangled name.
1298061da546Spatrick           m_func_full_names.Append(ConstString(name), addr_ids[vm_addr]);
1299061da546Spatrick         }
1300061da546Spatrick       }
1301061da546Spatrick     }
1302061da546Spatrick   }
1303061da546Spatrick   // Sort them before value searching is working properly
1304061da546Spatrick   m_func_full_names.Sort();
1305061da546Spatrick   m_func_full_names.SizeToFit();
1306061da546Spatrick   m_func_method_names.Sort();
1307061da546Spatrick   m_func_method_names.SizeToFit();
1308061da546Spatrick   m_func_base_names.Sort();
1309061da546Spatrick   m_func_base_names.SizeToFit();
1310061da546Spatrick }
1311061da546Spatrick 
FindFunctions(const lldb_private::Module::LookupInfo & lookup_info,const lldb_private::CompilerDeclContext & parent_decl_ctx,bool include_inlines,lldb_private::SymbolContextList & sc_list)1312061da546Spatrick void SymbolFilePDB::FindFunctions(
1313*f6aab3d8Srobert     const lldb_private::Module::LookupInfo &lookup_info,
1314dda28197Spatrick     const lldb_private::CompilerDeclContext &parent_decl_ctx,
1315*f6aab3d8Srobert     bool include_inlines,
1316061da546Spatrick     lldb_private::SymbolContextList &sc_list) {
1317061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1318*f6aab3d8Srobert   ConstString name = lookup_info.GetLookupName();
1319*f6aab3d8Srobert   FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();
1320061da546Spatrick   lldbassert((name_type_mask & eFunctionNameTypeAuto) == 0);
1321061da546Spatrick 
1322*f6aab3d8Srobert   if (name_type_mask & eFunctionNameTypeFull)
1323*f6aab3d8Srobert     name = lookup_info.GetName();
1324*f6aab3d8Srobert 
1325061da546Spatrick   if (name_type_mask == eFunctionNameTypeNone)
1326061da546Spatrick     return;
1327061da546Spatrick   if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
1328061da546Spatrick     return;
1329061da546Spatrick   if (name.IsEmpty())
1330061da546Spatrick     return;
1331061da546Spatrick 
1332061da546Spatrick   if (name_type_mask & eFunctionNameTypeFull ||
1333061da546Spatrick       name_type_mask & eFunctionNameTypeBase ||
1334061da546Spatrick       name_type_mask & eFunctionNameTypeMethod) {
1335061da546Spatrick     CacheFunctionNames();
1336061da546Spatrick 
1337061da546Spatrick     std::set<uint32_t> resolved_ids;
1338061da546Spatrick     auto ResolveFn = [this, &name, parent_decl_ctx, include_inlines, &sc_list,
1339061da546Spatrick                       &resolved_ids](UniqueCStringMap<uint32_t> &Names) {
1340061da546Spatrick       std::vector<uint32_t> ids;
1341061da546Spatrick       if (!Names.GetValues(name, ids))
1342061da546Spatrick         return;
1343061da546Spatrick 
1344061da546Spatrick       for (uint32_t id : ids) {
1345061da546Spatrick         if (resolved_ids.find(id) != resolved_ids.end())
1346061da546Spatrick           continue;
1347061da546Spatrick 
1348dda28197Spatrick         if (parent_decl_ctx.IsValid() &&
1349dda28197Spatrick             GetDeclContextContainingUID(id) != parent_decl_ctx)
1350061da546Spatrick           continue;
1351061da546Spatrick 
1352061da546Spatrick         if (ResolveFunction(id, include_inlines, sc_list))
1353061da546Spatrick           resolved_ids.insert(id);
1354061da546Spatrick       }
1355061da546Spatrick     };
1356061da546Spatrick     if (name_type_mask & eFunctionNameTypeFull) {
1357061da546Spatrick       ResolveFn(m_func_full_names);
1358061da546Spatrick       ResolveFn(m_func_base_names);
1359061da546Spatrick       ResolveFn(m_func_method_names);
1360061da546Spatrick     }
1361061da546Spatrick     if (name_type_mask & eFunctionNameTypeBase)
1362061da546Spatrick       ResolveFn(m_func_base_names);
1363061da546Spatrick     if (name_type_mask & eFunctionNameTypeMethod)
1364061da546Spatrick       ResolveFn(m_func_method_names);
1365061da546Spatrick   }
1366061da546Spatrick }
1367061da546Spatrick 
FindFunctions(const lldb_private::RegularExpression & regex,bool include_inlines,lldb_private::SymbolContextList & sc_list)1368061da546Spatrick void SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression &regex,
1369061da546Spatrick                                   bool include_inlines,
1370061da546Spatrick                                   lldb_private::SymbolContextList &sc_list) {
1371061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1372061da546Spatrick   if (!regex.IsValid())
1373061da546Spatrick     return;
1374061da546Spatrick 
1375061da546Spatrick   CacheFunctionNames();
1376061da546Spatrick 
1377061da546Spatrick   std::set<uint32_t> resolved_ids;
1378061da546Spatrick   auto ResolveFn = [&regex, include_inlines, &sc_list, &resolved_ids,
1379061da546Spatrick                     this](UniqueCStringMap<uint32_t> &Names) {
1380061da546Spatrick     std::vector<uint32_t> ids;
1381061da546Spatrick     if (Names.GetValues(regex, ids)) {
1382061da546Spatrick       for (auto id : ids) {
1383061da546Spatrick         if (resolved_ids.find(id) == resolved_ids.end())
1384061da546Spatrick           if (ResolveFunction(id, include_inlines, sc_list))
1385061da546Spatrick             resolved_ids.insert(id);
1386061da546Spatrick       }
1387061da546Spatrick     }
1388061da546Spatrick   };
1389061da546Spatrick   ResolveFn(m_func_full_names);
1390061da546Spatrick   ResolveFn(m_func_base_names);
1391061da546Spatrick }
1392061da546Spatrick 
GetMangledNamesForFunction(const std::string & scope_qualified_name,std::vector<lldb_private::ConstString> & mangled_names)1393061da546Spatrick void SymbolFilePDB::GetMangledNamesForFunction(
1394061da546Spatrick     const std::string &scope_qualified_name,
1395061da546Spatrick     std::vector<lldb_private::ConstString> &mangled_names) {}
1396061da546Spatrick 
AddSymbols(lldb_private::Symtab & symtab)1397061da546Spatrick void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) {
1398061da546Spatrick   std::set<lldb::addr_t> sym_addresses;
1399061da546Spatrick   for (size_t i = 0; i < symtab.GetNumSymbols(); i++)
1400061da546Spatrick     sym_addresses.insert(symtab.SymbolAtIndex(i)->GetFileAddress());
1401061da546Spatrick 
1402061da546Spatrick   auto results = m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>();
1403061da546Spatrick   if (!results)
1404061da546Spatrick     return;
1405061da546Spatrick 
1406061da546Spatrick   auto section_list = m_objfile_sp->GetSectionList();
1407061da546Spatrick   if (!section_list)
1408061da546Spatrick     return;
1409061da546Spatrick 
1410061da546Spatrick   while (auto pub_symbol = results->getNext()) {
1411061da546Spatrick     auto section_id = pub_symbol->getAddressSection();
1412061da546Spatrick 
1413061da546Spatrick     auto section = section_list->FindSectionByID(section_id);
1414061da546Spatrick     if (!section)
1415061da546Spatrick       continue;
1416061da546Spatrick 
1417061da546Spatrick     auto offset = pub_symbol->getAddressOffset();
1418061da546Spatrick 
1419061da546Spatrick     auto file_addr = section->GetFileAddress() + offset;
1420061da546Spatrick     if (sym_addresses.find(file_addr) != sym_addresses.end())
1421061da546Spatrick       continue;
1422061da546Spatrick     sym_addresses.insert(file_addr);
1423061da546Spatrick 
1424061da546Spatrick     auto size = pub_symbol->getLength();
1425061da546Spatrick     symtab.AddSymbol(
1426061da546Spatrick         Symbol(pub_symbol->getSymIndexId(),   // symID
1427061da546Spatrick                pub_symbol->getName().c_str(), // name
1428061da546Spatrick                pub_symbol->isCode() ? eSymbolTypeCode : eSymbolTypeData, // type
1429061da546Spatrick                true,      // external
1430061da546Spatrick                false,     // is_debug
1431061da546Spatrick                false,     // is_trampoline
1432061da546Spatrick                false,     // is_artificial
1433061da546Spatrick                section,   // section_sp
1434061da546Spatrick                offset,    // value
1435061da546Spatrick                size,      // size
1436061da546Spatrick                size != 0, // size_is_valid
1437061da546Spatrick                false,     // contains_linker_annotations
1438061da546Spatrick                0          // flags
1439061da546Spatrick                ));
1440061da546Spatrick   }
1441061da546Spatrick 
1442061da546Spatrick   symtab.Finalize();
1443061da546Spatrick }
1444061da546Spatrick 
FindTypes(lldb_private::ConstString name,const CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,llvm::DenseSet<lldb_private::SymbolFile * > & searched_symbol_files,lldb_private::TypeMap & types)1445061da546Spatrick void SymbolFilePDB::FindTypes(
1446dda28197Spatrick     lldb_private::ConstString name, const CompilerDeclContext &parent_decl_ctx,
1447061da546Spatrick     uint32_t max_matches,
1448061da546Spatrick     llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
1449061da546Spatrick     lldb_private::TypeMap &types) {
1450061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1451061da546Spatrick   if (!name)
1452061da546Spatrick     return;
1453061da546Spatrick   if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
1454061da546Spatrick     return;
1455061da546Spatrick 
1456061da546Spatrick   searched_symbol_files.clear();
1457061da546Spatrick   searched_symbol_files.insert(this);
1458061da546Spatrick 
1459061da546Spatrick   // There is an assumption 'name' is not a regex
1460061da546Spatrick   FindTypesByName(name.GetStringRef(), parent_decl_ctx, max_matches, types);
1461061da546Spatrick }
1462061da546Spatrick 
DumpClangAST(Stream & s)1463061da546Spatrick void SymbolFilePDB::DumpClangAST(Stream &s) {
1464061da546Spatrick   auto type_system_or_err =
1465061da546Spatrick       GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
1466061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
1467*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
1468*f6aab3d8Srobert                    "Unable to dump ClangAST");
1469061da546Spatrick     return;
1470061da546Spatrick   }
1471061da546Spatrick 
1472*f6aab3d8Srobert   auto ts = *type_system_or_err;
1473*f6aab3d8Srobert   TypeSystemClang *clang_type_system =
1474*f6aab3d8Srobert       llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
1475061da546Spatrick   if (!clang_type_system)
1476061da546Spatrick     return;
1477*f6aab3d8Srobert   clang_type_system->Dump(s.AsRawOstream());
1478061da546Spatrick }
1479061da546Spatrick 
FindTypesByRegex(const lldb_private::RegularExpression & regex,uint32_t max_matches,lldb_private::TypeMap & types)1480061da546Spatrick void SymbolFilePDB::FindTypesByRegex(
1481061da546Spatrick     const lldb_private::RegularExpression &regex, uint32_t max_matches,
1482061da546Spatrick     lldb_private::TypeMap &types) {
1483061da546Spatrick   // When searching by regex, we need to go out of our way to limit the search
1484061da546Spatrick   // space as much as possible since this searches EVERYTHING in the PDB,
1485061da546Spatrick   // manually doing regex comparisons.  PDB library isn't optimized for regex
1486061da546Spatrick   // searches or searches across multiple symbol types at the same time, so the
1487061da546Spatrick   // best we can do is to search enums, then typedefs, then classes one by one,
1488061da546Spatrick   // and do a regex comparison against each of them.
1489061da546Spatrick   PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef,
1490061da546Spatrick                                   PDB_SymType::UDT};
1491061da546Spatrick   std::unique_ptr<IPDBEnumSymbols> results;
1492061da546Spatrick 
1493061da546Spatrick   uint32_t matches = 0;
1494061da546Spatrick 
1495061da546Spatrick   for (auto tag : tags_to_search) {
1496061da546Spatrick     results = m_global_scope_up->findAllChildren(tag);
1497061da546Spatrick     if (!results)
1498061da546Spatrick       continue;
1499061da546Spatrick 
1500061da546Spatrick     while (auto result = results->getNext()) {
1501061da546Spatrick       if (max_matches > 0 && matches >= max_matches)
1502061da546Spatrick         break;
1503061da546Spatrick 
1504061da546Spatrick       std::string type_name;
1505061da546Spatrick       if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(result.get()))
1506061da546Spatrick         type_name = enum_type->getName();
1507061da546Spatrick       else if (auto typedef_type =
1508061da546Spatrick                    llvm::dyn_cast<PDBSymbolTypeTypedef>(result.get()))
1509061da546Spatrick         type_name = typedef_type->getName();
1510061da546Spatrick       else if (auto class_type = llvm::dyn_cast<PDBSymbolTypeUDT>(result.get()))
1511061da546Spatrick         type_name = class_type->getName();
1512061da546Spatrick       else {
1513061da546Spatrick         // We're looking only for types that have names.  Skip symbols, as well
1514061da546Spatrick         // as unnamed types such as arrays, pointers, etc.
1515061da546Spatrick         continue;
1516061da546Spatrick       }
1517061da546Spatrick 
1518061da546Spatrick       if (!regex.Execute(type_name))
1519061da546Spatrick         continue;
1520061da546Spatrick 
1521061da546Spatrick       // This should cause the type to get cached and stored in the `m_types`
1522061da546Spatrick       // lookup.
1523061da546Spatrick       if (!ResolveTypeUID(result->getSymIndexId()))
1524061da546Spatrick         continue;
1525061da546Spatrick 
1526061da546Spatrick       auto iter = m_types.find(result->getSymIndexId());
1527061da546Spatrick       if (iter == m_types.end())
1528061da546Spatrick         continue;
1529061da546Spatrick       types.Insert(iter->second);
1530061da546Spatrick       ++matches;
1531061da546Spatrick     }
1532061da546Spatrick   }
1533061da546Spatrick }
1534061da546Spatrick 
FindTypesByName(llvm::StringRef name,const lldb_private::CompilerDeclContext & parent_decl_ctx,uint32_t max_matches,lldb_private::TypeMap & types)1535061da546Spatrick void SymbolFilePDB::FindTypesByName(
1536061da546Spatrick     llvm::StringRef name,
1537dda28197Spatrick     const lldb_private::CompilerDeclContext &parent_decl_ctx,
1538061da546Spatrick     uint32_t max_matches, lldb_private::TypeMap &types) {
1539061da546Spatrick   std::unique_ptr<IPDBEnumSymbols> results;
1540061da546Spatrick   if (name.empty())
1541061da546Spatrick     return;
1542061da546Spatrick   results = m_global_scope_up->findAllChildren(PDB_SymType::None);
1543061da546Spatrick   if (!results)
1544061da546Spatrick     return;
1545061da546Spatrick 
1546061da546Spatrick   uint32_t matches = 0;
1547061da546Spatrick 
1548061da546Spatrick   while (auto result = results->getNext()) {
1549061da546Spatrick     if (max_matches > 0 && matches >= max_matches)
1550061da546Spatrick       break;
1551061da546Spatrick 
1552061da546Spatrick     if (MSVCUndecoratedNameParser::DropScope(
1553061da546Spatrick             result->getRawSymbol().getName()) != name)
1554061da546Spatrick       continue;
1555061da546Spatrick 
1556061da546Spatrick     switch (result->getSymTag()) {
1557061da546Spatrick     case PDB_SymType::Enum:
1558061da546Spatrick     case PDB_SymType::UDT:
1559061da546Spatrick     case PDB_SymType::Typedef:
1560061da546Spatrick       break;
1561061da546Spatrick     default:
1562061da546Spatrick       // We're looking only for types that have names.  Skip symbols, as well
1563061da546Spatrick       // as unnamed types such as arrays, pointers, etc.
1564061da546Spatrick       continue;
1565061da546Spatrick     }
1566061da546Spatrick 
1567061da546Spatrick     // This should cause the type to get cached and stored in the `m_types`
1568061da546Spatrick     // lookup.
1569061da546Spatrick     if (!ResolveTypeUID(result->getSymIndexId()))
1570061da546Spatrick       continue;
1571061da546Spatrick 
1572dda28197Spatrick     if (parent_decl_ctx.IsValid() &&
1573dda28197Spatrick         GetDeclContextContainingUID(result->getSymIndexId()) != parent_decl_ctx)
1574061da546Spatrick       continue;
1575061da546Spatrick 
1576061da546Spatrick     auto iter = m_types.find(result->getSymIndexId());
1577061da546Spatrick     if (iter == m_types.end())
1578061da546Spatrick       continue;
1579061da546Spatrick     types.Insert(iter->second);
1580061da546Spatrick     ++matches;
1581061da546Spatrick   }
1582061da546Spatrick }
1583061da546Spatrick 
FindTypes(llvm::ArrayRef<CompilerContext> pattern,LanguageSet languages,llvm::DenseSet<SymbolFile * > & searched_symbol_files,lldb_private::TypeMap & types)1584061da546Spatrick void SymbolFilePDB::FindTypes(
1585061da546Spatrick     llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
1586061da546Spatrick     llvm::DenseSet<SymbolFile *> &searched_symbol_files,
1587061da546Spatrick     lldb_private::TypeMap &types) {}
1588061da546Spatrick 
GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol & pdb_symbol,uint32_t type_mask,TypeCollection & type_collection)1589061da546Spatrick void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol,
1590061da546Spatrick                                          uint32_t type_mask,
1591061da546Spatrick                                          TypeCollection &type_collection) {
1592061da546Spatrick   bool can_parse = false;
1593061da546Spatrick   switch (pdb_symbol.getSymTag()) {
1594061da546Spatrick   case PDB_SymType::ArrayType:
1595061da546Spatrick     can_parse = ((type_mask & eTypeClassArray) != 0);
1596061da546Spatrick     break;
1597061da546Spatrick   case PDB_SymType::BuiltinType:
1598061da546Spatrick     can_parse = ((type_mask & eTypeClassBuiltin) != 0);
1599061da546Spatrick     break;
1600061da546Spatrick   case PDB_SymType::Enum:
1601061da546Spatrick     can_parse = ((type_mask & eTypeClassEnumeration) != 0);
1602061da546Spatrick     break;
1603061da546Spatrick   case PDB_SymType::Function:
1604061da546Spatrick   case PDB_SymType::FunctionSig:
1605061da546Spatrick     can_parse = ((type_mask & eTypeClassFunction) != 0);
1606061da546Spatrick     break;
1607061da546Spatrick   case PDB_SymType::PointerType:
1608061da546Spatrick     can_parse = ((type_mask & (eTypeClassPointer | eTypeClassBlockPointer |
1609061da546Spatrick                                eTypeClassMemberPointer)) != 0);
1610061da546Spatrick     break;
1611061da546Spatrick   case PDB_SymType::Typedef:
1612061da546Spatrick     can_parse = ((type_mask & eTypeClassTypedef) != 0);
1613061da546Spatrick     break;
1614061da546Spatrick   case PDB_SymType::UDT: {
1615061da546Spatrick     auto *udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&pdb_symbol);
1616061da546Spatrick     assert(udt);
1617061da546Spatrick     can_parse = (udt->getUdtKind() != PDB_UdtType::Interface &&
1618061da546Spatrick                  ((type_mask & (eTypeClassClass | eTypeClassStruct |
1619061da546Spatrick                                 eTypeClassUnion)) != 0));
1620061da546Spatrick   } break;
1621061da546Spatrick   default:
1622061da546Spatrick     break;
1623061da546Spatrick   }
1624061da546Spatrick 
1625061da546Spatrick   if (can_parse) {
1626061da546Spatrick     if (auto *type = ResolveTypeUID(pdb_symbol.getSymIndexId())) {
1627*f6aab3d8Srobert       if (!llvm::is_contained(type_collection, type))
1628061da546Spatrick         type_collection.push_back(type);
1629061da546Spatrick     }
1630061da546Spatrick   }
1631061da546Spatrick 
1632061da546Spatrick   auto results_up = pdb_symbol.findAllChildren();
1633061da546Spatrick   while (auto symbol_up = results_up->getNext())
1634061da546Spatrick     GetTypesForPDBSymbol(*symbol_up, type_mask, type_collection);
1635061da546Spatrick }
1636061da546Spatrick 
GetTypes(lldb_private::SymbolContextScope * sc_scope,TypeClass type_mask,lldb_private::TypeList & type_list)1637061da546Spatrick void SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
1638061da546Spatrick                              TypeClass type_mask,
1639061da546Spatrick                              lldb_private::TypeList &type_list) {
1640061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1641061da546Spatrick   TypeCollection type_collection;
1642061da546Spatrick   CompileUnit *cu =
1643061da546Spatrick       sc_scope ? sc_scope->CalculateSymbolContextCompileUnit() : nullptr;
1644061da546Spatrick   if (cu) {
1645061da546Spatrick     auto compiland_up = GetPDBCompilandByUID(cu->GetID());
1646061da546Spatrick     if (!compiland_up)
1647061da546Spatrick       return;
1648061da546Spatrick     GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection);
1649061da546Spatrick   } else {
1650061da546Spatrick     for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) {
1651061da546Spatrick       auto cu_sp = ParseCompileUnitAtIndex(cu_idx);
1652061da546Spatrick       if (cu_sp) {
1653061da546Spatrick         if (auto compiland_up = GetPDBCompilandByUID(cu_sp->GetID()))
1654061da546Spatrick           GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection);
1655061da546Spatrick       }
1656061da546Spatrick     }
1657061da546Spatrick   }
1658061da546Spatrick 
1659061da546Spatrick   for (auto type : type_collection) {
1660061da546Spatrick     type->GetForwardCompilerType();
1661061da546Spatrick     type_list.Insert(type->shared_from_this());
1662061da546Spatrick   }
1663061da546Spatrick }
1664061da546Spatrick 
1665*f6aab3d8Srobert llvm::Expected<lldb::TypeSystemSP>
GetTypeSystemForLanguage(lldb::LanguageType language)1666061da546Spatrick SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
1667061da546Spatrick   auto type_system_or_err =
1668061da546Spatrick       m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language);
1669061da546Spatrick   if (type_system_or_err) {
1670*f6aab3d8Srobert     if (auto ts = *type_system_or_err)
1671*f6aab3d8Srobert       ts->SetSymbolFile(this);
1672061da546Spatrick   }
1673061da546Spatrick   return type_system_or_err;
1674061da546Spatrick }
1675061da546Spatrick 
GetPDBAstParser()1676061da546Spatrick PDBASTParser *SymbolFilePDB::GetPDBAstParser() {
1677061da546Spatrick   auto type_system_or_err =
1678061da546Spatrick       GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
1679061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
1680*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
1681*f6aab3d8Srobert                    "Unable to get PDB AST parser");
1682061da546Spatrick     return nullptr;
1683061da546Spatrick   }
1684061da546Spatrick 
1685*f6aab3d8Srobert   auto ts = *type_system_or_err;
1686061da546Spatrick   auto *clang_type_system =
1687*f6aab3d8Srobert       llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
1688061da546Spatrick   if (!clang_type_system)
1689061da546Spatrick     return nullptr;
1690061da546Spatrick 
1691061da546Spatrick   return clang_type_system->GetPDBParser();
1692061da546Spatrick }
1693061da546Spatrick 
1694dda28197Spatrick lldb_private::CompilerDeclContext
FindNamespace(lldb_private::ConstString name,const CompilerDeclContext & parent_decl_ctx)1695dda28197Spatrick SymbolFilePDB::FindNamespace(lldb_private::ConstString name,
1696dda28197Spatrick                              const CompilerDeclContext &parent_decl_ctx) {
1697061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
1698061da546Spatrick   auto type_system_or_err =
1699061da546Spatrick       GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
1700061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
1701*f6aab3d8Srobert     LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),
1702*f6aab3d8Srobert                    "Unable to find namespace {}", name.AsCString());
1703061da546Spatrick     return CompilerDeclContext();
1704061da546Spatrick   }
1705*f6aab3d8Srobert   auto ts = *type_system_or_err;
1706061da546Spatrick   auto *clang_type_system =
1707*f6aab3d8Srobert       llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());
1708061da546Spatrick   if (!clang_type_system)
1709061da546Spatrick     return CompilerDeclContext();
1710061da546Spatrick 
1711061da546Spatrick   PDBASTParser *pdb = clang_type_system->GetPDBParser();
1712061da546Spatrick   if (!pdb)
1713061da546Spatrick     return CompilerDeclContext();
1714061da546Spatrick 
1715061da546Spatrick   clang::DeclContext *decl_context = nullptr;
1716061da546Spatrick   if (parent_decl_ctx)
1717061da546Spatrick     decl_context = static_cast<clang::DeclContext *>(
1718dda28197Spatrick         parent_decl_ctx.GetOpaqueDeclContext());
1719061da546Spatrick 
1720061da546Spatrick   auto namespace_decl =
1721061da546Spatrick       pdb->FindNamespaceDecl(decl_context, name.GetStringRef());
1722061da546Spatrick   if (!namespace_decl)
1723061da546Spatrick     return CompilerDeclContext();
1724061da546Spatrick 
1725061da546Spatrick   return clang_type_system->CreateDeclContext(namespace_decl);
1726061da546Spatrick }
1727061da546Spatrick 
GetPDBSession()1728061da546Spatrick IPDBSession &SymbolFilePDB::GetPDBSession() { return *m_session_up; }
1729061da546Spatrick 
GetPDBSession() const1730061da546Spatrick const IPDBSession &SymbolFilePDB::GetPDBSession() const {
1731061da546Spatrick   return *m_session_up;
1732061da546Spatrick }
1733061da546Spatrick 
ParseCompileUnitForUID(uint32_t id,uint32_t index)1734061da546Spatrick lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForUID(uint32_t id,
1735061da546Spatrick                                                        uint32_t index) {
1736061da546Spatrick   auto found_cu = m_comp_units.find(id);
1737061da546Spatrick   if (found_cu != m_comp_units.end())
1738061da546Spatrick     return found_cu->second;
1739061da546Spatrick 
1740061da546Spatrick   auto compiland_up = GetPDBCompilandByUID(id);
1741061da546Spatrick   if (!compiland_up)
1742061da546Spatrick     return CompUnitSP();
1743061da546Spatrick 
1744061da546Spatrick   lldb::LanguageType lang;
1745061da546Spatrick   auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>();
1746061da546Spatrick   if (!details)
1747061da546Spatrick     lang = lldb::eLanguageTypeC_plus_plus;
1748061da546Spatrick   else
1749061da546Spatrick     lang = TranslateLanguage(details->getLanguage());
1750061da546Spatrick 
1751061da546Spatrick   if (lang == lldb::LanguageType::eLanguageTypeUnknown)
1752061da546Spatrick     return CompUnitSP();
1753061da546Spatrick 
1754061da546Spatrick   std::string path = compiland_up->getSourceFileFullPath();
1755061da546Spatrick   if (path.empty())
1756061da546Spatrick     return CompUnitSP();
1757061da546Spatrick 
1758061da546Spatrick   // Don't support optimized code for now, DebugInfoPDB does not return this
1759061da546Spatrick   // information.
1760061da546Spatrick   LazyBool optimized = eLazyBoolNo;
1761061da546Spatrick   auto cu_sp = std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), nullptr,
1762061da546Spatrick                                              path.c_str(), id, lang, optimized);
1763061da546Spatrick 
1764061da546Spatrick   if (!cu_sp)
1765061da546Spatrick     return CompUnitSP();
1766061da546Spatrick 
1767061da546Spatrick   m_comp_units.insert(std::make_pair(id, cu_sp));
1768061da546Spatrick   if (index == UINT32_MAX)
1769061da546Spatrick     GetCompileUnitIndex(*compiland_up, index);
1770061da546Spatrick   lldbassert(index != UINT32_MAX);
1771061da546Spatrick   SetCompileUnitAtIndex(index, cu_sp);
1772061da546Spatrick   return cu_sp;
1773061da546Spatrick }
1774061da546Spatrick 
ParseCompileUnitLineTable(CompileUnit & comp_unit,uint32_t match_line)1775061da546Spatrick bool SymbolFilePDB::ParseCompileUnitLineTable(CompileUnit &comp_unit,
1776061da546Spatrick                                               uint32_t match_line) {
1777061da546Spatrick   auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID());
1778061da546Spatrick   if (!compiland_up)
1779061da546Spatrick     return false;
1780061da546Spatrick 
1781061da546Spatrick   // LineEntry needs the *index* of the file into the list of support files
1782061da546Spatrick   // returned by ParseCompileUnitSupportFiles.  But the underlying SDK gives us
1783061da546Spatrick   // a globally unique idenfitifier in the namespace of the PDB.  So, we have
1784061da546Spatrick   // to do a mapping so that we can hand out indices.
1785061da546Spatrick   llvm::DenseMap<uint32_t, uint32_t> index_map;
1786061da546Spatrick   BuildSupportFileIdToSupportFileIndexMap(*compiland_up, index_map);
1787061da546Spatrick   auto line_table = std::make_unique<LineTable>(&comp_unit);
1788061da546Spatrick 
1789061da546Spatrick   // Find contributions to `compiland` from all source and header files.
1790061da546Spatrick   auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
1791061da546Spatrick   if (!files)
1792061da546Spatrick     return false;
1793061da546Spatrick 
1794061da546Spatrick   // For each source and header file, create a LineSequence for contributions
1795061da546Spatrick   // to the compiland from that file, and add the sequence.
1796061da546Spatrick   while (auto file = files->getNext()) {
1797061da546Spatrick     std::unique_ptr<LineSequence> sequence(
1798061da546Spatrick         line_table->CreateLineSequenceContainer());
1799061da546Spatrick     auto lines = m_session_up->findLineNumbers(*compiland_up, *file);
1800061da546Spatrick     if (!lines)
1801061da546Spatrick       continue;
1802061da546Spatrick     int entry_count = lines->getChildCount();
1803061da546Spatrick 
1804061da546Spatrick     uint64_t prev_addr;
1805061da546Spatrick     uint32_t prev_length;
1806061da546Spatrick     uint32_t prev_line;
1807061da546Spatrick     uint32_t prev_source_idx;
1808061da546Spatrick 
1809061da546Spatrick     for (int i = 0; i < entry_count; ++i) {
1810061da546Spatrick       auto line = lines->getChildAtIndex(i);
1811061da546Spatrick 
1812061da546Spatrick       uint64_t lno = line->getLineNumber();
1813061da546Spatrick       uint64_t addr = line->getVirtualAddress();
1814061da546Spatrick       uint32_t length = line->getLength();
1815061da546Spatrick       uint32_t source_id = line->getSourceFileId();
1816061da546Spatrick       uint32_t col = line->getColumnNumber();
1817061da546Spatrick       uint32_t source_idx = index_map[source_id];
1818061da546Spatrick 
1819061da546Spatrick       // There was a gap between the current entry and the previous entry if
1820061da546Spatrick       // the addresses don't perfectly line up.
1821061da546Spatrick       bool is_gap = (i > 0) && (prev_addr + prev_length < addr);
1822061da546Spatrick 
1823061da546Spatrick       // Before inserting the current entry, insert a terminal entry at the end
1824061da546Spatrick       // of the previous entry's address range if the current entry resulted in
1825061da546Spatrick       // a gap from the previous entry.
1826061da546Spatrick       if (is_gap && ShouldAddLine(match_line, prev_line, prev_length)) {
1827061da546Spatrick         line_table->AppendLineEntryToSequence(
1828061da546Spatrick             sequence.get(), prev_addr + prev_length, prev_line, 0,
1829061da546Spatrick             prev_source_idx, false, false, false, false, true);
1830061da546Spatrick 
1831be691f3bSpatrick         line_table->InsertSequence(sequence.get());
1832dda28197Spatrick         sequence = line_table->CreateLineSequenceContainer();
1833061da546Spatrick       }
1834061da546Spatrick 
1835061da546Spatrick       if (ShouldAddLine(match_line, lno, length)) {
1836061da546Spatrick         bool is_statement = line->isStatement();
1837061da546Spatrick         bool is_prologue = false;
1838061da546Spatrick         bool is_epilogue = false;
1839061da546Spatrick         auto func =
1840061da546Spatrick             m_session_up->findSymbolByAddress(addr, PDB_SymType::Function);
1841061da546Spatrick         if (func) {
1842061da546Spatrick           auto prologue = func->findOneChild<PDBSymbolFuncDebugStart>();
1843061da546Spatrick           if (prologue)
1844061da546Spatrick             is_prologue = (addr == prologue->getVirtualAddress());
1845061da546Spatrick 
1846061da546Spatrick           auto epilogue = func->findOneChild<PDBSymbolFuncDebugEnd>();
1847061da546Spatrick           if (epilogue)
1848061da546Spatrick             is_epilogue = (addr == epilogue->getVirtualAddress());
1849061da546Spatrick         }
1850061da546Spatrick 
1851061da546Spatrick         line_table->AppendLineEntryToSequence(sequence.get(), addr, lno, col,
1852061da546Spatrick                                               source_idx, is_statement, false,
1853061da546Spatrick                                               is_prologue, is_epilogue, false);
1854061da546Spatrick       }
1855061da546Spatrick 
1856061da546Spatrick       prev_addr = addr;
1857061da546Spatrick       prev_length = length;
1858061da546Spatrick       prev_line = lno;
1859061da546Spatrick       prev_source_idx = source_idx;
1860061da546Spatrick     }
1861061da546Spatrick 
1862061da546Spatrick     if (entry_count > 0 && ShouldAddLine(match_line, prev_line, prev_length)) {
1863061da546Spatrick       // The end is always a terminal entry, so insert it regardless.
1864061da546Spatrick       line_table->AppendLineEntryToSequence(
1865061da546Spatrick           sequence.get(), prev_addr + prev_length, prev_line, 0,
1866061da546Spatrick           prev_source_idx, false, false, false, false, true);
1867061da546Spatrick     }
1868061da546Spatrick 
1869dda28197Spatrick     line_table->InsertSequence(sequence.get());
1870061da546Spatrick   }
1871061da546Spatrick 
1872061da546Spatrick   if (line_table->GetSize()) {
1873061da546Spatrick     comp_unit.SetLineTable(line_table.release());
1874061da546Spatrick     return true;
1875061da546Spatrick   }
1876061da546Spatrick   return false;
1877061da546Spatrick }
1878061da546Spatrick 
BuildSupportFileIdToSupportFileIndexMap(const PDBSymbolCompiland & compiland,llvm::DenseMap<uint32_t,uint32_t> & index_map) const1879061da546Spatrick void SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(
1880061da546Spatrick     const PDBSymbolCompiland &compiland,
1881061da546Spatrick     llvm::DenseMap<uint32_t, uint32_t> &index_map) const {
1882061da546Spatrick   // This is a hack, but we need to convert the source id into an index into
1883061da546Spatrick   // the support files array.  We don't want to do path comparisons to avoid
1884061da546Spatrick   // basename / full path issues that may or may not even be a problem, so we
1885061da546Spatrick   // use the globally unique source file identifiers.  Ideally we could use the
1886061da546Spatrick   // global identifiers everywhere, but LineEntry currently assumes indices.
1887061da546Spatrick   auto source_files = m_session_up->getSourceFilesForCompiland(compiland);
1888061da546Spatrick   if (!source_files)
1889061da546Spatrick     return;
1890061da546Spatrick 
1891061da546Spatrick   int index = 0;
1892061da546Spatrick   while (auto file = source_files->getNext()) {
1893061da546Spatrick     uint32_t source_id = file->getUniqueId();
1894061da546Spatrick     index_map[source_id] = index++;
1895061da546Spatrick   }
1896061da546Spatrick }
1897061da546Spatrick 
GetCompileUnitContainsAddress(const lldb_private::Address & so_addr)1898061da546Spatrick lldb::CompUnitSP SymbolFilePDB::GetCompileUnitContainsAddress(
1899061da546Spatrick     const lldb_private::Address &so_addr) {
1900061da546Spatrick   lldb::addr_t file_vm_addr = so_addr.GetFileAddress();
1901061da546Spatrick   if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
1902061da546Spatrick     return nullptr;
1903061da546Spatrick 
1904061da546Spatrick   // If it is a PDB function's vm addr, this is the first sure bet.
1905061da546Spatrick   if (auto lines =
1906061da546Spatrick           m_session_up->findLineNumbersByAddress(file_vm_addr, /*Length=*/1)) {
1907061da546Spatrick     if (auto first_line = lines->getNext())
1908061da546Spatrick       return ParseCompileUnitForUID(first_line->getCompilandId());
1909061da546Spatrick   }
1910061da546Spatrick 
1911061da546Spatrick   // Otherwise we resort to section contributions.
1912061da546Spatrick   if (auto sec_contribs = m_session_up->getSectionContribs()) {
1913061da546Spatrick     while (auto section = sec_contribs->getNext()) {
1914061da546Spatrick       auto va = section->getVirtualAddress();
1915061da546Spatrick       if (file_vm_addr >= va && file_vm_addr < va + section->getLength())
1916061da546Spatrick         return ParseCompileUnitForUID(section->getCompilandId());
1917061da546Spatrick     }
1918061da546Spatrick   }
1919061da546Spatrick   return nullptr;
1920061da546Spatrick }
1921061da546Spatrick 
1922061da546Spatrick Mangled
GetMangledForPDBFunc(const llvm::pdb::PDBSymbolFunc & pdb_func)1923061da546Spatrick SymbolFilePDB::GetMangledForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func) {
1924061da546Spatrick   Mangled mangled;
1925061da546Spatrick   auto func_name = pdb_func.getName();
1926061da546Spatrick   auto func_undecorated_name = pdb_func.getUndecoratedName();
1927061da546Spatrick   std::string func_decorated_name;
1928061da546Spatrick 
1929061da546Spatrick   // Seek from public symbols for non-static function's decorated name if any.
1930061da546Spatrick   // For static functions, they don't have undecorated names and aren't exposed
1931061da546Spatrick   // in Public Symbols either.
1932061da546Spatrick   if (!func_undecorated_name.empty()) {
1933061da546Spatrick     auto result_up = m_global_scope_up->findChildren(
1934061da546Spatrick         PDB_SymType::PublicSymbol, func_undecorated_name,
1935061da546Spatrick         PDB_NameSearchFlags::NS_UndecoratedName);
1936061da546Spatrick     if (result_up) {
1937061da546Spatrick       while (auto symbol_up = result_up->getNext()) {
1938061da546Spatrick         // For a public symbol, it is unique.
1939061da546Spatrick         lldbassert(result_up->getChildCount() == 1);
1940061da546Spatrick         if (auto *pdb_public_sym =
1941061da546Spatrick                 llvm::dyn_cast_or_null<PDBSymbolPublicSymbol>(
1942061da546Spatrick                     symbol_up.get())) {
1943061da546Spatrick           if (pdb_public_sym->isFunction()) {
1944061da546Spatrick             func_decorated_name = pdb_public_sym->getName();
1945061da546Spatrick             break;
1946061da546Spatrick           }
1947061da546Spatrick         }
1948061da546Spatrick       }
1949061da546Spatrick     }
1950061da546Spatrick   }
1951061da546Spatrick   if (!func_decorated_name.empty()) {
1952061da546Spatrick     mangled.SetMangledName(ConstString(func_decorated_name));
1953061da546Spatrick 
1954*f6aab3d8Srobert     // For MSVC, format of C function's decorated name depends on calling
1955dda28197Spatrick     // convention. Unfortunately none of the format is recognized by current
1956061da546Spatrick     // LLDB. For example, `_purecall` is a __cdecl C function. From PDB,
1957061da546Spatrick     // `__purecall` is retrieved as both its decorated and undecorated name
1958061da546Spatrick     // (using PDBSymbolFunc::getUndecoratedName method). However `__purecall`
1959061da546Spatrick     // string is not treated as mangled in LLDB (neither `?` nor `_Z` prefix).
1960061da546Spatrick     // Mangled::GetDemangledName method will fail internally and caches an
1961dda28197Spatrick     // empty string as its undecorated name. So we will face a contradiction
1962061da546Spatrick     // here for the same symbol:
1963061da546Spatrick     //   non-empty undecorated name from PDB
1964061da546Spatrick     //   empty undecorated name from LLDB
1965dda28197Spatrick     if (!func_undecorated_name.empty() && mangled.GetDemangledName().IsEmpty())
1966061da546Spatrick       mangled.SetDemangledName(ConstString(func_undecorated_name));
1967061da546Spatrick 
1968061da546Spatrick     // LLDB uses several flags to control how a C++ decorated name is
1969061da546Spatrick     // undecorated for MSVC. See `safeUndecorateName` in Class Mangled. So the
1970061da546Spatrick     // yielded name could be different from what we retrieve from
1971061da546Spatrick     // PDB source unless we also apply same flags in getting undecorated
1972061da546Spatrick     // name through PDBSymbolFunc::getUndecoratedNameEx method.
1973061da546Spatrick     if (!func_undecorated_name.empty() &&
1974dda28197Spatrick         mangled.GetDemangledName() != ConstString(func_undecorated_name))
1975061da546Spatrick       mangled.SetDemangledName(ConstString(func_undecorated_name));
1976061da546Spatrick   } else if (!func_undecorated_name.empty()) {
1977061da546Spatrick     mangled.SetDemangledName(ConstString(func_undecorated_name));
1978061da546Spatrick   } else if (!func_name.empty())
1979061da546Spatrick     mangled.SetValue(ConstString(func_name), false);
1980061da546Spatrick 
1981061da546Spatrick   return mangled;
1982061da546Spatrick }
1983061da546Spatrick 
DeclContextMatchesThisSymbolFile(const lldb_private::CompilerDeclContext & decl_ctx)1984061da546Spatrick bool SymbolFilePDB::DeclContextMatchesThisSymbolFile(
1985dda28197Spatrick     const lldb_private::CompilerDeclContext &decl_ctx) {
1986dda28197Spatrick   if (!decl_ctx.IsValid())
1987061da546Spatrick     return true;
1988061da546Spatrick 
1989dda28197Spatrick   TypeSystem *decl_ctx_type_system = decl_ctx.GetTypeSystem();
1990061da546Spatrick   if (!decl_ctx_type_system)
1991061da546Spatrick     return false;
1992061da546Spatrick   auto type_system_or_err = GetTypeSystemForLanguage(
1993061da546Spatrick       decl_ctx_type_system->GetMinimumLanguage(nullptr));
1994061da546Spatrick   if (auto err = type_system_or_err.takeError()) {
1995061da546Spatrick     LLDB_LOG_ERROR(
1996*f6aab3d8Srobert         GetLog(LLDBLog::Symbols), std::move(err),
1997061da546Spatrick         "Unable to determine if DeclContext matches this symbol file");
1998061da546Spatrick     return false;
1999061da546Spatrick   }
2000061da546Spatrick 
2001*f6aab3d8Srobert   if (decl_ctx_type_system == type_system_or_err->get())
2002061da546Spatrick     return true; // The type systems match, return true
2003061da546Spatrick 
2004061da546Spatrick   return false;
2005061da546Spatrick }
2006061da546Spatrick 
GetCompilandId(const llvm::pdb::PDBSymbolData & data)2007061da546Spatrick uint32_t SymbolFilePDB::GetCompilandId(const llvm::pdb::PDBSymbolData &data) {
2008061da546Spatrick   static const auto pred_upper = [](uint32_t lhs, SecContribInfo rhs) {
2009061da546Spatrick     return lhs < rhs.Offset;
2010061da546Spatrick   };
2011061da546Spatrick 
2012061da546Spatrick   // Cache section contributions
2013061da546Spatrick   if (m_sec_contribs.empty()) {
2014061da546Spatrick     if (auto SecContribs = m_session_up->getSectionContribs()) {
2015061da546Spatrick       while (auto SectionContrib = SecContribs->getNext()) {
2016061da546Spatrick         auto comp_id = SectionContrib->getCompilandId();
2017061da546Spatrick         if (!comp_id)
2018061da546Spatrick           continue;
2019061da546Spatrick 
2020061da546Spatrick         auto sec = SectionContrib->getAddressSection();
2021061da546Spatrick         auto &sec_cs = m_sec_contribs[sec];
2022061da546Spatrick 
2023061da546Spatrick         auto offset = SectionContrib->getAddressOffset();
2024*f6aab3d8Srobert         auto it = llvm::upper_bound(sec_cs, offset, pred_upper);
2025061da546Spatrick 
2026061da546Spatrick         auto size = SectionContrib->getLength();
2027061da546Spatrick         sec_cs.insert(it, {offset, size, comp_id});
2028061da546Spatrick       }
2029061da546Spatrick     }
2030061da546Spatrick   }
2031061da546Spatrick 
2032061da546Spatrick   // Check by line number
2033061da546Spatrick   if (auto Lines = data.getLineNumbers()) {
2034061da546Spatrick     if (auto FirstLine = Lines->getNext())
2035061da546Spatrick       return FirstLine->getCompilandId();
2036061da546Spatrick   }
2037061da546Spatrick 
2038061da546Spatrick   // Retrieve section + offset
2039061da546Spatrick   uint32_t DataSection = data.getAddressSection();
2040061da546Spatrick   uint32_t DataOffset = data.getAddressOffset();
2041061da546Spatrick   if (DataSection == 0) {
2042061da546Spatrick     if (auto RVA = data.getRelativeVirtualAddress())
2043061da546Spatrick       m_session_up->addressForRVA(RVA, DataSection, DataOffset);
2044061da546Spatrick   }
2045061da546Spatrick 
2046061da546Spatrick   if (DataSection) {
2047061da546Spatrick     // Search by section contributions
2048061da546Spatrick     auto &sec_cs = m_sec_contribs[DataSection];
2049*f6aab3d8Srobert     auto it = llvm::upper_bound(sec_cs, DataOffset, pred_upper);
2050061da546Spatrick     if (it != sec_cs.begin()) {
2051061da546Spatrick       --it;
2052061da546Spatrick       if (DataOffset < it->Offset + it->Size)
2053061da546Spatrick         return it->CompilandId;
2054061da546Spatrick     }
2055061da546Spatrick   } else {
2056061da546Spatrick     // Search in lexical tree
2057061da546Spatrick     auto LexParentId = data.getLexicalParentId();
2058061da546Spatrick     while (auto LexParent = m_session_up->getSymbolById(LexParentId)) {
2059061da546Spatrick       if (LexParent->getSymTag() == PDB_SymType::Exe)
2060061da546Spatrick         break;
2061061da546Spatrick       if (LexParent->getSymTag() == PDB_SymType::Compiland)
2062061da546Spatrick         return LexParentId;
2063061da546Spatrick       LexParentId = LexParent->getRawSymbol().getLexicalParentId();
2064061da546Spatrick     }
2065061da546Spatrick   }
2066061da546Spatrick 
2067061da546Spatrick   return 0;
2068061da546Spatrick }
2069