-
Notifications
You must be signed in to change notification settings - Fork 340
[LLDB] Deterministic module order in Target::SetExecutableModule
#10746
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: stable/20240723
Are you sure you want to change the base?
[LLDB] Deterministic module order in Target::SetExecutableModule
#10746
Conversation
This change separates module loading from symbol preloading to ensure a deterministic module loading order. Parallel module loading was causing non-deterministic behavior, but we only need to load symbols in parallel as that's the heavy part of the process.
@swift-ci Please test |
/// will likely be provided. | ||
lldb::ModuleSP GetOrCreateModule( | ||
const ModuleSpec &module_spec, bool notify, | ||
llvm::function_ref<void(std::function<void()>)> scheduleSymbolsPreload, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need a separate overload for this or could we use a default value of nullptr
for scheduleSymbolsPreload
? It looks like llvm::function_ref
has a suitable operator bool()
defined.
I suppose it might require updating more callsites that currently pass the Status
output pointer.
@@ -0,0 +1,26 @@ | |||
C_SOURCES := main.c | |||
LD_EXTRAS := -L. -la -lb -lc -ld -le |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ran into a few problems when running this test on linux.
- The
-lc
was confusing the locally build libc.so with the "real" libc and causing linking errors. - The linked shared libraries did not use a full path so only the basename is stored in the DT_NEEDED section. This does not resolve to a unique file location so it they are skipped by the load dependent code.
I worked around the first problem by not linking libc.so
into a.out
. But then when running the test with trace enabled I see the following output.
First run module list: ['a.out']
Run 2 module list: ['a.out']
...
Obviously this is not going to detect a non-deterministic module order for linux. But if we change it to link to the full path of the shared objects
--- a/lldb/test/API/functionalities/deterministic_module_order/Makefile
+++ b/lldb/test/API/functionalities/deterministic_module_order/Makefile
@@ -1,9 +1,12 @@
C_SOURCES := main.c
-LD_EXTRAS := -L. -la -lb -lc -ld -le
+include Makefile.rules
+
+# Use full path to shared libraries to make test effective on linux.
+LD_EXTRAS := $(BUILDDIR)/liba.so $(BUILDDIR)/libb.so $(BUILDDIR)/libc.so $(BUILDDIR)/libd.so $(BUILDDIR)/libe.so
a.out: liba libb libc libd libe
-include Makefile.rules
+
Then the test looks like it would work
First run module list: ['a.out', 'liba.so', 'libb.so', 'libc.so', 'libd.so', 'libe.so']
Run 2 module list: ['a.out', 'liba.so', 'libb.so', 'libc.so', 'libd.so', 'libe.so']
...
ModuleSpec module_spec(platform_dependent_file_spec, m_arch.GetSpec()); | ||
auto image_module_sp = GetOrCreateModule( | ||
module_spec, false /* notify */, | ||
[&](auto preloadSymbols) { task_group.async(preloadSymbols); }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be good to gate the parallel loading of modules here based on the with the target.parallel-module-load
setting.
This change separates module loading from symbol preloading to ensure a deterministic module loading order. Parallel module loading was causing non-deterministic behavior, but we only need to load symbols in parallel as that's the heavy part of the process.
Discussion https://discourse.llvm.org/t/non-deterministic-module-order-in-lldb/86446