Skip Navigation Links | |
Exit Print View | |
![]() |
Oracle Solaris 11.1 Linkers and Libraries Guide Oracle Solaris 11.1 Information Library |
Part I Using the Link-Editor and Runtime Linker
1. Introduction to the Oracle Solaris Link Editors
5. Link-Editor Quick Reference
7. Building Objects to Optimize System Performance
10. Establishing Dependencies with Dynamic String Tokens
Part IV ELF Application Binary Interface
13. Program Loading and Dynamic Linking
Runtime Allocation of Thread-Local Storage
Deferred Allocation of Thread-Local Storage Blocks
Thread-Local Storage Access Models
SPARC: Thread-Local Variable Access
32-bit SPARC: Initial Executable (IE)
64-bit SPARC: Initial Executable (IE)
SPARC: Thread-Local Storage Relocation Types
32-bit x86: Thread-Local Variable Access
32-bit x86: General Dynamic (GD)
32-bit x86: Initial Executable (IE)
32-bit x86: Local Executable (LE)
32-bit x86: Thread-Local Storage Relocation Types
A. Linker and Libraries Updates and New Features
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.
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 the block is first referenced from a specific thread.
This model is a optimization of the GD model. The compiler might determine that a variable is bound locally, or protected, within the object being built. In this case, the compiler instructs the link-editor to statically bind the dynamic tlsoffset and use this model. This model 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.
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 that are available at process startup, plus a small backup reservation. See Program Startup. In this model, the thread pointer-relative offset for a given variable x is stored in the GOT entry for x.
This model can reference a limited number of TLS variables from shared libraries loaded after initial process startup, such as by means of lazy loading, filters, or dlopen(3C). This access is satisfied from a fixed backup reservation. This reservation can only provide storage for uninitialized TLS data items. For maximum flexibility, shared objects should reference thread-local variables using a dynamic TLS model.
Note - Filters can be employed to dynamically select the use of static TLS. A shared object can be built to use dynamic TLS, and act as an auxiliary filter upon a counterpart built to use static TLS. If resourses allow the static TLS object to be loaded, the object is used. Otherwise, a fall back to the dynamic TLS object insures that the functionality provided by the shared object is always available. For more information on filters see Shared Objects as Filters.
This model can only reference TLS variables which are part of the TLS block of the dynamic executable. The link-editor calculates the thread pointer-relative offsets statically, without the need for dynamic relocations, or the extra reference to the GOT. 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 the transition is determined appropriate. 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.
Knowledge of the TLS access model, together with the type of object being created, allows the link-editor to perform translations. An example is if a relocatable object using the GD access model is being linked into a dynamic executable. In this case, the link-editor can transition the references using the IE or LE access models, as appropriate. The relocations that are required for the model are then performed.
The following diagram illustrates the different access models, together with the transition of one model to another model.
Figure 14-2 Thread-Local Storage Access Models and Transitions
On SPARC, the following code sequence models are available for accessing thread-local variables.
This code sequence implements the GD model described in Thread-Local Storage Access Models.
Table 14-2 SPARC: General Dynamic Thread-Local Variable Access Codes
|
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 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.
The load object index and TLS block index for x are not known until runtime. Therefore, 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 second 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 uses the special syntax, x@TLSPLT. This call references the TLS variable and 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. The add instruction can not be placed into the delay slot for the call. This requirement is necessary 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 requirement permits the link-editor to identify the GOT-pointer register during a code transformation.
This code sequence implements the LD model described in Thread-Local Storage Access Models.
Table 14-3 SPARC: Local Dynamic Thread-Local Variable Access Codes
|
The first sethi instruction and add instruction 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 GOT 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.
The load object index is not known until runtime. Therefore, 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 instruction and xor instruction 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 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.
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 requirement permits the link-editor to identify the register during a code transformation.
This code sequence implements the IE model described in Thread-Local Storage Access Models.
Table 14-4 32-bit SPARC: Initial Executable Thread-Local Variable Access Codes
|
The sethi instruction and or instruction 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 GOT to store the static TLS offset for symbol x. An 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 requirement permits the link-editor to identify the GOT-pointer register during a code transformation.
This code sequence implements the IE model described in Thread-Local Storage Access Models.
Table 14-5 64-bit SPARC: Initial Executable Thread-Local Variable Access Codes
|
This code sequence implements the LE model described in Thread-Local Storage Access Models.
Table 14-6 SPARC: Local Executable Thread-Local Variable Access Codes
|
The sethi and xor 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.
The TLS relocations that are listed in the following table are defined for SPARC. Descriptions in the table use the following notation.
Allocates two contiguous entries in the GOT 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.
Calculates the tlsoffset relative to the TLS block.
Calculates the negative tlsoffset relative to the static TLS block. This value is added to the thread-pointer to calculate the TLS address.
Calculates the object identifier of the object containing a TLS symbol.
Table 14-7 SPARC: Thread-Local Storage Relocation Types
|
Some relocation types have semantics beyond simple calculations.
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 relocation is used to transition between TLS models at link-edit time.
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.
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 relocation is used to transition between TLS models at link-edit time.
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.
This relocation tags the final add instruction in a LD code sequence. The register which contains the object address that is computed in the initial part of the code sequence is the first register in this instruction. This relocation permits the link-editor to identify this register for code transformations.
This relocation tags the ld instruction in the 32–bit IE code sequence. This relocation is used to transition between TLS models at link-edit time.
This relocation tags the ldx instruction in the 64–bit IE code sequence. This relocation is used to transition between TLS models at link-edit time.
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.
On x86, the following code sequence models are available for accessing TLS.
This code sequence implements the GD model described in Thread-Local Storage Access Models.
Table 14-8 32-bit x86: General Dynamic Thread-Local Variable Access Codes
|
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.
This code sequence implements the LD model described in Thread-Local Storage Access Models.
Table 14-9 32-bit x86: Local Dynamic Thread-Local Variable Access Codes
|
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.
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 14-10 32-bit x86: Initial Executable, Position Independent, Thread-Local Variable Access Codes
|
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 14-11 32-bit x86: Initial Executable, Position Dependent, Thread-Local Variable Access Codes
|
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 14-12 32-bit x86: Initial Executable, Position Independent, Dynamic Thread-Local Variable Access Codes
|
Table 14-13 32-bit x86: Initial Executable, Position Independent, Thread-Local Variable Access Codes
|
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.
This code sequence implements the LE model described in Thread-Local Storage Access Models.
Table 14-14 32-bit x86: Local Executable Thread-Local Variable Access Codes
|
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 14-15 32-bit x86: Local Executable Thread-Local Variable Access Codes
|
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 14-16 32-bit x86: Local Executable Thread-Local Variable Access Codes
|
The TLS relocations that are listed in the following table are defined for x86. Descriptions in the table use the following notation.
This relocation is handled as if it were a R_386_PLT32 relocation referencing the ___tls_get_addr() function.
Allocates two contiguous entries in the GOT to hold a TLS_index structure. This structure is passed to the ___tls_get_addr(). The ti_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.
Allocates a entry in the GOT, and initializes the entry with the negative tlsoffset relative to the static TLS block. This sequence is performed at runtime using the R_386_TLS_TPOFF relocation.
This expression is similar to @gotntpoff, but is 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.
Calculates the negative tlsoffset relative to the static TLS block.
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.
Calculates the object identifier of the object containing a TLS symbol.
Table 14-17 32-bit x86: Thread-Local Storage Relocation Types
|
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.
Table 14-18 x64: General Dynamic Thread-Local Variable Access Codes
|
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.
Note - The leaq instruction computes the address of the first GOT entry. This computation is carried out by adding the PC-relative address of the GOT, which was determined at link-edit time, to the current instruction pointer. The .byte, .word, and .rex64 prefixes insure that the whole instruction sequence occupies 16 bytes. Prefixes are employed, as prefixes have no negative inpact on the code.
This code sequence implements the LD model described in Thread-Local Storage Access Models.
Table 14-19 x64: Local Dynamic Thread-Local Variable Access Codes
|
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.
Table 14-20 x64: Initial Executable, Thread-Local Variable Access Codes
|
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 later loaded by the addq instruction.
To load the contents of x, rather than the address of x, the following sequence is available.
Table 14-21 x64: Initial Executable, Thread-Local Variable Access Codes II
|
This code sequence implements the LE model described in Thread-Local Storage Access Models.
Table 14-22 x64: Local Executable Thread-Local Variable Access Codes
|
To load the contents of a TLS variable instead of the address of a TLS variable, the following sequence can be used.
Table 14-23 x64: Local Executable Thread-Local Variable Access Codes II
|
The following sequence is even shorter.
Table 14-24 x64: Local Executable Thread-Local Variable Access Codes III
|
The TLS relocations that are listed in the following table are defined for x64. Descriptions in the table use the following notation.
Allocates two contiguous entries in the GOT to hold a TLS_index structure. This structure is passed to __tls_get_addr(). At runtime, the ti_offset offset field of the object is set to zero, and the ti_module offset is initialized. A call to the __tls_get_addr() function returns the starting offset if the dynamic TLS block. This instruction can be used in the exact code sequence.
Calculates the offset of the variable relative to the start of the TLS block which contains the variable. The computed value is used as an immediate value of an addend, and is not associated with a specific register.
Calculates the object identifier of the object containing a TLS symbol.
Allocates a entry in the GOT, to hold a variable offset in the initial TLS block. This offset is relative to the TLS blocks end, %fs:0. The operator can only be used with a movq or addq instruction.
Calculates the offset of a variable relative to the TLS block end, %fs:0. No GOT entry is created.
Table 14-25 x64: Thread-Local Storage Relocation Types
|