diff --git a/cli/Makefile b/cli/Makefile index c1918d3c3848b..a5a018174e070 100644 --- a/cli/Makefile +++ b/cli/Makefile @@ -54,7 +54,11 @@ $(BUILDDIR)/loader_exe.o : $(SRCDIR)/loader_exe.c $(HEADERS) $(BUILDDIR)/loader_exe.dbg.obj : $(SRCDIR)/loader_exe.c $(HEADERS) @$(call PRINT_CC, $(CC) $(DEBUGFLAGS) $(LOADER_CFLAGS) -c $< -o $@) $(BUILDDIR)/loader_trampolines.o : $(SRCDIR)/trampolines/trampolines_$(ARCH).S - @$(call PRINT_CC, $(CC) $(DEBUGFLAGS) $(LOADER_CFLAGS) $< -c -o $@) + @$(call PRINT_CC, $(CC) $(SHIPFLAGS) $(LOADER_CFLAGS) $< -c -o $@) + +# Debugging target to help us see what kind of code is being generated for our trampolines +dump-trampolines: $(SRCDIR)/trampolines/trampolines_$(ARCH).S + $(CC) $(SHIPFLAGS) $(LOADER_CFLAGS) $< -S | sed -E 's/ ((%%)|;) /\n/g' | sed -E 's/.global/\n.global/g' DIRS = $(build_bindir) $(build_libdir) $(DIRS): diff --git a/cli/jl_exports.h b/cli/jl_exports.h index ecbe81041f5ac..0d467a6528b75 100644 --- a/cli/jl_exports.h +++ b/cli/jl_exports.h @@ -5,9 +5,14 @@ #include "../src/jl_exported_data.inc" #include "../src/jl_exported_funcs.inc" -// Define data symbols as `const void * $(name);` +// Define pointer data as `const void * $(name);` #define XX(name) JL_DLLEXPORT const void * name; -JL_EXPORTED_DATA(XX) +JL_EXPORTED_DATA_POINTERS(XX) +#undef XX + +// Define symbol data as `$type) $(name);` +#define XX(name, type) JL_DLLEXPORT type name; +JL_EXPORTED_DATA_SYMBOLS(XX) #undef XX // Define holder locations for function addresses as `const void * $(name)_addr` diff --git a/cli/trampolines/trampolines_aarch64.S b/cli/trampolines/trampolines_aarch64.S index 174962bb80614..090c6c8cd4599 100644 --- a/cli/trampolines/trampolines_aarch64.S +++ b/cli/trampolines/trampolines_aarch64.S @@ -1,12 +1,27 @@ #include "../../src/jl_exported_funcs.inc" +// On macOS, we need to prepend underscores on symbols +#if defined(__APPLE__) && defined(__MACH__) +#define CNAME(x) _##x +#define PAGE(x) x##@PAGE +#define PAGEOFF(x) x##@PAGEOFF +#define SEP %% +#else +#define CNAME(x) x +#define PAGE(x) x +#define PAGEOFF(x) #:lo12:##x +#define SEP ; +#endif + #define XX(name) \ -.global name; \ -.cfi_startproc; \ -name##:; \ - adrp x0, name##_addr; \ - ldr x0, [x0, #:lo12:name##_addr]; \ - br x0; \ -.cfi_endproc; \ +.global CNAME(name) SEP \ +.cfi_startproc SEP \ +.p2align 2 SEP \ +CNAME(name)##: SEP \ + adrp x16, PAGE(CNAME(name##_addr)) SEP \ + ldr x16, [x16, PAGEOFF(CNAME(name##_addr))] SEP \ + br x16 SEP \ +.cfi_endproc SEP \ + JL_EXPORTED_FUNCS(XX) #undef XX diff --git a/cli/trampolines/trampolines_i686.S b/cli/trampolines/trampolines_i686.S index 3b2be2bfd8c28..2f2971ec81321 100644 --- a/cli/trampolines/trampolines_i686.S +++ b/cli/trampolines/trampolines_i686.S @@ -20,9 +20,9 @@ #define XX(name) \ DEBUGINFO(name); \ -.global name; \ +.global CNAME(name); \ .cfi_startproc; \ -name##:; \ +CNAME(name)##:; \ CET_START(); \ jmpl *(CNAME(name##_addr)); \ ud2; \ diff --git a/cli/trampolines/trampolines_x86_64.S b/cli/trampolines/trampolines_x86_64.S index d55ea57d04c9a..afcb452eefcd3 100644 --- a/cli/trampolines/trampolines_x86_64.S +++ b/cli/trampolines/trampolines_x86_64.S @@ -34,10 +34,10 @@ #define XX(name) \ DEBUGINFO(name); \ -.global name; \ +.global CNAME(name); \ .cfi_startproc; \ SEH_START1(name); \ -name##:; \ +CNAME(name)##:; \ SEH_START2(); \ CET_START(); \ mov CNAME(name##_addr)(%rip),%r11; \ diff --git a/src/ccall.cpp b/src/ccall.cpp index abc219d3b701f..8ef419d18bf84 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -22,11 +22,11 @@ static bool runtime_sym_gvs(jl_codegen_params_t &emission_context, const char *f GlobalVariable *libptrgv; jl_codegen_params_t::SymMapGV *symMap; #ifdef _OS_WINDOWS_ - if ((intptr_t)f_lib == 1) { + if ((intptr_t)f_lib == (intptr_t)JL_EXE_LIBNAME) { libptrgv = prepare_global_in(M, jlexe_var); symMap = &emission_context.symMapExe; } - else if ((intptr_t)f_lib == 2) { + else if ((intptr_t)f_lib == (intptr_t)JL_LIBJULIA_INTERNAL_DL_LIBNAME) { libptrgv = prepare_global_in(M, jldll_var); symMap = &emission_context.symMapDl; } @@ -1266,7 +1266,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) auto _is_libjulia_func = [&] (uintptr_t ptr, const char *name) { if ((uintptr_t)fptr == ptr) return true; - return (!f_lib || f_lib == JL_DL_LIBNAME) && f_name && !strcmp(f_name, name); + return (!f_lib || f_lib == JL_LIBJULIA_INTERNAL_DL_LIBNAME) && f_name && !strcmp(f_name, name); }; #define is_libjulia_func(name) _is_libjulia_func((uintptr_t)&(name), #name) diff --git a/src/codegen.cpp b/src/codegen.cpp index 94bd794677a11..144c3d8636e95 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -397,7 +397,7 @@ static const auto jlexe_var = new JuliaVariable{ [](LLVMContext &C) { return T_pint8; }, }; static const auto jldll_var = new JuliaVariable{ - "jl_dl_handle", + "jl_libjulia_internal_handle", true, [](LLVMContext &C) { return T_pint8; }, }; @@ -7531,7 +7531,7 @@ static void init_jit_functions(void) add_named_global(jlRTLD_DEFAULT_var, &jl_RTLD_DEFAULT_handle); #ifdef _OS_WINDOWS_ add_named_global(jlexe_var, &jl_exe_handle); - add_named_global(jldll_var, &jl_dl_handle); + add_named_global(jldll_var, &jl_libjulia_internal_handle); #endif global_jlvalue_to_llvm(new JuliaVariable{"jl_true", true, get_pjlvalue}, &jl_true); global_jlvalue_to_llvm(new JuliaVariable{"jl_false", true, get_pjlvalue}, &jl_false); diff --git a/src/dlload.c b/src/dlload.c index f696eabc4382d..0765f0e14c07c 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -308,8 +308,10 @@ const char *jl_dlfind_win32(const char *f_name) void * dummy; if (jl_dlsym(jl_exe_handle, f_name, &dummy, 0)) return JL_EXE_LIBNAME; - if (jl_dlsym(jl_dl_handle, f_name, &dummy, 0)) - return JL_DL_LIBNAME; + if (jl_dlsym(jl_libjulia_internal_handle, f_name, &dummy, 0)) + return JL_LIBJULIA_INTERNAL_DL_LIBNAME; + if (jl_dlsym(jl_libjulia_handle, f_name, &dummy, 0)) + return JL_LIBJULIA_DL_LIBNAME; if (jl_dlsym(jl_kernel32_handle, f_name, &dummy, 0)) return "kernel32"; if (jl_dlsym(jl_ntdll_handle, f_name, &dummy, 0)) @@ -334,8 +336,8 @@ const char *jl_dlfind_win32(const char *f_name) // explicit is preferred over implicit return NULL; // oops, we didn't find it. NULL defaults to searching jl_RTLD_DEFAULT_handle, - // which defaults to jl_dl_handle, where we won't find it, and will throw the - // appropriate error. + // which defaults to jl_libjulia_internal_handle, where we won't find it, and + // will throw the appropriate error. } #endif diff --git a/src/init.c b/src/init.c index e69c43837787d..a421578239680 100644 --- a/src/init.c +++ b/src/init.c @@ -293,7 +293,8 @@ JL_DLLEXPORT void jl_atexit_hook(int exitcode) static void post_boot_hooks(void); -JL_DLLEXPORT void *jl_dl_handle; +JL_DLLEXPORT void *jl_libjulia_internal_handle; +JL_DLLEXPORT void *jl_libjulia_handle; void *jl_RTLD_DEFAULT_handle; JL_DLLEXPORT void *jl_exe_handle; #ifdef _OS_WINDOWS_ @@ -657,7 +658,10 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_prep_sanitizers(); void *stack_lo, *stack_hi; jl_init_stack_limits(1, &stack_lo, &stack_hi); - jl_dl_handle = jl_load_dynamic_library(NULL, JL_RTLD_DEFAULT, 1); + + // Load libjulia-internal (which contains this function), and libjulia, explicitly. + jl_libjulia_internal_handle = jl_load_dynamic_library(NULL, JL_RTLD_DEFAULT, 1); + jl_libjulia_handle = jl_load_dynamic_library(JL_LIBJULIA_DL_LIBNAME, JL_RTLD_DEFAULT, 1); #ifdef _OS_WINDOWS_ jl_ntdll_handle = jl_dlopen("ntdll.dll", 0); // bypass julia's pathchecking for system dlls jl_kernel32_handle = jl_dlopen("kernel32.dll", 0); diff --git a/src/jl_exported_data.inc b/src/jl_exported_data.inc index ee09992c6a584..76e0984798522 100644 --- a/src/jl_exported_data.inc +++ b/src/jl_exported_data.inc @@ -1,4 +1,5 @@ -#define JL_EXPORTED_DATA(XX) \ +// Pointers that are exposed through the public libjulia +#define JL_EXPORTED_DATA_POINTERS(XX) \ XX(jl_abstractarray_type) \ XX(jl_abstractslot_type) \ XX(jl_abstractstring_type) \ @@ -115,3 +116,8 @@ XX(jl_void_type) \ XX(jl_voidpointer_type) \ XX(jl_weakref_type) + + +// Data symbols that are defined inside the public libjulia +#define JL_EXPORTED_DATA_SYMBOLS(XX) \ + XX(jl_n_threads, int) diff --git a/src/julia.h b/src/julia.h index 8cd070885c6fd..c16f9000fd89e 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1515,6 +1515,7 @@ JL_DLLEXPORT int jl_is_debugbuild(void) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_sym_t *jl_get_UNAME(void) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_sym_t *jl_get_ARCH(void) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_value_t *jl_get_libllvm(void) JL_NOTSAFEPOINT; +extern JL_DLLIMPORT int jl_n_threads; // environment entries JL_DLLEXPORT jl_value_t *jl_environ(int i); diff --git a/src/julia_internal.h b/src/julia_internal.h index 8f8c666b74aec..416fedf6dbbf6 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -990,7 +990,8 @@ STATIC_INLINE uint64_t cong(uint64_t max, uint64_t unbias, uint64_t *seed) } // libuv stuff: -JL_DLLEXPORT extern void *jl_dl_handle; +JL_DLLEXPORT extern void *jl_libjulia_handle; +JL_DLLEXPORT extern void *jl_libjulia_internal_handle; JL_DLLEXPORT extern void *jl_RTLD_DEFAULT_handle; #if defined(_OS_WINDOWS_) JL_DLLEXPORT extern void *jl_exe_handle; @@ -1012,8 +1013,13 @@ JL_DLLEXPORT jl_value_t *jl_get_cfunction_trampoline( // Windows only -#define JL_EXE_LIBNAME ((const char*)1) -#define JL_DL_LIBNAME ((const char*)2) +#define JL_EXE_LIBNAME ((const char*)1) +#define JL_LIBJULIA_INTERNAL_DL_LIBNAME ((const char*)2) +#if defined(JL_DEBUG_BUILD) +#define JL_LIBJULIA_DL_LIBNAME "libjulia-debug" +#else +#define JL_LIBJULIA_DL_LIBNAME "libjulia" +#endif const char *jl_dlfind_win32(const char *name); // libuv wrappers: diff --git a/src/runtime_ccall.cpp b/src/runtime_ccall.cpp index b9b3ed4dea41a..0dd727749f30e 100644 --- a/src/runtime_ccall.cpp +++ b/src/runtime_ccall.cpp @@ -33,8 +33,10 @@ void *jl_get_library_(const char *f_lib, int throw_err) JL_NOTSAFEPOINT #ifdef _OS_WINDOWS_ if (f_lib == JL_EXE_LIBNAME) return jl_exe_handle; - if (f_lib == JL_DL_LIBNAME) - return jl_dl_handle; + if (f_lib == JL_LIBJULIA_INTERNAL_DL_LIBNAME) + return jl_libjulia_internal_handle; + if (f_lib == JL_LIBJULIA_DL_LIBNAME) + return jl_libjulia_handle; #endif if (f_lib == NULL) return jl_RTLD_DEFAULT_handle; diff --git a/src/threading.c b/src/threading.c index 8f8dd45c28507..80722323c9367 100644 --- a/src/threading.c +++ b/src/threading.c @@ -221,7 +221,6 @@ jl_get_ptls_states_func jl_get_ptls_states_getter(void) } #endif -JL_DLLEXPORT int jl_n_threads; jl_ptls_t *jl_all_tls_states JL_GLOBALLY_ROOTED; // return calling thread's ID diff --git a/src/threading.h b/src/threading.h index 072b7264841c2..43516ccceebb1 100644 --- a/src/threading.h +++ b/src/threading.h @@ -13,7 +13,6 @@ extern "C" { #define PROFILE_JL_THREADING 0 extern jl_ptls_t *jl_all_tls_states JL_GLOBALLY_ROOTED; /* thread local storage */ -extern JL_DLLEXPORT int jl_n_threads; /* # threads we're actually using */ typedef struct _jl_threadarg_t { int16_t tid;