diff options
Diffstat (limited to 'man3/dlopen.3')
-rw-r--r-- | man3/dlopen.3 | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/man3/dlopen.3 b/man3/dlopen.3 new file mode 100644 index 000000000..308f9c972 --- /dev/null +++ b/man3/dlopen.3 @@ -0,0 +1,378 @@ +.\" -*- nroff -*- +.\" Copyright 1995 Yggdrasil Computing, Incorporated. +.\" written by Adam J. Richter (adam@yggdrasil.com), +.\" with typesetting help from Daniel Quinlan (quinlan@yggdrasil.com). +.\" Additional material copyright 2003, Michael Kerrisk +.\" +.\" 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, write to the Free +.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +.\" USA. +.\" +.\" 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 <mtk16@ext.canterbury.ac.nz> 2003-05-16. +.\" Modified by Walter Harms: dladdr, dlvsym +.\" +.TH DLOPEN 3 2003-11-17 "Linux" "Linux Programmer's Manual" +.SH NAME +dladdr, dlclose, dlerror, dlopen, dlsym, dlvsym \- programming interface to +dynamic linking loader +.SH SYNOPSIS +.B #include <dlfcn.h> +.sp +.BI "void *dlopen(const char *" filename ", int " flag ); +.sp +.BI "char *dlerror(void);" +.sp +.BI "void *dlsym(void *" handle ", const char *" symbol ); +.sp +.BI "int dlclose(void *" handle ); +.SH DESCRIPTION +The four functions +.BR dlopen() , +.BR dlsym() , +.BR dlclose() , +.BR dlerror() +implement the interface to the dynamic linking loader. +.SS "dlerror" +The function +.B dlerror() +returns a human readable string describing the most recent error +that occurred from any of the dl routines (dlopen, dlsym or dlclose) +since the last call to +.BR dlerror() . +It returns NULL if no errors have occurred since initialization or since +it was last called. +.SS "dlopen" +The function +.B dlopen() +loads the dynamic library file named by the null-terminated +string +.I filename +and returns an opaque "handle" for the dynamic library. +If +.I filename +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 library as follows +(see +.BR ld.so (8) +for further details): +.IP o +(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 the environment variable +.BR LD_LIBRARY_PATH +is defined to contain a colon-separated list of directories, +then these are searched. +(As a security measure this variable is ignored for set-UID and +set-GID 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 +.BR /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 +.B /lib +and +.B /usr/lib +are searched (in that order). +.PP +If the library has dependencies on other shared libraries, +then these are also automatically loaded by the dynamic linker +using the same rules. (This process may occur recursively, +if those libraries in turn have dependencies, and so on.) +.PP +The value of +.I flag +can be either +.B RTLD_LAZY +or +.BR RTLD_NOW . +When +.B RTLD_NOW +is specified, or the environment variable +.B LD_BIND_NOW +is set to a non-empty string, +all undefined symbols in the library are resolved before +.B dlopen() +returns. If this cannot be done, an error is returned. +Otherwise binding is lazy: symbol values are first resolved +when needed. +.PP +Optionally, +.B RTLD_GLOBAL +may be or'ed into +.IR flag , +in which case the external symbols defined in the library will be +made available for symbol resolution of subsequently loaded libraries. +(The converse of +.B RTLD_GLOBAL +is +.BR RTLD_LOCAL . +.\" that indicates that the symbols in this library should not be made +.\" available for resolution of symbols of subsequently loaded libraries. +This is the default.) +.PP +If +.I filename +is a NULL pointer, 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 libraries loaded at program startup, +and then all shared libraries loaded by +.BR dlopen() +with the flag +.B RTLD_GLOBAL. +.PP +External references in the library are resolved using the libraries +in that library's dependency list and any other libraries 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 library. +.PP +If the same library is loaded again with +.BR dlopen() , +the same file handle is returned. The dl library maintains reference +counts for library handles, so a dynamic library is not +deallocated until +.B dlclose() +has been called on it as many times as +.B dlopen() +has succeeded on it. The +.B _init +routine, if present, is only called once. But a subsequent call with +.B RTLD_NOW +may force symbol resolution for a library earlier loaded with +.BR RTLD_LAZY . +.PP +If +.B dlopen() +fails for any reason, it returns NULL. +.SS "dlsym" +The function +.B dlsym() +takes a "handle" of a dynamic library returned by dlopen and the +NUL-terminated symbol name, returning the address where that symbol is +loaded into memory. If the symbol is not found, in the specified +library or any of the libraries that were automatically loaded by +.B dlopen() +when that library was loaded, +.B dlsym() +returns NULL. +(The search performed by +.B dlsym() +is breadth first through the dependency tree of these libraries.) +Since the value of the symbol could actually be NULL (so that a +NULL return from +.B dlsym() +need not indicate an error), the correct way to test for an error +is to call +.B dlerror() +to clear any old error conditions, then call +.BR dlsym() , +and then call +.B dlerror() +again, saving its return value into a variable, and check whether +this saved value is not NULL. +.PP +There are two special pseudo-handles, +.B RTLD_DEFAULT +and +.BR RTLD_NEXT . +The former will find the first occurrence of the desired symbol +using the default library search order. The latter +will find the next occurrence of a function in the search order +after the current library. This allows one to provide a wrapper +around a function in another shared library. +.SS "dlclose" +The function +.B dlclose() +decrements the reference count on the dynamic library handle +.IR handle . +If the reference count drops to zero and no other loaded libraries use +symbols in it, then the dynamic library is unloaded. +.LP +The function +.B dlclose() +returns 0 on success, and non-zero on error. +.SS "The obsolete symbols _init and _fini" +The linker recognizes special symbols +.B _init +and +.BR _fini . +If a dynamic library exports a routine named +.BR _init , +then that code is executed after the loading, before +.B dlopen() +returns. If the dynamic library exports a routine named +.BR _fini , +then that routine is called just before the library is unloaded. +In case you need to avoid linking against the system startup files, +this can be done by giving gcc the "-nostartfiles" parameter on +the command line. +.LP +Using these routines, or the gcc +.B \-nostartupfiles +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)); +.LP +Instead, libraries should export routines using the +.BR __attribute__((constructor)) +and +.BR __attribute__((destructor)) +function attributes. See the gcc info pages for information on these. +Constructor routines are executed before +.B dlopen +returns, and destructor routines are executed before +.B dlclose +returns. +.SH "GNU EXTENSIONS" +Glibc adds two functions not described by POSIX, with prototypes +.sp +.nf +.B #define GNU_SOURCE +.B #include <dlfcn.h> +.sp +.BI "int dladdr(void *" addr ", Dl_info *" info ); +.sp +.BI "void *dlvsym(void *" handle ", char *" symbol ", char *" version ); +.fi +.PP +The function +.B dladdr() +takes a function pointer and tries to resolve name +and file where it is located. Information is stored in the +Dl_info structure: +.sp +.nf +typedef struct { + const char *dli_fname;/* File name of defining object */ + void *dli_fbase; /* Load address of that object */ + const char *dli_sname;/* Name of nearest lower symbol */ + void *dli_saddr; /* Exact value of nearest symbol */ +} Dl_info; +.fi +.sp +.B dladdr() +returns 0 on error, and non-zero on success. +.PP +The function +.B dlvsym() +does the same as +.B dlsym() +but takes a version string as additional argument. + +.SH EXAMPLE +.B Load the math library, and print the cosine of 2.0: +.RS +.nf +.if t .ft CW +#include <stdio.h> +#include <dlfcn.h> + +int main(int argc, char **argv) { + void *handle; + double (*cosine)(double); + char *error; + + handle = dlopen ("libm.so", RTLD_LAZY); + if (!handle) { + fprintf (stderr, "%s\en", dlerror()); + exit(1); + } + + dlerror(); /* Clear any existing error */ +.\" This is the (somewhat ugly) SUSv3 TC1 fix for +.\" the dlsym() typecasting problem + *(void **) (&cosine) = dlsym(handle, "cos"); + if ((error = dlerror()) != NULL) { + fprintf (stderr, "%s\en", error); + exit(1); + } + + printf ("%f\en", (*cosine)(2.0)); + dlclose(handle); + return 0; +} +.if t .ft P +.fi +.RE +.PP +If this program were in a file named "foo.c", you would build the program +with the following command: +.RS +.LP +gcc -rdynamic -o foo foo.c -ldl +.RE +.PP +Libraries exporting _init() and _fini() will want to be compiled as +follows, using bar.c as the example name: +.RS +.LP +gcc -shared -nostartfiles -o bar bar.c +.RE +.SH NOTES +The symbols RTLD_DEFAULT and RTLD_NEXT are defined by +.I <dlfcn.h> +only when _GNU_SOURCE was defined before including it. +.\" .LP +.\" The string returned by +.\" .B dlerror() +.\" should not be modified. Some systems give the prototype as +.\" .sp +.\" .in +5 +.\" .B "const char *dlerror(void);" +.\" .in +.SH HISTORY +The dlopen interface standard comes from SunOS. That system also has +dladdr, but not dlvsym. +.SH "CONFORMING TO" +POSIX 1003.1-2003 describes dlclose, dlerror, dlopen, dlsym. +.SH "SEE ALSO" +.BR ld (1), +.BR ldd (1), +.BR dl_iterate_phdr (3), +.BR ld.so (8), +.BR ldconfig (8), +ld.so info pages, gcc info pages, ld info pages |