You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
jl_dlfind: do not find symbols in library dependencies (#58815)
A `ccall` without a specific library finds one with `jl_dlfind`, which
calls `jl_dlsym` on each of the following libraries, in order:
- `libjulia-internal`
- `libjulia`
- The current executable
- (On Windows): `kernel32`, `crtdll`, `ntdll`, `ws2_32`
The semantics of using `dlsym` (this does not apply to
`GetProcAddress`) with a specific 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 hook functions. For example, `-fsanitize=thread` on clang intercepts
malloc and free by defining them in the executable; calls to malloc
from Julia code would go to the original libc version while calls to
free in `libjulia-internal` would go to the hooked version.
This change makes `jl_dlfind` return a handle only if the symbol is
found in that library and not one of its dependencies.
## Example
`a.c`:
```c
void b_func(void);
void c_func(void) {
puts("c override from a");
}
int main() {
puts("a");
b_func();
}
```
`b.c`:
```c
define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
void c_func(void);
void b_func(void) {
puts("b");
c_func();
/* How jl_libjulia_internal_handle is set by jl_find_dynamic_library_by_addr */
Dl_info info;
dladdr(&b_func, &info);
void *hdl = dlopen(info.dli_fname, RTLD_NOW | RTLD_NOLOAD | RTLD_LOCAL);
void *(*dl_c_func)(void) = dlsym(hdl, "c_func");
dl_c_func();
}
```
`c.c`:
```c
#include <stdio.h>
void c_func(void) {
puts("c");
}
```
```
$ cc -g -fPIC -shared -o libc.so c.c
$ cc -g -fPIC -shared -o libb.so b.c libc.so
$ cc -Wl,-rpath,. -g -fPIC -o main a.c libb.so libc.so
$ ./main
a
b
c override from a
c
```
0 commit comments