https://github.com/zhyty updated https://github.com/llvm/llvm-project/pull/130912
>From fbf25b1cd4f6d527944fb85fc4d2d03498755a05 Mon Sep 17 00:00:00 2001 From: Tom Yang <toy...@fb.com> Date: Mon, 10 Mar 2025 17:58:17 -0700 Subject: [PATCH 1/5] Add option for enabling/disabling parallel load Add a setting to gate the new parallel dynamic library loading feature in the next diff. I followed the example of `lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp` and `lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp` to create a scoped setting for the new feature. NOTE: this setting defaults to FALSE. Users should be able to enable the new feature as easily as adding a line to their .lldbinit file, or manually setting it in their session. ``` (lldb) apropos "POSIX dynamic" No commands found pertaining to 'POSIX dynamic'. Try 'help' to see a complete list of debugger commands. The following settings variables may relate to 'POSIX dynamic': plugin.dynamic-loader.posix-dyld.parallel-module-load -- Enable experimental loading of modules in parallel for the POSIX dynamic loader. (lldb) settings show plugin.dynamic-loader.posix-dyld.parallel-module-load plugin.dynamic-loader.posix-dyld.parallel-module-load (boolean) = false (lldb) settings set plugin.dynamic-loader.posix-dyld.parallel-module-load true (lldb) settings show plugin.dynamic-loader.posix-dyld.parallel-module-load plugin.dynamic-loader.posix-dyld.parallel-module-load (boolean) = true ``` --- .../DynamicLoader/POSIX-DYLD/CMakeLists.txt | 12 +++++ .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 49 ++++++++++++++++++- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.h | 2 + .../DynamicLoaderPOSIXDYLDProperties.td | 8 +++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLDProperties.td diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt index c1e00b2dd444f..532bfb20ea0f1 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt @@ -1,3 +1,11 @@ +lldb_tablegen(DynamicLoaderPOSIXDYLDProperties.inc -gen-lldb-property-defs + SOURCE DynamicLoaderPOSIXDYLDProperties.td + TARGET LLDBPluginDynamicLoaderPOSIXDYLDPropertiesGen) + +lldb_tablegen(DynamicLoaderPOSIXDYLDPropertiesEnum.inc -gen-lldb-property-enum-defs + SOURCE DynamicLoaderPOSIXDYLDProperties.td + TARGET LLDBPluginDynamicLoaderPOSIXDYLDPropertiesEnumGen) + add_lldb_library(lldbPluginDynamicLoaderPosixDYLD PLUGIN DYLDRendezvous.cpp DynamicLoaderPOSIXDYLD.cpp @@ -13,3 +21,7 @@ add_lldb_library(lldbPluginDynamicLoaderPosixDYLD PLUGIN LINK_COMPONENTS Support ) + +add_dependencies(lldbPluginDynamicLoaderPosixDYLD + LLDBPluginDynamicLoaderPOSIXDYLDPropertiesGen + LLDBPluginDynamicLoaderPOSIXDYLDPropertiesEnumGen) diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 53ba11ac21bd3..c89d16649922d 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -34,9 +34,56 @@ using namespace lldb_private; LLDB_PLUGIN_DEFINE_ADV(DynamicLoaderPOSIXDYLD, DynamicLoaderPosixDYLD) +namespace { + +#define LLDB_PROPERTIES_dynamicloaderposixdyld +#include "DynamicLoaderPOSIXDYLDProperties.inc" + +enum { +#define LLDB_PROPERTIES_dynamicloaderposixdyld +#include "DynamicLoaderPOSIXDYLDPropertiesEnum.inc" +}; + +class PluginProperties : public Properties { +public: + static llvm::StringRef GetSettingName() { + return DynamicLoaderPOSIXDYLD::GetPluginNameStatic(); + } + + PluginProperties() : Properties() { + m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); + m_collection_sp->Initialize(g_dynamicloaderposixdyld_properties); + } + + ~PluginProperties() override = default; + + bool GetParallelModuleLoad() const { + const uint32_t idx = ePropertyParallelModuleLoad; + return GetPropertyAtIndexAs<bool>(idx, true); + } +}; + +} // namespace + +static PluginProperties &GetGlobalPluginProperties() { + static PluginProperties g_settings; + return g_settings; +} + void DynamicLoaderPOSIXDYLD::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); + GetPluginDescriptionStatic(), CreateInstance, + &DebuggerInitialize); +} + +void DynamicLoaderPOSIXDYLD::DebuggerInitialize(Debugger &debugger) { + if (!PluginManager::GetSettingForDynamicLoaderPlugin( + debugger, PluginProperties::GetSettingName())) { + const bool is_global_setting = true; + PluginManager::CreateSettingForDynamicLoaderPlugin( + debugger, GetGlobalPluginProperties().GetValueProperties(), + "Properties for the POSIX dynamic loader plug-in.", is_global_setting); + } } void DynamicLoaderPOSIXDYLD::Terminate() {} diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h index bde334aaca40b..5bb1e00dd7df0 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -28,6 +28,8 @@ class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader { static void Initialize(); + static void DebuggerInitialize(lldb_private::Debugger &debugger); + static void Terminate(); static llvm::StringRef GetPluginNameStatic() { return "posix-dyld"; } diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLDProperties.td b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLDProperties.td new file mode 100644 index 0000000000000..68e3448196cec --- /dev/null +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLDProperties.td @@ -0,0 +1,8 @@ + +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "dynamicloaderposixdyld" in { + def ParallelModuleLoad: Property<"parallel-module-load", "Boolean">, + DefaultFalse, + Desc<"Enable experimental loading of modules in parallel for the POSIX dynamic loader.">; +} >From d0f9fadf068e9cc4e5146ef7be46b80bf8584f64 Mon Sep 17 00:00:00 2001 From: Tom Yang <toy...@fb.com> Date: Tue, 11 Mar 2025 10:17:23 -0700 Subject: [PATCH 2/5] parallelize POSIX dyld RefreshModules This diff parallelizes `DynamicLoaderPOSIXDYLD::RefreshModules`, which speeds up module loading on Linux. The major benefit of this is we can speed up symbol table indexing and parsing, which is the biggest bottleneck for targets which dynamically link many shared libraries. This speedup is only noticeable when **preloading** symbols. This is when `target.preload-symbols` is `true`, which is the default Meta. The symbol preload option tells the debugger to fully load all of the symbol tables when modules are loaded, as opposed to lazily loading when symbols are requested. Initially, I discovered the specific bottleneck by using the Linux `perf` tool. I saw that ~93% of samples were in `RefreshModules`, and mainly in `LoadModuleAtAddress` and `PreloadSymbols`. `LoadModuleAtAddress` appears independent and parallelize-able at first. The main issue is `DynamicLoaderPOSIXDYLD` maintains a map of loaded modules to their link addresses via `m_loaded_modules`. Modifying and reading to this map isn't thread-safe, so this diff also includes accessor methods that protect the map in the multithreaded context. Luckily, the critical section of modifying or reading from the map isn't super costly, so the contention doesn't appear to negatively impact performance. I tested with some larger projects with up to 15000 modules, and found significant performance improvements. Typically, I was seeing 2-3X launch speed increases, where "launch speed" is starting the binary and reaching `main`. I manually ran `ninja check-lldb` several times, and compared with the baseline. At this point, we're not seeing any new failures or new unresolved tests. --- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 121 +++++++++++++----- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.h | 17 ++- 2 files changed, 101 insertions(+), 37 deletions(-) diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index c89d16649922d..b1e2ea974c77d 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -10,6 +10,7 @@ #include "DynamicLoaderPOSIXDYLD.h" #include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" @@ -25,6 +26,7 @@ #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/ProcessInfo.h" +#include "llvm/Support/ThreadPool.h" #include <memory> #include <optional> @@ -231,16 +233,37 @@ void DynamicLoaderPOSIXDYLD::DidLaunch() { Status DynamicLoaderPOSIXDYLD::CanLoadImage() { return Status(); } +void DynamicLoaderPOSIXDYLD::SetLoadedModule(const ModuleSP &module_sp, + addr_t link_map_addr) { + std::unique_lock<std::shared_mutex> lock(m_loaded_modules_rw_mutex); + m_loaded_modules[module_sp] = link_map_addr; +} + +void DynamicLoaderPOSIXDYLD::UnloadModule(const ModuleSP &module_sp) { + std::unique_lock<std::shared_mutex> lock(m_loaded_modules_rw_mutex); + m_loaded_modules.erase(module_sp); +} + +std::optional<lldb::addr_t> +DynamicLoaderPOSIXDYLD::GetLoadedModuleLinkAddr(const ModuleSP &module_sp) { + std::shared_lock<std::shared_mutex> lock(m_loaded_modules_rw_mutex); + auto it = m_loaded_modules.find(module_sp); + if (it != m_loaded_modules.end()) + return it->second; + return std::nullopt; +} + void DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr, bool base_addr_is_offset) { - m_loaded_modules[module] = link_map_addr; + SetLoadedModule(module, link_map_addr); + UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset); } void DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module) { - m_loaded_modules.erase(module); + UnloadModule(module); UnloadSectionsCommon(module); } @@ -448,7 +471,7 @@ void DynamicLoaderPOSIXDYLD::RefreshModules() { // The rendezvous class doesn't enumerate the main module, so track that // ourselves here. ModuleSP executable = GetTargetExecutable(); - m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress(); + SetLoadedModule(executable, m_rendezvous.GetLinkMapAddress()); DYLDRendezvous::iterator I; DYLDRendezvous::iterator E; @@ -470,34 +493,66 @@ void DynamicLoaderPOSIXDYLD::RefreshModules() { E = m_rendezvous.end(); m_initial_modules_added = true; } - for (; I != E; ++I) { - // Don't load a duplicate copy of ld.so if we have already loaded it - // earlier in LoadInterpreterModule. If we instead loaded then unloaded it - // later, the section information for ld.so would be removed. That - // information is required for placing breakpoints on Arm/Thumb systems. - if ((m_interpreter_module.lock() != nullptr) && - (I->base_addr == m_interpreter_base)) - continue; - - ModuleSP module_sp = - LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); - if (!module_sp.get()) - continue; - - if (module_sp->GetObjectFile()->GetBaseAddress().GetLoadAddress( - &m_process->GetTarget()) == m_interpreter_base) { - ModuleSP interpreter_sp = m_interpreter_module.lock(); - if (m_interpreter_module.lock() == nullptr) { - m_interpreter_module = module_sp; - } else if (module_sp == interpreter_sp) { - // Module already loaded. - continue; - } - } - loaded_modules.AppendIfNeeded(module_sp); - new_modules.Append(module_sp); + std::mutex interpreter_module_mutex; + // We should be able to take SOEntry as reference since the data + // exists for the duration of this call in `m_rendezvous`. + auto load_module_fn = + [this, &loaded_modules, &new_modules, + &interpreter_module_mutex](const DYLDRendezvous::SOEntry &so_entry) { + // Don't load a duplicate copy of ld.so if we have already loaded it + // earlier in LoadInterpreterModule. If we instead loaded then + // unloaded it later, the section information for ld.so would be + // removed. That information is required for placing breakpoints on + // Arm/Thumb systems. + { + // `m_interpreter_module` may be modified by another thread at the + // same time, so we guard the access here. + std::lock_guard<std::mutex> lock(interpreter_module_mutex); + if ((m_interpreter_module.lock() != nullptr) && + (so_entry.base_addr == m_interpreter_base)) + return; + } + + ModuleSP module_sp = LoadModuleAtAddress( + so_entry.file_spec, so_entry.link_addr, so_entry.base_addr, true); + if (!module_sp.get()) + return; + + { + // `m_interpreter_module` may be modified by another thread at the + // same time, so we guard the access here. + std::lock_guard<std::mutex> lock(interpreter_module_mutex); + // Set the interpreter module, if this is the interpreter. + if (module_sp->GetObjectFile()->GetBaseAddress().GetLoadAddress( + &m_process->GetTarget()) == m_interpreter_base) { + ModuleSP interpreter_sp = m_interpreter_module.lock(); + if (m_interpreter_module.lock() == nullptr) { + m_interpreter_module = module_sp; + } else if (module_sp == interpreter_sp) { + // Module already loaded. + return; + } + } + } + + loaded_modules.AppendIfNeeded(module_sp); + new_modules.Append(module_sp); + }; + + // Loading modules in parallel tends to be faster, but is still unstable. + // Once it's stable, we can remove this setting and remove the serial + // approach. + if (GetGlobalPluginProperties().GetParallelModuleLoad()) { + llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool()); + for (; I != E; ++I) + task_group.async(load_module_fn, *I); + task_group.wait(); + } else { + for (; I != E; ++I) + load_module_fn(*I); } + m_process->GetTarget().ModulesDidLoad(new_modules); } @@ -683,7 +738,7 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { // The rendezvous class doesn't enumerate the main module, so track that // ourselves here. ModuleSP executable = GetTargetExecutable(); - m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress(); + SetLoadedModule(executable, m_rendezvous.GetLinkMapAddress()); std::vector<FileSpec> module_names; for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) @@ -775,15 +830,15 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp, const lldb::ThreadSP thread, lldb::addr_t tls_file_addr) { Log *log = GetLog(LLDBLog::DynamicLoader); - auto it = m_loaded_modules.find(module_sp); - if (it == m_loaded_modules.end()) { + std::optional<addr_t> link_map_addr_opt = GetLoadedModuleLinkAddr(module_sp); + if (!link_map_addr_opt.has_value()) { LLDB_LOGF( log, "GetThreadLocalData error: module(%s) not found in loaded modules", module_sp->GetObjectName().AsCString()); return LLDB_INVALID_ADDRESS; } - addr_t link_map = it->second; + addr_t link_map = link_map_addr_opt.value(); if (link_map == LLDB_INVALID_ADDRESS || link_map == 0) { LLDB_LOGF(log, "GetThreadLocalData error: invalid link map address=0x%" PRIx64, diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h index 5bb1e00dd7df0..183a157654ba2 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -95,10 +95,6 @@ class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader { /// Contains the pointer to the interpret module, if loaded. std::weak_ptr<lldb_private::Module> m_interpreter_module; - /// Loaded module list. (link map for each module) - std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>> - m_loaded_modules; - /// Returns true if the process is for a core file. bool IsCoreFile() const; @@ -182,6 +178,19 @@ class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader { DynamicLoaderPOSIXDYLD(const DynamicLoaderPOSIXDYLD &) = delete; const DynamicLoaderPOSIXDYLD & operator=(const DynamicLoaderPOSIXDYLD &) = delete; + + /// Loaded module list. (link map for each module) + /// This may be accessed in a multi-threaded context. Use the accessor methods + /// to access `m_loaded_modules` safely. + std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>> + m_loaded_modules; + std::shared_mutex m_loaded_modules_rw_mutex; + + void SetLoadedModule(const lldb::ModuleSP &module_sp, + lldb::addr_t link_map_addr); + void UnloadModule(const lldb::ModuleSP &module_sp); + std::optional<lldb::addr_t> + GetLoadedModuleLinkAddr(const lldb::ModuleSP &module_sp); }; #endif // LLDB_SOURCE_PLUGINS_DYNAMICLOADER_POSIX_DYLD_DYNAMICLOADERPOSIXDYLD_H >From 4a4a3550cd5bbb30beb9b86fc301da09e8266303 Mon Sep 17 00:00:00 2001 From: Tom Yang <toy...@fb.com> Date: Tue, 11 Mar 2025 10:35:02 -0700 Subject: [PATCH 3/5] parallelize dyld for attach scenario --- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index b1e2ea974c77d..f6f6057f830fe 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -746,19 +746,31 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { m_process->PrefetchModuleSpecs( module_names, m_process->GetTarget().GetArchitecture().GetTriple()); - for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) { - ModuleSP module_sp = - LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); + auto load_module_fn = [this, &module_list, + &log](const DYLDRendezvous::SOEntry &so_entry) { + ModuleSP module_sp = LoadModuleAtAddress( + so_entry.file_spec, so_entry.link_addr, so_entry.base_addr, true); if (module_sp.get()) { LLDB_LOG(log, "LoadAllCurrentModules loading module: {0}", - I->file_spec.GetFilename()); + so_entry.file_spec.GetFilename()); module_list.Append(module_sp); } else { Log *log = GetLog(LLDBLog::DynamicLoader); LLDB_LOGF( log, "DynamicLoaderPOSIXDYLD::%s failed loading module %s at 0x%" PRIx64, - __FUNCTION__, I->file_spec.GetPath().c_str(), I->base_addr); + __FUNCTION__, so_entry.file_spec.GetPath().c_str(), + so_entry.base_addr); + } + }; + if (GetGlobalPluginProperties().GetParallelModuleLoad()) { + llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool()); + for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) + task_group.async(load_module_fn, *I); + task_group.wait(); + } else { + for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) { + load_module_fn(*I); } } >From 6585ce1b3e4c625d4cd46d63a5cb1d7b167cd1b7 Mon Sep 17 00:00:00 2001 From: Tom Yang <toy...@fb.com> Date: Wed, 19 Mar 2025 11:18:24 -0700 Subject: [PATCH 4/5] move plugin.dynamic-loader.posix-dyld.parallel-module-load to target.parallel-module-load --- lldb/include/lldb/Target/Target.h | 2 + .../DynamicLoader/POSIX-DYLD/CMakeLists.txt | 12 ---- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 56 +------------------ .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.h | 2 - .../DynamicLoaderPOSIXDYLDProperties.td | 8 --- lldb/source/Target/Target.cpp | 6 ++ lldb/source/Target/TargetProperties.td | 3 + 7 files changed, 14 insertions(+), 75 deletions(-) delete mode 100644 lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLDProperties.td diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 98273fb7e1c97..01a928edc384d 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -118,6 +118,8 @@ class TargetProperties : public Properties { llvm::StringRef GetLaunchWorkingDirectory() const; + bool GetParallelModuleLoad() const; + const char *GetDisassemblyFlavor() const; const char *GetDisassemblyCPU() const; diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt index 532bfb20ea0f1..c1e00b2dd444f 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt @@ -1,11 +1,3 @@ -lldb_tablegen(DynamicLoaderPOSIXDYLDProperties.inc -gen-lldb-property-defs - SOURCE DynamicLoaderPOSIXDYLDProperties.td - TARGET LLDBPluginDynamicLoaderPOSIXDYLDPropertiesGen) - -lldb_tablegen(DynamicLoaderPOSIXDYLDPropertiesEnum.inc -gen-lldb-property-enum-defs - SOURCE DynamicLoaderPOSIXDYLDProperties.td - TARGET LLDBPluginDynamicLoaderPOSIXDYLDPropertiesEnumGen) - add_lldb_library(lldbPluginDynamicLoaderPosixDYLD PLUGIN DYLDRendezvous.cpp DynamicLoaderPOSIXDYLD.cpp @@ -21,7 +13,3 @@ add_lldb_library(lldbPluginDynamicLoaderPosixDYLD PLUGIN LINK_COMPONENTS Support ) - -add_dependencies(lldbPluginDynamicLoaderPosixDYLD - LLDBPluginDynamicLoaderPOSIXDYLDPropertiesGen - LLDBPluginDynamicLoaderPOSIXDYLDPropertiesEnumGen) diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index f6f6057f830fe..8c7f523935a92 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -36,56 +36,9 @@ using namespace lldb_private; LLDB_PLUGIN_DEFINE_ADV(DynamicLoaderPOSIXDYLD, DynamicLoaderPosixDYLD) -namespace { - -#define LLDB_PROPERTIES_dynamicloaderposixdyld -#include "DynamicLoaderPOSIXDYLDProperties.inc" - -enum { -#define LLDB_PROPERTIES_dynamicloaderposixdyld -#include "DynamicLoaderPOSIXDYLDPropertiesEnum.inc" -}; - -class PluginProperties : public Properties { -public: - static llvm::StringRef GetSettingName() { - return DynamicLoaderPOSIXDYLD::GetPluginNameStatic(); - } - - PluginProperties() : Properties() { - m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName()); - m_collection_sp->Initialize(g_dynamicloaderposixdyld_properties); - } - - ~PluginProperties() override = default; - - bool GetParallelModuleLoad() const { - const uint32_t idx = ePropertyParallelModuleLoad; - return GetPropertyAtIndexAs<bool>(idx, true); - } -}; - -} // namespace - -static PluginProperties &GetGlobalPluginProperties() { - static PluginProperties g_settings; - return g_settings; -} - void DynamicLoaderPOSIXDYLD::Initialize() { PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance, - &DebuggerInitialize); -} - -void DynamicLoaderPOSIXDYLD::DebuggerInitialize(Debugger &debugger) { - if (!PluginManager::GetSettingForDynamicLoaderPlugin( - debugger, PluginProperties::GetSettingName())) { - const bool is_global_setting = true; - PluginManager::CreateSettingForDynamicLoaderPlugin( - debugger, GetGlobalPluginProperties().GetValueProperties(), - "Properties for the POSIX dynamic loader plug-in.", is_global_setting); - } + GetPluginDescriptionStatic(), CreateInstance); } void DynamicLoaderPOSIXDYLD::Terminate() {} @@ -540,10 +493,7 @@ void DynamicLoaderPOSIXDYLD::RefreshModules() { new_modules.Append(module_sp); }; - // Loading modules in parallel tends to be faster, but is still unstable. - // Once it's stable, we can remove this setting and remove the serial - // approach. - if (GetGlobalPluginProperties().GetParallelModuleLoad()) { + if (m_process->GetTarget().GetParallelModuleLoad()) { llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool()); for (; I != E; ++I) task_group.async(load_module_fn, *I); @@ -763,7 +713,7 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() { so_entry.base_addr); } }; - if (GetGlobalPluginProperties().GetParallelModuleLoad()) { + if (m_process->GetTarget().GetParallelModuleLoad()) { llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool()); for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) task_group.async(load_module_fn, *I); diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h index 183a157654ba2..a41cbfac86349 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -28,8 +28,6 @@ class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader { static void Initialize(); - static void DebuggerInitialize(lldb_private::Debugger &debugger); - static void Terminate(); static llvm::StringRef GetPluginNameStatic() { return "posix-dyld"; } diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLDProperties.td b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLDProperties.td deleted file mode 100644 index 68e3448196cec..0000000000000 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLDProperties.td +++ /dev/null @@ -1,8 +0,0 @@ - -include "../../../../include/lldb/Core/PropertiesBase.td" - -let Definition = "dynamicloaderposixdyld" in { - def ParallelModuleLoad: Property<"parallel-module-load", "Boolean">, - DefaultFalse, - Desc<"Enable experimental loading of modules in parallel for the POSIX dynamic loader.">; -} diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 550424720e095..da3dabb414b8d 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -4502,6 +4502,12 @@ llvm::StringRef TargetProperties::GetLaunchWorkingDirectory() const { idx, g_target_properties[idx].default_cstr_value); } +bool TargetProperties::GetParallelModuleLoad() const { + const uint32_t idx = ePropertyParallelModuleLoad; + return GetPropertyAtIndexAs<bool>( + idx, g_target_properties[idx].default_uint_value != 0); +} + const char *TargetProperties::GetDisassemblyFlavor() const { const uint32_t idx = ePropertyDisassemblyFlavor; const char *return_value; diff --git a/lldb/source/Target/TargetProperties.td b/lldb/source/Target/TargetProperties.td index 38a345dfd8849..3940ac00a2bd9 100644 --- a/lldb/source/Target/TargetProperties.td +++ b/lldb/source/Target/TargetProperties.td @@ -217,6 +217,9 @@ let Definition = "target" in { "launched. If you change this setting, the new value will only apply to " "subsequent launches. Commands that take an explicit working directory " "will override this setting.">; + def ParallelModuleLoad: Property<"parallel-module-load", "Boolean">, + DefaultTrue, + Desc<"Enable loading of modules in parallel for the dynamic loader.">; } let Definition = "process_experimental" in { >From 38a017e9e80ebf274b6af4bfe37e7abcbd5ebf2d Mon Sep 17 00:00:00 2001 From: Tom Yang <toy...@fb.com> Date: Wed, 19 Mar 2025 11:32:39 -0700 Subject: [PATCH 5/5] switch usage of std shared_mutex with rwmutex, which is more portable --- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 13 ++++++++++--- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.h | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 8c7f523935a92..326b6910b5267 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -188,18 +188,18 @@ Status DynamicLoaderPOSIXDYLD::CanLoadImage() { return Status(); } void DynamicLoaderPOSIXDYLD::SetLoadedModule(const ModuleSP &module_sp, addr_t link_map_addr) { - std::unique_lock<std::shared_mutex> lock(m_loaded_modules_rw_mutex); + llvm::sys::ScopedWriter lock(m_loaded_modules_rw_mutex); m_loaded_modules[module_sp] = link_map_addr; } void DynamicLoaderPOSIXDYLD::UnloadModule(const ModuleSP &module_sp) { - std::unique_lock<std::shared_mutex> lock(m_loaded_modules_rw_mutex); + llvm::sys::ScopedWriter lock(m_loaded_modules_rw_mutex); m_loaded_modules.erase(module_sp); } std::optional<lldb::addr_t> DynamicLoaderPOSIXDYLD::GetLoadedModuleLinkAddr(const ModuleSP &module_sp) { - std::shared_lock<std::shared_mutex> lock(m_loaded_modules_rw_mutex); + llvm::sys::ScopedReader lock(m_loaded_modules_rw_mutex); auto it = m_loaded_modules.find(module_sp); if (it != m_loaded_modules.end()) return it->second; @@ -447,6 +447,7 @@ void DynamicLoaderPOSIXDYLD::RefreshModules() { m_initial_modules_added = true; } + // Synchronize reading and writing of `m_interpreter_module`. std::mutex interpreter_module_mutex; // We should be able to take SOEntry as reference since the data // exists for the duration of this call in `m_rendezvous`. @@ -489,6 +490,12 @@ void DynamicLoaderPOSIXDYLD::RefreshModules() { } } + // Note: in a multi-threaded environment, these module lists may be + // appended to out-of-order. This is fine, since there's no + // expectation for `loaded_modules` or `new_modules` to be in any + // particular order, and appending to each module list is thread-safe. + // Also, `new_modules` is only used for the `ModulesDidLoad` call at + // the end of this function. loaded_modules.AppendIfNeeded(module_sp); new_modules.Append(module_sp); }; diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h index a41cbfac86349..6efb92673a13c 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -182,7 +182,7 @@ class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader { /// to access `m_loaded_modules` safely. std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>> m_loaded_modules; - std::shared_mutex m_loaded_modules_rw_mutex; + llvm::sys::RWMutex m_loaded_modules_rw_mutex; void SetLoadedModule(const lldb::ModuleSP &module_sp, lldb::addr_t link_map_addr); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits