14bb0738eSEd Maste //===-- SymbolFilePDB.cpp ---------------------------------------*- C++ -*-===//
24bb0738eSEd Maste //
34bb0738eSEd Maste // The LLVM Compiler Infrastructure
44bb0738eSEd Maste //
54bb0738eSEd Maste // This file is distributed under the University of Illinois Open Source
64bb0738eSEd Maste // License. See LICENSE.TXT for details.
74bb0738eSEd Maste //
84bb0738eSEd Maste //===----------------------------------------------------------------------===//
94bb0738eSEd Maste
104bb0738eSEd Maste #include "SymbolFilePDB.h"
114bb0738eSEd Maste
12*b5893f02SDimitry Andric #include "PDBASTParser.h"
13*b5893f02SDimitry Andric #include "PDBLocationToDWARFExpression.h"
14*b5893f02SDimitry Andric
154bb0738eSEd Maste #include "clang/Lex/Lexer.h"
164bb0738eSEd Maste
174bb0738eSEd Maste #include "lldb/Core/Module.h"
184bb0738eSEd Maste #include "lldb/Core/PluginManager.h"
194bb0738eSEd Maste #include "lldb/Symbol/ClangASTContext.h"
204bb0738eSEd Maste #include "lldb/Symbol/CompileUnit.h"
214bb0738eSEd Maste #include "lldb/Symbol/LineTable.h"
224bb0738eSEd Maste #include "lldb/Symbol/ObjectFile.h"
234bb0738eSEd Maste #include "lldb/Symbol/SymbolContext.h"
244ba319b5SDimitry Andric #include "lldb/Symbol/SymbolVendor.h"
254ba319b5SDimitry Andric #include "lldb/Symbol/TypeList.h"
264bb0738eSEd Maste #include "lldb/Symbol/TypeMap.h"
274ba319b5SDimitry Andric #include "lldb/Symbol/Variable.h"
2838638513SDimitry Andric #include "lldb/Utility/RegularExpression.h"
294bb0738eSEd Maste
304bb0738eSEd Maste #include "llvm/DebugInfo/PDB/GenericError.h"
3138638513SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBDataStream.h"
324bb0738eSEd Maste #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
334bb0738eSEd Maste #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
344ba319b5SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBSectionContrib.h"
354bb0738eSEd Maste #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
3638638513SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBTable.h"
374bb0738eSEd Maste #include "llvm/DebugInfo/PDB/PDBSymbol.h"
384ba319b5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolBlock.h"
394bb0738eSEd Maste #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
404bb0738eSEd Maste #include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
4138638513SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
424bb0738eSEd Maste #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
434bb0738eSEd Maste #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
444bb0738eSEd Maste #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
454bb0738eSEd Maste #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
464ba319b5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
474bb0738eSEd Maste #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
484bb0738eSEd Maste #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
494bb0738eSEd Maste #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
504bb0738eSEd Maste
514ba319b5SDimitry Andric #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
52*b5893f02SDimitry Andric #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
53*b5893f02SDimitry Andric #include "Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h"
544bb0738eSEd Maste
554bb0738eSEd Maste #include <regex>
564bb0738eSEd Maste
574ba319b5SDimitry Andric using namespace lldb;
584bb0738eSEd Maste using namespace lldb_private;
594bb0738eSEd Maste using namespace llvm::pdb;
604bb0738eSEd Maste
61435933ddSDimitry Andric namespace {
TranslateLanguage(PDB_Lang lang)62435933ddSDimitry Andric lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
63435933ddSDimitry Andric switch (lang) {
644bb0738eSEd Maste case PDB_Lang::Cpp:
654bb0738eSEd Maste return lldb::LanguageType::eLanguageTypeC_plus_plus;
664bb0738eSEd Maste case PDB_Lang::C:
674bb0738eSEd Maste return lldb::LanguageType::eLanguageTypeC;
684bb0738eSEd Maste default:
694bb0738eSEd Maste return lldb::LanguageType::eLanguageTypeUnknown;
704bb0738eSEd Maste }
714bb0738eSEd Maste }
724bb0738eSEd Maste
ShouldAddLine(uint32_t requested_line,uint32_t actual_line,uint32_t addr_length)73435933ddSDimitry Andric bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line,
74435933ddSDimitry Andric uint32_t addr_length) {
75435933ddSDimitry Andric return ((requested_line == 0 || actual_line == requested_line) &&
76435933ddSDimitry Andric addr_length > 0);
774bb0738eSEd Maste }
784ba319b5SDimitry Andric } // namespace
794bb0738eSEd Maste
ShouldUseNativeReader()80*b5893f02SDimitry Andric static bool ShouldUseNativeReader() {
81*b5893f02SDimitry Andric #if defined(_WIN32)
82*b5893f02SDimitry Andric llvm::StringRef use_native = ::getenv("LLDB_USE_NATIVE_PDB_READER");
83*b5893f02SDimitry Andric return use_native.equals_lower("on") || use_native.equals_lower("yes") ||
84*b5893f02SDimitry Andric use_native.equals_lower("1") || use_native.equals_lower("true");
85*b5893f02SDimitry Andric #else
86*b5893f02SDimitry Andric return true;
87*b5893f02SDimitry Andric #endif
88*b5893f02SDimitry Andric }
89*b5893f02SDimitry Andric
Initialize()90435933ddSDimitry Andric void SymbolFilePDB::Initialize() {
91*b5893f02SDimitry Andric if (ShouldUseNativeReader()) {
92*b5893f02SDimitry Andric npdb::SymbolFileNativePDB::Initialize();
93*b5893f02SDimitry Andric } else {
94435933ddSDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(),
95435933ddSDimitry Andric GetPluginDescriptionStatic(), CreateInstance,
964bb0738eSEd Maste DebuggerInitialize);
974bb0738eSEd Maste }
98*b5893f02SDimitry Andric }
994bb0738eSEd Maste
Terminate()100435933ddSDimitry Andric void SymbolFilePDB::Terminate() {
101*b5893f02SDimitry Andric if (ShouldUseNativeReader()) {
102*b5893f02SDimitry Andric npdb::SymbolFileNativePDB::Terminate();
103*b5893f02SDimitry Andric } else {
1044bb0738eSEd Maste PluginManager::UnregisterPlugin(CreateInstance);
1054bb0738eSEd Maste }
106*b5893f02SDimitry Andric }
1074bb0738eSEd Maste
DebuggerInitialize(lldb_private::Debugger & debugger)108435933ddSDimitry Andric void SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger) {}
1094bb0738eSEd Maste
GetPluginNameStatic()110435933ddSDimitry Andric lldb_private::ConstString SymbolFilePDB::GetPluginNameStatic() {
1114bb0738eSEd Maste static ConstString g_name("pdb");
1124bb0738eSEd Maste return g_name;
1134bb0738eSEd Maste }
1144bb0738eSEd Maste
GetPluginDescriptionStatic()115435933ddSDimitry Andric const char *SymbolFilePDB::GetPluginDescriptionStatic() {
1164bb0738eSEd Maste return "Microsoft PDB debug symbol file reader.";
1174bb0738eSEd Maste }
1184bb0738eSEd Maste
1194bb0738eSEd Maste lldb_private::SymbolFile *
CreateInstance(lldb_private::ObjectFile * obj_file)120435933ddSDimitry Andric SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file) {
1214bb0738eSEd Maste return new SymbolFilePDB(obj_file);
1224bb0738eSEd Maste }
1234bb0738eSEd Maste
SymbolFilePDB(lldb_private::ObjectFile * object_file)1244bb0738eSEd Maste SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file)
1254ba319b5SDimitry Andric : SymbolFile(object_file), m_session_up(), m_global_scope_up(),
1264ba319b5SDimitry Andric m_cached_compile_unit_count(0), m_tu_decl_ctx_up() {}
1274bb0738eSEd Maste
~SymbolFilePDB()128435933ddSDimitry Andric SymbolFilePDB::~SymbolFilePDB() {}
1294bb0738eSEd Maste
CalculateAbilities()130435933ddSDimitry Andric uint32_t SymbolFilePDB::CalculateAbilities() {
13138638513SDimitry Andric uint32_t abilities = 0;
13238638513SDimitry Andric if (!m_obj_file)
13338638513SDimitry Andric return 0;
13438638513SDimitry Andric
135435933ddSDimitry Andric if (!m_session_up) {
1364bb0738eSEd Maste // Lazily load and match the PDB file, but only do this once.
1374bb0738eSEd Maste std::string exePath = m_obj_file->GetFileSpec().GetPath();
138435933ddSDimitry Andric auto error = loadDataForEXE(PDB_ReaderType::DIA, llvm::StringRef(exePath),
139435933ddSDimitry Andric m_session_up);
140435933ddSDimitry Andric if (error) {
1414bb0738eSEd Maste llvm::consumeError(std::move(error));
14238638513SDimitry Andric auto module_sp = m_obj_file->GetModule();
14338638513SDimitry Andric if (!module_sp)
14438638513SDimitry Andric return 0;
14538638513SDimitry Andric // See if any symbol file is specified through `--symfile` option.
14638638513SDimitry Andric FileSpec symfile = module_sp->GetSymbolFileFileSpec();
14738638513SDimitry Andric if (!symfile)
14838638513SDimitry Andric return 0;
14938638513SDimitry Andric error = loadDataForPDB(PDB_ReaderType::DIA,
1504ba319b5SDimitry Andric llvm::StringRef(symfile.GetPath()), m_session_up);
15138638513SDimitry Andric if (error) {
15238638513SDimitry Andric llvm::consumeError(std::move(error));
1534bb0738eSEd Maste return 0;
1544bb0738eSEd Maste }
1554bb0738eSEd Maste }
15638638513SDimitry Andric }
1574ba319b5SDimitry Andric if (!m_session_up)
15838638513SDimitry Andric return 0;
15938638513SDimitry Andric
16038638513SDimitry Andric auto enum_tables_up = m_session_up->getEnumTables();
16138638513SDimitry Andric if (!enum_tables_up)
16238638513SDimitry Andric return 0;
16338638513SDimitry Andric while (auto table_up = enum_tables_up->getNext()) {
16438638513SDimitry Andric if (table_up->getItemCount() == 0)
16538638513SDimitry Andric continue;
16638638513SDimitry Andric auto type = table_up->getTableType();
16738638513SDimitry Andric switch (type) {
16838638513SDimitry Andric case PDB_TableType::Symbols:
16938638513SDimitry Andric // This table represents a store of symbols with types listed in
17038638513SDimitry Andric // PDBSym_Type
1714ba319b5SDimitry Andric abilities |= (CompileUnits | Functions | Blocks | GlobalVariables |
1724ba319b5SDimitry Andric LocalVariables | VariableTypes);
17338638513SDimitry Andric break;
17438638513SDimitry Andric case PDB_TableType::LineNumbers:
17538638513SDimitry Andric abilities |= LineTables;
17638638513SDimitry Andric break;
1774ba319b5SDimitry Andric default:
1784ba319b5SDimitry Andric break;
17938638513SDimitry Andric }
18038638513SDimitry Andric }
18138638513SDimitry Andric return abilities;
1824bb0738eSEd Maste }
1834bb0738eSEd Maste
InitializeObject()184435933ddSDimitry Andric void SymbolFilePDB::InitializeObject() {
1854bb0738eSEd Maste lldb::addr_t obj_load_address = m_obj_file->GetFileOffset();
1864ba319b5SDimitry Andric lldbassert(obj_load_address && obj_load_address != LLDB_INVALID_ADDRESS);
1874bb0738eSEd Maste m_session_up->setLoadAddress(obj_load_address);
1884ba319b5SDimitry Andric if (!m_global_scope_up)
1894ba319b5SDimitry Andric m_global_scope_up = m_session_up->getGlobalScope();
1904ba319b5SDimitry Andric lldbassert(m_global_scope_up.get());
1914bb0738eSEd Maste
192435933ddSDimitry Andric TypeSystem *type_system =
193435933ddSDimitry Andric GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
194435933ddSDimitry Andric ClangASTContext *clang_type_system =
195435933ddSDimitry Andric llvm::dyn_cast_or_null<ClangASTContext>(type_system);
1964ba319b5SDimitry Andric lldbassert(clang_type_system);
197435933ddSDimitry Andric m_tu_decl_ctx_up = llvm::make_unique<CompilerDeclContext>(
198435933ddSDimitry Andric type_system, clang_type_system->GetTranslationUnitDecl());
1994bb0738eSEd Maste }
2004bb0738eSEd Maste
GetNumCompileUnits()201435933ddSDimitry Andric uint32_t SymbolFilePDB::GetNumCompileUnits() {
202435933ddSDimitry Andric if (m_cached_compile_unit_count == 0) {
2034ba319b5SDimitry Andric auto compilands = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
2044ba319b5SDimitry Andric if (!compilands)
2054ba319b5SDimitry Andric return 0;
2064ba319b5SDimitry Andric
2074ba319b5SDimitry Andric // The linker could link *.dll (compiland language = LINK), or import
2084ba319b5SDimitry Andric // *.dll. For example, a compiland with name `Import:KERNEL32.dll` could be
2094ba319b5SDimitry Andric // found as a child of the global scope (PDB executable). Usually, such
2104ba319b5SDimitry Andric // compilands contain `thunk` symbols in which we are not interested for
2114ba319b5SDimitry Andric // now. However we still count them in the compiland list. If we perform
2124ba319b5SDimitry Andric // any compiland related activity, like finding symbols through
2134ba319b5SDimitry Andric // llvm::pdb::IPDBSession methods, such compilands will all be searched
2144ba319b5SDimitry Andric // automatically no matter whether we include them or not.
2154bb0738eSEd Maste m_cached_compile_unit_count = compilands->getChildCount();
2164bb0738eSEd Maste
217435933ddSDimitry Andric // The linker can inject an additional "dummy" compilation unit into the
218f678e45dSDimitry Andric // PDB. Ignore this special compile unit for our purposes, if it is there.
219f678e45dSDimitry Andric // It is always the last one.
2204ba319b5SDimitry Andric auto last_compiland_up =
2214ba319b5SDimitry Andric compilands->getChildAtIndex(m_cached_compile_unit_count - 1);
2224ba319b5SDimitry Andric lldbassert(last_compiland_up.get());
2234ba319b5SDimitry Andric std::string name = last_compiland_up->getName();
2244bb0738eSEd Maste if (name == "* Linker *")
2254bb0738eSEd Maste --m_cached_compile_unit_count;
2264bb0738eSEd Maste }
2274bb0738eSEd Maste return m_cached_compile_unit_count;
2284bb0738eSEd Maste }
2294bb0738eSEd Maste
GetCompileUnitIndex(const llvm::pdb::PDBSymbolCompiland & pdb_compiland,uint32_t & index)2304ba319b5SDimitry Andric void SymbolFilePDB::GetCompileUnitIndex(
2314ba319b5SDimitry Andric const llvm::pdb::PDBSymbolCompiland &pdb_compiland, uint32_t &index) {
2324ba319b5SDimitry Andric auto results_up = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
2334ba319b5SDimitry Andric if (!results_up)
2344ba319b5SDimitry Andric return;
2354ba319b5SDimitry Andric auto uid = pdb_compiland.getSymIndexId();
2364ba319b5SDimitry Andric for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) {
2374ba319b5SDimitry Andric auto compiland_up = results_up->getChildAtIndex(cu_idx);
2384ba319b5SDimitry Andric if (!compiland_up)
2394ba319b5SDimitry Andric continue;
2404ba319b5SDimitry Andric if (compiland_up->getSymIndexId() == uid) {
2414ba319b5SDimitry Andric index = cu_idx;
2424ba319b5SDimitry Andric return;
2434ba319b5SDimitry Andric }
2444ba319b5SDimitry Andric }
2454ba319b5SDimitry Andric index = UINT32_MAX;
2464ba319b5SDimitry Andric return;
2474ba319b5SDimitry Andric }
2484ba319b5SDimitry Andric
2494ba319b5SDimitry Andric std::unique_ptr<llvm::pdb::PDBSymbolCompiland>
GetPDBCompilandByUID(uint32_t uid)2504ba319b5SDimitry Andric SymbolFilePDB::GetPDBCompilandByUID(uint32_t uid) {
2514ba319b5SDimitry Andric return m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(uid);
2524ba319b5SDimitry Andric }
2534ba319b5SDimitry Andric
ParseCompileUnitAtIndex(uint32_t index)254435933ddSDimitry Andric lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) {
2554ba319b5SDimitry Andric if (index >= GetNumCompileUnits())
2564ba319b5SDimitry Andric return CompUnitSP();
2574bb0738eSEd Maste
2584ba319b5SDimitry Andric // Assuming we always retrieve same compilands listed in same order through
2594ba319b5SDimitry Andric // `PDBSymbolExe::findAllChildren` method, otherwise using `index` to get a
2604ba319b5SDimitry Andric // compile unit makes no sense.
2614ba319b5SDimitry Andric auto results = m_global_scope_up->findAllChildren<PDBSymbolCompiland>();
2624ba319b5SDimitry Andric if (!results)
2634ba319b5SDimitry Andric return CompUnitSP();
2644ba319b5SDimitry Andric auto compiland_up = results->getChildAtIndex(index);
2654ba319b5SDimitry Andric if (!compiland_up)
2664ba319b5SDimitry Andric return CompUnitSP();
2674ba319b5SDimitry Andric return ParseCompileUnitForUID(compiland_up->getSymIndexId(), index);
2684bb0738eSEd Maste }
2694bb0738eSEd Maste
ParseLanguage(CompileUnit & comp_unit)270*b5893f02SDimitry Andric lldb::LanguageType SymbolFilePDB::ParseLanguage(CompileUnit &comp_unit) {
271*b5893f02SDimitry Andric auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID());
2724ba319b5SDimitry Andric if (!compiland_up)
2734bb0738eSEd Maste return lldb::eLanguageTypeUnknown;
2744ba319b5SDimitry Andric auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>();
2754bb0738eSEd Maste if (!details)
2764bb0738eSEd Maste return lldb::eLanguageTypeUnknown;
2774bb0738eSEd Maste return TranslateLanguage(details->getLanguage());
2784bb0738eSEd Maste }
2794bb0738eSEd Maste
280*b5893f02SDimitry Andric lldb_private::Function *
ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc & pdb_func,CompileUnit & comp_unit)281*b5893f02SDimitry Andric SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc &pdb_func,
282*b5893f02SDimitry Andric CompileUnit &comp_unit) {
283*b5893f02SDimitry Andric if (FunctionSP result = comp_unit.FindFunctionByUID(pdb_func.getSymIndexId()))
284*b5893f02SDimitry Andric return result.get();
2854ba319b5SDimitry Andric
2864ba319b5SDimitry Andric auto file_vm_addr = pdb_func.getVirtualAddress();
2874ba319b5SDimitry Andric if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
2884ba319b5SDimitry Andric return nullptr;
2894ba319b5SDimitry Andric
2904ba319b5SDimitry Andric auto func_length = pdb_func.getLength();
2914ba319b5SDimitry Andric AddressRange func_range =
292*b5893f02SDimitry Andric AddressRange(file_vm_addr, func_length,
293*b5893f02SDimitry Andric GetObjectFile()->GetModule()->GetSectionList());
2944ba319b5SDimitry Andric if (!func_range.GetBaseAddress().IsValid())
2954ba319b5SDimitry Andric return nullptr;
2964ba319b5SDimitry Andric
2974ba319b5SDimitry Andric lldb_private::Type *func_type = ResolveTypeUID(pdb_func.getSymIndexId());
2984ba319b5SDimitry Andric if (!func_type)
2994ba319b5SDimitry Andric return nullptr;
3004ba319b5SDimitry Andric
3014ba319b5SDimitry Andric user_id_t func_type_uid = pdb_func.getSignatureId();
3024ba319b5SDimitry Andric
3034ba319b5SDimitry Andric Mangled mangled = GetMangledForPDBFunc(pdb_func);
3044ba319b5SDimitry Andric
3054ba319b5SDimitry Andric FunctionSP func_sp =
306*b5893f02SDimitry Andric std::make_shared<Function>(&comp_unit, pdb_func.getSymIndexId(),
3074ba319b5SDimitry Andric func_type_uid, mangled, func_type, func_range);
3084ba319b5SDimitry Andric
309*b5893f02SDimitry Andric comp_unit.AddFunction(func_sp);
310*b5893f02SDimitry Andric
311*b5893f02SDimitry Andric TypeSystem *type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
312*b5893f02SDimitry Andric if (!type_system)
313*b5893f02SDimitry Andric return nullptr;
314*b5893f02SDimitry Andric ClangASTContext *clang_type_system =
315*b5893f02SDimitry Andric llvm::dyn_cast_or_null<ClangASTContext>(type_system);
316*b5893f02SDimitry Andric if (!clang_type_system)
317*b5893f02SDimitry Andric return nullptr;
318*b5893f02SDimitry Andric clang_type_system->GetPDBParser()->GetDeclForSymbol(pdb_func);
319*b5893f02SDimitry Andric
3204ba319b5SDimitry Andric return func_sp.get();
3214ba319b5SDimitry Andric }
3224ba319b5SDimitry Andric
ParseFunctions(CompileUnit & comp_unit)323*b5893f02SDimitry Andric size_t SymbolFilePDB::ParseFunctions(CompileUnit &comp_unit) {
3244ba319b5SDimitry Andric size_t func_added = 0;
325*b5893f02SDimitry Andric auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID());
3264ba319b5SDimitry Andric if (!compiland_up)
3274ba319b5SDimitry Andric return 0;
3284ba319b5SDimitry Andric auto results_up = compiland_up->findAllChildren<PDBSymbolFunc>();
3294ba319b5SDimitry Andric if (!results_up)
3304ba319b5SDimitry Andric return 0;
3314ba319b5SDimitry Andric while (auto pdb_func_up = results_up->getNext()) {
332*b5893f02SDimitry Andric auto func_sp = comp_unit.FindFunctionByUID(pdb_func_up->getSymIndexId());
3334ba319b5SDimitry Andric if (!func_sp) {
334*b5893f02SDimitry Andric if (ParseCompileUnitFunctionForPDBFunc(*pdb_func_up, comp_unit))
3354ba319b5SDimitry Andric ++func_added;
3364ba319b5SDimitry Andric }
3374ba319b5SDimitry Andric }
3384ba319b5SDimitry Andric return func_added;
3394bb0738eSEd Maste }
3404bb0738eSEd Maste
ParseLineTable(CompileUnit & comp_unit)341*b5893f02SDimitry Andric bool SymbolFilePDB::ParseLineTable(CompileUnit &comp_unit) {
342*b5893f02SDimitry Andric if (comp_unit.GetLineTable())
3434ba319b5SDimitry Andric return true;
344*b5893f02SDimitry Andric return ParseCompileUnitLineTable(comp_unit, 0);
3454bb0738eSEd Maste }
3464bb0738eSEd Maste
ParseDebugMacros(CompileUnit & comp_unit)347*b5893f02SDimitry Andric bool SymbolFilePDB::ParseDebugMacros(CompileUnit &comp_unit) {
3484bb0738eSEd Maste // PDB doesn't contain information about macros
3494bb0738eSEd Maste return false;
3504bb0738eSEd Maste }
3514bb0738eSEd Maste
ParseSupportFiles(CompileUnit & comp_unit,lldb_private::FileSpecList & support_files)352*b5893f02SDimitry Andric bool SymbolFilePDB::ParseSupportFiles(
353*b5893f02SDimitry Andric CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) {
3544bb0738eSEd Maste
355435933ddSDimitry Andric // In theory this is unnecessary work for us, because all of this information
356f678e45dSDimitry Andric // is easily (and quickly) accessible from DebugInfoPDB, so caching it a
357f678e45dSDimitry Andric // second time seems like a waste. Unfortunately, there's no good way around
358f678e45dSDimitry Andric // this short of a moderate refactor since SymbolVendor depends on being able
359f678e45dSDimitry Andric // to cache this list.
360*b5893f02SDimitry Andric auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID());
3614ba319b5SDimitry Andric if (!compiland_up)
3624bb0738eSEd Maste return false;
3634ba319b5SDimitry Andric auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
3644bb0738eSEd Maste if (!files || files->getChildCount() == 0)
3654bb0738eSEd Maste return false;
3664bb0738eSEd Maste
367435933ddSDimitry Andric while (auto file = files->getNext()) {
368*b5893f02SDimitry Andric FileSpec spec(file->getFileName(), FileSpec::Style::windows);
3694ba319b5SDimitry Andric support_files.AppendIfUnique(spec);
3704bb0738eSEd Maste }
3714ba319b5SDimitry Andric
3724ba319b5SDimitry Andric // LLDB uses the DWARF-like file numeration (one based),
3734ba319b5SDimitry Andric // the zeroth file is the compile unit itself
374*b5893f02SDimitry Andric support_files.Insert(0, comp_unit);
3754ba319b5SDimitry Andric
3764bb0738eSEd Maste return true;
3774bb0738eSEd Maste }
3784bb0738eSEd Maste
ParseImportedModules(const lldb_private::SymbolContext & sc,std::vector<lldb_private::ConstString> & imported_modules)379435933ddSDimitry Andric bool SymbolFilePDB::ParseImportedModules(
380435933ddSDimitry Andric const lldb_private::SymbolContext &sc,
381435933ddSDimitry Andric std::vector<lldb_private::ConstString> &imported_modules) {
3824bb0738eSEd Maste // PDB does not yet support module debug info
3834bb0738eSEd Maste return false;
3844bb0738eSEd Maste }
3854bb0738eSEd Maste
ParseFunctionBlocksForPDBSymbol(uint64_t func_file_vm_addr,const llvm::pdb::PDBSymbol * pdb_symbol,lldb_private::Block * parent_block,bool is_top_parent)3864ba319b5SDimitry Andric static size_t ParseFunctionBlocksForPDBSymbol(
387*b5893f02SDimitry Andric uint64_t func_file_vm_addr, const llvm::pdb::PDBSymbol *pdb_symbol,
388*b5893f02SDimitry Andric lldb_private::Block *parent_block, bool is_top_parent) {
3894ba319b5SDimitry Andric assert(pdb_symbol && parent_block);
3904ba319b5SDimitry Andric
3914ba319b5SDimitry Andric size_t num_added = 0;
3924ba319b5SDimitry Andric switch (pdb_symbol->getSymTag()) {
3934ba319b5SDimitry Andric case PDB_SymType::Block:
3944ba319b5SDimitry Andric case PDB_SymType::Function: {
3954ba319b5SDimitry Andric Block *block = nullptr;
3964ba319b5SDimitry Andric auto &raw_sym = pdb_symbol->getRawSymbol();
3974ba319b5SDimitry Andric if (auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(pdb_symbol)) {
3984ba319b5SDimitry Andric if (pdb_func->hasNoInlineAttribute())
3994ba319b5SDimitry Andric break;
4004ba319b5SDimitry Andric if (is_top_parent)
4014ba319b5SDimitry Andric block = parent_block;
4024ba319b5SDimitry Andric else
4034ba319b5SDimitry Andric break;
4044ba319b5SDimitry Andric } else if (llvm::dyn_cast<PDBSymbolBlock>(pdb_symbol)) {
4054ba319b5SDimitry Andric auto uid = pdb_symbol->getSymIndexId();
4064ba319b5SDimitry Andric if (parent_block->FindBlockByID(uid))
4074ba319b5SDimitry Andric break;
4084ba319b5SDimitry Andric if (raw_sym.getVirtualAddress() < func_file_vm_addr)
4094ba319b5SDimitry Andric break;
4104ba319b5SDimitry Andric
4114ba319b5SDimitry Andric auto block_sp = std::make_shared<Block>(pdb_symbol->getSymIndexId());
4124ba319b5SDimitry Andric parent_block->AddChild(block_sp);
4134ba319b5SDimitry Andric block = block_sp.get();
4144ba319b5SDimitry Andric } else
4154ba319b5SDimitry Andric llvm_unreachable("Unexpected PDB symbol!");
4164ba319b5SDimitry Andric
4174ba319b5SDimitry Andric block->AddRange(Block::Range(
4184ba319b5SDimitry Andric raw_sym.getVirtualAddress() - func_file_vm_addr, raw_sym.getLength()));
4194ba319b5SDimitry Andric block->FinalizeRanges();
4204ba319b5SDimitry Andric ++num_added;
4214ba319b5SDimitry Andric
4224ba319b5SDimitry Andric auto results_up = pdb_symbol->findAllChildren();
4234ba319b5SDimitry Andric if (!results_up)
4244ba319b5SDimitry Andric break;
4254ba319b5SDimitry Andric while (auto symbol_up = results_up->getNext()) {
4264ba319b5SDimitry Andric num_added += ParseFunctionBlocksForPDBSymbol(
427*b5893f02SDimitry Andric func_file_vm_addr, symbol_up.get(), block, false);
4284ba319b5SDimitry Andric }
4294ba319b5SDimitry Andric } break;
4304ba319b5SDimitry Andric default:
4314ba319b5SDimitry Andric break;
4324ba319b5SDimitry Andric }
4334ba319b5SDimitry Andric return num_added;
4344ba319b5SDimitry Andric }
4354ba319b5SDimitry Andric
ParseBlocksRecursive(Function & func)436*b5893f02SDimitry Andric size_t SymbolFilePDB::ParseBlocksRecursive(Function &func) {
4374ba319b5SDimitry Andric size_t num_added = 0;
438*b5893f02SDimitry Andric auto uid = func.GetID();
4394ba319b5SDimitry Andric auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid);
4404ba319b5SDimitry Andric if (!pdb_func_up)
4414ba319b5SDimitry Andric return 0;
442*b5893f02SDimitry Andric Block &parent_block = func.GetBlock(false);
443*b5893f02SDimitry Andric num_added = ParseFunctionBlocksForPDBSymbol(
444*b5893f02SDimitry Andric pdb_func_up->getVirtualAddress(), pdb_func_up.get(), &parent_block, true);
4454ba319b5SDimitry Andric return num_added;
446435933ddSDimitry Andric }
447435933ddSDimitry Andric
ParseTypes(CompileUnit & comp_unit)448*b5893f02SDimitry Andric size_t SymbolFilePDB::ParseTypes(CompileUnit &comp_unit) {
4494ba319b5SDimitry Andric
4504ba319b5SDimitry Andric size_t num_added = 0;
451*b5893f02SDimitry Andric auto compiland = GetPDBCompilandByUID(comp_unit.GetID());
4524ba319b5SDimitry Andric if (!compiland)
4534ba319b5SDimitry Andric return 0;
4544ba319b5SDimitry Andric
4554ba319b5SDimitry Andric auto ParseTypesByTagFn = [&num_added, this](const PDBSymbol &raw_sym) {
4564ba319b5SDimitry Andric std::unique_ptr<IPDBEnumSymbols> results;
4574ba319b5SDimitry Andric PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef,
4584ba319b5SDimitry Andric PDB_SymType::UDT};
4594ba319b5SDimitry Andric for (auto tag : tags_to_search) {
4604ba319b5SDimitry Andric results = raw_sym.findAllChildren(tag);
4614ba319b5SDimitry Andric if (!results || results->getChildCount() == 0)
4624ba319b5SDimitry Andric continue;
4634ba319b5SDimitry Andric while (auto symbol = results->getNext()) {
4644ba319b5SDimitry Andric switch (symbol->getSymTag()) {
4654ba319b5SDimitry Andric case PDB_SymType::Enum:
4664ba319b5SDimitry Andric case PDB_SymType::UDT:
4674ba319b5SDimitry Andric case PDB_SymType::Typedef:
4684ba319b5SDimitry Andric break;
4694ba319b5SDimitry Andric default:
4704ba319b5SDimitry Andric continue;
4714ba319b5SDimitry Andric }
4724ba319b5SDimitry Andric
4734ba319b5SDimitry Andric // This should cause the type to get cached and stored in the `m_types`
4744ba319b5SDimitry Andric // lookup.
475*b5893f02SDimitry Andric if (auto type = ResolveTypeUID(symbol->getSymIndexId())) {
476*b5893f02SDimitry Andric // Resolve the type completely to avoid a completion
477*b5893f02SDimitry Andric // (and so a list change, which causes an iterators invalidation)
478*b5893f02SDimitry Andric // during a TypeList dumping
479*b5893f02SDimitry Andric type->GetFullCompilerType();
4804ba319b5SDimitry Andric ++num_added;
4814ba319b5SDimitry Andric }
4824ba319b5SDimitry Andric }
483*b5893f02SDimitry Andric }
4844ba319b5SDimitry Andric };
4854ba319b5SDimitry Andric
4864ba319b5SDimitry Andric ParseTypesByTagFn(*compiland);
4874ba319b5SDimitry Andric
4884ba319b5SDimitry Andric // Also parse global types particularly coming from this compiland.
4894ba319b5SDimitry Andric // Unfortunately, PDB has no compiland information for each global type. We
4904ba319b5SDimitry Andric // have to parse them all. But ensure we only do this once.
4914ba319b5SDimitry Andric static bool parse_all_global_types = false;
4924ba319b5SDimitry Andric if (!parse_all_global_types) {
4934ba319b5SDimitry Andric ParseTypesByTagFn(*m_global_scope_up);
4944ba319b5SDimitry Andric parse_all_global_types = true;
4954ba319b5SDimitry Andric }
4964ba319b5SDimitry Andric return num_added;
4974bb0738eSEd Maste }
4984bb0738eSEd Maste
4994bb0738eSEd Maste size_t
ParseVariablesForContext(const lldb_private::SymbolContext & sc)500435933ddSDimitry Andric SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) {
5014ba319b5SDimitry Andric if (!sc.comp_unit)
5024ba319b5SDimitry Andric return 0;
5034ba319b5SDimitry Andric
5044ba319b5SDimitry Andric size_t num_added = 0;
5054ba319b5SDimitry Andric if (sc.function) {
5064ba319b5SDimitry Andric auto pdb_func = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(
5074ba319b5SDimitry Andric sc.function->GetID());
5084ba319b5SDimitry Andric if (!pdb_func)
5094ba319b5SDimitry Andric return 0;
5104ba319b5SDimitry Andric
5114ba319b5SDimitry Andric num_added += ParseVariables(sc, *pdb_func);
5124ba319b5SDimitry Andric sc.function->GetBlock(false).SetDidParseVariables(true, true);
5134ba319b5SDimitry Andric } else if (sc.comp_unit) {
5144ba319b5SDimitry Andric auto compiland = GetPDBCompilandByUID(sc.comp_unit->GetID());
5154ba319b5SDimitry Andric if (!compiland)
5164ba319b5SDimitry Andric return 0;
5174ba319b5SDimitry Andric
5184ba319b5SDimitry Andric if (sc.comp_unit->GetVariableList(false))
5194ba319b5SDimitry Andric return 0;
5204ba319b5SDimitry Andric
5214ba319b5SDimitry Andric auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
5224ba319b5SDimitry Andric if (results && results->getChildCount()) {
5234ba319b5SDimitry Andric while (auto result = results->getNext()) {
524*b5893f02SDimitry Andric auto cu_id = GetCompilandId(*result);
5254ba319b5SDimitry Andric // FIXME: We are not able to determine variable's compile unit.
5264ba319b5SDimitry Andric if (cu_id == 0)
5274ba319b5SDimitry Andric continue;
5284ba319b5SDimitry Andric
5294ba319b5SDimitry Andric if (cu_id == sc.comp_unit->GetID())
5304ba319b5SDimitry Andric num_added += ParseVariables(sc, *result);
5314ba319b5SDimitry Andric }
5324ba319b5SDimitry Andric }
5334ba319b5SDimitry Andric
5344ba319b5SDimitry Andric // FIXME: A `file static` or `global constant` variable appears both in
5354ba319b5SDimitry Andric // compiland's children and global scope's children with unexpectedly
5364ba319b5SDimitry Andric // different symbol's Id making it ambiguous.
5374ba319b5SDimitry Andric
5384ba319b5SDimitry Andric // FIXME: 'local constant', for example, const char var[] = "abc", declared
5394ba319b5SDimitry Andric // in a function scope, can't be found in PDB.
5404ba319b5SDimitry Andric
5414ba319b5SDimitry Andric // Parse variables in this compiland.
5424ba319b5SDimitry Andric num_added += ParseVariables(sc, *compiland);
5434ba319b5SDimitry Andric }
5444ba319b5SDimitry Andric
5454ba319b5SDimitry Andric return num_added;
5464bb0738eSEd Maste }
5474bb0738eSEd Maste
ResolveTypeUID(lldb::user_id_t type_uid)548435933ddSDimitry Andric lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
5494bb0738eSEd Maste auto find_result = m_types.find(type_uid);
5504bb0738eSEd Maste if (find_result != m_types.end())
5514bb0738eSEd Maste return find_result->second.get();
5524bb0738eSEd Maste
553435933ddSDimitry Andric TypeSystem *type_system =
554435933ddSDimitry Andric GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
555435933ddSDimitry Andric ClangASTContext *clang_type_system =
556435933ddSDimitry Andric llvm::dyn_cast_or_null<ClangASTContext>(type_system);
5574bb0738eSEd Maste if (!clang_type_system)
5584bb0738eSEd Maste return nullptr;
559*b5893f02SDimitry Andric PDBASTParser *pdb = clang_type_system->GetPDBParser();
5604bb0738eSEd Maste if (!pdb)
5614bb0738eSEd Maste return nullptr;
5624bb0738eSEd Maste
5634bb0738eSEd Maste auto pdb_type = m_session_up->getSymbolById(type_uid);
5644bb0738eSEd Maste if (pdb_type == nullptr)
5654bb0738eSEd Maste return nullptr;
5664bb0738eSEd Maste
5674bb0738eSEd Maste lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type);
5684ba319b5SDimitry Andric if (result) {
5694bb0738eSEd Maste m_types.insert(std::make_pair(type_uid, result));
5704ba319b5SDimitry Andric auto type_list = GetTypeList();
5714ba319b5SDimitry Andric if (type_list)
5724ba319b5SDimitry Andric type_list->Insert(result);
5734ba319b5SDimitry Andric }
5744bb0738eSEd Maste return result.get();
5754bb0738eSEd Maste }
5764bb0738eSEd Maste
GetDynamicArrayInfoForUID(lldb::user_id_t type_uid,const lldb_private::ExecutionContext * exe_ctx)577*b5893f02SDimitry Andric llvm::Optional<SymbolFile::ArrayInfo> SymbolFilePDB::GetDynamicArrayInfoForUID(
578*b5893f02SDimitry Andric lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
579*b5893f02SDimitry Andric return llvm::None;
580*b5893f02SDimitry Andric }
581*b5893f02SDimitry Andric
CompleteType(lldb_private::CompilerType & compiler_type)582435933ddSDimitry Andric bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) {
583*b5893f02SDimitry Andric std::lock_guard<std::recursive_mutex> guard(
584*b5893f02SDimitry Andric GetObjectFile()->GetModule()->GetMutex());
585*b5893f02SDimitry Andric
586*b5893f02SDimitry Andric ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
587*b5893f02SDimitry Andric GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
588*b5893f02SDimitry Andric if (!clang_ast_ctx)
5894bb0738eSEd Maste return false;
590*b5893f02SDimitry Andric
591*b5893f02SDimitry Andric PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
592*b5893f02SDimitry Andric if (!pdb)
593*b5893f02SDimitry Andric return false;
594*b5893f02SDimitry Andric
595*b5893f02SDimitry Andric return pdb->CompleteTypeFromPDB(compiler_type);
5964bb0738eSEd Maste }
5974bb0738eSEd Maste
GetDeclForUID(lldb::user_id_t uid)598435933ddSDimitry Andric lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) {
599*b5893f02SDimitry Andric ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
600*b5893f02SDimitry Andric GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
601*b5893f02SDimitry Andric if (!clang_ast_ctx)
602*b5893f02SDimitry Andric return CompilerDecl();
603*b5893f02SDimitry Andric
604*b5893f02SDimitry Andric PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
605*b5893f02SDimitry Andric if (!pdb)
606*b5893f02SDimitry Andric return CompilerDecl();
607*b5893f02SDimitry Andric
608*b5893f02SDimitry Andric auto symbol = m_session_up->getSymbolById(uid);
609*b5893f02SDimitry Andric if (!symbol)
610*b5893f02SDimitry Andric return CompilerDecl();
611*b5893f02SDimitry Andric
612*b5893f02SDimitry Andric auto decl = pdb->GetDeclForSymbol(*symbol);
613*b5893f02SDimitry Andric if (!decl)
614*b5893f02SDimitry Andric return CompilerDecl();
615*b5893f02SDimitry Andric
616*b5893f02SDimitry Andric return CompilerDecl(clang_ast_ctx, decl);
6174bb0738eSEd Maste }
6184bb0738eSEd Maste
6194bb0738eSEd Maste lldb_private::CompilerDeclContext
GetDeclContextForUID(lldb::user_id_t uid)620435933ddSDimitry Andric SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) {
621*b5893f02SDimitry Andric ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
622*b5893f02SDimitry Andric GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
623*b5893f02SDimitry Andric if (!clang_ast_ctx)
624*b5893f02SDimitry Andric return CompilerDeclContext();
625*b5893f02SDimitry Andric
626*b5893f02SDimitry Andric PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
627*b5893f02SDimitry Andric if (!pdb)
628*b5893f02SDimitry Andric return CompilerDeclContext();
629*b5893f02SDimitry Andric
630*b5893f02SDimitry Andric auto symbol = m_session_up->getSymbolById(uid);
631*b5893f02SDimitry Andric if (!symbol)
632*b5893f02SDimitry Andric return CompilerDeclContext();
633*b5893f02SDimitry Andric
634*b5893f02SDimitry Andric auto decl_context = pdb->GetDeclContextForSymbol(*symbol);
635*b5893f02SDimitry Andric if (!decl_context)
636*b5893f02SDimitry Andric return GetDeclContextContainingUID(uid);
637*b5893f02SDimitry Andric
638*b5893f02SDimitry Andric return CompilerDeclContext(clang_ast_ctx, decl_context);
6394bb0738eSEd Maste }
6404bb0738eSEd Maste
6414bb0738eSEd Maste lldb_private::CompilerDeclContext
GetDeclContextContainingUID(lldb::user_id_t uid)642435933ddSDimitry Andric SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
643*b5893f02SDimitry Andric ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
644*b5893f02SDimitry Andric GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
645*b5893f02SDimitry Andric if (!clang_ast_ctx)
646*b5893f02SDimitry Andric return CompilerDeclContext();
647*b5893f02SDimitry Andric
648*b5893f02SDimitry Andric PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
649*b5893f02SDimitry Andric if (!pdb)
650*b5893f02SDimitry Andric return CompilerDeclContext();
651*b5893f02SDimitry Andric
652*b5893f02SDimitry Andric auto symbol = m_session_up->getSymbolById(uid);
653*b5893f02SDimitry Andric if (!symbol)
654*b5893f02SDimitry Andric return CompilerDeclContext();
655*b5893f02SDimitry Andric
656*b5893f02SDimitry Andric auto decl_context = pdb->GetDeclContextContainingSymbol(*symbol);
657*b5893f02SDimitry Andric assert(decl_context);
658*b5893f02SDimitry Andric
659*b5893f02SDimitry Andric return CompilerDeclContext(clang_ast_ctx, decl_context);
6604bb0738eSEd Maste }
6614bb0738eSEd Maste
ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx)662435933ddSDimitry Andric void SymbolFilePDB::ParseDeclsForContext(
663*b5893f02SDimitry Andric lldb_private::CompilerDeclContext decl_ctx) {
664*b5893f02SDimitry Andric ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
665*b5893f02SDimitry Andric GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
666*b5893f02SDimitry Andric if (!clang_ast_ctx)
667*b5893f02SDimitry Andric return;
668*b5893f02SDimitry Andric
669*b5893f02SDimitry Andric PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
670*b5893f02SDimitry Andric if (!pdb)
671*b5893f02SDimitry Andric return;
672*b5893f02SDimitry Andric
673*b5893f02SDimitry Andric pdb->ParseDeclsForDeclContext(
674*b5893f02SDimitry Andric static_cast<clang::DeclContext *>(decl_ctx.GetOpaqueDeclContext()));
675*b5893f02SDimitry Andric }
6764bb0738eSEd Maste
6774bb0738eSEd Maste uint32_t
ResolveSymbolContext(const lldb_private::Address & so_addr,SymbolContextItem resolve_scope,lldb_private::SymbolContext & sc)678435933ddSDimitry Andric SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
679*b5893f02SDimitry Andric SymbolContextItem resolve_scope,
680435933ddSDimitry Andric lldb_private::SymbolContext &sc) {
6814ba319b5SDimitry Andric uint32_t resolved_flags = 0;
6824ba319b5SDimitry Andric if (resolve_scope & eSymbolContextCompUnit ||
6834ba319b5SDimitry Andric resolve_scope & eSymbolContextVariable ||
6844ba319b5SDimitry Andric resolve_scope & eSymbolContextFunction ||
6854ba319b5SDimitry Andric resolve_scope & eSymbolContextBlock ||
6864ba319b5SDimitry Andric resolve_scope & eSymbolContextLineEntry) {
6874ba319b5SDimitry Andric auto cu_sp = GetCompileUnitContainsAddress(so_addr);
6884ba319b5SDimitry Andric if (!cu_sp) {
6894ba319b5SDimitry Andric if (resolved_flags | eSymbolContextVariable) {
6904ba319b5SDimitry Andric // TODO: Resolve variables
6914ba319b5SDimitry Andric }
6924ba319b5SDimitry Andric return 0;
6934ba319b5SDimitry Andric }
6944ba319b5SDimitry Andric sc.comp_unit = cu_sp.get();
6954ba319b5SDimitry Andric resolved_flags |= eSymbolContextCompUnit;
6964ba319b5SDimitry Andric lldbassert(sc.module_sp == cu_sp->GetModule());
6974ba319b5SDimitry Andric }
6984ba319b5SDimitry Andric
699*b5893f02SDimitry Andric if (resolve_scope & eSymbolContextFunction ||
700*b5893f02SDimitry Andric resolve_scope & eSymbolContextBlock) {
7014ba319b5SDimitry Andric addr_t file_vm_addr = so_addr.GetFileAddress();
7024ba319b5SDimitry Andric auto symbol_up =
7034ba319b5SDimitry Andric m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::Function);
7044ba319b5SDimitry Andric if (symbol_up) {
7054ba319b5SDimitry Andric auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get());
7064ba319b5SDimitry Andric assert(pdb_func);
7074ba319b5SDimitry Andric auto func_uid = pdb_func->getSymIndexId();
7084ba319b5SDimitry Andric sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get();
7094ba319b5SDimitry Andric if (sc.function == nullptr)
710*b5893f02SDimitry Andric sc.function =
711*b5893f02SDimitry Andric ParseCompileUnitFunctionForPDBFunc(*pdb_func, *sc.comp_unit);
7124ba319b5SDimitry Andric if (sc.function) {
7134ba319b5SDimitry Andric resolved_flags |= eSymbolContextFunction;
7144ba319b5SDimitry Andric if (resolve_scope & eSymbolContextBlock) {
715*b5893f02SDimitry Andric auto block_symbol = m_session_up->findSymbolByAddress(
716*b5893f02SDimitry Andric file_vm_addr, PDB_SymType::Block);
717*b5893f02SDimitry Andric auto block_id = block_symbol ? block_symbol->getSymIndexId()
718*b5893f02SDimitry Andric : sc.function->GetID();
719*b5893f02SDimitry Andric sc.block = sc.function->GetBlock(true).FindBlockByID(block_id);
7204ba319b5SDimitry Andric if (sc.block)
7214ba319b5SDimitry Andric resolved_flags |= eSymbolContextBlock;
7224ba319b5SDimitry Andric }
7234ba319b5SDimitry Andric }
7244ba319b5SDimitry Andric }
7254ba319b5SDimitry Andric }
7264ba319b5SDimitry Andric
7274ba319b5SDimitry Andric if (resolve_scope & eSymbolContextLineEntry) {
7284ba319b5SDimitry Andric if (auto *line_table = sc.comp_unit->GetLineTable()) {
7294ba319b5SDimitry Andric Address addr(so_addr);
7304ba319b5SDimitry Andric if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
7314ba319b5SDimitry Andric resolved_flags |= eSymbolContextLineEntry;
7324ba319b5SDimitry Andric }
7334ba319b5SDimitry Andric }
7344ba319b5SDimitry Andric
7354ba319b5SDimitry Andric return resolved_flags;
7364bb0738eSEd Maste }
7374bb0738eSEd Maste
ResolveSymbolContext(const lldb_private::FileSpec & file_spec,uint32_t line,bool check_inlines,SymbolContextItem resolve_scope,lldb_private::SymbolContextList & sc_list)738435933ddSDimitry Andric uint32_t SymbolFilePDB::ResolveSymbolContext(
739435933ddSDimitry Andric const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines,
740*b5893f02SDimitry Andric SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) {
7414ba319b5SDimitry Andric const size_t old_size = sc_list.GetSize();
742435933ddSDimitry Andric if (resolve_scope & lldb::eSymbolContextCompUnit) {
743435933ddSDimitry Andric // Locate all compilation units with line numbers referencing the specified
744f678e45dSDimitry Andric // file. For example, if `file_spec` is <vector>, then this should return
745f678e45dSDimitry Andric // all source files and header files that reference <vector>, either
746f678e45dSDimitry Andric // directly or indirectly.
747435933ddSDimitry Andric auto compilands = m_session_up->findCompilandsForSourceFile(
748435933ddSDimitry Andric file_spec.GetPath(), PDB_NameSearchFlags::NS_CaseInsensitive);
7494bb0738eSEd Maste
7504ba319b5SDimitry Andric if (!compilands)
7514ba319b5SDimitry Andric return 0;
7524ba319b5SDimitry Andric
753f678e45dSDimitry Andric // For each one, either find its previously parsed data or parse it afresh
754f678e45dSDimitry Andric // and add it to the symbol context list.
755435933ddSDimitry Andric while (auto compiland = compilands->getNext()) {
7564ba319b5SDimitry Andric // If we're not checking inlines, then don't add line information for
7574ba319b5SDimitry Andric // this file unless the FileSpec matches. For inline functions, we don't
7584ba319b5SDimitry Andric // have to match the FileSpec since they could be defined in headers
7594ba319b5SDimitry Andric // other than file specified in FileSpec.
760435933ddSDimitry Andric if (!check_inlines) {
7614ba319b5SDimitry Andric std::string source_file = compiland->getSourceFileFullPath();
7624ba319b5SDimitry Andric if (source_file.empty())
7634ba319b5SDimitry Andric continue;
764*b5893f02SDimitry Andric FileSpec this_spec(source_file, FileSpec::Style::windows);
7654ba319b5SDimitry Andric bool need_full_match = !file_spec.GetDirectory().IsEmpty();
7664ba319b5SDimitry Andric if (FileSpec::Compare(file_spec, this_spec, need_full_match) != 0)
7674bb0738eSEd Maste continue;
7684bb0738eSEd Maste }
7694bb0738eSEd Maste
7704bb0738eSEd Maste SymbolContext sc;
7714ba319b5SDimitry Andric auto cu = ParseCompileUnitForUID(compiland->getSymIndexId());
7724ba319b5SDimitry Andric if (!cu)
7734ba319b5SDimitry Andric continue;
7744bb0738eSEd Maste sc.comp_unit = cu.get();
7754bb0738eSEd Maste sc.module_sp = cu->GetModule();
7764bb0738eSEd Maste
777435933ddSDimitry Andric // If we were asked to resolve line entries, add all entries to the line
778f678e45dSDimitry Andric // table that match the requested line (or all lines if `line` == 0).
7794ba319b5SDimitry Andric if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock |
7804ba319b5SDimitry Andric eSymbolContextLineEntry)) {
781*b5893f02SDimitry Andric bool has_line_table = ParseCompileUnitLineTable(*sc.comp_unit, line);
7824ba319b5SDimitry Andric
7834ba319b5SDimitry Andric if ((resolve_scope & eSymbolContextLineEntry) && !has_line_table) {
7844ba319b5SDimitry Andric // The query asks for line entries, but we can't get them for the
7854ba319b5SDimitry Andric // compile unit. This is not normal for `line` = 0. So just assert
7864ba319b5SDimitry Andric // it.
7874ba319b5SDimitry Andric assert(line && "Couldn't get all line entries!\n");
7884ba319b5SDimitry Andric
7894ba319b5SDimitry Andric // Current compiland does not have the requested line. Search next.
7904ba319b5SDimitry Andric continue;
7914ba319b5SDimitry Andric }
7924ba319b5SDimitry Andric
7934ba319b5SDimitry Andric if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) {
7944ba319b5SDimitry Andric if (!has_line_table)
7954ba319b5SDimitry Andric continue;
7964ba319b5SDimitry Andric
7974ba319b5SDimitry Andric auto *line_table = sc.comp_unit->GetLineTable();
7984ba319b5SDimitry Andric lldbassert(line_table);
7994ba319b5SDimitry Andric
8004ba319b5SDimitry Andric uint32_t num_line_entries = line_table->GetSize();
8014ba319b5SDimitry Andric // Skip the terminal line entry.
8024ba319b5SDimitry Andric --num_line_entries;
8034ba319b5SDimitry Andric
8044ba319b5SDimitry Andric // If `line `!= 0, see if we can resolve function for each line entry
8054ba319b5SDimitry Andric // in the line table.
8064ba319b5SDimitry Andric for (uint32_t line_idx = 0; line && line_idx < num_line_entries;
8074ba319b5SDimitry Andric ++line_idx) {
8084ba319b5SDimitry Andric if (!line_table->GetLineEntryAtIndex(line_idx, sc.line_entry))
8094ba319b5SDimitry Andric continue;
8104ba319b5SDimitry Andric
8114ba319b5SDimitry Andric auto file_vm_addr =
8124ba319b5SDimitry Andric sc.line_entry.range.GetBaseAddress().GetFileAddress();
8134ba319b5SDimitry Andric if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
8144ba319b5SDimitry Andric continue;
8154ba319b5SDimitry Andric
8164ba319b5SDimitry Andric auto symbol_up = m_session_up->findSymbolByAddress(
8174ba319b5SDimitry Andric file_vm_addr, PDB_SymType::Function);
8184ba319b5SDimitry Andric if (symbol_up) {
8194ba319b5SDimitry Andric auto func_uid = symbol_up->getSymIndexId();
8204ba319b5SDimitry Andric sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get();
8214ba319b5SDimitry Andric if (sc.function == nullptr) {
8224ba319b5SDimitry Andric auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get());
8234ba319b5SDimitry Andric assert(pdb_func);
824*b5893f02SDimitry Andric sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func,
825*b5893f02SDimitry Andric *sc.comp_unit);
8264ba319b5SDimitry Andric }
8274ba319b5SDimitry Andric if (sc.function && (resolve_scope & eSymbolContextBlock)) {
8284ba319b5SDimitry Andric Block &block = sc.function->GetBlock(true);
8294ba319b5SDimitry Andric sc.block = block.FindBlockByID(sc.function->GetID());
8304bb0738eSEd Maste }
8314bb0738eSEd Maste }
8324ba319b5SDimitry Andric sc_list.Append(sc);
8334ba319b5SDimitry Andric }
8344ba319b5SDimitry Andric } else if (has_line_table) {
8354ba319b5SDimitry Andric // We can parse line table for the compile unit. But no query to
8364ba319b5SDimitry Andric // resolve function or block. We append `sc` to the list anyway.
8374ba319b5SDimitry Andric sc_list.Append(sc);
8384ba319b5SDimitry Andric }
8394ba319b5SDimitry Andric } else {
8404ba319b5SDimitry Andric // No query for line entry, function or block. But we have a valid
8414ba319b5SDimitry Andric // compile unit, append `sc` to the list.
8424ba319b5SDimitry Andric sc_list.Append(sc);
8434ba319b5SDimitry Andric }
8444ba319b5SDimitry Andric }
8454ba319b5SDimitry Andric }
8464ba319b5SDimitry Andric return sc_list.GetSize() - old_size;
8474ba319b5SDimitry Andric }
8484ba319b5SDimitry Andric
GetMangledForPDBData(const PDBSymbolData & pdb_data)8494ba319b5SDimitry Andric std::string SymbolFilePDB::GetMangledForPDBData(const PDBSymbolData &pdb_data) {
850*b5893f02SDimitry Andric // Cache public names at first
851*b5893f02SDimitry Andric if (m_public_names.empty())
852*b5893f02SDimitry Andric if (auto result_up =
853*b5893f02SDimitry Andric m_global_scope_up->findAllChildren(PDB_SymType::PublicSymbol))
854*b5893f02SDimitry Andric while (auto symbol_up = result_up->getNext())
855*b5893f02SDimitry Andric if (auto addr = symbol_up->getRawSymbol().getVirtualAddress())
856*b5893f02SDimitry Andric m_public_names[addr] = symbol_up->getRawSymbol().getName();
8574ba319b5SDimitry Andric
858*b5893f02SDimitry Andric // Look up the name in the cache
859*b5893f02SDimitry Andric return m_public_names.lookup(pdb_data.getVirtualAddress());
8604ba319b5SDimitry Andric }
8614ba319b5SDimitry Andric
ParseVariableForPDBData(const lldb_private::SymbolContext & sc,const llvm::pdb::PDBSymbolData & pdb_data)8624ba319b5SDimitry Andric VariableSP SymbolFilePDB::ParseVariableForPDBData(
8634ba319b5SDimitry Andric const lldb_private::SymbolContext &sc,
8644ba319b5SDimitry Andric const llvm::pdb::PDBSymbolData &pdb_data) {
8654ba319b5SDimitry Andric VariableSP var_sp;
8664ba319b5SDimitry Andric uint32_t var_uid = pdb_data.getSymIndexId();
8674ba319b5SDimitry Andric auto result = m_variables.find(var_uid);
8684ba319b5SDimitry Andric if (result != m_variables.end())
8694ba319b5SDimitry Andric return result->second;
8704ba319b5SDimitry Andric
8714ba319b5SDimitry Andric ValueType scope = eValueTypeInvalid;
8724ba319b5SDimitry Andric bool is_static_member = false;
8734ba319b5SDimitry Andric bool is_external = false;
8744ba319b5SDimitry Andric bool is_artificial = false;
8754ba319b5SDimitry Andric
8764ba319b5SDimitry Andric switch (pdb_data.getDataKind()) {
8774ba319b5SDimitry Andric case PDB_DataKind::Global:
8784ba319b5SDimitry Andric scope = eValueTypeVariableGlobal;
8794ba319b5SDimitry Andric is_external = true;
8804ba319b5SDimitry Andric break;
8814ba319b5SDimitry Andric case PDB_DataKind::Local:
8824ba319b5SDimitry Andric scope = eValueTypeVariableLocal;
8834ba319b5SDimitry Andric break;
8844ba319b5SDimitry Andric case PDB_DataKind::FileStatic:
8854ba319b5SDimitry Andric scope = eValueTypeVariableStatic;
8864ba319b5SDimitry Andric break;
8874ba319b5SDimitry Andric case PDB_DataKind::StaticMember:
8884ba319b5SDimitry Andric is_static_member = true;
8894ba319b5SDimitry Andric scope = eValueTypeVariableStatic;
8904ba319b5SDimitry Andric break;
8914ba319b5SDimitry Andric case PDB_DataKind::Member:
8924ba319b5SDimitry Andric scope = eValueTypeVariableStatic;
8934ba319b5SDimitry Andric break;
8944ba319b5SDimitry Andric case PDB_DataKind::Param:
8954ba319b5SDimitry Andric scope = eValueTypeVariableArgument;
8964ba319b5SDimitry Andric break;
8974ba319b5SDimitry Andric case PDB_DataKind::Constant:
8984ba319b5SDimitry Andric scope = eValueTypeConstResult;
8994ba319b5SDimitry Andric break;
9004ba319b5SDimitry Andric default:
9014ba319b5SDimitry Andric break;
9024ba319b5SDimitry Andric }
9034ba319b5SDimitry Andric
9044ba319b5SDimitry Andric switch (pdb_data.getLocationType()) {
9054ba319b5SDimitry Andric case PDB_LocType::TLS:
9064ba319b5SDimitry Andric scope = eValueTypeVariableThreadLocal;
9074ba319b5SDimitry Andric break;
9084ba319b5SDimitry Andric case PDB_LocType::RegRel: {
9094ba319b5SDimitry Andric // It is a `this` pointer.
9104ba319b5SDimitry Andric if (pdb_data.getDataKind() == PDB_DataKind::ObjectPtr) {
9114ba319b5SDimitry Andric scope = eValueTypeVariableArgument;
9124ba319b5SDimitry Andric is_artificial = true;
9134ba319b5SDimitry Andric }
9144ba319b5SDimitry Andric } break;
9154ba319b5SDimitry Andric default:
9164ba319b5SDimitry Andric break;
9174ba319b5SDimitry Andric }
9184ba319b5SDimitry Andric
9194ba319b5SDimitry Andric Declaration decl;
9204ba319b5SDimitry Andric if (!is_artificial && !pdb_data.isCompilerGenerated()) {
9214ba319b5SDimitry Andric if (auto lines = pdb_data.getLineNumbers()) {
9224ba319b5SDimitry Andric if (auto first_line = lines->getNext()) {
9234ba319b5SDimitry Andric uint32_t src_file_id = first_line->getSourceFileId();
9244ba319b5SDimitry Andric auto src_file = m_session_up->getSourceFileById(src_file_id);
9254ba319b5SDimitry Andric if (src_file) {
926*b5893f02SDimitry Andric FileSpec spec(src_file->getFileName());
9274ba319b5SDimitry Andric decl.SetFile(spec);
9284ba319b5SDimitry Andric decl.SetColumn(first_line->getColumnNumber());
9294ba319b5SDimitry Andric decl.SetLine(first_line->getLineNumber());
9304ba319b5SDimitry Andric }
9314ba319b5SDimitry Andric }
9324ba319b5SDimitry Andric }
9334ba319b5SDimitry Andric }
9344ba319b5SDimitry Andric
9354ba319b5SDimitry Andric Variable::RangeList ranges;
9364ba319b5SDimitry Andric SymbolContextScope *context_scope = sc.comp_unit;
9374ba319b5SDimitry Andric if (scope == eValueTypeVariableLocal) {
9384ba319b5SDimitry Andric if (sc.function) {
9394ba319b5SDimitry Andric context_scope = sc.function->GetBlock(true).FindBlockByID(
940*b5893f02SDimitry Andric pdb_data.getLexicalParentId());
9414ba319b5SDimitry Andric if (context_scope == nullptr)
9424ba319b5SDimitry Andric context_scope = sc.function;
9434ba319b5SDimitry Andric }
9444ba319b5SDimitry Andric }
9454ba319b5SDimitry Andric
9464ba319b5SDimitry Andric SymbolFileTypeSP type_sp =
9474ba319b5SDimitry Andric std::make_shared<SymbolFileType>(*this, pdb_data.getTypeId());
9484ba319b5SDimitry Andric
9494ba319b5SDimitry Andric auto var_name = pdb_data.getName();
9504ba319b5SDimitry Andric auto mangled = GetMangledForPDBData(pdb_data);
9514ba319b5SDimitry Andric auto mangled_cstr = mangled.empty() ? nullptr : mangled.c_str();
9524ba319b5SDimitry Andric
9534ba319b5SDimitry Andric bool is_constant;
9544ba319b5SDimitry Andric DWARFExpression location = ConvertPDBLocationToDWARFExpression(
9554ba319b5SDimitry Andric GetObjectFile()->GetModule(), pdb_data, is_constant);
9564ba319b5SDimitry Andric
9574ba319b5SDimitry Andric var_sp = std::make_shared<Variable>(
9584ba319b5SDimitry Andric var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope,
9594ba319b5SDimitry Andric ranges, &decl, location, is_external, is_artificial, is_static_member);
9604ba319b5SDimitry Andric var_sp->SetLocationIsConstantValueData(is_constant);
9614ba319b5SDimitry Andric
9624ba319b5SDimitry Andric m_variables.insert(std::make_pair(var_uid, var_sp));
9634ba319b5SDimitry Andric return var_sp;
9644ba319b5SDimitry Andric }
9654ba319b5SDimitry Andric
9664ba319b5SDimitry Andric size_t
ParseVariables(const lldb_private::SymbolContext & sc,const llvm::pdb::PDBSymbol & pdb_symbol,lldb_private::VariableList * variable_list)9674ba319b5SDimitry Andric SymbolFilePDB::ParseVariables(const lldb_private::SymbolContext &sc,
9684ba319b5SDimitry Andric const llvm::pdb::PDBSymbol &pdb_symbol,
9694ba319b5SDimitry Andric lldb_private::VariableList *variable_list) {
9704ba319b5SDimitry Andric size_t num_added = 0;
9714ba319b5SDimitry Andric
9724ba319b5SDimitry Andric if (auto pdb_data = llvm::dyn_cast<PDBSymbolData>(&pdb_symbol)) {
9734ba319b5SDimitry Andric VariableListSP local_variable_list_sp;
9744ba319b5SDimitry Andric
9754ba319b5SDimitry Andric auto result = m_variables.find(pdb_data->getSymIndexId());
9764ba319b5SDimitry Andric if (result != m_variables.end()) {
9774ba319b5SDimitry Andric if (variable_list)
9784ba319b5SDimitry Andric variable_list->AddVariableIfUnique(result->second);
9794ba319b5SDimitry Andric } else {
9804ba319b5SDimitry Andric // Prepare right VariableList for this variable.
9814ba319b5SDimitry Andric if (auto lexical_parent = pdb_data->getLexicalParent()) {
9824ba319b5SDimitry Andric switch (lexical_parent->getSymTag()) {
9834ba319b5SDimitry Andric case PDB_SymType::Exe:
9844ba319b5SDimitry Andric assert(sc.comp_unit);
9854ba319b5SDimitry Andric LLVM_FALLTHROUGH;
9864ba319b5SDimitry Andric case PDB_SymType::Compiland: {
9874ba319b5SDimitry Andric if (sc.comp_unit) {
9884ba319b5SDimitry Andric local_variable_list_sp = sc.comp_unit->GetVariableList(false);
9894ba319b5SDimitry Andric if (!local_variable_list_sp) {
9904ba319b5SDimitry Andric local_variable_list_sp = std::make_shared<VariableList>();
9914ba319b5SDimitry Andric sc.comp_unit->SetVariableList(local_variable_list_sp);
9924ba319b5SDimitry Andric }
9934ba319b5SDimitry Andric }
9944ba319b5SDimitry Andric } break;
9954ba319b5SDimitry Andric case PDB_SymType::Block:
9964ba319b5SDimitry Andric case PDB_SymType::Function: {
9974ba319b5SDimitry Andric if (sc.function) {
9984ba319b5SDimitry Andric Block *block = sc.function->GetBlock(true).FindBlockByID(
9994ba319b5SDimitry Andric lexical_parent->getSymIndexId());
10004ba319b5SDimitry Andric if (block) {
10014ba319b5SDimitry Andric local_variable_list_sp = block->GetBlockVariableList(false);
10024ba319b5SDimitry Andric if (!local_variable_list_sp) {
10034ba319b5SDimitry Andric local_variable_list_sp = std::make_shared<VariableList>();
10044ba319b5SDimitry Andric block->SetVariableList(local_variable_list_sp);
10054ba319b5SDimitry Andric }
10064ba319b5SDimitry Andric }
10074ba319b5SDimitry Andric }
10084ba319b5SDimitry Andric } break;
10094ba319b5SDimitry Andric default:
10104ba319b5SDimitry Andric break;
10114ba319b5SDimitry Andric }
10124ba319b5SDimitry Andric }
10134ba319b5SDimitry Andric
10144ba319b5SDimitry Andric if (local_variable_list_sp) {
10154ba319b5SDimitry Andric if (auto var_sp = ParseVariableForPDBData(sc, *pdb_data)) {
10164ba319b5SDimitry Andric local_variable_list_sp->AddVariableIfUnique(var_sp);
10174ba319b5SDimitry Andric if (variable_list)
10184ba319b5SDimitry Andric variable_list->AddVariableIfUnique(var_sp);
10194ba319b5SDimitry Andric ++num_added;
1020*b5893f02SDimitry Andric PDBASTParser *ast = GetPDBAstParser();
1021*b5893f02SDimitry Andric if (ast)
1022*b5893f02SDimitry Andric ast->GetDeclForSymbol(*pdb_data);
10234ba319b5SDimitry Andric }
10244ba319b5SDimitry Andric }
10254ba319b5SDimitry Andric }
10264ba319b5SDimitry Andric }
10274ba319b5SDimitry Andric
10284ba319b5SDimitry Andric if (auto results = pdb_symbol.findAllChildren()) {
10294ba319b5SDimitry Andric while (auto result = results->getNext())
10304ba319b5SDimitry Andric num_added += ParseVariables(sc, *result, variable_list);
10314ba319b5SDimitry Andric }
10324ba319b5SDimitry Andric
10334ba319b5SDimitry Andric return num_added;
10344bb0738eSEd Maste }
10354bb0738eSEd Maste
FindGlobalVariables(const lldb_private::ConstString & name,const lldb_private::CompilerDeclContext * parent_decl_ctx,uint32_t max_matches,lldb_private::VariableList & variables)1036435933ddSDimitry Andric uint32_t SymbolFilePDB::FindGlobalVariables(
1037435933ddSDimitry Andric const lldb_private::ConstString &name,
10384ba319b5SDimitry Andric const lldb_private::CompilerDeclContext *parent_decl_ctx,
1039435933ddSDimitry Andric uint32_t max_matches, lldb_private::VariableList &variables) {
10404ba319b5SDimitry Andric if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
10414ba319b5SDimitry Andric return 0;
10424ba319b5SDimitry Andric if (name.IsEmpty())
10434ba319b5SDimitry Andric return 0;
10444ba319b5SDimitry Andric
1045*b5893f02SDimitry Andric auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
10464ba319b5SDimitry Andric if (!results)
10474ba319b5SDimitry Andric return 0;
10484ba319b5SDimitry Andric
10494ba319b5SDimitry Andric uint32_t matches = 0;
10504ba319b5SDimitry Andric size_t old_size = variables.GetSize();
10514ba319b5SDimitry Andric while (auto result = results->getNext()) {
10524ba319b5SDimitry Andric auto pdb_data = llvm::dyn_cast<PDBSymbolData>(result.get());
10534ba319b5SDimitry Andric if (max_matches > 0 && matches >= max_matches)
10544ba319b5SDimitry Andric break;
10554ba319b5SDimitry Andric
10564ba319b5SDimitry Andric SymbolContext sc;
10574ba319b5SDimitry Andric sc.module_sp = m_obj_file->GetModule();
10584ba319b5SDimitry Andric lldbassert(sc.module_sp.get());
10594ba319b5SDimitry Andric
1060*b5893f02SDimitry Andric if (!name.GetStringRef().equals(
1061*b5893f02SDimitry Andric MSVCUndecoratedNameParser::DropScope(pdb_data->getName())))
1062*b5893f02SDimitry Andric continue;
1063*b5893f02SDimitry Andric
1064*b5893f02SDimitry Andric sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get();
10654ba319b5SDimitry Andric // FIXME: We are not able to determine the compile unit.
10664ba319b5SDimitry Andric if (sc.comp_unit == nullptr)
10674ba319b5SDimitry Andric continue;
10684ba319b5SDimitry Andric
1069*b5893f02SDimitry Andric if (parent_decl_ctx && GetDeclContextContainingUID(
1070*b5893f02SDimitry Andric result->getSymIndexId()) != *parent_decl_ctx)
1071*b5893f02SDimitry Andric continue;
1072*b5893f02SDimitry Andric
10734ba319b5SDimitry Andric ParseVariables(sc, *pdb_data, &variables);
10744ba319b5SDimitry Andric matches = variables.GetSize() - old_size;
10754ba319b5SDimitry Andric }
10764ba319b5SDimitry Andric
10774ba319b5SDimitry Andric return matches;
10784bb0738eSEd Maste }
10794bb0738eSEd Maste
10804bb0738eSEd Maste uint32_t
FindGlobalVariables(const lldb_private::RegularExpression & regex,uint32_t max_matches,lldb_private::VariableList & variables)1081435933ddSDimitry Andric SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression ®ex,
10824ba319b5SDimitry Andric uint32_t max_matches,
1083435933ddSDimitry Andric lldb_private::VariableList &variables) {
10844ba319b5SDimitry Andric if (!regex.IsValid())
10854ba319b5SDimitry Andric return 0;
10864ba319b5SDimitry Andric auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
10874ba319b5SDimitry Andric if (!results)
10884ba319b5SDimitry Andric return 0;
10894ba319b5SDimitry Andric
10904ba319b5SDimitry Andric uint32_t matches = 0;
10914ba319b5SDimitry Andric size_t old_size = variables.GetSize();
10924ba319b5SDimitry Andric while (auto pdb_data = results->getNext()) {
10934ba319b5SDimitry Andric if (max_matches > 0 && matches >= max_matches)
10944ba319b5SDimitry Andric break;
10954ba319b5SDimitry Andric
10964ba319b5SDimitry Andric auto var_name = pdb_data->getName();
10974ba319b5SDimitry Andric if (var_name.empty())
10984ba319b5SDimitry Andric continue;
10994ba319b5SDimitry Andric if (!regex.Execute(var_name))
11004ba319b5SDimitry Andric continue;
11014ba319b5SDimitry Andric SymbolContext sc;
11024ba319b5SDimitry Andric sc.module_sp = m_obj_file->GetModule();
11034ba319b5SDimitry Andric lldbassert(sc.module_sp.get());
11044ba319b5SDimitry Andric
1105*b5893f02SDimitry Andric sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get();
11064ba319b5SDimitry Andric // FIXME: We are not able to determine the compile unit.
11074ba319b5SDimitry Andric if (sc.comp_unit == nullptr)
11084ba319b5SDimitry Andric continue;
11094ba319b5SDimitry Andric
11104ba319b5SDimitry Andric ParseVariables(sc, *pdb_data, &variables);
11114ba319b5SDimitry Andric matches = variables.GetSize() - old_size;
11124ba319b5SDimitry Andric }
11134ba319b5SDimitry Andric
11144ba319b5SDimitry Andric return matches;
11154ba319b5SDimitry Andric }
11164ba319b5SDimitry Andric
ResolveFunction(const llvm::pdb::PDBSymbolFunc & pdb_func,bool include_inlines,lldb_private::SymbolContextList & sc_list)11174ba319b5SDimitry Andric bool SymbolFilePDB::ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func,
11184ba319b5SDimitry Andric bool include_inlines,
11194ba319b5SDimitry Andric lldb_private::SymbolContextList &sc_list) {
11204ba319b5SDimitry Andric lldb_private::SymbolContext sc;
11214ba319b5SDimitry Andric sc.comp_unit = ParseCompileUnitForUID(pdb_func.getCompilandId()).get();
11224ba319b5SDimitry Andric if (!sc.comp_unit)
11234ba319b5SDimitry Andric return false;
11244ba319b5SDimitry Andric sc.module_sp = sc.comp_unit->GetModule();
1125*b5893f02SDimitry Andric sc.function = ParseCompileUnitFunctionForPDBFunc(pdb_func, *sc.comp_unit);
11264ba319b5SDimitry Andric if (!sc.function)
11274ba319b5SDimitry Andric return false;
11284ba319b5SDimitry Andric
11294ba319b5SDimitry Andric sc_list.Append(sc);
11304ba319b5SDimitry Andric return true;
11314ba319b5SDimitry Andric }
11324ba319b5SDimitry Andric
ResolveFunction(uint32_t uid,bool include_inlines,lldb_private::SymbolContextList & sc_list)11334ba319b5SDimitry Andric bool SymbolFilePDB::ResolveFunction(uint32_t uid, bool include_inlines,
11344ba319b5SDimitry Andric lldb_private::SymbolContextList &sc_list) {
11354ba319b5SDimitry Andric auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid);
11364ba319b5SDimitry Andric if (!pdb_func_up && !(include_inlines && pdb_func_up->hasInlineAttribute()))
11374ba319b5SDimitry Andric return false;
11384ba319b5SDimitry Andric return ResolveFunction(*pdb_func_up, include_inlines, sc_list);
11394ba319b5SDimitry Andric }
11404ba319b5SDimitry Andric
CacheFunctionNames()11414ba319b5SDimitry Andric void SymbolFilePDB::CacheFunctionNames() {
11424ba319b5SDimitry Andric if (!m_func_full_names.IsEmpty())
11434ba319b5SDimitry Andric return;
11444ba319b5SDimitry Andric
11454ba319b5SDimitry Andric std::map<uint64_t, uint32_t> addr_ids;
11464ba319b5SDimitry Andric
11474ba319b5SDimitry Andric if (auto results_up = m_global_scope_up->findAllChildren<PDBSymbolFunc>()) {
11484ba319b5SDimitry Andric while (auto pdb_func_up = results_up->getNext()) {
11494ba319b5SDimitry Andric if (pdb_func_up->isCompilerGenerated())
11504ba319b5SDimitry Andric continue;
11514ba319b5SDimitry Andric
11524ba319b5SDimitry Andric auto name = pdb_func_up->getName();
11534ba319b5SDimitry Andric auto demangled_name = pdb_func_up->getUndecoratedName();
11544ba319b5SDimitry Andric if (name.empty() && demangled_name.empty())
11554ba319b5SDimitry Andric continue;
11564ba319b5SDimitry Andric
11574ba319b5SDimitry Andric auto uid = pdb_func_up->getSymIndexId();
11584ba319b5SDimitry Andric if (!demangled_name.empty() && pdb_func_up->getVirtualAddress())
11594ba319b5SDimitry Andric addr_ids.insert(std::make_pair(pdb_func_up->getVirtualAddress(), uid));
11604ba319b5SDimitry Andric
11614ba319b5SDimitry Andric if (auto parent = pdb_func_up->getClassParent()) {
11624ba319b5SDimitry Andric
11634ba319b5SDimitry Andric // PDB have symbols for class/struct methods or static methods in Enum
11644ba319b5SDimitry Andric // Class. We won't bother to check if the parent is UDT or Enum here.
11654ba319b5SDimitry Andric m_func_method_names.Append(ConstString(name), uid);
11664ba319b5SDimitry Andric
11674ba319b5SDimitry Andric // To search a method name, like NS::Class:MemberFunc, LLDB searches
11684ba319b5SDimitry Andric // its base name, i.e. MemberFunc by default. Since PDBSymbolFunc does
11694ba319b5SDimitry Andric // not have inforamtion of this, we extract base names and cache them
11704ba319b5SDimitry Andric // by our own effort.
1171*b5893f02SDimitry Andric llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(name);
11724ba319b5SDimitry Andric if (!basename.empty())
11734ba319b5SDimitry Andric m_func_base_names.Append(ConstString(basename), uid);
11744ba319b5SDimitry Andric else {
11754ba319b5SDimitry Andric m_func_base_names.Append(ConstString(name), uid);
11764ba319b5SDimitry Andric }
11774ba319b5SDimitry Andric
11784ba319b5SDimitry Andric if (!demangled_name.empty())
11794ba319b5SDimitry Andric m_func_full_names.Append(ConstString(demangled_name), uid);
11804ba319b5SDimitry Andric
11814ba319b5SDimitry Andric } else {
11824ba319b5SDimitry Andric // Handle not-method symbols.
11834ba319b5SDimitry Andric
1184*b5893f02SDimitry Andric // The function name might contain namespace, or its lexical scope.
1185*b5893f02SDimitry Andric llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(name);
1186*b5893f02SDimitry Andric if (!basename.empty())
1187*b5893f02SDimitry Andric m_func_base_names.Append(ConstString(basename), uid);
1188*b5893f02SDimitry Andric else
11894ba319b5SDimitry Andric m_func_base_names.Append(ConstString(name), uid);
11904ba319b5SDimitry Andric
11914ba319b5SDimitry Andric if (name == "main") {
11924ba319b5SDimitry Andric m_func_full_names.Append(ConstString(name), uid);
11934ba319b5SDimitry Andric
11944ba319b5SDimitry Andric if (!demangled_name.empty() && name != demangled_name) {
11954ba319b5SDimitry Andric m_func_full_names.Append(ConstString(demangled_name), uid);
11964ba319b5SDimitry Andric m_func_base_names.Append(ConstString(demangled_name), uid);
11974ba319b5SDimitry Andric }
11984ba319b5SDimitry Andric } else if (!demangled_name.empty()) {
11994ba319b5SDimitry Andric m_func_full_names.Append(ConstString(demangled_name), uid);
12004ba319b5SDimitry Andric } else {
12014ba319b5SDimitry Andric m_func_full_names.Append(ConstString(name), uid);
12024ba319b5SDimitry Andric }
12034ba319b5SDimitry Andric }
12044ba319b5SDimitry Andric }
12054ba319b5SDimitry Andric }
12064ba319b5SDimitry Andric
12074ba319b5SDimitry Andric if (auto results_up =
12084ba319b5SDimitry Andric m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>()) {
12094ba319b5SDimitry Andric while (auto pub_sym_up = results_up->getNext()) {
12104ba319b5SDimitry Andric if (!pub_sym_up->isFunction())
12114ba319b5SDimitry Andric continue;
12124ba319b5SDimitry Andric auto name = pub_sym_up->getName();
12134ba319b5SDimitry Andric if (name.empty())
12144ba319b5SDimitry Andric continue;
12154ba319b5SDimitry Andric
12164ba319b5SDimitry Andric if (CPlusPlusLanguage::IsCPPMangledName(name.c_str())) {
12174ba319b5SDimitry Andric auto vm_addr = pub_sym_up->getVirtualAddress();
12184ba319b5SDimitry Andric
12194ba319b5SDimitry Andric // PDB public symbol has mangled name for its associated function.
12204ba319b5SDimitry Andric if (vm_addr && addr_ids.find(vm_addr) != addr_ids.end()) {
12214ba319b5SDimitry Andric // Cache mangled name.
12224ba319b5SDimitry Andric m_func_full_names.Append(ConstString(name), addr_ids[vm_addr]);
12234ba319b5SDimitry Andric }
12244ba319b5SDimitry Andric }
12254ba319b5SDimitry Andric }
12264ba319b5SDimitry Andric }
12274ba319b5SDimitry Andric // Sort them before value searching is working properly
12284ba319b5SDimitry Andric m_func_full_names.Sort();
12294ba319b5SDimitry Andric m_func_full_names.SizeToFit();
12304ba319b5SDimitry Andric m_func_method_names.Sort();
12314ba319b5SDimitry Andric m_func_method_names.SizeToFit();
12324ba319b5SDimitry Andric m_func_base_names.Sort();
12334ba319b5SDimitry Andric m_func_base_names.SizeToFit();
1234435933ddSDimitry Andric }
1235435933ddSDimitry Andric
FindFunctions(const lldb_private::ConstString & name,const lldb_private::CompilerDeclContext * parent_decl_ctx,FunctionNameType name_type_mask,bool include_inlines,bool append,lldb_private::SymbolContextList & sc_list)1236435933ddSDimitry Andric uint32_t SymbolFilePDB::FindFunctions(
1237435933ddSDimitry Andric const lldb_private::ConstString &name,
1238435933ddSDimitry Andric const lldb_private::CompilerDeclContext *parent_decl_ctx,
1239*b5893f02SDimitry Andric FunctionNameType name_type_mask, bool include_inlines, bool append,
1240435933ddSDimitry Andric lldb_private::SymbolContextList &sc_list) {
12414ba319b5SDimitry Andric if (!append)
12424ba319b5SDimitry Andric sc_list.Clear();
12434ba319b5SDimitry Andric lldbassert((name_type_mask & eFunctionNameTypeAuto) == 0);
12444ba319b5SDimitry Andric
12454ba319b5SDimitry Andric if (name_type_mask == eFunctionNameTypeNone)
12464ba319b5SDimitry Andric return 0;
12474ba319b5SDimitry Andric if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
12484ba319b5SDimitry Andric return 0;
12494ba319b5SDimitry Andric if (name.IsEmpty())
12504ba319b5SDimitry Andric return 0;
12514ba319b5SDimitry Andric
12524ba319b5SDimitry Andric auto old_size = sc_list.GetSize();
12534ba319b5SDimitry Andric if (name_type_mask & eFunctionNameTypeFull ||
12544ba319b5SDimitry Andric name_type_mask & eFunctionNameTypeBase ||
12554ba319b5SDimitry Andric name_type_mask & eFunctionNameTypeMethod) {
12564ba319b5SDimitry Andric CacheFunctionNames();
12574ba319b5SDimitry Andric
12584ba319b5SDimitry Andric std::set<uint32_t> resolved_ids;
1259*b5893f02SDimitry Andric auto ResolveFn = [this, &name, parent_decl_ctx, include_inlines, &sc_list,
1260*b5893f02SDimitry Andric &resolved_ids](UniqueCStringMap<uint32_t> &Names) {
12614ba319b5SDimitry Andric std::vector<uint32_t> ids;
1262*b5893f02SDimitry Andric if (!Names.GetValues(name, ids))
1263*b5893f02SDimitry Andric return;
1264*b5893f02SDimitry Andric
1265*b5893f02SDimitry Andric for (uint32_t id : ids) {
1266*b5893f02SDimitry Andric if (resolved_ids.find(id) != resolved_ids.end())
1267*b5893f02SDimitry Andric continue;
1268*b5893f02SDimitry Andric
1269*b5893f02SDimitry Andric if (parent_decl_ctx &&
1270*b5893f02SDimitry Andric GetDeclContextContainingUID(id) != *parent_decl_ctx)
1271*b5893f02SDimitry Andric continue;
1272*b5893f02SDimitry Andric
12734ba319b5SDimitry Andric if (ResolveFunction(id, include_inlines, sc_list))
12744ba319b5SDimitry Andric resolved_ids.insert(id);
12754ba319b5SDimitry Andric }
12764ba319b5SDimitry Andric };
12774ba319b5SDimitry Andric if (name_type_mask & eFunctionNameTypeFull) {
12784ba319b5SDimitry Andric ResolveFn(m_func_full_names);
1279*b5893f02SDimitry Andric ResolveFn(m_func_base_names);
1280*b5893f02SDimitry Andric ResolveFn(m_func_method_names);
12814ba319b5SDimitry Andric }
12824ba319b5SDimitry Andric if (name_type_mask & eFunctionNameTypeBase) {
12834ba319b5SDimitry Andric ResolveFn(m_func_base_names);
12844ba319b5SDimitry Andric }
12854ba319b5SDimitry Andric if (name_type_mask & eFunctionNameTypeMethod) {
12864ba319b5SDimitry Andric ResolveFn(m_func_method_names);
12874ba319b5SDimitry Andric }
12884ba319b5SDimitry Andric }
12894ba319b5SDimitry Andric return sc_list.GetSize() - old_size;
12904bb0738eSEd Maste }
12914bb0738eSEd Maste
12924bb0738eSEd Maste uint32_t
FindFunctions(const lldb_private::RegularExpression & regex,bool include_inlines,bool append,lldb_private::SymbolContextList & sc_list)1293435933ddSDimitry Andric SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression ®ex,
1294435933ddSDimitry Andric bool include_inlines, bool append,
1295435933ddSDimitry Andric lldb_private::SymbolContextList &sc_list) {
12964ba319b5SDimitry Andric if (!append)
12974ba319b5SDimitry Andric sc_list.Clear();
12984ba319b5SDimitry Andric if (!regex.IsValid())
12994ba319b5SDimitry Andric return 0;
13004ba319b5SDimitry Andric
13014ba319b5SDimitry Andric auto old_size = sc_list.GetSize();
13024ba319b5SDimitry Andric CacheFunctionNames();
13034ba319b5SDimitry Andric
13044ba319b5SDimitry Andric std::set<uint32_t> resolved_ids;
13054ba319b5SDimitry Andric auto ResolveFn = [®ex, include_inlines, &sc_list, &resolved_ids,
13064ba319b5SDimitry Andric this](UniqueCStringMap<uint32_t> &Names) {
13074ba319b5SDimitry Andric std::vector<uint32_t> ids;
13084ba319b5SDimitry Andric if (Names.GetValues(regex, ids)) {
13094ba319b5SDimitry Andric for (auto id : ids) {
13104ba319b5SDimitry Andric if (resolved_ids.find(id) == resolved_ids.end())
13114ba319b5SDimitry Andric if (ResolveFunction(id, include_inlines, sc_list))
13124ba319b5SDimitry Andric resolved_ids.insert(id);
13134ba319b5SDimitry Andric }
13144ba319b5SDimitry Andric }
13154ba319b5SDimitry Andric };
13164ba319b5SDimitry Andric ResolveFn(m_func_full_names);
13174ba319b5SDimitry Andric ResolveFn(m_func_base_names);
13184ba319b5SDimitry Andric
13194ba319b5SDimitry Andric return sc_list.GetSize() - old_size;
13204bb0738eSEd Maste }
13214bb0738eSEd Maste
GetMangledNamesForFunction(const std::string & scope_qualified_name,std::vector<lldb_private::ConstString> & mangled_names)1322435933ddSDimitry Andric void SymbolFilePDB::GetMangledNamesForFunction(
1323435933ddSDimitry Andric const std::string &scope_qualified_name,
1324435933ddSDimitry Andric std::vector<lldb_private::ConstString> &mangled_names) {}
13254bb0738eSEd Maste
AddSymbols(lldb_private::Symtab & symtab)1326*b5893f02SDimitry Andric void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) {
1327*b5893f02SDimitry Andric std::set<lldb::addr_t> sym_addresses;
1328*b5893f02SDimitry Andric for (size_t i = 0; i < symtab.GetNumSymbols(); i++)
1329*b5893f02SDimitry Andric sym_addresses.insert(symtab.SymbolAtIndex(i)->GetFileAddress());
1330*b5893f02SDimitry Andric
1331*b5893f02SDimitry Andric auto results = m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>();
1332*b5893f02SDimitry Andric if (!results)
1333*b5893f02SDimitry Andric return;
1334*b5893f02SDimitry Andric
1335*b5893f02SDimitry Andric auto section_list = m_obj_file->GetSectionList();
1336*b5893f02SDimitry Andric if (!section_list)
1337*b5893f02SDimitry Andric return;
1338*b5893f02SDimitry Andric
1339*b5893f02SDimitry Andric while (auto pub_symbol = results->getNext()) {
1340*b5893f02SDimitry Andric auto section_idx = pub_symbol->getAddressSection() - 1;
1341*b5893f02SDimitry Andric if (section_idx >= section_list->GetSize())
1342*b5893f02SDimitry Andric continue;
1343*b5893f02SDimitry Andric
1344*b5893f02SDimitry Andric auto section = section_list->GetSectionAtIndex(section_idx);
1345*b5893f02SDimitry Andric if (!section)
1346*b5893f02SDimitry Andric continue;
1347*b5893f02SDimitry Andric
1348*b5893f02SDimitry Andric auto offset = pub_symbol->getAddressOffset();
1349*b5893f02SDimitry Andric
1350*b5893f02SDimitry Andric auto file_addr = section->GetFileAddress() + offset;
1351*b5893f02SDimitry Andric if (sym_addresses.find(file_addr) != sym_addresses.end())
1352*b5893f02SDimitry Andric continue;
1353*b5893f02SDimitry Andric sym_addresses.insert(file_addr);
1354*b5893f02SDimitry Andric
1355*b5893f02SDimitry Andric auto size = pub_symbol->getLength();
1356*b5893f02SDimitry Andric symtab.AddSymbol(
1357*b5893f02SDimitry Andric Symbol(pub_symbol->getSymIndexId(), // symID
1358*b5893f02SDimitry Andric pub_symbol->getName().c_str(), // name
1359*b5893f02SDimitry Andric true, // name_is_mangled
1360*b5893f02SDimitry Andric pub_symbol->isCode() ? eSymbolTypeCode : eSymbolTypeData, // type
1361*b5893f02SDimitry Andric true, // external
1362*b5893f02SDimitry Andric false, // is_debug
1363*b5893f02SDimitry Andric false, // is_trampoline
1364*b5893f02SDimitry Andric false, // is_artificial
1365*b5893f02SDimitry Andric section, // section_sp
1366*b5893f02SDimitry Andric offset, // value
1367*b5893f02SDimitry Andric size, // size
1368*b5893f02SDimitry Andric size != 0, // size_is_valid
1369*b5893f02SDimitry Andric false, // contains_linker_annotations
1370*b5893f02SDimitry Andric 0 // flags
1371*b5893f02SDimitry Andric ));
1372*b5893f02SDimitry Andric }
1373*b5893f02SDimitry Andric
1374*b5893f02SDimitry Andric symtab.CalculateSymbolSizes();
1375*b5893f02SDimitry Andric symtab.Finalize();
1376*b5893f02SDimitry Andric }
1377*b5893f02SDimitry Andric
FindTypes(const lldb_private::ConstString & name,const lldb_private::CompilerDeclContext * parent_decl_ctx,bool append,uint32_t max_matches,llvm::DenseSet<lldb_private::SymbolFile * > & searched_symbol_files,lldb_private::TypeMap & types)1378435933ddSDimitry Andric uint32_t SymbolFilePDB::FindTypes(
1379435933ddSDimitry Andric const lldb_private::ConstString &name,
1380435933ddSDimitry Andric const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append,
1381435933ddSDimitry Andric uint32_t max_matches,
13824bb0738eSEd Maste llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
1383435933ddSDimitry Andric lldb_private::TypeMap &types) {
13844bb0738eSEd Maste if (!append)
13854bb0738eSEd Maste types.Clear();
13864bb0738eSEd Maste if (!name)
13874bb0738eSEd Maste return 0;
13884ba319b5SDimitry Andric if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
13894ba319b5SDimitry Andric return 0;
13904bb0738eSEd Maste
13914bb0738eSEd Maste searched_symbol_files.clear();
13924bb0738eSEd Maste searched_symbol_files.insert(this);
13934bb0738eSEd Maste
139438638513SDimitry Andric // There is an assumption 'name' is not a regex
1395*b5893f02SDimitry Andric FindTypesByName(name.GetStringRef(), parent_decl_ctx, max_matches, types);
139638638513SDimitry Andric
13974bb0738eSEd Maste return types.GetSize();
13984bb0738eSEd Maste }
13994bb0738eSEd Maste
DumpClangAST(Stream & s)1400*b5893f02SDimitry Andric void SymbolFilePDB::DumpClangAST(Stream &s) {
1401*b5893f02SDimitry Andric auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
1402*b5893f02SDimitry Andric auto clang = llvm::dyn_cast_or_null<ClangASTContext>(type_system);
1403*b5893f02SDimitry Andric if (!clang)
1404*b5893f02SDimitry Andric return;
1405*b5893f02SDimitry Andric clang->Dump(s);
1406*b5893f02SDimitry Andric }
1407*b5893f02SDimitry Andric
FindTypesByRegex(const lldb_private::RegularExpression & regex,uint32_t max_matches,lldb_private::TypeMap & types)14084ba319b5SDimitry Andric void SymbolFilePDB::FindTypesByRegex(
14094ba319b5SDimitry Andric const lldb_private::RegularExpression ®ex, uint32_t max_matches,
1410435933ddSDimitry Andric lldb_private::TypeMap &types) {
1411435933ddSDimitry Andric // When searching by regex, we need to go out of our way to limit the search
1412f678e45dSDimitry Andric // space as much as possible since this searches EVERYTHING in the PDB,
1413f678e45dSDimitry Andric // manually doing regex comparisons. PDB library isn't optimized for regex
1414f678e45dSDimitry Andric // searches or searches across multiple symbol types at the same time, so the
1415435933ddSDimitry Andric // best we can do is to search enums, then typedefs, then classes one by one,
1416f678e45dSDimitry Andric // and do a regex comparison against each of them.
1417435933ddSDimitry Andric PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef,
1418435933ddSDimitry Andric PDB_SymType::UDT};
14194bb0738eSEd Maste std::unique_ptr<IPDBEnumSymbols> results;
14204bb0738eSEd Maste
14214bb0738eSEd Maste uint32_t matches = 0;
14224bb0738eSEd Maste
1423435933ddSDimitry Andric for (auto tag : tags_to_search) {
14244ba319b5SDimitry Andric results = m_global_scope_up->findAllChildren(tag);
14254ba319b5SDimitry Andric if (!results)
14264ba319b5SDimitry Andric continue;
14274ba319b5SDimitry Andric
1428435933ddSDimitry Andric while (auto result = results->getNext()) {
14294bb0738eSEd Maste if (max_matches > 0 && matches >= max_matches)
14304bb0738eSEd Maste break;
14314bb0738eSEd Maste
14324bb0738eSEd Maste std::string type_name;
14334bb0738eSEd Maste if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(result.get()))
14344bb0738eSEd Maste type_name = enum_type->getName();
1435435933ddSDimitry Andric else if (auto typedef_type =
1436435933ddSDimitry Andric llvm::dyn_cast<PDBSymbolTypeTypedef>(result.get()))
14374bb0738eSEd Maste type_name = typedef_type->getName();
14384bb0738eSEd Maste else if (auto class_type = llvm::dyn_cast<PDBSymbolTypeUDT>(result.get()))
14394bb0738eSEd Maste type_name = class_type->getName();
1440435933ddSDimitry Andric else {
1441f678e45dSDimitry Andric // We're looking only for types that have names. Skip symbols, as well
1442f678e45dSDimitry Andric // as unnamed types such as arrays, pointers, etc.
14434bb0738eSEd Maste continue;
14444bb0738eSEd Maste }
14454bb0738eSEd Maste
144638638513SDimitry Andric if (!regex.Execute(type_name))
14474bb0738eSEd Maste continue;
14484bb0738eSEd Maste
1449435933ddSDimitry Andric // This should cause the type to get cached and stored in the `m_types`
1450435933ddSDimitry Andric // lookup.
14514bb0738eSEd Maste if (!ResolveTypeUID(result->getSymIndexId()))
14524bb0738eSEd Maste continue;
14534bb0738eSEd Maste
14544bb0738eSEd Maste auto iter = m_types.find(result->getSymIndexId());
14554bb0738eSEd Maste if (iter == m_types.end())
14564bb0738eSEd Maste continue;
14574bb0738eSEd Maste types.Insert(iter->second);
14584bb0738eSEd Maste ++matches;
14594bb0738eSEd Maste }
14604bb0738eSEd Maste }
14614bb0738eSEd Maste }
14624bb0738eSEd Maste
FindTypesByName(llvm::StringRef name,const lldb_private::CompilerDeclContext * parent_decl_ctx,uint32_t max_matches,lldb_private::TypeMap & types)1463*b5893f02SDimitry Andric void SymbolFilePDB::FindTypesByName(
1464*b5893f02SDimitry Andric llvm::StringRef name,
1465*b5893f02SDimitry Andric const lldb_private::CompilerDeclContext *parent_decl_ctx,
1466*b5893f02SDimitry Andric uint32_t max_matches, lldb_private::TypeMap &types) {
14674bb0738eSEd Maste std::unique_ptr<IPDBEnumSymbols> results;
14684ba319b5SDimitry Andric if (name.empty())
14694ba319b5SDimitry Andric return;
1470*b5893f02SDimitry Andric results = m_global_scope_up->findAllChildren(PDB_SymType::None);
14714ba319b5SDimitry Andric if (!results)
14724ba319b5SDimitry Andric return;
14734bb0738eSEd Maste
14744bb0738eSEd Maste uint32_t matches = 0;
14754bb0738eSEd Maste
1476435933ddSDimitry Andric while (auto result = results->getNext()) {
14774bb0738eSEd Maste if (max_matches > 0 && matches >= max_matches)
14784bb0738eSEd Maste break;
1479*b5893f02SDimitry Andric
1480*b5893f02SDimitry Andric if (MSVCUndecoratedNameParser::DropScope(
1481*b5893f02SDimitry Andric result->getRawSymbol().getName()) != name)
1482*b5893f02SDimitry Andric continue;
1483*b5893f02SDimitry Andric
1484435933ddSDimitry Andric switch (result->getSymTag()) {
14854bb0738eSEd Maste case PDB_SymType::Enum:
14864bb0738eSEd Maste case PDB_SymType::UDT:
14874bb0738eSEd Maste case PDB_SymType::Typedef:
14884bb0738eSEd Maste break;
14894bb0738eSEd Maste default:
14904ba319b5SDimitry Andric // We're looking only for types that have names. Skip symbols, as well
14914ba319b5SDimitry Andric // as unnamed types such as arrays, pointers, etc.
14924bb0738eSEd Maste continue;
14934bb0738eSEd Maste }
14944bb0738eSEd Maste
1495435933ddSDimitry Andric // This should cause the type to get cached and stored in the `m_types`
1496435933ddSDimitry Andric // lookup.
14974bb0738eSEd Maste if (!ResolveTypeUID(result->getSymIndexId()))
14984bb0738eSEd Maste continue;
14994bb0738eSEd Maste
1500*b5893f02SDimitry Andric if (parent_decl_ctx && GetDeclContextContainingUID(
1501*b5893f02SDimitry Andric result->getSymIndexId()) != *parent_decl_ctx)
1502*b5893f02SDimitry Andric continue;
1503*b5893f02SDimitry Andric
15044bb0738eSEd Maste auto iter = m_types.find(result->getSymIndexId());
15054bb0738eSEd Maste if (iter == m_types.end())
15064bb0738eSEd Maste continue;
15074bb0738eSEd Maste types.Insert(iter->second);
15084bb0738eSEd Maste ++matches;
15094bb0738eSEd Maste }
15104bb0738eSEd Maste }
15114bb0738eSEd Maste
FindTypes(const std::vector<lldb_private::CompilerContext> & contexts,bool append,lldb_private::TypeMap & types)1512435933ddSDimitry Andric size_t SymbolFilePDB::FindTypes(
1513435933ddSDimitry Andric const std::vector<lldb_private::CompilerContext> &contexts, bool append,
1514435933ddSDimitry Andric lldb_private::TypeMap &types) {
15154bb0738eSEd Maste return 0;
15164bb0738eSEd Maste }
15174bb0738eSEd Maste
GetTypeList()15184ba319b5SDimitry Andric lldb_private::TypeList *SymbolFilePDB::GetTypeList() {
15194ba319b5SDimitry Andric return m_obj_file->GetModule()->GetTypeList();
15204ba319b5SDimitry Andric }
15214ba319b5SDimitry Andric
GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol & pdb_symbol,uint32_t type_mask,TypeCollection & type_collection)15224ba319b5SDimitry Andric void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol,
15234ba319b5SDimitry Andric uint32_t type_mask,
15244ba319b5SDimitry Andric TypeCollection &type_collection) {
15254ba319b5SDimitry Andric bool can_parse = false;
15264ba319b5SDimitry Andric switch (pdb_symbol.getSymTag()) {
15274ba319b5SDimitry Andric case PDB_SymType::ArrayType:
15284ba319b5SDimitry Andric can_parse = ((type_mask & eTypeClassArray) != 0);
15294ba319b5SDimitry Andric break;
15304ba319b5SDimitry Andric case PDB_SymType::BuiltinType:
15314ba319b5SDimitry Andric can_parse = ((type_mask & eTypeClassBuiltin) != 0);
15324ba319b5SDimitry Andric break;
15334ba319b5SDimitry Andric case PDB_SymType::Enum:
15344ba319b5SDimitry Andric can_parse = ((type_mask & eTypeClassEnumeration) != 0);
15354ba319b5SDimitry Andric break;
15364ba319b5SDimitry Andric case PDB_SymType::Function:
15374ba319b5SDimitry Andric case PDB_SymType::FunctionSig:
15384ba319b5SDimitry Andric can_parse = ((type_mask & eTypeClassFunction) != 0);
15394ba319b5SDimitry Andric break;
15404ba319b5SDimitry Andric case PDB_SymType::PointerType:
15414ba319b5SDimitry Andric can_parse = ((type_mask & (eTypeClassPointer | eTypeClassBlockPointer |
15424ba319b5SDimitry Andric eTypeClassMemberPointer)) != 0);
15434ba319b5SDimitry Andric break;
15444ba319b5SDimitry Andric case PDB_SymType::Typedef:
15454ba319b5SDimitry Andric can_parse = ((type_mask & eTypeClassTypedef) != 0);
15464ba319b5SDimitry Andric break;
15474ba319b5SDimitry Andric case PDB_SymType::UDT: {
15484ba319b5SDimitry Andric auto *udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&pdb_symbol);
15494ba319b5SDimitry Andric assert(udt);
15504ba319b5SDimitry Andric can_parse = (udt->getUdtKind() != PDB_UdtType::Interface &&
15514ba319b5SDimitry Andric ((type_mask & (eTypeClassClass | eTypeClassStruct |
15524ba319b5SDimitry Andric eTypeClassUnion)) != 0));
15534ba319b5SDimitry Andric } break;
15544ba319b5SDimitry Andric default:
15554ba319b5SDimitry Andric break;
15564ba319b5SDimitry Andric }
15574ba319b5SDimitry Andric
15584ba319b5SDimitry Andric if (can_parse) {
15594ba319b5SDimitry Andric if (auto *type = ResolveTypeUID(pdb_symbol.getSymIndexId())) {
15604ba319b5SDimitry Andric auto result =
15614ba319b5SDimitry Andric std::find(type_collection.begin(), type_collection.end(), type);
15624ba319b5SDimitry Andric if (result == type_collection.end())
15634ba319b5SDimitry Andric type_collection.push_back(type);
15644ba319b5SDimitry Andric }
15654ba319b5SDimitry Andric }
15664ba319b5SDimitry Andric
15674ba319b5SDimitry Andric auto results_up = pdb_symbol.findAllChildren();
15684ba319b5SDimitry Andric while (auto symbol_up = results_up->getNext())
15694ba319b5SDimitry Andric GetTypesForPDBSymbol(*symbol_up, type_mask, type_collection);
15704ba319b5SDimitry Andric }
15714bb0738eSEd Maste
GetTypes(lldb_private::SymbolContextScope * sc_scope,TypeClass type_mask,lldb_private::TypeList & type_list)1572435933ddSDimitry Andric size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
1573*b5893f02SDimitry Andric TypeClass type_mask,
1574435933ddSDimitry Andric lldb_private::TypeList &type_list) {
15754ba319b5SDimitry Andric TypeCollection type_collection;
15764ba319b5SDimitry Andric uint32_t old_size = type_list.GetSize();
15774ba319b5SDimitry Andric CompileUnit *cu =
15784ba319b5SDimitry Andric sc_scope ? sc_scope->CalculateSymbolContextCompileUnit() : nullptr;
15794ba319b5SDimitry Andric if (cu) {
15804ba319b5SDimitry Andric auto compiland_up = GetPDBCompilandByUID(cu->GetID());
15814ba319b5SDimitry Andric if (!compiland_up)
15824ba319b5SDimitry Andric return 0;
15834ba319b5SDimitry Andric GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection);
15844ba319b5SDimitry Andric } else {
15854ba319b5SDimitry Andric for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) {
15864ba319b5SDimitry Andric auto cu_sp = ParseCompileUnitAtIndex(cu_idx);
15874ba319b5SDimitry Andric if (cu_sp) {
15884ba319b5SDimitry Andric if (auto compiland_up = GetPDBCompilandByUID(cu_sp->GetID()))
15894ba319b5SDimitry Andric GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection);
15904ba319b5SDimitry Andric }
15914ba319b5SDimitry Andric }
15924ba319b5SDimitry Andric }
15934ba319b5SDimitry Andric
15944ba319b5SDimitry Andric for (auto type : type_collection) {
15954ba319b5SDimitry Andric type->GetForwardCompilerType();
15964ba319b5SDimitry Andric type_list.Insert(type->shared_from_this());
15974ba319b5SDimitry Andric }
15984ba319b5SDimitry Andric return type_list.GetSize() - old_size;
15994bb0738eSEd Maste }
16004bb0738eSEd Maste
16014bb0738eSEd Maste lldb_private::TypeSystem *
GetTypeSystemForLanguage(lldb::LanguageType language)1602435933ddSDimitry Andric SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
1603435933ddSDimitry Andric auto type_system =
1604435933ddSDimitry Andric m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
16054bb0738eSEd Maste if (type_system)
16064bb0738eSEd Maste type_system->SetSymbolFile(this);
16074bb0738eSEd Maste return type_system;
16084bb0738eSEd Maste }
16094bb0738eSEd Maste
GetPDBAstParser()1610*b5893f02SDimitry Andric PDBASTParser *SymbolFilePDB::GetPDBAstParser() {
1611*b5893f02SDimitry Andric auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
1612*b5893f02SDimitry Andric auto clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system);
1613*b5893f02SDimitry Andric if (!clang_type_system)
1614*b5893f02SDimitry Andric return nullptr;
1615*b5893f02SDimitry Andric
1616*b5893f02SDimitry Andric return clang_type_system->GetPDBParser();
1617*b5893f02SDimitry Andric }
1618*b5893f02SDimitry Andric
1619*b5893f02SDimitry Andric
FindNamespace(const lldb_private::ConstString & name,const lldb_private::CompilerDeclContext * parent_decl_ctx)1620435933ddSDimitry Andric lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace(
1621435933ddSDimitry Andric const lldb_private::ConstString &name,
1622435933ddSDimitry Andric const lldb_private::CompilerDeclContext *parent_decl_ctx) {
1623*b5893f02SDimitry Andric auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
1624*b5893f02SDimitry Andric auto clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system);
1625*b5893f02SDimitry Andric if (!clang_type_system)
1626*b5893f02SDimitry Andric return CompilerDeclContext();
1627*b5893f02SDimitry Andric
1628*b5893f02SDimitry Andric PDBASTParser *pdb = clang_type_system->GetPDBParser();
1629*b5893f02SDimitry Andric if (!pdb)
1630*b5893f02SDimitry Andric return CompilerDeclContext();
1631*b5893f02SDimitry Andric
1632*b5893f02SDimitry Andric clang::DeclContext *decl_context = nullptr;
1633*b5893f02SDimitry Andric if (parent_decl_ctx)
1634*b5893f02SDimitry Andric decl_context = static_cast<clang::DeclContext *>(
1635*b5893f02SDimitry Andric parent_decl_ctx->GetOpaqueDeclContext());
1636*b5893f02SDimitry Andric
1637*b5893f02SDimitry Andric auto namespace_decl =
1638*b5893f02SDimitry Andric pdb->FindNamespaceDecl(decl_context, name.GetStringRef());
1639*b5893f02SDimitry Andric if (!namespace_decl)
1640*b5893f02SDimitry Andric return CompilerDeclContext();
1641*b5893f02SDimitry Andric
1642*b5893f02SDimitry Andric return CompilerDeclContext(type_system,
1643*b5893f02SDimitry Andric static_cast<clang::DeclContext *>(namespace_decl));
16444bb0738eSEd Maste }
16454bb0738eSEd Maste
GetPluginName()1646435933ddSDimitry Andric lldb_private::ConstString SymbolFilePDB::GetPluginName() {
16474bb0738eSEd Maste static ConstString g_name("pdb");
16484bb0738eSEd Maste return g_name;
16494bb0738eSEd Maste }
16504bb0738eSEd Maste
GetPluginVersion()1651435933ddSDimitry Andric uint32_t SymbolFilePDB::GetPluginVersion() { return 1; }
16524bb0738eSEd Maste
GetPDBSession()1653435933ddSDimitry Andric IPDBSession &SymbolFilePDB::GetPDBSession() { return *m_session_up; }
1654435933ddSDimitry Andric
GetPDBSession() const1655435933ddSDimitry Andric const IPDBSession &SymbolFilePDB::GetPDBSession() const {
16564bb0738eSEd Maste return *m_session_up;
16574bb0738eSEd Maste }
16584bb0738eSEd Maste
ParseCompileUnitForUID(uint32_t id,uint32_t index)16594ba319b5SDimitry Andric lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForUID(uint32_t id,
16604ba319b5SDimitry Andric uint32_t index) {
16614bb0738eSEd Maste auto found_cu = m_comp_units.find(id);
16624bb0738eSEd Maste if (found_cu != m_comp_units.end())
16634bb0738eSEd Maste return found_cu->second;
16644bb0738eSEd Maste
16654ba319b5SDimitry Andric auto compiland_up = GetPDBCompilandByUID(id);
16664ba319b5SDimitry Andric if (!compiland_up)
16674ba319b5SDimitry Andric return CompUnitSP();
16684bb0738eSEd Maste
16694bb0738eSEd Maste lldb::LanguageType lang;
16704ba319b5SDimitry Andric auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>();
16714bb0738eSEd Maste if (!details)
16724bb0738eSEd Maste lang = lldb::eLanguageTypeC_plus_plus;
16734bb0738eSEd Maste else
16744bb0738eSEd Maste lang = TranslateLanguage(details->getLanguage());
16754bb0738eSEd Maste
16764ba319b5SDimitry Andric if (lang == lldb::LanguageType::eLanguageTypeUnknown)
16774ba319b5SDimitry Andric return CompUnitSP();
16784ba319b5SDimitry Andric
16794ba319b5SDimitry Andric std::string path = compiland_up->getSourceFileFullPath();
16804ba319b5SDimitry Andric if (path.empty())
16814ba319b5SDimitry Andric return CompUnitSP();
16824ba319b5SDimitry Andric
1683435933ddSDimitry Andric // Don't support optimized code for now, DebugInfoPDB does not return this
1684435933ddSDimitry Andric // information.
16854bb0738eSEd Maste LazyBool optimized = eLazyBoolNo;
16864ba319b5SDimitry Andric auto cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr,
16874ba319b5SDimitry Andric path.c_str(), id, lang, optimized);
16884ba319b5SDimitry Andric
16894ba319b5SDimitry Andric if (!cu_sp)
16904ba319b5SDimitry Andric return CompUnitSP();
16914ba319b5SDimitry Andric
16924ba319b5SDimitry Andric m_comp_units.insert(std::make_pair(id, cu_sp));
16934ba319b5SDimitry Andric if (index == UINT32_MAX)
16944ba319b5SDimitry Andric GetCompileUnitIndex(*compiland_up, index);
16954ba319b5SDimitry Andric lldbassert(index != UINT32_MAX);
16964ba319b5SDimitry Andric m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(index,
16974ba319b5SDimitry Andric cu_sp);
16984ba319b5SDimitry Andric return cu_sp;
16994bb0738eSEd Maste }
17004bb0738eSEd Maste
ParseCompileUnitLineTable(CompileUnit & comp_unit,uint32_t match_line)1701*b5893f02SDimitry Andric bool SymbolFilePDB::ParseCompileUnitLineTable(CompileUnit &comp_unit,
1702*b5893f02SDimitry Andric uint32_t match_line) {
1703*b5893f02SDimitry Andric auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID());
17044ba319b5SDimitry Andric if (!compiland_up)
17054ba319b5SDimitry Andric return false;
17064bb0738eSEd Maste
1707435933ddSDimitry Andric // LineEntry needs the *index* of the file into the list of support files
1708f678e45dSDimitry Andric // returned by ParseCompileUnitSupportFiles. But the underlying SDK gives us
17094ba319b5SDimitry Andric // a globally unique idenfitifier in the namespace of the PDB. So, we have
17104ba319b5SDimitry Andric // to do a mapping so that we can hand out indices.
17114bb0738eSEd Maste llvm::DenseMap<uint32_t, uint32_t> index_map;
17124ba319b5SDimitry Andric BuildSupportFileIdToSupportFileIndexMap(*compiland_up, index_map);
1713*b5893f02SDimitry Andric auto line_table = llvm::make_unique<LineTable>(&comp_unit);
17144bb0738eSEd Maste
17154ba319b5SDimitry Andric // Find contributions to `compiland` from all source and header files.
1716*b5893f02SDimitry Andric std::string path = comp_unit.GetPath();
17174ba319b5SDimitry Andric auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
17184ba319b5SDimitry Andric if (!files)
17194ba319b5SDimitry Andric return false;
17204bb0738eSEd Maste
17214ba319b5SDimitry Andric // For each source and header file, create a LineSequence for contributions
17224ba319b5SDimitry Andric // to the compiland from that file, and add the sequence.
1723435933ddSDimitry Andric while (auto file = files->getNext()) {
1724435933ddSDimitry Andric std::unique_ptr<LineSequence> sequence(
1725435933ddSDimitry Andric line_table->CreateLineSequenceContainer());
17264ba319b5SDimitry Andric auto lines = m_session_up->findLineNumbers(*compiland_up, *file);
17274ba319b5SDimitry Andric if (!lines)
17284ba319b5SDimitry Andric continue;
17294bb0738eSEd Maste int entry_count = lines->getChildCount();
17304bb0738eSEd Maste
17314bb0738eSEd Maste uint64_t prev_addr;
17324bb0738eSEd Maste uint32_t prev_length;
17334bb0738eSEd Maste uint32_t prev_line;
17344bb0738eSEd Maste uint32_t prev_source_idx;
17354bb0738eSEd Maste
1736435933ddSDimitry Andric for (int i = 0; i < entry_count; ++i) {
17374bb0738eSEd Maste auto line = lines->getChildAtIndex(i);
17384bb0738eSEd Maste
17394bb0738eSEd Maste uint64_t lno = line->getLineNumber();
17404bb0738eSEd Maste uint64_t addr = line->getVirtualAddress();
17414bb0738eSEd Maste uint32_t length = line->getLength();
17424bb0738eSEd Maste uint32_t source_id = line->getSourceFileId();
17434bb0738eSEd Maste uint32_t col = line->getColumnNumber();
17444bb0738eSEd Maste uint32_t source_idx = index_map[source_id];
17454bb0738eSEd Maste
17464ba319b5SDimitry Andric // There was a gap between the current entry and the previous entry if
17474ba319b5SDimitry Andric // the addresses don't perfectly line up.
17484bb0738eSEd Maste bool is_gap = (i > 0) && (prev_addr + prev_length < addr);
17494bb0738eSEd Maste
1750435933ddSDimitry Andric // Before inserting the current entry, insert a terminal entry at the end
1751f678e45dSDimitry Andric // of the previous entry's address range if the current entry resulted in
1752f678e45dSDimitry Andric // a gap from the previous entry.
1753435933ddSDimitry Andric if (is_gap && ShouldAddLine(match_line, prev_line, prev_length)) {
1754435933ddSDimitry Andric line_table->AppendLineEntryToSequence(
1755435933ddSDimitry Andric sequence.get(), prev_addr + prev_length, prev_line, 0,
17564bb0738eSEd Maste prev_source_idx, false, false, false, false, true);
17574ba319b5SDimitry Andric
17584ba319b5SDimitry Andric line_table->InsertSequence(sequence.release());
17594ba319b5SDimitry Andric sequence.reset(line_table->CreateLineSequenceContainer());
17604bb0738eSEd Maste }
17614bb0738eSEd Maste
1762435933ddSDimitry Andric if (ShouldAddLine(match_line, lno, length)) {
17634bb0738eSEd Maste bool is_statement = line->isStatement();
17644bb0738eSEd Maste bool is_prologue = false;
17654bb0738eSEd Maste bool is_epilogue = false;
1766435933ddSDimitry Andric auto func =
1767435933ddSDimitry Andric m_session_up->findSymbolByAddress(addr, PDB_SymType::Function);
1768435933ddSDimitry Andric if (func) {
17694bb0738eSEd Maste auto prologue = func->findOneChild<PDBSymbolFuncDebugStart>();
17704ba319b5SDimitry Andric if (prologue)
17714bb0738eSEd Maste is_prologue = (addr == prologue->getVirtualAddress());
17724bb0738eSEd Maste
17734bb0738eSEd Maste auto epilogue = func->findOneChild<PDBSymbolFuncDebugEnd>();
17744ba319b5SDimitry Andric if (epilogue)
17754bb0738eSEd Maste is_epilogue = (addr == epilogue->getVirtualAddress());
17764bb0738eSEd Maste }
17774bb0738eSEd Maste
1778435933ddSDimitry Andric line_table->AppendLineEntryToSequence(sequence.get(), addr, lno, col,
1779435933ddSDimitry Andric source_idx, is_statement, false,
17804bb0738eSEd Maste is_prologue, is_epilogue, false);
17814bb0738eSEd Maste }
17824bb0738eSEd Maste
17834bb0738eSEd Maste prev_addr = addr;
17844bb0738eSEd Maste prev_length = length;
17854bb0738eSEd Maste prev_line = lno;
17864bb0738eSEd Maste prev_source_idx = source_idx;
17874bb0738eSEd Maste }
17884bb0738eSEd Maste
1789435933ddSDimitry Andric if (entry_count > 0 && ShouldAddLine(match_line, prev_line, prev_length)) {
17904bb0738eSEd Maste // The end is always a terminal entry, so insert it regardless.
1791435933ddSDimitry Andric line_table->AppendLineEntryToSequence(
1792435933ddSDimitry Andric sequence.get(), prev_addr + prev_length, prev_line, 0,
17934bb0738eSEd Maste prev_source_idx, false, false, false, false, true);
17944bb0738eSEd Maste }
17954bb0738eSEd Maste
17964bb0738eSEd Maste line_table->InsertSequence(sequence.release());
17974bb0738eSEd Maste }
17984bb0738eSEd Maste
17994ba319b5SDimitry Andric if (line_table->GetSize()) {
1800*b5893f02SDimitry Andric comp_unit.SetLineTable(line_table.release());
18014bb0738eSEd Maste return true;
18024bb0738eSEd Maste }
18034ba319b5SDimitry Andric return false;
18044ba319b5SDimitry Andric }
18054bb0738eSEd Maste
BuildSupportFileIdToSupportFileIndexMap(const PDBSymbolCompiland & compiland,llvm::DenseMap<uint32_t,uint32_t> & index_map) const1806435933ddSDimitry Andric void SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(
18074ba319b5SDimitry Andric const PDBSymbolCompiland &compiland,
1808435933ddSDimitry Andric llvm::DenseMap<uint32_t, uint32_t> &index_map) const {
18094ba319b5SDimitry Andric // This is a hack, but we need to convert the source id into an index into
18104ba319b5SDimitry Andric // the support files array. We don't want to do path comparisons to avoid
1811f678e45dSDimitry Andric // basename / full path issues that may or may not even be a problem, so we
1812f678e45dSDimitry Andric // use the globally unique source file identifiers. Ideally we could use the
1813f678e45dSDimitry Andric // global identifiers everywhere, but LineEntry currently assumes indices.
18144ba319b5SDimitry Andric auto source_files = m_session_up->getSourceFilesForCompiland(compiland);
18154ba319b5SDimitry Andric if (!source_files)
18164ba319b5SDimitry Andric return;
18174ba319b5SDimitry Andric
18184ba319b5SDimitry Andric // LLDB uses the DWARF-like file numeration (one based)
18194ba319b5SDimitry Andric int index = 1;
18204bb0738eSEd Maste
1821435933ddSDimitry Andric while (auto file = source_files->getNext()) {
18224bb0738eSEd Maste uint32_t source_id = file->getUniqueId();
18234bb0738eSEd Maste index_map[source_id] = index++;
18244bb0738eSEd Maste }
18254bb0738eSEd Maste }
18264ba319b5SDimitry Andric
GetCompileUnitContainsAddress(const lldb_private::Address & so_addr)18274ba319b5SDimitry Andric lldb::CompUnitSP SymbolFilePDB::GetCompileUnitContainsAddress(
18284ba319b5SDimitry Andric const lldb_private::Address &so_addr) {
18294ba319b5SDimitry Andric lldb::addr_t file_vm_addr = so_addr.GetFileAddress();
18304ba319b5SDimitry Andric if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
18314ba319b5SDimitry Andric return nullptr;
18324ba319b5SDimitry Andric
18334ba319b5SDimitry Andric // If it is a PDB function's vm addr, this is the first sure bet.
18344ba319b5SDimitry Andric if (auto lines =
18354ba319b5SDimitry Andric m_session_up->findLineNumbersByAddress(file_vm_addr, /*Length=*/1)) {
18364ba319b5SDimitry Andric if (auto first_line = lines->getNext())
18374ba319b5SDimitry Andric return ParseCompileUnitForUID(first_line->getCompilandId());
18384ba319b5SDimitry Andric }
18394ba319b5SDimitry Andric
18404ba319b5SDimitry Andric // Otherwise we resort to section contributions.
18414ba319b5SDimitry Andric if (auto sec_contribs = m_session_up->getSectionContribs()) {
18424ba319b5SDimitry Andric while (auto section = sec_contribs->getNext()) {
18434ba319b5SDimitry Andric auto va = section->getVirtualAddress();
18444ba319b5SDimitry Andric if (file_vm_addr >= va && file_vm_addr < va + section->getLength())
18454ba319b5SDimitry Andric return ParseCompileUnitForUID(section->getCompilandId());
18464ba319b5SDimitry Andric }
18474ba319b5SDimitry Andric }
18484ba319b5SDimitry Andric return nullptr;
18494ba319b5SDimitry Andric }
18504ba319b5SDimitry Andric
18514ba319b5SDimitry Andric Mangled
GetMangledForPDBFunc(const llvm::pdb::PDBSymbolFunc & pdb_func)18524ba319b5SDimitry Andric SymbolFilePDB::GetMangledForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func) {
18534ba319b5SDimitry Andric Mangled mangled;
18544ba319b5SDimitry Andric auto func_name = pdb_func.getName();
18554ba319b5SDimitry Andric auto func_undecorated_name = pdb_func.getUndecoratedName();
18564ba319b5SDimitry Andric std::string func_decorated_name;
18574ba319b5SDimitry Andric
18584ba319b5SDimitry Andric // Seek from public symbols for non-static function's decorated name if any.
18594ba319b5SDimitry Andric // For static functions, they don't have undecorated names and aren't exposed
18604ba319b5SDimitry Andric // in Public Symbols either.
18614ba319b5SDimitry Andric if (!func_undecorated_name.empty()) {
18624ba319b5SDimitry Andric auto result_up = m_global_scope_up->findChildren(
18634ba319b5SDimitry Andric PDB_SymType::PublicSymbol, func_undecorated_name,
18644ba319b5SDimitry Andric PDB_NameSearchFlags::NS_UndecoratedName);
18654ba319b5SDimitry Andric if (result_up) {
18664ba319b5SDimitry Andric while (auto symbol_up = result_up->getNext()) {
18674ba319b5SDimitry Andric // For a public symbol, it is unique.
18684ba319b5SDimitry Andric lldbassert(result_up->getChildCount() == 1);
18694ba319b5SDimitry Andric if (auto *pdb_public_sym =
18704ba319b5SDimitry Andric llvm::dyn_cast_or_null<PDBSymbolPublicSymbol>(
18714ba319b5SDimitry Andric symbol_up.get())) {
18724ba319b5SDimitry Andric if (pdb_public_sym->isFunction()) {
18734ba319b5SDimitry Andric func_decorated_name = pdb_public_sym->getName();
18744ba319b5SDimitry Andric break;
18754ba319b5SDimitry Andric }
18764ba319b5SDimitry Andric }
18774ba319b5SDimitry Andric }
18784ba319b5SDimitry Andric }
18794ba319b5SDimitry Andric }
18804ba319b5SDimitry Andric if (!func_decorated_name.empty()) {
18814ba319b5SDimitry Andric mangled.SetMangledName(ConstString(func_decorated_name));
18824ba319b5SDimitry Andric
18834ba319b5SDimitry Andric // For MSVC, format of C funciton's decorated name depends on calling
18844ba319b5SDimitry Andric // conventon. Unfortunately none of the format is recognized by current
18854ba319b5SDimitry Andric // LLDB. For example, `_purecall` is a __cdecl C function. From PDB,
18864ba319b5SDimitry Andric // `__purecall` is retrieved as both its decorated and undecorated name
18874ba319b5SDimitry Andric // (using PDBSymbolFunc::getUndecoratedName method). However `__purecall`
18884ba319b5SDimitry Andric // string is not treated as mangled in LLDB (neither `?` nor `_Z` prefix).
18894ba319b5SDimitry Andric // Mangled::GetDemangledName method will fail internally and caches an
18904ba319b5SDimitry Andric // empty string as its undecorated name. So we will face a contradition
18914ba319b5SDimitry Andric // here for the same symbol:
18924ba319b5SDimitry Andric // non-empty undecorated name from PDB
18934ba319b5SDimitry Andric // empty undecorated name from LLDB
18944ba319b5SDimitry Andric if (!func_undecorated_name.empty() &&
18954ba319b5SDimitry Andric mangled.GetDemangledName(mangled.GuessLanguage()).IsEmpty())
18964ba319b5SDimitry Andric mangled.SetDemangledName(ConstString(func_undecorated_name));
18974ba319b5SDimitry Andric
18984ba319b5SDimitry Andric // LLDB uses several flags to control how a C++ decorated name is
18994ba319b5SDimitry Andric // undecorated for MSVC. See `safeUndecorateName` in Class Mangled. So the
19004ba319b5SDimitry Andric // yielded name could be different from what we retrieve from
19014ba319b5SDimitry Andric // PDB source unless we also apply same flags in getting undecorated
19024ba319b5SDimitry Andric // name through PDBSymbolFunc::getUndecoratedNameEx method.
19034ba319b5SDimitry Andric if (!func_undecorated_name.empty() &&
19044ba319b5SDimitry Andric mangled.GetDemangledName(mangled.GuessLanguage()) !=
19054ba319b5SDimitry Andric ConstString(func_undecorated_name))
19064ba319b5SDimitry Andric mangled.SetDemangledName(ConstString(func_undecorated_name));
19074ba319b5SDimitry Andric } else if (!func_undecorated_name.empty()) {
19084ba319b5SDimitry Andric mangled.SetDemangledName(ConstString(func_undecorated_name));
19094ba319b5SDimitry Andric } else if (!func_name.empty())
19104ba319b5SDimitry Andric mangled.SetValue(ConstString(func_name), false);
19114ba319b5SDimitry Andric
19124ba319b5SDimitry Andric return mangled;
19134ba319b5SDimitry Andric }
19144ba319b5SDimitry Andric
DeclContextMatchesThisSymbolFile(const lldb_private::CompilerDeclContext * decl_ctx)19154ba319b5SDimitry Andric bool SymbolFilePDB::DeclContextMatchesThisSymbolFile(
19164ba319b5SDimitry Andric const lldb_private::CompilerDeclContext *decl_ctx) {
19174ba319b5SDimitry Andric if (decl_ctx == nullptr || !decl_ctx->IsValid())
19184ba319b5SDimitry Andric return true;
19194ba319b5SDimitry Andric
19204ba319b5SDimitry Andric TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem();
19214ba319b5SDimitry Andric if (!decl_ctx_type_system)
19224ba319b5SDimitry Andric return false;
19234ba319b5SDimitry Andric TypeSystem *type_system = GetTypeSystemForLanguage(
19244ba319b5SDimitry Andric decl_ctx_type_system->GetMinimumLanguage(nullptr));
19254ba319b5SDimitry Andric if (decl_ctx_type_system == type_system)
19264ba319b5SDimitry Andric return true; // The type systems match, return true
19274ba319b5SDimitry Andric
19284ba319b5SDimitry Andric return false;
19294ba319b5SDimitry Andric }
1930*b5893f02SDimitry Andric
GetCompilandId(const llvm::pdb::PDBSymbolData & data)1931*b5893f02SDimitry Andric uint32_t SymbolFilePDB::GetCompilandId(const llvm::pdb::PDBSymbolData &data) {
1932*b5893f02SDimitry Andric static const auto pred_upper = [](uint32_t lhs, SecContribInfo rhs) {
1933*b5893f02SDimitry Andric return lhs < rhs.Offset;
1934*b5893f02SDimitry Andric };
1935*b5893f02SDimitry Andric
1936*b5893f02SDimitry Andric // Cache section contributions
1937*b5893f02SDimitry Andric if (m_sec_contribs.empty()) {
1938*b5893f02SDimitry Andric if (auto SecContribs = m_session_up->getSectionContribs()) {
1939*b5893f02SDimitry Andric while (auto SectionContrib = SecContribs->getNext()) {
1940*b5893f02SDimitry Andric auto comp_id = SectionContrib->getCompilandId();
1941*b5893f02SDimitry Andric if (!comp_id)
1942*b5893f02SDimitry Andric continue;
1943*b5893f02SDimitry Andric
1944*b5893f02SDimitry Andric auto sec = SectionContrib->getAddressSection();
1945*b5893f02SDimitry Andric auto &sec_cs = m_sec_contribs[sec];
1946*b5893f02SDimitry Andric
1947*b5893f02SDimitry Andric auto offset = SectionContrib->getAddressOffset();
1948*b5893f02SDimitry Andric auto it =
1949*b5893f02SDimitry Andric std::upper_bound(sec_cs.begin(), sec_cs.end(), offset, pred_upper);
1950*b5893f02SDimitry Andric
1951*b5893f02SDimitry Andric auto size = SectionContrib->getLength();
1952*b5893f02SDimitry Andric sec_cs.insert(it, {offset, size, comp_id});
1953*b5893f02SDimitry Andric }
1954*b5893f02SDimitry Andric }
1955*b5893f02SDimitry Andric }
1956*b5893f02SDimitry Andric
1957*b5893f02SDimitry Andric // Check by line number
1958*b5893f02SDimitry Andric if (auto Lines = data.getLineNumbers()) {
1959*b5893f02SDimitry Andric if (auto FirstLine = Lines->getNext())
1960*b5893f02SDimitry Andric return FirstLine->getCompilandId();
1961*b5893f02SDimitry Andric }
1962*b5893f02SDimitry Andric
1963*b5893f02SDimitry Andric // Retrieve section + offset
1964*b5893f02SDimitry Andric uint32_t DataSection = data.getAddressSection();
1965*b5893f02SDimitry Andric uint32_t DataOffset = data.getAddressOffset();
1966*b5893f02SDimitry Andric if (DataSection == 0) {
1967*b5893f02SDimitry Andric if (auto RVA = data.getRelativeVirtualAddress())
1968*b5893f02SDimitry Andric m_session_up->addressForRVA(RVA, DataSection, DataOffset);
1969*b5893f02SDimitry Andric }
1970*b5893f02SDimitry Andric
1971*b5893f02SDimitry Andric if (DataSection) {
1972*b5893f02SDimitry Andric // Search by section contributions
1973*b5893f02SDimitry Andric auto &sec_cs = m_sec_contribs[DataSection];
1974*b5893f02SDimitry Andric auto it =
1975*b5893f02SDimitry Andric std::upper_bound(sec_cs.begin(), sec_cs.end(), DataOffset, pred_upper);
1976*b5893f02SDimitry Andric if (it != sec_cs.begin()) {
1977*b5893f02SDimitry Andric --it;
1978*b5893f02SDimitry Andric if (DataOffset < it->Offset + it->Size)
1979*b5893f02SDimitry Andric return it->CompilandId;
1980*b5893f02SDimitry Andric }
1981*b5893f02SDimitry Andric } else {
1982*b5893f02SDimitry Andric // Search in lexical tree
1983*b5893f02SDimitry Andric auto LexParentId = data.getLexicalParentId();
1984*b5893f02SDimitry Andric while (auto LexParent = m_session_up->getSymbolById(LexParentId)) {
1985*b5893f02SDimitry Andric if (LexParent->getSymTag() == PDB_SymType::Exe)
1986*b5893f02SDimitry Andric break;
1987*b5893f02SDimitry Andric if (LexParent->getSymTag() == PDB_SymType::Compiland)
1988*b5893f02SDimitry Andric return LexParentId;
1989*b5893f02SDimitry Andric LexParentId = LexParent->getRawSymbol().getLexicalParentId();
1990*b5893f02SDimitry Andric }
1991*b5893f02SDimitry Andric }
1992*b5893f02SDimitry Andric
1993*b5893f02SDimitry Andric return 0;
1994*b5893f02SDimitry Andric }
1995