diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index d91da9c64cda9..1b44a91be8746 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -974,10 +974,18 @@ static GlobalVariable *emit_shard_table(Module &M, Type *T_size, Type *T_psize, return tables_gv; } +static Function *emit_pgcstack_default_func(Module &M, Type *T_ptr) { + auto FT = FunctionType::get(T_ptr, false); + auto F = Function::Create(FT, GlobalValue::InternalLinkage, "pgcstack_default_func", &M); + llvm::IRBuilder<> builder(BasicBlock::Create(M.getContext(), "top", F)); + builder.CreateRet(Constant::getNullValue(T_ptr)); + return F; +} + // See src/processor.h for documentation about this table. Corresponds to jl_image_ptls_t. -static GlobalVariable *emit_ptls_table(Module &M, Type *T_size, Type *T_psize) { +static GlobalVariable *emit_ptls_table(Module &M, Type *T_size, Type *T_ptr) { std::array ptls_table{ - new GlobalVariable(M, T_size, false, GlobalValue::ExternalLinkage, Constant::getNullValue(T_size), "jl_pgcstack_func_slot"), + new GlobalVariable(M, T_ptr, false, GlobalValue::ExternalLinkage, emit_pgcstack_default_func(M, T_ptr), "jl_pgcstack_func_slot"), new GlobalVariable(M, T_size, false, GlobalValue::ExternalLinkage, Constant::getNullValue(T_size), "jl_pgcstack_key_slot"), new GlobalVariable(M, T_size, false, GlobalValue::ExternalLinkage, Constant::getNullValue(T_size), "jl_tls_offset"), }; @@ -985,7 +993,7 @@ static GlobalVariable *emit_ptls_table(Module &M, Type *T_size, Type *T_psize) { cast(gv)->setVisibility(GlobalValue::HiddenVisibility); cast(gv)->setDSOLocal(true); } - auto ptls_table_arr = ConstantArray::get(ArrayType::get(T_psize, ptls_table.size()), ptls_table); + auto ptls_table_arr = ConstantArray::get(ArrayType::get(T_ptr, ptls_table.size()), ptls_table); auto ptls_table_gv = new GlobalVariable(M, ptls_table_arr->getType(), false, GlobalValue::ExternalLinkage, ptls_table_arr, "jl_ptls_table"); ptls_table_gv->setVisibility(GlobalValue::HiddenVisibility); @@ -2184,6 +2192,7 @@ void jl_dump_native_impl(void *native_code, Type *T_size = DL.getIntPtrType(Context); Type *T_psize = T_size->getPointerTo(); + Type *T_ptr = PointerType::get(Context, 0); auto FT = FunctionType::get(Type::getInt8Ty(Context)->getPointerTo()->getPointerTo(), {}, false); auto F = Function::Create(FT, Function::ExternalLinkage, "get_jl_RTLD_DEFAULT_handle_addr", metadataM); @@ -2226,7 +2235,7 @@ void jl_dump_native_impl(void *native_code, GlobalVariable::InternalLinkage, value, "jl_dispatch_target_ids"); auto shards = emit_shard_table(metadataM, T_size, T_psize, threads); - auto ptls = emit_ptls_table(metadataM, T_size, T_psize); + auto ptls = emit_ptls_table(metadataM, T_size, T_ptr); auto header = emit_image_header(metadataM, threads, nfvars, ngvars); auto AT = ArrayType::get(T_size, sizeof(jl_small_typeof) / sizeof(void*)); auto jl_small_typeof_copy = new GlobalVariable(metadataM, AT, false, diff --git a/src/dlload.c b/src/dlload.c index 91980cc4ecbbf..7c3c88dc08df8 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -240,21 +240,32 @@ JL_DLLEXPORT int jl_dlclose(void *handle) JL_NOTSAFEPOINT #endif } -void *jl_find_dynamic_library_by_addr(void *symbol) { +void *jl_find_dynamic_library_by_addr(void *symbol, int throw_err) { void *handle; #ifdef _OS_WINDOWS_ if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCWSTR)symbol, (HMODULE*)&handle)) { - jl_error("could not load base module"); + if (throw_err) + jl_error("could not load base module"); + return NULL; } #else Dl_info info; if (!dladdr(symbol, &info) || !info.dli_fname) { - jl_error("could not load base module"); + if (throw_err) + jl_error("could not load base module"); + return NULL; } handle = dlopen(info.dli_fname, RTLD_NOW | RTLD_NOLOAD | RTLD_LOCAL); - dlclose(handle); // Undo ref count increment from `dlopen` +#if !defined(__APPLE__) + if (handle == RTLD_DEFAULT && (RTLD_DEFAULT != NULL || dlerror() == NULL)) { + // We loaded the executable but got RTLD_DEFAULT back, ask for a real handle instead + handle = dlopen("", RTLD_NOW | RTLD_NOLOAD | RTLD_LOCAL); + } +#endif + if (handle != NULL) + dlclose(handle); // Undo ref count increment from `dlopen` #endif return handle; } @@ -277,7 +288,7 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags, // modname == NULL is a sentinel value requesting the handle of libjulia-internal if (modname == NULL) - return jl_find_dynamic_library_by_addr(&jl_load_dynamic_library); + return jl_find_dynamic_library_by_addr(&jl_load_dynamic_library, throw_err); abspath = jl_isabspath(modname); is_atpath = 0; diff --git a/src/init.c b/src/init.c index aada2c75ed7a6..ba79a741d39bd 100644 --- a/src/init.c +++ b/src/init.c @@ -808,8 +808,8 @@ JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel) void *stack_lo, *stack_hi; jl_init_stack_limits(1, &stack_lo, &stack_hi); - jl_libjulia_internal_handle = jl_find_dynamic_library_by_addr(&jl_load_dynamic_library); - jl_libjulia_handle = jl_find_dynamic_library_by_addr(&jl_any_type); + jl_libjulia_internal_handle = jl_find_dynamic_library_by_addr(&jl_load_dynamic_library, /* throw_err */ 1); + jl_libjulia_handle = jl_find_dynamic_library_by_addr(&jl_any_type, /* throw_err */ 1); #ifdef _OS_WINDOWS_ jl_exe_handle = GetModuleHandleA(NULL); jl_RTLD_DEFAULT_handle = jl_libjulia_internal_handle; diff --git a/src/jl_exported_funcs.inc b/src/jl_exported_funcs.inc index 664e1270c7381..bdf8cedd6b3f6 100644 --- a/src/jl_exported_funcs.inc +++ b/src/jl_exported_funcs.inc @@ -40,6 +40,7 @@ XX(jl_atomic_store_bits) \ XX(jl_atomic_storeonce_bits) \ XX(jl_atomic_swap_bits) \ + XX(jl_autoinit_and_adopt_thread) \ XX(jl_backtrace_from_here) \ XX(jl_base_relative_to) \ XX(jl_bitcast) \ diff --git a/src/julia_internal.h b/src/julia_internal.h index 782e0bd0b1a96..9b5ab90551b2e 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -1513,7 +1513,7 @@ void win32_formatmessage(DWORD code, char *reason, int len) JL_NOTSAFEPOINT; #endif JL_DLLEXPORT void *jl_get_library_(const char *f_lib, int throw_err); -void *jl_find_dynamic_library_by_addr(void *symbol); +void *jl_find_dynamic_library_by_addr(void *symbol, int throw_err); #define jl_get_library(f_lib) jl_get_library_(f_lib, 1) JL_DLLEXPORT void *jl_load_and_lookup(const char *f_lib, const char *f_name, _Atomic(void*) *hnd); JL_DLLEXPORT void *jl_lazy_load_and_lookup(jl_value_t *lib_val, const char *f_name); diff --git a/src/llvm-ptls.cpp b/src/llvm-ptls.cpp index 238032e68d304..0bbac43bc004d 100644 --- a/src/llvm-ptls.cpp +++ b/src/llvm-ptls.cpp @@ -170,11 +170,11 @@ void LowerPTLS::fix_pgcstack_use(CallInst *pgcstack, Function *pgcstack_getter, *CFGModified = true; // emit slow branch code CallInst *adopt = cast(pgcstack->clone()); - Function *adoptFunc = M->getFunction(XSTR(jl_adopt_thread)); + Function *adoptFunc = M->getFunction(XSTR(jl_autoinit_and_adopt_thread)); if (adoptFunc == NULL) { adoptFunc = Function::Create(pgcstack_getter->getFunctionType(), pgcstack_getter->getLinkage(), pgcstack_getter->getAddressSpace(), - XSTR(jl_adopt_thread), M); + XSTR(jl_autoinit_and_adopt_thread), M); adoptFunc->copyAttributesFrom(pgcstack_getter); adoptFunc->copyMetadata(pgcstack_getter, 0); } diff --git a/src/threading.c b/src/threading.c index 690c5fafb5792..189fd58e485ea 100644 --- a/src/threading.c +++ b/src/threading.c @@ -434,7 +434,6 @@ static void jl_init_task_lock(jl_task_t *ct) } } - JL_DLLEXPORT jl_gcframe_t **jl_adopt_thread(void) { // `jl_init_threadtls` puts us in a GC unsafe region, so ensure GC isn't running. @@ -460,6 +459,23 @@ JL_DLLEXPORT jl_gcframe_t **jl_adopt_thread(void) return &ct->gcstack; } +JL_DLLEXPORT jl_gcframe_t **jl_autoinit_and_adopt_thread(void) +{ + if (!jl_is_initialized()) { + void *retaddr = __builtin_extract_return_addr(__builtin_return_address(0)); + void *sysimg_handle = jl_find_dynamic_library_by_addr(retaddr, /* throw_err */ 0); + + if (sysimg_handle == NULL) { + fprintf(stderr, "error: runtime auto-initialization failed due to bad sysimage lookup\n" + " (this should not happen, please file a bug report)\n"); + abort(); + } + + assert(0 && "TODO: implement auto-init"); + } + + return jl_adopt_thread(); +} void jl_safepoint_suspend_all_threads(jl_task_t *ct) {