| .\" Copyright 1995 Yggdrasil Computing, Incorporated. |
| .\" written by Adam J. Richter (adam@yggdrasil.com), |
| .\" with typesetting help from Daniel Quinlan (quinlan@yggdrasil.com). |
| .\" and Copyright 2003, 2015 Michael Kerrisk <mtk.manpages@gmail.com> |
| .\" |
| .\" %%%LICENSE_START(GPLv2+_DOC_FULL) |
| .\" This is free documentation; you can redistribute it and/or |
| .\" modify it under the terms of the GNU General Public License as |
| .\" published by the Free Software Foundation; either version 2 of |
| .\" the License, or (at your option) any later version. |
| .\" |
| .\" The GNU General Public License's references to "object code" |
| .\" and "executables" are to be interpreted as the output of any |
| .\" document formatting or typesetting system, including |
| .\" intermediate and printed output. |
| .\" |
| .\" This manual is distributed in the hope that it will be useful, |
| .\" but WITHOUT ANY WARRANTY; without even the implied warranty of |
| .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| .\" GNU General Public License for more details. |
| .\" |
| .\" You should have received a copy of the GNU General Public |
| .\" License along with this manual; if not, see |
| .\" <http://www.gnu.org/licenses/>. |
| .\" %%%LICENSE_END |
| .\" |
| .\" Modified by David A. Wheeler <dwheeler@dwheeler.com> 2000-11-28. |
| .\" Applied patch by Terran Melconian, aeb, 2001-12-14. |
| .\" Modified by Hacksaw <hacksaw@hacksaw.org> 2003-03-13. |
| .\" Modified by Matt Domsch, 2003-04-09: _init and _fini obsolete |
| .\" Modified by Michael Kerrisk <mtk.manpages@gmail.com> 2003-05-16. |
| .\" Modified by Walter Harms: dladdr, dlvsym |
| .\" Modified by Petr Baudis <pasky@suse.cz>, 2008-12-04: dladdr caveat |
| .\" |
| .TH DLOPEN 3 2017-09-15 "Linux" "Linux Programmer's Manual" |
| .SH NAME |
| dlclose, dlopen, dlmopen \- |
| open and close a shared object |
| .SH SYNOPSIS |
| .B #include <dlfcn.h> |
| .PP |
| .BI "void *dlopen(const char *" filename ", int " flags ); |
| .PP |
| .BI "int dlclose(void *" handle ); |
| .PP |
| .B #define _GNU_SOURCE |
| .br |
| .B #include <dlfcn.h> |
| .PP |
| .BI "void *dlmopen (Lmid_t " lmid ", const char *" filename ", int " flags ); |
| .PP |
| Link with \fI\-ldl\fP. |
| .SH DESCRIPTION |
| .SS dlopen() |
| The function |
| .BR dlopen () |
| loads the dynamic shared object (shared library) |
| file named by the null-terminated |
| string |
| .I filename |
| and returns an opaque "handle" for the loaded object. |
| This handle is employed with other functions in the dlopen API, such as |
| .BR dlsym (3), |
| .BR dladdr (3), |
| .BR dlinfo (3), |
| and |
| .BR dlclose (). |
| .PP |
| If |
| .I filename |
| .\" FIXME On Solaris, when handle is NULL, we seem to get back |
| .\" a handle for (something like) the root of the namespace. |
| .\" The point here is that if we do a dlmopen(LM_ID_NEWLM), then |
| .\" the filename==NULL case returns a different handle than |
| .\" in the initial namespace. But, on glibc, the same handle is |
| .\" returned. This is probably a bug in glibc. |
| .\" |
| is NULL, then the returned handle is for the main program. |
| If |
| .I filename |
| contains a slash ("/"), then it is interpreted as a (relative |
| or absolute) pathname. |
| Otherwise, the dynamic linker searches for the object as follows |
| (see |
| .BR ld.so (8) |
| for further details): |
| .IP o 4 |
| (ELF only) If the executable file for the calling program |
| contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag, |
| then the directories listed in the DT_RPATH tag are searched. |
| .IP o |
| If, at the time that the program was started, the environment variable |
| .B LD_LIBRARY_PATH |
| was defined to contain a colon-separated list of directories, |
| then these are searched. |
| (As a security measure, this variable is ignored for set-user-ID and |
| set-group-ID programs.) |
| .IP o |
| (ELF only) If the executable file for the calling program |
| contains a DT_RUNPATH tag, then the directories listed in that tag |
| are searched. |
| .IP o |
| The cache file |
| .I /etc/ld.so.cache |
| (maintained by |
| .BR ldconfig (8)) |
| is checked to see whether it contains an entry for |
| .IR filename . |
| .IP o |
| The directories |
| .I /lib |
| and |
| .I /usr/lib |
| are searched (in that order). |
| .PP |
| If the object specified by |
| .I filename |
| has dependencies on other shared objects, |
| then these are also automatically loaded by the dynamic linker |
| using the same rules. |
| (This process may occur recursively, |
| if those objects in turn have dependencies, and so on.) |
| .PP |
| One of the following two values must be included in |
| .IR flags : |
| .TP |
| .B RTLD_LAZY |
| Perform lazy binding. |
| Resolve symbols only as the code that references them is executed. |
| If the symbol is never referenced, then it is never resolved. |
| (Lazy binding is performed only for function references; |
| references to variables are always immediately bound when |
| the shared object is loaded.) |
| Since glibc 2.1.1, |
| .\" commit 12b5b6b7f78ea111e89bbf638294a5413c791072 |
| this flag is overridden by the effect of the |
| .B LD_BIND_NOW |
| environment variable. |
| .TP |
| .B RTLD_NOW |
| If this value is specified, or the environment variable |
| .B LD_BIND_NOW |
| is set to a nonempty string, |
| all undefined symbols in the shared object are resolved before |
| .BR dlopen () |
| returns. |
| If this cannot be done, an error is returned. |
| .PP |
| Zero or more of the following values may also be ORed in |
| .IR flags : |
| .TP |
| .B RTLD_GLOBAL |
| The symbols defined by this shared object will be |
| made available for symbol resolution of subsequently loaded shared objects. |
| .TP |
| .B RTLD_LOCAL |
| This is the converse of |
| .BR RTLD_GLOBAL , |
| and the default if neither flag is specified. |
| Symbols defined in this shared object are not made available to resolve |
| references in subsequently loaded shared objects. |
| .TP |
| .BR RTLD_NODELETE " (since glibc 2.2)" |
| Do not unload the shared object during |
| .BR dlclose (). |
| Consequently, the object's static variables are not reinitialized |
| if the object is reloaded with |
| .BR dlopen () |
| at a later time. |
| .TP |
| .BR RTLD_NOLOAD " (since glibc 2.2)" |
| Don't load the shared object. |
| This can be used to test if the object is already resident |
| .RB ( dlopen () |
| returns NULL if it is not, or the object's handle if it is resident). |
| This flag can also be used to promote the flags on a shared object |
| that is already loaded. |
| For example, a shared object that was previously loaded with |
| .B RTLD_LOCAL |
| can be reopened with |
| .BR RTLD_NOLOAD\ |\ RTLD_GLOBAL . |
| .\" |
| .TP |
| .BR RTLD_DEEPBIND " (since glibc 2.3.4)" |
| .\" Inimitably described by UD in |
| .\" http://sources.redhat.com/ml/libc-hacker/2004-09/msg00083.html. |
| Place the lookup scope of the symbols in this |
| shared object ahead of the global scope. |
| This means that a self-contained object will use |
| its own symbols in preference to global symbols with the same name |
| contained in objects that have already been loaded. |
| .PP |
| If |
| .I filename |
| is NULL, then the returned handle is for the main program. |
| When given to |
| .BR dlsym (), |
| this handle causes a search for a symbol in the main program, |
| followed by all shared objects loaded at program startup, |
| and then all shared objects loaded by |
| .BR dlopen () |
| with the flag |
| .BR RTLD_GLOBAL . |
| .PP |
| External references in the shared object are resolved using the |
| shared objects in that object's dependency list and any other |
| objects previously opened with the |
| .B RTLD_GLOBAL |
| flag. |
| If the executable was linked with the flag "\-rdynamic" |
| (or, synonymously, "\-\-export\-dynamic"), |
| then the global symbols in the executable will also be used |
| to resolve references in a dynamically loaded shared object. |
| .PP |
| If the same shared object is loaded again with |
| .BR dlopen (), |
| the same object handle is returned. |
| The dynamic linker maintains reference |
| counts for object handles, so a dynamically loaded shared object is not |
| deallocated until |
| .BR dlclose () |
| has been called on it as many times as |
| .BR dlopen () |
| has succeeded on it. |
| Any initialization returns (see below) are called just once. |
| However, a subsequent |
| .BR dlopen () |
| call that loads the same shared object with |
| .B RTLD_NOW |
| may force symbol resolution for a shared object earlier loaded with |
| .BR RTLD_LAZY . |
| .PP |
| If |
| .BR dlopen () |
| fails for any reason, it returns NULL. |
| .\" |
| .SS dlmopen() |
| This function performs the same task as |
| .BR dlopen ()\(emthe |
| .I filename |
| and |
| .I flags |
| arguments, as well as the return value, are the same, |
| except for the differences noted below. |
| .PP |
| The |
| .BR dlmopen () |
| function differs from |
| .BR dlopen () |
| primarily in that it accepts an additional argument, |
| .IR lmid , |
| that specifies the link-map list (also referred to as a |
| .IR namespace ) |
| in which the shared object should be loaded. |
| (By comparison, |
| .BR dlopen () |
| adds the dynamically loaded shared object to the same namespace as |
| the shared object from which the |
| .BR dlopen () |
| call is made.) |
| The |
| .I Lmid_t |
| type is an opaque handle that refers to a namespace. |
| .PP |
| The |
| .I lmid |
| argument is either the ID of an existing namespace |
| .\" FIXME: Is using dlinfo() RTLD_DI_LMID the right technique? |
| (which can be obtained using the |
| .BR dlinfo (3) |
| .B RTLD_DI_LMID |
| request) or one of the following special values: |
| .TP |
| .B LM_ID_BASE |
| Load the shared object in the initial namespace |
| (i.e., the application's namespace). |
| .TP |
| .B LM_ID_NEWLM |
| Create a new namespace and load the shared object in that namespace. |
| The object must have been correctly linked |
| to reference all of the other shared objects that it requires, |
| since the new namespace is initially empty. |
| .PP |
| If |
| .I filename |
| is NULL, then the only permitted value for |
| .I lmid |
| is |
| .BR LM_ID_BASE . |
| .SS dlclose() |
| The function |
| .BR dlclose () |
| decrements the reference count on the |
| dynamically loaded shared object referred to by |
| .IR handle . |
| If the reference count drops to zero, |
| then the object is unloaded. |
| All shared objects that were automatically loaded when |
| .BR dlopen () |
| was invoked on the object referred to by |
| .I handle |
| are recursively closed in the same manner. |
| .PP |
| A successful return from |
| .BR dlclose () |
| does not guarantee that the symbols associated with |
| .I handle |
| are removed from the caller's address space. |
| In addition to references resulting from explicit |
| .BR dlopen () |
| calls, a shared object may have been implicitly loaded |
| (and reference counted) because of dependencies in other shared objects. |
| Only when all references have been released can the shared object |
| be removed from the address space. |
| .SH RETURN VALUE |
| On success, |
| .BR dlopen () |
| and |
| .BR dlmopen () |
| return a non-NULL handle for the loaded library. |
| On error |
| (file could not be found, was not readable, had the wrong format, |
| or caused errors during loading), |
| these functions return NULL. |
| .PP |
| On success, |
| .BR dlclose () |
| returns 0; on error, it returns a nonzero value. |
| .PP |
| Errors from these functions can be diagnosed using |
| .BR dlerror (3). |
| .SH VERSIONS |
| .BR dlopen () |
| and |
| .BR dlclose () |
| are present in glibc 2.0 and later. |
| .BR dlmopen () |
| first appeared in glibc 2.3.4. |
| .SH ATTRIBUTES |
| For an explanation of the terms used in this section, see |
| .BR attributes (7). |
| .TS |
| allbox; |
| lbw30 lb lb |
| l l l. |
| Interface Attribute Value |
| T{ |
| .BR dlopen (), |
| .BR dlmopen (), |
| .BR dlclose () |
| T} Thread safety MT-Safe |
| .TE |
| .SH CONFORMING TO |
| POSIX.1-2001 describes |
| .BR dlclose () |
| and |
| .BR dlopen (). |
| The |
| .BR dlmopen () |
| function is a GNU extension. |
| .PP |
| The |
| .BR RTLD_NOLOAD , |
| .BR RTLD_NODELETE , |
| and |
| .BR RTLD_DEEPBIND |
| flags are GNU extensions; |
| the first two of these flags are also present on Solaris. |
| .SH NOTES |
| .SS dlmopen() and namespaces |
| A link-map list defines an isolated namespace for the |
| resolution of symbols by the dynamic linker. |
| Within a namespace, |
| dependent shared objects are implicitly loaded according to the usual rules, |
| and symbol references are likewise resolved according to the usual rules, |
| but such resolution is confined to the definitions provided by the |
| objects that have been (explicitly and implicitly) loaded into the namespace. |
| .PP |
| The |
| .BR dlmopen () |
| function permits object-load isolation\(emthe ability |
| to load a shared object in a new namespace without |
| exposing the rest of the application to the symbols |
| made available by the new object. |
| Note that the use of the |
| .B RTLD_LOCAL |
| flag is not sufficient for this purpose, |
| since it prevents a shared object's symbols from being available to |
| .I any |
| other shared object. |
| In some cases, |
| we may want to make the symbols provided by a dynamically |
| loaded shared object available to (a subset of) other shared objects |
| without exposing those symbols to the entire application. |
| This can be achieved by using a separate namespace and the |
| .B RTLD_GLOBAL |
| flag. |
| .PP |
| The |
| .BR dlmopen () |
| function also can be used to provide better isolation than the |
| .BR RTLD_LOCAL |
| flag. |
| In particular, shared objects loaded with |
| .BR RTLD_LOCAL |
| may be promoted to |
| .BR RTLD_GLOBAL |
| if they are dependencies of another shared object loaded with |
| .BR RTLD_GLOBAL . |
| Thus, |
| .BR RTLD_LOCAL |
| is insufficient to isolate a loaded shared object except in the (uncommon) |
| case where one has explicit control over all shared object dependencies. |
| .PP |
| Possible uses of |
| .BR dlmopen () |
| are plugins where the author of the plugin-loading framework |
| can't trust the plugin authors and does not wish |
| any undefined symbols from the plugin framework to be resolved to plugin |
| symbols. |
| Another use is to load the same object more than once. |
| Without the use of |
| .BR dlmopen (), |
| this would require the creation of distinct copies of the shared object file. |
| Using |
| .BR dlmopen (), |
| this can be achieved by loading the same shared object file into |
| different namespaces. |
| .PP |
| The glibc implementation supports a maximum of |
| .\" DL_NNS |
| 16 namespaces. |
| .\" |
| .SS Initialization and finalization functions |
| Shared objects may export functions using the |
| .B __attribute__((constructor)) |
| and |
| .B __attribute__((destructor)) |
| function attributes. |
| Constructor functions are executed before |
| .BR dlopen () |
| returns, and destructor functions are executed before |
| .BR dlclose () |
| returns. |
| A shared object may export multiple constructors and destructors, |
| and priorities can be associated with each function |
| to determine the order in which they are executed. |
| See the |
| .BR gcc |
| info pages (under "Function attributes") |
| .\" info gcc "C Extensions" "Function attributes" |
| for further information. |
| .PP |
| An older method of (partially) achieving the same result is via the use of |
| two special symbols recognized by the linker: |
| .B _init |
| and |
| .BR _fini . |
| If a dynamically loaded shared object exports a routine named |
| .BR _init (), |
| then that code is executed after loading a shared object, before |
| .BR dlopen () |
| returns. |
| If the shared object exports a routine named |
| .BR _fini (), |
| then that routine is called just before the object is unloaded. |
| In this case, one must avoid linking against the system startup files, |
| which contain default versions of these files; |
| this can be done by using the |
| .BR gcc (1) |
| .I \-nostartfiles |
| command-line option. |
| .PP |
| Use of |
| .B _init |
| and |
| .BR _fini |
| is now deprecated in favor of the aforementioned |
| constructors and destructors, |
| which among other advantages, |
| permit multiple initialization and finalization functions to be defined. |
| .\" |
| .\" Using these routines, or the gcc |
| .\" .B \-nostartfiles |
| .\" or |
| .\" .B \-nostdlib |
| .\" options, is not recommended. |
| .\" Their use may result in undesired behavior, |
| .\" since the constructor/destructor routines will not be executed |
| .\" (unless special measures are taken). |
| .\" .\" void _init(void) __attribute__((constructor)); |
| .\" .\" void _fini(void) __attribute__((destructor)); |
| .\" |
| .PP |
| Since glibc 2.2.3, |
| .BR atexit (3) |
| can be used to register an exit handler that is automatically |
| called when a shared object is unloaded. |
| .SS History |
| These functions are part of the dlopen API, derived from SunOS. |
| .SH BUGS |
| As at glibc 2.24, specifying the |
| .BR RTLD_GLOBAL |
| flag when calling |
| .BR dlmopen () |
| .\" dlerror(): "invalid mode" |
| generates an error. |
| Furthermore, specifying |
| .BR RTLD_GLOBAL |
| when calling |
| .BR dlopen () |
| results in a program crash |
| .RB ( SIGSEGV ) |
| if the call is made from any object loaded in a |
| namespace other than the initial namespace. |
| .SH EXAMPLE |
| The program below loads the (glibc) math library, |
| looks up the address of the |
| .BR cos (3) |
| function, and prints the cosine of 2.0. |
| The following is an example of building and running the program: |
| .PP |
| .in +4n |
| .EX |
| $ \fBcc dlopen_demo.c \-ldl\fP |
| $ \fB./a.out\fP |
| \-0.416147 |
| .EE |
| .in |
| .SS Program source |
| \& |
| .EX |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <dlfcn.h> |
| #include <gnu/lib-names.h> /* Defines LIBM_SO (which will be a |
| string such as "libm.so.6") */ |
| int |
| main(void) |
| { |
| void *handle; |
| double (*cosine)(double); |
| char *error; |
| |
| handle = dlopen(LIBM_SO, RTLD_LAZY); |
| if (!handle) { |
| fprintf(stderr, "%s\en", dlerror()); |
| exit(EXIT_FAILURE); |
| } |
| |
| dlerror(); /* Clear any existing error */ |
| |
| cosine = (double (*)(double)) dlsym(handle, "cos"); |
| |
| /* According to the ISO C standard, casting between function |
| pointers and 'void *', as done above, produces undefined results. |
| POSIX.1-2003 and POSIX.1-2008 accepted this state of affairs and |
| proposed the following workaround: |
| |
| *(void **) (&cosine) = dlsym(handle, "cos"); |
| |
| This (clumsy) cast conforms with the ISO C standard and will |
| avoid any compiler warnings. |
| |
| The 2013 Technical Corrigendum to POSIX.1-2008 (a.k.a. |
| POSIX.1-2013) improved matters by requiring that conforming |
| implementations support casting 'void *' to a function pointer. |
| Nevertheless, some compilers (e.g., gcc with the '-pedantic' |
| option) may complain about the cast used in this program. */ |
| .\" http://pubs.opengroup.org/onlinepubs/009695399/functions/dlsym.html#tag_03_112_08 |
| .\" http://pubs.opengroup.org/onlinepubs/9699919799/functions/dlsym.html#tag_16_96_07 |
| .\" http://austingroupbugs.net/view.php?id=74 |
| |
| error = dlerror(); |
| if (error != NULL) { |
| fprintf(stderr, "%s\en", error); |
| exit(EXIT_FAILURE); |
| } |
| |
| printf("%f\en", (*cosine)(2.0)); |
| dlclose(handle); |
| exit(EXIT_SUCCESS); |
| } |
| .EE |
| .SH SEE ALSO |
| .BR ld (1), |
| .BR ldd (1), |
| .BR pldd (1), |
| .BR dl_iterate_phdr (3), |
| .BR dladdr (3), |
| .BR dlerror (3), |
| .BR dlinfo (3), |
| .BR dlsym (3), |
| .BR rtld-audit (7), |
| .BR ld.so (8), |
| .BR ldconfig (8) |
| .PP |
| gcc info pages, ld info pages |