Linker and Libraries Guide

Defining Additional Symbols

Besides the symbols provided from input files, you can supply additional global symbol references or global symbol definitions to a link-edit. In the simplest form, symbol references can be generated using the link-editor's -u option. Greater flexibility is provided with the link-editor's -M option and an associated mapfile. This mapfile enables you to define global symbol references and a variety of global symbol definitions.

Defining Additional Symbols with the u option

The -u option provides a mechanism for generating a global symbol reference from the link-edit command line. This option can be used to perform a link-edit entirely from archives. This option can also provide additional flexibility in selecting the objects to extract from multiple archives. See section Archive Processing for an overview of archive extraction.

For example, perhaps you want to generate a dynamic executable from the relocatable object main.o, which refers to the symbols foo and bar. You want to obtain the symbol definition foo from the relocatable object foo.o contained in lib1.a, and the symbol definition bar from the relocatable object bar.o, contained in lib2.a.

However, the archive lib1.a also contains a relocatable object that defines the symbol bar. This relocatable object is presumably of differing functionality to the relocatable object that is provided in lib2.a. To specify the required archive extraction, you can use the following link-edit.


$ cc -o prog -L. -u foo -l1 main.o -l2

The -u option generates a reference to the symbol foo. This reference causes extraction of the relocatable object foo.o from the archive lib1.a. The first reference to the symbol bar occurs in main.o, which is encountered after lib1.a has been processed. Therefore, the relocatable object bar.o is obtained from the archive lib2.a.


Note –

This simple example assumes that the relocatable object foo.o from lib1.a does not directly or indirectly reference the symbol bar. If lib1.a does reference bar, then the relocatable object bar.o is also extracted from lib1.a during its processing. See Archive Processing for a discussion of the link-editor's multi-pass processing of an archive.


Defining Additional Symbols with a mapfile

An extensive set of global symbol definitions can be provided by using the link-editor's -M option and an associated mapfile. Symbol definition mapfile entries have the following syntax.


[ name ] {
      scope:
            symbol [ = [ type ] [ value ] [ size ] [ information ] ];
} [ dependency ];
name

A label for this set of symbol definitions, if present, identifies a version definition within the image. See Chapter 5, Application Binary Interfaces and Versioning.

scope

Indicates the visibility of the symbols' binding within the output file being generated. All symbols defined with a mapfile are treated as global in scope during the link-edit process. These symbols are resolved against any other global symbols of the same name that are obtained from any of the input files. The following definitions, and aliases, define a symbols' visibility in the object being created.

default / global

Global symbols of this scope are visible to all external objects. References to such symbols from within the object are bound at runtime, thus allowing interposition to take place. This visibility scope provides a default, that can be demoted, or eliminated by other symbol visibility techniques. This scope definition has the same affect as a symbol with STV_DEFAULT visibility. See Table 7–20.

protected / symbolic

Global symbols of this scope are visible to all external objects. References to these symbols from within the object are bound at link-edit, thus preventing runtime interposition. This visibility scope can be demoted, or eliminated by other symbol visibility techniques. This scope definition has the same affect as a symbol with STV_PROTECTED visibility. See Table 7–20.

If an object is created with a single symbolic scope, all relocations within the object are bound to the object at link-edit. With this single scope, even reserved symbols are reduced to symbolic scope. See Generating the Output File for a list of reserved symbol names.

hidden / local

Global symbols of this scope are reduced to symbols with a local binding. Symbols of this scope are not visible to other external objects. This scope definition has the same affect as a symbol with STV_HIDDEN visibility. See Table 7–20.

eliminate

Global symbols of this scope are hidden. Their symbol table entries are eliminated. Note that local symbols can also be eliminated by using the link-editor -z redlocsym option.


Note –

The STV_ symbol visibility attributes, originate from symbol declarations that are embedded in source code that are processed by the compilers.


symbol

A symbol name. This name can result in a symbol definition, or a symbol reference, depending on any qualifying attributes. In the simplest form, without any qualifying attributes, a symbol reference is created. This reference is exactly the same as would be generated using the -u option discussed in Defining Additional Symbols with the u option. Typically, if the symbol name is followed by any qualifying attributes, then a symbol definition is generated using the associated attributes.

When a local scope is defined, the symbol name can be defined as the special auto-reduction directive “*”. Symbols that have no explicitly defined visibility are demoted to a local binding within the dynamic object being generated. Explicit visibility definitions originate from mapfile definitions, or visibility definitions that are encapsulated within relocatable objects.

Similarly, when an eliminate scope is defined, the symbol name can be defined as the special auto-elimination directive “*”. Symbols that have no explicitly defined visibility are eliminated from the dynamic object being generated.

type

Indicates the symbol type attribute. This attribute can be either COMMON, data, or function. The COMMON attribute results in a tentative symbol definition. The data and function attributes result in a section symbol definition or an absolute symbol definition. See Symbol Table Section.

A data attribute results in the creation of an OBJT symbol. A data attribute that is accompanied with a size, but no value creates a section symbol by associating the symbol with an ELF section. This section is filled with zeros.

A function attribute results in the creation of an FUNC symbol. A function attribute that is accompanied with a size, but no value creates a section symbol by associating the symbol with an ELF section. This section is assigned a void function return, void (*)(void).

A data or function attribute that is accompanied with a value results in the appropriate symbol type together with an absolute, ABS, section index.

The creation of a section data symbol is useful for the creation of filters. External references to a section data symbol of a filter from an executable result in the appropriate copy relocation being generated. See Copy Relocations.

value

Indicates the value attribute. This attribute takes the form of Vnumber. This attribute results in the creation of a symbol definition.

size

Indicates the size attribute. This attribute takes the form of Snumber. This attribute results in the creation of a symbol definition.

information

This keyword provides additional information for the symbol.

AUXILIARY name

Indicates that this symbol is an auxiliary filter on the shared object name. See Generating Auxiliary Filters.

DIRECT

Indicates that this symbol should be directly bound to. When used with a symbol definition, this keyword results in any reference from within the object being built to be directly bound to the definition. When used with a symbol reference, this keyword results in a direct binding to the dependency that provides the definition. See Direct Bindings. This keyword can also be used with the PARENT keyword to establish a direct binding to any parent at runtime.

EXTERN

Indicates the symbol is defined externally to the object being created. This keyword is typically defined to label callback routines. Undefined symbols that would be flagged with the -z defs option are suppressed with this keyword.

This keyword is only meaningful when generating a symbol reference. Should a definition for this symbol occur within the objects combined at link-edit, then the keyword is silently ignored.

FILTER name

Indicates that this symbol is a filter on the shared object name. See Generating Standard Filters. Filter symbols do not require any backing implementation to be provided from an input relocatable object. Therefore, use this directive together with defining the symbol's type, to create an absolute symbol table entry.

NODIRECT

Indicates that this symbol should not be directly bound to. This state applies to references from within the object being created and from external references. See Direct Bindings. This keyword can also be used with the PARENT keyword to prevent a direct binding to any parent at runtime.

PARENT

Indicates the symbol is defined in the parent of the object being created. A parent is an object that references this object at runtime as an explicit dependency. A parent can also reference this object at runtime using dlopen(3C). This keyword is typically defined to label callback routines. This keyword can be used with the DIRECT or NODIRECT keywords to establish individual direct, or no-direct references to the parent. Undefined symbols that would be flagged with the -z defs option are suppressed with this keyword.

This keyword is only meaningful when generating a symbol reference. Should a definition for this symbol occur within the objects combined at link-edit, then the keyword is silently ignored.

dependency

Represents a version definition that is inherited by this definition. See Chapter 5, Application Binary Interfaces and Versioning.

If either a version definition or the auto-reduction directive is specified, then versioning information is recorded in the image created. If this image is an executable or shared object, then any symbol reduction is also applied.

If the image being created is a relocatable object, then by default, no symbol reduction is applied. In this case, any symbol reductions are recorded as part of the versioning information. These reductions are applied when the relocatable object is finally used to generate an executable or shared object. The link-editor's -B reduce option can be used to force symbol reduction when generating a relocatable object.

A more detailed description of the versioning information is provided in Chapter 5, Application Binary Interfaces and Versioning.


Note –

To ensure interface definition stability, no wildcard expansion is provided for defining symbol names.


The following sections presents several examples of using the mapfile syntax.

Defining Symbol References

The following example shows how three symbol references can be defined. These references are then used to extract members of an archive. Although this archive extraction can be achieved by specifying multiple -u options to the link-edit, this example also shows how the eventual scope of a symbol can be reduced to local.


$ cat foo.c
void foo()
{
        (void) printf("foo: called from lib.a\n");
}
$ cat bar.c
void bar()
{
        (void) printf("bar: called from lib.a\n");
}
$ cat main.c
extern  void    foo(), bar();

void main()
{
        foo();
        bar();
}
$ ar -rc lib.a foo.o bar.o main.o
$ cat mapfile
{
        local:
                foo;
                bar;
        global:
                main;
};
$ cc -o prog -M mapfile lib.a
$ prog
foo: called from lib.a
bar: called from lib.a
$ nm -x prog | egrep "main$|foo$|bar$"
[28]    |0x00010604|0x00000024|FUNC |LOCL |0x0  |7      |foo
[30]    |0x00010628|0x00000024|FUNC |LOCL |0x0  |7      |bar
[49]    |0x0001064c|0x00000024|FUNC |GLOB |0x0  |7      |main

The significance of reducing symbol scope from global to local is covered in more detail in the section Reducing Symbol Scope.

Defining Absolute Symbols

The following example shows how two absolute symbol definitions can be defined. These definitions are then used to resolve the references from the input file main.c.


$ cat main.c
extern  int     foo();
extern  int     bar;

void main()
{
        (void) printf("&foo = %x\n", &foo);
        (void) printf("&bar = %x\n", &bar);
}
$ cat mapfile
{
        global:
                foo = FUNCTION V0x400;
                bar = DATA V0x800;
};
$ cc -o prog -M mapfile main.c
$ prog
&foo = 400
&bar = 800
$ nm -x prog | egrep "foo$|bar$"
[37]    |0x00000800|0x00000000|OBJT |GLOB |0x0  |ABS    |bar
[42]    |0x00000400|0x00000000|FUNC |GLOB |0x0  |ABS    |foo

When obtained from an input file, symbol definitions for functions or data items are usually associated with elements of data storage. A mapfile definition is insufficient to be able to construct this data storage, so these symbols must remain as absolute values. A simple mapfile definition that is associated with a size, but no value results in the creation of data storage. In this case, the symbol definition is accompanied with a section index. However, a mapfile definition that is accompanied with a value results in the creation of an absolute symbol. If a symbol is defined in a shared object, an absolute definition should be avoided. See Augmenting a Symbol Definition.

Defining Tentative Symbols

A mapfile can also be used to define a COMMON, or tentative, symbol. Unlike other types of symbol definition, tentative symbols do not occupy storage within a file, but define storage that must be allocated at runtime. Therefore, symbol definitions of this kind can contribute to the storage allocation of the output file being generated.

A feature of tentative symbols that differs from other symbol types is that their value attribute indicates their alignment requirement. A mapfile definition can therefore be used to realign tentative definitions that are obtained from the input files of a link-edit.

The following example shows the definition of two tentative symbols. The symbol foo defines a new storage region whereas the symbol bar is actually used to change the alignment of the same tentative definition within the file main.c.


$ cat main.c
extern  int     foo;
int             bar[0x10];

void main()
{
        (void) printf("&foo = %x\n", &foo);
        (void) printf("&bar = %x\n", &bar);
}
$ cat mapfile
{
        global:
                foo = COMMON V0x4 S0x200;
                bar = COMMON V0x100 S0x40;
};
$ cc -o prog -M mapfile main.c
ld: warning: symbol `bar' has differing alignments:
        (file mapfile value=0x100; file main.o value=0x4);
        largest value applied
$ prog
&foo = 20940
&bar = 20900
$ nm -x prog | egrep "foo$|bar$"
[37]    |0x00020900|0x00000040|OBJT |GLOB |0x0  |16     |bar
[42]    |0x00020940|0x00000200|OBJT |GLOB |0x0  |16     |foo

Note –

This symbol resolution diagnostic can be suppressed by using the link-editor's -t option.


Augmenting a Symbol Definition

The creation of an absolute data symbol within a shared object should be avoided. An external reference from a dynamic executable to a data item within a shared object typically requires the creation of a copy relocation. See Copy Relocations. To provide for this relocation, the data item should be associated with data storage. This association can be produced by defining the symbol within a relocatable object file. This association can also be produced by defining the symbol within a mapfile together with a size declaration and no value declaration. See Defining Additional Symbols with a mapfile.

A data symbol can be filtered. See Shared Objects as Filters. To provide this filtering, an object file definition can be augmented with a mapfile definition. The following example creates a filter containing a function and data definition.


$ cat mapfile
{
        global:
                foo = FUNCTION FILTER filtee.so.1;
                bar = DATA S0x4 FILTER filtee.so.1;
        local:
                *;
};
$ cc -o filter.so.1 -G -Kpic -h filter.so.1 -M mapfile -R.
$ nm -x filter.so.1 | egrep "foo|bar"
[39]    |0x000102b0|0x00000004|OBJT |GLOB |0    |12     |bar
[45]    |0x00000000|0x00000000|FUNC |GLOB |0    |ABS    |foo
$ elfdump -y filter.so.1 | egrep "foo|bar"
       [1]  F        [0] filtee.so.1        bar
       [7]  F        [0] filtee.so.1        foo

At runtime, a reference from an external object to either of these symbols is resolved to the definition within the filtee.