Skip to content

Commit 95f4376

Browse files
committed
Lookup ccall symbols in local internal libraries first
This is similar to what we do on Windows, where handles to the exact library are required anyway. This is enough to make sure that our `dlsym` lookups are directed to the correct libjulia, even when loading a Julia run-time within Julia. The second change needed to get things working (not included in this commit) is to add symbol versioning, so that the runtime linker does not mix up symbols between the two libraries.
1 parent 0e361cf commit 95f4376

File tree

7 files changed

+45
-58
lines changed

7 files changed

+45
-58
lines changed

src/ccall.cpp

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ static bool runtime_sym_gvs(jl_codectx_t &ctx, const char *f_lib, const char *f_
6161
bool runtime_lib = false;
6262
GlobalVariable *libptrgv;
6363
jl_codegen_params_t::SymMapGV *symMap;
64-
#ifdef _OS_WINDOWS_
6564
if ((intptr_t)f_lib == (intptr_t)JL_EXE_LIBNAME) {
6665
libptrgv = prepare_global_in(M, jlexe_var);
6766
symMap = &ctx.emission_context.symMapExe;
@@ -74,9 +73,7 @@ static bool runtime_sym_gvs(jl_codectx_t &ctx, const char *f_lib, const char *f_
7473
libptrgv = prepare_global_in(M, jldll_var);
7574
symMap = &ctx.emission_context.symMapDll;
7675
}
77-
else
78-
#endif
79-
if (f_lib == NULL) {
76+
else if (f_lib == NULL) {
8077
libptrgv = jl_emit_RTLD_DEFAULT_var(M);
8178
symMap = &ctx.emission_context.symMapDefault;
8279
}
@@ -631,16 +628,12 @@ static void interpret_symbol_arg(jl_codectx_t &ctx, native_sym_arg_t &out, jl_va
631628
std::string iname("i");
632629
iname += f_name;
633630
if (jl_dlsym(jl_libjulia_internal_handle, iname.c_str(), &symaddr, 0)) {
634-
#ifdef _OS_WINDOWS_
635631
f_lib = JL_LIBJULIA_INTERNAL_DL_LIBNAME;
636-
#endif
637632
f_name = jl_symbol_name(jl_symbol(iname.c_str()));
638633
}
639-
#ifdef _OS_WINDOWS_
640634
else {
641-
f_lib = jl_dlfind_win32(f_name);
635+
f_lib = jl_dlfind(f_name);
642636
}
643-
#endif
644637
}
645638
}
646639
else if (jl_is_cpointer_type(jl_typeof(ptr))) {
@@ -726,7 +719,8 @@ static jl_cgval_t emit_cglobal(jl_codectx_t &ctx, jl_value_t **args, size_t narg
726719
void *symaddr;
727720

728721
void* libsym = jl_get_library_(sym.f_lib, 0);
729-
if (!libsym || !jl_dlsym(libsym, sym.f_name, &symaddr, 0)) {
722+
int symbol_found = jl_dlsym(libsym, sym.f_name, &symaddr, 0);
723+
if (!libsym || !symbol_found) {
730724
// Error mode, either the library or the symbol couldn't be find during compiletime.
731725
// Fallback to a runtime symbol lookup.
732726
res = runtime_sym_lookup(ctx, cast<PointerType>(getInt8PtrTy(ctx.builder.getContext())), sym.f_lib, NULL, sym.f_name, ctx.f);
@@ -1381,18 +1375,19 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs)
13811375
if ((uintptr_t)fptr == ptr)
13821376
return true;
13831377
if (f_lib) {
1384-
#ifdef _OS_WINDOWS_
13851378
if ((f_lib == JL_EXE_LIBNAME) || // preventing invalid pointer access
13861379
(f_lib == JL_LIBJULIA_INTERNAL_DL_LIBNAME) ||
1387-
(f_lib == JL_LIBJULIA_DL_LIBNAME) ||
1388-
(!strcmp(f_lib, jl_crtdll_basename))) {
1380+
(f_lib == JL_LIBJULIA_DL_LIBNAME)) {
1381+
// libjulia-like
1382+
}
1383+
else
1384+
#ifdef _OS_WINDOWS_
1385+
if (strcmp(f_lib, jl_crtdll_basename) == 0) {
13891386
// libjulia-like
13901387
}
13911388
else
1392-
return false;
1393-
#else
1394-
return false;
13951389
#endif
1390+
return false;
13961391
}
13971392
return f_name && f_name == name;
13981393
};
@@ -2082,7 +2077,8 @@ jl_cgval_t function_sig_t::emit_a_ccall(
20822077
else {
20832078
void *symaddr;
20842079
void *libsym = jl_get_library_(symarg.f_lib, 0);
2085-
if (!libsym || !jl_dlsym(libsym, symarg.f_name, &symaddr, 0)) {
2080+
int symbol_found = jl_dlsym(libsym, symarg.f_name, &symaddr, 0);
2081+
if (!libsym || !symbol_found) {
20862082
++DeferredCCallLookups;
20872083
// either the library or the symbol could not be found, place a runtime
20882084
// lookup here instead.

src/codegen.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8686,11 +8686,9 @@ static void init_jit_functions(void)
86868686
{
86878687
add_named_global(jlstack_chk_guard_var, &__stack_chk_guard);
86888688
add_named_global(jlRTLD_DEFAULT_var, &jl_RTLD_DEFAULT_handle);
8689-
#ifdef _OS_WINDOWS_
86908689
add_named_global(jlexe_var, &jl_exe_handle);
86918690
add_named_global(jldll_var, &jl_libjulia_handle);
86928691
add_named_global(jldlli_var, &jl_libjulia_internal_handle);
8693-
#endif
86948692
auto size2pjlvalue = [](Type *T_size) -> Type * {
86958693
return get_pjlvalue(T_size->getContext());
86968694
};

src/dlload.c

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ JL_DLLEXPORT JL_NO_SANITIZE void *jl_dlopen(const char *filename, unsigned flags
189189
if (!dlopen)
190190
return NULL;
191191
void *libdl_handle = dlopen("libdl.so", RTLD_NOW | RTLD_NOLOAD);
192+
assert(libdl_handle);
192193
dlopen = (dlopen_prototype*)dlsym(libdl_handle, "dlopen");
193194
dlclose(libdl_handle);
194195
assert(dlopen);
@@ -239,6 +240,25 @@ JL_DLLEXPORT int jl_dlclose(void *handle) JL_NOTSAFEPOINT
239240
#endif
240241
}
241242

243+
void *jl_find_dynamic_library_by_addr(void *symbol) {
244+
void *handle;
245+
#ifdef _OS_WINDOWS_
246+
if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
247+
(LPCWSTR)symbol,
248+
(HMODULE*)&handle)) {
249+
jl_error("could not load base module");
250+
}
251+
#else
252+
Dl_info info;
253+
if (!dladdr(symbol, &info) || !info.dli_fname) {
254+
jl_error("could not load base module");
255+
}
256+
handle = dlopen(info.dli_fname, RTLD_NOW | RTLD_NOLOAD);
257+
dlclose(handle); // Undo ref count increment from `dlopen`
258+
#endif
259+
return handle;
260+
}
261+
242262
JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags, int throw_err)
243263
{
244264
char path[PATHBUF], relocated[PATHBUF];
@@ -255,26 +275,6 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags,
255275
int n_extensions = endswith_extension(modname) ? 1 : N_EXTENSIONS;
256276
int ret;
257277

258-
/*
259-
this branch returns handle of libjulia-internal
260-
*/
261-
if (modname == NULL) {
262-
#ifdef _OS_WINDOWS_
263-
if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
264-
(LPCWSTR)(uintptr_t)(&jl_load_dynamic_library),
265-
(HMODULE*)&handle)) {
266-
jl_error("could not load base module");
267-
}
268-
#else
269-
Dl_info info;
270-
if (!dladdr((void*)(uintptr_t)&jl_load_dynamic_library, &info) || !info.dli_fname) {
271-
jl_error("could not load base module");
272-
}
273-
handle = dlopen(info.dli_fname, RTLD_NOW);
274-
#endif
275-
goto done;
276-
}
277-
278278
abspath = jl_isabspath(modname);
279279
is_atpath = 0;
280280

@@ -421,9 +421,8 @@ JL_DLLEXPORT int jl_dlsym(void *handle, const char *symbol, void ** value, int t
421421
return symbol_found;
422422
}
423423

424-
#ifdef _OS_WINDOWS_
425-
//Look for symbols in win32 libraries
426-
JL_DLLEXPORT const char *jl_dlfind_win32(const char *f_name)
424+
// Look for symbols in internal libraries
425+
JL_DLLEXPORT const char *jl_dlfind(const char *f_name)
427426
{
428427
void * dummy;
429428
if (jl_dlsym(jl_exe_handle, f_name, &dummy, 0))
@@ -432,6 +431,7 @@ JL_DLLEXPORT const char *jl_dlfind_win32(const char *f_name)
432431
return JL_LIBJULIA_INTERNAL_DL_LIBNAME;
433432
if (jl_dlsym(jl_libjulia_handle, f_name, &dummy, 0))
434433
return JL_LIBJULIA_DL_LIBNAME;
434+
#ifdef _OS_WINDOWS_
435435
if (jl_dlsym(jl_kernel32_handle, f_name, &dummy, 0))
436436
return "kernel32";
437437
if (jl_dlsym(jl_crtdll_handle, f_name, &dummy, 0)) // Prefer crtdll over ntdll
@@ -440,6 +440,7 @@ JL_DLLEXPORT const char *jl_dlfind_win32(const char *f_name)
440440
return "ntdll";
441441
if (jl_dlsym(jl_winsock_handle, f_name, &dummy, 0))
442442
return "ws2_32";
443+
#endif
443444
// additional common libraries (libc?) could be added here, but in general,
444445
// it is better to specify the library explicitly in the code. This exists
445446
// mainly to ease compatibility with linux, and for libraries that don't
@@ -451,7 +452,6 @@ JL_DLLEXPORT const char *jl_dlfind_win32(const char *f_name)
451452
// which defaults to jl_libjulia_internal_handle, where we won't find it, and
452453
// will throw the appropriate error.
453454
}
454-
#endif
455455

456456
#ifdef __cplusplus
457457
}

src/init.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -763,15 +763,11 @@ JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel)
763763
void *stack_lo, *stack_hi;
764764
jl_init_stack_limits(1, &stack_lo, &stack_hi);
765765

766-
jl_libjulia_internal_handle = jl_load_dynamic_library(NULL, JL_RTLD_DEFAULT, 1);
766+
jl_libjulia_internal_handle = jl_find_dynamic_library_by_addr(&jl_load_dynamic_library);
767+
jl_libjulia_handle = jl_find_dynamic_library_by_addr(&jl_any_type);
767768
#ifdef _OS_WINDOWS_
768769
jl_exe_handle = GetModuleHandleA(NULL);
769770
jl_RTLD_DEFAULT_handle = jl_libjulia_internal_handle;
770-
if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
771-
(LPCWSTR)&jl_any_type,
772-
(HMODULE*)&jl_libjulia_handle)) {
773-
jl_error("could not load base module");
774-
}
775771
jl_ntdll_handle = jl_dlopen("ntdll.dll", JL_RTLD_NOLOAD); // bypass julia's pathchecking for system dlls
776772
jl_kernel32_handle = jl_dlopen("kernel32.dll", JL_RTLD_NOLOAD);
777773
jl_crtdll_handle = jl_dlopen(jl_crtdll_name, JL_RTLD_NOLOAD);

src/julia_internal.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,11 +1254,11 @@ JL_DLLEXPORT uint64_t jl_rand(void) JL_NOTSAFEPOINT;
12541254
JL_DLLEXPORT void jl_srand(uint64_t) JL_NOTSAFEPOINT;
12551255
JL_DLLEXPORT void jl_init_rand(void);
12561256

1257+
JL_DLLEXPORT extern void *jl_exe_handle;
1258+
JL_DLLEXPORT extern void *jl_libjulia_handle;
12571259
JL_DLLEXPORT extern void *jl_libjulia_internal_handle;
12581260
JL_DLLEXPORT extern void *jl_RTLD_DEFAULT_handle;
12591261
#if defined(_OS_WINDOWS_)
1260-
JL_DLLEXPORT extern void *jl_exe_handle;
1261-
JL_DLLEXPORT extern void *jl_libjulia_handle;
12621262
JL_DLLEXPORT extern const char *jl_crtdll_basename;
12631263
extern void *jl_ntdll_handle;
12641264
extern void *jl_kernel32_handle;
@@ -1268,6 +1268,7 @@ void win32_formatmessage(DWORD code, char *reason, int len) JL_NOTSAFEPOINT;
12681268
#endif
12691269

12701270
JL_DLLEXPORT void *jl_get_library_(const char *f_lib, int throw_err);
1271+
void *jl_find_dynamic_library_by_addr(void *symbol);
12711272
#define jl_get_library(f_lib) jl_get_library_(f_lib, 1)
12721273
JL_DLLEXPORT void *jl_load_and_lookup(const char *f_lib, const char *f_name, _Atomic(void*) *hnd);
12731274
JL_DLLEXPORT void *jl_lazy_load_and_lookup(jl_value_t *lib_val, const char *f_name);
@@ -1277,11 +1278,11 @@ JL_DLLEXPORT jl_value_t *jl_get_cfunction_trampoline(
12771278
jl_unionall_t *env, jl_value_t **vals);
12781279

12791280

1280-
// Windows only
1281+
// Special filenames used to refer to internal julia libraries
12811282
#define JL_EXE_LIBNAME ((const char*)1)
12821283
#define JL_LIBJULIA_DL_LIBNAME ((const char*)2)
12831284
#define JL_LIBJULIA_INTERNAL_DL_LIBNAME ((const char*)3)
1284-
JL_DLLEXPORT const char *jl_dlfind_win32(const char *name);
1285+
JL_DLLEXPORT const char *jl_dlfind(const char *name);
12851286

12861287
// libuv wrappers:
12871288
JL_DLLEXPORT int jl_fs_rename(const char *src_path, const char *dst_path);

src/runtime_ccall.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,12 @@ void *jl_get_library_(const char *f_lib, int throw_err)
3131
{
3232
if (f_lib == NULL)
3333
return jl_RTLD_DEFAULT_handle;
34-
#ifdef _OS_WINDOWS_
3534
if (f_lib == JL_EXE_LIBNAME)
3635
return jl_exe_handle;
3736
if (f_lib == JL_LIBJULIA_INTERNAL_DL_LIBNAME)
3837
return jl_libjulia_internal_handle;
3938
if (f_lib == JL_LIBJULIA_DL_LIBNAME)
4039
return jl_libjulia_handle;
41-
#endif
4240
JL_LOCK(&libmap_lock);
4341
// This is the only operation we do on the map, which doesn't invalidate
4442
// any references or iterators.

src/runtime_intrinsics.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -508,10 +508,8 @@ JL_DLLEXPORT jl_value_t *jl_cglobal(jl_value_t *v, jl_value_t *ty)
508508
else
509509
JL_TYPECHK(cglobal, symbol, v)
510510

511-
#ifdef _OS_WINDOWS_
512511
if (!f_lib)
513-
f_lib = (char*)jl_dlfind_win32(f_name);
514-
#endif
512+
f_lib = (char*)jl_dlfind(f_name);
515513

516514
void *ptr;
517515
jl_dlsym(jl_get_library(f_lib), f_name, &ptr, 1);

0 commit comments

Comments
 (0)