32-bit x86: Procedure Linkage Table
For 32-bit x86 dynamic objects, the procedure linkage table resides in shared text but uses addresses in the private global offset table. The runtime linker determines the absolute addresses of the destinations and modifies the global offset table's memory image accordingly. The runtime linker thus redirects the entries without compromising the position-independence and shareability of the program's text. Dynamic objects have separate procedure linkage tables.
Table 15-16 32-bit x86: Absolute Procedure Linkage Table Example
.PLT0:
pushl got_plus_4
jmp *got_plus_8
nop; nop
nop; nop
.PLT1:
jmp *name1_in_GOT
pushl $offset
jmp .PLT0@PC
.PLT2:
jmp *name2_in_GOT
pushl $offset
jmp .PLT0@PC
|
Table 15-17 32-bit x86: Position-Independent Procedure Linkage Table Example
.PLT0:
pushl 4(%ebx)
jmp *8(%ebx)
nop; nop
nop; nop
.PLT1:
jmp *name1@GOT(%ebx)
pushl $offset
jmp .PLT0@PC
.PLT2:
jmp *name2@GOT(%ebx)
pushl $offset
jmp .PLT0@PC
|
Note:
As the preceding examples show, the procedure linkage table instructions use different operand addressing modes for absolute code and for position-independent code. Nonetheless, their interfaces to the runtime linker are the same.The following steps describe how the runtime linker and program cooperate to resolve the symbolic references through the procedure linkage table and the global offset table.
-
When the memory image of the program is initially created, the runtime linker sets the second and third entries in the global offset table to special values. The following steps explain these values.
-
If the procedure linkage table is position-independent, the address of the global offset table must be in
%ebx. 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. So, the calling function must set the global offset table base register before calling the procedure linkage table entry. -
For example, the program calls
name1, which transfers control to the label.PLT1. -
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 followingpushlinstruction, not the real address ofname1. -
The program pushes a relocation offset (
offset) on the stack. The relocation offset is a 32-bit, nonnegative byte offset into the relocation table. The designated relocation entry has the typeR_386_JMP_SLOT, and its offset specifies the global offset table entry used in the previousjmpinstruction. The relocation entry also contains a symbol table index, which the runtime linker uses to get the referenced symbol,name1. -
After pushing the relocation offset, the program jumps to
.PLT0, the first entry in the procedure linkage table. Thepushlinstruction pushes the value of the second global offset table entry (got_plus_4or4(%ebx)) on the stack, giving the runtime linker one word of identifying information. The program then jumps to the address in the third global offset table entry (got_plus_8or8(%ebx)), to jump to the runtime linker. -
The runtime linker unwinds the stack, checks the designated relocation entry, gets the symbol's value, stores the actual address of
name1in its global offset entry table, and jumps to the destination. -
Subsequent executions of the procedure linkage table entry transfer directly to
name1, without calling the runtime linker again. Thejmpinstruction at.PLT1jumps toname1instead of falling through to thepushlinstruction.
The LD_BIND_NOW environment variable changes dynamic
linking behavior. If its value is non-null, the runtime linker processes
R_386_JMP_SLOT relocation entries before transferring control
to the program.