0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-02 09:46:52 -05:00

Merge bitcoin/bitcoin#22365: guix: Avoid relying on newer symbols by rebasing our cross toolchains on older glibcs

647f7e5f1d guix: Also sort SHA256SUMS.part (Carl Dong)
dc4137a60c guix: Build depends/qt with our platform definition (Carl Dong)
16b0a936e1 guix: Rebase toolchain on glibc 2.24 (2.27 for riscv64) (Carl Dong)

Pull request description:

  After this PR, we'll have the following:
  - riscv64 -> build with a toolchain targeting glibc 2.27
  - everything else -> builds with a toolchain targeting glibc 2.24, but will not have symbols > 2.17 (checked by `symbol-check.py`)

ACKs for top commit:
  achow101:
    reACK 647f7e5f1d
  hebasto:
    ACK 647f7e5f1d
  MarcoFalke:
    review ACK 647f7e5f1d
  fanquake:
    ACK 647f7e5f1d - documentation can be fixed shortly.

Tree-SHA512: ddff57a5d7c053687b0a273720d4ad7d28c6fc8816226d4304869284d017af5e3630d4b57565d91e74f2e1b7583c9c83ee8b2e5e70e41d619ab618e602c97a94
This commit is contained in:
fanquake 2021-07-05 22:40:08 +08:00
commit 2711559845
No known key found for this signature in database
GPG key ID: 2EEB9F5CC09526C1
8 changed files with 522 additions and 2 deletions

View file

@ -214,6 +214,7 @@ make -C depends --jobs="$JOBS" HOST="$HOST" \
x86_64_linux_NM=x86_64-linux-gnu-nm \
x86_64_linux_STRIP=x86_64-linux-gnu-strip \
qt_config_opts_i686_linux='-platform linux-g++ -xplatform bitcoin-linux-g++' \
qt_config_opts_x86_64_linux='-platform linux-g++ -xplatform bitcoin-linux-g++' \
FORCE_USE_SYSTEM_CLANG=1
@ -445,5 +446,6 @@ mv --no-target-directory "$OUTDIR" "$ACTUAL_OUTDIR" \
find "$ACTUAL_OUTDIR" -type f
} | xargs realpath --relative-base="$PWD" \
| xargs sha256sum \
| sort -k2 \
| sponge "$ACTUAL_OUTDIR"/SHA256SUMS.part
)

View file

@ -108,5 +108,6 @@ mv --no-target-directory "$OUTDIR" "$ACTUAL_OUTDIR" \
find "$ACTUAL_OUTDIR" -type f
} | xargs realpath --relative-base="$PWD" \
| xargs sha256sum \
| sort -k2 \
| sponge "$ACTUAL_OUTDIR"/SHA256SUMS.part
)

View file

@ -135,11 +135,25 @@ chain for " target " development."))
(package-with-extra-patches gcc-8
(search-our-patches "gcc-8-sort-libtool-find-output.patch")))
;; Building glibc with stack smashing protector first landed in glibc 2.25, use
;; this function to disable for older glibcs
;;
;; From glibc 2.25 changelog:
;;
;; * Most of glibc can now be built with the stack smashing protector enabled.
;; It is recommended to build glibc with --enable-stack-protector=strong.
;; Implemented by Nick Alcock (Oracle).
(define (make-glibc-without-ssp xglibc)
(package-with-extra-configure-variable
(package-with-extra-configure-variable
xglibc "libc_cv_ssp" "no")
"libc_cv_ssp_strong" "no"))
(define* (make-bitcoin-cross-toolchain target
#:key
(base-gcc-for-libc gcc-7)
(base-kernel-headers linux-libre-headers-5.4)
(base-libc glibc) ; glibc 2.31
(base-libc (make-glibc-without-ssp glibc-2.24))
(base-gcc (make-gcc-rpath-link base-gcc)))
"Convenience wrapper around MAKE-CROSS-TOOLCHAIN with default values
desirable for building Bitcoin Core release binaries."
@ -557,6 +571,28 @@ and endian independent.")
inspecting signatures in Mach-O binaries.")
(license license:expat))))
(define-public glibc-2.24
(package
(inherit glibc)
(version "2.24")
(source (origin
(method git-fetch)
(uri (git-reference
(url "https://sourceware.org/git/glibc.git")
(commit "0d7f1ed30969886c8dde62fbf7d2c79967d4bace")))
(file-name (git-file-name "glibc" "0d7f1ed30969886c8dde62fbf7d2c79967d4bace"))
(sha256
(base32
"0g5hryia5v1k0qx97qffgwzrz4lr4jw3s5kj04yllhswsxyjbic3"))
(patches (search-our-patches "glibc-ldd-x86_64.patch"
"glibc-versioned-locpath.patch"
"glibc-2.24-elfm-loadaddr-dynamic-rewrite.patch"
"glibc-2.24-no-build-time-cxx-header-run.patch"))))))
(define glibc-2.27/bitcoin-patched
(package-with-extra-patches glibc-2.27
(search-our-patches "glibc-2.27-riscv64-Use-__has_include__-to-include-asm-syscalls.h.patch")))
(packages->manifest
(append
(list ;; The Basics
@ -606,7 +642,10 @@ inspecting signatures in Mach-O binaries.")
(make-nsis-with-sde-support nsis-x86_64)
osslsigncode))
((string-contains target "-linux-")
(list (make-bitcoin-cross-toolchain target)))
(list (cond ((string-contains target "riscv64-")
(make-bitcoin-cross-toolchain target #:base-libc glibc-2.27/bitcoin-patched))
(else
(make-bitcoin-cross-toolchain target)))))
((string-contains target "darwin")
(list clang-toolchain-10 binutils imagemagick libtiff librsvg font-tuffy cmake xorriso python-signapple))
(else '())))))

View file

@ -0,0 +1,60 @@
commit 6b02af31e9a721bb15a11380cd22d53b621711f8
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
Date: Wed Oct 18 17:26:23 2017 +0100
[AARCH64] Rewrite elf_machine_load_address using _DYNAMIC symbol
This patch rewrites aarch64 elf_machine_load_address to use special _DYNAMIC
symbol instead of _dl_start.
The static address of _DYNAMIC symbol is stored in the first GOT entry.
Here is the change which makes this solution work (part of binutils 2.24):
https://sourceware.org/ml/binutils/2013-06/msg00248.html
i386, x86_64 targets use the same method to do this as well.
The original implementation relies on a trick that R_AARCH64_ABS32 relocation
being resolved at link time and the static address fits in the 32bits.
However, in LP64, normally, the address is defined to be 64 bit.
Here is the C version one which should be portable in all cases.
* sysdeps/aarch64/dl-machine.h (elf_machine_load_address): Use
_DYNAMIC symbol to calculate load address.
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
index e86d8b5b63..5a5b8a5de5 100644
--- a/sysdeps/aarch64/dl-machine.h
+++ b/sysdeps/aarch64/dl-machine.h
@@ -49,26 +49,11 @@ elf_machine_load_address (void)
/* To figure out the load address we use the definition that for any symbol:
dynamic_addr(symbol) = static_addr(symbol) + load_addr
- The choice of symbol is arbitrary. The static address we obtain
- by constructing a non GOT reference to the symbol, the dynamic
- address of the symbol we compute using adrp/add to compute the
- symbol's address relative to the PC.
- This depends on 32bit relocations being resolved at link time
- and that the static address fits in the 32bits. */
-
- ElfW(Addr) static_addr;
- ElfW(Addr) dynamic_addr;
-
- asm (" \n"
-" adrp %1, _dl_start; \n"
-" add %1, %1, #:lo12:_dl_start \n"
-" ldr %w0, 1f \n"
-" b 2f \n"
-"1: \n"
-" .word _dl_start \n"
-"2: \n"
- : "=r" (static_addr), "=r" (dynamic_addr));
- return dynamic_addr - static_addr;
+ _DYNAMIC sysmbol is used here as its link-time address stored in
+ the special unrelocated first GOT entry. */
+
+ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
+ return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic ();
}
/* Set up the loaded object described by L so its unrelocated PLT

View file

@ -0,0 +1,98 @@
commit dc23a45db566095e83ff0b7a57afc87fb5ca89a1
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Sep 21 10:45:32 2016 +0200
Avoid running $(CXX) during build to obtain header file paths
This reduces the build time somewhat and is particularly noticeable
during rebuilds with few code changes.
diff --git a/Makerules b/Makerules
index 7e4077ee50..c338850de5 100644
--- a/Makerules
+++ b/Makerules
@@ -121,14 +121,10 @@ ifneq (,$(CXX))
# will be used instead of /usr/include/stdlib.h and /usr/include/math.h.
before-compile := $(common-objpfx)cstdlib $(common-objpfx)cmath \
$(before-compile)
-cstdlib=$(shell echo "\#include <cstdlib>" | $(CXX) -M -MP -x c++ - \
- | sed -n "/cstdlib:/{s/:$$//;p}")
-$(common-objpfx)cstdlib: $(cstdlib)
+$(common-objpfx)cstdlib: $(c++-cstdlib-header)
$(INSTALL_DATA) $< $@T
$(move-if-change) $@T $@
-cmath=$(shell echo "\#include <cmath>" | $(CXX) -M -MP -x c++ - \
- | sed -n "/cmath:/{s/:$$//;p}")
-$(common-objpfx)cmath: $(cmath)
+$(common-objpfx)cmath: $(c++-cmath-header)
$(INSTALL_DATA) $< $@T
$(move-if-change) $@T $@
endif
diff --git a/config.make.in b/config.make.in
index 95c6f36876..04a8b3ed7f 100644
--- a/config.make.in
+++ b/config.make.in
@@ -45,6 +45,8 @@ defines = @DEFINES@
sysheaders = @sysheaders@
sysincludes = @SYSINCLUDES@
c++-sysincludes = @CXX_SYSINCLUDES@
+c++-cstdlib-header = @CXX_CSTDLIB_HEADER@
+c++-cmath-header = @CXX_CMATH_HEADER@
all-warnings = @all_warnings@
enable-werror = @enable_werror@
diff --git a/configure b/configure
index 17625e1041..6ff252744b 100755
--- a/configure
+++ b/configure
@@ -635,6 +635,8 @@ BISON
INSTALL_INFO
PERL
BASH_SHELL
+CXX_CMATH_HEADER
+CXX_CSTDLIB_HEADER
CXX_SYSINCLUDES
SYSINCLUDES
AUTOCONF
@@ -5054,6 +5056,18 @@ fi
+# Obtain some C++ header file paths. This is used to make a local
+# copy of those headers in Makerules.
+if test -n "$CXX"; then
+ find_cxx_header () {
+ echo "#include <$1>" | $CXX -M -MP -x c++ - | sed -n "/$1:/{s/:\$//;p}"
+ }
+ CXX_CSTDLIB_HEADER="$(find_cxx_header cstdlib)"
+ CXX_CMATH_HEADER="$(find_cxx_header cmath)"
+fi
+
+
+
# Test if LD_LIBRARY_PATH contains the notation for the current directory
# since this would lead to problems installing/building glibc.
# LD_LIBRARY_PATH contains the current directory if one of the following
diff --git a/configure.ac b/configure.ac
index 33bcd62180..9938ab0dc2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1039,6 +1039,18 @@ fi
AC_SUBST(SYSINCLUDES)
AC_SUBST(CXX_SYSINCLUDES)
+# Obtain some C++ header file paths. This is used to make a local
+# copy of those headers in Makerules.
+if test -n "$CXX"; then
+ find_cxx_header () {
+ echo "#include <$1>" | $CXX -M -MP -x c++ - | sed -n "/$1:/{s/:\$//;p}"
+ }
+ CXX_CSTDLIB_HEADER="$(find_cxx_header cstdlib)"
+ CXX_CMATH_HEADER="$(find_cxx_header cmath)"
+fi
+AC_SUBST(CXX_CSTDLIB_HEADER)
+AC_SUBST(CXX_CMATH_HEADER)
+
# Test if LD_LIBRARY_PATH contains the notation for the current directory
# since this would lead to problems installing/building glibc.
# LD_LIBRARY_PATH contains the current directory if one of the following

View file

@ -0,0 +1,70 @@
From 562c52cc81a4e456a62e6455feb32732049e9070 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 31 Dec 2018 09:26:42 -0800
Subject: [PATCH] riscv: Use __has_include__ to include <asm/syscalls.h> [BZ
#24022]
<asm/syscalls.h> has been removed by
commit 27f8899d6002e11a6e2d995e29b8deab5aa9cc25
Author: David Abdurachmanov <david.abdurachmanov@gmail.com>
Date: Thu Nov 8 20:02:39 2018 +0100
riscv: add asm/unistd.h UAPI header
Marcin Juszkiewicz reported issues while generating syscall table for riscv
using 4.20-rc1. The patch refactors our unistd.h files to match some other
architectures.
- Add asm/unistd.h UAPI header, which has __ARCH_WANT_NEW_STAT only for 64-bit
- Remove asm/syscalls.h UAPI header and merge to asm/unistd.h
- Adjust kernel asm/unistd.h
So now asm/unistd.h UAPI header should show all syscalls for riscv.
<asm/syscalls.h> may be restored by
Subject: [PATCH] riscv: restore asm/syscalls.h UAPI header
Date: Tue, 11 Dec 2018 09:09:35 +0100
UAPI header asm/syscalls.h was merged into UAPI asm/unistd.h header,
which did resolve issue with missing syscalls macros resulting in
glibc (2.28) build failure. It also broke glibc in a different way:
asm/syscalls.h is being used by glibc. I noticed this while doing
Fedora 30/Rawhide mass rebuild.
The patch returns asm/syscalls.h header and incl. it into asm/unistd.h.
I plan to send a patch to glibc to use asm/unistd.h instead of
asm/syscalls.h
In the meantime, we use __has_include__, which was added to GCC 5, to
check if <asm/syscalls.h> exists before including it. Tested with
build-many-glibcs.py for riscv against kernel 4.19.12 and 4.20-rc7.
[BZ #24022]
* sysdeps/unix/sysv/linux/riscv/flush-icache.c: Check if
<asm/syscalls.h> exists with __has_include__ before including it.
---
sysdeps/unix/sysv/linux/riscv/flush-icache.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/sysdeps/unix/sysv/linux/riscv/flush-icache.c b/sysdeps/unix/sysv/linux/riscv/flush-icache.c
index d612ef4c6c..0b2042620b 100644
--- a/sysdeps/unix/sysv/linux/riscv/flush-icache.c
+++ b/sysdeps/unix/sysv/linux/riscv/flush-icache.c
@@ -21,7 +21,11 @@
#include <stdlib.h>
#include <atomic.h>
#include <sys/cachectl.h>
-#include <asm/syscalls.h>
+#if __has_include__ (<asm/syscalls.h>)
+# include <asm/syscalls.h>
+#else
+# include <asm/unistd.h>
+#endif
typedef int (*func_type) (void *, void *, unsigned long int);
--
2.31.1

View file

@ -0,0 +1,10 @@
By default, 'RTDLLIST' in 'ldd' refers to 'lib64/ld-linux-x86-64.so', whereas
it's in 'lib/' for us. This patch fixes that.
--- glibc-2.17/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed 2012-12-25 04:02:13.000000000 +0100
+++ glibc-2.17/sysdeps/unix/sysv/linux/x86_64/ldd-rewrite.sed 2013-09-15 23:08:03.000000000 +0200
@@ -1,3 +1,3 @@
/LD_TRACE_LOADED_OBJECTS=1/a\
add_env="$add_env LD_LIBRARY_VERSION=\\$verify_out"
-s_^\(RTLDLIST=\)\(.*lib\)\(\|64\|x32\)\(/[^/]*\)\(-x86-64\|-x32\)\(\.so\.[0-9.]*\)[ ]*$_\1"\2\4\6 \264\4-x86-64\6 \2x32\4-x32\6"_
+s_^\(RTLDLIST=\)\(.*lib\)\(\|64\|x32\)\(/[^/]*\)\(-x86-64\|-x32\)\(\.so\.[0-9.]*\)[ ]*$_\1"\2\4\6 \2\4-x86-64\6 \2x32\4-x32\6"_

View file

@ -0,0 +1,240 @@
The format of locale data can be incompatible between libc versions, and
loading incompatible data can lead to 'setlocale' returning EINVAL at best
or triggering an assertion failure at worst. See
https://lists.gnu.org/archive/html/guix-devel/2015-09/msg00717.html
for background information.
To address that, this patch changes libc to honor a new 'GUIX_LOCPATH'
variable, and to look for locale data in version-specific sub-directories of
that variable. So, if GUIX_LOCPATH=/foo:/bar, locale data is searched for in
/foo/X.Y and /bar/X.Y, where X.Y is the libc version number.
That way, a single 'GUIX_LOCPATH' setting can work even if different libc
versions coexist on the system.
--- a/locale/newlocale.c
+++ b/locale/newlocale.c
@@ -30,6 +30,7 @@
/* Lock for protecting global data. */
__libc_rwlock_define (extern , __libc_setlocale_lock attribute_hidden)
+extern error_t compute_locale_search_path (char **, size_t *);
/* Use this when we come along an error. */
#define ERROR_RETURN \
@@ -48,7 +49,6 @@ __newlocale (int category_mask, const char *locale, __locale_t base)
__locale_t result_ptr;
char *locale_path;
size_t locale_path_len;
- const char *locpath_var;
int cnt;
size_t names_len;
@@ -102,17 +102,8 @@ __newlocale (int category_mask, const char *locale, __locale_t base)
locale_path = NULL;
locale_path_len = 0;
- locpath_var = getenv ("LOCPATH");
- if (locpath_var != NULL && locpath_var[0] != '\0')
- {
- if (__argz_create_sep (locpath_var, ':',
- &locale_path, &locale_path_len) != 0)
- return NULL;
-
- if (__argz_add_sep (&locale_path, &locale_path_len,
- _nl_default_locale_path, ':') != 0)
- return NULL;
- }
+ if (compute_locale_search_path (&locale_path, &locale_path_len) != 0)
+ return NULL;
/* Get the names for the locales we are interested in. We either
allow a composite name or a single name. */
diff --git a/locale/setlocale.c b/locale/setlocale.c
index ead030d..0c0e314 100644
--- a/locale/setlocale.c
+++ b/locale/setlocale.c
@@ -215,12 +215,65 @@ setdata (int category, struct __locale_data *data)
}
}
+/* Return in *LOCALE_PATH and *LOCALE_PATH_LEN the locale data search path as
+ a colon-separated list. Return ENOMEN on error, zero otherwise. */
+error_t
+compute_locale_search_path (char **locale_path, size_t *locale_path_len)
+{
+ char* guix_locpath_var = getenv ("GUIX_LOCPATH");
+ char *locpath_var = getenv ("LOCPATH");
+
+ if (guix_locpath_var != NULL && guix_locpath_var[0] != '\0')
+ {
+ /* Entries in 'GUIX_LOCPATH' take precedence over 'LOCPATH'. These
+ entries are systematically prefixed with "/X.Y" where "X.Y" is the
+ libc version. */
+ if (__argz_create_sep (guix_locpath_var, ':',
+ locale_path, locale_path_len) != 0
+ || __argz_suffix_entries (locale_path, locale_path_len,
+ "/" VERSION) != 0)
+ goto bail_out;
+ }
+
+ if (locpath_var != NULL && locpath_var[0] != '\0')
+ {
+ char *reg_locale_path = NULL;
+ size_t reg_locale_path_len = 0;
+
+ if (__argz_create_sep (locpath_var, ':',
+ &reg_locale_path, &reg_locale_path_len) != 0)
+ goto bail_out;
+
+ if (__argz_append (locale_path, locale_path_len,
+ reg_locale_path, reg_locale_path_len) != 0)
+ goto bail_out;
+
+ free (reg_locale_path);
+ }
+
+ if (*locale_path != NULL)
+ {
+ /* Append the system default locale directory. */
+ if (__argz_add_sep (locale_path, locale_path_len,
+ _nl_default_locale_path, ':') != 0)
+ goto bail_out;
+ }
+
+ return 0;
+
+ bail_out:
+ free (*locale_path);
+ *locale_path = NULL;
+ *locale_path_len = 0;
+
+ return ENOMEM;
+}
+
char *
setlocale (int category, const char *locale)
{
char *locale_path;
size_t locale_path_len;
- const char *locpath_var;
char *composite;
/* Sanity check for CATEGORY argument. */
@@ -251,17 +304,10 @@ setlocale (int category, const char *locale)
locale_path = NULL;
locale_path_len = 0;
- locpath_var = getenv ("LOCPATH");
- if (locpath_var != NULL && locpath_var[0] != '\0')
+ if (compute_locale_search_path (&locale_path, &locale_path_len) != 0)
{
- if (__argz_create_sep (locpath_var, ':',
- &locale_path, &locale_path_len) != 0
- || __argz_add_sep (&locale_path, &locale_path_len,
- _nl_default_locale_path, ':') != 0)
- {
- __libc_rwlock_unlock (__libc_setlocale_lock);
- return NULL;
- }
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+ return NULL;
}
if (category == LC_ALL)
diff --git a/string/Makefile b/string/Makefile
index 8424a61..f925503 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -38,7 +38,7 @@ routines := strcat strchr strcmp strcoll strcpy strcspn \
swab strfry memfrob memmem rawmemchr strchrnul \
$(addprefix argz-,append count create ctsep next \
delete extract insert stringify \
- addsep replace) \
+ addsep replace suffix) \
envz basename \
strcoll_l strxfrm_l string-inlines memrchr \
xpg-strerror strerror_l
diff --git a/string/argz-suffix.c b/string/argz-suffix.c
new file mode 100644
index 0000000..505b0f2
--- /dev/null
+++ b/string/argz-suffix.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2015 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ludovic Courtès <ludo@gnu.org>.
+
+ 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 <argz.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+error_t
+__argz_suffix_entries (char **argz, size_t *argz_len, const char *suffix)
+
+{
+ size_t suffix_len = strlen (suffix);
+ size_t count = __argz_count (*argz, *argz_len);
+ size_t new_argz_len = *argz_len + count * suffix_len;
+ char *new_argz = malloc (new_argz_len);
+
+ if (new_argz)
+ {
+ char *p = new_argz, *entry;
+
+ for (entry = *argz;
+ entry != NULL;
+ entry = argz_next (*argz, *argz_len, entry))
+ {
+ p = stpcpy (p, entry);
+ p = stpcpy (p, suffix);
+ p++;
+ }
+
+ free (*argz);
+ *argz = new_argz;
+ *argz_len = new_argz_len;
+
+ return 0;
+ }
+ else
+ return ENOMEM;
+}
+weak_alias (__argz_suffix_entries, argz_suffix_entries)
diff --git a/string/argz.h b/string/argz.h
index bb62a31..d276a35 100644
--- a/string/argz.h
+++ b/string/argz.h
@@ -134,6 +134,16 @@ extern error_t argz_replace (char **__restrict __argz,
const char *__restrict __str,
const char *__restrict __with,
unsigned int *__restrict __replace_count);
+
+/* Suffix each entry of ARGZ & ARGZ_LEN with SUFFIX. Return 0 on success,
+ and ENOMEN if memory cannot be allocated. */
+extern error_t __argz_suffix_entries (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ const char *__restrict __suffix);
+extern error_t argz_suffix_entries (char **__restrict __argz,
+ size_t *__restrict __argz_len,
+ const char *__restrict __suffix);
+
/* Returns the next entry in ARGZ & ARGZ_LEN after ENTRY, or NULL if there
are no more. If entry is NULL, then the first entry is returned. This