Linker and Libraries Guide

Position-Independent Code

The compiler can generate position-independent code under the -K pic option. Whereas the code within a dynamic executable is usually tied to a fixed address in memory, position-independent code can be loaded anywhere in the address space of a process. Because the code is not tied to a specific address, it will execute correctly without page modification at a different address in each process that uses it. This code creates programs that require the smallest amount of page modification at runtime.

When you use position-independent code, relocatable references are generated as an indirection that will use data in the shared object's data segment. The text segment code will remain read-only, and all relocation updates will be applied to corresponding entries within the data segment. See "Global Offset Table (Processor-Specific)" and "Procedure Linkage Table (Processor-Specific)" for more details on the use of these two sections.

If a shared object is built from code that is not position-independent, the text segment will usually require a large number of relocations to be performed at runtime. Although the runtime linker is equipped to handle this, the system overhead this creates can cause serious performance degradation.

You can identify a shared object that requires relocations against its text segment. Use dump(1) and inspect the output for any TEXTREL entry. For example:


$ cc -o libfoo.so.1 -G -R. foo.c
$ dump -Lv libfoo.so.1 | grep TEXTREL
[9]     TEXTREL  0

Note -

The value of the TEXTREL entry is irrelevant. Its presence in a shared object indicates that text relocations exist.


To prevent the creation of a shared object that contains text relocations use the link-editor's -z text flag. This flag causes the link-editor to generate diagnostics indicating the source of any non-position-independent code used as input. Such code results in a failure to generate the intended shared object. For example:


$ cc -o libfoo.so.1 -z text -G -R. foo.c
Text relocation remains                       referenced
    against symbol                  offset      in file
foo                                 0x0         foo.o
bar                                 0x8         foo.o
ld: fatal: relocations remain against allocatable but \
non-writable sections

Two relocations are generated against the text segment because of the non-position-independent code generated from the file foo.o. Where possible, these diagnostics will indicate any symbolic references that are required to carry out the relocations. In this case, the relocations are against the symbols foo and bar.

Another common cause of creating text relocations when generating a shared object is by including hand-written assembler code that has not been coded with the appropriate position-independent prototypes.


Note -

You may want to experiment with some simple source files to determine coding sequences that enable position-independence. Use the compilers ability to generate intermediate assembler output.


SPARC: -Kpic and -KPIC Options

For SPARC binaries, a subtle difference between the -K pic option and an alternative -K PIC option affects references to global offset table entries. See "Global Offset Table (Processor-Specific)".

The global offset table is an array of pointers, the size of whose entries are constant for 32-bit (4 bytes) and 64-bit (8-bytes). The code sequence to make reference to an entry under -K pic is something like:


        ld    [%l7 + j], %o0    ! load &j into %o0

Where %l7 is the precomputed value of the symbol _GLOBAL_OFFSET_TABLE_ of the object making the reference.

This code sequence provides a 13-bit displacement constant for the global offset table entry, and thus provides for 2048 unique entries for 32-bit objects, and 1024 unique entries for 64-bit objects. If an object is built that requires more than the available number of entries, the link-editor produces a fatal error:


$ cc -Kpic -G -o lobfoo.so.1 a.o b.o ... z.o
ld: fatal: too many symbols require `small' PIC references:
        have 2050, maximum 2048 -- recompile some modules -K PIC.

To overcome this error condition, compile some or all of the input relocatable objects with the -K PIC option. This option provides a 32-bit constant for the global offset table entry:


        sethi %hi(j), %g1
        or    %g1, %lo(j), %g1  ! get 32-bit constant GOT offset
        ld    [%l7 + j], %o0    ! load &j into %o0

You can investigate the global offset table requirements of an object using elfdump(1) with the -G option. You can also examine the processing of these entries during a link-edit using the link-editors debugging tokens -D got,detail.

Ideally, any frequently accessed data items will benefit from using the -K pic model. You can reference a single entry using both models. However, determining which relocatable objects should be compiled with either option can be time consuming, and the performance improvement realized small. Recompiling all relocatable objects with the -K PIC option is typically easier.