What is a Position-Independent Code?

Position-independent code (PIC) is a form of absolute object code that does not contain any absolute addresses, and therefore does not depend on where it is loaded in the process's virtual address space. This is an important property for building shared libraries.

In order for the object code in a shared library to be fully shareable, it must not depend on its position in the virtual address space of any particular process. The object code in a shared library may be attached at different points in different processes, so it must work independent of being located at any particular position. Hence the term position-independent code.

Position independence is achieved by two mechanisms: First, PC-relative addressing is used wherever possible for branches within modules. Second, indirect addressing through a per-process linkage table is used for all accesses to global variables, or for inter-module procedure calls and other branches and literal accesses where PC-relative addressing cannot be used. Global variables must be accessed indirectly because they may be allocated in the main program's address space, and even the relative position of the global variables may vary from one process to another. The HP-UX dynamic loader (see dld.sl(5)) and the virtual memory management system work together to find free space at which to attach position-independent code within a process's address space. The dynamic loader also resolves any virtual addresses that might exist in the library.

Calls to PIC routines are accomplished through a procedure linkage table (PLT), which is built by the linker. Similarly, references to data are accomplished through a data linkage table (DLT). Both tables reside in a process's data segment. The dynamic loader fills in these tables with the absolute virtual addresses of the routines and data in a shared library at run time (known as binding).

Because of this, PIC can be loaded and executed anywhere that a process has free space.

On compilers that support PIC generation, the +z and +Z options cause the compiler to create PIC relocatable object code.

Generating Position-Independent Code

To be position-independent, the object code must restrict all references to code and data to either PC-relative or indirect references, where all indirect references are collected in a single linkage table that can be initialized on a per-process basis by dld.sl.

Register 19 (%r19) is the designated pointer to the linkage table. The linker generates stubs that ensure %r19 always points to the correct value for the target routine and that handle the inter-space calls needed to branch between shared libraries.

The linker generates an import stub for each external reference to a routine. The call to the routine is redirected to branch to the import stub, which obtains the target routine address and the new linkage table pointer value from the current linkage table; it then branches to an export stub for the target routine. In 32-bit mode, the linker generates an export stub for each externally visible routine in a shared library or program file. The export stub is responsible for trapping the return from the target routine in order to handle the inter-space call required between shared libraries and program files.

NOTE: The 64-bit mode linker does not require or support export stubs.

Shown below is the PIC code generated for import and export stubs. Note that this code is generated automatically by the linker. You do not have to generate the stubs yourself.

;Import Stub (Incomplete Executable)

X': ADDIL

L'lt_ptr+ltoff,%dp

; get procedure entry point

LDW

R'lt_ptr+ltoff(%r1),%r21

LDW

R'lt_ptr+ltoff+4(%r1),%r19 ; get new r19 value.

LDSID

(%r21),%r1

 

 

MTSP

%r1,%sr0

 

 

BE

0(%sr0,%r21)

;

branch to target

STW

%rp,-24(%sp)

;

save rp

;Import Stub (Shared Library)

186 Writing and Generating Position-Independent Code