mirror of https://github.com/mkerrisk/man-pages
486 lines
14 KiB
Groff
486 lines
14 KiB
Groff
.\" -*- nroff -*-
|
|
.\" 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 Michael Kerrisk (mtk.manpages@gmail.com).
|
|
.\"
|
|
.\" 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 <mtk.manpages@gmail.com> 2003-05-16.
|
|
.\" Modified by Walter Harms: dladdr, dlvsym
|
|
.\"
|
|
.TH DLOPEN 3 2008-06-14 "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
|
|
.B "char *dlerror(void);"
|
|
.sp
|
|
.BI "void *dlsym(void *" handle ", const char *" symbol );
|
|
.sp
|
|
.BI "int dlclose(void *" handle );
|
|
.sp
|
|
Link with \fI\-ldl\fP.
|
|
.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
|
|
.BR dlerror ()
|
|
returns a human readable string describing the most recent error
|
|
that occurred from
|
|
.BR dlopen (),
|
|
.BR dlsym ()
|
|
or
|
|
.BR 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
|
|
.BR 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 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 the environment variable
|
|
.B 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-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 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
|
|
One of the following two values must be included in
|
|
.IR flag :
|
|
.TP
|
|
.B RTLD_LAZY
|
|
Perform lazy binding.
|
|
Only resolve symbols as the code that references them is executed.
|
|
If the symbol is never referenced, then it is never resolved.
|
|
(Lazy binding is only performed for function references;
|
|
references to variables are always immediately bound when
|
|
the library is loaded.)
|
|
.TP
|
|
.B RTLD_NOW
|
|
If this value 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
|
|
.BR dlopen ()
|
|
returns.
|
|
If this cannot be done, an error is returned.
|
|
.PP
|
|
Zero of more of the following values may also be ORed in
|
|
.IR flag :
|
|
.TP
|
|
.B RTLD_GLOBAL
|
|
The symbols defined by this library will be
|
|
made available for symbol resolution of subsequently loaded libraries.
|
|
.TP
|
|
.B RTLD_LOCAL
|
|
This is the converse of
|
|
.BR RTLD_GLOBAL ,
|
|
and the default if neither flag is specified.
|
|
Symbols defined in this library are not made available to resolve
|
|
references in subsequently loaded libraries.
|
|
.TP
|
|
.BR RTLD_NODELETE " (since glibc 2.2)"
|
|
Do not unload the library during
|
|
.BR dlclose ().
|
|
Consequently, the library's static variables are not reinitialized
|
|
if the library is reloaded with
|
|
.BR dlopen ()
|
|
at a later time.
|
|
This flag is not specified in POSIX.1-2001.
|
|
.\" (But it is present on Solaris.)
|
|
.TP
|
|
.BR RTLD_NOLOAD " (since glibc 2.2)"
|
|
Don't load the library.
|
|
This can be used to test if the library is already resident
|
|
.RB ( dlopen ()
|
|
returns NULL if it is not, or the library's handle if it is resident).
|
|
This flag can also be used to promote the flags on a library
|
|
that is already loaded.
|
|
For example, a library that was previously loaded with
|
|
.B RTLD_LOCAL
|
|
can be re-opened with
|
|
.BR RTLD_NOLOAD\ |\ RTLD_GLOBAL .
|
|
This flag is not specified in POSIX.1-2001.
|
|
.\" (But it is present on Solaris.)
|
|
.\"
|
|
.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
|
|
library ahead of the global scope.
|
|
This means that a self-contained library will use
|
|
its own symbols in preference to global symbols with the same name
|
|
contained in libraries that have already been loaded.
|
|
This flag is not specified in POSIX.1-2001.
|
|
.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
|
|
.BR 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
|
|
.BR dlclose ()
|
|
has been called on it as many times as
|
|
.BR dlopen ()
|
|
has succeeded on it.
|
|
The
|
|
.BR _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
|
|
.BR dlopen ()
|
|
fails for any reason, it returns NULL.
|
|
.SS "dlsym()"
|
|
The function
|
|
.BR dlsym ()
|
|
takes a "handle" of a dynamic library returned by
|
|
.BR dlopen ()
|
|
and the
|
|
null-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
|
|
.BR dlopen ()
|
|
when that library was loaded,
|
|
.BR dlsym ()
|
|
returns NULL.
|
|
(The search performed by
|
|
.BR 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
|
|
.BR dlsym ()
|
|
need not indicate an error), the correct way to test for an error
|
|
is to call
|
|
.BR dlerror ()
|
|
to clear any old error conditions, then call
|
|
.BR dlsym (),
|
|
and then call
|
|
.BR 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
|
|
.BR 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
|
|
.BR 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
|
|
.BR 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 using the
|
|
.BR gcc (1)
|
|
.I \-nostartfiles
|
|
command-line option.
|
|
.LP
|
|
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));
|
|
.LP
|
|
Instead, libraries should export routines using the
|
|
.B __attribute__((constructor))
|
|
and
|
|
.B __attribute__((destructor))
|
|
function attributes.
|
|
See the gcc info pages for information on these.
|
|
Constructor routines are executed before
|
|
.BR dlopen ()
|
|
returns, and destructor routines are executed before
|
|
.BR dlclose ()
|
|
returns.
|
|
.SS Glibc extensions: dladdr() and dlvsym()
|
|
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
|
|
.BR dladdr ()
|
|
takes a function pointer and tries to resolve name
|
|
and file where it is located.
|
|
Information is stored in the
|
|
.I Dl_info
|
|
structure:
|
|
.sp
|
|
.in +4n
|
|
.nf
|
|
typedef struct {
|
|
const char *dli_fname; /* Pathname of shared object that
|
|
contains address */
|
|
void *dli_fbase; /* Address at which shared object
|
|
is loaded */
|
|
const char *dli_sname; /* Name of nearest symbol with address
|
|
lower than \fIaddr\fP */
|
|
void *dli_saddr; /* Exact address of symbol named
|
|
in \fIdli_sname\fP */
|
|
} Dl_info;
|
|
.fi
|
|
.in
|
|
.PP
|
|
If no symbol matching
|
|
.I addr
|
|
could be found, then
|
|
.I dli_sname
|
|
and
|
|
.I dli_saddr
|
|
are set to NULL.
|
|
.PP
|
|
.BR dladdr ()
|
|
returns 0 on error, and non-zero on success.
|
|
.PP
|
|
The function
|
|
.BR dlvsym (),
|
|
provided by glibc since version 2.1,
|
|
does the same as
|
|
.BR dlsym ()
|
|
but takes a version string as an additional argument.
|
|
.SH "CONFORMING TO"
|
|
POSIX.1-2001 describes
|
|
.BR dlclose (),
|
|
.BR dlerror (),
|
|
.BR dlopen (),
|
|
and
|
|
.BR dlsym ().
|
|
.SH NOTES
|
|
The symbols
|
|
.B RTLD_DEFAULT
|
|
and
|
|
.B RTLD_NEXT
|
|
are defined by
|
|
.I <dlfcn.h>
|
|
only when
|
|
.B _GNU_SOURCE
|
|
was defined before including it.
|
|
.\" .LP
|
|
.\" The string returned by
|
|
.\" .BR dlerror ()
|
|
.\" should not be modified.
|
|
.\" Some systems give the prototype as
|
|
.\" .sp
|
|
.\" .in +5
|
|
.\" .B "const char *dlerror(void);"
|
|
.\" .in
|
|
|
|
Since glibc 2.2.3,
|
|
.BR atexit (3)
|
|
can be used to register an exit handler that is automatically
|
|
called when a library is unloaded.
|
|
.SS History
|
|
The dlopen interface standard comes from SunOS.
|
|
That system also has
|
|
.BR dladdr (),
|
|
but not
|
|
.BR dlvsym ().
|
|
.SH EXAMPLE
|
|
Load the math library, and print the cosine of 2.0:
|
|
.nf
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.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(EXIT_FAILURE);
|
|
}
|
|
|
|
dlerror(); /* Clear any existing error */
|
|
|
|
/* Writing: cosine = (double (*)(double)) dlsym(handle, "cos");
|
|
would seem more natural, but the C99 standard leaves
|
|
casting from "void *" to a function pointer undefined.
|
|
The assignment used below is the POSIX.1\-2003 (Technical
|
|
Corrigendum 1) workaround; see the Rationale for the
|
|
POSIX specification of dlsym(). */
|
|
|
|
*(void **) (&cosine) = dlsym(handle, "cos");
|
|
.\" But in fact "gcc -O2 -Wall" will complain about the preceding cast.
|
|
|
|
if ((error = dlerror()) != NULL) {
|
|
fprintf(stderr, "%s\en", error);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
printf("%f\en", (*cosine)(2.0));
|
|
dlclose(handle);
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
.fi
|
|
.PP
|
|
If this program were in a file named "foo.c", you would build the program
|
|
with the following command:
|
|
.in +4n
|
|
.LP
|
|
gcc \-rdynamic \-o foo foo.c \-ldl
|
|
.in
|
|
.PP
|
|
Libraries exporting
|
|
.BR _init ()
|
|
and
|
|
.BR _fini ()
|
|
will want to be compiled as
|
|
follows, using \fIbar.c\fP as the example name:
|
|
.in +4n
|
|
.LP
|
|
gcc \-shared \-nostartfiles \-o bar bar.c
|
|
.in
|
|
.SH "SEE ALSO"
|
|
.BR ld (1),
|
|
.BR ldd (1),
|
|
.BR dl_iterate_phdr (3),
|
|
.BR feature_test_macros (7),
|
|
.BR ld.so (8),
|
|
.BR ldconfig (8),
|
|
ld.so info pages, gcc info pages, ld info pages
|