Linker and Libraries Guide

Generating a Standard Filter

First let's define a filtee, libbar.so.1, on which this filter technology will be applied. This filtee might be built from several relocatable objects. One of these objects originates from the file bar.c, and supplies the symbols foo and bar:


$ cat bar.c
char * bar = "bar";

char * foo()
{
    return("defined in bar.c");
}
$ cc -o libbar.so.1 -G -K pic .... bar.c ....

A standard filter, libfoo.so.1, is generated for the symbols foo and bar, and indicates the association to the filtee libbar.so.1. For example:


$ cat foo.c
char * bar = 0;

char * foo(){}

$ LD_OPTIONS='-F libbar.so.1' \
cc -o libfoo.so.1 -G -K pic -h libfoo.so.1 -R. foo.c
$ ln -s libfoo.so.1 libfoo.so
$ dump -Lv libfoo.so.1 | egrep "SONAME|FILTER"
[1]     SONAME   libfoo.so.1
[2]     FILTER   libbar.so.1

Note -

Here, the environment variable LD_OPTIONS is used to circumvent this compiler driver from interpreting the -F option as one of its own.


If the link-editor references the standard filter libfoo.so.1 to build a dynamic executable or shared object, it will use the information from the filter's symbol table during symbol resolution (see "Symbol Resolution" for more details).

At runtime, any reference to the symbols of the filter will result in the additional loading of the filtee libbar.so.1. The runtime linker will use this filtee to resolve any symbols defined by libfoo.so.1.

For example, the following dynamic executable, prog, references the symbols foo and bar, which are resolved during link-edit from the filter libfoo.so.1:


$ cat main.c
extern char * bar, * foo();

main(){
    (void) printf("foo() is %s: bar=%s\n", foo(), bar);
}
$ cc -o prog main.c -R. -L. -lfoo
$ prog
foo() is defined in bar.c: bar=bar

The execution of the dynamic executable prog results in the function foo(), and the data item bar, being obtained from the filtee libbar.so.1, not from the filter libfoo.so.1.


Note -

In this example, the filtee libbar.so.1 is uniquely associated to the filter libfoo.so.1 and is not available to satisfy symbol lookup from any other objects that might be loaded as a consequence of executing prog.


Standard filters provide a mechanism for defining a subset interface of an existing shared object, or an interface group spanning a number of existing shared objects. Two filters used in Solaris are /usr/lib/libsys.so.1 and /usr/lib/libdl.so.1.

The former provides a subset of the standard C library /usr/lib/libc.so.1. This subset represents the ABI-conforming functions and data items that reside in the C library that must be imported by a conforming application.

The latter defines the user interface to the runtime linker itself. This interface provides an abstraction between the symbols referenced in a compilation environment (from libdl.so.1) and the actual implementation binding produced within the runtime environment (from ld.so.1).

An example of a filter that uses mutiple filtees is /usr/lib/libxnet.so.1. This library provides socket and XTI interfaces from /usr/lib/libsocket.so.1, /usr/lib/libnsl.so.1, and /usr/lib/libc.so.1.

As any code in a standard filter is never referenced at runtime; there is no point in adding content to any functions defined within the filter. Any filter code might require relocation, which will result in an unnecessary overhead when processing the filter at runtime. Functions are best defined as empty routines.

Care should also be taken when generating the data symbols within a filter. Data items should always be initialized to ensure that they result in references from dynamic executables.

Some of the more complex symbol resolutions carried out by the link-editor require knowledge of a symbol's attributes, including the symbols size (see "Symbol Resolution" for more details). Therefore, it is recommended that the symbols in the filter be generated so that their attributes match those of the symbols in the filtee. This ensures that the link-editing process will analyze the filter in a manner compatible with the symbol definitions used at runtime.