Specifying a Version Binding

When creating a dynamic object that is linked against a shared object containing version definitions, you can instruct the link-editor to limit the binding to specific version definitions. Effectively, the link-editor enables you to control an object's binding to specific interfaces.

An object's binding requirements can be controlled using a DEPEND_VERSIONS mapfile directive. This directive is supplied using the link-editor's -M option and an associated mapfile. The DEPEND_VERSIONS directive uses the following syntax.

        $mapfile_version 2
        DEPEND_VERSIONS objname {
                ALLOW   = version_name;
                REQUIRE = version_name;
                ....
        };
  • objname represents the name of the shared object dependency. This name should match the shared object's compilation environment name as used by the link-editor. See Library Naming Conventions.

  • The ALLOW attribute is used to specify version definition names within the shared object that should be made available for binding. Multiple ALLOW attributes can be specified.

  • The REQUIRE attribute allows additional version definitions to be recorded. Multiple REQUIRE attributes can be specified.

The control of version binding can be useful in the following scenarios.

  • When a shared object defines independent, unique versions. This versioning is possible when defining different standards interfaces. An object can be built with binding controls to ensure the object only binds to a specific interface.

  • When a shared object has been versioned over several software releases. An object can be built with binding controls to restrict its binding to the interfaces that were available in a previous software release. Thus, an object can run with an old release of the shared object dependency, after being built using the latest release of the shared object.

The following example illustrates the use of the version control mechanism. This example uses the shared object libfoo.so.1 containing the following version interface definitions.

$ pvs -dsv libfoo.so.1
        libfoo.so.1:
                _end;
                _GLOBAL_OFFSET_TABLE_;
                _DYNAMIC;
                _edata;
                _PROCEDURE_LINKAGE_TABLE_;
                _etext;
        SUNW_1.1:
                foo1;
                foo2;
                SUNW_1.1;
        SUNW_1.2:           {SUNW_1.1}:
                bar;

The version definitions SUNW_1.1 and SUNW_1.2 represent interfaces within libfoo.so.1 that were made available in software Release X and Release X+1 respectively.

An application can be built to bind only to the interfaces available in Release X by using the following version control mapfile directive.

$ cat mapfile
$mapfile_version 2
DEPEND_VERSIONS libfoo.so {
        ALLOW = SUNW_1.1;
}

For example, suppose you develop an application, prog, and want to ensure that the application can run on Release X. The application must only use the interfaces available in Release X. If the application mistakenly references the symbol bar, then the application is not compliant with the required interface. This condition is signalled by the link-editor as an undefined symbol error.

$ cat prog.c
extern void foo1();
extern void bar();

main()
{
        foo1();
        bar();
}
$ cc -o prog prog.c -M mapfile -L. -R. -lfoo
Undefined           first referenced
 symbol                 in file
bar                     prog.o  (symbol belongs to unavailable \
                        version ./libfoo.so (SUNW_1.2))
ld: fatal: symbol referencing errors

To be compliant with the SUNW_1.1 interface, you must remove the reference to bar. You can either rework the application to remove the requirement on bar, or add an implementation of bar to the creation of the application.

Note:

By default, shared object dependencies encountered as part of a link-edit, are also verified against any file control directives. Use the environment variable LD_NOVERSION to suppress the version verification of any shared object dependencies.