Go to main content

Oracle® Solaris 11.4 Linkers and Libraries Guide

Exit Print View

Updated: October 2019
 
 

Identifying Capability Requirements

System capabilities are the capabilities that describe a running system. The platform name, and machine hardware name can be displayed with uname(1) using the –i option and –m option respectively. The system hardware capabilities can be displayed with isainfo(1) using the –v option. At runtime, the platform name, machine hardware name, and hardware capability requirements of an object are compared against the system capabilities to determine whether the object can be loaded, or a symbol within the object can be used.

Object capabilities are capabilities that are associated with an object. These capabilities define the requirements of the entire object. The platform, machine, and hardware capabilities control whether the object can be loaded at runtime. If an object requires capabilities that can not be satisfied by the system, then the object can not be loaded at runtime. Capabilities can be used to provide more than one instance of a given object, each optimized for systems that match the objects requirements. The runtime linker can transparently select the best instance from such a family of object instances by comparing the objects capability requirements to the capabilities provided by the system.

Symbol capabilities are capabilities that are associated with individual functions, or initialized data items, within an object. The platform, machine, and hardware capabilities define the requirements of one or more symbols within an object, and control whether the symbol can be used at runtime. Symbol capabilities allow for the presence of multiple instances of a function within a single object. Each instance of the function can be optimized for a system with different capabilities. Symbol capabilities also allow for the presence of multiple instances of an initialized data item within an object. Each instance of the data can define system specific data. If a symbol instance requires capabilities that can not be satisfied by the system, then that symbol instance can not be used at runtime. Instead, an alternative instance of the same symbol name must be used. Symbol capabilities offer the ability to construct a single object that can be used on systems of varying abilities. A family of functions can provide optimized instances for systems that can support the capabilities, and more generic instances for other, less capable systems. A family of initialized data items can provide system specific data. The runtime linker transparently selects the best instance from such a family of symbol instances by comparing the symbols capability requirements to the capabilities provided by the system.

Object and symbol capabilities provide for selecting the best object, and the best symbol within an object, for the currently running system. Object and symbol capabilities are optional features, both independent of each other. However, an object that defines symbol capabilities may also define object capabilities. In this case, any family of capabilities symbols should be accompanied with one instance of the symbol that satisfies the object capabilities. If no object capabilities exist, any family of capability symbols should be accompanied with one instance of the symbol that requires no capabilities. This symbol instance provides the default implementation, should no capability instance be applicable for a given system.

The following x86 example displays the object capabilities of foo.o. These capabilities apply to the entire object. In this example, no symbol capabilities exist.

$ elfdump -H foo.o

Capabilities Section:  .SUNW_cap

 Object Capabilities:
     index  tag               value
       [0]  CA_SUNW_HW_1      0x840  [ SSE  MMX ]

The following x86 example displays the symbol capabilities of bar.o. These capabilities apply to the individual functions foo() and bar(). Two instances of each symbol exist, each instance being assigned to a different set of capabilities. In this example, no object capabilities exist.

$ elfdump -H bar.o

Capabilities Section:  .SUNW_cap

 Symbol Capabilities:
     index  tag               value
       [1]  CA_SUNW_HW_1      0x40  [ MMX ]

  Symbols:
     index    value     size  type bind oth ver shndx    name
      [25]        0     0x21  FUNC LOCL  D    0 .text    foo%mmx
      [26]     0x24     0x1e  FUNC LOCL  D    0 .text    bar%mmx

 Symbol Capabilities:
     index  tag               value
       [3]  CA_SUNW_HW_1      0x800  [ SSE ]

  Symbols:
     index    value     size  type bind oth ver shndx    name
      [33]     0x44     0x21  FUNC LOCL  D    0 .text    foo%sse
      [34]     0x68     0x1e  FUNC LOCL  D    0 .text    bar%sse

Note -  In this example, the capability symbols follow a naming convention that appends a capability identifier to the generic symbol name. This convention can be produced by the link-editor when object capabilities are converted to symbol capabilities, and is discussed later in Converting Object Capabilities to Symbol Capabilities.

Capability definitions provide for many combinations that allow you to identify the requirements of an object, or of individual symbols within an object.


Note -  Platform names and machine hardware names have converged into very few variations. Although these capability names originated to target specific machines, and have the highest precedence, their usefulness is now limited. Targeting code to a specific platform or machine can be useful in some instances, however the development of a hardware capabilities family can provide greater flexibility, and is recommended. Hardware capabilities families can provide for optimized code to be exercised on a broader range of systems.

The following sections describe how capabilities can be defined, and used by the link-editor.

Identifying a Platform and Machine Capability

The platform or machine capability of an object identifies the platform name or machine hardware name of the systems that the object, or specific symbols within the object, can execute upon. Multiple platform or machine capabilities can be defined. These identifications are very specific, and take precedence over any other capability types. These identifications can be used by specialized system libraries, however hardware capabilities typically provide a more flexible means of creating capabilities instances.

The platform name of a system can be displayed by the utility uname(1) with the –i option. A platform capability requirement can be defined using the following mapfile syntax.

    $mapfile_version 2
        CAPABILITY {
                PLATFORM  = platform_name...;
                PLATFORM += platform_name...;
                PLATFORM -= platform_name...;
        };

The machine hardware name of a system can be displayed by the utility uname(1) with the –m option. A machine capability requirement can be defined using the following mapfile syntax.

    $mapfile_version 2
        CAPABILITY {
                MACHINE  = machine_name...;
                MACHINE += machine_name...;
                MACHINE -= machine_name...;
        };

A PLATFORM or MACHINE attribute is qualified with one or more, space separated platform or machine names. The "+=" form of assignment augments the platform or machine capabilities specified by the input objects, while the "=" form overrides them. The "-=" form of assignment is used to exclude platform or machine capabilities from the output object.

The following SPARC example identifies the object foo.so.1 as being specific to the sun4v machine hardware name.

$ cat mapfile
$mapfile_version 2
CAPABILITY {
        MACHINE = sun4v;
};
$ cc -o foo.so.1 -G -K pic -Mmapfile foo.c -lc
$ elfdump -H foo.so.1

Capabilities Section:  .SUNW_cap

 Object Capabilities:
     index  tag               value
       [0]  CA_SUNW_MACH      sun4v

Relocatable objects can define platform and machine capabilities. These capabilities are gathered together to define the final capability requirements of the object being built.

The platform or machine capability of an object can be controlled explicitly from a mapfile by using the "=" form of assignment to override any platform or machine capabilities that might be provided from any input relocatable objects. An empty PLATFORM or MACHINE attribute used with the "=" form of assignment effectively removes any platform or machine capabilities requirement from the object being built.

A platform or machine capability requirement defined in a dynamic object is validated by the runtime linker against the platform and machine name of the system. The object is only used if one of the platform or machine names recorded in the object match the platform or machine name of the system.

Identifying Hardware Capabilities

The hardware capabilities of an object identify the hardware requirements of a system necessary for the object, or specific symbol, to execute correctly. An example of this requirement might be the identification of code that requires the MMX or SSE features that are available on x86 architectures.

Hardware capability requirements can be identified using the following mapfile syntax.

    $mapfile_version 2
        CAPABILITY {
                HW  = hwcap_flag...;
                HW += hwcap_flag...;
                HW -= hwcap_flag...;
        };

The HW attribute to the CAPABILITY directive is qualified with one or more tokens, which are symbolic representations of hardware capabilities. The "+=" form of assignment augments the hardware capabilities specified by the input objects, while the "=" form overrides them. The "-=" form of assignment is used to exclude hardware capabilities from the output object.

For SPARC systems, hardware capabilities are defined as AV_ values in sys/auxv_SPARC.h. For x86 systems, hardware capabilities are defined as AV_ values in sys/auxv_386.h.

The following x86 example shows the declaration of MMX and SSE as hardware capabilities required by the object foo.so.1.

$ egrep "MMX|SSE" /usr/include/sys/auxv_386.h
#define AV_386_MMX    0x0040
#define AV_386_SSE    0x0800
$ cat mapfile
$mapfile_version 2
CAPABILITY {
        HW += SSE MMX;
};
$ cc -o foo.so.1 -G -K pic -Mmapfile foo.c -lc
$ elfdump -H foo.so.1

Capabilities Section:  .SUNW_cap

 Object Capabilities:
     index  tag               value
       [0]  CA_SUNW_HW_1      0x840  [ SSE  MMX ]

Relocatable objects can contain hardware capabilities values. The link-editor combines any hardware capabilities values from multiple input relocatable objects. The resulting CA_SUNW_HW_1 value is a bitwise-inclusive OR of the associated input values. By default, these values are combined with the hardware capabilities specified by a mapfile.

The hardware capability requirements of an object can be controlled explicitly from a mapfile by using the "=" form of assignment to override any hardware capabilities that might be provided from any input relocatable objects. An empty HW attribute used with the "=" form of assignment effectively removes any hardware capabilities requirement from the object being built.

The following example suppresses any hardware capabilities data defined by the input relocatable object foo.o from being included in the output file, bar.o.

$ elfdump -H foo.o

Capabilities Section:  .SUNW_cap

 Object Capabilities:
     index  tag               value
       [0]  CA_SUNW_HW_1      0x840  [ SSE  MMX ]
$ cat mapfile
$mapfile_version 2
CAPABILITY {
        HW = ;
};
$ ld -o bar.o -r -Mmapfile foo.o
$ elfdump -H bar.o
$ 

Any hardware capability requirements defined by a dynamic object are validated by the runtime linker against the hardware capabilities that are provided by the system. If any of the hardware capability requirements can not be satisfied, the object is not loaded at runtime. For example, if the SSE feature is not available to a process, ldd(1) indicates the following error.

$ ldd prog
        foo.so.1 =>      ./foo.so.1  - hardware capability unsupported: 0x800 [ SSE ]
        ....

Multiple instances of a dynamic object that exploit different hardware capabilities can provide a flexible runtime environment using filters. See Capability Specific Shared Objects.

Hardware capabilities can also be used to identify the capabilities of individual functions within a single object. In this case, the runtime linker can select the most appropriate function instance to use based upon the current system capabilities. See Creating a Family of Symbol Capabilities Functions.

Identifying Software Capabilities

The software capabilities of an object identify characteristics of the software that might be important for debugging or monitoring processes. Software capabilities can also influence process execution. Currently, the only software capability that is recognized relates to process address space restrictions.

64-bit objects can indicate that at runtime they must be exercised within a 32-bit address space.

Software capabilities flags are defined in sys/elf.h.

#define  SF1_SUNW_ADDR32    0x004

Software capability requirements can be identified using the following mapfile syntax.

    $mapfile_version 2
        CAPABILITY {
                SF  = sfcap_flags...;
                SF += sfcap_flags...;
                SF -= sfcap_flags...;
        };

The SF attribute to the CAPABILITY directive can be assigned the token ADDR32.

Relocatable objects can contain software capabilities values. The link-editor combines the software capabilities values from multiple input relocatable objects. Software capabilities can also be supplied with a mapfile. By default, any mapfile values are combined with the values supplied by relocatable objects.

The software capability requirements of an object can be controlled explicitly from a mapfile by using the "=" form of assignment to override any software capabilities that might be provided from any input relocatable objects. An empty SF attribute used with the "=" form of assignment effectively removes any software capabilities requirement from the object being built.

The following example suppresses any software capabilities data defined by the input relocatable object foo.o from being included in the output file, bar.o.

$ elfdump -H foo.o

Object Capabilities:
    index  tag               value
      [0]  CA_SUNW_SF_1      0x4  [ ADDR32 ]
$ cat mapfile
$mapfile_version 2
CAPABILITY {
        SF = ;
};
$ ld -o bar.o -r -Mmapfile foo.o
$ elfdump -H bar.o
$ 

Software Capability Address Space Restriction Processing

64-bit objects that are identified with the SF1_SUNW_ADDR32 software capabilities flag can contain optimized code that requires a 32-bit address space. 64-bit objects that are identified in this manner can interoperate with any other 64-bit objects whether they are identified with the SF1_SUNW_ADDR32 flag or not. An occurrence of the SF1_SUNW_ADDR32 flag within a 64-bit input relocatable object is propagated to the CA_SUNW_SF_1 value that is created for the output file being created by the link-editor.

The existence of the SF1_SUNW_ADDR32 flag within a 64-bit executable ensures that the associated process is restricted to the lower 32-bit address space. This restricted address space includes the process stack and all process dependencies. Within such a process, all objects, whether they are identified with the SF1_SUNW_ADDR32 flag or not, are loaded within the restricted 32-bit address space.

64-bit shared objects can contain the SF1_SUNW_ADDR32 flag. However, the restricted address space requirement can only be established by a 64-bit executable containing the SF1_SUNW_ADDR32 flag. Therefore, a 64-bit SF1_SUNW_ADDR32 shared object must be a dependency of a 64-bit SF1_SUNW_ADDR32 executable.

A 64-bit SF1_SUNW_ADDR32 shared object that is encountered by the link-editor when building an unrestricted 64-bit executable results in a warning.

$ cc -m64 -o main main.c -lfoo
ld: warning: file libfoo.so: section .SUNW_cap: software capability ADDR32: \
    requires executable be built with ADDR32 capability

A 64-bit SF1_SUNW_ADDR32 shared object that is encountered at runtime by a process that is created from an unrestricted 64-bit executable, results in a fatal error.

$ ldd main
    libfoo.so =>     ./libfoo.so  - software capability unsupported: 0x4  [ ADDR32 ]
    ....
$ main
ld.so.1: main: fatal: ./libfoo.so: software capability unsupported: 0x4  [ ADDR32 ]

An executable can be seeded with the SF1_SUNW_ADDR32 using a mapfile.

$ cat mapfile
$mapfile_version 2
CAPABILITY {
        SF += ADDR32;
};
$ cc -m64 -o main main.c -Mmapfile -lfoo
$ elfdump -H main

Object Capabilities:
    index  tag               value
      [0]  CA_SUNW_SF_1      0x4  [ SF1_SUNW_ADDR32 ]