mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-10-30 10:45:40 +03:00 
			
		
		
		
	Use the same code to compute the TLS block size and its alignment.
The code in elf/dl-tls.c is linked in anyway for all binaries
due to the reference to _dl_tls_static_surplus_init.
It is not possible to call _dl_allocate_tls_storage directly
because malloc is not available in the static case.  (The
dynamic linker uses the minimal malloc at this stage.)  Therefore,
split _dl_tls_block_size_with_pre and _dl_tls_block_align from
_dl_allocate_tls_storage, and call those new functions from
__libc_setup_tls.
This fixes extra TLS allocation for the static case, and apparently
some pre-existing bugs as well (the independent recomputation of
TLS block sizes in init_static_tls looks rather suspect).
Fixes commit 0e411c5d30 ("Add generic
'extra TLS'").
		
	
		
			
				
	
	
		
			71 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			71 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Computation of TLS block size and its alignment.
 | |
|    Copyright (C) 2002-2025 Free Software Foundation, Inc.
 | |
|    This file is part of the GNU C Library.
 | |
| 
 | |
|    The GNU C Library is free software; you can redistribute it and/or
 | |
|    modify it under the terms of the GNU Lesser General Public
 | |
|    License as published by the Free Software Foundation; either
 | |
|    version 2.1 of the License, or (at your option) any later version.
 | |
| 
 | |
|    The GNU C Library is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|    Lesser General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU Lesser General Public
 | |
|    License along with the GNU C Library; if not, see
 | |
|    <https://www.gnu.org/licenses/>.  */
 | |
| 
 | |
| /* Compute the size of the TLS block for memory allocation.  */
 | |
| static size_t
 | |
| _dl_tls_block_size_with_pre (void)
 | |
| {
 | |
|   size_t size = GLRO (dl_tls_static_size);
 | |
| 
 | |
| #if TLS_DTV_AT_TP
 | |
|   /* Memory layout is:
 | |
|      [ TLS_PRE_TCB_SIZE ] [ TLS_TCB_SIZE ] [ TLS blocks ]
 | |
|                           ^ This should be returned.  */
 | |
|   size += TLS_PRE_TCB_SIZE;
 | |
| #endif
 | |
|   return size;
 | |
| }
 | |
| 
 | |
| /* SIZE must be the value returned by _dl_tls_block_size_with_pre.
 | |
|    ALLOCATED must point to at least SIZE + GLRO (dl_tls_static_align)
 | |
|    bytes.  */
 | |
| static void *
 | |
| _dl_tls_block_align (size_t size, void *allocated)
 | |
| {
 | |
|   void *result;
 | |
|   size_t alignment = GLRO (dl_tls_static_align);
 | |
| 
 | |
| #if TLS_TCB_AT_TP
 | |
|   /* The TCB follows the TLS blocks, which determine the alignment.
 | |
|      (TCB alignment requirements have been taken into account when
 | |
|      calculating GLRO (dl_tls_static_align).)  */
 | |
|   void *aligned = (void *) roundup ((uintptr_t) allocated, alignment);
 | |
|   result = aligned + size - TLS_TCB_SIZE;
 | |
| 
 | |
|   /* Clear the TCB data structure.  We can't ask the caller (i.e.
 | |
|      libpthread) to do it, because we will initialize the DTV et al.  */
 | |
|   memset (result, '\0', TLS_TCB_SIZE);
 | |
| #elif TLS_DTV_AT_TP
 | |
|   /* Pre-TCB and TCB come before the TLS blocks.  The layout computed
 | |
|      in _dl_determine_tlsoffset assumes that the TCB is aligned to the
 | |
|      TLS block alignment, and not just the TLS blocks after it.  This
 | |
|      can leave an unused alignment gap between the TCB and the TLS
 | |
|      blocks.  */
 | |
|   result = (void *) roundup
 | |
|     (sizeof (void *) + TLS_PRE_TCB_SIZE + (uintptr_t) allocated,
 | |
|      alignment);
 | |
| 
 | |
|   /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before
 | |
|      it.  We can't ask the caller (i.e. libpthread) to do it, because
 | |
|      we will initialize the DTV et al.  */
 | |
|   memset (result - TLS_PRE_TCB_SIZE, '\0', TLS_PRE_TCB_SIZE + TLS_TCB_SIZE);
 | |
| #endif
 | |
| 
 | |
|   return result;
 | |
| }
 |