libc-tls.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /* Initialization code for TLS in statically linked application.
  2. Copyright (C) 2002-2026 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #include <startup.h>
  16. #include <errno.h>
  17. #include <ldsodefs.h>
  18. #include <tls.h>
  19. #include <dl-tls.h>
  20. #include <unistd.h>
  21. #include <stdio.h>
  22. #include <sys/param.h>
  23. #include <array_length.h>
  24. #include <pthreadP.h>
  25. #include <dl-call_tls_init_tp.h>
  26. #include <dl-extra_tls.h>
  27. #include <array_length.h>
  28. #include <elf/dl-tls_block_align.h>
  29. #include <dl-symbol-redir-ifunc.h>
  30. #ifdef SHARED
  31. #error makefile bug, this file is for static only
  32. #endif
  33. dtv_t _dl_static_dtv[2 + TLS_SLOTINFO_SURPLUS];
  34. static struct dtv_slotinfo_list static_slotinfo =
  35. {
  36. /* Allocate an array of 2 + TLS_SLOTINFO_SURPLUS elements. */
  37. .slotinfo = { [array_length (_dl_static_dtv) - 1] = { 0 } },
  38. };
  39. /* Highest dtv index currently needed. */
  40. size_t _dl_tls_max_dtv_idx;
  41. /* Flag signalling whether there are gaps in the module ID allocation. */
  42. bool _dl_tls_dtv_gaps;
  43. /* Information about the dtv slots. */
  44. struct dtv_slotinfo_list *_dl_tls_dtv_slotinfo_list;
  45. /* Number of modules in the static TLS block. */
  46. size_t _dl_tls_static_nelem;
  47. /* Size of the static TLS block. */
  48. size_t _dl_tls_static_size;
  49. /* Size actually allocated in the static TLS block. */
  50. size_t _dl_tls_static_used;
  51. /* Alignment requirement of the static TLS block. */
  52. size_t _dl_tls_static_align;
  53. /* Size of surplus space in the static TLS area for dynamically
  54. loaded modules with IE-model TLS or for TLSDESC optimization.
  55. See comments in elf/dl-tls.c where it is initialized. */
  56. size_t _dl_tls_static_surplus;
  57. /* Remaining amount of static TLS that may be used for optimizing
  58. dynamic TLS access (e.g. with TLSDESC). */
  59. size_t _dl_tls_static_optional;
  60. /* Generation counter for the dtv. */
  61. size_t _dl_tls_generation;
  62. /* Additional definitions needed by TLS initialization. */
  63. #ifdef TLS_INIT_HELPER
  64. TLS_INIT_HELPER
  65. #endif
  66. static void
  67. init_slotinfo (struct link_map *main_map)
  68. {
  69. /* Create the slotinfo list. Note that the type of static_slotinfo
  70. has effectively a zero-length array, so we cannot use the size of
  71. static_slotinfo to determine the array length. */
  72. static_slotinfo.len = array_length (_dl_static_dtv);
  73. /* static_slotinfo.next = NULL; -- Already zero. */
  74. main_map->l_tls_modid = 1;
  75. static_slotinfo.slotinfo[1].map = main_map;
  76. main_map->l_tls_in_slotinfo = 1;
  77. /* The slotinfo list. Will be extended by the code doing dynamic
  78. linking. */
  79. GL(dl_tls_max_dtv_idx) = 1;
  80. GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo;
  81. }
  82. /* Perform TLS setup for statically linked binaries. Similar to
  83. init_tls in elf/rtld.c. */
  84. void
  85. __libc_setup_tls (void)
  86. {
  87. size_t memsz = 0;
  88. size_t filesz = 0;
  89. void *initimage = NULL;
  90. size_t align = 0;
  91. size_t max_align = TCB_ALIGNMENT;
  92. const ElfW(Phdr) *phdr;
  93. struct link_map *main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
  94. __tls_pre_init_tp ();
  95. /* Look through the TLS segment if there is any. */
  96. for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr)
  97. if (phdr->p_type == PT_TLS)
  98. {
  99. /* Remember the values we need. */
  100. memsz = phdr->p_memsz;
  101. filesz = phdr->p_filesz;
  102. initimage = (void *) phdr->p_vaddr + main_map->l_addr;
  103. align = phdr->p_align;
  104. if (phdr->p_align > max_align)
  105. max_align = phdr->p_align;
  106. main_map->l_tls_align = align;
  107. main_map->l_tls_blocksize = memsz;
  108. main_map->l_tls_initimage = initimage;
  109. main_map->l_tls_initimage_size = filesz;
  110. init_slotinfo (main_map);
  111. break;
  112. }
  113. /* Number of elements in the static TLS block. */
  114. GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
  115. /* Calculate the size of the static TLS surplus, with 0 auditors. */
  116. _dl_tls_static_surplus_init (0);
  117. /* Calculate the TLS block size. */
  118. _dl_determine_tlsoffset ();
  119. /* See _dl_allocate_tls_storage in elf/dl-tls.c. */
  120. void *tcbp;
  121. {
  122. size_t size = _dl_tls_block_size_with_pre ();
  123. void *allocated = _dl_early_allocate (size + GLRO (dl_tls_static_align));
  124. if (allocated == NULL)
  125. _startup_fatal_tls_error ();
  126. tcbp = _dl_tls_block_align (size, allocated);
  127. }
  128. /* Initialize the dtv. [0] is the length, [1] the generation counter. */
  129. _dl_static_dtv[0].counter = array_length (_dl_static_dtv) - 2;
  130. /* Install the pointer to the DTV. See allocate_dtv in elf/dl-tls.c. */
  131. INSTALL_DTV (tcbp, _dl_static_dtv);
  132. /* _dl_allocate_tls_init uses recursive locking and the TCB, so this
  133. has to come first. */
  134. call_tls_init_tp (tcbp);
  135. /* Initialize the TLS image for the allocated TCB. */
  136. _dl_allocate_tls_init (tcbp, true);
  137. }