This section describes the dl* family of shared library
management routines. All these routines are available in IPF/PA-64 mode.
Support for the following routines is available in PA-32 mode:
dlopen
dlclose
dlsym
dlerror
The dlopen Routine
The dlopen routine opens a shared library.
Syntax
void *dlopen(const char *file, int mode);
void *dlopene(const char *file, int mode, struct dlopen_opts *opts);
Parameters
Parameter |
Definition |
|
file |
Used to construct a pathname to the shared library file.
If files contain a slash character (/ ),
dlopen uses the file argument itself as the pathname. If
not, dlopen searches a series of directories for file.
- Any directories specified by the dynamic search
path, which is set by calling
dlsetlibpath
Any directories specified by the environment
variable LD_LIBRARY_PATH .
Any directories specified by the variable
SHLIB_PATH .
Any directories specified by the RPATH
of the calling load module.
The default library search path.
The current working directory.
|
|
flags |
Mode |
Definition |
|
RTLD_LAZY
|
Under this mode, only references to data symbols are relocated when
the library is loaded. References to functions are not relocated until
a given function is invoked for the first time. This mode results
in better performance, because a process may not reference all of the functions
in any given shared object. |
|
RTLD_NOW
|
Under this mode, all necessary relocations are performed when the
library is first loaded. This can cause some wasted effort if relocations
are performed for functions that are never referenced. But it is useful for
applications that need to know as soon as an object is loaded that all
symbols referenced during execution are available. |
|
RTLD_GLOBAL
|
The shared library's symbols are made available for the relocation
processing of any other object. In addition, symbol lookup using dlopen(0,
mode) and an associated dlsym() allows objects loaded
with RTLD_GLOBAL to be searched. |
|
RTLD_LOCAL
|
The shared library's symbols are made available for relocation processing
only to objects loaded in the same dlopen invocation.
If neither RTLD_GLOBAL nor RTLD_LOCAL
are specified, the default is RTLD_LOCAL . |
Return Values
A successful dlopen call returns to the process a handle
which the process can use on subsequent calls to dlsym and
dlclose . This value must not be interpreted in any way
by the process.
The dlopen routine returns NULL
under the following conditions:
file
cannot be found.
file
cannot be opened for reading.
file
is not a shared object.
An error occurs during the process of loading
file or relocating its symbolic references.
More detailed diagnostic information is available through dlerror .
Description
The dlopen routine is one of a
family of routines that give the user direct access to the dynamic linking
facilities. The dlopen routine makes a shared library specified by a
file available to a running process. A shared library may specify
other objects that it "needs" in order to execute properly.
These dependencies are specified by DT_NEEDED entries in
the .dynamic section of the original shared library. Each needed shared
library may, in turn, specify other needed shared libraries. All such
shared libraries are loaded along with the original shared library as
a result of the call to dlopen .
If the value of file is 0, dlopen provides
a handle on a "global symbol shared library." This
shared library provides access to the symbols from an ordered set of shared
libraries consisting of the original a.out , all of the shared
libraries that were loaded at program startup along with the a.out ,
and all shared libraries loaded using a dlopen operation
along with the RTLD_GLOBAL flag. As the latter set of shared
libraries can change during execution, the set identified by handle
can also change dynamically.
Only a single copy of a shared library file is brought into the
address space, even if dlopen is invoked multiple times in
reference to the file, and even if different pathnames are used to reference
the file.
When a shared library is brought into the address space of a process,
it can contain references to symbols whose addresses are not known until
the shared library is loaded. These references must be relocated before
the symbols can be accessed. The mode parameter governs the relocations
and may have the following values (defined in Parameters):
RTLD_LAZY and RTLD_NOW .
Any shared library loaded by dlopen that requires relocations
against global symbols can reference the following:
Symbols in the original a.out .
Any shared libraries loaded at program startup,
from the shared library itself.
Any shared library included in the same dlopen
invocation.
Any shared libraries that were loaded in any
dlopen invocation that specified the RTLD_GLOBAL
flag.
To determine the scope of symbols that are made available for relocation
processing of objects loaded in a dlopen invocation, the
mode parameter can be bitwise alternated with one of the following values:
RTLD_GROUP : Under this
mode, the specified object and its dependencies behave as if they were
built with -B group (see ld(1)). Only symbols
from objects loaded in the same dlopen invocation are made
available for relocation. This ensures that all relocations are satisfied
using symbol definitions from the same dlopen invocation.
RTLD_WORLD : Under this
mode, only symbols from global objects and from the object itself are
available for relocation processing. It does not use symbol definitions
from other objects loaded as part of the dlopen invocation.
This flag has no effect on objects built with -B group (see
ld(1)).
RTLD_PARENT : Under
this mode, symbols from the object that invoked dlopen are
also made available for relocation.
The default modes for dlopen are RTLD_WORLD|RTLD_GROUP .
These flags are alternated together when the same object is loaded with different
modes.
The values RTLD_GROUP, RTLD_WORLD, and RTLD_PARENT are
not available for PA32 systems.
The following flags do not affect relocation processing, but provide
the following features:
RTLD_NODELETE : Under
this mode, the specified object and its dependencies behave as if they
were built with -B nodelete . An explicit unload using dlclose
or shl_load returns success silently without detaching the
shared library for the process. Subsequently, the shared library handle
is valid only for shl_findsym . It stays invalid for dlsym,
dlclose, and shl_unload until the next explicit load
using shl_load or dlclose .
RTLD_NOLOAD : Under
this mode, the specified object is not loaded into the process's address
space, but a valid handle is returned if the object already exists in
the process address space. If the specified object does not already exist,
then an error is returned. RTLD_NOLOAD can be used to query
the presence, or for overriding the modes of an existing object.
If a file is specified in multiple dlopen invocations,
mode is interpreted at each invocation. Note, however, that once RTLD_NOW
has been specified, the linker operation completes all relocations, rendering
any further RTLD_NOW operations redundant and any further
RTLD_LAZY operations irrelevant. Similarly note that once
you specify RTLD_GLOBAL , the shared library maintains the
RTLD_GLOBAL status regardless of any previous or future specification
of RTLD_LOCAL , as long as the shared library remains in the
address space [see dlclose(3C)].
Symbols introduced into a program through calls to dlopen
may be used in relocation activities. Symbols so introduced may duplicate
symbols already defined by the program or previous dlopen
operations. To resolve the ambiguities such a situation may present,
the resolution of a symbol reference to a symbol definition is based on
a symbol resolution order. Two such resolution orders are defined: load
and dependency ordering.
Load order establishes an ordering among symbol
definitions using the temporal order in which the shared libraries containing
the definitions were loaded, such that the definition first loaded has
priority over definitions added later. Load ordering is used in relocation
processing.
Dependency ordering uses a "breadth-first"
order starting with a given shared library, then all of its dependencies,
then any dependents of those, iterating until all dependencies are satisfied.
The dlsym function uses dependency ordering, except
when the global symbol shared library is obtained via a dlopen
operation on file with a value 0. The dlsym function
uses load ordering on the global symbol shared library.
When a dlopen operation first makes it accessible,
a shared library and its dependent shared libraries are added in dependency
order. Once all shared libraries are added, relocations are performed
using load order. Note that if a shared library and its dependencies have
been loaded by a previous dlopen invocation or on startup,
the load and dependency order may yield different resolutions.
The symbols introduced by dlopen operations and available
through dlsym are those which are "exported" as
symbols of global scope by the shared library. For shared libraries, such
symbols are typically those that were specified in (for example) C source
code as having extern linkage. In PA-32 mode, for a.out
files, only a subset of externally visible symbols are typically exported:
specifically those referenced by the shared libraries with which the a.out
is linked. The exact set of exported symbols for any shared library or
the a.out can be controlled using the linker [see ld(1)].
The dlopene routine is an extension
to dlopen , which allows the caller to specify explicitly
the placement of a shared library's text and data segment when the library
is dynamically loaded.
The dlopen_opts structure has the following members:
struct dlopen_opts {
long flags;
char* text_addr;
char* data_addr;
};
Flags contain the load option, defined by logical OR of the following
values:
RTLD_EXT_TEXT_ADDR
indicates that an explicit base address for the shared library text segment
is provided.
RTLD_EXT_DATA_ADDR
indicates that an explicit base address for the shared library private
data segment is provided.
If the RTLD_EXT_DATA_NO_ZERO_FILL flag is set, dlopene
does not zero fill the bss part of the data segment. This may improve
load time for libraries with large bss sections. This flag is only valid
with RTLD_EXT_DATA_ADDR .
The dynamic load accesses only the address fields that are specified
by the "Flags" fields.
The text_addr contains
the explicit base address for the shared library's text segment.
The data_addr contains
the explicit base address for the shared library's data segment.
Both the text_addr and data_addr must
be aligned at a 16-byte boundary.
The caller can invoke dlgetfileinfo to obtain the information
needed to allocate memory for the load segments.
The caller of dlopene is responsible for allocating
memory with the following permission:
NoteThe environment variable LD_LIBRARY_PATH must contain
a colon-separated list of directories, in the same format as the PATH
variable [see sh(1)]. In PA-64 and IPF mode LD_LIBRARY_PATH
is ignored if the process' real user id is different from its effective
user id or its real group id is different from its effective group id
[see exec(2)] or if the process has acquired any privileges
[see tfadmin(1M)]. In IPF/PA-64 mode, with the +compat option specified,
LD_LIBRARY_PATH and the +b embedded path are
ignored when searching for dependent libraries.
Example
The following example shows how to use dlopen to load
a shared library. The RTLD_GLOBAL flag enables global visibility
to symbols in lib1.so . The RTLD_LAZY flag indicates
that only references to data symbols are to be relocated and all function
symbol references are to be delayed until their first invocation.
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char **argv)
{
void* handle; handle = dlopen("./lib1.so", RTLD_GLOBAL | RTLD_LAZY);
if (handle == NULL) {
printf("Cannot load library\n");
}
}
The following example illustrates the use of dlopene
to load a shared library with an explicit data segment address. For simplicity,
error checking has been omitted:
#include <dlfcn.h>
#include <sys/mman.h>
int main() {
struct dlfileinfo info;
void *handle;
struct dlopen_opts opts;
int status;
memset(&info, 0, sizeof(info));
memset(&opts, 0, sizeof(opts));
/* Get file info */
status = dlgetfileinfo("libfoo.so", sizeof(info), &info);
opts.flags = RTLD_EXT_DATA_ADDR;
/* allocate memory for the data segment */
opts.data_addr = (char*) mmap(0, info.data_size,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_ANONYMOUS,
-1, 0);
/* call dlopene */
handle = dlopene("libfoo.so", RTLD_NOW|RTLD_GLOBAL, &opts);
/* Insert user code to use library */
/* close library */
status = dlclose(handle);
/* free memory */
munmap(opts.data_addr, info.data_size);
}
The dlsetlibpath Routine
The dlsetlibpath routine sets the dynamic search path to locate shared libraries.
Synopsis
cc [flag ... ] file ... -ldl [library] ...
#include <dlfcn.h>
int dlsetlibpath(const char *libpath, int flags)
Description
The dlsetlibpath routine is one
of a family of routines that give the user direct access to the dynamic
linking facilities (using the -ldl option on the compiler
of ld command line). The dlsetlibpath routine sets the dynamic
search path used by dlopen, dlopene , and dlgetfileinfo
to locate shared libraries.
The libpath is the dynamic
search path. It is a list of one or more path names separated by colons
(:).
When searching for a library, the dynamic loader uses search paths
in the following default order:
- The dynamic search path specified in a call to
dlsetlibpath .
- The
LD_LIBRARY_PATH environment variable.
- The
SHLIB_PATH environment variable.
- The embedded path of the calling module (executable program or shared
library) for libraries names in calls to
dlopen , dlopene , or
dlgetfileinfo . For dependent libraries, the embedded path
of the library that named it as a dependent is used.
- The standard library path.
- The current working directory. (This is only for libraries named
in calls to
dlopen , dlopene , and dlgetfileinfo ,
not their dependent libraries.)
See dld.so(5) for additional information on search
paths and options that can change the order described above.
Any combination of these paths may be disabled by setting flags
to one or more of the following values alternated together:
RTLD_FLAG_DISABLE_DYNAMIC_PATH - If
this flag is set, the dynamic loader does not search the directories specified
in the dynamic search path.
RTLD_FLAG_DISABLE_LD_LIBRARY_PATH - If
this flag is set, the dynamic loader does not search the directories specified
in the LD_LIBRARY_PATH environment variable.
RTLD_FLAG_DISABLE_SHLIB_PATH - If
this flag is set, the dynamic loader does not search the directories specified
in the SHLIB_PATH environment variable.
RTLD_FLAG_DISABLE_EMBEDDED_PATH - If
this flag is set, the dynamic loader does not search the directories specified
in the embedded path.
RTLD_FLAG_DISABLE_STD_PATH - If this flag is set, the
dynamic loader does not search the standard library directory.
RTLD_FLAG_DISABLE_CWD_PATH - If
this flag is set, the dynamic loader does not search the current.
Mulitple search paths can be disabled by alternating individual flags:
flags = RTLD_FLAG_DISABLE_STD_PATH | RTLD_FLAG_DISABLE_CWD_PATH
A single search path can be enabled by setting flags to the complement
of the flag value that disables that search path:
flags = ~RTLD_FLAG_DISABLE_DYNAMIC_PATH
Examples
The following example illustrates the use of dlsetlibpath
to set the dynamic search path and disable other search paths. For simplicity,
error checking has been omitted.
#include <dlfcn.h>
int main() {
void *handle;
int status;
int flags;
/* Set dynamic search path and disable the embedded
* path and the standard library directory.
*/
flags = RTLD_FLAG_DISABLE_EMBEDDED_PATH |
RTLD_FLAG_DISABLE_STD_PATH;
status = dlsetlibpath("/opt/lib:/opt/usr/lib", flags);
/* Call dlopen to load a library using the dynamic
* search path.
*/
handle = dlopen("mylib.so"), RTLD_LAZY);
/* Remove the dynamic search path and reenable all
* disabled search paths.
*/
status = dlsetlibpath(NULL, 0);
}
Multithread Usage
This routine is thread-safe. Calls to dlsetlibpath
affect all subsequent calls to dlopen , dlopene , and
dlgetfileinfo on any thread.
Return Value
If successful, dlsetlibpath returns 0, otherwise a
non-0 value is returned. More detailed diagnostic information is available
through dlerror or dlerrno .
Errors
If dlsetlibpath fails, a subsequent call to dlerrno
returns one of the following values:
RTLD_ERR_NO_MEMORY - Cannot allocate dynamic memory.
RTLD_ERR_CANT_APPLY_RELOC - Failed to apply relocation while
resolving call to dlsetlibpath .
RTLD_ERR_SIGINHIBIT_FAILED - The siginhibit call failed
on entry to dlsetlibpath .
RTLD_ERR_SIGENABLE_FAILED - The sigenable call failed
on exit from dlsetlibpath .
RTLD_ERR_SETCANCELSTATE_FAILED - __thread_setcancelstate
failed on entry to or exit from dlsetlibpath .
RTLD_ERR_INV_DLSETLIBPATH_ARGUMENT - Invalid argument in call
to dlsetlibpath .
See also dlopen(3C), dlopene(3C), dlgetfileinfo(3C), dlerror(3C),
dlerrno(3C), dld.so(5).
The dlerrno Routine
The dlerrno routine returns a numeric error code that corresponds to the last error
that occurred during dynamic linking processing.
Synopsis
cc [flag ... ] file ... -ldl [library] ...
#include <dlfcn.h>
int *dlerrno(void);
Description
The dlerrno routine is one of a
family of routines that give the user direct access to the dynamic linking
facilities (using the -ldl option on the compiler or ld command line).
The dlerrno routine returns a numeric error code that corresponds to
the last error that occurred during dynamic linking processing. If no
dynamic linking errors have occurred since the last invocation of dlerrno ,
dlerrno returns RTLD_ERR_NO_ERR (-1) . Thus, invoking
dlerrno a second time, immediately following a prior invocation,
returns RTLD_ERR_NO_ERR (-1) .
For a complete list of the mnemonic error codes, see the dlerrno(3C)
manpage.
The dlgetfileinfo Routine
The dlgetfileinfo routine returns file information for a library prior to loading it.
Synopsis
cc [flag ... ] file ... -ldl [library] ...
#include <dlfcn.h>
uint64_t dlgetfileinfo(const char *file,
size_t info_size,
struct dlfileinfo *info);
Description
The dlgetfileinfo routine is one
of a family of routines that give the user direct access to the dynamic
linking facilities (using the -ldl option on the compiler or ld command
line). dlgetfileinfo returns file information for a library
prior to loading it. This information can be used to allocate load segments
before calling dlopene .
The file is used to construct a pathname
to the library. The dynamic loader searches for the library using the
standard search rules used by dlopen and dlopene .
If the library is found and is a valid shared library, dlgetfileinfo
returns information about the library through the info parameter.
The info_size is the size in bytes
of the info buffer.
The info is a pointer to a buffer
allocated by the user program. The dynamic loader fills this buffer
with file information.
A dlfileinfo structure has the following members:
struct dlfileinfo {
size_t text_size;
size_t data_size;
char *filename;
}
The text_size is the size in bytes
of a shared library's text segment.
The data_size is the size in bytes
of a shared library's data segment.
The filename is the path to the shared
library. This path may be passed to a subsequent dlopen or
dlopene call to avoid searching for the library a second
time. The caller of dlgetfileinfo must copy the value of
filename to insure that it is not corrupted.
Examples
The following example illustrates the use of dlgetfileinfo
to allocate memory for mapping a shared library's data segment. For simplicity,
error checking has been omitted.
#include <dlfcn.h>
#include <string.h>
/* allocate_data is a user-supplied routine that allocates a
* memory buffer of at least "data_size" bytes and returns
* a pointer to the buffer.
*/
extern char *allocate_data(size_t data_size);
int main() {
void *handle;
int status;
char *pathname;
struct dlfileinfo info;
struct dlopen_opts opts;
/* Locate library and get file information */
status = dlgetfileinfo("mylib.so", sizeof(info), &info);
if (status == 0) {
/* Make a copy of the library pathname returned by
* dlgetfileinfo().
*/
pathname = strdup(info.filename);
/* Allocate data segment */
opts.data_addr = allocate_data(info.data_size);
/* Not preallocating text segment */
opts.text_addr = 0;
/* Set dlopen() flags to indicate the data segment
* has been preallocated.
*/
opts.flags = RTLD_EXT_DATA_ADDR:
/* Call dlopene() to load the library using the path
* where dlgetfileinfo found the library and the
* preallocated memory buffer for mapping the library
* data segment.
*/
handle = dlopene(pathname, RTLD_LAZY, &opts);
/* Remove copy of library pathname */
free(pathname);
/* Insert code here to use library */
/* Close library */
status = dlclose(handle);
/* Insert code here to free storage allocated by
* allocate_data().
*/
}
}
Multithread Usage
The dlgetfileinfo routine is thread-safe.
Return Value
If successful, dlgetfileinfo returns 0, otherwise a
non-0 value is returned. More detailed diagnostic information is available
through dlerror or dlerrno .
Errors
If dlgetfileinfo fails, a subsequent call to dlerrno
returns an error. For a complete listing of those values, see the
dlgetfileinfo(3C) manpage.
The dlerror Routine
The dlerror routine gets diagnostic information.
Syntax
char *dlerror(void);
Description
The dlerror routine returns a null-terminated
character string (with no trailing newline character) that describes the
last error that occurred during dynamic linking processing. If no dynamic
linking errors have occurred since the last invocation of dlerror ,
it returns NULL. Thus, invoking dlerror a second time, immediately
following a prior invocation, results in NULL being returned.
NoteThe messages returned by dlerror may reside in a static
buffer that is overwritten on each call to dlerror . Application
code must not write to this buffer. Programs taht seek to preserve an
error message must make their own copies of that message.
Example
The following code sequence shows how to use dlerror
to get diagnostic information:
void* handle;
/* Try to load a non-existing library */
handle = dlopen("invalid.so", RTLD_GLOBAL | RTLD_LAZY);
if (handle == NULL) {
printf("%s\n", dlerror());
}
The dlsym Routine
The dlsym gets the address of a symbol in shared library.
Syntax
void *dlsym(void *handle, const char *name);
Parameters
Parameter |
Definition |
handle |
Either the value returned by a call to dlopen or one
of the special flags RTLD_NEXT , RTLD_SELF , and RTLD_DEFAULT .
In the former case, the corresponding shared library must not have been
closed using dlclose . |
name |
The symbol's name as a character string. |
Return Values
If handle does not refer to a valid shared library opened
by dlopen , or if the named symbol cannot be found within
any of the shared libraries associated with handle, dlsym
returns NULL. The dlerror routine provides more detailed
diagnostic information.
Description
The dlsym routine allows a process
to obtain the address of a symbol defined within a shared library previously
opened by dlopen .
The dlsym routine searches for the named symbol in
all shared libraries loaded automatically as a result of loading the shared
library referenced by handle [see dlopen(3C)].
If handle is RTLD_NEXT , the search begins with
the "next" shared library after the shared library from which
dlsym was invoked. Shared libraries are searched using a
load order symbol resolution algorithm [see dlopen(3C)].
The "next" shared library, and all other shared libraries searched,
are either of global scope (because they were loaded at startup or as
part of a dlopen operation with the RTLD_GLOBAL
flag) or are shared libraries loaded by the same dlopen operation
that loaded the caller of dlsym .
If handle is RTLD_SELF , the search begins
with the object from which dlsym was invoked. Objects are
searched using the load order symbol resolution algorithm.
If handle is RTLD_DEFAULT , then the symbol
search is done in the scope of the object that invoked dlsym .
For example, if the caller object was loaded as a result of dlopen
with RTLD_GROUP , it searches symbols in objects that were
loaded in the same dlopen invocation as the caller object.
Usage
RTLD_NEXT can be used
to navigate an intentionally created hierarchy of multiply defined symbols
created through interposition. For example, if a program wished to create
an implementation of malloc that embedded some statistics
gathering about memory allocations, such an implementation could define
its own malloc which gathers the necessary information,
and use dlsym with RTLD_NEXT to find the "real"
malloc , which performs the actual memory allocation.
Of course, this "real" malloc can be another
user-defined interface that added its own value and then used RTLD_NEXT
to find the system malloc .
Examples
The following example shows how to use dlopen and dlsym
to access either function or data objects. (For simplicity, error checking
has been omitted.)
void *handle;
int i, *iptr;
int (*fptr)(int);
/* open the needed object */
handle = dlopen("/usr/mydir/mylib.so", RTLD_LAZY);
/* find address of function and data objects */
fptr = (int (*)(int))dlsym(handle, "some_function");
iptr = (int *)dlsym(handle, "int_object");
/* invoke function, passing value of integer as a parameter */
i = (*fptr)(*iptr);
The following example shows how to use dlsym with RTLD_NEXT
to add functionality to an existing interface. (Error checking has been
omitted.)
extern void record_malloc(void *, size_t);
void *
malloc(size_t sz)
{
void *ptr;
void *(*real_malloc)(size_t);
real_malloc = (void * (*) (size_t))
dlsym(RTLD_NEXT, "malloc");
ptr = (*real_malloc)(sz);
record_malloc(ptr, sz);
return ptr;
}
The dlget Routine
The dlget routine retrieves information about a loaded module (program or shared library).
Syntax
void *dlget(int index,
struct load_module_desc *desc,
size_t desc_size);
Parameters
Parameter |
Definition |
index |
Specifies the requested shared library by its placement on the dynamic
loader's search list. An index of -1 requests information about the dynamic
loader. An index of -2 requests information about the program file itself.
|
desc |
Must be preallocated by the user. The structure members are filled
in by the dynamic loader with information about the requested shared library.
|
desc_size |
Specifies the size in bytes of the load_module_desc
structure sent in by the user. |
Return Values
If successful, dlget returns a handle for the shared
library as defined by the return value from dlopen() . If
a call to dlget is unsuccessful, a NULL pointer is returned
and desc remains unchanged.
Description
The dlget routine is one of a family
of routines that give the user direct access to the dynamic linking facilities.
The dlget routine retrieves information about a load module from an index
specifying the placement of a load module in the dynamic loader's search
list.
A load_module_desc structure has the following members:
struct load_module_desc {
unsigned long text_base;
unsigned long text_size;
unsigned long data_base;
unsigned long data_size;
unsigned long unwind_base;
unsigned long linkage_ptr;
unsigned long phdr_base;
unsigned long tls_size;
unsigned long tls_start_addr;
}
Example
The following code sequence shows how to use dlget
to retrieve information about loaded modules. The code sequence
prints the text base of all loaded modules:
void* handle;
int index;
struct load_module_desc desc;
for (index = -2; ; i++) { handle = dlget(i, &desc, sizeof(struct load_module_desc));
if (handle = NULL) {
printf("%s\n", dlerror());
break;
}
else {
printf("library %d text base = %lx\n", index,
desc.text_base);
}
}
The dlmodinfo Routine
The dlmodinfo routine retrieves information about a loaded module (program or shared library).
Syntax
cc [flag...] file... -ldl [library]...
#include <dlfcn.h> unsigned long dlmodinfo(unsigned long ip_value,
struct load_module_desc *desc,
size_t desc_size,
void *(*read_tgt_mem)(void* buffer,
unsigned long ptr,
size_t bufsiz,
int ident),
int ident_parm,
uint64_t load_map_parm);
Parameters
Parameter |
Description |
ip_value |
An address. The instruction pointer value of the requested library. |
desc |
A buffer of memory allocated by the user program. The dynamic loader
fills this in with module information. |
desc_size |
Size in bytes of the desc buffer. |
read_tgm_mem |
A pointer to a function used by dlmodinfo to retrieve
needed information.
If the value is NULL, the dynamic loader uses its own internal data
structures to find the correct load module and ignore the ident_parm
and load_map_parm parameters. |
buffer |
A buffer supplied by dlmodinfo to read into. |
ptr |
The virtual memory address to read from. |
bufsiz |
The size of buffer in bytes. |
ident |
The value of the ident_parm parameter to dlmodinfo . |
ident_parm |
Only used to pass the fourth parameter to read_tgt_mem. |
load_map_parm |
Only used when calling through read_tgt_mem. Contains
the starting address of the load map. |
Return Values
If successful, dlmodinfo returns a handle
for the shared library as defined by the return value from dlopen() .
NULL is returned otherwise. The return values are type-converted to unsigned
long
Description
The dlmodinfo routine is one of
a family of routines that give the user direct access to the dynamic linking
facilities. The dlmodinfo routine retrieves information about
a load module from a given address value. The dlmodinfo routine searches
all currently loaded load modules looking for a load module whose address
range (address range of all loaded segments) holds the given address value.
The dlmodinfo routine fills the load_module_desc
with information from the matching load module.
The read_tgm_mem parameter allows the dlmodinfo
routine to find a load module in one process on behalf of another. The calling
process passes a callback via read_tgt_mem in order to read
memory in a different process address space from the one in which dlmodinfo
resides. The ip_value, load_map_parm, and ptr
from read_tgt_mem parameters can be pointers to shared libraries in another
process.
If the calling process calls dlmodinfo with a callback
registered via read_tgt_mem, it must supply the starting address
of the target process' load map in the load_map_parm parameter
to dlmodinfo . This can be retrieved from the DT_HP_LOAD_MAP
entry in the .dynamic section in the target executable file.
Example
The following code sequence shows how to use dlmodinfo
to retrieve information about a load module. In this example the dlmodinfo
is provided with the address of a function foo . The address
of foo is matched with the address range (the address range
of all loaded segments) of all load modules. The dlmodinfo
fills in the load_module_desc with information form the matching
load module.
void foo()
{
printf("foo\n");
}
int retrieve_info()
{
unsigned long handle; struct load_module_desc desc;
handle = dlmodinfo((unsigned long) &foo,
&desc,
sizeof(struct load_module_desc),
NULL,
0,
0);
if (handle != 0) {
printf("text base = %lx\n", desc.text_base);
}
}
The dlgetname Routine
The dlgetname routine retrieves the name of a load module given a load module descriptor.
Syntax
char *dlgetname(struct load_module_desc *desc,
size_t desc_size,
void *(*read_tgt_mem)(void* buffer,
unsigned long long ptr,
size_t bufsiz,
int ident),
int ident_parm,
unsigned long long load_map_parm);
Parameters
Parameter |
Description |
desc |
A buffer of memory allocated by the user program. The dynamic loader
fills this in with module information. |
desc_size |
Size in bytes of the desc buffer. |
read_tgm_mem |
A pointer to a function used by dlmodinfo to retrieve
needed information.
If the value is NULL, the dynamic loader uses its own internal data
structures to find the correct load module and ignore the ident_parm
and load_map_parm parameters. |
buffer |
A buffer supplied by dlmodinfo to read into. |
ptr |
The virtual memory address to read from. |
bufsiz |
The size of buffer in bytes. |
ident |
The value of the ident_parm parameter to dlmodinfo . |
ident_parm |
Only used to pass the fourth parameter to read_tgt_mem.
|
load_map_parm |
Only used when calling through read_tgt_mem. Contains
the starting address of the load map. |
Return Values
dlgetname returns the
pathname of a load module represented by desc. If desc
does not describe a loaded module, dlgetname returns NULL.
Description
The dlgetname routine is one of
a family of routines that give the user direct access to the dynamic linking
facilities.
The read_tgt_mem, ident_parm, and load_map_parm
parameters are identical to those for the dlmodinfo routine.
The caller of dlgetname must copy the return value
to insure that it is not corrupted.
Example
The following code sequence shows how to use dlgetname
to retrieve the pathname of a load module. This example uses dlget
to get a load_module_desc of the required load module and passes
that load_module_desc to dlgetname to retrieve
the pathname.
void* handle;
struct load_module_desc desc;
char* dll_name;
/* Get load module of the index'th shared library */
handle = dlget(1, &desc, sizeof(struct load_module_desc));
/* Retrieve pathname of the shared library */
dll_name = dlgetname(&desc,
sizeof(struct load_module_desc),
NULL,
0,
NULL);
printf("pathname of 1st shared library : %s\n", dll_name);
The dlclose Routine
The dlclose routine closes a shared library.
Syntax
int dlclose(void *handle);
Parameters
Parameter |
Definition |
handle |
Value returned by a previous invocation of dlopen . |
Return Values
If the referenced shared library was successfully closed, dlclose
returns 0. If the shared library cannot be closed or if the handle
does not refer to an open shared library, the dlclose routine returns
a non-0 value. For more detailed diagnostic information you can use the dlerror routine.
Description
The dlclose routine disassociates
a shared library previously opened by the dlopen routine from the current process.
Once a shared library has been closed using the dlclose routine, the dlsym
routine no longer has access to its symbols. All shared libraries loaded automatically
as a result of invoking dlopen on the referenced shared library
[see dlopen(3C)] are also closed.
A successful invocation of dlclose does not guarantee
that the shared libraries associated with handle have actually
been removed from the address space of the process. shared libraries loaded
by one invocation of dlopen may also be loaded by another
invocation of dlopen . The same shared library may also be
opened multiple times. A shared library is not removed from the address
space until all references to that shared library through an explicit
dlopen invocation have been closed and all other shared libraries
implicitly referencing that shared library have also been closed. Once
a shared library is closed by dlclose , referencing
symbols contained in that shared library can cause undefined behavior.
Example
The following example shows how to use dlclose to unload
a shared library:
void* handle;
int ret_value;
handle = dlopen("./lib1.so", RTLD_GLOBAL | RTLD_LAZY);if (handle == NULL) {
printf("%s\n", dlerror());
}
ret_value = dlclose(handle);
if (ret_value != 0) {
printf("%s\n", dlerror());
}
The dladdr Routine
The dladdr routine gets the symbolic information for an address.
Syntax
int dladdr(void *address, D1_info *dlip);
Parameters
Parameter |
Description |
address |
|
dlip |
A pointer to a D1_info structure. The structure must be allocated
by the user. |
Return Values
If the specified address does not fall within one of the load modules,
0 is returned; the contents of the D1_info structure are not modified.
Otherwise, a non-zero value is returned and the fields of the D1_info
structure are set.
Diagnostics
If no symbol is found within the load module containing address
whose value is less than or equal to address, the dli_sname , dli_saddr ,
and dli_size fields are set to 0; the dli_bind
field is set to STB_LOCAL , and the dli_type
field is set to STT_NOTYPE .
For a.out's , only a subset of externally visible symbols
are typically exported: specifically those referenced by the load modules
with which the a.out is linked. The exact set of exported
symbols for any shared library or the a.out can be controlled
using the linker (see ld(1)).
Description
The dladdr routine is one of a
family of routines that give the user direct access to the dynamic linking
facilities (using the -ldl option on the compiler or ld
line). The dladdr routine allows a process to obtain information about
the symbol that most closely defines a given address. The dladdr
routine determines whether the specified address is located within one of the
load modules (executable or shared libraries) that make up the process'
address space. An address is deemed to fall within a load module when
it is between the base address at which the load module was mapped and
the highest virtual address mapped for that load module, inclusive. If
a load module fits this criteria, its dynamic symbol table is searched
to locate the nearest symbol to the specified address. The nearest symbol
is the one whose value is equal to, or closest to but not less than, the
specified address.
The dlip parameter is a pointer to
a D1_info structure. The structure must be allocated by the user. The
structure members are set by dladdr if the specified address
falls within one of the load modules. The D1_info structure contains the
following members:
struct {
const char *dli_fname;
void *dli_fbase;
const char *dli_sname;
void *dli_saddr;
size_t dli_size;
int dli_bind;
int dli_type;
};
The dli_fname field contains a pointer to the filename
of the load module containing the address. The contents of this memory
location can change between calls to dladdr .
The dli_fbase field contains a handle to the load module.
This can be used as the first argument to dlsym .
The dli_sname field contains a pointer to the name
of the nearest symbol to the specified address. This symbol either has
the same address, or is the nearest symbol with a lower address. The contents
of this memory location can change between calls to dladdr .
The dli_saddr field contains the actual address of
the nearest symbol. For code symbols, it contains the address of the Official Plabel Descriptor
(OPD) for the nearest code symbol.
The dli_size field contains the size of the nearest
symbol as defined in the dynamic symbol table.
The dli_bind field contains the binding attribute of
the nearest symbol as defined in the dynamic symbol table. The values
for this are those used for a symbol's binding in the ELF symbol table
(see elf.h).
The dli_type field contains the type of the nearest
symbol as defined in the dynamic symbol table. The values for this are
those used for a symbol's type in the ELF symbol table (see elf.h).
Example
The following example shows how to use dladdr to :
#include <dlfcn.h>
typedef int (*fptr_t) ();
int func1() {return 11;}
int main()
{
D1_info di;
char* symname = (char*)strdup("func1");
if (dladdr(&func1, &di) == 0) {
printf("dladdr() failed for %s\n", symname);
return 1;
}
if (di.dli_sname) {
fptr_t tmp = (fptr_t)dlsym(di.dli_fbase, symname);
if (di.dli_saddr !=void *)&func1)
puts("approx match");
if (tmp != (fptr_t)di.dli_saddr) {
printf("dlsym(%s): %s\n", symname, dlerror());
}
}
printf("%s: %s(%d %d %d)\n", di.dli_sname? di.dli_sname:"nil",
di.dli_fname, di.dli_type, di.dli_bind, di.dli_size);
return 0;
}
The dlmodadd Routine
The dlmodadd routine registers information about dynamically-generated functions.
Syntax
void* dlmodadd(void *associate handle,
void *func_start,
size_t func_size,
void *linkage_ptr,
void *unwind_info);
Parameters
Parameter |
Description |
associate handle |
The module handle for an existing module with which the new function
is associated. When the dynamic loader is called from the new function,
it behaves as if it had been called from the associated module. This
handle must be a handle returned by the dlopen() routine or the dlget routine.
|
func_start |
The starting address of the generated machine code for the function.
It is NOT the address of a function descriptor. |
func_size |
The size, in bytes, of the generated machine code. |
linkage_ptr |
The global pointer (gp) value to be used for the function. It could
be the gp of the associated module. It must be set to a valid value, even
if the generated code doesn't actually use gp, as it is required at a
minimum for following the personality routine pointer in the unwind information.
|
unwind_info |
A pointer to the beginning of the unwind info block for the function.
The unwind info block contains the header word, unwind descriptors, personality
routine pointer, and language-specific data, as described in the Itanium-based
system Software Conventions and Runtime Architecture document. |
Return Values
If successful, dlmodadd returns a handle as identification
of the newly-added function. NULL is returned otherwise.
Description
The dlmodadd routine registers
information about a dynamically-generated function, which can be retrieved
through the dlmodinfo routine. The dlmodremove interface
can be used to remove the registered information.
When dlmodadd is invoked to register information about
a dynamically-generated function, the dynamic loader creates an unwind
header and a single-entry unwind table for the function. The unwind header
is associated with the address range occupied by the dynamically-generated
function. The dlmodadd() routine returns a handle as
identification of the newly-added function. Handles returned by dlmodadd()
share the same namespace as handles returned by dlopen()
and dlget() , but they may not be used in calls to dlclose() .
A handle returned by dlmodadd() is treated by dlsym()
as if the associated handle had been used instead. If dlmodinfo()
is called with an ip_value that belongs to a function that has been registered
with dlmodadd() , it returns the handle of the dynamically-generated
function, as originally returned by dlmodadd() , along with
a load_module_desc structure describing the function. A load_module_desc
for a dynamically-generated function always has a 0 value in the
phdr_base field.
The text_base , text_size , data_base , and data_size
fields may be used for converting segment-relative offsets to virtual
addresses, but they may not be relied on to identify a range of memory
belonging exclusively to the function. The unwind_base field
will contain the address of the unwind header built for the function.
If a library is unloaded by dlclose() , the unwind info for
all dynamically-generated functions associated with the library being
unloaded will also be removed.
The dlmodremove Routine
The dlmodremove removes information registered using dlmodadd .
Syntax
int dlmodremove(void* handle);
Parameters
Parameter |
Definition |
handle |
Value returned by a previous invocation of dlmodremove . |
Return Values
The dlmodremove routine returns 0 on success. If handle
does not refer to a valid handle, dlmodremove returns a non-0
value.
Description
The dlmodremove routine removes
the registered information of individual dynamically-generated functions.
It removes the registration of the indicated function and frees the space
used by the unwind header and unwind table created by dlmodadd() .
It does not free the space used by the unwind info block or by the generated
code, which was allocated by the user and must be freed by the user.
The dlgetmodinfo Routine
The dlgetmodinfo retrieves information about a loaded module (program or shared library).
Syntax
uint64_t dlgetmodinfo(int index,
struct load_module_desc *desc,
size_t desc_size,
void *(*read_tgt_mem) (void* buffer,
uint64_t ptr,
size_t bufsiz,
int ident),
int ident_parm,
uint64_t load_map_parm);
Parameters
Parameter |
Definition |
desc |
A buffer of memory allocated by the user program. The dynamic loader
fills this in with module information. |
desc_size |
Size in bytes of the desc buffer. |
read_tgm_mem |
A pointer to a function used by dlmodinfo to retrieve
needed information.
If the value is NULL, the dynamic loader uses its own internal data
structures to find the correct load module and ignore the ident_parm
and load_map_parm parameters. |
buffer |
A buffer supplied by dlmodinfo to read into. |
ptr |
The virtual memory address to read from. |
bufsiz |
The size of buffer in bytes. |
ident |
The value of the ident_parm parameter to dlmodinfo . |
ident_parm |
Only used to pass the fourth parameter to read_tgt_mem. |
load_map_parm |
Only used when calling through read_tgt_mem. Contains
the starting address of the load map. |
Return Values
If successful, dlgetmodinfo returns a handle for the
shared library as defined by the return value from dlopen() .
NULL is returned otherwise. The return values are type-converted
to uint64_t .
Description
The dlgetmodinfo routine is one
of a family of routines that give the user direct access to the dynamic
linking facilities. The dlgetmodinfo routine retrieves information about
a load module from an index specifying the placement of the load module
in the dynamic loader's search list. Unlike dlget , dlgetmodinfo
can retrieve information about a load module in another process.
An index of -1 requests information about the dynamic loader; an
index of -2 requests information about the program file itself.
The dlgetmodinfo routine fills the load_module_desc
with information from the matching load module.
Example
The following example shows how to use dlgetmodinfo :
#include <dlfcn.h>
#include <stdio.h>
int main()
{
void *handle;
struct load_module_desc desc;
handle = dlgetmodinfo((void*) -2,
&desc,
sizeof(struct load_module_desc),
NULL,
0,
0);
if (handle == NULL) {
printf("Error: dlgetmodinfo returns NULL\n");
exit(1);
} else {
printf("text base = 0x%x\n", desc.text_base);
}
}
|