import glibc-2.34-60.el9

c9-beta imports/c9-beta/glibc-2.34-60.el9
CentOS Sources 2 years ago committed by MSVSphere Packaging Team
commit e763638f91

1
.gitignore vendored

@ -0,0 +1 @@
SOURCES/glibc-2.34.tar.xz

@ -0,0 +1 @@
7c3b8890a6346793b6334cc5f2fea5d437d307b8 SOURCES/glibc-2.34.tar.xz

File diff suppressed because it is too large Load Diff

@ -0,0 +1,77 @@
objpfx = $(prefix)/$(ver)/usr/libexec/glibc-benchtests/
bench-math := acos acosh asin asinh atan atanh cos cosh exp exp2 ffs ffsll \
log log2 modf pow rint sin sincos sinh sqrt tan tanh
bench-pthread := pthread_once
bench := $(bench-math) $(bench-pthread)
run-bench := $(prefix)/$(ver)/lib64/ld-linux-x86-64.so.2 --library-path $(prefix)/$(ver)/lib64 $${run}
# String function benchmarks.
string-bench := bcopy bzero memccpy memchr memcmp memcpy memmem memmove \
mempcpy memset rawmemchr stpcpy stpncpy strcasecmp strcasestr \
strcat strchr strchrnul strcmp strcpy strcspn strlen \
strncasecmp strncat strncmp strncpy strnlen strpbrk strrchr \
strspn strstr strcpy_chk stpcpy_chk memrchr strsep strtok
string-bench-all := $(string-bench)
stdlib-bench := strtod
benchset := $(string-bench-all) $(stdlib-bench)
bench-malloc := malloc-thread
binaries-bench := $(addprefix $(objpfx)bench-,$(bench))
binaries-benchset := $(addprefix $(objpfx)bench-,$(benchset))
binaries-bench-malloc := $(addprefix $(objpfx)bench-,$(bench-malloc))
DETAILED_OPT :=
ifdef DETAILED
DETAILED_OPT := -d
endif
bench: bench-set bench-func bench-malloc
bench-set: $(binaries-benchset)
for run in $^; do \
outfile=$(prefix)/$$(basename $${run}.$(ver).out); \
echo "Running $${run}"; \
$(run-bench) > $${outfile}.tmp; \
mv $${outfile}{.tmp,}; \
done
bench-malloc: $(binaries-bench-malloc)
run=$(objpfx)bench-malloc-thread; \
outfile=$(prefix)/$$(basename $${run}.$(ver).out); \
for thr in 1 8 16 32; do \
echo "Running $${run} $${thr}"; \
$(run-bench) $${thr} > $${outfile}.tmp; \
mv $${outfile}{.tmp,}; \
done
# Build and execute the benchmark functions. This target generates JSON
# formatted bench.out. Each of the programs produce independent JSON output,
# so one could even execute them individually and process it using any JSON
# capable language or tool.
bench-func: $(binaries-bench)
{ echo "{\"timing_type\": \"hp-timing\","; \
echo " \"functions\": {"; \
for run in $^; do \
if ! [ "x$${run}" = "x$<" ]; then \
echo ","; \
fi; \
echo "Running $${run}" >&2; \
$(run-bench) $(DETAILED_OPT); \
done; \
echo; \
echo " }"; \
echo "}"; } > $(prefix)/bench.$(ver).out-tmp; \
if [ -f $(prefix)/bench.$(ver).out ]; then \
mv -f $(prefix)/bench.$(ver).out{,.old}; \
fi; \
mv -f $(prefix)/bench.$(ver).out{-tmp,}
# scripts/validate_benchout.py bench.out \
# scripts/benchout.schema.json

@ -0,0 +1,153 @@
#!/usr/bin/bash
# This script can be invoked as follows:
#
# glibc-bench-compare [options] <BUILD> [BUILD]
#
# Options may be one of the following:
#
# -t The BUILD arguments are task ids and not a version-release string
# -a ARCH Do comparison for ARCH architecture
#
# If any of the above options are given, both BUILD arguments must be given.
# Otherwise, if only one BUILD is specified, then it is compared against the
# installed glibc.
# Silence the pushd/popd messages
pushd() {
command pushd "$@" > /dev/null 2>&1
}
popd() {
command popd "$@" > /dev/null 2>&1
}
# Clean up any downloaded files before we exit
trap "rm -rf /tmp/glibc-bench-compare.$BASHPID.*" EXIT
task=0
arch=$(uname -i)
options=0
path=0
installed=
# Look for any commandline options
while getopts ":tpa:" opt; do
case $opt in
p)
path=1
;;
t)
task=1
options=1
echo "Not implemented."
exit 1
;;
a)
arch=$OPTARG
options=1
;;
*)
;;
esac
done
# Done, now shift all option arguments out.
shift $((OPTIND-1))
if [ $# -gt 2 ] || [ $# -eq 0 ] || [ $# -lt 2 -a $options -eq 1 ]; then
echo "Usage: $0 [OPTIONS] <old> [new]"
echo
echo "OPTIONS:"
echo -e "\t-t\tCompare two brew tasks"
echo -e "\t-a ARCH\tGet rpms for the ARCH architecture"
echo -e "\t-p\tCompare built rpms in two paths."
echo -e "\t\tThis minimally needs glibc, glibc-common and glibc-benchtests"
exit 1
fi
if [ -z $2 ]; then
new="$1"
old=$(rpm --queryformat "%{VERSION}-%{RELEASE}\n" -q glibc | head -1)
installed=$old
else
new="$2"
old="$1"
fi
decompress_rpms() {
# We were given a path to the rpms. Figure out the version-release and
# decompress the rpms.
if [ -n $1 ]; then
vr=$(rpm --queryformat="%{VERSION}-%{RELEASE}" -qp $1/glibc-2*.rpm | head -1)
mkdir $vr && pushd $vr
fi
for r in $1*.rpm; do
( rpm2cpio $r | cpio -di ) > /dev/null
done
if [ -n $1 ]; then
popd
echo $vr
fi
}
# Get rpms for a build and decompress them
get_build() {
echo "Processing build $1"
mkdir $1 && pushd $1
brew buildinfo "glibc-$1" |
sed -n -e "s|/mnt/koji\(.\+$arch.\+\)|http://kojipkgs.fedoraproject.org\1|p" |
while read url; do
echo "Downloading $url"
wget -q $url
done
decompress_rpms
echo "Removing rpms"
rm -f $1/*.rpm
popd
}
# Run benchmarks for a build
run_bench() {
if [ -z $1 ]; then
make DETAILED=1 ver=$installed prefix= -f /usr/libexec/glibc-benchtests/bench.mk bench
else
make DETAILED=1 ver=$1 prefix=$PWD -f $1/usr/libexec/glibc-benchtests/bench.mk bench
fi
}
# Get absolute paths if needed, since we will change into the working directory
# next.
if [ $path -eq 1 ]; then
old_path=$(realpath $old)/
new_path=$(realpath $new)/
fi
tmpdir=$(mktemp -p /tmp -d glibc-bench-compare.$$.XXXX)
pushd $tmpdir
# Get both builds.
if [ $path -eq 0 ]; then
if [ -z $installed ]; then
get_build $old
fi
get_build $new
else
old=$(decompress_rpms $old_path)
new=$(decompress_rpms $new_path)
fi
# make bench for each of those.
if [ -z $installed ]; then
run_bench $old
else
run_bench
fi
run_bench $new
# Now run the comparison script.
$old/usr/libexec/glibc-benchtests/compare_bench.py $old/usr/libexec/glibc-benchtests/benchout.schema.json \
bench.$old.out bench.$new.out

@ -0,0 +1,980 @@
commit f5117c6504888fab5423282a4607c552b90fd3f9
Author: Carlos O'Donell <carlos@redhat.com>
Date: Thu Jul 29 22:45:39 2021 -0400
Add 'codepoint_collation' support for LC_COLLATE.
Support a new directive 'codepoint_collation' in the LC_COLLATE
section of a locale source file. This new directive causes all
collation rules to be dropped and instead STRCMP (strcmp or
wcscmp) is used for collation of the input character set. This
is required to allow for a C.UTF-8 that contains zero collation
rules (minimal size) and sorts using code point sorting.
To date the only implementation of a locale with zero collation
rules is the C/POSIX locale. The C/POSIX locale provides
identity tables for _NL_COLLATE_COLLSEQMB and
_NL_COLLATE_COLLSEQWC that map to ASCII even though it has zero
rules. This has lead to existing fnmatch, regexec, and regcomp
implementations that require these tables. It is not correct
to use these tables when nrules == 0, but the conservative fix
is to provide these tables when nrules == 0. This assures that
existing static applications using a new C.UTF-8 locale with
'codepoint_collation' at least have functional range expressions
with ASCII e.g. [0-9] or [a-z]. Such static applications would
not have the fixes to fnmatch, regexec and regcomp that avoid
the use of the tables when nrules == 0. Future fixes to fnmatch,
regexec, and regcomp would allow range expressions to use the
full set of code points for such ranges.
Tested on x86_64 and i686 without regression.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
diff --git a/locale/C-collate-seq.c b/locale/C-collate-seq.c
new file mode 100644
index 0000000000000000..4fb82cb8357936b6
--- /dev/null
+++ b/locale/C-collate-seq.c
@@ -0,0 +1,100 @@
+/* Copyright (C) 1995-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 <stdint.h>
+
+static const char collseqmb[] =
+{
+ '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
+ '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
+ '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
+ '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
+ '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
+ '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
+ '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
+ '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
+ '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47',
+ '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f',
+ '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57',
+ '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
+ '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
+ '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f',
+ '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77',
+ '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
+ '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
+ '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
+ '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
+ '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
+ '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
+ '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
+ '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
+ '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
+ '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
+ '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
+ '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
+ '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
+ '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
+ '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
+ '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
+ '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff'
+};
+
+/* This table must be 256 bytes in size. We index bytes into the
+ table to find the collation sequence. */
+_Static_assert (sizeof (collseqmb) == 256);
+
+static const uint32_t collseqwc[] =
+{
+ 8, 1, 8, 0x0, 0xff,
+ /* 1st-level table */
+ 6 * sizeof (uint32_t),
+ /* 2nd-level table */
+ 7 * sizeof (uint32_t),
+ /* 3rd-level table */
+ L'\x00', L'\x01', L'\x02', L'\x03', L'\x04', L'\x05', L'\x06', L'\x07',
+ L'\x08', L'\x09', L'\x0a', L'\x0b', L'\x0c', L'\x0d', L'\x0e', L'\x0f',
+ L'\x10', L'\x11', L'\x12', L'\x13', L'\x14', L'\x15', L'\x16', L'\x17',
+ L'\x18', L'\x19', L'\x1a', L'\x1b', L'\x1c', L'\x1d', L'\x1e', L'\x1f',
+ L'\x20', L'\x21', L'\x22', L'\x23', L'\x24', L'\x25', L'\x26', L'\x27',
+ L'\x28', L'\x29', L'\x2a', L'\x2b', L'\x2c', L'\x2d', L'\x2e', L'\x2f',
+ L'\x30', L'\x31', L'\x32', L'\x33', L'\x34', L'\x35', L'\x36', L'\x37',
+ L'\x38', L'\x39', L'\x3a', L'\x3b', L'\x3c', L'\x3d', L'\x3e', L'\x3f',
+ L'\x40', L'\x41', L'\x42', L'\x43', L'\x44', L'\x45', L'\x46', L'\x47',
+ L'\x48', L'\x49', L'\x4a', L'\x4b', L'\x4c', L'\x4d', L'\x4e', L'\x4f',
+ L'\x50', L'\x51', L'\x52', L'\x53', L'\x54', L'\x55', L'\x56', L'\x57',
+ L'\x58', L'\x59', L'\x5a', L'\x5b', L'\x5c', L'\x5d', L'\x5e', L'\x5f',
+ L'\x60', L'\x61', L'\x62', L'\x63', L'\x64', L'\x65', L'\x66', L'\x67',
+ L'\x68', L'\x69', L'\x6a', L'\x6b', L'\x6c', L'\x6d', L'\x6e', L'\x6f',
+ L'\x70', L'\x71', L'\x72', L'\x73', L'\x74', L'\x75', L'\x76', L'\x77',
+ L'\x78', L'\x79', L'\x7a', L'\x7b', L'\x7c', L'\x7d', L'\x7e', L'\x7f',
+ L'\x80', L'\x81', L'\x82', L'\x83', L'\x84', L'\x85', L'\x86', L'\x87',
+ L'\x88', L'\x89', L'\x8a', L'\x8b', L'\x8c', L'\x8d', L'\x8e', L'\x8f',
+ L'\x90', L'\x91', L'\x92', L'\x93', L'\x94', L'\x95', L'\x96', L'\x97',
+ L'\x98', L'\x99', L'\x9a', L'\x9b', L'\x9c', L'\x9d', L'\x9e', L'\x9f',
+ L'\xa0', L'\xa1', L'\xa2', L'\xa3', L'\xa4', L'\xa5', L'\xa6', L'\xa7',
+ L'\xa8', L'\xa9', L'\xaa', L'\xab', L'\xac', L'\xad', L'\xae', L'\xaf',
+ L'\xb0', L'\xb1', L'\xb2', L'\xb3', L'\xb4', L'\xb5', L'\xb6', L'\xb7',
+ L'\xb8', L'\xb9', L'\xba', L'\xbb', L'\xbc', L'\xbd', L'\xbe', L'\xbf',
+ L'\xc0', L'\xc1', L'\xc2', L'\xc3', L'\xc4', L'\xc5', L'\xc6', L'\xc7',
+ L'\xc8', L'\xc9', L'\xca', L'\xcb', L'\xcc', L'\xcd', L'\xce', L'\xcf',
+ L'\xd0', L'\xd1', L'\xd2', L'\xd3', L'\xd4', L'\xd5', L'\xd6', L'\xd7',
+ L'\xd8', L'\xd9', L'\xda', L'\xdb', L'\xdc', L'\xdd', L'\xde', L'\xdf',
+ L'\xe0', L'\xe1', L'\xe2', L'\xe3', L'\xe4', L'\xe5', L'\xe6', L'\xe7',
+ L'\xe8', L'\xe9', L'\xea', L'\xeb', L'\xec', L'\xed', L'\xee', L'\xef',
+ L'\xf0', L'\xf1', L'\xf2', L'\xf3', L'\xf4', L'\xf5', L'\xf6', L'\xf7',
+ L'\xf8', L'\xf9', L'\xfa', L'\xfb', L'\xfc', L'\xfd', L'\xfe', L'\xff'
+};
diff --git a/locale/C-collate.c b/locale/C-collate.c
index 76d9373683314943..120ce0a40aeb9a0f 100644
--- a/locale/C-collate.c
+++ b/locale/C-collate.c
@@ -20,83 +20,7 @@
#include <stdint.h>
#include "localeinfo.h"
-static const char collseqmb[] =
-{
- '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
- '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
- '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
- '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
- '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
- '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
- '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
- '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
- '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47',
- '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f',
- '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57',
- '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
- '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
- '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f',
- '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77',
- '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
- '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
- '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
- '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
- '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
- '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
- '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
- '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
- '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
- '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
- '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
- '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
- '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
- '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
- '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
- '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
- '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff'
-};
-
-static const uint32_t collseqwc[] =
-{
- 8, 1, 8, 0x0, 0xff,
- /* 1st-level table */
- 6 * sizeof (uint32_t),
- /* 2nd-level table */
- 7 * sizeof (uint32_t),
- /* 3rd-level table */
- L'\x00', L'\x01', L'\x02', L'\x03', L'\x04', L'\x05', L'\x06', L'\x07',
- L'\x08', L'\x09', L'\x0a', L'\x0b', L'\x0c', L'\x0d', L'\x0e', L'\x0f',
- L'\x10', L'\x11', L'\x12', L'\x13', L'\x14', L'\x15', L'\x16', L'\x17',
- L'\x18', L'\x19', L'\x1a', L'\x1b', L'\x1c', L'\x1d', L'\x1e', L'\x1f',
- L'\x20', L'\x21', L'\x22', L'\x23', L'\x24', L'\x25', L'\x26', L'\x27',
- L'\x28', L'\x29', L'\x2a', L'\x2b', L'\x2c', L'\x2d', L'\x2e', L'\x2f',
- L'\x30', L'\x31', L'\x32', L'\x33', L'\x34', L'\x35', L'\x36', L'\x37',
- L'\x38', L'\x39', L'\x3a', L'\x3b', L'\x3c', L'\x3d', L'\x3e', L'\x3f',
- L'\x40', L'\x41', L'\x42', L'\x43', L'\x44', L'\x45', L'\x46', L'\x47',
- L'\x48', L'\x49', L'\x4a', L'\x4b', L'\x4c', L'\x4d', L'\x4e', L'\x4f',
- L'\x50', L'\x51', L'\x52', L'\x53', L'\x54', L'\x55', L'\x56', L'\x57',
- L'\x58', L'\x59', L'\x5a', L'\x5b', L'\x5c', L'\x5d', L'\x5e', L'\x5f',
- L'\x60', L'\x61', L'\x62', L'\x63', L'\x64', L'\x65', L'\x66', L'\x67',
- L'\x68', L'\x69', L'\x6a', L'\x6b', L'\x6c', L'\x6d', L'\x6e', L'\x6f',
- L'\x70', L'\x71', L'\x72', L'\x73', L'\x74', L'\x75', L'\x76', L'\x77',
- L'\x78', L'\x79', L'\x7a', L'\x7b', L'\x7c', L'\x7d', L'\x7e', L'\x7f',
- L'\x80', L'\x81', L'\x82', L'\x83', L'\x84', L'\x85', L'\x86', L'\x87',
- L'\x88', L'\x89', L'\x8a', L'\x8b', L'\x8c', L'\x8d', L'\x8e', L'\x8f',
- L'\x90', L'\x91', L'\x92', L'\x93', L'\x94', L'\x95', L'\x96', L'\x97',
- L'\x98', L'\x99', L'\x9a', L'\x9b', L'\x9c', L'\x9d', L'\x9e', L'\x9f',
- L'\xa0', L'\xa1', L'\xa2', L'\xa3', L'\xa4', L'\xa5', L'\xa6', L'\xa7',
- L'\xa8', L'\xa9', L'\xaa', L'\xab', L'\xac', L'\xad', L'\xae', L'\xaf',
- L'\xb0', L'\xb1', L'\xb2', L'\xb3', L'\xb4', L'\xb5', L'\xb6', L'\xb7',
- L'\xb8', L'\xb9', L'\xba', L'\xbb', L'\xbc', L'\xbd', L'\xbe', L'\xbf',
- L'\xc0', L'\xc1', L'\xc2', L'\xc3', L'\xc4', L'\xc5', L'\xc6', L'\xc7',
- L'\xc8', L'\xc9', L'\xca', L'\xcb', L'\xcc', L'\xcd', L'\xce', L'\xcf',
- L'\xd0', L'\xd1', L'\xd2', L'\xd3', L'\xd4', L'\xd5', L'\xd6', L'\xd7',
- L'\xd8', L'\xd9', L'\xda', L'\xdb', L'\xdc', L'\xdd', L'\xde', L'\xdf',
- L'\xe0', L'\xe1', L'\xe2', L'\xe3', L'\xe4', L'\xe5', L'\xe6', L'\xe7',
- L'\xe8', L'\xe9', L'\xea', L'\xeb', L'\xec', L'\xed', L'\xee', L'\xef',
- L'\xf0', L'\xf1', L'\xf2', L'\xf3', L'\xf4', L'\xf5', L'\xf6', L'\xf7',
- L'\xf8', L'\xf9', L'\xfa', L'\xfb', L'\xfc', L'\xfd', L'\xfe', L'\xff'
-};
+#include "C-collate-seq.c"
const struct __locale_data _nl_C_LC_COLLATE attribute_hidden =
{
diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c
index b6406b775d3a81ad..0f314e40c4305dea 100644
--- a/locale/programs/ld-collate.c
+++ b/locale/programs/ld-collate.c
@@ -24,6 +24,7 @@
#include <wchar.h>
#include <stdint.h>
#include <sys/param.h>
+#include <array_length.h>
#include "localedef.h"
#include "charmap.h"
@@ -195,6 +196,9 @@ struct name_list
/* The real definition of the struct for the LC_COLLATE locale. */
struct locale_collate_t
{
+ /* Does the locale use code points to compare the encoding? */
+ bool codepoint_collation;
+
int col_weight_max;
int cur_weight_max;
@@ -1510,6 +1514,7 @@ collate_startup (struct linereader *ldfile, struct localedef_t *locale,
obstack_init (&collate->mempool);
collate->col_weight_max = -1;
+ collate->codepoint_collation = false;
}
else
/* Reuse the copy_locale's data structures. */
@@ -1568,6 +1573,10 @@ collate_finish (struct localedef_t *locale, const struct charmap_t *charmap)
return;
}
+ /* No data required. */
+ if (collate->codepoint_collation)
+ return;
+
/* If this assertion is hit change the type in `element_t'. */
assert (nrules <= sizeof (runp->used_in_level) * 8);
@@ -2092,6 +2101,10 @@ add_to_tablewc (uint32_t ch, struct element_t *runp)
}
}
+/* Include the C locale identity tables for _NL_COLLATE_COLLSEQMB and
+ _NL_COLLATE_COLLSEQWC. */
+#include "C-collate-seq.c"
+
void
collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
const char *output_path)
@@ -2115,7 +2128,7 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
add_locale_uint32 (&file, nrules);
/* If we have no LC_COLLATE data emit only the number of rules as zero. */
- if (collate == NULL)
+ if (collate == NULL || collate->codepoint_collation)
{
size_t idx;
for (idx = 1; idx < nelems; idx++)
@@ -2123,6 +2136,17 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
/* The words have to be handled specially. */
if (idx == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZEMB))
add_locale_uint32 (&file, 0);
+ else if (idx == _NL_ITEM_INDEX (_NL_COLLATE_CODESET)
+ && collate != NULL)
+ /* A valid LC_COLLATE must have a code set name. */
+ add_locale_string (&file, charmap->code_set_name);
+ else if (idx == _NL_ITEM_INDEX (_NL_COLLATE_COLLSEQMB)
+ && collate != NULL)
+ add_locale_raw_data (&file, collseqmb, sizeof (collseqmb));
+ else if (idx == _NL_ITEM_INDEX (_NL_COLLATE_COLLSEQWC)
+ && collate != NULL)
+ add_locale_uint32_array (&file, collseqwc,
+ array_length (collseqwc));
else
add_locale_empty (&file);
}
@@ -2672,6 +2696,10 @@ collate_read (struct linereader *ldfile, struct localedef_t *result,
switch (nowtok)
{
+ case tok_codepoint_collation:
+ collate->codepoint_collation = true;
+ break;
+
case tok_copy:
/* Allow copying other locales. */
now = lr_token (ldfile, charmap, result, NULL, verbose);
@@ -3742,9 +3770,11 @@ error while adding equivalent collating symbol"));
/* Next we assume `LC_COLLATE'. */
if (!ignore_content)
{
- if (state == 0 && copy_locale == NULL)
+ if (state == 0
+ && copy_locale == NULL
+ && !collate->codepoint_collation)
/* We must either see a copy statement or have
- ordering values. */
+ ordering values, or codepoint_collation. */
lr_error (ldfile,
_("%s: empty category description not allowed"),
"LC_COLLATE");
diff --git a/locale/programs/locfile-kw.gperf b/locale/programs/locfile-kw.gperf
index bcded15ddb4c44bb..2e59eb9ac014134b 100644
--- a/locale/programs/locfile-kw.gperf
+++ b/locale/programs/locfile-kw.gperf
@@ -54,6 +54,7 @@ translit_end, tok_translit_end, 0
translit_ignore, tok_translit_ignore, 0
default_missing, tok_default_missing, 0
LC_COLLATE, tok_lc_collate, 0
+codepoint_collation, tok_codepoint_collation, 0
coll_weight_max, tok_coll_weight_max, 0
section-symbol, tok_section_symbol, 0
collating-element, tok_collating_element, 0
diff --git a/locale/programs/locfile-kw.h b/locale/programs/locfile-kw.h
index bc1cb8f0845852ad..fe6335692bd422cd 100644
--- a/locale/programs/locfile-kw.h
+++ b/locale/programs/locfile-kw.h
@@ -54,7 +54,7 @@
#line 24 "locfile-kw.gperf"
struct keyword_t ;
-#define TOTAL_KEYWORDS 178
+#define TOTAL_KEYWORDS 179
#define MIN_WORD_LENGTH 3
#define MAX_WORD_LENGTH 22
#define MIN_HASH_VALUE 3
@@ -134,92 +134,92 @@ locfile_hash (register const char *str, register size_t len)
#line 31 "locfile-kw.gperf"
{"END", tok_end, 0},
{""}, {""},
-#line 70 "locfile-kw.gperf"
+#line 71 "locfile-kw.gperf"
{"IGNORE", tok_ignore, 0},
-#line 129 "locfile-kw.gperf"
+#line 130 "locfile-kw.gperf"
{"LC_TIME", tok_lc_time, 0},
#line 30 "locfile-kw.gperf"
{"LC_CTYPE", tok_lc_ctype, 0},
{""},
-#line 168 "locfile-kw.gperf"
+#line 169 "locfile-kw.gperf"
{"LC_ADDRESS", tok_lc_address, 0},
-#line 153 "locfile-kw.gperf"
+#line 154 "locfile-kw.gperf"
{"LC_MESSAGES", tok_lc_messages, 0},
-#line 161 "locfile-kw.gperf"
+#line 162 "locfile-kw.gperf"
{"LC_NAME", tok_lc_name, 0},
-#line 158 "locfile-kw.gperf"
+#line 159 "locfile-kw.gperf"
{"LC_PAPER", tok_lc_paper, 0},
-#line 186 "locfile-kw.gperf"
+#line 187 "locfile-kw.gperf"
{"LC_MEASUREMENT", tok_lc_measurement, 0},
#line 56 "locfile-kw.gperf"
{"LC_COLLATE", tok_lc_collate, 0},
{""},
-#line 188 "locfile-kw.gperf"
+#line 189 "locfile-kw.gperf"
{"LC_IDENTIFICATION", tok_lc_identification, 0},
-#line 201 "locfile-kw.gperf"
+#line 202 "locfile-kw.gperf"
{"revision", tok_revision, 0},
-#line 69 "locfile-kw.gperf"
+#line 70 "locfile-kw.gperf"
{"UNDEFINED", tok_undefined, 0},
-#line 125 "locfile-kw.gperf"
+#line 126 "locfile-kw.gperf"
{"LC_NUMERIC", tok_lc_numeric, 0},
-#line 82 "locfile-kw.gperf"
+#line 83 "locfile-kw.gperf"
{"LC_MONETARY", tok_lc_monetary, 0},
-#line 181 "locfile-kw.gperf"
+#line 182 "locfile-kw.gperf"
{"LC_TELEPHONE", tok_lc_telephone, 0},
{""}, {""}, {""},
-#line 75 "locfile-kw.gperf"
+#line 76 "locfile-kw.gperf"
{"define", tok_define, 0},
-#line 154 "locfile-kw.gperf"
+#line 155 "locfile-kw.gperf"
{"yesexpr", tok_yesexpr, 0},
-#line 141 "locfile-kw.gperf"
+#line 142 "locfile-kw.gperf"
{"era_year", tok_era_year, 0},
{""},
#line 54 "locfile-kw.gperf"
{"translit_ignore", tok_translit_ignore, 0},
-#line 156 "locfile-kw.gperf"
+#line 157 "locfile-kw.gperf"
{"yesstr", tok_yesstr, 0},
{""},
-#line 89 "locfile-kw.gperf"
+#line 90 "locfile-kw.gperf"
{"negative_sign", tok_negative_sign, 0},
{""},
-#line 137 "locfile-kw.gperf"
+#line 138 "locfile-kw.gperf"
{"t_fmt", tok_t_fmt, 0},
-#line 159 "locfile-kw.gperf"
+#line 160 "locfile-kw.gperf"
{"height", tok_height, 0},
{""}, {""},
#line 52 "locfile-kw.gperf"
{"translit_start", tok_translit_start, 0},
-#line 136 "locfile-kw.gperf"
+#line 137 "locfile-kw.gperf"
{"d_fmt", tok_d_fmt, 0},
{""},
#line 53 "locfile-kw.gperf"
{"translit_end", tok_translit_end, 0},
-#line 94 "locfile-kw.gperf"
+#line 95 "locfile-kw.gperf"
{"n_cs_precedes", tok_n_cs_precedes, 0},
-#line 144 "locfile-kw.gperf"
+#line 145 "locfile-kw.gperf"
{"era_t_fmt", tok_era_t_fmt, 0},
#line 39 "locfile-kw.gperf"
{"space", tok_space, 0},
-#line 72 "locfile-kw.gperf"
- {"reorder-end", tok_reorder_end, 0},
#line 73 "locfile-kw.gperf"
+ {"reorder-end", tok_reorder_end, 0},
+#line 74 "locfile-kw.gperf"
{"reorder-sections-after", tok_reorder_sections_after, 0},
{""},
-#line 142 "locfile-kw.gperf"
+#line 143 "locfile-kw.gperf"
{"era_d_fmt", tok_era_d_fmt, 0},
-#line 189 "locfile-kw.gperf"
+#line 190 "locfile-kw.gperf"
{"title", tok_title, 0},
{""}, {""},
-#line 149 "locfile-kw.gperf"
+#line 150 "locfile-kw.gperf"
{"timezone", tok_timezone, 0},
{""},
-#line 74 "locfile-kw.gperf"
+#line 75 "locfile-kw.gperf"
{"reorder-sections-end", tok_reorder_sections_end, 0},
{""}, {""}, {""},
-#line 95 "locfile-kw.gperf"
+#line 96 "locfile-kw.gperf"
{"n_sep_by_space", tok_n_sep_by_space, 0},
{""}, {""},
-#line 100 "locfile-kw.gperf"
+#line 101 "locfile-kw.gperf"
{"int_n_cs_precedes", tok_int_n_cs_precedes, 0},
{""}, {""}, {""},
#line 26 "locfile-kw.gperf"
@@ -233,147 +233,147 @@ locfile_hash (register const char *str, register size_t len)
{"print", tok_print, 0},
#line 44 "locfile-kw.gperf"
{"xdigit", tok_xdigit, 0},
-#line 110 "locfile-kw.gperf"
+#line 111 "locfile-kw.gperf"
{"duo_n_cs_precedes", tok_duo_n_cs_precedes, 0},
-#line 127 "locfile-kw.gperf"
+#line 128 "locfile-kw.gperf"
{"thousands_sep", tok_thousands_sep, 0},
-#line 197 "locfile-kw.gperf"
+#line 198 "locfile-kw.gperf"
{"territory", tok_territory, 0},
#line 36 "locfile-kw.gperf"
{"digit", tok_digit, 0},
{""}, {""},
-#line 92 "locfile-kw.gperf"
+#line 93 "locfile-kw.gperf"
{"p_cs_precedes", tok_p_cs_precedes, 0},
{""}, {""},
-#line 62 "locfile-kw.gperf"
+#line 63 "locfile-kw.gperf"
{"script", tok_script, 0},
#line 29 "locfile-kw.gperf"
{"include", tok_include, 0},
{""},
-#line 78 "locfile-kw.gperf"
+#line 79 "locfile-kw.gperf"
{"else", tok_else, 0},
-#line 184 "locfile-kw.gperf"
+#line 185 "locfile-kw.gperf"
{"int_select", tok_int_select, 0},
{""}, {""}, {""},
-#line 132 "locfile-kw.gperf"
+#line 133 "locfile-kw.gperf"
{"week", tok_week, 0},
#line 33 "locfile-kw.gperf"
{"upper", tok_upper, 0},
{""}, {""},
-#line 194 "locfile-kw.gperf"
+#line 195 "locfile-kw.gperf"
{"tel", tok_tel, 0},
-#line 93 "locfile-kw.gperf"
+#line 94 "locfile-kw.gperf"
{"p_sep_by_space", tok_p_sep_by_space, 0},
-#line 160 "locfile-kw.gperf"
+#line 161 "locfile-kw.gperf"
{"width", tok_width, 0},
{""},
-#line 98 "locfile-kw.gperf"
+#line 99 "locfile-kw.gperf"
{"int_p_cs_precedes", tok_int_p_cs_precedes, 0},
{""}, {""},
#line 41 "locfile-kw.gperf"
{"punct", tok_punct, 0},
{""}, {""},
-#line 101 "locfile-kw.gperf"
+#line 102 "locfile-kw.gperf"
{"int_n_sep_by_space", tok_int_n_sep_by_space, 0},
{""}, {""}, {""},
-#line 108 "locfile-kw.gperf"
+#line 109 "locfile-kw.gperf"
{"duo_p_cs_precedes", tok_duo_p_cs_precedes, 0},
#line 48 "locfile-kw.gperf"
{"charconv", tok_charconv, 0},
{""},
#line 47 "locfile-kw.gperf"
{"class", tok_class, 0},
-#line 114 "locfile-kw.gperf"
- {"duo_int_n_cs_precedes", tok_duo_int_n_cs_precedes, 0},
#line 115 "locfile-kw.gperf"
+ {"duo_int_n_cs_precedes", tok_duo_int_n_cs_precedes, 0},
+#line 116 "locfile-kw.gperf"
{"duo_int_n_sep_by_space", tok_duo_int_n_sep_by_space, 0},
-#line 111 "locfile-kw.gperf"
+#line 112 "locfile-kw.gperf"
{"duo_n_sep_by_space", tok_duo_n_sep_by_space, 0},
-#line 119 "locfile-kw.gperf"
+#line 120 "locfile-kw.gperf"
{"duo_int_n_sign_posn", tok_duo_int_n_sign_posn, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""},
-#line 58 "locfile-kw.gperf"
+#line 59 "locfile-kw.gperf"
{"section-symbol", tok_section_symbol, 0},
-#line 185 "locfile-kw.gperf"
+#line 186 "locfile-kw.gperf"
{"int_prefix", tok_int_prefix, 0},
{""}, {""}, {""}, {""},
#line 42 "locfile-kw.gperf"
{"graph", tok_graph, 0},
{""}, {""},
-#line 99 "locfile-kw.gperf"
+#line 100 "locfile-kw.gperf"
{"int_p_sep_by_space", tok_int_p_sep_by_space, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 112 "locfile-kw.gperf"
- {"duo_int_p_cs_precedes", tok_duo_int_p_cs_precedes, 0},
#line 113 "locfile-kw.gperf"
+ {"duo_int_p_cs_precedes", tok_duo_int_p_cs_precedes, 0},
+#line 114 "locfile-kw.gperf"
{"duo_int_p_sep_by_space", tok_duo_int_p_sep_by_space, 0},
-#line 109 "locfile-kw.gperf"
+#line 110 "locfile-kw.gperf"
{"duo_p_sep_by_space", tok_duo_p_sep_by_space, 0},
-#line 118 "locfile-kw.gperf"
+#line 119 "locfile-kw.gperf"
{"duo_int_p_sign_posn", tok_duo_int_p_sign_posn, 0},
-#line 157 "locfile-kw.gperf"
+#line 158 "locfile-kw.gperf"
{"nostr", tok_nostr, 0},
{""}, {""},
-#line 140 "locfile-kw.gperf"
+#line 141 "locfile-kw.gperf"
{"era", tok_era, 0},
{""},
-#line 84 "locfile-kw.gperf"
+#line 85 "locfile-kw.gperf"
{"currency_symbol", tok_currency_symbol, 0},
{""},
-#line 167 "locfile-kw.gperf"
+#line 168 "locfile-kw.gperf"
{"name_ms", tok_name_ms, 0},
-#line 165 "locfile-kw.gperf"
- {"name_mrs", tok_name_mrs, 0},
#line 166 "locfile-kw.gperf"
+ {"name_mrs", tok_name_mrs, 0},
+#line 167 "locfile-kw.gperf"
{"name_miss", tok_name_miss, 0},
-#line 83 "locfile-kw.gperf"
+#line 84 "locfile-kw.gperf"
{"int_curr_symbol", tok_int_curr_symbol, 0},
-#line 190 "locfile-kw.gperf"
+#line 191 "locfile-kw.gperf"
{"source", tok_source, 0},
-#line 164 "locfile-kw.gperf"
+#line 165 "locfile-kw.gperf"
{"name_mr", tok_name_mr, 0},
-#line 163 "locfile-kw.gperf"
+#line 164 "locfile-kw.gperf"
{"name_gen", tok_name_gen, 0},
-#line 202 "locfile-kw.gperf"
+#line 203 "locfile-kw.gperf"
{"date", tok_date, 0},
{""}, {""},
-#line 191 "locfile-kw.gperf"
+#line 192 "locfile-kw.gperf"
{"address", tok_address, 0},
-#line 162 "locfile-kw.gperf"
+#line 163 "locfile-kw.gperf"
{"name_fmt", tok_name_fmt, 0},
#line 32 "locfile-kw.gperf"
{"copy", tok_copy, 0},
-#line 103 "locfile-kw.gperf"
+#line 104 "locfile-kw.gperf"
{"int_n_sign_posn", tok_int_n_sign_posn, 0},
{""}, {""},
-#line 131 "locfile-kw.gperf"
+#line 132 "locfile-kw.gperf"
{"day", tok_day, 0},
-#line 105 "locfile-kw.gperf"
+#line 106 "locfile-kw.gperf"
{"duo_currency_symbol", tok_duo_currency_symbol, 0},
{""}, {""}, {""},
-#line 150 "locfile-kw.gperf"
+#line 151 "locfile-kw.gperf"
{"date_fmt", tok_date_fmt, 0},
-#line 64 "locfile-kw.gperf"
+#line 65 "locfile-kw.gperf"
{"order_end", tok_order_end, 0},
-#line 117 "locfile-kw.gperf"
+#line 118 "locfile-kw.gperf"
{"duo_n_sign_posn", tok_duo_n_sign_posn, 0},
{""},
-#line 170 "locfile-kw.gperf"
+#line 171 "locfile-kw.gperf"
{"country_name", tok_country_name, 0},
-#line 71 "locfile-kw.gperf"
+#line 72 "locfile-kw.gperf"
{"reorder-after", tok_reorder_after, 0},
{""}, {""},
-#line 155 "locfile-kw.gperf"
+#line 156 "locfile-kw.gperf"
{"noexpr", tok_noexpr, 0},
#line 50 "locfile-kw.gperf"
{"tolower", tok_tolower, 0},
-#line 198 "locfile-kw.gperf"
+#line 199 "locfile-kw.gperf"
{"audience", tok_audience, 0},
{""}, {""}, {""},
#line 49 "locfile-kw.gperf"
{"toupper", tok_toupper, 0},
-#line 68 "locfile-kw.gperf"
+#line 69 "locfile-kw.gperf"
{"position", tok_position, 0},
{""},
#line 40 "locfile-kw.gperf"
@@ -381,196 +381,197 @@ locfile_hash (register const char *str, register size_t len)
{""},
#line 27 "locfile-kw.gperf"
{"comment_char", tok_comment_char, 0},
-#line 88 "locfile-kw.gperf"
+#line 89 "locfile-kw.gperf"
{"positive_sign", tok_positive_sign, 0},
{""}, {""}, {""}, {""},
-#line 61 "locfile-kw.gperf"
+#line 62 "locfile-kw.gperf"
{"symbol-equivalence", tok_symbol_equivalence, 0},
{""},
-#line 102 "locfile-kw.gperf"
+#line 103 "locfile-kw.gperf"
{"int_p_sign_posn", tok_int_p_sign_posn, 0},
-#line 175 "locfile-kw.gperf"
+#line 176 "locfile-kw.gperf"
{"country_car", tok_country_car, 0},
{""}, {""},
-#line 104 "locfile-kw.gperf"
+#line 105 "locfile-kw.gperf"
{"duo_int_curr_symbol", tok_duo_int_curr_symbol, 0},
{""}, {""},
-#line 135 "locfile-kw.gperf"
+#line 136 "locfile-kw.gperf"
{"d_t_fmt", tok_d_t_fmt, 0},
{""}, {""},
-#line 116 "locfile-kw.gperf"
+#line 117 "locfile-kw.gperf"
{"duo_p_sign_posn", tok_duo_p_sign_posn, 0},
-#line 187 "locfile-kw.gperf"
+#line 188 "locfile-kw.gperf"
{"measurement", tok_measurement, 0},
-#line 176 "locfile-kw.gperf"
+#line 177 "locfile-kw.gperf"
{"country_isbn", tok_country_isbn, 0},
#line 37 "locfile-kw.gperf"
{"outdigit", tok_outdigit, 0},
{""}, {""},
-#line 143 "locfile-kw.gperf"
+#line 144 "locfile-kw.gperf"
{"era_d_t_fmt", tok_era_d_t_fmt, 0},
{""}, {""}, {""},
#line 34 "locfile-kw.gperf"
{"lower", tok_lower, 0},
-#line 183 "locfile-kw.gperf"
+#line 184 "locfile-kw.gperf"
{"tel_dom_fmt", tok_tel_dom_fmt, 0},
-#line 171 "locfile-kw.gperf"
+#line 172 "locfile-kw.gperf"
{"country_post", tok_country_post, 0},
-#line 148 "locfile-kw.gperf"
+#line 149 "locfile-kw.gperf"
{"cal_direction", tok_cal_direction, 0},
- {""},
-#line 139 "locfile-kw.gperf"
+#line 57 "locfile-kw.gperf"
+ {"codepoint_collation", tok_codepoint_collation, 0},
+#line 140 "locfile-kw.gperf"
{"t_fmt_ampm", tok_t_fmt_ampm, 0},
-#line 91 "locfile-kw.gperf"
+#line 92 "locfile-kw.gperf"
{"frac_digits", tok_frac_digits, 0},
{""}, {""},
-#line 177 "locfile-kw.gperf"
+#line 178 "locfile-kw.gperf"
{"lang_name", tok_lang_name, 0},
-#line 90 "locfile-kw.gperf"
+#line 91 "locfile-kw.gperf"
{"int_frac_digits", tok_int_frac_digits, 0},
{""},
-#line 121 "locfile-kw.gperf"
+#line 122 "locfile-kw.gperf"
{"uno_valid_to", tok_uno_valid_to, 0},
-#line 126 "locfile-kw.gperf"
+#line 127 "locfile-kw.gperf"
{"decimal_point", tok_decimal_point, 0},
{""},
-#line 133 "locfile-kw.gperf"
+#line 134 "locfile-kw.gperf"
{"abmon", tok_abmon, 0},
{""}, {""}, {""}, {""},
-#line 107 "locfile-kw.gperf"
+#line 108 "locfile-kw.gperf"
{"duo_frac_digits", tok_duo_frac_digits, 0},
-#line 182 "locfile-kw.gperf"
+#line 183 "locfile-kw.gperf"
{"tel_int_fmt", tok_tel_int_fmt, 0},
-#line 123 "locfile-kw.gperf"
+#line 124 "locfile-kw.gperf"
{"duo_valid_to", tok_duo_valid_to, 0},
-#line 146 "locfile-kw.gperf"
+#line 147 "locfile-kw.gperf"
{"first_weekday", tok_first_weekday, 0},
{""},
-#line 130 "locfile-kw.gperf"
+#line 131 "locfile-kw.gperf"
{"abday", tok_abday, 0},
{""},
-#line 200 "locfile-kw.gperf"
+#line 201 "locfile-kw.gperf"
{"abbreviation", tok_abbreviation, 0},
-#line 147 "locfile-kw.gperf"
+#line 148 "locfile-kw.gperf"
{"first_workday", tok_first_workday, 0},
{""}, {""},
-#line 97 "locfile-kw.gperf"
+#line 98 "locfile-kw.gperf"
{"n_sign_posn", tok_n_sign_posn, 0},
{""}, {""}, {""},
-#line 145 "locfile-kw.gperf"
+#line 146 "locfile-kw.gperf"
{"alt_digits", tok_alt_digits, 0},
{""}, {""},
-#line 128 "locfile-kw.gperf"
+#line 129 "locfile-kw.gperf"
{"grouping", tok_grouping, 0},
{""},
#line 45 "locfile-kw.gperf"
{"blank", tok_blank, 0},
{""}, {""},
-#line 196 "locfile-kw.gperf"
+#line 197 "locfile-kw.gperf"
{"language", tok_language, 0},
-#line 120 "locfile-kw.gperf"
+#line 121 "locfile-kw.gperf"
{"uno_valid_from", tok_uno_valid_from, 0},
{""},
-#line 199 "locfile-kw.gperf"
+#line 200 "locfile-kw.gperf"
{"application", tok_application, 0},
{""},
-#line 80 "locfile-kw.gperf"
+#line 81 "locfile-kw.gperf"
{"elifndef", tok_elifndef, 0},
{""}, {""}, {""}, {""}, {""},
-#line 122 "locfile-kw.gperf"
+#line 123 "locfile-kw.gperf"
{"duo_valid_from", tok_duo_valid_from, 0},
-#line 57 "locfile-kw.gperf"
+#line 58 "locfile-kw.gperf"
{"coll_weight_max", tok_coll_weight_max, 0},
{""},
-#line 79 "locfile-kw.gperf"
+#line 80 "locfile-kw.gperf"
{"elifdef", tok_elifdef, 0},
-#line 67 "locfile-kw.gperf"
+#line 68 "locfile-kw.gperf"
{"backward", tok_backward, 0},
-#line 106 "locfile-kw.gperf"
+#line 107 "locfile-kw.gperf"
{"duo_int_frac_digits", tok_duo_int_frac_digits, 0},
{""}, {""}, {""}, {""}, {""}, {""},
-#line 96 "locfile-kw.gperf"
+#line 97 "locfile-kw.gperf"
{"p_sign_posn", tok_p_sign_posn, 0},
{""},
-#line 203 "locfile-kw.gperf"
+#line 204 "locfile-kw.gperf"
{"category", tok_category, 0},
{""}, {""}, {""}, {""},
-#line 134 "locfile-kw.gperf"
+#line 135 "locfile-kw.gperf"
{"mon", tok_mon, 0},
{""},
-#line 124 "locfile-kw.gperf"
+#line 125 "locfile-kw.gperf"
{"conversion_rate", tok_conversion_rate, 0},
{""}, {""}, {""}, {""}, {""},
-#line 63 "locfile-kw.gperf"
+#line 64 "locfile-kw.gperf"
{"order_start", tok_order_start, 0},
{""}, {""}, {""}, {""}, {""},
-#line 178 "locfile-kw.gperf"
+#line 179 "locfile-kw.gperf"
{"lang_ab", tok_lang_ab, 0},
-#line 180 "locfile-kw.gperf"
+#line 181 "locfile-kw.gperf"
{"lang_lib", tok_lang_lib, 0},
{""}, {""}, {""},
-#line 192 "locfile-kw.gperf"
+#line 193 "locfile-kw.gperf"
{"contact", tok_contact, 0},
{""}, {""}, {""},
-#line 173 "locfile-kw.gperf"
+#line 174 "locfile-kw.gperf"
{"country_ab3", tok_country_ab3, 0},
{""}, {""}, {""},
-#line 193 "locfile-kw.gperf"
+#line 194 "locfile-kw.gperf"
{"email", tok_email, 0},
-#line 172 "locfile-kw.gperf"
+#line 173 "locfile-kw.gperf"
{"country_ab2", tok_country_ab2, 0},
{""}, {""}, {""},
#line 55 "locfile-kw.gperf"
{"default_missing", tok_default_missing, 0},
{""}, {""},
-#line 195 "locfile-kw.gperf"
+#line 196 "locfile-kw.gperf"
{"fax", tok_fax, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 174 "locfile-kw.gperf"
+#line 175 "locfile-kw.gperf"
{"country_num", tok_country_num, 0},
{""}, {""}, {""}, {""}, {""}, {""},
#line 51 "locfile-kw.gperf"
{"map", tok_map, 0},
-#line 65 "locfile-kw.gperf"
+#line 66 "locfile-kw.gperf"
{"from", tok_from, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 86 "locfile-kw.gperf"
+#line 87 "locfile-kw.gperf"
{"mon_thousands_sep", tok_mon_thousands_sep, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""},
-#line 81 "locfile-kw.gperf"
+#line 82 "locfile-kw.gperf"
{"endif", tok_endif, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 151 "locfile-kw.gperf"
+#line 152 "locfile-kw.gperf"
{"alt_mon", tok_alt_mon, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 76 "locfile-kw.gperf"
+#line 77 "locfile-kw.gperf"
{"undef", tok_undef, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 59 "locfile-kw.gperf"
+#line 60 "locfile-kw.gperf"
{"collating-element", tok_collating_element, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 152 "locfile-kw.gperf"
+#line 153 "locfile-kw.gperf"
{"ab_alt_mon", tok_ab_alt_mon, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 66 "locfile-kw.gperf"
+#line 67 "locfile-kw.gperf"
{"forward", tok_forward, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""},
-#line 85 "locfile-kw.gperf"
+#line 86 "locfile-kw.gperf"
{"mon_decimal_point", tok_mon_decimal_point, 0},
{""}, {""},
-#line 169 "locfile-kw.gperf"
+#line 170 "locfile-kw.gperf"
{"postal_fmt", tok_postal_fmt, 0},
{""}, {""}, {""}, {""}, {""},
-#line 60 "locfile-kw.gperf"
+#line 61 "locfile-kw.gperf"
{"collating-symbol", tok_collating_symbol, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
@@ -583,15 +584,15 @@ locfile_hash (register const char *str, register size_t len)
#line 38 "locfile-kw.gperf"
{"alnum", tok_alnum, 0},
{""},
-#line 87 "locfile-kw.gperf"
+#line 88 "locfile-kw.gperf"
{"mon_grouping", tok_mon_grouping, 0},
{""},
-#line 179 "locfile-kw.gperf"
+#line 180 "locfile-kw.gperf"
{"lang_term", tok_lang_term, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 77 "locfile-kw.gperf"
+#line 78 "locfile-kw.gperf"
{"ifdef", tok_ifdef, 0},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
@@ -599,7 +600,7 @@ locfile_hash (register const char *str, register size_t len)
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""},
-#line 138 "locfile-kw.gperf"
+#line 139 "locfile-kw.gperf"
{"am_pm", tok_am_pm, 0}
};
diff --git a/locale/programs/locfile-token.h b/locale/programs/locfile-token.h
index 414ad3076223e971..f57d594e8d25c06f 100644
--- a/locale/programs/locfile-token.h
+++ b/locale/programs/locfile-token.h
@@ -91,6 +91,7 @@ enum token_t
tok_translit_ignore,
tok_default_missing,
tok_lc_collate,
+ tok_codepoint_collation,
tok_coll_weight_max,
tok_section_symbol,
tok_collating_element,

File diff suppressed because it is too large Load Diff

@ -0,0 +1,65 @@
commit 1d8e3a2c6636cf0b1b8fa2f869cef6ec10726933
Author: Carlos O'Donell <carlos@redhat.com>
Date: Mon Jan 31 00:34:41 2022 -0500
localedef: Fix handling of empty mon_decimal_point (Bug 28847)
The handling of mon_decimal_point is incorrect when it comes to
handling the empty "" value. The existing parser in monetary_read()
will correctly handle setting the non-wide-character value and the
wide-character value e.g. STR_ELEM_WC(mon_decimal_point) if they are
set in the locale definition. However, in monetary_finish() we have
conflicting TEST_ELEM() which sets a default value (if the locale
definition doesn't include one), and subsequent code which looks for
mon_decimal_point to be NULL to issue a specific error message and set
the defaults. The latter is unused because TEST_ELEM() always sets a
default. The simplest solution is to remove the TEST_ELEM() check,
and allow the existing check to look to see if mon_decimal_point is
NULL and set an appropriate default. The final fix is to move the
setting of mon_decimal_point_wc so it occurs only when
mon_decimal_point is being set to a default, keeping both values
consistent. There is no way to tell the difference between
mon_decimal_point_wc having been set to the empty string and not
having been defined at all, for that distinction we must use
mon_decimal_point being NULL or "", and so we must logically set
the default together with mon_decimal_point.
Lastly, there are more fixes similar to this that could be made to
ld-monetary.c, but we avoid that in order to fix just the code
required for mon_decimal_point, which impacts the ability for C.UTF-8
to set mon_decimal_point to "", since without this fix we end up with
an inconsistent setting of mon_decimal_point set to "", but
mon_decimal_point_wc set to "." which is incorrect.
Tested on x86_64 and i686 without regression.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
diff --git a/locale/programs/ld-monetary.c b/locale/programs/ld-monetary.c
index e1e45a3409123bf4..9b9a55bb4766dfcf 100644
--- a/locale/programs/ld-monetary.c
+++ b/locale/programs/ld-monetary.c
@@ -208,7 +208,6 @@ No definition for %s category found"), "LC_MONETARY");
TEST_ELEM (int_curr_symbol, "");
TEST_ELEM (currency_symbol, "");
- TEST_ELEM (mon_decimal_point, ".");
TEST_ELEM (mon_thousands_sep, "");
TEST_ELEM (positive_sign, "");
TEST_ELEM (negative_sign, "");
@@ -258,6 +257,7 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
record_error (0, 0, _("%s: field `%s' not defined"),
"LC_MONETARY", "mon_decimal_point");
monetary->mon_decimal_point = ".";
+ monetary->mon_decimal_point_wc = L'.';
}
else if (monetary->mon_decimal_point[0] == '\0' && ! be_quiet && ! nothing)
{
@@ -265,8 +265,6 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
%s: value for field `%s' must not be an empty string"),
"LC_MONETARY", "mon_decimal_point");
}
- if (monetary->mon_decimal_point_wc == L'\0')
- monetary->mon_decimal_point_wc = L'.';
if (monetary->mon_grouping_len == 0)
{

@ -0,0 +1,734 @@
commit de82cb0da4b8fa5b3d56c457438d2568c67ab1b1
Author: Joseph Myers <joseph@codesourcery.com>
Date: Tue Oct 12 13:48:39 2021 +0000
Add TEST_COMPARE_STRING_WIDE to support/check.h
I'd like to be able to test narrow and wide string interfaces, with
the narrow string tests using TEST_COMPARE_STRING and the wide string
tests using something analogous (possibly generated using macros from
a common test template for both the narrow and wide string tests where
appropriate).
Add such a TEST_COMPARE_STRING_WIDE, along with functions
support_quote_blob_wide and support_test_compare_string_wide that it
builds on. Those functions are built using macros from common
templates shared by the narrow and wide string implementations, though
I didn't do that for the tests of test functions. In
support_quote_blob_wide, I chose to use the \x{} delimited escape
sequence syntax proposed for C2X in N2785, rather than e.g. trying to
generate the end of a string and the start of a new string when
ambiguity would result from undelimited \x (when the next character
after such an escape sequence is valid hex) or forcing an escape
sequence to be used for the next character in the case of such
ambiguity.
Tested for x86_64.
diff --git a/support/Makefile b/support/Makefile
index 75bad6715ac3d08c..3c941e1ba9e29aa4 100644
--- a/support/Makefile
+++ b/support/Makefile
@@ -70,6 +70,7 @@ libsupport-routines = \
support_openpty \
support_paths \
support_quote_blob \
+ support_quote_blob_wide \
support_quote_string \
support_record_failure \
support_run_diff \
@@ -83,6 +84,7 @@ libsupport-routines = \
support_test_compare_blob \
support_test_compare_failure \
support_test_compare_string \
+ support_test_compare_string_wide \
support_test_main \
support_test_verify_impl \
support_wait_for_thread_exit \
@@ -275,11 +277,13 @@ tests = \
tst-support-open-dev-null-range \
tst-support-process_state \
tst-support_quote_blob \
+ tst-support_quote_blob_wide \
tst-support_quote_string \
tst-support_record_failure \
tst-test_compare \
tst-test_compare_blob \
tst-test_compare_string \
+ tst-test_compare_string_wide \
tst-timespec \
tst-xreadlink \
tst-xsigstack \
diff --git a/support/check.h b/support/check.h
index 83662b2d10c8cf58..9b1844352f32513a 100644
--- a/support/check.h
+++ b/support/check.h
@@ -20,6 +20,7 @@
#define SUPPORT_CHECK_H
#include <sys/cdefs.h>
+#include <stddef.h>
__BEGIN_DECLS
@@ -171,11 +172,25 @@ void support_test_compare_blob (const void *left,
(support_test_compare_string (left, right, __FILE__, __LINE__, \
#left, #right))
+/* Compare the wide strings LEFT and RIGHT and report a test failure
+ if they are different. Also report failure if one of the arguments
+ is a null pointer and the other is not. The strings should be
+ reasonably short because on mismatch, both are printed. */
+#define TEST_COMPARE_STRING_WIDE(left, right) \
+ (support_test_compare_string_wide (left, right, __FILE__, __LINE__, \
+ #left, #right))
+
void support_test_compare_string (const char *left, const char *right,
const char *file, int line,
const char *left_expr,
const char *right_expr);
+void support_test_compare_string_wide (const wchar_t *left,
+ const wchar_t *right,
+ const char *file, int line,
+ const char *left_expr,
+ const char *right_expr);
+
/* Internal function called by the test driver. */
int support_report_failure (int status)
__attribute__ ((weak, warn_unused_result));
diff --git a/support/support.h b/support/support.h
index c219e0d9d1aef046..29d56c7c891ee34b 100644
--- a/support/support.h
+++ b/support/support.h
@@ -73,6 +73,12 @@ void support_write_file_string (const char *path, const char *contents);
the result). */
char *support_quote_blob (const void *blob, size_t length);
+/* Quote the contents of the wide character array starting at BLOB, of
+ LENGTH wide characters, in such a way that the result string can be
+ included in a C wide string literal (in single/double quotes,
+ without putting the quotes into the result). */
+char *support_quote_blob_wide (const void *blob, size_t length);
+
/* Quote the contents of the string, in such a way that the result
string can be included in a C literal (in single/double quotes,
without putting the quotes into the result). */
diff --git a/support/support_quote_blob.c b/support/support_quote_blob.c
index b5e70125f13eb081..611980c9a2108670 100644
--- a/support/support_quote_blob.c
+++ b/support/support_quote_blob.c
@@ -1,4 +1,4 @@
-/* Quote a blob so that it can be used in C literals.
+/* Quote a narrow string blob so that it can be used in C literals.
Copyright (C) 2018-2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -16,68 +16,9 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <support/support.h>
-#include <support/xmemstream.h>
+#define CHAR unsigned char
+#define L_(C) C
+#define SUPPORT_QUOTE_BLOB support_quote_blob
+#define WIDE 0
-char *
-support_quote_blob (const void *blob, size_t length)
-{
- struct xmemstream out;
- xopen_memstream (&out);
-
- const unsigned char *p = blob;
- for (size_t i = 0; i < length; ++i)
- {
- unsigned char ch = p[i];
-
- /* Use C backslash escapes for those control characters for
- which they are defined. */
- switch (ch)
- {
- case '\a':
- putc_unlocked ('\\', out.out);
- putc_unlocked ('a', out.out);
- break;
- case '\b':
- putc_unlocked ('\\', out.out);
- putc_unlocked ('b', out.out);
- break;
- case '\f':
- putc_unlocked ('\\', out.out);
- putc_unlocked ('f', out.out);
- break;
- case '\n':
- putc_unlocked ('\\', out.out);
- putc_unlocked ('n', out.out);
- break;
- case '\r':
- putc_unlocked ('\\', out.out);
- putc_unlocked ('r', out.out);
- break;
- case '\t':
- putc_unlocked ('\\', out.out);
- putc_unlocked ('t', out.out);
- break;
- case '\v':
- putc_unlocked ('\\', out.out);
- putc_unlocked ('v', out.out);
- break;
- case '\\':
- case '\'':
- case '\"':
- putc_unlocked ('\\', out.out);
- putc_unlocked (ch, out.out);
- break;
- default:
- if (ch < ' ' || ch > '~')
- /* Use octal sequences because they are fixed width,
- unlike hexadecimal sequences. */
- fprintf (out.out, "\\%03o", ch);
- else
- putc_unlocked (ch, out.out);
- }
- }
-
- xfclose_memstream (&out);
- return out.buffer;
-}
+#include "support_quote_blob_main.c"
diff --git a/support/support_quote_blob_main.c b/support/support_quote_blob_main.c
new file mode 100644
index 0000000000000000..19ccfad59311bfee
--- /dev/null
+++ b/support/support_quote_blob_main.c
@@ -0,0 +1,88 @@
+/* Quote a blob so that it can be used in C literals.
+ Copyright (C) 2018-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/support.h>
+#include <support/xmemstream.h>
+
+char *
+SUPPORT_QUOTE_BLOB (const void *blob, size_t length)
+{
+ struct xmemstream out;
+ xopen_memstream (&out);
+
+ const CHAR *p = blob;
+ for (size_t i = 0; i < length; ++i)
+ {
+ CHAR ch = p[i];
+
+ /* Use C backslash escapes for those control characters for
+ which they are defined. */
+ switch (ch)
+ {
+ case L_('\a'):
+ putc_unlocked ('\\', out.out);
+ putc_unlocked ('a', out.out);
+ break;
+ case L_('\b'):
+ putc_unlocked ('\\', out.out);
+ putc_unlocked ('b', out.out);
+ break;
+ case L_('\f'):
+ putc_unlocked ('\\', out.out);
+ putc_unlocked ('f', out.out);
+ break;
+ case L_('\n'):
+ putc_unlocked ('\\', out.out);
+ putc_unlocked ('n', out.out);
+ break;
+ case L_('\r'):
+ putc_unlocked ('\\', out.out);
+ putc_unlocked ('r', out.out);
+ break;
+ case L_('\t'):
+ putc_unlocked ('\\', out.out);
+ putc_unlocked ('t', out.out);
+ break;
+ case L_('\v'):
+ putc_unlocked ('\\', out.out);
+ putc_unlocked ('v', out.out);
+ break;
+ case L_('\\'):
+ case L_('\''):
+ case L_('\"'):
+ putc_unlocked ('\\', out.out);
+ putc_unlocked (ch, out.out);
+ break;
+ default:
+ if (ch < L_(' ') || ch > L_('~'))
+ /* For narrow characters, use octal sequences because they
+ are fixed width, unlike hexadecimal sequences. For
+ wide characters, use N2785 delimited escape
+ sequences. */
+ if (WIDE)
+ fprintf (out.out, "\\x{%x}", (unsigned int) ch);
+ else
+ fprintf (out.out, "\\%03o", (unsigned int) ch);
+ else
+ putc_unlocked (ch, out.out);
+ }
+ }
+
+ xfclose_memstream (&out);
+ return out.buffer;
+}
diff --git a/support/support_quote_blob_wide.c b/support/support_quote_blob_wide.c
new file mode 100644
index 0000000000000000..c451ed889c21c626
--- /dev/null
+++ b/support/support_quote_blob_wide.c
@@ -0,0 +1,24 @@
+/* Quote a wide string blob so that it can be used in C literals.
+ Copyright (C) 2018-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 CHAR wchar_t
+#define L_(C) L ## C
+#define SUPPORT_QUOTE_BLOB support_quote_blob_wide
+#define WIDE 1
+
+#include "support_quote_blob_main.c"
diff --git a/support/support_test_compare_string.c b/support/support_test_compare_string.c
index cbeaf7b1eeea8ca8..12bafe43d44ae3d7 100644
--- a/support/support_test_compare_string.c
+++ b/support/support_test_compare_string.c
@@ -16,76 +16,13 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <support/check.h>
-#include <support/support.h>
-#include <support/xmemstream.h>
-
-static void
-report_length (const char *what, const char *str, size_t length)
-{
- if (str == NULL)
- printf (" %s string: NULL\n", what);
- else
- printf (" %s string: %zu bytes\n", what, length);
-}
-
-static void
-report_string (const char *what, const unsigned char *blob,
- size_t length, const char *expr)
-{
- if (length > 0)
- {
- printf (" %s (evaluated from %s):\n", what, expr);
- char *quoted = support_quote_blob (blob, length);
- printf (" \"%s\"\n", quoted);
- free (quoted);
-
- fputs (" ", stdout);
- for (size_t i = 0; i < length; ++i)
- printf (" %02X", blob[i]);
- putc ('\n', stdout);
- }
-}
-
-static size_t
-string_length_or_zero (const char *str)
-{
- if (str == NULL)
- return 0;
- else
- return strlen (str);
-}
-
-void
-support_test_compare_string (const char *left, const char *right,
- const char *file, int line,
- const char *left_expr, const char *right_expr)
-{
- /* Two null pointers are accepted. */
- if (left == NULL && right == NULL)
- return;
-
- size_t left_length = string_length_or_zero (left);
- size_t right_length = string_length_or_zero (right);
-
- if (left_length != right_length || left == NULL || right == NULL
- || memcmp (left, right, left_length) != 0)
- {
- support_record_failure ();
- printf ("%s:%d: error: string comparison failed\n", file, line);
- if (left_length == right_length && right != NULL && left != NULL)
- printf (" string length: %zu bytes\n", left_length);
- else
- {
- report_length ("left", left, left_length);
- report_length ("right", right, right_length);
- }
- report_string ("left", (const unsigned char *) left,
- left_length, left_expr);
- report_string ("right", (const unsigned char *) right,
- right_length, right_expr);
- }
-}
+#define CHAR char
+#define UCHAR unsigned char
+#define LPREFIX ""
+#define STRLEN strlen
+#define MEMCMP memcmp
+#define SUPPORT_QUOTE_BLOB support_quote_blob
+#define SUPPORT_TEST_COMPARE_STRING support_test_compare_string
+#define WIDE 0
+
+#include "support_test_compare_string_main.c"
diff --git a/support/support_test_compare_string_main.c b/support/support_test_compare_string_main.c
new file mode 100644
index 0000000000000000..0edc0ca97d79d71e
--- /dev/null
+++ b/support/support_test_compare_string_main.c
@@ -0,0 +1,94 @@
+/* Check two strings for equality.
+ Copyright (C) 2018-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 <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+static void
+report_length (const char *what, const CHAR *str, size_t length)
+{
+ if (str == NULL)
+ printf (" %s string: NULL\n", what);
+ else
+ printf (" %s string: %zu %s\n", what, length,
+ WIDE ? "wide characters" : "bytes");
+}
+
+static void
+report_string (const char *what, const UCHAR *blob,
+ size_t length, const char *expr)
+{
+ if (length > 0)
+ {
+ printf (" %s (evaluated from %s):\n", what, expr);
+ char *quoted = SUPPORT_QUOTE_BLOB (blob, length);
+ printf (" %s\"%s\"\n", LPREFIX, quoted);
+ free (quoted);
+
+ fputs (" ", stdout);
+ for (size_t i = 0; i < length; ++i)
+ printf (" %02X", (unsigned int) blob[i]);
+ putc ('\n', stdout);
+ }
+}
+
+static size_t
+string_length_or_zero (const CHAR *str)
+{
+ if (str == NULL)
+ return 0;
+ else
+ return STRLEN (str);
+}
+
+void
+SUPPORT_TEST_COMPARE_STRING (const CHAR *left, const CHAR *right,
+ const char *file, int line,
+ const char *left_expr, const char *right_expr)
+{
+ /* Two null pointers are accepted. */
+ if (left == NULL && right == NULL)
+ return;
+
+ size_t left_length = string_length_or_zero (left);
+ size_t right_length = string_length_or_zero (right);
+
+ if (left_length != right_length || left == NULL || right == NULL
+ || MEMCMP (left, right, left_length) != 0)
+ {
+ support_record_failure ();
+ printf ("%s:%d: error: string comparison failed\n", file, line);
+ if (left_length == right_length && right != NULL && left != NULL)
+ printf (" string length: %zu %s\n", left_length,
+ WIDE ? "wide characters" : "bytes");
+ else
+ {
+ report_length ("left", left, left_length);
+ report_length ("right", right, right_length);
+ }
+ report_string ("left", (const UCHAR *) left,
+ left_length, left_expr);
+ report_string ("right", (const UCHAR *) right,
+ right_length, right_expr);
+ }
+}
diff --git a/support/support_test_compare_string_wide.c b/support/support_test_compare_string_wide.c
new file mode 100644
index 0000000000000000..88b560b142a3c356
--- /dev/null
+++ b/support/support_test_compare_string_wide.c
@@ -0,0 +1,28 @@
+/* Check two wide strings for equality.
+ Copyright (C) 2018-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 CHAR wchar_t
+#define UCHAR wchar_t
+#define LPREFIX "L"
+#define STRLEN wcslen
+#define MEMCMP wmemcmp
+#define SUPPORT_QUOTE_BLOB support_quote_blob_wide
+#define SUPPORT_TEST_COMPARE_STRING support_test_compare_string_wide
+#define WIDE 1
+
+#include "support_test_compare_string_main.c"
diff --git a/support/tst-support_quote_blob_wide.c b/support/tst-support_quote_blob_wide.c
new file mode 100644
index 0000000000000000..ea71a1f7f873b23a
--- /dev/null
+++ b/support/tst-support_quote_blob_wide.c
@@ -0,0 +1,66 @@
+/* Test the support_quote_blob_wide function.
+ Copyright (C) 2018-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 <string.h>
+#include <stdlib.h>
+
+static int
+do_test (void)
+{
+ /* Check handling of the empty blob, both with and without trailing
+ NUL byte. */
+ char *p = support_quote_blob_wide (L"", 0);
+ TEST_COMPARE (strlen (p), 0);
+ free (p);
+ p = support_quote_blob_wide (L"X", 0);
+ TEST_COMPARE (strlen (p), 0);
+ free (p);
+
+ /* Check escaping of backslash-escaped characters, and lack of
+ escaping for other shell meta-characters. */
+ p = support_quote_blob_wide (L"$()*?`@[]{}~\'\"X", 14);
+ TEST_COMPARE (strcmp (p, "$()*?`@[]{}~\\'\\\""), 0);
+ free (p);
+
+ /* Check lack of escaping for letters and digits. */
+#define LETTERS_AND_DIGTS \
+ "abcdefghijklmnopqrstuvwxyz" \
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
+ "0123456789"
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+#define WLETTERS_AND_DIGTS CONCAT (L, LETTERS_AND_DIGTS)
+ p = support_quote_blob_wide (WLETTERS_AND_DIGTS "@", 2 * 26 + 10);
+ TEST_COMPARE (strcmp (p, LETTERS_AND_DIGTS), 0);
+ free (p);
+
+ /* Check escaping of control characters and other non-printable
+ characters. */
+ p = support_quote_blob_wide (L"\r\n\t\a\b\f\v\1\177\200\377"
+ "\x123\x76543210\xfedcba98\0@", 17);
+ TEST_COMPARE (strcmp (p, "\\r\\n\\t\\a\\b\\f\\v\\x{1}"
+ "\\x{7f}\\x{80}\\x{ff}\\x{123}\\x{76543210}"
+ "\\x{fedcba98}\\x{0}@\\x{0}"), 0);
+ free (p);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/support/tst-test_compare_string_wide.c b/support/tst-test_compare_string_wide.c
new file mode 100644
index 0000000000000000..548f7dcdc60b82d8
--- /dev/null
+++ b/support/tst-test_compare_string_wide.c
@@ -0,0 +1,107 @@
+/* Basic test for the TEST_COMPARE_STRING_WIDE macro.
+ Copyright (C) 2018-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 <string.h>
+#include <support/check.h>
+#include <support/capture_subprocess.h>
+
+static void
+subprocess (void *closure)
+{
+ /* These tests should fail. They were chosen to cover differences
+ in length (with the same contents), single-bit mismatches, and
+ mismatching null pointers. */
+ TEST_COMPARE_STRING_WIDE (L"", NULL); /* Line 29. */
+ TEST_COMPARE_STRING_WIDE (L"X", L""); /* Line 30. */
+ TEST_COMPARE_STRING_WIDE (NULL, L"X"); /* Line 31. */
+ TEST_COMPARE_STRING_WIDE (L"abcd", L"abcD"); /* Line 32. */
+ TEST_COMPARE_STRING_WIDE (L"abcd", NULL); /* Line 33. */
+ TEST_COMPARE_STRING_WIDE (NULL, L"abcd"); /* Line 34. */
+}
+
+/* Same contents, different addresses. */
+wchar_t buffer_abc_1[] = L"abc";
+wchar_t buffer_abc_2[] = L"abc";
+
+static int
+do_test (void)
+{
+ /* This should succeed. Even if the pointers and array contents are
+ different, zero-length inputs are not different. */
+ TEST_COMPARE_STRING_WIDE (NULL, NULL);
+ TEST_COMPARE_STRING_WIDE (L"", L"");
+ TEST_COMPARE_STRING_WIDE (buffer_abc_1, buffer_abc_2);
+ TEST_COMPARE_STRING_WIDE (buffer_abc_1, L"abc");
+
+ struct support_capture_subprocess proc = support_capture_subprocess
+ (&subprocess, NULL);
+
+ /* Discard the reported error. */
+ support_record_failure_reset ();
+
+ puts ("info: *** subprocess output starts ***");
+ fputs (proc.out.buffer, stdout);
+ puts ("info: *** subprocess output ends ***");
+
+ TEST_VERIFY
+ (strcmp (proc.out.buffer,
+"tst-test_compare_string_wide.c:29: error: string comparison failed\n"
+" left string: 0 wide characters\n"
+" right string: NULL\n"
+"tst-test_compare_string_wide.c:30: error: string comparison failed\n"
+" left string: 1 wide characters\n"
+" right string: 0 wide characters\n"
+" left (evaluated from L\"X\"):\n"
+" L\"X\"\n"
+" 58\n"
+"tst-test_compare_string_wide.c:31: error: string comparison failed\n"
+" left string: NULL\n"
+" right string: 1 wide characters\n"
+" right (evaluated from L\"X\"):\n"
+" L\"X\"\n"
+" 58\n"
+"tst-test_compare_string_wide.c:32: error: string comparison failed\n"
+" string length: 4 wide characters\n"
+" left (evaluated from L\"abcd\"):\n"
+" L\"abcd\"\n"
+" 61 62 63 64\n"
+" right (evaluated from L\"abcD\"):\n"
+" L\"abcD\"\n"
+" 61 62 63 44\n"
+"tst-test_compare_string_wide.c:33: error: string comparison failed\n"
+" left string: 4 wide characters\n"
+" right string: NULL\n"
+" left (evaluated from L\"abcd\"):\n"
+" L\"abcd\"\n"
+" 61 62 63 64\n"
+"tst-test_compare_string_wide.c:34: error: string comparison failed\n"
+" left string: NULL\n"
+" right string: 4 wide characters\n"
+" right (evaluated from L\"abcd\"):\n"
+" L\"abcd\"\n"
+" 61 62 63 64\n"
+ ) == 0);
+
+ /* Check that there is no output on standard error. */
+ support_capture_subprocess_check (&proc, "TEST_COMPARE_STRING_WIDE",
+ 0, sc_allow_stdout);
+
+ return 0;
+}
+
+#include <support/test-driver.c>

@ -0,0 +1,691 @@
commit 7e0ad15c0fbfe25435c1acd0ed3e9cedfbff2488
Author: Carlos O'Donell <carlos@redhat.com>
Date: Mon Jan 31 00:34:42 2022 -0500
localedata: Adjust C.UTF-8 to align with C/POSIX.
We have had one downstream report from Canonical [1] that
an rrdtool test was broken by the differences in LC_TIME
that we had in the non-builtin C locale (C.UTF-8). If one
application has an issue there are going to be others, and
so with this commit we review and fix all the issues that
cause the builtin C locale to be different from C.UTF-8,
which includes:
* mon_decimal_point should be empty e.g. ""
- Depends on mon_decimal_point_wc fix.
* negative_sign should be empty e.g. ""
* week should be aligned with the builtin C/POSIX locale
* d_fmt corrected with escaped slashes e.g. "%m//%d//%y"
* yesstr and nostr should be empty e.g. ""
* country_ab2 and country_ab3 should be empty e.g. ""
We bump LC_IDENTIFICATION version and adjust the date to
indicate the change in the locale.
A new tst-c-utf8-consistency test is added to ensure
consistency between C/POSIX and C.UTF-8.
Tested on x86_64 and i686 without regression.
[1] https://sourceware.org/pipermail/libc-alpha/2022-January/135703.html
Co-authored-by: Florian Weimer <fweimer@redhat.com>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
diff --git a/localedata/Makefile b/localedata/Makefile
index c9dd5a954e8194cc..5830b9d05141cccd 100644
--- a/localedata/Makefile
+++ b/localedata/Makefile
@@ -155,11 +155,31 @@ locale_test_suite := tst_iswalnum tst_iswalpha tst_iswcntrl \
tst_wcsxfrm tst_wctob tst_wctomb tst_wctrans \
tst_wctype tst_wcwidth
-tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
- tst-leaks tst-mbswcs1 tst-mbswcs2 tst-mbswcs3 tst-mbswcs4 tst-mbswcs5 \
- tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \
- tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2 tst-setlocale3 \
- tst-wctype tst-iconv-math-trans
+tests = \
+ $(locale_test_suite) \
+ bug-iconv-trans \
+ bug-setlocale1 \
+ bug-usesetlocale \
+ tst-c-utf8-consistency \
+ tst-digits \
+ tst-iconv-math-trans \
+ tst-leaks \
+ tst-mbswcs1 \
+ tst-mbswcs2 \
+ tst-mbswcs3 \
+ tst-mbswcs4 \
+ tst-mbswcs5 \
+ tst-mbswcs6 \
+ tst-setlocale \
+ tst-setlocale2 \
+ tst-setlocale3 \
+ tst-sscanf \
+ tst-strfmon1 \
+ tst-wctype \
+ tst-xlocale1 \
+ tst-xlocale2 \
+ # tests
+
tests-static = bug-setlocale1-static
tests += $(tests-static)
ifeq (yes,$(build-shared))
diff --git a/localedata/locales/C b/localedata/locales/C
index ca801c79cf7e953e..fc0614e551519c6b 100644
--- a/localedata/locales/C
+++ b/localedata/locales/C
@@ -12,8 +12,8 @@ tel ""
fax ""
language ""
territory ""
-revision "2.0"
-date "2020-06-28"
+revision "2.1"
+date "2022-01-30"
category "i18n:2012";LC_IDENTIFICATION
category "i18n:2012";LC_CTYPE
category "i18n:2012";LC_COLLATE
@@ -68,11 +68,11 @@ LC_MONETARY
% glibc/locale/C-monetary.c.).
int_curr_symbol ""
currency_symbol ""
-mon_decimal_point "."
+mon_decimal_point ""
mon_thousands_sep ""
mon_grouping -1
positive_sign ""
-negative_sign "-"
+negative_sign ""
int_frac_digits -1
frac_digits -1
p_cs_precedes -1
@@ -121,7 +121,9 @@ mon "January";"February";"March";"April";"May";"June";"July";/
%
% ISO 8601 conforming applications should use the values 7, 19971201 (a
% Monday), and 4 (Thursday), respectively.
-week 7;19971201;4
+%
+% This field is consciously aligned with the builtin C/POSIX locale.
+week 7;19971130;4
first_weekday 1
first_workday 2
@@ -129,7 +131,7 @@ first_workday 2
d_t_fmt "%a %b %e %H:%M:%S %Y"
% Appropriate date representation (%x)
-d_fmt "%m/%d/%y"
+d_fmt "%m//%d//%y"
% Appropriate time representation (%X)
t_fmt "%H:%M:%S"
@@ -150,8 +152,8 @@ LC_MESSAGES
%
yesexpr "^[yY]"
noexpr "^[nN]"
-yesstr "Yes"
-nostr "No"
+yesstr ""
+nostr ""
END LC_MESSAGES
LC_PAPER
@@ -175,6 +177,10 @@ LC_ADDRESS
% the LC_ADDRESS category.
% (also used in the built in C/POSIX locale in glibc/locale/C-address.c)
postal_fmt "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N"
+% The abbreviated 2 char and 3 char should be set to empty strings to
+% match the C/POSIX locale.
+country_ab2 ""
+country_ab3 ""
END LC_ADDRESS
LC_TELEPHONE
diff --git a/localedata/tst-c-utf8-consistency.c b/localedata/tst-c-utf8-consistency.c
new file mode 100644
index 0000000000000000..50feed3090df0ff1
--- /dev/null
+++ b/localedata/tst-c-utf8-consistency.c
@@ -0,0 +1,539 @@
+/* Test that C/POSIX and C.UTF-8 are consistent.
+ 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 <langinfo.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <support/check.h>
+
+/* Initialized by do_test using newlocale. */
+static locale_t c_utf8;
+
+/* Set to true for second pass. */
+static bool use_nl_langinfo_l;
+
+static void
+switch_to_c (void)
+{
+ if (setlocale (LC_ALL, "C") == NULL)
+ FAIL_EXIT1 ("setlocale (LC_ALL, \"C\")");
+}
+
+static void
+switch_to_c_utf8 (void)
+{
+ if (setlocale (LC_ALL, "C.UTF-8") == NULL)
+ FAIL_EXIT1 ("setlocale (LC_ALL, \"C.UTF-8\")");
+}
+
+static char *
+str (nl_item item)
+{
+ if (!use_nl_langinfo_l)
+ switch_to_c ();
+ return nl_langinfo (item);
+}
+
+static char *
+str_utf8 (nl_item item)
+{
+ if (use_nl_langinfo_l)
+ return nl_langinfo_l (item, c_utf8);
+ else
+ {
+ switch_to_c_utf8 ();
+ return nl_langinfo (item);
+ }
+}
+
+static wchar_t *
+wstr (nl_item item)
+{
+ return (wchar_t *) str (item);
+}
+
+static wchar_t *
+wstr_utf8 (nl_item item)
+{
+ return (wchar_t *) str_utf8 (item);
+}
+
+static int
+byte (nl_item item)
+{
+ return (signed char) *str (item);
+}
+
+static int
+byte_utf8 (nl_item item)
+{
+ return (signed char) *str_utf8 (item);
+}
+
+static int
+word (nl_item item)
+{
+ union
+ {
+ char *ptr;
+ int word;
+ } u;
+ u.ptr = str (item);
+ return u.word;
+}
+
+static int
+word_utf8 (nl_item item)
+{
+ union
+ {
+ char *ptr;
+ int word;
+ } u;
+ u.ptr = str_utf8 (item);
+ return u.word;
+}
+
+static void
+one_pass (void)
+{
+ /* LC_TIME. */
+ TEST_COMPARE_STRING (str (ABDAY_1), str_utf8 (ABDAY_1));
+ TEST_COMPARE_STRING (str (ABDAY_2), str_utf8 (ABDAY_2));
+ TEST_COMPARE_STRING (str (ABDAY_3), str_utf8 (ABDAY_3));
+ TEST_COMPARE_STRING (str (ABDAY_4), str_utf8 (ABDAY_4));
+ TEST_COMPARE_STRING (str (ABDAY_5), str_utf8 (ABDAY_5));
+ TEST_COMPARE_STRING (str (ABDAY_6), str_utf8 (ABDAY_6));
+ TEST_COMPARE_STRING (str (ABDAY_7), str_utf8 (ABDAY_7));
+
+ TEST_COMPARE_STRING (str (DAY_1), str_utf8 (DAY_1));
+ TEST_COMPARE_STRING (str (DAY_2), str_utf8 (DAY_2));
+ TEST_COMPARE_STRING (str (DAY_3), str_utf8 (DAY_3));
+ TEST_COMPARE_STRING (str (DAY_4), str_utf8 (DAY_4));
+ TEST_COMPARE_STRING (str (DAY_5), str_utf8 (DAY_5));
+ TEST_COMPARE_STRING (str (DAY_6), str_utf8 (DAY_6));
+ TEST_COMPARE_STRING (str (DAY_7), str_utf8 (DAY_7));
+
+ TEST_COMPARE_STRING (str (ABMON_1), str_utf8 (ABMON_1));
+ TEST_COMPARE_STRING (str (ABMON_2), str_utf8 (ABMON_2));
+ TEST_COMPARE_STRING (str (ABMON_3), str_utf8 (ABMON_3));
+ TEST_COMPARE_STRING (str (ABMON_4), str_utf8 (ABMON_4));
+ TEST_COMPARE_STRING (str (ABMON_5), str_utf8 (ABMON_5));
+ TEST_COMPARE_STRING (str (ABMON_6), str_utf8 (ABMON_6));
+ TEST_COMPARE_STRING (str (ABMON_7), str_utf8 (ABMON_7));
+ TEST_COMPARE_STRING (str (ABMON_8), str_utf8 (ABMON_8));
+ TEST_COMPARE_STRING (str (ABMON_9), str_utf8 (ABMON_9));
+ TEST_COMPARE_STRING (str (ABMON_10), str_utf8 (ABMON_10));
+ TEST_COMPARE_STRING (str (ABMON_11), str_utf8 (ABMON_11));
+ TEST_COMPARE_STRING (str (ABMON_12), str_utf8 (ABMON_12));
+
+ TEST_COMPARE_STRING (str (MON_1), str_utf8 (MON_1));
+ TEST_COMPARE_STRING (str (MON_2), str_utf8 (MON_2));
+ TEST_COMPARE_STRING (str (MON_3), str_utf8 (MON_3));
+ TEST_COMPARE_STRING (str (MON_4), str_utf8 (MON_4));
+ TEST_COMPARE_STRING (str (MON_5), str_utf8 (MON_5));
+ TEST_COMPARE_STRING (str (MON_6), str_utf8 (MON_6));
+ TEST_COMPARE_STRING (str (MON_7), str_utf8 (MON_7));
+ TEST_COMPARE_STRING (str (MON_8), str_utf8 (MON_8));
+ TEST_COMPARE_STRING (str (MON_9), str_utf8 (MON_9));
+ TEST_COMPARE_STRING (str (MON_10), str_utf8 (MON_10));
+ TEST_COMPARE_STRING (str (MON_11), str_utf8 (MON_11));
+ TEST_COMPARE_STRING (str (MON_12), str_utf8 (MON_12));
+
+ TEST_COMPARE_STRING (str (AM_STR), str_utf8 (AM_STR));
+ TEST_COMPARE_STRING (str (PM_STR), str_utf8 (PM_STR));
+
+ TEST_COMPARE_STRING (str (D_T_FMT), str_utf8 (D_T_FMT));
+ TEST_COMPARE_STRING (str (D_FMT), str_utf8 (D_FMT));
+ TEST_COMPARE_STRING (str (T_FMT), str_utf8 (T_FMT));
+ TEST_COMPARE_STRING (str (T_FMT_AMPM),
+ str_utf8 (T_FMT_AMPM));
+
+ TEST_COMPARE_STRING (str (ERA), str_utf8 (ERA));
+ TEST_COMPARE_STRING (str (ERA_YEAR), str_utf8 (ERA_YEAR));
+ TEST_COMPARE_STRING (str (ERA_D_FMT), str_utf8 (ERA_D_FMT));
+ TEST_COMPARE_STRING (str (ALT_DIGITS), str_utf8 (ALT_DIGITS));
+ TEST_COMPARE_STRING (str (ERA_D_T_FMT), str_utf8 (ERA_D_T_FMT));
+ TEST_COMPARE_STRING (str (ERA_T_FMT), str_utf8 (ERA_T_FMT));
+ TEST_COMPARE (word (_NL_TIME_ERA_NUM_ENTRIES),
+ word_utf8 (_NL_TIME_ERA_NUM_ENTRIES));
+ /* No array elements, so nothing to compare for _NL_TIME_ERA_ENTRIES. */
+ TEST_COMPARE (word (_NL_TIME_ERA_NUM_ENTRIES), 0);
+
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_1), wstr_utf8 (_NL_WABDAY_1));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_2), wstr_utf8 (_NL_WABDAY_2));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_3), wstr_utf8 (_NL_WABDAY_3));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_4), wstr_utf8 (_NL_WABDAY_4));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_5), wstr_utf8 (_NL_WABDAY_5));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_6), wstr_utf8 (_NL_WABDAY_6));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_7), wstr_utf8 (_NL_WABDAY_7));
+
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_1), wstr_utf8 (_NL_WDAY_1));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_2), wstr_utf8 (_NL_WDAY_2));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_3), wstr_utf8 (_NL_WDAY_3));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_4), wstr_utf8 (_NL_WDAY_4));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_5), wstr_utf8 (_NL_WDAY_5));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_6), wstr_utf8 (_NL_WDAY_6));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_7), wstr_utf8 (_NL_WDAY_7));
+
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_1), wstr_utf8 (_NL_WABMON_1));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_2), wstr_utf8 (_NL_WABMON_2));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_3), wstr_utf8 (_NL_WABMON_3));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_4), wstr_utf8 (_NL_WABMON_4));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_5), wstr_utf8 (_NL_WABMON_5));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_6), wstr_utf8 (_NL_WABMON_6));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_7), wstr_utf8 (_NL_WABMON_7));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_8), wstr_utf8 (_NL_WABMON_8));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_9), wstr_utf8 (_NL_WABMON_9));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_10), wstr_utf8 (_NL_WABMON_10));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_11), wstr_utf8 (_NL_WABMON_11));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_12), wstr_utf8 (_NL_WABMON_12));
+
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_1), wstr_utf8 (_NL_WMON_1));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_2), wstr_utf8 (_NL_WMON_2));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_3), wstr_utf8 (_NL_WMON_3));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_4), wstr_utf8 (_NL_WMON_4));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_5), wstr_utf8 (_NL_WMON_5));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_6), wstr_utf8 (_NL_WMON_6));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_7), wstr_utf8 (_NL_WMON_7));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_8), wstr_utf8 (_NL_WMON_8));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_9), wstr_utf8 (_NL_WMON_9));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_10), wstr_utf8 (_NL_WMON_10));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_11), wstr_utf8 (_NL_WMON_11));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_12), wstr_utf8 (_NL_WMON_12));
+
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WAM_STR), wstr_utf8 (_NL_WAM_STR));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WPM_STR), wstr_utf8 (_NL_WPM_STR));
+
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WD_T_FMT), wstr_utf8 (_NL_WD_T_FMT));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WD_FMT), wstr_utf8 (_NL_WD_FMT));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WT_FMT), wstr_utf8 (_NL_WT_FMT));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WT_FMT_AMPM),
+ wstr_utf8 (_NL_WT_FMT_AMPM));
+
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WERA_YEAR), wstr_utf8 (_NL_WERA_YEAR));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WERA_D_FMT), wstr_utf8 (_NL_WERA_D_FMT));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALT_DIGITS),
+ wstr_utf8 (_NL_WALT_DIGITS));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WERA_D_T_FMT),
+ wstr_utf8 (_NL_WERA_D_T_FMT));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WERA_T_FMT), wstr_utf8 (_NL_WERA_T_FMT));
+
+ /* This is somewhat inconsistent, but see locale/categories.def. */
+ TEST_COMPARE (byte (_NL_TIME_WEEK_NDAYS), byte_utf8 (_NL_TIME_WEEK_NDAYS));
+ TEST_COMPARE (word (_NL_TIME_WEEK_1STDAY),
+ word_utf8 (_NL_TIME_WEEK_1STDAY));
+ TEST_COMPARE (byte (_NL_TIME_WEEK_1STWEEK),
+ byte_utf8 (_NL_TIME_WEEK_1STWEEK));
+ TEST_COMPARE (byte (_NL_TIME_FIRST_WEEKDAY),
+ byte_utf8 (_NL_TIME_FIRST_WEEKDAY));
+ TEST_COMPARE (byte (_NL_TIME_FIRST_WORKDAY),
+ byte_utf8 (_NL_TIME_FIRST_WORKDAY));
+ TEST_COMPARE (byte (_NL_TIME_CAL_DIRECTION),
+ byte_utf8 (_NL_TIME_CAL_DIRECTION));
+ TEST_COMPARE_STRING (str (_NL_TIME_TIMEZONE), str_utf8 (_NL_TIME_TIMEZONE));
+
+ TEST_COMPARE_STRING (str (_DATE_FMT), str_utf8 (_DATE_FMT));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_W_DATE_FMT), wstr_utf8 (_NL_W_DATE_FMT));
+
+ /* Expected difference. */
+ TEST_COMPARE_STRING (str (_NL_TIME_CODESET), "ANSI_X3.4-1968");
+ TEST_COMPARE_STRING (str_utf8 (_NL_TIME_CODESET), "UTF-8");
+
+ TEST_COMPARE_STRING (str (ALTMON_1), str_utf8 (ALTMON_1));
+ TEST_COMPARE_STRING (str (ALTMON_2), str_utf8 (ALTMON_2));
+ TEST_COMPARE_STRING (str (ALTMON_3), str_utf8 (ALTMON_3));
+ TEST_COMPARE_STRING (str (ALTMON_4), str_utf8 (ALTMON_4));
+ TEST_COMPARE_STRING (str (ALTMON_5), str_utf8 (ALTMON_5));
+ TEST_COMPARE_STRING (str (ALTMON_6), str_utf8 (ALTMON_6));
+ TEST_COMPARE_STRING (str (ALTMON_7), str_utf8 (ALTMON_7));
+ TEST_COMPARE_STRING (str (ALTMON_8), str_utf8 (ALTMON_8));
+ TEST_COMPARE_STRING (str (ALTMON_9), str_utf8 (ALTMON_9));
+ TEST_COMPARE_STRING (str (ALTMON_10), str_utf8 (ALTMON_10));
+ TEST_COMPARE_STRING (str (ALTMON_11), str_utf8 (ALTMON_11));
+ TEST_COMPARE_STRING (str (ALTMON_12), str_utf8 (ALTMON_12));
+
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_1), wstr_utf8 (_NL_WALTMON_1));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_2), wstr_utf8 (_NL_WALTMON_2));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_3), wstr_utf8 (_NL_WALTMON_3));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_4), wstr_utf8 (_NL_WALTMON_4));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_5), wstr_utf8 (_NL_WALTMON_5));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_6), wstr_utf8 (_NL_WALTMON_6));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_7), wstr_utf8 (_NL_WALTMON_7));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_8), wstr_utf8 (_NL_WALTMON_8));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_9), wstr_utf8 (_NL_WALTMON_9));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_10), wstr_utf8 (_NL_WALTMON_10));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_11), wstr_utf8 (_NL_WALTMON_11));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_12), wstr_utf8 (_NL_WALTMON_12));
+
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_1), str_utf8 (_NL_ABALTMON_1));
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_2), str_utf8 (_NL_ABALTMON_2));
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_3), str_utf8 (_NL_ABALTMON_3));
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_4), str_utf8 (_NL_ABALTMON_4));
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_5), str_utf8 (_NL_ABALTMON_5));
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_6), str_utf8 (_NL_ABALTMON_6));
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_7), str_utf8 (_NL_ABALTMON_7));
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_8), str_utf8 (_NL_ABALTMON_8));
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_9), str_utf8 (_NL_ABALTMON_9));
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_10), str_utf8 (_NL_ABALTMON_10));
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_11), str_utf8 (_NL_ABALTMON_11));
+ TEST_COMPARE_STRING (str (_NL_ABALTMON_12), str_utf8 (_NL_ABALTMON_12));
+
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_1),
+ wstr_utf8 (_NL_WABALTMON_1));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_2),
+ wstr_utf8 (_NL_WABALTMON_2));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_3),
+ wstr_utf8 (_NL_WABALTMON_3));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_4),
+ wstr_utf8 (_NL_WABALTMON_4));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_5),
+ wstr_utf8 (_NL_WABALTMON_5));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_6),
+ wstr_utf8 (_NL_WABALTMON_6));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_7),
+ wstr_utf8 (_NL_WABALTMON_7));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_8),
+ wstr_utf8 (_NL_WABALTMON_8));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_9),
+ wstr_utf8 (_NL_WABALTMON_9));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_10),
+ wstr_utf8 (_NL_WABALTMON_10));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_11),
+ wstr_utf8 (_NL_WABALTMON_11));
+ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_12),
+ wstr_utf8 (_NL_WABALTMON_12));
+
+ /* LC_COLLATE. Mostly untested, only expected differences. */
+ TEST_COMPARE_STRING (str (_NL_COLLATE_CODESET), "ANSI_X3.4-1968");
+ TEST_COMPARE_STRING (str_utf8 (_NL_COLLATE_CODESET), "UTF-8");
+
+ /* LC_CTYPE. Mostly untested, only expected differences. */
+ TEST_COMPARE_STRING (str (CODESET), "ANSI_X3.4-1968");
+ TEST_COMPARE_STRING (str_utf8 (CODESET), "UTF-8");
+
+ /* LC_MONETARY. */
+ TEST_COMPARE_STRING (str (INT_CURR_SYMBOL), str_utf8 (INT_CURR_SYMBOL));
+ TEST_COMPARE_STRING (str (CURRENCY_SYMBOL), str_utf8 (CURRENCY_SYMBOL));
+ TEST_COMPARE_STRING (str (MON_DECIMAL_POINT), str_utf8 (MON_DECIMAL_POINT));
+ TEST_COMPARE_STRING (str (MON_THOUSANDS_SEP), str_utf8 (MON_THOUSANDS_SEP));
+ TEST_COMPARE_STRING (str (MON_GROUPING), str_utf8 (MON_GROUPING));
+ TEST_COMPARE_STRING (str (POSITIVE_SIGN), str_utf8 (POSITIVE_SIGN));
+ TEST_COMPARE_STRING (str (NEGATIVE_SIGN), str_utf8 (NEGATIVE_SIGN));
+ TEST_COMPARE (byte (INT_FRAC_DIGITS), byte_utf8 (INT_FRAC_DIGITS));
+ TEST_COMPARE (byte (FRAC_DIGITS), byte_utf8 (FRAC_DIGITS));
+ TEST_COMPARE (byte (P_CS_PRECEDES), byte_utf8 (P_CS_PRECEDES));
+ TEST_COMPARE (byte (P_SEP_BY_SPACE), byte_utf8 (P_SEP_BY_SPACE));
+ TEST_COMPARE (byte (N_CS_PRECEDES), byte_utf8 (N_CS_PRECEDES));
+ TEST_COMPARE (byte (N_SEP_BY_SPACE), byte_utf8 (N_SEP_BY_SPACE));
+ TEST_COMPARE (byte (P_SIGN_POSN), byte_utf8 (P_SIGN_POSN));
+ TEST_COMPARE (byte (N_SIGN_POSN), byte_utf8 (N_SIGN_POSN));
+ TEST_COMPARE_STRING (str (CRNCYSTR), str_utf8 (CRNCYSTR));
+ TEST_COMPARE (byte (INT_P_CS_PRECEDES), byte_utf8 (INT_P_CS_PRECEDES));
+ TEST_COMPARE (byte (INT_P_SEP_BY_SPACE), byte_utf8 (INT_P_SEP_BY_SPACE));
+ TEST_COMPARE (byte (INT_N_CS_PRECEDES), byte_utf8 (INT_N_CS_PRECEDES));
+ TEST_COMPARE (byte (INT_N_SEP_BY_SPACE), byte_utf8 (INT_N_SEP_BY_SPACE));
+ TEST_COMPARE (byte (INT_P_SIGN_POSN), byte_utf8 (INT_P_SIGN_POSN));
+ TEST_COMPARE (byte (INT_N_SIGN_POSN), byte_utf8 (INT_N_SIGN_POSN));
+ TEST_COMPARE_STRING (str (_NL_MONETARY_DUO_INT_CURR_SYMBOL),
+ str_utf8 (_NL_MONETARY_DUO_INT_CURR_SYMBOL));
+ TEST_COMPARE_STRING (str (_NL_MONETARY_DUO_CURRENCY_SYMBOL),
+ str_utf8 (_NL_MONETARY_DUO_CURRENCY_SYMBOL));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_FRAC_DIGITS),
+ byte_utf8 (_NL_MONETARY_DUO_INT_FRAC_DIGITS));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_FRAC_DIGITS),
+ byte_utf8 (_NL_MONETARY_DUO_FRAC_DIGITS));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_P_CS_PRECEDES),
+ byte_utf8 (_NL_MONETARY_DUO_P_CS_PRECEDES));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_P_SEP_BY_SPACE),
+ byte_utf8 (_NL_MONETARY_DUO_P_SEP_BY_SPACE));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_N_CS_PRECEDES),
+ byte_utf8 (_NL_MONETARY_DUO_N_CS_PRECEDES));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_N_SEP_BY_SPACE),
+ byte_utf8 (_NL_MONETARY_DUO_N_SEP_BY_SPACE));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_P_CS_PRECEDES),
+ byte_utf8 (_NL_MONETARY_DUO_INT_P_CS_PRECEDES));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_P_SEP_BY_SPACE),
+ byte_utf8 (_NL_MONETARY_DUO_INT_P_SEP_BY_SPACE));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_N_CS_PRECEDES),
+ byte_utf8 (_NL_MONETARY_DUO_INT_N_CS_PRECEDES));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_N_SEP_BY_SPACE),
+ byte_utf8 (_NL_MONETARY_DUO_INT_N_SEP_BY_SPACE));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_P_SIGN_POSN),
+ byte_utf8 (_NL_MONETARY_DUO_INT_P_SIGN_POSN));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_N_SIGN_POSN),
+ byte_utf8 (_NL_MONETARY_DUO_INT_N_SIGN_POSN));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_P_SIGN_POSN),
+ byte_utf8 (_NL_MONETARY_DUO_P_SIGN_POSN));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_N_SIGN_POSN),
+ byte_utf8 (_NL_MONETARY_DUO_N_SIGN_POSN));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_P_SIGN_POSN),
+ byte_utf8 (_NL_MONETARY_DUO_INT_P_SIGN_POSN));
+ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_N_SIGN_POSN),
+ byte_utf8 (_NL_MONETARY_DUO_INT_N_SIGN_POSN));
+ TEST_COMPARE (word (_NL_MONETARY_UNO_VALID_FROM),
+ word_utf8 (_NL_MONETARY_UNO_VALID_FROM));
+ TEST_COMPARE (word (_NL_MONETARY_UNO_VALID_TO),
+ word_utf8 (_NL_MONETARY_UNO_VALID_TO));
+ TEST_COMPARE (word (_NL_MONETARY_DUO_VALID_FROM),
+ word_utf8 (_NL_MONETARY_DUO_VALID_FROM));
+ TEST_COMPARE (word (_NL_MONETARY_DUO_VALID_TO),
+ word_utf8 (_NL_MONETARY_DUO_VALID_TO));
+ /* _NL_MONETARY_CONVERSION_RATE cannot be tested (word array). */
+ TEST_COMPARE (word (_NL_MONETARY_DECIMAL_POINT_WC),
+ word_utf8 (_NL_MONETARY_DECIMAL_POINT_WC));
+ TEST_COMPARE (word (_NL_MONETARY_THOUSANDS_SEP_WC),
+ word_utf8 (_NL_MONETARY_THOUSANDS_SEP_WC));
+ /* Expected difference. */
+ TEST_COMPARE_STRING (str (_NL_MONETARY_CODESET), "ANSI_X3.4-1968");
+ TEST_COMPARE_STRING (str_utf8 (_NL_MONETARY_CODESET), "UTF-8");
+
+ /* LC_NUMERIC. */
+
+ TEST_COMPARE_STRING (str (DECIMAL_POINT), str_utf8 (DECIMAL_POINT));
+ TEST_COMPARE_STRING (str (RADIXCHAR), str_utf8 (RADIXCHAR));
+ TEST_COMPARE_STRING (str (THOUSANDS_SEP), str_utf8 (THOUSANDS_SEP));
+ TEST_COMPARE_STRING (str (THOUSEP), str_utf8 (THOUSEP));
+ TEST_COMPARE_STRING (str (GROUPING), str_utf8 (GROUPING));
+ TEST_COMPARE (word (_NL_NUMERIC_DECIMAL_POINT_WC),
+ word_utf8 (_NL_NUMERIC_DECIMAL_POINT_WC));
+ TEST_COMPARE (word (_NL_NUMERIC_THOUSANDS_SEP_WC),
+ word_utf8 (_NL_NUMERIC_THOUSANDS_SEP_WC));
+ /* Expected difference. */
+ TEST_COMPARE_STRING (str (_NL_NUMERIC_CODESET), "ANSI_X3.4-1968");
+ TEST_COMPARE_STRING (str_utf8 (_NL_NUMERIC_CODESET), "UTF-8");
+
+ /* LC_MESSAGES. */
+
+ TEST_COMPARE_STRING (str (YESEXPR), str_utf8 (YESEXPR));
+ TEST_COMPARE_STRING (str (NOEXPR), str_utf8 (NOEXPR));
+ TEST_COMPARE_STRING (str (YESSTR), str_utf8 (YESSTR));
+ TEST_COMPARE_STRING (str (NOSTR), str_utf8 (NOSTR));
+ /* Expected difference. */
+ TEST_COMPARE_STRING (str (_NL_MESSAGES_CODESET), "ANSI_X3.4-1968");
+ TEST_COMPARE_STRING (str_utf8 (_NL_MESSAGES_CODESET), "UTF-8");
+
+ /* LC_PAPER. */
+
+ TEST_COMPARE (word (_NL_PAPER_HEIGHT), word_utf8 (_NL_PAPER_HEIGHT));
+ TEST_COMPARE (word (_NL_PAPER_WIDTH), word_utf8 (_NL_PAPER_WIDTH));
+ /* Expected difference. */
+ TEST_COMPARE_STRING (str (_NL_PAPER_CODESET), "ANSI_X3.4-1968");
+ TEST_COMPARE_STRING (str_utf8 (_NL_PAPER_CODESET), "UTF-8");
+
+ /* LC_NAME. */
+
+ TEST_COMPARE_STRING (str (_NL_NAME_NAME_FMT),
+ str_utf8 (_NL_NAME_NAME_FMT));
+ TEST_COMPARE_STRING (str (_NL_NAME_NAME_GEN),
+ str_utf8 (_NL_NAME_NAME_GEN));
+ TEST_COMPARE_STRING (str (_NL_NAME_NAME_MR),
+ str_utf8 (_NL_NAME_NAME_MR));
+ TEST_COMPARE_STRING (str (_NL_NAME_NAME_MRS),
+ str_utf8 (_NL_NAME_NAME_MRS));
+ TEST_COMPARE_STRING (str (_NL_NAME_NAME_MISS),
+ str_utf8 (_NL_NAME_NAME_MISS));
+ TEST_COMPARE_STRING (str (_NL_NAME_NAME_MS),
+ str_utf8 (_NL_NAME_NAME_MS));
+ /* Expected difference. */
+ TEST_COMPARE_STRING (str (_NL_NAME_CODESET), "ANSI_X3.4-1968");
+ TEST_COMPARE_STRING (str_utf8 (_NL_NAME_CODESET), "UTF-8");
+
+ /* LC_ADDRESS. */
+
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_POSTAL_FMT),
+ str_utf8 (_NL_ADDRESS_POSTAL_FMT));
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_NAME),
+ str_utf8 (_NL_ADDRESS_COUNTRY_NAME));
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_POST),
+ str_utf8 (_NL_ADDRESS_COUNTRY_POST));
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_AB2),
+ str_utf8 (_NL_ADDRESS_COUNTRY_AB2));
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_AB3),
+ str_utf8 (_NL_ADDRESS_COUNTRY_AB3));
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_CAR),
+ str_utf8 (_NL_ADDRESS_COUNTRY_CAR));
+ TEST_COMPARE (word (_NL_ADDRESS_COUNTRY_NUM),
+ word_utf8 (_NL_ADDRESS_COUNTRY_NUM));
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_ISBN),
+ str_utf8 (_NL_ADDRESS_COUNTRY_ISBN));
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_LANG_NAME),
+ str_utf8 (_NL_ADDRESS_LANG_NAME));
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_LANG_AB),
+ str_utf8 (_NL_ADDRESS_LANG_AB));
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_LANG_TERM),
+ str_utf8 (_NL_ADDRESS_LANG_TERM));
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_LANG_LIB),
+ str_utf8 (_NL_ADDRESS_LANG_LIB));
+ /* Expected difference. */
+ TEST_COMPARE_STRING (str (_NL_ADDRESS_CODESET), "ANSI_X3.4-1968");
+ TEST_COMPARE_STRING (str_utf8 (_NL_ADDRESS_CODESET), "UTF-8");
+
+ /* LC_TELEPHONE. */
+
+ TEST_COMPARE_STRING (str (_NL_TELEPHONE_TEL_INT_FMT),
+ str_utf8 (_NL_TELEPHONE_TEL_INT_FMT));
+ TEST_COMPARE_STRING (str (_NL_TELEPHONE_TEL_DOM_FMT),
+ str_utf8 (_NL_TELEPHONE_TEL_DOM_FMT));
+ TEST_COMPARE_STRING (str (_NL_TELEPHONE_INT_SELECT),
+ str_utf8 (_NL_TELEPHONE_INT_SELECT));
+ TEST_COMPARE_STRING (str (_NL_TELEPHONE_INT_PREFIX),
+ str_utf8 (_NL_TELEPHONE_INT_PREFIX));
+ /* Expected difference. */
+ TEST_COMPARE_STRING (str (_NL_TELEPHONE_CODESET), "ANSI_X3.4-1968");
+ TEST_COMPARE_STRING (str_utf8 (_NL_TELEPHONE_CODESET), "UTF-8");
+
+ /* LC_MEASUREMENT. */
+
+ TEST_COMPARE (byte (_NL_MEASUREMENT_MEASUREMENT),
+ byte_utf8 (_NL_MEASUREMENT_MEASUREMENT));
+ /* Expected difference. */
+ TEST_COMPARE_STRING (str (_NL_MEASUREMENT_CODESET), "ANSI_X3.4-1968");
+ TEST_COMPARE_STRING (str_utf8 (_NL_MEASUREMENT_CODESET), "UTF-8");
+
+ /* LC_IDENTIFICATION is skipped since C.UTF-8 is distinct from C. */
+
+ /* _NL_IDENTIFICATION_CATEGORY cannot be tested because it is a
+ string array. */
+ /* Expected difference. */
+ TEST_COMPARE_STRING (str (_NL_IDENTIFICATION_CODESET), "ANSI_X3.4-1968");
+ TEST_COMPARE_STRING (str_utf8 (_NL_IDENTIFICATION_CODESET), "UTF-8");
+}
+
+static int
+do_test (void)
+{
+ puts ("info: using setlocale and nl_langinfo");
+ one_pass ();
+
+ puts ("info: using nl_langinfo_l");
+
+ c_utf8 = newlocale (LC_ALL_MASK, "C.UTF-8", (locale_t) 0);
+ TEST_VERIFY_EXIT (c_utf8 != (locale_t) 0);
+
+ switch_to_c ();
+ use_nl_langinfo_l = true;
+ one_pass ();
+
+ freelocale (c_utf8);
+
+ return 0;
+}
+
+#include <support/test-driver.c>

@ -0,0 +1,44 @@
Short description: Adjust CS_PATH and the test container layout.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-needed
In Fedora we should return only /usr/bin as CS_PATH because /bin is just
a symlink to /usr/bin after MoveToUsr transition (which glibc has not
really completed).
We also create /{bin,lib,lib64,sbin} in the test container as symbolic
links. This brings the test container in line with Fedora's filesystem
layout and avoids some test failures. For example, because Fedora's
CS_PATH is /usr/bin, tst-vfork3 will try to execute /usr/bin/echo in the
container. Without this change the container installs `echo' in /bin
not /usr/bin, causing the test to fail.
diff --git a/Makefile b/Makefile
index a49870d3d1e636a9..feb2599203b10098 100644
--- a/Makefile
+++ b/Makefile
@@ -598,9 +598,13 @@ $(tests-container) $(addsuffix /tests,$(subdirs)) : \
$(objpfx)testroot.pristine/install.stamp :
test -d $(objpfx)testroot.pristine || \
mkdir $(objpfx)testroot.pristine
- # We need a working /bin/sh for some of the tests.
- test -d $(objpfx)testroot.pristine/bin || \
- mkdir $(objpfx)testroot.pristine/bin
+ # Set up symlinks to directories whose contents got moved to /usr
+ for moved in bin lib lib64 sbin; do \
+ test -d $(objpfx)testroot.pristine/usr/$$moved || \
+ mkdir -p $(objpfx)testroot.pristine/usr/$$moved ;\
+ test -e $(objpfx)testroot.pristine/$$moved || \
+ ln -s usr/$$moved $(objpfx)testroot.pristine/$$moved ;\
+ done
# We need the compiled locale dir for localedef tests.
test -d $(objpfx)testroot.pristine/$(complocaledir) || \
mkdir -p $(objpfx)testroot.pristine/$(complocaledir)
diff --git a/sysdeps/unix/confstr.h b/sysdeps/unix/confstr.h
index 15859c3b2759878e..9b63b7f8069866fd 100644
--- a/sysdeps/unix/confstr.h
+++ b/sysdeps/unix/confstr.h
@@ -1 +1 @@
-#define CS_PATH "/bin:/usr/bin"
+#define CS_PATH "/usr/bin"

@ -0,0 +1,20 @@
This is necessary to get things building again after libselinux changes.
A proper fix is under discussion upstream:
<https://sourceware.org/pipermail/libc-alpha/2020-July/116504.html>
diff --git a/nss/makedb.c b/nss/makedb.c
index 8e389a1683747cf1..9d81aed57d384a22 100644
--- a/nss/makedb.c
+++ b/nss/makedb.c
@@ -17,6 +17,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+/* This file uses deprecated declarations from libselinux. */
+#include <libc-diag.h>
+DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wdeprecated-declarations");
+
#include <argp.h>
#include <assert.h>
#include <ctype.h>

@ -0,0 +1,17 @@
This patch works around deprecated libselinux features used by nscd.
diff --git a/nscd/selinux.c b/nscd/selinux.c
index a4ea8008e201b939..0acca4639202a75a 100644
--- a/nscd/selinux.c
+++ b/nscd/selinux.c
@@ -17,6 +17,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+/* This file uses deprecated declarations from libselinux. */
+#include <libc-diag.h>
+DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wdeprecated-declarations");
+
#include "config.h"
#include <error.h>
#include <errno.h>

@ -0,0 +1,61 @@
Short description: Fedora-specific workaround for kernel pty bug.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-submitted
This is a Fedora-specific workaround for a kernel bug where calling
ioctl on a pty will silently ignore the invalid c_cflag. The
workaround is to use TCGETS to verify the setting matches. This is
not upstream and needs to either be removed or submitted upstream
after analysis.
Index: b/sysdeps/unix/sysv/linux/tcsetattr.c
===================================================================
--- a/sysdeps/unix/sysv/linux/tcsetattr.c
+++ b/sysdeps/unix/sysv/linux/tcsetattr.c
@@ -45,6 +45,7 @@ __tcsetattr (int fd, int optional_action
{
struct __kernel_termios k_termios;
unsigned long int cmd;
+ int retval;
switch (optional_actions)
{
@@ -75,7 +76,36 @@ __tcsetattr (int fd, int optional_action
memcpy (&k_termios.c_cc[0], &termios_p->c_cc[0],
__KERNEL_NCCS * sizeof (cc_t));
- return INLINE_SYSCALL (ioctl, 3, fd, cmd, &k_termios);
+ retval = INLINE_SYSCALL (ioctl, 3, fd, cmd, &k_termios);
+
+ if (retval == 0 && cmd == TCSETS)
+ {
+ /* The Linux kernel has a bug which silently ignore the invalid
+ c_cflag on pty. We have to check it here. */
+ int save = errno;
+ retval = INLINE_SYSCALL (ioctl, 3, fd, TCGETS, &k_termios);
+ if (retval)
+ {
+ /* We cannot verify if the setting is ok. We don't return
+ an error (?). */
+ __set_errno (save);
+ retval = 0;
+ }
+ else if ((termios_p->c_cflag & (PARENB | CREAD))
+ != (k_termios.c_cflag & (PARENB | CREAD))
+ || ((termios_p->c_cflag & CSIZE)
+ && ((termios_p->c_cflag & CSIZE)
+ != (k_termios.c_cflag & CSIZE))))
+ {
+ /* It looks like the Linux kernel silently changed the
+ PARENB/CREAD/CSIZE bits in c_cflag. Report it as an
+ error. */
+ __set_errno (EINVAL);
+ retval = -1;
+ }
+ }
+
+ return retval;
}
weak_alias (__tcsetattr, tcsetattr)
libc_hidden_def (tcsetattr)

@ -0,0 +1,49 @@
Short description: Add 4 ISO-8859-15 locales to SUPPORTED for Euro symbol.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Bug-RHEL: #61908
Upstream status: not-needed
Very early RHL 7.3 requirement to add these locales so users can
get access to Euro symbol. We should review this bug and decide if
the UTF-8 locales are now serving the same purpose and drop the
additional locales.
* Tue Mar 26 2002 Jakub Jelinek <jakub@redhat.com> 2.2.5-28
- add a couple of .ISO-8859-15 locales (#61908)
diff -Nrup a/localedata/SUPPORTED b/localedata/SUPPORTED
--- a/localedata/SUPPORTED 2012-11-25 12:59:31.000000000 -0700
+++ b/localedata/SUPPORTED 2012-11-26 12:58:43.298223018 -0700
@@ -89,6 +89,7 @@ cy_GB.UTF-8/UTF-8 \
cy_GB/ISO-8859-14 \
da_DK.UTF-8/UTF-8 \
da_DK/ISO-8859-1 \
+da_DK.ISO-8859-15/ISO-8859-15 \
de_AT.UTF-8/UTF-8 \
de_AT/ISO-8859-1 \
de_AT@euro/ISO-8859-15 \
@@ -121,6 +122,7 @@ en_DK.UTF-8/UTF-8 \
en_DK/ISO-8859-1 \
en_GB.UTF-8/UTF-8 \
en_GB/ISO-8859-1 \
+en_GB.ISO-8859-15/ISO-8859-15 \
en_HK.UTF-8/UTF-8 \
en_HK/ISO-8859-1 \
en_IE.UTF-8/UTF-8 \
@@ -136,6 +138,7 @@ en_SG.UTF-8/UTF-8 \
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_ZA.UTF-8/UTF-8 \
en_ZA/ISO-8859-1 \
en_ZM/UTF-8 \
@@ -385,6 +388,7 @@ sv_FI/ISO-8859-1 \
sv_FI@euro/ISO-8859-15 \
sv_SE.UTF-8/UTF-8 \
sv_SE/ISO-8859-1 \
+sv_SE.ISO-8859-15/ISO-8859-15 \
sw_KE/UTF-8 \
sw_TZ/UTF-8 \
szl_PL/UTF-8 \

@ -0,0 +1,31 @@
Short description: Place glibc info into "Libraries" category.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-needed
The category names for libraries is completely random including
"Libraries", "GNU Libraries", "GNU libraries", and "Software libraries."
In the GNU info manual the "Software libraries" category is given as an
example, but really we need to standardize on a category for upstream.
I suggest we drop this change after some upstream discussion.
From 4820b9175535e13df79ce816106016040014916e Mon Sep 17 00:00:00 2001
From: Jakub Jelinek <jakub@redhat.com>
Date: Fri, 3 Nov 2006 16:31:21 +0000
Subject: [PATCH] Change @dircategory.
---
manual/libc.texinfo | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
--- a/manual/libc.texinfo
+++ b/manual/libc.texinfo
@@ -7,7 +7,7 @@
@include macros.texi
@comment Tell install-info what to do.
-@dircategory Software libraries
+@dircategory Libraries
@direntry
* Libc: (libc). C library.
@end direntry

@ -0,0 +1,20 @@
Short description: NSCD must use nscd user.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-needed
Fedora-specific configuration adjustment to introduce the nscd user.
(Upstream does not assume this user exists.)
diff -Nrup a/nscd/nscd.conf b/nscd/nscd.conf
--- a/nscd/nscd.conf 2012-06-05 07:42:49.000000000 -0600
+++ b/nscd/nscd.conf 2012-06-07 12:15:21.818318670 -0600
@@ -33,7 +33,7 @@
# logfile /var/log/nscd.log
# threads 4
# max-threads 32
-# server-user nobody
+ server-user nscd
# stat-user somebody
debug-level 0
# reload-count 5

@ -0,0 +1,46 @@
The Fedora /etc/nsswitch.conf is based largely on the upstream
version with minor downstream distribution modifications for
use with SSSD and systemd.
diff --git a/nss/nsswitch.conf b/nss/nsswitch.conf
index 4a6bcb1f7bc0b1f4..980a68e32e6a04b8 100644
--- a/nss/nsswitch.conf
+++ b/nss/nsswitch.conf
@@ -1,7 +1,7 @@
#
# /etc/nsswitch.conf
#
-# An example Name Service Switch config file. This file should be
+# Name Service Switch config file. This file should be
# sorted with the most-used services at the beginning.
#
# Valid databases are: aliases, ethers, group, gshadow, hosts,
@@ -52,19 +52,21 @@
# shadow: db files
# group: db files
-# In alphabetical order. Re-order as required to optimize peformance.
+# In order of likelihood of use to accelerate lookup.
+passwd: sss files
+shadow: files
+group: sss files
+hosts: files dns myhostname
+services: files sss
+netgroup: sss
+automount: files sss
+
aliases: files
ethers: files
-group: files
gshadow: files
-hosts: files dns
# Allow initgroups to default to the setting for group.
# initgroups: files
-netgroup: files
networks: files dns
-passwd: files
protocols: files
publickey: files
rpc: files
-shadow: files
-services: files

@ -0,0 +1,21 @@
Short description: Provide options to nscd startup.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-needed
Fedora-specific nscd startup configuration file.
diff --git a/nscd/nscd.service b/nscd/nscd.service
index b7428a3..19ba185 100644
--- a/nscd/nscd.service
+++ b/nscd/nscd.service
@@ -5,7 +5,8 @@ Description=Name Service Cache Daemon
[Service]
Type=forking
-ExecStart=/usr/sbin/nscd
+EnvironmentFile=-/etc/sysconfig/nscd
+ExecStart=/usr/sbin/nscd $NSCD_OPTIONS
ExecStop=/usr/sbin/nscd --shutdown
ExecReload=/usr/sbin/nscd -i passwd
ExecReload=/usr/sbin/nscd -i group

@ -0,0 +1,30 @@
Use python3 for installed executable python scripts.
Fedora is a Python3-only distribution:
https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3
This fixes build failures where builders may strictly enforce only
python3 during a transitional phase.
Author: Carlos O'Donell <carlos@redhat.com>
diff --git a/benchtests/scripts/compare_bench.py b/benchtests/scripts/compare_bench.py
index 6fcbd0803808e5ca..d43db393d63433bc 100755
--- a/benchtests/scripts/compare_bench.py
+++ b/benchtests/scripts/compare_bench.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
# Copyright (C) 2015-2021 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
#
diff --git a/benchtests/scripts/import_bench.py b/benchtests/scripts/import_bench.py
index a799b4e1b7dc6f30..3286e267168e83bf 100644
--- a/benchtests/scripts/import_bench.py
+++ b/benchtests/scripts/import_bench.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
# Copyright (C) 2015-2021 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
#

@ -0,0 +1,38 @@
Short description: Add syslog.target dependency.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Bug-Fedora: #1070416
Upstream status: not-needed
Fedora-specific changes to the nscd.service file.
See also: glibc-nscd-sysconfig.patch.
--- a/nscd/nscd.service
+++ b/nscd/nscd.service
@@ -2,6 +2,7 @@
[Unit]
Description=Name Service Cache Daemon
+After=syslog.target
[Service]
Type=forking
@@ -17,3 +18,4 @@
[Install]
WantedBy=multi-user.target
+Also=nscd.socket
diff --git a/nscd/nscd.socket b/nscd/nscd.socket
new file mode 100644
index 0000000..7e512d5
--- /dev/null
+++ b/nscd/nscd.socket
@@ -0,0 +1,8 @@
+[Unit]
+Description=Name Service Cache Daemon Socket
+
+[Socket]
+ListenDatagram=/var/run/nscd/socket
+
+[Install]
+WantedBy=sockets.target

@ -0,0 +1,619 @@
commit 23645707f12f2dd9d80b51effb2d9618a7b65565
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date: Wed Dec 8 11:21:26 2021 +0530
Replace --enable-static-pie with --disable-default-pie
Build glibc programs and tests as PIE by default and enable static-pie
automatically if the architecture and toolchain supports it.
Also add a new configuration option --disable-default-pie to prevent
building programs as PIE.
Only the following architectures now have PIE disabled by default
because they do not work at the moment. hppa, ia64, alpha and csky
don't work because the linker is unable to handle a pcrel relocation
generated from PIE objects. The microblaze compiler is currently
failing with an ICE. GNU hurd tries to enable static-pie, which does
not work and hence fails. All these targets have default PIE disabled
at the moment and I have left it to the target maintainers to enable PIE
on their targets.
build-many-glibcs runs clean for all targets. I also tested x86_64 on
Fedora and Ubuntu, to verify that the default build as well as
--disable-default-pie work as expected with both system toolchains.
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/INSTALL b/INSTALL
index 02dcf6b1ca3a4c43..d6d93ec9be4262d7 100644
--- a/INSTALL
+++ b/INSTALL
@@ -111,16 +111,14 @@ if 'CFLAGS' is specified it must enable optimization. For example:
systems support shared libraries; you need ELF support and
(currently) the GNU linker.
-'--enable-static-pie'
- Enable static position independent executable (static PIE) support.
- Static PIE is similar to static executable, but can be loaded at
- any address without help from a dynamic linker. All static
- programs as well as static tests are built as static PIE, except
- for those marked with no-pie. The resulting glibc can be used with
- the GCC option, -static-pie, which is available with GCC 8 or
- above, to create static PIE. This option also implies that glibc
- programs and tests are created as dynamic position independent
- executables (PIE) by default.
+'--disable-default-pie'
+ Don't build glibc programs and the testsuite as position
+ independent executables (PIE). By default, glibc programs and tests
+ are created as position independent executables on targets that
+ support it. If the toolchain and architecture support it, static
+ executables are built as static PIE and the resulting glibc can be
+ used with the GCC option, -static-pie, which is available with GCC
+ 8 or above, to create static PIE.
'--enable-cet'
'--enable-cet=permissive'
diff --git a/Makeconfig b/Makeconfig
index 2fa0884b4eee5e53..8bc5540292c7b6fa 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -1,4 +1,5 @@
# Copyright (C) 1991-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
@@ -376,19 +377,24 @@ LDFLAGS.so += $(hashstyle-LDFLAGS)
LDFLAGS-rtld += $(hashstyle-LDFLAGS)
endif
-ifeq (yes,$(enable-static-pie))
+ifeq (no,$(build-pie-default))
+pie-default = $(no-pie-ccflag)
+else # build-pie-default
pic-default = -DPIC
# Compile libc.a and libc_p.a with -fPIE/-fpie for static PIE.
pie-default = $(pie-ccflag)
+
+ifeq (yes,$(enable-static-pie))
ifeq (yes,$(have-static-pie))
-default-pie-ldflag = -static-pie
+static-pie-ldflag = -static-pie
else
# Static PIE can't have dynamic relocations in read-only segments since
# static PIE is mapped into memory by kernel. --eh-frame-hdr is needed
# for PIE to support exception.
-default-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text
-endif
-endif
+static-pie-ldflag = -Wl,-pie,--no-dynamic-linker,--eh-frame-hdr,-z,text
+endif # have-static-pie
+endif # enable-static-pie
+endif # build-pie-default
# If lazy relocations are disabled, add the -z now flag. Use
# LDFLAGS-lib.so instead of LDFLAGS.so, to avoid adding the flag to
@@ -444,7 +450,7 @@ endif
# Command for statically linking programs with the C library.
ifndef +link-static
+link-static-before-inputs = -nostdlib -nostartfiles -static \
- $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \
+ $(if $($(@F)-no-pie),$(no-pie-ldflag),$(static-pie-ldflag)) \
$(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
$(firstword $(CRT-$(@F)) $(csu-objpfx)$(real-static-start-installed-name)) \
$(+preinit) $(+prectorT)
@@ -479,7 +485,7 @@ ifeq (yes,$(build-pie-default))
+link-tests-after-inputs = $(link-libc-tests) $(+link-pie-after-libc)
+link-printers-tests = $(+link-pie-printers-tests)
else # not build-pie-default
-+link-before-inputs = -nostdlib -nostartfiles \
++link-before-inputs = -nostdlib -nostartfiles $(no-pie-ldflag) \
$(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
$(combreloc-LDFLAGS) $(relro-LDFLAGS) $(hashstyle-LDFLAGS) \
$(firstword $(CRT-$(@F)) $(csu-objpfx)$(start-installed-name)) \
@@ -1047,6 +1053,7 @@ PIC-ccflag = -fPIC
endif
# This can be changed by a sysdep makefile
pie-ccflag = -fpie
+no-pie-ccflag = -fno-pie
# This one should always stay like this unless there is a very good reason.
PIE-ccflag = -fPIE
ifeq (yes,$(build-profile))
diff --git a/config.h.in b/config.h.in
index 8b45a3a61d774714..458342887e4e9380 100644
--- a/config.h.in
+++ b/config.h.in
@@ -277,6 +277,9 @@
/* Build glibc with tunables support. */
#define HAVE_TUNABLES 0
+/* Define if PIE is unsupported. */
+#undef PIE_UNSUPPORTED
+
/* Define if static PIE is supported. */
#undef SUPPORT_STATIC_PIE
diff --git a/config.make.in b/config.make.in
index cbf59114b0b9ae4f..e8630a8d0ccf874d 100644
--- a/config.make.in
+++ b/config.make.in
@@ -90,9 +90,6 @@ static-nss-crypt = @libc_cv_static_nss_crypt@
# Configuration options.
build-shared = @shared@
-build-pic-default= @libc_cv_pic_default@
-build-pie-default= @libc_cv_pie_default@
-cc-pie-default= @libc_cv_cc_pie_default@
build-profile = @profile@
build-static-nss = @static_nss@
cross-compiling = @cross_compiling@
diff --git a/configure b/configure
index 9619c10991d04362..e9d2b1f398c4dba0 100755
--- a/configure
+++ b/configure
@@ -596,9 +596,6 @@ DEFINES
static_nss
profile
libc_cv_multidir
-libc_cv_pie_default
-libc_cv_cc_pie_default
-libc_cv_pic_default
shared
static
ldd_rewrite_script
@@ -767,7 +764,7 @@ with_nonshared_cflags
enable_sanity_checks
enable_shared
enable_profile
-enable_static_pie
+enable_default_pie
enable_timezone_tools
enable_hardcoded_path_in_tests
enable_hidden_plt
@@ -1423,8 +1420,8 @@ Optional Features:
in special situations) [default=yes]
--enable-shared build shared library [default=yes if GNU ld]
--enable-profile build profiled library [default=no]
- --enable-static-pie enable static PIE support and use it in the
- testsuite [default=no]
+ --disable-default-pie Do not build glibc programs and the testsuite as PIE
+ [default=no]
--disable-timezone-tools
do not install timezone tools [default=install]
--enable-hardcoded-path-in-tests
@@ -3408,11 +3405,11 @@ else
profile=no
fi
-# Check whether --enable-static-pie was given.
-if test "${enable_static_pie+set}" = set; then :
- enableval=$enable_static_pie; static_pie=$enableval
+# Check whether --enable-default-pie was given.
+if test "${enable_default_pie+set}" = set; then :
+ enableval=$enable_default_pie; default_pie=$enableval
else
- static_pie=no
+ default_pie=yes
fi
# Check whether --enable-timezone-tools was given.
@@ -6912,7 +6909,8 @@ rm -f conftest.*
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pic_default" >&5
$as_echo "$libc_cv_pic_default" >&6; }
-
+config_vars="$config_vars
+build-pic-default = $libc_cv_pic_default"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -fPIE is default" >&5
$as_echo_n "checking whether -fPIE is default... " >&6; }
@@ -6932,17 +6930,37 @@ rm -f conftest.*
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cc_pie_default" >&5
$as_echo "$libc_cv_cc_pie_default" >&6; }
-libc_cv_pie_default=$libc_cv_cc_pie_default
-
-
-
-# Set the `multidir' variable by grabbing the variable from the compiler.
-# We do it once and save the result in a generated makefile.
-libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`
-
+config_vars="$config_vars
+cc-pie-default = $libc_cv_cc_pie_default"
-if test "$static_pie" = yes; then
- # Check target support for static PIE
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
+$as_echo_n "checking if we can build programs as PIE... " >&6; }
+if test "x$default_pie" != xno; then
+ # Disable build-pie-default if target does not support it.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef PIE_UNSUPPORTED
+# error PIE is not supported
+#endif
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ libc_cv_pie_default=yes
+else
+ libc_cv_pie_default=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pie_default" >&5
+$as_echo "$libc_cv_pie_default" >&6; }
+config_vars="$config_vars
+build-pie-default = $libc_cv_pie_default"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can build static PIE programs" >&5
+$as_echo_n "checking if we can build static PIE programs... " >&6; }
+libc_cv_static_pie=$libc_cv_pie_default
+if test "x$libc_cv_pie_default" != xno \
+ -a "$libc_cv_no_dynamic_linker" = yes; then
+ # Enable static-pie if available
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#ifndef SUPPORT_STATIC_PIE
@@ -6950,22 +6968,25 @@ if test "$static_pie" = yes; then
#endif
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
-
+ libc_cv_static_pie=yes
else
- as_fn_error $? "the architecture does not support static PIE" "$LINENO" 5
+ libc_cv_static_pie=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- # The linker must support --no-dynamic-linker.
- if test "$libc_cv_no_dynamic_linker" != yes; then
- as_fn_error $? "linker support for --no-dynamic-linker needed" "$LINENO" 5
- fi
- # Default to PIE.
- libc_cv_pie_default=yes
- $as_echo "#define ENABLE_STATIC_PIE 1" >>confdefs.h
+ if test "$libc_cv_static_pie" = "yes"; then
+ $as_echo "#define ENABLE_STATIC_PIE 1" >>confdefs.h
+ fi
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_static_pie" >&5
+$as_echo "$libc_cv_static_pie" >&6; }
config_vars="$config_vars
-enable-static-pie = $static_pie"
+enable-static-pie = $libc_cv_static_pie"
+
+# Set the `multidir' variable by grabbing the variable from the compiler.
+# We do it once and save the result in a generated makefile.
+libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`
+
diff --git a/configure.ac b/configure.ac
index 34ecbba540546337..79f6822d29ce21cf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -179,11 +179,11 @@ AC_ARG_ENABLE([profile],
[build profiled library @<:@default=no@:>@]),
[profile=$enableval],
[profile=no])
-AC_ARG_ENABLE([static-pie],
- AS_HELP_STRING([--enable-static-pie],
- [enable static PIE support and use it in the testsuite @<:@default=no@:>@]),
- [static_pie=$enableval],
- [static_pie=no])
+AC_ARG_ENABLE([default-pie],
+ AS_HELP_STRING([--disable-default-pie],
+ [Do not build glibc programs and the testsuite as PIE @<:@default=no@:>@]),
+ [default_pie=$enableval],
+ [default_pie=yes])
AC_ARG_ENABLE([timezone-tools],
AS_HELP_STRING([--disable-timezone-tools],
[do not install timezone tools @<:@default=install@:>@]),
@@ -1856,7 +1856,7 @@ if eval "${CC-cc} -S conftest.c 2>&AS_MESSAGE_LOG_FD 1>&AS_MESSAGE_LOG_FD"; then
libc_cv_pic_default=no
fi
rm -f conftest.*])
-AC_SUBST(libc_cv_pic_default)
+LIBC_CONFIG_VAR([build-pic-default], [$libc_cv_pic_default])
AC_CACHE_CHECK([whether -fPIE is default], libc_cv_cc_pie_default,
[libc_cv_cc_pie_default=yes
@@ -1869,30 +1869,38 @@ if eval "${CC-cc} -S conftest.c 2>&AS_MESSAGE_LOG_FD 1>&AS_MESSAGE_LOG_FD"; then
libc_cv_cc_pie_default=no
fi
rm -f conftest.*])
-libc_cv_pie_default=$libc_cv_cc_pie_default
-AC_SUBST(libc_cv_cc_pie_default)
-AC_SUBST(libc_cv_pie_default)
+LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
+
+AC_MSG_CHECKING(if we can build programs as PIE)
+if test "x$default_pie" != xno; then
+ # Disable build-pie-default if target does not support it.
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
+# error PIE is not supported
+#endif]])], [libc_cv_pie_default=yes], [libc_cv_pie_default=no])
+fi
+AC_MSG_RESULT($libc_cv_pie_default)
+LIBC_CONFIG_VAR([build-pie-default], [$libc_cv_pie_default])
+
+AC_MSG_CHECKING(if we can build static PIE programs)
+libc_cv_static_pie=$libc_cv_pie_default
+if test "x$libc_cv_pie_default" != xno \
+ -a "$libc_cv_no_dynamic_linker" = yes; then
+ # Enable static-pie if available
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifndef SUPPORT_STATIC_PIE
+# error static PIE is not supported
+#endif]])], [libc_cv_static_pie=yes], [libc_cv_static_pie=no])
+ if test "$libc_cv_static_pie" = "yes"; then
+ AC_DEFINE(ENABLE_STATIC_PIE)
+ fi
+fi
+AC_MSG_RESULT($libc_cv_static_pie)
+LIBC_CONFIG_VAR([enable-static-pie], [$libc_cv_static_pie])
# Set the `multidir' variable by grabbing the variable from the compiler.
# We do it once and save the result in a generated makefile.
libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`
AC_SUBST(libc_cv_multidir)
-if test "$static_pie" = yes; then
- # Check target support for static PIE
- AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifndef SUPPORT_STATIC_PIE
-# error static PIE is not supported
-#endif]])], , AC_MSG_ERROR([the architecture does not support static PIE]))
- # The linker must support --no-dynamic-linker.
- if test "$libc_cv_no_dynamic_linker" != yes; then
- AC_MSG_ERROR([linker support for --no-dynamic-linker needed])
- fi
- # Default to PIE.
- libc_cv_pie_default=yes
- AC_DEFINE(ENABLE_STATIC_PIE)
-fi
-LIBC_CONFIG_VAR([enable-static-pie], [$static_pie])
-
AC_SUBST(profile)
AC_SUBST(static_nss)
diff --git a/manual/install.texi b/manual/install.texi
index 46f73b538d3fee6f..1320ac69b3c645f2 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -141,15 +141,13 @@ Don't build shared libraries even if it is possible. Not all systems
support shared libraries; you need ELF support and (currently) the GNU
linker.
-@item --enable-static-pie
-Enable static position independent executable (static PIE) support.
-Static PIE is similar to static executable, but can be loaded at any
-address without help from a dynamic linker. All static programs as
-well as static tests are built as static PIE, except for those marked
-with no-pie. The resulting glibc can be used with the GCC option,
--static-pie, which is available with GCC 8 or above, to create static
-PIE. This option also implies that glibc programs and tests are created
-as dynamic position independent executables (PIE) by default.
+@item --disable-default-pie
+Don't build glibc programs and the testsuite as position independent
+executables (PIE). By default, glibc programs and tests are created as
+position independent executables on targets that support it. If the toolchain
+and architecture support it, static executables are built as static PIE and the
+resulting glibc can be used with the GCC option, -static-pie, which is
+available with GCC 8 or above, to create static PIE.
@item --enable-cet
@itemx --enable-cet=permissive
diff --git a/scripts/build-many-glibcs.py b/scripts/build-many-glibcs.py
index 86537fa8005cfd3d..2fd82a5d054c51ca 100755
--- a/scripts/build-many-glibcs.py
+++ b/scripts/build-many-glibcs.py
@@ -1,6 +1,7 @@
#!/usr/bin/python3
# Build many configurations of glibc.
# Copyright (C) 2016-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
@@ -435,15 +436,15 @@ class Context(object):
'--disable-experimental-malloc',
'--disable-build-nscd',
'--disable-nscd']},
- {'variant': 'static-pie',
- 'cfg': ['--enable-static-pie']},
- {'variant': 'x32-static-pie',
+ {'variant': 'no-pie',
+ 'cfg': ['--disable-default-pie']},
+ {'variant': 'x32-no-pie',
'ccopts': '-mx32',
- 'cfg': ['--enable-static-pie']},
- {'variant': 'static-pie',
+ 'cfg': ['--disable-default-pie']},
+ {'variant': 'no-pie',
'arch': 'i686',
'ccopts': '-m32 -march=i686',
- 'cfg': ['--enable-static-pie']},
+ 'cfg': ['--disable-default-pie']},
{'variant': 'disable-multi-arch',
'arch': 'i686',
'ccopts': '-m32 -march=i686',
diff --git a/sysdeps/alpha/configure b/sysdeps/alpha/configure
index 464b5965276dca19..3d665d96f2b40c4e 100644
--- a/sysdeps/alpha/configure
+++ b/sysdeps/alpha/configure
@@ -5,4 +5,9 @@
# symbols in a position independent way.
$as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h
+
+# PIE builds fail on binutils 2.37 and earlier, see:
+# https://sourceware.org/bugzilla/show_bug.cgi?id=28672
+$as_echo "#define PIE_UNSUPPORTED 1" >>confdefs.h
+
# work around problem with autoconf and empty lines at the end of files
diff --git a/sysdeps/alpha/configure.ac b/sysdeps/alpha/configure.ac
index 38e52e71ac2a5bc0..8f9a39ed2e4a29cb 100644
--- a/sysdeps/alpha/configure.ac
+++ b/sysdeps/alpha/configure.ac
@@ -4,4 +4,8 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
# With required gcc+binutils, we can always access static and hidden
# symbols in a position independent way.
AC_DEFINE(PI_STATIC_AND_HIDDEN)
+
+# PIE builds fail on binutils 2.37 and earlier, see:
+# https://sourceware.org/bugzilla/show_bug.cgi?id=28672
+AC_DEFINE(PIE_UNSUPPORTED)
# work around problem with autoconf and empty lines at the end of files
diff --git a/sysdeps/csky/configure b/sysdeps/csky/configure
index 19acb084fb43d9ea..27464eb707ebd6c6 100644
--- a/sysdeps/csky/configure
+++ b/sysdeps/csky/configure
@@ -2,3 +2,10 @@
# Local configure fragment for sysdeps/csky.
$as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h
+
+
+# PIE builds fail on binutils 2.37 and earlier, see:
+# https://sourceware.org/bugzilla/show_bug.cgi?id=28672
+$as_echo "#define PIE_UNSUPPORTED 1" >>confdefs.h
+
+# work around problem with autoconf and empty lines at the end of files
diff --git a/sysdeps/csky/configure.ac b/sysdeps/csky/configure.ac
index 5656b665da698d05..8e008249094d9e5a 100644
--- a/sysdeps/csky/configure.ac
+++ b/sysdeps/csky/configure.ac
@@ -2,3 +2,8 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
# Local configure fragment for sysdeps/csky.
AC_DEFINE(PI_STATIC_AND_HIDDEN)
+
+# PIE builds fail on binutils 2.37 and earlier, see:
+# https://sourceware.org/bugzilla/show_bug.cgi?id=28672
+AC_DEFINE(PIE_UNSUPPORTED)
+# work around problem with autoconf and empty lines at the end of files
diff --git a/sysdeps/hppa/configure b/sysdeps/hppa/configure
index 2cfe6cbea14549d0..cf5acf966dad67ba 100644
--- a/sysdeps/hppa/configure
+++ b/sysdeps/hppa/configure
@@ -30,3 +30,10 @@ $as_echo "$libc_cv_asm_line_sep" >&6; }
cat >>confdefs.h <<_ACEOF
#define ASM_LINE_SEP $libc_cv_asm_line_sep
_ACEOF
+
+
+# PIE builds fail on binutils 2.37 and earlier, see:
+# https://sourceware.org/bugzilla/show_bug.cgi?id=28672
+$as_echo "#define PIE_UNSUPPORTED 1" >>confdefs.h
+
+# work around problem with autoconf and empty lines at the end of files
diff --git a/sysdeps/hppa/configure.ac b/sysdeps/hppa/configure.ac
index 1ec417b9474c3382..3e1c35bbd992f548 100644
--- a/sysdeps/hppa/configure.ac
+++ b/sysdeps/hppa/configure.ac
@@ -19,3 +19,8 @@ else
fi
rm -f conftest*])
AC_DEFINE_UNQUOTED(ASM_LINE_SEP, $libc_cv_asm_line_sep)
+
+# PIE builds fail on binutils 2.37 and earlier, see:
+# https://sourceware.org/bugzilla/show_bug.cgi?id=28672
+AC_DEFINE(PIE_UNSUPPORTED)
+# work around problem with autoconf and empty lines at the end of files
diff --git a/sysdeps/ia64/configure b/sysdeps/ia64/configure
index 1ef70921bc5266db..748cb526012adeb8 100644
--- a/sysdeps/ia64/configure
+++ b/sysdeps/ia64/configure
@@ -3,4 +3,9 @@
$as_echo "#define PI_STATIC_AND_HIDDEN 1" >>confdefs.h
+
+# PIE builds fail on binutils 2.37 and earlier, see:
+# https://sourceware.org/bugzilla/show_bug.cgi?id=28672
+$as_echo "#define PIE_UNSUPPORTED 1" >>confdefs.h
+
# work around problem with autoconf and empty lines at the end of files
diff --git a/sysdeps/ia64/configure.ac b/sysdeps/ia64/configure.ac
index 3bae9fc5e1a3ff45..8e5fba32c3ec8bfc 100644
--- a/sysdeps/ia64/configure.ac
+++ b/sysdeps/ia64/configure.ac
@@ -4,4 +4,8 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
dnl It is always possible to access static and hidden symbols in an
dnl position independent way.
AC_DEFINE(PI_STATIC_AND_HIDDEN)
+
+# PIE builds fail on binutils 2.37 and earlier, see:
+# https://sourceware.org/bugzilla/show_bug.cgi?id=28672
+AC_DEFINE(PIE_UNSUPPORTED)
# work around problem with autoconf and empty lines at the end of files
diff --git a/sysdeps/mach/hurd/configure b/sysdeps/mach/hurd/configure
index 8d0702ad438d1c0a..3303e5dff8ef5ecf 100644
--- a/sysdeps/mach/hurd/configure
+++ b/sysdeps/mach/hurd/configure
@@ -49,3 +49,9 @@ fi
# Hurd has libpthread as a separate library.
pthread_in_libc=no
+
+# Hurd build needs to be updated to support static pie, see:
+# https://sourceware.org/bugzilla/show_bug.cgi?id=28671
+$as_echo "#define PIE_UNSUPPORTED 1" >>confdefs.h
+
+# work around problem with autoconf and empty lines at the end of files
diff --git a/sysdeps/mach/hurd/configure.ac b/sysdeps/mach/hurd/configure.ac
index 82d085af33701aa2..022c2eff79fc0d08 100644
--- a/sysdeps/mach/hurd/configure.ac
+++ b/sysdeps/mach/hurd/configure.ac
@@ -29,3 +29,8 @@ fi
# Hurd has libpthread as a separate library.
pthread_in_libc=no
+
+# Hurd build needs to be updated to support static pie, see:
+# https://sourceware.org/bugzilla/show_bug.cgi?id=28671
+AC_DEFINE(PIE_UNSUPPORTED)
+# work around problem with autoconf and empty lines at the end of files
diff --git a/sysdeps/microblaze/configure b/sysdeps/microblaze/configure
new file mode 100755
index 0000000000000000..e6652562d212b688
--- /dev/null
+++ b/sysdeps/microblaze/configure
@@ -0,0 +1,8 @@
+# This file is generated from configure.ac by Autoconf. DO NOT EDIT!
+ # Local configure fragment for sysdeps/microblaze.
+
+# gcc 11.2.1 and earlier crash with an internal compiler error, see:
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103613
+$as_echo "#define PIE_UNSUPPORTED 1" >>confdefs.h
+
+# work around problem with autoconf and empty lines at the end of files
diff --git a/sysdeps/microblaze/configure.ac b/sysdeps/microblaze/configure.ac
new file mode 100644
index 0000000000000000..1c58f70a7bdfebcb
--- /dev/null
+++ b/sysdeps/microblaze/configure.ac
@@ -0,0 +1,7 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/microblaze.
+
+# gcc 11.2.1 and earlier crash with an internal compiler error, see:
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103613
+AC_DEFINE(PIE_UNSUPPORTED)
+# work around problem with autoconf and empty lines at the end of files
diff --git a/sysdeps/sparc/Makefile b/sysdeps/sparc/Makefile
index 1be9a3db2ca12216..12c2c1b085fd4ae2 100644
--- a/sysdeps/sparc/Makefile
+++ b/sysdeps/sparc/Makefile
@@ -2,6 +2,7 @@
long-double-fcts = yes
pie-ccflag = -fPIE
+no-pie-ccflag = -fno-PIE
ifeq ($(subdir),gmon)
sysdep_routines += sparc-mcount

@ -0,0 +1,250 @@
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
(usual test differences)
elf/rtld.c
(missing ld.so self-relocation cleanup downstream)
diff --git a/elf/Makefile b/elf/Makefile
index 118d579c42c38110..7696aa1324919a80 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -224,7 +224,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-dlmopen-dlerror tst-dlmopen-gethostbyname \
- tst-dl-is_dso tst-ro-dynamic
+ tst-dl-is_dso tst-ro-dynamic \
+ tst-rtld-run-static \
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -1914,3 +1915,5 @@ $(objpfx)tst-ro-dynamic-mod.so: $(objpfx)tst-ro-dynamic-mod.os \
$(LINK.o) -nostdlib -nostartfiles -shared -o $@ \
-Wl,--script=tst-ro-dynamic-mod.map \
$(objpfx)tst-ro-dynamic-mod.os
+
+$(objpfx)tst-rtld-run-static.out: $(objpfx)/ldconfig
diff --git a/elf/rtld.c b/elf/rtld.c
index d83ac1bdc40a6081..6b0d6107801b2f44 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -50,6 +50,7 @@
#include <dl-main.h>
#include <gnu/lib-names.h>
#include <dl-tunables.h>
+#include <dl-execve.h>
#include <assert.h>
@@ -1106,6 +1107,45 @@ 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);
+ const char *errname = strerrorname_np (errcode);
+ if (errname != NULL)
+ _dl_fatal_printf("%s: cannot execute %s: %s\n",
+ rtld_soname, pathname, errname);
+ else
+ _dl_fatal_printf("%s: cannot execute %s: %d\n",
+ rtld_soname, pathname, errno);
+}
+
static void
dl_main (const ElfW(Phdr) *phdr,
ElfW(Word) phnum,
@@ -1374,14 +1414,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..ead3e1c28da34363
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/dl-execve.h
@@ -0,0 +1,25 @@
+/* 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)
+{
+ return -INTERNAL_SYSCALL_CALL (execve, path, argv, envp);
+}

@ -0,0 +1,37 @@
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>
diff --git a/elf/Makefile b/elf/Makefile
index 7696aa1324919a80..3e7debdd81baafe0 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -104,7 +104,7 @@ endif
ifeq (yes,$(build-shared))
extra-objs = $(all-rtld-routines:%=%.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
@@ -645,6 +645,11 @@ $(inst_rtlddir)/$(rtld-installed-name): $(objpfx)ld.so $(+force)
$(make-target-directory)
$(do-install-program)
+# 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)

@ -0,0 +1,19 @@
commit f1eeef945d49c72eb13654bd30b5904e89b4626f
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Dec 10 21:34:30 2021 +0100
elf: Use errcode instead of (unset) errno in rtld_chain_load
diff --git a/elf/rtld.c b/elf/rtld.c
index 6b0d6107801b2f44..6bbb373c5743cb99 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1143,7 +1143,7 @@ rtld_chain_load (struct link_map *main_map, char *argv0)
rtld_soname, pathname, errname);
else
_dl_fatal_printf("%s: cannot execute %s: %d\n",
- rtld_soname, pathname, errno);
+ rtld_soname, pathname, errcode);
}
static void

@ -0,0 +1,98 @@
commit 84a7eb1f87c1d01b58ad887a0ab5d87abbc1c772
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Fri Jul 30 19:07:30 2021 -0700
Use __executable_start as the lowest address for profiling [BZ #28153]
Glibc assumes that ENTRY_POINT is the lowest address for which we need
to keep profiling records and BFD linker uses a linker script to place
the input sections.
Starting from GCC 4.6, the main function is placed in .text.startup
section and starting from binutils 2.22, BFD linker with
commit add44f8d5c5c05e08b11e033127a744d61c26aee
Author: Alan Modra <amodra@gmail.com>
Date: Thu Nov 25 03:03:02 2010 +0000
* scripttempl/elf.sc: Group .text.exit, text.startup and .text.hot
sections.
places .text.startup section before .text section, which leave the main
function out of profiling records.
Starting from binutils 2.15, linker provides __executable_start to mark
the lowest address of the executable. Use __executable_start as the
lowest address to keep the main function in profiling records. This fixes
[BZ #28153].
Tested on Linux/x86-64, Linux/x32 and Linux/i686 as well as with
build-many-glibcs.py.
diff --git a/csu/gmon-start.c b/csu/gmon-start.c
index b3432885b39071cc..344606a676c188d4 100644
--- a/csu/gmon-start.c
+++ b/csu/gmon-start.c
@@ -52,6 +52,11 @@ extern char ENTRY_POINT[];
#endif
extern char etext[];
+/* Use __executable_start as the lowest address to keep profiling records
+ if it provided by the linker. */
+extern const char executable_start[] asm ("__executable_start")
+ __attribute__ ((weak, visibility ("hidden")));
+
#ifndef TEXT_START
# ifdef ENTRY_POINT_DECL
# define TEXT_START ENTRY_POINT
@@ -92,7 +97,10 @@ __gmon_start__ (void)
called = 1;
/* Start keeping profiling records. */
- __monstartup ((u_long) TEXT_START, (u_long) &etext);
+ if (&executable_start != NULL)
+ __monstartup ((u_long) &executable_start, (u_long) &etext);
+ else
+ __monstartup ((u_long) TEXT_START, (u_long) &etext);
/* Call _mcleanup before exiting; it will write out gmon.out from the
collected data. */
diff --git a/gmon/tst-gmon-gprof.sh b/gmon/tst-gmon-gprof.sh
index 9d371582b99677fa..dc0be021104f725d 100644
--- a/gmon/tst-gmon-gprof.sh
+++ b/gmon/tst-gmon-gprof.sh
@@ -39,12 +39,14 @@ trap cleanup 0
cat > "$expected" <<EOF
f1 2000
f2 1000
+f3 1
EOF
# Special version for powerpc with function descriptors.
cat > "$expected_dot" <<EOF
.f1 2000
.f2 1000
+.f3 1
EOF
"$GPROF" -C "$program" "$data" \
diff --git a/gmon/tst-gmon-static-gprof.sh b/gmon/tst-gmon-static-gprof.sh
index 79218df967f9387f..4cc99c80d0115271 100644
--- a/gmon/tst-gmon-static-gprof.sh
+++ b/gmon/tst-gmon-static-gprof.sh
@@ -39,6 +39,7 @@ trap cleanup 0
cat > "$expected" <<EOF
f1 2000
f2 1000
+f3 1
main 1
EOF
@@ -46,6 +47,7 @@ EOF
cat > "$expected_dot" <<EOF
.f1 2000
.f2 1000
+.f3 1
.main 1
EOF

@ -0,0 +1,74 @@
Downstream adjustment: Change return type of
rseq_register_current_thread to bool. Upstream, this was part of the
commit that introduced the ABI symbols.
commit a41c8e92350e744a4bc639df5025153d05263e7f
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Dec 9 09:49:32 2021 +0100
nptl: rseq failure after registration on main thread is fatal
This simplifies the application programming model.
Browser sandboxes have already been fixed:
Sandbox is incompatible with rseq registration
<https://bugzilla.mozilla.org/show_bug.cgi?id=1651701>
Allow rseq in the Linux sandboxes. r=gcp
<https://hg.mozilla.org/mozilla-central/rev/042425712eb1>
Sandbox needs to support rseq system call
<https://bugs.chromium.org/p/chromium/issues/detail?id=1104160>
Linux sandbox: Allow rseq(2)
<https://chromium.googlesource.com/chromium/src.git/+/230675d9ac8f1>
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index f405fa356c2955ce..109c5e3dc78c9aa2 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -371,7 +371,8 @@ start_thread (void *arg)
/* Register rseq TLS to the kernel. */
{
bool do_rseq = THREAD_GETMEM (pd, flags) & ATTR_FLAG_DO_RSEQ;
- rseq_register_current_thread (pd, do_rseq);
+ if (!rseq_register_current_thread (pd, do_rseq) && do_rseq)
+ __libc_fatal ("Fatal glibc error: rseq registration failed\n");
}
#ifndef __ASSUME_SET_ROBUST_LIST
diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
index 15bc7ffd6eda632d..6a3441f2cc49e7c4 100644
--- a/sysdeps/unix/sysv/linux/rseq-internal.h
+++ b/sysdeps/unix/sysv/linux/rseq-internal.h
@@ -26,7 +26,7 @@
#include <sys/rseq.h>
#ifdef RSEQ_SIG
-static inline void
+static inline bool
rseq_register_current_thread (struct pthread *self, bool do_rseq)
{
if (do_rseq)
@@ -35,15 +35,17 @@ rseq_register_current_thread (struct pthread *self, bool do_rseq)
sizeof (self->rseq_area),
0, RSEQ_SIG);
if (!INTERNAL_SYSCALL_ERROR_P (ret))
- return;
+ return true;
}
THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
+ return false;
}
#else /* RSEQ_SIG */
static inline void
rseq_register_current_thread (struct pthread *self, bool do_rseq)
{
THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
+ return false;
}
#endif /* RSEQ_SIG */

@ -0,0 +1,592 @@
commit 627f5ede70d70c77bdaf857db07404e8bf7f60af
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Dec 9 17:57:11 2021 +0100
Remove TLS_TCB_ALIGN and TLS_INIT_TCB_ALIGN
TLS_INIT_TCB_ALIGN is not actually used. TLS_TCB_ALIGN was likely
introduced to support a configuration where the thread pointer
has not the same alignment as THREAD_SELF. Only ia64 seems to use
that, but for the stack/pointer guard, not for storing tcbhead_t.
Some ports use TLS_TCB_OFFSET and TLS_PRE_TCB_SIZE to shift
the thread pointer, potentially landing in a different residue class
modulo the alignment, but the changes should not impact that.
In general, given that TLS variables have their own alignment
requirements, having different alignment for the (unshifted) thread
pointer and struct pthread would potentially result in dynamic
offsets, leading to more complexity.
hppa had different values before: __alignof__ (tcbhead_t), which
seems to be 4, and __alignof__ (struct pthread), which was 8
(old default) and is now 32. However, it defines THREAD_SELF as:
/* Return the thread descriptor for the current thread. */
# define THREAD_SELF \
({ struct pthread *__self; \
__self = __get_cr27(); \
__self - 1; \
})
So the thread pointer points after struct pthread (hence __self - 1),
and they have to have the same alignment on hppa as well.
Similarly, on ia64, the definitions were different. We have:
# define TLS_PRE_TCB_SIZE \
(sizeof (struct pthread) \
+ (PTHREAD_STRUCT_END_PADDING < 2 * sizeof (uintptr_t) \
? ((2 * sizeof (uintptr_t) + __alignof__ (struct pthread) - 1) \
& ~(__alignof__ (struct pthread) - 1)) \
: 0))
# define THREAD_SELF \
((struct pthread *) ((char *) __thread_self - TLS_PRE_TCB_SIZE))
And TLS_PRE_TCB_SIZE is a multiple of the struct pthread alignment
(confirmed by the new _Static_assert in sysdeps/ia64/libc-tls.c).
On m68k, we have a larger gap between tcbhead_t and struct pthread.
But as far as I can tell, the port is fine with that. The definition
of TCB_OFFSET is sufficient to handle the shifted TCB scenario.
This fixes commit 23c77f60181eb549f11ec2f913b4270af29eee38
("nptl: Increase default TCB alignment to 32").
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
diff --git a/csu/libc-tls.c b/csu/libc-tls.c
index 5515204863218163..d83e69f6257ae981 100644
--- a/csu/libc-tls.c
+++ b/csu/libc-tls.c
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <sys/param.h>
#include <array_length.h>
+#include <pthreadP.h>
#ifdef SHARED
#error makefile bug, this file is for static only
@@ -89,7 +90,7 @@ init_static_tls (size_t memsz, size_t align)
{
/* That is the size of the TLS memory for this object. */
GL(dl_tls_static_size) = roundup (memsz + GLRO(dl_tls_static_surplus),
- TLS_TCB_ALIGN);
+ TCB_ALIGNMENT);
#if TLS_TCB_AT_TP
GL(dl_tls_static_size) += TLS_TCB_SIZE;
#endif
@@ -214,5 +215,5 @@ __libc_setup_tls (void)
memsz += tcb_offset;
#endif
- init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align));
+ init_static_tls (memsz, MAX (TCB_ALIGNMENT, max_align));
}
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index 40263cf586e74c64..e2012d0cd515103b 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -219,7 +219,7 @@ _dl_count_modids (void)
void
_dl_determine_tlsoffset (void)
{
- size_t max_align = TLS_TCB_ALIGN;
+ size_t max_align = TCB_ALIGNMENT;
size_t freetop = 0;
size_t freebottom = 0;
@@ -350,7 +350,7 @@ _dl_determine_tlsoffset (void)
GL(dl_tls_static_used) = offset;
GLRO (dl_tls_static_size) = roundup (offset + GLRO(dl_tls_static_surplus),
- TLS_TCB_ALIGN);
+ TCB_ALIGNMENT);
#else
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
#endif
diff --git a/sysdeps/aarch64/nptl/tls.h b/sysdeps/aarch64/nptl/tls.h
index cd9abb5d1d073593..75c469d51b532a89 100644
--- a/sysdeps/aarch64/nptl/tls.h
+++ b/sysdeps/aarch64/nptl/tls.h
@@ -52,18 +52,12 @@ typedef struct
/* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE sizeof (tcbhead_t)
/* This is the size we need before TCB. */
# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* Install the dtv pointer. The pointer passed is to the element with
index -1 which contain the length. */
# define INSTALL_DTV(tcbp, dtvp) \
diff --git a/sysdeps/alpha/nptl/tls.h b/sysdeps/alpha/nptl/tls.h
index 5f4843b28e7f1ad1..c0b6c93891546480 100644
--- a/sysdeps/alpha/nptl/tls.h
+++ b/sysdeps/alpha/nptl/tls.h
@@ -46,18 +46,12 @@ typedef struct
/* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN 16
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE sizeof (tcbhead_t)
/* This is the size we need before TCB. */
# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN 16
-
/* Install the dtv pointer. The pointer passed is to the element with
index -1 which contain the length. */
# define INSTALL_DTV(tcbp, dtvp) \
diff --git a/sysdeps/arc/nptl/tls.h b/sysdeps/arc/nptl/tls.h
index d9ada2f38089e6cd..d5d282297d12ec98 100644
--- a/sysdeps/arc/nptl/tls.h
+++ b/sysdeps/arc/nptl/tls.h
@@ -48,17 +48,11 @@ typedef struct
/* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size of the TCB. */
#ifndef TLS_TCB_SIZE
# define TLS_TCB_SIZE sizeof (tcbhead_t)
#endif
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size we need before TCB. */
# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
diff --git a/sysdeps/arm/nptl/tls.h b/sysdeps/arm/nptl/tls.h
index 354aae3318291395..8475c66588f99cae 100644
--- a/sysdeps/arm/nptl/tls.h
+++ b/sysdeps/arm/nptl/tls.h
@@ -50,18 +50,12 @@ typedef struct
/* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN 16
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE sizeof (tcbhead_t)
/* This is the size we need before TCB. */
# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN 16
-
/* Install the dtv pointer. The pointer passed is to the element with
index -1 which contain the length. */
# define INSTALL_DTV(tcbp, dtvp) \
diff --git a/sysdeps/csky/nptl/tls.h b/sysdeps/csky/nptl/tls.h
index f3fa3fcb02748776..e81d4552d27e0378 100644
--- a/sysdeps/csky/nptl/tls.h
+++ b/sysdeps/csky/nptl/tls.h
@@ -61,15 +61,9 @@ typedef struct
/* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN 8
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE sizeof (tcbhead_t)
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN 8
-
/* This is the size we need before TCB. */
# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
diff --git a/sysdeps/generic/tls.h b/sysdeps/generic/tls.h
index e86d70e6cebba5c8..9214ed39b6383e8c 100644
--- a/sysdeps/generic/tls.h
+++ b/sysdeps/generic/tls.h
@@ -19,6 +19,11 @@
/* An architecture-specific version of this file has to defined a
number of symbols:
+ TCB_ALIGNMENT
+
+ Alignment of THREAD_SELF (struct pthread *) and the thread
+ pointer.
+
TLS_TCB_AT_TP or TLS_DTV_AT_TP
The presence of one of these symbols signals which variant of
@@ -43,15 +48,6 @@
dynamic linker itself. There are no threads in use at that time.
- TLS_TCB_ALIGN
-
- Alignment requirements for the TCB structure.
-
- TLS_INIT_TCB_ALIGN
-
- Similarly, but for the structure used at startup time.
-
-
INSTALL_DTV(tcb, init_dtv)
This macro must install the given initial DTV into the thread control
diff --git a/sysdeps/hppa/nptl/tls.h b/sysdeps/hppa/nptl/tls.h
index f0e274c45fb5e91e..88a6b902c0b7e2fd 100644
--- a/sysdeps/hppa/nptl/tls.h
+++ b/sysdeps/hppa/nptl/tls.h
@@ -52,15 +52,9 @@ typedef struct
/* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE sizeof (tcbhead_t)
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size we need before TCB */
# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h
index 111c9ee59df30bc3..06ab9784a5358b0b 100644
--- a/sysdeps/i386/nptl/tls.h
+++ b/sysdeps/i386/nptl/tls.h
@@ -102,15 +102,9 @@ union user_desc_init
struct pthread even when not linked with -lpthread. */
# define TLS_INIT_TCB_SIZE sizeof (struct pthread)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE sizeof (struct pthread)
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* The TCB can have any size and the memory following the address the
thread pointer points to is unspecified. Allocate the TCB there. */
# define TLS_TCB_AT_TP 1
diff --git a/sysdeps/ia64/libc-tls.c b/sysdeps/ia64/libc-tls.c
index a01edceab36d375e..ede1e8f463b135b4 100644
--- a/sysdeps/ia64/libc-tls.c
+++ b/sysdeps/ia64/libc-tls.c
@@ -18,6 +18,9 @@
#include <csu/libc-tls.c>
+_Static_assert (TLS_PRE_TCB_SIZE % __alignof (struct pthread) == 0,
+ "__thread_self and THREAD_SELF have same alignment");
+
/* On IA-64, as it lacks linker optimizations, __tls_get_addr can be
called even in statically linked binaries.
In this case module must be always 1 and PT_TLS segment
diff --git a/sysdeps/ia64/nptl/tls.h b/sysdeps/ia64/nptl/tls.h
index 26fe555cb4b5e164..ca8f1280aeeed3d5 100644
--- a/sysdeps/ia64/nptl/tls.h
+++ b/sysdeps/ia64/nptl/tls.h
@@ -53,9 +53,6 @@ register struct pthread *__thread_self __asm__("r13");
/* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE sizeof (tcbhead_t)
@@ -70,9 +67,6 @@ register struct pthread *__thread_self __asm__("r13");
& ~(__alignof__ (struct pthread) - 1)) \
: 0))
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* The DTV is allocated at the TP; the TCB is placed elsewhere. */
# define TLS_DTV_AT_TP 1
# define TLS_TCB_AT_TP 0
diff --git a/sysdeps/m68k/nptl/tls.h b/sysdeps/m68k/nptl/tls.h
index 9f562c38288df200..b88ef0c9c74ae0b0 100644
--- a/sysdeps/m68k/nptl/tls.h
+++ b/sysdeps/m68k/nptl/tls.h
@@ -54,20 +54,15 @@ typedef struct
pointer, we don't need this. */
# define TLS_INIT_TCB_SIZE 0
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size of the TCB. Because our TCB is before the thread
pointer, we don't need this. */
# define TLS_TCB_SIZE 0
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size we need before TCB - actually, it includes the TCB. */
# define TLS_PRE_TCB_SIZE \
(sizeof (struct pthread) \
- + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
+ + ((sizeof (tcbhead_t) + __alignof (struct pthread) - 1) \
+ & ~(__alignof (struct pthread) - 1)))
/* The thread pointer (TP) points to the end of the
TCB + 0x7000, as for PowerPC and MIPS. This implies that TCB address is
diff --git a/sysdeps/mach/hurd/tls.h b/sysdeps/mach/hurd/tls.h
index f83956d3d7ca4f9f..773a2a0c36d5d57d 100644
--- a/sysdeps/mach/hurd/tls.h
+++ b/sysdeps/mach/hurd/tls.h
@@ -29,20 +29,12 @@
# include <mach.h>
# include <atomic.h>
-
/* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE TLS_INIT_TCB_SIZE /* XXX */
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN TLS_INIT_TCB_ALIGN /* XXX */
-
-
/* Install the dtv pointer. The pointer passed is to the element with
index -1 which contain the length. */
# define INSTALL_DTV(descr, dtvp) \
diff --git a/sysdeps/microblaze/nptl/tls.h b/sysdeps/microblaze/nptl/tls.h
index bfa6efa78049bb2d..b69d7b4f28f3b757 100644
--- a/sysdeps/microblaze/nptl/tls.h
+++ b/sysdeps/microblaze/nptl/tls.h
@@ -56,18 +56,12 @@ typedef struct
/* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE sizeof (tcbhead_t)
/* This is the size we need before TCB. */
# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* Install the dtv pointer. The pointer passed is to the element with
index -1 which contain the length. */
# define INSTALL_DTV(tcbp, dtvp) \
diff --git a/sysdeps/mips/nptl/tls.h b/sysdeps/mips/nptl/tls.h
index ef99aa646c898e76..6ccaf9804a68634a 100644
--- a/sysdeps/mips/nptl/tls.h
+++ b/sysdeps/mips/nptl/tls.h
@@ -83,20 +83,15 @@ typedef struct
pointer, we don't need this. */
# define TLS_INIT_TCB_SIZE 0
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size of the TCB. Because our TCB is before the thread
pointer, we don't need this. */
# define TLS_TCB_SIZE 0
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size we need before TCB - actually, it includes the TCB. */
# define TLS_PRE_TCB_SIZE \
(sizeof (struct pthread) \
- + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
+ + ((sizeof (tcbhead_t) + __alignof (struct pthread) - 1) \
+ & ~(__alignof (struct pthread) - 1)))
/* The thread pointer (in hardware register $29) points to the end of
the TCB + 0x7000, as for PowerPC. The pthread_descr structure is
diff --git a/sysdeps/nios2/nptl/tls.h b/sysdeps/nios2/nptl/tls.h
index 7110cfccad7131f4..6ab6bd27b00a70ee 100644
--- a/sysdeps/nios2/nptl/tls.h
+++ b/sysdeps/nios2/nptl/tls.h
@@ -59,20 +59,15 @@ register struct pthread *__thread_self __asm__("r23");
pointer, we don't need this. */
# define TLS_INIT_TCB_SIZE 0
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size of the TCB. Because our TCB is before the thread
pointer, we don't need this. */
# define TLS_TCB_SIZE 0
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size we need before TCB - actually, it includes the TCB. */
# define TLS_PRE_TCB_SIZE \
(sizeof (struct pthread) \
- + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
+ + ((sizeof (tcbhead_t) + __alignof (struct pthread) - 1) \
+ & ~(__alignof (struct pthread) - 1)))
/* The thread pointer (in hardware register r23) points to the end of
the TCB + 0x7000, as for PowerPC and MIPS. */
diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h
index 110d085d30c86302..e194b334216eaa02 100644
--- a/sysdeps/powerpc/nptl/tls.h
+++ b/sysdeps/powerpc/nptl/tls.h
@@ -108,19 +108,14 @@ typedef struct
/* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE 0
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE 0
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size we need before TCB. */
# define TLS_PRE_TCB_SIZE \
(sizeof (struct pthread) \
- + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
+ + ((sizeof (tcbhead_t) + __alignof (struct pthread) - 1) \
+ & ~(__alignof (struct pthread) - 1)))
/* The following assumes that TP (R2 or R13) points to the end of the
TCB + 0x7000 (per the ABI). This implies that TCB address is
diff --git a/sysdeps/riscv/nptl/tls.h b/sysdeps/riscv/nptl/tls.h
index bdc0a3a6f91b51e8..8c12d8f971adeddb 100644
--- a/sysdeps/riscv/nptl/tls.h
+++ b/sysdeps/riscv/nptl/tls.h
@@ -50,20 +50,15 @@ typedef struct
pointer, we don't need this. */
# define TLS_INIT_TCB_SIZE 0
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size of the TCB. Because our TCB is before the thread
pointer, we don't need this. */
# define TLS_TCB_SIZE 0
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size we need before TCB - actually, it includes the TCB. */
# define TLS_PRE_TCB_SIZE \
(sizeof (struct pthread) \
- + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
+ + ((sizeof (tcbhead_t) + __alignof (struct pthread) - 1) \
+ & ~(__alignof (struct pthread) - 1)))
/* The thread pointer tp points to the end of the TCB.
The pthread_descr structure is immediately in front of the TCB. */
diff --git a/sysdeps/s390/nptl/tls.h b/sysdeps/s390/nptl/tls.h
index 2cdd18eb2907c060..3b4c0ab32a9439a3 100644
--- a/sysdeps/s390/nptl/tls.h
+++ b/sysdeps/s390/nptl/tls.h
@@ -66,15 +66,9 @@ typedef struct
struct pthread even when not linked with -lpthread. */
# define TLS_INIT_TCB_SIZE sizeof (struct pthread)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE sizeof (struct pthread)
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* The TCB can have any size and the memory following the address the
thread pointer points to is unspecified. Allocate the TCB there. */
# define TLS_TCB_AT_TP 1
diff --git a/sysdeps/sh/nptl/tls.h b/sysdeps/sh/nptl/tls.h
index 390640020e45f716..3e4d480b35951253 100644
--- a/sysdeps/sh/nptl/tls.h
+++ b/sysdeps/sh/nptl/tls.h
@@ -51,18 +51,12 @@ typedef struct
/* This is the size of the initial TCB. */
# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE sizeof (tcbhead_t)
/* This is the size we need before TCB. */
# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* The TLS blocks start right after the TCB. */
# define TLS_DTV_AT_TP 1
# define TLS_TCB_AT_TP 0
diff --git a/sysdeps/sparc/nptl/tls.h b/sysdeps/sparc/nptl/tls.h
index 376d729989e35660..3fb4ce6e6dacf28c 100644
--- a/sysdeps/sparc/nptl/tls.h
+++ b/sysdeps/sparc/nptl/tls.h
@@ -63,15 +63,9 @@ register struct pthread *__thread_self __asm__("%g7");
struct pthread even when not linked with -lpthread. */
# define TLS_INIT_TCB_SIZE sizeof (struct pthread)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE sizeof (struct pthread)
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* The TCB can have any size and the memory following the address the
thread pointer points to is unspecified. Allocate the TCB there. */
# define TLS_TCB_AT_TP 1
diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h
index 3af1836e28b26fdb..50f7e8b544f9e6fc 100644
--- a/sysdeps/x86_64/nptl/tls.h
+++ b/sysdeps/x86_64/nptl/tls.h
@@ -106,15 +106,9 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80,
struct pthread even when not linked with -lpthread. */
# define TLS_INIT_TCB_SIZE sizeof (struct pthread)
-/* Alignment requirements for the initial TCB. */
-# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
-
/* This is the size of the TCB. */
# define TLS_TCB_SIZE sizeof (struct pthread)
-/* Alignment requirements for the TCB. */
-# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-
/* The TCB can have any size and the memory following the address the
thread pointer points to is unspecified. Allocate the TCB there. */
# define TLS_TCB_AT_TP 1

@ -0,0 +1,73 @@
commit cb976fba4c51ede7bf8cee5035888527c308dfbc
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Dec 15 16:06:25 2021 +0100
powerpc: Use global register variable in <thread_pointer.h>
A local register variable is merely a compiler hint, and so not
appropriate in this context. Move the global register variable into
<thread_pointer.h> and include it from <tls.h>, as there can only
be one global definition for one particular register.
Fixes commit 8dbeb0561eeb876f557ac9eef5721912ec074ea5
("nptl: Add <thread_pointer.h> for defining __thread_pointer").
Reported-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Reviewed-by: Raphael M Zinsly <rzinsly@linux.ibm.com>
diff --git a/sysdeps/powerpc/nptl/thread_pointer.h b/sysdeps/powerpc/nptl/thread_pointer.h
index 8fd5ba671f6f5e64..4feba5961062cfaf 100644
--- a/sysdeps/powerpc/nptl/thread_pointer.h
+++ b/sysdeps/powerpc/nptl/thread_pointer.h
@@ -19,15 +19,16 @@
#ifndef _SYS_THREAD_POINTER_H
#define _SYS_THREAD_POINTER_H
-static inline void *
-__thread_pointer (void)
-{
#ifdef __powerpc64__
- register void *__result asm ("r13");
+register void *__thread_register asm ("r13");
#else
- register void *__result asm ("r2");
+register void *__thread_register asm ("r2");
#endif
- return __result;
+
+static inline void *
+__thread_pointer (void)
+{
+ return __thread_register;
}
#endif /* _SYS_THREAD_POINTER_H */
diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h
index e194b334216eaa02..050beb06a8f7de65 100644
--- a/sysdeps/powerpc/nptl/tls.h
+++ b/sysdeps/powerpc/nptl/tls.h
@@ -26,6 +26,7 @@
# include <stddef.h>
# include <stdint.h>
# include <dl-dtv.h>
+# include <thread_pointer.h>
#else /* __ASSEMBLER__ */
# include <tcb-offsets.h>
@@ -36,16 +37,10 @@
#ifndef __powerpc64__
/* Register r2 (tp) is reserved by the ABI as "thread pointer". */
# define PT_THREAD_POINTER PT_R2
-# ifndef __ASSEMBLER__
-register void *__thread_register __asm__ ("r2");
-# endif
#else /* __powerpc64__ */
/* Register r13 (tp) is reserved by the ABI as "thread pointer". */
# define PT_THREAD_POINTER PT_R13
-# ifndef __ASSEMBLER__
-register void *__thread_register __asm__ ("r13");
-# endif
#endif /* __powerpc64__ */
#ifndef __ASSEMBLER__

@ -0,0 +1,42 @@
Downstream-only patch to disable rseq by default. This is necessary
because CRIU does not yet support rseq:
criu: Implement rseq support
<https://bugzilla.redhat.com/show_bug.cgi?id=2033446>
diff --git a/manual/tunables.texi b/manual/tunables.texi
index 28ff502990c2a10f..f559c44dcec4624b 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -425,11 +425,13 @@ The value is measured in bytes. The default is @samp{41943040}
@end deftp
@deftp Tunable glibc.pthread.rseq
-The @code{glibc.pthread.rseq} tunable can be set to @samp{0}, to disable
-restartable sequences support in @theglibc{}. This enables applications
-to perform direct restartable sequence registration with the kernel.
-The default is @samp{1}, which means that @theglibc{} performs
-registration on behalf of the application.
+The @code{glibc.pthread.rseq} tunable can be set to @samp{1}, to enable
+restartable sequences support. @Theglibc{} uses this to optimize the
+@code{sched_getcpu} function.
+
+The default is @samp{0}, which means that applications can perform
+restartable sequences registration, but @code{sched_getcpu} is not
+accelerated.
Restartable sequences are a Linux-specific extension.
@end deftp
diff --git a/sysdeps/nptl/dl-tunables.list b/sysdeps/nptl/dl-tunables.list
index d24f4be0d08ba407..df2a39ce01858d3b 100644
--- a/sysdeps/nptl/dl-tunables.list
+++ b/sysdeps/nptl/dl-tunables.list
@@ -31,7 +31,7 @@ glibc {
type: INT_32
minval: 0
maxval: 1
- default: 1
+ default: 0
}
}
}

@ -0,0 +1,259 @@
commit 23c77f60181eb549f11ec2f913b4270af29eee38
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Dec 3 16:28:07 2021 +0100
nptl: Increase default TCB alignment to 32
rseq support will use a 32-byte aligned field in struct pthread,
so the whole struct needs to have at least that alignment.
nptl/tst-tls3mod.c uses TCB_ALIGNMENT, therefore include <descr.h>
to obtain the fallback definition.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
diff --git a/nptl/descr.h b/nptl/descr.h
index 4de84138fb960fa4..57be5b4fef564b36 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -37,7 +37,9 @@
#include <tls-internal-struct.h>
#ifndef TCB_ALIGNMENT
-# define TCB_ALIGNMENT sizeof (double)
+# define TCB_ALIGNMENT 32
+#elif TCB_ALIGNMENT < 32
+# error TCB_ALIGNMENT must be at least 32
#endif
diff --git a/nptl/tst-tls3mod.c b/nptl/tst-tls3mod.c
index cfd13aace1affcd5..77dcc550fc3b5017 100644
--- a/nptl/tst-tls3mod.c
+++ b/nptl/tst-tls3mod.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <pthreaddef.h>
+#include <descr.h>
extern pthread_barrier_t b;
diff --git a/sysdeps/aarch64/nptl/pthreaddef.h b/sysdeps/aarch64/nptl/pthreaddef.h
index 4d5ecf6661fd0fe6..8d9a10622d132a7a 100644
--- a/sysdeps/aarch64/nptl/pthreaddef.h
+++ b/sysdeps/aarch64/nptl/pthreaddef.h
@@ -28,8 +28,5 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 2048
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 16
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/alpha/nptl/pthreaddef.h b/sysdeps/alpha/nptl/pthreaddef.h
index 25edb5093e095548..660e5694a25ec60f 100644
--- a/sysdeps/alpha/nptl/pthreaddef.h
+++ b/sysdeps/alpha/nptl/pthreaddef.h
@@ -27,8 +27,5 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 4096
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 16
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/arc/nptl/pthreaddef.h b/sysdeps/arc/nptl/pthreaddef.h
index 873b9d149ac46a62..d4dbe9e079445353 100644
--- a/sysdeps/arc/nptl/pthreaddef.h
+++ b/sysdeps/arc/nptl/pthreaddef.h
@@ -28,8 +28,5 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 2048
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 4
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/arm/nptl/pthreaddef.h b/sysdeps/arm/nptl/pthreaddef.h
index 332f4079c4c3f2bf..13769f5ae270b0ca 100644
--- a/sysdeps/arm/nptl/pthreaddef.h
+++ b/sysdeps/arm/nptl/pthreaddef.h
@@ -28,9 +28,6 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 2048
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 16
-
/* Location of current stack frame.
diff --git a/sysdeps/csky/nptl/pthreaddef.h b/sysdeps/csky/nptl/pthreaddef.h
index e78bc0016b43b450..7dde9131b9b1a6b0 100644
--- a/sysdeps/csky/nptl/pthreaddef.h
+++ b/sysdeps/csky/nptl/pthreaddef.h
@@ -28,8 +28,5 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 2048
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 8
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/ia64/nptl/pthreaddef.h b/sysdeps/ia64/nptl/pthreaddef.h
index 3a0f6daf9ad871aa..c7420fd1e4ee6081 100644
--- a/sysdeps/ia64/nptl/pthreaddef.h
+++ b/sysdeps/ia64/nptl/pthreaddef.h
@@ -30,9 +30,6 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 16384
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 16
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME __stack_pointer
diff --git a/sysdeps/m68k/nptl/pthreaddef.h b/sysdeps/m68k/nptl/pthreaddef.h
index 13e785a86bbf47b4..ce9511cb02da69fd 100644
--- a/sysdeps/m68k/nptl/pthreaddef.h
+++ b/sysdeps/m68k/nptl/pthreaddef.h
@@ -28,9 +28,6 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 2048
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 16
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/microblaze/nptl/pthreaddef.h b/sysdeps/microblaze/nptl/pthreaddef.h
index 517157444da556ad..19d7235782afde53 100644
--- a/sysdeps/microblaze/nptl/pthreaddef.h
+++ b/sysdeps/microblaze/nptl/pthreaddef.h
@@ -31,8 +31,5 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 2048
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 16
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/mips/nptl/pthreaddef.h b/sysdeps/mips/nptl/pthreaddef.h
index a7bccef6e512438f..322591c293ce5e15 100644
--- a/sysdeps/mips/nptl/pthreaddef.h
+++ b/sysdeps/mips/nptl/pthreaddef.h
@@ -27,9 +27,6 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 2048
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 16
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/nios2/nptl/pthreaddef.h b/sysdeps/nios2/nptl/pthreaddef.h
index e01a0e6df72c089a..aa0709d0dc69f251 100644
--- a/sysdeps/nios2/nptl/pthreaddef.h
+++ b/sysdeps/nios2/nptl/pthreaddef.h
@@ -28,8 +28,5 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 2048
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 4
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/powerpc/nptl/pthreaddef.h b/sysdeps/powerpc/nptl/pthreaddef.h
index ef5310e6315fde2c..117c35229ea68f48 100644
--- a/sysdeps/powerpc/nptl/pthreaddef.h
+++ b/sysdeps/powerpc/nptl/pthreaddef.h
@@ -28,9 +28,6 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 4096
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 16
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/riscv/nptl/pthreaddef.h b/sysdeps/riscv/nptl/pthreaddef.h
index 7bf93d6a63fdecd2..0f33cc48fe4fc728 100644
--- a/sysdeps/riscv/nptl/pthreaddef.h
+++ b/sysdeps/riscv/nptl/pthreaddef.h
@@ -28,8 +28,5 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 2048
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 16
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/s390/nptl/pthreaddef.h b/sysdeps/s390/nptl/pthreaddef.h
index 091f82df24a4024c..0e32bd862f7fea48 100644
--- a/sysdeps/s390/nptl/pthreaddef.h
+++ b/sysdeps/s390/nptl/pthreaddef.h
@@ -28,9 +28,6 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 2048
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 16
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/sh/nptl/pthreaddef.h b/sysdeps/sh/nptl/pthreaddef.h
index 3fa3d189ef969c90..f4e3a290df4ee6e6 100644
--- a/sysdeps/sh/nptl/pthreaddef.h
+++ b/sysdeps/sh/nptl/pthreaddef.h
@@ -29,9 +29,6 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 2048
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 8
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME __builtin_frame_address (0)
diff --git a/sysdeps/sparc/sparc32/pthreaddef.h b/sysdeps/sparc/sparc32/pthreaddef.h
index 6526fb3d6e7e1448..7a0a04789dac478e 100644
--- a/sysdeps/sparc/sparc32/pthreaddef.h
+++ b/sysdeps/sparc/sparc32/pthreaddef.h
@@ -27,9 +27,6 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 2048
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 16
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME (stack_pointer + (2 * 64))
diff --git a/sysdeps/sparc/sparc64/pthreaddef.h b/sysdeps/sparc/sparc64/pthreaddef.h
index 3da9d7afc8054598..103842856d40432b 100644
--- a/sysdeps/sparc/sparc64/pthreaddef.h
+++ b/sysdeps/sparc/sparc64/pthreaddef.h
@@ -27,10 +27,6 @@
/* Minimal stack size after allocating thread descriptor and guard size. */
#define MINIMAL_REST_STACK 4096
-/* Alignment requirement for TCB. */
-#define TCB_ALIGNMENT 16
-
-
/* Location of current stack frame. */
#define CURRENT_STACK_FRAME (stack_pointer + (2 * 128))
register char *stack_pointer __asm__("%sp");

@ -0,0 +1,150 @@
commit 4fb4e7e821e36180835bf88e363f9f13b5797e3a
Author: Florian Weimer <fweimer@redhat.com>
Date: Sun Dec 5 13:50:17 2021 +0100
csu: Always use __executable_start in gmon-start.c
Current binutils defines __executable_start as the lowest text
address, so using the entry point address as a fallback is no
longer necessary. As a result, overriding <entry.h> is only
necessary if the entry point is not called _start.
The previous approach to define __ASSEMBLY__ to suppress the
declaration breaks if headers included by <entry.h> are not
compatible with __ASSEMBLY__. This happens with rseq integration
because it is necessary to include kernel headers in more places.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
diff --git a/csu/gmon-start.c b/csu/gmon-start.c
index 344606a676c188d4..260c7613e291a32d 100644
--- a/csu/gmon-start.c
+++ b/csu/gmon-start.c
@@ -38,32 +38,12 @@
#include <stdlib.h>
#include <unistd.h>
#include <elf-initfini.h>
-#define __ASSEMBLY__
-#include <entry.h>
-
-/* Beginning and end of our code segment. We cannot declare them
- as the external functions since we want the addresses of those
- labels. Taking the address of a function may have different
- meanings on different platforms. */
-#ifdef ENTRY_POINT_DECL
-ENTRY_POINT_DECL(extern)
-#else
-extern char ENTRY_POINT[];
-#endif
-extern char etext[];
/* Use __executable_start as the lowest address to keep profiling records
if it provided by the linker. */
-extern const char executable_start[] asm ("__executable_start")
- __attribute__ ((weak, visibility ("hidden")));
+extern const char __executable_start[] __attribute__ ((visibility ("hidden")));
-#ifndef TEXT_START
-# ifdef ENTRY_POINT_DECL
-# define TEXT_START ENTRY_POINT
-# else
-# define TEXT_START &ENTRY_POINT
-# endif
-#endif
+extern char etext[];
#if !ELF_INITFINI
/* Instead of defining __gmon_start__ globally in gcrt1.o, we make it
@@ -97,10 +77,7 @@ __gmon_start__ (void)
called = 1;
/* Start keeping profiling records. */
- if (&executable_start != NULL)
- __monstartup ((u_long) &executable_start, (u_long) &etext);
- else
- __monstartup ((u_long) TEXT_START, (u_long) &etext);
+ __monstartup ((u_long) &__executable_start, (u_long) &etext);
/* Call _mcleanup before exiting; it will write out gmon.out from the
collected data. */
diff --git a/sysdeps/hppa/entry.h b/sysdeps/hppa/entry.h
deleted file mode 100644
index 5ea5b47448ceb2e7..0000000000000000
--- a/sysdeps/hppa/entry.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ASSEMBLY__
-extern void _start (void);
-#endif
-
-/* Lives in libgcc.so and canonicalizes function pointers for comparison. */
-extern unsigned int __canonicalize_funcptr_for_compare (unsigned int fptr);
-
-/* The function's entry point is stored in the first word of the
- function descriptor (plabel) of _start(). */
-#define ENTRY_POINT __canonicalize_funcptr_for_compare((unsigned int)_start)
-
-/* We have to provide a special declaration. */
-#define ENTRY_POINT_DECL(class) class void _start (void);
diff --git a/sysdeps/ia64/entry.h b/sysdeps/ia64/entry.h
deleted file mode 100644
index e11b49fc53602eb8..0000000000000000
--- a/sysdeps/ia64/entry.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <link.h>
-#include <dl-fptr.h>
-
-#ifndef __ASSEMBLY__
-extern void _start (void);
-#endif
-
-/* The function's entry point is stored in the first word of the
- function descriptor (plabel) of _start(). */
-#define ENTRY_POINT ELF_PTR_TO_FDESC (_start)->ip
-
-/* We have to provide a special declaration. */
-#define ENTRY_POINT_DECL(class) class void _start (void);
diff --git a/sysdeps/powerpc/powerpc64/entry.h b/sysdeps/powerpc/powerpc64/entry.h
deleted file mode 100644
index 99c81cb9820d188d..0000000000000000
--- a/sysdeps/powerpc/powerpc64/entry.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Finding the entry point and start of text. PowerPC64 version.
- Copyright (C) 2002-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 __ASSEMBLY__
-extern void _start (void);
-#endif
-
-#define ENTRY_POINT _start
-
-#if _CALL_ELF != 2
-/* We have to provide a special declaration. */
-#define ENTRY_POINT_DECL(class) class void _start (void);
-
-/* Use the address of ._start as the lowest address for which we need
- to keep profiling records. We can't copy the ia64 scheme as our
- entry poiny address is really the address of the function
- descriptor, not the actual function entry. */
-#define TEXT_START \
- ({ extern unsigned long int _start_as_data[] asm ("_start"); \
- _start_as_data[0]; })
-#endif

@ -0,0 +1,130 @@
commit 8dbeb0561eeb876f557ac9eef5721912ec074ea5
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Dec 9 09:49:32 2021 +0100
nptl: Add <thread_pointer.h> for defining __thread_pointer
<tls.h> already contains a definition that is quite similar,
but it is not consistent across architectures.
Only architectures for which rseq support is added are covered.
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
diff --git a/sysdeps/nptl/thread_pointer.h b/sysdeps/nptl/thread_pointer.h
new file mode 100644
index 0000000000000000..92f2f3093eba55bb
--- /dev/null
+++ b/sysdeps/nptl/thread_pointer.h
@@ -0,0 +1,28 @@
+/* __thread_pointer definition. Generic 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/>. */
+
+#ifndef _SYS_THREAD_POINTER_H
+#define _SYS_THREAD_POINTER_H
+
+static inline void *
+__thread_pointer (void)
+{
+ return __builtin_thread_pointer ();
+}
+
+#endif /* _SYS_THREAD_POINTER_H */
diff --git a/sysdeps/powerpc/nptl/thread_pointer.h b/sysdeps/powerpc/nptl/thread_pointer.h
new file mode 100644
index 0000000000000000..8fd5ba671f6f5e64
--- /dev/null
+++ b/sysdeps/powerpc/nptl/thread_pointer.h
@@ -0,0 +1,33 @@
+/* __thread_pointer definition. powerpc 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/>. */
+
+#ifndef _SYS_THREAD_POINTER_H
+#define _SYS_THREAD_POINTER_H
+
+static inline void *
+__thread_pointer (void)
+{
+#ifdef __powerpc64__
+ register void *__result asm ("r13");
+#else
+ register void *__result asm ("r2");
+#endif
+ return __result;
+}
+
+#endif /* _SYS_THREAD_POINTER_H */
diff --git a/sysdeps/x86/nptl/thread_pointer.h b/sysdeps/x86/nptl/thread_pointer.h
new file mode 100644
index 0000000000000000..6b71b6f7e1401e4c
--- /dev/null
+++ b/sysdeps/x86/nptl/thread_pointer.h
@@ -0,0 +1,38 @@
+/* __thread_pointer definition. 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/>. */
+
+#ifndef _SYS_THREAD_POINTER_H
+#define _SYS_THREAD_POINTER_H
+
+static inline void *
+__thread_pointer (void)
+{
+#if __GNUC_PREREQ (11, 1)
+ return __builtin_thread_pointer ();
+#else
+ void *__result;
+# ifdef __x86_64__
+ __asm__ ("mov %%fs:0, %0" : "=r" (__result));
+# else
+ __asm__ ("mov %%gs:0, %0" : "=r" (__result));
+# endif
+ return __result;
+#endif /* !GCC 11 */
+}
+
+#endif /* _SYS_THREAD_POINTER_H */

@ -0,0 +1,904 @@
commit ce2248ab91b2ea09a378f85012f251f31ac65e31
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Dec 9 09:49:32 2021 +0100
nptl: Introduce <tcb-access.h> for THREAD_* accessors
These are common between most architectures. Only the x86 targets
are outliers.
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
diff --git a/sysdeps/aarch64/nptl/tls.h b/sysdeps/aarch64/nptl/tls.h
index 6e896207a659514f..cd9abb5d1d073593 100644
--- a/sysdeps/aarch64/nptl/tls.h
+++ b/sysdeps/aarch64/nptl/tls.h
@@ -98,15 +98,7 @@ typedef struct
# define DB_THREAD_SELF \
CONST_THREAD_AREA (64, sizeof (struct pthread))
-/* Access to data in the thread descriptor is easy. */
-# define THREAD_GETMEM(descr, member) \
- descr->member
-# define THREAD_GETMEM_NC(descr, member, idx) \
- descr->member[idx]
-# define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-# define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
/* Get and set the global scope generation counter in struct pthread. */
# define THREAD_GSCOPE_IN_TCB 1
diff --git a/sysdeps/alpha/nptl/tls.h b/sysdeps/alpha/nptl/tls.h
index 4dbccc5249539325..5f4843b28e7f1ad1 100644
--- a/sysdeps/alpha/nptl/tls.h
+++ b/sysdeps/alpha/nptl/tls.h
@@ -92,15 +92,7 @@ typedef struct
# define DB_THREAD_SELF \
REGISTER (64, 64, 32 * 8, -sizeof (struct pthread))
-/* Access to data in the thread descriptor is easy. */
-#define THREAD_GETMEM(descr, member) \
- descr->member
-#define THREAD_GETMEM_NC(descr, member, idx) \
- descr->member[idx]
-#define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-#define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
/* Get and set the global scope generation counter in struct pthread. */
#define THREAD_GSCOPE_IN_TCB 1
diff --git a/sysdeps/arc/nptl/tls.h b/sysdeps/arc/nptl/tls.h
index 95300fdd2159dc53..d9ada2f38089e6cd 100644
--- a/sysdeps/arc/nptl/tls.h
+++ b/sysdeps/arc/nptl/tls.h
@@ -100,15 +100,7 @@ typedef struct
# define DB_THREAD_SELF \
CONST_THREAD_AREA (32, sizeof (struct pthread))
-/* Access to data in the thread descriptor is easy. */
-# define THREAD_GETMEM(descr, member) \
- descr->member
-# define THREAD_GETMEM_NC(descr, member, idx) \
- descr->member[idx]
-# define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-# define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
/* Get and set the global scope generation counter in struct pthread. */
#define THREAD_GSCOPE_IN_TCB 1
diff --git a/sysdeps/arm/nptl/tls.h b/sysdeps/arm/nptl/tls.h
index 1bd11307ce0a7f0a..354aae3318291395 100644
--- a/sysdeps/arm/nptl/tls.h
+++ b/sysdeps/arm/nptl/tls.h
@@ -89,15 +89,7 @@ typedef struct
# define DB_THREAD_SELF \
CONST_THREAD_AREA (32, sizeof (struct pthread))
-/* Access to data in the thread descriptor is easy. */
-#define THREAD_GETMEM(descr, member) \
- descr->member
-#define THREAD_GETMEM_NC(descr, member, idx) \
- descr->member[idx]
-#define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-#define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
/* Get and set the global scope generation counter in struct pthread. */
#define THREAD_GSCOPE_IN_TCB 1
diff --git a/sysdeps/csky/nptl/tls.h b/sysdeps/csky/nptl/tls.h
index 7a234041ed0bff39..f3fa3fcb02748776 100644
--- a/sysdeps/csky/nptl/tls.h
+++ b/sysdeps/csky/nptl/tls.h
@@ -116,15 +116,7 @@ typedef struct
# define DB_THREAD_SELF \
CONST_THREAD_AREA (32, sizeof (struct pthread))
-/* Access to data in the thread descriptor is easy. */
-# define THREAD_GETMEM(descr, member) \
- descr->member
-# define THREAD_GETMEM_NC(descr, member, idx) \
- descr->member[idx]
-# define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-# define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
/* Get and set the global scope generation counter in struct pthread. */
# define THREAD_GSCOPE_IN_TCB 1
diff --git a/sysdeps/hppa/nptl/tls.h b/sysdeps/hppa/nptl/tls.h
index 857003a7d35073eb..f0e274c45fb5e91e 100644
--- a/sysdeps/hppa/nptl/tls.h
+++ b/sysdeps/hppa/nptl/tls.h
@@ -107,15 +107,7 @@ typedef struct
# define DB_THREAD_SELF \
REGISTER (32, 32, 53 * 4, -sizeof (struct pthread))
-/* Access to data in the thread descriptor is easy. */
-# define THREAD_GETMEM(descr, member) \
- descr->member
-# define THREAD_GETMEM_NC(descr, member, idx) \
- descr->member[idx]
-# define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-# define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
static inline struct pthread *__get_cr27(void)
{
diff --git a/sysdeps/i386/nptl/tcb-access.h b/sysdeps/i386/nptl/tcb-access.h
new file mode 100644
index 0000000000000000..6c6d561e394817c7
--- /dev/null
+++ b/sysdeps/i386/nptl/tcb-access.h
@@ -0,0 +1,123 @@
+/* THREAD_* accessors. i386 version.
+ Copyright (C) 2002-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/>. */
+
+/* Read member of the thread descriptor directly. */
+#define THREAD_GETMEM(descr, member) \
+ ({ __typeof (descr->member) __value; \
+ _Static_assert (sizeof (__value) == 1 \
+ || sizeof (__value) == 4 \
+ || sizeof (__value) == 8, \
+ "size of per-thread data"); \
+ if (sizeof (__value) == 1) \
+ asm volatile ("movb %%gs:%P2,%b0" \
+ : "=q" (__value) \
+ : "0" (0), "i" (offsetof (struct pthread, member))); \
+ else if (sizeof (__value) == 4) \
+ asm volatile ("movl %%gs:%P1,%0" \
+ : "=r" (__value) \
+ : "i" (offsetof (struct pthread, member))); \
+ else /* 8 */ \
+ { \
+ asm volatile ("movl %%gs:%P1,%%eax\n\t" \
+ "movl %%gs:%P2,%%edx" \
+ : "=A" (__value) \
+ : "i" (offsetof (struct pthread, member)), \
+ "i" (offsetof (struct pthread, member) + 4)); \
+ } \
+ __value; })
+
+
+/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
+#define THREAD_GETMEM_NC(descr, member, idx) \
+ ({ __typeof (descr->member[0]) __value; \
+ _Static_assert (sizeof (__value) == 1 \
+ || sizeof (__value) == 4 \
+ || sizeof (__value) == 8, \
+ "size of per-thread data"); \
+ if (sizeof (__value) == 1) \
+ asm volatile ("movb %%gs:%P2(%3),%b0" \
+ : "=q" (__value) \
+ : "0" (0), "i" (offsetof (struct pthread, member[0])), \
+ "r" (idx)); \
+ else if (sizeof (__value) == 4) \
+ asm volatile ("movl %%gs:%P1(,%2,4),%0" \
+ : "=r" (__value) \
+ : "i" (offsetof (struct pthread, member[0])), \
+ "r" (idx)); \
+ else /* 8 */ \
+ { \
+ asm volatile ("movl %%gs:%P1(,%2,8),%%eax\n\t" \
+ "movl %%gs:4+%P1(,%2,8),%%edx" \
+ : "=&A" (__value) \
+ : "i" (offsetof (struct pthread, member[0])), \
+ "r" (idx)); \
+ } \
+ __value; })
+
+
+
+/* Set member of the thread descriptor directly. */
+#define THREAD_SETMEM(descr, member, value) \
+ ({ \
+ _Static_assert (sizeof (descr->member) == 1 \
+ || sizeof (descr->member) == 4 \
+ || sizeof (descr->member) == 8, \
+ "size of per-thread data"); \
+ if (sizeof (descr->member) == 1) \
+ asm volatile ("movb %b0,%%gs:%P1" : \
+ : "iq" (value), \
+ "i" (offsetof (struct pthread, member))); \
+ else if (sizeof (descr->member) == 4) \
+ asm volatile ("movl %0,%%gs:%P1" : \
+ : "ir" (value), \
+ "i" (offsetof (struct pthread, member))); \
+ else /* 8 */ \
+ { \
+ asm volatile ("movl %%eax,%%gs:%P1\n\t" \
+ "movl %%edx,%%gs:%P2" : \
+ : "A" ((uint64_t) cast_to_integer (value)), \
+ "i" (offsetof (struct pthread, member)), \
+ "i" (offsetof (struct pthread, member) + 4)); \
+ }})
+
+
+/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
+#define THREAD_SETMEM_NC(descr, member, idx, value) \
+ ({ \
+ _Static_assert (sizeof (descr->member[0]) == 1 \
+ || sizeof (descr->member[0]) == 4 \
+ || sizeof (descr->member[0]) == 8, \
+ "size of per-thread data"); \
+ if (sizeof (descr->member[0]) == 1) \
+ asm volatile ("movb %b0,%%gs:%P1(%2)" : \
+ : "iq" (value), \
+ "i" (offsetof (struct pthread, member)), \
+ "r" (idx)); \
+ else if (sizeof (descr->member[0]) == 4) \
+ asm volatile ("movl %0,%%gs:%P1(,%2,4)" : \
+ : "ir" (value), \
+ "i" (offsetof (struct pthread, member)), \
+ "r" (idx)); \
+ else /* 8 */ \
+ { \
+ asm volatile ("movl %%eax,%%gs:%P1(,%2,8)\n\t" \
+ "movl %%edx,%%gs:4+%P1(,%2,8)" : \
+ : "A" ((uint64_t) cast_to_integer (value)), \
+ "i" (offsetof (struct pthread, member)), \
+ "r" (idx)); \
+ }})
diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h
index 86ee1ef30270f960..111c9ee59df30bc3 100644
--- a/sysdeps/i386/nptl/tls.h
+++ b/sysdeps/i386/nptl/tls.h
@@ -250,113 +250,7 @@ tls_fill_user_desc (union user_desc_init *desc,
REGISTER_THREAD_AREA (32, offsetof (struct user_regs_struct, xgs), 3) \
REGISTER_THREAD_AREA (64, 26 * 8, 3) /* x86-64's user_regs_struct->gs */
-
-/* Read member of the thread descriptor directly. */
-# define THREAD_GETMEM(descr, member) \
- ({ __typeof (descr->member) __value; \
- _Static_assert (sizeof (__value) == 1 \
- || sizeof (__value) == 4 \
- || sizeof (__value) == 8, \
- "size of per-thread data"); \
- if (sizeof (__value) == 1) \
- asm volatile ("movb %%gs:%P2,%b0" \
- : "=q" (__value) \
- : "0" (0), "i" (offsetof (struct pthread, member))); \
- else if (sizeof (__value) == 4) \
- asm volatile ("movl %%gs:%P1,%0" \
- : "=r" (__value) \
- : "i" (offsetof (struct pthread, member))); \
- else /* 8 */ \
- { \
- asm volatile ("movl %%gs:%P1,%%eax\n\t" \
- "movl %%gs:%P2,%%edx" \
- : "=A" (__value) \
- : "i" (offsetof (struct pthread, member)), \
- "i" (offsetof (struct pthread, member) + 4)); \
- } \
- __value; })
-
-
-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
-# define THREAD_GETMEM_NC(descr, member, idx) \
- ({ __typeof (descr->member[0]) __value; \
- _Static_assert (sizeof (__value) == 1 \
- || sizeof (__value) == 4 \
- || sizeof (__value) == 8, \
- "size of per-thread data"); \
- if (sizeof (__value) == 1) \
- asm volatile ("movb %%gs:%P2(%3),%b0" \
- : "=q" (__value) \
- : "0" (0), "i" (offsetof (struct pthread, member[0])), \
- "r" (idx)); \
- else if (sizeof (__value) == 4) \
- asm volatile ("movl %%gs:%P1(,%2,4),%0" \
- : "=r" (__value) \
- : "i" (offsetof (struct pthread, member[0])), \
- "r" (idx)); \
- else /* 8 */ \
- { \
- asm volatile ("movl %%gs:%P1(,%2,8),%%eax\n\t" \
- "movl %%gs:4+%P1(,%2,8),%%edx" \
- : "=&A" (__value) \
- : "i" (offsetof (struct pthread, member[0])), \
- "r" (idx)); \
- } \
- __value; })
-
-
-
-/* Set member of the thread descriptor directly. */
-# define THREAD_SETMEM(descr, member, value) \
- ({ \
- _Static_assert (sizeof (descr->member) == 1 \
- || sizeof (descr->member) == 4 \
- || sizeof (descr->member) == 8, \
- "size of per-thread data"); \
- if (sizeof (descr->member) == 1) \
- asm volatile ("movb %b0,%%gs:%P1" : \
- : "iq" (value), \
- "i" (offsetof (struct pthread, member))); \
- else if (sizeof (descr->member) == 4) \
- asm volatile ("movl %0,%%gs:%P1" : \
- : "ir" (value), \
- "i" (offsetof (struct pthread, member))); \
- else /* 8 */ \
- { \
- asm volatile ("movl %%eax,%%gs:%P1\n\t" \
- "movl %%edx,%%gs:%P2" : \
- : "A" ((uint64_t) cast_to_integer (value)), \
- "i" (offsetof (struct pthread, member)), \
- "i" (offsetof (struct pthread, member) + 4)); \
- }})
-
-
-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
-# define THREAD_SETMEM_NC(descr, member, idx, value) \
- ({ \
- _Static_assert (sizeof (descr->member[0]) == 1 \
- || sizeof (descr->member[0]) == 4 \
- || sizeof (descr->member[0]) == 8, \
- "size of per-thread data"); \
- if (sizeof (descr->member[0]) == 1) \
- asm volatile ("movb %b0,%%gs:%P1(%2)" : \
- : "iq" (value), \
- "i" (offsetof (struct pthread, member)), \
- "r" (idx)); \
- else if (sizeof (descr->member[0]) == 4) \
- asm volatile ("movl %0,%%gs:%P1(,%2,4)" : \
- : "ir" (value), \
- "i" (offsetof (struct pthread, member)), \
- "r" (idx)); \
- else /* 8 */ \
- { \
- asm volatile ("movl %%eax,%%gs:%P1(,%2,8)\n\t" \
- "movl %%edx,%%gs:4+%P1(,%2,8)" : \
- : "A" ((uint64_t) cast_to_integer (value)), \
- "i" (offsetof (struct pthread, member)), \
- "r" (idx)); \
- }})
-
+# include <tcb-access.h>
/* Set the stack guard field in TCB head. */
#define THREAD_SET_STACK_GUARD(value) \
diff --git a/sysdeps/ia64/nptl/tls.h b/sysdeps/ia64/nptl/tls.h
index 66d9bf3189f0b727..26fe555cb4b5e164 100644
--- a/sysdeps/ia64/nptl/tls.h
+++ b/sysdeps/ia64/nptl/tls.h
@@ -128,15 +128,7 @@ register struct pthread *__thread_self __asm__("r13");
/* Magic for libthread_db to know how to do THREAD_SELF. */
# define DB_THREAD_SELF REGISTER (64, 64, 13 * 8, -TLS_PRE_TCB_SIZE)
-/* Access to data in the thread descriptor is easy. */
-#define THREAD_GETMEM(descr, member) \
- descr->member
-#define THREAD_GETMEM_NC(descr, member, idx) \
- descr->member[idx]
-#define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-#define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
/* Set the stack guard field in TCB head. */
#define THREAD_SET_STACK_GUARD(value) \
diff --git a/sysdeps/m68k/nptl/tls.h b/sysdeps/m68k/nptl/tls.h
index cfcd6d2b7b59321c..9f562c38288df200 100644
--- a/sysdeps/m68k/nptl/tls.h
+++ b/sysdeps/m68k/nptl/tls.h
@@ -118,15 +118,7 @@ extern void * __m68k_read_tp (void);
# define DB_THREAD_SELF \
CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
-/* Access to data in the thread descriptor is easy. */
-# define THREAD_GETMEM(descr, member) \
- descr->member
-# define THREAD_GETMEM_NC(descr, member, idx) \
- descr->member[idx]
-# define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-# define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
/* l_tls_offset == 0 is perfectly valid on M68K, so we have to use some
different value to mean unset l_tls_offset. */
diff --git a/sysdeps/microblaze/nptl/tls.h b/sysdeps/microblaze/nptl/tls.h
index c93d90b11bfe4c74..bfa6efa78049bb2d 100644
--- a/sysdeps/microblaze/nptl/tls.h
+++ b/sysdeps/microblaze/nptl/tls.h
@@ -100,20 +100,7 @@ typedef struct
# define DB_THREAD_SELF \
CONST_THREAD_AREA (32, sizeof (struct pthread))
-/* Read member of the thread descriptor directly. */
-# define THREAD_GETMEM(descr, member) (descr->member)
-
-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
-# define THREAD_GETMEM_NC(descr, member, idx) \
- (descr->member[idx])
-
-/* Set member of the thread descriptor directly. */
-# define THREAD_SETMEM(descr, member, value) \
- (descr->member = (value))
-
-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
-# define THREAD_SETMEM_NC(descr, member, idx, value) \
- (descr->member[idx] = (value))
+# include <tcb-access.h>
/* Get and set the global scope generation counter in struct pthread. */
# define THREAD_GSCOPE_IN_TCB 1
diff --git a/sysdeps/mips/nptl/tls.h b/sysdeps/mips/nptl/tls.h
index c09f49071cf3b5b9..ef99aa646c898e76 100644
--- a/sysdeps/mips/nptl/tls.h
+++ b/sysdeps/mips/nptl/tls.h
@@ -144,14 +144,7 @@ typedef struct
CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
/* Access to data in the thread descriptor is easy. */
-# define THREAD_GETMEM(descr, member) \
- descr->member
-# define THREAD_GETMEM_NC(descr, member, idx) \
- descr->member[idx]
-# define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-# define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
/* l_tls_offset == 0 is perfectly valid on MIPS, so we have to use some
different value to mean unset l_tls_offset. */
diff --git a/sysdeps/nios2/nptl/tls.h b/sysdeps/nios2/nptl/tls.h
index 02a05b4e741092bf..7110cfccad7131f4 100644
--- a/sysdeps/nios2/nptl/tls.h
+++ b/sysdeps/nios2/nptl/tls.h
@@ -112,15 +112,7 @@ register struct pthread *__thread_self __asm__("r23");
# define DB_THREAD_SELF \
REGISTER (32, 32, 23 * 4, -TLS_PRE_TCB_SIZE - TLS_TCB_OFFSET)
-/* Access to data in the thread descriptor is easy. */
-# define THREAD_GETMEM(descr, member) \
- descr->member
-# define THREAD_GETMEM_NC(descr, member, idx) \
- descr->member[idx]
-# define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-# define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
# define THREAD_GET_POINTER_GUARD() \
(((tcbhead_t *) (READ_THREAD_POINTER () \
diff --git a/sysdeps/nptl/tcb-access.h b/sysdeps/nptl/tcb-access.h
new file mode 100644
index 0000000000000000..b4137b8ab8067915
--- /dev/null
+++ b/sysdeps/nptl/tcb-access.h
@@ -0,0 +1,30 @@
+/* THREAD_* accessors. Generic version based on struct pthread pointers.
+ Copyright (C) 2002-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/>. */
+
+/* Note: These are for accessing the TCB of the *current* thread.
+ descr can be disregarded on some targets as an optimization. See
+ i386 for an example. */
+
+#define THREAD_GETMEM(descr, member) \
+ descr->member
+#define THREAD_GETMEM_NC(descr, member, idx) \
+ descr->member[idx]
+#define THREAD_SETMEM(descr, member, value) \
+ descr->member = (value)
+#define THREAD_SETMEM_NC(descr, member, idx, value) \
+ descr->member[idx] = (value)
diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h
index 6c779b6609147d54..110d085d30c86302 100644
--- a/sysdeps/powerpc/nptl/tls.h
+++ b/sysdeps/powerpc/nptl/tls.h
@@ -176,20 +176,7 @@ typedef struct
REGISTER (64, 64, PT_THREAD_POINTER * 8, \
- TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
-/* Read member of the thread descriptor directly. */
-# define THREAD_GETMEM(descr, member) ((void)(descr), (THREAD_SELF)->member)
-
-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
-# define THREAD_GETMEM_NC(descr, member, idx) \
- ((void)(descr), (THREAD_SELF)->member[idx])
-
-/* Set member of the thread descriptor directly. */
-# define THREAD_SETMEM(descr, member, value) \
- ((void)(descr), (THREAD_SELF)->member = (value))
-
-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
-# define THREAD_SETMEM_NC(descr, member, idx, value) \
- ((void)(descr), (THREAD_SELF)->member[idx] = (value))
+# include <tcb-access.h>
/* Set the stack guard field in TCB head. */
# define THREAD_SET_STACK_GUARD(value) \
diff --git a/sysdeps/riscv/nptl/tls.h b/sysdeps/riscv/nptl/tls.h
index 5350bcc0498bab69..bdc0a3a6f91b51e8 100644
--- a/sysdeps/riscv/nptl/tls.h
+++ b/sysdeps/riscv/nptl/tls.h
@@ -105,14 +105,7 @@ typedef struct
REGISTER (64, 64, 4 * 8, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
/* Access to data in the thread descriptor is easy. */
-# define THREAD_GETMEM(descr, member) \
- descr->member
-# define THREAD_GETMEM_NC(descr, member, idx) \
- descr->member[idx]
-# define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-# define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
/* l_tls_offset == 0 is perfectly valid, so we have to use some different
value to mean unset l_tls_offset. */
diff --git a/sysdeps/s390/nptl/tls.h b/sysdeps/s390/nptl/tls.h
index efb52515e05c06a9..2cdd18eb2907c060 100644
--- a/sysdeps/s390/nptl/tls.h
+++ b/sysdeps/s390/nptl/tls.h
@@ -135,15 +135,7 @@ typedef struct
# define DB_THREAD_SELF REGISTER (32, 32, 18 * 4, 0) \
REGISTER (64, __WORDSIZE, 18 * 8, 0)
-/* Access to data in the thread descriptor is easy. */
-#define THREAD_GETMEM(descr, member) \
- descr->member
-#define THREAD_GETMEM_NC(descr, member, idx) \
- descr->member[idx]
-#define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-#define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
/* Set the stack guard field in TCB head. */
#define THREAD_SET_STACK_GUARD(value) \
diff --git a/sysdeps/sh/nptl/tls.h b/sysdeps/sh/nptl/tls.h
index ac3c9a9e856ee686..390640020e45f716 100644
--- a/sysdeps/sh/nptl/tls.h
+++ b/sysdeps/sh/nptl/tls.h
@@ -113,19 +113,7 @@ typedef struct
# define DB_THREAD_SELF \
REGISTER (32, 32, REG_GBR * 4, -sizeof (struct pthread))
-/* Read member of the thread descriptor directly. */
-# define THREAD_GETMEM(descr, member) (descr->member)
-
-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
-# define THREAD_GETMEM_NC(descr, member, idx) (descr->member[idx])
-
-/* Set member of the thread descriptor directly. */
-# define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-
-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
-# define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
#define THREAD_GET_POINTER_GUARD() \
({ tcbhead_t *__tcbp; \
diff --git a/sysdeps/sparc/nptl/tls.h b/sysdeps/sparc/nptl/tls.h
index dd1eb82a595619a9..376d729989e35660 100644
--- a/sysdeps/sparc/nptl/tls.h
+++ b/sysdeps/sparc/nptl/tls.h
@@ -112,15 +112,7 @@ register struct pthread *__thread_self __asm__("%g7");
REGISTER (32, 32, 10 * 4, 0) \
REGISTER (64, __WORDSIZE, (6 * 8) + (__WORDSIZE==64?0:4), 0)
-/* Access to data in the thread descriptor is easy. */
-#define THREAD_GETMEM(descr, member) \
- descr->member
-#define THREAD_GETMEM_NC(descr, member, idx) \
- descr->member[idx]
-#define THREAD_SETMEM(descr, member, value) \
- descr->member = (value)
-#define THREAD_SETMEM_NC(descr, member, idx, value) \
- descr->member[idx] = (value)
+# include <tcb-access.h>
/* Set the stack guard field in TCB head. */
#define THREAD_SET_STACK_GUARD(value) \
diff --git a/sysdeps/x86_64/nptl/tcb-access.h b/sysdeps/x86_64/nptl/tcb-access.h
new file mode 100644
index 0000000000000000..18848a729d16a4f5
--- /dev/null
+++ b/sysdeps/x86_64/nptl/tcb-access.h
@@ -0,0 +1,130 @@
+/* THREAD_* accessors. x86_64 version.
+ Copyright (C) 2002-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/>. */
+
+/* Read member of the thread descriptor directly. */
+# define THREAD_GETMEM(descr, member) \
+ ({ __typeof (descr->member) __value; \
+ _Static_assert (sizeof (__value) == 1 \
+ || sizeof (__value) == 4 \
+ || sizeof (__value) == 8, \
+ "size of per-thread data"); \
+ if (sizeof (__value) == 1) \
+ asm volatile ("movb %%fs:%P2,%b0" \
+ : "=q" (__value) \
+ : "0" (0), "i" (offsetof (struct pthread, member))); \
+ else if (sizeof (__value) == 4) \
+ asm volatile ("movl %%fs:%P1,%0" \
+ : "=r" (__value) \
+ : "i" (offsetof (struct pthread, member))); \
+ else /* 8 */ \
+ { \
+ asm volatile ("movq %%fs:%P1,%q0" \
+ : "=r" (__value) \
+ : "i" (offsetof (struct pthread, member))); \
+ } \
+ __value; })
+
+
+/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
+# define THREAD_GETMEM_NC(descr, member, idx) \
+ ({ __typeof (descr->member[0]) __value; \
+ _Static_assert (sizeof (__value) == 1 \
+ || sizeof (__value) == 4 \
+ || sizeof (__value) == 8, \
+ "size of per-thread data"); \
+ if (sizeof (__value) == 1) \
+ asm volatile ("movb %%fs:%P2(%q3),%b0" \
+ : "=q" (__value) \
+ : "0" (0), "i" (offsetof (struct pthread, member[0])), \
+ "r" (idx)); \
+ else if (sizeof (__value) == 4) \
+ asm volatile ("movl %%fs:%P1(,%q2,4),%0" \
+ : "=r" (__value) \
+ : "i" (offsetof (struct pthread, member[0])), "r" (idx));\
+ else /* 8 */ \
+ { \
+ asm volatile ("movq %%fs:%P1(,%q2,8),%q0" \
+ : "=r" (__value) \
+ : "i" (offsetof (struct pthread, member[0])), \
+ "r" (idx)); \
+ } \
+ __value; })
+
+
+/* Loading addresses of objects on x86-64 needs to be treated special
+ when generating PIC code. */
+#ifdef __pic__
+# define IMM_MODE "nr"
+#else
+# define IMM_MODE "ir"
+#endif
+
+
+/* Set member of the thread descriptor directly. */
+# define THREAD_SETMEM(descr, member, value) \
+ ({ \
+ _Static_assert (sizeof (descr->member) == 1 \
+ || sizeof (descr->member) == 4 \
+ || sizeof (descr->member) == 8, \
+ "size of per-thread data"); \
+ if (sizeof (descr->member) == 1) \
+ asm volatile ("movb %b0,%%fs:%P1" : \
+ : "iq" (value), \
+ "i" (offsetof (struct pthread, member))); \
+ else if (sizeof (descr->member) == 4) \
+ asm volatile ("movl %0,%%fs:%P1" : \
+ : IMM_MODE (value), \
+ "i" (offsetof (struct pthread, member))); \
+ else /* 8 */ \
+ { \
+ /* Since movq takes a signed 32-bit immediate or a register source \
+ operand, use "er" constraint for 32-bit signed integer constant \
+ or register. */ \
+ asm volatile ("movq %q0,%%fs:%P1" : \
+ : "er" ((uint64_t) cast_to_integer (value)), \
+ "i" (offsetof (struct pthread, member))); \
+ }})
+
+
+/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
+# define THREAD_SETMEM_NC(descr, member, idx, value) \
+ ({ \
+ _Static_assert (sizeof (descr->member[0]) == 1 \
+ || sizeof (descr->member[0]) == 4 \
+ || sizeof (descr->member[0]) == 8, \
+ "size of per-thread data"); \
+ if (sizeof (descr->member[0]) == 1) \
+ asm volatile ("movb %b0,%%fs:%P1(%q2)" : \
+ : "iq" (value), \
+ "i" (offsetof (struct pthread, member[0])), \
+ "r" (idx)); \
+ else if (sizeof (descr->member[0]) == 4) \
+ asm volatile ("movl %0,%%fs:%P1(,%q2,4)" : \
+ : IMM_MODE (value), \
+ "i" (offsetof (struct pthread, member[0])), \
+ "r" (idx)); \
+ else /* 8 */ \
+ { \
+ /* Since movq takes a signed 32-bit immediate or a register source \
+ operand, use "er" constraint for 32-bit signed integer constant \
+ or register. */ \
+ asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \
+ : "er" ((uint64_t) cast_to_integer (value)), \
+ "i" (offsetof (struct pthread, member[0])), \
+ "r" (idx)); \
+ }})
diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h
index a78c4f4d016002fa..3af1836e28b26fdb 100644
--- a/sysdeps/x86_64/nptl/tls.h
+++ b/sysdeps/x86_64/nptl/tls.h
@@ -195,119 +195,7 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80,
# define DB_THREAD_SELF_INCLUDE <sys/reg.h> /* For the FS constant. */
# define DB_THREAD_SELF CONST_THREAD_AREA (64, FS)
-/* Read member of the thread descriptor directly. */
-# define THREAD_GETMEM(descr, member) \
- ({ __typeof (descr->member) __value; \
- _Static_assert (sizeof (__value) == 1 \
- || sizeof (__value) == 4 \
- || sizeof (__value) == 8, \
- "size of per-thread data"); \
- if (sizeof (__value) == 1) \
- asm volatile ("movb %%fs:%P2,%b0" \
- : "=q" (__value) \
- : "0" (0), "i" (offsetof (struct pthread, member))); \
- else if (sizeof (__value) == 4) \
- asm volatile ("movl %%fs:%P1,%0" \
- : "=r" (__value) \
- : "i" (offsetof (struct pthread, member))); \
- else /* 8 */ \
- { \
- asm volatile ("movq %%fs:%P1,%q0" \
- : "=r" (__value) \
- : "i" (offsetof (struct pthread, member))); \
- } \
- __value; })
-
-
-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
-# define THREAD_GETMEM_NC(descr, member, idx) \
- ({ __typeof (descr->member[0]) __value; \
- _Static_assert (sizeof (__value) == 1 \
- || sizeof (__value) == 4 \
- || sizeof (__value) == 8, \
- "size of per-thread data"); \
- if (sizeof (__value) == 1) \
- asm volatile ("movb %%fs:%P2(%q3),%b0" \
- : "=q" (__value) \
- : "0" (0), "i" (offsetof (struct pthread, member[0])), \
- "r" (idx)); \
- else if (sizeof (__value) == 4) \
- asm volatile ("movl %%fs:%P1(,%q2,4),%0" \
- : "=r" (__value) \
- : "i" (offsetof (struct pthread, member[0])), "r" (idx));\
- else /* 8 */ \
- { \
- asm volatile ("movq %%fs:%P1(,%q2,8),%q0" \
- : "=r" (__value) \
- : "i" (offsetof (struct pthread, member[0])), \
- "r" (idx)); \
- } \
- __value; })
-
-
-/* Loading addresses of objects on x86-64 needs to be treated special
- when generating PIC code. */
-#ifdef __pic__
-# define IMM_MODE "nr"
-#else
-# define IMM_MODE "ir"
-#endif
-
-
-/* Set member of the thread descriptor directly. */
-# define THREAD_SETMEM(descr, member, value) \
- ({ \
- _Static_assert (sizeof (descr->member) == 1 \
- || sizeof (descr->member) == 4 \
- || sizeof (descr->member) == 8, \
- "size of per-thread data"); \
- if (sizeof (descr->member) == 1) \
- asm volatile ("movb %b0,%%fs:%P1" : \
- : "iq" (value), \
- "i" (offsetof (struct pthread, member))); \
- else if (sizeof (descr->member) == 4) \
- asm volatile ("movl %0,%%fs:%P1" : \
- : IMM_MODE (value), \
- "i" (offsetof (struct pthread, member))); \
- else /* 8 */ \
- { \
- /* Since movq takes a signed 32-bit immediate or a register source \
- operand, use "er" constraint for 32-bit signed integer constant \
- or register. */ \
- asm volatile ("movq %q0,%%fs:%P1" : \
- : "er" ((uint64_t) cast_to_integer (value)), \
- "i" (offsetof (struct pthread, member))); \
- }})
-
-
-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
-# define THREAD_SETMEM_NC(descr, member, idx, value) \
- ({ \
- _Static_assert (sizeof (descr->member[0]) == 1 \
- || sizeof (descr->member[0]) == 4 \
- || sizeof (descr->member[0]) == 8, \
- "size of per-thread data"); \
- if (sizeof (descr->member[0]) == 1) \
- asm volatile ("movb %b0,%%fs:%P1(%q2)" : \
- : "iq" (value), \
- "i" (offsetof (struct pthread, member[0])), \
- "r" (idx)); \
- else if (sizeof (descr->member[0]) == 4) \
- asm volatile ("movl %0,%%fs:%P1(,%q2,4)" : \
- : IMM_MODE (value), \
- "i" (offsetof (struct pthread, member[0])), \
- "r" (idx)); \
- else /* 8 */ \
- { \
- /* Since movq takes a signed 32-bit immediate or a register source \
- operand, use "er" constraint for 32-bit signed integer constant \
- or register. */ \
- asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \
- : "er" ((uint64_t) cast_to_integer (value)), \
- "i" (offsetof (struct pthread, member[0])), \
- "r" (idx)); \
- }})
-
+# include <tcb-access.h>
/* Set the stack guard field in TCB head. */
# define THREAD_SET_STACK_GUARD(value) \

@ -0,0 +1,49 @@
commit 8d1927d8dc5aad0f01c929123086be3a5b799d18
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Dec 9 09:49:32 2021 +0100
nptl: Introduce THREAD_GETMEM_VOLATILE
This will be needed for rseq TCB access.
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
diff --git a/sysdeps/i386/nptl/tcb-access.h b/sysdeps/i386/nptl/tcb-access.h
index 6c6d561e394817c7..5ddd83224bc8eb77 100644
--- a/sysdeps/i386/nptl/tcb-access.h
+++ b/sysdeps/i386/nptl/tcb-access.h
@@ -41,6 +41,8 @@
} \
__value; })
+/* THREAD_GETMEM already forces a read. */
+#define THREAD_GETMEM_VOLATILE(descr, member) THREAD_GETMEM (descr, member)
/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
#define THREAD_GETMEM_NC(descr, member, idx) \
diff --git a/sysdeps/nptl/tcb-access.h b/sysdeps/nptl/tcb-access.h
index b4137b8ab8067915..bbe20b7225b060fd 100644
--- a/sysdeps/nptl/tcb-access.h
+++ b/sysdeps/nptl/tcb-access.h
@@ -22,6 +22,8 @@
#define THREAD_GETMEM(descr, member) \
descr->member
+#define THREAD_GETMEM_VOLATILE(descr, member) \
+ (*(volatile __typeof (descr->member) *)&descr->member)
#define THREAD_GETMEM_NC(descr, member, idx) \
descr->member[idx]
#define THREAD_SETMEM(descr, member, value) \
diff --git a/sysdeps/x86_64/nptl/tcb-access.h b/sysdeps/x86_64/nptl/tcb-access.h
index 18848a729d16a4f5..e4d2d07a9b218025 100644
--- a/sysdeps/x86_64/nptl/tcb-access.h
+++ b/sysdeps/x86_64/nptl/tcb-access.h
@@ -39,6 +39,8 @@
} \
__value; })
+/* THREAD_GETMEM already forces a read. */
+#define THREAD_GETMEM_VOLATILE(descr, member) THREAD_GETMEM (descr, member)
/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
# define THREAD_GETMEM_NC(descr, member, idx) \

File diff suppressed because it is too large Load Diff

@ -0,0 +1,43 @@
commit 1d350aa06091211863e41169729cee1bca39f72f
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Dec 9 09:49:32 2021 +0100
Linux: Use rseq to accelerate sched_getcpu
Co-Authored-By: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
diff --git a/sysdeps/unix/sysv/linux/sched_getcpu.c b/sysdeps/unix/sysv/linux/sched_getcpu.c
index c41e986f2cab5e42..6f78edaea1495342 100644
--- a/sysdeps/unix/sysv/linux/sched_getcpu.c
+++ b/sysdeps/unix/sysv/linux/sched_getcpu.c
@@ -20,8 +20,8 @@
#include <sysdep.h>
#include <sysdep-vdso.h>
-int
-sched_getcpu (void)
+static int
+vsyscall_sched_getcpu (void)
{
unsigned int cpu;
int r = -1;
@@ -32,3 +32,18 @@ sched_getcpu (void)
#endif
return r == -1 ? r : cpu;
}
+
+#ifdef RSEQ_SIG
+int
+sched_getcpu (void)
+{
+ int cpu_id = THREAD_GETMEM_VOLATILE (THREAD_SELF, rseq_area.cpu_id);
+ return __glibc_likely (cpu_id >= 0) ? cpu_id : vsyscall_sched_getcpu ();
+}
+#else /* RSEQ_SIG */
+int
+sched_getcpu (void)
+{
+ return vsyscall_sched_getcpu ();
+}
+#endif /* RSEQ_SIG */

@ -0,0 +1,278 @@
commit e3e589829d16af9f7e73c7b70f74f3c5d5003e45
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Dec 9 09:49:32 2021 +0100
nptl: Add glibc.pthread.rseq tunable to control rseq registration
This tunable allows applications to register the rseq area instead
of glibc.
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
diff --git a/manual/tunables.texi b/manual/tunables.texi
index 658547c6137bf177..1f5c410288eeecec 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -413,6 +413,16 @@ The value is measured in bytes. The default is @samp{41943040}
(fourty mibibytes).
@end deftp
+@deftp Tunable glibc.pthread.rseq
+The @code{glibc.pthread.rseq} tunable can be set to @samp{0}, to disable
+restartable sequences support in @theglibc{}. This enables applications
+to perform direct restartable sequence registration with the kernel.
+The default is @samp{1}, which means that @theglibc{} performs
+registration on behalf of the application.
+
+Restartable sequences are a Linux-specific extension.
+@end deftp
+
@node Hardware Capability Tunables
@section Hardware Capability Tunables
@cindex hardware capability tunables
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index d2b40924dafad316..f405fa356c2955ce 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -369,7 +369,10 @@ start_thread (void *arg)
__ctype_init ();
/* Register rseq TLS to the kernel. */
- rseq_register_current_thread (pd);
+ {
+ bool do_rseq = THREAD_GETMEM (pd, flags) & ATTR_FLAG_DO_RSEQ;
+ rseq_register_current_thread (pd, do_rseq);
+ }
#ifndef __ASSUME_SET_ROBUST_LIST
if (__nptl_set_robust_list_avail)
@@ -678,6 +681,11 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
pd->flags = ((iattr->flags & ~(ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET))
| (self->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)));
+ /* Inherit rseq registration state. Without seccomp filters, rseq
+ registration will either always fail or always succeed. */
+ if ((int) THREAD_GETMEM_VOLATILE (self, rseq_area.cpu_id) >= 0)
+ pd->flags |= ATTR_FLAG_DO_RSEQ;
+
/* Initialize the field for the ID of the thread which is waiting
for us. This is a self-reference in case the thread is created
detached. */
diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
index fedb876fdb2642d2..b39dfbff2c6678d5 100644
--- a/sysdeps/nptl/dl-tls_init_tp.c
+++ b/sysdeps/nptl/dl-tls_init_tp.c
@@ -23,6 +23,9 @@
#include <tls.h>
#include <rseq-internal.h>
+#define TUNABLE_NAMESPACE pthread
+#include <dl-tunables.h>
+
#ifndef __ASSUME_SET_ROBUST_LIST
bool __nptl_set_robust_list_avail;
rtld_hidden_data_def (__nptl_set_robust_list_avail)
@@ -92,7 +95,13 @@ __tls_init_tp (void)
}
}
- rseq_register_current_thread (pd);
+ {
+ bool do_rseq = true;
+#if HAVE_TUNABLES
+ do_rseq = TUNABLE_GET (rseq, int, NULL);
+#endif
+ rseq_register_current_thread (pd, do_rseq);
+ }
/* Set initial thread's stack block from 0 up to __libc_stack_end.
It will be bigger than it actually is, but for unwind.c/pt-longjmp.c
diff --git a/sysdeps/nptl/dl-tunables.list b/sysdeps/nptl/dl-tunables.list
index ac5d053298725468..d24f4be0d08ba407 100644
--- a/sysdeps/nptl/dl-tunables.list
+++ b/sysdeps/nptl/dl-tunables.list
@@ -27,5 +27,11 @@ glibc {
type: SIZE_T
default: 41943040
}
+ rseq {
+ type: INT_32
+ minval: 0
+ maxval: 1
+ default: 1
+ }
}
}
diff --git a/sysdeps/nptl/internaltypes.h b/sysdeps/nptl/internaltypes.h
index 50a2ad19ae7210ae..8205c6d15a918952 100644
--- a/sysdeps/nptl/internaltypes.h
+++ b/sysdeps/nptl/internaltypes.h
@@ -49,6 +49,7 @@ struct pthread_attr
#define ATTR_FLAG_OLDATTR 0x0010
#define ATTR_FLAG_SCHED_SET 0x0020
#define ATTR_FLAG_POLICY_SET 0x0040
+#define ATTR_FLAG_DO_RSEQ 0x0080
/* Used to allocate a pthread_attr_t object which is also accessed
internally. */
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index f84ccd6bbb3b16ad..d30d21898b402d1e 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -135,6 +135,12 @@ tests-internal += \
tst-sigcontext-get_pc \
# tests-internal
+ifneq (no,$(have-tunables))
+tests-internal += \
+ tst-rseq-disable \
+ # tests-internal $(have-tunables)
+endif
+
tests-time64 += \
tst-adjtimex-time64 \
tst-clock_adjtime-time64 \
@@ -226,6 +232,8 @@ $(objpfx)tst-mman-consts.out: ../sysdeps/unix/sysv/linux/tst-mman-consts.py
< /dev/null > $@ 2>&1; $(evaluate-test)
$(objpfx)tst-mman-consts.out: $(sysdeps-linux-python-deps)
+tst-rseq-disable-ENV = GLIBC_TUNABLES=glibc.pthread.rseq=0
+
endif # $(subdir) == misc
ifeq ($(subdir),time)
diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
index 909f5478251d3d13..15bc7ffd6eda632d 100644
--- a/sysdeps/unix/sysv/linux/rseq-internal.h
+++ b/sysdeps/unix/sysv/linux/rseq-internal.h
@@ -21,22 +21,27 @@
#include <sysdep.h>
#include <errno.h>
#include <kernel-features.h>
+#include <stdbool.h>
#include <stdio.h>
#include <sys/rseq.h>
#ifdef RSEQ_SIG
static inline void
-rseq_register_current_thread (struct pthread *self)
+rseq_register_current_thread (struct pthread *self, bool do_rseq)
{
- int ret = INTERNAL_SYSCALL_CALL (rseq,
- &self->rseq_area, sizeof (self->rseq_area),
- 0, RSEQ_SIG);
- if (INTERNAL_SYSCALL_ERROR_P (ret))
- THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
+ if (do_rseq)
+ {
+ int ret = INTERNAL_SYSCALL_CALL (rseq, &self->rseq_area,
+ sizeof (self->rseq_area),
+ 0, RSEQ_SIG);
+ if (!INTERNAL_SYSCALL_ERROR_P (ret))
+ return;
+ }
+ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
}
#else /* RSEQ_SIG */
static inline void
-rseq_register_current_thread (struct pthread *self)
+rseq_register_current_thread (struct pthread *self, bool do_rseq)
{
THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
}
diff --git a/sysdeps/unix/sysv/linux/tst-rseq-disable.c b/sysdeps/unix/sysv/linux/tst-rseq-disable.c
new file mode 100644
index 0000000000000000..000e351872fc2f76
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-rseq-disable.c
@@ -0,0 +1,89 @@
+/* Test disabling of rseq registration via tunable.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+
+ 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 <stdio.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/xthread.h>
+#include <sysdep.h>
+#include <unistd.h>
+
+#ifdef RSEQ_SIG
+
+/* Check that rseq can be registered and has not been taken by glibc. */
+static void
+check_rseq_disabled (void)
+{
+ struct pthread *pd = THREAD_SELF;
+ TEST_COMPARE ((int) pd->rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
+
+ int ret = syscall (__NR_rseq, &pd->rseq_area, sizeof (pd->rseq_area),
+ 0, RSEQ_SIG);
+ if (ret == 0)
+ {
+ ret = syscall (__NR_rseq, &pd->rseq_area, sizeof (pd->rseq_area),
+ RSEQ_FLAG_UNREGISTER, RSEQ_SIG);
+ TEST_COMPARE (ret, 0);
+ pd->rseq_area.cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED;
+ }
+ else
+ {
+ TEST_VERIFY (errno != -EINVAL);
+ TEST_VERIFY (errno != -EBUSY);
+ }
+}
+
+static void *
+thread_func (void *ignored)
+{
+ check_rseq_disabled ();
+ return NULL;
+}
+
+static void
+proc_func (void *ignored)
+{
+ check_rseq_disabled ();
+}
+
+static int
+do_test (void)
+{
+ puts ("info: checking main thread");
+ check_rseq_disabled ();
+
+ puts ("info: checking main thread (2)");
+ check_rseq_disabled ();
+
+ puts ("info: checking new thread");
+ xpthread_join (xpthread_create (NULL, thread_func, NULL));
+
+ puts ("info: checking subprocess");
+ support_isolate_in_subprocess (proc_func, NULL);
+
+ return 0;
+}
+#else /* !RSEQ_SIG */
+static int
+do_test (void)
+{
+ FAIL_UNSUPPORTED ("glibc does not define RSEQ_SIG, skipping test");
+}
+#endif
+
+#include <support/test-driver.c>

@ -0,0 +1,23 @@
Downstream-only patch from Mark Wielaard <mjw@redhat.com> to avoid a
crash in backtrace if the vDSO is not available.
Upstream, this code was removed in commit 82fd7314c7df8c5555dce02
("powerpc: Remove backtrace implementation"), so patch is not needed
there.
diff --git a/sysdeps/powerpc/powerpc64/backtrace.c b/sysdeps/powerpc/powerpc64/backtrace.c
index 37de9b5bdd73c316..0ffa7509dfa4862a 100644
--- a/sysdeps/powerpc/powerpc64/backtrace.c
+++ b/sysdeps/powerpc/powerpc64/backtrace.c
@@ -68,8 +68,9 @@ static inline bool
is_sigtramp_address (void *nip)
{
#ifdef HAVE_SIGTRAMP_RT64
- if (nip == GLRO (dl_vdso_sigtramp_rt64) ||
- nip == GLRO (dl_vdso_sigtramp_rt64) + 4)
+ if ((nip == GLRO (dl_vdso_sigtramp_rt64) ||
+ nip == GLRO (dl_vdso_sigtramp_rt64) + 4)
+ && nip != NULL)
return true;
#endif
return false;

@ -0,0 +1,143 @@
commit ea5814467a02c9d2d7608b6445c5d60e2a81d3ee
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Fri Dec 10 13:00:09 2021 -0800
x86-64: Remove LD_PREFER_MAP_32BIT_EXEC support [BZ #28656]
Remove the LD_PREFER_MAP_32BIT_EXEC environment variable support since
the first PT_LOAD segment is no longer executable due to defaulting to
-z separate-code.
This fixes [BZ #28656].
Reviewed-by: Florian Weimer <fweimer@redhat.com>
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h b/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h
deleted file mode 100644
index 5b9696e2de8e5482..0000000000000000
--- a/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Optional code to distinguish library flavours. x86-64 version.
- Copyright (C) 2015-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_LIBRECON_H
-
-#include <sysdeps/unix/sysv/linux/dl-librecon.h>
-
-/* Recognizing extra environment variables. For 64-bit applications,
- branch prediction performance may be negatively impacted when the
- target of a branch is more than 4GB away from the branch. Add the
- Prefer_MAP_32BIT_EXEC bit so that mmap will try to map executable
- pages with MAP_32BIT first. NB: MAP_32BIT will map to lower 2GB,
- not lower 4GB, address. Prefer_MAP_32BIT_EXEC reduces bits available
- for address space layout randomization (ASLR). Prefer_MAP_32BIT_EXEC
- is always disabled for SUID programs and can be enabled by setting
- environment variable, LD_PREFER_MAP_32BIT_EXEC. */
-#define EXTRA_LD_ENVVARS \
- case 21: \
- if (!__libc_enable_secure \
- && memcmp (envline, "PREFER_MAP_32BIT_EXEC", 21) == 0) \
- GLRO(dl_x86_cpu_features).preferred[index_arch_Prefer_MAP_32BIT_EXEC] \
- |= bit_arch_Prefer_MAP_32BIT_EXEC; \
- break;
-
-/* Extra unsecure variables. The names are all stuffed in a single
- string which means they have to be terminated with a '\0' explicitly. */
-#define EXTRA_UNSECURE_ENVVARS \
- "LD_PREFER_MAP_32BIT_EXEC\0"
-
-#endif /* dl-librecon.h */
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h b/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h
deleted file mode 100644
index 18177d2cb3ae645f..0000000000000000
--- a/sysdeps/unix/sysv/linux/x86_64/64/mmap_internal.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Linux mmap system call. x86-64 version.
- Copyright (C) 2015-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 MMAP_X86_64_INTERNAL_H
-#define MMAP_X86_64_INTERNAL_H
-
-#include <ldsodefs.h>
-
-/* If the Prefer_MAP_32BIT_EXEC bit is set, try to map executable pages
- with MAP_32BIT first. */
-#define MMAP_PREPARE(addr, len, prot, flags, fd, offset) \
- if ((addr) == NULL \
- && ((prot) & PROT_EXEC) != 0 \
- && HAS_ARCH_FEATURE (Prefer_MAP_32BIT_EXEC)) \
- { \
- void *ret = (void*) INLINE_SYSCALL_CALL (mmap, (addr), (len), \
- (prot), \
- (flags) | MAP_32BIT, \
- (fd), (offset)); \
- if (ret != MAP_FAILED) \
- return ret; \
- }
-
-#include_next <mmap_internal.h>
-
-#endif
diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c
index 00fe5045eb56eb07..58f2fad4323d5d91 100644
--- a/sysdeps/x86/cpu-tunables.c
+++ b/sysdeps/x86/cpu-tunables.c
@@ -260,13 +260,6 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
20);
}
break;
- case 21:
- {
- CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features,
- Prefer_MAP_32BIT_EXEC,
- disable, 21);
- }
- break;
case 23:
{
CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH
diff --git a/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
index d7c93f00c5928a30..3bdc76cf71007948 100644
--- a/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
+++ b/sysdeps/x86/include/cpu-features-preferred_feature_index_1.def
@@ -26,7 +26,6 @@ BIT (I586)
BIT (I686)
BIT (Slow_SSE4_2)
BIT (AVX_Fast_Unaligned_Load)
-BIT (Prefer_MAP_32BIT_EXEC)
BIT (Prefer_No_VZEROUPPER)
BIT (Prefer_ERMS)
BIT (Prefer_No_AVX512)

File diff suppressed because one or more lines are too long

@ -0,0 +1,585 @@
commit 15a0c5730d1d5aeb95f50c9ec7470640084feae8
Author: Chung-Lin Tang <cltang@codesourcery.com>
Date: Thu Oct 21 21:41:22 2021 +0800
elf: Fix slow DSO sorting behavior in dynamic loader (BZ #17645)
This second patch contains the actual implementation of a new sorting algorithm
for shared objects in the dynamic loader, which solves the slow behavior that
the current "old" algorithm falls into when the DSO set contains circular
dependencies.
The new algorithm implemented here is simply depth-first search (DFS) to obtain
the Reverse-Post Order (RPO) sequence, a topological sort. A new l_visited:1
bitfield is added to struct link_map to more elegantly facilitate such a search.
The DFS algorithm is applied to the input maps[nmap-1] backwards towards
maps[0]. This has the effect of a more "shallow" recursion depth in general
since the input is in BFS. Also, when combined with the natural order of
processing l_initfini[] at each node, this creates a resulting output sorting
closer to the intuitive "left-to-right" order in most cases.
Another notable implementation adjustment related to this _dl_sort_maps change
is the removing of two char arrays 'used' and 'done' in _dl_close_worker to
represent two per-map attributes. This has been changed to simply use two new
bit-fields l_map_used:1, l_map_done:1 added to struct link_map. This also allows
discarding the clunky 'used' array sorting that _dl_sort_maps had to sometimes
do along the way.
Tunable support for switching between different sorting algorithms at runtime is
also added. A new tunable 'glibc.rtld.dynamic_sort' with current valid values 1
(old algorithm) and 2 (new DFS algorithm) has been added. At time of commit
of this patch, the default setting is 1 (old algorithm).
Signed-off-by: Chung-Lin Tang <cltang@codesourcery.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/dl-close.c b/elf/dl-close.c
index cd7b9c9fe83a1a44..f6fbf9de7d78555b 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -167,8 +167,6 @@ _dl_close_worker (struct link_map *map, bool force)
bool any_tls = false;
const unsigned int nloaded = ns->_ns_nloaded;
- char used[nloaded];
- char done[nloaded];
struct link_map *maps[nloaded];
/* Run over the list and assign indexes to the link maps and enter
@@ -176,24 +174,21 @@ _dl_close_worker (struct link_map *map, bool force)
int idx = 0;
for (struct link_map *l = ns->_ns_loaded; l != NULL; l = l->l_next)
{
+ l->l_map_used = 0;
+ l->l_map_done = 0;
l->l_idx = idx;
maps[idx] = l;
++idx;
-
}
assert (idx == nloaded);
- /* Prepare the bitmaps. */
- memset (used, '\0', sizeof (used));
- memset (done, '\0', sizeof (done));
-
/* Keep track of the lowest index link map we have covered already. */
int done_index = -1;
while (++done_index < nloaded)
{
struct link_map *l = maps[done_index];
- if (done[done_index])
+ if (l->l_map_done)
/* Already handled. */
continue;
@@ -204,12 +199,12 @@ _dl_close_worker (struct link_map *map, bool force)
/* See CONCURRENCY NOTES in cxa_thread_atexit_impl.c to know why
acquire is sufficient and correct. */
&& atomic_load_acquire (&l->l_tls_dtor_count) == 0
- && !used[done_index])
+ && !l->l_map_used)
continue;
/* We need this object and we handle it now. */
- done[done_index] = 1;
- used[done_index] = 1;
+ l->l_map_used = 1;
+ l->l_map_done = 1;
/* Signal the object is still needed. */
l->l_idx = IDX_STILL_USED;
@@ -225,9 +220,9 @@ _dl_close_worker (struct link_map *map, bool force)
{
assert ((*lp)->l_idx >= 0 && (*lp)->l_idx < nloaded);
- if (!used[(*lp)->l_idx])
+ if (!(*lp)->l_map_used)
{
- used[(*lp)->l_idx] = 1;
+ (*lp)->l_map_used = 1;
/* If we marked a new object as used, and we've
already processed it, then we need to go back
and process again from that point forward to
@@ -250,9 +245,9 @@ _dl_close_worker (struct link_map *map, bool force)
{
assert (jmap->l_idx >= 0 && jmap->l_idx < nloaded);
- if (!used[jmap->l_idx])
+ if (!jmap->l_map_used)
{
- used[jmap->l_idx] = 1;
+ jmap->l_map_used = 1;
if (jmap->l_idx - 1 < done_index)
done_index = jmap->l_idx - 1;
}
@@ -262,8 +257,7 @@ _dl_close_worker (struct link_map *map, bool force)
/* Sort the entries. We can skip looking for the binary itself which is
at the front of the search list for the main namespace. */
- _dl_sort_maps (maps + (nsid == LM_ID_BASE), nloaded - (nsid == LM_ID_BASE),
- used + (nsid == LM_ID_BASE), true);
+ _dl_sort_maps (maps, nloaded, (nsid == LM_ID_BASE), true);
/* Call all termination functions at once. */
#ifdef SHARED
@@ -280,7 +274,7 @@ _dl_close_worker (struct link_map *map, bool force)
/* All elements must be in the same namespace. */
assert (imap->l_ns == nsid);
- if (!used[i])
+ if (!imap->l_map_used)
{
assert (imap->l_type == lt_loaded && !imap->l_nodelete_active);
@@ -333,7 +327,7 @@ _dl_close_worker (struct link_map *map, bool force)
if (i < first_loaded)
first_loaded = i;
}
- /* Else used[i]. */
+ /* Else imap->l_map_used. */
else if (imap->l_type == lt_loaded)
{
struct r_scope_elem *new_list = NULL;
@@ -560,7 +554,7 @@ _dl_close_worker (struct link_map *map, bool force)
for (unsigned int i = first_loaded; i < nloaded; ++i)
{
struct link_map *imap = maps[i];
- if (!used[i])
+ if (!imap->l_map_used)
{
assert (imap->l_type == lt_loaded);
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 087a49b212a96920..237d9636c5be780c 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -613,10 +613,9 @@ Filters not supported with LD_TRACE_PRELINKING"));
/* If libc.so.6 is the main map, it participates in the sort, so
that the relocation order is correct regarding libc.so.6. */
- if (l_initfini[0] == GL (dl_ns)[l_initfini[0]->l_ns].libc_map)
- _dl_sort_maps (l_initfini, nlist, NULL, false);
- else
- _dl_sort_maps (&l_initfini[1], nlist - 1, NULL, false);
+ _dl_sort_maps (l_initfini, nlist,
+ (l_initfini[0] != GL (dl_ns)[l_initfini[0]->l_ns].libc_map),
+ false);
/* Terminate the list of dependencies. */
l_initfini[nlist] = NULL;
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index 6dbdfe4b3ebbeb89..c683884c355dfd52 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -92,8 +92,7 @@ _dl_fini (void)
/* Now we have to do the sorting. We can skip looking for the
binary itself which is at the front of the search list for
the main namespace. */
- _dl_sort_maps (maps + (ns == LM_ID_BASE), nmaps - (ns == LM_ID_BASE),
- NULL, true);
+ _dl_sort_maps (maps, nmaps, (ns == LM_ID_BASE), true);
/* We do not rely on the linked list of loaded object anymore
from this point on. We have our own list here (maps). The
diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
index d21770267a37e128..a274ed66cc987735 100644
--- a/elf/dl-sort-maps.c
+++ b/elf/dl-sort-maps.c
@@ -16,16 +16,24 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include <assert.h>
#include <ldsodefs.h>
+#include <elf/dl-tunables.h>
+/* Note: this is the older, "original" sorting algorithm, being used as
+ default up to 2.35.
-/* Sort array MAPS according to dependencies of the contained objects.
- Array USED, if non-NULL, is permutated along MAPS. If FOR_FINI this is
- called for finishing an object. */
-void
-_dl_sort_maps (struct link_map **maps, unsigned int nmaps, char *used,
- bool for_fini)
+ Sort array MAPS according to dependencies of the contained objects.
+ If FOR_FINI is true, this is called for finishing an object. */
+static void
+_dl_sort_maps_original (struct link_map **maps, unsigned int nmaps,
+ unsigned int skip, bool for_fini)
{
+ /* Allows caller to do the common optimization of skipping the first map,
+ usually the main binary. */
+ maps += skip;
+ nmaps -= skip;
+
/* A list of one element need not be sorted. */
if (nmaps <= 1)
return;
@@ -66,14 +74,6 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps, char *used,
(k - i) * sizeof (maps[0]));
maps[k] = thisp;
- if (used != NULL)
- {
- char here_used = used[i];
- memmove (&used[i], &used[i + 1],
- (k - i) * sizeof (used[0]));
- used[k] = here_used;
- }
-
if (seen[i + 1] > nmaps - i)
{
++i;
@@ -120,3 +120,183 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps, char *used,
next:;
}
}
+
+#if !HAVE_TUNABLES
+/* In this case, just default to the original algorithm. */
+strong_alias (_dl_sort_maps_original, _dl_sort_maps);
+#else
+
+/* We use a recursive function due to its better clarity and ease of
+ implementation, as well as faster execution speed. We already use
+ alloca() for list allocation during the breadth-first search of
+ dependencies in _dl_map_object_deps(), and this should be on the
+ same order of worst-case stack usage.
+
+ Note: the '*rpo' parameter is supposed to point to one past the
+ last element of the array where we save the sort results, and is
+ decremented before storing the current map at each level. */
+
+static void
+dfs_traversal (struct link_map ***rpo, struct link_map *map,
+ bool *do_reldeps)
+{
+ if (map->l_visited)
+ return;
+
+ map->l_visited = 1;
+
+ if (map->l_initfini)
+ {
+ for (int i = 0; map->l_initfini[i] != NULL; i++)
+ {
+ struct link_map *dep = map->l_initfini[i];
+ if (dep->l_visited == 0
+ && dep->l_main_map == 0)
+ dfs_traversal (rpo, dep, do_reldeps);
+ }
+ }
+
+ if (__glibc_unlikely (do_reldeps != NULL && map->l_reldeps != NULL))
+ {
+ /* Indicate that we encountered relocation dependencies during
+ traversal. */
+ *do_reldeps = true;
+
+ for (int m = map->l_reldeps->act - 1; m >= 0; m--)
+ {
+ struct link_map *dep = map->l_reldeps->list[m];
+ if (dep->l_visited == 0
+ && dep->l_main_map == 0)
+ dfs_traversal (rpo, dep, do_reldeps);
+ }
+ }
+
+ *rpo -= 1;
+ **rpo = map;
+}
+
+/* Topologically sort array MAPS according to dependencies of the contained
+ objects. */
+
+static void
+_dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
+ unsigned int skip __attribute__ ((unused)), bool for_fini)
+{
+ for (int i = nmaps - 1; i >= 0; i--)
+ maps[i]->l_visited = 0;
+
+ /* We apply DFS traversal for each of maps[i] until the whole total order
+ is found and we're at the start of the Reverse-Postorder (RPO) sequence,
+ which is a topological sort.
+
+ We go from maps[nmaps - 1] backwards towards maps[0] at this level.
+ Due to the breadth-first search (BFS) ordering we receive, going
+ backwards usually gives a more shallow depth-first recursion depth,
+ adding more stack usage safety. Also, combined with the natural
+ processing order of l_initfini[] at each node during DFS, this maintains
+ an ordering closer to the original link ordering in the sorting results
+ under most simpler cases.
+
+ Another reason we order the top level backwards, it that maps[0] is
+ usually exactly the main object of which we're in the midst of
+ _dl_map_object_deps() processing, and maps[0]->l_initfini[] is still
+ blank. If we start the traversal from maps[0], since having no
+ dependencies yet filled in, maps[0] will always be immediately
+ incorrectly placed at the last place in the order (first in reverse).
+ Adjusting the order so that maps[0] is last traversed naturally avoids
+ this problem.
+
+ Further, the old "optimization" of skipping the main object at maps[0]
+ from the call-site (i.e. _dl_sort_maps(maps+1,nmaps-1)) is in general
+ no longer valid, since traversing along object dependency-links
+ may "find" the main object even when it is not included in the initial
+ order (e.g. a dlopen()'ed shared object can have circular dependencies
+ linked back to itself). In such a case, traversing N-1 objects will
+ create a N-object result, and raise problems.
+
+ To summarize, just passing in the full list, and iterating from back
+ to front makes things much more straightforward. */
+
+ /* Array to hold RPO sorting results, before we copy back to maps[]. */
+ struct link_map *rpo[nmaps];
+
+ /* The 'head' position during each DFS iteration. Note that we start at
+ one past the last element due to first-decrement-then-store (see the
+ bottom of above dfs_traversal() routine). */
+ struct link_map **rpo_head = &rpo[nmaps];
+
+ bool do_reldeps = false;
+ bool *do_reldeps_ref = (for_fini ? &do_reldeps : NULL);
+
+ for (int i = nmaps - 1; i >= 0; i--)
+ {
+ dfs_traversal (&rpo_head, maps[i], do_reldeps_ref);
+
+ /* We can break early if all objects are already placed. */
+ if (rpo_head == rpo)
+ goto end;
+ }
+ assert (rpo_head == rpo);
+
+ end:
+ /* Here we may do a second pass of sorting, using only l_initfini[]
+ static dependency links. This is avoided if !FOR_FINI or if we didn't
+ find any reldeps in the first DFS traversal.
+
+ The reason we do this is: while it is unspecified how circular
+ dependencies should be handled, the presumed reasonable behavior is to
+ have destructors to respect static dependency links as much as possible,
+ overriding reldeps if needed. And the first sorting pass, which takes
+ l_initfini/l_reldeps links equally, may not preserve this priority.
+
+ Hence we do a 2nd sorting pass, taking only DT_NEEDED links into account
+ (see how the do_reldeps argument to dfs_traversal() is NULL below). */
+ if (do_reldeps)
+ {
+ for (int i = nmaps - 1; i >= 0; i--)
+ rpo[i]->l_visited = 0;
+
+ struct link_map **maps_head = &maps[nmaps];
+ for (int i = nmaps - 1; i >= 0; i--)
+ {
+ dfs_traversal (&maps_head, rpo[i], NULL);
+
+ /* We can break early if all objects are already placed.
+ The below memcpy is not needed in the do_reldeps case here,
+ since we wrote back to maps[] during DFS traversal. */
+ if (maps_head == maps)
+ return;
+ }
+ assert (maps_head == maps);
+ return;
+ }
+
+ memcpy (maps, rpo, sizeof (struct link_map *) * nmaps);
+}
+
+void
+_dl_sort_maps_init (void)
+{
+ int32_t algorithm = TUNABLE_GET (glibc, rtld, dynamic_sort, int32_t, NULL);
+ GLRO(dl_dso_sort_algo) = algorithm == 1 ? dso_sort_algorithm_original
+ : dso_sort_algorithm_dfs;
+}
+
+void
+_dl_sort_maps (struct link_map **maps, unsigned int nmaps,
+ unsigned int skip, bool for_fini)
+{
+ /* It can be tempting to use a static function pointer to store and call
+ the current selected sorting algorithm routine, but experimentation
+ shows that current processors still do not handle indirect branches
+ that efficiently, plus a static function pointer will involve
+ PTR_MANGLE/DEMANGLE, further impairing performance of small, common
+ input cases. A simple if-case with direct function calls appears to
+ be the fastest. */
+ if (__glibc_likely (GLRO(dl_dso_sort_algo) == dso_sort_algorithm_original))
+ _dl_sort_maps_original (maps, nmaps, skip, for_fini);
+ else
+ _dl_sort_maps_dfs (maps, nmaps, skip, for_fini);
+}
+
+#endif /* HAVE_TUNABLES. */
diff --git a/elf/dl-support.c b/elf/dl-support.c
index d8c06ba7eb4c76ea..c5ee5d33aa7e1d65 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -166,6 +166,8 @@ size_t _dl_phnum;
uint64_t _dl_hwcap;
uint64_t _dl_hwcap2;
+enum dso_sort_algorithm _dl_dso_sort_algo;
+
/* The value of the FPU control word the kernel will preset in hardware. */
fpu_control_t _dl_fpu_control = _FPU_DEFAULT;
diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
index 2c684c2db2a1f59b..4dc366eea445e974 100644
--- a/elf/dl-sysdep.c
+++ b/elf/dl-sysdep.c
@@ -231,6 +231,9 @@ _dl_sysdep_start (void **start_argptr,
__tunables_init (_environ);
+ /* Initialize DSO sorting algorithm after tunables. */
+ _dl_sort_maps_init ();
+
#ifdef DL_SYSDEP_INIT
DL_SYSDEP_INIT;
#endif
diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
index 8ddd4a23142a941b..46ffb2378416f90f 100644
--- a/elf/dl-tunables.list
+++ b/elf/dl-tunables.list
@@ -156,4 +156,13 @@ glibc {
security_level: SXID_IGNORE
}
}
+
+ rtld {
+ dynamic_sort {
+ type: INT_32
+ minval: 1
+ maxval: 2
+ default: 1
+ }
+ }
}
diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def
index 873ddf55d91155c6..5f7f18ef270bc12d 100644
--- a/elf/dso-sort-tests-1.def
+++ b/elf/dso-sort-tests-1.def
@@ -62,5 +62,5 @@ output: b>a>{}<a<b
# The below expected outputs are what the two algorithms currently produce
# respectively, for regression testing purposes.
tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};a->b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c
-xfail_output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];}
+output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];}
output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<g<f<a<b<c<d<e];}
diff --git a/elf/rtld.c b/elf/rtld.c
index 6bbb373c5743cb99..84eac9a8df7125a6 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1426,6 +1426,9 @@ dl_main (const ElfW(Phdr) *phdr,
main_map->l_name = (char *) "";
*user_entry = main_map->l_entry;
+ /* Set bit indicating this is the main program map. */
+ main_map->l_main_map = 1;
+
#ifdef HAVE_AUX_VECTOR
/* Adjust the on-stack auxiliary vector so that it looks like the
binary was executed directly. */
diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp
index 9f66c528855fb21d..9bf572715f996ca6 100644
--- a/elf/tst-rtld-list-tunables.exp
+++ b/elf/tst-rtld-list-tunables.exp
@@ -10,5 +10,6 @@ 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.dynamic_sort: 1 (min: 1, max: 2)
glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10)
glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0x[f]+)
diff --git a/include/link.h b/include/link.h
index c46aced9f7b43ba0..4dcf01d8aea90bc2 100644
--- a/include/link.h
+++ b/include/link.h
@@ -181,6 +181,11 @@ struct link_map
unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */
unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */
unsigned int l_reserved:2; /* Reserved for internal use. */
+ unsigned int l_main_map:1; /* Nonzero for the map of the main program. */
+ unsigned int l_visited:1; /* Used internally for map dependency
+ graph traversal. */
+ unsigned int l_map_used:1; /* These two bits are used during traversal */
+ unsigned int l_map_done:1; /* of maps in _dl_close_worker. */
unsigned int l_phdr_allocated:1; /* Nonzero if the data structure pointed
to by `l_phdr' is allocated. */
unsigned int l_soname_added:1; /* Nonzero if the SONAME is for sure in
diff --git a/manual/tunables.texi b/manual/tunables.texi
index 658547c6137bf177..10f4d75993f9940f 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -309,6 +309,17 @@ changed once allocated at process startup. The default allocation of
optional static TLS is 512 bytes and is allocated in every thread.
@end deftp
+@deftp Tunable glibc.rtld.dynamic_sort
+Sets the algorithm to use for DSO sorting, valid values are @samp{1} and
+@samp{2}. For value of @samp{1}, an older O(n^3) algorithm is used, which is
+long time tested, but may have performance issues when dependencies between
+shared objects contain cycles due to circular dependencies. When set to the
+value of @samp{2}, a different algorithm is used, which implements a
+topological sort through depth-first search, and does not exhibit the
+performance issues of @samp{1}.
+
+The default value of this tunable is @samp{1}.
+@end deftp
@node Elision Tunables
@section Elision Tunables
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index fcbbf6974827cdf1..bcf1f199c5985c65 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -245,6 +245,13 @@ enum allowmask
};
+/* DSO sort algorithm to use (check dl-sort-maps.c). */
+enum dso_sort_algorithm
+ {
+ dso_sort_algorithm_original,
+ dso_sort_algorithm_dfs
+ };
+
struct audit_ifaces
{
void (*activity) (uintptr_t *, unsigned int);
@@ -672,6 +679,8 @@ struct rtld_global_ro
platforms. */
EXTERN uint64_t _dl_hwcap2;
+ EXTERN enum dso_sort_algorithm _dl_dso_sort_algo;
+
#ifdef SHARED
/* We add a function table to _rtld_global which is then used to
call the function instead of going through the PLT. The result
@@ -1098,7 +1107,7 @@ extern void _dl_fini (void) attribute_hidden;
/* Sort array MAPS according to dependencies of the contained objects. */
extern void _dl_sort_maps (struct link_map **maps, unsigned int nmaps,
- char *used, bool for_fini) attribute_hidden;
+ unsigned int skip, bool for_fini) attribute_hidden;
/* The dynamic linker calls this function before and having changing
any shared object mappings. The `r_state' member of `struct r_debug'
@@ -1225,6 +1234,9 @@ extern struct link_map * _dl_get_dl_main_map (void)
# endif
#endif
+/* Initialize the DSO sort algorithm to use. */
+extern void _dl_sort_maps_init (void) attribute_hidden;
+
/* Initialization of libpthread for statically linked applications.
If libpthread is not linked in, this is an empty function. */
void __pthread_initialize_minimal (void) weak_function;

@ -0,0 +1,25 @@
commit d3bf2f5927d51258a51ac7fde04f4805f8ee294a
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed Nov 3 09:19:30 2021 -0300
elf: Do not run DSO sorting if tunables is not enabled
Since the argorithm selection requires tunables.
Checked on x86_64-linux-gnu with --enable-tunables=no.
diff --git a/elf/Makefile b/elf/Makefile
index 8dd2b24328113536..02ee834fdaf00a26 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -483,8 +483,10 @@ include $(objpfx)$(1).generated-makefile
endef
# Generate from each testcase description file
+ifeq (yes,$(have-tunables))
$(eval $(call include_dsosort_tests,dso-sort-tests-1.def))
$(eval $(call include_dsosort_tests,dso-sort-tests-2.def))
+endif
check-abi: $(objpfx)check-abi-ld.out
tests-special += $(objpfx)check-abi-ld.out

@ -0,0 +1,189 @@
commit b4bbedb1e75737a80bcc3d53d6eef1fbe0b5f4d5
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Sat Nov 6 14:13:27 2021 -0700
dso-ordering-test.py: Put all sources in one directory [BZ #28550]
Put all sources for DSO sorting tests in the dso-sort-tests-src directory
and compile test relocatable objects with
$(objpfx)tst-dso-ordering1-dir/tst-dso-ordering1-a.os: $(objpfx)dso-sort-tests-src/tst-dso-ordering1-a.c
$(compile.c) $(OUTPUT_OPTION)
to avoid random $< values from $(before-compile) when compiling test
relocatable objects with
$(objpfx)%$o: $(objpfx)%.c $(before-compile); $$(compile-command.c)
compile-command.c = $(compile.c) $(OUTPUT_OPTION) $(compile-mkdep-flags)
compile.c = $(CC) $< -c $(CFLAGS) $(CPPFLAGS)
for 3 "make -j 28" parallel builds on a machine with 112 cores at the
same time.
This partially fixes BZ #28550.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/scripts/dso-ordering-test.py b/scripts/dso-ordering-test.py
index 944ee740527d60fd..bde0406be9da14fc 100644
--- a/scripts/dso-ordering-test.py
+++ b/scripts/dso-ordering-test.py
@@ -526,9 +526,13 @@ def process_testcase(t):
base_test_name = t.test_name
test_subdir = base_test_name + "-dir"
testpfx = objpfx + test_subdir + "/"
+ test_srcdir = "dso-sort-tests-src/"
+ testpfx_src = objpfx + test_srcdir
if not os.path.exists(testpfx):
os.mkdir(testpfx)
+ if not os.path.exists(testpfx_src):
+ os.mkdir(testpfx_src)
def find_objs_not_depended_on(t):
objs_not_depended_on = []
@@ -595,6 +599,11 @@ def process_testcase(t):
# Print out needed Makefile fragments for use in glibc/elf/Makefile.
module_names = ""
for o in test_descr.objs:
+ rule = ("$(objpfx)" + test_subdir + "/" + test_name
+ + "-" + o + ".os: $(objpfx)" + test_srcdir
+ + test_name + "-" + o + ".c\n"
+ "\t$(compile.c) $(OUTPUT_OPTION)\n")
+ makefile.write (rule)
module_names += " " + test_subdir + "/" + test_name + "-" + o
makefile.write("modules-names +=%s\n" % (module_names))
@@ -637,7 +646,7 @@ def process_testcase(t):
# object. This only needs to be done at most once for
# an object name.
if not dep in fake_created:
- f = open(testpfx + test_name + "-" + dep
+ f = open(testpfx_src + test_name + "-" + dep
+ ".FAKE.c", "w")
f.write(" \n")
f.close()
@@ -648,6 +657,12 @@ def process_testcase(t):
% (test_name + "-" + dep + ".FAKE.so",
("$(objpfx)" + test_subdir + "/"
+ test_name + "-" + dep + ".so")))
+ rule = ("$(objpfx)" + test_subdir + "/"
+ + test_name + "-" + dep + ".FAKE.os: "
+ "$(objpfx)" + test_srcdir
+ + test_name + "-" + dep + ".FAKE.c\n"
+ "\t$(compile.c) $(OUTPUT_OPTION)\n")
+ makefile.write (rule)
makefile.write \
("modules-names += %s\n"
% (test_subdir + "/"
@@ -687,6 +702,10 @@ def process_testcase(t):
+ test_descr.soname_map['#'] + ".so")
ldflags += (" -Wl,-soname=" + soname)
makefile.write("LDFLAGS-%s = %s\n" % (test_name, ldflags))
+ rule = ("$(objpfx)" + test_subdir + "/" + test_name + ".o: "
+ "$(objpfx)" + test_srcdir + test_name + ".c\n"
+ "\t$(compile.c) $(OUTPUT_OPTION)\n")
+ makefile.write (rule)
not_depended_objs = find_objs_not_depended_on(test_descr)
if not_depended_objs:
@@ -745,7 +764,7 @@ def process_testcase(t):
" something_failed=true\n"
"else\n"
" diff -wu ${common_objpfx}elf/%s/%s%s.output \\\n"
- " ${common_objpfx}elf/%s/%s%s.exp\n"
+ " ${common_objpfx}elf/%s%s%s.exp\n"
" if [ $? -ne 0 ]; then\n"
" echo '%sFAIL: %s%s expected output comparison'\n"
" something_failed=true\n"
@@ -753,14 +772,14 @@ def process_testcase(t):
"fi\n"
% (("X" if xfail else ""), test_name, tunable_descr,
test_subdir, test_name, tunable_sfx,
- test_subdir, base_test_name, exp_tunable_sfx,
+ test_srcdir, base_test_name, exp_tunable_sfx,
("X" if xfail else ""), test_name, tunable_descr))
# Generate C files according to dependency and calling relations from
# description string.
for obj in test_descr.objs:
src_name = test_name + "-" + obj + ".c"
- f = open(testpfx + src_name, "w")
+ f = open(testpfx_src + src_name, "w")
if obj in test_descr.callrefs:
called_objs = test_descr.callrefs[obj]
for callee in called_objs:
@@ -804,7 +823,7 @@ def process_testcase(t):
f.close()
# Open C file for writing main program
- f = open(testpfx + test_name + ".c", "w")
+ f = open(testpfx_src + test_name + ".c", "w")
# if there are some operations in main(), it means we need -ldl
f.write("#include <stdio.h>\n")
@@ -885,7 +904,7 @@ def process_testcase(t):
for obj in test_descr.objs:
src_name = test_name + "-" + obj + ".c"
obj_name = test_name + "-" + obj + ".os"
- run_cmd([build_gcc, "-c", "-fPIC", testpfx + src_name,
+ run_cmd([build_gcc, "-c", "-fPIC", testpfx_src + src_name,
"-o", testpfx + obj_name])
obj_processed = {}
@@ -903,10 +922,12 @@ def process_testcase(t):
deps.append(dep + ".FAKE")
if not dep in fake_created:
base_name = testpfx + test_name + "-" + dep
+ src_base_name = (testpfx_src + test_name
+ + "-" + dep)
cmd = [build_gcc, "-Wl,--no-as-needed",
("-Wl,-soname=" + base_name + ".so"),
"-shared", base_name + ".FAKE.c",
- "-o", base_name + ".FAKE.so"]
+ "-o", src_base_name + ".FAKE.so"]
run_cmd(cmd)
fake_created[dep] = True
dso_deps = map(lambda d: testpfx + test_name + "-" + d + ".so",
@@ -932,7 +953,7 @@ def process_testcase(t):
main_deps = map(lambda d: testpfx + test_name + "-" + d + ".so",
deps)
cmd = [build_gcc, "-Wl,--no-as-needed", "-o", testpfx + test_name,
- testpfx + test_name + ".c", "-L%s" % (os.getcwd()),
+ testpfx_src + test_name + ".c", "-L%s" % (os.getcwd()),
"-Wl,-rpath-link=%s" % (os.getcwd())]
if '#' in test_descr.soname_map:
soname = ("-Wl,-soname=" + testpfx + test_name + "-"
@@ -987,14 +1008,14 @@ def process_testcase(t):
sfx = ""
if r[0] != "":
sfx = "-" + r[0].replace("=","_")
- f = open(testpfx + t.test_name + sfx + ".exp", "w")
+ f = open(testpfx_src + t.test_name + sfx + ".exp", "w")
(output, xfail) = r[1]
f.write('%s' % output)
f.close()
# Create header part of top-level testcase shell script, to wrap execution
# and output comparison together.
- t.sh = open(testpfx + t.test_name + ".sh", "w")
+ t.sh = open(testpfx_src + t.test_name + ".sh", "w")
t.sh.write("#!/bin/sh\n")
t.sh.write("# Test driver for %s, generated by "
"dso-ordering-test.py\n" % (t.test_name))
@@ -1022,12 +1043,12 @@ def process_testcase(t):
sfx = ""
if r[0] != "":
sfx = "-" + r[0].replace("=","_")
- expected_output_files += " $(objpfx)%s/%s%s.exp" % (test_subdir,
+ expected_output_files += " $(objpfx)%s%s%s.exp" % (test_srcdir,
t.test_name, sfx)
makefile.write \
- ("$(objpfx)%s.out: $(objpfx)%s/%s.sh%s "
+ ("$(objpfx)%s.out: $(objpfx)%s%s.sh%s "
"$(common-objpfx)support/test-run-command\n"
- % (t.test_name, test_subdir, t.test_name,
+ % (t.test_name, test_srcdir, t.test_name,
expected_output_files))
makefile.write("\t$(SHELL) $< $(common-objpfx) '$(test-wrapper-env)' "
"'$(run-program-env)' > $@; $(evaluate-test)\n")

@ -0,0 +1,45 @@
commit 1f67d8286b5da9266a138198ef1f15c27cbb0010
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Mon Nov 15 16:28:39 2021 -0800
elf: Use a temporary file to generate Makefile fragments [BZ #28550]
1. Use a temporary file to generate Makefile fragments for DSO sorting
tests and use -include on them.
2. Add Makefile fragments to postclean-generated so that a "make clean"
removes the autogenerated fragments and a subsequent "make" regenerates
them.
This partially fixes BZ #28550.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/Makefile b/elf/Makefile
index 02ee834fdaf00a26..535ba4260fb98e64 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -471,6 +471,7 @@ tests-special += $(objpfx)order-cmp.out $(objpfx)tst-array1-cmp.out \
$(objpfx)tst-unused-dep-cmp.out
endif
+ifndef avoid-generated
# DSO sorting tests:
# The dso-ordering-test.py script generates testcase source files in $(objpfx),
# creating a $(objpfx)<testcase-name>-dir for each testcase, and creates a
@@ -478,9 +479,14 @@ endif
define include_dsosort_tests
$(objpfx)$(1).generated-makefile: $(1)
$(PYTHON) $(..)scripts/dso-ordering-test.py \
- --description-file $$< --objpfx $(objpfx) --output-makefile $$@
-include $(objpfx)$(1).generated-makefile
+ --description-file $$< --objpfx $(objpfx) --output-makefile $$@T
+ mv $$@T $$@
+-include $(objpfx)$(1).generated-makefile
endef
+endif
+
+postclean-generated += $(objpfx)/dso-sort-tests-2.generated-makefile \
+ $(objpfx)/dso-sort-tests-2.generated-makefile
# Generate from each testcase description file
ifeq (yes,$(have-tunables))

@ -0,0 +1,49 @@
commit 0884724a95b60452ad483dbe086d237d02ba624d
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Dec 14 12:37:44 2021 +0100
elf: Use new dependency sorting algorithm by default
The default has to change eventually, and there are no known failures
that require a delay.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
index 46ffb2378416f90f..ffcd7f18d4fafb91 100644
--- a/elf/dl-tunables.list
+++ b/elf/dl-tunables.list
@@ -162,7 +162,7 @@ glibc {
type: INT_32
minval: 1
maxval: 2
- default: 1
+ default: 2
}
}
}
diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp
index 9bf572715f996ca6..44e4834cfb431633 100644
--- a/elf/tst-rtld-list-tunables.exp
+++ b/elf/tst-rtld-list-tunables.exp
@@ -10,6 +10,6 @@ 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.dynamic_sort: 1 (min: 1, max: 2)
+glibc.rtld.dynamic_sort: 2 (min: 1, max: 2)
glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10)
glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0x[f]+)
diff --git a/manual/tunables.texi b/manual/tunables.texi
index 10f4d75993f9940f..7c3b28d029410a6f 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -318,7 +318,7 @@ value of @samp{2}, a different algorithm is used, which implements a
topological sort through depth-first search, and does not exhibit the
performance issues of @samp{1}.
-The default value of this tunable is @samp{1}.
+The default value of this tunable is @samp{2}.
@end deftp
@node Elision Tunables

@ -0,0 +1,547 @@
commit 28713c06129f8f64f88c423266e6ff2880216509
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Mon Dec 13 09:43:52 2021 -0800
elf: Sort tests and modules-names
Sort tests and modules-names to reduce future conflicts.
Conflicts:
elf/Makefile
(Usual backport differences. Recreated tests and module-names
from scratch. Note that the upstream sort order is difficult
to fathom.)
diff --git a/elf/Makefile b/elf/Makefile
index 535ba4260fb98e64..33df5b4714176adc 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -193,40 +193,134 @@ static-dlopen-environment = \
tst-tls9-static-ENV = $(static-dlopen-environment)
tst-single_threaded-static-dlopen-ENV = $(static-dlopen-environment)
-tests += restest1 preloadtest loadfail multiload origtest resolvfail \
- constload1 order noload filter \
- reldep reldep2 reldep3 reldep4 nodelete nodelete2 \
- nodlopen nodlopen2 lateglobal initfirst global \
- restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
- tst-tls4 tst-tls5 \
- tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \
- tst-tls16 tst-tls17 tst-tls18 tst-tls19 tst-tls-dlinfo \
- tst-align tst-align2 \
- tst-dlmodcount tst-dlopenrpath tst-deep1 \
- tst-dlmopen1 tst-dlmopen3 \
- unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \
- tst-audit1 tst-audit2 tst-audit8 tst-audit9 \
- tst-addr1 tst-thrlock \
- tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \
- tst-nodelete tst-dlopen-nodelete-reloc) \
- tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
- tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \
- tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
- tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
- tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
- tst-unwind-ctor tst-unwind-main tst-audit13 \
- tst-sonamemove-link tst-sonamemove-dlopen tst-dlopen-tlsmodid \
- tst-dlopen-self tst-auditmany tst-initfinilazyfail tst-dlopenfail \
- tst-dlopenfail-2 \
- tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \
- tst-audit14 tst-audit15 tst-audit16 tst-audit17 \
- tst-single_threaded tst-single_threaded-pthread \
- tst-tls-ie tst-tls-ie-dlmopen argv0test \
- tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
- tst-tls20 tst-tls21 tst-dlmopen-dlerror tst-dlmopen-gethostbyname \
- tst-dl-is_dso tst-ro-dynamic \
- tst-rtld-run-static \
+tests += \
+ argv0test \
+ constload1 \
+ dblload \
+ dblunload \
+ filter \
+ global \
+ initfirst \
+ lateglobal \
+ loadfail \
+ multiload \
+ next \
+ nodelete \
+ nodelete2 \
+ nodlopen \
+ nodlopen2 \
+ noload \
+ order \
+ order2 \
+ origtest \
+ preloadtest \
+ reldep \
+ reldep2 \
+ reldep3 \
+ reldep4 \
+ reldep5 \
+ reldep6 \
+ reldep7 \
+ reldep8 \
+ resolvfail \
+ restest1 \
+ restest2 \
+ tst-absolute-sym \
+ tst-absolute-zero \
+ tst-addr1 \
+ tst-align \
+ tst-align2 \
+ tst-audit1 \
+ tst-audit2 \
+ tst-audit8 \
+ tst-audit9 \
+ tst-audit11 \
+ tst-audit12 \
+ tst-audit13 \
+ tst-audit14 \
+ tst-audit15 \
+ tst-audit16 \
+ tst-audit17 \
+ tst-auditmany \
+ tst-auxobj \
+ tst-auxobj-dlopen \
+ tst-big-note \
+ tst-debug1 \
+ tst-deep1 \
+ tst-dl-is_dso \
+ tst-dlmodcount \
+ tst-dlmopen1 \
+ tst-dlmopen3 \
+ tst-dlmopen-dlerror \
+ tst-dlmopen-gethostbyname \
+ tst-dlopenfail \
+ tst-dlopenfail-2 \
+ tst-dlopenrpath \
+ tst-dlopen-self \
+ tst-dlopen-tlsmodid \
+ tst-dlsym-error \
+ tst-filterobj \
+ tst-filterobj-dlopen \
+ tst-glibc-hwcaps \
+ tst-glibc-hwcaps-mask \
+ tst-glibc-hwcaps-prepend \
+ tst-global1 \
+ tst-initfinilazyfail \
+ tst-initorder \
+ tst-initorder2 \
+ tst-latepthread \
+ tst-main1 \
+ tst-nodelete2 \
+ tst-nodelete-dlclose \
+ tst-nodelete-opened \
+ tst-noload \
+ tst-null-argv \
+ tst-relsort1 \
+ tst-ro-dynamic \
+ tst-rtld-run-static \
+ tst-single_threaded \
+ tst-single_threaded-pthread \
+ tst-sonamemove-dlopen \
+ tst-sonamemove-link \
+ tst-thrlock \
+ tst-tls10 \
+ tst-tls11 \
+ tst-tls12 \
+ tst-tls13 \
+ tst-tls14 \
+ tst-tls15 \
+ tst-tls16 \
+ tst-tls17 \
+ tst-tls18 \
+ tst-tls19 \
+ tst-tls20 \
+ tst-tls21 \
+ tst-tls4 \
+ tst-tls5 \
+ tst-tlsalign \
+ tst-tlsalign-extern \
+ tst-tls-dlinfo \
+ tst-tls-ie \
+ tst-tls-ie-dlmopen \
+ tst-tls-manydynamic \
+ tst-unique1 \
+ tst-unique2 \
+ tst-unwind-ctor \
+ tst-unwind-main \
+ unload3 \
+ unload4 \
+ unload5 \
+ unload6 \
+ unload7 \
+ unload8 \
# reldep9
+tests-cxx = \
+ tst-dlopen-nodelete-reloc \
+ tst-nodelete \
+ tst-unique3 \
+ tst-unique4 \
+
+tests += $(if $(CXX),$(tests-cxx))
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \
@@ -264,101 +358,265 @@ tst-tls-many-dynamic-modules-dep-bad = \
extra-test-objs += $(tlsmod17a-modules:=.os) $(tlsmod18a-modules:=.os) \
tst-tlsalign-vars.o
test-extras += tst-tlsmod17a tst-tlsmod18a tst-tlsalign-vars
-modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
- testobj1_1 failobj constload2 constload3 unloadmod \
- dep1 dep2 dep3 dep4 vismod1 vismod2 vismod3 \
- nodelmod1 nodelmod2 nodelmod3 nodelmod4 \
- nodel2mod1 nodel2mod2 nodel2mod3 \
- nodlopenmod nodlopenmod2 filtmod1 filtmod2 \
- reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2 \
- reldep4mod1 reldep4mod2 reldep4mod3 reldep4mod4 \
- neededobj1 neededobj2 neededobj3 neededobj4 \
- neededobj5 neededobj6 firstobj globalmod1 \
- unload2mod unload2dep ltglobmod1 ltglobmod2 pathoptobj \
- dblloadmod1 dblloadmod2 dblloadmod3 reldepmod5 reldepmod6 \
- reldep6mod0 reldep6mod1 reldep6mod2 reldep6mod3 reldep6mod4 \
- reldep7mod1 reldep7mod2 \
- tst-tlsmod1 tst-tlsmod2 tst-tlsmod3 tst-tlsmod4 \
- tst-tlsmod5 tst-tlsmod6 tst-tlsmod7 tst-tlsmod8 \
- tst-tlsmod9 tst-tlsmod10 tst-tlsmod11 tst-tlsmod12 \
- tst-tlsmod13 tst-tlsmod13a tst-tlsmod14a tst-tlsmod14b \
- tst-tlsmod15a tst-tlsmod15b tst-tlsmod16a tst-tlsmod16b \
- $(tlsmod17a-modules) tst-tlsmod17b $(tlsmod18a-modules) \
- tst-tls19mod1 tst-tls19mod2 tst-tls19mod3 \
- circlemod1 circlemod1a circlemod2 circlemod2a \
- circlemod3 circlemod3a \
- reldep8mod1 reldep8mod2 reldep8mod3 \
- reldep9mod1 reldep9mod2 reldep9mod3 \
- tst-alignmod tst-alignmod2 \
- $(modules-execstack-$(have-z-execstack)) \
- tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \
- tst-dlmopen1mod tst-auditmod1 \
- unload3mod1 unload3mod2 unload3mod3 unload3mod4 \
- unload4mod1 unload4mod2 unload4mod3 unload4mod4 \
- unload6mod1 unload6mod2 unload6mod3 \
- unload7mod1 unload7mod2 \
- unload8mod1 unload8mod1x unload8mod2 unload8mod3 \
- order2mod1 order2mod2 order2mod3 order2mod4 \
- tst-unique1mod1 tst-unique1mod2 \
- tst-unique2mod1 tst-unique2mod2 \
- tst-auditmod9a tst-auditmod9b \
- $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
- tst-nodelete-uniquemod tst-nodelete-rtldmod \
- tst-nodelete-zmod \
- tst-dlopen-nodelete-reloc-mod1 \
- tst-dlopen-nodelete-reloc-mod2 \
- tst-dlopen-nodelete-reloc-mod3 \
- tst-dlopen-nodelete-reloc-mod4 \
- tst-dlopen-nodelete-reloc-mod5 \
- tst-dlopen-nodelete-reloc-mod6 \
- tst-dlopen-nodelete-reloc-mod7 \
- tst-dlopen-nodelete-reloc-mod8 \
- tst-dlopen-nodelete-reloc-mod9 \
- tst-dlopen-nodelete-reloc-mod10 \
- tst-dlopen-nodelete-reloc-mod11 \
- tst-dlopen-nodelete-reloc-mod12 \
- tst-dlopen-nodelete-reloc-mod13 \
- tst-dlopen-nodelete-reloc-mod14 \
- tst-dlopen-nodelete-reloc-mod15 \
- tst-dlopen-nodelete-reloc-mod16 \
- tst-dlopen-nodelete-reloc-mod17) \
- tst-initordera1 tst-initorderb1 \
- tst-initordera2 tst-initorderb2 \
- tst-initordera3 tst-initordera4 \
- tst-initorder2a tst-initorder2b tst-initorder2c \
- tst-initorder2d \
- tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \
- tst-array5dep tst-null-argv-lib \
- tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \
- 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-absolute-sym-lib \
- tst-absolute-zero-lib tst-big-note-lib tst-unwind-ctor-lib \
- tst-audit13mod1 tst-sonamemove-linkmod1 \
- tst-sonamemove-runmod1 tst-sonamemove-runmod2 \
- tst-auditmanymod1 tst-auditmanymod2 tst-auditmanymod3 \
- tst-auditmanymod4 tst-auditmanymod5 tst-auditmanymod6 \
- tst-auditmanymod7 tst-auditmanymod8 tst-auditmanymod9 \
- tst-initlazyfailmod tst-finilazyfailmod \
- tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \
- tst-dlopenfailmod3 tst-dlopenfailnodelmod tst-ldconfig-ld-mod \
- tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee \
- tst-auditlogmod-1 tst-auditlogmod-2 tst-auditlogmod-3 \
- tst-single_threaded-mod1 tst-single_threaded-mod2 \
- tst-single_threaded-mod3 tst-single_threaded-mod4 \
- tst-tls-ie-mod0 tst-tls-ie-mod1 tst-tls-ie-mod2 \
- tst-tls-ie-mod3 tst-tls-ie-mod4 tst-tls-ie-mod5 \
- tst-tls-ie-mod6 libmarkermod1-1 libmarkermod1-2 libmarkermod1-3 \
- libmarkermod2-1 libmarkermod2-2 \
- libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \
- libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \
- tst-tls20mod-bad tst-tls21mod tst-dlmopen-dlerror-mod \
- tst-auxvalmod \
- tst-dlmopen-gethostbyname-mod tst-ro-dynamic-mod \
+modules-names = \
+ circlemod1 \
+ circlemod1a \
+ circlemod2 \
+ circlemod2a \
+ circlemod3 \
+ circlemod3a \
+ constload2 \
+ constload3 \
+ dblloadmod1 \
+ dblloadmod2 \
+ dblloadmod3 \
+ dep1 \
+ dep2 \
+ dep3 \
+ dep4 \
+ failobj \
+ filtmod1 \
+ filtmod2 \
+ firstobj \
+ globalmod1 \
+ libmarkermod1-1 \
+ libmarkermod1-2 \
+ libmarkermod1-3 \
+ libmarkermod2-1 \
+ libmarkermod2-2 \
+ libmarkermod3-1 \
+ libmarkermod3-2 \
+ libmarkermod3-3 \
+ libmarkermod4-1 \
+ libmarkermod4-2 \
+ libmarkermod4-3 \
+ libmarkermod4-4 \
+ ltglobmod1 \
+ ltglobmod2 \
+ neededobj1 \
+ neededobj2 \
+ neededobj3 \
+ neededobj4 \
+ neededobj5 \
+ neededobj6 \
+ nextmod1 \
+ nextmod2 \
+ nodel2mod1 \
+ nodel2mod2 \
+ nodel2mod3 \
+ nodelmod1 \
+ nodelmod2 \
+ nodelmod3 \
+ nodelmod4 \
+ nodlopenmod \
+ nodlopenmod2 \
+ order2mod1 \
+ order2mod2 \
+ order2mod3 \
+ order2mod4 \
+ pathoptobj \
+ reldep4mod1 \
+ reldep4mod2 \
+ reldep4mod3 \
+ reldep4mod4 \
+ reldep6mod0 \
+ reldep6mod1 \
+ reldep6mod2 \
+ reldep6mod3 \
+ reldep6mod4 \
+ reldep7mod1 \
+ reldep7mod2 \
+ reldep8mod1 \
+ reldep8mod2 \
+ reldep8mod3 \
+ reldep9mod1 \
+ reldep9mod2 \
+ reldep9mod3 \
+ reldepmod1 \
+ reldepmod2 \
+ reldepmod3 \
+ reldepmod4 \
+ reldepmod5 \
+ reldepmod6 \
+ testobj1 \
+ testobj1_1 \
+ testobj2 \
+ testobj3 \
+ testobj4 \
+ testobj5 \
+ testobj6 \
+ tst-absolute-sym-lib \
+ tst-absolute-zero-lib \
+ tst-alignmod \
+ tst-alignmod2 \
+ tst-array2dep \
+ tst-array5dep \
+ tst-audit11mod1 \
+ tst-audit11mod2 \
+ tst-audit12mod1 \
+ tst-audit12mod2 \
+ tst-audit12mod3 \
+ tst-audit13mod1 \
+ tst-auditlogmod-1 \
+ tst-auditlogmod-2 \
+ tst-auditlogmod-3 \
+ tst-auditmanymod1 \
+ tst-auditmanymod2 \
+ tst-auditmanymod3 \
+ tst-auditmanymod4 \
+ tst-auditmanymod5 \
+ tst-auditmanymod6 \
+ tst-auditmanymod7 \
+ tst-auditmanymod8 \
+ tst-auditmanymod9 \
+ tst-auditmod1 \
+ tst-auditmod9a \
+ tst-auditmod9b \
+ tst-auditmod11 \
+ tst-auditmod12 \
+ tst-auxvalmod \
+ tst-big-note-lib \
+ tst-deep1mod1 \
+ tst-deep1mod2 \
+ tst-deep1mod3 \
+ tst-dlmopen1mod \
+ tst-dlmopen-dlerror-mod \
+ tst-dlmopen-gethostbyname-mod \
+ tst-dlopenfaillinkmod \
+ tst-dlopenfailmod1 \
+ tst-dlopenfailmod2 \
+ tst-dlopenfailmod3 \
+ tst-dlopenfailnodelmod \
+ tst-dlopenrpathmod \
+ tst-filterobj-aux \
+ tst-filterobj-filtee \
+ tst-filterobj-flt \
+ tst-finilazyfailmod \
+ tst-initlazyfailmod \
+ tst-initorder2a \
+ tst-initorder2b \
+ tst-initorder2c \
+ tst-initorder2d \
+ tst-initordera1 \
+ tst-initordera2 \
+ tst-initordera3 \
+ tst-initordera4 \
+ tst-initorderb1 \
+ tst-initorderb2 \
+ tst-latepthreadmod \
+ tst-ldconfig-ld-mod \
+ tst-main1mod \
+ tst-nodelete2mod \
+ tst-nodelete-dlclose-dso \
+ tst-nodelete-dlclose-plugin \
+ tst-nodelete-opened-lib \
+ tst-null-argv-lib \
+ tst-relsort1mod1 \
+ tst-relsort1mod2 \
+ tst-ro-dynamic-mod \
+ tst-single_threaded-mod1 \
+ tst-single_threaded-mod2 \
+ tst-single_threaded-mod3 \
+ tst-single_threaded-mod4 \
+ tst-sonamemove-linkmod1 \
+ tst-sonamemove-runmod1 \
+ tst-sonamemove-runmod2 \
+ tst-tls19mod1 \
+ tst-tls19mod2 \
+ tst-tls19mod3 \
+ tst-tls20mod-bad \
+ tst-tls21mod \
+ tst-tlsalign-lib \
+ tst-tls-ie-mod0 \
+ tst-tls-ie-mod1 \
+ tst-tls-ie-mod2 \
+ tst-tls-ie-mod3 \
+ tst-tls-ie-mod4 \
+ tst-tls-ie-mod5 \
+ tst-tls-ie-mod6 \
+ tst-tlsmod1 \
+ tst-tlsmod10 \
+ tst-tlsmod11 \
+ tst-tlsmod12 \
+ tst-tlsmod13 \
+ tst-tlsmod13a \
+ tst-tlsmod14a \
+ tst-tlsmod14b \
+ tst-tlsmod15a \
+ tst-tlsmod15b \
+ tst-tlsmod16a \
+ tst-tlsmod16b \
+ tst-tlsmod17b \
+ tst-tlsmod2 \
+ tst-tlsmod3 \
+ tst-tlsmod4 \
+ tst-tlsmod5 \
+ tst-tlsmod6 \
+ tst-tlsmod7 \
+ tst-tlsmod8 \
+ tst-tlsmod9 \
+ tst-unique1mod1 \
+ tst-unique1mod2 \
+ tst-unique2mod1 \
+ tst-unique2mod2 \
+ tst-unwind-ctor-lib \
+ unload2dep \
+ unload2mod \
+ unload3mod1 \
+ unload3mod2 \
+ unload3mod3 \
+ unload3mod4 \
+ unload4mod1 \
+ unload4mod2 \
+ unload4mod3 \
+ unload4mod4 \
+ unload6mod1 \
+ unload6mod2 \
+ unload6mod3 \
+ unload7mod1 \
+ unload7mod2 \
+ unload8mod1 \
+ unload8mod1x \
+ unload8mod2 \
+ unload8mod3 \
+ unloadmod \
+ vismod1 \
+ vismod2 \
+ vismod3 \
+
+modules-names-cxx = \
+ tst-dlopen-nodelete-reloc-mod1 \
+ tst-dlopen-nodelete-reloc-mod10 \
+ tst-dlopen-nodelete-reloc-mod11 \
+ tst-dlopen-nodelete-reloc-mod12 \
+ tst-dlopen-nodelete-reloc-mod13 \
+ tst-dlopen-nodelete-reloc-mod14 \
+ tst-dlopen-nodelete-reloc-mod15 \
+ tst-dlopen-nodelete-reloc-mod16 \
+ tst-dlopen-nodelete-reloc-mod17 \
+ tst-dlopen-nodelete-reloc-mod2 \
+ tst-dlopen-nodelete-reloc-mod3 \
+ tst-dlopen-nodelete-reloc-mod4 \
+ tst-dlopen-nodelete-reloc-mod5 \
+ tst-dlopen-nodelete-reloc-mod6 \
+ tst-dlopen-nodelete-reloc-mod7 \
+ tst-dlopen-nodelete-reloc-mod8 \
+ tst-dlopen-nodelete-reloc-mod9 \
+ tst-nodelete-rtldmod \
+ tst-nodelete-uniquemod \
+ tst-nodelete-zmod \
+ tst-unique3lib \
+ tst-unique3lib2 \
+ tst-unique4lib \
+
+modules-names += \
+ $(if $(CXX),$(modules-names-cxx)) \
+ $(modules-execstack-$(have-z-execstack)) \
+ $(tst-tls-many-dynamic-modules) \
+ $(tst-tls-many-dynamic-modules-dep) \
+ $(tst-tls-many-dynamic-modules-dep-bad) \
+ $(tlsmod17a-modules) \
+ $(tlsmod18a-modules) \
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.

@ -0,0 +1,73 @@
commit 990c953bce06d77360d2e933faa9a008e2c55405
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Jan 14 20:16:05 2022 +0100
x86: Add x86-64-vN check to early startup
This ISA level covers the glibc build itself. <dl-hwcap-check.h>
cannot be used because this check (by design) happens before
DL_PLATFORM_INIT and the x86 CPU flags initialization.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index 5ee06f94735e5189..36ca1a7126047b86 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -7,6 +7,7 @@ sysdep_routines += get-cpuid-feature-leaf
sysdep-dl-routines += dl-get-cpu-features
sysdep_headers += sys/platform/x86.h bits/platform/x86.h
+CFLAGS-dl-get-cpu-features.os += $(rtld-early-cflags)
CFLAGS-get-cpuid-feature-leaf.o += $(no-stack-protector)
tests += tst-get-cpu-features tst-get-cpu-features-static \
diff --git a/sysdeps/x86/dl-get-cpu-features.c b/sysdeps/x86/dl-get-cpu-features.c
index 839803c746f408ed..6ccde4404b13a725 100644
--- a/sysdeps/x86/dl-get-cpu-features.c
+++ b/sysdeps/x86/dl-get-cpu-features.c
@@ -20,6 +20,7 @@
#ifdef SHARED
# include <cpu-features.c>
+# include <gcc-macros.h>
/* NB: Normally, DL_PLATFORM_INIT calls init_cpu_features to initialize
CPU features in dynamic executable. But when loading ld.so inside of
@@ -36,7 +37,35 @@ _dl_x86_init_cpu_features (void)
{
struct cpu_features *cpu_features = __get_cpu_features ();
if (cpu_features->basic.kind == arch_kind_unknown)
- init_cpu_features (cpu_features);
+ {
+ init_cpu_features (cpu_features);
+
+# if IS_IN (rtld)
+ /* See isa-level.c. */
+# if defined GCCMACRO__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 \
+ && defined HAVE_X86_LAHF_SAHF && defined GCCMACRO__POPCNT__ \
+ && defined GCCMACRO__SSE3__ && defined GCCMACRO__SSSE3__ \
+ && defined GCCMACRO__SSE4_1__ && defined GCCMACRO__SSE4_2__
+ if (!(cpu_features->isa_1 & GNU_PROPERTY_X86_ISA_1_V2))
+ _dl_fatal_printf ("\
+Fatal glibc error: CPU does not support x86-64-v%d\n", 2);
+# if defined GCCMACRO__AVX__ && defined GCCMACRO__AVX2__ \
+ && defined GCCMACRO__F16C__ && defined GCCMACRO__FMA__ \
+ && defined GCCMACRO__LZCNT__ && defined HAVE_X86_MOVBE
+ if (!(cpu_features->isa_1 & GNU_PROPERTY_X86_ISA_1_V3))
+ _dl_fatal_printf ("\
+Fatal glibc error: CPU does not support x86-64-v%d\n", 3);
+# if defined GCCMACRO__AVX512F__ && defined GCCMACRO__AVX512BW__ \
+ && defined GCCMACRO__AVX512CD__ && defined GCCMACRO__AVX512DQ__ \
+ && defined GCCMACRO__AVX512VL__
+ if (!(cpu_features->isa_1 & GNU_PROPERTY_X86_ISA_1_V4))
+ _dl_fatal_printf ("\
+Fatal glibc error: CPU does not support x86-64-v%d\n", 4);
+# endif /* ISA level 4 */
+# endif /* ISA level 3 */
+# endif /* ISA level 2 */
+# endif /* IS_IN (rtld) */
+ }
}
__ifunc (__x86_cpu_features, __x86_cpu_features, NULL, void,

@ -0,0 +1,37 @@
commit f01d482f0355a7029d0715ace0ccf3323e7e94bc
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Jan 14 20:16:05 2022 +0100
s390x: Use <gcc-macros.h> in early HWCAP check
This is required so that the checks still work if $(early-cflags)
selects a different ISA level.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/sysdeps/s390/s390-64/dl-hwcap-check.h b/sysdeps/s390/s390-64/dl-hwcap-check.h
index 87e18be6bd0c512b..27f7e245b1d1a9e9 100644
--- a/sysdeps/s390/s390-64/dl-hwcap-check.h
+++ b/sysdeps/s390/s390-64/dl-hwcap-check.h
@@ -19,17 +19,18 @@
#ifndef _DL_HWCAP_CHECK_H
#define _DL_HWCAP_CHECK_H
+#include <gcc-macros.h>
#include <ldsodefs.h>
static inline void
dl_hwcap_check (void)
{
#if defined __ARCH__
-# if __ARCH__ >= 13
+# if GCCMACRO__ARCH__ >= 13
if (!(GLRO(dl_hwcap) & HWCAP_S390_VXRS_EXT2))
_dl_fatal_printf ("\
Fatal glibc error: CPU lacks VXRS_EXT2 support (z15 or later required)\n");
-# elif __ARCH__ >= 12
+# elif GCCMACRO__ARCH__ >= 12
if (!(GLRO(dl_hwcap) & HWCAP_S390_VXE))
_dl_fatal_printf ("\
Fatal glibc error: CPU lacks VXE support (z14 or later required)\n");

@ -0,0 +1,158 @@
commit c90363403b57b3b7919061851cb3e6d9c85e784a
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Jan 18 13:53:11 2022 +0100
elf: Move _dl_setup_hash to its own file
And compile it with the early CFLAGS. _dl_setup_hash is called
very early for the ld.so link map, so it should be compiled
differently.
Reviewed-by: Stefan Liebler <stli@linux.ibm.com>
Tested-by: Stefan Liebler <stli@linux.ibm.com>
diff --git a/elf/Makefile b/elf/Makefile
index 778e393395fc5248..948296dc2437e9a1 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -69,6 +69,7 @@ dl-routines = \
dl-reloc \
dl-runtime \
dl-scope \
+ dl-setup_hash \
dl-sort-maps \
dl-thread_gscope_wait \
dl-tls \
@@ -154,6 +155,7 @@ CFLAGS-.os += $(call elide-stack-protector,.os,$(all-rtld-routines))
# Add the requested compiler flags to the early startup code.
CFLAGS-dl-printf.os += $(rtld-early-cflags)
+CFLAGS-dl-setup_hash.os += $(rtld-early-cflags)
CFLAGS-dl-sysdep.os += $(rtld-early-cflags)
CFLAGS-dl-tunables.os += $(rtld-early-cflags)
CFLAGS-dl-write.os += $(rtld-early-cflags)
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index eea217eb2833164c..3391a990c8d288e5 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -948,51 +948,6 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
}
-/* Cache the location of MAP's hash table. */
-
-void
-_dl_setup_hash (struct link_map *map)
-{
- Elf_Symndx *hash;
-
- if (__glibc_likely (map->l_info[ELF_MACHINE_GNU_HASH_ADDRIDX] != NULL))
- {
- Elf32_Word *hash32
- = (void *) D_PTR (map, l_info[ELF_MACHINE_GNU_HASH_ADDRIDX]);
- map->l_nbuckets = *hash32++;
- Elf32_Word symbias = *hash32++;
- Elf32_Word bitmask_nwords = *hash32++;
- /* Must be a power of two. */
- assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0);
- map->l_gnu_bitmask_idxbits = bitmask_nwords - 1;
- map->l_gnu_shift = *hash32++;
-
- map->l_gnu_bitmask = (ElfW(Addr) *) hash32;
- hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords;
-
- map->l_gnu_buckets = hash32;
- hash32 += map->l_nbuckets;
- map->l_gnu_chain_zero = hash32 - symbias;
-
- /* Initialize MIPS xhash translation table. */
- ELF_MACHINE_XHASH_SETUP (hash32, symbias, map);
-
- return;
- }
-
- if (!map->l_info[DT_HASH])
- return;
- hash = (void *) D_PTR (map, l_info[DT_HASH]);
-
- map->l_nbuckets = *hash++;
- /* Skip nchain. */
- hash++;
- map->l_buckets = hash;
- hash += map->l_nbuckets;
- map->l_chain = hash;
-}
-
-
static void
_dl_debug_bindings (const char *undef_name, struct link_map *undef_map,
const ElfW(Sym) **ref, struct sym_val *value,
diff --git a/elf/dl-setup_hash.c b/elf/dl-setup_hash.c
new file mode 100644
index 0000000000000000..6dd57c5c94e541c2
--- /dev/null
+++ b/elf/dl-setup_hash.c
@@ -0,0 +1,63 @@
+/* Cache the location of a link map hash table.
+ Copyright (C) 1995-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 <assert.h>
+#include <link.h>
+#include <ldsodefs.h>
+
+void
+_dl_setup_hash (struct link_map *map)
+{
+ Elf_Symndx *hash;
+
+ if (__glibc_likely (map->l_info[ELF_MACHINE_GNU_HASH_ADDRIDX] != NULL))
+ {
+ Elf32_Word *hash32
+ = (void *) D_PTR (map, l_info[ELF_MACHINE_GNU_HASH_ADDRIDX]);
+ map->l_nbuckets = *hash32++;
+ Elf32_Word symbias = *hash32++;
+ Elf32_Word bitmask_nwords = *hash32++;
+ /* Must be a power of two. */
+ assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0);
+ map->l_gnu_bitmask_idxbits = bitmask_nwords - 1;
+ map->l_gnu_shift = *hash32++;
+
+ map->l_gnu_bitmask = (ElfW(Addr) *) hash32;
+ hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords;
+
+ map->l_gnu_buckets = hash32;
+ hash32 += map->l_nbuckets;
+ map->l_gnu_chain_zero = hash32 - symbias;
+
+ /* Initialize MIPS xhash translation table. */
+ ELF_MACHINE_XHASH_SETUP (hash32, symbias, map);
+
+ return;
+ }
+
+ if (!map->l_info[DT_HASH])
+ return;
+ hash = (void *) D_PTR (map, l_info[DT_HASH]);
+
+ map->l_nbuckets = *hash++;
+ /* Skip nchain. */
+ hash++;
+ map->l_buckets = hash;
+ hash += map->l_nbuckets;
+ map->l_chain = hash;
+}

@ -0,0 +1,42 @@
commit f4f70c2895e3d325188a42c10eb7bb4335be6773
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Tue Jan 4 06:58:34 2022 -0800
elf: Add a comment after trailing backslashes
diff --git a/elf/Makefile b/elf/Makefile
index 0cfcf0a61a442c9f..5b9c36bc6f0a3ee5 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -319,6 +319,7 @@ tests-cxx = \
tst-nodelete \
tst-unique3 \
tst-unique4 \
+# tests-cxx
tests += $(if $(CXX),$(tests-cxx))
tests-internal += loadtest unload unload2 circleload1 \
@@ -583,6 +584,7 @@ modules-names = \
vismod1 \
vismod2 \
vismod3 \
+# modules-names
modules-names-cxx = \
tst-dlopen-nodelete-reloc-mod1 \
@@ -608,6 +610,7 @@ modules-names-cxx = \
tst-unique3lib \
tst-unique3lib2 \
tst-unique4lib \
+# modules-names-cxx
modules-names += \
$(if $(CXX),$(modules-names-cxx)) \
@@ -617,6 +620,7 @@ modules-names += \
$(tst-tls-many-dynamic-modules-dep-bad) \
$(tlsmod17a-modules) \
$(tlsmod18a-modules) \
+# modules-names
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.

@ -0,0 +1,171 @@
commit 0835c0f0bad351117154b815f34f8af19ea7e325
Author: Matt Whitlock <sourceware@mattwhitlock.name>
Date: Wed Jun 16 23:40:47 2021 -0400
x86: fix Autoconf caching of instruction support checks [BZ #27991]
The Autoconf documentation for the AC_CACHE_CHECK macro states:
The commands-to-set-it must have no side effects except for setting
the variable cache-id, see below.
However, the tests for support of -msahf and -mmovbe were embedded in
the commands-to-set-it for lib_cv_include_x86_isa_level. This had the
consequence that libc_cv_have_x86_lahf_sahf and libc_cv_have_x86_movbe
were not defined whenever lib_cv_include_x86_isa_level was read from
cache. These variables' being undefined meant that their unquoted use
in later test expressions led to the 'test' built-in's misparsing its
arguments and emitting errors like "test: =: unexpected operator" or
"test: =: unary operator expected", depending on the particular shell.
This commit refactors the tests for LAHF/SAHF and MOVBE instruction
support into their own AC_CACHE_CHECK macro invocations to obey the
rule that the commands-to-set-it must have no side effects other than
setting the variable named by cache-id.
Signed-off-by: Matt Whitlock <sourceware@mattwhitlock.name>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure
index ead1295c38cf5f4e..62676bb686850938 100644
--- a/sysdeps/x86/configure
+++ b/sysdeps/x86/configure
@@ -126,8 +126,6 @@ cat > conftest2.S <<EOF
4:
EOF
libc_cv_include_x86_isa_level=no
-libc_cv_have_x86_lahf_sahf=no
-libc_cv_have_x86_movbe=no
if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest conftest1.S conftest2.S'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
@@ -137,9 +135,22 @@ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest c
count=`LC_ALL=C $READELF -n conftest | grep NT_GNU_PROPERTY_TYPE_0 | wc -l`
if test "$count" = 1; then
libc_cv_include_x86_isa_level=yes
- cat > conftest.c <<EOF
-EOF
- if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c'
+ fi
+fi
+rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_include_x86_isa_level" >&5
+$as_echo "$libc_cv_include_x86_isa_level" >&6; }
+if test $libc_cv_include_x86_isa_level = yes; then
+ $as_echo "#define INCLUDE_X86_ISA_LEVEL 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LAHF/SAHF instruction support" >&5
+$as_echo_n "checking for LAHF/SAHF instruction support... " >&6; }
+if ${libc_cv_have_x86_lahf_sahf+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ libc_cv_have_x86_lahf_sahf=no
+ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
@@ -147,7 +158,20 @@ EOF
test $ac_status = 0; }; } | grep -q "\-msahf"; then
libc_cv_have_x86_lahf_sahf=yes
fi
- if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_have_x86_lahf_sahf" >&5
+$as_echo "$libc_cv_have_x86_lahf_sahf" >&6; }
+ if test $libc_cv_have_x86_lahf_sahf = yes; then
+ $as_echo "#define HAVE_X86_LAHF_SAHF 1" >>confdefs.h
+
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MOVBE instruction support" >&5
+$as_echo_n "checking for MOVBE instruction support... " >&6; }
+if ${libc_cv_have_x86_movbe+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ libc_cv_have_x86_movbe=no
+ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
ac_status=$?
@@ -155,23 +179,13 @@ EOF
test $ac_status = 0; }; } | grep -q "\-mmovbe"; then
libc_cv_have_x86_movbe=yes
fi
- fi
-fi
-rm -f conftest*
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_include_x86_isa_level" >&5
-$as_echo "$libc_cv_include_x86_isa_level" >&6; }
-if test $libc_cv_include_x86_isa_level = yes; then
- $as_echo "#define INCLUDE_X86_ISA_LEVEL 1" >>confdefs.h
-
fi
-if test $libc_cv_have_x86_lahf_sahf = yes; then
- $as_echo "#define HAVE_X86_LAHF_SAHF 1" >>confdefs.h
-
-fi
-if test $libc_cv_have_x86_movbe = yes; then
- $as_echo "#define HAVE_X86_MOVBE 1" >>confdefs.h
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_have_x86_movbe" >&5
+$as_echo "$libc_cv_have_x86_movbe" >&6; }
+ if test $libc_cv_have_x86_movbe = yes; then
+ $as_echo "#define HAVE_X86_MOVBE 1" >>confdefs.h
+ fi
fi
config_vars="$config_vars
enable-x86-isa-level = $libc_cv_include_x86_isa_level"
diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac
index bca97fdc2f1ac1a7..04a12ab68048cd66 100644
--- a/sysdeps/x86/configure.ac
+++ b/sysdeps/x86/configure.ac
@@ -98,30 +98,32 @@ cat > conftest2.S <<EOF
4:
EOF
libc_cv_include_x86_isa_level=no
-libc_cv_have_x86_lahf_sahf=no
-libc_cv_have_x86_movbe=no
if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest conftest1.S conftest2.S); then
count=`LC_ALL=C $READELF -n conftest | grep NT_GNU_PROPERTY_TYPE_0 | wc -l`
if test "$count" = 1; then
libc_cv_include_x86_isa_level=yes
- cat > conftest.c <<EOF
-EOF
- if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c) | grep -q "\-msahf"; then
- libc_cv_have_x86_lahf_sahf=yes
- fi
- if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c) | grep -q "\-mmovbe"; then
- libc_cv_have_x86_movbe=yes
- fi
fi
fi
rm -f conftest*])
if test $libc_cv_include_x86_isa_level = yes; then
AC_DEFINE(INCLUDE_X86_ISA_LEVEL)
-fi
-if test $libc_cv_have_x86_lahf_sahf = yes; then
- AC_DEFINE(HAVE_X86_LAHF_SAHF)
-fi
-if test $libc_cv_have_x86_movbe = yes; then
- AC_DEFINE(HAVE_X86_MOVBE)
+ AC_CACHE_CHECK([for LAHF/SAHF instruction support],
+ libc_cv_have_x86_lahf_sahf, [dnl
+ libc_cv_have_x86_lahf_sahf=no
+ if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null) | grep -q "\-msahf"; then
+ libc_cv_have_x86_lahf_sahf=yes
+ fi])
+ if test $libc_cv_have_x86_lahf_sahf = yes; then
+ AC_DEFINE(HAVE_X86_LAHF_SAHF)
+ fi
+ AC_CACHE_CHECK([for MOVBE instruction support],
+ libc_cv_have_x86_movbe, [dnl
+ libc_cv_have_x86_movbe=no
+ if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null) | grep -q "\-mmovbe"; then
+ libc_cv_have_x86_movbe=yes
+ fi])
+ if test $libc_cv_have_x86_movbe = yes; then
+ AC_DEFINE(HAVE_X86_MOVBE)
+ fi
fi
LIBC_CONFIG_VAR([enable-x86-isa-level], [$libc_cv_include_x86_isa_level])

@ -0,0 +1,58 @@
commit 5732a881aad24fac876f5505a212395048a7a483
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Jan 14 16:09:20 2022 +0100
x86: HAVE_X86_LAHF_SAHF, HAVE_X86_MOVBE and -march=x86-64-vN (bug 28782)
HAVE_X86_LAHF_SAHF is implied by x86-64-v2, and HAVE_X86_MOVBE by
x86-64-v3.
The individual flag does not appear in -fverbose-asm flag output
even if the ISA level implies it.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure
index 62676bb686850938..7bdbfdc6dc2ad38f 100644
--- a/sysdeps/x86/configure
+++ b/sysdeps/x86/configure
@@ -155,7 +155,7 @@ else
(eval $ac_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; } | grep -q "\-msahf"; then
+ test $ac_status = 0; }; } | grep -qE '(-msahf\b|-march=x86-64-v)'; then
libc_cv_have_x86_lahf_sahf=yes
fi
fi
@@ -176,7 +176,7 @@ else
(eval $ac_try) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; } | grep -q "\-mmovbe"; then
+ test $ac_status = 0; }; } | grep -qE '(-mmovbe\b|-march=x86-64-v([3-9]|[1-9][0-9]))'; then
libc_cv_have_x86_movbe=yes
fi
fi
diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac
index 04a12ab68048cd66..10d5c2e0e555fc79 100644
--- a/sysdeps/x86/configure.ac
+++ b/sysdeps/x86/configure.ac
@@ -110,7 +110,7 @@ if test $libc_cv_include_x86_isa_level = yes; then
AC_CACHE_CHECK([for LAHF/SAHF instruction support],
libc_cv_have_x86_lahf_sahf, [dnl
libc_cv_have_x86_lahf_sahf=no
- if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null) | grep -q "\-msahf"; then
+ if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null) | grep -qE '(-msahf\b|-march=x86-64-v)'; then
libc_cv_have_x86_lahf_sahf=yes
fi])
if test $libc_cv_have_x86_lahf_sahf = yes; then
@@ -119,7 +119,7 @@ if test $libc_cv_include_x86_isa_level = yes; then
AC_CACHE_CHECK([for MOVBE instruction support],
libc_cv_have_x86_movbe, [dnl
libc_cv_have_x86_movbe=no
- if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null) | grep -q "\-mmovbe"; then
+ if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null) | grep -qE '(-mmovbe\b|-march=x86-64-v(@<:@3-9@:>@|@<:@1-9@:>@@<:@0-9@:>@))'; then
libc_cv_have_x86_movbe=yes
fi])
if test $libc_cv_have_x86_movbe = yes; then

@ -0,0 +1,32 @@
commit ef7c6d42fe163a5e49a478c43e655ce4633fa5ba
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Jan 14 16:09:20 2022 +0100
Generate gcc-macros.h
The file can be used to check the effect of the default compiler
flags on code generation even in areas of the build that uses
non-default compiler flags.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
diff --git a/Makeconfig b/Makeconfig
index 8bc5540292c7b6fa..99898a632a64be91 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -1202,6 +1202,15 @@ $(common-objpfx)dl-tunable-list.stmp: \
touch $@
endif
+# Dump the GCC macros used by the default compiler flags to a header
+# file, so that they can be inspected when using different compiler
+# flags. Add the GCCMACRO prefix to make these macro names unique.
+$(common-objpfx)gcc-macros.h.in: $(common-objpfx)config.status
+ $(CC) $(CFLAGS) $(CPPFLAGS) -E -dM -x c -o $@ /dev/null
+$(common-objpfx)gcc-macros.h: $(common-objpfx)gcc-macros.h.in
+ sed 's/^#define /#define GCCMACRO/' < $< > $@
+before-compile += $(common-objpfx)gcc-macros.h
+
# Generate version maps, but wait until sysdep-subdirs is known
ifeq ($(sysd-sorted-done),t)
ifeq ($(build-shared),yes)

@ -0,0 +1,549 @@
commit 7de01e60c200c431d3469deb784da8fd4508fc15
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Jan 14 20:16:05 2022 +0100
elf/Makefile: Reflow and sort most variable assignments
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Conflicts:
elf/Makefile
(Usual backporting differences. LLD support is missing
downstream.)
diff --git a/elf/Makefile b/elf/Makefile
index 5b9c36bc6f0a3ee5..124905f96c88ab53 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -21,21 +21,62 @@ subdir := elf
include ../Makeconfig
-headers = elf.h bits/elfclass.h link.h bits/link.h
-routines = $(all-dl-routines) dl-support dl-iteratephdr \
- dl-addr dl-addr-obj enbl-secure dl-profstub \
- dl-origin dl-libc dl-sym dl-sysdep dl-error \
- dl-reloc-static-pie libc_early_init rtld_static_init
+headers = \
+ bits/elfclass.h \
+ bits/link.h \
+ elf.h \
+ link.h \
+ # headers
+
+routines = \
+ $(all-dl-routines) \
+ dl-addr \
+ dl-addr-obj \
+ dl-error \
+ dl-iteratephdr \
+ dl-libc \
+ dl-origin \
+ dl-profstub \
+ dl-reloc-static-pie \
+ dl-support \
+ dl-sym \
+ dl-sysdep \
+ enbl-secure \
+ libc_early_init \
+ rtld_static_init \
+ # routines
# The core dynamic linking functions are in libc for the static and
# profiled libraries.
-dl-routines = $(addprefix dl-,load lookup object reloc deps \
- runtime init fini debug misc \
- version profile tls origin scope \
- execstack open close trampoline \
- exception sort-maps lookup-direct \
- call-libc-early-init write \
- thread_gscope_wait tls_init_tp)
+dl-routines = \
+ dl-call-libc-early-init \
+ dl-close \
+ dl-debug \
+ dl-deps \
+ dl-exception \
+ dl-execstack \
+ dl-fini \
+ dl-init \
+ dl-load \
+ dl-lookup \
+ dl-lookup-direct \
+ dl-misc \
+ dl-object \
+ dl-open \
+ dl-origin \
+ dl-profile \
+ dl-reloc \
+ dl-runtime \
+ dl-scope \
+ dl-sort-maps \
+ dl-thread_gscope_wait \
+ dl-tls \
+ dl-tls_init_tp \
+ dl-trampoline \
+ dl-version \
+ dl-write \
+ # dl-routines
+
ifeq (yes,$(use-ldconfig))
dl-routines += dl-cache
endif
@@ -58,16 +99,38 @@ endif
all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
# But they are absent from the shared libc, because that code is in ld.so.
-elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \
- dl-sysdep dl-exception dl-reloc-static-pie \
- thread_gscope_wait rtld_static_init
+elide-routines.os = \
+ $(all-dl-routines) \
+ dl-exception \
+ dl-origin \
+ dl-reloc-static-pie \
+ dl-support \
+ dl-sysdep \
+ enbl-secure \
+ rtld_static_init \
+ thread_gscope_wait \
+ # elide-routines.os
# ld.so uses those routines, plus some special stuff for being the program
# 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-diagnostics dl-diagnostics-kernel dl-diagnostics-cpu \
- dl-mutex
+rtld-routines = \
+ $(all-dl-routines) \
+ dl-conflict \
+ dl-diagnostics \
+ dl-diagnostics-cpu \
+ dl-diagnostics-kernel \
+ dl-environ \
+ dl-error-minimal \
+ dl-hwcaps \
+ dl-hwcaps-subdirs \
+ dl-hwcaps_split \
+ dl-minimal \
+ dl-mutex \
+ dl-sysdep \
+ dl-usage \
+ rtld \
+ # rtld-routines
+
all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines)
CFLAGS-dl-runtime.c += -fexceptions -fasynchronous-unwind-tables
@@ -102,8 +165,16 @@ ld-map = $(common-objpfx)ld.map
endif
ifeq (yes,$(build-shared))
-extra-objs = $(all-rtld-routines:%=%.os) sofini.os interp.os
-generated += librtld.os dl-allobjs.os ld.so ldd
+extra-objs = \
+ $(all-rtld-routines:%=%.os) \
+ sofini.os \
+ interp.os \
+ # extra-objs
+generated += \
+ dl-allobjs.os \
+ ld.so ldd \
+ librtld.os \
+ # generated
install-others = $(inst_rtlddir)/$(rtld-installed-name) $(inst_bindir)/ld.so
install-bin-script = ldd
endif
@@ -121,8 +192,15 @@ others-static += ldconfig
others += ldconfig
install-rootsbin += ldconfig
-ldconfig-modules := cache readlib xmalloc xstrdup chroot_canon static-stubs \
- stringtable
+ldconfig-modules := \
+ cache \
+ chroot_canon \
+ readlib \
+ static-stubs \
+ stringtable \
+ xmalloc \
+ xstrdup \
+ # ldconfig-modules
extra-objs += $(ldconfig-modules:=.o)
others-extras = $(ldconfig-modules)
endif
@@ -156,23 +234,36 @@ $(inst_auditdir)/sotruss-lib.so: $(objpfx)sotruss-lib.so $(+force)
$(do-install-program)
endif
-tests-static-normal := 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-single_threaded-static tst-single_threaded-pthread-static \
- tst-dst-static tst-getauxval-static
-
-tests-static-internal := tst-tls1-static tst-tls2-static \
- tst-ptrguard1-static tst-stackguard1-static \
- tst-tls1-static-non-pie
+tests-static-normal := \
+ tst-array1-static \
+ tst-array5-static \
+ tst-dl-iter-static \
+ tst-dst-static \
+ tst-env-setuid \
+ tst-env-setuid-tunables \
+ tst-getauxval-static \
+ tst-linkall-static \
+ tst-single_threaded-pthread-static \
+ tst-single_threaded-static \
+ tst-tlsalign-extern-static \
+ tst-tlsalign-static \
+ # tests-static-normal
+
+tests-static-internal := \
+ tst-ptrguard1-static \
+ tst-stackguard1-static \
+ tst-tls1-static \
+ tst-tls2-static \
+ tst-tls1-static-non-pie \
+ # tests-static-internal
CRT-tst-tls1-static-non-pie := $(csu-objpfx)crt1.o
tst-tls1-static-non-pie-no-pie = yes
tests-container := \
- tst-ldconfig-bad-aux-cache \
- tst-ldconfig-ld_so_conf-update
+ tst-ldconfig-bad-aux-cache \
+ tst-ldconfig-ld_so_conf-update \
+ # tests-container
ifeq (no,$(build-hardcoded-path-in-tests))
# This is an ld.so.cache test, and RPATH/RUNPATH in the executable
@@ -180,14 +271,32 @@ ifeq (no,$(build-hardcoded-path-in-tests))
tests-container += tst-glibc-hwcaps-prepend-cache
endif
-tests := tst-tls9 tst-leaks1 \
- tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \
- tst-auxv tst-stringtable
-tests-internal := tst-tls1 tst-tls2 $(tests-static-internal)
+tests := \
+ tst-array1 \
+ tst-array2 \
+ tst-array3 \
+ tst-array4 \
+ tst-array5 \
+ tst-auxv \
+ tst-leaks1 \
+ tst-stringtable \
+ tst-tls9 \
+ # tests
+
+tests-internal := \
+ $(tests-static-internal) \
+ tst-tls1 \
+ tst-tls2 \
+ # tests-internal
+
tests-static := $(tests-static-normal) $(tests-static-internal)
ifeq (yes,$(build-shared))
-tests-static += tst-tls9-static tst-single_threaded-static-dlopen
+tests-static += \
+ tst-single_threaded-static-dlopen \
+ tst-tls9-static \
+ # tests-static
+
static-dlopen-environment = \
LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx)dlfcn
tst-tls9-static-ENV = $(static-dlopen-environment)
@@ -313,33 +422,69 @@ tests += \
unload6 \
unload7 \
unload8 \
-# reldep9
+ # tests
tests-cxx = \
tst-dlopen-nodelete-reloc \
tst-nodelete \
tst-unique3 \
tst-unique4 \
-# tests-cxx
+ # tests-cxx
tests += $(if $(CXX),$(tests-cxx))
-tests-internal += loadtest unload unload2 circleload1 \
- neededtest neededtest2 neededtest3 neededtest4 \
- tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \
- tst-ptrguard1 tst-stackguard1 \
- tst-create_format1 tst-tls-surplus tst-dl-hwcaps_split
-tests-container += tst-pldd tst-dlopen-tlsmodid-container \
- tst-dlopen-self-container tst-preload-pthread-libc
-test-srcs = tst-pathopt
+
+tests-internal += \
+ circleload1 \
+ loadtest \
+ neededtest \
+ neededtest2 \
+ neededtest3 \
+ neededtest4 \
+ tst-create_format1 \
+ tst-dl-hwcaps_split \
+ tst-dlmopen2 \
+ tst-ptrguard1 \
+ tst-stackguard1 \
+ tst-tls-surplus \
+ tst-tls3 \
+ tst-tls6 \
+ tst-tls7 \
+ tst-tls8 \
+ unload \
+ unload2 \
+ # tests-internal
+
+tests-container += \
+ tst-dlopen-self-container \
+ tst-dlopen-tlsmodid-container \
+ tst-pldd \
+ tst-preload-pthread-libc \
+ # tests-container
+
+test-srcs = \
+ tst-pathopt \
+ # tests-srcs
+
+ifeq (yes,$(have-fpie))
+tests-pie += tst-align3
+endif
selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null)
+
ifneq ($(selinux-enabled),1)
-tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
+tests-execstack-yes = \
+ tst-execstack \
+ tst-execstack-needed \
+ tst-execstack-prog \
+ # tests-execstack-yes
endif
endif
tests += $(tests-execstack-$(have-z-execstack))
ifeq ($(run-built-tests),yes)
-tests-special += $(objpfx)tst-leaks1-mem.out \
- $(objpfx)noload-mem.out \
- $(objpfx)tst-ldconfig-X.out $(objpfx)tst-rtld-help.out
+tests-special += \
+ $(objpfx)noload-mem.out \
+ $(objpfx)tst-ldconfig-X.out \
+ $(objpfx)tst-leaks1-mem.out \
+ $(objpfx)tst-rtld-help.out \
+ # tests-special
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
@@ -356,9 +501,16 @@ tst-tls-many-dynamic-modules-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
+extra-test-objs += \
+ $(tlsmod17a-modules:=.os) \
+ $(tlsmod18a-modules:=.os) \
+ tst-tlsalign-vars.o \
+ # extra-test-objs
+test-extras += \
+ tst-tlsalign-vars \
+ tst-tlsmod17a \
+ tst-tlsmod18a \
+ # test-extras
modules-names = \
circlemod1 \
circlemod1a \
@@ -610,17 +762,17 @@ modules-names-cxx = \
tst-unique3lib \
tst-unique3lib2 \
tst-unique4lib \
-# modules-names-cxx
+ # modules-names-cxx
modules-names += \
$(if $(CXX),$(modules-names-cxx)) \
$(modules-execstack-$(have-z-execstack)) \
+ $(tlsmod17a-modules) \
+ $(tlsmod18a-modules) \
$(tst-tls-many-dynamic-modules) \
$(tst-tls-many-dynamic-modules-dep) \
$(tst-tls-many-dynamic-modules-dep-bad) \
- $(tlsmod17a-modules) \
- $(tlsmod18a-modules) \
-# modules-names
+ # modules-names
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.
@@ -669,35 +821,70 @@ modules-names-nobuild := filtmod1 tst-big-note-lib tst-ro-dynamic-mod
tests += $(tests-static)
ifeq (yes,$(have-ifunc))
-tests-ifuncstatic := ifuncmain1static ifuncmain1picstatic \
- ifuncmain2static ifuncmain2picstatic \
- ifuncmain4static ifuncmain4picstatic \
- ifuncmain5static ifuncmain5picstatic \
- ifuncmain7static ifuncmain7picstatic
+tests-ifuncstatic := \
+ ifuncmain1static \
+ ifuncmain1picstatic \
+ ifuncmain2static \
+ ifuncmain2picstatic \
+ ifuncmain4static \
+ ifuncmain4picstatic \
+ ifuncmain5static \
+ ifuncmain5picstatic \
+ ifuncmain7static \
+ ifuncmain7picstatic \
+ # tests-ifuncstatic
ifeq (yes,$(have-gcc-ifunc))
tests-ifuncstatic += ifuncmain9static ifuncmain9picstatic
endif
tests-static += $(tests-ifuncstatic)
tests-internal += $(tests-ifuncstatic)
ifeq (yes,$(build-shared))
-tests += tst-ifunc-fault-lazy tst-ifunc-fault-bindnow
+tests += \
+ tst-ifunc-fault-bindnow \
+ tst-ifunc-fault-lazy \
+ # tests
# Note: sysdeps/x86_64/ifuncmain8.c uses ifuncmain8.
tests-internal += \
- ifuncmain1 ifuncmain1pic ifuncmain1vis ifuncmain1vispic \
- ifuncmain1staticpic \
- ifuncmain2 ifuncmain2pic ifuncmain3 ifuncmain4 \
- ifuncmain5 ifuncmain5pic ifuncmain5staticpic \
- ifuncmain7 ifuncmain7pic
+ ifuncmain1 \
+ ifuncmain1pic \
+ ifuncmain1staticpic \
+ ifuncmain1vis \
+ ifuncmain1vispic \
+ ifuncmain2 \
+ ifuncmain2pic \
+ ifuncmain3 \
+ ifuncmain4 \
+ ifuncmain5 \
+ ifuncmain5pic \
+ ifuncmain5staticpic \
+ ifuncmain7 \
+ ifuncmain7pic \
+ # tests-internal
ifeq (yes,$(have-gcc-ifunc))
-tests-internal += ifuncmain9 ifuncmain9pic
+tests-internal += \
+ ifuncmain9 \
+ ifuncmain9pic \
+ # tests-internal
endif
-ifunc-test-modules = ifuncdep1 ifuncdep1pic ifuncdep2 ifuncdep2pic \
- ifuncdep5 ifuncdep5pic
+ifunc-test-modules = \
+ ifuncdep1 \
+ ifuncdep1pic \
+ ifuncdep2 \
+ ifuncdep2pic \
+ ifuncdep5 \
+ ifuncdep5pic \
+ # ifunc-test-modules
extra-test-objs += $(ifunc-test-modules:=.o)
test-internal-extras += $(ifunc-test-modules)
ifeq (yes,$(have-fpie))
-ifunc-pie-tests = ifuncmain1pie ifuncmain1vispie ifuncmain1staticpie \
- ifuncmain5pie ifuncmain6pie ifuncmain7pie
+ifunc-pie-tests = \
+ ifuncmain1pie \
+ ifuncmain1staticpie \
+ ifuncmain1vispie \
+ ifuncmain5pie \
+ ifuncmain6pie \
+ ifuncmain7pie \
+ # ifunc-pie-tests
ifeq (yes,$(have-gcc-ifunc))
ifunc-pie-tests += ifuncmain9pie
endif
@@ -707,30 +894,50 @@ endif
tests-internal += $(ifunc-pie-tests)
tests-pie += $(ifunc-pie-tests)
endif
-modules-names += ifuncmod1 ifuncmod3 ifuncmod5 ifuncmod6
+modules-names += \
+ ifuncmod1 \
+ ifuncmod3 \
+ ifuncmod5 \
+ ifuncmod6 \
+ # module-names
endif
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-help.out
+tests-special += \
+ $(objpfx)argv0test.out \
+ $(objpfx)tst-pathopt.out \
+ $(objpfx)tst-rtld-help.out \
+ $(objpfx)tst-rtld-load-self.out \
+ $(objpfx)tst-rtld-preload.out \
+ # tests-special
endif
-tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \
- $(objpfx)check-wx-segment.out \
- $(objpfx)check-localplt.out $(objpfx)check-initfini.out
+tests-special += \
+ $(objpfx)check-execstack.out \
+ $(objpfx)check-initfini.out \
+ $(objpfx)check-localplt.out \
+ $(objpfx)check-textrel.out \
+ $(objpfx)check-wx-segment.out \
+ # tests-special
endif
ifeq ($(run-built-tests),yes)
-tests-special += $(objpfx)order-cmp.out $(objpfx)tst-array1-cmp.out \
- $(objpfx)tst-array1-static-cmp.out \
- $(objpfx)tst-array2-cmp.out $(objpfx)tst-array3-cmp.out \
- $(objpfx)tst-array4-cmp.out $(objpfx)tst-array5-cmp.out \
- $(objpfx)tst-array5-static-cmp.out $(objpfx)order2-cmp.out \
- $(objpfx)tst-initorder-cmp.out \
- $(objpfx)tst-initorder2-cmp.out $(objpfx)tst-unused-dep.out \
- $(objpfx)tst-unused-dep-cmp.out
+tests-special += \
+ $(objpfx)order-cmp.out \
+ $(objpfx)order2-cmp.out \
+ $(objpfx)tst-array1-cmp.out \
+ $(objpfx)tst-array1-static-cmp.out \
+ $(objpfx)tst-array2-cmp.out \
+ $(objpfx)tst-array3-cmp.out \
+ $(objpfx)tst-array4-cmp.out \
+ $(objpfx)tst-array5-cmp.out \
+ $(objpfx)tst-array5-static-cmp.out \
+ $(objpfx)tst-initorder-cmp.out \
+ $(objpfx)tst-initorder2-cmp.out \
+ $(objpfx)tst-unused-dep-cmp.out \
+ $(objpfx)tst-unused-dep.out \
+ # tests-special
endif
ifndef avoid-generated
@@ -835,6 +1042,7 @@ rtld-stubbed-symbols = \
free \
malloc \
realloc \
+ # rtld-stubbed-symbols
ifeq ($(have-ssp),yes)
# rtld is not built with the stack protector, so these references will

@ -0,0 +1,633 @@
commit b693d75f0c611bce9b0ad984bad306121d42c535
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Jan 14 20:16:05 2022 +0100
elf: Split dl-printf.c from dl-misc.c
This allows to use different compiler flags for the diagnostics
code.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
diff --git a/elf/Makefile b/elf/Makefile
index 124905f96c88ab53..52aafc89cec835ab 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -64,6 +64,7 @@ dl-routines = \
dl-object \
dl-open \
dl-origin \
+ dl-printf \
dl-profile \
dl-reloc \
dl-runtime \
diff --git a/elf/dl-misc.c b/elf/dl-misc.c
index b256d792c6198683..f17140b129343f7b 100644
--- a/elf/dl-misc.c
+++ b/elf/dl-misc.c
@@ -16,24 +16,16 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <assert.h>
+#include <_itoa.h>
#include <fcntl.h>
#include <ldsodefs.h>
-#include <limits.h>
#include <link.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
+#include <not-cancel.h>
#include <stdint.h>
+#include <stdlib.h>
#include <sys/mman.h>
-#include <sys/param.h>
#include <sys/stat.h>
-#include <sys/uio.h>
-#include <sysdep.h>
-#include <_itoa.h>
-#include <dl-writev.h>
-#include <not-cancel.h>
+#include <unistd.h>
/* Read the whole contents of FILE into new mmap'd space with given
protections. *SIZEP gets the size of the file. On error MAP_FAILED
@@ -70,270 +62,6 @@ _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
return result;
}
-
-/* Bare-bones printf implementation. This function only knows about
- the formats and flags needed and can handle only up to 64 stripes in
- the output. */
-static void
-_dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
-{
-# define NIOVMAX 64
- struct iovec iov[NIOVMAX];
- int niov = 0;
- pid_t pid = 0;
- char pidbuf[12];
-
- while (*fmt != '\0')
- {
- const char *startp = fmt;
-
- if (tag_p > 0)
- {
- /* Generate the tag line once. It consists of the PID and a
- colon followed by a tab. */
- if (pid == 0)
- {
- char *p;
- pid = __getpid ();
- assert (pid >= 0 && sizeof (pid_t) <= 4);
- p = _itoa (pid, &pidbuf[10], 10, 0);
- while (p > pidbuf)
- *--p = ' ';
- pidbuf[10] = ':';
- pidbuf[11] = '\t';
- }
-
- /* Append to the output. */
- assert (niov < NIOVMAX);
- iov[niov].iov_len = 12;
- iov[niov++].iov_base = pidbuf;
-
- /* No more tags until we see the next newline. */
- tag_p = -1;
- }
-
- /* Skip everything except % and \n (if tags are needed). */
- while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
- ++fmt;
-
- /* Append constant string. */
- assert (niov < NIOVMAX);
- if ((iov[niov].iov_len = fmt - startp) != 0)
- iov[niov++].iov_base = (char *) startp;
-
- if (*fmt == '%')
- {
- /* It is a format specifier. */
- char fill = ' ';
- int width = -1;
- int prec = -1;
-#if LONG_MAX != INT_MAX
- int long_mod = 0;
-#endif
-
- /* Recognize zero-digit fill flag. */
- if (*++fmt == '0')
- {
- fill = '0';
- ++fmt;
- }
-
- /* See whether with comes from a parameter. Note that no other
- way to specify the width is implemented. */
- if (*fmt == '*')
- {
- width = va_arg (arg, int);
- ++fmt;
- }
-
- /* Handle precision. */
- if (*fmt == '.' && fmt[1] == '*')
- {
- prec = va_arg (arg, int);
- fmt += 2;
- }
-
- /* Recognize the l modifier. It is only important on some
- platforms where long and int have a different size. We
- can use the same code for size_t. */
- if (*fmt == 'l' || *fmt == 'Z')
- {
-#if LONG_MAX != INT_MAX
- long_mod = 1;
-#endif
- ++fmt;
- }
-
- switch (*fmt)
- {
- /* Integer formatting. */
- case 'd':
- case 'u':
- case 'x':
- {
- /* We have to make a difference if long and int have a
- different size. */
-#if LONG_MAX != INT_MAX
- unsigned long int num = (long_mod
- ? va_arg (arg, unsigned long int)
- : va_arg (arg, unsigned int));
-#else
- unsigned long int num = va_arg (arg, unsigned int);
-#endif
- bool negative = false;
- if (*fmt == 'd')
- {
-#if LONG_MAX != INT_MAX
- if (long_mod)
- {
- if ((long int) num < 0)
- negative = true;
- }
- else
- {
- if ((int) num < 0)
- {
- num = (unsigned int) num;
- negative = true;
- }
- }
-#else
- if ((int) num < 0)
- negative = true;
-#endif
- }
-
- /* We use alloca() to allocate the buffer with the most
- pessimistic guess for the size. Using alloca() allows
- having more than one integer formatting in a call. */
- char *buf = (char *) alloca (1 + 3 * sizeof (unsigned long int));
- char *endp = &buf[1 + 3 * sizeof (unsigned long int)];
- char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
-
- /* Pad to the width the user specified. */
- if (width != -1)
- while (endp - cp < width)
- *--cp = fill;
-
- if (negative)
- *--cp = '-';
-
- iov[niov].iov_base = cp;
- iov[niov].iov_len = endp - cp;
- ++niov;
- }
- break;
-
- case 's':
- /* Get the string argument. */
- iov[niov].iov_base = va_arg (arg, char *);
- iov[niov].iov_len = strlen (iov[niov].iov_base);
- if (prec != -1)
- iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
- ++niov;
- break;
-
- case '%':
- iov[niov].iov_base = (void *) fmt;
- iov[niov].iov_len = 1;
- ++niov;
- break;
-
- default:
- assert (! "invalid format specifier");
- }
- ++fmt;
- }
- else if (*fmt == '\n')
- {
- /* See whether we have to print a single newline character. */
- if (fmt == startp)
- {
- iov[niov].iov_base = (char *) startp;
- iov[niov++].iov_len = 1;
- }
- else
- /* No, just add it to the rest of the string. */
- ++iov[niov - 1].iov_len;
-
- /* Next line, print a tag again. */
- tag_p = 1;
- ++fmt;
- }
- }
-
- /* Finally write the result. */
- _dl_writev (fd, iov, niov);
-}
-
-
-/* Write to debug file. */
-void
-_dl_debug_printf (const char *fmt, ...)
-{
- va_list arg;
-
- va_start (arg, fmt);
- _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
- va_end (arg);
-}
-
-
-/* Write to debug file but don't start with a tag. */
-void
-_dl_debug_printf_c (const char *fmt, ...)
-{
- va_list arg;
-
- va_start (arg, fmt);
- _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
- va_end (arg);
-}
-
-
-/* Write the given file descriptor. */
-void
-_dl_dprintf (int fd, const char *fmt, ...)
-{
- va_list arg;
-
- va_start (arg, fmt);
- _dl_debug_vdprintf (fd, 0, fmt, arg);
- va_end (arg);
-}
-
-void
-_dl_printf (const char *fmt, ...)
-{
- va_list arg;
-
- va_start (arg, fmt);
- _dl_debug_vdprintf (STDOUT_FILENO, 0, fmt, arg);
- va_end (arg);
-}
-
-void
-_dl_error_printf (const char *fmt, ...)
-{
- va_list arg;
-
- va_start (arg, fmt);
- _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg);
- va_end (arg);
-}
-
-void
-_dl_fatal_printf (const char *fmt, ...)
-{
- va_list arg;
-
- va_start (arg, fmt);
- _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg);
- va_end (arg);
- _exit (127);
-}
-rtld_hidden_def (_dl_fatal_printf)
-
/* Test whether given NAME matches any of the names of the given object. */
int
_dl_name_match_p (const char *name, const struct link_map *map)
@@ -354,7 +82,6 @@ _dl_name_match_p (const char *name, const struct link_map *map)
return 0;
}
-
unsigned long int
_dl_higher_prime_number (unsigned long int n)
{
diff --git a/elf/dl-printf.c b/elf/dl-printf.c
new file mode 100644
index 0000000000000000..d3264ba96cd959bf
--- /dev/null
+++ b/elf/dl-printf.c
@@ -0,0 +1,292 @@
+/* printf implementation for the dynamic loader.
+ Copyright (C) 1997-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 <_itoa.h>
+#include <assert.h>
+#include <dl-writev.h>
+#include <ldsodefs.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+/* Bare-bones printf implementation. This function only knows about
+ the formats and flags needed and can handle only up to 64 stripes in
+ the output. */
+static void
+_dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
+{
+# define NIOVMAX 64
+ struct iovec iov[NIOVMAX];
+ int niov = 0;
+ pid_t pid = 0;
+ char pidbuf[12];
+
+ while (*fmt != '\0')
+ {
+ const char *startp = fmt;
+
+ if (tag_p > 0)
+ {
+ /* Generate the tag line once. It consists of the PID and a
+ colon followed by a tab. */
+ if (pid == 0)
+ {
+ char *p;
+ pid = __getpid ();
+ assert (pid >= 0 && sizeof (pid_t) <= 4);
+ p = _itoa (pid, &pidbuf[10], 10, 0);
+ while (p > pidbuf)
+ *--p = ' ';
+ pidbuf[10] = ':';
+ pidbuf[11] = '\t';
+ }
+
+ /* Append to the output. */
+ assert (niov < NIOVMAX);
+ iov[niov].iov_len = 12;
+ iov[niov++].iov_base = pidbuf;
+
+ /* No more tags until we see the next newline. */
+ tag_p = -1;
+ }
+
+ /* Skip everything except % and \n (if tags are needed). */
+ while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
+ ++fmt;
+
+ /* Append constant string. */
+ assert (niov < NIOVMAX);
+ if ((iov[niov].iov_len = fmt - startp) != 0)
+ iov[niov++].iov_base = (char *) startp;
+
+ if (*fmt == '%')
+ {
+ /* It is a format specifier. */
+ char fill = ' ';
+ int width = -1;
+ int prec = -1;
+#if LONG_MAX != INT_MAX
+ int long_mod = 0;
+#endif
+
+ /* Recognize zero-digit fill flag. */
+ if (*++fmt == '0')
+ {
+ fill = '0';
+ ++fmt;
+ }
+
+ /* See whether with comes from a parameter. Note that no other
+ way to specify the width is implemented. */
+ if (*fmt == '*')
+ {
+ width = va_arg (arg, int);
+ ++fmt;
+ }
+
+ /* Handle precision. */
+ if (*fmt == '.' && fmt[1] == '*')
+ {
+ prec = va_arg (arg, int);
+ fmt += 2;
+ }
+
+ /* Recognize the l modifier. It is only important on some
+ platforms where long and int have a different size. We
+ can use the same code for size_t. */
+ if (*fmt == 'l' || *fmt == 'Z')
+ {
+#if LONG_MAX != INT_MAX
+ long_mod = 1;
+#endif
+ ++fmt;
+ }
+
+ switch (*fmt)
+ {
+ /* Integer formatting. */
+ case 'd':
+ case 'u':
+ case 'x':
+ {
+ /* We have to make a difference if long and int have a
+ different size. */
+#if LONG_MAX != INT_MAX
+ unsigned long int num = (long_mod
+ ? va_arg (arg, unsigned long int)
+ : va_arg (arg, unsigned int));
+#else
+ unsigned long int num = va_arg (arg, unsigned int);
+#endif
+ bool negative = false;
+ if (*fmt == 'd')
+ {
+#if LONG_MAX != INT_MAX
+ if (long_mod)
+ {
+ if ((long int) num < 0)
+ negative = true;
+ }
+ else
+ {
+ if ((int) num < 0)
+ {
+ num = (unsigned int) num;
+ negative = true;
+ }
+ }
+#else
+ if ((int) num < 0)
+ negative = true;
+#endif
+ }
+
+ /* We use alloca() to allocate the buffer with the most
+ pessimistic guess for the size. Using alloca() allows
+ having more than one integer formatting in a call. */
+ char *buf = (char *) alloca (1 + 3 * sizeof (unsigned long int));
+ char *endp = &buf[1 + 3 * sizeof (unsigned long int)];
+ char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
+
+ /* Pad to the width the user specified. */
+ if (width != -1)
+ while (endp - cp < width)
+ *--cp = fill;
+
+ if (negative)
+ *--cp = '-';
+
+ iov[niov].iov_base = cp;
+ iov[niov].iov_len = endp - cp;
+ ++niov;
+ }
+ break;
+
+ case 's':
+ /* Get the string argument. */
+ iov[niov].iov_base = va_arg (arg, char *);
+ iov[niov].iov_len = strlen (iov[niov].iov_base);
+ if (prec != -1)
+ iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
+ ++niov;
+ break;
+
+ case '%':
+ iov[niov].iov_base = (void *) fmt;
+ iov[niov].iov_len = 1;
+ ++niov;
+ break;
+
+ default:
+ assert (! "invalid format specifier");
+ }
+ ++fmt;
+ }
+ else if (*fmt == '\n')
+ {
+ /* See whether we have to print a single newline character. */
+ if (fmt == startp)
+ {
+ iov[niov].iov_base = (char *) startp;
+ iov[niov++].iov_len = 1;
+ }
+ else
+ /* No, just add it to the rest of the string. */
+ ++iov[niov - 1].iov_len;
+
+ /* Next line, print a tag again. */
+ tag_p = 1;
+ ++fmt;
+ }
+ }
+
+ /* Finally write the result. */
+ _dl_writev (fd, iov, niov);
+}
+
+
+/* Write to debug file. */
+void
+_dl_debug_printf (const char *fmt, ...)
+{
+ va_list arg;
+
+ va_start (arg, fmt);
+ _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
+ va_end (arg);
+}
+
+
+/* Write to debug file but don't start with a tag. */
+void
+_dl_debug_printf_c (const char *fmt, ...)
+{
+ va_list arg;
+
+ va_start (arg, fmt);
+ _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
+ va_end (arg);
+}
+
+
+/* Write the given file descriptor. */
+void
+_dl_dprintf (int fd, const char *fmt, ...)
+{
+ va_list arg;
+
+ va_start (arg, fmt);
+ _dl_debug_vdprintf (fd, 0, fmt, arg);
+ va_end (arg);
+}
+
+void
+_dl_printf (const char *fmt, ...)
+{
+ va_list arg;
+
+ va_start (arg, fmt);
+ _dl_debug_vdprintf (STDOUT_FILENO, 0, fmt, arg);
+ va_end (arg);
+}
+
+void
+_dl_error_printf (const char *fmt, ...)
+{
+ va_list arg;
+
+ va_start (arg, fmt);
+ _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg);
+ va_end (arg);
+}
+
+void
+_dl_fatal_printf (const char *fmt, ...)
+{
+ va_list arg;
+
+ va_start (arg, fmt);
+ _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg);
+ va_end (arg);
+ _exit (127);
+}
+rtld_hidden_def (_dl_fatal_printf)

@ -0,0 +1,146 @@
commit 9ba202c78f0aa39f49929eee63c367847da72ee4
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Jan 14 20:16:05 2022 +0100
Add --with-rtld-early-cflags configure option
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Conflicts:
INSTALL
configure
manual/install.texi
(Missing --with-timeout-factor downstream.)
diff --git a/INSTALL b/INSTALL
index d6d93ec9be4262d7..d8d4e9f155f56616 100644
--- a/INSTALL
+++ b/INSTALL
@@ -106,6 +106,14 @@ if 'CFLAGS' is specified it must enable optimization. For example:
particular case and potentially change debugging information and
metadata only).
+'--with-rtld-early-cflags=CFLAGS'
+ Use additional compiler flags CFLAGS to build the early startup
+ code of the dynamic linker. These flags can be used to enable
+ early dynamic linker diagnostics to run on CPUs which are not
+ compatible with the rest of the GNU C Library, for example, due to
+ compiler flags which target a later instruction set architecture
+ (ISA).
+
'--disable-shared'
Don't build shared libraries even if it is possible. Not all
systems support shared libraries; you need ELF support and
diff --git a/config.make.in b/config.make.in
index e8630a8d0ccf874d..6d43e691f7823262 100644
--- a/config.make.in
+++ b/config.make.in
@@ -110,6 +110,7 @@ CFLAGS = @CFLAGS@
CPPFLAGS-config = @CPPFLAGS@
CPPUNDEFS = @CPPUNDEFS@
extra-nonshared-cflags = @extra_nonshared_cflags@
+rtld-early-cflags = @rtld_early_cflags@
ASFLAGS-config = @ASFLAGS_config@
AR = @AR@
NM = @NM@
diff --git a/configure b/configure
index e9d2b1f398c4dba0..03f4e59e754b5463 100755
--- a/configure
+++ b/configure
@@ -681,6 +681,7 @@ force_install
bindnow
hardcoded_path_in_tests
enable_timezone_tools
+rtld_early_cflags
extra_nonshared_cflags
use_default_link
sysheaders
@@ -761,6 +762,7 @@ with_selinux
with_headers
with_default_link
with_nonshared_cflags
+with_rtld_early_cflags
enable_sanity_checks
enable_shared
enable_profile
@@ -1479,6 +1481,8 @@ Optional Packages:
--with-default-link do not use explicit linker scripts
--with-nonshared-cflags=CFLAGS
build nonshared libraries with additional CFLAGS
+ --with-rtld-early-cflags=CFLAGS
+ build early initialization with additional CFLAGS
--with-cpu=CPU select code for CPU variant
Some influential environment variables:
@@ -3383,6 +3387,16 @@ fi
+# Check whether --with-rtld-early-cflags was given.
+if test "${with_rtld_early_cflags+set}" = set; then :
+ withval=$with_rtld_early_cflags; rtld_early_cflags=$withval
+else
+ rtld_early_cflags=
+fi
+
+
+
+
# Check whether --enable-sanity-checks was given.
if test "${enable_sanity_checks+set}" = set; then :
enableval=$enable_sanity_checks; enable_sanity=$enableval
diff --git a/configure.ac b/configure.ac
index 79f6822d29ce21cf..eb9431875fae1b0e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -162,6 +162,12 @@ AC_ARG_WITH([nonshared-cflags],
[extra_nonshared_cflags=$withval],
[extra_nonshared_cflags=])
AC_SUBST(extra_nonshared_cflags)
+AC_ARG_WITH([rtld-early-cflags],
+ AS_HELP_STRING([--with-rtld-early-cflags=CFLAGS],
+ [build early initialization with additional CFLAGS]),
+ [rtld_early_cflags=$withval],
+ [rtld_early_cflags=])
+AC_SUBST(rtld_early_cflags)
AC_ARG_ENABLE([sanity-checks],
AS_HELP_STRING([--disable-sanity-checks],
diff --git a/elf/Makefile b/elf/Makefile
index 52aafc89cec835ab..778e393395fc5248 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -152,6 +152,14 @@ CFLAGS-.o += $(call elide-stack-protector,.o,$(elide-routines.os))
CFLAGS-.op += $(call elide-stack-protector,.op,$(elide-routines.os))
CFLAGS-.os += $(call elide-stack-protector,.os,$(all-rtld-routines))
+# Add the requested compiler flags to the early startup code.
+CFLAGS-dl-printf.os += $(rtld-early-cflags)
+CFLAGS-dl-sysdep.os += $(rtld-early-cflags)
+CFLAGS-dl-tunables.os += $(rtld-early-cflags)
+CFLAGS-dl-write.os += $(rtld-early-cflags)
+CFLAGS-dl-writev.os += $(rtld-early-cflags)
+CFLAGS-rtld.os += $(rtld-early-cflags)
+
ifeq ($(unwind-find-fde),yes)
routines += unwind-dw2-fde-glibc
shared-only-routines += unwind-dw2-fde-glibc
diff --git a/manual/install.texi b/manual/install.texi
index 1320ac69b3c645f2..816b77a0a25a88a7 100644
--- a/manual/install.texi
+++ b/manual/install.texi
@@ -131,6 +131,13 @@ that the objects in @file{libc_nonshared.a} are compiled with this flag
(although this will not affect the generated code in this particular
case and potentially change debugging information and metadata only).
+@item --with-rtld-early-cflags=@var{cflags}
+Use additional compiler flags @var{cflags} to build the early startup
+code of the dynamic linker. These flags can be used to enable early
+dynamic linker diagnostics to run on CPUs which are not compatible with
+the rest of @theglibc{}, for example, due to compiler flags which target
+a later instruction set architecture (ISA).
+
@c disable static doesn't work currently
@c @item --disable-static
@c Don't build static libraries. Static libraries aren't that useful these

@ -0,0 +1,52 @@
commit 550116486692efc394d03befee19f7e9c17d5044
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Jan 14 20:16:05 2022 +0100
powerpc64le: Use <gcc-macros.h> in early HWCAP check
This is required so that the checks still work if $(early-cflags)
selects a different ISA level.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h b/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h
index 0437ae4d522fb36d..899c74f880e6f5f0 100644
--- a/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h
+++ b/sysdeps/powerpc/powerpc64/le/dl-hwcap-check.h
@@ -19,17 +19,18 @@
#ifndef _DL_HWCAP_CHECK_H
#define _DL_HWCAP_CHECK_H
+#include <gcc-macros.h>
#include <ldsodefs.h>
static inline void
dl_hwcap_check (void)
{
-#ifdef _ARCH_PWR9
+#ifdef GCCMACRO_ARCH_PWR9
if ((GLRO (dl_hwcap2) & PPC_FEATURE2_ARCH_3_00) == 0)
_dl_fatal_printf ("\
Fatal glibc error: CPU lacks ISA 3.00 support (POWER9 or later required)\n");
#endif
-#ifdef __FLOAT128_HARDWARE__
+#ifdef GCCMACRO__FLOAT128_HARDWARE__
if ((GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_IEEE128) == 0)
_dl_fatal_printf ("\
Fatal glibc error: CPU lacks float128 support (POWER 9 or later required)\n");
@@ -37,12 +38,12 @@ Fatal glibc error: CPU lacks float128 support (POWER 9 or later required)\n");
/* This check is not actually reached when building for POWER10 and
running on POWER9 because there are faulting PCREL instructions
before this point. */
-#if defined _ARCH_PWR10 || defined __PCREL__
+#if defined GCCMACRO_ARCH_PWR10 || defined GCCMACRO__PCREL__
if ((GLRO (dl_hwcap2) & PPC_FEATURE2_ARCH_3_1) == 0)
_dl_fatal_printf ("\
Fatal glibc error: CPU lacks ISA 3.10 support (POWER10 or later required)\n");
#endif
-#ifdef __MMA__
+#ifdef GCCMACRO__MMA__
if ((GLRO (dl_hwcap2) & PPC_FEATURE2_MMA) == 0)
_dl_fatal_printf ("\
Fatal glibc error: CPU lacks MMA support (POWER10 or later required)\n");

@ -0,0 +1,27 @@
commit ea89d5bbd9e5e514b606045d909e6ab87d851c88
Author: Arjun Shankar <arjun@redhat.com>
Date: Thu Feb 24 21:43:09 2022 +0100
localedef: Handle symbolic links when generating locale-archive
Whenever locale data for any locale included symbolic links, localedef
would throw the error "incomplete set of locale files" and exclude it
from the generated locale archive. This commit fixes that.
Co-authored-by: Florian Weimer <fweimer@redhat.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/locale/programs/locarchive.c b/locale/programs/locarchive.c
index f38e835c52e4a967..d79278b6ed7340bf 100644
--- a/locale/programs/locarchive.c
+++ b/locale/programs/locarchive.c
@@ -1391,7 +1391,7 @@ add_locales_to_archive (size_t nlist, char *list[], bool replace)
{
char fullname[fnamelen + 2 * strlen (d->d_name) + 7];
- if (d_type == DT_UNKNOWN)
+ if (d_type == DT_UNKNOWN || d_type == DT_LNK)
{
strcpy (stpcpy (stpcpy (fullname, fname), "/"),
d->d_name);

@ -0,0 +1,296 @@
commit 2ab8b74567dc0a9a3c98696e6444881997dd6c49
Author: Carlos O'Donell <carlos@redhat.com>
Date: Thu Feb 3 16:51:59 2022 -0500
localedef: Update LC_MONETARY handling (Bug 28845)
ISO C17, POSIX Issue 7, and ISO 30112 all allow the char*
types to be empty strings i.e. "", integer or char values to
be -1 or CHAR_MAX respectively, with the exception of
decimal_point which must be non-empty in ISO C. Note that
the defaults for mon_grouping vary, but are functionaly
equivalent e.g. "\177" (no further grouping reuqired) vs.
"" (no grouping defined for all groups).
We include a broad comment talking about harmonizing ISO C,
POSIX, ISO 30112, and the default C/POSIX locale for glibc.
We reorder all setting based on locale/categories.def order.
We soften all missing definitions from errors to warnings when
defaults exist.
Given that ISO C, POSIX and ISO 30112 allow the empty string
we change LC_MONETARY handling of mon_decimal_point to allow
the empty string. If mon_decimal_point is not defined at all
then we pick the existing legacy glibc default value of
<U002E> i.e. ".".
We also set the default for mon_thousands_sep_wc at the
same time as mon_thousands_sep, but this is not a change in
behaviour, it is always either a matching value or L'\0',
but if in the future we change the default to a non-empty
string we would need to update both at the same time.
Tested on x86_64 and i686 without regressions.
Tested with install-locale-archive target.
Tested with install-locale-files target.
Reviewed-by: DJ Delorie <dj@redhat.com>
diff --git a/locale/programs/ld-monetary.c b/locale/programs/ld-monetary.c
index 9b9a55bb4766dfcf..17a972e1a7516aa5 100644
--- a/locale/programs/ld-monetary.c
+++ b/locale/programs/ld-monetary.c
@@ -197,21 +197,105 @@ No definition for %s category found"), "LC_MONETARY");
}
}
+ /* Generally speaking there are 3 standards the define the default,
+ warning, and error behaviour of LC_MONETARY. They are ISO/IEC TR 30112,
+ ISO/IEC 9899:2018 (ISO C17), and POSIX.1-2017. Within 30112 we have the
+ definition of a standard i18n FDCC-set, which for LC_MONETARY has the
+ following default values:
+ int_curr_symbol ""
+ currency_symbol ""
+ mon_decimal_point "<U002C>" i.e. ","
+ mon_thousand_sep ""
+ mon_grouping "\177" i.e. CHAR_MAX
+ positive_sign ""
+ negative_sign "<U002E>" i.e. "."
+ int_frac_digits -1
+ frac_digits -1
+ p_cs_precedes -1
+ p_sep_by_space -1
+ n_cs_precedes -1
+ n_sep_by_space -1
+ p_sign_posn -1
+ n_sign_posn -1
+ Under 30112 a keyword that is not provided implies an empty string ""
+ for string values or a -1 for integer values, and indicates the value
+ is unspecified with no default implied. No errors are considered.
+ The exception is mon_grouping which is a string with a terminating
+ CHAR_MAX.
+ For POSIX Issue 7 we have:
+ https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html
+ and again values not provided default to "" or -1, and indicate the value
+ is not available to the locale. The exception is mon_grouping which is
+ a string with a terminating CHAR_MAX. For the POSIX locale the values of
+ LC_MONETARY should be:
+ int_curr_symbol ""
+ currency_symbol ""
+ mon_decimal_point ""
+ mon_thousands_sep ""
+ mon_grouping "\177" i.e. CHAR_MAX
+ positive_sign ""
+ negative_sign ""
+ int_frac_digits -1
+ frac_digits -1
+ p_cs_precedes -1
+ p_sep_by_space -1
+ n_cs_precedes -1
+ n_sep_by_space -1
+ p_sign_posn -1
+ n_sign_posn -1
+ int_p_cs_precedes -1
+ int_p_sep_by_space -1
+ int_n_cs_precedes -1
+ int_n_sep_by_space -1
+ int_p_sign_posn -1
+ int_n_sign_posn -1
+ Like with 30112, POSIX also considers no error if the keywords are
+ missing, only that if the cateory as a whole is missing the referencing
+ of the category results in unspecified behaviour.
+ For ISO C17 there is no default value provided, but the localeconv
+ specification in 7.11.2.1 admits that members of char * type may point
+ to "" to indicate a value is not available or is of length zero.
+ The exception is decimal_point (not mon_decimal_point) which must be a
+ defined non-empty string. The values of char, which are generally
+ mapped to integer values in 30112 and POSIX, must be non-negative
+ numbers that map to CHAR_MAX when a value is not available in the
+ locale.
+ In ISO C17 for the "C" locale all values are empty strings "", or
+ CHAR_MAX, with the exception of decimal_point which is "." (defined
+ in LC_NUMERIC). ISO C17 makes no exception for mon_grouping like
+ 30112 and POSIX, but a value of "" is functionally equivalent to
+ "\177" since neither defines a grouping (though the latter terminates
+ the grouping).
+
+ Lastly, we must consider the legacy C/POSIX locale that implemented
+ as a builtin in glibc and wether a default value mapping to the
+ C/POSIX locale may benefit the user from a compatibility perspective.
+
+ Thus given 30112, POSIX, ISO C, and the builtin C/POSIX locale we
+ need to pick appropriate defaults below. */
+
+ /* The members of LC_MONETARY are handled in the order of their definition
+ in locale/categories.def. Please keep them in that order. */
+
+ /* The purpose of TEST_ELEM is to define a default value for the fields
+ in the category if the field was not defined in the cateory. If the
+ category was present but we didn't see a definition for the field then
+ we also issue a warning, otherwise the only warning you get is the one
+ earlier when a default category is created (completely missing category).
+ This missing field warning is glibc-specific since no standard requires
+ this warning, but we consider it valuable to print a warning for all
+ missing fields in the category. */
#define TEST_ELEM(cat, initval) \
if (monetary->cat == NULL) \
{ \
if (! nothing) \
- record_error (0, 0, _("%s: field `%s' not defined"), \
- "LC_MONETARY", #cat); \
+ record_warning (_("%s: field `%s' not defined"), \
+ "LC_MONETARY", #cat); \
monetary->cat = initval; \
}
+ /* Keyword: int_curr_symbol. */
TEST_ELEM (int_curr_symbol, "");
- TEST_ELEM (currency_symbol, "");
- TEST_ELEM (mon_thousands_sep, "");
- TEST_ELEM (positive_sign, "");
- TEST_ELEM (negative_sign, "");
-
/* The international currency symbol must come from ISO 4217. */
if (monetary->int_curr_symbol != NULL)
{
@@ -248,41 +332,63 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
}
}
- /* The decimal point must not be empty. This is not said explicitly
- in POSIX but ANSI C (ISO/IEC 9899) says in 4.4.2.1 it has to be
- != "". */
+ /* Keyword: currency_symbol */
+ TEST_ELEM (currency_symbol, "");
+
+ /* Keyword: mon_decimal_point */
+ /* ISO C17 7.11.2.1.3 explicitly allows mon_decimal_point to be the
+ empty string e.g. "". This indicates the value is not available in the
+ current locale or is of zero length. However, if the value was never
+ defined then we issue a warning and use a glibc-specific default. ISO
+ 30112 in the i18n FDCC-Set uses <U002C> ",", and POSIX Issue 7 in the
+ POSIX locale uses "". It is specific to glibc that the default is <U002E>
+ "."; we retain this existing behaviour for backwards compatibility. */
if (monetary->mon_decimal_point == NULL)
{
if (! nothing)
- record_error (0, 0, _("%s: field `%s' not defined"),
- "LC_MONETARY", "mon_decimal_point");
+ record_warning (_("%s: field `%s' not defined, using defaults"),
+ "LC_MONETARY", "mon_decimal_point");
monetary->mon_decimal_point = ".";
monetary->mon_decimal_point_wc = L'.';
}
- else if (monetary->mon_decimal_point[0] == '\0' && ! be_quiet && ! nothing)
+
+ /* Keyword: mon_thousands_sep */
+ if (monetary->mon_thousands_sep == NULL)
{
- record_error (0, 0, _("\
-%s: value for field `%s' must not be an empty string"),
- "LC_MONETARY", "mon_decimal_point");
+ if (! nothing)
+ record_warning (_("%s: field `%s' not defined, using defaults"),
+ "LC_MONETARY", "mon_thousands_sep");
+ monetary->mon_thousands_sep = "";
+ monetary->mon_thousands_sep_wc = L'\0';
}
+ /* Keyword: mon_grouping */
if (monetary->mon_grouping_len == 0)
{
if (! nothing)
- record_error (0, 0, _("%s: field `%s' not defined"),
- "LC_MONETARY", "mon_grouping");
-
+ record_warning (_("%s: field `%s' not defined"),
+ "LC_MONETARY", "mon_grouping");
+ /* Missing entries are given 1 element in their bytearray with
+ a value of CHAR_MAX which indicates that "No further grouping
+ is to be performed" (functionally equivalent to ISO C's "C"
+ locale default of ""). */
monetary->mon_grouping = (char *) "\177";
monetary->mon_grouping_len = 1;
}
+ /* Keyword: positive_sign */
+ TEST_ELEM (positive_sign, "");
+
+ /* Keyword: negative_sign */
+ TEST_ELEM (negative_sign, "");
+
#undef TEST_ELEM
#define TEST_ELEM(cat, min, max, initval) \
if (monetary->cat == -2) \
{ \
if (! nothing) \
- record_error (0, 0, _("%s: field `%s' not defined"), \
- "LC_MONETARY", #cat); \
+ record_warning (_("%s: field `%s' not defined"), \
+ "LC_MONETARY", #cat); \
monetary->cat = initval; \
} \
else if ((monetary->cat < min || monetary->cat > max) \
@@ -301,16 +407,11 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
TEST_ELEM (p_sign_posn, -1, 4, -1);
TEST_ELEM (n_sign_posn, -1, 4, -1);
- /* The non-POSIX.2 extensions are optional. */
- if (monetary->duo_int_curr_symbol == NULL)
- monetary->duo_int_curr_symbol = monetary->int_curr_symbol;
- if (monetary->duo_currency_symbol == NULL)
- monetary->duo_currency_symbol = monetary->currency_symbol;
-
- if (monetary->duo_int_frac_digits == -2)
- monetary->duo_int_frac_digits = monetary->int_frac_digits;
- if (monetary->duo_frac_digits == -2)
- monetary->duo_frac_digits = monetary->frac_digits;
+ /* Keyword: crncystr */
+ monetary->crncystr = (char *) xmalloc (strlen (monetary->currency_symbol)
+ + 2);
+ monetary->crncystr[0] = monetary->p_cs_precedes ? '-' : '+';
+ strcpy (&monetary->crncystr[1], monetary->currency_symbol);
#undef TEST_ELEM
#define TEST_ELEM(cat, alt, min, max) \
@@ -328,6 +429,17 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
TEST_ELEM (int_p_sign_posn, p_sign_posn, -1, 4);
TEST_ELEM (int_n_sign_posn, n_sign_posn, -1, 4);
+ /* The non-POSIX.2 extensions are optional. */
+ if (monetary->duo_int_curr_symbol == NULL)
+ monetary->duo_int_curr_symbol = monetary->int_curr_symbol;
+ if (monetary->duo_currency_symbol == NULL)
+ monetary->duo_currency_symbol = monetary->currency_symbol;
+
+ if (monetary->duo_int_frac_digits == -2)
+ monetary->duo_int_frac_digits = monetary->int_frac_digits;
+ if (monetary->duo_frac_digits == -2)
+ monetary->duo_frac_digits = monetary->frac_digits;
+
TEST_ELEM (duo_p_cs_precedes, p_cs_precedes, -1, 1);
TEST_ELEM (duo_p_sep_by_space, p_sep_by_space, -1, 2);
TEST_ELEM (duo_n_cs_precedes, n_cs_precedes, -1, 1);
@@ -350,17 +462,15 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
if (monetary->duo_valid_to == 0)
monetary->duo_valid_to = 99991231;
+ /* Keyword: conversion_rate */
if (monetary->conversion_rate[0] == 0)
{
monetary->conversion_rate[0] = 1;
monetary->conversion_rate[1] = 1;
}
- /* Create the crncystr entry. */
- monetary->crncystr = (char *) xmalloc (strlen (monetary->currency_symbol)
- + 2);
- monetary->crncystr[0] = monetary->p_cs_precedes ? '-' : '+';
- strcpy (&monetary->crncystr[1], monetary->currency_symbol);
+ /* A value for monetary-decimal-point-wc was set when
+ monetary_decimal_point was set, likewise for monetary-thousands-sep-wc. */
}

@ -0,0 +1,62 @@
commit 1c7a34567d21fbd3b706c77cd794956b43daefe7
Author: Carlos O'Donell <carlos@redhat.com>
Date: Thu Feb 3 16:01:52 2022 -0500
localedata: Do not generate output if warnings were present.
With LC_MONETARY parsing fixed we can now generate locales
without forcing output with '-c'.
Removing '-c' from localedef invocation is the equivalent of
using -Werror for localedef. The glibc locale sources should
always be clean and free from warnings.
We remove '-c' from both test locale generation and the targets
used for installing locales e.g. install-locale-archive, and
install-locale-files.
Tested on x86_64 and i686 without regressions.
Tested with install-locale-archive target.
Tested with install-locale-files target.
Reviewed-by: DJ Delorie <dj@redhat.com>
diff --git a/localedata/Makefile b/localedata/Makefile
index 5830b9d05141cccd..a46da8a9311b00b0 100644
--- a/localedata/Makefile
+++ b/localedata/Makefile
@@ -469,11 +469,11 @@ define build-one-locale
endef
$(INSTALL-SUPPORTED-LOCALE-ARCHIVE): install-locales-dir
- @flags="-c"; \
+ @flags=""; \
$(build-one-locale)
$(INSTALL-SUPPORTED-LOCALE-FILES): install-locales-dir
- @flags="-c --no-archive --no-hard-links"; \
+ @flags="--no-archive --no-hard-links"; \
$(build-one-locale)
tst-setlocale-ENV = LC_ALL=ja_JP.EUC-JP
diff --git a/localedata/gen-locale.sh b/localedata/gen-locale.sh
index c7e2e160ae1506f8..a25d27f3e6986675 100644
--- a/localedata/gen-locale.sh
+++ b/localedata/gen-locale.sh
@@ -54,8 +54,14 @@ modifier=`echo $locfile|sed 's|[^.]*[.]\([^@ ]*\)\(@[^ ]*\)\?/LC_CTYPE|\2|'`
echo "Generating locale $locale.$charmap: this might take a while..."
-# Run quietly and force output.
-flags="--quiet -c"
+# Do not force output with '-c', all locales should compile without
+# warning or errors. There is likewise no need to run quietly with
+# '--quiet' since all locales should compile without additional
+# diagnostics. If there are messages printed then we want to see
+# them, fix them, and the associated error or warning. During
+# development it may be beneficialy to put '--quiet -c' here to allow
+# you to develop in-progress locales.
+flags=""
# For SJIS the charmap is SHIFT_JIS. We just want the locale to have
# a slightly nicer name instead of using "*.SHIFT_SJIS", but that

@ -0,0 +1,37 @@
Early backport of upstream patch under discussion:
[PATCH v3] elf: Fix DFS sorting algorithm for LD_TRACE_LOADED_OBJECTS
with missing libraries (BZ #28868)
<https://sourceware.org/pipermail/libc-alpha/2022-February/136641.html>
The tests are still being discussed upstream and are not backported
here.
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 237d9636c5be780c..9e30c6c3f6c58783 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -489,6 +489,8 @@ _dl_map_object_deps (struct link_map *map,
for (nlist = 0, runp = known; runp; runp = runp->next)
{
+ /* _dl_sort_maps ignores l_faked object, so it is save to not considere
+ them for nlist. */
if (__builtin_expect (trace_mode, 0) && runp->map->l_faked)
/* This can happen when we trace the loading. */
--map->l_searchlist.r_nlist;
diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
index a274ed66cc987735..72f4ff0e6eda3377 100644
--- a/elf/dl-sort-maps.c
+++ b/elf/dl-sort-maps.c
@@ -140,7 +140,9 @@ static void
dfs_traversal (struct link_map ***rpo, struct link_map *map,
bool *do_reldeps)
{
- if (map->l_visited)
+ /* _dl_map_object_deps filter l_faked objects when calculating the
+ number of maps before calling _dl_sort_maps, ignore them as well. */
+ if (map->l_visited || map->l_faked)
return;
map->l_visited = 1;

@ -0,0 +1,605 @@
commit c901c3e764d7c7079f006b4e21e877d5036eb4f5
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Dec 9 09:49:32 2021 +0100
nptl: Add public rseq symbols and <sys/rseq.h>
The relationship between the thread pointer and the rseq area
is made explicit. The constant offset can be used by JIT compilers
to optimize rseq access (e.g., for really fast sched_getcpu).
Extensibility is provided through __rseq_size and __rseq_flags.
(In the future, the kernel could request a different rseq size
via the auxiliary vector.)
Co-Authored-By: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
diff --git a/manual/threads.texi b/manual/threads.texi
index 7f166bfa87e88c36..4869f69d2ceed255 100644
--- a/manual/threads.texi
+++ b/manual/threads.texi
@@ -629,6 +629,8 @@ the standard.
* Waiting with Explicit Clocks:: Functions for waiting with an
explicit clock specification.
* Single-Threaded:: Detecting single-threaded execution.
+* Restartable Sequences:: Linux-specific restartable sequences
+ integration.
@end menu
@node Default Thread Attributes
@@ -958,6 +960,85 @@ application-created thread because future versions of @theglibc{} may
create background threads after the first thread has been created, and
the application has no way of knowning that these threads are present.
+@node Restartable Sequences
+@subsubsection Restartable Sequences
+
+This section describes restartable sequences integration for
+@theglibc{}. This functionality is only available on Linux.
+
+@deftp {Data Type} {struct rseq}
+@standards{Linux, sys/rseq.h}
+The type of the restartable sequences area. Future versions
+of Linux may add additional fields to the end of this structure.
+
+
+Users need to obtain the address of the restartable sequences area using
+the thread pointer and the @code{__rseq_offset} variable, described
+below.
+
+One use of the restartable sequences area is to read the current CPU
+number from its @code{cpu_id} field, as an inline version of
+@code{sched_getcpu}. @Theglibc{} sets the @code{cpu_id} field to
+@code{RSEQ_CPU_ID_REGISTRATION_FAILED} if registration failed or was
+explicitly disabled.
+
+Furthermore, users can store the address of a @code{struct rseq_cs}
+object into the @code{rseq_cs} field of @code{struct rseq}, thus
+informing the kernel that the thread enters a restartable sequence
+critical section. This pointer and the code areas it itself points to
+must not be left pointing to memory areas which are freed or re-used.
+Several approaches can guarantee this. If the application or library
+can guarantee that the memory used to hold the @code{struct rseq_cs} and
+the code areas it refers to are never freed or re-used, no special
+action must be taken. Else, before that memory is re-used of freed, the
+application is responsible for setting the @code{rseq_cs} field to
+@code{NULL} in each thread's restartable sequence area to guarantee that
+it does not leak dangling references. Because the application does not
+typically have knowledge of libraries' use of restartable sequences, it
+is recommended that libraries using restartable sequences which may end
+up freeing or re-using their memory set the @code{rseq_cs} field to
+@code{NULL} before returning from library functions which use
+restartable sequences.
+
+The manual for the @code{rseq} system call can be found
+at @uref{https://git.kernel.org/pub/scm/libs/librseq/librseq.git/tree/doc/man/rseq.2}.
+@end deftp
+
+@deftypevar {int} __rseq_offset
+@standards{Linux, sys/rseq.h}
+This variable contains the offset between the thread pointer (as defined
+by @code{__builtin_thread_pointer} or the thread pointer register for
+the architecture) and the restartable sequences area. This value is the
+same for all threads in the process. If the restartable sequences area
+is located at a lower address than the location to which the thread
+pointer points, the value is negative.
+@end deftypevar
+
+@deftypevar {unsigned int} __rseq_size
+@standards{Linux, sys/rseq.h}
+This variable is either zero (if restartable sequence registration
+failed or has been disabled) or the size of the restartable sequence
+registration. This can be different from the size of @code{struct rseq}
+if the kernel has extended the size of the registration. If
+registration is successful, @code{__rseq_size} is at least 32 (the
+initial size of @code{struct rseq}).
+@end deftypevar
+
+@deftypevar {unsigned int} __rseq_flags
+@standards{Linux, sys/rseq.h}
+The flags used during restartable sequence registration with the kernel.
+Currently zero.
+@end deftypevar
+
+@deftypevr Macro int RSEQ_SIG
+@standards{Linux, sys/rseq.h}
+Each supported architecture provides a @code{RSEQ_SIG} macro in
+@file{sys/rseq.h} which contains a signature. That signature is
+expected to be present in the code before each restartable sequences
+abort handler. Failure to provide the expected signature may terminate
+the process with a segmentation fault.
+@end deftypevr
+
@c FIXME these are undocumented:
@c pthread_atfork
@c pthread_attr_destroy
diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
index 23aa4cfc0b784dfc..0f5280a75d546d2f 100644
--- a/sysdeps/nptl/dl-tls_init_tp.c
+++ b/sysdeps/nptl/dl-tls_init_tp.c
@@ -22,6 +22,7 @@
#include <pthreadP.h>
#include <tls.h>
#include <rseq-internal.h>
+#include <thread_pointer.h>
#define TUNABLE_NAMESPACE pthread
#include <dl-tunables.h>
@@ -43,6 +44,10 @@ rtld_mutex_dummy (pthread_mutex_t *lock)
}
#endif
+const unsigned int __rseq_flags;
+const unsigned int __rseq_size attribute_relro;
+const int __rseq_offset attribute_relro;
+
void
__tls_pre_init_tp (void)
{
@@ -100,7 +105,23 @@ __tls_init_tp (void)
#if HAVE_TUNABLES
do_rseq = TUNABLE_GET (rseq, int, NULL);
#endif
- rseq_register_current_thread (pd, do_rseq);
+ if (rseq_register_current_thread (pd, do_rseq))
+ {
+ /* We need a writable view of the variables. They are in
+ .data.relro and are not yet write-protected. */
+ extern unsigned int size __asm__ ("__rseq_size");
+ size = sizeof (pd->rseq_area);
+ }
+
+#ifdef RSEQ_SIG
+ /* This should be a compile-time constant, but the current
+ infrastructure makes it difficult to determine its value. Not
+ all targets support __thread_pointer, so set __rseq_offset only
+ if thre rseq registration may have happened because RSEQ_SIG is
+ defined. */
+ extern int offset __asm__ ("__rseq_offset");
+ offset = (char *) &pd->rseq_area - (char *) __thread_pointer ();
+#endif
}
/* Set initial thread's stack block from 0 up to __libc_stack_end.
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 5c772f69d1b1f1f1..9b7e214219943531 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -110,7 +110,8 @@ sysdep_headers += sys/mount.h sys/acct.h \
bits/types/struct_semid64_ds_helper.h \
bits/types/struct_shmid64_ds.h \
bits/types/struct_shmid64_ds_helper.h \
- bits/pthread_stack_min.h bits/pthread_stack_min-dynamic.h
+ bits/pthread_stack_min.h bits/pthread_stack_min-dynamic.h \
+ sys/rseq.h bits/rseq.h
tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \
diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index 26452f3f17b5421d..3f8809a1581f27d0 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -316,6 +316,11 @@ librt {
}
ld {
+ GLIBC_2.35 {
+ __rseq_flags;
+ __rseq_offset;
+ __rseq_size;
+ }
GLIBC_PRIVATE {
__nptl_change_stack_perm;
}
diff --git a/sysdeps/unix/sysv/linux/aarch64/ld.abilist b/sysdeps/unix/sysv/linux/aarch64/ld.abilist
index b7196a80e2df8efc..bf4d4f9b6f2ddf97 100644
--- a/sysdeps/unix/sysv/linux/aarch64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/ld.abilist
@@ -4,3 +4,6 @@ GLIBC_2.17 __tls_get_addr F
GLIBC_2.17 _dl_mcount F
GLIBC_2.17 _r_debug D 0x28
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/alpha/ld.abilist b/sysdeps/unix/sysv/linux/alpha/ld.abilist
index 13f7fc74af62941d..a23325a566419b41 100644
--- a/sysdeps/unix/sysv/linux/alpha/ld.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/ld.abilist
@@ -3,4 +3,7 @@ GLIBC_2.1 __libc_stack_end D 0x8
GLIBC_2.1 _dl_mcount F
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x8
diff --git a/sysdeps/unix/sysv/linux/arc/ld.abilist b/sysdeps/unix/sysv/linux/arc/ld.abilist
index 7284383a6bea8e64..55f0c2ab9c6f7d91 100644
--- a/sysdeps/unix/sysv/linux/arc/ld.abilist
+++ b/sysdeps/unix/sysv/linux/arc/ld.abilist
@@ -4,3 +4,6 @@ GLIBC_2.32 __tls_get_addr F
GLIBC_2.32 _dl_mcount F
GLIBC_2.32 _r_debug D 0x14
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/arm/be/ld.abilist b/sysdeps/unix/sysv/linux/arm/be/ld.abilist
index 7987bbae1112aa3d..f1da2c636ddb359d 100644
--- a/sysdeps/unix/sysv/linux/arm/be/ld.abilist
+++ b/sysdeps/unix/sysv/linux/arm/be/ld.abilist
@@ -1,4 +1,7 @@
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __libc_stack_end D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
GLIBC_2.4 __tls_get_addr F
diff --git a/sysdeps/unix/sysv/linux/arm/le/ld.abilist b/sysdeps/unix/sysv/linux/arm/le/ld.abilist
index 7987bbae1112aa3d..f1da2c636ddb359d 100644
--- a/sysdeps/unix/sysv/linux/arm/le/ld.abilist
+++ b/sysdeps/unix/sysv/linux/arm/le/ld.abilist
@@ -1,4 +1,7 @@
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __libc_stack_end D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
GLIBC_2.4 __tls_get_addr F
diff --git a/sysdeps/unix/sysv/linux/csky/ld.abilist b/sysdeps/unix/sysv/linux/csky/ld.abilist
index 4939b20631dc6c54..7f482276ed8df1d5 100644
--- a/sysdeps/unix/sysv/linux/csky/ld.abilist
+++ b/sysdeps/unix/sysv/linux/csky/ld.abilist
@@ -4,3 +4,6 @@ GLIBC_2.29 __tls_get_addr F
GLIBC_2.29 _dl_mcount F
GLIBC_2.29 _r_debug D 0x14
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/hppa/ld.abilist b/sysdeps/unix/sysv/linux/hppa/ld.abilist
index 7cc9ebd792c2aadc..7f5527fb301b913c 100644
--- a/sysdeps/unix/sysv/linux/hppa/ld.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/ld.abilist
@@ -3,4 +3,7 @@ GLIBC_2.2 _dl_mcount F
GLIBC_2.2 _r_debug D 0x14
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
index e8d187b14d722a64..9c4a45d8dc525e52 100644
--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
+++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
@@ -4,3 +4,6 @@ GLIBC_2.1 _dl_mcount F
GLIBC_2.3 ___tls_get_addr F
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/ia64/ld.abilist b/sysdeps/unix/sysv/linux/ia64/ld.abilist
index be5122650ae2b327..8ccb5be911e0e9a2 100644
--- a/sysdeps/unix/sysv/linux/ia64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/ld.abilist
@@ -3,3 +3,6 @@ GLIBC_2.2 _dl_mcount F
GLIBC_2.2 _r_debug D 0x28
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist
index 7987bbae1112aa3d..f1da2c636ddb359d 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist
@@ -1,4 +1,7 @@
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __libc_stack_end D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
GLIBC_2.4 __tls_get_addr F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist
index 4f2854edf7746958..dadbf852d0522e77 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist
@@ -3,4 +3,7 @@ GLIBC_2.1 __libc_stack_end D 0x4
GLIBC_2.1 _dl_mcount F
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
diff --git a/sysdeps/unix/sysv/linux/microblaze/ld.abilist b/sysdeps/unix/sysv/linux/microblaze/ld.abilist
index 9f0fdeca38890a34..89a0b7e4fd5a95fa 100644
--- a/sysdeps/unix/sysv/linux/microblaze/ld.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/ld.abilist
@@ -4,3 +4,6 @@ GLIBC_2.18 __tls_get_addr F
GLIBC_2.18 _dl_mcount F
GLIBC_2.18 _r_debug D 0x14
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist
index f750067d5c34bf42..e304d1bb464b28f4 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist
@@ -3,4 +3,7 @@ GLIBC_2.2 __libc_stack_end D 0x4
GLIBC_2.2 _dl_mcount F
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist
index f750067d5c34bf42..e304d1bb464b28f4 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist
@@ -3,4 +3,7 @@ GLIBC_2.2 __libc_stack_end D 0x4
GLIBC_2.2 _dl_mcount F
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
index 2fba6a9b6ec92e47..37a47ebc0a0d16c8 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
@@ -3,4 +3,7 @@ GLIBC_2.2 __libc_stack_end D 0x8
GLIBC_2.2 _dl_mcount F
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x8
diff --git a/sysdeps/unix/sysv/linux/nios2/ld.abilist b/sysdeps/unix/sysv/linux/nios2/ld.abilist
index 57dfad5a53b739e8..811ae9da2fa85399 100644
--- a/sysdeps/unix/sysv/linux/nios2/ld.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/ld.abilist
@@ -4,3 +4,6 @@ GLIBC_2.21 __tls_get_addr F
GLIBC_2.21 _dl_mcount F
GLIBC_2.21 _r_debug D 0x14
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
index e89660739262c6ab..5a68aeb9eed33844 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
@@ -5,3 +5,6 @@ GLIBC_2.22 __tls_get_addr_opt F
GLIBC_2.23 __parse_hwcap_and_convert_at_platform F
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
index ce0bc639597c4bd9..da24dc7fb52ad2d4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
@@ -5,3 +5,6 @@ GLIBC_2.3 __tls_get_addr F
GLIBC_2.3 _dl_mcount F
GLIBC_2.3 _r_debug D 0x28
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
index 65b22674d2462e96..b9ae89ae8d90ed9e 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
@@ -5,3 +5,6 @@ GLIBC_2.17 _r_debug D 0x28
GLIBC_2.22 __tls_get_addr_opt F
GLIBC_2.23 __parse_hwcap_and_convert_at_platform F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist
index 5ad4c81d12d7a612..068368878eb2406e 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist
@@ -4,3 +4,6 @@ GLIBC_2.33 __tls_get_addr F
GLIBC_2.33 _dl_mcount F
GLIBC_2.33 _r_debug D 0x14
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
index 479efdea9bb654bb..48431c91a9fd16b0 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
@@ -4,3 +4,6 @@ GLIBC_2.27 __tls_get_addr F
GLIBC_2.27 _dl_mcount F
GLIBC_2.27 _r_debug D 0x28
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
index 6a3441f2cc49e7c4..9e8f99fd51a063b1 100644
--- a/sysdeps/unix/sysv/linux/rseq-internal.h
+++ b/sysdeps/unix/sysv/linux/rseq-internal.h
@@ -41,7 +41,7 @@ rseq_register_current_thread (struct pthread *self, bool do_rseq)
return false;
}
#else /* RSEQ_SIG */
-static inline void
+static inline bool
rseq_register_current_thread (struct pthread *self, bool do_rseq)
{
THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist
index d5ecb636bb792bdf..c15288394a232a8c 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist
@@ -3,3 +3,6 @@ GLIBC_2.1 __libc_stack_end D 0x4
GLIBC_2.1 _dl_mcount F
GLIBC_2.3 __tls_get_offset F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
index 62a5e1d99a2e6f42..117d1430a4c6272e 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
@@ -3,3 +3,6 @@ GLIBC_2.2 _dl_mcount F
GLIBC_2.2 _r_debug D 0x28
GLIBC_2.3 __tls_get_offset F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/sh/be/ld.abilist b/sysdeps/unix/sysv/linux/sh/be/ld.abilist
index 7cc9ebd792c2aadc..7f5527fb301b913c 100644
--- a/sysdeps/unix/sysv/linux/sh/be/ld.abilist
+++ b/sysdeps/unix/sysv/linux/sh/be/ld.abilist
@@ -3,4 +3,7 @@ GLIBC_2.2 _dl_mcount F
GLIBC_2.2 _r_debug D 0x14
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
diff --git a/sysdeps/unix/sysv/linux/sh/le/ld.abilist b/sysdeps/unix/sysv/linux/sh/le/ld.abilist
index 7cc9ebd792c2aadc..7f5527fb301b913c 100644
--- a/sysdeps/unix/sysv/linux/sh/le/ld.abilist
+++ b/sysdeps/unix/sysv/linux/sh/le/ld.abilist
@@ -3,4 +3,7 @@ GLIBC_2.2 _dl_mcount F
GLIBC_2.2 _r_debug D 0x14
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x4
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist
index 2e6054349871e7d5..3aac73f3df646cb6 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist
@@ -3,3 +3,6 @@ GLIBC_2.1 __libc_stack_end D 0x4
GLIBC_2.1 _dl_mcount F
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
index be5122650ae2b327..8ccb5be911e0e9a2 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
@@ -3,3 +3,6 @@ GLIBC_2.2 _dl_mcount F
GLIBC_2.2 _r_debug D 0x28
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h
index c8edff50d40e29b6..1215b5d086b8852b 100644
--- a/sysdeps/unix/sysv/linux/sys/rseq.h
+++ b/sysdeps/unix/sysv/linux/sys/rseq.h
@@ -171,4 +171,14 @@ struct rseq
#endif /* __GLIBC_HAVE_KERNEL_RSEQ */
+/* Offset from the thread pointer to the rseq area. */
+extern const int __rseq_offset;
+
+/* Size of the registered rseq area. 0 if the registration was
+ unsuccessful. */
+extern const unsigned int __rseq_size;
+
+/* Flags used during rseq registration. */
+extern const unsigned int __rseq_flags;
+
#endif /* sys/rseq.h */
diff --git a/sysdeps/unix/sysv/linux/tst-rseq-disable.c b/sysdeps/unix/sysv/linux/tst-rseq-disable.c
index 000e351872fc2f76..6d73f77e9621da42 100644
--- a/sysdeps/unix/sysv/linux/tst-rseq-disable.c
+++ b/sysdeps/unix/sysv/linux/tst-rseq-disable.c
@@ -21,6 +21,7 @@
#include <support/namespace.h>
#include <support/xthread.h>
#include <sysdep.h>
+#include <thread_pointer.h>
#include <unistd.h>
#ifdef RSEQ_SIG
@@ -30,6 +31,11 @@ static void
check_rseq_disabled (void)
{
struct pthread *pd = THREAD_SELF;
+
+ TEST_COMPARE (__rseq_flags, 0);
+ TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset
+ == (char *) &pd->rseq_area);
+ TEST_COMPARE (__rseq_size, 0);
TEST_COMPARE ((int) pd->rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
int ret = syscall (__NR_rseq, &pd->rseq_area, sizeof (pd->rseq_area),
diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c
index 926376b6a5446ece..572c11166f8b6533 100644
--- a/sysdeps/unix/sysv/linux/tst-rseq.c
+++ b/sysdeps/unix/sysv/linux/tst-rseq.c
@@ -29,12 +29,20 @@
# include <stdlib.h>
# include <string.h>
# include <syscall.h>
+# include <thread_pointer.h>
+# include <tls.h>
# include "tst-rseq.h"
static void
do_rseq_main_test (void)
{
+ struct pthread *pd = THREAD_SELF;
+
TEST_VERIFY_EXIT (rseq_thread_registered ());
+ TEST_COMPARE (__rseq_flags, 0);
+ TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset
+ == (char *) &pd->rseq_area);
+ TEST_COMPARE (__rseq_size, sizeof (pd->rseq_area));
}
static void
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
index afddaec57c11f837..ae622bdf9710bdbd 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
@@ -3,3 +3,6 @@ GLIBC_2.2.5 _dl_mcount F
GLIBC_2.2.5 _r_debug D 0x28
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
index defc488d137c61c3..e17496d124b0c7b7 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
@@ -3,3 +3,6 @@ GLIBC_2.16 __tls_get_addr F
GLIBC_2.16 _dl_mcount F
GLIBC_2.16 _r_debug D 0x14
GLIBC_2.34 __rtld_version_placeholder F
+GLIBC_2.35 __rseq_flags D 0x4
+GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_size D 0x4

@ -0,0 +1,180 @@
commit 6c33b018438ee799c29486f21d43d8100bdbd597
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Feb 2 22:37:20 2022 +0100
Linux: Use ptrdiff_t for __rseq_offset
This matches the data size initial-exec relocations use on most
targets.
Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/manual/threads.texi b/manual/threads.texi
index 4869f69d2ceed255..48fd562923800b34 100644
--- a/manual/threads.texi
+++ b/manual/threads.texi
@@ -1004,7 +1004,7 @@ The manual for the @code{rseq} system call can be found
at @uref{https://git.kernel.org/pub/scm/libs/librseq/librseq.git/tree/doc/man/rseq.2}.
@end deftp
-@deftypevar {int} __rseq_offset
+@deftypevar {ptrdiff_t} __rseq_offset
@standards{Linux, sys/rseq.h}
This variable contains the offset between the thread pointer (as defined
by @code{__builtin_thread_pointer} or the thread pointer register for
diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
index 0f5280a75d546d2f..d5f2587f1348441c 100644
--- a/sysdeps/nptl/dl-tls_init_tp.c
+++ b/sysdeps/nptl/dl-tls_init_tp.c
@@ -46,7 +46,7 @@ rtld_mutex_dummy (pthread_mutex_t *lock)
const unsigned int __rseq_flags;
const unsigned int __rseq_size attribute_relro;
-const int __rseq_offset attribute_relro;
+const ptrdiff_t __rseq_offset attribute_relro;
void
__tls_pre_init_tp (void)
@@ -119,7 +119,7 @@ __tls_init_tp (void)
all targets support __thread_pointer, so set __rseq_offset only
if thre rseq registration may have happened because RSEQ_SIG is
defined. */
- extern int offset __asm__ ("__rseq_offset");
+ extern ptrdiff_t offset __asm__ ("__rseq_offset");
offset = (char *) &pd->rseq_area - (char *) __thread_pointer ();
#endif
}
diff --git a/sysdeps/unix/sysv/linux/aarch64/ld.abilist b/sysdeps/unix/sysv/linux/aarch64/ld.abilist
index bf4d4f9b6f2ddf97..5151c0781de01bf1 100644
--- a/sysdeps/unix/sysv/linux/aarch64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/ld.abilist
@@ -5,5 +5,5 @@ GLIBC_2.17 _dl_mcount F
GLIBC_2.17 _r_debug D 0x28
GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
-GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/alpha/ld.abilist b/sysdeps/unix/sysv/linux/alpha/ld.abilist
index a23325a566419b41..3e296c547314f6c2 100644
--- a/sysdeps/unix/sysv/linux/alpha/ld.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/ld.abilist
@@ -4,6 +4,6 @@ GLIBC_2.1 _dl_mcount F
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
-GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x8
diff --git a/sysdeps/unix/sysv/linux/ia64/ld.abilist b/sysdeps/unix/sysv/linux/ia64/ld.abilist
index 8ccb5be911e0e9a2..5471b24d59a7527a 100644
--- a/sysdeps/unix/sysv/linux/ia64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/ld.abilist
@@ -4,5 +4,5 @@ GLIBC_2.2 _r_debug D 0x28
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
-GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
index 37a47ebc0a0d16c8..f26e594a139f0058 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
@@ -4,6 +4,6 @@ GLIBC_2.2 _dl_mcount F
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
-GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
GLIBC_2.4 __stack_chk_guard D 0x8
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
index da24dc7fb52ad2d4..21f472e674299ab7 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
@@ -6,5 +6,5 @@ GLIBC_2.3 _dl_mcount F
GLIBC_2.3 _r_debug D 0x28
GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
-GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
index b9ae89ae8d90ed9e..9c9c40450d651880 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
@@ -6,5 +6,5 @@ GLIBC_2.22 __tls_get_addr_opt F
GLIBC_2.23 __parse_hwcap_and_convert_at_platform F
GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
-GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
index 48431c91a9fd16b0..a7758a0e52fc8cc8 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
@@ -5,5 +5,5 @@ GLIBC_2.27 _dl_mcount F
GLIBC_2.27 _r_debug D 0x28
GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
-GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
index 117d1430a4c6272e..78d071600b1f3431 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
@@ -4,5 +4,5 @@ GLIBC_2.2 _r_debug D 0x28
GLIBC_2.3 __tls_get_offset F
GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
-GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
index 8ccb5be911e0e9a2..5471b24d59a7527a 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
@@ -4,5 +4,5 @@ GLIBC_2.2 _r_debug D 0x28
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
-GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4
diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h
index 1215b5d086b8852b..791ed83176b61fe4 100644
--- a/sysdeps/unix/sysv/linux/sys/rseq.h
+++ b/sysdeps/unix/sysv/linux/sys/rseq.h
@@ -21,6 +21,7 @@
/* Architecture-specific rseq signature. */
#include <bits/rseq.h>
+#include <stddef.h>
#include <stdint.h>
#include <sys/cdefs.h>
#include <bits/endian.h>
@@ -172,7 +173,7 @@ struct rseq
#endif /* __GLIBC_HAVE_KERNEL_RSEQ */
/* Offset from the thread pointer to the rseq area. */
-extern const int __rseq_offset;
+extern const ptrdiff_t __rseq_offset;
/* Size of the registered rseq area. 0 if the registration was
unsuccessful. */
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
index ae622bdf9710bdbd..5a8bd322cdc95d5b 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
@@ -4,5 +4,5 @@ GLIBC_2.2.5 _r_debug D 0x28
GLIBC_2.3 __tls_get_addr F
GLIBC_2.34 __rtld_version_placeholder F
GLIBC_2.35 __rseq_flags D 0x4
-GLIBC_2.35 __rseq_offset D 0x4
+GLIBC_2.35 __rseq_offset D 0x8
GLIBC_2.35 __rseq_size D 0x4

@ -0,0 +1,59 @@
commit 4b527650e0d559a5f693275c598667e06cd6455c
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Jun 2 16:29:55 2022 +0200
Linux: Adjust struct rseq definition to current kernel version
This definition is only used as a fallback with old kernel headers.
The change follows kernel commit bfdf4e6208051ed7165b2e92035b4bf11
("rseq: Remove broken uapi field layout on 32-bit little endian").
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h
index 791ed83176b61fe4..56550329db962cc8 100644
--- a/sysdeps/unix/sysv/linux/sys/rseq.h
+++ b/sysdeps/unix/sysv/linux/sys/rseq.h
@@ -24,7 +24,6 @@
#include <stddef.h>
#include <stdint.h>
#include <sys/cdefs.h>
-#include <bits/endian.h>
#ifdef __has_include
# if __has_include ("linux/rseq.h")
@@ -129,28 +128,13 @@ struct rseq
targeted by the rseq_cs. Also needs to be set to NULL by user-space
before reclaiming memory that contains the targeted struct rseq_cs.
- Read and set by the kernel. Set by user-space with single-copy
- atomicity semantics. This field should only be updated by the
- thread which registered this data structure. Aligned on 64-bit. */
- union
- {
- uint64_t ptr64;
-# ifdef __LP64__
- uint64_t ptr;
-# else /* __LP64__ */
- struct
- {
-#if __BYTE_ORDER == __BIG_ENDIAN
- uint32_t padding; /* Initialized to zero. */
- uint32_t ptr32;
-# else /* LITTLE */
- uint32_t ptr32;
- uint32_t padding; /* Initialized to zero. */
-# endif /* ENDIAN */
- } ptr;
-# endif /* __LP64__ */
- } rseq_cs;
+ Read and set by the kernel. Set by user-space with single-copy
+ atomicity semantics. This field should only be updated by the
+ thread which registered this data structure. Aligned on 64-bit.
+ 32-bit architectures should update the low order bits of the
+ rseq_cs field, leaving the high order bits initialized to 0. */
+ uint64_t rseq_cs;
/* Restartable sequences flags field.
This field should only be updated by the thread which

@ -0,0 +1,38 @@
Revert glibc-rh2024347-13.patch. Enable rseq by default.
diff --git a/manual/tunables.texi b/manual/tunables.texi
index f559c44dcec4624b..28ff502990c2a10f 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -425,13 +425,11 @@ The value is measured in bytes. The default is @samp{41943040}
@end deftp
@deftp Tunable glibc.pthread.rseq
-The @code{glibc.pthread.rseq} tunable can be set to @samp{1}, to enable
-restartable sequences support. @Theglibc{} uses this to optimize the
-@code{sched_getcpu} function.
-
-The default is @samp{0}, which means that applications can perform
-restartable sequences registration, but @code{sched_getcpu} is not
-accelerated.
+The @code{glibc.pthread.rseq} tunable can be set to @samp{0}, to disable
+restartable sequences support in @theglibc{}. This enables applications
+to perform direct restartable sequence registration with the kernel.
+The default is @samp{1}, which means that @theglibc{} performs
+registration on behalf of the application.
Restartable sequences are a Linux-specific extension.
@end deftp
diff --git a/sysdeps/nptl/dl-tunables.list b/sysdeps/nptl/dl-tunables.list
index df2a39ce01858d3b..d24f4be0d08ba407 100644
--- a/sysdeps/nptl/dl-tunables.list
+++ b/sysdeps/nptl/dl-tunables.list
@@ -31,7 +31,7 @@ glibc {
type: INT_32
minval: 0
maxval: 1
- default: 0
+ default: 1
}
}
}

@ -0,0 +1,67 @@
commit 62a321b12d0e397af88fa422db65079332f971dc
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Jun 24 18:16:41 2022 +0200
support: Change non-address output format of support_format_dns_packet
It makes sense to include the owner name (LHS) and record type in the
output, so that they can be checked for correctness.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/support/support_format_dns_packet.c b/support/support_format_dns_packet.c
index 1f8e9ca172a06f4f..c3dff0e019801904 100644
--- a/support/support_format_dns_packet.c
+++ b/support/support_format_dns_packet.c
@@ -101,6 +101,17 @@ extract_name (struct in_buffer full, struct in_buffer *in, struct dname *value)
return true;
}
+static void
+extract_name_data (struct in_buffer full, struct in_buffer *rdata,
+ const struct dname *owner, const char *typename, FILE *out)
+{
+ struct dname name;
+ if (extract_name (full, rdata, &name))
+ fprintf (out, "data: %s %s %s\n", owner->name, typename, name.name);
+ else
+ fprintf (out, "error: malformed CNAME/PTR record\n");
+}
+
char *
support_format_dns_packet (const unsigned char *buffer, size_t length)
{
@@ -206,14 +217,11 @@ support_format_dns_packet (const unsigned char *buffer, size_t length)
}
break;
case T_CNAME:
+ extract_name_data (full, &rdata, &rname, "CNAME", mem.out);
+ break;
case T_PTR:
- {
- struct dname name;
- if (extract_name (full, &rdata, &name))
- fprintf (mem.out, "name: %s\n", name.name);
- else
- fprintf (mem.out, "error: malformed CNAME/PTR record\n");
- }
+ extract_name_data (full, &rdata, &rname, "PTR", mem.out);
+ break;
}
}
diff --git a/support/tst-support_format_dns_packet.c b/support/tst-support_format_dns_packet.c
index 03ff59457e3bdde8..5596db1785009557 100644
--- a/support/tst-support_format_dns_packet.c
+++ b/support/tst-support_format_dns_packet.c
@@ -85,8 +85,8 @@ test_multiple_cnames (void)
"\xc0\x00\x02\x01";
check_packet (packet, sizeof (packet) - 1, __func__,
"name: www.example\n"
- "name: www1.example\n"
- "name: www2.example\n"
+ "data: www.example CNAME www1.example\n"
+ "data: www1.example CNAME www2.example\n"
"address: 192.0.2.1\n");
}

@ -0,0 +1,941 @@
commit f282cdbe7f436c75864e5640a409a10485e9abb2
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Jun 24 18:16:41 2022 +0200
resolv: Implement no-aaaa stub resolver option
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/resolv/Makefile b/resolv/Makefile
index 59e599535c7aa6eb..e8269dcb5bcf216b 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -51,6 +51,7 @@ routines := \
nss_dns_functions \
res-close \
res-name-checking \
+ res-noaaaa \
res-state \
res_context_hostalias \
res_enable_icmp \
@@ -93,6 +94,7 @@ tests += \
tst-resolv-binary \
tst-resolv-edns \
tst-resolv-network \
+ tst-resolv-noaaaa \
tst-resolv-nondecimal \
tst-resolv-res_init-multi \
tst-resolv-search \
@@ -256,6 +258,7 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \
$(shared-thread-library)
$(objpfx)tst-resolv-res_init-thread: $(objpfx)libresolv.so \
$(shared-thread-library)
+$(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library)
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 7248ade18db5ba47..6e83fca1c5b1f98c 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -125,6 +125,14 @@ static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1,
char *buffer, size_t buflen,
int *errnop, int *h_errnop,
int32_t *ttlp);
+static enum nss_status gaih_getanswer_noaaaa (const querybuf *answer1,
+ int anslen1,
+ const char *qname,
+ struct gaih_addrtuple **pat,
+ char *buffer, size_t buflen,
+ int *errnop, int *h_errnop,
+ int32_t *ttlp);
+
static enum nss_status gethostbyname3_context (struct resolv_context *ctx,
const char *name, int af,
@@ -370,17 +378,31 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
int resplen2 = 0;
int ans2p_malloced = 0;
+
int olderr = errno;
- int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
+ int n;
+
+ if ((ctx->resp->options & RES_NOAAAA) == 0)
+ {
+ n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
host_buffer.buf->buf, 2048, &host_buffer.ptr,
&ans2p, &nans2p, &resplen2, &ans2p_malloced);
- if (n >= 0)
- {
- status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
- resplen2, name, pat, buffer, buflen,
- errnop, herrnop, ttlp);
+ if (n >= 0)
+ status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
+ resplen2, name, pat, buffer, buflen,
+ errnop, herrnop, ttlp);
}
else
+ {
+ n = __res_context_search (ctx, name, C_IN, T_A,
+ host_buffer.buf->buf, 2048, NULL,
+ NULL, NULL, NULL, NULL);
+ if (n >= 0)
+ status = gaih_getanswer_noaaaa (host_buffer.buf, n,
+ name, pat, buffer, buflen,
+ errnop, herrnop, ttlp);
+ }
+ if (n < 0)
{
switch (errno)
{
@@ -1388,3 +1410,21 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
return status;
}
+
+/* Variant of gaih_getanswer without a second (AAAA) response. */
+static enum nss_status
+gaih_getanswer_noaaaa (const querybuf *answer1, int anslen1, const char *qname,
+ struct gaih_addrtuple **pat,
+ char *buffer, size_t buflen,
+ int *errnop, int *h_errnop, int32_t *ttlp)
+{
+ int first = 1;
+
+ enum nss_status status = NSS_STATUS_NOTFOUND;
+ if (anslen1 > 0)
+ status = gaih_getanswer_slice (answer1, anslen1, qname,
+ &pat, &buffer, &buflen,
+ errnop, h_errnop, ttlp,
+ &first);
+ return status;
+}
diff --git a/resolv/res-noaaaa.c b/resolv/res-noaaaa.c
new file mode 100644
index 0000000000000000..4ba197664a86aed7
--- /dev/null
+++ b/resolv/res-noaaaa.c
@@ -0,0 +1,143 @@
+/* Implement suppression of AAAA queries.
+ 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 <resolv.h>
+#include <string.h>
+#include <resolv-internal.h>
+#include <resolv_context.h>
+#include <arpa/nameser.h>
+
+/* Returns true if the question type at P matches EXPECTED, and the
+ class is IN. */
+static bool
+qtype_matches (const unsigned char *p, int expected)
+{
+ /* This assumes that T_A/C_IN constants are less than 256, which
+ they are. */
+ return p[0] == 0 && p[1] == expected && p[2] == 0 && p[3] == C_IN;
+}
+
+/* Handle RES_NOAAAA translation of AAAA queries. To produce a Name
+ Error (NXDOMAIN) repsonse for domain names that do not exist, it is
+ still necessary to send a query. Using question type A is a
+ conservative choice. In the returned answer, it is necessary to
+ switch back the question type to AAAA. */
+bool
+__res_handle_no_aaaa (struct resolv_context *ctx,
+ const unsigned char *buf, int buflen,
+ unsigned char *ans, int anssiz, int *result)
+{
+ /* AAAA mode is not active, or the query looks invalid (will not be
+ able to be parsed). */
+ if ((ctx->resp->options & RES_NOAAAA) == 0
+ || buflen <= sizeof (HEADER))
+ return false;
+
+ /* The replacement A query is produced here. */
+ struct
+ {
+ HEADER header;
+ unsigned char question[NS_MAXCDNAME + 4];
+ } replacement;
+ memcpy (&replacement.header, buf, sizeof (replacement.header));
+
+ if (replacement.header.qr
+ || replacement.header.opcode != 0
+ || replacement.header.rcode != 0
+ || ntohs (replacement.header.qdcount) != 1
+ || ntohs (replacement.header.ancount) != 0
+ || ntohs (replacement.header.nscount) != 0)
+ /* Not a well-formed question. Let the core resolver code produce
+ the proper error. */
+ return false;
+
+ /* Disable EDNS0. */
+ replacement.header.arcount = htons (0);
+
+ /* Extract the QNAME. */
+ int ret = __ns_name_unpack (buf, buf + buflen, buf + sizeof (HEADER),
+ replacement.question, NS_MAXCDNAME);
+ if (ret < 0)
+ /* Format error. */
+ return false;
+
+ /* Compute the end of the question name. */
+ const unsigned char *after_question = buf + sizeof (HEADER) + ret;
+
+ /* Check that we are dealing with an AAAA query. */
+ if (buf + buflen - after_question < 4
+ || !qtype_matches (after_question, T_AAAA))
+ return false;
+
+ /* Find the place to store the type/class data in the replacement
+ query. */
+ after_question = replacement.question;
+ /* This cannot fail because __ns_name_unpack above produced a valid
+ domain name. */
+ (void) __ns_name_skip (&after_question, &replacement.question[NS_MAXCDNAME]);
+ unsigned char *start_of_query = (unsigned char *) &replacement;
+ const unsigned char *end_of_query = after_question + 4;
+
+ /* Produce an A/IN query. */
+ {
+ unsigned char *p = (unsigned char *) after_question;
+ p[0] = 0;
+ p[1] = T_A;
+ p[2] = 0;
+ p[3] = C_IN;
+ }
+
+ /* Clear the output buffer, to avoid reading undefined data when
+ rewriting the result from A to AAAA. */
+ memset (ans, 0, anssiz);
+
+ /* Always perform the message translation, independent of the error
+ code. */
+ ret = __res_context_send (ctx,
+ start_of_query, end_of_query - start_of_query,
+ NULL, 0, ans, anssiz,
+ NULL, NULL, NULL, NULL, NULL);
+
+ /* Patch in the AAAA question type if there is room and the A query
+ type was received. */
+ after_question = ans + sizeof (HEADER);
+ if (__ns_name_skip (&after_question, ans + anssiz) == 0
+ && ans + anssiz - after_question >= 4
+ && qtype_matches (after_question, T_A))
+ {
+ ((unsigned char *) after_question)[1] = T_AAAA;
+
+ /* Create an aligned copy of the header. Hide all data except
+ the question from the response. Put back the header. There is
+ no need to change the response code. The zero answer count turns
+ a positive response with data into a no-data response. */
+ memcpy (&replacement.header, ans, sizeof (replacement.header));
+ replacement.header.ancount = htons (0);
+ replacement.header.nscount = htons (0);
+ replacement.header.arcount = htons (0);
+ memcpy (ans, &replacement.header, sizeof (replacement.header));
+
+ /* Truncate the reply. */
+ if (ret <= 0)
+ *result = ret;
+ else
+ *result = after_question - ans + 4;
+ }
+
+ return true;
+}
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
index 030df0aa90c9f34f..b0fe69b1aa5186a0 100644
--- a/resolv/res_debug.c
+++ b/resolv/res_debug.c
@@ -613,6 +613,7 @@ p_option(u_long option) {
case RES_NOTLDQUERY: return "no-tld-query";
case RES_NORELOAD: return "no-reload";
case RES_TRUSTAD: return "trust-ad";
+ case RES_NOAAAA: return "no-aaaa";
/* XXX nonreentrant */
default: sprintf(nbuf, "?0x%lx?", (u_long)option);
return (nbuf);
diff --git a/resolv/res_init.c b/resolv/res_init.c
index 6b2936eda9618ac9..8bde915903565f60 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -695,6 +695,7 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options)
{ STRnLEN ("no-reload"), 0, RES_NORELOAD },
{ STRnLEN ("use-vc"), 0, RES_USEVC },
{ STRnLEN ("trust-ad"), 0, RES_TRUSTAD },
+ { STRnLEN ("no-aaaa"), 0, RES_NOAAAA },
};
#define noptions (sizeof (options) / sizeof (options[0]))
for (int i = 0; i < noptions; ++i)
diff --git a/resolv/res_query.c b/resolv/res_query.c
index 75b0e5f2f7b51eb2..2f3c28cfc8c0d832 100644
--- a/resolv/res_query.c
+++ b/resolv/res_query.c
@@ -204,10 +204,26 @@ __res_context_query (struct resolv_context *ctx, const char *name,
free (buf);
return (n);
}
- assert (answerp == NULL || (void *) *answerp == (void *) answer);
- n = __res_context_send (ctx, query1, nquery1, query2, nquery2, answer,
- anslen, answerp, answerp2, nanswerp2, resplen2,
- answerp2_malloced);
+
+ /* Suppress AAAA lookups if required. __res_handle_no_aaaa
+ checks RES_NOAAAA first, so avoids parsing the
+ just-generated query packet in most cases. nss_dns avoids
+ using T_QUERY_A_AND_AAAA in RES_NOAAAA mode, so there is no
+ need to handle it here. */
+ if (type == T_AAAA && __res_handle_no_aaaa (ctx, query1, nquery1,
+ answer, anslen, &n))
+ /* There must be no second query for AAAA queries. The code
+ below is still needed to translate NODATA responses. */
+ assert (query2 == NULL);
+ else
+ {
+ assert (answerp == NULL || (void *) *answerp == (void *) answer);
+ n = __res_context_send (ctx, query1, nquery1, query2, nquery2,
+ answer, anslen,
+ answerp, answerp2, nanswerp2, resplen2,
+ answerp2_malloced);
+ }
+
if (use_malloc)
free (buf);
if (n < 0) {
diff --git a/resolv/res_send.c b/resolv/res_send.c
index 9f86f5fe47194887..8ac6a307b40fa2ca 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -438,8 +438,13 @@ context_send_common (struct resolv_context *ctx,
RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
return -1;
}
- int result = __res_context_send (ctx, buf, buflen, NULL, 0, ans, anssiz,
- NULL, NULL, NULL, NULL, NULL);
+
+ int result;
+ if (__res_handle_no_aaaa (ctx, buf, buflen, ans, anssiz, &result))
+ return result;
+
+ result = __res_context_send (ctx, buf, buflen, NULL, 0, ans, anssiz,
+ NULL, NULL, NULL, NULL, NULL);
__resolv_context_put (ctx);
return result;
}
diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h
index 216e47ed42076b72..8ab02fc9e648d30f 100644
--- a/resolv/resolv-internal.h
+++ b/resolv/resolv-internal.h
@@ -78,6 +78,14 @@ int __res_context_send (struct resolv_context *, const unsigned char *, int,
int *, int *, int *);
libc_hidden_proto (__res_context_send)
+/* Return true if the query has been handled in RES_NOAAAA mode. For
+ that, RES_NOAAAA must be active, and the question type must be AAAA.
+ The caller is expected to return *RESULT as the return value. */
+bool __res_handle_no_aaaa (struct resolv_context *ctx,
+ const unsigned char *buf, int buflen,
+ unsigned char *ans, int anssiz, int *result)
+ attribute_hidden;
+
/* Internal function similar to res_hostalias. */
const char *__res_context_hostalias (struct resolv_context *,
const char *, char *, size_t);
diff --git a/resolv/resolv.h b/resolv/resolv.h
index e7c8d44645912ddf..3a79ffea57a6916f 100644
--- a/resolv/resolv.h
+++ b/resolv/resolv.h
@@ -132,6 +132,7 @@ struct res_sym {
as a TLD. */
#define RES_NORELOAD 0x02000000 /* No automatic configuration reload. */
#define RES_TRUSTAD 0x04000000 /* Request AD bit, keep it in responses. */
+#define RES_NOAAAA 0x08000000 /* Suppress AAAA queries. */
#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH)
diff --git a/resolv/tst-resolv-noaaaa.c b/resolv/tst-resolv-noaaaa.c
new file mode 100644
index 0000000000000000..56b25f88a58ad286
--- /dev/null
+++ b/resolv/tst-resolv-noaaaa.c
@@ -0,0 +1,533 @@
+/* Test the RES_NOAAAA resolver option.
+ 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 <netdb.h>
+#include <resolv.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+
+/* Used to keep track of the number of queries. */
+static volatile unsigned int queries;
+
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ /* Each test should only send one query. */
+ ++queries;
+ TEST_COMPARE (queries, 1);
+
+ /* AAAA queries are supposed to be disabled. */
+ TEST_VERIFY (qtype != T_AAAA);
+ TEST_COMPARE (qclass, C_IN);
+
+ /* The only other query type besides A is PTR. */
+ if (qtype != T_A)
+ TEST_COMPARE (qtype, T_PTR);
+
+ int an, ns, ar;
+ char *tail;
+ if (sscanf (qname, "an%d.ns%d.ar%d.%ms", &an, &ns, &ar, &tail) != 4)
+ FAIL_EXIT1 ("invalid QNAME: %s\n", qname);
+ TEST_COMPARE_STRING (tail, "example");
+ free (tail);
+
+ if (an < 0 || ns < 0 || ar < 0)
+ {
+ struct resolv_response_flags flags = { .rcode = NXDOMAIN, };
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+ return;
+ }
+
+ struct resolv_response_flags flags = {};
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+
+ resolv_response_section (b, ns_s_an);
+ for (int i = 0; i < an; ++i)
+ {
+ resolv_response_open_record (b, qname, qclass, qtype, 60);
+ switch (qtype)
+ {
+ case T_A:
+ char ipv4[4] = {192, 0, 2, i + 1};
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
+ break;
+
+ case T_PTR:
+ char *name = xasprintf ("ptr-%d", i);
+ resolv_response_add_name (b, name);
+ free (name);
+ break;
+ }
+ resolv_response_close_record (b);
+ }
+
+ resolv_response_section (b, ns_s_ns);
+ for (int i = 0; i < ns; ++i)
+ {
+ resolv_response_open_record (b, qname, qclass, T_NS, 60);
+ char *name = xasprintf ("ns%d.example.net", i);
+ resolv_response_add_name (b, name);
+ free (name);
+ resolv_response_close_record (b);
+ }
+
+ resolv_response_section (b, ns_s_ar);
+ int addr = 1;
+ for (int i = 0; i < ns; ++i)
+ {
+ char *name = xasprintf ("ns%d.example.net", i);
+ for (int j = 0; j < ar; ++j)
+ {
+ resolv_response_open_record (b, name, qclass, T_A, 60);
+ char ipv4[4] = {192, 0, 2, addr};
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
+ resolv_response_close_record (b);
+
+ resolv_response_open_record (b, name, qclass, T_AAAA, 60);
+ char ipv6[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, addr};
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
+ resolv_response_close_record (b);
+
+ ++addr;
+ }
+ free (name);
+ }
+}
+
+/* Number of modes. Lowest bit encodes *n* function vs implicit _res
+ argument. The mode numbers themselves are arbitrary. */
+enum { mode_count = 8 };
+
+/* res_send-like modes do not perform error translation. */
+enum { first_send_mode = 6 };
+
+static int
+libresolv_query (unsigned int mode, const char *qname, uint16_t qtype,
+ unsigned char *buf, size_t buflen)
+{
+ int saved_errno = errno;
+
+ TEST_VERIFY_EXIT (mode < mode_count);
+
+ switch (mode)
+ {
+ case 0:
+ return res_query (qname, C_IN, qtype, buf, buflen);
+ case 1:
+ return res_nquery (&_res, qname, C_IN, qtype, buf, buflen);
+ case 2:
+ return res_search (qname, C_IN, qtype, buf, buflen);
+ case 3:
+ return res_nsearch (&_res, qname, C_IN, qtype, buf, buflen);
+ case 4:
+ return res_querydomain (qname, "", C_IN, qtype, buf, buflen);
+ case 5:
+ return res_nquerydomain (&_res, qname, "", C_IN, qtype, buf, buflen);
+ case 6:
+ {
+ unsigned char querybuf[512];
+ int ret = res_mkquery (QUERY, qname, C_IN, qtype,
+ NULL, 0, NULL, querybuf, sizeof (querybuf));
+ TEST_VERIFY_EXIT (ret > 0);
+ errno = saved_errno;
+ return res_send (querybuf, ret, buf, buflen);
+ }
+ case 7:
+ {
+ unsigned char querybuf[512];
+ int ret = res_nmkquery (&_res, QUERY, qname, C_IN, qtype,
+ NULL, 0, NULL, querybuf, sizeof (querybuf));
+ TEST_VERIFY_EXIT (ret > 0);
+ errno = saved_errno;
+ return res_nsend (&_res, querybuf, ret, buf, buflen);
+ }
+ }
+ __builtin_unreachable ();
+}
+
+static int
+do_test (void)
+{
+ struct resolv_test *obj = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response
+ });
+
+ _res.options |= RES_NOAAAA;
+
+ check_hostent ("an1.ns2.ar1.example",
+ gethostbyname ("an1.ns2.ar1.example"),
+ "name: an1.ns2.ar1.example\n"
+ "address: 192.0.2.1\n");
+ queries = 0;
+ check_hostent ("an0.ns2.ar1.example",
+ gethostbyname ("an0.ns2.ar1.example"),
+ "error: NO_ADDRESS\n");
+ queries = 0;
+ check_hostent ("an-1.ns2.ar1.example",
+ gethostbyname ("an-1.ns2.ar1.example"),
+ "error: HOST_NOT_FOUND\n");
+ queries = 0;
+
+ check_hostent ("an1.ns2.ar1.example AF_INET",
+ gethostbyname2 ("an1.ns2.ar1.example", AF_INET),
+ "name: an1.ns2.ar1.example\n"
+ "address: 192.0.2.1\n");
+ queries = 0;
+ check_hostent ("an0.ns2.ar1.example AF_INET",
+ gethostbyname2 ("an0.ns2.ar1.example", AF_INET),
+ "error: NO_ADDRESS\n");
+ queries = 0;
+ check_hostent ("an-1.ns2.ar1.example AF_INET",
+ gethostbyname2 ("an-1.ns2.ar1.example", AF_INET),
+ "error: HOST_NOT_FOUND\n");
+ queries = 0;
+
+ check_hostent ("an1.ns2.ar1.example AF_INET6",
+ gethostbyname2 ("an1.ns2.ar1.example", AF_INET6),
+ "error: NO_ADDRESS\n");
+ queries = 0;
+ check_hostent ("an0.ns2.ar1.example AF_INET6",
+ gethostbyname2 ("an0.ns2.ar1.example", AF_INET6),
+ "error: NO_ADDRESS\n");
+ queries = 0;
+ check_hostent ("an-1.ns2.ar1.example AF_INET6",
+ gethostbyname2 ("an-1.ns2.ar1.example", AF_INET6),
+ "error: HOST_NOT_FOUND\n");
+ queries = 0;
+
+ /* Multiple addresses. */
+ check_hostent ("an2.ns0.ar0.example",
+ gethostbyname ("an2.ns0.ar0.example"),
+ "name: an2.ns0.ar0.example\n"
+ "address: 192.0.2.1\n"
+ "address: 192.0.2.2\n");
+ queries = 0;
+ check_hostent ("an2.ns0.ar0.example AF_INET6",
+ gethostbyname2 ("an2.ns0.ar0.example", AF_INET6),
+ "error: NO_ADDRESS\n");
+ queries = 0;
+
+ /* getaddrinfo checks with one address. */
+ struct addrinfo *ai;
+ int ret;
+ ret = getaddrinfo ("an1.ns2.ar1.example", "80",
+ &(struct addrinfo)
+ {
+ .ai_family = AF_INET,
+ .ai_socktype = SOCK_STREAM,
+ }, &ai);
+ check_addrinfo ("an1.ns2.ar1.example (AF_INET)", ai, ret,
+ "address: STREAM/TCP 192.0.2.1 80\n");
+ freeaddrinfo (ai);
+ queries = 0;
+ ret = getaddrinfo ("an1.ns2.ar1.example", "80",
+ &(struct addrinfo)
+ {
+ .ai_family = AF_INET6,
+ .ai_socktype = SOCK_STREAM,
+ }, &ai);
+ check_addrinfo ("an1.ns2.ar1.example (AF_INET6)", ai, ret,
+ "error: No address associated with hostname\n");
+ queries = 0;
+ ret = getaddrinfo ("an1.ns2.ar1.example", "80",
+ &(struct addrinfo)
+ {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM,
+ }, &ai);
+ check_addrinfo ("an1.ns2.ar1.example (AF_UNSPEC)", ai, ret,
+ "address: STREAM/TCP 192.0.2.1 80\n");
+ freeaddrinfo (ai);
+ queries = 0;
+
+ /* getaddrinfo checks with three addresses. */
+ ret = getaddrinfo ("an3.ns2.ar1.example", "80",
+ &(struct addrinfo)
+ {
+ .ai_family = AF_INET,
+ .ai_socktype = SOCK_STREAM,
+ }, &ai);
+ check_addrinfo ("an3.ns2.ar1.example (AF_INET)", ai, ret,
+ "address: STREAM/TCP 192.0.2.1 80\n"
+ "address: STREAM/TCP 192.0.2.2 80\n"
+ "address: STREAM/TCP 192.0.2.3 80\n");
+ freeaddrinfo (ai);
+ queries = 0;
+ ret = getaddrinfo ("an3.ns2.ar1.example", "80",
+ &(struct addrinfo)
+ {
+ .ai_family = AF_INET6,
+ .ai_socktype = SOCK_STREAM,
+ }, &ai);
+ check_addrinfo ("an3.ns2.ar1.example (AF_INET6)", ai, ret,
+ "error: No address associated with hostname\n");
+ queries = 0;
+ ret = getaddrinfo ("an3.ns2.ar1.example", "80",
+ &(struct addrinfo)
+ {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM,
+ }, &ai);
+ check_addrinfo ("an3.ns2.ar1.example (AF_UNSPEC)", ai, ret,
+ "address: STREAM/TCP 192.0.2.1 80\n"
+ "address: STREAM/TCP 192.0.2.2 80\n"
+ "address: STREAM/TCP 192.0.2.3 80\n");
+ freeaddrinfo (ai);
+ queries = 0;
+
+ /* getaddrinfo checks with no address. */
+ ret = getaddrinfo ("an0.ns2.ar1.example", "80",
+ &(struct addrinfo)
+ {
+ .ai_family = AF_INET,
+ .ai_socktype = SOCK_STREAM,
+ }, &ai);
+ check_addrinfo ("an0.ns2.ar1.example (AF_INET)", ai, ret,
+ "error: No address associated with hostname\n");
+ queries = 0;
+ ret = getaddrinfo ("an0.ns2.ar1.example", "80",
+ &(struct addrinfo)
+ {
+ .ai_family = AF_INET6,
+ .ai_socktype = SOCK_STREAM,
+ }, &ai);
+ check_addrinfo ("an0.ns2.ar1.example (AF_INET6)", ai, ret,
+ "error: No address associated with hostname\n");
+ queries = 0;
+ ret = getaddrinfo ("an0.ns2.ar1.example", "80",
+ &(struct addrinfo)
+ {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM,
+ }, &ai);
+ check_addrinfo ("an-1.ns2.ar1.example (AF_UNSPEC)", ai, ret,
+ "error: No address associated with hostname\n");
+ queries = 0;
+
+ /* getaddrinfo checks with NXDOMAIN. */
+ ret = getaddrinfo ("an-1.ns2.ar1.example", "80",
+ &(struct addrinfo)
+ {
+ .ai_family = AF_INET,
+ .ai_socktype = SOCK_STREAM,
+ }, &ai);
+ check_addrinfo ("an-1.ns2.ar1.example (AF_INET)", ai, ret,
+ "error: Name or service not known\n");
+ queries = 0;
+ ret = getaddrinfo ("an-1.ns2.ar1.example", "80",
+ &(struct addrinfo)
+ {
+ .ai_family = AF_INET6,
+ .ai_socktype = SOCK_STREAM,
+ }, &ai);
+ check_addrinfo ("an-1.ns2.ar1.example (AF_INET6)", ai, ret,
+ "error: Name or service not known\n");
+ queries = 0;
+ ret = getaddrinfo ("an-1.ns2.ar1.example", "80",
+ &(struct addrinfo)
+ {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM,
+ }, &ai);
+ check_addrinfo ("an-1.ns2.ar1.example (AF_UNSPEC)", ai, ret,
+ "error: Name or service not known\n");
+ queries = 0;
+
+ for (unsigned int mode = 0; mode < mode_count; ++mode)
+ {
+ unsigned char *buf;
+ int ret;
+
+ /* Response for A. */
+ buf = malloc (512);
+ ret = libresolv_query (mode, "an1.ns2.ar1.example", T_A, buf, 512);
+ TEST_VERIFY_EXIT (ret > 0);
+ check_dns_packet ("an1.ns2.ar1.example A", buf, ret,
+ "name: an1.ns2.ar1.example\n"
+ "address: 192.0.2.1\n");
+ free (buf);
+ queries = 0;
+
+ /* NODATA response for A. */
+ buf = malloc (512);
+ errno = 0;
+ ret = libresolv_query (mode, "an0.ns2.ar1.example", T_A, buf, 512);
+ if (mode < first_send_mode)
+ {
+ TEST_COMPARE (ret, -1);
+ TEST_COMPARE (errno, 0);
+ TEST_COMPARE (h_errno, NO_ADDRESS);
+ }
+ else
+ {
+ TEST_VERIFY_EXIT (ret > 0);
+ TEST_COMPARE (((HEADER *)buf)->rcode, 0);
+ check_dns_packet ("an1.ns2.ar1.example A", buf, ret,
+ "name: an0.ns2.ar1.example\n");
+ }
+ free (buf);
+ queries = 0;
+
+ /* NXDOMAIN response for A. */
+ buf = malloc (512);
+ errno = 0;
+ ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_A, buf, 512);
+ if (mode < first_send_mode)
+ {
+ TEST_COMPARE (ret, -1);
+ TEST_COMPARE (errno, 0);
+ TEST_COMPARE (h_errno, HOST_NOT_FOUND);
+ }
+ else
+ {
+ TEST_VERIFY_EXIT (ret > 0);
+ TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN);
+ check_dns_packet ("an1.ns2.ar1.example A", buf, ret,
+ "name: an-1.ns2.ar1.example\n");
+ }
+ free (buf);
+ queries = 0;
+
+ /* Response for PTR. */
+ buf = malloc (512);
+ ret = libresolv_query (mode, "an1.ns2.ar1.example", T_PTR, buf, 512);
+ TEST_VERIFY_EXIT (ret > 0);
+ check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret,
+ "name: an1.ns2.ar1.example\n"
+ "data: an1.ns2.ar1.example PTR ptr-0\n");
+ free (buf);
+ queries = 0;
+
+ /* NODATA response for PTR. */
+ buf = malloc (512);
+ errno = 0;
+ ret = libresolv_query (mode, "an0.ns2.ar1.example", T_PTR, buf, 512);
+ if (mode < first_send_mode)
+ {
+ TEST_COMPARE (ret, -1);
+ TEST_COMPARE (errno, 0);
+ TEST_COMPARE (h_errno, NO_ADDRESS);
+ }
+ else
+ {
+ TEST_VERIFY_EXIT (ret > 0);
+ TEST_COMPARE (((HEADER *)buf)->rcode, 0);
+ check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret,
+ "name: an0.ns2.ar1.example\n");
+ }
+ free (buf);
+ queries = 0;
+
+ /* NXDOMAIN response for PTR. */
+ buf = malloc (512);
+ errno = 0;
+ ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_PTR, buf, 512);
+ if (mode < first_send_mode)
+ {
+ TEST_COMPARE (ret, -1);
+ TEST_COMPARE (errno, 0);
+ TEST_COMPARE (h_errno, HOST_NOT_FOUND);
+ }
+ else
+ {
+ TEST_VERIFY_EXIT (ret > 0);
+ TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN);
+ check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret,
+ "name: an-1.ns2.ar1.example\n");
+ }
+ free (buf);
+ queries = 0;
+
+ /* NODATA response for AAAA. */
+ buf = malloc (512);
+ errno = 0;
+ ret = libresolv_query (mode, "an1.ns2.ar1.example", T_AAAA, buf, 512);
+ if (mode < first_send_mode)
+ {
+ TEST_COMPARE (ret, -1);
+ TEST_COMPARE (errno, 0);
+ TEST_COMPARE (h_errno, NO_ADDRESS);
+ }
+ else
+ {
+ TEST_VERIFY_EXIT (ret > 0);
+ TEST_COMPARE (((HEADER *)buf)->rcode, 0);
+ check_dns_packet ("an1.ns2.ar1.example A", buf, ret,
+ "name: an1.ns2.ar1.example\n");
+ }
+ free (buf);
+ queries = 0;
+
+ /* NODATA response for AAAA (original is already NODATA). */
+ buf = malloc (512);
+ errno = 0;
+ ret = libresolv_query (mode, "an0.ns2.ar1.example", T_AAAA, buf, 512);
+ if (mode < first_send_mode)
+ {
+ TEST_COMPARE (ret, -1);
+ TEST_COMPARE (errno, 0);
+ TEST_COMPARE (h_errno, NO_ADDRESS);
+ }
+ else
+ {
+ TEST_VERIFY_EXIT (ret > 0);
+ TEST_COMPARE (((HEADER *)buf)->rcode, 0);
+ check_dns_packet ("an0.ns2.ar1.example A", buf, ret,
+ "name: an0.ns2.ar1.example\n");
+ }
+ free (buf);
+ queries = 0;
+
+ /* NXDOMAIN response. */
+ buf = malloc (512);
+ errno = 0;
+ ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_AAAA, buf, 512);
+ if (mode < first_send_mode)
+ {
+ TEST_COMPARE (ret, -1);
+ TEST_COMPARE (errno, 0);
+ TEST_COMPARE (h_errno, HOST_NOT_FOUND);
+ }
+ else
+ {
+ TEST_VERIFY_EXIT (ret > 0);
+ TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN);
+ check_dns_packet ("an-1.ns2.ar1.example A", buf, ret,
+ "name: an-1.ns2.ar1.example\n");
+ }
+ free (buf);
+ queries = 0;
+ }
+
+ resolv_test_end (obj);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
index c87596762fcb23b1..28ed9c2eb150532d 100644
--- a/resolv/tst-resolv-res_init-skeleton.c
+++ b/resolv/tst-resolv-res_init-skeleton.c
@@ -128,6 +128,7 @@ print_resp (FILE *fp, res_state resp)
print_option_flag (fp, &options, RES_NOTLDQUERY, "no-tld-query");
print_option_flag (fp, &options, RES_NORELOAD, "no-reload");
print_option_flag (fp, &options, RES_TRUSTAD, "trust-ad");
+ print_option_flag (fp, &options, RES_NOAAAA, "no-aaaa");
fputc ('\n', fp);
if (options != 0)
fprintf (fp, "; error: unresolved option bits: 0x%x\n", options);
@@ -721,6 +722,15 @@ struct test_case test_cases[] =
"nameserver 192.0.2.1\n"
"; nameserver[0]: [192.0.2.1]:53\n"
},
+ {.name = "no-aaaa flag",
+ .conf = "options no-aaaa\n"
+ "nameserver 192.0.2.1\n",
+ .expected = "options no-aaaa\n"
+ "search example.com\n"
+ "; search[0]: example.com\n"
+ "nameserver 192.0.2.1\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ },
{ NULL }
};

@ -0,0 +1,154 @@
commit cca9684f2d7a74fc0b28bfb1859955e0e28d7b4b
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Aug 3 11:41:53 2022 +0200
stdio: Clean up __libc_message after unconditional abort
Since commit ec2c1fcefb200c6cb7e09553f3c6af8815013d83 ("malloc:
Abort on heap corruption, without a backtrace [BZ #21754]"),
__libc_message always terminates the process. Since commit
a289ea09ea843ced6e5277c2f2e63c357bc7f9a3 ("Do not print backtraces
on fatal glibc errors"), the backtrace facility has been removed.
Therefore, remove enum __libc_message_action and the action
argument of __libc_message, and mark __libc_message as _No_return.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/debug/fortify_fail.c b/debug/fortify_fail.c
index 9fa07af4867c2bd1..1b490d9da78b8d0d 100644
--- a/debug/fortify_fail.c
+++ b/debug/fortify_fail.c
@@ -21,8 +21,6 @@ void
__attribute__ ((noreturn))
__fortify_fail (const char *msg)
{
- /* The loop is added only to keep gcc happy. */
- while (1)
- __libc_message (do_abort, "*** %s ***: terminated\n", msg);
+ __libc_message ("*** %s ***: terminated\n", msg);
}
libc_hidden_def (__fortify_fail)
diff --git a/include/stdio.h b/include/stdio.h
index 23b7fd288cdaba66..3d4544575318a934 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -143,18 +143,11 @@ extern int __gen_tempname (char *__tmpl, int __suffixlen, int __flags,
# define __GT_DIR 1 /* create a directory */
# define __GT_NOCREATE 2 /* just find a name not currently in use */
-enum __libc_message_action
-{
- do_message = 0, /* Print message. */
- do_abort = 1 << 0, /* Abort. */
-};
-
/* Print out MESSAGE (which should end with a newline) on the error output
and abort. */
extern void __libc_fatal (const char *__message)
__attribute__ ((__noreturn__));
-extern void __libc_message (enum __libc_message_action action,
- const char *__fnt, ...) attribute_hidden;
+_Noreturn void __libc_message (const char *__fnt, ...) attribute_hidden;
extern void __fortify_fail (const char *msg) __attribute__ ((__noreturn__));
libc_hidden_proto (__fortify_fail)
diff --git a/malloc/malloc.c b/malloc/malloc.c
index d31e985ecce968fe..918e7936f1983437 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -298,8 +298,7 @@ _Noreturn static void
__malloc_assert (const char *assertion, const char *file, unsigned int line,
const char *function)
{
- __libc_message (do_abort, "\
-Fatal glibc error: malloc assertion failure in %s: %s\n",
+ __libc_message ("Fatal glibc error: malloc assertion failure in %s: %s\n",
function, assertion);
__builtin_unreachable ();
}
@@ -5528,7 +5527,7 @@ static void
malloc_printerr (const char *str)
{
#if IS_IN (libc)
- __libc_message (do_abort, "%s\n", str);
+ __libc_message ("%s\n", str);
#else
__libc_fatal (str);
#endif
diff --git a/sysdeps/posix/libc_fatal.c b/sysdeps/posix/libc_fatal.c
index 6d24bee6134856d1..1feacfbeba765035 100644
--- a/sysdeps/posix/libc_fatal.c
+++ b/sysdeps/posix/libc_fatal.c
@@ -54,7 +54,7 @@ struct str_list
/* Abort with an error message. */
void
-__libc_message (enum __libc_message_action action, const char *fmt, ...)
+__libc_message (const char *fmt, ...)
{
va_list ap;
int fd = -1;
@@ -123,36 +123,31 @@ __libc_message (enum __libc_message_action action, const char *fmt, ...)
WRITEV_FOR_FATAL (fd, iov, nlist, total);
- if ((action & do_abort))
+ total = (total + 1 + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1);
+ struct abort_msg_s *buf = __mmap (NULL, total,
+ PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (__glibc_likely (buf != MAP_FAILED))
{
- total = ((total + 1 + GLRO(dl_pagesize) - 1)
- & ~(GLRO(dl_pagesize) - 1));
- struct abort_msg_s *buf = __mmap (NULL, total,
- PROT_READ | PROT_WRITE,
- MAP_ANON | MAP_PRIVATE, -1, 0);
- if (__glibc_likely (buf != MAP_FAILED))
- {
- buf->size = total;
- char *wp = buf->msg;
- for (int cnt = 0; cnt < nlist; ++cnt)
- wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len);
- *wp = '\0';
-
- /* We have to free the old buffer since the application might
- catch the SIGABRT signal. */
- struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg,
- buf);
- if (old != NULL)
- __munmap (old, old->size);
- }
+ buf->size = total;
+ char *wp = buf->msg;
+ for (int cnt = 0; cnt < nlist; ++cnt)
+ wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len);
+ *wp = '\0';
+
+ /* We have to free the old buffer since the application might
+ catch the SIGABRT signal. */
+ struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg,
+ buf);
+ if (old != NULL)
+ __munmap (old, old->size);
}
}
va_end (ap);
- if ((action & do_abort))
- /* Kill the application. */
- abort ();
+ /* Kill the application. */
+ abort ();
}
@@ -161,6 +156,6 @@ __libc_fatal (const char *message)
{
/* The loop is added only to keep gcc happy. */
while (1)
- __libc_message (do_abort, "%s", message);
+ __libc_message ("%s", message);
}
libc_hidden_def (__libc_fatal)

@ -0,0 +1,45 @@
commit 68e036f27f31c3378201702e182246504fb00f87
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Aug 3 11:41:53 2022 +0200
nptl: Remove uses of assert_perror
__pthread_sigmask cannot actually fail with valid pointer arguments
(it would need a really broken seccomp filter), and we do not check
for errors elsewhere.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/sysdeps/nptl/gai_misc.h b/sysdeps/nptl/gai_misc.h
index 261e24dae62d7871..700fd5c46b4b7c82 100644
--- a/sysdeps/nptl/gai_misc.h
+++ b/sysdeps/nptl/gai_misc.h
@@ -81,9 +81,7 @@ __gai_start_notify_thread (void)
{
sigset_t ss;
sigemptyset (&ss);
- int sigerr __attribute__ ((unused));
- sigerr = __pthread_sigmask (SIG_SETMASK, &ss, NULL);
- assert_perror (sigerr);
+ (void) __pthread_sigmask (SIG_SETMASK, &ss, NULL);
}
extern inline int
@@ -106,15 +104,12 @@ __gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *),
sigset_t ss;
sigset_t oss;
sigfillset (&ss);
- int sigerr __attribute__ ((unused));
- sigerr = __pthread_sigmask (SIG_SETMASK, &ss, &oss);
- assert_perror (sigerr);
+ (void) __pthread_sigmask (SIG_SETMASK, &ss, &oss);
int ret = __pthread_create (threadp, &attr, tf, arg);
/* Restore the signal mask. */
- sigerr = __pthread_sigmask (SIG_SETMASK, &oss, NULL);
- assert_perror (sigerr);
+ (void) __pthread_sigmask (SIG_SETMASK, &oss, NULL);
(void) __pthread_attr_destroy (&attr);
return ret;

@ -0,0 +1,164 @@
commit 9001cb1102cddba54f0e84e147dfbb0356067356
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Aug 3 11:41:53 2022 +0200
assert: Do not use stderr in libc-internal assert
Redirect internal assertion failures to __libc_assert_fail, based on
based on __libc_message, which writes directly to STDERR_FILENO
and calls abort. Also disable message translation and reword the
error message slightly (adjusting stdlib/tst-bz20544 accordingly).
As a result of these changes, malloc no longer needs its own
redefinition of __assert_fail.
__libc_assert_fail needs to be stubbed out during rtld dependency
analysis because the rtld rebuilds turn __libc_assert_fail into
__assert_fail, which is unconditionally provided by elf/dl-minimal.c.
This change is not possible for the public assert macro and its
__assert_fail function because POSIX requires that the diagnostic
is written to stderr.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/assert/Makefile b/assert/Makefile
index 0008de34cb484a13..2bc9e2214e3e9a8b 100644
--- a/assert/Makefile
+++ b/assert/Makefile
@@ -24,7 +24,12 @@ include ../Makeconfig
headers := assert.h
-routines := assert assert-perr __assert
+routines := \
+ __assert \
+ __libc_assert_fail \
+ assert \
+ assert-perr \
+ # routines
tests := test-assert test-assert-perr tst-assert-c++ tst-assert-g++
ifeq ($(have-cxx-thread_local),yes)
diff --git a/assert/__libc_assert_fail.c b/assert/__libc_assert_fail.c
new file mode 100644
index 0000000000000000..149d5feae12f4af8
--- /dev/null
+++ b/assert/__libc_assert_fail.c
@@ -0,0 +1,33 @@
+/* libc-internal assert that calls __libc_message.
+ 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 <_itoa.h>
+#include <array_length.h>
+#include <intprops.h>
+#include <stdio.h>
+
+void
+__libc_assert_fail (const char *assertion, const char *file, unsigned int line,
+ const char *function)
+{
+ char linebuf[INT_BUFSIZE_BOUND (unsigned int)];
+ array_end (linebuf)[-1] = '\0';
+ char *linestr = _itoa_word (line, array_end (linebuf) - 1, 10, 0);
+ __libc_message ("Fatal glibc error: %s:%s (%s): assertion failed: %s\n",
+ file, linestr, function, assertion);
+}
diff --git a/assert/assert.c b/assert/assert.c
index 8a277dce008b3495..989126c7e5b6b265 100644
--- a/assert/assert.c
+++ b/assert/assert.c
@@ -101,4 +101,3 @@ __assert_fail (const char *assertion, const char *file, unsigned int line,
__assert_fail_base (_("%s%s%s:%u: %s%sAssertion `%s' failed.\n%n"),
assertion, file, line, function);
}
-hidden_def(__assert_fail)
diff --git a/elf/Makefile b/elf/Makefile
index 613d244e7781d479..2b547d5b58f1759b 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -1158,6 +1158,7 @@ $(objpfx)dl-allobjs.os: $(all-rtld-routines:%=$(objpfx)%.os)
rtld-stubbed-symbols = \
__GI___pthread_disable_asynccancel \
__GI___pthread_enable_asynccancel \
+ __libc_assert_fail \
__pthread_disable_asynccancel \
__pthread_enable_asynccancel \
calloc \
diff --git a/include/assert.h b/include/assert.h
index 61cc8aa22ff4b913..c812808f9b767964 100644
--- a/include/assert.h
+++ b/include/assert.h
@@ -20,8 +20,14 @@ extern void __assert_fail_base (const char *fmt, const char *assertion,
const char *function)
__THROW __attribute__ ((__noreturn__)) attribute_hidden;
-# if IS_IN (libc) || (IS_IN (rtld) && !defined NO_RTLD_HIDDEN)
-hidden_proto (__assert_fail)
-hidden_proto (__assert_perror_fail)
+rtld_hidden_proto (__assert_fail)
+rtld_hidden_proto (__assert_perror_fail)
+libc_hidden_proto (__assert_perror_fail)
+
+
+# if IS_IN (libc)
+/* Redirect to the internal version which does not use stderr. */
+extern _Noreturn __typeof (__assert_fail) __libc_assert_fail attribute_hidden;
+# define __assert_fail __libc_assert_fail
# endif
#endif
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 918e7936f1983437..2edb469d5dbf1203 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -289,22 +289,6 @@
#define MALLOC_DEBUG 0
#endif
-#if IS_IN (libc)
-#ifndef NDEBUG
-# define __assert_fail(assertion, file, line, function) \
- __malloc_assert(assertion, file, line, function)
-
-_Noreturn static void
-__malloc_assert (const char *assertion, const char *file, unsigned int line,
- const char *function)
-{
- __libc_message ("Fatal glibc error: malloc assertion failure in %s: %s\n",
- function, assertion);
- __builtin_unreachable ();
-}
-#endif
-#endif
-
#if USE_TCACHE
/* We want 64 entries. This is an arbitrary limit, which tunables can reduce. */
# define TCACHE_MAX_BINS 64
diff --git a/stdlib/tst-bz20544.c b/stdlib/tst-bz20544.c
index 4aa5793b8994d1f6..1337a3952c30e517 100644
--- a/stdlib/tst-bz20544.c
+++ b/stdlib/tst-bz20544.c
@@ -78,7 +78,7 @@ test_bz20544_cxa_at_quick_exit (void *closure)
static void
test_one_fn (void (*test_fn) (void *))
{
- const char expected_error[] = "Assertion `func != NULL' failed.\n";
+ const char expected_error[] = "assertion failed: func != NULL\n";
struct support_capture_subprocess result;
result = support_capture_subprocess (test_fn, NULL);
support_capture_subprocess_check (&result, "bz20544", -SIGABRT,

@ -0,0 +1,22 @@
commit 8fabe0e632bd441c760f878d1022c378f04f8497
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Aug 4 06:17:50 2022 +0200
Linux: Remove exit system call from _exit
exit only terminates the current thread, not the whole process, so it
is the wrong fallback system call in this context. All supported
Linux versions implement the exit_group system call anyway.
diff --git a/sysdeps/unix/sysv/linux/_exit.c b/sysdeps/unix/sysv/linux/_exit.c
index 2f0ec35459f25314..cd1270ac9b2b5b2b 100644
--- a/sysdeps/unix/sysv/linux/_exit.c
+++ b/sysdeps/unix/sysv/linux/_exit.c
@@ -28,7 +28,6 @@ _exit (int status)
while (1)
{
INLINE_SYSCALL (exit_group, 1, status);
- INLINE_SYSCALL (exit, 1, status);
#ifdef ABORT_INSTRUCTION
ABORT_INSTRUCTION;

@ -0,0 +1,69 @@
Very limited backport of the following upstream commit, to obtain
the definition of __getrandom_nocancel.
commit 6f4e0fcfa2d2b0915816a3a3a1d48b4763a7dee2
Author: Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>
Date: Thu Jul 21 10:04:59 2022 -0300
stdlib: Add arc4random, arc4random_buf, and arc4random_uniform (BZ #4417)
With the INTERNAL_SYSCALL_CALL change from this patch already applied:
commit 609c9d0951da387cd523b5db42a82d38dabc37c4
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Thu Sep 29 16:18:06 2022 -0300
malloc: Do not clobber errno on __getrandom_nocancel (BZ #29624)
Use INTERNAL_SYSCALL_CALL instead of INLINE_SYSCALL_CALL. This
requires emulate the semantic for hurd call (so __arc4random_buf
uses the fallback).
Checked on x86_64-linux-gnu.
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
diff --git a/sysdeps/generic/not-cancel.h b/sysdeps/generic/not-cancel.h
index 8a3772a1fe66271e..14188041c2c0ad57 100644
--- a/sysdeps/generic/not-cancel.h
+++ b/sysdeps/generic/not-cancel.h
@@ -49,5 +49,7 @@
(void) __writev (fd, iov, n)
#define __fcntl64_nocancel(fd, cmd, ...) \
__fcntl64 (fd, cmd, __VA_ARGS__)
+#define __getrandom_nocancel(buf, size, flags) \
+ __getrandom (buf, size, flags)
#endif /* NOT_CANCEL_H */
diff --git a/sysdeps/mach/hurd/not-cancel.h b/sysdeps/mach/hurd/not-cancel.h
index cd320cb721e6ff7e..7a3d2cc3532cf866 100644
--- a/sysdeps/mach/hurd/not-cancel.h
+++ b/sysdeps/mach/hurd/not-cancel.h
@@ -75,6 +75,9 @@ __typeof (__fcntl) __fcntl_nocancel;
#define __fcntl64_nocancel(...) \
__fcntl_nocancel (__VA_ARGS__)
+#define __getrandom_nocancel(buf, size, flags) \
+ __getrandom (buf, size, flags)
+
#if IS_IN (libc)
hidden_proto (__close_nocancel)
hidden_proto (__close_nocancel_nostatus)
diff --git a/sysdeps/unix/sysv/linux/not-cancel.h b/sysdeps/unix/sysv/linux/not-cancel.h
index f06d57426a40227e..d2bb59acddbcfee0 100644
--- a/sysdeps/unix/sysv/linux/not-cancel.h
+++ b/sysdeps/unix/sysv/linux/not-cancel.h
@@ -68,6 +68,13 @@ __writev_nocancel_nostatus (int fd, const struct iovec *iov, int iovcnt)
INTERNAL_SYSCALL_CALL (writev, fd, iov, iovcnt);
}
+static inline int
+__getrandom_nocancel (void *buf, size_t buflen, unsigned int flags)
+{
+ return INTERNAL_SYSCALL_CALL (getrandom, buf, buflen, flags);
+}
+
+
/* Uncancelable fcntl. */
__typeof (__fcntl) __fcntl64_nocancel;

@ -0,0 +1,35 @@
commit 7187efd0aa270c83c428ea6cd0e1cffc34b41a74
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Aug 1 15:49:07 2022 +0200
malloc: Use __getrandom_nocancel during tcache initiailization
Cancellation currently cannot happen at this point because dlopen
as used by the unwind link always performs additional allocations
for libgcc_s.so.1, even if it has been loaded already as a dependency
of the main executable. But it seems prudent not to rely on this
quirk.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 2edb469d5dbf1203..375f50f5db13e234 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -256,6 +256,7 @@
/* For tcache double-free check. */
#include <random-bits.h>
#include <sys/random.h>
+#include <not-cancel.h>
/*
Debugging:
@@ -3025,7 +3026,7 @@ static uintptr_t tcache_key;
static void
tcache_key_initialize (void)
{
- if (__getrandom (&tcache_key, sizeof(tcache_key), GRND_NONBLOCK)
+ if (__getrandom_nocancel (&tcache_key, sizeof(tcache_key), GRND_NONBLOCK)
!= sizeof (tcache_key))
{
tcache_key = random_bits ();

@ -0,0 +1,94 @@
commit dd2315a866a4ac2b838ea1cb10c5ea1c35d51a2f
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Aug 16 08:27:50 2022 +0200
elf: Run tst-audit-tlsdesc, tst-audit-tlsdesc-dlopen everywhere
The test is valid for all TLS models, but we want to make a reasonable
effort to test the GNU2 model specifically. For example, aarch64
defaults to GNU2, but does not have -mtls-dialect=gnu2, and the test
was not run there.
Suggested-by: Martin Coufal <mcoufal@redhat.com>
Conflicts:
elf/Makefile
(missing tst-align3 test downstream)
diff --git a/elf/Makefile b/elf/Makefile
index ea1512549be3f628..613d244e7781d479 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -361,6 +361,8 @@ tests += \
tst-addr1 \
tst-align \
tst-align2 \
+ tst-audit-tlsdesc \
+ tst-audit-tlsdesc-dlopen \
tst-audit1 \
tst-audit2 \
tst-audit8 \
@@ -679,6 +681,8 @@ modules-names = \
tst-alignmod2 \
tst-array2dep \
tst-array5dep \
+ tst-audit-tlsdesc-mod1 \
+ tst-audit-tlsdesc-mod2 \
tst-audit11mod1 \
tst-audit11mod2 \
tst-audit12mod1 \
@@ -712,6 +716,7 @@ modules-names = \
tst-auditmanymod7 \
tst-auditmanymod8 \
tst-auditmanymod9 \
+ tst-auditmod-tlsdesc \
tst-auditmod1 \
tst-auditmod9a \
tst-auditmod9b \
@@ -889,23 +894,8 @@ modules-names += tst-gnu2-tls1mod
$(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so
tst-gnu2-tls1mod.so-no-z-defs = yes
CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2
+endif # $(have-mtls-dialect-gnu2)
-tests += tst-audit-tlsdesc tst-audit-tlsdesc-dlopen
-modules-names += tst-audit-tlsdesc-mod1 tst-audit-tlsdesc-mod2 tst-auditmod-tlsdesc
-$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \
- $(objpfx)tst-audit-tlsdesc-mod2.so \
- $(shared-thread-library)
-CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=gnu2
-CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=gnu2
-$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library)
-$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \
- $(objpfx)tst-audit-tlsdesc-mod2.so
-$(objpfx)tst-audit-tlsdesc-mod1.so: $(objpfx)tst-audit-tlsdesc-mod2.so
-$(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so
-tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
-$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so
-tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
-endif
ifeq (yes,$(have-protected-data))
modules-names += tst-protected1moda tst-protected1modb
tests += tst-protected1a tst-protected1b
@@ -2656,3 +2646,21 @@ $(objpfx)tst-tls-allocation-failure-static-patched.out: \
grep -q '^Fatal glibc error: Cannot allocate TLS block$$' $@ \
&& grep -q '^status: 127$$' $@; \
$(evaluate-test)
+
+$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \
+ $(objpfx)tst-audit-tlsdesc-mod2.so \
+ $(shared-thread-library)
+ifeq (yes,$(have-mtls-dialect-gnu2))
+# The test is valid for all TLS types, but we want to exercise GNU2
+# TLS if possible.
+CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=gnu2
+CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=gnu2
+endif
+$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library)
+$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \
+ $(objpfx)tst-audit-tlsdesc-mod2.so
+$(objpfx)tst-audit-tlsdesc-mod1.so: $(objpfx)tst-audit-tlsdesc-mod2.so
+$(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so
+tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
+$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so
+tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so

@ -0,0 +1,37 @@
commit 183d99737298bb3200f0610fdcd1c7549c8ed560
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Sep 6 07:38:10 2022 +0200
scripts/dso-ordering-test.py: Generate program run-time dependencies
The main program needs to depend on all shared objects, even objects
that have link-time dependencies among shared objects. Filtering
out shared objects that already have an link-time dependencies is not
necessary here; make will do this automatically.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/scripts/dso-ordering-test.py b/scripts/dso-ordering-test.py
index bde0406be9da14fc..4ffcff6136145ef1 100644
--- a/scripts/dso-ordering-test.py
+++ b/scripts/dso-ordering-test.py
@@ -707,13 +707,12 @@ def process_testcase(t):
"\t$(compile.c) $(OUTPUT_OPTION)\n")
makefile.write (rule)
- not_depended_objs = find_objs_not_depended_on(test_descr)
- if not_depended_objs:
- depstr = ""
- for dep in not_depended_objs:
- depstr += (" $(objpfx)" + test_subdir + "/"
- + test_name + "-" + dep + ".so")
- makefile.write("$(objpfx)%s.out:%s\n" % (base_test_name, depstr))
+ # Ensure that all shared objects are built before running the
+ # test, whether there link-time dependencies or not.
+ depobjs = ["$(objpfx){}/{}-{}.so".format(test_subdir, test_name, dep)
+ for dep in test_descr.objs]
+ makefile.write("$(objpfx){}.out: {}\n".format(
+ base_test_name, " ".join(depobjs)))
# Add main executable to test-srcs
makefile.write("test-srcs += %s/%s\n" % (test_subdir, test_name))

@ -0,0 +1,79 @@
commit dbb75513f5cf9285c77c9e55777c5c35b653f890
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Sep 6 07:38:10 2022 +0200
elf: Rename _dl_sort_maps parameter from skip to force_first
The new implementation will not be able to skip an arbitrary number
of objects.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
index 72f4ff0e6eda3377..7c614bca5d8115c6 100644
--- a/elf/dl-sort-maps.c
+++ b/elf/dl-sort-maps.c
@@ -27,12 +27,12 @@
If FOR_FINI is true, this is called for finishing an object. */
static void
_dl_sort_maps_original (struct link_map **maps, unsigned int nmaps,
- unsigned int skip, bool for_fini)
+ bool force_first, bool for_fini)
{
/* Allows caller to do the common optimization of skipping the first map,
usually the main binary. */
- maps += skip;
- nmaps -= skip;
+ maps += force_first;
+ nmaps -= force_first;
/* A list of one element need not be sorted. */
if (nmaps <= 1)
@@ -182,7 +182,7 @@ dfs_traversal (struct link_map ***rpo, struct link_map *map,
static void
_dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
- unsigned int skip __attribute__ ((unused)), bool for_fini)
+ bool force_first __attribute__ ((unused)), bool for_fini)
{
for (int i = nmaps - 1; i >= 0; i--)
maps[i]->l_visited = 0;
@@ -286,7 +286,7 @@ _dl_sort_maps_init (void)
void
_dl_sort_maps (struct link_map **maps, unsigned int nmaps,
- unsigned int skip, bool for_fini)
+ bool force_first, bool for_fini)
{
/* It can be tempting to use a static function pointer to store and call
the current selected sorting algorithm routine, but experimentation
@@ -296,9 +296,9 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps,
input cases. A simple if-case with direct function calls appears to
be the fastest. */
if (__glibc_likely (GLRO(dl_dso_sort_algo) == dso_sort_algorithm_original))
- _dl_sort_maps_original (maps, nmaps, skip, for_fini);
+ _dl_sort_maps_original (maps, nmaps, force_first, for_fini);
else
- _dl_sort_maps_dfs (maps, nmaps, skip, for_fini);
+ _dl_sort_maps_dfs (maps, nmaps, force_first, for_fini);
}
#endif /* HAVE_TUNABLES. */
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 87ad2f3f4d89eb7d..8c0fe98f69a88f1e 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1106,9 +1106,11 @@ extern void _dl_init (struct link_map *main_map, int argc, char **argv,
initializer functions have completed. */
extern void _dl_fini (void) attribute_hidden;
-/* Sort array MAPS according to dependencies of the contained objects. */
+/* Sort array MAPS according to dependencies of the contained objects.
+ If FORCE_FIRST, MAPS[0] keeps its place even if the dependencies
+ say otherwise. */
extern void _dl_sort_maps (struct link_map **maps, unsigned int nmaps,
- unsigned int skip, bool for_fini) attribute_hidden;
+ bool force_first, bool for_fini) attribute_hidden;
/* The dynamic linker calls this function before and having changing
any shared object mappings. The `r_state' member of `struct r_debug'

@ -0,0 +1,90 @@
commit 1df71d32fe5f5905ffd5d100e5e9ca8ad6210891
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Sep 20 11:00:42 2022 +0200
elf: Implement force_first handling in _dl_sort_maps_dfs (bug 28937)
The implementation in _dl_close_worker requires that the first
element of l_initfini is always this very map (“We are always the
zeroth entry, and since we don't include ourselves in the
dependency analysis start at 1.”). Rather than fixing that
assumption, this commit adds an implementation of the force_first
argument to the new dependency sorting algorithm. This also means
that the directly dlopen'ed shared object is always initialized last,
which is the least surprising behavior in the presence of cycles.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
index 7c614bca5d8115c6..e8ef5e8b3588ab53 100644
--- a/elf/dl-sort-maps.c
+++ b/elf/dl-sort-maps.c
@@ -182,8 +182,9 @@ dfs_traversal (struct link_map ***rpo, struct link_map *map,
static void
_dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
- bool force_first __attribute__ ((unused)), bool for_fini)
+ bool force_first, bool for_fini)
{
+ struct link_map *first_map = maps[0];
for (int i = nmaps - 1; i >= 0; i--)
maps[i]->l_visited = 0;
@@ -208,14 +209,6 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
Adjusting the order so that maps[0] is last traversed naturally avoids
this problem.
- Further, the old "optimization" of skipping the main object at maps[0]
- from the call-site (i.e. _dl_sort_maps(maps+1,nmaps-1)) is in general
- no longer valid, since traversing along object dependency-links
- may "find" the main object even when it is not included in the initial
- order (e.g. a dlopen()'ed shared object can have circular dependencies
- linked back to itself). In such a case, traversing N-1 objects will
- create a N-object result, and raise problems.
-
To summarize, just passing in the full list, and iterating from back
to front makes things much more straightforward. */
@@ -274,6 +267,27 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
}
memcpy (maps, rpo, sizeof (struct link_map *) * nmaps);
+
+ /* Skipping the first object at maps[0] is not valid in general,
+ since traversing along object dependency-links may "find" that
+ first object even when it is not included in the initial order
+ (e.g., a dlopen'ed shared object can have circular dependencies
+ linked back to itself). In such a case, traversing N-1 objects
+ will create a N-object result, and raise problems. Instead,
+ force the object back into first place after sorting. This naive
+ approach may introduce further dependency ordering violations
+ compared to rotating the cycle until the first map is again in
+ the first position, but as there is a cycle, at least one
+ violation is already present. */
+ if (force_first && maps[0] != first_map)
+ {
+ int i;
+ for (i = 0; maps[i] != first_map; ++i)
+ ;
+ assert (i < nmaps);
+ memmove (&maps[1], maps, i * sizeof (maps[0]));
+ maps[0] = first_map;
+ }
}
void
diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def
index 5f7f18ef270bc12d..4bf9052db16fb352 100644
--- a/elf/dso-sort-tests-1.def
+++ b/elf/dso-sort-tests-1.def
@@ -64,3 +64,10 @@ output: b>a>{}<a<b
tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};a->b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c
output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];}
output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<g<f<a<b<c<d<e];}
+
+# Test that even in the presence of dependency loops involving dlopen'ed
+# object, that object is initialized last (and not unloaded prematurely).
+# Final destructor order is indeterminate due to the cycle.
+tst-bz28937: {+a;+b;-b;+c;%c};a->a1;a->a2;a2->a;b->b1;c->a1;c=>a1
+output(glibc.rtld.dynamic_sort=1): {+a[a2>a1>a>];+b[b1>b>];-b[<b<b1];+c[c>];%c(a1());}<a<a2<c<a1
+output(glibc.rtld.dynamic_sort=2): {+a[a2>a1>a>];+b[b1>b>];-b[<b<b1];+c[c>];%c(a1());}<a2<a<c<a1

@ -0,0 +1,589 @@
commit 1d495912a746e2a1ffb780c9a81fd234ec2464e8
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Aug 30 10:02:49 2022 +0200
nss_dns: Rewrite _nss_dns_gethostbyname4_r using current interfaces
Introduce struct alloc_buffer to this function, and use it and
struct ns_rr_cursor in gaih_getanswer_slice. Adjust gaih_getanswer
and gaih_getanswer_noaaaa accordingly.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 1cb3be71f04d98eb..36789965c06757d0 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -101,13 +101,6 @@
#endif
#define MAXHOSTNAMELEN 256
-/* We need this time later. */
-typedef union querybuf
-{
- HEADER hdr;
- u_char buf[MAXPACKET];
-} querybuf;
-
/* For historic reasons, pointers to IP addresses are char *, so use a
single list type for addresses and host names. */
#define DYNARRAY_STRUCT ptrlist
@@ -126,18 +119,18 @@ static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen,
char **hnamep, int *errnop,
int *h_errnop, int32_t *ttlp);
-static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1,
- const querybuf *answer2, int anslen2,
- const char *qname,
+static enum nss_status gaih_getanswer (unsigned char *packet1,
+ size_t packet1len,
+ unsigned char *packet2,
+ size_t packet2len,
+ struct alloc_buffer *abuf,
struct gaih_addrtuple **pat,
- char *buffer, size_t buflen,
int *errnop, int *h_errnop,
int32_t *ttlp);
-static enum nss_status gaih_getanswer_noaaaa (const querybuf *answer1,
- int anslen1,
- const char *qname,
+static enum nss_status gaih_getanswer_noaaaa (unsigned char *packet,
+ size_t packetlen,
+ struct alloc_buffer *abuf,
struct gaih_addrtuple **pat,
- char *buffer, size_t buflen,
int *errnop, int *h_errnop,
int32_t *ttlp);
@@ -409,17 +402,13 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
name = cp;
}
- union
- {
- querybuf *buf;
- u_char *ptr;
- } host_buffer;
- querybuf *orig_host_buffer;
- host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048);
+ unsigned char dns_packet_buffer[2048];
+ unsigned char *alt_dns_packet_buffer = dns_packet_buffer;
u_char *ans2p = NULL;
int nans2p = 0;
int resplen2 = 0;
int ans2p_malloced = 0;
+ struct alloc_buffer abuf = alloc_buffer_create (buffer, buflen);
int olderr = errno;
@@ -428,22 +417,21 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
if ((ctx->resp->options & RES_NOAAAA) == 0)
{
n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
- host_buffer.buf->buf, 2048, &host_buffer.ptr,
- &ans2p, &nans2p, &resplen2, &ans2p_malloced);
+ dns_packet_buffer, sizeof (dns_packet_buffer),
+ &alt_dns_packet_buffer, &ans2p, &nans2p,
+ &resplen2, &ans2p_malloced);
if (n >= 0)
- status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
- resplen2, name, pat, buffer, buflen,
- errnop, herrnop, ttlp);
+ status = gaih_getanswer (alt_dns_packet_buffer, n, ans2p, resplen2,
+ &abuf, pat, errnop, herrnop, ttlp);
}
else
{
n = __res_context_search (ctx, name, C_IN, T_A,
- host_buffer.buf->buf, 2048, NULL,
- NULL, NULL, NULL, NULL);
+ dns_packet_buffer, sizeof (dns_packet_buffer),
+ NULL, NULL, NULL, NULL, NULL);
if (n >= 0)
- status = gaih_getanswer_noaaaa (host_buffer.buf, n,
- name, pat, buffer, buflen,
- errnop, herrnop, ttlp);
+ status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n,
+ &abuf, pat, errnop, herrnop, ttlp);
}
if (n < 0)
{
@@ -474,12 +462,20 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
__set_errno (olderr);
}
+ /* Implement the buffer resizing protocol. */
+ if (alloc_buffer_has_failed (&abuf))
+ {
+ *errnop = ERANGE;
+ *herrnop = NETDB_INTERNAL;
+ status = NSS_STATUS_TRYAGAIN;
+ }
+
/* Check whether ans2p was separately allocated. */
if (ans2p_malloced)
free (ans2p);
- if (host_buffer.buf != orig_host_buffer)
- free (host_buffer.buf);
+ if (alt_dns_packet_buffer != dns_packet_buffer)
+ free (alt_dns_packet_buffer);
__resolv_context_put (ctx);
return status;
@@ -893,259 +889,152 @@ getanswer_ptr (unsigned char *packet, size_t packetlen,
return NSS_STATUS_TRYAGAIN;
}
+/* Parses DNS data found in PACKETLEN bytes at PACKET in struct
+ gaih_addrtuple address tuples. The new address tuples are linked
+ from **TAILP, with backing store allocated from ABUF, and *TAILP is
+ updated to point where the next tuple pointer should be stored. If
+ TTLP is not null, *TTLP is updated to reflect the minimum TTL. If
+ STORE_CANON is true, the canonical name is stored as part of the
+ first address tuple being written. */
static enum nss_status
-gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
- struct gaih_addrtuple ***patp,
- char **bufferp, size_t *buflenp,
- int *errnop, int *h_errnop, int32_t *ttlp, int *firstp)
+gaih_getanswer_slice (unsigned char *packet, size_t packetlen,
+ struct alloc_buffer *abuf,
+ struct gaih_addrtuple ***tailp,
+ int *errnop, int *h_errnop, int32_t *ttlp,
+ bool store_canon)
{
- char *buffer = *bufferp;
- size_t buflen = *buflenp;
-
- struct gaih_addrtuple **pat = *patp;
- const HEADER *hp = &answer->hdr;
- int ancount = ntohs (hp->ancount);
- int qdcount = ntohs (hp->qdcount);
- const u_char *cp = answer->buf + HFIXEDSZ;
- const u_char *end_of_message = answer->buf + anslen;
- if (__glibc_unlikely (qdcount != 1))
- {
- *h_errnop = NO_RECOVERY;
- return NSS_STATUS_UNAVAIL;
- }
-
- u_char packtmp[NS_MAXCDNAME];
- int n = __ns_name_unpack (answer->buf, end_of_message, cp,
- packtmp, sizeof packtmp);
- /* We unpack the name to check it for validity. But we do not need
- it later. */
- if (n != -1 && __ns_name_ntop (packtmp, buffer, buflen) == -1)
- {
- if (__glibc_unlikely (errno == EMSGSIZE))
- {
- too_small:
- *errnop = ERANGE;
- *h_errnop = NETDB_INTERNAL;
- return NSS_STATUS_TRYAGAIN;
- }
-
- n = -1;
- }
-
- if (__glibc_unlikely (n < 0))
- {
- *errnop = errno;
- *h_errnop = NO_RECOVERY;
- return NSS_STATUS_UNAVAIL;
- }
- if (__glibc_unlikely (__libc_res_hnok (buffer) == 0))
+ struct ns_rr_cursor c;
+ if (!__ns_rr_cursor_init (&c, packet, packetlen))
{
- errno = EBADMSG;
- *errnop = EBADMSG;
+ /* This should not happen because __res_context_query already
+ perfroms response validation. */
*h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
}
- cp += n + QFIXEDSZ;
+ bool haveanswer = false; /* Set to true if at least one address. */
+ uint16_t qtype = ns_rr_cursor_qtype (&c);
+ int ancount = ns_rr_cursor_ancount (&c);
+ const unsigned char *expected_name = ns_rr_cursor_qname (&c);
+ /* expected_name may be updated to point into this buffer. */
+ unsigned char name_buffer[NS_MAXCDNAME];
- int haveanswer = 0;
- int had_error = 0;
- char *canon = NULL;
- char *h_name = NULL;
- int h_namelen = 0;
+ /* This is a pointer to a possibly-compressed name in the packet.
+ Eventually it is equivalent to the canonical name. If needed, it
+ is uncompressed and translated to text form when the first
+ address tuple is encountered. */
+ const unsigned char *compressed_alias_name = expected_name;
- if (ancount == 0)
+ if (ancount == 0 || !__res_binary_hnok (compressed_alias_name))
{
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;
}
- while (ancount-- > 0 && cp < end_of_message && had_error == 0)
+ for (; ancount > -0; --ancount)
{
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
- packtmp, sizeof packtmp);
- if (n != -1 &&
- (h_namelen = __ns_name_ntop (packtmp, buffer, buflen)) == -1)
- {
- if (__glibc_unlikely (errno == EMSGSIZE))
- goto too_small;
-
- n = -1;
- }
- if (__glibc_unlikely (n < 0))
- {
- ++had_error;
- continue;
- }
- if (*firstp && canon == NULL && __libc_res_hnok (buffer))
- {
- h_name = buffer;
- buffer += h_namelen;
- buflen -= h_namelen;
- }
-
- cp += n; /* name */
-
- if (__glibc_unlikely (cp + 10 > end_of_message))
- {
- ++had_error;
- continue;
- }
-
- uint16_t type;
- NS_GET16 (type, cp);
- uint16_t class;
- NS_GET16 (class, cp);
- int32_t ttl;
- NS_GET32 (ttl, cp);
- NS_GET16 (n, cp); /* RDATA length. */
-
- if (end_of_message - cp < n)
+ struct ns_rr_wire rr;
+ if (!__ns_rr_cursor_next (&c, &rr))
{
- /* RDATA extends beyond the end of the packet. */
- ++had_error;
- continue;
+ *h_errnop = NO_RECOVERY;
+ return NSS_STATUS_UNAVAIL;
}
- if (class != C_IN)
- {
- cp += n;
- continue;
- }
+ /* Update TTL for known record types. */
+ if ((rr.rtype == T_CNAME || rr.rtype == qtype)
+ && ttlp != NULL && *ttlp > rr.ttl)
+ *ttlp = rr.ttl;
- if (type == T_CNAME)
+ if (rr.rtype == T_CNAME)
{
- char tbuf[MAXDNAME];
-
- /* A CNAME could also have a TTL entry. */
- if (ttlp != NULL && ttl < *ttlp)
- *ttlp = ttl;
-
- n = __libc_dn_expand (answer->buf, end_of_message, cp,
- tbuf, sizeof tbuf);
- if (__glibc_unlikely (n < 0))
- {
- ++had_error;
- continue;
- }
- cp += n;
-
- if (*firstp && __libc_res_hnok (tbuf))
+ /* NB: No check for owner name match, based on historic
+ precedent. Record the CNAME target as the new expected
+ name. */
+ int n = __ns_name_unpack (c.begin, c.end, rr.rdata,
+ name_buffer, sizeof (name_buffer));
+ if (n < 0)
{
- /* Reclaim buffer space. */
- if (h_name + h_namelen == buffer)
- {
- buffer = h_name;
- buflen += h_namelen;
- }
-
- n = strlen (tbuf) + 1;
- if (__glibc_unlikely (n > buflen))
- goto too_small;
- if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
- {
- ++had_error;
- continue;
- }
-
- canon = buffer;
- buffer = __mempcpy (buffer, tbuf, n);
- buflen -= n;
- h_namelen = 0;
+ *h_errnop = NO_RECOVERY;
+ return NSS_STATUS_UNAVAIL;
}
- continue;
+ expected_name = name_buffer;
+ if (store_canon && __res_binary_hnok (name_buffer))
+ /* This name can be used as a canonical name. Do not
+ translate to text form here to conserve buffer space.
+ Point to the compressed name because name_buffer can be
+ overwritten with an unusable name later. */
+ compressed_alias_name = rr.rdata;
}
-
- /* Stop parsing if we encounter a record with incorrect RDATA
- length. */
- if (type == T_A || type == T_AAAA)
+ else if (rr.rtype == qtype
+ && __ns_samebinaryname (rr.rname, expected_name)
+ && rr.rdlength == rrtype_to_rdata_length (qtype))
{
- if (n != rrtype_to_rdata_length (type))
+ struct gaih_addrtuple *ntup
+ = alloc_buffer_alloc (abuf, struct gaih_addrtuple);
+ /* Delay error reporting to the callers (they implement the
+ ERANGE buffer resizing handshake). */
+ if (ntup != NULL)
{
- ++had_error;
- continue;
+ ntup->next = NULL;
+ if (store_canon && compressed_alias_name != NULL)
+ {
+ /* This assumes that all the CNAME records come
+ first. Use MAXHOSTNAMELEN instead of
+ NS_MAXCDNAME for additional length checking.
+ However, these checks are not expected to fail
+ because all size NS_MAXCDNAME names should into
+ the hname buffer because no escaping is
+ needed. */
+ char unsigned nbuf[NS_MAXCDNAME];
+ char hname[MAXHOSTNAMELEN + 1];
+ if (__ns_name_unpack (c.begin, c.end,
+ compressed_alias_name,
+ nbuf, sizeof (nbuf)) >= 0
+ && __ns_name_ntop (nbuf, hname, sizeof (hname)) >= 0)
+ /* Space checking is performed by the callers. */
+ ntup->name = alloc_buffer_copy_string (abuf, hname);
+ store_canon = false;
+ }
+ else
+ ntup->name = NULL;
+ if (rr.rdlength == 4)
+ ntup->family = AF_INET;
+ else
+ ntup->family = AF_INET6;
+ memcpy (ntup->addr, rr.rdata, rr.rdlength);
+ ntup->scopeid = 0;
+
+ /* Link in the new tuple, and update the tail pointer to
+ point to its next field. */
+ **tailp = ntup;
+ *tailp = &ntup->next;
+
+ haveanswer = true;
}
}
- else
- {
- /* Skip unknown records. */
- cp += n;
- continue;
- }
-
- assert (type == T_A || type == T_AAAA);
- if (*pat == NULL)
- {
- uintptr_t pad = (-(uintptr_t) buffer
- % __alignof__ (struct gaih_addrtuple));
- buffer += pad;
- buflen = buflen > pad ? buflen - pad : 0;
-
- if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple)))
- goto too_small;
-
- *pat = (struct gaih_addrtuple *) buffer;
- buffer += sizeof (struct gaih_addrtuple);
- buflen -= sizeof (struct gaih_addrtuple);
- }
-
- (*pat)->name = NULL;
- (*pat)->next = NULL;
-
- if (*firstp)
- {
- /* We compose a single hostent out of the entire chain of
- entries, so the TTL of the hostent is essentially the lowest
- TTL in the chain. */
- if (ttlp != NULL && ttl < *ttlp)
- *ttlp = ttl;
-
- (*pat)->name = canon ?: h_name;
-
- *firstp = 0;
- }
-
- (*pat)->family = type == T_A ? AF_INET : AF_INET6;
- memcpy ((*pat)->addr, cp, n);
- cp += n;
- (*pat)->scopeid = 0;
-
- pat = &((*pat)->next);
-
- haveanswer = 1;
}
if (haveanswer)
{
- *patp = pat;
- *bufferp = buffer;
- *buflenp = buflen;
-
*h_errnop = NETDB_SUCCESS;
return NSS_STATUS_SUCCESS;
}
-
- /* Special case here: if the resolver sent a result but it only
- contains a CNAME while we are looking for a T_A or T_AAAA record,
- we fail with NOTFOUND instead of TRYAGAIN. */
- if (canon != NULL)
+ else
{
+ /* Special case here: if the resolver sent a result but it only
+ contains a CNAME while we are looking for a T_A or T_AAAA
+ record, we fail with NOTFOUND. */
*h_errnop = HOST_NOT_FOUND;
return NSS_STATUS_NOTFOUND;
}
-
- *h_errnop = NETDB_INTERNAL;
- return NSS_STATUS_TRYAGAIN;
}
static enum nss_status
-gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
- int anslen2, const char *qname,
- struct gaih_addrtuple **pat, char *buffer, size_t buflen,
+gaih_getanswer (unsigned char *packet1, size_t packet1len,
+ unsigned char *packet2, size_t packet2len,
+ struct alloc_buffer *abuf, struct gaih_addrtuple **pat,
int *errnop, int *h_errnop, int32_t *ttlp)
{
- int first = 1;
-
enum nss_status status = NSS_STATUS_NOTFOUND;
/* Combining the NSS status of two distinct queries requires some
@@ -1157,7 +1046,10 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
A recoverable TRYAGAIN is almost always due to buffer size issues
and returns ERANGE in errno and the caller is expected to retry
- with a larger buffer.
+ with a larger buffer. (The caller, _nss_dns_gethostbyname4_r,
+ ignores the return status if it detects that the result buffer
+ has been exhausted and generates a TRYAGAIN failure with an
+ ERANGE code.)
Lastly, you may be tempted to make significant changes to the
conditions in this code to bring about symmetry between responses.
@@ -1237,36 +1129,30 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
is a recoverable error we now return TRYAGIN even if the first
response was SUCCESS. */
- if (anslen1 > 0)
- status = gaih_getanswer_slice(answer1, anslen1, qname,
- &pat, &buffer, &buflen,
- errnop, h_errnop, ttlp,
- &first);
-
- if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
- || (status == NSS_STATUS_TRYAGAIN
- /* We want to look at the second answer in case of an
- NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
- *h_errnop is NO_RECOVERY. If not, and if the failure was due to
- an insufficient buffer (ERANGE), then we need to drop the results
- and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
- repeat the query with a larger buffer. */
- && (*errnop != ERANGE || *h_errnop == NO_RECOVERY)))
- && answer2 != NULL && anslen2 > 0)
+ if (packet1len > 0)
{
- enum nss_status status2 = gaih_getanswer_slice(answer2, anslen2, qname,
- &pat, &buffer, &buflen,
- errnop, h_errnop, ttlp,
- &first);
+ status = gaih_getanswer_slice (packet1, packet1len,
+ abuf, &pat, errnop, h_errnop, ttlp, true);
+ if (alloc_buffer_has_failed (abuf))
+ /* Do not try parsing the second packet if a larger result
+ buffer is needed. The caller implements the resizing
+ protocol because *abuf has been exhausted. */
+ return NSS_STATUS_TRYAGAIN; /* Ignored by the caller. */
+ }
+
+ if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND)
+ && packet2 != NULL && packet2len > 0)
+ {
+ enum nss_status status2
+ = gaih_getanswer_slice (packet2, packet2len,
+ abuf, &pat, errnop, h_errnop, ttlp,
+ /* Success means that data with a
+ canonical name has already been
+ stored. Do not store the name again. */
+ status != NSS_STATUS_SUCCESS);
/* Use the second response status in some cases. */
if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
status = status2;
- /* Do not return a truncated second response (unless it was
- unavoidable e.g. unrecoverable TRYAGAIN). */
- if (status == NSS_STATUS_SUCCESS
- && (status2 == NSS_STATUS_TRYAGAIN
- && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
- status = NSS_STATUS_TRYAGAIN;
}
return status;
@@ -1274,18 +1160,13 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
/* Variant of gaih_getanswer without a second (AAAA) response. */
static enum nss_status
-gaih_getanswer_noaaaa (const querybuf *answer1, int anslen1, const char *qname,
- struct gaih_addrtuple **pat,
- char *buffer, size_t buflen,
+gaih_getanswer_noaaaa (unsigned char *packet, size_t packetlen,
+ struct alloc_buffer *abuf, struct gaih_addrtuple **pat,
int *errnop, int *h_errnop, int32_t *ttlp)
{
- int first = 1;
-
enum nss_status status = NSS_STATUS_NOTFOUND;
- if (anslen1 > 0)
- status = gaih_getanswer_slice (answer1, anslen1, qname,
- &pat, &buffer, &buflen,
- errnop, h_errnop, ttlp,
- &first);
+ if (packetlen > 0)
+ status = gaih_getanswer_slice (packet, packetlen,
+ abuf, &pat, errnop, h_errnop, ttlp, true);
return status;
}

@ -0,0 +1,19 @@
commit b8c6166b1b75036ab3e4127a1c0aacf52ca93651
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Sep 6 19:43:37 2021 +0200
locale: Add missing second argument to _Static_assert in C-collate-seq.c
diff --git a/locale/C-collate-seq.c b/locale/C-collate-seq.c
index 4fb82cb8357936b6..40b17f4f90313144 100644
--- a/locale/C-collate-seq.c
+++ b/locale/C-collate-seq.c
@@ -55,7 +55,7 @@ static const char collseqmb[] =
/* This table must be 256 bytes in size. We index bytes into the
table to find the collation sequence. */
-_Static_assert (sizeof (collseqmb) == 256);
+_Static_assert (sizeof (collseqmb) == 256, "sizeof (collseqmb)");
static const uint32_t collseqwc[] =
{

@ -0,0 +1,306 @@
Maintain an explicit order of tunables, so that the tunable_list
array and the tunable_id_t constant can remain consistent over time.
Related to this upstream bug:
Internal tunables ABI depends on awk array iteration order
<https://sourceware.org/bugzilla/show_bug.cgi?id=30027>
The new dl-tunables.list files are already on the sysdeps search
path, which is why the existing Makeconfig rule picks them up.
The files for RHEL 9.1z were created by applying the gen-tunables.awk
part of this patch to RHEL 9.1.0 (glibc-2.34-40.el9_2.1, to be
precise). The sysdeps/unix/sysv/linux/**/dl-tunables.list files were
created based on the generated error message during the RHEL 9.1.z
build.
Going forward, new tunables will have to be added manually to the end
of those files. Existing tunables should not be deleted. For
deletion, the script would have to be extended to be able to create
gaps in the tunable_list array.
diff --git a/scripts/gen-tunables.awk b/scripts/gen-tunables.awk
index fa63e86d1a51fe61..c5445e95f9fc36e7 100644
--- a/scripts/gen-tunables.awk
+++ b/scripts/gen-tunables.awk
@@ -14,6 +14,7 @@ BEGIN {
top_ns=""
max_name_len=0
max_alias_len=0
+ tunable_order_count = 0
}
# Skip over blank lines and comments.
@@ -83,6 +84,37 @@ $1 == "}" {
next
}
+$1 == "@order" {
+ if (top_ns != "") {
+ printf("%s:%d: error: invalid @order directive inside namespace %s\n",
+ FILENAME, FNR, top_ns) > "/dev/stderr"
+ exit 1
+ }
+ if (NF != 2) {
+ printf("%s:%d: error: invalid argument count in @order directive\n",
+ FILENAME, FNR) > "/dev/stderr"
+ exit 1
+ }
+ order_arg = $2
+ if (split(order_arg, indices, /\./) != 3) {
+ printf("%s:%d: error: invalid tunable syntax in @order directive\n",
+ FILENAME, FNR) > "/dev/stderr"
+ exit 1
+ }
+ t = indices[1]
+ n = indices[2]
+ m = indices[3]
+ if ((t, n, m) in tunable_order) {
+ printf("%s:%d: error: duplicate\"@order %s\"\n" \
+ FILENAME, FNR, order_arg) > "/dev/stderr"
+ exit 1
+ }
+ ++tunable_order_count
+ tunable_order[t,n,m] = tunable_order_count
+ tunable_order_list[tunable_order_count] = t SUBSEP n SUBSEP m
+ next
+}
+
# Everything else, which could either be a tunable without any attributes or a
# tunable attribute.
{
@@ -145,6 +177,31 @@ END {
exit 1
}
+ missing_order = 0
+ for (tnm in types) {
+ if (!(tnm in tunable_order)) {
+ if (!missing_order) {
+ print "error: Missing @order directives:" > "/dev/stderr"
+ missing_order = 1
+ }
+ split(tnm, indices, SUBSEP)
+ printf("@order %s.%s.%s\n", indices[1], indices[2], indices[3]) \
+ > "/dev/stderr"
+ }
+ }
+ for (i = 1; i <= tunable_order_count; ++i) {
+ tnm = tunable_order_list[i]
+ if (!(tnm in types)) {
+ split(tnm, indices, SUBSEP)
+ printf("error: tunable in \"@order %s.%s.%s\" not known\n", \
+ indices[1], indices[2], indices[3]) > "/dev/stderr"
+ missing_order = 1
+ }
+ }
+ if (missing_order) {
+ exit 1
+ }
+
print "/* AUTOGENERATED by gen-tunables.awk. */"
print "#ifndef _TUNABLES_H_"
print "# error \"Do not include this file directly.\""
@@ -155,7 +212,8 @@ END {
# Now, the enum names
print "\ntypedef enum"
print "{"
- for (tnm in types) {
+ for (i = 1; i <= tunable_order_count; ++i) {
+ tnm = tunable_order_list[i]
split (tnm, indices, SUBSEP);
t = indices[1];
n = indices[2];
@@ -171,7 +229,8 @@ END {
print "# include \"dl-tunable-types.h\""
# Finally, the tunable list.
print "static tunable_t tunable_list[] attribute_relro = {"
- for (tnm in types) {
+ for (i = 1; i <= tunable_order_count; ++i) {
+ tnm = tunable_order_list[i]
split (tnm, indices, SUBSEP);
t = indices[1];
n = indices[2];
diff --git a/sysdeps/unix/sysv/linux/aarch64/dl-tunables.list b/sysdeps/unix/sysv/linux/aarch64/dl-tunables.list
new file mode 100644
index 0000000000000000..d9d62499be4d67cb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/aarch64/dl-tunables.list
@@ -0,0 +1,28 @@
+# Order of tunables in RHEL 9.1.z.
+@order glibc.rtld.nns
+@order glibc.elision.skip_lock_after_retries
+@order glibc.malloc.trim_threshold
+@order glibc.malloc.perturb
+@order glibc.pthread.rseq
+@order glibc.cpu.name
+@order glibc.mem.tagging
+@order glibc.elision.tries
+@order glibc.elision.enable
+@order glibc.malloc.mxfast
+@order glibc.rtld.dynamic_sort
+@order glibc.elision.skip_lock_busy
+@order glibc.malloc.top_pad
+@order glibc.pthread.stack_cache_size
+@order glibc.cpu.hwcap_mask
+@order glibc.malloc.mmap_max
+@order glibc.elision.skip_trylock_internal_abort
+@order glibc.malloc.tcache_unsorted_limit
+@order glibc.elision.skip_lock_internal_abort
+@order glibc.malloc.arena_max
+@order glibc.malloc.mmap_threshold
+@order glibc.malloc.tcache_count
+@order glibc.malloc.arena_test
+@order glibc.pthread.mutex_spin_count
+@order glibc.rtld.optional_static_tls
+@order glibc.malloc.tcache_max
+@order glibc.malloc.check
diff --git a/sysdeps/unix/sysv/linux/i386/dl-tunables.list b/sysdeps/unix/sysv/linux/i386/dl-tunables.list
new file mode 100644
index 0000000000000000..e83962ec3af11691
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/dl-tunables.list
@@ -0,0 +1,35 @@
+# Order of tunables in RHEL 9.1.z.
+@order glibc.rtld.nns
+@order glibc.elision.skip_lock_after_retries
+@order glibc.malloc.trim_threshold
+@order glibc.malloc.perturb
+@order glibc.cpu.x86_shared_cache_size
+@order glibc.pthread.rseq
+@order glibc.mem.tagging
+@order glibc.elision.tries
+@order glibc.elision.enable
+@order glibc.cpu.x86_rep_movsb_threshold
+@order glibc.malloc.mxfast
+@order glibc.rtld.dynamic_sort
+@order glibc.elision.skip_lock_busy
+@order glibc.malloc.top_pad
+@order glibc.cpu.x86_rep_stosb_threshold
+@order glibc.cpu.x86_non_temporal_threshold
+@order glibc.cpu.x86_shstk
+@order glibc.pthread.stack_cache_size
+@order glibc.cpu.hwcap_mask
+@order glibc.malloc.mmap_max
+@order glibc.elision.skip_trylock_internal_abort
+@order glibc.malloc.tcache_unsorted_limit
+@order glibc.cpu.x86_ibt
+@order glibc.cpu.hwcaps
+@order glibc.elision.skip_lock_internal_abort
+@order glibc.malloc.arena_max
+@order glibc.malloc.mmap_threshold
+@order glibc.cpu.x86_data_cache_size
+@order glibc.malloc.tcache_count
+@order glibc.malloc.arena_test
+@order glibc.pthread.mutex_spin_count
+@order glibc.rtld.optional_static_tls
+@order glibc.malloc.tcache_max
+@order glibc.malloc.check
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list
new file mode 100644
index 0000000000000000..8f01840ef57874e7
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list
@@ -0,0 +1,28 @@
+# Order of tunables in RHEL 9.1.z.
+@order glibc.rtld.nns
+@order glibc.elision.skip_lock_after_retries
+@order glibc.malloc.trim_threshold
+@order glibc.malloc.perturb
+@order glibc.pthread.rseq
+@order glibc.mem.tagging
+@order glibc.elision.tries
+@order glibc.elision.enable
+@order glibc.malloc.mxfast
+@order glibc.rtld.dynamic_sort
+@order glibc.elision.skip_lock_busy
+@order glibc.malloc.top_pad
+@order glibc.pthread.stack_cache_size
+@order glibc.cpu.hwcap_mask
+@order glibc.malloc.mmap_max
+@order glibc.elision.skip_trylock_internal_abort
+@order glibc.malloc.tcache_unsorted_limit
+@order glibc.elision.skip_lock_internal_abort
+@order glibc.malloc.arena_max
+@order glibc.malloc.mmap_threshold
+@order glibc.cpu.cached_memopt
+@order glibc.malloc.tcache_count
+@order glibc.malloc.arena_test
+@order glibc.pthread.mutex_spin_count
+@order glibc.rtld.optional_static_tls
+@order glibc.malloc.tcache_max
+@order glibc.malloc.check
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list b/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list
new file mode 100644
index 0000000000000000..c3bc83f33910af22
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list
@@ -0,0 +1,27 @@
+# Order of tunables in RHEL 9.1.z.
+@order glibc.rtld.nns
+@order glibc.elision.skip_lock_after_retries
+@order glibc.malloc.trim_threshold
+@order glibc.malloc.perturb
+@order glibc.pthread.rseq
+@order glibc.mem.tagging
+@order glibc.elision.tries
+@order glibc.elision.enable
+@order glibc.malloc.mxfast
+@order glibc.rtld.dynamic_sort
+@order glibc.elision.skip_lock_busy
+@order glibc.malloc.top_pad
+@order glibc.pthread.stack_cache_size
+@order glibc.cpu.hwcap_mask
+@order glibc.malloc.mmap_max
+@order glibc.elision.skip_trylock_internal_abort
+@order glibc.malloc.tcache_unsorted_limit
+@order glibc.elision.skip_lock_internal_abort
+@order glibc.malloc.arena_max
+@order glibc.malloc.mmap_threshold
+@order glibc.malloc.tcache_count
+@order glibc.malloc.arena_test
+@order glibc.pthread.mutex_spin_count
+@order glibc.rtld.optional_static_tls
+@order glibc.malloc.tcache_max
+@order glibc.malloc.check
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list
new file mode 100644
index 0000000000000000..e83962ec3af11691
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list
@@ -0,0 +1,35 @@
+# Order of tunables in RHEL 9.1.z.
+@order glibc.rtld.nns
+@order glibc.elision.skip_lock_after_retries
+@order glibc.malloc.trim_threshold
+@order glibc.malloc.perturb
+@order glibc.cpu.x86_shared_cache_size
+@order glibc.pthread.rseq
+@order glibc.mem.tagging
+@order glibc.elision.tries
+@order glibc.elision.enable
+@order glibc.cpu.x86_rep_movsb_threshold
+@order glibc.malloc.mxfast
+@order glibc.rtld.dynamic_sort
+@order glibc.elision.skip_lock_busy
+@order glibc.malloc.top_pad
+@order glibc.cpu.x86_rep_stosb_threshold
+@order glibc.cpu.x86_non_temporal_threshold
+@order glibc.cpu.x86_shstk
+@order glibc.pthread.stack_cache_size
+@order glibc.cpu.hwcap_mask
+@order glibc.malloc.mmap_max
+@order glibc.elision.skip_trylock_internal_abort
+@order glibc.malloc.tcache_unsorted_limit
+@order glibc.cpu.x86_ibt
+@order glibc.cpu.hwcaps
+@order glibc.elision.skip_lock_internal_abort
+@order glibc.malloc.arena_max
+@order glibc.malloc.mmap_threshold
+@order glibc.cpu.x86_data_cache_size
+@order glibc.malloc.tcache_count
+@order glibc.malloc.arena_test
+@order glibc.pthread.mutex_spin_count
+@order glibc.rtld.optional_static_tls
+@order glibc.malloc.tcache_max
+@order glibc.malloc.check

@ -0,0 +1,37 @@
Short description: Fix newlocale error return.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Bug-RHEL: #832516
Bug-Fedora: #827510
Bug-Upstream: #14247
Upstream status: not-submitted
This needs to go upstream right away to fix the error case for
newlocale not correctly returning an error.
2012-06-14 Jeff Law <law@redhat.com>
* locale/loadlocale.c (_nl_load_locale): Delay setting
file->decided until we have successfully loaded the file's
data.
diff --git a/locale/loadlocale.c b/locale/loadlocale.c
index e3fa187..9fd9216 100644
--- a/locale/loadlocale.c
+++ b/locale/loadlocale.c
@@ -169,7 +169,6 @@ _nl_load_locale (struct loaded_l10nfile *file, int category)
int save_err;
int alloc = ld_mapped;
- file->decided = 1;
file->data = NULL;
fd = __open_nocancel (file->filename, O_RDONLY | O_CLOEXEC);
@@ -278,6 +277,7 @@ _nl_load_locale (struct loaded_l10nfile *file, int category)
newdata->alloc = alloc;
file->data = newdata;
+ file->decided = 1;
}
void

@ -0,0 +1,26 @@
commit 0b03996304f86d6dba8f0d4b7048b9bb7186f17d
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date: Tue Aug 3 21:10:10 2021 +0530
ldconfig: avoid leak on empty paths in config file
Reviewed-by: Arjun Shankar <arjun@redhat.com>
(cherry picked from commit b0234d79e7d82475d1666f25326ec045c045b3ed)
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
index 1037e8d0cf8d28b6..b8893637f8aaea8d 100644
--- a/elf/ldconfig.c
+++ b/elf/ldconfig.c
@@ -503,7 +503,11 @@ add_dir_1 (const char *line, const char *from_file, int from_line)
entry->path[--i] = '\0';
if (i == 0)
- return;
+ {
+ free (entry->path);
+ free (entry);
+ return;
+ }
char *path = entry->path;
if (opt_chroot != NULL)

@ -0,0 +1,34 @@
commit f2413f2710d5d5cc884b413b83fcf8198e3717fa
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Sat Aug 28 06:10:38 2021 -0700
x86-64: Use testl to check __x86_string_control
Use testl, instead of andl, to check __x86_string_control to avoid
updating __x86_string_control.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 3c8b9879cab6d41787bc5b14c1748f62fd6d0e5f)
diff --git a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S
index 9f02624375c07b26..abde8438d41f2320 100644
--- a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S
+++ b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S
@@ -325,7 +325,7 @@ L(movsb):
/* Avoid slow backward REP MOVSB. */
jb L(more_8x_vec_backward)
# if AVOID_SHORT_DISTANCE_REP_MOVSB
- andl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip)
+ testl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip)
jz 3f
movq %rdi, %rcx
subq %rsi, %rcx
@@ -333,7 +333,7 @@ L(movsb):
# endif
1:
# if AVOID_SHORT_DISTANCE_REP_MOVSB
- andl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip)
+ testl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip)
jz 3f
movq %rsi, %rcx
subq %rdi, %rcx

@ -0,0 +1,95 @@
commit e09e7b1492b2d5c2f68ddf81f8f58e093dd4df6d
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Mon Dec 13 11:36:42 2021 -0300
support: Add support_socket_so_timestamp_time64
Check if the socket support 64-bit network packages timestamps
(SO_TIMESTAMP and SO_TIMESTAMPNS). This will be used on recvmsg
and recvmmsg tests to check if the timestamp should be generated.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from 38bc0f4e78934aab455b31af05cefcbf3c22bece)
diff --git a/support/Makefile b/support/Makefile
index 3c941e1ba9e29aa4..6a5fc9faf2ca2e2d 100644
--- a/support/Makefile
+++ b/support/Makefile
@@ -79,6 +79,7 @@ libsupport-routines = \
support_set_small_thread_stack_size \
support_shared_allocate \
support_small_stack_thread_attribute \
+ support_socket_so_timestamp_time64 \
support_stat_nanoseconds \
support_subprocess \
support_test_compare_blob \
diff --git a/support/support.h b/support/support.h
index 29d56c7c891ee34b..ecfc9a336d272a30 100644
--- a/support/support.h
+++ b/support/support.h
@@ -170,6 +170,10 @@ extern bool support_select_modifies_timeout (void);
tv_usec larger than 1000000. */
extern bool support_select_normalizes_timeout (void);
+/* Return true if socket FD supports 64-bit timestamps with the SOL_SOCKET
+ and SO_TIMESTAMP/SO_TIMESTAMPNS. */
+extern bool support_socket_so_timestamp_time64 (int fd);
+
/* Create a timer that trigger after SEC seconds and NSEC nanoseconds. If
REPEAT is true the timer will repeat indefinitely. If CALLBACK is not
NULL, the function will be called when the timer expires; otherwise a
diff --git a/support/support_socket_so_timestamp_time64.c b/support/support_socket_so_timestamp_time64.c
new file mode 100644
index 0000000000000000..54bf3f42724566f5
--- /dev/null
+++ b/support/support_socket_so_timestamp_time64.c
@@ -0,0 +1,48 @@
+/* Return whether socket supports 64-bit timestamps.
+ 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 <unistd.h>
+#include <sys/syscall.h>
+#include <sys/socket.h>
+#include <support/support.h>
+#ifdef __linux__
+# include <socket-constants-time64.h>
+#endif
+
+bool
+support_socket_so_timestamp_time64 (int fd)
+{
+#ifdef __linux__
+# if __LINUX_KERNEL_VERSION >= 0x050100 \
+ || __WORDSIZE == 64 \
+ || (defined __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64)
+ return true;
+# else
+ int level = SOL_SOCKET;
+ int optname = COMPAT_SO_TIMESTAMP_NEW;
+ int optval;
+ socklen_t len = sizeof (optval);
+
+ int r = syscall (__NR_getsockopt, fd, level, optname, &optval, &len);
+ return r != -1;
+# endif
+#else
+ return false;
+#endif
+}

@ -0,0 +1,431 @@
commit e098446037da532d4a250efac9a813bc22f3669f
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Mon Jan 24 08:55:53 2022 -0300
linux: Fix ancillary 64-bit time timestamp conversion (BZ #28349, BZ#28350)
The __convert_scm_timestamps only updates the control message last
pointer for SOL_SOCKET type, so if the message control buffer contains
multiple ancillary message types the converted timestamp one might
overwrite a valid message.
The test checks if the extra ancillary space is correctly handled
by recvmsg/recvmmsg, where if there is no extra space for the 64-bit
time_t converted message the control buffer should be marked with
MSG_TRUNC. It also check if recvmsg/recvmmsg handle correctly multiple
ancillary data.
Checked on x86_64-linux and on i686-linux-gnu on both 5.11 and
4.15 kernel.
Co-authored-by: Fabian Vogt <fvogt@suse.de>
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 8fba672472ae0055387e9315fc2eddfa6775ca79)
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index cdc01a3f023ec09a..7c75e22c6d0e9ff5 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -273,6 +273,9 @@ sysdep_routines += cmsg_nxthdr
CFLAGS-recvmmsg.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-sendmmsg.c = -fexceptions -fasynchronous-unwind-tables
+tests += tst-socket-timestamp
+tests-time64 += tst-socket-timestamp-time64
+
tests-special += $(objpfx)tst-socket-consts.out
$(objpfx)tst-socket-consts.out: ../sysdeps/unix/sysv/linux/tst-socket-consts.py
PYTHONPATH=../scripts \
diff --git a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
index 00c934c4135f0d42..5d3c4199e0b32944 100644
--- a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
+++ b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
@@ -54,6 +54,8 @@ __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize)
cmsg != NULL;
cmsg = CMSG_NXTHDR (msg, cmsg))
{
+ last = cmsg;
+
if (cmsg->cmsg_level != SOL_SOCKET)
continue;
@@ -75,11 +77,9 @@ __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize)
tvts[1] = tmp[1];
break;
}
-
- last = cmsg;
}
- if (last == NULL || type == 0)
+ if (type == 0)
return;
if (CMSG_SPACE (sizeof tvts) > msgsize - msg->msg_controllen)
@@ -88,10 +88,12 @@ __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize)
return;
}
+ /* Zero memory for the new cmsghdr, so reading cmsg_len field
+ by CMSG_NXTHDR does not trigger UB. */
+ memset (msg->msg_control + msg->msg_controllen, 0,
+ CMSG_SPACE (sizeof tvts));
msg->msg_controllen += CMSG_SPACE (sizeof tvts);
- cmsg = CMSG_NXTHDR(msg, last);
- if (cmsg == NULL)
- return;
+ cmsg = CMSG_NXTHDR (msg, last);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = type;
cmsg->cmsg_len = CMSG_LEN (sizeof tvts);
diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp-time64.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp-time64.c
new file mode 100644
index 0000000000000000..ae424c2a70026cf5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp-time64.c
@@ -0,0 +1 @@
+#include "tst-socket-timestamp.c"
diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp.c
new file mode 100644
index 0000000000000000..9c2e76f7e27bd312
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp.c
@@ -0,0 +1,336 @@
+/* Check recvmsg/recvmmsg 64-bit timestamp support.
+ 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 <array_length.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <support/check.h>
+#include <support/next_to_fault.h>
+#include <support/support.h>
+#include <support/test-driver.h>
+#include <support/xunistd.h>
+#include <support/xsocket.h>
+#include <sys/mman.h>
+
+/* Some extra space added for ancillary data, it might be used to convert
+ 32-bit timestamp to 64-bit for _TIME_BITS=64. */
+enum { slack_max_size = 64 };
+static const int slack[] = { 0, 4, 8, 16, 32, slack_max_size };
+
+static bool support_64_timestamp;
+/* AF_INET socket and address used to receive data. */
+static int srv;
+static struct sockaddr_in srv_addr;
+
+static int
+do_sendto (const struct sockaddr_in *addr, int nmsgs)
+{
+ int s = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ xconnect (s, (const struct sockaddr *) addr, sizeof (*addr));
+
+ for (int i = 0; i < nmsgs; i++)
+ xsendto (s, &i, sizeof (i), 0, (const struct sockaddr *) addr,
+ sizeof (*addr));
+
+ xclose (s);
+
+ return 0;
+}
+
+static void
+do_recvmsg_slack_ancillary (bool use_multi_call, int s, void *cmsg,
+ size_t slack, size_t tsize, int exp_payload)
+{
+ int payload;
+ struct iovec iov =
+ {
+ .iov_base = &payload,
+ .iov_len = sizeof (payload)
+ };
+ size_t msg_controllen = CMSG_SPACE (tsize) + slack;
+ char *msg_control = cmsg - msg_controllen;
+ memset (msg_control, 0x55, msg_controllen);
+ struct mmsghdr mmhdr =
+ {
+ .msg_hdr =
+ {
+ .msg_name = NULL,
+ .msg_namelen = 0,
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_control = msg_control,
+ .msg_controllen = msg_controllen
+ },
+ };
+
+ int r;
+ if (use_multi_call)
+ {
+ r = recvmmsg (s, &mmhdr, 1, 0, NULL);
+ if (r >= 0)
+ r = mmhdr.msg_len;
+ }
+ else
+ r = recvmsg (s, &mmhdr.msg_hdr, 0);
+ TEST_COMPARE (r, sizeof (int));
+ TEST_COMPARE (payload, exp_payload);
+
+ if (cmsg == NULL)
+ return;
+
+ /* A timestamp is expected if 32-bit timestamp are used (support in every
+ configuration) or if underlying kernel support 64-bit timestamps.
+ Otherwise recvmsg will need extra space do add the 64-bit timestamp. */
+ bool exp_timestamp;
+ if (sizeof (time_t) == 4 || support_64_timestamp)
+ exp_timestamp = true;
+ else
+ exp_timestamp = slack >= CMSG_SPACE (tsize);
+
+ bool timestamp = false;
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg))
+ {
+ if (cmsg->cmsg_level != SOL_SOCKET)
+ continue;
+ if (cmsg->cmsg_type == SCM_TIMESTAMP
+ && cmsg->cmsg_len == CMSG_LEN (sizeof (struct timeval)))
+ {
+ struct timeval tv;
+ memcpy (&tv, CMSG_DATA (cmsg), sizeof (tv));
+ if (test_verbose)
+ printf ("SCM_TIMESTAMP: {%jd, %jd}\n", (intmax_t)tv.tv_sec,
+ (intmax_t)tv.tv_usec);
+ timestamp = true;
+ }
+ else if (cmsg->cmsg_type == SCM_TIMESTAMPNS
+ && cmsg->cmsg_len == CMSG_LEN (sizeof (struct timespec)))
+ {
+ struct timespec ts;
+ memcpy (&ts, CMSG_DATA (cmsg), sizeof (ts));
+ if (test_verbose)
+ printf ("SCM_TIMESTAMPNS: {%jd, %jd}\n", (intmax_t)ts.tv_sec,
+ (intmax_t)ts.tv_nsec);
+ timestamp = true;
+ }
+ }
+
+ TEST_COMPARE (timestamp, exp_timestamp);
+}
+
+/* Check if the extra ancillary space is correctly handled by recvmsg and
+ recvmmsg with different extra space for the ancillaty buffer. */
+static void
+do_test_slack_space (void)
+{
+ /* Setup the ancillary data buffer with an extra page with PROT_NONE to
+ check the possible timestamp conversion on some systems. */
+ struct support_next_to_fault nf =
+ support_next_to_fault_allocate (slack_max_size);
+ void *msgbuf = nf.buffer + slack_max_size;
+
+ /* Enable the timestamp using struct timeval precision. */
+ {
+ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMP, &(int){1},
+ sizeof (int));
+ TEST_VERIFY_EXIT (r != -1);
+ }
+ /* Check recvmsg. */
+ do_sendto (&srv_addr, array_length (slack));
+ for (int s = 0; s < array_length (slack); s++)
+ {
+ memset (nf.buffer, 0x55, nf.length);
+ do_recvmsg_slack_ancillary (false, srv, msgbuf, slack[s],
+ sizeof (struct timeval), s);
+ }
+ /* Check recvmmsg. */
+ do_sendto (&srv_addr, array_length (slack));
+ for (int s = 0; s < array_length (slack); s++)
+ {
+ memset (nf.buffer, 0x55, nf.length);
+ do_recvmsg_slack_ancillary (true, srv, msgbuf, slack[s],
+ sizeof (struct timeval), s);
+ }
+
+ /* Now enable timestamp using a higher precision, it overwrites the previous
+ precision. */
+ {
+ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMPNS, &(int){1},
+ sizeof (int));
+ TEST_VERIFY_EXIT (r != -1);
+ }
+ /* Check recvmsg. */
+ do_sendto (&srv_addr, array_length (slack));
+ for (int s = 0; s < array_length (slack); s++)
+ do_recvmsg_slack_ancillary (false, srv, msgbuf, slack[s],
+ sizeof (struct timespec), s);
+ /* Check recvmmsg. */
+ do_sendto (&srv_addr, array_length (slack));
+ for (int s = 0; s < array_length (slack); s++)
+ do_recvmsg_slack_ancillary (true, srv, msgbuf, slack[s],
+ sizeof (struct timespec), s);
+
+ support_next_to_fault_free (&nf);
+}
+
+/* Check if the converted 64-bit timestamp is correctly appended when there
+ are multiple ancillary messages. */
+static void
+do_recvmsg_multiple_ancillary (bool use_multi_call, int s, void *cmsg,
+ size_t cmsgsize, int exp_msg)
+{
+ int msg;
+ struct iovec iov =
+ {
+ .iov_base = &msg,
+ .iov_len = sizeof (msg)
+ };
+ size_t msgs = cmsgsize;
+ struct mmsghdr mmhdr =
+ {
+ .msg_hdr =
+ {
+ .msg_name = NULL,
+ .msg_namelen = 0,
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ .msg_controllen = msgs,
+ .msg_control = cmsg,
+ },
+ };
+
+ int r;
+ if (use_multi_call)
+ {
+ r = recvmmsg (s, &mmhdr, 1, 0, NULL);
+ if (r >= 0)
+ r = mmhdr.msg_len;
+ }
+ else
+ r = recvmsg (s, &mmhdr.msg_hdr, 0);
+ TEST_COMPARE (r, sizeof (int));
+ TEST_COMPARE (msg, exp_msg);
+
+ if (cmsg == NULL)
+ return;
+
+ bool timestamp = false;
+ bool origdstaddr = false;
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg))
+ {
+ if (cmsg->cmsg_level == SOL_IP
+ && cmsg->cmsg_type == IP_ORIGDSTADDR
+ && cmsg->cmsg_len >= CMSG_LEN (sizeof (struct sockaddr_in)))
+ {
+ struct sockaddr_in sa;
+ memcpy (&sa, CMSG_DATA (cmsg), sizeof (sa));
+ if (test_verbose)
+ {
+ char str[INET_ADDRSTRLEN];
+ inet_ntop (AF_INET, &sa.sin_addr, str, INET_ADDRSTRLEN);
+ printf ("IP_ORIGDSTADDR: %s:%d\n", str, ntohs (sa.sin_port));
+ }
+ origdstaddr = sa.sin_addr.s_addr == srv_addr.sin_addr.s_addr
+ && sa.sin_port == srv_addr.sin_port;
+ }
+ if (cmsg->cmsg_level == SOL_SOCKET
+ && cmsg->cmsg_type == SCM_TIMESTAMP
+ && cmsg->cmsg_len >= CMSG_LEN (sizeof (struct timeval)))
+ {
+ struct timeval tv;
+ memcpy (&tv, CMSG_DATA (cmsg), sizeof (tv));
+ if (test_verbose)
+ printf ("SCM_TIMESTAMP: {%jd, %jd}\n", (intmax_t)tv.tv_sec,
+ (intmax_t)tv.tv_usec);
+ timestamp = true;
+ }
+ }
+
+ TEST_COMPARE (timestamp, true);
+ TEST_COMPARE (origdstaddr, true);
+}
+
+static void
+do_test_multiple_ancillary (void)
+{
+ {
+ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMP, &(int){1},
+ sizeof (int));
+ TEST_VERIFY_EXIT (r != -1);
+ }
+ {
+ int r = setsockopt (srv, IPPROTO_IP, IP_RECVORIGDSTADDR, &(int){1},
+ sizeof (int));
+ TEST_VERIFY_EXIT (r != -1);
+ }
+
+ /* Enougth data for default SO_TIMESTAMP, the IP_RECVORIGDSTADDR, and the
+ extra 64-bit SO_TIMESTAMP. */
+ enum { msgbuflen = CMSG_SPACE (2 * sizeof (uint64_t))
+ + CMSG_SPACE (sizeof (struct sockaddr_in))
+ + CMSG_SPACE (2 * sizeof (uint64_t)) };
+ char msgbuf[msgbuflen];
+
+ enum { nmsgs = 8 };
+ /* Check recvmsg. */
+ do_sendto (&srv_addr, nmsgs);
+ for (int s = 0; s < nmsgs; s++)
+ do_recvmsg_multiple_ancillary (false, srv, msgbuf, msgbuflen, s);
+ /* Check recvmmsg. */
+ do_sendto (&srv_addr, nmsgs);
+ for (int s = 0; s < nmsgs; s++)
+ do_recvmsg_multiple_ancillary (true, srv, msgbuf, msgbuflen, s);
+}
+
+static int
+do_test (void)
+{
+ srv = xsocket (AF_INET, SOCK_DGRAM, 0);
+ srv_addr = (struct sockaddr_in) {
+ .sin_family = AF_INET,
+ .sin_addr = {.s_addr = htonl (INADDR_LOOPBACK) },
+ };
+ xbind (srv, (struct sockaddr *) &srv_addr, sizeof (srv_addr));
+ {
+ socklen_t sa_len = sizeof (srv_addr);
+ xgetsockname (srv, (struct sockaddr *) &srv_addr, &sa_len);
+ TEST_VERIFY (sa_len == sizeof (srv_addr));
+ }
+
+ TEST_COMPARE (recvmsg (-1, NULL, 0), -1);
+ TEST_COMPARE (errno, EBADF);
+ TEST_COMPARE (recvmmsg (-1, NULL, 0, 0, NULL), -1);
+ TEST_COMPARE (errno, EBADF);
+
+ /* If underlying kernel does not support */
+ support_64_timestamp = support_socket_so_timestamp_time64 (srv);
+
+ do_test_slack_space ();
+ do_test_multiple_ancillary ();
+
+ xclose (srv);
+
+ return 0;
+}
+
+#include <support/test-driver.c>

@ -0,0 +1,485 @@
commit 489d0b8b32548bc569cd3067aebf98b030720753
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Thu Jan 27 16:45:18 2022 -0300
Linux: Only generate 64 bit timestamps for 64 bit time_t recvmsg/recvmmsg
The timestamps created by __convert_scm_timestamps only make sense for
64 bit time_t programs, 32 bit time_t programs will ignore 64 bit time_t
timestamps since SO_TIMESTAMP will be defined to old values (either by
glibc or kernel headers).
Worse, if the buffer is not suffice MSG_CTRUNC is set to indicate it
(which breaks some programs [1]).
This patch makes only 64 bit time_t recvmsg and recvmmsg to call
__convert_scm_timestamps. Also, the assumption to called it is changed
from __ASSUME_TIME64_SYSCALLS to __TIMESIZE != 64 since the setsockopt
might be called by libraries built without __TIME_BITS=64. The
MSG_CTRUNC is only set for the 64 bit symbols, it should happen only
if 64 bit time_t programs run older kernels.
Checked on x86_64-linux-gnu and i686-linux-gnu.
[1] https://github.com/systemd/systemd/pull/20567
Reviewed-by: Florian Weimer <fweimer@redhat.com>
(cherry picked from commit 948ce73b31fdb0860bcec4b8e62b14e88234f98a)
diff --git a/include/sys/socket.h b/include/sys/socket.h
index a1d749f9fa7b9257..6e4cf5077fb885a9 100644
--- a/include/sys/socket.h
+++ b/include/sys/socket.h
@@ -98,15 +98,21 @@ extern int __sendmmsg (int __fd, struct mmsghdr *__vmessages,
libc_hidden_proto (__sendmmsg)
#endif
-/* Receive a message as described by MESSAGE from socket FD.
- Returns the number of bytes read or -1 for errors. */
extern ssize_t __libc_recvmsg (int __fd, struct msghdr *__message,
int __flags);
extern ssize_t __recvmsg (int __fd, struct msghdr *__message,
int __flags) attribute_hidden;
#if __TIMESIZE == 64
+# define __libc_recvmsg64 __libc_recvmsg
+# define __recvmsg64 __recvmsg
# define __recvmmsg64 __recvmmsg
#else
+extern ssize_t __libc_recvmsg64 (int __fd, struct msghdr *__message,
+ int __flags);
+extern ssize_t __recvmsg64 (int __fd, struct msghdr *__message,
+ int __flags);
+/* Receive a message as described by MESSAGE from socket FD.
+ Returns the number of bytes read or -1 for errors. */
extern int __recvmmsg64 (int __fd, struct mmsghdr *vmessages,
unsigned int vlen, int flags,
struct __timespec64 *timeout);
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 7c75e22c6d0e9ff5..0657f4003e7116c6 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -273,8 +273,14 @@ sysdep_routines += cmsg_nxthdr
CFLAGS-recvmmsg.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-sendmmsg.c = -fexceptions -fasynchronous-unwind-tables
-tests += tst-socket-timestamp
-tests-time64 += tst-socket-timestamp-time64
+tests += \
+ tst-socket-timestamp \
+ tst-socket-timestamp-compat \
+ # tests
+tests-time64 += \
+ tst-socket-timestamp-time64 \
+ tst-socket-timestamp-compat-time64
+ # tests-time64
tests-special += $(objpfx)tst-socket-consts.out
$(objpfx)tst-socket-consts.out: ../sysdeps/unix/sysv/linux/tst-socket-consts.py
diff --git a/sysdeps/unix/sysv/linux/recvmmsg.c b/sysdeps/unix/sysv/linux/recvmmsg.c
index 5cd107ffa9be0699..fca9f6582db67fd7 100644
--- a/sysdeps/unix/sysv/linux/recvmmsg.c
+++ b/sysdeps/unix/sysv/linux/recvmmsg.c
@@ -20,9 +20,9 @@
#include <sysdep.h>
#include <socketcall.h>
-int
-__recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
- struct __timespec64 *timeout)
+static int
+recvmmsg_syscall (int fd, struct mmsghdr *vmessages, unsigned int vlen,
+ int flags, struct __timespec64 *timeout)
{
#ifndef __NR_recvmmsg_time64
# define __NR_recvmmsg_time64 __NR_recvmmsg
@@ -45,12 +45,6 @@ __recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
pts32 = &ts32;
}
- socklen_t csize[IOV_MAX];
- if (vlen > IOV_MAX)
- vlen = IOV_MAX;
- for (int i = 0; i < vlen; i++)
- csize[i] = vmessages[i].msg_hdr.msg_controllen;
-
# ifdef __ASSUME_RECVMMSG_SYSCALL
r = SYSCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, pts32);
# else
@@ -60,11 +54,31 @@ __recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
{
if (timeout != NULL)
*timeout = valid_timespec_to_timespec64 (ts32);
+ }
+#endif
+ return r;
+}
+
+int
+__recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
+ struct __timespec64 *timeout)
+{
+#if __TIMESIZE != 64
+ socklen_t csize[IOV_MAX];
+ if (vlen > IOV_MAX)
+ vlen = IOV_MAX;
+ for (int i = 0; i < vlen; i++)
+ csize[i] = vmessages[i].msg_hdr.msg_controllen;
+#endif
+ int r = recvmmsg_syscall (fd, vmessages, vlen, flags, timeout);
+#if __TIMESIZE != 64
+ if (r > 0)
+ {
for (int i=0; i < r; i++)
__convert_scm_timestamps (&vmessages[i].msg_hdr, csize[i]);
}
-#endif /* __ASSUME_TIME64_SYSCALLS */
+#endif
return r;
}
#if __TIMESIZE != 64
@@ -80,7 +94,7 @@ __recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
ts64 = valid_timespec_to_timespec64 (*timeout);
pts64 = &ts64;
}
- int r = __recvmmsg64 (fd, vmessages, vlen, flags, pts64);
+ int r = recvmmsg_syscall (fd, vmessages, vlen, flags, pts64);
if (r >= 0 && timeout != NULL)
/* The remanining timeout will be always less the input TIMEOUT. */
*timeout = valid_timespec64_to_timespec (ts64);
diff --git a/sysdeps/unix/sysv/linux/recvmsg.c b/sysdeps/unix/sysv/linux/recvmsg.c
index 07212f7c8641a921..c4b4704fd65d80c1 100644
--- a/sysdeps/unix/sysv/linux/recvmsg.c
+++ b/sysdeps/unix/sysv/linux/recvmsg.c
@@ -20,29 +20,41 @@
#include <sysdep-cancel.h>
#include <socketcall.h>
+static int
+__recvmsg_syscall (int fd, struct msghdr *msg, int flags)
+{
+#ifdef __ASSUME_RECVMSG_SYSCALL
+ return SYSCALL_CANCEL (recvmsg, fd, msg, flags);
+#else
+ return SOCKETCALL_CANCEL (recvmsg, fd, msg, flags);
+#endif
+}
+
ssize_t
-__libc_recvmsg (int fd, struct msghdr *msg, int flags)
+__libc_recvmsg64 (int fd, struct msghdr *msg, int flags)
{
ssize_t r;
-#ifndef __ASSUME_TIME64_SYSCALLS
+#if __TIMESIZE != 64
socklen_t orig_controllen = msg != NULL ? msg->msg_controllen : 0;
#endif
-#ifdef __ASSUME_RECVMSG_SYSCALL
- r = SYSCALL_CANCEL (recvmsg, fd, msg, flags);
-#else
- r = SOCKETCALL_CANCEL (recvmsg, fd, msg, flags);
-#endif
+ r = __recvmsg_syscall (fd, msg, flags);
-#ifndef __ASSUME_TIME64_SYSCALLS
+#if __TIMESIZE != 64
if (r >= 0 && orig_controllen != 0)
__convert_scm_timestamps (msg, orig_controllen);
#endif
return r;
}
-weak_alias (__libc_recvmsg, recvmsg)
-weak_alias (__libc_recvmsg, __recvmsg)
#if __TIMESIZE != 64
-weak_alias (__recvmsg, __recvmsg64)
+weak_alias (__libc_recvmsg64, __recvmsg64)
+
+ssize_t
+__libc_recvmsg (int fd, struct msghdr *msg, int flags)
+{
+ return __recvmsg_syscall (fd, msg, flags);
+}
#endif
+weak_alias (__libc_recvmsg, recvmsg)
+weak_alias (__libc_recvmsg, __recvmsg)
diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat-time64.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat-time64.c
new file mode 100644
index 0000000000000000..96a0bef0bf4a908b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat-time64.c
@@ -0,0 +1 @@
+#include "tst-socket-timestamp-compat.c"
diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c
new file mode 100644
index 0000000000000000..de261dae5a6385cf
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c
@@ -0,0 +1,265 @@
+/* Check recvmsg/recvmmsg 64-bit timestamp support.
+ 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 <arpa/inet.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/xsocket.h>
+#include <support/xunistd.h>
+#include <stdbool.h>
+
+/* AF_INET socket and address used to receive data. */
+static int srv;
+static struct sockaddr_in srv_addr;
+
+static int
+do_sendto (const struct sockaddr_in *addr, int payload)
+{
+ int s = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ xconnect (s, (const struct sockaddr *) addr, sizeof (*addr));
+
+ xsendto (s, &payload, sizeof (payload), 0, (const struct sockaddr *) addr,
+ sizeof (*addr));
+
+ xclose (s);
+
+ return 0;
+}
+
+static void
+do_recvmsg_ancillary (bool use_multi_call, struct mmsghdr *mmhdr,
+ void *msgbuf, size_t msgbuflen, int exp_payload)
+{
+ int payload;
+ struct iovec iov =
+ {
+ .iov_base = &payload,
+ .iov_len = sizeof (payload)
+ };
+ mmhdr->msg_hdr.msg_name = NULL;
+ mmhdr->msg_hdr.msg_iov = &iov;
+ mmhdr->msg_hdr.msg_iovlen = 1;
+ mmhdr->msg_hdr.msg_control = msgbuf;
+ mmhdr->msg_hdr.msg_controllen = msgbuflen;
+
+ int r;
+ if (use_multi_call)
+ {
+ r = recvmmsg (srv, mmhdr, 1, 0, NULL);
+ if (r >= 0)
+ r = mmhdr->msg_len;
+ }
+ else
+ r = recvmsg (srv, &mmhdr->msg_hdr, 0);
+ TEST_COMPARE (r, sizeof (int));
+ TEST_COMPARE (payload, exp_payload);
+}
+
+/* Check if recvmsg create the additional 64 bit timestamp if only 32 bit
+ is enabled for 64 bit recvmsg symbol. */
+static void
+do_test_large_buffer (bool mc)
+{
+ struct mmsghdr mmhdr = { 0 };
+ /* It should be large enought for either timeval/timespec and the
+ 64 time type as well. */
+
+ union
+ {
+ struct cmsghdr cmsghdr;
+ char msgbuf[512];
+ } control;
+
+ /* Enable 32 bit timeval precision and check if no 64 bit timeval stamp
+ is created. */
+ {
+ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMP_OLD, &(int){1},
+ sizeof (int));
+ TEST_VERIFY_EXIT (r != -1);
+
+ do_sendto (&srv_addr, 42);
+ do_recvmsg_ancillary (mc, &mmhdr, &control, sizeof control, 42);
+
+ bool found_timestamp = false;
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg))
+ {
+ if (cmsg->cmsg_level != SOL_SOCKET)
+ continue;
+
+ if (sizeof (time_t) > 4 && cmsg->cmsg_type == SO_TIMESTAMP_NEW)
+ found_timestamp = true;
+ else
+ TEST_VERIFY (cmsg->cmsg_type != SO_TIMESTAMP_NEW);
+ }
+
+ TEST_COMPARE (found_timestamp, sizeof (time_t) > 4);
+ }
+
+ /* Same as before, but for timespec. */
+ {
+ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMPNS_OLD, &(int){1},
+ sizeof (int));
+ TEST_VERIFY_EXIT (r != -1);
+
+ do_sendto (&srv_addr, 42);
+ do_recvmsg_ancillary (mc, &mmhdr, &control, sizeof control, 42);
+
+ bool found_timestamp = false;
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg))
+ {
+ if (cmsg->cmsg_level != SOL_SOCKET)
+ continue;
+
+ if (sizeof (time_t) > 4 && cmsg->cmsg_type == SO_TIMESTAMPNS_NEW)
+ found_timestamp = true;
+ else
+ TEST_VERIFY (cmsg->cmsg_type != SO_TIMESTAMPNS_NEW);
+ }
+
+ TEST_COMPARE (found_timestamp, sizeof (time_t) > 4);
+ }
+}
+
+/* Check if recvmsg does not create the additional 64 bit timestamp if
+ only 32 bit timestamp is enabled if the ancillary buffer is not large
+ enought. Also checks if MSG_CTRUNC is set iff for 64 bit recvmsg
+ symbol. */
+static void
+do_test_small_buffer (bool mc)
+{
+ struct mmsghdr mmhdr = { 0 };
+
+ /* Enable 32 bit timeval precision and check if no 64 bit timeval stamp
+ is created. */
+ {
+ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMP_OLD, &(int){1},
+ sizeof (int));
+ TEST_VERIFY_EXIT (r != -1);
+
+ union
+ {
+ struct cmsghdr cmsghdr;
+ char msgbuf[CMSG_SPACE (sizeof (struct timeval))];
+ } control;
+
+ do_sendto (&srv_addr, 42);
+ do_recvmsg_ancillary (mc, &mmhdr, &control, sizeof control, 42);
+
+ bool found_timestamp = false;
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg))
+ {
+ if (cmsg->cmsg_level != SOL_SOCKET)
+ continue;
+
+ if (sizeof (time_t) > 4 && cmsg->cmsg_type == SO_TIMESTAMP_NEW)
+ found_timestamp = true;
+ else
+ TEST_VERIFY (cmsg->cmsg_type != SO_TIMESTAMP_NEW);
+ }
+
+ if (sizeof (time_t) > 4)
+ {
+ TEST_VERIFY ((mmhdr.msg_hdr.msg_flags & MSG_CTRUNC));
+ TEST_COMPARE (found_timestamp, 0);
+ }
+ else
+ {
+ TEST_VERIFY (!(mmhdr.msg_hdr.msg_flags & MSG_CTRUNC));
+ TEST_COMPARE (found_timestamp, 0);
+ }
+ }
+
+ /* Same as before, but for timespec. */
+ {
+ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMPNS_OLD, &(int){1},
+ sizeof (int));
+ TEST_VERIFY_EXIT (r != -1);
+
+ union
+ {
+ struct cmsghdr cmsghdr;
+ char msgbuf[CMSG_SPACE (sizeof (struct timespec))];
+ } control;
+
+ do_sendto (&srv_addr, 42);
+ do_recvmsg_ancillary (mc, &mmhdr, &control, sizeof control, 42);
+
+ bool found_timestamp = false;
+ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg))
+ {
+ if (cmsg->cmsg_level != SOL_SOCKET)
+ continue;
+
+ if (sizeof (time_t) > 4 && cmsg->cmsg_type == SO_TIMESTAMPNS_NEW)
+ found_timestamp = true;
+ else
+ TEST_VERIFY (cmsg->cmsg_type != SO_TIMESTAMPNS_NEW);
+ }
+
+ if (sizeof (time_t) > 4)
+ {
+ TEST_VERIFY ((mmhdr.msg_hdr.msg_flags & MSG_CTRUNC));
+ TEST_COMPARE (found_timestamp, 0);
+ }
+ else
+ {
+ TEST_VERIFY ((mmhdr.msg_hdr.msg_flags & MSG_CTRUNC) == 0);
+ TEST_COMPARE (found_timestamp, 0);
+ }
+ }
+}
+
+static int
+do_test (void)
+{
+ /* This test only make sense for ABIs that support 32 bit time_t socket
+ timestampss. */
+ if (sizeof (time_t) > 4 && __WORDSIZE == 64)
+ return 0;
+
+ srv = xsocket (AF_INET, SOCK_DGRAM, 0);
+ srv_addr = (struct sockaddr_in) {
+ .sin_family = AF_INET,
+ .sin_addr = {.s_addr = htonl (INADDR_LOOPBACK) },
+ };
+ xbind (srv, (struct sockaddr *) &srv_addr, sizeof (srv_addr));
+ {
+ socklen_t sa_len = sizeof (srv_addr);
+ xgetsockname (srv, (struct sockaddr *) &srv_addr, &sa_len);
+ TEST_VERIFY (sa_len == sizeof (srv_addr));
+ }
+
+ /* Check recvmsg; */
+ do_test_large_buffer (false);
+ do_test_small_buffer (false);
+ /* Check recvmmsg. */
+ do_test_large_buffer (true);
+ do_test_small_buffer (true);
+
+ return 0;
+}
+
+#include <support/test-driver.c>

@ -0,0 +1,24 @@
commit 008003dc6e83439c5e04a744b7fd8197df19096e
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Sat Jan 29 05:22:31 2022 -0800
tst-socket-timestamp-compat.c: Check __TIMESIZE [BZ #28837]
time_t size is defined by __TIMESIZE, not __WORDSIZE. Check __TIMESIZE,
instead of __WORDSIZE, for time_t size. This fixes BZ #28837.
(cherry pick from commit 77a602ebb0769e7ccc5f9f8e06f7fffe66f69dfc)
diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c
index de261dae5a6385cf..0ff1a214e605105b 100644
--- a/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c
+++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c
@@ -237,7 +237,7 @@ do_test (void)
{
/* This test only make sense for ABIs that support 32 bit time_t socket
timestampss. */
- if (sizeof (time_t) > 4 && __WORDSIZE == 64)
+ if (sizeof (time_t) > 4 && __TIMESIZE == 64)
return 0;
srv = xsocket (AF_INET, SOCK_DGRAM, 0);

@ -0,0 +1,26 @@
commit 05c83ccaf50aef2dd30d92cbb814383f6bddea2c
Author: Gleb Fotengauer-Malinovskiy <glebfm@altlinux.org>
Date: Tue Feb 1 22:39:02 2022 +0000
linux: __get_nprocs_sched: do not feed CPU_COUNT_S with garbage [BZ #28850]
Pass the actual number of bytes returned by the kernel.
Fixes: 33099d72e41c ("linux: Simplify get_nprocs")
Reviewed-by: Dmitry V. Levin <ldv@altlinux.org>
(cherry picked from commit 97ba273b505763325efd802dc3a9562dbba79579)
diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
index 7fc6521942e87293..7babd947aa902e77 100644
--- a/sysdeps/unix/sysv/linux/getsysstats.c
+++ b/sysdeps/unix/sysv/linux/getsysstats.c
@@ -45,7 +45,7 @@ __get_nprocs_sched (void)
int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, cpu_bits_size,
cpu_bits);
if (r > 0)
- return CPU_COUNT_S (cpu_bits_size, (cpu_set_t*) cpu_bits);
+ return CPU_COUNT_S (r, (cpu_set_t*) cpu_bits);
else if (r == -EINVAL)
/* The input buffer is still not enough to store the number of cpus. This
is an arbitrary values assuming such systems should be rare and there

@ -0,0 +1,234 @@
commit ad615b59c78d6d37fee921fb2b2ae6b72c930625
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Sep 28 18:55:49 2021 +0200
Linux: Simplify __opensock and fix race condition [BZ #28353]
AF_NETLINK support is not quite optional on modern Linux systems
anymore, so it is likely that the first attempt will always succeed.
Consequently, there is no need to cache the result. Keep AF_UNIX
and the Internet address families as a fallback, for the rare case
that AF_NETLINK is missing. The other address families previously
probed are totally obsolete be now, so remove them.
Use this simplified version as the generic implementation, disabling
Netlink support as needed.
(cherry picked from commit 5bf07e1b3a74232bfb8332275110be1a5da50f83)
diff --git a/socket/opensock.c b/socket/opensock.c
index 37148d4743343ff4..ff94d27a61bd3889 100644
--- a/socket/opensock.c
+++ b/socket/opensock.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1999-2021 Free Software Foundation, Inc.
+/* Create socket with an unspecified address family for use with ioctl.
+ Copyright (C) 1999-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
@@ -15,56 +16,34 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <stdio.h>
+#include <errno.h>
#include <sys/socket.h>
-#include <libc-lock.h>
/* Return a socket of any type. The socket can be used in subsequent
ioctl calls to talk to the kernel. */
int
__opensock (void)
{
- /* Cache the last AF that worked, to avoid many redundant calls to
- socket(). */
- static int sock_af = -1;
- int fd = -1;
- __libc_lock_define_initialized (static, lock);
-
- if (sock_af != -1)
- {
- fd = __socket (sock_af, SOCK_DGRAM, 0);
- if (fd != -1)
- return fd;
- }
-
- __libc_lock_lock (lock);
-
- if (sock_af != -1)
- fd = __socket (sock_af, SOCK_DGRAM, 0);
-
- if (fd == -1)
- {
-#ifdef AF_INET
- fd = __socket (sock_af = AF_INET, SOCK_DGRAM, 0);
-#endif
-#ifdef AF_INET6
- if (fd < 0)
- fd = __socket (sock_af = AF_INET6, SOCK_DGRAM, 0);
-#endif
-#ifdef AF_IPX
- if (fd < 0)
- fd = __socket (sock_af = AF_IPX, SOCK_DGRAM, 0);
-#endif
-#ifdef AF_AX25
- if (fd < 0)
- fd = __socket (sock_af = AF_AX25, SOCK_DGRAM, 0);
-#endif
-#ifdef AF_APPLETALK
- if (fd < 0)
- fd = __socket (sock_af = AF_APPLETALK, SOCK_DGRAM, 0);
+ /* SOCK_DGRAM is supported by all address families. (Netlink does
+ not support SOCK_STREAM.) */
+ int type = SOCK_DGRAM | SOCK_CLOEXEC;
+ int fd;
+
+#ifdef AF_NETLINK
+ fd = __socket (AF_NETLINK, type, 0);
+ if (fd >= 0)
+ return fd;
#endif
- }
- __libc_lock_unlock (lock);
+ fd = __socket (AF_UNIX, type, 0);
+ if (fd >= 0)
+ return fd;
+ fd = __socket (AF_INET, type, 0);
+ if (fd >= 0)
+ return fd;
+ fd = __socket (AF_INET6, type, 0);
+ if (fd >= 0)
+ return fd;
+ __set_errno (ENOENT);
return fd;
}
diff --git a/sysdeps/unix/sysv/linux/opensock.c b/sysdeps/unix/sysv/linux/opensock.c
deleted file mode 100644
index e87d6e58b0b84f82..0000000000000000
--- a/sysdeps/unix/sysv/linux/opensock.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* Copyright (C) 1999-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 <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/socket.h>
-
-/* Return a socket of any type. The socket can be used in subsequent
- ioctl calls to talk to the kernel. */
-int
-__opensock (void)
-{
- static int last_family; /* Available socket family we will use. */
- static int last_type;
- static const struct
- {
- int family;
- const char procname[15];
- } afs[] =
- {
- { AF_UNIX, "net/unix" },
- { AF_INET, "" },
- { AF_INET6, "net/if_inet6" },
- { AF_AX25, "net/ax25" },
- { AF_NETROM, "net/nr" },
- { AF_ROSE, "net/rose" },
- { AF_IPX, "net/ipx" },
- { AF_APPLETALK, "net/appletalk" },
- { AF_ECONET, "sys/net/econet" },
- { AF_ASH, "sys/net/ash" },
- { AF_X25, "net/x25" },
-#ifdef NEED_AF_IUCV
- { AF_IUCV, "net/iucv" }
-#endif
- };
-#define nafs (sizeof (afs) / sizeof (afs[0]))
- char fname[sizeof "/proc/" + 14];
- int result;
- int has_proc;
- size_t cnt;
-
- /* We already know which family to use from the last call. Use it
- again. */
- if (last_family != 0)
- {
- assert (last_type != 0);
-
- result = __socket (last_family, last_type | SOCK_CLOEXEC, 0);
- if (result != -1 || errno != EAFNOSUPPORT)
- /* Maybe the socket type isn't supported anymore (module is
- unloaded). In this case again try to find the type. */
- return result;
-
- /* Reset the values. They seem not valid anymore. */
- last_family = 0;
- last_type = 0;
- }
-
- /* Check whether the /proc filesystem is available. */
- has_proc = __access ("/proc/net", R_OK) != -1;
- strcpy (fname, "/proc/");
-
- /* Iterate over the interface families and find one which is
- available. */
- for (cnt = 0; cnt < nafs; ++cnt)
- {
- int type = SOCK_DGRAM;
-
- if (has_proc && afs[cnt].procname[0] != '\0')
- {
- strcpy (fname + 6, afs[cnt].procname);
- if (__access (fname, R_OK) == -1)
- /* The /proc entry is not available. I.e., we cannot
- create a socket of this type (without loading the
- module). Don't look for it since this might trigger
- loading the module. */
- continue;
- }
-
- if (afs[cnt].family == AF_NETROM || afs[cnt].family == AF_X25)
- type = SOCK_SEQPACKET;
-
- result = __socket (afs[cnt].family, type | SOCK_CLOEXEC, 0);
- if (result != -1)
- {
- /* Found an available family. */
- last_type = type;
- last_family = afs[cnt].family;
- return result;
- }
- }
-
- /* None of the protocol families is available. It is unclear what kind
- of error is returned. ENOENT seems like a reasonable choice. */
- __set_errno (ENOENT);
- return -1;
-}
diff --git a/sysdeps/unix/sysv/linux/s390/opensock.c b/sysdeps/unix/sysv/linux/s390/opensock.c
deleted file mode 100644
index f099d651ff04d211..0000000000000000
--- a/sysdeps/unix/sysv/linux/s390/opensock.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define NEED_AF_IUCV 1
-#include "../opensock.c"

@ -0,0 +1,44 @@
commit d8302ba2da1e5ac59a1c4dc1c1207a10fdafdb08
Author: Samuel Thibault <samuel.thibault@ens-lyon.org>
Date: Mon Oct 18 01:39:02 2021 +0200
hurd if_index: Explicitly use AF_INET for if index discovery
5bf07e1b3a74 ("Linux: Simplify __opensock and fix race condition [BZ #28353]")
made __opensock try NETLINK then UNIX then INET. On the Hurd, only INET
knows about network interfaces, so better actually specify that in
if_index.
(cherry picked from commit 1d3decee997ba2fc24af81803299b2f4f3c47063)
diff --git a/sysdeps/mach/hurd/if_index.c b/sysdeps/mach/hurd/if_index.c
index 0eab510453c9e861..e785ac15aa6a1002 100644
--- a/sysdeps/mach/hurd/if_index.c
+++ b/sysdeps/mach/hurd/if_index.c
@@ -32,7 +32,7 @@ unsigned int
__if_nametoindex (const char *ifname)
{
struct ifreq ifr;
- int fd = __opensock ();
+ int fd = __socket (AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
return 0;
@@ -84,7 +84,7 @@ __if_nameindex (void)
error_t err = 0;
char data[2048];
file_t server;
- int fd = __opensock ();
+ int fd = __socket (AF_INET, SOCK_DGRAM, 0);
struct ifconf ifc;
unsigned int nifs, i;
struct if_nameindex *idx = NULL;
@@ -169,7 +169,7 @@ char *
__if_indextoname (unsigned int ifindex, char ifname[IF_NAMESIZE])
{
struct ifreq ifr;
- int fd = __opensock ();
+ int fd = __socket (AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
return NULL;

@ -0,0 +1,35 @@
commit 6eaf10cbb78d22eae7999d9de55f6b93999e0860
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Nov 22 14:41:14 2021 +0100
socket: Do not use AF_NETLINK in __opensock
It is not possible to use interface ioctls with netlink sockets
on all Linux kernels.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 3d981795cd00cc9b73c3ee5087c308361acd62e5)
diff --git a/socket/opensock.c b/socket/opensock.c
index ff94d27a61bd3889..3e35821f91643456 100644
--- a/socket/opensock.c
+++ b/socket/opensock.c
@@ -24,17 +24,10 @@
int
__opensock (void)
{
- /* SOCK_DGRAM is supported by all address families. (Netlink does
- not support SOCK_STREAM.) */
+ /* SOCK_DGRAM is supported by all address families. */
int type = SOCK_DGRAM | SOCK_CLOEXEC;
int fd;
-#ifdef AF_NETLINK
- fd = __socket (AF_NETLINK, type, 0);
- if (fd >= 0)
- return fd;
-#endif
-
fd = __socket (AF_UNIX, type, 0);
if (fd >= 0)
return fd;

@ -0,0 +1,32 @@
commit 0351c75c5f94134fcec0e778e8cf86d149f8bbfb
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Thu Feb 3 16:52:52 2022 -0300
linux: Fix missing __convert_scm_timestamps (BZ #28860)
Commit 948ce73b31 made recvmsg/recvmmsg to always call
__convert_scm_timestamps for 64 bit time_t symbol, so adjust it to
always build it for __TIMESIZE != 64.
It fixes build for architecture with 32 bit time_t support when
configured with minimum kernel of 5.1.
(cherry-picked from 798d716df71fb23dc89d1d5dba1fc26a1b5c0024)
diff --git a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
index 5d3c4199e0b32944..953ce97bd2e03849 100644
--- a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
+++ b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
@@ -16,9 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#include <kernel-features.h>
+#include <bits/wordsize.h>
+#include <bits/timesize.h>
-#ifndef __ASSUME_TIME64_SYSCALLS
+#if __TIMESIZE != 64
# include <stdint.h>
# include <string.h>
# include <sys/socket.h>

@ -0,0 +1,62 @@
commit 52d0119743180164d1664b6773ac5d873f224608
Author: Jiaxun Yang <jiaxun.yang@flygoat.com>
Date: Tue Sep 7 13:31:42 2021 +0800
MIPS: Setup errno for {f,l,}xstat
{f,l,}xstat stub for MIPS is using INTERNAL_SYSCALL
to do xstat syscall for glibc ver, However it leaves
errno untouched and thus giving bad errno output.
Setup errno properly when syscall returns non-zero.
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 66016ec8aeefd40e016d7040d966484c764b0e9c)
diff --git a/sysdeps/unix/sysv/linux/mips/fxstat.c b/sysdeps/unix/sysv/linux/mips/fxstat.c
index 11511d30b38708ce..4a6016ff123e8dd9 100644
--- a/sysdeps/unix/sysv/linux/mips/fxstat.c
+++ b/sysdeps/unix/sysv/linux/mips/fxstat.c
@@ -35,7 +35,9 @@ __fxstat (int vers, int fd, struct stat *buf)
{
struct kernel_stat kbuf;
int r = INTERNAL_SYSCALL_CALL (fstat, fd, &kbuf);
- return r ?: __xstat_conv (vers, &kbuf, buf);
+ if (r == 0)
+ return __xstat_conv (vers, &kbuf, buf);
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (-r);
}
}
}
diff --git a/sysdeps/unix/sysv/linux/mips/lxstat.c b/sysdeps/unix/sysv/linux/mips/lxstat.c
index 871fb6c6c5886665..54f990a250677091 100644
--- a/sysdeps/unix/sysv/linux/mips/lxstat.c
+++ b/sysdeps/unix/sysv/linux/mips/lxstat.c
@@ -35,7 +35,9 @@ __lxstat (int vers, const char *name, struct stat *buf)
{
struct kernel_stat kbuf;
int r = INTERNAL_SYSCALL_CALL (lstat, name, &kbuf);
- return r ?: __xstat_conv (vers, &kbuf, buf);
+ if (r == 0)
+ return __xstat_conv (vers, &kbuf, buf);
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (-r);
}
}
}
diff --git a/sysdeps/unix/sysv/linux/mips/xstat.c b/sysdeps/unix/sysv/linux/mips/xstat.c
index 9d810b6f653b964b..86f4dc31a82ff1bb 100644
--- a/sysdeps/unix/sysv/linux/mips/xstat.c
+++ b/sysdeps/unix/sysv/linux/mips/xstat.c
@@ -35,7 +35,9 @@ __xstat (int vers, const char *name, struct stat *buf)
{
struct kernel_stat kbuf;
int r = INTERNAL_SYSCALL_CALL (stat, name, &kbuf);
- return r ?: __xstat_conv (vers, &kbuf, buf);
+ if (r == 0)
+ return __xstat_conv (vers, &kbuf, buf);
+ return INLINE_SYSCALL_ERROR_RETURN_VALUE (-r);
}
}
}

@ -0,0 +1,192 @@
commit 007e054d786be340699c634e3a3b30ab1fde1a7a
Author: Dmitry V. Levin <ldv@altlinux.org>
Date: Sat Feb 5 08:00:00 2022 +0000
linux: fix accuracy of get_nprocs and get_nprocs_conf [BZ #28865]
get_nprocs() and get_nprocs_conf() use various methods to obtain an
accurate number of processors. Re-introduce __get_nprocs_sched() as
a source of information, and fix the order in which these methods are
used to return the most accurate information. The primary source of
information used in both functions remains unchanged.
This also changes __get_nprocs_sched() error return value from 2 to 0,
but all its users are already prepared to handle that.
Old fallback order:
get_nprocs:
/sys/devices/system/cpu/online -> /proc/stat -> 2
get_nprocs_conf:
/sys/devices/system/cpu/ -> /proc/stat -> 2
New fallback order:
get_nprocs:
/sys/devices/system/cpu/online -> /proc/stat -> sched_getaffinity -> 2
get_nprocs_conf:
/sys/devices/system/cpu/ -> /proc/stat -> sched_getaffinity -> 2
Fixes: 342298278e ("linux: Revert the use of sched_getaffinity on get_nproc")
Closes: BZ #28865
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit e1d32b836410767270a3adf1f82b1a47e6e4cd51)
diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
index 7babd947aa902e77..327802b14c7326a3 100644
--- a/sysdeps/unix/sysv/linux/getsysstats.c
+++ b/sysdeps/unix/sysv/linux/getsysstats.c
@@ -51,9 +51,8 @@ __get_nprocs_sched (void)
is an arbitrary values assuming such systems should be rare and there
is no offline cpus. */
return max_num_cpus;
- /* Some other error. 2 is conservative (not a uniprocessor system, so
- atomics are needed). */
- return 2;
+ /* Some other error. */
+ return 0;
}
static char *
@@ -109,22 +108,19 @@ next_line (int fd, char *const buffer, char **cp, char **re,
}
static int
-get_nproc_stat (char *buffer, size_t buffer_size)
+get_nproc_stat (void)
{
+ enum { buffer_size = 1024 };
+ char buffer[buffer_size];
char *buffer_end = buffer + buffer_size;
char *cp = buffer_end;
char *re = buffer_end;
-
- /* Default to an SMP system in case we cannot obtain an accurate
- number. */
- int result = 2;
+ int result = 0;
const int flags = O_RDONLY | O_CLOEXEC;
int fd = __open_nocancel ("/proc/stat", flags);
if (fd != -1)
{
- result = 0;
-
char *l;
while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL)
/* The current format of /proc/stat has all the cpu* entries
@@ -140,8 +136,8 @@ get_nproc_stat (char *buffer, size_t buffer_size)
return result;
}
-int
-__get_nprocs (void)
+static int
+get_nprocs_cpu_online (void)
{
enum { buffer_size = 1024 };
char buffer[buffer_size];
@@ -180,7 +176,8 @@ __get_nprocs (void)
}
}
- result += m - n + 1;
+ if (m >= n)
+ result += m - n + 1;
l = endp;
if (l < re && *l == ',')
@@ -189,28 +186,18 @@ __get_nprocs (void)
while (l < re && *l != '\n');
__close_nocancel_nostatus (fd);
-
- if (result > 0)
- return result;
}
- return get_nproc_stat (buffer, buffer_size);
+ return result;
}
-libc_hidden_def (__get_nprocs)
-weak_alias (__get_nprocs, get_nprocs)
-
-/* On some architectures it is possible to distinguish between configured
- and active cpus. */
-int
-__get_nprocs_conf (void)
+static int
+get_nprocs_cpu (void)
{
- /* Try to use the sysfs filesystem. It has actual information about
- online processors. */
+ int count = 0;
DIR *dir = __opendir ("/sys/devices/system/cpu");
if (dir != NULL)
{
- int count = 0;
struct dirent64 *d;
while ((d = __readdir64 (dir)) != NULL)
@@ -225,12 +212,57 @@ __get_nprocs_conf (void)
__closedir (dir);
- return count;
}
+ return count;
+}
- enum { buffer_size = 1024 };
- char buffer[buffer_size];
- return get_nproc_stat (buffer, buffer_size);
+static int
+get_nprocs_fallback (void)
+{
+ int result;
+
+ /* Try /proc/stat first. */
+ result = get_nproc_stat ();
+ if (result != 0)
+ return result;
+
+ /* Try sched_getaffinity. */
+ result = __get_nprocs_sched ();
+ if (result != 0)
+ return result;
+
+ /* We failed to obtain an accurate number. Be conservative: return
+ the smallest number meaning that this is not a uniprocessor system,
+ so atomics are needed. */
+ return 2;
+}
+
+int
+__get_nprocs (void)
+{
+ /* Try /sys/devices/system/cpu/online first. */
+ int result = get_nprocs_cpu_online ();
+ if (result != 0)
+ return result;
+
+ /* Fall back to /proc/stat and sched_getaffinity. */
+ return get_nprocs_fallback ();
+}
+libc_hidden_def (__get_nprocs)
+weak_alias (__get_nprocs, get_nprocs)
+
+/* On some architectures it is possible to distinguish between configured
+ and active cpus. */
+int
+__get_nprocs_conf (void)
+{
+ /* Try /sys/devices/system/cpu/ first. */
+ int result = get_nprocs_cpu ();
+ if (result != 0)
+ return result;
+
+ /* Fall back to /proc/stat and sched_getaffinity. */
+ return get_nprocs_fallback ();
}
libc_hidden_def (__get_nprocs_conf)
weak_alias (__get_nprocs_conf, get_nprocs_conf)

@ -0,0 +1,60 @@
commit 04d60ce0f21ffe2a4add148cb37a1942dbad64e2
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Thu Feb 17 08:10:35 2022 -0800
string: Add a testcase for wcsncmp with SIZE_MAX [BZ #28755]
Verify that wcsncmp (L("abc"), L("abd"), SIZE_MAX) == 0. The new test
fails without
commit ddf0992cf57a93200e0c782e2a94d0733a5a0b87
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date: Sun Jan 9 16:02:21 2022 -0600
x86: Fix __wcsncmp_avx2 in strcmp-avx2.S [BZ# 28755]
and
commit 7e08db3359c86c94918feb33a1182cd0ff3bb10b
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date: Sun Jan 9 16:02:28 2022 -0600
x86: Fix __wcsncmp_evex in strcmp-evex.S [BZ# 28755]
This is for BZ #28755.
Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>
(cherry picked from commit aa5a720056d37cf24924c138a3dbe6dace98e97c)
diff --git a/string/test-strncmp.c b/string/test-strncmp.c
index 10b34de8d2acb2a1..97e831d88fd24316 100644
--- a/string/test-strncmp.c
+++ b/string/test-strncmp.c
@@ -435,6 +435,18 @@ check3 (void)
}
}
+static void
+check4 (void)
+{
+ const CHAR *s1 = L ("abc");
+ CHAR *s2 = STRDUP (s1);
+
+ FOR_EACH_IMPL (impl, 0)
+ check_result (impl, s1, s2, SIZE_MAX, 0);
+
+ free (s2);
+}
+
int
test_main (void)
{
@@ -445,6 +457,7 @@ test_main (void)
check1 ();
check2 ();
check3 ();
+ check4 ();
printf ("%23s", "");
FOR_EACH_IMPL (impl, 0)

@ -0,0 +1,120 @@
commit 38e0d2479413ccdbc02b4c9e9e246eca31e956c9
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date: Tue Feb 15 08:18:15 2022 -0600
x86: Fallback {str|wcs}cmp RTM in the ncmp overflow case [BZ #28896]
In the overflow fallback strncmp-avx2-rtm and wcsncmp-avx2-rtm would
call strcmp-avx2 and wcscmp-avx2 respectively. This would have
not checks around vzeroupper and would trigger spurious
aborts. This commit fixes that.
test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass on
AVX2 machines with and without RTM.
Co-authored-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit c6272098323153db373f2986c67786ea8c85f1cf)
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index 36ca1a7126047b86..af934d6ccf1fa337 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -105,7 +105,7 @@ CFLAGS-tst-memset-rtm.c += -mrtm
CFLAGS-tst-strchr-rtm.c += -mrtm
CFLAGS-tst-strcpy-rtm.c += -mrtm
CFLAGS-tst-strlen-rtm.c += -mrtm
-CFLAGS-tst-strncmp-rtm.c += -mrtm
+CFLAGS-tst-strncmp-rtm.c += -mrtm -Wno-error
CFLAGS-tst-strrchr-rtm.c += -mrtm
endif
diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c
index 236ad951b5b59cd1..4d0004b58aae428d 100644
--- a/sysdeps/x86/tst-strncmp-rtm.c
+++ b/sysdeps/x86/tst-strncmp-rtm.c
@@ -16,6 +16,7 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include <stdint.h>
#include <tst-string-rtm.h>
#define LOOP 3000
@@ -45,8 +46,22 @@ function (void)
return 1;
}
+__attribute__ ((noinline, noclone))
+static int
+function_overflow (void)
+{
+ if (strncmp (string1, string2, SIZE_MAX) == 0)
+ return 0;
+ else
+ return 1;
+}
+
static int
do_test (void)
{
- return do_test_1 ("strncmp", LOOP, prepare, function);
+ int status = do_test_1 ("strncmp", LOOP, prepare, function);
+ if (status != EXIT_SUCCESS)
+ return status;
+ status = do_test_1 ("strncmp", LOOP, prepare, function_overflow);
+ return status;
}
diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S
index 3dfcb1bf803cf9ec..fa70c994fc25dfd8 100644
--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S
+++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S
@@ -95,7 +95,7 @@ ENTRY (STRCMP)
length to bound a valid memory region. In these cases just use
'wcscmp'. */
shrq $56, %rcx
- jnz __wcscmp_avx2
+ jnz OVERFLOW_STRCMP
# endif
/* Convert units: from wide to byte char. */
shl $2, %RDX_LP
diff --git a/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S b/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S
index 37d1224bb9b7056b..68bad365ba728eec 100644
--- a/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S
+++ b/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S
@@ -1,3 +1,4 @@
#define STRCMP __strncmp_avx2_rtm
#define USE_AS_STRNCMP 1
+#define OVERFLOW_STRCMP __strcmp_avx2_rtm
#include "strcmp-avx2-rtm.S"
diff --git a/sysdeps/x86_64/multiarch/strncmp-avx2.S b/sysdeps/x86_64/multiarch/strncmp-avx2.S
index 1678bcc235a4bc6a..f138e9f1fdcf277c 100644
--- a/sysdeps/x86_64/multiarch/strncmp-avx2.S
+++ b/sysdeps/x86_64/multiarch/strncmp-avx2.S
@@ -1,3 +1,4 @@
#define STRCMP __strncmp_avx2
#define USE_AS_STRNCMP 1
+#define OVERFLOW_STRCMP __strcmp_avx2
#include "strcmp-avx2.S"
diff --git a/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S b/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S
index 4e88c70cc696b82d..f467582cbedd4535 100644
--- a/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S
+++ b/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S
@@ -1,5 +1,5 @@
#define STRCMP __wcsncmp_avx2_rtm
#define USE_AS_STRNCMP 1
#define USE_AS_WCSCMP 1
-
+#define OVERFLOW_STRCMP __wcscmp_avx2_rtm
#include "strcmp-avx2-rtm.S"
diff --git a/sysdeps/x86_64/multiarch/wcsncmp-avx2.S b/sysdeps/x86_64/multiarch/wcsncmp-avx2.S
index 4fa1de4d3f1f97ff..e9ede522b8bde27d 100644
--- a/sysdeps/x86_64/multiarch/wcsncmp-avx2.S
+++ b/sysdeps/x86_64/multiarch/wcsncmp-avx2.S
@@ -1,5 +1,5 @@
#define STRCMP __wcsncmp_avx2
#define USE_AS_STRNCMP 1
#define USE_AS_WCSCMP 1
-
+#define OVERFLOW_STRCMP __wcscmp_avx2
#include "strcmp-avx2.S"

@ -0,0 +1,139 @@
commit d093b677c36ef4b360bf30483b68b95d9f0ad1d2
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date: Fri Feb 18 14:19:15 2022 -0600
x86: Test wcscmp RTM in the wcsncmp overflow case [BZ #28896]
In the overflow fallback strncmp-avx2-rtm and wcsncmp-avx2-rtm would
call strcmp-avx2 and wcscmp-avx2 respectively. This would have
not checks around vzeroupper and would trigger spurious
aborts. This commit fixes that.
test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass on
AVX2 machines with and without RTM.
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit 7835d611af0854e69a0c71e3806f8fe379282d6f)
diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
index af934d6ccf1fa337..cd94e683afd5b4a4 100644
--- a/sysdeps/x86/Makefile
+++ b/sysdeps/x86/Makefile
@@ -95,7 +95,9 @@ tests += \
tst-strcpy-rtm \
tst-strlen-rtm \
tst-strncmp-rtm \
- tst-strrchr-rtm
+ tst-strrchr-rtm \
+ tst-wcsncmp-rtm \
+# tests
CFLAGS-tst-memchr-rtm.c += -mrtm
CFLAGS-tst-memcmp-rtm.c += -mrtm
@@ -107,6 +109,7 @@ CFLAGS-tst-strcpy-rtm.c += -mrtm
CFLAGS-tst-strlen-rtm.c += -mrtm
CFLAGS-tst-strncmp-rtm.c += -mrtm -Wno-error
CFLAGS-tst-strrchr-rtm.c += -mrtm
+CFLAGS-tst-wcsncmp-rtm.c += -mrtm -Wno-error
endif
ifneq ($(enable-cet),no)
diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c
index 4d0004b58aae428d..4e9f094f39c72f67 100644
--- a/sysdeps/x86/tst-strncmp-rtm.c
+++ b/sysdeps/x86/tst-strncmp-rtm.c
@@ -19,18 +19,32 @@
#include <stdint.h>
#include <tst-string-rtm.h>
+#ifdef WIDE
+# define CHAR wchar_t
+# define MEMSET wmemset
+# define STRNCMP wcsncmp
+# define TEST_NAME wcsncmp
+#else /* !WIDE */
+# define CHAR char
+# define MEMSET memset
+# define STRNCMP strncmp
+# define TEST_NAME strncmp
+#endif /* !WIDE */
+
+
+
#define LOOP 3000
#define STRING_SIZE 1024
-char string1[STRING_SIZE];
-char string2[STRING_SIZE];
+CHAR string1[STRING_SIZE];
+CHAR string2[STRING_SIZE];
__attribute__ ((noinline, noclone))
static int
prepare (void)
{
- memset (string1, 'a', STRING_SIZE - 1);
- memset (string2, 'a', STRING_SIZE - 1);
- if (strncmp (string1, string2, STRING_SIZE) == 0)
+ MEMSET (string1, 'a', STRING_SIZE - 1);
+ MEMSET (string2, 'a', STRING_SIZE - 1);
+ if (STRNCMP (string1, string2, STRING_SIZE) == 0)
return EXIT_SUCCESS;
else
return EXIT_FAILURE;
@@ -40,7 +54,7 @@ __attribute__ ((noinline, noclone))
static int
function (void)
{
- if (strncmp (string1, string2, STRING_SIZE) == 0)
+ if (STRNCMP (string1, string2, STRING_SIZE) == 0)
return 0;
else
return 1;
@@ -50,7 +64,7 @@ __attribute__ ((noinline, noclone))
static int
function_overflow (void)
{
- if (strncmp (string1, string2, SIZE_MAX) == 0)
+ if (STRNCMP (string1, string2, SIZE_MAX) == 0)
return 0;
else
return 1;
@@ -59,9 +73,9 @@ function_overflow (void)
static int
do_test (void)
{
- int status = do_test_1 ("strncmp", LOOP, prepare, function);
+ int status = do_test_1 (TEST_NAME, LOOP, prepare, function);
if (status != EXIT_SUCCESS)
return status;
- status = do_test_1 ("strncmp", LOOP, prepare, function_overflow);
+ status = do_test_1 (TEST_NAME, LOOP, prepare, function_overflow);
return status;
}
diff --git a/sysdeps/x86/tst-wcsncmp-rtm.c b/sysdeps/x86/tst-wcsncmp-rtm.c
new file mode 100644
index 0000000000000000..bad3b863782c5e56
--- /dev/null
+++ b/sysdeps/x86/tst-wcsncmp-rtm.c
@@ -0,0 +1,21 @@
+/* Test case for wcsncmp inside a transactionally executing RTM region.
+ 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/>. */
+
+#define WIDE 1
+#include <wchar.h>
+#include "tst-strncmp-rtm.c"

@ -0,0 +1,32 @@
commit 15b00d2af0e56dcc8c244a36d6872d301b0c7185
Author: Noah Goldstein <goldstein.w.n@gmail.com>
Date: Fri Feb 18 17:00:25 2022 -0600
x86: Fix TEST_NAME to make it a string in tst-strncmp-rtm.c
Previously TEST_NAME was passing a function pointer. This didn't fail
because of the -Wno-error flag (to allow for overflow sizes passed
to strncmp/wcsncmp)
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
(cherry picked from commit b98d0bbf747f39770e0caba7e984ce9f8f900330)
diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c
index 4e9f094f39c72f67..aef9866cf2fbe774 100644
--- a/sysdeps/x86/tst-strncmp-rtm.c
+++ b/sysdeps/x86/tst-strncmp-rtm.c
@@ -23,12 +23,12 @@
# define CHAR wchar_t
# define MEMSET wmemset
# define STRNCMP wcsncmp
-# define TEST_NAME wcsncmp
+# define TEST_NAME "wcsncmp"
#else /* !WIDE */
# define CHAR char
# define MEMSET memset
# define STRNCMP strncmp
-# define TEST_NAME strncmp
+# define TEST_NAME "strncmp"
#endif /* !WIDE */

@ -0,0 +1,104 @@
commit 3be79b72d556e3ac37075ad6b99eb5eac18e1402
Author: John David Anglin <danglin@gcc.gnu.org>
Date: Sun Mar 6 15:56:57 2022 +0000
Fix elf/tst-audit2 on hppa
The test elf/tst-audit2 fails on hppa with a segmentation fault in the
long branch stub used to call malloc from calloc. This occurs because
the test is not a PIC executable and calloc is called from the dynamic
linker before the dp register is initialized in _dl_start_user.
The fix is to move the dp register initialization into
elf_machine_runtime_setup. Since the address of $global$ can't be
loaded directly, we continue to use the DT_PLTGOT value from the
the main_map to initialize dp. Since l_main_map is not available
in v2.34 and earlier, we use a new function, elf_machine_main_map,
to find the main map.
diff --git a/sysdeps/hppa/dl-machine.h b/sysdeps/hppa/dl-machine.h
index f048fd20728ccde6..24f0f47d8f1e25cd 100644
--- a/sysdeps/hppa/dl-machine.h
+++ b/sysdeps/hppa/dl-machine.h
@@ -27,6 +27,7 @@
#include <string.h>
#include <link.h>
#include <errno.h>
+#include <ldsodefs.h>
#include <dl-fptr.h>
#include <abort-instr.h>
#include <tls.h>
@@ -159,6 +160,24 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
return (struct fdesc) { value.ip + reloc->r_addend, value.gp };
}
+static inline struct link_map *
+elf_machine_main_map (void)
+{
+ struct link_map *main_map;
+
+#if defined SHARED && IS_IN (rtld)
+ asm (
+" bl 1f,%0\n"
+" addil L'_rtld_local - ($PIC_pcrel$0 - 1),%0\n"
+"1: ldw R'_rtld_local - ($PIC_pcrel$0 - 5)(%%r1),%0\n"
+ : "=r" (main_map) : : "r1");
+#else
+ main_map = NULL;
+#endif
+
+ return main_map;
+}
+
/* Set up the loaded object described by L so its unrelocated PLT
entries will jump to the on-demand fixup code in dl-runtime.c. */
@@ -174,6 +193,15 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
Elf32_Addr i[2];
} sig = {{0x00,0xc0,0xff,0xee, 0xde,0xad,0xbe,0xef}};
+ /* Initialize dp register for main executable. */
+ if (l == elf_machine_main_map ())
+ {
+ register Elf32_Addr dp asm ("%r27");
+
+ dp = D_PTR (l, l_info[DT_PLTGOT]);
+ asm volatile ("" : : "r" (dp));
+ }
+
/* If we don't have a PLT we can just skip all this... */
if (__builtin_expect (l->l_info[DT_JMPREL] == NULL,0))
return lazy;
@@ -336,16 +364,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
its return value is the user program's entry point. */
#define RTLD_START \
-/* Set up dp for any non-PIC lib constructors that may be called. */ \
-static struct link_map * __attribute__((used)) \
-set_dp (struct link_map *map) \
-{ \
- register Elf32_Addr dp asm ("%r27"); \
- dp = D_PTR (map, l_info[DT_PLTGOT]); \
- asm volatile ("" : : "r" (dp)); \
- return map; \
-} \
- \
asm ( \
" .text\n" \
" .globl _start\n" \
@@ -445,14 +463,11 @@ asm ( \
" stw %r24,-44(%sp)\n" \
\
".Lnofix:\n" \
+ /* Call _dl_init(main_map, argc, argv, envp). */ \
" addil LT'_rtld_local,%r19\n" \
" ldw RT'_rtld_local(%r1),%r26\n" \
-" bl set_dp, %r2\n" \
" ldw 0(%r26),%r26\n" \
\
- /* Call _dl_init(_dl_loaded, argc, argv, envp). */ \
-" copy %r28,%r26\n" \
- \
/* envp = argv + argc + 1 */ \
" sh2add %r25,%r24,%r23\n" \
" bl _dl_init,%r2\n" \

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save