From 7fca8c0757a5ee5f290844376c7f8c5f3c1ffcfe Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Fri, 28 Apr 2017 00:51:06 +0000 Subject: [PATCH] Provide a mechanism to do some pre-loading of symbols up front. Loading a shared library can require a large amount of work; rather than do that serially for each library, this patch will allow parallelization of the symbols and debug info name indexes. From scott.smith@purestorage.com https://reviews.llvm.org/D32598 llvm-svn: 301609 --- lldb/include/lldb/Core/Module.h | 2 ++ lldb/include/lldb/Symbol/SymbolFile.h | 2 ++ lldb/include/lldb/Symbol/Symtab.h | 1 + lldb/include/lldb/Target/Target.h | 4 ++++ .../test/lang/c/shared_lib/TestSharedLib.py | 21 +++++++++++++++++---- lldb/source/Core/Module.cpp | 16 ++++++++++++++++ .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 6 ++++++ .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.h | 2 ++ lldb/source/Symbol/SymbolFile.cpp | 4 ++++ lldb/source/Symbol/Symtab.cpp | 5 +++++ lldb/source/Target/Target.cpp | 19 +++++++++++++++++++ 11 files changed, 78 insertions(+), 4 deletions(-) diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index ca47a38..33735bc 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -614,6 +614,8 @@ public: const FileSpec &GetSymbolFileFileSpec() const { return m_symfile_spec; } + void PreloadSymbols(); + void SetSymbolFileFileSpec(const FileSpec &file); const llvm::sys::TimePoint<> &GetModificationTime() const { diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 34ae8d7..69110dc 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -180,6 +180,8 @@ public: uint32_t type_mask, lldb_private::TypeList &type_list) = 0; + virtual void PreloadSymbols(); + virtual lldb_private::TypeSystem * GetTypeSystemForLanguage(lldb::LanguageType language); diff --git a/lldb/include/lldb/Symbol/Symtab.h b/lldb/include/lldb/Symbol/Symtab.h index 6a8d62c..3d24862 100644 --- a/lldb/include/lldb/Symbol/Symtab.h +++ b/lldb/include/lldb/Symbol/Symtab.h @@ -40,6 +40,7 @@ public: Symtab(ObjectFile *objfile); ~Symtab(); + void PreloadSymbols(); void Reserve(size_t count); Symbol *Resize(size_t count); uint32_t AddSymbol(const Symbol &symbol); diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 8d6fc77..8aa263f 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -82,6 +82,10 @@ public: bool SetPreferDynamicValue(lldb::DynamicValueType d); + bool GetPreloadSymbols() const; + + void SetPreloadSymbols(bool b); + bool GetDisableASLR() const; void SetDisableASLR(bool b); diff --git a/lldb/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py b/lldb/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py index 61a67dc..edc83bf 100644 --- a/lldb/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py +++ b/lldb/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py @@ -13,14 +13,13 @@ class SharedLibTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - def test_expr(self): - """Test that types work when defined in a shared library and forward-declared in the main executable""" + def common_test_expr(self, preload_symbols): if "clang" in self.getCompiler() and "3.4" in self.getCompilerVersion(): self.skipTest( "llvm.org/pr16214 -- clang emits partial DWARF for structures referenced via typedef") self.build() - self.common_setup() + self.common_setup(preload_symbols) # This should display correctly. self.expect( @@ -31,6 +30,18 @@ class SharedLibTestCase(TestBase): "(sub_foo)", "other_element = 3"]) + self.expect( + "expression GetMeASubFoo(my_foo_ptr)", + startstr="(sub_foo *) $") + + def test_expr(self): + """Test that types work when defined in a shared library and forward-declared in the main executable""" + self.common_test_expr(True) + + def test_expr_no_preload(self): + """Test that types work when defined in a shared library and forward-declared in the main executable, but with preloading disabled""" + self.common_test_expr(False) + @unittest2.expectedFailure("rdar://problem/10704639") def test_frame_variable(self): """Test that types work when defined in a shared library and forward-declared in the main executable""" @@ -54,7 +65,7 @@ class SharedLibTestCase(TestBase): self.line = line_number(self.source, '// Set breakpoint 0 here.') self.shlib_names = ["foo"] - def common_setup(self): + def common_setup(self, preload_symbols = True): # Run in synchronous mode self.dbg.SetAsync(False) @@ -62,6 +73,8 @@ class SharedLibTestCase(TestBase): target = self.dbg.CreateTarget("a.out") self.assertTrue(target, VALID_TARGET) + self.runCmd("settings set target.preload-symbols " + str(preload_symbols).lower()) + # Break inside the foo function which takes a bar_ptr argument. lldbutil.run_break_set_by_file_and_line( self, self.source, self.line, num_expected_locations=1, loc_exact=True) diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index ddc9fca..d168474 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -1432,6 +1432,22 @@ size_t Module::FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, return sc_list.GetSize() - initial_size; } +void Module::PreloadSymbols() { + 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->PreloadSymbols(); + } + // Now we can prime the symbol table. + if (Symtab * symtab = sym_vendor->GetSymtab()) { + symtab->PreloadSymbols(); + } +} + void Module::SetSymbolFileFileSpec(const FileSpec &file) { if (!file.Exists()) return; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 973b5ef..8c2fc3d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1917,6 +1917,12 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec, return sc_list.GetSize() - prev_size; } +void SymbolFileDWARF::PreloadSymbols() { + std::lock_guard guard( + GetObjectFile()->GetModule()->GetMutex()); + Index(); +} + void SymbolFileDWARF::Index() { if (m_indexed) return; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 14b29fa..9b1eb1d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -226,6 +226,8 @@ public: const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx) override; + void PreloadSymbols() override; + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ diff --git a/lldb/source/Symbol/SymbolFile.cpp b/lldb/source/Symbol/SymbolFile.cpp index d789891..eb20b80 100644 --- a/lldb/source/Symbol/SymbolFile.cpp +++ b/lldb/source/Symbol/SymbolFile.cpp @@ -21,6 +21,10 @@ using namespace lldb_private; +void SymbolFile::PreloadSymbols() { + // No-op for most implementations. +} + SymbolFile *SymbolFile::FindPlugin(ObjectFile *obj_file) { std::unique_ptr best_symfile_ap; if (obj_file != nullptr) { diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp index 4270298..f4cb49c 100644 --- a/lldb/source/Symbol/Symtab.cpp +++ b/lldb/source/Symbol/Symtab.cpp @@ -427,6 +427,11 @@ void Symtab::InitNameIndexes() { } } +void Symtab::PreloadSymbols() { + 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 { diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index df021e3..5c9e92a 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -1870,6 +1870,11 @@ ModuleSP Target::GetSharedModule(const ModuleSpec &module_spec, } } + // Preload symbols outside of any lock, so hopefully we can do this for + // each library in parallel. + if (GetPreloadSymbols()) + module_sp->PreloadSymbols(); + if (old_module_sp && m_images.GetIndexForModule(old_module_sp.get()) != LLDB_INVALID_INDEX32) { @@ -3277,6 +3282,8 @@ static PropertyDefinition g_properties[] = { {"detach-on-error", OptionValue::eTypeBoolean, false, true, nullptr, nullptr, "debugserver will detach (rather than killing) a process if it " "loses connection with lldb."}, + {"preload-symbols", 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 @@ enum { ePropertyOutputPath, ePropertyErrorPath, ePropertyDetachOnError, + ePropertyPreloadSymbols, ePropertyDisableASLR, ePropertyDisableSTDIO, ePropertyInlineStrategy, @@ -3641,6 +3649,17 @@ bool TargetProperties::SetPreferDynamicValue(lldb::DynamicValueType d) { return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx, d); } +bool TargetProperties::GetPreloadSymbols() const { + const uint32_t idx = ePropertyPreloadSymbols; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); +} + +void TargetProperties::SetPreloadSymbols(bool b) { + const uint32_t idx = ePropertyPreloadSymbols; + m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); +} + bool TargetProperties::GetDisableASLR() const { const uint32_t idx = ePropertyDisableASLR; return m_collection_sp->GetPropertyAtIndexAsBoolean( -- 2.7.4