Jump to content United States-English
HP.com Home Products and Services Support and Drivers Solutions How to Buy
» Contact HP
More options
HP.com home
HP-UX Linker and Libraries User's Guide: HP 9000 Computers > Chapter 6 Shared Library Management Routines

The shl_load Shared Library Management Routines

» 

Technical documentation

Complete book in PDF
» Feedback
Content starts here

 » Table of Contents

 » Glossary

 » Index

This section describes the shl_load family of shared library management routines.

NOTE: You can use these routines in both 32-bit and 64-bit mode. Support for these routines may be discontinues in a future 64-bit HP-UX release. If you use these routines in 64-bit mode, consider converting your programs to the dl* family of shared library management routines.

The shl_load and cxxshl_load Routines

Explicitly loads a library.

Syntax

shl_t shl_load( const char * path,
int flags,
long address )

Parameters

path

A null-terminated character string containing the path name of the shared library to load.

flags

Specifies when the symbols in the library should be bound to addresses. It must be one of these values, defined in <dl.h>:

BIND_IMMEDIATE

Bind the addresses of all symbols immediately upon loading the library.

BIND_DEFERRED

Bind the addresses when they are first referenced.

Be aware that BIND_IMMEDIATE causes the binding of all symbols, and the resolution of all imports, even from older versioned modules in the shared library. If symbols are not accessible because they come from old modules, they are unresolved and shl_load may fail.

In addition to the above values, the flags parameter can be ORed with the following values:

BIND_NONFATAL

Allow binding of unresolved symbols.

BIND_VERBOSE

Make dynamic loader display verbose messages when binding symbols.

BIND_FIRST

Insert the loaded library before all others in the current link order.

DYNAMIC_PATH

Causes the dynamic loader to perform dynamic library searching when loading the library. The +s and +b options to the ld command determine the directories the linker searches. This is the default mode for the 64-bit mode linker if +compat linker option is not specified.

BIND_NOSTART

Causes the dynamic loader to not call the initializer, even if one is declared for the library, when the library is loaded or on a future call to shl_load or dlopen. This also inhibits a call to the initializer when the library is unloaded.

BIND_RESTRICTED

Causes the search for a symbol definition to be restricted to those symbols that were visible when the library was loaded.

BIND_TOGETHER

Causes the library being loaded and all its dependent libraries to be bound together rather than each independently. Use this when you have interdependent libraries and you are using BIND_FIRST.

BIND_BREADTH_FIRST

64-bit mode only:

Causes the dependent libraries to be loaded breadth first. By default, the 64-bit mode shl_load loads dependent libraries depth-first.

These flags are discussed in detail in“shl_load Example ”.

address

Specifies the virtual address at which to attach the library. Set this parameter to 0 (zero) to tell the system to choose the best location. This argument is currently ignored; mapping a library at a user-defined address is not currently supported.

Return Value

If successful, shl_load returns a shared library handle of type shl_t. This address can be used in subsequent calls to shl_close, shl_findsym, shl_gethandle, and shl_gethandle_r. Otherwise, shl_load returns a shared library handle of NULL and sets errno to one of these error codes (from <errno.h>):

Title not available (Return Value )

ENOEXEC

The specified path is not a shared library, or a format error was detected in this or another library.

ENOSYM

A symbol needed by this library or another library which this library depends on could not be found.

ENOMEM

There is insufficient room in the address space to load the shared library.

EINVAL

The requested shared library address was invalid.

ENOENT

The specified path does not exist.

EACCESS

Read or execute permission is denied for the specified path.

Description

A program needs to explicitly load a library only if the library was not linked with the program. This typically occurs only when the library cannot be known at link time — for example, when writing programs that must support future graphics devices.

However, programs are not restricted to using shared libraries only in that situation. For example, rather than linking with any required libraries, a program could explicitly load libraries as they are needed. One possible reason for doing this is to minimize virtual memory overhead. To keep virtual memory resource usage to a minimum, a program could load libraries with shl_load and unload with shl_unload when the library is no longer needed. However, it is normally not necessary to incur the programming overhead of loading and unloading libraries yourself for the sole reason of managing system resources.

Note that if shared library initializers have been declared for an explicitly loaded library, they are called after the library is loaded. For details, see “Initializers for Shared Libraries”.

To explicitly load a shared library, use the shl_load routine. If loading a C++ library, use the cxxshl_load routine. This ensures that constructors of nonlocal static objects are executed when the library is loaded. The syntax of cxxshl_load is the same as that of shl_load.

In 64-bit mode, shl_load lets you load a compatibility or standard mode shared libraries. The BIND_BREADTH_FIRST flag overrides the default depth-first loading mechanism.

shl_load Usage

Since the library was not specified at link time, the program must get the library name at run time. Here are some practical ways to do this:

  • Hard-code the library name into the program (the easiest method).

  • Get the library name from an environment variable using the getenv library routine (see getenv(3C)).

  • Get the library path name from the command line through argv.

  • Read the library name from a configuration file.

  • Prompt for the library path name at run time.

If successful, shl_load returns a shared library handle (of type shl_t), which uniquely identifies the library. This handle can then be passed to the shl_findsym or shl_unload routine.

Once a library is explicitly loaded, use the shl_findsym routine to get pointers to functions or data contained in the library; then call or reference them through the pointers. This is described in detail in“The shl_findsym Routine ”.

shl_load Example

The following example shows the source for a function named load_lib that explicitly loads a library specified by the user. The user can specify the library in the environment variable SHLPATH or as the only argument on the command line. If the user chooses neither of these methods, the function prompts for the library path name.

The function then attempts to load the specified library. If successful, it returns the shared library handle, of type shl_t. If an error occurs, it displays an error message and exits. This function is used later in “The shl_findsym Routine ”.

Example 6-13 load_lib — Function to Load a Shared Library

#include        <stdio.h>      /* contains standard I/O defs           */
#include <stdlib.h> /* contains getenv definition */
#include <dl.h> /* contains shared library type defs */

shl_t load_lib(int argc,
char * argv[]) /* pass argc and argv from main */
{
shl_t lib_handle; /* temporarily holds library handle */
char lib_path[MAXPATHLEN]; /* holds library path name */
char *env_ptr; /* points to SHLPATH variable value */
/*
* Get the shared library path name:
*/
if (argc > 1) /* library path given on command line */
strcpy(lib_path, argv[1]);
else /* get lib_path from SHLPATH variable */
{
env_ptr = getenv("SHLPATH");
if (env_ptr != NULL)
strcpy(lib_path, env_ptr);
else /* prompt user for shared library path */
{
printf("Shared library to use >> ");
scanf("%s", lib_path);
}
}
/*
* Dynamically load the shared library using BIND_IMMEDIATE binding:
*/
lib_handle = shl_load( lib_path, BIND_IMMEDIATE, 0);
if (lib_handle == NULL)
perror("shl_load: error loading library"), exit(1);
return lib_handle;
}

BIND_NONFATAL Modifier

If you load a shared library with the BIND_IMMEDIATE flag and the library contains unresolved symbols, the load fails and sets errno to ENOSYM. ORing BIND_NONFATAL with BIND_IMMEDIATE causes shl_load to allow the binding of unresolved symbols to be deferred if their later use can be detected — for example:

shl_t libH;
. . .
libH = shl_load("libxyz.sl", BIND_IMMEDIATE | BIND_NONFATAL, 0);

However, data symbol binding cannot be deferred, so using the BIND_NONFATAL modifier does not allow the binding of unresolved data symbols.

BIND_VERBOSE Modifier

If BIND_VERBOSE is ORed with the flags parameter, the dynamic loader displays messages for all unresolved symbols. This option is useful to see exactly which symbols cannot be bound. Typically, you would use this with BIND_IMMEDIATE to debug unresolved symbols — for example:

shl_t libH;
. . .
libH = shl_load("libxyz.sl", BIND_IMMEDIATE | BIND_VERBOSE, 0);

BIND_FIRST Modifier

If BIND_FIRST is ORed with the flags parameter, the loaded library is inserted before all other loaded shared libraries in the symbol resolution search order. This has the same effect as placing the library first in the link order — that is, the library is searched before other libraries when resolving symbols. This is used with either BIND_IMMEDIATE or BIND_DEFERRED — for example:

shl_t libH;
. . .
libH = shl_load("libpdq.sl", BIND_DEFERRED | BIND_FIRST, 0);

BIND_FIRST is typically used when you want to make the symbols in a particular library more visible than the symbols of the same name in other libraries. Compare this with the default behavior, which is to append loaded libraries to the link order.

DYNAMIC_PATH Modifier

The flag DYNAMIC_PATH can also be ORed with the flags parameter, causing the dynamic loader to search for the library using a path list specified by the +b option at link time or the SHLIB_PATH environment variable at run time.

BIND_NOSTART Modifier

The flag BIND_NOSTART inhibits execution of initializers for the library.

BIND_RESTRICTED Modifier

This flag is most useful with the BIND_DEFERRED flag; it has no effect with BIND_IMMEDIATE. It is also useful with the BIND_NONFATAL flag.

When used with only the BIND_DEFERRED flag, it has this behavior: When a symbol is referenced and needs to be bound, this flag causes the search for the symbol definition to be restricted to those symbols that were visible when the library was loaded. If a symbol definition cannot be found within this restricted set, it results in a run-time symbol-binding error.

When used with BIND_DEFERRED and the BIND_NONFATAL modifier, it has the same behavior, except that when a symbol definition cannot be found, the dynamic loader will then look in the global symbol set. If a definition still cannot be found within the global set, a run-time symbol-binding error occurs.

BIND_TOGETHER Modifier

BIND_TOGETHER modifies the behavior of BIND_FIRST. When the library being loaded has dependencies, BIND_FIRST causes each dependent library to be loaded and bound separately. If the libraries have interdependencies, the load may fail because the needed symbols are not available when needed.

BIND_FIRST | BIND_TOGETHER causes the library being loaded and its dependent libraries to be bound all at the same time, thereby resolving interdependencies. If you are not using BIND_FIRST, libraries are bound together by default so this option has no effect.

BIND_BREADTH_FIRST Modifier

64-bit mode only:

This flag causes the dependent libraries to be loaded breadth first. By default, the 64-bit mode shl_load loads dependent libraries depth-first. This modifier overrides the default load order.

Binding Flags Examples

Suppose you have the libraries libE.sl, libF.sl, and libG.sl. The libE library depends on libF and libF depends on libG. In addition, libG depends on libFlibF and libG are interdependent. Your program loads libE.sl with shl_load().

When using BIND_DEFERRED or BIND_IMMEDIATE without BIND_FIRST, these libraries are loaded such that all symbols are visible and the interdependencies are resolved:

shl_t libE;
libE = shl_load("libE.sl", BIND_IMMEDIATE, 0);
shl_load succeeds.

When using BIND_IMMEDIATE | BIND_FIRST, however, libG is loaded and bound first and since it depends on libF, an error results because the needed symbols in libF are not yet available:

libE = shl_load("libE.sl", BIND_IMMEDIATE | BIND_FIRST, 0); 
shl_load fails.

Using BIND_IMMEDIATE | BIND_FIRST | BIND_TOGETHER loads libE, libF, and libG together and correctly resolves all symbols:

libE = shl_load("libE.sl", BIND_IMMEDIATE | BIND_FIRST | BIND_TOGETHER, 0); 
shl_load succeeds.

The shl_findsym Routine

Obtains the address of an exported symbol from a shared library. To call a routine or access data in an explicitly loaded library, first get the address of the routine or data with shl_findsym.

Syntax

int shl_findsym( shl_t * handle,
const char * sym,
short type,
void * value )

Parameters

handle

A pointer to a shared library handle of the library to search for the symbol name sym. This handle could be obtained from the shl_get routine (described in the “The shl_get and shl_get_r Routines”). handle can also point to:

NULL

If a pointer to NULL is specified, shl_findsym searches all loaded libraries for sym. If sym is found, shl_findsym sets handle to a pointer to the handle of the shared library containing sym. This is useful for determining which library a symbol resides in. For example, the following code sets handle to a pointer to the handle of the library containing symbol _foo:

shl_t handle;
handle = NULL;
shl_findsym(&handle,"_foo",...);
PROG_HANDLE

This constant, defined in dl.h, tells shl_findsym to search for the symbol in the program itself. This way, any symbols exported from the program can be accessed explicitly.

sym

A null-terminated character string containing the name of the symbol to search for.

type

The type of symbol to look for. It must be one of the following values, defined in <dl.h>:

TYPE_PROCEDURE

Look for a function or procedure.

TYPE_DATA

Look for a symbol in the data segment (for example, variables).

TYPE_UNDEFINED

Look for any symbol.

TYPE_STORAGE

32-bit mode only.

TYPE_TSTORAGE

32-bit mode only.

value

A pointer in which shl_findsym stores the address of sym, if found.

Return Value

If successful, shl_findsym returns an integer (int) value zero. If shl_findsym cannot find sym, it returns -1 and sets errno to zero. If any other errors occur, shl_findsym returns -1 and sets errno to one of these values (defined in <errno.h>):

ENOEXEC

A format error was detected in the specified library.

ENOSYM

A symbol on which sym depends could not be found.

EINVAL

The specified handle is invalid.

Description

To call a routine or access data in an explicitly loaded library, first get the address of the routine or data with shl_findsym.

To call a routine in an explicitly loaded library

  1. declare a pointer to a function of the same type as the function in the shared library

  2. using shl_findsym with the type parameter set to TYPE_PROCEDURE, find the symbol in the shared library and assign its address to the function pointer declared in Step 1

  3. call the pointer to the function obtained in Step 2, with the correct number and type of arguments

To access data in an explicitly loaded library

  1. declare a pointer to a data structure of the same type as the data structure to access in the library

  2. using shl_findsym with the type parameter set to TYPE_DATA, find the symbol in the shared library and assign its address to the pointer declared in Step 1

  3. access the data through the pointer obtained in Step 2

shl_findsym Example

Suppose you have a set of libraries that output to various graphics devices. Each graphics device has its own library. Although the actual code in each library varies, the routines in these shared libraries have the same name and parameters, and the global data is the same. For instance, they all have these routines and data:

gopen()

opens the graphics device for output

gclose()

closes the graphics device

move2d(x,y)

moves to pixel location x,y

draw2d(x,y)

draws to pixel location x,y from current x,y

maxX

contains the maximum X pixel location on the output device

maxY

contains the maximum Y pixel location on the output device

The following example shows a C program that can load any supported graphics library at run time, and call the routines and access data in the library. The program calls load_lib (see Example 6-13 “load_lib — Function to Load a Shared Library ”) to load the library.

Example 6-14 Load a Shared Library and Call Its Routines and Access Its Data

#include <stdio.h>      /* contains standard I/O defs        */
#include <stdlib.h> /* contains getenv definition */
#include <dl.h> /* contains shared library type defs */
/*
* Define linker symbols:
*/

#define GOPEN "gopen"
#define GCLOSE "gclose"
#define MOVE2D "move2d"
#define DRAW2D "draw2d"
#define MAXX "maxX"
#define MAXY "maxY"

shl_t load_lib(int argc, char * argv[]);
main(int argc,
char * argv[])
{
shl_t lib_handle; /* handle of shared library */
int (*gopen)(void); /* opens the graphics device */
int (*gclose)(void); /* closes the graphics device */
int (*move2d)(int, int); /* moves to specified x,y location */
int (*draw2d)(int, int); /* draw line to specified x,y location*/
int *maxX; /* maximum X pixel on device */
int *maxY; /* maximum Y pixel on device */

lib_handle = load_lib(argc, argv); /* load required shared library */
/*
* Get addresses of all functions and data that will be used:
*/
if (shl_findsym(&lib_handle, GOPEN, TYPE_PROCEDURE, (void *) &gopen))
perror("shl_findsym: error finding function gopen"), exit(1);
if (shl_findsym(&lib_handle, GCLOSE, TYPE_PROCEDURE, (void *) &gclose))
perror("shl_findsym: error finding function gclose"), exit(1);
if (shl_findsym(&lib_handle, MOVE2D, TYPE_PROCEDURE, (void *) &move2d))
perror("shl_findsym: error finding function move2d"), exit(1);
if (shl_findsym(&lib_handle, DRAW2D, TYPE_PROCEDURE, (void *) &draw2d))
perror("shl_findsym: error finding function draw2d"), exit(1);
if (shl_findsym(&lib_handle, MAXX, TYPE_DATA, (void *) &maxX))
perror("shl_findsym: error finding data maxX"), exit(1);
if (shl_findsym(&lib_handle, MAXY, TYPE_DATA, (void *) &maxY))
perror("shl_findsym: error finding data maxY"), exit(1);
/*
* Using the routines, draw a line from (0,0) to (maxX,maxY):
*/
(*gopen)(); /* open the graphics device */
(*move2d)(0,0); /* move to pixel 0,0 */
(*draw2d)(*maxX,*maxY); /* draw line to maxX,maxY pixel */
(*gclose)(); /* close the graphics device */
}

Shown below is the compile line for this program, along with the commands to set SHLPATH appropriately before running the program. SHLPATH is declared and used by load_lib(), defined in “The shl_load and cxxshl_load Routines ” example. Notice that load_lib() is compiled here along with this program. Finally, this example assumes you have created a graphics library, libgrphdd.sl:

$ cc -Aa -o drawline shl_findsym.c load_lib.c -ldld
$ SHLPATH=/usr/lib/libgrphdd.sl
$ export SHLPATH
$ drawline

The shl_get and shl_get_r Routines

Obtains information on the currently loaded libraries.

Syntax

int shl_get( int index,
struct shl_descriptor **desc )

Parameters

index

Specifies an ordinal number of the shared library in the process. For libraries loaded implicitly (at startup time), index is the ordinal number of the library as it appeared on the command line. For example, if libc was the first library specified on the ld command line, then libc has an index of 1. For explicitly loaded libraries, index corresponds to the order in which the libraries were loaded, starting after the ordinal number of the last implicitly loaded library. Two index values have special meaning:

0

Refers to the main program itself

-1

Refers to the dynamic loader (dld.sl).

A shared library's index can be modified during program execution by either of the following events:

  • The program loads a shared library with the BIND_FIRST modifier to shl_load. This increments all the shared library indexes by one.

  • The program unloads a shared library with shl_unload. Any libraries following the unloaded library have their index decremented by one.

desc

Returns a pointer to a statically allocated buffer (struct shl_descriptor **) containing a shared library descriptor. The structure contains these important fields:

tstart

The start address (unsigned long) of the shared library text segment.

tend

The end address (unsigned long) of the shared library text segment.

dstart

The start address (unsigned long) of the shared library data segment.

dend

The end address (unsigned long) of the shared library bss segment. The data and bss segments together form a contiguous memory block starting at dstart and ending at dend.

handle

The shared library's handle (type shl_t).

filename

A character array containing the library's path name as specified at link time or at explicit load time.

initializer

A pointer to the shared library's initializer routine (see “Initializers for Shared Libraries”. It is NULL if there is no initializer. This field is useful for calling the initializer if it was disabled by the BIND_NOSTART flag to shl_load.

If the shared library has multiple initializers, this field will also be set to NULL. Multiple initializers can be found with shl_getsymbols, described later in this chapter.

This buffer is statically allocated. Therefore, if a program intends to use any of the members of the structure, the program should make a copy of the structure before the next call to shl_get. Otherwise, shl_get will overwrite the static buffer when called again.

Return Value

If successful, shl_get returns an integer value 0. If the index value exceeds the number of currently loaded libraries, shl_get returns -1 and sets errno to EINVAL.

Description

To obtain information on currently loaded libraries, use the shl_get function. If you are programming in a threaded environment, use the thread-safe version shl_get_r which is the same as shl_get in all other respects. (See Programming with Threads on HP-UX for more information about threads.)

Other than obtaining interesting information, this routine is of little use to most programmers. A typical use might be to display the names and starting/ending address of all shared libraries in a process's virtual memory address space.

Example

The function show_loaded_libs shown below displays the name and start and end address of the text and data/bss segments the library occupies in a process's virtual address space.

Example 6-15 show_loaded_libs — Display Library Information

#include        <stdio.h>      /* contains standard I/O defs           */
#include <dl.h> /* contains shared library type defs */
void show_loaded_libs(void)
{
int idx;
struct shl_descriptor *desc;

printf("SUMMARY of currently loaded libraries:\n");
printf("%-25s %10s %10s %10s %10s\n",
"___library___", "_tstart_", "__tend__", "_dstart_", "__dend__");

idx = 0;
for (idx = 0; shl_get(idx, &desc) != -1; idx++)
printf("%-25s %#10lx %#10lx %#10lx %#10lx\n",
desc->filename, desc->tstart, desc->tend, desc->dstart, desc->dend);
}

Calling this function from a C program compiled with shared libc and libdld produced the following output:

SUMMARY of currently loaded libraries:
___library___ _tstart_ __tend__ _dstart_ __dend__
./a.out 0x1000 0x1918 0x40000000 0x40000200
/usr/lib/libdld.sl 0x800ac800 0x800ad000 0x6df62800 0x6df63000
/usr/lib/libc.sl 0x80003800 0x80091000 0x6df63000 0x6df85000

The shl_gethandle and shl_gethandle_r Routines

Returns descriptor information about a loaded shared library.

Syntax

int shl_gethandle( shl_t handle,
struct shl_descriptor **desc )

Parameters

handle

The handle of the shared library you want information about. This handle is the same as that returned by shl_load.

desc

Points to shared library descriptor information — the same information returned by the shl_get routine. The buffer used to store this desc information is static, meaning that subsequent calls to shl_gethandle will overwrite the same area with new data. Therefore, if you need to save the desc information, copy it elsewhere before calling shl_gethandle again.

Return Value

If handle is not valid, the routine returns -1 and sets errno to EINVAL. Otherwise, shl_gethandle returns 0.

Description

The shl_gethandle routine returns descriptor information about a loaded shared library. If you are programming in a threaded environment, use the thread-safe version shl_gethandle_r which is the same as shl_gethandle in all other respects. (See Programming with Threads on HP-UX for more information about threads.)

Example

The following function named show_lib_info displays information about a shared library, given the library's handle.

Example 6-16 show_lib_info — Display Information for a Shared Library

#include <stdio.h>
#include <dl.h>

int show_lib_info(shl_t libH)
{
struct shl_descriptor *desc;

if (shl_gethandle(libH, &desc) == -1)
{
fprintf(stderr, "Invalid library handle.\\n");
return -1;
}
printf("library path: %s\\n", desc->filename);
printf("text start: %#10lx\\n", desc->tstart);
printf("text end: %#10lx\\n", desc->tend);
printf("data start: %#10lx\\n", desc->dstart);
printf("data end: %#10lx\\n", desc->dend);
return 0;
}

The shl_definesym Routine

Adds new symbols to the global shared library symbol table.

Syntax

int shl_definesym( const char *sym,
short type,
long value,
int flags )

Parameters

sym

A null-terminated string containing the name of the symbol to change or to add to the process's shared library symbol table.

type

The type of symbol — either TYPE_PROCEDURE or TYPE_DATA.

value

If value falls in the address range of a currently loaded library, an association will be made and the symbol is undefined when the library is unloaded. (Note that memory dynamically allocated with malloc(3C) does not fall in the range of any library.) The defined symbol may be overridden by a subsequent call to this routine or by loading a more visible library that provides a definition for the symbol.

flags

Must be set to zero.

Return Value

If successful, shl_definesym returns 0. Otherwise, it returns -1 and sets errno accordingly. See shl_definesym(3X) for details.

Description

The shl_definesym function allows you to add a new symbol to the global shared library symbol table. Use of this routine will be unnecessary for most programmers.

There are two main reasons to add or change shared library symbol table entries:

  • to generate symbol definitions as the program runs — for example, aliasing one symbol with another

  • to override a current definition

Symbol definitions in the incomplete executable may also be redefined with certain restrictions:

  • The incomplete executable always uses its own definition for any data (storage) symbol, even if a more visible one is provided.

  • The incomplete executable only uses a more visible code symbol if the main program itself does not provide a definition.

The shl_getsymbols Routine

The shl_getsymbols function retrieves symbols that are imported (referenced) or exported (defined) by a shared library. This information is returned in an allocated array of records, one for each symbol. Most programmers do not need to use this routine.

Syntax

int shl_getsymbols( shl_t handle,
short type,
int flags,
void * (*memfunc)(),
struct shl_symbol **symbols )

Parameters

handle

The handle of the shared library whose symbols you want to retrieve. If handle is NULL, shl_getsymbols returns symbols that were defined with the shl_definesym routine.

type

Defines the type of symbol to retrieve. It must be one of the following values, which are defined as constants in <dl.h>:

TYPE_PROCEDURE

Retrieve only function or procedure symbols.

TYPE_DATA

Retrieve only symbols from the data segment (for example, variables).

TYPE_UNDEFINED

Retrieve all symbols, regardless of type.

TYPE_STORAGE

32-bit mode only.

TYPE_TSTORAGE

32-bit mode only.

flags

Defines whether to retrieve import or export symbols from the library. An import symbol is an external reference made from a library. An export symbol is a symbol definition that is referenced outside the library. In addition, any symbol defined by shl_definesym is an export symbol. Set this argument to one of the following values (defined in <dl.h>):

IMPORT_SYMBOLS

To return import symbols.

EXPORT_SYMBOLS

To return export symbols.

INITIALIZERS

To return initializer symbols.

One of the following modifiers can be ORed with both the EXPORT_SYMBOLS and the INITIALIZERS flags:

NO_VALUES

Do not calculate the value field of the shl_symbol structure for symbols. The value field has an undefined value.

GLOBAL_VALUES

For symbols that are defined in multiple libraries, this flag causes shl_getsymbols to return the most-visible occurrence, and to set the value and handle fields of the shl_symbol structure (defined in the description of the symbols parameter).

memfunc

Points to a function that has the same interface (calling conventions and return value) as malloc(3C). The shl_getsymbols function uses this function to allocate memory to store the array of symbol records, symbols.

symbols

This points to an array of symbol records for all symbols that match the criteria determined by the type and value parameters. The type of these records is struct shl_symbol, defined in <dl.h> as:

struct shl_symbol {
char * name;
short type;
void * value;
shl_t handle;
};

The members of this structure are described in “The shl_symbol Structure”.

Return Value

If successful, shl_getsymbols returns the number of symbols found; otherwise, -1 is returned and shl_getsymbols sets errno to one of these values:

ENOEXEC

A format error was detected in the specified library.

ENOSYM

Some symbol required by the shared library could not be found.

EINVAL

The specified handle is invalid.

ENOMEM

memfunc failed to allocate the requested memory.

The shl_symbol Structure

The members of the shl_symbol structure are defined as follows:

name

Contains the name of a symbol.

type

Contains the symbol's type: TYPE_PROCEDURE, TYPE_DATA, or TYPE_STORAGE. TYPE_STORAGE is a data symbol used for C uninitialized global variables or FORTRAN common blocks.

value

Contains the symbol's address. It is valid only if EXPORT_SYMBOLS is specified without the NO_VALUES modifier.

handle

Contains the handle of the shared library in which the symbol is found, or NULL in the case of symbols defined by shl_definesym. It is valid only if EXPORT_SYMBOLS or INITIALIZERS were requested without the NO_VALUES modifier. It is especially useful when used with the GLOBAL_VALUES modifier, allowing you to determine the library in which the most-visible definition of a symbol occurs.

shl_getsymbols Example

Example 6-17 “show_symbols — Display Shared Library Symbols ” shows the source for a function named show_symbols that displays shared library symbols. The syntax of this routine is defined as:

int show_symbols(shl_t  hndl,
short type,
int flags)
hndl

The handle of the shared library whose symbols you want to display.

type

The type of symbol you want to display. This is the same as the type parameter to shl_getsymbols and can have these values: TYPE_PROCEDURE, TYPE_DATA, or TYPE_UNDEFINED. If it is TYPE_UNDEFINED, show_symbols displays the type of each symbol.

flags

This is the same as the flags parameter. It can have the value EXPORT_SYMBOLS or IMPORT_SYMBOLS. In addition, it can be ORed with NO_VALUES or GLOBAL_VALUES. If EXPORT_SYMBOLS is specified without being ORed with NO_VALUES, show_symbols displays the address of each symbol.

Example 6-17 show_symbols — Display Shared Library Symbols

#include <dl.h>
#include <stdio.h>
#include <stdlib.h>
int show_symbols(shl_t hndl,
short type,
int flags)
{
int num_symbols, sym_idx;
struct shl_symbol *symbols, *orig_symbols;

num_symbols = shl_getsymbols(hndl, type, flags, malloc, &symbols);
if (num_symbols < 0) {
printf("shl_getsymbols failed\n");
exit(1);
}
orig_symbols = symbols;
for (sym_idx = 0; sym_idx < num_symbols; sym_idx++)
{
printf(" %-30s", symbols->name); /* display symbol name */
if (type == TYPE_UNDEFINED) /* display type if TYPE_UNDEFINED */
switch (symbols->type) {
case TYPE_PROCEDURE:
printf(" PROCEDURE");
break;
case TYPE_DATA:
printf(" DATA ");
break;
case TYPE_STORAGE:
printf(" STORAGE ");
}
if ((flags & EXPORT_SYMBOLS) /* export symbols requested */
&& (flags & NO_VALUES)==0) /* NO_VALUES was NOT specified */
printf(" 0x%8X", symbols->value); /* so display symbol's address */
printf("\n"); /* terminate output line */
symbols++; /* move to next symbol record */
}
free(orig_symbols); /* free memory allocated by malloc */
return num_symbols; /* return the number of symbols */
}

The following example shows the source for a program named show_all.c that calls show_symbols to show all imported and exported symbols for every loaded shared library. It uses shl_get to get the library handles of all loaded libraries.

Example 6-18 show_all — Use show_symbols to Show All Symbols

#include <dl.h>
#include <stdio.h>
/* prototype for show_syms */
int show_syms(shl_t hndl, short type, int flags);
main()
{
int idx, num_syms;
struct shl_descriptor * desc;

for (idx=0; shl_get(idx, &desc) != -1; idx++) /* step through libs */
{
printf("[%s]\n", desc->filename); /* show imports & exports for each */
printf(" Imports:\n");
num_syms = show_symbols(desc->handle, TYPE_UNDEFINED, IMPORT_SYMBOLS);
printf(" TOTAL SYMBOLS: %d\n", num_syms);
printf(" Exports:\n");
num_syms = show_symbols(desc->handle, TYPE_UNDEFINED, EXPORT_SYMBOLS);
printf(" TOTAL SYMBOLS: %d\n", num_syms);
}
}

The show_all program shown above was compiled with the command:

$ cc -Aa -o show_all show_all.c show_symbols.c -ldld
NOTE: The following output for the example will differ in 64-bit mode. For example, STORAGE is not supported.

The output produced by running this program is shown below:

[show_all]
Imports:
errno STORAGE
_start PROCEDURE
malloc PROCEDURE
free PROCEDURE
exit PROCEDURE
printf PROCEDURE
shl_get PROCEDURE
shl_getsymbols PROCEDURE
__d_trap PROCEDURE
TOTAL SYMBOLS: 9
Exports:
environ DATA 0x40001018
errno STORAGE 0x400011CC
_SYSTEM_ID DATA 0x40001008
__dld_loc STORAGE 0x400011C8
_FPU_MODEL DATA 0x4000100C
_end DATA 0x400011D0
_environ DATA 0x40001018
__d_trap PROCEDURE 0x7AFFF1A6
main PROCEDURE 0x7AFFF1BE
TOTAL SYMBOLS: 9
[/usr/lib/libc.1]
Imports:
_res_rmutex STORAGE
errno STORAGE
_regrpc_rmutex STORAGE
_yellowup_rmutex STORAGE
_FPU_MODEL STORAGE
_environ_rmutex STORAGE
_iop_rmutex STORAGE
_rpcnls_rmutex STORAGE
_switch_rmutex STORAGE
_mem_rmutex STORAGE
_dir_rmutex STORAGE

The shl_unload and cxxshl_unload Routines

Unloads or frees up space for a shared library.

Syntax

int shl_unload(shl_t handle)

Parameters

handle

The handle of the shared library you wish to unload. The handle value is obtained from a previous call to shl_load, shl_findsym, or shl_get.

Return Value

If successful, shl_unload returns 0. Otherwise, shl_unload returns -1 and sets errno to an appropriate value:

EINVAL

Indicates the specified handle is invalid.

Description

To unload a shared library, use the shl_unload function. One reason to do this is to free up the private copy of shared library data and swap space allocated when the library was loaded with shl_load. (This is done automatically when a process exits.)

Another reason for doing this occurs if a program needs to replace a shared library. For example, suppose you implement some sort of shell or interpreter, and you want to load and execute user "programs" which are actually shared libraries. So you load one program, look up its entry point, and call it. Now you want to run a different program. If you do not unload the old one, its symbol definitions might get in the way of the new library. So you should unload it before loading the new library.

Note that if shared library initializers have been declared for a shared library, they will be called when the shared library is explicitly unloaded. For details, see “Initializers for Shared Libraries”.

If unloading a C++ library, use the cxxshl_unload routine. This ensures that destructors of nonlocal static objects are executed when the library is unloaded. The syntax of cxxshl_unload is the same as that of shl_unload.

Usage

When a library is unloaded, existing linkages to symbols in an unloaded library are not invalidated. Therefore, the programmer must ensure that the program does not reference symbols in an unloaded library as undefined behavior will result. In general, this routine is recommended only for experienced programmers.

In 32-bit mode the shl_unload routine unloads a shared library irrespective of whether other shared libraries depend on it. In 64-bit mode shl_unload unloads a shared library only if no other shared library depend on it.

Printable version
Privacy statement Using this site means you accept its terms Feedback to webmaster
© 1997 Hewlett-Packard Development Company, L.P.