99// Main header include
1010#include " DynamicLoaderDumpWithModuleList.h"
1111
12+ #include " lldb/Core/Debugger.h"
1213#include " lldb/Core/Module.h"
1314#include " lldb/Core/PluginManager.h"
1415#include " lldb/Target/Process.h"
1516#include " lldb/Utility/LLDBLog.h"
1617#include " lldb/Utility/Log.h"
18+ #include " llvm/Support/ThreadPool.h"
1719
1820#include " Plugins/ObjectFile/Placeholder/ObjectFilePlaceholder.h"
21+ #include < mutex>
1922#include < regex>
2023
2124using namespace lldb ;
@@ -53,6 +56,26 @@ DynamicLoaderDumpWithModuleList::DynamicLoaderDumpWithModuleList(
5356
5457DynamicLoaderDumpWithModuleList::~DynamicLoaderDumpWithModuleList () {}
5558
59+ void DynamicLoaderDumpWithModuleList::SetLoadedModule (const ModuleSP &module_sp,
60+ addr_t link_map_addr) {
61+ llvm::sys::ScopedWriter lock (m_loaded_modules_rw_mutex);
62+ m_loaded_modules[module_sp] = link_map_addr;
63+ }
64+
65+ void DynamicLoaderDumpWithModuleList::UnloadModule (const ModuleSP &module_sp) {
66+ llvm::sys::ScopedWriter lock (m_loaded_modules_rw_mutex);
67+ m_loaded_modules.erase (module_sp);
68+ }
69+
70+ std::optional<lldb::addr_t >
71+ DynamicLoaderDumpWithModuleList::GetLoadedModuleLinkAddr (const ModuleSP &module_sp) {
72+ llvm::sys::ScopedReader lock (m_loaded_modules_rw_mutex);
73+ auto it = m_loaded_modules.find (module_sp);
74+ if (it != m_loaded_modules.end ())
75+ return it->second ;
76+ return std::nullopt ;
77+ }
78+
5679std::optional<const LoadedModuleInfoList::LoadedModuleInfo>
5780DynamicLoaderDumpWithModuleList::GetModuleInfo (lldb::addr_t module_base_addr) {
5881 if (m_module_addr_to_info_map.empty ()) {
@@ -201,11 +224,23 @@ void DynamicLoaderDumpWithModuleList::DidAttach() {
201224 LoadVDSO ();
202225
203226 ModuleList module_list;
227+
228+ // Collect module information first
229+ std::vector<ModuleInfo> module_info_list;
204230 LoadAllModules ([&](const std::string &name, addr_t base_addr,
205231 addr_t module_size, addr_t link_map_addr) {
206232 // vdso module has already been loaded.
207233 if (base_addr == m_vdso_base)
208234 return ;
235+ module_info_list.emplace_back (ModuleInfo{name, base_addr, module_size, link_map_addr});
236+ });
237+
238+ // Load modules in parallel or sequentially based on target setting
239+ auto load_module_fn = [this , &module_list, &log](const ModuleInfo &module_info) {
240+ const std::string &name = module_info.name ;
241+ addr_t base_addr = module_info.base_addr ;
242+ addr_t module_size = module_info.module_size ;
243+ addr_t link_map_addr = module_info.link_map_addr ;
209244
210245 FileSpec file (name, m_process->GetTarget ().GetArchitecture ().GetTriple ());
211246 const bool base_addr_is_offset = false ;
@@ -214,6 +249,10 @@ void DynamicLoaderDumpWithModuleList::DidAttach() {
214249 if (module_sp.get ()) {
215250 LLDB_LOGF (log, " LoadAllCurrentModules loading module at 0x%lX: %s" ,
216251 base_addr, name.c_str ());
252+ // Note: in a multi-threaded environment, these module lists may be
253+ // appended to out-of-order. This is fine, since there's no
254+ // expectation for `module_list` to be in any particular order, and
255+ // appending to the module list is thread-safe.
217256 module_list.Append (module_sp);
218257 } else {
219258 LLDB_LOGF (
@@ -229,8 +268,18 @@ void DynamicLoaderDumpWithModuleList::DidAttach() {
229268 base_addr_is_offset);
230269 m_process->GetTarget ().GetImages ().Append (module_sp, /* notify*/ true );
231270 }
232- m_loaded_modules[module_sp] = link_map_addr;
233- });
271+ SetLoadedModule (module_sp, link_map_addr);
272+ };
273+
274+ if (m_process->GetTarget ().GetParallelModuleLoad ()) {
275+ llvm::ThreadPoolTaskGroup task_group (Debugger::GetThreadPool ());
276+ for (const auto &module_info : module_info_list)
277+ task_group.async (load_module_fn, module_info);
278+ task_group.wait ();
279+ } else {
280+ for (const auto &module_info : module_info_list)
281+ load_module_fn (module_info);
282+ }
234283
235284 m_process->GetTarget ().ModulesDidLoad (module_list);
236285}
@@ -273,15 +322,15 @@ lldb::addr_t DynamicLoaderDumpWithModuleList::GetThreadLocalData(
273322 const lldb::ModuleSP module_sp, const lldb::ThreadSP thread,
274323 lldb::addr_t tls_file_addr) {
275324 Log *log = GetLog (LLDBLog::DynamicLoader);
276- auto it = m_loaded_modules. find (module_sp);
277- if (it == m_loaded_modules. end ()) {
325+ std::optional< addr_t > link_map_addr_opt = GetLoadedModuleLinkAddr (module_sp);
326+ if (!link_map_addr_opt. has_value ()) {
278327 LLDB_LOGF (
279328 log, " GetThreadLocalData error: module(%s) not found in loaded modules" ,
280329 module_sp->GetObjectName ().AsCString ());
281330 return LLDB_INVALID_ADDRESS;
282331 }
283332
284- addr_t link_map = it-> second ;
333+ addr_t link_map = link_map_addr_opt. value () ;
285334 if (link_map == LLDB_INVALID_ADDRESS || link_map == 0 ) {
286335 LLDB_LOGF (log,
287336 " GetThreadLocalData error: invalid link map address=0x%" PRIx64,
0 commit comments