On x64, the following code sequence models are available for accessing TLS
This code sequence implements the GD model described in Thread-Local Storage Access Models.
The __tls_get_addr() function takes a single parameter, the address of the tls_index structure. The R_AMD64_TLSGD relocation that is associated with the x@tlsgd(%rip) expression, instructs the link-editor to allocate a tls_index structure within the GOT. The two elements required for the tls_index structure are maintained in consecutive GOT entries, GOT[n] and GOT[n+1]. These GOT entries are associated to the R_AMD64_DTPMOD64 and R_AMD64_DTPOFF64 relocations.
The instruction at address 0x00 computes the address of the first GOT entry. This computation adds the PC relative address of the beginning of the GOT, which is known at link-edit time, to the current instruction pointer. The result is passed using the %rdi register to the __tls_get_addr() function.
This code sequence implements the LD model described in Thread-Local Storage Access Models.
The first two instructions are equivalent to the code sequence used for the general dynamic model, although without any padding. The two instructions must be consecutive. The x1@tlsld(%rip) sequence generates a the tls_index entry for symbol x1. This index refers to the current module that contains x1 with an offset of zero. The link-editor creates one relocation for the object, R_AMD64_DTMOD64.
The R_AMD64_DTOFF32 relocation is unnecessary, because offsets are loaded separately. The x1@dtpoff expression is used to access the offset of the symbol x1. Using the instruction as address 0x10, the complete offset is loaded and added to the result of the __tls_get_addr() call in %rax to produce the result in %rcx. The x1@dtpoff expression creates the R_AMD64_DTPOFF32 relocation.
Instead of computing the address of the variable, the value of the variable can be loaded using the following instruction. This instruction creates the same relocation as the original leaq instruction.
movq x1@dtpoff(%rax), %r11
Provided the base address of a TLS block is maintained within a register, loading, storing or computing the address of a protected thread-local variable requires one instruction.
Benefits exist in using the local dynamic model over the general dynamic model. Every additional thread-local variable access only requires three new instructions. In addition, no additional GOT entries, or runtime relocations are required.
This code sequence implements the IE model described in Thread-Local Storage Access Models.
The R_AMD64_GOTTPOFF relocation for the symbol x requests the link-editor to generate a GOT entry and an associated R_AMD64_TPOFF64 relocation. The offset of the GOT entry relative to the end of the x@gottpoff(%rip) instruction, is then used by the instruction. The R_AMD64_TPOFF64 relocation uses the value of the symbol x that is determined from the presently loaded modules. The offset is written in the GOT entry and is later loaded by the addq instruction.
To load the contents of x, rather than the address of x, the following sequence is available.
This code sequence implements the LE model described in Thread-Local Storage Access Models.
To load the contents of a TLS variable instead of the address of a TLS variable, the following sequence can be used.
The following sequence is even shorter.