Skip to content

Commit f6ca73a

Browse files
authored
Merge pull request #33820 from JuliaLang/vc/backtrace_ccall
Better stacktraces for `ccall` libraries that do not exist
2 parents 975f0cf + b797ba3 commit f6ca73a

File tree

4 files changed

+40
-36
lines changed

4 files changed

+40
-36
lines changed

src/ccall.cpp

Lines changed: 21 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -663,22 +663,18 @@ static jl_cgval_t emit_cglobal(jl_codectx_t &ctx, jl_value_t **args, size_t narg
663663
}
664664
else {
665665
void *symaddr;
666-
if (!jl_dlsym(jl_get_library(sym.f_lib), sym.f_name, &symaddr, 0)) {
667-
std::stringstream msg;
668-
msg << "cglobal: could not find symbol ";
669-
msg << sym.f_name;
670-
if (sym.f_lib != NULL) {
671-
#ifdef _OS_WINDOWS_
672-
assert(sym.f_lib != JL_EXE_LIBNAME && sym.f_lib != JL_DL_LIBNAME);
673-
#endif
674-
msg << " in library ";
675-
msg << sym.f_lib;
676-
}
677-
emit_error(ctx, msg.str());
666+
667+
void* libsym = jl_get_library_(sym.f_lib, 0);
668+
if (!libsym || !jl_dlsym(libsym, sym.f_name, &symaddr, 0)) {
669+
// Error mode, either the library or the symbol couldn't be find during compiletime.
670+
// Fallback to a runtime symbol lookup.
671+
res = runtime_sym_lookup(ctx, cast<PointerType>(T_pint8), sym.f_lib, sym.f_name, ctx.f);
672+
res = ctx.builder.CreatePtrToInt(res, lrt);
673+
} else {
674+
// since we aren't saving this code, there's no sense in
675+
// putting anything complicated here: just JIT the address of the cglobal
676+
res = ConstantInt::get(lrt, (uint64_t)symaddr);
678677
}
679-
// since we aren't saving this code, there's no sense in
680-
// putting anything complicated here: just JIT the address of the cglobal
681-
res = ConstantInt::get(lrt, (uint64_t)symaddr);
682678
}
683679
}
684680

@@ -1877,23 +1873,17 @@ jl_cgval_t function_sig_t::emit_a_ccall(
18771873
}
18781874
else {
18791875
void *symaddr;
1880-
if (!jl_dlsym(jl_get_library(symarg.f_lib), symarg.f_name, &symaddr, 0)) {
1881-
std::stringstream msg;
1882-
msg << "ccall: could not find function ";
1883-
msg << symarg.f_name;
1884-
if (symarg.f_lib != NULL) {
1885-
#ifdef _OS_WINDOWS_
1886-
assert(symarg.f_lib != JL_EXE_LIBNAME && symarg.f_lib != JL_DL_LIBNAME);
1887-
#endif
1888-
msg << " in library ";
1889-
msg << symarg.f_lib;
1890-
}
1891-
emit_error(ctx, msg.str());
1892-
return jl_cgval_t();
1876+
1877+
void* libsym = jl_get_library_(symarg.f_lib, 0);
1878+
if (!libsym || !jl_dlsym(libsym, symarg.f_name, &symaddr, 0)) {
1879+
// either the library or the symbol could not be found, place a runtime
1880+
// lookup here instead.
1881+
llvmf = runtime_sym_lookup(ctx, funcptype, symarg.f_lib, symarg.f_name, ctx.f);
1882+
} else {
1883+
// since we aren't saving this code, there's no sense in
1884+
// putting anything complicated here: just JIT the function address
1885+
llvmf = literal_static_pointer_val(ctx, symaddr, funcptype);
18931886
}
1894-
// since we aren't saving this code, there's no sense in
1895-
// putting anything complicated here: just JIT the function address
1896-
llvmf = literal_static_pointer_val(ctx, symaddr, funcptype);
18971887
}
18981888
}
18991889

src/julia_internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,8 @@ extern void *jl_crtdll_handle;
861861
extern void *jl_winsock_handle;
862862
#endif
863863

864-
void *jl_get_library(const char *f_lib);
864+
void *jl_get_library_(const char *f_lib, int throw_err);
865+
#define jl_get_library(f_lib) jl_get_library_(f_lib, 1)
865866
JL_DLLEXPORT void *jl_load_and_lookup(const char *f_lib, const char *f_name,
866867
void **hnd);
867868
JL_DLLEXPORT jl_value_t *jl_get_cfunction_trampoline(

src/runtime_ccall.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ using namespace llvm;
2727
static std::map<std::string, void*> libMap;
2828
static jl_mutex_t libmap_lock;
2929
extern "C"
30-
void *jl_get_library(const char *f_lib)
30+
void *jl_get_library_(const char *f_lib, int throw_err)
3131
{
3232
void *hnd;
3333
#ifdef _OS_WINDOWS_
@@ -47,7 +47,7 @@ void *jl_get_library(const char *f_lib)
4747
if (hnd != NULL)
4848
return hnd;
4949
// We might run this concurrently on two threads but it doesn't matter.
50-
hnd = jl_load_dynamic_library(f_lib, JL_RTLD_DEFAULT, 1);
50+
hnd = jl_load_dynamic_library(f_lib, JL_RTLD_DEFAULT, throw_err);
5151
if (hnd != NULL)
5252
jl_atomic_store_release(map_slot, hnd);
5353
return hnd;

stdlib/InteractiveUtils/test/runtests.jl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,12 +251,25 @@ end
251251
@which get_A18434()(1, y=2)
252252
@test counter18434 == 2
253253

254+
@eval function f_invalid(x)
255+
Base.@_noinline_meta
256+
$(Expr(:loopinfo, 1.0f0)) # some expression that throws an error in codegen
257+
x
258+
end
259+
260+
let _true = Ref(true), g, h
261+
@noinline g() = _true[] ? 0 : h()
262+
@noinline h() = (g(); f_invalid(_true[]))
263+
@test_throws ErrorException @code_native h() # due to a failure to compile f()
264+
@test g() == 0
265+
end
266+
254267
let _true = Ref(true), f, g, h
255-
@noinline f() = ccall((:time, "error_library_doesnt_exist\0"), Cvoid, ()) # some expression that throws an error in codegen
268+
@noinline f() = ccall((:time, "error_library_doesnt_exist\0"), Cvoid, ()) # should throw error during runtime
256269
@noinline g() = _true[] ? 0 : h()
257270
@noinline h() = (g(); f())
258-
@test_throws ErrorException @code_native h() # due to a failure to compile f()
259271
@test g() == 0
272+
@test_throws ErrorException h()
260273
end
261274

262275
module ReflectionTest

0 commit comments

Comments
 (0)