Skip to content

add optional RTLD flags argument to dlopen, fixes issue #2312 #2380

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 24, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion base/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,21 @@ object_id(x::ANY) = ccall(:jl_object_id, Uint, (Any,), x)
const isimmutable = x->(isa(x,Tuple) || isa(x,Symbol) ||
isa(typeof(x),BitsKind))

# constants to match JL_RTLD_* in src/julia.h
const RTLD_LOCAL = 0x00000000
const RTLD_GLOBAL = 0x00000001
const RTLD_LAZY = 0x00000002
const RTLD_NOW = 0x00000004
const RTLD_NODELETE = 0x00000008
const RTLD_NOLOAD = 0x00000010
const RTLD_DEEPBIND = 0x00000020
const RTLD_FIRST = 0x00000040

dlsym(hnd, s::String) = ccall(:jl_dlsym, Ptr{Void}, (Ptr{Void}, Ptr{Uint8}), hnd, s)
dlsym(hnd, s::Symbol) = ccall(:jl_dlsym, Ptr{Void}, (Ptr{Void}, Ptr{Uint8}), hnd, s)
dlsym_e(hnd, s::Union(Symbol,String)) = ccall(:jl_dlsym_e, Ptr{Void}, (Ptr{Void}, Ptr{Uint8}), hnd, s)
dlopen(s::String) = ccall(:jl_load_dynamic_library, Ptr{Void}, (Ptr{Uint8},), s)
dlopen(s::String, flags::Integer) = ccall(:jl_load_dynamic_library, Ptr{Void}, (Ptr{Uint8},Uint32), s, flags)
dlopen(s::String) = dlopen(s, RTLD_LAZY | RTLD_DEEPBIND)
dlclose(p::Ptr) = ccall(:uv_dlclose,Void,(Ptr{Void},),p)

cfunction(f::Function, r, a) =
Expand Down
7 changes: 7 additions & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,13 @@ export
NaN,
NaN32,
OUTPUT_STREAM,
RTLD_LOCAL,
RTLD_GLOBAL,
RTLD_LAZY,
RTLD_NOW,
RTLD_NODELETE,
RTLD_DEEPBIND,
RTLD_FIRST,
STDERR,
STDIN,
STDOUT,
Expand Down
14 changes: 13 additions & 1 deletion doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3003,10 +3003,22 @@ C Interface

Generate C-callable function pointer from Julia function.

.. function:: dlopen(libfile::String)
.. function:: dlopen(libfile::String [, flags::Integer])

Load a shared library, returning an opaque handle.

The optional flags argument is a bitwise-or of zero or more of
RTLD_LOCAL, RTLD_GLOBAL, RTLD_LAZY, RTLD_NOW, RTLD_NODELETE,
RTLD_NOLOAD, RTLD_DEEPBIND, and RTLD_FIRST. These are converted to
the corresponding flags of the POSIX (and/or GNU libc and/or MacOS)
dlopen command, if possible, or are ignored if the specified
functionality is not available on the current platform. The
default is RTLD_LAZY|RTLD_DEEPBIND|RTLD_LOCAL. An important usage
of these flags, on POSIX platforms, is to specify
RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL in order for the library's
symbols to be available for usage in other shared libraries, in
situations where there are dependencies between shared libraries.

.. function:: dlsym(handle, sym)

Look up a symbol from a shared library handle, return callable function pointer on success.
Expand Down
2 changes: 1 addition & 1 deletion src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ static void *add_library_sym(char *name, char *lib)
else {
hnd = libMap[lib];
if (hnd == NULL) {
hnd = jl_load_dynamic_library(lib);
hnd = jl_load_dynamic_library(lib, JL_RTLD_DEFAULT);
if (hnd != NULL)
libMap[lib] = hnd;
else
Expand Down
31 changes: 24 additions & 7 deletions src/dlload.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,28 @@ extern char *julia_home;
char *jl_lookup_soname(char *pfx, size_t n);
#endif

int jl_uv_dlopen(const char* filename, uv_lib_t* lib)
#define JL_RTLD(flags, FLAG) (flags & JL_RTLD_ ## FLAG ? RTLD_ ## FLAG : 0)

int jl_uv_dlopen(const char* filename, uv_lib_t* lib, unsigned flags)
{
#ifdef RTLD_DEEPBIND
#if defined(RTLD_GLOBAL) && defined(RTLD_LAZY) /* POSIX flags available */
dlerror(); /* Reset error status. */
lib->handle = dlopen(filename, RTLD_LAZY|RTLD_DEEPBIND);
lib->handle = dlopen(filename,
(flags & JL_RTLD_NOW ? RTLD_NOW : RTLD_LAZY)
| JL_RTLD(flags, GLOBAL) | JL_RTLD(flags, LOCAL)
#ifdef RTLD_NODELETE
| JL_RTLD(flags, NODELETE)
#endif
#ifdef RTLD_NOLOAD
| JL_RTLD(flags, NOLOAD)
#endif
#ifdef RTLD_DEEPBIND
| JL_RTLD(flags, DEEPBIND)
#endif
#ifdef RTLD_FIRST
| JL_RTLD(flags, FIRST)
#endif
);
if (lib->handle) {
lib->errmsg = NULL;
return 0;
Expand All @@ -51,7 +68,7 @@ int jl_uv_dlopen(const char* filename, uv_lib_t* lib)
#endif
}

uv_lib_t *jl_load_dynamic_library(char *modname)
uv_lib_t *jl_load_dynamic_library(char *modname, unsigned flags)
{
int error;
char *ext;
Expand All @@ -76,7 +93,7 @@ uv_lib_t *jl_load_dynamic_library(char *modname)
#else
else if (modname[0] == '/') {
#endif
error = jl_uv_dlopen(modname,handle);
error = jl_uv_dlopen(modname,handle,flags);
if (!error) goto done;
}

Expand All @@ -86,12 +103,12 @@ uv_lib_t *jl_load_dynamic_library(char *modname)
handle->handle = NULL;
/* try loading from standard library path */
snprintf(path, PATHBUF, "%s%s", modname, ext);
error = jl_uv_dlopen(path, handle);
error = jl_uv_dlopen(path, handle,flags);
if (!error) goto done;
}
#if defined(__linux__)
char *soname = jl_lookup_soname(modname, strlen(modname));
error = (soname==NULL) || jl_uv_dlopen(soname, handle);
error = (soname==NULL) || jl_uv_dlopen(soname, handle, flags);
if (!error) goto done;
#endif

Expand Down
2 changes: 1 addition & 1 deletion src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ void julia_init(char *imageFile)
{
jl_page_size = getPageSize();
jl_find_stack_bottom();
jl_dl_handle = jl_load_dynamic_library(NULL);
jl_dl_handle = jl_load_dynamic_library(NULL, JL_RTLD_DEFAULT);
#ifdef __WIN32__
uv_dlopen("ntdll.dll",jl_ntdll_handle); //bypass julia's pathchecking for system dlls
uv_dlopen("Kernel32.dll",jl_kernel32_handle);
Expand Down
11 changes: 10 additions & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,16 @@ DLLEXPORT void jl_module_export(jl_module_t *from, jl_sym_t *s);
void jl_add_standard_imports(jl_module_t *m);

// external libraries
DLLEXPORT uv_lib_t *jl_load_dynamic_library(char *fname);
enum JL_RTLD_CONSTANT {
JL_RTLD_LOCAL=0U, JL_RTLD_GLOBAL=1U, /* LOCAL=0 since it is the default */
JL_RTLD_LAZY=2U, JL_RTLD_NOW=4U,
/* Linux/glibc and MacOS X: */
JL_RTLD_NODELETE=8U, JL_RTLD_NOLOAD=16U,
/* Linux/glibc: */ JL_RTLD_DEEPBIND=32U,
/* MacOS X 10.5+: */ JL_RTLD_FIRST=64U
};
#define JL_RTLD_DEFAULT (JL_RTLD_LAZY | JL_RTLD_DEEPBIND)
DLLEXPORT uv_lib_t *jl_load_dynamic_library(char *fname, unsigned flags);
DLLEXPORT void *jl_dlsym_e(uv_lib_t *handle, char *symbol);
DLLEXPORT void *jl_dlsym(uv_lib_t *handle, char *symbol);
DLLEXPORT uv_lib_t *jl_wrap_raw_dl_handle(void *handle);
Expand Down