From 1724a179e7ae2d0485f0fc8fee7ac3a18cc29152 Mon Sep 17 00:00:00 2001 From: Jason Molenda Date: Mon, 8 Apr 2019 23:03:02 +0000 Subject: [PATCH] Rename Target::GetSharedModule to Target::GetOrCreateModule. Add a flag to control whether the ModulesDidLoad notification is called when a module is added. If the notifications are disabled, the caller must call ModulesDidLoad after adding all the new modules, but postponing this notification until they're all batched up can allow for better efficiency than notifying one-by-one. Change the name of the ModuleList notifier functions that a subclass can implement to start with 'Notify' to make it clear what they are. Add a NotifyModulesRemoved. Add header documentation for the changed/updated methods. Added defaulted-value 'notify' argument to ModuleList Append, AppendIfNeeded, and Remove because callers working with a local ModuleList don't have an obvious idea of what notify means in this context. When the ModuleList is a part of the Target class, the notify behavior matters. DynamicLoaderDarwin has been updated so that libraries being added/removed are correctly batched up before notifications are sent. Added the TestModuleLoadedNotifys.py test to run on Darwin to test this. Differential Revision: https://reviews.llvm.org/D60172 llvm-svn: 357955 --- lldb/include/lldb/Core/ModuleList.h | 67 +++++++++--- lldb/include/lldb/Target/Target.h | 57 +++++++++-- .../target-new-solib-notifications/Makefile | 5 + .../TestModuleLoadedNotifys.py | 114 +++++++++++++++++++++ .../target-new-solib-notifications/main.cpp | 6 ++ lldb/source/API/SBTarget.cpp | 5 +- lldb/source/Commands/CommandObjectTarget.cpp | 9 +- lldb/source/Core/DynamicLoader.cpp | 8 +- lldb/source/Core/ModuleList.cpp | 26 +++-- lldb/source/Expression/FunctionCaller.cpp | 3 +- .../Darwin-Kernel/DynamicLoaderDarwinKernel.cpp | 2 +- .../Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp | 2 +- .../MacOSX-DYLD/DynamicLoaderDarwin.cpp | 7 +- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 3 +- .../Windows-DYLD/DynamicLoaderWindowsDYLD.cpp | 6 +- .../Process/Windows/Common/ProcessWindows.cpp | 3 +- .../Plugins/Process/elf-core/ProcessElfCore.cpp | 3 +- .../Plugins/Process/minidump/ProcessMinidump.cpp | 8 +- lldb/source/Target/Target.cpp | 39 +++++-- 19 files changed, 305 insertions(+), 68 deletions(-) create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py create mode 100644 lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/main.cpp diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index eec176d..9c24794 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -96,14 +96,16 @@ public: public: virtual ~Notifier() = default; - virtual void ModuleAdded(const ModuleList &module_list, - const lldb::ModuleSP &module_sp) = 0; - virtual void ModuleRemoved(const ModuleList &module_list, - const lldb::ModuleSP &module_sp) = 0; - virtual void ModuleUpdated(const ModuleList &module_list, - const lldb::ModuleSP &old_module_sp, - const lldb::ModuleSP &new_module_sp) = 0; - virtual void WillClearList(const ModuleList &module_list) = 0; + virtual void NotifyModuleAdded(const ModuleList &module_list, + const lldb::ModuleSP &module_sp) = 0; + virtual void NotifyModuleRemoved(const ModuleList &module_list, + const lldb::ModuleSP &module_sp) = 0; + virtual void NotifyModuleUpdated(const ModuleList &module_list, + const lldb::ModuleSP &old_module_sp, + const lldb::ModuleSP &new_module_sp) = 0; + virtual void NotifyWillClearList(const ModuleList &module_list) = 0; + + virtual void NotifyModulesRemoved(lldb_private::ModuleList &module_list) = 0; }; //------------------------------------------------------------------ @@ -146,12 +148,20 @@ public: //------------------------------------------------------------------ /// Append a module to the module list. /// - /// Appends the module to the collection. - /// /// \param[in] module_sp /// A shared pointer to a module to add to this collection. + /// + /// \param[in] notify + /// If true, and a notifier function is set, the notifier function + /// will be called. Defaults to true. + /// + /// When this ModuleList is the Target's ModuleList, the notifier + /// function is Target::ModulesDidLoad -- the call to + /// ModulesDidLoad may be deferred when adding multiple Modules + /// to the Target, but it must be called at the end, + /// before resuming execution. //------------------------------------------------------------------ - void Append(const lldb::ModuleSP &module_sp); + void Append(const lldb::ModuleSP &module_sp, bool notify = true); //------------------------------------------------------------------ /// Append a module to the module list and remove any equivalent modules. @@ -165,7 +175,22 @@ public: //------------------------------------------------------------------ void ReplaceEquivalent(const lldb::ModuleSP &module_sp); - bool AppendIfNeeded(const lldb::ModuleSP &module_sp); + //------------------------------------------------------------------ + /// Append a module to the module list, if it is not already there. + /// + /// \param[in] module_sp + /// + /// \param[in] notify + /// If true, and a notifier function is set, the notifier function + /// will be called. Defaults to true. + /// + /// When this ModuleList is the Target's ModuleList, the notifier + /// function is Target::ModulesDidLoad -- the call to + /// ModulesDidLoad may be deferred when adding multiple Modules + /// to the Target, but it must be called at the end, + /// before resuming execution. + //------------------------------------------------------------------ + bool AppendIfNeeded(const lldb::ModuleSP &module_sp, bool notify = true); void Append(const ModuleList &module_list); @@ -481,7 +506,23 @@ public: std::vector
&output_local, std::vector
&output_extern); - bool Remove(const lldb::ModuleSP &module_sp); + //------------------------------------------------------------------ + /// Remove a module from the module list. + /// + /// \param[in] module_sp + /// A shared pointer to a module to remove from this collection. + /// + /// \param[in] notify + /// If true, and a notifier function is set, the notifier function + /// will be called. Defaults to true. + /// + /// When this ModuleList is the Target's ModuleList, the notifier + /// function is Target::ModulesDidUnload -- the call to + /// ModulesDidUnload may be deferred when removing multiple Modules + /// from the Target, but it must be called at the end, + /// before resuming execution. + //------------------------------------------------------------------ + bool Remove(const lldb::ModuleSP &module_sp, bool notify = true); size_t Remove(ModuleList &module_list); diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 715017f..530615a 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -505,8 +505,42 @@ public: static void SetDefaultArchitecture(const ArchSpec &arch); - lldb::ModuleSP GetSharedModule(const ModuleSpec &module_spec, - Status *error_ptr = nullptr); + //------------------------------------------------------------------ + /// Find a binary on the system and return its Module, + /// or return an existing Module that is already in the Target. + /// + /// Given a ModuleSpec, find a binary satisifying that specification, + /// or identify a matching Module already present in the Target, + /// and return a shared pointer to it. + /// + /// \param[in] module_spec + /// The criteria that must be matched for the binary being loaded. + /// e.g. UUID, architecture, file path. + /// + /// \param[in] notify + /// If notify is true, and the Module is new to this Target, + /// Target::ModulesDidLoad will be called. + /// If notify is false, it is assumed that the caller is adding + /// multiple Modules and will call ModulesDidLoad with the + /// full list at the end. + /// ModulesDidLoad must be called when a Module/Modules have + /// been added to the target, one way or the other. + /// + /// \param[out] error_ptr + /// Optional argument, pointing to a Status object to fill in + /// with any results / messages while attempting to find/load + /// this binary. Many callers will be internal functions that + /// will handle / summarize the failures in a custom way and + /// don't use these messages. + /// + /// \return + /// An empty ModuleSP will be returned if no matching file + /// was found. If error_ptr was non-nullptr, an error message + /// will likely be provided. + //------------------------------------------------------------------ + lldb::ModuleSP GetOrCreateModule(const ModuleSpec &module_spec, + bool notify, + Status *error_ptr = nullptr); //---------------------------------------------------------------------- // Settings accessors @@ -1250,16 +1284,19 @@ protected: /// Implementing of ModuleList::Notifier. //------------------------------------------------------------------ - void ModuleAdded(const ModuleList &module_list, - const lldb::ModuleSP &module_sp) override; + void NotifyModuleAdded(const ModuleList &module_list, + const lldb::ModuleSP &module_sp) override; + + void NotifyModuleRemoved(const ModuleList &module_list, + const lldb::ModuleSP &module_sp) override; + + void NotifyModuleUpdated(const ModuleList &module_list, + const lldb::ModuleSP &old_module_sp, + const lldb::ModuleSP &new_module_sp) override; - void ModuleRemoved(const ModuleList &module_list, - const lldb::ModuleSP &module_sp) override; + void NotifyWillClearList(const ModuleList &module_list) override; - void ModuleUpdated(const ModuleList &module_list, - const lldb::ModuleSP &old_module_sp, - const lldb::ModuleSP &new_module_sp) override; - void WillClearList(const ModuleList &module_list) override; + void NotifyModulesRemoved(lldb_private::ModuleList &module_list) override; class Arch { public: diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/Makefile b/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/Makefile new file mode 100644 index 0000000..8a7102e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py b/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py new file mode 100644 index 0000000..e6614b0 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/TestModuleLoadedNotifys.py @@ -0,0 +1,114 @@ +""" +Test how many times newly loaded binaries are notified; +they should be delivered in batches instead of one-by-one. +""" + +from __future__ import print_function + + +import os +import time +import re +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class ModuleLoadedNotifysTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + # DyanmicLoaderDarwin should batch up notifications about + # newly added/removed libraries. Other DynamicLoaders may + # not be written this way. + @skipUnlessDarwin + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.line = line_number('main.cpp', '// breakpoint') + + def test_launch_notifications(self): + """Test that lldb broadcasts newly loaded libraries in batches.""" + self.build() + exe = self.getBuildArtifact("a.out") + self.dbg.SetAsync(False) + + listener = self.dbg.GetListener() + listener.StartListeningForEventClass( + self.dbg, + lldb.SBTarget.GetBroadcasterClassName(), + lldb.SBTarget.eBroadcastBitModulesLoaded | lldb.SBTarget.eBroadcastBitModulesUnloaded) + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # break on main + breakpoint = target.BreakpointCreateByName('main', 'a.out') + + event = lldb.SBEvent() + # CreateTarget() generated modules-loaded events; consume them & toss + while listener.GetNextEvent(event): + True + + error = lldb.SBError() + process = target.Launch(listener, + None, # argv + None, # envp + None, # stdin_path + None, # stdout_path + None, # stderr_path + None, # working directory + 0, # launch flags + False, # Stop at entry + error) # error + + self.assertTrue( + process.GetState() == lldb.eStateStopped, + PROCESS_STOPPED) + + total_solibs_added = 0 + total_solibs_removed = 0 + total_modules_added_events = 0 + total_modules_removed_events = 0 + while listener.GetNextEvent(event): + if lldb.SBTarget.EventIsTargetEvent(event): + if event.GetType() == lldb.SBTarget.eBroadcastBitModulesLoaded: + solib_count = lldb.SBTarget.GetNumModulesFromEvent(event) + total_modules_added_events += 1 + total_solibs_added += solib_count + if self.TraceOn(): + # print all of the binaries that have been added + added_files = [] + i = 0 + while i < solib_count: + module = lldb.SBTarget.GetModuleAtIndexFromEvent(i, event) + added_files.append(module.GetFileSpec().GetFilename()) + i = i + 1 + print("Loaded files: %s" % (', '.join(added_files))) + + if event.GetType() == lldb.SBTarget.eBroadcastBitModulesUnloaded: + solib_count = lldb.SBTarget.GetNumModulesFromEvent(event) + total_modules_removed_events += 1 + total_solibs_removed += solib_count + if self.TraceOn(): + # print all of the binaries that have been removed + removed_files = [] + i = 0 + while i < solib_count: + module = lldb.SBTarget.GetModuleAtIndexFromEvent(i, event) + removed_files.append(module.GetFileSpec().GetFilename()) + i = i + 1 + print("Unloaded files: %s" % (', '.join(removed_files))) + + + # This is testing that we get back a small number of events with the loaded + # binaries in batches. Check that we got back more than 1 solib per event. + # In practice on Darwin today, we get back two events for a do-nothing c + # program: a.out and dyld, and then all the rest of the system libraries. + + avg_solibs_added_per_event = int(float(total_solibs_added) / float(total_modules_added_events)) + self.assertGreater(avg_solibs_added_per_event, 1) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/main.cpp new file mode 100644 index 0000000..00130c9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/functionalities/target-new-solib-notifications/main.cpp @@ -0,0 +1,6 @@ +#include +int main () +{ + puts("running"); // breakpoint here + return 0; +} diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index e17355f..fefc70a 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -1591,7 +1591,7 @@ lldb::SBModule SBTarget::AddModule(const char *path, const char *triple, if (symfile) module_spec.GetSymbolFileSpec().SetFile(symfile, FileSpec::Style::native); - sb_module.SetSP(target_sp->GetSharedModule(module_spec)); + sb_module.SetSP(target_sp->GetOrCreateModule(module_spec, true /* notify */)); } return LLDB_RECORD_RESULT(sb_module); } @@ -1603,7 +1603,8 @@ lldb::SBModule SBTarget::AddModule(const SBModuleSpec &module_spec) { lldb::SBModule sb_module; TargetSP target_sp(GetSP()); if (target_sp) - sb_module.SetSP(target_sp->GetSharedModule(*module_spec.m_opaque_up)); + sb_module.SetSP(target_sp->GetOrCreateModule(*module_spec.m_opaque_up, + true /* notify */)); return LLDB_RECORD_RESULT(sb_module); } diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 6051b6c..a76fb9b 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -395,7 +395,8 @@ protected: debugger.GetTargetList().SetSelectedTarget(target_sp.get()); if (must_set_platform_path) { ModuleSpec main_module_spec(file_spec); - ModuleSP module_sp = target_sp->GetSharedModule(main_module_spec); + ModuleSP module_sp = target_sp->GetOrCreateModule(main_module_spec, + true /* notify */); if (module_sp) module_sp->SetPlatformFileSpec(remote_file); } @@ -2598,7 +2599,8 @@ protected: module_spec.GetSymbolFileSpec() = m_symbol_file.GetOptionValue().GetCurrentValue(); if (Symbols::DownloadObjectAndSymbolFile(module_spec)) { - ModuleSP module_sp(target->GetSharedModule(module_spec)); + ModuleSP module_sp(target->GetOrCreateModule(module_spec, + true /* notify */)); if (module_sp) { result.SetStatus(eReturnStatusSuccessFinishResult); return true; @@ -2660,7 +2662,8 @@ protected: if (!module_spec.GetArchitecture().IsValid()) module_spec.GetArchitecture() = target->GetArchitecture(); Status error; - ModuleSP module_sp(target->GetSharedModule(module_spec, &error)); + ModuleSP module_sp(target->GetOrCreateModule(module_spec, + true /* notify */, &error)); if (!module_sp) { const char *error_cstr = error.AsCString(); if (error_cstr) diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp index a580539..c773caa 100644 --- a/lldb/source/Core/DynamicLoader.cpp +++ b/lldb/source/Core/DynamicLoader.cpp @@ -96,7 +96,7 @@ ModuleSP DynamicLoader::GetTargetExecutable() { } if (!executable) { - executable = target.GetSharedModule(module_spec); + executable = target.GetOrCreateModule(module_spec, true /* notify */); if (executable.get() != target.GetExecutableModulePointer()) { // Don't load dependent images since we are in dyld where we will // know and find out about all images that are loaded @@ -166,7 +166,8 @@ ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file, return module_sp; } - if ((module_sp = target.GetSharedModule(module_spec))) { + if ((module_sp = target.GetOrCreateModule(module_spec, + true /* notify */))) { UpdateLoadedSections(module_sp, link_map_addr, base_addr, base_addr_is_offset); return module_sp; @@ -202,7 +203,8 @@ ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file, return module_sp; } - if ((module_sp = target.GetSharedModule(new_module_spec))) { + if ((module_sp = target.GetOrCreateModule(new_module_spec, + true /* notify */))) { UpdateLoadedSections(module_sp, link_map_addr, base_addr, false); return module_sp; } diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index d59e429..e02c6e5 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -147,11 +147,13 @@ void ModuleList::AppendImpl(const ModuleSP &module_sp, bool use_notifier) { std::lock_guard guard(m_modules_mutex); m_modules.push_back(module_sp); if (use_notifier && m_notifier) - m_notifier->ModuleAdded(*this, module_sp); + m_notifier->NotifyModuleAdded(*this, module_sp); } } -void ModuleList::Append(const ModuleSP &module_sp) { AppendImpl(module_sp); } +void ModuleList::Append(const ModuleSP &module_sp, bool notify) { + AppendImpl(module_sp, notify); +} void ModuleList::ReplaceEquivalent(const ModuleSP &module_sp) { if (module_sp) { @@ -177,7 +179,7 @@ void ModuleList::ReplaceEquivalent(const ModuleSP &module_sp) { } } -bool ModuleList::AppendIfNeeded(const ModuleSP &module_sp) { +bool ModuleList::AppendIfNeeded(const ModuleSP &module_sp, bool notify) { if (module_sp) { std::lock_guard guard(m_modules_mutex); collection::iterator pos, end = m_modules.end(); @@ -186,7 +188,7 @@ bool ModuleList::AppendIfNeeded(const ModuleSP &module_sp) { return false; // Already in the list } // Only push module_sp on the list if it wasn't already in there. - Append(module_sp); + Append(module_sp, notify); return true; } return false; @@ -214,7 +216,7 @@ bool ModuleList::RemoveImpl(const ModuleSP &module_sp, bool use_notifier) { if (pos->get() == module_sp.get()) { m_modules.erase(pos); if (use_notifier && m_notifier) - m_notifier->ModuleRemoved(*this, module_sp); + m_notifier->NotifyModuleRemoved(*this, module_sp); return true; } } @@ -228,12 +230,12 @@ ModuleList::RemoveImpl(ModuleList::collection::iterator pos, ModuleSP module_sp(*pos); collection::iterator retval = m_modules.erase(pos); if (use_notifier && m_notifier) - m_notifier->ModuleRemoved(*this, module_sp); + m_notifier->NotifyModuleRemoved(*this, module_sp); return retval; } -bool ModuleList::Remove(const ModuleSP &module_sp) { - return RemoveImpl(module_sp); +bool ModuleList::Remove(const ModuleSP &module_sp, bool notify) { + return RemoveImpl(module_sp, notify); } bool ModuleList::ReplaceModule(const lldb::ModuleSP &old_module_sp, @@ -242,7 +244,7 @@ bool ModuleList::ReplaceModule(const lldb::ModuleSP &old_module_sp, return false; AppendImpl(new_module_sp, false); if (m_notifier) - m_notifier->ModuleUpdated(*this, old_module_sp, new_module_sp); + m_notifier->NotifyModuleUpdated(*this, old_module_sp, new_module_sp); return true; } @@ -291,9 +293,11 @@ size_t ModuleList::Remove(ModuleList &module_list) { size_t num_removed = 0; collection::iterator pos, end = module_list.m_modules.end(); for (pos = module_list.m_modules.begin(); pos != end; ++pos) { - if (Remove(*pos)) + if (Remove(*pos, false /* notify */)) ++num_removed; } + if (m_notifier) + m_notifier->NotifyModulesRemoved(module_list); return num_removed; } @@ -304,7 +308,7 @@ void ModuleList::Destroy() { ClearImpl(); } void ModuleList::ClearImpl(bool use_notifier) { std::lock_guard guard(m_modules_mutex); if (use_notifier && m_notifier) - m_notifier->WillClearList(*this); + m_notifier->NotifyWillClearList(*this); m_modules.clear(); } diff --git a/lldb/source/Expression/FunctionCaller.cpp b/lldb/source/Expression/FunctionCaller.cpp index 52c86ff..fa156dc 100644 --- a/lldb/source/Expression/FunctionCaller.cpp +++ b/lldb/source/Expression/FunctionCaller.cpp @@ -103,7 +103,8 @@ bool FunctionCaller::WriteFunctionWrapper( jit_file.GetFilename() = const_func_name; jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString()); m_jit_module_wp = jit_module_sp; - process->GetTarget().GetImages().Append(jit_module_sp); + process->GetTarget().GetImages().Append(jit_module_sp, + true /* notify */); } } if (process && m_jit_start_addr) diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp index d88ce1c..45f6d49 100644 --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -841,7 +841,7 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule( // the DebugSymbols framework with the UUID to find the binary via its // search methods. if (!m_module_sp) { - m_module_sp = target.GetSharedModule(module_spec); + m_module_sp = target.GetOrCreateModule(module_spec, true /* notify */); } if (IsKernel() && !m_module_sp) { diff --git a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp index e6deab8..0fb05e9 100644 --- a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp @@ -199,7 +199,7 @@ ModuleSP DynamicLoaderHexagonDYLD::GetTargetExecutable() { return executable; // TODO: What case is this code used? - executable = target.GetSharedModule(module_spec); + executable = target.GetOrCreateModule(module_spec, true /* notify */); if (executable.get() != target.GetExecutableModulePointer()) { // Don't load dependent images since we are in dyld where we will know and // find out about all images that are loaded diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp index 87e43eb..086169d 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp @@ -122,7 +122,9 @@ ModuleSP DynamicLoaderDarwin::FindTargetModuleForImageInfo( if (!module_sp) { if (can_create) { - module_sp = target.GetSharedModule(module_spec); + // We'll call Target::ModulesDidLoad after all the modules have been + // added to the target, don't let it be called for every one. + module_sp = target.GetOrCreateModule(module_spec, false /* notify */); if (!module_sp || module_sp->GetObjectFile() == NULL) module_sp = m_process->ReadModuleFromMemory(image_info.file_spec, image_info.address); @@ -637,7 +639,8 @@ bool DynamicLoaderDarwin::AddModulesUsingImageInfos( module_spec.SetObjectOffset(objfile->GetFileOffset() + commpage_section->GetFileOffset()); module_spec.SetObjectSize(objfile->GetByteSize()); - commpage_image_module_sp = target.GetSharedModule(module_spec); + commpage_image_module_sp = target.GetOrCreateModule(module_spec, + true /* notify */); if (!commpage_image_module_sp || commpage_image_module_sp->GetObjectFile() == NULL) { commpage_image_module_sp = m_process->ReadModuleFromMemory( diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 6583a80..31ab9fa 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -543,7 +543,8 @@ ModuleSP DynamicLoaderPOSIXDYLD::LoadInterpreterModule() { FileSpec file(info.GetName().GetCString()); ModuleSpec module_spec(file, target.GetArchitecture()); - if (ModuleSP module_sp = target.GetSharedModule(module_spec)) { + if (ModuleSP module_sp = target.GetOrCreateModule(module_spec, + true /* notify */)) { UpdateLoadedSections(module_sp, LLDB_INVALID_ADDRESS, m_interpreter_base, false); return module_sp; diff --git a/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp index a2a17b2..fa3fbe0 100644 --- a/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp @@ -68,11 +68,9 @@ void DynamicLoaderWindowsDYLD::OnLoadModule(lldb::ModuleSP module_sp, // Resolve the module unless we already have one. if (!module_sp) { - // Confusingly, there is no Target::AddSharedModule. Instead, calling - // GetSharedModule() with a new module will add it to the module list and - // return a corresponding ModuleSP. Status error; - module_sp = m_process->GetTarget().GetSharedModule(module_spec, &error); + module_sp = m_process->GetTarget().GetOrCreateModule(module_spec, + true /* notify */, &error); if (error.Fail()) return; } diff --git a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp index 2a248f6..e9146b5 100644 --- a/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp @@ -915,7 +915,8 @@ void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) { FileSystem::Instance().Resolve(executable_file); ModuleSpec module_spec(executable_file); Status error; - module = GetTarget().GetSharedModule(module_spec, &error); + module = GetTarget().GetOrCreateModule(module_spec, + true /* notify */, &error); if (!module) { return; } diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 1c79705..21c9be5 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -244,7 +244,8 @@ Status ProcessElfCore::DoLoadCore() { exe_module_spec.GetFileSpec().SetFile( m_nt_file_entries[0].path.GetCString(), FileSpec::Style::native); if (exe_module_spec.GetFileSpec()) { - exe_module_sp = GetTarget().GetSharedModule(exe_module_spec); + exe_module_sp = GetTarget().GetOrCreateModule(exe_module_spec, + true /* notify */); if (exe_module_sp) GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsNo); } diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp index d6ab58c..3da103b 100644 --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -388,7 +388,8 @@ void ProcessMinidump::ReadModuleList() { Status error; // Try and find a module with a full UUID that matches. This function will // add the module to the target if it finds one. - lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec, &error); + lldb::ModuleSP module_sp = GetTarget().GetOrCreateModule(module_spec, + true /* notify */, &error); if (!module_sp) { // Try and find a module without specifying the UUID and only looking for // the file given a basename. We then will look for a partial UUID match @@ -400,7 +401,8 @@ void ProcessMinidump::ReadModuleList() { ModuleSpec basename_module_spec(module_spec); basename_module_spec.GetUUID().Clear(); basename_module_spec.GetFileSpec().GetDirectory().Clear(); - module_sp = GetTarget().GetSharedModule(basename_module_spec, &error); + module_sp = GetTarget().GetOrCreateModule(basename_module_spec, + true /* notify */, &error); if (module_sp) { // We consider the module to be a match if the minidump UUID is a // prefix of the actual UUID, or if either of the UUIDs are empty. @@ -430,7 +432,7 @@ void ProcessMinidump::ReadModuleList() { module_sp = Module::CreateModuleFromObjectFile( module_spec, module->base_of_image, module->size_of_image); - GetTarget().GetImages().Append(module_sp); + GetTarget().GetImages().Append(module_sp, true /* notify */); } bool load_addr_changed = false; diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index a1bf4d9..f382813 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -1442,7 +1442,8 @@ void Target::SetExecutableModule(ModuleSP &executable_sp, "Target::SetExecutableModule (executable = '%s')", executable_sp->GetFileSpec().GetPath().c_str()); - m_images.Append(executable_sp); // The first image is our executable file + const bool notify = true; + m_images.Append(executable_sp, notify); // The first image is our executable file // If we haven't set an architecture yet, reset our architecture based on // what we found in the executable module. @@ -1470,6 +1471,7 @@ void Target::SetExecutableModule(ModuleSP &executable_sp, } if (executable_objfile && load_dependents) { + ModuleList added_modules; executable_objfile->GetDependentModules(dependent_files); for (uint32_t i = 0; i < dependent_files.GetSize(); i++) { FileSpec dependent_file_spec( @@ -1482,13 +1484,16 @@ void Target::SetExecutableModule(ModuleSP &executable_sp, platform_dependent_file_spec = dependent_file_spec; ModuleSpec module_spec(platform_dependent_file_spec, m_arch.GetSpec()); - ModuleSP image_module_sp(GetSharedModule(module_spec)); + ModuleSP image_module_sp(GetOrCreateModule(module_spec, + false /* notify */)); if (image_module_sp) { + added_modules.AppendIfNeeded (image_module_sp, false); ObjectFile *objfile = image_module_sp->GetObjectFile(); if (objfile) objfile->GetDependentModules(dependent_files); } } + ModulesDidLoad(added_modules); } } } @@ -1606,20 +1611,19 @@ bool Target::MergeArchitecture(const ArchSpec &arch_spec) { return false; } -void Target::WillClearList(const ModuleList &module_list) {} +void Target::NotifyWillClearList(const ModuleList &module_list) {} -void Target::ModuleAdded(const ModuleList &module_list, +void Target::NotifyModuleAdded(const ModuleList &module_list, const ModuleSP &module_sp) { // A module is being added to this target for the first time if (m_valid) { ModuleList my_module_list; my_module_list.Append(module_sp); - LoadScriptingResourceForModule(module_sp, this); ModulesDidLoad(my_module_list); } } -void Target::ModuleRemoved(const ModuleList &module_list, +void Target::NotifyModuleRemoved(const ModuleList &module_list, const ModuleSP &module_sp) { // A module is being removed from this target. if (m_valid) { @@ -1629,7 +1633,7 @@ void Target::ModuleRemoved(const ModuleList &module_list, } } -void Target::ModuleUpdated(const ModuleList &module_list, +void Target::NotifyModuleUpdated(const ModuleList &module_list, const ModuleSP &old_module_sp, const ModuleSP &new_module_sp) { // A module is replacing an already added module @@ -1641,8 +1645,20 @@ void Target::ModuleUpdated(const ModuleList &module_list, } } +void Target::NotifyModulesRemoved(lldb_private::ModuleList &module_list) { + ModulesDidUnload (module_list, false); +} + + void Target::ModulesDidLoad(ModuleList &module_list) { if (m_valid && module_list.GetSize()) { + + const ModuleList &modules = GetImages(); + const size_t num_images = modules.GetSize(); + for (size_t idx = 0; idx < num_images; ++idx) { + ModuleSP module_sp(modules.GetModuleAtIndex(idx)); + LoadScriptingResourceForModule(module_sp, this); + } m_breakpoint_list.UpdateBreakpoints(module_list, true, false); m_internal_breakpoint_list.UpdateBreakpoints(module_list, true, false); if (m_process_sp) { @@ -1984,8 +2000,8 @@ bool Target::ReadPointerFromMemory(const Address &addr, bool prefer_file_cache, return false; } -ModuleSP Target::GetSharedModule(const ModuleSpec &module_spec, - Status *error_ptr) { +ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify, + Status *error_ptr) { ModuleSP module_sp; Status error; @@ -2118,8 +2134,9 @@ ModuleSP Target::GetSharedModule(const ModuleSpec &module_spec, Module *old_module_ptr = old_module_sp.get(); old_module_sp.reset(); ModuleList::RemoveSharedModuleIfOrphaned(old_module_ptr); - } else - m_images.Append(module_sp); + } else { + m_images.Append(module_sp, notify); + } } else module_sp.reset(); } -- 2.7.4