diff options
-rw-r--r-- | .SRCINFO | 26 | ||||
-rw-r--r-- | 0001-Revert-elf-Correct-absolute-SHN_ABS-symbol-run-time-.patch | 194 | ||||
-rw-r--r-- | PKGBUILD | 24 | ||||
-rw-r--r-- | bz20338.patch | 8 | ||||
-rw-r--r-- | glibc-34fb5f61d3c3f4b8fc616ea259fa19168b58ecd4.patch | 4059 | ||||
-rw-r--r-- | glibc-a6aaabd036d735a1b412f441bf6c706832655598.patch | 414 | ||||
-rw-r--r-- | sdt-config.h | 6 | ||||
-rw-r--r-- | sdt.h | 430 |
8 files changed, 883 insertions, 4278 deletions
@@ -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 - @@ -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 */ |