Skip to content

Commit ffd2e0c

Browse files
author
Tom Yang
committed
move preload out of GetOrCreateModules and parallelize
Summary: Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D86004440
1 parent e5f3d7f commit ffd2e0c

File tree

10 files changed

+92
-35
lines changed

10 files changed

+92
-35
lines changed

lldb/include/lldb/Core/ModuleList.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,9 @@ class ModuleList {
511511
/// Atomically swaps the contents of this module list with \a other.
512512
void Swap(ModuleList &other);
513513

514+
/// For each module in this ModuleList, preload its symbols.
515+
void PreloadSymbols() const;
516+
514517
protected:
515518
// Class typedefs.
516519
typedef std::vector<lldb::ModuleSP>

lldb/include/lldb/Target/DynamicLoader.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,17 @@ class DynamicLoader : public PluginInterface {
207207
/// resulting module at the virtual base address \p base_addr.
208208
/// Note that this calls Target::GetOrCreateModule with notify being false,
209209
/// so it is necessary to call Target::ModulesDidLoad afterwards.
210+
///
211+
/// \param[in] defer_module_preload
212+
/// If the module needs to be loaded, prevent the module from being
213+
/// preloaded even if the user sets the preload symbols option. This is
214+
/// used as a performance optimization should the caller preload the
215+
/// modules in parallel after calling this function.
210216
virtual lldb::ModuleSP LoadModuleAtAddress(const lldb_private::FileSpec &file,
211217
lldb::addr_t link_map_addr,
212218
lldb::addr_t base_addr,
213-
bool base_addr_is_offset);
219+
bool base_addr_is_offset,
220+
bool defer_module_preload = false);
214221

215222
/// Find/load a binary into lldb given a UUID and the address where it is
216223
/// loaded in memory, or a slide to be applied to the file address.
@@ -352,7 +359,13 @@ class DynamicLoader : public PluginInterface {
352359
protected:
353360
// Utility methods for derived classes
354361

355-
lldb::ModuleSP FindModuleViaTarget(const FileSpec &file);
362+
/// Find a module in the target that matches the given file.
363+
///
364+
/// \param[in] defer_module_preload
365+
/// If the module needs to be loaded, prevent the module from being
366+
/// preloaded even if the user sets the preload symbols option.
367+
lldb::ModuleSP FindModuleViaTarget(const FileSpec &file,
368+
bool defer_module_preload = false);
356369

357370
/// Checks to see if the target module has changed, updates the target
358371
/// accordingly and returns the target executable module.

lldb/include/lldb/Target/Target.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,12 +649,20 @@ class Target : public std::enable_shared_from_this<Target>,
649649
/// will handle / summarize the failures in a custom way and
650650
/// don't use these messages.
651651
///
652+
/// \param[in] defer_preload
653+
/// If true, the module will not be preloaded even if
654+
/// Target::GetPreloadSymbols() is true. This is useful when the caller
655+
/// wishes to preload loaded modules in parallel after calling this
656+
/// function for better performance. This is because it's currently not
657+
/// thread-safe to do so during the execution of this function.
658+
///
652659
/// \return
653660
/// An empty ModuleSP will be returned if no matching file
654661
/// was found. If error_ptr was non-nullptr, an error message
655662
/// will likely be provided.
656663
lldb::ModuleSP GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
657-
Status *error_ptr = nullptr);
664+
Status *error_ptr = nullptr,
665+
bool defer_preload = false);
658666

659667
// Settings accessors
660668

lldb/source/Core/DynamicLoader.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,8 @@ DynamicLoader::GetSectionListFromModule(const ModuleSP module) const {
154154
return sections;
155155
}
156156

157-
ModuleSP DynamicLoader::FindModuleViaTarget(const FileSpec &file) {
157+
ModuleSP DynamicLoader::FindModuleViaTarget(const FileSpec &file,
158+
bool defer_module_preload) {
158159
Target &target = m_process->GetTarget();
159160
ModuleSpec module_spec(file, target.GetArchitecture());
160161
if (UUID uuid = m_process->FindModuleUUID(file.GetPath())) {
@@ -165,7 +166,9 @@ ModuleSP DynamicLoader::FindModuleViaTarget(const FileSpec &file) {
165166
if (ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec))
166167
return module_sp;
167168

168-
if (ModuleSP module_sp = target.GetOrCreateModule(module_spec, false))
169+
if (ModuleSP module_sp = target.GetOrCreateModule(
170+
module_spec, false /* notify */, nullptr /* error_ptr */,
171+
defer_module_preload))
169172
return module_sp;
170173

171174
return nullptr;
@@ -174,8 +177,9 @@ ModuleSP DynamicLoader::FindModuleViaTarget(const FileSpec &file) {
174177
ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
175178
addr_t link_map_addr,
176179
addr_t base_addr,
177-
bool base_addr_is_offset) {
178-
if (ModuleSP module_sp = FindModuleViaTarget(file)) {
180+
bool base_addr_is_offset,
181+
bool defer_module_preload) {
182+
if (ModuleSP module_sp = FindModuleViaTarget(file, defer_module_preload)) {
179183
UpdateLoadedSections(module_sp, link_map_addr, base_addr,
180184
base_addr_is_offset);
181185
return module_sp;

lldb/source/Core/ModuleList.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "lldb/Core/Debugger.h"
910
#include "lldb/Core/ModuleList.h"
1011
#include "lldb/Core/Module.h"
1112
#include "lldb/Core/ModuleSpec.h"
@@ -15,6 +16,7 @@
1516
#include "lldb/Interpreter/OptionValueFileSpecList.h"
1617
#include "lldb/Interpreter/OptionValueProperties.h"
1718
#include "lldb/Interpreter/Property.h"
19+
#include "llvm/Support/ThreadPool.h"
1820
#include "lldb/Symbol/ObjectFile.h"
1921
#include "lldb/Symbol/SymbolContext.h"
2022
#include "lldb/Symbol/TypeList.h"
@@ -1357,3 +1359,14 @@ void ModuleList::Swap(ModuleList &other) {
13571359
m_modules_mutex, other.m_modules_mutex);
13581360
m_modules.swap(other.m_modules);
13591361
}
1362+
1363+
void ModuleList::PreloadSymbols() const {
1364+
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
1365+
llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool());
1366+
for (const ModuleSP &module_sp : m_modules)
1367+
task_group.async([module_sp] {
1368+
if (module_sp)
1369+
module_sp->PreloadSymbols();
1370+
});
1371+
// task group destructor waits for all tasks to complete
1372+
}

lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,8 @@ void DynamicLoaderPOSIXDYLD::RefreshModules() {
453453
// exists for the duration of this call in `m_rendezvous`.
454454
auto load_module_fn =
455455
[this, &loaded_modules, &new_modules,
456-
&interpreter_module_mutex](const DYLDRendezvous::SOEntry &so_entry) {
456+
&interpreter_module_mutex](const DYLDRendezvous::SOEntry &so_entry,
457+
bool defer_module_preload) {
457458
// Don't load a duplicate copy of ld.so if we have already loaded it
458459
// earlier in LoadInterpreterModule. If we instead loaded then
459460
// unloaded it later, the section information for ld.so would be
@@ -469,7 +470,8 @@ void DynamicLoaderPOSIXDYLD::RefreshModules() {
469470
}
470471

471472
ModuleSP module_sp = LoadModuleAtAddress(
472-
so_entry.file_spec, so_entry.link_addr, so_entry.base_addr, true);
473+
so_entry.file_spec, so_entry.link_addr, so_entry.base_addr,
474+
true /* base_addr_is_offset */, defer_module_preload);
473475
if (!module_sp.get())
474476
return;
475477

@@ -503,11 +505,14 @@ void DynamicLoaderPOSIXDYLD::RefreshModules() {
503505
if (m_process->GetTarget().GetParallelModuleLoad()) {
504506
llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool());
505507
for (; I != E; ++I)
506-
task_group.async(load_module_fn, *I);
508+
task_group.async(load_module_fn, *I, true /* defer_module_preload */);
507509
task_group.wait();
510+
511+
if (m_process->GetTarget().GetPreloadSymbols())
512+
new_modules.PreloadSymbols();
508513
} else {
509514
for (; I != E; ++I)
510-
load_module_fn(*I);
515+
load_module_fn(*I, false /* defer_module_preload */);
511516
}
512517

513518
m_process->GetTarget().ModulesDidLoad(new_modules);
@@ -644,12 +649,12 @@ ModuleSP DynamicLoaderPOSIXDYLD::LoadInterpreterModule() {
644649
return nullptr;
645650
}
646651

647-
ModuleSP DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file,
648-
addr_t link_map_addr,
649-
addr_t base_addr,
650-
bool base_addr_is_offset) {
652+
ModuleSP DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(
653+
const FileSpec &file, addr_t link_map_addr, addr_t base_addr,
654+
bool base_addr_is_offset, bool defer_module_preload) {
651655
if (ModuleSP module_sp = DynamicLoader::LoadModuleAtAddress(
652-
file, link_map_addr, base_addr, base_addr_is_offset))
656+
file, link_map_addr, base_addr, base_addr_is_offset,
657+
defer_module_preload))
653658
return module_sp;
654659

655660
// This works around an dynamic linker "bug" on android <= 23, where the
@@ -668,7 +673,7 @@ ModuleSP DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file,
668673
!(memory_info.GetName().IsEmpty())) {
669674
if (ModuleSP module_sp = DynamicLoader::LoadModuleAtAddress(
670675
FileSpec(memory_info.GetName().GetStringRef()), link_map_addr,
671-
base_addr, base_addr_is_offset))
676+
base_addr, base_addr_is_offset, defer_module_preload))
672677
return module_sp;
673678
}
674679
}
@@ -704,9 +709,11 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() {
704709
module_names, m_process->GetTarget().GetArchitecture().GetTriple());
705710

706711
auto load_module_fn = [this, &module_list,
707-
&log](const DYLDRendezvous::SOEntry &so_entry) {
708-
ModuleSP module_sp = LoadModuleAtAddress(
709-
so_entry.file_spec, so_entry.link_addr, so_entry.base_addr, true);
712+
&log](const DYLDRendezvous::SOEntry &so_entry,
713+
bool defer_module_preload) {
714+
ModuleSP module_sp =
715+
LoadModuleAtAddress(so_entry.file_spec, so_entry.link_addr,
716+
so_entry.base_addr, true, defer_module_preload);
710717
if (module_sp.get()) {
711718
LLDB_LOG(log, "LoadAllCurrentModules loading module: {0}",
712719
so_entry.file_spec.GetFilename());
@@ -723,11 +730,14 @@ void DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() {
723730
if (m_process->GetTarget().GetParallelModuleLoad()) {
724731
llvm::ThreadPoolTaskGroup task_group(Debugger::GetThreadPool());
725732
for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
726-
task_group.async(load_module_fn, *I);
733+
task_group.async(load_module_fn, *I, true /* defer_module_preload */);
727734
task_group.wait();
735+
736+
if (m_process->GetTarget().GetPreloadSymbols())
737+
module_list.PreloadSymbols();
728738
} else {
729739
for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) {
730-
load_module_fn(*I);
740+
load_module_fn(*I, false /* defer_module_preload */);
731741
}
732742
}
733743

lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,11 @@ class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader {
5555
// PluginInterface protocol
5656
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
5757

58-
lldb::ModuleSP LoadModuleAtAddress(const lldb_private::FileSpec &file,
59-
lldb::addr_t link_map_addr,
60-
lldb::addr_t base_addr,
61-
bool base_addr_is_offset) override;
58+
lldb::ModuleSP
59+
LoadModuleAtAddress(const lldb_private::FileSpec &file,
60+
lldb::addr_t link_map_addr, lldb::addr_t base_addr,
61+
bool base_addr_is_offset,
62+
bool defer_module_preload = false) override;
6263

6364
void CalculateDynamicSaveCoreRanges(
6465
lldb_private::Process &process,

lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,11 @@ ThreadPlanSP DynamicLoaderWasmDYLD::GetStepThroughTrampolinePlan(Thread &thread,
6767

6868
lldb::ModuleSP DynamicLoaderWasmDYLD::LoadModuleAtAddress(
6969
const lldb_private::FileSpec &file, lldb::addr_t link_map_addr,
70-
lldb::addr_t base_addr, bool base_addr_is_offset) {
70+
lldb::addr_t base_addr, bool base_addr_is_offset,
71+
bool defer_module_preload) {
7172
if (ModuleSP module_sp = DynamicLoader::LoadModuleAtAddress(
72-
file, link_map_addr, base_addr, base_addr_is_offset))
73+
file, link_map_addr, base_addr, base_addr_is_offset,
74+
defer_module_preload))
7375
return module_sp;
7476

7577
if (ModuleSP module_sp = m_process->ReadModuleFromMemory(file, base_addr)) {

lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ class DynamicLoaderWasmDYLD : public DynamicLoader {
3333
Status CanLoadImage() override { return Status(); }
3434
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
3535
bool stop) override;
36-
lldb::ModuleSP LoadModuleAtAddress(const lldb_private::FileSpec &file,
37-
lldb::addr_t link_map_addr,
38-
lldb::addr_t base_addr,
39-
bool base_addr_is_offset) override;
36+
lldb::ModuleSP
37+
LoadModuleAtAddress(const lldb_private::FileSpec &file,
38+
lldb::addr_t link_map_addr, lldb::addr_t base_addr,
39+
bool base_addr_is_offset,
40+
bool defer_module_preload = false) override;
4041

4142
/// \}
4243

lldb/source/Target/Target.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2342,7 +2342,8 @@ bool Target::ReadPointerFromMemory(const Address &addr, Status &error,
23422342
}
23432343

23442344
ModuleSP Target::GetOrCreateModule(const ModuleSpec &orig_module_spec,
2345-
bool notify, Status *error_ptr) {
2345+
bool notify, Status *error_ptr,
2346+
bool defer_preload) {
23462347
ModuleSP module_sp;
23472348

23482349
Status error;
@@ -2406,7 +2407,7 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &orig_module_spec,
24062407
module_spec.GetFileSpec().GetDirectory(), transformed_dir)) {
24072408
transformed_spec.GetFileSpec().SetDirectory(transformed_dir);
24082409
transformed_spec.GetFileSpec().SetFilename(
2409-
module_spec.GetFileSpec().GetFilename());
2410+
module_spec.GetFileSpec().GetFilename());
24102411
error = ModuleList::GetSharedModule(transformed_spec, module_sp,
24112412
&search_paths, &old_modules,
24122413
&did_create_module);
@@ -2510,8 +2511,9 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &orig_module_spec,
25102511

25112512
// Preload symbols outside of any lock, so hopefully we can do this for
25122513
// each library in parallel.
2513-
if (GetPreloadSymbols())
2514+
if (GetPreloadSymbols() && !defer_preload)
25142515
module_sp->PreloadSymbols();
2516+
25152517
llvm::SmallVector<ModuleSP, 1> replaced_modules;
25162518
for (ModuleSP &old_module_sp : old_modules) {
25172519
if (m_images.GetIndexForModule(old_module_sp.get()) !=

0 commit comments

Comments
 (0)