The -B local option can be used to assert the auto-reduction directive "*" from the command line. Thus, the previous example could be compiled successfully with:
$ cc -o lib.so.1 -M mapfile -B local -G foo.c bar.c |
When generating an executable or shared object, any symbol reduction results in the recording of version definitions within the output image, together with the reduction of the appropriate symbols. When generating a relocatable object, the version definitions are created but the symbol reductions are not processed. The result is that the symbol entries for any symbol reductions still remain global. For example, using the previous mapfile with the auto-reduction directive and associated relocatable objects, an intermediate relocatable object is created that shows no symbol reduction.
$ cat mapfile lib.so.1.1 { global: foo; local: *; }; $ ld -o lib.o -M mapfile -r foo.o bar.o $ nm -x lib.o | egrep "foo$|bar$|str$" [17] |0x00000000|0x00000004|OBJT |GLOB |0x0 |3 |str [19] |0x00000028|0x00000028|FUNC |GLOB |0x0 |1 |bar [20] |0x00000000|0x00000028|FUNC |GLOB |0x0 |1 |foo |
The version definitions created within this image show that symbol reductions are required. When the relocatable object is used eventually to generate an executable or shared object, the symbol reductions occur. In other words, the link-editor reads and interprets symbol reduction information contained in relocatable objects in the same manner as it processes the data from a mapfile.
Thus, the intermediate relocatable object produced in the previous example can now be used to generate a shared object:
$ ld -o lib.so.1 -G lib.o $ nm -x lib.so.1 | egrep "foo$|bar$|str$" [22] |0x000104a4|0x00000004|OBJT |LOCL |0x0 |14 |str [24] |0x000003dc|0x00000028|FUNC |LOCL |0x0 |8 |bar [36] |0x000003b4|0x00000028|FUNC |GLOB |0x0 |8 |foo |
Symbol reduction at the point at which an executable or shared object is created is typically the most common requirement. However, symbol reductions can be forced to occur when creating a relocatable object by using the link-editor's -B reduce option.
$ ld -o lib.o -M mapfile -B reduce -r foo.o bar.o $ nm -x lib.o | egrep "foo$|bar$|str$" [15] |0x00000000|0x00000004|OBJT |LOCL |0x0 |3 |str [16] |0x00000028|0x00000028|FUNC |LOCL |0x0 |1 |bar [20] |0x00000000|0x00000028|FUNC |GLOB |0x0 |1 |foo |
Symbol Elimination
An extension to symbol reduction is the elimination of a symbol entry from an object's symbol table. Local symbols are only maintained in an object's .symtab symbol table. This entire table can be removed from the object using the link-editor's -s option, or strip(1). On occasion, you might want to maintain the .symtab symbol table but remove selected local symbol definitions from it.
Symbol elimination can be carried out using the mapfile directive eliminate. As with the local directive, symbols can be individually defined, or the symbol name can be defined as the special auto-elimination directive "*". The following example shows the elimination of the symbol bar for the previous symbol reduction example.
$ cat mapfile lib.so.1.1 { global: foo; local: str; eliminate: *; }; $ cc -o lib.so.1 -M mapfile -G foo.c bar.c $ nm -x lib.so.1 | egrep "foo$|bar$|str$" [31] |0x00010428|0x00000004|OBJT |LOCL |0x0 |12 |str [35] |0x00000348|0x00000028|FUNC |GLOB |0x0 |6 |foo |
The -B eliminate option can be used to assert the auto-elimination directive "*" from the command line.
External Bindings
When a symbol reference from the object being created is satisfied by a definition within a shared object, the symbol remains undefined and its associated relocation information provides for its lookup at runtime. The shared object that provided the definition typically becomes a dependency.
The runtime linker employs a default search model to locate this definition at runtime. It typically searches each object, starting with the dynamic executable, and progressing through each dependency in the same order in which the objects were loaded.
Objects can also be created using the link-editor's -B direct option. With this option the relationship between the referenced symbol and the object that provides the symbol's definition is maintained within the object being created. Using this information, the runtime linker can directly bind the reference to the object that defines the symbol, thus bypassing the default symbol search model. Direct binding information can only be established to dependencies specified with the link-edit. Therefore, use of the -z defs option is recommended. This direct binding can significantly reduce runtime symbol lookup processing. See "Direct Binding" for more details on this runtime binding model.
Generating the Output File
After all input file processing and symbol resolution is completed with no fatal errors, the link-editor can start generating the output file. The link-editor establishes the additional sections that must be generated to complete the output file. These sections include the symbol tables that contain local symbol definitions from the input files, together with the global and weak symbol information that has been collected in the link-editor's internal symbol table.
Also included are any output relocation and dynamic information sections required by the runtime linker. After all the output section information has been established, the total output file size is calculated and the output file image is created accordingly.
When creating a dynamic executable or shared object, two symbol tables are usually generated. The .dynsym table and its associated string table .dynstr contain register (even if these are local), global, weak, and section symbols. These sections become part of the text segment that is mapped as part of the process image at runtime (see the mmap(2) man page). This enables the runtime linker to read these sections and perform any necessary relocations.
The .symtab table, and its associated string table .strtab contain all the symbols collected from the input file processing. These sections are not mapped as part of the process image. They can even be stripped from the image using the link-editor's -s option, or after the link-edit using strip(1).
During the generation of the symbol tables, reserved symbols are created. These symbols have special meaning to the linking process and should not be defined in your code.
- _etext
- _edata
- _end
- _DYNAMIC
The address of the dynamic information section (the .dynamic section).
- _END_
The same as _end. The symbol has local scope and, together with _START_, provides a means of establishing an object's address range.
- _GLOBAL_OFFSET_TABLE_
The position-independent reference to a link-editor supplied table of addresses, the .got section. This table is constructed from position-independent data references occurring in objects that have been compiled with the -K pic option. See "Position-Independent Code".
- _PROCEDURE_LINKAGE_TABLE_
The position-independent reference to a link-editor supplied table of addresses, the .plt section. This table is constructed from position-independent function references occurring in objects that have been compiled with the -K pic option. See "Position-Independent Code".
- _START_
The first location within the text segment. The symbol has local scope and, together with _END_, provides a means of establishing an object's address range.
When generating an executable, the link-editor looks for additional symbols to define the executable's entry point. If a symbol was specified using the link-editor's -e option, that symbol is used. Otherwise the link-editor looks for the reserved symbol names _start, and then main. If none of these symbols exists, the first address of the text segment is used.
Relocation Processing
After you have created the output file, all data sections from the input files are copied to the new image. Any relocations specified by the input files are applied to the output image. Any additional relocation information that must be generated is also written to the new image.
Relocation processing is normally uneventful, although error conditions might arise that are accompanied by specific error messages. Two conditions are worth more discussion. The first condition involves text relocations that result from position-dependent code. This condition is covered in more detail in "Position-Independent Code". The second condition can arise from displacement relocations, which is described more fully in the next section.
Displacement Relocations
Error conditions might occur if displacement relocations are applied to a data item, which itself can be used in a copy relocation. The details of copy relocations are covered in "Copy Relocations".
A displacement relocation remains valid when both the relocated offset and the target to which it is relocated remain separated by the same displacement. A copy relocation is one where a global data item within a shared object is copied to the .bss of an executable, to preserve the executable's read-only text segment. If the copied data has a displacement relocation applied to it, or an external relocation is a displacement into the copied data, the displacement relocation becomes invalidated.
The areas to address in trying to catch these sorts of errors are:
When generating a shared object, flag any potential copy relocatable data items that can be problematic if they are involved in a displacement relocation. During construction of a shared object, the link-editor has no knowledge of what references might be made to it. Thus, all that can be flagged are potential problems.
When generating an executable, flag the creation of a copy relocation whose data is involved in a displacement relocation.
However, displacement relocations applied to a shared object might be completed during its creation at link-edit time. Therefore a link-edit of an application that references this shared object has no knowledge of a displacement being in effect in any copy-relocated data.
To help diagnose these problem areas, the link-editor indicates the displacement relocation use of a dynamic object with one or more dynamic DT_FLAGS_1 flags, as shown in Table 7-44. In addition, the link-editor's -z verbose option can be used to display suspicious relocations.
For example, say you create a shared object with a global data item, bar[], which has a displacement relocation applied to it. This item could be copy-relocated if referenced from a dynamic executable. The link-editor warns of this condition with:
$ cc -G -o libfoo.so.1 -z verbose -Kpic foo.o ld: warning: relocation warning: R_SPARC_DISP32: file foo.o: symbol foo: \ displacement relocation to be applied to the symbol bar: at 0x194: \ displacement relocation will be visible in output image |
If you now create an application that references the data item bar[], a copy relocation will be created which results in the displacement relocation being invalidated. Because the link-editor can explicitly discover this situation, an error message is generated regardless of the use of the -z verbose option.
$ cc -o prog prog.o -L. -lfoo ld: warning: relocation error: R_SPARC_DISP32: file foo.so: symbol foo: \ displacement relocation applied to the symbol bar at: 0x194: \ the symbol bar is a copy relocated symbol |
Note - ldd(1), when used with either the -d or -r options, uses the displacement dynamic flags to generate similar relocation warnings.
These error conditions can be avoided by ensuring that the symbol definition being relocated (offset) and the symbol target of the relocation are both local. Use static definitions or the link-editor's scoping technology. See "Reducing Symbol Scope". Relocation problems such as these can be avoided by accessing data within shared objects using functional interfaces.