Linker and Libraries Guide

32-bit x86: Thread-Local Variable Access

On x86, the following code sequence models are available for accessing TLS.

32-bit x86: General Dynamic (GD)

This code sequence implements the GD model described in Thread-Local Storage Access Models.

Table 8–8 32-bit x86: General Dynamic Thread-Local Variable Access Codes

Code Sequence

Initial Relocations

Symbol

0x00 leal  x@tlsgd(,%ebx,1), %eax
0x07 call  x@tlsgdplt

# %eax - contains address of TLS variable
R_386_TLS_GD
R_386_TLS_GD_PLT
x
x
 

Outstanding Relocations

Symbol

GOT[n]
GOT[n + 1]
R_386_TLS_DTPMOD32
R_386_TLS_DTPOFF32
x

The leal instruction generates a R_386_TLS_GD relocation which instructs the link-editor to allocate space in the GOT to hold a TLS_index structure for variable x. The link-editor processes this relocation by substituting the GOT-relative offset for the new GOT entry.

Since the load object index and TLS block index for x are not known until runtime, the link-editor places the R_386_TLS_DTPMOD32 and R_386_TLS_DTPOFF32 relocations against the GOT for processing by the runtime linker. The address of the generated GOT entry is loaded into register %eax for the call to ___tls_get_addr().

The call instruction causes the generation of the R_386_TLS_GD_PLT relocation. This instructs the link-editor to bind the call to the ___tls_get_addr() function and associates the call instruction with the GD code sequence.

The call instruction must immediately follow the leal instruction. This requirement is necessary to permit the code transformations.

x86: Local Dynamic (LD)

This code sequence implements the LD model described in Thread-Local Storage Access Models.

Table 8–9 32-bit x86: Local Dynamic Thread-Local Variable Access Codes

Code Sequence

Initial Relocations

Symbol

0x00 leal  x1@tlsldm(%ebx), %eax
0x06 call  x1@tlsldmplt

# %eax - contains address of TLS block of current object

0x10 leal  x1@dtpoff(%eax), %edx

# %edx - contains address of local TLS variable x1

0x20 leal  x2@dtpoff(%eax), %edx

# %edx - contains address of local TLS variable x2
R_386_TLS_LDM
R_386_TLS_LDM_PLT
 
 
 
R_386_TLS_LDO_32
 
 
 
R_386_TLS_LDO_32
x1
x1
 
 
 
x1
 
 
 
x2
 

Outstanding Relocations

Symbol

GOT[n]
GOT[n + 1]
R_386_TLS_DTPMOD32
<none>
x

The first leal instruction generates a R_386_TLS_LDM relocation. This relocation instructs the link-editor to allocate space in the GOT to hold a TLS_index structure for the current object. The link-editor process this relocation by substituting the GOT -relative offset for the new linkage table entry.

The load object index is not known until runtime. Therefore, a R_386_TLS_DTPMOD32 relocation is created, and the ti_tlsoffset field of the structure is zero filled. The call instruction is tagged with the R_386_TLS_LDM_PLT relocation.

The TLS offset for each local symbol is known at link-edit time so the link-editor fills these values in directly.

When a procedure references more than one local symbol, the compiler generates code to obtain the base address of the TLS block once. This base address is then used to calculate the address of each symbol without a separate library call.

32-bit x86: Initial Executable (IE)

This code sequence implements the IE model described in Thread-Local Storage Access Models.

Two code-sequences for the IE model exist. One sequence is for position independent code which uses a GOT-pointer. The other sequence is for position dependent code which does not use a GOT-pointer.

Table 8–10 32-bit x86: Initial Executable, Position Independent, Thread-Local Variable Access Codes

Code Sequence

Initial Relocations

Symbol

0x00 movl  %gs:0, %eax
0x06 addl  x@gotntpoff(%ebx), %eax

# %eax - contains address of TLS variable
<none>
R_386_TLS_GOTIE
 
x
 

Outstanding Relocations

Symbol

GOT[n]
R_386_TLS_TPOFF
x

The addl instruction generates a R_386_TLS_GOTIE relocation. This relocation instructs the link–editor to create space in the GOT to store the static TLS offset for symbol x. A R_386_TLS_TPOFF relocation is left outstanding against the GOT table for the runtime linker to fill in with the static TLS offset for symbol x.

Table 8–11 32-bit x86: Initial Executable, Position Dependent, Thread-Local Variable Access Codes

Code Sequence

Initial Relocations

Symbol

0x00 movl  %gs:0, %eax
0x06 addl  x@indntpoff, %eax

# %eax - contains address of TLS variable
<none>
R_386_TLS_IE
 
x
 

Outstanding Relocations

Symbol

GOT[n]
R_386_TLS_TPOFF
x

The addl instruction generates a R_386_TLS_IE relocation. This relocation instructs the link-editor to create space in the GOT to store the static TLS offset for symbol x. The main difference between this sequence and the position independent form, is that the instruction is bound directly to the GOT entry created, instead of using an offset off of the GOT-pointer register. A R_386_TLS_TPOFF relocation is left outstanding against the GOT for the runtime linker to fill in with the static TLS offset for symbol x.

The contents of variable x, rather than the address, can be loaded by embedding the offset directly into the memory reference as shown in the next two sequences.

Table 8–12 32-bit x86: Initial Executable, Position Independent, Dynamic Thread-Local Variable Access Codes

Code Sequence

Initial Relocations

Symbol

0x00 movl  x@gotntpoff(%ebx), %eax
0x06 movl  %gs:(%eax), %eax

# %eax - contains address of TLS variable
R_386_TLS_GOTIE
<none>
x
 

Outstanding Relocations

Symbol

GOT[n]
R_386_TLS_TPOFF
x

Table 8–13 32-bit x86: Initial Executable, Position Independent, Thread-Local Variable Access Codes

Code Sequence

Initial Relocations

Symbol

0x00 movl  x@indntpoff, %ecx
0x06 movl  %gs:(%ecx), %eax

# %eax - contains address of TLS variable
R_386_TLS_IE
<none>
x
 

Outstanding Relocations

Symbol

GOT[n]
R_386_TLS_TPOFF
x

In the last sequence, if the %eax register is used instead of the %ecx register, the first instruction can be either 5 or 6 bytes long.

32-bit x86: Local Executable (LE)

This code sequence implements the LE model described in Thread-Local Storage Access Models.

Table 8–14 32-bit x86: Local Executable Thread-Local Variable Access Codes

Code Sequence

Initial Relocations

Symbol

0x00 movl  %gs:0, %eax
0x06 leal  x@ntpoff(%eax), %eax

# %eax - contains address of TLS variable
<none>
R_386_TLS_LE
 
x

The movl instruction generates a R_386_TLS_LE_32 relocation. The link-editor binds this relocation directly to the static TLS offset for the symbol defined in the executable. No processing is required at runtime.

The contents of variable x, rather then the address, can be accessed with the same relocation by using the following instruction sequence.

Table 8–15 32-bit x86: Local Executable Thread-Local Variable Access Codes

Code Sequence

Initial Relocations

Symbol

0x00 movl  %gs:0, %eax
0x06 movl  x@ntpoff(%eax), %eax

# %eax - contains address of TLS variable
<none>
R_386_TLS_LE
 
x

Rather than computing the address of the variable, a load from the variable or store to the variable can be accomplished using the following sequence. Note, the x@ntpoff expression is not used as an immediate value, but as an absolute address.

Table 8–16 32-bit x86: Local Executable Thread-Local Variable Access Codes

Code Sequence

Initial Relocations

Symbol

0x00 movl %gs:x@ntpoff, %eax

# %eax - contains address of TLS variable
R_386_TLS_LE
x