forked from rpms/glibc
		
	import glibc-2.28-189.1.el8
This commit is contained in:
		
							parent
							
								
									e3ace7a765
								
							
						
					
					
						commit
						385bc0f199
					
				| @ -159,6 +159,7 @@ en_SG/ISO-8859-1 \ | ||||
| en_US.UTF-8/UTF-8 \ | ||||
| en_US/ISO-8859-1 \ | ||||
| en_US.ISO-8859-15/ISO-8859-15 \ | ||||
| en_US@ampm.UTF-8/UTF-8 \ | ||||
| en_ZA.UTF-8/UTF-8 \ | ||||
| en_ZA/ISO-8859-1 \ | ||||
| en_ZM/UTF-8 \ | ||||
|  | ||||
							
								
								
									
										38
									
								
								SOURCES/glibc-rh1929928-1.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								SOURCES/glibc-rh1929928-1.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| This patch is a downstream-only variant of this upstream commit: | ||||
| 
 | ||||
| commit 45b1e17e9150dbd9ac2d578579063fbfa8e1b327 | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Thu Dec 17 10:03:05 2020 +0000 | ||||
| 
 | ||||
|     aarch64: use PTR_ARG and SIZE_ARG instead of DELOUSE | ||||
|      | ||||
|     DELOUSE was added to asm code to make them compatible with non-LP64 | ||||
|     ABIs, but it is an unfortunate name and the code was not compatible | ||||
|     with ABIs where pointer and size_t are different. Glibc currently | ||||
|     only supports the LP64 ABI so these macros are not really needed or | ||||
|     tested, but for now the name is changed to be more meaningful instead | ||||
|     of removing them completely. | ||||
|      | ||||
|     Some DELOUSE macros were dropped: clone, strlen and strnlen used it | ||||
|     unnecessarily. | ||||
|      | ||||
|     The out of tree ILP32 patches are currently not maintained and will | ||||
|     likely need a rework to rebase them on top of the time64 changes. | ||||
| 
 | ||||
| Keeping the DELOUSE macro avoids the need to update all string | ||||
| functions.  Lack of BTI markers and architecture variants cause many | ||||
| conflicts in a full upstream backport. | ||||
| 
 | ||||
| diff --git a/sysdeps/aarch64/sysdep.h b/sysdeps/aarch64/sysdep.h
 | ||||
| index 5b30709436d3acea..1bcf15d4f18586ba 100644
 | ||||
| --- a/sysdeps/aarch64/sysdep.h
 | ||||
| +++ b/sysdeps/aarch64/sysdep.h
 | ||||
| @@ -32,6 +32,8 @@
 | ||||
|  # define PTR_LOG_SIZE		2 | ||||
|  # define DELOUSE(n)		mov     w##n, w##n | ||||
|  #endif | ||||
| +#define PTR_ARG(n) DELOUSE(n)
 | ||||
| +#define SIZE_ARG(n) DELOUSE(n)
 | ||||
|   | ||||
|  #define PTR_SIZE	(1<<PTR_LOG_SIZE) | ||||
|   | ||||
							
								
								
									
										88
									
								
								SOURCES/glibc-rh1929928-2.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								SOURCES/glibc-rh1929928-2.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | ||||
| commit 77d175e14e5f4cf24e9579c03eef5d006a286316 | ||||
| Author: Naohiro Tamura <naohirot@jp.fujitsu.com> | ||||
| Date:   Wed May 12 09:26:40 2021 +0000 | ||||
| 
 | ||||
|     config: Added HAVE_AARCH64_SVE_ASM for aarch64 | ||||
|      | ||||
|     This patch checks if assembler supports '-march=armv8.2-a+sve' to | ||||
|     generate SVE code or not, and then define HAVE_AARCH64_SVE_ASM macro. | ||||
| 
 | ||||
| Conflicts: | ||||
| 	config.h.in | ||||
| 	  (missing PAC+BTI support downstream, missing other ports) | ||||
| 
 | ||||
| diff --git a/config.h.in b/config.h.in
 | ||||
| index 8520b0fa8d4668fb..94d5ea367e10f849 100644
 | ||||
| --- a/config.h.in
 | ||||
| +++ b/config.h.in
 | ||||
| @@ -112,6 +112,11 @@
 | ||||
|  /* AArch64 big endian ABI */ | ||||
|  #undef HAVE_AARCH64_BE | ||||
|   | ||||
| +/* Assembler support ARMv8.2-A SVE.
 | ||||
| +   This macro becomes obsolete when glibc increased the minimum
 | ||||
| +   required version of GNU 'binutils' to 2.28 or later. */
 | ||||
| +#define HAVE_AARCH64_SVE_ASM 0
 | ||||
| +
 | ||||
|  /* RISC-V integer ABI for ld.so.  */ | ||||
|  #undef RISCV_ABI_XLEN | ||||
|   | ||||
| diff --git a/sysdeps/aarch64/configure b/sysdeps/aarch64/configure
 | ||||
| index f78a79338aba1e34..9fb713155d4ee6d8 100644
 | ||||
| --- a/sysdeps/aarch64/configure
 | ||||
| +++ b/sysdeps/aarch64/configure
 | ||||
| @@ -212,3 +212,31 @@ fi
 | ||||
|  $as_echo "$libc_cv_aarch64_variant_pcs" >&6; } | ||||
|  config_vars="$config_vars | ||||
|  aarch64-variant-pcs = $libc_cv_aarch64_variant_pcs" | ||||
| +
 | ||||
| +# Check if asm support armv8.2-a+sve
 | ||||
| +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SVE support in assembler" >&5
 | ||||
| +$as_echo_n "checking for SVE support in assembler... " >&6; }
 | ||||
| +if ${libc_cv_asm_sve+:} false; then :
 | ||||
| +  $as_echo_n "(cached) " >&6
 | ||||
| +else
 | ||||
| +  cat > conftest.s <<\EOF
 | ||||
| +        ptrue p0.b
 | ||||
| +EOF
 | ||||
| +if { ac_try='${CC-cc} -c -march=armv8.2-a+sve conftest.s 1>&5'
 | ||||
| +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
 | ||||
| +  (eval $ac_try) 2>&5
 | ||||
| +  ac_status=$?
 | ||||
| +  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
 | ||||
| +  test $ac_status = 0; }; }; then
 | ||||
| +  libc_cv_aarch64_sve_asm=yes
 | ||||
| +else
 | ||||
| +  libc_cv_aarch64_sve_asm=no
 | ||||
| +fi
 | ||||
| +rm -f conftest*
 | ||||
| +fi
 | ||||
| +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_sve" >&5
 | ||||
| +$as_echo "$libc_cv_asm_sve" >&6; }
 | ||||
| +if test $libc_cv_aarch64_sve_asm = yes; then
 | ||||
| +  $as_echo "#define HAVE_AARCH64_SVE_ASM 1" >>confdefs.h
 | ||||
| +
 | ||||
| +fi
 | ||||
| diff --git a/sysdeps/aarch64/configure.ac b/sysdeps/aarch64/configure.ac
 | ||||
| index 7f13bfb93b60bfd7..0236cfcdf3c8d10d 100644
 | ||||
| --- a/sysdeps/aarch64/configure.ac
 | ||||
| +++ b/sysdeps/aarch64/configure.ac
 | ||||
| @@ -42,3 +42,18 @@ EOF
 | ||||
|    fi | ||||
|    rm -rf conftest.*]) | ||||
|  LIBC_CONFIG_VAR([aarch64-variant-pcs], [$libc_cv_aarch64_variant_pcs]) | ||||
| +
 | ||||
| +# Check if asm support armv8.2-a+sve
 | ||||
| +AC_CACHE_CHECK(for SVE support in assembler, libc_cv_asm_sve, [dnl
 | ||||
| +cat > conftest.s <<\EOF
 | ||||
| +        ptrue p0.b
 | ||||
| +EOF
 | ||||
| +if AC_TRY_COMMAND(${CC-cc} -c -march=armv8.2-a+sve conftest.s 1>&AS_MESSAGE_LOG_FD); then
 | ||||
| +  libc_cv_aarch64_sve_asm=yes
 | ||||
| +else
 | ||||
| +  libc_cv_aarch64_sve_asm=no
 | ||||
| +fi
 | ||||
| +rm -f conftest*])
 | ||||
| +if test $libc_cv_aarch64_sve_asm = yes; then
 | ||||
| +  AC_DEFINE(HAVE_AARCH64_SVE_ASM)
 | ||||
| +fi
 | ||||
							
								
								
									
										140
									
								
								SOURCES/glibc-rh1929928-3.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								SOURCES/glibc-rh1929928-3.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,140 @@ | ||||
| commit 38560563587ad8eafa700c56800ff844f18fbad1 | ||||
| Author: Naohiro Tamura <naohirot@fujitsu.com> | ||||
| Date:   Thu May 20 07:34:37 2021 +0000 | ||||
| 
 | ||||
|     aarch64: Added Vector Length Set test helper script | ||||
|      | ||||
|     This patch is a test helper script to change Vector Length for child | ||||
|     process. This script can be used as test-wrapper for 'make check'. | ||||
|      | ||||
|     Usage examples: | ||||
|      | ||||
|     ~/build$ make check subdirs=string \ | ||||
|     test-wrapper='~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 16' | ||||
|      | ||||
|     ~/build$ ~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 16 \ | ||||
|     make test t=string/test-memcpy | ||||
|      | ||||
|     ~/build$ ~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 32 \ | ||||
|     ./debugglibc.sh string/test-memmove | ||||
|      | ||||
|     ~/build$ ~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 64 \ | ||||
|     ./testrun.sh string/test-memset | ||||
| 
 | ||||
| diff --git a/INSTALL b/INSTALL
 | ||||
| index 065565093bd76d5b..b3a4370f592c5047 100644
 | ||||
| --- a/INSTALL
 | ||||
| +++ b/INSTALL
 | ||||
| @@ -387,6 +387,10 @@ the same syntax as 'test-wrapper-env', the only difference in its
 | ||||
|  semantics being starting with an empty set of environment variables | ||||
|  rather than the ambient set. | ||||
|   | ||||
| +   For AArch64 with SVE, when testing the GNU C Library, 'test-wrapper'
 | ||||
| +may be set to "SRCDIR/sysdeps/unix/sysv/linux/aarch64/vltest.py
 | ||||
| +VECTOR-LENGTH" to change Vector Length.
 | ||||
| +
 | ||||
|  Installing the C Library | ||||
|  ======================== | ||||
|   | ||||
| diff --git a/manual/install.texi b/manual/install.texi
 | ||||
| index 7e9f2be150e6f98a..c262fd56d0cef67b 100644
 | ||||
| --- a/manual/install.texi
 | ||||
| +++ b/manual/install.texi
 | ||||
| @@ -425,6 +425,9 @@ use has the same syntax as @samp{test-wrapper-env}, the only
 | ||||
|  difference in its semantics being starting with an empty set of | ||||
|  environment variables rather than the ambient set. | ||||
|   | ||||
| +For AArch64 with SVE, when testing @theglibc{}, @samp{test-wrapper}
 | ||||
| +may be set to "@var{srcdir}/sysdeps/unix/sysv/linux/aarch64/vltest.py
 | ||||
| +@var{vector-length}" to change Vector Length.
 | ||||
|   | ||||
|  @node Running make install | ||||
|  @appendixsec Installing the C Library | ||||
| diff --git a/sysdeps/unix/sysv/linux/aarch64/vltest.py b/sysdeps/unix/sysv/linux/aarch64/vltest.py
 | ||||
| new file mode 100755 | ||||
| index 0000000000000000..bed62ad151e06868
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/unix/sysv/linux/aarch64/vltest.py
 | ||||
| @@ -0,0 +1,82 @@
 | ||||
| +#!/usr/bin/python3
 | ||||
| +# Set Scalable Vector Length test helper
 | ||||
| +# Copyright (C) 2021 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/>.
 | ||||
| +"""Set Scalable Vector Length test helper.
 | ||||
| +
 | ||||
| +Set Scalable Vector Length for child process.
 | ||||
| +
 | ||||
| +examples:
 | ||||
| +
 | ||||
| +~/build$ make check subdirs=string \
 | ||||
| +test-wrapper='~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 16'
 | ||||
| +
 | ||||
| +~/build$ ~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 16 \
 | ||||
| +make test t=string/test-memcpy
 | ||||
| +
 | ||||
| +~/build$ ~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 32 \
 | ||||
| +./debugglibc.sh string/test-memmove
 | ||||
| +
 | ||||
| +~/build$ ~/glibc/sysdeps/unix/sysv/linux/aarch64/vltest.py 64 \
 | ||||
| +./testrun.sh string/test-memset
 | ||||
| +"""
 | ||||
| +import argparse
 | ||||
| +from ctypes import cdll, CDLL
 | ||||
| +import os
 | ||||
| +import sys
 | ||||
| +
 | ||||
| +EXIT_SUCCESS = 0
 | ||||
| +EXIT_FAILURE = 1
 | ||||
| +EXIT_UNSUPPORTED = 77
 | ||||
| +
 | ||||
| +AT_HWCAP = 16
 | ||||
| +HWCAP_SVE = (1 << 22)
 | ||||
| +
 | ||||
| +PR_SVE_GET_VL = 51
 | ||||
| +PR_SVE_SET_VL = 50
 | ||||
| +PR_SVE_SET_VL_ONEXEC = (1 << 18)
 | ||||
| +PR_SVE_VL_INHERIT = (1 << 17)
 | ||||
| +PR_SVE_VL_LEN_MASK = 0xffff
 | ||||
| +
 | ||||
| +def main(args):
 | ||||
| +    libc = CDLL("libc.so.6")
 | ||||
| +    if not libc.getauxval(AT_HWCAP) & HWCAP_SVE:
 | ||||
| +        print("CPU doesn't support SVE")
 | ||||
| +        sys.exit(EXIT_UNSUPPORTED)
 | ||||
| +
 | ||||
| +    libc.prctl(PR_SVE_SET_VL,
 | ||||
| +               args.vl[0] | PR_SVE_SET_VL_ONEXEC | PR_SVE_VL_INHERIT)
 | ||||
| +    os.execvp(args.args[0], args.args)
 | ||||
| +    print("exec system call failure")
 | ||||
| +    sys.exit(EXIT_FAILURE)
 | ||||
| +
 | ||||
| +if __name__ == '__main__':
 | ||||
| +    parser = argparse.ArgumentParser(description=
 | ||||
| +            "Set Scalable Vector Length test helper",
 | ||||
| +            formatter_class=argparse.ArgumentDefaultsHelpFormatter)
 | ||||
| +
 | ||||
| +    # positional argument
 | ||||
| +    parser.add_argument("vl", nargs=1, type=int,
 | ||||
| +                        choices=range(16, 257, 16),
 | ||||
| +                        help=('vector length '\
 | ||||
| +                              'which is multiples of 16 from 16 to 256'))
 | ||||
| +    # remainDer arguments
 | ||||
| +    parser.add_argument('args', nargs=argparse.REMAINDER,
 | ||||
| +                        help=('args '\
 | ||||
| +                              'which is passed to child process'))
 | ||||
| +    args = parser.parse_args()
 | ||||
| +    main(args)
 | ||||
							
								
								
									
										623
									
								
								SOURCES/glibc-rh1929928-4.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										623
									
								
								SOURCES/glibc-rh1929928-4.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,623 @@ | ||||
| commit fa527f345cbbe852ec085932fbea979956c195b5 | ||||
| Author: Naohiro Tamura <naohirot@jp.fujitsu.com> | ||||
| Date:   Thu May 27 07:42:35 2021 +0000 | ||||
| 
 | ||||
|     aarch64: Added optimized memcpy and memmove for A64FX | ||||
|      | ||||
|     This patch optimizes the performance of memcpy/memmove for A64FX [1] | ||||
|     which implements ARMv8-A SVE and has L1 64KB cache per core and L2 8MB | ||||
|     cache per NUMA node. | ||||
|      | ||||
|     The performance optimization makes use of Scalable Vector Register | ||||
|     with several techniques such as loop unrolling, memory access | ||||
|     alignment, cache zero fill, and software pipelining. | ||||
|      | ||||
|     SVE assembler code for memcpy/memmove is implemented as Vector Length | ||||
|     Agnostic code so theoretically it can be run on any SOC which supports | ||||
|     ARMv8-A SVE standard. | ||||
|      | ||||
|     We confirmed that all testcases have been passed by running 'make | ||||
|     check' and 'make xcheck' not only on A64FX but also on ThunderX2. | ||||
|      | ||||
|     And also we confirmed that the SVE 512 bit vector register performance | ||||
|     is roughly 4 times better than Advanced SIMD 128 bit register and 8 | ||||
|     times better than scalar 64 bit register by running 'make bench'. | ||||
|      | ||||
|     [1] https://github.com/fujitsu/A64FX | ||||
|      | ||||
|     Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com> | ||||
|     Reviewed-by: Szabolcs Nagy <Szabolcs.Nagy@arm.com> | ||||
| 
 | ||||
| Conflicts: | ||||
| 	manual/tunables.texi | ||||
| 	sysdeps/aarch64/multiarch/Makefile | ||||
| 	sysdeps/aarch64/multiarch/ifunc-impl-list.c | ||||
| 	sysdeps/aarch64/multiarch/init-arch.h | ||||
| 	sysdeps/aarch64/multiarch/memcpy.c | ||||
| 	sysdeps/aarch64/multiarch/memmove.c | ||||
| 	sysdeps/unix/sysv/linux/aarch64/cpu-features.c | ||||
| 	sysdeps/unix/sysv/linux/aarch64/cpu-features.h | ||||
| 	  (all conflicts due to missing optimizations for other CPUs) | ||||
| 
 | ||||
| diff --git a/manual/tunables.texi b/manual/tunables.texi
 | ||||
| index bd737b5d57080462..07887981748bc44b 100644
 | ||||
| --- a/manual/tunables.texi
 | ||||
| +++ b/manual/tunables.texi
 | ||||
| @@ -386,7 +386,7 @@ This tunable is specific to powerpc, powerpc64 and powerpc64le.
 | ||||
|  The @code{glibc.cpu.name=xxx} tunable allows the user to tell @theglibc{} to | ||||
|  assume that the CPU is @code{xxx} where xxx may have one of these values: | ||||
|  @code{generic}, @code{falkor}, @code{thunderxt88}, @code{thunderx2t99}, | ||||
| -@code{thunderx2t99p1}.
 | ||||
| +@code{thunderx2t99p1}, @code{a64fx}.
 | ||||
|   | ||||
|  This tunable is specific to aarch64. | ||||
|  @end deftp | ||||
| diff --git a/sysdeps/aarch64/multiarch/Makefile b/sysdeps/aarch64/multiarch/Makefile
 | ||||
| index 57ffdf72382c0a44..5a19ba0308e80983 100644
 | ||||
| --- a/sysdeps/aarch64/multiarch/Makefile
 | ||||
| +++ b/sysdeps/aarch64/multiarch/Makefile
 | ||||
| @@ -1,4 +1,5 @@
 | ||||
|  ifeq ($(subdir),string) | ||||
|  sysdep_routines += memcpy_generic memcpy_thunderx memcpy_thunderx2 \ | ||||
| -		   memcpy_falkor memmove_falkor memset_generic memset_falkor
 | ||||
| +		   memcpy_falkor memcpy_a64fx \
 | ||||
| +		   memmove_falkor memset_generic memset_falkor
 | ||||
|  endif | ||||
| diff --git a/sysdeps/aarch64/multiarch/ifunc-impl-list.c b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
 | ||||
| index e55be80103b948a2..f53db12acce37877 100644
 | ||||
| --- a/sysdeps/aarch64/multiarch/ifunc-impl-list.c
 | ||||
| +++ b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
 | ||||
| @@ -25,7 +25,7 @@
 | ||||
|  #include <stdio.h> | ||||
|   | ||||
|  /* Maximum number of IFUNC implementations.  */ | ||||
| -#define MAX_IFUNC	4
 | ||||
| +#define MAX_IFUNC	7
 | ||||
|   | ||||
|  size_t | ||||
|  __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, | ||||
| @@ -42,10 +42,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 | ||||
|  	      IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx) | ||||
|  	      IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx2) | ||||
|  	      IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_falkor) | ||||
| +#if HAVE_AARCH64_SVE_ASM
 | ||||
| +	      IFUNC_IMPL_ADD (array, i, memcpy, sve, __memcpy_a64fx)
 | ||||
| +#endif
 | ||||
|  	      IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_generic)) | ||||
|    IFUNC_IMPL (i, name, memmove, | ||||
|  	      IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_thunderx) | ||||
|  	      IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_falkor) | ||||
| +#if HAVE_AARCH64_SVE_ASM
 | ||||
| +	      IFUNC_IMPL_ADD (array, i, memmove, sve, __memmove_a64fx)
 | ||||
| +#endif
 | ||||
|  	      IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_generic)) | ||||
|    IFUNC_IMPL (i, name, memset, | ||||
|  	      /* Enable this on non-falkor processors too so that other cores | ||||
| diff --git a/sysdeps/aarch64/multiarch/init-arch.h b/sysdeps/aarch64/multiarch/init-arch.h
 | ||||
| index d1e5703cb25fdcff..65dc8f82ff23c754 100644
 | ||||
| --- a/sysdeps/aarch64/multiarch/init-arch.h
 | ||||
| +++ b/sysdeps/aarch64/multiarch/init-arch.h
 | ||||
| @@ -22,4 +22,6 @@
 | ||||
|    uint64_t __attribute__((unused)) midr =				      \ | ||||
|      GLRO(dl_aarch64_cpu_features).midr_el1;				      \ | ||||
|    unsigned __attribute__((unused)) zva_size =				      \ | ||||
| -    GLRO(dl_aarch64_cpu_features).zva_size;
 | ||||
| +    GLRO(dl_aarch64_cpu_features).zva_size;				      \
 | ||||
| +  bool __attribute__((unused)) sve =					      \
 | ||||
| +    GLRO(dl_aarch64_cpu_features).sve;
 | ||||
| diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c
 | ||||
| index 4a04a63b0fe0c84b..e0313c42e82a7b86 100644
 | ||||
| --- a/sysdeps/aarch64/multiarch/memcpy.c
 | ||||
| +++ b/sysdeps/aarch64/multiarch/memcpy.c
 | ||||
| @@ -32,6 +32,9 @@ extern __typeof (__redirect_memcpy) __memcpy_generic attribute_hidden;
 | ||||
|  extern __typeof (__redirect_memcpy) __memcpy_thunderx attribute_hidden; | ||||
|  extern __typeof (__redirect_memcpy) __memcpy_thunderx2 attribute_hidden; | ||||
|  extern __typeof (__redirect_memcpy) __memcpy_falkor attribute_hidden; | ||||
| +# if HAVE_AARCH64_SVE_ASM
 | ||||
| +extern __typeof (__redirect_memcpy) __memcpy_a64fx attribute_hidden;
 | ||||
| +# endif
 | ||||
|   | ||||
|  libc_ifunc (__libc_memcpy, | ||||
|              (IS_THUNDERX (midr) | ||||
| @@ -40,8 +43,13 @@ libc_ifunc (__libc_memcpy,
 | ||||
|  		? __memcpy_falkor | ||||
|  		: (IS_THUNDERX2 (midr) || IS_THUNDERX2PA (midr) | ||||
|  		  ? __memcpy_thunderx2 | ||||
| +# if HAVE_AARCH64_SVE_ASM
 | ||||
| +		  : (IS_A64FX (midr)
 | ||||
| +		     ? __memcpy_a64fx
 | ||||
| +		     : __memcpy_generic)))));
 | ||||
| +# else
 | ||||
|  		  : __memcpy_generic)))); | ||||
| -
 | ||||
| +# endif
 | ||||
|  # undef memcpy | ||||
|  strong_alias (__libc_memcpy, memcpy); | ||||
|  #endif | ||||
| diff --git a/sysdeps/aarch64/multiarch/memcpy_a64fx.S b/sysdeps/aarch64/multiarch/memcpy_a64fx.S
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..65528405bb123737
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/aarch64/multiarch/memcpy_a64fx.S
 | ||||
| @@ -0,0 +1,406 @@
 | ||||
| +/* Optimized memcpy for Fujitsu A64FX processor.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <sysdep.h>
 | ||||
| +
 | ||||
| +/* Assumptions:
 | ||||
| + *
 | ||||
| + * ARMv8.2-a, AArch64, unaligned accesses, sve
 | ||||
| + *
 | ||||
| + */
 | ||||
| +
 | ||||
| +#define L2_SIZE		(8*1024*1024)/2	// L2 8MB/2
 | ||||
| +#define CACHE_LINE_SIZE	256
 | ||||
| +#define ZF_DIST		(CACHE_LINE_SIZE * 21)	// Zerofill distance
 | ||||
| +#define dest		x0
 | ||||
| +#define src		x1
 | ||||
| +#define n		x2	// size
 | ||||
| +#define tmp1		x3
 | ||||
| +#define tmp2		x4
 | ||||
| +#define tmp3		x5
 | ||||
| +#define rest		x6
 | ||||
| +#define dest_ptr	x7
 | ||||
| +#define src_ptr		x8
 | ||||
| +#define vector_length	x9
 | ||||
| +#define cl_remainder	x10	// CACHE_LINE_SIZE remainder
 | ||||
| +
 | ||||
| +#if HAVE_AARCH64_SVE_ASM
 | ||||
| +# if IS_IN (libc)
 | ||||
| +#  define MEMCPY __memcpy_a64fx
 | ||||
| +#  define MEMMOVE __memmove_a64fx
 | ||||
| +
 | ||||
| +	.arch armv8.2-a+sve
 | ||||
| +
 | ||||
| +	.macro dc_zva times
 | ||||
| +	dc	zva, tmp1
 | ||||
| +	add	tmp1, tmp1, CACHE_LINE_SIZE
 | ||||
| +	.if \times-1
 | ||||
| +	dc_zva "(\times-1)"
 | ||||
| +	.endif
 | ||||
| +	.endm
 | ||||
| +
 | ||||
| +	.macro ld1b_unroll8
 | ||||
| +	ld1b	z0.b, p0/z, [src_ptr, #0, mul vl]
 | ||||
| +	ld1b	z1.b, p0/z, [src_ptr, #1, mul vl]
 | ||||
| +	ld1b	z2.b, p0/z, [src_ptr, #2, mul vl]
 | ||||
| +	ld1b	z3.b, p0/z, [src_ptr, #3, mul vl]
 | ||||
| +	ld1b	z4.b, p0/z, [src_ptr, #4, mul vl]
 | ||||
| +	ld1b	z5.b, p0/z, [src_ptr, #5, mul vl]
 | ||||
| +	ld1b	z6.b, p0/z, [src_ptr, #6, mul vl]
 | ||||
| +	ld1b	z7.b, p0/z, [src_ptr, #7, mul vl]
 | ||||
| +	.endm
 | ||||
| +
 | ||||
| +	.macro stld1b_unroll4a
 | ||||
| +	st1b	z0.b, p0,   [dest_ptr, #0, mul vl]
 | ||||
| +	st1b	z1.b, p0,   [dest_ptr, #1, mul vl]
 | ||||
| +	ld1b	z0.b, p0/z, [src_ptr,  #0, mul vl]
 | ||||
| +	ld1b	z1.b, p0/z, [src_ptr,  #1, mul vl]
 | ||||
| +	st1b	z2.b, p0,   [dest_ptr, #2, mul vl]
 | ||||
| +	st1b	z3.b, p0,   [dest_ptr, #3, mul vl]
 | ||||
| +	ld1b	z2.b, p0/z, [src_ptr,  #2, mul vl]
 | ||||
| +	ld1b	z3.b, p0/z, [src_ptr,  #3, mul vl]
 | ||||
| +	.endm
 | ||||
| +
 | ||||
| +	.macro stld1b_unroll4b
 | ||||
| +	st1b	z4.b, p0,   [dest_ptr, #4, mul vl]
 | ||||
| +	st1b	z5.b, p0,   [dest_ptr, #5, mul vl]
 | ||||
| +	ld1b	z4.b, p0/z, [src_ptr,  #4, mul vl]
 | ||||
| +	ld1b	z5.b, p0/z, [src_ptr,  #5, mul vl]
 | ||||
| +	st1b	z6.b, p0,   [dest_ptr, #6, mul vl]
 | ||||
| +	st1b	z7.b, p0,   [dest_ptr, #7, mul vl]
 | ||||
| +	ld1b	z6.b, p0/z, [src_ptr,  #6, mul vl]
 | ||||
| +	ld1b	z7.b, p0/z, [src_ptr,  #7, mul vl]
 | ||||
| +	.endm
 | ||||
| +
 | ||||
| +	.macro stld1b_unroll8
 | ||||
| +	stld1b_unroll4a
 | ||||
| +	stld1b_unroll4b
 | ||||
| +	.endm
 | ||||
| +
 | ||||
| +	.macro st1b_unroll8
 | ||||
| +	st1b	z0.b, p0, [dest_ptr, #0, mul vl]
 | ||||
| +	st1b	z1.b, p0, [dest_ptr, #1, mul vl]
 | ||||
| +	st1b	z2.b, p0, [dest_ptr, #2, mul vl]
 | ||||
| +	st1b	z3.b, p0, [dest_ptr, #3, mul vl]
 | ||||
| +	st1b	z4.b, p0, [dest_ptr, #4, mul vl]
 | ||||
| +	st1b	z5.b, p0, [dest_ptr, #5, mul vl]
 | ||||
| +	st1b	z6.b, p0, [dest_ptr, #6, mul vl]
 | ||||
| +	st1b	z7.b, p0, [dest_ptr, #7, mul vl]
 | ||||
| +	.endm
 | ||||
| +
 | ||||
| +	.macro shortcut_for_small_size exit
 | ||||
| +	// if rest <= vector_length * 2
 | ||||
| +	whilelo	p0.b, xzr, n
 | ||||
| +	whilelo	p1.b, vector_length, n
 | ||||
| +	b.last	1f
 | ||||
| +	ld1b	z0.b, p0/z, [src, #0, mul vl]
 | ||||
| +	ld1b	z1.b, p1/z, [src, #1, mul vl]
 | ||||
| +	st1b	z0.b, p0, [dest, #0, mul vl]
 | ||||
| +	st1b	z1.b, p1, [dest, #1, mul vl]
 | ||||
| +	ret
 | ||||
| +1:	// if rest > vector_length * 8
 | ||||
| +	cmp	n, vector_length, lsl 3 // vector_length * 8
 | ||||
| +	b.hi	\exit
 | ||||
| +	// if rest <= vector_length * 4
 | ||||
| +	lsl	tmp1, vector_length, 1  // vector_length * 2
 | ||||
| +	whilelo	p2.b, tmp1, n
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p3.b, tmp1, n
 | ||||
| +	b.last	1f
 | ||||
| +	ld1b	z0.b, p0/z, [src, #0, mul vl]
 | ||||
| +	ld1b	z1.b, p1/z, [src, #1, mul vl]
 | ||||
| +	ld1b	z2.b, p2/z, [src, #2, mul vl]
 | ||||
| +	ld1b	z3.b, p3/z, [src, #3, mul vl]
 | ||||
| +	st1b	z0.b, p0, [dest, #0, mul vl]
 | ||||
| +	st1b	z1.b, p1, [dest, #1, mul vl]
 | ||||
| +	st1b	z2.b, p2, [dest, #2, mul vl]
 | ||||
| +	st1b	z3.b, p3, [dest, #3, mul vl]
 | ||||
| +	ret
 | ||||
| +1:	// if rest <= vector_length * 8
 | ||||
| +	lsl	tmp1, vector_length, 2  // vector_length * 4
 | ||||
| +	whilelo	p4.b, tmp1, n
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p5.b, tmp1, n
 | ||||
| +	b.last	1f
 | ||||
| +	ld1b	z0.b, p0/z, [src, #0, mul vl]
 | ||||
| +	ld1b	z1.b, p1/z, [src, #1, mul vl]
 | ||||
| +	ld1b	z2.b, p2/z, [src, #2, mul vl]
 | ||||
| +	ld1b	z3.b, p3/z, [src, #3, mul vl]
 | ||||
| +	ld1b	z4.b, p4/z, [src, #4, mul vl]
 | ||||
| +	ld1b	z5.b, p5/z, [src, #5, mul vl]
 | ||||
| +	st1b	z0.b, p0, [dest, #0, mul vl]
 | ||||
| +	st1b	z1.b, p1, [dest, #1, mul vl]
 | ||||
| +	st1b	z2.b, p2, [dest, #2, mul vl]
 | ||||
| +	st1b	z3.b, p3, [dest, #3, mul vl]
 | ||||
| +	st1b	z4.b, p4, [dest, #4, mul vl]
 | ||||
| +	st1b	z5.b, p5, [dest, #5, mul vl]
 | ||||
| +	ret
 | ||||
| +1:	lsl	tmp1, vector_length, 2	// vector_length * 4
 | ||||
| +	incb	tmp1			// vector_length * 5
 | ||||
| +	incb	tmp1			// vector_length * 6
 | ||||
| +	whilelo	p6.b, tmp1, n
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p7.b, tmp1, n
 | ||||
| +	ld1b	z0.b, p0/z, [src, #0, mul vl]
 | ||||
| +	ld1b	z1.b, p1/z, [src, #1, mul vl]
 | ||||
| +	ld1b	z2.b, p2/z, [src, #2, mul vl]
 | ||||
| +	ld1b	z3.b, p3/z, [src, #3, mul vl]
 | ||||
| +	ld1b	z4.b, p4/z, [src, #4, mul vl]
 | ||||
| +	ld1b	z5.b, p5/z, [src, #5, mul vl]
 | ||||
| +	ld1b	z6.b, p6/z, [src, #6, mul vl]
 | ||||
| +	ld1b	z7.b, p7/z, [src, #7, mul vl]
 | ||||
| +	st1b	z0.b, p0, [dest, #0, mul vl]
 | ||||
| +	st1b	z1.b, p1, [dest, #1, mul vl]
 | ||||
| +	st1b	z2.b, p2, [dest, #2, mul vl]
 | ||||
| +	st1b	z3.b, p3, [dest, #3, mul vl]
 | ||||
| +	st1b	z4.b, p4, [dest, #4, mul vl]
 | ||||
| +	st1b	z5.b, p5, [dest, #5, mul vl]
 | ||||
| +	st1b	z6.b, p6, [dest, #6, mul vl]
 | ||||
| +	st1b	z7.b, p7, [dest, #7, mul vl]
 | ||||
| +	ret
 | ||||
| +	.endm
 | ||||
| +
 | ||||
| +ENTRY (MEMCPY)
 | ||||
| +
 | ||||
| +	PTR_ARG (0)
 | ||||
| +	PTR_ARG (1)
 | ||||
| +	SIZE_ARG (2)
 | ||||
| +
 | ||||
| +L(memcpy):
 | ||||
| +	cntb	vector_length
 | ||||
| +	// shortcut for less than vector_length * 8
 | ||||
| +	// gives a free ptrue to p0.b for n >= vector_length
 | ||||
| +	shortcut_for_small_size L(vl_agnostic)
 | ||||
| +	// end of shortcut
 | ||||
| +
 | ||||
| +L(vl_agnostic): // VL Agnostic
 | ||||
| +	mov	rest, n
 | ||||
| +	mov	dest_ptr, dest
 | ||||
| +	mov	src_ptr, src
 | ||||
| +	// if rest >= L2_SIZE && vector_length == 64 then L(L2)
 | ||||
| +	mov	tmp1, 64
 | ||||
| +	cmp	rest, L2_SIZE
 | ||||
| +	ccmp	vector_length, tmp1, 0, cs
 | ||||
| +	b.eq	L(L2)
 | ||||
| +
 | ||||
| +L(unroll8): // unrolling and software pipeline
 | ||||
| +	lsl	tmp1, vector_length, 3	// vector_length * 8
 | ||||
| +	.p2align 3
 | ||||
| +	cmp	 rest, tmp1
 | ||||
| +	b.cc	L(last)
 | ||||
| +	ld1b_unroll8
 | ||||
| +	add	src_ptr, src_ptr, tmp1
 | ||||
| +	sub	rest, rest, tmp1
 | ||||
| +	cmp	rest, tmp1
 | ||||
| +	b.cc	2f
 | ||||
| +	.p2align 3
 | ||||
| +1:	stld1b_unroll8
 | ||||
| +	add	dest_ptr, dest_ptr, tmp1
 | ||||
| +	add	src_ptr, src_ptr, tmp1
 | ||||
| +	sub	rest, rest, tmp1
 | ||||
| +	cmp	rest, tmp1
 | ||||
| +	b.ge	1b
 | ||||
| +2:	st1b_unroll8
 | ||||
| +	add	dest_ptr, dest_ptr, tmp1
 | ||||
| +
 | ||||
| +	.p2align 3
 | ||||
| +L(last):
 | ||||
| +	whilelo	p0.b, xzr, rest
 | ||||
| +	whilelo	p1.b, vector_length, rest
 | ||||
| +	b.last	1f
 | ||||
| +	ld1b	z0.b, p0/z, [src_ptr, #0, mul vl]
 | ||||
| +	ld1b	z1.b, p1/z, [src_ptr, #1, mul vl]
 | ||||
| +	st1b	z0.b, p0, [dest_ptr, #0, mul vl]
 | ||||
| +	st1b	z1.b, p1, [dest_ptr, #1, mul vl]
 | ||||
| +	ret
 | ||||
| +1:	lsl	tmp1, vector_length, 1	// vector_length * 2
 | ||||
| +	whilelo	p2.b, tmp1, rest
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p3.b, tmp1, rest
 | ||||
| +	b.last	1f
 | ||||
| +	ld1b	z0.b, p0/z, [src_ptr, #0, mul vl]
 | ||||
| +	ld1b	z1.b, p1/z, [src_ptr, #1, mul vl]
 | ||||
| +	ld1b	z2.b, p2/z, [src_ptr, #2, mul vl]
 | ||||
| +	ld1b	z3.b, p3/z, [src_ptr, #3, mul vl]
 | ||||
| +	st1b	z0.b, p0, [dest_ptr, #0, mul vl]
 | ||||
| +	st1b	z1.b, p1, [dest_ptr, #1, mul vl]
 | ||||
| +	st1b	z2.b, p2, [dest_ptr, #2, mul vl]
 | ||||
| +	st1b	z3.b, p3, [dest_ptr, #3, mul vl]
 | ||||
| +	ret
 | ||||
| +1:	lsl	tmp1, vector_length, 2	// vector_length * 4
 | ||||
| +	whilelo	p4.b, tmp1, rest
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p5.b, tmp1, rest
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p6.b, tmp1, rest
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p7.b, tmp1, rest
 | ||||
| +	ld1b	z0.b, p0/z, [src_ptr, #0, mul vl]
 | ||||
| +	ld1b	z1.b, p1/z, [src_ptr, #1, mul vl]
 | ||||
| +	ld1b	z2.b, p2/z, [src_ptr, #2, mul vl]
 | ||||
| +	ld1b	z3.b, p3/z, [src_ptr, #3, mul vl]
 | ||||
| +	ld1b	z4.b, p4/z, [src_ptr, #4, mul vl]
 | ||||
| +	ld1b	z5.b, p5/z, [src_ptr, #5, mul vl]
 | ||||
| +	ld1b	z6.b, p6/z, [src_ptr, #6, mul vl]
 | ||||
| +	ld1b	z7.b, p7/z, [src_ptr, #7, mul vl]
 | ||||
| +	st1b	z0.b, p0, [dest_ptr, #0, mul vl]
 | ||||
| +	st1b	z1.b, p1, [dest_ptr, #1, mul vl]
 | ||||
| +	st1b	z2.b, p2, [dest_ptr, #2, mul vl]
 | ||||
| +	st1b	z3.b, p3, [dest_ptr, #3, mul vl]
 | ||||
| +	st1b	z4.b, p4, [dest_ptr, #4, mul vl]
 | ||||
| +	st1b	z5.b, p5, [dest_ptr, #5, mul vl]
 | ||||
| +	st1b	z6.b, p6, [dest_ptr, #6, mul vl]
 | ||||
| +	st1b	z7.b, p7, [dest_ptr, #7, mul vl]
 | ||||
| +	ret
 | ||||
| +
 | ||||
| +L(L2):
 | ||||
| +	// align dest address at CACHE_LINE_SIZE byte boundary
 | ||||
| +	mov	tmp1, CACHE_LINE_SIZE
 | ||||
| +	ands	tmp2, dest_ptr, CACHE_LINE_SIZE - 1
 | ||||
| +	// if cl_remainder == 0
 | ||||
| +	b.eq	L(L2_dc_zva)
 | ||||
| +	sub	cl_remainder, tmp1, tmp2
 | ||||
| +	// process remainder until the first CACHE_LINE_SIZE boundary
 | ||||
| +	whilelo	p1.b, xzr, cl_remainder	// keep p0.b all true
 | ||||
| +	whilelo	p2.b, vector_length, cl_remainder
 | ||||
| +	b.last	1f
 | ||||
| +	ld1b	z1.b, p1/z, [src_ptr, #0, mul vl]
 | ||||
| +	ld1b	z2.b, p2/z, [src_ptr, #1, mul vl]
 | ||||
| +	st1b	z1.b, p1, [dest_ptr, #0, mul vl]
 | ||||
| +	st1b	z2.b, p2, [dest_ptr, #1, mul vl]
 | ||||
| +	b	2f
 | ||||
| +1:	lsl	tmp1, vector_length, 1	// vector_length * 2
 | ||||
| +	whilelo	p3.b, tmp1, cl_remainder
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p4.b, tmp1, cl_remainder
 | ||||
| +	ld1b	z1.b, p1/z, [src_ptr, #0, mul vl]
 | ||||
| +	ld1b	z2.b, p2/z, [src_ptr, #1, mul vl]
 | ||||
| +	ld1b	z3.b, p3/z, [src_ptr, #2, mul vl]
 | ||||
| +	ld1b	z4.b, p4/z, [src_ptr, #3, mul vl]
 | ||||
| +	st1b	z1.b, p1, [dest_ptr, #0, mul vl]
 | ||||
| +	st1b	z2.b, p2, [dest_ptr, #1, mul vl]
 | ||||
| +	st1b	z3.b, p3, [dest_ptr, #2, mul vl]
 | ||||
| +	st1b	z4.b, p4, [dest_ptr, #3, mul vl]
 | ||||
| +2:	add	dest_ptr, dest_ptr, cl_remainder
 | ||||
| +	add	src_ptr, src_ptr, cl_remainder
 | ||||
| +	sub	rest, rest, cl_remainder
 | ||||
| +
 | ||||
| +L(L2_dc_zva):
 | ||||
| +	// zero fill
 | ||||
| +	and	tmp1, dest, 0xffffffffffffff
 | ||||
| +	and	tmp2, src, 0xffffffffffffff
 | ||||
| +	subs	tmp1, tmp1, tmp2	// diff
 | ||||
| +	b.ge	1f
 | ||||
| +	neg	tmp1, tmp1
 | ||||
| +1:	mov	tmp3, ZF_DIST + CACHE_LINE_SIZE * 2
 | ||||
| +	cmp	tmp1, tmp3
 | ||||
| +	b.lo	L(unroll8)
 | ||||
| +	mov	tmp1, dest_ptr
 | ||||
| +	dc_zva	(ZF_DIST / CACHE_LINE_SIZE) - 1
 | ||||
| +	// unroll
 | ||||
| +	ld1b_unroll8	// this line has to be after "b.lo L(unroll8)"
 | ||||
| +	add	 src_ptr, src_ptr, CACHE_LINE_SIZE * 2
 | ||||
| +	sub	 rest, rest, CACHE_LINE_SIZE * 2
 | ||||
| +	mov	 tmp1, ZF_DIST
 | ||||
| +	.p2align 3
 | ||||
| +1:	stld1b_unroll4a
 | ||||
| +	add	tmp2, dest_ptr, tmp1	// dest_ptr + ZF_DIST
 | ||||
| +	dc	zva, tmp2
 | ||||
| +	stld1b_unroll4b
 | ||||
| +	add	tmp2, tmp2, CACHE_LINE_SIZE
 | ||||
| +	dc	zva, tmp2
 | ||||
| +	add	dest_ptr, dest_ptr, CACHE_LINE_SIZE * 2
 | ||||
| +	add	src_ptr, src_ptr, CACHE_LINE_SIZE * 2
 | ||||
| +	sub	rest, rest, CACHE_LINE_SIZE * 2
 | ||||
| +	cmp	rest, tmp3	// ZF_DIST + CACHE_LINE_SIZE * 2
 | ||||
| +	b.ge	1b
 | ||||
| +	st1b_unroll8
 | ||||
| +	add	dest_ptr, dest_ptr, CACHE_LINE_SIZE * 2
 | ||||
| +	b	L(unroll8)
 | ||||
| +
 | ||||
| +END (MEMCPY)
 | ||||
| +libc_hidden_builtin_def (MEMCPY)
 | ||||
| +
 | ||||
| +
 | ||||
| +ENTRY (MEMMOVE)
 | ||||
| +
 | ||||
| +	PTR_ARG (0)
 | ||||
| +	PTR_ARG (1)
 | ||||
| +	SIZE_ARG (2)
 | ||||
| +
 | ||||
| +	// remove tag address
 | ||||
| +	// dest has to be immutable because it is the return value
 | ||||
| +	// src has to be immutable because it is used in L(bwd_last)
 | ||||
| +	and	tmp2, dest, 0xffffffffffffff	// save dest_notag into tmp2
 | ||||
| +	and	tmp3, src, 0xffffffffffffff	// save src_notag intp tmp3
 | ||||
| +	cmp	n, 0
 | ||||
| +	ccmp	tmp2, tmp3, 4, ne
 | ||||
| +	b.ne	1f
 | ||||
| +	ret
 | ||||
| +1:	cntb	vector_length
 | ||||
| +	// shortcut for less than vector_length * 8
 | ||||
| +	// gives a free ptrue to p0.b for n >= vector_length
 | ||||
| +	// tmp2 and tmp3 should not be used in this macro to keep
 | ||||
| +	// notag addresses
 | ||||
| +	shortcut_for_small_size L(dispatch)
 | ||||
| +	// end of shortcut
 | ||||
| +
 | ||||
| +L(dispatch):
 | ||||
| +	// tmp2 = dest_notag, tmp3 = src_notag
 | ||||
| +	// diff = dest_notag - src_notag
 | ||||
| +	sub	tmp1, tmp2, tmp3
 | ||||
| +	// if diff <= 0 || diff >= n then memcpy
 | ||||
| +	cmp	tmp1, 0
 | ||||
| +	ccmp	tmp1, n, 2, gt
 | ||||
| +	b.cs	L(vl_agnostic)
 | ||||
| +
 | ||||
| +L(bwd_start):
 | ||||
| +	mov	rest, n
 | ||||
| +	add	dest_ptr, dest, n	// dest_end
 | ||||
| +	add	src_ptr, src, n		// src_end
 | ||||
| +
 | ||||
| +L(bwd_unroll8): // unrolling and software pipeline
 | ||||
| +	lsl	tmp1, vector_length, 3	// vector_length * 8
 | ||||
| +	.p2align 3
 | ||||
| +	cmp	rest, tmp1
 | ||||
| +	b.cc	L(bwd_last)
 | ||||
| +	sub	src_ptr, src_ptr, tmp1
 | ||||
| +	ld1b_unroll8
 | ||||
| +	sub	rest, rest, tmp1
 | ||||
| +	cmp	rest, tmp1
 | ||||
| +	b.cc	2f
 | ||||
| +	.p2align 3
 | ||||
| +1:	sub	src_ptr, src_ptr, tmp1
 | ||||
| +	sub	dest_ptr, dest_ptr, tmp1
 | ||||
| +	stld1b_unroll8
 | ||||
| +	sub	rest, rest, tmp1
 | ||||
| +	cmp	rest, tmp1
 | ||||
| +	b.ge	1b
 | ||||
| +2:	sub	dest_ptr, dest_ptr, tmp1
 | ||||
| +	st1b_unroll8
 | ||||
| +
 | ||||
| +L(bwd_last):
 | ||||
| +	mov	dest_ptr, dest
 | ||||
| +	mov	src_ptr, src
 | ||||
| +	b	L(last)
 | ||||
| +
 | ||||
| +END (MEMMOVE)
 | ||||
| +libc_hidden_builtin_def (MEMMOVE)
 | ||||
| +# endif /* IS_IN (libc) */
 | ||||
| +#endif /* HAVE_AARCH64_SVE_ASM */
 | ||||
| diff --git a/sysdeps/aarch64/multiarch/memmove.c b/sysdeps/aarch64/multiarch/memmove.c
 | ||||
| index e69d8162910b938e..d96612b9cf7c3a4e 100644
 | ||||
| --- a/sysdeps/aarch64/multiarch/memmove.c
 | ||||
| +++ b/sysdeps/aarch64/multiarch/memmove.c
 | ||||
| @@ -31,14 +31,22 @@ extern __typeof (__redirect_memmove) __libc_memmove;
 | ||||
|  extern __typeof (__redirect_memmove) __memmove_generic attribute_hidden; | ||||
|  extern __typeof (__redirect_memmove) __memmove_thunderx attribute_hidden; | ||||
|  extern __typeof (__redirect_memmove) __memmove_falkor attribute_hidden; | ||||
| +# if HAVE_AARCH64_SVE_ASM
 | ||||
| +extern __typeof (__redirect_memmove) __memmove_a64fx attribute_hidden;
 | ||||
| +# endif
 | ||||
|   | ||||
|  libc_ifunc (__libc_memmove, | ||||
|              (IS_THUNDERX (midr) | ||||
|  	     ? __memmove_thunderx | ||||
|  	     : (IS_FALKOR (midr) || IS_PHECDA (midr) | ||||
|  		? __memmove_falkor | ||||
| +# if HAVE_AARCH64_SVE_ASM
 | ||||
| +		: (IS_A64FX (midr)
 | ||||
| +		   ? __memmove_a64fx
 | ||||
| +		   : __memmove_generic))));
 | ||||
| +# else
 | ||||
|  		: __memmove_generic))); | ||||
| -
 | ||||
| +# endif
 | ||||
|  # undef memmove | ||||
|  strong_alias (__libc_memmove, memmove); | ||||
|  #endif | ||||
| diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
 | ||||
| index b4f348509eb1c6b3..71e4355c972f1ffb 100644
 | ||||
| --- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
 | ||||
| +++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c
 | ||||
| @@ -36,6 +36,7 @@ static struct cpu_list cpu_list[] = {
 | ||||
|        {"thunderx2t99",   0x431F0AF0}, | ||||
|        {"thunderx2t99p1", 0x420F5160}, | ||||
|        {"phecda",	 0x680F0000}, | ||||
| +      {"a64fx",		 0x460F0010},
 | ||||
|        {"generic", 	 0x0} | ||||
|  }; | ||||
|   | ||||
| @@ -80,4 +81,7 @@ init_cpu_features (struct cpu_features *cpu_features)
 | ||||
|   | ||||
|    if ((dczid & DCZID_DZP_MASK) == 0) | ||||
|      cpu_features->zva_size = 4 << (dczid & DCZID_BS_MASK); | ||||
| +
 | ||||
| +  /* Check if SVE is supported.  */
 | ||||
| +  cpu_features->sve = GLRO (dl_hwcap) & HWCAP_SVE;
 | ||||
|  } | ||||
| diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h b/sysdeps/unix/sysv/linux/aarch64/cpu-features.h
 | ||||
| index eb35adfbe9d429d5..5691aea6de3cb7f4 100644
 | ||||
| --- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.h
 | ||||
| +++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.h
 | ||||
| @@ -20,6 +20,7 @@
 | ||||
|  #define _CPU_FEATURES_AARCH64_H | ||||
|   | ||||
|  #include <stdint.h> | ||||
| +#include <stdbool.h>
 | ||||
|   | ||||
|  #define MIDR_PARTNUM_SHIFT	4 | ||||
|  #define MIDR_PARTNUM_MASK	(0xfff << MIDR_PARTNUM_SHIFT) | ||||
| @@ -52,10 +53,14 @@
 | ||||
|  #define IS_PHECDA(midr) (MIDR_IMPLEMENTOR(midr) == 'h'			      \ | ||||
|                          && MIDR_PARTNUM(midr) == 0x000) | ||||
|   | ||||
| +#define IS_A64FX(midr) (MIDR_IMPLEMENTOR(midr) == 'F'			      \
 | ||||
| +			&& MIDR_PARTNUM(midr) == 0x001)
 | ||||
| +
 | ||||
|  struct cpu_features | ||||
|  { | ||||
|    uint64_t midr_el1; | ||||
|    unsigned zva_size; | ||||
| +  bool sve;
 | ||||
|  }; | ||||
|   | ||||
|  #endif /* _CPU_FEATURES_AARCH64_H  */ | ||||
							
								
								
									
										371
									
								
								SOURCES/glibc-rh1929928-5.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										371
									
								
								SOURCES/glibc-rh1929928-5.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,371 @@ | ||||
| commit 4f26956d5ba394eb3ade6c1c20b5c16864a00766 | ||||
| Author: Naohiro Tamura <naohirot@jp.fujitsu.com> | ||||
| Date:   Thu May 27 07:44:12 2021 +0000 | ||||
| 
 | ||||
|     aarch64: Added optimized memset for A64FX | ||||
|      | ||||
|     This patch optimizes the performance of memset for A64FX [1] which | ||||
|     implements ARMv8-A SVE and has L1 64KB cache per core and L2 8MB cache | ||||
|     per NUMA node. | ||||
|      | ||||
|     The performance optimization makes use of Scalable Vector Register | ||||
|     with several techniques such as loop unrolling, memory access | ||||
|     alignment, cache zero fill and prefetch. | ||||
|      | ||||
|     SVE assembler code for memset is implemented as Vector Length Agnostic | ||||
|     code so theoretically it can be run on any SOC which supports ARMv8-A | ||||
|     SVE standard. | ||||
|      | ||||
|     We confirmed that all testcases have been passed by running 'make | ||||
|     check' and 'make xcheck' not only on A64FX but also on ThunderX2. | ||||
|      | ||||
|     And also we confirmed that the SVE 512 bit vector register performance | ||||
|     is roughly 4 times better than Advanced SIMD 128 bit register and 8 | ||||
|     times better than scalar 64 bit register by running 'make bench'. | ||||
|      | ||||
|     [1] https://github.com/fujitsu/A64FX | ||||
|      | ||||
|     Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com> | ||||
|     Reviewed-by: Szabolcs Nagy <Szabolcs.Nagy@arm.com> | ||||
| 
 | ||||
| Conflicts: | ||||
| 	sysdeps/aarch64/multiarch/Makefile | ||||
| 	sysdeps/aarch64/multiarch/ifunc-impl-list.c | ||||
| 	sysdeps/aarch64/multiarch/memset.c | ||||
| 	  (all conflicts due to missing other CPU implementations downstream) | ||||
| 
 | ||||
| diff --git a/sysdeps/aarch64/multiarch/Makefile b/sysdeps/aarch64/multiarch/Makefile
 | ||||
| index 5a19ba0308e80983..5ff883a8ad8e3067 100644
 | ||||
| --- a/sysdeps/aarch64/multiarch/Makefile
 | ||||
| +++ b/sysdeps/aarch64/multiarch/Makefile
 | ||||
| @@ -1,5 +1,6 @@
 | ||||
|  ifeq ($(subdir),string) | ||||
|  sysdep_routines += memcpy_generic memcpy_thunderx memcpy_thunderx2 \ | ||||
|  		   memcpy_falkor memcpy_a64fx \ | ||||
| -		   memmove_falkor memset_generic memset_falkor
 | ||||
| +		   memmove_falkor memset_generic memset_falkor \
 | ||||
| +		   memset_a64fx
 | ||||
|  endif | ||||
| diff --git a/sysdeps/aarch64/multiarch/ifunc-impl-list.c b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
 | ||||
| index f53db12acce37877..53e3e162a1025e40 100644
 | ||||
| --- a/sysdeps/aarch64/multiarch/ifunc-impl-list.c
 | ||||
| +++ b/sysdeps/aarch64/multiarch/ifunc-impl-list.c
 | ||||
| @@ -37,7 +37,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 | ||||
|   | ||||
|    INIT_ARCH (); | ||||
|   | ||||
| -  /* Support sysdeps/aarch64/multiarch/memcpy.c and memmove.c.  */
 | ||||
| +  /* Support sysdeps/aarch64/multiarch/memcpy.c, memmove.c and memset.c.  */
 | ||||
|    IFUNC_IMPL (i, name, memcpy, | ||||
|  	      IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx) | ||||
|  	      IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx2) | ||||
| @@ -57,6 +57,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 | ||||
|  	      /* Enable this on non-falkor processors too so that other cores | ||||
|  		 can do a comparative analysis with __memset_generic.  */ | ||||
|  	      IFUNC_IMPL_ADD (array, i, memset, (zva_size == 64), __memset_falkor) | ||||
| +#if HAVE_AARCH64_SVE_ASM
 | ||||
| +	      IFUNC_IMPL_ADD (array, i, memset, sve, __memset_a64fx)
 | ||||
| +#endif
 | ||||
|  	      IFUNC_IMPL_ADD (array, i, memset, 1, __memset_generic)) | ||||
|   | ||||
|    return i; | ||||
| diff --git a/sysdeps/aarch64/multiarch/memset.c b/sysdeps/aarch64/multiarch/memset.c
 | ||||
| index d74ed3a549a54b10..2c8cc72bb0b18474 100644
 | ||||
| --- a/sysdeps/aarch64/multiarch/memset.c
 | ||||
| +++ b/sysdeps/aarch64/multiarch/memset.c
 | ||||
| @@ -29,12 +29,21 @@
 | ||||
|  extern __typeof (__redirect_memset) __libc_memset; | ||||
|   | ||||
|  extern __typeof (__redirect_memset) __memset_falkor attribute_hidden; | ||||
| +# if HAVE_AARCH64_SVE_ASM
 | ||||
| +extern __typeof (__redirect_memset) __memset_a64fx attribute_hidden;
 | ||||
| +# endif
 | ||||
|  extern __typeof (__redirect_memset) __memset_generic attribute_hidden; | ||||
|   | ||||
|  libc_ifunc (__libc_memset, | ||||
|  	    ((IS_FALKOR (midr) || IS_PHECDA (midr)) && zva_size == 64 | ||||
|  	     ? __memset_falkor | ||||
| +# if HAVE_AARCH64_SVE_ASM
 | ||||
| +	     : (IS_A64FX (midr)
 | ||||
| +		? __memset_a64fx
 | ||||
| +		: __memset_generic)));
 | ||||
| +# else
 | ||||
|  	     : __memset_generic)); | ||||
| +# endif
 | ||||
|   | ||||
|  # undef memset | ||||
|  strong_alias (__libc_memset, memset); | ||||
| diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..ce54e5418b08c8bc
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
 | ||||
| @@ -0,0 +1,268 @@
 | ||||
| +/* Optimized memset for Fujitsu A64FX processor.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <sysdep.h>
 | ||||
| +#include <sysdeps/aarch64/memset-reg.h>
 | ||||
| +
 | ||||
| +/* Assumptions:
 | ||||
| + *
 | ||||
| + * ARMv8.2-a, AArch64, unaligned accesses, sve
 | ||||
| + *
 | ||||
| + */
 | ||||
| +
 | ||||
| +#define L1_SIZE		(64*1024)	// L1 64KB
 | ||||
| +#define L2_SIZE         (8*1024*1024)	// L2 8MB - 1MB
 | ||||
| +#define CACHE_LINE_SIZE	256
 | ||||
| +#define PF_DIST_L1	(CACHE_LINE_SIZE * 16)	// Prefetch distance L1
 | ||||
| +#define ZF_DIST		(CACHE_LINE_SIZE * 21)	// Zerofill distance
 | ||||
| +#define rest		x8
 | ||||
| +#define vector_length	x9
 | ||||
| +#define vl_remainder	x10	// vector_length remainder
 | ||||
| +#define cl_remainder	x11	// CACHE_LINE_SIZE remainder
 | ||||
| +
 | ||||
| +#if HAVE_AARCH64_SVE_ASM
 | ||||
| +# if IS_IN (libc)
 | ||||
| +#  define MEMSET __memset_a64fx
 | ||||
| +
 | ||||
| +	.arch armv8.2-a+sve
 | ||||
| +
 | ||||
| +	.macro dc_zva times
 | ||||
| +	dc	zva, tmp1
 | ||||
| +	add	tmp1, tmp1, CACHE_LINE_SIZE
 | ||||
| +	.if \times-1
 | ||||
| +	dc_zva "(\times-1)"
 | ||||
| +	.endif
 | ||||
| +	.endm
 | ||||
| +
 | ||||
| +	.macro st1b_unroll first=0, last=7
 | ||||
| +	st1b	z0.b, p0, [dst, #\first, mul vl]
 | ||||
| +	.if \last-\first
 | ||||
| +	st1b_unroll "(\first+1)", \last
 | ||||
| +	.endif
 | ||||
| +	.endm
 | ||||
| +
 | ||||
| +	.macro shortcut_for_small_size exit
 | ||||
| +	// if rest <= vector_length * 2
 | ||||
| +	whilelo	p0.b, xzr, count
 | ||||
| +	whilelo	p1.b, vector_length, count
 | ||||
| +	b.last	1f
 | ||||
| +	st1b	z0.b, p0, [dstin, #0, mul vl]
 | ||||
| +	st1b	z0.b, p1, [dstin, #1, mul vl]
 | ||||
| +	ret
 | ||||
| +1:	// if rest > vector_length * 8
 | ||||
| +	cmp	count, vector_length, lsl 3	// vector_length * 8
 | ||||
| +	b.hi	\exit
 | ||||
| +	// if rest <= vector_length * 4
 | ||||
| +	lsl	tmp1, vector_length, 1	// vector_length * 2
 | ||||
| +	whilelo	p2.b, tmp1, count
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p3.b, tmp1, count
 | ||||
| +	b.last	1f
 | ||||
| +	st1b	z0.b, p0, [dstin, #0, mul vl]
 | ||||
| +	st1b	z0.b, p1, [dstin, #1, mul vl]
 | ||||
| +	st1b	z0.b, p2, [dstin, #2, mul vl]
 | ||||
| +	st1b	z0.b, p3, [dstin, #3, mul vl]
 | ||||
| +	ret
 | ||||
| +1:	// if rest <= vector_length * 8
 | ||||
| +	lsl	tmp1, vector_length, 2	// vector_length * 4
 | ||||
| +	whilelo	p4.b, tmp1, count
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p5.b, tmp1, count
 | ||||
| +	b.last	1f
 | ||||
| +	st1b	z0.b, p0, [dstin, #0, mul vl]
 | ||||
| +	st1b	z0.b, p1, [dstin, #1, mul vl]
 | ||||
| +	st1b	z0.b, p2, [dstin, #2, mul vl]
 | ||||
| +	st1b	z0.b, p3, [dstin, #3, mul vl]
 | ||||
| +	st1b	z0.b, p4, [dstin, #4, mul vl]
 | ||||
| +	st1b	z0.b, p5, [dstin, #5, mul vl]
 | ||||
| +	ret
 | ||||
| +1:	lsl	tmp1, vector_length, 2	// vector_length * 4
 | ||||
| +	incb	tmp1			// vector_length * 5
 | ||||
| +	incb	tmp1			// vector_length * 6
 | ||||
| +	whilelo	p6.b, tmp1, count
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p7.b, tmp1, count
 | ||||
| +	st1b	z0.b, p0, [dstin, #0, mul vl]
 | ||||
| +	st1b	z0.b, p1, [dstin, #1, mul vl]
 | ||||
| +	st1b	z0.b, p2, [dstin, #2, mul vl]
 | ||||
| +	st1b	z0.b, p3, [dstin, #3, mul vl]
 | ||||
| +	st1b	z0.b, p4, [dstin, #4, mul vl]
 | ||||
| +	st1b	z0.b, p5, [dstin, #5, mul vl]
 | ||||
| +	st1b	z0.b, p6, [dstin, #6, mul vl]
 | ||||
| +	st1b	z0.b, p7, [dstin, #7, mul vl]
 | ||||
| +	ret
 | ||||
| +	.endm
 | ||||
| +
 | ||||
| +ENTRY (MEMSET)
 | ||||
| +
 | ||||
| +	PTR_ARG (0)
 | ||||
| +	SIZE_ARG (2)
 | ||||
| +
 | ||||
| +	cbnz	count, 1f
 | ||||
| +	ret
 | ||||
| +1:	dup	z0.b, valw
 | ||||
| +	cntb	vector_length
 | ||||
| +	// shortcut for less than vector_length * 8
 | ||||
| +	// gives a free ptrue to p0.b for n >= vector_length
 | ||||
| +	shortcut_for_small_size L(vl_agnostic)
 | ||||
| +	// end of shortcut
 | ||||
| +
 | ||||
| +L(vl_agnostic): // VL Agnostic
 | ||||
| +	mov	rest, count
 | ||||
| +	mov	dst, dstin
 | ||||
| +	add	dstend, dstin, count
 | ||||
| +	// if rest >= L2_SIZE && vector_length == 64 then L(L2)
 | ||||
| +	mov	tmp1, 64
 | ||||
| +	cmp	rest, L2_SIZE
 | ||||
| +	ccmp	vector_length, tmp1, 0, cs
 | ||||
| +	b.eq	L(L2)
 | ||||
| +	// if rest >= L1_SIZE && vector_length == 64 then L(L1_prefetch)
 | ||||
| +	cmp	rest, L1_SIZE
 | ||||
| +	ccmp	vector_length, tmp1, 0, cs
 | ||||
| +	b.eq	L(L1_prefetch)
 | ||||
| +
 | ||||
| +L(unroll32):
 | ||||
| +	lsl	tmp1, vector_length, 3	// vector_length * 8
 | ||||
| +	lsl	tmp2, vector_length, 5	// vector_length * 32
 | ||||
| +	.p2align 3
 | ||||
| +1:	cmp	rest, tmp2
 | ||||
| +	b.cc	L(unroll8)
 | ||||
| +	st1b_unroll
 | ||||
| +	add	dst, dst, tmp1
 | ||||
| +	st1b_unroll
 | ||||
| +	add	dst, dst, tmp1
 | ||||
| +	st1b_unroll
 | ||||
| +	add	dst, dst, tmp1
 | ||||
| +	st1b_unroll
 | ||||
| +	add	dst, dst, tmp1
 | ||||
| +	sub	rest, rest, tmp2
 | ||||
| +	b	1b
 | ||||
| +
 | ||||
| +L(unroll8):
 | ||||
| +	lsl	tmp1, vector_length, 3
 | ||||
| +	.p2align 3
 | ||||
| +1:	cmp	rest, tmp1
 | ||||
| +	b.cc	L(last)
 | ||||
| +	st1b_unroll
 | ||||
| +	add	dst, dst, tmp1
 | ||||
| +	sub	rest, rest, tmp1
 | ||||
| +	b	1b
 | ||||
| +
 | ||||
| +L(last):
 | ||||
| +	whilelo	p0.b, xzr, rest
 | ||||
| +	whilelo	p1.b, vector_length, rest
 | ||||
| +	b.last	1f
 | ||||
| +	st1b	z0.b, p0, [dst, #0, mul vl]
 | ||||
| +	st1b	z0.b, p1, [dst, #1, mul vl]
 | ||||
| +	ret
 | ||||
| +1:	lsl	tmp1, vector_length, 1	// vector_length * 2
 | ||||
| +	whilelo	p2.b, tmp1, rest
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p3.b, tmp1, rest
 | ||||
| +	b.last	1f
 | ||||
| +	st1b	z0.b, p0, [dst, #0, mul vl]
 | ||||
| +	st1b	z0.b, p1, [dst, #1, mul vl]
 | ||||
| +	st1b	z0.b, p2, [dst, #2, mul vl]
 | ||||
| +	st1b	z0.b, p3, [dst, #3, mul vl]
 | ||||
| +	ret
 | ||||
| +1:	lsl	tmp1, vector_length, 2	// vector_length * 4
 | ||||
| +	whilelo	p4.b, tmp1, rest
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p5.b, tmp1, rest
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p6.b, tmp1, rest
 | ||||
| +	incb	tmp1
 | ||||
| +	whilelo	p7.b, tmp1, rest
 | ||||
| +	st1b	z0.b, p0, [dst, #0, mul vl]
 | ||||
| +	st1b	z0.b, p1, [dst, #1, mul vl]
 | ||||
| +	st1b	z0.b, p2, [dst, #2, mul vl]
 | ||||
| +	st1b	z0.b, p3, [dst, #3, mul vl]
 | ||||
| +	st1b	z0.b, p4, [dst, #4, mul vl]
 | ||||
| +	st1b	z0.b, p5, [dst, #5, mul vl]
 | ||||
| +	st1b	z0.b, p6, [dst, #6, mul vl]
 | ||||
| +	st1b	z0.b, p7, [dst, #7, mul vl]
 | ||||
| +	ret
 | ||||
| +
 | ||||
| +L(L1_prefetch): // if rest >= L1_SIZE
 | ||||
| +	.p2align 3
 | ||||
| +1:	st1b_unroll 0, 3
 | ||||
| +	prfm	pstl1keep, [dst, PF_DIST_L1]
 | ||||
| +	st1b_unroll 4, 7
 | ||||
| +	prfm	pstl1keep, [dst, PF_DIST_L1 + CACHE_LINE_SIZE]
 | ||||
| +	add	dst, dst, CACHE_LINE_SIZE * 2
 | ||||
| +	sub	rest, rest, CACHE_LINE_SIZE * 2
 | ||||
| +	cmp	rest, L1_SIZE
 | ||||
| +	b.ge	1b
 | ||||
| +	cbnz	rest, L(unroll32)
 | ||||
| +	ret
 | ||||
| +
 | ||||
| +L(L2):
 | ||||
| +	// align dst address at vector_length byte boundary
 | ||||
| +	sub	tmp1, vector_length, 1
 | ||||
| +	ands	tmp2, dst, tmp1
 | ||||
| +	// if vl_remainder == 0
 | ||||
| +	b.eq	1f
 | ||||
| +	sub	vl_remainder, vector_length, tmp2
 | ||||
| +	// process remainder until the first vector_length boundary
 | ||||
| +	whilelt	p2.b, xzr, vl_remainder
 | ||||
| +	st1b	z0.b, p2, [dst]
 | ||||
| +	add	dst, dst, vl_remainder
 | ||||
| +	sub	rest, rest, vl_remainder
 | ||||
| +	// align dstin address at CACHE_LINE_SIZE byte boundary
 | ||||
| +1:	mov	tmp1, CACHE_LINE_SIZE
 | ||||
| +	ands	tmp2, dst, CACHE_LINE_SIZE - 1
 | ||||
| +	// if cl_remainder == 0
 | ||||
| +	b.eq	L(L2_dc_zva)
 | ||||
| +	sub	cl_remainder, tmp1, tmp2
 | ||||
| +	// process remainder until the first CACHE_LINE_SIZE boundary
 | ||||
| +	mov	tmp1, xzr       // index
 | ||||
| +2:	whilelt	p2.b, tmp1, cl_remainder
 | ||||
| +	st1b	z0.b, p2, [dst, tmp1]
 | ||||
| +	incb	tmp1
 | ||||
| +	cmp	tmp1, cl_remainder
 | ||||
| +	b.lo	2b
 | ||||
| +	add	dst, dst, cl_remainder
 | ||||
| +	sub	rest, rest, cl_remainder
 | ||||
| +
 | ||||
| +L(L2_dc_zva):
 | ||||
| +	// zero fill
 | ||||
| +	mov	tmp1, dst
 | ||||
| +	dc_zva	(ZF_DIST / CACHE_LINE_SIZE) - 1
 | ||||
| +	mov	zva_len, ZF_DIST
 | ||||
| +	add	tmp1, zva_len, CACHE_LINE_SIZE * 2
 | ||||
| +	// unroll
 | ||||
| +	.p2align 3
 | ||||
| +1:	st1b_unroll 0, 3
 | ||||
| +	add	tmp2, dst, zva_len
 | ||||
| +	dc	 zva, tmp2
 | ||||
| +	st1b_unroll 4, 7
 | ||||
| +	add	tmp2, tmp2, CACHE_LINE_SIZE
 | ||||
| +	dc	zva, tmp2
 | ||||
| +	add	dst, dst, CACHE_LINE_SIZE * 2
 | ||||
| +	sub	rest, rest, CACHE_LINE_SIZE * 2
 | ||||
| +	cmp	rest, tmp1	// ZF_DIST + CACHE_LINE_SIZE * 2
 | ||||
| +	b.ge	1b
 | ||||
| +	cbnz	rest, L(unroll8)
 | ||||
| +	ret
 | ||||
| +
 | ||||
| +END (MEMSET)
 | ||||
| +libc_hidden_builtin_def (MEMSET)
 | ||||
| +
 | ||||
| +#endif /* IS_IN (libc) */
 | ||||
| +#endif /* HAVE_AARCH64_SVE_ASM */
 | ||||
							
								
								
									
										159
									
								
								SOURCES/glibc-rh1934162-1.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								SOURCES/glibc-rh1934162-1.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,159 @@ | ||||
| From 332421312576bd7095e70589154af99b124dd2d1 Mon Sep 17 00:00:00 2001 | ||||
| From: Carlos O'Donell <carlos@redhat.com> | ||||
| Date: Fri, 12 Mar 2021 16:44:47 +0100 | ||||
| Subject: elf: Always set l in _dl_init_paths (bug 23462) | ||||
| 
 | ||||
| After d1d5471579eb0426671bf94f2d71e61dfb204c30 ("Remove dead | ||||
| DL_DST_REQ_STATIC code.") we always setup the link map l to make the | ||||
| static and shared cases the same.  The bug is that in elf/dl-load.c | ||||
| (_dl_init_paths) we conditionally set l only in the #ifdef SHARED | ||||
| case, but unconditionally use it later.  The simple solution is to | ||||
| remove the #ifdef SHARED conditional, because it's no longer needed, | ||||
| and unconditionally setup l for both the static and shared cases. A | ||||
| regression test is added to run a static binary with | ||||
| LD_LIBRARY_PATH='$ORIGIN' which crashes before the fix and runs after | ||||
| the fix. | ||||
| 
 | ||||
| Co-Authored-By: Florian Weimer <fweimer@redhat.com> | ||||
| 
 | ||||
| diff --git a/elf/Makefile b/elf/Makefile
 | ||||
| --- a/elf/Makefile	2021-11-02 16:28:14.720143774 -0400
 | ||||
| +++ b/elf/Makefile	2021-11-02 18:42:38.763843571 -0400
 | ||||
| @@ -151,7 +151,8 @@ endif
 | ||||
|  tests-static-normal := tst-leaks1-static tst-array1-static tst-array5-static \ | ||||
|  	       tst-dl-iter-static \ | ||||
|  	       tst-tlsalign-static tst-tlsalign-extern-static \ | ||||
| -	       tst-linkall-static tst-env-setuid tst-env-setuid-tunables
 | ||||
| +	       tst-linkall-static tst-env-setuid tst-env-setuid-tunables \
 | ||||
| +	       tst-dst-static
 | ||||
|  tests-static-internal := tst-tls1-static tst-tls2-static \ | ||||
|  	       tst-ptrguard1-static tst-stackguard1-static \ | ||||
|  	       tst-tls1-static-non-pie tst-libc_dlvsym-static | ||||
| @@ -1811,3 +1812,5 @@ $(objpfx)tst-glibc-hwcaps-mask.out: \
 | ||||
|  # Generic dependency for sysdeps implementation of | ||||
|  # tst-glibc-hwcaps-cache. | ||||
|  $(objpfx)tst-glibc-hwcaps-cache.out: $(objpfx)tst-glibc-hwcaps | ||||
| +
 | ||||
| +tst-dst-static-ENV = LD_LIBRARY_PATH='$$ORIGIN'
 | ||||
| diff --git a/elf/dl-load.c b/elf/dl-load.c
 | ||||
| index 9e2089cfaa..376a2e64d6 100644
 | ||||
| --- a/elf/dl-load.c
 | ||||
| +++ b/elf/dl-load.c
 | ||||
| @@ -758,50 +758,45 @@ _dl_init_paths (const char *llp, const char *source,
 | ||||
|    max_dirnamelen = SYSTEM_DIRS_MAX_LEN; | ||||
|    *aelem = NULL; | ||||
|   | ||||
| -#ifdef SHARED
 | ||||
|    /* This points to the map of the main object.  */ | ||||
|    l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; | ||||
| -  if (l != NULL)
 | ||||
| +  assert (l->l_type != lt_loaded);
 | ||||
| +
 | ||||
| +  if (l->l_info[DT_RUNPATH])
 | ||||
| +    {
 | ||||
| +      /* Allocate room for the search path and fill in information
 | ||||
| +	 from RUNPATH.  */
 | ||||
| +      decompose_rpath (&l->l_runpath_dirs,
 | ||||
| +		       (const void *) (D_PTR (l, l_info[DT_STRTAB])
 | ||||
| +				       + l->l_info[DT_RUNPATH]->d_un.d_val),
 | ||||
| +		       l, "RUNPATH");
 | ||||
| +      /* During rtld init the memory is allocated by the stub malloc,
 | ||||
| +	 prevent any attempt to free it by the normal malloc.  */
 | ||||
| +      l->l_runpath_dirs.malloced = 0;
 | ||||
| +
 | ||||
| +      /* The RPATH is ignored.  */
 | ||||
| +      l->l_rpath_dirs.dirs = (void *) -1;
 | ||||
| +    }
 | ||||
| +  else
 | ||||
|      { | ||||
| -      assert (l->l_type != lt_loaded);
 | ||||
| +      l->l_runpath_dirs.dirs = (void *) -1;
 | ||||
|   | ||||
| -      if (l->l_info[DT_RUNPATH])
 | ||||
| +      if (l->l_info[DT_RPATH])
 | ||||
|  	{ | ||||
|  	  /* Allocate room for the search path and fill in information | ||||
| -	     from RUNPATH.  */
 | ||||
| -	  decompose_rpath (&l->l_runpath_dirs,
 | ||||
| +	     from RPATH.  */
 | ||||
| +	  decompose_rpath (&l->l_rpath_dirs,
 | ||||
|  			   (const void *) (D_PTR (l, l_info[DT_STRTAB]) | ||||
| -					   + l->l_info[DT_RUNPATH]->d_un.d_val),
 | ||||
| -			   l, "RUNPATH");
 | ||||
| -	  /* During rtld init the memory is allocated by the stub malloc,
 | ||||
| -	     prevent any attempt to free it by the normal malloc.  */
 | ||||
| -	  l->l_runpath_dirs.malloced = 0;
 | ||||
| -
 | ||||
| -	  /* The RPATH is ignored.  */
 | ||||
| -	  l->l_rpath_dirs.dirs = (void *) -1;
 | ||||
| +					   + l->l_info[DT_RPATH]->d_un.d_val),
 | ||||
| +			   l, "RPATH");
 | ||||
| +	  /* During rtld init the memory is allocated by the stub
 | ||||
| +	     malloc, prevent any attempt to free it by the normal
 | ||||
| +	     malloc.  */
 | ||||
| +	  l->l_rpath_dirs.malloced = 0;
 | ||||
|  	} | ||||
|        else | ||||
| -	{
 | ||||
| -	  l->l_runpath_dirs.dirs = (void *) -1;
 | ||||
| -
 | ||||
| -	  if (l->l_info[DT_RPATH])
 | ||||
| -	    {
 | ||||
| -	      /* Allocate room for the search path and fill in information
 | ||||
| -		 from RPATH.  */
 | ||||
| -	      decompose_rpath (&l->l_rpath_dirs,
 | ||||
| -			       (const void *) (D_PTR (l, l_info[DT_STRTAB])
 | ||||
| -					       + l->l_info[DT_RPATH]->d_un.d_val),
 | ||||
| -			       l, "RPATH");
 | ||||
| -	      /* During rtld init the memory is allocated by the stub
 | ||||
| -		 malloc, prevent any attempt to free it by the normal
 | ||||
| -		 malloc.  */
 | ||||
| -	      l->l_rpath_dirs.malloced = 0;
 | ||||
| -	    }
 | ||||
| -	  else
 | ||||
| -	    l->l_rpath_dirs.dirs = (void *) -1;
 | ||||
| -	}
 | ||||
| +	l->l_rpath_dirs.dirs = (void *) -1;
 | ||||
|      } | ||||
| -#endif	/* SHARED */
 | ||||
|   | ||||
|    if (llp != NULL && *llp != '\0') | ||||
|      { | ||||
| diff --git a/elf/tst-dst-static.c b/elf/tst-dst-static.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000..56eb371c96
 | ||||
| --- /dev/null
 | ||||
| +++ b/elf/tst-dst-static.c
 | ||||
| @@ -0,0 +1,32 @@
 | ||||
| +/* Test DST expansion for static binaries doesn't carsh.  Bug 23462.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +/* The purpose of this test is to exercise the code in elf/dl-loac.c
 | ||||
| +   (_dl_init_paths) or thereabout and ensure that static binaries
 | ||||
| +   don't crash when expanding DSTs.
 | ||||
| +
 | ||||
| +   If the dynamic loader code linked into the static binary cannot
 | ||||
| +   handle expanding the DSTs e.g. null-deref on an incomplete link
 | ||||
| +   map, then it will crash before reaching main, so the test harness
 | ||||
| +   is unnecessary.  */
 | ||||
| +
 | ||||
| +int
 | ||||
| +main (void)
 | ||||
| +{
 | ||||
| +  return 0;
 | ||||
| +}
 | ||||
							
								
								
									
										74
									
								
								SOURCES/glibc-rh1934162-2.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								SOURCES/glibc-rh1934162-2.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,74 @@ | ||||
| From 4e6db99c665d3b82a70a3e218860ef087b1555b4 Mon Sep 17 00:00:00 2001 | ||||
| From: Florian Weimer <fweimer@redhat.com> | ||||
| Date: Mon, 15 Mar 2021 10:33:43 +0100 | ||||
| Subject: elf: ld.so --help calls _dl_init_paths without a main map [BZ #27577] | ||||
| 
 | ||||
| In this case, use the link map of the dynamic loader itself as | ||||
| a replacement.  This is more than just a hack: if we ever support | ||||
| DT_RUNPATH/DT_RPATH for the dynamic loader, reporting it for | ||||
| ld.so --help (without further command line arguments) would be the | ||||
| right thing to do. | ||||
| 
 | ||||
| Fixes commit 332421312576bd7095e70589154af99b124dd2d1 ("elf: Always | ||||
| set l in _dl_init_paths (bug 23462)"). | ||||
| 
 | ||||
| diff --git a/elf/Makefile b/elf/Makefile
 | ||||
| index 4c9e63dac9..ba4689a7fa 100644
 | ||||
| --- a/elf/Makefile
 | ||||
| +++ b/elf/Makefile
 | ||||
| @@ -231,7 +231,7 @@ tests += $(tests-execstack-$(have-z-execstack))
 | ||||
|  ifeq ($(run-built-tests),yes) | ||||
|  tests-special += $(objpfx)tst-leaks1-mem.out \ | ||||
|  		 $(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out \ | ||||
| -		 $(objpfx)tst-ldconfig-X.out
 | ||||
| +		 $(objpfx)tst-ldconfig-X.out $(objpfx)tst-rtld-help.out
 | ||||
|  endif | ||||
|  tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ||||
|  tlsmod18a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ||||
| @@ -409,7 +409,8 @@ endif
 | ||||
|  ifeq (yes,$(build-shared)) | ||||
|  ifeq ($(run-built-tests),yes) | ||||
|  tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \ | ||||
| -		 $(objpfx)tst-rtld-preload.out $(objpfx)argv0test.out
 | ||||
| +		 $(objpfx)tst-rtld-preload.out $(objpfx)argv0test.out \
 | ||||
| +		 $(objpfx)tst-rtld-help.out
 | ||||
|  endif | ||||
|  tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \ | ||||
|  		 $(objpfx)check-wx-segment.out \ | ||||
| @@ -1814,3 +1815,16 @@ $(objpfx)list-tunables.out: tst-rtld-list-tunables.sh $(objpfx)ld.so
 | ||||
|  $(objpfx)tst-glibc-hwcaps-cache.out: $(objpfx)tst-glibc-hwcaps | ||||
|   | ||||
|  tst-dst-static-ENV = LD_LIBRARY_PATH='$$ORIGIN' | ||||
| +
 | ||||
| +$(objpfx)tst-rtld-help.out: $(objpfx)ld.so
 | ||||
| +	$(test-wrapper) $(rtld-prefix) --help > $@; \
 | ||||
| +	status=$$?; \
 | ||||
| +	echo "info: ld.so exit status: $$status" >> $@; \
 | ||||
| +	if ! grep -q 'Legacy HWCAP subdirectories under library search path directories' $@; then \
 | ||||
| +	  echo "error: missing subdirectory pattern" >> $@; \
 | ||||
| +	  if test $$status -eq 0; then \
 | ||||
| +	    status=1; \
 | ||||
| +	  fi; \
 | ||||
| +	fi; \
 | ||||
| +	(exit $$status); \
 | ||||
| +	$(evaluate-test)
 | ||||
| diff --git a/elf/dl-load.c b/elf/dl-load.c
 | ||||
| index 376a2e64d6..2f760503c5 100644
 | ||||
| --- a/elf/dl-load.c
 | ||||
| +++ b/elf/dl-load.c
 | ||||
| @@ -758,8 +758,14 @@ _dl_init_paths (const char *llp, const char *source,
 | ||||
|    max_dirnamelen = SYSTEM_DIRS_MAX_LEN; | ||||
|    *aelem = NULL; | ||||
|   | ||||
| -  /* This points to the map of the main object.  */
 | ||||
| +  /* This points to the map of the main object.  If there is no main
 | ||||
| +     object (e.g., under --help, use the dynamic loader itself as a
 | ||||
| +     stand-in.  */
 | ||||
|    l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; | ||||
| +#ifdef SHARED
 | ||||
| +  if (l == NULL)
 | ||||
| +    l = &GL (dl_rtld_map);
 | ||||
| +#endif
 | ||||
|    assert (l->l_type != lt_loaded); | ||||
|   | ||||
|    if (l->l_info[DT_RUNPATH]) | ||||
							
								
								
									
										90
									
								
								SOURCES/glibc-rh1937515.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								SOURCES/glibc-rh1937515.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,90 @@ | ||||
| Based on the following commit, adjusted for glibc-2.28 in RHEL-8: | ||||
| 
 | ||||
| commit 27f74636752d0c4438cf8346cf2a76b6fcf3be16 | ||||
| Author: H.J. Lu <hjl.tools@gmail.com> | ||||
| Date:   Fri Mar 19 06:15:37 2021 -0700 | ||||
| 
 | ||||
|     x86: Properly disable XSAVE related features [BZ #27605] | ||||
|      | ||||
|     1. Support GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVE. | ||||
|     2. Disable all features which depend on XSAVE: | ||||
|        a. If OSXSAVE is disabled by glibc tunables.  Or | ||||
|        b. If both XSAVE and XSAVEC aren't usable. | ||||
| 
 | ||||
| diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
 | ||||
| index 805d00a43309fc23..910425053d9e226f 100644
 | ||||
| --- a/sysdeps/x86/cpu-features.c
 | ||||
| +++ b/sysdeps/x86/cpu-features.c
 | ||||
| @@ -654,6 +654,60 @@ no_cpuid:
 | ||||
|      = TUNABLE_GET (x86_data_cache_size, long int, NULL); | ||||
|    cpu_features->shared_cache_size | ||||
|      = TUNABLE_GET (x86_shared_cache_size, long int, NULL); | ||||
| +
 | ||||
| +  bool disable_xsave_features = false;
 | ||||
| +
 | ||||
| +  if (!CPU_FEATURE_USABLE_P (cpu_features, OSXSAVE))
 | ||||
| +    {
 | ||||
| +      /* These features are usable only if OSXSAVE is usable.  */
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, XSAVE);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, XSAVEOPT);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, XSAVEC);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, XGETBV_ECX_1);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, XFD);
 | ||||
| +
 | ||||
| +      disable_xsave_features = true;
 | ||||
| +    }
 | ||||
| +
 | ||||
| +  if (disable_xsave_features
 | ||||
| +      || (!CPU_FEATURE_USABLE_P (cpu_features, XSAVE)
 | ||||
| +	  && !CPU_FEATURE_USABLE_P (cpu_features, XSAVEC)))
 | ||||
| +    {
 | ||||
| +      /* Clear xsave_state_size if both XSAVE and XSAVEC aren't usable.  */
 | ||||
| +      cpu_features->xsave_state_size = 0;
 | ||||
| +
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX2);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX_VNNI);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, FMA);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, VAES);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, VPCLMULQDQ);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, XOP);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, F16C);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512F);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512CD);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512ER);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512PF);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512VL);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512DQ);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512BW);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512_4FMAPS);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512_4VNNIW);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512_BITALG);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512_IFMA);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512_VBMI);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512_VBMI2);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512_VNNI);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512_VPOPCNTDQ);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512_VP2INTERSECT);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512_BF16);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AVX512_FP16);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AMX_BF16);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AMX_TILE);
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, AMX_INT8);
 | ||||
| +
 | ||||
| +      CPU_FEATURE_UNSET (cpu_features, FMA4);
 | ||||
| +    }
 | ||||
|  #endif | ||||
|   | ||||
|    /* Reuse dl_platform, dl_hwcap and dl_hwcap_mask for x86.  */ | ||||
| diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c
 | ||||
| index 0728023007a0f423..3173b2b959ca88f9 100644
 | ||||
| --- a/sysdeps/x86/cpu-tunables.c
 | ||||
| +++ b/sysdeps/x86/cpu-tunables.c
 | ||||
| @@ -168,6 +168,7 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
 | ||||
|  	      CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, MOVBE, 5); | ||||
|  	      CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SHSTK, 5); | ||||
|  	      CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SSSE3, 5); | ||||
| +	      CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, XSAVE, 5);
 | ||||
|  	    } | ||||
|  	  break; | ||||
|  	case 6: | ||||
							
								
								
									
										102
									
								
								SOURCES/glibc-rh1971664-1.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								SOURCES/glibc-rh1971664-1.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,102 @@ | ||||
| commit 0c78b0bb78d87a7de18726a033d88904f158f0fe | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Mon Jun 7 14:22:17 2021 +0530 | ||||
| 
 | ||||
|     iconvconfig: Make file handling more general purpose | ||||
|      | ||||
|     Split out configuration file handling code from handle_dir into its | ||||
|     own function so that it can be reused for multiple configuration | ||||
|     files. | ||||
|      | ||||
|     Reviewed-by: DJ Delorie <dj@redhat.com> | ||||
| 
 | ||||
| diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
 | ||||
| index b6fef1553cbbdd3d..2b3c587bc77cfdcd 100644
 | ||||
| --- a/iconv/iconvconfig.c
 | ||||
| +++ b/iconv/iconvconfig.c
 | ||||
| @@ -644,37 +644,17 @@ add_module (char *rp, const char *directory)
 | ||||
|  	      cost, need_ext); | ||||
|  } | ||||
|   | ||||
| -
 | ||||
| -/* Read the config file and add the data for this directory to that.  */
 | ||||
| -static int
 | ||||
| -handle_dir (const char *dir)
 | ||||
| +/* Read a gconv-modules configuration file.  */
 | ||||
| +static bool
 | ||||
| +handle_file (const char *dir, const char *infile)
 | ||||
|  { | ||||
| -  char *cp;
 | ||||
|    FILE *fp; | ||||
|    char *line = NULL; | ||||
|    size_t linelen = 0; | ||||
| -  size_t dirlen = strlen (dir);
 | ||||
| -
 | ||||
| -  if (dir[dirlen - 1] != '/')
 | ||||
| -    {
 | ||||
| -      char *newp = (char *) xmalloc (dirlen + 2);
 | ||||
| -      dir = memcpy (newp, dir, dirlen);
 | ||||
| -      newp[dirlen++] = '/';
 | ||||
| -      newp[dirlen] = '\0';
 | ||||
| -    }
 | ||||
| -
 | ||||
| -  char infile[prefix_len + dirlen + sizeof "gconv-modules"];
 | ||||
| -  cp = infile;
 | ||||
| -  if (dir[0] == '/')
 | ||||
| -    cp = mempcpy (cp, prefix, prefix_len);
 | ||||
| -  strcpy (mempcpy (cp, dir, dirlen), "gconv-modules");
 | ||||
|   | ||||
|    fp = fopen (infile, "r"); | ||||
|    if (fp == NULL) | ||||
| -    {
 | ||||
| -      error (0, errno, "cannot open `%s'", infile);
 | ||||
| -      return 1;
 | ||||
| -    }
 | ||||
| +    return false;
 | ||||
|   | ||||
|    /* No threads present.  */ | ||||
|    __fsetlocking (fp, FSETLOCKING_BYCALLER); | ||||
| @@ -723,7 +703,42 @@ handle_dir (const char *dir)
 | ||||
|   | ||||
|    fclose (fp); | ||||
|   | ||||
| -  return 0;
 | ||||
| +  return true;
 | ||||
| +}
 | ||||
| +
 | ||||
| +/* Read config files and add the data for this directory to cache.  */
 | ||||
| +static int
 | ||||
| +handle_dir (const char *dir)
 | ||||
| +{
 | ||||
| +  char *cp;
 | ||||
| +  size_t dirlen = strlen (dir);
 | ||||
| +  bool found = false;
 | ||||
| +
 | ||||
| +  if (dir[dirlen - 1] != '/')
 | ||||
| +    {
 | ||||
| +      char *newp = (char *) xmalloc (dirlen + 2);
 | ||||
| +      dir = memcpy (newp, dir, dirlen);
 | ||||
| +      newp[dirlen++] = '/';
 | ||||
| +      newp[dirlen] = '\0';
 | ||||
| +    }
 | ||||
| +
 | ||||
| +  char infile[prefix_len + dirlen + sizeof "gconv-modules"];
 | ||||
| +  cp = infile;
 | ||||
| +  if (dir[0] == '/')
 | ||||
| +    cp = mempcpy (cp, prefix, prefix_len);
 | ||||
| +  strcpy (mempcpy (cp, dir, dirlen), "gconv-modules");
 | ||||
| +
 | ||||
| +  found |= handle_file (dir, infile);
 | ||||
| +
 | ||||
| +  if (!found)
 | ||||
| +    {
 | ||||
| +      error (0, errno, "failed to open gconv configuration file in `%s'",
 | ||||
| +	     dir);
 | ||||
| +      error (0, 0,
 | ||||
| +	     "ensure that the directory contains a valid gconv-modules file.");
 | ||||
| +    }
 | ||||
| +
 | ||||
| +  return found ? 0 : 1;
 | ||||
|  } | ||||
|   | ||||
|   | ||||
							
								
								
									
										188
									
								
								SOURCES/glibc-rh1971664-10.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								SOURCES/glibc-rh1971664-10.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,188 @@ | ||||
| commit eeac390eecf7de24a110dc84e77e1190f42c5305 | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Thu Jun 10 14:31:57 2021 +0530 | ||||
| 
 | ||||
|     iconvconfig: Use common gconv module parsing function | ||||
|      | ||||
|     Drop local copy of gconv file parsing and use the one in | ||||
|     gconv_parseconfdir.h instead.  Now there is a single implementation of | ||||
|     configuration file parsing. | ||||
|      | ||||
|     Reviewed-by: DJ Delorie <dj@redhat.com> | ||||
| 
 | ||||
| diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
 | ||||
| index 2f9d5f45ad3a8159..01ecf6f67d55dbbf 100644
 | ||||
| --- a/iconv/iconvconfig.c
 | ||||
| +++ b/iconv/iconvconfig.c
 | ||||
| @@ -18,7 +18,6 @@
 | ||||
|   | ||||
|  #include <argp.h> | ||||
|  #include <assert.h> | ||||
| -#include <dirent.h>
 | ||||
|  #include <error.h> | ||||
|  #include <errno.h> | ||||
|  #include <fcntl.h> | ||||
| @@ -34,10 +33,10 @@
 | ||||
|  #include <string.h> | ||||
|  #include <unistd.h> | ||||
|  #include <sys/cdefs.h> | ||||
| -#include <sys/types.h>
 | ||||
|  #include <sys/uio.h> | ||||
|   | ||||
|  #include "iconvconfig.h" | ||||
| +#include <gconv_parseconfdir.h>
 | ||||
|   | ||||
|  /* Get libc version number.  */ | ||||
|  #include "../version.h" | ||||
| @@ -568,7 +567,9 @@ new_module (const char *fromname, size_t fromlen, const char *toname,
 | ||||
|   | ||||
|  /* Add new module.  */ | ||||
|  static void | ||||
| -add_module (char *rp, const char *directory)
 | ||||
| +add_module (char *rp, const char *directory,
 | ||||
| +	    size_t dirlen __attribute__ ((__unused__)),
 | ||||
| +	    int modcount __attribute__ ((__unused__)))
 | ||||
|  { | ||||
|    /* We expect now | ||||
|       1. `from' name | ||||
| @@ -646,131 +647,28 @@ add_module (char *rp, const char *directory)
 | ||||
|  	      cost, need_ext); | ||||
|  } | ||||
|   | ||||
| -/* Read a gconv-modules configuration file.  */
 | ||||
| -static bool
 | ||||
| -handle_file (const char *dir, const char *infile)
 | ||||
| -{
 | ||||
| -  FILE *fp;
 | ||||
| -  char *line = NULL;
 | ||||
| -  size_t linelen = 0;
 | ||||
| -
 | ||||
| -  fp = fopen (infile, "r");
 | ||||
| -  if (fp == NULL)
 | ||||
| -    return false;
 | ||||
| -
 | ||||
| -  /* No threads present.  */
 | ||||
| -  __fsetlocking (fp, FSETLOCKING_BYCALLER);
 | ||||
| -
 | ||||
| -  while (!feof_unlocked (fp))
 | ||||
| -    {
 | ||||
| -      char *rp, *endp, *word;
 | ||||
| -      ssize_t n = __getdelim (&line, &linelen, '\n', fp);
 | ||||
| -
 | ||||
| -      if (n < 0)
 | ||||
| -	/* An error occurred.  */
 | ||||
| -	break;
 | ||||
| -
 | ||||
| -      rp = line;
 | ||||
| -      /* Terminate the line (excluding comments or newline) with a NUL
 | ||||
| -	 byte to simplify the following code.  */
 | ||||
| -      endp = strchr (rp, '#');
 | ||||
| -      if (endp != NULL)
 | ||||
| -	*endp = '\0';
 | ||||
| -      else
 | ||||
| -	if (rp[n - 1] == '\n')
 | ||||
| -	  rp[n - 1] = '\0';
 | ||||
| -
 | ||||
| -      while (isspace (*rp))
 | ||||
| -	++rp;
 | ||||
| -
 | ||||
| -      /* If this is an empty line go on with the next one.  */
 | ||||
| -      if (rp == endp)
 | ||||
| -	continue;
 | ||||
| -
 | ||||
| -      word = rp;
 | ||||
| -      while (*rp != '\0' && !isspace (*rp))
 | ||||
| -	++rp;
 | ||||
| -
 | ||||
| -      if (rp - word == sizeof ("alias") - 1
 | ||||
| -	  && memcmp (word, "alias", sizeof ("alias") - 1) == 0)
 | ||||
| -	add_alias (rp);
 | ||||
| -      else if (rp - word == sizeof ("module") - 1
 | ||||
| -	       && memcmp (word, "module", sizeof ("module") - 1) == 0)
 | ||||
| -	add_module (rp, dir);
 | ||||
| -      /* else */
 | ||||
| -	/* Otherwise ignore the line.  */
 | ||||
| -    }
 | ||||
| -
 | ||||
| -  free (line);
 | ||||
| -
 | ||||
| -  fclose (fp);
 | ||||
| -
 | ||||
| -  return true;
 | ||||
| -}
 | ||||
| -
 | ||||
|  /* Read config files and add the data for this directory to cache.  */ | ||||
|  static int | ||||
|  handle_dir (const char *dir) | ||||
|  { | ||||
| -  char *cp;
 | ||||
|    size_t dirlen = strlen (dir); | ||||
|    bool found = false; | ||||
|   | ||||
| +  /* Add the prefix before sending it off to the parser.  */
 | ||||
| +  char *fulldir = xmalloc (prefix_len + dirlen + 2);
 | ||||
| +  char *cp = mempcpy (mempcpy (fulldir, prefix, prefix_len), dir, dirlen);
 | ||||
| +
 | ||||
|    if (dir[dirlen - 1] != '/') | ||||
|      { | ||||
| -      char *newp = (char *) xmalloc (dirlen + 2);
 | ||||
| -      dir = memcpy (newp, dir, dirlen);
 | ||||
| -      newp[dirlen++] = '/';
 | ||||
| -      newp[dirlen] = '\0';
 | ||||
| +      *cp++ = '/';
 | ||||
| +      *cp = '\0';
 | ||||
| +      dirlen++;
 | ||||
|      } | ||||
|   | ||||
| -  /* First, look for a gconv-modules file.  */
 | ||||
| -  char *buf = malloc (prefix_len + dirlen + sizeof "gconv-modules.d");
 | ||||
| -  if (buf == NULL)
 | ||||
| -    goto out;
 | ||||
| -
 | ||||
| -  cp = buf;
 | ||||
| -  if (dir[0] == '/')
 | ||||
| -    cp = mempcpy (cp, prefix, prefix_len);
 | ||||
| -  cp = mempcpy (cp, dir, dirlen);
 | ||||
| -  cp = stpcpy (cp, "gconv-modules");
 | ||||
| -
 | ||||
| -  found |= handle_file (dir, buf);
 | ||||
| -
 | ||||
| -  /* Next, see if there is a gconv-modules.d directory containing configuration
 | ||||
| -     files and if it is non-empty.  */
 | ||||
| -  cp[0] = '.';
 | ||||
| -  cp[1] = 'd';
 | ||||
| -  cp[2] = '\0';
 | ||||
| -
 | ||||
| -  DIR *confdir = opendir (buf);
 | ||||
| -  if (confdir != NULL)
 | ||||
| -    {
 | ||||
| -      struct dirent *ent;
 | ||||
| -      while ((ent = readdir (confdir)) != NULL)
 | ||||
| -	{
 | ||||
| -	  if (ent->d_type != DT_REG)
 | ||||
| -	    continue;
 | ||||
| -
 | ||||
| -	  size_t len = strlen (ent->d_name);
 | ||||
| -	  const char *suffix = ".conf";
 | ||||
| -
 | ||||
| -	  if (len > strlen (suffix)
 | ||||
| -	      && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
 | ||||
| -	    {
 | ||||
| -	      char *conf;
 | ||||
| -	      if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
 | ||||
| -		continue;
 | ||||
| -	      found |= handle_file (dir, conf);
 | ||||
| -	      free (conf);
 | ||||
| -	    }
 | ||||
| -	}
 | ||||
| -      closedir (confdir);
 | ||||
| -    }
 | ||||
| +  found = gconv_parseconfdir (fulldir, dirlen + prefix_len);
 | ||||
|   | ||||
| -  free (buf);
 | ||||
| +  free (fulldir);
 | ||||
|   | ||||
| -out:
 | ||||
|    if (!found) | ||||
|      { | ||||
|        error (0, errno, "failed to open gconv configuration files in `%s'", | ||||
							
								
								
									
										53
									
								
								SOURCES/glibc-rh1971664-11.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								SOURCES/glibc-rh1971664-11.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | ||||
| Changes specific to RHEL-8: | ||||
| 
 | ||||
| - lstat64 is a macro, so undefine it first
 | ||||
| 
 | ||||
| commit f3629a4be82a393ff56646c388da2fda0101f557 | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Thu Jun 10 14:56:37 2021 +0530 | ||||
| 
 | ||||
|     Handle DT_UNKNOWN in gconv-modules.d | ||||
|      | ||||
|     On filesystems that do not support dt_type, a regular file shows up as | ||||
|     DT_UNKNOWN.  Fall back to using lstat64 to read file properties in | ||||
|     such cases. | ||||
|      | ||||
|     Reviewed-by: DJ Delorie <dj@redhat.com> | ||||
| 
 | ||||
| diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
 | ||||
| index 3d4d58d4be10a250..ba9b3fd36d9e30f9 100644
 | ||||
| --- a/iconv/gconv_parseconfdir.h
 | ||||
| +++ b/iconv/gconv_parseconfdir.h
 | ||||
| @@ -32,6 +32,8 @@
 | ||||
|  # define readdir __readdir | ||||
|  # define closedir __closedir | ||||
|  # define mempcpy __mempcpy | ||||
| +# undef lstat64
 | ||||
| +# define lstat64 __lstat64
 | ||||
|  #endif | ||||
|   | ||||
|  /* Name of the file containing the module information in the directories | ||||
| @@ -138,7 +140,7 @@ gconv_parseconfdir (const char *dir, size_t dir_len)
 | ||||
|        struct dirent *ent; | ||||
|        while ((ent = readdir (confdir)) != NULL) | ||||
|  	{ | ||||
| -	  if (ent->d_type != DT_REG)
 | ||||
| +	  if (ent->d_type != DT_REG && ent->d_type != DT_UNKNOWN)
 | ||||
|  	    continue; | ||||
|   | ||||
|  	  size_t len = strlen (ent->d_name); | ||||
| @@ -148,8 +150,14 @@ gconv_parseconfdir (const char *dir, size_t dir_len)
 | ||||
|  	      && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0) | ||||
|  	    { | ||||
|  	      char *conf; | ||||
| +	      struct stat64 st;
 | ||||
|  	      if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0) | ||||
|  		continue; | ||||
| +	      if (ent->d_type == DT_UNKNOWN
 | ||||
| +		  && (lstat64 (conf, &st) == -1
 | ||||
| +		      || !S_ISREG (st.st_mode)))
 | ||||
| +		continue;
 | ||||
| +
 | ||||
|  	      found |= read_conf_file (conf, dir, dir_len); | ||||
|  	      free (conf); | ||||
|  	    } | ||||
							
								
								
									
										98
									
								
								SOURCES/glibc-rh1971664-12.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								SOURCES/glibc-rh1971664-12.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | ||||
| commit 9429049c178b3af3d6afeb3717ff1f2214dc9572 | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Mon Jun 28 09:15:55 2021 +0530 | ||||
| 
 | ||||
|     iconvconfig: Fix multiple issues | ||||
|      | ||||
|     It was noticed on big-endian systems that msgfmt would fail with the | ||||
|     following error: | ||||
|      | ||||
|     msgfmt: gconv_builtin.c:70: __gconv_get_builtin_trans: Assertion `cnt < sizeof (map) / sizeof (map[0])' failed. | ||||
|     Aborted (core dumped) | ||||
|      | ||||
|     This is only seen on installed systems because it was due to a | ||||
|     corrupted gconv-modules.cache.  iconvconfig had the following issues | ||||
|     (it was specifically freeing fulldir that caused this issue, but other | ||||
|     cleanups are also needed) that this patch fixes. | ||||
|      | ||||
|     - Add prefix only if dir starts with '/' | ||||
|     - Use asprintf instead of mempcpy so that the directory string is NULL | ||||
|       terminated | ||||
|     - Make a copy of the directory reference in new_module so that fulldir | ||||
|       can be freed within the same scope in handle_dir. | ||||
|      | ||||
|     Reviewed-by: Florian Weimer <fweimer@redhat.com> | ||||
| 
 | ||||
| diff --git a/iconv/Makefile b/iconv/Makefile
 | ||||
| index d09b8ac842731780..6df9862e748ae588 100644
 | ||||
| --- a/iconv/Makefile
 | ||||
| +++ b/iconv/Makefile
 | ||||
| @@ -33,7 +33,7 @@ vpath %.c ../locale/programs ../intl
 | ||||
|  iconv_prog-modules = iconv_charmap charmap charmap-dir linereader \ | ||||
|  		     dummy-repertoire simple-hash xstrdup xmalloc \ | ||||
|  		     record-status | ||||
| -iconvconfig-modules = strtab xmalloc hash-string
 | ||||
| +iconvconfig-modules = strtab xmalloc xasprintf xstrdup hash-string
 | ||||
|  extra-objs	   = $(iconv_prog-modules:=.o) $(iconvconfig-modules:=.o) | ||||
|  CFLAGS-iconv_prog.c += -I../locale/programs | ||||
|  CFLAGS-iconv_charmap.c += -I../locale/programs | ||||
| diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
 | ||||
| index 01ecf6f67d55dbbf..777da870d2f8e99a 100644
 | ||||
| --- a/iconv/iconvconfig.c
 | ||||
| +++ b/iconv/iconvconfig.c
 | ||||
| @@ -250,6 +250,7 @@ static const char gconv_module_ext[] = MODULE_EXT;
 | ||||
|   | ||||
|   | ||||
|  #include <programs/xmalloc.h> | ||||
| +#include <programs/xasprintf.h>
 | ||||
|   | ||||
|   | ||||
|  /* C string table handling.  */ | ||||
| @@ -519,11 +520,12 @@ module_compare (const void *p1, const void *p2)
 | ||||
|  /* Create new module record.  */ | ||||
|  static void | ||||
|  new_module (const char *fromname, size_t fromlen, const char *toname, | ||||
| -	    size_t tolen, const char *directory,
 | ||||
| +	    size_t tolen, const char *dir_in,
 | ||||
|  	    const char *filename, size_t filelen, int cost, size_t need_ext) | ||||
|  { | ||||
|    struct module *new_module; | ||||
| -  size_t dirlen = strlen (directory) + 1;
 | ||||
| +  size_t dirlen = strlen (dir_in) + 1;
 | ||||
| +  const char *directory = xstrdup (dir_in);
 | ||||
|    char *tmp; | ||||
|    void **inserted; | ||||
|   | ||||
| @@ -654,20 +656,10 @@ handle_dir (const char *dir)
 | ||||
|    size_t dirlen = strlen (dir); | ||||
|    bool found = false; | ||||
|   | ||||
| -  /* Add the prefix before sending it off to the parser.  */
 | ||||
| -  char *fulldir = xmalloc (prefix_len + dirlen + 2);
 | ||||
| -  char *cp = mempcpy (mempcpy (fulldir, prefix, prefix_len), dir, dirlen);
 | ||||
| +  char *fulldir = xasprintf ("%s%s%s", dir[0] == '/' ? prefix : "",
 | ||||
| +			     dir, dir[dirlen - 1] != '/' ? "/" : "");
 | ||||
|   | ||||
| -  if (dir[dirlen - 1] != '/')
 | ||||
| -    {
 | ||||
| -      *cp++ = '/';
 | ||||
| -      *cp = '\0';
 | ||||
| -      dirlen++;
 | ||||
| -    }
 | ||||
| -
 | ||||
| -  found = gconv_parseconfdir (fulldir, dirlen + prefix_len);
 | ||||
| -
 | ||||
| -  free (fulldir);
 | ||||
| +  found = gconv_parseconfdir (fulldir, strlen (fulldir));
 | ||||
|   | ||||
|    if (!found) | ||||
|      { | ||||
| @@ -679,6 +671,8 @@ handle_dir (const char *dir)
 | ||||
|  	     "configuration files with names ending in .conf."); | ||||
|      } | ||||
|   | ||||
| +  free (fulldir);
 | ||||
| +
 | ||||
|    return found ? 0 : 1; | ||||
|  } | ||||
|   | ||||
							
								
								
									
										34
									
								
								SOURCES/glibc-rh1971664-13.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								SOURCES/glibc-rh1971664-13.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | ||||
| commit 7f784fabcb186ffaa082ed0aeed52a56b7d96cee | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Fri Jul 2 16:53:25 2021 +0530 | ||||
| 
 | ||||
|     iconvconfig: Use the public feof_unlocked | ||||
|      | ||||
|     Build of iconvconfig failed with CFLAGS=-Os since __feof_unlocked is | ||||
|     not a public symbol.  Replace with feof_unlocked (defined to | ||||
|     __feof_unlocked when IS_IN (libc)) to fix this. | ||||
|      | ||||
|     Reported-by: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
|     Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| 
 | ||||
| diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
 | ||||
| index ba9b3fd36d9e30f9..234b85a586f1d79a 100644
 | ||||
| --- a/iconv/gconv_parseconfdir.h
 | ||||
| +++ b/iconv/gconv_parseconfdir.h
 | ||||
| @@ -34,6 +34,7 @@
 | ||||
|  # define mempcpy __mempcpy | ||||
|  # undef lstat64 | ||||
|  # define lstat64 __lstat64 | ||||
| +# define feof_unlocked __feof_unlocked
 | ||||
|  #endif | ||||
|   | ||||
|  /* Name of the file containing the module information in the directories | ||||
| @@ -65,7 +66,7 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len)
 | ||||
|   | ||||
|    /* Process the known entries of the file.  Comments start with `#' and | ||||
|       end with the end of the line.  Empty lines are ignored.  */ | ||||
| -  while (!__feof_unlocked (fp))
 | ||||
| +  while (!feof_unlocked (fp))
 | ||||
|      { | ||||
|        char *rp, *endp, *word; | ||||
|        ssize_t n = __getdelim (&line, &line_len, '\n', fp); | ||||
							
								
								
									
										32
									
								
								SOURCES/glibc-rh1971664-14.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								SOURCES/glibc-rh1971664-14.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| commit 5f9b78fe35d08739b6da1e5b356786d41116c108 | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Tue Aug 3 21:10:20 2021 +0530 | ||||
| 
 | ||||
|     gconv_parseconfdir: Fix memory leak | ||||
|      | ||||
|     The allocated `conf` would leak if we have to skip over the file due | ||||
|     to the underlying filesystem not supporting dt_type. | ||||
|      | ||||
|     Reviewed-by: Arjun Shankar <arjun@redhat.com> | ||||
| 
 | ||||
| diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
 | ||||
| index 915b60845ca11c03..e4c3c16d1f96ce0c 100644
 | ||||
| --- a/iconv/gconv_parseconfdir.h
 | ||||
| +++ b/iconv/gconv_parseconfdir.h
 | ||||
| @@ -153,12 +153,11 @@ gconv_parseconfdir (const char *dir, size_t dir_len)
 | ||||
|  	      struct stat64 st; | ||||
|  	      if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0) | ||||
|  		continue; | ||||
| -	      if (ent->d_type == DT_UNKNOWN
 | ||||
| -		  && (lstat64 (conf, &st) == -1
 | ||||
| -		      || !S_ISREG (st.st_mode)))
 | ||||
| -		continue;
 | ||||
|   | ||||
| -	      found |= read_conf_file (conf, dir, dir_len);
 | ||||
| +	      if (ent->d_type != DT_UNKNOWN
 | ||||
| +		  || (lstat64 (conf, &st) != -1 && S_ISREG (st.st_mode)))
 | ||||
| +		found |= read_conf_file (conf, dir, dir_len);
 | ||||
| +
 | ||||
|  	      free (conf); | ||||
|  	    } | ||||
|  	} | ||||
							
								
								
									
										116
									
								
								SOURCES/glibc-rh1971664-15.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								SOURCES/glibc-rh1971664-15.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,116 @@ | ||||
| commit 43cea6d5652b6b9e61ac6ecc69419c909b504f47 | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Mon Sep 13 20:48:35 2021 +0530 | ||||
| 
 | ||||
|     iconvconfig: Fix behaviour with --prefix [BZ #28199] | ||||
|      | ||||
|     The consolidation of configuration parsing broke behaviour with | ||||
|     --prefix, where the prefix bled into the modules cache.  Accept a | ||||
|     prefix which, when non-NULL, is prepended to the path when looking for | ||||
|     configuration files but only the original directory is added to the | ||||
|     modules cache. | ||||
|      | ||||
|     This has no effect on the codegen of gconv_conf since it passes NULL. | ||||
|      | ||||
|     Reported-by: Patrick McCarty <patrick.mccarty@intel.com> | ||||
|     Reported-by: Michael Hudson-Doyle <michael.hudson@canonical.com> | ||||
|     Reviewed-by: Andreas Schwab <schwab@linux-m68k.org> | ||||
| 
 | ||||
| diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
 | ||||
| index ce64faa928dc1c52..3f5a692f1510157c 100644
 | ||||
| --- a/iconv/gconv_conf.c
 | ||||
| +++ b/iconv/gconv_conf.c
 | ||||
| @@ -476,7 +476,7 @@ __gconv_read_conf (void)
 | ||||
|      __gconv_get_path (); | ||||
|   | ||||
|    for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt) | ||||
| -    gconv_parseconfdir (__gconv_path_elem[cnt].name,
 | ||||
| +    gconv_parseconfdir (NULL, __gconv_path_elem[cnt].name,
 | ||||
|  			__gconv_path_elem[cnt].len); | ||||
|  #endif | ||||
|   | ||||
| diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
 | ||||
| index e4c3c16d1f96ce0c..433aa18bab5083b0 100644
 | ||||
| --- a/iconv/gconv_parseconfdir.h
 | ||||
| +++ b/iconv/gconv_parseconfdir.h
 | ||||
| @@ -39,7 +39,6 @@
 | ||||
|  /* Name of the file containing the module information in the directories | ||||
|     along the path.  */ | ||||
|  static const char gconv_conf_filename[] = "gconv-modules"; | ||||
| -static const char gconv_conf_dirname[] = "gconv-modules.d";
 | ||||
|   | ||||
|  static void add_alias (char *); | ||||
|  static void add_module (char *, const char *, size_t, int); | ||||
| @@ -110,19 +109,28 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len)
 | ||||
|    return true; | ||||
|  } | ||||
|   | ||||
| +/* Prefix DIR (with length DIR_LEN) with PREFIX if the latter is non-NULL and
 | ||||
| +   parse configuration in it.  */
 | ||||
| +
 | ||||
|  static __always_inline bool | ||||
| -gconv_parseconfdir (const char *dir, size_t dir_len)
 | ||||
| +gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len)
 | ||||
|  { | ||||
| -  /* No slash needs to be inserted between dir and gconv_conf_filename;
 | ||||
| -     dir already ends in a slash.  */
 | ||||
| -  char *buf = malloc (dir_len + sizeof (gconv_conf_dirname));
 | ||||
| +  /* No slash needs to be inserted between dir and gconv_conf_filename; dir
 | ||||
| +     already ends in a slash.  The additional 2 is to accommodate the ".d"
 | ||||
| +     when looking for configuration files in gconv-modules.d.  */
 | ||||
| +  size_t buflen = dir_len + sizeof (gconv_conf_filename) + 2;
 | ||||
| +  char *buf = malloc (buflen + (prefix != NULL ? strlen (prefix) : 0));
 | ||||
| +  char *cp = buf;
 | ||||
|    bool found = false; | ||||
|   | ||||
|    if (buf == NULL) | ||||
|      return false; | ||||
|   | ||||
| -  char *cp = mempcpy (mempcpy (buf, dir, dir_len), gconv_conf_filename,
 | ||||
| -		      sizeof (gconv_conf_filename));
 | ||||
| +  if (prefix != NULL)
 | ||||
| +    cp = stpcpy (cp, prefix);
 | ||||
| +
 | ||||
| +  cp = mempcpy (mempcpy (cp, dir, dir_len), gconv_conf_filename,
 | ||||
| +		sizeof (gconv_conf_filename));
 | ||||
|   | ||||
|    /* Read the gconv-modules configuration file first.  */ | ||||
|    found = read_conf_file (buf, dir, dir_len); | ||||
| diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
 | ||||
| index 777da870d2f8e99a..b1fd4100b5cbc9d2 100644
 | ||||
| --- a/iconv/iconvconfig.c
 | ||||
| +++ b/iconv/iconvconfig.c
 | ||||
| @@ -653,13 +653,21 @@ add_module (char *rp, const char *directory,
 | ||||
|  static int | ||||
|  handle_dir (const char *dir) | ||||
|  { | ||||
| +  char *newp = NULL;
 | ||||
|    size_t dirlen = strlen (dir); | ||||
|    bool found = false; | ||||
|   | ||||
| -  char *fulldir = xasprintf ("%s%s%s", dir[0] == '/' ? prefix : "",
 | ||||
| -			     dir, dir[dirlen - 1] != '/' ? "/" : "");
 | ||||
| +  /* End directory path with a '/' if it doesn't already.  */
 | ||||
| +  if (dir[dirlen - 1] != '/')
 | ||||
| +    {
 | ||||
| +      newp = xmalloc (dirlen + 2);
 | ||||
| +      memcpy (newp, dir, dirlen);
 | ||||
| +      newp[dirlen++] = '/';
 | ||||
| +      newp[dirlen] = '\0';
 | ||||
| +      dir = newp;
 | ||||
| +    }
 | ||||
|   | ||||
| -  found = gconv_parseconfdir (fulldir, strlen (fulldir));
 | ||||
| +  found = gconv_parseconfdir (dir[0] == '/' ? prefix : NULL, dir, dirlen);
 | ||||
|   | ||||
|    if (!found) | ||||
|      { | ||||
| @@ -671,7 +679,7 @@ handle_dir (const char *dir)
 | ||||
|  	     "configuration files with names ending in .conf."); | ||||
|      } | ||||
|   | ||||
| -  free (fulldir);
 | ||||
| +  free (newp);
 | ||||
|   | ||||
|    return found ? 0 : 1; | ||||
|  } | ||||
							
								
								
									
										109
									
								
								SOURCES/glibc-rh1971664-2.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								SOURCES/glibc-rh1971664-2.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,109 @@ | ||||
| commit 3979c3e1bae20459d9b6d424bdb49927d9cd6fec | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Mon Jun 7 14:22:18 2021 +0530 | ||||
| 
 | ||||
|     iconvconfig: Read configuration from gconv-modules.d subdirectory | ||||
|      | ||||
|     In addition to GCONV_PATH/gconv-modules, also read module | ||||
|     configuration from *.conf files in GCONV_PATH/gconv-modules.d.  This | ||||
|     allows a single gconv directory to have multiple sets of gconv modules | ||||
|     but at the same time, a single modules cache. | ||||
|      | ||||
|     With this feature, one could separate the glibc supported gconv | ||||
|     modules into a minimal essential set (ISO-8859-*, UTF, etc.) from the | ||||
|     remaining modules.  In future, these could be further segregated into | ||||
|     langpack-associated sets with their own | ||||
|     gconv-modules.d/someconfig.conf. | ||||
|      | ||||
|     Reviewed-by: DJ Delorie <dj@redhat.com> | ||||
| 
 | ||||
| diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
 | ||||
| index 2b3c587bc77cfdcd..fafc686ae25fb5c1 100644
 | ||||
| --- a/iconv/iconvconfig.c
 | ||||
| +++ b/iconv/iconvconfig.c
 | ||||
| @@ -18,6 +18,7 @@
 | ||||
|   | ||||
|  #include <argp.h> | ||||
|  #include <assert.h> | ||||
| +#include <dirent.h>
 | ||||
|  #include <error.h> | ||||
|  #include <errno.h> | ||||
|  #include <fcntl.h> | ||||
| @@ -33,6 +34,7 @@
 | ||||
|  #include <string.h> | ||||
|  #include <unistd.h> | ||||
|  #include <sys/cdefs.h> | ||||
| +#include <sys/types.h>
 | ||||
|  #include <sys/uio.h> | ||||
|   | ||||
|  #include "iconvconfig.h" | ||||
| @@ -710,6 +712,7 @@ handle_file (const char *dir, const char *infile)
 | ||||
|  static int | ||||
|  handle_dir (const char *dir) | ||||
|  { | ||||
| +#define BUF_LEN prefix_len + dirlen + sizeof "gconv-modules.d"
 | ||||
|    char *cp; | ||||
|    size_t dirlen = strlen (dir); | ||||
|    bool found = false; | ||||
| @@ -722,20 +725,55 @@ handle_dir (const char *dir)
 | ||||
|        newp[dirlen] = '\0'; | ||||
|      } | ||||
|   | ||||
| -  char infile[prefix_len + dirlen + sizeof "gconv-modules"];
 | ||||
| -  cp = infile;
 | ||||
| +  /* First, look for a gconv-modules file.  */
 | ||||
| +  char buf[BUF_LEN];
 | ||||
| +  cp = buf;
 | ||||
|    if (dir[0] == '/') | ||||
|      cp = mempcpy (cp, prefix, prefix_len); | ||||
| -  strcpy (mempcpy (cp, dir, dirlen), "gconv-modules");
 | ||||
| +  cp = mempcpy (cp, dir, dirlen);
 | ||||
| +  cp = stpcpy (cp, "gconv-modules");
 | ||||
|   | ||||
| -  found |= handle_file (dir, infile);
 | ||||
| +  found |= handle_file (dir, buf);
 | ||||
| +
 | ||||
| +  /* Next, see if there is a gconv-modules.d directory containing configuration
 | ||||
| +     files and if it is non-empty.  */
 | ||||
| +  cp[0] = '.';
 | ||||
| +  cp[1] = 'd';
 | ||||
| +  cp[2] = '\0';
 | ||||
| +
 | ||||
| +  DIR *confdir = opendir (buf);
 | ||||
| +  if (confdir != NULL)
 | ||||
| +    {
 | ||||
| +      struct dirent *ent;
 | ||||
| +      while ((ent = readdir (confdir)) != NULL)
 | ||||
| +	{
 | ||||
| +	  if (ent->d_type != DT_REG)
 | ||||
| +	    continue;
 | ||||
| +
 | ||||
| +	  size_t len = strlen (ent->d_name);
 | ||||
| +	  const char *suffix = ".conf";
 | ||||
| +
 | ||||
| +	  if (len > strlen (suffix)
 | ||||
| +	      && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
 | ||||
| +	    {
 | ||||
| +	      /* LEN <= PATH_MAX so this alloca is not unbounded.  */
 | ||||
| +	      char *conf = alloca (BUF_LEN + len + 1);
 | ||||
| +	      cp = stpcpy (conf, buf);
 | ||||
| +	      sprintf (cp, "/%s", ent->d_name);
 | ||||
| +	      found |= handle_file (dir, conf);
 | ||||
| +	    }
 | ||||
| +	}
 | ||||
| +      closedir (confdir);
 | ||||
| +    }
 | ||||
|   | ||||
|    if (!found) | ||||
|      { | ||||
| -      error (0, errno, "failed to open gconv configuration file in `%s'",
 | ||||
| +      error (0, errno, "failed to open gconv configuration files in `%s'",
 | ||||
|  	     dir); | ||||
|        error (0, 0, | ||||
| -	     "ensure that the directory contains a valid gconv-modules file.");
 | ||||
| +	     "ensure that the directory contains either a valid "
 | ||||
| +	     "gconv-modules file or a gconv-modules.d directory with "
 | ||||
| +	     "configuration files with names ending in .conf.");
 | ||||
|      } | ||||
|   | ||||
|    return found ? 0 : 1; | ||||
							
								
								
									
										99
									
								
								SOURCES/glibc-rh1971664-3.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								SOURCES/glibc-rh1971664-3.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | ||||
| commit b17d29b390154df9dfad9d21f1e6605422521fd2 | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Mon Jun 7 14:22:19 2021 +0530 | ||||
| 
 | ||||
|     gconv_conf: Read configuration files in gconv-modules.d | ||||
|      | ||||
|     Read configuration files with names ending in .conf in | ||||
|     GCONV_PATH/gconv-modules.d to mirror configuration flexibility in | ||||
|     iconvconfig into the iconv program and function. | ||||
|      | ||||
|     Reviewed-by: DJ Delorie <dj@redhat.com> | ||||
| 
 | ||||
| diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
 | ||||
| index f173cde71b2a61d7..8eb981fca7cee36a 100644
 | ||||
| --- a/iconv/gconv_conf.c
 | ||||
| +++ b/iconv/gconv_conf.c
 | ||||
| @@ -19,6 +19,7 @@
 | ||||
|   | ||||
|  #include <assert.h> | ||||
|  #include <ctype.h> | ||||
| +#include <dirent.h>
 | ||||
|  #include <errno.h> | ||||
|  #include <limits.h> | ||||
|  #include <locale.h> | ||||
| @@ -30,6 +31,7 @@
 | ||||
|  #include <string.h> | ||||
|  #include <unistd.h> | ||||
|  #include <sys/param.h> | ||||
| +#include <sys/types.h>
 | ||||
|   | ||||
|  #include <libc-lock.h> | ||||
|  #include <gconv_int.h> | ||||
| @@ -50,6 +52,7 @@ static const struct path_elem empty_path_elem = { NULL, 0 };
 | ||||
|  /* Name of the file containing the module information in the directories | ||||
|     along the path.  */ | ||||
|  static const char gconv_conf_filename[] = "gconv-modules"; | ||||
| +static const char gconv_conf_dirname[] = "gconv-modules.d";
 | ||||
|   | ||||
|  /* Filename extension for the modules.  */ | ||||
|  #ifndef MODULE_EXT | ||||
| @@ -554,18 +557,52 @@ __gconv_read_conf (void)
 | ||||
|   | ||||
|    for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt) | ||||
|      { | ||||
| +#define BUF_LEN elem_len + sizeof (gconv_conf_dirname)
 | ||||
| +
 | ||||
|        const char *elem = __gconv_path_elem[cnt].name; | ||||
|        size_t elem_len = __gconv_path_elem[cnt].len; | ||||
| -      char *filename;
 | ||||
| +      char *buf;
 | ||||
|   | ||||
|        /* No slash needs to be inserted between elem and gconv_conf_filename; | ||||
|  	 elem already ends in a slash.  */ | ||||
| -      filename = alloca (elem_len + sizeof (gconv_conf_filename));
 | ||||
| -      __mempcpy (__mempcpy (filename, elem, elem_len),
 | ||||
| -		 gconv_conf_filename, sizeof (gconv_conf_filename));
 | ||||
| +      buf = alloca (BUF_LEN);
 | ||||
| +      char *cp = __mempcpy (__mempcpy (buf, elem, elem_len),
 | ||||
| +			    gconv_conf_filename, sizeof (gconv_conf_filename));
 | ||||
| +
 | ||||
| +      /* Read the gconv-modules configuration file first.  */
 | ||||
| +      read_conf_file (buf, elem, elem_len, &modules, &nmodules);
 | ||||
| +
 | ||||
| +      /* Next, see if there is a gconv-modules.d directory containing
 | ||||
| +	 configuration files and if it is non-empty.  */
 | ||||
| +      cp--;
 | ||||
| +      cp[0] = '.';
 | ||||
| +      cp[1] = 'd';
 | ||||
| +      cp[2] = '\0';
 | ||||
| +
 | ||||
| +      DIR *confdir = __opendir (buf);
 | ||||
| +      if (confdir != NULL)
 | ||||
| +	{
 | ||||
| +	  struct dirent *ent;
 | ||||
| +	  while ((ent = __readdir (confdir)) != NULL)
 | ||||
| +	    {
 | ||||
| +	      if (ent->d_type != DT_REG)
 | ||||
| +		continue;
 | ||||
| +
 | ||||
| +	      size_t len = strlen (ent->d_name);
 | ||||
| +	      const char *suffix = ".conf";
 | ||||
|   | ||||
| -      /* Read the next configuration file.  */
 | ||||
| -      read_conf_file (filename, elem, elem_len, &modules, &nmodules);
 | ||||
| +	      if (len > strlen (suffix)
 | ||||
| +		  && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
 | ||||
| +		{
 | ||||
| +		  /* LEN <= PATH_MAX so this alloca is not unbounded.  */
 | ||||
| +		  char *conf = alloca (BUF_LEN + len + 1);
 | ||||
| +		  cp = stpcpy (conf, buf);
 | ||||
| +		  sprintf (cp, "/%s", ent->d_name);
 | ||||
| +		  read_conf_file (conf, elem, elem_len, &modules, &nmodules);
 | ||||
| +		}
 | ||||
| +	    }
 | ||||
| +	  __closedir (confdir);
 | ||||
| +	}
 | ||||
|      } | ||||
|  #endif | ||||
|   | ||||
							
								
								
									
										179
									
								
								SOURCES/glibc-rh1971664-4.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								SOURCES/glibc-rh1971664-4.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,179 @@ | ||||
| commit fc5bfade69ca12d034967dc6b929dbe3dd715172 | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Mon Jun 7 14:22:20 2021 +0530 | ||||
| 
 | ||||
|     iconvdata: Move gconv-modules configuration to gconv-modules.conf | ||||
|      | ||||
|     Move all gconv-modules configuration files to gconv-modules.conf. | ||||
|     That is, the S390 extensions now become gconv-modules-s390.conf.  Move | ||||
|     both configuration files into gconv-modules.d. | ||||
|      | ||||
|     Now GCONV_PATH/gconv-modules is read only for backward compatibility | ||||
|     for third-party gconv modules directories. | ||||
|      | ||||
|     Reviewed-by: DJ Delorie <dj@redhat.com> | ||||
| 
 | ||||
| # Conflicts: | ||||
| #	iconvdata/Makefile | ||||
| 
 | ||||
| diff --git a/iconvdata/Makefile b/iconvdata/Makefile
 | ||||
| index 32656ad31d9b434b..fc403e8abe3cc11f 100644
 | ||||
| --- a/iconvdata/Makefile
 | ||||
| +++ b/iconvdata/Makefile
 | ||||
| @@ -136,10 +136,13 @@ charmaps = ../localedata/charmaps
 | ||||
|  extra-modules-left := $(modules) | ||||
|  include extra-module.mk | ||||
|   | ||||
| +gconv-modules = gconv-modules.conf
 | ||||
| +modpfx = $(objpfx)gconv-modules.d/
 | ||||
|   | ||||
|  extra-objs	+= $(modules.so) | ||||
|  install-others	= $(addprefix $(inst_gconvdir)/, $(modules.so))	\ | ||||
| -		  $(inst_gconvdir)/gconv-modules
 | ||||
| +		  $(addprefix $(inst_gconvdir)/gconv-modules.d/, \
 | ||||
| +			      $(gconv-modules))
 | ||||
|   | ||||
|  # We can build the conversion tables for numerous charsets automatically. | ||||
|   | ||||
| @@ -181,7 +184,7 @@ generated += $(generated-modules:=.h) $(generated-modules:=.stmp) \
 | ||||
|  	     iconv-test.out iconv-rules tst-loading.mtrace	 \ | ||||
|  	     mtrace-tst-loading.out tst-tables.out iconv-test.xxx | ||||
|  ifdef objpfx | ||||
| -generated += gconv-modules
 | ||||
| +generated += $(addprefix gconv-modules.d/,$(gconv-modules))
 | ||||
|  endif | ||||
|   | ||||
|  # Rules to generate the headers. | ||||
| @@ -249,7 +252,8 @@ headers: $(addprefix $(objpfx), $(generated-modules:=.h))
 | ||||
|  $(addprefix $(inst_gconvdir)/, $(modules.so)): \ | ||||
|      $(inst_gconvdir)/%: $(objpfx)% $(+force) | ||||
|  	$(do-install-program) | ||||
| -$(inst_gconvdir)/gconv-modules: $(objpfx)gconv-modules $(+force)
 | ||||
| +$(addprefix $(inst_gconvdir)/gconv-modules.d/, $(gconv-modules)): \
 | ||||
| +    $(inst_gconvdir)/gconv-modules.d/%: $(modpfx)% $(+force)
 | ||||
|  	$(do-install) | ||||
|  ifeq (no,$(cross-compiling)) | ||||
|  # Update the $(prefix)/lib/gconv/gconv-modules.cache file. This is necessary | ||||
| @@ -297,29 +301,30 @@ $(objpfx)mtrace-tst-loading.out: $(objpfx)tst-loading.out
 | ||||
|  	$(common-objpfx)malloc/mtrace $(objpfx)tst-loading.mtrace > $@; \ | ||||
|  	$(evaluate-test) | ||||
|   | ||||
| -$(objpfx)bug-iconv1.out: $(objpfx)gconv-modules \
 | ||||
| +$(objpfx)bug-iconv1.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)bug-iconv2.out: $(objpfx)gconv-modules \
 | ||||
| +$(objpfx)bug-iconv2.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) | ||||
|  $(objpfx)bug-iconv3: $(libdl) | ||||
| -$(objpfx)bug-iconv3.out: $(objpfx)gconv-modules \
 | ||||
| +$(objpfx)bug-iconv3.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)bug-iconv5.out: $(objpfx)gconv-modules \
 | ||||
| +$(objpfx)bug-iconv5.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)tst-loading.out: $(objpfx)gconv-modules \
 | ||||
| +$(objpfx)tst-loading.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
|  			  $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)tst-iconv4.out: $(objpfx)gconv-modules \
 | ||||
| +$(objpfx)tst-iconv4.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)tst-iconv7.out: $(objpfx)gconv-modules \
 | ||||
| +$(objpfx)tst-iconv7.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)bug-iconv10.out: $(objpfx)gconv-modules \
 | ||||
| +$(objpfx)bug-iconv10.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
|  			  $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)bug-iconv12.out: $(objpfx)gconv-modules \
 | ||||
| +$(objpfx)bug-iconv12.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
|  			  $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)bug-iconv14.out: $(objpfx)gconv-modules \
 | ||||
| +$(objpfx)bug-iconv14.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
|  			  $(addprefix $(objpfx),$(modules.so)) | ||||
|   | ||||
| -$(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \
 | ||||
| +$(objpfx)iconv-test.out: run-iconv-test.sh \
 | ||||
| +			 $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) \ | ||||
|  			 $(common-objdir)/iconv/iconv_prog TESTS | ||||
|  	iconv_modules="$(modules)" \ | ||||
| @@ -327,7 +332,8 @@ $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \
 | ||||
|  		 '$(run-program-env)' > $@; \ | ||||
|  	$(evaluate-test) | ||||
|   | ||||
| -$(objpfx)tst-tables.out: tst-tables.sh $(objpfx)gconv-modules \
 | ||||
| +$(objpfx)tst-tables.out: tst-tables.sh \
 | ||||
| +			 $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) \ | ||||
|  			 $(objpfx)tst-table-from $(objpfx)tst-table-to | ||||
|  	$(SHELL) $< $(common-objpfx) $(common-objpfx)iconvdata/ \ | ||||
| @@ -340,5 +346,8 @@ do-tests-clean common-mostlyclean: tst-tables-clean
 | ||||
|  tst-tables-clean: | ||||
|  	-rm -f $(objpfx)tst-*.table $(objpfx)tst-EUC-TW.irreversible | ||||
|   | ||||
| -$(objpfx)gconv-modules: gconv-modules
 | ||||
| -	cat $(sysdeps-gconv-modules) $^ > $@
 | ||||
| +$(modpfx):
 | ||||
| +	mkdir -p $@
 | ||||
| +
 | ||||
| +$(modpfx)%: % $(modpfx)
 | ||||
| +	cp $< $@
 | ||||
| diff --git a/iconvdata/gconv-modules b/iconvdata/gconv-modules.conf
 | ||||
| similarity index 100% | ||||
| rename from iconvdata/gconv-modules | ||||
| rename to iconvdata/gconv-modules.conf | ||||
| diff --git a/localedata/Makefile b/localedata/Makefile
 | ||||
| index 14fcc37fed21e740..a5ca7a31f43d50c3 100644
 | ||||
| --- a/localedata/Makefile
 | ||||
| +++ b/localedata/Makefile
 | ||||
| @@ -179,7 +179,7 @@ install-others := $(addprefix $(inst_i18ndir)/, \
 | ||||
|  			      $(locales)) | ||||
|  endif | ||||
|   | ||||
| -tests: $(objdir)/iconvdata/gconv-modules
 | ||||
| +tests: $(objdir)/iconvdata/gconv-modules.d/gconv-modules.conf
 | ||||
|   | ||||
|  tests-static += tst-langinfo-newlocale-static tst-langinfo-setlocale-static | ||||
|   | ||||
| @@ -442,5 +442,5 @@ $(objpfx)mtrace-tst-leaks.out: $(objpfx)tst-leaks.out
 | ||||
|  bug-setlocale1-ENV-only = LOCPATH=$(objpfx) LC_CTYPE=de_DE.UTF-8 | ||||
|  bug-setlocale1-static-ENV-only = $(bug-setlocale1-ENV-only) | ||||
|   | ||||
| -$(objdir)/iconvdata/gconv-modules:
 | ||||
| +$(objdir)/iconvdata/gconv-modules.d/gconv-modules.conf:
 | ||||
|  	$(MAKE) -C ../iconvdata subdir=iconvdata $@ | ||||
| diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile
 | ||||
| index 8bc82e523f9049db..5c8e1170b4d799ba 100644
 | ||||
| --- a/sysdeps/s390/Makefile
 | ||||
| +++ b/sysdeps/s390/Makefile
 | ||||
| @@ -21,13 +21,25 @@ lib := iconvdata
 | ||||
|  include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left)) | ||||
|   | ||||
|  extra-objs      += $(addsuffix .so, $(s390x-iconv-modules)) | ||||
| -install-others  += $(patsubst %, $(inst_gconvdir)/%.so, $(s390x-iconv-modules))
 | ||||
| +install-others  += $(patsubst %, $(inst_gconvdir)/%.so, \
 | ||||
| +				 $(s390x-iconv-modules)) \
 | ||||
| +		   $(inst_gconvdir)/gconv-modules.d/gconv-modules-s390.conf
 | ||||
|   | ||||
|  $(patsubst %, $(inst_gconvdir)/%.so, $(s390x-iconv-modules)) : \ | ||||
|  $(inst_gconvdir)/%.so: $(objpfx)%.so $(+force) | ||||
|  	$(do-install-program) | ||||
|   | ||||
| -sysdeps-gconv-modules = ../sysdeps/s390/gconv-modules
 | ||||
| +ifdef objpfx
 | ||||
| +generated += gconv-modules.d/gconv-modules-s390.conf
 | ||||
| +endif
 | ||||
| +
 | ||||
| +$(inst_gconvdir)/gconv-modules.d/gconv-modules-s390.conf: \
 | ||||
| +		$(modpfx)gconv-modules-s390.conf $(+force)
 | ||||
| +	$(do-install)
 | ||||
| +
 | ||||
| +$(modpfx)gconv-modules-s390.conf: ../sysdeps/s390/gconv-modules-s390.conf \
 | ||||
| +				  $(modpfx)
 | ||||
| +	cp $< $@
 | ||||
|  endif | ||||
|   | ||||
|  ifeq ($(subdir),string) | ||||
| diff --git a/sysdeps/s390/gconv-modules b/sysdeps/s390/gconv-modules-s390.conf
 | ||||
| similarity index 100% | ||||
| rename from sysdeps/s390/gconv-modules | ||||
| rename to sysdeps/s390/gconv-modules-s390.conf | ||||
							
								
								
									
										3825
									
								
								SOURCES/glibc-rh1971664-5.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3825
									
								
								SOURCES/glibc-rh1971664-5.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										137
									
								
								SOURCES/glibc-rh1971664-6.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								SOURCES/glibc-rh1971664-6.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,137 @@ | ||||
| commit 06a1b794073c4d6adbfb2e4b11339985a14d7a00 | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Mon Jun 14 11:09:56 2021 +0530 | ||||
| 
 | ||||
|     Reinstate gconv-modules as the default configuration file | ||||
|      | ||||
|     Reinstate gconv-modules as the main file so that the configuration | ||||
|     files in gconv-modules.d/ become add-on configuration.  With this, the | ||||
|     effective user visible change is that GCONV_PATH can now have | ||||
|     supplementary configuration in GCONV_PATH/gconv-modules.d/ in addition | ||||
|     to the main GCONV_PATH/gconv-modules file. | ||||
| 
 | ||||
| # Conflicts: | ||||
| #	iconvdata/Makefile | ||||
| 
 | ||||
| diff --git a/iconvdata/Makefile b/iconvdata/Makefile
 | ||||
| index d682a98b5c4a8003..95e5fb8f722a513b 100644
 | ||||
| --- a/iconvdata/Makefile
 | ||||
| +++ b/iconvdata/Makefile
 | ||||
| @@ -136,13 +136,12 @@ charmaps = ../localedata/charmaps
 | ||||
|  extra-modules-left := $(modules) | ||||
|  include extra-module.mk | ||||
|   | ||||
| -gconv-modules = gconv-modules.conf gconv-modules-extra.conf
 | ||||
| +gconv-modules = gconv-modules gconv-modules.d/gconv-modules-extra.conf
 | ||||
|  modpfx = $(objpfx)gconv-modules.d/ | ||||
|   | ||||
|  extra-objs	+= $(modules.so) | ||||
|  install-others	= $(addprefix $(inst_gconvdir)/, $(modules.so))	\ | ||||
| -		  $(addprefix $(inst_gconvdir)/gconv-modules.d/, \
 | ||||
| -			      $(gconv-modules))
 | ||||
| +		  $(addprefix $(inst_gconvdir)/, $(gconv-modules))
 | ||||
|   | ||||
|  # We can build the conversion tables for numerous charsets automatically. | ||||
|   | ||||
| @@ -184,7 +183,7 @@ generated += $(generated-modules:=.h) $(generated-modules:=.stmp) \
 | ||||
|  	     iconv-test.out iconv-rules tst-loading.mtrace	 \ | ||||
|  	     mtrace-tst-loading.out tst-tables.out iconv-test.xxx | ||||
|  ifdef objpfx | ||||
| -generated += $(addprefix gconv-modules.d/,$(gconv-modules))
 | ||||
| +generated += $(gconv-modules)
 | ||||
|  endif | ||||
|   | ||||
|  # Rules to generate the headers. | ||||
| @@ -252,8 +251,8 @@ headers: $(addprefix $(objpfx), $(generated-modules:=.h))
 | ||||
|  $(addprefix $(inst_gconvdir)/, $(modules.so)): \ | ||||
|      $(inst_gconvdir)/%: $(objpfx)% $(+force) | ||||
|  	$(do-install-program) | ||||
| -$(addprefix $(inst_gconvdir)/gconv-modules.d/, $(gconv-modules)): \
 | ||||
| -    $(inst_gconvdir)/gconv-modules.d/%: $(modpfx)% $(+force)
 | ||||
| +$(addprefix $(inst_gconvdir)/, $(gconv-modules)): \
 | ||||
| +    $(inst_gconvdir)/%: $(objpfx)% $(+force)
 | ||||
|  	$(do-install) | ||||
|  ifeq (no,$(cross-compiling)) | ||||
|  # Update the $(prefix)/lib/gconv/gconv-modules.cache file. This is necessary | ||||
| @@ -301,30 +300,30 @@ $(objpfx)mtrace-tst-loading.out: $(objpfx)tst-loading.out
 | ||||
|  	$(common-objpfx)malloc/mtrace $(objpfx)tst-loading.mtrace > $@; \ | ||||
|  	$(evaluate-test) | ||||
|   | ||||
| -$(objpfx)bug-iconv1.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
| +$(objpfx)bug-iconv1.out: $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)bug-iconv2.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
| +$(objpfx)bug-iconv2.out: $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) | ||||
|  $(objpfx)bug-iconv3: $(libdl) | ||||
| -$(objpfx)bug-iconv3.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
| +$(objpfx)bug-iconv3.out: $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)bug-iconv5.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
| +$(objpfx)bug-iconv5.out: $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)tst-loading.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
| +$(objpfx)tst-loading.out: $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
|  			  $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)tst-iconv4.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
| +$(objpfx)tst-iconv4.out: $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)tst-iconv7.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
| +$(objpfx)tst-iconv7.out: $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)bug-iconv10.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
| +$(objpfx)bug-iconv10.out: $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
|  			  $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)bug-iconv12.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
| +$(objpfx)bug-iconv12.out: $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
|  			  $(addprefix $(objpfx),$(modules.so)) | ||||
| -$(objpfx)bug-iconv14.out: $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
| +$(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
|  			  $(addprefix $(objpfx),$(modules.so)) | ||||
|   | ||||
|  $(objpfx)iconv-test.out: run-iconv-test.sh \ | ||||
| -			 $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
| +			 $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) \ | ||||
|  			 $(common-objdir)/iconv/iconv_prog TESTS | ||||
|  	iconv_modules="$(modules)" \ | ||||
| @@ -333,7 +332,7 @@ $(objpfx)iconv-test.out: run-iconv-test.sh \
 | ||||
|  	$(evaluate-test) | ||||
|   | ||||
|  $(objpfx)tst-tables.out: tst-tables.sh \ | ||||
| -			 $(addprefix $(modpfx), $(gconv-modules)) \
 | ||||
| +			 $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
|  			 $(addprefix $(objpfx),$(modules.so)) \ | ||||
|  			 $(objpfx)tst-table-from $(objpfx)tst-table-to | ||||
|  	$(SHELL) $< $(common-objpfx) $(common-objpfx)iconvdata/ \ | ||||
| @@ -351,3 +350,6 @@ $(modpfx):
 | ||||
|   | ||||
|  $(modpfx)%: % $(modpfx) | ||||
|  	cp $< $@ | ||||
| +
 | ||||
| +$(objpfx)gconv-modules: gconv-modules
 | ||||
| +	cp $^ $@
 | ||||
| diff --git a/iconvdata/gconv-modules.conf b/iconvdata/gconv-modules
 | ||||
| similarity index 100% | ||||
| rename from iconvdata/gconv-modules.conf | ||||
| rename to iconvdata/gconv-modules | ||||
| diff --git a/localedata/Makefile b/localedata/Makefile
 | ||||
| index a5ca7a31f43d50c3..14fcc37fed21e740 100644
 | ||||
| --- a/localedata/Makefile
 | ||||
| +++ b/localedata/Makefile
 | ||||
| @@ -179,7 +179,7 @@ install-others := $(addprefix $(inst_i18ndir)/, \
 | ||||
|  			      $(locales)) | ||||
|  endif | ||||
|   | ||||
| -tests: $(objdir)/iconvdata/gconv-modules.d/gconv-modules.conf
 | ||||
| +tests: $(objdir)/iconvdata/gconv-modules
 | ||||
|   | ||||
|  tests-static += tst-langinfo-newlocale-static tst-langinfo-setlocale-static | ||||
|   | ||||
| @@ -442,5 +442,5 @@ $(objpfx)mtrace-tst-leaks.out: $(objpfx)tst-leaks.out
 | ||||
|  bug-setlocale1-ENV-only = LOCPATH=$(objpfx) LC_CTYPE=de_DE.UTF-8 | ||||
|  bug-setlocale1-static-ENV-only = $(bug-setlocale1-ENV-only) | ||||
|   | ||||
| -$(objdir)/iconvdata/gconv-modules.d/gconv-modules.conf:
 | ||||
| +$(objdir)/iconvdata/gconv-modules:
 | ||||
|  	$(MAKE) -C ../iconvdata subdir=iconvdata $@ | ||||
							
								
								
									
										107
									
								
								SOURCES/glibc-rh1971664-7.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								SOURCES/glibc-rh1971664-7.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,107 @@ | ||||
| commit e3217c7fd9e67aa2d53700bb1da9a966e73b9684 | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Thu Jun 10 00:41:35 2021 +0530 | ||||
| 
 | ||||
|     iconv: Remove alloca use in gconv-modules configuration parsing | ||||
|      | ||||
|     The alloca sizes ought to be constrained to PATH_MAX, but replace them | ||||
|     with dynamic allocation to be safe.  A static PATH_MAX array would | ||||
|     have worked too but Hurd does not have PATH_MAX and the code path is | ||||
|     not hot enough to micro-optimise this allocation.  Revisit if any of | ||||
|     those realities change. | ||||
|      | ||||
|     Reviewed-by: DJ Delorie <dj@redhat.com> | ||||
| 
 | ||||
| diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
 | ||||
| index 8eb981fca7cee36a..3099bf192adce711 100644
 | ||||
| --- a/iconv/gconv_conf.c
 | ||||
| +++ b/iconv/gconv_conf.c
 | ||||
| @@ -557,15 +557,15 @@ __gconv_read_conf (void)
 | ||||
|   | ||||
|    for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt) | ||||
|      { | ||||
| -#define BUF_LEN elem_len + sizeof (gconv_conf_dirname)
 | ||||
| -
 | ||||
|        const char *elem = __gconv_path_elem[cnt].name; | ||||
|        size_t elem_len = __gconv_path_elem[cnt].len; | ||||
| -      char *buf;
 | ||||
|   | ||||
|        /* No slash needs to be inserted between elem and gconv_conf_filename; | ||||
|  	 elem already ends in a slash.  */ | ||||
| -      buf = alloca (BUF_LEN);
 | ||||
| +      char *buf = malloc (elem_len + sizeof (gconv_conf_dirname));
 | ||||
| +      if (buf == NULL)
 | ||||
| +	continue;
 | ||||
| +
 | ||||
|        char *cp = __mempcpy (__mempcpy (buf, elem, elem_len), | ||||
|  			    gconv_conf_filename, sizeof (gconv_conf_filename)); | ||||
|   | ||||
| @@ -594,15 +594,16 @@ __gconv_read_conf (void)
 | ||||
|  	      if (len > strlen (suffix) | ||||
|  		  && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0) | ||||
|  		{ | ||||
| -		  /* LEN <= PATH_MAX so this alloca is not unbounded.  */
 | ||||
| -		  char *conf = alloca (BUF_LEN + len + 1);
 | ||||
| -		  cp = stpcpy (conf, buf);
 | ||||
| -		  sprintf (cp, "/%s", ent->d_name);
 | ||||
| +		  char *conf;
 | ||||
| +		  if (__asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
 | ||||
| +		    continue;
 | ||||
|  		  read_conf_file (conf, elem, elem_len, &modules, &nmodules); | ||||
| +		  free (conf);
 | ||||
|  		} | ||||
|  	    } | ||||
|  	  __closedir (confdir); | ||||
|  	} | ||||
| +      free (buf);
 | ||||
|      } | ||||
|  #endif | ||||
|   | ||||
| diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
 | ||||
| index fafc686ae25fb5c1..2f9d5f45ad3a8159 100644
 | ||||
| --- a/iconv/iconvconfig.c
 | ||||
| +++ b/iconv/iconvconfig.c
 | ||||
| @@ -712,7 +712,6 @@ handle_file (const char *dir, const char *infile)
 | ||||
|  static int | ||||
|  handle_dir (const char *dir) | ||||
|  { | ||||
| -#define BUF_LEN prefix_len + dirlen + sizeof "gconv-modules.d"
 | ||||
|    char *cp; | ||||
|    size_t dirlen = strlen (dir); | ||||
|    bool found = false; | ||||
| @@ -726,7 +725,10 @@ handle_dir (const char *dir)
 | ||||
|      } | ||||
|   | ||||
|    /* First, look for a gconv-modules file.  */ | ||||
| -  char buf[BUF_LEN];
 | ||||
| +  char *buf = malloc (prefix_len + dirlen + sizeof "gconv-modules.d");
 | ||||
| +  if (buf == NULL)
 | ||||
| +    goto out;
 | ||||
| +
 | ||||
|    cp = buf; | ||||
|    if (dir[0] == '/') | ||||
|      cp = mempcpy (cp, prefix, prefix_len); | ||||
| @@ -756,16 +758,19 @@ handle_dir (const char *dir)
 | ||||
|  	  if (len > strlen (suffix) | ||||
|  	      && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0) | ||||
|  	    { | ||||
| -	      /* LEN <= PATH_MAX so this alloca is not unbounded.  */
 | ||||
| -	      char *conf = alloca (BUF_LEN + len + 1);
 | ||||
| -	      cp = stpcpy (conf, buf);
 | ||||
| -	      sprintf (cp, "/%s", ent->d_name);
 | ||||
| +	      char *conf;
 | ||||
| +	      if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
 | ||||
| +		continue;
 | ||||
|  	      found |= handle_file (dir, conf); | ||||
| +	      free (conf);
 | ||||
|  	    } | ||||
|  	} | ||||
|        closedir (confdir); | ||||
|      } | ||||
|   | ||||
| +  free (buf);
 | ||||
| +
 | ||||
| +out:
 | ||||
|    if (!found) | ||||
|      { | ||||
|        error (0, errno, "failed to open gconv configuration files in `%s'", | ||||
							
								
								
									
										113
									
								
								SOURCES/glibc-rh1971664-8.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								SOURCES/glibc-rh1971664-8.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,113 @@ | ||||
| commit 23e15ea1ae80ec2120afdf643691359644cf2873 | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Thu Jun 10 09:51:50 2021 +0530 | ||||
| 
 | ||||
|     gconv_conf: Remove unused variables | ||||
|      | ||||
|     The modules and nmodules parameters passed to add_modules, add_alias, | ||||
|     etc. are not used and are hence unnecessary.  Remove them so that | ||||
|     their signatures match the functions in iconvconfig. | ||||
|      | ||||
|     Reviewed-by: DJ Delorie <dj@redhat.com> | ||||
|     Reviewed-by: Andreas Schwab <schwab@linux-m68k.org> | ||||
| 
 | ||||
| diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
 | ||||
| index 3099bf192adce711..dc12ce24844474cc 100644
 | ||||
| --- a/iconv/gconv_conf.c
 | ||||
| +++ b/iconv/gconv_conf.c
 | ||||
| @@ -125,7 +125,7 @@ detect_conflict (const char *alias)
 | ||||
|   | ||||
|  /* The actual code to add aliases.  */ | ||||
|  static void | ||||
| -add_alias2 (const char *from, const char *to, const char *wp, void *modules)
 | ||||
| +add_alias2 (const char *from, const char *to, const char *wp)
 | ||||
|  { | ||||
|    /* Test whether this alias conflicts with any available module.  */ | ||||
|    if (detect_conflict (from)) | ||||
| @@ -154,7 +154,7 @@ add_alias2 (const char *from, const char *to, const char *wp, void *modules)
 | ||||
|   | ||||
|  /* Add new alias.  */ | ||||
|  static void | ||||
| -add_alias (char *rp, void *modules)
 | ||||
| +add_alias (char *rp)
 | ||||
|  { | ||||
|    /* We now expect two more string.  The strings are normalized | ||||
|       (converted to UPPER case) and strored in the alias database.  */ | ||||
| @@ -179,7 +179,7 @@ add_alias (char *rp, void *modules)
 | ||||
|      return; | ||||
|    *wp++ = '\0'; | ||||
|   | ||||
| -  add_alias2 (from, to, wp, modules);
 | ||||
| +  add_alias2 (from, to, wp);
 | ||||
|  } | ||||
|   | ||||
|   | ||||
| @@ -243,8 +243,7 @@ insert_module (struct gconv_module *newp, int tobefreed)
 | ||||
|   | ||||
|  /* Add new module.  */ | ||||
|  static void | ||||
| -add_module (char *rp, const char *directory, size_t dir_len, void **modules,
 | ||||
| -	    size_t *nmodules, int modcounter)
 | ||||
| +add_module (char *rp, const char *directory, size_t dir_len, int modcounter)
 | ||||
|  { | ||||
|    /* We expect now | ||||
|       1. `from' name | ||||
| @@ -357,8 +356,7 @@ add_module (char *rp, const char *directory, size_t dir_len, void **modules,
 | ||||
|   | ||||
|  /* Read the next configuration file.  */ | ||||
|  static void | ||||
| -read_conf_file (const char *filename, const char *directory, size_t dir_len,
 | ||||
| -		void **modules, size_t *nmodules)
 | ||||
| +read_conf_file (const char *filename, const char *directory, size_t dir_len)
 | ||||
|  { | ||||
|    /* Note the file is opened with cancellation in the I/O functions | ||||
|       disabled.  */ | ||||
| @@ -408,10 +406,10 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len,
 | ||||
|   | ||||
|        if (rp - word == sizeof ("alias") - 1 | ||||
|  	  && memcmp (word, "alias", sizeof ("alias") - 1) == 0) | ||||
| -	add_alias (rp, *modules);
 | ||||
| +	add_alias (rp);
 | ||||
|        else if (rp - word == sizeof ("module") - 1 | ||||
|  	       && memcmp (word, "module", sizeof ("module") - 1) == 0) | ||||
| -	add_module (rp, directory, dir_len, modules, nmodules, modcounter++);
 | ||||
| +	add_module (rp, directory, dir_len, modcounter++);
 | ||||
|        /* else */ | ||||
|  	/* Otherwise ignore the line.  */ | ||||
|      } | ||||
| @@ -537,8 +535,6 @@ void
 | ||||
|  attribute_hidden | ||||
|  __gconv_read_conf (void) | ||||
|  { | ||||
| -  void *modules = NULL;
 | ||||
| -  size_t nmodules = 0;
 | ||||
|    int save_errno = errno; | ||||
|    size_t cnt; | ||||
|   | ||||
| @@ -570,7 +566,7 @@ __gconv_read_conf (void)
 | ||||
|  			    gconv_conf_filename, sizeof (gconv_conf_filename)); | ||||
|   | ||||
|        /* Read the gconv-modules configuration file first.  */ | ||||
| -      read_conf_file (buf, elem, elem_len, &modules, &nmodules);
 | ||||
| +      read_conf_file (buf, elem, elem_len);
 | ||||
|   | ||||
|        /* Next, see if there is a gconv-modules.d directory containing | ||||
|  	 configuration files and if it is non-empty.  */ | ||||
| @@ -597,7 +593,7 @@ __gconv_read_conf (void)
 | ||||
|  		  char *conf; | ||||
|  		  if (__asprintf (&conf, "%s/%s", buf, ent->d_name) < 0) | ||||
|  		    continue; | ||||
| -		  read_conf_file (conf, elem, elem_len, &modules, &nmodules);
 | ||||
| +		  read_conf_file (conf, elem, elem_len);
 | ||||
|  		  free (conf); | ||||
|  		} | ||||
|  	    } | ||||
| @@ -631,7 +627,7 @@ __gconv_read_conf (void)
 | ||||
|        const char *to = __rawmemchr (from, '\0') + 1; | ||||
|        cp = __rawmemchr (to, '\0') + 1; | ||||
|   | ||||
| -      add_alias2 (from, to, cp, modules);
 | ||||
| +      add_alias2 (from, to, cp);
 | ||||
|      } | ||||
|    while (*cp != '\0'); | ||||
|   | ||||
							
								
								
									
										360
									
								
								SOURCES/glibc-rh1971664-9.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										360
									
								
								SOURCES/glibc-rh1971664-9.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,360 @@ | ||||
| commit d8e8097f3be5b3c49fc741fa19e1da0b0431384c | ||||
| Author: Siddhesh Poyarekar <siddhesh@sourceware.org> | ||||
| Date:   Thu Jun 10 14:07:27 2021 +0530 | ||||
| 
 | ||||
|     gconv_conf: Split out configuration file processing | ||||
|      | ||||
|     Split configuration file processing into a separate header file and | ||||
|     include it.  Macroize all calls that need to go through internal | ||||
|     interfaces so that iconvconfig can also use them. | ||||
|      | ||||
|     Reviewed-by: DJ Delorie <dj@redhat.com> | ||||
| 
 | ||||
| # Conflicts: | ||||
| #	iconv/gconv_conf.c | ||||
| 
 | ||||
| diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
 | ||||
| index dc12ce24844474cc..ce64faa928dc1c52 100644
 | ||||
| --- a/iconv/gconv_conf.c
 | ||||
| +++ b/iconv/gconv_conf.c
 | ||||
| @@ -19,7 +19,6 @@
 | ||||
|   | ||||
|  #include <assert.h> | ||||
|  #include <ctype.h> | ||||
| -#include <dirent.h>
 | ||||
|  #include <errno.h> | ||||
|  #include <limits.h> | ||||
|  #include <locale.h> | ||||
| @@ -31,11 +30,10 @@
 | ||||
|  #include <string.h> | ||||
|  #include <unistd.h> | ||||
|  #include <sys/param.h> | ||||
| -#include <sys/types.h>
 | ||||
|   | ||||
|  #include <libc-lock.h> | ||||
|  #include <gconv_int.h> | ||||
| -
 | ||||
| +#include <gconv_parseconfdir.h>
 | ||||
|   | ||||
|  /* This is the default path where we look for module lists.  */ | ||||
|  static const char default_gconv_path[] = GCONV_PATH; | ||||
| @@ -49,11 +47,6 @@ size_t __gconv_max_path_elem_len;
 | ||||
|  /* We use the following struct if we couldn't allocate memory.  */ | ||||
|  static const struct path_elem empty_path_elem = { NULL, 0 }; | ||||
|   | ||||
| -/* Name of the file containing the module information in the directories
 | ||||
| -   along the path.  */
 | ||||
| -static const char gconv_conf_filename[] = "gconv-modules";
 | ||||
| -static const char gconv_conf_dirname[] = "gconv-modules.d";
 | ||||
| -
 | ||||
|  /* Filename extension for the modules.  */ | ||||
|  #ifndef MODULE_EXT | ||||
|  # define MODULE_EXT ".so" | ||||
| @@ -92,9 +85,6 @@ static const char builtin_aliases[] =
 | ||||
|  #undef BUILTIN_ALIAS | ||||
|  }; | ||||
|   | ||||
| -#include <libio/libioP.h>
 | ||||
| -#define __getdelim(line, len, c, fp) _IO_getdelim (line, len, c, fp)
 | ||||
| -
 | ||||
|   | ||||
|  /* Value of the GCONV_PATH environment variable.  */ | ||||
|  const char *__gconv_path_envvar; | ||||
| @@ -354,72 +344,6 @@ add_module (char *rp, const char *directory, size_t dir_len, int modcounter)
 | ||||
|  } | ||||
|   | ||||
|   | ||||
| -/* Read the next configuration file.  */
 | ||||
| -static void
 | ||||
| -read_conf_file (const char *filename, const char *directory, size_t dir_len)
 | ||||
| -{
 | ||||
| -  /* Note the file is opened with cancellation in the I/O functions
 | ||||
| -     disabled.  */
 | ||||
| -  FILE *fp = fopen (filename, "rce");
 | ||||
| -  char *line = NULL;
 | ||||
| -  size_t line_len = 0;
 | ||||
| -  static int modcounter;
 | ||||
| -
 | ||||
| -  /* Don't complain if a file is not present or readable, simply silently
 | ||||
| -     ignore it.  */
 | ||||
| -  if (fp == NULL)
 | ||||
| -    return;
 | ||||
| -
 | ||||
| -  /* No threads reading from this stream.  */
 | ||||
| -  __fsetlocking (fp, FSETLOCKING_BYCALLER);
 | ||||
| -
 | ||||
| -  /* Process the known entries of the file.  Comments start with `#' and
 | ||||
| -     end with the end of the line.  Empty lines are ignored.  */
 | ||||
| -  while (!__feof_unlocked (fp))
 | ||||
| -    {
 | ||||
| -      char *rp, *endp, *word;
 | ||||
| -      ssize_t n = __getdelim (&line, &line_len, '\n', fp);
 | ||||
| -      if (n < 0)
 | ||||
| -	/* An error occurred.  */
 | ||||
| -	break;
 | ||||
| -
 | ||||
| -      rp = line;
 | ||||
| -      /* Terminate the line (excluding comments or newline) by an NUL byte
 | ||||
| -	 to simplify the following code.  */
 | ||||
| -      endp = strchr (rp, '#');
 | ||||
| -      if (endp != NULL)
 | ||||
| -	*endp = '\0';
 | ||||
| -      else
 | ||||
| -	if (rp[n - 1] == '\n')
 | ||||
| -	  rp[n - 1] = '\0';
 | ||||
| -
 | ||||
| -      while (__isspace_l (*rp, _nl_C_locobj_ptr))
 | ||||
| -	++rp;
 | ||||
| -
 | ||||
| -      /* If this is an empty line go on with the next one.  */
 | ||||
| -      if (rp == endp)
 | ||||
| -	continue;
 | ||||
| -
 | ||||
| -      word = rp;
 | ||||
| -      while (*rp != '\0' && !__isspace_l (*rp, _nl_C_locobj_ptr))
 | ||||
| -	++rp;
 | ||||
| -
 | ||||
| -      if (rp - word == sizeof ("alias") - 1
 | ||||
| -	  && memcmp (word, "alias", sizeof ("alias") - 1) == 0)
 | ||||
| -	add_alias (rp);
 | ||||
| -      else if (rp - word == sizeof ("module") - 1
 | ||||
| -	       && memcmp (word, "module", sizeof ("module") - 1) == 0)
 | ||||
| -	add_module (rp, directory, dir_len, modcounter++);
 | ||||
| -      /* else */
 | ||||
| -	/* Otherwise ignore the line.  */
 | ||||
| -    }
 | ||||
| -
 | ||||
| -  free (line);
 | ||||
| -
 | ||||
| -  fclose (fp);
 | ||||
| -}
 | ||||
| -
 | ||||
| -
 | ||||
|  /* Determine the directories we are looking for data in.  */ | ||||
|  void | ||||
|  __gconv_get_path (void) | ||||
| @@ -552,55 +476,8 @@ __gconv_read_conf (void)
 | ||||
|      __gconv_get_path (); | ||||
|   | ||||
|    for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt) | ||||
| -    {
 | ||||
| -      const char *elem = __gconv_path_elem[cnt].name;
 | ||||
| -      size_t elem_len = __gconv_path_elem[cnt].len;
 | ||||
| -
 | ||||
| -      /* No slash needs to be inserted between elem and gconv_conf_filename;
 | ||||
| -	 elem already ends in a slash.  */
 | ||||
| -      char *buf = malloc (elem_len + sizeof (gconv_conf_dirname));
 | ||||
| -      if (buf == NULL)
 | ||||
| -	continue;
 | ||||
| -
 | ||||
| -      char *cp = __mempcpy (__mempcpy (buf, elem, elem_len),
 | ||||
| -			    gconv_conf_filename, sizeof (gconv_conf_filename));
 | ||||
| -
 | ||||
| -      /* Read the gconv-modules configuration file first.  */
 | ||||
| -      read_conf_file (buf, elem, elem_len);
 | ||||
| -
 | ||||
| -      /* Next, see if there is a gconv-modules.d directory containing
 | ||||
| -	 configuration files and if it is non-empty.  */
 | ||||
| -      cp--;
 | ||||
| -      cp[0] = '.';
 | ||||
| -      cp[1] = 'd';
 | ||||
| -      cp[2] = '\0';
 | ||||
| -
 | ||||
| -      DIR *confdir = __opendir (buf);
 | ||||
| -      if (confdir != NULL)
 | ||||
| -	{
 | ||||
| -	  struct dirent *ent;
 | ||||
| -	  while ((ent = __readdir (confdir)) != NULL)
 | ||||
| -	    {
 | ||||
| -	      if (ent->d_type != DT_REG)
 | ||||
| -		continue;
 | ||||
| -
 | ||||
| -	      size_t len = strlen (ent->d_name);
 | ||||
| -	      const char *suffix = ".conf";
 | ||||
| -
 | ||||
| -	      if (len > strlen (suffix)
 | ||||
| -		  && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
 | ||||
| -		{
 | ||||
| -		  char *conf;
 | ||||
| -		  if (__asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
 | ||||
| -		    continue;
 | ||||
| -		  read_conf_file (conf, elem, elem_len);
 | ||||
| -		  free (conf);
 | ||||
| -		}
 | ||||
| -	    }
 | ||||
| -	  __closedir (confdir);
 | ||||
| -	}
 | ||||
| -      free (buf);
 | ||||
| -    }
 | ||||
| +    gconv_parseconfdir (__gconv_path_elem[cnt].name,
 | ||||
| +			__gconv_path_elem[cnt].len);
 | ||||
|  #endif | ||||
|   | ||||
|    /* Add the internal modules.  */ | ||||
| diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..3d4d58d4be10a250
 | ||||
| --- /dev/null
 | ||||
| +++ b/iconv/gconv_parseconfdir.h
 | ||||
| @@ -0,0 +1,161 @@
 | ||||
| +/* Handle configuration data.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <dirent.h>
 | ||||
| +#include <libc-symbols.h>
 | ||||
| +#include <locale.h>
 | ||||
| +#include <sys/types.h>
 | ||||
| +
 | ||||
| +#if IS_IN (libc)
 | ||||
| +# include <libio/libioP.h>
 | ||||
| +# define __getdelim(line, len, c, fp) _IO_getdelim (line, len, c, fp)
 | ||||
| +
 | ||||
| +# undef isspace
 | ||||
| +# define isspace(__c) __isspace_l ((__c), _nl_C_locobj_ptr)
 | ||||
| +# define asprintf __asprintf
 | ||||
| +# define opendir __opendir
 | ||||
| +# define readdir __readdir
 | ||||
| +# define closedir __closedir
 | ||||
| +# define mempcpy __mempcpy
 | ||||
| +#endif
 | ||||
| +
 | ||||
| +/* Name of the file containing the module information in the directories
 | ||||
| +   along the path.  */
 | ||||
| +static const char gconv_conf_filename[] = "gconv-modules";
 | ||||
| +static const char gconv_conf_dirname[] = "gconv-modules.d";
 | ||||
| +
 | ||||
| +static void add_alias (char *);
 | ||||
| +static void add_module (char *, const char *, size_t, int);
 | ||||
| +
 | ||||
| +/* Read the next configuration file.  */
 | ||||
| +static bool
 | ||||
| +read_conf_file (const char *filename, const char *directory, size_t dir_len)
 | ||||
| +{
 | ||||
| +  /* Note the file is opened with cancellation in the I/O functions
 | ||||
| +     disabled.  */
 | ||||
| +  FILE *fp = fopen (filename, "rce");
 | ||||
| +  char *line = NULL;
 | ||||
| +  size_t line_len = 0;
 | ||||
| +  static int modcounter;
 | ||||
| +
 | ||||
| +  /* Don't complain if a file is not present or readable, simply silently
 | ||||
| +     ignore it.  */
 | ||||
| +  if (fp == NULL)
 | ||||
| +    return false;
 | ||||
| +
 | ||||
| +  /* No threads reading from this stream.  */
 | ||||
| +  __fsetlocking (fp, FSETLOCKING_BYCALLER);
 | ||||
| +
 | ||||
| +  /* Process the known entries of the file.  Comments start with `#' and
 | ||||
| +     end with the end of the line.  Empty lines are ignored.  */
 | ||||
| +  while (!__feof_unlocked (fp))
 | ||||
| +    {
 | ||||
| +      char *rp, *endp, *word;
 | ||||
| +      ssize_t n = __getdelim (&line, &line_len, '\n', fp);
 | ||||
| +      if (n < 0)
 | ||||
| +	/* An error occurred.  */
 | ||||
| +	break;
 | ||||
| +
 | ||||
| +      rp = line;
 | ||||
| +      /* Terminate the line (excluding comments or newline) by an NUL byte
 | ||||
| +	 to simplify the following code.  */
 | ||||
| +      endp = strchr (rp, '#');
 | ||||
| +      if (endp != NULL)
 | ||||
| +	*endp = '\0';
 | ||||
| +      else
 | ||||
| +	if (rp[n - 1] == '\n')
 | ||||
| +	  rp[n - 1] = '\0';
 | ||||
| +
 | ||||
| +      while (isspace (*rp))
 | ||||
| +	++rp;
 | ||||
| +
 | ||||
| +      /* If this is an empty line go on with the next one.  */
 | ||||
| +      if (rp == endp)
 | ||||
| +	continue;
 | ||||
| +
 | ||||
| +      word = rp;
 | ||||
| +      while (*rp != '\0' && !isspace (*rp))
 | ||||
| +	++rp;
 | ||||
| +
 | ||||
| +      if (rp - word == sizeof ("alias") - 1
 | ||||
| +	  && memcmp (word, "alias", sizeof ("alias") - 1) == 0)
 | ||||
| +	add_alias (rp);
 | ||||
| +      else if (rp - word == sizeof ("module") - 1
 | ||||
| +	       && memcmp (word, "module", sizeof ("module") - 1) == 0)
 | ||||
| +	add_module (rp, directory, dir_len, modcounter++);
 | ||||
| +      /* else */
 | ||||
| +	/* Otherwise ignore the line.  */
 | ||||
| +    }
 | ||||
| +
 | ||||
| +  free (line);
 | ||||
| +
 | ||||
| +  fclose (fp);
 | ||||
| +  return true;
 | ||||
| +}
 | ||||
| +
 | ||||
| +static __always_inline bool
 | ||||
| +gconv_parseconfdir (const char *dir, size_t dir_len)
 | ||||
| +{
 | ||||
| +  /* No slash needs to be inserted between dir and gconv_conf_filename;
 | ||||
| +     dir already ends in a slash.  */
 | ||||
| +  char *buf = malloc (dir_len + sizeof (gconv_conf_dirname));
 | ||||
| +  bool found = false;
 | ||||
| +
 | ||||
| +  if (buf == NULL)
 | ||||
| +    return false;
 | ||||
| +
 | ||||
| +  char *cp = mempcpy (mempcpy (buf, dir, dir_len), gconv_conf_filename,
 | ||||
| +		      sizeof (gconv_conf_filename));
 | ||||
| +
 | ||||
| +  /* Read the gconv-modules configuration file first.  */
 | ||||
| +  found = read_conf_file (buf, dir, dir_len);
 | ||||
| +
 | ||||
| +  /* Next, see if there is a gconv-modules.d directory containing
 | ||||
| +     configuration files and if it is non-empty.  */
 | ||||
| +  cp--;
 | ||||
| +  cp[0] = '.';
 | ||||
| +  cp[1] = 'd';
 | ||||
| +  cp[2] = '\0';
 | ||||
| +
 | ||||
| +  DIR *confdir = opendir (buf);
 | ||||
| +  if (confdir != NULL)
 | ||||
| +    {
 | ||||
| +      struct dirent *ent;
 | ||||
| +      while ((ent = readdir (confdir)) != NULL)
 | ||||
| +	{
 | ||||
| +	  if (ent->d_type != DT_REG)
 | ||||
| +	    continue;
 | ||||
| +
 | ||||
| +	  size_t len = strlen (ent->d_name);
 | ||||
| +	  const char *suffix = ".conf";
 | ||||
| +
 | ||||
| +	  if (len > strlen (suffix)
 | ||||
| +	      && strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
 | ||||
| +	    {
 | ||||
| +	      char *conf;
 | ||||
| +	      if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
 | ||||
| +		continue;
 | ||||
| +	      found |= read_conf_file (conf, dir, dir_len);
 | ||||
| +	      free (conf);
 | ||||
| +	    }
 | ||||
| +	}
 | ||||
| +      closedir (confdir);
 | ||||
| +    }
 | ||||
| +  free (buf);
 | ||||
| +  return found;
 | ||||
| +}
 | ||||
							
								
								
									
										33
									
								
								SOURCES/glibc-rh1977614.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								SOURCES/glibc-rh1977614.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| commit dfec225ee1972488bb48a8b67a2c4a13010c334a | ||||
| Author: JeffyChen <jeffy.chen@rock-chips.com> | ||||
| Date:   Fri Jul 2 17:39:24 2021 +0200 | ||||
| 
 | ||||
|     malloc: Initiate tcache shutdown even without allocations [BZ #28028] | ||||
|      | ||||
|     After commit 1e26d35193efbb29239c710a4c46a64708643320 ("malloc: Fix | ||||
|     tcache leak after thread destruction [BZ #22111]"), | ||||
|     tcache_shutting_down is still not early enough.  When we detach a | ||||
|     thread with no tcache allocated, tcache_shutting_down would still be | ||||
|     false. | ||||
|      | ||||
|     Reviewed-by: DJ Delorie <dj@redhat.com> | ||||
| 
 | ||||
| diff --git a/malloc/malloc.c b/malloc/malloc.c
 | ||||
| index 00a37f218c0ab3b2..61f7bdc76064c340 100644
 | ||||
| --- a/malloc/malloc.c
 | ||||
| +++ b/malloc/malloc.c
 | ||||
| @@ -2960,12 +2960,13 @@ tcache_thread_shutdown (void)
 | ||||
|    int i; | ||||
|    tcache_perthread_struct *tcache_tmp = tcache; | ||||
|   | ||||
| +  tcache_shutting_down = true;
 | ||||
| +
 | ||||
|    if (!tcache) | ||||
|      return; | ||||
|   | ||||
|    /* Disable the tcache and prevent it from being reinitialized.  */ | ||||
|    tcache = NULL; | ||||
| -  tcache_shutting_down = true;
 | ||||
|   | ||||
|    /* Free all of the entries and the tcache itself back to the arena | ||||
|       heap for coalescing.  */ | ||||
							
								
								
									
										306
									
								
								SOURCES/glibc-rh1983203-1.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								SOURCES/glibc-rh1983203-1.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,306 @@ | ||||
| commit a55e2da2702e235fa0ae66a116d304d1bffc060a | ||||
| Author: Lucas A. M. Magalhaes <lamm@linux.ibm.com> | ||||
| Date:   Thu May 6 17:01:52 2021 -0300 | ||||
| 
 | ||||
|     powerpc: Optimized memcmp for power10 | ||||
|      | ||||
|     This patch was based on the __memcmp_power8 and the recent | ||||
|     __strlen_power10. | ||||
|      | ||||
|     Improvements from __memcmp_power8: | ||||
|      | ||||
|     1. Don't need alignment code. | ||||
|      | ||||
|        On POWER10 lxvp and lxvl do not generate alignment interrupts, so | ||||
|     they are safe for use on caching-inhibited memory.  Notice that the | ||||
|     comparison on the main loop will wait for both VSR to be ready. | ||||
|     Therefore aligning one of the input address does not improve | ||||
|     performance.  In order to align both registers a vperm is necessary | ||||
|     which add too much overhead. | ||||
|      | ||||
|     2. Uses new POWER10 instructions | ||||
|      | ||||
|        This code uses lxvp to decrease contention on load by loading 32 bytes | ||||
|     per instruction. | ||||
|        The vextractbm is used to have a smaller tail code for calculating the | ||||
|     return value. | ||||
|      | ||||
|     3. Performance improvement | ||||
|      | ||||
|        This version has around 35% better performance on average. I saw no | ||||
|     performance regressions for any length or alignment. | ||||
|      | ||||
|     Thanks Matheus for helping me out with some details. | ||||
|      | ||||
|     Co-authored-by: Matheus Castanho <msc@linux.ibm.com> | ||||
|     Reviewed-by: Raphael M Zinsly <rzinsly@linux.ibm.com> | ||||
| 
 | ||||
| diff --git a/sysdeps/powerpc/powerpc64/le/power10/memcmp.S b/sysdeps/powerpc/powerpc64/le/power10/memcmp.S
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..52f244e7e77cbdf9
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/powerpc/powerpc64/le/power10/memcmp.S
 | ||||
| @@ -0,0 +1,179 @@
 | ||||
| +/* Optimized memcmp implementation for POWER10.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <sysdep.h>
 | ||||
| +
 | ||||
| +/* TODO: Replace macros by the actual instructions when minimum binutils becomes
 | ||||
| +   >= 2.35.  This is used to keep compatibility with older versions.  */
 | ||||
| +#define VEXTRACTBM(rt,vrb)	 \
 | ||||
| +	.long(((4)<<(32-6))	 \
 | ||||
| +	      | ((rt)<<(32-11))  \
 | ||||
| +	      | ((8)<<(32-16))	 \
 | ||||
| +	      | ((vrb)<<(32-21)) \
 | ||||
| +	      | 1602)
 | ||||
| +
 | ||||
| +#define LXVP(xtp,dq,ra)			   \
 | ||||
| +	.long(((6)<<(32-6))		   \
 | ||||
| +	      | ((((xtp)-32)>>1)<<(32-10)) \
 | ||||
| +	      | ((1)<<(32-11))		   \
 | ||||
| +	      | ((ra)<<(32-16))		   \
 | ||||
| +	      | dq)
 | ||||
| +
 | ||||
| +/* Compare 32 bytes.  */
 | ||||
| +#define COMPARE_32(vr1,vr2,offset,tail_1,tail_2)\
 | ||||
| +	LXVP(32+vr1,offset,r3);		\
 | ||||
| +	LXVP(32+vr2,offset,r4);		\
 | ||||
| +	vcmpneb.  v5,vr1+1,vr2+1;	\
 | ||||
| +	bne	  cr6,L(tail_2);	\
 | ||||
| +	vcmpneb.  v4,vr1,vr2;		\
 | ||||
| +	bne	  cr6,L(tail_1);	\
 | ||||
| +
 | ||||
| +#define TAIL(v_res,s1,s2)	\
 | ||||
| +	vctzlsbb  r7,v_res;	\
 | ||||
| +	vextubrx  r8,r7,s1;	\
 | ||||
| +	vextubrx  r9,r7,s2;	\
 | ||||
| +	subf	  r3,r9,r8;	\
 | ||||
| +	blr;			\
 | ||||
| +
 | ||||
| +/* int [r3] memcmp (const char *s1 [r3], const char *s2 [r4],
 | ||||
| +					size_t size [r5])  */
 | ||||
| +
 | ||||
| +#ifndef MEMCMP
 | ||||
| +# define MEMCMP memcmp
 | ||||
| +#endif
 | ||||
| +	.machine  power9
 | ||||
| +ENTRY_TOCLESS (MEMCMP, 4)
 | ||||
| +	CALL_MCOUNT 3
 | ||||
| +
 | ||||
| +	cmpldi	cr6,r5,64
 | ||||
| +	bgt	cr6,L(loop_head)
 | ||||
| +
 | ||||
| +/* Compare 64 bytes. This section is used for lengths <= 64 and for the last
 | ||||
| +   bytes for larger lengths.  */
 | ||||
| +L(last_compare):
 | ||||
| +	li	r8,16
 | ||||
| +
 | ||||
| +	sldi	r9,r5,56
 | ||||
| +	sldi	r8,r8,56
 | ||||
| +	addi	r6,r3,16
 | ||||
| +	addi	r7,r4,16
 | ||||
| +
 | ||||
| +	/* Align up to 16 bytes.  */
 | ||||
| +	lxvl	32+v0,r3,r9
 | ||||
| +	lxvl	32+v2,r4,r9
 | ||||
| +
 | ||||
| +	/* The sub. and vcmpneb. results are concatenated by the crnand in order
 | ||||
| +	   to do a single branch. It's doing a NOT(CR0.GT AND CR6.EQ) then
 | ||||
| +	   loading to CR0.LT.  That means r9 is not bigger than 0 and v4 is not
 | ||||
| +	   all equal to 0.  */
 | ||||
| +	sub.	  r9,r9,r8
 | ||||
| +	vcmpneb.  v4,v0,v2
 | ||||
| +	crnand	  4*cr0+lt,4*cr0+gt,4*cr6+eq
 | ||||
| +	bt	  4*cr0+lt,L(tail1)
 | ||||
| +
 | ||||
| +	addi	  r3,r3,32
 | ||||
| +	addi	  r4,r4,32
 | ||||
| +
 | ||||
| +	lxvl	  32+v1,r6,r9
 | ||||
| +	lxvl	  32+v3,r7,r9
 | ||||
| +	sub.	  r9,r9,r8
 | ||||
| +	vcmpneb.  v5,v1,v3
 | ||||
| +	crnand	  4*cr0+lt,4*cr0+gt,4*cr6+eq
 | ||||
| +	bt	  4*cr0+lt,L(tail2)
 | ||||
| +
 | ||||
| +	addi	  r6,r3,16
 | ||||
| +	addi	  r7,r4,16
 | ||||
| +
 | ||||
| +	lxvl	  32+v6,r3,r9
 | ||||
| +	lxvl	  32+v8,r4,r9
 | ||||
| +	sub.	  r9,r9,r8
 | ||||
| +	vcmpneb.  v4,v6,v8
 | ||||
| +	crnand	  4*cr0+lt,4*cr0+gt,4*cr6+eq
 | ||||
| +	bt	  4*cr0+lt,L(tail3)
 | ||||
| +
 | ||||
| +	lxvl	  32+v7,r6,r9
 | ||||
| +	lxvl	  32+v9,r7,r9
 | ||||
| +	vcmpneb.  v5,v7,v9
 | ||||
| +	bne	  cr6,L(tail4)
 | ||||
| +
 | ||||
| +L(finish):
 | ||||
| +	/* The contents are equal.  */
 | ||||
| +	li	r3,0
 | ||||
| +	blr
 | ||||
| +
 | ||||
| +L(loop_head):
 | ||||
| +	/* Calculate how many loops to run.  */
 | ||||
| +	srdi.	r8,r5,7
 | ||||
| +	beq	L(loop_tail)
 | ||||
| +	mtctr	r8
 | ||||
| +
 | ||||
| +/* Main loop.  Compares 128 bytes each loop.  */
 | ||||
| +	.p2align 5
 | ||||
| +L(loop_128):
 | ||||
| +	COMPARE_32(v0,v2,0,tail1,tail2)
 | ||||
| +	COMPARE_32(v6,v8,32,tail3,tail4)
 | ||||
| +	COMPARE_32(v10,v12,64,tail5,tail6)
 | ||||
| +	COMPARE_32(v14,v16,96,tail7,tail8)
 | ||||
| +
 | ||||
| +	addi	r3,r3,128
 | ||||
| +	addi	r4,r4,128
 | ||||
| +	bdnz	L(loop_128)
 | ||||
| +
 | ||||
| +	/* Account loop comparisons.  */
 | ||||
| +	clrldi.  r5,r5,57
 | ||||
| +	beq	 L(finish)
 | ||||
| +
 | ||||
| +/* Compares 64 bytes if length is still bigger than 64 bytes.  */
 | ||||
| +	.p2align 5
 | ||||
| +L(loop_tail):
 | ||||
| +	cmpldi	r5,64
 | ||||
| +	ble	L(last_compare)
 | ||||
| +	COMPARE_32(v0,v2,0,tail1,tail2)
 | ||||
| +	COMPARE_32(v6,v8,32,tail3,tail4)
 | ||||
| +	addi	r3,r3,64
 | ||||
| +	addi	r4,r4,64
 | ||||
| +	subi	r5,r5,64
 | ||||
| +	b	L(last_compare)
 | ||||
| +
 | ||||
| +L(tail1):
 | ||||
| +	TAIL(v4,v0,v2)
 | ||||
| +
 | ||||
| +L(tail2):
 | ||||
| +	TAIL(v5,v1,v3)
 | ||||
| +
 | ||||
| +L(tail3):
 | ||||
| +	TAIL(v4,v6,v8)
 | ||||
| +
 | ||||
| +L(tail4):
 | ||||
| +	TAIL(v5,v7,v9)
 | ||||
| +
 | ||||
| +L(tail5):
 | ||||
| +	TAIL(v4,v10,v12)
 | ||||
| +
 | ||||
| +L(tail6):
 | ||||
| +	TAIL(v5,v11,v13)
 | ||||
| +
 | ||||
| +L(tail7):
 | ||||
| +	TAIL(v4,v14,v16)
 | ||||
| +
 | ||||
| +L(tail8):
 | ||||
| +	TAIL(v5,v15,v17)
 | ||||
| +
 | ||||
| +END (MEMCMP)
 | ||||
| +libc_hidden_builtin_def (memcmp)
 | ||||
| +weak_alias (memcmp, bcmp)
 | ||||
| diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile
 | ||||
| index ac2446aca62cc4ab..ee98417f4a383356 100644
 | ||||
| --- a/sysdeps/powerpc/powerpc64/multiarch/Makefile
 | ||||
| +++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile
 | ||||
| @@ -32,7 +32,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \
 | ||||
|  		   strncase-power8 | ||||
|   | ||||
|  ifneq (,$(filter %le,$(config-machine))) | ||||
| -sysdep_routines += memcpy-power10 memmove-power10 memset-power10 \
 | ||||
| +sysdep_routines += memcmp-power10 memcpy-power10 memmove-power10 memset-power10 \
 | ||||
|  		   rawmemchr-power9 rawmemchr-power10 \ | ||||
|  		   strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 \ | ||||
|  		   strlen-power9 strncpy-power9 stpncpy-power9 strlen-power10 | ||||
| diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
 | ||||
| index 127af84b32a8196f..5213abdf87c79c88 100644
 | ||||
| --- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
 | ||||
| +++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c
 | ||||
| @@ -184,6 +184,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 | ||||
|   | ||||
|    /* Support sysdeps/powerpc/powerpc64/multiarch/memcmp.c.  */ | ||||
|    IFUNC_IMPL (i, name, memcmp, | ||||
| +#ifdef __LITTLE_ENDIAN__
 | ||||
| +	      IFUNC_IMPL_ADD (array, i, memcmp,
 | ||||
| +            hwcap2 & PPC_FEATURE2_ARCH_3_1
 | ||||
| +            && hwcap & PPC_FEATURE_HAS_VSX,
 | ||||
| +			      __memcmp_power10)
 | ||||
| +#endif
 | ||||
|  	      IFUNC_IMPL_ADD (array, i, memcmp, hwcap2 & PPC_FEATURE2_ARCH_2_07, | ||||
|  			      __memcmp_power8) | ||||
|  	      IFUNC_IMPL_ADD (array, i, memcmp, hwcap & PPC_FEATURE_HAS_VSX, | ||||
| diff --git a/sysdeps/powerpc/powerpc64/multiarch/memcmp-power10.S b/sysdeps/powerpc/powerpc64/multiarch/memcmp-power10.S
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..73a0debd4a811d8e
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/powerpc/powerpc64/multiarch/memcmp-power10.S
 | ||||
| @@ -0,0 +1,26 @@
 | ||||
| +/* Optimized memcmp implementation for POWER10.
 | ||||
| +   Copyright (C) 2017-2021 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/>.  */
 | ||||
| +
 | ||||
| +#define MEMCMP __memcmp_power10
 | ||||
| +
 | ||||
| +#undef libc_hidden_builtin_def
 | ||||
| +#define libc_hidden_builtin_def(name)
 | ||||
| +#undef weak_alias
 | ||||
| +#define weak_alias(name,alias)
 | ||||
| +
 | ||||
| +#include <sysdeps/powerpc/powerpc64/le/power10/memcmp.S>
 | ||||
| diff --git a/sysdeps/powerpc/powerpc64/multiarch/memcmp.c b/sysdeps/powerpc/powerpc64/multiarch/memcmp.c
 | ||||
| index 2c7a083a6560f920..0b8c0c1d8aa3f90a 100644
 | ||||
| --- a/sysdeps/powerpc/powerpc64/multiarch/memcmp.c
 | ||||
| +++ b/sysdeps/powerpc/powerpc64/multiarch/memcmp.c
 | ||||
| @@ -27,11 +27,17 @@ extern __typeof (memcmp) __memcmp_ppc attribute_hidden;
 | ||||
|  extern __typeof (memcmp) __memcmp_power4 attribute_hidden; | ||||
|  extern __typeof (memcmp) __memcmp_power7 attribute_hidden; | ||||
|  extern __typeof (memcmp) __memcmp_power8 attribute_hidden; | ||||
| +extern __typeof (memcmp) __memcmp_power10 attribute_hidden;
 | ||||
|  # undef memcmp | ||||
|   | ||||
|  /* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle | ||||
|     ifunc symbol properly.  */ | ||||
|  libc_ifunc_redirected (__redirect_memcmp, memcmp, | ||||
| +#ifdef __LITTLE_ENDIAN__
 | ||||
| +				(hwcap2 & PPC_FEATURE2_ARCH_3_1
 | ||||
| +				 && hwcap & PPC_FEATURE_HAS_VSX)
 | ||||
| +				 ? __memcmp_power10 :
 | ||||
| +#endif
 | ||||
|  		       (hwcap2 & PPC_FEATURE2_ARCH_2_07) | ||||
|  		       ? __memcmp_power8 : | ||||
|  		       (hwcap & PPC_FEATURE_HAS_VSX) | ||||
							
								
								
									
										278
									
								
								SOURCES/glibc-rh1983203-2.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										278
									
								
								SOURCES/glibc-rh1983203-2.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,278 @@ | ||||
| commit 813c6ec808556553be9d39e900a3fc97ceb32330 | ||||
| Author: Pedro Franco de Carvalho <pedromfc@linux.ibm.com> | ||||
| Date:   Wed Jun 30 12:36:07 2021 -0300 | ||||
| 
 | ||||
|     powerpc: optimize strcpy/stpcpy for POWER9/10 | ||||
|      | ||||
|     This patch modifies the current POWER9 implementation of strcpy and | ||||
|     stpcpy to optimize it for POWER9/10. | ||||
|      | ||||
|     Since no new POWER10 instructions are used, the original POWER9 strcpy is | ||||
|     modified instead of creating a new implementation for POWER10.  This | ||||
|     implementation is based on both the original POWER9 implementation of | ||||
|     strcpy and the preamble of the new POWER10 implementation of strlen. | ||||
|      | ||||
|     The changes also affect stpcpy, which uses the same implementation with | ||||
|     some additional code before returning. | ||||
|      | ||||
|     On POWER9, averaging improvements across the benchmark | ||||
|     inputs (length/source alignment/destination alignment), for an | ||||
|     experiment that ran the benchmark five times, bench-strcpy showed an | ||||
|     improvement of 5.23%, and bench-stpcpy showed an improvement of 6.59%. | ||||
|      | ||||
|     On POWER10, bench-strcpy showed 13.16%, and bench-stpcpy showed 13.59%. | ||||
|      | ||||
|     The changes are: | ||||
|      | ||||
|     1. Removed the null string optimization. | ||||
|      | ||||
|        Although this results in a few extra cycles for the null string, in | ||||
|        combination with the second change, this resulted in improvements for | ||||
|        for other cases. | ||||
|      | ||||
|     2. Adapted the preamble from strlen for POWER10. | ||||
|      | ||||
|        This is the part of the function that handles up to the first 16 bytes | ||||
|        of the string. | ||||
|      | ||||
|     3. Increased number of unrolled iterations in the main loop to 6. | ||||
|      | ||||
|     Reviewed-by: Matheus Castanho <msc@linux.ibm.com> | ||||
|     Tested-by: Matheus Castanho <msc@linux.ibm.com> | ||||
| 
 | ||||
| diff --git a/sysdeps/powerpc/powerpc64/le/power9/strcpy.S b/sysdeps/powerpc/powerpc64/le/power9/strcpy.S
 | ||||
| index ce8f50329177fd06..9845a1d4cf0e1e5d 100644
 | ||||
| --- a/sysdeps/powerpc/powerpc64/le/power9/strcpy.S
 | ||||
| +++ b/sysdeps/powerpc/powerpc64/le/power9/strcpy.S
 | ||||
| @@ -45,91 +45,78 @@
 | ||||
|     The implementation can load bytes past a null terminator, but only | ||||
|     up to the next 16B boundary, so it never crosses a page.  */ | ||||
|   | ||||
| +/* Load quadword at addr+offset to vreg, check for null bytes,
 | ||||
| +   and branch to label if any are found.  */
 | ||||
| +#define CHECK16(vreg,offset,addr,label) \
 | ||||
| +	lxv	vreg+32,offset(addr);	\
 | ||||
| +	vcmpequb. v6,vreg,v18;	\
 | ||||
| +	bne	cr6,L(label);
 | ||||
| +
 | ||||
|  .machine power9 | ||||
|  ENTRY_TOCLESS (FUNC_NAME, 4) | ||||
|  	CALL_MCOUNT 2 | ||||
|   | ||||
| -	/* NULL string optimisation  */
 | ||||
| -	lbz	r0,0(r4)
 | ||||
| -	stb	r0,0(r3)
 | ||||
| -	cmpwi	r0,0
 | ||||
| -	beqlr
 | ||||
| -
 | ||||
| -	addi	r4,r4,1
 | ||||
| -	addi	r11,r3,1
 | ||||
| -
 | ||||
|  	vspltisb v18,0		/* Zeroes in v18  */ | ||||
| +	vspltisb v19,-1 	/* 0xFF bytes in v19  */
 | ||||
|   | ||||
| -	neg	r5,r4
 | ||||
| -	rldicl	r9,r5,0,60	/* How many bytes to get source 16B aligned?  */
 | ||||
| +	/* Next 16B-aligned address. Prepare address for L(loop).  */
 | ||||
| +	addi	r5,r4,16
 | ||||
| +	clrrdi	r5,r5,4
 | ||||
| +	subf	r8,r4,r5
 | ||||
| +	add	r11,r3,r8
 | ||||
|   | ||||
| -	/* Get source 16B aligned  */
 | ||||
| +	/* Align data and fill bytes not loaded with non matching char.  */
 | ||||
|  	lvx	v0,0,r4 | ||||
|  	lvsr	v1,0,r4 | ||||
| -	vperm	v0,v18,v0,v1
 | ||||
| -
 | ||||
| -	vcmpequb v6,v0,v18	/* 0xff if byte is NULL, 0x00 otherwise  */
 | ||||
| -	vctzlsbb r7,v6		/* Number of trailing zeroes  */
 | ||||
| -	addi	r8,r7,1		/* Add null terminator  */
 | ||||
| +	vperm	v0,v19,v0,v1
 | ||||
|   | ||||
| -	/* r8 = bytes including null
 | ||||
| -	   r9 = bytes to get source 16B aligned
 | ||||
| -	   if r8 > r9
 | ||||
| -	      no null, copy r9 bytes
 | ||||
| -	   else
 | ||||
| -	      there is a null, copy r8 bytes and return.  */
 | ||||
| -	cmpd	r8,r9
 | ||||
| -	bgt	L(no_null)
 | ||||
| +	vcmpequb. v6,v0,v18	/* 0xff if byte is NULL, 0x00 otherwise  */
 | ||||
| +	beq	cr6,L(no_null)
 | ||||
|   | ||||
| -	sldi	r10,r8,56	/* stxvl wants size in top 8 bits  */
 | ||||
| -	stxvl	32+v0,r11,r10	/* Partial store  */
 | ||||
| +	/* There's a null byte.  */
 | ||||
| +	vctzlsbb r8,v6		/* Number of trailing zeroes  */
 | ||||
| +	addi	r9,r8,1 	/* Add null byte.  */
 | ||||
| +	sldi	r10,r9,56	/* stxvl wants size in top 8 bits.  */
 | ||||
| +	stxvl	32+v0,r3,r10	/* Partial store  */
 | ||||
|   | ||||
|  #ifdef USE_AS_STPCPY | ||||
|  	/* stpcpy returns the dest address plus the size not counting the | ||||
|  	   final '\0'.  */ | ||||
| -	add	r3,r11,r7
 | ||||
| +	add	r3,r3,r8
 | ||||
|  #endif | ||||
|  	blr | ||||
|   | ||||
|  L(no_null): | ||||
| -	sldi	r10,r9,56	/* stxvl wants size in top 8 bits  */
 | ||||
| -	stxvl	32+v0,r11,r10	/* Partial store  */
 | ||||
| -
 | ||||
| -	add	r4,r4,r9
 | ||||
| -	add	r11,r11,r9
 | ||||
| +	sldi	r10,r8,56	/* stxvl wants size in top 8 bits  */
 | ||||
| +	stxvl	32+v0,r3,r10	/* Partial store  */
 | ||||
|   | ||||
| +	.p2align 4
 | ||||
|  L(loop): | ||||
| -	lxv	32+v0,0(r4)
 | ||||
| -	vcmpequb. v6,v0,v18	/* Any zero bytes?  */
 | ||||
| -	bne	cr6,L(tail1)
 | ||||
| -
 | ||||
| -	lxv	32+v1,16(r4)
 | ||||
| -	vcmpequb. v6,v1,v18	/* Any zero bytes?  */
 | ||||
| -	bne	cr6,L(tail2)
 | ||||
| -
 | ||||
| -	lxv	32+v2,32(r4)
 | ||||
| -	vcmpequb. v6,v2,v18	/* Any zero bytes?  */
 | ||||
| -	bne	cr6,L(tail3)
 | ||||
| -
 | ||||
| -	lxv	32+v3,48(r4)
 | ||||
| -	vcmpequb. v6,v3,v18	/* Any zero bytes?  */
 | ||||
| -	bne	cr6,L(tail4)
 | ||||
| +	CHECK16(v0,0,r5,tail1)
 | ||||
| +	CHECK16(v1,16,r5,tail2)
 | ||||
| +	CHECK16(v2,32,r5,tail3)
 | ||||
| +	CHECK16(v3,48,r5,tail4)
 | ||||
| +	CHECK16(v4,64,r5,tail5)
 | ||||
| +	CHECK16(v5,80,r5,tail6)
 | ||||
|   | ||||
|  	stxv	32+v0,0(r11) | ||||
|  	stxv	32+v1,16(r11) | ||||
|  	stxv	32+v2,32(r11) | ||||
|  	stxv	32+v3,48(r11) | ||||
| +	stxv	32+v4,64(r11)
 | ||||
| +	stxv	32+v5,80(r11)
 | ||||
|   | ||||
| -	addi	r4,r4,64
 | ||||
| -	addi	r11,r11,64
 | ||||
| +	addi	r5,r5,96
 | ||||
| +	addi	r11,r11,96
 | ||||
|   | ||||
|  	b	L(loop) | ||||
|   | ||||
| +	.p2align 4
 | ||||
|  L(tail1): | ||||
| -	vctzlsbb r8,v6
 | ||||
| -	addi	r9,r8,1
 | ||||
| +	vctzlsbb r8,v6		/* Number of trailing zeroes  */
 | ||||
| +	addi	r9,r8,1		/* Add null terminator  */
 | ||||
|  	sldi	r9,r9,56	/* stxvl wants size in top 8 bits  */ | ||||
| -	stxvl	32+v0,r11,r9
 | ||||
| +	stxvl	32+v0,r11,r9	/* Partial store  */
 | ||||
|  #ifdef USE_AS_STPCPY | ||||
|  	/* stpcpy returns the dest address plus the size not counting the | ||||
|  	   final '\0'.  */ | ||||
| @@ -137,50 +124,81 @@ L(tail1):
 | ||||
|  #endif | ||||
|  	blr | ||||
|   | ||||
| +	.p2align 4
 | ||||
|  L(tail2): | ||||
|  	stxv	32+v0,0(r11) | ||||
| -	vctzlsbb r8,v6		/* Number of trailing zeroes  */
 | ||||
| -	addi	r9,r8,1		/* Add null terminator  */
 | ||||
| -	sldi	r10,r9,56	/* stxvl wants size in top 8 bits  */
 | ||||
| +	vctzlsbb r8,v6
 | ||||
| +	addi	r9,r8,1
 | ||||
| +	sldi	r9,r9,56
 | ||||
|  	addi	r11,r11,16 | ||||
| -	stxvl	32+v1,r11,r10	/* Partial store  */
 | ||||
| +	stxvl	32+v1,r11,r9
 | ||||
|  #ifdef USE_AS_STPCPY | ||||
| -	/* stpcpy returns the dest address plus the size not counting the
 | ||||
| -	   final '\0'.  */
 | ||||
|  	add	r3,r11,r8 | ||||
|  #endif | ||||
|  	blr | ||||
|   | ||||
| +	.p2align 4
 | ||||
|  L(tail3): | ||||
|  	stxv	32+v0,0(r11) | ||||
|  	stxv	32+v1,16(r11) | ||||
| -	vctzlsbb r8,v6		/* Number of trailing zeroes  */
 | ||||
| -	addi	r9,r8,1		/* Add null terminator  */
 | ||||
| -	sldi	r10,r9,56	/* stxvl wants size in top 8 bits  */
 | ||||
| +	vctzlsbb r8,v6
 | ||||
| +	addi	r9,r8,1
 | ||||
| +	sldi	r9,r9,56
 | ||||
|  	addi	r11,r11,32 | ||||
| -	stxvl	32+v2,r11,r10	/* Partial store  */
 | ||||
| +	stxvl	32+v2,r11,r9
 | ||||
|  #ifdef USE_AS_STPCPY | ||||
| -	/* stpcpy returns the dest address plus the size not counting the
 | ||||
| -	   final '\0'.  */
 | ||||
|  	add	r3,r11,r8 | ||||
|  #endif | ||||
|  	blr | ||||
|   | ||||
| +	.p2align 4
 | ||||
|  L(tail4): | ||||
|  	stxv	32+v0,0(r11) | ||||
|  	stxv	32+v1,16(r11) | ||||
|  	stxv	32+v2,32(r11) | ||||
| -	vctzlsbb r8,v6		/* Number of trailing zeroes  */
 | ||||
| -	addi	r9,r8,1		/* Add null terminator  */
 | ||||
| -	sldi	r10,r9,56	/* stxvl wants size in top 8 bits  */
 | ||||
| +	vctzlsbb r8,v6
 | ||||
| +	addi	r9,r8,1
 | ||||
| +	sldi	r9,r9,56
 | ||||
|  	addi	r11,r11,48 | ||||
| -	stxvl	32+v3,r11,r10	/* Partial store  */
 | ||||
| +	stxvl	32+v3,r11,r9
 | ||||
|  #ifdef USE_AS_STPCPY | ||||
| -	/* stpcpy returns the dest address plus the size not counting the
 | ||||
| -	   final '\0'.  */
 | ||||
|  	add	r3,r11,r8 | ||||
|  #endif | ||||
|  	blr | ||||
| +
 | ||||
| +	.p2align 4
 | ||||
| +L(tail5):
 | ||||
| +	stxv	32+v0,0(r11)
 | ||||
| +	stxv	32+v1,16(r11)
 | ||||
| +	stxv	32+v2,32(r11)
 | ||||
| +	stxv	32+v3,48(r11)
 | ||||
| +	vctzlsbb r8,v6
 | ||||
| +	addi	r9,r8,1
 | ||||
| +	sldi	r9,r9,56
 | ||||
| +	addi	r11,r11,64
 | ||||
| +	stxvl	32+v4,r11,r9
 | ||||
| +#ifdef USE_AS_STPCPY
 | ||||
| +	add	r3,r11,r8
 | ||||
| +#endif
 | ||||
| +	blr
 | ||||
| +
 | ||||
| +	.p2align 4
 | ||||
| +L(tail6):
 | ||||
| +	stxv	32+v0,0(r11)
 | ||||
| +	stxv	32+v1,16(r11)
 | ||||
| +	stxv	32+v2,32(r11)
 | ||||
| +	stxv	32+v3,48(r11)
 | ||||
| +	stxv	32+v4,64(r11)
 | ||||
| +	vctzlsbb r8,v6
 | ||||
| +	addi	r9,r8,1
 | ||||
| +	sldi	r9,r9,56
 | ||||
| +	addi	r11,r11,80
 | ||||
| +	stxvl	32+v5,r11,r9
 | ||||
| +#ifdef USE_AS_STPCPY
 | ||||
| +	add	r3,r11,r8
 | ||||
| +#endif
 | ||||
| +	blr
 | ||||
| +
 | ||||
|  END (FUNC_NAME) | ||||
|  #ifndef USE_AS_STPCPY | ||||
|  libc_hidden_builtin_def (strcpy) | ||||
							
								
								
									
										50
									
								
								SOURCES/glibc-rh1984802-1.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								SOURCES/glibc-rh1984802-1.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| From 756c306502498f999fdd494477b9cea1b45e4faf Mon Sep 17 00:00:00 2001 | ||||
| From: Stefan Liebler <stli@linux.ibm.com> | ||||
| Date: Fri, 21 Aug 2020 11:23:17 +0200 | ||||
| Subject: [PATCH] S390: Sync HWCAP names with kernel by adding aliases [BZ | ||||
|  #25971] | ||||
| 
 | ||||
| Unfortunately some HWCAP names like HWCAP_S390_VX differs between | ||||
| kernel (see <kernel>/arch/s390/include/asm/elf.h) and glibc. | ||||
| 
 | ||||
| Therefore, those HWCAP names from kernel are now introduced as alias | ||||
| ---
 | ||||
|  sysdeps/s390/dl-procinfo.h                | 3 +++ | ||||
|  sysdeps/unix/sysv/linux/s390/bits/hwcap.h | 3 +++ | ||||
|  2 files changed, 6 insertions(+) | ||||
| 
 | ||||
| diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h
 | ||||
| index 0db4bc39c7..08eee109f7 100644
 | ||||
| --- a/sysdeps/s390/dl-procinfo.h
 | ||||
| +++ b/sysdeps/s390/dl-procinfo.h
 | ||||
| @@ -51,8 +51,11 @@ enum
 | ||||
|    HWCAP_S390_HIGH_GPRS = 1 << 9, | ||||
|    HWCAP_S390_TE = 1 << 10, | ||||
|    HWCAP_S390_VX = 1 << 11, | ||||
| +  HWCAP_S390_VXRS = HWCAP_S390_VX,
 | ||||
|    HWCAP_S390_VXD = 1 << 12, | ||||
| +  HWCAP_S390_VXRS_BCD = HWCAP_S390_VXD,
 | ||||
|    HWCAP_S390_VXE = 1 << 13, | ||||
| +  HWCAP_S390_VXRS_EXT = HWCAP_S390_VXE,
 | ||||
|    HWCAP_S390_GS = 1 << 14, | ||||
|    HWCAP_S390_VXRS_EXT2 = 1 << 15, | ||||
|    HWCAP_S390_VXRS_PDE = 1 << 16, | ||||
| diff --git a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
 | ||||
| index 6adbec018b..f2998ff131 100644
 | ||||
| --- a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
 | ||||
| +++ b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
 | ||||
| @@ -36,8 +36,11 @@
 | ||||
|  #define HWCAP_S390_HIGH_GPRS    512 | ||||
|  #define HWCAP_S390_TE           1024 | ||||
|  #define HWCAP_S390_VX           2048 | ||||
| +#define HWCAP_S390_VXRS         HWCAP_S390_VX
 | ||||
|  #define HWCAP_S390_VXD          4096 | ||||
| +#define HWCAP_S390_VXRS_BCD     HWCAP_S390_VXD
 | ||||
|  #define HWCAP_S390_VXE          8192 | ||||
| +#define HWCAP_S390_VXRS_EXT     HWCAP_S390_VXE
 | ||||
|  #define HWCAP_S390_GS           16384 | ||||
|  #define HWCAP_S390_VXRS_EXT2    32768 | ||||
|  #define HWCAP_S390_VXRS_PDE     65536 | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
							
								
								
									
										67
									
								
								SOURCES/glibc-rh1984802-2.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								SOURCES/glibc-rh1984802-2.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | ||||
| From 25251c0707fe34f30a27381a5fabc35435a96621 Mon Sep 17 00:00:00 2001 | ||||
| From: Stefan Liebler <stli@linux.ibm.com> | ||||
| Date: Tue, 16 Feb 2021 16:18:56 +0100 | ||||
| Subject: [PATCH] S390: Add new hwcap values. | ||||
| 
 | ||||
| The new hwcap values indicate support for arch14 architecture. | ||||
| ---
 | ||||
|  sysdeps/s390/dl-procinfo.c                | 5 +++-- | ||||
|  sysdeps/s390/dl-procinfo.h                | 4 +++- | ||||
|  sysdeps/unix/sysv/linux/s390/bits/hwcap.h | 2 ++ | ||||
|  3 files changed, 8 insertions(+), 3 deletions(-) | ||||
| 
 | ||||
| diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c
 | ||||
| index 0c334a2551..c174e27b35 100644
 | ||||
| --- a/sysdeps/s390/dl-procinfo.c
 | ||||
| +++ b/sysdeps/s390/dl-procinfo.c
 | ||||
| @@ -46,12 +46,13 @@
 | ||||
|  #if !defined PROCINFO_DECL && defined SHARED | ||||
|    ._dl_s390_cap_flags | ||||
|  #else | ||||
| -PROCINFO_CLASS const char _dl_s390_cap_flags[19][9]
 | ||||
| +PROCINFO_CLASS const char _dl_s390_cap_flags[21][9]
 | ||||
|  #endif | ||||
|  #ifndef PROCINFO_DECL | ||||
|  = { | ||||
|       "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh", | ||||
| -     "highgprs", "te", "vx", "vxd", "vxe", "gs", "vxe2", "vxp", "sort", "dflt"
 | ||||
| +     "highgprs", "te", "vx", "vxd", "vxe", "gs", "vxe2", "vxp", "sort", "dflt",
 | ||||
| +     "vxp2", "nnpa"
 | ||||
|    } | ||||
|  #endif | ||||
|  #if !defined SHARED || defined PROCINFO_DECL | ||||
| diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h
 | ||||
| index 9e1a8c7ba9..2d9c305808 100644
 | ||||
| --- a/sysdeps/s390/dl-procinfo.h
 | ||||
| +++ b/sysdeps/s390/dl-procinfo.h
 | ||||
| @@ -21,7 +21,7 @@
 | ||||
|  #define _DL_PROCINFO_H	1 | ||||
|  #include <ldsodefs.h> | ||||
|   | ||||
| -#define _DL_HWCAP_COUNT 19
 | ||||
| +#define _DL_HWCAP_COUNT 21
 | ||||
|   | ||||
|  #define _DL_PLATFORMS_COUNT	10 | ||||
|   | ||||
| @@ -61,6 +61,8 @@ enum
 | ||||
|    HWCAP_S390_VXRS_PDE = 1 << 16, | ||||
|    HWCAP_S390_SORT = 1 << 17, | ||||
|    HWCAP_S390_DFLT = 1 << 18, | ||||
| +  HWCAP_S390_VXRS_PDE2 = 1 << 19,
 | ||||
| +  HWCAP_S390_NNPA = 1 << 20,
 | ||||
|  }; | ||||
|   | ||||
|  #define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \ | ||||
| diff --git a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
 | ||||
| index 696616e779..e9bd3684db 100644
 | ||||
| --- a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
 | ||||
| +++ b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
 | ||||
| @@ -46,3 +46,5 @@
 | ||||
|  #define HWCAP_S390_VXRS_PDE     65536 | ||||
|  #define HWCAP_S390_SORT         131072 | ||||
|  #define HWCAP_S390_DFLT         262144 | ||||
| +#define HWCAP_S390_VXRS_PDE2    524288
 | ||||
| +#define HWCAP_S390_NNPA         1048576
 | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
							
								
								
									
										88
									
								
								SOURCES/glibc-rh1984802-3.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								SOURCES/glibc-rh1984802-3.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | ||||
| From f2e06656d04a9fcb0603802a4f8ce7aa3a1f055e Mon Sep 17 00:00:00 2001 | ||||
| From: Stefan Liebler <stli@linux.ibm.com> | ||||
| Date: Tue, 5 Oct 2021 16:14:10 +0200 | ||||
| Subject: [PATCH] S390: Add PCI_MIO and SIE HWCAPs | ||||
| 
 | ||||
| Both new HWCAPs were introduced in these kernel commits: | ||||
| - 7e8403ecaf884f307b627f3c371475913dd29292
 | ||||
|   "s390: add HWCAP_S390_PCI_MIO to ELF hwcaps" | ||||
| - 7e82523f2583e9813e4109df3656707162541297
 | ||||
|   "s390/hwcaps: make sie capability regular hwcap" | ||||
| 
 | ||||
| Also note that the kernel commit 511ad531afd4090625def4d9aba1f5227bd44b8e | ||||
| "s390/hwcaps: shorten HWCAP defines" has shortened the prefix of the macros | ||||
| from "HWCAP_S390_" to "HWCAP_".  For compatibility reasons, we do not | ||||
| change the prefix in public glibc header file. | ||||
| ---
 | ||||
|  sysdeps/s390/dl-procinfo.c                | 4 ++-- | ||||
|  sysdeps/s390/dl-procinfo.h                | 4 +++- | ||||
|  sysdeps/unix/sysv/linux/s390/bits/hwcap.h | 7 +++++++ | ||||
|  3 files changed, 12 insertions(+), 3 deletions(-) | ||||
| 
 | ||||
| diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c
 | ||||
| index 7314c31b15..97be34fe9d 100644
 | ||||
| --- a/sysdeps/s390/dl-procinfo.c
 | ||||
| +++ b/sysdeps/s390/dl-procinfo.c
 | ||||
| @@ -45,13 +45,13 @@
 | ||||
|  #if !defined PROCINFO_DECL && defined SHARED | ||||
|    ._dl_s390_cap_flags | ||||
|  #else | ||||
| -PROCINFO_CLASS const char _dl_s390_cap_flags[21][9]
 | ||||
| +PROCINFO_CLASS const char _dl_s390_cap_flags[23][9]
 | ||||
|  #endif | ||||
|  #ifndef PROCINFO_DECL | ||||
|  = { | ||||
|       "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh", | ||||
|       "highgprs", "te", "vx", "vxd", "vxe", "gs", "vxe2", "vxp", "sort", "dflt", | ||||
| -     "vxp2", "nnpa"
 | ||||
| +     "vxp2", "nnpa", "pcimio", "sie"
 | ||||
|    } | ||||
|  #endif | ||||
|  #if !defined SHARED || defined PROCINFO_DECL | ||||
| diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h
 | ||||
| index 2502dd2604..d9a3b264ff 100644
 | ||||
| --- a/sysdeps/s390/dl-procinfo.h
 | ||||
| +++ b/sysdeps/s390/dl-procinfo.h
 | ||||
| @@ -20,7 +20,7 @@
 | ||||
|  #define _DL_PROCINFO_H	1 | ||||
|  #include <ldsodefs.h> | ||||
|   | ||||
| -#define _DL_HWCAP_COUNT 21
 | ||||
| +#define _DL_HWCAP_COUNT 23
 | ||||
|   | ||||
|  #define _DL_PLATFORMS_COUNT	10 | ||||
|   | ||||
| @@ -62,6 +62,8 @@ enum
 | ||||
|    HWCAP_S390_DFLT = 1 << 18, | ||||
|    HWCAP_S390_VXRS_PDE2 = 1 << 19, | ||||
|    HWCAP_S390_NNPA = 1 << 20, | ||||
| +  HWCAP_S390_PCI_MIO = 1 << 21,
 | ||||
| +  HWCAP_S390_SIE = 1 << 22,
 | ||||
|  }; | ||||
|   | ||||
|  #define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \ | ||||
| diff --git a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
 | ||||
| index e9bd3684db..00e73a3e3b 100644
 | ||||
| --- a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
 | ||||
| +++ b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h
 | ||||
| @@ -22,6 +22,11 @@
 | ||||
|   | ||||
|  /* | ||||
|   * The following must match the kernels asm/elf.h. | ||||
| + * Note: The kernel commit 511ad531afd4090625def4d9aba1f5227bd44b8e
 | ||||
| + * "s390/hwcaps: shorten HWCAP defines" has shortened the prefix of the macros
 | ||||
| + * from "HWCAP_S390_" to "HWCAP_".  For compatibility reasons, we do not
 | ||||
| + * change the prefix in public glibc header file.
 | ||||
| + *
 | ||||
|   * Note that these are *not* the same as the STORE FACILITY LIST bits. | ||||
|   */ | ||||
|  #define HWCAP_S390_ESAN3        1 | ||||
| @@ -48,3 +53,5 @@
 | ||||
|  #define HWCAP_S390_DFLT         262144 | ||||
|  #define HWCAP_S390_VXRS_PDE2    524288 | ||||
|  #define HWCAP_S390_NNPA         1048576 | ||||
| +#define HWCAP_S390_PCI_MIO      2097152
 | ||||
| +#define HWCAP_S390_SIE          4194304
 | ||||
| -- 
 | ||||
| 2.31.1 | ||||
| 
 | ||||
							
								
								
									
										30
									
								
								SOURCES/glibc-rh1991001-1.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								SOURCES/glibc-rh1991001-1.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| commit ad78d702757a189b1fa552d607e8aaa22252a45f | ||||
| Author: Florian Weimer <fweimer@redhat.com> | ||||
| Date:   Tue May 12 19:06:18 2020 +0200 | ||||
| 
 | ||||
|     elf: Remove redundant add_to_global_resize_failure  call from dl_open_args | ||||
|      | ||||
|     The second call does not do anything because the data structures have | ||||
|     already been resized by the call that comes before the demarcation | ||||
|     point.  Fixes commit a509eb117fac1d764b15eba64993f4bdb63d7f3c | ||||
|     ("Avoid late dlopen failure due to scope, TLS slotinfo updates | ||||
|     [BZ #25112]"). | ||||
|      | ||||
|     Reviewed-by: Carlos O'Donell <carlos@redhat.com> | ||||
| 
 | ||||
| diff --git a/elf/dl-open.c b/elf/dl-open.c
 | ||||
| index 3d49a84596e99bf6..b052bb0bc2cd17aa 100644
 | ||||
| --- a/elf/dl-open.c
 | ||||
| +++ b/elf/dl-open.c
 | ||||
| @@ -769,11 +769,6 @@ dl_open_worker (void *a)
 | ||||
|    DL_STATIC_INIT (new); | ||||
|  #endif | ||||
|   | ||||
| -  /* Perform the necessary allocations for adding new global objects
 | ||||
| -     to the global scope below, via add_to_global_update.  */
 | ||||
| -  if (mode & RTLD_GLOBAL)
 | ||||
| -    add_to_global_resize (new);
 | ||||
| -
 | ||||
|    /* Run the initializer functions of new objects.  Temporarily | ||||
|       disable the exception handler, so that lazy binding failures are | ||||
|       fatal.  */ | ||||
							
								
								
									
										23
									
								
								SOURCES/glibc-rh1991001-10.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								SOURCES/glibc-rh1991001-10.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| commit 52290d8c04569615fb011ee286d52dc5147afbd7 | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Thu Apr 15 09:57:10 2021 +0100 | ||||
| 
 | ||||
|     elf: Fix missing include in test case [BZ #27136] | ||||
|      | ||||
|     Broken test was introduced in | ||||
|      | ||||
|       commit 8f85075a2e9c26ff7486d4bbaf358999807d215c | ||||
|       elf: Add a DTV setup test [BZ #27136] | ||||
| 
 | ||||
| diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
 | ||||
| index ac5f8c8d39b66dd6..9977ec803208b9c8 100644
 | ||||
| --- a/elf/tst-tls20.c
 | ||||
| +++ b/elf/tst-tls20.c
 | ||||
| @@ -21,6 +21,7 @@
 | ||||
|  #include <stdio.h> | ||||
|  #include <stdlib.h> | ||||
|  #include <support/check.h> | ||||
| +#include <support/support.h>
 | ||||
|  #include <support/xdlfcn.h> | ||||
|  #include <support/xthread.h> | ||||
|   | ||||
							
								
								
									
										160
									
								
								SOURCES/glibc-rh1991001-11.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								SOURCES/glibc-rh1991001-11.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,160 @@ | ||||
| commit 2208066603a136f95cfb815ca9281262e6465784 | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Thu Feb 11 13:24:47 2021 +0000 | ||||
| 
 | ||||
|     elf: Remove lazy tlsdesc relocation related code | ||||
|      | ||||
|     Remove generic tlsdesc code related to lazy tlsdesc processing since | ||||
|     lazy tlsdesc relocation is no longer supported.  This includes removing | ||||
|     GL(dl_load_lock) from _dl_make_tlsdesc_dynamic which is only called at | ||||
|     load time when that lock is already held. | ||||
|      | ||||
|     Added a documentation comment too. | ||||
|      | ||||
|     Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org> | ||||
| 
 | ||||
| diff --git a/elf/tlsdeschtab.h b/elf/tlsdeschtab.h
 | ||||
| index fea9eefe72edcd6b..c20857e5b4264f00 100644
 | ||||
| --- a/elf/tlsdeschtab.h
 | ||||
| +++ b/elf/tlsdeschtab.h
 | ||||
| @@ -78,6 +78,10 @@ map_generation (struct link_map *map)
 | ||||
|    return GL(dl_tls_generation) + 1; | ||||
|  } | ||||
|   | ||||
| +/* Returns the data pointer for a given map and tls offset that is used
 | ||||
| +   to fill in one of the GOT entries referenced by a TLSDESC relocation
 | ||||
| +   when using dynamic TLS.  This requires allocation, returns NULL on
 | ||||
| +   allocation failure.  */
 | ||||
|  void * | ||||
|  _dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset) | ||||
|  { | ||||
| @@ -85,18 +89,12 @@ _dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset)
 | ||||
|    void **entry; | ||||
|    struct tlsdesc_dynamic_arg *td, test; | ||||
|   | ||||
| -  /* FIXME: We could use a per-map lock here, but is it worth it?  */
 | ||||
| -  __rtld_lock_lock_recursive (GL(dl_load_lock));
 | ||||
| -
 | ||||
|    ht = map->l_mach.tlsdesc_table; | ||||
|    if (! ht) | ||||
|      { | ||||
|        ht = htab_create (); | ||||
|        if (! ht) | ||||
| -	{
 | ||||
| -	  __rtld_lock_unlock_recursive (GL(dl_load_lock));
 | ||||
| -	  return 0;
 | ||||
| -	}
 | ||||
| +	return 0;
 | ||||
|        map->l_mach.tlsdesc_table = ht; | ||||
|      } | ||||
|   | ||||
| @@ -104,15 +102,11 @@ _dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset)
 | ||||
|    test.tlsinfo.ti_offset = ti_offset; | ||||
|    entry = htab_find_slot (ht, &test, 1, hash_tlsdesc, eq_tlsdesc); | ||||
|    if (! entry) | ||||
| -    {
 | ||||
| -      __rtld_lock_unlock_recursive (GL(dl_load_lock));
 | ||||
| -      return 0;
 | ||||
| -    }
 | ||||
| +    return 0;
 | ||||
|   | ||||
|    if (*entry) | ||||
|      { | ||||
|        td = *entry; | ||||
| -      __rtld_lock_unlock_recursive (GL(dl_load_lock));
 | ||||
|        return td; | ||||
|      } | ||||
|   | ||||
| @@ -122,44 +116,9 @@ _dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset)
 | ||||
|       thread.  */ | ||||
|    td->gen_count = map_generation (map); | ||||
|    td->tlsinfo = test.tlsinfo; | ||||
| -
 | ||||
| -  __rtld_lock_unlock_recursive (GL(dl_load_lock));
 | ||||
|    return td; | ||||
|  } | ||||
|   | ||||
|  # endif /* SHARED */ | ||||
|   | ||||
| -/* The idea of the following two functions is to stop multiple threads
 | ||||
| -   from attempting to resolve the same TLS descriptor without busy
 | ||||
| -   waiting.  Ideally, we should be able to release the lock right
 | ||||
| -   after changing td->entry, and then using say a condition variable
 | ||||
| -   or a futex wake to wake up any waiting threads, but let's try to
 | ||||
| -   avoid introducing such dependencies.  */
 | ||||
| -
 | ||||
| -static int
 | ||||
| -__attribute__ ((unused))
 | ||||
| -_dl_tlsdesc_resolve_early_return_p (struct tlsdesc volatile *td, void *caller)
 | ||||
| -{
 | ||||
| -  if (caller != atomic_load_relaxed (&td->entry))
 | ||||
| -    return 1;
 | ||||
| -
 | ||||
| -  __rtld_lock_lock_recursive (GL(dl_load_lock));
 | ||||
| -  if (caller != atomic_load_relaxed (&td->entry))
 | ||||
| -    {
 | ||||
| -      __rtld_lock_unlock_recursive (GL(dl_load_lock));
 | ||||
| -      return 1;
 | ||||
| -    }
 | ||||
| -
 | ||||
| -  atomic_store_relaxed (&td->entry, _dl_tlsdesc_resolve_hold);
 | ||||
| -
 | ||||
| -  return 0;
 | ||||
| -}
 | ||||
| -
 | ||||
| -static void
 | ||||
| -__attribute__ ((unused))
 | ||||
| -_dl_tlsdesc_wake_up_held_fixups (void)
 | ||||
| -{
 | ||||
| -  __rtld_lock_unlock_recursive (GL(dl_load_lock));
 | ||||
| -}
 | ||||
| -
 | ||||
|  #endif | ||||
| diff --git a/sysdeps/aarch64/tlsdesc.c b/sysdeps/aarch64/tlsdesc.c
 | ||||
| index 357465f23d76e2bd..1ead73ab8250e29c 100644
 | ||||
| --- a/sysdeps/aarch64/tlsdesc.c
 | ||||
| +++ b/sysdeps/aarch64/tlsdesc.c
 | ||||
| @@ -22,7 +22,6 @@
 | ||||
|  #include <tls.h> | ||||
|  #include <dl-tlsdesc.h> | ||||
|  #include <dl-unmap-segments.h> | ||||
| -#define _dl_tlsdesc_resolve_hold 0
 | ||||
|  #include <tlsdeschtab.h> | ||||
|   | ||||
|  /* Unmap the dynamic object, but also release its TLS descriptor table | ||||
| diff --git a/sysdeps/arm/tlsdesc.c b/sysdeps/arm/tlsdesc.c
 | ||||
| index d142d7a2c91e9adb..b78e3f65785bf587 100644
 | ||||
| --- a/sysdeps/arm/tlsdesc.c
 | ||||
| +++ b/sysdeps/arm/tlsdesc.c
 | ||||
| @@ -20,7 +20,6 @@
 | ||||
|  #include <tls.h> | ||||
|  #include <dl-tlsdesc.h> | ||||
|  #include <dl-unmap-segments.h> | ||||
| -#define _dl_tlsdesc_resolve_hold 0
 | ||||
|  #include <tlsdeschtab.h> | ||||
|   | ||||
|  /* Unmap the dynamic object, but also release its TLS descriptor table | ||||
| diff --git a/sysdeps/i386/tlsdesc.c b/sysdeps/i386/tlsdesc.c
 | ||||
| index 1b4227c8381e1b3d..c242ffce726d50e4 100644
 | ||||
| --- a/sysdeps/i386/tlsdesc.c
 | ||||
| +++ b/sysdeps/i386/tlsdesc.c
 | ||||
| @@ -20,7 +20,6 @@
 | ||||
|  #include <tls.h> | ||||
|  #include <dl-tlsdesc.h> | ||||
|  #include <dl-unmap-segments.h> | ||||
| -#define _dl_tlsdesc_resolve_hold 0
 | ||||
|  #include <tlsdeschtab.h> | ||||
|   | ||||
|  /* Unmap the dynamic object, but also release its TLS descriptor table | ||||
| diff --git a/sysdeps/x86_64/tlsdesc.c b/sysdeps/x86_64/tlsdesc.c
 | ||||
| index 61a19ae26944c84f..a9325827d0e5e31b 100644
 | ||||
| --- a/sysdeps/x86_64/tlsdesc.c
 | ||||
| +++ b/sysdeps/x86_64/tlsdesc.c
 | ||||
| @@ -20,7 +20,6 @@
 | ||||
|  #include <tls.h> | ||||
|  #include <dl-tlsdesc.h> | ||||
|  #include <dl-unmap-segments.h> | ||||
| -#define _dl_tlsdesc_resolve_hold 0
 | ||||
|  #include <tlsdeschtab.h> | ||||
|   | ||||
|  /* Unmap the dynamic object, but also release its TLS descriptor table | ||||
							
								
								
									
										182
									
								
								SOURCES/glibc-rh1991001-12.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								SOURCES/glibc-rh1991001-12.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,182 @@ | ||||
| commit 1387ad6225c2222f027790e3f460e31aa5dd2c54 | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Wed Dec 30 19:19:37 2020 +0000 | ||||
| 
 | ||||
|     elf: Fix data races in pthread_create and TLS access [BZ #19329] | ||||
|      | ||||
|     DTV setup at thread creation (_dl_allocate_tls_init) is changed | ||||
|     to take the dlopen lock, GL(dl_load_lock).  Avoiding data races | ||||
|     here without locks would require design changes: the map that is | ||||
|     accessed for static TLS initialization here may be concurrently | ||||
|     freed by dlclose.  That use after free may be solved by only | ||||
|     locking around static TLS setup or by ensuring dlclose does not | ||||
|     free modules with static TLS, however currently every link map | ||||
|     with TLS has to be accessed at least to see if it needs static | ||||
|     TLS.  And even if that's solved, still a lot of atomics would be | ||||
|     needed to synchronize DTV related globals without a lock. So fix | ||||
|     both bug 19329 and bug 27111 with a lock that prevents DTV setup | ||||
|     running concurrently with dlopen or dlclose. | ||||
|      | ||||
|     _dl_update_slotinfo at TLS access still does not use any locks | ||||
|     so CONCURRENCY NOTES are added to explain the synchronization. | ||||
|     The early exit from the slotinfo walk when max_modid is reached | ||||
|     is not strictly necessary, but does not hurt either. | ||||
|      | ||||
|     An incorrect acquire load was removed from _dl_resize_dtv: it | ||||
|     did not synchronize with any release store or fence and | ||||
|     synchronization is now handled separately at thread creation | ||||
|     and TLS access time. | ||||
|      | ||||
|     There are still a number of racy read accesses to globals that | ||||
|     will be changed to relaxed MO atomics in a followup patch. This | ||||
|     should not introduce regressions compared to existing behaviour | ||||
|     and avoid cluttering the main part of the fix. | ||||
|      | ||||
|     Not all TLS access related data races got fixed here: there are | ||||
|     additional races at lazy tlsdesc relocations see bug 27137. | ||||
|      | ||||
|     Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org> | ||||
| 
 | ||||
| diff --git a/elf/dl-tls.c b/elf/dl-tls.c
 | ||||
| index 15ed01d795a8627a..da83cd6ae2ee6504 100644
 | ||||
| --- a/elf/dl-tls.c
 | ||||
| +++ b/elf/dl-tls.c
 | ||||
| @@ -471,14 +471,11 @@ extern dtv_t _dl_static_dtv[];
 | ||||
|  #endif | ||||
|   | ||||
|  static dtv_t * | ||||
| -_dl_resize_dtv (dtv_t *dtv)
 | ||||
| +_dl_resize_dtv (dtv_t *dtv, size_t max_modid)
 | ||||
|  { | ||||
|    /* Resize the dtv.  */ | ||||
|    dtv_t *newp; | ||||
| -  /* Load GL(dl_tls_max_dtv_idx) atomically since it may be written to by
 | ||||
| -     other threads concurrently.  */
 | ||||
| -  size_t newsize
 | ||||
| -    = atomic_load_acquire (&GL(dl_tls_max_dtv_idx)) + DTV_SURPLUS;
 | ||||
| +  size_t newsize = max_modid + DTV_SURPLUS;
 | ||||
|    size_t oldsize = dtv[-1].counter; | ||||
|   | ||||
|    if (dtv == GL(dl_initial_dtv)) | ||||
| @@ -524,11 +521,14 @@ _dl_allocate_tls_init (void *result)
 | ||||
|    size_t total = 0; | ||||
|    size_t maxgen = 0; | ||||
|   | ||||
| +  /* Protects global dynamic TLS related state.  */
 | ||||
| +  __rtld_lock_lock_recursive (GL(dl_load_lock));
 | ||||
| +
 | ||||
|    /* Check if the current dtv is big enough.   */ | ||||
|    if (dtv[-1].counter < GL(dl_tls_max_dtv_idx)) | ||||
|      { | ||||
|        /* Resize the dtv.  */ | ||||
| -      dtv = _dl_resize_dtv (dtv);
 | ||||
| +      dtv = _dl_resize_dtv (dtv, GL(dl_tls_max_dtv_idx));
 | ||||
|   | ||||
|        /* Install this new dtv in the thread data structures.  */ | ||||
|        INSTALL_DTV (result, &dtv[-1]); | ||||
| @@ -596,6 +596,7 @@ _dl_allocate_tls_init (void *result)
 | ||||
|        listp = listp->next; | ||||
|        assert (listp != NULL); | ||||
|      } | ||||
| +  __rtld_lock_unlock_recursive (GL(dl_load_lock));
 | ||||
|   | ||||
|    /* The DTV version is up-to-date now.  */ | ||||
|    dtv[0].counter = maxgen; | ||||
| @@ -730,12 +731,29 @@ _dl_update_slotinfo (unsigned long int req_modid)
 | ||||
|   | ||||
|    if (dtv[0].counter < listp->slotinfo[idx].gen) | ||||
|      { | ||||
| -      /* The generation counter for the slot is higher than what the
 | ||||
| -	 current dtv implements.  We have to update the whole dtv but
 | ||||
| -	 only those entries with a generation counter <= the one for
 | ||||
| -	 the entry we need.  */
 | ||||
| +      /* CONCURRENCY NOTES:
 | ||||
| +
 | ||||
| +	 Here the dtv needs to be updated to new_gen generation count.
 | ||||
| +
 | ||||
| +	 This code may be called during TLS access when GL(dl_load_lock)
 | ||||
| +	 is not held.  In that case the user code has to synchronize with
 | ||||
| +	 dlopen and dlclose calls of relevant modules.  A module m is
 | ||||
| +	 relevant if the generation of m <= new_gen and dlclose of m is
 | ||||
| +	 synchronized: a memory access here happens after the dlopen and
 | ||||
| +	 before the dlclose of relevant modules.  The dtv entries for
 | ||||
| +	 relevant modules need to be updated, other entries can be
 | ||||
| +	 arbitrary.
 | ||||
| +
 | ||||
| +	 This e.g. means that the first part of the slotinfo list can be
 | ||||
| +	 accessed race free, but the tail may be concurrently extended.
 | ||||
| +	 Similarly relevant slotinfo entries can be read race free, but
 | ||||
| +	 other entries are racy.  However updating a non-relevant dtv
 | ||||
| +	 entry does not affect correctness.  For a relevant module m,
 | ||||
| +	 max_modid >= modid of m.  */
 | ||||
|        size_t new_gen = listp->slotinfo[idx].gen; | ||||
|        size_t total = 0; | ||||
| +      size_t max_modid  = atomic_load_relaxed (&GL(dl_tls_max_dtv_idx));
 | ||||
| +      assert (max_modid >= req_modid);
 | ||||
|   | ||||
|        /* We have to look through the entire dtv slotinfo list.  */ | ||||
|        listp =  GL(dl_tls_dtv_slotinfo_list); | ||||
| @@ -745,12 +763,14 @@ _dl_update_slotinfo (unsigned long int req_modid)
 | ||||
|  	    { | ||||
|  	      size_t modid = total + cnt; | ||||
|   | ||||
| +	      /* Later entries are not relevant.  */
 | ||||
| +	      if (modid > max_modid)
 | ||||
| +		break;
 | ||||
| +
 | ||||
|  	      size_t gen = listp->slotinfo[cnt].gen; | ||||
|   | ||||
|  	      if (gen > new_gen) | ||||
| -		/* This is a slot for a generation younger than the
 | ||||
| -		   one we are handling now.  It might be incompletely
 | ||||
| -		   set up so ignore it.  */
 | ||||
| +		/* Not relevant.  */
 | ||||
|  		continue; | ||||
|   | ||||
|  	      /* If the entry is older than the current dtv layout we | ||||
| @@ -767,7 +787,7 @@ _dl_update_slotinfo (unsigned long int req_modid)
 | ||||
|  		    continue; | ||||
|   | ||||
|  		  /* Resize the dtv.  */ | ||||
| -		  dtv = _dl_resize_dtv (dtv);
 | ||||
| +		  dtv = _dl_resize_dtv (dtv, max_modid);
 | ||||
|   | ||||
|  		  assert (modid <= dtv[-1].counter); | ||||
|   | ||||
| @@ -789,8 +809,17 @@ _dl_update_slotinfo (unsigned long int req_modid)
 | ||||
|  	    } | ||||
|   | ||||
|  	  total += listp->len; | ||||
| +	  if (total > max_modid)
 | ||||
| +	    break;
 | ||||
| +
 | ||||
| +	  /* Synchronize with _dl_add_to_slotinfo.  Ideally this would
 | ||||
| +	     be consume MO since we only need to order the accesses to
 | ||||
| +	     the next node after the read of the address and on most
 | ||||
| +	     hardware (other than alpha) a normal load would do that
 | ||||
| +	     because of the address dependency.  */
 | ||||
| +	  listp = atomic_load_acquire (&listp->next);
 | ||||
|  	} | ||||
| -      while ((listp = listp->next) != NULL);
 | ||||
| +      while (listp != NULL);
 | ||||
|   | ||||
|        /* This will be the new maximum generation counter.  */ | ||||
|        dtv[0].counter = new_gen; | ||||
| @@ -982,7 +1011,7 @@ _dl_add_to_slotinfo (struct link_map *l, bool do_add)
 | ||||
|  	 the first slot.  */ | ||||
|        assert (idx == 0); | ||||
|   | ||||
| -      listp = prevp->next = (struct dtv_slotinfo_list *)
 | ||||
| +      listp = (struct dtv_slotinfo_list *)
 | ||||
|  	malloc (sizeof (struct dtv_slotinfo_list) | ||||
|  		+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); | ||||
|        if (listp == NULL) | ||||
| @@ -996,6 +1025,8 @@ cannot create TLS data structures"));
 | ||||
|        listp->next = NULL; | ||||
|        memset (listp->slotinfo, '\0', | ||||
|  	      TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); | ||||
| +      /* Synchronize with _dl_update_slotinfo.  */
 | ||||
| +      atomic_store_release (&prevp->next, listp);
 | ||||
|      } | ||||
|   | ||||
|    /* Add the information into the slotinfo data structure.  */ | ||||
							
								
								
									
										193
									
								
								SOURCES/glibc-rh1991001-13.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								SOURCES/glibc-rh1991001-13.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,193 @@ | ||||
| commit f4f8f4d4e0f92488431b268c8cd9555730b9afe9 | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Wed Dec 30 19:19:37 2020 +0000 | ||||
| 
 | ||||
|     elf: Use relaxed atomics for racy accesses [BZ #19329] | ||||
|      | ||||
|     This is a follow up patch to the fix for bug 19329.  This adds relaxed | ||||
|     MO atomics to accesses that were previously data races but are now | ||||
|     race conditions, and where relaxed MO is sufficient. | ||||
|      | ||||
|     The race conditions all follow the pattern that the write is behind the | ||||
|     dlopen lock, but a read can happen concurrently (e.g. during tls access) | ||||
|     without holding the lock.  For slotinfo entries the read value only | ||||
|     matters if it reads from a synchronized write in dlopen or dlclose, | ||||
|     otherwise the related dtv entry is not valid to access so it is fine | ||||
|     to leave it in an inconsistent state.  The same applies for | ||||
|     GL(dl_tls_max_dtv_idx) and GL(dl_tls_generation), but there the | ||||
|     algorithm relies on the fact that the read of the last synchronized | ||||
|     write is an increasing value. | ||||
|      | ||||
|     Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org> | ||||
| 
 | ||||
| diff --git a/elf/dl-close.c b/elf/dl-close.c
 | ||||
| index 1ece0ae1dd062d1e..7d2dc2272cd643f5 100644
 | ||||
| --- a/elf/dl-close.c
 | ||||
| +++ b/elf/dl-close.c
 | ||||
| @@ -79,9 +79,10 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
 | ||||
|  	{ | ||||
|  	  assert (old_map->l_tls_modid == idx); | ||||
|   | ||||
| -	  /* Mark the entry as unused. */
 | ||||
| -	  listp->slotinfo[idx - disp].gen = GL(dl_tls_generation) + 1;
 | ||||
| -	  listp->slotinfo[idx - disp].map = NULL;
 | ||||
| +	  /* Mark the entry as unused.  These can be read concurrently.  */
 | ||||
| +	  atomic_store_relaxed (&listp->slotinfo[idx - disp].gen,
 | ||||
| +				GL(dl_tls_generation) + 1);
 | ||||
| +	  atomic_store_relaxed (&listp->slotinfo[idx - disp].map, NULL);
 | ||||
|  	} | ||||
|   | ||||
|        /* If this is not the last currently used entry no need to look | ||||
| @@ -96,8 +97,8 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
 | ||||
|   | ||||
|        if (listp->slotinfo[idx - disp].map != NULL) | ||||
|  	{ | ||||
| -	  /* Found a new last used index.  */
 | ||||
| -	  GL(dl_tls_max_dtv_idx) = idx;
 | ||||
| +	  /* Found a new last used index.  This can be read concurrently.  */
 | ||||
| +	  atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), idx);
 | ||||
|  	  return true; | ||||
|  	} | ||||
|      } | ||||
| @@ -571,7 +572,9 @@ _dl_close_worker (struct link_map *map, bool force)
 | ||||
|  					GL(dl_tls_dtv_slotinfo_list), 0, | ||||
|  					imap->l_init_called)) | ||||
|  		/* All dynamically loaded modules with TLS are unloaded.  */ | ||||
| -		GL(dl_tls_max_dtv_idx) = GL(dl_tls_static_nelem);
 | ||||
| +		/* Can be read concurrently.  */
 | ||||
| +		atomic_store_relaxed (&GL(dl_tls_max_dtv_idx),
 | ||||
| +				      GL(dl_tls_static_nelem));
 | ||||
|   | ||||
|  	      if (imap->l_tls_offset != NO_TLS_OFFSET | ||||
|  		  && imap->l_tls_offset != FORCED_DYNAMIC_TLS_OFFSET) | ||||
| @@ -769,8 +772,11 @@ _dl_close_worker (struct link_map *map, bool force)
 | ||||
|    /* If we removed any object which uses TLS bump the generation counter.  */ | ||||
|    if (any_tls) | ||||
|      { | ||||
| -      if (__glibc_unlikely (++GL(dl_tls_generation) == 0))
 | ||||
| +      size_t newgen = GL(dl_tls_generation) + 1;
 | ||||
| +      if (__glibc_unlikely (newgen == 0))
 | ||||
|  	_dl_fatal_printf ("TLS generation counter wrapped!  Please report as described in "REPORT_BUGS_TO".\n"); | ||||
| +      /* Can be read concurrently.  */
 | ||||
| +      atomic_store_relaxed (&GL(dl_tls_generation), newgen);
 | ||||
|   | ||||
|        if (tls_free_end == GL(dl_tls_static_used)) | ||||
|  	GL(dl_tls_static_used) = tls_free_start; | ||||
| diff --git a/elf/dl-open.c b/elf/dl-open.c
 | ||||
| index b052bb0bc2cd17aa..a67fb3aee40860e1 100644
 | ||||
| --- a/elf/dl-open.c
 | ||||
| +++ b/elf/dl-open.c
 | ||||
| @@ -395,9 +395,12 @@ update_tls_slotinfo (struct link_map *new)
 | ||||
|  	} | ||||
|      } | ||||
|   | ||||
| -  if (__builtin_expect (++GL(dl_tls_generation) == 0, 0))
 | ||||
| +  size_t newgen = GL(dl_tls_generation) + 1;
 | ||||
| +  if (__glibc_unlikely (newgen == 0))
 | ||||
|      _dl_fatal_printf (N_("\ | ||||
|  TLS generation counter wrapped!  Please report this.")); | ||||
| +  /* Can be read concurrently.  */
 | ||||
| +  atomic_store_relaxed (&GL(dl_tls_generation), newgen);
 | ||||
|   | ||||
|    /* We need a second pass for static tls data, because | ||||
|       _dl_update_slotinfo must not be run while calls to | ||||
| diff --git a/elf/dl-tls.c b/elf/dl-tls.c
 | ||||
| index da83cd6ae2ee6504..801eafad3961573c 100644
 | ||||
| --- a/elf/dl-tls.c
 | ||||
| +++ b/elf/dl-tls.c
 | ||||
| @@ -175,7 +175,9 @@ _dl_next_tls_modid (void)
 | ||||
|        /* No gaps, allocate a new entry.  */ | ||||
|      nogaps: | ||||
|   | ||||
| -      result = ++GL(dl_tls_max_dtv_idx);
 | ||||
| +      result = GL(dl_tls_max_dtv_idx) + 1;
 | ||||
| +      /* Can be read concurrently.  */
 | ||||
| +      atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), result);
 | ||||
|      } | ||||
|   | ||||
|    return result; | ||||
| @@ -359,10 +361,12 @@ allocate_dtv (void *result)
 | ||||
|    dtv_t *dtv; | ||||
|    size_t dtv_length; | ||||
|   | ||||
| +  /* Relaxed MO, because the dtv size is later rechecked, not relied on.  */
 | ||||
| +  size_t max_modid = atomic_load_relaxed (&GL(dl_tls_max_dtv_idx));
 | ||||
|    /* We allocate a few more elements in the dtv than are needed for the | ||||
|       initial set of modules.  This should avoid in most cases expansions | ||||
|       of the dtv.  */ | ||||
| -  dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
 | ||||
| +  dtv_length = max_modid + DTV_SURPLUS;
 | ||||
|    dtv = calloc (dtv_length + 2, sizeof (dtv_t)); | ||||
|    if (dtv != NULL) | ||||
|      { | ||||
| @@ -767,7 +771,7 @@ _dl_update_slotinfo (unsigned long int req_modid)
 | ||||
|  	      if (modid > max_modid) | ||||
|  		break; | ||||
|   | ||||
| -	      size_t gen = listp->slotinfo[cnt].gen;
 | ||||
| +	      size_t gen = atomic_load_relaxed (&listp->slotinfo[cnt].gen);
 | ||||
|   | ||||
|  	      if (gen > new_gen) | ||||
|  		/* Not relevant.  */ | ||||
| @@ -779,7 +783,8 @@ _dl_update_slotinfo (unsigned long int req_modid)
 | ||||
|  		continue; | ||||
|   | ||||
|  	      /* If there is no map this means the entry is empty.  */ | ||||
| -	      struct link_map *map = listp->slotinfo[cnt].map;
 | ||||
| +	      struct link_map *map
 | ||||
| +		= atomic_load_relaxed (&listp->slotinfo[cnt].map);
 | ||||
|  	      /* Check whether the current dtv array is large enough.  */ | ||||
|  	      if (dtv[-1].counter < modid) | ||||
|  		{ | ||||
| @@ -923,7 +928,12 @@ __tls_get_addr (GET_ADDR_ARGS)
 | ||||
|  { | ||||
|    dtv_t *dtv = THREAD_DTV (); | ||||
|   | ||||
| -  if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation)))
 | ||||
| +  /* Update is needed if dtv[0].counter < the generation of the accessed
 | ||||
| +     module.  The global generation counter is used here as it is easier
 | ||||
| +     to check.  Synchronization for the relaxed MO access is guaranteed
 | ||||
| +     by user code, see CONCURRENCY NOTES in _dl_update_slotinfo.  */
 | ||||
| +  size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
 | ||||
| +  if (__glibc_unlikely (dtv[0].counter != gen))
 | ||||
|      return update_get_addr (GET_ADDR_PARAM); | ||||
|   | ||||
|    void *p = dtv[GET_ADDR_MODULE].pointer.val; | ||||
| @@ -946,7 +956,10 @@ _dl_tls_get_addr_soft (struct link_map *l)
 | ||||
|      return NULL; | ||||
|   | ||||
|    dtv_t *dtv = THREAD_DTV (); | ||||
| -  if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation)))
 | ||||
| +  /* This may be called without holding the GL(dl_load_lock).  Reading
 | ||||
| +     arbitrary gen value is fine since this is best effort code.  */
 | ||||
| +  size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
 | ||||
| +  if (__glibc_unlikely (dtv[0].counter != gen))
 | ||||
|      { | ||||
|        /* This thread's DTV is not completely current, | ||||
|  	 but it might already cover this module.  */ | ||||
| @@ -1032,7 +1045,9 @@ cannot create TLS data structures"));
 | ||||
|    /* Add the information into the slotinfo data structure.  */ | ||||
|    if (do_add) | ||||
|      { | ||||
| -      listp->slotinfo[idx].map = l;
 | ||||
| -      listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
 | ||||
| +      /* Can be read concurrently.  See _dl_update_slotinfo.  */
 | ||||
| +      atomic_store_relaxed (&listp->slotinfo[idx].map, l);
 | ||||
| +      atomic_store_relaxed (&listp->slotinfo[idx].gen,
 | ||||
| +			    GL(dl_tls_generation) + 1);
 | ||||
|      } | ||||
|  } | ||||
| diff --git a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c
 | ||||
| index 533ee2b3a6e85ad8..bc543dcc264ea361 100644
 | ||||
| --- a/sysdeps/x86_64/dl-tls.c
 | ||||
| +++ b/sysdeps/x86_64/dl-tls.c
 | ||||
| @@ -40,7 +40,8 @@ __tls_get_addr_slow (GET_ADDR_ARGS)
 | ||||
|  { | ||||
|    dtv_t *dtv = THREAD_DTV (); | ||||
|   | ||||
| -  if (__glibc_unlikely (dtv[0].counter != GL(dl_tls_generation)))
 | ||||
| +  size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
 | ||||
| +  if (__glibc_unlikely (dtv[0].counter != gen))
 | ||||
|      return update_get_addr (GET_ADDR_PARAM); | ||||
|   | ||||
|    return tls_get_addr_tail (GET_ADDR_PARAM, dtv, NULL); | ||||
							
								
								
									
										133
									
								
								SOURCES/glibc-rh1991001-14.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								SOURCES/glibc-rh1991001-14.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,133 @@ | ||||
| commit 9d0e30329c23b5ad736fda3f174208c25970dbce | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Tue Dec 13 12:28:41 2016 +0000 | ||||
| 
 | ||||
|     elf: Add test case for [BZ #19329] | ||||
|      | ||||
|     Test concurrent dlopen and pthread_create when the loaded modules have | ||||
|     TLS.  This triggers dl-tls assertion failures more reliably than the | ||||
|     nptl/tst-stack4 test. | ||||
|      | ||||
|     The dlopened module has 100 DT_NEEDED dependencies with TLS, they were | ||||
|     reused from an existing TLS test. The number of created threads during | ||||
|     dlopen depends on filesystem speed and hardware, but at most 3 threads | ||||
|     are alive at a time to limit resource usage. | ||||
|      | ||||
|     Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org> | ||||
| 
 | ||||
| Conflicts: | ||||
| 	elf/Makefile | ||||
| 	  (usual testing differences) | ||||
| 
 | ||||
| diff --git a/elf/Makefile b/elf/Makefile
 | ||||
| index 0995d810b57d0dda..be40e3761cf91c4a 100644
 | ||||
| --- a/elf/Makefile
 | ||||
| +++ b/elf/Makefile
 | ||||
| @@ -210,7 +210,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
 | ||||
|  	 tst-tls-ie tst-tls-ie-dlmopen \ | ||||
|  	 argv0test \ | ||||
|  	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \ | ||||
| -	 tst-tls20
 | ||||
| +	 tst-tls20 tst-tls21
 | ||||
|  #	 reldep9 | ||||
|  tests-internal += loadtest unload unload2 circleload1 \ | ||||
|  	 neededtest neededtest2 neededtest3 neededtest4 \ | ||||
| @@ -333,7 +333,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 | ||||
|  		libmarkermod2-1 libmarkermod2-2 \ | ||||
|  		libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \ | ||||
|  		libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \ | ||||
| -		tst-tls20mod-bad
 | ||||
| +		tst-tls20mod-bad tst-tls21mod \
 | ||||
|   | ||||
|  # Most modules build with _ISOMAC defined, but those filtered out | ||||
|  # depend on internal headers. | ||||
| @@ -1836,3 +1836,8 @@ tst-tls20mod-bad.so-no-z-defs = yes
 | ||||
|  $(objpfx)tst-tls20: $(libdl) $(shared-thread-library) | ||||
|  $(objpfx)tst-tls20.out: $(objpfx)tst-tls20mod-bad.so \ | ||||
|  			$(tst-tls-many-dynamic-modules:%=$(objpfx)%.so) | ||||
| +
 | ||||
| +# Reuses tst-tls-many-dynamic-modules
 | ||||
| +$(objpfx)tst-tls21: $(libdl) $(shared-thread-library)
 | ||||
| +$(objpfx)tst-tls21.out: $(objpfx)tst-tls21mod.so
 | ||||
| +$(objpfx)tst-tls21mod.so: $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so)
 | ||||
| diff --git a/elf/tst-tls21.c b/elf/tst-tls21.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..560bf5813a746417
 | ||||
| --- /dev/null
 | ||||
| +++ b/elf/tst-tls21.c
 | ||||
| @@ -0,0 +1,68 @@
 | ||||
| +/* Test concurrent dlopen and pthread_create: BZ 19329.
 | ||||
| +   Copyright (C) 2021 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
 | ||||
| +   <http://www.gnu.org/licenses/>.  */
 | ||||
| +
 | ||||
| +#include <dlfcn.h>
 | ||||
| +#include <pthread.h>
 | ||||
| +#include <stdio.h>
 | ||||
| +#include <stdatomic.h>
 | ||||
| +#include <support/xdlfcn.h>
 | ||||
| +#include <support/xthread.h>
 | ||||
| +
 | ||||
| +#define THREADS 10000
 | ||||
| +
 | ||||
| +static atomic_int done;
 | ||||
| +
 | ||||
| +static void *
 | ||||
| +start (void *a)
 | ||||
| +{
 | ||||
| +  /* Load a module with many dependencies that each have TLS.  */
 | ||||
| +  xdlopen ("tst-tls21mod.so", RTLD_LAZY);
 | ||||
| +  atomic_store_explicit (&done, 1, memory_order_release);
 | ||||
| +  return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void *
 | ||||
| +nop (void *a)
 | ||||
| +{
 | ||||
| +  return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +static int
 | ||||
| +do_test (void)
 | ||||
| +{
 | ||||
| +  pthread_t t1, t2;
 | ||||
| +  int i;
 | ||||
| +
 | ||||
| +  /* Load a module with lots of dependencies and TLS.  */
 | ||||
| +  t1 = xpthread_create (0, start, 0);
 | ||||
| +
 | ||||
| +  /* Concurrently create lots of threads until dlopen is observably done.  */
 | ||||
| +  for (i = 0; i < THREADS; i++)
 | ||||
| +    {
 | ||||
| +      if (atomic_load_explicit (&done, memory_order_acquire) != 0)
 | ||||
| +	break;
 | ||||
| +      t2 = xpthread_create (0, nop, 0);
 | ||||
| +      xpthread_join (t2);
 | ||||
| +    }
 | ||||
| +
 | ||||
| +  xpthread_join (t1);
 | ||||
| +  printf ("threads created during dlopen: %d\n", i);
 | ||||
| +  return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +#include <support/test-driver.c>
 | ||||
| diff --git a/elf/tst-tls21mod.c b/elf/tst-tls21mod.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..206ece4fb34622a9
 | ||||
| --- /dev/null
 | ||||
| +++ b/elf/tst-tls21mod.c
 | ||||
| @@ -0,0 +1 @@
 | ||||
| +int __thread x;
 | ||||
							
								
								
									
										81
									
								
								SOURCES/glibc-rh1991001-15.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								SOURCES/glibc-rh1991001-15.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,81 @@ | ||||
| commit 572bd547d57a39b6cf0ea072545dc4048921f4c3 | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Thu Dec 31 13:59:38 2020 +0000 | ||||
| 
 | ||||
|     elf: Fix DTV gap reuse logic [BZ #27135] | ||||
|      | ||||
|     For some reason only dlopen failure caused dtv gaps to be reused. | ||||
|      | ||||
|     It is possible that the intent was to never reuse modids for a | ||||
|     different module, but after dlopen failure all gaps are reused | ||||
|     not just the ones caused by the unfinished dlopened. | ||||
|      | ||||
|     So the code has to handle reused modids already which seems to | ||||
|     work, however the data races at thread creation and tls access | ||||
|     (see bug 19329 and bug 27111) may be more severe if slots are | ||||
|     reused so this is scheduled after those fixes. I think fixing | ||||
|     the races are not simpler if reuse is disallowed and reuse has | ||||
|     other benefits, so set GL(dl_tls_dtv_gaps) whenever entries are | ||||
|     removed from the middle of the slotinfo list. The value does | ||||
|     not have to be correct: incorrect true value causes the next | ||||
|     modid query to do a slotinfo walk, incorrect false will leave | ||||
|     gaps and new entries are added at the end. | ||||
|      | ||||
|     Fixes bug 27135. | ||||
|      | ||||
|     Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org> | ||||
| 
 | ||||
| diff --git a/elf/dl-close.c b/elf/dl-close.c
 | ||||
| index 7d2dc2272cd643f5..41cb6c58491c364b 100644
 | ||||
| --- a/elf/dl-close.c
 | ||||
| +++ b/elf/dl-close.c
 | ||||
| @@ -88,7 +88,11 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
 | ||||
|        /* If this is not the last currently used entry no need to look | ||||
|  	 further.  */ | ||||
|        if (idx != GL(dl_tls_max_dtv_idx)) | ||||
| -	return true;
 | ||||
| +	{
 | ||||
| +	  /* There is an unused dtv entry in the middle.  */
 | ||||
| +	  GL(dl_tls_dtv_gaps) = true;
 | ||||
| +	  return true;
 | ||||
| +	}
 | ||||
|      } | ||||
|   | ||||
|    while (idx - disp > (disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0)) | ||||
| diff --git a/elf/dl-open.c b/elf/dl-open.c
 | ||||
| index a67fb3aee40860e1..54727402750f4c0c 100644
 | ||||
| --- a/elf/dl-open.c
 | ||||
| +++ b/elf/dl-open.c
 | ||||
| @@ -896,16 +896,6 @@ no more namespaces available for dlmopen()"));
 | ||||
|  	 state if relocation failed, for example.  */ | ||||
|        if (args.map) | ||||
|  	{ | ||||
| -	  /* Maybe some of the modules which were loaded use TLS.
 | ||||
| -	     Since it will be removed in the following _dl_close call
 | ||||
| -	     we have to mark the dtv array as having gaps to fill the
 | ||||
| -	     holes.  This is a pessimistic assumption which won't hurt
 | ||||
| -	     if not true.  There is no need to do this when we are
 | ||||
| -	     loading the auditing DSOs since TLS has not yet been set
 | ||||
| -	     up.  */
 | ||||
| -	  if ((mode & __RTLD_AUDIT) == 0)
 | ||||
| -	    GL(dl_tls_dtv_gaps) = true;
 | ||||
| -
 | ||||
|  	  _dl_close_worker (args.map, true); | ||||
|   | ||||
|  	  /* All l_nodelete_pending objects should have been deleted | ||||
| diff --git a/elf/dl-tls.c b/elf/dl-tls.c
 | ||||
| index 801eafad3961573c..bacb4101e2e2c4e5 100644
 | ||||
| --- a/elf/dl-tls.c
 | ||||
| +++ b/elf/dl-tls.c
 | ||||
| @@ -187,10 +187,7 @@ _dl_next_tls_modid (void)
 | ||||
|  size_t | ||||
|  _dl_count_modids (void) | ||||
|  { | ||||
| -  /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where
 | ||||
| -     we fail to load a module and unload it leaving a gap.  If we don't
 | ||||
| -     have gaps then the number of modids is the current maximum so
 | ||||
| -     return that.  */
 | ||||
| +  /* The count is the max unless dlclose or failed dlopen created gaps.  */
 | ||||
|    if (__glibc_likely (!GL(dl_tls_dtv_gaps))) | ||||
|      return GL(dl_tls_max_dtv_idx); | ||||
|   | ||||
							
								
								
									
										71
									
								
								SOURCES/glibc-rh1991001-16.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								SOURCES/glibc-rh1991001-16.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,71 @@ | ||||
| commit 40ebfd016ad284872f434bdd76dbe9c708db4d6b | ||||
| Author: Florian Weimer <fweimer@redhat.com> | ||||
| Date:   Fri Jun 25 08:09:08 2021 +0200 | ||||
| 
 | ||||
|     elf: Disable most of TLS modid gaps processing [BZ #27135] | ||||
|      | ||||
|     Revert "elf: Fix DTV gap reuse logic [BZ #27135]" | ||||
|      | ||||
|     This reverts commit 572bd547d57a39b6cf0ea072545dc4048921f4c3. | ||||
|      | ||||
|     It turns out that the _dl_next_tls_modid in _dl_map_object_from_fd keeps | ||||
|     returning the same modid over and over again if there is a gap and | ||||
|     more than TLS-using module is loaded in one dlopen call.  This corrupts | ||||
|     TLS data structures.  The bug is still present after a revert, but | ||||
|     empirically it is much more difficult to trigger (because it involves a | ||||
|     dlopen failure). | ||||
| 
 | ||||
| diff --git a/elf/dl-close.c b/elf/dl-close.c
 | ||||
| index 41cb6c58491c364b..7d2dc2272cd643f5 100644
 | ||||
| --- a/elf/dl-close.c
 | ||||
| +++ b/elf/dl-close.c
 | ||||
| @@ -88,11 +88,7 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
 | ||||
|        /* If this is not the last currently used entry no need to look | ||||
|  	 further.  */ | ||||
|        if (idx != GL(dl_tls_max_dtv_idx)) | ||||
| -	{
 | ||||
| -	  /* There is an unused dtv entry in the middle.  */
 | ||||
| -	  GL(dl_tls_dtv_gaps) = true;
 | ||||
| -	  return true;
 | ||||
| -	}
 | ||||
| +	return true;
 | ||||
|      } | ||||
|   | ||||
|    while (idx - disp > (disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0)) | ||||
| diff --git a/elf/dl-open.c b/elf/dl-open.c
 | ||||
| index 54727402750f4c0c..a67fb3aee40860e1 100644
 | ||||
| --- a/elf/dl-open.c
 | ||||
| +++ b/elf/dl-open.c
 | ||||
| @@ -896,6 +896,16 @@ no more namespaces available for dlmopen()"));
 | ||||
|  	 state if relocation failed, for example.  */ | ||||
|        if (args.map) | ||||
|  	{ | ||||
| +	  /* Maybe some of the modules which were loaded use TLS.
 | ||||
| +	     Since it will be removed in the following _dl_close call
 | ||||
| +	     we have to mark the dtv array as having gaps to fill the
 | ||||
| +	     holes.  This is a pessimistic assumption which won't hurt
 | ||||
| +	     if not true.  There is no need to do this when we are
 | ||||
| +	     loading the auditing DSOs since TLS has not yet been set
 | ||||
| +	     up.  */
 | ||||
| +	  if ((mode & __RTLD_AUDIT) == 0)
 | ||||
| +	    GL(dl_tls_dtv_gaps) = true;
 | ||||
| +
 | ||||
|  	  _dl_close_worker (args.map, true); | ||||
|   | ||||
|  	  /* All l_nodelete_pending objects should have been deleted | ||||
| diff --git a/elf/dl-tls.c b/elf/dl-tls.c
 | ||||
| index bacb4101e2e2c4e5..801eafad3961573c 100644
 | ||||
| --- a/elf/dl-tls.c
 | ||||
| +++ b/elf/dl-tls.c
 | ||||
| @@ -187,7 +187,10 @@ _dl_next_tls_modid (void)
 | ||||
|  size_t | ||||
|  _dl_count_modids (void) | ||||
|  { | ||||
| -  /* The count is the max unless dlclose or failed dlopen created gaps.  */
 | ||||
| +  /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where
 | ||||
| +     we fail to load a module and unload it leaving a gap.  If we don't
 | ||||
| +     have gaps then the number of modids is the current maximum so
 | ||||
| +     return that.  */
 | ||||
|    if (__glibc_likely (!GL(dl_tls_dtv_gaps))) | ||||
|      return GL(dl_tls_max_dtv_idx); | ||||
|   | ||||
							
								
								
									
										585
									
								
								SOURCES/glibc-rh1991001-17.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										585
									
								
								SOURCES/glibc-rh1991001-17.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,585 @@ | ||||
| commit ba33937be210da5d07f7f01709323743f66011ce | ||||
| Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> | ||||
| Date:   Fri Jun 25 10:54:12 2021 -0300 | ||||
| 
 | ||||
|     elf: Fix DTV gap reuse logic (BZ #27135) | ||||
|      | ||||
|     This is updated version of the 572bd547d57a (reverted by 40ebfd016ad2) | ||||
|     that fixes the _dl_next_tls_modid issues. | ||||
|      | ||||
|     This issue with 572bd547d57a patch is the DTV entry will be only | ||||
|     update on dl_open_worker() with the update_tls_slotinfo() call after | ||||
|     all dependencies are being processed by _dl_map_object_deps().  However | ||||
|     _dl_map_object_deps() itself might call _dl_next_tls_modid(), and since | ||||
|     the _dl_tls_dtv_slotinfo_list::map is not yet set the entry will be | ||||
|     wrongly reused. | ||||
|      | ||||
|     This patch fixes by renaming the _dl_next_tls_modid() function to | ||||
|     _dl_assign_tls_modid() and by passing the link_map so it can set | ||||
|     the slotinfo value so a subsequente _dl_next_tls_modid() call will | ||||
|     see the entry as allocated. | ||||
|      | ||||
|     The intermediary value is cleared up on remove_slotinfo() for the case | ||||
|     a library fails to load with RTLD_NOW. | ||||
|      | ||||
|     This patch fixes BZ #27135. | ||||
|      | ||||
|     Checked on x86_64-linux-gnu. | ||||
|      | ||||
|     Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| 
 | ||||
| Conflicts: | ||||
| 	elf/Makefile | ||||
| 	  (testing differences; libdl removal upstream) | ||||
| 
 | ||||
| diff --git a/elf/Makefile b/elf/Makefile
 | ||||
| index be40e3761cf91c4a..3e71939d3234c4c3 100644
 | ||||
| --- a/elf/Makefile
 | ||||
| +++ b/elf/Makefile
 | ||||
| @@ -242,6 +242,13 @@ one-hundred = $(foreach x,0 1 2 3 4 5 6 7 8 9, \
 | ||||
|    0$x 1$x 2$x 3$x 4$x 5$x 6$x 7$x 8$x 9$x) | ||||
|  tst-tls-many-dynamic-modules := \ | ||||
|    $(foreach n,$(one-hundred),tst-tls-manydynamic$(n)mod) | ||||
| +tst-tls-many-dynamic-modules-dep-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 \
 | ||||
| +					    14 15 16 17 18 19
 | ||||
| +tst-tls-many-dynamic-modules-dep = \
 | ||||
| +  $(foreach n,$(tst-tls-many-dynamic-modules-dep-suffixes),tst-tls-manydynamic$(n)mod-dep)
 | ||||
| +tst-tls-many-dynamic-modules-dep-bad-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
 | ||||
| +tst-tls-many-dynamic-modules-dep-bad = \
 | ||||
| +  $(foreach n,$(tst-tls-many-dynamic-modules-dep-bad-suffixes),tst-tls-manydynamic$(n)mod-dep-bad)
 | ||||
|  extra-test-objs += $(tlsmod17a-modules:=.os) $(tlsmod18a-modules:=.os) \ | ||||
|  		   tst-tlsalign-vars.o | ||||
|  test-extras += tst-tlsmod17a tst-tlsmod18a tst-tlsalign-vars | ||||
| @@ -314,6 +321,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 | ||||
|  		tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \ | ||||
|  		tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \ | ||||
|  		tst-latepthreadmod $(tst-tls-many-dynamic-modules) \ | ||||
| +		$(tst-tls-many-dynamic-modules-dep) \
 | ||||
| +		$(tst-tls-many-dynamic-modules-dep-bad) \
 | ||||
|  		tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \ | ||||
|  		tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \ | ||||
|  		tst-absolute-zero-lib tst-big-note-lib \ | ||||
| @@ -1832,10 +1841,63 @@ $(objpfx)tst-rtld-help.out: $(objpfx)ld.so
 | ||||
|  	$(evaluate-test) | ||||
|   | ||||
|  # Reuses tst-tls-many-dynamic-modules | ||||
| +$(patsubst %,$(objpfx)%.os,$(tst-tls-many-dynamic-modules-dep)): \
 | ||||
| +  $(objpfx)tst-tls-manydynamic%mod-dep.os : tst-tls-manydynamicmod.c
 | ||||
| +	$(compile-command.c) \
 | ||||
| +	  -DNAME=tls_global_$* -DSETTER=set_value_$* -DGETTER=get_value_$*
 | ||||
| +$(patsubst %,$(objpfx)%.os,$(tst-tls-many-dynamic-modules-dep-bad)): \
 | ||||
| +  $(objpfx)tst-tls-manydynamic%mod-dep-bad.os : tst-tls-manydynamicmod.c
 | ||||
| +	$(compile-command.c) \
 | ||||
| +	  -DNAME=tls_global_$* -DSETTER=set_value_$* -DGETTER=get_value_$*
 | ||||
|  tst-tls20mod-bad.so-no-z-defs = yes | ||||
| +# Single dependency.
 | ||||
| +$(objpfx)tst-tls-manydynamic0mod-dep.so: $(objpfx)tst-tls-manydynamic1mod-dep.so
 | ||||
| +# Double dependencies.
 | ||||
| +$(objpfx)tst-tls-manydynamic2mod-dep.so: $(objpfx)tst-tls-manydynamic3mod-dep.so \
 | ||||
| +					 $(objpfx)tst-tls-manydynamic4mod-dep.so
 | ||||
| +# Double dependencies with each dependency depent of another module.
 | ||||
| +$(objpfx)tst-tls-manydynamic5mod-dep.so: $(objpfx)tst-tls-manydynamic6mod-dep.so \
 | ||||
| +					 $(objpfx)tst-tls-manydynamic7mod-dep.so
 | ||||
| +$(objpfx)tst-tls-manydynamic6mod-dep.so: $(objpfx)tst-tls-manydynamic8mod-dep.so
 | ||||
| +$(objpfx)tst-tls-manydynamic7mod-dep.so: $(objpfx)tst-tls-manydynamic8mod-dep.so
 | ||||
| +# Long chain with one double dependency in the middle
 | ||||
| +$(objpfx)tst-tls-manydynamic9mod-dep.so: $(objpfx)tst-tls-manydynamic10mod-dep.so \
 | ||||
| +					 $(objpfx)tst-tls-manydynamic11mod-dep.so
 | ||||
| +$(objpfx)tst-tls-manydynamic10mod-dep.so: $(objpfx)tst-tls-manydynamic12mod-dep.so
 | ||||
| +$(objpfx)tst-tls-manydynamic12mod-dep.so: $(objpfx)tst-tls-manydynamic13mod-dep.so
 | ||||
| +# Long chain with two double depedencies in the middle
 | ||||
| +$(objpfx)tst-tls-manydynamic14mod-dep.so: $(objpfx)tst-tls-manydynamic15mod-dep.so
 | ||||
| +$(objpfx)tst-tls-manydynamic15mod-dep.so: $(objpfx)tst-tls-manydynamic16mod-dep.so \
 | ||||
| +					  $(objpfx)tst-tls-manydynamic17mod-dep.so
 | ||||
| +$(objpfx)tst-tls-manydynamic16mod-dep.so: $(objpfx)tst-tls-manydynamic18mod-dep.so \
 | ||||
| +					  $(objpfx)tst-tls-manydynamic19mod-dep.so
 | ||||
| +# Same but with an invalid module.
 | ||||
| +# Single dependency.
 | ||||
| +$(objpfx)tst-tls-manydynamic0mod-dep-bad.so: $(objpfx)tst-tls20mod-bad.so
 | ||||
| +# Double dependencies.
 | ||||
| +$(objpfx)tst-tls-manydynamic1mod-dep-bad.so: $(objpfx)tst-tls-manydynamic2mod-dep-bad.so \
 | ||||
| +					     $(objpfx)tst-tls20mod-bad.so
 | ||||
| +# Double dependencies with each dependency depent of another module.
 | ||||
| +$(objpfx)tst-tls-manydynamic3mod-dep-bad.so: $(objpfx)tst-tls-manydynamic4mod-dep-bad.so \
 | ||||
| +					     $(objpfx)tst-tls-manydynamic5mod-dep-bad.so
 | ||||
| +$(objpfx)tst-tls-manydynamic4mod-dep-bad.so: $(objpfx)tst-tls20mod-bad.so
 | ||||
| +$(objpfx)tst-tls-manydynamic5mod-dep-bad.so: $(objpfx)tst-tls20mod-bad.so
 | ||||
| +# Long chain with one double dependency in the middle
 | ||||
| +$(objpfx)tst-tls-manydynamic6mod-dep-bad.so: $(objpfx)tst-tls-manydynamic7mod-dep-bad.so \
 | ||||
| +					     $(objpfx)tst-tls-manydynamic8mod-dep-bad.so
 | ||||
| +$(objpfx)tst-tls-manydynamic7mod-dep-bad.so: $(objpfx)tst-tls-manydynamic9mod-dep-bad.so
 | ||||
| +$(objpfx)tst-tls-manydynamic9mod-dep-bad.so: $(objpfx)tst-tls20mod-bad.so
 | ||||
| +# Long chain with two double depedencies in the middle
 | ||||
| +$(objpfx)tst-tls-manydynamic10mod-dep-bad.so: $(objpfx)tst-tls-manydynamic11mod-dep-bad.so
 | ||||
| +$(objpfx)tst-tls-manydynamic11mod-dep-bad.so: $(objpfx)tst-tls-manydynamic12mod-dep-bad.so \
 | ||||
| +					      $(objpfx)tst-tls-manydynamic13mod-dep-bad.so
 | ||||
| +$(objpfx)tst-tls-manydynamic12mod-dep-bad.so: $(objpfx)tst-tls-manydynamic14mod-dep-bad.so \
 | ||||
| +					      $(objpfx)tst-tls20mod-bad.so
 | ||||
|  $(objpfx)tst-tls20: $(libdl) $(shared-thread-library) | ||||
|  $(objpfx)tst-tls20.out: $(objpfx)tst-tls20mod-bad.so \ | ||||
| -			$(tst-tls-many-dynamic-modules:%=$(objpfx)%.so)
 | ||||
| +			$(tst-tls-many-dynamic-modules:%=$(objpfx)%.so) \
 | ||||
| +			$(tst-tls-many-dynamic-modules-dep:%=$(objpfx)%.so) \
 | ||||
| +			$(tst-tls-many-dynamic-modules-dep-bad:%=$(objpfx)%.so) \
 | ||||
|   | ||||
|  # Reuses tst-tls-many-dynamic-modules | ||||
|  $(objpfx)tst-tls21: $(libdl) $(shared-thread-library) | ||||
| diff --git a/elf/dl-close.c b/elf/dl-close.c
 | ||||
| index 7d2dc2272cd643f5..18227fe992029364 100644
 | ||||
| --- a/elf/dl-close.c
 | ||||
| +++ b/elf/dl-close.c
 | ||||
| @@ -77,8 +77,6 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
 | ||||
|  	 object that wasn't fully set up.  */ | ||||
|        if (__glibc_likely (old_map != NULL)) | ||||
|  	{ | ||||
| -	  assert (old_map->l_tls_modid == idx);
 | ||||
| -
 | ||||
|  	  /* Mark the entry as unused.  These can be read concurrently.  */ | ||||
|  	  atomic_store_relaxed (&listp->slotinfo[idx - disp].gen, | ||||
|  				GL(dl_tls_generation) + 1); | ||||
| @@ -88,7 +86,11 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
 | ||||
|        /* If this is not the last currently used entry no need to look | ||||
|  	 further.  */ | ||||
|        if (idx != GL(dl_tls_max_dtv_idx)) | ||||
| -	return true;
 | ||||
| +	{
 | ||||
| +	  /* There is an unused dtv entry in the middle.  */
 | ||||
| +	  GL(dl_tls_dtv_gaps) = true;
 | ||||
| +	  return true;
 | ||||
| +	}
 | ||||
|      } | ||||
|   | ||||
|    while (idx - disp > (disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0)) | ||||
| diff --git a/elf/dl-load.c b/elf/dl-load.c
 | ||||
| index 80fc38041a936c3c..cdb5d4b5b67f1ca1 100644
 | ||||
| --- a/elf/dl-load.c
 | ||||
| +++ b/elf/dl-load.c
 | ||||
| @@ -1419,7 +1419,7 @@ cannot enable executable stack as shared object requires");
 | ||||
|  	     not set up TLS data structures, so don't use them now.  */ | ||||
|  	  || __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL))) | ||||
|      /* Assign the next available module ID.  */ | ||||
| -    l->l_tls_modid = _dl_next_tls_modid ();
 | ||||
| +    _dl_assign_tls_modid (l);
 | ||||
|   | ||||
|  #ifdef DL_AFTER_LOAD | ||||
|    DL_AFTER_LOAD (l); | ||||
| diff --git a/elf/dl-open.c b/elf/dl-open.c
 | ||||
| index a67fb3aee40860e1..54727402750f4c0c 100644
 | ||||
| --- a/elf/dl-open.c
 | ||||
| +++ b/elf/dl-open.c
 | ||||
| @@ -896,16 +896,6 @@ no more namespaces available for dlmopen()"));
 | ||||
|  	 state if relocation failed, for example.  */ | ||||
|        if (args.map) | ||||
|  	{ | ||||
| -	  /* Maybe some of the modules which were loaded use TLS.
 | ||||
| -	     Since it will be removed in the following _dl_close call
 | ||||
| -	     we have to mark the dtv array as having gaps to fill the
 | ||||
| -	     holes.  This is a pessimistic assumption which won't hurt
 | ||||
| -	     if not true.  There is no need to do this when we are
 | ||||
| -	     loading the auditing DSOs since TLS has not yet been set
 | ||||
| -	     up.  */
 | ||||
| -	  if ((mode & __RTLD_AUDIT) == 0)
 | ||||
| -	    GL(dl_tls_dtv_gaps) = true;
 | ||||
| -
 | ||||
|  	  _dl_close_worker (args.map, true); | ||||
|   | ||||
|  	  /* All l_nodelete_pending objects should have been deleted | ||||
| diff --git a/elf/dl-tls.c b/elf/dl-tls.c
 | ||||
| index 801eafad3961573c..8c0f9e972d7a0eac 100644
 | ||||
| --- a/elf/dl-tls.c
 | ||||
| +++ b/elf/dl-tls.c
 | ||||
| @@ -122,8 +122,8 @@ oom (void)
 | ||||
|  } | ||||
|   | ||||
|   | ||||
| -size_t
 | ||||
| -_dl_next_tls_modid (void)
 | ||||
| +void
 | ||||
| +_dl_assign_tls_modid (struct link_map *l)
 | ||||
|  { | ||||
|    size_t result; | ||||
|   | ||||
| @@ -153,7 +153,11 @@ _dl_next_tls_modid (void)
 | ||||
|  	      } | ||||
|   | ||||
|  	    if (result - disp < runp->len) | ||||
| -	      break;
 | ||||
| +	      {
 | ||||
| +		/* Mark the entry as used, so any dependency see it.  */
 | ||||
| +		atomic_store_relaxed (&runp->slotinfo[result - disp].map, l);
 | ||||
| +		break;
 | ||||
| +	      }
 | ||||
|   | ||||
|  	    disp += runp->len; | ||||
|  	  } | ||||
| @@ -180,17 +184,14 @@ _dl_next_tls_modid (void)
 | ||||
|        atomic_store_relaxed (&GL(dl_tls_max_dtv_idx), result); | ||||
|      } | ||||
|   | ||||
| -  return result;
 | ||||
| +  l->l_tls_modid = result;
 | ||||
|  } | ||||
|   | ||||
|   | ||||
|  size_t | ||||
|  _dl_count_modids (void) | ||||
|  { | ||||
| -  /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where
 | ||||
| -     we fail to load a module and unload it leaving a gap.  If we don't
 | ||||
| -     have gaps then the number of modids is the current maximum so
 | ||||
| -     return that.  */
 | ||||
| +  /* The count is the max unless dlclose or failed dlopen created gaps.  */
 | ||||
|    if (__glibc_likely (!GL(dl_tls_dtv_gaps))) | ||||
|      return GL(dl_tls_max_dtv_idx); | ||||
|   | ||||
| diff --git a/elf/rtld.c b/elf/rtld.c
 | ||||
| index 992f825ba00762a7..118c454a2329573f 100644
 | ||||
| --- a/elf/rtld.c
 | ||||
| +++ b/elf/rtld.c
 | ||||
| @@ -1693,7 +1693,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
 | ||||
|    /* Add the dynamic linker to the TLS list if it also uses TLS.  */ | ||||
|    if (GL(dl_rtld_map).l_tls_blocksize != 0) | ||||
|      /* Assign a module ID.  Do this before loading any audit modules.  */ | ||||
| -    GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
 | ||||
| +    _dl_assign_tls_modid (&GL(dl_rtld_map));
 | ||||
|   | ||||
|    audit_list_add_dynamic_tag (&state.audit_list, main_map, DT_AUDIT); | ||||
|    audit_list_add_dynamic_tag (&state.audit_list, main_map, DT_DEPAUDIT); | ||||
| diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
 | ||||
| index 9977ec803208b9c8..d8d04fe574597f35 100644
 | ||||
| --- a/elf/tst-tls20.c
 | ||||
| +++ b/elf/tst-tls20.c
 | ||||
| @@ -16,12 +16,14 @@
 | ||||
|     License along with the GNU C Library; if not, see | ||||
|     <http://www.gnu.org/licenses/>.  */ | ||||
|   | ||||
| +#include <array_length.h>
 | ||||
|  #include <dlfcn.h> | ||||
|  #include <pthread.h> | ||||
|  #include <stdio.h> | ||||
|  #include <stdlib.h> | ||||
|  #include <support/check.h> | ||||
|  #include <support/support.h> | ||||
| +#include <support/test-driver.h>
 | ||||
|  #include <support/xdlfcn.h> | ||||
|  #include <support/xthread.h> | ||||
|   | ||||
| @@ -59,28 +61,75 @@ access (int i)
 | ||||
|    char *buf = xasprintf ("tls_global_%02d", i); | ||||
|    dlerror (); | ||||
|    int *p = dlsym (mod[i], buf); | ||||
| -  printf ("mod[%d]: &tls = %p\n", i, p);
 | ||||
| +  if (test_verbose)
 | ||||
| +    printf ("mod[%d]: &tls = %p\n", i, p);
 | ||||
|    if (p == NULL) | ||||
|      FAIL_EXIT1 ("dlsym failed: %s\n", dlerror ()); | ||||
| +  TEST_COMPARE (*p, 0);
 | ||||
|    ++*p; | ||||
|    free (buf); | ||||
|  } | ||||
|   | ||||
| +static void
 | ||||
| +access_mod (const char *modname, void *mod, int i)
 | ||||
| +{
 | ||||
| +  char *modsym = xasprintf ("tls_global_%d", i);
 | ||||
| +  dlerror ();
 | ||||
| +  int *p = dlsym (mod, modsym);
 | ||||
| +  if (test_verbose)
 | ||||
| +    printf ("%s: &tls = %p\n", modname, p);
 | ||||
| +  if (p == NULL)
 | ||||
| +    FAIL_EXIT1 ("dlsym failed: %s\n", dlerror ());
 | ||||
| +  TEST_COMPARE (*p, 0);
 | ||||
| +  ++*p;
 | ||||
| +  free (modsym);
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void
 | ||||
| +access_dep (int i)
 | ||||
| +{
 | ||||
| +  char *modname = xasprintf ("tst-tls-manydynamic%dmod-dep.so", i);
 | ||||
| +  void *moddep = xdlopen (modname, RTLD_LAZY);
 | ||||
| +  access_mod (modname, moddep, i);
 | ||||
| +  free (modname);
 | ||||
| +  xdlclose (moddep);
 | ||||
| +}
 | ||||
| +
 | ||||
| +struct start_args
 | ||||
| +{
 | ||||
| +  const char *modname;
 | ||||
| +  void *mod;
 | ||||
| +  int modi;
 | ||||
| +  int ndeps;
 | ||||
| +  const int *deps;
 | ||||
| +};
 | ||||
| +
 | ||||
|  static void * | ||||
|  start (void *a) | ||||
|  { | ||||
| +  struct start_args *args = a;
 | ||||
| +
 | ||||
|    for (int i = 0; i < NMOD; i++) | ||||
|      if (mod[i] != NULL) | ||||
|        access (i); | ||||
| +
 | ||||
| +  if (args != NULL)
 | ||||
| +    {
 | ||||
| +      access_mod (args->modname, args->mod, args->modi);
 | ||||
| +      for (int n = 0; n < args->ndeps; n++)
 | ||||
| +	access_dep (args->deps[n]);
 | ||||
| +    }
 | ||||
| +
 | ||||
|    return 0; | ||||
|  } | ||||
|   | ||||
| -static int
 | ||||
| -do_test (void)
 | ||||
| +/* This test gaps with shared libraries with dynamic TLS that has no
 | ||||
| +   dependencies.  The DTV gap is set with by trying to load an invalid
 | ||||
| +   module, the entry should be used on the dlopen.  */
 | ||||
| +static void
 | ||||
| +do_test_no_depedency (void)
 | ||||
|  { | ||||
| -  int i;
 | ||||
| -
 | ||||
| -  for (i = 0; i < NMOD; i++)
 | ||||
| +  for (int i = 0; i < NMOD; i++)
 | ||||
|      { | ||||
|        load_mod (i); | ||||
|        /* Bump the generation of mod[0] without using new dtv slot.  */ | ||||
| @@ -91,8 +140,220 @@ do_test (void)
 | ||||
|        pthread_t t = xpthread_create (0, start, 0); | ||||
|        xpthread_join (t); | ||||
|      } | ||||
| -  for (i = 0; i < NMOD; i++)
 | ||||
| +  for (int i = 0; i < NMOD; i++)
 | ||||
|      unload_mod (i); | ||||
| +}
 | ||||
| +
 | ||||
| +/* The following test check DTV gaps handling with shared libraries that has
 | ||||
| +   dependencies.  It defines 5 different sets:
 | ||||
| +
 | ||||
| +   1. Single dependency:
 | ||||
| +      mod0 -> mod1
 | ||||
| +   2. Double dependency:
 | ||||
| +      mod2 -> [mod3,mod4]
 | ||||
| +   3. Double dependency with each dependency depent of another module:
 | ||||
| +      mod5 -> [mod6,mod7] -> mod8
 | ||||
| +   4. Long chain with one double dependency in the middle:
 | ||||
| +      mod9 -> [mod10, mod11] -> mod12 -> mod13
 | ||||
| +   5. Long chain with two double depedencies in the middle:
 | ||||
| +      mod14 -> mod15 -> [mod16, mod17]
 | ||||
| +      mod15 -> [mod18, mod19]
 | ||||
| +
 | ||||
| +   This does not cover all the possible gaps and configuration, but it
 | ||||
| +   should check if different dynamic shared sets are placed correctly in
 | ||||
| +   different gaps configurations.  */
 | ||||
| +
 | ||||
| +static int
 | ||||
| +nmodules (uint32_t v)
 | ||||
| +{
 | ||||
| +  unsigned int r = 0;
 | ||||
| +  while (v >>= 1)
 | ||||
| +    r++;
 | ||||
| +  return r + 1;
 | ||||
| +}
 | ||||
| +
 | ||||
| +static inline bool
 | ||||
| +is_mod_set (uint32_t g, uint32_t n)
 | ||||
| +{
 | ||||
| +  return (1U << (n - 1)) & g;
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void
 | ||||
| +print_gap (uint32_t g)
 | ||||
| +{
 | ||||
| +  if (!test_verbose)
 | ||||
| +    return;
 | ||||
| +  printf ("gap: ");
 | ||||
| +  int nmods = nmodules (g);
 | ||||
| +  for (int n = 1; n <= nmods; n++)
 | ||||
| +    printf ("%c", ((1 << (n - 1)) & g) == 0 ? 'G' : 'M');
 | ||||
| +  printf ("\n");
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void
 | ||||
| +do_test_dependency (void)
 | ||||
| +{
 | ||||
| +  /* Maps the module and its dependencies, use thread to access the TLS on
 | ||||
| +     each loaded module.  */
 | ||||
| +  static const int tlsmanydeps0[] = { 1 };
 | ||||
| +  static const int tlsmanydeps1[] = { 3, 4 };
 | ||||
| +  static const int tlsmanydeps2[] = { 6, 7, 8 };
 | ||||
| +  static const int tlsmanydeps3[] = { 10, 11, 12 };
 | ||||
| +  static const int tlsmanydeps4[] = { 15, 16, 17, 18, 19 };
 | ||||
| +  static const struct tlsmanydeps_t
 | ||||
| +  {
 | ||||
| +    int modi;
 | ||||
| +    int ndeps;
 | ||||
| +    const int *deps;
 | ||||
| +  } tlsmanydeps[] =
 | ||||
| +  {
 | ||||
| +    {  0, array_length (tlsmanydeps0), tlsmanydeps0 },
 | ||||
| +    {  2, array_length (tlsmanydeps1), tlsmanydeps1 },
 | ||||
| +    {  5, array_length (tlsmanydeps2), tlsmanydeps2 },
 | ||||
| +    {  9, array_length (tlsmanydeps3), tlsmanydeps3 },
 | ||||
| +    { 14, array_length (tlsmanydeps4), tlsmanydeps4 },
 | ||||
| +  };
 | ||||
| +
 | ||||
| +  /* The gap configuration is defined as a bitmap: the bit set represents a
 | ||||
| +     loaded module prior the tests execution, while a bit unsed is a module
 | ||||
| +     unloaded.  Not all permtation will show gaps, but it is simpler than
 | ||||
| +     define each one independently.  */
 | ||||
| +  for (uint32_t g = 0; g < 64; g++)
 | ||||
| +    {
 | ||||
| +      print_gap (g);
 | ||||
| +      int nmods = nmodules (g);
 | ||||
| +
 | ||||
| +      int mods[nmods];
 | ||||
| +      /* We use '0' as indication for a gap, to avoid the dlclose on iteration
 | ||||
| +	 cleanup.  */
 | ||||
| +      for (int n = 1; n <= nmods; n++)
 | ||||
| +	{
 | ||||
| +	  load_mod (n);
 | ||||
| +	   mods[n] = n;
 | ||||
| +	}
 | ||||
| +      for (int n = 1; n <= nmods; n++)
 | ||||
| +	{
 | ||||
| +	  if (!is_mod_set (g, n))
 | ||||
| +	    {
 | ||||
| +	      unload_mod (n);
 | ||||
| +	      mods[n] = 0;
 | ||||
| +	    }
 | ||||
| +	}
 | ||||
| +
 | ||||
| +      for (int t = 0; t < array_length (tlsmanydeps); t++)
 | ||||
| +	{
 | ||||
| +	  char *moddepname = xasprintf ("tst-tls-manydynamic%dmod-dep.so",
 | ||||
| +					tlsmanydeps[t].modi);
 | ||||
| +	  void *moddep = xdlopen (moddepname, RTLD_LAZY);
 | ||||
| +
 | ||||
| +	  /* Access TLS in all loaded modules.  */
 | ||||
| +	  struct start_args args =
 | ||||
| +	    {
 | ||||
| +	      moddepname,
 | ||||
| +	      moddep,
 | ||||
| +	      tlsmanydeps[t].modi,
 | ||||
| +	      tlsmanydeps[t].ndeps,
 | ||||
| +	      tlsmanydeps[t].deps
 | ||||
| +	    };
 | ||||
| +	  pthread_t t = xpthread_create (0, start, &args);
 | ||||
| +	  xpthread_join (t);
 | ||||
| +
 | ||||
| +	  free (moddepname);
 | ||||
| +	  xdlclose (moddep);
 | ||||
| +	}
 | ||||
| +
 | ||||
| +      for (int n = 1; n <= nmods; n++)
 | ||||
| +	if (mods[n] != 0)
 | ||||
| +	  unload_mod (n);
 | ||||
| +    }
 | ||||
| +}
 | ||||
| +
 | ||||
| +/* The following test check DTV gaps handling with shared libraries that has
 | ||||
| +   invalid dependencies.  It defines 5 different sets:
 | ||||
| +
 | ||||
| +   1. Single dependency:
 | ||||
| +      mod0 -> invalid
 | ||||
| +   2. Double dependency:
 | ||||
| +      mod1 -> [mod2,invalid]
 | ||||
| +   3. Double dependency with each dependency depent of another module:
 | ||||
| +      mod3 -> [mod4,mod5] -> invalid
 | ||||
| +   4. Long chain with one double dependency in the middle:
 | ||||
| +      mod6 -> [mod7, mod8] -> mod12 -> invalid
 | ||||
| +   5. Long chain with two double depedencies in the middle:
 | ||||
| +      mod10 -> mod11 -> [mod12, mod13]
 | ||||
| +      mod12 -> [mod14, invalid]
 | ||||
| +
 | ||||
| +   This does not cover all the possible gaps and configuration, but it
 | ||||
| +   should check if different dynamic shared sets are placed correctly in
 | ||||
| +   different gaps configurations.  */
 | ||||
| +
 | ||||
| +static void
 | ||||
| +do_test_invalid_dependency (bool bind_now)
 | ||||
| +{
 | ||||
| +  static const int tlsmanydeps[] = { 0, 1, 3, 6, 10 };
 | ||||
| +
 | ||||
| +  /* The gap configuration is defined as a bitmap: the bit set represents a
 | ||||
| +     loaded module prior the tests execution, while a bit unsed is a module
 | ||||
| +     unloaded.  Not all permtation will show gaps, but it is simpler than
 | ||||
| +     define each one independently.  */
 | ||||
| +  for (uint32_t g = 0; g < 64; g++)
 | ||||
| +    {
 | ||||
| +      print_gap (g);
 | ||||
| +      int nmods = nmodules (g);
 | ||||
| +
 | ||||
| +      int mods[nmods];
 | ||||
| +      /* We use '0' as indication for a gap, to avoid the dlclose on iteration
 | ||||
| +	 cleanup.  */
 | ||||
| +      for (int n = 1; n <= nmods; n++)
 | ||||
| +	{
 | ||||
| +	  load_mod (n);
 | ||||
| +	   mods[n] = n;
 | ||||
| +	}
 | ||||
| +      for (int n = 1; n <= nmods; n++)
 | ||||
| +	{
 | ||||
| +	  if (!is_mod_set (g, n))
 | ||||
| +	    {
 | ||||
| +	      unload_mod (n);
 | ||||
| +	      mods[n] = 0;
 | ||||
| +	    }
 | ||||
| +	}
 | ||||
| +
 | ||||
| +      for (int t = 0; t < array_length (tlsmanydeps); t++)
 | ||||
| +	{
 | ||||
| +	  char *moddepname = xasprintf ("tst-tls-manydynamic%dmod-dep-bad.so",
 | ||||
| +					tlsmanydeps[t]);
 | ||||
| +	  void *moddep;
 | ||||
| +	  if (bind_now)
 | ||||
| +	    {
 | ||||
| +	      moddep = dlopen (moddepname, RTLD_NOW);
 | ||||
| +	      TEST_VERIFY (moddep == 0);
 | ||||
| +	    }
 | ||||
| +	  else
 | ||||
| +	    moddep = dlopen (moddepname, RTLD_LAZY);
 | ||||
| +
 | ||||
| +	  /* Access TLS in all loaded modules.  */
 | ||||
| +	  pthread_t t = xpthread_create (0, start, NULL);
 | ||||
| +	  xpthread_join (t);
 | ||||
| +
 | ||||
| +	  free (moddepname);
 | ||||
| +	  if (!bind_now)
 | ||||
| +	    xdlclose (moddep);
 | ||||
| +	}
 | ||||
| +
 | ||||
| +      for (int n = 1; n <= nmods; n++)
 | ||||
| +	if (mods[n] != 0)
 | ||||
| +	  unload_mod (n);
 | ||||
| +    }
 | ||||
| +}
 | ||||
| +
 | ||||
| +static int
 | ||||
| +do_test (void)
 | ||||
| +{
 | ||||
| +  do_test_no_depedency ();
 | ||||
| +  do_test_dependency ();
 | ||||
| +  do_test_invalid_dependency (true);
 | ||||
| +  do_test_invalid_dependency (false);
 | ||||
| +
 | ||||
|    return 0; | ||||
|  } | ||||
|   | ||||
| diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
 | ||||
| index 6cbbaa808a596f77..0138353ccb41c5f1 100644
 | ||||
| --- a/sysdeps/generic/ldsodefs.h
 | ||||
| +++ b/sysdeps/generic/ldsodefs.h
 | ||||
| @@ -1111,8 +1111,8 @@ extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
 | ||||
|  extern void _dl_sysdep_start_cleanup (void) attribute_hidden; | ||||
|   | ||||
|   | ||||
| -/* Determine next available module ID.  */
 | ||||
| -extern size_t _dl_next_tls_modid (void) attribute_hidden;
 | ||||
| +/* Determine next available module ID and set the L l_tls_modid.  */
 | ||||
| +extern void _dl_assign_tls_modid (struct link_map *l) attribute_hidden;
 | ||||
|   | ||||
|  /* Count the modules with TLS segments.  */ | ||||
|  extern size_t _dl_count_modids (void) attribute_hidden; | ||||
							
								
								
									
										42
									
								
								SOURCES/glibc-rh1991001-18.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								SOURCES/glibc-rh1991001-18.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| commit 881b68e45c3a518319dcf5a3c4a2b3ec59e1c1e5 | ||||
| Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> | ||||
| Date:   Fri Jul 16 08:32:05 2021 -0300 | ||||
| 
 | ||||
|     elf: Fix a wrong array access on tst-tls20 | ||||
|      | ||||
|     Check on x86_64-linux-gnu with --enable-stack-protector=all. | ||||
| 
 | ||||
| diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
 | ||||
| index d8d04fe574597f35..831c3336c914790d 100644
 | ||||
| --- a/elf/tst-tls20.c
 | ||||
| +++ b/elf/tst-tls20.c
 | ||||
| @@ -226,12 +226,12 @@ do_test_dependency (void)
 | ||||
|        int mods[nmods]; | ||||
|        /* We use '0' as indication for a gap, to avoid the dlclose on iteration | ||||
|  	 cleanup.  */ | ||||
| -      for (int n = 1; n <= nmods; n++)
 | ||||
| +      for (int n = 1; n < nmods; n++)
 | ||||
|  	{ | ||||
|  	  load_mod (n); | ||||
|  	   mods[n] = n; | ||||
|  	} | ||||
| -      for (int n = 1; n <= nmods; n++)
 | ||||
| +      for (int n = 1; n < nmods; n++)
 | ||||
|  	{ | ||||
|  	  if (!is_mod_set (g, n)) | ||||
|  	    { | ||||
| @@ -304,12 +304,12 @@ do_test_invalid_dependency (bool bind_now)
 | ||||
|        int mods[nmods]; | ||||
|        /* We use '0' as indication for a gap, to avoid the dlclose on iteration | ||||
|  	 cleanup.  */ | ||||
| -      for (int n = 1; n <= nmods; n++)
 | ||||
| +      for (int n = 1; n < nmods; n++)
 | ||||
|  	{ | ||||
|  	  load_mod (n); | ||||
|  	   mods[n] = n; | ||||
|  	} | ||||
| -      for (int n = 1; n <= nmods; n++)
 | ||||
| +      for (int n = 1; n < nmods; n++)
 | ||||
|  	{ | ||||
|  	  if (!is_mod_set (g, n)) | ||||
|  	    { | ||||
							
								
								
									
										468
									
								
								SOURCES/glibc-rh1991001-19.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										468
									
								
								SOURCES/glibc-rh1991001-19.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,468 @@ | ||||
| commit 83b5323261bb72313bffcf37476c1b8f0847c736 | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Wed Sep 15 15:16:19 2021 +0100 | ||||
| 
 | ||||
|     elf: Avoid deadlock between pthread_create and ctors [BZ #28357] | ||||
| 
 | ||||
|     The fix for bug 19329 caused a regression such that pthread_create can | ||||
|     deadlock when concurrent ctors from dlopen are waiting for it to finish. | ||||
|     Use a new GL(dl_load_tls_lock) in pthread_create that is not taken | ||||
|     around ctors in dlopen. | ||||
| 
 | ||||
|     The new lock is also used in __tls_get_addr instead of GL(dl_load_lock). | ||||
| 
 | ||||
|     The new lock is held in _dl_open_worker and _dl_close_worker around | ||||
|     most of the logic before/after the init/fini routines.  When init/fini | ||||
|     routines are running then TLS is in a consistent, usable state. | ||||
|     In _dl_open_worker the new lock requires catching and reraising dlopen | ||||
|     failures that happen in the critical section. | ||||
| 
 | ||||
|     The new lock is reinitialized in a fork child, to keep the existing | ||||
|     behaviour and it is kept recursive in case malloc interposition or TLS | ||||
|     access from signal handlers can retake it.  It is not obvious if this | ||||
|     is necessary or helps, but avoids changing the preexisting behaviour. | ||||
| 
 | ||||
|     The new lock may be more appropriate for dl_iterate_phdr too than | ||||
|     GL(dl_load_write_lock), since TLS state of an incompletely loaded | ||||
|     module may be accessed.  If the new lock can replace the old one, | ||||
|     that can be a separate change. | ||||
| 
 | ||||
|     Fixes bug 28357. | ||||
| 
 | ||||
|     Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org> | ||||
| 
 | ||||
| Conflicts: | ||||
| 	posix/fork.c | ||||
| 	  (reworked due to file rename upstream and libpthread integration) | ||||
| 	sysdeps/pthread/Makefile | ||||
| 	  (htl testing support was missing downstream, reconstituted here; | ||||
| 	  added $(libdl) required downstream) | ||||
| 
 | ||||
| diff --git a/elf/dl-close.c b/elf/dl-close.c
 | ||||
| index 18227fe992029364..7fe91bdd9aaf694e 100644
 | ||||
| --- a/elf/dl-close.c
 | ||||
| +++ b/elf/dl-close.c
 | ||||
| @@ -549,6 +549,9 @@ _dl_close_worker (struct link_map *map, bool force)
 | ||||
|    size_t tls_free_end; | ||||
|    tls_free_start = tls_free_end = NO_TLS_OFFSET; | ||||
|   | ||||
| +  /* Protects global and module specitic TLS state.  */
 | ||||
| +  __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
 | ||||
| +
 | ||||
|    /* We modify the list of loaded objects.  */ | ||||
|    __rtld_lock_lock_recursive (GL(dl_load_write_lock)); | ||||
|   | ||||
| @@ -784,6 +787,9 @@ _dl_close_worker (struct link_map *map, bool force)
 | ||||
|  	GL(dl_tls_static_used) = tls_free_start; | ||||
|      } | ||||
|   | ||||
| +  /* TLS is cleaned up for the unloaded modules.  */
 | ||||
| +  __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
 | ||||
| +
 | ||||
|  #ifdef SHARED | ||||
|    /* Auditing checkpoint: we have deleted all objects.  */ | ||||
|    if (__glibc_unlikely (do_audit)) | ||||
| diff --git a/elf/dl-open.c b/elf/dl-open.c
 | ||||
| index 54727402750f4c0c..736df62ce6e46d34 100644
 | ||||
| --- a/elf/dl-open.c
 | ||||
| +++ b/elf/dl-open.c
 | ||||
| @@ -65,6 +65,9 @@ struct dl_open_args
 | ||||
|       libc_map value in the namespace in case of a dlopen failure.  */ | ||||
|    bool libc_already_loaded; | ||||
|   | ||||
| +  /* Set to true if the end of dl_open_worker_begin was reached.  */
 | ||||
| +  bool worker_continue;
 | ||||
| +
 | ||||
|    /* Original parameters to the program and the current environment.  */ | ||||
|    int argc; | ||||
|    char **argv; | ||||
| @@ -481,7 +484,7 @@ call_dl_init (void *closure)
 | ||||
|  } | ||||
|   | ||||
|  static void | ||||
| -dl_open_worker (void *a)
 | ||||
| +dl_open_worker_begin (void *a)
 | ||||
|  { | ||||
|    struct dl_open_args *args = a; | ||||
|    const char *file = args->file; | ||||
| @@ -772,6 +775,36 @@ dl_open_worker (void *a)
 | ||||
|    DL_STATIC_INIT (new); | ||||
|  #endif | ||||
|   | ||||
| +  args->worker_continue = true;
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void
 | ||||
| +dl_open_worker (void *a)
 | ||||
| +{
 | ||||
| +  struct dl_open_args *args = a;
 | ||||
| +
 | ||||
| +  args->worker_continue = false;
 | ||||
| +
 | ||||
| +  {
 | ||||
| +    /* Protects global and module specific TLS state.  */
 | ||||
| +    __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
 | ||||
| +
 | ||||
| +    struct dl_exception ex;
 | ||||
| +    int err = _dl_catch_exception (&ex, dl_open_worker_begin, args);
 | ||||
| +
 | ||||
| +    __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
 | ||||
| +
 | ||||
| +    if (__glibc_unlikely (ex.errstring != NULL))
 | ||||
| +      /* Reraise the error.  */
 | ||||
| +      _dl_signal_exception (err, &ex, NULL);
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  if (!args->worker_continue)
 | ||||
| +    return;
 | ||||
| +
 | ||||
| +  int mode = args->mode;
 | ||||
| +  struct link_map *new = args->map;
 | ||||
| +
 | ||||
|    /* Run the initializer functions of new objects.  Temporarily | ||||
|       disable the exception handler, so that lazy binding failures are | ||||
|       fatal.  */ | ||||
| diff --git a/elf/dl-support.c b/elf/dl-support.c
 | ||||
| index 34be8e5babfb6af3..3e5531138eaa18f8 100644
 | ||||
| --- a/elf/dl-support.c
 | ||||
| +++ b/elf/dl-support.c
 | ||||
| @@ -212,6 +212,13 @@ __rtld_lock_define_initialized_recursive (, _dl_load_lock)
 | ||||
|     list of loaded objects while an object is added to or removed from | ||||
|     that list.  */ | ||||
|  __rtld_lock_define_initialized_recursive (, _dl_load_write_lock) | ||||
| +  /* This lock protects global and module specific TLS related data.
 | ||||
| +     E.g. it is held in dlopen and dlclose when GL(dl_tls_generation),
 | ||||
| +     GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are
 | ||||
| +     accessed and when TLS related relocations are processed for a
 | ||||
| +     module.  It was introduced to keep pthread_create accessing TLS
 | ||||
| +     state that is being set up.  */
 | ||||
| +__rtld_lock_define_initialized_recursive (, _dl_load_tls_lock)
 | ||||
|   | ||||
|   | ||||
|  #ifdef HAVE_AUX_VECTOR | ||||
| diff --git a/elf/dl-tls.c b/elf/dl-tls.c
 | ||||
| index 8c0f9e972d7a0eac..7865fc390c3f3f0a 100644
 | ||||
| --- a/elf/dl-tls.c
 | ||||
| +++ b/elf/dl-tls.c
 | ||||
| @@ -527,7 +527,7 @@ _dl_allocate_tls_init (void *result)
 | ||||
|    size_t maxgen = 0; | ||||
|   | ||||
|    /* Protects global dynamic TLS related state.  */ | ||||
| -  __rtld_lock_lock_recursive (GL(dl_load_lock));
 | ||||
| +  __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
 | ||||
|   | ||||
|    /* Check if the current dtv is big enough.   */ | ||||
|    if (dtv[-1].counter < GL(dl_tls_max_dtv_idx)) | ||||
| @@ -601,7 +601,7 @@ _dl_allocate_tls_init (void *result)
 | ||||
|        listp = listp->next; | ||||
|        assert (listp != NULL); | ||||
|      } | ||||
| -  __rtld_lock_unlock_recursive (GL(dl_load_lock));
 | ||||
| +  __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
 | ||||
|   | ||||
|    /* The DTV version is up-to-date now.  */ | ||||
|    dtv[0].counter = maxgen; | ||||
| @@ -740,7 +740,7 @@ _dl_update_slotinfo (unsigned long int req_modid)
 | ||||
|   | ||||
|  	 Here the dtv needs to be updated to new_gen generation count. | ||||
|   | ||||
| -	 This code may be called during TLS access when GL(dl_load_lock)
 | ||||
| +	 This code may be called during TLS access when GL(dl_load_tls_lock)
 | ||||
|  	 is not held.  In that case the user code has to synchronize with | ||||
|  	 dlopen and dlclose calls of relevant modules.  A module m is | ||||
|  	 relevant if the generation of m <= new_gen and dlclose of m is | ||||
| @@ -862,11 +862,11 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
 | ||||
|    if (__glibc_unlikely (the_map->l_tls_offset | ||||
|  			!= FORCED_DYNAMIC_TLS_OFFSET)) | ||||
|      { | ||||
| -      __rtld_lock_lock_recursive (GL(dl_load_lock));
 | ||||
| +      __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
 | ||||
|        if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET)) | ||||
|  	{ | ||||
|  	  the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET; | ||||
| -	  __rtld_lock_unlock_recursive (GL(dl_load_lock));
 | ||||
| +	  __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
 | ||||
|  	} | ||||
|        else if (__glibc_likely (the_map->l_tls_offset | ||||
|  			       != FORCED_DYNAMIC_TLS_OFFSET)) | ||||
| @@ -878,7 +878,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
 | ||||
|  #else | ||||
|  # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" | ||||
|  #endif | ||||
| -	  __rtld_lock_unlock_recursive (GL(dl_load_lock));
 | ||||
| +	  __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
 | ||||
|   | ||||
|  	  dtv[GET_ADDR_MODULE].pointer.to_free = NULL; | ||||
|  	  dtv[GET_ADDR_MODULE].pointer.val = p; | ||||
| @@ -886,7 +886,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
 | ||||
|  	  return (char *) p + GET_ADDR_OFFSET; | ||||
|  	} | ||||
|        else | ||||
| -	__rtld_lock_unlock_recursive (GL(dl_load_lock));
 | ||||
| +	__rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
 | ||||
|      } | ||||
|    struct dtv_pointer result = allocate_and_init (the_map); | ||||
|    dtv[GET_ADDR_MODULE].pointer = result; | ||||
| @@ -957,7 +957,7 @@ _dl_tls_get_addr_soft (struct link_map *l)
 | ||||
|      return NULL; | ||||
|   | ||||
|    dtv_t *dtv = THREAD_DTV (); | ||||
| -  /* This may be called without holding the GL(dl_load_lock).  Reading
 | ||||
| +  /* This may be called without holding the GL(dl_load_tls_lock).  Reading
 | ||||
|       arbitrary gen value is fine since this is best effort code.  */ | ||||
|    size_t gen = atomic_load_relaxed (&GL(dl_tls_generation)); | ||||
|    if (__glibc_unlikely (dtv[0].counter != gen)) | ||||
| diff --git a/elf/rtld.c b/elf/rtld.c
 | ||||
| index 118c454a2329573f..9e09896da078274d 100644
 | ||||
| --- a/elf/rtld.c
 | ||||
| +++ b/elf/rtld.c
 | ||||
| @@ -317,6 +317,7 @@ struct rtld_global _rtld_global =
 | ||||
|  #ifdef _LIBC_REENTRANT | ||||
|      ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER, | ||||
|      ._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER, | ||||
| +    ._dl_load_tls_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
 | ||||
|  #endif | ||||
|      ._dl_nns = 1, | ||||
|      ._dl_ns = | ||||
| diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
 | ||||
| index 0138353ccb41c5f1..7b0a667629ddc06a 100644
 | ||||
| --- a/sysdeps/generic/ldsodefs.h
 | ||||
| +++ b/sysdeps/generic/ldsodefs.h
 | ||||
| @@ -373,6 +373,13 @@ struct rtld_global
 | ||||
|       list of loaded objects while an object is added to or removed | ||||
|       from that list.  */ | ||||
|    __rtld_lock_define_recursive (EXTERN, _dl_load_write_lock) | ||||
| +  /* This lock protects global and module specific TLS related data.
 | ||||
| +     E.g. it is held in dlopen and dlclose when GL(dl_tls_generation),
 | ||||
| +     GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are
 | ||||
| +     accessed and when TLS related relocations are processed for a
 | ||||
| +     module.  It was introduced to keep pthread_create accessing TLS
 | ||||
| +     state that is being set up.  */
 | ||||
| +  __rtld_lock_define_recursive (EXTERN, _dl_load_tls_lock)
 | ||||
|   | ||||
|    /* Incremented whenever something may have been added to dl_loaded.  */ | ||||
|    EXTERN unsigned long long _dl_load_adds; | ||||
| @@ -1192,7 +1199,7 @@ extern int _dl_scope_free (void *) attribute_hidden;
 | ||||
|   | ||||
|  /* Add module to slot information data.  If DO_ADD is false, only the | ||||
|     required memory is allocated.  Must be called with GL | ||||
| -   (dl_load_lock) acquired.  If the function has already been called
 | ||||
| +   (dl_load_tls_lock) acquired.  If the function has already been called
 | ||||
|     for the link map L with !do_add, then this function will not raise | ||||
|     an exception, otherwise it is possible that it encounters a memory | ||||
|     allocation failure.  */ | ||||
| diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c
 | ||||
| index 37db30f3d1e846b6..b4d20fa652f4ba3b 100644
 | ||||
| --- a/sysdeps/nptl/fork.c
 | ||||
| +++ b/sysdeps/nptl/fork.c
 | ||||
| @@ -125,6 +125,9 @@ __libc_fork (void)
 | ||||
|        /* Reset the lock the dynamic loader uses to protect its data.  */ | ||||
|        __rtld_lock_initialize (GL(dl_load_lock)); | ||||
|   | ||||
| +      /* Reset the lock protecting dynamic TLS related data.  */
 | ||||
| +      __rtld_lock_initialize (GL(dl_load_tls_lock));
 | ||||
| +
 | ||||
|        /* Run the handlers registered for the child.  */ | ||||
|        __run_fork_handlers (atfork_run_child, multiple_threads); | ||||
|      } | ||||
| diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
 | ||||
| index ea4f8894891b2636..98a92f8d6bb119ba 100644
 | ||||
| --- a/sysdeps/pthread/Makefile
 | ||||
| +++ b/sysdeps/pthread/Makefile
 | ||||
| @@ -25,3 +25,24 @@ $(objpfx)tst-timer: $(objpfx)librt.a $(static-thread-library)
 | ||||
|  endif | ||||
|   | ||||
|  endif | ||||
| +
 | ||||
| +ifneq (,$(filter $(subdir),htl nptl))
 | ||||
| +ifeq ($(build-shared),yes)
 | ||||
| +tests += tst-create1
 | ||||
| +endif
 | ||||
| +
 | ||||
| +tst-create1mod.so-no-z-defs = yes
 | ||||
| +
 | ||||
| +ifeq ($(build-shared),yes)
 | ||||
| +# Build all the modules even when not actually running test programs.
 | ||||
| +tests: $(test-modules)
 | ||||
| +endif
 | ||||
| +
 | ||||
| +modules-names += tst-create1mod
 | ||||
| +test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
 | ||||
| +
 | ||||
| +LDFLAGS-tst-create1 = -Wl,-export-dynamic
 | ||||
| +$(objpfx)tst-create1: $(libdl) $(shared-thread-library)
 | ||||
| +$(objpfx)tst-create1.out: $(objpfx)tst-create1mod.so
 | ||||
| +
 | ||||
| +endif
 | ||||
| diff --git a/sysdeps/pthread/tst-create1.c b/sysdeps/pthread/tst-create1.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..932586c30990d1d4
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/pthread/tst-create1.c
 | ||||
| @@ -0,0 +1,119 @@
 | ||||
| +/* Verify that pthread_create does not deadlock when ctors take locks.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <stdio.h>
 | ||||
| +#include <support/xdlfcn.h>
 | ||||
| +#include <support/xthread.h>
 | ||||
| +
 | ||||
| +/*
 | ||||
| +Check if ctor and pthread_create deadlocks in
 | ||||
| +
 | ||||
| +thread 1: dlopen -> ctor -> lock(user_lock)
 | ||||
| +thread 2: lock(user_lock) -> pthread_create
 | ||||
| +
 | ||||
| +or in
 | ||||
| +
 | ||||
| +thread 1: dlclose -> dtor -> lock(user_lock)
 | ||||
| +thread 2: lock(user_lock) -> pthread_create
 | ||||
| +*/
 | ||||
| +
 | ||||
| +static pthread_barrier_t bar_ctor;
 | ||||
| +static pthread_barrier_t bar_dtor;
 | ||||
| +static pthread_mutex_t user_lock = PTHREAD_MUTEX_INITIALIZER;
 | ||||
| +
 | ||||
| +void
 | ||||
| +ctor (void)
 | ||||
| +{
 | ||||
| +  xpthread_barrier_wait (&bar_ctor);
 | ||||
| +  dprintf (1, "thread 1: in ctor: started.\n");
 | ||||
| +  xpthread_mutex_lock (&user_lock);
 | ||||
| +  dprintf (1, "thread 1: in ctor: locked user_lock.\n");
 | ||||
| +  xpthread_mutex_unlock (&user_lock);
 | ||||
| +  dprintf (1, "thread 1: in ctor: unlocked user_lock.\n");
 | ||||
| +  dprintf (1, "thread 1: in ctor: done.\n");
 | ||||
| +}
 | ||||
| +
 | ||||
| +void
 | ||||
| +dtor (void)
 | ||||
| +{
 | ||||
| +  xpthread_barrier_wait (&bar_dtor);
 | ||||
| +  dprintf (1, "thread 1: in dtor: started.\n");
 | ||||
| +  xpthread_mutex_lock (&user_lock);
 | ||||
| +  dprintf (1, "thread 1: in dtor: locked user_lock.\n");
 | ||||
| +  xpthread_mutex_unlock (&user_lock);
 | ||||
| +  dprintf (1, "thread 1: in dtor: unlocked user_lock.\n");
 | ||||
| +  dprintf (1, "thread 1: in dtor: done.\n");
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void *
 | ||||
| +thread3 (void *a)
 | ||||
| +{
 | ||||
| +  dprintf (1, "thread 3: started.\n");
 | ||||
| +  dprintf (1, "thread 3: done.\n");
 | ||||
| +  return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void *
 | ||||
| +thread2 (void *a)
 | ||||
| +{
 | ||||
| +  pthread_t t3;
 | ||||
| +  dprintf (1, "thread 2: started.\n");
 | ||||
| +
 | ||||
| +  xpthread_mutex_lock (&user_lock);
 | ||||
| +  dprintf (1, "thread 2: locked user_lock.\n");
 | ||||
| +  xpthread_barrier_wait (&bar_ctor);
 | ||||
| +  t3 = xpthread_create (0, thread3, 0);
 | ||||
| +  xpthread_mutex_unlock (&user_lock);
 | ||||
| +  dprintf (1, "thread 2: unlocked user_lock.\n");
 | ||||
| +  xpthread_join (t3);
 | ||||
| +
 | ||||
| +  xpthread_mutex_lock (&user_lock);
 | ||||
| +  dprintf (1, "thread 2: locked user_lock.\n");
 | ||||
| +  xpthread_barrier_wait (&bar_dtor);
 | ||||
| +  t3 = xpthread_create (0, thread3, 0);
 | ||||
| +  xpthread_mutex_unlock (&user_lock);
 | ||||
| +  dprintf (1, "thread 2: unlocked user_lock.\n");
 | ||||
| +  xpthread_join (t3);
 | ||||
| +
 | ||||
| +  dprintf (1, "thread 2: done.\n");
 | ||||
| +  return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void
 | ||||
| +thread1 (void)
 | ||||
| +{
 | ||||
| +  dprintf (1, "thread 1: started.\n");
 | ||||
| +  xpthread_barrier_init (&bar_ctor, NULL, 2);
 | ||||
| +  xpthread_barrier_init (&bar_dtor, NULL, 2);
 | ||||
| +  pthread_t t2 = xpthread_create (0, thread2, 0);
 | ||||
| +  void *p = xdlopen ("tst-create1mod.so", RTLD_NOW | RTLD_GLOBAL);
 | ||||
| +  dprintf (1, "thread 1: dlopen done.\n");
 | ||||
| +  xdlclose (p);
 | ||||
| +  dprintf (1, "thread 1: dlclose done.\n");
 | ||||
| +  xpthread_join (t2);
 | ||||
| +  dprintf (1, "thread 1: done.\n");
 | ||||
| +}
 | ||||
| +
 | ||||
| +static int
 | ||||
| +do_test (void)
 | ||||
| +{
 | ||||
| +  thread1 ();
 | ||||
| +  return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +#include <support/test-driver.c>
 | ||||
| diff --git a/sysdeps/pthread/tst-create1mod.c b/sysdeps/pthread/tst-create1mod.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..62c9006961683177
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/pthread/tst-create1mod.c
 | ||||
| @@ -0,0 +1,41 @@
 | ||||
| +/* Verify that pthread_create does not deadlock when ctors take locks.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <stdio.h>
 | ||||
| +
 | ||||
| +/* Require TLS setup for the module.  */
 | ||||
| +__thread int tlsvar;
 | ||||
| +
 | ||||
| +void ctor (void);
 | ||||
| +void dtor (void);
 | ||||
| +
 | ||||
| +static void __attribute__ ((constructor))
 | ||||
| +do_init (void)
 | ||||
| +{
 | ||||
| +  dprintf (1, "constructor started: %d.\n", tlsvar++);
 | ||||
| +  ctor ();
 | ||||
| +  dprintf (1, "constructor done: %d.\n", tlsvar++);
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void __attribute__ ((destructor))
 | ||||
| +do_end (void)
 | ||||
| +{
 | ||||
| +  dprintf (1, "destructor started: %d.\n", tlsvar++);
 | ||||
| +  dtor ();
 | ||||
| +  dprintf (1, "destructor done: %d.\n", tlsvar++);
 | ||||
| +}
 | ||||
							
								
								
									
										28
									
								
								SOURCES/glibc-rh1991001-2.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								SOURCES/glibc-rh1991001-2.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| commit d2b997c7172e9a00895a9deb379f8782fbd2e36f | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Wed Dec 30 23:40:14 2020 +0000 | ||||
| 
 | ||||
|     elf: Fix a DTV setup issue [BZ #27136] | ||||
|      | ||||
|     The max modid is a valid index in the dtv, it should not be skipped. | ||||
|      | ||||
|     The bug is observable if the last module has modid == 64 and its | ||||
|     generation is same or less than the max generation of the previous | ||||
|     modules.  Then dtv[0].counter implies dtv[64] is initialized but | ||||
|     it isn't. Fixes bug 27136. | ||||
|      | ||||
|     Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org> | ||||
| 
 | ||||
| diff --git a/elf/dl-tls.c b/elf/dl-tls.c
 | ||||
| index cccf74b33481b866..0b96b1dceed99d58 100644
 | ||||
| --- a/elf/dl-tls.c
 | ||||
| +++ b/elf/dl-tls.c
 | ||||
| @@ -590,7 +590,7 @@ _dl_allocate_tls_init (void *result)
 | ||||
|  	} | ||||
|   | ||||
|        total += cnt; | ||||
| -      if (total >= GL(dl_tls_max_dtv_idx))
 | ||||
| +      if (total > GL(dl_tls_max_dtv_idx))
 | ||||
|  	break; | ||||
|   | ||||
|        listp = listp->next; | ||||
							
								
								
									
										20
									
								
								SOURCES/glibc-rh1991001-20.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								SOURCES/glibc-rh1991001-20.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| commit 3c7c5117826816021f9d3f352f49e0dd0236cbad | ||||
| Author: Florian Weimer <fweimer@redhat.com> | ||||
| Date:   Tue Nov 30 14:35:54 2021 +0100 | ||||
| 
 | ||||
|     elf: Include <stdint.h> in tst-tls20.c | ||||
|      | ||||
|     The test uses standard integer types. | ||||
| 
 | ||||
| diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
 | ||||
| index 831c3336c914790d..18067e6b0a6093f9 100644
 | ||||
| --- a/elf/tst-tls20.c
 | ||||
| +++ b/elf/tst-tls20.c
 | ||||
| @@ -19,6 +19,7 @@
 | ||||
|  #include <array_length.h> | ||||
|  #include <dlfcn.h> | ||||
|  #include <pthread.h> | ||||
| +#include <stdint.h>
 | ||||
|  #include <stdio.h> | ||||
|  #include <stdlib.h> | ||||
|  #include <support/check.h> | ||||
							
								
								
									
										20
									
								
								SOURCES/glibc-rh1991001-21.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								SOURCES/glibc-rh1991001-21.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| commit df4cb2280e32187380520f71bd27ab32252cbc85 | ||||
| Author: Florian Weimer <fweimer@redhat.com> | ||||
| Date:   Tue Nov 30 15:39:17 2021 +0100 | ||||
| 
 | ||||
|     elf: Include <stdbool.h> in tst-tls20.c | ||||
|      | ||||
|     The test uses the bool type. | ||||
| 
 | ||||
| diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
 | ||||
| index 18067e6b0a6093f9..200dacb748af21a8 100644
 | ||||
| --- a/elf/tst-tls20.c
 | ||||
| +++ b/elf/tst-tls20.c
 | ||||
| @@ -19,6 +19,7 @@
 | ||||
|  #include <array_length.h> | ||||
|  #include <dlfcn.h> | ||||
|  #include <pthread.h> | ||||
| +#include <stdbool.h>
 | ||||
|  #include <stdint.h> | ||||
|  #include <stdio.h> | ||||
|  #include <stdlib.h> | ||||
							
								
								
									
										62
									
								
								SOURCES/glibc-rh1991001-22.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								SOURCES/glibc-rh1991001-22.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | ||||
| commit 5cc338565479a620244c2f8ff35956629c4dbf81 | ||||
| Author: Florian Weimer <fweimer@redhat.com> | ||||
| Date:   Fri Dec 10 05:14:24 2021 +0100 | ||||
| 
 | ||||
|     nptl: Add one more barrier to nptl/tst-create1 | ||||
|      | ||||
|     Without the bar_ctor_finish barrier, it was possible that thread2 | ||||
|     re-locked user_lock before ctor had a chance to lock it.  ctor then | ||||
|     blocked in its locking operation, xdlopen from the main thread | ||||
|     did not return, and thread2 was stuck waiting in bar_dtor: | ||||
|      | ||||
|     thread 1: started. | ||||
|     thread 2: started. | ||||
|     thread 2: locked user_lock. | ||||
|     constructor started: 0. | ||||
|     thread 1: in ctor: started. | ||||
|     thread 3: started. | ||||
|     thread 3: done. | ||||
|     thread 2: unlocked user_lock. | ||||
|     thread 2: locked user_lock. | ||||
|      | ||||
|     Fixes the test in commit 83b5323261bb72313bffcf37476c1b8f0847c736 | ||||
|     ("elf: Avoid deadlock between pthread_create and ctors [BZ #28357]"). | ||||
|      | ||||
|     Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| 
 | ||||
| diff --git a/sysdeps/pthread/tst-create1.c b/sysdeps/pthread/tst-create1.c
 | ||||
| index 932586c30990d1d4..763ded8d7956f943 100644
 | ||||
| --- a/sysdeps/pthread/tst-create1.c
 | ||||
| +++ b/sysdeps/pthread/tst-create1.c
 | ||||
| @@ -33,6 +33,7 @@ thread 2: lock(user_lock) -> pthread_create
 | ||||
|  */ | ||||
|   | ||||
|  static pthread_barrier_t bar_ctor; | ||||
| +static pthread_barrier_t bar_ctor_finish;
 | ||||
|  static pthread_barrier_t bar_dtor; | ||||
|  static pthread_mutex_t user_lock = PTHREAD_MUTEX_INITIALIZER; | ||||
|   | ||||
| @@ -46,6 +47,7 @@ ctor (void)
 | ||||
|    xpthread_mutex_unlock (&user_lock); | ||||
|    dprintf (1, "thread 1: in ctor: unlocked user_lock.\n"); | ||||
|    dprintf (1, "thread 1: in ctor: done.\n"); | ||||
| +  xpthread_barrier_wait (&bar_ctor_finish);
 | ||||
|  } | ||||
|   | ||||
|  void | ||||
| @@ -81,6 +83,7 @@ thread2 (void *a)
 | ||||
|    xpthread_mutex_unlock (&user_lock); | ||||
|    dprintf (1, "thread 2: unlocked user_lock.\n"); | ||||
|    xpthread_join (t3); | ||||
| +  xpthread_barrier_wait (&bar_ctor_finish);
 | ||||
|   | ||||
|    xpthread_mutex_lock (&user_lock); | ||||
|    dprintf (1, "thread 2: locked user_lock.\n"); | ||||
| @@ -99,6 +102,7 @@ thread1 (void)
 | ||||
|  { | ||||
|    dprintf (1, "thread 1: started.\n"); | ||||
|    xpthread_barrier_init (&bar_ctor, NULL, 2); | ||||
| +  xpthread_barrier_init (&bar_ctor_finish, NULL, 2);
 | ||||
|    xpthread_barrier_init (&bar_dtor, NULL, 2); | ||||
|    pthread_t t2 = xpthread_create (0, thread2, 0); | ||||
|    void *p = xdlopen ("tst-create1mod.so", RTLD_NOW | RTLD_GLOBAL); | ||||
							
								
								
									
										163
									
								
								SOURCES/glibc-rh1991001-3.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								SOURCES/glibc-rh1991001-3.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,163 @@ | ||||
| commit 8f85075a2e9c26ff7486d4bbaf358999807d215c | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Thu Dec 31 12:24:38 2020 +0000 | ||||
| 
 | ||||
|     elf: Add a DTV setup test [BZ #27136] | ||||
|      | ||||
|     The test dlopens a large number of modules with TLS, they are reused | ||||
|     from an existing test. | ||||
|      | ||||
|     The test relies on the reuse of slotinfo entries after dlclose, without | ||||
|     bug 27135 fixed this needs a failing dlopen. With a slotinfo list that | ||||
|     has non-monotone increasing generation counters, bug 27136 can trigger. | ||||
|      | ||||
|     Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org> | ||||
| 
 | ||||
| Conflicts: | ||||
| 	elf/Makefile | ||||
| 	  (usual test differences) | ||||
| 
 | ||||
| diff --git a/elf/Makefile b/elf/Makefile
 | ||||
| index 82fb019a634caf81..0995d810b57d0dda 100644
 | ||||
| --- a/elf/Makefile
 | ||||
| +++ b/elf/Makefile
 | ||||
| @@ -209,7 +209,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
 | ||||
|  	 tst-audit14 tst-audit15 tst-audit16 \ | ||||
|  	 tst-tls-ie tst-tls-ie-dlmopen \ | ||||
|  	 argv0test \ | ||||
| -	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask
 | ||||
| +	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
 | ||||
| +	 tst-tls20
 | ||||
|  #	 reldep9 | ||||
|  tests-internal += loadtest unload unload2 circleload1 \ | ||||
|  	 neededtest neededtest2 neededtest3 neededtest4 \ | ||||
| @@ -332,6 +333,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 | ||||
|  		libmarkermod2-1 libmarkermod2-2 \ | ||||
|  		libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \ | ||||
|  		libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \ | ||||
| +		tst-tls20mod-bad
 | ||||
|   | ||||
|  # Most modules build with _ISOMAC defined, but those filtered out | ||||
|  # depend on internal headers. | ||||
| @@ -1828,3 +1830,9 @@ $(objpfx)tst-rtld-help.out: $(objpfx)ld.so
 | ||||
|  	fi; \ | ||||
|  	(exit $$status); \ | ||||
|  	$(evaluate-test) | ||||
| +
 | ||||
| +# Reuses tst-tls-many-dynamic-modules
 | ||||
| +tst-tls20mod-bad.so-no-z-defs = yes
 | ||||
| +$(objpfx)tst-tls20: $(libdl) $(shared-thread-library)
 | ||||
| +$(objpfx)tst-tls20.out: $(objpfx)tst-tls20mod-bad.so \
 | ||||
| +			$(tst-tls-many-dynamic-modules:%=$(objpfx)%.so)
 | ||||
| diff --git a/elf/tst-tls20.c b/elf/tst-tls20.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..ac5f8c8d39b66dd6
 | ||||
| --- /dev/null
 | ||||
| +++ b/elf/tst-tls20.c
 | ||||
| @@ -0,0 +1,98 @@
 | ||||
| +/* Test dtv setup if entries don't have monotone increasing generation.
 | ||||
| +   Copyright (C) 2021 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
 | ||||
| +   <http://www.gnu.org/licenses/>.  */
 | ||||
| +
 | ||||
| +#include <dlfcn.h>
 | ||||
| +#include <pthread.h>
 | ||||
| +#include <stdio.h>
 | ||||
| +#include <stdlib.h>
 | ||||
| +#include <support/check.h>
 | ||||
| +#include <support/xdlfcn.h>
 | ||||
| +#include <support/xthread.h>
 | ||||
| +
 | ||||
| +#define NMOD 100
 | ||||
| +static void *mod[NMOD];
 | ||||
| +
 | ||||
| +static void
 | ||||
| +load_fail (void)
 | ||||
| +{
 | ||||
| +  /* Expected to fail because of a missing symbol.  */
 | ||||
| +  void *m = dlopen ("tst-tls20mod-bad.so", RTLD_NOW);
 | ||||
| +  if (m != NULL)
 | ||||
| +    FAIL_EXIT1 ("dlopen of tst-tls20mod-bad.so succeeded\n");
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void
 | ||||
| +load_mod (int i)
 | ||||
| +{
 | ||||
| +  char *buf = xasprintf ("tst-tls-manydynamic%02dmod.so", i);
 | ||||
| +  mod[i] = xdlopen (buf, RTLD_LAZY);
 | ||||
| +  free (buf);
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void
 | ||||
| +unload_mod (int i)
 | ||||
| +{
 | ||||
| +  if (mod[i] != NULL)
 | ||||
| +    xdlclose (mod[i]);
 | ||||
| +  mod[i] = NULL;
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void
 | ||||
| +access (int i)
 | ||||
| +{
 | ||||
| +  char *buf = xasprintf ("tls_global_%02d", i);
 | ||||
| +  dlerror ();
 | ||||
| +  int *p = dlsym (mod[i], buf);
 | ||||
| +  printf ("mod[%d]: &tls = %p\n", i, p);
 | ||||
| +  if (p == NULL)
 | ||||
| +    FAIL_EXIT1 ("dlsym failed: %s\n", dlerror ());
 | ||||
| +  ++*p;
 | ||||
| +  free (buf);
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void *
 | ||||
| +start (void *a)
 | ||||
| +{
 | ||||
| +  for (int i = 0; i < NMOD; i++)
 | ||||
| +    if (mod[i] != NULL)
 | ||||
| +      access (i);
 | ||||
| +  return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +static int
 | ||||
| +do_test (void)
 | ||||
| +{
 | ||||
| +  int i;
 | ||||
| +
 | ||||
| +  for (i = 0; i < NMOD; i++)
 | ||||
| +    {
 | ||||
| +      load_mod (i);
 | ||||
| +      /* Bump the generation of mod[0] without using new dtv slot.  */
 | ||||
| +      unload_mod (0);
 | ||||
| +      load_fail (); /* Ensure GL(dl_tls_dtv_gaps) is true: see bug 27135.  */
 | ||||
| +      load_mod (0);
 | ||||
| +      /* Access TLS in all loaded modules.  */
 | ||||
| +      pthread_t t = xpthread_create (0, start, 0);
 | ||||
| +      xpthread_join (t);
 | ||||
| +    }
 | ||||
| +  for (i = 0; i < NMOD; i++)
 | ||||
| +    unload_mod (i);
 | ||||
| +  return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +#include <support/test-driver.c>
 | ||||
| diff --git a/elf/tst-tls20mod-bad.c b/elf/tst-tls20mod-bad.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..c1aed8ea7deffd22
 | ||||
| --- /dev/null
 | ||||
| +++ b/elf/tst-tls20mod-bad.c
 | ||||
| @@ -0,0 +1,2 @@
 | ||||
| +void missing_symbol (void);
 | ||||
| +void f (void) {missing_symbol ();}
 | ||||
							
								
								
									
										41
									
								
								SOURCES/glibc-rh1991001-4.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								SOURCES/glibc-rh1991001-4.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| commit c489c35054c39d7f2437ca61b369e3ede448f022 | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Wed Nov 30 11:44:25 2016 +0000 | ||||
| 
 | ||||
|     elf: Fix comments and logic in _dl_add_to_slotinfo | ||||
|      | ||||
|     Since | ||||
|      | ||||
|       commit a509eb117fac1d764b15eba64993f4bdb63d7f3c | ||||
|       Avoid late dlopen failure due to scope, TLS slotinfo updates [BZ #25112] | ||||
|      | ||||
|     the generation counter update is not needed in the failure path. | ||||
|     That commit ensures allocation in _dl_add_to_slotinfo happens before | ||||
|     the demarcation point in dlopen (it is called twice, first time is for | ||||
|     allocation only where dlopen can still be reverted on failure, then | ||||
|     second time actual dtv updates are done which then cannot fail). | ||||
|      | ||||
|     Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org> | ||||
| 
 | ||||
| diff --git a/elf/dl-tls.c b/elf/dl-tls.c
 | ||||
| index 0b96b1dceed99d58..9375650a3ab5247d 100644
 | ||||
| --- a/elf/dl-tls.c
 | ||||
| +++ b/elf/dl-tls.c
 | ||||
| @@ -998,16 +998,7 @@ _dl_add_to_slotinfo (struct link_map *l, bool do_add)
 | ||||
|  		+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); | ||||
|        if (listp == NULL) | ||||
|  	{ | ||||
| -	  /* We ran out of memory.  We will simply fail this
 | ||||
| -	     call but don't undo anything we did so far.  The
 | ||||
| -	     application will crash or be terminated anyway very
 | ||||
| -	     soon.  */
 | ||||
| -
 | ||||
| -	  /* We have to do this since some entries in the dtv
 | ||||
| -	     slotinfo array might already point to this
 | ||||
| -	     generation.  */
 | ||||
| -	  ++GL(dl_tls_generation);
 | ||||
| -
 | ||||
| +	  /* We ran out of memory while resizing the dtv slotinfo list.  */
 | ||||
|  	  _dl_signal_error (ENOMEM, "dlopen", NULL, N_("\ | ||||
|  cannot create TLS data structures")); | ||||
|  	} | ||||
							
								
								
									
										58
									
								
								SOURCES/glibc-rh1991001-5.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								SOURCES/glibc-rh1991001-5.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| commit c0669ae1a629e16b536bf11cdd0865e0dbcf4bee | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Wed Dec 30 21:52:38 2020 +0000 | ||||
| 
 | ||||
|     elf: Refactor _dl_update_slotinfo to avoid use after free | ||||
|      | ||||
|     map is not valid to access here because it can be freed by a concurrent | ||||
|     dlclose: during tls access (via __tls_get_addr) _dl_update_slotinfo is | ||||
|     called without holding dlopen locks. So don't check the modid of map. | ||||
|      | ||||
|     The map == 0 and map != 0 code paths can be shared (avoiding the dtv | ||||
|     resize in case of map == 0 is just an optimization: larger dtv than | ||||
|     necessary would be fine too). | ||||
|      | ||||
|     Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org> | ||||
| 
 | ||||
| diff --git a/elf/dl-tls.c b/elf/dl-tls.c
 | ||||
| index 9375650a3ab5247d..15ed01d795a8627a 100644
 | ||||
| --- a/elf/dl-tls.c
 | ||||
| +++ b/elf/dl-tls.c
 | ||||
| @@ -743,6 +743,8 @@ _dl_update_slotinfo (unsigned long int req_modid)
 | ||||
|  	{ | ||||
|  	  for (size_t cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt) | ||||
|  	    { | ||||
| +	      size_t modid = total + cnt;
 | ||||
| +
 | ||||
|  	      size_t gen = listp->slotinfo[cnt].gen; | ||||
|   | ||||
|  	      if (gen > new_gen) | ||||
| @@ -758,25 +760,12 @@ _dl_update_slotinfo (unsigned long int req_modid)
 | ||||
|   | ||||
|  	      /* If there is no map this means the entry is empty.  */ | ||||
|  	      struct link_map *map = listp->slotinfo[cnt].map; | ||||
| -	      if (map == NULL)
 | ||||
| -		{
 | ||||
| -		  if (dtv[-1].counter >= total + cnt)
 | ||||
| -		    {
 | ||||
| -		      /* If this modid was used at some point the memory
 | ||||
| -			 might still be allocated.  */
 | ||||
| -		      free (dtv[total + cnt].pointer.to_free);
 | ||||
| -		      dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
 | ||||
| -		      dtv[total + cnt].pointer.to_free = NULL;
 | ||||
| -		    }
 | ||||
| -
 | ||||
| -		  continue;
 | ||||
| -		}
 | ||||
| -
 | ||||
|  	      /* Check whether the current dtv array is large enough.  */ | ||||
| -	      size_t modid = map->l_tls_modid;
 | ||||
| -	      assert (total + cnt == modid);
 | ||||
|  	      if (dtv[-1].counter < modid) | ||||
|  		{ | ||||
| +		  if (map == NULL)
 | ||||
| +		    continue;
 | ||||
| +
 | ||||
|  		  /* Resize the dtv.  */ | ||||
|  		  dtv = _dl_resize_dtv (dtv); | ||||
|   | ||||
							
								
								
									
										48
									
								
								SOURCES/glibc-rh1991001-6.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								SOURCES/glibc-rh1991001-6.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | ||||
| commit 8f7e09f4dbdb5c815a18b8285fbc5d5d7bc17d86 | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Thu Feb 11 11:29:23 2021 +0000 | ||||
| 
 | ||||
|     x86_64: Avoid lazy relocation of tlsdesc [BZ #27137] | ||||
|      | ||||
|     Lazy tlsdesc relocation is racy because the static tls optimization and | ||||
|     tlsdesc management operations are done without holding the dlopen lock. | ||||
|      | ||||
|     This similar to the commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67 | ||||
|     for aarch64, but it fixes a different race: bug 27137. | ||||
|      | ||||
|     Another issue is that ld auditing ignores DT_BIND_NOW and thus tries to | ||||
|     relocate tlsdesc lazily, but that does not work in a BIND_NOW module | ||||
|     due to missing DT_TLSDESC_PLT. Unconditionally relocating tlsdesc at | ||||
|     load time fixes this bug 27721 too. | ||||
| 
 | ||||
| diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
 | ||||
| index e308b662d245cc63..ef5740ba281c7282 100644
 | ||||
| --- a/sysdeps/x86_64/dl-machine.h
 | ||||
| +++ b/sysdeps/x86_64/dl-machine.h
 | ||||
| @@ -563,12 +563,21 @@ elf_machine_lazy_rel (struct link_map *map,
 | ||||
|      } | ||||
|    else if (__glibc_likely (r_type == R_X86_64_TLSDESC)) | ||||
|      { | ||||
| -      struct tlsdesc volatile * __attribute__((__unused__)) td =
 | ||||
| -	(struct tlsdesc volatile *)reloc_addr;
 | ||||
| +      const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
 | ||||
| +      const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]);
 | ||||
| +      const ElfW (Sym) *sym = &symtab[symndx];
 | ||||
| +      const struct r_found_version *version = NULL;
 | ||||
|   | ||||
| -      td->arg = (void*)reloc;
 | ||||
| -      td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)])
 | ||||
| -			  + map->l_addr);
 | ||||
| +      if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
 | ||||
| +	{
 | ||||
| +	  const ElfW (Half) *vernum =
 | ||||
| +	    (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
 | ||||
| +	  version = &map->l_versions[vernum[symndx] & 0x7fff];
 | ||||
| +	}
 | ||||
| +
 | ||||
| +      /* Always initialize TLS descriptors completely at load time, in
 | ||||
| +	 case static TLS is allocated for it that requires locking.  */
 | ||||
| +      elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc);
 | ||||
|      } | ||||
|    else if (__glibc_unlikely (r_type == R_X86_64_IRELATIVE)) | ||||
|      { | ||||
							
								
								
									
										116
									
								
								SOURCES/glibc-rh1991001-7.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								SOURCES/glibc-rh1991001-7.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,116 @@ | ||||
| commit ddcacd91cc10ff92d6201eda87047d029c14158d | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Thu Feb 11 11:40:11 2021 +0000 | ||||
| 
 | ||||
|     i386: Avoid lazy relocation of tlsdesc [BZ #27137] | ||||
|      | ||||
|     Lazy tlsdesc relocation is racy because the static tls optimization and | ||||
|     tlsdesc management operations are done without holding the dlopen lock. | ||||
|      | ||||
|     This similar to the commit b7cf203b5c17dd6d9878537d41e0c7cc3d270a67 | ||||
|     for aarch64, but it fixes a different race: bug 27137. | ||||
|      | ||||
|     On i386 the code is a bit more complicated than on x86_64 because both | ||||
|     rel and rela relocs are supported. | ||||
| 
 | ||||
| diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
 | ||||
| index e5776ef7bc8ad749..3a30671591284d79 100644
 | ||||
| --- a/sysdeps/i386/dl-machine.h
 | ||||
| +++ b/sysdeps/i386/dl-machine.h
 | ||||
| @@ -679,50 +679,32 @@ elf_machine_lazy_rel (struct link_map *map,
 | ||||
|      } | ||||
|    else if (__glibc_likely (r_type == R_386_TLS_DESC)) | ||||
|      { | ||||
| -      struct tlsdesc volatile * __attribute__((__unused__)) td =
 | ||||
| -	(struct tlsdesc volatile *)reloc_addr;
 | ||||
| -
 | ||||
| -      /* Handle relocations that reference the local *ABS* in a simple
 | ||||
| -	 way, so as to preserve a potential addend.  */
 | ||||
| -      if (ELF32_R_SYM (reloc->r_info) == 0)
 | ||||
| -	td->entry = _dl_tlsdesc_resolve_abs_plus_addend;
 | ||||
| -      /* Given a known-zero addend, we can store a pointer to the
 | ||||
| -	 reloc in the arg position.  */
 | ||||
| -      else if (td->arg == 0)
 | ||||
| -	{
 | ||||
| -	  td->arg = (void*)reloc;
 | ||||
| -	  td->entry = _dl_tlsdesc_resolve_rel;
 | ||||
| -	}
 | ||||
| -      else
 | ||||
| -	{
 | ||||
| -	  /* We could handle non-*ABS* relocations with non-zero addends
 | ||||
| -	     by allocating dynamically an arg to hold a pointer to the
 | ||||
| -	     reloc, but that sounds pointless.  */
 | ||||
| -	  const Elf32_Rel *const r = reloc;
 | ||||
| -	  /* The code below was borrowed from elf_dynamic_do_rel().  */
 | ||||
| -	  const ElfW(Sym) *const symtab =
 | ||||
| -	    (const void *) D_PTR (map, l_info[DT_SYMTAB]);
 | ||||
| +      const Elf32_Rel *const r = reloc;
 | ||||
| +      /* The code below was borrowed from elf_dynamic_do_rel().  */
 | ||||
| +      const ElfW(Sym) *const symtab =
 | ||||
| +	(const void *) D_PTR (map, l_info[DT_SYMTAB]);
 | ||||
|   | ||||
| +      /* Always initialize TLS descriptors completely at load time, in
 | ||||
| +	 case static TLS is allocated for it that requires locking.  */
 | ||||
|  # ifdef RTLD_BOOTSTRAP | ||||
| -	  /* The dynamic linker always uses versioning.  */
 | ||||
| -	  assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
 | ||||
| +      /* The dynamic linker always uses versioning.  */
 | ||||
| +      assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
 | ||||
|  # else | ||||
| -	  if (map->l_info[VERSYMIDX (DT_VERSYM)])
 | ||||
| +      if (map->l_info[VERSYMIDX (DT_VERSYM)])
 | ||||
|  # endif | ||||
| -	    {
 | ||||
| -	      const ElfW(Half) *const version =
 | ||||
| -		(const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
 | ||||
| -	      ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
 | ||||
| -	      elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
 | ||||
| -			       &map->l_versions[ndx],
 | ||||
| -			       (void *) (l_addr + r->r_offset), skip_ifunc);
 | ||||
| -	    }
 | ||||
| +	{
 | ||||
| +	  const ElfW(Half) *const version =
 | ||||
| +	    (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
 | ||||
| +	  ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
 | ||||
| +	  elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
 | ||||
| +			   &map->l_versions[ndx],
 | ||||
| +			   (void *) (l_addr + r->r_offset), skip_ifunc);
 | ||||
| +	}
 | ||||
|  # ifndef RTLD_BOOTSTRAP | ||||
| -	  else
 | ||||
| -	    elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
 | ||||
| -			     (void *) (l_addr + r->r_offset), skip_ifunc);
 | ||||
| +      else
 | ||||
| +	elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
 | ||||
| +			 (void *) (l_addr + r->r_offset), skip_ifunc);
 | ||||
|  # endif | ||||
| -	}
 | ||||
|      } | ||||
|    else if (__glibc_unlikely (r_type == R_386_IRELATIVE)) | ||||
|      { | ||||
| @@ -749,11 +731,21 @@ elf_machine_lazy_rela (struct link_map *map,
 | ||||
|      ; | ||||
|    else if (__glibc_likely (r_type == R_386_TLS_DESC)) | ||||
|      { | ||||
| -      struct tlsdesc volatile * __attribute__((__unused__)) td =
 | ||||
| -	(struct tlsdesc volatile *)reloc_addr;
 | ||||
| +      const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
 | ||||
| +      const ElfW (Sym) *symtab = (const void *)D_PTR (map, l_info[DT_SYMTAB]);
 | ||||
| +      const ElfW (Sym) *sym = &symtab[symndx];
 | ||||
| +      const struct r_found_version *version = NULL;
 | ||||
| +
 | ||||
| +      if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
 | ||||
| +	{
 | ||||
| +	  const ElfW (Half) *vernum =
 | ||||
| +	    (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
 | ||||
| +	  version = &map->l_versions[vernum[symndx] & 0x7fff];
 | ||||
| +	}
 | ||||
|   | ||||
| -      td->arg = (void*)reloc;
 | ||||
| -      td->entry = _dl_tlsdesc_resolve_rela;
 | ||||
| +      /* Always initialize TLS descriptors completely at load time, in
 | ||||
| +	 case static TLS is allocated for it that requires locking.  */
 | ||||
| +      elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc);
 | ||||
|      } | ||||
|    else if (__glibc_unlikely (r_type == R_386_IRELATIVE)) | ||||
|      { | ||||
							
								
								
									
										277
									
								
								SOURCES/glibc-rh1991001-8.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										277
									
								
								SOURCES/glibc-rh1991001-8.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,277 @@ | ||||
| commit 55c9f3238080e9aba733bc0902779c46cfa16446 | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Thu Feb 11 11:52:24 2021 +0000 | ||||
| 
 | ||||
|     x86_64: Remove lazy tlsdesc relocation related code | ||||
|      | ||||
|     _dl_tlsdesc_resolve_rela and _dl_tlsdesc_resolve_hold are only used for | ||||
|     lazy tlsdesc relocation processing which is no longer supported. | ||||
| 
 | ||||
| diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
 | ||||
| index ef5740ba281c7282..b94d3b39ec1dca64 100644
 | ||||
| --- a/sysdeps/x86_64/dl-machine.h
 | ||||
| +++ b/sysdeps/x86_64/dl-machine.h
 | ||||
| @@ -127,10 +127,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 | ||||
|  	} | ||||
|      } | ||||
|   | ||||
| -  if (l->l_info[ADDRIDX (DT_TLSDESC_GOT)] && lazy)
 | ||||
| -    *(ElfW(Addr)*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_GOT)]) + l->l_addr)
 | ||||
| -      = (ElfW(Addr)) &_dl_tlsdesc_resolve_rela;
 | ||||
| -
 | ||||
|    return lazy; | ||||
|  } | ||||
|   | ||||
| diff --git a/sysdeps/x86_64/dl-tlsdesc.S b/sysdeps/x86_64/dl-tlsdesc.S
 | ||||
| index 80d771cd887dd626..77e78cf0a6d8babc 100644
 | ||||
| --- a/sysdeps/x86_64/dl-tlsdesc.S
 | ||||
| +++ b/sysdeps/x86_64/dl-tlsdesc.S
 | ||||
| @@ -148,107 +148,3 @@ _dl_tlsdesc_dynamic:
 | ||||
|  	cfi_endproc | ||||
|  	.size	_dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic | ||||
|  #endif /* SHARED */ | ||||
| -
 | ||||
| -     /* This function is a wrapper for a lazy resolver for TLS_DESC
 | ||||
| -	RELA relocations.  The incoming 0(%rsp) points to the caller's
 | ||||
| -	link map, pushed by the dynamic object's internal lazy TLS
 | ||||
| -	resolver front-end before tail-calling us.  We need to pop it
 | ||||
| -	ourselves.  %rax points to a TLS descriptor, such that 0(%rax)
 | ||||
| -	holds the address of the internal resolver front-end (unless
 | ||||
| -	some other thread beat us to resolving it) and 8(%rax) holds a
 | ||||
| -	pointer to the relocation.
 | ||||
| -
 | ||||
| -	When the actual resolver returns, it will have adjusted the
 | ||||
| -	TLS descriptor such that we can tail-call it for it to return
 | ||||
| -	the TP offset of the symbol.  */
 | ||||
| -
 | ||||
| -	.hidden _dl_tlsdesc_resolve_rela
 | ||||
| -	.global	_dl_tlsdesc_resolve_rela
 | ||||
| -	.type	_dl_tlsdesc_resolve_rela,@function
 | ||||
| -	cfi_startproc
 | ||||
| -	.align 16
 | ||||
| -	/* The PLT entry will have pushed the link_map pointer.  */
 | ||||
| -_dl_tlsdesc_resolve_rela:
 | ||||
| -	_CET_ENDBR
 | ||||
| -	cfi_adjust_cfa_offset (8)
 | ||||
| -	/* Save all call-clobbered registers.  Add 8 bytes for push in
 | ||||
| -	   the PLT entry to align the stack.  */
 | ||||
| -	subq	$80, %rsp
 | ||||
| -	cfi_adjust_cfa_offset (80)
 | ||||
| -	movq	%rax, (%rsp)
 | ||||
| -	movq	%rdi, 8(%rsp)
 | ||||
| -	movq	%rax, %rdi	/* Pass tlsdesc* in %rdi.  */
 | ||||
| -	movq	%rsi, 16(%rsp)
 | ||||
| -	movq	80(%rsp), %rsi	/* Pass link_map* in %rsi.  */
 | ||||
| -	movq	%r8, 24(%rsp)
 | ||||
| -	movq	%r9, 32(%rsp)
 | ||||
| -	movq	%r10, 40(%rsp)
 | ||||
| -	movq	%r11, 48(%rsp)
 | ||||
| -	movq	%rdx, 56(%rsp)
 | ||||
| -	movq	%rcx, 64(%rsp)
 | ||||
| -	call	_dl_tlsdesc_resolve_rela_fixup
 | ||||
| -	movq	(%rsp), %rax
 | ||||
| -	movq	8(%rsp), %rdi
 | ||||
| -	movq	16(%rsp), %rsi
 | ||||
| -	movq	24(%rsp), %r8
 | ||||
| -	movq	32(%rsp), %r9
 | ||||
| -	movq	40(%rsp), %r10
 | ||||
| -	movq	48(%rsp), %r11
 | ||||
| -	movq	56(%rsp), %rdx
 | ||||
| -	movq	64(%rsp), %rcx
 | ||||
| -	addq	$88, %rsp
 | ||||
| -	cfi_adjust_cfa_offset (-88)
 | ||||
| -	jmp	*(%rax)
 | ||||
| -	cfi_endproc
 | ||||
| -	.size	_dl_tlsdesc_resolve_rela, .-_dl_tlsdesc_resolve_rela
 | ||||
| -
 | ||||
| -     /* This function is a placeholder for lazy resolving of TLS
 | ||||
| -	relocations.  Once some thread starts resolving a TLS
 | ||||
| -	relocation, it sets up the TLS descriptor to use this
 | ||||
| -	resolver, such that other threads that would attempt to
 | ||||
| -	resolve it concurrently may skip the call to the original lazy
 | ||||
| -	resolver and go straight to a condition wait.
 | ||||
| -
 | ||||
| -	When the actual resolver returns, it will have adjusted the
 | ||||
| -	TLS descriptor such that we can tail-call it for it to return
 | ||||
| -	the TP offset of the symbol.  */
 | ||||
| -
 | ||||
| -	.hidden _dl_tlsdesc_resolve_hold
 | ||||
| -	.global	_dl_tlsdesc_resolve_hold
 | ||||
| -	.type	_dl_tlsdesc_resolve_hold,@function
 | ||||
| -	cfi_startproc
 | ||||
| -	.align 16
 | ||||
| -_dl_tlsdesc_resolve_hold:
 | ||||
| -0:
 | ||||
| -	_CET_ENDBR
 | ||||
| -	/* Save all call-clobbered registers.  */
 | ||||
| -	subq	$72, %rsp
 | ||||
| -	cfi_adjust_cfa_offset (72)
 | ||||
| -	movq	%rax, (%rsp)
 | ||||
| -	movq	%rdi, 8(%rsp)
 | ||||
| -	movq	%rax, %rdi	/* Pass tlsdesc* in %rdi.  */
 | ||||
| -	movq	%rsi, 16(%rsp)
 | ||||
| -	/* Pass _dl_tlsdesc_resolve_hold's address in %rsi.  */
 | ||||
| -	leaq	. - _dl_tlsdesc_resolve_hold(%rip), %rsi
 | ||||
| -	movq	%r8, 24(%rsp)
 | ||||
| -	movq	%r9, 32(%rsp)
 | ||||
| -	movq	%r10, 40(%rsp)
 | ||||
| -	movq	%r11, 48(%rsp)
 | ||||
| -	movq	%rdx, 56(%rsp)
 | ||||
| -	movq	%rcx, 64(%rsp)
 | ||||
| -	call	_dl_tlsdesc_resolve_hold_fixup
 | ||||
| -1:
 | ||||
| -	movq	(%rsp), %rax
 | ||||
| -	movq	8(%rsp), %rdi
 | ||||
| -	movq	16(%rsp), %rsi
 | ||||
| -	movq	24(%rsp), %r8
 | ||||
| -	movq	32(%rsp), %r9
 | ||||
| -	movq	40(%rsp), %r10
 | ||||
| -	movq	48(%rsp), %r11
 | ||||
| -	movq	56(%rsp), %rdx
 | ||||
| -	movq	64(%rsp), %rcx
 | ||||
| -	addq	$72, %rsp
 | ||||
| -	cfi_adjust_cfa_offset (-72)
 | ||||
| -	jmp	*(%rax)
 | ||||
| -	cfi_endproc
 | ||||
| -	.size	_dl_tlsdesc_resolve_hold, .-_dl_tlsdesc_resolve_hold
 | ||||
| diff --git a/sysdeps/x86_64/dl-tlsdesc.h b/sysdeps/x86_64/dl-tlsdesc.h
 | ||||
| index 66e659bb5c7ede74..1cde1ee9664f4908 100644
 | ||||
| --- a/sysdeps/x86_64/dl-tlsdesc.h
 | ||||
| +++ b/sysdeps/x86_64/dl-tlsdesc.h
 | ||||
| @@ -55,9 +55,7 @@ struct tlsdesc_dynamic_arg
 | ||||
|   | ||||
|  extern ptrdiff_t attribute_hidden | ||||
|    _dl_tlsdesc_return(struct tlsdesc *on_rax), | ||||
| -  _dl_tlsdesc_undefweak(struct tlsdesc *on_rax),
 | ||||
| -  _dl_tlsdesc_resolve_rela(struct tlsdesc *on_rax),
 | ||||
| -  _dl_tlsdesc_resolve_hold(struct tlsdesc *on_rax);
 | ||||
| +  _dl_tlsdesc_undefweak(struct tlsdesc *on_rax);
 | ||||
|   | ||||
|  # ifdef SHARED | ||||
|  extern void *_dl_make_tlsdesc_dynamic (struct link_map *map, | ||||
| diff --git a/sysdeps/x86_64/tlsdesc.c b/sysdeps/x86_64/tlsdesc.c
 | ||||
| index 302d097dbb0c4f1e..61a19ae26944c84f 100644
 | ||||
| --- a/sysdeps/x86_64/tlsdesc.c
 | ||||
| +++ b/sysdeps/x86_64/tlsdesc.c
 | ||||
| @@ -16,120 +16,13 @@
 | ||||
|     License along with the GNU C Library; if not, see | ||||
|     <http://www.gnu.org/licenses/>.  */ | ||||
|   | ||||
| -#include <link.h>
 | ||||
|  #include <ldsodefs.h> | ||||
| -#include <elf/dynamic-link.h>
 | ||||
|  #include <tls.h> | ||||
|  #include <dl-tlsdesc.h> | ||||
|  #include <dl-unmap-segments.h> | ||||
| +#define _dl_tlsdesc_resolve_hold 0
 | ||||
|  #include <tlsdeschtab.h> | ||||
|   | ||||
| -/* The following 2 functions take a caller argument, that contains the
 | ||||
| -   address expected to be in the TLS descriptor.  If it's changed, we
 | ||||
| -   want to return immediately.  */
 | ||||
| -
 | ||||
| -/* This function is used to lazily resolve TLS_DESC RELA relocations.
 | ||||
| -   The argument location is used to hold a pointer to the relocation.  */
 | ||||
| -
 | ||||
| -void
 | ||||
| -attribute_hidden
 | ||||
| -_dl_tlsdesc_resolve_rela_fixup (struct tlsdesc volatile *td,
 | ||||
| -				struct link_map *l)
 | ||||
| -{
 | ||||
| -  const ElfW(Rela) *reloc = td->arg;
 | ||||
| -
 | ||||
| -  if (_dl_tlsdesc_resolve_early_return_p
 | ||||
| -      (td, (void*)(D_PTR (l, l_info[ADDRIDX (DT_TLSDESC_PLT)]) + l->l_addr)))
 | ||||
| -    return;
 | ||||
| -
 | ||||
| -  /* The code below was borrowed from _dl_fixup().  */
 | ||||
| -  const ElfW(Sym) *const symtab
 | ||||
| -    = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
 | ||||
| -  const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
 | ||||
| -  const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
 | ||||
| -  lookup_t result;
 | ||||
| -
 | ||||
| -   /* Look up the target symbol.  If the normal lookup rules are not
 | ||||
| -      used don't look in the global scope.  */
 | ||||
| -  if (ELFW(ST_BIND) (sym->st_info) != STB_LOCAL
 | ||||
| -      && __builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
 | ||||
| -    {
 | ||||
| -      const struct r_found_version *version = NULL;
 | ||||
| -
 | ||||
| -      if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
 | ||||
| -	{
 | ||||
| -	  const ElfW(Half) *vernum =
 | ||||
| -	    (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
 | ||||
| -	  ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
 | ||||
| -	  version = &l->l_versions[ndx];
 | ||||
| -	  if (version->hash == 0)
 | ||||
| -	    version = NULL;
 | ||||
| -	}
 | ||||
| -
 | ||||
| -      result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
 | ||||
| -				    l->l_scope, version, ELF_RTYPE_CLASS_PLT,
 | ||||
| -				    DL_LOOKUP_ADD_DEPENDENCY, NULL);
 | ||||
| -    }
 | ||||
| -  else
 | ||||
| -    {
 | ||||
| -      /* We already found the symbol.  The module (and therefore its load
 | ||||
| -	 address) is also known.  */
 | ||||
| -      result = l;
 | ||||
| -    }
 | ||||
| -
 | ||||
| -  if (! sym)
 | ||||
| -    {
 | ||||
| -      td->arg = (void*)reloc->r_addend;
 | ||||
| -      td->entry = _dl_tlsdesc_undefweak;
 | ||||
| -    }
 | ||||
| -  else
 | ||||
| -    {
 | ||||
| -#  ifndef SHARED
 | ||||
| -      CHECK_STATIC_TLS (l, result);
 | ||||
| -#  else
 | ||||
| -      if (!TRY_STATIC_TLS (l, result))
 | ||||
| -	{
 | ||||
| -	  td->arg = _dl_make_tlsdesc_dynamic (result, sym->st_value
 | ||||
| -					      + reloc->r_addend);
 | ||||
| -	  td->entry = _dl_tlsdesc_dynamic;
 | ||||
| -	}
 | ||||
| -      else
 | ||||
| -#  endif
 | ||||
| -	{
 | ||||
| -	  td->arg = (void*)(sym->st_value - result->l_tls_offset
 | ||||
| -			    + reloc->r_addend);
 | ||||
| -	  td->entry = _dl_tlsdesc_return;
 | ||||
| -	}
 | ||||
| -    }
 | ||||
| -
 | ||||
| -  _dl_tlsdesc_wake_up_held_fixups ();
 | ||||
| -}
 | ||||
| -
 | ||||
| -/* This function is used to avoid busy waiting for other threads to
 | ||||
| -   complete the lazy relocation.  Once another thread wins the race to
 | ||||
| -   relocate a TLS descriptor, it sets the descriptor up such that this
 | ||||
| -   function is called to wait until the resolver releases the
 | ||||
| -   lock.  */
 | ||||
| -
 | ||||
| -void
 | ||||
| -attribute_hidden
 | ||||
| -_dl_tlsdesc_resolve_hold_fixup (struct tlsdesc volatile *td,
 | ||||
| -				void *caller)
 | ||||
| -{
 | ||||
| -  /* Maybe we're lucky and can return early.  */
 | ||||
| -  if (caller != td->entry)
 | ||||
| -    return;
 | ||||
| -
 | ||||
| -  /* Locking here will stop execution until the running resolver runs
 | ||||
| -     _dl_tlsdesc_wake_up_held_fixups(), releasing the lock.
 | ||||
| -
 | ||||
| -     FIXME: We'd be better off waiting on a condition variable, such
 | ||||
| -     that we didn't have to hold the lock throughout the relocation
 | ||||
| -     processing.  */
 | ||||
| -  __rtld_lock_lock_recursive (GL(dl_load_lock));
 | ||||
| -  __rtld_lock_unlock_recursive (GL(dl_load_lock));
 | ||||
| -}
 | ||||
| -
 | ||||
|  /* Unmap the dynamic object, but also release its TLS descriptor table | ||||
|     if there is one.  */ | ||||
|   | ||||
							
								
								
									
										443
									
								
								SOURCES/glibc-rh1991001-9.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										443
									
								
								SOURCES/glibc-rh1991001-9.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,443 @@ | ||||
| commit a75a02a696f9f869d77b17b99964823aa8833a8b | ||||
| Author: Szabolcs Nagy <szabolcs.nagy@arm.com> | ||||
| Date:   Thu Feb 11 11:58:20 2021 +0000 | ||||
| 
 | ||||
|     i386: Remove lazy tlsdesc relocation related code | ||||
|      | ||||
|     Like in commit e75711ebfa976d5468ec292282566a18b07e4d67 for x86_64, | ||||
|     remove unused lazy tlsdesc relocation processing code: | ||||
|      | ||||
|       _dl_tlsdesc_resolve_abs_plus_addend | ||||
|       _dl_tlsdesc_resolve_rel | ||||
|       _dl_tlsdesc_resolve_rela | ||||
|       _dl_tlsdesc_resolve_hold | ||||
| 
 | ||||
| diff --git a/sysdeps/i386/dl-tlsdesc.S b/sysdeps/i386/dl-tlsdesc.S
 | ||||
| index 128f0af3188f46bb..22ecb2c6adc6cc6e 100644
 | ||||
| --- a/sysdeps/i386/dl-tlsdesc.S
 | ||||
| +++ b/sysdeps/i386/dl-tlsdesc.S
 | ||||
| @@ -138,159 +138,3 @@ _dl_tlsdesc_dynamic:
 | ||||
|  	cfi_endproc | ||||
|  	.size	_dl_tlsdesc_dynamic, .-_dl_tlsdesc_dynamic | ||||
|  #endif /* SHARED */ | ||||
| -
 | ||||
| -     /* This function is a wrapper for a lazy resolver for TLS_DESC
 | ||||
| -	REL relocations that reference the *ABS* segment in their own
 | ||||
| -	link maps.  %ebx points to the caller's GOT.  %eax points to a
 | ||||
| -	TLS descriptor, such that 0(%eax) holds the address of the
 | ||||
| -	resolver wrapper itself (unless some other thread beat us to
 | ||||
| -	it) and 4(%eax) holds the addend in the relocation.
 | ||||
| -
 | ||||
| -	When the actual resolver returns, it will have adjusted the
 | ||||
| -	TLS descriptor such that we can tail-call it for it to return
 | ||||
| -	the TP offset of the symbol.  */
 | ||||
| -
 | ||||
| -	.hidden _dl_tlsdesc_resolve_abs_plus_addend
 | ||||
| -	.global	_dl_tlsdesc_resolve_abs_plus_addend
 | ||||
| -	.type	_dl_tlsdesc_resolve_abs_plus_addend,@function
 | ||||
| -	cfi_startproc
 | ||||
| -	.align 16
 | ||||
| -_dl_tlsdesc_resolve_abs_plus_addend:
 | ||||
| -0:
 | ||||
| -	_CET_ENDBR
 | ||||
| -	pushl	%eax
 | ||||
| -	cfi_adjust_cfa_offset (4)
 | ||||
| -	pushl	%ecx
 | ||||
| -	cfi_adjust_cfa_offset (4)
 | ||||
| -	pushl	%edx
 | ||||
| -	cfi_adjust_cfa_offset (4)
 | ||||
| -	movl	$1f - 0b, %ecx
 | ||||
| -	movl	4(%ebx), %edx
 | ||||
| -	call	_dl_tlsdesc_resolve_abs_plus_addend_fixup
 | ||||
| -1:
 | ||||
| -	popl	%edx
 | ||||
| -	cfi_adjust_cfa_offset (-4)
 | ||||
| -	popl	%ecx
 | ||||
| -	cfi_adjust_cfa_offset (-4)
 | ||||
| -	popl	%eax
 | ||||
| -	cfi_adjust_cfa_offset (-4)
 | ||||
| -	jmp	*(%eax)
 | ||||
| -	cfi_endproc
 | ||||
| -	.size	_dl_tlsdesc_resolve_abs_plus_addend, .-_dl_tlsdesc_resolve_abs_plus_addend
 | ||||
| -
 | ||||
| -     /* This function is a wrapper for a lazy resolver for TLS_DESC
 | ||||
| -	REL relocations that had zero addends.  %ebx points to the
 | ||||
| -	caller's GOT.  %eax points to a TLS descriptor, such that
 | ||||
| -	0(%eax) holds the address of the resolver wrapper itself
 | ||||
| -	(unless some other thread beat us to it) and 4(%eax) holds a
 | ||||
| -	pointer to the relocation.
 | ||||
| -
 | ||||
| -	When the actual resolver returns, it will have adjusted the
 | ||||
| -	TLS descriptor such that we can tail-call it for it to return
 | ||||
| -	the TP offset of the symbol.  */
 | ||||
| -
 | ||||
| -	.hidden _dl_tlsdesc_resolve_rel
 | ||||
| -	.global	_dl_tlsdesc_resolve_rel
 | ||||
| -	.type	_dl_tlsdesc_resolve_rel,@function
 | ||||
| -	cfi_startproc
 | ||||
| -	.align 16
 | ||||
| -_dl_tlsdesc_resolve_rel:
 | ||||
| -0:
 | ||||
| -	_CET_ENDBR
 | ||||
| -	pushl	%eax
 | ||||
| -	cfi_adjust_cfa_offset (4)
 | ||||
| -	pushl	%ecx
 | ||||
| -	cfi_adjust_cfa_offset (4)
 | ||||
| -	pushl	%edx
 | ||||
| -	cfi_adjust_cfa_offset (4)
 | ||||
| -	movl	$1f - 0b, %ecx
 | ||||
| -	movl	4(%ebx), %edx
 | ||||
| -	call	_dl_tlsdesc_resolve_rel_fixup
 | ||||
| -1:
 | ||||
| -	popl	%edx
 | ||||
| -	cfi_adjust_cfa_offset (-4)
 | ||||
| -	popl	%ecx
 | ||||
| -	cfi_adjust_cfa_offset (-4)
 | ||||
| -	popl	%eax
 | ||||
| -	cfi_adjust_cfa_offset (-4)
 | ||||
| -	jmp	*(%eax)
 | ||||
| -	cfi_endproc
 | ||||
| -	.size	_dl_tlsdesc_resolve_rel, .-_dl_tlsdesc_resolve_rel
 | ||||
| -
 | ||||
| -     /* This function is a wrapper for a lazy resolver for TLS_DESC
 | ||||
| -	RELA relocations.  %ebx points to the caller's GOT.  %eax
 | ||||
| -	points to a TLS descriptor, such that 0(%eax) holds the
 | ||||
| -	address of the resolver wrapper itself (unless some other
 | ||||
| -	thread beat us to it) and 4(%eax) holds a pointer to the
 | ||||
| -	relocation.
 | ||||
| -
 | ||||
| -	When the actual resolver returns, it will have adjusted the
 | ||||
| -	TLS descriptor such that we can tail-call it for it to return
 | ||||
| -	the TP offset of the symbol.  */
 | ||||
| -
 | ||||
| -	.hidden _dl_tlsdesc_resolve_rela
 | ||||
| -	.global	_dl_tlsdesc_resolve_rela
 | ||||
| -	.type	_dl_tlsdesc_resolve_rela,@function
 | ||||
| -	cfi_startproc
 | ||||
| -	.align 16
 | ||||
| -_dl_tlsdesc_resolve_rela:
 | ||||
| -0:
 | ||||
| -	_CET_ENDBR
 | ||||
| -	pushl	%eax
 | ||||
| -	cfi_adjust_cfa_offset (4)
 | ||||
| -	pushl	%ecx
 | ||||
| -	cfi_adjust_cfa_offset (4)
 | ||||
| -	pushl	%edx
 | ||||
| -	cfi_adjust_cfa_offset (4)
 | ||||
| -	movl	$1f - 0b, %ecx
 | ||||
| -	movl	4(%ebx), %edx
 | ||||
| -	call	_dl_tlsdesc_resolve_rela_fixup
 | ||||
| -1:
 | ||||
| -	popl	%edx
 | ||||
| -	cfi_adjust_cfa_offset (-4)
 | ||||
| -	popl	%ecx
 | ||||
| -	cfi_adjust_cfa_offset (-4)
 | ||||
| -	popl	%eax
 | ||||
| -	cfi_adjust_cfa_offset (-4)
 | ||||
| -	jmp	*(%eax)
 | ||||
| -	cfi_endproc
 | ||||
| -	.size	_dl_tlsdesc_resolve_rela, .-_dl_tlsdesc_resolve_rela
 | ||||
| -
 | ||||
| -     /* This function is a placeholder for lazy resolving of TLS
 | ||||
| -	relocations.  Once some thread starts resolving a TLS
 | ||||
| -	relocation, it sets up the TLS descriptor to use this
 | ||||
| -	resolver, such that other threads that would attempt to
 | ||||
| -	resolve it concurrently may skip the call to the original lazy
 | ||||
| -	resolver and go straight to a condition wait.
 | ||||
| -
 | ||||
| -	When the actual resolver returns, it will have adjusted the
 | ||||
| -	TLS descriptor such that we can tail-call it for it to return
 | ||||
| -	the TP offset of the symbol.  */
 | ||||
| -
 | ||||
| -	.hidden _dl_tlsdesc_resolve_hold
 | ||||
| -	.global	_dl_tlsdesc_resolve_hold
 | ||||
| -	.type	_dl_tlsdesc_resolve_hold,@function
 | ||||
| -	cfi_startproc
 | ||||
| -	.align 16
 | ||||
| -_dl_tlsdesc_resolve_hold:
 | ||||
| -0:
 | ||||
| -	_CET_ENDBR
 | ||||
| -	pushl	%eax
 | ||||
| -	cfi_adjust_cfa_offset (4)
 | ||||
| -	pushl	%ecx
 | ||||
| -	cfi_adjust_cfa_offset (4)
 | ||||
| -	pushl	%edx
 | ||||
| -	cfi_adjust_cfa_offset (4)
 | ||||
| -	movl	$1f - 0b, %ecx
 | ||||
| -	movl	4(%ebx), %edx
 | ||||
| -	call	_dl_tlsdesc_resolve_hold_fixup
 | ||||
| -1:
 | ||||
| -	popl	%edx
 | ||||
| -	cfi_adjust_cfa_offset (-4)
 | ||||
| -	popl	%ecx
 | ||||
| -	cfi_adjust_cfa_offset (-4)
 | ||||
| -	popl	%eax
 | ||||
| -	cfi_adjust_cfa_offset (-4)
 | ||||
| -	jmp	*(%eax)
 | ||||
| -	cfi_endproc
 | ||||
| -	.size	_dl_tlsdesc_resolve_hold, .-_dl_tlsdesc_resolve_hold
 | ||||
| diff --git a/sysdeps/i386/dl-tlsdesc.h b/sysdeps/i386/dl-tlsdesc.h
 | ||||
| index c8a1e056150dc418..1a1a22c303baf85b 100644
 | ||||
| --- a/sysdeps/i386/dl-tlsdesc.h
 | ||||
| +++ b/sysdeps/i386/dl-tlsdesc.h
 | ||||
| @@ -43,11 +43,7 @@ struct tlsdesc_dynamic_arg
 | ||||
|   | ||||
|  extern ptrdiff_t attribute_hidden __attribute__ ((regparm (1))) | ||||
|    _dl_tlsdesc_return (struct tlsdesc *), | ||||
| -  _dl_tlsdesc_undefweak (struct tlsdesc *),
 | ||||
| -  _dl_tlsdesc_resolve_abs_plus_addend (struct tlsdesc *),
 | ||||
| -  _dl_tlsdesc_resolve_rel (struct tlsdesc *),
 | ||||
| -  _dl_tlsdesc_resolve_rela (struct tlsdesc *),
 | ||||
| -  _dl_tlsdesc_resolve_hold (struct tlsdesc *);
 | ||||
| +  _dl_tlsdesc_undefweak (struct tlsdesc *);
 | ||||
|   | ||||
|  # ifdef SHARED | ||||
|  extern void *_dl_make_tlsdesc_dynamic (struct link_map *map, | ||||
| diff --git a/sysdeps/i386/tlsdesc.c b/sysdeps/i386/tlsdesc.c
 | ||||
| index 82fa8a1d35fd1912..1b4227c8381e1b3d 100644
 | ||||
| --- a/sysdeps/i386/tlsdesc.c
 | ||||
| +++ b/sysdeps/i386/tlsdesc.c
 | ||||
| @@ -16,242 +16,13 @@
 | ||||
|     License along with the GNU C Library; if not, see | ||||
|     <http://www.gnu.org/licenses/>.  */ | ||||
|   | ||||
| -#include <link.h>
 | ||||
|  #include <ldsodefs.h> | ||||
| -#include <elf/dynamic-link.h>
 | ||||
|  #include <tls.h> | ||||
|  #include <dl-tlsdesc.h> | ||||
|  #include <dl-unmap-segments.h> | ||||
| +#define _dl_tlsdesc_resolve_hold 0
 | ||||
|  #include <tlsdeschtab.h> | ||||
|   | ||||
| -/* The following 4 functions take an entry_check_offset argument.
 | ||||
| -   It's computed by the caller as an offset between its entry point
 | ||||
| -   and the call site, such that by adding the built-in return address
 | ||||
| -   that is implicitly passed to the function with this offset, we can
 | ||||
| -   easily obtain the caller's entry point to compare with the entry
 | ||||
| -   point given in the TLS descriptor.  If it's changed, we want to
 | ||||
| -   return immediately.  */
 | ||||
| -
 | ||||
| -/* This function is used to lazily resolve TLS_DESC REL relocations
 | ||||
| -   that reference the *ABS* segment in their own link maps.  The
 | ||||
| -   argument is the addend originally stored there.  */
 | ||||
| -
 | ||||
| -void
 | ||||
| -__attribute__ ((regparm (3))) attribute_hidden
 | ||||
| -_dl_tlsdesc_resolve_abs_plus_addend_fixup (struct tlsdesc volatile *td,
 | ||||
| -					   struct link_map *l,
 | ||||
| -					   ptrdiff_t entry_check_offset)
 | ||||
| -{
 | ||||
| -  ptrdiff_t addend = (ptrdiff_t) td->arg;
 | ||||
| -
 | ||||
| -  if (_dl_tlsdesc_resolve_early_return_p (td, __builtin_return_address (0)
 | ||||
| -					  - entry_check_offset))
 | ||||
| -    return;
 | ||||
| -
 | ||||
| -#ifndef SHARED
 | ||||
| -  CHECK_STATIC_TLS (l, l);
 | ||||
| -#else
 | ||||
| -  if (!TRY_STATIC_TLS (l, l))
 | ||||
| -    {
 | ||||
| -      td->arg = _dl_make_tlsdesc_dynamic (l, addend);
 | ||||
| -      td->entry = _dl_tlsdesc_dynamic;
 | ||||
| -    }
 | ||||
| -  else
 | ||||
| -#endif
 | ||||
| -    {
 | ||||
| -      td->arg = (void*) (addend - l->l_tls_offset);
 | ||||
| -      td->entry = _dl_tlsdesc_return;
 | ||||
| -    }
 | ||||
| -
 | ||||
| -  _dl_tlsdesc_wake_up_held_fixups ();
 | ||||
| -}
 | ||||
| -
 | ||||
| -/* This function is used to lazily resolve TLS_DESC REL relocations
 | ||||
| -   that originally had zero addends.  The argument location, that
 | ||||
| -   originally held the addend, is used to hold a pointer to the
 | ||||
| -   relocation, but it has to be restored before we call the function
 | ||||
| -   that applies relocations.  */
 | ||||
| -
 | ||||
| -void
 | ||||
| -__attribute__ ((regparm (3))) attribute_hidden
 | ||||
| -_dl_tlsdesc_resolve_rel_fixup (struct tlsdesc volatile *td,
 | ||||
| -			       struct link_map *l,
 | ||||
| -			       ptrdiff_t entry_check_offset)
 | ||||
| -{
 | ||||
| -  const ElfW(Rel) *reloc = td->arg;
 | ||||
| -
 | ||||
| -  if (_dl_tlsdesc_resolve_early_return_p (td, __builtin_return_address (0)
 | ||||
| -					  - entry_check_offset))
 | ||||
| -    return;
 | ||||
| -
 | ||||
| -  /* The code below was borrowed from _dl_fixup(),
 | ||||
| -     except for checking for STB_LOCAL.  */
 | ||||
| -  const ElfW(Sym) *const symtab
 | ||||
| -    = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
 | ||||
| -  const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
 | ||||
| -  const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
 | ||||
| -  lookup_t result;
 | ||||
| -
 | ||||
| -   /* Look up the target symbol.  If the normal lookup rules are not
 | ||||
| -      used don't look in the global scope.  */
 | ||||
| -  if (ELFW(ST_BIND) (sym->st_info) != STB_LOCAL
 | ||||
| -      && __builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
 | ||||
| -    {
 | ||||
| -      const struct r_found_version *version = NULL;
 | ||||
| -
 | ||||
| -      if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
 | ||||
| -	{
 | ||||
| -	  const ElfW(Half) *vernum =
 | ||||
| -	    (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
 | ||||
| -	  ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
 | ||||
| -	  version = &l->l_versions[ndx];
 | ||||
| -	  if (version->hash == 0)
 | ||||
| -	    version = NULL;
 | ||||
| -	}
 | ||||
| -
 | ||||
| -      result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
 | ||||
| -				    l->l_scope, version, ELF_RTYPE_CLASS_PLT,
 | ||||
| -				    DL_LOOKUP_ADD_DEPENDENCY, NULL);
 | ||||
| -    }
 | ||||
| -  else
 | ||||
| -    {
 | ||||
| -      /* We already found the symbol.  The module (and therefore its load
 | ||||
| -	 address) is also known.  */
 | ||||
| -      result = l;
 | ||||
| -    }
 | ||||
| -
 | ||||
| -  if (!sym)
 | ||||
| -    {
 | ||||
| -      td->arg = 0;
 | ||||
| -      td->entry = _dl_tlsdesc_undefweak;
 | ||||
| -    }
 | ||||
| -  else
 | ||||
| -    {
 | ||||
| -#  ifndef SHARED
 | ||||
| -      CHECK_STATIC_TLS (l, result);
 | ||||
| -#  else
 | ||||
| -      if (!TRY_STATIC_TLS (l, result))
 | ||||
| -	{
 | ||||
| -	  td->arg = _dl_make_tlsdesc_dynamic (result, sym->st_value);
 | ||||
| -	  td->entry = _dl_tlsdesc_dynamic;
 | ||||
| -	}
 | ||||
| -      else
 | ||||
| -#  endif
 | ||||
| -	{
 | ||||
| -	  td->arg = (void*)(sym->st_value - result->l_tls_offset);
 | ||||
| -	  td->entry = _dl_tlsdesc_return;
 | ||||
| -	}
 | ||||
| -    }
 | ||||
| -
 | ||||
| -  _dl_tlsdesc_wake_up_held_fixups ();
 | ||||
| -}
 | ||||
| -
 | ||||
| -/* This function is used to lazily resolve TLS_DESC RELA relocations.
 | ||||
| -   The argument location is used to hold a pointer to the relocation.  */
 | ||||
| -
 | ||||
| -void
 | ||||
| -__attribute__ ((regparm (3))) attribute_hidden
 | ||||
| -_dl_tlsdesc_resolve_rela_fixup (struct tlsdesc volatile *td,
 | ||||
| -				struct link_map *l,
 | ||||
| -				ptrdiff_t entry_check_offset)
 | ||||
| -{
 | ||||
| -  const ElfW(Rela) *reloc = td->arg;
 | ||||
| -
 | ||||
| -  if (_dl_tlsdesc_resolve_early_return_p (td, __builtin_return_address (0)
 | ||||
| -					  - entry_check_offset))
 | ||||
| -    return;
 | ||||
| -
 | ||||
| -  /* The code below was borrowed from _dl_fixup(),
 | ||||
| -     except for checking for STB_LOCAL.  */
 | ||||
| -  const ElfW(Sym) *const symtab
 | ||||
| -    = (const void *) D_PTR (l, l_info[DT_SYMTAB]);
 | ||||
| -  const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]);
 | ||||
| -  const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
 | ||||
| -  lookup_t result;
 | ||||
| -
 | ||||
| -   /* Look up the target symbol.  If the normal lookup rules are not
 | ||||
| -      used don't look in the global scope.  */
 | ||||
| -  if (ELFW(ST_BIND) (sym->st_info) != STB_LOCAL
 | ||||
| -      && __builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)
 | ||||
| -    {
 | ||||
| -      const struct r_found_version *version = NULL;
 | ||||
| -
 | ||||
| -      if (l->l_info[VERSYMIDX (DT_VERSYM)] != NULL)
 | ||||
| -	{
 | ||||
| -	  const ElfW(Half) *vernum =
 | ||||
| -	    (const void *) D_PTR (l, l_info[VERSYMIDX (DT_VERSYM)]);
 | ||||
| -	  ElfW(Half) ndx = vernum[ELFW(R_SYM) (reloc->r_info)] & 0x7fff;
 | ||||
| -	  version = &l->l_versions[ndx];
 | ||||
| -	  if (version->hash == 0)
 | ||||
| -	    version = NULL;
 | ||||
| -	}
 | ||||
| -
 | ||||
| -      result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
 | ||||
| -				    l->l_scope, version, ELF_RTYPE_CLASS_PLT,
 | ||||
| -				    DL_LOOKUP_ADD_DEPENDENCY, NULL);
 | ||||
| -    }
 | ||||
| -  else
 | ||||
| -    {
 | ||||
| -      /* We already found the symbol.  The module (and therefore its load
 | ||||
| -	 address) is also known.  */
 | ||||
| -      result = l;
 | ||||
| -    }
 | ||||
| -
 | ||||
| -  if (!sym)
 | ||||
| -    {
 | ||||
| -      td->arg = (void*) reloc->r_addend;
 | ||||
| -      td->entry = _dl_tlsdesc_undefweak;
 | ||||
| -    }
 | ||||
| -  else
 | ||||
| -    {
 | ||||
| -#  ifndef SHARED
 | ||||
| -      CHECK_STATIC_TLS (l, result);
 | ||||
| -#  else
 | ||||
| -      if (!TRY_STATIC_TLS (l, result))
 | ||||
| -	{
 | ||||
| -	  td->arg = _dl_make_tlsdesc_dynamic (result, sym->st_value
 | ||||
| -					      + reloc->r_addend);
 | ||||
| -	  td->entry = _dl_tlsdesc_dynamic;
 | ||||
| -	}
 | ||||
| -      else
 | ||||
| -#  endif
 | ||||
| -	{
 | ||||
| -	  td->arg = (void*) (sym->st_value - result->l_tls_offset
 | ||||
| -			     + reloc->r_addend);
 | ||||
| -	  td->entry = _dl_tlsdesc_return;
 | ||||
| -	}
 | ||||
| -    }
 | ||||
| -
 | ||||
| -  _dl_tlsdesc_wake_up_held_fixups ();
 | ||||
| -}
 | ||||
| -
 | ||||
| -/* This function is used to avoid busy waiting for other threads to
 | ||||
| -   complete the lazy relocation.  Once another thread wins the race to
 | ||||
| -   relocate a TLS descriptor, it sets the descriptor up such that this
 | ||||
| -   function is called to wait until the resolver releases the
 | ||||
| -   lock.  */
 | ||||
| -
 | ||||
| -void
 | ||||
| -__attribute__ ((regparm (3))) attribute_hidden
 | ||||
| -_dl_tlsdesc_resolve_hold_fixup (struct tlsdesc volatile *td,
 | ||||
| -				struct link_map *l __attribute__((__unused__)),
 | ||||
| -				ptrdiff_t entry_check_offset)
 | ||||
| -{
 | ||||
| -  /* Maybe we're lucky and can return early.  */
 | ||||
| -  if (__builtin_return_address (0) - entry_check_offset != td->entry)
 | ||||
| -    return;
 | ||||
| -
 | ||||
| -  /* Locking here will stop execution until the running resolver runs
 | ||||
| -     _dl_tlsdesc_wake_up_held_fixups(), releasing the lock.
 | ||||
| -
 | ||||
| -     FIXME: We'd be better off waiting on a condition variable, such
 | ||||
| -     that we didn't have to hold the lock throughout the relocation
 | ||||
| -     processing.  */
 | ||||
| -  __rtld_lock_lock_recursive (GL(dl_load_lock));
 | ||||
| -  __rtld_lock_unlock_recursive (GL(dl_load_lock));
 | ||||
| -}
 | ||||
| -
 | ||||
| -
 | ||||
|  /* Unmap the dynamic object, but also release its TLS descriptor table | ||||
|     if there is one.  */ | ||||
|   | ||||
							
								
								
									
										205
									
								
								SOURCES/glibc-rh2000374.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								SOURCES/glibc-rh2000374.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,205 @@ | ||||
| Bug RHEL #2000374 | ||||
| Bugs Upstream #24046, #25923 | ||||
| 
 | ||||
| This patch provides 12-hour time for the English language UTF-8 locale as a | ||||
| new locale en_US@ampm.UTF-8. | ||||
| 
 | ||||
| Two upstream commits were applied to en_US to create the new file en_US@ampm: | ||||
|   Upstream commit: 7395f3a0efad9fc51bb54fa383ef6524702e0c49 | ||||
|   Upstream commit: 8cde977077b3568310c743b21a905ca9ab286724 | ||||
| 
 | ||||
| en_US remains unchanged and the new file en_US@ampm is now supported. | ||||
| 
 | ||||
| 
 | ||||
| diff -Nrup a/localedata/locales/en_US@ampm b/localedata/locales/en_US@ampm
 | ||||
| --- a/localedata/locales/en_US@ampm	1969-12-31 19:00:00.000000000 -0500
 | ||||
| +++ b/localedata/locales/en_US@ampm	2021-11-17 17:19:15.338720307 -0500
 | ||||
| @@ -0,0 +1,177 @@
 | ||||
| +comment_char %
 | ||||
| +escape_char /
 | ||||
| +
 | ||||
| +% This file is part of the GNU C Library and contains locale data.
 | ||||
| +% The Free Software Foundation does not claim any copyright interest
 | ||||
| +% in the locale data contained in this file.  The foregoing does not
 | ||||
| +% affect the license of the GNU C Library as a whole.  It does not
 | ||||
| +% exempt you from the conditions of the license if your use would
 | ||||
| +% otherwise be governed by that license.
 | ||||
| +
 | ||||
| +% Locale for English locale in the USA
 | ||||
| +% Contributed by Ulrich Drepper <drepper@redhat.com>, 2000
 | ||||
| +
 | ||||
| +LC_IDENTIFICATION
 | ||||
| +title      "English locale for the USA"
 | ||||
| +source     "Free Software Foundation, Inc."
 | ||||
| +address    "http:////www.gnu.org//software//libc//"
 | ||||
| +contact    ""
 | ||||
| +email      "bug-glibc-locales@gnu.org"
 | ||||
| +tel        ""
 | ||||
| +fax        ""
 | ||||
| +language   "American English"
 | ||||
| +territory  "United States"
 | ||||
| +revision   "1.0"
 | ||||
| +date       "2000-06-24"
 | ||||
| +
 | ||||
| +category "i18n:2012";LC_IDENTIFICATION
 | ||||
| +category "i18n:2012";LC_CTYPE
 | ||||
| +category "i18n:2012";LC_COLLATE
 | ||||
| +category "i18n:2012";LC_TIME
 | ||||
| +category "i18n:2012";LC_NUMERIC
 | ||||
| +category "i18n:2012";LC_MONETARY
 | ||||
| +category "i18n:2012";LC_MESSAGES
 | ||||
| +category "i18n:2012";LC_PAPER
 | ||||
| +category "i18n:2012";LC_NAME
 | ||||
| +category "i18n:2012";LC_ADDRESS
 | ||||
| +category "i18n:2012";LC_TELEPHONE
 | ||||
| +category "i18n:2012";LC_MEASUREMENT
 | ||||
| +END LC_IDENTIFICATION
 | ||||
| +
 | ||||
| +LC_CTYPE
 | ||||
| +copy "en_GB"
 | ||||
| +END LC_CTYPE
 | ||||
| +
 | ||||
| +LC_COLLATE
 | ||||
| +
 | ||||
| +% Copy the template from ISO/IEC 14651
 | ||||
| +copy "iso14651_t1"
 | ||||
| +
 | ||||
| +END LC_COLLATE
 | ||||
| +
 | ||||
| +LC_MONETARY
 | ||||
| +int_curr_symbol     "USD "
 | ||||
| +currency_symbol     "$"
 | ||||
| +mon_decimal_point   "."
 | ||||
| +mon_thousands_sep   ","
 | ||||
| +mon_grouping        3;3
 | ||||
| +positive_sign       ""
 | ||||
| +negative_sign       "-"
 | ||||
| +int_frac_digits     2
 | ||||
| +frac_digits         2
 | ||||
| +p_cs_precedes       1
 | ||||
| +int_p_sep_by_space  1
 | ||||
| +p_sep_by_space      0
 | ||||
| +n_cs_precedes       1
 | ||||
| +int_n_sep_by_space  1
 | ||||
| +n_sep_by_space      0
 | ||||
| +p_sign_posn         1
 | ||||
| +n_sign_posn         1
 | ||||
| +%
 | ||||
| +END LC_MONETARY
 | ||||
| +
 | ||||
| +LC_NUMERIC
 | ||||
| +decimal_point   "."
 | ||||
| +thousands_sep   ","
 | ||||
| +grouping        3;3
 | ||||
| +END LC_NUMERIC
 | ||||
| +
 | ||||
| +LC_TIME
 | ||||
| +abday	"Sun";"Mon";"Tue";"Wed";"Thu";"Fri";"Sat"
 | ||||
| +day	"Sunday";/
 | ||||
| +	"Monday";/
 | ||||
| +	"Tuesday";/
 | ||||
| +	"Wednesday";/
 | ||||
| +	"Thursday";/
 | ||||
| +	"Friday";/
 | ||||
| +	"Saturday"
 | ||||
| +
 | ||||
| +week 7;19971130;1
 | ||||
| +abmon	"Jan";"Feb";/
 | ||||
| +	"Mar";"Apr";/
 | ||||
| +	"May";"Jun";/
 | ||||
| +	"Jul";"Aug";/
 | ||||
| +	"Sep";"Oct";/
 | ||||
| +	"Nov";"Dec"
 | ||||
| +mon	"January";/
 | ||||
| +	"February";/
 | ||||
| +	"March";/
 | ||||
| +	"April";/
 | ||||
| +	"May";/
 | ||||
| +	"June";/
 | ||||
| +	"July";/
 | ||||
| +	"August";/
 | ||||
| +	"September";/
 | ||||
| +	"October";/
 | ||||
| +	"November";/
 | ||||
| +	"December"
 | ||||
| +% Appropriate date and time representation (%c)
 | ||||
| +d_t_fmt "%a %d %b %Y %r %Z"
 | ||||
| +%
 | ||||
| +% Appropriate date representation (%x)
 | ||||
| +d_fmt   "%m//%d//%Y"
 | ||||
| +%
 | ||||
| +% Appropriate time representation (%X)
 | ||||
| +t_fmt   "%r"
 | ||||
| +%
 | ||||
| +% Appropriate AM/PM time representation (%r)
 | ||||
| +t_fmt_ampm "%I:%M:%S %p"
 | ||||
| +%
 | ||||
| +% Appropriate date and time representation for date(1).  This is
 | ||||
| +% different from d_t_fmt for historical reasons and has been different
 | ||||
| +% since 2000 when date_fmt was added as a GNU extension.  At the end
 | ||||
| +% of 2018 it was adjusted to use 12H time (bug 24046) instead of 24H.
 | ||||
| +date_fmt "%a %b %e %r %Z %Y"
 | ||||
| +%
 | ||||
| +% Strings for AM/PM
 | ||||
| +%
 | ||||
| +am_pm	"AM";"PM"
 | ||||
| +END LC_TIME
 | ||||
| +
 | ||||
| +LC_MESSAGES
 | ||||
| +yesexpr "^[+1yY]"
 | ||||
| +noexpr  "^[-0nN]"
 | ||||
| +yesstr  "yes"
 | ||||
| +nostr   "no"
 | ||||
| +END LC_MESSAGES
 | ||||
| +
 | ||||
| +LC_PAPER
 | ||||
| +height   279
 | ||||
| +width    216
 | ||||
| +END LC_PAPER
 | ||||
| +
 | ||||
| +LC_NAME
 | ||||
| +name_fmt    "%d%t%g%t%m%t%f"
 | ||||
| +name_miss   "Miss."
 | ||||
| +name_mr     "Mr."
 | ||||
| +name_mrs    "Mrs."
 | ||||
| +name_ms     "Ms."
 | ||||
| +END LC_NAME
 | ||||
| +
 | ||||
| +
 | ||||
| +LC_ADDRESS
 | ||||
| +postal_fmt    "%a%N%f%N%d%N%b%N%h %s %e %r%N%T, %S %z%N%c%N"
 | ||||
| +country_name "United States"
 | ||||
| +country_post  "USA"
 | ||||
| +country_ab2   "US"
 | ||||
| +country_ab3   "USA"
 | ||||
| +country_num   840
 | ||||
| +country_car   "USA"
 | ||||
| +country_isbn  0
 | ||||
| +lang_name     "English"
 | ||||
| +lang_ab      "en"
 | ||||
| +lang_term    "eng"
 | ||||
| +lang_lib    "eng"
 | ||||
| +END LC_ADDRESS
 | ||||
| +
 | ||||
| +LC_TELEPHONE
 | ||||
| +tel_int_fmt    "+%c (%a) %l"
 | ||||
| +tel_dom_fmt    "(%a) %l"
 | ||||
| +int_select     "11"
 | ||||
| +int_prefix     "1"
 | ||||
| +END LC_TELEPHONE
 | ||||
| +
 | ||||
| +LC_MEASUREMENT
 | ||||
| +% US customary units.
 | ||||
| +measurement 2
 | ||||
| +END LC_MEASUREMENT
 | ||||
| diff -Nrup a/localedata/SUPPORTED b/localedata/SUPPORTED
 | ||||
| --- a/localedata/SUPPORTED	2021-11-17 17:14:33.831631483 -0500
 | ||||
| +++ b/localedata/SUPPORTED	2021-11-17 17:21:16.418188595 -0500
 | ||||
| @@ -159,6 +159,7 @@ en_SG/ISO-8859-1 \
 | ||||
|  en_US.UTF-8/UTF-8 \ | ||||
|  en_US/ISO-8859-1 \ | ||||
|  en_US.ISO-8859-15/ISO-8859-15 \ | ||||
| +en_US@ampm.UTF-8/UTF-8 \
 | ||||
|  en_ZA.UTF-8/UTF-8 \ | ||||
|  en_ZA/ISO-8859-1 \ | ||||
|  en_ZM/UTF-8 \ | ||||
							
								
								
									
										92
									
								
								SOURCES/glibc-rh2007327-1.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								SOURCES/glibc-rh2007327-1.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | ||||
| commit 28c30a6232aa9a54783c146590498a061fc0112a | ||||
| Author: Samuel Thibault <samuel.thibault@ens-lyon.org> | ||||
| Date:   Sun Feb 9 19:50:21 2020 +0000 | ||||
| 
 | ||||
|     pthread: Move most once tests from nptl to sysdeps/pthread | ||||
|      | ||||
|     So they can be checked with htl too. | ||||
| 
 | ||||
| # Conflicts: | ||||
| #	sysdeps/pthread/Makefile | ||||
| #	(Moved only the tests in this commit which subsequently | ||||
| #	 needed for the pthread_once fix) | ||||
| 
 | ||||
| diff --git a/nptl/Makefile b/nptl/Makefile
 | ||||
| index b14de3ffb330c10b..dcf3868869767015 100644
 | ||||
| --- a/nptl/Makefile
 | ||||
| +++ b/nptl/Makefile
 | ||||
| @@ -260,7 +260,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
 | ||||
|  	tst-rwlock4 tst-rwlock5 tst-rwlock6 tst-rwlock7 tst-rwlock8 \ | ||||
|  	tst-rwlock9 tst-rwlock10 tst-rwlock11 tst-rwlock12 tst-rwlock13 \ | ||||
|  	tst-rwlock14 tst-rwlock15 tst-rwlock16 tst-rwlock17 tst-rwlock18 \ | ||||
| -	tst-once1 tst-once2 tst-once3 tst-once4 tst-once5 \
 | ||||
| +	tst-once5 \
 | ||||
|  	tst-key1 tst-key2 tst-key3 tst-key4 \ | ||||
|  	tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \ | ||||
|  	tst-sem8 tst-sem9 tst-sem10 tst-sem14 \ | ||||
| @@ -384,8 +384,7 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \
 | ||||
|  	 tst-cancelx6 tst-cancelx7 tst-cancelx8 tst-cancelx9 tst-cancelx10 \ | ||||
|  	 tst-cancelx11 tst-cancelx12 tst-cancelx13 tst-cancelx14 tst-cancelx15 \ | ||||
|  	 tst-cancelx16 tst-cancelx17 tst-cancelx18 tst-cancelx20 tst-cancelx21 \ | ||||
| -	 tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 \
 | ||||
| -	 tst-oncex3 tst-oncex4
 | ||||
| +	 tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4
 | ||||
|  ifeq ($(build-shared),yes) | ||||
|  tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder \ | ||||
|  	 tst-audit-threads | ||||
| @@ -525,8 +524,6 @@ CFLAGS-tst-cleanupx2.c += -fexceptions
 | ||||
|  CFLAGS-tst-cleanupx3.c += -fexceptions | ||||
|  CFLAGS-tst-cleanupx4.c += -fexceptions | ||||
|  CFLAGS-tst-cleanupx4aux.c += -fexceptions | ||||
| -CFLAGS-tst-oncex3.c += -fexceptions
 | ||||
| -CFLAGS-tst-oncex4.c += -fexceptions
 | ||||
|  CFLAGS-tst-align.c += $(stack-align-test-flags) | ||||
|  CFLAGS-tst-align3.c += $(stack-align-test-flags) | ||||
|  CFLAGS-tst-initializers1.c += -W -Wall -Werror | ||||
| diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
 | ||||
| index 98a92f8d6bb119ba..14ef04247cb84ad3 100644
 | ||||
| --- a/sysdeps/pthread/Makefile
 | ||||
| +++ b/sysdeps/pthread/Makefile
 | ||||
| @@ -33,11 +33,18 @@ endif
 | ||||
|   | ||||
|  tst-create1mod.so-no-z-defs = yes | ||||
|   | ||||
| +tests += tst-once1 tst-once2 tst-once3 tst-once4
 | ||||
| +
 | ||||
| +tests += tst-oncex3 tst-oncex4
 | ||||
| +
 | ||||
|  ifeq ($(build-shared),yes) | ||||
|  # Build all the modules even when not actually running test programs. | ||||
|  tests: $(test-modules) | ||||
|  endif | ||||
|   | ||||
| +CFLAGS-tst-oncex3.c += -fexceptions
 | ||||
| +CFLAGS-tst-oncex4.c += -fexceptions
 | ||||
| +
 | ||||
|  modules-names += tst-create1mod | ||||
|  test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) | ||||
|   | ||||
| diff --git a/nptl/tst-once1.c b/sysdeps/pthread/tst-once1.c
 | ||||
| similarity index 100% | ||||
| rename from nptl/tst-once1.c | ||||
| rename to sysdeps/pthread/tst-once1.c | ||||
| diff --git a/nptl/tst-once2.c b/sysdeps/pthread/tst-once2.c
 | ||||
| similarity index 100% | ||||
| rename from nptl/tst-once2.c | ||||
| rename to sysdeps/pthread/tst-once2.c | ||||
| diff --git a/nptl/tst-once3.c b/sysdeps/pthread/tst-once3.c
 | ||||
| similarity index 100% | ||||
| rename from nptl/tst-once3.c | ||||
| rename to sysdeps/pthread/tst-once3.c | ||||
| diff --git a/nptl/tst-once4.c b/sysdeps/pthread/tst-once4.c
 | ||||
| similarity index 100% | ||||
| rename from nptl/tst-once4.c | ||||
| rename to sysdeps/pthread/tst-once4.c | ||||
| diff --git a/nptl/tst-oncex3.c b/sysdeps/pthread/tst-oncex3.c
 | ||||
| similarity index 100% | ||||
| rename from nptl/tst-oncex3.c | ||||
| rename to sysdeps/pthread/tst-oncex3.c | ||||
| diff --git a/nptl/tst-oncex4.c b/sysdeps/pthread/tst-oncex4.c
 | ||||
| similarity index 100% | ||||
| rename from nptl/tst-oncex4.c | ||||
| rename to sysdeps/pthread/tst-oncex4.c | ||||
							
								
								
									
										200
									
								
								SOURCES/glibc-rh2007327-2.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								SOURCES/glibc-rh2007327-2.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,200 @@ | ||||
| commit f0419e6a10740a672b28e112c409ae24f5e890ab | ||||
| Author: Jakub Jelinek <jakub@redhat.com> | ||||
| Date:   Thu Mar 4 15:15:33 2021 +0100 | ||||
| 
 | ||||
|     [PATCH] pthread_once hangs when init routine throws an exception [BZ #18435] | ||||
|      | ||||
|     This is another attempt at making pthread_once handle throwing exceptions | ||||
|     from the init routine callback.  As the new testcases show, just switching | ||||
|     to the cleanup attribute based cleanup does fix the tst-once5 test, but | ||||
|     breaks the new tst-oncey3 test.  That is because when throwing exceptions, | ||||
|     only the unwind info registered cleanups (i.e. C++ destructors or cleanup | ||||
|     attribute), when cancelling threads and there has been unwind info from the | ||||
|     cancellation point up to whatever needs cleanup both unwind info registered | ||||
|     cleanups and THREAD_SETMEM (self, cleanup, ...) registered cleanups are | ||||
|     invoked, but once we hit some frame with no unwind info, only the | ||||
|     THREAD_SETMEM (self, cleanup, ...) registered cleanups are invoked. | ||||
|     So, to stay fully backwards compatible (allow init routines without | ||||
|     unwind info which encounter cancellation points) and handle exception throwing | ||||
|     we actually need to register the pthread_once cleanups in both unwind info | ||||
|     and in the THREAD_SETMEM (self, cleanup, ...) way. | ||||
|     If an exception is thrown, only the former will happen and we in that case | ||||
|     need to also unregister the THREAD_SETMEM (self, cleanup, ...) registered | ||||
|     handler, because otherwise after catching the exception the user code could | ||||
|     call deeper into the stack some cancellation point, get cancelled and then | ||||
|     a stale cleanup handler would clobber stack and probably crash. | ||||
|     If a thread calling init routine is cancelled and unwind info ends before | ||||
|     the pthread_once frame, it will be cleaned up through self->cleanup as | ||||
|     before.  And if unwind info is present, unwind_stop first calls the | ||||
|     self->cleanup registered handler for the frame, then it will call the | ||||
|     unwind info registered handler but that will already see __do_it == 0 | ||||
|     and do nothing. | ||||
| 
 | ||||
| # Conflicts: | ||||
| #	nptl/Makefile | ||||
| #	(The usual cleanups because they don't match.) | ||||
| #	sysdeps/pthread/Makefile | ||||
| #	(The usual cleanups because all the other tests aren't moved.) | ||||
| 
 | ||||
| diff --git a/nptl/Makefile b/nptl/Makefile
 | ||||
| index dcf3868869767015..70a3be23ecfcd9c9 100644
 | ||||
| --- a/nptl/Makefile
 | ||||
| +++ b/nptl/Makefile
 | ||||
| @@ -334,10 +334,6 @@ xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \
 | ||||
|  	tst-mutexpp1 tst-mutexpp6 tst-mutexpp10 | ||||
|  test-srcs = tst-oddstacklimit | ||||
|   | ||||
| -# Test expected to fail on most targets (except x86_64) due to bug
 | ||||
| -# 18435 - pthread_once hangs when init routine throws an exception.
 | ||||
| -test-xfail-tst-once5 = yes
 | ||||
| -
 | ||||
|  # Files which must not be linked with libpthread. | ||||
|  tests-nolibpthread = tst-unload | ||||
|   | ||||
| diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
 | ||||
| index a2d48b2015cd385c..7ddc166cf32414c4 100644
 | ||||
| --- a/nptl/pthreadP.h
 | ||||
| +++ b/nptl/pthreadP.h
 | ||||
| @@ -571,6 +571,67 @@ extern void __pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
 | ||||
|  # undef pthread_cleanup_pop | ||||
|  # define pthread_cleanup_pop(execute)                   \ | ||||
|    __pthread_cleanup_pop (&_buffer, (execute)); } | ||||
| +
 | ||||
| +# if defined __EXCEPTIONS && !defined __cplusplus
 | ||||
| +/* Structure to hold the cleanup handler information.  */
 | ||||
| +struct __pthread_cleanup_combined_frame
 | ||||
| +{
 | ||||
| +  void (*__cancel_routine) (void *);
 | ||||
| +  void *__cancel_arg;
 | ||||
| +  int __do_it;
 | ||||
| +  struct _pthread_cleanup_buffer __buffer;
 | ||||
| +};
 | ||||
| +
 | ||||
| +/* Special cleanup macros which register cleanup both using
 | ||||
| +   __pthread_cleanup_{push,pop} and using cleanup attribute.  This is needed
 | ||||
| +   for pthread_once, so that it supports both throwing exceptions from the
 | ||||
| +   pthread_once callback (only cleanup attribute works there) and cancellation
 | ||||
| +   of the thread running the callback if the callback or some routines it
 | ||||
| +   calls don't have unwind information.  */
 | ||||
| +
 | ||||
| +static __always_inline void
 | ||||
| +__pthread_cleanup_combined_routine (struct __pthread_cleanup_combined_frame
 | ||||
| +				    *__frame)
 | ||||
| +{
 | ||||
| +  if (__frame->__do_it)
 | ||||
| +    {
 | ||||
| +      __frame->__cancel_routine (__frame->__cancel_arg);
 | ||||
| +      __frame->__do_it = 0;
 | ||||
| +      __pthread_cleanup_pop (&__frame->__buffer, 0);
 | ||||
| +    }
 | ||||
| +}
 | ||||
| +
 | ||||
| +static inline void
 | ||||
| +__pthread_cleanup_combined_routine_voidptr (void *__arg)
 | ||||
| +{
 | ||||
| +  struct __pthread_cleanup_combined_frame *__frame
 | ||||
| +    = (struct __pthread_cleanup_combined_frame *) __arg;
 | ||||
| +  if (__frame->__do_it)
 | ||||
| +    {
 | ||||
| +      __frame->__cancel_routine (__frame->__cancel_arg);
 | ||||
| +      __frame->__do_it = 0;
 | ||||
| +    }
 | ||||
| +}
 | ||||
| +
 | ||||
| +#  define pthread_cleanup_combined_push(routine, arg) \
 | ||||
| +  do {									      \
 | ||||
| +    void (*__cancel_routine) (void *) = (routine);			      \
 | ||||
| +    struct __pthread_cleanup_combined_frame __clframe			      \
 | ||||
| +      __attribute__ ((__cleanup__ (__pthread_cleanup_combined_routine)))      \
 | ||||
| +      = { .__cancel_routine = __cancel_routine, .__cancel_arg = (arg),	      \
 | ||||
| +	  .__do_it = 1 };						      \
 | ||||
| +    __pthread_cleanup_push (&__clframe.__buffer,			      \
 | ||||
| +			    __pthread_cleanup_combined_routine_voidptr,	      \
 | ||||
| +			    &__clframe);
 | ||||
| +
 | ||||
| +#  define pthread_cleanup_combined_pop(execute) \
 | ||||
| +    __pthread_cleanup_pop (&__clframe.__buffer, 0);			      \
 | ||||
| +    __clframe.__do_it = 0;						      \
 | ||||
| +    if (execute)							      \
 | ||||
| +      __cancel_routine (__clframe.__cancel_arg);			      \
 | ||||
| +  } while (0)
 | ||||
| +
 | ||||
| +# endif
 | ||||
|  #endif | ||||
|   | ||||
|  extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, | ||||
| diff --git a/nptl/pthread_once.c b/nptl/pthread_once.c
 | ||||
| index 1653226286dc3539..45e965e8743d9412 100644
 | ||||
| --- a/nptl/pthread_once.c
 | ||||
| +++ b/nptl/pthread_once.c
 | ||||
| @@ -111,11 +111,11 @@ __pthread_once_slow (pthread_once_t *once_control, void (*init_routine) (void))
 | ||||
|        /* This thread is the first here.  Do the initialization. | ||||
|  	 Register a cleanup handler so that in case the thread gets | ||||
|  	 interrupted the initialization can be restarted.  */ | ||||
| -      pthread_cleanup_push (clear_once_control, once_control);
 | ||||
| +      pthread_cleanup_combined_push (clear_once_control, once_control);
 | ||||
|   | ||||
|        init_routine (); | ||||
|   | ||||
| -      pthread_cleanup_pop (0);
 | ||||
| +      pthread_cleanup_combined_pop (0);
 | ||||
|   | ||||
|   | ||||
|        /* Mark *once_control as having finished the initialization.  We need | ||||
| diff --git a/nptl/tst-once5.cc b/nptl/tst-once5.cc
 | ||||
| index d232266c3ace89d9..dda18e610c9114bc 100644
 | ||||
| --- a/nptl/tst-once5.cc
 | ||||
| +++ b/nptl/tst-once5.cc
 | ||||
| @@ -59,7 +59,7 @@ do_test (void)
 | ||||
|                 " throwing an exception", stderr); | ||||
|      } | ||||
|      catch (OnceException) { | ||||
| -      if (1 < niter)
 | ||||
| +      if (niter > 1)
 | ||||
|          fputs ("pthread_once unexpectedly threw", stderr); | ||||
|        result = 0; | ||||
|      } | ||||
| @@ -75,7 +75,5 @@ do_test (void)
 | ||||
|    return result; | ||||
|  } | ||||
|   | ||||
| -// The test currently hangs and is XFAILed.  Reduce the timeout.
 | ||||
| -#define TIMEOUT 1
 | ||||
|  #define TEST_FUNCTION do_test () | ||||
|  #include "../test-skeleton.c" | ||||
| diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
 | ||||
| index 14ef04247cb84ad3..80a71f3f9f0e72ae 100644
 | ||||
| --- a/sysdeps/pthread/Makefile
 | ||||
| +++ b/sysdeps/pthread/Makefile
 | ||||
| @@ -35,7 +35,7 @@ tst-create1mod.so-no-z-defs = yes
 | ||||
|   | ||||
|  tests += tst-once1 tst-once2 tst-once3 tst-once4 | ||||
|   | ||||
| -tests += tst-oncex3 tst-oncex4
 | ||||
| +tests += tst-oncex3 tst-oncex4 tst-oncey3 tst-oncey4
 | ||||
|   | ||||
|  ifeq ($(build-shared),yes) | ||||
|  # Build all the modules even when not actually running test programs. | ||||
| @@ -44,6 +44,8 @@ endif
 | ||||
|   | ||||
|  CFLAGS-tst-oncex3.c += -fexceptions | ||||
|  CFLAGS-tst-oncex4.c += -fexceptions | ||||
| +CFLAGS-tst-oncey3.c += -fno-exceptions -fno-asynchronous-unwind-tables
 | ||||
| +CFLAGS-tst-oncey4.c += -fno-exceptions -fno-asynchronous-unwind-tables
 | ||||
|   | ||||
|  modules-names += tst-create1mod | ||||
|  test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) | ||||
| diff --git a/sysdeps/pthread/tst-oncey3.c b/sysdeps/pthread/tst-oncey3.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..08225b88dc06b979
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/pthread/tst-oncey3.c
 | ||||
| @@ -0,0 +1 @@
 | ||||
| +#include "tst-once3.c"
 | ||||
| diff --git a/sysdeps/pthread/tst-oncey4.c b/sysdeps/pthread/tst-oncey4.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..9b4d98f3f13c265a
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/pthread/tst-oncey4.c
 | ||||
| @@ -0,0 +1 @@
 | ||||
| +#include "tst-once4.c"
 | ||||
							
								
								
									
										40
									
								
								SOURCES/glibc-rh2021452.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								SOURCES/glibc-rh2021452.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| commit 98966749f2b418825ff2ea496a0ee89fe63d2cc8 | ||||
| Author: Florian Weimer <fweimer@redhat.com> | ||||
| Date:   Wed Nov 10 15:21:37 2021 +0100 | ||||
| 
 | ||||
|     s390: Use long branches across object boundaries (jgh instead of jh) | ||||
|      | ||||
|     Depending on the layout chosen by the linker, the 16-bit displacement | ||||
|     of the jh instruction is insufficient to reach the target label. | ||||
|      | ||||
|     Analysis of the linker failure was carried out by Nick Clifton. | ||||
|      | ||||
|     Reviewed-by: Carlos O'Donell <carlos@redhat.com> | ||||
|     Reviewed-by: Stefan Liebler <stli@linux.ibm.com> | ||||
| 
 | ||||
| diff --git a/sysdeps/s390/memmem-arch13.S b/sysdeps/s390/memmem-arch13.S
 | ||||
| index b59d60acf0f6aaa0..4faede0cd2f942e3 100644
 | ||||
| --- a/sysdeps/s390/memmem-arch13.S
 | ||||
| +++ b/sysdeps/s390/memmem-arch13.S
 | ||||
| @@ -41,7 +41,7 @@ ENTRY(MEMMEM_ARCH13)
 | ||||
|  #  error The arch13 variant of memmem needs the z13 variant of memmem! | ||||
|  # endif | ||||
|  	clgfi	%r5,9 | ||||
| -	jh	MEMMEM_Z13
 | ||||
| +	jgh	MEMMEM_Z13
 | ||||
|   | ||||
|  	aghik	%r0,%r5,-1		/* vll needs highest index.  */ | ||||
|  	bc	4,0(%r14)		/* cc==1: return if needle-len == 0.  */ | ||||
| diff --git a/sysdeps/s390/strstr-arch13.S b/sysdeps/s390/strstr-arch13.S
 | ||||
| index faa969849e09c2e1..ffc34c2523ce635a 100644
 | ||||
| --- a/sysdeps/s390/strstr-arch13.S
 | ||||
| +++ b/sysdeps/s390/strstr-arch13.S
 | ||||
| @@ -49,7 +49,7 @@ ENTRY(STRSTR_ARCH13)
 | ||||
|  #  error The arch13 variant of strstr needs the z13 variant of strstr! | ||||
|  # endif | ||||
|  	clgfi	%r4,9 | ||||
| -	jh	STRSTR_Z13
 | ||||
| +	jgh	STRSTR_Z13
 | ||||
|   | ||||
|  	/* In case of a partial match, the vstrs instruction returns the index | ||||
|  	   of the partial match in a vector-register.  Then we have to | ||||
							
								
								
									
										304
									
								
								SOURCES/glibc-rh2023420-1.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								SOURCES/glibc-rh2023420-1.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,304 @@ | ||||
| commit 86f65dffc2396d408beb628f1cad2b8f63e197bd | ||||
| Author: H.J. Lu <hjl.tools@gmail.com> | ||||
| Date:   Sun Jul 12 06:04:53 2020 -0700 | ||||
| 
 | ||||
|     ld.so: Add --list-tunables to print tunable values | ||||
|      | ||||
|     Pass --list-tunables to ld.so to print tunables with min and max values. | ||||
|      | ||||
|     Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org> | ||||
| 
 | ||||
| Conflicts: | ||||
| 	elf/Makefile | ||||
| 	  (different backporting order) | ||||
| 
 | ||||
| diff --git a/elf/Makefile b/elf/Makefile
 | ||||
| index 3e71939d3234c4c3..aa65ec59f143bccf 100644
 | ||||
| --- a/elf/Makefile
 | ||||
| +++ b/elf/Makefile
 | ||||
| @@ -44,6 +44,10 @@ dl-routines += dl-tunables
 | ||||
|  tunables-type = $(addprefix TUNABLES_FRONTEND_,$(have-tunables)) | ||||
|  CPPFLAGS-dl-tunables.c += -DTUNABLES_FRONTEND=$(tunables-type) | ||||
|   | ||||
| +ifeq (yesyes,$(build-shared)$(run-built-tests))
 | ||||
| +tests-special += $(objpfx)list-tunables.out
 | ||||
| +endif
 | ||||
| +
 | ||||
|  # Make sure that the compiler does not insert any library calls in tunables | ||||
|  # code paths. | ||||
|  ifeq (yes,$(have-loop-to-function)) | ||||
| @@ -1825,6 +1829,13 @@ $(objpfx)tst-glibc-hwcaps-mask.out: \
 | ||||
|  # tst-glibc-hwcaps-cache. | ||||
|  $(objpfx)tst-glibc-hwcaps-cache.out: $(objpfx)tst-glibc-hwcaps | ||||
|   | ||||
| +$(objpfx)list-tunables.out: tst-rtld-list-tunables.sh $(objpfx)ld.so
 | ||||
| +	$(SHELL) $< $(objpfx)ld.so '$(test-wrapper-env)' \
 | ||||
| +	    '$(run_program_env)' > $(objpfx)/tst-rtld-list-tunables.out
 | ||||
| +	cmp tst-rtld-list-tunables.exp \
 | ||||
| +	    $(objpfx)/tst-rtld-list-tunables.out > $@; \
 | ||||
| +	$(evaluate-test)
 | ||||
| +
 | ||||
|  tst-dst-static-ENV = LD_LIBRARY_PATH='$$ORIGIN' | ||||
|   | ||||
|  $(objpfx)tst-rtld-help.out: $(objpfx)ld.so | ||||
| diff --git a/elf/dl-main.h b/elf/dl-main.h
 | ||||
| index 566713a0d10cfdb7..9e7b51d8f010e904 100644
 | ||||
| --- a/elf/dl-main.h
 | ||||
| +++ b/elf/dl-main.h
 | ||||
| @@ -63,7 +63,7 @@ struct audit_list
 | ||||
|  enum rtld_mode | ||||
|    { | ||||
|      rtld_mode_normal, rtld_mode_list, rtld_mode_verify, rtld_mode_trace, | ||||
| -    rtld_mode_help,
 | ||||
| +    rtld_mode_list_tunables, rtld_mode_help,
 | ||||
|    }; | ||||
|   | ||||
|  /* Aggregated state information extracted from environment variables | ||||
| diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
 | ||||
| index bbc3679e3564a766..3c84809d44381241 100644
 | ||||
| --- a/elf/dl-tunables.c
 | ||||
| +++ b/elf/dl-tunables.c
 | ||||
| @@ -26,6 +26,7 @@
 | ||||
|  #include <sysdep.h> | ||||
|  #include <fcntl.h> | ||||
|  #include <ldsodefs.h> | ||||
| +#include <array_length.h>
 | ||||
|   | ||||
|  #define TUNABLES_INTERNAL 1 | ||||
|  #include "dl-tunables.h" | ||||
| @@ -359,6 +360,48 @@ __tunables_init (char **envp)
 | ||||
|      } | ||||
|  } | ||||
|   | ||||
| +void
 | ||||
| +__tunables_print (void)
 | ||||
| +{
 | ||||
| +  for (int i = 0; i < array_length (tunable_list); i++)
 | ||||
| +    {
 | ||||
| +      const tunable_t *cur = &tunable_list[i];
 | ||||
| +      if (cur->type.type_code == TUNABLE_TYPE_STRING
 | ||||
| +	  && cur->val.strval == NULL)
 | ||||
| +	_dl_printf ("%s:\n", cur->name);
 | ||||
| +      else
 | ||||
| +	{
 | ||||
| +	  _dl_printf ("%s: ", cur->name);
 | ||||
| +	  switch (cur->type.type_code)
 | ||||
| +	    {
 | ||||
| +	    case TUNABLE_TYPE_INT_32:
 | ||||
| +	      _dl_printf ("%d (min: %d, max: %d)\n",
 | ||||
| +			  (int) cur->val.numval,
 | ||||
| +			  (int) cur->type.min,
 | ||||
| +			  (int) cur->type.max);
 | ||||
| +	      break;
 | ||||
| +	    case TUNABLE_TYPE_UINT_64:
 | ||||
| +	      _dl_printf ("0x%lx (min: 0x%lx, max: 0x%lx)\n",
 | ||||
| +			  (long int) cur->val.numval,
 | ||||
| +			  (long int) cur->type.min,
 | ||||
| +			  (long int) cur->type.max);
 | ||||
| +	      break;
 | ||||
| +	    case TUNABLE_TYPE_SIZE_T:
 | ||||
| +	      _dl_printf ("0x%Zx (min: 0x%Zx, max: 0x%Zx)\n",
 | ||||
| +			  (size_t) cur->val.numval,
 | ||||
| +			  (size_t) cur->type.min,
 | ||||
| +			  (size_t) cur->type.max);
 | ||||
| +	      break;
 | ||||
| +	    case TUNABLE_TYPE_STRING:
 | ||||
| +	      _dl_printf ("%s\n", cur->val.strval);
 | ||||
| +	      break;
 | ||||
| +	    default:
 | ||||
| +	      __builtin_unreachable ();
 | ||||
| +	    }
 | ||||
| +	}
 | ||||
| +    }
 | ||||
| +}
 | ||||
| +
 | ||||
|  /* Set the tunable value.  This is called by the module that the tunable exists | ||||
|     in. */ | ||||
|  void | ||||
| diff --git a/elf/dl-tunables.h b/elf/dl-tunables.h
 | ||||
| index 7f181f3316cd9fc1..f4f2cfaeb9828599 100644
 | ||||
| --- a/elf/dl-tunables.h
 | ||||
| +++ b/elf/dl-tunables.h
 | ||||
| @@ -69,9 +69,11 @@ typedef struct _tunable tunable_t;
 | ||||
|  # include "dl-tunable-list.h" | ||||
|   | ||||
|  extern void __tunables_init (char **); | ||||
| +extern void __tunables_print (void);
 | ||||
|  extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t); | ||||
|  extern void __tunable_set_val (tunable_id_t, void *); | ||||
|  rtld_hidden_proto (__tunables_init) | ||||
| +rtld_hidden_proto (__tunables_print)
 | ||||
|  rtld_hidden_proto (__tunable_get_val) | ||||
|   | ||||
|  /* Define TUNABLE_GET and TUNABLE_SET in short form if TOP_NAMESPACE and | ||||
| diff --git a/elf/dl-usage.c b/elf/dl-usage.c
 | ||||
| index e22a9c39427187d1..908b4894b3014b2d 100644
 | ||||
| --- a/elf/dl-usage.c
 | ||||
| +++ b/elf/dl-usage.c
 | ||||
| @@ -255,7 +255,12 @@ setting environment variables (which would be inherited by subprocesses).\n\
 | ||||
|                          in LIST\n\ | ||||
|    --audit LIST          use objects named in LIST as auditors\n\ | ||||
|    --preload LIST        preload objects named in LIST\n\ | ||||
| -  --argv0 STRING        set argv[0] to STRING before running\n\
 | ||||
| +  --argv0 STRING        set argv[0] to STRING before running\n"
 | ||||
| +#if HAVE_TUNABLES
 | ||||
| +"\
 | ||||
| +  --list-tunables       list all tunables with minimum and maximum values\n"
 | ||||
| +#endif
 | ||||
| +"\
 | ||||
|    --help                display this help and exit\n\ | ||||
|    --version             output version information and exit\n\ | ||||
|  \n\ | ||||
| diff --git a/elf/rtld.c b/elf/rtld.c
 | ||||
| index 9e09896da078274d..54b621ec5ca014fa 100644
 | ||||
| --- a/elf/rtld.c
 | ||||
| +++ b/elf/rtld.c
 | ||||
| @@ -47,6 +47,7 @@
 | ||||
|  #include <libc-early-init.h> | ||||
|  #include <dl-main.h> | ||||
|  #include <gnu/lib-names.h> | ||||
| +#include <dl-tunables.h>
 | ||||
|   | ||||
|  #include <assert.h> | ||||
|   | ||||
| @@ -1262,6 +1263,16 @@ dl_main (const ElfW(Phdr) *phdr,
 | ||||
|  	    _dl_argc -= 2; | ||||
|  	    _dl_argv += 2; | ||||
|  	  } | ||||
| +#if HAVE_TUNABLES
 | ||||
| +	else if (! strcmp (_dl_argv[1], "--list-tunables"))
 | ||||
| +	  {
 | ||||
| +	    state.mode = rtld_mode_list_tunables;
 | ||||
| +
 | ||||
| +	    ++_dl_skip_args;
 | ||||
| +	    --_dl_argc;
 | ||||
| +	    ++_dl_argv;
 | ||||
| +	  }
 | ||||
| +#endif
 | ||||
|  	else if (strcmp (_dl_argv[1], "--help") == 0) | ||||
|  	  { | ||||
|  	    state.mode = rtld_mode_help; | ||||
| @@ -1282,6 +1293,14 @@ dl_main (const ElfW(Phdr) *phdr,
 | ||||
|  	else | ||||
|  	  break; | ||||
|   | ||||
| +#if HAVE_TUNABLES
 | ||||
| +      if (__glibc_unlikely (state.mode == rtld_mode_list_tunables))
 | ||||
| +	{
 | ||||
| +	  __tunables_print ();
 | ||||
| +	  _exit (0);
 | ||||
| +	}
 | ||||
| +#endif
 | ||||
| +
 | ||||
|        /* If we have no further argument the program was called incorrectly. | ||||
|  	 Grant the user some education.  */ | ||||
|        if (_dl_argc < 2) | ||||
| diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..4f3f7ee4e30a2b42
 | ||||
| --- /dev/null
 | ||||
| +++ b/elf/tst-rtld-list-tunables.exp
 | ||||
| @@ -0,0 +1,14 @@
 | ||||
| +glibc.malloc.arena_max: 0x0 (min: 0x1, max: 0x[f]+)
 | ||||
| +glibc.malloc.arena_test: 0x0 (min: 0x1, max: 0x[f]+)
 | ||||
| +glibc.malloc.check: 0 (min: 0, max: 3)
 | ||||
| +glibc.malloc.mmap_max: 0 (min: -2147483648, max: 2147483647)
 | ||||
| +glibc.malloc.mmap_threshold: 0x0 (min: 0x0, max: 0x[f]+)
 | ||||
| +glibc.malloc.mxfast: 0x0 (min: 0x0, max: 0x[f]+)
 | ||||
| +glibc.malloc.perturb: 0 (min: 0, max: 255)
 | ||||
| +glibc.malloc.tcache_count: 0x0 (min: 0x0, max: 0x[f]+)
 | ||||
| +glibc.malloc.tcache_max: 0x0 (min: 0x0, max: 0x[f]+)
 | ||||
| +glibc.malloc.tcache_unsorted_limit: 0x0 (min: 0x0, max: 0x[f]+)
 | ||||
| +glibc.malloc.top_pad: 0x0 (min: 0x0, max: 0x[f]+)
 | ||||
| +glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0x[f]+)
 | ||||
| +glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10)
 | ||||
| +glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0x[f]+)
 | ||||
| diff --git a/elf/tst-rtld-list-tunables.sh b/elf/tst-rtld-list-tunables.sh
 | ||||
| new file mode 100755 | ||||
| index 0000000000000000..e7bbdde94952b872
 | ||||
| --- /dev/null
 | ||||
| +++ b/elf/tst-rtld-list-tunables.sh
 | ||||
| @@ -0,0 +1,34 @@
 | ||||
| +#!/bin/sh
 | ||||
| +# Test for --list-tunables option ld.so.
 | ||||
| +# Copyright (C) 2021 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/>.
 | ||||
| +
 | ||||
| +set -e
 | ||||
| +
 | ||||
| +rtld=$1
 | ||||
| +test_wrapper_env=$2
 | ||||
| +run_program_env=$3
 | ||||
| +
 | ||||
| +LC_ALL=C
 | ||||
| +export LC_ALL
 | ||||
| +
 | ||||
| +${test_wrapper_env} \
 | ||||
| +${run_program_env} \
 | ||||
| +$rtld --list-tunables \
 | ||||
| +| sort -u \
 | ||||
| +| egrep "(rtld|malloc)" \
 | ||||
| +| sed -e "s/0xf\+/0x[f]+/"
 | ||||
| diff --git a/manual/tunables.texi b/manual/tunables.texi
 | ||||
| index 07887981748bc44b..43272cf885d1e3e6 100644
 | ||||
| --- a/manual/tunables.texi
 | ||||
| +++ b/manual/tunables.texi
 | ||||
| @@ -28,6 +28,44 @@ Finally, the set of tunables available may vary between distributions as
 | ||||
|  the tunables feature allows distributions to add their own tunables under | ||||
|  their own namespace. | ||||
|   | ||||
| +Passing @option{--list-tunables} to the dynamic loader to print all
 | ||||
| +tunables with minimum and maximum values:
 | ||||
| +
 | ||||
| +@example
 | ||||
| +$ /lib64/ld-linux-x86-64.so.2 --list-tunables
 | ||||
| +glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10)
 | ||||
| +glibc.elision.skip_lock_after_retries: 3 (min: -2147483648, max: 2147483647)
 | ||||
| +glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0xffffffffffffffff)
 | ||||
| +glibc.malloc.perturb: 0 (min: 0, max: 255)
 | ||||
| +glibc.cpu.x86_shared_cache_size: 0x100000 (min: 0x0, max: 0xffffffffffffffff)
 | ||||
| +glibc.mem.tagging: 0 (min: 0, max: 255)
 | ||||
| +glibc.elision.tries: 3 (min: -2147483648, max: 2147483647)
 | ||||
| +glibc.elision.enable: 0 (min: 0, max: 1)
 | ||||
| +glibc.cpu.x86_rep_movsb_threshold: 0x1000 (min: 0x100, max: 0xffffffffffffffff)
 | ||||
| +glibc.malloc.mxfast: 0x0 (min: 0x0, max: 0xffffffffffffffff)
 | ||||
| +glibc.elision.skip_lock_busy: 3 (min: -2147483648, max: 2147483647)
 | ||||
| +glibc.malloc.top_pad: 0x0 (min: 0x0, max: 0xffffffffffffffff)
 | ||||
| +glibc.cpu.x86_rep_stosb_threshold: 0x800 (min: 0x1, max: 0xffffffffffffffff)
 | ||||
| +glibc.cpu.x86_non_temporal_threshold: 0xc0000 (min: 0x0, max: 0xffffffffffffffff)
 | ||||
| +glibc.cpu.x86_shstk:
 | ||||
| +glibc.cpu.hwcap_mask: 0x6 (min: 0x0, max: 0xffffffffffffffff)
 | ||||
| +glibc.malloc.mmap_max: 0 (min: -2147483648, max: 2147483647)
 | ||||
| +glibc.elision.skip_trylock_internal_abort: 3 (min: -2147483648, max: 2147483647)
 | ||||
| +glibc.malloc.tcache_unsorted_limit: 0x0 (min: 0x0, max: 0xffffffffffffffff)
 | ||||
| +glibc.cpu.x86_ibt:
 | ||||
| +glibc.cpu.hwcaps:
 | ||||
| +glibc.elision.skip_lock_internal_abort: 3 (min: -2147483648, max: 2147483647)
 | ||||
| +glibc.malloc.arena_max: 0x0 (min: 0x1, max: 0xffffffffffffffff)
 | ||||
| +glibc.malloc.mmap_threshold: 0x0 (min: 0x0, max: 0xffffffffffffffff)
 | ||||
| +glibc.cpu.x86_data_cache_size: 0x8000 (min: 0x0, max: 0xffffffffffffffff)
 | ||||
| +glibc.malloc.tcache_count: 0x0 (min: 0x0, max: 0xffffffffffffffff)
 | ||||
| +glibc.malloc.arena_test: 0x0 (min: 0x1, max: 0xffffffffffffffff)
 | ||||
| +glibc.pthread.mutex_spin_count: 100 (min: 0, max: 32767)
 | ||||
| +glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0xffffffffffffffff)
 | ||||
| +glibc.malloc.tcache_max: 0x0 (min: 0x0, max: 0xffffffffffffffff)
 | ||||
| +glibc.malloc.check: 0 (min: 0, max: 3)
 | ||||
| +@end example
 | ||||
| +
 | ||||
|  @menu | ||||
|  * Tunable names::  The structure of a tunable name | ||||
|  * Memory Allocation Tunables::  Tunables in the memory allocation subsystem | ||||
							
								
								
									
										30
									
								
								SOURCES/glibc-rh2023420-2.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								SOURCES/glibc-rh2023420-2.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| commit d2d12c7a988a9a04aec23b5e4af549db61b0a005 | ||||
| Author: H.J. Lu <hjl.tools@gmail.com> | ||||
| Date:   Tue Feb 2 09:31:56 2021 -0800 | ||||
| 
 | ||||
|     tst-rtld-list-tunables.sh: Unset glibc tunables | ||||
|      | ||||
|     Unset glibc tunables and their aliases for --list-tunables test. | ||||
| 
 | ||||
| diff --git a/elf/tst-rtld-list-tunables.sh b/elf/tst-rtld-list-tunables.sh
 | ||||
| index e7bbdde94952b872..78f4ed2ebbd3db2c 100755
 | ||||
| --- a/elf/tst-rtld-list-tunables.sh
 | ||||
| +++ b/elf/tst-rtld-list-tunables.sh
 | ||||
| @@ -26,6 +26,17 @@ run_program_env=$3
 | ||||
|  LC_ALL=C | ||||
|  export LC_ALL | ||||
|   | ||||
| +# Unset tunables and their aliases.
 | ||||
| +GLIBC_TUNABLES=
 | ||||
| +MALLOC_ARENA_MAX=
 | ||||
| +MALLOC_ARENA_TEST=
 | ||||
| +MALLOC_CHECK_=
 | ||||
| +MALLOC_MMAP_MAX_=
 | ||||
| +MALLOC_MMAP_THRESHOLD_=
 | ||||
| +MALLOC_PERTURB_=
 | ||||
| +MALLOC_TOP_PAD_=
 | ||||
| +MALLOC_TRIM_THRESHOLD_=
 | ||||
| +
 | ||||
|  ${test_wrapper_env} \ | ||||
|  ${run_program_env} \ | ||||
|  $rtld --list-tunables \ | ||||
							
								
								
									
										578
									
								
								SOURCES/glibc-rh2023420-3.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										578
									
								
								SOURCES/glibc-rh2023420-3.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,578 @@ | ||||
| commit 851f32cf7bf7067f73b991610778915edd57d7b4 | ||||
| Author: Florian Weimer <fweimer@redhat.com> | ||||
| Date:   Tue Mar 2 14:38:42 2021 +0100 | ||||
| 
 | ||||
|     ld.so: Implement the --list-diagnostics option | ||||
| 
 | ||||
| diff --git a/elf/Makefile b/elf/Makefile
 | ||||
| index aa65ec59f143bccf..d246f1c0d9e019fd 100644
 | ||||
| --- a/elf/Makefile
 | ||||
| +++ b/elf/Makefile
 | ||||
| @@ -64,7 +64,7 @@ elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \
 | ||||
|  # interpreter and operating independent of libc. | ||||
|  rtld-routines	= rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal \ | ||||
|    dl-error-minimal dl-conflict dl-hwcaps dl-hwcaps_split dl-hwcaps-subdirs \ | ||||
| -  dl-usage
 | ||||
| +  dl-usage dl-diagnostics dl-diagnostics-kernel dl-diagnostics-cpu
 | ||||
|  all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines) | ||||
|   | ||||
|  CFLAGS-dl-runtime.c += -fexceptions -fasynchronous-unwind-tables | ||||
| @@ -672,6 +672,9 @@ CFLAGS-cache.c += $(SYSCONF-FLAGS)
 | ||||
|  CFLAGS-rtld.c += $(SYSCONF-FLAGS) | ||||
|  CFLAGS-dl-usage.c += $(SYSCONF-FLAGS) \ | ||||
|    -D'RTLD="$(rtlddir)/$(rtld-installed-name)"' | ||||
| +CFLAGS-dl-diagnostics.c += $(SYSCONF-FLAGS) \
 | ||||
| +  -D'PREFIX="$(prefix)"' \
 | ||||
| +  -D'RTLD="$(rtlddir)/$(rtld-installed-name)"'
 | ||||
|   | ||||
|  cpp-srcs-left := $(all-rtld-routines:=.os) | ||||
|  lib := rtld | ||||
| diff --git a/elf/dl-diagnostics-cpu.c b/elf/dl-diagnostics-cpu.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..f7d149764bcb35a1
 | ||||
| --- /dev/null
 | ||||
| +++ b/elf/dl-diagnostics-cpu.c
 | ||||
| @@ -0,0 +1,24 @@
 | ||||
| +/* Print CPU diagnostics data in ld.so.  Stub version.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <dl-diagnostics.h>
 | ||||
| +
 | ||||
| +void
 | ||||
| +_dl_diagnostics_cpu (void)
 | ||||
| +{
 | ||||
| +}
 | ||||
| diff --git a/elf/dl-diagnostics-kernel.c b/elf/dl-diagnostics-kernel.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..831c358f1463cbf4
 | ||||
| --- /dev/null
 | ||||
| +++ b/elf/dl-diagnostics-kernel.c
 | ||||
| @@ -0,0 +1,24 @@
 | ||||
| +/* Print kernel diagnostics data in ld.so.  Stub version.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <dl-diagnostics.h>
 | ||||
| +
 | ||||
| +void
 | ||||
| +_dl_diagnostics_kernel (void)
 | ||||
| +{
 | ||||
| +}
 | ||||
| diff --git a/elf/dl-diagnostics.c b/elf/dl-diagnostics.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..bef224b36cbf5fc3
 | ||||
| --- /dev/null
 | ||||
| +++ b/elf/dl-diagnostics.c
 | ||||
| @@ -0,0 +1,265 @@
 | ||||
| +/* Print diagnostics data in ld.so.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <gnu/lib-names.h>
 | ||||
| +#include <stdbool.h>
 | ||||
| +#include <stddef.h>
 | ||||
| +#include <unistd.h>
 | ||||
| +
 | ||||
| +#include <dl-diagnostics.h>
 | ||||
| +#include <dl-hwcaps.h>
 | ||||
| +#include <dl-main.h>
 | ||||
| +#include <dl-procinfo.h>
 | ||||
| +#include <dl-sysdep.h>
 | ||||
| +#include <ldsodefs.h>
 | ||||
| +#include "trusted-dirs.h"
 | ||||
| +#include "version.h"
 | ||||
| +
 | ||||
| +/* Write CH to standard output.  */
 | ||||
| +static void
 | ||||
| +_dl_putc (char ch)
 | ||||
| +{
 | ||||
| +  _dl_write (STDOUT_FILENO, &ch, 1);
 | ||||
| +}
 | ||||
| +
 | ||||
| +/* Print CH to standard output, quoting it if necessary.  */
 | ||||
| +static void
 | ||||
| +print_quoted_char (char ch)
 | ||||
| +{
 | ||||
| +  if (ch < ' ' || ch > '~')
 | ||||
| +    {
 | ||||
| +      char buf[4];
 | ||||
| +      buf[0] = '\\';
 | ||||
| +      buf[1] = '0' + ((ch >> 6) & 7);
 | ||||
| +      buf[2] = '0' + ((ch >> 6) & 7);
 | ||||
| +      buf[3] = '0' + (ch & 7);
 | ||||
| +      _dl_write (STDOUT_FILENO, buf, 4);
 | ||||
| +    }
 | ||||
| +  else
 | ||||
| +    {
 | ||||
| +      if (ch == '\\' || ch == '"')
 | ||||
| +        _dl_putc ('\\');
 | ||||
| +      _dl_putc (ch);
 | ||||
| +    }
 | ||||
| +}
 | ||||
| +
 | ||||
| +/* Print S of LEN bytes to standard output, quoting characters as
 | ||||
| +   needed.  */
 | ||||
| +static void
 | ||||
| +print_string_length (const char *s, size_t len)
 | ||||
| +{
 | ||||
| +  _dl_putc ('"');
 | ||||
| +  for (size_t i = 0; i < len; ++i)
 | ||||
| +    print_quoted_char (s[i]);
 | ||||
| +  _dl_putc ('"');
 | ||||
| +}
 | ||||
| +
 | ||||
| +void
 | ||||
| +_dl_diagnostics_print_string (const char *s)
 | ||||
| +{
 | ||||
| +  if (s == NULL)
 | ||||
| +    {
 | ||||
| +      _dl_printf ("0x0");
 | ||||
| +      return;
 | ||||
| +    }
 | ||||
| +
 | ||||
| +  _dl_putc ('"');
 | ||||
| +  while (*s != '\0')
 | ||||
| +    {
 | ||||
| +      print_quoted_char (*s);
 | ||||
| +      ++s;
 | ||||
| +    }
 | ||||
| +  _dl_putc ('"');
 | ||||
| +}
 | ||||
| +
 | ||||
| +void
 | ||||
| +_dl_diagnostics_print_labeled_string (const char *label, const char *s)
 | ||||
| +{
 | ||||
| +  _dl_printf ("%s=", label);
 | ||||
| +  _dl_diagnostics_print_string (s);
 | ||||
| +  _dl_putc ('\n');
 | ||||
| +}
 | ||||
| +
 | ||||
| +void
 | ||||
| +_dl_diagnostics_print_labeled_value (const char *label, uint64_t value)
 | ||||
| +{
 | ||||
| +  if (sizeof (value) == sizeof (unsigned long int))
 | ||||
| +    /* _dl_printf can print 64-bit values directly.  */
 | ||||
| +    _dl_printf ("%s=0x%lx\n", label, (unsigned long int) value);
 | ||||
| +  else
 | ||||
| +    {
 | ||||
| +      uint32_t high = value >> 32;
 | ||||
| +      uint32_t low = value;
 | ||||
| +      if (high == 0)
 | ||||
| +        _dl_printf ("%s=0x%x\n", label, low);
 | ||||
| +      else
 | ||||
| +        _dl_printf ("%s=0x%x%08x\n", label, high, low);
 | ||||
| +    }
 | ||||
| +}
 | ||||
| +
 | ||||
| +/* Return true if ENV is an unfiltered environment variable.  */
 | ||||
| +static bool
 | ||||
| +unfiltered_envvar (const char *env, size_t *name_length)
 | ||||
| +{
 | ||||
| +  char *env_equal = strchr (env, '=');
 | ||||
| +  if (env_equal == NULL)
 | ||||
| +    {
 | ||||
| +      /* Always dump malformed entries.  */
 | ||||
| +      *name_length = strlen (env);
 | ||||
| +      return true;
 | ||||
| +    }
 | ||||
| +  size_t envname_length = env_equal - env;
 | ||||
| +  *name_length = envname_length;
 | ||||
| +
 | ||||
| +  /* LC_ and LD_ variables.  */
 | ||||
| +  if (env[0] == 'L' && (env[1] == 'C' || env[1] == 'D')
 | ||||
| +      && env[2] == '_')
 | ||||
| +    return true;
 | ||||
| +
 | ||||
| +  /* MALLOC_ variables.  */
 | ||||
| +  if (strncmp (env, "MALLOC_", strlen ("MALLOC_")) == 0)
 | ||||
| +    return true;
 | ||||
| +
 | ||||
| +  static const char unfiltered[] =
 | ||||
| +    "DATEMSK\0"
 | ||||
| +    "GCONV_PATH\0"
 | ||||
| +    "GETCONF_DIR\0"
 | ||||
| +    "GETCONF_DIR\0"
 | ||||
| +    "GLIBC_TUNABLES\0"
 | ||||
| +    "GMON_OUTPUT_PREFIX\0"
 | ||||
| +    "HESIOD_CONFIG\0"
 | ||||
| +    "HES_DOMAIN\0"
 | ||||
| +    "HOSTALIASES\0"
 | ||||
| +    "I18NPATH\0"
 | ||||
| +    "IFS\0"
 | ||||
| +    "LANG\0"
 | ||||
| +    "LOCALDOMAIN\0"
 | ||||
| +    "LOCPATH\0"
 | ||||
| +    "MSGVERB\0"
 | ||||
| +    "NIS_DEFAULTS\0"
 | ||||
| +    "NIS_GROUP\0"
 | ||||
| +    "NIS_PATH\0"
 | ||||
| +    "NLSPATH\0"
 | ||||
| +    "PATH\0"
 | ||||
| +    "POSIXLY_CORRECT\0"
 | ||||
| +    "RESOLV_HOST_CONF\0"
 | ||||
| +    "RES_OPTIONS\0"
 | ||||
| +    "SEV_LEVEL\0"
 | ||||
| +    "TMPDIR\0"
 | ||||
| +    "TZ\0"
 | ||||
| +    "TZDIR\0"
 | ||||
| +    /* Two null bytes at the end to mark the end of the list via an
 | ||||
| +       empty substring.  */
 | ||||
| +    ;
 | ||||
| +  for (const char *candidate = unfiltered; *candidate != '\0'; )
 | ||||
| +    {
 | ||||
| +      size_t candidate_length = strlen (candidate);
 | ||||
| +      if (candidate_length == envname_length
 | ||||
| +          && memcmp (candidate, env, candidate_length) == 0)
 | ||||
| +        return true;
 | ||||
| +      candidate += candidate_length + 1;
 | ||||
| +    }
 | ||||
| +
 | ||||
| +  return false;
 | ||||
| +}
 | ||||
| +
 | ||||
| +/* Dump the process environment.  */
 | ||||
| +static void
 | ||||
| +print_environ (char **environ)
 | ||||
| +{
 | ||||
| +  unsigned int index = 0;
 | ||||
| +  for (char **envp = environ; *envp != NULL; ++envp)
 | ||||
| +    {
 | ||||
| +      char *env = *envp;
 | ||||
| +      size_t name_length;
 | ||||
| +      bool unfiltered = unfiltered_envvar (env, &name_length);
 | ||||
| +      _dl_printf ("env%s[0x%x]=",
 | ||||
| +                  unfiltered ? "" : "_filtered", index);
 | ||||
| +      if (unfiltered)
 | ||||
| +        _dl_diagnostics_print_string (env);
 | ||||
| +      else
 | ||||
| +        print_string_length (env, name_length);
 | ||||
| +      _dl_putc ('\n');
 | ||||
| +      ++index;
 | ||||
| +    }
 | ||||
| +}
 | ||||
| +
 | ||||
| +/* Print configured paths and the built-in search path.  */
 | ||||
| +static void
 | ||||
| +print_paths (void)
 | ||||
| +{
 | ||||
| +  _dl_diagnostics_print_labeled_string ("path.prefix", PREFIX);
 | ||||
| +  _dl_diagnostics_print_labeled_string ("path.rtld", RTLD);
 | ||||
| +  _dl_diagnostics_print_labeled_string ("path.sysconfdir", SYSCONFDIR);
 | ||||
| +
 | ||||
| +  unsigned int index = 0;
 | ||||
| +  static const char *system_dirs = SYSTEM_DIRS "\0";
 | ||||
| +  for (const char *e = system_dirs; *e != '\0'; )
 | ||||
| +    {
 | ||||
| +      size_t len = strlen (e);
 | ||||
| +      _dl_printf ("path.system_dirs[0x%x]=", index);
 | ||||
| +      print_string_length (e, len);
 | ||||
| +      _dl_putc ('\n');
 | ||||
| +      ++index;
 | ||||
| +      e += len + 1;
 | ||||
| +    }
 | ||||
| +}
 | ||||
| +
 | ||||
| +/* Print information about the glibc version.  */
 | ||||
| +static void
 | ||||
| +print_version (void)
 | ||||
| +{
 | ||||
| +  _dl_diagnostics_print_labeled_string ("version.release", RELEASE);
 | ||||
| +  _dl_diagnostics_print_labeled_string ("version.version", VERSION);
 | ||||
| +}
 | ||||
| +
 | ||||
| +void
 | ||||
| +_dl_print_diagnostics (char **environ)
 | ||||
| +{
 | ||||
| +#ifdef HAVE_DL_DISCOVER_OSVERSION
 | ||||
| +  _dl_diagnostics_print_labeled_value
 | ||||
| +    ("dl_discover_osversion", _dl_discover_osversion ());
 | ||||
| +#endif
 | ||||
| +  _dl_diagnostics_print_labeled_string ("dl_dst_lib", DL_DST_LIB);
 | ||||
| +  _dl_diagnostics_print_labeled_value ("dl_hwcap", GLRO (dl_hwcap));
 | ||||
| +  _dl_diagnostics_print_labeled_value ("dl_hwcap_important", HWCAP_IMPORTANT);
 | ||||
| +  _dl_diagnostics_print_labeled_value ("dl_hwcap2", GLRO (dl_hwcap2));
 | ||||
| +  _dl_diagnostics_print_labeled_string
 | ||||
| +    ("dl_hwcaps_subdirs", _dl_hwcaps_subdirs);
 | ||||
| +  _dl_diagnostics_print_labeled_value
 | ||||
| +    ("dl_hwcaps_subdirs_active", _dl_hwcaps_subdirs_active ());
 | ||||
| +  _dl_diagnostics_print_labeled_value ("dl_osversion", GLRO (dl_osversion));
 | ||||
| +  _dl_diagnostics_print_labeled_value ("dl_pagesize", GLRO (dl_pagesize));
 | ||||
| +  _dl_diagnostics_print_labeled_string ("dl_platform", GLRO (dl_platform));
 | ||||
| +  _dl_diagnostics_print_labeled_string
 | ||||
| +    ("dl_profile_output", GLRO (dl_profile_output));
 | ||||
| +  _dl_diagnostics_print_labeled_value
 | ||||
| +    ("dl_string_platform", _dl_string_platform ( GLRO (dl_platform)));
 | ||||
| +
 | ||||
| +  _dl_diagnostics_print_labeled_string ("dso.ld", LD_SO);
 | ||||
| +  _dl_diagnostics_print_labeled_string ("dso.libc", LIBC_SO);
 | ||||
| +
 | ||||
| +  print_environ (environ);
 | ||||
| +  print_paths ();
 | ||||
| +  print_version ();
 | ||||
| +
 | ||||
| +  _dl_diagnostics_kernel ();
 | ||||
| +  _dl_diagnostics_cpu ();
 | ||||
| +
 | ||||
| +  _exit (EXIT_SUCCESS);
 | ||||
| +}
 | ||||
| diff --git a/elf/dl-diagnostics.h b/elf/dl-diagnostics.h
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..27dcb12bca12e5b6
 | ||||
| --- /dev/null
 | ||||
| +++ b/elf/dl-diagnostics.h
 | ||||
| @@ -0,0 +1,46 @@
 | ||||
| +/* Interfaces for printing diagnostics in ld.so.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#ifndef _DL_DIAGNOSTICS_H
 | ||||
| +#define _DL_DIAGNOSTICS_H
 | ||||
| +
 | ||||
| +#include <stdint.h>
 | ||||
| +
 | ||||
| +/* Write the null-terminated string to standard output, surrounded in
 | ||||
| +   quotation marks.  */
 | ||||
| +void _dl_diagnostics_print_string (const char *s) attribute_hidden;
 | ||||
| +
 | ||||
| +/* Like _dl_diagnostics_print_string, but add a LABEL= prefix, and a
 | ||||
| +   newline character as a suffix.  */
 | ||||
| +void _dl_diagnostics_print_labeled_string (const char *label, const char *s)
 | ||||
| +  attribute_hidden;
 | ||||
| +
 | ||||
| +/* Print LABEL=VALUE to standard output, followed by a newline
 | ||||
| +   character.  */
 | ||||
| +void _dl_diagnostics_print_labeled_value (const char *label, uint64_t value)
 | ||||
| +  attribute_hidden;
 | ||||
| +
 | ||||
| +/* Print diagnostics data for the kernel.  Called from
 | ||||
| +   _dl_print_diagnostics.  */
 | ||||
| +void _dl_diagnostics_kernel (void) attribute_hidden;
 | ||||
| +
 | ||||
| +/* Print diagnostics data for the CPU(s).  Called from
 | ||||
| +   _dl_print_diagnostics.  */
 | ||||
| +void _dl_diagnostics_cpu (void) attribute_hidden;
 | ||||
| +
 | ||||
| +#endif /* _DL_DIAGNOSTICS_H */
 | ||||
| diff --git a/elf/dl-main.h b/elf/dl-main.h
 | ||||
| index 9e7b51d8f010e904..9fbbdb0fac09adf3 100644
 | ||||
| --- a/elf/dl-main.h
 | ||||
| +++ b/elf/dl-main.h
 | ||||
| @@ -63,7 +63,7 @@ struct audit_list
 | ||||
|  enum rtld_mode | ||||
|    { | ||||
|      rtld_mode_normal, rtld_mode_list, rtld_mode_verify, rtld_mode_trace, | ||||
| -    rtld_mode_list_tunables, rtld_mode_help,
 | ||||
| +    rtld_mode_list_tunables, rtld_mode_list_diagnostics, rtld_mode_help,
 | ||||
|    }; | ||||
|   | ||||
|  /* Aggregated state information extracted from environment variables | ||||
| @@ -121,4 +121,7 @@ _Noreturn void _dl_version (void) attribute_hidden;
 | ||||
|  _Noreturn void _dl_help (const char *argv0, struct dl_main_state *state) | ||||
|    attribute_hidden; | ||||
|   | ||||
| +/* Print a diagnostics dump.  */
 | ||||
| +_Noreturn void _dl_print_diagnostics (char **environ) attribute_hidden;
 | ||||
| +
 | ||||
|  #endif /* _DL_MAIN */ | ||||
| diff --git a/elf/dl-usage.c b/elf/dl-usage.c
 | ||||
| index 908b4894b3014b2d..e19e1791d9169da2 100644
 | ||||
| --- a/elf/dl-usage.c
 | ||||
| +++ b/elf/dl-usage.c
 | ||||
| @@ -261,6 +261,7 @@ setting environment variables (which would be inherited by subprocesses).\n\
 | ||||
|    --list-tunables       list all tunables with minimum and maximum values\n" | ||||
|  #endif | ||||
|  "\ | ||||
| +  --list-diagnostics    list diagnostics information\n\
 | ||||
|    --help                display this help and exit\n\ | ||||
|    --version             output version information and exit\n\ | ||||
|  \n\ | ||||
| diff --git a/elf/rtld.c b/elf/rtld.c
 | ||||
| index 54b621ec5ca014fa..d14c388f548d6d51 100644
 | ||||
| --- a/elf/rtld.c
 | ||||
| +++ b/elf/rtld.c
 | ||||
| @@ -138,6 +138,7 @@ static void dl_main_state_init (struct dl_main_state *state);
 | ||||
|  /* Process all environments variables the dynamic linker must recognize. | ||||
|     Since all of them start with `LD_' we are a bit smarter while finding | ||||
|     all the entries.  */ | ||||
| +extern char **_environ attribute_hidden;
 | ||||
|  static void process_envvars (struct dl_main_state *state); | ||||
|   | ||||
|  #ifdef DL_ARGV_NOT_RELRO | ||||
| @@ -1273,6 +1274,14 @@ dl_main (const ElfW(Phdr) *phdr,
 | ||||
|  	    ++_dl_argv; | ||||
|  	  } | ||||
|  #endif | ||||
| +	else if (! strcmp (_dl_argv[1], "--list-diagnostics"))
 | ||||
| +	  {
 | ||||
| +	    state.mode = rtld_mode_list_diagnostics;
 | ||||
| +
 | ||||
| +	    ++_dl_skip_args;
 | ||||
| +	    --_dl_argc;
 | ||||
| +	    ++_dl_argv;
 | ||||
| +	  }
 | ||||
|  	else if (strcmp (_dl_argv[1], "--help") == 0) | ||||
|  	  { | ||||
|  	    state.mode = rtld_mode_help; | ||||
| @@ -1301,6 +1310,9 @@ dl_main (const ElfW(Phdr) *phdr,
 | ||||
|  	} | ||||
|  #endif | ||||
|   | ||||
| +      if (state.mode == rtld_mode_list_diagnostics)
 | ||||
| +	_dl_print_diagnostics (_environ);
 | ||||
| +
 | ||||
|        /* If we have no further argument the program was called incorrectly. | ||||
|  	 Grant the user some education.  */ | ||||
|        if (_dl_argc < 2) | ||||
| @@ -2623,12 +2635,6 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n");
 | ||||
|      } | ||||
|  } | ||||
|   | ||||
| -/* Process all environments variables the dynamic linker must recognize.
 | ||||
| -   Since all of them start with `LD_' we are a bit smarter while finding
 | ||||
| -   all the entries.  */
 | ||||
| -extern char **_environ attribute_hidden;
 | ||||
| -
 | ||||
| -
 | ||||
|  static void | ||||
|  process_envvars (struct dl_main_state *state) | ||||
|  { | ||||
| diff --git a/sysdeps/unix/sysv/linux/dl-diagnostics-kernel.c b/sysdeps/unix/sysv/linux/dl-diagnostics-kernel.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..59f6402c547ba590
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/unix/sysv/linux/dl-diagnostics-kernel.c
 | ||||
| @@ -0,0 +1,77 @@
 | ||||
| +/* Print kernel diagnostics data in ld.so.  Linux version.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <dl-diagnostics.h>
 | ||||
| +#include <ldsodefs.h>
 | ||||
| +#include <sys/utsname.h>
 | ||||
| +
 | ||||
| +/* Dump the auxiliary vector to standard output.  */
 | ||||
| +static void
 | ||||
| +print_auxv (void)
 | ||||
| +{
 | ||||
| +  /* See _dl_show_auxv.  The code below follows the general output
 | ||||
| +     format for diagnostic dumps.  */
 | ||||
| +  unsigned int index = 0;
 | ||||
| +  for (ElfW(auxv_t) *av = GLRO(dl_auxv); av->a_type != AT_NULL; ++av)
 | ||||
| +    {
 | ||||
| +      _dl_printf ("auxv[0x%x].a_type=0x%lx\n"
 | ||||
| +                  "auxv[0x%x].a_val=",
 | ||||
| +                  index, (unsigned long int) av->a_type, index);
 | ||||
| +      if (av->a_type == AT_EXECFN
 | ||||
| +          || av->a_type == AT_PLATFORM
 | ||||
| +          || av->a_type == AT_BASE_PLATFORM)
 | ||||
| +        /* The address of the strings is not useful at all, so print
 | ||||
| +           the strings themselvs.  */
 | ||||
| +        _dl_diagnostics_print_string ((const char *) av->a_un.a_val);
 | ||||
| +      else
 | ||||
| +        _dl_printf ("0x%lx", (unsigned long int) av->a_un.a_val);
 | ||||
| +      _dl_printf ("\n");
 | ||||
| +      ++index;
 | ||||
| +    }
 | ||||
| +}
 | ||||
| +
 | ||||
| +/* Print one uname entry.  */
 | ||||
| +static void
 | ||||
| +print_utsname_entry (const char *field, const char *value)
 | ||||
| +{
 | ||||
| +  _dl_printf ("uname.");
 | ||||
| +  _dl_diagnostics_print_labeled_string (field, value);
 | ||||
| +}
 | ||||
| +
 | ||||
| +/* Print information from uname, including the kernel version.  */
 | ||||
| +static void
 | ||||
| +print_uname (void)
 | ||||
| +{
 | ||||
| +  struct utsname uts;
 | ||||
| +  if (__uname (&uts) == 0)
 | ||||
| +    {
 | ||||
| +      print_utsname_entry ("sysname", uts.sysname);
 | ||||
| +      print_utsname_entry ("nodename", uts.nodename);
 | ||||
| +      print_utsname_entry ("release", uts.release);
 | ||||
| +      print_utsname_entry ("version", uts.version);
 | ||||
| +      print_utsname_entry ("machine", uts.machine);
 | ||||
| +      print_utsname_entry ("domainname", uts.domainname);
 | ||||
| +    }
 | ||||
| +}
 | ||||
| +
 | ||||
| +void
 | ||||
| +_dl_diagnostics_kernel (void)
 | ||||
| +{
 | ||||
| +  print_auxv ();
 | ||||
| +  print_uname ();
 | ||||
| +}
 | ||||
							
								
								
									
										117
									
								
								SOURCES/glibc-rh2023420-4.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								SOURCES/glibc-rh2023420-4.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,117 @@ | ||||
| commit e4933c8a92ea08eecdf3ab45e7f76c95dc3d20ac | ||||
| Author: Florian Weimer <fweimer@redhat.com> | ||||
| Date:   Tue Mar 2 14:58:05 2021 +0100 | ||||
| 
 | ||||
|     x86: Automate generation of PREFERRED_FEATURE_INDEX_1 bitfield | ||||
| 
 | ||||
|     Use a .def file to define the bitfield layout, so that it is possible | ||||
|     to iterate over field members using the preprocessor. | ||||
| 
 | ||||
| Conflicts: | ||||
| 	sysdeps/x86/include/cpu-features.h | ||||
| 	  (re-did the change from scratch) | ||||
| 	sysdeps/x86/include/cpu-features-preferred_feature_index_1.def | ||||
| 	  (adjusted to the downstream bits) | ||||
| 
 | ||||
| diff --git a/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..17a5cc428c1dabea
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
 | ||||
| @@ -0,0 +1,34 @@
 | ||||
| +/* Bits in the PREFERRED_FEATURE_INDEX_1 bitfield of <cpu-features.h>.
 | ||||
| +   Copyright (C) 2020-2021 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/>.  */
 | ||||
| +
 | ||||
| +BIT (I586)
 | ||||
| +BIT (I686)
 | ||||
| +BIT (Fast_Rep_String)
 | ||||
| +BIT (Fast_Copy_Backward)
 | ||||
| +BIT (Fast_Unaligned_Load)
 | ||||
| +BIT (Fast_Unaligned_Copy)
 | ||||
| +BIT (Slow_BSF)
 | ||||
| +BIT (Slow_SSE4_2)
 | ||||
| +BIT (AVX_Fast_Unaligned_Load)
 | ||||
| +BIT (Prefer_MAP_32BIT_EXEC)
 | ||||
| +BIT (Prefer_PMINUB_for_stringop)
 | ||||
| +BIT (Prefer_No_VZEROUPPER)
 | ||||
| +BIT (Prefer_ERMS)
 | ||||
| +BIT (Prefer_FSRM)
 | ||||
| +BIT (Prefer_No_AVX512)
 | ||||
| +BIT (MathVec_Prefer_No_AVX512)
 | ||||
| diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
 | ||||
| index f62be0b9b3746675..f43e22f677b249a9 100644
 | ||||
| --- a/sysdeps/x86/include/cpu-features.h
 | ||||
| +++ b/sysdeps/x86/include/cpu-features.h
 | ||||
| @@ -80,40 +80,23 @@ enum
 | ||||
|  # define HAS_ARCH_FEATURE(name) \ | ||||
|    CPU_FEATURE_PREFERRED (name) | ||||
|   | ||||
| -/* PREFERRED_FEATURE_INDEX_1.  */
 | ||||
| -# define bit_arch_I586				(1u << 0)
 | ||||
| -# define bit_arch_I686				(1u << 1)
 | ||||
| -# define bit_arch_Fast_Rep_String		(1u << 2)
 | ||||
| -# define bit_arch_Fast_Copy_Backward		(1u << 3)
 | ||||
| -# define bit_arch_Fast_Unaligned_Load		(1u << 4)
 | ||||
| -# define bit_arch_Fast_Unaligned_Copy		(1u << 5)
 | ||||
| -# define bit_arch_Slow_BSF			(1u << 6)
 | ||||
| -# define bit_arch_Slow_SSE4_2			(1u << 7)
 | ||||
| -# define bit_arch_AVX_Fast_Unaligned_Load	(1u << 8)
 | ||||
| -# define bit_arch_Prefer_MAP_32BIT_EXEC		(1u << 9)
 | ||||
| -# define bit_arch_Prefer_PMINUB_for_stringop	(1u << 10)
 | ||||
| -# define bit_arch_Prefer_No_VZEROUPPER		(1u << 11)
 | ||||
| -# define bit_arch_Prefer_ERMS			(1u << 12)
 | ||||
| -# define bit_arch_Prefer_FSRM			(1u << 13)
 | ||||
| -# define bit_arch_Prefer_No_AVX512		(1u << 14)
 | ||||
| -# define bit_arch_MathVec_Prefer_No_AVX512	(1u << 15)
 | ||||
| -
 | ||||
| -# define index_arch_Fast_Rep_String		PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_Fast_Copy_Backward		PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_Slow_BSF			PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_Fast_Unaligned_Load		PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_Prefer_PMINUB_for_stringop 	PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_Fast_Unaligned_Copy		PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_I586			PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_I686			PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_Slow_SSE4_2			PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_AVX_Fast_Unaligned_Load	PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_Prefer_MAP_32BIT_EXEC	PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_Prefer_No_VZEROUPPER	PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_Prefer_ERMS			PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_Prefer_No_AVX512		PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_MathVec_Prefer_No_AVX512	PREFERRED_FEATURE_INDEX_1
 | ||||
| -# define index_arch_Prefer_FSRM			PREFERRED_FEATURE_INDEX_1
 | ||||
| +/* PREFERRED_FEATURE_INDEX_1.  First define the bitindex values
 | ||||
| +   sequentially, then define the bit_arch* and index_arch_* lookup
 | ||||
| +   constants.  */
 | ||||
| +enum
 | ||||
| +  {
 | ||||
| +#define BIT(x) _bitindex_arch_##x ,
 | ||||
| +#include "cpu-features-preferred_feature_index_1.def"
 | ||||
| +#undef BIT
 | ||||
| +  };
 | ||||
| +enum
 | ||||
| +  {
 | ||||
| +#define BIT(x)                                 \
 | ||||
| +    bit_arch_##x = 1u << _bitindex_arch_##x ,  \
 | ||||
| +    index_arch_##x = PREFERRED_FEATURE_INDEX_1,
 | ||||
| +#include "cpu-features-preferred_feature_index_1.def"
 | ||||
| +#undef BIT
 | ||||
| +  };
 | ||||
|   | ||||
|  /* XCR0 Feature flags.  */ | ||||
|  # define bit_XMM_state		(1u << 1) | ||||
							
								
								
									
										131
									
								
								SOURCES/glibc-rh2023420-5.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								SOURCES/glibc-rh2023420-5.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,131 @@ | ||||
| commit 01a5746b6c8a44dc29d33e056b63485075a6a3cc | ||||
| Author: Florian Weimer <fweimer@redhat.com> | ||||
| Date:   Wed Feb 24 13:12:04 2021 +0100 | ||||
| 
 | ||||
|     x86: Add CPU-specific diagnostics to ld.so --list-diagnostics | ||||
| 
 | ||||
| Conflicts: | ||||
| 	sysdeps/x86/dl-diagnostics-cpu.c | ||||
| 	  (reworked due to struct differences, different knobs | ||||
| 	  downstream) | ||||
| 
 | ||||
| diff --git a/sysdeps/x86/dl-diagnostics-cpu.c b/sysdeps/x86/dl-diagnostics-cpu.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..0ba286a828b69937
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/x86/dl-diagnostics-cpu.c
 | ||||
| @@ -0,0 +1,101 @@
 | ||||
| +/* Print CPU diagnostics data in ld.so.  x86 version.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <dl-diagnostics.h>
 | ||||
| +#include <ldsodefs.h>
 | ||||
| +
 | ||||
| +static void
 | ||||
| +print_cpu_features_value (const char *label, uint64_t value)
 | ||||
| +{
 | ||||
| +  _dl_printf ("x86.cpu_features.");
 | ||||
| +  _dl_diagnostics_print_labeled_value (label, value);
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void
 | ||||
| +print_cpu_feature_internal (unsigned int index, const char *kind,
 | ||||
| +                            unsigned int reg, uint32_t value)
 | ||||
| +{
 | ||||
| +  _dl_printf ("x86.cpu_features.features[0x%x].%s[0x%x]=0x%x\n",
 | ||||
| +              index, kind, reg, value);
 | ||||
| +}
 | ||||
| +
 | ||||
| +static void
 | ||||
| +print_cpu_feature_preferred (const char *label, unsigned int flag)
 | ||||
| +{
 | ||||
| +  _dl_printf("x86.cpu_features.preferred.%s=0x%x\n", label, flag);
 | ||||
| +}
 | ||||
| +
 | ||||
| +void
 | ||||
| +_dl_diagnostics_cpu (void)
 | ||||
| +{
 | ||||
| +  const struct cpu_features *cpu_features = __get_cpu_features ();
 | ||||
| +
 | ||||
| +  print_cpu_features_value ("basic.kind", cpu_features->basic.kind);
 | ||||
| +  print_cpu_features_value ("basic.max_cpuid", cpu_features->basic.max_cpuid);
 | ||||
| +  print_cpu_features_value ("basic.family", cpu_features->basic.family);
 | ||||
| +  print_cpu_features_value ("basic.model", cpu_features->basic.model);
 | ||||
| +  print_cpu_features_value ("basic.stepping", cpu_features->basic.stepping);
 | ||||
| +
 | ||||
| +  for (unsigned int index = 0; index < COMMON_CPUID_INDEX_MAX; ++index)
 | ||||
| +    {
 | ||||
| +      /* Downstream, these constants are not part of the ABI yet, so
 | ||||
| +         analysis needs to take the precise glibc version into
 | ||||
| +         account.  */
 | ||||
| +      print_cpu_feature_internal
 | ||||
| +        (index, "cpuid", 0, cpu_features->features[index].cpuid.eax);
 | ||||
| +      print_cpu_feature_internal
 | ||||
| +        (index, "cpuid", 1, cpu_features->features[index].cpuid.ebx);
 | ||||
| +      print_cpu_feature_internal
 | ||||
| +        (index, "cpuid", 2, cpu_features->features[index].cpuid.ecx);
 | ||||
| +      print_cpu_feature_internal
 | ||||
| +        (index, "cpuid", 3, cpu_features->features[index].cpuid.edx);
 | ||||
| +      print_cpu_feature_internal
 | ||||
| +        (index, "usable", 0, cpu_features->features[index].usable.eax);
 | ||||
| +      print_cpu_feature_internal
 | ||||
| +        (index, "usable", 1, cpu_features->features[index].usable.ebx);
 | ||||
| +      print_cpu_feature_internal
 | ||||
| +        (index, "usable", 2, cpu_features->features[index].usable.ecx);
 | ||||
| +      print_cpu_feature_internal
 | ||||
| +        (index, "usable", 3, cpu_features->features[index].usable.edx);
 | ||||
| +    }
 | ||||
| +
 | ||||
| +  /* The preferred indicators are not part of the ABI and need to be
 | ||||
| +     translated.  */
 | ||||
| +#define BIT(x) \
 | ||||
| +  print_cpu_feature_preferred (#x, CPU_FEATURE_PREFERRED_P (cpu_features, x));
 | ||||
| +#include "cpu-features-preferred_feature_index_1.def"
 | ||||
| +#undef BIT
 | ||||
| +
 | ||||
| +  print_cpu_features_value ("xsave_state_size",
 | ||||
| +                            cpu_features->xsave_state_size);
 | ||||
| +  print_cpu_features_value ("xsave_state_full_size",
 | ||||
| +                            cpu_features->xsave_state_full_size);
 | ||||
| +  print_cpu_features_value ("data_cache_size", cpu_features->data_cache_size);
 | ||||
| +  print_cpu_features_value ("shared_cache_size",
 | ||||
| +                            cpu_features->shared_cache_size);
 | ||||
| +  print_cpu_features_value ("non_temporal_threshold",
 | ||||
| +                            cpu_features->non_temporal_threshold);
 | ||||
| +  print_cpu_features_value ("rep_movsb_threshold",
 | ||||
| +                            cpu_features->rep_movsb_threshold);
 | ||||
| +  print_cpu_features_value ("rep_stosb_threshold",
 | ||||
| +                            cpu_features->rep_stosb_threshold);
 | ||||
| +  _Static_assert (offsetof (struct cpu_features, rep_stosb_threshold)
 | ||||
| +                  + sizeof (cpu_features->rep_stosb_threshold)
 | ||||
| +                  == sizeof (*cpu_features),
 | ||||
| +                  "last cpu_features field has been printed");
 | ||||
| +}
 | ||||
| diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h
 | ||||
| index f43e22f677b249a9..536643b209425198 100644
 | ||||
| --- a/sysdeps/x86/include/cpu-features.h
 | ||||
| +++ b/sysdeps/x86/include/cpu-features.h
 | ||||
| @@ -107,6 +107,8 @@ enum
 | ||||
|  # define bit_XTILECFG_state	(1u << 17) | ||||
|  # define bit_XTILEDATA_state	(1u << 18) | ||||
|   | ||||
| +/* NB: When adding new fields, update sysdeps/x86/dl-diagnostics-cpu.c
 | ||||
| +   to print them.  */
 | ||||
|  struct cpu_features | ||||
|  { | ||||
|    struct cpu_features_basic basic; | ||||
							
								
								
									
										255
									
								
								SOURCES/glibc-rh2023420-6.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								SOURCES/glibc-rh2023420-6.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,255 @@ | ||||
| commit c1cb2deeca1a85c6fc5bd41b90816d48a95bc434 | ||||
| Author: Florian Weimer <fweimer@redhat.com> | ||||
| Date:   Sun Dec 5 11:28:34 2021 +0100 | ||||
| 
 | ||||
|     elf: execve statically linked programs instead of crashing [BZ #28648] | ||||
| 
 | ||||
|     Programs without dynamic dependencies and without a program | ||||
|     interpreter are now run via execve. | ||||
| 
 | ||||
|     Previously, the dynamic linker either crashed while attempting to | ||||
|     read a non-existing dynamic segment (looking for DT_AUDIT/DT_DEPAUDIT | ||||
|     data), or the self-relocated in the static PIE executable crashed | ||||
|     because the outer dynamic linker had already applied RELRO protection. | ||||
| 
 | ||||
|     <dl-execve.h> is needed because execve is not available in the | ||||
|     dynamic loader on Hurd. | ||||
| 
 | ||||
|     Reviewed-by: H.J. Lu <hjl.tools@gmail.com> | ||||
| 
 | ||||
| Conflicts: | ||||
| 	elf/Makefile | ||||
| 	  (some missing backports) | ||||
| 	elf/rtld.c | ||||
| 	  (missing rework of ld.so self-relocation downstream, | ||||
| 	  always print error as a number due to missing | ||||
| 	  sterrorname_np, also fix errcode/errno glitch) | ||||
| 	sysdeps/unix/sysv/linux/dl-execve.h | ||||
| 	  (missing INTERNAL_SYSCALL_CALL refactoring to Linux-like | ||||
| 	  calling convention) | ||||
| 
 | ||||
| diff --git a/elf/Makefile b/elf/Makefile
 | ||||
| index d246f1c0d9e019fd..b3e8ab2792608de7 100644
 | ||||
| --- a/elf/Makefile
 | ||||
| +++ b/elf/Makefile
 | ||||
| @@ -214,7 +214,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
 | ||||
|  	 tst-tls-ie tst-tls-ie-dlmopen \ | ||||
|  	 argv0test \ | ||||
|  	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \ | ||||
| -	 tst-tls20 tst-tls21
 | ||||
| +	 tst-tls20 tst-tls21 \
 | ||||
| +	 tst-rtld-run-static \
 | ||||
|  #	 reldep9 | ||||
|  tests-internal += loadtest unload unload2 circleload1 \ | ||||
|  	 neededtest neededtest2 neededtest3 neededtest4 \ | ||||
| @@ -1917,3 +1918,5 @@ $(objpfx)tst-tls20.out: $(objpfx)tst-tls20mod-bad.so \
 | ||||
|  $(objpfx)tst-tls21: $(libdl) $(shared-thread-library) | ||||
|  $(objpfx)tst-tls21.out: $(objpfx)tst-tls21mod.so | ||||
|  $(objpfx)tst-tls21mod.so: $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so) | ||||
| +
 | ||||
| +$(objpfx)tst-rtld-run-static.out: $(objpfx)/ldconfig
 | ||||
| diff --git a/elf/rtld.c b/elf/rtld.c
 | ||||
| index d14c388f548d6d51..461d8c114a875a9b 100644
 | ||||
| --- a/elf/rtld.c
 | ||||
| +++ b/elf/rtld.c
 | ||||
| @@ -48,6 +48,7 @@
 | ||||
|  #include <dl-main.h> | ||||
|  #include <gnu/lib-names.h> | ||||
|  #include <dl-tunables.h> | ||||
| +#include <dl-execve.h>
 | ||||
|   | ||||
|  #include <assert.h> | ||||
|   | ||||
| @@ -1114,6 +1115,40 @@ load_audit_modules (struct link_map *main_map, struct audit_list *audit_list)
 | ||||
|      } | ||||
|  } | ||||
|   | ||||
| +/* Check if the executable is not actualy dynamically linked, and
 | ||||
| +   invoke it directly in that case.  */
 | ||||
| +static void
 | ||||
| +rtld_chain_load (struct link_map *main_map, char *argv0)
 | ||||
| +{
 | ||||
| +  /* The dynamic loader run against itself.  */
 | ||||
| +  const char *rtld_soname
 | ||||
| +    = ((const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB])
 | ||||
| +       + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_val);
 | ||||
| +  if (main_map->l_info[DT_SONAME] != NULL
 | ||||
| +      && strcmp (rtld_soname,
 | ||||
| +		 ((const char *) D_PTR (main_map, l_info[DT_STRTAB])
 | ||||
| +		  + main_map->l_info[DT_SONAME]->d_un.d_val)) == 0)
 | ||||
| +    _dl_fatal_printf ("%s: loader cannot load itself\n", rtld_soname);
 | ||||
| +
 | ||||
| +  /* With DT_NEEDED dependencies, the executable is dynamically
 | ||||
| +     linked.  */
 | ||||
| +  if (__glibc_unlikely (main_map->l_info[DT_NEEDED] != NULL))
 | ||||
| +    return;
 | ||||
| +
 | ||||
| +  /* If the executable has program interpreter, it is dynamically
 | ||||
| +     linked.  */
 | ||||
| +  for (size_t i = 0; i < main_map->l_phnum; ++i)
 | ||||
| +    if (main_map->l_phdr[i].p_type == PT_INTERP)
 | ||||
| +      return;
 | ||||
| +
 | ||||
| +  const char *pathname = _dl_argv[0];
 | ||||
| +  if (argv0 != NULL)
 | ||||
| +    _dl_argv[0] = argv0;
 | ||||
| +  int errcode = __rtld_execve (pathname, _dl_argv, _environ);
 | ||||
| +  _dl_fatal_printf("%s: cannot execute %s: %d\n",
 | ||||
| +		   rtld_soname, pathname, errcode);
 | ||||
| +}
 | ||||
| +
 | ||||
|  static void | ||||
|  dl_main (const ElfW(Phdr) *phdr, | ||||
|  	 ElfW(Word) phnum, | ||||
| @@ -1384,14 +1419,8 @@ dl_main (const ElfW(Phdr) *phdr,
 | ||||
|        /* Now the map for the main executable is available.  */ | ||||
|        main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; | ||||
|   | ||||
| -      if (__glibc_likely (state.mode == rtld_mode_normal)
 | ||||
| -	  && GL(dl_rtld_map).l_info[DT_SONAME] != NULL
 | ||||
| -	  && main_map->l_info[DT_SONAME] != NULL
 | ||||
| -	  && strcmp ((const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB])
 | ||||
| -		     + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_val,
 | ||||
| -		     (const char *) D_PTR (main_map, l_info[DT_STRTAB])
 | ||||
| -		     + main_map->l_info[DT_SONAME]->d_un.d_val) == 0)
 | ||||
| -	_dl_fatal_printf ("loader cannot load itself\n");
 | ||||
| +      if (__glibc_likely (state.mode == rtld_mode_normal))
 | ||||
| +	rtld_chain_load (main_map, argv0);
 | ||||
|   | ||||
|        phdr = main_map->l_phdr; | ||||
|        phnum = main_map->l_phnum; | ||||
| diff --git a/elf/tst-rtld-run-static.c b/elf/tst-rtld-run-static.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..7281093504b675c4
 | ||||
| --- /dev/null
 | ||||
| +++ b/elf/tst-rtld-run-static.c
 | ||||
| @@ -0,0 +1,62 @@
 | ||||
| +/* Test running statically linked programs using ld.so.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <support/check.h>
 | ||||
| +#include <support/support.h>
 | ||||
| +#include <support/capture_subprocess.h>
 | ||||
| +#include <string.h>
 | ||||
| +#include <stdlib.h>
 | ||||
| +
 | ||||
| +static int
 | ||||
| +do_test (void)
 | ||||
| +{
 | ||||
| +  char *ldconfig_path = xasprintf ("%s/elf/ldconfig", support_objdir_root);
 | ||||
| +
 | ||||
| +  {
 | ||||
| +    char *argv[] = { (char *) "ld.so", ldconfig_path, (char *) "--help", NULL };
 | ||||
| +    struct support_capture_subprocess cap
 | ||||
| +      = support_capture_subprogram (support_objdir_elf_ldso, argv);
 | ||||
| +    support_capture_subprocess_check (&cap, "no --argv0", 0, sc_allow_stdout);
 | ||||
| +    puts ("info: output without --argv0:");
 | ||||
| +    puts (cap.out.buffer);
 | ||||
| +    TEST_VERIFY (strstr (cap.out.buffer, "Usage: ldconfig [OPTION...]\n")
 | ||||
| +                 == cap.out.buffer);
 | ||||
| +    support_capture_subprocess_free (&cap);
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  {
 | ||||
| +    char *argv[] =
 | ||||
| +      {
 | ||||
| +        (char *) "ld.so", (char *) "--argv0", (char *) "ldconfig-argv0",
 | ||||
| +        ldconfig_path, (char *) "--help", NULL
 | ||||
| +      };
 | ||||
| +    struct support_capture_subprocess cap
 | ||||
| +      = support_capture_subprogram (support_objdir_elf_ldso, argv);
 | ||||
| +    support_capture_subprocess_check (&cap, "with --argv0", 0, sc_allow_stdout);
 | ||||
| +    puts ("info: output with --argv0:");
 | ||||
| +    puts (cap.out.buffer);
 | ||||
| +    TEST_VERIFY (strstr (cap.out.buffer, "Usage: ldconfig-argv0 [OPTION...]\n")
 | ||||
| +                 == cap.out.buffer);
 | ||||
| +    support_capture_subprocess_free (&cap);
 | ||||
| +  }
 | ||||
| +
 | ||||
| +  free (ldconfig_path);
 | ||||
| +  return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +#include <support/test-driver.c>
 | ||||
| diff --git a/sysdeps/generic/dl-execve.h b/sysdeps/generic/dl-execve.h
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..5fd097df69e1770c
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/generic/dl-execve.h
 | ||||
| @@ -0,0 +1,25 @@
 | ||||
| +/* execve for the dynamic linker.  Generic stub version.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <errno.h>
 | ||||
| +
 | ||||
| +static int
 | ||||
| +__rtld_execve (const char *path, char *const *argv, char *const *envp)
 | ||||
| +{
 | ||||
| +  return ENOSYS;
 | ||||
| +}
 | ||||
| diff --git a/sysdeps/unix/sysv/linux/dl-execve.h b/sysdeps/unix/sysv/linux/dl-execve.h
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..9ec6539286bb0589
 | ||||
| --- /dev/null
 | ||||
| +++ b/sysdeps/unix/sysv/linux/dl-execve.h
 | ||||
| @@ -0,0 +1,30 @@
 | ||||
| +/* execve for the dynamic linker.  Linux version.
 | ||||
| +   Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <errno.h>
 | ||||
| +
 | ||||
| +static inline int
 | ||||
| +__rtld_execve (const char *path, char *const *argv, char *const *envp)
 | ||||
| +{
 | ||||
| +  INTERNAL_SYSCALL_DECL (err);
 | ||||
| +  long int r = INTERNAL_SYSCALL_CALL (execve, err, path, argv, envp);
 | ||||
| +  if (INTERNAL_SYSCALL_ERROR_P (r, err))
 | ||||
| +    return INTERNAL_SYSCALL_ERRNO (r, err);
 | ||||
| +  else
 | ||||
| +    return 0;
 | ||||
| +}
 | ||||
							
								
								
									
										41
									
								
								SOURCES/glibc-rh2023420-7.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								SOURCES/glibc-rh2023420-7.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,41 @@ | ||||
| commit 2e75604f8337fa4332977f72a8f6726309679edf | ||||
| Author: Florian Weimer <fweimer@redhat.com> | ||||
| Date:   Fri Dec 10 16:06:36 2021 +0100 | ||||
| 
 | ||||
|     elf: Install a symbolic link to ld.so as /usr/bin/ld.so | ||||
|      | ||||
|     This makes ld.so features such as --preload, --audit, | ||||
|     and --list-diagnostics more accessible to end users because they | ||||
|     do not need to know the ABI name of the dynamic loader. | ||||
|      | ||||
|     Reviewed-by: Carlos O'Donell <carlos@redhat.com> | ||||
| 
 | ||||
|  Conflicts: | ||||
| 	elf/Makefile | ||||
| 	  (versioned shared objects downstream) | ||||
| 
 | ||||
| diff --git a/elf/Makefile b/elf/Makefile
 | ||||
| index b3e8ab2792608de7..c552aff350c2faac 100644
 | ||||
| --- a/elf/Makefile
 | ||||
| +++ b/elf/Makefile
 | ||||
| @@ -99,7 +99,7 @@ endif
 | ||||
|  ifeq (yes,$(build-shared)) | ||||
|  extra-objs	= $(all-rtld-routines:%=%.os) soinit.os sofini.os interp.os | ||||
|  generated	+= librtld.os dl-allobjs.os ld.so ldd | ||||
| -install-others	= $(inst_rtlddir)/$(rtld-installed-name)
 | ||||
| +install-others	= $(inst_rtlddir)/$(rtld-installed-name) $(inst_bindir)/ld.so
 | ||||
|  install-bin-script = ldd | ||||
|  endif | ||||
|   | ||||
| @@ -622,6 +622,11 @@ $(inst_rtlddir)/$(rtld-installed-name): \
 | ||||
|  	$(make-target-directory) | ||||
|  	$(make-shlib-link) | ||||
|   | ||||
| +# Creates the relative /usr/bin/ld.so symbolic link.
 | ||||
| +$(inst_bindir)/ld.so: $(inst_rtlddir)/$(rtld-installed-name)
 | ||||
| +	$(make-target-directory)
 | ||||
| +	$(make-link)
 | ||||
| +
 | ||||
|  # Special target called by parent to install just the dynamic linker. | ||||
|  .PHONY: ldso_install | ||||
|  ldso_install: $(inst_rtlddir)/$(rtld-installed-name) | ||||
| @ -1,3 +1,5 @@ | ||||
| Additionally include stdbool.h to fix issues with bool keyword usage. | ||||
| 
 | ||||
| commit 60854f40ea2d420867ed2f0f052ee7fca661dbff | ||||
| Author: Adhemerval Zanella <adhemerval.zanella@linaro.org> | ||||
| Date:   Thu Oct 15 15:14:22 2020 -0300 | ||||
							
								
								
									
										51
									
								
								SOURCES/glibc-rh2033648-1.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								SOURCES/glibc-rh2033648-1.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| commit c36f64aa6dff13b12a1e03a185e75a50fa9f6a4c | ||||
| Author: Hans-Peter Nilsson <hp@axis.com> | ||||
| Date:   Fri Dec 17 21:38:00 2021 +0100 | ||||
| 
 | ||||
|     timezone: handle truncated timezones from tzcode-2021d and later (BZ #28707) | ||||
|      | ||||
|     When using a timezone file with a truncated starting time, | ||||
|     generated by the zic in IANA tzcode-2021d a.k.a. tzlib-2021d | ||||
|     (also in tzlib-2021e; current as of this writing), glibc | ||||
|     asserts in __tzfile_read (on e.g. tzset() for this file) and | ||||
|     you may find lines matching "tzfile.c:435: __tzfile_read: | ||||
|     Assertion `num_types == 1' failed" in your syslog. | ||||
|      | ||||
|     One example of such a file is the tzfile for Asuncion | ||||
|     generated by tzlib-2021e as follows, using the tzlib-2021e zic: | ||||
|     "zic -d DEST -r @1546300800 -L /dev/null -b slim | ||||
|     SOURCE/southamerica".  Note that in its type 2 header, it has | ||||
|     two entries in its "time-types" array (types), but only one | ||||
|     entry in its "transition types" array (type_idxs). | ||||
|      | ||||
|     This is valid and expected already in the published RFC8536, and | ||||
|     not even frowned upon: "Local time for timestamps before the | ||||
|     first transition is specified by the first time type (time type | ||||
|     0)" ... "every nonzero local time type index SHOULD appear at | ||||
|     least once in the transition type array".  Note the "nonzero ... | ||||
|     index".  Until the 2021d zic, index 0 has been shared by the | ||||
|     first valid transition but with 2021d it's separate, set apart | ||||
|     as a placeholder and only "implicitly" indexed.  (A draft update | ||||
|     of the RFC mandates that the entry at index 0 is a placeholder | ||||
|     in this case, hence can no longer be shared.) | ||||
|      | ||||
|             * time/tzfile.c (__tzfile_read): Don't assert when no transitions | ||||
|             are found. | ||||
|      | ||||
|     Co-authored-by: Christopher Wong <Christopher.Wong@axis.com> | ||||
| 
 | ||||
| diff --git a/time/tzfile.c b/time/tzfile.c
 | ||||
| index 190a777152..8668392ad3 100644
 | ||||
| --- a/time/tzfile.c
 | ||||
| +++ b/time/tzfile.c
 | ||||
| @@ -431,8 +431,8 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
 | ||||
|    if (__tzname[0] == NULL) | ||||
|      { | ||||
|        /* This should only happen if there are no transition rules. | ||||
| -	 In this case there should be only one single type.  */
 | ||||
| -      assert (num_types == 1);
 | ||||
| +	 In this case there's usually only one single type, unless
 | ||||
| +	 e.g. the data file has a truncated time-range.  */
 | ||||
|        __tzname[0] = __tzstring (zone_names); | ||||
|      } | ||||
|    if (__tzname[1] == NULL) | ||||
							
								
								
									
										126
									
								
								SOURCES/glibc-rh2033648-2.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								SOURCES/glibc-rh2033648-2.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,126 @@ | ||||
| commit ebe899af0dc3215159a9c896ac6f35b72a18cb6e | ||||
| Author: Hans-Peter Nilsson <hp@axis.com> | ||||
| Date:   Fri Dec 17 21:45:54 2021 +0100 | ||||
| 
 | ||||
|     timezone: test-case for BZ #28707 | ||||
| 
 | ||||
|     This test-case is the tzfile for Asuncion generated by | ||||
|     tzlib-2021e as follows, using the tzlib-2021e zic: "zic -d | ||||
|     DEST -r @1546300800 -L /dev/null -b slim | ||||
|     SOURCE/southamerica".  Note that in its type 2 header, it | ||||
|     has two entries in its "time-types" array (types), but only | ||||
|     one entry in its "transition types" array (type_idxs). | ||||
|    | ||||
|             * timezone/Makefile, timezone/tst-pr28707.c, | ||||
|             timezone/testdata/gen-XT5.sh: New test. | ||||
|      | ||||
|     Co-authored-by: Christopher Wong <Christopher.Wong@axis.com> | ||||
| 
 | ||||
|     Reworked due to timezone/Makefile difference. | ||||
| 
 | ||||
| diff -Nrup a/timezone/Makefile b/timezone/Makefile
 | ||||
| --- a/timezone/Makefile	2021-07-06 15:04:00.000000000 -0400
 | ||||
| +++ b/timezone/Makefile	2022-01-05 15:03:57.433756574 -0500
 | ||||
| @@ -23,7 +23,7 @@ subdir	:= timezone
 | ||||
|  include ../Makeconfig | ||||
|   | ||||
|  others	:= zdump zic | ||||
| -tests	:= test-tz tst-timezone tst-tzset
 | ||||
| +tests	:= test-tz tst-timezone tst-tzset tst-bz28707
 | ||||
|   | ||||
|  generated-dirs += testdata | ||||
|   | ||||
| @@ -85,10 +85,12 @@ $(objpfx)tst-timezone.out: $(addprefix $
 | ||||
|  				       America/Sao_Paulo Asia/Tokyo \ | ||||
|  				       Europe/London) | ||||
|  $(objpfx)tst-tzset.out: $(addprefix $(testdata)/XT, 1 2 3 4) | ||||
| +$(objpfx)tst-bz28707.out: $(testdata)/XT5
 | ||||
|   | ||||
|  test-tz-ENV = TZDIR=$(testdata) | ||||
|  tst-timezone-ENV = TZDIR=$(testdata) | ||||
|  tst-tzset-ENV = TZDIR=$(testdata) | ||||
| +tst-bz28707-ENV = TZDIR=$(testdata)
 | ||||
|   | ||||
|  # Note this must come second in the deps list for $(built-program-cmd) to work. | ||||
|  zic-deps = $(objpfx)zic $(leapseconds) yearistype | ||||
| @@ -122,6 +124,10 @@ $(testdata)/XT%: testdata/XT%
 | ||||
|  	$(make-target-directory) | ||||
|  	cp $< $@ | ||||
|   | ||||
| +$(testdata)/XT%: testdata/gen-XT%.sh
 | ||||
| +	$(SHELL) $< > $@.tmp
 | ||||
| +	mv $@.tmp $@
 | ||||
| +
 | ||||
|  $(objpfx)tzselect: tzselect.ksh $(common-objpfx)config.make | ||||
|  	sed -e 's|/bin/bash|$(BASH)|' \ | ||||
|  	    -e 's|TZDIR=[^}]*|TZDIR=$(zonedir)|' \ | ||||
| diff -Nrup a/timezone/testdata/gen-XT5.sh b/timezone/testdata/gen-XT5.sh
 | ||||
| --- a/timezone/testdata/gen-XT5.sh	1969-12-31 19:00:00.000000000 -0500
 | ||||
| +++ b/timezone/testdata/gen-XT5.sh	2022-01-05 12:50:01.666972313 -0500
 | ||||
| @@ -0,0 +1,16 @@
 | ||||
| +#! /bin/sh
 | ||||
| +
 | ||||
| +# This test-case is the tzfile for America/Asuncion
 | ||||
| +# generated by tzlib-2021e as follows, using the tzlib-2021e
 | ||||
| +# zic: "zic -d DEST -r @1546300800 -L /dev/null -b slim
 | ||||
| +# SOURCE/southamerica".  Note that in its type 2 header, it
 | ||||
| +# has two entries in its "time-types" array (types), but
 | ||||
| +# only one entry in its "transition types" array
 | ||||
| +# (type_idxs).
 | ||||
| +
 | ||||
| +printf \
 | ||||
| +'TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'\
 | ||||
| +'\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0TZif2\0\0\0\0\0\0\0\0'\
 | ||||
| +'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\2\0\0\0\b\0'\
 | ||||
| +'\0\0\0\*\255\200\1\0\0\0\0\0\0\377\377\325\320\1\4-00\0-03\0\n'\
 | ||||
| +'<-04>4<-03>,M10.1.0/0,M3.4.0/0\n'
 | ||||
| diff -Nrup a/timezone/tst-bz28707.c b/timezone/tst-bz28707.c
 | ||||
| --- a/timezone/tst-bz28707.c	1969-12-31 19:00:00.000000000 -0500
 | ||||
| +++ b/timezone/tst-bz28707.c	2022-01-05 12:50:01.666972313 -0500
 | ||||
| @@ -0,0 +1,46 @@
 | ||||
| +/* Copyright (C) 2021 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/>.  */
 | ||||
| +
 | ||||
| +#include <time.h>
 | ||||
| +#include <stdio.h>
 | ||||
| +#include <stdlib.h>
 | ||||
| +#include <string.h>
 | ||||
| +
 | ||||
| +/* Test that we can use a truncated timezone-file, where the time-type
 | ||||
| +   at index 0 is not indexed by the transition-types array (and the
 | ||||
| +   transition-types array does not contain at least both one DST and one
 | ||||
| +   normal time members).  */
 | ||||
| +
 | ||||
| +static int
 | ||||
| +do_test (void)
 | ||||
| +{
 | ||||
| +  if (setenv ("TZ", "XT5", 1))
 | ||||
| +    {
 | ||||
| +      puts ("setenv failed.");
 | ||||
| +      return 1;
 | ||||
| +    }
 | ||||
| +
 | ||||
| +  tzset ();
 | ||||
| +
 | ||||
| +  return
 | ||||
| +    /* Sanity-check that we got the right timezone-name for DST.  For
 | ||||
| +       normal time, we're likely to get "-00" (the "unspecified" marker),
 | ||||
| +       even though the POSIX timezone string says "-04".  Let's not test
 | ||||
| +       that.  */
 | ||||
| +    !(strcmp (tzname[1], "-03") == 0);
 | ||||
| +}
 | ||||
| +#include <support/test-driver.c>
 | ||||
							
								
								
									
										185
									
								
								SOURCES/glibc-rh2033655.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								SOURCES/glibc-rh2033655.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,185 @@ | ||||
| commit ff012870b2c02a62598c04daa1e54632e020fd7d | ||||
| Author: Nikita Popov <npv1310@gmail.com> | ||||
| Date:   Tue Nov 2 13:21:42 2021 +0500 | ||||
| 
 | ||||
|     gconv: Do not emit spurious NUL character in ISO-2022-JP-3 (bug 28524) | ||||
|      | ||||
|     Bugfix 27256 has introduced another issue: | ||||
|     In conversion from ISO-2022-JP-3 encoding, it is possible | ||||
|     to force iconv to emit extra NUL character on internal state reset. | ||||
|     To do this, it is sufficient to feed iconv with escape sequence | ||||
|     which switches active character set. | ||||
|     The simplified check 'data->__statep->__count != ASCII_set' | ||||
|     introduced by the aforementioned bugfix picks that case and | ||||
|     behaves as if '\0' character has been queued thus emitting it. | ||||
|      | ||||
|     To eliminate this issue, these steps are taken: | ||||
|     * Restore original condition | ||||
|     '(data->__statep->__count & ~7) != ASCII_set'. | ||||
|     It is necessary since bits 0-2 may contain | ||||
|     number of buffered input characters. | ||||
|     * Check that queued character is not NUL. | ||||
|     Similar step is taken for main conversion loop. | ||||
|      | ||||
|     Bundled test case follows following logic: | ||||
|     * Try to convert ISO-2022-JP-3 escape sequence | ||||
|     switching active character set | ||||
|     * Reset internal state by providing NULL as input buffer | ||||
|     * Ensure that nothing has been converted. | ||||
|      | ||||
|     Signed-off-by: Nikita Popov <npv1310@gmail.com> | ||||
| 
 | ||||
| Conflicts: | ||||
| 	iconvdata/Makefile | ||||
| 	  (Copyright header.  Usual test backporting differences.) | ||||
| 	iconvdata/iso-2022-jp-3.c | ||||
| 	  (Copyright header.) | ||||
| 
 | ||||
| diff --git a/iconvdata/Makefile b/iconvdata/Makefile
 | ||||
| index 95e5fb8f722a513b..646e2ccd11478646 100644
 | ||||
| --- a/iconvdata/Makefile
 | ||||
| +++ b/iconvdata/Makefile
 | ||||
| @@ -1,4 +1,5 @@
 | ||||
| -# Copyright (C) 1997-2018 Free Software Foundation, Inc.
 | ||||
| +# Copyright (C) 1997-2021 Free Software Foundation, Inc.
 | ||||
| +# Copyright (C) The GNU Toolchain Authors.
 | ||||
|  # This file is part of the GNU C Library. | ||||
|   | ||||
|  # The GNU C Library is free software; you can redistribute it and/or | ||||
| @@ -73,7 +74,8 @@ modules.so := $(addsuffix .so, $(modules))
 | ||||
|  ifeq (yes,$(build-shared)) | ||||
|  tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ | ||||
|  	tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \ | ||||
| -	bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 bug-iconv14
 | ||||
| +	bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 bug-iconv14 \
 | ||||
| +	bug-iconv15
 | ||||
|  ifeq ($(have-thread-library),yes) | ||||
|  tests += bug-iconv3 | ||||
|  endif | ||||
| @@ -321,6 +323,8 @@ $(objpfx)bug-iconv12.out: $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
|  			  $(addprefix $(objpfx),$(modules.so)) | ||||
|  $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \ | ||||
|  			  $(addprefix $(objpfx),$(modules.so)) | ||||
| +$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
 | ||||
| +			  $(addprefix $(objpfx),$(modules.so))
 | ||||
|   | ||||
|  $(objpfx)iconv-test.out: run-iconv-test.sh \ | ||||
|  			 $(addprefix $(objpfx), $(gconv-modules)) \ | ||||
| diff --git a/iconvdata/bug-iconv15.c b/iconvdata/bug-iconv15.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..cc04bd0313a68786
 | ||||
| --- /dev/null
 | ||||
| +++ b/iconvdata/bug-iconv15.c
 | ||||
| @@ -0,0 +1,60 @@
 | ||||
| +/* Bug 28524: Conversion from ISO-2022-JP-3 with iconv
 | ||||
| +   may emit spurious NUL character on state reset.
 | ||||
| +   Copyright (C) The GNU Toolchain Authors.
 | ||||
| +   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/>.  */
 | ||||
| +
 | ||||
| +#include <stddef.h>
 | ||||
| +#include <iconv.h>
 | ||||
| +#include <support/check.h>
 | ||||
| +
 | ||||
| +static int
 | ||||
| +do_test (void)
 | ||||
| +{
 | ||||
| +  char in[] = "\x1b(I";
 | ||||
| +  char *inbuf = in;
 | ||||
| +  size_t inleft = sizeof (in) - 1;
 | ||||
| +  char out[1];
 | ||||
| +  char *outbuf = out;
 | ||||
| +  size_t outleft = sizeof (out);
 | ||||
| +  iconv_t cd;
 | ||||
| +
 | ||||
| +  cd = iconv_open ("UTF8", "ISO-2022-JP-3");
 | ||||
| +  TEST_VERIFY_EXIT (cd != (iconv_t) -1);
 | ||||
| +
 | ||||
| +  /* First call to iconv should alter internal state.
 | ||||
| +     Now, JISX0201_Kana_set is selected and
 | ||||
| +     state value != ASCII_set.  */
 | ||||
| +  TEST_VERIFY (iconv (cd, &inbuf, &inleft, &outbuf, &outleft) != (size_t) -1);
 | ||||
| +
 | ||||
| +  /* No bytes should have been added to
 | ||||
| +     the output buffer at this point.  */
 | ||||
| +  TEST_VERIFY (outbuf == out);
 | ||||
| +  TEST_VERIFY (outleft == sizeof (out));
 | ||||
| +
 | ||||
| +  /* Second call shall emit spurious NUL character in unpatched glibc.  */
 | ||||
| +  TEST_VERIFY (iconv (cd, NULL, NULL, &outbuf, &outleft) != (size_t) -1);
 | ||||
| +
 | ||||
| +  /* No characters are expected to be produced.  */
 | ||||
| +  TEST_VERIFY (outbuf == out);
 | ||||
| +  TEST_VERIFY (outleft == sizeof (out));
 | ||||
| +
 | ||||
| +  TEST_VERIFY_EXIT (iconv_close (cd) != -1);
 | ||||
| +
 | ||||
| +  return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +#include <support/test-driver.c>
 | ||||
| diff --git a/iconvdata/iso-2022-jp-3.c b/iconvdata/iso-2022-jp-3.c
 | ||||
| index 047fab8e8dfbde7e..a2b33b171e56392a 100644
 | ||||
| --- a/iconvdata/iso-2022-jp-3.c
 | ||||
| +++ b/iconvdata/iso-2022-jp-3.c
 | ||||
| @@ -1,5 +1,6 @@
 | ||||
|  /* Conversion module for ISO-2022-JP-3. | ||||
| -   Copyright (C) 1998-2018 Free Software Foundation, Inc.
 | ||||
| +   Copyright (C) 1998-2021 Free Software Foundation, Inc.
 | ||||
| +   Copyright (C) The GNU Toolchain Authors.
 | ||||
|     This file is part of the GNU C Library. | ||||
|     Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998, | ||||
|     and Bruno Haible <bruno@clisp.org>, 2002. | ||||
| @@ -81,20 +82,31 @@ enum
 | ||||
|     the output state to the initial state.  This has to be done during the | ||||
|     flushing.  */ | ||||
|  #define EMIT_SHIFT_TO_INIT \ | ||||
| -  if (data->__statep->__count != ASCII_set)			      \
 | ||||
| +  if ((data->__statep->__count & ~7) != ASCII_set)			      \
 | ||||
|      {									      \ | ||||
|        if (FROM_DIRECTION)						      \ | ||||
|  	{								      \ | ||||
| -	  if (__glibc_likely (outbuf + 4 <= outend))			      \
 | ||||
| +	  uint32_t ch = data->__statep->__count >> 6;			      \
 | ||||
| +									      \
 | ||||
| +	  if (__glibc_unlikely (ch != 0))				      \
 | ||||
|  	    {								      \ | ||||
| -	      /* Write out the last character.  */			      \
 | ||||
| -	      *((uint32_t *) outbuf) = data->__statep->__count >> 6;	      \
 | ||||
| -	      outbuf += sizeof (uint32_t);				      \
 | ||||
| -	      data->__statep->__count = ASCII_set;			\
 | ||||
| +	      if (__glibc_likely (outbuf + 4 <= outend))		      \
 | ||||
| +		{							      \
 | ||||
| +		  /* Write out the last character.  */			      \
 | ||||
| +		  put32u (outbuf, ch);					      \
 | ||||
| +		  outbuf += 4;						      \
 | ||||
| +		  data->__statep->__count &= 7;				      \
 | ||||
| +		  data->__statep->__count |= ASCII_set;			      \
 | ||||
| +		}							      \
 | ||||
| +	      else							      \
 | ||||
| +		/* We don't have enough room in the output buffer.  */	      \
 | ||||
| +		status = __GCONV_FULL_OUTPUT;				      \
 | ||||
|  	    }								      \ | ||||
|  	  else								      \ | ||||
| -	    /* We don't have enough room in the output buffer.  */	      \
 | ||||
| -	    status = __GCONV_FULL_OUTPUT;				      \
 | ||||
| +	    {								      \
 | ||||
| +	      data->__statep->__count &= 7;				      \
 | ||||
| +	      data->__statep->__count |= ASCII_set;			      \
 | ||||
| +	    }								      \
 | ||||
|  	}								      \ | ||||
|        else								      \ | ||||
|  	{								      \ | ||||
							
								
								
									
										54
									
								
								SOURCES/glibc-rh2036955.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								SOURCES/glibc-rh2036955.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | ||||
| commit e5fa62b8db546f8792ec9e5c61e6419f4f8e3f4d | ||||
| Author: Wilco Dijkstra <wdijkstr@arm.com> | ||||
| Date:   Thu Jan 6 14:36:28 2022 +0000 | ||||
| 
 | ||||
|     AArch64: Check for SVE in ifuncs [BZ #28744] | ||||
|      | ||||
|     Add a check for SVE in the A64FX ifuncs for memcpy, memset and memmove. | ||||
|     This fixes BZ #28744. | ||||
| 
 | ||||
| Conflicts: | ||||
| 	sysdeps/aarch64/multiarch/memcpy.c | ||||
| 	sysdeps/aarch64/multiarch/memmove.c | ||||
| 	sysdeps/aarch64/multiarch/memset.c | ||||
| 	  (IFUNC resolver differences in the backport.) | ||||
| 
 | ||||
| diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c
 | ||||
| index e0313c42e82a7b86..a6ebeb06d3bda00f 100644
 | ||||
| --- a/sysdeps/aarch64/multiarch/memcpy.c
 | ||||
| +++ b/sysdeps/aarch64/multiarch/memcpy.c
 | ||||
| @@ -44,7 +44,7 @@ libc_ifunc (__libc_memcpy,
 | ||||
|  		: (IS_THUNDERX2 (midr) || IS_THUNDERX2PA (midr) | ||||
|  		  ? __memcpy_thunderx2 | ||||
|  # if HAVE_AARCH64_SVE_ASM | ||||
| -		  : (IS_A64FX (midr)
 | ||||
| +		  : (IS_A64FX (midr) && sve
 | ||||
|  		     ? __memcpy_a64fx | ||||
|  		     : __memcpy_generic))))); | ||||
|  # else | ||||
| diff --git a/sysdeps/aarch64/multiarch/memmove.c b/sysdeps/aarch64/multiarch/memmove.c
 | ||||
| index d96612b9cf7c3a4e..bea72b3eddde54c0 100644
 | ||||
| --- a/sysdeps/aarch64/multiarch/memmove.c
 | ||||
| +++ b/sysdeps/aarch64/multiarch/memmove.c
 | ||||
| @@ -41,7 +41,7 @@ libc_ifunc (__libc_memmove,
 | ||||
|  	     : (IS_FALKOR (midr) || IS_PHECDA (midr) | ||||
|  		? __memmove_falkor | ||||
|  # if HAVE_AARCH64_SVE_ASM | ||||
| -		: (IS_A64FX (midr)
 | ||||
| +		: (IS_A64FX (midr) && sve
 | ||||
|  		   ? __memmove_a64fx | ||||
|  		   : __memmove_generic)))); | ||||
|  # else | ||||
| diff --git a/sysdeps/aarch64/multiarch/memset.c b/sysdeps/aarch64/multiarch/memset.c
 | ||||
| index 2c8cc72bb0b18474..e7bd412377533f18 100644
 | ||||
| --- a/sysdeps/aarch64/multiarch/memset.c
 | ||||
| +++ b/sysdeps/aarch64/multiarch/memset.c
 | ||||
| @@ -38,7 +38,7 @@ libc_ifunc (__libc_memset,
 | ||||
|  	    ((IS_FALKOR (midr) || IS_PHECDA (midr)) && zva_size == 64 | ||||
|  	     ? __memset_falkor | ||||
|  # if HAVE_AARCH64_SVE_ASM | ||||
| -	     : (IS_A64FX (midr)
 | ||||
| +	     : (IS_A64FX (midr) && sve
 | ||||
|  		? __memset_a64fx | ||||
|  		: __memset_generic))); | ||||
|  # else | ||||
							
								
								
									
										208
									
								
								SOURCES/glibc-rh2061727.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								SOURCES/glibc-rh2061727.patch
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,208 @@ | ||||
| This is a downstream rework of this upstream patch: | ||||
| 
 | ||||
|   [PATCH v2 2/2] nss: Protect against errno changes in function lookup (bug 28953) | ||||
|   <https://sourceware.org/pipermail/libc-alpha/2022-March/137015.html> | ||||
| 
 | ||||
| The NSS module loading code has been rewritten upstream, which is why | ||||
| only the test can be reused.  NSS_DECLARE_MODULE_FUNCTIONS does not yet | ||||
| exist downstream, so this part had to be skipped. | ||||
| 
 | ||||
| diff --git a/nss/Makefile b/nss/Makefile
 | ||||
| index d5c28a6b5ed3661c..e8a7d9c7b3cefcdf 100644
 | ||||
| --- a/nss/Makefile
 | ||||
| +++ b/nss/Makefile
 | ||||
| @@ -59,7 +59,8 @@ tests			= test-netdb test-digits-dots tst-nss-getpwent bug17079 \
 | ||||
|  			  tst-nss-test2 \ | ||||
|  			  tst-nss-test3 \ | ||||
|  			  tst-nss-test4 \ | ||||
| -			  tst-nss-test5
 | ||||
| +			  tst-nss-test5 \
 | ||||
| +			  tst-nss-test_errno
 | ||||
|  xtests			= bug-erange | ||||
|   | ||||
|  tests-container = \ | ||||
| @@ -130,7 +131,7 @@ routines                += $(libnss_files-routines)
 | ||||
|  static-only-routines    += $(libnss_files-routines) | ||||
|  tests-static		+= tst-nss-static | ||||
|  endif | ||||
| -extra-test-objs		+= nss_test1.os nss_test2.os
 | ||||
| +extra-test-objs		+= nss_test1.os nss_test2.os nss_test_errno.os
 | ||||
|   | ||||
|  include ../Rules | ||||
|   | ||||
| @@ -166,10 +167,13 @@ rtld-tests-LDFLAGS += -Wl,--dynamic-list=nss_test.ver
 | ||||
|   | ||||
|  libof-nss_test1 = extramodules | ||||
|  libof-nss_test2 = extramodules | ||||
| +libof-nss_test_errno = extramodules
 | ||||
|  $(objpfx)/libnss_test1.so: $(objpfx)nss_test1.os $(link-libc-deps) | ||||
|  	$(build-module) | ||||
|  $(objpfx)/libnss_test2.so: $(objpfx)nss_test2.os $(link-libc-deps) | ||||
|  	$(build-module) | ||||
| +$(objpfx)/libnss_test_errno.so: $(objpfx)nss_test_errno.os $(link-libc-deps)
 | ||||
| +	$(build-module)
 | ||||
|  $(objpfx)nss_test2.os : nss_test1.c | ||||
|  ifdef libnss_test1.so-version | ||||
|  $(objpfx)/libnss_test1.so$(libnss_test1.so-version): $(objpfx)/libnss_test1.so | ||||
| @@ -179,9 +183,13 @@ ifdef libnss_test2.so-version
 | ||||
|  $(objpfx)/libnss_test2.so$(libnss_test2.so-version): $(objpfx)/libnss_test2.so | ||||
|  	$(make-link) | ||||
|  endif | ||||
| +$(objpfx)/libnss_test_errno.so$(libnss_files.so-version): \
 | ||||
| +  $(objpfx)/libnss_test_errno.so
 | ||||
| +	$(make-link)
 | ||||
|  $(patsubst %,$(objpfx)%.out,$(tests)) : \ | ||||
|  	$(objpfx)/libnss_test1.so$(libnss_test1.so-version) \ | ||||
| -	$(objpfx)/libnss_test2.so$(libnss_test2.so-version)
 | ||||
| +	$(objpfx)/libnss_test2.so$(libnss_test2.so-version) \
 | ||||
| +	$(objpfx)/libnss_test_errno.so$(libnss_files.so-version)
 | ||||
|   | ||||
|  ifeq (yes,$(have-thread-library)) | ||||
|  $(objpfx)tst-cancel-getpwuid_r: $(shared-thread-library) | ||||
| diff --git a/nss/nss_test_errno.c b/nss/nss_test_errno.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..ca75c890aa057869
 | ||||
| --- /dev/null
 | ||||
| +++ b/nss/nss_test_errno.c
 | ||||
| @@ -0,0 +1,53 @@
 | ||||
| +/* NSS service provider with errno clobber.
 | ||||
| +   Copyright (C) 2022 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/>.  */
 | ||||
| +
 | ||||
| +#include <errno.h>
 | ||||
| +#include <nss.h>
 | ||||
| +#include <pwd.h>
 | ||||
| +#include <stdlib.h>
 | ||||
| +
 | ||||
| +static void __attribute__ ((constructor))
 | ||||
| +init (void)
 | ||||
| +{
 | ||||
| +  /* An arbitrary error code which is otherwise not used.  */
 | ||||
| +  errno = ELIBBAD;
 | ||||
| +}
 | ||||
| +
 | ||||
| +/* Lookup functions for pwd follow that do not return any data.  */
 | ||||
| +
 | ||||
| +enum nss_status
 | ||||
| +_nss_test_errno_setpwent (int stayopen)
 | ||||
| +{
 | ||||
| +  setenv ("_nss_test_errno_setpwent", "yes", 1);
 | ||||
| +  return NSS_STATUS_SUCCESS;
 | ||||
| +}
 | ||||
| +
 | ||||
| +enum nss_status
 | ||||
| +_nss_test_errno_getpwent_r (struct passwd *result,
 | ||||
| +                            char *buffer, size_t size, int *errnop)
 | ||||
| +{
 | ||||
| +  setenv ("_nss_test_errno_getpwent_r", "yes", 1);
 | ||||
| +  return NSS_STATUS_NOTFOUND;
 | ||||
| +}
 | ||||
| +
 | ||||
| +enum nss_status
 | ||||
| +_nss_test_errno_endpwent (void)
 | ||||
| +{
 | ||||
| +  setenv ("_nss_test_errno_endpwent", "yes", 1);
 | ||||
| +  return NSS_STATUS_SUCCESS;
 | ||||
| +}
 | ||||
| diff --git a/nss/nsswitch.c b/nss/nsswitch.c
 | ||||
| index 17adf1ef03f93d60..e59ab674e0426b26 100644
 | ||||
| --- a/nss/nsswitch.c
 | ||||
| +++ b/nss/nsswitch.c
 | ||||
| @@ -401,6 +401,7 @@ void *
 | ||||
|  __nss_lookup_function (service_user *ni, const char *fct_name) | ||||
|  { | ||||
|    void **found, *result; | ||||
| +  int saved_errno = errno;
 | ||||
|   | ||||
|    /* We now modify global data.  Protect it.  */ | ||||
|    __libc_lock_lock (lock); | ||||
| @@ -523,6 +524,8 @@ __nss_lookup_function (service_user *ni, const char *fct_name)
 | ||||
|    /* Remove the lock.  */ | ||||
|    __libc_lock_unlock (lock); | ||||
|   | ||||
| +  __set_errno (saved_errno);
 | ||||
| +
 | ||||
|    return result; | ||||
|  } | ||||
|  libc_hidden_def (__nss_lookup_function) | ||||
| diff --git a/nss/tst-nss-test_errno.c b/nss/tst-nss-test_errno.c
 | ||||
| new file mode 100644 | ||||
| index 0000000000000000..d2c42dd363a38b0e
 | ||||
| --- /dev/null
 | ||||
| +++ b/nss/tst-nss-test_errno.c
 | ||||
| @@ -0,0 +1,61 @@
 | ||||
| +/* getpwent failure when dlopen clobbers errno (bug 28953).
 | ||||
| +   Copyright (C) 2022 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/>.  */
 | ||||
| +
 | ||||
| +#include <nss.h>
 | ||||
| +#include <support/check.h>
 | ||||
| +#include <stdlib.h>
 | ||||
| +#include <errno.h>
 | ||||
| +#include <stdbool.h>
 | ||||
| +#include <pwd.h>
 | ||||
| +#include <string.h>
 | ||||
| +
 | ||||
| +static int
 | ||||
| +do_test (void)
 | ||||
| +{
 | ||||
| +  __nss_configure_lookup ("passwd", "files test_errno");
 | ||||
| +
 | ||||
| +  errno = 0;
 | ||||
| +  setpwent ();
 | ||||
| +  TEST_COMPARE (errno, 0);
 | ||||
| +
 | ||||
| +  bool root_seen = false;
 | ||||
| +  while (true)
 | ||||
| +    {
 | ||||
| +      errno = 0;
 | ||||
| +      struct passwd *e = getpwent ();
 | ||||
| +      if (e == NULL)
 | ||||
| +        break;
 | ||||
| +      if (strcmp (e->pw_name, "root"))
 | ||||
| +        root_seen = true;
 | ||||
| +    }
 | ||||
| +
 | ||||
| +  TEST_COMPARE (errno, 0);
 | ||||
| +  TEST_VERIFY (root_seen);
 | ||||
| +
 | ||||
| +  errno = 0;
 | ||||
| +  endpwent ();
 | ||||
| +  TEST_COMPARE (errno, 0);
 | ||||
| +
 | ||||
| +  TEST_COMPARE_STRING (getenv ("_nss_test_errno_setpwent"), "yes");
 | ||||
| +  TEST_COMPARE_STRING (getenv ("_nss_test_errno_getpwent_r"), "yes");
 | ||||
| +  TEST_COMPARE_STRING (getenv ("_nss_test_errno_endpwent"), "yes");
 | ||||
| +
 | ||||
| +  return 0;
 | ||||
| +}
 | ||||
| +
 | ||||
| +#include <support/test-driver.c>
 | ||||
							
								
								
									
										112
									
								
								SOURCES/wrap-find-debuginfo.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										112
									
								
								SOURCES/wrap-find-debuginfo.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,112 @@ | ||||
| #!/bin/bash | ||||
| # Wrapper script for find-debuginfo.sh | ||||
| # | ||||
| # Usage: | ||||
| #  wrap-find-debuginfo.sh SYSROOT-PATH SCRIPT-PATH SCRIPT-ARGS... | ||||
| # | ||||
| # The wrapper saves the original version of ld.so found in SYSROOT-PATH, | ||||
| # invokes SCRIPT-PATH with SCRIPT-ARGS, and then restores the | ||||
| # LDSO-PATH file, followed by note merging and DWZ compression. | ||||
| # As a result, ld.so has (mostly) unchanged debuginfo even | ||||
| # after debuginfo extraction. | ||||
| # | ||||
| # For libc.so.6 and other shared objects, a set of strategic symbols | ||||
| # is preserved in .symtab that are frequently used in valgrind | ||||
| # suppressions and elsewhere. | ||||
| 
 | ||||
| set -evx | ||||
| 
 | ||||
| tar_tmp="$(mktemp)" | ||||
| 
 | ||||
| # Prefer a separately installed debugedit over the RPM-integrated one. | ||||
| if command -v debugedit >/dev/null ; then | ||||
|     debugedit=debugedit | ||||
| else | ||||
|     debugedit=/usr/lib/rpm/debugedit | ||||
| fi | ||||
| 
 | ||||
| cleanup () { | ||||
|     rm -f "$tar_tmp" | ||||
| } | ||||
| trap cleanup 0 | ||||
| 
 | ||||
| sysroot_path="$1" | ||||
| shift | ||||
| script_path="$1" | ||||
| shift | ||||
| 
 | ||||
| # See run_ldso setting in glibc.spec. | ||||
| ldso_list=`cd "$sysroot_path"; find . -name 'ld-*.so' -type f` | ||||
| libc_list=`cd "$sysroot_path"; find . -name 'libc-*.so' -type f` | ||||
| libdl_list=`cd "$sysroot_path"; find . -name 'libdl-*.so' -type f` | ||||
| libpthread_list=`cd "$sysroot_path"; find . -name 'libpthread-*.so' -type f` | ||||
| librt_list=`cd "$sysroot_path"; find . -name 'librt-*.so' -type f` | ||||
| 
 | ||||
| full_list="$ldso_list $libc_list $libdl_list $libpthread_list $librt_list" | ||||
| 
 | ||||
| # Preserve the original files. | ||||
| (cd "$sysroot_path"; ls -l $full_list) | ||||
| (cd "$sysroot_path"; tar cvf "$tar_tmp" $full_list) | ||||
| 
 | ||||
| # Run the debuginfo extraction. | ||||
| "$script_path" "$@" | ||||
| 
 | ||||
| # Restore the original files. | ||||
| (cd "$sysroot_path"; tar xf "$tar_tmp") | ||||
| (cd "$sysroot_path"; ls -l $full_list) | ||||
| 
 | ||||
| # Reduce the size of notes.  Primarily for annobin. | ||||
| for p in $full_list | ||||
| do | ||||
|     objcopy --merge-notes "$sysroot_path/$p" | ||||
| done | ||||
| 
 | ||||
| # libc.so.6 and other shared objects: Reduce to valuable symbols. | ||||
| # Eliminate file symbols, annobin symbols, and symbols used by the | ||||
| # glibc build to implement hidden aliases (__EI_*).  We would also | ||||
| # like to remove __GI_* symbols, but even listing them explicitly (as | ||||
| # in -K __GI_strlen) still causes strip to remove them, so there is no | ||||
| # filtering of __GI_* here.  (Debuginfo is gone after this, so no need | ||||
| # to optimize it.) | ||||
| for p in $libc_list $libdl_list $libpthread_list $librt_list ; do | ||||
|     strip -w \ | ||||
| 	  -K '*' \ | ||||
| 	  -K '!*.c' \ | ||||
| 	  -K '!*.os' \ | ||||
| 	  -K '!.annobin_*' \ | ||||
| 	  -K '!__EI_*' \ | ||||
| 	  -K '!__PRETTY_FUNCTION__*' \ | ||||
| 	  "$sysroot_path/$p" | ||||
| done | ||||
| 
 | ||||
| # ld.so: Rewrite the source file paths to match the extracted | ||||
| # locations.  First compute the arguments for invoking debugedit. | ||||
| # See find-debuginfo.sh. | ||||
| debug_dest_name="/usr/src/debug" | ||||
| last_arg= | ||||
| while true ; do | ||||
|     arg="$1" | ||||
|     shift || break | ||||
|     case "$arg" in | ||||
| 	(--unique-debug-src-base) | ||||
| 	    debug_dest_name="/usr/src/debug/$1" | ||||
| 	    shift | ||||
| 	    ;; | ||||
| 	(-*) | ||||
| 	    ;; | ||||
| 	(*) | ||||
| 	    last_arg="$arg" | ||||
| 	    ;; | ||||
|     esac | ||||
| done | ||||
| debug_base_name=${last_arg:-$RPM_BUILD_ROOT} | ||||
| for p in $ldso_list | ||||
| do | ||||
|     $debugedit -b "$debug_base_name" -d "$debug_dest_name" -n "$sysroot_path/$p" | ||||
| done | ||||
| 
 | ||||
| # Apply single-file DWARF optimization. | ||||
| for ldso in $ldso_list | ||||
| do | ||||
|     dwz "$sysroot_path/$p" | ||||
| done | ||||
							
								
								
									
										599
									
								
								SPECS/glibc.spec
									
									
									
									
									
								
							
							
						
						
									
										599
									
								
								SPECS/glibc.spec
									
									
									
									
									
								
							| @ -1,6 +1,6 @@ | ||||
| %define glibcsrcdir glibc-2.28 | ||||
| %define glibcversion 2.28 | ||||
| %define glibcrelease 164%{?dist}.3 | ||||
| %define glibcrelease 189.1%{?dist} | ||||
| # Pre-release tarballs are pulled in from git using a command that is | ||||
| # effectively: | ||||
| # | ||||
| @ -85,6 +85,47 @@ | ||||
| # here. If the arch is not listed here then a single core debuginfo package | ||||
| # will be created for the architecture. | ||||
| %define debuginfocommonarches %{biarcharches} alpha alphaev6 | ||||
| 
 | ||||
| ############################################################################## | ||||
| # Utility functions for pre/post scripts.  Stick them at the beginning of | ||||
| # any lua %pre, %post, %postun, etc. sections to have them expand into | ||||
| # those scripts.  It only works in lua sections and not anywhere else. | ||||
| %define glibc_post_funcs() \ | ||||
| -- We use lua posix.exec because there may be no shell that we can \ | ||||
| -- run during glibc upgrade.  We used to implement much of %%post as a \ | ||||
| -- C program, but from an overall maintenance perspective the lua in \ | ||||
| -- the spec file was simpler and safer given the operations required. \ | ||||
| -- All lua code will be ignored by rpm-ostree; see: \ | ||||
| -- https://github.com/projectatomic/rpm-ostree/pull/1869 \ | ||||
| -- If we add new lua actions to the %%post code we should coordinate \ | ||||
| -- with rpm-ostree and ensure that their glibc install is functional. \ | ||||
| function post_exec (program, ...) \ | ||||
|   local pid = posix.fork () \ | ||||
|   if pid == 0 then \ | ||||
|     posix.exec (program, ...) \ | ||||
|     assert (nil) \ | ||||
|   elseif pid > 0 then \ | ||||
|     posix.wait (pid) \ | ||||
|   end \ | ||||
| end \ | ||||
| \ | ||||
| function update_gconv_modules_cache () \ | ||||
|   local iconv_dir = "%{_libdir}/gconv" \ | ||||
|   local iconv_cache = iconv_dir .. "/gconv-modules.cache" \ | ||||
|   local iconv_modules = iconv_dir .. "/gconv-modules" \ | ||||
|   if (posix.utime (iconv_modules) == 0) then \ | ||||
|     if (posix.utime (iconv_cache) == 0) then \ | ||||
|       post_exec ("%{_prefix}/sbin/iconvconfig", \ | ||||
| 		 "-o", iconv_cache, \ | ||||
| 		 "--nostdlib", \ | ||||
| 		 iconv_dir) \ | ||||
|     else \ | ||||
|       io.stdout:write ("Error: Missing " .. iconv_cache .. " file.\n") \ | ||||
|     end \ | ||||
|   end \ | ||||
| end \ | ||||
| %{nil} | ||||
| 
 | ||||
| ############################################################################## | ||||
| # %%package glibc - The GNU C Library (glibc) core package. | ||||
| ############################################################################## | ||||
| @ -135,6 +176,23 @@ Source11: SUPPORTED | ||||
| # Include in the source RPM for reference. | ||||
| Source12: ChangeLog.old | ||||
| 
 | ||||
| Source13: wrap-find-debuginfo.sh | ||||
| 
 | ||||
| ###################################################################### | ||||
| # Activate the wrapper script for debuginfo generation, by rewriting | ||||
| # the definition of __debug_install_post. | ||||
| %{lua: | ||||
| local wrapper = rpm.expand("%{SOURCE13}") | ||||
| local sysroot = rpm.expand("%{glibc_sysroot}") | ||||
| local original = rpm.expand("%{__find_debuginfo}") | ||||
| rpm.define("__find_debuginfo  " .. wrapper .. " " .. sysroot .. " " .. original) | ||||
| } | ||||
| 
 | ||||
| # The wrapper script relies on the fact that debugedit does not change | ||||
| # build IDs. | ||||
| %define _no_recompute_build_ids 1 | ||||
| %undefine _unique_build_ids | ||||
| 
 | ||||
| ############################################################################## | ||||
| # Patches: | ||||
| # - See each individual patch file for origin and upstream status. | ||||
| @ -719,18 +777,85 @@ Patch582: glibc-rh1966472-1.patch | ||||
| Patch583: glibc-rh1966472-2.patch | ||||
| Patch584: glibc-rh1966472-3.patch | ||||
| Patch585: glibc-rh1966472-4.patch | ||||
| Patch586: glibc-rh2032280-1.patch | ||||
| Patch587: glibc-rh2032280-2.patch | ||||
| Patch588: glibc-rh2032280-3.patch | ||||
| Patch589: glibc-rh2032280-4.patch | ||||
| Patch590: glibc-rh2032280-5.patch | ||||
| Patch591: glibc-rh2032280-6.patch | ||||
| Patch592: glibc-rh2032280-7.patch | ||||
| Patch593: glibc-rh2045062-1.patch | ||||
| Patch594: glibc-rh2045062-2.patch | ||||
| Patch595: glibc-rh2045062-3.patch | ||||
| Patch596: glibc-rh2045062-4.patch | ||||
| Patch597: glibc-rh2045062-5.patch | ||||
| Patch586: glibc-rh1971664-1.patch | ||||
| Patch587: glibc-rh1971664-2.patch | ||||
| Patch588: glibc-rh1971664-3.patch | ||||
| Patch589: glibc-rh1971664-4.patch | ||||
| Patch590: glibc-rh1971664-5.patch | ||||
| Patch591: glibc-rh1971664-6.patch | ||||
| Patch592: glibc-rh1971664-7.patch | ||||
| Patch593: glibc-rh1971664-8.patch | ||||
| Patch594: glibc-rh1971664-9.patch | ||||
| Patch595: glibc-rh1971664-10.patch | ||||
| Patch596: glibc-rh1971664-11.patch | ||||
| Patch597: glibc-rh1971664-12.patch | ||||
| Patch598: glibc-rh1971664-13.patch | ||||
| Patch599: glibc-rh1971664-14.patch | ||||
| Patch600: glibc-rh1971664-15.patch | ||||
| Patch601: glibc-rh1977614.patch | ||||
| Patch602: glibc-rh1983203-1.patch | ||||
| Patch603: glibc-rh1983203-2.patch | ||||
| Patch604: glibc-rh2021452.patch | ||||
| Patch605: glibc-rh1937515.patch | ||||
| Patch606: glibc-rh1934162-1.patch | ||||
| Patch607: glibc-rh1934162-2.patch | ||||
| Patch608: glibc-rh2000374.patch | ||||
| Patch609: glibc-rh1991001-1.patch | ||||
| Patch610: glibc-rh1991001-2.patch | ||||
| Patch611: glibc-rh1991001-3.patch | ||||
| Patch612: glibc-rh1991001-4.patch | ||||
| Patch613: glibc-rh1991001-5.patch | ||||
| Patch614: glibc-rh1991001-6.patch | ||||
| Patch615: glibc-rh1991001-7.patch | ||||
| Patch616: glibc-rh1991001-8.patch | ||||
| Patch617: glibc-rh1991001-9.patch | ||||
| Patch618: glibc-rh1991001-10.patch | ||||
| Patch619: glibc-rh1991001-11.patch | ||||
| Patch620: glibc-rh1991001-12.patch | ||||
| Patch621: glibc-rh1991001-13.patch | ||||
| Patch622: glibc-rh1991001-14.patch | ||||
| Patch623: glibc-rh1991001-15.patch | ||||
| Patch624: glibc-rh1991001-16.patch | ||||
| Patch625: glibc-rh1991001-17.patch | ||||
| Patch626: glibc-rh1991001-18.patch | ||||
| Patch627: glibc-rh1991001-19.patch | ||||
| Patch628: glibc-rh1991001-20.patch | ||||
| Patch629: glibc-rh1991001-21.patch | ||||
| Patch630: glibc-rh1991001-22.patch | ||||
| Patch631: glibc-rh1929928-1.patch | ||||
| Patch632: glibc-rh1929928-2.patch | ||||
| Patch633: glibc-rh1929928-3.patch | ||||
| Patch634: glibc-rh1929928-4.patch | ||||
| Patch635: glibc-rh1929928-5.patch | ||||
| Patch636: glibc-rh1984802-1.patch | ||||
| Patch637: glibc-rh1984802-2.patch | ||||
| Patch638: glibc-rh1984802-3.patch | ||||
| Patch639: glibc-rh2023420-1.patch | ||||
| Patch640: glibc-rh2023420-2.patch | ||||
| Patch641: glibc-rh2023420-3.patch | ||||
| Patch642: glibc-rh2023420-4.patch | ||||
| Patch643: glibc-rh2023420-5.patch | ||||
| Patch644: glibc-rh2023420-6.patch | ||||
| Patch645: glibc-rh2023420-7.patch | ||||
| Patch646: glibc-rh2033648-1.patch | ||||
| Patch647: glibc-rh2033648-2.patch | ||||
| Patch648: glibc-rh2036955.patch | ||||
| Patch649: glibc-rh2033655.patch | ||||
| Patch650: glibc-rh2007327-1.patch | ||||
| Patch651: glibc-rh2007327-2.patch | ||||
| Patch652: glibc-rh2032281-1.patch | ||||
| Patch653: glibc-rh2032281-2.patch | ||||
| Patch654: glibc-rh2032281-3.patch | ||||
| Patch655: glibc-rh2032281-4.patch | ||||
| Patch656: glibc-rh2032281-5.patch | ||||
| Patch657: glibc-rh2032281-6.patch | ||||
| Patch658: glibc-rh2032281-7.patch | ||||
| Patch659: glibc-rh2045063-1.patch | ||||
| Patch660: glibc-rh2045063-2.patch | ||||
| Patch661: glibc-rh2045063-3.patch | ||||
| Patch662: glibc-rh2045063-4.patch | ||||
| Patch663: glibc-rh2045063-5.patch | ||||
| Patch664: glibc-rh2061727.patch | ||||
| 
 | ||||
| ############################################################################## | ||||
| # Continued list of core "glibc" package information: | ||||
| @ -760,11 +885,6 @@ Recommends: (nss_db(x86-32) if nss_db(x86-64)) | ||||
| BuildRequires: gd-devel libpng-devel zlib-devel | ||||
| %endif | ||||
| %if %{with docs} | ||||
| # Removing texinfo will cause check-safety.sh test to fail because it seems to | ||||
| # trigger documentation generation based on dependencies.  We need to fix this | ||||
| # upstream in some way that doesn't depend on generating docs to validate the | ||||
| # texinfo.  I expect it's simply the wrong dependency for that target. | ||||
| BuildRequires: texinfo >= 5.0 | ||||
| %endif | ||||
| %if %{without bootstrap} | ||||
| BuildRequires: libselinux-devel >= 1.33.4-3 | ||||
| @ -825,7 +945,8 @@ Conflicts: prelink < 0.4.2 | ||||
| 
 | ||||
| %if 0%{?_enable_debug_packages} | ||||
| BuildRequires: elfutils >= 0.72 | ||||
| BuildRequires: rpm >= 4.2-0.56 | ||||
| # -20 adds __find_debuginfo macro | ||||
| BuildRequires: rpm >= 4.14.3-20 | ||||
| %endif | ||||
| 
 | ||||
| %if %{without bootstrap} | ||||
| @ -861,6 +982,10 @@ BuildRequires: libidn2 | ||||
| Requires: glibc-langpack = %{version}-%{release} | ||||
| Suggests: glibc-all-langpacks = %{version}-%{release} | ||||
| 
 | ||||
| # Suggest extra gconv modules so that they are installed by default but can be | ||||
| # removed if needed to build a minimal OS image. | ||||
| Recommends: glibc-gconv-extra%{_isa} = %{version}-%{release} | ||||
| 
 | ||||
| %description | ||||
| The glibc package contains standard libraries which are used by | ||||
| multiple programs on the system. In order to save disk space and | ||||
| @ -908,6 +1033,26 @@ executables. | ||||
| Install glibc-devel if you are going to develop programs which will | ||||
| use the standard C libraries. | ||||
| 
 | ||||
| ############################################################################## | ||||
| # glibc "doc" sub-package | ||||
| ############################################################################## | ||||
| %if %{with docs} | ||||
| %package doc | ||||
| Summary: Documentation for GNU libc | ||||
| BuildArch: noarch | ||||
| Requires: %{name} = %{version}-%{release} | ||||
| 
 | ||||
| # Removing texinfo will cause check-safety.sh test to fail because it seems to | ||||
| # trigger documentation generation based on dependencies.  We need to fix this | ||||
| # upstream in some way that doesn't depend on generating docs to validate the | ||||
| # texinfo.  I expect it's simply the wrong dependency for that target. | ||||
| BuildRequires: texinfo >= 5.0 | ||||
| 
 | ||||
| %description doc | ||||
| The glibc-doc package contains The GNU C Library Reference Manual in info | ||||
| format.  Additional package documentation is also provided. | ||||
| %endif | ||||
| 
 | ||||
| ############################################################################## | ||||
| # glibc "static" sub-package | ||||
| ############################################################################## | ||||
| @ -1110,6 +1255,15 @@ nothing else. It is designed for assembling a minimal system. | ||||
| %files minimal-langpack | ||||
| %endif | ||||
| 
 | ||||
| # Infrequently used iconv converter modules. | ||||
| %package gconv-extra | ||||
| Summary: All iconv converter modules for %{name}. | ||||
| Requires: %{name}%{_isa} = %{version}-%{release} | ||||
| Requires: %{name}-common = %{version}-%{release} | ||||
| 
 | ||||
| %description gconv-extra | ||||
| This package contains all iconv converter modules built in %{name}. | ||||
| 
 | ||||
| ############################################################################## | ||||
| # glibc "nscd" sub-package | ||||
| ############################################################################## | ||||
| @ -1192,62 +1346,6 @@ which can be helpful during program debugging. | ||||
| 
 | ||||
| If unsure if you need this, don't install this package. | ||||
| 
 | ||||
| ############################################################################## | ||||
| # glibc core "debuginfo" sub-package | ||||
| ############################################################################## | ||||
| %if 0%{?_enable_debug_packages} | ||||
| %define debug_package %{nil} | ||||
| %define __debug_install_post %{nil} | ||||
| %global __debug_package 1 | ||||
| # Disable thew new features that glibc packages don't use. | ||||
| %undefine _debugsource_packages | ||||
| %undefine _debuginfo_subpackages | ||||
| %undefine _unique_debug_names | ||||
| %undefine _unique_debug_srcs | ||||
| 
 | ||||
| %package debuginfo | ||||
| Summary: Debug information for package %{name} | ||||
| AutoReqProv: no | ||||
| %ifarch %{debuginfocommonarches} | ||||
| Requires: glibc-debuginfo-common = %{version}-%{release} | ||||
| %else | ||||
| %ifarch %{ix86} %{sparc} | ||||
| Obsoletes: glibc-debuginfo-common | ||||
| %endif | ||||
| %endif | ||||
| 
 | ||||
| %description debuginfo | ||||
| This package provides debug information for package %{name}. | ||||
| Debug information is useful when developing applications that use this | ||||
| package or when debugging this package. | ||||
| 
 | ||||
| This package also contains static standard C libraries with | ||||
| debugging information.  You need this only if you want to step into | ||||
| C library routines during debugging programs statically linked against | ||||
| one or more of the standard C libraries. | ||||
| To use this debugging information, you need to link binaries | ||||
| with -static -L%{_prefix}/lib/debug%{_libdir} compiler options. | ||||
| 
 | ||||
| ############################################################################## | ||||
| # glibc common "debuginfo-common" sub-package | ||||
| ############################################################################## | ||||
| %ifarch %{debuginfocommonarches} | ||||
| 
 | ||||
| %package debuginfo-common | ||||
| Summary: Debug information for package %{name} | ||||
| AutoReqProv: no | ||||
| 
 | ||||
| %description debuginfo-common | ||||
| This package provides debug information for package %{name}. | ||||
| Debug information is useful when developing applications that use this | ||||
| package or when debugging this package. | ||||
| 
 | ||||
| %comment Matches: %ifarch %{debuginfocommonarches} | ||||
| %endif | ||||
| 
 | ||||
| %comment Matches: %if 0%{?_enable_debug_packages} | ||||
| %endif | ||||
| 
 | ||||
| %if %{with benchtests} | ||||
| %package benchtests | ||||
| Summary: Benchmarking binaries and scripts for %{name} | ||||
| @ -1614,6 +1712,9 @@ fi | ||||
| # Compress all of the info files. | ||||
| gzip -9nvf %{glibc_sysroot}%{_infodir}/libc* | ||||
| 
 | ||||
| # Copy the debugger interface documentation over to the right location | ||||
| mkdir -p %{glibc_sysroot}%{_docdir}/glibc | ||||
| cp elf/rtld-debugger-interface.txt %{glibc_sysroot}%{_docdir}/glibc | ||||
| %else | ||||
| rm -f %{glibc_sysroot}%{_infodir}/dir | ||||
| rm -f %{glibc_sysroot}%{_infodir}/libc.info* | ||||
| @ -1705,15 +1806,6 @@ chmod 644 %{glibc_sysroot}%{_libdir}/gconv/gconv-modules.cache | ||||
| #   archives we might have added. | ||||
| ############################################################################## | ||||
| 
 | ||||
| # If we are building a debug package then copy all of the static archives | ||||
| # into the debug directory to keep them as unstripped copies. | ||||
| %if 0%{?_enable_debug_packages} | ||||
| mkdir -p %{glibc_sysroot}%{_prefix}/lib/debug%{_libdir} | ||||
| cp -a %{glibc_sysroot}%{_libdir}/*.a \ | ||||
| 	%{glibc_sysroot}%{_prefix}/lib/debug%{_libdir}/ | ||||
| rm -f %{glibc_sysroot}%{_prefix}/lib/debug%{_libdir}/*_p.a | ||||
| %endif | ||||
| 
 | ||||
| # Remove any zoneinfo files; they are maintained by tzdata. | ||||
| rm -rf %{glibc_sysroot}%{_prefix}/share/zoneinfo | ||||
| 
 | ||||
| @ -1727,7 +1819,14 @@ touch -r %{SOURCE0} %{glibc_sysroot}/etc/ld.so.conf | ||||
| touch -r sunrpc/etc.rpc %{glibc_sysroot}/etc/rpc | ||||
| 
 | ||||
| pushd build-%{target} | ||||
| $GCC -Os -g -static -o build-locale-archive %{SOURCE1} \ | ||||
| $GCC -Os -g \ | ||||
| %ifarch %{pie_arches} | ||||
| 	-fPIE \ | ||||
| 	-static-pie \ | ||||
| %else | ||||
| 	-static \ | ||||
| %endif | ||||
| 	 -o build-locale-archive %{SOURCE1} \ | ||||
| 	../build-%{target}/locale/locarchive.o \ | ||||
| 	../build-%{target}/locale/md5.o \ | ||||
| 	../build-%{target}/locale/record-status.o \ | ||||
| @ -1737,12 +1836,6 @@ $GCC -Os -g -static -o build-locale-archive %{SOURCE1} \ | ||||
| install -m 700 build-locale-archive %{glibc_sysroot}%{_prefix}/sbin/build-locale-archive | ||||
| popd | ||||
| 
 | ||||
| # Lastly copy some additional documentation for the packages. | ||||
| rm -rf documentation | ||||
| mkdir documentation | ||||
| cp timezone/README documentation/README.timezone | ||||
| cp posix/gai.conf documentation/ | ||||
| 
 | ||||
| %ifarch s390x | ||||
| # Compatibility symlink | ||||
| mkdir -p %{glibc_sysroot}/lib | ||||
| @ -1767,6 +1860,7 @@ cp benchtests/scripts/benchout.schema.json %{glibc_sysroot}%{_prefix}/libexec/gl | ||||
| cp benchtests/scripts/compare_bench.py %{glibc_sysroot}%{_prefix}/libexec/glibc-benchtests/ | ||||
| cp benchtests/scripts/import_bench.py %{glibc_sysroot}%{_prefix}/libexec/glibc-benchtests/ | ||||
| cp benchtests/scripts/validate_benchout.py %{glibc_sysroot}%{_prefix}/libexec/glibc-benchtests/ | ||||
| %endif | ||||
| 
 | ||||
| %if 0%{?_enable_debug_packages} | ||||
| # The #line directives gperf generates do not give the proper | ||||
| @ -1777,6 +1871,7 @@ popd | ||||
| pushd iconv | ||||
| ln -s ../locale/programs/charmap-kw.gperf . | ||||
| popd | ||||
| %endif | ||||
| 
 | ||||
| %if %{with docs} | ||||
| # Remove the `dir' info-heirarchy file which will be maintained | ||||
| @ -1861,6 +1956,8 @@ ar cr %{glibc_sysroot}%{_prefix}/%{_lib}/libpthread_nonshared.a | ||||
| #	- Files for the nscd subpackage. | ||||
| # * devel.filelist | ||||
| #	- Files for the devel subpackage. | ||||
| # * doc.filelist | ||||
| #	- Files for the documentation subpackage. | ||||
| # * headers.filelist | ||||
| #	- Files for the headers subpackage. | ||||
| # * static.filelist | ||||
| @ -1874,11 +1971,6 @@ ar cr %{glibc_sysroot}%{_prefix}/%{_lib}/libpthread_nonshared.a | ||||
| #       - File list with the .so symbolic links for NSS packages. | ||||
| # * compat-libpthread-nonshared.filelist. | ||||
| #	- File list for compat-libpthread-nonshared subpackage. | ||||
| # * debuginfo.filelist | ||||
| #	- Files for the glibc debuginfo package. | ||||
| # * debuginfocommon.filelist | ||||
| #	- Files for the glibc common debuginfo package. | ||||
| # | ||||
| 
 | ||||
| # Create the main file lists. This way we can append to any one of them later | ||||
| # wihtout having to create it. Note these are removed at the start of the | ||||
| @ -1887,8 +1979,10 @@ touch master.filelist | ||||
| touch glibc.filelist | ||||
| touch common.filelist | ||||
| touch utils.filelist | ||||
| touch gconv.filelist | ||||
| touch nscd.filelist | ||||
| touch devel.filelist | ||||
| touch doc.filelist | ||||
| touch headers.filelist | ||||
| touch static.filelist | ||||
| touch libnsl.filelist | ||||
| @ -1896,8 +1990,6 @@ touch nss_db.filelist | ||||
| touch nss_hesiod.filelist | ||||
| touch nss-devel.filelist | ||||
| touch compat-libpthread-nonshared.filelist | ||||
| touch debuginfo.filelist | ||||
| touch debuginfocommon.filelist | ||||
| 
 | ||||
| ############################################################################### | ||||
| # Master file list, excluding a few things. | ||||
| @ -1909,10 +2001,10 @@ touch debuginfocommon.filelist | ||||
|   find %{glibc_sysroot} \( -type f -o -type l \) \ | ||||
|        \( \ | ||||
| 	 -name etc -printf "%%%%config " -o \ | ||||
| 	 -name gconv-modules \ | ||||
| 	 -printf "%%%%verify(not md5 size mtime) %%%%config(noreplace) " -o \ | ||||
| 	 -name gconv-modules.cache \ | ||||
| 	 -printf "%%%%verify(not md5 size mtime) " \ | ||||
|          -name gconv-modules.cache \ | ||||
|          -printf "%%%%verify(not md5 size mtime) " -o \ | ||||
|          -name gconv-modules* \ | ||||
|          -printf "%%%%verify(not md5 size mtime) %%%%config(noreplace) " \ | ||||
| 	 , \ | ||||
| 	 ! -path "*/lib/debug/*" -printf "/%%P\n" \) | ||||
|   # List all directories with a %%dir prefix.  We omit the info directory and | ||||
| @ -1964,6 +2056,7 @@ chmod 0444 master.filelist | ||||
| # - All bench test binaries. | ||||
| # - The aux-cache, since it's handled specially in the files section. | ||||
| # - The build-locale-archive binary since it's in the common package. | ||||
| # - Extra gconv modules.  We add the required modules later. | ||||
| cat master.filelist \ | ||||
| 	| grep -v \ | ||||
| 	-e '%{_infodir}' \ | ||||
| @ -1972,6 +2065,8 @@ cat master.filelist \ | ||||
| 	-e '%{_libdir}/lib.*\.a' \ | ||||
|         -e '%{_libdir}/.*\.o' \ | ||||
| 	-e '%{_libdir}/lib.*\.so' \ | ||||
| 	-e '%{_libdir}/gconv/.*\.so$' \ | ||||
| 	-e '%{_libdir}/gconv/gconv-modules.d/gconv-modules-extra\.conf$' \ | ||||
| 	-e 'nscd' \ | ||||
| 	-e '%{_prefix}/bin' \ | ||||
| 	-e '%{_prefix}/lib/locale' \ | ||||
| @ -1997,18 +2092,41 @@ done | ||||
| grep -e "libmemusage.so" -e "libpcprofile.so" master.filelist >> glibc.filelist | ||||
| 
 | ||||
| ############################################################################### | ||||
| # glibc-devel | ||||
| # glibc-gconv-extra | ||||
| ############################################################################### | ||||
| 
 | ||||
| %if %{with docs} | ||||
| # Put the info files into the devel file list, but exclude the generated dir. | ||||
| grep '%{_infodir}' master.filelist | grep -v '%{_infodir}/dir' > devel.filelist | ||||
| grep -e "gconv-modules-extra.conf" master.filelist > gconv.filelist | ||||
| 
 | ||||
| # Put the essential gconv modules into the main package. | ||||
| GconvBaseModules="ANSI_X3.110 ISO8859-15 ISO8859-1 CP1252" | ||||
| GconvBaseModules="$GconvBaseModules UNICODE UTF-16 UTF-32 UTF-7" | ||||
| %ifarch s390 s390x | ||||
| GconvBaseModules="$GconvBaseModules ISO-8859-1_CP037_Z900 UTF8_UTF16_Z9" | ||||
| GconvBaseModules="$GconvBaseModules UTF16_UTF32_Z9 UTF8_UTF32_Z9" | ||||
| %endif | ||||
| GconvAllModules=$(cat master.filelist | | ||||
|                  sed -n 's|%{_libdir}/gconv/\(.*\)\.so|\1|p') | ||||
| 
 | ||||
| # Put the base modules into glibc and the rest into glibc-gconv-extra | ||||
| for conv in $GconvAllModules; do | ||||
|     if echo $GconvBaseModules | grep -q $conv; then | ||||
|         grep -E -e "%{_libdir}/gconv/$conv.so$" \ | ||||
|             master.filelist >> glibc.filelist | ||||
|     else | ||||
|         grep -E -e "%{_libdir}/gconv/$conv.so$" \ | ||||
|             master.filelist >> gconv.filelist | ||||
|     fi | ||||
| done | ||||
| 
 | ||||
| 
 | ||||
| ############################################################################### | ||||
| # glibc-devel | ||||
| ############################################################################### | ||||
| 
 | ||||
| # Put some static files into the devel package. | ||||
| grep '%{_libdir}/lib.*\.a' master.filelist \ | ||||
|   | grep '/lib\(\(c\|pthread\|nldbl\|mvec\)_nonshared\|g\|ieee\|mcheck\)\.a$' \ | ||||
|   >> devel.filelist | ||||
|   > devel.filelist | ||||
| 
 | ||||
| # Put all of the object files and *.so (not the versioned ones) into the | ||||
| # devel package. | ||||
| @ -2022,6 +2140,16 @@ sed -i -e '\,libmemusage.so,d' \ | ||||
| 	-e '\,/libnss_[a-z]*\.so$,d' \ | ||||
| 	devel.filelist | ||||
| 
 | ||||
| ############################################################################### | ||||
| # glibc-doc | ||||
| ############################################################################### | ||||
| 
 | ||||
| %if %{with docs} | ||||
| # Put the info files into the doc file list, but exclude the generated dir. | ||||
| grep '%{_infodir}' master.filelist | grep -v '%{_infodir}/dir' > doc.filelist | ||||
| grep '%{_docdir}' master.filelist >> doc.filelist | ||||
| %endif | ||||
| 
 | ||||
| ############################################################################### | ||||
| # glibc-headers | ||||
| ############################################################################### | ||||
| @ -2064,12 +2192,14 @@ grep '%{_prefix}/sbin' master.filelist \ | ||||
| # multilib-independent. | ||||
| # Exceptions: | ||||
| # - The actual share directory, not owned by us. | ||||
| # - The info files which go in devel, and the info directory. | ||||
| # - The info files which go into doc, and the info directory. | ||||
| # - All documentation files, which go into doc. | ||||
| grep '%{_prefix}/share' master.filelist \ | ||||
| 	| grep -v \ | ||||
| 	-e '%{_prefix}/share/info/libc.info.*' \ | ||||
| 	-e '%%dir %{prefix}/share/info' \ | ||||
| 	-e '%%dir %{prefix}/share' \ | ||||
| 	-e '%{_docdir}' \ | ||||
| 	>> common.filelist | ||||
| 
 | ||||
| # Add the binary to build locales to the common subpackage. | ||||
| @ -2091,8 +2221,8 @@ cat > utils.filelist <<EOF | ||||
| %if %{without bootstrap} | ||||
| %{_prefix}/bin/memusage | ||||
| %{_prefix}/bin/memusagestat | ||||
| %endif | ||||
| %{_prefix}/bin/mtrace | ||||
| %endif | ||||
| %{_prefix}/bin/pcprofiledump | ||||
| %{_prefix}/bin/xtrace | ||||
| EOF | ||||
| @ -2124,6 +2254,7 @@ grep '/libnss_[a-z]*\.so$' master.filelist > nss-devel.filelist | ||||
| grep '/libnsl-[0-9.]*.so$' master.filelist > libnsl.filelist | ||||
| test $(wc -l < libnsl.filelist) -eq 1 | ||||
| 
 | ||||
| %if %{with benchtests} | ||||
| ############################################################################### | ||||
| # glibc-benchtests | ||||
| ############################################################################### | ||||
| @ -2148,101 +2279,6 @@ echo "%{_prefix}/libexec/glibc-benchtests/validate_benchout.py*" >> benchtests.f | ||||
| ############################################################################### | ||||
| echo "%{_libdir}/libpthread_nonshared.a" >> compat-libpthread-nonshared.filelist | ||||
| 
 | ||||
| ############################################################################### | ||||
| # glibc-debuginfocommon, and glibc-debuginfo | ||||
| ############################################################################### | ||||
| 
 | ||||
| find_debuginfo_args='--strict-build-id -g -i' | ||||
| %ifarch %{debuginfocommonarches} | ||||
| find_debuginfo_args="$find_debuginfo_args \ | ||||
| 	-l common.filelist \ | ||||
| 	-l utils.filelist \ | ||||
| 	-l nscd.filelist \ | ||||
| 	-p '.*/(sbin|libexec)/.*' \ | ||||
| 	-o debuginfocommon.filelist \ | ||||
| 	-l nss_db.filelist -l nss_hesiod.filelist \ | ||||
| 	-l libnsl.filelist -l glibc.filelist \ | ||||
| %if %{with benchtests} | ||||
| 	-l benchtests.filelist | ||||
| %endif | ||||
| 	" | ||||
| %endif | ||||
| 
 | ||||
| /usr/lib/rpm/find-debuginfo.sh $find_debuginfo_args -o debuginfo.filelist | ||||
| 
 | ||||
| # List all of the *.a archives in the debug directory. | ||||
| list_debug_archives() | ||||
| { | ||||
| 	local dir=%{_prefix}/lib/debug%{_libdir} | ||||
| 	find %{glibc_sysroot}$dir -name "*.a" -printf "$dir/%%P\n" | ||||
| } | ||||
| 
 | ||||
| %ifarch %{debuginfocommonarches} | ||||
| 
 | ||||
| # Remove the source files from the common package debuginfo. | ||||
| sed -i '\#^%{glibc_sysroot}%{_prefix}/src/debug/#d' debuginfocommon.filelist | ||||
| 
 | ||||
| # Create a list of all of the source files we copied to the debug directory. | ||||
| find %{glibc_sysroot}%{_prefix}/src/debug \ | ||||
|      \( -type d -printf '%%%%dir ' \) , \ | ||||
|      -printf '%{_prefix}/src/debug/%%P\n' > debuginfocommon.sources | ||||
| 
 | ||||
| %ifarch %{biarcharches} | ||||
| 
 | ||||
| # Add the source files to the core debuginfo package. | ||||
| cat debuginfocommon.sources >> debuginfo.filelist | ||||
| 
 | ||||
| %else | ||||
| 
 | ||||
| %ifarch %{ix86} | ||||
| %define basearch i686 | ||||
| %endif | ||||
| %ifarch sparc sparcv9 | ||||
| %define basearch sparc | ||||
| %endif | ||||
| 
 | ||||
| # The auxarches get only these few source files. | ||||
| auxarches_debugsources=\ | ||||
| '/(generic|linux|%{basearch}|nptl(_db)?)/|/%{glibcsrcdir}/build|/dl-osinfo\.h' | ||||
| 
 | ||||
| # Place the source files into the core debuginfo pakcage. | ||||
| egrep "$auxarches_debugsources" debuginfocommon.sources >> debuginfo.filelist | ||||
| 
 | ||||
| # Remove the source files from the common debuginfo package. | ||||
| egrep -v "$auxarches_debugsources" \ | ||||
|   debuginfocommon.sources >> debuginfocommon.filelist | ||||
| 
 | ||||
| %comment Matches: %ifarch %{biarcharches} | ||||
| %endif | ||||
| 
 | ||||
| # Add the list of *.a archives in the debug directory to | ||||
| # the common debuginfo package. | ||||
| list_debug_archives >> debuginfocommon.filelist | ||||
| 
 | ||||
| %comment Matches: %ifarch %{debuginfocommonarches} | ||||
| %endif | ||||
| 
 | ||||
| # Remove some common directories from the common package debuginfo so that we | ||||
| # don't end up owning them. | ||||
| exclude_common_dirs() | ||||
| { | ||||
| 	exclude_dirs="%{_prefix}/src/debug" | ||||
| 	exclude_dirs="$exclude_dirs $(echo %{_prefix}/lib/debug{,/%{_lib},/bin,/sbin})" | ||||
| 	exclude_dirs="$exclude_dirs $(echo %{_prefix}/lib/debug%{_prefix}{,/%{_lib},/libexec,/bin,/sbin})" | ||||
| 
 | ||||
| 	for d in $(echo $exclude_dirs | sed 's/ /\n/g'); do | ||||
| 		sed -i "\|^%%dir $d/\?$|d" $1 | ||||
| 	done | ||||
| } | ||||
| 
 | ||||
| %ifarch %{debuginfocommonarches} | ||||
| exclude_common_dirs debuginfocommon.filelist | ||||
| %endif | ||||
| exclude_common_dirs debuginfo.filelist | ||||
| 
 | ||||
| %comment Matches: %if 0%{?_enable_debug_packages} | ||||
| %endif | ||||
| 
 | ||||
| ############################################################################## | ||||
| # Delete files that we do not intended to ship with the auxarch. | ||||
| # This is the only place where we touch the installed files after generating | ||||
| @ -2332,6 +2368,15 @@ echo ====================PLT RELOCS LIBC.SO============== | ||||
| readelf -Wr %{glibc_sysroot}/%{_lib}/libc-*.so | sed -n -e "$PLTCMD" | ||||
| echo ====================PLT RELOCS END================== | ||||
| 
 | ||||
| # Obtain a way to run the dynamic loader.  Avoid matching the symbolic | ||||
| # link and then pick the first loader (although there should be only | ||||
| # one). | ||||
| run_ldso="$(find %{glibc_sysroot}/%{_lib}/ld-*.so -type f | LC_ALL=C sort | head -n1) --library-path %{glibc_sysroot}/%{_lib}" | ||||
| 
 | ||||
| # Show the auxiliary vector as seen by the new library | ||||
| # (even if we do not perform the valgrind test). | ||||
| LD_SHOW_AUXV=1 $run_ldso /bin/true | ||||
| 
 | ||||
| # Finally, check if valgrind runs with the new glibc. | ||||
| # We want to fail building if valgrind is not able to run with this glibc so | ||||
| # that we can then coordinate with valgrind to get it fixed before we update | ||||
| @ -2340,16 +2385,15 @@ pushd build-%{target} | ||||
| 
 | ||||
| # Show the auxiliary vector as seen by the new library | ||||
| # (even if we do not perform the valgrind test). | ||||
| LD_SHOW_AUXV=1 elf/ld.so --library-path .:elf:nptl:dlfcn /bin/true | ||||
| LD_SHOW_AUXV=1 $run_ldso /bin/true | ||||
| 
 | ||||
| %if %{with valgrind} | ||||
| elf/ld.so --library-path .:elf:nptl:dlfcn \ | ||||
| 	/usr/bin/valgrind --error-exitcode=1 \ | ||||
| 	elf/ld.so --library-path .:elf:nptl:dlfcn /usr/bin/true | ||||
| $run_ldso /usr/bin/valgrind --error-exitcode=1 \ | ||||
| 	$run_ldso /usr/bin/true | ||||
| %endif | ||||
| popd | ||||
| 
 | ||||
| %comment Matches: %if %{run_glibc_tests} | ||||
| %comment Matches: %if %{with testsuite} | ||||
| %endif | ||||
| 
 | ||||
| 
 | ||||
| @ -2362,17 +2406,7 @@ if rpm.vercmp(rel, required) < 0 then | ||||
| end | ||||
| 
 | ||||
| %post -p <lua> | ||||
| -- We use lua's posix.exec because there may be no shell that we can | ||||
| -- run during glibc upgrade. | ||||
| function post_exec (program, ...) | ||||
|   local pid = posix.fork () | ||||
|   if pid == 0 then | ||||
|     assert (posix.exec (program, ...)) | ||||
|   elseif pid > 0 then | ||||
|     posix.wait (pid) | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| %glibc_post_funcs | ||||
| -- (1) Remove multilib libraries from previous installs. | ||||
| -- In order to support in-place upgrades, we must immediately remove | ||||
| -- obsolete platform directories after installing a new glibc | ||||
| @ -2481,16 +2515,7 @@ post_exec ("%{_prefix}/sbin/ldconfig") | ||||
| -- We assume that the cache is in _libdir/gconv and called | ||||
| -- "gconv-modules.cache". | ||||
| 
 | ||||
| local iconv_dir = "%{_libdir}/gconv" | ||||
| local iconv_cache = iconv_dir .. "/gconv-modules.cache" | ||||
| if (posix.utime (iconv_cache) == 0) then | ||||
|   post_exec ("%{_prefix}/sbin/iconvconfig", | ||||
| 	     "-o", iconv_cache, | ||||
| 	     "--nostdlib", | ||||
| 	     iconv_dir) | ||||
| else | ||||
|   io.stdout:write ("Error: Missing " .. iconv_cache .. " file.\n") | ||||
| end | ||||
| update_gconv_modules_cache() | ||||
| 
 | ||||
| %posttrans all-langpacks -e -p <lua> | ||||
| -- If at the end of the transaction we are still installed | ||||
| @ -2531,6 +2556,14 @@ if [ "$1" = 0 ]; then | ||||
| fi | ||||
| %endif | ||||
| 
 | ||||
| %post gconv-extra -p <lua> | ||||
| %glibc_post_funcs | ||||
| update_gconv_modules_cache () | ||||
| 
 | ||||
| %postun gconv-extra -p <lua> | ||||
| %glibc_post_funcs | ||||
| update_gconv_modules_cache () | ||||
| 
 | ||||
| %pre -n nscd | ||||
| getent group nscd >/dev/null || /usr/sbin/groupadd -g 28 -r nscd | ||||
| getent passwd nscd >/dev/null || | ||||
| @ -2563,11 +2596,11 @@ fi | ||||
| %dir /etc/ld.so.conf.d | ||||
| %dir %{_prefix}/libexec/getconf | ||||
| %dir %{_libdir}/gconv | ||||
| %dir %{_libdir}/gconv/gconv-modules.d | ||||
| %dir %attr(0700,root,root) /var/cache/ldconfig | ||||
| %attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/cache/ldconfig/aux-cache | ||||
| %attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/ld.so.cache | ||||
| %attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/gai.conf | ||||
| %doc README NEWS INSTALL elf/rtld-debugger-interface.txt | ||||
| # If rpm doesn't support %license, then use %doc instead. | ||||
| %{!?_licensedir:%global license %%doc} | ||||
| %license COPYING COPYING.LIB LICENSES | ||||
| @ -2577,8 +2610,6 @@ fi | ||||
| %dir %{_prefix}/lib/locale | ||||
| %dir %{_prefix}/lib/locale/C.utf8 | ||||
| %{_prefix}/lib/locale/C.utf8/* | ||||
| %doc documentation/README.timezone | ||||
| %doc documentation/gai.conf | ||||
| 
 | ||||
| %files all-langpacks | ||||
| %attr(0644,root,root) %verify(not md5 size mtime) %{_prefix}/lib/locale/locale-archive.tmpl | ||||
| @ -2592,12 +2623,18 @@ fi | ||||
| 
 | ||||
| %files -f devel.filelist devel | ||||
| 
 | ||||
| %if %{with docs} | ||||
| %files -f doc.filelist doc | ||||
| %endif | ||||
| 
 | ||||
| %files -f static.filelist static | ||||
| 
 | ||||
| %files -f headers.filelist headers | ||||
| 
 | ||||
| %files -f utils.filelist utils | ||||
| 
 | ||||
| %files -f gconv.filelist gconv-extra | ||||
| 
 | ||||
| %files -f nscd.filelist -n nscd | ||||
| %config(noreplace) /etc/nscd.conf | ||||
| %dir %attr(0755,root,root) /var/run/nscd | ||||
| @ -2627,15 +2664,6 @@ fi | ||||
| %files -f libnsl.filelist -n libnsl | ||||
| /%{_lib}/libnsl.so.1 | ||||
| 
 | ||||
| %if 0%{?_enable_debug_packages} | ||||
| %files debuginfo -f debuginfo.filelist | ||||
| %ifarch %{debuginfocommonarches} | ||||
| %ifnarch %{auxarches} | ||||
| %files debuginfo-common -f debuginfocommon.filelist | ||||
| %endif | ||||
| %endif | ||||
| %endif | ||||
| 
 | ||||
| %if %{with benchtests} | ||||
| %files benchtests -f benchtests.filelist | ||||
| %endif | ||||
| @ -2643,16 +2671,91 @@ fi | ||||
| %files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared | ||||
| 
 | ||||
| %changelog | ||||
| * Thu Jan 27 2022 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-164.3 | ||||
| * Thu Mar 10 2022 Florian Weimer <fweimer@redhat.com> - 2.28-189.1 | ||||
| - nss: Avoid clobbering errno in get*ent via dlopen (#2061727) | ||||
| 
 | ||||
| * Thu Jan 27 2022 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-189 | ||||
| - CVE-2021-3999: getcwd: align stack on clone in aarch64 and fix a memory leak | ||||
|   (#2032280) | ||||
|   (#2032281) | ||||
| 
 | ||||
| * Wed Jan 26 2022 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-164.2 | ||||
| * Tue Jan 25 2022 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-188 | ||||
| - CVE-2022-23218, CVE-2022-23219: Fix buffer overflows in sunrpc clnt_create | ||||
|   for "unix" and svcunix_create (#2045062). | ||||
|   for "unix" and svcunix_create (#2045063). | ||||
| 
 | ||||
| * Mon Jan 24 2022 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-164.1 | ||||
| - CVE-2021-3999: getcwd: Set errno to ERANGE for size == 1 (#2032280) | ||||
| * Mon Jan 24 2022 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-187 | ||||
| - CVE-2021-3999: getcwd: Set errno to ERANGE for size == 1 (#2032281) | ||||
| 
 | ||||
| * Fri Jan 21 2022 Carlos O'Donell <carlos@redhat.com> - 2.28-186 | ||||
| - Fix pthread_once regression with C++ exceptions (#2007327) | ||||
| 
 | ||||
| * Thu Jan 20 2022 DJ Delorie <dj@redhat.com> - 2.28-185 | ||||
| - Adjust to rpm's find-debuginfo.sh changes, to keep stripping binaries (#1661513) | ||||
| 
 | ||||
| * Fri Jan  7 2022 Florian Weimer <fweimer@redhat.com> - 2.28-184 | ||||
| - Conversion from ISO-2022-JP-3 may emit spurious NUL character (#2033655) | ||||
| 
 | ||||
| * Fri Jan  7 2022 Florian Weimer <fweimer@redhat.com> - 2.28-183 | ||||
| - aarch64: A64FX optimizations break "sve=off" guest mode (#2036955) | ||||
| 
 | ||||
| * Fri Jan  7 2022 Patsy Griffin <patsy@redhat.com> - 2.28-182 | ||||
| - Handle truncated timezones from tzcode-2021d and later. (#2033648) | ||||
| 
 | ||||
| * Tue Jan  4 2022 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-181 | ||||
| - Weaken dependency of glibc on glibc-gconv-extra (#2015768) | ||||
| 
 | ||||
| * Mon Dec 13 2021 Florian Weimer <fweimer@redhat.com> - 2.28-180 | ||||
| - Do not install /usr/lib/debug/usr/bin/ld.so.debug (#2023420) | ||||
| 
 | ||||
| * Fri Dec 10 2021 Florian Weimer <fweimer@redhat.com> - 2.28-179 | ||||
| - Add /usr/bin/ld.so --list-diagnostics (#2023420) | ||||
| 
 | ||||
| * Fri Dec 10 2021 Carlos O'Donell <carlos@redhat.com> - 2.28-178 | ||||
| - Preliminary support for new IBM zSeries hardware (#1984802) | ||||
| 
 | ||||
| * Fri Dec 10 2021 Carlos O'Donell <carlos@redhat.com> - 2.28-177 | ||||
| - Fix --with and --without builds for benchtests and bootstrap (#2020989) | ||||
| 
 | ||||
| * Wed Dec  1 2021 Florian Weimer <fweimer@redhat.com> - 2.28-176 | ||||
| - A64FX memcpy/memmove/memset optimizations (#1929928) | ||||
| 
 | ||||
| * Tue Nov 30 2021 Florian Weimer <fweimer@redhat.com> - 2.28-175 | ||||
| - Fix dl-tls.c assert failure with pthread_create & dlopen (#1991001) | ||||
| - Fix x86_64 TLS lazy binding with auditors (#1950056) | ||||
| 
 | ||||
| * Thu Nov 25 2021 Arjun Shankar <arjun@redhat.com> - 2.28-174 | ||||
| - Introduce new glibc-doc.noarch subpackage (#2021671) | ||||
| - Move the reference manual info pages from glibc-devel to glibc-doc | ||||
| - Move debugger interface documentation from glibc to glibc-doc | ||||
| - Remove unnecessary README, INSTALL, NEWS files from glibc | ||||
| - Remove unnecessary README.timezone and gai.conf files from glibc-common | ||||
| 
 | ||||
| * Wed Nov 17 2021 Patsy Griffin <patsy@redhat.com> - 2.28-173 | ||||
| - Add new English-language 12 hour time locale en_US@ampm.UTF-8 (#2000374) | ||||
| 
 | ||||
| * Tue Nov 16 2021 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-172 | ||||
| - Build build-locale-archive with -static-pie when supported (#1965377) | ||||
| 
 | ||||
| * Wed Nov  10 2021 DJ Delorie <dj@redhat.com> - 2.28-171 | ||||
| - elf: Always set link map in _dl_init_paths (#1934162) | ||||
| 
 | ||||
| * Wed Nov 10 2021 Arjun Shankar <arjun@redhat.com> - 2.28-170 | ||||
| - x86: Properly disable XSAVE related features when its use is disabled via | ||||
|   tunables (#1937515) | ||||
| 
 | ||||
| * Wed Nov 10 2021 Arjun Shankar <arjun@redhat.com> - 2.28-169 | ||||
| - s390: Use long branches across object boundaries (#2021452) | ||||
| 
 | ||||
| * Fri Oct 29 2021 Arjun Shankar <arjun@redhat.com> - 2.28-168 | ||||
| - Optimize memcmp, strcpy, and stpcpy for IBM POWER10 (#1983203) | ||||
| 
 | ||||
| * Wed Oct 13 2021 Arjun Shankar <arjun@redhat.com> - 2.28-167 | ||||
| - malloc: Initiate tcache shutdown even without allocations (#1977614) | ||||
| 
 | ||||
| * Wed Oct 13 2021 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-166 | ||||
| - Fix debuginfo location for gconv-extra and make glibc Require it (#1971664). | ||||
| 
 | ||||
| * Wed Oct  6 2021 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-165 | ||||
| - Split extra gconv modules into a separate package (#1971664). | ||||
| 
 | ||||
| * Mon Aug  9 2021 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-164 | ||||
| - librt: fix NULL pointer dereference (#1966472). | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user