diff options
Diffstat (limited to 'man/man3/dlopen.3')
-rw-r--r-- | man/man3/dlopen.3 | 624 |
1 files changed, 624 insertions, 0 deletions
diff --git a/man/man3/dlopen.3 b/man/man3/dlopen.3 new file mode 100644 index 0000000..14f1689 --- /dev/null +++ b/man/man3/dlopen.3 @@ -0,0 +1,624 @@ +'\" t +.\" 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> +.\" +.\" SPDX-License-Identifier: GPL-2.0-or-later +.\" +.\" 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 2024-05-02 "Linux man-pages (unreleased)" +.SH NAME +dlclose, dlopen, dlmopen \- +open and close a shared object +.SH LIBRARY +Dynamic linking library +.RI ( libdl ", " \-ldl ) +.SH SYNOPSIS +.nf +.B #include <dlfcn.h> +.P +.BI "void *dlopen(const char *" filename ", int " flags ); +.BI "int dlclose(void *" handle ); +.P +.B #define _GNU_SOURCE +.br +.B #include <dlfcn.h> +.P +.BI "void *dlmopen(Lmid_t " lmid ", const char *" filename ", int " flags ); +.fi +.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 (). +.P +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 \[bu] 3 +(ELF only) If the calling object +(i.e., the shared library or executable from which +.BR dlopen () +is called) +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 \[bu] +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 \[bu] +(ELF only) If the calling object +contains a DT_RUNPATH tag, then the directories listed in that tag +are searched. +.IP \[bu] +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 \[bu] +The directories +.I /lib +and +.I /usr/lib +are searched (in that order). +.P +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.) +.P +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. +.P +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 and global 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. +.P +If +.I filename +is NULL, then the returned handle is for the main program. +When given to +.BR dlsym (3), +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 . +.P +Symbol references in the shared object are resolved using (in order): +symbols in the link map of objects loaded for the main program and its +dependencies; +symbols in shared objects (and their dependencies) +that were previously opened with +.BR dlopen () +using the +.B RTLD_GLOBAL +flag; +and definitions in the shared object itself +(and any dependencies that were loaded for that object). +.P +Any global symbols in the executable that were placed into +its dynamic symbol table by +.BR ld (1) +can also be used to resolve references in a dynamically loaded shared object. +Symbols may be placed in the dynamic symbol table +either because the executable was linked with the flag "\-rdynamic" +(or, synonymously, "\-\-export\-dynamic"), which causes all of +the executable's global symbols to be placed in the dynamic symbol table, +or because +.BR ld (1) +noted a dependency on a symbol in another object during static linking. +.P +If the same shared object is opened 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. +Constructors (see below) are called only when the object is actually loaded +into memory (i.e., when the reference count increases to 1). +.P +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 . +Similarly, an object that was previously opened with +.B RTLD_LOCAL +can be promoted to +.B RTLD_GLOBAL +in a subsequent +.BR dlopen (). +.P +If +.BR dlopen () +fails for any reason, it returns NULL. +.\" +.SS dlmopen() +This function performs the same task as +.BR dlopen ()\[em]the +.I filename +and +.I flags +arguments, as well as the return value, are the same, +except for the differences noted below. +.P +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. +.P +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. +.P +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 . +.P +If the object's reference count drops to zero +and no symbols in this object are required by other objects, +then the object is unloaded +after first calling any destructors defined for the object. +(Symbols in this object might be required in another object +because this object was opened with the +.B RTLD_GLOBAL +flag and one of its symbols satisfied a relocation in another object.) +.P +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. +.P +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 object. +On error +(file could not be found, was not readable, had the wrong format, +or caused errors during loading), +these functions return NULL. +.P +On success, +.BR dlclose () +returns 0; on error, it returns a nonzero value. +.P +Errors from these functions can be diagnosed using +.BR dlerror (3). +.SH ATTRIBUTES +For an explanation of the terms used in this section, see +.BR attributes (7). +.TS +allbox; +lbx lb lb +l l l. +Interface Attribute Value +T{ +.na +.nh +.BR dlopen (), +.BR dlmopen (), +.BR dlclose () +T} Thread safety MT-Safe +.TE +.SH STANDARDS +.TP +.BR dlopen () +.TQ +.BR dlclose () +POSIX.1-2008. +.TP +.BR dlmopen () +.TQ +.B RTLD_NOLOAD +.TQ +.B RTLD_NODELETE +GNU. +.TP +.B RTLD_DEEPBIND +Solaris. +.SH HISTORY +.TP +.BR dlopen () +.TQ +.BR dlclose () +glibc 2.0. +POSIX.1-2001. +.TP +.BR dlmopen () +glibc 2.3.4. +.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. +.P +The +.BR dlmopen () +function permits object-load isolation\[em]the 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. +.P +The +.BR dlmopen () +function also can be used to provide better isolation than the +.B RTLD_LOCAL +flag. +In particular, shared objects loaded with +.B RTLD_LOCAL +may be promoted to +.B RTLD_GLOBAL +if they are dependencies of another shared object loaded with +.BR RTLD_GLOBAL . +Thus, +.B 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. +.P +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. +.P +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 +.B gcc +info pages (under "Function attributes") +.\" info gcc "C Extensions" "Function attributes" +for further information. +.P +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. +.P +Use of +.B _init +and +.B _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)); +.\" +.P +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 +.B RTLD_GLOBAL +flag when calling +.BR dlmopen () +.\" dlerror(): "invalid mode" +generates an error. +Furthermore, specifying +.B RTLD_GLOBAL +when calling +.BR dlopen () +results in a program crash +.RB ( SIGSEGV ) +.\" https://sourceware.org/bugzilla/show_bug.cgi?id=18684 +if the call is made from any object loaded in a +namespace other than the initial namespace. +.SH EXAMPLES +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: +.P +.in +4n +.EX +$ \fBcc dlopen_demo.c \-ldl\fP +$ \fB./a.out\fP +\-0.416147 +.EE +.in +.SS Program source +\& +.\" SRC BEGIN (dlopen.c) +.EX +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.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 \[aq]void *\[aq], as done above, produces undefined results. + POSIX.1\-2001 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 1 to POSIX.1\-2008 improved matters + by requiring that conforming implementations support casting + \[aq]void *\[aq] to a function pointer. Nevertheless, some compilers + (e.g., gcc with the \[aq]\-pedantic\[aq] 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 +.\" SRC END +.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) +.P +gcc info pages, ld info pages |