tlsaddr.S 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*++
  2. Copyright (c) 2015 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. tlsaddr.S
  9. Abstract:
  10. This module implements functionality for fast access Thread Local Storage
  11. symbol lookup.
  12. Author:
  13. Evan Green 20-Apr-2015
  14. Environment:
  15. User Mode C Library
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/kernel/x86.inc>
  21. //
  22. // ---------------------------------------------------------------- Definitions
  23. //
  24. //
  25. // Define the offset of the TLS vector within the TCB.
  26. //
  27. .equ TCB_TLS_VECTOR_OFFSET, 0x4
  28. //
  29. // ----------------------------------------------------------------------- Code
  30. //
  31. //
  32. // .text specifies that this code belongs in the executable section.
  33. //
  34. // .code32 specifies that this is 32-bit protected mode code.
  35. //
  36. .text
  37. .code32
  38. //
  39. // LIBC_API
  40. // void *
  41. // ___tls_get_addr (
  42. // PTLS_INDEX Entry
  43. // )
  44. //
  45. /*++
  46. Routine Description:
  47. This routine returns the address of a thread-local symbol. References to
  48. this function are emitted directly by the compiler.
  49. Arguments:
  50. Entry - Supplies a pointer to the TLS symbol information. This argument is
  51. supplied in the eax register.
  52. Return Value:
  53. Returns a pointer to the thread local symbol.
  54. --*/
  55. EXPORTED_FUNCTION(___tls_get_addr)
  56. movl %gs:(TCB_TLS_VECTOR_OFFSET), %ecx # Get the TLS vector.
  57. movl (%eax), %edx # Get the module ID.
  58. cmpl %edx, (%ecx) # Compare module ID to generation number.
  59. jb ___tls_get_addrSlowPath
  60. movl (%ecx, %edx, 4), %ecx # Get the vector[ModuleId].
  61. cmpl $0, %ecx # Compare against NULL.
  62. je ___tls_get_addrSlowPath # Do the slow path if it's the first run.
  63. movl 4(%eax), %eax # Get the TLS entry offset.
  64. addl %ecx, %eax # Add in the TLS base.
  65. ret # Return the value.
  66. //
  67. // Call the slow C routine.
  68. //
  69. ___tls_get_addrSlowPath:
  70. pushl %ebx # Save ebx.
  71. call __x86.get_pc_thunk.bx # ebx must be set up correctly for the PLT.
  72. addl $_GLOBAL_OFFSET_TABLE_,%ebx # Get GOT address.
  73. pushl %eax # Push the structure parameter.
  74. call OsGetTlsAddress@PLT # Call the OS API routine.
  75. addl $4, %esp # Pop the parameter.
  76. popl %ebx # Restore ebx.
  77. ret # Return.
  78. END_FUNCTION(___tls_get_addr)