On SPARC architectures, procedure linkage tables reside in private data. The runtime linker determines the destinations' absolute addresses and modifies the procedure linkage table's memory image accordingly. The runtime linker thus redirects 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.
The first four procedure linkage table entries are reserved. (The original contents of these entries are unspecified, despite the example below.) Each entry in the table occupies 3 words (12 bytes), and the last table entry is followed by a nop instruction. For 64-bit SPARCV9 objects, each entry occupies 8 instructions (32 bytes) and must be aligned on a 32-byte boundary (the table as a whole must be aligned on a 256-byte boundary).
A relocation table is associated with the procedure linkage table. The DT_JMP_REL entry in the _DYNAMIC array gives the location of the first relocation entry. The relocation table has one entry, in the same sequence, for each procedure linkage table entry. Except the first four entries, the relocation type is R_SPARC_JMP_SLOT, the relocation offset specifies the address of the first byte of the associated procedure linkage table entry, and the symbol table index refers to the appropriate symbol.
To illustrate procedure linkage tables, the figure below shows four entries: two of the four initial reserved entries, the third is a call to name1, and the fourth is a call to name2. The example assumes the entry for name2 is the table's last entry and shows the following nop instruction. The left column shows the instructions from the object file before dynamic linking. The right column demonstrates a possible way the runtime linker might fix the procedure linkage table entries.
Table 7-45 SPARC: Procedure Linkage Table ExampleObject File | Memory Segment |
---|---|
.PLT0: unimp unimp unimp .PLT1: unimp unimp unimp ... |
.PLT0: save %sp,-64,%sp call runtime-linker nop .PLT1: .word identification unimp unimp ... |
... .PLT101: sethi (.-.PLT0),%g1 ba,a .PLT0 nop .PLT102: sethi (.-.PLT0),%g1 ba,a .PLT0 nop |
... .PLT101: sethi (.-.PLT0),%g1 sethi %hi(name1),%g1 jmp1 %g1+%lo(name1),%g0 .PLT102: sethi (.-.PLT0),%g1 sethi %hi(name2),%g1 jmp1 %g1+%lo(name2),%g0 |
nop |
nop |
Following the steps below, the runtime linker and program jointly resolve the symbolic references through the procedure linkage table. Again, the steps described below are for explanation only. The precise execution-time behavior of the runtime linker is not specified.
When first creating the memory image of the program, the runtime linker changes the initial procedure linkage table entries, making them transfer control to one of the runtime linker's own routines. It also stores a word of identification information in the second entry. When it receives control, it can examine this word to find what object called it.
All other procedure linkage table entries initially transfer to the first entry, letting the runtime linker gain control at the first execution of each table entry. For example, the program calls name1, which transfers control to the label .PLT101.
The sethi instruction computes the distance between the current and the initial procedure linkage table entries, .PLT101 and .PLT0, respectively. This value occupies the most significant 22 bits of the %g1 register. In this example, &g1 contains 0x12f000, when the runtime linker receives control.
Next, the ba,a instruction jumps to .PLT0, establishing a stack frame and calls the runtime linker.
With the identification value, the runtime linker gets its data structures for the object, including the relocation table.
By shifting the %g1 value and dividing by the size of the procedure linkage table entries, the runtime linker calculates the index of the relocation entry for name1. Relocation entry 101 has type R_SPARC_JMP_SLOT, its offset specifies the address of .PLT101, and its symbol table index refers to name1. Thus, the runtime linker gets the symbol's real value, unwinds the stack, modifies the procedure linkage table entry, and transfers control to the desired destination.
Although the runtime linker does not have to create the instruction sequences under the Memory Segment column, it might. If it did, some points deserve more explanation.
To make the code reentrant, the procedure linkage table's instructions are changed in a particular sequence. If the runtime linker is fixing a function's procedure linkage table entry and a signal arrives, the signal handling code must be able to call the original function with predictable (and correct) results.
The runtime linker changes two words to convert an entry. It updates each word automatically. Reentrancy is achieved by first overwriting the nop with the jmp1 instruction, and then patching the ba,a to be sethi. If a reentrant function call happens between the two word updates, the jmp1 resides in the delay slot of the ba,a instruction, and cancels the delay instruction. So, the runtime linker gains control a second time. Although both invocations of the runtime linker modify the same procedure linkage table entry, their changes do not interfere with each other.
The first sethi instruction of a procedure linkage table entry can fill the delay slot of the previous entry's jmp1 instruction. Although the sethi changes the value of the %g1 register, the previous contents can be safely discarded.
After conversion, the last procedure linkage table entry (.PLT102 above) needs a delay instruction for its jmp1. The required, trailing nop fills this delay slot.
The LD_BIND_NOW
environment variable changes dynamic linking behavior. If its value is non-null, the runtime linker processes R_SPARC_JMP_SLOT relocation entries (procedure linkage table entries) before transferring control to the program. If LD_BIND_NOW
is null, the runtime linker evaluates linkage table entries on the first execution of each table entry.