Index: include/lldb/Core/Module.h =================================================================== --- include/lldb/Core/Module.h +++ include/lldb/Core/Module.h @@ -614,6 +614,8 @@ const FileSpec &GetSymbolFileFileSpec() const { return m_symfile_spec; } + void PrimeCaches(); + void SetSymbolFileFileSpec(const FileSpec &file); const llvm::sys::TimePoint<> &GetModificationTime() const { Index: include/lldb/Symbol/SymbolFile.h =================================================================== --- include/lldb/Symbol/SymbolFile.h +++ include/lldb/Symbol/SymbolFile.h @@ -180,6 +180,8 @@ uint32_t type_mask, lldb_private::TypeList &type_list) = 0; + virtual void PrimeCaches(); + virtual lldb_private::TypeSystem * GetTypeSystemForLanguage(lldb::LanguageType language); Index: include/lldb/Symbol/Symtab.h =================================================================== --- include/lldb/Symbol/Symtab.h +++ include/lldb/Symbol/Symtab.h @@ -40,6 +40,7 @@ Symtab(ObjectFile *objfile); ~Symtab(); + void PrimeCaches(); void Reserve(size_t count); Symbol *Resize(size_t count); uint32_t AddSymbol(const Symbol &symbol); Index: include/lldb/Target/Target.h =================================================================== --- include/lldb/Target/Target.h +++ include/lldb/Target/Target.h @@ -82,6 +82,10 @@ bool SetPreferDynamicValue(lldb::DynamicValueType d); + bool GetCachePriming() const; + + void SetCachePriming(bool b); + bool GetDisableASLR() const; void SetDisableASLR(bool b); Index: source/Core/Module.cpp =================================================================== --- source/Core/Module.cpp +++ source/Core/Module.cpp @@ -1432,6 +1432,22 @@ return sc_list.GetSize() - initial_size; } +void Module::PrimeCaches() { + std::lock_guard guard(m_mutex); + SymbolVendor * sym_vendor = GetSymbolVendor(); + if (!sym_vendor) { + return; + } + // Prime the symbol file first, since it adds symbols to the symbol table. + if (SymbolFile *symbol_file = sym_vendor->GetSymbolFile()) { + symbol_file->PrimeCaches(); + } + // Now we can prime the symbol table. + if (Symtab * symtab = sym_vendor->GetSymtab()) { + symtab->PrimeCaches(); + } +} + void Module::SetSymbolFileFileSpec(const FileSpec &file) { if (!file.Exists()) return; Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -226,6 +226,8 @@ const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx) override; + void PrimeCaches() override; + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1917,6 +1917,12 @@ return sc_list.GetSize() - prev_size; } +void SymbolFileDWARF::PrimeCaches() { + std::lock_guard guard( + GetObjectFile()->GetModule()->GetMutex()); + Index(); +} + void SymbolFileDWARF::Index() { if (m_indexed) return; Index: source/Symbol/SymbolFile.cpp =================================================================== --- source/Symbol/SymbolFile.cpp +++ source/Symbol/SymbolFile.cpp @@ -21,6 +21,10 @@ using namespace lldb_private; +void SymbolFile::PrimeCaches() { + // No-op for most implementations. +} + SymbolFile *SymbolFile::FindPlugin(ObjectFile *obj_file) { std::unique_ptr best_symfile_ap; if (obj_file != nullptr) { Index: source/Symbol/Symtab.cpp =================================================================== --- source/Symbol/Symtab.cpp +++ source/Symbol/Symtab.cpp @@ -425,6 +425,11 @@ } } +void Symtab::PrimeCaches() { + std::lock_guard guard(m_mutex); + InitNameIndexes(); +} + void Symtab::AppendSymbolNamesToMap(const IndexCollection &indexes, bool add_demangled, bool add_mangled, NameToIndexMap &name_to_index_map) const { Index: source/Target/Target.cpp =================================================================== --- source/Target/Target.cpp +++ source/Target/Target.cpp @@ -1870,6 +1870,11 @@ } } + // Prime caches outside of any lock, so hopefully we can do this for + // each library in parallel. + if (GetCachePriming()) + module_sp->PrimeCaches(); + if (old_module_sp && m_images.GetIndexForModule(old_module_sp.get()) != LLDB_INVALID_INDEX32) { @@ -3277,6 +3282,8 @@ {"detach-on-error", OptionValue::eTypeBoolean, false, true, nullptr, nullptr, "debugserver will detach (rather than killing) a process if it " "loses connection with lldb."}, + {"cache-priming", OptionValue::eTypeBoolean, false, true, nullptr, nullptr, + "Enable loading of symbol tables before they are needed."}, {"disable-aslr", OptionValue::eTypeBoolean, false, true, nullptr, nullptr, "Disable Address Space Layout Randomization (ASLR)"}, {"disable-stdio", OptionValue::eTypeBoolean, false, false, nullptr, nullptr, @@ -3379,6 +3386,7 @@ ePropertyOutputPath, ePropertyErrorPath, ePropertyDetachOnError, + ePropertyCachePriming, ePropertyDisableASLR, ePropertyDisableSTDIO, ePropertyInlineStrategy, @@ -3641,6 +3649,17 @@ return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx, d); } +bool TargetProperties::GetCachePriming() const { + const uint32_t idx = ePropertyCachePriming; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); +} + +void TargetProperties::SetCachePriming(bool b) { + const uint32_t idx = ePropertyCachePriming; + m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); +} + bool TargetProperties::GetDisableASLR() const { const uint32_t idx = ePropertyDisableASLR; return m_collection_sp->GetPropertyAtIndexAsBoolean(