DYLD_FALLBACK_FRAMEWORK_PATH, DYLD_FALLBACK_LIBRARY_PATH, DYLD_FRAMEWORK_PATH, flat_namespace| DLOPEN(3) | Library Functions Manual | DLOPEN(3) |
NAME
dlopen — load and
link a dynamic library or bundle
SYNOPSIS
#include
<dlfcn.h>
void*
dlopen(const
char* path, int
mode);
DESCRIPTION
dlopen()
examines the mach-o file specified by path. If the
file is compatible with the current process and has not already been loaded
into the current process, it is loaded and linked. After being linked, if it
contains any initializer functions, they are called, before
dlopen() returns. dlopen()
can load dynamic libraries and bundles. It returns a handle that can be used
with dlsym() and dlclose().
A second call to dlopen() with the same path will
return the same handle, but the internal reference count for the handle will
be incremented.
If a null pointer is passed in
path,
dlopen()
returns a handle equivalent to RTLD_DEFAULT.
mode contains options to
dlopen().
It must contain one or more of the following values, possibly ORed
together:
RTLD_LAZY- Each external function reference is bound the first time the function is called.
RTLD_NOW- All external function references are bound immediately during the call to
dlopen().
RTLD_LAZY is normally
preferred, for reasons of efficiency. However,
RTLD_NOW is useful to ensure that any undefined
symbols are discovered during the call to
dlopen().
If neither RTLD_LAZY nor RTLD_NOW is specified, the default is
RTLD_LAZY.
Note: With chained-fixups (the default mach-o format since macOS 12 and iOS 15) using RTLD_LAZY or RTLD_NOW has no effect, as all symbols are immediately bound.
One of the following flags may be ORed into the mode argument:
RTLD_GLOBAL- Symbols exported from this image (dynamic library or bundle) will be
available to any images build with -flat_namespace option to
ld(1) or to calls to
dlsym() when using a special handle. RTLD_LOCAL- Symbols exported from this image (dynamic library or bundle) are generally
hidden and only available to
dlsym() when directly using the handle returned by this call todlopen().
If neither RTLD_GLOBAL nor RTLD_LOCAL is specified, the default is RTLD_GLOBAL.
One of the following may be ORed into the mode argument:
RTLD_NOLOAD- The specified image is not loaded. However, a valid
handle is returned if the image already exists in
the process. This provides a way to query if an image is already loaded.
The handle returned is ref-counted, so you
eventually need a corresponding call to
dlclose() RTLD_NODELETE- The specified image is tagged so that will never be removed from the
address space, even after all clients have released it via
dlclose()
Additionally, the following may be ORed into the mode argument:
RTLD_FIRST- The returned handle is tagged so that any
dlsym() calls on the handle will only search the image specified, and not subsequent images. If path is NULL and the option RTLD_FIRST is used, the handle returned will only search the main executable.
SEARCHING
In general, dyld does not search for dylibs. Dylibs are specified
via a full path, either as a static dependent dylib in a mach-o file, or as
a path passed to dlopen() , But during development
the env vars DYLD_LIBRARY_PATH and DYLD_FRAMEWORK_PATH can be used to
override the specified path and look for the leaf framework/dylib name in
the specified directories.
When path does not contain a
slash character (i.e. it is just a leaf name),
dlopen()
will do searching. If $DYLD_LIBRARY_PATH was set at launch, dyld will first
look in that directory. Next, if the calling mach-o file or the main
executable specify an LC_RPATH, then dyld will look in those directories.
Next, if the process is unrestricted, dyld will search in the current
working directory. Lastly, for old binaries, dyld will try some fallbacks.
If $DYLD_FALLBACK_LIBRARY_PATH was set at launch, dyld will search in those
directories, otherwise, dyld will look in /usr/local/lib/ (if the process is
unrestricted), and then in /usr/lib/.
When path looks like a framework path (e.g. /stuff/foo.framework/foo), if $DYLD_FRAMEWORK_PATH was set at launch, dyld will first look in that directory for the framework partial path (e.g. foo.framework/foo). Next, dyld will try the supplied path as-is (using current working directory for relative paths). Lastly, for old binaries, dyld will try some fallbacks. If $DYLD_FALLBACK_FRAMEWORK_PATH was set at launch, dyld will search those directories. Otherwise, it will search /Library/Frameworks (on macOS if process is unrestricted), then /System/Library/Frameworks.
When path contains a slash but
is not a framework path (i.e. a full path or a partial path to a dylib),
dlopen()
first looks in (if set) in $DYLD_LIBRARY_PATH (with leaf part from
path ). Next, dyld tries the supplied
path (using current working directory for relative
paths (but only for unrestricted processes)). Lastly, for older binaries,
dyld will try fallbacks. If $DYLD_FALLBACK_LIBRARY_PATH was set at launch,
dyld will search in those directories, otherwise, dyld will look in
/usr/local/lib/ (if the process is unrestricted), and then in /usr/lib/.
If you want to find a dylib via the dynamic run path, use @rpath (e.g. dlopen("@rpath/libfoo.dylib",xxx)),
Note: There are no configuration files to control dlopen searching.
Note: If the main executable is a set[ug]id binary or codesigned with entitlements, then all environment variables are ignored, and only a full path can be used.
Note: Apple platforms use "universal" files to combine 32-bit and 64-bit libraries. This means there are no separate 32-bit and 64-bit search paths.
Note: On Apple platforms most OS dylibs are combined into the dyld cache and do not exist on disk. Therefore, calling stat() to preflight if an OS dylib exists won't work.
RETURN VALUES
If dlopen() fails, it returns a null
pointer, and sets an error condition which may be interrogated with
dlerror().
SEE ALSO
dlopen_preflight(3) dlclose(3) dlsym(3) dlerror(3) dyld(1) ld(1)
| February 8, 2024 | macOS 26.4 |