595 lines · cpp
1//===-- SymbolFileOnDemand.cpp ---------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Symbol/SymbolFileOnDemand.h"10 11#include "lldb/Core/Module.h"12#include "lldb/Symbol/SymbolFile.h"13 14#include <memory>15#include <optional>16 17using namespace lldb;18using namespace lldb_private;19 20char SymbolFileOnDemand::ID;21 22SymbolFileOnDemand::SymbolFileOnDemand(23 std::unique_ptr<SymbolFile> &&symbol_file)24 : m_sym_file_impl(std::move(symbol_file)) {}25 26SymbolFileOnDemand::~SymbolFileOnDemand() = default;27 28uint32_t SymbolFileOnDemand::CalculateAbilities() {29 // Explicitly allow ability checking to pass though.30 // This should be a cheap operation.31 return m_sym_file_impl->CalculateAbilities();32}33 34std::recursive_mutex &SymbolFileOnDemand::GetModuleMutex() const {35 return m_sym_file_impl->GetModuleMutex();36}37 38void SymbolFileOnDemand::InitializeObject() {39 if (!m_debug_info_enabled) {40 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),41 __FUNCTION__);42 return;43 }44 return m_sym_file_impl->InitializeObject();45}46 47lldb::LanguageType SymbolFileOnDemand::ParseLanguage(CompileUnit &comp_unit) {48 if (!m_debug_info_enabled) {49 Log *log = GetLog();50 LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);51 if (log) {52 lldb::LanguageType langType = m_sym_file_impl->ParseLanguage(comp_unit);53 if (langType != eLanguageTypeUnknown)54 LLDB_LOG(log, "Language {0} would return if hydrated.", langType);55 }56 return eLanguageTypeUnknown;57 }58 return m_sym_file_impl->ParseLanguage(comp_unit);59}60 61XcodeSDK SymbolFileOnDemand::ParseXcodeSDK(CompileUnit &comp_unit) {62 if (!m_debug_info_enabled) {63 Log *log = GetLog();64 LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);65 XcodeSDK defaultValue{};66 if (log) {67 XcodeSDK sdk = m_sym_file_impl->ParseXcodeSDK(comp_unit);68 if (!(sdk == defaultValue))69 LLDB_LOG(log, "SDK {0} would return if hydrated.", sdk.GetString());70 }71 return defaultValue;72 }73 return m_sym_file_impl->ParseXcodeSDK(comp_unit);74}75 76size_t SymbolFileOnDemand::ParseFunctions(CompileUnit &comp_unit) {77 if (!m_debug_info_enabled) {78 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),79 __FUNCTION__);80 return 0;81 }82 return m_sym_file_impl->ParseFunctions(comp_unit);83}84 85bool SymbolFileOnDemand::ParseLineTable(CompileUnit &comp_unit) {86 if (!m_debug_info_enabled) {87 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),88 __FUNCTION__);89 return false;90 }91 return m_sym_file_impl->ParseLineTable(comp_unit);92}93 94bool SymbolFileOnDemand::ParseDebugMacros(CompileUnit &comp_unit) {95 if (!m_debug_info_enabled) {96 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),97 __FUNCTION__);98 return false;99 }100 return m_sym_file_impl->ParseDebugMacros(comp_unit);101}102 103bool SymbolFileOnDemand::ForEachExternalModule(104 CompileUnit &comp_unit,105 llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,106 llvm::function_ref<bool(Module &)> lambda) {107 if (!m_debug_info_enabled) {108 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),109 __FUNCTION__);110 // Return false to not early exit.111 return false;112 }113 return m_sym_file_impl->ForEachExternalModule(comp_unit, visited_symbol_files,114 lambda);115}116 117bool SymbolFileOnDemand::ParseSupportFiles(CompileUnit &comp_unit,118 SupportFileList &support_files) {119 LLDB_LOG(GetLog(),120 "[{0}] {1} is not skipped: explicitly allowed to support breakpoint",121 GetSymbolFileName(), __FUNCTION__);122 // Explicitly allow this API through to support source line breakpoint.123 return m_sym_file_impl->ParseSupportFiles(comp_unit, support_files);124}125 126bool SymbolFileOnDemand::ParseIsOptimized(CompileUnit &comp_unit) {127 if (!m_debug_info_enabled) {128 Log *log = GetLog();129 LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);130 if (log) {131 bool optimized = m_sym_file_impl->ParseIsOptimized(comp_unit);132 if (optimized) {133 LLDB_LOG(log, "Would return optimized if hydrated.");134 }135 }136 return false;137 }138 return m_sym_file_impl->ParseIsOptimized(comp_unit);139}140 141size_t SymbolFileOnDemand::ParseTypes(CompileUnit &comp_unit) {142 if (!m_debug_info_enabled) {143 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),144 __FUNCTION__);145 return 0;146 }147 return m_sym_file_impl->ParseTypes(comp_unit);148}149 150bool SymbolFileOnDemand::ParseImportedModules(151 const lldb_private::SymbolContext &sc,152 std::vector<SourceModule> &imported_modules) {153 if (!m_debug_info_enabled) {154 Log *log = GetLog();155 LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);156 if (log) {157 std::vector<SourceModule> tmp_imported_modules;158 bool succeed =159 m_sym_file_impl->ParseImportedModules(sc, tmp_imported_modules);160 if (succeed)161 LLDB_LOG(log, "{0} imported modules would be parsed if hydrated.",162 tmp_imported_modules.size());163 }164 return false;165 }166 return m_sym_file_impl->ParseImportedModules(sc, imported_modules);167}168 169size_t SymbolFileOnDemand::ParseBlocksRecursive(Function &func) {170 if (!m_debug_info_enabled) {171 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),172 __FUNCTION__);173 return 0;174 }175 return m_sym_file_impl->ParseBlocksRecursive(func);176}177 178size_t SymbolFileOnDemand::ParseVariablesForContext(const SymbolContext &sc) {179 if (!m_debug_info_enabled) {180 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),181 __FUNCTION__);182 return 0;183 }184 return m_sym_file_impl->ParseVariablesForContext(sc);185}186 187Type *SymbolFileOnDemand::ResolveTypeUID(lldb::user_id_t type_uid) {188 if (!m_debug_info_enabled) {189 Log *log = GetLog();190 LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);191 if (log) {192 Type *resolved_type = m_sym_file_impl->ResolveTypeUID(type_uid);193 if (resolved_type)194 LLDB_LOG(log, "Type would be parsed for {0} if hydrated.", type_uid);195 }196 return nullptr;197 }198 return m_sym_file_impl->ResolveTypeUID(type_uid);199}200 201std::optional<SymbolFile::ArrayInfo>202SymbolFileOnDemand::GetDynamicArrayInfoForUID(203 lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {204 if (!m_debug_info_enabled) {205 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),206 __FUNCTION__);207 return std::nullopt;208 }209 return m_sym_file_impl->GetDynamicArrayInfoForUID(type_uid, exe_ctx);210}211 212bool SymbolFileOnDemand::CompleteType(CompilerType &compiler_type) {213 if (!m_debug_info_enabled) {214 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),215 __FUNCTION__);216 return false;217 }218 return m_sym_file_impl->CompleteType(compiler_type);219}220 221CompilerDecl SymbolFileOnDemand::GetDeclForUID(lldb::user_id_t type_uid) {222 if (!m_debug_info_enabled) {223 Log *log = GetLog();224 LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);225 if (log) {226 CompilerDecl parsed_decl = m_sym_file_impl->GetDeclForUID(type_uid);227 if (parsed_decl != CompilerDecl()) {228 LLDB_LOG(log, "CompilerDecl {0} would be parsed for {1} if hydrated.",229 parsed_decl.GetName(), type_uid);230 }231 }232 return CompilerDecl();233 }234 return m_sym_file_impl->GetDeclForUID(type_uid);235}236 237CompilerDeclContext238SymbolFileOnDemand::GetDeclContextForUID(lldb::user_id_t type_uid) {239 if (!m_debug_info_enabled) {240 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),241 __FUNCTION__);242 return CompilerDeclContext();243 }244 return m_sym_file_impl->GetDeclContextForUID(type_uid);245}246 247CompilerDeclContext248SymbolFileOnDemand::GetDeclContextContainingUID(lldb::user_id_t type_uid) {249 if (!m_debug_info_enabled) {250 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),251 __FUNCTION__);252 return CompilerDeclContext();253 }254 return m_sym_file_impl->GetDeclContextContainingUID(type_uid);255}256 257void SymbolFileOnDemand::ParseDeclsForContext(CompilerDeclContext decl_ctx) {258 if (!m_debug_info_enabled) {259 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),260 __FUNCTION__);261 return;262 }263 return m_sym_file_impl->ParseDeclsForContext(decl_ctx);264}265 266uint32_t267SymbolFileOnDemand::ResolveSymbolContext(const Address &so_addr,268 SymbolContextItem resolve_scope,269 SymbolContext &sc) {270 if (!m_debug_info_enabled) {271 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),272 __FUNCTION__);273 return 0;274 }275 return m_sym_file_impl->ResolveSymbolContext(so_addr, resolve_scope, sc);276}277 278Status SymbolFileOnDemand::CalculateFrameVariableError(StackFrame &frame) {279 if (!m_debug_info_enabled) {280 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),281 __FUNCTION__);282 return Status();283 }284 return m_sym_file_impl->CalculateFrameVariableError(frame);285}286 287uint32_t SymbolFileOnDemand::ResolveSymbolContext(288 const SourceLocationSpec &src_location_spec,289 SymbolContextItem resolve_scope, SymbolContextList &sc_list) {290 if (!m_debug_info_enabled) {291 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),292 __FUNCTION__);293 return 0;294 }295 return m_sym_file_impl->ResolveSymbolContext(src_location_spec, resolve_scope,296 sc_list);297}298 299void SymbolFileOnDemand::Dump(lldb_private::Stream &s) {300 if (!m_debug_info_enabled) {301 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),302 __FUNCTION__);303 return;304 }305 return m_sym_file_impl->Dump(s);306}307 308void SymbolFileOnDemand::DumpClangAST(lldb_private::Stream &s,309 llvm::StringRef filter, bool show_color) {310 if (!m_debug_info_enabled) {311 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),312 __FUNCTION__);313 return;314 }315 return m_sym_file_impl->DumpClangAST(s, filter, show_color);316}317 318void SymbolFileOnDemand::FindGlobalVariables(const RegularExpression ®ex,319 uint32_t max_matches,320 VariableList &variables) {321 if (!m_debug_info_enabled) {322 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),323 __FUNCTION__);324 return;325 }326 return m_sym_file_impl->FindGlobalVariables(regex, max_matches, variables);327}328 329void SymbolFileOnDemand::FindGlobalVariables(330 ConstString name, const CompilerDeclContext &parent_decl_ctx,331 uint32_t max_matches, VariableList &variables) {332 if (!m_debug_info_enabled) {333 Log *log = GetLog();334 Symtab *symtab = GetSymtab();335 if (!symtab) {336 LLDB_LOG(log, "[{0}] {1} is skipped - fail to get symtab",337 GetSymbolFileName(), __FUNCTION__);338 return;339 }340 Symbol *sym = symtab->FindFirstSymbolWithNameAndType(341 name, eSymbolTypeData, Symtab::eDebugAny, Symtab::eVisibilityAny);342 if (!sym) {343 LLDB_LOG(log, "[{0}] {1} is skipped - fail to find match in symtab",344 GetSymbolFileName(), __FUNCTION__);345 return;346 }347 LLDB_LOG(log, "[{0}] {1} is NOT skipped - found match in symtab",348 GetSymbolFileName(), __FUNCTION__);349 350 // Found match in symbol table hydrate debug info and351 // allow the FindGlobalVariables to go through.352 SetLoadDebugInfoEnabled();353 }354 return m_sym_file_impl->FindGlobalVariables(name, parent_decl_ctx,355 max_matches, variables);356}357 358void SymbolFileOnDemand::FindFunctions(const RegularExpression ®ex,359 bool include_inlines,360 SymbolContextList &sc_list) {361 if (!m_debug_info_enabled) {362 Log *log = GetLog();363 Symtab *symtab = GetSymtab();364 if (!symtab) {365 LLDB_LOG(log, "[{0}] {1} is skipped - fail to get symtab",366 GetSymbolFileName(), __FUNCTION__);367 return;368 }369 std::vector<uint32_t> symbol_indexes;370 symtab->AppendSymbolIndexesMatchingRegExAndType(371 regex, eSymbolTypeAny, Symtab::eDebugAny, Symtab::eVisibilityAny,372 symbol_indexes);373 if (symbol_indexes.empty()) {374 LLDB_LOG(log, "[{0}] {1} is skipped - fail to find match in symtab",375 GetSymbolFileName(), __FUNCTION__);376 return;377 }378 LLDB_LOG(log, "[{0}] {1} is NOT skipped - found match in symtab",379 GetSymbolFileName(), __FUNCTION__);380 381 // Found match in symbol table hydrate debug info and382 // allow the FindFucntions to go through.383 SetLoadDebugInfoEnabled();384 }385 return m_sym_file_impl->FindFunctions(regex, include_inlines, sc_list);386}387 388void SymbolFileOnDemand::FindFunctions(389 const Module::LookupInfo &lookup_info,390 const CompilerDeclContext &parent_decl_ctx, bool include_inlines,391 SymbolContextList &sc_list) {392 ConstString name = lookup_info.GetLookupName();393 FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();394 if (!m_debug_info_enabled) {395 Log *log = GetLog();396 397 Symtab *symtab = GetSymtab();398 if (!symtab) {399 LLDB_LOG(log, "[{0}] {1}({2}) is skipped - fail to get symtab",400 GetSymbolFileName(), __FUNCTION__, name);401 return;402 }403 404 SymbolContextList sc_list_helper;405 symtab->FindFunctionSymbols(name, name_type_mask, sc_list_helper);406 if (sc_list_helper.GetSize() == 0) {407 LLDB_LOG(log, "[{0}] {1}({2}) is skipped - fail to find match in symtab",408 GetSymbolFileName(), __FUNCTION__, name);409 return;410 }411 LLDB_LOG(log, "[{0}] {1}({2}) is NOT skipped - found match in symtab",412 GetSymbolFileName(), __FUNCTION__, name);413 414 // Found match in symbol table hydrate debug info and415 // allow the FindFucntions to go through.416 SetLoadDebugInfoEnabled();417 }418 return m_sym_file_impl->FindFunctions(lookup_info, parent_decl_ctx,419 include_inlines, sc_list);420}421 422void SymbolFileOnDemand::GetMangledNamesForFunction(423 const std::string &scope_qualified_name,424 std::vector<ConstString> &mangled_names) {425 if (!m_debug_info_enabled) {426 Log *log = GetLog();427 LLDB_LOG(log, "[{0}] {1}({2}) is skipped", GetSymbolFileName(),428 __FUNCTION__, scope_qualified_name);429 return;430 }431 return m_sym_file_impl->GetMangledNamesForFunction(scope_qualified_name,432 mangled_names);433}434 435void SymbolFileOnDemand::FindTypes(const TypeQuery &match,436 TypeResults &results) {437 if (!m_debug_info_enabled) {438 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),439 __FUNCTION__);440 return;441 }442 return m_sym_file_impl->FindTypes(match, results);443}444 445void SymbolFileOnDemand::GetTypes(SymbolContextScope *sc_scope,446 TypeClass type_mask, TypeList &type_list) {447 if (!m_debug_info_enabled) {448 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),449 __FUNCTION__);450 return;451 }452 return m_sym_file_impl->GetTypes(sc_scope, type_mask, type_list);453}454 455llvm::Expected<lldb::TypeSystemSP>456SymbolFileOnDemand::GetTypeSystemForLanguage(LanguageType language) {457 if (!m_debug_info_enabled) {458 Log *log = GetLog();459 LLDB_LOG(log, "[{0}] {1} is skipped for language type {2}",460 GetSymbolFileName(), __FUNCTION__, language);461 return llvm::createStringError(462 "GetTypeSystemForLanguage is skipped by SymbolFileOnDemand");463 }464 return m_sym_file_impl->GetTypeSystemForLanguage(language);465}466 467CompilerDeclContext468SymbolFileOnDemand::FindNamespace(ConstString name,469 const CompilerDeclContext &parent_decl_ctx,470 bool only_root_namespaces) {471 if (!m_debug_info_enabled) {472 LLDB_LOG(GetLog(), "[{0}] {1}({2}) is skipped", GetSymbolFileName(),473 __FUNCTION__, name);474 return SymbolFile::FindNamespace(name, parent_decl_ctx,475 only_root_namespaces);476 }477 return m_sym_file_impl->FindNamespace(name, parent_decl_ctx,478 only_root_namespaces);479}480 481std::vector<std::unique_ptr<lldb_private::CallEdge>>482SymbolFileOnDemand::ParseCallEdgesInFunction(UserID func_id) {483 if (!m_debug_info_enabled) {484 Log *log = GetLog();485 LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);486 if (log) {487 std::vector<std::unique_ptr<lldb_private::CallEdge>> call_edges =488 m_sym_file_impl->ParseCallEdgesInFunction(func_id);489 if (call_edges.size() > 0) {490 LLDB_LOG(log, "{0} call edges would be parsed for {1} if hydrated.",491 call_edges.size(), func_id.GetID());492 }493 }494 return {};495 }496 return m_sym_file_impl->ParseCallEdgesInFunction(func_id);497}498 499lldb::UnwindPlanSP500SymbolFileOnDemand::GetUnwindPlan(const Address &address,501 const RegisterInfoResolver &resolver) {502 if (!m_debug_info_enabled) {503 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),504 __FUNCTION__);505 return nullptr;506 }507 return m_sym_file_impl->GetUnwindPlan(address, resolver);508}509 510llvm::Expected<lldb::addr_t>511SymbolFileOnDemand::GetParameterStackSize(Symbol &symbol) {512 if (!m_debug_info_enabled) {513 Log *log = GetLog();514 LLDB_LOG(log, "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__);515 if (log) {516 llvm::Expected<lldb::addr_t> stack_size =517 m_sym_file_impl->GetParameterStackSize(symbol);518 if (stack_size) {519 LLDB_LOG(log, "{0} stack size would return for symbol {1} if hydrated.",520 *stack_size, symbol.GetName());521 }522 }523 return SymbolFile::GetParameterStackSize(symbol);524 }525 return m_sym_file_impl->GetParameterStackSize(symbol);526}527 528void SymbolFileOnDemand::PreloadSymbols() {529 m_preload_symbols = true;530 if (!m_debug_info_enabled) {531 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),532 __FUNCTION__);533 return;534 }535 return m_sym_file_impl->PreloadSymbols();536}537 538uint64_t SymbolFileOnDemand::GetDebugInfoSize(bool load_all_debug_info) {539 // Always return the real debug info size.540 LLDB_LOG(GetLog(), "[{0}] {1} is not skipped", GetSymbolFileName(),541 __FUNCTION__);542 return m_sym_file_impl->GetDebugInfoSize(load_all_debug_info);543}544 545StatsDuration::Duration SymbolFileOnDemand::GetDebugInfoParseTime() {546 // Always return the real parse time.547 LLDB_LOG(GetLog(), "[{0}] {1} is not skipped", GetSymbolFileName(),548 __FUNCTION__);549 return m_sym_file_impl->GetDebugInfoParseTime();550}551 552StatsDuration::Duration SymbolFileOnDemand::GetDebugInfoIndexTime() {553 // Always return the real index time.554 LLDB_LOG(GetLog(), "[{0}] {1} is not skipped", GetSymbolFileName(),555 __FUNCTION__);556 return m_sym_file_impl->GetDebugInfoIndexTime();557}558 559void SymbolFileOnDemand::ResetStatistics() {560 LLDB_LOG(GetLog(), "[{0}] {1} is not skipped", GetSymbolFileName(),561 __FUNCTION__);562 return m_sym_file_impl->ResetStatistics();563}564 565void SymbolFileOnDemand::SetLoadDebugInfoEnabled() {566 if (m_debug_info_enabled)567 return;568 LLDB_LOG(GetLog(), "[{0}] Hydrate debug info", GetSymbolFileName());569 m_debug_info_enabled = true;570 InitializeObject();571 if (m_preload_symbols)572 PreloadSymbols();573}574 575uint32_t SymbolFileOnDemand::GetNumCompileUnits() {576 LLDB_LOG(GetLog(), "[{0}] {1} is not skipped to support breakpoint hydration",577 GetSymbolFileName(), __FUNCTION__);578 return m_sym_file_impl->GetNumCompileUnits();579}580 581CompUnitSP SymbolFileOnDemand::GetCompileUnitAtIndex(uint32_t idx) {582 LLDB_LOG(GetLog(), "[{0}] {1} is not skipped to support breakpoint hydration",583 GetSymbolFileName(), __FUNCTION__);584 return m_sym_file_impl->GetCompileUnitAtIndex(idx);585}586 587uint32_t SymbolFileOnDemand::GetAbilities() {588 if (!m_debug_info_enabled) {589 LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),590 __FUNCTION__);591 return 0;592 }593 return m_sym_file_impl->GetAbilities();594}595