174e08ca0SZachary Turner //===-- SymbolFilePDB.cpp ---------------------------------------*- C++ -*-===//
274e08ca0SZachary Turner //
374e08ca0SZachary Turner //                     The LLVM Compiler Infrastructure
474e08ca0SZachary Turner //
574e08ca0SZachary Turner // This file is distributed under the University of Illinois Open Source
674e08ca0SZachary Turner // License. See LICENSE.TXT for details.
774e08ca0SZachary Turner //
874e08ca0SZachary Turner //===----------------------------------------------------------------------===//
974e08ca0SZachary Turner 
1074e08ca0SZachary Turner #include "SymbolFilePDB.h"
1174e08ca0SZachary Turner 
1242dff790SZachary Turner #include "clang/Lex/Lexer.h"
1342dff790SZachary Turner 
1474e08ca0SZachary Turner #include "lldb/Core/Module.h"
1574e08ca0SZachary Turner #include "lldb/Core/PluginManager.h"
1642dff790SZachary Turner #include "lldb/Symbol/ClangASTContext.h"
1774e08ca0SZachary Turner #include "lldb/Symbol/CompileUnit.h"
1874e08ca0SZachary Turner #include "lldb/Symbol/LineTable.h"
1974e08ca0SZachary Turner #include "lldb/Symbol/ObjectFile.h"
2074e08ca0SZachary Turner #include "lldb/Symbol/SymbolContext.h"
2110a02577SAaron Smith #include "lldb/Symbol/SymbolVendor.h"
22ec40f818SAaron Smith #include "lldb/Symbol/TypeList.h"
23308e39caSAaron Smith #include "lldb/Symbol/TypeMap.h"
2486e9434dSAaron Smith #include "lldb/Utility/RegularExpression.h"
2574e08ca0SZachary Turner 
26b8d8c62bSPavel Labath #include "llvm/DebugInfo/PDB/GenericError.h"
271f8552abSAaron Smith #include "llvm/DebugInfo/PDB/IPDBDataStream.h"
2874e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
2974e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
30308e39caSAaron Smith #include "llvm/DebugInfo/PDB/IPDBSectionContrib.h"
3174e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
321f8552abSAaron Smith #include "llvm/DebugInfo/PDB/IPDBTable.h"
3374e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbol.h"
347ac1c780SAaron Smith #include "llvm/DebugInfo/PDB/PDBSymbolBlock.h"
3574e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
3674e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
371f8552abSAaron Smith #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
3874e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
3974e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
4074e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
4174e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
427ac1c780SAaron Smith #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
4342dff790SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
4442dff790SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
4542dff790SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
4642dff790SZachary Turner 
477ac1c780SAaron Smith #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
4842dff790SZachary Turner #include "Plugins/SymbolFile/PDB/PDBASTParser.h"
4942dff790SZachary Turner 
5042dff790SZachary Turner #include <regex>
5174e08ca0SZachary Turner 
5210a02577SAaron Smith using namespace lldb;
5374e08ca0SZachary Turner using namespace lldb_private;
5454fd7ff6SZachary Turner using namespace llvm::pdb;
5574e08ca0SZachary Turner 
56b9c1b51eSKate Stone namespace {
57b9c1b51eSKate Stone lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
58b9c1b51eSKate Stone   switch (lang) {
5954fd7ff6SZachary Turner   case PDB_Lang::Cpp:
6074e08ca0SZachary Turner     return lldb::LanguageType::eLanguageTypeC_plus_plus;
6154fd7ff6SZachary Turner   case PDB_Lang::C:
6274e08ca0SZachary Turner     return lldb::LanguageType::eLanguageTypeC;
6374e08ca0SZachary Turner   default:
6474e08ca0SZachary Turner     return lldb::LanguageType::eLanguageTypeUnknown;
6574e08ca0SZachary Turner   }
6674e08ca0SZachary Turner }
677e8c7beaSZachary Turner 
68b9c1b51eSKate Stone bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line,
69b9c1b51eSKate Stone                    uint32_t addr_length) {
70b9c1b51eSKate Stone   return ((requested_line == 0 || actual_line == requested_line) &&
71b9c1b51eSKate Stone           addr_length > 0);
727e8c7beaSZachary Turner }
73c8316ed2SAaron Smith } // namespace
7474e08ca0SZachary Turner 
75b9c1b51eSKate Stone void SymbolFilePDB::Initialize() {
76b9c1b51eSKate Stone   PluginManager::RegisterPlugin(GetPluginNameStatic(),
77b9c1b51eSKate Stone                                 GetPluginDescriptionStatic(), CreateInstance,
7874e08ca0SZachary Turner                                 DebuggerInitialize);
7974e08ca0SZachary Turner }
8074e08ca0SZachary Turner 
81b9c1b51eSKate Stone void SymbolFilePDB::Terminate() {
8274e08ca0SZachary Turner   PluginManager::UnregisterPlugin(CreateInstance);
8374e08ca0SZachary Turner }
8474e08ca0SZachary Turner 
85b9c1b51eSKate Stone void SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger) {}
8674e08ca0SZachary Turner 
87b9c1b51eSKate Stone lldb_private::ConstString SymbolFilePDB::GetPluginNameStatic() {
8874e08ca0SZachary Turner   static ConstString g_name("pdb");
8974e08ca0SZachary Turner   return g_name;
9074e08ca0SZachary Turner }
9174e08ca0SZachary Turner 
92b9c1b51eSKate Stone const char *SymbolFilePDB::GetPluginDescriptionStatic() {
9374e08ca0SZachary Turner   return "Microsoft PDB debug symbol file reader.";
9474e08ca0SZachary Turner }
9574e08ca0SZachary Turner 
9674e08ca0SZachary Turner lldb_private::SymbolFile *
97b9c1b51eSKate Stone SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file) {
9874e08ca0SZachary Turner   return new SymbolFilePDB(obj_file);
9974e08ca0SZachary Turner }
10074e08ca0SZachary Turner 
10174e08ca0SZachary Turner SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file)
10210a02577SAaron Smith     : SymbolFile(object_file), m_session_up(), m_global_scope_up(),
10310a02577SAaron Smith       m_cached_compile_unit_count(0), m_tu_decl_ctx_up() {}
10474e08ca0SZachary Turner 
105b9c1b51eSKate Stone SymbolFilePDB::~SymbolFilePDB() {}
10674e08ca0SZachary Turner 
107b9c1b51eSKate Stone uint32_t SymbolFilePDB::CalculateAbilities() {
1081f8552abSAaron Smith   uint32_t abilities = 0;
1091f8552abSAaron Smith   if (!m_obj_file)
1101f8552abSAaron Smith     return 0;
1111f8552abSAaron Smith 
112b9c1b51eSKate Stone   if (!m_session_up) {
11374e08ca0SZachary Turner     // Lazily load and match the PDB file, but only do this once.
11474e08ca0SZachary Turner     std::string exePath = m_obj_file->GetFileSpec().GetPath();
115b9c1b51eSKate Stone     auto error = loadDataForEXE(PDB_ReaderType::DIA, llvm::StringRef(exePath),
116b9c1b51eSKate Stone                                 m_session_up);
117b9c1b51eSKate Stone     if (error) {
1184fd6a960SZachary Turner       llvm::consumeError(std::move(error));
1191f8552abSAaron Smith       auto module_sp = m_obj_file->GetModule();
1201f8552abSAaron Smith       if (!module_sp)
1211f8552abSAaron Smith         return 0;
1221f8552abSAaron Smith       // See if any symbol file is specified through `--symfile` option.
1231f8552abSAaron Smith       FileSpec symfile = module_sp->GetSymbolFileFileSpec();
1241f8552abSAaron Smith       if (!symfile)
1251f8552abSAaron Smith         return 0;
1261f8552abSAaron Smith       error = loadDataForPDB(PDB_ReaderType::DIA,
127c8316ed2SAaron Smith                              llvm::StringRef(symfile.GetPath()), m_session_up);
1281f8552abSAaron Smith       if (error) {
1291f8552abSAaron Smith         llvm::consumeError(std::move(error));
13074e08ca0SZachary Turner         return 0;
13174e08ca0SZachary Turner       }
132b8d8c62bSPavel Labath     }
1331f8552abSAaron Smith   }
134d5a925f4SAaron Smith   if (!m_session_up)
1351f8552abSAaron Smith     return 0;
1361f8552abSAaron Smith 
1371f8552abSAaron Smith   auto enum_tables_up = m_session_up->getEnumTables();
1381f8552abSAaron Smith   if (!enum_tables_up)
1391f8552abSAaron Smith     return 0;
1401f8552abSAaron Smith   while (auto table_up = enum_tables_up->getNext()) {
1411f8552abSAaron Smith     if (table_up->getItemCount() == 0)
1421f8552abSAaron Smith       continue;
1431f8552abSAaron Smith     auto type = table_up->getTableType();
1441f8552abSAaron Smith     switch (type) {
1451f8552abSAaron Smith     case PDB_TableType::Symbols:
1461f8552abSAaron Smith       // This table represents a store of symbols with types listed in
1471f8552abSAaron Smith       // PDBSym_Type
148c8316ed2SAaron Smith       abilities |= (CompileUnits | Functions | Blocks | GlobalVariables |
149c8316ed2SAaron Smith                     LocalVariables | VariableTypes);
1501f8552abSAaron Smith       break;
1511f8552abSAaron Smith     case PDB_TableType::LineNumbers:
1521f8552abSAaron Smith       abilities |= LineTables;
1531f8552abSAaron Smith       break;
154c8316ed2SAaron Smith     default:
155c8316ed2SAaron Smith       break;
1561f8552abSAaron Smith     }
1571f8552abSAaron Smith   }
1581f8552abSAaron Smith   return abilities;
15974e08ca0SZachary Turner }
16074e08ca0SZachary Turner 
161b9c1b51eSKate Stone void SymbolFilePDB::InitializeObject() {
16274e08ca0SZachary Turner   lldb::addr_t obj_load_address = m_obj_file->GetFileOffset();
163c8316ed2SAaron Smith   lldbassert(obj_load_address && obj_load_address != LLDB_INVALID_ADDRESS);
16474e08ca0SZachary Turner   m_session_up->setLoadAddress(obj_load_address);
16510a02577SAaron Smith   if (!m_global_scope_up)
16610a02577SAaron Smith     m_global_scope_up = m_session_up->getGlobalScope();
16710a02577SAaron Smith   lldbassert(m_global_scope_up.get());
16842dff790SZachary Turner 
169b9c1b51eSKate Stone   TypeSystem *type_system =
170b9c1b51eSKate Stone       GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
171b9c1b51eSKate Stone   ClangASTContext *clang_type_system =
172b9c1b51eSKate Stone       llvm::dyn_cast_or_null<ClangASTContext>(type_system);
17310a02577SAaron Smith   lldbassert(clang_type_system);
174b9c1b51eSKate Stone   m_tu_decl_ctx_up = llvm::make_unique<CompilerDeclContext>(
175b9c1b51eSKate Stone       type_system, clang_type_system->GetTranslationUnitDecl());
17674e08ca0SZachary Turner }
17774e08ca0SZachary Turner 
178b9c1b51eSKate Stone uint32_t SymbolFilePDB::GetNumCompileUnits() {
179b9c1b51eSKate Stone   if (m_cached_compile_unit_count == 0) {
18010a02577SAaron Smith     auto compilands = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
18110a02577SAaron Smith     if (!compilands)
18210a02577SAaron Smith       return 0;
18310a02577SAaron Smith 
18410a02577SAaron Smith     // The linker could link *.dll (compiland language = LINK), or import
18505097246SAdrian Prantl     // *.dll. For example, a compiland with name `Import:KERNEL32.dll` could be
18605097246SAdrian Prantl     // found as a child of the global scope (PDB executable). Usually, such
18705097246SAdrian Prantl     // compilands contain `thunk` symbols in which we are not interested for
18805097246SAdrian Prantl     // now. However we still count them in the compiland list. If we perform
18905097246SAdrian Prantl     // any compiland related activity, like finding symbols through
19005097246SAdrian Prantl     // llvm::pdb::IPDBSession methods, such compilands will all be searched
19105097246SAdrian Prantl     // automatically no matter whether we include them or not.
19274e08ca0SZachary Turner     m_cached_compile_unit_count = compilands->getChildCount();
19374e08ca0SZachary Turner 
194b9c1b51eSKate Stone     // The linker can inject an additional "dummy" compilation unit into the
1959d0eb996SAdrian McCarthy     // PDB. Ignore this special compile unit for our purposes, if it is there.
1969d0eb996SAdrian McCarthy     // It is always the last one.
19710a02577SAaron Smith     auto last_compiland_up =
19810a02577SAaron Smith         compilands->getChildAtIndex(m_cached_compile_unit_count - 1);
19910a02577SAaron Smith     lldbassert(last_compiland_up.get());
20010a02577SAaron Smith     std::string name = last_compiland_up->getName();
20174e08ca0SZachary Turner     if (name == "* Linker *")
20274e08ca0SZachary Turner       --m_cached_compile_unit_count;
20374e08ca0SZachary Turner   }
20474e08ca0SZachary Turner   return m_cached_compile_unit_count;
20574e08ca0SZachary Turner }
20674e08ca0SZachary Turner 
20710a02577SAaron Smith void SymbolFilePDB::GetCompileUnitIndex(
208c8316ed2SAaron Smith     const llvm::pdb::PDBSymbolCompiland &pdb_compiland, uint32_t &index) {
20910a02577SAaron Smith   auto results_up = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
21010a02577SAaron Smith   if (!results_up)
21110a02577SAaron Smith     return;
212e664b5dcSAaron Smith   auto uid = pdb_compiland.getSymIndexId();
213fbdf0b93SRaphael Isemann   for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) {
21410a02577SAaron Smith     auto compiland_up = results_up->getChildAtIndex(cu_idx);
21510a02577SAaron Smith     if (!compiland_up)
21610a02577SAaron Smith       continue;
21710a02577SAaron Smith     if (compiland_up->getSymIndexId() == uid) {
21810a02577SAaron Smith       index = cu_idx;
21910a02577SAaron Smith       return;
22010a02577SAaron Smith     }
22110a02577SAaron Smith   }
22210a02577SAaron Smith   index = UINT32_MAX;
22310a02577SAaron Smith   return;
22410a02577SAaron Smith }
22510a02577SAaron Smith 
22610a02577SAaron Smith std::unique_ptr<llvm::pdb::PDBSymbolCompiland>
22710a02577SAaron Smith SymbolFilePDB::GetPDBCompilandByUID(uint32_t uid) {
22810a02577SAaron Smith   return m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(uid);
22910a02577SAaron Smith }
23010a02577SAaron Smith 
231b9c1b51eSKate Stone lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) {
23210a02577SAaron Smith   if (index >= GetNumCompileUnits())
23310a02577SAaron Smith     return CompUnitSP();
23474e08ca0SZachary Turner 
23510a02577SAaron Smith   // Assuming we always retrieve same compilands listed in same order through
23610a02577SAaron Smith   // `PDBSymbolExe::findAllChildren` method, otherwise using `index` to get a
23710a02577SAaron Smith   // compile unit makes no sense.
23810a02577SAaron Smith   auto results = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
23910a02577SAaron Smith   if (!results)
24010a02577SAaron Smith     return CompUnitSP();
24110a02577SAaron Smith   auto compiland_up = results->getChildAtIndex(index);
24210a02577SAaron Smith   if (!compiland_up)
24310a02577SAaron Smith     return CompUnitSP();
24410a02577SAaron Smith   return ParseCompileUnitForUID(compiland_up->getSymIndexId(), index);
24574e08ca0SZachary Turner }
24674e08ca0SZachary Turner 
24774e08ca0SZachary Turner lldb::LanguageType
248b9c1b51eSKate Stone SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) {
24974e08ca0SZachary Turner   // What fields should I expect to be filled out on the SymbolContext?  Is it
25074e08ca0SZachary Turner   // safe to assume that `sc.comp_unit` is valid?
25174e08ca0SZachary Turner   if (!sc.comp_unit)
25274e08ca0SZachary Turner     return lldb::eLanguageTypeUnknown;
25374e08ca0SZachary Turner 
25410a02577SAaron Smith   auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
25510a02577SAaron Smith   if (!compiland_up)
25674e08ca0SZachary Turner     return lldb::eLanguageTypeUnknown;
25710a02577SAaron Smith   auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>();
25874e08ca0SZachary Turner   if (!details)
25974e08ca0SZachary Turner     return lldb::eLanguageTypeUnknown;
26074e08ca0SZachary Turner   return TranslateLanguage(details->getLanguage());
26174e08ca0SZachary Turner }
26274e08ca0SZachary Turner 
263c8316ed2SAaron Smith lldb_private::Function *SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(
264c8316ed2SAaron Smith     const PDBSymbolFunc &pdb_func, const lldb_private::SymbolContext &sc) {
2657ac1c780SAaron Smith   lldbassert(sc.comp_unit && sc.module_sp.get());
2667ac1c780SAaron Smith 
267e664b5dcSAaron Smith   auto file_vm_addr = pdb_func.getVirtualAddress();
268308e39caSAaron Smith   if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
2697ac1c780SAaron Smith     return nullptr;
2707ac1c780SAaron Smith 
271e664b5dcSAaron Smith   auto func_length = pdb_func.getLength();
272c8316ed2SAaron Smith   AddressRange func_range =
273c8316ed2SAaron Smith       AddressRange(file_vm_addr, func_length, sc.module_sp->GetSectionList());
2747ac1c780SAaron Smith   if (!func_range.GetBaseAddress().IsValid())
2757ac1c780SAaron Smith     return nullptr;
2767ac1c780SAaron Smith 
277e664b5dcSAaron Smith   lldb_private::Type *func_type = ResolveTypeUID(pdb_func.getSymIndexId());
2787ac1c780SAaron Smith   if (!func_type)
2797ac1c780SAaron Smith     return nullptr;
2807ac1c780SAaron Smith 
281e664b5dcSAaron Smith   user_id_t func_type_uid = pdb_func.getSignatureId();
282f76fe682SAaron Smith 
2837ac1c780SAaron Smith   Mangled mangled = GetMangledForPDBFunc(pdb_func);
2847ac1c780SAaron Smith 
285c8316ed2SAaron Smith   FunctionSP func_sp =
286c8316ed2SAaron Smith       std::make_shared<Function>(sc.comp_unit, pdb_func.getSymIndexId(),
287c8316ed2SAaron Smith                                  func_type_uid, mangled, func_type, func_range);
2887ac1c780SAaron Smith 
2897ac1c780SAaron Smith   sc.comp_unit->AddFunction(func_sp);
2907ac1c780SAaron Smith   return func_sp.get();
2917ac1c780SAaron Smith }
2927ac1c780SAaron Smith 
293b9c1b51eSKate Stone size_t SymbolFilePDB::ParseCompileUnitFunctions(
294b9c1b51eSKate Stone     const lldb_private::SymbolContext &sc) {
2957ac1c780SAaron Smith   lldbassert(sc.comp_unit);
2967ac1c780SAaron Smith   size_t func_added = 0;
2977ac1c780SAaron Smith   auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
2987ac1c780SAaron Smith   if (!compiland_up)
2997ac1c780SAaron Smith     return 0;
3007ac1c780SAaron Smith   auto results_up = compiland_up->findAllChildren<PDBSymbolFunc>();
3017ac1c780SAaron Smith   if (!results_up)
3027ac1c780SAaron Smith     return 0;
3037ac1c780SAaron Smith   while (auto pdb_func_up = results_up->getNext()) {
3047ac1c780SAaron Smith     auto func_sp =
3057ac1c780SAaron Smith         sc.comp_unit->FindFunctionByUID(pdb_func_up->getSymIndexId());
3067ac1c780SAaron Smith     if (!func_sp) {
307e664b5dcSAaron Smith       if (ParseCompileUnitFunctionForPDBFunc(*pdb_func_up, sc))
3087ac1c780SAaron Smith         ++func_added;
3097ac1c780SAaron Smith     }
3107ac1c780SAaron Smith   }
3117ac1c780SAaron Smith   return func_added;
31274e08ca0SZachary Turner }
31374e08ca0SZachary Turner 
314b9c1b51eSKate Stone bool SymbolFilePDB::ParseCompileUnitLineTable(
315b9c1b51eSKate Stone     const lldb_private::SymbolContext &sc) {
31610a02577SAaron Smith   lldbassert(sc.comp_unit);
31710a02577SAaron Smith   if (sc.comp_unit->GetLineTable())
31810a02577SAaron Smith     return true;
31974e08ca0SZachary Turner   return ParseCompileUnitLineTable(sc, 0);
32074e08ca0SZachary Turner }
32174e08ca0SZachary Turner 
322b9c1b51eSKate Stone bool SymbolFilePDB::ParseCompileUnitDebugMacros(
323b9c1b51eSKate Stone     const lldb_private::SymbolContext &sc) {
32474e08ca0SZachary Turner   // PDB doesn't contain information about macros
32574e08ca0SZachary Turner   return false;
32674e08ca0SZachary Turner }
32774e08ca0SZachary Turner 
328b9c1b51eSKate Stone bool SymbolFilePDB::ParseCompileUnitSupportFiles(
329b9c1b51eSKate Stone     const lldb_private::SymbolContext &sc,
330b9c1b51eSKate Stone     lldb_private::FileSpecList &support_files) {
33110a02577SAaron Smith   lldbassert(sc.comp_unit);
33274e08ca0SZachary Turner 
333b9c1b51eSKate Stone   // In theory this is unnecessary work for us, because all of this information
3349d0eb996SAdrian McCarthy   // is easily (and quickly) accessible from DebugInfoPDB, so caching it a
3359d0eb996SAdrian McCarthy   // second time seems like a waste.  Unfortunately, there's no good way around
3369d0eb996SAdrian McCarthy   // this short of a moderate refactor since SymbolVendor depends on being able
3379d0eb996SAdrian McCarthy   // to cache this list.
33810a02577SAaron Smith   auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
33910a02577SAaron Smith   if (!compiland_up)
34074e08ca0SZachary Turner     return false;
34110a02577SAaron Smith   auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
34274e08ca0SZachary Turner   if (!files || files->getChildCount() == 0)
34374e08ca0SZachary Turner     return false;
34474e08ca0SZachary Turner 
345b9c1b51eSKate Stone   while (auto file = files->getNext()) {
346*2cb7cf8eSPavel Labath     FileSpec spec(file->getFileName(), false, FileSpec::Style::windows);
34710a02577SAaron Smith     support_files.AppendIfUnique(spec);
34874e08ca0SZachary Turner   }
34974e08ca0SZachary Turner   return true;
35074e08ca0SZachary Turner }
35174e08ca0SZachary Turner 
352b9c1b51eSKate Stone bool SymbolFilePDB::ParseImportedModules(
353b9c1b51eSKate Stone     const lldb_private::SymbolContext &sc,
354b9c1b51eSKate Stone     std::vector<lldb_private::ConstString> &imported_modules) {
35574e08ca0SZachary Turner   // PDB does not yet support module debug info
35674e08ca0SZachary Turner   return false;
35774e08ca0SZachary Turner }
35874e08ca0SZachary Turner 
359c8316ed2SAaron Smith static size_t ParseFunctionBlocksForPDBSymbol(
360c8316ed2SAaron Smith     const lldb_private::SymbolContext &sc, uint64_t func_file_vm_addr,
361c8316ed2SAaron Smith     const llvm::pdb::PDBSymbol *pdb_symbol, lldb_private::Block *parent_block,
3627ac1c780SAaron Smith     bool is_top_parent) {
3637ac1c780SAaron Smith   assert(pdb_symbol && parent_block);
3647ac1c780SAaron Smith 
3657ac1c780SAaron Smith   size_t num_added = 0;
3667ac1c780SAaron Smith   switch (pdb_symbol->getSymTag()) {
3677ac1c780SAaron Smith   case PDB_SymType::Block:
3687ac1c780SAaron Smith   case PDB_SymType::Function: {
3697ac1c780SAaron Smith     Block *block = nullptr;
3707ac1c780SAaron Smith     auto &raw_sym = pdb_symbol->getRawSymbol();
3717ac1c780SAaron Smith     if (auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(pdb_symbol)) {
3727ac1c780SAaron Smith       if (pdb_func->hasNoInlineAttribute())
3737ac1c780SAaron Smith         break;
3747ac1c780SAaron Smith       if (is_top_parent)
3757ac1c780SAaron Smith         block = parent_block;
3767ac1c780SAaron Smith       else
3777ac1c780SAaron Smith         break;
3787ac1c780SAaron Smith     } else if (llvm::dyn_cast<PDBSymbolBlock>(pdb_symbol)) {
3797ac1c780SAaron Smith       auto uid = pdb_symbol->getSymIndexId();
3807ac1c780SAaron Smith       if (parent_block->FindBlockByID(uid))
3817ac1c780SAaron Smith         break;
3827ac1c780SAaron Smith       if (raw_sym.getVirtualAddress() < func_file_vm_addr)
3837ac1c780SAaron Smith         break;
3847ac1c780SAaron Smith 
3857ac1c780SAaron Smith       auto block_sp = std::make_shared<Block>(pdb_symbol->getSymIndexId());
3867ac1c780SAaron Smith       parent_block->AddChild(block_sp);
3877ac1c780SAaron Smith       block = block_sp.get();
3887ac1c780SAaron Smith     } else
3897ac1c780SAaron Smith       llvm_unreachable("Unexpected PDB symbol!");
3907ac1c780SAaron Smith 
391c8316ed2SAaron Smith     block->AddRange(Block::Range(
392c8316ed2SAaron Smith         raw_sym.getVirtualAddress() - func_file_vm_addr, raw_sym.getLength()));
3937ac1c780SAaron Smith     block->FinalizeRanges();
3947ac1c780SAaron Smith     ++num_added;
3957ac1c780SAaron Smith 
3967ac1c780SAaron Smith     auto results_up = pdb_symbol->findAllChildren();
3977ac1c780SAaron Smith     if (!results_up)
3987ac1c780SAaron Smith       break;
3997ac1c780SAaron Smith     while (auto symbol_up = results_up->getNext()) {
400c8316ed2SAaron Smith       num_added += ParseFunctionBlocksForPDBSymbol(
401c8316ed2SAaron Smith           sc, func_file_vm_addr, symbol_up.get(), block, false);
4027ac1c780SAaron Smith     }
4037ac1c780SAaron Smith   } break;
404c8316ed2SAaron Smith   default:
405c8316ed2SAaron Smith     break;
4067ac1c780SAaron Smith   }
4077ac1c780SAaron Smith   return num_added;
4087ac1c780SAaron Smith }
4097ac1c780SAaron Smith 
41074e08ca0SZachary Turner size_t
411b9c1b51eSKate Stone SymbolFilePDB::ParseFunctionBlocks(const lldb_private::SymbolContext &sc) {
4127ac1c780SAaron Smith   lldbassert(sc.comp_unit && sc.function);
4137ac1c780SAaron Smith   size_t num_added = 0;
4147ac1c780SAaron Smith   auto uid = sc.function->GetID();
4157ac1c780SAaron Smith   auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid);
4167ac1c780SAaron Smith   if (!pdb_func_up)
4177ac1c780SAaron Smith     return 0;
4187ac1c780SAaron Smith   Block &parent_block = sc.function->GetBlock(false);
4197ac1c780SAaron Smith   num_added =
4207ac1c780SAaron Smith       ParseFunctionBlocksForPDBSymbol(sc, pdb_func_up->getVirtualAddress(),
4217ac1c780SAaron Smith                                       pdb_func_up.get(), &parent_block, true);
4227ac1c780SAaron Smith   return num_added;
423b9c1b51eSKate Stone }
424b9c1b51eSKate Stone 
425b9c1b51eSKate Stone size_t SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc) {
426ec40f818SAaron Smith   lldbassert(sc.module_sp.get());
42766b84079SAaron Smith   if (!sc.comp_unit)
428ec40f818SAaron Smith     return 0;
42966b84079SAaron Smith 
43066b84079SAaron Smith   size_t num_added = 0;
43166b84079SAaron Smith   auto compiland = GetPDBCompilandByUID(sc.comp_unit->GetID());
43266b84079SAaron Smith   if (!compiland)
43366b84079SAaron Smith     return 0;
43466b84079SAaron Smith 
43566b84079SAaron Smith   auto ParseTypesByTagFn = [&num_added, this](const PDBSymbol &raw_sym) {
43666b84079SAaron Smith     std::unique_ptr<IPDBEnumSymbols> results;
43766b84079SAaron Smith     PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef,
43866b84079SAaron Smith                                     PDB_SymType::UDT};
43966b84079SAaron Smith     for (auto tag : tags_to_search) {
44066b84079SAaron Smith       results = raw_sym.findAllChildren(tag);
44166b84079SAaron Smith       if (!results || results->getChildCount() == 0)
44266b84079SAaron Smith         continue;
44366b84079SAaron Smith       while (auto symbol = results->getNext()) {
44466b84079SAaron Smith         switch (symbol->getSymTag()) {
445ec40f818SAaron Smith         case PDB_SymType::Enum:
446ec40f818SAaron Smith         case PDB_SymType::UDT:
447ec40f818SAaron Smith         case PDB_SymType::Typedef:
448ec40f818SAaron Smith           break;
449ec40f818SAaron Smith         default:
450ec40f818SAaron Smith           continue;
451ec40f818SAaron Smith         }
452ec40f818SAaron Smith 
453ec40f818SAaron Smith         // This should cause the type to get cached and stored in the `m_types`
454ec40f818SAaron Smith         // lookup.
45566b84079SAaron Smith         if (!ResolveTypeUID(symbol->getSymIndexId()))
456ec40f818SAaron Smith           continue;
457ec40f818SAaron Smith 
458ec40f818SAaron Smith         ++num_added;
459ec40f818SAaron Smith       }
46066b84079SAaron Smith     }
46166b84079SAaron Smith   };
46266b84079SAaron Smith 
46366b84079SAaron Smith   if (sc.function) {
464c8316ed2SAaron Smith     auto pdb_func = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(
465c8316ed2SAaron Smith         sc.function->GetID());
46666b84079SAaron Smith     if (!pdb_func)
46766b84079SAaron Smith       return 0;
46866b84079SAaron Smith     ParseTypesByTagFn(*pdb_func);
46966b84079SAaron Smith   } else {
47066b84079SAaron Smith     ParseTypesByTagFn(*compiland);
47166b84079SAaron Smith 
47266b84079SAaron Smith     // Also parse global types particularly coming from this compiland.
47305097246SAdrian Prantl     // Unfortunately, PDB has no compiland information for each global type. We
47405097246SAdrian Prantl     // have to parse them all. But ensure we only do this once.
47566b84079SAaron Smith     static bool parse_all_global_types = false;
47666b84079SAaron Smith     if (!parse_all_global_types) {
47766b84079SAaron Smith       ParseTypesByTagFn(*m_global_scope_up);
47866b84079SAaron Smith       parse_all_global_types = true;
47966b84079SAaron Smith     }
48066b84079SAaron Smith   }
481ec40f818SAaron Smith   return num_added;
48274e08ca0SZachary Turner }
48374e08ca0SZachary Turner 
48474e08ca0SZachary Turner size_t
485b9c1b51eSKate Stone SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) {
48674e08ca0SZachary Turner   // TODO: Implement this
48774e08ca0SZachary Turner   return size_t();
48874e08ca0SZachary Turner }
48974e08ca0SZachary Turner 
490b9c1b51eSKate Stone lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
49142dff790SZachary Turner   auto find_result = m_types.find(type_uid);
49242dff790SZachary Turner   if (find_result != m_types.end())
49342dff790SZachary Turner     return find_result->second.get();
49442dff790SZachary Turner 
495b9c1b51eSKate Stone   TypeSystem *type_system =
496b9c1b51eSKate Stone       GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
497b9c1b51eSKate Stone   ClangASTContext *clang_type_system =
498b9c1b51eSKate Stone       llvm::dyn_cast_or_null<ClangASTContext>(type_system);
49942dff790SZachary Turner   if (!clang_type_system)
50074e08ca0SZachary Turner     return nullptr;
501b9c1b51eSKate Stone   PDBASTParser *pdb =
502b9c1b51eSKate Stone       llvm::dyn_cast<PDBASTParser>(clang_type_system->GetPDBParser());
50342dff790SZachary Turner   if (!pdb)
50442dff790SZachary Turner     return nullptr;
50542dff790SZachary Turner 
50642dff790SZachary Turner   auto pdb_type = m_session_up->getSymbolById(type_uid);
50742dff790SZachary Turner   if (pdb_type == nullptr)
50842dff790SZachary Turner     return nullptr;
50942dff790SZachary Turner 
51042dff790SZachary Turner   lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type);
511d5a925f4SAaron Smith   if (result) {
51242dff790SZachary Turner     m_types.insert(std::make_pair(type_uid, result));
513ec40f818SAaron Smith     auto type_list = GetTypeList();
514f76fe682SAaron Smith     if (type_list)
515ec40f818SAaron Smith       type_list->Insert(result);
516ec40f818SAaron Smith   }
51742dff790SZachary Turner   return result.get();
51874e08ca0SZachary Turner }
51974e08ca0SZachary Turner 
520b9c1b51eSKate Stone bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) {
52174e08ca0SZachary Turner   // TODO: Implement this
52274e08ca0SZachary Turner   return false;
52374e08ca0SZachary Turner }
52474e08ca0SZachary Turner 
525b9c1b51eSKate Stone lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) {
52674e08ca0SZachary Turner   return lldb_private::CompilerDecl();
52774e08ca0SZachary Turner }
52874e08ca0SZachary Turner 
52974e08ca0SZachary Turner lldb_private::CompilerDeclContext
530b9c1b51eSKate Stone SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) {
531b9c1b51eSKate Stone   // PDB always uses the translation unit decl context for everything.  We can
5329d0eb996SAdrian McCarthy   // improve this later but it's not easy because PDB doesn't provide a high
5339d0eb996SAdrian McCarthy   // enough level of type fidelity in this area.
53442dff790SZachary Turner   return *m_tu_decl_ctx_up;
53574e08ca0SZachary Turner }
53674e08ca0SZachary Turner 
53774e08ca0SZachary Turner lldb_private::CompilerDeclContext
538b9c1b51eSKate Stone SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
53942dff790SZachary Turner   return *m_tu_decl_ctx_up;
54074e08ca0SZachary Turner }
54174e08ca0SZachary Turner 
542b9c1b51eSKate Stone void SymbolFilePDB::ParseDeclsForContext(
543b9c1b51eSKate Stone     lldb_private::CompilerDeclContext decl_ctx) {}
54474e08ca0SZachary Turner 
54574e08ca0SZachary Turner uint32_t
546b9c1b51eSKate Stone SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
547b9c1b51eSKate Stone                                     uint32_t resolve_scope,
548b9c1b51eSKate Stone                                     lldb_private::SymbolContext &sc) {
5497ac1c780SAaron Smith   uint32_t resolved_flags = 0;
5504d4d63eeSPavel Labath   if (resolve_scope & eSymbolContextCompUnit ||
5514d4d63eeSPavel Labath       resolve_scope & eSymbolContextVariable ||
5524d4d63eeSPavel Labath       resolve_scope & eSymbolContextFunction ||
5534d4d63eeSPavel Labath       resolve_scope & eSymbolContextBlock ||
5547ac1c780SAaron Smith       resolve_scope & eSymbolContextLineEntry) {
5557ac1c780SAaron Smith     addr_t file_vm_addr = so_addr.GetFileAddress();
5567ac1c780SAaron Smith     auto symbol_up =
5577ac1c780SAaron Smith         m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::None);
5587ac1c780SAaron Smith     if (!symbol_up)
5597ac1c780SAaron Smith       return 0;
5607ac1c780SAaron Smith 
5617ac1c780SAaron Smith     auto cu_sp = GetCompileUnitContainsAddress(so_addr);
5627ac1c780SAaron Smith     if (!cu_sp) {
5637ac1c780SAaron Smith       if (resolved_flags | eSymbolContextVariable) {
5647ac1c780SAaron Smith         // TODO: Resolve variables
5657ac1c780SAaron Smith       }
5667ac1c780SAaron Smith       return 0;
5677ac1c780SAaron Smith     }
5687ac1c780SAaron Smith     sc.comp_unit = cu_sp.get();
5697ac1c780SAaron Smith     resolved_flags |= eSymbolContextCompUnit;
5707ac1c780SAaron Smith     lldbassert(sc.module_sp == cu_sp->GetModule());
5717ac1c780SAaron Smith 
5727ac1c780SAaron Smith     switch (symbol_up->getSymTag()) {
5737ac1c780SAaron Smith     case PDB_SymType::Function:
5747ac1c780SAaron Smith       if (resolve_scope & eSymbolContextFunction) {
5757ac1c780SAaron Smith         auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get());
5767ac1c780SAaron Smith         assert(pdb_func);
5777ac1c780SAaron Smith         auto func_uid = pdb_func->getSymIndexId();
5787ac1c780SAaron Smith         sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get();
5797ac1c780SAaron Smith         if (sc.function == nullptr)
580e664b5dcSAaron Smith           sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc);
5817ac1c780SAaron Smith         if (sc.function) {
5827ac1c780SAaron Smith           resolved_flags |= eSymbolContextFunction;
5837ac1c780SAaron Smith           if (resolve_scope & eSymbolContextBlock) {
5847ac1c780SAaron Smith             Block &block = sc.function->GetBlock(true);
5857ac1c780SAaron Smith             sc.block = block.FindBlockByID(sc.function->GetID());
5867ac1c780SAaron Smith             if (sc.block)
5877ac1c780SAaron Smith               resolved_flags |= eSymbolContextBlock;
5887ac1c780SAaron Smith           }
5897ac1c780SAaron Smith         }
5907ac1c780SAaron Smith       }
5917ac1c780SAaron Smith       break;
5927ac1c780SAaron Smith     default:
5937ac1c780SAaron Smith       break;
5947ac1c780SAaron Smith     }
5957ac1c780SAaron Smith 
5967ac1c780SAaron Smith     if (resolve_scope & eSymbolContextLineEntry) {
5977ac1c780SAaron Smith       if (auto *line_table = sc.comp_unit->GetLineTable()) {
5987ac1c780SAaron Smith         Address addr(so_addr);
5997ac1c780SAaron Smith         if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
6007ac1c780SAaron Smith           resolved_flags |= eSymbolContextLineEntry;
6017ac1c780SAaron Smith       }
6027ac1c780SAaron Smith     }
6037ac1c780SAaron Smith   }
6047ac1c780SAaron Smith   return resolved_flags;
60574e08ca0SZachary Turner }
60674e08ca0SZachary Turner 
607b9c1b51eSKate Stone uint32_t SymbolFilePDB::ResolveSymbolContext(
608b9c1b51eSKate Stone     const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines,
609b9c1b51eSKate Stone     uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list) {
61010a02577SAaron Smith   const size_t old_size = sc_list.GetSize();
611b9c1b51eSKate Stone   if (resolve_scope & lldb::eSymbolContextCompUnit) {
612b9c1b51eSKate Stone     // Locate all compilation units with line numbers referencing the specified
6139d0eb996SAdrian McCarthy     // file.  For example, if `file_spec` is <vector>, then this should return
6149d0eb996SAdrian McCarthy     // all source files and header files that reference <vector>, either
6159d0eb996SAdrian McCarthy     // directly or indirectly.
616b9c1b51eSKate Stone     auto compilands = m_session_up->findCompilandsForSourceFile(
617b9c1b51eSKate Stone         file_spec.GetPath(), PDB_NameSearchFlags::NS_CaseInsensitive);
61874e08ca0SZachary Turner 
61910a02577SAaron Smith     if (!compilands)
62010a02577SAaron Smith       return 0;
62110a02577SAaron Smith 
6229d0eb996SAdrian McCarthy     // For each one, either find its previously parsed data or parse it afresh
6239d0eb996SAdrian McCarthy     // and add it to the symbol context list.
624b9c1b51eSKate Stone     while (auto compiland = compilands->getNext()) {
62505097246SAdrian Prantl       // If we're not checking inlines, then don't add line information for
62605097246SAdrian Prantl       // this file unless the FileSpec matches. For inline functions, we don't
62705097246SAdrian Prantl       // have to match the FileSpec since they could be defined in headers
62805097246SAdrian Prantl       // other than file specified in FileSpec.
629b9c1b51eSKate Stone       if (!check_inlines) {
630487b0c6bSAaron Smith         std::string source_file = compiland->getSourceFileFullPath();
63110a02577SAaron Smith         if (source_file.empty())
63210a02577SAaron Smith           continue;
633*2cb7cf8eSPavel Labath         FileSpec this_spec(source_file, false, FileSpec::Style::windows);
63410a02577SAaron Smith         bool need_full_match = !file_spec.GetDirectory().IsEmpty();
63510a02577SAaron Smith         if (FileSpec::Compare(file_spec, this_spec, need_full_match) != 0)
63674e08ca0SZachary Turner           continue;
63774e08ca0SZachary Turner       }
63874e08ca0SZachary Turner 
63974e08ca0SZachary Turner       SymbolContext sc;
64010a02577SAaron Smith       auto cu = ParseCompileUnitForUID(compiland->getSymIndexId());
641d5a925f4SAaron Smith       if (!cu)
64210a02577SAaron Smith         continue;
64374e08ca0SZachary Turner       sc.comp_unit = cu.get();
64474e08ca0SZachary Turner       sc.module_sp = cu->GetModule();
64574e08ca0SZachary Turner 
646b9c1b51eSKate Stone       // If we were asked to resolve line entries, add all entries to the line
6479d0eb996SAdrian McCarthy       // table that match the requested line (or all lines if `line` == 0).
6487ac1c780SAaron Smith       if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock |
6497ac1c780SAaron Smith                            eSymbolContextLineEntry)) {
6507ac1c780SAaron Smith         bool has_line_table = ParseCompileUnitLineTable(sc, line);
6517ac1c780SAaron Smith 
6527ac1c780SAaron Smith         if ((resolve_scope & eSymbolContextLineEntry) && !has_line_table) {
6537ac1c780SAaron Smith           // The query asks for line entries, but we can't get them for the
65405097246SAdrian Prantl           // compile unit. This is not normal for `line` = 0. So just assert
65505097246SAdrian Prantl           // it.
656f76fe682SAaron Smith           assert(line && "Couldn't get all line entries!\n");
6577ac1c780SAaron Smith 
6587ac1c780SAaron Smith           // Current compiland does not have the requested line. Search next.
6597ac1c780SAaron Smith           continue;
6607ac1c780SAaron Smith         }
6617ac1c780SAaron Smith 
6627ac1c780SAaron Smith         if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) {
6637ac1c780SAaron Smith           if (!has_line_table)
6647ac1c780SAaron Smith             continue;
6657ac1c780SAaron Smith 
6667ac1c780SAaron Smith           auto *line_table = sc.comp_unit->GetLineTable();
6677ac1c780SAaron Smith           lldbassert(line_table);
6687ac1c780SAaron Smith 
6697ac1c780SAaron Smith           uint32_t num_line_entries = line_table->GetSize();
6707ac1c780SAaron Smith           // Skip the terminal line entry.
6717ac1c780SAaron Smith           --num_line_entries;
6727ac1c780SAaron Smith 
67305097246SAdrian Prantl           // If `line `!= 0, see if we can resolve function for each line entry
67405097246SAdrian Prantl           // in the line table.
6757ac1c780SAaron Smith           for (uint32_t line_idx = 0; line && line_idx < num_line_entries;
6767ac1c780SAaron Smith                ++line_idx) {
6777ac1c780SAaron Smith             if (!line_table->GetLineEntryAtIndex(line_idx, sc.line_entry))
6787ac1c780SAaron Smith               continue;
6797ac1c780SAaron Smith 
6807ac1c780SAaron Smith             auto file_vm_addr =
6817ac1c780SAaron Smith                 sc.line_entry.range.GetBaseAddress().GetFileAddress();
682308e39caSAaron Smith             if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
6837ac1c780SAaron Smith               continue;
6847ac1c780SAaron Smith 
685c8316ed2SAaron Smith             auto symbol_up = m_session_up->findSymbolByAddress(
686c8316ed2SAaron Smith                 file_vm_addr, PDB_SymType::Function);
6877ac1c780SAaron Smith             if (symbol_up) {
6887ac1c780SAaron Smith               auto func_uid = symbol_up->getSymIndexId();
6897ac1c780SAaron Smith               sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get();
6907ac1c780SAaron Smith               if (sc.function == nullptr) {
6917ac1c780SAaron Smith                 auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get());
6927ac1c780SAaron Smith                 assert(pdb_func);
693e664b5dcSAaron Smith                 sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc);
6947ac1c780SAaron Smith               }
6957ac1c780SAaron Smith               if (sc.function && (resolve_scope & eSymbolContextBlock)) {
6967ac1c780SAaron Smith                 Block &block = sc.function->GetBlock(true);
6977ac1c780SAaron Smith                 sc.block = block.FindBlockByID(sc.function->GetID());
6987ac1c780SAaron Smith               }
6997ac1c780SAaron Smith             }
7007ac1c780SAaron Smith             sc_list.Append(sc);
7017ac1c780SAaron Smith           }
7027ac1c780SAaron Smith         } else if (has_line_table) {
7037ac1c780SAaron Smith           // We can parse line table for the compile unit. But no query to
7047ac1c780SAaron Smith           // resolve function or block. We append `sc` to the list anyway.
7057ac1c780SAaron Smith           sc_list.Append(sc);
7067ac1c780SAaron Smith         }
7077ac1c780SAaron Smith       } else {
7087ac1c780SAaron Smith         // No query for line entry, function or block. But we have a valid
7097ac1c780SAaron Smith         // compile unit, append `sc` to the list.
7107ac1c780SAaron Smith         sc_list.Append(sc);
7117ac1c780SAaron Smith       }
71274e08ca0SZachary Turner     }
71374e08ca0SZachary Turner   }
71410a02577SAaron Smith   return sc_list.GetSize() - old_size;
71574e08ca0SZachary Turner }
71674e08ca0SZachary Turner 
717b9c1b51eSKate Stone uint32_t SymbolFilePDB::FindGlobalVariables(
718b9c1b51eSKate Stone     const lldb_private::ConstString &name,
71974e08ca0SZachary Turner     const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append,
720b9c1b51eSKate Stone     uint32_t max_matches, lldb_private::VariableList &variables) {
72174e08ca0SZachary Turner   return uint32_t();
72274e08ca0SZachary Turner }
72374e08ca0SZachary Turner 
72474e08ca0SZachary Turner uint32_t
725b9c1b51eSKate Stone SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression &regex,
726b9c1b51eSKate Stone                                    bool append, uint32_t max_matches,
727b9c1b51eSKate Stone                                    lldb_private::VariableList &variables) {
728b9c1b51eSKate Stone   return uint32_t();
729b9c1b51eSKate Stone }
730b9c1b51eSKate Stone 
731e664b5dcSAaron Smith bool SymbolFilePDB::ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func,
7327ac1c780SAaron Smith                                     bool include_inlines,
7337ac1c780SAaron Smith                                     lldb_private::SymbolContextList &sc_list) {
7347ac1c780SAaron Smith   lldb_private::SymbolContext sc;
735a3a8cc80SAaron Smith   sc.comp_unit = ParseCompileUnitForUID(pdb_func.getCompilandId()).get();
7367ac1c780SAaron Smith   if (!sc.comp_unit)
7377ac1c780SAaron Smith     return false;
7387ac1c780SAaron Smith   sc.module_sp = sc.comp_unit->GetModule();
739a3a8cc80SAaron Smith   sc.function = ParseCompileUnitFunctionForPDBFunc(pdb_func, sc);
7407ac1c780SAaron Smith   if (!sc.function)
7417ac1c780SAaron Smith     return false;
7427ac1c780SAaron Smith 
7437ac1c780SAaron Smith   sc_list.Append(sc);
7447ac1c780SAaron Smith   return true;
7457ac1c780SAaron Smith }
7467ac1c780SAaron Smith 
7477ac1c780SAaron Smith bool SymbolFilePDB::ResolveFunction(uint32_t uid, bool include_inlines,
7487ac1c780SAaron Smith                                     lldb_private::SymbolContextList &sc_list) {
749c8316ed2SAaron Smith   auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid);
7507ac1c780SAaron Smith   if (!pdb_func_up && !(include_inlines && pdb_func_up->hasInlineAttribute()))
7517ac1c780SAaron Smith     return false;
752e664b5dcSAaron Smith   return ResolveFunction(*pdb_func_up, include_inlines, sc_list);
7537ac1c780SAaron Smith }
7547ac1c780SAaron Smith 
7557ac1c780SAaron Smith void SymbolFilePDB::CacheFunctionNames() {
7567ac1c780SAaron Smith   if (!m_func_full_names.IsEmpty())
7577ac1c780SAaron Smith     return;
7587ac1c780SAaron Smith 
7597ac1c780SAaron Smith   std::map<uint64_t, uint32_t> addr_ids;
7607ac1c780SAaron Smith 
7617ac1c780SAaron Smith   if (auto results_up = m_global_scope_up->findAllChildren<PDBSymbolFunc>()) {
7627ac1c780SAaron Smith     while (auto pdb_func_up = results_up->getNext()) {
763f76fe682SAaron Smith       if (pdb_func_up->isCompilerGenerated())
764f76fe682SAaron Smith         continue;
765f76fe682SAaron Smith 
7667ac1c780SAaron Smith       auto name = pdb_func_up->getName();
7677ac1c780SAaron Smith       auto demangled_name = pdb_func_up->getUndecoratedName();
7687ac1c780SAaron Smith       if (name.empty() && demangled_name.empty())
7697ac1c780SAaron Smith         continue;
7707ac1c780SAaron Smith 
771f76fe682SAaron Smith       auto uid = pdb_func_up->getSymIndexId();
7727ac1c780SAaron Smith       if (!demangled_name.empty() && pdb_func_up->getVirtualAddress())
7737ac1c780SAaron Smith         addr_ids.insert(std::make_pair(pdb_func_up->getVirtualAddress(), uid));
7747ac1c780SAaron Smith 
7757ac1c780SAaron Smith       if (auto parent = pdb_func_up->getClassParent()) {
7767ac1c780SAaron Smith 
7777ac1c780SAaron Smith         // PDB have symbols for class/struct methods or static methods in Enum
7787ac1c780SAaron Smith         // Class. We won't bother to check if the parent is UDT or Enum here.
7797ac1c780SAaron Smith         m_func_method_names.Append(ConstString(name), uid);
7807ac1c780SAaron Smith 
7817ac1c780SAaron Smith         ConstString cstr_name(name);
7827ac1c780SAaron Smith 
78305097246SAdrian Prantl         // To search a method name, like NS::Class:MemberFunc, LLDB searches
78405097246SAdrian Prantl         // its base name, i.e. MemberFunc by default. Since PDBSymbolFunc does
78505097246SAdrian Prantl         // not have inforamtion of this, we extract base names and cache them
78605097246SAdrian Prantl         // by our own effort.
7877ac1c780SAaron Smith         llvm::StringRef basename;
7887ac1c780SAaron Smith         CPlusPlusLanguage::MethodName cpp_method(cstr_name);
7897ac1c780SAaron Smith         if (cpp_method.IsValid()) {
7907ac1c780SAaron Smith           llvm::StringRef context;
7917ac1c780SAaron Smith           basename = cpp_method.GetBasename();
7927ac1c780SAaron Smith           if (basename.empty())
7937ac1c780SAaron Smith             CPlusPlusLanguage::ExtractContextAndIdentifier(name.c_str(),
7947ac1c780SAaron Smith                                                            context, basename);
7957ac1c780SAaron Smith         }
7967ac1c780SAaron Smith 
7977ac1c780SAaron Smith         if (!basename.empty())
7987ac1c780SAaron Smith           m_func_base_names.Append(ConstString(basename), uid);
7997ac1c780SAaron Smith         else {
8007ac1c780SAaron Smith           m_func_base_names.Append(ConstString(name), uid);
8017ac1c780SAaron Smith         }
8027ac1c780SAaron Smith 
8037ac1c780SAaron Smith         if (!demangled_name.empty())
8047ac1c780SAaron Smith           m_func_full_names.Append(ConstString(demangled_name), uid);
8057ac1c780SAaron Smith 
8067ac1c780SAaron Smith       } else {
8077ac1c780SAaron Smith         // Handle not-method symbols.
8087ac1c780SAaron Smith 
8097ac1c780SAaron Smith         // The function name might contain namespace, or its lexical scope. It
8107ac1c780SAaron Smith         // is not safe to get its base name by applying same scheme as we deal
8117ac1c780SAaron Smith         // with the method names.
8127ac1c780SAaron Smith         // FIXME: Remove namespace if function is static in a scope.
8137ac1c780SAaron Smith         m_func_base_names.Append(ConstString(name), uid);
8147ac1c780SAaron Smith 
8157ac1c780SAaron Smith         if (name == "main") {
8167ac1c780SAaron Smith           m_func_full_names.Append(ConstString(name), uid);
8177ac1c780SAaron Smith 
8187ac1c780SAaron Smith           if (!demangled_name.empty() && name != demangled_name) {
8197ac1c780SAaron Smith             m_func_full_names.Append(ConstString(demangled_name), uid);
8207ac1c780SAaron Smith             m_func_base_names.Append(ConstString(demangled_name), uid);
8217ac1c780SAaron Smith           }
8227ac1c780SAaron Smith         } else if (!demangled_name.empty()) {
8237ac1c780SAaron Smith           m_func_full_names.Append(ConstString(demangled_name), uid);
8247ac1c780SAaron Smith         } else {
8257ac1c780SAaron Smith           m_func_full_names.Append(ConstString(name), uid);
8267ac1c780SAaron Smith         }
8277ac1c780SAaron Smith       }
8287ac1c780SAaron Smith     }
8297ac1c780SAaron Smith   }
8307ac1c780SAaron Smith 
8317ac1c780SAaron Smith   if (auto results_up =
8327ac1c780SAaron Smith           m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>()) {
8337ac1c780SAaron Smith     while (auto pub_sym_up = results_up->getNext()) {
8347ac1c780SAaron Smith       if (!pub_sym_up->isFunction())
8357ac1c780SAaron Smith         continue;
8367ac1c780SAaron Smith       auto name = pub_sym_up->getName();
8377ac1c780SAaron Smith       if (name.empty())
8387ac1c780SAaron Smith         continue;
8397ac1c780SAaron Smith 
8407ac1c780SAaron Smith       if (CPlusPlusLanguage::IsCPPMangledName(name.c_str())) {
8417ac1c780SAaron Smith         auto vm_addr = pub_sym_up->getVirtualAddress();
8427ac1c780SAaron Smith 
8437ac1c780SAaron Smith         // PDB public symbol has mangled name for its associated function.
8447ac1c780SAaron Smith         if (vm_addr && addr_ids.find(vm_addr) != addr_ids.end()) {
8457ac1c780SAaron Smith           // Cache mangled name.
8467ac1c780SAaron Smith           m_func_full_names.Append(ConstString(name), addr_ids[vm_addr]);
8477ac1c780SAaron Smith         }
8487ac1c780SAaron Smith       }
8497ac1c780SAaron Smith     }
8507ac1c780SAaron Smith   }
8517ac1c780SAaron Smith   // Sort them before value searching is working properly
8527ac1c780SAaron Smith   m_func_full_names.Sort();
8537ac1c780SAaron Smith   m_func_full_names.SizeToFit();
8547ac1c780SAaron Smith   m_func_method_names.Sort();
8557ac1c780SAaron Smith   m_func_method_names.SizeToFit();
8567ac1c780SAaron Smith   m_func_base_names.Sort();
8577ac1c780SAaron Smith   m_func_base_names.SizeToFit();
8587ac1c780SAaron Smith }
8597ac1c780SAaron Smith 
860b9c1b51eSKate Stone uint32_t SymbolFilePDB::FindFunctions(
861b9c1b51eSKate Stone     const lldb_private::ConstString &name,
862b9c1b51eSKate Stone     const lldb_private::CompilerDeclContext *parent_decl_ctx,
863b9c1b51eSKate Stone     uint32_t name_type_mask, bool include_inlines, bool append,
864b9c1b51eSKate Stone     lldb_private::SymbolContextList &sc_list) {
8657ac1c780SAaron Smith   if (!append)
8667ac1c780SAaron Smith     sc_list.Clear();
8677ac1c780SAaron Smith   lldbassert((name_type_mask & eFunctionNameTypeAuto) == 0);
8687ac1c780SAaron Smith 
8697ac1c780SAaron Smith   if (name_type_mask == eFunctionNameTypeNone)
8707ac1c780SAaron Smith     return 0;
8717ac1c780SAaron Smith   if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
8727ac1c780SAaron Smith     return 0;
8737ac1c780SAaron Smith   if (name.IsEmpty())
8747ac1c780SAaron Smith     return 0;
8757ac1c780SAaron Smith 
8767ac1c780SAaron Smith   auto old_size = sc_list.GetSize();
8774d4d63eeSPavel Labath   if (name_type_mask & eFunctionNameTypeFull ||
8784d4d63eeSPavel Labath       name_type_mask & eFunctionNameTypeBase ||
8797ac1c780SAaron Smith       name_type_mask & eFunctionNameTypeMethod) {
8807ac1c780SAaron Smith     CacheFunctionNames();
8817ac1c780SAaron Smith 
8827ac1c780SAaron Smith     std::set<uint32_t> resolved_ids;
883c8316ed2SAaron Smith     auto ResolveFn = [include_inlines, &name, &sc_list, &resolved_ids,
884c8316ed2SAaron Smith                       this](UniqueCStringMap<uint32_t> &Names) {
8857ac1c780SAaron Smith       std::vector<uint32_t> ids;
8867ac1c780SAaron Smith       if (Names.GetValues(name, ids)) {
8877ac1c780SAaron Smith         for (auto id : ids) {
8887ac1c780SAaron Smith           if (resolved_ids.find(id) == resolved_ids.end()) {
8897ac1c780SAaron Smith             if (ResolveFunction(id, include_inlines, sc_list))
8907ac1c780SAaron Smith               resolved_ids.insert(id);
8917ac1c780SAaron Smith           }
8927ac1c780SAaron Smith         }
8937ac1c780SAaron Smith       }
8947ac1c780SAaron Smith     };
8957ac1c780SAaron Smith     if (name_type_mask & eFunctionNameTypeFull) {
8967ac1c780SAaron Smith       ResolveFn(m_func_full_names);
8977ac1c780SAaron Smith     }
8987ac1c780SAaron Smith     if (name_type_mask & eFunctionNameTypeBase) {
8997ac1c780SAaron Smith       ResolveFn(m_func_base_names);
9007ac1c780SAaron Smith     }
9017ac1c780SAaron Smith     if (name_type_mask & eFunctionNameTypeMethod) {
9027ac1c780SAaron Smith       ResolveFn(m_func_method_names);
9037ac1c780SAaron Smith     }
9047ac1c780SAaron Smith   }
9057ac1c780SAaron Smith   return sc_list.GetSize() - old_size;
90674e08ca0SZachary Turner }
90774e08ca0SZachary Turner 
90874e08ca0SZachary Turner uint32_t
909b9c1b51eSKate Stone SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression &regex,
910b9c1b51eSKate Stone                              bool include_inlines, bool append,
911b9c1b51eSKate Stone                              lldb_private::SymbolContextList &sc_list) {
9127ac1c780SAaron Smith   if (!append)
9137ac1c780SAaron Smith     sc_list.Clear();
9147ac1c780SAaron Smith   if (!regex.IsValid())
9157ac1c780SAaron Smith     return 0;
9167ac1c780SAaron Smith 
9177ac1c780SAaron Smith   auto old_size = sc_list.GetSize();
9187ac1c780SAaron Smith   CacheFunctionNames();
9197ac1c780SAaron Smith 
9207ac1c780SAaron Smith   std::set<uint32_t> resolved_ids;
921c8316ed2SAaron Smith   auto ResolveFn = [&regex, include_inlines, &sc_list, &resolved_ids,
922c8316ed2SAaron Smith                     this](UniqueCStringMap<uint32_t> &Names) {
9237ac1c780SAaron Smith     std::vector<uint32_t> ids;
9247ac1c780SAaron Smith     if (Names.GetValues(regex, ids)) {
9257ac1c780SAaron Smith       for (auto id : ids) {
9267ac1c780SAaron Smith         if (resolved_ids.find(id) == resolved_ids.end())
9277ac1c780SAaron Smith           if (ResolveFunction(id, include_inlines, sc_list))
9287ac1c780SAaron Smith             resolved_ids.insert(id);
9297ac1c780SAaron Smith       }
9307ac1c780SAaron Smith     }
9317ac1c780SAaron Smith   };
9327ac1c780SAaron Smith   ResolveFn(m_func_full_names);
9337ac1c780SAaron Smith   ResolveFn(m_func_base_names);
9347ac1c780SAaron Smith 
9357ac1c780SAaron Smith   return sc_list.GetSize() - old_size;
93674e08ca0SZachary Turner }
93774e08ca0SZachary Turner 
938b9c1b51eSKate Stone void SymbolFilePDB::GetMangledNamesForFunction(
939b9c1b51eSKate Stone     const std::string &scope_qualified_name,
940b9c1b51eSKate Stone     std::vector<lldb_private::ConstString> &mangled_names) {}
94174e08ca0SZachary Turner 
942b9c1b51eSKate Stone uint32_t SymbolFilePDB::FindTypes(
943b9c1b51eSKate Stone     const lldb_private::SymbolContext &sc,
944b9c1b51eSKate Stone     const lldb_private::ConstString &name,
945b9c1b51eSKate Stone     const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append,
946b9c1b51eSKate Stone     uint32_t max_matches,
94774e08ca0SZachary Turner     llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
948b9c1b51eSKate Stone     lldb_private::TypeMap &types) {
94942dff790SZachary Turner   if (!append)
95042dff790SZachary Turner     types.Clear();
95142dff790SZachary Turner   if (!name)
95242dff790SZachary Turner     return 0;
9537ac1c780SAaron Smith   if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
9547ac1c780SAaron Smith     return 0;
95542dff790SZachary Turner 
95642dff790SZachary Turner   searched_symbol_files.clear();
95742dff790SZachary Turner   searched_symbol_files.insert(this);
95842dff790SZachary Turner 
95942dff790SZachary Turner   std::string name_str = name.AsCString();
96042dff790SZachary Turner 
96186e9434dSAaron Smith   // There is an assumption 'name' is not a regex
96242dff790SZachary Turner   FindTypesByName(name_str, max_matches, types);
96386e9434dSAaron Smith 
96442dff790SZachary Turner   return types.GetSize();
96542dff790SZachary Turner }
96642dff790SZachary Turner 
967c8316ed2SAaron Smith void SymbolFilePDB::FindTypesByRegex(
968c8316ed2SAaron Smith     const lldb_private::RegularExpression &regex, uint32_t max_matches,
969b9c1b51eSKate Stone     lldb_private::TypeMap &types) {
970b9c1b51eSKate Stone   // When searching by regex, we need to go out of our way to limit the search
9719d0eb996SAdrian McCarthy   // space as much as possible since this searches EVERYTHING in the PDB,
9729d0eb996SAdrian McCarthy   // manually doing regex comparisons.  PDB library isn't optimized for regex
9739d0eb996SAdrian McCarthy   // searches or searches across multiple symbol types at the same time, so the
974b9c1b51eSKate Stone   // best we can do is to search enums, then typedefs, then classes one by one,
9759d0eb996SAdrian McCarthy   // and do a regex comparison against each of them.
976b9c1b51eSKate Stone   PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef,
977b9c1b51eSKate Stone                                   PDB_SymType::UDT};
97854fd7ff6SZachary Turner   std::unique_ptr<IPDBEnumSymbols> results;
97942dff790SZachary Turner 
98042dff790SZachary Turner   uint32_t matches = 0;
98142dff790SZachary Turner 
982b9c1b51eSKate Stone   for (auto tag : tags_to_search) {
98310a02577SAaron Smith     results = m_global_scope_up->findAllChildren(tag);
98410a02577SAaron Smith     if (!results)
98510a02577SAaron Smith       continue;
98610a02577SAaron Smith 
987b9c1b51eSKate Stone     while (auto result = results->getNext()) {
98842dff790SZachary Turner       if (max_matches > 0 && matches >= max_matches)
98942dff790SZachary Turner         break;
99042dff790SZachary Turner 
99142dff790SZachary Turner       std::string type_name;
99254fd7ff6SZachary Turner       if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(result.get()))
99342dff790SZachary Turner         type_name = enum_type->getName();
994b9c1b51eSKate Stone       else if (auto typedef_type =
995b9c1b51eSKate Stone                    llvm::dyn_cast<PDBSymbolTypeTypedef>(result.get()))
99642dff790SZachary Turner         type_name = typedef_type->getName();
99754fd7ff6SZachary Turner       else if (auto class_type = llvm::dyn_cast<PDBSymbolTypeUDT>(result.get()))
99842dff790SZachary Turner         type_name = class_type->getName();
999b9c1b51eSKate Stone       else {
10009d0eb996SAdrian McCarthy         // We're looking only for types that have names.  Skip symbols, as well
10019d0eb996SAdrian McCarthy         // as unnamed types such as arrays, pointers, etc.
100242dff790SZachary Turner         continue;
100342dff790SZachary Turner       }
100442dff790SZachary Turner 
100586e9434dSAaron Smith       if (!regex.Execute(type_name))
100642dff790SZachary Turner         continue;
100742dff790SZachary Turner 
1008b9c1b51eSKate Stone       // This should cause the type to get cached and stored in the `m_types`
1009b9c1b51eSKate Stone       // lookup.
101042dff790SZachary Turner       if (!ResolveTypeUID(result->getSymIndexId()))
101142dff790SZachary Turner         continue;
101242dff790SZachary Turner 
101342dff790SZachary Turner       auto iter = m_types.find(result->getSymIndexId());
101442dff790SZachary Turner       if (iter == m_types.end())
101542dff790SZachary Turner         continue;
101642dff790SZachary Turner       types.Insert(iter->second);
101742dff790SZachary Turner       ++matches;
101842dff790SZachary Turner     }
101942dff790SZachary Turner   }
102042dff790SZachary Turner }
102142dff790SZachary Turner 
1022b9c1b51eSKate Stone void SymbolFilePDB::FindTypesByName(const std::string &name,
1023b9c1b51eSKate Stone                                     uint32_t max_matches,
1024b9c1b51eSKate Stone                                     lldb_private::TypeMap &types) {
102554fd7ff6SZachary Turner   std::unique_ptr<IPDBEnumSymbols> results;
1026f76fe682SAaron Smith   if (name.empty())
1027f76fe682SAaron Smith     return;
102810a02577SAaron Smith   results = m_global_scope_up->findChildren(PDB_SymType::None, name,
1029b9c1b51eSKate Stone                                             PDB_NameSearchFlags::NS_Default);
103010a02577SAaron Smith   if (!results)
103110a02577SAaron Smith     return;
103242dff790SZachary Turner 
103342dff790SZachary Turner   uint32_t matches = 0;
103442dff790SZachary Turner 
1035b9c1b51eSKate Stone   while (auto result = results->getNext()) {
103642dff790SZachary Turner     if (max_matches > 0 && matches >= max_matches)
103742dff790SZachary Turner       break;
1038b9c1b51eSKate Stone     switch (result->getSymTag()) {
103954fd7ff6SZachary Turner     case PDB_SymType::Enum:
104054fd7ff6SZachary Turner     case PDB_SymType::UDT:
104154fd7ff6SZachary Turner     case PDB_SymType::Typedef:
104242dff790SZachary Turner       break;
104342dff790SZachary Turner     default:
104405097246SAdrian Prantl       // We're looking only for types that have names.  Skip symbols, as well
104505097246SAdrian Prantl       // as unnamed types such as arrays, pointers, etc.
104642dff790SZachary Turner       continue;
104742dff790SZachary Turner     }
104842dff790SZachary Turner 
1049b9c1b51eSKate Stone     // This should cause the type to get cached and stored in the `m_types`
1050b9c1b51eSKate Stone     // lookup.
105142dff790SZachary Turner     if (!ResolveTypeUID(result->getSymIndexId()))
105242dff790SZachary Turner       continue;
105342dff790SZachary Turner 
105442dff790SZachary Turner     auto iter = m_types.find(result->getSymIndexId());
105542dff790SZachary Turner     if (iter == m_types.end())
105642dff790SZachary Turner       continue;
105742dff790SZachary Turner     types.Insert(iter->second);
105842dff790SZachary Turner     ++matches;
105942dff790SZachary Turner   }
106074e08ca0SZachary Turner }
106174e08ca0SZachary Turner 
1062b9c1b51eSKate Stone size_t SymbolFilePDB::FindTypes(
1063b9c1b51eSKate Stone     const std::vector<lldb_private::CompilerContext> &contexts, bool append,
1064b9c1b51eSKate Stone     lldb_private::TypeMap &types) {
106542dff790SZachary Turner   return 0;
106674e08ca0SZachary Turner }
106774e08ca0SZachary Turner 
1068ec40f818SAaron Smith lldb_private::TypeList *SymbolFilePDB::GetTypeList() {
1069ec40f818SAaron Smith   return m_obj_file->GetModule()->GetTypeList();
1070ec40f818SAaron Smith }
107174e08ca0SZachary Turner 
1072c8316ed2SAaron Smith void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol,
10737ac1c780SAaron Smith                                          uint32_t type_mask,
10747ac1c780SAaron Smith                                          TypeCollection &type_collection) {
10757ac1c780SAaron Smith   bool can_parse = false;
1076e664b5dcSAaron Smith   switch (pdb_symbol.getSymTag()) {
10777ac1c780SAaron Smith   case PDB_SymType::ArrayType:
10787ac1c780SAaron Smith     can_parse = ((type_mask & eTypeClassArray) != 0);
10797ac1c780SAaron Smith     break;
10807ac1c780SAaron Smith   case PDB_SymType::BuiltinType:
10817ac1c780SAaron Smith     can_parse = ((type_mask & eTypeClassBuiltin) != 0);
10827ac1c780SAaron Smith     break;
10837ac1c780SAaron Smith   case PDB_SymType::Enum:
10847ac1c780SAaron Smith     can_parse = ((type_mask & eTypeClassEnumeration) != 0);
10857ac1c780SAaron Smith     break;
10867ac1c780SAaron Smith   case PDB_SymType::Function:
10877ac1c780SAaron Smith   case PDB_SymType::FunctionSig:
10887ac1c780SAaron Smith     can_parse = ((type_mask & eTypeClassFunction) != 0);
10897ac1c780SAaron Smith     break;
10907ac1c780SAaron Smith   case PDB_SymType::PointerType:
10917ac1c780SAaron Smith     can_parse = ((type_mask & (eTypeClassPointer | eTypeClassBlockPointer |
10927ac1c780SAaron Smith                                eTypeClassMemberPointer)) != 0);
10937ac1c780SAaron Smith     break;
10947ac1c780SAaron Smith   case PDB_SymType::Typedef:
10957ac1c780SAaron Smith     can_parse = ((type_mask & eTypeClassTypedef) != 0);
10967ac1c780SAaron Smith     break;
10977ac1c780SAaron Smith   case PDB_SymType::UDT: {
1098e664b5dcSAaron Smith     auto *udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&pdb_symbol);
10997ac1c780SAaron Smith     assert(udt);
11007ac1c780SAaron Smith     can_parse = (udt->getUdtKind() != PDB_UdtType::Interface &&
11017ac1c780SAaron Smith                  ((type_mask & (eTypeClassClass | eTypeClassStruct |
11027ac1c780SAaron Smith                                 eTypeClassUnion)) != 0));
11037ac1c780SAaron Smith   } break;
1104c8316ed2SAaron Smith   default:
1105c8316ed2SAaron Smith     break;
11067ac1c780SAaron Smith   }
11077ac1c780SAaron Smith 
11087ac1c780SAaron Smith   if (can_parse) {
1109e664b5dcSAaron Smith     if (auto *type = ResolveTypeUID(pdb_symbol.getSymIndexId())) {
11107ac1c780SAaron Smith       auto result =
11117ac1c780SAaron Smith           std::find(type_collection.begin(), type_collection.end(), type);
11127ac1c780SAaron Smith       if (result == type_collection.end())
11137ac1c780SAaron Smith         type_collection.push_back(type);
11147ac1c780SAaron Smith     }
11157ac1c780SAaron Smith   }
11167ac1c780SAaron Smith 
1117e664b5dcSAaron Smith   auto results_up = pdb_symbol.findAllChildren();
11187ac1c780SAaron Smith   while (auto symbol_up = results_up->getNext())
1119e664b5dcSAaron Smith     GetTypesForPDBSymbol(*symbol_up, type_mask, type_collection);
11207ac1c780SAaron Smith }
11217ac1c780SAaron Smith 
1122b9c1b51eSKate Stone size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
1123b9c1b51eSKate Stone                                uint32_t type_mask,
1124b9c1b51eSKate Stone                                lldb_private::TypeList &type_list) {
11257ac1c780SAaron Smith   TypeCollection type_collection;
11267ac1c780SAaron Smith   uint32_t old_size = type_list.GetSize();
1127c8316ed2SAaron Smith   CompileUnit *cu =
1128c8316ed2SAaron Smith       sc_scope ? sc_scope->CalculateSymbolContextCompileUnit() : nullptr;
11297ac1c780SAaron Smith   if (cu) {
11307ac1c780SAaron Smith     auto compiland_up = GetPDBCompilandByUID(cu->GetID());
1131e664b5dcSAaron Smith     if (!compiland_up)
1132e664b5dcSAaron Smith       return 0;
1133e664b5dcSAaron Smith     GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection);
11347ac1c780SAaron Smith   } else {
11357ac1c780SAaron Smith     for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) {
11367ac1c780SAaron Smith       auto cu_sp = ParseCompileUnitAtIndex(cu_idx);
1137d5a925f4SAaron Smith       if (cu_sp) {
1138e664b5dcSAaron Smith         if (auto compiland_up = GetPDBCompilandByUID(cu_sp->GetID()))
1139e664b5dcSAaron Smith           GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection);
11407ac1c780SAaron Smith       }
11417ac1c780SAaron Smith     }
11427ac1c780SAaron Smith   }
11437ac1c780SAaron Smith 
11447ac1c780SAaron Smith   for (auto type : type_collection) {
11457ac1c780SAaron Smith     type->GetForwardCompilerType();
11467ac1c780SAaron Smith     type_list.Insert(type->shared_from_this());
11477ac1c780SAaron Smith   }
11487ac1c780SAaron Smith   return type_list.GetSize() - old_size;
114974e08ca0SZachary Turner }
115074e08ca0SZachary Turner 
115174e08ca0SZachary Turner lldb_private::TypeSystem *
1152b9c1b51eSKate Stone SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
1153b9c1b51eSKate Stone   auto type_system =
1154b9c1b51eSKate Stone       m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
115574e08ca0SZachary Turner   if (type_system)
115674e08ca0SZachary Turner     type_system->SetSymbolFile(this);
115774e08ca0SZachary Turner   return type_system;
115874e08ca0SZachary Turner }
115974e08ca0SZachary Turner 
1160b9c1b51eSKate Stone lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace(
1161b9c1b51eSKate Stone     const lldb_private::SymbolContext &sc,
1162b9c1b51eSKate Stone     const lldb_private::ConstString &name,
1163b9c1b51eSKate Stone     const lldb_private::CompilerDeclContext *parent_decl_ctx) {
116474e08ca0SZachary Turner   return lldb_private::CompilerDeclContext();
116574e08ca0SZachary Turner }
116674e08ca0SZachary Turner 
1167b9c1b51eSKate Stone lldb_private::ConstString SymbolFilePDB::GetPluginName() {
116874e08ca0SZachary Turner   static ConstString g_name("pdb");
116974e08ca0SZachary Turner   return g_name;
117074e08ca0SZachary Turner }
117174e08ca0SZachary Turner 
1172b9c1b51eSKate Stone uint32_t SymbolFilePDB::GetPluginVersion() { return 1; }
117374e08ca0SZachary Turner 
1174b9c1b51eSKate Stone IPDBSession &SymbolFilePDB::GetPDBSession() { return *m_session_up; }
1175b9c1b51eSKate Stone 
1176b9c1b51eSKate Stone const IPDBSession &SymbolFilePDB::GetPDBSession() const {
117742dff790SZachary Turner   return *m_session_up;
117842dff790SZachary Turner }
117942dff790SZachary Turner 
1180c8316ed2SAaron Smith lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForUID(uint32_t id,
1181c8316ed2SAaron Smith                                                        uint32_t index) {
118274e08ca0SZachary Turner   auto found_cu = m_comp_units.find(id);
118374e08ca0SZachary Turner   if (found_cu != m_comp_units.end())
118474e08ca0SZachary Turner     return found_cu->second;
118574e08ca0SZachary Turner 
118610a02577SAaron Smith   auto compiland_up = GetPDBCompilandByUID(id);
118710a02577SAaron Smith   if (!compiland_up)
118810a02577SAaron Smith     return CompUnitSP();
118974e08ca0SZachary Turner 
119074e08ca0SZachary Turner   lldb::LanguageType lang;
119110a02577SAaron Smith   auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>();
119274e08ca0SZachary Turner   if (!details)
119374e08ca0SZachary Turner     lang = lldb::eLanguageTypeC_plus_plus;
119474e08ca0SZachary Turner   else
119574e08ca0SZachary Turner     lang = TranslateLanguage(details->getLanguage());
119674e08ca0SZachary Turner 
1197f76fe682SAaron Smith   if (lang == lldb::LanguageType::eLanguageTypeUnknown)
1198f76fe682SAaron Smith     return CompUnitSP();
1199f76fe682SAaron Smith 
1200487b0c6bSAaron Smith   std::string path = compiland_up->getSourceFileFullPath();
1201f76fe682SAaron Smith   if (path.empty())
1202f76fe682SAaron Smith     return CompUnitSP();
1203f76fe682SAaron Smith 
1204b9c1b51eSKate Stone   // Don't support optimized code for now, DebugInfoPDB does not return this
1205b9c1b51eSKate Stone   // information.
1206ad2b63cbSGreg Clayton   LazyBool optimized = eLazyBoolNo;
1207c8316ed2SAaron Smith   auto cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr,
1208c8316ed2SAaron Smith                                              path.c_str(), id, lang, optimized);
120910a02577SAaron Smith 
121010a02577SAaron Smith   if (!cu_sp)
121110a02577SAaron Smith     return CompUnitSP();
121210a02577SAaron Smith 
121310a02577SAaron Smith   m_comp_units.insert(std::make_pair(id, cu_sp));
121410a02577SAaron Smith   if (index == UINT32_MAX)
1215e664b5dcSAaron Smith     GetCompileUnitIndex(*compiland_up, index);
121610a02577SAaron Smith   lldbassert(index != UINT32_MAX);
1217c8316ed2SAaron Smith   m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(index,
1218c8316ed2SAaron Smith                                                                     cu_sp);
121910a02577SAaron Smith   return cu_sp;
122074e08ca0SZachary Turner }
122174e08ca0SZachary Turner 
1222b9c1b51eSKate Stone bool SymbolFilePDB::ParseCompileUnitLineTable(
1223b9c1b51eSKate Stone     const lldb_private::SymbolContext &sc, uint32_t match_line) {
122410a02577SAaron Smith   lldbassert(sc.comp_unit);
122510a02577SAaron Smith 
122610a02577SAaron Smith   auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
122710a02577SAaron Smith   if (!compiland_up)
122810a02577SAaron Smith     return false;
122974e08ca0SZachary Turner 
1230b9c1b51eSKate Stone   // LineEntry needs the *index* of the file into the list of support files
12319d0eb996SAdrian McCarthy   // returned by ParseCompileUnitSupportFiles.  But the underlying SDK gives us
123205097246SAdrian Prantl   // a globally unique idenfitifier in the namespace of the PDB.  So, we have
123305097246SAdrian Prantl   // to do a mapping so that we can hand out indices.
123442dff790SZachary Turner   llvm::DenseMap<uint32_t, uint32_t> index_map;
123510a02577SAaron Smith   BuildSupportFileIdToSupportFileIndexMap(*compiland_up, index_map);
123674e08ca0SZachary Turner   auto line_table = llvm::make_unique<LineTable>(sc.comp_unit);
123774e08ca0SZachary Turner 
123810a02577SAaron Smith   // Find contributions to `compiland` from all source and header files.
123974e08ca0SZachary Turner   std::string path = sc.comp_unit->GetPath();
124010a02577SAaron Smith   auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
124110a02577SAaron Smith   if (!files)
124210a02577SAaron Smith     return false;
124374e08ca0SZachary Turner 
124405097246SAdrian Prantl   // For each source and header file, create a LineSequence for contributions
124505097246SAdrian Prantl   // to the compiland from that file, and add the sequence.
1246b9c1b51eSKate Stone   while (auto file = files->getNext()) {
1247b9c1b51eSKate Stone     std::unique_ptr<LineSequence> sequence(
1248b9c1b51eSKate Stone         line_table->CreateLineSequenceContainer());
124910a02577SAaron Smith     auto lines = m_session_up->findLineNumbers(*compiland_up, *file);
125010a02577SAaron Smith     if (!lines)
125110a02577SAaron Smith       continue;
125274e08ca0SZachary Turner     int entry_count = lines->getChildCount();
125374e08ca0SZachary Turner 
12547e8c7beaSZachary Turner     uint64_t prev_addr;
12557e8c7beaSZachary Turner     uint32_t prev_length;
12567e8c7beaSZachary Turner     uint32_t prev_line;
12577e8c7beaSZachary Turner     uint32_t prev_source_idx;
12587e8c7beaSZachary Turner 
1259b9c1b51eSKate Stone     for (int i = 0; i < entry_count; ++i) {
126074e08ca0SZachary Turner       auto line = lines->getChildAtIndex(i);
126174e08ca0SZachary Turner 
12627e8c7beaSZachary Turner       uint64_t lno = line->getLineNumber();
12637e8c7beaSZachary Turner       uint64_t addr = line->getVirtualAddress();
12647e8c7beaSZachary Turner       uint32_t length = line->getLength();
126574e08ca0SZachary Turner       uint32_t source_id = line->getSourceFileId();
12667e8c7beaSZachary Turner       uint32_t col = line->getColumnNumber();
126774e08ca0SZachary Turner       uint32_t source_idx = index_map[source_id];
126874e08ca0SZachary Turner 
126905097246SAdrian Prantl       // There was a gap between the current entry and the previous entry if
127005097246SAdrian Prantl       // the addresses don't perfectly line up.
12717e8c7beaSZachary Turner       bool is_gap = (i > 0) && (prev_addr + prev_length < addr);
12727e8c7beaSZachary Turner 
1273b9c1b51eSKate Stone       // Before inserting the current entry, insert a terminal entry at the end
12749d0eb996SAdrian McCarthy       // of the previous entry's address range if the current entry resulted in
12759d0eb996SAdrian McCarthy       // a gap from the previous entry.
1276b9c1b51eSKate Stone       if (is_gap && ShouldAddLine(match_line, prev_line, prev_length)) {
1277b9c1b51eSKate Stone         line_table->AppendLineEntryToSequence(
1278b9c1b51eSKate Stone             sequence.get(), prev_addr + prev_length, prev_line, 0,
12797e8c7beaSZachary Turner             prev_source_idx, false, false, false, false, true);
12807e8c7beaSZachary Turner       }
12817e8c7beaSZachary Turner 
1282b9c1b51eSKate Stone       if (ShouldAddLine(match_line, lno, length)) {
12837e8c7beaSZachary Turner         bool is_statement = line->isStatement();
128474e08ca0SZachary Turner         bool is_prologue = false;
128574e08ca0SZachary Turner         bool is_epilogue = false;
1286b9c1b51eSKate Stone         auto func =
1287b9c1b51eSKate Stone             m_session_up->findSymbolByAddress(addr, PDB_SymType::Function);
1288b9c1b51eSKate Stone         if (func) {
128954fd7ff6SZachary Turner           auto prologue = func->findOneChild<PDBSymbolFuncDebugStart>();
129010a02577SAaron Smith           if (prologue)
12917e8c7beaSZachary Turner             is_prologue = (addr == prologue->getVirtualAddress());
129274e08ca0SZachary Turner 
129354fd7ff6SZachary Turner           auto epilogue = func->findOneChild<PDBSymbolFuncDebugEnd>();
129410a02577SAaron Smith           if (epilogue)
12957e8c7beaSZachary Turner             is_epilogue = (addr == epilogue->getVirtualAddress());
12967e8c7beaSZachary Turner         }
129774e08ca0SZachary Turner 
1298b9c1b51eSKate Stone         line_table->AppendLineEntryToSequence(sequence.get(), addr, lno, col,
1299b9c1b51eSKate Stone                                               source_idx, is_statement, false,
13007e8c7beaSZachary Turner                                               is_prologue, is_epilogue, false);
13017e8c7beaSZachary Turner       }
13027e8c7beaSZachary Turner 
13037e8c7beaSZachary Turner       prev_addr = addr;
13047e8c7beaSZachary Turner       prev_length = length;
13057e8c7beaSZachary Turner       prev_line = lno;
13067e8c7beaSZachary Turner       prev_source_idx = source_idx;
13077e8c7beaSZachary Turner     }
13087e8c7beaSZachary Turner 
1309b9c1b51eSKate Stone     if (entry_count > 0 && ShouldAddLine(match_line, prev_line, prev_length)) {
13107e8c7beaSZachary Turner       // The end is always a terminal entry, so insert it regardless.
1311b9c1b51eSKate Stone       line_table->AppendLineEntryToSequence(
1312b9c1b51eSKate Stone           sequence.get(), prev_addr + prev_length, prev_line, 0,
13137e8c7beaSZachary Turner           prev_source_idx, false, false, false, false, true);
131474e08ca0SZachary Turner     }
131574e08ca0SZachary Turner 
13167e8c7beaSZachary Turner     line_table->InsertSequence(sequence.release());
131774e08ca0SZachary Turner   }
131874e08ca0SZachary Turner 
131910a02577SAaron Smith   if (line_table->GetSize()) {
132074e08ca0SZachary Turner     sc.comp_unit->SetLineTable(line_table.release());
132174e08ca0SZachary Turner     return true;
132274e08ca0SZachary Turner   }
132310a02577SAaron Smith   return false;
132410a02577SAaron Smith }
132574e08ca0SZachary Turner 
1326b9c1b51eSKate Stone void SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(
132710a02577SAaron Smith     const PDBSymbolCompiland &compiland,
1328b9c1b51eSKate Stone     llvm::DenseMap<uint32_t, uint32_t> &index_map) const {
132905097246SAdrian Prantl   // This is a hack, but we need to convert the source id into an index into
133005097246SAdrian Prantl   // the support files array.  We don't want to do path comparisons to avoid
13319d0eb996SAdrian McCarthy   // basename / full path issues that may or may not even be a problem, so we
13329d0eb996SAdrian McCarthy   // use the globally unique source file identifiers.  Ideally we could use the
13339d0eb996SAdrian McCarthy   // global identifiers everywhere, but LineEntry currently assumes indices.
133410a02577SAaron Smith   auto source_files = m_session_up->getSourceFilesForCompiland(compiland);
133510a02577SAaron Smith   if (!source_files)
133610a02577SAaron Smith     return;
133774e08ca0SZachary Turner   int index = 0;
133874e08ca0SZachary Turner 
1339b9c1b51eSKate Stone   while (auto file = source_files->getNext()) {
134074e08ca0SZachary Turner     uint32_t source_id = file->getUniqueId();
134174e08ca0SZachary Turner     index_map[source_id] = index++;
134274e08ca0SZachary Turner   }
134374e08ca0SZachary Turner }
13447ac1c780SAaron Smith 
13457ac1c780SAaron Smith lldb::CompUnitSP SymbolFilePDB::GetCompileUnitContainsAddress(
13467ac1c780SAaron Smith     const lldb_private::Address &so_addr) {
13477ac1c780SAaron Smith   lldb::addr_t file_vm_addr = so_addr.GetFileAddress();
1348308e39caSAaron Smith   if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
13497ac1c780SAaron Smith     return nullptr;
13507ac1c780SAaron Smith 
1351308e39caSAaron Smith   // If it is a PDB function's vm addr, this is the first sure bet.
1352308e39caSAaron Smith   if (auto lines =
1353308e39caSAaron Smith           m_session_up->findLineNumbersByAddress(file_vm_addr, /*Length=*/1)) {
1354308e39caSAaron Smith     if (auto first_line = lines->getNext())
1355308e39caSAaron Smith       return ParseCompileUnitForUID(first_line->getCompilandId());
13567ac1c780SAaron Smith   }
13577ac1c780SAaron Smith 
1358308e39caSAaron Smith   // Otherwise we resort to section contributions.
1359308e39caSAaron Smith   if (auto sec_contribs = m_session_up->getSectionContribs()) {
1360308e39caSAaron Smith     while (auto section = sec_contribs->getNext()) {
1361308e39caSAaron Smith       auto va = section->getVirtualAddress();
1362308e39caSAaron Smith       if (file_vm_addr >= va && file_vm_addr < va + section->getLength())
1363308e39caSAaron Smith         return ParseCompileUnitForUID(section->getCompilandId());
1364308e39caSAaron Smith     }
1365308e39caSAaron Smith   }
13667ac1c780SAaron Smith   return nullptr;
13677ac1c780SAaron Smith }
13687ac1c780SAaron Smith 
13697ac1c780SAaron Smith Mangled
1370e664b5dcSAaron Smith SymbolFilePDB::GetMangledForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func) {
13717ac1c780SAaron Smith   Mangled mangled;
1372e664b5dcSAaron Smith   auto func_name = pdb_func.getName();
1373e664b5dcSAaron Smith   auto func_undecorated_name = pdb_func.getUndecoratedName();
13747ac1c780SAaron Smith   std::string func_decorated_name;
13757ac1c780SAaron Smith 
13767ac1c780SAaron Smith   // Seek from public symbols for non-static function's decorated name if any.
13777ac1c780SAaron Smith   // For static functions, they don't have undecorated names and aren't exposed
13787ac1c780SAaron Smith   // in Public Symbols either.
13797ac1c780SAaron Smith   if (!func_undecorated_name.empty()) {
1380c8316ed2SAaron Smith     auto result_up = m_global_scope_up->findChildren(
1381c8316ed2SAaron Smith         PDB_SymType::PublicSymbol, func_undecorated_name,
13827ac1c780SAaron Smith         PDB_NameSearchFlags::NS_UndecoratedName);
13837ac1c780SAaron Smith     if (result_up) {
13847ac1c780SAaron Smith       while (auto symbol_up = result_up->getNext()) {
13857ac1c780SAaron Smith         // For a public symbol, it is unique.
13867ac1c780SAaron Smith         lldbassert(result_up->getChildCount() == 1);
13877ac1c780SAaron Smith         if (auto *pdb_public_sym =
1388c8316ed2SAaron Smith                 llvm::dyn_cast_or_null<PDBSymbolPublicSymbol>(
1389c8316ed2SAaron Smith                     symbol_up.get())) {
13907ac1c780SAaron Smith           if (pdb_public_sym->isFunction()) {
13917ac1c780SAaron Smith             func_decorated_name = pdb_public_sym->getName();
1392f76fe682SAaron Smith             break;
13937ac1c780SAaron Smith           }
13947ac1c780SAaron Smith         }
13957ac1c780SAaron Smith       }
13967ac1c780SAaron Smith     }
13977ac1c780SAaron Smith   }
13987ac1c780SAaron Smith   if (!func_decorated_name.empty()) {
13997ac1c780SAaron Smith     mangled.SetMangledName(ConstString(func_decorated_name));
14007ac1c780SAaron Smith 
14017ac1c780SAaron Smith     // For MSVC, format of C funciton's decorated name depends on calling
14027ac1c780SAaron Smith     // conventon. Unfortunately none of the format is recognized by current
14037ac1c780SAaron Smith     // LLDB. For example, `_purecall` is a __cdecl C function. From PDB,
140405097246SAdrian Prantl     // `__purecall` is retrieved as both its decorated and undecorated name
140505097246SAdrian Prantl     // (using PDBSymbolFunc::getUndecoratedName method). However `__purecall`
140605097246SAdrian Prantl     // string is not treated as mangled in LLDB (neither `?` nor `_Z` prefix).
140705097246SAdrian Prantl     // Mangled::GetDemangledName method will fail internally and caches an
140805097246SAdrian Prantl     // empty string as its undecorated name. So we will face a contradition
140905097246SAdrian Prantl     // here for the same symbol:
14107ac1c780SAaron Smith     //   non-empty undecorated name from PDB
14117ac1c780SAaron Smith     //   empty undecorated name from LLDB
14127ac1c780SAaron Smith     if (!func_undecorated_name.empty() &&
14137ac1c780SAaron Smith         mangled.GetDemangledName(mangled.GuessLanguage()).IsEmpty())
14147ac1c780SAaron Smith       mangled.SetDemangledName(ConstString(func_undecorated_name));
14157ac1c780SAaron Smith 
14167ac1c780SAaron Smith     // LLDB uses several flags to control how a C++ decorated name is
141705097246SAdrian Prantl     // undecorated for MSVC. See `safeUndecorateName` in Class Mangled. So the
141805097246SAdrian Prantl     // yielded name could be different from what we retrieve from
14197ac1c780SAaron Smith     // PDB source unless we also apply same flags in getting undecorated
14207ac1c780SAaron Smith     // name through PDBSymbolFunc::getUndecoratedNameEx method.
14217ac1c780SAaron Smith     if (!func_undecorated_name.empty() &&
14227ac1c780SAaron Smith         mangled.GetDemangledName(mangled.GuessLanguage()) !=
14237ac1c780SAaron Smith             ConstString(func_undecorated_name))
14247ac1c780SAaron Smith       mangled.SetDemangledName(ConstString(func_undecorated_name));
14257ac1c780SAaron Smith   } else if (!func_undecorated_name.empty()) {
14267ac1c780SAaron Smith     mangled.SetDemangledName(ConstString(func_undecorated_name));
14277ac1c780SAaron Smith   } else if (!func_name.empty())
14287ac1c780SAaron Smith     mangled.SetValue(ConstString(func_name), false);
14297ac1c780SAaron Smith 
14307ac1c780SAaron Smith   return mangled;
14317ac1c780SAaron Smith }
14327ac1c780SAaron Smith 
14337ac1c780SAaron Smith bool SymbolFilePDB::DeclContextMatchesThisSymbolFile(
14347ac1c780SAaron Smith     const lldb_private::CompilerDeclContext *decl_ctx) {
14357ac1c780SAaron Smith   if (decl_ctx == nullptr || !decl_ctx->IsValid())
14367ac1c780SAaron Smith     return true;
14377ac1c780SAaron Smith 
14387ac1c780SAaron Smith   TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem();
14397ac1c780SAaron Smith   if (!decl_ctx_type_system)
14407ac1c780SAaron Smith     return false;
14417ac1c780SAaron Smith   TypeSystem *type_system = GetTypeSystemForLanguage(
14427ac1c780SAaron Smith       decl_ctx_type_system->GetMinimumLanguage(nullptr));
14437ac1c780SAaron Smith   if (decl_ctx_type_system == type_system)
14447ac1c780SAaron Smith     return true; // The type systems match, return true
14457ac1c780SAaron Smith 
14467ac1c780SAaron Smith   return false;
14477ac1c780SAaron Smith }
1448