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