Dynamic Linking

Dynamic Section

No changes required.

Global Offset Table

The global offset table contains 64-bit addresses.

No other changes required.

Figure: Global Offset Table
...T_TABLE_ [];}\xspace }\end{center}\noindent\rule{\linewidth}{0.3mm}

Function Addresses

No changes required.

Procedure Linkage Table

Much as the global offset table redirects position-independent address calculations to absolute locations, the procedure linkage table redirects position-independent function calls to absolute locations. The link editor cannot resolve execution transfers (such as function calls) from one executable or shared object to another. Consequently, the link editor arranges to have the program transfer control to entries in the procedure linkage table. On the AMD64 architecture, procedure linkage tables reside in shared text, but they use addresses in the private global offset table. The dynamic linker determines the destinations' absolute addresses and modifies the global offset table's memory image accordingly. The dynamic linker thus can redirect the entries without compromising the position-independence and shareability of the program's text. Executable files and shared object files have separate procedure linkage tables. Unlike Intel386 ABI, this ABI uses the same procedure linkage table for both programs and shared objects.

Figure: Procedure Linkage Table

Following the steps below, the dynamic linker and the program ``cooperate'' to resolve symbolic references through the procedure linkage table and the global offset table.

  1. When first creating the memory image of the program, the dynamic linker sets the second and the third entries in the global offset table to special values. Steps below explain more about these values.
  2. Each shared object file in the process image has its own procedure linkage table, and control transfers to a procedure linkage table entry only from within the same object file.
  3. For illustration, assume the program calls name1, which transfers control to the label .PLT1.
  4. The first instruction jumps to the address in the global offset table entry for name1. Initially the global offset table holds the address of the following pushl instruction, not the real address of name1.
  5. Now the program pushes a relocation index (index) on the stack. The relocation index is a 32-bit, non-negative index into the relocation table addressed by the DT_JMPREL dynamic section entry. The designated relocation entry will have type R_X86_64_JUMP_SLOT, and its offset will specify the global offset table entry used in the previous jmp instruction. The relocation entry contains a symbol table index that will reference the appropriate symbol, name1 in the example.
  6. After pushing the relocation index, the program then jumps to .PLT0, the first entry in the procedure linkage table. The pushl instruction places the value of the second global offset table entry (GOT+8) on the stack, thus giving the dynamic linker one word of identifying information. The program then jumps to the address in the third global offset table entry (GOT+16), which transfers control to the dynamic linker.
  7. When the dynamic linker receives control, it unwinds the stack, looks at the designated relocation entry, finds the symbol's value, stores the ``real'' address for name1 in its global offset table entry, and transfers control to the desired destination.
  8. Subsequent executions of the procedure linkage table entry will transfer directly to name1, without calling the dynamic linker a second time. That is, the jmp instruction at .PLT1 will transfer to name1, instead of ``falling through'' to the pushl instruction.

The LD_BIND_NOW environment variable can change the dynamic linking behavior. If its value is non-null, the dynamic linker evaluates procedure linkage table entries before transferring control to the program. That is, the dynamic linker processes relocation entries of type R_X86_64_JUMP_SLOT during process initialization. Otherwise, the dynamic linker evaluates procedure linkage table entries lazily, delaying symbol resolution and relocation until the first execution of a table entry.

Program Interpreter

There is one valid program interpreter for programs conforming to the AMD64 ABI:


However, Linux puts this in


Initialization and Termination Functions

The implementation is responsible for executing the initialization functions specified by DT_INIT, DT_INIT_ARRAY, and DT_PREINIT_ARRAY entries in the executable file and shared object files for a process, and the termination (or finalization) functions specified by DT_FINI and DT_FINI_ARRAY, as specified by the System V ABI. The user program plays no further part in executing the initialization and termination functions specified by these dynamic tags.

Jan Hubicka 2003-05-04