Generating Weak Filters

Standard filters provide a simple and effective solution to the problem of maintaining runtime compatibility while allowing the underlying system to evolve. However, filters also impose ongoing overhead. Although such a filter provides no functionality, it must be loaded and processed by the system every time the program runs. It is generally recommended that programs discontinue linking against these filters, and leave them for the benefit of old code that hasn't yet been rebuilt.

Eliminating unnecessary filters when building an object is the best solution when feasible. However, there are cases where this can be difficult to achieve. In particular, many open source packages have complicated configuration systems that are intended to work across a span of operating system versions. On some versions, a library may deliver necessary content, while on newer ones, they are mere filters. Rather then grapple with these complexities, the configuration simply links against everything. On Oracle Solaris, this frequently happens with libraries such as libpthread.

Weak filters, in conjunction with the -z discard-unused=dependencies command line option, offer an automated solution to this problem. Typically, the link-editor resolves external symbols from libraries by taking the symbol from the first library on the command line that provides a symbol definition. In the case of weak filters, such symbols are ignored if the filtee providing the same filter is also present on the command line. Resolving such symbols directly to the filtee allows unused dependency processing to eliminate the filter. This results in a simpler and more efficient object, without requiring large changes to the upstream code base.

The following example uses a filter object named libprint, which provides the standard printf() from libc.

$ cat mapfile-libprint-std
$mapfile_version 2
FILTER {
        FILTEE = "libc.so.1";
        TYPE = STANDARD;
};
SYMBOL_SCOPE {
    global:
        printf { TYPE = FUNCTION };
};
$ ld -o libprint.so.1 -G -h libprint.so.1 -Mmapfile-libprint-std
$ elfdump libprint.so.1 | egrep 'SONAME|FILTER'
      [0]  SONAME          0x1     libprint.so.1
      [1]  FILTER          0x4c    libc.so.1

An application built against libprint, requires that this filter be loaded at runtime even though the filtee libc contains the printf() function used at runtime.

$ cc hello.c -o hello -L. -R. libprint.so.1
$ elfdump -d hello | grep NEEDED
      [0]  NEEDED          0x13b      libprint.so.1
      [1]  NEEDED          0x125      libc.so.1
$ ./hello
hello, world

The libprint filter is rebuilt as a weak filter. The hello world program links to libprint as before, but with unused dependency processing enabled. The resulting program resolves printf() directly from libc. The link-editor is therefore able to discard the unused libprint dependency.

$ cat mapfile-libprint-weak
$mapfile_version 2
FILTER {
        FILTEE = "libc.so.1";
        TYPE = WEAK;
};
SYMBOL_SCOPE {
    global:
        printf { TYPE = FUNCTION };
};
$ ld -o libprint.so.1 -G -h libprint.so.1 -Mmapfile-libprint-weak
$ elfdump libprint.so.1 | egrep 'SONAME|FILTER'
      [0]  SONAME          0x1         libprint.so.1
      [1]  FILTER          0x4c        libc.so.1
     [14]  FLAGS_1         0x20000000  [ WEAKFILTER ]
$ cc hello.c -o hello -L. -R. libprint.so.1 -z discard-unused=dependencies
$ elfdump -d hello | grep NEEDED
      [0]  NEEDED          0x125      libc.so.1
$ ./hello
hello, world

In current versions of Oracle Solaris, libraries such as libpthread are built as weak filters instead of standard filters in order to enable the automatic removal of unnecessary filter dependencies when unused dependency processing is enabled with the -z discard-unused=dependencies option.

Note:

When the -z discard-unused=dependencies option is enabled, and the symbol resolution process determines that a weak filter symbol from a dependency is needed, the filtee for that symbol is added to the end of the link line as an additional dependency. This allows the link-editor to find the symbol from the filtee, and to eliminate the weak filter. Therefore, the runpath for a weak filter must be sufficient to allow the link-editor to find the filtee.