Obtaining New Symbols
A process can obtain the address of a specific symbol
using
dlsym
(3C). This function takes a
handle and a symbol
name, and returns the address of the symbol to
the caller. The handle directs the search for the symbol in the
following manner.
-
A handle can be returned from a
dlopen
(3C) of a named object. The handle enables symbols to be obtained from the named object and the objects that define its dependency tree. A handle returned using the modeRTLD_FIRST
, enables symbols to be obtained only from the named object. -
A handle can be returned from a
dlopen
(3C) of a path name whose value is0
. The handle enables symbols to be obtained from the initiating object of the associated link-map and the objects that define its dependency tree. Typically, the initiating object is the executable. This handle also enables symbols to be obtained from any object obtained by adlopen
(3C) with theRTLD_GLOBAL
mode, on the associated link-map. A handle returned using the modeRTLD_FIRST
, enables symbols to be obtained only from the initiating object of the associated link-map. -
The special handle
RTLD_DEFAULT
, andRTLD_PROBE
enable symbols to be obtained from the initiating object of the associated link-map and objects that define its dependency tree. This handle also enables symbols to be obtained from any object obtained by adlopen
(3C) that belongs to the same group as the caller. Use ofRTLD_DEFAULT
, orRTLD_PROBE
follows the same model as used to resolve a symbolic relocation from the calling object. -
The special handle
RTLD_NEXT
enables symbols to be obtained from the next associated object on the callers link-map list.
In the following example, which is probably the most common, an
application adds additional objects to its address space. The
application then uses
dlsym
(3C) to locate function or data symbols. The application then uses these symbols to call upon services that
are provided in these new objects. The file
main.c
contains the following
code.
#include <stdio.h> #include <dlfcn.h> int main() { void *handle; int *dptr, (*fptr)(); if ((handle = dlopen("foo.so.1", RTLD_LAZY)) == NULL) { (void) printf("dlopen: %s\n", dlerror()); return (1); } if (((fptr = (int (*)())dlsym(handle, "foo")) == NULL) || ((dptr = (int *)dlsym(handle, "bar")) == NULL)) { (void) printf("dlsym: %s\n", dlerror()); return (1); } return ((*fptr)(*dptr)); }
The symbols foo
and bar
are
searched for in the file foo.so.1
, followed by
any dependencies that are associated with this file. The function
foo
is then called with the single
argument bar
as part of the
return
() statement.
The application prog
, built using the previous
file main.c
, contains the following
dependencies.
$ ldd prog
libc.so.1 => /lib/libc.so.1
If the file name specified in the
dlopen
(3C) had the value 0, the symbols
foo
and bar
are
searched for in prog
, followed by
/lib/libc.so.1
.
The handle indicates the root at which to start a symbol search. From this root, the search mechanism follows the same model as described in Relocation Symbol Lookup.
If the required symbol cannot be located,
dlsym
(3C) returns a NULL
value. In this case,
dlerror
(3C) can be used to indicate the true
reason for the failure. In the following example, the application
prog
is unable to locate the symbol
bar
.
$ prog
dlsym: ld.so.1: main: fatal: bar: can't find symbol