-
-
Couldn't load subscription status.
- Fork 5.7k
jl_dlfind: do not find symbols in library dependencies #58815
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
Conversation
|
FWIW, I believe that the macOS / Solaris version of this is called The design of that feature actually means that handle pointers are not unique on macOS (they contain a bit of information to encode whether they have |
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.
On macOS, you can additionally specify RTLD_FIRST when getting these internal handles and (like Windows) avoid the need for the extra dladdr call check
|
I appreciate the very clear writeup given the unintuitive behavior here. |
How do you do that? Does the implementation here need to be changed? |
I thought it might be too breaking, but you're right that code relying on it wouldn't work on Windows anyhow. Looking a bit harder for options on Linux, it seems we can get the handle from an address directly with |
Yeah, it's required to mask off some of the lower bits (see https://github.com/opensource-apple/dyld/blob/3f928f32597888c5eac6003b9199d972d49857b5/src/dyldAPIs.cpp#L1513-L1518 and Lines 668 to 670 in 4ae3f5e
If we use |
This is the only code that relies on it, and mostly just for the purpose of making these platforms act similarly when |
All calls to jl_dlsym from within Julia are now strict about which library the symbol is from. Now only Libdl.dlsym uses the default behaviour, to keep it the same as libc dlsym. On macOS, we can skip the jl_find_dynamic_library_by_addr check if we detect that the handle was opened with RTLD_FIRST. Do this by default for libraries loaded by Julia ccalls.
|
Reviving this! I've made both the internal |
|
The FreeBSD failures look related: EDIT: I'm reminded of #50162, which caused #50846, which was fixed in #51114. @topolarity's description in that last PR seems potentially relevant here. |
|
Investigating this has revealed all sorts of weird stuff:
In fact, we don't really have macOS: |
|
Different failure now on FreeBSD with the most recent commit: |
Turns out this was yet another linuxism we were relying on: you can't |
|
As much as it's tempting to grab the dlopen reference count from the handle and check if we need to avoid dlclose()ing it, the comment for the struct already seems a little angry at the JVM for doing this: https://github.com/freebsd/freebsd-src/blob/a9f5b68837094699a3d5204d79c1cbe59d93ae00/libexec/rtld-elf/rtld.h#L128-L130 |
FreeBSD maintains two separate reference counts inside dlopen handles: one for total references, including transitive dependencies loaded by rtld, and another only for dlopen handles. It checks to make sure that there are unclosed dlopen handles when doing dlsym, so we've got to ensure that at least one handle exists for all the libraries we want to use with jl_find_dynamic_library_by_addr (specifically, libjulia and libjulia-internal).
|
Nice, FreeBSD is green now! However, Windows is not... |
FreeBSD returns NULL and no error when using dlopen() with RTLD_NOLOAD on the main executable, so we can check and return jl_exe_handle directly.
Co-authored-by: Jameson Nash <[email protected]>
|
Just as a note, this has caused an observable behavior change in MPI.jl |
|
This requires knowing internal details of libraries, which isn't easy to do in general: JuliaParallel/MPI.jl#915 (comment) |
Reverts the behaviour change for ccalls introduced by JuliaLang#58815. This is motivated by libraries like MPI, where the dynamic library that actually defines a symbol is difficult to predict: JuliaParallel/MPI.jl#915 (comment)
|
This in particular is for consistency with Windows, where this behavior is already mandatory |
Reverts the behaviour change for ccalls with an explicit library introduced by #58815. This is motivated by libraries like MPI, where the dynamic library that actually defines a symbol is difficult to predict: JuliaParallel/MPI.jl#915 (comment)
|
It seems that the behavior isn't consistent. The compiler can still find the symbol if a constant library name is used. |
Reverts the behaviour change for ccalls with an explicit library introduced by JuliaLang#58815. This is motivated by libraries like MPI, where the dynamic library that actually defines a symbol is difficult to predict: JuliaParallel/MPI.jl#915 (comment)

A
ccallwithout a specific library finds one withjl_dlfind, which callsjl_dlsymon each of the following libraries, in order:libjulia-internallibjuliakernel32,crtdll,ntdll,ws2_32The semantics of using
dlsym(this does not apply toGetProcAddress) with aspecific handle are a little weird: the library and its dependencies are
searched, even if the provided symbol would resolve somewhere else if used in
the library.
On macOS and Linux, this causes all of the calls to libc functions in Base go
through the handle for
libjulia-internal, making it difficult to hookfunctions. For example,
-fsanitize=threadon clang intercepts malloc and freeby defining them in the executable; calls to malloc from Julia code would go to
the original libc version while calls to free in
libjulia-internalwould go tothe hooked version.
This change makes
jl_dlfindreturn a handle only if the symbol is found inthat library and not one of its dependencies.
Example
a.c:b.c:c.c: