Skip to content

Commit

Permalink
Merge pull request JuliaLang#33820 from JuliaLang/vc/backtrace_ccall
Browse files Browse the repository at this point in the history
Better stacktraces for `ccall` libraries that do not exist
  • Loading branch information
vchuravy committed Dec 22, 2019
2 parents 975f0cf + b797ba3 commit f6ca73a
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 36 deletions.
52 changes: 21 additions & 31 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -663,22 +663,18 @@ static jl_cgval_t emit_cglobal(jl_codectx_t &ctx, jl_value_t **args, size_t narg
}
else {
void *symaddr;
if (!jl_dlsym(jl_get_library(sym.f_lib), sym.f_name, &symaddr, 0)) {
std::stringstream msg;
msg << "cglobal: could not find symbol ";
msg << sym.f_name;
if (sym.f_lib != NULL) {
#ifdef _OS_WINDOWS_
assert(sym.f_lib != JL_EXE_LIBNAME && sym.f_lib != JL_DL_LIBNAME);
#endif
msg << " in library ";
msg << sym.f_lib;
}
emit_error(ctx, msg.str());

void* libsym = jl_get_library_(sym.f_lib, 0);
if (!libsym || !jl_dlsym(libsym, sym.f_name, &symaddr, 0)) {
// Error mode, either the library or the symbol couldn't be find during compiletime.
// Fallback to a runtime symbol lookup.
res = runtime_sym_lookup(ctx, cast<PointerType>(T_pint8), sym.f_lib, sym.f_name, ctx.f);
res = ctx.builder.CreatePtrToInt(res, lrt);
} else {
// since we aren't saving this code, there's no sense in
// putting anything complicated here: just JIT the address of the cglobal
res = ConstantInt::get(lrt, (uint64_t)symaddr);
}
// since we aren't saving this code, there's no sense in
// putting anything complicated here: just JIT the address of the cglobal
res = ConstantInt::get(lrt, (uint64_t)symaddr);
}
}

Expand Down Expand Up @@ -1877,23 +1873,17 @@ jl_cgval_t function_sig_t::emit_a_ccall(
}
else {
void *symaddr;
if (!jl_dlsym(jl_get_library(symarg.f_lib), symarg.f_name, &symaddr, 0)) {
std::stringstream msg;
msg << "ccall: could not find function ";
msg << symarg.f_name;
if (symarg.f_lib != NULL) {
#ifdef _OS_WINDOWS_
assert(symarg.f_lib != JL_EXE_LIBNAME && symarg.f_lib != JL_DL_LIBNAME);
#endif
msg << " in library ";
msg << symarg.f_lib;
}
emit_error(ctx, msg.str());
return jl_cgval_t();

void* libsym = jl_get_library_(symarg.f_lib, 0);
if (!libsym || !jl_dlsym(libsym, symarg.f_name, &symaddr, 0)) {
// either the library or the symbol could not be found, place a runtime
// lookup here instead.
llvmf = runtime_sym_lookup(ctx, funcptype, symarg.f_lib, symarg.f_name, ctx.f);
} else {
// since we aren't saving this code, there's no sense in
// putting anything complicated here: just JIT the function address
llvmf = literal_static_pointer_val(ctx, symaddr, funcptype);
}
// since we aren't saving this code, there's no sense in
// putting anything complicated here: just JIT the function address
llvmf = literal_static_pointer_val(ctx, symaddr, funcptype);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,8 @@ extern void *jl_crtdll_handle;
extern void *jl_winsock_handle;
#endif

void *jl_get_library(const char *f_lib);
void *jl_get_library_(const char *f_lib, 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,
void **hnd);
JL_DLLEXPORT jl_value_t *jl_get_cfunction_trampoline(
Expand Down
4 changes: 2 additions & 2 deletions src/runtime_ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ using namespace llvm;
static std::map<std::string, void*> libMap;
static jl_mutex_t libmap_lock;
extern "C"
void *jl_get_library(const char *f_lib)
void *jl_get_library_(const char *f_lib, int throw_err)
{
void *hnd;
#ifdef _OS_WINDOWS_
Expand All @@ -47,7 +47,7 @@ void *jl_get_library(const char *f_lib)
if (hnd != NULL)
return hnd;
// We might run this concurrently on two threads but it doesn't matter.
hnd = jl_load_dynamic_library(f_lib, JL_RTLD_DEFAULT, 1);
hnd = jl_load_dynamic_library(f_lib, JL_RTLD_DEFAULT, throw_err);
if (hnd != NULL)
jl_atomic_store_release(map_slot, hnd);
return hnd;
Expand Down
17 changes: 15 additions & 2 deletions stdlib/InteractiveUtils/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,25 @@ end
@which get_A18434()(1, y=2)
@test counter18434 == 2

@eval function f_invalid(x)
Base.@_noinline_meta
$(Expr(:loopinfo, 1.0f0)) # some expression that throws an error in codegen
x
end

let _true = Ref(true), g, h
@noinline g() = _true[] ? 0 : h()
@noinline h() = (g(); f_invalid(_true[]))
@test_throws ErrorException @code_native h() # due to a failure to compile f()
@test g() == 0
end

let _true = Ref(true), f, g, h
@noinline f() = ccall((:time, "error_library_doesnt_exist\0"), Cvoid, ()) # some expression that throws an error in codegen
@noinline f() = ccall((:time, "error_library_doesnt_exist\0"), Cvoid, ()) # should throw error during runtime
@noinline g() = _true[] ? 0 : h()
@noinline h() = (g(); f())
@test_throws ErrorException @code_native h() # due to a failure to compile f()
@test g() == 0
@test_throws ErrorException h()
end

module ReflectionTest
Expand Down

0 comments on commit f6ca73a

Please sign in to comment.