/*++ Copyright (c) 2015 Minoca Corp. This file is licensed under the terms of the GNU General Public License version 3. Alternative licensing terms are available. Contact info@minocacorp.com for details. See the LICENSE file at the root of this project for complete licensing information. Module Name: tlsaddr.S Abstract: This module implements functionality for fast access Thread Local Storage symbol lookup. Author: Evan Green 20-Apr-2015 Environment: User Mode C Library --*/ // // ------------------------------------------------------------------- Includes // #include // // ---------------------------------------------------------------- Definitions // // // Define the offset of the TLS vector within the TCB. // .equ TCB_TLS_VECTOR_OFFSET, 0x4 // // ----------------------------------------------------------------------- Code // // // .text specifies that this code belongs in the executable section. // // .code32 specifies that this is 32-bit protected mode code. // .text .code32 // // LIBC_API // void * // ___tls_get_addr ( // PTLS_INDEX Entry // ) // /*++ Routine Description: This routine returns the address of a thread-local symbol. References to this function are emitted directly by the compiler. Arguments: Entry - Supplies a pointer to the TLS symbol information. This argument is supplied in the eax register. Return Value: Returns a pointer to the thread local symbol. --*/ EXPORTED_FUNCTION(___tls_get_addr) movl %gs:(TCB_TLS_VECTOR_OFFSET), %ecx # Get the TLS vector. movl (%eax), %edx # Get the module ID. cmpl %edx, (%ecx) # Compare module ID to generation number. jb ___tls_get_addrSlowPath movl (%ecx, %edx, 4), %ecx # Get the vector[ModuleId]. cmpl $0, %ecx # Compare against NULL. je ___tls_get_addrSlowPath # Do the slow path if it's the first run. movl 4(%eax), %eax # Get the TLS entry offset. addl %ecx, %eax # Add in the TLS base. ret # Return the value. // // Call the slow C routine. // ___tls_get_addrSlowPath: pushl %ebx # Save ebx. call __x86.get_pc_thunk.bx # ebx must be set up correctly for the PLT. addl $_GLOBAL_OFFSET_TABLE_,%ebx # Get GOT address. pushl %eax # Push the structure parameter. call OsGetTlsAddress@PLT # Call the OS API routine. addl $4, %esp # Pop the parameter. popl %ebx # Restore ebx. ret # Return. END_FUNCTION(___tls_get_addr)