Linker and Libraries Guide

Thread-Local Storage Access Models

Each TLS reference follows one of the following access models. These models are listed from the most general, but least optimized, to the fastest, but most restrictive.

General Dynamic (GD) - dynamic TLS

This model allows reference of all TLS variables, from either a shared object or a dynamic executable. This model also supports the deferred allocation of a TLS block when it is first referenced from a specific thread.

Local Dynamic (LD) - dynamic TLS of local symbols

This model is a optimization of the GD model. If the compiler determines that a variable is bound locally, or protected, within the dynamic object being built, it instructs the link-editor to statically bind the dynamic tlsoffset and use this model. This provides a performance benefit over the GD model. Only one call to tls_get_addr() is required per function, to determine the address of dtv0,m. The dynamic TLS offset, bound at link-edit time, is added to the dtv0,m address for each reference.

Initial Executable (IE) - static TLS with assigned offsets

This model can only reference TLS variables which are available as part of the initial static TLS template. This template is composed of all TLS blocks available at process startup. In this model, the thread pointer-relative offset for a given variable x is stored in the global offset table entry for x. This model can not reference TLS variables from shared libraries loaded after initial process startup, such as via lazy loading, filters, or dlopen(3DL). This model can not access TLS blocks which use deferred allocation.

Local Executable (LE )- static TLS

This model can only reference TLS variables which are part of the TLS block of the dynamic executable itself. The link-editor calculates the thread pointer-relative offsets statically, without the need for dynamic relocations, or the extra reference to the global offset table. This model can not be used to reference variables outside of the dynamic executable.

The link-editor can transition code from the more general access models to the more optimized models, if it is determined appropriate to do so. This transitioning is achievable through the use of unique TLS relocations. These relocations, not only request updates be performed, but identify which TLS access model is being used.

Knowing the TLS access model, and the type of object being created, allows the link-editor to perform translations. For example, if a relocatable object using the GD access model is being linked into a dynamic executable, the link-editor can transition the references using the IE or LE access models, as appropriate. The relocations required for the model are then performed.

The following diagram illustrates the different access models, and when one model can be transitioned from one to the other.

Figure 8–2 Thread-Local Storage Access Models and Transitions

Thread-Local Storage Access Models and Transitions

SPARC: Thread-Local Variable Access

On SPARC, the following code sequence models are available for accessing thread-local variables.

SPARC: 32-bit and 64-bit General Dynamic (GD)

This code sequence is the most general, and can be included in both shared objects and dynamic executables. This code sequence can also reference an external TLS variable in either a shared object or dynamic executable.

Table 8–2 SPARC: 32-bit and 64-bit General Dynamic Thread-Local Variable Access Codes

Code Sequence 

Initial Relocations 

Symbol 

# %l7 - initialized to GOT pointer

0x00 sethi %hi(@dtlndx(x)), %o0
0x04 add   %o0,%lo(@dtlndx(x)),%o0
0x08 add   %l7, %o0, %o0
0x0c call  x@TLSPLT
 
# %o0 - contains address of TLS variable
 
 
R_SPARC_TLS_GD_HI22
R_SPARC_TLS_GD_LO22
R_SPARC_TLS_GD_ADD
R_SPARC_TLS_GD_CALL
 
 
x
x
x
x
 

Outstanding Relocations: 32-bit 

Symbol 

GOT[n]
GOT[n + 1]
R_SPARC_TLS_DTPMOD32
R_SPARC_TLS_DTPOFF32
x
x
 

Outstanding Relocations: 64-bit 

Symbol 

GOT[n]
GOT[n + 1]
R_SPARC_TLS_DTPMOD64
R_SPARC_TLS_DTPOFF64
x
x

The sethi, and add instructions generate R_SPARC_TLS_GD_HI22 and R_SPARC_TLS_GD_LO10 relocations respectively. These relocations instruct the link-editor to allocate space in the global offset table 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_SPARC_TLS_DTPMOD32 and R_SPARC_TLS_DPTOFF32 relocations against the GOT for processing by the runtime linker.

The add instruction causes the generation of the R_SPARC_TLS_GD_ADD relocation. This relocation is used only if the GD code sequence is changed to another sequence by the link-editor.

The call instruction generates the R_SPARC_TLS_GD_CALL relocation. This relocation instructs the link-editor to bind the call to the __tls_get_addr() function, and associates the call instruction with the GD code sequence.


Note –

The add instruction must appear before the call instruction. It cannot be placed into the delay slot for the call. This is required as the code-transformations that can occur later require a known order.

The register used as the GOT-pointer for the add instruction tagged by the R_SPARC_TLS_GD_ADD relocation, must be the first register in the add instruction. This permits the link-editor to identify the GOT-pointer register during a code transformation.


SPARC: 32-bit and 64-bit Local Dynamic (LD)

This code sequence can be used in either a shared object or dynamic executable. This sequence is used when referencing a TLS variable bound within the same object as the reference. Because the dynamic tlsoffset can be bound at link-edit time, only one call to __tls_get_addr() is required per function call for all symbols referenced via the LD code sequence.

Table 8–3 SPARC: 32-bit and 64-bit Local Dynamic Thread-Local Variable Access Codes

Code Sequence 

Initial Relocations 

Symbol 

# %l7 - initialized to GOT pointer

0x00 sethi %hi(@tmndx(x1)), %o0
0x04 add   %o0,%lo(@tmndx(x1)),%o0
0x08 add   %l7, %o0, %o0
0x0c call  x@TLSPLT

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

0x10 sethi %hi(@dtpoff(x1)), %l1
0x14 xor   %l1, %lo(@dtpoff(x1)), %l1
0x18 add   %o0, %l1, %l1

# %l1 - contains address of local TLS variable x1

0x20 sethi %hi(@dtpoff(x2)), %l2
0x24 xor   %l2, %lo(@dtpoff(x2)), %l2
0x28 add   %o0, %l2, %l2

# %l2 - contains address of local TLS variable x2
 
 
R_SPARC_TLS_LDM_HI22
R_SPARC_TLS_LDM_LO10
R_SPARC_TLS_LDM_ADD
R_SPARC_TLS_LDM_CALL
 
 
 
R_SPARC_TLS_LDO_HIX22
R_SPARC_TLS_LDO_LOX10
R_SPARC_TLS_LDO_ADD
 
 
 
R_SPARC_TLS_LDO_HIX22
R_SPARC_TLS_LDO_LOX10
R_SPARC_TLS_LDO_ADD
 
 
x1
x1
x1
x1
 
 
 
x1
x1
x1
 
 
 
x2
x2
x2
 

Outstanding Relocations: 32-bit 

Symbol 

GOT[n]
GOT[n + 1]
R_SPARC_TLS_DTPMOD32
<none>
x1
 

Outstanding Relocations: 64-bit 

Symbol 

GOT[n]
GOT[n + 1]
R_SPARC_TLS_DTPMOD64
<none>
x1

The first sethi and add instructions generate R_SPARC_TLS_LDM_HI22 and R_SPARC_TLS_LDM_LO10 relocations respectively. These relocations instruct the link-editor to allocate space in the global offset table to hold a TLS_index structure for the current object. The link-editor processes this relocation by substituting the GOT-relative offset for the new GOT entry.

Since the load object index is not known until runtime, a R_SPARC_TLS_DTPMOD32 relocation is created, and the ti_tlsoffset field of the TLS_index structure is zero filled.

The second add and the call instruction are tagged with the R_SPARC_TLS_LDM_ADD and R_SPARC_TLS_LDM_CALL relocations respectively.

The following sethi and or instructions generate the R_SPARC_LDO_HIX22 and R_SPARC_TLS_LDO_LOX10 relocations, respectively. The TLS offset for each local symbol is known at link-edit time, therefore these values are filled in directly. The add instruction is tagged with the R_SPARC_TLS_LDO_ADD relocation.

When a procedure references more then 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.


Note –

The register containing the TLS object address in the add instruction tagged by the R_SPARC_TLS_LDO_ADD must be the first register in the instruction sequence. This permits the link-editor to identify the register during a code transformation.


SPARC: 32-bit Initial Executable (IE)

This code sequence can only be used in a dynamic executable. It can reference a TLS variable defined in either the executable or any shared libraries loaded at process startup. This model can not reference TLS variables from shared libraries loaded after process startup.

Table 8–4 SPARC: 32-bit Initial Executable Thread-Local Variable Access Codes

Code Sequence 

Initial Relocations 

Symbol 

# %l7 - initialized to GOT pointer

0x00 sethi %hi(@tpoff(x)), %o0
0x04 or    %o0,%lo(@tpoff(x)),%o0
0x08 ld    [%l7 + %o0], %o0
0x0c add   %g7, %o0, %o0
 
# %o0 - contains address of TLS variable
 
 
R_SPARC_TLS_IE_HI22
R_SPARC_TLS_IE_LO10
R_SPARC_TLS_IE_LD
R_SPARC_TLS_IE_ADD
 
 
x
x
x
x
 

Outstanding Relocations 

Symbol 

GOT[n]
R_SPARC_TLS_TPOFF32
x

The sethi and or instructions generate R_SPARC_TLS_IE_HI22 and R_SPARC_TLS_IE_LO10 relocations, respectively. These relocations instruct the link-editor to create space in the global offset table to store the static TLS offset for symbol x. A R_SPARC_TLS_TPOFF32 relocation is left outstanding against the GOT for the runtime linker to fill in with the negative static TLS offset for symbol x. The ld and the add instructions are tagged with the R_SPARC_TLS_IE_LD and R_SPARC_TLS_IE_ADD relocations respectively.


Note –

The register used as the GOT-pointer for the add instruction tagged by the R_SPARC_TLS_IE_ADD relocation must be the first register in the instruction. This permits the link-editor to identify the GOT-pointer register during a code transformation.


SPARC: 64-bit Initial Executable (IE)

This sequence is identical to the SPARC 32–bit sequence, except that an ldx instruction is used to load the 64–bit address instead of an ld instruction.

Table 8–5 SPARC: 64-bit Initial Executable Thread-Local Variable Access Codes

Code Sequence 

Initial Relocations 

Symbol 

# %l7 - initialized to GOT pointer

0x00 sethi %hi(@tpoff(x)), %o0
0x04 or    %o0,%lo(@tpoff(x)),%o0
0x08 ldx   [%l7 + %o0], %o0
0x0c add   %g7, %o0, %o0
 
# %o0 - contains address of TLS variable
 
 
R_SPARC_TLS_IE_HI22
R_SPARC_TLS_IE_LO10
R_SPARC_TLS_IE_LD
R_SPARC_TLS_IE_ADD
 
 
x
x
x
x
 

Outstanding Relocations 

Symbol 

GOT[n]
R_SPARC_TLS_TPOFF64
x

SPARC: 32-bit and 64-bit Local Executable (LE)

This code sequence can only be used from within a dynamic executable to reference a TLS variable defined within the executable. If this is the case, the static tlsoffset is known at link-edit time and no runtime relocations are required.

Table 8–6 SPARC: 32-bit and 64-bit Local Executable Thread-Local Variable Access Codes

Code Sequence 

Initial Relocations 

Symbol 

0x00 sethi %hix(@tpoff(x)), %o0
0x04 xor   %o0,%lo(@tpoff(x)),%o0
0x08 add   %g7, %o0, %o0
 
# %o0 - contains address of TLS variable
R_SPARC_TLS_LE_HIX22
R_SPARC_TLS_LE_LOX10
<none>
x
x

The sethi and or instructions generate R_SPARC_TLS_LE_HIX22 and R_SPARC_TLS_LE_LOX10 relocations respectively. The link-editor binds these relocations directly to the static TLS offset for the symbol defined in the executable. No relocation processing is required at runtime.

SPARC: Thread-Local Storage Relocation Types

The TLS relocations listed in the following table are defined for SPARC. Descriptions in the table use the following notation:

@dtlndx(x)

Allocates two contiguous entries in the global offset table to hold a TLS_index structure. This information is passed to __tls_get_addr(). The instruction referencing this entry is bound to the address of the first of the two GOT entries.

@tmndx(x)

Allocates two contiguous entries in the global offset table to hold a TLS_index structure. This information is passed to __tls_get_addr(). The ti_tlsoffset field of this structure is set to 0, and the ti_moduleid is filled in at runtime. The call to __tls_get_addr() returns the starting offset of the dynamic TLS block.

@dtpoff(x)

Calculates the tlsoffset relative to the TLS block.

@tpoff(x)

Calculates the negative tlsoffset relative to the static TLS block. This value is added to the thread-pointer to calculate the TLS address.

@dtpmod(x)

Calculates the object identifier of the object containing symbol S.

Table 8–7 SPARC: Thread-Local Storage Relocation Types

Name 

Value 

Field 

Calculation 

R_SPARC_TLS_GD_HI22

56

T-simm22

@dtlndx(S + A) >> 10

R_SPARC_TLS_GD_LO10

57

T-simm13

@dtlndx(S + A) & 0x3ff

R_SPARC_TLS_GD_ADD

58

None 

See R_SPARC_R_SPARC_TLS_GD_ADD

R_SPARC_TLS_GD_CALL

59

V-disp30

See R_SPARC_R_SPARC_TLS_GD_CALL

R_SPARC_TLS_LDM_HI22

60 

T-simm22

@tmndx(S + A) >> 10

R_SPARC_TLS_LDM_LO10

61

T-simm13

@tmndx(S + A) & 0x3ff

R_SPARC_TLS_LDM_ADD

62 

None 

See R_SPARC_R_SPARC_TLS_LDM_ADD

R_SPARC_TLS_LDM_CALL

63

V-disp30

See R_SPARC_R_SPARC_TLS_LDM_CALL

R_SPARC_TLS_LDO_HIX22

64

T-simm22

@dtpoff(S + A) >> 10

R_SPARC_TLS_LDO_LOX10

65

T-simm13

@dtpoff(S + A) & 0x3ff

R_SPARC_TLS_LDO_ADD

66

None 

See R_SPARC_R_SPARC_TLS_LDO_ADD

R_SPARC_TLS_IE_HI22

67

T-simm22

@got(@tpoff(S + A)) >> 10

R_SPARC_TLS_IE_LO10

68

T-simm13

@got(@tpoff(S + A)) & 0x3ff

R_SPARC_TLS_IE_LD

69

None 

See R_SPARC_R_SPARC_TLS_IE_LD

R_SPARC_TLS_IE_LDX

70

None 

See R_SPARC_R_SPARC_TLS_IE_LDX

R_SPARC_TLS_IE_ADD

71

None 

See R_SPARC_R_SPARC_TLS_IE_ADD

R_SPARC_TLS_LE_HIX22

72

T-imm22

(@tpoff(S + A) ^0xffffffffffffffff) >> 10

R_SPARC_TLS_LE_LOX10

73

T-simm13

(@tpoff(S + A) & 0x3ff) | 0x1c00

R_SPARC_TLS_DTPMOD32

74

V-word32

@dtpmod(S + A)

R_SPARC_TLS_DTPMOD64

75

V-word64

@dtpmod(S + A)

R_SPARC_TLS_DTPOFF32

76

V-word32

@dtpoff(S + A)

R_SPARC_TLS_DTPOFF64

77

V-word64

@dtpoff(S + A)

R_SPARC_TLS_TPOFF32

78

V-word32

@tpoff(S + A)

R_SPARC_TLS_TPOFF64

79

V-word64

@tpoff(S + A)

Some relocation types have semantics beyond simple calculations:

R_SPARC_TLS_GD_ADD

This relocation tags the add instruction of a GD code sequence. The register used for the GOT-pointer is the first register in the sequence. The instruction tagged by this relocation comes before the call instruction tagged by the R_SPARC_TLS_GD_CALL relocation. This is used to transition between TLS models at link-edit time.

R_SPARC_TLS_GD_CALL

This relocation is handled as if it were a R_SPARC_WPLT30 relocation referencing the __tls_get_addr() function. This relocation is part of a GD code sequence.

R_SPARC_LDM_ADD

This relocation tags the first add instruction of a LD code sequence. The register used for the GOT-pointer is the first register in the sequence. The instruction tagged by this relocation comes before the call instruction tagged by the R_SPARC_TLS_GD_CALL relocation. This is used to transition between TLS models at link-edit time.

R_SPARC_LDM_CALL

This relocation is handled as if it were a R_SPARC_WPLT30 relocation referencing the __tls_get_addr() function. This relocation is part of a LD code sequence.

R_SPARC_LDO_ADD

This relocation tags the final add instruction in a LD code sequence. The register which contains the object address computed in the initial part of the code sequence is the first register in this instruction. This permits the link-editor to identify this register for code transformations.

R_SPARC_TLS_IE_LD

This relocation tags the ld instruction in the 32–bit IE code sequence. This is used to transition between TLS models at link-edit time.

R_SPARC_TLS_IE_LDX

This relocation tags the ldx instruction in the 64–bit IE code sequence. This is used to transition between TLS models at link-edit time.

R_SPARC_TLS_IE_ADD

This relocation tags the add instruction in the IE code sequence. The register that is used for the GOT-pointer is the first register in the sequence.

x86: Thread-Local Variable Access

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

x86: General Dynamic (GD)

This code sequence is the most general, and can be included both in a shared objects and dynamic executables. This code sequence can reference an external TLS variable in either a shared object or dynamic executable.

Table 8–8 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 global offset table 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 is a required to permit the code transformations.

x86: Local Dynamic (LD)

This code sequence can be used in either a shared object or dynamic executable. This sequence is used when referencing a TLS variable bound to the same object as the reference. Because the dynamic tlsoffset can be bound at link-edit time, only one call to ___tls_get_addr() is required per function call for all symbols which are referenced via the LD code sequence.

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

Code Sequence 

Initial Relocations 

Symbol 

0x00 leal  x1@tlsldm(%ebx), %eax
0x06 call  x@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 that instructs the link-editor to allocate space in the global offset table 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.

Since the load object index is not known until runtime, aR_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 then 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.

x86: Initial Executable (IE)

There are two code-sequences for the IE model. 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. Both of these code sequences can only be used in a dynamic executable. These code sequences can reference a TLS variable defined in either the executable or any of the shared libraries loaded at process startup. This model can not reference TLS variables from shared libraries loaded after process startup.

Table 8–10 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 that instructs the link–editor to create space in the global offset table 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 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, that instructs the link-editor to create space in the global offset table 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 via 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 then the address, can be loaded by embedding the offset directly into the memory reference as shown in the next two sequences.

Table 8–12 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 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 above, the first instruction may be either 5 or 6 bytes long.

x86: Local Executable (LE)

This code sequence can only be used from within a dynamic executable and referencing a TLS variable defined within the executable. If this is the case the static tlsoffset it known at link-edit time and no runtime relocations are required.

Table 8–14 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 aR_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 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

If instead of computing the address of the variable we want to load from it or store in it the following sequence can be used. Note that in this case we use the x@ntpoff expression not as an immediate value, but instead as an absolute address.

Table 8–16 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

x86: Thread-Local Storage Relocation Types

The TLS relocations listed in the following table are defined for x86. Descriptions in the table use the following notation:

@tlsgd(x)

Allocates two contiguous entries in the GOT to hold a TLS_index structure. This structure is passed to ___tls_get_addr(). The instruction referencing this entry will be bound to the first of the two GOT entries.

@tlsgdplt(x)

This relocation is handled as if it were a R_386_PLT32 relocation referencing the ___tls_get_addr() function.

@tlsldm(x)

Allocates two contiguous entries in the GOT to hold a TLS_index structure. This structure is passed to the ___tls_get_addr(). Theti_tlsoffset field of the TLS_index is set to 0, and the ti_moduleid is filled in at runtime. The call to ___tls_get_addr() returns the starting offset of the dynamic TLS block.

@gotntpoff(x)

Allocates a entry in the GOT, and initializes it with the negative tlsoffset relative to the static TLS block. This is performed at runtime via the R_386_TLS_TPOFF relocation.

@indntpoff(x)

This expression is similar to @gotntpoff, but used in position dependent code. @gotntpoff resolves to a GOT slot address relative to the start of the GOT in the movl or addl instructions. @indntpoff resolves to the absolute GOT slot address.

@ntpoff(x)

Calculates the negative offset of the variable it is added to relative to the static TLS block.

@dtpoff(x)

Calculates the tlsoffset relative to the TLS block. The value is used as an immediate value of an addend and is not associated with a specific register.

@dtpmod(x)

Calculates the object identifier of the object containing symbol S.

Table 8–17 x86: Thread-Local Storage Relocation Types

Name 

Value 

Field 

Calculation 

R_386_TLS_GD_PLT

12

Word32

@tlsgdplt

R_386_TLS_LDM_PLT

13

Word32

@tlsldmplt

R_386_TLS_TPOFF

14

Word32

@ntpoff(S)

R_386_TLS_IE

15

Word32

@indntpoff(S)

R_386_TLS_GOTIE

16

Word32

@gotntpoff(S)

R_386_TLS_LE

17

Word32

@ntpoff(S)

R_386_TLS_GD

18

Word32

@tlsgd(S)

R_386_TLS_LDM

19

Word32

@tlsldm(S)

R_386_TLS_LDO_32

32

Word32

@dtpoff(S)

R_386_TLS_DTPMOD32

35

Word32

@dtpmod(S)

R_386_TLS_DTPOFF32

36

Word32

@dtpoff(S)