summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes2020-01-09 22:55:25 -0500
committerTavian Barnes2020-01-09 22:55:25 -0500
commite12c73e9be304d76039555c2877b1dcecb824718 (patch)
tree8b2f33ea9955ee00401def8b5a4c4ac9e604631f
parentfa4883f399b05063052edbe9da2fd0004c8883d1 (diff)
downloadaur-e12c73e9be304d76039555c2877b1dcecb824718.tar.gz
Bump to 2.30-3
-rw-r--r--.SRCINFO26
-rw-r--r--0001-Revert-elf-Correct-absolute-SHN_ABS-symbol-run-time-.patch194
-rw-r--r--PKGBUILD24
-rw-r--r--bz20338.patch8
-rw-r--r--glibc-34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4.patch4059
-rw-r--r--glibc-a6aaabd036d735a1b412f441bf6c706832655598.patch414
-rw-r--r--sdt-config.h6
-rw-r--r--sdt.h430
8 files changed, 883 insertions, 4278 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 5040f4119429..83329b62f867 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,15 +1,15 @@
pkgbase = arm-linux-gnueabihf-glibc
pkgdesc = GNU C Library (arm-linux-gnueabihf)
- pkgver = 2.29
+ pkgver = 2.30
pkgrel = 3
url = https://www.gnu.org/software/libc/
arch = any
license = GPL
license = LGPL
- makedepends = arm-linux-gnueabihf-gcc-stage2>=8.2.1+20181127
+ makedepends = arm-linux-gnueabihf-gcc-stage2>=9.2.0-4
makedepends = gperf
- depends = arm-linux-gnueabihf-linux-api-headers>=4.17.11-1
- provides = arm-linux-gnueabihf-glibc-headers=2.29
+ depends = arm-linux-gnueabihf-linux-api-headers>=5.3.1-2
+ provides = arm-linux-gnueabihf-glibc-headers=2.30
provides = arm-linux-gnueabihf-eglibc
conflicts = arm-linux-gnueabihf-glibc-headers
conflicts = arm-linux-gnueabihf-eglibc
@@ -17,19 +17,21 @@ pkgbase = arm-linux-gnueabihf-glibc
options = !buildflags
options = !strip
options = staticlibs
- source = https://ftp.gnu.org/gnu/glibc/glibc-2.29.tar.xz
- source = https://ftp.gnu.org/gnu/glibc/glibc-2.29.tar.xz.sig
- source = glibc-34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4.patch
+ source = https://ftp.gnu.org/gnu/glibc/glibc-2.30.tar.xz
+ source = https://ftp.gnu.org/gnu/glibc/glibc-2.30.tar.xz.sig
+ source = glibc-a6aaabd036d735a1b412f441bf6c706832655598.patch
+ source = sdt.h
+ source = sdt-config.h
source = bz20338.patch
- source = 0001-Revert-elf-Correct-absolute-SHN_ABS-symbol-run-time-.patch
source = file-truncated-while-reading-soname-after-patchelf.patch
validpgpkeys = 7273542B39962DF7B299931416792B4EA25340F8
validpgpkeys = BC7C7372637EC10C57D7AA6579C43DFBF1CF2187
- md5sums = e6c279d5b2f0736f740216f152acf974
+ md5sums = 2b1dbdf27b28620752956c061d62f60c
md5sums = SKIP
- md5sums = 35a4ca5cdf86d706e054e02bb31d1616
- md5sums = dc0d3ad59aeaaf591b085a77de6e03e9
- md5sums = af5d3c5227ac639effe39667a43879a1
+ md5sums = 0cdb7529cb9e2965d7ffaa155e1fcf9d
+ md5sums = 91fec3b7e75510ae2ac42533aa2e695e
+ md5sums = 680df504c683640b02ed4a805797c0b2
+ md5sums = 430673eccc78e52c249aa4b0f1786450
md5sums = 0820504d2e83ee15f74a656771361872
pkgname = arm-linux-gnueabihf-glibc
diff --git a/0001-Revert-elf-Correct-absolute-SHN_ABS-symbol-run-time-.patch b/0001-Revert-elf-Correct-absolute-SHN_ABS-symbol-run-time-.patch
deleted file mode 100644
index ba9b874f3617..000000000000
--- a/0001-Revert-elf-Correct-absolute-SHN_ABS-symbol-run-time-.patch
+++ /dev/null
@@ -1,194 +0,0 @@
-From 2cbf10ae2ea9e378ff91b8f5c4d8cb77ed05378e Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= <bpiotrowski@archlinux.org>
-Date: Fri, 10 Aug 2018-2019 14:12:40 +0000
-Subject: [PATCH] Revert "elf: Correct absolute (SHN_ABS) symbol run-time
- calculation [BZ #19818]"
-
-This reverts commit e7feec374c635b6a29d65c39ae5e1855528fed39.
----
- elf/Makefile | 14 ++-----------
- elf/dl-addr.c | 2 --
- elf/tst-absolute-sym-lib.c | 25 ------------------------
- elf/tst-absolute-sym-lib.lds | 19 ------------------
- elf/tst-absolute-sym.c | 38 ------------------------------------
- sysdeps/generic/ldsodefs.h | 3 +--
- 6 files changed, 3 insertions(+), 98 deletions(-)
- delete mode 100644 elf/tst-absolute-sym-lib.c
- delete mode 100644 elf/tst-absolute-sym-lib.lds
- delete mode 100644 elf/tst-absolute-sym.c
-
-diff --git a/elf/Makefile b/elf/Makefile
-index cd0771307f..5084ba4f6f 100644
---- a/elf/Makefile
-+++ b/elf/Makefile
-@@ -186,7 +186,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
- 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-debug1 tst-main1 \
- tst-unwind-ctor tst-unwind-main
- # reldep9
- tests-internal += loadtest unload unload2 circleload1 \
-@@ -272,8 +272,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
- tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \
- tst-latepthreadmod $(tst-tls-many-dynamic-modules) \
- tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \
-- tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \
-- tst-absolute-zero-lib tst-big-note-lib tst-unwind-ctor-lib
-+ tst-main1mod tst-libc_dlvsym-dso tst-unwind-ctor-lib
- # Most modules build with _ISOMAC defined, but those filtered out
- # depend on internal headers.
- modules-names-tests = $(filter-out ifuncmod% tst-libc_dlvsym-dso tst-tlsmod%,\
-@@ -1465,14 +1463,6 @@ tst-main1-no-pie = yes
- LDLIBS-tst-main1 = $(libsupport)
- tst-main1mod.so-no-z-defs = yes
-
--LDLIBS-tst-absolute-sym-lib.so = tst-absolute-sym-lib.lds
--$(objpfx)tst-absolute-sym-lib.so: $(LDLIBS-tst-absolute-sym-lib.so)
--$(objpfx)tst-absolute-sym: $(objpfx)tst-absolute-sym-lib.so
--
--LDLIBS-tst-absolute-zero-lib.so = tst-absolute-zero-lib.lds
--$(objpfx)tst-absolute-zero-lib.so: $(LDLIBS-tst-absolute-zero-lib.so)
--$(objpfx)tst-absolute-zero: $(objpfx)tst-absolute-zero-lib.so
--
- # Both the main program and the DSO for tst-libc_dlvsym need to link
- # against libdl.
- $(objpfx)tst-libc_dlvsym: $(libdl)
-diff --git a/elf/dl-addr.c b/elf/dl-addr.c
-index e6c7d02094..2250617a73 100644
---- a/elf/dl-addr.c
-+++ b/elf/dl-addr.c
-@@ -59,7 +59,6 @@ determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info,
- we can omit that test here. */
- if ((symtab[symndx].st_shndx != SHN_UNDEF
- || symtab[symndx].st_value != 0)
-- && symtab[symndx].st_shndx != SHN_ABS
- && ELFW(ST_TYPE) (symtab[symndx].st_info) != STT_TLS
- && DL_ADDR_SYM_MATCH (match, &symtab[symndx],
- matchsym, addr)
-@@ -92,7 +91,6 @@ determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info,
- && ELFW(ST_TYPE) (symtab->st_info) != STT_TLS
- && (symtab->st_shndx != SHN_UNDEF
- || symtab->st_value != 0)
-- && symtab->st_shndx != SHN_ABS
- && DL_ADDR_SYM_MATCH (match, symtab, matchsym, addr)
- && symtab->st_name < strtabsize)
- matchsym = (ElfW(Sym) *) symtab;
-diff --git a/elf/tst-absolute-sym-lib.c b/elf/tst-absolute-sym-lib.c
-deleted file mode 100644
-index 912cb0048a..0000000000
---- a/elf/tst-absolute-sym-lib.c
-+++ /dev/null
-@@ -1,25 +0,0 @@
--/* BZ #19818 absolute symbol calculation shared module.
-- Copyright (C) 2018-2019 Free Software Foundation, Inc.
-- This file is part of the GNU C Library.
--
-- The GNU C Library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
--
-- The GNU C Library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public
-- License along with the GNU C Library; if not, see
-- <http://www.gnu.org/licenses/>. */
--
--extern char absolute;
--
--void *
--get_absolute (void)
--{
-- return &absolute;
--}
-diff --git a/elf/tst-absolute-sym-lib.lds b/elf/tst-absolute-sym-lib.lds
-deleted file mode 100644
-index d4a4128514..0000000000
---- a/elf/tst-absolute-sym-lib.lds
-+++ /dev/null
-@@ -1,19 +0,0 @@
--/* BZ #19818 absolute symbol calculation linker script.
-- Copyright (C) 2018-2019 Free Software Foundation, Inc.
-- This file is part of the GNU C Library.
--
-- The GNU C Library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
--
-- The GNU C Library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public
-- License along with the GNU C Library; if not, see
-- <http://www.gnu.org/licenses/>. */
--
--"absolute" = 0x55aa;
-diff --git a/elf/tst-absolute-sym.c b/elf/tst-absolute-sym.c
-deleted file mode 100644
-index 111491d159..0000000000
---- a/elf/tst-absolute-sym.c
-+++ /dev/null
-@@ -1,38 +0,0 @@
--/* BZ #19818 absolute symbol calculation main executable.
-- Copyright (C) 2018-2019 Free Software Foundation, Inc.
-- This file is part of the GNU C Library.
--
-- The GNU C Library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
--
-- The GNU C Library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-- Lesser General Public License for more details.
--
-- You should have received a copy of the GNU Lesser General Public
-- License along with the GNU C Library; if not, see
-- <http://www.gnu.org/licenses/>. */
--
--#include <support/check.h>
--#include <support/support.h>
--#include <support/test-driver.h>
--
--void *get_absolute (void);
--
--static int
--do_test (void)
--{
-- void *ref = (void *) 0x55aa;
-- void *ptr;
--
-- ptr = get_absolute ();
-- if (ptr != ref)
-- FAIL_EXIT1 ("Got %p, expected %p\n", ptr, ref);
--
-- return 0;
--}
--
--#include <support/test-driver.c>
-diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
-index 95dc87519b..3cac4fa362 100644
---- a/sysdeps/generic/ldsodefs.h
-+++ b/sysdeps/generic/ldsodefs.h
-@@ -72,8 +72,7 @@ typedef struct link_map *lookup_t;
- if non-NULL. Don't check for NULL map if MAP_SET is TRUE. */
- #define SYMBOL_ADDRESS(map, ref, map_set) \
- ((ref) == NULL ? 0 \
-- : (__glibc_unlikely ((ref)->st_shndx == SHN_ABS) ? 0 \
-- : LOOKUP_VALUE_ADDRESS (map, map_set)) + (ref)->st_value)
-+ : LOOKUP_VALUE_ADDRESS (map, map_set) + (ref)->st_value)
-
- /* On some architectures a pointer to a function is not just a pointer
- to the actual code of the function but rather an architecture
---
-2.18.0
-
diff --git a/PKGBUILD b/PKGBUILD
index a359b18ef130..433acbc6e4df 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -7,32 +7,33 @@
_target="arm-linux-gnueabihf"
pkgname=${_target}-glibc
-pkgver=2.29
+pkgver=2.30
pkgrel=3
pkgdesc="GNU C Library (${_target})"
arch=('any')
url="https://www.gnu.org/software/libc/"
license=(GPL LGPL)
-depends=("${_target}-linux-api-headers>=4.17.11-1")
-makedepends=("${_target}-gcc-stage2>=8.2.1+20181127" gperf)
+depends=("${_target}-linux-api-headers>=5.3.1-2")
+makedepends=("${_target}-gcc-stage2>=9.2.0-4" gperf)
provides=("${_target}-glibc-headers=${pkgver}" "${_target}-eglibc")
conflicts=("${_target}-glibc-headers" "${_target}-eglibc")
replaces=("${_target}-glibc-headers")
options=(!buildflags !strip staticlibs)
-_commit=34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4
+_commit=a6aaabd036d735a1b412f441bf6c706832655598
#source=(git+https://sourceware.org/git/glibc.git#commit=$_commit
source=(https://ftp.gnu.org/gnu/glibc/glibc-$pkgver.tar.xz{,.sig}
glibc-${_commit}.patch
+ sdt.h sdt-config.h
bz20338.patch
- 0001-Revert-elf-Correct-absolute-SHN_ABS-symbol-run-time-.patch
file-truncated-while-reading-soname-after-patchelf.patch)
validpgpkeys=(7273542B39962DF7B299931416792B4EA25340F8 # Carlos O'Donell
BC7C7372637EC10C57D7AA6579C43DFBF1CF2187) # Siddhesh Poyarekar
-md5sums=('e6c279d5b2f0736f740216f152acf974'
+md5sums=('2b1dbdf27b28620752956c061d62f60c'
'SKIP'
- '35a4ca5cdf86d706e054e02bb31d1616'
- 'dc0d3ad59aeaaf591b085a77de6e03e9'
- 'af5d3c5227ac639effe39667a43879a1'
+ '0cdb7529cb9e2965d7ffaa155e1fcf9d'
+ '91fec3b7e75510ae2ac42533aa2e695e'
+ '680df504c683640b02ed4a805797c0b2'
+ '430673eccc78e52c249aa4b0f1786450'
'0820504d2e83ee15f74a656771361872')
prepare() {
@@ -108,4 +109,9 @@ package() {
# Remove unneeded for compilation files
rm -rf "$pkgdir/usr/$_target/"{bin,sbin,etc,share,var}
+
+ # Provide tracing probes to libstdc++ for exceptions, possibly for other
+ # libraries too. Useful for gdb's catch command.
+ install -Dm644 "$srcdir/sdt.h" "$pkgdir/usr/$_target/include/sys/sdt.h"
+ install -Dm644 "$srcdir/sdt-config.h" "$pkgdir/usr/$_target/include/sys/sdt-config.h"
}
diff --git a/bz20338.patch b/bz20338.patch
index d223e9f08882..ddcc3efe4202 100644
--- a/bz20338.patch
+++ b/bz20338.patch
@@ -74,12 +74,12 @@ index b70f6fa..02cd33a 100644
/* Skip leading blanks. */
while (isspace (*p))
++p;
-- } while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
-+ } while (*p == '\0' || *p == '#' /* Ignore empty and comment lines. */
+- } while (*p == '\0' || *p == '#' /* Ignore empty and comment lines. */
++ } while (*p == '\0' || *p == '#' /* Ignore empty and comment lines. */
/* Parse the line. If it is invalid, loop to
get the next line of the file to parse. */
-- ! parse_line (buffer, (void *) resbuf, (void *) buffer, buflen,
-- &errno));
+- || ! parse_line (buffer, (void *) resbuf, (void *) buffer, buflen,
+- &errno));
+ || ! (parse_result = parse_line (p, resbuf,
+ (void *) buffer, buflen,
+ &errno)));
diff --git a/glibc-34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4.patch b/glibc-34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4.patch
deleted file mode 100644
index fa7f94c4a793..000000000000
--- a/glibc-34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4.patch
+++ /dev/null
@@ -1,4059 +0,0 @@
-diff --git a/ChangeLog b/ChangeLog
-index 59dab18463..20b650e026 100644
---- a/ChangeLog
-+++ b/ChangeLog
-@@ -1,3 +1,219 @@
-+2019-06-20 Dmitry V. Levin <ldv@altlinux.org>
-+ Florian Weimer <fweimer@redhat.com>
-+
-+ [BZ #24228]
-+ * libio/genops.c (_IO_unbuffer_all)
-+ [SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)]: Do not attempt to free wide
-+ buffers and access _IO_FILE_complete members of legacy libio streams.
-+ * libio/tst-bz24228.c: New file.
-+ * libio/tst-bz24228.map: Likewise.
-+ * libio/Makefile [build-shared] (tests): Add tst-bz24228.
-+ [build-shared] (generated): Add tst-bz24228.mtrace and
-+ tst-bz24228.check.
-+ [run-built-tests && build-shared] (tests-special): Add
-+ $(objpfx)tst-bz24228-mem.out.
-+ (LDFLAGS-tst-bz24228, tst-bz24228-ENV): New variables.
-+ ($(objpfx)tst-bz24228-mem.out): New rule.
-+
-+2019-03-13 Zack Weinberg <zackw@panix.com>
-+
-+ * scripts/check-obsolete-constructs.py: New test script.
-+ * scripts/check-installed-headers.sh: Remove tests for
-+ obsolete typedefs, superseded by check-obsolete-constructs.py.
-+ * Rules: Run scripts/check-obsolete-constructs.py over $(headers)
-+ as a special test. Update commentary.
-+ * posix/bits/types.h (__SQUAD_TYPE, __S64_TYPE): Define as __int64_t.
-+ (__UQUAD_TYPE, __U64_TYPE): Define as __uint64_t.
-+ Update commentary.
-+ * posix/sys/types.h (__u_intN_t): Remove.
-+ (u_int8_t): Typedef using __uint8_t.
-+ (u_int16_t): Typedef using __uint16_t.
-+ (u_int32_t): Typedef using __uint32_t.
-+ (u_int64_t): Typedef using __uint64_t.
-+
-+2019-04-18 Adhemerval Zanella <adhemerval.zanella@linaro.org>
-+
-+ * malloc/tst-memalign.c (do_test): Disable
-+ -Walloc-size-larger-than= around tests of malloc with negative
-+ sizes.
-+ * malloc/tst-malloc-too-large.c (do_test): Likewise.
-+
-+2019-05-22 Wilco Dijkstra <wdijkstr@arm.com>
-+
-+ [BZ #24531]
-+ * malloc/malloc.c (MAX_TCACHE_COUNT): New define.
-+ (do_set_tcache_count): Only update if count is small enough.
-+ * manual/tunables.texi (glibc.malloc.tcache_count): Document max value.
-+
-+2019-05-15 Mark Wielaard <mark@klomp.org>
-+
-+ [BZ#24476]
-+ * dlfcn/dlerror.c (__dlerror_main_freeres): Guard using
-+ __libc_once_get (once) and static_buf == NULL.
-+ (__dlerror): Check we have a valid key, set result to static_buf
-+ otherwise.
-+
-+2019-05-15 Andreas Schwab <schwab@suse.de>
-+
-+ [BZ #20568]
-+ * libio/wfileops.c (_IO_wfile_sync): Correct last argument to
-+ __codecvt_do_length.
-+ * libio/Makefile (tests): Add tst-wfile-sync.
-+ ($(objpfx)tst-wfile-sync.out): Depend on $(gen-locales).
-+ * libio/tst-wfile-sync.c: New file.
-+ * libio/tst-wfile-sync.input: New file.
-+
-+2019-04-23 Adhemerval Zanella <adhemerval.zanella@linaro.org>
-+
-+ [BZ #18035]
-+ * elf/Makefile (tests-container): Add tst-pldd.
-+ * elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
-+ (E(find_maps)): Avoid use alloca, use default read file operations
-+ instead of explicit LFS names, and fix infinite loop.
-+ * elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
-+ (get_process_info): Use _Static_assert instead of assert, use default
-+ directory operations instead of explicit LFS names, and free some
-+ leadek pointers.
-+ * elf/tst-pldd.c: New file.
-+
-+2019-04-17 Adhemerval Zanella <adhemerval.zanella@linaro.org>
-+
-+ * support/Makefile (libsupport-routines): Add support_subprocess,
-+ xposix_spawn, xposix_spawn_file_actions_addclose, and
-+ xposix_spawn_file_actions_adddup2.
-+ (tst-support_capture_subprocess-ARGS): New rule.
-+ * support/capture_subprocess.h (support_capture_subprogram): New
-+ prototype.
-+ * support/support_capture_subprocess.c (support_capture_subprocess):
-+ Refactor to use support_subprocess and support_capture_poll.
-+ (support_capture_subprogram): New function.
-+ * support/tst-support_capture_subprocess.c (write_mode_to_str,
-+ str_to_write_mode, test_common, parse_int, handle_restart,
-+ do_subprocess, do_subprogram, do_multiple_tests): New functions.
-+ (do_test): Add support_capture_subprogram tests.
-+ * support/subprocess.h: New file.
-+ * support/support_subprocess.c: Likewise.
-+ * support/xposix_spawn.c: Likewise.
-+ * support/xposix_spawn_file_actions_addclose.c: Likewise.
-+ * support/xposix_spawn_file_actions_adddup2.c: Likewise.
-+ * support/xspawn.h: Likewise.
-+
-+2019-04-09 Carlos O'Donell <carlos@redhat.com>
-+ Kwok Cheung Yeung <kcy@codesourcery.com>
-+
-+ [BZ #16573]
-+ * malloc/mtrace.c: Define prototypes for all hooks.
-+ (set_default_hooks): New function.
-+ (set_trace_hooks): Likewise.
-+ (save_default_hooks): Likewise.
-+ (tr_freehook): Use new s*_hooks functions.
-+ (tr_mallochook): Likewise.
-+ (tr_reallochook): Likewise.
-+ (tr_memalignhook): Likewise.
-+ (mtrace): Likewise.
-+ (muntrace): Likewise.
-+
-+2019-04-02 TAMUKI Shoichi <tamuki@linet.gr.jp>
-+
-+ [BZ #22964]
-+ * localedata/locales/ja_JP (LC_TIME): Add entry for the new Japanese
-+ era.
-+
-+2019-03-02 TAMUKI Shoichi <tamuki@linet.gr.jp>
-+
-+ [BZ #24162]
-+ * localedata/locales/ja_JP (LC_TIME): Change the offset for Taisho
-+ gan-nen from 2 to 1. Problem reported by Morimitsu, Junji.
-+
-+2019-03-21 Stefan Liebler <stli@linux.ibm.com>
-+
-+ * sysdeps/s390/dl-procinfo.h (HWCAP_IMPORTANT):
-+ Add HWCAP_S390_VX and HWCAP_S390_VXE.
-+
-+2019-01-31 Paul Eggert <eggert@cs.ucla.edu>
-+
-+ CVE-2019-9169
-+ regex: fix read overrun [BZ #24114]
-+ Problem found by AddressSanitizer, reported by Hongxu Chen in:
-+ https://debbugs.gnu.org/34140
-+ * posix/regexec.c (proceed_next_node):
-+ Do not read past end of input buffer.
-+
-+2019-03-13 Stefan Liebler <stli@linux.ibm.com>
-+
-+ * elf/dl-sysdep.c (_dl_show_auxv): Remove condition and always
-+ call _dl_procinfo.
-+ * sysdeps/unix/sysv/linux/s390/dl-procinfo.h (_dl_procinfo):
-+ Ignore types other than AT_HWCAP.
-+ * sysdeps/sparc/dl-procinfo.h (_dl_procinfo): Likewise.
-+ * sysdeps/unix/sysv/linux/i386/dl-procinfo.h (_dl_procinfo):
-+ Likewise.
-+ * sysdeps/powerpc/dl-procinfo.h (_dl_procinfo): Adjust comment
-+ in the case of falling back to generic output mechanism.
-+ * sysdeps/unix/sysv/linux/arm/dl-procinfo.h (_dl_procinfo):
-+ Likewise.
-+
-+2019-02-15 Florian Weimer <fweimer@redhat.com>
-+
-+ [BZ #24211]
-+ * nptl/pthread_join_common.c (__pthread_timedjoin_ex): Do not read
-+ pd->result after the thread descriptor has been freed.
-+
-+2019-02-08 Florian Weimer <fweimer@redhat.com>
-+
-+ [BZ #24161]
-+ * sysdeps/nptl/fork.h (__run_fork_handlers): Add multiple_threads
-+ argument.
-+ * nptl/register-atfork.c (__run_fork_handlers): Only perform
-+ locking if the new do_locking argument is true.
-+ * sysdeps/nptl/fork.c (__libc_fork): Pass multiple_threads to
-+ __run_fork_handlers.
-+
-+2019-02-07 Stefan Liebler <stli@linux.ibm.com>
-+
-+ [BZ #24180]
-+ * nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock):
-+ Add compiler barriers and comments.
-+
-+2019-02-05 Florian Weimer <fweimer@redhat.com>
-+
-+ [BZ #24164]
-+ arm: Use "nr" constraint for Systemtap probes, to avoid the
-+ compiler using memory operands for constants, due to the "o"
-+ alternative in the default "nor" constraint.
-+ * include/stap-probe.h [USE_STAP_PROBE]: Include
-+ <stap-probe-machine.h>
-+ * sysdeps/generic/stap-probe-machine.h: New file.
-+ * sysdeps/arm/stap-probe-machine.h: Likewise.
-+
-+2019-02-04 H.J. Lu <hongjiu.lu@intel.com>
-+
-+ [BZ #24155]
-+ CVE-2019-7309
-+ * NEWS: Updated for CVE-2019-7309.
-+ * sysdeps/x86_64/memcmp.S: Use RDX_LP for size. Clear the
-+ upper 32 bits of RDX register for x32. Use unsigned Jcc
-+ instructions, instead of signed.
-+ * sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp-2.
-+ * sysdeps/x86_64/x32/tst-size_t-memcmp-2.c: New test.
-+
-+2019-01-31 Carlos O'Donell <carlos@redhat.com>
-+ Torvald Riegel <triegel@redhat.com>
-+ Rik Prohaska <prohaska7@gmail.com>
-+
-+ [BZ# 23844]
-+ * nptl/Makefile (tests): Add tst-rwlock-tryrdlock-stall, and
-+ tst-rwlock-trywrlock-stall.
-+ * nptl/pthread_rwlock_tryrdlock.c (__pthread_rwlock_tryrdlock):
-+ Wake waiters if PTHREAD_RWLOCK_FUTEX_USED is set.
-+ * nptl/pthread_rwlock_trywrlock.c (__pthread_rwlock_trywrlock):
-+ Set __wrphase_fute to 1 only if we started the write phase.
-+ * nptl/tst-rwlock-tryrdlock-stall.c: New file.
-+ * nptl/tst-rwlock-trywrlock-stall.c: New file.
-+ * support/Makefile (libsupport-routines): Add xpthread_rwlock_destroy.
-+ * support/xpthread_rwlock_destroy.c: New file.
-+ * support/xthread.h: Declare xpthread_rwlock_destroy.
-+
- 2019-01-31 Siddhesh Poyarekar <siddhesh@sourceware.org>
-
- * version.h (RELEASE): Set to "stable".
-diff --git a/NEWS b/NEWS
-index 912a9bdc0f..68d88b1036 100644
---- a/NEWS
-+++ b/NEWS
-@@ -4,6 +4,39 @@ See the end for copying conditions.
-
- Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
- using `glibc' in the "product" field.
-+
-+Version 2.29.1
-+
-+Major new features:
-+
-+* The entry for the new Japanese era has been added for ja_JP locale.
-+
-+The following bugs are resolved with this release:
-+
-+ [16573] malloc: Set and reset all hooks for tracing
-+ [18035] Fix pldd hang
-+ [20568] Fix crash in _IO_wfile_sync
-+ [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309)
-+ [24164] Systemtap probes need to use "nr" constraint on 32-bit Arm
-+ [24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2
-+ [24211] Use-after-free in Systemtap probe in pthread_join
-+ [24228] old x86 applications that use legacy libio crash on exit
-+ [24476] dlfcn: Guard __dlerror_main_freeres with __libc_once_get (once)
-+
-+Security related changes:
-+
-+ CVE-2019-7309: x86-64 memcmp used signed Jcc instructions to check
-+ size. For x86-64, memcmp on an object size larger than SSIZE_MAX
-+ has undefined behavior. On x32, the size_t argument may be passed
-+ in the lower 32 bits of the 64-bit RDX register with non-zero upper
-+ 32 bits. When it happened with the sign bit of RDX register set,
-+ memcmp gave the wrong result since it treated the size argument as
-+ zero. Reported by H.J. Lu.
-+
-+ CVE-2019-9169: Attempted case-insensitive regular-expression match
-+ via proceed_next_node in posix/regexec.c leads to heap-based buffer
-+ over-read. Reported by Hongxu Chen.
-+
-
- Version 2.29
-
-diff --git a/Rules b/Rules
-index 1562f2ce6d..16afa6acaa 100644
---- a/Rules
-+++ b/Rules
-@@ -82,7 +82,8 @@ $(common-objpfx)dummy.c:
- common-generated += dummy.o dummy.c
-
- ifneq "$(headers)" ""
--# Special test of all the installed headers in this directory.
-+# Test that all of the headers installed by this directory can be compiled
-+# in isolation.
- tests-special += $(objpfx)check-installed-headers-c.out
- libof-check-installed-headers-c := testsuite
- $(objpfx)check-installed-headers-c.out: \
-@@ -93,6 +94,8 @@ $(objpfx)check-installed-headers-c.out: \
- $(evaluate-test)
-
- ifneq "$(CXX)" ""
-+# If a C++ compiler is available, also test that they can be compiled
-+# in isolation as C++.
- tests-special += $(objpfx)check-installed-headers-cxx.out
- libof-check-installed-headers-cxx := testsuite
- $(objpfx)check-installed-headers-cxx.out: \
-diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c
-index 27376582d0..ca42c126c1 100644
---- a/dlfcn/dlerror.c
-+++ b/dlfcn/dlerror.c
-@@ -72,9 +72,16 @@ __dlerror (void)
- __libc_once (once, init);
-
- /* Get error string. */
-- result = (struct dl_action_result *) __libc_getspecific (key);
-- if (result == NULL)
-- result = &last_result;
-+ if (static_buf != NULL)
-+ result = static_buf;
-+ else
-+ {
-+ /* init () has been run and we don't use the static buffer.
-+ So we have a valid key. */
-+ result = (struct dl_action_result *) __libc_getspecific (key);
-+ if (result == NULL)
-+ result = &last_result;
-+ }
-
- /* Test whether we already returned the string. */
- if (result->returned != 0)
-@@ -230,13 +237,19 @@ free_key_mem (void *mem)
- void
- __dlerror_main_freeres (void)
- {
-- void *mem;
- /* Free the global memory if used. */
- check_free (&last_result);
-- /* Free the TSD memory if used. */
-- mem = __libc_getspecific (key);
-- if (mem != NULL)
-- free_key_mem (mem);
-+
-+ if (__libc_once_get (once) && static_buf == NULL)
-+ {
-+ /* init () has been run and we don't use the static buffer.
-+ So we have a valid key. */
-+ void *mem;
-+ /* Free the TSD memory if used. */
-+ mem = __libc_getspecific (key);
-+ if (mem != NULL)
-+ free_key_mem (mem);
-+ }
- }
-
- struct dlfcn_hook *_dlfcn_hook __attribute__((nocommon));
-diff --git a/elf/Makefile b/elf/Makefile
-index 9cf5cd8dfd..e7457e809f 100644
---- a/elf/Makefile
-+++ b/elf/Makefile
-@@ -194,6 +194,7 @@ tests-internal += loadtest unload unload2 circleload1 \
- tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \
- tst-ptrguard1 tst-stackguard1 tst-libc_dlvsym \
- tst-create_format1
-+tests-container += tst-pldd
- ifeq ($(build-hardcoded-path-in-tests),yes)
- tests += tst-dlopen-aout
- tst-dlopen-aout-no-pie = yes
-diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
-index 5f6c679a3f..5d19b100b2 100644
---- a/elf/dl-sysdep.c
-+++ b/elf/dl-sysdep.c
-@@ -328,14 +328,9 @@ _dl_show_auxv (void)
- assert (AT_NULL == 0);
- assert (AT_IGNORE == 1);
-
-- if (av->a_type == AT_HWCAP || av->a_type == AT_HWCAP2
-- || AT_L1I_CACHEGEOMETRY || AT_L1D_CACHEGEOMETRY
-- || AT_L2_CACHEGEOMETRY || AT_L3_CACHEGEOMETRY)
-- {
-- /* These are handled in a special way per platform. */
-- if (_dl_procinfo (av->a_type, av->a_un.a_val) == 0)
-- continue;
-- }
-+ /* Some entries are handled in a special way per platform. */
-+ if (_dl_procinfo (av->a_type, av->a_un.a_val) == 0)
-+ continue;
-
- if (idx < sizeof (auxvars) / sizeof (auxvars[0])
- && auxvars[idx].form != unknown)
-diff --git a/elf/pldd-xx.c b/elf/pldd-xx.c
-index 547f840ee1..756f6d7a1c 100644
---- a/elf/pldd-xx.c
-+++ b/elf/pldd-xx.c
-@@ -23,10 +23,6 @@
- #define EW_(e, w, t) EW__(e, w, _##t)
- #define EW__(e, w, t) e##w##t
-
--#define pldd_assert(name, exp) \
-- typedef int __assert_##name[((exp) != 0) - 1]
--
--
- struct E(link_map)
- {
- EW(Addr) l_addr;
-@@ -39,12 +35,12 @@ struct E(link_map)
- EW(Addr) l_libname;
- };
- #if CLASS == __ELF_NATIVE_CLASS
--pldd_assert (l_addr, (offsetof (struct link_map, l_addr)
-- == offsetof (struct E(link_map), l_addr)));
--pldd_assert (l_name, (offsetof (struct link_map, l_name)
-- == offsetof (struct E(link_map), l_name)));
--pldd_assert (l_next, (offsetof (struct link_map, l_next)
-- == offsetof (struct E(link_map), l_next)));
-+_Static_assert (offsetof (struct link_map, l_addr)
-+ == offsetof (struct E(link_map), l_addr), "l_addr");
-+_Static_assert (offsetof (struct link_map, l_name)
-+ == offsetof (struct E(link_map), l_name), "l_name");
-+_Static_assert (offsetof (struct link_map, l_next)
-+ == offsetof (struct E(link_map), l_next), "l_next");
- #endif
-
-
-@@ -54,10 +50,10 @@ struct E(libname_list)
- EW(Addr) next;
- };
- #if CLASS == __ELF_NATIVE_CLASS
--pldd_assert (name, (offsetof (struct libname_list, name)
-- == offsetof (struct E(libname_list), name)));
--pldd_assert (next, (offsetof (struct libname_list, next)
-- == offsetof (struct E(libname_list), next)));
-+_Static_assert (offsetof (struct libname_list, name)
-+ == offsetof (struct E(libname_list), name), "name");
-+_Static_assert (offsetof (struct libname_list, next)
-+ == offsetof (struct E(libname_list), next), "next");
- #endif
-
- struct E(r_debug)
-@@ -69,16 +65,17 @@ struct E(r_debug)
- EW(Addr) r_map;
- };
- #if CLASS == __ELF_NATIVE_CLASS
--pldd_assert (r_version, (offsetof (struct r_debug, r_version)
-- == offsetof (struct E(r_debug), r_version)));
--pldd_assert (r_map, (offsetof (struct r_debug, r_map)
-- == offsetof (struct E(r_debug), r_map)));
-+_Static_assert (offsetof (struct r_debug, r_version)
-+ == offsetof (struct E(r_debug), r_version), "r_version");
-+_Static_assert (offsetof (struct r_debug, r_map)
-+ == offsetof (struct E(r_debug), r_map), "r_map");
- #endif
-
-
- static int
-
--E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
-+E(find_maps) (const char *exe, int memfd, pid_t pid, void *auxv,
-+ size_t auxv_size)
- {
- EW(Addr) phdr = 0;
- unsigned int phnum = 0;
-@@ -104,12 +101,9 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
- if (phdr == 0 || phnum == 0 || phent == 0)
- error (EXIT_FAILURE, 0, gettext ("cannot find program header of process"));
-
-- EW(Phdr) *p = alloca (phnum * phent);
-- if (pread64 (memfd, p, phnum * phent, phdr) != phnum * phent)
-- {
-- error (0, 0, gettext ("cannot read program header"));
-- return EXIT_FAILURE;
-- }
-+ EW(Phdr) *p = xmalloc (phnum * phent);
-+ if (pread (memfd, p, phnum * phent, phdr) != phnum * phent)
-+ error (EXIT_FAILURE, 0, gettext ("cannot read program header"));
-
- /* Determine the load offset. We need this for interpreting the
- other program header entries so we do this in a separate loop.
-@@ -129,24 +123,18 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
- if (p[i].p_type == PT_DYNAMIC)
- {
- EW(Dyn) *dyn = xmalloc (p[i].p_filesz);
-- if (pread64 (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr)
-+ if (pread (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr)
- != p[i].p_filesz)
-- {
-- error (0, 0, gettext ("cannot read dynamic section"));
-- return EXIT_FAILURE;
-- }
-+ error (EXIT_FAILURE, 0, gettext ("cannot read dynamic section"));
-
- /* Search for the DT_DEBUG entry. */
- for (unsigned int j = 0; j < p[i].p_filesz / sizeof (EW(Dyn)); ++j)
- if (dyn[j].d_tag == DT_DEBUG && dyn[j].d_un.d_ptr != 0)
- {
- struct E(r_debug) r;
-- if (pread64 (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr)
-+ if (pread (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr)
- != sizeof (r))
-- {
-- error (0, 0, gettext ("cannot read r_debug"));
-- return EXIT_FAILURE;
-- }
-+ error (EXIT_FAILURE, 0, gettext ("cannot read r_debug"));
-
- if (r.r_map != 0)
- {
-@@ -160,13 +148,10 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
- }
- else if (p[i].p_type == PT_INTERP)
- {
-- interp = alloca (p[i].p_filesz);
-- if (pread64 (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr)
-+ interp = xmalloc (p[i].p_filesz);
-+ if (pread (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr)
- != p[i].p_filesz)
-- {
-- error (0, 0, gettext ("cannot read program interpreter"));
-- return EXIT_FAILURE;
-- }
-+ error (EXIT_FAILURE, 0, gettext ("cannot read program interpreter"));
- }
-
- if (list == 0)
-@@ -174,14 +159,16 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
- if (interp == NULL)
- {
- // XXX check whether the executable itself is the loader
-- return EXIT_FAILURE;
-+ exit (EXIT_FAILURE);
- }
-
- // XXX perhaps try finding ld.so and _r_debug in it
--
-- return EXIT_FAILURE;
-+ exit (EXIT_FAILURE);
- }
-
-+ free (p);
-+ free (interp);
-+
- /* Print the PID and program name first. */
- printf ("%lu:\t%s\n", (unsigned long int) pid, exe);
-
-@@ -192,47 +179,27 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
- do
- {
- struct E(link_map) m;
-- if (pread64 (memfd, &m, sizeof (m), list) != sizeof (m))
-- {
-- error (0, 0, gettext ("cannot read link map"));
-- status = EXIT_FAILURE;
-- goto out;
-- }
-+ if (pread (memfd, &m, sizeof (m), list) != sizeof (m))
-+ error (EXIT_FAILURE, 0, gettext ("cannot read link map"));
-
- EW(Addr) name_offset = m.l_name;
-- again:
- while (1)
- {
-- ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
-+ ssize_t n = pread (memfd, tmpbuf.data, tmpbuf.length, name_offset);
- if (n == -1)
-- {
-- error (0, 0, gettext ("cannot read object name"));
-- status = EXIT_FAILURE;
-- goto out;
-- }
-+ error (EXIT_FAILURE, 0, gettext ("cannot read object name"));
-
- if (memchr (tmpbuf.data, '\0', n) != NULL)
- break;
-
- if (!scratch_buffer_grow (&tmpbuf))
-- {
-- error (0, 0, gettext ("cannot allocate buffer for object name"));
-- status = EXIT_FAILURE;
-- goto out;
-- }
-+ error (EXIT_FAILURE, 0,
-+ gettext ("cannot allocate buffer for object name"));
- }
-
-- if (((char *)tmpbuf.data)[0] == '\0' && name_offset == m.l_name
-- && m.l_libname != 0)
-- {
-- /* Try the l_libname element. */
-- struct E(libname_list) ln;
-- if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
-- {
-- name_offset = ln.name;
-- goto again;
-- }
-- }
-+ /* The m.l_name and m.l_libname.name for loader linkmap points to same
-+ values (since BZ#387 fix). Trying to use l_libname name as the
-+ shared object name might lead to an infinite loop (BZ#18035). */
-
- /* Skip over the executable. */
- if (((char *)tmpbuf.data)[0] != '\0')
-@@ -242,7 +209,6 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
- }
- while (list != 0);
-
-- out:
- scratch_buffer_free (&tmpbuf);
- return status;
- }
-diff --git a/elf/pldd.c b/elf/pldd.c
-index f3fac4e487..69629bd5d2 100644
---- a/elf/pldd.c
-+++ b/elf/pldd.c
-@@ -17,23 +17,17 @@
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
--#include <alloca.h>
-+#define _FILE_OFFSET_BITS 64
-+
- #include <argp.h>
--#include <assert.h>
- #include <dirent.h>
--#include <elf.h>
--#include <errno.h>
- #include <error.h>
- #include <fcntl.h>
- #include <libintl.h>
--#include <link.h>
--#include <stddef.h>
- #include <stdio.h>
- #include <stdlib.h>
--#include <string.h>
- #include <unistd.h>
- #include <sys/ptrace.h>
--#include <sys/stat.h>
- #include <sys/wait.h>
- #include <scratch_buffer.h>
-
-@@ -76,14 +70,9 @@ static struct argp argp =
- options, parse_opt, args_doc, doc, NULL, more_help, NULL
- };
-
--// File descriptor of /proc/*/mem file.
--static int memfd;
--
--/* Name of the executable */
--static char *exe;
-
- /* Local functions. */
--static int get_process_info (int dfd, long int pid);
-+static int get_process_info (const char *exe, int dfd, long int pid);
- static void wait_for_ptrace_stop (long int pid);
-
-
-@@ -102,8 +91,10 @@ main (int argc, char *argv[])
- return 1;
- }
-
-- assert (sizeof (pid_t) == sizeof (int)
-- || sizeof (pid_t) == sizeof (long int));
-+ _Static_assert (sizeof (pid_t) == sizeof (int)
-+ || sizeof (pid_t) == sizeof (long int),
-+ "sizeof (pid_t) != sizeof (int) or sizeof (long int)");
-+
- char *endp;
- errno = 0;
- long int pid = strtol (argv[remaining], &endp, 10);
-@@ -119,25 +110,24 @@ main (int argc, char *argv[])
- if (dfd == -1)
- error (EXIT_FAILURE, errno, gettext ("cannot open %s"), buf);
-
-- struct scratch_buffer exebuf;
-- scratch_buffer_init (&exebuf);
-+ /* Name of the executable */
-+ struct scratch_buffer exe;
-+ scratch_buffer_init (&exe);
- ssize_t nexe;
- while ((nexe = readlinkat (dfd, "exe",
-- exebuf.data, exebuf.length)) == exebuf.length)
-+ exe.data, exe.length)) == exe.length)
- {
-- if (!scratch_buffer_grow (&exebuf))
-+ if (!scratch_buffer_grow (&exe))
- {
- nexe = -1;
- break;
- }
- }
- if (nexe == -1)
-- exe = (char *) "<program name undetermined>";
-+ /* Default stack allocation is at least 1024. */
-+ snprintf (exe.data, exe.length, "<program name undetermined>");
- else
-- {
-- exe = exebuf.data;
-- exe[nexe] = '\0';
-- }
-+ ((char*)exe.data)[nexe] = '\0';
-
- /* Stop all threads since otherwise the list of loaded modules might
- change while we are reading it. */
-@@ -155,8 +145,8 @@ main (int argc, char *argv[])
- error (EXIT_FAILURE, errno, gettext ("cannot prepare reading %s/task"),
- buf);
-
-- struct dirent64 *d;
-- while ((d = readdir64 (dir)) != NULL)
-+ struct dirent *d;
-+ while ((d = readdir (dir)) != NULL)
- {
- if (! isdigit (d->d_name[0]))
- continue;
-@@ -182,7 +172,7 @@ main (int argc, char *argv[])
-
- wait_for_ptrace_stop (tid);
-
-- struct thread_list *newp = alloca (sizeof (*newp));
-+ struct thread_list *newp = xmalloc (sizeof (*newp));
- newp->tid = tid;
- newp->next = thread_list;
- thread_list = newp;
-@@ -190,17 +180,22 @@ main (int argc, char *argv[])
-
- closedir (dir);
-
-- int status = get_process_info (dfd, pid);
-+ if (thread_list == NULL)
-+ error (EXIT_FAILURE, 0, gettext ("no valid %s/task entries"), buf);
-+
-+ int status = get_process_info (exe.data, dfd, pid);
-
-- assert (thread_list != NULL);
- do
- {
- ptrace (PTRACE_DETACH, thread_list->tid, NULL, NULL);
-+ struct thread_list *prev = thread_list;
- thread_list = thread_list->next;
-+ free (prev);
- }
- while (thread_list != NULL);
-
- close (dfd);
-+ scratch_buffer_free (&exe);
-
- return status;
- }
-@@ -281,9 +276,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-
-
- static int
--get_process_info (int dfd, long int pid)
-+get_process_info (const char *exe, int dfd, long int pid)
- {
-- memfd = openat (dfd, "mem", O_RDONLY);
-+ /* File descriptor of /proc/<pid>/mem file. */
-+ int memfd = openat (dfd, "mem", O_RDONLY);
- if (memfd == -1)
- goto no_info;
-
-@@ -333,9 +329,9 @@ get_process_info (int dfd, long int pid)
-
- int retval;
- if (e_ident[EI_CLASS] == ELFCLASS32)
-- retval = find_maps32 (pid, auxv, auxv_size);
-+ retval = find_maps32 (exe, memfd, pid, auxv, auxv_size);
- else
-- retval = find_maps64 (pid, auxv, auxv_size);
-+ retval = find_maps64 (exe, memfd, pid, auxv, auxv_size);
-
- free (auxv);
- close (memfd);
-diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c
-new file mode 100644
-index 0000000000..ed19cedd05
---- /dev/null
-+++ b/elf/tst-pldd.c
-@@ -0,0 +1,118 @@
-+/* Basic tests for pldd program.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <stdio.h>
-+#include <string.h>
-+#include <unistd.h>
-+#include <stdint.h>
-+#include <libgen.h>
-+#include <stdbool.h>
-+
-+#include <array_length.h>
-+#include <gnu/lib-names.h>
-+
-+#include <support/subprocess.h>
-+#include <support/capture_subprocess.h>
-+#include <support/check.h>
-+
-+static void
-+target_process (void *arg)
-+{
-+ pause ();
-+}
-+
-+/* The test runs in a container because pldd does not support tracing
-+ a binary started by the loader iself (as with testrun.sh). */
-+
-+static int
-+do_test (void)
-+{
-+ /* Create a copy of current test to check with pldd. */
-+ struct support_subprocess target = support_subprocess (target_process, NULL);
-+
-+ /* Run 'pldd' on test subprocess. */
-+ struct support_capture_subprocess pldd;
-+ {
-+ /* Three digits per byte plus null terminator. */
-+ char pid[3 * sizeof (uint32_t) + 1];
-+ snprintf (pid, array_length (pid), "%d", target.pid);
-+
-+ const char prog[] = "/usr/bin/pldd";
-+
-+ pldd = support_capture_subprogram (prog,
-+ (char *const []) { (char *) prog, pid, NULL });
-+
-+ support_capture_subprocess_check (&pldd, "pldd", 0, sc_allow_stdout);
-+ }
-+
-+ /* Check 'pldd' output. The test is expected to be linked against only
-+ loader and libc. */
-+ {
-+ pid_t pid;
-+ char buffer[512];
-+#define STRINPUT(size) "%" # size "s"
-+
-+ FILE *out = fmemopen (pldd.out.buffer, pldd.out.length, "r");
-+ TEST_VERIFY (out != NULL);
-+
-+ /* First line is in the form of <pid>: <full path of executable> */
-+ TEST_COMPARE (fscanf (out, "%u: " STRINPUT (512), &pid, buffer), 2);
-+
-+ TEST_COMPARE (pid, target.pid);
-+ TEST_COMPARE (strcmp (basename (buffer), "tst-pldd"), 0);
-+
-+ /* It expects only one loader and libc loaded by the program. */
-+ bool interpreter_found = false, libc_found = false;
-+ while (fgets (buffer, array_length (buffer), out) != NULL)
-+ {
-+ /* Ignore vDSO. */
-+ if (buffer[0] != '/')
-+ continue;
-+
-+ /* Remove newline so baseline (buffer) can compare against the
-+ LD_SO and LIBC_SO macros unmodified. */
-+ if (buffer[strlen(buffer)-1] == '\n')
-+ buffer[strlen(buffer)-1] = '\0';
-+
-+ if (strcmp (basename (buffer), LD_SO) == 0)
-+ {
-+ TEST_COMPARE (interpreter_found, false);
-+ interpreter_found = true;
-+ continue;
-+ }
-+
-+ if (strcmp (basename (buffer), LIBC_SO) == 0)
-+ {
-+ TEST_COMPARE (libc_found, false);
-+ libc_found = true;
-+ continue;
-+ }
-+ }
-+ TEST_COMPARE (interpreter_found, true);
-+ TEST_COMPARE (libc_found, true);
-+
-+ fclose (out);
-+ }
-+
-+ support_capture_subprocess_free (&pldd);
-+ support_process_terminate (&target);
-+
-+ return 0;
-+}
-+
-+#include <support/test-driver.c>
-diff --git a/include/stap-probe.h b/include/stap-probe.h
-index c53dd86592..8c26292edd 100644
---- a/include/stap-probe.h
-+++ b/include/stap-probe.h
-@@ -21,6 +21,7 @@
-
- #ifdef USE_STAP_PROBE
-
-+# include <stap-probe-machine.h>
- # include <sys/sdt.h>
-
- /* Our code uses one macro LIBC_PROBE (name, n, arg1, ..., argn).
-diff --git a/libio/Makefile b/libio/Makefile
-index 5bee83e55c..9626a16b01 100644
---- a/libio/Makefile
-+++ b/libio/Makefile
-@@ -65,7 +65,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
- tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
- tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \
- tst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof \
-- tst-sprintf-ub tst-sprintf-chk-ub
-+ tst-sprintf-ub tst-sprintf-chk-ub tst-wfile-sync
-
- tests-internal = tst-vtables tst-vtables-interposed tst-readline
-
-@@ -73,6 +73,9 @@ ifeq (yes,$(build-shared))
- # Add test-fopenloc only if shared library is enabled since it depends on
- # shared localedata objects.
- tests += tst-fopenloc
-+# Add tst-bz24228 only if shared library is enabled since it can never meet its
-+# objective with static linking because the relevant code just is not there.
-+tests += tst-bz24228
- endif
- test-srcs = test-freopen
-
-@@ -157,11 +160,14 @@ CFLAGS-tst_putwc.c += -DOBJPFX=\"$(objpfx)\"
- CFLAGS-tst-sprintf-ub.c += -Wno-restrict
- CFLAGS-tst-sprintf-chk-ub.c += -Wno-restrict
-
-+LDFLAGS-tst-bz24228 = -Wl,--version-script=tst-bz24228.map
-+
- tst_wprintf2-ARGS = "Some Text"
-
- test-fmemopen-ENV = MALLOC_TRACE=$(objpfx)test-fmemopen.mtrace
- tst-fopenloc-ENV = MALLOC_TRACE=$(objpfx)tst-fopenloc.mtrace
- tst-bz22415-ENV = MALLOC_TRACE=$(objpfx)tst-bz22415.mtrace
-+tst-bz24228-ENV = MALLOC_TRACE=$(objpfx)tst-bz24228.mtrace
-
- generated += test-fmemopen.mtrace test-fmemopen.check
- generated += tst-fopenloc.mtrace tst-fopenloc.check
-@@ -170,6 +176,7 @@ generated += tst-bz22415.mtrace tst-bz22415.check
- aux := fileops genops stdfiles stdio strops
-
- ifeq ($(build-shared),yes)
-+generated += tst-bz24228.mtrace tst-bz24228.check
- aux += oldfileops oldstdfiles
- endif
-
-@@ -184,7 +191,8 @@ tests-special += $(objpfx)test-freopen.out $(objpfx)test-fmemopen-mem.out \
- ifeq (yes,$(build-shared))
- # Run tst-fopenloc-cmp.out and tst-openloc-mem.out only if shared
- # library is enabled since they depend on tst-fopenloc.out.
--tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out
-+tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
-+ $(objpfx)tst-bz24228-mem.out
- endif
- endif
-
-@@ -212,6 +220,7 @@ $(objpfx)tst-ungetwc1.out: $(gen-locales)
- $(objpfx)tst-ungetwc2.out: $(gen-locales)
- $(objpfx)tst-widetext.out: $(gen-locales)
- $(objpfx)tst_wprintf2.out: $(gen-locales)
-+$(objpfx)tst-wfile-sync.out: $(gen-locales)
- endif
-
- $(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
-@@ -235,3 +244,7 @@ $(objpfx)tst-fopenloc-mem.out: $(objpfx)tst-fopenloc.out
- $(objpfx)tst-bz22415-mem.out: $(objpfx)tst-bz22415.out
- $(common-objpfx)malloc/mtrace $(objpfx)tst-bz22415.mtrace > $@; \
- $(evaluate-test)
-+
-+$(objpfx)tst-bz24228-mem.out: $(objpfx)tst-bz24228.out
-+ $(common-objpfx)malloc/mtrace $(objpfx)tst-bz24228.mtrace > $@; \
-+ $(evaluate-test)
-diff --git a/libio/genops.c b/libio/genops.c
-index 2a0d9b81df..11a15549e8 100644
---- a/libio/genops.c
-+++ b/libio/genops.c
-@@ -789,9 +789,16 @@ _IO_unbuffer_all (void)
-
- for (fp = (FILE *) _IO_list_all; fp; fp = fp->_chain)
- {
-+ int legacy = 0;
-+
-+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
-+ if (__glibc_unlikely (_IO_vtable_offset (fp) != 0))
-+ legacy = 1;
-+#endif
-+
- if (! (fp->_flags & _IO_UNBUFFERED)
- /* Iff stream is un-orientated, it wasn't used. */
-- && fp->_mode != 0)
-+ && (legacy || fp->_mode != 0))
- {
- #ifdef _IO_MTSAFE_IO
- int cnt;
-@@ -805,7 +812,7 @@ _IO_unbuffer_all (void)
- __sched_yield ();
- #endif
-
-- if (! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
-+ if (! legacy && ! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
- {
- fp->_flags |= _IO_USER_BUF;
-
-@@ -816,7 +823,7 @@ _IO_unbuffer_all (void)
-
- _IO_SETBUF (fp, NULL, 0);
-
-- if (fp->_mode > 0)
-+ if (! legacy && fp->_mode > 0)
- _IO_wsetb (fp, NULL, NULL, 0);
-
- #ifdef _IO_MTSAFE_IO
-@@ -827,7 +834,8 @@ _IO_unbuffer_all (void)
-
- /* Make sure that never again the wide char functions can be
- used. */
-- fp->_mode = -1;
-+ if (! legacy)
-+ fp->_mode = -1;
- }
-
- #ifdef _IO_MTSAFE_IO
-diff --git a/libio/tst-bz24228.c b/libio/tst-bz24228.c
-new file mode 100644
-index 0000000000..6a74500d47
---- /dev/null
-+++ b/libio/tst-bz24228.c
-@@ -0,0 +1,29 @@
-+/* BZ #24228 check for memory corruption in legacy libio
-+ Copyright (C) 2019 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 <mcheck.h>
-+#include <support/test-driver.h>
-+
-+static int
-+do_test (void)
-+{
-+ mtrace ();
-+ return 0;
-+}
-+
-+#include <support/test-driver.c>
-diff --git a/libio/tst-bz24228.map b/libio/tst-bz24228.map
-new file mode 100644
-index 0000000000..4383e0817d
---- /dev/null
-+++ b/libio/tst-bz24228.map
-@@ -0,0 +1,5 @@
-+# Hide the symbol from libc.so.6 to switch to the libio/oldfileops.c
-+# implementation when it is available for the architecture.
-+{
-+ local: _IO_stdin_used;
-+};
-diff --git a/libio/tst-wfile-sync.c b/libio/tst-wfile-sync.c
-new file mode 100644
-index 0000000000..618682064d
---- /dev/null
-+++ b/libio/tst-wfile-sync.c
-@@ -0,0 +1,39 @@
-+/* Test that _IO_wfile_sync does not crash (bug 20568).
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <locale.h>
-+#include <stdio.h>
-+#include <wchar.h>
-+#include <support/check.h>
-+#include <support/xunistd.h>
-+
-+static int
-+do_test (void)
-+{
-+ TEST_VERIFY_EXIT (setlocale (LC_ALL, "de_DE.UTF-8") != NULL);
-+ /* Fill the stdio buffer and advance the read pointer. */
-+ TEST_VERIFY_EXIT (fgetwc (stdin) != WEOF);
-+ /* This calls _IO_wfile_sync, it should not crash. */
-+ TEST_VERIFY_EXIT (setvbuf (stdin, NULL, _IONBF, 0) == 0);
-+ /* Verify that the external file offset has been synchronized. */
-+ TEST_COMPARE (xlseek (0, 0, SEEK_CUR), 1);
-+
-+ return 0;
-+}
-+
-+#include <support/test-driver.c>
-diff --git a/libio/tst-wfile-sync.input b/libio/tst-wfile-sync.input
-new file mode 100644
-index 0000000000..12d0958f7a
---- /dev/null
-+++ b/libio/tst-wfile-sync.input
-@@ -0,0 +1 @@
-+This is a test of _IO_wfile_sync.
-diff --git a/libio/wfileops.c b/libio/wfileops.c
-index 78f20486e5..bab2ba4892 100644
---- a/libio/wfileops.c
-+++ b/libio/wfileops.c
-@@ -508,11 +508,12 @@ _IO_wfile_sync (FILE *fp)
- generate the wide characters up to the current reading
- position. */
- int nread;
--
-+ size_t wnread = (fp->_wide_data->_IO_read_ptr
-+ - fp->_wide_data->_IO_read_base);
- fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
- nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state,
- fp->_IO_read_base,
-- fp->_IO_read_end, delta);
-+ fp->_IO_read_end, wnread);
- fp->_IO_read_ptr = fp->_IO_read_base + nread;
- delta = -(fp->_IO_read_end - fp->_IO_read_base - nread);
- }
-diff --git a/localedata/locales/ja_JP b/localedata/locales/ja_JP
-index 1fd2fee44b..c64aaaff55 100644
---- a/localedata/locales/ja_JP
-+++ b/localedata/locales/ja_JP
-@@ -14946,12 +14946,14 @@ am_pm "<U5348><U524D>";"<U5348><U5F8C>"
-
- t_fmt_ampm "%p%I<U6642>%M<U5206>%S<U79D2>"
-
--era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/
-+era "+:2:2020//01//01:+*:<U4EE4><U548C>:%EC%Ey<U5E74>";/
-+ "+:1:2019//05//01:2019//12//31:<U4EE4><U548C>:%EC<U5143><U5E74>";/
-+ "+:2:1990//01//01:2019//04//30:<U5E73><U6210>:%EC%Ey<U5E74>";/
- "+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/
- "+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/
- "+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/
- "+:2:1913//01//01:1926//12//24:<U5927><U6B63>:%EC%Ey<U5E74>";/
-- "+:2:1912//07//30:1912//12//31:<U5927><U6B63>:%EC<U5143><U5E74>";/
-+ "+:1:1912//07//30:1912//12//31:<U5927><U6B63>:%EC<U5143><U5E74>";/
- "+:6:1873//01//01:1912//07//29:<U660E><U6CBB>:%EC%Ey<U5E74>";/
- "+:1:0001//01//01:1872//12//31:<U897F><U66A6>:%EC%Ey<U5E74>";/
- "+:1:-0001//12//31:-*:<U7D00><U5143><U524D>:%EC%Ey<U5E74>"
-diff --git a/malloc/malloc.c b/malloc/malloc.c
-index feaf7ee0bf..0abd653be2 100644
---- a/malloc/malloc.c
-+++ b/malloc/malloc.c
-@@ -2919,6 +2919,8 @@ typedef struct tcache_perthread_struct
- tcache_entry *entries[TCACHE_MAX_BINS];
- } tcache_perthread_struct;
-
-+#define MAX_TCACHE_COUNT 127 /* Maximum value of counts[] entries. */
-+
- static __thread bool tcache_shutting_down = false;
- static __thread tcache_perthread_struct *tcache = NULL;
-
-@@ -3876,10 +3878,14 @@ _int_malloc (mstate av, size_t bytes)
- {
- victim->fd_nextsize = fwd;
- victim->bk_nextsize = fwd->bk_nextsize;
-+ if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))
-+ malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
- fwd->bk_nextsize = victim;
- victim->bk_nextsize->fd_nextsize = victim;
- }
- bck = fwd->bk;
-+ if (bck->fd != fwd)
-+ malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");
- }
- }
- else
-@@ -5120,8 +5126,11 @@ static inline int
- __always_inline
- do_set_tcache_count (size_t value)
- {
-- LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count);
-- mp_.tcache_count = value;
-+ if (value <= MAX_TCACHE_COUNT)
-+ {
-+ LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count);
-+ mp_.tcache_count = value;
-+ }
- return 1;
- }
-
-diff --git a/malloc/mtrace.c b/malloc/mtrace.c
-index a2facf65ea..2fda262508 100644
---- a/malloc/mtrace.c
-+++ b/malloc/mtrace.c
-@@ -121,6 +121,41 @@ lock_and_info (const void *caller, Dl_info *mem)
- return res;
- }
-
-+static void tr_freehook (void *, const void *);
-+static void * tr_mallochook (size_t, const void *);
-+static void * tr_reallochook (void *, size_t, const void *);
-+static void * tr_memalignhook (size_t, size_t, const void *);
-+
-+/* Set all the default non-trace hooks. */
-+static __always_inline void
-+set_default_hooks (void)
-+{
-+ __free_hook = tr_old_free_hook;
-+ __malloc_hook = tr_old_malloc_hook;
-+ __realloc_hook = tr_old_realloc_hook;
-+ __memalign_hook = tr_old_memalign_hook;
-+}
-+
-+/* Set all of the tracing hooks used for mtrace. */
-+static __always_inline void
-+set_trace_hooks (void)
-+{
-+ __free_hook = tr_freehook;
-+ __malloc_hook = tr_mallochook;
-+ __realloc_hook = tr_reallochook;
-+ __memalign_hook = tr_memalignhook;
-+}
-+
-+/* Save the current set of hooks as the default hooks. */
-+static __always_inline void
-+save_default_hooks (void)
-+{
-+ tr_old_free_hook = __free_hook;
-+ tr_old_malloc_hook = __malloc_hook;
-+ tr_old_realloc_hook = __realloc_hook;
-+ tr_old_memalign_hook = __memalign_hook;
-+}
-+
- static void
- tr_freehook (void *ptr, const void *caller)
- {
-@@ -138,12 +173,12 @@ tr_freehook (void *ptr, const void *caller)
- tr_break ();
- __libc_lock_lock (lock);
- }
-- __free_hook = tr_old_free_hook;
-+ set_default_hooks ();
- if (tr_old_free_hook != NULL)
- (*tr_old_free_hook)(ptr, caller);
- else
- free (ptr);
-- __free_hook = tr_freehook;
-+ set_trace_hooks ();
- __libc_lock_unlock (lock);
- }
-
-@@ -155,12 +190,12 @@ tr_mallochook (size_t size, const void *caller)
- Dl_info mem;
- Dl_info *info = lock_and_info (caller, &mem);
-
-- __malloc_hook = tr_old_malloc_hook;
-+ set_default_hooks ();
- if (tr_old_malloc_hook != NULL)
- hdr = (void *) (*tr_old_malloc_hook)(size, caller);
- else
- hdr = (void *) malloc (size);
-- __malloc_hook = tr_mallochook;
-+ set_trace_hooks ();
-
- tr_where (caller, info);
- /* We could be printing a NULL here; that's OK. */
-@@ -185,16 +220,12 @@ tr_reallochook (void *ptr, size_t size, const void *caller)
- Dl_info mem;
- Dl_info *info = lock_and_info (caller, &mem);
-
-- __free_hook = tr_old_free_hook;
-- __malloc_hook = tr_old_malloc_hook;
-- __realloc_hook = tr_old_realloc_hook;
-+ set_default_hooks ();
- if (tr_old_realloc_hook != NULL)
- hdr = (void *) (*tr_old_realloc_hook)(ptr, size, caller);
- else
- hdr = (void *) realloc (ptr, size);
-- __free_hook = tr_freehook;
-- __malloc_hook = tr_mallochook;
-- __realloc_hook = tr_reallochook;
-+ set_trace_hooks ();
-
- tr_where (caller, info);
- if (hdr == NULL)
-@@ -230,14 +261,12 @@ tr_memalignhook (size_t alignment, size_t size, const void *caller)
- Dl_info mem;
- Dl_info *info = lock_and_info (caller, &mem);
-
-- __memalign_hook = tr_old_memalign_hook;
-- __malloc_hook = tr_old_malloc_hook;
-+ set_default_hooks ();
- if (tr_old_memalign_hook != NULL)
- hdr = (void *) (*tr_old_memalign_hook)(alignment, size, caller);
- else
- hdr = (void *) memalign (alignment, size);
-- __memalign_hook = tr_memalignhook;
-- __malloc_hook = tr_mallochook;
-+ set_trace_hooks ();
-
- tr_where (caller, info);
- /* We could be printing a NULL here; that's OK. */
-@@ -305,14 +334,8 @@ mtrace (void)
- malloc_trace_buffer = mtb;
- setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
- fprintf (mallstream, "= Start\n");
-- tr_old_free_hook = __free_hook;
-- __free_hook = tr_freehook;
-- tr_old_malloc_hook = __malloc_hook;
-- __malloc_hook = tr_mallochook;
-- tr_old_realloc_hook = __realloc_hook;
-- __realloc_hook = tr_reallochook;
-- tr_old_memalign_hook = __memalign_hook;
-- __memalign_hook = tr_memalignhook;
-+ save_default_hooks ();
-+ set_trace_hooks ();
- #ifdef _LIBC
- if (!added_atexit_handler)
- {
-@@ -338,10 +361,7 @@ muntrace (void)
- file. */
- FILE *f = mallstream;
- mallstream = NULL;
-- __free_hook = tr_old_free_hook;
-- __malloc_hook = tr_old_malloc_hook;
-- __realloc_hook = tr_old_realloc_hook;
-- __memalign_hook = tr_old_memalign_hook;
-+ set_default_hooks ();
-
- fprintf (f, "= End\n");
- fclose (f);
-diff --git a/malloc/tst-malloc-too-large.c b/malloc/tst-malloc-too-large.c
-index 15e25f558e..51d42cee81 100644
---- a/malloc/tst-malloc-too-large.c
-+++ b/malloc/tst-malloc-too-large.c
-@@ -72,13 +72,28 @@ test_large_allocations (size_t size)
- void * ptr_to_realloc;
-
- test_setup ();
-+ DIAG_PUSH_NEEDS_COMMENT;
-+#if __GNUC_PREREQ (7, 0)
-+ /* GCC 7 warns about too-large allocations; here we want to test
-+ that they fail. */
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- TEST_VERIFY (malloc (size) == NULL);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
- TEST_VERIFY (errno == ENOMEM);
-
- ptr_to_realloc = malloc (16);
- TEST_VERIFY_EXIT (ptr_to_realloc != NULL);
- test_setup ();
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- TEST_VERIFY (realloc (ptr_to_realloc, size) == NULL);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
- TEST_VERIFY (errno == ENOMEM);
- free (ptr_to_realloc);
-
-@@ -135,7 +150,13 @@ test_large_aligned_allocations (size_t size)
- for (align = 1; align <= pagesize; align *= 2)
- {
- test_setup ();
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- TEST_VERIFY (memalign (align, size) == NULL);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
- TEST_VERIFY (errno == ENOMEM);
-
- /* posix_memalign expects an alignment that is a power of 2 *and* a
-@@ -151,7 +172,13 @@ test_large_aligned_allocations (size_t size)
- if ((size % align) == 0)
- {
- test_setup ();
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- TEST_VERIFY (aligned_alloc (align, size) == NULL);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
- TEST_VERIFY (errno == ENOMEM);
- }
- }
-@@ -159,11 +186,23 @@ test_large_aligned_allocations (size_t size)
- /* Both valloc and pvalloc return page-aligned memory. */
-
- test_setup ();
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- TEST_VERIFY (valloc (size) == NULL);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
- TEST_VERIFY (errno == ENOMEM);
-
- test_setup ();
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- TEST_VERIFY (pvalloc (size) == NULL);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
- TEST_VERIFY (errno == ENOMEM);
- }
-
-diff --git a/malloc/tst-memalign.c b/malloc/tst-memalign.c
-index a6a9140a3d..e7997518cb 100644
---- a/malloc/tst-memalign.c
-+++ b/malloc/tst-memalign.c
-@@ -21,6 +21,7 @@
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
-+#include <libc-diag.h>
-
- static int errors = 0;
-
-@@ -41,9 +42,18 @@ do_test (void)
-
- errno = 0;
-
-+ DIAG_PUSH_NEEDS_COMMENT;
-+#if __GNUC_PREREQ (7, 0)
-+ /* GCC 7 warns about too-large allocations; here we want to test
-+ that they fail. */
-+ DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
-+#endif
- /* An attempt to allocate a huge value should return NULL and set
- errno to ENOMEM. */
- p = memalign (sizeof (void *), -1);
-+#if __GNUC_PREREQ (7, 0)
-+ DIAG_POP_NEEDS_COMMENT;
-+#endif
-
- save = errno;
-
-diff --git a/manual/tunables.texi b/manual/tunables.texi
-index af820820e0..8edfea4edd 100644
---- a/manual/tunables.texi
-+++ b/manual/tunables.texi
-@@ -189,8 +189,8 @@ per-thread cache. The default (and maximum) value is 1032 bytes on
-
- @deftp Tunable glibc.malloc.tcache_count
- The maximum number of chunks of each size to cache. The default is 7.
--There is no upper limit, other than available system memory. If set
--to zero, the per-thread cache is effectively disabled.
-+The upper limit is 127. If set to zero, the per-thread cache is effectively
-+disabled.
-
- The approximate maximum overhead of the per-thread cache is thus equal
- to the number of bins times the chunk count in each bin times the size
-diff --git a/nptl/Makefile b/nptl/Makefile
-index 340282c6cb..0e316edfac 100644
---- a/nptl/Makefile
-+++ b/nptl/Makefile
-@@ -319,7 +319,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
- tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
- tst-cnd-timedwait tst-thrd-detach tst-mtx-basic tst-thrd-sleep \
- tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \
-- tst-rwlock-pwn
-+ tst-rwlock-pwn \
-+ tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall
-
- tests-internal := tst-rwlock19 tst-rwlock20 \
- tst-sem11 tst-sem12 tst-sem13 \
-diff --git a/nptl/pthread_join_common.c b/nptl/pthread_join_common.c
-index ecb78ffba5..366feb376b 100644
---- a/nptl/pthread_join_common.c
-+++ b/nptl/pthread_join_common.c
-@@ -86,6 +86,7 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return,
- pthread_cleanup_pop (0);
- }
-
-+ void *pd_result = pd->result;
- if (__glibc_likely (result == 0))
- {
- /* We mark the thread as terminated and as joined. */
-@@ -93,7 +94,7 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return,
-
- /* Store the return value if the caller is interested. */
- if (thread_return != NULL)
-- *thread_return = pd->result;
-+ *thread_return = pd_result;
-
- /* Free the TCB. */
- __free_tcb (pd);
-@@ -101,7 +102,7 @@ __pthread_timedjoin_ex (pthread_t threadid, void **thread_return,
- else
- pd->joinid = NULL;
-
-- LIBC_PROBE (pthread_join_ret, 3, threadid, result, pd->result);
-+ LIBC_PROBE (pthread_join_ret, 3, threadid, result, pd_result);
-
- return result;
- }
-diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
-index 8fe43b8f0f..bf2869eca2 100644
---- a/nptl/pthread_mutex_trylock.c
-+++ b/nptl/pthread_mutex_trylock.c
-@@ -94,6 +94,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
- &mutex->__data.__list.__next);
-+ /* We need to set op_pending before starting the operation. Also
-+ see comments at ENQUEUE_MUTEX. */
-+ __asm ("" ::: "memory");
-
- oldval = mutex->__data.__lock;
- do
-@@ -119,7 +122,12 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- /* But it is inconsistent unless marked otherwise. */
- mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
-
-+ /* We must not enqueue the mutex before we have acquired it.
-+ Also see comments at ENQUEUE_MUTEX. */
-+ __asm ("" ::: "memory");
- ENQUEUE_MUTEX (mutex);
-+ /* We need to clear op_pending after we enqueue the mutex. */
-+ __asm ("" ::: "memory");
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- /* Note that we deliberately exist here. If we fall
-@@ -135,6 +143,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- int kind = PTHREAD_MUTEX_TYPE (mutex);
- if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP)
- {
-+ /* We do not need to ensure ordering wrt another memory
-+ access. Also see comments at ENQUEUE_MUTEX. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
- NULL);
- return EDEADLK;
-@@ -142,6 +152,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
-
- if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP)
- {
-+ /* We do not need to ensure ordering wrt another memory
-+ access. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
- NULL);
-
-@@ -160,6 +172,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- id, 0);
- if (oldval != 0 && (oldval & FUTEX_OWNER_DIED) == 0)
- {
-+ /* We haven't acquired the lock as it is already acquired by
-+ another owner. We do not need to ensure ordering wrt another
-+ memory access. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- return EBUSY;
-@@ -173,13 +188,20 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- if (oldval == id)
- lll_unlock (mutex->__data.__lock,
- PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
-+ /* FIXME This violates the mutex destruction requirements. See
-+ __pthread_mutex_unlock_full. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
- return ENOTRECOVERABLE;
- }
- }
- while ((oldval & FUTEX_OWNER_DIED) != 0);
-
-+ /* We must not enqueue the mutex before we have acquired it.
-+ Also see comments at ENQUEUE_MUTEX. */
-+ __asm ("" ::: "memory");
- ENQUEUE_MUTEX (mutex);
-+ /* We need to clear op_pending after we enqueue the mutex. */
-+ __asm ("" ::: "memory");
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- mutex->__data.__owner = id;
-@@ -211,10 +233,15 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- }
-
- if (robust)
-- /* Note: robust PI futexes are signaled by setting bit 0. */
-- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
-- (void *) (((uintptr_t) &mutex->__data.__list.__next)
-- | 1));
-+ {
-+ /* Note: robust PI futexes are signaled by setting bit 0. */
-+ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
-+ (void *) (((uintptr_t) &mutex->__data.__list.__next)
-+ | 1));
-+ /* We need to set op_pending before starting the operation. Also
-+ see comments at ENQUEUE_MUTEX. */
-+ __asm ("" ::: "memory");
-+ }
-
- oldval = mutex->__data.__lock;
-
-@@ -223,12 +250,16 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- {
- if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
- {
-+ /* We do not need to ensure ordering wrt another memory
-+ access. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
- return EDEADLK;
- }
-
- if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
- {
-+ /* We do not need to ensure ordering wrt another memory
-+ access. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- /* Just bump the counter. */
-@@ -250,6 +281,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- {
- if ((oldval & FUTEX_OWNER_DIED) == 0)
- {
-+ /* We haven't acquired the lock as it is already acquired by
-+ another owner. We do not need to ensure ordering wrt another
-+ memory access. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- return EBUSY;
-@@ -270,6 +304,9 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- if (INTERNAL_SYSCALL_ERROR_P (e, __err)
- && INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK)
- {
-+ /* The kernel has not yet finished the mutex owner death.
-+ We do not need to ensure ordering wrt another memory
-+ access. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- return EBUSY;
-@@ -287,7 +324,12 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- /* But it is inconsistent unless marked otherwise. */
- mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
-
-+ /* We must not enqueue the mutex before we have acquired it.
-+ Also see comments at ENQUEUE_MUTEX. */
-+ __asm ("" ::: "memory");
- ENQUEUE_MUTEX (mutex);
-+ /* We need to clear op_pending after we enqueue the mutex. */
-+ __asm ("" ::: "memory");
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
-
- /* Note that we deliberately exit here. If we fall
-@@ -310,13 +352,20 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
- PTHREAD_ROBUST_MUTEX_PSHARED (mutex)),
- 0, 0);
-
-+ /* To the kernel, this will be visible after the kernel has
-+ acquired the mutex in the syscall. */
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
- return ENOTRECOVERABLE;
- }
-
- if (robust)
- {
-+ /* We must not enqueue the mutex before we have acquired it.
-+ Also see comments at ENQUEUE_MUTEX. */
-+ __asm ("" ::: "memory");
- ENQUEUE_MUTEX_PI (mutex);
-+ /* We need to clear op_pending after we enqueue the mutex. */
-+ __asm ("" ::: "memory");
- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
- }
-
-diff --git a/nptl/pthread_rwlock_tryrdlock.c b/nptl/pthread_rwlock_tryrdlock.c
-index 368862ff07..2f94f17f36 100644
---- a/nptl/pthread_rwlock_tryrdlock.c
-+++ b/nptl/pthread_rwlock_tryrdlock.c
-@@ -94,15 +94,22 @@ __pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
- /* Same as in __pthread_rwlock_rdlock_full:
- We started the read phase, so we are also responsible for
- updating the write-phase futex. Relaxed MO is sufficient.
-- Note that there can be no other reader that we have to wake
-- because all other readers will see the read phase started by us
-- (or they will try to start it themselves); if a writer started
-- the read phase, we cannot have started it. Furthermore, we
-- cannot discard a PTHREAD_RWLOCK_FUTEX_USED flag because we will
-- overwrite the value set by the most recent writer (or the readers
-- before it in case of explicit hand-over) and we know that there
-- are no waiting readers. */
-- atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0);
-+ We have to do the same steps as a writer would when handing over the
-+ read phase to use because other readers cannot distinguish between
-+ us and the writer.
-+ Note that __pthread_rwlock_tryrdlock callers will not have to be
-+ woken up because they will either see the read phase started by us
-+ or they will try to start it themselves; however, callers of
-+ __pthread_rwlock_rdlock_full just increase the reader count and then
-+ check what state the lock is in, so they cannot distinguish between
-+ us and a writer that acquired and released the lock in the
-+ meantime. */
-+ if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0)
-+ & PTHREAD_RWLOCK_FUTEX_USED) != 0)
-+ {
-+ int private = __pthread_rwlock_get_private (rwlock);
-+ futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private);
-+ }
- }
-
- return 0;
-diff --git a/nptl/pthread_rwlock_trywrlock.c b/nptl/pthread_rwlock_trywrlock.c
-index fd37a71ce4..fae475cc70 100644
---- a/nptl/pthread_rwlock_trywrlock.c
-+++ b/nptl/pthread_rwlock_trywrlock.c
-@@ -46,8 +46,15 @@ __pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
- &rwlock->__data.__readers, &r,
- r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED))
- {
-+ /* We have become the primary writer and we cannot have shared
-+ the PTHREAD_RWLOCK_FUTEX_USED flag with someone else, so we
-+ can simply enable blocking (see full wrlock code). */
- atomic_store_relaxed (&rwlock->__data.__writers_futex, 1);
-- atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
-+ /* If we started a write phase, we need to enable readers to
-+ wait. If we did not, we must not change it because other threads
-+ may have set the PTHREAD_RWLOCK_FUTEX_USED in the meantime. */
-+ if ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
-+ atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
- atomic_store_relaxed (&rwlock->__data.__cur_writer,
- THREAD_GETMEM (THREAD_SELF, tid));
- return 0;
-diff --git a/nptl/register-atfork.c b/nptl/register-atfork.c
-index bc797b761a..80a1becb5f 100644
---- a/nptl/register-atfork.c
-+++ b/nptl/register-atfork.c
-@@ -107,13 +107,14 @@ __unregister_atfork (void *dso_handle)
- }
-
- void
--__run_fork_handlers (enum __run_fork_handler_type who)
-+__run_fork_handlers (enum __run_fork_handler_type who, _Bool do_locking)
- {
- struct fork_handler *runp;
-
- if (who == atfork_run_prepare)
- {
-- lll_lock (atfork_lock, LLL_PRIVATE);
-+ if (do_locking)
-+ lll_lock (atfork_lock, LLL_PRIVATE);
- size_t sl = fork_handler_list_size (&fork_handlers);
- for (size_t i = sl; i > 0; i--)
- {
-@@ -133,7 +134,8 @@ __run_fork_handlers (enum __run_fork_handler_type who)
- else if (who == atfork_run_parent && runp->parent_handler)
- runp->parent_handler ();
- }
-- lll_unlock (atfork_lock, LLL_PRIVATE);
-+ if (do_locking)
-+ lll_unlock (atfork_lock, LLL_PRIVATE);
- }
- }
-
-diff --git a/nptl/tst-rwlock-tryrdlock-stall.c b/nptl/tst-rwlock-tryrdlock-stall.c
-new file mode 100644
-index 0000000000..5e476da2b8
---- /dev/null
-+++ b/nptl/tst-rwlock-tryrdlock-stall.c
-@@ -0,0 +1,355 @@
-+/* Bug 23844: Test for pthread_rwlock_tryrdlock stalls.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+/* For a full analysis see comment:
-+ https://sourceware.org/bugzilla/show_bug.cgi?id=23844#c14
-+
-+ Provided here for reference:
-+
-+ --- Analysis of pthread_rwlock_tryrdlock() stall ---
-+ A read lock begins to execute.
-+
-+ In __pthread_rwlock_rdlock_full:
-+
-+ We can attempt a read lock, but find that the lock is
-+ in a write phase (PTHREAD_RWLOCK_WRPHASE, or WP-bit
-+ is set), and the lock is held by a primary writer
-+ (PTHREAD_RWLOCK_WRLOCKED is set). In this case we must
-+ wait for explicit hand over from the writer to us or
-+ one of the other waiters. The read lock threads are
-+ about to execute:
-+
-+ 341 r = (atomic_fetch_add_acquire (&rwlock->__data.__readers,
-+ 342 (1 << PTHREAD_RWLOCK_READER_SHIFT))
-+ 343 + (1 << PTHREAD_RWLOCK_READER_SHIFT));
-+
-+ An unlock beings to execute.
-+
-+ Then in __pthread_rwlock_wrunlock:
-+
-+ 547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
-+ ...
-+ 549 while (!atomic_compare_exchange_weak_release
-+ 550 (&rwlock->__data.__readers, &r,
-+ 551 ((r ^ PTHREAD_RWLOCK_WRLOCKED)
-+ 552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
-+ 553 : PTHREAD_RWLOCK_WRPHASE))))
-+ 554 {
-+ ...
-+ 556 }
-+
-+ We clear PTHREAD_RWLOCK_WRLOCKED, and if there are
-+ no readers so we leave the lock in PTHRAD_RWLOCK_WRPHASE.
-+
-+ Back in the read lock.
-+
-+ The read lock adjusts __readres as above.
-+
-+ 383 while ((r & PTHREAD_RWLOCK_WRPHASE) != 0
-+ 384 && (r & PTHREAD_RWLOCK_WRLOCKED) == 0)
-+ 385 {
-+ ...
-+ 390 if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, &r,
-+ 391 r ^ PTHREAD_RWLOCK_WRPHASE))
-+ 392 {
-+
-+ And then attemps to start the read phase.
-+
-+ Assume there happens to be a tryrdlock at this point, noting
-+ that PTHREAD_RWLOCK_WRLOCKED is clear, and PTHREAD_RWLOCK_WRPHASE
-+ is 1. So the try lock attemps to start the read phase.
-+
-+ In __pthread_rwlock_tryrdlock:
-+
-+ 44 if ((r & PTHREAD_RWLOCK_WRPHASE) == 0)
-+ 45 {
-+ ...
-+ 49 if (((r & PTHREAD_RWLOCK_WRLOCKED) != 0)
-+ 50 && (rwlock->__data.__flags
-+ 51 == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP))
-+ 52 return EBUSY;
-+ 53 rnew = r + (1 << PTHREAD_RWLOCK_READER_SHIFT);
-+ 54 }
-+ ...
-+ 89 while (!atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers,
-+ 90 &r, rnew));
-+
-+ And succeeds.
-+
-+ Back in the write unlock:
-+
-+ 557 if ((r >> PTHREAD_RWLOCK_READER_SHIFT) != 0)
-+ 558 {
-+ ...
-+ 563 if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0)
-+ 564 & PTHREAD_RWLOCK_FUTEX_USED) != 0)
-+ 565 futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private);
-+ 566 }
-+
-+ We note that PTHREAD_RWLOCK_FUTEX_USED is non-zero
-+ and don't wake anyone. This is OK because we handed
-+ over to the trylock. It will be the trylock's responsibility
-+ to wake any waiters.
-+
-+ Back in the read lock:
-+
-+ The read lock fails to install PTHRAD_REWLOCK_WRPHASE as 0 because
-+ the __readers value was adjusted by the trylock, and so it falls through
-+ to waiting on the lock for explicit handover from either a new writer
-+ or a new reader.
-+
-+ 448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
-+ 449 1 | PTHREAD_RWLOCK_FUTEX_USED,
-+ 450 abstime, private);
-+
-+ We use PTHREAD_RWLOCK_FUTEX_USED to indicate the futex
-+ is in use.
-+
-+ At this point we have readers waiting on the read lock
-+ to unlock. The wrlock is done. The trylock is finishing
-+ the installation of the read phase.
-+
-+ 92 if ((r & PTHREAD_RWLOCK_WRPHASE) != 0)
-+ 93 {
-+ ...
-+ 105 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 0);
-+ 106 }
-+
-+ The trylock does note that we were the one that
-+ installed the read phase, but the comments are not
-+ correct, the execution ordering above shows that
-+ readers might indeed be waiting, and they are.
-+
-+ The atomic_store_relaxed throws away PTHREAD_RWLOCK_FUTEX_USED,
-+ and the waiting reader is never worken becuase as noted
-+ above it is conditional on the futex being used.
-+
-+ The solution is for the trylock thread to inspect
-+ PTHREAD_RWLOCK_FUTEX_USED and wake the waiting readers.
-+
-+ --- Analysis of pthread_rwlock_trywrlock() stall ---
-+
-+ A write lock begins to execute, takes the write lock,
-+ and then releases the lock...
-+
-+ In pthread_rwlock_wrunlock():
-+
-+ 547 unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers);
-+ ...
-+ 549 while (!atomic_compare_exchange_weak_release
-+ 550 (&rwlock->__data.__readers, &r,
-+ 551 ((r ^ PTHREAD_RWLOCK_WRLOCKED)
-+ 552 ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0
-+ 553 : PTHREAD_RWLOCK_WRPHASE))))
-+ 554 {
-+ ...
-+ 556 }
-+
-+ ... leaving it in the write phase with zero readers
-+ (the case where we leave the write phase in place
-+ during a write unlock).
-+
-+ A write trylock begins to execute.
-+
-+ In __pthread_rwlock_trywrlock:
-+
-+ 40 while (((r & PTHREAD_RWLOCK_WRLOCKED) == 0)
-+ 41 && (((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0)
-+ 42 || (prefer_writer && ((r & PTHREAD_RWLOCK_WRPHASE) != 0))))
-+ 43 {
-+
-+ The lock is not locked.
-+
-+ There are no readers.
-+
-+ 45 if (atomic_compare_exchange_weak_acquire (
-+ 46 &rwlock->__data.__readers, &r,
-+ 47 r | PTHREAD_RWLOCK_WRPHASE | PTHREAD_RWLOCK_WRLOCKED))
-+
-+ We atomically install the write phase and we take the
-+ exclusive write lock.
-+
-+ 48 {
-+ 49 atomic_store_relaxed (&rwlock->__data.__writers_futex, 1);
-+
-+ We get this far.
-+
-+ A reader lock begins to execute.
-+
-+ In pthread_rwlock_rdlock:
-+
-+ 437 for (;;)
-+ 438 {
-+ 439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
-+ 440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
-+ 441 {
-+ 442 int private = __pthread_rwlock_get_private (rwlock);
-+ 443 if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0)
-+ 444 && (!atomic_compare_exchange_weak_relaxed
-+ 445 (&rwlock->__data.__wrphase_futex,
-+ 446 &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED)))
-+ 447 continue;
-+ 448 int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex,
-+ 449 1 | PTHREAD_RWLOCK_FUTEX_USED,
-+ 450 abstime, private);
-+
-+ We are in a write phase, so the while() on line 439 is true.
-+
-+ The value of wpf does not have PTHREAD_RWLOCK_FUTEX_USED set
-+ since this is the first reader to lock.
-+
-+ The atomic operation sets wpf with PTHREAD_RELOCK_FUTEX_USED
-+ on the expectation that this reader will be woken during
-+ the handoff.
-+
-+ Back in pthread_rwlock_trywrlock:
-+
-+ 50 atomic_store_relaxed (&rwlock->__data.__wrphase_futex, 1);
-+ 51 atomic_store_relaxed (&rwlock->__data.__cur_writer,
-+ 52 THREAD_GETMEM (THREAD_SELF, tid));
-+ 53 return 0;
-+ 54 }
-+ ...
-+ 57 }
-+
-+ We write 1 to __wrphase_futex discarding PTHREAD_RWLOCK_FUTEX_USED,
-+ and so in the unlock we will not awaken the waiting reader.
-+
-+ The solution to this is to realize that if we did not start the write
-+ phase we need not write 1 or any other value to __wrphase_futex.
-+ This ensures that any readers (which saw __wrphase_futex != 0) can
-+ set PTHREAD_RWLOCK_FUTEX_USED and this can be used at unlock to
-+ wake them.
-+
-+ If we installed the write phase then all other readers are looping
-+ here:
-+
-+ In __pthread_rwlock_rdlock_full:
-+
-+ 437 for (;;)
-+ 438 {
-+ 439 while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex))
-+ 440 | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED))
-+ 441 {
-+ ...
-+ 508 }
-+
-+ waiting for the write phase to be installed or removed before they
-+ can begin waiting on __wrphase_futex (part of the algorithm), or
-+ taking a concurrent read lock, and thus we can safely write 1 to
-+ __wrphase_futex.
-+
-+ If we did not install the write phase then the readers may already
-+ be waiting on the futex, the original writer wrote 1 to __wrphase_futex
-+ as part of starting the write phase, and we cannot also write 1
-+ without loosing the PTHREAD_RWLOCK_FUTEX_USED bit.
-+
-+ ---
-+
-+ Summary for the pthread_rwlock_tryrdlock() stall:
-+
-+ The stall is caused by pthread_rwlock_tryrdlock failing to check
-+ that PTHREAD_RWLOCK_FUTEX_USED is set in the __wrphase_futex futex
-+ and then waking the futex.
-+
-+ The fix for bug 23844 ensures that waiters on __wrphase_futex are
-+ correctly woken. Before the fix the test stalls as readers can
-+ wait forever on __wrphase_futex. */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <pthread.h>
-+#include <support/xthread.h>
-+#include <errno.h>
-+
-+/* We need only one lock to reproduce the issue. We will need multiple
-+ threads to get the exact case where we have a read, try, and unlock
-+ all interleaving to produce the case where the readers are waiting
-+ and the try fails to wake them. */
-+pthread_rwlock_t onelock;
-+
-+/* The number of threads is arbitrary but empirically chosen to have
-+ enough threads that we see the condition where waiting readers are
-+ not woken by a successful tryrdlock. */
-+#define NTHREADS 32
-+
-+_Atomic int do_exit;
-+
-+void *
-+run_loop (void *arg)
-+{
-+ int i = 0, ret;
-+ while (!do_exit)
-+ {
-+ /* Arbitrarily choose if we are the writer or reader. Choose a
-+ high enough ratio of readers to writers to make it likely
-+ that readers block (and eventually are susceptable to
-+ stalling).
-+
-+ If we are a writer, take the write lock, and then unlock.
-+ If we are a reader, try the lock, then lock, then unlock. */
-+ if ((i % 8) != 0)
-+ xpthread_rwlock_wrlock (&onelock);
-+ else
-+ {
-+ if ((ret = pthread_rwlock_tryrdlock (&onelock)) != 0)
-+ {
-+ if (ret == EBUSY)
-+ xpthread_rwlock_rdlock (&onelock);
-+ else
-+ exit (EXIT_FAILURE);
-+ }
-+ }
-+ /* Thread does some work and then unlocks. */
-+ xpthread_rwlock_unlock (&onelock);
-+ i++;
-+ }
-+ return NULL;
-+}
-+
-+int
-+do_test (void)
-+{
-+ int i;
-+ pthread_t tids[NTHREADS];
-+ xpthread_rwlock_init (&onelock, NULL);
-+ for (i = 0; i < NTHREADS; i++)
-+ tids[i] = xpthread_create (NULL, run_loop, NULL);
-+ /* Run for some amount of time. Empirically speaking exercising
-+ the stall via pthread_rwlock_tryrdlock is much harder, and on
-+ a 3.5GHz 4 core x86_64 VM system it takes somewhere around
-+ 20-200s to stall, approaching 100% stall past 200s. We can't
-+ wait that long for a regression test so we just test for 20s,
-+ and expect the stall to happen with a 5-10% chance (enough for
-+ developers to see). */
-+ sleep (20);
-+ /* Then exit. */
-+ printf ("INFO: Exiting...\n");
-+ do_exit = 1;
-+ /* If any readers stalled then we will timeout waiting for them. */
-+ for (i = 0; i < NTHREADS; i++)
-+ xpthread_join (tids[i]);
-+ printf ("INFO: Done.\n");
-+ xpthread_rwlock_destroy (&onelock);
-+ printf ("PASS: No pthread_rwlock_tryrdlock stalls detected.\n");
-+ return 0;
-+}
-+
-+#define TIMEOUT 30
-+#include <support/test-driver.c>
-diff --git a/nptl/tst-rwlock-trywrlock-stall.c b/nptl/tst-rwlock-trywrlock-stall.c
-new file mode 100644
-index 0000000000..14d27cbcbc
---- /dev/null
-+++ b/nptl/tst-rwlock-trywrlock-stall.c
-@@ -0,0 +1,108 @@
-+/* Bug 23844: Test for pthread_rwlock_trywrlock stalls.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+/* For a full analysis see comments in tst-rwlock-tryrdlock-stall.c.
-+
-+ Summary for the pthread_rwlock_trywrlock() stall:
-+
-+ The stall is caused by pthread_rwlock_trywrlock setting
-+ __wrphase_futex futex to 1 and loosing the
-+ PTHREAD_RWLOCK_FUTEX_USED bit.
-+
-+ The fix for bug 23844 ensures that waiters on __wrphase_futex are
-+ correctly woken. Before the fix the test stalls as readers can
-+ wait forever on __wrphase_futex. */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <unistd.h>
-+#include <pthread.h>
-+#include <support/xthread.h>
-+#include <errno.h>
-+
-+/* We need only one lock to reproduce the issue. We will need multiple
-+ threads to get the exact case where we have a read, try, and unlock
-+ all interleaving to produce the case where the readers are waiting
-+ and the try clears the PTHREAD_RWLOCK_FUTEX_USED bit and a
-+ subsequent unlock fails to wake them. */
-+pthread_rwlock_t onelock;
-+
-+/* The number of threads is arbitrary but empirically chosen to have
-+ enough threads that we see the condition where waiting readers are
-+ not woken by a successful unlock. */
-+#define NTHREADS 32
-+
-+_Atomic int do_exit;
-+
-+void *
-+run_loop (void *arg)
-+{
-+ int i = 0, ret;
-+ while (!do_exit)
-+ {
-+ /* Arbitrarily choose if we are the writer or reader. Choose a
-+ high enough ratio of readers to writers to make it likely
-+ that readers block (and eventually are susceptable to
-+ stalling).
-+
-+ If we are a writer, take the write lock, and then unlock.
-+ If we are a reader, try the lock, then lock, then unlock. */
-+ if ((i % 8) != 0)
-+ {
-+ if ((ret = pthread_rwlock_trywrlock (&onelock)) != 0)
-+ {
-+ if (ret == EBUSY)
-+ xpthread_rwlock_wrlock (&onelock);
-+ else
-+ exit (EXIT_FAILURE);
-+ }
-+ }
-+ else
-+ xpthread_rwlock_rdlock (&onelock);
-+ /* Thread does some work and then unlocks. */
-+ xpthread_rwlock_unlock (&onelock);
-+ i++;
-+ }
-+ return NULL;
-+}
-+
-+int
-+do_test (void)
-+{
-+ int i;
-+ pthread_t tids[NTHREADS];
-+ xpthread_rwlock_init (&onelock, NULL);
-+ for (i = 0; i < NTHREADS; i++)
-+ tids[i] = xpthread_create (NULL, run_loop, NULL);
-+ /* Run for some amount of time. The pthread_rwlock_tryrwlock stall
-+ is very easy to trigger and happens in seconds under the test
-+ conditions. */
-+ sleep (10);
-+ /* Then exit. */
-+ printf ("INFO: Exiting...\n");
-+ do_exit = 1;
-+ /* If any readers stalled then we will timeout waiting for them. */
-+ for (i = 0; i < NTHREADS; i++)
-+ xpthread_join (tids[i]);
-+ printf ("INFO: Done.\n");
-+ xpthread_rwlock_destroy (&onelock);
-+ printf ("PASS: No pthread_rwlock_tryrwlock stalls detected.\n");
-+ return 0;
-+}
-+
-+#include <support/test-driver.c>
-diff --git a/posix/bits/types.h b/posix/bits/types.h
-index 27e065c3be..0de6c59bb4 100644
---- a/posix/bits/types.h
-+++ b/posix/bits/types.h
-@@ -87,7 +87,7 @@ __extension__ typedef unsigned long long int __uintmax_t;
- 32 -- "natural" 32-bit type (always int)
- 64 -- "natural" 64-bit type (long or long long)
- LONG32 -- 32-bit type, traditionally long
-- QUAD -- 64-bit type, always long long
-+ QUAD -- 64-bit type, traditionally long long
- WORD -- natural type of __WORDSIZE bits (int or long)
- LONGWORD -- type of __WORDSIZE bits, traditionally long
-
-@@ -113,14 +113,14 @@ __extension__ typedef unsigned long long int __uintmax_t;
- #define __SLONGWORD_TYPE long int
- #define __ULONGWORD_TYPE unsigned long int
- #if __WORDSIZE == 32
--# define __SQUAD_TYPE __quad_t
--# define __UQUAD_TYPE __u_quad_t
-+# define __SQUAD_TYPE __int64_t
-+# define __UQUAD_TYPE __uint64_t
- # define __SWORD_TYPE int
- # define __UWORD_TYPE unsigned int
- # define __SLONG32_TYPE long int
- # define __ULONG32_TYPE unsigned long int
--# define __S64_TYPE __quad_t
--# define __U64_TYPE __u_quad_t
-+# define __S64_TYPE __int64_t
-+# define __U64_TYPE __uint64_t
- /* We want __extension__ before typedef's that use nonstandard base types
- such as `long long' in C89 mode. */
- # define __STD_TYPE __extension__ typedef
-diff --git a/posix/regexec.c b/posix/regexec.c
-index 91d5a797b8..084b1222d9 100644
---- a/posix/regexec.c
-+++ b/posix/regexec.c
-@@ -1293,8 +1293,10 @@ proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
- else if (naccepted)
- {
- char *buf = (char *) re_string_get_buffer (&mctx->input);
-- if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
-- naccepted) != 0)
-+ if (mctx->input.valid_len - *pidx < naccepted
-+ || (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
-+ naccepted)
-+ != 0))
- return -1;
- }
- }
-diff --git a/posix/sys/types.h b/posix/sys/types.h
-index 27129c5c23..0e37b1ce6a 100644
---- a/posix/sys/types.h
-+++ b/posix/sys/types.h
-@@ -154,37 +154,20 @@ typedef unsigned int uint;
-
- #include <bits/stdint-intn.h>
-
--#if !__GNUC_PREREQ (2, 7)
--
- /* These were defined by ISO C without the first `_'. */
--typedef unsigned char u_int8_t;
--typedef unsigned short int u_int16_t;
--typedef unsigned int u_int32_t;
--# if __WORDSIZE == 64
--typedef unsigned long int u_int64_t;
--# else
--__extension__ typedef unsigned long long int u_int64_t;
--# endif
--
--typedef int register_t;
--
--#else
--
--/* For GCC 2.7 and later, we can use specific type-size attributes. */
--# define __u_intN_t(N, MODE) \
-- typedef unsigned int u_int##N##_t __attribute__ ((__mode__ (MODE)))
--
--__u_intN_t (8, __QI__);
--__u_intN_t (16, __HI__);
--__u_intN_t (32, __SI__);
--__u_intN_t (64, __DI__);
-+typedef __uint8_t u_int8_t;
-+typedef __uint16_t u_int16_t;
-+typedef __uint32_t u_int32_t;
-+typedef __uint64_t u_int64_t;
-
-+#if __GNUC_PREREQ (2, 7)
- typedef int register_t __attribute__ ((__mode__ (__word__)));
--
-+#else
-+typedef int register_t;
-+#endif
-
- /* Some code from BIND tests this macro to see if the types above are
- defined. */
--#endif
- #define __BIT_TYPES_DEFINED__ 1
-
-
-diff --git a/scripts/check-installed-headers.sh b/scripts/check-installed-headers.sh
-index 8e7beffd82..63bc8d4fa6 100644
---- a/scripts/check-installed-headers.sh
-+++ b/scripts/check-installed-headers.sh
-@@ -16,11 +16,9 @@
- # License along with the GNU C Library; if not, see
- # <http://www.gnu.org/licenses/>.
-
--# Check installed headers for cleanliness. For each header, confirm
--# that it's possible to compile a file that includes that header and
--# does nothing else, in several different compilation modes. Also,
--# scan the header for a set of obsolete typedefs that should no longer
--# appear.
-+# For each installed header, confirm that it's possible to compile a
-+# file that includes that header and does nothing else, in several
-+# different compilation modes.
-
- # These compilation switches assume GCC or compatible, which is probably
- # fine since we also assume that when _building_ glibc.
-@@ -31,13 +29,6 @@ cxx_modes="-std=c++98 -std=gnu++98 -std=c++11 -std=gnu++11"
- # These are probably the most commonly used three.
- lib_modes="-D_DEFAULT_SOURCE=1 -D_GNU_SOURCE=1 -D_XOPEN_SOURCE=700"
-
--# sys/types.h+bits/types.h have to define the obsolete types.
--# rpc(svc)/* have the obsolete types too deeply embedded in their API
--# to remove.
--skip_obsolete_type_check='*/sys/types.h|*/bits/types.h|*/rpc/*|*/rpcsvc/*'
--obsolete_type_re=\
--'\<((__)?(quad_t|u(short|int|long|_(char|short|int([0-9]+_t)?|long|quad_t))))\>'
--
- if [ $# -lt 3 ]; then
- echo "usage: $0 c|c++ \"compile command\" header header header..." >&2
- exit 2
-@@ -46,14 +37,10 @@ case "$1" in
- (c)
- lang_modes="$c_modes"
- cih_test_c=$(mktemp ${TMPDIR-/tmp}/cih_test_XXXXXX.c)
-- already="$skip_obsolete_type_check"
- ;;
- (c++)
- lang_modes="$cxx_modes"
- cih_test_c=$(mktemp ${TMPDIR-/tmp}/cih_test_XXXXXX.cc)
-- # The obsolete-type check can be skipped for C++; it is
-- # sufficient to do it for C.
-- already="*"
- ;;
- (*)
- echo "usage: $0 c|c++ \"compile command\" header header header..." >&2
-@@ -151,22 +138,8 @@ $expanded_lib_mode
- int avoid_empty_translation_unit;
- EOF
- if $cc_cmd -fsyntax-only $lang_mode "$cih_test_c" 2>&1
-- then
-- includes=$($cc_cmd -fsyntax-only -H $lang_mode \
-- "$cih_test_c" 2>&1 | sed -ne 's/^[.][.]* //p')
-- for h in $includes; do
-- # Don't repeat work.
-- eval 'case "$h" in ('"$already"') continue;; esac'
--
-- if grep -qE "$obsolete_type_re" "$h"; then
-- echo "*** Obsolete types detected:"
-- grep -HE "$obsolete_type_re" "$h"
-- failed=1
-- fi
-- already="$already|$h"
-- done
-- else
-- failed=1
-+ then :
-+ else failed=1
- fi
- done
- done
-diff --git a/scripts/check-obsolete-constructs.py b/scripts/check-obsolete-constructs.py
-new file mode 100755
-index 0000000000..ce5c72251f
---- /dev/null
-+++ b/scripts/check-obsolete-constructs.py
-@@ -0,0 +1,466 @@
-+#! /usr/bin/python3
-+# Copyright (C) 2019 Free Software Foundation, Inc.
-+# This file is part of the GNU C Library.
-+#
-+# The GNU C Library is free software; you can redistribute it and/or
-+# modify it under the terms of the GNU Lesser General Public
-+# License as published by the Free Software Foundation; either
-+# version 2.1 of the License, or (at your option) any later version.
-+#
-+# The GNU C Library is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+# Lesser General Public License for more details.
-+#
-+# You should have received a copy of the GNU Lesser General Public
-+# License along with the GNU C Library; if not, see
-+# <http://www.gnu.org/licenses/>.
-+
-+"""Verifies that installed headers do not use any obsolete constructs:
-+ * legacy BSD typedefs superseded by <stdint.h>:
-+ ushort uint ulong u_char u_short u_int u_long u_intNN_t quad_t u_quad_t
-+ (sys/types.h is allowed to _define_ these types, but not to use them
-+ to define anything else).
-+"""
-+
-+import argparse
-+import collections
-+import re
-+import sys
-+
-+# Simplified lexical analyzer for C preprocessing tokens.
-+# Does not implement trigraphs.
-+# Does not implement backslash-newline in the middle of any lexical
-+# item other than a string literal.
-+# Does not implement universal-character-names in identifiers.
-+# Treats prefixed strings (e.g. L"...") as two tokens (L and "...")
-+# Accepts non-ASCII characters only within comments and strings.
-+
-+# Caution: The order of the outermost alternation matters.
-+# STRING must be before BAD_STRING, CHARCONST before BAD_CHARCONST,
-+# BLOCK_COMMENT before BAD_BLOCK_COM before PUNCTUATOR, and OTHER must
-+# be last.
-+# Caution: There should be no capturing groups other than the named
-+# captures in the outermost alternation.
-+
-+# For reference, these are all of the C punctuators as of C11:
-+# [ ] ( ) { } , ; ? ~
-+# ! != * *= / /= ^ ^= = ==
-+# # ##
-+# % %= %> %: %:%:
-+# & &= &&
-+# | |= ||
-+# + += ++
-+# - -= -- ->
-+# . ...
-+# : :>
-+# < <% <: << <<= <=
-+# > >= >> >>=
-+
-+# The BAD_* tokens are not part of the official definition of pp-tokens;
-+# they match unclosed strings, character constants, and block comments,
-+# so that the regex engine doesn't have to backtrack all the way to the
-+# beginning of a broken construct and then emit dozens of junk tokens.
-+
-+PP_TOKEN_RE_ = re.compile(r"""
-+ (?P<STRING> \"(?:[^\"\\\r\n]|\\(?:[\r\n -~]|\r\n))*\")
-+ |(?P<BAD_STRING> \"(?:[^\"\\\r\n]|\\[ -~])*)
-+ |(?P<CHARCONST> \'(?:[^\'\\\r\n]|\\(?:[\r\n -~]|\r\n))*\')
-+ |(?P<BAD_CHARCONST> \'(?:[^\'\\\r\n]|\\[ -~])*)
-+ |(?P<BLOCK_COMMENT> /\*(?:\*(?!/)|[^*])*\*/)
-+ |(?P<BAD_BLOCK_COM> /\*(?:\*(?!/)|[^*])*\*?)
-+ |(?P<LINE_COMMENT> //[^\r\n]*)
-+ |(?P<IDENT> [_a-zA-Z][_a-zA-Z0-9]*)
-+ |(?P<PP_NUMBER> \.?[0-9](?:[0-9a-df-oq-zA-DF-OQ-Z_.]|[eEpP][+-]?)*)
-+ |(?P<PUNCTUATOR>
-+ [,;?~(){}\[\]]
-+ | [!*/^=]=?
-+ | \#\#?
-+ | %(?:[=>]|:(?:%:)?)?
-+ | &[=&]?
-+ |\|[=|]?
-+ |\+[=+]?
-+ | -[=->]?
-+ |\.(?:\.\.)?
-+ | :>?
-+ | <(?:[%:]|<(?:=|<=?)?)?
-+ | >(?:=|>=?)?)
-+ |(?P<ESCNL> \\(?:\r|\n|\r\n))
-+ |(?P<WHITESPACE> [ \t\n\r\v\f]+)
-+ |(?P<OTHER> .)
-+""", re.DOTALL | re.VERBOSE)
-+
-+HEADER_NAME_RE_ = re.compile(r"""
-+ < [^>\r\n]+ >
-+ | " [^"\r\n]+ "
-+""", re.DOTALL | re.VERBOSE)
-+
-+ENDLINE_RE_ = re.compile(r"""\r|\n|\r\n""")
-+
-+# based on the sample code in the Python re documentation
-+Token_ = collections.namedtuple("Token", (
-+ "kind", "text", "line", "column", "context"))
-+Token_.__doc__ = """
-+ One C preprocessing token, comment, or chunk of whitespace.
-+ 'kind' identifies the token type, which will be one of:
-+ STRING, CHARCONST, BLOCK_COMMENT, LINE_COMMENT, IDENT,
-+ PP_NUMBER, PUNCTUATOR, ESCNL, WHITESPACE, HEADER_NAME,
-+ or OTHER. The BAD_* alternatives in PP_TOKEN_RE_ are
-+ handled within tokenize_c, below.
-+
-+ 'text' is the sequence of source characters making up the token;
-+ no decoding whatsoever is performed.
-+
-+ 'line' and 'column' give the position of the first character of the
-+ token within the source file. They are both 1-based.
-+
-+ 'context' indicates whether or not this token occurred within a
-+ preprocessing directive; it will be None for running text,
-+ '<null>' for the leading '#' of a directive line (because '#'
-+ all by itself on a line is a "null directive"), or the name of
-+ the directive for tokens within a directive line, starting with
-+ the IDENT for the name itself.
-+"""
-+
-+def tokenize_c(file_contents, reporter):
-+ """Yield a series of Token objects, one for each preprocessing
-+ token, comment, or chunk of whitespace within FILE_CONTENTS.
-+ The REPORTER object is expected to have one method,
-+ reporter.error(token, message), which will be called to
-+ indicate a lexical error at the position of TOKEN.
-+ If MESSAGE contains the four-character sequence '{!r}', that
-+ is expected to be replaced by repr(token.text).
-+ """
-+
-+ Token = Token_
-+ PP_TOKEN_RE = PP_TOKEN_RE_
-+ ENDLINE_RE = ENDLINE_RE_
-+ HEADER_NAME_RE = HEADER_NAME_RE_
-+
-+ line_num = 1
-+ line_start = 0
-+ pos = 0
-+ limit = len(file_contents)
-+ directive = None
-+ at_bol = True
-+ while pos < limit:
-+ if directive == "include":
-+ mo = HEADER_NAME_RE.match(file_contents, pos)
-+ if mo:
-+ kind = "HEADER_NAME"
-+ directive = "after_include"
-+ else:
-+ mo = PP_TOKEN_RE.match(file_contents, pos)
-+ kind = mo.lastgroup
-+ if kind != "WHITESPACE":
-+ directive = "after_include"
-+ else:
-+ mo = PP_TOKEN_RE.match(file_contents, pos)
-+ kind = mo.lastgroup
-+
-+ text = mo.group()
-+ line = line_num
-+ column = mo.start() - line_start
-+ adj_line_start = 0
-+ # only these kinds can contain a newline
-+ if kind in ("WHITESPACE", "BLOCK_COMMENT", "LINE_COMMENT",
-+ "STRING", "CHARCONST", "BAD_BLOCK_COM", "ESCNL"):
-+ for tmo in ENDLINE_RE.finditer(text):
-+ line_num += 1
-+ adj_line_start = tmo.end()
-+ if adj_line_start:
-+ line_start = mo.start() + adj_line_start
-+
-+ # Track whether or not we are scanning a preprocessing directive.
-+ if kind == "LINE_COMMENT" or (kind == "WHITESPACE" and adj_line_start):
-+ at_bol = True
-+ directive = None
-+ else:
-+ if kind == "PUNCTUATOR" and text == "#" and at_bol:
-+ directive = "<null>"
-+ elif kind == "IDENT" and directive == "<null>":
-+ directive = text
-+ at_bol = False
-+
-+ # Report ill-formed tokens and rewrite them as their well-formed
-+ # equivalents, so downstream processing doesn't have to know about them.
-+ # (Rewriting instead of discarding provides better error recovery.)
-+ if kind == "BAD_BLOCK_COM":
-+ reporter.error(Token("BAD_BLOCK_COM", "", line, column+1, ""),
-+ "unclosed block comment")
-+ text += "*/"
-+ kind = "BLOCK_COMMENT"
-+ elif kind == "BAD_STRING":
-+ reporter.error(Token("BAD_STRING", "", line, column+1, ""),
-+ "unclosed string")
-+ text += "\""
-+ kind = "STRING"
-+ elif kind == "BAD_CHARCONST":
-+ reporter.error(Token("BAD_CHARCONST", "", line, column+1, ""),
-+ "unclosed char constant")
-+ text += "'"
-+ kind = "CHARCONST"
-+
-+ tok = Token(kind, text, line, column+1,
-+ "include" if directive == "after_include" else directive)
-+ # Do not complain about OTHER tokens inside macro definitions.
-+ # $ and @ appear in macros defined by headers intended to be
-+ # included from assembly language, e.g. sysdeps/mips/sys/asm.h.
-+ if kind == "OTHER" and directive != "define":
-+ self.error(tok, "stray {!r} in program")
-+
-+ yield tok
-+ pos = mo.end()
-+
-+#
-+# Base and generic classes for individual checks.
-+#
-+
-+class ConstructChecker:
-+ """Scan a stream of C preprocessing tokens and possibly report
-+ problems with them. The REPORTER object passed to __init__ has
-+ one method, reporter.error(token, message), which should be
-+ called to indicate a problem detected at the position of TOKEN.
-+ If MESSAGE contains the four-character sequence '{!r}' then that
-+ will be replaced with a textual representation of TOKEN.
-+ """
-+ def __init__(self, reporter):
-+ self.reporter = reporter
-+
-+ def examine(self, tok):
-+ """Called once for each token in a header file.
-+ Call self.reporter.error if a problem is detected.
-+ """
-+ raise NotImplementedError
-+
-+ def eof(self):
-+ """Called once at the end of the stream. Subclasses need only
-+ override this if it might have something to do."""
-+ pass
-+
-+class NoCheck(ConstructChecker):
-+ """Generic checker class which doesn't do anything. Substitute this
-+ class for a real checker when a particular check should be skipped
-+ for some file."""
-+
-+ def examine(self, tok):
-+ pass
-+
-+#
-+# Check for obsolete type names.
-+#
-+
-+# The obsolete type names we're looking for:
-+OBSOLETE_TYPE_RE_ = re.compile(r"""\A
-+ (__)?
-+ ( quad_t
-+ | u(?: short | int | long
-+ | _(?: char | short | int(?:[0-9]+_t)? | long | quad_t )))
-+\Z""", re.VERBOSE)
-+
-+class ObsoleteNotAllowed(ConstructChecker):
-+ """Don't allow any use of the obsolete typedefs."""
-+ def examine(self, tok):
-+ if OBSOLETE_TYPE_RE_.match(tok.text):
-+ self.reporter.error(tok, "use of {!r}")
-+
-+class ObsoletePrivateDefinitionsAllowed(ConstructChecker):
-+ """Allow definitions of the private versions of the
-+ obsolete typedefs; that is, 'typedef [anything] __obsolete;'
-+ """
-+ def __init__(self, reporter):
-+ super().__init__(reporter)
-+ self.in_typedef = False
-+ self.prev_token = None
-+
-+ def examine(self, tok):
-+ # bits/types.h hides 'typedef' in a macro sometimes.
-+ if (tok.kind == "IDENT"
-+ and tok.text in ("typedef", "__STD_TYPE")
-+ and tok.context is None):
-+ self.in_typedef = True
-+ elif tok.kind == "PUNCTUATOR" and tok.text == ";" and self.in_typedef:
-+ self.in_typedef = False
-+ if self.prev_token.kind == "IDENT":
-+ m = OBSOLETE_TYPE_RE_.match(self.prev_token.text)
-+ if m and m.group(1) != "__":
-+ self.reporter.error(self.prev_token, "use of {!r}")
-+ self.prev_token = None
-+ else:
-+ self._check_prev()
-+
-+ self.prev_token = tok
-+
-+ def eof(self):
-+ self._check_prev()
-+
-+ def _check_prev(self):
-+ if (self.prev_token is not None
-+ and self.prev_token.kind == "IDENT"
-+ and OBSOLETE_TYPE_RE_.match(self.prev_token.text)):
-+ self.reporter.error(self.prev_token, "use of {!r}")
-+
-+class ObsoletePublicDefinitionsAllowed(ConstructChecker):
-+ """Allow definitions of the public versions of the obsolete
-+ typedefs. Only specific forms of definition are allowed:
-+
-+ typedef __obsolete obsolete; // identifiers must agree
-+ typedef __uintN_t u_intN_t; // N must agree
-+ typedef unsigned long int ulong;
-+ typedef unsigned short int ushort;
-+ typedef unsigned int uint;
-+ """
-+ def __init__(self, reporter):
-+ super().__init__(reporter)
-+ self.typedef_tokens = []
-+
-+ def examine(self, tok):
-+ if tok.kind in ("WHITESPACE", "BLOCK_COMMENT",
-+ "LINE_COMMENT", "NL", "ESCNL"):
-+ pass
-+
-+ elif (tok.kind == "IDENT" and tok.text == "typedef"
-+ and tok.context is None):
-+ if self.typedef_tokens:
-+ self.reporter.error(tok, "typedef inside typedef")
-+ self._reset()
-+ self.typedef_tokens.append(tok)
-+
-+ elif tok.kind == "PUNCTUATOR" and tok.text == ";":
-+ self._finish()
-+
-+ elif self.typedef_tokens:
-+ self.typedef_tokens.append(tok)
-+
-+ def eof(self):
-+ self._reset()
-+
-+ def _reset(self):
-+ while self.typedef_tokens:
-+ tok = self.typedef_tokens.pop(0)
-+ if tok.kind == "IDENT" and OBSOLETE_TYPE_RE_.match(tok.text):
-+ self.reporter.error(tok, "use of {!r}")
-+
-+ def _finish(self):
-+ if not self.typedef_tokens: return
-+ if self.typedef_tokens[-1].kind == "IDENT":
-+ m = OBSOLETE_TYPE_RE_.match(self.typedef_tokens[-1].text)
-+ if m:
-+ if self._permissible_public_definition(m):
-+ self.typedef_tokens.clear()
-+ self._reset()
-+
-+ def _permissible_public_definition(self, m):
-+ if m.group(1) == "__": return False
-+ name = m.group(2)
-+ toks = self.typedef_tokens
-+ ntok = len(toks)
-+ if ntok == 3 and toks[1].kind == "IDENT":
-+ defn = toks[1].text
-+ n = OBSOLETE_TYPE_RE_.match(defn)
-+ if n and n.group(1) == "__" and n.group(2) == name:
-+ return True
-+
-+ if (name[:5] == "u_int" and name[-2:] == "_t"
-+ and defn[:6] == "__uint" and defn[-2:] == "_t"
-+ and name[5:-2] == defn[6:-2]):
-+ return True
-+
-+ return False
-+
-+ if (name == "ulong" and ntok == 5
-+ and toks[1].kind == "IDENT" and toks[1].text == "unsigned"
-+ and toks[2].kind == "IDENT" and toks[2].text == "long"
-+ and toks[3].kind == "IDENT" and toks[3].text == "int"):
-+ return True
-+
-+ if (name == "ushort" and ntok == 5
-+ and toks[1].kind == "IDENT" and toks[1].text == "unsigned"
-+ and toks[2].kind == "IDENT" and toks[2].text == "short"
-+ and toks[3].kind == "IDENT" and toks[3].text == "int"):
-+ return True
-+
-+ if (name == "uint" and ntok == 4
-+ and toks[1].kind == "IDENT" and toks[1].text == "unsigned"
-+ and toks[2].kind == "IDENT" and toks[2].text == "int"):
-+ return True
-+
-+ return False
-+
-+def ObsoleteTypedefChecker(reporter, fname):
-+ """Factory: produce an instance of the appropriate
-+ obsolete-typedef checker for FNAME."""
-+
-+ # The obsolete rpc/ and rpcsvc/ headers are allowed to use the
-+ # obsolete types, because it would be more trouble than it's
-+ # worth to remove them from headers that we intend to stop
-+ # installing eventually anyway.
-+ if (fname.startswith("rpc/")
-+ or fname.startswith("rpcsvc/")
-+ or "/rpc/" in fname
-+ or "/rpcsvc/" in fname):
-+ return NoCheck(reporter)
-+
-+ # bits/types.h is allowed to define the __-versions of the
-+ # obsolete types.
-+ if (fname == "bits/types.h"
-+ or fname.endswith("/bits/types.h")):
-+ return ObsoletePrivateDefinitionsAllowed(reporter)
-+
-+ # sys/types.h is allowed to use the __-versions of the
-+ # obsolete types, but only to define the unprefixed versions.
-+ if (fname == "sys/types.h"
-+ or fname.endswith("/sys/types.h")):
-+ return ObsoletePublicDefinitionsAllowed(reporter)
-+
-+ return ObsoleteNotAllowed(reporter)
-+
-+#
-+# Master control
-+#
-+
-+class HeaderChecker:
-+ """Perform all of the checks on each header. This is also the
-+ "reporter" object expected by tokenize_c and ConstructChecker.
-+ """
-+ def __init__(self):
-+ self.fname = None
-+ self.status = 0
-+
-+ def error(self, tok, message):
-+ self.status = 1
-+ if '{!r}' in message:
-+ message = message.format(tok.text)
-+ sys.stderr.write("{}:{}:{}: error: {}\n".format(
-+ self.fname, tok.line, tok.column, message))
-+
-+ def check(self, fname):
-+ self.fname = fname
-+ try:
-+ with open(fname, "rt") as fp:
-+ contents = fp.read()
-+ except OSError as e:
-+ sys.stderr.write("{}: {}\n".format(fname, e.strerror))
-+ self.status = 1
-+ return
-+
-+ typedef_checker = ObsoleteTypedefChecker(self, self.fname)
-+
-+ for tok in tokenize_c(contents, self):
-+ typedef_checker.examine(tok)
-+
-+def main():
-+ ap = argparse.ArgumentParser(description=__doc__)
-+ ap.add_argument("headers", metavar="header", nargs="+",
-+ help="one or more headers to scan for obsolete constructs")
-+ args = ap.parse_args()
-+
-+ checker = HeaderChecker()
-+ for fname in args.headers:
-+ # Headers whose installed name begins with "finclude/" contain
-+ # Fortran, not C, and this program should completely ignore them.
-+ if not (fname.startswith("finclude/") or "/finclude/" in fname):
-+ checker.check(fname)
-+ sys.exit(checker.status)
-+
-+main()
-diff --git a/support/Makefile b/support/Makefile
-index 432cf2fe6c..8d61de6c57 100644
---- a/support/Makefile
-+++ b/support/Makefile
-@@ -63,6 +63,7 @@ libsupport-routines = \
- support_record_failure \
- support_run_diff \
- support_shared_allocate \
-+ support_subprocess \
- support_test_compare_blob \
- support_test_compare_failure \
- support_test_compare_string \
-@@ -129,6 +130,7 @@ libsupport-routines = \
- xpthread_mutexattr_settype \
- xpthread_once \
- xpthread_rwlock_init \
-+ xpthread_rwlock_destroy \
- xpthread_rwlock_rdlock \
- xpthread_rwlock_unlock \
- xpthread_rwlock_wrlock \
-@@ -147,6 +149,9 @@ libsupport-routines = \
- xsignal \
- xsigstack \
- xsocket \
-+ xposix_spawn \
-+ xposix_spawn_file_actions_addclose \
-+ xposix_spawn_file_actions_adddup2 \
- xstrdup \
- xstrndup \
- xsymlink \
-@@ -222,4 +227,6 @@ endif
-
- $(objpfx)tst-support_format_dns_packet: $(common-objpfx)resolv/libresolv.so
-
-+tst-support_capture_subprocess-ARGS = -- $(host-test-program-cmd)
-+
- include ../Rules
-diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h
-index 2dce42e3a3..2832cfc635 100644
---- a/support/capture_subprocess.h
-+++ b/support/capture_subprocess.h
-@@ -35,6 +35,12 @@ struct support_capture_subprocess
- struct support_capture_subprocess support_capture_subprocess
- (void (*callback) (void *), void *closure);
-
-+/* Issue FILE with ARGV arguments by using posix_spawn and capture standard
-+ output, standard error, and the exit status. The out.buffer and err.buffer
-+ are handle as support_capture_subprocess. */
-+struct support_capture_subprocess support_capture_subprogram
-+ (const char *file, char *const argv[]);
-+
- /* Deallocate the subprocess data captured by
- support_capture_subprocess. */
- void support_capture_subprocess_free (struct support_capture_subprocess *);
-diff --git a/support/subprocess.h b/support/subprocess.h
-new file mode 100644
-index 0000000000..c031878d94
---- /dev/null
-+++ b/support/subprocess.h
-@@ -0,0 +1,49 @@
-+/* Create a subprocess.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#ifndef SUPPORT_SUBPROCESS_H
-+#define SUPPORT_SUBPROCESS_H
-+
-+#include <sys/types.h>
-+
-+struct support_subprocess
-+{
-+ int stdout_pipe[2];
-+ int stderr_pipe[2];
-+ pid_t pid;
-+};
-+
-+/* Invoke CALLBACK (CLOSURE) in a subprocess created with fork and return
-+ its PID, a pipe redirected to STDOUT, and a pipe redirected to STDERR. */
-+struct support_subprocess support_subprocess
-+ (void (*callback) (void *), void *closure);
-+
-+/* Issue FILE with ARGV arguments by using posix_spawn and return is PID, a
-+ pipe redirected to STDOUT, and a pipe redirected to STDERR. */
-+struct support_subprocess support_subprogram
-+ (const char *file, char *const argv[]);
-+
-+/* Wait for the subprocess indicated by PROC::PID. Return the status
-+ indicate by waitpid call. */
-+int support_process_wait (struct support_subprocess *proc);
-+
-+/* Terminate the subprocess indicated by PROC::PID, first with a SIGTERM and
-+ then with a SIGKILL. Return the status as for waitpid call. */
-+int support_process_terminate (struct support_subprocess *proc);
-+
-+#endif
-diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c
-index 167514faf1..948ce5a0c6 100644
---- a/support/support_capture_subprocess.c
-+++ b/support/support_capture_subprocess.c
-@@ -16,6 +16,7 @@
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-+#include <support/subprocess.h>
- #include <support/capture_subprocess.h>
-
- #include <errno.h>
-@@ -23,6 +24,7 @@
- #include <support/check.h>
- #include <support/xunistd.h>
- #include <support/xsocket.h>
-+#include <support/xspawn.h>
-
- static void
- transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream)
-@@ -50,59 +52,53 @@ transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream)
- }
- }
-
--struct support_capture_subprocess
--support_capture_subprocess (void (*callback) (void *), void *closure)
-+static void
-+support_capture_poll (struct support_capture_subprocess *result,
-+ struct support_subprocess *proc)
- {
-- struct support_capture_subprocess result;
-- xopen_memstream (&result.out);
-- xopen_memstream (&result.err);
--
-- int stdout_pipe[2];
-- xpipe (stdout_pipe);
-- TEST_VERIFY (stdout_pipe[0] > STDERR_FILENO);
-- TEST_VERIFY (stdout_pipe[1] > STDERR_FILENO);
-- int stderr_pipe[2];
-- xpipe (stderr_pipe);
-- TEST_VERIFY (stderr_pipe[0] > STDERR_FILENO);
-- TEST_VERIFY (stderr_pipe[1] > STDERR_FILENO);
--
-- TEST_VERIFY (fflush (stdout) == 0);
-- TEST_VERIFY (fflush (stderr) == 0);
--
-- pid_t pid = xfork ();
-- if (pid == 0)
-- {
-- xclose (stdout_pipe[0]);
-- xclose (stderr_pipe[0]);
-- xdup2 (stdout_pipe[1], STDOUT_FILENO);
-- xdup2 (stderr_pipe[1], STDERR_FILENO);
-- xclose (stdout_pipe[1]);
-- xclose (stderr_pipe[1]);
-- callback (closure);
-- _exit (0);
-- }
-- xclose (stdout_pipe[1]);
-- xclose (stderr_pipe[1]);
--
- struct pollfd fds[2] =
- {
-- { .fd = stdout_pipe[0], .events = POLLIN },
-- { .fd = stderr_pipe[0], .events = POLLIN },
-+ { .fd = proc->stdout_pipe[0], .events = POLLIN },
-+ { .fd = proc->stderr_pipe[0], .events = POLLIN },
- };
-
- do
- {
- xpoll (fds, 2, -1);
-- transfer ("stdout", &fds[0], &result.out);
-- transfer ("stderr", &fds[1], &result.err);
-+ transfer ("stdout", &fds[0], &result->out);
-+ transfer ("stderr", &fds[1], &result->err);
- }
- while (fds[0].events != 0 || fds[1].events != 0);
-- xclose (stdout_pipe[0]);
-- xclose (stderr_pipe[0]);
-
-- xfclose_memstream (&result.out);
-- xfclose_memstream (&result.err);
-- xwaitpid (pid, &result.status, 0);
-+ xfclose_memstream (&result->out);
-+ xfclose_memstream (&result->err);
-+
-+ result->status = support_process_wait (proc);
-+}
-+
-+struct support_capture_subprocess
-+support_capture_subprocess (void (*callback) (void *), void *closure)
-+{
-+ struct support_capture_subprocess result;
-+ xopen_memstream (&result.out);
-+ xopen_memstream (&result.err);
-+
-+ struct support_subprocess proc = support_subprocess (callback, closure);
-+
-+ support_capture_poll (&result, &proc);
-+ return result;
-+}
-+
-+struct support_capture_subprocess
-+support_capture_subprogram (const char *file, char *const argv[])
-+{
-+ struct support_capture_subprocess result;
-+ xopen_memstream (&result.out);
-+ xopen_memstream (&result.err);
-+
-+ struct support_subprocess proc = support_subprogram (file, argv);
-+
-+ support_capture_poll (&result, &proc);
- return result;
- }
-
-diff --git a/support/support_subprocess.c b/support/support_subprocess.c
-new file mode 100644
-index 0000000000..0c8cc6af30
---- /dev/null
-+++ b/support/support_subprocess.c
-@@ -0,0 +1,152 @@
-+/* Create subprocess.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <stdio.h>
-+#include <signal.h>
-+#include <time.h>
-+#include <sys/wait.h>
-+#include <stdbool.h>
-+#include <support/xspawn.h>
-+#include <support/check.h>
-+#include <support/xunistd.h>
-+#include <support/subprocess.h>
-+
-+static struct support_subprocess
-+support_suprocess_init (void)
-+{
-+ struct support_subprocess result;
-+
-+ xpipe (result.stdout_pipe);
-+ TEST_VERIFY (result.stdout_pipe[0] > STDERR_FILENO);
-+ TEST_VERIFY (result.stdout_pipe[1] > STDERR_FILENO);
-+
-+ xpipe (result.stderr_pipe);
-+ TEST_VERIFY (result.stderr_pipe[0] > STDERR_FILENO);
-+ TEST_VERIFY (result.stderr_pipe[1] > STDERR_FILENO);
-+
-+ TEST_VERIFY (fflush (stdout) == 0);
-+ TEST_VERIFY (fflush (stderr) == 0);
-+
-+ return result;
-+}
-+
-+struct support_subprocess
-+support_subprocess (void (*callback) (void *), void *closure)
-+{
-+ struct support_subprocess result = support_suprocess_init ();
-+
-+ result.pid = xfork ();
-+ if (result.pid == 0)
-+ {
-+ xclose (result.stdout_pipe[0]);
-+ xclose (result.stderr_pipe[0]);
-+ xdup2 (result.stdout_pipe[1], STDOUT_FILENO);
-+ xdup2 (result.stderr_pipe[1], STDERR_FILENO);
-+ xclose (result.stdout_pipe[1]);
-+ xclose (result.stderr_pipe[1]);
-+ callback (closure);
-+ _exit (0);
-+ }
-+ xclose (result.stdout_pipe[1]);
-+ xclose (result.stderr_pipe[1]);
-+
-+ return result;
-+}
-+
-+struct support_subprocess
-+support_subprogram (const char *file, char *const argv[])
-+{
-+ struct support_subprocess result = support_suprocess_init ();
-+
-+ posix_spawn_file_actions_t fa;
-+ /* posix_spawn_file_actions_init does not fail. */
-+ posix_spawn_file_actions_init (&fa);
-+
-+ xposix_spawn_file_actions_addclose (&fa, result.stdout_pipe[0]);
-+ xposix_spawn_file_actions_addclose (&fa, result.stderr_pipe[0]);
-+ xposix_spawn_file_actions_adddup2 (&fa, result.stdout_pipe[1], STDOUT_FILENO);
-+ xposix_spawn_file_actions_adddup2 (&fa, result.stderr_pipe[1], STDERR_FILENO);
-+ xposix_spawn_file_actions_addclose (&fa, result.stdout_pipe[1]);
-+ xposix_spawn_file_actions_addclose (&fa, result.stderr_pipe[1]);
-+
-+ result.pid = xposix_spawn (file, &fa, NULL, argv, NULL);
-+
-+ xclose (result.stdout_pipe[1]);
-+ xclose (result.stderr_pipe[1]);
-+
-+ return result;
-+}
-+
-+int
-+support_process_wait (struct support_subprocess *proc)
-+{
-+ xclose (proc->stdout_pipe[0]);
-+ xclose (proc->stderr_pipe[0]);
-+
-+ int status;
-+ xwaitpid (proc->pid, &status, 0);
-+ return status;
-+}
-+
-+
-+static bool
-+support_process_kill (int pid, int signo, int *status)
-+{
-+ /* Kill the whole process group. */
-+ kill (-pid, signo);
-+ /* In case setpgid failed in the child, kill it individually too. */
-+ kill (pid, signo);
-+
-+ /* Wait for it to terminate. */
-+ pid_t killed;
-+ for (int i = 0; i < 5; ++i)
-+ {
-+ int status;
-+ killed = xwaitpid (pid, &status, WNOHANG|WUNTRACED);
-+ if (killed != 0)
-+ break;
-+
-+ /* Delay, give the system time to process the kill. If the
-+ nanosleep() call return prematurely, all the better. We
-+ won't restart it since this probably means the child process
-+ finally died. */
-+ nanosleep (&((struct timespec) { 0, 100000000 }), NULL);
-+ }
-+ if (killed != 0 && killed != pid)
-+ return false;
-+
-+ return true;
-+}
-+
-+int
-+support_process_terminate (struct support_subprocess *proc)
-+{
-+ xclose (proc->stdout_pipe[0]);
-+ xclose (proc->stderr_pipe[0]);
-+
-+ int status;
-+ pid_t killed = xwaitpid (proc->pid, &status, WNOHANG|WUNTRACED);
-+ if (killed != 0 && killed == proc->pid)
-+ return status;
-+
-+ /* Subprocess is still running, terminate it. */
-+ if (!support_process_kill (proc->pid, SIGTERM, &status) )
-+ support_process_kill (proc->pid, SIGKILL, &status);
-+
-+ return status;
-+}
-diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c
-index d8ba42ea8b..ab363e41ac 100644
---- a/support/tst-support_capture_subprocess.c
-+++ b/support/tst-support_capture_subprocess.c
-@@ -23,8 +23,20 @@
- #include <support/capture_subprocess.h>
- #include <support/check.h>
- #include <support/support.h>
-+#include <support/temp_file.h>
- #include <sys/wait.h>
- #include <unistd.h>
-+#include <paths.h>
-+#include <getopt.h>
-+#include <limits.h>
-+#include <errno.h>
-+#include <array_length.h>
-+
-+/* Nonzero if the program gets called via 'exec'. */
-+static int restart;
-+
-+/* Hold the four initial argument used to respawn the process. */
-+static char *initial_argv[5];
-
- /* Write one byte at *P to FD and advance *P. Do nothing if *P is
- '\0'. */
-@@ -42,6 +54,30 @@ transfer (const unsigned char **p, int fd)
- enum write_mode { out_first, err_first, interleave,
- write_mode_last = interleave };
-
-+static const char *
-+write_mode_to_str (enum write_mode mode)
-+{
-+ switch (mode)
-+ {
-+ case out_first: return "out_first";
-+ case err_first: return "err_first";
-+ case interleave: return "interleave";
-+ default: return "write_mode_last";
-+ }
-+}
-+
-+static enum write_mode
-+str_to_write_mode (const char *mode)
-+{
-+ if (strcmp (mode, "out_first") == 0)
-+ return out_first;
-+ else if (strcmp (mode, "err_first") == 0)
-+ return err_first;
-+ else if (strcmp (mode, "interleave") == 0)
-+ return interleave;
-+ return write_mode_last;
-+}
-+
- /* Describe what to write in the subprocess. */
- struct test
- {
-@@ -52,11 +88,9 @@ struct test
- int status;
- };
-
--/* For use with support_capture_subprocess. */
--static void
--callback (void *closure)
-+_Noreturn static void
-+test_common (const struct test *test)
- {
-- const struct test *test = closure;
- bool mode_ok = false;
- switch (test->write_mode)
- {
-@@ -95,6 +129,40 @@ callback (void *closure)
- exit (test->status);
- }
-
-+static int
-+parse_int (const char *str)
-+{
-+ char *endptr;
-+ long int ret = strtol (str, &endptr, 10);
-+ TEST_COMPARE (errno, 0);
-+ TEST_VERIFY (ret >= 0 && ret <= INT_MAX);
-+ return ret;
-+}
-+
-+/* For use with support_capture_subprogram. */
-+_Noreturn static void
-+handle_restart (char *out, char *err, const char *write_mode,
-+ const char *signal, const char *status)
-+{
-+ struct test test =
-+ {
-+ out,
-+ err,
-+ str_to_write_mode (write_mode),
-+ parse_int (signal),
-+ parse_int (status)
-+ };
-+ test_common (&test);
-+}
-+
-+/* For use with support_capture_subprocess. */
-+_Noreturn static void
-+callback (void *closure)
-+{
-+ const struct test *test = closure;
-+ test_common (test);
-+}
-+
- /* Create a heap-allocated random string of letters. */
- static char *
- random_string (size_t length)
-@@ -130,12 +198,59 @@ check_stream (const char *what, const struct xmemstream *stream,
- }
- }
-
-+static struct support_capture_subprocess
-+do_subprocess (struct test *test)
-+{
-+ return support_capture_subprocess (callback, test);
-+}
-+
-+static struct support_capture_subprocess
-+do_subprogram (const struct test *test)
-+{
-+ /* Three digits per byte plus null terminator. */
-+ char signalstr[3 * sizeof(int) + 1];
-+ snprintf (signalstr, sizeof (signalstr), "%d", test->signal);
-+ char statusstr[3 * sizeof(int) + 1];
-+ snprintf (statusstr, sizeof (statusstr), "%d", test->status);
-+
-+ int argc = 0;
-+ enum {
-+ /* 4 elements from initial_argv (path to ld.so, '--library-path', the
-+ path', and application name'), 2 for restart argument ('--direct',
-+ '--restart'), 5 arguments plus NULL. */
-+ argv_size = 12
-+ };
-+ char *args[argv_size];
-+
-+ for (char **arg = initial_argv; *arg != NULL; arg++)
-+ args[argc++] = *arg;
-+
-+ args[argc++] = (char*) "--direct";
-+ args[argc++] = (char*) "--restart";
-+
-+ args[argc++] = test->out;
-+ args[argc++] = test->err;
-+ args[argc++] = (char*) write_mode_to_str (test->write_mode);
-+ args[argc++] = signalstr;
-+ args[argc++] = statusstr;
-+ args[argc] = NULL;
-+ TEST_VERIFY (argc < argv_size);
-+
-+ return support_capture_subprogram (args[0], args);
-+}
-+
-+enum test_type
-+{
-+ subprocess,
-+ subprogram,
-+};
-+
- static int
--do_test (void)
-+do_multiple_tests (enum test_type type)
- {
- const int lengths[] = {0, 1, 17, 512, 20000, -1};
-
-- /* Test multiple combinations of support_capture_subprocess.
-+ /* Test multiple combinations of support_capture_sub{process,program}.
-
- length_idx_stdout: Index into the lengths array above,
- controls how many bytes are written by the subprocess to
-@@ -164,8 +279,10 @@ do_test (void)
- TEST_VERIFY (strlen (test.out) == lengths[length_idx_stdout]);
- TEST_VERIFY (strlen (test.err) == lengths[length_idx_stderr]);
-
-- struct support_capture_subprocess result
-- = support_capture_subprocess (callback, &test);
-+ struct support_capture_subprocess result
-+ = type == subprocess ? do_subprocess (&test)
-+ : do_subprogram (&test);
-+
- check_stream ("stdout", &result.out, test.out);
- check_stream ("stderr", &result.err, test.err);
-
-@@ -199,4 +316,54 @@ do_test (void)
- return 0;
- }
-
-+static int
-+do_test (int argc, char *argv[])
-+{
-+ /* We must have either:
-+
-+ - one or four parameters if called initially:
-+ + argv[1]: path for ld.so optional
-+ + argv[2]: "--library-path" optional
-+ + argv[3]: the library path optional
-+ + argv[4]: the application name
-+
-+ - six parameters left if called through re-execution:
-+ + argv[1]: the application name
-+ + argv[2]: the stdout to print
-+ + argv[3]: the stderr to print
-+ + argv[4]: the write mode to use
-+ + argv[5]: the signal to issue
-+ + argv[6]: the exit status code to use
-+
-+ * When built with --enable-hardcoded-path-in-tests or issued without
-+ using the loader directly.
-+ */
-+
-+ if (argc != (restart ? 6 : 5) && argc != (restart ? 6 : 2))
-+ FAIL_EXIT1 ("wrong number of arguments (%d)", argc);
-+
-+ if (restart)
-+ {
-+ handle_restart (argv[1], /* stdout */
-+ argv[2], /* stderr */
-+ argv[3], /* write_mode */
-+ argv[4], /* signal */
-+ argv[5]); /* status */
-+ }
-+
-+ initial_argv[0] = argv[1]; /* path for ld.so */
-+ initial_argv[1] = argv[2]; /* "--library-path" */
-+ initial_argv[2] = argv[3]; /* the library path */
-+ initial_argv[3] = argv[4]; /* the application name */
-+ initial_argv[4] = NULL;
-+
-+ do_multiple_tests (subprocess);
-+ do_multiple_tests (subprogram);
-+
-+ return 0;
-+}
-+
-+#define CMDLINE_OPTIONS \
-+ { "restart", no_argument, &restart, 1 },
-+#define TEST_FUNCTION_ARGV do_test
- #include <support/test-driver.c>
-diff --git a/support/xposix_spawn.c b/support/xposix_spawn.c
-new file mode 100644
-index 0000000000..e846017632
---- /dev/null
-+++ b/support/xposix_spawn.c
-@@ -0,0 +1,32 @@
-+/* xposix_spawn implementation.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <support/xspawn.h>
-+#include <support/check.h>
-+
-+pid_t
-+xposix_spawn (const char *file, const posix_spawn_file_actions_t *fa,
-+ const posix_spawnattr_t *attr, char *const args[],
-+ char *const envp[])
-+{
-+ pid_t pid;
-+ int status = posix_spawn (&pid, file, fa, attr, args, envp);
-+ if (status != 0)
-+ FAIL_EXIT1 ("posix_spawn to %s file failed: %m", file);
-+ return pid;
-+}
-diff --git a/support/xposix_spawn_file_actions_addclose.c b/support/xposix_spawn_file_actions_addclose.c
-new file mode 100644
-index 0000000000..eed54a6514
---- /dev/null
-+++ b/support/xposix_spawn_file_actions_addclose.c
-@@ -0,0 +1,29 @@
-+/* xposix_spawn_file_actions_addclose implementation.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <support/xspawn.h>
-+#include <support/check.h>
-+
-+int
-+xposix_spawn_file_actions_addclose (posix_spawn_file_actions_t *fa, int fd)
-+{
-+ int status = posix_spawn_file_actions_addclose (fa, fd);
-+ if (status == -1)
-+ FAIL_EXIT1 ("posix_spawn_file_actions_addclose failed: %m\n");
-+ return status;
-+}
-diff --git a/support/xposix_spawn_file_actions_adddup2.c b/support/xposix_spawn_file_actions_adddup2.c
-new file mode 100644
-index 0000000000..a43b6490be
---- /dev/null
-+++ b/support/xposix_spawn_file_actions_adddup2.c
-@@ -0,0 +1,30 @@
-+/* xposix_spawn_file_actions_adddup2 implementation.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <support/xspawn.h>
-+#include <support/check.h>
-+
-+int
-+xposix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *fa, int fd,
-+ int newfd)
-+{
-+ int status = posix_spawn_file_actions_adddup2 (fa, fd, newfd);
-+ if (status == -1)
-+ FAIL_EXIT1 ("posix_spawn_file_actions_adddup2 failed: %m\n");
-+ return status;
-+}
-diff --git a/support/xpthread_rwlock_destroy.c b/support/xpthread_rwlock_destroy.c
-new file mode 100644
-index 0000000000..6d6e953569
---- /dev/null
-+++ b/support/xpthread_rwlock_destroy.c
-@@ -0,0 +1,26 @@
-+/* pthread_rwlock_destroy with error checking.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#include <support/xthread.h>
-+
-+void
-+xpthread_rwlock_destroy (pthread_rwlock_t *rwlock)
-+{
-+ xpthread_check_return ("pthread_rwlock_destroy",
-+ pthread_rwlock_destroy (rwlock));
-+}
-diff --git a/support/xspawn.h b/support/xspawn.h
-new file mode 100644
-index 0000000000..bbf89132e4
---- /dev/null
-+++ b/support/xspawn.h
-@@ -0,0 +1,34 @@
-+/* posix_spawn with support checks.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#ifndef SUPPORT_XSPAWN_H
-+#define SUPPORT_XSPAWN_H
-+
-+#include <spawn.h>
-+
-+__BEGIN_DECLS
-+
-+int xposix_spawn_file_actions_addclose (posix_spawn_file_actions_t *, int);
-+int xposix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *, int, int);
-+
-+pid_t xposix_spawn (const char *, const posix_spawn_file_actions_t *,
-+ const posix_spawnattr_t *, char *const [], char *const []);
-+
-+__END_DECLS
-+
-+#endif
-diff --git a/support/xthread.h b/support/xthread.h
-index 47c23235f3..9fe1f68b3b 100644
---- a/support/xthread.h
-+++ b/support/xthread.h
-@@ -84,6 +84,7 @@ void xpthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref);
- void xpthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
- void xpthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
- void xpthread_rwlock_unlock (pthread_rwlock_t *rwlock);
-+void xpthread_rwlock_destroy (pthread_rwlock_t *rwlock);
-
- __END_DECLS
-
-diff --git a/sysdeps/arm/stap-probe-machine.h b/sysdeps/arm/stap-probe-machine.h
-new file mode 100644
-index 0000000000..d27ca22040
---- /dev/null
-+++ b/sysdeps/arm/stap-probe-machine.h
-@@ -0,0 +1,22 @@
-+/* Macros for customizing Systemtap <sys/sdt.h>. Arm version.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+/* The default "nor" constraint produces unparseable memory references
-+ for constants. Omit the problematic "o" constraint. See bug 24164
-+ and GCC PR 89146. */
-+#define STAP_SDT_ARG_CONSTRAINT nr
-diff --git a/sysdeps/generic/stap-probe-machine.h b/sysdeps/generic/stap-probe-machine.h
-new file mode 100644
-index 0000000000..2e5790c3b2
---- /dev/null
-+++ b/sysdeps/generic/stap-probe-machine.h
-@@ -0,0 +1,19 @@
-+/* Macros for customizing Systemtap <sys/sdt.h>. Generic version.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+/* By default, there are no customizations. */
-diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c
-index bd68f18b45..14b69a6f89 100644
---- a/sysdeps/nptl/fork.c
-+++ b/sysdeps/nptl/fork.c
-@@ -55,7 +55,7 @@ __libc_fork (void)
- but our current fork implementation is not. */
- bool multiple_threads = THREAD_GETMEM (THREAD_SELF, header.multiple_threads);
-
-- __run_fork_handlers (atfork_run_prepare);
-+ __run_fork_handlers (atfork_run_prepare, multiple_threads);
-
- /* If we are not running multiple threads, we do not have to
- preserve lock state. If fork runs from a signal handler, only
-@@ -134,7 +134,7 @@ __libc_fork (void)
- __rtld_lock_initialize (GL(dl_load_lock));
-
- /* Run the handlers registered for the child. */
-- __run_fork_handlers (atfork_run_child);
-+ __run_fork_handlers (atfork_run_child, multiple_threads);
- }
- else
- {
-@@ -149,7 +149,7 @@ __libc_fork (void)
- }
-
- /* Run the handlers registered for the parent. */
-- __run_fork_handlers (atfork_run_parent);
-+ __run_fork_handlers (atfork_run_parent, multiple_threads);
- }
-
- return pid;
-diff --git a/sysdeps/nptl/fork.h b/sysdeps/nptl/fork.h
-index a1c3b26b68..99ed76034b 100644
---- a/sysdeps/nptl/fork.h
-+++ b/sysdeps/nptl/fork.h
-@@ -52,9 +52,11 @@ enum __run_fork_handler_type
- - atfork_run_child: run all the CHILD_HANDLER and unlocks the internal
- lock.
- - atfork_run_parent: run all the PARENT_HANDLER and unlocks the internal
-- lock. */
--extern void __run_fork_handlers (enum __run_fork_handler_type who)
-- attribute_hidden;
-+ lock.
-+
-+ Perform locking only if DO_LOCKING. */
-+extern void __run_fork_handlers (enum __run_fork_handler_type who,
-+ _Bool do_locking) attribute_hidden;
-
- /* C library side function to register new fork handlers. */
- extern int __register_atfork (void (*__prepare) (void),
-diff --git a/sysdeps/powerpc/dl-procinfo.h b/sysdeps/powerpc/dl-procinfo.h
-index f542f7318f..dfc3b33a72 100644
---- a/sysdeps/powerpc/dl-procinfo.h
-+++ b/sysdeps/powerpc/dl-procinfo.h
-@@ -225,7 +225,7 @@ _dl_procinfo (unsigned int type, unsigned long int word)
- break;
- }
- default:
-- /* This should not happen. */
-+ /* Fallback to generic output mechanism. */
- return -1;
- }
- _dl_printf ("\n");
-diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h
-index b4b81fc70a..99697ae649 100644
---- a/sysdeps/s390/dl-procinfo.h
-+++ b/sysdeps/s390/dl-procinfo.h
-@@ -57,7 +57,8 @@ enum
- };
-
- #define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \
-- | HWCAP_S390_EIMM | HWCAP_S390_DFP)
-+ | HWCAP_S390_EIMM | HWCAP_S390_DFP \
-+ | HWCAP_S390_VX | HWCAP_S390_VXE)
-
- /* We cannot provide a general printing function. */
- #define _dl_procinfo(type, word) -1
-diff --git a/sysdeps/sparc/dl-procinfo.h b/sysdeps/sparc/dl-procinfo.h
-index 282b8c5117..64ee267fc7 100644
---- a/sysdeps/sparc/dl-procinfo.h
-+++ b/sysdeps/sparc/dl-procinfo.h
-@@ -31,8 +31,8 @@ _dl_procinfo (unsigned int type, unsigned long int word)
- {
- int i;
-
-- /* Fallback to unknown output mechanism. */
-- if (type == AT_HWCAP2)
-+ /* Fallback to generic output mechanism. */
-+ if (type != AT_HWCAP)
- return -1;
-
- _dl_printf ("AT_HWCAP: ");
-diff --git a/sysdeps/unix/sysv/linux/arm/dl-procinfo.h b/sysdeps/unix/sysv/linux/arm/dl-procinfo.h
-index 66c00297b7..05c62c8687 100644
---- a/sysdeps/unix/sysv/linux/arm/dl-procinfo.h
-+++ b/sysdeps/unix/sysv/linux/arm/dl-procinfo.h
-@@ -67,7 +67,7 @@ _dl_procinfo (unsigned int type, unsigned long int word)
- break;
- }
- default:
-- /* This should not happen. */
-+ /* Fallback to generic output mechanism. */
- return -1;
- }
- _dl_printf ("\n");
-diff --git a/sysdeps/unix/sysv/linux/i386/dl-procinfo.h b/sysdeps/unix/sysv/linux/i386/dl-procinfo.h
-index 22b43431bc..0585cdaa9c 100644
---- a/sysdeps/unix/sysv/linux/i386/dl-procinfo.h
-+++ b/sysdeps/unix/sysv/linux/i386/dl-procinfo.h
-@@ -30,8 +30,8 @@ _dl_procinfo (unsigned int type, unsigned long int word)
- in the kernel sources. */
- int i;
-
-- /* Fallback to unknown output mechanism. */
-- if (type == AT_HWCAP2)
-+ /* Fallback to generic output mechanism. */
-+ if (type != AT_HWCAP)
- return -1;
-
- _dl_printf ("AT_HWCAP: ");
-diff --git a/sysdeps/unix/sysv/linux/s390/dl-procinfo.h b/sysdeps/unix/sysv/linux/s390/dl-procinfo.h
-index 19329a335b..d67fde368f 100644
---- a/sysdeps/unix/sysv/linux/s390/dl-procinfo.h
-+++ b/sysdeps/unix/sysv/linux/s390/dl-procinfo.h
-@@ -32,8 +32,8 @@ _dl_procinfo (unsigned int type, unsigned long int word)
- in the kernel sources. */
- int i;
-
-- /* Fallback to unknown output mechanism. */
-- if (type == AT_HWCAP2)
-+ /* Fallback to generic output mechanism. */
-+ if (type != AT_HWCAP)
- return -1;
-
- _dl_printf ("AT_HWCAP: ");
-diff --git a/sysdeps/x86_64/memcmp.S b/sysdeps/x86_64/memcmp.S
-index 1fc487caa5..1322bb3b92 100644
---- a/sysdeps/x86_64/memcmp.S
-+++ b/sysdeps/x86_64/memcmp.S
-@@ -21,14 +21,18 @@
-
- .text
- ENTRY (memcmp)
-- test %rdx, %rdx
-+#ifdef __ILP32__
-+ /* Clear the upper 32 bits. */
-+ movl %edx, %edx
-+#endif
-+ test %RDX_LP, %RDX_LP
- jz L(finz)
- cmpq $1, %rdx
-- jle L(finr1b)
-+ jbe L(finr1b)
- subq %rdi, %rsi
- movq %rdx, %r10
- cmpq $32, %r10
-- jge L(gt32)
-+ jae L(gt32)
- /* Handle small chunks and last block of less than 32 bytes. */
- L(small):
- testq $1, %r10
-@@ -156,7 +160,7 @@ L(A32):
- movq %r11, %r10
- andq $-32, %r10
- cmpq %r10, %rdi
-- jge L(mt16)
-+ jae L(mt16)
- /* Pre-unroll to be ready for unrolled 64B loop. */
- testq $32, %rdi
- jz L(A64)
-@@ -178,7 +182,7 @@ L(A64):
- movq %r11, %r10
- andq $-64, %r10
- cmpq %r10, %rdi
-- jge L(mt32)
-+ jae L(mt32)
-
- L(A64main):
- movdqu (%rdi,%rsi), %xmm0
-@@ -216,7 +220,7 @@ L(mt32):
- movq %r11, %r10
- andq $-32, %r10
- cmpq %r10, %rdi
-- jge L(mt16)
-+ jae L(mt16)
-
- L(A32main):
- movdqu (%rdi,%rsi), %xmm0
-@@ -254,7 +258,7 @@ L(ATR):
- movq %r11, %r10
- andq $-32, %r10
- cmpq %r10, %rdi
-- jge L(mt16)
-+ jae L(mt16)
- testq $16, %rdi
- jz L(ATR32)
-
-@@ -325,7 +329,7 @@ L(ATR64main):
- movq %r11, %r10
- andq $-32, %r10
- cmpq %r10, %rdi
-- jge L(mt16)
-+ jae L(mt16)
-
- L(ATR32res):
- movdqa (%rdi,%rsi), %xmm0
-diff --git a/sysdeps/x86_64/x32/Makefile b/sysdeps/x86_64/x32/Makefile
-index 1557724b0c..8748956563 100644
---- a/sysdeps/x86_64/x32/Makefile
-+++ b/sysdeps/x86_64/x32/Makefile
-@@ -8,7 +8,8 @@ endif
- ifeq ($(subdir),string)
- tests += tst-size_t-memchr tst-size_t-memcmp tst-size_t-memcpy \
- tst-size_t-memrchr tst-size_t-memset tst-size_t-strncasecmp \
-- tst-size_t-strncmp tst-size_t-strncpy tst-size_t-strnlen
-+ tst-size_t-strncmp tst-size_t-strncpy tst-size_t-strnlen \
-+ tst-size_t-memcmp-2
- endif
-
- ifeq ($(subdir),wcsmbs)
-diff --git a/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c b/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c
-new file mode 100644
-index 0000000000..d8ae1a0813
---- /dev/null
-+++ b/sysdeps/x86_64/x32/tst-size_t-memcmp-2.c
-@@ -0,0 +1,79 @@
-+/* Test memcmp with size_t in the lower 32 bits of 64-bit register.
-+ Copyright (C) 2019 Free Software Foundation, Inc.
-+ This file is part of the GNU C Library.
-+
-+ The GNU C Library is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU Lesser General Public
-+ License as published by the Free Software Foundation; either
-+ version 2.1 of the License, or (at your option) any later version.
-+
-+ The GNU C Library is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ Lesser General Public License for more details.
-+
-+ You should have received a copy of the GNU Lesser General Public
-+ License along with the GNU C Library; if not, see
-+ <http://www.gnu.org/licenses/>. */
-+
-+#define TEST_MAIN
-+#ifdef WIDE
-+# define TEST_NAME "wmemcmp"
-+#else
-+# define TEST_NAME "memcmp"
-+#endif
-+
-+#include "test-size_t.h"
-+
-+#ifdef WIDE
-+# include <inttypes.h>
-+# include <wchar.h>
-+
-+# define MEMCMP wmemcmp
-+# define CHAR wchar_t
-+#else
-+# define MEMCMP memcmp
-+# define CHAR char
-+#endif
-+
-+IMPL (MEMCMP, 1)
-+
-+typedef int (*proto_t) (const CHAR *, const CHAR *, size_t);
-+
-+static int
-+__attribute__ ((noinline, noclone))
-+do_memcmp (parameter_t a, parameter_t b)
-+{
-+ return CALL (&b, a.p, b.p, a.len);
-+}
-+
-+static int
-+test_main (void)
-+{
-+ test_init ();
-+
-+ parameter_t dest = { { page_size / sizeof (CHAR) }, buf1 };
-+ parameter_t src = { { 0 }, buf2 };
-+
-+ memcpy (buf1, buf2, page_size);
-+
-+ CHAR *p = (CHAR *) buf1;
-+ p[page_size / sizeof (CHAR) - 1] = (CHAR) 1;
-+
-+ int ret = 0;
-+ FOR_EACH_IMPL (impl, 0)
-+ {
-+ src.fn = impl->fn;
-+ int res = do_memcmp (dest, src);
-+ if (res >= 0)
-+ {
-+ error (0, 0, "Wrong result in function %s: %i >= 0",
-+ impl->name, res);
-+ ret = 1;
-+ }
-+ }
-+
-+ return ret ? EXIT_FAILURE : EXIT_SUCCESS;
-+}
-+
-+#include <support/test-driver.c>
diff --git a/glibc-a6aaabd036d735a1b412f441bf6c706832655598.patch b/glibc-a6aaabd036d735a1b412f441bf6c706832655598.patch
new file mode 100644
index 000000000000..b683636cae71
--- /dev/null
+++ b/glibc-a6aaabd036d735a1b412f441bf6c706832655598.patch
@@ -0,0 +1,414 @@
+diff --git a/ChangeLog b/ChangeLog
+index cdb9e14881..29c864868a 100644
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,3 +1,42 @@
++2019-09-20 Joseph Myers <joseph@codesourcery.com>
++
++ * sysdeps/unix/sysv/linux/riscv/vfork.S: Do not include
++ <linux/sched.h>.
++ (CLONE_VM): New macro.
++ (CLONE_VFORK): Likewise.
++
++2019-09-14 Aurelien Jarno <aurelien@aurel32.net>
++
++ [BZ #24986]
++ * sysdeps/unix/alpha/getegid.S: Move to ...
++ * sysdeps/unix/sysv/linux/alpha/getegid.S: ... here.
++ * sysdeps/unix/alpha/geteuid.S: Move to ...
++ * sysdeps/unix/sysv/linux/alpha/geteuid.S: ... here.
++ * sysdeps/unix/alpha/getppid.S: Move to ...
++ * sysdeps/unix/sysv/linux/alpha/getppid.S: ... here
++
++2019-09-08 Adhemerval Zanella <adhemerval.zanella@linaro.org>
++
++ * sysdeps/hppa/fpu/libm-test-ulps: Update.
++
++2019-09-03 Aurelien Jarno <aurelien@aurel32.net>
++
++ * sysdeps/alpha/fpu/libm-test-ulps: Regenerated using GCC 9.2.
++
++2019-08-28 Rafal Luzynski <digitalfreak@lingonborough.com>
++
++ [BZ #24682]
++ * NEWS: Mention this bug fixed.
++ * localedata/locales/bo_CN (first_weekday): Add, set to 2 (Monday).
++ * localedata/locales/ug_CN (first_weekday): Likewise.
++ * localedata/locales/zh_CN (first_weekday): Likewise.
++
++2019-08-01 Florian Weimer <fweimer@redhat.com>
++
++ [BZ #24867]
++ * malloc/malloc.c (__malloc_info): Remove unwanted leading
++ whitespace.
++
+ 2019-08-01 Carlos O'Donell <carlos@redhat.com>
+
+ * version.h (RELEASE): Set to "stable".
+diff --git a/NEWS b/NEWS
+index ee9ed4de5a..5f1ade1c49 100644
+--- a/NEWS
++++ b/NEWS
+@@ -4,6 +4,17 @@ See the end for copying conditions.
+
+ Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
+ using `glibc' in the "product" field.
++
++Version 2.30.1
++
++The following bugs are resolved with this release:
++
++ [24682] localedata: zh_CN first weekday should be Monday per GB/T
++ 7408-2005
++ [24867] malloc: Remove unwanted leading whitespace in malloc_info
++ [24986] alpha: new getegid, geteuid and getppid syscalls used
++ unconditionally
++
+
+ Version 2.30
+
+diff --git a/localedata/locales/bo_CN b/localedata/locales/bo_CN
+index 90cbc7807b..9df91a1721 100644
+--- a/localedata/locales/bo_CN
++++ b/localedata/locales/bo_CN
+@@ -128,6 +128,7 @@ t_fmt_ampm "<U0F46><U0F74><U0F0B><U0F5A><U0F7C><U0F51>/
+ <U0025><U0070>"
+
+ week 7;19971130;1
++first_weekday 2
+ END LC_TIME
+
+ LC_MESSAGES
+diff --git a/localedata/locales/ug_CN b/localedata/locales/ug_CN
+index 1ba583c588..83d15c90e4 100644
+--- a/localedata/locales/ug_CN
++++ b/localedata/locales/ug_CN
+@@ -165,6 +165,7 @@ am_pm "";""
+ date_fmt "%a<U060C> %d-%m-%Y<U060C> %T"
+
+ week 7;19971130;1
++first_weekday 2
+ END LC_TIME
+
+ LC_MESSAGES
+diff --git a/localedata/locales/zh_CN b/localedata/locales/zh_CN
+index 62a46415c1..cd4b33602a 100644
+--- a/localedata/locales/zh_CN
++++ b/localedata/locales/zh_CN
+@@ -139,6 +139,7 @@ t_fmt_ampm "%p %I<U65F6>%M<U5206>%S<U79D2>"
+
+ date_fmt "%Y<U5E74> %m<U6708> %d<U65E5> %A %H:%M:%S %Z"
+ week 7;19971130;1
++first_weekday 2
+ END LC_TIME
+
+ LC_MESSAGES
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index 00ce48cf58..343d89f489 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -5491,7 +5491,7 @@ __malloc_info (int options, FILE *fp)
+
+ for (size_t i = 0; i < nsizes; ++i)
+ if (sizes[i].count != 0 && i != NFASTBINS)
+- fprintf (fp, " \
++ fprintf (fp, "\
+ <size from=\"%zu\" to=\"%zu\" total=\"%zu\" count=\"%zu\"/>\n",
+ sizes[i].from, sizes[i].to, sizes[i].total, sizes[i].count);
+
+diff --git a/sysdeps/alpha/fpu/libm-test-ulps b/sysdeps/alpha/fpu/libm-test-ulps
+index 0f77dd2ed0..89c4527a81 100644
+--- a/sysdeps/alpha/fpu/libm-test-ulps
++++ b/sysdeps/alpha/fpu/libm-test-ulps
+@@ -1084,10 +1084,10 @@ ildouble: 1
+ ldouble: 1
+
+ Function: Real part of "cpow_downward":
+-double: 2
+-float: 4
+-idouble: 2
+-ifloat: 4
++double: 5
++float: 8
++idouble: 5
++ifloat: 8
+ ildouble: 6
+ ldouble: 6
+
+@@ -1100,10 +1100,10 @@ ildouble: 2
+ ldouble: 2
+
+ Function: Real part of "cpow_towardzero":
+-double: 2
+-float: 4
+-idouble: 2
+-ifloat: 4
++double: 5
++float: 8
++idouble: 5
++ifloat: 8
+ ildouble: 6
+ ldouble: 6
+
+diff --git a/sysdeps/hppa/fpu/libm-test-ulps b/sysdeps/hppa/fpu/libm-test-ulps
+index d0c4dea001..2c61a7ae91 100644
+--- a/sysdeps/hppa/fpu/libm-test-ulps
++++ b/sysdeps/hppa/fpu/libm-test-ulps
+@@ -544,9 +544,9 @@ idouble: 1
+ ifloat: 1
+
+ Function: Imaginary part of "ccos_downward":
+-double: 2
++double: 3
+ float: 3
+-idouble: 2
++idouble: 3
+ ifloat: 3
+
+ Function: Real part of "ccos_towardzero":
+@@ -556,9 +556,9 @@ idouble: 1
+ ifloat: 2
+
+ Function: Imaginary part of "ccos_towardzero":
+-double: 2
++double: 3
+ float: 3
+-idouble: 2
++idouble: 3
+ ifloat: 3
+
+ Function: Real part of "ccos_upward":
+@@ -588,27 +588,27 @@ idouble: 1
+ ifloat: 1
+
+ Function: Real part of "ccosh_downward":
+-double: 1
++double: 2
+ float: 3
+-idouble: 1
++idouble: 2
+ ifloat: 3
+
+ Function: Imaginary part of "ccosh_downward":
+-double: 2
++double: 3
+ float: 3
+-idouble: 2
++idouble: 3
+ ifloat: 3
+
+ Function: Real part of "ccosh_towardzero":
+-double: 1
++double: 2
+ float: 3
+-idouble: 1
++idouble: 2
+ ifloat: 3
+
+ Function: Imaginary part of "ccosh_towardzero":
+-double: 2
++double: 3
+ float: 3
+-idouble: 2
++idouble: 3
+ ifloat: 3
+
+ Function: Real part of "ccosh_upward":
+@@ -636,27 +636,27 @@ idouble: 1
+ ifloat: 2
+
+ Function: Real part of "cexp_downward":
+-double: 1
++double: 2
+ float: 2
+-idouble: 1
++idouble: 2
+ ifloat: 2
+
+ Function: Imaginary part of "cexp_downward":
+-double: 1
++double: 3
+ float: 3
+-idouble: 1
++idouble: 3
+ ifloat: 3
+
+ Function: Real part of "cexp_towardzero":
+-double: 1
++double: 2
+ float: 2
+-idouble: 1
++idouble: 2
+ ifloat: 2
+
+ Function: Imaginary part of "cexp_towardzero":
+-double: 1
++double: 3
+ float: 3
+-idouble: 1
++idouble: 3
+ ifloat: 3
+
+ Function: Real part of "cexp_upward":
+@@ -666,9 +666,9 @@ idouble: 1
+ ifloat: 2
+
+ Function: Imaginary part of "cexp_upward":
+-double: 1
++double: 3
+ float: 2
+-idouble: 1
++idouble: 3
+ ifloat: 2
+
+ Function: Real part of "clog":
+@@ -800,21 +800,21 @@ idouble: 1
+ ifloat: 1
+
+ Function: "cosh_downward":
+-double: 1
++double: 2
+ float: 1
+-idouble: 1
++idouble: 2
+ ifloat: 1
+
+ Function: "cosh_towardzero":
+-double: 1
++double: 2
+ float: 1
+-idouble: 1
++idouble: 2
+ ifloat: 1
+
+ Function: "cosh_upward":
+-double: 1
++double: 2
+ float: 2
+-idouble: 1
++idouble: 2
+ ifloat: 2
+
+ Function: Real part of "cpow":
+@@ -834,9 +834,9 @@ ildouble: 2
+ ldouble: 2
+
+ Function: Real part of "cpow_downward":
+-double: 4
++double: 5
+ float: 8
+-idouble: 4
++idouble: 5
+ ifloat: 8
+
+ Function: Imaginary part of "cpow_downward":
+@@ -846,9 +846,9 @@ idouble: 2
+ ifloat: 2
+
+ Function: Real part of "cpow_towardzero":
+-double: 4
++double: 5
+ float: 8
+-idouble: 4
++idouble: 5
+ ifloat: 8
+
+ Function: Imaginary part of "cpow_towardzero":
+@@ -876,9 +876,9 @@ idouble: 1
+ ifloat: 1
+
+ Function: Real part of "csin_downward":
+-double: 2
++double: 3
+ float: 3
+-idouble: 2
++idouble: 3
+ ifloat: 3
+
+ Function: Imaginary part of "csin_downward":
+@@ -888,9 +888,9 @@ idouble: 1
+ ifloat: 2
+
+ Function: Real part of "csin_towardzero":
+-double: 2
++double: 3
+ float: 3
+-idouble: 2
++idouble: 3
+ ifloat: 3
+
+ Function: Imaginary part of "csin_towardzero":
+@@ -930,9 +930,9 @@ idouble: 2
+ ifloat: 2
+
+ Function: Imaginary part of "csinh_downward":
+-double: 2
++double: 3
+ float: 3
+-idouble: 2
++idouble: 3
+ ifloat: 3
+
+ Function: Real part of "csinh_towardzero":
+@@ -942,9 +942,9 @@ idouble: 2
+ ifloat: 2
+
+ Function: Imaginary part of "csinh_towardzero":
+-double: 2
++double: 3
+ float: 3
+-idouble: 2
++idouble: 3
+ ifloat: 3
+
+ Function: Real part of "csinh_upward":
+@@ -1172,15 +1172,15 @@ ildouble: 6
+ ldouble: 6
+
+ Function: "exp10_downward":
+-double: 2
++double: 3
+ float: 1
+-idouble: 2
++idouble: 3
+ ifloat: 1
+
+ Function: "exp10_towardzero":
+-double: 2
++double: 3
+ float: 1
+-idouble: 2
++idouble: 3
+ ifloat: 1
+
+ Function: "exp10_upward":
+diff --git a/sysdeps/unix/alpha/getegid.S b/sysdeps/unix/sysv/linux/alpha/getegid.S
+similarity index 100%
+rename from sysdeps/unix/alpha/getegid.S
+rename to sysdeps/unix/sysv/linux/alpha/getegid.S
+diff --git a/sysdeps/unix/alpha/geteuid.S b/sysdeps/unix/sysv/linux/alpha/geteuid.S
+similarity index 100%
+rename from sysdeps/unix/alpha/geteuid.S
+rename to sysdeps/unix/sysv/linux/alpha/geteuid.S
+diff --git a/sysdeps/unix/alpha/getppid.S b/sysdeps/unix/sysv/linux/alpha/getppid.S
+similarity index 100%
+rename from sysdeps/unix/alpha/getppid.S
+rename to sysdeps/unix/sysv/linux/alpha/getppid.S
+diff --git a/sysdeps/unix/sysv/linux/riscv/vfork.S b/sysdeps/unix/sysv/linux/riscv/vfork.S
+index 67373f181b..dc173d6b47 100644
+--- a/sysdeps/unix/sysv/linux/riscv/vfork.S
++++ b/sysdeps/unix/sysv/linux/riscv/vfork.S
+@@ -21,9 +21,12 @@
+ #include <sys/asm.h>
+ #include <sysdep.h>
+ #define __ASSEMBLY__
+-#include <linux/sched.h>
+ #include <asm/signal.h>
+
++#define CLONE_VM 0x00000100 /* Set if VM shared between processes. */
++#define CLONE_VFORK 0x00004000 /* Set if the parent wants the child to
++ wake it up on mm_release. */
++
+ .text
+ LEAF (__libc_vfork)
+
diff --git a/sdt-config.h b/sdt-config.h
new file mode 100644
index 000000000000..733045a52771
--- /dev/null
+++ b/sdt-config.h
@@ -0,0 +1,6 @@
+/* includes/sys/sdt-config.h. Generated from sdt-config.h.in by configure.
+
+ This file just defines _SDT_ASM_SECTION_AUTOGROUP_SUPPORT to 0 or 1 to
+ indicate whether the assembler supports "?" in .pushsection directives. */
+
+#define _SDT_ASM_SECTION_AUTOGROUP_SUPPORT 1
diff --git a/sdt.h b/sdt.h
new file mode 100644
index 000000000000..c0c5a492cb9c
--- /dev/null
+++ b/sdt.h
@@ -0,0 +1,430 @@
+/* <sys/sdt.h> - Systemtap static probe definition macros.
+
+ This file is dedicated to the public domain, pursuant to CC0
+ (https://creativecommons.org/publicdomain/zero/1.0/)
+*/
+
+#ifndef _SYS_SDT_H
+#define _SYS_SDT_H 1
+
+/*
+ This file defines a family of macros
+
+ STAP_PROBEn(op1, ..., opn)
+
+ that emit a nop into the instruction stream, and some data into an auxiliary
+ note section. The data in the note section describes the operands, in terms
+ of size and location. Each location is encoded as assembler operand string.
+ Consumer tools such as gdb or systemtap insert breakpoints on top of
+ the nop, and decode the location operand-strings, like an assembler,
+ to find the values being passed.
+
+ The operand strings are selected by the compiler for each operand.
+ They are constrained by gcc inline-assembler codes. The default is:
+
+ #define STAP_SDT_ARG_CONSTRAINT nor
+
+ This is a good default if the operands tend to be integral and
+ moderate in number (smaller than number of registers). In other
+ cases, the compiler may report "'asm' requires impossible reload" or
+ similar. In this case, consider simplifying the macro call (fewer
+ and simpler operands), reduce optimization, or override the default
+ constraints string via:
+
+ #define STAP_SDT_ARG_CONSTRAINT g
+ #include <sys/sdt.h>
+
+ See also:
+ https://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation
+ https://gcc.gnu.org/onlinedocs/gcc/Constraints.html
+ */
+
+
+
+#ifdef __ASSEMBLER__
+# define _SDT_PROBE(provider, name, n, arglist) \
+ _SDT_ASM_BODY(provider, name, _SDT_ASM_STRING_1, (_SDT_DEPAREN_##n arglist)) \
+ _SDT_ASM_BASE
+# define _SDT_ASM_1(x) x;
+# define _SDT_ASM_2(a, b) a,b;
+# define _SDT_ASM_3(a, b, c) a,b,c;
+# define _SDT_ASM_5(a, b, c, d, e) a,b,c,d,e;
+# define _SDT_ASM_STRING_1(x) .asciz #x;
+# define _SDT_DEPAREN_0() /* empty */
+# define _SDT_DEPAREN_1(a) a
+# define _SDT_DEPAREN_2(a,b) a b
+# define _SDT_DEPAREN_3(a,b,c) a b c
+# define _SDT_DEPAREN_4(a,b,c,d) a b c d
+# define _SDT_DEPAREN_5(a,b,c,d,e) a b c d e
+# define _SDT_DEPAREN_6(a,b,c,d,e,f) a b c d e f
+# define _SDT_DEPAREN_7(a,b,c,d,e,f,g) a b c d e f g
+# define _SDT_DEPAREN_8(a,b,c,d,e,f,g,h) a b c d e f g h
+# define _SDT_DEPAREN_9(a,b,c,d,e,f,g,h,i) a b c d e f g h i
+# define _SDT_DEPAREN_10(a,b,c,d,e,f,g,h,i,j) a b c d e f g h i j
+# define _SDT_DEPAREN_11(a,b,c,d,e,f,g,h,i,j,k) a b c d e f g h i j k
+# define _SDT_DEPAREN_12(a,b,c,d,e,f,g,h,i,j,k,l) a b c d e f g h i j k l
+#else
+# define _SDT_PROBE(provider, name, n, arglist) \
+ do { \
+ __asm__ __volatile__ (_SDT_ASM_BODY(provider, name, _SDT_ASM_ARGS, (n)) \
+ :: _SDT_ASM_OPERANDS_##n arglist); \
+ __asm__ __volatile__ (_SDT_ASM_BASE); \
+ } while (0)
+# define _SDT_S(x) #x
+# define _SDT_ASM_1(x) _SDT_S(x) "\n"
+# define _SDT_ASM_2(a, b) _SDT_S(a) "," _SDT_S(b) "\n"
+# define _SDT_ASM_3(a, b, c) _SDT_S(a) "," _SDT_S(b) "," \
+ _SDT_S(c) "\n"
+# define _SDT_ASM_5(a, b, c, d, e) _SDT_S(a) "," _SDT_S(b) "," \
+ _SDT_S(c) "," _SDT_S(d) "," \
+ _SDT_S(e) "\n"
+# define _SDT_ASM_ARGS(n) _SDT_ASM_STRING(_SDT_ASM_TEMPLATE_##n)
+# define _SDT_ASM_STRING_1(x) _SDT_ASM_1(.asciz #x)
+
+# define _SDT_ARGFMT(no) %n[_SDT_S##no]@_SDT_ARGTMPL(_SDT_A##no)
+
+# ifndef STAP_SDT_ARG_CONSTRAINT
+# if defined __powerpc__
+# define STAP_SDT_ARG_CONSTRAINT nZr
+# else
+# define STAP_SDT_ARG_CONSTRAINT nor
+# endif
+# endif
+
+# define _SDT_STRINGIFY(x) #x
+# define _SDT_ARG_CONSTRAINT_STRING(x) _SDT_STRINGIFY(x)
+# define _SDT_ARG(n, x) \
+ [_SDT_S##n] "n" ((_SDT_ARGSIGNED (x) ? 1 : -1) * (int) _SDT_ARGSIZE (x)), \
+ [_SDT_A##n] _SDT_ARG_CONSTRAINT_STRING (STAP_SDT_ARG_CONSTRAINT) (_SDT_ARGVAL (x))
+#endif
+#define _SDT_ASM_STRING(x) _SDT_ASM_STRING_1(x)
+
+#define _SDT_ARGARRAY(x) (__builtin_classify_type (x) == 14 \
+ || __builtin_classify_type (x) == 5)
+
+#ifdef __cplusplus
+# define _SDT_ARGSIGNED(x) (!_SDT_ARGARRAY (x) \
+ && __sdt_type<__typeof (x)>::__sdt_signed)
+# define _SDT_ARGSIZE(x) (_SDT_ARGARRAY (x) \
+ ? sizeof (void *) : sizeof (x))
+# define _SDT_ARGVAL(x) (x)
+
+# include <cstddef>
+
+template<typename __sdt_T>
+struct __sdt_type
+{
+ static const bool __sdt_signed = false;
+};
+
+#define __SDT_ALWAYS_SIGNED(T) \
+template<> struct __sdt_type<T> { static const bool __sdt_signed = true; };
+#define __SDT_COND_SIGNED(T,CT) \
+template<> struct __sdt_type<T> { static const bool __sdt_signed = ((CT)(-1) < 1); };
+__SDT_ALWAYS_SIGNED(signed char)
+__SDT_ALWAYS_SIGNED(short)
+__SDT_ALWAYS_SIGNED(int)
+__SDT_ALWAYS_SIGNED(long)
+__SDT_ALWAYS_SIGNED(long long)
+__SDT_ALWAYS_SIGNED(volatile signed char)
+__SDT_ALWAYS_SIGNED(volatile short)
+__SDT_ALWAYS_SIGNED(volatile int)
+__SDT_ALWAYS_SIGNED(volatile long)
+__SDT_ALWAYS_SIGNED(volatile long long)
+__SDT_ALWAYS_SIGNED(const signed char)
+__SDT_ALWAYS_SIGNED(const short)
+__SDT_ALWAYS_SIGNED(const int)
+__SDT_ALWAYS_SIGNED(const long)
+__SDT_ALWAYS_SIGNED(const long long)
+__SDT_ALWAYS_SIGNED(const volatile signed char)
+__SDT_ALWAYS_SIGNED(const volatile short)
+__SDT_ALWAYS_SIGNED(const volatile int)
+__SDT_ALWAYS_SIGNED(const volatile long)
+__SDT_ALWAYS_SIGNED(const volatile long long)
+__SDT_COND_SIGNED(char, char)
+__SDT_COND_SIGNED(wchar_t, wchar_t)
+__SDT_COND_SIGNED(volatile char, char)
+__SDT_COND_SIGNED(volatile wchar_t, wchar_t)
+__SDT_COND_SIGNED(const char, char)
+__SDT_COND_SIGNED(const wchar_t, wchar_t)
+__SDT_COND_SIGNED(const volatile char, char)
+__SDT_COND_SIGNED(const volatile wchar_t, wchar_t)
+#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
+/* __SDT_COND_SIGNED(char16_t) */
+/* __SDT_COND_SIGNED(char32_t) */
+#endif
+
+template<typename __sdt_E>
+struct __sdt_type<__sdt_E[]> : public __sdt_type<__sdt_E *> {};
+
+template<typename __sdt_E, size_t __sdt_N>
+struct __sdt_type<__sdt_E[__sdt_N]> : public __sdt_type<__sdt_E *> {};
+
+#elif !defined(__ASSEMBLER__)
+__extension__ extern unsigned long long __sdt_unsp;
+# define _SDT_ARGINTTYPE(x) \
+ __typeof (__builtin_choose_expr (((__builtin_classify_type (x) \
+ + 3) & -4) == 4, (x), 0U))
+# define _SDT_ARGSIGNED(x) \
+ (!__extension__ \
+ (__builtin_constant_p ((((unsigned long long) \
+ (_SDT_ARGINTTYPE (x)) __sdt_unsp) \
+ & ((unsigned long long)1 << (sizeof (unsigned long long) \
+ * __CHAR_BIT__ - 1))) == 0) \
+ || (_SDT_ARGINTTYPE (x)) -1 > (_SDT_ARGINTTYPE (x)) 0))
+# define _SDT_ARGSIZE(x) \
+ (_SDT_ARGARRAY (x) ? sizeof (void *) : sizeof (x))
+# define _SDT_ARGVAL(x) (x)
+#endif
+
+#if defined __powerpc__ || defined __powerpc64__
+# define _SDT_ARGTMPL(id) %I[id]%[id]
+#elif defined __i386__
+# define _SDT_ARGTMPL(id) %w[id] /* gcc.gnu.org/PR80115 */
+#else
+# define _SDT_ARGTMPL(id) %[id]
+#endif
+
+#ifdef __LP64__
+# define _SDT_ASM_ADDR .8byte
+#else
+# define _SDT_ASM_ADDR .4byte
+#endif
+
+/* The ia64 and s390 nop instructions take an argument. */
+#if defined(__ia64__) || defined(__s390__) || defined(__s390x__)
+#define _SDT_NOP nop 0
+#else
+#define _SDT_NOP nop
+#endif
+
+#define _SDT_NOTE_NAME "stapsdt"
+#define _SDT_NOTE_TYPE 3
+
+/* If the assembler supports the necessary feature, then we can play
+ nice with code in COMDAT sections, which comes up in C++ code.
+ Without that assembler support, some combinations of probe placements
+ in certain kinds of C++ code may produce link-time errors. */
+#include "sdt-config.h"
+#if _SDT_ASM_SECTION_AUTOGROUP_SUPPORT
+# define _SDT_ASM_AUTOGROUP "?"
+#else
+# define _SDT_ASM_AUTOGROUP ""
+#endif
+
+#define _SDT_ASM_BODY(provider, name, pack_args, args) \
+ _SDT_ASM_1(990: _SDT_NOP) \
+ _SDT_ASM_3( .pushsection .note.stapsdt,_SDT_ASM_AUTOGROUP,"note") \
+ _SDT_ASM_1( .balign 4) \
+ _SDT_ASM_3( .4byte 992f-991f, 994f-993f, _SDT_NOTE_TYPE) \
+ _SDT_ASM_1(991: .asciz _SDT_NOTE_NAME) \
+ _SDT_ASM_1(992: .balign 4) \
+ _SDT_ASM_1(993: _SDT_ASM_ADDR 990b) \
+ _SDT_ASM_1( _SDT_ASM_ADDR _.stapsdt.base) \
+ _SDT_SEMAPHORE(provider,name) \
+ _SDT_ASM_STRING(provider) \
+ _SDT_ASM_STRING(name) \
+ pack_args args \
+ _SDT_ASM_1(994: .balign 4) \
+ _SDT_ASM_1( .popsection)
+
+#define _SDT_ASM_BASE \
+ _SDT_ASM_1(.ifndef _.stapsdt.base) \
+ _SDT_ASM_5( .pushsection .stapsdt.base,"aG","progbits", \
+ .stapsdt.base,comdat) \
+ _SDT_ASM_1( .weak _.stapsdt.base) \
+ _SDT_ASM_1( .hidden _.stapsdt.base) \
+ _SDT_ASM_1( _.stapsdt.base: .space 1) \
+ _SDT_ASM_2( .size _.stapsdt.base, 1) \
+ _SDT_ASM_1( .popsection) \
+ _SDT_ASM_1(.endif)
+
+#if defined _SDT_HAS_SEMAPHORES
+#define _SDT_SEMAPHORE(p,n) _SDT_ASM_1( _SDT_ASM_ADDR p##_##n##_semaphore)
+#else
+#define _SDT_SEMAPHORE(p,n) _SDT_ASM_1( _SDT_ASM_ADDR 0)
+#endif
+
+#define _SDT_ASM_TEMPLATE_0 /* no arguments */
+#define _SDT_ASM_TEMPLATE_1 _SDT_ARGFMT(1)
+#define _SDT_ASM_TEMPLATE_2 _SDT_ASM_TEMPLATE_1 _SDT_ARGFMT(2)
+#define _SDT_ASM_TEMPLATE_3 _SDT_ASM_TEMPLATE_2 _SDT_ARGFMT(3)
+#define _SDT_ASM_TEMPLATE_4 _SDT_ASM_TEMPLATE_3 _SDT_ARGFMT(4)
+#define _SDT_ASM_TEMPLATE_5 _SDT_ASM_TEMPLATE_4 _SDT_ARGFMT(5)
+#define _SDT_ASM_TEMPLATE_6 _SDT_ASM_TEMPLATE_5 _SDT_ARGFMT(6)
+#define _SDT_ASM_TEMPLATE_7 _SDT_ASM_TEMPLATE_6 _SDT_ARGFMT(7)
+#define _SDT_ASM_TEMPLATE_8 _SDT_ASM_TEMPLATE_7 _SDT_ARGFMT(8)
+#define _SDT_ASM_TEMPLATE_9 _SDT_ASM_TEMPLATE_8 _SDT_ARGFMT(9)
+#define _SDT_ASM_TEMPLATE_10 _SDT_ASM_TEMPLATE_9 _SDT_ARGFMT(10)
+#define _SDT_ASM_TEMPLATE_11 _SDT_ASM_TEMPLATE_10 _SDT_ARGFMT(11)
+#define _SDT_ASM_TEMPLATE_12 _SDT_ASM_TEMPLATE_11 _SDT_ARGFMT(12)
+#define _SDT_ASM_OPERANDS_0() [__sdt_dummy] "g" (0)
+#define _SDT_ASM_OPERANDS_1(arg1) _SDT_ARG(1, arg1)
+#define _SDT_ASM_OPERANDS_2(arg1, arg2) \
+ _SDT_ASM_OPERANDS_1(arg1), _SDT_ARG(2, arg2)
+#define _SDT_ASM_OPERANDS_3(arg1, arg2, arg3) \
+ _SDT_ASM_OPERANDS_2(arg1, arg2), _SDT_ARG(3, arg3)
+#define _SDT_ASM_OPERANDS_4(arg1, arg2, arg3, arg4) \
+ _SDT_ASM_OPERANDS_3(arg1, arg2, arg3), _SDT_ARG(4, arg4)
+#define _SDT_ASM_OPERANDS_5(arg1, arg2, arg3, arg4, arg5) \
+ _SDT_ASM_OPERANDS_4(arg1, arg2, arg3, arg4), _SDT_ARG(5, arg5)
+#define _SDT_ASM_OPERANDS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
+ _SDT_ASM_OPERANDS_5(arg1, arg2, arg3, arg4, arg5), _SDT_ARG(6, arg6)
+#define _SDT_ASM_OPERANDS_7(arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+ _SDT_ASM_OPERANDS_6(arg1, arg2, arg3, arg4, arg5, arg6), _SDT_ARG(7, arg7)
+#define _SDT_ASM_OPERANDS_8(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
+ _SDT_ASM_OPERANDS_7(arg1, arg2, arg3, arg4, arg5, arg6, arg7), \
+ _SDT_ARG(8, arg8)
+#define _SDT_ASM_OPERANDS_9(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9) \
+ _SDT_ASM_OPERANDS_8(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), \
+ _SDT_ARG(9, arg9)
+#define _SDT_ASM_OPERANDS_10(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10) \
+ _SDT_ASM_OPERANDS_9(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), \
+ _SDT_ARG(10, arg10)
+#define _SDT_ASM_OPERANDS_11(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11) \
+ _SDT_ASM_OPERANDS_10(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), \
+ _SDT_ARG(11, arg11)
+#define _SDT_ASM_OPERANDS_12(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12) \
+ _SDT_ASM_OPERANDS_11(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11), \
+ _SDT_ARG(12, arg12)
+
+/* These macros can be used in C, C++, or assembly code.
+ In assembly code the arguments should use normal assembly operand syntax. */
+
+#define STAP_PROBE(provider, name) \
+ _SDT_PROBE(provider, name, 0, ())
+#define STAP_PROBE1(provider, name, arg1) \
+ _SDT_PROBE(provider, name, 1, (arg1))
+#define STAP_PROBE2(provider, name, arg1, arg2) \
+ _SDT_PROBE(provider, name, 2, (arg1, arg2))
+#define STAP_PROBE3(provider, name, arg1, arg2, arg3) \
+ _SDT_PROBE(provider, name, 3, (arg1, arg2, arg3))
+#define STAP_PROBE4(provider, name, arg1, arg2, arg3, arg4) \
+ _SDT_PROBE(provider, name, 4, (arg1, arg2, arg3, arg4))
+#define STAP_PROBE5(provider, name, arg1, arg2, arg3, arg4, arg5) \
+ _SDT_PROBE(provider, name, 5, (arg1, arg2, arg3, arg4, arg5))
+#define STAP_PROBE6(provider, name, arg1, arg2, arg3, arg4, arg5, arg6) \
+ _SDT_PROBE(provider, name, 6, (arg1, arg2, arg3, arg4, arg5, arg6))
+#define STAP_PROBE7(provider, name, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
+ _SDT_PROBE(provider, name, 7, (arg1, arg2, arg3, arg4, arg5, arg6, arg7))
+#define STAP_PROBE8(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) \
+ _SDT_PROBE(provider, name, 8, (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8))
+#define STAP_PROBE9(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9)\
+ _SDT_PROBE(provider, name, 9, (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9))
+#define STAP_PROBE10(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10) \
+ _SDT_PROBE(provider, name, 10, \
+ (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10))
+#define STAP_PROBE11(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11) \
+ _SDT_PROBE(provider, name, 11, \
+ (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11))
+#define STAP_PROBE12(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12) \
+ _SDT_PROBE(provider, name, 12, \
+ (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12))
+
+/* This STAP_PROBEV macro can be used in variadic scenarios, where the
+ number of probe arguments is not known until compile time. Since
+ variadic macro support may vary with compiler options, you must
+ pre-#define SDT_USE_VARIADIC to enable this type of probe.
+
+ The trick to count __VA_ARGS__ was inspired by this post by
+ Laurent Deniau <laurent.deniau@cern.ch>:
+ http://groups.google.com/group/comp.std.c/msg/346fc464319b1ee5
+
+ Note that our _SDT_NARG is called with an extra 0 arg that's not
+ counted, so we don't have to worry about the behavior of macros
+ called without any arguments. */
+
+#ifdef SDT_USE_VARIADIC
+#define _SDT_NARG(...) __SDT_NARG(__VA_ARGS__, 12,11,10,9,8,7,6,5,4,3,2,1,0)
+#define __SDT_NARG(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12, N, ...) N
+#define _SDT_PROBE_N(provider, name, N, ...) \
+ _SDT_PROBE(provider, name, N, (__VA_ARGS__))
+#define STAP_PROBEV(provider, name, ...) \
+ _SDT_PROBE_N(provider, name, _SDT_NARG(0, ##__VA_ARGS__), ##__VA_ARGS__)
+#endif
+
+/* These macros are for use in asm statements. You must compile
+ with -std=gnu99 or -std=c99 to use the STAP_PROBE_ASM macro.
+
+ The STAP_PROBE_ASM macro generates a quoted string to be used in the
+ template portion of the asm statement, concatenated with strings that
+ contain the actual assembly code around the probe site.
+
+ For example:
+
+ asm ("before\n"
+ STAP_PROBE_ASM(provider, fooprobe, %eax 4(%esi))
+ "after");
+
+ emits the assembly code for "before\nafter", with a probe in between.
+ The probe arguments are the %eax register, and the value of the memory
+ word located 4 bytes past the address in the %esi register. Note that
+ because this is a simple asm, not a GNU C extended asm statement, these
+ % characters do not need to be doubled to generate literal %reg names.
+
+ In a GNU C extended asm statement, the probe arguments can be specified
+ using the macro STAP_PROBE_ASM_TEMPLATE(n) for n arguments. The paired
+ macro STAP_PROBE_ASM_OPERANDS gives the C values of these probe arguments,
+ and appears in the input operand list of the asm statement. For example:
+
+ asm ("someinsn %0,%1\n" // %0 is output operand, %1 is input operand
+ STAP_PROBE_ASM(provider, fooprobe, STAP_PROBE_ASM_TEMPLATE(3))
+ "otherinsn %[namedarg]"
+ : "r" (outvar)
+ : "g" (some_value), [namedarg] "i" (1234),
+ STAP_PROBE_ASM_OPERANDS(3, some_value, some_ptr->field, 1234));
+
+ This is just like writing:
+
+ STAP_PROBE3(provider, fooprobe, some_value, some_ptr->field, 1234));
+
+ but the probe site is right between "someinsn" and "otherinsn".
+
+ The probe arguments in STAP_PROBE_ASM can be given as assembly
+ operands instead, even inside a GNU C extended asm statement.
+ Note that these can use operand templates like %0 or %[name],
+ and likewise they must write %%reg for a literal operand of %reg. */
+
+#if __STDC_VERSION__ >= 199901L
+# define STAP_PROBE_ASM(provider, name, ...) \
+ _SDT_ASM_BODY(provider, name, _SDT_ASM_STRING, (__VA_ARGS__)) \
+ _SDT_ASM_BASE
+# define STAP_PROBE_ASM_OPERANDS(n, ...) _SDT_ASM_OPERANDS_##n(__VA_ARGS__)
+#else
+# define STAP_PROBE_ASM(provider, name, args) \
+ _SDT_ASM_BODY(provider, name, _SDT_ASM_STRING, (args)) \
+ _SDT_ASM_BASE
+#endif
+#define STAP_PROBE_ASM_TEMPLATE(n) _SDT_ASM_TEMPLATE_##n
+
+
+/* DTrace compatible macro names. */
+#define DTRACE_PROBE(provider,probe) \
+ STAP_PROBE(provider,probe)
+#define DTRACE_PROBE1(provider,probe,parm1) \
+ STAP_PROBE1(provider,probe,parm1)
+#define DTRACE_PROBE2(provider,probe,parm1,parm2) \
+ STAP_PROBE2(provider,probe,parm1,parm2)
+#define DTRACE_PROBE3(provider,probe,parm1,parm2,parm3) \
+ STAP_PROBE3(provider,probe,parm1,parm2,parm3)
+#define DTRACE_PROBE4(provider,probe,parm1,parm2,parm3,parm4) \
+ STAP_PROBE4(provider,probe,parm1,parm2,parm3,parm4)
+#define DTRACE_PROBE5(provider,probe,parm1,parm2,parm3,parm4,parm5) \
+ STAP_PROBE5(provider,probe,parm1,parm2,parm3,parm4,parm5)
+#define DTRACE_PROBE6(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6) \
+ STAP_PROBE6(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6)
+#define DTRACE_PROBE7(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \
+ STAP_PROBE7(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7)
+#define DTRACE_PROBE8(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \
+ STAP_PROBE8(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8)
+#define DTRACE_PROBE9(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \
+ STAP_PROBE9(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9)
+#define DTRACE_PROBE10(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \
+ STAP_PROBE10(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10)
+#define DTRACE_PROBE11(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11) \
+ STAP_PROBE11(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11)
+#define DTRACE_PROBE12(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11,parm12) \
+ STAP_PROBE12(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11,parm12)
+
+
+#endif /* sys/sdt.h */