Linker and Libraries Guide

Defining Additional Symbols

Besides the symbols provided from input files, you can supply additional symbol references or 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 that enables you to define symbol references and a variety of symbol definitions.

The -u option provides a mechanism for generating a symbol reference from the link-edit command line. This option can be used to perform a link-edit entirely from archives, or to 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 defining the symbol bar. This relocatable object is presumably of differing functionality to the relocatable object 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 it does 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.


A more extensive set of symbol definitions can be provided using the link-editor's -M option and an associated mapfile. The syntax for these mapfile entries is:


[ name ] {
      scope:
            symbol [ = [ type ] [ value ] [ size ] [ extern ] ];
} [ 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. That is, they are resolved against any other symbols of the same name obtained from any of the input files. The following definitions, and aliases, define a symbols' visibility in the object being created:

default / global

Symbols of this scope remain visible to other external objects. References to such symbols from within the object are bound at runtime, thus allowing interposition to take place.

protected / symbolic

Symbols of this scope remain visible to other external objects. References to these symbols from within the object are bound at link-edit, thus preventing runtime interposition. This scope definition has the same affect as a symbol with STV_PROTECTED visibility. See Table 7–24.

hidden / local

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–24.

eliminate

Symbols of this scope are hidden. Their symbol table entries are eliminated.

symbol

The name of the symbol required. If the name is not followed by one of the symbol attributes, type, value, size or extern, a symbol reference is created. This reference is exactly the same as would be generated using the -u option discussed earlier in this section. If the symbol name is followed by any symbol attributes, then a symbol definition is generated using the associated attributes.

When in local scope, this symbol name can be defined as the special auto-reduction directive “*”. This directive results in all global symbols, not explicitly defined to be global in the mapfile, receiving a local binding within any dynamic object file being generated.

type

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

value

Indicates the value attribute and takes the form of Vnumber.

size

Indicates the size attribute and takes the form of Snumber.

extern

This keyword indicates the symbol is defined externally to the object being created. Undefined symbols flagged with the -z defs option can be suppressed with this option.

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.


This section presents several examples of using the mapfile syntax.

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
foo()
{
        (void) printf("foo: called from lib.a\n");
}
$ cat bar.c
bar()
{
        (void) printf("bar: called from lib.a\n");
}
$ cat main.c
extern  void    foo(), bar();

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.

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;

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.

However, 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 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];

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.