dlopen()

Gain access to an executable object file

Synopsis:

#include <dlfcn.h>

void * dlopen( const char * pathname, 
               int mode );

Arguments:

pathname
NULL, or the path to the executable object file that you want to access.
mode
Flags that control how dlopen() operates; see "The mode," below.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The dlopen() function gives you direct access to the dynamic linking facilities by making the executable object file specified in pathname available to the calling process. It returns a handle that you can use in subsequent calls to dlsym() and dlclose().


Note:

The dlopen/() function is available only to a dynamically-linked process. A statically-linked process (one where libc is linked statically) can't call dlopen() because a statically-linked executable:

  • doesn't export any of its symbols
  • can't export the required structure for libraries to link against
  • can't fill structures at startup needed to load subsequent shared objects.

Any dependencies recorded within pathname are loaded as part of the dlopen() call. These dependencies are searched in load-order to locate any additional dependencies. This process continues until all of the dependencies for pathname have been satisfied. This dependency tree is called a group.

If pathname is NULL, dlopen() provides a handle to the running process's global symbol object. This provides access to the symbols from the original program image file, the dependencies it loaded at startup, plus any objects opened with dlopen() calls using the RTLD_GLOBAL flag. This set of symbols can change dynamically if the application subsequently calls dlopen() using RTLD_GLOBAL.

You can use dlopen() any number of times to open objects whose names resolve to the same absolute or relative path name; the object is loaded into the process's address space only once.

In order to find the shared objects, the following directories or paths are searched in order:

Note that LD_LIBRARY_PATH is ignored if the binary is setuid and the euid is not the same as the uid of the user running the binary. This is done for security purposes.


Note: The above directories are set as follows:
  • The RPATH value is set up when binary is linked, using the ld command line option -rpath. See ld for details.
  • The LD_LIBRARY_PATH is generally set up by other startup script, either in the boot image or by a secondary script. For example, on self hosted QNX system, it is setup by ph script. It is not part of any default environment.
  • _CS_LIBPATH is populated by the kernel, and the default value is based on the LD_LIBRARY_PATH value of the procnto command line in the boot image. Note that, you may use getconf utility to inspect this value and setconf to set this value. For example:
    setconf _CS_LIBPATH 'getconf _CS_LIBPATH':/new/path

When loading shared objects, the application should open a specific version instead of relying on the version pointed to by a symbolic link.

The mode

The mode argument indicates how dlopen() operates on pathname when handling relocations, and controls the visibility of symbols found in pathname and its dependencies.

The mode argument is a bitwise-OR of the constants described below. Note that the relocation and visibility constants are mutually exclusive.

Relocation

When you load an object by calling dlopen(), the object may contain references to symbols whose addresses aren't known until the object has been loaded; these references must be relocated before accessing the symbols. The mode controls when relocations take place, and can be one of:

RTLD_LAZY
References to data symbols are relocated when the object is loaded. References to functions aren't relocated until that function is invoked. This improves performance by preventing unnecessary relocations.
RTLD_NOW
All references are relocated when the object is loaded. This may waste cycles if relocations are performed for functions that never get called, but this behavior could be useful for applications that need to know that all symbols referenced during execution are available as soon as the object is loaded.

Note: RTLD_LAZY isn't currently supported.

Visibility

The following mode bits determine the scope of visibility for symbols loaded with dlopen():

RTLD_GLOBAL
Make the object's global symbols available to any other object. Symbol lookup using dlopen( 0, mode ) and an associated dlsym() are also able to find the object's symbols.
RTLD_LOCAL
Make the object's global symbols available only to objects in the same group.

The program's image and any objects loaded at program startup have a mode of RTLD_GLOBAL; the default mode for objects acquired with dlopen() is RTLD_LOCAL. A local object may be part of the dependencies for more than one group; any object with a RTLD_LOCAL mode referenced as a dependency of an object with a RTLD_GLOBAL mode is promoted to RTLD_GLOBAL.

Objects loaded with dlopen() that require relocations against global symbols can reference the symbols in any RTLD_GLOBAL object.

You can OR the mode with the following values to affect symbol scope:

RTLD_GROUP
Only symbols from the associated group are available. All dependencies between group members must be satisfied by the objects in the group.
RTLD_WORLD
Only symbols from RTLD_GLOBAL objects are available.

The default mode is RTLD_WORLD | RTLD_GROUP.


Note: If you specify RTLD_WORLD without RTLD_GROUP, dlopen() doesn't load any of the DLL's dependencies.

Symbol Resolution

When resolving the symbols in the shared object, the runtime linker searches for them in the dynamic symbol table using the following order:

By default:
  1. main executable
  2. the shared object being loaded
  3. all other loaded shared objects that were loaded with the RTLD_GLOBAL flag.
When -Bsymbolic is specified:
  1. the shared object being loaded
  2. main executable
  3. all other loaded shared objects that were loaded with the RTLD_GLOBAL flag.

For executables, the dynamic symbol table typically contains only those symbols that are known to be needed by any shared libraries. This is determined by the linker when the executable is linked against a shared library.

Since you don't link your executable against a shared object that you load with dlopen(), the linker can't determine which executable symbols need to be made available to the shared object.

If your shared object needs to resolve symbols in the executable, then you may force the linker to make all of the symbols in the executable available for dynamic linking by specifying the -E linker option. For example:

qcc -Vgcc_ntox86 -Wl,-E -o main main.o

Shared objects always place all their symbols in dynamic symbol tables, so this option isn't needed when linking a shared object.

Returns:

A handle to the object, or NULL if an error occurs.


Note: Don't interpret the value of this handle in any way. For example, if you open the same object repeatedly, don't assume that dlopen() returns the same handle.

Errors:

If an error occurs, more detailed diagnostic information is available from dlerror().

Environment variables:

DL_DEBUG
Display debugging information about the libraries as they're opened.
LD_LIBRARY_PATH
The LD_LIBRARY_PATH environment variable is searched for any dependencies required by pathname.

Classification:

POSIX 1003.1 XSI

Safety:
Cancellation point Yes
Interrupt handler No
Signal handler No
Thread Yes

Caveats:

Some symbols defined in executables or shared objects might not be available to the runtime linker. The symbol table created by ld for use by the runtime linker might contain a subset of the symbols defined in the object.

See also:

dladdr(), dlclose(), dlerror(), dlsym()

ld, qcc in the Utilities Reference