Oracle® Solaris 11.2 Linkers and Libraries Guide

Exit Print View

Updated: July 2014
 
 

Generating Auxiliary Filters

To generate an auxiliary filter, you first define a filtee on which the filtering is applied. The following example builds a filtee filtee.so.1, supplying the symbol foo.

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

Auxiliary filtering can be provided in one of two ways. To declare all of the interfaces offered by a shared object to be auxiliary filters, use the link-editor's –f option. To declare individual interfaces of a shared object to be auxiliary filters, use a link-editor mapfile and the AUXILIARY keyword.

In the following example, the shared object filter.so.1 is defined to be an auxiliary filter. filter.so.1 offers the symbols foo and bar, and is an auxiliary filter on the filtee filtee.so.1. In this example, the environment variable LD_OPTIONS is used to circumvent the compiler driver from interpreting the –f option.

$ cat filter.c
char *bar = "defined in filter";

char *foo()
{
        return ("defined in filter");
}
$ LD_OPTIONS='-f filtee.so.1' \
cc -o filter.so.1 -G -K pic -h filter.so.1 -R. filter.c
$ elfdump -d filter.so.1 | egrep "SONAME|AUXILIARY"
     [2]  SONAME           0xee     filter.so.1
     [3]  AUXILIARY        0xfb     filtee.so.1

The link-editor can reference the auxiliary filter filter.so.1 as a dependency when creating a dynamic executable or shared object. The link-editor uses information from the symbol table of the filter to satisfy any symbol resolution. However, at runtime, any reference to the symbols of the filter result in a search for the filtee filtee.so.1. If this filtee is found, the runtime linker uses the filtee to resolve any symbols defined by filter.so.1. If the filtee is not found, or a symbol from the filter is not found in the filtee, then the original symbol within the filter is used.

For example, the following dynamic executable prog, references the symbols foo and bar, which are resolved during link-edit from the filter filter.so.1. The execution of prog results in foo being obtained from the filtee filtee.so.1, not from the filter filter.so.1. However, bar is obtained from the filter filter.so.1, as this symbol has no alternative definition in the filtee filtee.so.1.

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

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

In the following example, the shared object filter.so.2 defines the interface foo, to be an auxiliary filter on the filtee filtee.so.1.

$ cat filter.c
char *bar = "defined in filter";

char *foo()
{
        return ("defined in filter");
}
$ cat mapfile
$mapfile_version 2
SYMBOL_SCOPE {
        global:
                foo     { AUXILIARY=filtee.so.1 };
};
$ cc -o filter.so.2 -G -K pic -h filter.so.2 -M mapfile -R. filter.c
$ elfdump -d filter.so.2 | egrep "SONAME|AUXILIARY"
     [2]  SONAME           0xd8     filter.so.2
     [3]  SUNW_AUXILIARY   0xfb     filtee.so.1
$ elfdump -y filter.so.2 | egrep "foo|bar"
     [1]  A    [3] filtee.so.1      foo
    [10]  D        <self>           bar

At runtime, any reference to the symbol foo of the filter, results in a search for the filtee filtee.so.1. If the filtee is found, the filtee is loaded. The filtee is then used to resolve the symbol foo defined by filter.so.2. If the filtee is not found, symbol foo defined by filter.so.2 is used. Reference to the symbol bar always uses the symbol from filter.so.2, as no filtee processing is defined for this symbol.

For example, the following dynamic executable prog, references the symbols foo and bar, which are resolved during link-edit from the filter filter.so.2. If the filtee filtee.so.1 exists, the execution of prog results in foo being obtained from the filtee filtee.so.1, and bar being obtained from the filter filter.so.2.

$ cc -o prog main.c -R. filter.so.2
$ prog
foo is defined in filtee: bar is defined in filter

If the filtee filtee.so.1 does not exist, the execution of prog results in foo and bar being obtained from the filter filter.so.2.

$ prog
foo is defined in filter: bar is defined in filter

In these examples, the filtee filtee.so.1 is uniquely associated to the filter. The filtee is not available to satisfy symbol lookup from any other objects that might be loaded as a consequence of executing prog.

Auxiliary filters provide a mechanism for defining an alternative interface of an existing shared object. This mechanism is used in the Oracle Solaris OS to provide optimized functionality within hardware capability, and platform specific shared objects. See Capability Specific Shared Objects, Instruction Set Specific Shared Objects, and System Specific Shared Objects for examples.


Note - The environment variable LD_NOAUXFLTR can be set to disable the runtime linkers auxiliary filter processing. Because auxiliary filters are frequently employed to provide platform specific optimizations, this option can be useful in evaluating filtee use and their performance impact.