diff --git a/0083-CVE-2023-4527.patch b/0083-CVE-2023-4527.patch deleted file mode 100644 index 2f71bc4..0000000 --- a/0083-CVE-2023-4527.patch +++ /dev/null @@ -1,194 +0,0 @@ -From 4ea972b7edd7e36610e8cde18bf7a8149d7bac4f Mon Sep 17 00:00:00 2001 -From: Florian Weimer -Date: Wed, 13 Sep 2023 14:10:56 +0200 -Subject: [PATCH] CVE-2023-4527: Stack read overflow with large TCP responses - in no-aaaa mode - -Without passing alt_dns_packet_buffer, __res_context_search can only -store 2048 bytes (what fits into dns_packet_buffer). However, -the function returns the total packet size, and the subsequent -DNS parsing code in _nss_dns_gethostbyname4_r reads beyond the end -of the stack-allocated buffer. - -Fixes commit f282cdbe7f436c75864e5640a4 ("resolv: Implement no-aaaa -stub resolver option") and bug 30842. - -(cherry picked from commit bd77dd7e73e3530203be1c52c8a29d08270cb25d) ---- - resolv/Makefile | 2 + - resolv/nss_dns/dns-host.c | 2 +- - resolv/tst-resolv-noaaaa-vc.c | 129 ++++++++++++++++++++++++++++++++++ - 4 files changed, 139 insertions(+), 1 deletion(-) - create mode 100644 resolv/tst-resolv-noaaaa-vc.c - -diff --git a/resolv/Makefile b/resolv/Makefile -index f8a92c6cff..28cedf49ee 100644 ---- a/resolv/Makefile -+++ b/resolv/Makefile -@@ -101,6 +101,7 @@ tests += \ - tst-resolv-invalid-cname \ - tst-resolv-network \ - tst-resolv-noaaaa \ -+ tst-resolv-noaaaa-vc \ - tst-resolv-nondecimal \ - tst-resolv-res_init-multi \ - tst-resolv-search \ -@@ -291,6 +292,7 @@ $(objpfx)tst-resolv-res_init-thread: $(objpfx)libresolv.so \ - $(objpfx)tst-resolv-invalid-cname: $(objpfx)libresolv.so \ - $(shared-thread-library) - $(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library) -+$(objpfx)tst-resolv-noaaaa-vc: $(objpfx)libresolv.so $(shared-thread-library) - $(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library) - $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library) - $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library) -diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c -index 9fa81f23c8..227734da5c 100644 ---- a/resolv/nss_dns/dns-host.c -+++ b/resolv/nss_dns/dns-host.c -@@ -427,7 +427,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, - { - n = __res_context_search (ctx, name, C_IN, T_A, - dns_packet_buffer, sizeof (dns_packet_buffer), -- NULL, NULL, NULL, NULL, NULL); -+ &alt_dns_packet_buffer, NULL, NULL, NULL, NULL); - if (n >= 0) - status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n, - &abuf, pat, errnop, herrnop, ttlp); -diff --git a/resolv/tst-resolv-noaaaa-vc.c b/resolv/tst-resolv-noaaaa-vc.c -new file mode 100644 -index 0000000000..9f5aebd99f ---- /dev/null -+++ b/resolv/tst-resolv-noaaaa-vc.c -@@ -0,0 +1,129 @@ -+/* Test the RES_NOAAAA resolver option with a large response. -+ Copyright (C) 2022-2023 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Used to keep track of the number of queries. */ -+static volatile unsigned int queries; -+ -+/* If true, add a large TXT record at the start of the answer section. */ -+static volatile bool stuff_txt; -+ -+static void -+response (const struct resolv_response_context *ctx, -+ struct resolv_response_builder *b, -+ const char *qname, uint16_t qclass, uint16_t qtype) -+{ -+ /* If not using TCP, just force its use. */ -+ if (!ctx->tcp) -+ { -+ struct resolv_response_flags flags = {.tc = true}; -+ resolv_response_init (b, flags); -+ resolv_response_add_question (b, qname, qclass, qtype); -+ return; -+ } -+ -+ /* The test needs to send four queries, the first three are used to -+ grow the NSS buffer via the ERANGE handshake. */ -+ ++queries; -+ TEST_VERIFY (queries <= 4); -+ -+ /* AAAA queries are supposed to be disabled. */ -+ TEST_COMPARE (qtype, T_A); -+ TEST_COMPARE (qclass, C_IN); -+ TEST_COMPARE_STRING (qname, "example.com"); -+ -+ struct resolv_response_flags flags = {}; -+ resolv_response_init (b, flags); -+ resolv_response_add_question (b, qname, qclass, qtype); -+ -+ resolv_response_section (b, ns_s_an); -+ -+ if (stuff_txt) -+ { -+ resolv_response_open_record (b, qname, qclass, T_TXT, 60); -+ int zero = 0; -+ for (int i = 0; i <= 15000; ++i) -+ resolv_response_add_data (b, &zero, sizeof (zero)); -+ resolv_response_close_record (b); -+ } -+ -+ for (int i = 0; i < 200; ++i) -+ { -+ resolv_response_open_record (b, qname, qclass, qtype, 60); -+ char ipv4[4] = {192, 0, 2, i + 1}; -+ resolv_response_add_data (b, &ipv4, sizeof (ipv4)); -+ resolv_response_close_record (b); -+ } -+} -+ -+static int -+do_test (void) -+{ -+ struct resolv_test *obj = resolv_test_start -+ ((struct resolv_redirect_config) -+ { -+ .response_callback = response -+ }); -+ -+ _res.options |= RES_NOAAAA; -+ -+ for (int do_stuff_txt = 0; do_stuff_txt < 2; ++do_stuff_txt) -+ { -+ queries = 0; -+ stuff_txt = do_stuff_txt; -+ -+ struct addrinfo *ai = NULL; -+ int ret; -+ ret = getaddrinfo ("example.com", "80", -+ &(struct addrinfo) -+ { -+ .ai_family = AF_UNSPEC, -+ .ai_socktype = SOCK_STREAM, -+ }, &ai); -+ -+ char *expected_result; -+ { -+ struct xmemstream mem; -+ xopen_memstream (&mem); -+ for (int i = 0; i < 200; ++i) -+ fprintf (mem.out, "address: STREAM/TCP 192.0.2.%d 80\n", i + 1); -+ xfclose_memstream (&mem); -+ expected_result = mem.buffer; -+ } -+ -+ check_addrinfo ("example.com", ai, ret, expected_result); -+ -+ free (expected_result); -+ freeaddrinfo (ai); -+ } -+ -+ resolv_test_end (obj); -+ return 0; -+} -+ -+#include --- -2.39.3 - diff --git a/0084-CVE-2023-4806.patch b/0084-CVE-2023-4806.patch deleted file mode 100644 index 1e7f10b..0000000 --- a/0084-CVE-2023-4806.patch +++ /dev/null @@ -1,338 +0,0 @@ -From a9728f798ec7f05454c95637ee6581afaa9b487d Mon Sep 17 00:00:00 2001 -From: Siddhesh Poyarekar -Date: Fri, 15 Sep 2023 13:51:12 -0400 -Subject: [PATCH] getaddrinfo: Fix use after free in getcanonname - (CVE-2023-4806) - -When an NSS plugin only implements the _gethostbyname2_r and -_getcanonname_r callbacks, getaddrinfo could use memory that was freed -during tmpbuf resizing, through h_name in a previous query response. - -The backing store for res->at->name when doing a query with -gethostbyname3_r or gethostbyname2_r is tmpbuf, which is reallocated in -gethosts during the query. For AF_INET6 lookup with AI_ALL | -AI_V4MAPPED, gethosts gets called twice, once for a v6 lookup and second -for a v4 lookup. In this case, if the first call reallocates tmpbuf -enough number of times, resulting in a malloc, th->h_name (that -res->at->name refers to) ends up on a heap allocated storage in tmpbuf. -Now if the second call to gethosts also causes the plugin callback to -return NSS_STATUS_TRYAGAIN, tmpbuf will get freed, resulting in a UAF -reference in res->at->name. This then gets dereferenced in the -getcanonname_r plugin call, resulting in the use after free. - -Fix this by copying h_name over and freeing it at the end. This -resolves BZ #30843, which is assigned CVE-2023-4806. - -Signed-off-by: Siddhesh Poyarekar -(cherry picked from commit 973fe93a5675c42798b2161c6f29c01b0e243994) ---- - nss/Makefile | 15 ++++- - nss/nss_test_gai_hv2_canonname.c | 56 +++++++++++++++++ - nss/tst-nss-gai-hv2-canonname.c | 63 +++++++++++++++++++ - nss/tst-nss-gai-hv2-canonname.h | 1 + - .../postclean.req | 0 - .../tst-nss-gai-hv2-canonname.script | 2 + - sysdeps/posix/getaddrinfo.c | 25 +++++--- - 7 files changed, 152 insertions(+), 10 deletions(-) - create mode 100644 nss/nss_test_gai_hv2_canonname.c - create mode 100644 nss/tst-nss-gai-hv2-canonname.c - create mode 100644 nss/tst-nss-gai-hv2-canonname.h - create mode 100644 nss/tst-nss-gai-hv2-canonname.root/postclean.req - create mode 100644 nss/tst-nss-gai-hv2-canonname.root/tst-nss-gai-hv2-canonname.script - -diff --git a/nss/Makefile b/nss/Makefile -index a978e3927a..f0af87e6f1 100644 ---- a/nss/Makefile -+++ b/nss/Makefile -@@ -81,6 +81,7 @@ tests-container := \ - tst-nss-test3 \ - tst-reload1 \ - tst-reload2 \ -+ tst-nss-gai-hv2-canonname \ - # tests-container - - # Tests which need libdl -@@ -144,7 +145,8 @@ libnss_compat-inhibit-o = $(filter-out .os,$(object-suffixes)) - ifeq ($(build-static-nss),yes) - tests-static += tst-nss-static - endif --extra-test-objs += nss_test1.os nss_test2.os nss_test_errno.os -+extra-test-objs += nss_test1.os nss_test2.os nss_test_errno.os \ -+ nss_test_gai_hv2_canonname.os - - include ../Rules - -@@ -179,12 +181,16 @@ rtld-tests-LDFLAGS += -Wl,--dynamic-list=nss_test.ver - libof-nss_test1 = extramodules - libof-nss_test2 = extramodules - libof-nss_test_errno = extramodules -+libof-nss_test_gai_hv2_canonname = extramodules - $(objpfx)/libnss_test1.so: $(objpfx)nss_test1.os $(link-libc-deps) - $(build-module) - $(objpfx)/libnss_test2.so: $(objpfx)nss_test2.os $(link-libc-deps) - $(build-module) - $(objpfx)/libnss_test_errno.so: $(objpfx)nss_test_errno.os $(link-libc-deps) - $(build-module) -+$(objpfx)/libnss_test_gai_hv2_canonname.so: \ -+ $(objpfx)nss_test_gai_hv2_canonname.os $(link-libc-deps) -+ $(build-module) - $(objpfx)nss_test2.os : nss_test1.c - # Use the nss_files suffix for these objects as well. - $(objpfx)/libnss_test1.so$(libnss_files.so-version): $(objpfx)/libnss_test1.so -@@ -194,10 +200,14 @@ $(objpfx)/libnss_test2.so$(libnss_files.so-version): $(objpfx)/libnss_test2.so - $(objpfx)/libnss_test_errno.so$(libnss_files.so-version): \ - $(objpfx)/libnss_test_errno.so - $(make-link) -+$(objpfx)/libnss_test_gai_hv2_canonname.so$(libnss_files.so-version): \ -+ $(objpfx)/libnss_test_gai_hv2_canonname.so -+ $(make-link) - $(patsubst %,$(objpfx)%.out,$(tests) $(tests-container)) : \ - $(objpfx)/libnss_test1.so$(libnss_files.so-version) \ - $(objpfx)/libnss_test2.so$(libnss_files.so-version) \ -- $(objpfx)/libnss_test_errno.so$(libnss_files.so-version) -+ $(objpfx)/libnss_test_errno.so$(libnss_files.so-version) \ -+ $(objpfx)/libnss_test_gai_hv2_canonname.so$(libnss_files.so-version) - - ifeq (yes,$(have-thread-library)) - $(objpfx)tst-cancel-getpwuid_r: $(shared-thread-library) -@@ -214,3 +224,4 @@ LDFLAGS-tst-nss-test3 = -Wl,--disable-new-dtags - LDFLAGS-tst-nss-test4 = -Wl,--disable-new-dtags - LDFLAGS-tst-nss-test5 = -Wl,--disable-new-dtags - LDFLAGS-tst-nss-test_errno = -Wl,--disable-new-dtags -+LDFLAGS-tst-nss-test_gai_hv2_canonname = -Wl,--disable-new-dtags -diff --git a/nss/nss_test_gai_hv2_canonname.c b/nss/nss_test_gai_hv2_canonname.c -new file mode 100644 -index 0000000000..4439c83c9f ---- /dev/null -+++ b/nss/nss_test_gai_hv2_canonname.c -@@ -0,0 +1,56 @@ -+/* NSS service provider that only provides gethostbyname2_r. -+ Copyright The GNU Toolchain Authors. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+#include -+#include -+#include "nss/tst-nss-gai-hv2-canonname.h" -+ -+/* Catch misnamed and functions. */ -+#pragma GCC diagnostic error "-Wmissing-prototypes" -+NSS_DECLARE_MODULE_FUNCTIONS (test_gai_hv2_canonname) -+ -+extern enum nss_status _nss_files_gethostbyname2_r (const char *, int, -+ struct hostent *, char *, -+ size_t, int *, int *); -+ -+enum nss_status -+_nss_test_gai_hv2_canonname_gethostbyname2_r (const char *name, int af, -+ struct hostent *result, -+ char *buffer, size_t buflen, -+ int *errnop, int *herrnop) -+{ -+ return _nss_files_gethostbyname2_r (name, af, result, buffer, buflen, errnop, -+ herrnop); -+} -+ -+enum nss_status -+_nss_test_gai_hv2_canonname_getcanonname_r (const char *name, char *buffer, -+ size_t buflen, char **result, -+ int *errnop, int *h_errnop) -+{ -+ /* We expect QUERYNAME, which is a small enough string that it shouldn't fail -+ the test. */ -+ if (memcmp (QUERYNAME, name, sizeof (QUERYNAME)) -+ || buflen < sizeof (QUERYNAME)) -+ abort (); -+ -+ strncpy (buffer, name, buflen); -+ *result = buffer; -+ return NSS_STATUS_SUCCESS; -+} -diff --git a/nss/tst-nss-gai-hv2-canonname.c b/nss/tst-nss-gai-hv2-canonname.c -new file mode 100644 -index 0000000000..d5f10c07d6 ---- /dev/null -+++ b/nss/tst-nss-gai-hv2-canonname.c -@@ -0,0 +1,63 @@ -+/* Test NSS query path for plugins that only implement gethostbyname2 -+ (#30843). -+ Copyright The GNU Toolchain Authors. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "nss/tst-nss-gai-hv2-canonname.h" -+ -+#define PREPARE do_prepare -+ -+static void do_prepare (int a, char **av) -+{ -+ FILE *hosts = xfopen ("/etc/hosts", "w"); -+ for (unsigned i = 2; i < 255; i++) -+ { -+ fprintf (hosts, "ff01::ff02:ff03:%u:2\ttest.example.com\n", i); -+ fprintf (hosts, "192.168.0.%u\ttest.example.com\n", i); -+ } -+ xfclose (hosts); -+} -+ -+static int -+do_test (void) -+{ -+ __nss_configure_lookup ("hosts", "test_gai_hv2_canonname"); -+ -+ struct addrinfo hints = {}; -+ struct addrinfo *result = NULL; -+ -+ hints.ai_family = AF_INET6; -+ hints.ai_flags = AI_ALL | AI_V4MAPPED | AI_CANONNAME; -+ -+ int ret = getaddrinfo (QUERYNAME, NULL, &hints, &result); -+ -+ if (ret != 0) -+ FAIL_EXIT1 ("getaddrinfo failed: %s\n", gai_strerror (ret)); -+ -+ TEST_COMPARE_STRING (result->ai_canonname, QUERYNAME); -+ -+ freeaddrinfo(result); -+ return 0; -+} -+ -+#include -diff --git a/nss/tst-nss-gai-hv2-canonname.h b/nss/tst-nss-gai-hv2-canonname.h -new file mode 100644 -index 0000000000..14f2a9cb08 ---- /dev/null -+++ b/nss/tst-nss-gai-hv2-canonname.h -@@ -0,0 +1 @@ -+#define QUERYNAME "test.example.com" -diff --git a/nss/tst-nss-gai-hv2-canonname.root/postclean.req b/nss/tst-nss-gai-hv2-canonname.root/postclean.req -new file mode 100644 -index 0000000000..e69de29bb2 -diff --git a/nss/tst-nss-gai-hv2-canonname.root/tst-nss-gai-hv2-canonname.script b/nss/tst-nss-gai-hv2-canonname.root/tst-nss-gai-hv2-canonname.script -new file mode 100644 -index 0000000000..31848b4a28 ---- /dev/null -+++ b/nss/tst-nss-gai-hv2-canonname.root/tst-nss-gai-hv2-canonname.script -@@ -0,0 +1,2 @@ -+cp $B/nss/libnss_test_gai_hv2_canonname.so $L/libnss_test_gai_hv2_canonname.so.2 -+su -diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c -index 5cda9bb072..7a43a3bf4c 100644 ---- a/sysdeps/posix/getaddrinfo.c -+++ b/sysdeps/posix/getaddrinfo.c -@@ -120,6 +120,7 @@ struct gaih_result - { - struct gaih_addrtuple *at; - char *canon; -+ char *h_name; - bool free_at; - bool got_ipv6; - }; -@@ -165,6 +166,7 @@ gaih_result_reset (struct gaih_result *res) - if (res->free_at) - free (res->at); - free (res->canon); -+ free (res->h_name); - memset (res, 0, sizeof (*res)); - } - -@@ -203,9 +205,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, - return 0; - } - --/* Convert struct hostent to a list of struct gaih_addrtuple objects. h_name -- is not copied, and the struct hostent object must not be deallocated -- prematurely. The new addresses are appended to the tuple array in RES. */ -+/* Convert struct hostent to a list of struct gaih_addrtuple objects. The new -+ addresses are appended to the tuple array in RES. */ - static bool - convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family, - struct hostent *h, struct gaih_result *res) -@@ -238,6 +239,15 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family, - res->at = array; - res->free_at = true; - -+ /* Duplicate h_name because it may get reclaimed when the underlying storage -+ is freed. */ -+ if (res->h_name == NULL) -+ { -+ res->h_name = __strdup (h->h_name); -+ if (res->h_name == NULL) -+ return false; -+ } -+ - /* Update the next pointers on reallocation. */ - for (size_t i = 0; i < old; i++) - array[i].next = array + i + 1; -@@ -262,7 +272,6 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family, - } - array[i].next = array + i + 1; - } -- array[0].name = h->h_name; - array[count - 1].next = NULL; - - return true; -@@ -324,15 +333,15 @@ gethosts (nss_gethostbyname3_r fct, int family, const char *name, - memory allocation failure. The returned string is allocated on the - heap; the caller has to free it. */ - static char * --getcanonname (nss_action_list nip, struct gaih_addrtuple *at, const char *name) -+getcanonname (nss_action_list nip, const char *hname, const char *name) - { - nss_getcanonname_r *cfct = __nss_lookup_function (nip, "getcanonname_r"); - char *s = (char *) name; - if (cfct != NULL) - { - char buf[256]; -- if (DL_CALL_FCT (cfct, (at->name ?: name, buf, sizeof (buf), -- &s, &errno, &h_errno)) != NSS_STATUS_SUCCESS) -+ if (DL_CALL_FCT (cfct, (hname ?: name, buf, sizeof (buf), &s, &errno, -+ &h_errno)) != NSS_STATUS_SUCCESS) - /* If the canonical name cannot be determined, use the passed - string. */ - s = (char *) name; -@@ -771,7 +780,7 @@ get_nss_addresses (const char *name, const struct addrinfo *req, - if ((req->ai_flags & AI_CANONNAME) != 0 - && res->canon == NULL) - { -- char *canonbuf = getcanonname (nip, res->at, name); -+ char *canonbuf = getcanonname (nip, res->h_name, name); - if (canonbuf == NULL) - { - __resolv_context_put (res_ctx); --- -2.39.3 - diff --git a/0085-CVE-2023-5156.patch b/0085-CVE-2023-5156.patch deleted file mode 100644 index 59a3c83..0000000 --- a/0085-CVE-2023-5156.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 856bac55f98dc840e7c27cfa82262b933385de90 Mon Sep 17 00:00:00 2001 -From: Romain Geissler -Date: Mon, 25 Sep 2023 01:21:51 +0100 -Subject: [PATCH] Fix leak in getaddrinfo introduced by the fix for - CVE-2023-4806 [BZ #30843] - -This patch fixes a very recently added leak in getaddrinfo. - -This was assigned CVE-2023-5156. - -Resolves: BZ #30884 -Related: BZ #30842 - -Reviewed-by: Siddhesh Poyarekar -(cherry picked from commit ec6b95c3303c700eb89eebeda2d7264cc184a796) ---- - nss/Makefile | 20 ++++++++++++++++++++ - nss/tst-nss-gai-hv2-canonname.c | 3 +++ - sysdeps/posix/getaddrinfo.c | 4 +--- - 3 files changed, 24 insertions(+), 3 deletions(-) - -diff --git a/nss/Makefile b/nss/Makefile -index f0af87e6f1..7a52c68791 100644 ---- a/nss/Makefile -+++ b/nss/Makefile -@@ -148,6 +148,15 @@ endif - extra-test-objs += nss_test1.os nss_test2.os nss_test_errno.os \ - nss_test_gai_hv2_canonname.os - -+ifeq ($(run-built-tests),yes) -+ifneq (no,$(PERL)) -+tests-special += $(objpfx)mtrace-tst-nss-gai-hv2-canonname.out -+endif -+endif -+ -+generated += mtrace-tst-nss-gai-hv2-canonname.out \ -+ tst-nss-gai-hv2-canonname.mtrace -+ - include ../Rules - - ifeq (yes,$(have-selinux)) -@@ -216,6 +225,17 @@ endif - $(objpfx)tst-nss-files-alias-leak.out: $(objpfx)/libnss_files.so - $(objpfx)tst-nss-files-alias-truncated.out: $(objpfx)/libnss_files.so - -+tst-nss-gai-hv2-canonname-ENV = \ -+ MALLOC_TRACE=$(objpfx)tst-nss-gai-hv2-canonname.mtrace \ -+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so -+$(objpfx)mtrace-tst-nss-gai-hv2-canonname.out: \ -+ $(objpfx)tst-nss-gai-hv2-canonname.out -+ { test -r $(objpfx)tst-nss-gai-hv2-canonname.mtrace \ -+ || ( echo "tst-nss-gai-hv2-canonname.mtrace does not exist"; exit 77; ) \ -+ && $(common-objpfx)malloc/mtrace \ -+ $(objpfx)tst-nss-gai-hv2-canonname.mtrace; } > $@; \ -+ $(evaluate-test) -+ - # Disable DT_RUNPATH on NSS tests so that the glibc internal NSS - # functions can load testing NSS modules via DT_RPATH. - LDFLAGS-tst-nss-test1 = -Wl,--disable-new-dtags -diff --git a/nss/tst-nss-gai-hv2-canonname.c b/nss/tst-nss-gai-hv2-canonname.c -index d5f10c07d6..7db53cf09d 100644 ---- a/nss/tst-nss-gai-hv2-canonname.c -+++ b/nss/tst-nss-gai-hv2-canonname.c -@@ -21,6 +21,7 @@ - #include - #include - #include -+#include - #include - #include - #include "nss/tst-nss-gai-hv2-canonname.h" -@@ -41,6 +42,8 @@ static void do_prepare (int a, char **av) - static int - do_test (void) - { -+ mtrace (); -+ - __nss_configure_lookup ("hosts", "test_gai_hv2_canonname"); - - struct addrinfo hints = {}; -diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c -index 7a43a3bf4c..f975dcd2bc 100644 ---- a/sysdeps/posix/getaddrinfo.c -+++ b/sysdeps/posix/getaddrinfo.c -@@ -1196,9 +1196,7 @@ free_and_return: - if (malloc_name) - free ((char *) name); - free (addrmem); -- if (res.free_at) -- free (res.at); -- free (res.canon); -+ gaih_result_reset (&res); - - return result; - } --- -2.39.3 - diff --git a/0087-CVE-2023-6246.patch b/0087-CVE-2023-6246.patch deleted file mode 100644 index 9ddca42..0000000 --- a/0087-CVE-2023-6246.patch +++ /dev/null @@ -1,181 +0,0 @@ -From d1a83b6767f68b3cb5b4b4ea2617254acd040c82 Mon Sep 17 00:00:00 2001 -From: Arjun Shankar -Date: Mon, 15 Jan 2024 17:44:43 +0100 -Subject: [PATCH] syslog: Fix heap buffer overflow in __vsyslog_internal - (CVE-2023-6246) - -__vsyslog_internal did not handle a case where printing a SYSLOG_HEADER -containing a long program name failed to update the required buffer -size, leading to the allocation and overflow of a too-small buffer on -the heap. This commit fixes that. It also adds a new regression test -that uses glibc.malloc.check. - -Reviewed-by: Adhemerval Zanella -Reviewed-by: Carlos O'Donell -Tested-by: Carlos O'Donell -(cherry picked from commit 6bd0e4efcc78f3c0115e5ea9739a1642807450da) ---- - misc/Makefile | 8 ++- - misc/syslog.c | 50 +++++++++++++------ - misc/tst-syslog-long-progname.c | 39 +++++++++++++++ - .../postclean.req | 0 - 4 files changed, 82 insertions(+), 15 deletions(-) - create mode 100644 misc/tst-syslog-long-progname.c - create mode 100644 misc/tst-syslog-long-progname.root/postclean.req - -diff --git a/misc/Makefile b/misc/Makefile -index ba8232a0e9..66e9ded8f9 100644 ---- a/misc/Makefile -+++ b/misc/Makefile -@@ -115,7 +115,10 @@ tests-special += $(objpfx)tst-error1-mem.out \ - $(objpfx)tst-allocate_once-mem.out - endif - --tests-container := tst-syslog -+tests-container := \ -+ tst-syslog \ -+ tst-syslog-long-progname \ -+ # tests-container - - CFLAGS-select.c += -fexceptions -fasynchronous-unwind-tables - CFLAGS-tsearch.c += $(uses-callbacks) -@@ -175,6 +178,9 @@ $(objpfx)tst-allocate_once-mem.out: $(objpfx)tst-allocate_once.out - $(common-objpfx)malloc/mtrace $(objpfx)tst-allocate_once.mtrace > $@; \ - $(evaluate-test) - -+tst-syslog-long-progname-ENV = GLIBC_TUNABLES=glibc.malloc.check=3 \ -+ LD_PRELOAD=libc_malloc_debug.so.0 -+ - $(objpfx)tst-select: $(librt) - $(objpfx)tst-select-time64: $(librt) - $(objpfx)tst-pselect: $(librt) -diff --git a/misc/syslog.c b/misc/syslog.c -index f67d4b58a4..fe1daf988b 100644 ---- a/misc/syslog.c -+++ b/misc/syslog.c -@@ -122,8 +122,9 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap, - { - /* Try to use a static buffer as an optimization. */ - char bufs[1024]; -- char *buf = NULL; -- size_t bufsize = 0; -+ char *buf = bufs; -+ size_t bufsize; -+ - int msgoff; - int saved_errno = errno; - -@@ -175,29 +176,50 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap, - #define SYSLOG_HEADER_WITHOUT_TS(__pri, __msgoff) \ - "<%d>: %n", __pri, __msgoff - -- int l; -+ int l, vl; - if (has_ts) - l = __snprintf (bufs, sizeof bufs, - SYSLOG_HEADER (pri, timestamp, &msgoff, pid)); - else - l = __snprintf (bufs, sizeof bufs, - SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff)); -+ -+ char *pos; -+ size_t len; -+ - if (0 <= l && l < sizeof bufs) - { -- va_list apc; -- va_copy (apc, ap); -+ /* At this point, there is still a chance that we can print the -+ remaining part of the log into bufs and use that. */ -+ pos = bufs + l; -+ len = sizeof (bufs) - l; -+ } -+ else -+ { -+ buf = NULL; -+ /* We already know that bufs is too small to use for this log message. -+ The next vsnprintf into bufs is used only to calculate the total -+ required buffer length. We will discard bufs contents and allocate -+ an appropriately sized buffer later instead. */ -+ pos = bufs; -+ len = sizeof (bufs); -+ } - -- /* Restore errno for %m format. */ -- __set_errno (saved_errno); -+ { -+ va_list apc; -+ va_copy (apc, ap); - -- int vl = __vsnprintf_internal (bufs + l, sizeof bufs - l, fmt, apc, -- mode_flags); -- if (0 <= vl && vl < sizeof bufs - l) -- buf = bufs; -- bufsize = l + vl; -+ /* Restore errno for %m format. */ -+ __set_errno (saved_errno); - -- va_end (apc); -- } -+ vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags); -+ -+ if (!(0 <= vl && vl < len)) -+ buf = NULL; -+ -+ bufsize = l + vl; -+ va_end (apc); -+ } - - if (buf == NULL) - { -diff --git a/misc/tst-syslog-long-progname.c b/misc/tst-syslog-long-progname.c -new file mode 100644 -index 0000000000..88f37a8a00 ---- /dev/null -+++ b/misc/tst-syslog-long-progname.c -@@ -0,0 +1,39 @@ -+/* Test heap buffer overflow in syslog with long __progname (CVE-2023-6246) -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+ -+extern char * __progname; -+ -+static int -+do_test (void) -+{ -+ char long_progname[2048]; -+ -+ memset (long_progname, 'X', sizeof (long_progname) - 1); -+ long_progname[sizeof (long_progname) - 1] = '\0'; -+ -+ __progname = long_progname; -+ -+ syslog (LOG_INFO, "Hello, World!"); -+ -+ return 0; -+} -+ -+#include -diff --git a/misc/tst-syslog-long-progname.root/postclean.req b/misc/tst-syslog-long-progname.root/postclean.req -new file mode 100644 -index 0000000000..e69de29bb2 --- -2.39.3 - diff --git a/0088-CVE-2023-6779.patch b/0088-CVE-2023-6779.patch deleted file mode 100644 index 8a658bb..0000000 --- a/0088-CVE-2023-6779.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 2bc9d7c002bdac38b5c2a3f11b78e309d7765b83 Mon Sep 17 00:00:00 2001 -From: Arjun Shankar -Date: Mon, 15 Jan 2024 17:44:44 +0100 -Subject: [PATCH] syslog: Fix heap buffer overflow in __vsyslog_internal - (CVE-2023-6779) - -__vsyslog_internal used the return value of snprintf/vsnprintf to -calculate buffer sizes for memory allocation. If these functions (for -any reason) failed and returned -1, the resulting buffer would be too -small to hold output. This commit fixes that. - -All snprintf/vsnprintf calls are checked for negative return values and -the function silently returns upon encountering them. - -Reviewed-by: Carlos O'Donell -(cherry picked from commit 7e5a0c286da33159d47d0122007aac016f3e02cd) ---- - misc/syslog.c | 39 ++++++++++++++++++++++++++++----------- - 1 file changed, 28 insertions(+), 11 deletions(-) - -diff --git a/misc/syslog.c b/misc/syslog.c -index fe1daf988b..3108ae9134 100644 ---- a/misc/syslog.c -+++ b/misc/syslog.c -@@ -183,11 +183,13 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap, - else - l = __snprintf (bufs, sizeof bufs, - SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff)); -+ if (l < 0) -+ goto out; - - char *pos; - size_t len; - -- if (0 <= l && l < sizeof bufs) -+ if (l < sizeof bufs) - { - /* At this point, there is still a chance that we can print the - remaining part of the log into bufs and use that. */ -@@ -213,12 +215,15 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap, - __set_errno (saved_errno); - - vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags); -+ va_end (apc); -+ -+ if (vl < 0) -+ goto out; - -- if (!(0 <= vl && vl < len)) -+ if (vl >= len) - buf = NULL; - - bufsize = l + vl; -- va_end (apc); - } - - if (buf == NULL) -@@ -229,25 +234,37 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap, - /* Tell the cancellation handler to free this buffer. */ - clarg.buf = buf; - -+ int cl; - if (has_ts) -- __snprintf (buf, l + 1, -- SYSLOG_HEADER (pri, timestamp, &msgoff, pid)); -+ cl = __snprintf (buf, l + 1, -+ SYSLOG_HEADER (pri, timestamp, &msgoff, pid)); - else -- __snprintf (buf, l + 1, -- SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff)); -+ cl = __snprintf (buf, l + 1, -+ SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff)); -+ if (cl != l) -+ goto out; - - va_list apc; - va_copy (apc, ap); -- __vsnprintf_internal (buf + l, bufsize - l + 1, fmt, apc, -- mode_flags); -+ cl = __vsnprintf_internal (buf + l, bufsize - l + 1, fmt, apc, -+ mode_flags); - va_end (apc); -+ -+ if (cl != vl) -+ goto out; - } - else - { -+ int bl; - /* Nothing much to do but emit an error message. */ -- bufsize = __snprintf (bufs, sizeof bufs, -- "out of memory[%d]", __getpid ()); -+ bl = __snprintf (bufs, sizeof bufs, -+ "out of memory[%d]", __getpid ()); -+ if (bl < 0 || bl >= sizeof bufs) -+ goto out; -+ -+ bufsize = bl; - buf = bufs; -+ msgoff = 0; - } - } - --- -2.39.3 - diff --git a/0089-CVE-2023-6780.patch b/0089-CVE-2023-6780.patch deleted file mode 100644 index d6190b7..0000000 --- a/0089-CVE-2023-6780.patch +++ /dev/null @@ -1,41 +0,0 @@ -From b9b7d6a27aa0632f334352fa400771115b3c69b7 Mon Sep 17 00:00:00 2001 -From: Arjun Shankar -Date: Mon, 15 Jan 2024 17:44:45 +0100 -Subject: [PATCH] syslog: Fix integer overflow in __vsyslog_internal - (CVE-2023-6780) - -__vsyslog_internal calculated a buffer size by adding two integers, but -did not first check if the addition would overflow. This commit fixes -that. - -Reviewed-by: Carlos O'Donell -Tested-by: Carlos O'Donell -(cherry picked from commit ddf542da94caf97ff43cc2875c88749880b7259b) ---- - misc/syslog.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/misc/syslog.c b/misc/syslog.c -index 3108ae9134..9336036666 100644 ---- a/misc/syslog.c -+++ b/misc/syslog.c -@@ -41,6 +41,7 @@ static char sccsid[] = "@(#)syslog.c 8.4 (Berkeley) 3/18/94"; - #include - #include - #include -+#include - - static int LogType = SOCK_DGRAM; /* type of socket connection */ - static int LogFile = -1; /* fd for log */ -@@ -217,7 +218,7 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap, - vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags); - va_end (apc); - -- if (vl < 0) -+ if (vl < 0 || vl >= INT_MAX - l) - goto out; - - if (vl >= len) --- -2.39.3 - diff --git a/0090-CVE-2024-2961.patch b/0090-CVE-2024-2961.patch deleted file mode 100644 index aa33e4c..0000000 --- a/0090-CVE-2024-2961.patch +++ /dev/null @@ -1,213 +0,0 @@ -From f9dc609e06b1136bb0408be9605ce7973a767ada Mon Sep 17 00:00:00 2001 -From: Charles Fol -Date: Thu, 28 Mar 2024 12:25:38 -0300 -Subject: [PATCH] iconv: ISO-2022-CN-EXT: fix out-of-bound writes when writing - escape sequence (CVE-2024-2961) - -ISO-2022-CN-EXT uses escape sequences to indicate character set changes -(as specified by RFC 1922). While the SOdesignation has the expected -bounds checks, neither SS2designation nor SS3designation have its; -allowing a write overflow of 1, 2, or 3 bytes with fixed values: -'$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'. - -Checked on aarch64-linux-gnu. - -Co-authored-by: Adhemerval Zanella -Reviewed-by: Carlos O'Donell -Tested-by: Carlos O'Donell ---- - iconvdata/Makefile | 5 +- - iconvdata/iso-2022-cn-ext.c | 12 +++ - iconvdata/tst-iconv-iso-2022-cn-ext.c | 128 ++++++++++++++++++++++++++ - 3 files changed, 144 insertions(+), 1 deletion(-) - create mode 100644 iconvdata/tst-iconv-iso-2022-cn-ext.c - -diff --git a/iconvdata/Makefile b/iconvdata/Makefile -index ea019ce5c0..7196a8744b 100644 ---- a/iconvdata/Makefile -+++ b/iconvdata/Makefile -@@ -75,7 +75,8 @@ ifeq (yes,$(build-shared)) - tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ - tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \ - bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \ -- bug-iconv13 bug-iconv14 bug-iconv15 -+ bug-iconv13 bug-iconv14 bug-iconv15 \ -+ tst-iconv-iso-2022-cn-ext - ifeq ($(have-thread-library),yes) - tests += bug-iconv3 - endif -@@ -330,6 +331,8 @@ $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \ - $(addprefix $(objpfx),$(modules.so)) - $(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \ - $(addprefix $(objpfx),$(modules.so)) -+$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \ -+ $(addprefix $(objpfx),$(modules.so)) - - $(objpfx)iconv-test.out: run-iconv-test.sh \ - $(addprefix $(objpfx), $(gconv-modules)) \ -diff --git a/iconvdata/iso-2022-cn-ext.c b/iconvdata/iso-2022-cn-ext.c -index b34c8a36f4..cce29b1969 100644 ---- a/iconvdata/iso-2022-cn-ext.c -+++ b/iconvdata/iso-2022-cn-ext.c -@@ -574,6 +574,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized"); - { \ - const char *escseq; \ - \ -+ if (outptr + 4 > outend) \ -+ { \ -+ result = __GCONV_FULL_OUTPUT; \ -+ break; \ -+ } \ -+ \ - assert (used == CNS11643_2_set); /* XXX */ \ - escseq = "*H"; \ - *outptr++ = ESC; \ -@@ -587,6 +593,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized"); - { \ - const char *escseq; \ - \ -+ if (outptr + 4 > outend) \ -+ { \ -+ result = __GCONV_FULL_OUTPUT; \ -+ break; \ -+ } \ -+ \ - assert ((used >> 5) >= 3 && (used >> 5) <= 7); \ - escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2; \ - *outptr++ = ESC; \ -diff --git a/iconvdata/tst-iconv-iso-2022-cn-ext.c b/iconvdata/tst-iconv-iso-2022-cn-ext.c -new file mode 100644 -index 0000000000..96a8765fd5 ---- /dev/null -+++ b/iconvdata/tst-iconv-iso-2022-cn-ext.c -@@ -0,0 +1,128 @@ -+/* Verify ISO-2022-CN-EXT does not write out of the bounds. -+ Copyright (C) 2024 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 -+ . */ -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/* The test sets up a two memory page buffer with the second page marked -+ PROT_NONE to trigger a fault if the conversion writes beyond the exact -+ expected amount. Then we carry out various conversions and precisely -+ place the start of the output buffer in order to trigger a SIGSEGV if the -+ process writes anywhere between 1 and page sized bytes more (only one -+ PROT_NONE page is setup as a canary) than expected. These tests exercise -+ all three of the cases in ISO-2022-CN-EXT where the converter must switch -+ character sets and may run out of buffer space while doing the -+ operation. */ -+ -+static int -+do_test (void) -+{ -+ iconv_t cd = iconv_open ("ISO-2022-CN-EXT", "UTF-8"); -+ TEST_VERIFY_EXIT (cd != (iconv_t) -1); -+ -+ char *ntf; -+ size_t ntfsize; -+ char *outbufbase; -+ { -+ int pgz = getpagesize (); -+ TEST_VERIFY_EXIT (pgz > 0); -+ ntfsize = 2 * pgz; -+ -+ ntf = xmmap (NULL, ntfsize, PROT_READ | PROT_WRITE, MAP_PRIVATE -+ | MAP_ANONYMOUS, -1); -+ xmprotect (ntf + pgz, pgz, PROT_NONE); -+ -+ outbufbase = ntf + pgz; -+ } -+ -+ /* Check if SOdesignation escape sequence does not trigger an OOB write. */ -+ { -+ char inbuf[] = "\xe4\xba\xa4\xe6\x8d\xa2"; -+ -+ for (int i = 0; i < 9; i++) -+ { -+ char *inp = inbuf; -+ size_t inleft = sizeof (inbuf) - 1; -+ -+ char *outp = outbufbase - i; -+ size_t outleft = i; -+ -+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft) -+ == (size_t) -1); -+ TEST_COMPARE (errno, E2BIG); -+ -+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0); -+ } -+ } -+ -+ /* Same as before for SS2designation. */ -+ { -+ char inbuf[] = "ã´½ \xe3\xb4\xbd"; -+ -+ for (int i = 0; i < 14; i++) -+ { -+ char *inp = inbuf; -+ size_t inleft = sizeof (inbuf) - 1; -+ -+ char *outp = outbufbase - i; -+ size_t outleft = i; -+ -+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft) -+ == (size_t) -1); -+ TEST_COMPARE (errno, E2BIG); -+ -+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0); -+ } -+ } -+ -+ /* Same as before for SS3designation. */ -+ { -+ char inbuf[] = "劄 \xe5\x8a\x84"; -+ -+ for (int i = 0; i < 14; i++) -+ { -+ char *inp = inbuf; -+ size_t inleft = sizeof (inbuf) - 1; -+ -+ char *outp = outbufbase - i; -+ size_t outleft = i; -+ -+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft) -+ == (size_t) -1); -+ TEST_COMPARE (errno, E2BIG); -+ -+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0); -+ } -+ } -+ -+ TEST_VERIFY_EXIT (iconv_close (cd) != -1); -+ -+ xmunmap (ntf, ntfsize); -+ -+ return 0; -+} -+ -+#include --- -2.39.3 diff --git a/1086-CVE-2023-4911.patch b/1086-CVE-2023-4911.patch deleted file mode 100644 index d836104..0000000 --- a/1086-CVE-2023-4911.patch +++ /dev/null @@ -1,139 +0,0 @@ -From 27e06a423cf06845a0515ab767a109b31b34724a Mon Sep 17 00:00:00 2001 -From: Chunmei Xu -Date: Tue, 5 Mar 2024 14:12:15 +0800 -Subject: [PATCH 1/1] fix CVE-2023-4911 - ---- - elf/dl-tunables.c | 16 ++++++++------- - elf/tst-env-setuid-tunables.c | 37 +++++++++++++++++++++++++++-------- - 2 files changed, 38 insertions(+), 15 deletions(-) - -diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c -index 62b7332d..0edfade8 100644 ---- a/elf/dl-tunables.c -+++ b/elf/dl-tunables.c -@@ -180,11 +180,7 @@ parse_tunables (char *tunestr, char *valstring) - /* If we reach the end of the string before getting a valid name-value - pair, bail out. */ - if (p[len] == '\0') -- { -- if (__libc_enable_secure) -- tunestr[off] = '\0'; -- return; -- } -+ break; - - /* We did not find a valid name-value pair before encountering the - colon. */ -@@ -244,9 +240,15 @@ parse_tunables (char *tunestr, char *valstring) - } - } - -- if (p[len] != '\0') -- p += len + 1; -+ /* We reached the end while processing the tunable string. */ -+ if (p[len] == '\0') -+ break; -+ p += len + 1; - } -+ -+ /* Terminate tunestr before we leave. */ -+ if (__libc_enable_secure) -+ tunestr[off] = '\0'; - } - - /* Enable the glibc.malloc.check tunable in SETUID/SETGID programs only when -diff --git a/elf/tst-env-setuid-tunables.c b/elf/tst-env-setuid-tunables.c -index 7dfb0e07..2364d162 100644 ---- a/elf/tst-env-setuid-tunables.c -+++ b/elf/tst-env-setuid-tunables.c -@@ -50,6 +50,8 @@ const char *teststrings[] = - "glibc.malloc.perturb=0x800:not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096", - "glibc.not_valid.check=2:glibc.malloc.mmap_threshold=4096", - "not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096", -+ "glibc.malloc.mmap_threshold=glibc.malloc.mmap_threshold=4096", -+ "glibc.malloc.check=2", - "glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096:glibc.malloc.check=2", - "glibc.malloc.check=4:glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096", - ":glibc.malloc.garbage=2:glibc.malloc.check=1", -@@ -68,6 +70,8 @@ const char *resultstrings[] = - "glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096", - "glibc.malloc.mmap_threshold=4096", - "glibc.malloc.mmap_threshold=4096", -+ "glibc.malloc.mmap_threshold=glibc.malloc.mmap_threshold=4096", -+ "", - "", - "", - "", -@@ -81,11 +85,17 @@ test_child (int off) - { - const char *val = getenv ("GLIBC_TUNABLES"); - -+ printf (" [%d] GLIBC_TUNABLES is %s\n", off, val); -+ fflush (stdout); - if (val != NULL && strcmp (val, resultstrings[off]) == 0) - return 0; - - if (val != NULL) -- printf ("[%d] Unexpected GLIBC_TUNABLES VALUE %s\n", off, val); -+ printf (" [%d] Unexpected GLIBC_TUNABLES VALUE %s, expected %s\n", -+ off, val, resultstrings[off]); -+ else -+ printf (" [%d] GLIBC_TUNABLES environment variable absent\n", off); -+ fflush (stdout); - - return 1; - } -@@ -106,31 +116,42 @@ do_test (int argc, char **argv) - if (ret != 0) - exit (1); - -- exit (EXIT_SUCCESS); -+ /* Special return code to make sure that the child executed all the way -+ through. */ -+ exit (42); - } - else - { -- int ret = 0; - - /* Spawn tests. */ - for (int i = 0; i < array_length (teststrings); i++) - { - char buf[INT_BUFSIZE_BOUND (int)]; - -- printf ("Spawned test for %s (%d)\n", teststrings[i], i); -+ printf ("[%d] Spawned test for %s\n", i, teststrings[i]); - snprintf (buf, sizeof (buf), "%d\n", i); -+ fflush (stdout); - if (setenv ("GLIBC_TUNABLES", teststrings[i], 1) != 0) -- exit (1); -- -+ { -+ printf (" [%d] Failed to set GLIBC_TUNABLES: %m", i); -+ support_record_failure (); -+ continue; -+ } -+ - int status = support_capture_subprogram_self_sgid (buf); - - /* Bail out early if unsupported. */ - if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) - return EXIT_UNSUPPORTED; - -- ret |= status; -+ if (WEXITSTATUS (status) != 42) -+ { -+ printf (" [%d] child failed with status %d\n", i, -+ WEXITSTATUS (status)); -+ support_record_failure (); -+ } - } -- return ret; -+ return 0; - } - } - --- -2.41.0 - diff --git a/ChangeLog.old b/ChangeLog.old new file mode 100755 index 0000000..28b5ace --- /dev/null +++ b/ChangeLog.old @@ -0,0 +1,6058 @@ +* Wed Aug 02 2017 Fedora Release Engineering - 2.25.90-30.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Sat Jul 29 2017 Florian Weimer - 2.25.90-30 +- Auto-sync with upstream master, + commit 5920a4a624b1f4db310d1c44997b640e2a4653e5: +- mutex: Fix robust mutex lock acquire (swbz#21778) + +* Fri Jul 28 2017 Florian Weimer - 2.25.90-29 +- Auto-sync with upstream master, + commit d95fcb2df478efbf4f8537ba898374043ac4561f: +- rwlock: Fix explicit hand-over (swbz#21298) +- tunables: Use direct syscall for access (swbz#21744) +- Avoid accessing corrupted stack from __stack_chk_fail (swbz#21752) +- Remove extra semicolons in struct pthread_mutex (swbz#21804) +- grp: Fix cast-after-dereference (another big-endian group merge issue) +- S390: fix sys/ptrace.h to make it includible again after asm/ptrace.h +- Don't add stack_chk_fail_local.o to libc.a (swbz#21740) +- i386: Test memmove_chk and memset_chk only in libc.so (swbz#21741) +- Add new locales az_IR, mai_NP (swbz#14172) +- Various locale improvements + +* Thu Jul 27 2017 Carlos O'Donell - 2.25.90-28 +- Adjust to new rpm debuginfo generation (#1475009). + +* Wed Jul 26 2017 Fedora Release Engineering - 2.25.90-27.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Wed Jul 19 2017 Florian Weimer - 2.25.90-27 +- Auto-sync with upstream master, + commit 00d7a3777369bac3d8d44152dde2bb7381984ef6: +- aarch64: Fix out of bound array access in _dl_hwcap_string + +* Mon Jul 17 2017 Florian Weimer - 2.25.90-26 +- Drop glibc-rh1467518.patch in favor of upstream patch (#1467518) +- Auto-sync with upstream master, + commit 91ac3a7d8474480685632cd25f844d3154c69fdf: +- Fix pointer alignment in NSS group merge result construction (#1471985) +- Various locale fixes + +* Fri Jul 14 2017 Carlos O'Donell - 2.25.90-25 +- armv7hl: Drop 32-bit ARM build fix, already in upstream master. +- s390x: Apply glibc fix again, removing PTRACE_GETREGS etc. (#1469536). +- Auto-sync with upstream master, + commit de895ddcd7fc45caeeeb0ae312311b8bd31d82c5: +- Added Fiji Hindi language locale for Fiji (swbz#21694). +- Added yesstr/nostr for nds_DE and nds_NL (swbz#21756). +- Added yesstr and nostr for Tigrinya (swbz#21759). +- Fix LC_MESSAGES and LC_ADDRESS for anp_IN (swbz#21760). +- Added yesstr/nostr and fix yesexpr for pap_AW and pap_CW (swbz#21757). +- Added Tongan language locale for Tonga (swbz#21728). +- [ARM] Fix ld.so crash when built using Binutils 2.29. +- Added yesstr and nostr for aa_ET (swbz#21768). +- New locale for bi_VU (swbz#21767). +- Disable single thread optimization for open_memstream + +* Wed Jul 12 2017 Carlos O'Donell - 2.25.90-24 +- Fix IFUNC crash in early startup for ppc64le static binaries (#1467518). +- Enable building with BIND_NOW on ppc64le (#1467518). +- Fix 32-bit ARM builds in presence of new binutils. + +* Wed Jul 12 2017 Florian Weimer - 2.25.90-23 +- malloc: Tell GCC optimizers about MAX_FAST_SIZE in _int_malloc (#1470060) +- Auto-sync with upstream master, + commit 30200427a99e5ddac9bad08599418d44d54aa9aa: +- Add per-thread cache to malloc +- Add Samoan language locale for Samoa +- Add Awajún / Aguaruna locale for Peru +- CVE-2010-3192: Avoid backtrace from __stack_chk_fail (swbz#12189) +- Add preadv2, writev2 RWF_NOWAIT flag (swbz#21738) +- Fix abday strings for ar_JO/ar_LB/ar_SY locales (swbz#21749) +- Fix abday strings for ar_SA locale (swbz#21748, swbz#19066) +- Set data_fmt for da_DK locale (swbz#17297) +- Add yesstr and nostr for the zh_HK locale (swbz#21733) +- Fix abday strings for the ksIN@devanagari locale (swbz#21743) +- Do not include _dl_resolv_conflicts in libc.a (swbz#21742) +- Test __memmove_chk, __memset_chk only in libc.so (swbz#21741) +- Add iI and eE to yesexpr and noexpr respectively for ts_ZA locale +- Add yesstr/nostr for kw_GB locale (swbz#21734) +- Add yesstr and nostr for the ts_ZA locale (swbz#21727) +- Fix LC_NAME for hi_IN locale (swbz#21729) +- Add yesstr and nostr for the xh_ZA locale (swbz#21724) +- Add yesstr and nostr for the zh_CN locale (swbz#21723) +- Fix full weekday names for the ks_IN@devanagari locale (swbz#21721) +- Various fixes to Arabic locales after CLDR import + +* Tue Jul 11 2017 Florian Weimer - 2.25.90-22 +- Reinstantiate stack_t cleanup (#1468904) +- s390x: Restore PTRACE_GETREGS etc. to get GCC to build (#1469536) + +* Sun Jul 9 2017 Florian Weimer - 2.25.90-21 +- Back out stack_t cleanup (#1468904) + +* Thu Jul 06 2017 Florian Weimer - 2.25.90-20 +- Auto-sync with upstream master, + commit 031e519c95c069abe4e4c7c59e2b4b67efccdee5: +- x86-64: Align the stack in __tls_get_addr (#1440287) +- Add Tok-Pisin (tpi_PG) locale. +- Add missing yesstr/nostr for Pashto locale (swbz#21711) +- Add missing yesstr/nostr for Breton locale (swbz#21706) +- Single threaded stdio optimization +- sysconf: Use conservative default for _SC_NPROCESSORS_ONLN (swbz#21542) + +* Tue Jul 04 2017 Florian Weimer - 2.25.90-19 +- Auto-sync with upstream master, + commit 4446a885f3aeb3a33b95c72bae1f115bed77f0cb. + +* Tue Jul 04 2017 Florian Weimer - 2.25.90-18 +- Auto-sync with upstream master, + commit 89f6307c5d270ed4f11cee373031fa9f2222f2b9. + +* Tue Jul 4 2017 Florian Weimer - 2.25.90-17 +- Disable building with BIND_NOW on ppc64le (#1467518) + +* Mon Jul 03 2017 Florian Weimer - 2.25.90-16 +- Auto-sync with upstream master, + commit e237357a5a0559dee92261f1914d1fa2cd43a1a8: +- Support an arbitrary number of search domains in the stub resolver (#168253) +- Detect and apply /etc/resolv.conf changes in libresolv (#1374239) +- Increase malloc alignment on i386 to 16 (swbz#21120) +- Make RES_ROTATE start with a random name server (swbz#19570) +- Fix tgmath.h totalorder, totalordermag return type (swbz#21687) +- Miscellaneous sys/ucontext.h namespace fixes (swbz#21457) +- Rename struct ucontext tag (swbz#21457) +- Call exit system call directly in clone (swbz#21512) +- powerpc64le: Enable float128 +- getaddrinfo: Merge IPv6 addresses and IPv4 addresses (swbz#21295) +- Avoid .symver on common symbols (swbz#21666) +- inet_pton: Reject IPv6 addresses with many leading zeros (swbz#16637) + +* Fri Jun 23 2017 Florian Weimer - 2.25.90-15 +- Auto-sync with upstream master, + commit 3ec7c02cc3e922b9364dc8cfd1d4546671b91003, fixing: +- memcmp-avx2-movbe.S incorrect results for lengths 2/3 (#1464403) + +* Fri Jun 23 2017 Florian Weimer - 2.25.90-14 +- Auto-sync with upstream master, + commit 12f50337ae80672c393c2317d471d097ad92c492, changing: +- localedata: fur_IT: Fix spelling of Wednesday (Miercus) +- Update to Unicode 10.0.0 +- inet: __inet6_scopeid_pton should accept node-local addresses (swbz#21657) + +* Fri Jun 23 2017 Florian Weimer - 2.25.90-13 +- Reenable valgrind on aarch64 + +* Thu Jun 22 2017 Florian Weimer - 2.25.90-12 +- Log auxiliary vector during build + +* Thu Jun 22 2017 Florian Weimer - 2.25.90-11 +- Auto-sync with upstream master, + commit 0a47d031e44f15236bcef8aeba80e737bd013c6f. + +* Thu Jun 22 2017 Florian Weimer - 2.25.90-10 +- Disable valgrind on aarch64 + +* Wed Jun 21 2017 Florian Weimer - 2.25.90-9 +- Drop historic aarch64 TLS patches +- Drop workaround for GCC PR69537 +- Auto-sync with upstream master, + commit 9649350d2ee47fae00794d57e2526aa5d67d900e. + +* Wed Jun 21 2017 Florian Weimer - 2.25.90-8 +- Adjust build requirements for gcc, binutils, kernel-headers. +- Auto-sync with upstream master, + commit 43e0ac24c836eed627a75ca932eb7e64698407c6, changing: +- Remove + +* Mon Jun 19 2017 Florian Weimer - 2.25.90-7 +- Drop glibc-Disable-buf-NULL-in-login-tst-ptsname.c, applied upstream. +- Auto-sync with upstream master, + commit 37e9dc814636915afb88d0779e5e897e90e7b8c0, fixing: +- CVE-2017-1000366: Avoid large allocas in the dynamic linker (#1462820) +- wait3 namespace (swbz#21625) +- S390: Sync ptrace.h with kernel (swbz#21539) +- Another x86 sys/ucontext.h namespace issue (swbz#21457) +- siginterrupt namespace (swbz#21597) +- Signal stack namespace (swbz#21584) +- Define struct rusage in sys/wait.h when required (swbz#21575) +- S390: Fix build with gcc configured with --enable-default-pie (swbz#21537) +- Update timezone code from tzcode 2017b +- nptl: Invert the mmap/mprotect logic on allocated stacks (swbz#18988) +- PowerPC64 ELFv2 PPC64_OPT_LOCALENTRY +- Make copy of from GCC (swbz#21573) +- localedata: ce_RU: update weekdays from CLDR (swbz#21207) +- localedata: Remove trailing spaces (swbz#20275) +- XPG4 bsd_signal namespace (swbz#21552) +- Correct collation rules for Malayalam (swbz#19922, swbz#19919) +- waitid namespace (swbz#21561) +- Condition signal.h inclusion in sys/wait.h (swbz#21560) +- ld.so: Consolidate 2 strtouls into _dl_strtoul (swbz#21528) +- tst-timezone race (swbz#14096) +- Define SIG_HOLD for XPG4 (swbz#21538) +- struct sigaltstack namespace (swbz#21517) +- sigevent namespace (swbz#21543) +- Add shim header for bits/syscall.h (swbz#21514) +- namespace issues in sys/ucontext.h (swbz#21457) +- posix: Implement preadv2 and pwritev2 +- Various float128 and tunables improvements + +* Tue Jun 06 2017 Stephen Gallagher - 2.25.90-6 +- Reduce libcrypt-nss dependency to 'Suggests:' + +* Wed May 31 2017 Arjun Shankar - 2.25.90-5 +- Auto-sync with upstream master, + commit cfa9bb61cd09c40def96f042a3123ec0093c4ad0. +- Fix sys/ucontext.h namespace from signal.h etc. inclusion (swbz#21457) +- Fix sigstack namespace (swbz#21511) + +* Wed May 31 2017 Arjun Shankar - 2.25.90-4 +- Disable the NULL buffer test in login/tst-ptsname.c. It leads to a build + failure during 'make check'. A permanent solution is being discussed + upstream. + +* Tue May 23 2017 Arjun Shankar - 2.25.90-3 +- Auto-sync with upstream master, + commit 231a59ce2c5719d2d77752c21092960e28837b4a. +- Add el_GR@euro support (swbz#20686) +- Set dl_platform and dl_hwcap from CPU features (swbz#21391) +- Use __glibc_reserved convention in mcontext, sigcontext (swbz#21457) +- Fix signal.h bsd_signal namespace (swbz#21445) +- Fix network headers stdint.h namespace (swbz#21455) +- resolv: Use RES_DFLRETRY consistently (swbz#21474) +- Condition some sys/ucontext.h contents on __USE_MISC (swbz#21457) +- Consolidate Linux read syscall (swbz#21428) +- fork: Remove bogus parent PID assertions (swbz#21386) +- Reduce value of LD_HWCAP_MASK for tst-env-setuid test case (swbz#21502) +- libio: Avoid dup already opened file descriptor (swbz#21393) + +* Mon May 01 2017 Carlos O'Donell - 2.25.90-2 +- Auto-sync with upstream master, + commit 25e39b4229fb365a605dc4c8f5d6426a77bc08a6. +- logbl for POWER7 return incorrect results (swbz#21280) +- sys/socket.h uio.h namespace (swbz#21426) +- Support POSIX_SPAWN_SETSID (swbz#21340) +- Document how to provide a malloc replacement (swbz#20424) +- Verify that all internal sockets opened with SOCK_CLOEXEC (swbz#15722) +- Use AVX2 memcpy/memset on Skylake server (swbz#21396) +- unwind-dw2-fde deadlock when using AddressSanitizer (swbz#21357) +- resolv: Reduce advertised EDNS0 buffer size to guard against + fragmentation attacks (swbz#21361) +- mmap64 silently truncates large offset values (swbz#21270) +- _dl_map_segments does not test for __mprotect failures consistently + (swbz#20831) + +* Thu Mar 02 2017 Florian Weimer - 2.25.90-1 +- Switch back to upstream master branch. +- Drop Unicode 9 patch, merged upstream. +- Auto-sync with upstream master, + commit a10e9c4e53fc652b79abf838f7f837589d2c84db, fixing: +- Build all DSOs with BIND_NOW (#1406731) + +* Wed Mar 1 2017 Jakub Hrozek - 2.25-3 +- NSS: Prefer sss service for passwd, group databases (#1427646) + +* Tue Feb 28 2017 Florian Weimer - 2.25-2 +- Auto-sync with upstream release/2.25/master, + commit 93cf93e06ce123439e41d3d62790601c313134cb, fixing: +- sunrpc: Improvements for UDP client timeout handling (#1346406) +- sunrpc: Avoid use-after-free read access in clntudp_call (swbz#21115) +- Fix getting tunable values on big-endian (swbz#21109) + +* Wed Feb 08 2017 Carlos O'Donell - 2.25-1 +- Update to final released glibc 2.25. + +* Wed Feb 08 2017 Carlos O'Donell - 2.24.90-31 +- Fix builds with GCC 7.0. + +* Wed Feb 01 2017 Carlos O'Donell - 2.24.90-30 +- Optimize IBM z System builds for zEC12. + +* Wed Jan 25 2017 Florian Weimer - 2.24.90-29 +- Use vpath in crypt-glibc/Makefile to obtain the test input file. +- Auto-sync with upstream master, + commit 5653ab12b4ae15b32d41de7c56b2a4626cd0437a, fixing: +- ARM fpu_control.h for assemblers requiring VFP insn names (swbz#21047) +- FAIL in test string/tst-xbzero-opt (swbz#21006) +- Make soft-float powerpc swapcontext restore the signal mask (swbz#21045) +- Clear list of acquired robust mutexes in the child after fork (swbz#19402) + +* Thu Jan 12 2017 Carlos O'Donell - 2.24.90-28 +- Auto-sync with upstream master, + commit 468e525c81a4af10f2e613289b6ff7c950773a9e: +- Drop rwlock related patches applied upstream. +- Fix i686 memchr for large input sizes (swbz#21014) +- Fix x86 strncat for large input sizes (swbz#19390) +- powerpc: Fix write-after-destroy in lock elision (swbz#20822) +- New pthread rwlock that is more scalable. +- Fix testsuite build for GCC 7 -Wformat-truncation. + +* Mon Jan 02 2017 Florian Weimer - 2.24.90-27 +- Auto-sync with upstream master, + commit 73dfd088936b9237599e4ab737c7ae2ea7d710e1: +- Enable tunables. +- Drop condvar-related patches applied upstream. +- Update DNS RR type definitions (swbz#20593) +- CVE-2015-5180: resolv: Fix crash with internal QTYPE (#1249603) +- sunrpc: Always obtain AF_INET addresses from NSS (swbz#20964) + + +* Mon Dec 26 2016 Florian Weimer - 2.24.90-26 +- Auto-sync with upstream master, + commit cecbc7967f0bcac718b6f8f8942b58403c0e917c +- Enable stack protector for most of glibc (#1406731) + +* Fri Dec 23 2016 Carlos O'Donell - 2.24.90-25 +- Auto-sync with upstream master, + commit 81e0662e5f2c342ffa413826b7b100d56677b613, fixing: +- Shared object unload assert when calling dlclose (#1398370, swbz#11941) +- Fix nss_nisplus build with mainline GCC (swbz#20978) +- Add Intel TSX blacklist for silicon with known errata. +- Add fmax, fmin, fmaxf, fminf microbenchmarks. +- Robust mutexes: Fix lost wake-up (swbz#20973). +- Add fmaxmag, fminmag, roundeven, roundevenf, roundevenl functions. + +* Sun Dec 18 2016 Florian Weimer - 2.24.90-24 +- Auto-sync with upstream master, + commit e077349ce589466eecd47213db4fae6b80ec18c4, fixing: +- Warn about assignment in assertions (#1105335) +- powerpc64/power7 memchr for large input sizes (swbz#20971) +- fmax, fmin sNaN handling (swbz#20947) + +* Mon Dec 12 2016 Florian Weimer - 2.24.90-23 +- Auto-sync with upstream master, + commit 92dcaa3e2f7bf0f7f1c04cd2fb6a317df1a4e225, fixing: +- Add getrandom, getentropy (#1172273) +- Add additional compiler barriers to backtrace tests (swbz#20956) + +* Fri Dec 09 2016 Florian Weimer - 2.24.90-22 +- Auto-sync with upstream master, + commit 0abbe7cd700951082b314182a0958d65238297ef, changing: +- IN6_IS_ADDR_ does not require enabling non-standard extensions (#1138893) +- Install libm.a as linker script (swbz#20539) +- Fix writes past the allocated array bounds in execvpe (swbz#20847) +- Fix hypot sNaN handling (swbz#20940) +- Fix x86_64/x86 powl handling of sNaN arguments (swbz#20916) +- Fix sysdeps/ieee754 pow handling of sNaN arguments (swbz#20916) +- Fix pow (qNaN, 0) result with -lieee (swbz#20919) +- Fix --enable-nss-crypt failure of tst-linkall-static (swbz#20918) + +* Fri Dec 02 2016 Florian Weimer - 2.24.90-21 +- Auto-sync with upstream master, + commit 01b23a30b42a90b1ebd882a0d81110a1542e504a, fixing: +- aarch64: Incorrect dynamic TLS resolution (#1400347) + +* Wed Nov 30 2016 Florian Weimer - 2.24.90-20 +- Auto-sync with upstream master, + commit 9e78f6f6e7134a5f299cc8de77370218f8019237, fixing: +- stdio buffering with certain network file systems (#1400144) +- libpthread initialization breaks ld.so exceptions (#1393909) +- x86_64: Use of PLT and GOT in static archives (swbz#20750) +- localedata, iconvdata: 0x80->Euro sign mapping for GBK (swbz#20864) +- math: x86_64 -mfpmath=387 float_t, double_t (swbz#20787) + +* Wed Nov 23 2016 Florian Weimer - 2.24.90-19 +- Auto-sync with upstream master, + commit 7a5e3d9d633c828d84a9535f26b202a6179978e7: +- Fix default float_t definition (swbz#20855) +- Fix writes past the allocated array bounds in execvpe (swbz#20847) + +* Tue Nov 22 2016 Florian Weimer - 2.24.90-18 +- Auto-sync with upstream master, + commit 5ee1a4443a3eb0868cef1fe506ae6fb6af33d4ad. + +* Wed Nov 16 2016 Carlos O'Donell - 2.24.90-17 +* Add new scalable implementation of POSIX read-write locks. + +* Wed Nov 16 2016 Florian Weimer - 2.24.90-16 +- Do not try to link libcrypt statically during tests + +* Wed Nov 16 2016 Florian Weimer - 2.24.90-15 +- Auto-sync with upstream master, + commit 530862a63e0929128dc98fbbd463b120934434fb, fixing: +- Fix rpcgen buffer overrun (swbz#20790) +- Fix ppc64 build failure to swbz#20729 fix attempt + +* Wed Nov 2 2016 Florian Weimer - 2.24.90-14 +- Drop glibc-swbz20019.patch, applied upstream. +- dlerror returns NULL after dlsym (RTLD_NEXT) lookup failure (#1333945) + (fixed by dropping the revert) +- Auto-sync with upstream master, + commit 9032070deaa03431921315f973c548c2c403fecc, fixing: +- Correct clog10 documentation (swbz#19673) +- Fix building with -Os (swbz#20729) +- Properly initialize glob structure with GLOB_BRACE|GLOB_DOOFFS (swbz#20707) +- powerpc: Fix TOC stub on powerpc64 clone (swbz#20728) +- math: Make strtod raise "inexact" exceptions (swbz#19380) +- malloc: Remove malloc_get_state, malloc_set_state (swbz#19473) + +* Sat Oct 22 2016 Florian Weimer - 2.24.90-13 +- Auto-sync with upstream master, + commit e37208ce86916af9510ffb9ce7b3c187986f07de, changing: +- Restore compatbility with extern "C" wrappers + +* Fri Oct 21 2016 Florian Weimer - 2.24.90-12 +- Auto-sync with upstream master, + commit b3918c44db615637b26d919ce599cd86592316b3, fixing: +- math: Turn iszero into a function template (#1387415) +- ARM: Use VSQRT instruction (swbz#20660) +- math: Stop powerpc copysignl raising "invalid" for sNaN (swbz#20718) +- x86: Fix FMA and AVX2 detection (swbz#20689) +- x86: Avoid assertion failure on older Intel CPus (swbz#20647) + +* Mon Oct 17 2016 Carlos O'Donell - 2.24.90-11 +- Add prototype support for detecting invalid IFUNC calls (swbz#20019). +- New POSIX thread condition variable implementation (swbz#13165). + +* Fri Oct 07 2016 Florian Weimer - 2.24.90-10 +- Auto-sync with upstream master, + commit 5140d036f9c16585448b5908c3a219bd96842161, fixing: +- resolv: Remove RES_USEBSTRING and its implementation (swbz#20629) +- Refactor ifunc resolvers due to false debuginfo (swbz#20478) + +* Tue Oct 04 2016 Florian Weimer - 2.24.90-9 +- Auto-sync with upstream master, + commit ff88ee7edfaa439e23c42fccaf3a36cd5f041894, fixing: +- LONG_WIDTH is incorrectly set to the 64 on 32-bit platforms (#1381582) +- libio: Multiple fixes for open_{w}memstream (swbz#18241, swbz#20181) +- Simplify and test _dl_addr_inside_object (swbz#20292) + +* Thu Sep 22 2016 Florian Weimer - 2.24.90-8 +- Add support for MIPS (#1377795) +- Drop glibc-rh1315476-1.patch (sln pre-processor cleanup), it was + applied upstream. +- Auto-sync with upstream master, + commit 17af5da98cd2c9ec958421ae2108f877e0945451, fixing the following bugs: +- Fix non-LE TLS in static programs (swbz#19826) +- resolv: Remove unsupported hook functions from the API (swbz#20016) +- Remove RR type classification macros (swbz#20592) +- Remove obsolete DNSSEC support (swbz#20591) +- manual: Clarify the documentation of strverscmp (swbz#20524) + +* Tue Sep 20 2016 Carlos O'Donell - 2.24.90-7 +- Auto-sync with upstream master. + +* Thu Sep 01 2016 Florian Weimer - 2.24.90-6 +- Auto-sync with upstream master, + commit 4d728087ef8cc826b05bd21d0c74d4eca9b1a27d, fixing: +- Base on Linux headers (#1360480) +- Simplify static malloc interposition (swbz#20432) + +* Fri Aug 26 2016 Florian Weimer - 2.24.90-5 +- Auto-sync with upstream master, + commit 7e625f7e85b4e88f10dbde35a0641742af581806, fixing: +- lt_LT locale: use hyphens in d_fmt (swbz#20497) +- nptl test time reductions (swbz#19946) + +* Sun Aug 21 2016 Florian Weimer - 2.24.90-4 +- Auto-sync with upstream master, + commit 66abf9bfbe24ac1e7207d26ccad725ed938dc52c, fixing: +- argp: Do not override GCC keywords with macros (#1366830) + +* Wed Aug 17 2016 Florian Weimer - 2.24.90-3 +- Auto-sync with upstream master, + commit d9067fca40b8aac156d73cfa44d6875813555a6c, with these changes: +- Avoid duplicating object files already in libc.a (#1352625) +- CVE-2016-6323: Backtraces can hang on ARM EABI (32-bit) (swbz#20435) +- et_EE: locale has wrong {p,n}_cs_precedes value (swbz#20459 + +* Thu Aug 11 2016 Florian Weimer - 2.24.90-2 +- Auto-sync with upstream master, + commit f79211792127f38d5954419bb3784c8eb7f5e4e5 + +* Mon Aug 08 2016 Carlos O'Donell - 2.24.90-1 +- Set version to 2.24.90 to match upstream development. + +* Mon Aug 08 2016 Carlos O'Donell - 2.23.90-31 +- Auto-sync with upstream master. + +* Thu Jul 21 2016 Florian Weimer - 2.23.90-30 +- Drop sendmsg/recvmsg compatibility patch (#1344830) +- glibc-devel depends on libgcc%%{_isa} (#1289356) +- Drop Requires(pre) on libgcc +- Introduce libcrypt and libcrypt-nss (#1324623) +- Do not try to install mtrace when bootstrapping + +* Wed Jul 20 2016 Florian Weimer - 2.23.90-29 +- Move NSS modules to subpackages (#1338889) + +* Wed Jul 13 2016 Florian Weimer - 2.23.90-28 +- Auto-sync with upstream master, commit + f531f93056b34800383c5154280e7ba5112563c7. +- Add de_LI.UTF-8 locale. +- Make ldconfig and sln the same binary. (#1315476) + +* Fri Jul 08 2016 Mike FABIAN - 2.23.90-27 +- Unicode 9.0.0 updates (ctype, charmap, transliteration) (#1351108) + +* Tue Jul 05 2016 Florian Weimer - 2.23.90-26 +- Auto-sync with upstream master, up to commit + 30e4cc5413f72c2c728a544389da0c48500d9904, fixing these bug: +- strcasecmp failure on ppc64le (#nscd breaks initgroups with nis (initgroups are empty) (#1294574) + +* Fri Jun 24 2016 Carlos O'Donell - 2.23.90-25 +- Properly handle more invalid --install-langs arguments (#1349906). + +* Tue Jun 21 2016 Florian Weimer - 2.23.90-24 +- Auto-sync with upstream master, commit + a3b473373ee43a292f5ec68a7fda6b9cfb26a9b0, fixing these bugs: +- Unnecessary mmap fallback in malloc (#1348620) +- pwritev system call passes incorrect offset to kernel (#1346070) + +* Sat Jun 18 2016 Carlos O'Donell - 2.23.90-23 +- Use scriptlet expansion in all-langpacks posttrans script to expand + _install_langes macro. + +* Mon Jun 13 2016 Florian Weimer - 2.23.90-22 +- Remove glibc-fedora-uname-getrlimit.patch. This patch was + introduced to fix bug rhbz#579086 (Preloading a replacement uname + is causing environment to be cleaned if libpthread is loaded). + UTS namespaces should now offer a cleaner way yo do this. +- Drop sendmmsg/recvmmsg compat symbols on 32-bit architectures (#1344830) +* Sat Jun 11 2016 Florian Weimer - 2.23.90-21 +- First phase of sendmsg/recvmsg/sendmmsg/recvmmsg ABI revert: + GLIBC_2.24 compatibility symbols (#1344830) +- Auto-sync with upstream master + (commit 31d0a4fa646db8b8c97ce24e0ec0a7b73de4fca1), + fixing the following bugs: +- Add eo locale +- Crash in the nss_db NSS service module during iteration (#1344480) + +* Thu Jun 09 2016 Florian Weimer - 2.23.90-20 +- Auto-sync with upstream master, fixing this bug: +- Emacs crashes on startup (#1342976) + +* Wed Jun 01 2016 Florian Weimer - 2.23.90-19 +- Auto-sync with upstream master. +- Adjust glibc-rh1315108.patch accordingly. +- Fix fork redirection in libpthread (#1326903) +- CVE-2016-4429: stack overflow in Sun RPC clntudp_call (#1337140) +- Do not disable assertions in release builds (#1338887) + +* Wed May 11 2016 Carlos O'Donell - 2.23.90-18 +- Move support for building GCC 2.96 into compat-gcc-296. + +* Wed May 11 2016 Florian Weimer - 2.23.90-17 +- Temporily revert dlsym (RTLD_NEXT)/dlerror change, to unbreak + ASAN until it is fixed (#1335011) + +* Mon May 9 2016 Florian Weimer - 2.23.90-16 +- Drop the “fix” for fork/vfork NULL symbols in libpthread. It does + not work because ld.so apparently supports some variant of direct + binding. + +* Mon May 09 2016 Florian Weimer - 2.23.90-15 +- Auto-sync with upstream master. +- Drop glibc-nsswitch-Add-group-merging-support.patch, applied upstream. +- Drop glibc-rh1252570.patch, alternative fixes applied upstream. +- Adjust glibc-rh1315108.patch to minor upstream change. +- Update SUPPORTED file. +- Experimental fix for NULL fork/vfork symbols in libpthread (#1326903) + +* Tue May 03 2016 Carlos O'Donell - 2.23.90-14 +- Require libselinux for nscd in non-bootstrap configuration. + +* Fri Apr 29 2016 Carlos O'Donell - 2.23.90-13 +- Auto-sync with upstream master. + +* Thu Apr 28 2016 Carlos O'Donell - 2.23.90-12 +- Move spec file system information logging to the build stage. + +* Thu Apr 14 2016 Florian Weimer - 2.23.90-11 +- Auto-sync with upstream master. +- Unbreak pread/pread64 on armhfp (#1327277) + +* Thu Apr 14 2016 Florian Weimer - 2.23.90-10 +- Auto-sync with upstream master. + +* Thu Apr 14 2016 Florian Weimer - 2.23.90-9 +- Auto-sync with upstream master. Removes type union wait. +- Update SUPPORTED locales file. + +* Fri Apr 08 2016 Florian Weimer - 2.23.90-8 +- Auto-sync with upstream master. + +* Tue Mar 29 2016 Florian Weimer - 2.23.90-7 +- Auto-sync with upstream master. +- Adjust glibc-rh1252570.patch to partial upstream fix. +- Drop glibc-fix-an_ES.patch, now included upstream. + +* Wed Mar 16 2016 Carlos O'Donell - 2.23.90-6 +- Use 'an' as language abbreviation for an_ES. + +* Mon Mar 07 2016 Carlos O'Donell - 2.23.90-5 +- Auto-sync with upstream master. + +* Sun Mar 6 2016 Florian Weimer - 2.23.90-4 +- Remove extend_alloca (#1315108) + +* Mon Feb 29 2016 Carlos O'Donell - 2.23.90-3 +- Enhance support for upgrading from a non-language-pack system. + +* Fri Feb 26 2016 Mike FABIAN - 2.23.90-2 +- Create new language packages for all supported languages. + Locales, translations, and locale sources are split into + distinct sub-packages. A meta-package is created for users + to install all languages. Transparent installation support + is provided via dnf langpacks. + +* Fri Feb 26 2016 Carlos O'Donell - 2.23.90-1 +- Upstream development version is now 2.23.90. + +* Thu Feb 25 2016 Carlos O'Donell - 2.22.90-38 +- Auto-sync with upstream master. + +* Fri Feb 19 2016 Florian Weimer - 2.22.90-37 +- Remove stray newline from Serbian locales (#1114591). + +* Tue Feb 16 2016 CArlos O'Donell - 2.22.90-36 +- Fix CVE-2015-7547: getaddrinfo() stack-based buffer overflow (#1308943). + +* Mon Feb 15 2016 Florian Weimer - 2.22.90-35 +- Revert may_alias attribute for struct sockaddr (#1306511). +- Revert upstream commit 2212c1420c92a33b0e0bd9a34938c9814a56c0f7 (#1252570). + +* Sat Feb 13 2016 Florian Weimer - 2.22.90-34 +- Auto-sync with upstream master. +- Support aliasing with struct sockaddr pointers (#1306511). + +* Tue Feb 09 2016 Carlos O'Donell - 2.22.90-33 +- Use --with-cpu=power8 for ppc64le default runtime (#1227361). + +* Tue Feb 02 2016 Florian Weimer - 2.22.90-32 +- Auto-sync with upstream master. +- Add glibc-isinf-cxx11.patch to improve C++11 compatibility. + +* Thu Jan 28 2016 Florian Weimer - 2.22.90-31 +- Add workaround for GCC PR69537. + +* Thu Jan 28 2016 Florian Weimer - 2.22.90-30 +- Auto-sync with upstream master. + +* Wed Jan 13 2016 Carlos O'Donell - 2.22.90-29 +- New pthread_barrier algorithm with improved standards compliance. + +* Wed Jan 13 2016 Carlos O'Donell - 2.22.90-28 +- Add group merging support for distributed management (#1146822). + +* Tue Jan 12 2016 Carlos O'Donell - 2.22.90-27 +- Remove 32-bit POWER support. +- Add 64-bit POWER7 BE and 64-bit POWER8 BE optimized libraries. + +* Mon Dec 21 2015 Florian Weimer - 2.22.90-26 +- Auto-sync with upstream master. + +* Wed Dec 16 2015 Florian Weimer - 2.22.90-25 +- Auto-sync with upstream master. +- Includes fix for malloc assertion failure in get_free_list. (#1281714) +- Drop Unicode 8.0 patches (now merged upstream). + +* Sat Dec 5 2015 Florian Weimer - 2.22.90-24 +- Put libmvec_nonshared.a into the -devel package. (#1288738) + +* Sat Dec 05 2015 Florian Weimer - 2.22.90-23 +- Auto-sync with upstream master. + +* Thu Nov 26 2015 Carlos O'Donell - 2.22.90-22 +- The generic hidden directive support is already used for + preinit/init/fini-array symbols so we drop the Fedora-specific + patch that does the same thing. + Reported by Dmitry V. Levin + +* Thu Nov 26 2015 DJ Delorie - 2.22.90-22 +- Require glibc-static for C++ tests. +- Require gcc-c++, libstdc++-static, and glibc-static only when needed. +- Fix --without docs to not leave info files. + +* Fri Nov 20 2015 Florian Weimer - 2.22.90-21 +- Auto-sync with upstream master. + +* Wed Nov 18 2015 Florian Weimer - 2.22.90-20 +- Auto-sync with upstream master. + +* Wed Nov 18 2015 Florian Weimer - 2.22.90-19 +- Disable -Werror on s390 (#1283184). + +* Mon Nov 16 2015 Florian Weimer - 2.22.90-18 +- Auto-sync with upstream master. + +* Mon Nov 16 2015 Florian Weimer - 2.22.90-17 +- Revert temporary armhfp build fix. + +* Mon Nov 9 2015 Florian Weimer - 2.22.90-16 +- Apply temporary fix for armhfp build issue. + +* Mon Nov 09 2015 Florian Weimer - 2.22.90-15 +- Auto-sync with upstream master. + +* Tue Nov 3 2015 Florian Weimer - 2.22.90-14 +- Log uname, cpuinfo, meminfo during build (#1276636) + +* Fri Oct 30 2015 Florian Weimer - 2.22.90-13 +- Auto-sync with upstream master. + +* Fri Oct 30 2015 Florian Weimer - 2.22.90-12 +- Revert to upstream implementation of condition variables (#1229659) + +* Wed Oct 28 2015 Florian Weimer - 2.22.90-11 +- Disable valgrind test on ppc64p7, too. + +* Mon Oct 26 2015 Carlos O'Donell - 2.22.90-10 +- Disable valgrind test for ppc64. + +* Wed Oct 21 2015 Carlos O'Donell - 2.22.90-9 +- Sync with upstream master. +- Update new condvar implementation. + +* Fri Oct 9 2015 Carlos O'Donell - 2.22.90-8 +- Remove libbsd.a (#1193168). + +* Wed Sep 16 2015 Mike FABIAN - 2.22.90-7 +- Add the C.UTF-8 locale (#902094). + +* Wed Sep 16 2015 Carlos O'Donell - 2.22.90-6 +- Fix GCC 5 and -Werror related build failures. +- Fix --install-langs bug which causes SIGABRT (#1262040). + +* Fri Aug 28 2015 Carlos O'Donell - 2.22.90-5 +- Auto-sync with upstream master. + +* Thu Aug 27 2015 Carlos O'Donell - 2.22.90-4 +- Build require gcc-c++ for the C++ tests. +- Support --without testsuite option to disable testing after build. +- Support --without benchtests option to disable microbenchmarks. +- Update --with bootstrap to disable benchtests, valgrind, documentation, + selinux, and nss-crypt during bootstrap. +- Support --without werror to disable building with -Werror. +- Support --without docs to disable build requirement on texinfo. +- Support --without valgrind to disable testing with valgrind. +- Remove c_stubs add-on and enable fuller support for static binaries. +- Remove librtkaio support (#1227855). + +* Sun Aug 16 2015 Siddhesh Poyarekar - 2.22.90-3 +- Auto-sync with upstream master. + +* Fri Aug 14 2015 Siddhesh Poyarekar - 2.22.90-2 +- Remove initgroups from the default nsswitch.conf (#751450). + +* Fri Aug 14 2015 Siddhesh Poyarekar - 2.22.90-1 +- Sync with upstream master. + +* Tue Jul 28 2015 Siddhesh Poyarekar - 2.21.90-20 +- Sync with upstream master. + +* Thu Jul 23 2015 Mike FABIAN - 2.21.90-19 +- some more additions to the translit_neutral file by Marko Myllynen + +* Tue Jul 14 2015 Mike FABIAN - 2.21.90-18 +- Unicode 8.0.0 updates, including the transliteration files (#1238412). + +* Sun Jun 21 2015 Carlos O'Donell - 2.21.90-17 +- Remove all linuxthreads handling from glibc spec file. + +* Wed Jun 17 2015 Carlos O'Donell - 2.21.90-16 +- Move split out architecture-dependent header files into devel package + and keep generic variant in headers package, thus keeping headers package + content and file list identical across multilib rpms. + +* Wed Jun 17 2015 Fedora Release Engineering - 2.21.90-15.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Wed Jun 3 2015 Carlos O'Donell - 2.21.90-15 +- Remove patch to increase DTV surplus which is no longer needed after + upstream commit f8aeae347377f3dfa8cbadde057adf1827fb1d44. + +* Sat May 30 2015 Siddhesh Poyarekar - 2.21.90-14 +- Fix build failure on aarch64 (#1226459). + +* Mon May 18 2015 Siddhesh Poyarekar - 2.21.90-13 +- Sync with upstream master. +- Install new condvar implementation. + +* Fri May 08 2015 Siddhesh Poyarekar - 2.21.90-12 +- Add benchmark comparison scripts. + +* Thu May 07 2015 Siddhesh Poyarekar - 2.21.90-11 +- Auto-sync with upstream master. +- Revert arena threshold fix to work around #1209451. + +* Tue Apr 07 2015 Siddhesh Poyarekar - 2.21.90-10 +- Revert last auto-sync (#1209451). + +* Mon Apr 06 2015 Siddhesh Poyarekar - 2.21.90-9 +- Auto-sync with upstream master. + +* Tue Mar 24 2015 Siddhesh Poyarekar - 2.21.90-8 +- Auto-sync with upstream master. + +* Tue Mar 17 2015 Carlos O'Donell - 2.21.90-7 +- Use rpm.expand in scripts to reduce set of required RPM features. + +* Thu Mar 12 2015 Siddhesh Poyarekar - 2.21.90-6 +- Auto-sync with upstream master. + +* Tue Mar 3 2015 Mike Fabian - 2.21.90-5 +- Support installing only those locales specified by the RPM macro + %%_install_langs (#156477). + +* Mon Feb 23 2015 Siddhesh Poyarekar - 2.21.90-4 +- Auto-sync with upstream master. + +* Sat Feb 21 2015 Till Maas - 2.21.90-3.1 +- Rebuilt for Fedora 23 Change + https://fedoraproject.org/wiki/Changes/Harden_all_packages_with_position-independent_code + +* Thu Feb 12 2015 Carlos O'Donell - 2.21.90-3 +- Fix missing clock_* IFUNCs in librtkaio. + +* Thu Feb 12 2015 Carlos O'Donell - 2.21.90-2 +- Auto-sync with upstream master. + +* Wed Feb 11 2015 Carlos O'Donell - 2.21.90-1 +- Add back x86 vDSO support. +- Fix rtkaio build to reference clock_* functions from libc. + +* Wed Jan 21 2015 Siddhesh Poyarekar - 2.20.90-20 +- Sync with upstream master. +- Disable werror on s390x. +- Revert x86 vDSO support since it breaks i686 rtkaio build. + +* Tue Jan 20 2015 Peter Robinson 2.20.90-19 +- Drop large ancient ChangeLogs (rhbz #1169546) + +* Mon Jan 12 2015 Siddhesh Poyarekar - 2.20.90-18 +- Pass address of main_arena.mutex to mutex_lock/unlock. + +* Thu Jan 08 2015 Siddhesh Poyarekar - 2.20.90-17 +- Define a __tls_get_addr macro to avoid a conflicting declaration. + +* Wed Jan 07 2015 Siddhesh Poyarekar - 2.20.90-16 +- Disable -Werror for s390 as well. + +* Wed Jan 07 2015 Siddhesh Poyarekar - 2.20.90-14 +- Sync with upstream master. +- Disable -Werror on powerpc and armv7hl. +- Temporarily disable valgrind test on ppc64. + +* Sun Dec 28 2014 Dan Horák +- valgrind available only on selected arches (missing on s390) + +* Wed Dec 10 2014 Kyle McMartin +- aarch64: Drop strchrnul.S revert, apply fix from Richard Earnshaw. + +* Fri Dec 05 2014 Carlos O'Donell - 2.20.90-13 +- Fix permission of debuginfo source files to allow multiarch + debuginfo packages to be installed and upgraded. + +* Fri Dec 05 2014 Siddhesh Poyarekar - 2.20.90-12 +- Remove LIB_LANG since we don't install locales in /usr/lib/locale anymore. +- Don't own any directories in /usr/share/locale (#1167445). +- Use the %%find_lang macro to get the *.mo files (#1167445). +- Add %%lang tags to language locale files in /usr/share/i18n/locale (#1169044). + +* Wed Dec 03 2014 Kyle McMartin - 2.20.90-11 +- aarch64: revert optimized strchrnul.S implementation (rhbz#1167501) + until it can be debugged. + +* Fri Nov 28 2014 Carlos O'Donell - 2.20.90-10 +- Auto-sync with upstream master. + +* Wed Nov 19 2014 Carlos O'Donell - 2.20.90-9 +- Sync with upstream master. + +* Wed Nov 05 2014 Siddhesh Poyarekar - 2.20.90-8 +- Make getconf return only /usr/bin (#1138835). +- Sync with upstream master. + +* Tue Nov 04 2014 Arjun Shankar - 2.20.90-7 +- Add patch that modifies several tests to use test-skeleton.c. + The patch is accepted but not yet committed upstream. + https://sourceware.org/ml/libc-alpha/2014-10/msg00744.html + +* Tue Sep 30 2014 Siddhesh Poyarekar - 2.20.90-6 +- Sync with upstream master. +- Disable more Intel TSX usage in rwlocks (#1146967). +- Enable lock elision again on s390 and s390x. +- Enable Systemtap SDT probes for all architectures (#985109). + +* Fri Sep 26 2014 Carlos O'Donell - 2.20.90-5 +- Disable lock elision support for Intel hardware until microcode + updates can be done in early bootup (#1146967). +- Fix building test tst-strtod-round for ARM. + +* Tue Sep 23 2014 Siddhesh Poyarekar - 2.20.90-4 +- Sync with upstream master. +- Don't own the common debuginfo directories (#1144853). +- Run valgrind in the %%check section to ensure that it does not break. + +* Tue Sep 16 2014 Siddhesh Poyarekar - 2.20.90-3 +- Sync with upstream master. +- Revert patch for #737223. + +* Mon Sep 08 2014 Siddhesh Poyarekar - 2.20.90-2 +- Build build-locale-archive statically again. + +* Mon Sep 08 2014 Siddhesh Poyarekar - 2.20.90-1 +- Sync with upstream master. + +* Thu Sep 4 2014 Carlos O'Donell - 2.19.90-36 +- Allow up to 32 dlopened modules to use static TLS (#1124987). +- Run glibc tests in %%check section of RPM spec file. +- Do not run tests with `-k` and fail if any test fails to build. + +* Tue Aug 26 2014 Siddhesh Poyarekar - 2.19.90-35 +- Sync with upstream master. +- Use INTERNAL_SYSCALL in TLS_INIT_TP (#1133134). +- Remove gconv loadable module transliteration support (CVE-2014-5119, #1119128). + +* Fri Aug 22 2014 Dennis Gilmore - 2.19.90-34 +- add back sss to nsswitch.conf we have added workarounds in the tools + +* Thu Aug 21 2014 Kevin Fenzi - 2.19.90-33.1 +- Rebuild for rpm bug 1131960 + +* Tue Aug 19 2014 Dennis Gilmore - 2.19.90-33 +- remove sss from default nsswitch.conf it causes issues with live image composing + +* Wed Aug 13 2014 Siddhesh Poyarekar - 2.19.90-32 +- Auto-sync with upstream master. +- Revert to only defining __extern_always_inline for g++-4.3+. +- Fix build failure in compat-gcc-32 (#186410). + +* Mon Jul 28 2014 Siddhesh Poyarekar - 2.19.90-31 +- Auto-sync with upstream master. + +* Wed Jul 23 2014 Siddhesh Poyarekar - 2.19.90-30 +- Undo last master sync to fix up rawhide. + +* Tue Jul 15 2014 Siddhesh Poyarekar - 2.19.90-29 +- Auto-sync with upstream master. + +* Sat Jul 12 2014 Tom Callaway - 2.19.90-28 +- fix license handling + +* Mon Jul 07 2014 Siddhesh Poyarekar - 2.19.90-27 +- Auto-sync with upstream master. + +* Fri Jul 04 2014 Siddhesh Poyarekar - 2.19.90-26 +- Sync with upstream roland/nptl branch. +- Improve testsuite failure outputs in build.log + +* Thu Jul 03 2014 Siddhesh Poyarekar - 2.19.90-25 +- Sync with upstream roland/nptl branch. + +* Wed Jul 02 2014 Siddhesh Poyarekar - 2.19.90-24 +- Sync with upstream master. + +* Tue Jun 24 2014 Siddhesh Poyarekar - 2.19.90-23 +- Sync with upstream master. +- Add fix to unbreak i386 ABI breakage due to a change in scalbn. + +* Fri Jun 20 2014 Kyle McMartin - 2.19.90-22 +- AArch64: Save & restore NZCV (flags) upon entry to _dl_tlsdesc_dynamic + in order to work around GCC reordering compares across the TLS + descriptor sequence (GCC PR61545.) Committing a (temporary) fix here + allows us to avoid rebuilding the world with gcc 4.9.0-11.fc21. + +* Mon Jun 16 2014 Kyle McMartin - 2.19.90-21 +- Auto-sync with upstream master. + +* Thu Jun 12 2014 Siddhesh Poyarekar - 2.19.90-20 +- Auto-sync with upstream master. + +* Sat Jun 07 2014 Fedora Release Engineering - 2.19.90-19.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue Jun 03 2014 Siddhesh Poyarekar - 2.19.90-19 +- Sync with upstream master. + +* Mon May 26 2014 Siddhesh Poyarekar - 2.19.90-18 +- Sync with upstream master. +- Adjust rtkaio patches to build with upstream master. + +* Wed May 21 2014 Kyle McMartin - 2.19.90-17 +- Backport some upstream-wards patches to fix TLS issues on AArch64. + +* Wed May 21 2014 Kyle McMartin - 2.19.90-16 +- AArch64: Fix handling of nocancel syscall failures (#1098327) + +* Thu May 15 2014 Siddhesh Poyarekar - 2.19.90-15 +- Sync with upstream master. + +* Wed May 14 2014 Carlos O'Donell - 2.19.90-14 +- Add support for displaying all test results in build logs. + +* Wed May 14 2014 Carlos O'Donell - 2.19.90-13 +- Add initial support for ppc64le. + +* Tue Apr 29 2014 Siddhesh Poyarekar - 2.19.90-12 +- Auto-sync with upstream master. +- Remove ports addon. + +* Fri Apr 18 2014 Siddhesh Poyarekar - 2.19.90-11 +- Sync with upstream master. + +* Thu Apr 10 2014 Siddhesh Poyarekar - 2.19.90-10 +- Sync with upstream master. + +* Thu Apr 03 2014 Siddhesh Poyarekar - 2.19.90-9 +- Sync with upstream master. + +* Wed Mar 26 2014 Siddhesh Poyarekar - 2.19.90-8 +- Sync with upstream master. + +* Wed Mar 19 2014 Siddhesh Poyarekar - 2.19.90-7 +- Sync with upstream master. +- Fix offset computation for append+ mode on switching from read (#1078355). + +* Wed Mar 12 2014 Carlos O'Donell - 2.19.90-6 +- Sync with upstream master. +- Use cleaner upstream solution for -ftree-loop-distribute-patterns (#911307). + +* Tue Mar 04 2014 Siddhesh Poyarekar - 2.19.90-5 +- Sync with upstream master. + +* Thu Feb 27 2014 Siddhesh Poyarekar - 2.19.90-4 +- Use nscd service files from glibc sources. +- Make nscd service forking in systemd service file. + +* Tue Feb 25 2014 Siddhesh Poyarekar - 2.19.90-3 +- Sync with upstream master. +- Separate ftell from fseek logic and avoid modifying FILE data (#1069559). + +* Mon Feb 24 2014 Carlos O'Donell - 2.19.90-2 +- Fix build-locale-archive failure to open default template. + +* Tue Feb 18 2014 Siddhesh Poyarekar - 2.19.90-1 +- Sync with upstream master. + +* Tue Feb 04 2014 Siddhesh Poyarekar - 2.18.90-27 +- Sync with upstream master. + +* Wed Jan 29 2014 Siddhesh Poyarekar - 2.18.90-26 +- Modify regular expressions to include powerpcle stubs-*.h (#1058258). + +* Wed Jan 29 2014 Siddhesh Poyarekar - 2.18.90-25 +- Sync with upstream master. + +* Sat Jan 25 2014 Ville Skyttä - 2.18.90-24 +- Own the %%{_prefix}/lib/locale dir. + +* Thu Jan 23 2014 Siddhesh Poyarekar - 2.18.90-23 +- Sync with upstream master. + +* Thu Jan 16 2014 Siddhesh Poyarekar - 2.18.90-22 +- Back out ftell test case (#1052846). + +* Tue Jan 14 2014 Siddhesh Poyarekar - 2.18.90-21 +- Sync with upstream master. +- Fix infinite loop in ftell when writing wide char data (#1052846). + +* Tue Jan 7 2014 Siddhesh Poyarekar - 2.18.90-20 +- Sync with upstream master. +- Enable systemtap probes on Power and S/390. + +* Fri Dec 27 2013 Siddhesh Poyarekar - 2.18.90-19 +- Sync with upstream master. + +* Fri Dec 20 2013 Siddhesh Poyarekar - 2.18.90-18 +- Sync with upstream master. + +* Wed Dec 4 2013 Siddhesh Poyarekar - 2.18.90-17 +- Sync with upstream master. + - Fix shm_open validation (#1037787); + +* Thu Nov 28 2013 Siddhesh Poyarekar - 2.18.90-16 +- Sync with upstream master. + +* Wed Nov 20 2013 Siddhesh Poyarekar - 2.18.90-15 +- Sync with upstream master. + +* Fri Nov 8 2013 Carlos O'Donell - 2.18.90-14 +- Enhance NSCD's SELinux support to use dynamic permission names (#1025126). + +* Mon Oct 28 2013 Siddhesh Poyarekar - 2.18.90-13 +- Sync with upstream master. + - Skip over unimplemented timezone format specifier in strptime (#947722). + +* Mon Oct 21 2013 Siddhesh Poyarekar - 2.18.90-12 +- Allow fill_archive to be called with NULL fname. +- Sync with upstream master. + +* Tue Oct 15 2013 Siddhesh Poyarekar - 2.18.90-11 +- Sync with upstream master. + +* Thu Oct 3 2013 Carlos O'Donell - 2.18.90-10 +- Allow applications to use pthread_atfork without explicitly + requiring libpthread.so. (#1013801) +- Support `--list-archive FILE' in localedef utility. + +* Thu Oct 3 2013 Siddhesh Poyarekar - 2.18.90-9 +- Define swap_endianness_p in build-locale-archive. + +* Wed Oct 2 2013 Carlos O'Donell - 2.18.90-8 +- Allow ldconfig cached objects previously marked as hard or soft + ABI to now become unmarked without raising an error. This works + around a binutils bug that caused objects to become unmarked. + (#1009145) + +* Tue Oct 1 2013 Siddhesh Poyarekar - 2.18.90-7 +- Fix check for PI mutex on non-x86 systems (#1007590). +- Resync with upstream master. + +* Tue Sep 24 2013 Carlos O'Donell - 2.18.90-6 +- Avoid the use of __block which is a reserved keyword for clang++ + (#1009623). + +* Mon Sep 23 2013 Siddhesh Poyarekar - 2.18.90-5 +- Resync with upstream master. + +* Sun Sep 22 2013 Carlos O'Donell - 2.18.90-4 +- Fix CVE-2013-4788: Static applications now support pointer mangling. + Existing static applications must be recompiled (#985625). + +* Wed Sep 18 2013 Patsy Franklin - 2.18.90-3 +- Fix conditional requiring specific binutils for s390/s390x. + +* Mon Sep 16 2013 Siddhesh Poyarekar - 2.18.90-2 +- Resync with upstream master. +- Fix CVE-2013-4332 (#1008299). + +* Thu Sep 5 2013 Siddhesh Poyarekar - 2.18.90-1 +- Resync with upstream master. +- Drop patch for #800224. + +* Thu Aug 29 2013 Carlos O'Donell - 2.18-6 +- Fix Power build (#997531). + +* Wed Aug 28 2013 Carlos O'Donell - 2.18-5 +- Fix indirect function support to avoid calling optimized routines + for the wrong hardware (#985342). + +* Mon Aug 26 2013 Siddhesh Poyarekar - 2.18-4 +- Initialize res_hconf in nscd. (#1000924). + +* Tue Aug 20 2013 Siddhesh Poyarekar - 2.18-3 +- Remove non-ELF support in rtkaio. +- Avoid inlining of cleanup function for kaio_suspend. +- Expand sizes of some types in strcoll (#855399, CVE-2012-4424). +- Fix tst-aiod2 and tst-aiod3 test failures (#970865). + +* Mon Aug 19 2013 Siddhesh Poyarekar - 2.18-2 +- Fix buffer overflow in readdir_r (#995841, CVE-2013-4237). +- Remove releng tarball. + +* Fri Aug 16 2013 Siddhesh Poyarekar - 2.18-1 +- Upstream release 2.18. +- Pull in systemd during build and use the tmpfilesdir macro. + +* Wed Aug 14 2013 Carlos O'Donell - 2.17.90-14 +- Update spec file to use rpm prefix everywhere. + +* Tue Aug 13 2013 Carlos O'Donell - 2.17.90-13 +- Revert `Move to /usr' transition. + +* Tue Aug 13 2013 Carlos O'Donell - 2.17.90-12 +- Complete `Move to /usr' transition. All relevant files are now + installed into `/usr'. + +* Wed Aug 07 2013 Karsten Hopp 2.17.90-11 +- rebuild with the latest rpm to fix missing ld64.so provides on PPC + +* Mon Jul 29 2013 Carlos O'Donell - 2.17.90-10 +- Fix missing libbsd.a in debuginfo packages. + +* Mon Jul 29 2013 Siddhesh Poyarekar - 2.17.90-9 +- Fix strcoll flaws (#855399, CVE-2012-4412, CVE-2012-4424). + +* Mon Jul 29 2013 Siddhesh Poyarekar - 2.17.90-8 +- Resync with upstream master. +- Disable pt_chown (CVE-2013-2207). + +* Thu Jul 25 2013 Carlos O'Donell - 2.17.90-7 +- Correctly name the 240-bit slow path sytemtap probe slowpow_p10 for slowpow. + +* Wed Jul 24 2013 Carlos O'Donell - 2.17.90-6 +- Add build requirement on static libstdc++ library to fix testsuite failures + for static C++ tests. + +* Fri Jul 12 2013 Siddhesh Poyarekar - 2.17.90-5 +- Enable lock elision support (#982363). +- Depend on systemd instead of systemd-units (#983760). + +* Tue Jul 9 2013 Siddhesh Poyarekar - 2.17.90-4 +- Resync with upstream master. + +* Thu Jun 20 2013 Siddhesh Poyarekar - 2.17.90-3 +- Resync with upstream master. + +* Tue Jun 11 2013 Remi Collet - 2.17.90-2 +- rebuild for new GD 2.1.0 + +* Tue Jun 4 2013 Siddhesh Poyarekar - 2.17.90-1 +- Resync with upstream master. + +* Tue May 14 2013 Siddhesh Poyarekar - 2.17-9 +- Avoid crashing in LD_DEBUG when program name is unavailable (#961238). + +* Sun May 5 2013 Patsy Franklin - 2.17-8 +- Fix _nl_find_msg malloc failure case, and callers. (#959034). + +* Tue Apr 23 2013 Patsy Franklin - 2.17-7 +- Test init_fct for NULL, not result->__init_fct, after demangling (#952799). + +* Tue Apr 23 2013 Patsy Franklin - 2.17-6 +- Increase limits on xdr name and record requests (#892777). +- Consistently MANGLE/DEMANGLE init_fct, end_fct and btow_fct (#952799). + +* Thu Mar 28 2013 Siddhesh Poyarekar - 2.17-5 +- Don't add input group during initgroups_dyn in hesiod (#921760). + +* Sun Mar 17 2013 Carlos O'Donell - 2.17-4 +- Fixed i386 glibc builds (#917161). +- Fixed multibyte character processing crash in regexp (#905877, CVE-2013-0242) + +* Wed Feb 27 2013 Carlos O'Donell - 2.17-3 +- Renamed release engineering directory to `releng' (#903754). +- Fix building with gcc 4.8.0 (#911307). + +* Thu Feb 7 2013 Carlos O'Donell - 2.17-2 +- Fix ownership of /usr/lib[64]/audit (#894307). +- Support unmarked ARM objects in ld.so.cache and aux cache (#905184). + +* Tue Jan 1 2013 Jeff Law - 2.17-1 +- Resync with official glibc-2.17 release +* Fri Dec 21 2012 Jeff Law - 2.16.90-40 +- Resync with master + +* Wed Dec 19 2012 Jeff Law - 2.16.90-39 +- Add rtld-debugger-interface.txt as documentation. (#872242) + +* Fri Dec 7 2012 Jeff Law - 2.16.90-38 +- Resync with master +- Drop patch for 731228 that is no longer needed. + +* Thu Dec 6 2012 Jeff Law - 2.16.90-37 +- Resync with master +- Patch for 697421 has been submitted upstream. +- Drop local patch for 691912 that is no longer needed. + +* Mon Dec 3 2012 Jeff Law - 2.16.90-36 +- Resync with master +- Drop local patch for 657588 that is no longer needed. +- Drop local patch for 740682 that is no longer needed. +- Drop local patch for 770439 that is no longer needed. +- Drop local patch for 789209 that is no longer needed. +- Drop local patch for nss-files-overflow that seems + useless. +- Drop localedata-locales-fixes as they were rejected + upstream. +- Drop test-debug-gnuc-hack.patch that seems useless now. +- Repack patchlist. + +* Fri Nov 30 2012 Jeff Law - 2.16.90-35 +- Resync with master (#882137). +- Remove local patch for strict-aliasing warnings that + is no longer needed. +- Remove local patch for 730856 that is no longer needed. +- Repack patchlist. + +* Thu Nov 29 2012 Jeff Law - 2.16.90-34 +- Remove local patch which "temporarily" re-added currences + obsoleted by the Euro. +- Remove hunks from strict-aliasing patch that are no longer + needed. + +* Thu Nov 29 2012 Jeff Law - 2.16.90-33 +- Resync with master. +- Drop local patch for 788989. +- Repack patchlist. + +* Wed Nov 28 2012 Jeff Law - 2.16.90-32 +- Resync with master. +- Drop local patch for 878913. +- Drop local patch for 880666. +- Drop local patch for 767693. +- Repack patchlist. + +* Tue Nov 27 2012 Siddhesh Poyarekar - 2.16.90-31 +- Ensure that hashtable size is greater than 3 (#878913). +- fwrite returns 0 on EOF (#880666). + +* Mon Nov 26 2012 Jeff Law - 2.16.90-30 +- Resync with upstream sources +- Drop local patch for getconf. +- Repack patchlist. + +* Fri Nov 16 2012 Jeff Law - 2.16.90-29 +- Rsync with upstream sources +- Drop local patches for 803286, 791161, 790292, 790298 + +* Wed Nov 7 2012 Jeff Law - 2.16.90-28 +- Resync with upstream sources (#873397) + +* Mon Nov 5 2012 Jeff Law - 2.16.90-27 +- Resync with upstream sources. +- Don't use distinct patches for 770869, 787201 and 688948 + as they all modify stuff under fedora/ +- Repack patchlist + +* Thu Nov 1 2012 Jeff Law - 2.16.90-26 +- Resync with upstream sources (#872336) + +* Mon Oct 22 2012 Jeff Law - 2.16.90-25 +- Rsync with upstream sources +- Drop 864820 patch as now that it's upstream. +- Add sss to /etc/nsswitch.conf (#867473) + +* Thu Oct 11 2012 Jeff Law - 2.16.90-24 +- Rsync with upstream sources +- Drop local 552960-2 patch now that it's upstream. +- Drop local 858274 patch now that the root problem is fixed upstream. +- Repack patchlist. + +* Wed Oct 10 2012 Siddhesh Poyarekar - 2.16.90-23 +- Fix Marathi names for Wednesday, September and October (#rh864820). + +* Fri Oct 5 2012 Jeff Law - 2.16.90-22 +- Resync with upstream sources +- Drop local 552960 patch now that it's upstream +- Drop local stap patch now obsolete +- Drop local s390 patch which avoided problems with old assemblers +- Drop old fortify source patch to deal with old compilers + +* Thu Oct 4 2012 Siddhesh Poyarekar - 2.16.90-21 +- Take mutex in cleanup only if it is not already taken. + +* Tue Oct 2 2012 Jeff Law - 2.16.90-20 +- Resync with upstream sources. +- Repack patchlist. + +* Mon Oct 1 2012 Jeff Law - 2.16.90-19 +- Resync with upstream sources to pick up fma fixes + +* Fri Sep 28 2012 Jeff Law - 2.16.90-18 +- Resync with upstream sources. +- Drop fedora-cdefs-gnuc.patch, it's not needed anymore. +- Drop fedora-gai-rfc1918.patch, it's upstream now. +- Drop fedora-localedata-no_NO.patch, it was supposed to be + temporary -- that was back in 2003. This should have been + sorted out long ago. We'll just have to deal with the + fallout. +- Drop fedora-vfprintf-sw6530.patch, it's upstream now. +- Drop rh769421.patch; Siddhesh has fixed this properly with 552960. + +* Fri Sep 28 2012 Siddhesh Poyarekar - 2.16.90-17 +- Release mutex before going back to wait for PI mutexes (#552960). + +* Tue Sep 25 2012 Jeff Law - 2.16.90-16 +- Resync with upstream sources. + +* Fri Sep 21 2012 Jeff Law - 2.16.90-15 +- Remove most of fedora-nscd patch as we no longer use the + old init files, but systemd instead. +- Remove path-to-vi patch. With the usr-move changes that + patch is totally unnecessary. +- Remove i686-nopl patch. Gas was changed back in 2011 to + avoid nopl. +- Move gai-rfc1918 patch to submitted upstream status + +* Fri Sep 21 2012 Jeff Law - 2.16.90-14 +- Revert patch for 816647, it's blatently broken. + +* Fri Sep 21 2012 Siddhesh Poyarekar - 2.16.90-13 +- Bring back byteswap-16.h (#859268). + +* Thu Sep 20 2012 Jeff Law - 2.16.90-12 +- Revert recent upstream strstr changes (#858274) +- Demangle function pointers before testing them (#816647) +- Remove handling of /etc/localtime and /var/spool/postfix/etc/localtime + as systemd will be handling them from now on (#858735). + +* Fri Sep 14 2012 Jeff Law - 2.16.90-11 +- Resync with upstream sources (#857236). + +* Sat Sep 8 2012 Peter Robinson - 2.16.90-10 +- Enable ports to fix FTBFS on ARM + +* Wed Sep 5 2012 Jeff Law - 2.16.90-9 +- Resync with upstream sources. + +* Tue Sep 4 2012 Jeff Law - 2.16.90-8 +- Incorporate ppc64p7 arch changes (#854250) + +* Thu Aug 30 2012 Jeff Law - 2.16.90-7 +- Resync with upstream sources. + +* Wed Aug 22 2012 Jeff Law - 2.16.90-6 +- Resync with upstream sources. + +* Tue Aug 21 2012 Jeff Law - 2.16.90-5 +- Replace manual systemd scriptlets with macroized scriptlets (#850129) + +* Mon Aug 20 2012 Jeff Law - 2.16.90-4 +- Move /etc/localtime into glibc-common package since glibc-common + owns the scriptlets which update it. + +* Mon Aug 20 2012 Jeff Law - 2.16.90-3 +- Remove obsolete patches from glibc-fedora.patch. Explode + remaining patches into distinct patchfiles. Thanks to + Dmitry V. Levin for identifying them! + Drop ia64 specific patches and specfile fragments + +* Wed Aug 15 2012 Jeff Law - 2.16.90-2 +- Fix integer overflow leading to buffer overflow in strto* (#847718) + +* Mon Aug 13 2012 Jeff Law - 2.16.90-1 +- Resync with upstream sources, drop obsolete patches. +- Drop glibc-ports bits as they're part of the master + sources now. + +* Mon Aug 13 2012 Jeff Law - 2.16-9 +- Replace patch for 179072 with official version from upstream. + +* Fri Aug 10 2012 Jeff Law - 2.16-8 +- Replace patch for 789238 with official version from upstream. + +* Wed Jul 25 2012 Jeff Law - 2.16-7 +- Pack IPv4 servers at the start of nsaddr_list and + only track the number of IPV4 servers in EXT(statp->nscounti (#808147) +- Mark set*uid, set*gid as __wur (warn unused result) (#845960) + +* Wed Jul 25 2012 Jeff Law - 2.16-6 +- Revert patch for BZ696143, it made it impossible to use IPV6 + addresses explicitly in getaddrinfo, which in turn broke + ssh, apache and other code. (#808147) +- Avoid another unbound alloca in vfprintf (#841318) +- Remove /etc/localtime.tzupdate in lua scriptlets +- Revert back to using posix.symlink as posix.link with a 3rd + argument isn't supported in the lua version embedded in rpm. +- Revert recent changes to res_send (804630, 835090). +- Fix memcpy args in res_send (#841787). + +* Thu Jul 19 2012 Fedora Release Engineering - 2.16-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Thu Jul 5 2012 Jeff Law - 2.16-2 +- Use posix.link rather than posix.symlink in scriptlet to + update /etc/localtime (#837344). + +* Mon Jul 2 2012 Jeff Law - 2.16-1 +- Resync with upstream glibc-2.16 release. + +* Fri Jun 22 2012 Jeff Law - 2.15.90-16 +- Resync with upstream sources, drop obsolete patch. + +* Thu Jun 21 2012 Jeff Law - 2.15.90-15 +- Resync with upstream sources (#834447). +- Fix use-after-free in dcigettext.c (#816647). + +* Fri Jun 15 2012 Jeff Law - 2.15.90-14 +- Resync with master. + +* Thu Jun 14 2012 Jeff Law - 2.15.90-13 +- Delay setting DECIDED field in locale file structure until + we have read the file's data (#827510). + +* Mon Jun 11 2012 Dennis Gilmore - 2.15.90-12 +- actually apply the arm linker hack + +* Mon Jun 11 2012 Dennis Gilmore - 2.15.90-11 +- only deal with the arm linker compat hack on armhfp arches +- armsfp arches do not have a linker change +- Backward compat hack for armhf binaries. + +* Thu Jun 7 2012 Jeff Law - 2.15.90-10 +- Fix parsing of /etc/sysconfig/clock when ZONE has spaces. (#828291) + +* Tue Jun 5 2012 Jeff Law - 2.15.90-9 +- Resync with upstream sources, drop unnecessary patches. +- Fix DoS in RPC implementation (#767693) +- Remove deprecated alpha support. +- Remove redundant hunk from patch. (#823905) + +* Fri Jun 1 2012 Patsy Franklin - 2.15.90-8 +- Fix iconv() segfault when the invalid multibyte character 0xffff is input + when converting from IBM930 (#823905) + +* Fri Jun 1 2012 Jeff Law - 2.15.90-7 +- Resync with upstream sources. (#827040) + +* Thu May 31 2012 Patsy Franklin - 2.15.90-6 +- Fix fnmatch() when '*' wildcard is applied on a file name containing + multibyte chars. (#819430) + +* Wed May 30 2012 Jeff Law - 2.15.90-5 +- Resync with upstream sources, drop unnecessary patches. + +* Tue May 29 2012 Jeff Law - 2.15.90-4 +- Build info files in the source dir, then move to objdir + to avoid multilib conflicts (#825061) + +* Fri May 25 2012 Jeff Law - 2.15.90-3 +- Work around RPM dropping the contents of /etc/localtime + when it turns into a symlink with %post common script (#825159). + +* Wed May 23 2012 Jeff Law - 2.15.90-2 +- Fix option rotate when one IPV6 server is enabled (#804630) +- Reenable slow/uberslow path taps slowpow/slowexp. + +* Wed May 23 2012 Jeff Law - 2.15.90-1 +- Resync with upstream sources, drop unnecessary patches. + +* Tue May 22 2012 Patsy Franklin - 2.15-41 +- Fix tzdata trigger (#822200) +- Make the symlink relative rather than linking into the buildroot (#822200). +- Changed /etc/localtime to a symlink. 8222000 (#822200) + +* Tue May 15 2012 Jeff Law - 2.15-40 +- Update to upstream patch for 806070 (#806070) + +* Mon May 14 2012 Jeff Law - 2.15-39 +- Update upstream patch for AVX testing (#801650) + +* Fri May 11 2012 Jeff Law - 2.15-38 +- Upstream patch to fix AVX testing (#801650) + +* Thu May 10 2012 Jeff Law - 2.15-37 +- Try again to fix AVX testing (#801650) + +* Mon May 7 2012 Jeff Law - 2.15-36 +- Improve fortification disabled warning. +- Change location of dynamic linker for armhf. + +* Mon Apr 30 2012 Jeff Law - 2.15-35 +- Implement context routines for ARM (#817276) + +* Fri Apr 13 2012 Jeff Law - 2.15-34 +- Issue a warning if FORTIFY_CHECKING is requested, but disabled. + +* Thu Apr 12 2012 Jeff Law - 2.15-33 +- Fix another unbound alloca in nscd groups (#788989) + +* Tue Apr 3 2012 Jeff Law - 2.15-32 +- Fix first day of week for lv_LV (#682500) + +* Mon Apr 2 2012 Jeff Law - 2.15-31 +- When retrying after main arena failure, always retry in a + different arena. (#789238) + +* Tue Mar 27 2012 Jeff Law - 2.15-30 +- Avoid unbound alloca usage in *-crypt routines (#804792) +- Fix data race in nscd (#806070) + +* Fri Mar 23 2012 Jeff Law - 2.15-29 +- Fix typo in __nss_getent (#806403). + +* Wed Mar 14 2012 Jeff Law - 2.15-28 +- Add doi_IN, sat_IN and mni_IN to SUPPORTED locals (#803286) +- Add stap probes in slowpow and slowexp. + +* Fri Mar 09 2012 Jeff Law - 2.15-27 +- Fix AVX checks (#801650) + +* Wed Feb 29 2012 Jeff Law - 2.15-26 +- Set errno properly in vfprintf (#794797) +- Don't kill application when LD_PROFILE is set. (#800224) + +* Wed Feb 29 2012 Jeff Law - 2.15-25 +- Fix out of bounds memory access in resolver (#798471) +- Always mark vDSO as used (#758888) + +* Fri Feb 24 2012 Jeff Law - 2.15-24 +- Fix bogus underflow (#760935) +- Correctly handle dns request where large numbers of A and AAA records + are returned (#795498) +- Fix nscd crash when group has many members (#788989) + +* Mon Feb 20 2012 Jeff Law - 2.15-23 +- Avoid "nargs" integer overflow which could be used to bypass FORTIFY_SOURCE (#794797) + +* Mon Feb 20 2012 Jeff Law - 2.15-22 +- Fix main arena locking in malloc/calloc retry path (#789238) + +* Fri Feb 17 2012 Jeff Law - 2.15-21 +- Correctly identify all 127.x.y.z addresses (#739743) +- Don't assign native result if result has no associated interface (#739743) + +* Fri Feb 17 2012 Jeff Law - 2.15-20 +- Ignore link-local IPV6 addresses for AI_ADDRCONFIG (#697149) + +* Fri Feb 17 2012 Jeff Law - 2.15-19 +- Fix reply buffer mismanagement in resolver (#730856) + +* Thu Feb 16 2012 Jeff Law - 2.15-18 +- Revert 552960/769421 changes again, still causing problems. +- Add doi_IN (#791161) +- Add sat_IN (#790292) +- Add mni_IN (#790298) + +* Thu Feb 9 2012 Jeff Law - 2.15-17 +- Fix lost wakeups in pthread_cond_*. (#552960, #769421) +- Clarify info page for snprintf (#564528) +- Fix first_weekday and first_workday for ru_UA (#624296) + +* Tue Feb 7 2012 Jeff Law - 2.15-16 +- Fix currency_symbol for uk_UA (#789209) +- Fix weekday names in Kashmiri locale (#770439) + +* Tue Feb 7 2012 Jeff Law - 2.15-15 +- Remove change for 787662, correct fix is in gcc. + +* Mon Feb 6 2012 Jeff Law - 2.15-13 +- More accurately detect if we're in a chroot (#688948) + +* Fri Feb 3 2012 Jeff Law - 2.15-12 +- Add fedfs to /etc/rpc (#691912) +- Run nscd in the foreground w/ syslogging, fix systemd config (#770869) +- Avoid mapping past end of shared object (#741105) +- Turn off -mno-minimal-toc on PPC (#787201) +- Remove hunk from glibc-rh657588.patch that didn't belong + +* Wed Feb 1 2012 Jeff Law - 2.15-8 +- Prevent erroneous inline optimization of initfini.s on PowerPC64 (#783979) +- Use upstream variant of fix for 740506. +- Fix month abbreviations for zh_CN (#657588) + +* Sun Jan 29 2012 Jeff Law - 2.15-7 +- Sort objects before relocations (sw#13618) +- Fix bogus sort code that was copied from dl-deps.c. + +* Thu Jan 26 2012 Jeff Law - 2.15-6 +- First argument to settimeofday can be null (#740682) +- Add aliases for ISO-10646-UCS-2 (#697421) + +* Tue Jan 24 2012 Jeff Law - 2.15-4 +- Update ports from master. +- Fix first workday/weekday for it_IT (#622499) +- Fix type to uint16_t based on upstream comments (729661) +- Do not cache negative results in nscd if these are transient (#784402) + +* Mon Jan 23 2012 Jeff Law - 2.15-3 +- Fix cycle detection (#729661) +- Fix first workday/weekday for it_IT (#446078) +- Fix first workday/weekday for ca_ES (#454629) + +* Fri Jan 13 2012 Fedora Release Engineering - 2.15-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Sun Jan 1 2012 Jeff Law - 2.15-1.fc17 +- Update from master (a316c1f) + +* Thu Dec 22 2011 Jeff Law - 2.14.90-26.fc17 +- Update from master (16c6f99) +- Fix typo in recent tzfile change (#769476) +- Make MALLOC_ARENA_MAX and MALLOC_ARENA_TEST match documentation (#740506) +- Revert "fix" to pthread_cond_wait (#769421) +- Extract patch for 730856 from fedora-patch into a distinct patchfile + +* Mon Dec 19 2011 Jeff Law - 2.14.90-25.fc17 +- Update from master (a4647e7). + +* Sun Dec 18 2011 Jeff Law - 2.14.90-24.fc16.3 +- Check values from TZ file header (#767696) +- Handle EAGAIN from FUTEX_WAIT_REQUEUE_PI (#552960) +- Add {dist}.# +- Correct return value from pthread_create when stack alloction fails. + (#767746) + +* Wed Dec 7 2011 Jeff Law - 2.14.90-23 +- Fix a wrong constant in powerpc hypot implementation (#750811) + #13534 in python bug database + #13472 in glibc bug database +- Truncate time values in Linux futimes when falling back to utime + +* Mon Dec 5 2011 Jeff Law - 2.14.90-22 +- Mark fortified __FD_ELT as extension (#761021) +- Fix typo in manual (#708455) + +* Wed Nov 30 2011 Jeff Law - 2.14.90-21 +- Don't fail in makedb if SELinux is disabled (#750858) +- Fix access after end of search string in regex matcher (#757887) + +* Mon Nov 28 2011 Jeff Law - 2.14.90-20 +- Drop lock before calling malloc_printerr (#757881) + +* Fri Nov 18 2011 Jeff Law - 2.14.90-19 +- Check malloc arena atomically (BZ#13071) +- Don't call reused_arena when _int_new_arena failed (#753601) + +* Wed Nov 16 2011 Jeff Law - 2.14.90-18 +- Fix grouping and reuse other locales in various locales (BZ#13147) + +* Tue Nov 15 2011 Jeff Law - 2.14.90-17 +- Revert bogus commits/rebasing of Nov 14, Nov 11 and Nov 8. Sources + should be equivalent to Fedora 16's initial release. + +* Wed Oct 26 2011 Fedora Release Engineering - 2.14.90-15 +- Rebuilt for glibc bug#747377 + +* Wed Oct 19 2011 Jim Meyering - 2.14.90-14 +- Revert the upstream patch that added the leaf attribute, since it + caused gcc -O2 to move code past thread primitives and sometimes + even out of critical sections. See http://bugzilla.redhat.com/747377 + +* Wed Oct 19 2011 Andreas Schwab - 2.14.90-13 +- Update from master + - Fix linkage conflict with feraiseexcept (#746753) + - More libm optimisations + +* Mon Oct 17 2011 Andreas Schwab - 2.14.90-12 +- Update from master + - Correctly handle missing initgroups database (#745675) + - Optimize many libm functions + - Optimize access to isXYZ and toXYZ tables + - Optimized memcmp and wmemcmp for x86-64 and x86-32 + - Add parameter annotation to modf (BZ#13268) + - Support optimized isXXX functions in C++ code + - Check for zero size in memrchr for x86_64 (#745739) + - Optimized memchr, memrchr, rawmemchr for x86-32 + +* Tue Oct 11 2011 Andreas Schwab - 2.14.90-11 +- Update from master + - Clean up locarchive mmap reservation code + - Fix netname2host (BZ#13179) + - Fix remainder (NaN, 0) (BZ#6779, BZ#6783) + - S/390: Fix longlong.h inline asms for zarch + - Improve 64 bit memchr, memrchr, rawmemchr with SSE2 + - Update translations + - Implement caching of netgroups in nscd + - Handle OOM in NSS + - Don't call ifunc functions in trace mode +- Convert tzdata-update to lua (#729796) +- Horrible workaround for horribly broken software (#737223) + +* Wed Sep 28 2011 Andreas Schwab - 2.14.90-10 +- Update from master + - Correctly reparse group line after enlarging the buffer (#739360) + - Fix parse error in bits/mathinline.h with --std=c99 (#740235) +- Update nscd service file (#740284) +- Drop nscd init file (#740196) + +* Fri Sep 16 2011 Andreas Schwab - 2.14.90-9 +- Update from master + - Define IP_MULTICAST_ALL (BZ#13192) + - Add fmax and fmin inlines for x86-64 + - Avoid race between {,__de}allocate_stack and __reclaim_stacks + during fork (#737387) + - Optimized lrint and llrint for x86-64 + - Also relocate in dependency order when doing symbol dependency + testing (#737459) + - Optimize logb code for 64-bit machines + - Fix jn precision (BZ#11589) + - Fix boundary conditions in scanf (BZ#13138) + - Don't lock string streams in stream cleanup code (BZ#12847) + - Define ELFOSABI_GNU + - Fix lround loss of precision + - Add range checking for FD_SET, FD_CLR, and FD_ISSET +- Make sure AVC thread has capabilities + +* Thu Sep 8 2011 Andreas Schwab - 2.14.90-8 +- Update from master + - Use O_CLOEXEC when loading objects and cache in ld.so (BZ#13068) + - Fix memory leak in case of failed dlopen (BZ#13123) + - Optimizations for POWER + - Prefer real syscalls instead of vsyscalls on x86-64 outside libc.so + - Add Atom-optimized strchr and strrchr for x86-64 + - Try shell in posix_spawn* only in compat mode (BZ#13134) + - Fix glob.h header by removing gcc 1.x support (BZ#13150) + - Optimized strchr and strrchr with SSE2 on x86-32 + - Add optimized x86 wcscmp + - Fixes and optimizations for 32-bit sparc fabs + - Fix nptl semaphore cleanup invocation + - Sanitize HWCAP_SPARC_* defines/usage, and add new entries + +* Thu Sep 1 2011 Andreas Schwab - 2.14.90-7 +- Update from master + - Relocate objects in dependency order (#733462) +- Avoid assertion failure when first DNS answer was empty (#730856) +- Don't treat tls_offset == 1 as forced dynamic (#731228) + +* Wed Aug 24 2011 Andreas Schwab - 2.14.90-6 +- Update from master + - Correct cycle detection during dependency sorting + - Use ifuncs for time and gettimeofday on x86-64 + - Fix fopen (non-existing-file, "re") errno + - Fix CFI info in x86-64 trampolines for non-AVX code + - Build libresolv with SSP flags + - Avoid executable stack in makedb (#731063) + - Align x86 TCB to 64 bytes (cache line size), important for Atom + +* Mon Aug 15 2011 Andreas Schwab - 2.14.90-5 +- Update from master + - Implement LD_DEBUG=scopes + - Locale-independent parsing in libintl (#726536) + - Fix stack alignment on x86_64 (#728762) + - Implement scandirat function + +* Tue Aug 9 2011 Andreas Schwab - 2.14.90-4 +- Update from master + - Properly tokenize nameserver line for servers with IPv6 address + - Fix encoding name for IDN in getaddrinfo (#725755) + - Fix inline strncat/strncmp on x86 + - Define SEEK_DATA and SEEK_HOLE + - Define AF_NFC and PF_NFC + - Update ptrace constants + - Add read barriers in cancellation initialization + - Add read barrier protecting DES initialization + - Fix overflow bug in optimized strncat for x86-64 + - Check for overflows in expressions (BZ#12852) + - Fix check for AVX enablement (#720176, BZ#13007) + - Force La_x86_64_ymm to be 16-byte aligned + - Add const attr to gnu_dev_{major,minor,makedev} +- Filter out GLIBC_PRIVATE symbols again + +* Wed Jul 20 2011 Andreas Schwab - 2.14.90-3 +- Update from master + - S/390: Don't use r11 in INTERNAL_VSYSCALL_NCS macro + - Avoid warning in nscd config file parsing code + - Improve 64 bit strcat functions with SSE2/SSSE3 + - Fix alloca accounting in strxfrm + - Avoid possible crashes in anormal nscd exits + - Updated Swedish and Dutch translations + +* Thu Jul 14 2011 Andreas Schwab - 2.14.90-2 +- Update from master + - Generalize framework to register monitoring of files in nscd + - Handle ext4 in {,f}pathconf + - Handle Lustre filesystem (BZ#12868) + - Handle W; without long options in getopt (BZ#12922) + - Change error code for underflows in strtod (BZ#9696) + - Fix handling of chained netgroups + - Optimize long-word additions in SHA implementation + - Handle nscd negtimeout==0 + - nss_compat: query NIS domain only when needed + - Fix robust mutex handling after fork + - Make sure RES_USE_INET6 is always restored +- Add systemd configuration for nscd +- Be more careful running build-locale-archive + +* Thu Jun 30 2011 Andreas Schwab - 2.14.90-1 +- Update from master + - Fix quoting in some installed shell scripts (BZ#12935) + - Fix missing .ctors/.dtors lead word in soinit + - Improved st{r,p}{,n}cpy for SSE2 and SSSE3 on x86 + - Avoid __check_pf calls in getaddrinfo unless really needed + (BZ#12907) + - Rate limit expensive _SC_NPROCESSORS_ONLN computation + - Add initgroups lookup support to getent + - Reenable nss_db with a completely new implementation + - Rewrite makedb to avoid using db library + - Add pldd program +- Obsolete nss_db +- Don't build tzdata-update and build-locale-archive statically + +* Tue Jun 28 2011 Andreas Schwab - 2.14-4 +- Update from 2.14 branch + - Fix crash in GB18030 encoder (#712901) +- Fix more bugs in GB18030 charmap +- Don't use gethostbyaddr to determine canonical name + +* Tue Jun 21 2011 Andreas Schwab - 2.14-3 +- Update from 2.14 branch + - Fix typo in recent resolver change which causes segvs (#710279) + - Fix memory leak in getaddrinfo (#712178) + - Fix for C++ (BZ#12841) + - Assume Intel Core i3/i5/i7 processor if AVX is available +- Filter results from gethostbyname4_r according to request flags + (#711827) +- Repair GB18030 charmap (#712901) +- Revert "Use .machine to prevent AS from complaining about z9-109 + instructions in iconv modules" (#711330) + +* Fri Jun 3 2011 Andreas Schwab - 2.14-2 +- Revert "Handle DNS server failures in case of AF_UNSPEC lookups + correctly" (#710279) + +* Tue May 31 2011 Andreas Schwab - 2.14-1 +- Update to 2.14 release + - Handle DNS server failures in case of AF_UNSPEC lookups correctly + (BZ#12684) + - Prevent loader from loading itself + - Restore _res correctly (BZ#12350) + - Interpret numeric values in shadow file as signed (BZ#11099) + - Recognize use-vc option in resolv.conf (BZ#11558) + - Mark malloc hook variables as deprecated + - Declare malloc hook variables as volatile (BZ#11781) + - Don't document si_code used for raise (BZ#11799) + - Fix unnecessary overallocation due to incomplete character (BZ#12811) + - Handle failure of _nl_explode_name in all cases + - Add support for time syscall in vDSO (BZ#12813) + - Add sendmmsg and setns syscalls + - Use getcpu definition from vDSO on x86-64 (BZ#12813) +- Don't free non-malloced memory and fix memory leak (#709267) + +* Fri May 27 2011 Andreas Schwab - 2.13.90-14 +- Update from master + - Fix conversion to ISO-2022-JP-2 with ISO-8859-7 designation + (BZ#12814) + - Undo accidental change in x86-64 user.h + - Update Japanese translation + - Define RLIMIT_RTTIME (BZ#12795) + - Update longlong.h from GCC + - Add a few more alloca size checks (BZ#12671) + - Fix flags parameter value passed to pltenter and pltexit + - Define CLOCK_REALTIME_ALARM and CLOCK_BOOTTIME_ALARM + - Always fill output buffer in XPG strerror function (BZ#12782) + - Nicer output for negative error numbers in strerror_r + - Fix CP1258 conversion (BZ#12777) + - Fix handling of LC_CTYPE in locale name handling (BZ#12788) + - Set stream errors in more cases (BZ#12792) + - Don't unconditionally use alloca in gaih_inet (BZ#11869) + - Update documentation in regex.h (BZ#11857) + - Prevent Altivec and VSX insns on PowerPC64 when no FPRs or VRs are + available + - Fix typo in x86-64 powl (BZ#12775) +- Avoid overriding CFLAGS (#703880) + +* Wed May 18 2011 Andreas Schwab - 2.13.90-13 +- Update from master + - Update GB18030 to 2005 version (BZ#11837) + - Update RE_SYNTAX*_AWK constants in regex.h + - Handle long variable names in putenv (BZ#11892) + - Fix test for error_one_per_line mode in error (BZ#12766) + - Cleanup x86-64 sys/user.h (BZ#11820) + - Several locale data updates (BZ#11987, BZ#9732, BZ#9730, BZ#4357, + BZ#12582) + - Avoid potential deadlock in mtrace (BZ#6420) + - Fix a few problems in fopen and freopen + - Provide more helpful error message in getopt (BZ#7101) + - Make stack canary value harder to read through read overflow (BZ#10149) + - Use mmap for allocation of buffers used for __abort_msg (BZ#11901) + - Fix handling of static TLS in dlopen'ed objects (BZ#12453) + - Fix initialization of optimization values for AIO (BZ#12083) + - Fix handling of conversion problem in CP932 module (BZ#12601) + - Fix potential problem with out-of-scope buffer (BZ#12626) + - Handle recursive calls in backtrace better (BZ#12432) + - Fix handling of incomplete character storage in state + - Fix file descriptor position after fclose (BZ#12724) +- Reinstall NIS RPC headers + +* Fri May 13 2011 Andreas Schwab - 2.13.90-12 +- Update from master + - Fix resizing table for unique symbols when adding symbol for copy + relocation (BZ#12511) + - Fix sched_setscheduler call in spawn implementation (BZ#12052) + - Report write error in addmnt even for cached streams (BZ#12625) + - Translate kernel error into what pthread_create should return + (BZ#386) + - More configurability for secondary group lookup (BZ#11257) + - Several locale data updates (BZ#11258, BZ#11487, BZ#11532, + BZ#11578, BZ#11653, BZ#11668, BZ#11945, BZ#11947, BZ#12158, + BZ#12200, BZ#12178, BZ#12178, BZ#12346, BZ#12449, BZ#12545, + BZ#12551, BZ#12611, BZ#12660, BZ#12681, BZ#12541, BZ#12711, + BZ#12738) + - Fix Linux getcwd for long paths (BZ#12713) + - static tls memory leak on TLS_DTV_AT_TP archs + - Actually undefine ARG_MAX from + - Backport BIND code to query name as TLD (BZ#12734) + - Allow $ORIGIN to reference trusted directoreis in SUID binaries + (BZ #12393) + - Add missing {__BEGIN,__END}_DECLS to sys/sysmacros.h + - Report if no record is found by initgroups in nss_files +- Never leave $ORIGIN unexpanded +- Revert "Ignore origin of privileged program" +- Reexport RPC interface + +* Thu May 5 2011 Andreas Schwab - 2.13.90-11 +- Update from master + - Don't use removed rpc headers +- Install rpc/netdb.h again + +* Wed May 4 2011 Andreas Schwab - 2.13.90-10 +- Update from master + - ldconfig: don't crash on empty path in config file (#699784) + - getaddrinfo(AF_INET6) does not return scope_id info provided by + NSS modules (BZ#12714) + - Fix pathconf(_PC_BUF_SIZE) (BZ#12723) + - Fix getnameinfo flags parameter type (BZ#12717) + - Add finer grained control for initgroups lookups to NSS + - Use all possible bytes from fopen mode string (BZ#12685, #698025) + - Define initgroups callback for nss_files + - elf.h: Define R_ARM_IRELATIVE reloc type + - Fix static linking with checking x86/x86-64 memcpy (BZ#12653) + - Fix POWER4/POWER7 optimized strncmp to not read past differing bytes + - Fix FPU context handling in getcontext on x86-64 (BZ#12420) + - Skip extra zeroes when searching auxv on s390 + - Obsolete RPC implementation in libc + - Fix memory leak in TLS of loaded objects (BZ#12650) + - Don't leave empty element in rpath when skipping an element + - Make ppc sync_file_range cancelable + - Maintain stack alignment in ____longjmp_chk on x86_64 + +* Thu Apr 7 2011 Andreas Schwab - 2.13.90-9 +- Update from master + - Fix typo in cache information table for x86-{32,64} + - Define CLOCK_BOOTTIME, O_PATH, AT_EMPTY_PATH + - Work around old buggy program which cannot cope with memcpy + semantics (BZ#12518) + - Fix visibility of declarations of wcpcpy and wcpncpy (BZ#12631) + - Add clock_adjtime, name_to_handle_at, open_by_handle_at, syncfs + syscalls + - Really implement fallocate{,64} and sync_file_range as + cancellation points +- Enable systemtap support (#690281) + +* Thu Mar 24 2011 Andreas Schwab - 2.13.90-8 +- Update from master + - Fix infinite loop (#690323) + +* Mon Mar 21 2011 Andreas Schwab - 2.13.90-7 +- Update from master + - Handle page boundaries in x86 SSE4.2 strncmp (BZ#12597) + - Implement x86 cpuid handling of leaf4 for cache information (BZ#12587) + - Check size of pattern in wide character representation in fnmatch + (BZ #12583) + - Remove __restrict quals from wmemcmp prototype + - Fix copy relocations handling of unique objects (BZ#12510) +- ldd: never run file directly +- Ignore rpath elements containing non-isolated use of $ORIGIN when + privileged +- Don't leave empty element in rpath when skipping the first element +- Revert "Don't crash when dependencies are missing" (#688990) + +* Mon Mar 7 2011 Andreas Schwab - 2.13.90-6 +- Update from master + - Fix loading first object along a path when tracing + - Enable SSE2 memset for AMD'supcoming Orochi processor + - Don't read past end of buffer in fmemopen +- Revert broken changes (#682307) + +* Wed Mar 2 2011 Andreas Schwab - 2.13.90-5 +- Update from master + - Fix memory leak in dlopen with RTLD_NOLOAD (BZ#12509) + - Don't crash when dependencies are missing (BZ#12454) + - Fix allocation when handling positional parameters in printf + (BZ#12445) + - Fix two printf handler issues +- Fix false assertion (BZ#12454, #673014) + +* Mon Feb 14 2011 Andreas Schwab - 2.13.90-4 +- Update from master + - Update sysdeps/unix/sysv/linux/sparc/bits/socket.h + - Synchronize generic bits/sched.h cpu_set_t with Linux implementation + - Schedule nscd cache pruning more accurately from re-added values + - Fix passing symbol value to pltexit callbacks when ld.so auditing + - Fix range error handling in sgetspent +- Revert "Fix ordering of DSO constructors and destructors" (#673014) +- Create debuginfo-common on biarch archs +- Reinstall assembler workaround. +- Replace setuid by file capabilities (#646469) + +* Tue Jan 25 2011 Andreas Schwab - 2.13.90-1 +- Update from master + - Fix ordering of DSO constructors and destructors (BZ#11724) +- Remove no longer needed assembler workaround + +* Tue Jan 18 2011 Andreas Schwab - 2.13-1 +- Update to 2.13 release + - Define AT_NO_AUTOMOUNT + - Define MADV_HUGEPAGE and MADV_NOHUGEPAGE + - Add definitions for new socket protocols + - Signal temporary host lookup errors in nscd as such to the + requester (BZ#6812) + - Change setgroups to affect all the threads in the process + (BZ#10563) + - FIx handling of unterminated [ expression in fnmatch (BZ#12378) + - Relax requirement on close in child created by posix_spawn + - Fix handling of missing syscall in Linux mkdirat (BZ#12397) + - Handle long lines in host lookups in the right place (BZ#10484) + - Fix assertion when handling DSTs during auditing + - Fix alignment in x86 destructor calls + - Fix grouping when rounding increases number of integer digits + (BZ#12394) + - Update Japanese translations + - Fix infloop on persistent failing calloc in regex (BZ#12348) + - Use prlimit64 for 32-bit [gs]etrlimit64 implementation (BZ#12201) + - Change XPG-compliant strerror_r function to return error code + (BZ#12204) + - Always allow overwriting printf modifiers etc. + - Make PowerPC64 default to nonexecutable stack + +* Tue Dec 14 2010 Andreas Schwab - 2.12.90-21 +- Revert bogus change + +* Mon Dec 13 2010 Andreas Schwab - 2.12.90-20 +- Update from master + - Declare wcpcpy and wcpncpy only under _GNU_SOURCE + - Fix use of restrict in wchar.h and string.h + - Fix race in qsort_r initialization (BZ#11655) + - Don't ignore zero TTL in DNS answers + - Allow aux_cache_file open()ing to fail silently even in the chroot + mode (BZ#11149) + - Fix multiple nss_compat initgroups() bugs (BZ#10085) + - Define MAP_HUGETLB and SWAP_FLAG_DISCARD +- Remove .UTF-8 suffix from locale names when it is the only supported + codeset (#657556) +- Don't ignore $ORIGIN in libraries + +* Fri Nov 12 2010 Andreas Schwab - 2.12.90-19 +- Update from master + - Fix memory leak in fnmatch + - Support Intel processor model 6 and model 0x2c + - Fix comparison in sqrtl for IBM long double + - Fix one exit path in x86-64 SSE4.2 str{,n}casecmp (BZ#12205, #651638) + - Fix warnings in __bswap_16 (BZ#12194) + - Use IFUNC on x86-64 memset + - Power7-optimized mempcpy + - Handle uneven cache size in 32bit SSE2 memset (BZ#12191) + - Verify in ttyname that the symlink is valid (BZ#12167) + - Update Danish translations + - Fix concurrency problem between dl_open and dl_iterate_phdr + - Fix x86-64 strchr propagation of search byte into all bytes of SSE + register (BZ#12159) + - Fix perturbing in malloc on free (BZ#12140) + - PPC/A2 optimized memcpy function + - Add C99 FP_FAST_FMA{,F,L} macros to +- Check that the running kernel is new enough (#649589) + +* Fri Oct 22 2010 Andreas Schwab - 2.12.90-18 +- Require suid bit on audit objects in privileged programs (CVE-2010-3856) + +* Tue Oct 19 2010 Andreas Schwab - 2.12.90-17 +- Update from master + - Fix some fma issues, implement fmal (BZ#3268, #43358) + - Expect PLT call to _Unwind_Find_FDE on s390*-linux +- Never expand $ORIGIN in privileged programs (#643306, CVE-2010-3847) + +* Thu Oct 14 2010 Andreas Schwab - 2.12.90-16 +- Update from master + - Implement accurate fma (BZ#3268, #43358) + - Fix alignment of AVX save area on x86-64 (BZ#12113) + - Fix regex memory leaks (BZ#12078) + - Improve output of psiginfo (BZ#12107, BZ#12108) + - Don't return NULL address in getifaddrs (BZ#12093) + - Fix strstr and memmem algorithm (BZ#12092, #641124) +- Don't discard result of decoding ACE if AI_CANONIDN (#636642) +- Remove /etc/gai.conf from glibc-common and mark it %%ghost in glibc +- Require exact glibc version in nscd + +* Mon Oct 4 2010 Andreas Schwab - 2.12.90-15 +- Update from master + - Handle large requests in debugging hooks for malloc (BZ#12005) + - Fix handling of remaining bytes in buffer for strncmp and + strncasecmp (BZ#12077) + - Handle cgroup and btrfs filesystems in statvfs + - S/390: Fix highgprs check in startup code (BZ#12067) + - Properly convert f_fsid in statvfs (BZ#11611) + +* Tue Sep 28 2010 Andreas Schwab - 2.12.90-14 +- Don't try to write to _rtld_global_ro after performing relro + protection (#638091) + +* Mon Sep 27 2010 Andreas Schwab - 2.12.90-13 +- Update from master + - Add two forgotten licence exceptions + - getdents64 fallback d_type support + - Move freeres function from ld.so to libc.so + - Undo feature selection for ftruncate (BZ#12037) + - Fix namespace pollution in pthread_cleanup_push + - Fix limit detection in x86-64 SSE2 strncasecmp (#632560) + - Add support for fanotify_mark on sparc32 and s390 + - Fix register conflict in s390 ____longjmp_chk (#629970) + - Don't try to free rpath strings allocated during startup (#629976) + - Actually make it possible to user the default name server +- Fix memory leak on init/fini dependency list (#632936) +- Fix handling of collating symbols in regexps (BZ#11561) +- Don't parse %%s format argument as multibyte string (BZ#6530) +- Fix overflow in nss files parser +- Fix spurious nop at start of __strspn_ia32 + +* Wed Sep 15 2010 Dennis Gilmore - 2.12.90-12 +- dont build sparcv9v and sparc64v anymore + +* Mon Sep 13 2010 Andreas Schwab - 2.12.90-11 +- Update from master + - Fix _FORITY_SOURCE version of longjmp for Linux/x86-64 (BZ#11968) +- Work around shortest-stem feature in make 3.82+ + +* Mon Sep 6 2010 Andreas Schwab - 2.12.90-10 +- Update from master + - Remove invalid iconv aliases (BZ#11979) + - Update x86-64 mpn routines from GMP 5.0.1 + - Fix array overflow in floating point parser (BZ#7066) + - Support fanotify_mark syscall on powerpc32 + - Unroll x86-64 strlen + - Unroll 32bit SSE strlen and handle slow bsf + - Missing server address again leads to localhost being used (BZ#10851) +- Revert last change +- Remove or don't install unpackaged files for auxarches + +* Sat Sep 04 2010 Dennis Gilmore - 2.12.90-9 +- disable unpackaged file check on auxarches + +* Mon Aug 23 2010 Andreas Schwab - 2.12.90-8 +- Update from master + - Fix static strspn on x86 (#624852) + - Various POWER7 optimized string functions + - Fix x86 pthread_cond_signal() FUTEX_WAKE_OP fallback + - Add optimized strncasecmp versions for x86-64 + - PowerPC64 ABI fixes + - Properly quote output of locale (BZ#11904) + - f_flags in statfs implementation + - Add support for fanotify_init and fanotify_mask syscalls + - Add support for prlimit and prlimit64 + - Fix IPTOS_CLASS definition (BZ#11903) + - Avoid too much stack use in fnmatch (BZ#11883) + - x86: Add support for frame pointer less mcount +- Disable asynchronous-unwind-tables during configure run + +* Mon Aug 2 2010 Andreas Schwab - 2.12.90-7 +- Update from master + - Add optimized x86-64 implementation of strnlen and strcaecmp + - Document M_PERTURB + - Fix vDSO synthetic hwcap handling so they are not masked out from + ld.so.cache matching + - POWER6/7 optimizations for copysign +- Build with ports addon on alpha and armv5tel +- Add conflict with kernel < 2.6.32 (#619538) +- Switch to xz compressed tar files +- build-locale-archive: process only directories matching *_* + +* Wed Jul 21 2010 Andreas Schwab - 2.12.90-6 +- Bump minimum kernel version to 2.6.32 + +* Mon Jul 12 2010 Andreas Schwab - 2.12.90-5 +- Update from master + - Don't pass NULL occation to dl_signal_cerror + - Implement _PC_PIPE_BUF. +- Add glibc-ports tarball + +* Fri Jul 2 2010 Andreas Schwab - 2.12.90-4 +- Update from master + - Work around kernel rejecting valid absolute timestamps + - Improve 64bit memcpy/memmove for Atom, Core 2 and Core i7 + - Fix error handling in Linux getlogin* +- Workaround assembler bug sneaking in nopl (#579838) +- Fix scope handling during dl_close +- Fix setxid race handling exiting threads + +* Tue Jun 15 2010 Andreas Schwab - 2.12.90-3 +- Update from master + - Power7 string compare optimizations + - Properly resize buffer in NIS initgroups + - Define F_SETPIPE_SZ and F_GETPIPE_SZ + - Fix more C++ incompatibility problems in headers +- Properly set __libc_multiple_libcs +- Don't assume AT_PAGESIZE is always available (#597578) +- Don't call uname or getrlimit in libpthread init function (#579086) +- Mark /etc/rpc as %%config (#587050) + +* Mon May 31 2010 Andreas Schwab - 2.12.90-2 +- Update from master + - Small fix to POWER7 32-bit memcpy + - Correct x86 CPU family and model check (BZ#11640, #596554) + - Fix iov size in SH register_dump + - Don't crash on unresolved weak symbol reference + - Implement recvmmsg also as socketcall + - sunrpc: Fix spurious fall-through + - Make compatible with C++ (#593762) +- Fix users and groups creation in nscd %%post script + +* Wed May 19 2010 Andreas Schwab - 2.12.90-1 +- Update from master + - POWER7 optimized memset + - Fix typo in es_CR locale + - Enable IDN support in getent + - Fix race in free sanity check + - Fix lookup of collation sequence value during regexp matching + - Fix name of tt_RU.UTF-8@iqtelif locale (#589138) + - Handle too-small buffers in Linux getlogin_r (BZ#11571, #589946) + +* Tue May 4 2010 Roland McGrath - 2.12-1 +- Update to 2.12 release. + - Fix ldconfig chroot handling. + - Don't deadlock in __dl_iterate_phdr while (un)loading objects. + - Fix handling of newline in addmntent. + - Fix AIO when thread creation failed. + +* Fri Apr 16 2010 Andreas Schwab - 2.11.90-20 +- Update from master + - Fix bugs in x86-32 strcmp-sse4.S and strcmp-ssse3.S + - Add x86-32 FMA support + - Don't crash in trace mode when dependencies are missing + - x86-64 SSE4 optimized memcmp + - Fix makecontext on s390/s390x + +* Tue Apr 13 2010 Andreas Schwab - 2.11.90-19 +- Avoid multiarch memcmp in tzdata-update (#581677) + +* Mon Apr 12 2010 Andreas Schwab - 2.11.90-18 +- Update from master + - Implement interfaces to set and get names of threads (BZ#11390) + - Locale data updates (BZ#10824, BZ#10936, BZ#11470, BZ#11471) + - Print reload count in nscd statistics (BZ#10915) + - Fix reading loginuid file in getlogin{,_r} + - Fix fallocate error return on i386 + - Fix cproj implmentation (BZ#10401) + - Fix getopt handing (BZ#11039, BZ#11040, BZ#11041) + - Implement new mode for NIS passwd.adjunct.byname table (BZ#11134) + - Obey LD_HWCAP_MASK in ld.so.cache lookups + +* Tue Apr 6 2010 Andreas Schwab - 2.11.90-17 +- Update from master + - Locale data updates (BZ#11007, BZ#11258, BZ#11272, BZ#10554) + - Handle DNS timeouts in old-style lookup code (BZ#11010) + - Fix aux cache handling in ldconfig with chroot (BZ#11149) + - Fix printing error messages in getopt (BZ#11043) + - Declare iruserok and iruserok_af (BZ#11070) + - Fix option aliasing in argp (BZ#11254) + - Handle POSIX-compliant errno value of unlink in remove (BZ#11276) + - Fix definition and testing of S_ISSOCK (BZ#11279) + - Fix retrieving of kernel header version (BZ#11287) + - Fix concurrent handling of __cpu_features (BZ#11292) + - Handle unnecessary padding in getdents64 (BZ#11333) + - Fix changes to interface list during getifaddrs calls (BZ#11387) + - Missing memory barrier in DES initialization (BZ#11449) + - Fix spurious UNAVAIL status is getaddrinfo + - Add support for new clocks (BZ#11389) + - Fix Linux getlogin{_r,} implementation + - Fix missing zero-termination in cuserid (BZ#11397) + - Fix glob with empty pattern + - Fix handling of STB_GNU_UNIQUE in LD_TRACE_PRELINKING + - Unify wint_t handling in wchar.h and wctype.h (BZ#11410) + - Implement handling of libc ABI in ELF header + - Don't underestimate length of DST substitution in rpath + - Power7-optimized 64-bit and 32-bit memcpy +- Assign global scope to RFC 1918 addresses (#577626) + +* Thu Mar 18 2010 Andreas Schwab - 2.11.90-16 +- Fix SSSE3 memcmp (#574210) + +* Tue Mar 9 2010 Andreas Schwab - 2.11.90-15 +- Update from master + - sparc64: Fix handling of R_SPARC_TLS_LE_* relocations (#571551) + - Handle ext4 and logfs in statvfs functions + - Fix setxid race with thread creation + - Pass -mtune=i686 to assembler when compiling for i686 + - Fix R_X86_64_PC32 overflow detection + - Fix msgrcv on sparc64 + - Fix unwind info in x86 strcmp-sse4.S (BZ#11332) + - sparc: Add multiarch support for memset/bzero/memcpy +- Remove directories owned by filesystem (#569414) +- Add %%ghost /etc/gai.conf to glibc-common (#567748) + +* Tue Feb 23 2010 Andreas Schwab - 2.11.90-14 +- Update from master + - Sparc updates +- Fix SSSE3 memcpy (#556584) + +* Mon Feb 22 2010 Andreas Schwab - 2.11.90-13 +- Update from master + - Use CPUID_OFFSET instead of FEATURE_OFFSET + - Add 32bit memcmp/strcmp/strncmp optimized for SSSE3/SSS4.2 + - Fix file descriotor leak in nftw with FTW_CHDIR (BZ#11271) + - Add Sparc STT_GNU_IFUNC support + - Add power7-optimized classification functions +- Reapply "Optimize 32bit memset/memcpy with SSE2/SSSE3." +- Use unsigned comparison in sse memcpy/memset + +* Mon Feb 8 2010 Andreas Schwab - 2.11.90-12 +- Update from master + - Update constants in for current kernels (#11235) + - Fix endless loop with invalid /etc/shells file (#11242) + - Fix sorting of malayalam letter 'na' (#10414) + - Add kok_IN locale + - Use common collation data in as_IN locale + - Avoid alloca in setenv for long strings +- Use shared mapping to reserve memory when creating locale archive (#10855) +- Fix fstat on Linux/sparc64 (#11155) + +* Mon Feb 1 2010 Andreas Schwab - 2.11.90-11 +- Update from master + - Fix error checking in iconv (#558053) + - Don't map U00DF to U1E9E in toupper table + - _nl_load_locale() incorrectly handles mmap() failures (BZ#11200) + - Fix various issues in regex matcher (BZ#11183, BZ#11184, BZ#11185, + BZ#11186, BZ#11187, BZ#11188, BZ#11189, BZ#11190, BZ#11191, + BZ#11192, BZ#11193) + +* Tue Jan 19 2010 Andreas Schwab - 2.11.90-10 +- Update from master + - Fix ____longjmp_chk for s390/s390x + - Remove duplicate definitions of O_DSYNC and O_RSYNC for Linux/sparc + - Ignore negative dynamic entry types (#546890) + - Fix pthread_cond_*wait with requeue-PI on i386 (#548989) + - Fix _XOPEN_SOURCE_EXTENDED handling +- Revert "Optimize 32bit memset/memcpy with SSE2/SSSE3." + +* Fri Jan 15 2010 Andreas Schwab - 2.11.90-9 +- Update from master. + - Define IPTOS_CLASS_* macros according to RFC 2474 (BZ#11027) + - Always use IPv4 sockets for IPv4 addresses (BZ#11141) + - regcomp.c: do not ignore memory allocation failure (BZ#11127) + - Fix malloc_info without prior allocations (BZ#11126) + - Optimize 32bit memset/memcpy with SSE2/SSSE3 + - Relax feature tests in headers + +* Tue Jan 12 2010 Andreas Schwab - 2.11.90-8 +- Update from master. + - More POSIX conformance fixes. + +* Mon Jan 11 2010 Andreas Schwab - 2.11.90-7 +- Fix build failure. + +* Mon Jan 11 2010 Andreas Schwab - 2.11.90-6 +- Update from master. + - POSIX conformance fixes (BZ#11125). + +* Mon Jan 4 2010 Andreas Schwab - 2.11.90-5 +- Update from master. + - Additional setcontext(), etc. conformance tests (BZ#11115). + - Handle AT_FDCWD in futimens (BZ#10992). + - Update poll.h header for POSIX 2008 (BZ#11093). + - Avoid ELF lookup race. + +* Mon Dec 14 2009 Andreas Schwab - 2.11.90-4 +- Update from master. + - Add Requeue-PI support for x86 arch. + - Redefine O_SYNC and O_DSYNC to match 2.6.33+ kernels. + - Fix a few error cases in *name4_r lookup handling (BZ#11000). + - Fix kernel version check in recent ptsname change (BZ#11046). + - Add more warnings to exec functions (BZ#11056). + - Add recvmmsg interface. + - Define SCHED_IDLE and SCHED_RESET_ON_FORK for Linux. + +* Mon Nov 30 2009 Andreas Schwab - 2.11.90-3 +- Update from master. + - Fix infloop in __pthread_disable_asynccancel on x86_64 (#537690). + - Prevent unintended file desriptor leak in grantpt (#530558). + - Fix startup to security-relevant statically linked binaries (#528631). +- Re-install CFI in x86/x86_64 clone (#491542). + +* Tue Nov 24 2009 Andreas Schwab - 2.11.90-2 +- Update from master. + - Define week, first_weekday, and first_workday for en_DK locale (#525126). + - Use struct timespec for timestamps in struct stat also if + __USE_XOPEN2K8 (#539870). + - Fix week information for nl_NL locale (#499748). + - Update ntp_gettime for Linux (#479558). + - Fix getwc* and putwc* on non-wide streams (BZ#10958). + - Avoid warnings in CPU_* macros when using const bitsets (BZ#10918). + - Handle LC_GLOBAL_LOCALE in duplocale (BZ#10969). + - Fix _NC_LOCALE_NAME definition (BZ#10968). + - Add missing Linux MADV_* definitions (BZ#10972). + - Add support for new Linux error ERFKILL (BZ#10939). +- Enable multi-arch support on ppc and ppc64. + +* Thu Nov 12 2009 Andreas Schwab - 2.11.90-1 +- Update from master. + +* Thu Nov 5 2009 Andreas Schwab - 2.11-2 +- Fix readahead on powerpc32. +- Fix R_PPC64_{JMP_IREL,IRELATIVE} handling. +- Fix preadv, pwritev and fallocate for -D_FILE_OFFSET_BITS=64 (#533063). + +* Mon Nov 2 2009 Andreas Schwab - 2.11-1 +- Update to 2.11 release. +- Disable multi-arch support on PowerPC again since binutils is too old. +- Fix crash in tzdata-update due to use of multi-arch symbol (#532128). + +* Fri Oct 30 2009 Andreas Schwab - 2.10.90-27 +- Update from master. + - Fix races in setXid implementation (BZ#3270). + - Implement IFUNC for PPC and enable multi-arch support. + - Implement mkstemps/mkstemps64 and mkostemps/mkostemps64 (BZ#10349). + - Fix IA-64 and S390 sigevent definitions (BZ#10446). + - Fix memory leak in NIS grp database handling (BZ#10713). + - Print timestamp in nscd debug messages (BZ#10742). + - Fix mixing IPv4 and IPv6 name server in resolv.conf. + - Fix range checks in coshl. + - Implement SSE4.2 optimized strchr and strrchr. + - Handle IFUNC symbols in dlsym (#529965). + - Misc fixes (BZ#10312, BZ#10315, BZ#10319, BZ#10391, BZ#10425, + BZ#10540, BZ#10553, BZ#10564, BZ#10609, BZ#10692, BZ#10780, + BZ#10717, BZ#10784, BZ#10789, BZ#10847 +- No longer build with -fno-var-tracking-assignments. + +* Mon Oct 19 2009 Andreas Schwab - 2.10.90-26 +- Update from master. + - Add ____longjmp_chk for sparc. +- Avoid installing the same libraries twice. + +* Mon Oct 12 2009 Andreas Schwab - 2.10.90-25 +- Update from master + - Fix descriptor leak when calling dlopen with RTLD_NOLOAD (#527409). + - Fix week-1stday in C locale. + - Check for integer overflows in formatting functions. + - Fix locale program error handling (#525363). + +* Mon Sep 28 2009 Andreas Schwab - 2.10.90-24 +- Update from master. + - Fix missing reloc dependency (#517001). + +* Mon Sep 21 2009 Andreas Schwab - 2.10.90-23 +- Update from master. + +* Mon Sep 14 2009 Andreas Schwab - 2.10.90-22 +- Update from master. + - Fix endless loop in localedef. + - Fix __longjmp_chk on s390/s390x. +- Fix exit codes in nscd start script (#521848). +- Build with -fno-var-tracking-assignments for now (#523172). + +* Mon Sep 7 2009 Andreas Schwab - 2.10.90-21 +- Update from master. + - Fix strstr/strcasestr on i386 (#519226). + +* Thu Sep 3 2009 Andreas Schwab - 2.10.90-20 +- Update from master. + - Fix strstr/strcasestr/fma/fmaf on x86_64 (#519226). + - Fix lookup of group names in hesiod initgroups (#520472). + +* Wed Sep 2 2009 Andreas Schwab - 2.10.90-19 +- Update from master. + - Fix x86_64 bits/mathinline.h for -m32 compilation. + +* Tue Sep 1 2009 Andreas Schwab - 2.10.90-18 +- Update from master. + - fix parse error in (#520209). + +* Thu Aug 27 2009 Roland McGrath - 2.10.90-17 +- Update from master. + +* Wed Aug 26 2009 Andreas Schwab - 2.10.90-16 +- Update from master. + - handle AVX saving on x86-64 in interrupted symbol lookups (#519081). + +* Mon Aug 24 2009 Andreas Schwab - 2.10.90-15 +- Update from master. + - fix fortify failure with longjmp from alternate stack (#512103). +- Add conflict with prelink (#509655). + +* Mon Aug 17 2009 Andreas Schwab - 2.10.90-14 +- Update from master. + - fix pthread_cond_signal (#516469) + +* Mon Aug 10 2009 Andreas Schwab - 2.10.90-13 +- Update from master. + - fix rehashing of unique symbols (#515677) +- Fix spurious messages with --excludedocs (#515948) + +* Mon Aug 3 2009 Andreas Schwab - 2.10.90-12 +- Update from master. + - fix fortify failure with longjmp from alternate stack (#512103) + +* Thu Jul 30 2009 Andreas Schwab - 2.10.90-11 +- Update from master. +- Don't package debuginfo files in glibc-devel. + +* Tue Jul 28 2009 Andreas Schwab - 2.10.90-10 +- Update from master. + * fix memory ordering in pthread_mutex_unlock (BZ#10418) + * implement RES_USE_DNSSEC option in resolver (#205842) + * fix hang in ldd -r (#513945) + +* Mon Jul 27 2009 Andreas Schwab - 2.10.90-9 +- Update from master. + +* Fri Jul 24 2009 Fedora Release Engineering - 2.10.90-8.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Fri Jul 24 2009 Jakub Jelinek - 2.10.90-7.1 +- Fix up pthread_cond_timedwait on x86_64 with old kernels. + +* Thu Jul 23 2009 Andreas Schwab - 2.10.90-7 +- Update from master. +- Build with -DNDEBUG unless using a prerelease. + +* Thu Jul 23 2009 Andreas Schwab - 2.10.90-6 +- Rebuilt with binutils-2.19.51.0.14-29.fc12 to fix static binaries + +* Wed Jul 22 2009 Andreas Schwab - 2.10.90-5 +- Update from master. +- Undefine __i686 on x86 to fix build. + +* Mon Jul 20 2009 Andreas Schwab - 2.10.90-4 +- Update from master. +- Don't build separate i686 package. + +* Wed Jul 8 2009 Andreas Schwab 2.10.90-3 +- Reenable setuid on pt_chown. + +* Thu Jul 2 2009 Andreas Schwab 2.10.90-2 +- Update from master. + +* Fri Jun 26 2009 Andreas Schwab 2.10.90-1 +- Update from master. +- Enable multi-arch support on x86/x86-64. +- Add requires glibc-headers to glibc-devel (#476295). +- Implement second fallback mode for DNS requests (#505105). +- Don't generate invalid POSIX TZ string for Asia/Dhaka timezone (#506941). +- Allow backtrace through __longjmp_chk on powerpc. + +* Fri May 22 2009 Jakub Jelinek 2.10.1-2 +- fix accept4 on architectures other than i?86/x86_64 +- robustify nscd client code during server GC +- fix up nscd segfaults during daemon shutdown +- fix memchr on ia64 (BZ#10162) +- replace the Sun RPC license with the BSD license, with the explicit + permission of Sun Microsystems +- fix up powerpc long double errno reporting + +* Sun May 10 2009 Jakub Jelinek 2.10.1-1 +- fix up getsgent_r and getsgnam_r exports on i?86 and ppc + +* Sat May 9 2009 Jakub Jelinek 2.10-2 +- update from trunk + - glibc 2.10 release + - fix memchr on x86_64 (#499689) + +* Mon Apr 27 2009 Jakub Jelinek 2.9.90-22 +- update from trunk + - further localedef fixes +- fix build-locale-archive + +* Fri Apr 24 2009 Jakub Jelinek 2.9.90-21 +- update from trunk + - fix localedef + - fix SHIFT_JIS iconv EILSEQ handling (#497267) + - misc fixes (BZ#10093, BZ#10100) + +* Fri Apr 24 2009 Jakub Jelinek 2.9.90-20 +- update from trunk + - fix p{read,write}v{,64} (#497429, #497434) + - fix strfmon (#496386) + +* Thu Apr 16 2009 Jakub Jelinek 2.9.90-19 +- update from trunk + - fix dlopen from statically linked binaries (#495830) + +* Thu Apr 16 2009 Jakub Jelinek 2.9.90-18 +- update from trunk + - fix fallocate + +* Wed Apr 15 2009 Jakub Jelinek 2.9.90-17 +- update from trunk + - if threads have very small stack sizes, use much smaller buffer + in __get_nprocs when called from within malloc (#494631) + +* Tue Apr 14 2009 Jakub Jelinek 2.9.90-16 +- update from trunk + +* Thu Apr 9 2009 Jakub Jelinek 2.9.90-15 +- rebuilt with fixed gcc to avoid miscompilation of i586 memmove +- reenable experimental malloc again + +* Wed Apr 8 2009 Jakub Jelinek 2.9.90-14 +- update from trunk +- temporarily disable experimental malloc + +* Tue Apr 7 2009 Jakub Jelinek 2.9.90-13 +- update from trunk + - fix strverscmp (#494457) +- configure with --enable-nss-crypt + +* Wed Apr 1 2009 Jakub Jelinek 2.9.90-12 +- update from trunk +- configure with --enable-experimental-malloc + +* Fri Mar 20 2009 Jakub Jelinek 2.9.90-11 +- update from trunk + - POSIX 2008 prototype adjustments for scandir{,64}, alphasort{,64} and + versionsort{,64} + - fix libthread_db (#491197) + +* Tue Mar 10 2009 Jakub Jelinek 2.9.90-10 +- update from trunk + - fix atexit/__cxa_atexit + +* Mon Mar 9 2009 Jakub Jelinek 2.9.90-9 +- update from trunk + - POSIX 2008 support: -D_XOPEN_SOURCE=700 and -D_POSIX_C_SOURCE=200809L +- move libnldbl_nonshared.a on ppc*/s390*/sparc* back to glibc-devel + +* Fri Feb 27 2009 Roland McGrath - 2.9.90-8.1 +- fix libthread_db (#487212) + +* Tue Feb 24 2009 Fedora Release Engineering - 2.9.90-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Wed Feb 18 2009 Jakub Jelinek 2.9.90-7 +- update from trunk +- adjust for i586 + i686 from i386 + i686 build +- split static libraries into glibc-static subpackage +- ld -r the whole libpthread.a together to avoid endless issues with + -static ... -lpthread +- require 2.6.18 and later kernel + +* Wed Feb 4 2009 Jakub Jelinek 2.9.90-3 +- update from trunk + - ISO C++ compliant strchr etc. with GCC 4.4+ + - AT_RANDOM support + +* Thu Jan 8 2009 Jakub Jelinek 2.9.90-2 +- update from trunk + +* Fri Jan 2 2009 Jakub Jelinek 2.9.90-1 +- update from trunk (#478314) + +* Mon Dec 8 2008 Jakub Jelinek 2.9-3 +- temporarily disable _nss_dns_gethostbyname4_r (#459756) +- NIS hostname lookup fixes (#473073, #474800, BZ#7058) +- fix unsetenv (#472941) + +* Thu Nov 13 2008 Jakub Jelinek 2.9-2 +- glibc 2.9 release +- fix CPU_ALLOC_SIZE on 32-bit arches (BZ#7029) + +* Wed Nov 12 2008 Jakub Jelinek 2.8.90-17 +- update from trunk + - don't abort on broken DNS replies (#469299, BZ#7009) + - misc fixes (BZ#6966, BZ#7008, BZ#6955, BZ#6843) + +* Fri Oct 31 2008 Jakub Jelinek 2.8.90-16 +- update from trunk + - further resolver fixes + - another dynamic TLS handling fix (#469263) + - misc fixes (BZ#6867, BZ#6875, BZ#6919, BZ#6920, BZ#6942, BZ#6947, + BZ#6968, BZ#6974, BZ#6980, BZ#6995) +- rebuild with newer rpm to avoid stripping + shared libraries when they shouldn't be (#468129) + +* Tue Oct 28 2008 Jakub Jelinek 2.8.90-15 +- update from trunk + - __libc_res_nquery fixes (#466786) + +* Sun Oct 19 2008 Jakub Jelinek 2.8.90-14 +- update from trunk + - fix dynamic TLS handling (#467309) + - fix sys/signalfd.h for C++ (#467172) + - fix sprof (#458861) + - fix _mcount and socket syscalls on s390x (#464146) + - try harder to allocate memory in valloc and pvalloc (#461481) +- fix power6 32-bit libs (#467311) + +* Fri Oct 10 2008 Dennis Gilmore 2.8.90-13 +- apply sparcv9v memset patch from jakub and davem + +* Fri Aug 29 2008 Jakub Jelinek 2.8.90-12 +- update from trunk + - revert origin changes (#457849) + - use MAP_STACK for thread stacks + - misc fixes (BZ#6845, BZ#6544, BZ#6634, BZ#6589, BZ#6790, BZ#6791, + BZ#6824) + - power7 bits (BZ#6817) + - fix expm1 on i?86/x86_64 (#43354, BZ#5794) + +* Sat Aug 2 2008 Jakub Jelinek 2.8.90-11 +- update from trunk + - fix non-absolute $ORIGIN handling (#457560) + - exported some further libresolv APIs (#453325) + - misc fixes + +* Tue Jul 29 2008 Jakub Jelinek 2.8.90-10 +- update from trunk + - resolver fixes + - misc fixes (BZ#6771, BZ#6763, BZ#6698, BZ#6712) + - s390{,x} utmp/utmpx bi-arch support (BZ#6724) + - popen "e" flag +- fr_FR locale changes reenabled + +* Wed Jul 16 2008 Jakub Jelinek 2.8.90-9 +- update from trunk + - fix unbuffered vfprintf if writing to the stream fails (#455360) + - remove useless "malloc: using debugging hooks" message (#455355) + - nscd fixes + - fix resolver alignment issues (#454500) + - fix setvbuf (BZ#6719) + +* Thu Jul 3 2008 Jakub Jelinek 2.8.90-8 +- update from trunk + - watch even resolv.conf in nscd using inotify + - some nscd fixes + +* Fri Jun 13 2008 Jakub Jelinek 2.8.90-7 +- update from trunk + - avoid *lround* on ppc* clobbering cr3/cr4 registers (#450790) + - further nscd fixes (#450704) + - use inotify in nscd to watch files + +* Thu Jun 12 2008 Jakub Jelinek 2.8.90-6 +- update from trunk + - nscd fixes (#450704) + - fix getservbyport (#449358) + - fix regexp.h (#446406) + - avoid crashing on T_DNAME in DNS responses (#450766) + +* Sun May 25 2008 Jakub Jelinek 2.8.90-5 +- update from trunk + +* Tue May 20 2008 Jakub Jelinek 2.8.90-4 +- further getaddrinfo and nscd fixes + +* Sun May 18 2008 Jakub Jelinek 2.8.90-3 +- getaddrinfo and nscd fixes +- reenable assertion checking in rawhide + +* Fri May 16 2008 Jakub Jelinek 2.8.90-2 +- fix getaddrinfo (#446801, #446808) + +* Thu May 15 2008 Jakub Jelinek 2.8.90-1 +- update to trunk + - O(n) memmem/strstr/strcasestr + - i386/x86_64 TLS descriptors support + - concurrent IPv4 and IPv6 DNS lookups by getaddrinfo + +* Mon May 5 2008 Jakub Jelinek 2.8-3 +- don't run telinit u in %%post if both /dev/initctl and + /sbin/initctl exist (#444978) +- workaround GCC ppc64 miscompilation of c{log{,10},acosh,atan}l + (#444996) + +* Wed Apr 30 2008 Jakub Jelinek 2.8-2 +- fix nscd races during GC (BZ#5381) +- rebuilt with fixed GCC to fix regex miscompilation on power6 +- SPARC fixes + +* Sat Apr 12 2008 Jakub Jelinek 2.8-1 +- 2.8 release + +* Fri Apr 11 2008 Jakub Jelinek 2.7.90-16 +- update to trunk + - misc fixes (BZ#4997, BZ#5741) + - make sure all users of __libc_setlocale_lock know it is + now a rwlock + - fix ppc/ppc64 compatibility _sys_errlist and _sys_siglist + symbols + +* Thu Apr 10 2008 Jakub Jelinek 2.7.90-15 +- update to trunk + - misc fixes (BZ#4314, BZ#4407, BZ#5209, BZ#5436, BZ#5768, BZ#5998, + BZ#6024) +- restart sshd in %%post when upstart is used - it doesn't have + /dev/initctl (#441763) +- disable assert checking again + +* Tue Apr 8 2008 Jakub Jelinek 2.7.90-14 +- update to trunk + - misc fixes (BZ#5443, BZ#5475, BZ#5478, BZ#5939, BZ#5979, BZ#5995, + BZ#6004, BZ#6007, BZ#6020, BZ#6021, BZ#6042) + - change mtrace to keep perl 5.10 quiet (#441082) + - don't share conversion state between mbtowc and wctomb (#438687) + - if st_blksize is too large and malloc fails, retry with smaller + buffer in opendir (#430768) + - correct *printf overflow test (#358111) + +* Fri Mar 28 2008 Jakub Jelinek 2.7.90-13 +- update to trunk + - don't define ARG_MAX in , as it is no longer + constant - use sysconf (_SC_ARG_MAX) to get the current + argument size limit + - fix build on sparc64 +- only service sshd condrestart if /etc/rc.d/init.d/sshd exists + (#428859) + +* Wed Mar 26 2008 Jakub Jelinek 2.7.90-12 +- update to trunk + - new CLONE_* flags in (#438542) + - nis+ errno clobbering fix (#437945) + - fix adjtime (#437974) + +* Fri Mar 14 2008 Jakub Jelinek 2.7.90-11 +- update to trunk +- remove , define _XOPEN_STREAMS -1 (#436349) + +* Wed Mar 5 2008 Jakub Jelinek 2.7.90-8 +- update to trunk + - {,v}{as,d}printf and obstack_{,v}printf fortification (#435905) + - fix getnameinfo/gethostbyaddr (#428067, BZ#5790) + - fix yp_order (#435519, BZ#5854) + - misc fixes (BZ#5779, BZ#5736, BZ#5627, BZ#5818, BZ#5012) +- merge review cleanup (Tom Callaway, #225806) + +* Sat Feb 16 2008 Jakub Jelinek 2.7.90-7 +- update to trunk + - make NI_MAXHOST and NI_MAXSERV available even in BSDish + namespaces (BZ#5737) + - timerfd_* syscalls + +* Fri Feb 1 2008 Jakub Jelinek 2.7.90-6 +- fix build + +* Thu Jan 31 2008 Jakub Jelinek 2.7.90-5 +- update to trunk +- rebuild with gcc 4.3 + +* Fri Jan 11 2008 Jakub Jelinek 2.7.90-4 +- update to trunk + - misc fixes (BZ#5541, BZ#5545, BZ#5553, BZ#5112, BZ#5520) + - getaddrinfo fixes + - signalize EOVERFLOW from sem_post instead of overflowing + the counter + - fix i?86 makecontext + - fix iconv for iso-2022-jp//translit (#397021) + +* Thu Jan 3 2008 Jakub Jelinek 2.7.90-3 +- update to trunk + - fix recognition of interface family (#425768) + - add __THROW to __ctype_{b,tolower,toupper}_loc prototypes + +* Thu Dec 27 2007 Jakub Jelinek 2.7.90-2 +- update to trunk + - nsswitch fix (#425768) +- temporarily enable assert checking + +* Wed Dec 12 2007 Jakub Jelinek 2.7.90-1 +- update to trunk + - fix __USE_STRING_INLINES on i?86 (#408731, #371711) + - fix *scanf (#388751) + +* Wed Oct 17 2007 Jakub Jelinek 2.7-1 +- glibc 2.7 release +- fix tzfile.c for times after last transition (#333561) +- fix sem_post@GLIBC_2.0 on i?86 +- appease valgrind in libpthread.so initialization +- misc fixes (BZ#3425, BZ#5184, BZ#5186) + +* Mon Oct 15 2007 Jakub Jelinek 2.6.90-21 +- fix getgr{name,gid}{,_r} with nscd + +* Sun Oct 14 2007 Jakub Jelinek 2.6.90-20 +- install (#330031) +- disable -D_FORTIFY_SOURCE{,=2} support (with a warning) for + GCC 3.4.x and earlier(#327641) +- pl_PL locale changes (BZ#4098, #242296) +- misc fixes (BZ#1140, BZ#3195, BZ#3242, BZ#4359) + +* Thu Oct 11 2007 Jakub Jelinek 2.6.90-19 +- fix +- simple preprocessor in localedef, fix de_DE collation with it + +* Wed Oct 10 2007 Jakub Jelinek 2.6.90-18 +- add signalfd, eventfd, eventfd_read, eventfd_write +- qsort speedups +- workaround for cpuid bugs (#324081) +- make sure gettext's conversion_lock is initialized even if + program isn't linked against libpthread.so.0, only dlopens it (#321761) +- misc fixes (BZ#5112, BZ#5113, BZ#5104, BZ#5063, BZ#5010, BZ#4407, + BZ#3924, BZ#5103, BZ#2633, BZ#181, BZ#73, #321901) + +* Wed Oct 3 2007 Jakub Jelinek 2.6.90-17 +- fix {,v}swprintf with -D_FORTIFY_SOURCE=1 -mlong-double-64 on ppc*/s390*/sparc* +- strcoll fixes +- misc fixes (BZ#645, BZ#5071) +- locale fixes (BZ#4941, #299321, #203364, #196711, #236212) + +* Sat Sep 29 2007 Jakub Jelinek 2.6.90-16 +- misc fixes (BZ#4963, BZ#4972, BZ#5028, BZ#5043, BZ#5058) +- improve -D_FORTIFY_SOURCE{,=2} diagnostic through warning/error + attributes +- fix wcscpy, wcpcpy, fgetws, fgetws_unlocked, swprintf and vswprintf + fortification inlines +- fix a scalability issue with lazy binding in heavily multithreaded + programs + +* Thu Sep 20 2007 Jakub Jelinek 2.6.90-15 +- $5$ (SHA-256) and $6$ (SHA-512) support in crypt + (#228697, #249477, #173834) + +* Tue Sep 18 2007 Jakub Jelinek 2.6.90-14 +- -D_FORTIFY_SOURCE{,=2} support for C++ +- fortification of fread{,_unlocked} +- support *scanf m allocation modifier (%%ms, %%mls, %%mc, ...) +- in -std=c99 or -D_XOPEN_SOURCE=600 mode don't recognize + %%as, %%aS and %%a[ as a GNU extension for *scanf +- fix splice, vmsplice, tee return value, make them cancellation + points +- mq_open checking +- use inline function rather than function-like macro + for open{,at}{,64} checking +- IFA_F_OPTIMISTIC handling in getaddrinfo (#259681) +- fix an ABBA deadlock in ld.so (#284171) +- remove sparc{32,64} unwind info from _start and clone + +* Mon Aug 27 2007 Jakub Jelinek 2.6.90-13 +- fix personality on x86_64/ppc/ppc64 (#256281) + +* Sat Aug 25 2007 Jakub Jelinek 2.6.90-12 +- readd x86_64 gettimeofday stuff, initialize it earlier +- nis_list fix (#254115) +- workaround for bugs in ia64 silly /emul/ia32-linux hack (#253961) +- misc fixes (BZ#3924, BZ#4566, BZ#4582, BZ#4588, BZ#4726, BZ#4946, + BZ#4905, BZ#4814, BZ#4925, BZ#4936, BZ#4896, BZ#4937, BZ#3842, + BZ#4554, BZ#4557, BZ#4938) + +* Fri Aug 17 2007 Jakub Jelinek 2.6.90-11 +- remove __strtold_internal and __wcstold_internal from ppc*/s390*/sparc* + *-ldbl.h headers +- temporarily backout x86_64 gettimeofday.S changes (#252453) +- some further sparc, sparc64 and alpha fixes + +* Wed Aug 15 2007 Jakub Jelinek 2.6.90-10 +- don't open /etc/ld.so.{cache,preload} with O_NOATIME (#252146) +- s390{,x}, alpha and sparc fixes +- sparcv9 is no longer an aux arch, as we expect + to not build sparc.rpm glibc any longer, only sparcv9.rpm, + sparc64.rpm and new two aux arches sparcv9v.rpm and sparc64v.rpm + +* Tue Aug 14 2007 Jakub Jelinek 2.6.90-9 +- private futex even for mutexes and condvars +- some further O_CLOEXEC changes +- use vDSO on x86_64 if available +- ia64 build fixes (#251983) + +* Fri Aug 10 2007 Roland McGrath 2.6.90-8 +- update to trunk + - fix missing strtold_l export on ppc64 + +* Thu Aug 9 2007 Roland McGrath 2.6.90-6 +- update to trunk + - fix local PLT regressions +- spec file revamp for new find-debuginfo.sh + +* Sun Aug 5 2007 Jakub Jelinek 2.6.90-4 +- fix librt.so and librtkaio.so on ppc32, so that it is not using + bss PLT + +* Sat Aug 4 2007 Jakub Jelinek 2.6.90-3 +- fix open{,at}{,64} macro for -pedantic (#250897) +- add transliteration for l with stroke (#250492) +- fix strtod ("-0", NULL) +- update License tag + +* Wed Aug 1 2007 Jakub Jelinek 2.6.90-2 +- make aux-cache purely optional performance optimization in ldconfig, + don't issue any errors if it can't be created (#250430) +- remove override_headers hack, BuildRequire >= 2.6.22 kernel-headers + and rely on its content + +* Tue Jul 31 2007 Jakub Jelinek 2.6.90-1 +- update to trunk + - private futex optimizations + - open{,at}{,64} argument checking +- ldconfig speedups + +* Sun Jul 8 2007 Jakub Jelinek 2.6-4 +- filter pseudo-files from debuginfo source lists (#245714) +- fix sscanf when errno is EINTR before the call (BZ#4745) +- save/restore errno around reading /etc/default/nss (BZ#4702) +- fix LD_HWCAP_MASK handling +- disable workaround for #210748, instead backport + ld.so locking fixes from the trunk (#235026) +- new x86_64 memcpy +- don't write uninitialized padding bytes to nscd socket +- fix dl{,v}sym, dl_iterate_phdr and dlopen if some library is + mapped into ld.so's inter-segment hole on x86_64 (#245035, #244545) +- fix LD_AUDIT=a:b program (#180432) +- don't crash on pseudo-zero long double values passed to + *printf on i?86/x86_64/ia64 (BZ#4586) +- fix *printf %%La and strtold with some hexadecimal floating point + constants on ppc/ppc64 +- fix nextafterl on ppc/ppc64 +- fix sem_timedwait on i?86 and x86_64 + +* Thu May 24 2007 Jakub Jelinek 2.6-3 +- don't use %%config(missingok) for locale-archive.tmpl, + instead of removing it altogether truncate it to zero + size (#240697) +- add a workaround for #210748 + +* Mon May 21 2007 Jakub Jelinek 2.6-2 +- restore malloc_set_state backwards compatibility (#239344) +- fix epoll_pwait (BZ#4525) +- fix printf with unknown format spec or positional arguments + and large width and/or precision (BZ#4514) +- robust mutexes fix (BZ#4512) + +* Tue May 15 2007 Roland McGrath 2.6-1 +- glibc 2.6 release + +* Fri May 11 2007 Jakub Jelinek 2.5.90-24 +- utimensat, futimens and lutimes support + +* Thu May 10 2007 Jakub Jelinek 2.5.90-23 +- use madvise MADV_DONTNEED in malloc +- fix ia64 feraiseexcept +- fix s390{,x} feholdexcept (BZ#3427) +- ppc fenv fixes +- make fdatasync a cancellation point (BZ#4465) +- fix *printf for huge precisions with wide char code and multi-byte + strings +- fix dladdr (#232224, BZ#4131) + +* Fri May 4 2007 Jakub Jelinek 2.5.90-22 +- add transliteration for (BZ#3213) +- fix *scanf with %%f on hexadecimal floats without exponent (BZ#4342) +- fix *printf with very large precisions for %%s (#238406, BZ#4438) +- fix inet_ntop size checking for AF_INET (BZ#4439) +- for *printf %%e avoid 1.000e-00, for exponent 0 always use + sign (#238431) +- fix a regression introduced in #223467 changes +- gethostby*_r alignment fixes (BZ#4381) +- fix ifaddrs error handling + +* Mon Apr 16 2007 Jakub Jelinek 2.5.90-21 +- don't include individual locale files in glibc-common, + rather include prepared locale-archive template and let + build-locale-archive create locale-archive from the template + and any user supplied /usr/lib/locale/*_* directories, + then unlink the locale-archive template - this should save + > 80MB of glibc-common occupied disk space +- fix _XOPEN_VERSION (BZ#4364) +- fix printf with %%g and values tiny bit smaller than 1.e-4 (#235864, + BZ#4362) +- fix NIS+ __nisfind_server (#235229) + +* Sat Mar 31 2007 Jakub Jelinek 2.5.90-20 +- assorted NIS+ speedups (#223467) +- fix HAVE_LIBCAP configure detection (#178934) +- remove %%{_prefix}/sbin/rpcinfo from glibc-common (#228894) +- nexttoward*/nextafter* fixes (BZ#3306) +- feholdexcept/feupdateenv fixes (BZ#3427) +- speed up fnmatch with two or more * in the pattern + +* Sat Mar 17 2007 Jakub Jelinek 2.5.90-19 +- fix power6 libm compat symbols on ppc32 (#232633) +- fix child refcntr in NPTL fork (#230198) +- fix ifaddrs with many net devices on > 4KB page size arches (#230151) +- fix pthread_mutex_timedlock on x86_64 (#228103) +- various fixes (BZ#3919, BZ#4101, BZ#4130, BZ#4181, BZ#4069, BZ#3458) + +* Wed Feb 21 2007 Jakub Jelinek 2.5.90-18 +- fix nftw with FTW_CHDIR on / (BZ#4076) +- nscd fixes (BZ#4074) +- fix fmod{,f,l} on i?86 (BZ#3325) +- support localized digits for fp values in *scanf (BZ#2211) +- namespaces fixes (BZ#2633) +- fix euidaccess (BZ#3842) +- glob fixes (BZ#3996) +- assorted locale data fixes (BZ#1430, BZ#672, BZ#58, BZ#3156, + BZ#2692, BZ#2648, BZ#3363, BZ#3334, BZ#3326, BZ#3322, BZ#3995, + BZ#3885, BZ#3884, BZ#3851) + +* Sun Feb 11 2007 Jakub Jelinek 2.5.90-17 +- RFC2671 support in resolver (#205842) +- fix strptime (BZ#3944) +- fix regcomp with REG_NEWLINE (BZ#3957) +- fix pthread_mutex_timedlock on x86_64 (#228103) + +* Fri Feb 2 2007 Jakub Jelinek 2.5.90-16 +- add strerror_l +- fix application crashes when doing NSS lookups through nscd + mmapped databases and nscd decides to start garbage collection + during the lookups (#219145, #225315) +- fix %%0lld printing of 0LL on 32-bit architectures (BZ#3902) +- ignore errors from install-info in glibc-devel scriptlets + (#223691) + +* Wed Jan 17 2007 Jakub Jelinek 2.5.90-15 +- fix NIS getservbyname when proto is NULL +- fix nss_compat +group handling (#220658) +- cache services in nscd +- fix double free in fts_close (#222089) +- fix vfork+execvp memory leak (#221187) +- soft-fp fixes (BZ#2749) +- further strtod fixes (BZ#3855) +- make sure pthread_kill doesn't return EINVAL even if + the target thread exits in between pthread_kill ESRCH check + and the actual tgkill syscall (#220420) +- fix ABBA deadlock possibility in ld.so scope locking code + +* Tue Dec 19 2006 Jakub Jelinek 2.5.90-14 +- fix {j,m}rand48{,_r} on 64-bit arches (BZ#3747) +- handle power6x AT_PLATFORM (#216970) +- fix a race condition in getXXbyYY_r (#219145) +- fix tst-pselect testcase + +* Thu Dec 14 2006 Jakub Jelinek 2.5.90-13 +- fix setcontext on ppc32 (#219107) +- fix wide stdio after setvbuf (#217064, BZ#2337) +- handle relatime mount option in statvfs +- revert i?86/x86_64 clone CFI temporarily + +* Sun Dec 10 2006 Jakub Jelinek 2.5.90-12 +- fix hasmntopt (#218802) +- fix setusershell and getusershell (#218782) +- strtod fixes (BZ#3664, BZ#3673, BZ#3674) +- fix memusage with realloc (x, 0) + +* Tue Dec 5 2006 Jakub Jelinek 2.5.90-11 +- allow suid apps to setenv NIS_PATH and influence through that + nis_list and nis_lookup (#209155) +- fix ttyname and ttyname_r with invalid file descriptor (#218276) +- cs_CZ LC_TIME fixes (#218438) +- fix build with 2.6.19+ headers (#217723) + +* Fri Dec 1 2006 Jakub Jelinek 2.5.90-10 +- fix x86-64 restore_rt unwind info + +* Thu Nov 30 2006 Jakub Jelinek 2.5.90-9 +- fix last svc_run change (#217850) +- on ppc64 build __libc_start_main without unwind info, + as it breaks MD_FROB_UPDATE_CONTEXT (#217729, #217775; in the + future that could be fixable just by providing .cfi_undefined r2 + in __libc_start_main instead) +- add unwind info for x86-64 restore_rt signal return landing pad + (#217087) +- add power6x subdir to /%%{_lib}/ and /%%{_lib}/rtkaio/, + link all libs from ../power6/* into them + +* Tue Nov 28 2006 Jakub Jelinek 2.5.90-8 +- fix svc_run (#216834, BZ#3559) +- add -fasynchronous-unwind-tables to CFLAGS (#216518) +- make sure there is consistent timestamp for /etc/ld.so.conf, + /etc/localtime and /etc/rpc between multilib glibc rpms + +* Mon Nov 20 2006 Jakub Jelinek 2.5.90-7 +- handle IPv6 addresses in /etc/hosts that are mappable to + IPv4 addresses in IPv4 host lookups (#215283) +- fix :include: /etc/alias handling (#215572) +- handle new tzdata format to cope with year > 2037 transitions + on 64-bit architectures + +* Fri Nov 10 2006 Jakub Jelinek 2.5.90-6 +- fix strxfrm fix +- fix i?86 floor and ceil inlines (BZ#3451) + +* Thu Nov 9 2006 Jakub Jelinek 2.5.90-5 +- fix sysconf (_SC_LEVEL{2,3}_CACHE_SIZE) on Intel Core Duo + CPUs +- fix libthread_db.so on TLS_DTV_AT_TP architectures +- fix --inhibit-rpath (#214569) +- fix _r_debug content when prelinked ld.so executes + a program as its argument +- fix strxfrm +- powerpc-cpu add-on updates + +* Fri Nov 3 2006 Jakub Jelinek 2.5.90-4 +- fix atexit backwards compatibility (#213388) +- add mai_IN locale (#213415) +- remove bogus %%{_libdir}/librt.so.1 symlink (#213555) +- fix memusage (#213656) +- change libc.info category (#209493) + +* Sun Oct 29 2006 Jakub Jelinek 2.5.90-3 +- fix suid/sgid binaries on i?86/x86_64 (#212723) + +* Fri Oct 27 2006 Jakub Jelinek 2.5.90-2 +- fix ia64 build +- don't call _dl_close outside of dl_load_lock critical section + if dlopen failed (BZ#3426) +- add rtld scope locking (#211133) + +* Wed Oct 25 2006 Jakub Jelinek 2.5.90-1 +- fix i?86 6 argument syscalls (e.g. splice) +- fix rtld minimal realloc (BZ#3352) +- fix RFC3484 getaddrinfo sorting according to rules 4 and 7 (BZ#3369) +- fix xdrmem_setpos (#211452) +- bump __GLIBC_MINOR__ +- increase PTHREAD_STACK_MIN on ppc{,64} to 128K to allow + 64K pagesize kernels (#209877) +- speed up initgroups on NIS+ (#208203) + +* Mon Oct 2 2006 Jakub Jelinek 2.5-2 +- fix nscd database growing (#207928) +- bypass prelinking when LD_DYNAMIC_WEAK=1 is in the environment + +* Fri Sep 29 2006 Jakub Jelinek 2.5-1 +- glibc 2.5 release + +* Wed Sep 27 2006 Jakub Jelinek 2.4.90-36 +- rebuilt with gcc-4.1.1-26 to fix unwind info + +* Mon Sep 25 2006 Jakub Jelinek 2.4.90-35 +- fix glob with large number of matches (BZ#3253) +- fix fchownat on kernels that don't support that syscall (BZ#3252) +- fix lrintl on s390{,64} + +* Sat Sep 23 2006 Jakub Jelinek 2.4.90-34 +- fix ppc{32,64} longjmp (BZ#3225) +- fix user visible spelling errors (BZ#3137) +- fix l{,l}rint{,f,l} around zero (BZ#2592) +- avoid stack trampoline in s390{,x} makecontext + +* Tue Sep 19 2006 Jakub Jelinek 2.4.90-33 +- fix dlclose (#206639) +- don't load platform optimized libraries if kernel doesn't set + AT_PLATFORM +- fix ppc{32,64} libSegFault.so +- use -mtune=generic even for glibc-devel.i386 (#206437) +- fix /%%{_lib}/librt.so.1 symlink + +* Fri Sep 15 2006 Jakub Jelinek 2.4.90-32 +- on ppc* use just AT_PLATFORM and altivec AT_HWCAP bit for library selection +- fix lrintl and lroundl on ppc{,64} +- use hidden visibility on fstatat{,64} and mknodat in libc_nonshared.a + +* Sun Sep 10 2006 Jakub Jelinek 2.4.90-31 +- fix pthread_cond_{,timed}wait cancellation (BZ#3123) +- fix lrint on ppc32 (BZ#3155) +- fix malloc allocating more than half of address space (BZ#2775) +- fix mktime on 32-bit arches a few years after 2038 (BZ#2821) + +* Thu Sep 7 2006 Jakub Jelinek 2.4.90-30 +- add librtkaio, to use it add /%%{lib}/rtkaio to your + LD_LIBRARY_PATH or /etc/ld.so.conf +- fix or_IN February name (#204730) +- fix pthread_create called from cancellation handlers (BZ#3124) +- fix regex case insensitive searches with characters where upper + and lower case multibyte representations have different length + (e.g. I and dotless i, #202991) + +* Tue Sep 5 2006 Jakub Jelinek 2.4.90-29 +- randomize resolver query ids before use instead after use (#205113) +- fix resolver symver checking with DT_GNU_HASH (#204909) +- put .hash section in glibc libraries at the end of RO segment + when .gnu.hash is present + +* Thu Aug 31 2006 Jakub Jelinek 2.4.90-28 +- another malloc doubly linked list corruption problem fix (#204653) + +* Thu Aug 31 2006 Jakub Jelinek 2.4.90-27 +- allow $LIB and $PLATFORM in dlopen parameters even in suid/sgid (#204399) +- handle $LIB/$PLATFORM in LD_LIBRARY_PATH +- fix splice prototype (#204530) + +* Mon Aug 28 2006 Jakub Jelinek 2.4.90-26 +- real fix for the doubly linked list corruption problem +- try harder in realloc to allocate memory (BZ#2684) +- fix getnameinfo error reporting (#204122) +- make localedef more robust on invalid input (#203728) + +* Fri Aug 25 2006 Jakub Jelinek 2.4.90-25 +- temporarily back out code to limit number of unsorted block + sort iterations (#203735, #204027) +- handle PLT symbols in dladdr properly (BZ#2683) +- avoid malloc infinite looping for allocations larger than + the system can allocate (#203915) + +* Tue Aug 22 2006 Jakub Jelinek 2.4.90-23 +- malloc fixes, especially for 32-bit arches (#202309) +- further *_IN locale fixes (#200230) +- fix get{serv,rpc}ent{,_r} if NIS map is empty (#203237) +- fix /usr/bin/iconv (#203400) + +* Fri Aug 18 2006 Jakub Jelinek 2.4.90-22 +- rebuilt with latest binutils to pick up 64K -z commonpagesize + on ppc/ppc64 (#203001) + +* Tue Aug 15 2006 Jakub Jelinek 2.4.90-21 +- if some test gets stuck, kill the tee process after make check + finishes +- build with -mtune=generic on i686 and x86_64 + +* Tue Aug 15 2006 Jakub Jelinek 2.4.90-20 +- PTHREAD_PRIO_PROTECT support +- fix errno if nice() fails (#201826) + +* Thu Aug 10 2006 Jakub Jelinek 2.4.90-19 +- adaptive malloc brk/mmap threshold +- fix fchownat to use kernel syscall (if available) on many arches (#201870) +- only define O_DIRECT with -D_GNU_SOURCE on ia64 to match all + other arches (#201748) + +* Mon Aug 7 2006 Jakub Jelinek 2.4.90-18 +- NIS+ fixes +- fix memusage and xtrace scripts (#200736) +- redirect /sbin/service sshd condrestart std{out,err} to /dev/null + when executed from glibc_post_upgrade + +* Wed Aug 2 2006 Jakub Jelinek 2.4.90-17 +- typo fix for the dladdr patch +- build i?86 glibc with -mno-tls-direct-seg-refs (#200469) + +* Wed Aug 2 2006 Jakub Jelinek 2.4.90-16 +- fix dladdr on binaries/libraries with only DT_GNU_HASH and no + DT_HASH (#200635) +- fix early timeout of initgroups data in nscd (#173019) +- add am/pm display to es_PE and es_NI locales (#167101) +- fix nss_compat failures when nis/nis+ unavailable (#192072) + +* Mon Jul 31 2006 Roland McGrath 2.4.90-15 +- fix missing destructor calls in dlclose (#197932) +- enable transliteration support in all locales (#196713) +- disallow RTLD_GLOBAL flag for dlmopen in secondary namespaces (#197462) +- PI mutex support + +* Mon Jul 10 2006 Jakub Jelinek 2.4.90-13 +- DT_GNU_HASH support + +* Fri Jun 30 2006 Jakub Jelinek 2.4.90-12 +- buildrequire gettext +- enable fstatat64/newfstatat syscalls even on ppc*/s390*/ia64 (#196494) +- fix out of memory behavior in gettext (#194321) +- fix regex on multi-byte non-UTF-8 charsets (#193873) +- minor NIS+ fixes (#190803) +- don't use cancellable calls in posix_spawn* and only set{u,g}id + current thread if requested (#193631) + +* Wed May 31 2006 Jakub Jelinek 2.4.90-11 +- don't exit from nscd -i before the database is + actually invalidated, add locking to prune_cache (#191464) +- build glibc-devel.i386 static libraries with + -mno-tls-direct-seg-refs -DNO_TLS_DIRECT_SEG_REFS +- RFC3542 support (advanced API for IPv6; #191001, BZ##2693) + +* Wed May 24 2006 Jakub Jelinek 2.4.90-10 +- on i686 make glibc owner of /lib/i686 directory (#192597) +- search parent NIS+ domains (#190803) + +* Sun May 21 2006 Jakub Jelinek 2.4.90-9 +- update from CVS + - big NIS+ changes + +* Fri May 19 2006 Jakub Jelinek 2.4.90-8 +- update from CVS + - fix nss_compat when SETENT_BATCH_READ=TRUE is in /etc/default/nss + - fix RFC3484 precedence table for site-local and ULA addresses (#188364) + - fix a sunrpc memory leak + +* Thu May 11 2006 Jakub Jelinek 2.4.90-7 +- update from CVS + - fix tcgetattr (#177965) + - fix (#191264) + +* Fri May 5 2006 Jakub Jelinek 2.4.90-6 +- update from CVS +- rebuilt using fixed rpm + +* Fri May 5 2006 Jakub Jelinek 2.4.90-5 +- update from CVS + - some NIS+ fixes + - allow overriding rfc3484 address sorting tables for getaddrinfo + through /etc/gai.conf (sample config file included in %%doc directory) + +* Mon May 1 2006 Jakub Jelinek 2.4.90-4 +- update from CVS + - SETENT_BATCH_READ /etc/default/nss option for speeding up + some usages of NIS+ (#188246) + - move debug state change notification (#179208) + - fix ldd script if one of the dynamic linkers is not installed (#190259) + +* Thu Apr 27 2006 Jakub Jelinek 2.4.90-3 +- update from CVS + - fix a typo in nscd.conf (#190085) + - fix handling of SIGHUP in nscd when some caches are disabled (#189978) + - make nscd paranoia mode working with non-root server-user (#189779) + +* Wed Apr 26 2006 Jakub Jelinek 2.4.90-2 +- update from CVS + - fix getaddrinfo (#190002) + - add auto-propagate nscd.conf options (#177154) + - fix nscd auditing (#169148) + +* Tue Apr 25 2006 Jakub Jelinek 2.4.90-1 +- update from CVS + +* Mon Apr 24 2006 Jakub Jelinek 2.4-6 +- update from CVS + - NIS+ fixes + - don't segfault on too large argp key values (#189545) + - getaddrinfo fixes for RFC3484 (#188364) + +* Tue Mar 28 2006 Jakub Jelinek 2.4-5 +- update from CVS + - pshared robust mutex support + - fix btowc and bwtoc in C++ (#186410) + - fix NIS+ (#186592) + - don't declare __wcsto*l_internal for non-GCC or if not -O1+ (#185667) +- don't mention nscd failures on 2.0 kernels (#185335) + +* Tue Mar 7 2006 Roland McGrath 2.4-4 +- back up %%{ix86} gdb conflicts to < 6.3.0.0-1.111 + +* Tue Mar 7 2006 Jakub Jelinek 2.4-3 +- really fix rintl on ppc64 + +* Tue Mar 7 2006 Jakub Jelinek 2.4-2 +- accurate unwind info for lowlevellock.h stubs on %%{ix86} +- fix ppc/ppc64 ceill, floorl, rintl, roundl and truncl (BZ#2423) + +* Mon Mar 6 2006 Jakub Jelinek 2.4-1 +- update from CVS + - glibc 2.4 release + +* Mon Mar 6 2006 Jakub Jelinek 2.3.91-2 +- update from CVS + - fix sYSMALLOc for MALLOC_ALIGNMENT > 2 * SIZE_SZ (#183895) + - revert ppc32 malloc alignment patch, it breaks malloc_set_state + and needs some further thoughts and time (#183894) +- provide accurate unwind info for lowlevellock.h stubs on x86_64 + +* Thu Mar 2 2006 Jakub Jelinek 2.3.91-1 +- update from CVS + - fixes for various arches +- ensure malloc returns pointers aligned to at least + MIN (2 * sizeof (size_t), __alignof__ (long double)) + (only on ppc32 this has not been the case lately with addition + of 128-bit long double, #182742) + +* Wed Mar 1 2006 Jakub Jelinek 2.3.90-39 +- update from CVS + +* Fri Feb 17 2006 Jakub Jelinek 2.3.90-38 +- update from CVS + - robust mutexes rewrite + +* Mon Feb 13 2006 Jakub Jelinek 2.3.90-37 +- update from CVS + - *at fixes + - unshare syscall wrapper + +* Sat Feb 4 2006 Jakub Jelinek 2.3.90-36 +- update from CVS + - fix frequency setting for ITIMER_PROF (#179938, BZ#2268) + - fix powerpc inline fegetround () + - fix nptl_db (#179946) + +* Fri Feb 3 2006 Jakub Jelinek 2.3.90-35 +- update from CVS + - handle futimesat (fd, NULL, tvp) as futimes (fd, tvp) +- fix q{e,f,g}cvt{,_r} for -mlong-double-64 + +* Thu Feb 2 2006 Jakub Jelinek 2.3.90-34 +- fix with C++ and -mlong-double-64 (#179742) +- add nexttowardl redirect for -mlong-double-64 + +* Thu Feb 2 2006 Jakub Jelinek 2.3.90-33 +- update from CVS + - long double support fixes + +* Wed Feb 1 2006 Jakub Jelinek 2.3.90-32 +- update from CVS + - 128-bit long double fixes for ppc{,64}, s390{,x} and sparc{,v9}, + alpha 128-bit long double support +- add inotify syscall numbers to the override headers + (#179366) + +* Mon Jan 30 2006 Jakub Jelinek 2.3.90-31 +- update from CVS + - 128-bit long double on ppc, ppc64, s390, s390x and sparc{,v9} +- add some new syscall numbers to the override + headers + +* Mon Jan 9 2006 Jakub Jelinek 2.3.90-30 +- update from CVS + - initializer fixes for -std=c{8,9}9 on 32-bit + arches +- avoid writable .rodata (#177121) + +* Fri Jan 6 2006 Jakub Jelinek 2.3.90-29 +- update from CVS + - make pthread_mutex_t an unnamed union again, as it affects + libstdc++ ABI mangling + +* Fri Jan 6 2006 Jakub Jelinek 2.3.90-28 +- update from CVS + - make aio_suspend interruptible by signals (#171968) + +* Fri Jan 6 2006 Jakub Jelinek 2.3.90-27 +- only rely on d_type in 32-bit getdents on s390 for 2.6.11+ + +* Wed Jan 4 2006 Jakub Jelinek 2.3.90-26 +- update from CVS + - for newly linked lio_listio* callers, send per request + notifications (#170116) + - fixup nscd -S option removal changes (#176860) + - remove nonnull attribute from ctermid (#176753) + - fix PTHREAD_*_INITIALIZER{,_NP} on 64-bit arches + - SPARC NPTL support for pre-v9 CPUs +- drop support for 2.4.xx and < 2.6.9 kernels + +* Mon Jan 2 2006 Jakub Jelinek 2.3.90-25 +- update from CVS + - s390{,x} and sparc{,64} pointer mangling fixes +- install a sanitized LinuxThreads + +* Mon Jan 2 2006 Jakub Jelinek 2.3.90-24 +- update from CVS + - nscd audit changes (#174422) + - ppc{32,64} vDSO support and ppc32 hp-timing + +* Tue Dec 27 2005 Jakub Jelinek 2.3.90-23 +- update from CVS + - robust mutexes +- fix transliteration segfaults (#176573, #176583) +- ignore prelink temporaries in ldconfig (#176570) + +* Wed Dec 21 2005 Jakub Jelinek 2.3.90-22 +- update from CVS + - minor fts fixes +- revert broken _Pragma () workaround +- fix ldconfig on bi-arch architectures (#176316) + +* Tue Dec 20 2005 Jakub Jelinek 2.3.90-21 +- update from CVS + - fix pointer (de)mangling in gconv_cache.c + +* Tue Dec 20 2005 Jakub Jelinek 2.3.90-20 +- update from CVS + - time ((void *) 1) should segfault, not return -EFAULT (#174856, BZ#1952) + - fix errlist generation +- update ulps for GCC 4.1 on IA-64 + +* Mon Dec 19 2005 Jakub Jelinek 2.3.90-19 +- update from CVS + - sysdeps/generic reorg + - setjmp/longjmp jump pointer mangling +- rebuilt with GCC 4.1-RH prerelease, worked around broken _Pragma () + handling in it +- remove glibc-profile subpackage +- use non-PLT calls for malloc/free/realloc/memalign invocations in + mtrace and mcheck hooks (#175261) +- setjmp/longjmp jump pointer mangling on ppc{,64}/ia64/s390{,x} + +* Sat Nov 19 2005 Jakub Jelinek 2.3.90-18 +- update from CVS + - change for broken apps that #define const /**/, + handle non-GCC compilers + - fix ppc{32,64} strncmp (BZ#1877, #173643, IT#83510) + - provide shmatt_t typedef in ia64 2.3.90-17 +- update from CVS + - fix in C++ + - {fstat,fchown,rename,unlink}at fixes + - epoll_wait is now a cancellation point + +* Tue Nov 15 2005 Jakub Jelinek 2.3.90-16 +- update from CVS +- make sure waitid syscall is used on ppc*/s390* + +* Thu Oct 20 2005 Jakub Jelinek 2.3.90-15 +- update from CVS + - be permissive in %%n check because of kernel bug #165351 (#171240) + - don't misalign stack in pthread_once on x86_64 (#170786, IT#81521) + - many locale fixes + +* Mon Oct 10 2005 Jakub Jelinek 2.3.90-14 +- update from CVS + - fix malloc bug after fork introduced in the last update + - fix getent hosts IP for IPv4 IPs (#169831) + +* Mon Oct 3 2005 Jakub Jelinek 2.3.90-13 +- update from CVS + - fix setuid etc. hangs if some thread exits during the call (#167766) + - fix innetgr memory leak (#169051) + - support > 2GB nscd log files (#168851) + - too many other changes to list here +- include errno in nscd message if audit_open failed (#169148) + +* Mon Sep 12 2005 Jakub Jelinek 2.3.90-12 +- update from CVS + - netgrp handling fixes (#167728) + - fix memory leak in setlocale (BZ#1318) + - fix hwcaps computation + - several regex portability improvements (#167019) + - hypotf fix + - fix *printf return code if underlying write fails (BZ#1146) + - PPC64 dl{,v}sym fixes for new ABI .opd symbols +- fix calloc with MALLOC_PERTURB_ in environment on 64-bit architectures + (#166719) +- source /etc/sysconfig/nscd (if it exists) in /etc/rc.d/init.d/nscd + (#167083) +- add %%triggerin for tzdata to glibc-common, so that tzdata updates + update /etc/localtime and /var/spool/postfix/etc/localtime if they + exist (#167787) + +* Mon Aug 29 2005 Jakub Jelinek 2.3.90-11 +- FUTEX_WAKE_OP support to speed up pthread_cond_signal + +* Wed Aug 24 2005 Jakub Jelinek 2.3.90-10 +- update from CVS + - fix growing of nscd persistent database (BZ#1204) + - fix _FORTIFY_SOURCE mbstowcs and wcstombs if destination size + is known at compile time, but length argument is not + +* Mon Aug 22 2005 Jakub Jelinek 2.3.90-9 +- update from CVS + - fix resolving over TCP (#161181, #165802) + - on ia64 don't abort on unhandled math function exception codes + (#165693) + +* Mon Aug 8 2005 Jakub Jelinek 2.3.90-8 +- update from CVS + - nscd persistent database verifier (#164001) + - cleanup _FORTIFY_SOURCE bits/*.h headers (#165000) + - handle EINTR in sigwait properly +- make sure poor man's stack guard randomization keeps first + byte 0 even on big-endian 32-bit arches +- fix {elf,nptl}/tst-stackguard1 +- obsolete linuxthreads-devel in glibc-devel + +* Fri Jul 29 2005 Jakub Jelinek 2.3.90-7 +- update from CVS +- do some poor man's stack guard randomization even without + the costly --enable-stackguard-randomization +- rebuilt with new GCC to make it use -msecure-plt on PPC32 + +* Mon Jul 25 2005 Jakub Jelinek 2.3.90-6 +- update from CVS + - fix execvp if PATH is not in environment and the call is going + to fail (BZ#1125) + - another bits/wchar2.h fix (#163990) + +* Fri Jul 22 2005 Jakub Jelinek 2.3.90-5 +- update from CVS + - fix stubs.h generation +- don't use _G_va_list in bits/wchar2.h + +* Fri Jul 22 2005 Jakub Jelinek 2.3.90-4 +- update from CVS + - make sure bits/wchar2.h header is installed + - fix __getgroups_chk return type + +* Thu Jul 21 2005 Jakub Jelinek 2.3.90-3 +- update from CVS + - make sure nscd cmsg buffers aren't misaligned, handle EINTR from + poll when contacting nscd more gracefully + - remove malloc attribute from posix_memalign + - correctly size nscd buffer for grpcache key (#163538) + - fix atan2f + - fix error memory leaks + - some more _FORTIFY_SOURCE protection + +* Fri Jul 8 2005 Jakub Jelinek 2.3.90-2 +- update from CVS + - ia64 stack protector support + - handle DNS referral results as server errors (#162625) + - ctan{,h}{,f,l} fixes (#160759) + - pass argc, argv and envp also to executable's *ni_array + functions (BZ#974) + - add ellipsis to clone prototype (#161593) + - fix glibc-profile (#162601) + - nss_compat fixes +- use sysdeps/generic version of in installed + headers instead of NPTL version (#162634) + +* Mon Jun 27 2005 Jakub Jelinek 2.3.90-1 +- update from CVS + - stack protector support + - fix xdr_{,u_}{longlong_t,hyper} on 64-bit arches (#161583) +- enable @GLIBC_2.4 symbols +- remove linuxthreads + +* Mon Jun 20 2005 Jakub Jelinek 2.3.5-11 +- update from CVS + - PPC32 -msecure-plt support + - support classes keyword in /etc/hesiod.conf (#150350) + - add RLIMIT_NICE and RLIMIT_RTPRIO to (#157049) + - decrease number of .plt relocations in libc.so + - use -laudit in nscd (#159217) + - handle big amounts of networking interfaces in getifaddrs/if_nameindex + (#159399) + - fix pa_IN locale's am_pm (#158715, BZ#622) + - fix debugging of PIEs + +* Mon May 30 2005 Jakub Jelinek 2.3.5-10 +- fix LD_ASSUME_KERNEL (since 2.3.5-8 GLRO(dl_osversion) + has been always overwritten with the version of currently + running kernel) +- remove linuxthreads man pages other than those covered in + 3p section, as 3p man pages are far better quality and describe + POSIX behaviour that NPTL implements (#159084) + +* Tue May 24 2005 Jakub Jelinek 2.3.5-9 +- update from CVS + - increase bindresvport's LOWPORT to 512, apparently some + broken daemons don't think 0 .. 511 ports are reserved + +* Mon May 23 2005 Jakub Jelinek 2.3.5-8 +- update from CVS + - fix kernel version check in ld.so +- fix sendfile{,64} prototypes (BZ#961) +- try more ports in bindresvport if all 600..1023 are + used, don't use priviledged ports when talking to portmap + (#141773) + +* Fri May 20 2005 Jakub Jelinek 2.3.5-7 +- update from CVS + - make regexec thread safe (BZ#934) +- fix statically linked programs on i?86, x86_64, s390* and + sparc* (#158027) +- fix IBM939 iconv module (BZ#955) + +* Wed May 4 2005 Jakub Jelinek 2.3.5-6 +- update from CVS + - fix cancellation on i?86 + - add call frame information to i?86 assembly + +* Tue May 3 2005 Jakub Jelinek 2.3.5-5 +- update from CVS + - add some more UTF-8 locales (#156115) +- clean up /lib64/tls instead of /lib/tls on x86-64, s390x and + ppc64 in glibc_post_upgrade (#156656) +- fix posix_fallocate{,64} (#156289) + +* Thu Apr 28 2005 Jakub Jelinek 2.3.5-4 +- update from CVS + - fix nscd cache pruning (#150748) + +* Wed Apr 27 2005 Jakub Jelinek 2.3.5-3 +- update from CVS + - fix linuxthreads clocks +- put xen libs into the glibc-2*.i686 package instead of a separate one +- fix librt.so symlink in linuxthreads-devel +- do not include linuxthreads-devel on %%{auxarches}, + just on the base architectures + +* Wed Apr 27 2005 Jakub Jelinek 2.3.5-2 +- update from CVS + - with MALLOC_CHECK_=N N>0 (#153003) + - fix recursive dlclose (#154641) + - handle %%z in strptime (#154804) + - automatically append /%%{_lib}/obsolete/linuxthreads/ + to standard library search path if LD_ASSUME_KERNEL=N N <= 2.4.19 + or for glibc 2.0 binaries (or broken ones that don't use errno/h_errno + properly). Warning: all those will stop working when LinuxThreads + is finally nuked, which is not very far away + - remove nonnull attribute from acct prototype (BZ#877) + - kernel CPU clocks support + - fix *scanf in locales with multi-byte decimal point + +* Wed Apr 27 2005 Roland McGrath +- glibc-xen subpackage for i686 + +* Fri Apr 15 2005 Roland McGrath 2.3.5-1 +- update from CVS + - fix execvp regression (BZ#851) + - ia64 libm updates + - sparc updates + - fix initstate{,_r}/strfry (#154504) + - grok PT_NOTE in vDSO for kernel version and extra hwcap dirs, + support "hwcap" keyword in ld.so.conf files + +* Tue Apr 5 2005 Jakub Jelinek 2.3.4-21 +- update from CVS + - fix xdr_rmtcall_args on 64-bit arches (#151686) +- fix and with -std=c89 -fexceptions (#153774) + +* Mon Apr 4 2005 Jakub Jelinek 2.3.4-20 +- move LinuxThreads libraries to /%%{_lib}/obsolete/linuxthreads/ + and NPTL libraries to /%%{_lib}. To run a program against LinuxThreads, + LD_ASSUME_KERNEL=2.4.xx LD_LIBRARY_PATH=/%%{_lib}/obsolete/linuxthreads/ + is now needed +- bzip2 ChangeLog* files instead of gzipping them + +* Sat Apr 2 2005 Jakub Jelinek 2.3.4-19 +- update from CVS + - fix nextafterl and several other libm routines on ia64 + - fix initgroups (BZ#661) +- kill nptl-devel subpackage, add linuxthreads-devel, + compile and link by default against NPTL and only with + -I/usr/include/linuxthreads -L/usr/%%{_lib}/linuxthreads + against LinuxThreads +- package /usr/lib/debug/%%{_lib}/tls/i{5,6}86 symlinks in + i386 glibc-debuginfo +- limit number of ChangeLog* files in glibc-common %%doc + to last 2.5 years of changes only to save space + +* Fri Mar 25 2005 Jakub Jelinek 2.3.4-18 +- fix build on 64-bit arches with new GCC + +* Thu Mar 24 2005 Jakub Jelinek 2.3.4-17 +- update from CVS + - fix LD_AUDIT in LinuxThreads ld.so + - fix calloc with M_PERTURB + - fix error handling in pthread_create with PTHREAD_EXPLICIT_SCHED + on ppc*/ia64/alpha/mips (BZ#801) + - fix a typo in WINDOWS-31J charmap (#151739) + - fix NIS ypprot_err (#151469) + +* Sun Mar 20 2005 Jakub Jelinek 2.3.4-16 +- fix pread with -D_FILE_OFFSET_BITS=64 (#151573) + +* Sat Mar 19 2005 Jakub Jelinek 2.3.4-15 +- update from CVS + - better fix for the dlclose bug (#145810, #150414) + - fix regex crash on case insensitive search in zh_CN locale + (#151215) + - fix malloc_trim (BZ#779) + - with -D_FORTIFY_SOURCE=*, avoid defining read and a bunch of others + as function-like macros, there are too many broken programs + out there +- add %%dir %%{_prefix}/%%{_lib}/gconv to glibc's file list (#151372) + +* Sun Mar 6 2005 Roland McGrath 2.3.4-14 +- fix bits/socket2.h macro typos + +* Sat Mar 5 2005 Jakub Jelinek 2.3.4-12 +- fix tst-chk{2,3} +- fix up AS_NEEDED directive in /usr/%%{_lib}/libc.so +- BuildReq binutils >= 2.15.94.0.2-1 for AS_NEEDED, in + glibc-devel Conflict with binutils < 2.15.94.0.2-1 + +* Thu Mar 3 2005 Jakub Jelinek 2.3.4-11 +- update from CVS + - fix execvp (#149290) + - fix dlclose (#145810) + - clear padding in gconv-modules.cache (#146614, BZ#776) +- rebuilt with GCC4 +- changed __GLIBC_MINOR__ for now back to 3 +- back out the newly added GLIBC_2.4 *_chk routines, instead + do the checking in macros + +* Sat Feb 12 2005 Jakub Jelinek 2.3.4-10 +- hopefully fix interaction with prelink (#147655) + +* Fri Feb 11 2005 Jakub Jelinek 2.3.4-9 +- update from CVS + - bi-arch (BZ#715) + +* Fri Feb 11 2005 Jakub Jelinek 2.3.4-8 +- update from CVS + - bi-arch (BZ#632) + - fix libdl on s390 and maybe other platforms + - fix initstate{,_r} (BZ#710) + - fix generation (BZ#157) +- define CMSPAR in bits/termios.h (#147533) + +* Tue Feb 8 2005 Jakub Jelinek 2.3.4-7 +- update from CVS + - fix TLS handling in linuxthreads + +* Tue Feb 8 2005 Jakub Jelinek 2.3.4-6 +- update from CVS + - ld.so auditing + - fix segfault if chrooted app attempts to dlopen a library + and no standard library directory exists at all (#147067, #144303) + - fix initgroups when nscd is running, but has group caching disabled + (#146588) + - fix pthread_key_{create,destroy} in LinuxThreads when pthread_create + has not been called yet (#146710) + - fix ppc64 swapcontext and setcontext (#146736, BZ#700) + - service nscd cosmetic fixes (#146776) + - fix IA-32 and x86-64 stack alignment in DSO constructors (#145689) + - fix zdump -v segfaults on x86-64 (#146210) + - avoid calling sigaction (SIGPIPE, ...) inside syslog (#146021, IT#56686) + - fix errno values for futimes (BZ#633) + - unconditionally include in malloc.h (BZ#650) + - change regex \B handling to match old GNU regex as well as perl/grep's dfa + (from empty string inside of word to empty string not at a word boundary, + BZ#693) + - slightly optimize i686 TLS accesses, use direct TLS %%gs access in sem_* + and allow building -mno-tls-direct-seg-refs glibc that is free of direct TLS + %%gs access with negative offsets + - fix addseverity + - fix fmemopen + - fix rewinddir + - increase svc{tcp,unix}_create listen backlog + +* Thu Jan 6 2005 Jakub Jelinek 2.3.4-5 +- update from CVS + - add some warn_unused_result marking + - make ftruncate available even for just -D_POSIX_C_SOURCE=200112L + (BZ#640) + +* Thu Jan 6 2005 Jakub Jelinek 2.3.4-4 +- update from CVS + - fix IA-32 stack alignment for LinuxThreads thread functions + and functions passed to clone(2) directly + - fix ecvt{,_r} on denormals (#143279) + - fix __tls_get_addr typo + - fix rounding in IA-64 alarm (#143710) + - don't reinitialize __environ in __libc_start_main, so that + effects of setenv/putenv done in DSO initializers are preserved + (#144037, IT#57403) + - fix fmemopen + - fix vDSO l_map_end and l_text_end values + - IA64 libm update (#142494) +- fix ppc rint/ceil etc. (BZ#602) + +* Tue Dec 21 2004 Jakub Jelinek 2.3.4-3 +- rebuilt + +* Mon Dec 20 2004 Jakub Jelinek 2.3.4-2 +- work around rpm bug some more, this time by copying + iconvconfig to iconvconfig.%%{_target_cpu}. + +* Mon Dec 20 2004 Jakub Jelinek 2.3.4-1 +- update from CVS + - glibc 2.3.4 release + - add -o and --nostdlib options to iconvconfig +- if /sbin/ldconfig doesn't exist when running + glibc_post_upgrade.%%{_target_cpu}, just don't attempt to run it. + This can happen during first install of bi-arch glibc and the + other arch glibc's %%post wil run /sbin/ldconfig (#143326) +- use -o and --nostdlib options to create all needed + gconv-modules.cache files on bi-arch setups + +* Sun Dec 19 2004 Jakub Jelinek 2.3.3-99 +- rebuilt + +* Sat Dec 18 2004 Jakub Jelinek 2.3.3-98 +- add .%%{_target_cpu} to glibc_post_upgrade, only run telinit u + if /sbin/init is the same ELF class and machine as + glibc_post_upgrade.%%{_target_cpu} and similarly with + condrestarting sshd (#143046) + +* Fri Dec 17 2004 Jakub Jelinek 2.3.3-97 +- update from CVS + - fix ppc64 getcontext and swapcontext (BZ#610) + - sparc/sparc64 fixes + +* Wed Dec 15 2004 Jakub Jelinek 2.3.3-96 +- update from CVS + - fix i686 __USE_STRING_INLINES strncat + - make sure ppc/ppc64 maintain correct stack alignment + across clone + +* Wed Dec 15 2004 Jakub Jelinek 2.3.3-95 +- export nis_domain_of_r from libnsl.so again which was + unintentionally lost + +* Wed Dec 15 2004 Jakub Jelinek 2.3.3-93 +- update from CVS + - ppc/ppc64 clone without CLONE_THREAD getpid () adjustement + - fix MALLOC_CHECK_={1,2,3} for non-contiguous main arena + (BZ#457) + - fix sysconf (_POSIX_V6_*) for other ABI environments in + bi-arch setups +- s390/s390x clone without CLONE_THREAD getpid () adjustement + +* Tue Dec 14 2004 Jakub Jelinek 2.3.3-92 +- update from CVS +- fix %%{_prefix}/libexec/getconf filenames generation + +* Tue Dec 14 2004 Jakub Jelinek 2.3.3-91 +- update from CVS + - double buffer size in getXXbyYY or getXXent on ERANGE + instead of adding BUFLEN (#142617) + - avoid busy loop in malloc if another thread is doing fork + (#142214) + - some more realloc corruption checks + - fix getconf _POSIX_V6_WIDTH_RESTRICTED_ENVS output, + tweak %%{_prefix}/libexec/getconf/ filenames + +* Fri Dec 10 2004 Jakub Jelinek 2.3.3-90 +- update from CVS + - regex speedups + - use | cat in ldd if running under bash3+ to allow running + it on binaries that are not through SELinux allowed to access + console or tty +- add __NR_waitid defines for alpha and ia64 + +* Wed Dec 8 2004 Jakub Jelinek 2.3.3-89 +- update from CVS + - fix clone2 on ia64 + - avoid tst-timer5 failing with linuxthreads implementation +- if __libc_enable_secure, disallow mode != normal +- change ldd script to imply -r when -u is used, properly + propagate return value and handle suid binaries + +* Tue Dec 7 2004 Jakub Jelinek 2.3.3-88 +- update from CVS + - disregard LD_SHOW_AUXV and LD_DYNAMIC_WEAK if __libc_enable_secure + - disregard LD_DEBUG if __libc_enable_secure in normal mode + if /suid-debug doesn't exist + - fix fseekpos after ungetc + - avoid reading bytes before start of buffers in regex's + check_dst_limits_calc_pos_1 (#142060) + - make getpid () working with clone/clone2 without CLONE_THREAD + (so far on i386/x86_64/ia64 only) +- move %%{_prefix}/libexec/getconf/* to glibc from glibc-common +- make %%{_prefix}/libexec/getconf directory owned by glibc package + +* Fri Dec 3 2004 Jakub Jelinek 2.3.3-87 +- update from CVS + - build libpthread_nonshared.a objects with -fPIC on s390/s390x + - fix mktime with < 0 or > 59 tm_sec on entry + - remove nonnull attribute for realpath + - add $(make-target-directory) for errlist-compat.c rule + (hopefully fix #141404) +- add testcase for ungetc bug +- define _POSIX_{,THREAD_}CPUTIME to 0 on all Linux arches + +* Tue Nov 30 2004 Jakub Jelinek 2.3.3-86 +- update from CVS + - some posix_opt.h fixes +- fix strtold use of unitialized memory (#141000) +- some more bugfixes for bugs detected by valgrind +- rebuilt with GCC >= 3.4.3-5 to avoid packed stack layout + on s390{,x} (#139678) + +* Fri Nov 26 2004 Jakub Jelinek 2.3.3-85 +- update from CVS + - support -v specification in getconf + - fix sysconf (_SC_LFS64_CFLAGS) etc. + - avoid thread stack aliasing issues on EM64T (#140803) +- move %%{_prefix}/include/nptl headers from nptl-devel + to glibc-headers, so that even NPTL specific programs + can be built bi-arch without problems + +* Wed Nov 24 2004 Jakub Jelinek 2.3.3-84 +- update from CVS + - fix memory leak in getaddrinfo if using nscd (#139559) + - handle large lines in /etc/hosts and /etc/networks + (#140378) + - add nonnull attributes to selected dirent.h and dlfcn.h + functions + +* Sun Nov 21 2004 Jakub Jelinek 2.3.3-83 +- update from CVS + - add deprecated and/or nonnull attribute to some signal.h + functions + - speed up tzset () by only using stat instead of open/fstat + when calling tzset for the second and following time if + /etc/localtime has not changed +- fix tgamma (BZ #552) + +* Sat Nov 20 2004 Jakub Jelinek 2.3.3-82 +- update from CVS + - some malloc () checking + - libpthread.a object dependency cleanups (#115157) + - fix for -std=c89 -pedantic-errors (#140132) + +* Fri Nov 19 2004 Jakub Jelinek 2.3.3-81 +- don't use chunksize in <= 2 * SIZE_SZ free () checks + +* Fri Nov 19 2004 Jakub Jelinek 2.3.3-80 +- update from CVS + - with -D_FORTIFY_SOURCE=2, prevent missing %%N$ formats + - for -D_FORTIFY_SOURCE=2 and %%n in writable format string, + issue special error message instead of using the buffer overflow + detected one + - speedup regex searching with REG_NOSUB, add RE_NO_SUB, + speedup searching with nested subexps (BZ #544) + - block SIGCANCEL in NPTL timer_* helper thread +- further free () checking + +* Tue Nov 16 2004 Jakub Jelinek 2.3.3-79 +- update from CVS +- fix free () checking +- move /etc/default/nss into glibc-common (hopefully fix #132392) + +* Mon Nov 15 2004 Jakub Jelinek 2.3.3-78 +- update from CVS + - fix LD_DEBUG=statistics + - issue error message before aborting in __chk_fail () +- some more free () checking + +* Fri Nov 12 2004 Jakub Jelinek 2.3.3-77 +- update from CVS + - speedup regex on palindromes (BZ #429) + - fix NPTL set{,e,re,res}[ug]id, so that even if making process + less priviledged all threads change their credentials successfully + +* Wed Nov 10 2004 Jakub Jelinek 2.3.3-76 +- update from CVS + - fix regcomp crash (#138439) + - fix ftell{,o,o64} (#137885) + - robustification of nscd to cope with corrupt databases (#137140) + - fix NPTL with pthread_exit immediately after pthread_create (BZ #530) + - some regex optimizations + +* Tue Nov 2 2004 Jakub Jelinek 2.3.3-75 +- update from CVS + - mktime cleanups (BZ #487, #473) + - unique comments in free(3) check error messages +- adjust some x86_64 headers for -m32 (#129712) +- object size checking support even with GCC-3.4.2-RH >= 3.4.2-8 + +* Wed Oct 27 2004 Jakub Jelinek 2.3.3-74 +- fix header +- fix globfree (#137176) +- fix exiting if there are dlmopened libraries in namespaces + other than main one not closed yet +- export again _res_opcodes and __p_{class,type}_syms from + libresolv.so that were lost in -69 + +* Thu Oct 21 2004 Jakub Jelinek 2.3.3-73 +- remove setaltroot and key{_add,_request,ctl} also from Versions +- back out _sys_errlist changes + +* Thu Oct 21 2004 Jakub Jelinek 2.3.3-72 +- back out setaltroot and key{_add,_request,ctl} addition +- fix severe x86-64 symbol versioning regressions that breaks + e.g. java binaries + +* Wed Oct 20 2004 Jakub Jelinek 2.3.3-71 +- update from CVS + - fix minor catchsegv temp file handling vulnerability + (CAN-2004-0968, #136319) + - add 4 new errno codes + - setaltroot, key{_add,_request,ctl} syscalls on some arches + - export _dl_debug_state@GLIBC_PRIVATE from ld.so again for + gdb purpose + - use inet_pton to decide what is address and what is hostname + in getent (#135422) + - change dladdr/dladdr1, so that dli_saddr is the same kind + of value as dlsym/dlvsym return (makes difference on ia64/hppa only) + - fix catchsegv script so that it works with both 32-bit and 64-bit + programs on multi-arch platforms + +* Tue Oct 19 2004 Jakub Jelinek 2.3.3-70 +- update from CVS +- require newer selinux-policy (#135978) +- add %%dir for /var/run/nscd and /var/db/nscd and %%ghost + files in it +- conflict with gcc4 4.0.0-0.6 and earlier (needs __builtin_object_size) + +* Mon Oct 18 2004 Jakub Jelinek 2.3.3-69 +- update from CVS + - object size checking support (-D_FORTIFY_SOURCE={1,2}) + +* Thu Oct 14 2004 Jakub Jelinek 2.3.3-68 +- update from CVS + - support for namespaces in the dynamic linker + - fix dlclose (BZ #77) + - libSegFault.so uses now backtrace() to work on IA-64, x86-64 + and s390 (#130254) + +* Tue Oct 12 2004 Jakub Jelinek 2.3.3-67 +- update from CVS + - use non-blocking sockets in resolver (#135234) + - reset pd->res options on thread exit, so that threads + reusing cached stacks get resolver state properly initialized + (BZ #434) + +* Wed Oct 6 2004 Jakub Jelinek 2.3.3-66 +- update from CVS +- avoid using perl in the spec file, buildrequire sed >= 3.95 + (#127671) +- export TIMEOUTFACTOR=16 +- fix _JMPBUF_CFA_UNWINDS_ADJ on s390{,x} + +* Tue Oct 5 2004 Jakub Jelinek 2.3.3-65 +- update from CVS + - define _POSIX_THREAD_PROCESS_SHARED and _POSIX_CLOCK_SELECTION + to -1 in LinuxThreads + - define _POSIX_CPUTIME and _POSIX_THREAD_CPUTIME to 0 + on i?86/ia64 and make sure sysconf (_SC_{,THREAD_}CPUTIME) + returns correct value +- if _POSIX_CLOCK_SELECTION == -1 in nscd, still try + sysconf (_SC_CLOCK_SELECTION) and if it returns true, + dlopen libpthread.so and dlsym pthread_condattr_setclock +- build nscd with -z relro and -z now + +* Mon Oct 4 2004 Jakub Jelinek 2.3.3-64 +- update from CVS + - stop using __builtin_expect in assert and assert_perror + (#127606) + - try to avoid too much VA fragmentation with malloc + on flexmap layout (#118574) + - nscd robustification + - change valloc to use debugging hooks (#134385) +- make glibc_post_upgrade more verbose on errors (Fergal Daly, + #125700) + +* Fri Oct 1 2004 Jakub Jelinek 2.3.3-63 +- update from CVS + - fix __nscd_getgrouplist + - fix a typo in x86_64 pthread_mutex_timedwait fix + +* Fri Oct 1 2004 Jakub Jelinek 2.3.3-62 +- update from CVS + - fix NPTL pthread_mutex_timedwait on i386/x86_64 (BZ #417) + +* Thu Sep 30 2004 Jakub Jelinek 2.3.3-61 +- update from CVS + - some nscd fixes (#134193) + - cache initgroups in nscd (#132850) + - reread /etc/localtime in tzset () even if just mtime changed + (#133481) + - fix glob (#126460) + - another get_myaddress fix + +* Wed Sep 29 2004 Jakub Jelinek 2.3.3-60 +- update from CVS + - fix get_myaddress (#133982) + - remove nonnull attribute from second utime argument (#133866) + - handle SIGSETXID the same way as SIGCANCEL in + sigaction/pthread_kill/sigwait/sigwaitinfo etc. + - add __extension__ to long long types in NPTL + +* Mon Sep 27 2004 Jakub Jelinek 2.3.3-59 +- update from CVS + - fix BZ #151, #362, #381, #407 + - fdim fix for +inf/+inf (BZ #376) + +* Sun Sep 26 2004 Jakub Jelinek 2.3.3-58 +- update from CVS + - vasprintf fix (BZ #346) + - gettext locking (BZ #322) +- change linuxthreads useldt.h inclusion login again, the last + one failed all linuxthreads FLOATING_STACKS tests + +* Sat Sep 25 2004 Jakub Jelinek 2.3.3-57 +- update from CVS + - fix setuid in LD_ASSUME_KERNEL=2.2.5 libc (#133558) + - fix nis locking (#132204) + - RTLD_DEEPBIND support + - fix pthread_create bugs (BZ #401, #405) + +* Wed Sep 22 2004 Roland McGrath 2.3.3-56 +- migrated CVS to fedora-branch in sources.redhat.com glibc repository + - source tarballs renamed + - redhat/ moved to fedora/, some old cruft removed +- update from trunk + - some __nonnull annotations + +* Wed Sep 22 2004 Jakub Jelinek 2.3.3-55 +- update from CVS + - set{re,e,res}[ug]id now affect the whole process in NPTL + - return EAGAIN instead of ENOMEM when not enough memory + in pthread_create + +* Fri Sep 17 2004 Jakub Jelinek 2.3.3-54 +- update from CVS + - nscd getaddrinfo caching + +* Tue Sep 14 2004 Jakub Jelinek 2.3.3-53 +- restore temporarily old definition of __P()/__PMT() + for third party apps + +* Tue Sep 14 2004 Jakub Jelinek 2.3.3-52 +- update from CVS + - nscd bi-arch fix + - remove all uses of __P()/__PMT() from glibc headers +- update and reenable nscd SELinux patch +- remove libnss1* and libnss*.so.1 compatibility NSS modules + on IA-32, SPARC and Alpha + +* Fri Sep 10 2004 Jakub Jelinek 2.3.3-51 +- update from CVS + - disable one of the malloc double free checks for non-contiguous + arenas where it doesn't have to be true even for non-broken + apps + +* Thu Sep 9 2004 Jakub Jelinek 2.3.3-50 +- update from CVS + - pwd/grp/host loops with nscd speed up by sharing the + nscd cache r/o with applications + - inexpensive double free check in free(3) + - make NPTL pthread.h initializers usable even from C++ + (BZ #375) +- use atomic instructions even in i386 nscd on i486+ CPUs + (conditionally) + +* Fri Sep 3 2004 Jakub Jelinek 2.3.3-49 +- update from CVS +- fix linuxthreads tst-cancel{[45],-static} + +* Fri Sep 3 2004 Jakub Jelinek 2.3.3-48 +- update from CVS + - fix pthread_cond_destroy (BZ #342) + - fix fnmatch without FNM_NOESCAPE (BZ #361) + - fix ppc32 setcontext (BZ #357) +- add NPTL support for i386 glibc (only if run on i486 or higher CPU) +- add __NR_waitid defines for i386, x86_64 and sparc* + +* Tue Aug 31 2004 Jakub Jelinek 2.3.3-47 +- update from CVS + - persistent nscd caching + - ppc64 32-bit atomicity fix + - fix x86-64 nptl-devel headers for -m32 compilation +- %%ghost /etc/ld.so.cache (#130597) +- edit /etc/ld.so.conf in glibc_post_upgrade if + include ld.so.conf.d/*.conf line is missing (#120588) +- ugly hacks for the IA-64 /emul braindamage (#124996, #128267) + +* Sat Aug 21 2004 Jakub Jelinek 2.3.3-46 +- update from CVS + +* Thu Aug 19 2004 Jakub Jelinek 2.3.3-45 +- update from CVS + - fix nss_compat's initgroups handling (#130363) + - fix getaddrinfo ai_canonname setting + +* Thu Aug 19 2004 Jakub Jelinek 2.3.3-44 +- update from CVS + - add ip6-dotint resolv.conf option, make + no-ip6-dotint the default +- BuildPrereq libselinux-devel (#129946) +- on ppc64, build without dot symbols + +* Thu Aug 12 2004 Jakub Jelinek 2.3.3-43 +- update from CVS + - remove debugging printout (#129747) + - make usable in C++ (IT#45148) +- update RLIMIT_* constants in , make + POSIX compliant (#129740) + +* Wed Aug 11 2004 Jakub Jelinek 2.3.3-42 +- fix last tzset () fixes, disable rereading of /etc/localtime + every time for now +- really enable SELinux support for NSCD + +* Wed Aug 11 2004 Jakub Jelinek 2.3.3-41 +- update from CVS + - fread_unlocked/fwrite_unlocked macro fixes (BZ #309, #316) + - tzset () fixes (BZ #154) +- speed up pthread_rwlock_unlock on arches other than i386 and + x86_64 (#129455) +- fix compilation with -ansi (resp. -std=c89 or -std=c99) and + -D_XOPEN_SOURCE=[56]00 but no -D_POSIX_SOURCE* or -D_POSIX_C_SOURCE* + (BZ #284) +- add SELinux support for NSCD + +* Fri Aug 6 2004 Jakub Jelinek 2.3.3-40 +- update from CVS + - change res_init to force all threads to re-initialize + resolver before they use it next time (#125712) + - various getaddrinfo and related fixes (BZ #295, #296) + - fix IBM{932,943} iconv modules (#128674) + - some nscd fixes (e.g. BZ #292) + - RFC 3678 support (Multicast Source Filters) +- handle /lib/i686/librtkaio-* in i386 glibc_post_upgrade + the same as /lib/i686/librt-* + +* Fri Jul 23 2004 Jakub Jelinek 2.3.3-39 +- update from CVS + - conformance related changes in headers +- remove -finline-limit=2000 for GCC 3.4.x+ + +* Thu Jul 22 2004 Jakub Jelinek 2.3.3-38 +- update from CVS + - fix res_init leaks + - fix newlocale races + - fix ppc64 setjmp +- fix strtold (BZ #274) + +* Fri Jul 16 2004 Jakub Jelinek 2.3.3-37 +- update from CVS + - allow pthread_cancel in DSO destructors run at exit time +- fix pow{f,,l} on IA-32 and powl on x86-64 +- allow PIEs on IA-32 to have main in a shared library they depend on + +* Mon Jul 5 2004 Jakub Jelinek 2.3.3-36 +- s390* .plt slot reduction +- fix pthread_rwlock_timedrdlock on x86_64 + +* Wed Jun 30 2004 Jakub Jelinek 2.3.3-35 +- tweak spec file for the libpthread-0.61.so -> libpthread-2.3.3.so + NPTL changes + +* Wed Jun 30 2004 Jakub Jelinek 2.3.3-34 +- update from CVS + - if_nameindex using preferably netlink + - printf_parsemb initialization fix + - NPTL version is now the same as glibc version + +* Mon Jun 28 2004 Jakub Jelinek 2.3.3-33 +- update from CVS + - reread resolv.conf for nscd --invalidate=hosts + - fix F_GETLK/F_SETLK/F_SETLKW constants on x86_64 for + -m32 -D_FILE_OFFSET_BITS=64 compilations + - avoid calling non-existing fcntl64 syscall on ppc64 + +* Mon Jun 14 2004 Jakub Jelinek 2.3.3-32 +- update from CVS + - FUTEX_CMP_REQUEUE support (fix pthread_cond_* deadlocks) + - fix backtrace in statically linked programs +- rebuilt with GCC 3.4, adjusted ulps and i386 + +* Fri May 28 2004 Jakub Jelinek 2.3.3-31 +- update from CVS +- and changes for GCC 3.{2,4,5}+ +- make c_stubs buildable even with GCC 3.2.x (#123042) + +* Fri May 21 2004 Jakub Jelinek 2.3.3-30 +- fix pthread_cond_wait on architectures other than IA-32 and + x86_64 + +* Thu May 20 2004 Jakub Jelinek 2.3.3-29 +- use lib64 instead of lib on ia64 if %%{_lib} is defined to lib64 + +* Wed May 19 2004 Jakub Jelinek 2.3.3-28 +- update from CVS + - FUTEX_REQUEUE fixes (#115349) + - SPARC GCC 3.4 build fix + - fix handling of undefined TLS symbols on IA32 (RELA only), + SPARC and SH + - regex translate fix + - speed up sprintf + - x86_64 makecontext alignment fix + - make POSIX sigpause the default sigpause, unless BSD sigpause + requested + +* Tue May 11 2004 Jakub Jelinek 2.3.3-27 +- remove /lib64/tls/librtkaio-2.3.[23].so in glibc_post_upgrade + on x86-64, s390x and ppc64 instead of /lib/tls/librtkaio-2.3.[23].so +- build mq_{send,receive} with -fexceptions + +* Fri May 7 2004 Jakub Jelinek 2.3.3-26 +- update from CVS + - fix + - fix memory leaks in nis, getifaddrs, etc. caused by incorrect + use of realloc +- remove /lib/{tls,i686}/librtkaio-2.3.[23].so in glibc_post_upgrade + and rerun ldconfig if needed, otherwise after glibc upgrade librt.so.1 + might be a stale symlink + +* Wed May 5 2004 Jakub Jelinek 2.3.3-25 +- update from CVS +- disable FUTEX_REQUEUE (work around #115349) +- mq for sparc/sparc64/ia64 + +* Tue May 4 2004 Jakub Jelinek 2.3.3-24 +- update from CVS + - define S_ISSOCK in -D_XOPEN_SOURCE=600 and S_I[FS]SOCK + plus F_[SG]ETOWN also in -D_XOPEN_SOURCE=500 (both + included already in XNS5) + - reorder dlopen checks, so that dlopening ET_REL objects + complains about != ET_DYN != ET_EXEC, not about phentsize + (#121606) + - fix strpbrk macro for GCC 3.4+ (BZ #130) + - fix (BZ #140) + - sched_[gs]etaffinity documentation fix (BZ #131) + - fix sparc64 build (BZ #139) + - change linuxthreads back to use non-cancellable writes + to manager pipes etc. + - fix sem_timedwait return value in linuxthreads (BZ #133) + - ia64 unnecessary PLT relocs removal + +* Thu Apr 22 2004 Jakub Jelinek 2.3.3-23 +- update from CVS + - fix *scanf + - fix shm_unlink, sem_unlink and mq_unlink errno values + - avoid memory leaks in error + - execstack fixes on s390 + +* Mon Apr 19 2004 Jakub Jelinek 2.3.3-22 +- update from CVS + - mq and timer fixes +- rebuilt with binutils >= 2.15.90.0.3-2 to fix IA-64 statically + linked binaries +- fix linuxthreads librt.so on s390{,x}, so it is no longer DT_TEXTREL + +* Sat Apr 17 2004 Jakub Jelinek 2.3.3-21 +- disable rtkaio +- update from CVS + - POSIX message passing support + - fixed SIGEV_THREAD support for POSIX timers + - fix free on non-malloced memory in syslog + - fix ffsl on some 64-bit arches + - fix sched_setaffinity on x86-64, ia64 + - fix ppc64 umount + - NETID_AUTHORITATIVE, SERVICES_AUTHORITATIVE support + - various NIS speedups + - fix fwrite with > 2GB sizes on 64-bit arches + - fix pthread_getattr_np guardsize reporting in NPTL +- report PLT relocations in ld.so and libc.so during the build + +* Thu Mar 25 2004 Jakub Jelinek 2.3.3-20 +- update from CVS + - change NPTL PTHREAD_MUTEX_ADAPTIVE_NP mutexes to spin on SMP + - strtol speed optimization + - don't try to use certainly unimplemented syscalls on ppc64 +- kill -debug subpackage, move the libs to glibc-debuginfo{,-common} + into /usr/lib/debug/usr/%%{_lib}/ directory +- fix c_stubs with gcc 3.4 +- move all the up to 3 builds into %%build scriptlet and + leave only installation in the %%install scriptlet + +* Mon Mar 22 2004 Jakub Jelinek 2.3.3-19 +- update from CVS + - affinity API changes + +* Thu Mar 18 2004 Jakub Jelinek 2.3.3-18 +- update from CVS + - fix ia64 iopl (#118591) + - add support for /etc/ld.so.conf.d/*.conf + - fix x86-64 LD_DEBUG=statistics +- fix hwcap handling when using ld.so.cache (#118518) + +* Mon Mar 15 2004 Jakub Jelinek 2.3.3-17 +- update from CVS + - implement non-_l function on top of _l functions + +* Thu Mar 11 2004 Jakub Jelinek 2.3.3-16 +- update from CVS +- fix s390{,x} TLS handling + +* Wed Mar 10 2004 Jakub Jelinek 2.3.3-15 +- update from CVS + - special section for compatibility code + - make getpid () work even in vfork () child +- configure with --enable-bind-now to avoid lazy binding in ld.so + and libc.so + +* Fri Mar 5 2004 Jakub Jelinek 2.3.3-14 +- update from CVS + - fix iconv -c (#117021) + - fix PIEs on sparc/sparc64 + - fix posix_fadvise on 64-bit architectures +- add locale-archive as %%ghost file (#117014) + +* Mon Mar 1 2004 Jakub Jelinek 2.3.3-13 +- update from CVS + +* Fri Feb 27 2004 Jakub Jelinek 2.3.3-12 +- update from CVS + +* Fri Feb 27 2004 Jakub Jelinek 2.3.3-11 +- update from CVS + - fix ld.so when vDSO is randomized + +* Fri Feb 20 2004 Jakub Jelinek 2.3.3-10 +- update from CVS + +* Fri Feb 20 2004 Jakub Jelinek 2.3.3-9 +- update from CVS + +* Tue Feb 10 2004 Jakub Jelinek 2.3.3-8 +- update from CVS + +* Tue Jan 27 2004 Jakub Jelinek 2.3.3-7 +- update from CVS + - dl_iterate_phdr extension to signal number of added/removed + libraries +- fix PT_GNU_RELRO support on ppc* with prelinking + +* Fri Jan 23 2004 Jakub Jelinek 2.3.3-6 +- rebuilt with fixed GCC on IA-64 + +* Thu Jan 22 2004 Jakub Jelinek 2.3.3-5 +- fix PT_GNU_RELRO support + +* Wed Jan 21 2004 Jakub Jelinek 2.3.3-4 +- update from CVS + - some further regex speedups + - fix re.translate handling in regex (#112869) + - change regfree to match old regex behaviour (what is freed + and clearing of freed pointers) + - fix accesses to unitialized memory in regex (#113507, #113425, + #113421) + - PT_GNU_RELRO support + +* Tue Dec 30 2003 Jakub Jelinek 2.3.3-3 +- update from CVS + - fix pmap_set fd and memory leak (#112726) +- fix backreference handling in regex +- rebuilt under glibc without the above bug to fix + libc.so linker script (#112738) + +* Mon Dec 29 2003 Jakub Jelinek 2.3.3-2 +- update from CVS + - faster getpid () in NPTL builds + - fix to make pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, ) + really disable cancellation (#112512) + - more regex fixes and speedups + - fix nextafter*/nexttoward* + - handle 6th syscall(3) argument on AMD64 + - handle memalign/posix_memalign in mtrace + - fix linuxthreads memory leak (#112208) + - remove throw () from cancellation points in linuxthreads (#112602) + - fix NPTL unregister_atfork + - fix unwinding through alternate signal stacks + +* Mon Dec 1 2003 Jakub Jelinek 2.3.3-1 +- update from CVS + - 2.3.3 release + - lots of regex fixes and speedups (#110401) + - fix atan2 + - fix pshared condvars in NPTL + - fix pthread_attr_destroy for attributes created with + pthread_attr_init@GLIBC_2.0 +- for the time being, include both nb_NO* and no_NO* as locales + so that the distribution can catch up with the no_NO->nb_NO + transition +- add BuildPrereq texinfo (#110252) + +* Tue Nov 18 2003 Jakub Jelinek 2.3.2-102 +- update from CVS + - fix getifaddrs (CAN-2003-0859) + - fix ftw fd leak + - fix linuxthreads sigaction (#108634) + - fix glibc 2.0 stdio compatibility + - fix uselocale (LC_GLOBAL_LOCALE) + - speed up stdio locking in non-threaded programs on IA-32 + - try to maintain correct order of cleanups between those + registered with __attribute__((cleanup)) + and with LinuxThreads style pthread_cleanup_push/pop (#108631) + - fix segfault in regex (#109606) + - fix RE_ICASE multi-byte handling in regex + - fix pthread_exit in libpthread.a (#109790) + - FTW_ACTIONRETVAL support + - lots of regex fixes and speedups + - fix ceill/floorl on AMD64 + +* Mon Oct 27 2003 Jakub Jelinek 2.3.2-101 +- update from CVS + - fix ld.so --verify (and ldd) + +* Mon Oct 27 2003 Jakub Jelinek 2.3.2-100 +- update from CVS + - fix sprof (#103727) + - avoid infinite loops in {,f}statvfs{,64} with hosed mounts file + - prevent dlopening of executables + - fix glob with GLOB_BRACE and without GLOB_NOESCAPE + - fix locale printing of word values on 64-bit big-endian arches + (#107846) + - fix getnameinfo and getaddrinfo with reverse IPv6 lookups + (#101261) + +* Wed Oct 22 2003 Jakub Jelinek 2.3.2-99 +- update from CVS + - dl_iterate_phdr in libc.a on arches other than IA-64 + - LD_DEBUG=statistics prints number of relative relocations + - fix hwcap computation +- NPTL is now part of upstream glibc CVS +- include {st,xh,zu}_ZA{,.UTF-8} locales + +* Sat Oct 4 2003 Jakub Jelinek 2.3.2-98 +- update from CVS + - fix close, pause and fsync (#105348) + - fix pthread_once on IA-32 +- implement backtrace () on IA-64, handle -fomit-frame-pointer + in AMD64 backtrace () (#90402) + +* Tue Sep 30 2003 Jakub Jelinek 2.3.2-97 +- update from CVS + - fix with C++ or -ansi or -pedantic C + - fix mknod/ustat return value when given bogus device number (#105768) + +* Fri Sep 26 2003 Jakub Jelinek 2.3.2-96 +- rebuilt + +* Fri Sep 26 2003 Jakub Jelinek 2.3.2-95 +- fix IA-64 getcontext + +* Thu Sep 25 2003 Jakub Jelinek 2.3.2-94 +- update from CVS +- fix syslog with non-C non-en_* locales (#61296, #104979) +- filter GLIBC_PRIVATE symbols from glibc provides +- fix NIS+ + +* Thu Sep 25 2003 Jakub Jelinek 2.3.2-93 +- update from CVS +- assume 2.4.21 kernel features on RHEL/ppc*, so that + {make,set,get,swap}context works +- backout execstack support for RHEL +- build rtkaio on amd64 too + +* Wed Sep 24 2003 Jakub Jelinek 2.3.2-92 +- update from CVS + - execstack/noexecstack support + - build nscd as PIE +- move __libc_stack_end back to @GLIBC_2.1 +- build against elfutils >= 0.86 to fix stripping on s390x + +* Mon Sep 22 2003 Jakub Jelinek 2.3.2-91 +- rebuilt + +* Mon Sep 22 2003 Jakub Jelinek 2.3.2-90 +- update from CVS + - NPTL locking change (#102682) +- don't jump around lock on amd64 + +* Thu Sep 18 2003 Jakub Jelinek 2.3.2-89 +- fix open_memstream/syslog (#104661) + +* Thu Sep 18 2003 Jakub Jelinek 2.3.2-88 +- update from CVS + - retrieve affinity in pthread_getattr_np + - fix pthread_attr_[gs]etaffinity_np + - handle hex and octal in wordexp + +* Wed Sep 17 2003 Jakub Jelinek 2.3.2-87 +- update from CVS + - truncate instead of round in utimes when utimes syscall is not available + - don't align stack in every glibc function unnecessarily on IA-32 + - make sure threads have their stack 16 byte aligned on IA-32 + - move sched_[sg]etaffinity to GLIBC_2.3.3 symbol version (#103231) + - fix pthread_getattr_np for the initial thread (#102683) + - avoid linuxthreads signal race (#104368) +- ensure all gzip invocations are done with -n option + +* Fri Sep 12 2003 Jakub Jelinek 2.3.2-86 +- update from CVS +- avoid linking in libgcc_eh.a unnecessarily +- change ssize_t back to long int on s390 -m31, unless + gcc 2.95.x is used + +* Wed Sep 10 2003 Jakub Jelinek 2.3.2-85 +- update from CVS + - fix IA-64 memccpy (#104114) + +* Tue Sep 9 2003 Jakub Jelinek 2.3.2-84 +- update from CVS + - undo broken amd64 signal context changes + +* Tue Sep 9 2003 Jakub Jelinek 2.3.2-83 +- update from CVS +- change *nlink_t, *ssize_t and *intptr_t types on s390 -m31 to + {unsigned,} int +- change *u_quad_t, *quad_t, *qaddr_t, *dev_t, *ino64_t, *loff_t, + *off64_t, *rlim64_t, *blkcnt64_t, *fsblkcnt64_t, *fsfilcnt64_t + on 64-bit arches from {unsigned,} long long int {,*} to + {unsigned,} long int {,*} to restore binary compatibility + for C++ functions using these types as arguments + +* Sun Sep 7 2003 Jakub Jelinek 2.3.2-82 +- rebuilt + +* Sat Sep 6 2003 Jakub Jelinek 2.3.2-81 +- update from CVS + - fix tc[gs]etattr/cf[gs]et[io]speed on ppc (#102732) + - libio fixes + +* Thu Sep 4 2003 Jakub Jelinek 2.3.2-80 +- update from CVS + - fix IA-64 cancellation when mixing __attribute__((cleanup ())) + and old-style pthread_cleanup_push cleanups + +* Tue Sep 2 2003 Jakub Jelinek 2.3.2-79 +- updated from CVS + - lots of cancellation fixes + - fix posix_fadvise* on ppc32 + - TLS layout fix + - optimize stdio cleanups (#103354) + - sparcv9 NPTL + - include sigset, sighold, sigrelse, sigpause and sigignore prototypes + in signal.h even if -D_XOPEN_SOURCE_EXTENDED (#103269) + - fix svc_getreqset on 64-bit big-endian arches + - return ENOSYS in linuxthreads pthread_barrierattr_setpshared for + PTHREAD_PROCESS_SHARED + - add pthread_cond_timedwait stubs to libc.so (#102709) +- split glibc-devel into glibc-devel and glibc-headers to ensure + amd64 /usr/include always wins on amd64/i386 bi-arch installs +- increase PTHREAD_STACK_MIN on alpha, ia64 and sparc* +- get rid of __syscall_* prototypes and stubs in sysdeps/unix/sysv/linux +- run make check also with linuxthreads (on IA-32 non-FLOATING_STACKS) + ld.so and NPTL (on IA-32 also FLOATING_STACKS linuxthreads) libraries + and tests + +* Mon Aug 25 2003 Jakub Jelinek 2.3.2-78 +- include dl-osinfo.h only in glibc-debuginfo-2*.rpm, not + in glibc-debuginfo-common* + +* Mon Aug 25 2003 Jakub Jelinek 2.3.2-77 +- update from CVS + - fix glibc 2.0 libio compatibility (#101385) + - fix ldconfig with /usr/lib/lib*.so symlinks (#102853) + - fix assert.h (#102916, #103017) + - make ld.so.cache identical between IA-32 and AMD64 (#102887) + - fix static linking of large IA-64 binaries (#102586) +- avoid using floating point regs in lazy binding code on ppc64 (#102763) + +* Fri Aug 22 2003 Roland McGrath 2.3.2-76 +- add td_thr_tls_get_addr changes missed in initial nptl_db rewrite + +* Sun Aug 17 2003 Roland McGrath 2.3.2-74 +- nptl_db rewrite not yet in CVS + +* Thu Aug 14 2003 Jakub Jelinek 2.3.2-72 +- update from CVS + - fix rtkaio aio_fsync{,64} + - update rtkaio for !BROKEN_THREAD_SIGNALS + - fix assert macro when used on pointers + +* Wed Aug 13 2003 Jakub Jelinek 2.3.2-71 +- update from CVS + +* Tue Aug 12 2003 Jakub Jelinek 2.3.2-70 +- update from CVS +- disable CLONE_STOPPED for now until it is resolved +- strip crt files +- fix libio on arches with no < GLIBC_2.2 support (#102102, #102105) +- fix glibc-debuginfo to include all nptl and nptl_db sources + +* Thu Aug 7 2003 Jakub Jelinek 2.3.2-69 +- update from CVS + - fix pthread_create@GLIBC_2.0 (#101767) +- __ASSUME_CLONE_STOPPED on all arches but s390* in RHEL + +* Sun Aug 3 2003 Jakub Jelinek 2.3.2-68 +- update from CVS + - only use CLONE_STOPPED if kernel supports it, fix setting of thread + explicit scheduling (#101457) + +* Fri Aug 1 2003 Jakub Jelinek 2.3.2-67 +- update from CVS + - fix utimes and futimes if kernel doesn't support utimes syscall + - fix s390 ssize_t type + - fix dlerror when called before any dlopen/dlsym + - update IA-64 bits/sigcontext.h (#101344) + - various warning fixes + - fix pthread.h comment typos (#101363) + +* Wed Jul 30 2003 Jakub Jelinek 2.3.2-66 +- update from CVS +- fix dlopen of libraries using TLS IE/LE models + +* Tue Jul 29 2003 Jakub Jelinek 2.3.2-65 +- update from CVS + - fix timer_create + - use __extension__ before long long typedefs in (#100718) + +* Mon Jul 28 2003 Jakub Jelinek 2.3.2-64 +- update from CVS + - fix wcpncpy (#99462) + - export _res@GLIBC_2.0 even from NPTL libc.so (__res_state () + unlike __errno_location () or __h_errno_location () was introduced + in glibc 2.2) + - fix zic bug on 64-bit platforms + - some TLS handling fixes + - make ldconfig look into alternate ABI dirs by default (#99402) +- move %%{_datadir}/zoneinfo to tzdata package, so that it can be + errataed separately from glibc +- new add-on - rtkaio +- prereq libgcc, as glibc now relies on libgcc_s.so.1 for pthread_cancel + +* Tue Jul 15 2003 Jakub Jelinek 2.3.2-63 +- fix thread cancellation on ppc64 + +* Sat Jul 12 2003 Jakub Jelinek 2.3.2-62 +- update from CVS + - fix thread cancellation on ppc32, s390 and s390x + +* Thu Jul 10 2003 Jakub Jelinek 2.3.2-61 +- update from CVS + - build libc_nonshared.a with -fPIC instead of -fpic +- fix ppc64 PIE support +- add cfi directives to NPTL sysdep-cancel.h on ppc/ppc64/s390/s390x + +* Tue Jul 8 2003 Jakub Jelinek 2.3.2-60 +- update from CVS + +* Thu Jul 3 2003 Jakub Jelinek 2.3.2-59 +- update from CVS +- on IA-64 use different symbols for cancellation portion of syscall + handlers to make gdb happier + +* Thu Jun 26 2003 Jakub Jelinek 2.3.2-58 +- update from CVS + - nss_compat supporting LDAP etc. + +* Tue Jun 24 2003 Jakub Jelinek 2.3.2-57 +- update from CVS + +* Thu Jun 19 2003 Jakub Jelinek 2.3.2-56 +- fix condvars and semaphores in ppc* NPTL +- fix test-skeleton.c reporting of timed-out tests (#91269) +- increase timeouts for tests during make check + +* Wed Jun 18 2003 Jakub Jelinek 2.3.2-55 +- make ldconfig default to both /lib+/usr/lib and /lib64+/usr/lib64 + on bi-ABI architectures (#97557) +- disable FUTEX_REQUEUE on ppc* temporarily + +* Wed Jun 18 2003 Jakub Jelinek 2.3.2-54 +- update from CVS +- fix glibc_post_upgrade on ppc + +* Tue Jun 17 2003 Jakub Jelinek 2.3.2-53 +- update from CVS +- fix localedef (#90659) +- tweak linuxthreads for librt cancellation + +* Mon Jun 16 2003 Jakub Jelinek 2.3.2-52 +- update from CVS + +* Thu Jun 12 2003 Jakub Jelinek 2.3.2-51 +- update from CVS +- fix (#97169) + +* Wed Jun 11 2003 Jakub Jelinek 2.3.2-50 +- update from CVS + +* Tue Jun 10 2003 Jakub Jelinek 2.3.2-49 +- update from CVS + - fix pthread_cond_signal on IA-32 (#92080, #92253) + - fix setegid (#91567) +- don't prelink -R libc.so on any architecture, it prohibits + address randomization + +* Thu Jun 5 2003 Jakub Jelinek 2.3.2-48 +- update from CVS + - fix IA-64 NPTL build + +* Thu Jun 5 2003 Jakub Jelinek 2.3.2-47 +- update from CVS +- PT_GNU_STACK segment in binaries/executables and .note.GNU-stack + section in *.[oa] + +* Sun Jun 1 2003 Jakub Jelinek 2.3.2-46 +- update from CVS +- enable NPTL on AMD64 +- avoid using trampolines in localedef + +* Thu May 29 2003 Jakub Jelinek 2.3.2-45 +- enable NPTL on IA-64 + +* Thu May 29 2003 Jakub Jelinek 2.3.2-44 +- update from CVS +- enable NPTL on s390 and s390x +- make __init_array_start etc. symbols in elf-init.oS hidden undefined + +* Thu May 29 2003 Jakub Jelinek 2.3.2-43 +- update from CVS + +* Fri May 23 2003 Jakub Jelinek 2.3.2-42 +- update from CVS + +* Tue May 20 2003 Jakub Jelinek 2.3.2-41 +- update from CVS +- use NPTL libs if uname -r contains nptl substring or is >= 2.5.69 + or set_tid_address syscall is available instead of checking + AT_SYSINFO dynamic tag + +* Thu May 15 2003 Jakub Jelinek 2.3.2-40 +- update from CVS + +* Wed May 14 2003 Jakub Jelinek 2.3.2-39 +- update from CVS + - fix for prelinking of libraries with no dependencies + +* Tue May 13 2003 Jakub Jelinek 2.3.2-38 +- update from CVS +- enable NPTL on ppc and ppc64 + +* Tue May 6 2003 Matt Wilson 2.3.2-37 +- rebuild + +* Sun May 4 2003 Jakub Jelinek 2.3.2-36 +- update from CVS + +* Sat May 3 2003 Jakub Jelinek 2.3.2-35 +- update from CVS + - make -jN build fixes + +* Fri May 2 2003 Jakub Jelinek 2.3.2-34 +- update from CVS +- avoid using trampolines in iconvconfig for now + +* Sat Apr 26 2003 Jakub Jelinek 2.3.2-33 +- update from CVS + +* Fri Apr 25 2003 Jakub Jelinek 2.3.2-32 +- update from CVS +- more ppc TLS fixes + +* Wed Apr 23 2003 Jakub Jelinek 2.3.2-31 +- update from CVS + - nscd fixes + - fix Bahrain spelling (#56298) + - fix Ukrainian collation (#83973) + - accept trailing spaces in /etc/ld.so.conf (#86032) + - perror fix (#85994) + - fix localedef (#88978) + - fix getifaddrs (#89026) + - fix strxfrm (#88409) +- fix ppc TLS +- fix getaddrinfo (#89448) +- don't print warning about errno, h_errno or _res if + LD_ASSUME_KERNEL=2.4.1 or earlier + +* Tue Apr 15 2003 Jakub Jelinek 2.3.2-30 +- update from CVS +- fix prelink on ppc32 +- add TLS support on ppc32 and ppc64 +- make sure on -m64 arches all helper binaries are built with this + option + +* Mon Apr 14 2003 Jakub Jelinek 2.3.2-29 +- update from CVS + - fix strxfrm (#88409) +- use -m64 -mno-minimal-toc on ppc64 +- conflict with kernels < 2.4.20 on ppc64 and < 2.4.0 on x86_64 +- link glibc_post_upgrade against newly built libc.a + +* Sun Apr 13 2003 Jakub Jelinek 2.3.2-28 +- update from CVS + - fix NPTL pthread_detach and already terminated, but not yet + joined thread (#88219) + - fix bug-regex4 testcase (#88118) + - reenable prelink support broken in 2.3.2-13 + - fix register_printf_function (#88052) + - fix double free with fopen using ccs= (#88056) + - fix potential access below $esp in {set,swap}context (#88093) + - fix buffer underrun in gencat -H (#88099) + - avoid using unitialized variable in tst-tgmath (#88101) + - fix gammal (#88104) + - fix iconv -c + - fix xdr_string (PR libc/4999) + - fix /usr/lib/nptl/librt.so symlink + - avoid running NPTL cleanups twice in some cases + - unblock __pthread_signal_cancel in linuxthreads, so that + linuxthreads threaded programs work correctly if spawned + from NPTL threaded programs + - fix sysconf _SC_{NPROCESSORS_{CONF,ONLN},{,AV}PHYS_PAGES} +- remove /lib/i686 directory before running ldconfig in glibc post + during i686 -> i386 glibc "upgrades" (#88456) + +* Wed Apr 2 2003 Jakub Jelinek 2.3.2-22 +- update from CVS + - add pthread_atfork to libpthread.a + +* Tue Apr 1 2003 Jakub Jelinek 2.3.2-21 +- update from CVS +- make sure linuxthreads pthread_mutex_lock etc. is not a cancellation + point + +* Sat Mar 29 2003 Jakub Jelinek 2.3.2-20 +- update from CVS +- if kernel >= 2.4.1 doesn't support NPTL, fall back to + /lib/i686 libs on i686, not stright to /lib + +* Fri Mar 28 2003 Jakub Jelinek 2.3.2-19 +- update from CVS + - timers fixes + +* Thu Mar 27 2003 Jakub Jelinek 2.3.2-18 +- update from CVS +- fix NPTL pthread_cond_timedwait +- fix sysconf (_SC_MONOTONIC_CLOCK) +- use /%%{_lib}/tls instead of /lib/tls on x86-64 +- add /%%{_lib}/tls/librt*so* and /%%{_lib}/i686/librt*so* +- display content of .out files for all make check failures + +* Wed Mar 26 2003 Jakub Jelinek 2.3.2-17 +- update from CVS + - kernel POSIX timers support + +* Sat Mar 22 2003 Jakub Jelinek 2.3.2-16 +- update from CVS + - export __fork from glibc again +- fix glibc-compat build in NPTL +- fix c_stubs +- fix some more atomic.h problems +- don't check abi in glibc-compat libs + +* Fri Mar 21 2003 Jakub Jelinek 2.3.2-15 +- update from CVS +- build glibc-compat (for glibc 2.0 compatibility) and c_stubs add-ons +- condrestart sshd in glibc_post_upgrade so that the user can + log in remotely and handle the rest (#86339) +- fix a typo in glibc_post_upgrade on sparc + +* Tue Mar 18 2003 Jakub Jelinek 2.3.2-14 +- update from CVS +- change i686/athlon libc.so.6 base to 0x00e80000 + +* Mon Mar 17 2003 Jakub Jelinek 2.3.2-13 +- update from CVS + - hopefully last fix for condvar problems + +* Fri Mar 14 2003 Jakub Jelinek 2.3.2-12 +- fix bits/syscall.h creation on x86-64 + +* Thu Mar 13 2003 Jakub Jelinek 2.3.2-11 +- update from CVS + +* Wed Mar 12 2003 Jakub Jelinek 2.3.2-10 +- update from CVS + +* Tue Mar 11 2003 Jakub Jelinek 2.3.2-9 +- update from CVS +- fix glibc-debug description (#85111) +- make librt.so a symlink again, not linker script + +* Tue Mar 4 2003 Jakub Jelinek 2.3.2-8 +- update from CVS +- remove the workarounds for broken software accessing GLIBC_PRIVATE + symbols + +* Mon Mar 3 2003 Jakub Jelinek 2.3.2-7 +- update from CVS + +* Sun Mar 2 2003 Jakub Jelinek 2.3.2-6 +- fix TLS IE/LE model handling in dlopened libraries + on TCB_AT_TP arches + +* Tue Feb 25 2003 Jakub Jelinek 2.3.2-5 +- update from CVS + +* Tue Feb 25 2003 Jakub Jelinek 2.3.2-4 +- update from CVS + +* Mon Feb 24 2003 Jakub Jelinek 2.3.2-3 +- update from CVS +- only warn about errno, h_errno or _res for binaries, never + libraries +- rebuilt with gcc-3.2.2-4 to use direct %%gs TLS access insn sequences + +* Sun Feb 23 2003 Jakub Jelinek 2.3.2-2 +- update from CVS + +* Sat Feb 22 2003 Jakub Jelinek 2.3.2-1 +- update from CVS + +* Thu Feb 20 2003 Jakub Jelinek 2.3.1-51 +- update from CVS + +* Wed Feb 19 2003 Jakub Jelinek 2.3.1-50 +- update from CVS + +* Wed Feb 19 2003 Jakub Jelinek 2.3.1-49 +- update from CVS +- remove nisplus and nis from the default nsswitch.conf (#67401, #9952) + +* Tue Feb 18 2003 Jakub Jelinek 2.3.1-48 +- update from CVS + +* Sat Feb 15 2003 Jakub Jelinek 2.3.1-47 +- update from CVS + +* Fri Feb 14 2003 Jakub Jelinek 2.3.1-46 +- update from CVS + - pthread_cond* NPTL fixes, new NPTL testcases + +* Thu Feb 13 2003 Jakub Jelinek 2.3.1-45 +- update from CVS +- include also linuxthreads FLOATING_STACKS libs on i686 and athlon: + LD_ASSUME_KERNEL=2.2.5 to LD_ASSUME_KERNEL=2.4.0 is non-FLOATING_STACKS lt, + LD_ASSUME_KERNEL=2.4.1 to LD_ASSUME_KERNEL=2.4.19 is FLOATING_STACKS lt, + later is NPTL +- enable TLS on alpha/alphaev6 +- add BuildPreReq: /usr/bin/readlink + +* Tue Feb 11 2003 Jakub Jelinek 2.3.1-44 +- update from CVS + - pthread_once fix + +* Mon Feb 10 2003 Jakub Jelinek 2.3.1-43 +- update from CVS +- vfork fix on s390 +- rebuilt with binutils 2.13.90.0.18-5 so that accesses to errno + don't bind locally (#83325) + +* Thu Feb 06 2003 Jakub Jelinek 2.3.1-42 +- update from CVS +- fix pthread_create after vfork+exec in linuxthreads + +* Wed Feb 05 2003 Jakub Jelinek 2.3.1-41 +- update from CVS + +* Thu Jan 30 2003 Jakub Jelinek 2.3.1-40 +- update from CVS + +* Wed Jan 29 2003 Jakub Jelinek 2.3.1-39 +- update from CVS +- enable TLS on s390{,x} and sparc{,v9} + +* Fri Jan 17 2003 Jakub Jelinek 2.3.1-38 +- update from CVS +- initialize __environ in glibc_post_upgrade to empty array, + so that it is not NULL +- compat symlink for s390x /lib/ld64.so.1 +- enable glibc-profile on x86-64 +- only include libNoVersion.so on IA-32, Alpha and Sparc 32-bit + +* Thu Jan 16 2003 Jakub Jelinek 2.3.1-37 +- update from CVS + - nscd fixes, *scanf fix +- fix %%nptlarches noarch build (#81909) +- IA-64 TLS fixes + +* Tue Jan 14 2003 Jakub Jelinek 2.3.1-36 +- update from CVS +- rework -debuginfo subpackage, add -debuginfo-common + subpackage on IA-32, Alpha and Sparc (ie. auxiliary arches) +- fix vfork in libc.a on PPC32, Alpha, Sparc +- fix libio locks in linuxthreads libc.so if libpthread.so + is dlopened later (#81374) + +* Mon Jan 13 2003 Jakub Jelinek 2.3.1-35 +- update from CVS + - dlclose bugfixes +- fix NPTL libpthread.a +- fix glibc_post_upgrade on several arches + +* Sat Jan 11 2003 Jakub Jelinek 2.3.1-34 +- update from CVS +- TLS support on IA-64 + +* Wed Jan 8 2003 Jakub Jelinek 2.3.1-33 +- fix vfork in linuxthreads (#81377, #81363) + +* Tue Jan 7 2003 Jakub Jelinek 2.3.1-32 +- update from CVS +- don't use TLS libs if kernel doesn't set AT_SYSINFO + (#80921, #81212) +- add ntp_adjtime on alpha (#79996) +- fix nptl_db (#81116) + +* Sun Jan 5 2003 Jakub Jelinek 2.3.1-31 +- update from CVS +- support all architectures again + +* Fri Jan 3 2003 Jakub Jelinek 2.3.1-30 +- fix condvar compatibility wrappers +- add ugly hack to use non-TLS libs if a binary is seen + to have errno, h_errno or _res symbols in .dynsym + +* Fri Jan 3 2003 Jakub Jelinek 2.3.1-29 +- update from CVS + - fixes for new condvar + +* Thu Jan 2 2003 Jakub Jelinek 2.3.1-28 +- new NPTL condvar implementation plus related linuxthreads + symbol versioning updates + +* Thu Jan 2 2003 Jakub Jelinek 2.3.1-27 +- update from CVS +- fix #include with -D_BSD_SOURCE or without + feature set macros +- make *sigaction, sigwait and raise the same between + -lpthread -lc and -lc -lpthread in linuxthreads builds + +* Tue Dec 31 2002 Jakub Jelinek 2.3.1-26 +- fix dlclose + +* Sun Dec 29 2002 Jakub Jelinek 2.3.1-25 +- enable sysenter by default for now +- fix endless loop in ldconfig + +* Sat Dec 28 2002 Jakub Jelinek 2.3.1-24 +- update from CVS + +* Fri Dec 27 2002 Jakub Jelinek 2.3.1-23 +- update from CVS + - fix ptmalloc_init after clearenv (#80370) + +* Sun Dec 22 2002 Jakub Jelinek 2.3.1-22 +- update from CVS +- add IA-64 back +- move TLS libraries from /lib/i686 to /lib/tls + +* Thu Dec 19 2002 Jakub Jelinek 2.3.1-21 +- system(3) fix for linuxthreads +- don't segfault in pthread_attr_init from libc.so +- add cancellation tests from nptl to linuxthreads + +* Wed Dec 18 2002 Jakub Jelinek 2.3.1-20 +- fix up lists of exported symbols + their versions + from the libraries + +* Wed Dec 18 2002 Jakub Jelinek 2.3.1-19 +- fix --with-tls --enable-kernel=2.2.5 libc on IA-32 + +* Wed Dec 18 2002 Jakub Jelinek 2.3.1-18 +- update from CVS + - fix NPTL hanging mozilla + - initialize malloc in mALLOPt (fixes problems with squid, #79957) + - make linuxthreads work with dl_dynamic_weak 0 + - clear dl_dynamic_weak everywhere + +* Tue Dec 17 2002 Jakub Jelinek 2.3.1-17 +- update from CVS + - NPTL socket fixes, flockfile/ftrylockfile/funlockfile fix + - kill -debug sub-package, rename -debug-static to -debug + - clear dl_dynamic_weak for NPTL + +* Mon Dec 16 2002 Jakub Jelinek 2.3.1-16 +- fix and for C++ +- automatically generate NPTL libpthread wrappers + +* Mon Dec 16 2002 Jakub Jelinek 2.3.1-15 +- update from CVS + - all functions which need cancellation should now be cancellable + both in libpthread.so and libc.so + - removed @@GLIBC_2.3.2 cancellation wrappers + +* Fri Dec 13 2002 Jakub Jelinek 2.3.1-14 +- update from CVS + - replace __libc_lock_needed@GOTOFF(%%ebx) with + %%gs:offsetof(tcbhead_t, multiple_threads) + - start of new NPTL cancellation wrappers + +* Thu Dec 12 2002 Jakub Jelinek 2.3.1-13 +- update from CVS +- use inline locks in malloc + +* Tue Dec 10 2002 Jakub Jelinek 2.3.1-12 +- update from CVS + - support LD_ASSUME_KERNEL=2.2.5 in statically linked programs + +* Mon Dec 9 2002 Jakub Jelinek 2.3.1-11 +- update from CVS +- rebuilt with gcc-3.2.1-2 + +* Fri Dec 6 2002 Jakub Jelinek 2.3.1-10 +- update from CVS +- non-nptl --with-tls --without-__thread FLOATING_STACKS libpthread + should work now +- faster libc locking when using nptl +- add OUTPUT_FORMAT to linker scripts +- fix x86_64 sendfile (#79111) + +* Wed Dec 4 2002 Jakub Jelinek 2.3.1-9 +- update from CVS + - RUSCII support (#78906) +- for nptl builds add BuildRequires +- fix byteswap.h for non-gcc (#77689) +- add nptl-devel package + +* Tue Dec 3 2002 Jakub Jelinek 2.3.1-8 +- update from CVS + - make --enable-kernel=2.2.5 --with-tls --without-__thread + ld.so load nptl and other --with-__thread libs +- disable nptl by default for now + +* Wed Nov 27 2002 Jakub Jelinek 2.3.1-7 +- update from CVS +- restructured redhat/Makefile and spec, so that src.rpm contains + glibc-.tar.bz2, glibc-redhat-.tar.bz2 and glibc-redhat.patch +- added nptl + +* Fri Nov 8 2002 Jakub Jelinek 2.3.1-6 +- update from CVS + - even more regex fixes +- run sed testsuite to check glibc regex + +* Thu Oct 24 2002 Jakub Jelinek 2.3.1-5 +- fix LD_DEBUG=statistics and LD_TRACE_PRELINKING in programs + using libpthread.so. + +* Thu Oct 24 2002 Jakub Jelinek 2.3.1-4 +- update from CVS + - fixed %%a and %%A in *printf (#75821) + - fix re_comp memory leaking (#76594) + +* Tue Oct 22 2002 Jakub Jelinek 2.3.1-3 +- update from CVS + - some more regex fixes +- fix libpthread.a (#76484) +- fix locale-archive enlarging + +* Fri Oct 18 2002 Jakub Jelinek 2.3.1-2 +- update from CVS + - don't need to use 128K of stacks for DNS lookups + - regex fixes + - updated timezone data e.g. for this year's Brasil DST + changes + - expand ${LIB} in RPATH/RUNPATH/dlopen filenames + +* Fri Oct 11 2002 Jakub Jelinek 2.3.1-1 +- update to 2.3.1 final + - support really low thread stack sizes (#74073) +- tzdata update + +* Wed Oct 9 2002 Jakub Jelinek 2.3-2 +- update from CVS + - handle low stack limits + - move s390x into */lib64 + +* Thu Oct 3 2002 Jakub Jelinek 2.3-1 +- update to 2.3 final + - fix freopen on libstdc++ <= 2.96 stdin/stdout/stderr (#74800) + +* Sun Sep 29 2002 Jakub Jelinek 2.2.94-3 +- don't prelink -r libc.so on ppc/x86-64/sparc*, it doesn't + speed things up, because they are neither REL arches, nor + ELF_MACHINE_REL_RELATIVE +- fix sparc64 build + +* Sun Sep 29 2002 Jakub Jelinek 2.2.94-2 +- update from CVS + +* Sat Sep 28 2002 Jakub Jelinek 2.2.94-1 +- update from CVS +- prelink on ppc and x86-64 too +- don't remove ppc memset +- instead of listing on which arches to remove glibc-compat + list where it should stay + +* Fri Sep 6 2002 Jakub Jelinek 2.2.93-5 +- fix wcsmbs functions with invalid character sets (or malloc + failures) +- make sure __ctype_b etc. compat vars are updated even if + they are copy relocs in the main program + +* Thu Sep 5 2002 Jakub Jelinek 2.2.93-4 +- fix /lib/libnss1_dns.so.1 (missing __set_h_errno definition + leading to unresolved __set_h_errno symbol) + +* Wed Sep 4 2002 Jakub Jelinek 2.2.93-3 +- security fix - increase dns-network.c MAXPACKET to at least + 65536 to avoid buffer overrun. Likewise glibc-compat + dns-{host,network}.c. + +* Tue Sep 3 2002 Jakub Jelinek 2.2.93-2 +- temporarily add back __ctype_b, __ctype_tolower and __ctype_toupper to + libc.a and export them as @@GLIBC_2.0 symbols, not @GLIBC_2.0 + from libc.so - we have still lots of .a libraries referencing + __ctype_{b,tolower,toupper} out there... + +* Tue Sep 3 2002 Jakub Jelinek 2.2.93-1 +- update from CVS + - 2.2.93 release + - use double instead of single indirection in isXXX macros + - per-locale wcsmbs conversion state + +* Sat Aug 31 2002 Jakub Jelinek 2.2.92-2 +- update from CVS + - fix newlocale/duplocale/uselocale +- disable profile on x86_64 for now + +* Sat Aug 31 2002 Jakub Jelinek 2.2.92-1 +- update from CVS + - 2.2.92 release + - fix gettext after uselocale + - fix locales in statically linked threaded programs + - fix NSS + +* Thu Aug 29 2002 Jakub Jelinek 2.2.91-1 +- update from CVS + - 2.2.91 release + - fix fd leaks in locale-archive reader (#72043) +- handle EROFS in build-locale-archive gracefully (#71665) + +* Wed Aug 28 2002 Jakub Jelinek 2.2.90-27 +- update from CVS + - fix re_match (#72312) +- support more than 1024 threads + +* Fri Aug 23 2002 Jakub Jelinek 2.2.90-26 +- update from CVS + - fix i386 build + +* Thu Aug 22 2002 Jakub Jelinek 2.2.90-25 +- update from CVS + - fix locale-archive loading hang on some (non-primary) locales + (#72122, #71878) + - fix umount problems with locale-archives when /usr is a separate + partition (#72043) +- add LICENSES file + +* Fri Aug 16 2002 Jakub Jelinek 2.2.90-24 +- update from CVS + - only mmap up to 2MB of locale-archive on 32-bit machines + initially + - fix fseek past end + fread segfault with mmaped stdio +- include which is mistakenly not included + in glibc-devel on IA-32 + +* Fri Aug 16 2002 Jakub Jelinek 2.2.90-23 +- don't return normalized locale name in setlocale when using + locale-archive + +* Thu Aug 15 2002 Jakub Jelinek 2.2.90-22 +- update from CVS + - optimize for primary system locale +- localedef fixes (#71552, #67705) + +* Wed Aug 14 2002 Jakub Jelinek 2.2.90-21 +- fix path to locale-archive in libc reader +- build locale archive at glibc-common %%post time +- export __strtold_internal and __wcstold_internal on Alpha again +- workaround some localedata problems + +* Tue Aug 13 2002 Jakub Jelinek 2.2.90-20 +- update from CVS +- patch out set_thread_area for now + +* Fri Aug 9 2002 Jakub Jelinek 2.2.90-19 +- update from CVS +- GB18030 patch from Yu Shao +- applied Debian patch for getaddrinfo IPv4 vs. IPv6 +- fix regcomp (#71039) + +* Sun Aug 4 2002 Jakub Jelinek 2.2.90-18 +- update from CVS +- use /usr/sbin/prelink, not prelink (#70376) + +* Thu Jul 25 2002 Jakub Jelinek 2.2.90-17 +- update from CVS + +* Thu Jul 25 2002 Jakub Jelinek 2.2.90-16 +- update from CVS + - ungetc fix (#69586) + - fseek errno fix (#69589) + - change *etrlimit prototypes for C++ (#68588) +- use --without-tls instead of --disable-tls + +* Thu Jul 11 2002 Jakub Jelinek 2.2.90-15 +- set nscd user's shell to /sbin/nologin (#68369) +- fix glibc-compat buffer overflows (security) +- buildrequire prelink, don't build glibc's own copy of it (#67567) +- update from CVS + - regex fix (#67734) + - fix unused warnings (#67706) + - fix freopen with mmap stdio (#67552) + - fix realloc (#68499) + +* Tue Jun 25 2002 Bill Nottingham 2.2.90-14 +- update from CVS + - fix argp on long words + - update atime in libio + +* Sat Jun 22 2002 Jakub Jelinek 2.2.90-13 +- update from CVS + - a thread race fix + - fix readdir on invalid dirp + +* Wed Jun 19 2002 Jakub Jelinek 2.2.90-12 +- update from CVS + - don't use __thread in headers +- fix system(3) in threaded apps +- update prelink, so that it is possible to prelink -u libc.so.6.1 + on Alpha + +* Fri Jun 7 2002 Jakub Jelinek 2.2.90-11 +- update from CVS + - fix __moddi3 (#65612, #65695) + - fix ether_line (#64427) +- fix setvbuf with mmap stdio (#65864) +- --disable-tls for now, waiting for kernel +- avoid duplication of __divtf3 etc. on IA-64 +- make sure get*ent_r and _IO_wfile_jumps are exported (#62278) + +* Tue May 21 2002 Jakub Jelinek 2.2.90-10 +- update from CVS + - fix Alpha pthread bug with gcc 3.1 + +* Fri Apr 19 2002 Jakub Jelinek 2.2.5-35 +- fix nice + +* Mon Apr 15 2002 Jakub Jelinek 2.2.5-34 +- add relocation dependencies even for weak symbols (#63422) +- stricter check_fds check for suid/sgid binaries +- run make check at %%install time + +* Sat Apr 13 2002 Jakub Jelinek 2.2.5-33 +- handle Dec 31 1969 in mktime for timezones west of GMT (#63369) +- back out do-lookup.h change (#63261, #63305) +- use "memory" clobber instead all the fancy stuff in i386/i686/bits/string.h + since lots of compilers break on it +- fix sparc build with gcc 3.1 +- fix spec file for athlon + +* Tue Apr 9 2002 Jakub Jelinek 2.2.5-32 +- fix debugging of threaded apps (#62804) +- fix DST for Estonia (#61494) +- document that pthread_mutexattr_?etkind_np are deprecated + and pthread_mutexattr_?ettype should be used instead in man + pages (#61485) +- fix libSegFault.so undefined externals + +* Fri Apr 5 2002 Jakub Jelinek 2.2.5-31 +- temporarily disable prelinking ld.so, as some statically linked + binaries linked against debugging versions of old glibcs die on it + (#62352) +- fix for -std=c99 (#62516) +- fix ether_ntohost segfault (#62397) +- remove in glibc_post_upgrade on i386 all /lib/i686/libc-*.so, + /lib/i686/libm-*.so and /lib/i686/libpthread-*.so, not just current + version (#61633) +- prelink -r on alpha too + +* Thu Mar 28 2002 Jakub Jelinek 2.2.5-30 +- update GB18030 iconv module (Yu Shao) + +* Tue Mar 26 2002 Jakub Jelinek 2.2.5-29 +- features.h fix + +* Tue Mar 26 2002 Jakub Jelinek 2.2.5-28 +- update from CVS + - fix nscd with huge groups + - fix nis to not close fds it shouldn't +- rebuilt against newer glibc-kernheaders to use the correct + PATH_MAX +- handle .athlon.rpm glibc the same way as .i686.rpm +- add a couple of .ISO-8859-15 locales (#61908) +- readd temporarily currencies which were superceeded by Euro + into the list of accepted currencies by localedef to make + standard conformance testsuites happy +- temporarily moved __libc_waitpid back to make Sun JDK happy +- use old malloc code +- prelink i686/athlon ld.so and prelink -r i686/athlon libc.so + +* Thu Mar 14 2002 Jakub Jelinek 2.2.5-27 +- update from CVS + - fix DST handling for southern hemisphere (#60747) + - fix daylight setting for tzset (#59951) + - fix ftime (#60350) + - fix nice return value + - fix a malloc segfault +- temporarily moved __libc_wait, __libc_fork and __libc_stack_end + back to what they used to be exported at +- censorship (#60758) + +* Thu Feb 28 2002 Jakub Jelinek 2.2.5-26 +- update from CVS +- use __attribute__((visibility(...))) if supported, use _rtld_local + for ld.so only objects +- provide libc's own __{,u}{div,mod}di3 + +* Wed Feb 27 2002 Jakub Jelinek 2.2.5-25 +- switch back to 2.2.5, mmap stdio needs work + +* Mon Feb 25 2002 Jakub Jelinek 2.2.90-8 +- fix two other mmap stdio bugs (#60228) + +* Thu Feb 21 2002 Jakub Jelinek 2.2.90-7 +- fix yet another mmap stdio bug (#60145) + +* Tue Feb 19 2002 Jakub Jelinek 2.2.90-6 +- fix mmap stdio bug (seen on ld as File truncated error, #60043) +- apply Andreas Schwab's fix for pthread sigwait +- remove /lib/i686/ libraries in glibc_post_upgrade when + performing i386 glibc install + +* Thu Feb 14 2002 Jakub Jelinek 2.2.90-5 +- update to CVS +- added glibc-utils subpackage +- disable autoreq in glibc-debug +- readd %%lang() to locale files + +* Thu Feb 7 2002 Jakub Jelinek 2.2.90-4 +- update to CVS +- move glibc private symbols to GLIBC_PRIVATE symbol version + +* Wed Jan 9 2002 Jakub Jelinek 2.2.90-3 +- fix a sqrt bug on alpha which caused SHN_UNDEF $__full_ieee754_sqrt..ng + symbol in libm + +* Tue Jan 8 2002 Jakub Jelinek 2.2.90-2 +- add debug-static package + +* Mon Dec 31 2001 Jakub Jelinek 2.2.90-1 +- update from CVS +- remove -D__USE_STRING_INLINES +- add debug subpackage to trim glibc and glibc-devel size + +* Wed Oct 3 2001 Jakub Jelinek 2.2.4-19 +- fix strsep + +* Fri Sep 28 2001 Jakub Jelinek 2.2.4-18 +- fix a ld.so bug with duplicate searchlists in l_scope +- fix erfcl(-inf) +- turn /usr/lib/librt.so into linker script + +* Wed Sep 26 2001 Jakub Jelinek 2.2.4-17 +- fix a ld.so lookup bug after lots of dlopen calls +- fix CMSG_DATA for non-gcc non-ISOC99 compilers (#53984) +- prelinking support for Sparc64 + +* Fri Sep 21 2001 Jakub Jelinek 2.2.4-16 +- update from CVS to fix DT_SYMBOLIC +- prelinking support for Alpha and Sparc + +* Tue Sep 18 2001 Jakub Jelinek 2.2.4-15 +- update from CVS + - linuxthreads now retries if -1/EINTR is returned from + reading or writing to thread manager pipe (#43742) +- use DT_FILTER in librt.so (#53394) + - update glibc prelink patch so that it handles filters +- fix timer_* with SIGEV_NONE (#53494) +- make glibc_post_upgrade work on PPC (patch from Franz Sirl) + +* Mon Sep 10 2001 Jakub Jelinek 2.2.4-14 +- fix build on sparc32 +- 2.2.4-13 build for some reason missed some locales + on alpha/ia64 + +* Mon Sep 3 2001 Jakub Jelinek 2.2.4-13 +- fix iconvconfig + +* Mon Sep 3 2001 Jakub Jelinek 2.2.4-12 +- add fam to /etc/rpc (#52863) +- fix for C++ (#52960) +- fix perror + +* Mon Aug 27 2001 Jakub Jelinek 2.2.4-11 +- fix strnlen(x, -1) + +* Mon Aug 27 2001 Jakub Jelinek 2.2.4-10 +- doh, should only define __libc_rwlock_t + if __USE_UNIX98. + +* Mon Aug 27 2001 Jakub Jelinek 2.2.4-9 +- fix bits/libc-lock.h so that gcc can compile +- fix s390 build + +* Fri Aug 24 2001 Jakub Jelinek 2.2.4-8 +- kill stale library symlinks in ldconfig (#52350) +- fix inttypes.h for G++ < 3.0 +- use DT_REL*COUNT + +* Wed Aug 22 2001 Jakub Jelinek 2.2.4-7 +- fix strnlen on IA-64 (#50077) + +* Thu Aug 16 2001 Jakub Jelinek 2.2.4-6 +- glibc 2.2.4 final +- fix -lpthread -static (#51672) + +* Fri Aug 10 2001 Jakub Jelinek 2.2.4-5 +- doh, include libio/tst-swscanf.c + +* Fri Aug 10 2001 Jakub Jelinek 2.2.4-4 +- don't crash on catclose(-1) +- fix wscanf %%[] handling +- fix return value from swprintf +- handle year + %%U/%%W week + week day in strptime + +* Thu Aug 9 2001 Jakub Jelinek 2.2.4-3 +- update from CVS to + - fix strcoll (#50548) + - fix seekdir (#51132) + - fix memusage (#50606) +- don't make gconv-modules.cache %%config file, just don't verify + its content. + +* Mon Aug 6 2001 Jakub Jelinek +- fix strtod and *scanf (#50723, #50724) + +* Sat Aug 4 2001 Jakub Jelinek +- update from CVS + - fix iconv cache handling +- glibc should not own %%{_infodir}, %%{_mandir} nor %%{_mandir}/man3 (#50673) +- add gconv-modules.cache as emtpy config file (#50699) +- only run iconvconfig if /usr is mounted read-write (#50667) + +* Wed Jul 25 2001 Jakub Jelinek +- move iconvconfig from glibc-common into glibc subpackage, + call it from glibc_post_upgrade instead of common's post. + +* Tue Jul 24 2001 Jakub Jelinek +- turn off debugging printouts in iconvconfig + +* Tue Jul 24 2001 Jakub Jelinek +- update from CVS + - fix IA-32 makecontext + - make fflush(0) thread-safe (#46446) + +* Mon Jul 23 2001 Jakub Jelinek +- adjust prelinking DT_* and SHT_* values in elf.h +- update from CVS + - iconv cache + - make iconv work in SUID/SGID programs (#34611) + +* Fri Jul 20 2001 Jakub Jelinek +- update from CVS + - kill non-pic code in libm.so + - fix getdate + - fix some locales (#49402) +- rebuilt with binutils-2.11.90.0.8-5 to place .interp section + properly in libBrokenLocale.so, libNoVersion.so and libanl.so +- add floating stacks on IA-64, Alpha, Sparc (#49308) + +* Mon Jul 16 2001 Jakub Jelinek +- make /lib/i686 directory owned by glibc*.i686.rpm + +* Mon Jul 9 2001 Jakub Jelinek +- remove rquota.[hx] headers which are now provided by quota (#47141) +- add prelinking patch + +* Thu Jul 5 2001 Jakub Jelinek +- require sh-utils for nscd + +* Mon Jun 25 2001 Jakub Jelinek +- update from CVS (#43681, #43350, #44663, #45685) +- fix ro_RO bug (#44644) + +* Wed Jun 6 2001 Jakub Jelinek +- fix a bunch of math bugs (#43210, #43345, #43346, #43347, #43348, #43355) +- make rpc headers -ansi compilable (#42390) +- remove alphaev6 optimized memcpy, since there are still far too many + broken apps which call memcpy where they should call memmove +- update from CVS to (among other things): + - fix tanhl bug (#43352) + +* Tue May 22 2001 Jakub Jelinek +- fix #include with -D_XOPEN_SOURCE=500 on ia64 (#35968) +- fix a dlclose reldeps handling bug +- some more profiling fixes +- fix tgmath.h + +* Thu May 17 2001 Jakub Jelinek +- make ldconfig more quiet +- fix LD_PROFILE on i686 (#41030) + +* Wed May 16 2001 Jakub Jelinek +- fix the hardlink program, so that it really catches all files with + identical content +- add a s390x clone fix + +* Wed May 16 2001 Jakub Jelinek +- fix rpc for non-threaded apps using svc_fdset and similar variables (#40409) +- fix nss compatibility DSO versions for alphaev6 +- add a hardlink program instead of the shell 3x for plus cmp -s/link + which takes a lot of time during build +- rework BuildPreReq and Conflicts with gcc, so that + it applies only where it has to + +* Fri May 11 2001 Jakub Jelinek +- fix locale name of ja_JP in UTF-8 (#39783) +- fix re_search_2 (#40244) +- fix memusage script (#39138, #39823) +- fix dlsym(RTLD_NEXT, ) from main program (#39803) +- fix xtrace script (#39609) +- make glibc conflict with glibc-devel 2.2.2 and below (to make sure + libc_nonshared.a has atexit) +- fix getconf LFS_CFLAGS on 64bitters +- recompile with gcc-2.96-84 or above to fix binary compatibility problem + with __frame_state_for function (#37933) + +* Fri Apr 27 2001 Jakub Jelinek +- glibc 2.2.3 release + - fix strcoll (#36539) +- add BuildPreReqs (#36378) + +* Wed Apr 25 2001 Jakub Jelinek +- update from CVS + +* Fri Apr 20 2001 Jakub Jelinek +- update from CVS + - fix sparc64, ia64 + - fix some locale syntax errors (#35982) + +* Wed Apr 18 2001 Jakub Jelinek +- update from CVS + +* Wed Apr 11 2001 Jakub Jelinek +- update from CVS + +* Fri Apr 6 2001 Jakub Jelinek +- support even 2.4.0 kernels on ia64, sparc64 and s390x +- include UTF-8 locales +- make gconv-modules %%config(noreplace) + +* Fri Mar 23 2001 Jakub Jelinek +- back out sunrpc changes + +* Wed Mar 21 2001 Jakub Jelinek +- update from CVS + - fix ia64 build + - fix pthread_getattr_np + +* Fri Mar 16 2001 Jakub Jelinek +- update from CVS + - run atexit() registered functions at dlclose time if they are in shared + libraries (#28625) + - add pthread_getattr_np API to make JVM folks happy + +* Wed Mar 14 2001 Jakub Jelinek +- require 2.4.1 instead of 2.4.0 on platforms where it required 2.4 kernel +- fix ldd behaviour on unresolved symbols +- remove nonsensical ldconfig warning, update osversion for the most + recent library with the same soname in the same directory instead (#31703) +- apply selected patches from CVS +- s390x spec file changes from Florian La Roche + +* Wed Mar 7 2001 Jakub Jelinek +- fix gencat (#30894) +- fix ldconfig changes from yesterday, fix LD_ASSUME_KERNEL handling + +* Tue Mar 6 2001 Jakub Jelinek +- update from CVS +- make pthread_attr_setstacksize consistent before and after pthread manager + is started (#28194) +- pass back struct sigcontext from pthread signal wrapper (on ia32 only so + far, #28493) +- on i686 ship both --enable-kernel 2.2.5 and 2.4.0 libc/libm/libpthread, + make ld.so pick the right one + +* Sat Feb 17 2001 Preston Brown +- glib-common doesn't require glibc, until we can figure out how to get out of dependency hell. + +* Sat Feb 17 2001 Jakub Jelinek +- make glibc require particular version of glibc-common + and glibc-common prerequire glibc. + +* Fri Feb 16 2001 Jakub Jelinek +- glibc 2.2.2 release + - fix regex REG_ICASE bug seen in ksymoops + +* Sat Feb 10 2001 Jakub Jelinek +- fix regexec leaking memory (#26864) + +* Fri Feb 9 2001 Jakub Jelinek +- update from CVS + - fix ia64 build with gnupro + - make regex 64bit clean + - fix tgmath make check failures on alpha + +* Tue Feb 6 2001 Jakub Jelinek +- update again for ia64 DF_1_INITFIRST + +* Fri Feb 2 2001 Jakub Jelinek +- update from CVS + - fix getaddrinfo (#25437) + - support DF_1_INITFIRST (#25029) + +* Wed Jan 24 2001 Jakub Jelinek +- build all auxiliary arches with --enablekernel 2.4.0, those wanting + to run 2.2 kernels can downgrade to the base architecture glibc. + +* Sat Jan 20 2001 Jakub Jelinek +- remove %%lang() flags from %%{_prefix}/lib/locale files temporarily + +* Sun Jan 14 2001 Jakub Jelinek +- update to 2.2.1 final + - fix a pthread_kill_other_threads_np breakage (#23966) + - make static binaries using dlopen work on ia64 again +- fix a typo in glibc-common group + +* Wed Jan 10 2001 Bernhard Rosenkraenzer +- devel requires glibc = %%{version} +- noreplace /etc/nscd.conf + +* Wed Jan 10 2001 Jakub Jelinek +- some more security fixes: + - don't look up LD_PRELOAD libs in cache for SUID apps + (because that bypasses SUID bit checking on the library) + - place output files for profiling SUID apps into /var/profile, + use O_NOFOLLOW for them + - add checks for $MEMUSAGE_OUTPUT and $SEGFAULT_OUTPUT_NAME +- hardlink identical locale files together +- add %%lang() tags to locale stuff +- remove ko_KR.utf8 for now, it is provided by locale-utf8 package + +* Mon Jan 8 2001 Jakub Jelinek +- add glibc-common subpackage +- fix alphaev6 memcpy (#22494) +- fix sys/cdefs.h (#22908) +- don't define stdin/stdout/stderr as macros for -traditional (#22913) +- work around a bug in IBM JDK (#22932, #23012) +- fix pmap_unset when network is down (#23176) +- move nscd in rc.d before netfs on shutdown +- fix $RESOLV_HOST_CONF in SUID apps (#23562) + +* Fri Dec 15 2000 Jakub Jelinek +- fix ftw and nftw + +* Wed Dec 13 2000 Jakub Jelinek +- fix fcvt (#22184) +- ldd /lib/ld-linux.so.2 is not crashing any longer again (#22197) +- fix gencat + +* Mon Dec 11 2000 Jakub Jelinek +- fix alpha htonl and alphaev6 stpcpy + +* Sat Dec 9 2000 Jakub Jelinek +- update to CVS to: + - fix getnameinfo (#21934) + - don't stomp on memory in rpath handling (#21544) + - fix setlocale (#21507) +- fix libNoVersion.so.1 loading code (#21579) +- use auxarches define in spec file for auxiliary + architectures (#21219) +- remove /usr/share directory from filelist (#21218) + +* Sun Nov 19 2000 Jakub Jelinek +- update to CVS to fix getaddrinfo + +* Fri Nov 17 2000 Jakub Jelinek +- update to CVS to fix freopen +- remove all alpha workarounds, not needed anymore + +* Wed Nov 15 2000 Jakub Jelinek +- fix dladdr bug on alpha/sparc32/sparc64 +- fix Makefiles so that they run static tests properly + +* Tue Nov 14 2000 Jakub Jelinek +- update to CVS to fix ldconfig + +* Thu Nov 9 2000 Jakub Jelinek +- update to glibc 2.2 release + +* Mon Nov 6 2000 Jakub Jelinek +- update to CVS to: + - export __sysconf@@GLIBC_2.2 (#20417) + +* Fri Nov 3 2000 Jakub Jelinek +- merge to 2.1.97 + +* Mon Oct 30 2000 Jakub Jelinek +- update to CVS, including: + - fix WORD_BIT/LONG_BIT definition in limits.h (#19088) + - fix hesiod (#19375) + - set LC_MESSAGES in zic/zdump for proper error message output (#19495) + - fix LFS fcntl when used with non-LFS aware kernels (#19730) + +* Thu Oct 19 2000 Jakub Jelinek +- fix alpha semctl (#19199) +- update to CVS, including: + - fix glibc headers for Compaq non-gcc compilers + - fix locale alias handling code (#18832) + - fix rexec on little endian machines (#18886) +- started writing changelog again + +* Thu Aug 10 2000 Adrian Havill +- added ja ujis alias for backwards compatibility diff --git a/Decrease-value-of-arch_minimum_kernel-with-LoongArch.patch b/Decrease-value-of-arch_minimum_kernel-with-LoongArch.patch deleted file mode 100644 index 0c43817..0000000 --- a/Decrease-value-of-arch_minimum_kernel-with-LoongArch.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 2c8dfc45a8009e5110a9d2148b62d802e989fde7 Mon Sep 17 00:00:00 2001 -From: ticat_fp -Date: Thu, 29 Feb 2024 15:58:31 +0800 -Subject: [PATCH] Decrease value of arch_minimum_kernel with LoongArch - -Signed-off-by: ticat_fp ---- - sysdeps/unix/sysv/linux/loongarch/configure | 2 +- - sysdeps/unix/sysv/linux/loongarch/configure.ac | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/sysdeps/unix/sysv/linux/loongarch/configure b/sysdeps/unix/sysv/linux/loongarch/configure -index 0d1159e9..851b2285 100644 ---- a/sysdeps/unix/sysv/linux/loongarch/configure -+++ b/sysdeps/unix/sysv/linux/loongarch/configure -@@ -1,7 +1,7 @@ - # This file is generated from configure.ac by Autoconf. DO NOT EDIT! - # Local configure fragment for sysdeps/unix/sysv/linux/loongarch. - --arch_minimum_kernel=5.19.0 -+arch_minimum_kernel=4.19.0 - - libc_cv_loongarch_int_abi=no - -diff --git a/sysdeps/unix/sysv/linux/loongarch/configure.ac b/sysdeps/unix/sysv/linux/loongarch/configure.ac -index 04e9150a..00815c2f 100644 ---- a/sysdeps/unix/sysv/linux/loongarch/configure.ac -+++ b/sysdeps/unix/sysv/linux/loongarch/configure.ac -@@ -2,7 +2,7 @@ sinclude(./aclocal.m4)dnl Autoconf lossage - GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. - # Local configure fragment for sysdeps/unix/sysv/linux/loongarch. - --arch_minimum_kernel=5.19.0 -+arch_minimum_kernel=4.19.0 - - libc_cv_loongarch_int_abi=no - AC_EGREP_CPP(4 8 8, [__SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_POINTER__ --- -2.33.0 - diff --git a/LoongArch-Add-glibc.cpu.hwcap-support.patch b/LoongArch-Add-glibc.cpu.hwcap-support.patch deleted file mode 100644 index 3629d05..0000000 --- a/LoongArch-Add-glibc.cpu.hwcap-support.patch +++ /dev/null @@ -1,499 +0,0 @@ -From 8923e4e9c79e672fd6b3b89aba598a60d5c01211 Mon Sep 17 00:00:00 2001 -From: caiyinyu -Date: Fri, 15 Sep 2023 17:35:19 +0800 -Subject: [PATCH 25/29] LoongArch: Add glibc.cpu.hwcap support. - -Key Points: -1. On lasx & lsx platforms, We must use _dl_runtime_{profile, resolve}_{lsx, lasx} - to save vector registers. -2. Via "tunables", users can choose str/mem_{lasx,lsx,unaligned} functions with - `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,...`. - Note: glibc.cpu.hwcaps doesn't affect _dl_runtime_{profile, resolve}_{lsx, lasx} - selection. - -Usage Notes: -1. Only valid inputs: LASX, LSX, UAL. Case-sensitive, comma-separated, no spaces. -2. Example: `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL` turns on LASX & UAL. - Unmentioned features turn off. With default ifunc: lasx > lsx > unaligned > - aligned > generic, effect is: lasx > unaligned > aligned > generic; lsx off. -3. Incorrect GLIBC_TUNABLES settings will show error messages. - For example: On lsx platforms, you cannot enable lasx features. If you do - that, you will get error messages. -4. Valid input examples: - - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX: lasx > aligned > generic. - - GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX,UAL: lsx > unaligned > aligned > generic. - - GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL,LASX,UAL,LSX,LASX,UAL: Repetitions - allowed but not recommended. Results in: lasx > lsx > unaligned > aligned > - generic. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/Makefile | 4 + - sysdeps/loongarch/Versions | 5 ++ - sysdeps/loongarch/cpu-tunables.c | 89 +++++++++++++++++++ - sysdeps/loongarch/dl-get-cpu-features.c | 25 ++++++ - sysdeps/loongarch/dl-machine.h | 27 +++++- - sysdeps/loongarch/dl-tunables.list | 25 ++++++ - .../unix/sysv/linux/loongarch/cpu-features.c | 29 ++++++ - .../unix/sysv/linux/loongarch/cpu-features.h | 18 +++- - .../unix/sysv/linux/loongarch/dl-procinfo.c | 60 +++++++++++++ - sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c | 21 +++++ - .../unix/sysv/linux/loongarch/libc-start.c | 34 +++++++ - 11 files changed, 329 insertions(+), 8 deletions(-) - create mode 100644 sysdeps/loongarch/Versions - create mode 100644 sysdeps/loongarch/cpu-tunables.c - create mode 100644 sysdeps/loongarch/dl-get-cpu-features.c - create mode 100644 sysdeps/loongarch/dl-tunables.list - create mode 100644 sysdeps/unix/sysv/linux/loongarch/cpu-features.c - create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c - create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c - create mode 100644 sysdeps/unix/sysv/linux/loongarch/libc-start.c - -diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile -index 43d2f583..30a1f4a8 100644 ---- a/sysdeps/loongarch/Makefile -+++ b/sysdeps/loongarch/Makefile -@@ -6,6 +6,10 @@ ifeq ($(subdir),elf) - gen-as-const-headers += dl-link.sym - endif - -+ifeq ($(subdir),elf) -+ sysdep-dl-routines += dl-get-cpu-features -+endif -+ - # LoongArch's assembler also needs to know about PIC as it changes the - # definition of some assembler macros. - ASFLAGS-.os += $(pic-ccflag) -diff --git a/sysdeps/loongarch/Versions b/sysdeps/loongarch/Versions -new file mode 100644 -index 00000000..33ae2cc0 ---- /dev/null -+++ b/sysdeps/loongarch/Versions -@@ -0,0 +1,5 @@ -+ld { -+ GLIBC_PRIVATE { -+ _dl_larch_get_cpu_features; -+ } -+} -diff --git a/sysdeps/loongarch/cpu-tunables.c b/sysdeps/loongarch/cpu-tunables.c -new file mode 100644 -index 00000000..8e9fab93 ---- /dev/null -+++ b/sysdeps/loongarch/cpu-tunables.c -@@ -0,0 +1,89 @@ -+/* LoongArch CPU feature tuning. -+ This file is part of the GNU C Library. -+ Copyright (C) 2023 Free Software Foundation, Inc. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+# include -+# include -+# include /* Get STDOUT_FILENO for _dl_printf. */ -+# include -+# include -+# include -+# include -+# include -+ -+# define HWCAP_LOONGARCH_IFUNC \ -+ (HWCAP_LOONGARCH_UAL | HWCAP_LOONGARCH_LSX | HWCAP_LOONGARCH_LASX) -+ -+# define CHECK_GLIBC_IFUNC_CPU_OFF(f, name, len) \ -+ _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \ -+ if (!memcmp (f, #name, len) && \ -+ (GLRO (dl_hwcap) & HWCAP_LOONGARCH_##name)) \ -+ { \ -+ hwcap |= (HWCAP_LOONGARCH_##name | (~HWCAP_LOONGARCH_IFUNC)); \ -+ break; \ -+ } \ -+ -+attribute_hidden -+void -+TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp) -+{ -+ const char *p = valp->strval; -+ size_t len; -+ unsigned long hwcap = 0; -+ const char *c; -+ -+ do { -+ for (c = p; *c != ','; c++) -+ if (*c == '\0') -+ break; -+ -+ len = c - p; -+ -+ switch(len) -+ { -+ default: -+ _dl_fatal_printf ( -+ "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n" -+ ); -+ break; -+ case 3: -+ { -+ CHECK_GLIBC_IFUNC_CPU_OFF (p, LSX, 3); -+ CHECK_GLIBC_IFUNC_CPU_OFF (p, UAL, 3); -+ _dl_fatal_printf ( -+ "Some features are invalid or not supported on this machine!!\n" -+ "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n" -+ ); -+ } -+ break; -+ case 4: -+ { -+ CHECK_GLIBC_IFUNC_CPU_OFF (p, LASX, 4); -+ _dl_fatal_printf ( -+ "Some features are invalid or not supported on this machine!!\n" -+ "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n" -+ ); -+ } -+ break; -+ } -+ -+ p += len + 1; -+ } -+ while (*c != '\0'); -+ -+ GLRO (dl_larch_cpu_features).hwcap &= hwcap; -+} -diff --git a/sysdeps/loongarch/dl-get-cpu-features.c b/sysdeps/loongarch/dl-get-cpu-features.c -new file mode 100644 -index 00000000..7cd9bc15 ---- /dev/null -+++ b/sysdeps/loongarch/dl-get-cpu-features.c -@@ -0,0 +1,25 @@ -+/* Define _dl_larch_get_cpu_features. -+ Copyright (C) 2023 Free Software Foundation, Inc. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+ -+#include -+ -+const struct cpu_features * -+_dl_larch_get_cpu_features (void) -+{ -+ return &GLRO(dl_larch_cpu_features); -+} -diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h -index 57913cef..b395a928 100644 ---- a/sysdeps/loongarch/dl-machine.h -+++ b/sysdeps/loongarch/dl-machine.h -@@ -29,6 +29,8 @@ - #include - #include - -+#include -+ - #ifndef _RTLD_PROLOGUE - # define _RTLD_PROLOGUE(entry) \ - ".globl\t" __STRING (entry) "\n\t" \ -@@ -53,6 +55,23 @@ - #define ELF_MACHINE_NO_REL 1 - #define ELF_MACHINE_NO_RELA 0 - -+#define DL_PLATFORM_INIT dl_platform_init () -+ -+static inline void __attribute__ ((unused)) -+dl_platform_init (void) -+{ -+ if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0') -+ /* Avoid an empty string which would disturb us. */ -+ GLRO(dl_platform) = NULL; -+ -+#ifdef SHARED -+ /* init_cpu_features has been called early from __libc_start_main in -+ static executable. */ -+ init_cpu_features (&GLRO(dl_larch_cpu_features)); -+#endif -+} -+ -+ - /* Return nonzero iff ELF header is compatible with the running host. */ - static inline int - elf_machine_matches_host (const ElfW (Ehdr) *ehdr) -@@ -290,9 +309,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], - if (profile != 0) - { - #if !defined __loongarch_soft_float -- if (SUPPORT_LASX) -+ if (RTLD_SUPPORT_LASX) - gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lasx; -- else if (SUPPORT_LSX) -+ else if (RTLD_SUPPORT_LSX) - gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lsx; - else - #endif -@@ -310,9 +329,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], - indicated by the offset on the stack, and then jump to - the resolved address. */ - #if !defined __loongarch_soft_float -- if (SUPPORT_LASX) -+ if (RTLD_SUPPORT_LASX) - gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lasx; -- else if (SUPPORT_LSX) -+ else if (RTLD_SUPPORT_LSX) - gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lsx; - else - #endif -diff --git a/sysdeps/loongarch/dl-tunables.list b/sysdeps/loongarch/dl-tunables.list -new file mode 100644 -index 00000000..66b34275 ---- /dev/null -+++ b/sysdeps/loongarch/dl-tunables.list -@@ -0,0 +1,25 @@ -+# LoongArch specific tunables. -+# Copyright (C) 2023 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 -+# . -+ -+glibc { -+ cpu { -+ hwcaps { -+ type: STRING -+ } -+ } -+} -diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.c b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c -new file mode 100644 -index 00000000..1290c4ce ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c -@@ -0,0 +1,29 @@ -+/* Initialize CPU feature data. LoongArch64 version. -+ This file is part of the GNU C Library. -+ Copyright (C) 2023 Free Software Foundation, Inc. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+#include -+#include -+extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) attribute_hidden; -+ -+static inline void -+init_cpu_features (struct cpu_features *cpu_features) -+{ -+ GLRO (dl_larch_cpu_features).hwcap = GLRO (dl_hwcap); -+ TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps)); -+} -diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h -index d1a280a5..450963ce 100644 ---- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h -+++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h -@@ -19,13 +19,23 @@ - #ifndef _CPU_FEATURES_LOONGARCH64_H - #define _CPU_FEATURES_LOONGARCH64_H - -+#include - #include - --#define SUPPORT_UAL (GLRO (dl_hwcap) & HWCAP_LOONGARCH_UAL) --#define SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX) --#define SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX) -+struct cpu_features -+ { -+ uint64_t hwcap; -+ }; - -+/* Get a pointer to the CPU features structure. */ -+extern const struct cpu_features *_dl_larch_get_cpu_features (void) -+ __attribute__ ((pure)); -+ -+#define SUPPORT_UAL (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_UAL) -+#define SUPPORT_LSX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LSX) -+#define SUPPORT_LASX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LASX) -+#define RTLD_SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX) -+#define RTLD_SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX) - #define INIT_ARCH() - - #endif /* _CPU_FEATURES_LOONGARCH64_H */ -- -diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c -new file mode 100644 -index 00000000..6217fda9 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c -@@ -0,0 +1,60 @@ -+/* Data for LoongArch64 version of processor capability information. -+ Linux version. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* If anything should be added here check whether the size of each string -+ is still ok with the given array size. -+ -+ All the #ifdefs in the definitions are quite irritating but -+ necessary if we want to avoid duplicating the information. There -+ are three different modes: -+ -+ - PROCINFO_DECL is defined. This means we are only interested in -+ declarations. -+ -+ - PROCINFO_DECL is not defined: -+ -+ + if SHARED is defined the file is included in an array -+ initializer. The .element = { ... } syntax is needed. -+ -+ + if SHARED is not defined a normal array initialization is -+ needed. -+ */ -+ -+#ifndef PROCINFO_CLASS -+# define PROCINFO_CLASS -+#endif -+ -+#if !IS_IN (ldconfig) -+# if !defined PROCINFO_DECL && defined SHARED -+ ._dl_larch_cpu_features -+# else -+PROCINFO_CLASS struct cpu_features _dl_larch_cpu_features -+# endif -+# ifndef PROCINFO_DECL -+= { } -+# endif -+# if !defined SHARED || defined PROCINFO_DECL -+; -+# else -+, -+# endif -+#endif -+ -+#undef PROCINFO_DECL -+#undef PROCINFO_CLASS -diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c -new file mode 100644 -index 00000000..455fd71a ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c -@@ -0,0 +1,21 @@ -+/* Operating system support for run-time dynamic linker. LoongArch version. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -diff --git a/sysdeps/unix/sysv/linux/loongarch/libc-start.c b/sysdeps/unix/sysv/linux/loongarch/libc-start.c -new file mode 100644 -index 00000000..f1346ece ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/libc-start.c -@@ -0,0 +1,34 @@ -+/* Override csu/libc-start.c on LoongArch64. -+ Copyright (C) 2023 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 -+ . */ -+ -+#ifndef SHARED -+ -+/* Mark symbols hidden in static PIE for early self relocation to work. */ -+# if BUILD_PIE_DEFAULT -+# pragma GCC visibility push(hidden) -+# endif -+ -+# include -+# include -+ -+extern struct cpu_features _dl_larch_cpu_features; -+ -+# define ARCH_INIT_CPU_FEATURES() init_cpu_features (&_dl_larch_cpu_features) -+ -+#endif -+#include --- -2.33.0 - diff --git a/LoongArch-Add-ifunc-support-for-memchr-aligned-lsx-l.patch b/LoongArch-Add-ifunc-support-for-memchr-aligned-lsx-l.patch deleted file mode 100644 index ad7e613..0000000 --- a/LoongArch-Add-ifunc-support-for-memchr-aligned-lsx-l.patch +++ /dev/null @@ -1,485 +0,0 @@ -From 3ee56bbc56faa7b85a6513340db4a4fdd6ce709d Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Mon, 28 Aug 2023 10:08:36 +0800 -Subject: [PATCH 15/29] LoongArch: Add ifunc support for memchr{aligned, lsx, - lasx} - -According to glibc memchr microbenchmark, this implementation could reduce -the runtime as following: - -Name Percent of runtime reduced -memchr-lasx 37%-83% -memchr-lsx 30%-66% -memchr-aligned 0%-15% - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/Makefile | 3 + - .../lp64/multiarch/ifunc-impl-list.c | 7 ++ - .../loongarch/lp64/multiarch/ifunc-memchr.h | 40 ++++++ - .../loongarch/lp64/multiarch/memchr-aligned.S | 95 ++++++++++++++ - .../loongarch/lp64/multiarch/memchr-lasx.S | 117 ++++++++++++++++++ - sysdeps/loongarch/lp64/multiarch/memchr-lsx.S | 102 +++++++++++++++ - sysdeps/loongarch/lp64/multiarch/memchr.c | 37 ++++++ - 7 files changed, 401 insertions(+) - create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-memchr.h - create mode 100644 sysdeps/loongarch/lp64/multiarch/memchr-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memchr-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memchr-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memchr.c - -diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile -index 64416b02..2f4802cf 100644 ---- a/sysdeps/loongarch/lp64/multiarch/Makefile -+++ b/sysdeps/loongarch/lp64/multiarch/Makefile -@@ -24,5 +24,8 @@ sysdep_routines += \ - rawmemchr-aligned \ - rawmemchr-lsx \ - rawmemchr-lasx \ -+ memchr-aligned \ -+ memchr-lsx \ -+ memchr-lasx \ - # sysdep_routines - endif -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -index 3db9af14..a567b9cf 100644 ---- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -@@ -102,5 +102,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, - IFUNC_IMPL_ADD (array, i, rawmemchr, 1, __rawmemchr_aligned) - ) - -+ IFUNC_IMPL (i, name, memchr, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, memchr, SUPPORT_LASX, __memchr_lasx) -+ IFUNC_IMPL_ADD (array, i, memchr, SUPPORT_LSX, __memchr_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, memchr, 1, __memchr_aligned) -+ ) - return i; - } -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-memchr.h b/sysdeps/loongarch/lp64/multiarch/ifunc-memchr.h -new file mode 100644 -index 00000000..9060ccd5 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-memchr.h -@@ -0,0 +1,40 @@ -+/* Common definition for memchr ifunc selections. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+ -+#if !defined __loongarch_soft_float -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden; -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden; -+#endif -+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden; -+ -+static inline void * -+IFUNC_SELECTOR (void) -+{ -+#if !defined __loongarch_soft_float -+ if (SUPPORT_LASX) -+ return OPTIMIZE (lasx); -+ else if (SUPPORT_LSX) -+ return OPTIMIZE (lsx); -+ else -+#endif -+ return OPTIMIZE (aligned); -+} -diff --git a/sysdeps/loongarch/lp64/multiarch/memchr-aligned.S b/sysdeps/loongarch/lp64/multiarch/memchr-aligned.S -new file mode 100644 -index 00000000..81d0d004 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memchr-aligned.S -@@ -0,0 +1,95 @@ -+/* Optimized memchr implementation using basic LoongArch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+# define MEMCHR_NAME __memchr_aligned -+#else -+# define MEMCHR_NAME memchr -+#endif -+ -+LEAF(MEMCHR_NAME, 6) -+ beqz a2, L(out) -+ andi t1, a0, 0x7 -+ add.d a5, a0, a2 -+ bstrins.d a0, zero, 2, 0 -+ -+ ld.d t0, a0, 0 -+ bstrins.d a1, a1, 15, 8 -+ lu12i.w a3, 0x01010 -+ slli.d t2, t1, 03 -+ -+ bstrins.d a1, a1, 31, 16 -+ ori a3, a3, 0x101 -+ li.d t7, -1 -+ li.d t8, 8 -+ -+ bstrins.d a1, a1, 63, 32 -+ bstrins.d a3, a3, 63, 32 -+ sll.d t2, t7, t2 -+ xor t0, t0, a1 -+ -+ -+ addi.d a6, a5, -1 -+ slli.d a4, a3, 7 -+ sub.d t1, t8, t1 -+ orn t0, t0, t2 -+ -+ sub.d t2, t0, a3 -+ andn t3, a4, t0 -+ bstrins.d a6, zero, 2, 0 -+ and t0, t2, t3 -+ -+ bgeu t1, a2, L(end) -+L(loop): -+ bnez t0, L(found) -+ ld.d t1, a0, 8 -+ xor t0, t1, a1 -+ -+ addi.d a0, a0, 8 -+ sub.d t2, t0, a3 -+ andn t3, a4, t0 -+ and t0, t2, t3 -+ -+ -+ bne a0, a6, L(loop) -+L(end): -+ sub.d t1, a5, a6 -+ ctz.d t0, t0 -+ srli.d t0, t0, 3 -+ -+ sltu t1, t0, t1 -+ add.d a0, a0, t0 -+ maskeqz a0, a0, t1 -+ jr ra -+ -+L(found): -+ ctz.d t0, t0 -+ srli.d t0, t0, 3 -+ add.d a0, a0, t0 -+ jr ra -+ -+L(out): -+ move a0, zero -+ jr ra -+END(MEMCHR_NAME) -+ -+libc_hidden_builtin_def (MEMCHR_NAME) -diff --git a/sysdeps/loongarch/lp64/multiarch/memchr-lasx.S b/sysdeps/loongarch/lp64/multiarch/memchr-lasx.S -new file mode 100644 -index 00000000..a26cdf48 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memchr-lasx.S -@@ -0,0 +1,117 @@ -+/* Optimized memchr implementation using LoongArch LASX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define MEMCHR __memchr_lasx -+ -+LEAF(MEMCHR, 6) -+ beqz a2, L(ret0) -+ add.d a3, a0, a2 -+ andi t0, a0, 0x3f -+ bstrins.d a0, zero, 5, 0 -+ -+ xvld xr0, a0, 0 -+ xvld xr1, a0, 32 -+ li.d t1, -1 -+ li.d t2, 64 -+ -+ xvreplgr2vr.b xr2, a1 -+ sll.d t3, t1, t0 -+ sub.d t2, t2, t0 -+ xvseq.b xr0, xr0, xr2 -+ -+ xvseq.b xr1, xr1, xr2 -+ xvmsknz.b xr0, xr0 -+ xvmsknz.b xr1, xr1 -+ xvpickve.w xr3, xr0, 4 -+ -+ -+ xvpickve.w xr4, xr1, 4 -+ vilvl.h vr0, vr3, vr0 -+ vilvl.h vr1, vr4, vr1 -+ vilvl.w vr0, vr1, vr0 -+ -+ movfr2gr.d t0, fa0 -+ and t0, t0, t3 -+ bgeu t2, a2, L(end) -+ bnez t0, L(found) -+ -+ addi.d a4, a3, -1 -+ bstrins.d a4, zero, 5, 0 -+L(loop): -+ xvld xr0, a0, 64 -+ xvld xr1, a0, 96 -+ -+ addi.d a0, a0, 64 -+ xvseq.b xr0, xr0, xr2 -+ xvseq.b xr1, xr1, xr2 -+ beq a0, a4, L(out) -+ -+ -+ xvmax.bu xr3, xr0, xr1 -+ xvseteqz.v fcc0, xr3 -+ bcnez fcc0, L(loop) -+ xvmsknz.b xr0, xr0 -+ -+ xvmsknz.b xr1, xr1 -+ xvpickve.w xr3, xr0, 4 -+ xvpickve.w xr4, xr1, 4 -+ vilvl.h vr0, vr3, vr0 -+ -+ vilvl.h vr1, vr4, vr1 -+ vilvl.w vr0, vr1, vr0 -+ movfr2gr.d t0, fa0 -+L(found): -+ ctz.d t1, t0 -+ -+ add.d a0, a0, t1 -+ jr ra -+L(ret0): -+ move a0, zero -+ jr ra -+ -+ -+L(out): -+ xvmsknz.b xr0, xr0 -+ xvmsknz.b xr1, xr1 -+ xvpickve.w xr3, xr0, 4 -+ xvpickve.w xr4, xr1, 4 -+ -+ vilvl.h vr0, vr3, vr0 -+ vilvl.h vr1, vr4, vr1 -+ vilvl.w vr0, vr1, vr0 -+ movfr2gr.d t0, fa0 -+ -+L(end): -+ sub.d t2, zero, a3 -+ srl.d t1, t1, t2 -+ and t0, t0, t1 -+ ctz.d t1, t0 -+ -+ add.d a0, a0, t1 -+ maskeqz a0, a0, t0 -+ jr ra -+END(MEMCHR) -+ -+libc_hidden_builtin_def (MEMCHR) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memchr-lsx.S b/sysdeps/loongarch/lp64/multiarch/memchr-lsx.S -new file mode 100644 -index 00000000..a73ecd25 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memchr-lsx.S -@@ -0,0 +1,102 @@ -+/* Optimized memchr implementation using LoongArch LSX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define MEMCHR __memchr_lsx -+ -+LEAF(MEMCHR, 6) -+ beqz a2, L(ret0) -+ add.d a3, a0, a2 -+ andi t0, a0, 0x1f -+ bstrins.d a0, zero, 4, 0 -+ -+ vld vr0, a0, 0 -+ vld vr1, a0, 16 -+ li.d t1, -1 -+ li.d t2, 32 -+ -+ vreplgr2vr.b vr2, a1 -+ sll.d t3, t1, t0 -+ sub.d t2, t2, t0 -+ vseq.b vr0, vr0, vr2 -+ -+ vseq.b vr1, vr1, vr2 -+ vmsknz.b vr0, vr0 -+ vmsknz.b vr1, vr1 -+ vilvl.h vr0, vr1, vr0 -+ -+ -+ movfr2gr.s t0, fa0 -+ and t0, t0, t3 -+ bgeu t2, a2, L(end) -+ bnez t0, L(found) -+ -+ addi.d a4, a3, -1 -+ bstrins.d a4, zero, 4, 0 -+L(loop): -+ vld vr0, a0, 32 -+ vld vr1, a0, 48 -+ -+ addi.d a0, a0, 32 -+ vseq.b vr0, vr0, vr2 -+ vseq.b vr1, vr1, vr2 -+ beq a0, a4, L(out) -+ -+ vmax.bu vr3, vr0, vr1 -+ vseteqz.v fcc0, vr3 -+ bcnez fcc0, L(loop) -+ vmsknz.b vr0, vr0 -+ -+ -+ vmsknz.b vr1, vr1 -+ vilvl.h vr0, vr1, vr0 -+ movfr2gr.s t0, fa0 -+L(found): -+ ctz.w t0, t0 -+ -+ add.d a0, a0, t0 -+ jr ra -+L(ret0): -+ move a0, zero -+ jr ra -+ -+L(out): -+ vmsknz.b vr0, vr0 -+ vmsknz.b vr1, vr1 -+ vilvl.h vr0, vr1, vr0 -+ movfr2gr.s t0, fa0 -+ -+L(end): -+ sub.d t2, zero, a3 -+ srl.w t1, t1, t2 -+ and t0, t0, t1 -+ ctz.w t1, t0 -+ -+ -+ add.d a0, a0, t1 -+ maskeqz a0, a0, t0 -+ jr ra -+END(MEMCHR) -+ -+libc_hidden_builtin_def (MEMCHR) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memchr.c b/sysdeps/loongarch/lp64/multiarch/memchr.c -new file mode 100644 -index 00000000..059479c0 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memchr.c -@@ -0,0 +1,37 @@ -+/* Multiple versions of memchr. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+#if IS_IN (libc) -+# define memchr __redirect_memchr -+# include -+# undef memchr -+ -+# define SYMBOL_NAME memchr -+# include "ifunc-memchr.h" -+ -+libc_ifunc_redirected (__redirect_memchr, memchr, -+ IFUNC_SELECTOR ()); -+ -+# ifdef SHARED -+__hidden_ver1 (memchr, __GI_memchr, __redirect_memchr) -+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (memchr); -+# endif -+ -+#endif --- -2.33.0 - diff --git a/LoongArch-Add-ifunc-support-for-memcmp-aligned-lsx-l.patch b/LoongArch-Add-ifunc-support-for-memcmp-aligned-lsx-l.patch deleted file mode 100644 index 72c26d0..0000000 --- a/LoongArch-Add-ifunc-support-for-memcmp-aligned-lsx-l.patch +++ /dev/null @@ -1,946 +0,0 @@ -From 60f4bbd1eec528ba8df044ae6b3091f6337a7fcc Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Mon, 28 Aug 2023 10:08:39 +0800 -Subject: [PATCH 18/29] LoongArch: Add ifunc support for memcmp{aligned, lsx, - lasx} - -According to glibc memcmp microbenchmark test results(Add generic -memcmp), this implementation have performance improvement -except the length is less than 3, details as below: - -Name Percent of time reduced -memcmp-lasx 16%-74% -memcmp-lsx 20%-50% -memcmp-aligned 5%-20% - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/Makefile | 3 + - .../lp64/multiarch/ifunc-impl-list.c | 7 + - .../loongarch/lp64/multiarch/ifunc-memcmp.h | 40 +++ - .../loongarch/lp64/multiarch/memcmp-aligned.S | 292 ++++++++++++++++++ - .../loongarch/lp64/multiarch/memcmp-lasx.S | 207 +++++++++++++ - sysdeps/loongarch/lp64/multiarch/memcmp-lsx.S | 269 ++++++++++++++++ - sysdeps/loongarch/lp64/multiarch/memcmp.c | 43 +++ - 7 files changed, 861 insertions(+) - create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-memcmp.h - create mode 100644 sysdeps/loongarch/lp64/multiarch/memcmp-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memcmp-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memcmp-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memcmp.c - -diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile -index 216886c5..360a6718 100644 ---- a/sysdeps/loongarch/lp64/multiarch/Makefile -+++ b/sysdeps/loongarch/lp64/multiarch/Makefile -@@ -34,5 +34,8 @@ sysdep_routines += \ - memset-unaligned \ - memset-lsx \ - memset-lasx \ -+ memcmp-aligned \ -+ memcmp-lsx \ -+ memcmp-lasx \ - # sysdep_routines - endif -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -index 37f60dde..e397d58c 100644 ---- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -@@ -127,5 +127,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, - IFUNC_IMPL_ADD (array, i, memset, 1, __memset_aligned) - ) - -+ IFUNC_IMPL (i, name, memcmp, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, memcmp, SUPPORT_LASX, __memcmp_lasx) -+ IFUNC_IMPL_ADD (array, i, memcmp, SUPPORT_LSX, __memcmp_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, memcmp, 1, __memcmp_aligned) -+ ) - return i; - } -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-memcmp.h b/sysdeps/loongarch/lp64/multiarch/ifunc-memcmp.h -new file mode 100644 -index 00000000..04adc2e5 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-memcmp.h -@@ -0,0 +1,40 @@ -+/* Common definition for memcmp ifunc selections. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+ -+#if !defined __loongarch_soft_float -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden; -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden; -+#endif -+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden; -+ -+static inline void * -+IFUNC_SELECTOR (void) -+{ -+#if !defined __loongarch_soft_float -+ if (SUPPORT_LASX) -+ return OPTIMIZE (lasx); -+ else if (SUPPORT_LSX) -+ return OPTIMIZE (lsx); -+ else -+#endif -+ return OPTIMIZE (aligned); -+} -diff --git a/sysdeps/loongarch/lp64/multiarch/memcmp-aligned.S b/sysdeps/loongarch/lp64/multiarch/memcmp-aligned.S -new file mode 100644 -index 00000000..14a7caa9 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memcmp-aligned.S -@@ -0,0 +1,292 @@ -+/* Optimized memcmp implementation using basic LoongArch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+# define MEMCMP_NAME __memcmp_aligned -+#else -+# define MEMCMP_NAME memcmp -+#endif -+ -+LEAF(MEMCMP_NAME, 6) -+ beqz a2, L(ret) -+ andi a4, a1, 0x7 -+ andi a3, a0, 0x7 -+ sltu a5, a4, a3 -+ -+ xor t0, a0, a1 -+ li.w t8, 8 -+ maskeqz t0, t0, a5 -+ li.w t7, -1 -+ -+ xor a0, a0, t0 -+ xor a1, a1, t0 -+ andi a3, a0, 0x7 -+ andi a4, a1, 0x7 -+ -+ xor a0, a0, a3 -+ xor a1, a1, a4 -+ ld.d t2, a0, 0 -+ ld.d t1, a1, 0 -+ -+ slli.d t3, a3, 3 -+ slli.d t4, a4, 3 -+ sub.d a6, t3, t4 -+ srl.d t1, t1, t4 -+ -+ srl.d t0, t2, t3 -+ srl.d t5, t7, t4 -+ sub.d t6, t0, t1 -+ and t6, t6, t5 -+ -+ sub.d t5, t8, a4 -+ bnez t6, L(first_out) -+ bgeu t5, a2, L(ret) -+ sub.d a2, a2, t5 -+ -+ bnez a6, L(unaligned) -+ blt a2, t8, L(al_less_8bytes) -+ andi t1, a2, 31 -+ beq t1, a2, L(al_less_32bytes) -+ -+ sub.d t2, a2, t1 -+ add.d a4, a0, t2 -+ move a2, t1 -+ -+L(al_loop): -+ ld.d t0, a0, 8 -+ -+ ld.d t1, a1, 8 -+ ld.d t2, a0, 16 -+ ld.d t3, a1, 16 -+ ld.d t4, a0, 24 -+ -+ ld.d t5, a1, 24 -+ ld.d t6, a0, 32 -+ ld.d t7, a1, 32 -+ addi.d a0, a0, 32 -+ -+ addi.d a1, a1, 32 -+ bne t0, t1, L(out1) -+ bne t2, t3, L(out2) -+ bne t4, t5, L(out3) -+ -+ bne t6, t7, L(out4) -+ bne a0, a4, L(al_loop) -+ -+L(al_less_32bytes): -+ srai.d a4, a2, 4 -+ beqz a4, L(al_less_16bytes) -+ -+ ld.d t0, a0, 8 -+ ld.d t1, a1, 8 -+ ld.d t2, a0, 16 -+ ld.d t3, a1, 16 -+ -+ addi.d a0, a0, 16 -+ addi.d a1, a1, 16 -+ addi.d a2, a2, -16 -+ bne t0, t1, L(out1) -+ -+ bne t2, t3, L(out2) -+ -+L(al_less_16bytes): -+ srai.d a4, a2, 3 -+ beqz a4, L(al_less_8bytes) -+ ld.d t0, a0, 8 -+ -+ ld.d t1, a1, 8 -+ addi.d a0, a0, 8 -+ addi.d a1, a1, 8 -+ addi.d a2, a2, -8 -+ -+ bne t0, t1, L(out1) -+ -+L(al_less_8bytes): -+ beqz a2, L(ret) -+ ld.d t0, a0, 8 -+ ld.d t1, a1, 8 -+ -+ li.d t7, -1 -+ slli.d t2, a2, 3 -+ sll.d t2, t7, t2 -+ sub.d t3, t0, t1 -+ -+ andn t6, t3, t2 -+ bnez t6, L(count_diff) -+ -+L(ret): -+ move a0, zero -+ jr ra -+ -+L(out4): -+ move t0, t6 -+ move t1, t7 -+ sub.d t6, t6, t7 -+ b L(count_diff) -+ -+L(out3): -+ move t0, t4 -+ move t1, t5 -+ sub.d t6, t4, t5 -+ b L(count_diff) -+ -+L(out2): -+ move t0, t2 -+ move t1, t3 -+L(out1): -+ sub.d t6, t0, t1 -+ b L(count_diff) -+ -+L(first_out): -+ slli.d t4, a2, 3 -+ slt t3, a2, t5 -+ sll.d t4, t7, t4 -+ maskeqz t4, t4, t3 -+ -+ andn t6, t6, t4 -+ -+L(count_diff): -+ ctz.d t2, t6 -+ bstrins.d t2, zero, 2, 0 -+ srl.d t0, t0, t2 -+ -+ srl.d t1, t1, t2 -+ andi t0, t0, 0xff -+ andi t1, t1, 0xff -+ sub.d t2, t0, t1 -+ -+ sub.d t3, t1, t0 -+ masknez t2, t2, a5 -+ maskeqz t3, t3, a5 -+ or a0, t2, t3 -+ -+ jr ra -+ -+L(unaligned): -+ sub.d a7, zero, a6 -+ srl.d t0, t2, a6 -+ blt a2, t8, L(un_less_8bytes) -+ -+ andi t1, a2, 31 -+ beq t1, a2, L(un_less_32bytes) -+ sub.d t2, a2, t1 -+ add.d a4, a0, t2 -+ -+ move a2, t1 -+ -+L(un_loop): -+ ld.d t2, a0, 8 -+ ld.d t1, a1, 8 -+ ld.d t4, a0, 16 -+ -+ ld.d t3, a1, 16 -+ ld.d t6, a0, 24 -+ ld.d t5, a1, 24 -+ ld.d t8, a0, 32 -+ -+ ld.d t7, a1, 32 -+ addi.d a0, a0, 32 -+ addi.d a1, a1, 32 -+ sll.d a3, t2, a7 -+ -+ or t0, a3, t0 -+ bne t0, t1, L(out1) -+ srl.d t0, t2, a6 -+ sll.d a3, t4, a7 -+ -+ or t2, a3, t0 -+ bne t2, t3, L(out2) -+ srl.d t0, t4, a6 -+ sll.d a3, t6, a7 -+ -+ or t4, a3, t0 -+ bne t4, t5, L(out3) -+ srl.d t0, t6, a6 -+ sll.d a3, t8, a7 -+ -+ or t6, t0, a3 -+ bne t6, t7, L(out4) -+ srl.d t0, t8, a6 -+ bne a0, a4, L(un_loop) -+ -+L(un_less_32bytes): -+ srai.d a4, a2, 4 -+ beqz a4, L(un_less_16bytes) -+ ld.d t2, a0, 8 -+ ld.d t1, a1, 8 -+ -+ ld.d t4, a0, 16 -+ ld.d t3, a1, 16 -+ addi.d a0, a0, 16 -+ addi.d a1, a1, 16 -+ -+ addi.d a2, a2, -16 -+ sll.d a3, t2, a7 -+ or t0, a3, t0 -+ bne t0, t1, L(out1) -+ -+ srl.d t0, t2, a6 -+ sll.d a3, t4, a7 -+ or t2, a3, t0 -+ bne t2, t3, L(out2) -+ -+ srl.d t0, t4, a6 -+ -+L(un_less_16bytes): -+ srai.d a4, a2, 3 -+ beqz a4, L(un_less_8bytes) -+ ld.d t2, a0, 8 -+ -+ ld.d t1, a1, 8 -+ addi.d a0, a0, 8 -+ addi.d a1, a1, 8 -+ addi.d a2, a2, -8 -+ -+ sll.d a3, t2, a7 -+ or t0, a3, t0 -+ bne t0, t1, L(out1) -+ srl.d t0, t2, a6 -+ -+L(un_less_8bytes): -+ beqz a2, L(ret) -+ andi a7, a7, 63 -+ slli.d a4, a2, 3 -+ bgeu a7, a4, L(last_cmp) -+ -+ ld.d t2, a0, 8 -+ sll.d a3, t2, a7 -+ or t0, a3, t0 -+ -+L(last_cmp): -+ ld.d t1, a1, 8 -+ -+ li.d t7, -1 -+ sll.d t2, t7, a4 -+ sub.d t3, t0, t1 -+ andn t6, t3, t2 -+ -+ bnez t6, L(count_diff) -+ move a0, zero -+ jr ra -+END(MEMCMP_NAME) -+ -+libc_hidden_builtin_def (MEMCMP_NAME) -diff --git a/sysdeps/loongarch/lp64/multiarch/memcmp-lasx.S b/sysdeps/loongarch/lp64/multiarch/memcmp-lasx.S -new file mode 100644 -index 00000000..3151a179 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memcmp-lasx.S -@@ -0,0 +1,207 @@ -+/* Optimized memcmp implementation using LoongArch LASX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define MEMCMP __memcmp_lasx -+ -+LEAF(MEMCMP, 6) -+ li.d t2, 32 -+ add.d a3, a0, a2 -+ add.d a4, a1, a2 -+ bgeu t2, a2, L(less32) -+ -+ li.d t1, 160 -+ bgeu a2, t1, L(make_aligned) -+L(loop32): -+ xvld xr0, a0, 0 -+ xvld xr1, a1, 0 -+ -+ addi.d a0, a0, 32 -+ addi.d a1, a1, 32 -+ addi.d a2, a2, -32 -+ xvseq.b xr2, xr0, xr1 -+ -+ xvsetanyeqz.b fcc0, xr2 -+ bcnez fcc0, L(end) -+L(last_bytes): -+ bltu t2, a2, L(loop32) -+ xvld xr0, a3, -32 -+ -+ -+ xvld xr1, a4, -32 -+ xvseq.b xr2, xr0, xr1 -+L(end): -+ xvmsknz.b xr2, xr2 -+ xvpermi.q xr4, xr0, 1 -+ -+ xvpickve.w xr3, xr2, 4 -+ xvpermi.q xr5, xr1, 1 -+ vilvl.h vr2, vr3, vr2 -+ movfr2gr.s t0, fa2 -+ -+ cto.w t0, t0 -+ vreplgr2vr.b vr2, t0 -+ vshuf.b vr0, vr4, vr0, vr2 -+ vshuf.b vr1, vr5, vr1, vr2 -+ -+ vpickve2gr.bu t0, vr0, 0 -+ vpickve2gr.bu t1, vr1, 0 -+ sub.d a0, t0, t1 -+ jr ra -+ -+ -+L(less32): -+ srli.d t0, a2, 4 -+ beqz t0, L(less16) -+ vld vr0, a0, 0 -+ vld vr1, a1, 0 -+ -+ vld vr2, a3, -16 -+ vld vr3, a4, -16 -+L(short_ret): -+ vseq.b vr4, vr0, vr1 -+ vseq.b vr5, vr2, vr3 -+ -+ vmsknz.b vr4, vr4 -+ vmsknz.b vr5, vr5 -+ vilvl.h vr4, vr5, vr4 -+ movfr2gr.s t0, fa4 -+ -+ cto.w t0, t0 -+ vreplgr2vr.b vr4, t0 -+ vshuf.b vr0, vr2, vr0, vr4 -+ vshuf.b vr1, vr3, vr1, vr4 -+ -+ -+ vpickve2gr.bu t0, vr0, 0 -+ vpickve2gr.bu t1, vr1, 0 -+ sub.d a0, t0, t1 -+ jr ra -+ -+L(less16): -+ srli.d t0, a2, 3 -+ beqz t0, L(less8) -+ vldrepl.d vr0, a0, 0 -+ vldrepl.d vr1, a1, 0 -+ -+ vldrepl.d vr2, a3, -8 -+ vldrepl.d vr3, a4, -8 -+ b L(short_ret) -+ nop -+ -+L(less8): -+ srli.d t0, a2, 2 -+ beqz t0, L(less4) -+ vldrepl.w vr0, a0, 0 -+ vldrepl.w vr1, a1, 0 -+ -+ -+ vldrepl.w vr2, a3, -4 -+ vldrepl.w vr3, a4, -4 -+ b L(short_ret) -+ nop -+ -+L(less4): -+ srli.d t0, a2, 1 -+ beqz t0, L(less2) -+ vldrepl.h vr0, a0, 0 -+ vldrepl.h vr1, a1, 0 -+ -+ vldrepl.h vr2, a3, -2 -+ vldrepl.h vr3, a4, -2 -+ b L(short_ret) -+ nop -+ -+L(less2): -+ beqz a2, L(ret0) -+ ld.bu t0, a0, 0 -+ ld.bu t1, a1, 0 -+ sub.d a0, t0, t1 -+ -+ jr ra -+L(ret0): -+ move a0, zero -+ jr ra -+ -+L(make_aligned): -+ xvld xr0, a0, 0 -+ -+ xvld xr1, a1, 0 -+ xvseq.b xr2, xr0, xr1 -+ xvsetanyeqz.b fcc0, xr2 -+ bcnez fcc0, L(end) -+ -+ andi t0, a0, 0x1f -+ sub.d t0, t2, t0 -+ sub.d t1, a2, t0 -+ add.d a0, a0, t0 -+ -+ add.d a1, a1, t0 -+ andi a2, t1, 0x3f -+ sub.d t0, t1, a2 -+ add.d a5, a0, t0 -+ -+ -+L(loop_align): -+ xvld xr0, a0, 0 -+ xvld xr1, a1, 0 -+ xvld xr2, a0, 32 -+ xvld xr3, a1, 32 -+ -+ xvseq.b xr0, xr0, xr1 -+ xvseq.b xr1, xr2, xr3 -+ xvmin.bu xr2, xr1, xr0 -+ xvsetanyeqz.b fcc0, xr2 -+ -+ bcnez fcc0, L(pair_end) -+ addi.d a0, a0, 64 -+ addi.d a1, a1, 64 -+ bne a0, a5, L(loop_align) -+ -+ bnez a2, L(last_bytes) -+ move a0, zero -+ jr ra -+ nop -+ -+ -+L(pair_end): -+ xvmsknz.b xr0, xr0 -+ xvmsknz.b xr1, xr1 -+ xvpickve.w xr2, xr0, 4 -+ xvpickve.w xr3, xr1, 4 -+ -+ vilvl.h vr0, vr2, vr0 -+ vilvl.h vr1, vr3, vr1 -+ vilvl.w vr0, vr1, vr0 -+ movfr2gr.d t0, fa0 -+ -+ cto.d t0, t0 -+ ldx.bu t1, a0, t0 -+ ldx.bu t2, a1, t0 -+ sub.d a0, t1, t2 -+ -+ jr ra -+END(MEMCMP) -+ -+libc_hidden_builtin_def (MEMCMP) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memcmp-lsx.S b/sysdeps/loongarch/lp64/multiarch/memcmp-lsx.S -new file mode 100644 -index 00000000..38a50a4c ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memcmp-lsx.S -@@ -0,0 +1,269 @@ -+/* Optimized memcmp implementation using LoongArch LSX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+#define MEMCMP __memcmp_lsx -+ -+LEAF(MEMCMP, 6) -+ beqz a2, L(out) -+ pcalau12i t0, %pc_hi20(L(INDEX)) -+ andi a3, a0, 0xf -+ vld vr5, t0, %pc_lo12(L(INDEX)) -+ -+ andi a4, a1, 0xf -+ bne a3, a4, L(unaligned) -+ bstrins.d a0, zero, 3, 0 -+ xor a1, a1, a4 -+ -+ vld vr0, a0, 0 -+ vld vr1, a1, 0 -+ li.d t0, 16 -+ vreplgr2vr.b vr3, a3 -+ -+ sub.d t1, t0, a3 -+ vadd.b vr3, vr3, vr5 -+ vshuf.b vr0, vr3, vr0, vr3 -+ vshuf.b vr1, vr3, vr1, vr3 -+ -+ -+ vseq.b vr4, vr0, vr1 -+ bgeu t1, a2, L(al_end) -+ vsetanyeqz.b fcc0, vr4 -+ bcnez fcc0, L(al_found) -+ -+ sub.d t1, a2, t1 -+ andi a2, t1, 31 -+ beq a2, t1, L(al_less_32bytes) -+ sub.d t2, t1, a2 -+ -+ add.d a4, a0, t2 -+L(al_loop): -+ vld vr0, a0, 16 -+ vld vr1, a1, 16 -+ vld vr2, a0, 32 -+ -+ vld vr3, a1, 32 -+ addi.d a0, a0, 32 -+ addi.d a1, a1, 32 -+ vseq.b vr4, vr0, vr1 -+ -+ -+ vseq.b vr6, vr2, vr3 -+ vand.v vr6, vr4, vr6 -+ vsetanyeqz.b fcc0, vr6 -+ bcnez fcc0, L(al_pair_end) -+ -+ bne a0, a4, L(al_loop) -+L(al_less_32bytes): -+ bgeu t0, a2, L(al_less_16bytes) -+ vld vr0, a0, 16 -+ vld vr1, a1, 16 -+ -+ vld vr2, a0, 32 -+ vld vr3, a1, 32 -+ addi.d a2, a2, -16 -+ vreplgr2vr.b vr6, a2 -+ -+ vslt.b vr5, vr5, vr6 -+ vseq.b vr4, vr0, vr1 -+ vseq.b vr6, vr2, vr3 -+ vorn.v vr6, vr6, vr5 -+ -+ -+L(al_pair_end): -+ vsetanyeqz.b fcc0, vr4 -+ bcnez fcc0, L(al_found) -+ vnori.b vr4, vr6, 0 -+ vfrstpi.b vr4, vr4, 0 -+ -+ vshuf.b vr0, vr2, vr2, vr4 -+ vshuf.b vr1, vr3, vr3, vr4 -+ vpickve2gr.bu t0, vr0, 0 -+ vpickve2gr.bu t1, vr1, 0 -+ -+ sub.d a0, t0, t1 -+ jr ra -+ nop -+ nop -+ -+L(al_less_16bytes): -+ beqz a2, L(out) -+ vld vr0, a0, 16 -+ vld vr1, a1, 16 -+ vseq.b vr4, vr0, vr1 -+ -+ -+L(al_end): -+ vreplgr2vr.b vr6, a2 -+ vslt.b vr5, vr5, vr6 -+ vorn.v vr4, vr4, vr5 -+ nop -+ -+L(al_found): -+ vnori.b vr4, vr4, 0 -+ vfrstpi.b vr4, vr4, 0 -+ vshuf.b vr0, vr0, vr0, vr4 -+ vshuf.b vr1, vr1, vr1, vr4 -+ -+ vpickve2gr.bu t0, vr0, 0 -+ vpickve2gr.bu t1, vr1, 0 -+ sub.d a0, t0, t1 -+ jr ra -+ -+L(out): -+ move a0, zero -+ jr ra -+ nop -+ nop -+ -+ -+L(unaligned): -+ xor t2, a0, a1 -+ sltu a5, a3, a4 -+ masknez t2, t2, a5 -+ xor a0, a0, t2 -+ -+ xor a1, a1, t2 -+ andi a3, a0, 0xf -+ andi a4, a1, 0xf -+ bstrins.d a0, zero, 3, 0 -+ -+ xor a1, a1, a4 -+ vld vr4, a0, 0 -+ vld vr1, a1, 0 -+ li.d t0, 16 -+ -+ vreplgr2vr.b vr2, a4 -+ sub.d a6, a4, a3 -+ sub.d t1, t0, a4 -+ sub.d t2, t0, a6 -+ -+ -+ vadd.b vr2, vr2, vr5 -+ vreplgr2vr.b vr6, t2 -+ vadd.b vr6, vr6, vr5 -+ vshuf.b vr0, vr4, vr4, vr6 -+ -+ vshuf.b vr1, vr2, vr1, vr2 -+ vshuf.b vr0, vr2, vr0, vr2 -+ vseq.b vr7, vr0, vr1 -+ bgeu t1, a2, L(un_end) -+ -+ vsetanyeqz.b fcc0, vr7 -+ bcnez fcc0, L(un_found) -+ sub.d a2, a2, t1 -+ andi t1, a2, 31 -+ -+ beq a2, t1, L(un_less_32bytes) -+ sub.d t2, a2, t1 -+ move a2, t1 -+ add.d a4, a1, t2 -+ -+ -+L(un_loop): -+ vld vr2, a0, 16 -+ vld vr1, a1, 16 -+ vld vr3, a1, 32 -+ addi.d a1, a1, 32 -+ -+ addi.d a0, a0, 32 -+ vshuf.b vr0, vr2, vr4, vr6 -+ vld vr4, a0, 0 -+ vseq.b vr7, vr0, vr1 -+ -+ vshuf.b vr2, vr4, vr2, vr6 -+ vseq.b vr8, vr2, vr3 -+ vand.v vr8, vr7, vr8 -+ vsetanyeqz.b fcc0, vr8 -+ -+ bcnez fcc0, L(un_pair_end) -+ bne a1, a4, L(un_loop) -+ -+L(un_less_32bytes): -+ bltu a2, t0, L(un_less_16bytes) -+ vld vr2, a0, 16 -+ vld vr1, a1, 16 -+ addi.d a0, a0, 16 -+ -+ addi.d a1, a1, 16 -+ addi.d a2, a2, -16 -+ vshuf.b vr0, vr2, vr4, vr6 -+ vor.v vr4, vr2, vr2 -+ -+ vseq.b vr7, vr0, vr1 -+ vsetanyeqz.b fcc0, vr7 -+ bcnez fcc0, L(un_found) -+L(un_less_16bytes): -+ beqz a2, L(out) -+ vld vr1, a1, 16 -+ bgeu a6, a2, 1f -+ -+ vld vr2, a0, 16 -+1: -+ vshuf.b vr0, vr2, vr4, vr6 -+ vseq.b vr7, vr0, vr1 -+L(un_end): -+ vreplgr2vr.b vr3, a2 -+ -+ -+ vslt.b vr3, vr5, vr3 -+ vorn.v vr7, vr7, vr3 -+ -+L(un_found): -+ vnori.b vr7, vr7, 0 -+ vfrstpi.b vr7, vr7, 0 -+ -+ vshuf.b vr0, vr0, vr0, vr7 -+ vshuf.b vr1, vr1, vr1, vr7 -+L(calc_result): -+ vpickve2gr.bu t0, vr0, 0 -+ vpickve2gr.bu t1, vr1, 0 -+ -+ sub.d t2, t0, t1 -+ sub.d t3, t1, t0 -+ masknez t0, t3, a5 -+ maskeqz t1, t2, a5 -+ -+ or a0, t0, t1 -+ jr ra -+L(un_pair_end): -+ vsetanyeqz.b fcc0, vr7 -+ bcnez fcc0, L(un_found) -+ -+ -+ vnori.b vr7, vr8, 0 -+ vfrstpi.b vr7, vr7, 0 -+ vshuf.b vr0, vr2, vr2, vr7 -+ vshuf.b vr1, vr3, vr3, vr7 -+ -+ b L(calc_result) -+END(MEMCMP) -+ -+ .section .rodata.cst16,"M",@progbits,16 -+ .align 4 -+L(INDEX): -+ .dword 0x0706050403020100 -+ .dword 0x0f0e0d0c0b0a0908 -+ -+libc_hidden_builtin_def (MEMCMP) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memcmp.c b/sysdeps/loongarch/lp64/multiarch/memcmp.c -new file mode 100644 -index 00000000..32eccac2 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memcmp.c -@@ -0,0 +1,43 @@ -+/* Multiple versions of memcmp. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+#if IS_IN (libc) -+# define memcmp __redirect_memcmp -+# include -+# undef memcmp -+ -+# define SYMBOL_NAME memcmp -+# include "ifunc-memcmp.h" -+ -+libc_ifunc_redirected (__redirect_memcmp, memcmp, -+ IFUNC_SELECTOR ()); -+# undef bcmp -+weak_alias (memcmp, bcmp) -+ -+# undef __memcmpeq -+strong_alias (memcmp, __memcmpeq) -+libc_hidden_def (__memcmpeq) -+ -+# ifdef SHARED -+__hidden_ver1 (memcmp, __GI_memcmp, __redirect_memcmp) -+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (memcmp); -+# endif -+ -+#endif --- -2.33.0 - diff --git a/LoongArch-Add-ifunc-support-for-memrchr-lsx-lasx.patch b/LoongArch-Add-ifunc-support-for-memrchr-lsx-lasx.patch deleted file mode 100644 index 26a0f40..0000000 --- a/LoongArch-Add-ifunc-support-for-memrchr-lsx-lasx.patch +++ /dev/null @@ -1,417 +0,0 @@ -From c4c272fb8067364530a2a78df92c37403acc963f Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Mon, 28 Aug 2023 10:08:37 +0800 -Subject: [PATCH 16/29] LoongArch: Add ifunc support for memrchr{lsx, lasx} - -According to glibc memrchr microbenchmark, this implementation could reduce -the runtime as following: - -Name Percent of rutime reduced -memrchr-lasx 20%-83% -memrchr-lsx 20%-64% - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/Makefile | 3 + - .../lp64/multiarch/ifunc-impl-list.c | 8 ++ - .../loongarch/lp64/multiarch/ifunc-memrchr.h | 40 ++++++ - .../lp64/multiarch/memrchr-generic.c | 23 ++++ - .../loongarch/lp64/multiarch/memrchr-lasx.S | 123 ++++++++++++++++++ - .../loongarch/lp64/multiarch/memrchr-lsx.S | 105 +++++++++++++++ - sysdeps/loongarch/lp64/multiarch/memrchr.c | 33 +++++ - 7 files changed, 335 insertions(+) - create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-memrchr.h - create mode 100644 sysdeps/loongarch/lp64/multiarch/memrchr-generic.c - create mode 100644 sysdeps/loongarch/lp64/multiarch/memrchr-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memrchr-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memrchr.c - -diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile -index 2f4802cf..7b87bc90 100644 ---- a/sysdeps/loongarch/lp64/multiarch/Makefile -+++ b/sysdeps/loongarch/lp64/multiarch/Makefile -@@ -27,5 +27,8 @@ sysdep_routines += \ - memchr-aligned \ - memchr-lsx \ - memchr-lasx \ -+ memrchr-generic \ -+ memrchr-lsx \ -+ memrchr-lasx \ - # sysdep_routines - endif -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -index a567b9cf..8bd5489e 100644 ---- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -@@ -109,5 +109,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, - #endif - IFUNC_IMPL_ADD (array, i, memchr, 1, __memchr_aligned) - ) -+ -+ IFUNC_IMPL (i, name, memrchr, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, memrchr, SUPPORT_LASX, __memrchr_lasx) -+ IFUNC_IMPL_ADD (array, i, memrchr, SUPPORT_LSX, __memrchr_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, memrchr, 1, __memrchr_generic) -+ ) - return i; - } -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-memrchr.h b/sysdeps/loongarch/lp64/multiarch/ifunc-memrchr.h -new file mode 100644 -index 00000000..8215f9ad ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-memrchr.h -@@ -0,0 +1,40 @@ -+/* Common definition for memrchr implementation. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+ -+#if !defined __loongarch_soft_float -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden; -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden; -+#endif -+extern __typeof (REDIRECT_NAME) OPTIMIZE (generic) attribute_hidden; -+ -+static inline void * -+IFUNC_SELECTOR (void) -+{ -+#if !defined __loongarch_soft_float -+ if (SUPPORT_LASX) -+ return OPTIMIZE (lasx); -+ else if (SUPPORT_LSX) -+ return OPTIMIZE (lsx); -+ else -+#endif -+ return OPTIMIZE (generic); -+} -diff --git a/sysdeps/loongarch/lp64/multiarch/memrchr-generic.c b/sysdeps/loongarch/lp64/multiarch/memrchr-generic.c -new file mode 100644 -index 00000000..ced61ebc ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memrchr-generic.c -@@ -0,0 +1,23 @@ -+/* Generic implementation of memrchr. -+ Copyright (C) 2023 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 -+ . */ -+ -+#if IS_IN (libc) -+# define MEMRCHR __memrchr_generic -+#endif -+ -+#include -diff --git a/sysdeps/loongarch/lp64/multiarch/memrchr-lasx.S b/sysdeps/loongarch/lp64/multiarch/memrchr-lasx.S -new file mode 100644 -index 00000000..5f3e0d06 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memrchr-lasx.S -@@ -0,0 +1,123 @@ -+/* Optimized memrchr implementation using LoongArch LASX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+#ifndef MEMRCHR -+# define MEMRCHR __memrchr_lasx -+#endif -+ -+LEAF(MEMRCHR, 6) -+ beqz a2, L(ret0) -+ addi.d a2, a2, -1 -+ add.d a3, a0, a2 -+ andi t1, a3, 0x3f -+ -+ bstrins.d a3, zero, 5, 0 -+ addi.d t1, t1, 1 -+ xvld xr0, a3, 0 -+ xvld xr1, a3, 32 -+ -+ sub.d t2, zero, t1 -+ li.d t3, -1 -+ xvreplgr2vr.b xr2, a1 -+ andi t4, a0, 0x3f -+ -+ srl.d t2, t3, t2 -+ xvseq.b xr0, xr0, xr2 -+ xvseq.b xr1, xr1, xr2 -+ xvmsknz.b xr0, xr0 -+ -+ -+ xvmsknz.b xr1, xr1 -+ xvpickve.w xr3, xr0, 4 -+ xvpickve.w xr4, xr1, 4 -+ vilvl.h vr0, vr3, vr0 -+ -+ vilvl.h vr1, vr4, vr1 -+ vilvl.w vr0, vr1, vr0 -+ movfr2gr.d t0, fa0 -+ and t0, t0, t2 -+ -+ bltu a2, t1, L(end) -+ bnez t0, L(found) -+ bstrins.d a0, zero, 5, 0 -+L(loop): -+ xvld xr0, a3, -64 -+ -+ xvld xr1, a3, -32 -+ addi.d a3, a3, -64 -+ xvseq.b xr0, xr0, xr2 -+ xvseq.b xr1, xr1, xr2 -+ -+ -+ beq a0, a3, L(out) -+ xvmax.bu xr3, xr0, xr1 -+ xvseteqz.v fcc0, xr3 -+ bcnez fcc0, L(loop) -+ -+ xvmsknz.b xr0, xr0 -+ xvmsknz.b xr1, xr1 -+ xvpickve.w xr3, xr0, 4 -+ xvpickve.w xr4, xr1, 4 -+ -+ vilvl.h vr0, vr3, vr0 -+ vilvl.h vr1, vr4, vr1 -+ vilvl.w vr0, vr1, vr0 -+ movfr2gr.d t0, fa0 -+ -+L(found): -+ addi.d a0, a3, 63 -+ clz.d t1, t0 -+ sub.d a0, a0, t1 -+ jr ra -+ -+ -+L(out): -+ xvmsknz.b xr0, xr0 -+ xvmsknz.b xr1, xr1 -+ xvpickve.w xr3, xr0, 4 -+ xvpickve.w xr4, xr1, 4 -+ -+ vilvl.h vr0, vr3, vr0 -+ vilvl.h vr1, vr4, vr1 -+ vilvl.w vr0, vr1, vr0 -+ movfr2gr.d t0, fa0 -+ -+L(end): -+ sll.d t2, t3, t4 -+ and t0, t0, t2 -+ addi.d a0, a3, 63 -+ clz.d t1, t0 -+ -+ sub.d a0, a0, t1 -+ maskeqz a0, a0, t0 -+ jr ra -+L(ret0): -+ move a0, zero -+ -+ -+ jr ra -+END(MEMRCHR) -+ -+libc_hidden_builtin_def (MEMRCHR) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memrchr-lsx.S b/sysdeps/loongarch/lp64/multiarch/memrchr-lsx.S -new file mode 100644 -index 00000000..39a7c8b0 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memrchr-lsx.S -@@ -0,0 +1,105 @@ -+/* Optimized memrchr implementation using LoongArch LSX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define MEMRCHR __memrchr_lsx -+ -+LEAF(MEMRCHR, 6) -+ beqz a2, L(ret0) -+ addi.d a2, a2, -1 -+ add.d a3, a0, a2 -+ andi t1, a3, 0x1f -+ -+ bstrins.d a3, zero, 4, 0 -+ addi.d t1, t1, 1 -+ vld vr0, a3, 0 -+ vld vr1, a3, 16 -+ -+ sub.d t2, zero, t1 -+ li.d t3, -1 -+ vreplgr2vr.b vr2, a1 -+ andi t4, a0, 0x1f -+ -+ srl.d t2, t3, t2 -+ vseq.b vr0, vr0, vr2 -+ vseq.b vr1, vr1, vr2 -+ vmsknz.b vr0, vr0 -+ -+ -+ vmsknz.b vr1, vr1 -+ vilvl.h vr0, vr1, vr0 -+ movfr2gr.s t0, fa0 -+ and t0, t0, t2 -+ -+ bltu a2, t1, L(end) -+ bnez t0, L(found) -+ bstrins.d a0, zero, 4, 0 -+L(loop): -+ vld vr0, a3, -32 -+ -+ vld vr1, a3, -16 -+ addi.d a3, a3, -32 -+ vseq.b vr0, vr0, vr2 -+ vseq.b vr1, vr1, vr2 -+ -+ beq a0, a3, L(out) -+ vmax.bu vr3, vr0, vr1 -+ vseteqz.v fcc0, vr3 -+ bcnez fcc0, L(loop) -+ -+ -+ vmsknz.b vr0, vr0 -+ vmsknz.b vr1, vr1 -+ vilvl.h vr0, vr1, vr0 -+ movfr2gr.s t0, fa0 -+ -+L(found): -+ addi.d a0, a3, 31 -+ clz.w t1, t0 -+ sub.d a0, a0, t1 -+ jr ra -+ -+L(out): -+ vmsknz.b vr0, vr0 -+ vmsknz.b vr1, vr1 -+ vilvl.h vr0, vr1, vr0 -+ movfr2gr.s t0, fa0 -+ -+L(end): -+ sll.d t2, t3, t4 -+ and t0, t0, t2 -+ addi.d a0, a3, 31 -+ clz.w t1, t0 -+ -+ -+ sub.d a0, a0, t1 -+ maskeqz a0, a0, t0 -+ jr ra -+L(ret0): -+ move a0, zero -+ -+ jr ra -+END(MEMRCHR) -+ -+libc_hidden_builtin_def (MEMRCHR) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memrchr.c b/sysdeps/loongarch/lp64/multiarch/memrchr.c -new file mode 100644 -index 00000000..8baba9ab ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memrchr.c -@@ -0,0 +1,33 @@ -+/* Multiple versions of memrchr. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+#if IS_IN (libc) -+# define memrchr __redirect_memrchr -+# include -+# undef memrchr -+ -+# define SYMBOL_NAME memrchr -+# include "ifunc-memrchr.h" -+ -+libc_ifunc_redirected (__redirect_memrchr, __memrchr, IFUNC_SELECTOR ()); -+libc_hidden_def (__memrchr) -+weak_alias (__memrchr, memrchr) -+ -+#endif --- -2.33.0 - diff --git a/LoongArch-Add-ifunc-support-for-memset-aligned-unali.patch b/LoongArch-Add-ifunc-support-for-memset-aligned-unali.patch deleted file mode 100644 index 2e18ba2..0000000 --- a/LoongArch-Add-ifunc-support-for-memset-aligned-unali.patch +++ /dev/null @@ -1,784 +0,0 @@ -From 14032f7bbe18443af8492f5d0365f72b76701673 Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Mon, 28 Aug 2023 10:08:38 +0800 -Subject: [PATCH 17/29] LoongArch: Add ifunc support for memset{aligned, - unaligned, lsx, lasx} - -According to glibc memset microbenchmark test results, for LSX and LASX -versions, A few cases with length less than 8 experience performace -degradation, overall, the LASX version could reduce the runtime about -15% - 75%, LSX version could reduce the runtime about 15%-50%. - -The unaligned version uses unaligned memmory access to set data which -length is less than 64 and make address aligned with 8. For this part, -the performace is better than aligned version. Comparing with the generic -version, the performance is close when the length is larger than 128. When -the length is 8-128, the unaligned version could reduce the runtime about -30%-70%, the aligned version could reduce the runtime about 20%-50%. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/Makefile | 4 + - .../lp64/multiarch/dl-symbol-redir-ifunc.h | 24 +++ - .../lp64/multiarch/ifunc-impl-list.c | 10 + - .../loongarch/lp64/multiarch/memset-aligned.S | 174 ++++++++++++++++++ - .../loongarch/lp64/multiarch/memset-lasx.S | 142 ++++++++++++++ - sysdeps/loongarch/lp64/multiarch/memset-lsx.S | 135 ++++++++++++++ - .../lp64/multiarch/memset-unaligned.S | 162 ++++++++++++++++ - sysdeps/loongarch/lp64/multiarch/memset.c | 37 ++++ - 8 files changed, 688 insertions(+) - create mode 100644 sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h - create mode 100644 sysdeps/loongarch/lp64/multiarch/memset-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memset-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memset-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memset-unaligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memset.c - -diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile -index 7b87bc90..216886c5 100644 ---- a/sysdeps/loongarch/lp64/multiarch/Makefile -+++ b/sysdeps/loongarch/lp64/multiarch/Makefile -@@ -30,5 +30,9 @@ sysdep_routines += \ - memrchr-generic \ - memrchr-lsx \ - memrchr-lasx \ -+ memset-aligned \ -+ memset-unaligned \ -+ memset-lsx \ -+ memset-lasx \ - # sysdep_routines - endif -diff --git a/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h b/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h -new file mode 100644 -index 00000000..e2723873 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h -@@ -0,0 +1,24 @@ -+/* Symbol rediretion for loader/static initialization code. -+ Copyright (C) 2023 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 -+ . */ -+ -+#ifndef _DL_IFUNC_GENERIC_H -+#define _DL_IFUNC_GENERIC_H -+ -+asm ("memset = __memset_aligned"); -+ -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -index 8bd5489e..37f60dde 100644 ---- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -@@ -117,5 +117,15 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, - #endif - IFUNC_IMPL_ADD (array, i, memrchr, 1, __memrchr_generic) - ) -+ -+ IFUNC_IMPL (i, name, memset, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, memset, SUPPORT_LASX, __memset_lasx) -+ IFUNC_IMPL_ADD (array, i, memset, SUPPORT_LSX, __memset_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, memset, SUPPORT_UAL, __memset_unaligned) -+ IFUNC_IMPL_ADD (array, i, memset, 1, __memset_aligned) -+ ) -+ - return i; - } -diff --git a/sysdeps/loongarch/lp64/multiarch/memset-aligned.S b/sysdeps/loongarch/lp64/multiarch/memset-aligned.S -new file mode 100644 -index 00000000..1fce95b7 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memset-aligned.S -@@ -0,0 +1,174 @@ -+/* Optimized memset aligned implementation using basic LoongArch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+# define MEMSET_NAME __memset_aligned -+#else -+# define MEMSET_NAME memset -+#endif -+ -+LEAF(MEMSET_NAME, 6) -+ move t0, a0 -+ andi a3, a0, 0x7 -+ li.w t6, 16 -+ beqz a3, L(align) -+ bltu a2, t6, L(short_data) -+ -+L(make_align): -+ li.w t8, 8 -+ sub.d t2, t8, a3 -+ pcaddi t1, 11 -+ slli.d t3, t2, 2 -+ sub.d t1, t1, t3 -+ jr t1 -+ -+L(al7): -+ st.b a1, t0, 6 -+L(al6): -+ st.b a1, t0, 5 -+L(al5): -+ st.b a1, t0, 4 -+L(al4): -+ st.b a1, t0, 3 -+L(al3): -+ st.b a1, t0, 2 -+L(al2): -+ st.b a1, t0, 1 -+L(al1): -+ st.b a1, t0, 0 -+L(al0): -+ add.d t0, t0, t2 -+ sub.d a2, a2, t2 -+ -+L(align): -+ bstrins.d a1, a1, 15, 8 -+ bstrins.d a1, a1, 31, 16 -+ bstrins.d a1, a1, 63, 32 -+ bltu a2, t6, L(less_16bytes) -+ -+ andi a4, a2, 0x3f -+ beq a4, a2, L(less_64bytes) -+ -+ sub.d t1, a2, a4 -+ move a2, a4 -+ add.d a5, t0, t1 -+ -+L(loop_64bytes): -+ addi.d t0, t0, 64 -+ st.d a1, t0, -64 -+ st.d a1, t0, -56 -+ st.d a1, t0, -48 -+ st.d a1, t0, -40 -+ -+ st.d a1, t0, -32 -+ st.d a1, t0, -24 -+ st.d a1, t0, -16 -+ st.d a1, t0, -8 -+ bne t0, a5, L(loop_64bytes) -+ -+L(less_64bytes): -+ srai.d a4, a2, 5 -+ beqz a4, L(less_32bytes) -+ addi.d a2, a2, -32 -+ st.d a1, t0, 0 -+ -+ st.d a1, t0, 8 -+ st.d a1, t0, 16 -+ st.d a1, t0, 24 -+ addi.d t0, t0, 32 -+ -+L(less_32bytes): -+ bltu a2, t6, L(less_16bytes) -+ addi.d a2, a2, -16 -+ st.d a1, t0, 0 -+ st.d a1, t0, 8 -+ addi.d t0, t0, 16 -+ -+L(less_16bytes): -+ srai.d a4, a2, 3 -+ beqz a4, L(less_8bytes) -+ addi.d a2, a2, -8 -+ st.d a1, t0, 0 -+ addi.d t0, t0, 8 -+ -+L(less_8bytes): -+ beqz a2, L(less_1byte) -+ srai.d a4, a2, 2 -+ beqz a4, L(less_4bytes) -+ addi.d a2, a2, -4 -+ st.w a1, t0, 0 -+ addi.d t0, t0, 4 -+ -+L(less_4bytes): -+ srai.d a3, a2, 1 -+ beqz a3, L(less_2bytes) -+ addi.d a2, a2, -2 -+ st.h a1, t0, 0 -+ addi.d t0, t0, 2 -+ -+L(less_2bytes): -+ beqz a2, L(less_1byte) -+ st.b a1, t0, 0 -+L(less_1byte): -+ jr ra -+ -+L(short_data): -+ pcaddi t1, 19 -+ slli.d t3, a2, 2 -+ sub.d t1, t1, t3 -+ jr t1 -+L(short_15): -+ st.b a1, a0, 14 -+L(short_14): -+ st.b a1, a0, 13 -+L(short_13): -+ st.b a1, a0, 12 -+L(short_12): -+ st.b a1, a0, 11 -+L(short_11): -+ st.b a1, a0, 10 -+L(short_10): -+ st.b a1, a0, 9 -+L(short_9): -+ st.b a1, a0, 8 -+L(short_8): -+ st.b a1, a0, 7 -+L(short_7): -+ st.b a1, a0, 6 -+L(short_6): -+ st.b a1, a0, 5 -+L(short_5): -+ st.b a1, a0, 4 -+L(short_4): -+ st.b a1, a0, 3 -+L(short_3): -+ st.b a1, a0, 2 -+L(short_2): -+ st.b a1, a0, 1 -+L(short_1): -+ st.b a1, a0, 0 -+L(short_0): -+ jr ra -+END(MEMSET_NAME) -+ -+libc_hidden_builtin_def (MEMSET_NAME) -diff --git a/sysdeps/loongarch/lp64/multiarch/memset-lasx.S b/sysdeps/loongarch/lp64/multiarch/memset-lasx.S -new file mode 100644 -index 00000000..041abbac ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memset-lasx.S -@@ -0,0 +1,142 @@ -+/* Optimized memset implementation using LoongArch LASX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define MEMSET __memset_lasx -+ -+LEAF(MEMSET, 6) -+ li.d t1, 32 -+ move a3, a0 -+ xvreplgr2vr.b xr0, a1 -+ add.d a4, a0, a2 -+ -+ bgeu t1, a2, L(less_32bytes) -+ li.d t3, 128 -+ li.d t2, 64 -+ blt t3, a2, L(long_bytes) -+ -+L(less_128bytes): -+ bgeu t2, a2, L(less_64bytes) -+ xvst xr0, a3, 0 -+ xvst xr0, a3, 32 -+ xvst xr0, a4, -32 -+ -+ xvst xr0, a4, -64 -+ jr ra -+L(less_64bytes): -+ xvst xr0, a3, 0 -+ xvst xr0, a4, -32 -+ -+ -+ jr ra -+L(less_32bytes): -+ srli.d t0, a2, 4 -+ beqz t0, L(less_16bytes) -+ vst vr0, a3, 0 -+ -+ vst vr0, a4, -16 -+ jr ra -+L(less_16bytes): -+ srli.d t0, a2, 3 -+ beqz t0, L(less_8bytes) -+ -+ vstelm.d vr0, a3, 0, 0 -+ vstelm.d vr0, a4, -8, 0 -+ jr ra -+L(less_8bytes): -+ srli.d t0, a2, 2 -+ -+ beqz t0, L(less_4bytes) -+ vstelm.w vr0, a3, 0, 0 -+ vstelm.w vr0, a4, -4, 0 -+ jr ra -+ -+ -+L(less_4bytes): -+ srli.d t0, a2, 1 -+ beqz t0, L(less_2bytes) -+ vstelm.h vr0, a3, 0, 0 -+ vstelm.h vr0, a4, -2, 0 -+ -+ jr ra -+L(less_2bytes): -+ beqz a2, L(less_1bytes) -+ st.b a1, a3, 0 -+L(less_1bytes): -+ jr ra -+ -+L(long_bytes): -+ xvst xr0, a3, 0 -+ bstrins.d a3, zero, 4, 0 -+ addi.d a3, a3, 32 -+ sub.d a2, a4, a3 -+ -+ andi t0, a2, 0xff -+ beq t0, a2, L(long_end) -+ move a2, t0 -+ sub.d t0, a4, t0 -+ -+ -+L(loop_256): -+ xvst xr0, a3, 0 -+ xvst xr0, a3, 32 -+ xvst xr0, a3, 64 -+ xvst xr0, a3, 96 -+ -+ xvst xr0, a3, 128 -+ xvst xr0, a3, 160 -+ xvst xr0, a3, 192 -+ xvst xr0, a3, 224 -+ -+ addi.d a3, a3, 256 -+ bne a3, t0, L(loop_256) -+L(long_end): -+ bltu a2, t3, L(end_less_128) -+ addi.d a2, a2, -128 -+ -+ xvst xr0, a3, 0 -+ xvst xr0, a3, 32 -+ xvst xr0, a3, 64 -+ xvst xr0, a3, 96 -+ -+ -+ addi.d a3, a3, 128 -+L(end_less_128): -+ bltu a2, t2, L(end_less_64) -+ addi.d a2, a2, -64 -+ xvst xr0, a3, 0 -+ -+ xvst xr0, a3, 32 -+ addi.d a3, a3, 64 -+L(end_less_64): -+ bltu a2, t1, L(end_less_32) -+ xvst xr0, a3, 0 -+ -+L(end_less_32): -+ xvst xr0, a4, -32 -+ jr ra -+END(MEMSET) -+ -+libc_hidden_builtin_def (MEMSET) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memset-lsx.S b/sysdeps/loongarch/lp64/multiarch/memset-lsx.S -new file mode 100644 -index 00000000..3d3982aa ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memset-lsx.S -@@ -0,0 +1,135 @@ -+/* Optimized memset implementation using LoongArch LSX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define MEMSET __memset_lsx -+ -+LEAF(MEMSET, 6) -+ li.d t1, 16 -+ move a3, a0 -+ vreplgr2vr.b vr0, a1 -+ add.d a4, a0, a2 -+ -+ bgeu t1, a2, L(less_16bytes) -+ li.d t3, 64 -+ li.d t2, 32 -+ bgeu a2, t3, L(long_bytes) -+ -+L(less_64bytes): -+ bgeu t2, a2, L(less_32bytes) -+ vst vr0, a3, 0 -+ vst vr0, a3, 16 -+ vst vr0, a4, -32 -+ -+ vst vr0, a4, -16 -+ jr ra -+L(less_32bytes): -+ vst vr0, a3, 0 -+ vst vr0, a4, -16 -+ -+ -+ jr ra -+L(less_16bytes): -+ srli.d t0, a2, 3 -+ beqz t0, L(less_8bytes) -+ vstelm.d vr0, a3, 0, 0 -+ -+ vstelm.d vr0, a4, -8, 0 -+ jr ra -+L(less_8bytes): -+ srli.d t0, a2, 2 -+ beqz t0, L(less_4bytes) -+ -+ vstelm.w vr0, a3, 0, 0 -+ vstelm.w vr0, a4, -4, 0 -+ jr ra -+L(less_4bytes): -+ srli.d t0, a2, 1 -+ -+ beqz t0, L(less_2bytes) -+ vstelm.h vr0, a3, 0, 0 -+ vstelm.h vr0, a4, -2, 0 -+ jr ra -+ -+ -+L(less_2bytes): -+ beqz a2, L(less_1bytes) -+ vstelm.b vr0, a3, 0, 0 -+L(less_1bytes): -+ jr ra -+L(long_bytes): -+ vst vr0, a3, 0 -+ -+ bstrins.d a3, zero, 3, 0 -+ addi.d a3, a3, 16 -+ sub.d a2, a4, a3 -+ andi t0, a2, 0x7f -+ -+ beq t0, a2, L(long_end) -+ move a2, t0 -+ sub.d t0, a4, t0 -+ -+L(loop_128): -+ vst vr0, a3, 0 -+ -+ vst vr0, a3, 16 -+ vst vr0, a3, 32 -+ vst vr0, a3, 48 -+ vst vr0, a3, 64 -+ -+ -+ vst vr0, a3, 80 -+ vst vr0, a3, 96 -+ vst vr0, a3, 112 -+ addi.d a3, a3, 128 -+ -+ bne a3, t0, L(loop_128) -+L(long_end): -+ bltu a2, t3, L(end_less_64) -+ addi.d a2, a2, -64 -+ vst vr0, a3, 0 -+ -+ vst vr0, a3, 16 -+ vst vr0, a3, 32 -+ vst vr0, a3, 48 -+ addi.d a3, a3, 64 -+ -+L(end_less_64): -+ bltu a2, t2, L(end_less_32) -+ addi.d a2, a2, -32 -+ vst vr0, a3, 0 -+ vst vr0, a3, 16 -+ -+ addi.d a3, a3, 32 -+L(end_less_32): -+ bltu a2, t1, L(end_less_16) -+ vst vr0, a3, 0 -+ -+L(end_less_16): -+ vst vr0, a4, -16 -+ jr ra -+END(MEMSET) -+ -+libc_hidden_builtin_def (MEMSET) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memset-unaligned.S b/sysdeps/loongarch/lp64/multiarch/memset-unaligned.S -new file mode 100644 -index 00000000..f7d32039 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memset-unaligned.S -@@ -0,0 +1,162 @@ -+/* Optimized memset unaligned implementation using basic LoongArch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+ -+# define MEMSET_NAME __memset_unaligned -+ -+#define ST_128(n) \ -+ st.d a1, a0, n; \ -+ st.d a1, a0, n+8 ; \ -+ st.d a1, a0, n+16 ; \ -+ st.d a1, a0, n+24 ; \ -+ st.d a1, a0, n+32 ; \ -+ st.d a1, a0, n+40 ; \ -+ st.d a1, a0, n+48 ; \ -+ st.d a1, a0, n+56 ; \ -+ st.d a1, a0, n+64 ; \ -+ st.d a1, a0, n+72 ; \ -+ st.d a1, a0, n+80 ; \ -+ st.d a1, a0, n+88 ; \ -+ st.d a1, a0, n+96 ; \ -+ st.d a1, a0, n+104; \ -+ st.d a1, a0, n+112; \ -+ st.d a1, a0, n+120; -+ -+LEAF(MEMSET_NAME, 6) -+ bstrins.d a1, a1, 15, 8 -+ add.d t7, a0, a2 -+ bstrins.d a1, a1, 31, 16 -+ move t0, a0 -+ -+ bstrins.d a1, a1, 63, 32 -+ srai.d t8, a2, 4 -+ beqz t8, L(less_16bytes) -+ srai.d t8, a2, 6 -+ -+ bnez t8, L(more_64bytes) -+ srai.d t8, a2, 5 -+ beqz t8, L(less_32bytes) -+ -+ st.d a1, a0, 0 -+ st.d a1, a0, 8 -+ st.d a1, a0, 16 -+ st.d a1, a0, 24 -+ -+ st.d a1, t7, -32 -+ st.d a1, t7, -24 -+ st.d a1, t7, -16 -+ st.d a1, t7, -8 -+ -+ jr ra -+ -+L(less_32bytes): -+ st.d a1, a0, 0 -+ st.d a1, a0, 8 -+ st.d a1, t7, -16 -+ st.d a1, t7, -8 -+ -+ jr ra -+ -+L(less_16bytes): -+ srai.d t8, a2, 3 -+ beqz t8, L(less_8bytes) -+ st.d a1, a0, 0 -+ st.d a1, t7, -8 -+ -+ jr ra -+ -+L(less_8bytes): -+ srai.d t8, a2, 2 -+ beqz t8, L(less_4bytes) -+ st.w a1, a0, 0 -+ st.w a1, t7, -4 -+ -+ jr ra -+ -+L(less_4bytes): -+ srai.d t8, a2, 1 -+ beqz t8, L(less_2bytes) -+ st.h a1, a0, 0 -+ st.h a1, t7, -2 -+ -+ jr ra -+ -+L(less_2bytes): -+ beqz a2, L(less_1bytes) -+ st.b a1, a0, 0 -+ -+ jr ra -+ -+L(less_1bytes): -+ jr ra -+ -+L(more_64bytes): -+ srli.d a0, a0, 3 -+ slli.d a0, a0, 3 -+ addi.d a0, a0, 0x8 -+ st.d a1, t0, 0 -+ -+ sub.d t2, t0, a0 -+ add.d a2, t2, a2 -+ addi.d a2, a2, -0x80 -+ blt a2, zero, L(end_unalign_proc) -+ -+L(loop_less): -+ ST_128(0) -+ addi.d a0, a0, 0x80 -+ addi.d a2, a2, -0x80 -+ bge a2, zero, L(loop_less) -+ -+L(end_unalign_proc): -+ addi.d a2, a2, 0x80 -+ pcaddi t1, 20 -+ andi t5, a2, 0x78 -+ srli.d t5, t5, 1 -+ -+ sub.d t1, t1, t5 -+ jr t1 -+ -+ st.d a1, a0, 112 -+ st.d a1, a0, 104 -+ st.d a1, a0, 96 -+ st.d a1, a0, 88 -+ st.d a1, a0, 80 -+ st.d a1, a0, 72 -+ st.d a1, a0, 64 -+ st.d a1, a0, 56 -+ st.d a1, a0, 48 -+ st.d a1, a0, 40 -+ st.d a1, a0, 32 -+ st.d a1, a0, 24 -+ st.d a1, a0, 16 -+ st.d a1, a0, 8 -+ st.d a1, a0, 0 -+ st.d a1, t7, -8 -+ -+ move a0, t0 -+ jr ra -+END(MEMSET_NAME) -+ -+libc_hidden_builtin_def (MEMSET_NAME) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memset.c b/sysdeps/loongarch/lp64/multiarch/memset.c -new file mode 100644 -index 00000000..3ff60d8a ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memset.c -@@ -0,0 +1,37 @@ -+/* Multiple versions of memset. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+#if IS_IN (libc) -+# define memset __redirect_memset -+# include -+# undef memset -+ -+# define SYMBOL_NAME memset -+# include "ifunc-lasx.h" -+ -+libc_ifunc_redirected (__redirect_memset, memset, -+ IFUNC_SELECTOR ()); -+ -+# ifdef SHARED -+__hidden_ver1 (memset, __GI_memset, __redirect_memset) -+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (memset); -+# endif -+ -+#endif --- -2.33.0 - diff --git a/LoongArch-Add-ifunc-support-for-rawmemchr-aligned-ls.patch b/LoongArch-Add-ifunc-support-for-rawmemchr-aligned-ls.patch deleted file mode 100644 index 1ac8637..0000000 --- a/LoongArch-Add-ifunc-support-for-rawmemchr-aligned-ls.patch +++ /dev/null @@ -1,448 +0,0 @@ -From b412bcb2cf4914a664bcd24924d670a2e37394b3 Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Mon, 28 Aug 2023 10:08:35 +0800 -Subject: [PATCH 14/29] LoongArch: Add ifunc support for rawmemchr{aligned, - lsx, lasx} - -According to glibc rawmemchr microbenchmark, A few cases tested with -char '\0' experience performance degradation due to the lasx and lsx -versions don't handle the '\0' separately. Overall, rawmemchr-lasx -implementation could reduce the runtime about 40%-80%, rawmemchr-lsx -implementation could reduce the runtime about 40%-66%, rawmemchr-aligned -implementation could reduce the runtime about 20%-40%. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/Makefile | 3 + - .../lp64/multiarch/ifunc-impl-list.c | 8 ++ - .../lp64/multiarch/ifunc-rawmemchr.h | 40 ++++++ - .../lp64/multiarch/rawmemchr-aligned.S | 124 ++++++++++++++++++ - .../loongarch/lp64/multiarch/rawmemchr-lasx.S | 82 ++++++++++++ - .../loongarch/lp64/multiarch/rawmemchr-lsx.S | 71 ++++++++++ - sysdeps/loongarch/lp64/multiarch/rawmemchr.c | 37 ++++++ - 7 files changed, 365 insertions(+) - create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-rawmemchr.h - create mode 100644 sysdeps/loongarch/lp64/multiarch/rawmemchr-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/rawmemchr-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/rawmemchr-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/rawmemchr.c - -diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile -index 5d7ae7ae..64416b02 100644 ---- a/sysdeps/loongarch/lp64/multiarch/Makefile -+++ b/sysdeps/loongarch/lp64/multiarch/Makefile -@@ -21,5 +21,8 @@ sysdep_routines += \ - memmove-unaligned \ - memmove-lsx \ - memmove-lasx \ -+ rawmemchr-aligned \ -+ rawmemchr-lsx \ -+ rawmemchr-lasx \ - # sysdep_routines - endif -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -index c8ba87bd..3db9af14 100644 ---- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -@@ -94,5 +94,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, - IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_aligned) - ) - -+ IFUNC_IMPL (i, name, rawmemchr, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, rawmemchr, SUPPORT_LASX, __rawmemchr_lasx) -+ IFUNC_IMPL_ADD (array, i, rawmemchr, SUPPORT_LSX, __rawmemchr_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, rawmemchr, 1, __rawmemchr_aligned) -+ ) -+ - return i; - } -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-rawmemchr.h b/sysdeps/loongarch/lp64/multiarch/ifunc-rawmemchr.h -new file mode 100644 -index 00000000..a7bb4cf9 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-rawmemchr.h -@@ -0,0 +1,40 @@ -+/* Common definition for rawmemchr ifunc selections. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+ -+#if !defined __loongarch_soft_float -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden; -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden; -+#endif -+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden; -+ -+static inline void * -+IFUNC_SELECTOR (void) -+{ -+#if !defined __loongarch_soft_float -+ if (SUPPORT_LASX) -+ return OPTIMIZE (lasx); -+ else if (SUPPORT_LSX) -+ return OPTIMIZE (lsx); -+ else -+#endif -+ return OPTIMIZE (aligned); -+} -diff --git a/sysdeps/loongarch/lp64/multiarch/rawmemchr-aligned.S b/sysdeps/loongarch/lp64/multiarch/rawmemchr-aligned.S -new file mode 100644 -index 00000000..9c7155ae ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/rawmemchr-aligned.S -@@ -0,0 +1,124 @@ -+/* Optimized rawmemchr implementation using basic LoongArch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+# define RAWMEMCHR_NAME __rawmemchr_aligned -+#else -+# define RAWMEMCHR_NAME __rawmemchr -+#endif -+ -+LEAF(RAWMEMCHR_NAME, 6) -+ andi t1, a0, 0x7 -+ bstrins.d a0, zero, 2, 0 -+ lu12i.w a2, 0x01010 -+ bstrins.d a1, a1, 15, 8 -+ -+ ld.d t0, a0, 0 -+ slli.d t1, t1, 3 -+ ori a2, a2, 0x101 -+ bstrins.d a1, a1, 31, 16 -+ -+ li.w t8, -1 -+ bstrins.d a1, a1, 63, 32 -+ bstrins.d a2, a2, 63, 32 -+ sll.d t2, t8, t1 -+ -+ sll.d t3, a1, t1 -+ orn t0, t0, t2 -+ slli.d a3, a2, 7 -+ beqz a1, L(find_zero) -+ -+ xor t0, t0, t3 -+ sub.d t1, t0, a2 -+ andn t2, a3, t0 -+ and t3, t1, t2 -+ -+ bnez t3, L(count_pos) -+ addi.d a0, a0, 8 -+ -+L(loop): -+ ld.d t0, a0, 0 -+ xor t0, t0, a1 -+ -+ sub.d t1, t0, a2 -+ andn t2, a3, t0 -+ and t3, t1, t2 -+ bnez t3, L(count_pos) -+ -+ ld.d t0, a0, 8 -+ addi.d a0, a0, 16 -+ xor t0, t0, a1 -+ sub.d t1, t0, a2 -+ -+ andn t2, a3, t0 -+ and t3, t1, t2 -+ beqz t3, L(loop) -+ addi.d a0, a0, -8 -+L(count_pos): -+ ctz.d t0, t3 -+ srli.d t0, t0, 3 -+ add.d a0, a0, t0 -+ jr ra -+ -+L(loop_7bit): -+ ld.d t0, a0, 0 -+L(find_zero): -+ sub.d t1, t0, a2 -+ and t2, t1, a3 -+ bnez t2, L(more_check) -+ -+ ld.d t0, a0, 8 -+ addi.d a0, a0, 16 -+ sub.d t1, t0, a2 -+ and t2, t1, a3 -+ -+ beqz t2, L(loop_7bit) -+ addi.d a0, a0, -8 -+ -+L(more_check): -+ andn t2, a3, t0 -+ and t3, t1, t2 -+ bnez t3, L(count_pos) -+ addi.d a0, a0, 8 -+ -+L(loop_8bit): -+ ld.d t0, a0, 0 -+ -+ sub.d t1, t0, a2 -+ andn t2, a3, t0 -+ and t3, t1, t2 -+ bnez t3, L(count_pos) -+ -+ ld.d t0, a0, 8 -+ addi.d a0, a0, 16 -+ sub.d t1, t0, a2 -+ -+ andn t2, a3, t0 -+ and t3, t1, t2 -+ beqz t3, L(loop_8bit) -+ -+ addi.d a0, a0, -8 -+ b L(count_pos) -+ -+END(RAWMEMCHR_NAME) -+ -+libc_hidden_builtin_def (__rawmemchr) -diff --git a/sysdeps/loongarch/lp64/multiarch/rawmemchr-lasx.S b/sysdeps/loongarch/lp64/multiarch/rawmemchr-lasx.S -new file mode 100644 -index 00000000..be2eb59d ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/rawmemchr-lasx.S -@@ -0,0 +1,82 @@ -+/* Optimized rawmemchr implementation using LoongArch LASX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define RAWMEMCHR __rawmemchr_lasx -+ -+LEAF(RAWMEMCHR, 6) -+ move a2, a0 -+ bstrins.d a0, zero, 5, 0 -+ xvld xr0, a0, 0 -+ xvld xr1, a0, 32 -+ -+ xvreplgr2vr.b xr2, a1 -+ xvseq.b xr0, xr0, xr2 -+ xvseq.b xr1, xr1, xr2 -+ xvmsknz.b xr0, xr0 -+ -+ xvmsknz.b xr1, xr1 -+ xvpickve.w xr3, xr0, 4 -+ xvpickve.w xr4, xr1, 4 -+ vilvl.h vr0, vr3, vr0 -+ -+ vilvl.h vr1, vr4, vr1 -+ vilvl.w vr0, vr1, vr0 -+ movfr2gr.d t0, fa0 -+ sra.d t0, t0, a2 -+ -+ -+ beqz t0, L(loop) -+ ctz.d t0, t0 -+ add.d a0, a2, t0 -+ jr ra -+ -+L(loop): -+ xvld xr0, a0, 64 -+ xvld xr1, a0, 96 -+ addi.d a0, a0, 64 -+ xvseq.b xr0, xr0, xr2 -+ -+ xvseq.b xr1, xr1, xr2 -+ xvmax.bu xr3, xr0, xr1 -+ xvseteqz.v fcc0, xr3 -+ bcnez fcc0, L(loop) -+ -+ xvmsknz.b xr0, xr0 -+ xvmsknz.b xr1, xr1 -+ xvpickve.w xr3, xr0, 4 -+ xvpickve.w xr4, xr1, 4 -+ -+ -+ vilvl.h vr0, vr3, vr0 -+ vilvl.h vr1, vr4, vr1 -+ vilvl.w vr0, vr1, vr0 -+ movfr2gr.d t0, fa0 -+ -+ ctz.d t0, t0 -+ add.d a0, a0, t0 -+ jr ra -+END(RAWMEMCHR) -+ -+libc_hidden_builtin_def (RAWMEMCHR) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/rawmemchr-lsx.S b/sysdeps/loongarch/lp64/multiarch/rawmemchr-lsx.S -new file mode 100644 -index 00000000..2f6fe024 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/rawmemchr-lsx.S -@@ -0,0 +1,71 @@ -+/* Optimized rawmemchr implementation using LoongArch LSX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define RAWMEMCHR __rawmemchr_lsx -+ -+LEAF(RAWMEMCHR, 6) -+ move a2, a0 -+ bstrins.d a0, zero, 4, 0 -+ vld vr0, a0, 0 -+ vld vr1, a0, 16 -+ -+ vreplgr2vr.b vr2, a1 -+ vseq.b vr0, vr0, vr2 -+ vseq.b vr1, vr1, vr2 -+ vmsknz.b vr0, vr0 -+ -+ vmsknz.b vr1, vr1 -+ vilvl.h vr0, vr1, vr0 -+ movfr2gr.s t0, fa0 -+ sra.w t0, t0, a2 -+ -+ beqz t0, L(loop) -+ ctz.w t0, t0 -+ add.d a0, a2, t0 -+ jr ra -+ -+ -+L(loop): -+ vld vr0, a0, 32 -+ vld vr1, a0, 48 -+ addi.d a0, a0, 32 -+ vseq.b vr0, vr0, vr2 -+ -+ vseq.b vr1, vr1, vr2 -+ vmax.bu vr3, vr0, vr1 -+ vseteqz.v fcc0, vr3 -+ bcnez fcc0, L(loop) -+ -+ vmsknz.b vr0, vr0 -+ vmsknz.b vr1, vr1 -+ vilvl.h vr0, vr1, vr0 -+ movfr2gr.s t0, fa0 -+ -+ ctz.w t0, t0 -+ add.d a0, a0, t0 -+ jr ra -+END(RAWMEMCHR) -+ -+libc_hidden_builtin_def (RAWMEMCHR) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/rawmemchr.c b/sysdeps/loongarch/lp64/multiarch/rawmemchr.c -new file mode 100644 -index 00000000..89c7ffff ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/rawmemchr.c -@@ -0,0 +1,37 @@ -+/* Multiple versions of rawmemchr. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+#if IS_IN (libc) -+# define rawmemchr __redirect_rawmemchr -+# define __rawmemchr __redirect___rawmemchr -+# include -+# undef rawmemchr -+# undef __rawmemchr -+ -+# define SYMBOL_NAME rawmemchr -+# include "ifunc-rawmemchr.h" -+ -+libc_ifunc_redirected (__redirect_rawmemchr, __rawmemchr, -+ IFUNC_SELECTOR ()); -+weak_alias (__rawmemchr, rawmemchr) -+# ifdef SHARED -+__hidden_ver1 (__rawmemchr, __GI___rawmemchr, __redirect___rawmemchr) -+ __attribute__((visibility ("hidden"))); -+# endif -+#endif --- -2.33.0 - diff --git a/LoongArch-Add-ifunc-support-for-strcmp-aligned-lsx.patch b/LoongArch-Add-ifunc-support-for-strcmp-aligned-lsx.patch deleted file mode 100644 index d960bc6..0000000 --- a/LoongArch-Add-ifunc-support-for-strcmp-aligned-lsx.patch +++ /dev/null @@ -1,499 +0,0 @@ -From e258cfcf92f5e31e902fa045b41652f00fcf2521 Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Thu, 24 Aug 2023 16:50:18 +0800 -Subject: [PATCH 09/29] LoongArch: Add ifunc support for strcmp{aligned, lsx} - -Based on the glibc microbenchmark, strcmp-aligned implementation could -reduce the runtime 0%-10% for aligned comparison, 10%-20% for unaligned -comparison, strcmp-lsx implemenation could reduce the runtime 0%-50%. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/Makefile | 2 + - .../lp64/multiarch/ifunc-impl-list.c | 7 + - .../loongarch/lp64/multiarch/ifunc-strcmp.h | 38 ++++ - .../loongarch/lp64/multiarch/strcmp-aligned.S | 179 ++++++++++++++++++ - sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S | 165 ++++++++++++++++ - sysdeps/loongarch/lp64/multiarch/strcmp.c | 35 ++++ - 6 files changed, 426 insertions(+) - create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-strcmp.h - create mode 100644 sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strcmp.c - -diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile -index c4dd3143..d5a500de 100644 ---- a/sysdeps/loongarch/lp64/multiarch/Makefile -+++ b/sysdeps/loongarch/lp64/multiarch/Makefile -@@ -12,6 +12,8 @@ sysdep_routines += \ - strchrnul-aligned \ - strchrnul-lsx \ - strchrnul-lasx \ -+ strcmp-aligned \ -+ strcmp-lsx \ - memcpy-aligned \ - memcpy-unaligned \ - memmove-unaligned \ -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -index 7cec0b77..9183b7da 100644 ---- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -@@ -62,6 +62,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, - IFUNC_IMPL_ADD (array, i, strchrnul, 1, __strchrnul_aligned) - ) - -+ IFUNC_IMPL (i, name, strcmp, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, strcmp, SUPPORT_LSX, __strcmp_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, strcmp, 1, __strcmp_aligned) -+ ) -+ - IFUNC_IMPL (i, name, memcpy, - #if !defined __loongarch_soft_float - IFUNC_IMPL_ADD (array, i, memcpy, SUPPORT_LASX, __memcpy_lasx) -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-strcmp.h b/sysdeps/loongarch/lp64/multiarch/ifunc-strcmp.h -new file mode 100644 -index 00000000..ca26352b ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-strcmp.h -@@ -0,0 +1,38 @@ -+/* Common definition for strcmp ifunc selection. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+ -+#if !defined __loongarch_soft_float -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden; -+#endif -+ -+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden; -+ -+static inline void * -+IFUNC_SELECTOR (void) -+{ -+#if !defined __loongarch_soft_float -+ if (SUPPORT_LSX) -+ return OPTIMIZE (lsx); -+ else -+#endif -+ return OPTIMIZE (aligned); -+} -diff --git a/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S b/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S -new file mode 100644 -index 00000000..f5f4f336 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S -@@ -0,0 +1,179 @@ -+/* Optimized strcmp implementation using basic Loongarch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+# define STRCMP_NAME __strcmp_aligned -+#else -+# define STRCMP_NAME strcmp -+#endif -+ -+LEAF(STRCMP_NAME, 6) -+ lu12i.w a4, 0x01010 -+ andi a2, a0, 0x7 -+ ori a4, a4, 0x101 -+ andi a3, a1, 0x7 -+ -+ bstrins.d a4, a4, 63, 32 -+ li.d t7, -1 -+ li.d t8, 8 -+ slli.d a5, a4, 7 -+ -+ bne a2, a3, L(unaligned) -+ bstrins.d a0, zero, 2, 0 -+ bstrins.d a1, zero, 2, 0 -+ ld.d t0, a0, 0 -+ -+ ld.d t1, a1, 0 -+ slli.d t3, a2, 3 -+ sll.d t2, t7, t3 -+ orn t0, t0, t2 -+ -+ -+ orn t1, t1, t2 -+ sub.d t2, t0, a4 -+ andn t3, a5, t0 -+ and t2, t2, t3 -+ -+ bne t0, t1, L(al_end) -+L(al_loop): -+ bnez t2, L(ret0) -+ ldx.d t0, a0, t8 -+ ldx.d t1, a1, t8 -+ -+ addi.d t8, t8, 8 -+ sub.d t2, t0, a4 -+ andn t3, a5, t0 -+ and t2, t2, t3 -+ -+ beq t0, t1, L(al_loop) -+L(al_end): -+ xor t3, t0, t1 -+ or t2, t2, t3 -+ ctz.d t3, t2 -+ -+ -+ bstrins.d t3, zero, 2, 0 -+ srl.d t0, t0, t3 -+ srl.d t1, t1, t3 -+ andi t0, t0, 0xff -+ -+ andi t1, t1, 0xff -+ sub.d a0, t0, t1 -+ jr ra -+ nop -+ -+L(ret0): -+ move a0, zero -+ jr ra -+ nop -+ nop -+ -+L(unaligned): -+ slt a6, a3, a2 -+ xor t0, a0, a1 -+ maskeqz t0, t0, a6 -+ xor a0, a0, t0 -+ -+ -+ xor a1, a1, t0 -+ andi a2, a0, 0x7 -+ andi a3, a1, 0x7 -+ bstrins.d a0, zero, 2, 0 -+ -+ bstrins.d a1, zero, 2, 0 -+ ld.d t4, a0, 0 -+ ld.d t1, a1, 0 -+ slli.d a2, a2, 3 -+ -+ slli.d a3, a3, 3 -+ srl.d t0, t4, a2 -+ srl.d t1, t1, a3 -+ srl.d t5, t7, a3 -+ -+ orn t0, t0, t5 -+ orn t1, t1, t5 -+ bne t0, t1, L(not_equal) -+ sll.d t5, t7, a2 -+ -+ -+ sub.d a3, a2, a3 -+ orn t4, t4, t5 -+ sub.d a2, zero, a3 -+ sub.d t2, t4, a4 -+ -+ andn t3, a5, t4 -+ and t2, t2, t3 -+ bnez t2, L(find_zero) -+L(un_loop): -+ srl.d t5, t4, a3 -+ -+ ldx.d t4, a0, t8 -+ ldx.d t1, a1, t8 -+ addi.d t8, t8, 8 -+ sll.d t0, t4, a2 -+ -+ or t0, t0, t5 -+ bne t0, t1, L(not_equal) -+ sub.d t2, t4, a4 -+ andn t3, a5, t4 -+ -+ -+ and t2, t2, t3 -+ beqz t2, L(un_loop) -+L(find_zero): -+ sub.d t2, t0, a4 -+ andn t3, a5, t0 -+ -+ and t2, t2, t3 -+ bnez t2, L(ret0) -+ ldx.d t1, a1, t8 -+ srl.d t0, t4, a3 -+ -+L(not_equal): -+ sub.d t2, t0, a4 -+ andn t3, a5, t0 -+ and t2, t2, t3 -+ xor t3, t0, t1 -+ -+ or t2, t2, t3 -+L(un_end): -+ ctz.d t3, t2 -+ bstrins.d t3, zero, 2, 0 -+ srl.d t0, t0, t3 -+ -+ -+ srl.d t1, t1, t3 -+ andi t0, t0, 0xff -+ andi t1, t1, 0xff -+ sub.d t2, t0, t1 -+ -+ -+ sub.d t3, t1, t0 -+ masknez t0, t2, a6 -+ maskeqz t1, t3, a6 -+ or a0, t0, t1 -+ -+ jr ra -+END(STRCMP_NAME) -+ -+libc_hidden_builtin_def (STRCMP_NAME) -diff --git a/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S b/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S -new file mode 100644 -index 00000000..2e177a38 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S -@@ -0,0 +1,165 @@ -+/* Optimized strcmp implementation using Loongarch LSX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define STRCMP __strcmp_lsx -+ -+LEAF(STRCMP, 6) -+ pcalau12i t0, %pc_hi20(L(INDEX)) -+ andi a2, a0, 0xf -+ vld vr2, t0, %pc_lo12(L(INDEX)) -+ andi a3, a1, 0xf -+ -+ bne a2, a3, L(unaligned) -+ bstrins.d a0, zero, 3, 0 -+ bstrins.d a1, zero, 3, 0 -+ vld vr0, a0, 0 -+ -+ vld vr1, a1, 0 -+ vreplgr2vr.b vr3, a2 -+ vslt.b vr2, vr2, vr3 -+ vseq.b vr3, vr0, vr1 -+ -+ vmin.bu vr3, vr0, vr3 -+ vor.v vr3, vr3, vr2 -+ vsetanyeqz.b fcc0, vr3 -+ bcnez fcc0, L(al_out) -+ -+ -+L(al_loop): -+ vld vr0, a0, 16 -+ vld vr1, a1, 16 -+ addi.d a0, a0, 16 -+ addi.d a1, a1, 16 -+ -+ vseq.b vr3, vr0, vr1 -+ vmin.bu vr3, vr0, vr3 -+ vsetanyeqz.b fcc0, vr3 -+ bceqz fcc0, L(al_loop) -+ -+L(al_out): -+ vseqi.b vr3, vr3, 0 -+ vfrstpi.b vr3, vr3, 0 -+ vshuf.b vr0, vr0, vr0, vr3 -+ vshuf.b vr1, vr1, vr1, vr3 -+ -+ vpickve2gr.bu t0, vr0, 0 -+ vpickve2gr.bu t1, vr1, 0 -+ sub.d a0, t0, t1 -+ jr ra -+ -+ -+L(unaligned): -+ slt a4, a3, a2 -+ xor t0, a0, a1 -+ maskeqz t0, t0, a4 -+ xor a0, a0, t0 -+ -+ xor a1, a1, t0 -+ andi a2, a0, 0xf -+ andi a3, a1, 0xf -+ bstrins.d a0, zero, 3, 0 -+ -+ bstrins.d a1, zero, 3, 0 -+ vld vr3, a0, 0 -+ vld vr1, a1, 0 -+ vreplgr2vr.b vr4, a2 -+ -+ vreplgr2vr.b vr5, a3 -+ vslt.b vr7, vr2, vr5 -+ vsub.b vr5, vr5, vr4 -+ vaddi.bu vr6, vr2, 16 -+ -+ -+ vsub.b vr6, vr6, vr5 -+ vshuf.b vr0, vr3, vr3, vr6 -+ vor.v vr0, vr0, vr7 -+ vor.v vr1, vr1, vr7 -+ -+ vseq.b vr5, vr0, vr1 -+ vsetanyeqz.b fcc0, vr5 -+ bcnez fcc0, L(not_equal) -+ vslt.b vr4, vr2, vr4 -+ -+ vor.v vr0, vr3, vr4 -+ vsetanyeqz.b fcc0, vr0 -+ bcnez fcc0, L(find_zero) -+ nop -+ -+L(un_loop): -+ vld vr3, a0, 16 -+ vld vr1, a1, 16 -+ addi.d a0, a0, 16 -+ addi.d a1, a1, 16 -+ -+ -+ vshuf.b vr0, vr3, vr0, vr6 -+ vseq.b vr5, vr0, vr1 -+ vsetanyeqz.b fcc0, vr5 -+ bcnez fcc0, L(not_equal) -+ -+ vsetanyeqz.b fcc0, vr3 -+ vor.v vr0, vr3, vr3 -+ bceqz fcc0, L(un_loop) -+L(find_zero): -+ vmin.bu vr5, vr1, vr5 -+ -+ vsetanyeqz.b fcc0, vr5 -+ bcnez fcc0, L(ret0) -+ vld vr1, a1, 16 -+ vshuf.b vr0, vr3, vr3, vr6 -+ -+ vseq.b vr5, vr0, vr1 -+L(not_equal): -+ vmin.bu vr5, vr0, vr5 -+L(un_end): -+ vseqi.b vr5, vr5, 0 -+ vfrstpi.b vr5, vr5, 0 -+ -+ -+ vshuf.b vr0, vr0, vr0, vr5 -+ vshuf.b vr1, vr1, vr1, vr5 -+ vpickve2gr.bu t0, vr0, 0 -+ vpickve2gr.bu t1, vr1, 0 -+ -+ sub.d t3, t0, t1 -+ sub.d t4, t1, t0 -+ masknez t0, t3, a4 -+ maskeqz t1, t4, a4 -+ -+ or a0, t0, t1 -+ jr ra -+L(ret0): -+ move a0, zero -+ jr ra -+END(STRCMP) -+ -+ .section .rodata.cst16,"M",@progbits,16 -+ .align 4 -+L(INDEX): -+ .dword 0x0706050403020100 -+ .dword 0x0f0e0d0c0b0a0908 -+ -+libc_hidden_builtin_def (STRCMP) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strcmp.c b/sysdeps/loongarch/lp64/multiarch/strcmp.c -new file mode 100644 -index 00000000..6f249c0b ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strcmp.c -@@ -0,0 +1,35 @@ -+/* Multiple versions of strcmp. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+#if IS_IN (libc) -+# define strcmp __redirect_strcmp -+# include -+# undef strcmp -+ -+# define SYMBOL_NAME strcmp -+# include "ifunc-strcmp.h" -+ -+libc_ifunc_redirected (__redirect_strcmp, strcmp, IFUNC_SELECTOR ()); -+ -+# ifdef SHARED -+__hidden_ver1 (strcmp, __GI_strcmp, __redirect_strcmp) -+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strcmp); -+# endif -+#endif --- -2.33.0 - diff --git a/LoongArch-Add-ifunc-support-for-strcpy-stpcpy-aligne.patch b/LoongArch-Add-ifunc-support-for-strcpy-stpcpy-aligne.patch deleted file mode 100644 index 2e98b05..0000000 --- a/LoongArch-Add-ifunc-support-for-strcpy-stpcpy-aligne.patch +++ /dev/null @@ -1,1099 +0,0 @@ -From 351086591d938aaf884d475261ae96ec5da00384 Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Wed, 13 Sep 2023 15:34:59 +0800 -Subject: [PATCH 22/29] LoongArch: Add ifunc support for strcpy, - stpcpy{aligned, unaligned, lsx, lasx} - -According to glibc strcpy and stpcpy microbenchmark test results(changed -to use generic_strcpy and generic_stpcpy instead of strlen + memcpy), -comparing with the generic version, this implementation could reduce the -runtime as following: - -Name Percent of rutime reduced -strcpy-aligned 8%-45% -strcpy-unaligned 8%-48%, comparing with the aligned version, unaligned - version takes less instructions to copy the tail of data - which length is less than 8. it also has better performance - in case src and dest cannot be both aligned with 8bytes -strcpy-lsx 20%-80% -strcpy-lasx 15%-86% -stpcpy-aligned 6%-43% -stpcpy-unaligned 8%-48% -stpcpy-lsx 10%-80% -stpcpy-lasx 10%-87% - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/Makefile | 8 + - .../lp64/multiarch/ifunc-impl-list.c | 18 ++ - .../loongarch/lp64/multiarch/stpcpy-aligned.S | 27 +++ - .../loongarch/lp64/multiarch/stpcpy-lasx.S | 22 ++ - sysdeps/loongarch/lp64/multiarch/stpcpy-lsx.S | 22 ++ - .../lp64/multiarch/stpcpy-unaligned.S | 22 ++ - sysdeps/loongarch/lp64/multiarch/stpcpy.c | 42 ++++ - .../loongarch/lp64/multiarch/strcpy-aligned.S | 202 ++++++++++++++++ - .../loongarch/lp64/multiarch/strcpy-lasx.S | 215 ++++++++++++++++++ - sysdeps/loongarch/lp64/multiarch/strcpy-lsx.S | 212 +++++++++++++++++ - .../lp64/multiarch/strcpy-unaligned.S | 138 +++++++++++ - sysdeps/loongarch/lp64/multiarch/strcpy.c | 35 +++ - 12 files changed, 963 insertions(+) - create mode 100644 sysdeps/loongarch/lp64/multiarch/stpcpy-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/stpcpy-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/stpcpy-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/stpcpy-unaligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/stpcpy.c - create mode 100644 sysdeps/loongarch/lp64/multiarch/strcpy-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strcpy-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strcpy-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strcpy-unaligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strcpy.c - -diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile -index 360a6718..39550bea 100644 ---- a/sysdeps/loongarch/lp64/multiarch/Makefile -+++ b/sysdeps/loongarch/lp64/multiarch/Makefile -@@ -16,6 +16,14 @@ sysdep_routines += \ - strcmp-lsx \ - strncmp-aligned \ - strncmp-lsx \ -+ strcpy-aligned \ -+ strcpy-unaligned \ -+ strcpy-lsx \ -+ strcpy-lasx \ -+ stpcpy-aligned \ -+ stpcpy-unaligned \ -+ stpcpy-lsx \ -+ stpcpy-lasx \ - memcpy-aligned \ - memcpy-unaligned \ - memmove-unaligned \ -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -index e397d58c..39a14f1d 100644 ---- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -@@ -76,6 +76,24 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, - IFUNC_IMPL_ADD (array, i, strncmp, 1, __strncmp_aligned) - ) - -+ IFUNC_IMPL (i, name, strcpy, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, strcpy, SUPPORT_LASX, __strcpy_lasx) -+ IFUNC_IMPL_ADD (array, i, strcpy, SUPPORT_LSX, __strcpy_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, strcpy, SUPPORT_UAL, __strcpy_unaligned) -+ IFUNC_IMPL_ADD (array, i, strcpy, 1, __strcpy_aligned) -+ ) -+ -+ IFUNC_IMPL (i, name, stpcpy, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, stpcpy, SUPPORT_LASX, __stpcpy_lasx) -+ IFUNC_IMPL_ADD (array, i, stpcpy, SUPPORT_LSX, __stpcpy_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, stpcpy, SUPPORT_UAL, __stpcpy_unaligned) -+ IFUNC_IMPL_ADD (array, i, stpcpy, 1, __stpcpy_aligned) -+ ) -+ - IFUNC_IMPL (i, name, memcpy, - #if !defined __loongarch_soft_float - IFUNC_IMPL_ADD (array, i, memcpy, SUPPORT_LASX, __memcpy_lasx) -diff --git a/sysdeps/loongarch/lp64/multiarch/stpcpy-aligned.S b/sysdeps/loongarch/lp64/multiarch/stpcpy-aligned.S -new file mode 100644 -index 00000000..1f763db6 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/stpcpy-aligned.S -@@ -0,0 +1,27 @@ -+/* stpcpy-aligned implementation is in strcpy-aligned.S. -+ Copyright (C) 2023 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 -+ . */ -+ -+#if IS_IN (libc) -+# define STPCPY __stpcpy_aligned -+#else -+# define STPCPY __stpcpy -+#endif -+ -+#define USE_AS_STPCPY -+#define STRCPY STPCPY -+#include "strcpy-aligned.S" -diff --git a/sysdeps/loongarch/lp64/multiarch/stpcpy-lasx.S b/sysdeps/loongarch/lp64/multiarch/stpcpy-lasx.S -new file mode 100644 -index 00000000..13d6c953 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/stpcpy-lasx.S -@@ -0,0 +1,22 @@ -+/* stpcpy-lasx implementation is in strcpy-lasx.S. -+ Copyright (C) 2023 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 -+ . */ -+ -+#define STPCPY __stpcpy_lasx -+#define USE_AS_STPCPY -+#define STRCPY STPCPY -+#include "strcpy-lasx.S" -diff --git a/sysdeps/loongarch/lp64/multiarch/stpcpy-lsx.S b/sysdeps/loongarch/lp64/multiarch/stpcpy-lsx.S -new file mode 100644 -index 00000000..e0f17ab5 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/stpcpy-lsx.S -@@ -0,0 +1,22 @@ -+/* stpcpy-lsx implementation is in strcpy-lsx.S. -+ Copyright (C) 2023 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 -+ . */ -+ -+#define STPCPY __stpcpy_lsx -+#define USE_AS_STPCPY -+#define STRCPY STPCPY -+#include "strcpy-lsx.S" -diff --git a/sysdeps/loongarch/lp64/multiarch/stpcpy-unaligned.S b/sysdeps/loongarch/lp64/multiarch/stpcpy-unaligned.S -new file mode 100644 -index 00000000..cc2f9712 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/stpcpy-unaligned.S -@@ -0,0 +1,22 @@ -+/* stpcpy-unaligned implementation is in strcpy-unaligned.S. -+ Copyright (C) 2023 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 -+ . */ -+ -+#define STPCPY __stpcpy_unaligned -+#define USE_AS_STPCPY -+#define STRCPY STPCPY -+#include "strcpy-unaligned.S" -diff --git a/sysdeps/loongarch/lp64/multiarch/stpcpy.c b/sysdeps/loongarch/lp64/multiarch/stpcpy.c -new file mode 100644 -index 00000000..d4860d7a ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/stpcpy.c -@@ -0,0 +1,42 @@ -+/* Multiple versions of stpcpy. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2017-2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+#if IS_IN (libc) -+# define stpcpy __redirect_stpcpy -+# define __stpcpy __redirect___stpcpy -+# define NO_MEMPCPY_STPCPY_REDIRECT -+# define __NO_STRING_INLINES -+# include -+# undef stpcpy -+# undef __stpcpy -+ -+# define SYMBOL_NAME stpcpy -+# include "ifunc-lasx.h" -+ -+libc_ifunc_redirected (__redirect_stpcpy, __stpcpy, IFUNC_SELECTOR ()); -+ -+weak_alias (__stpcpy, stpcpy) -+# ifdef SHARED -+__hidden_ver1 (__stpcpy, __GI___stpcpy, __redirect___stpcpy) -+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (stpcpy); -+__hidden_ver1 (stpcpy, __GI_stpcpy, __redirect_stpcpy) -+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (stpcpy); -+# endif -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strcpy-aligned.S b/sysdeps/loongarch/lp64/multiarch/strcpy-aligned.S -new file mode 100644 -index 00000000..4ed539fd ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strcpy-aligned.S -@@ -0,0 +1,202 @@ -+/* Optimized strcpy stpcpy aligned implementation using basic LoongArch -+ instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+# ifndef STRCPY -+# define STRCPY __strcpy_aligned -+# endif -+#else -+# ifndef STRCPY -+# define STRCPY strcpy -+# endif -+#endif -+ -+LEAF(STRCPY, 6) -+ andi a3, a0, 0x7 -+ move a2, a0 -+ beqz a3, L(dest_align) -+ sub.d a5, a1, a3 -+ addi.d a5, a5, 8 -+ -+L(make_dest_align): -+ ld.b t0, a1, 0 -+ addi.d a1, a1, 1 -+ st.b t0, a2, 0 -+ addi.d a2, a2, 1 -+ beqz t0, L(al_out) -+ -+ bne a1, a5, L(make_dest_align) -+ -+L(dest_align): -+ andi a4, a1, 7 -+ bstrins.d a1, zero, 2, 0 -+ -+ lu12i.w t5, 0x1010 -+ ld.d t0, a1, 0 -+ ori t5, t5, 0x101 -+ bstrins.d t5, t5, 63, 32 -+ -+ slli.d t6, t5, 0x7 -+ bnez a4, L(unalign) -+ sub.d t1, t0, t5 -+ andn t2, t6, t0 -+ -+ and t3, t1, t2 -+ bnez t3, L(al_end) -+ -+L(al_loop): -+ st.d t0, a2, 0 -+ ld.d t0, a1, 8 -+ -+ addi.d a1, a1, 8 -+ addi.d a2, a2, 8 -+ sub.d t1, t0, t5 -+ andn t2, t6, t0 -+ -+ and t3, t1, t2 -+ beqz t3, L(al_loop) -+ -+L(al_end): -+ ctz.d t1, t3 -+ srli.d t1, t1, 3 -+ addi.d t1, t1, 1 -+ -+ andi a3, t1, 8 -+ andi a4, t1, 4 -+ andi a5, t1, 2 -+ andi a6, t1, 1 -+ -+L(al_end_8): -+ beqz a3, L(al_end_4) -+ st.d t0, a2, 0 -+#ifdef USE_AS_STPCPY -+ addi.d a0, a2, 7 -+#endif -+ jr ra -+L(al_end_4): -+ beqz a4, L(al_end_2) -+ st.w t0, a2, 0 -+ addi.d a2, a2, 4 -+ srli.d t0, t0, 32 -+L(al_end_2): -+ beqz a5, L(al_end_1) -+ st.h t0, a2, 0 -+ addi.d a2, a2, 2 -+ srli.d t0, t0, 16 -+L(al_end_1): -+ beqz a6, L(al_out) -+ st.b t0, a2, 0 -+ addi.d a2, a2, 1 -+L(al_out): -+#ifdef USE_AS_STPCPY -+ addi.d a0, a2, -1 -+#endif -+ jr ra -+ -+ .align 4 -+L(unalign): -+ slli.d a5, a4, 3 -+ li.d t1, -1 -+ sub.d a6, zero, a5 -+ -+ srl.d a7, t0, a5 -+ sll.d t7, t1, a6 -+ -+ or t0, a7, t7 -+ sub.d t1, t0, t5 -+ andn t2, t6, t0 -+ and t3, t1, t2 -+ -+ bnez t3, L(un_end) -+ -+ ld.d t4, a1, 8 -+ -+ sub.d t1, t4, t5 -+ andn t2, t6, t4 -+ sll.d t0, t4, a6 -+ and t3, t1, t2 -+ -+ or t0, t0, a7 -+ bnez t3, L(un_end_with_remaining) -+ -+L(un_loop): -+ srl.d a7, t4, a5 -+ -+ ld.d t4, a1, 16 -+ addi.d a1, a1, 8 -+ -+ st.d t0, a2, 0 -+ addi.d a2, a2, 8 -+ -+ sub.d t1, t4, t5 -+ andn t2, t6, t4 -+ sll.d t0, t4, a6 -+ and t3, t1, t2 -+ -+ or t0, t0, a7 -+ beqz t3, L(un_loop) -+ -+L(un_end_with_remaining): -+ ctz.d t1, t3 -+ srli.d t1, t1, 3 -+ addi.d t1, t1, 1 -+ sub.d t1, t1, a4 -+ -+ blt t1, zero, L(un_end_less_8) -+ st.d t0, a2, 0 -+ addi.d a2, a2, 8 -+ beqz t1, L(un_out) -+ srl.d t0, t4, a5 -+ b L(un_end_less_8) -+ -+L(un_end): -+ ctz.d t1, t3 -+ srli.d t1, t1, 3 -+ addi.d t1, t1, 1 -+ -+L(un_end_less_8): -+ andi a4, t1, 4 -+ andi a5, t1, 2 -+ andi a6, t1, 1 -+L(un_end_4): -+ beqz a4, L(un_end_2) -+ st.w t0, a2, 0 -+ addi.d a2, a2, 4 -+ srli.d t0, t0, 32 -+L(un_end_2): -+ beqz a5, L(un_end_1) -+ st.h t0, a2, 0 -+ addi.d a2, a2, 2 -+ srli.d t0, t0, 16 -+L(un_end_1): -+ beqz a6, L(un_out) -+ st.b t0, a2, 0 -+ addi.d a2, a2, 1 -+L(un_out): -+#ifdef USE_AS_STPCPY -+ addi.d a0, a2, -1 -+#endif -+ jr ra -+END(STRCPY) -+ -+libc_hidden_builtin_def (STRCPY) -diff --git a/sysdeps/loongarch/lp64/multiarch/strcpy-lasx.S b/sysdeps/loongarch/lp64/multiarch/strcpy-lasx.S -new file mode 100644 -index 00000000..c2825612 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strcpy-lasx.S -@@ -0,0 +1,215 @@ -+/* Optimized strcpy stpcpy implementation using LoongArch LASX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# ifndef STRCPY -+# define STRCPY __strcpy_lasx -+# endif -+ -+# ifdef USE_AS_STPCPY -+# define dstend a0 -+# else -+# define dstend a4 -+# endif -+ -+LEAF(STRCPY, 6) -+ ori t8, zero, 0xfe0 -+ andi t0, a1, 0xfff -+ li.d t7, -1 -+ move a2, a0 -+ -+ bltu t8, t0, L(page_cross_start) -+L(start_entry): -+ xvld xr0, a1, 0 -+ li.d t0, 32 -+ andi t1, a2, 0x1f -+ -+ xvsetanyeqz.b fcc0, xr0 -+ sub.d t0, t0, t1 -+ bcnez fcc0, L(end) -+ add.d a1, a1, t0 -+ -+ xvst xr0, a2, 0 -+ andi a3, a1, 0x1f -+ add.d a2, a2, t0 -+ bnez a3, L(unaligned) -+ -+ -+ xvld xr0, a1, 0 -+ xvsetanyeqz.b fcc0, xr0 -+ bcnez fcc0, L(al_end) -+L(al_loop): -+ xvst xr0, a2, 0 -+ -+ xvld xr0, a1, 32 -+ addi.d a2, a2, 32 -+ addi.d a1, a1, 32 -+ xvsetanyeqz.b fcc0, xr0 -+ -+ bceqz fcc0, L(al_loop) -+L(al_end): -+ xvmsknz.b xr0, xr0 -+ xvpickve.w xr1, xr0, 4 -+ vilvl.h vr0, vr1, vr0 -+ -+ movfr2gr.s t0, fa0 -+ cto.w t0, t0 -+ add.d a1, a1, t0 -+ xvld xr0, a1, -31 -+ -+ -+ add.d dstend, a2, t0 -+ xvst xr0, dstend, -31 -+ jr ra -+ nop -+ -+L(page_cross_start): -+ move a4, a1 -+ bstrins.d a4, zero, 4, 0 -+ xvld xr0, a4, 0 -+ xvmsknz.b xr0, xr0 -+ -+ xvpickve.w xr1, xr0, 4 -+ vilvl.h vr0, vr1, vr0 -+ movfr2gr.s t0, fa0 -+ sra.w t0, t0, a1 -+ -+ beq t0, t7, L(start_entry) -+ b L(tail) -+L(unaligned): -+ andi t0, a1, 0xfff -+ bltu t8, t0, L(un_page_cross) -+ -+ -+L(un_start_entry): -+ xvld xr0, a1, 0 -+ xvsetanyeqz.b fcc0, xr0 -+ bcnez fcc0, L(un_end) -+ addi.d a1, a1, 32 -+ -+L(un_loop): -+ xvst xr0, a2, 0 -+ andi t0, a1, 0xfff -+ addi.d a2, a2, 32 -+ bltu t8, t0, L(page_cross_loop) -+ -+L(un_loop_entry): -+ xvld xr0, a1, 0 -+ addi.d a1, a1, 32 -+ xvsetanyeqz.b fcc0, xr0 -+ bceqz fcc0, L(un_loop) -+ -+ addi.d a1, a1, -32 -+L(un_end): -+ xvmsknz.b xr0, xr0 -+ xvpickve.w xr1, xr0, 4 -+ vilvl.h vr0, vr1, vr0 -+ -+ -+ movfr2gr.s t0, fa0 -+L(un_tail): -+ cto.w t0, t0 -+ add.d a1, a1, t0 -+ xvld xr0, a1, -31 -+ -+ add.d dstend, a2, t0 -+ xvst xr0, dstend, -31 -+ jr ra -+L(un_page_cross): -+ sub.d a4, a1, a3 -+ -+ xvld xr0, a4, 0 -+ xvmsknz.b xr0, xr0 -+ xvpickve.w xr1, xr0, 4 -+ vilvl.h vr0, vr1, vr0 -+ -+ movfr2gr.s t0, fa0 -+ sra.w t0, t0, a1 -+ beq t0, t7, L(un_start_entry) -+ b L(un_tail) -+ -+ -+L(page_cross_loop): -+ sub.d a4, a1, a3 -+ xvld xr0, a4, 0 -+ xvmsknz.b xr0, xr0 -+ xvpickve.w xr1, xr0, 4 -+ -+ vilvl.h vr0, vr1, vr0 -+ movfr2gr.s t0, fa0 -+ sra.w t0, t0, a1 -+ beq t0, t7, L(un_loop_entry) -+ -+ b L(un_tail) -+L(end): -+ xvmsknz.b xr0, xr0 -+ xvpickve.w xr1, xr0, 4 -+ vilvl.h vr0, vr1, vr0 -+ -+ movfr2gr.s t0, fa0 -+L(tail): -+ cto.w t0, t0 -+ add.d dstend, a2, t0 -+ add.d a5, a1, t0 -+ -+L(less_32): -+ srli.d t1, t0, 4 -+ beqz t1, L(less_16) -+ vld vr0, a1, 0 -+ vld vr1, a5, -15 -+ -+ vst vr0, a2, 0 -+ vst vr1, dstend, -15 -+ jr ra -+L(less_16): -+ srli.d t1, t0, 3 -+ -+ beqz t1, L(less_8) -+ ld.d t2, a1, 0 -+ ld.d t3, a5, -7 -+ st.d t2, a2, 0 -+ -+ st.d t3, dstend, -7 -+ jr ra -+L(less_8): -+ li.d t1, 3 -+ bltu t0, t1, L(less_3) -+ -+ ld.w t2, a1, 0 -+ ld.w t3, a5, -3 -+ st.w t2, a2, 0 -+ st.w t3, dstend, -3 -+ -+ jr ra -+L(less_3): -+ beqz t0, L(zero_byte) -+ ld.h t2, a1, 0 -+ -+ st.h t2, a2, 0 -+L(zero_byte): -+ st.b zero, dstend, 0 -+ jr ra -+END(STRCPY) -+ -+libc_hidden_builtin_def (STRCPY) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strcpy-lsx.S b/sysdeps/loongarch/lp64/multiarch/strcpy-lsx.S -new file mode 100644 -index 00000000..fc2498f7 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strcpy-lsx.S -@@ -0,0 +1,212 @@ -+/* Optimized strcpy stpcpy implementation using LoongArch LSX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# ifndef STRCPY -+# define STRCPY __strcpy_lsx -+# endif -+ -+LEAF(STRCPY, 6) -+ pcalau12i t0, %pc_hi20(L(INDEX)) -+ andi a4, a1, 0xf -+ vld vr1, t0, %pc_lo12(L(INDEX)) -+ move a2, a0 -+ -+ beqz a4, L(load_start) -+ xor t0, a1, a4 -+ vld vr0, t0, 0 -+ vreplgr2vr.b vr2, a4 -+ -+ vadd.b vr2, vr2, vr1 -+ vshuf.b vr0, vr2, vr0, vr2 -+ vsetanyeqz.b fcc0, vr0 -+ bcnez fcc0, L(end) -+ -+L(load_start): -+ vld vr0, a1, 0 -+ li.d t1, 16 -+ andi a3, a2, 0xf -+ vsetanyeqz.b fcc0, vr0 -+ -+ -+ sub.d t0, t1, a3 -+ bcnez fcc0, L(end) -+ add.d a1, a1, t0 -+ vst vr0, a2, 0 -+ -+ andi a3, a1, 0xf -+ add.d a2, a2, t0 -+ bnez a3, L(unaligned) -+ vld vr0, a1, 0 -+ -+ vsetanyeqz.b fcc0, vr0 -+ bcnez fcc0, L(al_end) -+L(al_loop): -+ vst vr0, a2, 0 -+ vld vr0, a1, 16 -+ -+ addi.d a2, a2, 16 -+ addi.d a1, a1, 16 -+ vsetanyeqz.b fcc0, vr0 -+ bceqz fcc0, L(al_loop) -+ -+ -+L(al_end): -+ vmsknz.b vr1, vr0 -+ movfr2gr.s t0, fa1 -+ cto.w t0, t0 -+ add.d a1, a1, t0 -+ -+ vld vr0, a1, -15 -+# ifdef USE_AS_STPCPY -+ add.d a0, a2, t0 -+ vst vr0, a0, -15 -+# else -+ add.d a2, a2, t0 -+ vst vr0, a2, -15 -+# endif -+ jr ra -+ -+L(end): -+ vmsknz.b vr1, vr0 -+ movfr2gr.s t0, fa1 -+ cto.w t0, t0 -+ addi.d t0, t0, 1 -+ -+L(end_16): -+ andi t1, t0, 16 -+ beqz t1, L(end_8) -+ vst vr0, a2, 0 -+# ifdef USE_AS_STPCPY -+ addi.d a0, a2, 15 -+# endif -+ jr ra -+ -+L(end_8): -+ andi t2, t0, 8 -+ andi t3, t0, 4 -+ andi t4, t0, 2 -+ andi t5, t0, 1 -+ -+ beqz t2, L(end_4) -+ vstelm.d vr0, a2, 0, 0 -+ addi.d a2, a2, 8 -+ vbsrl.v vr0, vr0, 8 -+ -+L(end_4): -+ beqz t3, L(end_2) -+ vstelm.w vr0, a2, 0, 0 -+ addi.d a2, a2, 4 -+ vbsrl.v vr0, vr0, 4 -+ -+L(end_2): -+ beqz t4, L(end_1) -+ vstelm.h vr0, a2, 0, 0 -+ addi.d a2, a2, 2 -+ vbsrl.v vr0, vr0, 2 -+ -+ -+L(end_1): -+ beqz t5, L(out) -+ vstelm.b vr0, a2, 0, 0 -+ addi.d a2, a2, 1 -+L(out): -+# ifdef USE_AS_STPCPY -+ addi.d a0, a2, -1 -+# endif -+ jr ra -+ -+ .align 4 -+L(unaligned): -+ bstrins.d a1, zero, 3, 0 -+ vld vr2, a1, 0 -+ vreplgr2vr.b vr3, a3 -+ vslt.b vr4, vr1, vr3 -+ -+ vor.v vr0, vr2, vr4 -+ vsetanyeqz.b fcc0, vr0 -+ bcnez fcc0, L(un_first_end) -+ vld vr0, a1, 16 -+ -+ vadd.b vr3, vr3, vr1 -+ vshuf.b vr4, vr0, vr2, vr3 -+ vsetanyeqz.b fcc0, vr0 -+ bcnez fcc0, L(un_end) -+ -+ -+ vor.v vr2, vr0, vr0 -+ addi.d a1, a1, 16 -+L(un_loop): -+ vld vr0, a1, 16 -+ vst vr4, a2, 0 -+ -+ addi.d a2, a2, 16 -+ vshuf.b vr4, vr0, vr2, vr3 -+ vsetanyeqz.b fcc0, vr0 -+ bcnez fcc0, L(un_end) -+ -+ vld vr2, a1, 32 -+ vst vr4, a2, 0 -+ addi.d a1, a1, 32 -+ addi.d a2, a2, 16 -+ -+ vshuf.b vr4, vr2, vr0, vr3 -+ vsetanyeqz.b fcc0, vr2 -+ bceqz fcc0, L(un_loop) -+ vor.v vr0, vr2, vr2 -+ -+ -+ addi.d a1, a1, -16 -+L(un_end): -+ vsetanyeqz.b fcc0, vr4 -+ bcnez fcc0, 1f -+ vst vr4, a2, 0 -+ -+1: -+ vmsknz.b vr1, vr0 -+ movfr2gr.s t0, fa1 -+ cto.w t0, t0 -+ add.d a1, a1, t0 -+ -+ vld vr0, a1, 1 -+ add.d a2, a2, t0 -+ sub.d a2, a2, a3 -+ vst vr0, a2, 1 -+# ifdef USE_AS_STPCPY -+ addi.d a0, a2, 16 -+# endif -+ jr ra -+L(un_first_end): -+ addi.d a2, a2, -16 -+ addi.d a1, a1, -16 -+ b 1b -+END(STRCPY) -+ -+ .section .rodata.cst16,"M",@progbits,16 -+ .align 4 -+L(INDEX): -+ .dword 0x0706050403020100 -+ .dword 0x0f0e0d0c0b0a0908 -+ -+libc_hidden_builtin_def (STRCPY) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strcpy-unaligned.S b/sysdeps/loongarch/lp64/multiarch/strcpy-unaligned.S -new file mode 100644 -index 00000000..9e31883b ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strcpy-unaligned.S -@@ -0,0 +1,138 @@ -+/* Optimized strcpy unaligned implementation using basic LoongArch -+ instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+ -+# ifndef STRCPY -+# define STRCPY __strcpy_unaligned -+# endif -+ -+# ifdef USE_AS_STPCPY -+# define dstend a0 -+# else -+# define dstend a4 -+# endif -+ -+LEAF(STRCPY, 6) -+ lu12i.w t5, 0x01010 -+ li.w t0, 0xff8 -+ ori t5, t5, 0x101 -+ andi t1, a1, 0xfff -+ -+ bstrins.d t5, t5, 63, 32 -+ move a2, a0 -+ slli.d t6, t5, 7 -+ bltu t0, t1, L(page_cross) -+ -+L(start_entry): -+ ld.d t0, a1, 0 -+ li.d t3, 8 -+ andi a3, a1, 0x7 -+ sub.d t1, t0, t5 -+ -+ andn t2, t6, t0 -+ sub.d t3, t3, a3 -+ and t1, t1, t2 -+ bnez t1, L(end) -+ -+ -+ add.d a1, a1, t3 -+ st.d t0, a2, 0 -+ add.d a2, a2, t3 -+ ld.d t0, a1, 0 -+ -+ sub.d t1, t0, t5 -+ andn t2, t6, t0 -+ and t1, t1, t2 -+ bnez t1, L(long_end) -+ -+L(loop): -+ st.d t0, a2, 0 -+ ld.d t0, a1, 8 -+ addi.d a2, a2, 8 -+ addi.d a1, a1, 8 -+ -+ sub.d t1, t0, t5 -+ andn t2, t6, t0 -+ and t1, t1, t2 -+ beqz t1, L(loop) -+ -+ -+L(long_end): -+ ctz.d t1, t1 -+ srli.d t1, t1, 3 -+ add.d a1, a1, t1 -+ ld.d t0, a1, -7 -+ -+ add.d dstend, a2, t1 -+ st.d t0, dstend, -7 -+ jr ra -+ nop -+ -+L(end): -+ ctz.d t1, t1 -+ srli.d t1, t1, 3 -+ add.d a3, a1, t1 -+ add.d dstend, a2, t1 -+ -+L(less_8): -+ li.d t0, 3 -+ bltu t1, t0, L(less_3) -+ ld.w t1, a1, 0 -+ ld.w t2, a3, -3 -+ -+ -+ st.w t1, a2, 0 -+ st.w t2, dstend, -3 -+ jr ra -+L(less_3): -+ beqz t1, L(zero_bytes) -+ -+ ld.h t1, a1, 0 -+ st.h t1, a2, 0 -+L(zero_bytes): -+ st.b zero, dstend, 0 -+ jr ra -+ -+L(page_cross): -+ move a4, a1 -+ bstrins.d a4, zero, 2, 0 -+ ld.d t0, a4, 0 -+ li.d t3, -1 -+ -+ slli.d t4, a1, 3 -+ srl.d t3, t3, t4 -+ srl.d t0, t0, t4 -+ orn t0, t0, t3 -+ -+ -+ sub.d t1, t0, t5 -+ andn t2, t6, t0 -+ and t1, t1, t2 -+ beqz t1, L(start_entry) -+ -+ b L(end) -+END(STRCPY) -+ -+libc_hidden_builtin_def (STRCPY) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strcpy.c b/sysdeps/loongarch/lp64/multiarch/strcpy.c -new file mode 100644 -index 00000000..46afd068 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strcpy.c -@@ -0,0 +1,35 @@ -+/* Multiple versions of strcpy. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+#if IS_IN (libc) -+# define strcpy __redirect_strcpy -+# include -+# undef strcpy -+ -+# define SYMBOL_NAME strcpy -+# include "ifunc-lasx.h" -+ -+libc_ifunc_redirected (__redirect_strcpy, strcpy, IFUNC_SELECTOR ()); -+ -+# ifdef SHARED -+__hidden_ver1 (strcpy, __GI_strcpy, __redirect_strcpy) -+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strcpy); -+# endif -+#endif --- -2.33.0 - diff --git a/LoongArch-Add-ifunc-support-for-strncmp-aligned-lsx.patch b/LoongArch-Add-ifunc-support-for-strncmp-aligned-lsx.patch deleted file mode 100644 index 0297fc3..0000000 --- a/LoongArch-Add-ifunc-support-for-strncmp-aligned-lsx.patch +++ /dev/null @@ -1,583 +0,0 @@ -From 6f03da2d7ef218c0f78375cf706dada59c3fee63 Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Thu, 24 Aug 2023 16:50:19 +0800 -Subject: [PATCH 10/29] LoongArch: Add ifunc support for strncmp{aligned, lsx} - -Based on the glibc microbenchmark, only a few short inputs with this -strncmp-aligned and strncmp-lsx implementation experience performance -degradation, overall, strncmp-aligned could reduce the runtime 0%-10% -for aligned comparision, 10%-25% for unaligend comparision, strncmp-lsx -could reduce the runtime about 0%-60%. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/Makefile | 2 + - .../lp64/multiarch/ifunc-impl-list.c | 7 + - .../loongarch/lp64/multiarch/ifunc-strncmp.h | 38 +++ - .../lp64/multiarch/strncmp-aligned.S | 218 ++++++++++++++++++ - .../loongarch/lp64/multiarch/strncmp-lsx.S | 208 +++++++++++++++++ - sysdeps/loongarch/lp64/multiarch/strncmp.c | 35 +++ - 6 files changed, 508 insertions(+) - create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-strncmp.h - create mode 100644 sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strncmp.c - -diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile -index d5a500de..5d7ae7ae 100644 ---- a/sysdeps/loongarch/lp64/multiarch/Makefile -+++ b/sysdeps/loongarch/lp64/multiarch/Makefile -@@ -14,6 +14,8 @@ sysdep_routines += \ - strchrnul-lasx \ - strcmp-aligned \ - strcmp-lsx \ -+ strncmp-aligned \ -+ strncmp-lsx \ - memcpy-aligned \ - memcpy-unaligned \ - memmove-unaligned \ -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -index 9183b7da..c8ba87bd 100644 ---- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -@@ -69,6 +69,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, - IFUNC_IMPL_ADD (array, i, strcmp, 1, __strcmp_aligned) - ) - -+ IFUNC_IMPL (i, name, strncmp, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, strncmp, SUPPORT_LSX, __strncmp_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, strncmp, 1, __strncmp_aligned) -+ ) -+ - IFUNC_IMPL (i, name, memcpy, - #if !defined __loongarch_soft_float - IFUNC_IMPL_ADD (array, i, memcpy, SUPPORT_LASX, __memcpy_lasx) -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-strncmp.h b/sysdeps/loongarch/lp64/multiarch/ifunc-strncmp.h -new file mode 100644 -index 00000000..1a7dc36b ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-strncmp.h -@@ -0,0 +1,38 @@ -+/* Common definition for strncmp ifunc selection. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+ -+#if !defined __loongarch_soft_float -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden; -+#endif -+ -+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden; -+ -+static inline void * -+IFUNC_SELECTOR (void) -+{ -+#if !defined __loongarch_soft_float -+ if (SUPPORT_LSX) -+ return OPTIMIZE (lsx); -+ else -+#endif -+ return OPTIMIZE (aligned); -+} -diff --git a/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S b/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S -new file mode 100644 -index 00000000..e2687fa7 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S -@@ -0,0 +1,218 @@ -+/* Optimized strncmp implementation using basic Loongarch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+# define STRNCMP __strncmp_aligned -+#else -+# define STRNCMP strncmp -+#endif -+ -+LEAF(STRNCMP, 6) -+ beqz a2, L(ret0) -+ lu12i.w a5, 0x01010 -+ andi a3, a0, 0x7 -+ ori a5, a5, 0x101 -+ -+ andi a4, a1, 0x7 -+ bstrins.d a5, a5, 63, 32 -+ li.d t7, -1 -+ li.d t8, 8 -+ -+ addi.d a2, a2, -1 -+ slli.d a6, a5, 7 -+ bne a3, a4, L(unaligned) -+ bstrins.d a0, zero, 2, 0 -+ -+ bstrins.d a1, zero, 2, 0 -+ ld.d t0, a0, 0 -+ ld.d t1, a1, 0 -+ slli.d t2, a3, 3 -+ -+ -+ sub.d t5, t8, a3 -+ srl.d t3, t7, t2 -+ srl.d t0, t0, t2 -+ srl.d t1, t1, t2 -+ -+ orn t0, t0, t3 -+ orn t1, t1, t3 -+ sub.d t2, t0, a5 -+ andn t3, a6, t0 -+ -+ and t2, t2, t3 -+ bne t0, t1, L(al_end) -+ sltu t4, a2, t5 -+ sub.d a2, a2, t5 -+ -+L(al_loop): -+ or t4, t2, t4 -+ bnez t4, L(ret0) -+ ldx.d t0, a0, t8 -+ ldx.d t1, a1, t8 -+ -+ -+ addi.d t8, t8, 8 -+ sltui t4, a2, 8 -+ addi.d a2, a2, -8 -+ sub.d t2, t0, a5 -+ -+ andn t3, a6, t0 -+ and t2, t2, t3 -+ beq t0, t1, L(al_loop) -+ addi.d a2, a2, 8 -+ -+L(al_end): -+ xor t3, t0, t1 -+ or t2, t2, t3 -+ ctz.d t2, t2 -+ srli.d t4, t2, 3 -+ -+ bstrins.d t2, zero, 2, 0 -+ srl.d t0, t0, t2 -+ srl.d t1, t1, t2 -+ andi t0, t0, 0xff -+ -+ -+ andi t1, t1, 0xff -+ sltu t2, a2, t4 -+ sub.d a0, t0, t1 -+ masknez a0, a0, t2 -+ -+ jr ra -+L(ret0): -+ move a0, zero -+ jr ra -+ nop -+ -+L(unaligned): -+ slt a7, a4, a3 -+ xor t0, a0, a1 -+ maskeqz t0, t0, a7 -+ xor a0, a0, t0 -+ -+ xor a1, a1, t0 -+ andi a3, a0, 0x7 -+ andi a4, a1, 0x7 -+ bstrins.d a0, zero, 2, 0 -+ -+ -+ bstrins.d a1, zero, 2, 0 -+ ld.d t4, a0, 0 -+ ld.d t1, a1, 0 -+ slli.d t2, a3, 3 -+ -+ slli.d t3, a4, 3 -+ srl.d t5, t7, t3 -+ srl.d t0, t4, t2 -+ srl.d t1, t1, t3 -+ -+ orn t0, t0, t5 -+ orn t1, t1, t5 -+ bne t0, t1, L(not_equal) -+ sub.d t6, t8, a4 -+ -+ sub.d a4, t2, t3 -+ sll.d t2, t7, t2 -+ sub.d t5, t8, a3 -+ orn t4, t4, t2 -+ -+ -+ sub.d t2, t4, a5 -+ andn t3, a6, t4 -+ sltu t7, a2, t5 -+ and t2, t2, t3 -+ -+ sub.d a3, zero, a4 -+ or t2, t2, t7 -+ bnez t2, L(un_end) -+ sub.d t7, t5, t6 -+ -+ sub.d a2, a2, t5 -+ sub.d t6, t8, t7 -+L(un_loop): -+ srl.d t5, t4, a4 -+ ldx.d t4, a0, t8 -+ -+ ldx.d t1, a1, t8 -+ addi.d t8, t8, 8 -+ sll.d t0, t4, a3 -+ or t0, t0, t5 -+ -+ -+ bne t0, t1, L(loop_not_equal) -+ sub.d t2, t4, a5 -+ andn t3, a6, t4 -+ sltui t5, a2, 8 -+ -+ and t2, t2, t3 -+ addi.d a2, a2, -8 -+ or t3, t2, t5 -+ beqz t3, L(un_loop) -+ -+ addi.d a2, a2, 8 -+L(un_end): -+ sub.d t2, t0, a5 -+ andn t3, a6, t0 -+ sltu t5, a2, t6 -+ -+ and t2, t2, t3 -+ or t2, t2, t5 -+ bnez t2, L(ret0) -+ ldx.d t1, a1, t8 -+ -+ -+ srl.d t0, t4, a4 -+ sub.d a2, a2, t6 -+L(not_equal): -+ sub.d t2, t0, a5 -+ andn t3, a6, t0 -+ -+ xor t4, t0, t1 -+ and t2, t2, t3 -+ or t2, t2, t4 -+ ctz.d t2, t2 -+ -+ bstrins.d t2, zero, 2, 0 -+ srli.d t4, t2, 3 -+ srl.d t0, t0, t2 -+ srl.d t1, t1, t2 -+ -+ andi t0, t0, 0xff -+ andi t1, t1, 0xff -+ sub.d t2, t0, t1 -+ sub.d t3, t1, t0 -+ -+ -+ masknez t0, t2, a7 -+ maskeqz t1, t3, a7 -+ sltu t2, a2, t4 -+ or a0, t0, t1 -+ -+ masknez a0, a0, t2 -+ jr ra -+L(loop_not_equal): -+ add.d a2, a2, t7 -+ b L(not_equal) -+END(STRNCMP) -+ -+libc_hidden_builtin_def (STRNCMP) -diff --git a/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S b/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S -new file mode 100644 -index 00000000..0b4eee2a ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S -@@ -0,0 +1,208 @@ -+/* Optimized strncmp implementation using Loongarch LSX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define STRNCMP __strncmp_lsx -+ -+LEAF(STRNCMP, 6) -+ beqz a2, L(ret0) -+ pcalau12i t0, %pc_hi20(L(INDEX)) -+ andi a3, a0, 0xf -+ vld vr2, t0, %pc_lo12(L(INDEX)) -+ -+ andi a4, a1, 0xf -+ li.d t2, 16 -+ bne a3, a4, L(unaligned) -+ xor t0, a0, a3 -+ -+ xor t1, a1, a4 -+ vld vr0, t0, 0 -+ vld vr1, t1, 0 -+ vreplgr2vr.b vr3, a3 -+ -+ -+ sub.d t2, t2, a3 -+ vadd.b vr3, vr3, vr2 -+ vshuf.b vr0, vr3, vr0, vr3 -+ vshuf.b vr1, vr3, vr1, vr3 -+ -+ vseq.b vr3, vr0, vr1 -+ vmin.bu vr3, vr0, vr3 -+ bgeu t2, a2, L(al_early_end) -+ vsetanyeqz.b fcc0, vr3 -+ -+ bcnez fcc0, L(al_end) -+ add.d a3, a0, a2 -+ addi.d a4, a3, -1 -+ bstrins.d a4, zero, 3, 0 -+ -+ sub.d a2, a3, a4 -+L(al_loop): -+ vld vr0, t0, 16 -+ vld vr1, t1, 16 -+ addi.d t0, t0, 16 -+ -+ -+ addi.d t1, t1, 16 -+ vseq.b vr3, vr0, vr1 -+ vmin.bu vr3, vr0, vr3 -+ beq t0, a4, L(al_early_end) -+ -+ vsetanyeqz.b fcc0, vr3 -+ bceqz fcc0, L(al_loop) -+L(al_end): -+ vseqi.b vr3, vr3, 0 -+ vfrstpi.b vr3, vr3, 0 -+ -+ vshuf.b vr0, vr0, vr0, vr3 -+ vshuf.b vr1, vr1, vr1, vr3 -+ vpickve2gr.bu t0, vr0, 0 -+ vpickve2gr.bu t1, vr1, 0 -+ -+ sub.d a0, t0, t1 -+ jr ra -+L(al_early_end): -+ vreplgr2vr.b vr4, a2 -+ vslt.b vr4, vr2, vr4 -+ -+ -+ vorn.v vr3, vr3, vr4 -+ b L(al_end) -+L(unaligned): -+ slt a5, a3, a4 -+ xor t0, a0, a1 -+ -+ maskeqz t0, t0, a5 -+ xor a0, a0, t0 -+ xor a1, a1, t0 -+ andi a3, a0, 0xf -+ -+ andi a4, a1, 0xf -+ xor t0, a0, a3 -+ xor t1, a1, a4 -+ vld vr0, t0, 0 -+ -+ vld vr3, t1, 0 -+ sub.d t2, t2, a3 -+ vreplgr2vr.b vr4, a3 -+ vreplgr2vr.b vr5, a4 -+ -+ -+ vaddi.bu vr6, vr2, 16 -+ vsub.b vr7, vr4, vr5 -+ vsub.b vr6, vr6, vr7 -+ vadd.b vr4, vr2, vr4 -+ -+ vshuf.b vr1, vr3, vr3, vr6 -+ vshuf.b vr0, vr7, vr0, vr4 -+ vshuf.b vr1, vr7, vr1, vr4 -+ vseq.b vr4, vr0, vr1 -+ -+ vmin.bu vr4, vr0, vr4 -+ bgeu t2, a2, L(un_early_end) -+ vsetanyeqz.b fcc0, vr4 -+ bcnez fcc0, L(un_end) -+ -+ add.d a6, a0, a2 -+ vslt.b vr5, vr2, vr5 -+ addi.d a7, a6, -1 -+ vor.v vr3, vr3, vr5 -+ -+ -+ bstrins.d a7, zero, 3, 0 -+ sub.d a2, a6, a7 -+L(un_loop): -+ vld vr0, t0, 16 -+ addi.d t0, t0, 16 -+ -+ vsetanyeqz.b fcc0, vr3 -+ bcnez fcc0, L(has_zero) -+ beq t0, a7, L(end_with_len) -+ vor.v vr1, vr3, vr3 -+ -+ vld vr3, t1, 16 -+ addi.d t1, t1, 16 -+ vshuf.b vr1, vr3, vr1, vr6 -+ vseq.b vr4, vr0, vr1 -+ -+ vmin.bu vr4, vr0, vr4 -+ vsetanyeqz.b fcc0, vr4 -+ bceqz fcc0, L(un_loop) -+L(un_end): -+ vseqi.b vr4, vr4, 0 -+ -+ -+ vfrstpi.b vr4, vr4, 0 -+ vshuf.b vr0, vr0, vr0, vr4 -+ vshuf.b vr1, vr1, vr1, vr4 -+ vpickve2gr.bu t0, vr0, 0 -+ -+ vpickve2gr.bu t1, vr1, 0 -+ sub.d t2, t0, t1 -+ sub.d t3, t1, t0 -+ masknez t0, t2, a5 -+ -+ maskeqz t1, t3, a5 -+ or a0, t0, t1 -+ jr ra -+L(has_zero): -+ vshuf.b vr1, vr3, vr3, vr6 -+ -+ vseq.b vr4, vr0, vr1 -+ vmin.bu vr4, vr0, vr4 -+ bne t0, a7, L(un_end) -+L(un_early_end): -+ vreplgr2vr.b vr5, a2 -+ -+ vslt.b vr5, vr2, vr5 -+ vorn.v vr4, vr4, vr5 -+ b L(un_end) -+L(end_with_len): -+ sub.d a6, a3, a4 -+ -+ bgeu a6, a2, 1f -+ vld vr4, t1, 16 -+1: -+ vshuf.b vr1, vr4, vr3, vr6 -+ vseq.b vr4, vr0, vr1 -+ -+ vmin.bu vr4, vr0, vr4 -+ vreplgr2vr.b vr5, a2 -+ vslt.b vr5, vr2, vr5 -+ vorn.v vr4, vr4, vr5 -+ -+ b L(un_end) -+L(ret0): -+ move a0, zero -+ jr ra -+END(STRNCMP) -+ -+ .section .rodata.cst16,"M",@progbits,16 -+ .align 4 -+L(INDEX): -+ .dword 0x0706050403020100 -+ .dword 0x0f0e0d0c0b0a0908 -+ -+libc_hidden_builtin_def (STRNCMP) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strncmp.c b/sysdeps/loongarch/lp64/multiarch/strncmp.c -new file mode 100644 -index 00000000..af6d0bc4 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strncmp.c -@@ -0,0 +1,35 @@ -+/* Multiple versions of strncmp. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+#if IS_IN (libc) -+# define strncmp __redirect_strncmp -+# include -+# undef strncmp -+ -+# define SYMBOL_NAME strncmp -+# include "ifunc-strncmp.h" -+ -+libc_ifunc_redirected (__redirect_strncmp, strncmp, IFUNC_SELECTOR ()); -+ -+# ifdef SHARED -+__hidden_ver1 (strncmp, __GI_strncmp, __redirect_strncmp) -+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strncmp); -+# endif -+#endif --- -2.33.0 - diff --git a/LoongArch-Add-ifunc-support-for-strnlen-aligned-lsx-.patch b/LoongArch-Add-ifunc-support-for-strnlen-aligned-lsx-.patch deleted file mode 100644 index e6b4d91..0000000 --- a/LoongArch-Add-ifunc-support-for-strnlen-aligned-lsx-.patch +++ /dev/null @@ -1,465 +0,0 @@ -From e494d32d3b76eee0d59cfab37789a356459b517a Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Thu, 24 Aug 2023 16:50:17 +0800 -Subject: [PATCH 08/29] LoongArch: Add ifunc support for strnlen{aligned, lsx, - lasx} - -Based on the glibc microbenchmark, strnlen-aligned implementation could -reduce the runtime more than 10%, strnlen-lsx implementation could reduce -the runtime about 50%-78%, strnlen-lasx implementation could reduce the -runtime about 50%-88%. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/Makefile | 3 + - .../lp64/multiarch/ifunc-impl-list.c | 8 ++ - .../loongarch/lp64/multiarch/ifunc-strnlen.h | 41 +++++++ - .../lp64/multiarch/strnlen-aligned.S | 102 ++++++++++++++++++ - .../loongarch/lp64/multiarch/strnlen-lasx.S | 100 +++++++++++++++++ - .../loongarch/lp64/multiarch/strnlen-lsx.S | 89 +++++++++++++++ - sysdeps/loongarch/lp64/multiarch/strnlen.c | 39 +++++++ - 7 files changed, 382 insertions(+) - create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-strnlen.h - create mode 100644 sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strnlen.c - -diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile -index afa51041..c4dd3143 100644 ---- a/sysdeps/loongarch/lp64/multiarch/Makefile -+++ b/sysdeps/loongarch/lp64/multiarch/Makefile -@@ -3,6 +3,9 @@ sysdep_routines += \ - strlen-aligned \ - strlen-lsx \ - strlen-lasx \ -+ strnlen-aligned \ -+ strnlen-lsx \ -+ strnlen-lasx \ - strchr-aligned \ - strchr-lsx \ - strchr-lasx \ -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -index 25eb96b0..7cec0b77 100644 ---- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -@@ -38,6 +38,14 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, - IFUNC_IMPL_ADD (array, i, strlen, 1, __strlen_aligned) - ) - -+ IFUNC_IMPL (i, name, strnlen, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, strnlen, SUPPORT_LASX, __strnlen_lasx) -+ IFUNC_IMPL_ADD (array, i, strnlen, SUPPORT_LSX, __strnlen_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, strnlen, 1, __strnlen_aligned) -+ ) -+ - IFUNC_IMPL (i, name, strchr, - #if !defined __loongarch_soft_float - IFUNC_IMPL_ADD (array, i, strchr, SUPPORT_LASX, __strchr_lasx) -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-strnlen.h b/sysdeps/loongarch/lp64/multiarch/ifunc-strnlen.h -new file mode 100644 -index 00000000..5cf89810 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-strnlen.h -@@ -0,0 +1,41 @@ -+/* Common definition for strnlen ifunc selections. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+ -+#if !defined __loongarch_soft_float -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden; -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden; -+#endif -+ -+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden; -+ -+static inline void * -+IFUNC_SELECTOR (void) -+{ -+#if !defined __loongarch_soft_float -+ if (SUPPORT_LASX) -+ return OPTIMIZE (lasx); -+ else if (SUPPORT_LSX) -+ return OPTIMIZE (lsx); -+ else -+#endif -+ return OPTIMIZE (aligned); -+} -diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S b/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S -new file mode 100644 -index 00000000..b900430a ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S -@@ -0,0 +1,102 @@ -+/* Optimized strnlen implementation using basic Loongarch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+# define STRNLEN __strnlen_aligned -+#else -+# define STRNLEN __strnlen -+#endif -+ -+LEAF(STRNLEN, 6) -+ beqz a1, L(out) -+ lu12i.w a2, 0x01010 -+ andi t1, a0, 0x7 -+ move t4, a0 -+ -+ bstrins.d a0, zero, 2, 0 -+ ori a2, a2, 0x101 -+ li.w t0, -1 -+ ld.d t2, a0, 0 -+ -+ slli.d t3, t1, 3 -+ bstrins.d a2, a2, 63, 32 -+ li.w t5, 8 -+ slli.d a3, a2, 7 -+ -+ sub.w t1, t5, t1 -+ sll.d t0, t0, t3 -+ orn t2, t2, t0 -+ sub.d t0, t2, a2 -+ -+ -+ andn t3, a3, t2 -+ and t0, t0, t3 -+ bnez t0, L(count_pos) -+ sub.d t5, a1, t1 -+ -+ bgeu t1, a1, L(out) -+ addi.d a0, a0, 8 -+L(loop): -+ ld.d t2, a0, 0 -+ sub.d t0, t2, a2 -+ -+ andn t1, a3, t2 -+ sltui t6, t5, 9 -+ and t0, t0, t1 -+ or t7, t0, t6 -+ -+ bnez t7, L(count_pos) -+ ld.d t2, a0, 8 -+ addi.d a0, a0, 16 -+ sub.d t0, t2, a2 -+ -+ -+ andn t1, a3, t2 -+ sltui t6, t5, 17 -+ and t0, t0, t1 -+ addi.d t5, t5, -16 -+ -+ or t7, t0, t6 -+ beqz t7, L(loop) -+ addi.d a0, a0, -8 -+L(count_pos): -+ ctz.d t1, t0 -+ -+ sub.d a0, a0, t4 -+ srli.d t1, t1, 3 -+ add.d a0, t1, a0 -+ sltu t0, a0, a1 -+ -+ masknez t1, a1, t0 -+ maskeqz a0, a0, t0 -+ or a0, a0, t1 -+ jr ra -+ -+ -+L(out): -+ move a0, a1 -+ jr ra -+END(STRNLEN) -+ -+weak_alias (STRNLEN, strnlen) -+libc_hidden_builtin_def (STRNLEN) -diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S b/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S -new file mode 100644 -index 00000000..2c03d3d9 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S -@@ -0,0 +1,100 @@ -+/* Optimized strnlen implementation using loongarch LASX instructions -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define STRNLEN __strnlen_lasx -+ -+LEAF(STRNLEN, 6) -+ beqz a1, L(ret0) -+ andi t1, a0, 0x3f -+ li.d t3, 65 -+ sub.d a2, a0, t1 -+ -+ xvld xr0, a2, 0 -+ xvld xr1, a2, 32 -+ sub.d t1, t3, t1 -+ move a3, a0 -+ -+ sltu t1, a1, t1 -+ xvmsknz.b xr0, xr0 -+ xvmsknz.b xr1, xr1 -+ xvpickve.w xr2, xr0, 4 -+ -+ xvpickve.w xr3, xr1, 4 -+ vilvl.h vr0, vr2, vr0 -+ vilvl.h vr1, vr3, vr1 -+ vilvl.w vr0, vr1, vr0 -+ -+ -+ movfr2gr.d t0, fa0 -+ sra.d t0, t0, a0 -+ orn t1, t1, t0 -+ bnez t1, L(end) -+ -+ add.d a4, a0, a1 -+ move a0, a2 -+ addi.d a4, a4, -1 -+ bstrins.d a4, zero, 5, 0 -+ -+L(loop): -+ xvld xr0, a0, 64 -+ xvld xr1, a0, 96 -+ addi.d a0, a0, 64 -+ beq a0, a4, L(out) -+ -+ xvmin.bu xr2, xr0, xr1 -+ xvsetanyeqz.b fcc0, xr2 -+ bceqz fcc0, L(loop) -+L(out): -+ xvmsknz.b xr0, xr0 -+ -+ -+ xvmsknz.b xr1, xr1 -+ xvpickve.w xr2, xr0, 4 -+ xvpickve.w xr3, xr1, 4 -+ vilvl.h vr0, vr2, vr0 -+ -+ vilvl.h vr1, vr3, vr1 -+ vilvl.w vr0, vr1, vr0 -+ movfr2gr.d t0, fa0 -+L(end): -+ sub.d a0, a0, a3 -+ -+ cto.d t0, t0 -+ add.d a0, a0, t0 -+ sltu t1, a0, a1 -+ masknez t0, a1, t1 -+ -+ maskeqz t1, a0, t1 -+ or a0, t0, t1 -+ jr ra -+L(ret0): -+ move a0, zero -+ -+ -+ jr ra -+END(STRNLEN) -+ -+libc_hidden_def (STRNLEN) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S b/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S -new file mode 100644 -index 00000000..b769a895 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S -@@ -0,0 +1,89 @@ -+/* Optimized strnlen implementation using loongarch LSX instructions -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define STRNLEN __strnlen_lsx -+ -+LEAF(STRNLEN, 6) -+ beqz a1, L(ret0) -+ andi t1, a0, 0x1f -+ li.d t3, 33 -+ sub.d a2, a0, t1 -+ -+ vld vr0, a2, 0 -+ vld vr1, a2, 16 -+ sub.d t1, t3, t1 -+ move a3, a0 -+ -+ sltu t1, a1, t1 -+ vmsknz.b vr0, vr0 -+ vmsknz.b vr1, vr1 -+ vilvl.h vr0, vr1, vr0 -+ -+ movfr2gr.s t0, fa0 -+ sra.w t0, t0, a0 -+ orn t1, t1, t0 -+ bnez t1, L(end) -+ -+ -+ add.d a4, a0, a1 -+ move a0, a2 -+ addi.d a4, a4, -1 -+ bstrins.d a4, zero, 4, 0 -+ -+L(loop): -+ vld vr0, a0, 32 -+ vld vr1, a0, 48 -+ addi.d a0, a0, 32 -+ beq a0, a4, L(out) -+ -+ vmin.bu vr2, vr0, vr1 -+ vsetanyeqz.b fcc0, vr2 -+ bceqz fcc0, L(loop) -+L(out): -+ vmsknz.b vr0, vr0 -+ -+ vmsknz.b vr1, vr1 -+ vilvl.h vr0, vr1, vr0 -+ movfr2gr.s t0, fa0 -+L(end): -+ sub.d a0, a0, a3 -+ -+ -+ cto.w t0, t0 -+ add.d a0, a0, t0 -+ sltu t1, a0, a1 -+ masknez t0, a1, t1 -+ -+ maskeqz t1, a0, t1 -+ or a0, t0, t1 -+ jr ra -+L(ret0): -+ move a0, zero -+ -+ jr ra -+END(STRNLEN) -+ -+libc_hidden_builtin_def (STRNLEN) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen.c b/sysdeps/loongarch/lp64/multiarch/strnlen.c -new file mode 100644 -index 00000000..38b7a25a ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strnlen.c -@@ -0,0 +1,39 @@ -+/* Multiple versions of strnlen. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+#if IS_IN (libc) -+# define strnlen __redirect_strnlen -+# define __strnlen __redirect___strnlen -+# include -+# undef __strnlen -+# undef strnlen -+ -+# define SYMBOL_NAME strnlen -+# include "ifunc-strnlen.h" -+ -+libc_ifunc_redirected (__redirect_strnlen, __strnlen, IFUNC_SELECTOR ()); -+weak_alias (__strnlen, strnlen); -+# ifdef SHARED -+__hidden_ver1 (__strnlen, __GI___strnlen, __redirect___strnlen) -+ __attribute__((visibility ("hidden"))) __attribute_copy__ (strnlen); -+__hidden_ver1 (strnlen, __GI_strnlen, __redirect_strnlen) -+ __attribute__((weak, visibility ("hidden"))) __attribute_copy__ (strnlen); -+# endif -+#endif --- -2.33.0 - diff --git a/LoongArch-Add-ifunc-support-for-strrchr-aligned-lsx-.patch b/LoongArch-Add-ifunc-support-for-strrchr-aligned-lsx-.patch deleted file mode 100644 index 63301f8..0000000 --- a/LoongArch-Add-ifunc-support-for-strrchr-aligned-lsx-.patch +++ /dev/null @@ -1,670 +0,0 @@ -From d537d0ab45a55048c8da483e73be4448ddb45525 Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Wed, 13 Sep 2023 15:35:00 +0800 -Subject: [PATCH 23/29] LoongArch: Add ifunc support for strrchr{aligned, lsx, - lasx} - -According to glibc strrchr microbenchmark test results, this implementation -could reduce the runtime time as following: - -Name Percent of rutime reduced -strrchr-lasx 10%-50% -strrchr-lsx 0%-50% -strrchr-aligned 5%-50% - -Generic strrchr is implemented by function strlen + memrchr, the lasx version -will compare with generic strrchr implemented by strlen-lasx + memrchr-lasx, -the lsx version will compare with generic strrchr implemented by strlen-lsx + -memrchr-lsx, the aligned version will compare with generic strrchr implemented -by strlen-aligned + memrchr-generic. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/Makefile | 3 + - .../lp64/multiarch/ifunc-impl-list.c | 8 + - .../loongarch/lp64/multiarch/ifunc-strrchr.h | 41 ++++ - .../lp64/multiarch/strrchr-aligned.S | 170 +++++++++++++++++ - .../loongarch/lp64/multiarch/strrchr-lasx.S | 176 ++++++++++++++++++ - .../loongarch/lp64/multiarch/strrchr-lsx.S | 144 ++++++++++++++ - sysdeps/loongarch/lp64/multiarch/strrchr.c | 36 ++++ - 7 files changed, 578 insertions(+) - create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-strrchr.h - create mode 100644 sysdeps/loongarch/lp64/multiarch/strrchr-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strrchr-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strrchr-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strrchr.c - -diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile -index 39550bea..fe863e1b 100644 ---- a/sysdeps/loongarch/lp64/multiarch/Makefile -+++ b/sysdeps/loongarch/lp64/multiarch/Makefile -@@ -9,6 +9,9 @@ sysdep_routines += \ - strchr-aligned \ - strchr-lsx \ - strchr-lasx \ -+ strrchr-aligned \ -+ strrchr-lsx \ -+ strrchr-lasx \ - strchrnul-aligned \ - strchrnul-lsx \ - strchrnul-lasx \ -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -index 39a14f1d..529e2369 100644 ---- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -@@ -94,6 +94,14 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, - IFUNC_IMPL_ADD (array, i, stpcpy, 1, __stpcpy_aligned) - ) - -+ IFUNC_IMPL (i, name, strrchr, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, strrchr, SUPPORT_LASX, __strrchr_lasx) -+ IFUNC_IMPL_ADD (array, i, strrchr, SUPPORT_LSX, __strrchr_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, strrchr, 1, __strrchr_aligned) -+ ) -+ - IFUNC_IMPL (i, name, memcpy, - #if !defined __loongarch_soft_float - IFUNC_IMPL_ADD (array, i, memcpy, SUPPORT_LASX, __memcpy_lasx) -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-strrchr.h b/sysdeps/loongarch/lp64/multiarch/ifunc-strrchr.h -new file mode 100644 -index 00000000..bbb34089 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-strrchr.h -@@ -0,0 +1,41 @@ -+/* Common definition for strrchr ifunc selections. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+ -+#if !defined __loongarch_soft_float -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden; -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden; -+#endif -+ -+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden; -+ -+static inline void * -+IFUNC_SELECTOR (void) -+{ -+#if !defined __loongarch_soft_float -+ if (SUPPORT_LASX) -+ return OPTIMIZE (lasx); -+ else if (SUPPORT_LSX) -+ return OPTIMIZE (lsx); -+ else -+#endif -+ return OPTIMIZE (aligned); -+} -diff --git a/sysdeps/loongarch/lp64/multiarch/strrchr-aligned.S b/sysdeps/loongarch/lp64/multiarch/strrchr-aligned.S -new file mode 100644 -index 00000000..a73deb78 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strrchr-aligned.S -@@ -0,0 +1,170 @@ -+/* Optimized strrchr implementation using basic LoongArch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+# define STRRCHR __strrchr_aligned -+#else -+# define STRRCHR strrchr -+#endif -+ -+LEAF(STRRCHR, 6) -+ slli.d t0, a0, 3 -+ bstrins.d a0, zero, 2, 0 -+ lu12i.w a2, 0x01010 -+ ld.d t2, a0, 0 -+ -+ andi a1, a1, 0xff -+ ori a2, a2, 0x101 -+ li.d t3, -1 -+ bstrins.d a2, a2, 63, 32 -+ -+ sll.d t5, t3, t0 -+ slli.d a3, a2, 7 -+ orn t4, t2, t5 -+ mul.d a1, a1, a2 -+ -+ sub.d t0, t4, a2 -+ andn t1, a3, t4 -+ and t1, t0, t1 -+ beqz t1, L(find_tail) -+ -+ -+ ctz.d t0, t1 -+ orn t0, zero, t0 -+ xor t2, t4, a1 -+ srl.d t0, t3, t0 -+ -+ orn t2, t2, t0 -+ orn t2, t2, t5 -+ revb.d t2, t2 -+ sub.d t1, t2, a2 -+ -+ andn t0, a3, t2 -+ and t1, t0, t1 -+ ctz.d t0, t1 -+ srli.d t0, t0, 3 -+ -+ addi.d a0, a0, 7 -+ sub.d a0, a0, t0 -+ maskeqz a0, a0, t1 -+ jr ra -+ -+ -+L(find_tail): -+ addi.d a4, a0, 8 -+ addi.d a0, a0, 8 -+L(loop_ascii): -+ ld.d t2, a0, 0 -+ sub.d t1, t2, a2 -+ -+ and t0, t1, a3 -+ bnez t0, L(more_check) -+ ld.d t2, a0, 8 -+ sub.d t1, t2, a2 -+ -+ and t0, t1, a3 -+ addi.d a0, a0, 16 -+ beqz t0, L(loop_ascii) -+ addi.d a0, a0, -8 -+ -+L(more_check): -+ andn t0, a3, t2 -+ and t1, t1, t0 -+ bnez t1, L(tail) -+ addi.d a0, a0, 8 -+ -+ -+L(loop_nonascii): -+ ld.d t2, a0, 0 -+ sub.d t1, t2, a2 -+ andn t0, a3, t2 -+ and t1, t0, t1 -+ -+ bnez t1, L(tail) -+ ld.d t2, a0, 8 -+ addi.d a0, a0, 16 -+ sub.d t1, t2, a2 -+ -+ andn t0, a3, t2 -+ and t1, t0, t1 -+ beqz t1, L(loop_nonascii) -+ addi.d a0, a0, -8 -+ -+L(tail): -+ ctz.d t0, t1 -+ orn t0, zero, t0 -+ xor t2, t2, a1 -+ srl.d t0, t3, t0 -+ -+ -+ orn t2, t2, t0 -+ revb.d t2, t2 -+ sub.d t1, t2, a2 -+ andn t0, a3, t2 -+ -+ and t1, t0, t1 -+ bnez t1, L(count_pos) -+L(find_loop): -+ beq a0, a4, L(find_end) -+ ld.d t2, a0, -8 -+ -+ addi.d a0, a0, -8 -+ xor t2, t2, a1 -+ sub.d t1, t2, a2 -+ andn t0, a3, t2 -+ -+ and t1, t0, t1 -+ beqz t1, L(find_loop) -+ revb.d t2, t2 -+ sub.d t1, t2, a2 -+ -+ -+ andn t0, a3, t2 -+ and t1, t0, t1 -+L(count_pos): -+ ctz.d t0, t1 -+ addi.d a0, a0, 7 -+ -+ srli.d t0, t0, 3 -+ sub.d a0, a0, t0 -+ jr ra -+ nop -+ -+L(find_end): -+ xor t2, t4, a1 -+ orn t2, t2, t5 -+ revb.d t2, t2 -+ sub.d t1, t2, a2 -+ -+ -+ andn t0, a3, t2 -+ and t1, t0, t1 -+ ctz.d t0, t1 -+ srli.d t0, t0, 3 -+ -+ addi.d a0, a4, -1 -+ sub.d a0, a0, t0 -+ maskeqz a0, a0, t1 -+ jr ra -+END(STRRCHR) -+ -+libc_hidden_builtin_def(STRRCHR) -diff --git a/sysdeps/loongarch/lp64/multiarch/strrchr-lasx.S b/sysdeps/loongarch/lp64/multiarch/strrchr-lasx.S -new file mode 100644 -index 00000000..5a6e2297 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strrchr-lasx.S -@@ -0,0 +1,176 @@ -+/* Optimized strrchr implementation using LoongArch LASX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+#define STRRCHR __strrchr_lasx -+ -+LEAF(STRRCHR, 6) -+ move a2, a0 -+ bstrins.d a0, zero, 5, 0 -+ xvld xr0, a0, 0 -+ xvld xr1, a0, 32 -+ -+ li.d t2, -1 -+ xvreplgr2vr.b xr4, a1 -+ xvmsknz.b xr2, xr0 -+ xvmsknz.b xr3, xr1 -+ -+ xvpickve.w xr5, xr2, 4 -+ xvpickve.w xr6, xr3, 4 -+ vilvl.h vr2, vr5, vr2 -+ vilvl.h vr3, vr6, vr3 -+ -+ vilvl.w vr2, vr3, vr2 -+ movfr2gr.d t0, fa2 -+ sra.d t0, t0, a2 -+ beq t0, t2, L(find_tail) -+ -+ -+ xvseq.b xr2, xr0, xr4 -+ xvseq.b xr3, xr1, xr4 -+ xvmsknz.b xr2, xr2 -+ xvmsknz.b xr3, xr3 -+ -+ xvpickve.w xr4, xr2, 4 -+ xvpickve.w xr5, xr3, 4 -+ vilvl.h vr2, vr4, vr2 -+ vilvl.h vr3, vr5, vr3 -+ -+ vilvl.w vr1, vr3, vr2 -+ slli.d t3, t2, 1 -+ movfr2gr.d t1, fa1 -+ cto.d t0, t0 -+ -+ srl.d t1, t1, a2 -+ sll.d t3, t3, t0 -+ addi.d a0, a2, 63 -+ andn t1, t1, t3 -+ -+ -+ clz.d t0, t1 -+ sub.d a0, a0, t0 -+ maskeqz a0, a0, t1 -+ jr ra -+ -+ .align 5 -+L(find_tail): -+ addi.d a3, a0, 64 -+L(loop): -+ xvld xr2, a0, 64 -+ xvld xr3, a0, 96 -+ addi.d a0, a0, 64 -+ -+ xvmin.bu xr5, xr2, xr3 -+ xvsetanyeqz.b fcc0, xr5 -+ bceqz fcc0, L(loop) -+ xvmsknz.b xr5, xr2 -+ -+ -+ xvmsknz.b xr6, xr3 -+ xvpickve.w xr7, xr5, 4 -+ xvpickve.w xr8, xr6, 4 -+ vilvl.h vr5, vr7, vr5 -+ -+ vilvl.h vr6, vr8, vr6 -+ xvseq.b xr2, xr2, xr4 -+ xvseq.b xr3, xr3, xr4 -+ xvmsknz.b xr2, xr2 -+ -+ xvmsknz.b xr3, xr3 -+ xvpickve.w xr7, xr2, 4 -+ xvpickve.w xr8, xr3, 4 -+ vilvl.h vr2, vr7, vr2 -+ -+ vilvl.h vr3, vr8, vr3 -+ vilvl.w vr5, vr6, vr5 -+ vilvl.w vr2, vr3, vr2 -+ movfr2gr.d t0, fa5 -+ -+ -+ movfr2gr.d t1, fa2 -+ slli.d t3, t2, 1 -+ cto.d t0, t0 -+ sll.d t3, t3, t0 -+ -+ andn t1, t1, t3 -+ beqz t1, L(find_loop) -+ clz.d t0, t1 -+ addi.d a0, a0, 63 -+ -+ sub.d a0, a0, t0 -+ jr ra -+L(find_loop): -+ beq a0, a3, L(find_end) -+ xvld xr2, a0, -64 -+ -+ xvld xr3, a0, -32 -+ addi.d a0, a0, -64 -+ xvseq.b xr2, xr2, xr4 -+ xvseq.b xr3, xr3, xr4 -+ -+ -+ xvmax.bu xr5, xr2, xr3 -+ xvseteqz.v fcc0, xr5 -+ bcnez fcc0, L(find_loop) -+ xvmsknz.b xr0, xr2 -+ -+ xvmsknz.b xr1, xr3 -+ xvpickve.w xr2, xr0, 4 -+ xvpickve.w xr3, xr1, 4 -+ vilvl.h vr0, vr2, vr0 -+ -+ vilvl.h vr1, vr3, vr1 -+ vilvl.w vr0, vr1, vr0 -+ movfr2gr.d t0, fa0 -+ addi.d a0, a0, 63 -+ -+ clz.d t0, t0 -+ sub.d a0, a0, t0 -+ jr ra -+ nop -+ -+ -+L(find_end): -+ xvseq.b xr2, xr0, xr4 -+ xvseq.b xr3, xr1, xr4 -+ xvmsknz.b xr2, xr2 -+ xvmsknz.b xr3, xr3 -+ -+ xvpickve.w xr4, xr2, 4 -+ xvpickve.w xr5, xr3, 4 -+ vilvl.h vr2, vr4, vr2 -+ vilvl.h vr3, vr5, vr3 -+ -+ vilvl.w vr1, vr3, vr2 -+ movfr2gr.d t1, fa1 -+ addi.d a0, a2, 63 -+ srl.d t1, t1, a2 -+ -+ clz.d t0, t1 -+ sub.d a0, a0, t0 -+ maskeqz a0, a0, t1 -+ jr ra -+END(STRRCHR) -+ -+libc_hidden_builtin_def(STRRCHR) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strrchr-lsx.S b/sysdeps/loongarch/lp64/multiarch/strrchr-lsx.S -new file mode 100644 -index 00000000..8f2fd22e ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strrchr-lsx.S -@@ -0,0 +1,144 @@ -+/* Optimized strrchr implementation using LoongArch LSX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+#define STRRCHR __strrchr_lsx -+ -+LEAF(STRRCHR, 6) -+ move a2, a0 -+ bstrins.d a0, zero, 4, 0 -+ vld vr0, a0, 0 -+ vld vr1, a0, 16 -+ -+ li.d t2, -1 -+ vreplgr2vr.b vr4, a1 -+ vmsknz.b vr2, vr0 -+ vmsknz.b vr3, vr1 -+ -+ vilvl.h vr2, vr3, vr2 -+ movfr2gr.s t0, fa2 -+ sra.w t0, t0, a2 -+ beq t0, t2, L(find_tail) -+ -+ vseq.b vr2, vr0, vr4 -+ vseq.b vr3, vr1, vr4 -+ vmsknz.b vr2, vr2 -+ vmsknz.b vr3, vr3 -+ -+ -+ vilvl.h vr1, vr3, vr2 -+ slli.d t3, t2, 1 -+ movfr2gr.s t1, fa1 -+ cto.w t0, t0 -+ -+ srl.w t1, t1, a2 -+ sll.d t3, t3, t0 -+ addi.d a0, a2, 31 -+ andn t1, t1, t3 -+ -+ clz.w t0, t1 -+ sub.d a0, a0, t0 -+ maskeqz a0, a0, t1 -+ jr ra -+ -+ .align 5 -+L(find_tail): -+ addi.d a3, a0, 32 -+L(loop): -+ vld vr2, a0, 32 -+ vld vr3, a0, 48 -+ addi.d a0, a0, 32 -+ -+ vmin.bu vr5, vr2, vr3 -+ vsetanyeqz.b fcc0, vr5 -+ bceqz fcc0, L(loop) -+ vmsknz.b vr5, vr2 -+ -+ vmsknz.b vr6, vr3 -+ vilvl.h vr5, vr6, vr5 -+ vseq.b vr2, vr2, vr4 -+ vseq.b vr3, vr3, vr4 -+ -+ vmsknz.b vr2, vr2 -+ vmsknz.b vr3, vr3 -+ vilvl.h vr2, vr3, vr2 -+ movfr2gr.s t0, fa5 -+ -+ -+ movfr2gr.s t1, fa2 -+ slli.d t3, t2, 1 -+ cto.w t0, t0 -+ sll.d t3, t3, t0 -+ -+ andn t1, t1, t3 -+ beqz t1, L(find_loop) -+ clz.w t0, t1 -+ addi.d a0, a0, 31 -+ -+ sub.d a0, a0, t0 -+ jr ra -+L(find_loop): -+ beq a0, a3, L(find_end) -+ vld vr2, a0, -32 -+ -+ vld vr3, a0, -16 -+ addi.d a0, a0, -32 -+ vseq.b vr2, vr2, vr4 -+ vseq.b vr3, vr3, vr4 -+ -+ -+ vmax.bu vr5, vr2, vr3 -+ vseteqz.v fcc0, vr5 -+ bcnez fcc0, L(find_loop) -+ vmsknz.b vr0, vr2 -+ -+ vmsknz.b vr1, vr3 -+ vilvl.h vr0, vr1, vr0 -+ movfr2gr.s t0, fa0 -+ addi.d a0, a0, 31 -+ -+ clz.w t0, t0 -+ sub.d a0, a0, t0 -+ jr ra -+ nop -+ -+L(find_end): -+ vseq.b vr2, vr0, vr4 -+ vseq.b vr3, vr1, vr4 -+ vmsknz.b vr2, vr2 -+ vmsknz.b vr3, vr3 -+ -+ -+ vilvl.h vr1, vr3, vr2 -+ movfr2gr.s t1, fa1 -+ addi.d a0, a2, 31 -+ srl.w t1, t1, a2 -+ -+ clz.w t0, t1 -+ sub.d a0, a0, t0 -+ maskeqz a0, a0, t1 -+ jr ra -+END(STRRCHR) -+ -+libc_hidden_builtin_def(STRRCHR) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strrchr.c b/sysdeps/loongarch/lp64/multiarch/strrchr.c -new file mode 100644 -index 00000000..d9c9f660 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strrchr.c -@@ -0,0 +1,36 @@ -+/* Multiple versions of strrchr. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+#if IS_IN (libc) -+# define strrchr __redirect_strrchr -+# include -+# undef strrchr -+ -+# define SYMBOL_NAME strrchr -+# include "ifunc-strrchr.h" -+ -+libc_ifunc_redirected (__redirect_strrchr, strrchr, IFUNC_SELECTOR ()); -+weak_alias (strrchr, rindex) -+# ifdef SHARED -+__hidden_ver1 (strrchr, __GI_strrchr, __redirect_strrchr) -+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strrchr); -+# endif -+ -+#endif --- -2.33.0 - diff --git a/LoongArch-Add-lasx-lsx-support-for-_dl_runtime_profi.patch b/LoongArch-Add-lasx-lsx-support-for-_dl_runtime_profi.patch deleted file mode 100644 index 35acd20..0000000 --- a/LoongArch-Add-lasx-lsx-support-for-_dl_runtime_profi.patch +++ /dev/null @@ -1,626 +0,0 @@ -From b5979df8ad07823c79a934c1fa0a91ec0abffb61 Mon Sep 17 00:00:00 2001 -From: caiyinyu -Date: Fri, 8 Sep 2023 14:10:55 +0800 -Subject: [PATCH 20/29] LoongArch: Add lasx/lsx support for - _dl_runtime_profile. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/bits/link.h | 24 ++- - sysdeps/loongarch/bits/link_lavcurrent.h | 25 +++ - sysdeps/loongarch/dl-audit-check.h | 23 +++ - sysdeps/loongarch/dl-link.sym | 8 +- - sysdeps/loongarch/dl-machine.h | 11 +- - sysdeps/loongarch/dl-trampoline.S | 177 +---------------- - sysdeps/loongarch/dl-trampoline.h | 242 +++++++++++++++++++++++ - 7 files changed, 331 insertions(+), 179 deletions(-) - create mode 100644 sysdeps/loongarch/bits/link_lavcurrent.h - create mode 100644 sysdeps/loongarch/dl-audit-check.h - -diff --git a/sysdeps/loongarch/bits/link.h b/sysdeps/loongarch/bits/link.h -index 7fa61312..00f6f25f 100644 ---- a/sysdeps/loongarch/bits/link.h -+++ b/sysdeps/loongarch/bits/link.h -@@ -20,10 +20,26 @@ - #error "Never include directly; use instead." - #endif - -+#ifndef __loongarch_soft_float -+typedef float La_loongarch_vr -+ __attribute__ ((__vector_size__ (16), __aligned__ (16))); -+typedef float La_loongarch_xr -+ __attribute__ ((__vector_size__ (32), __aligned__ (16))); -+ -+typedef union -+{ -+ double fpreg[4]; -+ La_loongarch_vr vr[2]; -+ La_loongarch_xr xr[1]; -+} La_loongarch_vector __attribute__ ((__aligned__ (16))); -+#endif -+ - typedef struct La_loongarch_regs - { - unsigned long int lr_reg[8]; /* a0 - a7 */ -- double lr_fpreg[8]; /* fa0 - fa7 */ -+#ifndef __loongarch_soft_float -+ La_loongarch_vector lr_vec[8]; /* fa0 - fa7 or vr0 - vr7 or xr0 - xr7*/ -+#endif - unsigned long int lr_ra; - unsigned long int lr_sp; - } La_loongarch_regs; -@@ -33,8 +49,10 @@ typedef struct La_loongarch_retval - { - unsigned long int lrv_a0; - unsigned long int lrv_a1; -- double lrv_fa0; -- double lrv_fa1; -+#ifndef __loongarch_soft_float -+ La_loongarch_vector lrv_vec0; -+ La_loongarch_vector lrv_vec1; -+#endif - } La_loongarch_retval; - - __BEGIN_DECLS -diff --git a/sysdeps/loongarch/bits/link_lavcurrent.h b/sysdeps/loongarch/bits/link_lavcurrent.h -new file mode 100644 -index 00000000..15f1eb84 ---- /dev/null -+++ b/sysdeps/loongarch/bits/link_lavcurrent.h -@@ -0,0 +1,25 @@ -+/* Data structure for communication from the run-time dynamic linker for -+ loaded ELF shared objects. LAV_CURRENT definition. -+ Copyright (C) 2023 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 -+ . */ -+ -+#ifndef _LINK_H -+# error "Never include directly; use instead." -+#endif -+ -+/* Version numbers for la_version handshake interface. */ -+#define LAV_CURRENT 3 -diff --git a/sysdeps/loongarch/dl-audit-check.h b/sysdeps/loongarch/dl-audit-check.h -new file mode 100644 -index 00000000..a139c939 ---- /dev/null -+++ b/sysdeps/loongarch/dl-audit-check.h -@@ -0,0 +1,23 @@ -+/* rtld-audit version check. LoongArch version. -+ Copyright (C) 2023 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 -+ . */ -+ -+static inline bool -+_dl_audit_check_version (unsigned int lav) -+{ -+ return lav == LAV_CURRENT; -+} -diff --git a/sysdeps/loongarch/dl-link.sym b/sysdeps/loongarch/dl-link.sym -index 868ab7c6..b534968e 100644 ---- a/sysdeps/loongarch/dl-link.sym -+++ b/sysdeps/loongarch/dl-link.sym -@@ -6,9 +6,13 @@ DL_SIZEOF_RG sizeof(struct La_loongarch_regs) - DL_SIZEOF_RV sizeof(struct La_loongarch_retval) - - DL_OFFSET_RG_A0 offsetof(struct La_loongarch_regs, lr_reg) --DL_OFFSET_RG_FA0 offsetof(struct La_loongarch_regs, lr_fpreg) -+#ifndef __loongarch_soft_float -+DL_OFFSET_RG_VEC0 offsetof(struct La_loongarch_regs, lr_vec) -+#endif - DL_OFFSET_RG_RA offsetof(struct La_loongarch_regs, lr_ra) - DL_OFFSET_RG_SP offsetof(struct La_loongarch_regs, lr_sp) - - DL_OFFSET_RV_A0 offsetof(struct La_loongarch_retval, lrv_a0) --DL_OFFSET_RV_FA0 offsetof(struct La_loongarch_retval, lrv_a1) -+#ifndef __loongarch_soft_float -+DL_OFFSET_RV_VEC0 offsetof(struct La_loongarch_retval, lrv_vec0) -+#endif -diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h -index 066bb233..8a2db9de 100644 ---- a/sysdeps/loongarch/dl-machine.h -+++ b/sysdeps/loongarch/dl-machine.h -@@ -273,6 +273,8 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], - #if !defined __loongarch_soft_float - extern void _dl_runtime_resolve_lasx (void) attribute_hidden; - extern void _dl_runtime_resolve_lsx (void) attribute_hidden; -+ extern void _dl_runtime_profile_lasx (void) attribute_hidden; -+ extern void _dl_runtime_profile_lsx (void) attribute_hidden; - #endif - extern void _dl_runtime_resolve (void) attribute_hidden; - extern void _dl_runtime_profile (void) attribute_hidden; -@@ -287,7 +289,14 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], - end in this function. */ - if (profile != 0) - { -- gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile; -+#if !defined __loongarch_soft_float -+ if (SUPPORT_LASX) -+ gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lasx; -+ else if (SUPPORT_LSX) -+ gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lsx; -+ else -+#endif -+ gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile; - - if (GLRO(dl_profile) != NULL - && _dl_name_match_p (GLRO(dl_profile), l)) -diff --git a/sysdeps/loongarch/dl-trampoline.S b/sysdeps/loongarch/dl-trampoline.S -index 8fd91469..bb449ecf 100644 ---- a/sysdeps/loongarch/dl-trampoline.S -+++ b/sysdeps/loongarch/dl-trampoline.S -@@ -22,190 +22,21 @@ - #if !defined __loongarch_soft_float - #define USE_LASX - #define _dl_runtime_resolve _dl_runtime_resolve_lasx -+#define _dl_runtime_profile _dl_runtime_profile_lasx - #include "dl-trampoline.h" - #undef FRAME_SIZE - #undef USE_LASX - #undef _dl_runtime_resolve -+#undef _dl_runtime_profile - - #define USE_LSX - #define _dl_runtime_resolve _dl_runtime_resolve_lsx -+#define _dl_runtime_profile _dl_runtime_profile_lsx - #include "dl-trampoline.h" - #undef FRAME_SIZE - #undef USE_LSX - #undef _dl_runtime_resolve -+#undef _dl_runtime_profile - #endif - - #include "dl-trampoline.h" -- --#include "dl-link.h" -- --ENTRY (_dl_runtime_profile) -- /* LoongArch we get called with: -- t0 linkr_map pointer -- t1 the scaled offset stored in t0, which can be used -- to calculate the offset of the current symbol in .rela.plt -- t2 %hi(%pcrel(.got.plt)) stored in t2, no use in this function -- t3 dl resolver entry point, no use in this function -- -- Stack frame layout: -- [sp, #96] La_loongarch_regs -- [sp, #48] La_loongarch_retval -- [sp, #40] frame size return from pltenter -- [sp, #32] dl_profile_call saved a1 -- [sp, #24] dl_profile_call saved a0 -- [sp, #16] T1 -- [sp, #0] ra, fp <- fp -- */ -- --# define OFFSET_T1 16 --# define OFFSET_SAVED_CALL_A0 OFFSET_T1 + 8 --# define OFFSET_FS OFFSET_SAVED_CALL_A0 + 16 --# define OFFSET_RV OFFSET_FS + 8 --# define OFFSET_RG OFFSET_RV + DL_SIZEOF_RV -- --# define SF_SIZE (-(-(OFFSET_RG + DL_SIZEOF_RG) & ALMASK)) -- -- /* Save arguments to stack. */ -- ADDI sp, sp, -SF_SIZE -- REG_S ra, sp, 0 -- REG_S fp, sp, 8 -- -- or fp, sp, zero -- -- REG_S a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG -- REG_S a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG -- REG_S a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG -- REG_S a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG -- REG_S a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG -- REG_S a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG -- REG_S a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG -- REG_S a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG -- --#ifndef __loongarch_soft_float -- FREG_S fa0, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 0*SZFREG -- FREG_S fa1, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 1*SZFREG -- FREG_S fa2, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 2*SZFREG -- FREG_S fa3, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 3*SZFREG -- FREG_S fa4, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 4*SZFREG -- FREG_S fa5, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 5*SZFREG -- FREG_S fa6, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 6*SZFREG -- FREG_S fa7, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 7*SZFREG --#endif -- -- /* Update .got.plt and obtain runtime address of callee. */ -- SLLI a1, t1, 1 -- or a0, t0, zero -- ADD a1, a1, t1 -- or a2, ra, zero /* return addr */ -- ADDI a3, fp, OFFSET_RG /* La_loongarch_regs pointer */ -- ADDI a4, fp, OFFSET_FS /* frame size return from pltenter */ -- -- REG_S a0, fp, OFFSET_SAVED_CALL_A0 -- REG_S a1, fp, OFFSET_SAVED_CALL_A0 + SZREG -- -- la t2, _dl_profile_fixup -- jirl ra, t2, 0 -- -- REG_L t3, fp, OFFSET_FS -- bge t3, zero, 1f -- -- /* Save the return. */ -- or t4, v0, zero -- -- /* Restore arguments from stack. */ -- REG_L a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG -- REG_L a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG -- REG_L a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG -- REG_L a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG -- REG_L a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG -- REG_L a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG -- REG_L a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG -- REG_L a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG -- --#ifndef __loongarch_soft_float -- FREG_L fa0, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 0*SZFREG -- FREG_L fa1, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 1*SZFREG -- FREG_L fa2, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 2*SZFREG -- FREG_L fa3, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 3*SZFREG -- FREG_L fa4, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 4*SZFREG -- FREG_L fa5, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 5*SZFREG -- FREG_L fa6, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 6*SZFREG -- FREG_L fa7, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 7*SZFREG --#endif -- -- REG_L ra, fp, 0 -- REG_L fp, fp, SZREG -- -- ADDI sp, sp, SF_SIZE -- jirl zero, t4, 0 -- --1: -- /* The new frame size is in t3. */ -- SUB sp, fp, t3 -- BSTRINS sp, zero, 3, 0 -- -- REG_S a0, fp, OFFSET_T1 -- -- or a0, sp, zero -- ADDI a1, fp, SF_SIZE -- or a2, t3, zero -- la t5, memcpy -- jirl ra, t5, 0 -- -- REG_L t6, fp, OFFSET_T1 -- -- /* Call the function. */ -- REG_L a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG -- REG_L a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG -- REG_L a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG -- REG_L a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG -- REG_L a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG -- REG_L a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG -- REG_L a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG -- REG_L a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG -- --#ifndef __loongarch_soft_float -- FREG_L fa0, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 0*SZFREG -- FREG_L fa1, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 1*SZFREG -- FREG_L fa2, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 2*SZFREG -- FREG_L fa3, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 3*SZFREG -- FREG_L fa4, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 4*SZFREG -- FREG_L fa5, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 5*SZFREG -- FREG_L fa6, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 6*SZFREG -- FREG_L fa7, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 7*SZFREG --#endif -- jirl ra, t6, 0 -- -- REG_S a0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_A0 -- REG_S a1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_A0 + SZREG -- --#ifndef __loongarch_soft_float -- FREG_S fa0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_FA0 -- FREG_S fa1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_FA0 + SZFREG --#endif -- -- /* Setup call to pltexit. */ -- REG_L a0, fp, OFFSET_SAVED_CALL_A0 -- REG_L a1, fp, OFFSET_SAVED_CALL_A0 + SZREG -- ADDI a2, fp, OFFSET_RG -- ADDI a3, fp, OFFSET_RV -- la t7, _dl_audit_pltexit -- jirl ra, t7, 0 -- -- REG_L a0, fp, OFFSET_RV + DL_OFFSET_RV_A0 -- REG_L a1, fp, OFFSET_RV + DL_OFFSET_RV_A0 + SZREG -- --#ifndef __loongarch_soft_float -- FREG_L fa0, fp, OFFSET_RV + DL_OFFSET_RV_FA0 -- FREG_L fa1, fp, OFFSET_RV + DL_OFFSET_RV_FA0 + SZFREG --#endif -- -- /* RA from within La_loongarch_reg. */ -- REG_L ra, fp, OFFSET_RG + DL_OFFSET_RG_RA -- or sp, fp, zero -- ADDI sp, sp, SF_SIZE -- REG_S fp, fp, SZREG -- -- jirl zero, ra, 0 -- --END (_dl_runtime_profile) -diff --git a/sysdeps/loongarch/dl-trampoline.h b/sysdeps/loongarch/dl-trampoline.h -index 99fcacab..e298439d 100644 ---- a/sysdeps/loongarch/dl-trampoline.h -+++ b/sysdeps/loongarch/dl-trampoline.h -@@ -125,3 +125,245 @@ ENTRY (_dl_runtime_resolve) - /* Invoke the callee. */ - jirl zero, t1, 0 - END (_dl_runtime_resolve) -+ -+#include "dl-link.h" -+ -+ENTRY (_dl_runtime_profile) -+ /* LoongArch we get called with: -+ t0 linkr_map pointer -+ t1 the scaled offset stored in t0, which can be used -+ to calculate the offset of the current symbol in .rela.plt -+ t2 %hi(%pcrel(.got.plt)) stored in t2, no use in this function -+ t3 dl resolver entry point, no use in this function -+ -+ Stack frame layout: -+ [sp, #208] La_loongarch_regs -+ [sp, #128] La_loongarch_retval // align: 16 -+ [sp, #112] frame size return from pltenter -+ [sp, #80 ] dl_profile_call saved vec1 -+ [sp, #48 ] dl_profile_call saved vec0 // align: 16 -+ [sp, #32 ] dl_profile_call saved a1 -+ [sp, #24 ] dl_profile_call saved a0 -+ [sp, #16 ] T1 -+ [sp, #0 ] ra, fp <- fp -+ */ -+ -+# define OFFSET_T1 16 -+# define OFFSET_SAVED_CALL_A0 OFFSET_T1 + 8 -+# define OFFSET_FS OFFSET_SAVED_CALL_A0 + 16 + 8 + 64 -+# define OFFSET_RV OFFSET_FS + 8 + 8 -+# define OFFSET_RG OFFSET_RV + DL_SIZEOF_RV -+ -+# define SF_SIZE (-(-(OFFSET_RG + DL_SIZEOF_RG) & ALMASK)) -+ -+ /* Save arguments to stack. */ -+ ADDI sp, sp, -SF_SIZE -+ REG_S ra, sp, 0 -+ REG_S fp, sp, 8 -+ -+ or fp, sp, zero -+ -+ REG_S a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG -+ REG_S a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG -+ REG_S a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG -+ REG_S a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG -+ REG_S a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG -+ REG_S a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG -+ REG_S a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG -+ REG_S a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG -+ -+#ifdef USE_LASX -+ xvst xr0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZXREG -+ xvst xr1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZXREG -+ xvst xr2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZXREG -+ xvst xr3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZXREG -+ xvst xr4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZXREG -+ xvst xr5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZXREG -+ xvst xr6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZXREG -+ xvst xr7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZXREG -+#elif defined USE_LSX -+ vst vr0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZVREG -+ vst vr1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZVREG -+ vst vr2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZVREG -+ vst vr3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZVREG -+ vst vr4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZVREG -+ vst vr5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZVREG -+ vst vr6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZVREG -+ vst vr7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZVREG -+#elif !defined __loongarch_soft_float -+ FREG_S fa0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZFREG -+ FREG_S fa1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZFREG -+ FREG_S fa2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZFREG -+ FREG_S fa3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZFREG -+ FREG_S fa4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZFREG -+ FREG_S fa5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZFREG -+ FREG_S fa6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZFREG -+ FREG_S fa7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZFREG -+#endif -+ -+ /* Update .got.plt and obtain runtime address of callee. */ -+ SLLI a1, t1, 1 -+ or a0, t0, zero -+ ADD a1, a1, t1 -+ or a2, ra, zero /* return addr */ -+ ADDI a3, fp, OFFSET_RG /* La_loongarch_regs pointer */ -+ ADDI a4, fp, OFFSET_FS /* frame size return from pltenter */ -+ -+ REG_S a0, fp, OFFSET_SAVED_CALL_A0 -+ REG_S a1, fp, OFFSET_SAVED_CALL_A0 + SZREG -+ -+ la t2, _dl_profile_fixup -+ jirl ra, t2, 0 -+ -+ REG_L t3, fp, OFFSET_FS -+ bge t3, zero, 1f -+ -+ /* Save the return. */ -+ or t4, v0, zero -+ -+ /* Restore arguments from stack. */ -+ REG_L a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG -+ REG_L a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG -+ REG_L a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG -+ REG_L a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG -+ REG_L a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG -+ REG_L a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG -+ REG_L a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG -+ REG_L a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG -+ -+#ifdef USE_LASX -+ xvld xr0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZXREG -+ xvld xr1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZXREG -+ xvld xr2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZXREG -+ xvld xr3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZXREG -+ xvld xr4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZXREG -+ xvld xr5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZXREG -+ xvld xr6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZXREG -+ xvld xr7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZXREG -+#elif defined USE_LSX -+ vld vr0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZVREG -+ vld vr1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZVREG -+ vld vr2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZVREG -+ vld vr3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZVREG -+ vld vr4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZVREG -+ vld vr5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZVREG -+ vld vr6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZVREG -+ vld vr7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZVREG -+#elif !defined __loongarch_soft_float -+ FREG_L fa0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZFREG -+ FREG_L fa1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZFREG -+ FREG_L fa2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZFREG -+ FREG_L fa3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZFREG -+ FREG_L fa4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZFREG -+ FREG_L fa5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZFREG -+ FREG_L fa6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZFREG -+ FREG_L fa7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZFREG -+#endif -+ -+ REG_L ra, fp, 0 -+ REG_L fp, fp, SZREG -+ -+ ADDI sp, sp, SF_SIZE -+ jirl zero, t4, 0 -+ -+1: -+ /* The new frame size is in t3. */ -+ SUB sp, fp, t3 -+ BSTRINS sp, zero, 3, 0 -+ -+ REG_S a0, fp, OFFSET_T1 -+ -+ or a0, sp, zero -+ ADDI a1, fp, SF_SIZE -+ or a2, t3, zero -+ la t5, memcpy -+ jirl ra, t5, 0 -+ -+ REG_L t6, fp, OFFSET_T1 -+ -+ /* Call the function. */ -+ REG_L a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG -+ REG_L a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG -+ REG_L a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG -+ REG_L a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG -+ REG_L a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG -+ REG_L a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG -+ REG_L a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG -+ REG_L a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG -+ -+#ifdef USE_LASX -+ xvld xr0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZXREG -+ xvld xr1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZXREG -+ xvld xr2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZXREG -+ xvld xr3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZXREG -+ xvld xr4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZXREG -+ xvld xr5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZXREG -+ xvld xr6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZXREG -+ xvld xr7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZXREG -+#elif defined USE_LSX -+ vld vr0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZVREG -+ vld vr1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZVREG -+ vld vr2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZVREG -+ vld vr3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZVREG -+ vld vr4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZVREG -+ vld vr5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZVREG -+ vld vr6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZVREG -+ vld vr7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZVREG -+#elif !defined __loongarch_soft_float -+ FREG_L fa0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZFREG -+ FREG_L fa1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZFREG -+ FREG_L fa2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZFREG -+ FREG_L fa3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZFREG -+ FREG_L fa4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZFREG -+ FREG_L fa5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZFREG -+ FREG_L fa6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZFREG -+ FREG_L fa7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZFREG -+#endif -+ -+ jirl ra, t6, 0 -+ -+ REG_S a0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_A0 -+ REG_S a1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_A0 + SZREG -+ -+#ifdef USE_LASX -+ xvst xr0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 -+ xvst xr1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 + SZXREG -+#elif defined USE_LSX -+ vst vr0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 -+ vst vr1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 + SZVREG -+#elif !defined __loongarch_soft_float -+ FREG_S fa0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 -+ FREG_S fa1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 + SZFREG -+#endif -+ -+ /* Setup call to pltexit. */ -+ REG_L a0, fp, OFFSET_SAVED_CALL_A0 -+ REG_L a1, fp, OFFSET_SAVED_CALL_A0 + SZREG -+ ADDI a2, fp, OFFSET_RG -+ ADDI a3, fp, OFFSET_RV -+ la t7, _dl_audit_pltexit -+ jirl ra, t7, 0 -+ -+ REG_L a0, fp, OFFSET_RV + DL_OFFSET_RV_A0 -+ REG_L a1, fp, OFFSET_RV + DL_OFFSET_RV_A0 + SZREG -+ -+#ifdef USE_LASX -+ xvld xr0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 -+ xvld xr1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 + SZXREG -+#elif defined USE_LSX -+ vld vr0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 -+ vld vr1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 + SZVREG -+#elif !defined __loongarch_soft_float -+ FREG_L fa0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 -+ FREG_L fa1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 + SZFREG -+#endif -+ -+ /* RA from within La_loongarch_reg. */ -+ REG_L ra, fp, OFFSET_RG + DL_OFFSET_RG_RA -+ or sp, fp, zero -+ ADDI sp, sp, SF_SIZE -+ REG_S fp, fp, SZREG -+ -+ jirl zero, ra, 0 -+ -+END (_dl_runtime_profile) --- -2.33.0 - diff --git a/LoongArch-Add-minuimum-binutils-required-version.patch b/LoongArch-Add-minuimum-binutils-required-version.patch deleted file mode 100644 index 9bdcf22..0000000 --- a/LoongArch-Add-minuimum-binutils-required-version.patch +++ /dev/null @@ -1,102 +0,0 @@ -From 7353f21f6ed1754b67e455e2b80123787efa9e91 Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Tue, 8 Aug 2023 14:15:43 +0800 -Subject: [PATCH 02/29] LoongArch: Add minuimum binutils required version - -LoongArch glibc can add some LASX/LSX vector instructions codes, -change the required minimum binutils version to 2.41 which could -support vector instructions. HAVE_LOONGARCH_VEC_ASM is removed -accordingly. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - config.h.in | 5 ----- - sysdeps/loongarch/configure | 5 ++--- - sysdeps/loongarch/configure.ac | 4 ++-- - sysdeps/loongarch/dl-machine.h | 4 ++-- - sysdeps/loongarch/dl-trampoline.S | 2 +- - 5 files changed, 7 insertions(+), 13 deletions(-) - -diff --git a/config.h.in b/config.h.in -index 0dedc124..44a34072 100644 ---- a/config.h.in -+++ b/config.h.in -@@ -141,11 +141,6 @@ - /* LOONGARCH floating-point ABI for ld.so. */ - #undef LOONGARCH_ABI_FRLEN - --/* Assembler support LoongArch LASX/LSX vector instructions. -- This macro becomes obsolete when glibc increased the minimum -- required version of GNU 'binutils' to 2.41 or later. */ --#define HAVE_LOONGARCH_VEC_ASM 0 -- - /* Linux specific: minimum supported kernel version. */ - #undef __LINUX_KERNEL_VERSION - -diff --git a/sysdeps/loongarch/configure b/sysdeps/loongarch/configure -index 5843c7cf..395ddc92 100644 ---- a/sysdeps/loongarch/configure -+++ b/sysdeps/loongarch/configure -@@ -128,8 +128,7 @@ rm -f conftest* - fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_loongarch_vec_asm" >&5 - printf "%s\n" "$libc_cv_loongarch_vec_asm" >&6; } --if test $libc_cv_loongarch_vec_asm = yes; then -- printf "%s\n" "#define HAVE_LOONGARCH_VEC_ASM 1" >>confdefs.h -- -+if test $libc_cv_loongarch_vec_asm = no; then -+ as_fn_error $? "binutils version is too old, use 2.41 or newer version" "$LINENO" 5 - fi - -diff --git a/sysdeps/loongarch/configure.ac b/sysdeps/loongarch/configure.ac -index ba89d834..989287c6 100644 ---- a/sysdeps/loongarch/configure.ac -+++ b/sysdeps/loongarch/configure.ac -@@ -74,6 +74,6 @@ else - libc_cv_loongarch_vec_asm=no - fi - rm -f conftest*]) --if test $libc_cv_loongarch_vec_asm = yes; then -- AC_DEFINE(HAVE_LOONGARCH_VEC_ASM) -+if test $libc_cv_loongarch_vec_asm = no; then -+ AC_MSG_ERROR([binutils version is too old, use 2.41 or newer version]) - fi -diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h -index 51ce9af8..066bb233 100644 ---- a/sysdeps/loongarch/dl-machine.h -+++ b/sysdeps/loongarch/dl-machine.h -@@ -270,7 +270,7 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], - /* If using PLTs, fill in the first two entries of .got.plt. */ - if (l->l_info[DT_JMPREL]) - { --#if HAVE_LOONGARCH_VEC_ASM && !defined __loongarch_soft_float -+#if !defined __loongarch_soft_float - extern void _dl_runtime_resolve_lasx (void) attribute_hidden; - extern void _dl_runtime_resolve_lsx (void) attribute_hidden; - #endif -@@ -300,7 +300,7 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], - /* This function will get called to fix up the GOT entry - indicated by the offset on the stack, and then jump to - the resolved address. */ --#if HAVE_LOONGARCH_VEC_ASM && !defined __loongarch_soft_float -+#if !defined __loongarch_soft_float - if (SUPPORT_LASX) - gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lasx; - else if (SUPPORT_LSX) -diff --git a/sysdeps/loongarch/dl-trampoline.S b/sysdeps/loongarch/dl-trampoline.S -index f6ba5e44..8fd91469 100644 ---- a/sysdeps/loongarch/dl-trampoline.S -+++ b/sysdeps/loongarch/dl-trampoline.S -@@ -19,7 +19,7 @@ - #include - #include - --#if HAVE_LOONGARCH_VEC_ASM && !defined __loongarch_soft_float -+#if !defined __loongarch_soft_float - #define USE_LASX - #define _dl_runtime_resolve _dl_runtime_resolve_lasx - #include "dl-trampoline.h" --- -2.33.0 - diff --git a/LoongArch-Change-loongarch-to-LoongArch-in-comments.patch b/LoongArch-Change-loongarch-to-LoongArch-in-comments.patch deleted file mode 100644 index 1f7bff6..0000000 --- a/LoongArch-Change-loongarch-to-LoongArch-in-comments.patch +++ /dev/null @@ -1,277 +0,0 @@ -From e5ccd79e81de7ad5821fde83875973e878d85d4b Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Mon, 28 Aug 2023 10:08:40 +0800 -Subject: [PATCH 19/29] LoongArch: Change loongarch to LoongArch in comments - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S | 2 +- - sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S | 2 +- - sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S | 2 +- - sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S | 2 +- - sysdeps/loongarch/lp64/multiarch/memmove-aligned.S | 2 +- - sysdeps/loongarch/lp64/multiarch/memmove-lasx.S | 2 +- - sysdeps/loongarch/lp64/multiarch/memmove-lsx.S | 2 +- - sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strchr-aligned.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strchr-lasx.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strchr-lsx.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strlen-aligned.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strlen-lasx.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strlen-lsx.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S | 2 +- - sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S | 2 +- - 24 files changed, 24 insertions(+), 24 deletions(-) - -diff --git a/sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S b/sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S -index 299dd49c..7eb34395 100644 ---- a/sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S -+++ b/sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S -@@ -1,4 +1,4 @@ --/* Optimized memcpy_aligned implementation using basic Loongarch instructions. -+/* Optimized memcpy_aligned implementation using basic LoongArch instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S b/sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S -index 4aae5bf8..ae148df5 100644 ---- a/sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S -+++ b/sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S -@@ -1,4 +1,4 @@ --/* Optimized memcpy implementation using Loongarch LASX instructions. -+/* Optimized memcpy implementation using LoongArch LASX instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S b/sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S -index 6ebbe7a2..feb2bb0e 100644 ---- a/sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S -+++ b/sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S -@@ -1,4 +1,4 @@ --/* Optimized memcpy implementation using Loongarch LSX instructions. -+/* Optimized memcpy implementation using LoongArch LSX instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S b/sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S -index 8e60a22d..31019b13 100644 ---- a/sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S -+++ b/sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S -@@ -1,4 +1,4 @@ --/* Optimized unaligned memcpy implementation using basic Loongarch instructions. -+/* Optimized unaligned memcpy implementation using basic LoongArch instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-aligned.S b/sysdeps/loongarch/lp64/multiarch/memmove-aligned.S -index 5354f383..a02114c0 100644 ---- a/sysdeps/loongarch/lp64/multiarch/memmove-aligned.S -+++ b/sysdeps/loongarch/lp64/multiarch/memmove-aligned.S -@@ -1,4 +1,4 @@ --/* Optimized memmove_aligned implementation using basic Loongarch instructions. -+/* Optimized memmove_aligned implementation using basic LoongArch instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-lasx.S b/sysdeps/loongarch/lp64/multiarch/memmove-lasx.S -index ff68e7a2..95d8ee7b 100644 ---- a/sysdeps/loongarch/lp64/multiarch/memmove-lasx.S -+++ b/sysdeps/loongarch/lp64/multiarch/memmove-lasx.S -@@ -1,4 +1,4 @@ --/* Optimized memmove implementation using Loongarch LASX instructions. -+/* Optimized memmove implementation using LoongArch LASX instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S b/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S -index 9e1502a7..8a936770 100644 ---- a/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S -+++ b/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S -@@ -1,4 +1,4 @@ --/* Optimized memmove implementation using Loongarch LSX instructions. -+/* Optimized memmove implementation using LoongArch LSX instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S b/sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S -index 90a64b6b..3284ce25 100644 ---- a/sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S -+++ b/sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S -@@ -1,4 +1,4 @@ --/* Optimized memmove_unaligned implementation using basic Loongarch instructions. -+/* Optimized memmove_unaligned implementation using basic LoongArch instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strchr-aligned.S b/sysdeps/loongarch/lp64/multiarch/strchr-aligned.S -index 5fb01806..62020054 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strchr-aligned.S -+++ b/sysdeps/loongarch/lp64/multiarch/strchr-aligned.S -@@ -1,4 +1,4 @@ --/* Optimized strchr implementation using basic Loongarch instructions. -+/* Optimized strchr implementation using basic LoongArch instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strchr-lasx.S b/sysdeps/loongarch/lp64/multiarch/strchr-lasx.S -index 254402da..4d3cc588 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strchr-lasx.S -+++ b/sysdeps/loongarch/lp64/multiarch/strchr-lasx.S -@@ -1,4 +1,4 @@ --/* Optimized strchr implementation using loongarch LASX SIMD instructions. -+/* Optimized strchr implementation using LoongArch LASX instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strchr-lsx.S b/sysdeps/loongarch/lp64/multiarch/strchr-lsx.S -index dae98b0a..8b78c35c 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strchr-lsx.S -+++ b/sysdeps/loongarch/lp64/multiarch/strchr-lsx.S -@@ -1,4 +1,4 @@ --/* Optimized strlen implementation using loongarch LSX SIMD instructions. -+/* Optimized strlen implementation using LoongArch LSX instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S b/sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S -index 1c01a023..20856a06 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S -+++ b/sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S -@@ -1,4 +1,4 @@ --/* Optimized strchrnul implementation using basic Loongarch instructions. -+/* Optimized strchrnul implementation using basic LoongArch instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S b/sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S -index d45495e4..4753d4ce 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S -+++ b/sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S -@@ -1,4 +1,4 @@ --/* Optimized strchrnul implementation using loongarch LASX SIMD instructions. -+/* Optimized strchrnul implementation using LoongArch LASX instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S b/sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S -index 07d793ae..671e740c 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S -+++ b/sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S -@@ -1,4 +1,4 @@ --/* Optimized strchrnul implementation using loongarch LSX SIMD instructions. -+/* Optimized strchrnul implementation using LoongArch LSX instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S b/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S -index f5f4f336..ba1f9667 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S -+++ b/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S -@@ -1,4 +1,4 @@ --/* Optimized strcmp implementation using basic Loongarch instructions. -+/* Optimized strcmp implementation using basic LoongArch instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S b/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S -index 2e177a38..091c8c9e 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S -+++ b/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S -@@ -1,4 +1,4 @@ --/* Optimized strcmp implementation using Loongarch LSX instructions. -+/* Optimized strcmp implementation using LoongArch LSX instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S b/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S -index e9e1d2fc..ed0548e4 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S -+++ b/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S -@@ -1,4 +1,4 @@ --/* Optimized strlen implementation using basic Loongarch instructions. -+/* Optimized strlen implementation using basic LoongArch instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S b/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S -index 258c47ce..91342f34 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S -+++ b/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S -@@ -1,4 +1,4 @@ --/* Optimized strlen implementation using loongarch LASX SIMD instructions. -+/* Optimized strlen implementation using LoongArch LASX instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S b/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S -index b194355e..b09c12e0 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S -+++ b/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S -@@ -1,4 +1,4 @@ --/* Optimized strlen implementation using Loongarch LSX SIMD instructions. -+/* Optimized strlen implementation using LoongArch LSX instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S b/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S -index e2687fa7..f63de872 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S -+++ b/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S -@@ -1,4 +1,4 @@ --/* Optimized strncmp implementation using basic Loongarch instructions. -+/* Optimized strncmp implementation using basic LoongArch instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S b/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S -index 0b4eee2a..83cb801d 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S -+++ b/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S -@@ -1,4 +1,4 @@ --/* Optimized strncmp implementation using Loongarch LSX instructions. -+/* Optimized strncmp implementation using LoongArch LSX instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S b/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S -index b900430a..a8296a1b 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S -+++ b/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S -@@ -1,4 +1,4 @@ --/* Optimized strnlen implementation using basic Loongarch instructions. -+/* Optimized strnlen implementation using basic LoongArch instructions. - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S b/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S -index 2c03d3d9..aa6c812d 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S -+++ b/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S -@@ -1,4 +1,4 @@ --/* Optimized strnlen implementation using loongarch LASX instructions -+/* Optimized strnlen implementation using LoongArch LASX instructions - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. -diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S b/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S -index b769a895..d0febe3e 100644 ---- a/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S -+++ b/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S -@@ -1,4 +1,4 @@ --/* Optimized strnlen implementation using loongarch LSX instructions -+/* Optimized strnlen implementation using LoongArch LSX instructions - Copyright (C) 2023 Free Software Foundation, Inc. - - This file is part of the GNU C Library. --- -2.33.0 - diff --git a/LoongArch-Change-to-put-magic-number-to-.rodata-sect.patch b/LoongArch-Change-to-put-magic-number-to-.rodata-sect.patch deleted file mode 100644 index 896eb1f..0000000 --- a/LoongArch-Change-to-put-magic-number-to-.rodata-sect.patch +++ /dev/null @@ -1,67 +0,0 @@ -From fb72c81f9894b23797f6e2e066532c0963f5155f Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Wed, 13 Sep 2023 15:35:01 +0800 -Subject: [PATCH 24/29] LoongArch: Change to put magic number to .rodata - section - -Change to put magic number to .rodata section in memmove-lsx, and use -pcalau12i and %pc_lo12 with vld to get the data. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - .../loongarch/lp64/multiarch/memmove-lsx.S | 20 +++++++++---------- - 1 file changed, 10 insertions(+), 10 deletions(-) - -diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S b/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S -index 8a936770..5eb819ef 100644 ---- a/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S -+++ b/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S -@@ -209,13 +209,10 @@ L(al_less_16): - nop - - --L(magic_num): -- .dword 0x0706050403020100 -- .dword 0x0f0e0d0c0b0a0908 - L(unaligned): -- pcaddi t2, -4 -+ pcalau12i t2, %pc_hi20(L(INDEX)) - bstrins.d a1, zero, 3, 0 -- vld vr8, t2, 0 -+ vld vr8, t2, %pc_lo12(L(INDEX)) - vld vr0, a1, 0 - - vld vr1, a1, 16 -@@ -413,13 +410,10 @@ L(back_al_less_16): - vst vr1, a0, 0 - jr ra - --L(magic_num_2): -- .dword 0x0706050403020100 -- .dword 0x0f0e0d0c0b0a0908 - L(back_unaligned): -- pcaddi t2, -4 -+ pcalau12i t2, %pc_hi20(L(INDEX)) - bstrins.d a4, zero, 3, 0 -- vld vr8, t2, 0 -+ vld vr8, t2, %pc_lo12(L(INDEX)) - vld vr0, a4, 0 - - vld vr1, a4, -16 -@@ -529,6 +523,12 @@ L(back_un_less_16): - jr ra - END(MEMMOVE_NAME) - -+ .section .rodata.cst16,"M",@progbits,16 -+ .align 4 -+L(INDEX): -+ .dword 0x0706050403020100 -+ .dword 0x0f0e0d0c0b0a0908 -+ - libc_hidden_builtin_def (MEMCPY_NAME) - libc_hidden_builtin_def (MEMMOVE_NAME) - #endif --- -2.33.0 - diff --git a/LoongArch-Micro-optimize-LD_PCREL.patch b/LoongArch-Micro-optimize-LD_PCREL.patch deleted file mode 100644 index 0362e34..0000000 --- a/LoongArch-Micro-optimize-LD_PCREL.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 7f703cf758c4f185dd62f2a4f463002bb514af16 Mon Sep 17 00:00:00 2001 -From: Xi Ruoyao -Date: Sun, 27 Aug 2023 00:36:51 +0800 -Subject: [PATCH 13/29] LoongArch: Micro-optimize LD_PCREL - -We are requiring Binutils >= 2.41, so explicit relocation syntax is -always supported by the assembler. Use it to reduce one instruction. - -Signed-off-by: Xi Ruoyao -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/unix/sysv/linux/loongarch/pointer_guard.h | 10 ++++------ - 1 file changed, 4 insertions(+), 6 deletions(-) - -diff --git a/sysdeps/unix/sysv/linux/loongarch/pointer_guard.h b/sysdeps/unix/sysv/linux/loongarch/pointer_guard.h -index b25e353b..d6c78687 100644 ---- a/sysdeps/unix/sysv/linux/loongarch/pointer_guard.h -+++ b/sysdeps/unix/sysv/linux/loongarch/pointer_guard.h -@@ -19,17 +19,15 @@ - #ifndef POINTER_GUARD_H - #define POINTER_GUARD_H - --/* Load a got-relative EXPR into G, using T. -- Note G and T are register names. */ -+/* Load a got-relative EXPR into register G. */ - #define LD_GLOBAL(G, EXPR) \ - la.global G, EXPR; \ - REG_L G, G, 0; - --/* Load a pc-relative EXPR into G, using T. -- Note G and T are register names. */ -+/* Load a pc-relative EXPR into register G. */ - #define LD_PCREL(G, EXPR) \ -- la.pcrel G, EXPR; \ -- REG_L G, G, 0; -+ pcalau12i G, %pc_hi20(EXPR); \ -+ REG_L G, G, %pc_lo12(EXPR); - - #if (IS_IN (rtld) \ - || (!defined SHARED && (IS_IN (libc) \ --- -2.33.0 - diff --git a/LoongArch-Redefine-macro-LEAF-ENTRY.patch b/LoongArch-Redefine-macro-LEAF-ENTRY.patch deleted file mode 100644 index 414ba83..0000000 --- a/LoongArch-Redefine-macro-LEAF-ENTRY.patch +++ /dev/null @@ -1,65 +0,0 @@ -From 8dcd8c837df2e3cf81675522487697522f1542f8 Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Tue, 8 Aug 2023 14:15:42 +0800 -Subject: [PATCH 01/29] LoongArch: Redefine macro LEAF/ENTRY. - -The following usage of macro LEAF/ENTRY are all feasible: -1. LEAF(fcn) -- the align value of fcn is .align 3(default value) -2. LEAF(fcn, 6) -- the align value of fcn is .align 6 - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/sys/asm.h | 36 ++++++++++++++++++++++++++---------- - 1 file changed, 26 insertions(+), 10 deletions(-) - -diff --git a/sysdeps/loongarch/sys/asm.h b/sysdeps/loongarch/sys/asm.h -index d1a279b8..c5eb8afa 100644 ---- a/sysdeps/loongarch/sys/asm.h -+++ b/sysdeps/loongarch/sys/asm.h -@@ -39,16 +39,32 @@ - #define FREG_L fld.d - #define FREG_S fst.d - --/* Declare leaf routine. */ --#define LEAF(symbol) \ -- .text; \ -- .globl symbol; \ -- .align 3; \ -- cfi_startproc; \ -- .type symbol, @function; \ -- symbol: -- --#define ENTRY(symbol) LEAF (symbol) -+/* Declare leaf routine. -+ The usage of macro LEAF/ENTRY is as follows: -+ 1. LEAF(fcn) -- the align value of fcn is .align 3 (default value) -+ 2. LEAF(fcn, 6) -- the align value of fcn is .align 6 -+*/ -+#define LEAF_IMPL(symbol, aln, ...) \ -+ .text; \ -+ .globl symbol; \ -+ .align aln; \ -+ .type symbol, @function; \ -+symbol: \ -+ cfi_startproc; -+ -+ -+#define LEAF(...) LEAF_IMPL(__VA_ARGS__, 3) -+#define ENTRY(...) LEAF(__VA_ARGS__) -+ -+#define LEAF_NO_ALIGN(symbol) \ -+ .text; \ -+ .globl symbol; \ -+ .type symbol, @function; \ -+symbol: \ -+ cfi_startproc; -+ -+#define ENTRY_NO_ALIGN(symbol) LEAF_NO_ALIGN(symbol) -+ - - /* Mark end of function. */ - #undef END --- -2.33.0 - diff --git a/LoongArch-Remove-support-code-for-old-linker-in-star.patch b/LoongArch-Remove-support-code-for-old-linker-in-star.patch deleted file mode 100644 index 3d688da..0000000 --- a/LoongArch-Remove-support-code-for-old-linker-in-star.patch +++ /dev/null @@ -1,56 +0,0 @@ -From f8d66a269cb6f1a7087afadf3375bdf0553abf53 Mon Sep 17 00:00:00 2001 -From: Xi Ruoyao -Date: Sun, 27 Aug 2023 00:36:50 +0800 -Subject: [PATCH 12/29] LoongArch: Remove support code for old linker in - start.S - -We are requiring Binutils >= 2.41, so la.pcrel always works here. - -Signed-off-by: Xi Ruoyao -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/start.S | 19 +++---------------- - 1 file changed, 3 insertions(+), 16 deletions(-) - -diff --git a/sysdeps/loongarch/start.S b/sysdeps/loongarch/start.S -index e9d82033..bf6bfc9e 100644 ---- a/sysdeps/loongarch/start.S -+++ b/sysdeps/loongarch/start.S -@@ -60,20 +60,7 @@ ENTRY (ENTRY_POINT) - cfi_undefined (1) - or a5, a0, zero /* rtld_fini */ - --#if ENABLE_STATIC_PIE --/* For static PIE, the GOT cannot be used in _start because the GOT entries are -- offsets instead of real addresses before __libc_start_main. -- __libc_start_main and/or main may be not local, so we rely on the linker to -- produce PLT entries for them. GNU ld >= 2.40 supports this. */ --# define LA la.pcrel --#else --/* Old GNU ld (< 2.40) cannot handle PC relative address against a non-local -- function correctly. We deem these old linkers failing to support static PIE -- and load the addresses from GOT. */ --# define LA la.got --#endif -- -- LA a0, t0, main -+ la.pcrel a0, t0, main - REG_L a1, sp, 0 - ADDI a2, sp, SZREG - -@@ -84,9 +71,9 @@ ENTRY (ENTRY_POINT) - move a4, zero /* used to be fini */ - or a6, sp, zero /* stack_end */ - -- LA ra, t0, __libc_start_main -+ la.pcrel ra, t0, __libc_start_main - jirl ra, ra, 0 - -- LA ra, t0, abort -+ la.pcrel ra, t0, abort - jirl ra, ra, 0 - END (ENTRY_POINT) --- -2.33.0 - diff --git a/LoongArch-Replace-deprecated-v0-with-a0-to-eliminate.patch b/LoongArch-Replace-deprecated-v0-with-a0-to-eliminate.patch deleted file mode 100644 index 82ae1be..0000000 --- a/LoongArch-Replace-deprecated-v0-with-a0-to-eliminate.patch +++ /dev/null @@ -1,28 +0,0 @@ -From b4b4bb7c9220a0bbdf5aec0ac8c1de1d22329280 Mon Sep 17 00:00:00 2001 -From: caiyinyu -Date: Thu, 14 Sep 2023 19:48:24 +0800 -Subject: [PATCH 21/29] LoongArch: Replace deprecated $v0 with $a0 to eliminate - 'as' Warnings. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/dl-machine.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h -index 8a2db9de..57913cef 100644 ---- a/sysdeps/loongarch/dl-machine.h -+++ b/sysdeps/loongarch/dl-machine.h -@@ -90,7 +90,7 @@ static inline ElfW (Addr) elf_machine_dynamic (void) - or $a0, $sp, $zero \n\ - bl _dl_start \n\ - # Stash user entry point in s0. \n\ -- or $s0, $v0, $zero \n\ -+ or $s0, $a0, $zero \n\ - # Load the original argument count. \n\ - ld.d $a1, $sp, 0 \n\ - # Call _dl_init (struct link_map *main_map, int argc, \ --- -2.33.0 - diff --git a/LoongArch-Unify-Register-Names.patch b/LoongArch-Unify-Register-Names.patch deleted file mode 100644 index 9473b78..0000000 --- a/LoongArch-Unify-Register-Names.patch +++ /dev/null @@ -1,81 +0,0 @@ -From 458ab6d5f39cca1cabd83abd2022f67491f6f5ed Mon Sep 17 00:00:00 2001 -From: caiyinyu -Date: Fri, 20 Oct 2023 09:20:02 +0800 -Subject: [PATCH 27/29] LoongArch: Unify Register Names. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/__longjmp.S | 20 ++++++++++---------- - sysdeps/loongarch/setjmp.S | 18 +++++++++--------- - 2 files changed, 19 insertions(+), 19 deletions(-) - -diff --git a/sysdeps/loongarch/__longjmp.S b/sysdeps/loongarch/__longjmp.S -index cbde1946..e87ce311 100644 ---- a/sysdeps/loongarch/__longjmp.S -+++ b/sysdeps/loongarch/__longjmp.S -@@ -43,18 +43,18 @@ ENTRY (__longjmp) - REG_L s8, a0, 12*SZREG - - #ifndef __loongarch_soft_float -- FREG_L $f24, a0, 13*SZREG + 0*SZFREG -- FREG_L $f25, a0, 13*SZREG + 1*SZFREG -- FREG_L $f26, a0, 13*SZREG + 2*SZFREG -- FREG_L $f27, a0, 13*SZREG + 3*SZFREG -- FREG_L $f28, a0, 13*SZREG + 4*SZFREG -- FREG_L $f29, a0, 13*SZREG + 5*SZFREG -- FREG_L $f30, a0, 13*SZREG + 6*SZFREG -- FREG_L $f31, a0, 13*SZREG + 7*SZFREG -+ FREG_L fs0, a0, 13*SZREG + 0*SZFREG -+ FREG_L fs1, a0, 13*SZREG + 1*SZFREG -+ FREG_L fs2, a0, 13*SZREG + 2*SZFREG -+ FREG_L fs3, a0, 13*SZREG + 3*SZFREG -+ FREG_L fs4, a0, 13*SZREG + 4*SZFREG -+ FREG_L fs5, a0, 13*SZREG + 5*SZFREG -+ FREG_L fs6, a0, 13*SZREG + 6*SZFREG -+ FREG_L fs7, a0, 13*SZREG + 7*SZFREG - #endif - -- sltui a0,a1,1 -+ sltui a0, a1, 1 - ADD a0, a0, a1 # a0 = (a1 == 0) ? 1 : a1 -- jirl zero,ra,0 -+ jirl zero, ra, 0 - - END (__longjmp) -diff --git a/sysdeps/loongarch/setjmp.S b/sysdeps/loongarch/setjmp.S -index 6c7065cd..b6e4f727 100644 ---- a/sysdeps/loongarch/setjmp.S -+++ b/sysdeps/loongarch/setjmp.S -@@ -52,19 +52,19 @@ ENTRY (__sigsetjmp) - REG_S s8, a0, 12*SZREG - - #ifndef __loongarch_soft_float -- FREG_S $f24, a0, 13*SZREG + 0*SZFREG -- FREG_S $f25, a0, 13*SZREG + 1*SZFREG -- FREG_S $f26, a0, 13*SZREG + 2*SZFREG -- FREG_S $f27, a0, 13*SZREG + 3*SZFREG -- FREG_S $f28, a0, 13*SZREG + 4*SZFREG -- FREG_S $f29, a0, 13*SZREG + 5*SZFREG -- FREG_S $f30, a0, 13*SZREG + 6*SZFREG -- FREG_S $f31, a0, 13*SZREG + 7*SZFREG -+ FREG_S fs0, a0, 13*SZREG + 0*SZFREG -+ FREG_S fs1, a0, 13*SZREG + 1*SZFREG -+ FREG_S fs2, a0, 13*SZREG + 2*SZFREG -+ FREG_S fs3, a0, 13*SZREG + 3*SZFREG -+ FREG_S fs4, a0, 13*SZREG + 4*SZFREG -+ FREG_S fs5, a0, 13*SZREG + 5*SZFREG -+ FREG_S fs6, a0, 13*SZREG + 6*SZFREG -+ FREG_S fs7, a0, 13*SZREG + 7*SZFREG - #endif - - #if !IS_IN (libc) && IS_IN(rtld) - li.w v0, 0 -- jirl zero,ra,0 -+ jirl zero, ra, 0 - #else - b __sigjmp_save - #endif --- -2.33.0 - diff --git a/LoongArch-Update-hwcap.h-to-sync-with-LoongArch-kern.patch b/LoongArch-Update-hwcap.h-to-sync-with-LoongArch-kern.patch deleted file mode 100644 index 27ee625..0000000 --- a/LoongArch-Update-hwcap.h-to-sync-with-LoongArch-kern.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 4828d1aa0028e819a5fb336d962e8f7cbfedf8b4 Mon Sep 17 00:00:00 2001 -From: caiyinyu -Date: Mon, 23 Oct 2023 15:53:38 +0800 -Subject: [PATCH 28/29] LoongArch: Update hwcap.h to sync with LoongArch - kernel. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/unix/sysv/linux/loongarch/bits/hwcap.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/hwcap.h b/sysdeps/unix/sysv/linux/loongarch/bits/hwcap.h -index 5104b69c..7acec23d 100644 ---- a/sysdeps/unix/sysv/linux/loongarch/bits/hwcap.h -+++ b/sysdeps/unix/sysv/linux/loongarch/bits/hwcap.h -@@ -35,3 +35,4 @@ - #define HWCAP_LOONGARCH_LBT_X86 (1 << 10) - #define HWCAP_LOONGARCH_LBT_ARM (1 << 11) - #define HWCAP_LOONGARCH_LBT_MIPS (1 << 12) -+#define HWCAP_LOONGARCH_PTW (1 << 13) --- -2.33.0 - diff --git a/LoongArch-elf-Add-new-LoongArch-reloc-types-109-into.patch b/LoongArch-elf-Add-new-LoongArch-reloc-types-109-into.patch deleted file mode 100644 index b9b6f0d..0000000 --- a/LoongArch-elf-Add-new-LoongArch-reloc-types-109-into.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 4938840b15ff9734fdcc63cc0744ce3f3bbb0b16 Mon Sep 17 00:00:00 2001 -From: caiyinyu -Date: Mon, 14 Aug 2023 15:34:08 +0800 -Subject: [PATCH 05/29] LoongArch: elf: Add new LoongArch reloc types 109 into - elf.h - -These reloc types are generated by GNU assembler >= 2.41 for relaxation -support. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - elf/elf.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/elf/elf.h b/elf/elf.h -index d623bdeb..9c51073f 100644 ---- a/elf/elf.h -+++ b/elf/elf.h -@@ -4213,6 +4213,7 @@ enum - #define R_LARCH_SUB6 106 - #define R_LARCH_ADD_ULEB128 107 - #define R_LARCH_SUB_ULEB128 108 -+#define R_LARCH_64_PCREL 109 - - /* ARC specific declarations. */ - --- -2.33.0 - diff --git a/Loongarch-Add-ifunc-support-and-add-different-versio.patch b/Loongarch-Add-ifunc-support-and-add-different-versio.patch deleted file mode 100644 index aae8ddc..0000000 --- a/Loongarch-Add-ifunc-support-and-add-different-versio.patch +++ /dev/null @@ -1,528 +0,0 @@ -From 43abd8772a143cd96688c081500397dd712e631b Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Tue, 8 Aug 2023 14:15:44 +0800 -Subject: [PATCH 03/29] Loongarch: Add ifunc support and add different versions - of strlen - -strlen-lasx is implemeted by LASX simd instructions(256bit) -strlen-lsx is implemeted by LSX simd instructions(128bit) -strlen-align is implemented by LA basic instructions and never use unaligned memory acess - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/Makefile | 7 ++ - .../lp64/multiarch/ifunc-impl-list.c | 41 +++++++ - .../loongarch/lp64/multiarch/ifunc-strlen.h | 40 +++++++ - .../loongarch/lp64/multiarch/strlen-aligned.S | 100 ++++++++++++++++++ - .../loongarch/lp64/multiarch/strlen-lasx.S | 63 +++++++++++ - sysdeps/loongarch/lp64/multiarch/strlen-lsx.S | 71 +++++++++++++ - sysdeps/loongarch/lp64/multiarch/strlen.c | 37 +++++++ - sysdeps/loongarch/sys/regdef.h | 57 ++++++++++ - .../unix/sysv/linux/loongarch/cpu-features.h | 2 + - 9 files changed, 418 insertions(+) - create mode 100644 sysdeps/loongarch/lp64/multiarch/Makefile - create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c - create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-strlen.h - create mode 100644 sysdeps/loongarch/lp64/multiarch/strlen-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strlen-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strlen-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strlen.c - -diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile -new file mode 100644 -index 00000000..76c506c9 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/Makefile -@@ -0,0 +1,7 @@ -+ifeq ($(subdir),string) -+sysdep_routines += \ -+ strlen-aligned \ -+ strlen-lsx \ -+ strlen-lasx \ -+# sysdep_routines -+endif -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -new file mode 100644 -index 00000000..1a2a576f ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -@@ -0,0 +1,41 @@ -+/* Enumerate available IFUNC implementations of a function LoongArch64 version. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+size_t -+__libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, -+ size_t max) -+{ -+ -+ size_t i = max; -+ -+ IFUNC_IMPL (i, name, strlen, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, strlen, SUPPORT_LASX, __strlen_lasx) -+ IFUNC_IMPL_ADD (array, i, strlen, SUPPORT_LSX, __strlen_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, strlen, 1, __strlen_aligned) -+ ) -+ return i; -+} -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-strlen.h b/sysdeps/loongarch/lp64/multiarch/ifunc-strlen.h -new file mode 100644 -index 00000000..6258bb76 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-strlen.h -@@ -0,0 +1,40 @@ -+/* Common definition for strlen ifunc selections. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+ -+#if !defined __loongarch_soft_float -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden; -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden; -+#endif -+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden; -+ -+static inline void * -+IFUNC_SELECTOR (void) -+{ -+#if !defined __loongarch_soft_float -+ if (SUPPORT_LASX) -+ return OPTIMIZE (lasx); -+ else if (SUPPORT_LSX) -+ return OPTIMIZE (lsx); -+ else -+#endif -+ return OPTIMIZE (aligned); -+} -diff --git a/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S b/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S -new file mode 100644 -index 00000000..e9e1d2fc ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S -@@ -0,0 +1,100 @@ -+/* Optimized strlen implementation using basic Loongarch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+# define STRLEN __strlen_aligned -+#else -+# define STRLEN strlen -+#endif -+ -+LEAF(STRLEN, 6) -+ move a1, a0 -+ bstrins.d a0, zero, 2, 0 -+ lu12i.w a2, 0x01010 -+ li.w t0, -1 -+ -+ ld.d t2, a0, 0 -+ andi t1, a1, 0x7 -+ ori a2, a2, 0x101 -+ slli.d t1, t1, 3 -+ -+ bstrins.d a2, a2, 63, 32 -+ sll.d t1, t0, t1 -+ slli.d t3, a2, 7 -+ nor a3, zero, t3 -+ -+ orn t2, t2, t1 -+ sub.d t0, t2, a2 -+ nor t1, t2, a3 -+ and t0, t0, t1 -+ -+ -+ bnez t0, L(count_pos) -+ addi.d a0, a0, 8 -+L(loop_16_7bit): -+ ld.d t2, a0, 0 -+ sub.d t1, t2, a2 -+ -+ and t0, t1, t3 -+ bnez t0, L(more_check) -+ ld.d t2, a0, 8 -+ sub.d t1, t2, a2 -+ -+ and t0, t1, t3 -+ addi.d a0, a0, 16 -+ beqz t0, L(loop_16_7bit) -+ addi.d a0, a0, -8 -+ -+L(more_check): -+ nor t0, t2, a3 -+ and t0, t1, t0 -+ bnez t0, L(count_pos) -+ addi.d a0, a0, 8 -+ -+ -+L(loop_16_8bit): -+ ld.d t2, a0, 0 -+ sub.d t1, t2, a2 -+ nor t0, t2, a3 -+ and t0, t0, t1 -+ -+ bnez t0, L(count_pos) -+ ld.d t2, a0, 8 -+ addi.d a0, a0, 16 -+ sub.d t1, t2, a2 -+ -+ nor t0, t2, a3 -+ and t0, t0, t1 -+ beqz t0, L(loop_16_8bit) -+ addi.d a0, a0, -8 -+ -+L(count_pos): -+ ctz.d t1, t0 -+ sub.d a0, a0, a1 -+ srli.d t1, t1, 3 -+ add.d a0, a0, t1 -+ -+ jr ra -+END(STRLEN) -+ -+libc_hidden_builtin_def (STRLEN) -diff --git a/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S b/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S -new file mode 100644 -index 00000000..258c47ce ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S -@@ -0,0 +1,63 @@ -+/* Optimized strlen implementation using loongarch LASX SIMD instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define STRLEN __strlen_lasx -+ -+LEAF(STRLEN, 6) -+ move a1, a0 -+ bstrins.d a0, zero, 4, 0 -+ li.d t1, -1 -+ xvld xr0, a0, 0 -+ -+ xvmsknz.b xr0, xr0 -+ xvpickve.w xr1, xr0, 4 -+ vilvl.h vr0, vr1, vr0 -+ movfr2gr.s t0, fa0 # sign extend -+ -+ sra.w t0, t0, a1 -+ beq t0, t1, L(loop) -+ cto.w a0, t0 -+ jr ra -+ -+L(loop): -+ xvld xr0, a0, 32 -+ addi.d a0, a0, 32 -+ xvsetanyeqz.b fcc0, xr0 -+ bceqz fcc0, L(loop) -+ -+ -+ xvmsknz.b xr0, xr0 -+ sub.d a0, a0, a1 -+ xvpickve.w xr1, xr0, 4 -+ vilvl.h vr0, vr1, vr0 -+ -+ movfr2gr.s t0, fa0 -+ cto.w t0, t0 -+ add.d a0, a0, t0 -+ jr ra -+END(STRLEN) -+ -+libc_hidden_builtin_def (STRLEN) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S b/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S -new file mode 100644 -index 00000000..b194355e ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S -@@ -0,0 +1,71 @@ -+/* Optimized strlen implementation using Loongarch LSX SIMD instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define STRLEN __strlen_lsx -+ -+LEAF(STRLEN, 6) -+ move a1, a0 -+ bstrins.d a0, zero, 4, 0 -+ vld vr0, a0, 0 -+ vld vr1, a0, 16 -+ -+ li.d t1, -1 -+ vmsknz.b vr0, vr0 -+ vmsknz.b vr1, vr1 -+ vilvl.h vr0, vr1, vr0 -+ -+ movfr2gr.s t0, fa0 -+ sra.w t0, t0, a1 -+ beq t0, t1, L(loop) -+ cto.w a0, t0 -+ -+ jr ra -+ nop -+ nop -+ nop -+ -+ -+L(loop): -+ vld vr0, a0, 32 -+ vld vr1, a0, 48 -+ addi.d a0, a0, 32 -+ vmin.bu vr2, vr0, vr1 -+ -+ vsetanyeqz.b fcc0, vr2 -+ bceqz fcc0, L(loop) -+ vmsknz.b vr0, vr0 -+ vmsknz.b vr1, vr1 -+ -+ vilvl.h vr0, vr1, vr0 -+ sub.d a0, a0, a1 -+ movfr2gr.s t0, fa0 -+ cto.w t0, t0 -+ -+ add.d a0, a0, t0 -+ jr ra -+END(STRLEN) -+ -+libc_hidden_builtin_def (STRLEN) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strlen.c b/sysdeps/loongarch/lp64/multiarch/strlen.c -new file mode 100644 -index 00000000..381c2daa ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strlen.c -@@ -0,0 +1,37 @@ -+/* Multiple versions of strlen. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+ -+#if IS_IN (libc) -+# define strlen __redirect_strlen -+# include -+# undef strlen -+ -+# define SYMBOL_NAME strlen -+# include "ifunc-strlen.h" -+ -+libc_ifunc_redirected (__redirect_strlen, strlen, IFUNC_SELECTOR ()); -+ -+# ifdef SHARED -+__hidden_ver1 (strlen, __GI_strlen, __redirect_strlen) -+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strlen); -+# endif -+ -+#endif -diff --git a/sysdeps/loongarch/sys/regdef.h b/sysdeps/loongarch/sys/regdef.h -index 5100f36d..524d2e32 100644 ---- a/sysdeps/loongarch/sys/regdef.h -+++ b/sysdeps/loongarch/sys/regdef.h -@@ -89,6 +89,14 @@ - #define fs5 $f29 - #define fs6 $f30 - #define fs7 $f31 -+#define fcc0 $fcc0 -+#define fcc1 $fcc1 -+#define fcc2 $fcc2 -+#define fcc3 $fcc3 -+#define fcc4 $fcc4 -+#define fcc5 $fcc5 -+#define fcc6 $fcc6 -+#define fcc7 $fcc7 - - #define vr0 $vr0 - #define vr1 $vr1 -@@ -98,6 +106,30 @@ - #define vr5 $vr5 - #define vr6 $vr6 - #define vr7 $vr7 -+#define vr8 $vr8 -+#define vr9 $vr9 -+#define vr10 $vr10 -+#define vr11 $vr11 -+#define vr12 $vr12 -+#define vr13 $vr13 -+#define vr14 $vr14 -+#define vr15 $vr15 -+#define vr16 $vr16 -+#define vr17 $vr17 -+#define vr18 $vr18 -+#define vr19 $vr19 -+#define vr20 $vr20 -+#define vr21 $vr21 -+#define vr22 $vr22 -+#define vr23 $vr23 -+#define vr24 $vr24 -+#define vr25 $vr25 -+#define vr26 $vr26 -+#define vr27 $vr27 -+#define vr28 $vr28 -+#define vr29 $vr29 -+#define vr30 $vr30 -+#define vr31 $vr31 - - #define xr0 $xr0 - #define xr1 $xr1 -@@ -107,5 +139,30 @@ - #define xr5 $xr5 - #define xr6 $xr6 - #define xr7 $xr7 -+#define xr7 $xr7 -+#define xr8 $xr8 -+#define xr9 $xr9 -+#define xr10 $xr10 -+#define xr11 $xr11 -+#define xr12 $xr12 -+#define xr13 $xr13 -+#define xr14 $xr14 -+#define xr15 $xr15 -+#define xr16 $xr16 -+#define xr17 $xr17 -+#define xr18 $xr18 -+#define xr19 $xr19 -+#define xr20 $xr20 -+#define xr21 $xr21 -+#define xr22 $xr22 -+#define xr23 $xr23 -+#define xr24 $xr24 -+#define xr25 $xr25 -+#define xr26 $xr26 -+#define xr27 $xr27 -+#define xr28 $xr28 -+#define xr29 $xr29 -+#define xr30 $xr30 -+#define xr31 $xr31 - - #endif /* _SYS_REGDEF_H */ -diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h -index e371e13b..d1a280a5 100644 ---- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h -+++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h -@@ -25,5 +25,7 @@ - #define SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX) - #define SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX) - -+#define INIT_ARCH() -+ - #endif /* _CPU_FEATURES_LOONGARCH64_H */ - --- -2.33.0 - diff --git a/Loongarch-Add-ifunc-support-for-memcpy-aligned-unali.patch b/Loongarch-Add-ifunc-support-for-memcpy-aligned-unali.patch deleted file mode 100644 index 2bbf367..0000000 --- a/Loongarch-Add-ifunc-support-for-memcpy-aligned-unali.patch +++ /dev/null @@ -1,2570 +0,0 @@ -From 9c522272146423c1ef9fb9e071737a8ad26e844e Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Tue, 15 Aug 2023 09:11:53 +0800 -Subject: [PATCH 07/29] Loongarch: Add ifunc support for memcpy{aligned, - unaligned, lsx, lasx} and memmove{aligned, unaligned, lsx, lasx} - -These implementations improve the time to copy data in the glibc -microbenchmark as below: -memcpy-lasx reduces the runtime about 8%-76% -memcpy-lsx reduces the runtime about 8%-72% -memcpy-unaligned reduces the runtime of unaligned data copying up to 40% -memcpy-aligned reduece the runtime of unaligned data copying up to 25% -memmove-lasx reduces the runtime about 20%-73% -memmove-lsx reduces the runtime about 50% -memmove-unaligned reduces the runtime of unaligned data moving up to 40% -memmove-aligned reduces the runtime of unaligned data moving up to 25% - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/Makefile | 5 + - .../lp64/multiarch/ifunc-impl-list.c | 19 + - sysdeps/loongarch/lp64/multiarch/ifunc-lasx.h | 45 + - .../loongarch/lp64/multiarch/memcpy-aligned.S | 783 ++++++++++++++++++ - .../loongarch/lp64/multiarch/memcpy-lasx.S | 20 + - sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S | 20 + - .../lp64/multiarch/memcpy-unaligned.S | 247 ++++++ - sysdeps/loongarch/lp64/multiarch/memcpy.c | 37 + - .../lp64/multiarch/memmove-aligned.S | 20 + - .../loongarch/lp64/multiarch/memmove-lasx.S | 287 +++++++ - .../loongarch/lp64/multiarch/memmove-lsx.S | 534 ++++++++++++ - .../lp64/multiarch/memmove-unaligned.S | 380 +++++++++ - sysdeps/loongarch/lp64/multiarch/memmove.c | 38 + - 13 files changed, 2435 insertions(+) - create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-lasx.h - create mode 100644 sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memcpy.c - create mode 100644 sysdeps/loongarch/lp64/multiarch/memmove-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memmove-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memmove-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/memmove.c - -diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile -index 110a8c5c..afa51041 100644 ---- a/sysdeps/loongarch/lp64/multiarch/Makefile -+++ b/sysdeps/loongarch/lp64/multiarch/Makefile -@@ -9,5 +9,10 @@ sysdep_routines += \ - strchrnul-aligned \ - strchrnul-lsx \ - strchrnul-lasx \ -+ memcpy-aligned \ -+ memcpy-unaligned \ -+ memmove-unaligned \ -+ memmove-lsx \ -+ memmove-lasx \ - # sysdep_routines - endif -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -index c7164b45..25eb96b0 100644 ---- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -@@ -53,5 +53,24 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, - #endif - IFUNC_IMPL_ADD (array, i, strchrnul, 1, __strchrnul_aligned) - ) -+ -+ IFUNC_IMPL (i, name, memcpy, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, memcpy, SUPPORT_LASX, __memcpy_lasx) -+ IFUNC_IMPL_ADD (array, i, memcpy, SUPPORT_LSX, __memcpy_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, memcpy, SUPPORT_UAL, __memcpy_unaligned) -+ IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_aligned) -+ ) -+ -+ IFUNC_IMPL (i, name, memmove, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, memmove, SUPPORT_LASX, __memmove_lasx) -+ IFUNC_IMPL_ADD (array, i, memmove, SUPPORT_LSX, __memmove_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, memmove, SUPPORT_UAL, __memmove_unaligned) -+ IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_aligned) -+ ) -+ - return i; - } -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-lasx.h b/sysdeps/loongarch/lp64/multiarch/ifunc-lasx.h -new file mode 100644 -index 00000000..3be67da6 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-lasx.h -@@ -0,0 +1,45 @@ -+/* Common definition for ifunc selection implementation. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+ -+#if !defined __loongarch_soft_float -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden; -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden; -+#endif -+ -+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden; -+extern __typeof (REDIRECT_NAME) OPTIMIZE (unaligned) attribute_hidden; -+ -+static inline void * -+IFUNC_SELECTOR (void) -+{ -+#if !defined __loongarch_soft_float -+ if (SUPPORT_LASX) -+ return OPTIMIZE (lasx); -+ else if (SUPPORT_LSX) -+ return OPTIMIZE (lsx); -+ else -+#endif -+ if (SUPPORT_UAL) -+ return OPTIMIZE (unaligned); -+ else -+ return OPTIMIZE (aligned); -+} -diff --git a/sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S b/sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S -new file mode 100644 -index 00000000..299dd49c ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S -@@ -0,0 +1,783 @@ -+/* Optimized memcpy_aligned implementation using basic Loongarch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+# define MEMCPY_NAME __memcpy_aligned -+# define MEMMOVE_NAME __memmove_aligned -+#else -+# define MEMCPY_NAME memcpy -+# define MEMMOVE_NAME memmove -+#endif -+ -+#define LD_64(reg, n) \ -+ ld.d t0, reg, n; \ -+ ld.d t1, reg, n + 8; \ -+ ld.d t2, reg, n + 16; \ -+ ld.d t3, reg, n + 24; \ -+ ld.d t4, reg, n + 32; \ -+ ld.d t5, reg, n + 40; \ -+ ld.d t6, reg, n + 48; \ -+ ld.d t7, reg, n + 56; -+ -+#define ST_64(reg, n) \ -+ st.d t0, reg, n; \ -+ st.d t1, reg, n + 8; \ -+ st.d t2, reg, n + 16; \ -+ st.d t3, reg, n + 24; \ -+ st.d t4, reg, n + 32; \ -+ st.d t5, reg, n + 40; \ -+ st.d t6, reg, n + 48; \ -+ st.d t7, reg, n + 56; -+ -+LEAF(MEMMOVE_NAME, 6) -+ sub.d t0, a0, a1 -+ bltu t0, a2, L(copy_back) -+END(MEMMOVE_NAME) -+ -+LEAF_NO_ALIGN(MEMCPY_NAME) -+ srai.d a3, a2, 4 -+ beqz a3, L(short_data) -+ -+ move a4, a0 -+ andi a5, a0, 0x7 -+ andi a6, a1, 0x7 -+ li.d t8, 8 -+ beqz a5, L(check_align) -+ -+ sub.d t2, t8, a5 -+ sub.d a2, a2, t2 -+ pcaddi t1, 20 -+ slli.d t3, t2, 3 -+ -+ add.d a1, a1, t2 -+ sub.d t1, t1, t3 -+ add.d a4, a4, t2 -+ jr t1 -+ -+L(al7): -+ ld.b t0, a1, -7 -+ st.b t0, a4, -7 -+L(al6): -+ ld.b t0, a1, -6 -+ st.b t0, a4, -6 -+L(al5): -+ ld.b t0, a1, -5 -+ st.b t0, a4, -5 -+L(al4): -+ ld.b t0, a1, -4 -+ st.b t0, a4, -4 -+L(al3): -+ ld.b t0, a1, -3 -+ st.b t0, a4, -3 -+L(al2): -+ ld.b t0, a1, -2 -+ st.b t0, a4, -2 -+L(al1): -+ ld.b t0, a1, -1 -+ st.b t0, a4, -1 -+ -+L(check_align): -+ bne a5, a6, L(unalign) -+ srai.d a3, a2, 4 -+ beqz a3, L(al_less_16bytes) -+ andi a3, a2, 0x3f -+ -+ beq a3, a2, L(al_less_64bytes) -+ sub.d t0, a2, a3 -+ move a2, a3 -+ add.d a5, a1, t0 -+ -+L(loop_64bytes): -+ LD_64(a1, 0) -+ addi.d a1, a1, 64 -+ ST_64(a4, 0) -+ -+ addi.d a4, a4, 64 -+ bne a1, a5, L(loop_64bytes) -+ -+L(al_less_64bytes): -+ srai.d a3, a2, 5 -+ beqz a3, L(al_less_32bytes) -+ -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ ld.d t2, a1, 16 -+ ld.d t3, a1, 24 -+ -+ addi.d a1, a1, 32 -+ addi.d a2, a2, -32 -+ -+ st.d t0, a4, 0 -+ st.d t1, a4, 8 -+ st.d t2, a4, 16 -+ st.d t3, a4, 24 -+ -+ addi.d a4, a4, 32 -+ -+L(al_less_32bytes): -+ srai.d a3, a2, 4 -+ beqz a3, L(al_less_16bytes) -+ -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ addi.d a1, a1, 16 -+ addi.d a2, a2, -16 -+ -+ st.d t0, a4, 0 -+ st.d t1, a4, 8 -+ addi.d a4, a4, 16 -+ -+L(al_less_16bytes): -+ srai.d a3, a2, 3 -+ beqz a3, L(al_less_8bytes) -+ -+ ld.d t0, a1, 0 -+ addi.d a1, a1, 8 -+ addi.d a2, a2, -8 -+ st.d t0, a4, 0 -+ addi.d a4, a4, 8 -+ -+L(al_less_8bytes): -+ srai.d a3, a2, 2 -+ beqz a3, L(al_less_4bytes) -+ -+ ld.w t0, a1, 0 -+ addi.d a1, a1, 4 -+ addi.d a2, a2, -4 -+ st.w t0, a4, 0 -+ addi.d a4, a4, 4 -+ -+L(al_less_4bytes): -+ srai.d a3, a2, 1 -+ beqz a3, L(al_less_2bytes) -+ -+ ld.h t0, a1, 0 -+ addi.d a1, a1, 2 -+ addi.d a2, a2, -2 -+ st.h t0, a4, 0 -+ addi.d a4, a4, 2 -+ -+L(al_less_2bytes): -+ beqz a2, L(al_less_1byte) -+ -+ ld.b t0, a1, 0 -+ st.b t0, a4, 0 -+ -+L(al_less_1byte): -+ jr ra -+ -+L(unalign): -+ andi a5, a1, 0x7 -+ bstrins.d a1, zero, 2, 0 -+ sub.d t8, t8, a5 -+ slli.d a5, a5, 3 -+ -+ ld.d t0, a1, 0 -+ addi.d a1, a1, 8 -+ slli.d a6, t8, 3 -+ srl.d a7, t0, a5 -+ -+ srai.d a3, a2, 4 -+ beqz a3, L(un_less_16bytes) -+ andi a3, a2, 0x3f -+ beq a3, a2, L(un_less_64bytes) -+ -+ sub.d t0, a2, a3 -+ move a2, a3 -+ add.d a3, a1, t0 -+ -+L(un_long_bytes): -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ ld.d t2, a1, 16 -+ ld.d t3, a1, 24 -+ -+ srl.d t4, t0, a5 -+ sll.d t0, t0, a6 -+ srl.d t5, t1, a5 -+ sll.d t1, t1, a6 -+ -+ srl.d t6, t2, a5 -+ sll.d t2, t2, a6 -+ srl.d t7, t3, a5 -+ sll.d t3, t3, a6 -+ -+ or t0, a7, t0 -+ or t1, t4, t1 -+ or t2, t5, t2 -+ or t3, t6, t3 -+ -+ ld.d t4, a1, 32 -+ ld.d t5, a1, 40 -+ ld.d t6, a1, 48 -+ ld.d a7, a1, 56 -+ -+ st.d t0, a4, 0 -+ st.d t1, a4, 8 -+ st.d t2, a4, 16 -+ st.d t3, a4, 24 -+ -+ addi.d a1, a1, 64 -+ -+ srl.d t0, t4, a5 -+ sll.d t4, t4, a6 -+ srl.d t1, t5, a5 -+ sll.d t5, t5, a6 -+ -+ srl.d t2, t6, a5 -+ sll.d t6, t6, a6 -+ sll.d t3, a7, a6 -+ srl.d a7, a7, a5 -+ -+ or t4, t7, t4 -+ or t5, t0, t5 -+ or t6, t1, t6 -+ or t3, t2, t3 -+ -+ st.d t4, a4, 32 -+ st.d t5, a4, 40 -+ st.d t6, a4, 48 -+ st.d t3, a4, 56 -+ -+ addi.d a4, a4, 64 -+ bne a3, a1, L(un_long_bytes) -+ -+L(un_less_64bytes): -+ srai.d a3, a2, 5 -+ beqz a3, L(un_less_32bytes) -+ -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ ld.d t2, a1, 16 -+ ld.d t3, a1, 24 -+ -+ addi.d a1, a1, 32 -+ addi.d a2, a2, -32 -+ -+ srl.d t4, t0, a5 -+ sll.d t0, t0, a6 -+ srl.d t5, t1, a5 -+ sll.d t1, t1, a6 -+ -+ srl.d t6, t2, a5 -+ sll.d t2, t2, a6 -+ or t0, a7, t0 -+ srl.d a7, t3, a5 -+ sll.d t3, t3, a6 -+ -+ or t1, t4, t1 -+ or t2, t5, t2 -+ or t3, t6, t3 -+ -+ st.d t0, a4, 0 -+ st.d t1, a4, 8 -+ st.d t2, a4, 16 -+ st.d t3, a4, 24 -+ -+ addi.d a4, a4, 32 -+ -+L(un_less_32bytes): -+ srai.d a3, a2, 4 -+ beqz a3, L(un_less_16bytes) -+ -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ addi.d a1, a1, 16 -+ addi.d a2, a2, -16 -+ -+ srl.d t2, t0, a5 -+ sll.d t3, t0, a6 -+ sll.d t4, t1, a6 -+ or t3, a7, t3 -+ or t4, t2, t4 -+ -+ srl.d a7, t1, a5 -+ st.d t3, a4, 0 -+ st.d t4, a4, 8 -+ addi.d a4, a4, 16 -+ -+L(un_less_16bytes): -+ srai.d a3, a2, 3 -+ beqz a3, L(un_less_8bytes) -+ -+ ld.d t0, a1, 0 -+ addi.d a1, a1, 8 -+ addi.d a2, a2, -8 -+ sll.d t1, t0, a6 -+ -+ or t2, a7, t1 -+ srl.d a7, t0, a5 -+ st.d t2, a4, 0 -+ addi.d a4, a4, 8 -+ -+L(un_less_8bytes): -+ beqz a2, L(un_less_1byte) -+ bge t8, a2, 1f -+ -+ ld.d t0, a1, 0 -+ sll.d t0, t0, a6 -+ or a7, a7, t0 -+ -+1: -+ srai.d a3, a2, 2 -+ beqz a3, L(un_less_4bytes) -+ -+ addi.d a2, a2, -4 -+ st.w a7, a4, 0 -+ addi.d a4, a4, 4 -+ srai.d a7, a7, 32 -+ -+L(un_less_4bytes): -+ srai.d a3, a2, 1 -+ beqz a3, L(un_less_2bytes) -+ -+ addi.d a2, a2, -2 -+ st.h a7, a4, 0 -+ addi.d a4, a4, 2 -+ srai.d a7, a7, 16 -+ -+L(un_less_2bytes): -+ beqz a2, L(un_less_1byte) -+ st.b a7, a4, 0 -+ -+L(un_less_1byte): -+ jr ra -+ -+L(short_data): -+ pcaddi t1, 36 -+ slli.d t2, a2, 3 -+ add.d a4, a0, a2 -+ sub.d t1, t1, t2 -+ add.d a1, a1, a2 -+ jr t1 -+ -+L(short_15_bytes): -+ ld.b t0, a1, -15 -+ st.b t0, a4, -15 -+L(short_14_bytes): -+ ld.b t0, a1, -14 -+ st.b t0, a4, -14 -+L(short_13_bytes): -+ ld.b t0, a1, -13 -+ st.b t0, a4, -13 -+L(short_12_bytes): -+ ld.b t0, a1, -12 -+ st.b t0, a4, -12 -+L(short_11_bytes): -+ ld.b t0, a1, -11 -+ st.b t0, a4, -11 -+L(short_10_bytes): -+ ld.b t0, a1, -10 -+ st.b t0, a4, -10 -+L(short_9_bytes): -+ ld.b t0, a1, -9 -+ st.b t0, a4, -9 -+L(short_8_bytes): -+ ld.b t0, a1, -8 -+ st.b t0, a4, -8 -+L(short_7_bytes): -+ ld.b t0, a1, -7 -+ st.b t0, a4, -7 -+L(short_6_bytes): -+ ld.b t0, a1, -6 -+ st.b t0, a4, -6 -+L(short_5_bytes): -+ ld.b t0, a1, -5 -+ st.b t0, a4, -5 -+L(short_4_bytes): -+ ld.b t0, a1, -4 -+ st.b t0, a4, -4 -+L(short_3_bytes): -+ ld.b t0, a1, -3 -+ st.b t0, a4, -3 -+L(short_2_bytes): -+ ld.b t0, a1, -2 -+ st.b t0, a4, -2 -+L(short_1_bytes): -+ ld.b t0, a1, -1 -+ st.b t0, a4, -1 -+ jr ra -+ -+L(copy_back): -+ srai.d a3, a2, 4 -+ beqz a3, L(back_short_data) -+ -+ add.d a4, a0, a2 -+ add.d a1, a1, a2 -+ -+ andi a5, a4, 0x7 -+ andi a6, a1, 0x7 -+ beqz a5, L(back_check_align) -+ -+ sub.d a2, a2, a5 -+ sub.d a1, a1, a5 -+ sub.d a4, a4, a5 -+ -+ pcaddi t1, 18 -+ slli.d t3, a5, 3 -+ sub.d t1, t1, t3 -+ jr t1 -+ -+ ld.b t0, a1, 6 -+ st.b t0, a4, 6 -+ ld.b t0, a1, 5 -+ st.b t0, a4, 5 -+ ld.b t0, a1, 4 -+ st.b t0, a4, 4 -+ ld.b t0, a1, 3 -+ st.b t0, a4, 3 -+ ld.b t0, a1, 2 -+ st.b t0, a4, 2 -+ ld.b t0, a1, 1 -+ st.b t0, a4, 1 -+ ld.b t0, a1, 0 -+ st.b t0, a4, 0 -+ -+L(back_check_align): -+ bne a5, a6, L(back_unalign) -+ -+ srai.d a3, a2, 4 -+ beqz a3, L(back_less_16bytes) -+ -+ andi a3, a2, 0x3f -+ beq a3, a2, L(back_less_64bytes) -+ -+ sub.d t0, a2, a3 -+ move a2, a3 -+ sub.d a5, a1, t0 -+ -+L(back_loop_64bytes): -+ LD_64(a1, -64) -+ addi.d a1, a1, -64 -+ ST_64(a4, -64) -+ -+ addi.d a4, a4, -64 -+ bne a1, a5, L(back_loop_64bytes) -+ -+L(back_less_64bytes): -+ srai.d a3, a2, 5 -+ beqz a3, L(back_less_32bytes) -+ -+ ld.d t0, a1, -32 -+ ld.d t1, a1, -24 -+ ld.d t2, a1, -16 -+ ld.d t3, a1, -8 -+ -+ addi.d a1, a1, -32 -+ addi.d a2, a2, -32 -+ -+ st.d t0, a4, -32 -+ st.d t1, a4, -24 -+ st.d t2, a4, -16 -+ st.d t3, a4, -8 -+ -+ addi.d a4, a4, -32 -+ -+L(back_less_32bytes): -+ srai.d a3, a2, 4 -+ beqz a3, L(back_less_16bytes) -+ -+ ld.d t0, a1, -16 -+ ld.d t1, a1, -8 -+ -+ addi.d a2, a2, -16 -+ addi.d a1, a1, -16 -+ -+ st.d t0, a4, -16 -+ st.d t1, a4, -8 -+ addi.d a4, a4, -16 -+ -+L(back_less_16bytes): -+ srai.d a3, a2, 3 -+ beqz a3, L(back_less_8bytes) -+ -+ ld.d t0, a1, -8 -+ addi.d a2, a2, -8 -+ addi.d a1, a1, -8 -+ -+ st.d t0, a4, -8 -+ addi.d a4, a4, -8 -+ -+L(back_less_8bytes): -+ srai.d a3, a2, 2 -+ beqz a3, L(back_less_4bytes) -+ -+ ld.w t0, a1, -4 -+ addi.d a2, a2, -4 -+ addi.d a1, a1, -4 -+ -+ st.w t0, a4, -4 -+ addi.d a4, a4, -4 -+ -+L(back_less_4bytes): -+ srai.d a3, a2, 1 -+ beqz a3, L(back_less_2bytes) -+ -+ ld.h t0, a1, -2 -+ addi.d a2, a2, -2 -+ addi.d a1, a1, -2 -+ -+ st.h t0, a4, -2 -+ addi.d a4, a4, -2 -+ -+L(back_less_2bytes): -+ beqz a2, L(back_less_1byte) -+ -+ ld.b t0, a1, -1 -+ st.b t0, a4, -1 -+ -+L(back_less_1byte): -+ jr ra -+ -+L(back_unalign): -+ andi t8, a1, 0x7 -+ bstrins.d a1, zero, 2, 0 -+ -+ sub.d a6, zero, t8 -+ -+ ld.d t0, a1, 0 -+ slli.d a6, a6, 3 -+ slli.d a5, t8, 3 -+ sll.d a7, t0, a6 -+ -+ srai.d a3, a2, 4 -+ beqz a3, L(back_un_less_16bytes) -+ -+ andi a3, a2, 0x3f -+ beq a3, a2, L(back_un_less_64bytes) -+ -+ sub.d t0, a2, a3 -+ move a2, a3 -+ sub.d a3, a1, t0 -+ -+L(back_un_long_bytes): -+ ld.d t0, a1, -8 -+ ld.d t1, a1, -16 -+ ld.d t2, a1, -24 -+ ld.d t3, a1, -32 -+ -+ sll.d t4, t0, a6 -+ srl.d t0, t0, a5 -+ -+ sll.d t5, t1, a6 -+ srl.d t1, t1, a5 -+ -+ sll.d t6, t2, a6 -+ srl.d t2, t2, a5 -+ -+ sll.d t7, t3, a6 -+ srl.d t3, t3, a5 -+ -+ or t0, t0, a7 -+ or t1, t1, t4 -+ or t2, t2, t5 -+ or t3, t3, t6 -+ -+ ld.d t4, a1, -40 -+ ld.d t5, a1, -48 -+ ld.d t6, a1, -56 -+ ld.d a7, a1, -64 -+ st.d t0, a4, -8 -+ st.d t1, a4, -16 -+ st.d t2, a4, -24 -+ st.d t3, a4, -32 -+ -+ addi.d a1, a1, -64 -+ -+ sll.d t0, t4, a6 -+ srl.d t4, t4, a5 -+ -+ sll.d t1, t5, a6 -+ srl.d t5, t5, a5 -+ -+ sll.d t2, t6, a6 -+ srl.d t6, t6, a5 -+ -+ srl.d t3, a7, a5 -+ sll.d a7, a7, a6 -+ -+ or t4, t7, t4 -+ or t5, t0, t5 -+ or t6, t1, t6 -+ or t3, t2, t3 -+ -+ st.d t4, a4, -40 -+ st.d t5, a4, -48 -+ st.d t6, a4, -56 -+ st.d t3, a4, -64 -+ -+ addi.d a4, a4, -64 -+ bne a3, a1, L(back_un_long_bytes) -+ -+L(back_un_less_64bytes): -+ srai.d a3, a2, 5 -+ beqz a3, L(back_un_less_32bytes) -+ -+ ld.d t0, a1, -8 -+ ld.d t1, a1, -16 -+ ld.d t2, a1, -24 -+ ld.d t3, a1, -32 -+ -+ addi.d a1, a1, -32 -+ addi.d a2, a2, -32 -+ -+ sll.d t4, t0, a6 -+ srl.d t0, t0, a5 -+ -+ sll.d t5, t1, a6 -+ srl.d t1, t1, a5 -+ -+ sll.d t6, t2, a6 -+ srl.d t2, t2, a5 -+ -+ or t0, a7, t0 -+ -+ sll.d a7, t3, a6 -+ srl.d t3, t3, a5 -+ -+ or t1, t4, t1 -+ or t2, t5, t2 -+ or t3, t6, t3 -+ -+ st.d t0, a4, -8 -+ st.d t1, a4, -16 -+ st.d t2, a4, -24 -+ st.d t3, a4, -32 -+ -+ addi.d a4, a4, -32 -+ -+L(back_un_less_32bytes): -+ srai.d a3, a2, 4 -+ beqz a3, L(back_un_less_16bytes) -+ -+ ld.d t0, a1, -8 -+ ld.d t1, a1, -16 -+ -+ addi.d a1, a1, -16 -+ addi.d a2, a2, -16 -+ -+ sll.d t2, t0, a6 -+ srl.d t3, t0, a5 -+ -+ srl.d t4, t1, a5 -+ or t3, a7, t3 -+ or t4, t2, t4 -+ sll.d a7, t1, a6 -+ -+ st.d t3, a4, -8 -+ st.d t4, a4, -16 -+ -+ addi.d a4, a4, -16 -+ -+L(back_un_less_16bytes): -+ srai.d a3, a2, 3 -+ beqz a3, L(back_un_less_8bytes) -+ -+ ld.d t0, a1, -8 -+ -+ addi.d a1, a1, -8 -+ addi.d a2, a2, -8 -+ -+ srl.d t1, t0, a5 -+ or t2, a7, t1 -+ sll.d a7, t0, a6 -+ -+ st.d t2, a4, -8 -+ addi.d a4, a4, -8 -+ -+L(back_un_less_8bytes): -+ beqz a2, L(back_end) -+ bge t8, a2, 1f -+ -+ ld.d t0, a1, -8 -+ srl.d t0, t0, a5 -+ or a7, a7, t0 -+ -+1: -+ srai.d a3, a2, 2 -+ beqz a3, L(back_un_less_4bytes) -+ -+ srai.d t0, a7, 32 -+ addi.d a2, a2, -4 -+ st.w t0, a4, -4 -+ addi.d a4, a4, -4 -+ slli.d a7, a7, 32 -+ -+L(back_un_less_4bytes): -+ srai.d a3, a2, 1 -+ beqz a3, L(back_un_less_2bytes) -+ srai.d t0, a7, 48 -+ addi.d a2, a2, -2 -+ st.h t0, a4, -2 -+ addi.d a4, a4, -2 -+ slli.d a7, a7, 16 -+L(back_un_less_2bytes): -+ beqz a2, L(back_un_less_1byte) -+ srai.d t0, a7, 56 -+ st.b t0, a4, -1 -+L(back_un_less_1byte): -+ jr ra -+ -+L(back_short_data): -+ pcaddi t1, 34 -+ slli.d t2, a2, 3 -+ sub.d t1, t1, t2 -+ jr t1 -+ -+ ld.b t0, a1, 14 -+ st.b t0, a0, 14 -+ ld.b t0, a1, 13 -+ st.b t0, a0, 13 -+ ld.b t0, a1, 12 -+ st.b t0, a0, 12 -+ ld.b t0, a1, 11 -+ st.b t0, a0, 11 -+ ld.b t0, a1, 10 -+ st.b t0, a0, 10 -+ ld.b t0, a1, 9 -+ st.b t0, a0, 9 -+ ld.b t0, a1, 8 -+ st.b t0, a0, 8 -+ ld.b t0, a1, 7 -+ st.b t0, a0, 7 -+ ld.b t0, a1, 6 -+ st.b t0, a0, 6 -+ ld.b t0, a1, 5 -+ st.b t0, a0, 5 -+ ld.b t0, a1, 4 -+ st.b t0, a0, 4 -+ ld.b t0, a1, 3 -+ st.b t0, a0, 3 -+ ld.b t0, a1, 2 -+ st.b t0, a0, 2 -+ ld.b t0, a1, 1 -+ st.b t0, a0, 1 -+ ld.b t0, a1, 0 -+ st.b t0, a0, 0 -+L(back_end): -+ jr ra -+ -+END(MEMCPY_NAME) -+ -+libc_hidden_builtin_def (MEMMOVE_NAME) -+libc_hidden_builtin_def (MEMCPY_NAME) -diff --git a/sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S b/sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S -new file mode 100644 -index 00000000..4aae5bf8 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S -@@ -0,0 +1,20 @@ -+/* Optimized memcpy implementation using Loongarch LASX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* memcpy is part of memmove.S */ -diff --git a/sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S b/sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S -new file mode 100644 -index 00000000..6ebbe7a2 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S -@@ -0,0 +1,20 @@ -+/* Optimized memcpy implementation using Loongarch LSX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* memcpy is part of memmove.S */ -diff --git a/sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S b/sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S -new file mode 100644 -index 00000000..8e60a22d ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S -@@ -0,0 +1,247 @@ -+/* Optimized unaligned memcpy implementation using basic Loongarch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+ -+# define MEMCPY_NAME __memcpy_unaligned -+ -+# define LD_64(reg, n) \ -+ ld.d t0, reg, n; \ -+ ld.d t1, reg, n + 8; \ -+ ld.d t2, reg, n + 16; \ -+ ld.d t3, reg, n + 24; \ -+ ld.d t4, reg, n + 32; \ -+ ld.d t5, reg, n + 40; \ -+ ld.d t6, reg, n + 48; \ -+ ld.d t7, reg, n + 56; -+ -+# define ST_64(reg, n) \ -+ st.d t0, reg, n; \ -+ st.d t1, reg, n + 8; \ -+ st.d t2, reg, n + 16; \ -+ st.d t3, reg, n + 24; \ -+ st.d t4, reg, n + 32; \ -+ st.d t5, reg, n + 40; \ -+ st.d t6, reg, n + 48; \ -+ st.d t7, reg, n + 56; -+ -+LEAF(MEMCPY_NAME, 3) -+ add.d a4, a1, a2 -+ add.d a3, a0, a2 -+ li.w a6, 16 -+ bge a6, a2, L(less_16bytes) -+ -+ li.w a6, 128 -+ blt a6, a2, L(long_bytes) -+ li.w a6, 64 -+ blt a6, a2, L(more_64bytes) -+ -+ li.w a6, 32 -+ blt a6, a2, L(more_32bytes) -+ -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ ld.d t2, a4, -16 -+ ld.d t3, a4, -8 -+ -+ st.d t0, a0, 0 -+ st.d t1, a0, 8 -+ st.d t2, a3, -16 -+ st.d t3, a3, -8 -+ jr ra -+ -+L(more_64bytes): -+ srli.d t8, a0, 3 -+ slli.d t8, t8, 3 -+ addi.d t8, t8, 0x8 -+ sub.d a7, a0, t8 -+ -+ ld.d t0, a1, 0 -+ sub.d a1, a1, a7 -+ st.d t0, a0, 0 -+ add.d a7, a7, a2 -+ addi.d a7, a7, -0x20 -+ -+L(loop_32): -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ ld.d t2, a1, 16 -+ ld.d t3, a1, 24 -+ -+ st.d t0, t8, 0 -+ st.d t1, t8, 8 -+ st.d t2, t8, 16 -+ st.d t3, t8, 24 -+ -+ addi.d t8, t8, 0x20 -+ addi.d a1, a1, 0x20 -+ addi.d a7, a7, -0x20 -+ blt zero, a7, L(loop_32) -+ -+ ld.d t4, a4, -32 -+ ld.d t5, a4, -24 -+ ld.d t6, a4, -16 -+ ld.d t7, a4, -8 -+ -+ st.d t4, a3, -32 -+ st.d t5, a3, -24 -+ st.d t6, a3, -16 -+ st.d t7, a3, -8 -+ -+ jr ra -+ -+L(more_32bytes): -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ ld.d t2, a1, 16 -+ ld.d t3, a1, 24 -+ -+ ld.d t4, a4, -32 -+ ld.d t5, a4, -24 -+ ld.d t6, a4, -16 -+ ld.d t7, a4, -8 -+ -+ st.d t0, a0, 0 -+ st.d t1, a0, 8 -+ st.d t2, a0, 16 -+ st.d t3, a0, 24 -+ -+ st.d t4, a3, -32 -+ st.d t5, a3, -24 -+ st.d t6, a3, -16 -+ st.d t7, a3, -8 -+ -+ jr ra -+ -+L(less_16bytes): -+ srai.d a6, a2, 3 -+ beqz a6, L(less_8bytes) -+ -+ ld.d t0, a1, 0 -+ ld.d t1, a4, -8 -+ st.d t0, a0, 0 -+ st.d t1, a3, -8 -+ -+ jr ra -+ -+L(less_8bytes): -+ srai.d a6, a2, 2 -+ beqz a6, L(less_4bytes) -+ -+ ld.w t0, a1, 0 -+ ld.w t1, a4, -4 -+ st.w t0, a0, 0 -+ st.w t1, a3, -4 -+ -+ jr ra -+ -+L(less_4bytes): -+ srai.d a6, a2, 1 -+ beqz a6, L(less_2bytes) -+ -+ ld.h t0, a1, 0 -+ ld.h t1, a4, -2 -+ st.h t0, a0, 0 -+ st.h t1, a3, -2 -+ -+ jr ra -+ -+L(less_2bytes): -+ beqz a2, L(less_1bytes) -+ -+ ld.b t0, a1, 0 -+ st.b t0, a0, 0 -+ jr ra -+ -+L(less_1bytes): -+ jr ra -+ -+L(long_bytes): -+ srli.d t8, a0, 3 -+ slli.d t8, t8, 3 -+ beq a0, t8, L(start) -+ ld.d t0, a1, 0 -+ -+ addi.d t8, t8, 0x8 -+ st.d t0, a0, 0 -+ sub.d a7, a0, t8 -+ sub.d a1, a1, a7 -+ -+L(start): -+ addi.d a5, a3, -0x80 -+ blt a5, t8, L(align_end_proc) -+ -+L(loop_128): -+ LD_64(a1, 0) -+ ST_64(t8, 0) -+ LD_64(a1, 64) -+ addi.d a1, a1, 0x80 -+ ST_64(t8, 64) -+ addi.d t8, t8, 0x80 -+ bge a5, t8, L(loop_128) -+ -+L(align_end_proc): -+ sub.d a2, a3, t8 -+ pcaddi t1, 34 -+ andi t2, a2, 0x78 -+ sub.d t1, t1, t2 -+ jr t1 -+ -+ ld.d t0, a1, 112 -+ st.d t0, t8, 112 -+ ld.d t0, a1, 104 -+ st.d t0, t8, 104 -+ ld.d t0, a1, 96 -+ st.d t0, t8, 96 -+ ld.d t0, a1, 88 -+ st.d t0, t8, 88 -+ ld.d t0, a1, 80 -+ st.d t0, t8, 80 -+ ld.d t0, a1, 72 -+ st.d t0, t8, 72 -+ ld.d t0, a1, 64 -+ st.d t0, t8, 64 -+ ld.d t0, a1, 56 -+ st.d t0, t8, 56 -+ ld.d t0, a1, 48 -+ st.d t0, t8, 48 -+ ld.d t0, a1, 40 -+ st.d t0, t8, 40 -+ ld.d t0, a1, 32 -+ st.d t0, t8, 32 -+ ld.d t0, a1, 24 -+ st.d t0, t8, 24 -+ ld.d t0, a1, 16 -+ st.d t0, t8, 16 -+ ld.d t0, a1, 8 -+ st.d t0, t8, 8 -+ ld.d t0, a1, 0 -+ st.d t0, t8, 0 -+ ld.d t0, a4, -8 -+ st.d t0, a3, -8 -+ -+ jr ra -+END(MEMCPY_NAME) -+ -+libc_hidden_builtin_def (MEMCPY_NAME) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memcpy.c b/sysdeps/loongarch/lp64/multiarch/memcpy.c -new file mode 100644 -index 00000000..93b238ce ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memcpy.c -@@ -0,0 +1,37 @@ -+/* Multiple versions of memcpy. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+#if IS_IN (libc) -+# define memcpy __redirect_memcpy -+# include -+# undef memcpy -+ -+# define SYMBOL_NAME memcpy -+# include "ifunc-lasx.h" -+ -+libc_ifunc_redirected (__redirect_memcpy, memcpy, -+ IFUNC_SELECTOR ()); -+ -+# ifdef SHARED -+__hidden_ver1 (memcpy, __GI_memcpy, __redirect_memcpy) -+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (memcmp); -+# endif -+ -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-aligned.S b/sysdeps/loongarch/lp64/multiarch/memmove-aligned.S -new file mode 100644 -index 00000000..5354f383 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memmove-aligned.S -@@ -0,0 +1,20 @@ -+/* Optimized memmove_aligned implementation using basic Loongarch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* memmove_aligned is part of memcpy_aligned, see memcpy-aligned.S. */ -diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-lasx.S b/sysdeps/loongarch/lp64/multiarch/memmove-lasx.S -new file mode 100644 -index 00000000..ff68e7a2 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memmove-lasx.S -@@ -0,0 +1,287 @@ -+/* Optimized memmove implementation using Loongarch LASX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+#ifndef MEMCPY_NAME -+# define MEMCPY_NAME __memcpy_lasx -+#endif -+ -+#ifndef MEMMOVE_NAME -+# define MEMMOVE_NAME __memmove_lasx -+#endif -+ -+LEAF(MEMCPY_NAME, 6) -+ li.d t0, 32 -+ add.d a3, a0, a2 -+ add.d a4, a1, a2 -+ bgeu t0, a2, L(less_32bytes) -+ -+ li.d t1, 64 -+ bltu t1, a2, L(copy_long) -+ xvld xr0, a1, 0 -+ xvld xr1, a4, -32 -+ -+ xvst xr0, a0, 0 -+ xvst xr1, a3, -32 -+ jr ra -+L(less_32bytes): -+ srli.d t0, a2, 4 -+ -+ beqz t0, L(less_16bytes) -+ vld vr0, a1, 0 -+ vld vr1, a4, -16 -+ vst vr0, a0, 0 -+ -+ -+ vst vr1, a3, -16 -+ jr ra -+L(less_16bytes): -+ srli.d t0, a2, 3 -+ beqz t0, L(less_8bytes) -+ -+ ld.d t0, a1, 0 -+ ld.d t1, a4, -8 -+ st.d t0, a0, 0 -+ st.d t1, a3, -8 -+ -+ jr ra -+L(less_8bytes): -+ srli.d t0, a2, 2 -+ beqz t0, L(less_4bytes) -+ ld.w t0, a1, 0 -+ -+ ld.w t1, a4, -4 -+ st.w t0, a0, 0 -+ st.w t1, a3, -4 -+ jr ra -+ -+ -+L(less_4bytes): -+ srli.d t0, a2, 1 -+ beqz t0, L(less_2bytes) -+ ld.h t0, a1, 0 -+ ld.h t1, a4, -2 -+ -+ st.h t0, a0, 0 -+ st.h t1, a3, -2 -+ jr ra -+L(less_2bytes): -+ beqz a2, L(less_1bytes) -+ -+ ld.b t0, a1, 0 -+ st.b t0, a0, 0 -+L(less_1bytes): -+ jr ra -+END(MEMCPY_NAME) -+ -+LEAF(MEMMOVE_NAME, 6) -+ -+ li.d t0, 32 -+ add.d a3, a0, a2 -+ add.d a4, a1, a2 -+ bgeu t0, a2, L(less_32bytes) -+ -+ li.d t1, 64 -+ bltu t1, a2, L(move_long) -+ xvld xr0, a1, 0 -+ xvld xr1, a4, -32 -+ -+ xvst xr0, a0, 0 -+ xvst xr1, a3, -32 -+ jr ra -+L(move_long): -+ sub.d t2, a0, a1 -+ -+ bltu t2, a2, L(copy_back) -+L(copy_long): -+ andi t2, a0, 0x1f -+ addi.d a2, a2, -1 -+ sub.d t2, t0, t2 -+ -+ -+ xvld xr8, a1, 0 -+ xvld xr9, a4, -32 -+ sub.d t3, a2, t2 -+ add.d a5, a0, t2 -+ -+ andi a2, t3, 0xff -+ add.d a1, a1, t2 -+ beq a2, t3, L(lt256) -+ sub.d a6, a4, a2 -+ -+ addi.d a6, a6, -1 -+L(loop_256): -+ xvld xr0, a1, 0 -+ xvld xr1, a1, 32 -+ xvld xr2, a1, 64 -+ -+ xvld xr3, a1, 96 -+ xvld xr4, a1, 128 -+ xvld xr5, a1, 160 -+ xvld xr6, a1, 192 -+ -+ -+ xvld xr7, a1, 224 -+ addi.d a1, a1, 256 -+ xvst xr0, a5, 0 -+ xvst xr1, a5, 32 -+ -+ xvst xr2, a5, 64 -+ xvst xr3, a5, 96 -+ xvst xr4, a5, 128 -+ xvst xr5, a5, 160 -+ -+ xvst xr6, a5, 192 -+ xvst xr7, a5, 224 -+ addi.d a5, a5, 256 -+ bne a1, a6, L(loop_256) -+ -+L(lt256): -+ srli.d t2, a2, 7 -+ beqz t2, L(lt128) -+ xvld xr0, a1, 0 -+ xvld xr1, a1, 32 -+ -+ -+ xvld xr2, a1, 64 -+ xvld xr3, a1, 96 -+ addi.d a1, a1, 128 -+ addi.d a2, a2, -128 -+ -+ xvst xr0, a5, 0 -+ xvst xr1, a5, 32 -+ xvst xr2, a5, 64 -+ xvst xr3, a5, 96 -+ -+ addi.d a5, a5, 128 -+L(lt128): -+ bltu a2, t1, L(lt64) -+ xvld xr0, a1, 0 -+ xvld xr1, a1, 32 -+ -+ addi.d a1, a1, 64 -+ addi.d a2, a2, -64 -+ xvst xr0, a5, 0 -+ xvst xr1, a5, 32 -+ -+ -+ addi.d a5, a5, 64 -+L(lt64): -+ bltu a2, t0, L(lt32) -+ xvld xr0, a1, 0 -+ xvst xr0, a5, 0 -+ -+L(lt32): -+ xvst xr8, a0, 0 -+ xvst xr9, a3, -32 -+ jr ra -+ nop -+ -+L(copy_back): -+ addi.d a3, a3, -1 -+ addi.d a2, a2, -2 -+ andi t2, a3, 0x1f -+ xvld xr8, a1, 0 -+ -+ xvld xr9, a4, -32 -+ sub.d t3, a2, t2 -+ sub.d a5, a3, t2 -+ sub.d a4, a4, t2 -+ -+ -+ andi a2, t3, 0xff -+ beq a2, t3, L(back_lt256) -+ add.d a6, a1, a2 -+ addi.d a6, a6, 2 -+ -+L(back_loop_256): -+ xvld xr0, a4, -33 -+ xvld xr1, a4, -65 -+ xvld xr2, a4, -97 -+ xvld xr3, a4, -129 -+ -+ xvld xr4, a4, -161 -+ xvld xr5, a4, -193 -+ xvld xr6, a4, -225 -+ xvld xr7, a4, -257 -+ -+ addi.d a4, a4, -256 -+ xvst xr0, a5, -32 -+ xvst xr1, a5, -64 -+ xvst xr2, a5, -96 -+ -+ -+ xvst xr3, a5, -128 -+ xvst xr4, a5, -160 -+ xvst xr5, a5, -192 -+ xvst xr6, a5, -224 -+ -+ xvst xr7, a5, -256 -+ addi.d a5, a5, -256 -+ bne a4, a6, L(back_loop_256) -+L(back_lt256): -+ srli.d t2, a2, 7 -+ -+ beqz t2, L(back_lt128) -+ xvld xr0, a4, -33 -+ xvld xr1, a4, -65 -+ xvld xr2, a4, -97 -+ -+ xvld xr3, a4, -129 -+ addi.d a2, a2, -128 -+ addi.d a4, a4, -128 -+ xvst xr0, a5, -32 -+ -+ -+ xvst xr1, a5, -64 -+ xvst xr2, a5, -96 -+ xvst xr3, a5, -128 -+ addi.d a5, a5, -128 -+ -+L(back_lt128): -+ blt a2, t1, L(back_lt64) -+ xvld xr0, a4, -33 -+ xvld xr1, a4, -65 -+ addi.d a2, a2, -64 -+ -+ addi.d a4, a4, -64 -+ xvst xr0, a5, -32 -+ xvst xr1, a5, -64 -+ addi.d a5, a5, -64 -+ -+L(back_lt64): -+ bltu a2, t0, L(back_lt32) -+ xvld xr0, a4, -33 -+ xvst xr0, a5, -32 -+L(back_lt32): -+ xvst xr8, a0, 0 -+ -+ -+ xvst xr9, a3, -31 -+ jr ra -+END(MEMMOVE_NAME) -+ -+libc_hidden_builtin_def (MEMCPY_NAME) -+libc_hidden_builtin_def (MEMMOVE_NAME) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S b/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S -new file mode 100644 -index 00000000..9e1502a7 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S -@@ -0,0 +1,534 @@ -+/* Optimized memmove implementation using Loongarch LSX instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+# define MEMCPY_NAME __memcpy_lsx -+# define MEMMOVE_NAME __memmove_lsx -+ -+LEAF(MEMCPY_NAME, 6) -+ li.d t6, 16 -+ add.d a3, a0, a2 -+ add.d a4, a1, a2 -+ bgeu t6, a2, L(less_16bytes) -+ -+ li.d t8, 64 -+ li.d t7, 32 -+ bltu t8, a2, L(copy_long) -+ bltu t7, a2, L(more_32bytes) -+ -+ vld vr0, a1, 0 -+ vld vr1, a4, -16 -+ vst vr0, a0, 0 -+ vst vr1, a3, -16 -+ -+ jr ra -+L(more_32bytes): -+ vld vr0, a1, 0 -+ vld vr1, a1, 16 -+ vld vr2, a4, -32 -+ -+ -+ vld vr3, a4, -16 -+ vst vr0, a0, 0 -+ vst vr1, a0, 16 -+ vst vr2, a3, -32 -+ -+ vst vr3, a3, -16 -+ jr ra -+L(less_16bytes): -+ srli.d t0, a2, 3 -+ beqz t0, L(less_8bytes) -+ -+ vldrepl.d vr0, a1, 0 -+ vldrepl.d vr1, a4, -8 -+ vstelm.d vr0, a0, 0, 0 -+ vstelm.d vr1, a3, -8, 0 -+ -+ jr ra -+L(less_8bytes): -+ srli.d t0, a2, 2 -+ beqz t0, L(less_4bytes) -+ vldrepl.w vr0, a1, 0 -+ -+ -+ vldrepl.w vr1, a4, -4 -+ vstelm.w vr0, a0, 0, 0 -+ vstelm.w vr1, a3, -4, 0 -+ jr ra -+ -+L(less_4bytes): -+ srli.d t0, a2, 1 -+ beqz t0, L(less_2bytes) -+ vldrepl.h vr0, a1, 0 -+ vldrepl.h vr1, a4, -2 -+ -+ vstelm.h vr0, a0, 0, 0 -+ vstelm.h vr1, a3, -2, 0 -+ jr ra -+L(less_2bytes): -+ beqz a2, L(less_1bytes) -+ -+ ld.b t0, a1, 0 -+ st.b t0, a0, 0 -+L(less_1bytes): -+ jr ra -+ nop -+END(MEMCPY_NAME) -+ -+LEAF(MEMMOVE_NAME, 6) -+ li.d t6, 16 -+ add.d a3, a0, a2 -+ add.d a4, a1, a2 -+ bgeu t6, a2, L(less_16bytes) -+ -+ li.d t8, 64 -+ li.d t7, 32 -+ bltu t8, a2, L(move_long) -+ bltu t7, a2, L(more_32bytes) -+ -+ vld vr0, a1, 0 -+ vld vr1, a4, -16 -+ vst vr0, a0, 0 -+ vst vr1, a3, -16 -+ -+ jr ra -+ nop -+L(move_long): -+ sub.d t0, a0, a1 -+ bltu t0, a2, L(copy_back) -+ -+ -+L(copy_long): -+ vld vr2, a1, 0 -+ andi t0, a0, 0xf -+ sub.d t0, t6, t0 -+ add.d a1, a1, t0 -+ -+ sub.d a2, a2, t0 -+ andi t1, a1, 0xf -+ bnez t1, L(unaligned) -+ vld vr0, a1, 0 -+ -+ addi.d a2, a2, -16 -+ vst vr2, a0, 0 -+ andi t2, a2, 0x7f -+ add.d a5, a0, t0 -+ -+ beq a2, t2, L(al_less_128) -+ sub.d t3, a2, t2 -+ move a2, t2 -+ add.d a6, a1, t3 -+ -+ -+L(al_loop): -+ vld vr1, a1, 16 -+ vld vr2, a1, 32 -+ vld vr3, a1, 48 -+ vld vr4, a1, 64 -+ -+ vld vr5, a1, 80 -+ vld vr6, a1, 96 -+ vld vr7, a1, 112 -+ vst vr0, a5, 0 -+ -+ vld vr0, a1, 128 -+ addi.d a1, a1, 128 -+ vst vr1, a5, 16 -+ vst vr2, a5, 32 -+ -+ vst vr3, a5, 48 -+ vst vr4, a5, 64 -+ vst vr5, a5, 80 -+ vst vr6, a5, 96 -+ -+ -+ vst vr7, a5, 112 -+ addi.d a5, a5, 128 -+ bne a1, a6, L(al_loop) -+L(al_less_128): -+ blt a2, t8, L(al_less_64) -+ -+ vld vr1, a1, 16 -+ vld vr2, a1, 32 -+ vld vr3, a1, 48 -+ addi.d a2, a2, -64 -+ -+ vst vr0, a5, 0 -+ vld vr0, a1, 64 -+ addi.d a1, a1, 64 -+ vst vr1, a5, 16 -+ -+ vst vr2, a5, 32 -+ vst vr3, a5, 48 -+ addi.d a5, a5, 64 -+L(al_less_64): -+ blt a2, t7, L(al_less_32) -+ -+ -+ vld vr1, a1, 16 -+ addi.d a2, a2, -32 -+ vst vr0, a5, 0 -+ vld vr0, a1, 32 -+ -+ addi.d a1, a1, 32 -+ vst vr1, a5, 16 -+ addi.d a5, a5, 32 -+L(al_less_32): -+ blt a2, t6, L(al_less_16) -+ -+ vst vr0, a5, 0 -+ vld vr0, a1, 16 -+ addi.d a5, a5, 16 -+L(al_less_16): -+ vld vr1, a4, -16 -+ -+ vst vr0, a5, 0 -+ vst vr1, a3, -16 -+ jr ra -+ nop -+ -+ -+L(magic_num): -+ .dword 0x0706050403020100 -+ .dword 0x0f0e0d0c0b0a0908 -+L(unaligned): -+ pcaddi t2, -4 -+ bstrins.d a1, zero, 3, 0 -+ vld vr8, t2, 0 -+ vld vr0, a1, 0 -+ -+ vld vr1, a1, 16 -+ addi.d a2, a2, -16 -+ vst vr2, a0, 0 -+ add.d a5, a0, t0 -+ -+ vreplgr2vr.b vr9, t1 -+ andi t2, a2, 0x7f -+ vadd.b vr9, vr9, vr8 -+ addi.d a1, a1, 32 -+ -+ -+ beq t2, a2, L(un_less_128) -+ sub.d t3, a2, t2 -+ move a2, t2 -+ add.d a6, a1, t3 -+ -+L(un_loop): -+ vld vr2, a1, 0 -+ vld vr3, a1, 16 -+ vld vr4, a1, 32 -+ vld vr5, a1, 48 -+ -+ vld vr6, a1, 64 -+ vld vr7, a1, 80 -+ vshuf.b vr8, vr1, vr0, vr9 -+ vld vr0, a1, 96 -+ -+ vst vr8, a5, 0 -+ vshuf.b vr8, vr2, vr1, vr9 -+ vld vr1, a1, 112 -+ vst vr8, a5, 16 -+ -+ -+ addi.d a1, a1, 128 -+ vshuf.b vr2, vr3, vr2, vr9 -+ vshuf.b vr3, vr4, vr3, vr9 -+ vst vr2, a5, 32 -+ -+ vshuf.b vr4, vr5, vr4, vr9 -+ vst vr3, a5, 48 -+ vshuf.b vr5, vr6, vr5, vr9 -+ vst vr4, a5, 64 -+ -+ vshuf.b vr6, vr7, vr6, vr9 -+ vst vr5, a5, 80 -+ vshuf.b vr7, vr0, vr7, vr9 -+ vst vr6, a5, 96 -+ -+ vst vr7, a5, 112 -+ addi.d a5, a5, 128 -+ bne a1, a6, L(un_loop) -+L(un_less_128): -+ blt a2, t8, L(un_less_64) -+ -+ -+ vld vr2, a1, 0 -+ vld vr3, a1, 16 -+ vshuf.b vr4, vr1, vr0, vr9 -+ vld vr0, a1, 32 -+ -+ vst vr4, a5, 0 -+ addi.d a2, a2, -64 -+ vshuf.b vr4, vr2, vr1, vr9 -+ vld vr1, a1, 48 -+ -+ addi.d a1, a1, 64 -+ vst vr4, a5, 16 -+ vshuf.b vr2, vr3, vr2, vr9 -+ vshuf.b vr3, vr0, vr3, vr9 -+ -+ vst vr2, a5, 32 -+ vst vr3, a5, 48 -+ addi.d a5, a5, 64 -+L(un_less_64): -+ blt a2, t7, L(un_less_32) -+ -+ -+ vshuf.b vr3, vr1, vr0, vr9 -+ vld vr0, a1, 0 -+ vst vr3, a5, 0 -+ addi.d a2, a2, -32 -+ -+ vshuf.b vr3, vr0, vr1, vr9 -+ vld vr1, a1, 16 -+ addi.d a1, a1, 32 -+ vst vr3, a5, 16 -+ -+ addi.d a5, a5, 32 -+L(un_less_32): -+ blt a2, t6, L(un_less_16) -+ vshuf.b vr2, vr1, vr0, vr9 -+ vor.v vr0, vr1, vr1 -+ -+ vld vr1, a1, 0 -+ vst vr2, a5, 0 -+ addi.d a5, a5, 16 -+L(un_less_16): -+ vld vr2, a4, -16 -+ -+ -+ vshuf.b vr0, vr1, vr0, vr9 -+ vst vr0, a5, 0 -+ vst vr2, a3, -16 -+ jr ra -+ -+L(copy_back): -+ addi.d t0, a3, -1 -+ vld vr2, a4, -16 -+ andi t0, t0, 0xf -+ addi.d t0, t0, 1 -+ -+ sub.d a4, a4, t0 -+ sub.d a2, a2, t0 -+ andi t1, a4, 0xf -+ bnez t1, L(back_unaligned) -+ -+ vld vr0, a4, -16 -+ addi.d a2, a2, -16 -+ vst vr2, a3, -16 -+ andi t2, a2, 0x7f -+ -+ -+ sub.d a3, a3, t0 -+ beq t2, a2, L(back_al_less_128) -+ sub.d t3, a2, t2 -+ move a2, t2 -+ -+ sub.d a6, a4, t3 -+L(back_al_loop): -+ vld vr1, a4, -32 -+ vld vr2, a4, -48 -+ vld vr3, a4, -64 -+ -+ vld vr4, a4, -80 -+ vld vr5, a4, -96 -+ vld vr6, a4, -112 -+ vld vr7, a4, -128 -+ -+ vst vr0, a3, -16 -+ vld vr0, a4, -144 -+ addi.d a4, a4, -128 -+ vst vr1, a3, -32 -+ -+ -+ vst vr2, a3, -48 -+ vst vr3, a3, -64 -+ vst vr4, a3, -80 -+ vst vr5, a3, -96 -+ -+ vst vr6, a3, -112 -+ vst vr7, a3, -128 -+ addi.d a3, a3, -128 -+ bne a4, a6, L(back_al_loop) -+ -+L(back_al_less_128): -+ blt a2, t8, L(back_al_less_64) -+ vld vr1, a4, -32 -+ vld vr2, a4, -48 -+ vld vr3, a4, -64 -+ -+ addi.d a2, a2, -64 -+ vst vr0, a3, -16 -+ vld vr0, a4, -80 -+ addi.d a4, a4, -64 -+ -+ -+ vst vr1, a3, -32 -+ vst vr2, a3, -48 -+ vst vr3, a3, -64 -+ addi.d a3, a3, -64 -+ -+L(back_al_less_64): -+ blt a2, t7, L(back_al_less_32) -+ vld vr1, a4, -32 -+ addi.d a2, a2, -32 -+ vst vr0, a3, -16 -+ -+ vld vr0, a4, -48 -+ vst vr1, a3, -32 -+ addi.d a3, a3, -32 -+ addi.d a4, a4, -32 -+ -+L(back_al_less_32): -+ blt a2, t6, L(back_al_less_16) -+ vst vr0, a3, -16 -+ vld vr0, a4, -32 -+ addi.d a3, a3, -16 -+ -+ -+L(back_al_less_16): -+ vld vr1, a1, 0 -+ vst vr0, a3, -16 -+ vst vr1, a0, 0 -+ jr ra -+ -+L(magic_num_2): -+ .dword 0x0706050403020100 -+ .dword 0x0f0e0d0c0b0a0908 -+L(back_unaligned): -+ pcaddi t2, -4 -+ bstrins.d a4, zero, 3, 0 -+ vld vr8, t2, 0 -+ vld vr0, a4, 0 -+ -+ vld vr1, a4, -16 -+ addi.d a2, a2, -16 -+ vst vr2, a3, -16 -+ sub.d a3, a3, t0 -+ -+ -+ vreplgr2vr.b vr9, t1 -+ andi t2, a2, 0x7f -+ vadd.b vr9, vr9, vr8 -+ addi.d a4, a4, -16 -+ -+ beq t2, a2, L(back_un_less_128) -+ sub.d t3, a2, t2 -+ move a2, t2 -+ sub.d a6, a4, t3 -+ -+L(back_un_loop): -+ vld vr2, a4, -16 -+ vld vr3, a4, -32 -+ vld vr4, a4, -48 -+ -+ vld vr5, a4, -64 -+ vld vr6, a4, -80 -+ vld vr7, a4, -96 -+ vshuf.b vr8, vr0, vr1, vr9 -+ -+ -+ vld vr0, a4, -112 -+ vst vr8, a3, -16 -+ vshuf.b vr8, vr1, vr2, vr9 -+ vld vr1, a4, -128 -+ -+ vst vr8, a3, -32 -+ addi.d a4, a4, -128 -+ vshuf.b vr2, vr2, vr3, vr9 -+ vshuf.b vr3, vr3, vr4, vr9 -+ -+ vst vr2, a3, -48 -+ vshuf.b vr4, vr4, vr5, vr9 -+ vst vr3, a3, -64 -+ vshuf.b vr5, vr5, vr6, vr9 -+ -+ vst vr4, a3, -80 -+ vshuf.b vr6, vr6, vr7, vr9 -+ vst vr5, a3, -96 -+ vshuf.b vr7, vr7, vr0, vr9 -+ -+ -+ vst vr6, a3, -112 -+ vst vr7, a3, -128 -+ addi.d a3, a3, -128 -+ bne a4, a6, L(back_un_loop) -+ -+L(back_un_less_128): -+ blt a2, t8, L(back_un_less_64) -+ vld vr2, a4, -16 -+ vld vr3, a4, -32 -+ vshuf.b vr4, vr0, vr1, vr9 -+ -+ vld vr0, a4, -48 -+ vst vr4, a3, -16 -+ addi.d a2, a2, -64 -+ vshuf.b vr4, vr1, vr2, vr9 -+ -+ vld vr1, a4, -64 -+ addi.d a4, a4, -64 -+ vst vr4, a3, -32 -+ vshuf.b vr2, vr2, vr3, vr9 -+ -+ -+ vshuf.b vr3, vr3, vr0, vr9 -+ vst vr2, a3, -48 -+ vst vr3, a3, -64 -+ addi.d a3, a3, -64 -+ -+L(back_un_less_64): -+ blt a2, t7, L(back_un_less_32) -+ vshuf.b vr3, vr0, vr1, vr9 -+ vld vr0, a4, -16 -+ vst vr3, a3, -16 -+ -+ addi.d a2, a2, -32 -+ vshuf.b vr3, vr1, vr0, vr9 -+ vld vr1, a4, -32 -+ addi.d a4, a4, -32 -+ -+ vst vr3, a3, -32 -+ addi.d a3, a3, -32 -+L(back_un_less_32): -+ blt a2, t6, L(back_un_less_16) -+ vshuf.b vr2, vr0, vr1, vr9 -+ -+ -+ vor.v vr0, vr1, vr1 -+ vld vr1, a4, -16 -+ vst vr2, a3, -16 -+ addi.d a3, a3, -16 -+ -+L(back_un_less_16): -+ vld vr2, a1, 0 -+ vshuf.b vr0, vr0, vr1, vr9 -+ vst vr0, a3, -16 -+ vst vr2, a0, 0 -+ -+ jr ra -+END(MEMMOVE_NAME) -+ -+libc_hidden_builtin_def (MEMCPY_NAME) -+libc_hidden_builtin_def (MEMMOVE_NAME) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S b/sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S -new file mode 100644 -index 00000000..90a64b6b ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S -@@ -0,0 +1,380 @@ -+/* Optimized memmove_unaligned implementation using basic Loongarch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+ -+# define MEMMOVE_NAME __memmove_unaligned -+ -+# define LD_64(reg, n) \ -+ ld.d t0, reg, n; \ -+ ld.d t1, reg, n + 8; \ -+ ld.d t2, reg, n + 16; \ -+ ld.d t3, reg, n + 24; \ -+ ld.d t4, reg, n + 32; \ -+ ld.d t5, reg, n + 40; \ -+ ld.d t6, reg, n + 48; \ -+ ld.d t7, reg, n + 56; -+ -+# define ST_64(reg, n) \ -+ st.d t0, reg, n; \ -+ st.d t1, reg, n + 8; \ -+ st.d t2, reg, n + 16; \ -+ st.d t3, reg, n + 24; \ -+ st.d t4, reg, n + 32; \ -+ st.d t5, reg, n + 40; \ -+ st.d t6, reg, n + 48; \ -+ st.d t7, reg, n + 56; -+ -+LEAF(MEMMOVE_NAME, 3) -+ add.d a4, a1, a2 -+ add.d a3, a0, a2 -+ beq a1, a0, L(less_1bytes) -+ move t8, a0 -+ -+ srai.d a6, a2, 4 -+ beqz a6, L(less_16bytes) -+ srai.d a6, a2, 6 -+ bnez a6, L(more_64bytes) -+ srai.d a6, a2, 5 -+ beqz a6, L(less_32bytes) -+ -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ ld.d t2, a1, 16 -+ ld.d t3, a1, 24 -+ -+ ld.d t4, a4, -32 -+ ld.d t5, a4, -24 -+ ld.d t6, a4, -16 -+ ld.d t7, a4, -8 -+ -+ st.d t0, a0, 0 -+ st.d t1, a0, 8 -+ st.d t2, a0, 16 -+ st.d t3, a0, 24 -+ -+ st.d t4, a3, -32 -+ st.d t5, a3, -24 -+ st.d t6, a3, -16 -+ st.d t7, a3, -8 -+ -+ jr ra -+ -+L(less_32bytes): -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ ld.d t2, a4, -16 -+ ld.d t3, a4, -8 -+ -+ st.d t0, a0, 0 -+ st.d t1, a0, 8 -+ st.d t2, a3, -16 -+ st.d t3, a3, -8 -+ -+ jr ra -+ -+L(less_16bytes): -+ srai.d a6, a2, 3 -+ beqz a6, L(less_8bytes) -+ -+ ld.d t0, a1, 0 -+ ld.d t1, a4, -8 -+ st.d t0, a0, 0 -+ st.d t1, a3, -8 -+ -+ jr ra -+ -+L(less_8bytes): -+ srai.d a6, a2, 2 -+ beqz a6, L(less_4bytes) -+ -+ ld.w t0, a1, 0 -+ ld.w t1, a4, -4 -+ st.w t0, a0, 0 -+ st.w t1, a3, -4 -+ -+ jr ra -+ -+L(less_4bytes): -+ srai.d a6, a2, 1 -+ beqz a6, L(less_2bytes) -+ -+ ld.h t0, a1, 0 -+ ld.h t1, a4, -2 -+ st.h t0, a0, 0 -+ st.h t1, a3, -2 -+ -+ jr ra -+ -+L(less_2bytes): -+ beqz a2, L(less_1bytes) -+ -+ ld.b t0, a1, 0 -+ st.b t0, a0, 0 -+ -+ jr ra -+ -+L(less_1bytes): -+ jr ra -+ -+L(more_64bytes): -+ sub.d a7, a0, a1 -+ bltu a7, a2, L(copy_backward) -+ -+L(copy_forward): -+ srli.d a0, a0, 3 -+ slli.d a0, a0, 3 -+ beq a0, t8, L(all_align) -+ addi.d a0, a0, 0x8 -+ sub.d a7, t8, a0 -+ sub.d a1, a1, a7 -+ add.d a2, a7, a2 -+ -+L(start_unalign_proc): -+ pcaddi t1, 18 -+ slli.d a6, a7, 3 -+ add.d t1, t1, a6 -+ jr t1 -+ -+ ld.b t0, a1, -7 -+ st.b t0, a0, -7 -+ ld.b t0, a1, -6 -+ st.b t0, a0, -6 -+ ld.b t0, a1, -5 -+ st.b t0, a0, -5 -+ ld.b t0, a1, -4 -+ st.b t0, a0, -4 -+ ld.b t0, a1, -3 -+ st.b t0, a0, -3 -+ ld.b t0, a1, -2 -+ st.b t0, a0, -2 -+ ld.b t0, a1, -1 -+ st.b t0, a0, -1 -+L(start_over): -+ -+ addi.d a2, a2, -0x80 -+ blt a2, zero, L(end_unalign_proc) -+ -+L(loop_less): -+ LD_64(a1, 0) -+ ST_64(a0, 0) -+ LD_64(a1, 64) -+ ST_64(a0, 64) -+ -+ addi.d a0, a0, 0x80 -+ addi.d a1, a1, 0x80 -+ addi.d a2, a2, -0x80 -+ bge a2, zero, L(loop_less) -+ -+L(end_unalign_proc): -+ addi.d a2, a2, 0x80 -+ -+ pcaddi t1, 36 -+ andi t2, a2, 0x78 -+ add.d a1, a1, t2 -+ add.d a0, a0, t2 -+ sub.d t1, t1, t2 -+ jr t1 -+ -+ ld.d t0, a1, -120 -+ st.d t0, a0, -120 -+ ld.d t0, a1, -112 -+ st.d t0, a0, -112 -+ ld.d t0, a1, -104 -+ st.d t0, a0, -104 -+ ld.d t0, a1, -96 -+ st.d t0, a0, -96 -+ ld.d t0, a1, -88 -+ st.d t0, a0, -88 -+ ld.d t0, a1, -80 -+ st.d t0, a0, -80 -+ ld.d t0, a1, -72 -+ st.d t0, a0, -72 -+ ld.d t0, a1, -64 -+ st.d t0, a0, -64 -+ ld.d t0, a1, -56 -+ st.d t0, a0, -56 -+ ld.d t0, a1, -48 -+ st.d t0, a0, -48 -+ ld.d t0, a1, -40 -+ st.d t0, a0, -40 -+ ld.d t0, a1, -32 -+ st.d t0, a0, -32 -+ ld.d t0, a1, -24 -+ st.d t0, a0, -24 -+ ld.d t0, a1, -16 -+ st.d t0, a0, -16 -+ ld.d t0, a1, -8 -+ st.d t0, a0, -8 -+ -+ andi a2, a2, 0x7 -+ pcaddi t1, 18 -+ slli.d a2, a2, 3 -+ sub.d t1, t1, a2 -+ jr t1 -+ -+ ld.b t0, a4, -7 -+ st.b t0, a3, -7 -+ ld.b t0, a4, -6 -+ st.b t0, a3, -6 -+ ld.b t0, a4, -5 -+ st.b t0, a3, -5 -+ ld.b t0, a4, -4 -+ st.b t0, a3, -4 -+ ld.b t0, a4, -3 -+ st.b t0, a3, -3 -+ ld.b t0, a4, -2 -+ st.b t0, a3, -2 -+ ld.b t0, a4, -1 -+ st.b t0, a3, -1 -+L(end): -+ move a0, t8 -+ jr ra -+ -+L(all_align): -+ addi.d a1, a1, 0x8 -+ addi.d a0, a0, 0x8 -+ ld.d t0, a1, -8 -+ st.d t0, a0, -8 -+ addi.d a2, a2, -8 -+ b L(start_over) -+ -+L(all_align_back): -+ addi.d a4, a4, -0x8 -+ addi.d a3, a3, -0x8 -+ ld.d t0, a4, 0 -+ st.d t0, a3, 0 -+ addi.d a2, a2, -8 -+ b L(start_over_back) -+ -+L(copy_backward): -+ move a5, a3 -+ srli.d a3, a3, 3 -+ slli.d a3, a3, 3 -+ beq a3, a5, L(all_align_back) -+ sub.d a7, a3, a5 -+ add.d a4, a4, a7 -+ add.d a2, a7, a2 -+ -+ pcaddi t1, 18 -+ slli.d a6, a7, 3 -+ add.d t1, t1, a6 -+ jr t1 -+ -+ ld.b t0, a4, 6 -+ st.b t0, a3, 6 -+ ld.b t0, a4, 5 -+ st.b t0, a3, 5 -+ ld.b t0, a4, 4 -+ st.b t0, a3, 4 -+ ld.b t0, a4, 3 -+ st.b t0, a3, 3 -+ ld.b t0, a4, 2 -+ st.b t0, a3, 2 -+ ld.b t0, a4, 1 -+ st.b t0, a3, 1 -+ ld.b t0, a4, 0 -+ st.b t0, a3, 0 -+L(start_over_back): -+ addi.d a2, a2, -0x80 -+ blt a2, zero, L(end_unalign_proc_back) -+ -+L(loop_less_back): -+ LD_64(a4, -64) -+ ST_64(a3, -64) -+ LD_64(a4, -128) -+ ST_64(a3, -128) -+ -+ addi.d a4, a4, -0x80 -+ addi.d a3, a3, -0x80 -+ addi.d a2, a2, -0x80 -+ bge a2, zero, L(loop_less_back) -+ -+L(end_unalign_proc_back): -+ addi.d a2, a2, 0x80 -+ -+ pcaddi t1, 36 -+ andi t2, a2, 0x78 -+ sub.d a4, a4, t2 -+ sub.d a3, a3, t2 -+ sub.d t1, t1, t2 -+ jr t1 -+ -+ ld.d t0, a4, 112 -+ st.d t0, a3, 112 -+ ld.d t0, a4, 104 -+ st.d t0, a3, 104 -+ ld.d t0, a4, 96 -+ st.d t0, a3, 96 -+ ld.d t0, a4, 88 -+ st.d t0, a3, 88 -+ ld.d t0, a4, 80 -+ st.d t0, a3, 80 -+ ld.d t0, a4, 72 -+ st.d t0, a3, 72 -+ ld.d t0, a4, 64 -+ st.d t0, a3, 64 -+ ld.d t0, a4, 56 -+ st.d t0, a3, 56 -+ ld.d t0, a4, 48 -+ st.d t0, a3, 48 -+ ld.d t0, a4, 40 -+ st.d t0, a3, 40 -+ ld.d t0, a4, 32 -+ st.d t0, a3, 32 -+ ld.d t0, a4, 24 -+ st.d t0, a3, 24 -+ ld.d t0, a4, 16 -+ st.d t0, a3, 16 -+ ld.d t0, a4, 8 -+ st.d t0, a3, 8 -+ ld.d t0, a4, 0 -+ st.d t0, a3, 0 -+ -+ andi a2, a2, 0x7 -+ pcaddi t1, 18 -+ slli.d a2, a2, 3 -+ sub.d t1, t1, a2 -+ jr t1 -+ -+ ld.b t0, a1, 6 -+ st.b t0, a0, 6 -+ ld.b t0, a1, 5 -+ st.b t0, a0, 5 -+ ld.b t0, a1, 4 -+ st.b t0, a0, 4 -+ ld.b t0, a1, 3 -+ st.b t0, a0, 3 -+ ld.b t0, a1, 2 -+ st.b t0, a0, 2 -+ ld.b t0, a1, 1 -+ st.b t0, a0, 1 -+ ld.b t0, a1, 0 -+ st.b t0, a0, 0 -+ -+ move a0, t8 -+ jr ra -+END(MEMMOVE_NAME) -+ -+libc_hidden_builtin_def (MEMMOVE_NAME) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/memmove.c b/sysdeps/loongarch/lp64/multiarch/memmove.c -new file mode 100644 -index 00000000..7e3ca4c4 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/memmove.c -@@ -0,0 +1,38 @@ -+/* Multiple versions of memmove. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+#if IS_IN (libc) -+# define memmove __redirect_memmove -+# include -+# undef memmove -+ -+# define SYMBOL_NAME memmove -+# include "ifunc-lasx.h" -+ -+libc_ifunc_redirected (__redirect_memmove, __libc_memmove, -+ IFUNC_SELECTOR ()); -+strong_alias (__libc_memmove, memmove); -+ -+# ifdef SHARED -+__hidden_ver1 (__libc_memmove, __GI_memmove, __redirect_memmove) -+ __attribute__ ((visibility ("hidden"))); -+# endif -+ -+#endif --- -2.33.0 - diff --git a/Loongarch-Add-ifunc-support-for-strchr-aligned-lsx-l.patch b/Loongarch-Add-ifunc-support-for-strchr-aligned-lsx-l.patch deleted file mode 100644 index 03e1299..0000000 --- a/Loongarch-Add-ifunc-support-for-strchr-aligned-lsx-l.patch +++ /dev/null @@ -1,706 +0,0 @@ -From aca7d7f0dde5f56344e8e58e5f6648c96bb1f1cc Mon Sep 17 00:00:00 2001 -From: dengjianbo -Date: Tue, 15 Aug 2023 09:08:11 +0800 -Subject: [PATCH 06/29] Loongarch: Add ifunc support for strchr{aligned, lsx, - lasx} and strchrnul{aligned, lsx, lasx} - -These implementations improve the time to run strchr{nul} -microbenchmark in glibc as below: -strchr-lasx reduces the runtime about 50%-83% -strchr-lsx reduces the runtime about 30%-67% -strchr-aligned reduces the runtime about 10%-20% -strchrnul-lasx reduces the runtime about 50%-83% -strchrnul-lsx reduces the runtime about 36%-65% -strchrnul-aligned reduces the runtime about 6%-10% - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/lp64/multiarch/Makefile | 6 ++ - .../lp64/multiarch/ifunc-impl-list.c | 16 +++ - .../loongarch/lp64/multiarch/ifunc-strchr.h | 41 ++++++++ - .../lp64/multiarch/ifunc-strchrnul.h | 41 ++++++++ - .../loongarch/lp64/multiarch/strchr-aligned.S | 99 +++++++++++++++++++ - .../loongarch/lp64/multiarch/strchr-lasx.S | 91 +++++++++++++++++ - sysdeps/loongarch/lp64/multiarch/strchr-lsx.S | 73 ++++++++++++++ - sysdeps/loongarch/lp64/multiarch/strchr.c | 36 +++++++ - .../lp64/multiarch/strchrnul-aligned.S | 95 ++++++++++++++++++ - .../loongarch/lp64/multiarch/strchrnul-lasx.S | 22 +++++ - .../loongarch/lp64/multiarch/strchrnul-lsx.S | 22 +++++ - sysdeps/loongarch/lp64/multiarch/strchrnul.c | 39 ++++++++ - 12 files changed, 581 insertions(+) - create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-strchr.h - create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-strchrnul.h - create mode 100644 sysdeps/loongarch/lp64/multiarch/strchr-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strchr-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strchr-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strchr.c - create mode 100644 sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S - create mode 100644 sysdeps/loongarch/lp64/multiarch/strchrnul.c - -diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile -index 76c506c9..110a8c5c 100644 ---- a/sysdeps/loongarch/lp64/multiarch/Makefile -+++ b/sysdeps/loongarch/lp64/multiarch/Makefile -@@ -3,5 +3,11 @@ sysdep_routines += \ - strlen-aligned \ - strlen-lsx \ - strlen-lasx \ -+ strchr-aligned \ -+ strchr-lsx \ -+ strchr-lasx \ -+ strchrnul-aligned \ -+ strchrnul-lsx \ -+ strchrnul-lasx \ - # sysdep_routines - endif -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -index 1a2a576f..c7164b45 100644 ---- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c -@@ -37,5 +37,21 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, - #endif - IFUNC_IMPL_ADD (array, i, strlen, 1, __strlen_aligned) - ) -+ -+ IFUNC_IMPL (i, name, strchr, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, strchr, SUPPORT_LASX, __strchr_lasx) -+ IFUNC_IMPL_ADD (array, i, strchr, SUPPORT_LSX, __strchr_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, strchr, 1, __strchr_aligned) -+ ) -+ -+ IFUNC_IMPL (i, name, strchrnul, -+#if !defined __loongarch_soft_float -+ IFUNC_IMPL_ADD (array, i, strchrnul, SUPPORT_LASX, __strchrnul_lasx) -+ IFUNC_IMPL_ADD (array, i, strchrnul, SUPPORT_LSX, __strchrnul_lsx) -+#endif -+ IFUNC_IMPL_ADD (array, i, strchrnul, 1, __strchrnul_aligned) -+ ) - return i; - } -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-strchr.h b/sysdeps/loongarch/lp64/multiarch/ifunc-strchr.h -new file mode 100644 -index 00000000..4494db79 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-strchr.h -@@ -0,0 +1,41 @@ -+/* Common definition for strchr ifunc selections. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+ -+#if !defined __loongarch_soft_float -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden; -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden; -+#endif -+ -+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden; -+ -+static inline void * -+IFUNC_SELECTOR (void) -+{ -+#if !defined __loongarch_soft_float -+ if (SUPPORT_LASX) -+ return OPTIMIZE (lasx); -+ else if (SUPPORT_LSX) -+ return OPTIMIZE (lsx); -+ else -+#endif -+ return OPTIMIZE (aligned); -+} -diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-strchrnul.h b/sysdeps/loongarch/lp64/multiarch/ifunc-strchrnul.h -new file mode 100644 -index 00000000..8a925120 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-strchrnul.h -@@ -0,0 +1,41 @@ -+/* Common definition for strchrnul ifunc selections. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+ -+#if !defined __loongarch_soft_float -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden; -+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden; -+#endif -+ -+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden; -+ -+static inline void * -+IFUNC_SELECTOR (void) -+{ -+#if !defined __loongarch_soft_float -+ if (SUPPORT_LASX) -+ return OPTIMIZE (lasx); -+ else if (SUPPORT_LSX) -+ return OPTIMIZE (lsx); -+ else -+#endif -+ return OPTIMIZE (aligned); -+} -diff --git a/sysdeps/loongarch/lp64/multiarch/strchr-aligned.S b/sysdeps/loongarch/lp64/multiarch/strchr-aligned.S -new file mode 100644 -index 00000000..5fb01806 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strchr-aligned.S -@@ -0,0 +1,99 @@ -+/* Optimized strchr implementation using basic Loongarch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+# define STRCHR_NAME __strchr_aligned -+#else -+# define STRCHR_NAME strchr -+#endif -+ -+LEAF(STRCHR_NAME, 6) -+ slli.d t1, a0, 3 -+ bstrins.d a0, zero, 2, 0 -+ lu12i.w a2, 0x01010 -+ ld.d t2, a0, 0 -+ -+ ori a2, a2, 0x101 -+ andi a1, a1, 0xff -+ bstrins.d a2, a2, 63, 32 -+ li.w t0, -1 -+ -+ mul.d a1, a1, a2 -+ sll.d t0, t0, t1 -+ slli.d a3, a2, 7 -+ orn t2, t2, t0 -+ -+ sll.d t3, a1, t1 -+ xor t4, t2, t3 -+ sub.d a4, t2, a2 -+ sub.d a5, t4, a2 -+ -+ -+ andn a4, a4, t2 -+ andn a5, a5, t4 -+ or t0, a4, a5 -+ and t0, t0, a3 -+ -+ bnez t0, L(end) -+ addi.d a0, a0, 8 -+L(loop): -+ ld.d t4, a0, 0 -+ xor t2, t4, a1 -+ -+ sub.d a4, t4, a2 -+ sub.d a5, t2, a2 -+ andn a4, a4, t4 -+ andn a5, a5, t2 -+ -+ or t0, a4, a5 -+ and t0, t0, a3 -+ bnez t0, L(end) -+ ld.d t4, a0, 8 -+ -+ -+ addi.d a0, a0, 16 -+ xor t2, t4, a1 -+ sub.d a4, t4, a2 -+ sub.d a5, t2, a2 -+ -+ andn a4, a4, t4 -+ andn a5, a5, t2 -+ or t0, a4, a5 -+ and t0, t0, a3 -+ -+ beqz t0, L(loop) -+ addi.d a0, a0, -8 -+L(end): -+ and t0, a5, a3 -+ and t1, a4, a3 -+ -+ ctz.d t0, t0 -+ ctz.d t1, t1 -+ srli.w t2, t0, 3 -+ sltu t3, t1, t0 -+ -+ -+ add.d a0, a0, t2 -+ masknez a0, a0, t3 -+ jr ra -+END(STRCHR_NAME) -diff --git a/sysdeps/loongarch/lp64/multiarch/strchr-lasx.S b/sysdeps/loongarch/lp64/multiarch/strchr-lasx.S -new file mode 100644 -index 00000000..254402da ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strchr-lasx.S -@@ -0,0 +1,91 @@ -+/* Optimized strchr implementation using loongarch LASX SIMD instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+#ifndef AS_STRCHRNUL -+# define STRCHR __strchr_lasx -+#endif -+ -+LEAF(STRCHR, 6) -+ andi t1, a0, 0x1f -+ bstrins.d a0, zero, 4, 0 -+ xvld xr0, a0, 0 -+ li.d t2, -1 -+ -+ xvreplgr2vr.b xr1, a1 -+ sll.d t1, t2, t1 -+ xvxor.v xr2, xr0, xr1 -+ xvmin.bu xr0, xr0, xr2 -+ -+ xvmsknz.b xr0, xr0 -+ xvpickve.w xr3, xr0, 4 -+ vilvl.h vr0, vr3, vr0 -+ movfr2gr.s t0, fa0 -+ -+ orn t0, t0, t1 -+ bne t0, t2, L(end) -+ addi.d a0, a0, 32 -+ nop -+ -+ -+L(loop): -+ xvld xr0, a0, 0 -+ xvxor.v xr2, xr0, xr1 -+ xvmin.bu xr0, xr0, xr2 -+ xvsetanyeqz.b fcc0, xr0 -+ -+ bcnez fcc0, L(loop_end) -+ xvld xr0, a0, 32 -+ addi.d a0, a0, 64 -+ xvxor.v xr2, xr0, xr1 -+ -+ xvmin.bu xr0, xr0, xr2 -+ xvsetanyeqz.b fcc0, xr0 -+ bceqz fcc0, L(loop) -+ addi.d a0, a0, -32 -+ -+L(loop_end): -+ xvmsknz.b xr0, xr0 -+ xvpickve.w xr1, xr0, 4 -+ vilvl.h vr0, vr1, vr0 -+ movfr2gr.s t0, fa0 -+ -+ -+L(end): -+ cto.w t0, t0 -+ add.d a0, a0, t0 -+#ifndef AS_STRCHRNUL -+ vreplgr2vr.b vr0, t0 -+ xvpermi.q xr3, xr2, 1 -+ -+ vshuf.b vr0, vr3, vr2, vr0 -+ vpickve2gr.bu t0, vr0, 0 -+ masknez a0, a0, t0 -+#endif -+ jr ra -+ -+END(STRCHR) -+ -+libc_hidden_builtin_def(STRCHR) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strchr-lsx.S b/sysdeps/loongarch/lp64/multiarch/strchr-lsx.S -new file mode 100644 -index 00000000..dae98b0a ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strchr-lsx.S -@@ -0,0 +1,73 @@ -+/* Optimized strlen implementation using loongarch LSX SIMD instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) && !defined __loongarch_soft_float -+ -+#ifndef AS_STRCHRNUL -+# define STRCHR __strchr_lsx -+#endif -+ -+LEAF(STRCHR, 6) -+ andi t1, a0, 0xf -+ bstrins.d a0, zero, 3, 0 -+ vld vr0, a0, 0 -+ li.d t2, -1 -+ -+ vreplgr2vr.b vr1, a1 -+ sll.d t3, t2, t1 -+ vxor.v vr2, vr0, vr1 -+ vmin.bu vr0, vr0, vr2 -+ -+ vmsknz.b vr0, vr0 -+ movfr2gr.s t0, fa0 -+ ext.w.h t0, t0 -+ orn t0, t0, t3 -+ -+ beq t0, t2, L(loop) -+L(found): -+ cto.w t0, t0 -+ add.d a0, a0, t0 -+#ifndef AS_STRCHRNUL -+ vreplve.b vr2, vr2, t0 -+ vpickve2gr.bu t1, vr2, 0 -+ masknez a0, a0, t1 -+#endif -+ jr ra -+ -+ -+L(loop): -+ vld vr0, a0, 16 -+ addi.d a0, a0, 16 -+ vxor.v vr2, vr0, vr1 -+ vmin.bu vr0, vr0, vr2 -+ -+ vsetanyeqz.b fcc0, vr0 -+ bceqz fcc0, L(loop) -+ vmsknz.b vr0, vr0 -+ movfr2gr.s t0, fa0 -+ -+ b L(found) -+END(STRCHR) -+ -+libc_hidden_builtin_def (STRCHR) -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strchr.c b/sysdeps/loongarch/lp64/multiarch/strchr.c -new file mode 100644 -index 00000000..404e97bd ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strchr.c -@@ -0,0 +1,36 @@ -+/* Multiple versions of strchr. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+#if IS_IN (libc) -+# define strchr __redirect_strchr -+# include -+# undef strchr -+ -+# define SYMBOL_NAME strchr -+# include "ifunc-strchr.h" -+ -+libc_ifunc_redirected (__redirect_strchr, strchr, IFUNC_SELECTOR ()); -+weak_alias(strchr, index) -+# ifdef SHARED -+__hidden_ver1 (strchr, __GI_strchr, __redirect_strchr) -+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strchr); -+# endif -+ -+#endif -diff --git a/sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S b/sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S -new file mode 100644 -index 00000000..1c01a023 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S -@@ -0,0 +1,95 @@ -+/* Optimized strchrnul implementation using basic Loongarch instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#include -+#include -+#include -+ -+#if IS_IN (libc) -+# define STRCHRNUL_NAME __strchrnul_aligned -+#else -+# define STRCHRNUL_NAME __strchrnul -+#endif -+ -+LEAF(STRCHRNUL_NAME, 6) -+ slli.d t1, a0, 3 -+ bstrins.d a0, zero, 2, 0 -+ lu12i.w a2, 0x01010 -+ ld.d t2, a0, 0 -+ -+ ori a2, a2, 0x101 -+ andi a1, a1, 0xff -+ bstrins.d a2, a2, 63, 32 -+ li.w t0, -1 -+ -+ mul.d a1, a1, a2 -+ sll.d t0, t0, t1 -+ slli.d a3, a2, 7 -+ orn t2, t2, t0 -+ -+ sll.d t3, a1, t1 -+ xor t4, t2, t3 -+ sub.d a4, t2, a2 -+ sub.d a5, t4, a2 -+ -+ -+ andn a4, a4, t2 -+ andn a5, a5, t4 -+ or t0, a4, a5 -+ and t0, t0, a3 -+ -+ bnez t0, L(end) -+ addi.d a0, a0, 8 -+L(loop): -+ ld.d t4, a0, 0 -+ xor t2, t4, a1 -+ -+ sub.d a4, t4, a2 -+ sub.d a5, t2, a2 -+ andn a4, a4, t4 -+ andn a5, a5, t2 -+ -+ or t0, a4, a5 -+ and t0, t0, a3 -+ bnez t0, L(end) -+ ld.d t4, a0, 8 -+ -+ -+ addi.d a0, a0, 16 -+ xor t2, t4, a1 -+ sub.d a4, t4, a2 -+ sub.d a5, t2, a2 -+ -+ andn a4, a4, t4 -+ andn a5, a5, t2 -+ or t0, a4, a5 -+ and t0, t0, a3 -+ -+ beqz t0, L(loop) -+ addi.d a0, a0, -8 -+L(end): -+ ctz.d t0, t0 -+ srli.w t0, t0, 3 -+ -+ -+ add.d a0, a0, t0 -+ jr ra -+END(STRCHRNUL_NAME) -+ -+libc_hidden_builtin_def (STRCHRNUL_NAME) -diff --git a/sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S b/sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S -new file mode 100644 -index 00000000..d45495e4 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S -@@ -0,0 +1,22 @@ -+/* Optimized strchrnul implementation using loongarch LASX SIMD instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#define STRCHR __strchrnul_lasx -+#define AS_STRCHRNUL -+#include "strchr-lasx.S" -diff --git a/sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S b/sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S -new file mode 100644 -index 00000000..07d793ae ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S -@@ -0,0 +1,22 @@ -+/* Optimized strchrnul implementation using loongarch LSX SIMD instructions. -+ Copyright (C) 2023 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 -+ . */ -+ -+#define STRCHR __strchrnul_lsx -+#define AS_STRCHRNUL -+#include "strchr-lsx.S" -diff --git a/sysdeps/loongarch/lp64/multiarch/strchrnul.c b/sysdeps/loongarch/lp64/multiarch/strchrnul.c -new file mode 100644 -index 00000000..f3b8296e ---- /dev/null -+++ b/sysdeps/loongarch/lp64/multiarch/strchrnul.c -@@ -0,0 +1,39 @@ -+/* Multiple versions of strchrnul. -+ All versions must be listed in ifunc-impl-list.c. -+ Copyright (C) 2023 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 -+ . */ -+ -+/* Define multiple versions only for the definition in libc. */ -+ -+#if IS_IN (libc) -+# define strchrnul __redirect_strchrnul -+# define __strchrnul __redirect___strchrnul -+# include -+# undef __strchrnul -+# undef strchrnul -+ -+# define SYMBOL_NAME strchrnul -+# include "ifunc-strchrnul.h" -+ -+libc_ifunc_redirected (__redirect_strchrnul, __strchrnul, -+ IFUNC_SELECTOR ()); -+weak_alias (__strchrnul, strchrnul) -+# ifdef SHARED -+__hidden_ver1 (__strchrnul, __GI___strchrnul, __redirect_strchrnul) -+ __attribute__((visibility ("hidden"))) __attribute_copy__ (strchrnul); -+# endif -+#endif --- -2.33.0 - diff --git a/README.md b/README.md deleted file mode 100644 index 7342728..0000000 --- a/README.md +++ /dev/null @@ -1,11 +0,0 @@ -Anolis OS -======================================= -# 代码仓库说明 -## 分支说明 ->进行代码开发工作时,请注意选择当前版本对应的分支 -* aX分支为对应大版本的主分支,如a8分支对应当前最新版本 -* aX.Y分支为对应小版本的维护分支,如a8.2分支对应8.2版本 -## 开发流程 -1. 首先fork目标分支到自己的namespace -2. 在自己的fork分支上做出修改 -3. 向对应的仓库中提交merge request,源分支为fork分支 diff --git a/Revert-LoongArch-Add-glibc.cpu.hwcap-support.patch b/Revert-LoongArch-Add-glibc.cpu.hwcap-support.patch deleted file mode 100644 index 6180f26..0000000 --- a/Revert-LoongArch-Add-glibc.cpu.hwcap-support.patch +++ /dev/null @@ -1,478 +0,0 @@ -From c0f3b0a8c71c26d5351e8ddabe3e8a323803e683 Mon Sep 17 00:00:00 2001 -From: caiyinyu -Date: Thu, 21 Sep 2023 09:10:11 +0800 -Subject: [PATCH 26/29] Revert "LoongArch: Add glibc.cpu.hwcap support." - -This reverts commit a53451559dc9cce765ea5bcbb92c4007e058e92b. - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - sysdeps/loongarch/Makefile | 4 - - sysdeps/loongarch/Versions | 5 -- - sysdeps/loongarch/cpu-tunables.c | 89 ------------------- - sysdeps/loongarch/dl-get-cpu-features.c | 25 ------ - sysdeps/loongarch/dl-machine.h | 27 +----- - sysdeps/loongarch/dl-tunables.list | 25 ------ - .../unix/sysv/linux/loongarch/cpu-features.c | 29 ------ - .../unix/sysv/linux/loongarch/cpu-features.h | 18 +--- - .../unix/sysv/linux/loongarch/dl-procinfo.c | 60 ------------- - sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c | 21 ----- - .../unix/sysv/linux/loongarch/libc-start.c | 34 ------- - 11 files changed, 8 insertions(+), 329 deletions(-) - delete mode 100644 sysdeps/loongarch/Versions - delete mode 100644 sysdeps/loongarch/cpu-tunables.c - delete mode 100644 sysdeps/loongarch/dl-get-cpu-features.c - delete mode 100644 sysdeps/loongarch/dl-tunables.list - delete mode 100644 sysdeps/unix/sysv/linux/loongarch/cpu-features.c - delete mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c - delete mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c - delete mode 100644 sysdeps/unix/sysv/linux/loongarch/libc-start.c - -diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile -index 30a1f4a8..43d2f583 100644 ---- a/sysdeps/loongarch/Makefile -+++ b/sysdeps/loongarch/Makefile -@@ -6,10 +6,6 @@ ifeq ($(subdir),elf) - gen-as-const-headers += dl-link.sym - endif - --ifeq ($(subdir),elf) -- sysdep-dl-routines += dl-get-cpu-features --endif -- - # LoongArch's assembler also needs to know about PIC as it changes the - # definition of some assembler macros. - ASFLAGS-.os += $(pic-ccflag) -diff --git a/sysdeps/loongarch/Versions b/sysdeps/loongarch/Versions -deleted file mode 100644 -index 33ae2cc0..00000000 ---- a/sysdeps/loongarch/Versions -+++ /dev/null -@@ -1,5 +0,0 @@ --ld { -- GLIBC_PRIVATE { -- _dl_larch_get_cpu_features; -- } --} -diff --git a/sysdeps/loongarch/cpu-tunables.c b/sysdeps/loongarch/cpu-tunables.c -deleted file mode 100644 -index 8e9fab93..00000000 ---- a/sysdeps/loongarch/cpu-tunables.c -+++ /dev/null -@@ -1,89 +0,0 @@ --/* LoongArch CPU feature tuning. -- This file is part of the GNU C Library. -- Copyright (C) 2023 Free Software Foundation, Inc. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- --# include --# include --# include /* Get STDOUT_FILENO for _dl_printf. */ --# include --# include --# include --# include --# include -- --# define HWCAP_LOONGARCH_IFUNC \ -- (HWCAP_LOONGARCH_UAL | HWCAP_LOONGARCH_LSX | HWCAP_LOONGARCH_LASX) -- --# define CHECK_GLIBC_IFUNC_CPU_OFF(f, name, len) \ -- _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \ -- if (!memcmp (f, #name, len) && \ -- (GLRO (dl_hwcap) & HWCAP_LOONGARCH_##name)) \ -- { \ -- hwcap |= (HWCAP_LOONGARCH_##name | (~HWCAP_LOONGARCH_IFUNC)); \ -- break; \ -- } \ -- --attribute_hidden --void --TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp) --{ -- const char *p = valp->strval; -- size_t len; -- unsigned long hwcap = 0; -- const char *c; -- -- do { -- for (c = p; *c != ','; c++) -- if (*c == '\0') -- break; -- -- len = c - p; -- -- switch(len) -- { -- default: -- _dl_fatal_printf ( -- "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n" -- ); -- break; -- case 3: -- { -- CHECK_GLIBC_IFUNC_CPU_OFF (p, LSX, 3); -- CHECK_GLIBC_IFUNC_CPU_OFF (p, UAL, 3); -- _dl_fatal_printf ( -- "Some features are invalid or not supported on this machine!!\n" -- "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n" -- ); -- } -- break; -- case 4: -- { -- CHECK_GLIBC_IFUNC_CPU_OFF (p, LASX, 4); -- _dl_fatal_printf ( -- "Some features are invalid or not supported on this machine!!\n" -- "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n" -- ); -- } -- break; -- } -- -- p += len + 1; -- } -- while (*c != '\0'); -- -- GLRO (dl_larch_cpu_features).hwcap &= hwcap; --} -diff --git a/sysdeps/loongarch/dl-get-cpu-features.c b/sysdeps/loongarch/dl-get-cpu-features.c -deleted file mode 100644 -index 7cd9bc15..00000000 ---- a/sysdeps/loongarch/dl-get-cpu-features.c -+++ /dev/null -@@ -1,25 +0,0 @@ --/* Define _dl_larch_get_cpu_features. -- Copyright (C) 2023 Free Software Foundation, Inc. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- -- --#include -- --const struct cpu_features * --_dl_larch_get_cpu_features (void) --{ -- return &GLRO(dl_larch_cpu_features); --} -diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h -index b395a928..57913cef 100644 ---- a/sysdeps/loongarch/dl-machine.h -+++ b/sysdeps/loongarch/dl-machine.h -@@ -29,8 +29,6 @@ - #include - #include - --#include -- - #ifndef _RTLD_PROLOGUE - # define _RTLD_PROLOGUE(entry) \ - ".globl\t" __STRING (entry) "\n\t" \ -@@ -55,23 +53,6 @@ - #define ELF_MACHINE_NO_REL 1 - #define ELF_MACHINE_NO_RELA 0 - --#define DL_PLATFORM_INIT dl_platform_init () -- --static inline void __attribute__ ((unused)) --dl_platform_init (void) --{ -- if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0') -- /* Avoid an empty string which would disturb us. */ -- GLRO(dl_platform) = NULL; -- --#ifdef SHARED -- /* init_cpu_features has been called early from __libc_start_main in -- static executable. */ -- init_cpu_features (&GLRO(dl_larch_cpu_features)); --#endif --} -- -- - /* Return nonzero iff ELF header is compatible with the running host. */ - static inline int - elf_machine_matches_host (const ElfW (Ehdr) *ehdr) -@@ -309,9 +290,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], - if (profile != 0) - { - #if !defined __loongarch_soft_float -- if (RTLD_SUPPORT_LASX) -+ if (SUPPORT_LASX) - gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lasx; -- else if (RTLD_SUPPORT_LSX) -+ else if (SUPPORT_LSX) - gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lsx; - else - #endif -@@ -329,9 +310,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], - indicated by the offset on the stack, and then jump to - the resolved address. */ - #if !defined __loongarch_soft_float -- if (RTLD_SUPPORT_LASX) -+ if (SUPPORT_LASX) - gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lasx; -- else if (RTLD_SUPPORT_LSX) -+ else if (SUPPORT_LSX) - gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lsx; - else - #endif -diff --git a/sysdeps/loongarch/dl-tunables.list b/sysdeps/loongarch/dl-tunables.list -deleted file mode 100644 -index 66b34275..00000000 ---- a/sysdeps/loongarch/dl-tunables.list -+++ /dev/null -@@ -1,25 +0,0 @@ --# LoongArch specific tunables. --# Copyright (C) 2023 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 --# . -- --glibc { -- cpu { -- hwcaps { -- type: STRING -- } -- } --} -diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.c b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c -deleted file mode 100644 -index 1290c4ce..00000000 ---- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.c -+++ /dev/null -@@ -1,29 +0,0 @@ --/* Initialize CPU feature data. LoongArch64 version. -- This file is part of the GNU C Library. -- Copyright (C) 2023 Free Software Foundation, Inc. -- -- The GNU C Library is free software; you can redistribute it and/or -- modify it under the terms of the GNU Lesser General Public -- License as published by the Free Software Foundation; either -- version 2.1 of the License, or (at your option) any later version. -- -- The GNU C Library is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Lesser General Public License for more details. -- -- You should have received a copy of the GNU Lesser General Public -- License along with the GNU C Library; if not, see -- . */ -- --#include --#include --#include --extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) attribute_hidden; -- --static inline void --init_cpu_features (struct cpu_features *cpu_features) --{ -- GLRO (dl_larch_cpu_features).hwcap = GLRO (dl_hwcap); -- TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps)); --} -diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h -index 450963ce..d1a280a5 100644 ---- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h -+++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h -@@ -19,23 +19,13 @@ - #ifndef _CPU_FEATURES_LOONGARCH64_H - #define _CPU_FEATURES_LOONGARCH64_H - --#include - #include - --struct cpu_features -- { -- uint64_t hwcap; -- }; -+#define SUPPORT_UAL (GLRO (dl_hwcap) & HWCAP_LOONGARCH_UAL) -+#define SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX) -+#define SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX) - --/* Get a pointer to the CPU features structure. */ --extern const struct cpu_features *_dl_larch_get_cpu_features (void) -- __attribute__ ((pure)); -- --#define SUPPORT_UAL (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_UAL) --#define SUPPORT_LSX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LSX) --#define SUPPORT_LASX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LASX) --#define RTLD_SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX) --#define RTLD_SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX) - #define INIT_ARCH() - - #endif /* _CPU_FEATURES_LOONGARCH64_H */ -+ -diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c -deleted file mode 100644 -index 6217fda9..00000000 ---- a/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c -+++ /dev/null -@@ -1,60 +0,0 @@ --/* Data for LoongArch64 version of processor capability information. -- Linux version. -- Copyright (C) 2023 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 -- . */ -- --/* If anything should be added here check whether the size of each string -- is still ok with the given array size. -- -- All the #ifdefs in the definitions are quite irritating but -- necessary if we want to avoid duplicating the information. There -- are three different modes: -- -- - PROCINFO_DECL is defined. This means we are only interested in -- declarations. -- -- - PROCINFO_DECL is not defined: -- -- + if SHARED is defined the file is included in an array -- initializer. The .element = { ... } syntax is needed. -- -- + if SHARED is not defined a normal array initialization is -- needed. -- */ -- --#ifndef PROCINFO_CLASS --# define PROCINFO_CLASS --#endif -- --#if !IS_IN (ldconfig) --# if !defined PROCINFO_DECL && defined SHARED -- ._dl_larch_cpu_features --# else --PROCINFO_CLASS struct cpu_features _dl_larch_cpu_features --# endif --# ifndef PROCINFO_DECL --= { } --# endif --# if !defined SHARED || defined PROCINFO_DECL --; --# else --, --# endif --#endif -- --#undef PROCINFO_DECL --#undef PROCINFO_CLASS -diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c -deleted file mode 100644 -index 455fd71a..00000000 ---- a/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c -+++ /dev/null -@@ -1,21 +0,0 @@ --/* Operating system support for run-time dynamic linker. LoongArch version. -- Copyright (C) 2023 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 -- . */ -- --#include --#include --#include -diff --git a/sysdeps/unix/sysv/linux/loongarch/libc-start.c b/sysdeps/unix/sysv/linux/loongarch/libc-start.c -deleted file mode 100644 -index f1346ece..00000000 ---- a/sysdeps/unix/sysv/linux/loongarch/libc-start.c -+++ /dev/null -@@ -1,34 +0,0 @@ --/* Override csu/libc-start.c on LoongArch64. -- Copyright (C) 2023 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 -- . */ -- --#ifndef SHARED -- --/* Mark symbols hidden in static PIE for early self relocation to work. */ --# if BUILD_PIE_DEFAULT --# pragma GCC visibility push(hidden) --# endif -- --# include --# include -- --extern struct cpu_features _dl_larch_cpu_features; -- --# define ARCH_INIT_CPU_FEATURES() init_cpu_features (&_dl_larch_cpu_features) -- --#endif --#include --- -2.33.0 - diff --git a/SUPPORTED b/SUPPORTED new file mode 100755 index 0000000..952f13d --- /dev/null +++ b/SUPPORTED @@ -0,0 +1,494 @@ +# This file names the currently supported and somewhat tested locales. +# If you have any additions please file a glibc bug report. +SUPPORTED-LOCALES=\ +C.UTF-8/UTF-8 \ +aa_DJ.UTF-8/UTF-8 \ +aa_DJ/ISO-8859-1 \ +aa_ER/UTF-8 \ +aa_ER@saaho/UTF-8 \ +aa_ET/UTF-8 \ +af_ZA.UTF-8/UTF-8 \ +af_ZA/ISO-8859-1 \ +agr_PE/UTF-8 \ +ak_GH/UTF-8 \ +am_ET/UTF-8 \ +an_ES.UTF-8/UTF-8 \ +an_ES/ISO-8859-15 \ +anp_IN/UTF-8 \ +ar_AE.UTF-8/UTF-8 \ +ar_AE/ISO-8859-6 \ +ar_BH.UTF-8/UTF-8 \ +ar_BH/ISO-8859-6 \ +ar_DZ.UTF-8/UTF-8 \ +ar_DZ/ISO-8859-6 \ +ar_EG.UTF-8/UTF-8 \ +ar_EG/ISO-8859-6 \ +ar_IN/UTF-8 \ +ar_IQ.UTF-8/UTF-8 \ +ar_IQ/ISO-8859-6 \ +ar_JO.UTF-8/UTF-8 \ +ar_JO/ISO-8859-6 \ +ar_KW.UTF-8/UTF-8 \ +ar_KW/ISO-8859-6 \ +ar_LB.UTF-8/UTF-8 \ +ar_LB/ISO-8859-6 \ +ar_LY.UTF-8/UTF-8 \ +ar_LY/ISO-8859-6 \ +ar_MA.UTF-8/UTF-8 \ +ar_MA/ISO-8859-6 \ +ar_OM.UTF-8/UTF-8 \ +ar_OM/ISO-8859-6 \ +ar_QA.UTF-8/UTF-8 \ +ar_QA/ISO-8859-6 \ +ar_SA.UTF-8/UTF-8 \ +ar_SA/ISO-8859-6 \ +ar_SD.UTF-8/UTF-8 \ +ar_SD/ISO-8859-6 \ +ar_SS/UTF-8 \ +ar_SY.UTF-8/UTF-8 \ +ar_SY/ISO-8859-6 \ +ar_TN.UTF-8/UTF-8 \ +ar_TN/ISO-8859-6 \ +ar_YE.UTF-8/UTF-8 \ +ar_YE/ISO-8859-6 \ +ayc_PE/UTF-8 \ +az_AZ/UTF-8 \ +az_IR/UTF-8 \ +as_IN/UTF-8 \ +ast_ES.UTF-8/UTF-8 \ +ast_ES/ISO-8859-15 \ +be_BY.UTF-8/UTF-8 \ +be_BY/CP1251 \ +be_BY@latin/UTF-8 \ +bem_ZM/UTF-8 \ +ber_DZ/UTF-8 \ +ber_MA/UTF-8 \ +bg_BG.UTF-8/UTF-8 \ +bg_BG/CP1251 \ +bhb_IN.UTF-8/UTF-8 \ +bho_IN/UTF-8 \ +bho_NP/UTF-8 \ +bi_VU/UTF-8 \ +bn_BD/UTF-8 \ +bn_IN/UTF-8 \ +bo_CN/UTF-8 \ +bo_IN/UTF-8 \ +br_FR.UTF-8/UTF-8 \ +br_FR/ISO-8859-1 \ +br_FR@euro/ISO-8859-15 \ +brx_IN/UTF-8 \ +bs_BA.UTF-8/UTF-8 \ +bs_BA/ISO-8859-2 \ +byn_ER/UTF-8 \ +ca_AD.UTF-8/UTF-8 \ +ca_AD/ISO-8859-15 \ +ca_ES.UTF-8/UTF-8 \ +ca_ES/ISO-8859-1 \ +ca_ES@euro/ISO-8859-15 \ +ca_ES@valencia/UTF-8 \ +ca_FR.UTF-8/UTF-8 \ +ca_FR/ISO-8859-15 \ +ca_IT.UTF-8/UTF-8 \ +ca_IT/ISO-8859-15 \ +ce_RU/UTF-8 \ +chr_US/UTF-8 \ +cmn_TW/UTF-8 \ +crh_UA/UTF-8 \ +cs_CZ.UTF-8/UTF-8 \ +cs_CZ/ISO-8859-2 \ +csb_PL/UTF-8 \ +cv_RU/UTF-8 \ +cy_GB.UTF-8/UTF-8 \ +cy_GB/ISO-8859-14 \ +da_DK.UTF-8/UTF-8 \ +da_DK/ISO-8859-1 \ +da_DK.ISO-8859-15/ISO-8859-15 \ +de_AT.UTF-8/UTF-8 \ +de_AT/ISO-8859-1 \ +de_AT@euro/ISO-8859-15 \ +de_BE.UTF-8/UTF-8 \ +de_BE/ISO-8859-1 \ +de_BE@euro/ISO-8859-15 \ +de_CH.UTF-8/UTF-8 \ +de_CH/ISO-8859-1 \ +de_DE.UTF-8/UTF-8 \ +de_DE/ISO-8859-1 \ +de_DE@euro/ISO-8859-15 \ +de_IT.UTF-8/UTF-8 \ +de_IT/ISO-8859-1 \ +de_LI.UTF-8/UTF-8 \ +de_LU.UTF-8/UTF-8 \ +de_LU/ISO-8859-1 \ +de_LU@euro/ISO-8859-15 \ +doi_IN/UTF-8 \ +dsb_DE/UTF-8 \ +dv_MV/UTF-8 \ +dz_BT/UTF-8 \ +el_GR.UTF-8/UTF-8 \ +el_GR/ISO-8859-7 \ +el_GR@euro/ISO-8859-7 \ +el_CY.UTF-8/UTF-8 \ +el_CY/ISO-8859-7 \ +en_AG/UTF-8 \ +en_AU.UTF-8/UTF-8 \ +en_AU/ISO-8859-1 \ +en_BW.UTF-8/UTF-8 \ +en_BW/ISO-8859-1 \ +en_CA.UTF-8/UTF-8 \ +en_CA/ISO-8859-1 \ +en_DK.UTF-8/UTF-8 \ +en_DK/ISO-8859-1 \ +en_GB.UTF-8/UTF-8 \ +en_GB/ISO-8859-1 \ +en_GB.ISO-8859-15/ISO-8859-15 \ +en_HK.UTF-8/UTF-8 \ +en_HK/ISO-8859-1 \ +en_IE.UTF-8/UTF-8 \ +en_IE/ISO-8859-1 \ +en_IE@euro/ISO-8859-15 \ +en_IL/UTF-8 \ +en_IN/UTF-8 \ +en_NG/UTF-8 \ +en_NZ.UTF-8/UTF-8 \ +en_NZ/ISO-8859-1 \ +en_PH.UTF-8/UTF-8 \ +en_PH/ISO-8859-1 \ +en_SC.UTF-8/UTF-8 \ +en_SG.UTF-8/UTF-8 \ +en_SG/ISO-8859-1 \ +en_US.UTF-8/UTF-8 \ +en_US/ISO-8859-1 \ +en_US.ISO-8859-15/ISO-8859-15 \ +en_ZA.UTF-8/UTF-8 \ +en_ZA/ISO-8859-1 \ +en_ZM/UTF-8 \ +en_ZW.UTF-8/UTF-8 \ +en_ZW/ISO-8859-1 \ +eo/UTF-8 \ +es_AR.UTF-8/UTF-8 \ +es_AR/ISO-8859-1 \ +es_BO.UTF-8/UTF-8 \ +es_BO/ISO-8859-1 \ +es_CL.UTF-8/UTF-8 \ +es_CL/ISO-8859-1 \ +es_CO.UTF-8/UTF-8 \ +es_CO/ISO-8859-1 \ +es_CR.UTF-8/UTF-8 \ +es_CR/ISO-8859-1 \ +es_CU/UTF-8 \ +es_DO.UTF-8/UTF-8 \ +es_DO/ISO-8859-1 \ +es_EC.UTF-8/UTF-8 \ +es_EC/ISO-8859-1 \ +es_ES.UTF-8/UTF-8 \ +es_ES/ISO-8859-1 \ +es_ES@euro/ISO-8859-15 \ +es_GT.UTF-8/UTF-8 \ +es_GT/ISO-8859-1 \ +es_HN.UTF-8/UTF-8 \ +es_HN/ISO-8859-1 \ +es_MX.UTF-8/UTF-8 \ +es_MX/ISO-8859-1 \ +es_NI.UTF-8/UTF-8 \ +es_NI/ISO-8859-1 \ +es_PA.UTF-8/UTF-8 \ +es_PA/ISO-8859-1 \ +es_PE.UTF-8/UTF-8 \ +es_PE/ISO-8859-1 \ +es_PR.UTF-8/UTF-8 \ +es_PR/ISO-8859-1 \ +es_PY.UTF-8/UTF-8 \ +es_PY/ISO-8859-1 \ +es_SV.UTF-8/UTF-8 \ +es_SV/ISO-8859-1 \ +es_US.UTF-8/UTF-8 \ +es_US/ISO-8859-1 \ +es_UY.UTF-8/UTF-8 \ +es_UY/ISO-8859-1 \ +es_VE.UTF-8/UTF-8 \ +es_VE/ISO-8859-1 \ +et_EE.UTF-8/UTF-8 \ +et_EE/ISO-8859-1 \ +et_EE.ISO-8859-15/ISO-8859-15 \ +eu_ES.UTF-8/UTF-8 \ +eu_ES/ISO-8859-1 \ +eu_ES@euro/ISO-8859-15 \ +fa_IR/UTF-8 \ +ff_SN/UTF-8 \ +fi_FI.UTF-8/UTF-8 \ +fi_FI/ISO-8859-1 \ +fi_FI@euro/ISO-8859-15 \ +fil_PH/UTF-8 \ +fo_FO.UTF-8/UTF-8 \ +fo_FO/ISO-8859-1 \ +fr_BE.UTF-8/UTF-8 \ +fr_BE/ISO-8859-1 \ +fr_BE@euro/ISO-8859-15 \ +fr_CA.UTF-8/UTF-8 \ +fr_CA/ISO-8859-1 \ +fr_CH.UTF-8/UTF-8 \ +fr_CH/ISO-8859-1 \ +fr_FR.UTF-8/UTF-8 \ +fr_FR/ISO-8859-1 \ +fr_FR@euro/ISO-8859-15 \ +fr_LU.UTF-8/UTF-8 \ +fr_LU/ISO-8859-1 \ +fr_LU@euro/ISO-8859-15 \ +fur_IT/UTF-8 \ +fy_NL/UTF-8 \ +fy_DE/UTF-8 \ +ga_IE.UTF-8/UTF-8 \ +ga_IE/ISO-8859-1 \ +ga_IE@euro/ISO-8859-15 \ +gd_GB.UTF-8/UTF-8 \ +gd_GB/ISO-8859-15 \ +gez_ER/UTF-8 \ +gez_ER@abegede/UTF-8 \ +gez_ET/UTF-8 \ +gez_ET@abegede/UTF-8 \ +gl_ES.UTF-8/UTF-8 \ +gl_ES/ISO-8859-1 \ +gl_ES@euro/ISO-8859-15 \ +gu_IN/UTF-8 \ +gv_GB.UTF-8/UTF-8 \ +gv_GB/ISO-8859-1 \ +ha_NG/UTF-8 \ +hak_TW/UTF-8 \ +he_IL.UTF-8/UTF-8 \ +he_IL/ISO-8859-8 \ +hi_IN/UTF-8 \ +hif_FJ/UTF-8 \ +hne_IN/UTF-8 \ +hr_HR.UTF-8/UTF-8 \ +hr_HR/ISO-8859-2 \ +hsb_DE/ISO-8859-2 \ +hsb_DE.UTF-8/UTF-8 \ +ht_HT/UTF-8 \ +hu_HU.UTF-8/UTF-8 \ +hu_HU/ISO-8859-2 \ +hy_AM/UTF-8 \ +hy_AM.ARMSCII-8/ARMSCII-8 \ +ia_FR/UTF-8 \ +id_ID.UTF-8/UTF-8 \ +id_ID/ISO-8859-1 \ +ig_NG/UTF-8 \ +ik_CA/UTF-8 \ +is_IS.UTF-8/UTF-8 \ +is_IS/ISO-8859-1 \ +it_CH.UTF-8/UTF-8 \ +it_CH/ISO-8859-1 \ +it_IT.UTF-8/UTF-8 \ +it_IT/ISO-8859-1 \ +it_IT@euro/ISO-8859-15 \ +iu_CA/UTF-8 \ +ja_JP.EUC-JP/EUC-JP \ +ja_JP.UTF-8/UTF-8 \ +ka_GE.UTF-8/UTF-8 \ +ka_GE/GEORGIAN-PS \ +kab_DZ/UTF-8 \ +kk_KZ.UTF-8/UTF-8 \ +kk_KZ/PT154 \ +kl_GL.UTF-8/UTF-8 \ +kl_GL/ISO-8859-1 \ +km_KH/UTF-8 \ +kn_IN/UTF-8 \ +ko_KR.EUC-KR/EUC-KR \ +ko_KR.UTF-8/UTF-8 \ +kok_IN/UTF-8 \ +ks_IN/UTF-8 \ +ks_IN@devanagari/UTF-8 \ +ku_TR.UTF-8/UTF-8 \ +ku_TR/ISO-8859-9 \ +kw_GB.UTF-8/UTF-8 \ +kw_GB/ISO-8859-1 \ +ky_KG/UTF-8 \ +lb_LU/UTF-8 \ +lg_UG.UTF-8/UTF-8 \ +lg_UG/ISO-8859-10 \ +li_BE/UTF-8 \ +li_NL/UTF-8 \ +lij_IT/UTF-8 \ +ln_CD/UTF-8 \ +lo_LA/UTF-8 \ +lt_LT.UTF-8/UTF-8 \ +lt_LT/ISO-8859-13 \ +lv_LV.UTF-8/UTF-8 \ +lv_LV/ISO-8859-13 \ +lzh_TW/UTF-8 \ +mag_IN/UTF-8 \ +mai_IN/UTF-8 \ +mai_NP/UTF-8 \ +mfe_MU/UTF-8 \ +mg_MG.UTF-8/UTF-8 \ +mg_MG/ISO-8859-15 \ +mhr_RU/UTF-8 \ +mi_NZ.UTF-8/UTF-8 \ +mi_NZ/ISO-8859-13 \ +miq_NI/UTF-8 \ +mjw_IN/UTF-8 \ +mk_MK.UTF-8/UTF-8 \ +mk_MK/ISO-8859-5 \ +ml_IN/UTF-8 \ +mn_MN/UTF-8 \ +mni_IN/UTF-8 \ +mr_IN/UTF-8 \ +ms_MY.UTF-8/UTF-8 \ +ms_MY/ISO-8859-1 \ +mt_MT.UTF-8/UTF-8 \ +mt_MT/ISO-8859-3 \ +my_MM/UTF-8 \ +nan_TW/UTF-8 \ +nan_TW@latin/UTF-8 \ +nb_NO.UTF-8/UTF-8 \ +nb_NO/ISO-8859-1 \ +nds_DE/UTF-8 \ +nds_NL/UTF-8 \ +ne_NP/UTF-8 \ +nhn_MX/UTF-8 \ +niu_NU/UTF-8 \ +niu_NZ/UTF-8 \ +nl_AW/UTF-8 \ +nl_BE.UTF-8/UTF-8 \ +nl_BE/ISO-8859-1 \ +nl_BE@euro/ISO-8859-15 \ +nl_NL.UTF-8/UTF-8 \ +nl_NL/ISO-8859-1 \ +nl_NL@euro/ISO-8859-15 \ +nn_NO.UTF-8/UTF-8 \ +nn_NO/ISO-8859-1 \ +nr_ZA/UTF-8 \ +nso_ZA/UTF-8 \ +oc_FR.UTF-8/UTF-8 \ +oc_FR/ISO-8859-1 \ +om_ET/UTF-8 \ +om_KE.UTF-8/UTF-8 \ +om_KE/ISO-8859-1 \ +or_IN/UTF-8 \ +os_RU/UTF-8 \ +pa_IN/UTF-8 \ +pa_PK/UTF-8 \ +pap_AW/UTF-8 \ +pap_CW/UTF-8 \ +pl_PL.UTF-8/UTF-8 \ +pl_PL/ISO-8859-2 \ +ps_AF/UTF-8 \ +pt_BR.UTF-8/UTF-8 \ +pt_BR/ISO-8859-1 \ +pt_PT.UTF-8/UTF-8 \ +pt_PT/ISO-8859-1 \ +pt_PT@euro/ISO-8859-15 \ +quz_PE/UTF-8 \ +raj_IN/UTF-8 \ +ro_RO.UTF-8/UTF-8 \ +ro_RO/ISO-8859-2 \ +ru_RU.KOI8-R/KOI8-R \ +ru_RU.UTF-8/UTF-8 \ +ru_RU/ISO-8859-5 \ +ru_UA.UTF-8/UTF-8 \ +ru_UA/KOI8-U \ +rw_RW/UTF-8 \ +sa_IN/UTF-8 \ +sah_RU/UTF-8 \ +sat_IN/UTF-8 \ +sc_IT/UTF-8 \ +sd_IN/UTF-8 \ +sd_IN@devanagari/UTF-8 \ +se_NO/UTF-8 \ +sgs_LT/UTF-8 \ +shn_MM/UTF-8 \ +shs_CA/UTF-8 \ +si_LK/UTF-8 \ +sid_ET/UTF-8 \ +sk_SK.UTF-8/UTF-8 \ +sk_SK/ISO-8859-2 \ +sl_SI.UTF-8/UTF-8 \ +sl_SI/ISO-8859-2 \ +sm_WS/UTF-8 \ +so_DJ.UTF-8/UTF-8 \ +so_DJ/ISO-8859-1 \ +so_ET/UTF-8 \ +so_KE.UTF-8/UTF-8 \ +so_KE/ISO-8859-1 \ +so_SO.UTF-8/UTF-8 \ +so_SO/ISO-8859-1 \ +sq_AL.UTF-8/UTF-8 \ +sq_AL/ISO-8859-1 \ +sq_MK/UTF-8 \ +sr_ME/UTF-8 \ +sr_RS/UTF-8 \ +sr_RS@latin/UTF-8 \ +ss_ZA/UTF-8 \ +st_ZA.UTF-8/UTF-8 \ +st_ZA/ISO-8859-1 \ +sv_FI.UTF-8/UTF-8 \ +sv_FI/ISO-8859-1 \ +sv_FI@euro/ISO-8859-15 \ +sv_SE.UTF-8/UTF-8 \ +sv_SE/ISO-8859-1 \ +sv_SE.ISO-8859-15/ISO-8859-15 \ +sw_KE/UTF-8 \ +sw_TZ/UTF-8 \ +szl_PL/UTF-8 \ +ta_IN/UTF-8 \ +ta_LK/UTF-8 \ +tcy_IN.UTF-8/UTF-8 \ +te_IN/UTF-8 \ +tg_TJ.UTF-8/UTF-8 \ +tg_TJ/KOI8-T \ +th_TH.UTF-8/UTF-8 \ +th_TH/TIS-620 \ +the_NP/UTF-8 \ +ti_ER/UTF-8 \ +ti_ET/UTF-8 \ +tig_ER/UTF-8 \ +tk_TM/UTF-8 \ +tl_PH.UTF-8/UTF-8 \ +tl_PH/ISO-8859-1 \ +tn_ZA/UTF-8 \ +to_TO/UTF-8 \ +tpi_PG/UTF-8 \ +tr_CY.UTF-8/UTF-8 \ +tr_CY/ISO-8859-9 \ +tr_TR.UTF-8/UTF-8 \ +tr_TR/ISO-8859-9 \ +ts_ZA/UTF-8 \ +tt_RU/UTF-8 \ +tt_RU@iqtelif/UTF-8 \ +ug_CN/UTF-8 \ +uk_UA.UTF-8/UTF-8 \ +uk_UA/KOI8-U \ +unm_US/UTF-8 \ +ur_IN/UTF-8 \ +ur_PK/UTF-8 \ +uz_UZ.UTF-8/UTF-8 \ +uz_UZ/ISO-8859-1 \ +uz_UZ@cyrillic/UTF-8 \ +ve_ZA/UTF-8 \ +vi_VN/UTF-8 \ +wa_BE/ISO-8859-1 \ +wa_BE@euro/ISO-8859-15 \ +wa_BE.UTF-8/UTF-8 \ +wae_CH/UTF-8 \ +wal_ET/UTF-8 \ +wo_SN/UTF-8 \ +xh_ZA.UTF-8/UTF-8 \ +xh_ZA/ISO-8859-1 \ +yi_US.UTF-8/UTF-8 \ +yi_US/CP1255 \ +yo_NG/UTF-8 \ +yue_HK/UTF-8 \ +yuw_PG/UTF-8 \ +zh_CN.GB18030/GB18030 \ +zh_CN.GBK/GBK \ +zh_CN.UTF-8/UTF-8 \ +zh_CN/GB2312 \ +zh_HK.UTF-8/UTF-8 \ +zh_HK/BIG5-HKSCS \ +zh_SG.UTF-8/UTF-8 \ +zh_SG.GBK/GBK \ +zh_SG/GB2312 \ +zh_TW.EUC-TW/EUC-TW \ +zh_TW.UTF-8/UTF-8 \ +zh_TW/BIG5 \ +zu_ZA.UTF-8/UTF-8 \ +zu_ZA/ISO-8859-1 \ diff --git a/bench.mk b/bench.mk old mode 100644 new mode 100755 diff --git a/build-locale-archive.c b/build-locale-archive.c new file mode 100755 index 0000000..9183972 --- /dev/null +++ b/build-locale-archive.c @@ -0,0 +1,862 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../locale/hashval.h" +#define __LC_LAST 13 +#include "../locale/locarchive.h" +#include "../crypt/md5.h" + +const char *alias_file = DATADIR "/locale/locale.alias"; +const char *locar_file = PREFIX "/lib/locale/locale-archive"; +const char *tmpl_file = PREFIX "/lib/locale/locale-archive.tmpl"; +const char *loc_path = PREFIX "/lib/locale/"; +/* Flags set by `--verbose` option. */ +int be_quiet = 1; +int verbose = 0; +int max_locarchive_open_retry = 10; +const char *output_prefix; + +/* Endianness should have been taken care of by localedef. We don't need to do + additional swapping. We need this variable exported however, since + locarchive.c uses it to determine if it needs to swap endianness of a value + before writing to or reading from the archive. */ +bool swap_endianness_p = false; + +static const char *locnames[] = + { +#define DEFINE_CATEGORY(category, category_name, items, a) \ + [category] = category_name, +#include "../locale/categories.def" +#undef DEFINE_CATEGORY + }; + +static int +is_prime (unsigned long candidate) +{ + /* No even number and none less than 10 will be passed here. */ + unsigned long int divn = 3; + unsigned long int sq = divn * divn; + + while (sq < candidate && candidate % divn != 0) + { + ++divn; + sq += 4 * divn; + ++divn; + } + + return candidate % divn != 0; +} + +unsigned long +next_prime (unsigned long seed) +{ + /* Make it definitely odd. */ + seed |= 1; + + while (!is_prime (seed)) + seed += 2; + + return seed; +} + +void +error (int status, int errnum, const char *message, ...) +{ + va_list args; + + va_start (args, message); + fflush (stdout); + fprintf (stderr, "%s: ", program_invocation_name); + vfprintf (stderr, message, args); + va_end (args); + if (errnum) + fprintf (stderr, ": %s", strerror (errnum)); + putc ('\n', stderr); + fflush (stderr); + if (status) + exit (errnum == EROFS ? 0 : status); +} + +void * +xmalloc (size_t size) +{ + void *p = malloc (size); + if (p == NULL) + error (EXIT_FAILURE, errno, "could not allocate %zd bytes of memory", size); + return p; +} + +static void +open_tmpl_archive (struct locarhandle *ah) +{ + struct stat64 st; + int fd; + struct locarhead head; + const char *archivefname = ah->fname == NULL ? tmpl_file : ah->fname; + + /* Open the archive. We must have exclusive write access. */ + fd = open64 (archivefname, O_RDONLY); + if (fd == -1) + error (EXIT_FAILURE, errno, "cannot open locale archive template file \"%s\"", + archivefname); + + if (fstat64 (fd, &st) < 0) + error (EXIT_FAILURE, errno, "cannot stat locale archive template file \"%s\"", + archivefname); + + /* Read the header. */ + if (TEMP_FAILURE_RETRY (read (fd, &head, sizeof (head))) != sizeof (head)) + error (EXIT_FAILURE, errno, "cannot read archive header"); + + ah->fd = fd; + ah->mmaped = (head.sumhash_offset + + head.sumhash_size * sizeof (struct sumhashent)); + if (ah->mmaped > (unsigned long) st.st_size) + error (EXIT_FAILURE, 0, "locale archive template file truncated"); + ah->mmaped = st.st_size; + ah->reserved = st.st_size; + + /* Now we know how large the administrative information part is. + Map all of it. */ + ah->addr = mmap64 (NULL, ah->mmaped, PROT_READ, MAP_SHARED, fd, 0); + if (ah->addr == MAP_FAILED) + error (EXIT_FAILURE, errno, "cannot map archive header"); +} + +/* Open the locale archive. */ +extern void open_archive (struct locarhandle *ah, bool readonly); + +/* Close the locale archive. */ +extern void close_archive (struct locarhandle *ah); + +/* Add given locale data to the archive. */ +extern int add_locale_to_archive (struct locarhandle *ah, const char *name, + locale_data_t data, bool replace); + +extern void add_alias (struct locarhandle *ah, const char *alias, + bool replace, const char *oldname, + uint32_t *locrec_offset_p); + +extern struct namehashent * +insert_name (struct locarhandle *ah, + const char *name, size_t name_len, bool replace); + +struct nameent +{ + char *name; + struct locrecent *locrec; +}; + +struct dataent +{ + const unsigned char *sum; + uint32_t file_offset; +}; + +static int +nameentcmp (const void *a, const void *b) +{ + struct locrecent *la = ((const struct nameent *) a)->locrec; + struct locrecent *lb = ((const struct nameent *) b)->locrec; + uint32_t start_a = -1, end_a = 0; + uint32_t start_b = -1, end_b = 0; + int cnt; + + for (cnt = 0; cnt < __LC_LAST; ++cnt) + if (cnt != LC_ALL) + { + if (la->record[cnt].offset < start_a) + start_a = la->record[cnt].offset; + if (la->record[cnt].offset + la->record[cnt].len > end_a) + end_a = la->record[cnt].offset + la->record[cnt].len; + } + assert (start_a != (uint32_t)-1); + assert (end_a != 0); + + for (cnt = 0; cnt < __LC_LAST; ++cnt) + if (cnt != LC_ALL) + { + if (lb->record[cnt].offset < start_b) + start_b = lb->record[cnt].offset; + if (lb->record[cnt].offset + lb->record[cnt].len > end_b) + end_b = lb->record[cnt].offset + lb->record[cnt].len; + } + assert (start_b != (uint32_t)-1); + assert (end_b != 0); + + if (start_a != start_b) + return (int)start_a - (int)start_b; + return (int)end_a - (int)end_b; +} + +static int +dataentcmp (const void *a, const void *b) +{ + if (((const struct dataent *) a)->file_offset + < ((const struct dataent *) b)->file_offset) + return -1; + + if (((const struct dataent *) a)->file_offset + > ((const struct dataent *) b)->file_offset) + return 1; + + return 0; +} + +static int +sumsearchfn (const void *key, const void *ent) +{ + uint32_t keyn = *(uint32_t *)key; + uint32_t entn = ((struct dataent *)ent)->file_offset; + + if (keyn < entn) + return -1; + if (keyn > entn) + return 1; + return 0; +} + +static void +compute_data (struct locarhandle *ah, struct nameent *name, size_t sumused, + struct dataent *files, locale_data_t data) +{ + int cnt; + struct locrecent *locrec = name->locrec; + struct dataent *file; + data[LC_ALL].addr = ((char *) ah->addr) + locrec->record[LC_ALL].offset; + data[LC_ALL].size = locrec->record[LC_ALL].len; + for (cnt = 0; cnt < __LC_LAST; ++cnt) + if (cnt != LC_ALL) + { + data[cnt].addr = ((char *) ah->addr) + locrec->record[cnt].offset; + data[cnt].size = locrec->record[cnt].len; + if (data[cnt].addr >= data[LC_ALL].addr + && data[cnt].addr + data[cnt].size + <= data[LC_ALL].addr + data[LC_ALL].size) + __md5_buffer (data[cnt].addr, data[cnt].size, data[cnt].sum); + else + { + file = bsearch (&locrec->record[cnt].offset, files, sumused, + sizeof (*files), sumsearchfn); + if (file == NULL) + error (EXIT_FAILURE, 0, "inconsistent template file"); + memcpy (data[cnt].sum, file->sum, sizeof (data[cnt].sum)); + } + } +} + +static int +fill_archive (struct locarhandle *tmpl_ah, + const char *fname, + size_t install_langs_count, char *install_langs_list[], + size_t nlist, char *list[], + const char *primary) +{ + struct locarhandle ah; + struct locarhead *head; + int result = 0; + struct nameent *names; + struct namehashent *namehashtab; + size_t cnt, used; + struct dataent *files; + struct sumhashent *sumhashtab; + size_t sumused; + struct locrecent *primary_locrec = NULL; + struct nameent *primary_nameent = NULL; + + head = tmpl_ah->addr; + names = (struct nameent *) malloc (head->namehash_used + * sizeof (struct nameent)); + files = (struct dataent *) malloc (head->sumhash_used + * sizeof (struct dataent)); + if (names == NULL || files == NULL) + error (EXIT_FAILURE, errno, "could not allocate tables"); + + namehashtab = (struct namehashent *) ((char *) tmpl_ah->addr + + head->namehash_offset); + sumhashtab = (struct sumhashent *) ((char *) tmpl_ah->addr + + head->sumhash_offset); + + for (cnt = used = 0; cnt < head->namehash_size; ++cnt) + if (namehashtab[cnt].locrec_offset != 0) + { + char * name; + int i; + assert (used < head->namehash_used); + name = tmpl_ah->addr + namehashtab[cnt].name_offset; + if (install_langs_count == 0) + { + /* Always intstall the entry. */ + names[used].name = name; + names[used++].locrec + = (struct locrecent *) ((char *) tmpl_ah->addr + + namehashtab[cnt].locrec_offset); + } + else + { + /* Only install the entry if the user asked for it via + --install-langs. */ + for (i = 0; i < install_langs_count; i++) + { + /* Add one for "_" and one for the null terminator. */ + size_t len = strlen (install_langs_list[i]) + 2; + char *install_lang = (char *)xmalloc (len); + strcpy (install_lang, install_langs_list[i]); + if (strchr (install_lang, '_') == NULL) + strcat (install_lang, "_"); + if (strncmp (name, install_lang, strlen (install_lang)) == 0) + { + names[used].name = name; + names[used++].locrec + = (struct locrecent *) ((char *)tmpl_ah->addr + + namehashtab[cnt].locrec_offset); + } + free (install_lang); + } + } + } + + /* Sort the names. */ + qsort (names, used, sizeof (struct nameent), nameentcmp); + + for (cnt = sumused = 0; cnt < head->sumhash_size; ++cnt) + if (sumhashtab[cnt].file_offset != 0) + { + assert (sumused < head->sumhash_used); + files[sumused].sum = (const unsigned char *) sumhashtab[cnt].sum; + files[sumused++].file_offset = sumhashtab[cnt].file_offset; + } + + /* Sort by file locations. */ + qsort (files, sumused, sizeof (struct dataent), dataentcmp); + + /* Open the archive. This call never returns if we cannot + successfully open the archive. */ + ah.fname = NULL; + if (fname != NULL) + ah.fname = fname; + open_archive (&ah, false); + + if (primary != NULL) + { + for (cnt = 0; cnt < used; ++cnt) + if (strcmp (names[cnt].name, primary) == 0) + break; + if (cnt < used) + { + locale_data_t data; + + compute_data (tmpl_ah, &names[cnt], sumused, files, data); + result |= add_locale_to_archive (&ah, primary, data, 0); + primary_locrec = names[cnt].locrec; + primary_nameent = &names[cnt]; + } + } + + for (cnt = 0; cnt < used; ++cnt) + if (&names[cnt] == primary_nameent) + continue; + else if ((cnt > 0 && names[cnt - 1].locrec == names[cnt].locrec) + || names[cnt].locrec == primary_locrec) + { + const char *oldname; + struct namehashent *namehashent; + uint32_t locrec_offset; + + if (names[cnt].locrec == primary_locrec) + oldname = primary; + else + oldname = names[cnt - 1].name; + namehashent = insert_name (&ah, oldname, strlen (oldname), true); + assert (namehashent->name_offset != 0); + assert (namehashent->locrec_offset != 0); + locrec_offset = namehashent->locrec_offset; + add_alias (&ah, names[cnt].name, 0, oldname, &locrec_offset); + } + else + { + locale_data_t data; + + compute_data (tmpl_ah, &names[cnt], sumused, files, data); + result |= add_locale_to_archive (&ah, names[cnt].name, data, 0); + } + + while (nlist-- > 0) + { + const char *fname = *list++; + size_t fnamelen = strlen (fname); + struct stat64 st; + DIR *dirp; + struct dirent64 *d; + int seen; + locale_data_t data; + int cnt; + + /* First see whether this really is a directory and whether it + contains all the require locale category files. */ + if (stat64 (fname, &st) < 0) + { + error (0, 0, "stat of \"%s\" failed: %s: ignored", fname, + strerror (errno)); + continue; + } + if (!S_ISDIR (st.st_mode)) + { + error (0, 0, "\"%s\" is no directory; ignored", fname); + continue; + } + + dirp = opendir (fname); + if (dirp == NULL) + { + error (0, 0, "cannot open directory \"%s\": %s: ignored", + fname, strerror (errno)); + continue; + } + + seen = 0; + while ((d = readdir64 (dirp)) != NULL) + { + for (cnt = 0; cnt < __LC_LAST; ++cnt) + if (cnt != LC_ALL) + if (strcmp (d->d_name, locnames[cnt]) == 0) + { + unsigned char d_type; + + /* We have an object of the required name. If it's + a directory we have to look at a file with the + prefix "SYS_". Otherwise we have found what we + are looking for. */ +#ifdef _DIRENT_HAVE_D_TYPE + d_type = d->d_type; + + if (d_type != DT_REG) +#endif + { + char fullname[fnamelen + 2 * strlen (d->d_name) + 7]; + +#ifdef _DIRENT_HAVE_D_TYPE + if (d_type == DT_UNKNOWN) +#endif + { + strcpy (stpcpy (stpcpy (fullname, fname), "/"), + d->d_name); + + if (stat64 (fullname, &st) == -1) + /* We cannot stat the file, ignore it. */ + break; + + d_type = IFTODT (st.st_mode); + } + + if (d_type == DT_DIR) + { + /* We have to do more tests. The file is a + directory and it therefore must contain a + regular file with the same name except a + "SYS_" prefix. */ + char *t = stpcpy (stpcpy (fullname, fname), "/"); + strcpy (stpcpy (stpcpy (t, d->d_name), "/SYS_"), + d->d_name); + + if (stat64 (fullname, &st) == -1) + /* There is no SYS_* file or we cannot + access it. */ + break; + + d_type = IFTODT (st.st_mode); + } + } + + /* If we found a regular file (eventually after + following a symlink) we are successful. */ + if (d_type == DT_REG) + ++seen; + break; + } + } + + closedir (dirp); + + if (seen != __LC_LAST - 1) + { + /* We don't have all locale category files. Ignore the name. */ + error (0, 0, "incomplete set of locale files in \"%s\"", + fname); + continue; + } + + /* Add the files to the archive. To do this we first compute + sizes and the MD5 sums of all the files. */ + for (cnt = 0; cnt < __LC_LAST; ++cnt) + if (cnt != LC_ALL) + { + char fullname[fnamelen + 2 * strlen (locnames[cnt]) + 7]; + int fd; + + strcpy (stpcpy (stpcpy (fullname, fname), "/"), locnames[cnt]); + fd = open64 (fullname, O_RDONLY); + if (fd == -1 || fstat64 (fd, &st) == -1) + { + /* Cannot read the file. */ + if (fd != -1) + close (fd); + break; + } + + if (S_ISDIR (st.st_mode)) + { + char *t; + close (fd); + t = stpcpy (stpcpy (fullname, fname), "/"); + strcpy (stpcpy (stpcpy (t, locnames[cnt]), "/SYS_"), + locnames[cnt]); + + fd = open64 (fullname, O_RDONLY); + if (fd == -1 || fstat64 (fd, &st) == -1 + || !S_ISREG (st.st_mode)) + { + if (fd != -1) + close (fd); + break; + } + } + + /* Map the file. */ + data[cnt].addr = mmap64 (NULL, st.st_size, PROT_READ, MAP_SHARED, + fd, 0); + if (data[cnt].addr == MAP_FAILED) + { + /* Cannot map it. */ + close (fd); + break; + } + + data[cnt].size = st.st_size; + __md5_buffer (data[cnt].addr, st.st_size, data[cnt].sum); + + /* We don't need the file descriptor anymore. */ + close (fd); + } + + if (cnt != __LC_LAST) + { + while (cnt-- > 0) + if (cnt != LC_ALL) + munmap (data[cnt].addr, data[cnt].size); + + error (0, 0, "cannot read all files in \"%s\": ignored", fname); + + continue; + } + + result |= add_locale_to_archive (&ah, basename (fname), data, 0); + + for (cnt = 0; cnt < __LC_LAST; ++cnt) + if (cnt != LC_ALL) + munmap (data[cnt].addr, data[cnt].size); + } + + /* We are done. */ + close_archive (&ah); + + return result; +} + +void usage() +{ + printf ("\ +Usage: build-locale-archive [OPTION]... [TEMPLATE-FILE] [ARCHIVE-FILE]\n\ + Builds a locale archive from a template file.\n\ + Options:\n\ + -h, --help Print this usage message.\n\ + -v, --verbose Verbose execution.\n\ + -l, --install-langs=LIST Only include locales given in LIST into the \n\ + locale archive. LIST is a colon separated list\n\ + of locale prefixes, for example \"de:en:ja\".\n\ + The special argument \"all\" means to install\n\ + all languages and it must be present by itself.\n\ + If \"all\" is present with any other language it\n\ + will be treated as the name of a locale.\n\ + If the --install-langs option is missing, all\n\ + locales are installed. The colon separated list\n\ + can contain any strings matching the beginning of\n\ + locale names.\n\ + If a string does not contain a \"_\", it is added.\n\ + Examples:\n\ + --install-langs=\"en\"\n\ + installs en_US, en_US.iso88591,\n\ + en_US.iso885915, en_US.utf8,\n\ + en_GB ...\n\ + --install-langs=\"en_US.utf8\"\n\ + installs only en_US.utf8.\n\ + --install-langs=\"ko\"\n\ + installs ko_KR, ko_KR.euckr,\n\ + ko_KR.utf8 but *not* kok_IN\n\ + because \"ko\" does not contain\n\ + \"_\" and it is silently added\n\ + --install-langs\"ko:kok\"\n\ + installs ko_KR, ko_KR.euckr,\n\ + ko_KR.utf8, kok_IN, and\n\ + kok_IN.utf8.\n\ + --install-langs=\"POSIX\" will\n\ + installs *no* locales at all\n\ + because POSIX matches none of\n\ + the locales. Actually, any string\n\ + matching nothing will do that.\n\ + POSIX and C will always be\n\ + available because they are\n\ + builtin.\n\ + Aliases are installed as well,\n\ + i.e. --install-langs=\"de\"\n\ + will install not only every locale starting with\n\ + \"de\" but also the aliases \"deutsch\"\n\ + and and \"german\" although the latter does not\n\ + start with \"de\".\n\ +\n\ + If the arguments TEMPLATE-FILE and ARCHIVE-FILE are not given the locations\n\ + where the glibc used expects these files are used by default.\n\ +"); +} + +int main (int argc, char *argv[]) +{ + char path[4096]; + DIR *dirp; + struct dirent64 *d; + struct stat64 st; + char *list[16384], *primary; + char *lang; + int install_langs_count = 0; + int i; + char *install_langs_arg, *ila_start; + char **install_langs_list = NULL; + unsigned int cnt = 0; + struct locarhandle tmpl_ah; + char *new_locar_fname = NULL; + size_t loc_path_len = strlen (loc_path); + + while (1) + { + int c; + + static struct option long_options[] = + { + {"help", no_argument, 0, 'h'}, + {"verbose", no_argument, 0, 'v'}, + {"install-langs", required_argument, 0, 'l'}, + {0, 0, 0, 0} + }; + /* getopt_long stores the option index here. */ + int option_index = 0; + + c = getopt_long (argc, argv, "vhl:", + long_options, &option_index); + + /* Detect the end of the options. */ + if (c == -1) + break; + + switch (c) + { + case 0: + printf ("unknown option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + usage (); + exit (1); + + case 'v': + verbose = 1; + be_quiet = 0; + break; + + case 'h': + usage (); + exit (0); + + case 'l': + install_langs_arg = ila_start = strdup (optarg); + /* If the argument to --install-lang is "all", do + not limit the list of languages to install and install + them all. We do not support installing a single locale + called "all". */ +#define MAGIC_INSTALL_ALL "all" + if (install_langs_arg != NULL + && install_langs_arg[0] != '\0' + && !(strncmp(install_langs_arg, MAGIC_INSTALL_ALL, + strlen(MAGIC_INSTALL_ALL)) == 0 + && strlen (install_langs_arg) == 3)) + { + /* Count the number of languages we will install. */ + while (true) + { + lang = strtok(install_langs_arg, ":;,"); + if (lang == NULL) + break; + install_langs_count++; + install_langs_arg = NULL; + } + free (ila_start); + + /* Reject an entire string made up of delimiters. */ + if (install_langs_count == 0) + break; + + /* Copy the list. */ + install_langs_list = (char **)xmalloc (sizeof(char *) * install_langs_count); + install_langs_arg = ila_start = strdup (optarg); + install_langs_count = 0; + while (true) + { + lang = strtok(install_langs_arg, ":;,"); + if (lang == NULL) + break; + install_langs_list[install_langs_count] = lang; + install_langs_count++; + install_langs_arg = NULL; + } + } + break; + + case '?': + /* getopt_long already printed an error message. */ + usage (); + exit (0); + + default: + abort (); + } + } + tmpl_ah.fname = NULL; + if (optind < argc) + tmpl_ah.fname = argv[optind]; + if (optind + 1 < argc) + new_locar_fname = argv[optind + 1]; + if (verbose) + { + if (tmpl_ah.fname) + printf("input archive file specified on command line: %s\n", + tmpl_ah.fname); + else + printf("using default input archive file.\n"); + if (new_locar_fname) + printf("output archive file specified on command line: %s\n", + new_locar_fname); + else + printf("using default output archive file.\n"); + } + + dirp = opendir (loc_path); + if (dirp == NULL) + error (EXIT_FAILURE, errno, "cannot open directory \"%s\"", loc_path); + + open_tmpl_archive (&tmpl_ah); + + if (new_locar_fname) + unlink (new_locar_fname); + else + unlink (locar_file); + primary = getenv ("LC_ALL"); + if (primary == NULL) + primary = getenv ("LANG"); + if (primary != NULL) + { + if (strncmp (primary, "ja", 2) != 0 + && strncmp (primary, "ko", 2) != 0 + && strncmp (primary, "zh", 2) != 0) + { + char *ptr = malloc (strlen (primary) + strlen (".utf8") + 1), *p, *q; + /* This leads to invalid locales sometimes: + de_DE.iso885915@euro -> de_DE.utf8@euro */ + if (ptr != NULL) + { + p = ptr; + q = primary; + while (*q && *q != '.' && *q != '@') + *p++ = *q++; + if (*q == '.') + while (*q && *q != '@') + q++; + p = stpcpy (p, ".utf8"); + strcpy (p, q); + primary = ptr; + } + else + primary = NULL; + } + } + + memcpy (path, loc_path, loc_path_len); + + while ((d = readdir64 (dirp)) != NULL) + { + if (strcmp (d->d_name, ".") == 0 || strcmp (d->d_name, "..") == 0) + continue; + if (strchr (d->d_name, '_') == NULL) + continue; + + size_t d_name_len = strlen (d->d_name); + if (loc_path_len + d_name_len + 1 > sizeof (path)) + { + error (0, 0, "too long filename \"%s\"", d->d_name); + continue; + } + + memcpy (path + loc_path_len, d->d_name, d_name_len + 1); + if (stat64 (path, &st) < 0) + { + error (0, errno, "cannot stat \"%s\"", path); + continue; + } + if (! S_ISDIR (st.st_mode)) + continue; + if (cnt == 16384) + { + error (0, 0, "too many directories in \"%s\"", loc_path); + break; + } + list[cnt] = strdup (path); + if (list[cnt] == NULL) + { + error (0, errno, "cannot add file to list \"%s\"", path); + continue; + } + if (primary != NULL && cnt > 0 && strcmp (primary, d->d_name) == 0) + { + char *p = list[0]; + list[0] = list[cnt]; + list[cnt] = p; + } + cnt++; + } + closedir (dirp); + /* Store the archive to the file specified as the second argument on the + command line or the default locale archive. */ + fill_archive (&tmpl_ah, new_locar_fname, + install_langs_count, install_langs_list, + cnt, list, primary); + close_archive (&tmpl_ah); + truncate (tmpl_file, 0); + if (install_langs_count > 0) + { + free (ila_start); + free (install_langs_list); + } + char *tz_argv[] = { "/usr/sbin/tzdata-update", NULL }; + execve (tz_argv[0], (char *const *)tz_argv, (char *const *)&tz_argv[1]); + exit (0); +} diff --git a/elf-Add-new-LoongArch-reloc-types-101-to-108-into-el.patch b/elf-Add-new-LoongArch-reloc-types-101-to-108-into-el.patch deleted file mode 100644 index b3d7545..0000000 --- a/elf-Add-new-LoongArch-reloc-types-101-to-108-into-el.patch +++ /dev/null @@ -1,39 +0,0 @@ -From fc60db3cf29ba157d09ba4f4b92e3ab382b0339d Mon Sep 17 00:00:00 2001 -From: Xi Ruoyao -Date: Wed, 9 Aug 2023 19:12:54 +0800 -Subject: [PATCH 04/29] elf: Add new LoongArch reloc types (101 to 108) into - elf.h - -These reloc types are generated by GNU assembler >= 2.41 for relaxation -support. - -Link: https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=57a930e3 -Signed-off-by: Xi Ruoyao -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - elf/elf.h | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/elf/elf.h b/elf/elf.h -index 89fc8021..d623bdeb 100644 ---- a/elf/elf.h -+++ b/elf/elf.h -@@ -4205,6 +4205,14 @@ enum - #define R_LARCH_TLS_GD_HI20 98 - #define R_LARCH_32_PCREL 99 - #define R_LARCH_RELAX 100 -+#define R_LARCH_DELETE 101 -+#define R_LARCH_ALIGN 102 -+#define R_LARCH_PCREL20_S2 103 -+#define R_LARCH_CFA 104 -+#define R_LARCH_ADD6 105 -+#define R_LARCH_SUB6 106 -+#define R_LARCH_ADD_ULEB128 107 -+#define R_LARCH_SUB_ULEB128 108 - - /* ARC specific declarations. */ - --- -2.33.0 - diff --git a/glibc-2.38.tar.xz b/glibc-2.38.tar.xz deleted file mode 100644 index 677b2a7..0000000 Binary files a/glibc-2.38.tar.xz and /dev/null differ diff --git a/glibc-asflags.patch b/glibc-asflags.patch new file mode 100755 index 0000000..9bd733f --- /dev/null +++ b/glibc-asflags.patch @@ -0,0 +1,25 @@ +Author: Florian Weimer +Date: Wed Jul 4 16:16:57 2018 +0200 + + Makeconfig (ASFLAGS): Always append required assembler flags. + +Submitted upstream here: + + https://sourceware.org/ml/libc-alpha/2018-07/msg00077.html + +Otherwise, we lose essential flags such as -Wa,--noexecstack due to +the way += works in make due to the ASFLAGS command line override. + +diff --git a/Makeconfig b/Makeconfig +index b0b27f0113ac18b8..92e76d6200bbcd5b 100644 +--- a/Makeconfig ++++ b/Makeconfig +@@ -1047,7 +1047,7 @@ endif + ifndef ASFLAGS + ASFLAGS := $(filter -g% -fdebug-prefix-map=%,$(CFLAGS)) + endif +-ASFLAGS += -Werror=undef $(ASFLAGS-config) $(asflags-cpu) ++override ASFLAGS += -Werror=undef $(ASFLAGS-config) $(asflags-cpu) + + ifndef BUILD_CC + BUILD_CC = $(CC) diff --git a/glibc-c-utf8-locale.patch b/glibc-c-utf8-locale.patch new file mode 100755 index 0000000..7215e15 --- /dev/null +++ b/glibc-c-utf8-locale.patch @@ -0,0 +1,286 @@ +Short description: Add C.UTF-8 support. +Author(s): Fedora glibc team +Origin: PATCH +Upstream status: not-submitted + +This patch needs to upstream as part of Carlos O'Donell +'s work on enabling upstream C.UTF-8 support. This +work is currently blocked on cleaning up the test results to prove that +full code-point sorting is working as intended. + +Note that this patch does not provide full code-point sorting as +expected. + +This patch needs to upstream as soon as possible since it would be nice +to have this in F29 and fixed. + +From 2eda7b462b415105f5a05c1323372d4e39d46439 Mon Sep 17 00:00:00 2001 +From: Mike FABIAN +Date: Mon, 10 Aug 2015 15:58:12 +0200 +Subject: [PATCH] Add a C.UTF-8 locale + +--- + localedata/SUPPORTED | 1 + + localedata/locales/C | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 239 insertions(+) + create mode 100644 localedata/locales/C + +diff --git a/localedata/SUPPORTED b/localedata/SUPPORTED +index 8ca023e..2a78391 100644 +--- a/localedata/SUPPORTED ++++ b/localedata/SUPPORTED +@@ -1,6 +1,7 @@ + # This file names the currently supported and somewhat tested locales. + # If you have any additions please file a glibc bug report. + SUPPORTED-LOCALES=\ ++C.UTF-8/UTF-8 \ + aa_DJ.UTF-8/UTF-8 \ + aa_DJ/ISO-8859-1 \ + aa_ER/UTF-8 \ +diff --git a/localedata/locales/C b/localedata/locales/C +new file mode 100644 +index 0000000..fdf460e +--- /dev/null ++++ b/localedata/locales/C +@@ -0,0 +1,238 @@ ++escape_char / ++comment_char % ++% Locale for C locale in UTF-8 ++ ++LC_IDENTIFICATION ++title "C locale" ++source "" ++address "" ++contact "" ++email "mfabian@redhat.com" ++tel "" ++fax "" ++language "C" ++territory "" ++revision "1.0" ++date "2015-08-10" ++% ++category "i18n:2012";LC_IDENTIFICATION ++category "i18n:2012";LC_CTYPE ++category "i18n:2012";LC_COLLATE ++category "i18n:2012";LC_TIME ++category "i18n:2012";LC_NUMERIC ++category "i18n:2012";LC_MONETARY ++category "i18n:2012";LC_MESSAGES ++category "i18n:2012";LC_PAPER ++category "i18n:2012";LC_NAME ++category "i18n:2012";LC_ADDRESS ++category "i18n:2012";LC_TELEPHONE ++category "i18n:2012";LC_MEASUREMENT ++END LC_IDENTIFICATION ++ ++LC_CTYPE ++copy "i18n" ++ ++translit_start ++include "translit_combining";"" ++translit_end ++ ++END LC_CTYPE ++ ++LC_COLLATE ++order_start forward ++ ++.. ++ ++ ++.. ++ ++ ++.. ++ ++ ++.. ++ ++ ++.. ++ ++ ++.. ++ ++UNDEFINED ++order_end ++END LC_COLLATE ++ ++LC_MONETARY ++% This is the 14652 i18n fdcc-set definition for ++% the LC_MONETARY category ++% (except for the int_curr_symbol and currency_symbol, they are empty in ++% the 14652 i18n fdcc-set definition and also empty in ++% glibc/locale/C-monetary.c. But localedef complains in that case). ++% ++% Using "USD" for int_curr_symbol. But maybe "XXX" would be better? ++% XXX is "No currency" (https://en.wikipedia.org/wiki/ISO_4217) ++int_curr_symbol "" ++% Using "$" for currency_symbol. But maybe would be better? ++% U+00A4 is the "generic currency symbol" ++% (https://en.wikipedia.org/wiki/Currency_sign_%28typography%29) ++currency_symbol "" ++mon_decimal_point "" ++mon_thousands_sep "" ++mon_grouping -1 ++positive_sign "" ++negative_sign "" ++int_frac_digits -1 ++frac_digits -1 ++p_cs_precedes -1 ++int_p_sep_by_space -1 ++p_sep_by_space -1 ++n_cs_precedes -1 ++int_n_sep_by_space -1 ++n_sep_by_space -1 ++p_sign_posn -1 ++n_sign_posn -1 ++% ++END LC_MONETARY ++ ++LC_NUMERIC ++% This is the POSIX Locale definition for ++% the LC_NUMERIC category. ++% ++decimal_point "" ++thousands_sep "" ++grouping -1 ++END LC_NUMERIC ++ ++LC_TIME ++% This is the POSIX Locale definition for ++% the LC_TIME category. ++% ++% Abbreviated weekday names (%a) ++abday "";"";/ ++ "";"";/ ++ "";"";/ ++ "" ++ ++% Full weekday names (%A) ++day "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "" ++ ++% Abbreviated month names (%b) ++abmon "";"";/ ++ "";"";/ ++ "";"";/ ++ "";"";/ ++ "";"";/ ++ "";"" ++ ++% Full month names (%B) ++mon "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "";/ ++ "" ++ ++% Week description, consists of three fields: ++% 1. Number of days in a week. ++% 2. Gregorian date that is a first weekday (19971130 for Sunday, 19971201 for Monday). ++% 3. The weekday number to be contained in the first week of the year. ++% ++% ISO 8601 conforming applications should use the values 7, 19971201 (a ++% Monday), and 4 (Thursday), respectively. ++week 7;19971201;4 ++first_weekday 1 ++first_workday 1 ++ ++% Appropriate date and time representation (%c) ++% "%a %b %e %H:%M:%S %Y" ++d_t_fmt "" ++ ++% Appropriate date representation (%x) ++% "%m/%d/%y" ++d_fmt "" ++ ++% Appropriate time representation (%X) ++% "%H:%M:%S" ++t_fmt "" ++ ++% Appropriate AM/PM time representation (%r) ++% "%I:%M:%S %p" ++t_fmt_ampm "" ++ ++% Equivalent of AM/PM (%p) "AM"/"PM" ++% ++am_pm "";"" ++ ++% Appropriate date representation (date(1)) "%a %b %e %H:%M:%S %Z %Y" ++date_fmt "" ++END LC_TIME ++ ++LC_MESSAGES ++% This is the POSIX Locale definition for ++% the LC_NUMERIC category. ++% ++yesexpr "" ++noexpr "" ++yesstr "" ++nostr "" ++END LC_MESSAGES ++ ++LC_PAPER ++% This is the ISO/IEC 14652 "i18n" definition for ++% the LC_PAPER category. ++% (A4 paper, this is also used in the built in C/POSIX ++% locale in glibc/locale/C-paper.c) ++height 297 ++width 210 ++END LC_PAPER ++ ++LC_NAME ++% This is the ISO/IEC 14652 "i18n" definition for ++% the LC_NAME category. ++% "%p%t%g%t%m%t%f" ++% (also used in the built in C/POSIX locale in glibc/locale/C-name.c) ++name_fmt "/ ++" ++END LC_NAME ++ ++LC_ADDRESS ++% This is the ISO/IEC 14652 "i18n" definition for ++% the LC_ADDRESS category. ++% "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N" ++% (also used in the built in C/POSIX locale in glibc/locale/C-address.c) ++postal_fmt "/ ++/ ++/ ++/ ++" ++END LC_ADDRESS ++ ++LC_TELEPHONE ++% This is the ISO/IEC 14652 "i18n" definition for ++% the LC_TELEPHONE category. ++% "+%c %a %l" ++tel_int_fmt "/ ++" ++% (also used in the built in C/POSIX locale in glibc/locale/C-telephone.c) ++END LC_TELEPHONE ++ ++LC_MEASUREMENT ++% This is the ISO/IEC 14652 "i18n" definition for ++% the LC_MEASUREMENT category. ++% (same as in the built in C/POSIX locale in glibc/locale/C-measurement.c) ++%metric ++measurement 1 ++END LC_MEASUREMENT ++ +-- +2.4.3 + diff --git a/glibc-cs-path.patch b/glibc-cs-path.patch old mode 100644 new mode 100755 index 40835d2..aafa741 --- a/glibc-cs-path.patch +++ b/glibc-cs-path.patch @@ -1,44 +1,15 @@ -Short description: Adjust CS_PATH and the test container layout. +Short description: Adjust CS_PATH return value. Author(s): Fedora glibc team Origin: PATCH Upstream status: not-needed -In Fedora we should return only /usr/bin as CS_PATH because /bin is just -a symlink to /usr/bin after MoveToUsr transition (which glibc has not -really completed). +In Fedora we should return only /usr/bin because /bin is just a symlink +to /usr/bin after MoveToUsr transition (which glibc has not really +completed). -We also create /{bin,lib,lib64,sbin} in the test container as symbolic -links. This brings the test container in line with Fedora's filesystem -layout and avoids some test failures. For example, because Fedora's -CS_PATH is /usr/bin, tst-vfork3 will try to execute /usr/bin/echo in the -container. Without this change the container installs `echo' in /bin -not /usr/bin, causing the test to fail. - -diff --git a/Makefile b/Makefile -index a49870d3d1e636a9..feb2599203b10098 100644 ---- a/Makefile -+++ b/Makefile -@@ -598,9 +598,13 @@ $(tests-container) $(addsuffix /tests,$(subdirs)) : \ - $(objpfx)testroot.pristine/install.stamp : - test -d $(objpfx)testroot.pristine || \ - mkdir $(objpfx)testroot.pristine -- # We need a working /bin/sh for some of the tests. -- test -d $(objpfx)testroot.pristine/bin || \ -- mkdir $(objpfx)testroot.pristine/bin -+ # Set up symlinks to directories whose contents got moved to /usr -+ for moved in bin lib lib64 sbin; do \ -+ test -d $(objpfx)testroot.pristine/usr/$$moved || \ -+ mkdir -p $(objpfx)testroot.pristine/usr/$$moved ;\ -+ test -e $(objpfx)testroot.pristine/$$moved || \ -+ ln -s usr/$$moved $(objpfx)testroot.pristine/$$moved ;\ -+ done - # We need the compiled locale dir for localedef tests. - test -d $(objpfx)testroot.pristine/$(complocaledir) || \ - mkdir -p $(objpfx)testroot.pristine/$(complocaledir) -diff --git a/sysdeps/unix/confstr.h b/sysdeps/unix/confstr.h -index 15859c3b2759878e..9b63b7f8069866fd 100644 ---- a/sysdeps/unix/confstr.h -+++ b/sysdeps/unix/confstr.h +diff -pruN a/sysdeps/unix/confstr.h b/sysdeps/unix/confstr.h +--- a/sysdeps/unix/confstr.h 2012-12-25 08:32:13.000000000 +0530 ++++ b/sysdeps/unix/confstr.h 2014-09-05 20:02:55.698275219 +0530 @@ -1 +1 @@ -#define CS_PATH "/bin:/usr/bin" +#define CS_PATH "/usr/bin" diff --git a/glibc-deprecated-selinux-makedb.patch b/glibc-deprecated-selinux-makedb.patch deleted file mode 100644 index c762d02..0000000 --- a/glibc-deprecated-selinux-makedb.patch +++ /dev/null @@ -1,20 +0,0 @@ -This is necessary to get things building again after libselinux changes. -A proper fix is under discussion upstream: - - - -diff --git a/nss/makedb.c b/nss/makedb.c -index 8e389a1683747cf1..9d81aed57d384a22 100644 ---- a/nss/makedb.c -+++ b/nss/makedb.c -@@ -17,6 +17,10 @@ - License along with the GNU C Library; if not, see - . */ - -+/* This file uses deprecated declarations from libselinux. */ -+#include -+DIAG_IGNORE_NEEDS_COMMENT (4.9, "-Wdeprecated-declarations"); -+ - #include - #include - #include diff --git a/glibc-fedora-__libc_multiple_libcs.patch b/glibc-fedora-__libc_multiple_libcs.patch new file mode 100755 index 0000000..256ef20 --- /dev/null +++ b/glibc-fedora-__libc_multiple_libcs.patch @@ -0,0 +1,91 @@ +Short description: Cleanup use of _dl_starting_up. +Author(s): Fedora glibc team +Origin: PATCH +Upstream status: https://sourceware.org/ml/libc-alpha/2014-02/msg00589.html + +Upstream discussions: +https://sourceware.org/ml/libc-alpha/2014-02/msg00580.html + +Based on the following commit: +~~~ +From 16552c01a66633c9e412984d9d92616bd4e5303c Mon Sep 17 00:00:00 2001 +From: Andreas Schwab +Date: Fri, 11 Jun 2010 11:04:11 +0200 +Subject: [PATCH] Properly set __libc_multiple_libcs + + * elf/rtld.c (_dl_starting_up): Always define. + (dl_main): Always set _dl_starting_up. + * elf/dl-support.c (_dl_starting_up): Always define. + * elf/dl-init.c (_dl_init): Always clear _dl_starting_up. + +--- +ChangeLog | 7 +++++++ +elf/dl-init.c | 4 ---- +elf/dl-support.c | 2 -- +elf/rtld.c | 4 ---- +4 files changed, 7 insertions(+), 10 deletions(-) +~~~ + +This patch needs to go upstream to get cleaned up, but has always involed +analysis of the GNU/Hurd parts of the change and that stalled out, but +perhaps with build-many-glibcs we can now test these changes more easily. + +Index: b/elf/dl-init.c +=================================================================== +--- a/elf/dl-init.c ++++ b/elf/dl-init.c +@@ -119,8 +119,6 @@ _dl_init (struct link_map *main_map, int + while (i-- > 0) + call_init (main_map->l_initfini[i], argc, argv, env); + +-#ifndef HAVE_INLINED_SYSCALLS + /* Finished starting up. */ + _dl_starting_up = 0; +-#endif + } +Index: b/elf/dl-support.c +=================================================================== +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -117,10 +117,8 @@ struct r_scope_elem _dl_initial_searchli + .r_nlist = 1, + }; + +-#ifndef HAVE_INLINED_SYSCALLS + /* Nonzero during startup. */ + int _dl_starting_up = 1; +-#endif + + /* Random data provided by the kernel. */ + void *_dl_random; +Index: b/elf/rtld.c +=================================================================== +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -214,7 +214,6 @@ audit_list_iter_next (struct audit_list_ + return iter->previous->name; + } + +-#ifndef HAVE_INLINED_SYSCALLS + /* Set nonzero during loading and initialization of executable and + libraries, cleared before the executable's entry point runs. This + must not be initialized to nonzero, because the unused dynamic +@@ -224,7 +223,6 @@ audit_list_iter_next (struct audit_list_ + never be called. */ + int _dl_starting_up = 0; + rtld_hidden_def (_dl_starting_up) +-#endif + + /* This is the structure which defines all variables global to ld.so + (except those which cannot be added for some reason). */ +@@ -898,10 +896,8 @@ dl_main (const ElfW(Phdr) *phdr, + /* Process the environment variable which control the behaviour. */ + process_envvars (&mode); + +-#ifndef HAVE_INLINED_SYSCALLS + /* Set up a flag which tells we are just starting. */ + _dl_starting_up = 1; +-#endif + + if (*user_entry == (ElfW(Addr)) ENTRY_POINT) + { diff --git a/glibc-fedora-linux-tcsetattr.patch b/glibc-fedora-linux-tcsetattr.patch new file mode 100755 index 0000000..3ae7e27 --- /dev/null +++ b/glibc-fedora-linux-tcsetattr.patch @@ -0,0 +1,61 @@ +Short description: Fedora-specific workaround for kernel pty bug. +Author(s): Fedora glibc team +Origin: PATCH +Upstream status: not-submitted + +This is a Fedora-specific workaround for a kernel bug where calling +ioctl on a pty will silently ignore the invalid c_cflag. The +workaround is to use TCGETS to verify the setting matches. This is +not upstream and needs to either be removed or submitted upstream +after analysis. + +Index: b/sysdeps/unix/sysv/linux/tcsetattr.c +=================================================================== +--- a/sysdeps/unix/sysv/linux/tcsetattr.c ++++ b/sysdeps/unix/sysv/linux/tcsetattr.c +@@ -45,6 +45,7 @@ __tcsetattr (int fd, int optional_action + { + struct __kernel_termios k_termios; + unsigned long int cmd; ++ int retval; + + switch (optional_actions) + { +@@ -75,7 +76,36 @@ __tcsetattr (int fd, int optional_action + memcpy (&k_termios.c_cc[0], &termios_p->c_cc[0], + __KERNEL_NCCS * sizeof (cc_t)); + +- return INLINE_SYSCALL (ioctl, 3, fd, cmd, &k_termios); ++ retval = INLINE_SYSCALL (ioctl, 3, fd, cmd, &k_termios); ++ ++ if (retval == 0 && cmd == TCSETS) ++ { ++ /* The Linux kernel has a bug which silently ignore the invalid ++ c_cflag on pty. We have to check it here. */ ++ int save = errno; ++ retval = INLINE_SYSCALL (ioctl, 3, fd, TCGETS, &k_termios); ++ if (retval) ++ { ++ /* We cannot verify if the setting is ok. We don't return ++ an error (?). */ ++ __set_errno (save); ++ retval = 0; ++ } ++ else if ((termios_p->c_cflag & (PARENB | CREAD)) ++ != (k_termios.c_cflag & (PARENB | CREAD)) ++ || ((termios_p->c_cflag & CSIZE) ++ && ((termios_p->c_cflag & CSIZE) ++ != (k_termios.c_cflag & CSIZE)))) ++ { ++ /* It looks like the Linux kernel silently changed the ++ PARENB/CREAD/CSIZE bits in c_cflag. Report it as an ++ error. */ ++ __set_errno (EINVAL); ++ retval = -1; ++ } ++ } ++ ++ return retval; + } + weak_alias (__tcsetattr, tcsetattr) + libc_hidden_def (tcsetattr) diff --git a/glibc-fedora-localedata-rh61908.patch b/glibc-fedora-localedata-rh61908.patch new file mode 100755 index 0000000..518253d --- /dev/null +++ b/glibc-fedora-localedata-rh61908.patch @@ -0,0 +1,49 @@ +Short description: Add 4 ISO-8859-15 locales to SUPPORTED for Euro symbol. +Author(s): Fedora glibc team +Origin: PATCH +Bug-RHEL: #61908 +Upstream status: not-needed + +Very early RHL 7.3 requirement to add these locales so users can +get access to Euro symbol. We should review this bug and decide if +the UTF-8 locales are now serving the same purpose and drop the +additional locales. + +* Tue Mar 26 2002 Jakub Jelinek 2.2.5-28 +- add a couple of .ISO-8859-15 locales (#61908) + +diff -Nrup a/localedata/SUPPORTED b/localedata/SUPPORTED +--- a/localedata/SUPPORTED 2012-11-25 12:59:31.000000000 -0700 ++++ b/localedata/SUPPORTED 2012-11-26 12:58:43.298223018 -0700 +@@ -89,6 +89,7 @@ cy_GB.UTF-8/UTF-8 \ + cy_GB/ISO-8859-14 \ + da_DK.UTF-8/UTF-8 \ + da_DK/ISO-8859-1 \ ++da_DK.ISO-8859-15/ISO-8859-15 \ + de_AT.UTF-8/UTF-8 \ + de_AT/ISO-8859-1 \ + de_AT@euro/ISO-8859-15 \ +@@ -121,6 +122,7 @@ en_DK.UTF-8/UTF-8 \ + en_DK/ISO-8859-1 \ + en_GB.UTF-8/UTF-8 \ + en_GB/ISO-8859-1 \ ++en_GB.ISO-8859-15/ISO-8859-15 \ + en_HK.UTF-8/UTF-8 \ + en_HK/ISO-8859-1 \ + en_IE.UTF-8/UTF-8 \ +@@ -136,6 +138,7 @@ en_SG.UTF-8/UTF-8 \ + en_SG/ISO-8859-1 \ + en_US.UTF-8/UTF-8 \ + en_US/ISO-8859-1 \ ++en_US.ISO-8859-15/ISO-8859-15 \ + en_ZA.UTF-8/UTF-8 \ + en_ZA/ISO-8859-1 \ + en_ZM/UTF-8 \ +@@ -385,6 +388,7 @@ sv_FI/ISO-8859-1 \ + sv_FI@euro/ISO-8859-15 \ + sv_SE.UTF-8/UTF-8 \ + sv_SE/ISO-8859-1 \ ++sv_SE.ISO-8859-15/ISO-8859-15 \ + sw_KE/UTF-8 \ + sw_TZ/UTF-8 \ + szl_PL/UTF-8 \ diff --git a/glibc-no-archive-for-localedef.patch b/glibc-fedora-localedef.patch old mode 100644 new mode 100755 similarity index 84% rename from glibc-no-archive-for-localedef.patch rename to glibc-fedora-localedef.patch index 515611a..787951f --- a/glibc-no-archive-for-localedef.patch +++ b/glibc-fedora-localedef.patch @@ -8,14 +8,14 @@ behaviour which updates the locale archive. The Fedora install phase in the spec file of the rpm will handle this manually. diff --git a/localedata/Makefile b/localedata/Makefile -index 0eea396ad86da956..54caabda33728207 100644 +index a5f3c92d58954dfc..56719c7c714aa0f1 100644 --- a/localedata/Makefile +++ b/localedata/Makefile -@@ -413,6 +413,7 @@ define build-one-locale +@@ -218,6 +218,7 @@ $(INSTALL-SUPPORTED-LOCALES): install-locales-dir echo -n '...'; \ input=`echo $$locale | sed 's/\([^.]*\)[^@]*\(.*\)/\1\2/'`; \ $(LOCALEDEF) $$flags --alias-file=../intl/locale.alias \ + --no-archive \ -i locales/$$input -f charmaps/$$charset \ $(addprefix --prefix=,$(install_root)) $$locale \ - && echo ' done'; + && echo ' done'; \ diff --git a/glibc-fedora-locarchive.patch b/glibc-fedora-locarchive.patch new file mode 100755 index 0000000..299b0f0 --- /dev/null +++ b/glibc-fedora-locarchive.patch @@ -0,0 +1,46 @@ +Short description: Allow access to internal locale archive functions. +Author(s): Fedora glibc team +Origin: PATCH +Upstream status: not-needed + +This is a part of commit glibc-2.3.3-1492-ga891c7b, +needed for fedora/build-locale-archive.c only. + +2007-04-16 Jakub Jelinek + + * locale/programs/locarchive.c (add_alias, insert_name): Remove static. + +diff -Nrup a/locale/programs/locarchive.c b/locale/programs/locarchive.c +--- a/locale/programs/locarchive.c 2012-06-05 07:42:49.000000000 -0600 ++++ b/locale/programs/locarchive.c 2012-06-07 12:15:21.585319540 -0600 +@@ -252,9 +252,9 @@ oldlocrecentcmp (const void *a, const vo + /* forward decls for below */ + static uint32_t add_locale (struct locarhandle *ah, const char *name, + locale_data_t data, bool replace); +-static void add_alias (struct locarhandle *ah, const char *alias, +- bool replace, const char *oldname, +- uint32_t *locrec_offset_p); ++void add_alias (struct locarhandle *ah, const char *alias, ++ bool replace, const char *oldname, ++ uint32_t *locrec_offset_p); + + + static bool +@@ -635,7 +635,7 @@ close_archive (struct locarhandle *ah) + #include "../../intl/explodename.c" + #include "../../intl/l10nflist.c" + +-static struct namehashent * ++struct namehashent * + insert_name (struct locarhandle *ah, + const char *name, size_t name_len, bool replace) + { +@@ -693,7 +693,7 @@ insert_name (struct locarhandle *ah, + return &namehashtab[idx]; + } + +-static void ++void + add_alias (struct locarhandle *ah, const char *alias, bool replace, + const char *oldname, uint32_t *locrec_offset_p) + { diff --git a/glibc-place-info-into-Libraries-category.patch b/glibc-fedora-manual-dircategory.patch old mode 100644 new mode 100755 similarity index 100% rename from glibc-place-info-into-Libraries-category.patch rename to glibc-fedora-manual-dircategory.patch diff --git a/glibc-fedora-nis-rh188246.patch b/glibc-fedora-nis-rh188246.patch new file mode 100755 index 0000000..5ec2237 --- /dev/null +++ b/glibc-fedora-nis-rh188246.patch @@ -0,0 +1,31 @@ +Short description: Fedora-specific enabling batch read in NSS. +Author(s): Fedora glibc team +Origin: PATCH +Bug-RHEL: #188246 +Upstream status: not-submitted + +Enable batch read in NSS. It's not clear if this is always a win or +just a win for NIS+, this needs to be analyzed and sent upstream or +removed. + +From baba5d9461d4e8a581ac26fe4412ad783ffc73e7 Mon Sep 17 00:00:00 2001 +From: Jakub Jelinek +Date: Mon, 1 May 2006 08:02:53 +0000 +Subject: [PATCH] Enable SETENT_BATCH_READ nis/nss option by default + +* Mon May 1 2006 Jakub Jelinek 2.4.90-4 +- SETENT_BATCH_READ /etc/default/nss option for speeding up + some usages of NIS+ (#188246) + +diff --git a/nis/nss b/nis/nss +--- a/nis/nss ++++ b/nis/nss +@@ -25,7 +25,7 @@ + # memory with every getXXent() call. Otherwise each getXXent() call + # might result into a network communication with the server to get + # the next entry. +-#SETENT_BATCH_READ=TRUE ++SETENT_BATCH_READ=TRUE + # + # ADJUNCT_AS_SHADOW + # If set to TRUE, the passwd routines in the NIS NSS module will not diff --git a/glibc-fedora-nscd.patch b/glibc-fedora-nscd.patch new file mode 100755 index 0000000..6f8f764 --- /dev/null +++ b/glibc-fedora-nscd.patch @@ -0,0 +1,20 @@ +Short description: NSCD must use nscd user. +Author(s): Fedora glibc team +Origin: PATCH +Upstream status: not-needed + +Fedora-specific configuration adjustment to introduce the nscd user. +(Upstream does not assume this user exists.) + +diff -Nrup a/nscd/nscd.conf b/nscd/nscd.conf +--- a/nscd/nscd.conf 2012-06-05 07:42:49.000000000 -0600 ++++ b/nscd/nscd.conf 2012-06-07 12:15:21.818318670 -0600 +@@ -33,7 +33,7 @@ + # logfile /var/log/nscd.log + # threads 4 + # max-threads 32 +-# server-user nobody ++ server-user nscd + # stat-user somebody + debug-level 0 + # reload-count 5 diff --git a/glibc-fedora-streams-rh436349.patch b/glibc-fedora-streams-rh436349.patch new file mode 100755 index 0000000..0d8f7d9 --- /dev/null +++ b/glibc-fedora-streams-rh436349.patch @@ -0,0 +1,38 @@ +Short description: Do not define _XOPEN_STREAMS. +Author(s): Fedora glibc team +Origin: PATCH +Bug-Fedora: #436349 +Upstream status: not-submitted + +This patch should go upstream. Not defining _XOPEN_STREAMS is the +same as setting it to -1 for POSIX conformance. The headers setting +needs to be reviewed indepedently. + +This is part of commit glibc-2.3.3-1564-gd0b6ac6 + +* Fri Mar 14 2008 Jakub Jelinek 2.7.90-11 +- remove , define _XOPEN_STREAMS -1 (#436349) + +diff -Nrup a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h +--- a/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-05 07:42:49.000000000 -0600 ++++ b/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-07 12:15:21.817318674 -0600 +@@ -188,4 +188,7 @@ + /* Typed memory objects are not available. */ + #define _POSIX_TYPED_MEMORY_OBJECTS -1 + ++/* Streams are not available. */ ++#define _XOPEN_STREAMS -1 ++ + #endif /* bits/posix_opt.h */ +diff -Nrup a/streams/Makefile b/streams/Makefile +--- a/streams/Makefile 2012-06-05 07:42:49.000000000 -0600 ++++ b/streams/Makefile 2012-06-07 12:15:21.824318649 -0600 +@@ -20,7 +20,7 @@ + + include ../Makeconfig + +-headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h ++#headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h + routines = isastream getmsg getpmsg putmsg putpmsg fattach fdetach + + include ../Rules diff --git a/glibc-gb18030-2022-bug30243.patch b/glibc-gb18030-2022-bug30243.patch deleted file mode 100644 index 8e87f34..0000000 --- a/glibc-gb18030-2022-bug30243.patch +++ /dev/null @@ -1,797 +0,0 @@ -diff --git a/iconvdata/gb18030.c b/iconvdata/gb18030.c -index 0b03b9bb..ca383dc0 100644 ---- a/iconvdata/gb18030.c -+++ b/iconvdata/gb18030.c -@@ -6020,49 +6020,50 @@ static const uint16_t __twobyte_to_ucs[] = - [0x5dc2] = 0xfa0e, [0x5dc3] = 0xfa0f, [0x5dc4] = 0xfa11, [0x5dc5] = 0xfa13, - [0x5dc6] = 0xfa14, [0x5dc7] = 0xfa18, [0x5dc8] = 0xfa1f, [0x5dc9] = 0xfa20, - [0x5dca] = 0xfa21, [0x5dcb] = 0xfa23, [0x5dcc] = 0xfa24, [0x5dcd] = 0xfa27, -- [0x5dce] = 0xfa28, [0x5dcf] = 0xfa29, [0x5dd0] = 0x2e81, [0x5dd4] = 0x2e84, -- [0x5dd5] = 0x3473, [0x5dd6] = 0x3447, [0x5dd7] = 0x2e88, [0x5dd8] = 0x2e8b, -- [0x5dd9] = 0x9fb4, [0x5dda] = 0x359e, [0x5ddb] = 0x361a, [0x5ddc] = 0x360e, -- [0x5ddd] = 0x2e8c, [0x5dde] = 0x2e97, [0x5ddf] = 0x396e, [0x5de0] = 0x3918, -- [0x5de1] = 0x9fb5, [0x5de2] = 0x39cf, [0x5de3] = 0x39df, [0x5de4] = 0x3a73, -- [0x5de5] = 0x39d0, [0x5de6] = 0x9fb6, [0x5de7] = 0x9fb7, [0x5de8] = 0x3b4e, -- [0x5de9] = 0x3c6e, [0x5dea] = 0x3ce0, [0x5deb] = 0x2ea7, [0x5ded] = 0x9fb8, -+ [0x5dce] = 0xfa28, [0x5dcf] = 0xfa29, [0x5dd0] = 0x2e81, [0x5dd1] = 0xe816, -+ [0x5dd2] = 0xe817, [0x5dd3] = 0xe818, [0x5dd4] = 0x2e84, [0x5dd5] = 0x3473, -+ [0x5dd6] = 0x3447, [0x5dd7] = 0x2e88, [0x5dd8] = 0x2e8b, [0x5dd9] = 0x9fb4, -+ [0x5dda] = 0x359e, [0x5ddb] = 0x361a, [0x5ddc] = 0x360e, [0x5ddd] = 0x2e8c, -+ [0x5dde] = 0x2e97, [0x5ddf] = 0x396e, [0x5de0] = 0x3918, [0x5de1] = 0x9fb5, -+ [0x5de2] = 0x39cf, [0x5de3] = 0x39df, [0x5de4] = 0x3a73, [0x5de5] = 0x39d0, -+ [0x5de6] = 0x9fb6, [0x5de7] = 0x9fb7, [0x5de8] = 0x3b4e, [0x5de9] = 0x3c6e, -+ [0x5dea] = 0x3ce0, [0x5deb] = 0x2ea7, [0x5dec] = 0xe831, [0x5ded] = 0x9fb8, - [0x5dee] = 0x2eaa, [0x5def] = 0x4056, [0x5df0] = 0x415f, [0x5df1] = 0x2eae, - [0x5df2] = 0x4337, [0x5df3] = 0x2eb3, [0x5df4] = 0x2eb6, [0x5df5] = 0x2eb7, -- [0x5df7] = 0x43b1, [0x5df8] = 0x43ac, [0x5df9] = 0x2ebb, [0x5dfa] = 0x43dd, -- [0x5dfb] = 0x44d6, [0x5dfc] = 0x4661, [0x5dfd] = 0x464c, [0x5dfe] = 0x9fb9, -- [0x5e00] = 0x4723, [0x5e01] = 0x4729, [0x5e02] = 0x477c, [0x5e03] = 0x478d, -- [0x5e04] = 0x2eca, [0x5e05] = 0x4947, [0x5e06] = 0x497a, [0x5e07] = 0x497d, -- [0x5e08] = 0x4982, [0x5e09] = 0x4983, [0x5e0a] = 0x4985, [0x5e0b] = 0x4986, -- [0x5e0c] = 0x499f, [0x5e0d] = 0x499b, [0x5e0e] = 0x49b7, [0x5e0f] = 0x49b6, -- [0x5e10] = 0x9fba, [0x5e12] = 0x4ca3, [0x5e13] = 0x4c9f, [0x5e14] = 0x4ca0, -- [0x5e15] = 0x4ca1, [0x5e16] = 0x4c77, [0x5e17] = 0x4ca2, [0x5e18] = 0x4d13, -- [0x5e19] = 0x4d14, [0x5e1a] = 0x4d15, [0x5e1b] = 0x4d16, [0x5e1c] = 0x4d17, -- [0x5e1d] = 0x4d18, [0x5e1e] = 0x4d19, [0x5e1f] = 0x4dae, [0x5e20] = 0x9fbb, -- [0x5e21] = 0xe468, [0x5e22] = 0xe469, [0x5e23] = 0xe46a, [0x5e24] = 0xe46b, -- [0x5e25] = 0xe46c, [0x5e26] = 0xe46d, [0x5e27] = 0xe46e, [0x5e28] = 0xe46f, -- [0x5e29] = 0xe470, [0x5e2a] = 0xe471, [0x5e2b] = 0xe472, [0x5e2c] = 0xe473, -- [0x5e2d] = 0xe474, [0x5e2e] = 0xe475, [0x5e2f] = 0xe476, [0x5e30] = 0xe477, -- [0x5e31] = 0xe478, [0x5e32] = 0xe479, [0x5e33] = 0xe47a, [0x5e34] = 0xe47b, -- [0x5e35] = 0xe47c, [0x5e36] = 0xe47d, [0x5e37] = 0xe47e, [0x5e38] = 0xe47f, -- [0x5e39] = 0xe480, [0x5e3a] = 0xe481, [0x5e3b] = 0xe482, [0x5e3c] = 0xe483, -- [0x5e3d] = 0xe484, [0x5e3e] = 0xe485, [0x5e3f] = 0xe486, [0x5e40] = 0xe487, -- [0x5e41] = 0xe488, [0x5e42] = 0xe489, [0x5e43] = 0xe48a, [0x5e44] = 0xe48b, -- [0x5e45] = 0xe48c, [0x5e46] = 0xe48d, [0x5e47] = 0xe48e, [0x5e48] = 0xe48f, -- [0x5e49] = 0xe490, [0x5e4a] = 0xe491, [0x5e4b] = 0xe492, [0x5e4c] = 0xe493, -- [0x5e4d] = 0xe494, [0x5e4e] = 0xe495, [0x5e4f] = 0xe496, [0x5e50] = 0xe497, -- [0x5e51] = 0xe498, [0x5e52] = 0xe499, [0x5e53] = 0xe49a, [0x5e54] = 0xe49b, -- [0x5e55] = 0xe49c, [0x5e56] = 0xe49d, [0x5e57] = 0xe49e, [0x5e58] = 0xe49f, -- [0x5e59] = 0xe4a0, [0x5e5a] = 0xe4a1, [0x5e5b] = 0xe4a2, [0x5e5c] = 0xe4a3, -- [0x5e5d] = 0xe4a4, [0x5e5e] = 0xe4a5, [0x5e5f] = 0xe4a6, [0x5e60] = 0xe4a7, -- [0x5e61] = 0xe4a8, [0x5e62] = 0xe4a9, [0x5e63] = 0xe4aa, [0x5e64] = 0xe4ab, -- [0x5e65] = 0xe4ac, [0x5e66] = 0xe4ad, [0x5e67] = 0xe4ae, [0x5e68] = 0xe4af, -- [0x5e69] = 0xe4b0, [0x5e6a] = 0xe4b1, [0x5e6b] = 0xe4b2, [0x5e6c] = 0xe4b3, -- [0x5e6d] = 0xe4b4, [0x5e6e] = 0xe4b5, [0x5e6f] = 0xe4b6, [0x5e70] = 0xe4b7, -- [0x5e71] = 0xe4b8, [0x5e72] = 0xe4b9, [0x5e73] = 0xe4ba, [0x5e74] = 0xe4bb, -- [0x5e75] = 0xe4bc, [0x5e76] = 0xe4bd, [0x5e77] = 0xe4be, [0x5e78] = 0xe4bf, -- [0x5e79] = 0xe4c0, [0x5e7a] = 0xe4c1, [0x5e7b] = 0xe4c2, [0x5e7c] = 0xe4c3, -- [0x5e7d] = 0xe4c4, [0x5e7e] = 0xe4c5, -+ [0x5df6] = 0xe83b, [0x5df7] = 0x43b1, [0x5df8] = 0x43ac, [0x5df9] = 0x2ebb, -+ [0x5dfa] = 0x43dd, [0x5dfb] = 0x44d6, [0x5dfc] = 0x4661, [0x5dfd] = 0x464c, -+ [0x5dfe] = 0x9fb9, [0x5e00] = 0x4723, [0x5e01] = 0x4729, [0x5e02] = 0x477c, -+ [0x5e03] = 0x478d, [0x5e04] = 0x2eca, [0x5e05] = 0x4947, [0x5e06] = 0x497a, -+ [0x5e07] = 0x497d, [0x5e08] = 0x4982, [0x5e09] = 0x4983, [0x5e0a] = 0x4985, -+ [0x5e0b] = 0x4986, [0x5e0c] = 0x499f, [0x5e0d] = 0x499b, [0x5e0e] = 0x49b7, -+ [0x5e0f] = 0x49b6, [0x5e10] = 0x9fba, [0x5e11] = 0xe855, [0x5e12] = 0x4ca3, -+ [0x5e13] = 0x4c9f, [0x5e14] = 0x4ca0, [0x5e15] = 0x4ca1, [0x5e16] = 0x4c77, -+ [0x5e17] = 0x4ca2, [0x5e18] = 0x4d13, [0x5e19] = 0x4d14, [0x5e1a] = 0x4d15, -+ [0x5e1b] = 0x4d16, [0x5e1c] = 0x4d17, [0x5e1d] = 0x4d18, [0x5e1e] = 0x4d19, -+ [0x5e1f] = 0x4dae, [0x5e20] = 0x9fbb, [0x5e21] = 0xe468, [0x5e22] = 0xe469, -+ [0x5e23] = 0xe46a, [0x5e24] = 0xe46b, [0x5e25] = 0xe46c, [0x5e26] = 0xe46d, -+ [0x5e27] = 0xe46e, [0x5e28] = 0xe46f, [0x5e29] = 0xe470, [0x5e2a] = 0xe471, -+ [0x5e2b] = 0xe472, [0x5e2c] = 0xe473, [0x5e2d] = 0xe474, [0x5e2e] = 0xe475, -+ [0x5e2f] = 0xe476, [0x5e30] = 0xe477, [0x5e31] = 0xe478, [0x5e32] = 0xe479, -+ [0x5e33] = 0xe47a, [0x5e34] = 0xe47b, [0x5e35] = 0xe47c, [0x5e36] = 0xe47d, -+ [0x5e37] = 0xe47e, [0x5e38] = 0xe47f, [0x5e39] = 0xe480, [0x5e3a] = 0xe481, -+ [0x5e3b] = 0xe482, [0x5e3c] = 0xe483, [0x5e3d] = 0xe484, [0x5e3e] = 0xe485, -+ [0x5e3f] = 0xe486, [0x5e40] = 0xe487, [0x5e41] = 0xe488, [0x5e42] = 0xe489, -+ [0x5e43] = 0xe48a, [0x5e44] = 0xe48b, [0x5e45] = 0xe48c, [0x5e46] = 0xe48d, -+ [0x5e47] = 0xe48e, [0x5e48] = 0xe48f, [0x5e49] = 0xe490, [0x5e4a] = 0xe491, -+ [0x5e4b] = 0xe492, [0x5e4c] = 0xe493, [0x5e4d] = 0xe494, [0x5e4e] = 0xe495, -+ [0x5e4f] = 0xe496, [0x5e50] = 0xe497, [0x5e51] = 0xe498, [0x5e52] = 0xe499, -+ [0x5e53] = 0xe49a, [0x5e54] = 0xe49b, [0x5e55] = 0xe49c, [0x5e56] = 0xe49d, -+ [0x5e57] = 0xe49e, [0x5e58] = 0xe49f, [0x5e59] = 0xe4a0, [0x5e5a] = 0xe4a1, -+ [0x5e5b] = 0xe4a2, [0x5e5c] = 0xe4a3, [0x5e5d] = 0xe4a4, [0x5e5e] = 0xe4a5, -+ [0x5e5f] = 0xe4a6, [0x5e60] = 0xe4a7, [0x5e61] = 0xe4a8, [0x5e62] = 0xe4a9, -+ [0x5e63] = 0xe4aa, [0x5e64] = 0xe4ab, [0x5e65] = 0xe4ac, [0x5e66] = 0xe4ad, -+ [0x5e67] = 0xe4ae, [0x5e68] = 0xe4af, [0x5e69] = 0xe4b0, [0x5e6a] = 0xe4b1, -+ [0x5e6b] = 0xe4b2, [0x5e6c] = 0xe4b3, [0x5e6d] = 0xe4b4, [0x5e6e] = 0xe4b5, -+ [0x5e6f] = 0xe4b6, [0x5e70] = 0xe4b7, [0x5e71] = 0xe4b8, [0x5e72] = 0xe4b9, -+ [0x5e73] = 0xe4ba, [0x5e74] = 0xe4bb, [0x5e75] = 0xe4bc, [0x5e76] = 0xe4bd, -+ [0x5e77] = 0xe4be, [0x5e78] = 0xe4bf, [0x5e79] = 0xe4c0, [0x5e7a] = 0xe4c1, -+ [0x5e7b] = 0xe4c2, [0x5e7c] = 0xe4c3, [0x5e7d] = 0xe4c4, [0x5e7e] = 0xe4c5, - }; - - /* Table for GB18030 -> UCS-4, containing the four-byte characters only, -@@ -8691,7 +8692,9 @@ static const uint16_t __fourbyte_to_ucs[0x99e2 - 6637 - 2110 - 14404 - 4295] = - [0x2838] = 0x9fa6, [0x2839] = 0x9fa7, [0x283a] = 0x9fa8, [0x283b] = 0x9fa9, - [0x283c] = 0x9faa, [0x283d] = 0x9fab, [0x283e] = 0x9fac, [0x283f] = 0x9fad, - [0x2840] = 0x9fae, [0x2841] = 0x9faf, [0x2842] = 0x9fb0, [0x2843] = 0x9fb1, -- [0x2844] = 0x9fb2, [0x2845] = 0x9fb3, [0x284e] = 0xe76c, [0x284f] = 0xe7c8, -+ [0x2844] = 0x9fb2, [0x2845] = 0x9fb3, [0x2846] = 0xe81e, [0x2847] = 0xe826, -+ [0x2848] = 0xe82b, [0x2849] = 0xe82c, [0x284a] = 0xe832, [0x284b] = 0xe843, -+ [0x284c] = 0xe854, [0x284d] = 0xe864, [0x284e] = 0xe76c, [0x284f] = 0xe7c8, - [0x2850] = 0xe7e7, [0x2851] = 0xe7e8, [0x2852] = 0xe7e9, [0x2853] = 0xe7ea, - [0x2854] = 0xe7eb, [0x2855] = 0xe7ec, [0x2856] = 0xe7ed, [0x2857] = 0xe7ee, - [0x2858] = 0xe7ef, [0x2859] = 0xe7f0, [0x285a] = 0xe7f1, [0x285b] = 0xe7f2, -@@ -9019,84 +9022,86 @@ static const uint16_t __fourbyte_to_ucs[0x99e2 - 6637 - 2110 - 14404 - 4295] = - [0x2d60] = 0xfe02, [0x2d61] = 0xfe03, [0x2d62] = 0xfe04, [0x2d63] = 0xfe05, - [0x2d64] = 0xfe06, [0x2d65] = 0xfe07, [0x2d66] = 0xfe08, [0x2d67] = 0xfe09, - [0x2d68] = 0xfe0a, [0x2d69] = 0xfe0b, [0x2d6a] = 0xfe0c, [0x2d6b] = 0xfe0d, -- [0x2d6c] = 0xfe0e, [0x2d6d] = 0xfe0f, [0x2d78] = 0xfe1a, [0x2d79] = 0xfe1b, -- [0x2d7a] = 0xfe1c, [0x2d7b] = 0xfe1d, [0x2d7c] = 0xfe1e, [0x2d7d] = 0xfe1f, -- [0x2d7e] = 0xfe20, [0x2d7f] = 0xfe21, [0x2d80] = 0xfe22, [0x2d81] = 0xfe23, -- [0x2d82] = 0xfe24, [0x2d83] = 0xfe25, [0x2d84] = 0xfe26, [0x2d85] = 0xfe27, -- [0x2d86] = 0xfe28, [0x2d87] = 0xfe29, [0x2d88] = 0xfe2a, [0x2d89] = 0xfe2b, -- [0x2d8a] = 0xfe2c, [0x2d8b] = 0xfe2d, [0x2d8c] = 0xfe2e, [0x2d8d] = 0xfe2f, -- [0x2d8e] = 0xfe32, [0x2d8f] = 0xfe45, [0x2d90] = 0xfe46, [0x2d91] = 0xfe47, -- [0x2d92] = 0xfe48, [0x2d93] = 0xfe53, [0x2d94] = 0xfe58, [0x2d95] = 0xfe67, -- [0x2d96] = 0xfe6c, [0x2d97] = 0xfe6d, [0x2d98] = 0xfe6e, [0x2d99] = 0xfe6f, -- [0x2d9a] = 0xfe70, [0x2d9b] = 0xfe71, [0x2d9c] = 0xfe72, [0x2d9d] = 0xfe73, -- [0x2d9e] = 0xfe74, [0x2d9f] = 0xfe75, [0x2da0] = 0xfe76, [0x2da1] = 0xfe77, -- [0x2da2] = 0xfe78, [0x2da3] = 0xfe79, [0x2da4] = 0xfe7a, [0x2da5] = 0xfe7b, -- [0x2da6] = 0xfe7c, [0x2da7] = 0xfe7d, [0x2da8] = 0xfe7e, [0x2da9] = 0xfe7f, -- [0x2daa] = 0xfe80, [0x2dab] = 0xfe81, [0x2dac] = 0xfe82, [0x2dad] = 0xfe83, -- [0x2dae] = 0xfe84, [0x2daf] = 0xfe85, [0x2db0] = 0xfe86, [0x2db1] = 0xfe87, -- [0x2db2] = 0xfe88, [0x2db3] = 0xfe89, [0x2db4] = 0xfe8a, [0x2db5] = 0xfe8b, -- [0x2db6] = 0xfe8c, [0x2db7] = 0xfe8d, [0x2db8] = 0xfe8e, [0x2db9] = 0xfe8f, -- [0x2dba] = 0xfe90, [0x2dbb] = 0xfe91, [0x2dbc] = 0xfe92, [0x2dbd] = 0xfe93, -- [0x2dbe] = 0xfe94, [0x2dbf] = 0xfe95, [0x2dc0] = 0xfe96, [0x2dc1] = 0xfe97, -- [0x2dc2] = 0xfe98, [0x2dc3] = 0xfe99, [0x2dc4] = 0xfe9a, [0x2dc5] = 0xfe9b, -- [0x2dc6] = 0xfe9c, [0x2dc7] = 0xfe9d, [0x2dc8] = 0xfe9e, [0x2dc9] = 0xfe9f, -- [0x2dca] = 0xfea0, [0x2dcb] = 0xfea1, [0x2dcc] = 0xfea2, [0x2dcd] = 0xfea3, -- [0x2dce] = 0xfea4, [0x2dcf] = 0xfea5, [0x2dd0] = 0xfea6, [0x2dd1] = 0xfea7, -- [0x2dd2] = 0xfea8, [0x2dd3] = 0xfea9, [0x2dd4] = 0xfeaa, [0x2dd5] = 0xfeab, -- [0x2dd6] = 0xfeac, [0x2dd7] = 0xfead, [0x2dd8] = 0xfeae, [0x2dd9] = 0xfeaf, -- [0x2dda] = 0xfeb0, [0x2ddb] = 0xfeb1, [0x2ddc] = 0xfeb2, [0x2ddd] = 0xfeb3, -- [0x2dde] = 0xfeb4, [0x2ddf] = 0xfeb5, [0x2de0] = 0xfeb6, [0x2de1] = 0xfeb7, -- [0x2de2] = 0xfeb8, [0x2de3] = 0xfeb9, [0x2de4] = 0xfeba, [0x2de5] = 0xfebb, -- [0x2de6] = 0xfebc, [0x2de7] = 0xfebd, [0x2de8] = 0xfebe, [0x2de9] = 0xfebf, -- [0x2dea] = 0xfec0, [0x2deb] = 0xfec1, [0x2dec] = 0xfec2, [0x2ded] = 0xfec3, -- [0x2dee] = 0xfec4, [0x2def] = 0xfec5, [0x2df0] = 0xfec6, [0x2df1] = 0xfec7, -- [0x2df2] = 0xfec8, [0x2df3] = 0xfec9, [0x2df4] = 0xfeca, [0x2df5] = 0xfecb, -- [0x2df6] = 0xfecc, [0x2df7] = 0xfecd, [0x2df8] = 0xfece, [0x2df9] = 0xfecf, -- [0x2dfa] = 0xfed0, [0x2dfb] = 0xfed1, [0x2dfc] = 0xfed2, [0x2dfd] = 0xfed3, -- [0x2dfe] = 0xfed4, [0x2dff] = 0xfed5, [0x2e00] = 0xfed6, [0x2e01] = 0xfed7, -- [0x2e02] = 0xfed8, [0x2e03] = 0xfed9, [0x2e04] = 0xfeda, [0x2e05] = 0xfedb, -- [0x2e06] = 0xfedc, [0x2e07] = 0xfedd, [0x2e08] = 0xfede, [0x2e09] = 0xfedf, -- [0x2e0a] = 0xfee0, [0x2e0b] = 0xfee1, [0x2e0c] = 0xfee2, [0x2e0d] = 0xfee3, -- [0x2e0e] = 0xfee4, [0x2e0f] = 0xfee5, [0x2e10] = 0xfee6, [0x2e11] = 0xfee7, -- [0x2e12] = 0xfee8, [0x2e13] = 0xfee9, [0x2e14] = 0xfeea, [0x2e15] = 0xfeeb, -- [0x2e16] = 0xfeec, [0x2e17] = 0xfeed, [0x2e18] = 0xfeee, [0x2e19] = 0xfeef, -- [0x2e1a] = 0xfef0, [0x2e1b] = 0xfef1, [0x2e1c] = 0xfef2, [0x2e1d] = 0xfef3, -- [0x2e1e] = 0xfef4, [0x2e1f] = 0xfef5, [0x2e20] = 0xfef6, [0x2e21] = 0xfef7, -- [0x2e22] = 0xfef8, [0x2e23] = 0xfef9, [0x2e24] = 0xfefa, [0x2e25] = 0xfefb, -- [0x2e26] = 0xfefc, [0x2e27] = 0xfefd, [0x2e28] = 0xfefe, [0x2e29] = 0xfeff, -- [0x2e2a] = 0xff00, [0x2e2b] = 0xff5f, [0x2e2c] = 0xff60, [0x2e2d] = 0xff61, -- [0x2e2e] = 0xff62, [0x2e2f] = 0xff63, [0x2e30] = 0xff64, [0x2e31] = 0xff65, -- [0x2e32] = 0xff66, [0x2e33] = 0xff67, [0x2e34] = 0xff68, [0x2e35] = 0xff69, -- [0x2e36] = 0xff6a, [0x2e37] = 0xff6b, [0x2e38] = 0xff6c, [0x2e39] = 0xff6d, -- [0x2e3a] = 0xff6e, [0x2e3b] = 0xff6f, [0x2e3c] = 0xff70, [0x2e3d] = 0xff71, -- [0x2e3e] = 0xff72, [0x2e3f] = 0xff73, [0x2e40] = 0xff74, [0x2e41] = 0xff75, -- [0x2e42] = 0xff76, [0x2e43] = 0xff77, [0x2e44] = 0xff78, [0x2e45] = 0xff79, -- [0x2e46] = 0xff7a, [0x2e47] = 0xff7b, [0x2e48] = 0xff7c, [0x2e49] = 0xff7d, -- [0x2e4a] = 0xff7e, [0x2e4b] = 0xff7f, [0x2e4c] = 0xff80, [0x2e4d] = 0xff81, -- [0x2e4e] = 0xff82, [0x2e4f] = 0xff83, [0x2e50] = 0xff84, [0x2e51] = 0xff85, -- [0x2e52] = 0xff86, [0x2e53] = 0xff87, [0x2e54] = 0xff88, [0x2e55] = 0xff89, -- [0x2e56] = 0xff8a, [0x2e57] = 0xff8b, [0x2e58] = 0xff8c, [0x2e59] = 0xff8d, -- [0x2e5a] = 0xff8e, [0x2e5b] = 0xff8f, [0x2e5c] = 0xff90, [0x2e5d] = 0xff91, -- [0x2e5e] = 0xff92, [0x2e5f] = 0xff93, [0x2e60] = 0xff94, [0x2e61] = 0xff95, -- [0x2e62] = 0xff96, [0x2e63] = 0xff97, [0x2e64] = 0xff98, [0x2e65] = 0xff99, -- [0x2e66] = 0xff9a, [0x2e67] = 0xff9b, [0x2e68] = 0xff9c, [0x2e69] = 0xff9d, -- [0x2e6a] = 0xff9e, [0x2e6b] = 0xff9f, [0x2e6c] = 0xffa0, [0x2e6d] = 0xffa1, -- [0x2e6e] = 0xffa2, [0x2e6f] = 0xffa3, [0x2e70] = 0xffa4, [0x2e71] = 0xffa5, -- [0x2e72] = 0xffa6, [0x2e73] = 0xffa7, [0x2e74] = 0xffa8, [0x2e75] = 0xffa9, -- [0x2e76] = 0xffaa, [0x2e77] = 0xffab, [0x2e78] = 0xffac, [0x2e79] = 0xffad, -- [0x2e7a] = 0xffae, [0x2e7b] = 0xffaf, [0x2e7c] = 0xffb0, [0x2e7d] = 0xffb1, -- [0x2e7e] = 0xffb2, [0x2e7f] = 0xffb3, [0x2e80] = 0xffb4, [0x2e81] = 0xffb5, -- [0x2e82] = 0xffb6, [0x2e83] = 0xffb7, [0x2e84] = 0xffb8, [0x2e85] = 0xffb9, -- [0x2e86] = 0xffba, [0x2e87] = 0xffbb, [0x2e88] = 0xffbc, [0x2e89] = 0xffbd, -- [0x2e8a] = 0xffbe, [0x2e8b] = 0xffbf, [0x2e8c] = 0xffc0, [0x2e8d] = 0xffc1, -- [0x2e8e] = 0xffc2, [0x2e8f] = 0xffc3, [0x2e90] = 0xffc4, [0x2e91] = 0xffc5, -- [0x2e92] = 0xffc6, [0x2e93] = 0xffc7, [0x2e94] = 0xffc8, [0x2e95] = 0xffc9, -- [0x2e96] = 0xffca, [0x2e97] = 0xffcb, [0x2e98] = 0xffcc, [0x2e99] = 0xffcd, -- [0x2e9a] = 0xffce, [0x2e9b] = 0xffcf, [0x2e9c] = 0xffd0, [0x2e9d] = 0xffd1, -- [0x2e9e] = 0xffd2, [0x2e9f] = 0xffd3, [0x2ea0] = 0xffd4, [0x2ea1] = 0xffd5, -- [0x2ea2] = 0xffd6, [0x2ea3] = 0xffd7, [0x2ea4] = 0xffd8, [0x2ea5] = 0xffd9, -- [0x2ea6] = 0xffda, [0x2ea7] = 0xffdb, [0x2ea8] = 0xffdc, [0x2ea9] = 0xffdd, -- [0x2eaa] = 0xffde, [0x2eab] = 0xffdf, -+ [0x2d6c] = 0xfe0e, [0x2d6d] = 0xfe0f, [0x2d6e] = 0xe78d, [0x2d6f] = 0xe78f, -+ [0x2d70] = 0xe78e, [0x2d71] = 0xe790, [0x2d72] = 0xe791, [0x2d73] = 0xe792, -+ [0x2d74] = 0xe793, [0x2d75] = 0xe794, [0x2d76] = 0xe795, [0x2d77] = 0xe796, -+ [0x2d78] = 0xfe1a, [0x2d79] = 0xfe1b, [0x2d7a] = 0xfe1c, [0x2d7b] = 0xfe1d, -+ [0x2d7c] = 0xfe1e, [0x2d7d] = 0xfe1f, [0x2d7e] = 0xfe20, [0x2d7f] = 0xfe21, -+ [0x2d80] = 0xfe22, [0x2d81] = 0xfe23, [0x2d82] = 0xfe24, [0x2d83] = 0xfe25, -+ [0x2d84] = 0xfe26, [0x2d85] = 0xfe27, [0x2d86] = 0xfe28, [0x2d87] = 0xfe29, -+ [0x2d88] = 0xfe2a, [0x2d89] = 0xfe2b, [0x2d8a] = 0xfe2c, [0x2d8b] = 0xfe2d, -+ [0x2d8c] = 0xfe2e, [0x2d8d] = 0xfe2f, [0x2d8e] = 0xfe32, [0x2d8f] = 0xfe45, -+ [0x2d90] = 0xfe46, [0x2d91] = 0xfe47, [0x2d92] = 0xfe48, [0x2d93] = 0xfe53, -+ [0x2d94] = 0xfe58, [0x2d95] = 0xfe67, [0x2d96] = 0xfe6c, [0x2d97] = 0xfe6d, -+ [0x2d98] = 0xfe6e, [0x2d99] = 0xfe6f, [0x2d9a] = 0xfe70, [0x2d9b] = 0xfe71, -+ [0x2d9c] = 0xfe72, [0x2d9d] = 0xfe73, [0x2d9e] = 0xfe74, [0x2d9f] = 0xfe75, -+ [0x2da0] = 0xfe76, [0x2da1] = 0xfe77, [0x2da2] = 0xfe78, [0x2da3] = 0xfe79, -+ [0x2da4] = 0xfe7a, [0x2da5] = 0xfe7b, [0x2da6] = 0xfe7c, [0x2da7] = 0xfe7d, -+ [0x2da8] = 0xfe7e, [0x2da9] = 0xfe7f, [0x2daa] = 0xfe80, [0x2dab] = 0xfe81, -+ [0x2dac] = 0xfe82, [0x2dad] = 0xfe83, [0x2dae] = 0xfe84, [0x2daf] = 0xfe85, -+ [0x2db0] = 0xfe86, [0x2db1] = 0xfe87, [0x2db2] = 0xfe88, [0x2db3] = 0xfe89, -+ [0x2db4] = 0xfe8a, [0x2db5] = 0xfe8b, [0x2db6] = 0xfe8c, [0x2db7] = 0xfe8d, -+ [0x2db8] = 0xfe8e, [0x2db9] = 0xfe8f, [0x2dba] = 0xfe90, [0x2dbb] = 0xfe91, -+ [0x2dbc] = 0xfe92, [0x2dbd] = 0xfe93, [0x2dbe] = 0xfe94, [0x2dbf] = 0xfe95, -+ [0x2dc0] = 0xfe96, [0x2dc1] = 0xfe97, [0x2dc2] = 0xfe98, [0x2dc3] = 0xfe99, -+ [0x2dc4] = 0xfe9a, [0x2dc5] = 0xfe9b, [0x2dc6] = 0xfe9c, [0x2dc7] = 0xfe9d, -+ [0x2dc8] = 0xfe9e, [0x2dc9] = 0xfe9f, [0x2dca] = 0xfea0, [0x2dcb] = 0xfea1, -+ [0x2dcc] = 0xfea2, [0x2dcd] = 0xfea3, [0x2dce] = 0xfea4, [0x2dcf] = 0xfea5, -+ [0x2dd0] = 0xfea6, [0x2dd1] = 0xfea7, [0x2dd2] = 0xfea8, [0x2dd3] = 0xfea9, -+ [0x2dd4] = 0xfeaa, [0x2dd5] = 0xfeab, [0x2dd6] = 0xfeac, [0x2dd7] = 0xfead, -+ [0x2dd8] = 0xfeae, [0x2dd9] = 0xfeaf, [0x2dda] = 0xfeb0, [0x2ddb] = 0xfeb1, -+ [0x2ddc] = 0xfeb2, [0x2ddd] = 0xfeb3, [0x2dde] = 0xfeb4, [0x2ddf] = 0xfeb5, -+ [0x2de0] = 0xfeb6, [0x2de1] = 0xfeb7, [0x2de2] = 0xfeb8, [0x2de3] = 0xfeb9, -+ [0x2de4] = 0xfeba, [0x2de5] = 0xfebb, [0x2de6] = 0xfebc, [0x2de7] = 0xfebd, -+ [0x2de8] = 0xfebe, [0x2de9] = 0xfebf, [0x2dea] = 0xfec0, [0x2deb] = 0xfec1, -+ [0x2dec] = 0xfec2, [0x2ded] = 0xfec3, [0x2dee] = 0xfec4, [0x2def] = 0xfec5, -+ [0x2df0] = 0xfec6, [0x2df1] = 0xfec7, [0x2df2] = 0xfec8, [0x2df3] = 0xfec9, -+ [0x2df4] = 0xfeca, [0x2df5] = 0xfecb, [0x2df6] = 0xfecc, [0x2df7] = 0xfecd, -+ [0x2df8] = 0xfece, [0x2df9] = 0xfecf, [0x2dfa] = 0xfed0, [0x2dfb] = 0xfed1, -+ [0x2dfc] = 0xfed2, [0x2dfd] = 0xfed3, [0x2dfe] = 0xfed4, [0x2dff] = 0xfed5, -+ [0x2e00] = 0xfed6, [0x2e01] = 0xfed7, [0x2e02] = 0xfed8, [0x2e03] = 0xfed9, -+ [0x2e04] = 0xfeda, [0x2e05] = 0xfedb, [0x2e06] = 0xfedc, [0x2e07] = 0xfedd, -+ [0x2e08] = 0xfede, [0x2e09] = 0xfedf, [0x2e0a] = 0xfee0, [0x2e0b] = 0xfee1, -+ [0x2e0c] = 0xfee2, [0x2e0d] = 0xfee3, [0x2e0e] = 0xfee4, [0x2e0f] = 0xfee5, -+ [0x2e10] = 0xfee6, [0x2e11] = 0xfee7, [0x2e12] = 0xfee8, [0x2e13] = 0xfee9, -+ [0x2e14] = 0xfeea, [0x2e15] = 0xfeeb, [0x2e16] = 0xfeec, [0x2e17] = 0xfeed, -+ [0x2e18] = 0xfeee, [0x2e19] = 0xfeef, [0x2e1a] = 0xfef0, [0x2e1b] = 0xfef1, -+ [0x2e1c] = 0xfef2, [0x2e1d] = 0xfef3, [0x2e1e] = 0xfef4, [0x2e1f] = 0xfef5, -+ [0x2e20] = 0xfef6, [0x2e21] = 0xfef7, [0x2e22] = 0xfef8, [0x2e23] = 0xfef9, -+ [0x2e24] = 0xfefa, [0x2e25] = 0xfefb, [0x2e26] = 0xfefc, [0x2e27] = 0xfefd, -+ [0x2e28] = 0xfefe, [0x2e29] = 0xfeff, [0x2e2a] = 0xff00, [0x2e2b] = 0xff5f, -+ [0x2e2c] = 0xff60, [0x2e2d] = 0xff61, [0x2e2e] = 0xff62, [0x2e2f] = 0xff63, -+ [0x2e30] = 0xff64, [0x2e31] = 0xff65, [0x2e32] = 0xff66, [0x2e33] = 0xff67, -+ [0x2e34] = 0xff68, [0x2e35] = 0xff69, [0x2e36] = 0xff6a, [0x2e37] = 0xff6b, -+ [0x2e38] = 0xff6c, [0x2e39] = 0xff6d, [0x2e3a] = 0xff6e, [0x2e3b] = 0xff6f, -+ [0x2e3c] = 0xff70, [0x2e3d] = 0xff71, [0x2e3e] = 0xff72, [0x2e3f] = 0xff73, -+ [0x2e40] = 0xff74, [0x2e41] = 0xff75, [0x2e42] = 0xff76, [0x2e43] = 0xff77, -+ [0x2e44] = 0xff78, [0x2e45] = 0xff79, [0x2e46] = 0xff7a, [0x2e47] = 0xff7b, -+ [0x2e48] = 0xff7c, [0x2e49] = 0xff7d, [0x2e4a] = 0xff7e, [0x2e4b] = 0xff7f, -+ [0x2e4c] = 0xff80, [0x2e4d] = 0xff81, [0x2e4e] = 0xff82, [0x2e4f] = 0xff83, -+ [0x2e50] = 0xff84, [0x2e51] = 0xff85, [0x2e52] = 0xff86, [0x2e53] = 0xff87, -+ [0x2e54] = 0xff88, [0x2e55] = 0xff89, [0x2e56] = 0xff8a, [0x2e57] = 0xff8b, -+ [0x2e58] = 0xff8c, [0x2e59] = 0xff8d, [0x2e5a] = 0xff8e, [0x2e5b] = 0xff8f, -+ [0x2e5c] = 0xff90, [0x2e5d] = 0xff91, [0x2e5e] = 0xff92, [0x2e5f] = 0xff93, -+ [0x2e60] = 0xff94, [0x2e61] = 0xff95, [0x2e62] = 0xff96, [0x2e63] = 0xff97, -+ [0x2e64] = 0xff98, [0x2e65] = 0xff99, [0x2e66] = 0xff9a, [0x2e67] = 0xff9b, -+ [0x2e68] = 0xff9c, [0x2e69] = 0xff9d, [0x2e6a] = 0xff9e, [0x2e6b] = 0xff9f, -+ [0x2e6c] = 0xffa0, [0x2e6d] = 0xffa1, [0x2e6e] = 0xffa2, [0x2e6f] = 0xffa3, -+ [0x2e70] = 0xffa4, [0x2e71] = 0xffa5, [0x2e72] = 0xffa6, [0x2e73] = 0xffa7, -+ [0x2e74] = 0xffa8, [0x2e75] = 0xffa9, [0x2e76] = 0xffaa, [0x2e77] = 0xffab, -+ [0x2e78] = 0xffac, [0x2e79] = 0xffad, [0x2e7a] = 0xffae, [0x2e7b] = 0xffaf, -+ [0x2e7c] = 0xffb0, [0x2e7d] = 0xffb1, [0x2e7e] = 0xffb2, [0x2e7f] = 0xffb3, -+ [0x2e80] = 0xffb4, [0x2e81] = 0xffb5, [0x2e82] = 0xffb6, [0x2e83] = 0xffb7, -+ [0x2e84] = 0xffb8, [0x2e85] = 0xffb9, [0x2e86] = 0xffba, [0x2e87] = 0xffbb, -+ [0x2e88] = 0xffbc, [0x2e89] = 0xffbd, [0x2e8a] = 0xffbe, [0x2e8b] = 0xffbf, -+ [0x2e8c] = 0xffc0, [0x2e8d] = 0xffc1, [0x2e8e] = 0xffc2, [0x2e8f] = 0xffc3, -+ [0x2e90] = 0xffc4, [0x2e91] = 0xffc5, [0x2e92] = 0xffc6, [0x2e93] = 0xffc7, -+ [0x2e94] = 0xffc8, [0x2e95] = 0xffc9, [0x2e96] = 0xffca, [0x2e97] = 0xffcb, -+ [0x2e98] = 0xffcc, [0x2e99] = 0xffcd, [0x2e9a] = 0xffce, [0x2e9b] = 0xffcf, -+ [0x2e9c] = 0xffd0, [0x2e9d] = 0xffd1, [0x2e9e] = 0xffd2, [0x2e9f] = 0xffd3, -+ [0x2ea0] = 0xffd4, [0x2ea1] = 0xffd5, [0x2ea2] = 0xffd6, [0x2ea3] = 0xffd7, -+ [0x2ea4] = 0xffd8, [0x2ea5] = 0xffd9, [0x2ea6] = 0xffda, [0x2ea7] = 0xffdb, -+ [0x2ea8] = 0xffdc, [0x2ea9] = 0xffdd, [0x2eaa] = 0xffde, [0x2eab] = 0xffdf, - }; - - /* Table for UCS-4 -> GB18030, for the range U+0080..U+9FBB. -@@ -23448,71 +23453,79 @@ static const unsigned char __ucs_to_gb18030_tab2[][2] = - [0x0783] = "\xa5\xfd", [0x0784] = "\xa5\xfe", [0x0785] = "\xa6\xb9", - [0x0786] = "\xa6\xba", [0x0787] = "\xa6\xbb", [0x0788] = "\xa6\xbc", - [0x0789] = "\xa6\xbd", [0x078a] = "\xa6\xbe", [0x078b] = "\xa6\xbf", -- [0x078c] = "\xa6\xc0", [0x0797] = "\xa6\xf6", [0x0798] = "\xa6\xf7", -- [0x0799] = "\xa6\xf8", [0x079a] = "\xa6\xf9", [0x079b] = "\xa6\xfa", -- [0x079c] = "\xa6\xfb", [0x079d] = "\xa6\xfc", [0x079e] = "\xa6\xfd", -- [0x079f] = "\xa6\xfe", [0x07a0] = "\xa7\xc2", [0x07a1] = "\xa7\xc3", -- [0x07a2] = "\xa7\xc4", [0x07a3] = "\xa7\xc5", [0x07a4] = "\xa7\xc6", -- [0x07a5] = "\xa7\xc7", [0x07a6] = "\xa7\xc8", [0x07a7] = "\xa7\xc9", -- [0x07a8] = "\xa7\xca", [0x07a9] = "\xa7\xcb", [0x07aa] = "\xa7\xcc", -- [0x07ab] = "\xa7\xcd", [0x07ac] = "\xa7\xce", [0x07ad] = "\xa7\xcf", -- [0x07ae] = "\xa7\xd0", [0x07af] = "\xa7\xf2", [0x07b0] = "\xa7\xf3", -- [0x07b1] = "\xa7\xf4", [0x07b2] = "\xa7\xf5", [0x07b3] = "\xa7\xf6", -- [0x07b4] = "\xa7\xf7", [0x07b5] = "\xa7\xf8", [0x07b6] = "\xa7\xf9", -- [0x07b7] = "\xa7\xfa", [0x07b8] = "\xa7\xfb", [0x07b9] = "\xa7\xfc", -- [0x07ba] = "\xa7\xfd", [0x07bb] = "\xa7\xfe", [0x07bc] = "\xa8\x96", -- [0x07bd] = "\xa8\x97", [0x07be] = "\xa8\x98", [0x07bf] = "\xa8\x99", -- [0x07c0] = "\xa8\x9a", [0x07c1] = "\xa8\x9b", [0x07c2] = "\xa8\x9c", -- [0x07c3] = "\xa8\x9d", [0x07c4] = "\xa8\x9e", [0x07c5] = "\xa8\x9f", -- [0x07c6] = "\xa8\xa0", [0x07c7] = "\x00\x01", [0x07c8] = "\x65\x9e", -- [0x07c9] = "\xa8\xc1", [0x07ca] = "\xa8\xc2", [0x07cb] = "\xa8\xc3", -- [0x07cc] = "\xa8\xc4", [0x07cd] = "\xa8\xea", [0x07ce] = "\xa8\xeb", -- [0x07cf] = "\xa8\xec", [0x07d0] = "\xa8\xed", [0x07d1] = "\xa8\xee", -- [0x07d2] = "\xa8\xef", [0x07d3] = "\xa8\xf0", [0x07d4] = "\xa8\xf1", -- [0x07d5] = "\xa8\xf2", [0x07d6] = "\xa8\xf3", [0x07d7] = "\xa8\xf4", -- [0x07d8] = "\xa8\xf5", [0x07d9] = "\xa8\xf6", [0x07da] = "\xa8\xf7", -- [0x07db] = "\xa8\xf8", [0x07dc] = "\xa8\xf9", [0x07dd] = "\xa8\xfa", -- [0x07de] = "\xa8\xfb", [0x07df] = "\xa8\xfc", [0x07e0] = "\xa8\xfd", -- [0x07e1] = "\xa8\xfe", [0x07e2] = "\xa9\x58", [0x07e3] = "\xa9\x5b", -- [0x07e4] = "\xa9\x5d", [0x07e5] = "\xa9\x5e", [0x07e6] = "\xa9\x5f", -- [0x07e7] = "\x65\x9f", [0x07e8] = "\x65\xa0", [0x07e9] = "\x65\xa1", -- [0x07ea] = "\x65\xa2", [0x07eb] = "\x65\xa3", [0x07ec] = "\x65\xa4", -- [0x07ed] = "\x65\xa5", [0x07ee] = "\x65\xa6", [0x07ef] = "\x65\xa7", -- [0x07f0] = "\x65\xa8", [0x07f1] = "\x65\xa9", [0x07f2] = "\x65\xaa", -- [0x07f3] = "\x65\xab", [0x07f4] = "\xa9\x97", [0x07f5] = "\xa9\x98", -- [0x07f6] = "\xa9\x99", [0x07f7] = "\xa9\x9a", [0x07f8] = "\xa9\x9b", -- [0x07f9] = "\xa9\x9c", [0x07fa] = "\xa9\x9d", [0x07fb] = "\xa9\x9e", -- [0x07fc] = "\xa9\x9f", [0x07fd] = "\xa9\xa0", [0x07fe] = "\xa9\xa1", -- [0x07ff] = "\xa9\xa2", [0x0800] = "\xa9\xa3", [0x0801] = "\xa9\xf0", -- [0x0802] = "\xa9\xf1", [0x0803] = "\xa9\xf2", [0x0804] = "\xa9\xf3", -- [0x0805] = "\xa9\xf4", [0x0806] = "\xa9\xf5", [0x0807] = "\xa9\xf6", -- [0x0808] = "\xa9\xf7", [0x0809] = "\xa9\xf8", [0x080a] = "\xa9\xf9", -- [0x080b] = "\xa9\xfa", [0x080c] = "\xa9\xfb", [0x080d] = "\xa9\xfc", -- [0x080e] = "\xa9\xfd", [0x080f] = "\xa9\xfe", [0x0810] = "\xd7\xfa", -- [0x0811] = "\xd7\xfb", [0x0812] = "\xd7\xfc", [0x0813] = "\xd7\xfd", -- [0x0814] = "\xd7\xfe", [0x0815] = "\x65\xac", [0x0819] = "\x65\xad", -- [0x081a] = "\x65\xae", [0x081b] = "\x65\xaf", [0x081c] = "\x65\xb0", -- [0x081d] = "\x65\xb1", [0x081f] = "\x65\xb2", [0x0820] = "\x65\xb3", -- [0x0821] = "\x65\xb4", [0x0822] = "\x65\xb5", [0x0823] = "\x65\xb6", -- [0x0824] = "\x65\xb7", [0x0825] = "\x65\xb8", [0x0827] = "\x65\xb9", -+ [0x078c] = "\xa6\xc0", [0x078d] = "\x7b\x84", [0x078e] = "\x7b\x86", -+ [0x078f] = "\x7b\x85", [0x0790] = "\x7b\x87", [0x0791] = "\x7b\x88", -+ [0x0792] = "\x7b\x89", [0x0793] = "\x7b\x8a", [0x0794] = "\x7b\x8b", -+ [0x0795] = "\x7b\x8c", [0x0796] = "\x7b\x8d", [0x0797] = "\xa6\xf6", -+ [0x0798] = "\xa6\xf7", [0x0799] = "\xa6\xf8", [0x079a] = "\xa6\xf9", -+ [0x079b] = "\xa6\xfa", [0x079c] = "\xa6\xfb", [0x079d] = "\xa6\xfc", -+ [0x079e] = "\xa6\xfd", [0x079f] = "\xa6\xfe", [0x07a0] = "\xa7\xc2", -+ [0x07a1] = "\xa7\xc3", [0x07a2] = "\xa7\xc4", [0x07a3] = "\xa7\xc5", -+ [0x07a4] = "\xa7\xc6", [0x07a5] = "\xa7\xc7", [0x07a6] = "\xa7\xc8", -+ [0x07a7] = "\xa7\xc9", [0x07a8] = "\xa7\xca", [0x07a9] = "\xa7\xcb", -+ [0x07aa] = "\xa7\xcc", [0x07ab] = "\xa7\xcd", [0x07ac] = "\xa7\xce", -+ [0x07ad] = "\xa7\xcf", [0x07ae] = "\xa7\xd0", [0x07af] = "\xa7\xf2", -+ [0x07b0] = "\xa7\xf3", [0x07b1] = "\xa7\xf4", [0x07b2] = "\xa7\xf5", -+ [0x07b3] = "\xa7\xf6", [0x07b4] = "\xa7\xf7", [0x07b5] = "\xa7\xf8", -+ [0x07b6] = "\xa7\xf9", [0x07b7] = "\xa7\xfa", [0x07b8] = "\xa7\xfb", -+ [0x07b9] = "\xa7\xfc", [0x07ba] = "\xa7\xfd", [0x07bb] = "\xa7\xfe", -+ [0x07bc] = "\xa8\x96", [0x07bd] = "\xa8\x97", [0x07be] = "\xa8\x98", -+ [0x07bf] = "\xa8\x99", [0x07c0] = "\xa8\x9a", [0x07c1] = "\xa8\x9b", -+ [0x07c2] = "\xa8\x9c", [0x07c3] = "\xa8\x9d", [0x07c4] = "\xa8\x9e", -+ [0x07c5] = "\xa8\x9f", [0x07c6] = "\xa8\xa0", [0x07c7] = "\x00\x01", -+ [0x07c8] = "\x65\x9e", [0x07c9] = "\xa8\xc1", [0x07ca] = "\xa8\xc2", -+ [0x07cb] = "\xa8\xc3", [0x07cc] = "\xa8\xc4", [0x07cd] = "\xa8\xea", -+ [0x07ce] = "\xa8\xeb", [0x07cf] = "\xa8\xec", [0x07d0] = "\xa8\xed", -+ [0x07d1] = "\xa8\xee", [0x07d2] = "\xa8\xef", [0x07d3] = "\xa8\xf0", -+ [0x07d4] = "\xa8\xf1", [0x07d5] = "\xa8\xf2", [0x07d6] = "\xa8\xf3", -+ [0x07d7] = "\xa8\xf4", [0x07d8] = "\xa8\xf5", [0x07d9] = "\xa8\xf6", -+ [0x07da] = "\xa8\xf7", [0x07db] = "\xa8\xf8", [0x07dc] = "\xa8\xf9", -+ [0x07dd] = "\xa8\xfa", [0x07de] = "\xa8\xfb", [0x07df] = "\xa8\xfc", -+ [0x07e0] = "\xa8\xfd", [0x07e1] = "\xa8\xfe", [0x07e2] = "\xa9\x58", -+ [0x07e3] = "\xa9\x5b", [0x07e4] = "\xa9\x5d", [0x07e5] = "\xa9\x5e", -+ [0x07e6] = "\xa9\x5f", [0x07e7] = "\x65\x9f", [0x07e8] = "\x65\xa0", -+ [0x07e9] = "\x65\xa1", [0x07ea] = "\x65\xa2", [0x07eb] = "\x65\xa3", -+ [0x07ec] = "\x65\xa4", [0x07ed] = "\x65\xa5", [0x07ee] = "\x65\xa6", -+ [0x07ef] = "\x65\xa7", [0x07f0] = "\x65\xa8", [0x07f1] = "\x65\xa9", -+ [0x07f2] = "\x65\xaa", [0x07f3] = "\x65\xab", [0x07f4] = "\xa9\x97", -+ [0x07f5] = "\xa9\x98", [0x07f6] = "\xa9\x99", [0x07f7] = "\xa9\x9a", -+ [0x07f8] = "\xa9\x9b", [0x07f9] = "\xa9\x9c", [0x07fa] = "\xa9\x9d", -+ [0x07fb] = "\xa9\x9e", [0x07fc] = "\xa9\x9f", [0x07fd] = "\xa9\xa0", -+ [0x07fe] = "\xa9\xa1", [0x07ff] = "\xa9\xa2", [0x0800] = "\xa9\xa3", -+ [0x0801] = "\xa9\xf0", [0x0802] = "\xa9\xf1", [0x0803] = "\xa9\xf2", -+ [0x0804] = "\xa9\xf3", [0x0805] = "\xa9\xf4", [0x0806] = "\xa9\xf5", -+ [0x0807] = "\xa9\xf6", [0x0808] = "\xa9\xf7", [0x0809] = "\xa9\xf8", -+ [0x080a] = "\xa9\xf9", [0x080b] = "\xa9\xfa", [0x080c] = "\xa9\xfb", -+ [0x080d] = "\xa9\xfc", [0x080e] = "\xa9\xfd", [0x080f] = "\xa9\xfe", -+ [0x0810] = "\xd7\xfa", [0x0811] = "\xd7\xfb", [0x0812] = "\xd7\xfc", -+ [0x0813] = "\xd7\xfd", [0x0814] = "\xd7\xfe", [0x0815] = "\x65\xac", -+ [0x0816] = "\xfe\x51", [0x0817] = "\xfe\x52", [0x0818] = "\xfe\x53", -+ [0x0819] = "\x65\xad", [0x081a] = "\x65\xae", [0x081b] = "\x65\xaf", -+ [0x081c] = "\x65\xb0", [0x081d] = "\x65\xb1", [0x081e] = "\x2d\x51", -+ [0x081f] = "\x65\xb2", [0x0820] = "\x65\xb3", [0x0821] = "\x65\xb4", -+ [0x0822] = "\x65\xb5", [0x0823] = "\x65\xb6", [0x0824] = "\x65\xb7", -+ [0x0825] = "\x65\xb8", [0x0826] = "\x2d\x52", [0x0827] = "\x65\xb9", - [0x0828] = "\x65\xba", [0x0829] = "\x65\xbb", [0x082a] = "\x65\xbc", -- [0x082d] = "\x65\xbd", [0x082e] = "\x65\xbe", [0x082f] = "\x65\xbf", -- [0x0830] = "\x65\xc0", [0x0833] = "\x65\xc1", [0x0834] = "\x65\xc2", -- [0x0835] = "\x65\xc3", [0x0836] = "\x65\xc4", [0x0837] = "\x65\xc5", -- [0x0838] = "\x65\xc6", [0x0839] = "\x65\xc7", [0x083a] = "\x65\xc8", -- [0x083c] = "\x65\xc9", [0x083d] = "\x65\xca", [0x083e] = "\x65\xcb", -- [0x083f] = "\x65\xcc", [0x0840] = "\x65\xcd", [0x0841] = "\x65\xce", -- [0x0842] = "\x65\xcf", [0x0844] = "\x65\xd0", [0x0845] = "\x65\xd1", -+ [0x082b] = "\x2d\x53", [0x082c] = "\x2d\x54", [0x082d] = "\x65\xbd", -+ [0x082e] = "\x65\xbe", [0x082f] = "\x65\xbf", [0x0830] = "\x65\xc0", -+ [0x0831] = "\xfe\x6c", [0x0832] = "\x2d\x55", [0x0833] = "\x65\xc1", -+ [0x0834] = "\x65\xc2", [0x0835] = "\x65\xc3", [0x0836] = "\x65\xc4", -+ [0x0837] = "\x65\xc5", [0x0838] = "\x65\xc6", [0x0839] = "\x65\xc7", -+ [0x083a] = "\x65\xc8", [0x083b] = "\xfe\x76", [0x083c] = "\x65\xc9", -+ [0x083d] = "\x65\xca", [0x083e] = "\x65\xcb", [0x083f] = "\x65\xcc", -+ [0x0840] = "\x65\xcd", [0x0841] = "\x65\xce", [0x0842] = "\x65\xcf", -+ [0x0843] = "\x2d\x56", [0x0844] = "\x65\xd0", [0x0845] = "\x65\xd1", - [0x0846] = "\x65\xd2", [0x0847] = "\x65\xd3", [0x0848] = "\x65\xd4", - [0x0849] = "\x65\xd5", [0x084a] = "\x65\xd6", [0x084b] = "\x65\xd7", - [0x084c] = "\x65\xd8", [0x084d] = "\x65\xd9", [0x084e] = "\x65\xda", - [0x084f] = "\x65\xdb", [0x0850] = "\x65\xdc", [0x0851] = "\x65\xdd", -- [0x0852] = "\x65\xde", [0x0853] = "\x65\xdf", [0x0856] = "\x65\xe0", -- [0x0857] = "\x65\xe1", [0x0858] = "\x65\xe2", [0x0859] = "\x65\xe3", -- [0x085a] = "\x65\xe4", [0x085b] = "\x65\xe5", [0x085c] = "\x65\xe6", -- [0x085d] = "\x65\xe7", [0x085e] = "\x65\xe8", [0x085f] = "\x65\xe9", -- [0x0860] = "\x65\xea", [0x0861] = "\x65\xeb", [0x0862] = "\x65\xec", -- [0x0863] = "\x65\xed", [0x0865] = "\xfd\x9c", [0x0866] = "\x76\xb5", -+ [0x0852] = "\x65\xde", [0x0853] = "\x65\xdf", [0x0854] = "\x2d\x57", -+ [0x0855] = "\xfe\x91", [0x0856] = "\x65\xe0", [0x0857] = "\x65\xe1", -+ [0x0858] = "\x65\xe2", [0x0859] = "\x65\xe3", [0x085a] = "\x65\xe4", -+ [0x085b] = "\x65\xe5", [0x085c] = "\x65\xe6", [0x085d] = "\x65\xe7", -+ [0x085e] = "\x65\xe8", [0x085f] = "\x65\xe9", [0x0860] = "\x65\xea", -+ [0x0861] = "\x65\xeb", [0x0862] = "\x65\xec", [0x0863] = "\x65\xed", -+ [0x0864] = "\x2d\x58", [0x0865] = "\xfd\x9c", [0x0866] = "\x76\xb5", - [0x0867] = "\x76\xb6", [0x0868] = "\x76\xb7", [0x0869] = "\x76\xb8", - [0x086a] = "\x76\xb9", [0x086b] = "\x76\xba", [0x086c] = "\x76\xbb", - [0x086d] = "\x76\xbc", [0x086e] = "\x76\xbd", [0x086f] = "\x76\xbe", -@@ -24222,24 +24235,8 @@ static const unsigned char __ucs_to_gb18030_tab2[][2] = - || (ch = __twobyte_to_ucs[idx], \ - ch == 0 && *inptr != '\0')) \ - { \ -- /* Handle a few special cases. */ \ -- if (idx == 0x5dd1) \ -- ch = 0x20087; \ -- else if (idx == 0x5dd2) \ -- ch = 0x20089; \ -- else if (idx == 0x5dd3) \ -- ch = 0x200cc; \ -- else if (idx == 0x5dec) \ -- ch = 0x215D7; \ -- else if (idx == 0x5df6) \ -- ch = 0x2298F; \ -- else if (idx == 0x5e11) \ -- ch = 0x241FE; \ -- else \ -- { \ -- /* This is an illegal character. */ \ -- STANDARD_FROM_LOOP_ERR_HANDLER (2); \ -- } \ -+ /* This is an illegal character. */ \ -+ STANDARD_FROM_LOOP_ERR_HANDLER (2); \ - } \ - \ - inptr += 2; \ -@@ -24331,17 +24328,35 @@ static const unsigned char __ucs_to_gb18030_tab2[][2] = - len = 4; \ - } \ - else if (ch == 0x20087) \ -- cp = (const unsigned char *) "\xfe\x51"; \ -+ { \ -+ idx = 0x3E2CF; \ -+ len = 4; \ -+ } \ - else if (ch == 0x20089) \ -- cp = (const unsigned char *) "\xfe\x52"; \ -+ { \ -+ idx = 0x3E2D1; \ -+ len = 4; \ -+ } \ - else if (ch == 0x200CC) \ -- cp = (const unsigned char *) "\xfe\x53"; \ -+ { \ -+ idx = 0x3E314; \ -+ len = 4; \ -+ } \ - else if (ch == 0x215d7) \ -- cp = (const unsigned char *) "\xfe\x6c"; \ -+ { \ -+ idx = 0x3F81F; \ -+ len = 4; \ -+ } \ - else if (ch == 0x2298F) \ -- cp = (const unsigned char *) "\xfe\x76"; \ -+ { \ -+ idx = 0x40BD7; \ -+ len = 4; \ -+ } \ - else if (ch == 0x241FE) \ -- cp = (const unsigned char *) "\xfe\x91"; \ -+ { \ -+ idx = 0x42446; \ -+ len = 4; \ -+ } \ - else if (ch >= 0x10000 && ch <= 0x10FFFF) \ - { \ - idx = ch + 0x1E248; \ -diff --git a/iconvdata/tst-table-from.c b/iconvdata/tst-table-from.c -index 9ad1f44e..c881c86b 100644 ---- a/iconvdata/tst-table-from.c -+++ b/iconvdata/tst-table-from.c -@@ -195,10 +195,9 @@ main (int argc, char *argv[]) - exit (1); - } - -- /* When testing UTF-8 or GB18030, stop at 0x10000, otherwise the output -+ /* When testing UTF-8, stop at 0x10000, otherwise the output - file gets too big. */ -- bmp_only = (strcmp (charset, "UTF-8") == 0 -- || strcmp (charset, "GB18030") == 0); -+ bmp_only = (strcmp (charset, "UTF-8") == 0); - search_depth = (strcmp (charset, "UTF-8") == 0 ? 3 : 4); - - { -diff --git a/iconvdata/tst-table-to.c b/iconvdata/tst-table-to.c -index 6f0aa29c..8d097527 100644 ---- a/iconvdata/tst-table-to.c -+++ b/iconvdata/tst-table-to.c -@@ -33,6 +33,7 @@ main (int argc, char *argv[]) - const char *charset; - iconv_t cd; - int bmp_only; -+ int no_tags; - - if (argc != 2) - { -@@ -48,16 +49,19 @@ main (int argc, char *argv[]) - return 1; - } - -- /* When testing UTF-8 or GB18030, stop at 0x10000, otherwise the output -+ /* When testing UTF-8, stop at 0x10000, otherwise the output - file gets too big. */ -- bmp_only = (strcmp (charset, "UTF-8") == 0 -+ bmp_only = (strcmp (charset, "UTF-8") == 0); -+ /* When testing any encoding other than UTF-8 or GB18030, stop at 0xE0000, -+ because the conversion drops Unicode tag characters (range -+ U+E0000..U+E007F). */ -+ no_tags = !(strcmp (charset, "UTF-8") == 0 - || strcmp (charset, "GB18030") == 0); - - { - unsigned int i; - unsigned char buf[10]; -- -- for (i = 0; i < (bmp_only ? 0x10000 : 0x30000); i++) -+ for (i = 0; i < (bmp_only ? 0x10000 : no_tags ? 0xE0000 : 0x110000); i++) - { - unsigned char in[6]; - unsigned int incount = -diff --git a/iconvdata/tst-table.sh b/iconvdata/tst-table.sh -index 04c06136..3c6927ee 100755 ---- a/iconvdata/tst-table.sh -+++ b/iconvdata/tst-table.sh -@@ -38,7 +38,8 @@ set -e - < ../localedata/charmaps/${charmap:-$charset} \ - > ${objpfx}tst-${charset}.charmap.table - # When the charset is GB18030, truncate this table because for this encoding, --# the tst-table-from and tst-table-to programs scan the Unicode BMP only. -+# the charmap contains ranges (.. notation), which the -+# tst-table-charmap.sh script does not grok. - if test ${charset} = GB18030; then - grep '0x....$' < ${objpfx}tst-${charset}.charmap.table \ - > ${objpfx}tst-${charset}.truncated.table -@@ -74,25 +75,42 @@ diff ${objpfx}tst-${charset}.charmap.table ${objpfx}tst-${charset}.inverse.table - - # Check 1: charmap and iconv forward should be identical, except for - # precomposed characters. --if test -f ${precomposed}; then -- cat ${objpfx}tst-${charset}.table ${precomposed} | sort | uniq -u \ -- > ${objpfx}tst-${charset}.tmp.table -- cmp -s ${objpfx}tst-${charset}.charmap.table ${objpfx}tst-${charset}.tmp.table || -+{ if test -f ${precomposed}; then -+ cat ${objpfx}tst-${charset}.table ${precomposed} | sort | uniq -u -+ else -+ cat ${objpfx}tst-${charset}.table -+ fi -+} | { if test ${charset} = GB18030; then grep '0x....$'; else cat; fi; } \ -+ > ${objpfx}tst-${charset}.tmp1.table -+cmp -s ${objpfx}tst-${charset}.charmap.table ${objpfx}tst-${charset}.tmp1.table || - exit 1 --else -- cmp -s ${objpfx}tst-${charset}.charmap.table ${objpfx}tst-${charset}.table || -- exit 1 --fi - - # Check 2: the difference between the charmap and iconv backward. --if test -f ${irreversible}; then -- cat ${objpfx}tst-${charset}.charmap.table ${irreversible} | sort | uniq -u \ -- > ${objpfx}tst-${charset}.tmp.table -- cmp -s ${objpfx}tst-${charset}.tmp.table ${objpfx}tst-${charset}.inverse.table || -- exit 1 --else -- cmp -s ${objpfx}tst-${charset}.charmap.table ${objpfx}tst-${charset}.inverse.table || -+{ if test -f ${irreversible}; then -+ cat ${objpfx}tst-${charset}.charmap.table ${irreversible} | sort | uniq -u -+ else -+ cat ${objpfx}tst-${charset}.charmap.table -+ fi -+} | { if test ${charset} = GB18030; then grep '0x....$'; else cat; fi; } \ -+ > ${objpfx}tst-${charset}.tmp2c.table -+cat ${objpfx}tst-${charset}.inverse.table \ -+ | { if test ${charset} = GB18030; then grep '0x....$'; else cat; fi; } \ -+ > ${objpfx}tst-${charset}.tmp2i.table -+cmp -s ${objpfx}tst-${charset}.tmp2c.table ${objpfx}tst-${charset}.tmp2i.table || - exit 1 -+ -+# Check 3: the difference between iconv forward and iconv backward. This is -+# necessary only for GB18030, because ${objpfx}tst-${charset}.charmap.table -+# is truncated for this encoding (see above). -+if test ${charset} = GB18030; then -+ { if test -f ${irreversible}; then -+ cat ${objpfx}tst-${charset}.table ${irreversible} | sort | uniq -u -+ else -+ cat ${objpfx}tst-${charset}.table -+ fi -+ } > ${objpfx}tst-${charset}.tmp3.table -+ cmp -s ${objpfx}tst-${charset}.tmp3.table ${objpfx}tst-${charset}.inverse.table || -+ exit 1 - fi - - exit 0 -diff --git a/localedata/charmaps/GB18030 b/localedata/charmaps/GB18030 -index ad6728c5..fc3b1d2d 100644 ---- a/localedata/charmaps/GB18030 -+++ b/localedata/charmaps/GB18030 -@@ -57234,32 +57234,16 @@ CHARMAP - /xa6/xbe - /xa6/xbf - /xa6/xc0 --% The newest GB 18030-2005 standard still uses some private use area --% code points. Any implementation which has Unicode 4.1 or newer --% support should not use these PUA code points, and instead should --% map these entries to their equivalent non-PUA code points. There --% are 24 idiograms in GB 18030-2005 which have non-PUA equivalents. --% In glibc we only support roundtrip code points, and so must choose --% between supporting the old PUA code points, or using the newer --% non-PUA code points. We choose to use the non-PUA code points to --% be compatible with ICU's similar choice. In choosing the non-PUA --% code points we can no longer convert the old PUA code points back --% to GB-18030-2005 (technically only fixable if we added support --% for non-roundtrip code points e.g. ICU's "fallback mapping"). --% The recommendation to use the non-PUA code points, where available, --% is based on "CJKV Information Processing" 2nd Ed. by Dr. Ken Lunde. --% --% These 10 PUA mappings use equivalents from to . --% /xa6/xd9 --% /xa6/xda --% /xa6/xdb --% /xa6/xdc --% /xa6/xdd --% /xa6/xde --% /xa6/xdf --% /xa6/xec --% /xa6/xed --% /xa6/xf3 -+ /x84/x31/x82/x36 -+ /x84/x31/x82/x38 -+ /x84/x31/x82/x37 -+ /x84/x31/x82/x39 -+ /x84/x31/x83/x30 -+ /x84/x31/x83/x31 -+ /x84/x31/x83/x32 -+ /x84/x31/x83/x33 -+ /x84/x31/x83/x34 -+ /x84/x31/x83/x35 - /xa6/xf6 - /xa6/xf7 - /xa6/xf8 -@@ -57387,17 +57371,15 @@ CHARMAP - /xd7/xfd - /xd7/xfe - /x83/x36/xc9/x34 --% These 3 PUA mappings use equivalents , and . --% /xfe/x51 --% /xfe/x52 --% /xfe/x53 -+ /xfe/x51 -+ /xfe/x52 -+ /xfe/x53 - /x83/x36/xc9/x35 - /x83/x36/xc9/x36 - /x83/x36/xc9/x37 - /x83/x36/xc9/x38 - /x83/x36/xc9/x39 --% This 1 PUA mapping uses the equivalent . --% /xfe/x59 -+ /x82/x35/x90/x37 - /x83/x36/xca/x30 - /x83/x36/xca/x31 - /x83/x36/xca/x32 -@@ -57405,22 +57387,19 @@ CHARMAP - /x83/x36/xca/x34 - /x83/x36/xca/x35 - /x83/x36/xca/x36 --% This 1 PUA mapping uses the equivalent . --% /xfe/x61 -+ /x82/x35/x90/x38 - /x83/x36/xca/x37 - /x83/x36/xca/x38 - /x83/x36/xca/x39 - /x83/x36/xcb/x30 --% These 2 PUA mappings use the equivalents and . --% /xfe/x66 --% /xfe/x67 -+ /x82/x35/x90/x39 -+ /x82/x35/x91/x30 - /x83/x36/xcb/x31 - /x83/x36/xcb/x32 - /x83/x36/xcb/x33 - /x83/x36/xcb/x34 --% These 2 PUA mappings use the equivalents and . --% /xfe/x6c --% /xfe/x6d -+ /xfe/x6c -+ /x82/x35/x91/x31 - /x83/x36/xcb/x35 - /x83/x36/xcb/x36 - /x83/x36/xcb/x37 -@@ -57429,8 +57408,7 @@ CHARMAP - /x83/x36/xcc/x30 - /x83/x36/xcc/x31 - /x83/x36/xcc/x32 --% This 1 PUA mapping uses the equivalent . --% /xfe/x76 -+ /xfe/x76 - /x83/x36/xcc/x33 - /x83/x36/xcc/x34 - /x83/x36/xcc/x35 -@@ -57438,8 +57416,7 @@ CHARMAP - /x83/x36/xcc/x37 - /x83/x36/xcc/x38 - /x83/x36/xcc/x39 --% This 1 PUA mapping uses the equivalent . --% /xfe/x7e -+ /x82/x35/x91/x32 - /x83/x36/xcd/x30 - /x83/x36/xcd/x31 - /x83/x36/xcd/x32 -@@ -57456,9 +57433,8 @@ CHARMAP - /x83/x36/xce/x33 - /x83/x36/xce/x34 - /x83/x36/xce/x35 --% These 2 PUA mappings use the equivalents and . --% /xfe/x90 --% /xfe/x91 -+ /x82/x35/x91/x33 -+ /xfe/x91 - /x83/x36/xce/x36 - /x83/x36/xce/x37 - /x83/x36/xce/x38 -@@ -57473,8 +57449,7 @@ CHARMAP - /x83/x36/xcf/x37 - /x83/x36/xcf/x38 - /x83/x36/xcf/x39 --% This 1 PUA mapping uses the equivalent . --% /xfe/xa0 -+ /x82/x35/x91/x34 - /x83/x36/xd0/x30 - /x83/x36/xd0/x31 - /x83/x36/xd0/x32 -@@ -70447,19 +70422,14 @@ CHARMAP - .. /x95/x32/x8d/x30 - .. /x95/x32/x8e/x30 - .. /x95/x32/x8f/x30 -- /x95/x32/x90/x30 -- /xfe/x51 -- /x95/x32/x90/x32 -- /xfe/x52 --.. /x95/x32/x90/x34 -+.. /x95/x32/x90/x30 - .. /x95/x32/x91/x30 - .. /x95/x32/x92/x30 - .. /x95/x32/x93/x30 - .. /x95/x32/x94/x30 - .. /x95/x32/x95/x30 - .. /x95/x32/x96/x30 -- /xfe/x53 --.. /x95/x32/x97/x31 -+.. /x95/x32/x97/x30 - .. /x95/x32/x98/x30 - .. /x95/x32/x99/x30 - .. /x95/x32/x9a/x30 -@@ -70998,8 +70968,7 @@ CHARMAP - .. /x95/x36/xb7/x30 - .. /x95/x36/xb8/x30 - .. /x95/x36/xb9/x30 -- /xfe/x6c --.. /x95/x36/xb9/x38 -+.. /x95/x36/xb9/x37 - .. /x95/x36/xba/x30 - .. /x95/x36/xbb/x30 - .. /x95/x36/xbc/x30 -@@ -71505,8 +71474,7 @@ CHARMAP - .. /x96/x30/xb8/x30 - .. /x96/x30/xb9/x30 - .. /x96/x30/xba/x30 -- /xfe/x76 --.. /x96/x30/xba/x36 -+.. /x96/x30/xba/x35 - .. /x96/x30/xbb/x30 - .. /x96/x30/xbc/x30 - .. /x96/x30/xbd/x30 -@@ -72132,8 +72100,7 @@ CHARMAP - .. /x96/x35/xb3/x30 - .. /x96/x35/xb4/x30 - .. /x96/x35/xb5/x30 -- /xfe/x91 --.. /x96/x35/xb6/x31 -+.. /x96/x35/xb6/x30 - .. /x96/x35/xb7/x30 - .. /x96/x35/xb8/x30 - .. /x96/x35/xb9/x30 diff --git a/glibc-nscd-sysconfig.patch b/glibc-nscd-sysconfig.patch new file mode 100755 index 0000000..03dee9e --- /dev/null +++ b/glibc-nscd-sysconfig.patch @@ -0,0 +1,21 @@ +Short description: Provide options to nscd startup. +Author(s): Fedora glibc team +Origin: PATCH +Upstream status: not-needed + +Fedora-specific nscd startup configuration file. + +diff --git a/nscd/nscd.service b/nscd/nscd.service +index b7428a3..19ba185 100644 +--- a/nscd/nscd.service ++++ b/nscd/nscd.service +@@ -5,7 +5,8 @@ Description=Name Service Cache Daemon + + [Service] + Type=forking +-ExecStart=/usr/sbin/nscd ++EnvironmentFile=-/etc/sysconfig/nscd ++ExecStart=/usr/sbin/nscd $NSCD_OPTIONS + ExecStop=/usr/sbin/nscd --shutdown + ExecReload=/usr/sbin/nscd -i passwd + ExecReload=/usr/sbin/nscd -i group diff --git a/glibc-python3.patch b/glibc-python3.patch old mode 100644 new mode 100755 index 122a3f5..a9a7a4f --- a/glibc-python3.patch +++ b/glibc-python3.patch @@ -8,24 +8,33 @@ python3 during a transitional phase. Author: Carlos O'Donell - diff --git a/benchtests/scripts/compare_bench.py b/benchtests/scripts/compare_bench.py -index a85ca3a38be1fdeb..9f1ea9d85f4b833a 100755 +index ea25f778c09bba9d..b53beb3c6e32c3cf 100755 --- a/benchtests/scripts/compare_bench.py +++ b/benchtests/scripts/compare_bench.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 - # Copyright (C) 2015-2023 Free Software Foundation, Inc. + # Copyright (C) 2015-2018 Free Software Foundation, Inc. # This file is part of the GNU C Library. # diff --git a/benchtests/scripts/import_bench.py b/benchtests/scripts/import_bench.py -index d8bdde7753885a4d..698c4ff81b13f697 100644 +index 602b3f954d4801a6..76bf1528a5418748 100644 --- a/benchtests/scripts/import_bench.py +++ b/benchtests/scripts/import_bench.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 - # Copyright (C) 2015-2023 Free Software Foundation, Inc. + # Copyright (C) 2015-2018 Free Software Foundation, Inc. + # This file is part of the GNU C Library. + # +diff --git a/benchtests/scripts/validate_benchout.py b/benchtests/scripts/validate_benchout.py +index 6147f05bec3a4844..9a5c7947ee4ed7e9 100755 +--- a/benchtests/scripts/validate_benchout.py ++++ b/benchtests/scripts/validate_benchout.py +@@ -1,4 +1,4 @@ +-#!/usr/bin/python ++#!/usr/bin/python3 + # Copyright (C) 2014-2018 Free Software Foundation, Inc. # This file is part of the GNU C Library. # diff --git a/glibc-nscd-add-syslog-target-dependency.patch b/glibc-rh1070416.patch old mode 100644 new mode 100755 similarity index 100% rename from glibc-nscd-add-syslog-target-dependency.patch rename to glibc-rh1070416.patch diff --git a/glibc-rh1361965.patch b/glibc-rh1361965.patch new file mode 100755 index 0000000..cfbf09c --- /dev/null +++ b/glibc-rh1361965.patch @@ -0,0 +1,49 @@ +Backport of this Fedora Rawhide commit but split out into a distinct +patch. + +commit 72195d44855ab96875f117acb75c37f98dcb26a9 +Author: Carlos O'Donell +Date: Thu Jun 6 23:58:21 2019 -0400 + + locale: Fix C.UTF-8 ranges. + + The ellipsis range support only allows or as + valid unicode code points, otherwise it treats it as a symbol and + since we don't define the symbol the entire range is unused. + +diff --git a/localedata/locales/C b/localedata/locales/C +index b2c2d1dc417cde69..30d9563213b8cb0f 100644 +--- a/localedata/locales/C ++++ b/localedata/locales/C +@@ -43,21 +43,21 @@ order_start forward + + .. + +- ++ + .. +- +- ++ ++ + .. +- +- ++ ++ + .. +- +- ++ ++ + .. +- +- ++ ++ + .. +- ++ + UNDEFINED + order_end + END LC_COLLATE diff --git a/glibc-rh1410154-1.patch b/glibc-rh1410154-1.patch new file mode 100755 index 0000000..6acd167 --- /dev/null +++ b/glibc-rh1410154-1.patch @@ -0,0 +1,185 @@ +commit 96cd0558bcd69481ccc42e1b392f0c0b36fce2b0 +Author: Florian Weimer +Date: Wed Nov 28 19:59:45 2018 +0100 + + support: Add signal support to support_capture_subprocess_check + + Signal zero does not terminate a process, so it is safe to use negative + values for signal numbers. + + Adjust libio/tst-vtables-common.c to use this new functionality, + instead of determining the termination status for a signal indirectly. + +diff --git a/libio/tst-vtables-common.c b/libio/tst-vtables-common.c +index 5e3101206919fa1b..85e246cd1131f8e8 100644 +--- a/libio/tst-vtables-common.c ++++ b/libio/tst-vtables-common.c +@@ -380,21 +380,6 @@ without_compatibility_fflush (void *closure) + _exit (1); + } + +-/* Exit status after abnormal termination. */ +-static int termination_status; +- +-static void +-init_termination_status (void) +-{ +- pid_t pid = xfork (); +- if (pid == 0) +- abort (); +- xwaitpid (pid, &termination_status, 0); +- +- TEST_VERIFY (WIFSIGNALED (termination_status)); +- TEST_COMPARE (WTERMSIG (termination_status), SIGABRT); +-} +- + static void + check_for_termination (const char *name, void (*callback) (void *)) + { +@@ -404,7 +389,7 @@ check_for_termination (const char *name, void (*callback) (void *)) + shared->calls = 0; + struct support_capture_subprocess proc + = support_capture_subprocess (callback, NULL); +- support_capture_subprocess_check (&proc, name, termination_status, ++ support_capture_subprocess_check (&proc, name, -SIGABRT, + sc_allow_stderr); + const char *message + = "Fatal error: glibc detected an invalid stdio handle\n"; +@@ -491,7 +476,6 @@ run_tests (bool initially_disabled) + + shared = support_shared_allocate (sizeof (*shared)); + shared->initially_disabled = initially_disabled; +- init_termination_status (); + + if (initially_disabled) + { +diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h +index d5eac84d09ae325f..2d2384e73df0d2d0 100644 +--- a/support/capture_subprocess.h ++++ b/support/capture_subprocess.h +@@ -55,13 +55,16 @@ enum support_capture_allow + sc_allow_stderr = 0x04, + }; + +-/* Check that the subprocess exited with STATUS and that only the +- allowed outputs happened. ALLOWED is a combination of +- support_capture_allow flags. Report errors under the CONTEXT +- message. */ ++/* Check that the subprocess exited and that only the allowed outputs ++ happened. If STATUS_OR_SIGNAL is nonnegative, it is the expected ++ (decoded) exit status of the process, as returned by WEXITSTATUS. ++ If STATUS_OR_SIGNAL is negative, -STATUS_OR_SIGNAL is the expected ++ termination signal, as returned by WTERMSIG. ALLOWED is a ++ combination of support_capture_allow flags. Report errors under ++ the CONTEXT message. */ + void support_capture_subprocess_check (struct support_capture_subprocess *, +- const char *context, int status, +- int allowed) ++ const char *context, ++ int status_or_signal, int allowed) + __attribute__ ((nonnull (1, 2))); + + #endif /* SUPPORT_CAPTURE_SUBPROCESS_H */ +diff --git a/support/support_capture_subprocess_check.c b/support/support_capture_subprocess_check.c +index ff5ee89fb02599ae..8b4c352c96227b78 100644 +--- a/support/support_capture_subprocess_check.c ++++ b/support/support_capture_subprocess_check.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + static void + print_context (const char *context, bool *failed) +@@ -31,9 +32,22 @@ print_context (const char *context, bool *failed) + printf ("error: subprocess failed: %s\n", context); + } + ++static void ++print_actual_status (struct support_capture_subprocess *proc) ++{ ++ if (WIFEXITED (proc->status)) ++ printf ("error: actual exit status: %d [0x%x]\n", ++ WEXITSTATUS (proc->status), proc->status); ++ else if (WIFSIGNALED (proc->status)) ++ printf ("error: actual termination signal: %d [0x%x]\n", ++ WTERMSIG (proc->status), proc->status); ++ else ++ printf ("error: actual undecoded exit status: [0x%x]\n", proc->status); ++} ++ + void + support_capture_subprocess_check (struct support_capture_subprocess *proc, +- const char *context, int status, ++ const char *context, int status_or_signal, + int allowed) + { + TEST_VERIFY ((allowed & sc_allow_none) +@@ -44,11 +58,28 @@ support_capture_subprocess_check (struct support_capture_subprocess *proc, + || (allowed & sc_allow_stderr)))); + + bool failed = false; +- if (proc->status != status) ++ if (status_or_signal >= 0) + { +- print_context (context, &failed); +- printf ("error: expected exit status: %d\n", status); +- printf ("error: actual exit status: %d\n", proc->status); ++ /* Expect regular termination. */ ++ if (!(WIFEXITED (proc->status) ++ && WEXITSTATUS (proc->status) == status_or_signal)) ++ { ++ print_context (context, &failed); ++ printf ("error: expected exit status: %d\n", status_or_signal); ++ print_actual_status (proc); ++ } ++ } ++ else ++ { ++ /* status_or_signal < 0. Expect termination by signal. */ ++ if (!(WIFSIGNALED (proc->status) ++ && WTERMSIG (proc->status) == -status_or_signal)) ++ { ++ print_context (context, &failed); ++ printf ("error: expected termination signal: %d\n", ++ -status_or_signal); ++ print_actual_status (proc); ++ } + } + if (!(allowed & sc_allow_stdout) && proc->out.length != 0) + { +diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c +index 63b6699622f97fcc..99570879eedd65b1 100644 +--- a/support/tst-support_capture_subprocess.c ++++ b/support/tst-support_capture_subprocess.c +@@ -285,15 +285,29 @@ do_multiple_tests (enum test_type type) + + check_stream ("stdout", &result.out, test.out); + check_stream ("stderr", &result.err, test.err); ++ ++ /* Allowed output for support_capture_subprocess_check. */ ++ int check_allow = 0; ++ if (lengths[length_idx_stdout] > 0) ++ check_allow |= sc_allow_stdout; ++ if (lengths[length_idx_stderr] > 0) ++ check_allow |= sc_allow_stderr; ++ if (check_allow == 0) ++ check_allow = sc_allow_none; ++ + if (test.signal != 0) + { + TEST_VERIFY (WIFSIGNALED (result.status)); + TEST_VERIFY (WTERMSIG (result.status) == test.signal); ++ support_capture_subprocess_check (&result, "signal", ++ -SIGTERM, check_allow); + } + else + { + TEST_VERIFY (WIFEXITED (result.status)); + TEST_VERIFY (WEXITSTATUS (result.status) == test.status); ++ support_capture_subprocess_check (&result, "exit", ++ test.status, check_allow); + } + support_capture_subprocess_free (&result); + free (test.out); diff --git a/glibc-rh1410154-10.patch b/glibc-rh1410154-10.patch new file mode 100755 index 0000000..9025c9e --- /dev/null +++ b/glibc-rh1410154-10.patch @@ -0,0 +1,42 @@ +commit e37c2cf299b61ce18f62852f6c5624c27829b610 +Author: Florian Weimer +Date: Thu Oct 31 18:48:43 2019 +0100 + + Move _dl_open_check to its original place in dl_open_worker + + This reverts the non-test change from commit d0093c5cefb7f7a4143f + ("Call _dl_open_check after relocation [BZ #24259]"), given that + the underlying bug has been fixed properly in commit 61b74477fa7f63 + ("Remove all loaded objects if dlopen fails, ignoring NODELETE + [BZ #20839]"). + + Tested on x86-64-linux-gnu, with and without --enable-cet. + + Change-Id: I995a6cfb89f25d2b0cf5e606428c2a93eb48fc33 + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 25838b073ac1edaf..e13968d4d7c4c83f 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -619,6 +619,8 @@ dl_open_worker (void *a) + _dl_debug_state (); + LIBC_PROBE (map_complete, 3, args->nsid, r, new); + ++ _dl_open_check (new); ++ + /* Print scope information. */ + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) + _dl_show_scope (new, 0); +@@ -699,12 +701,6 @@ dl_open_worker (void *a) + _dl_relocate_object (l, l->l_scope, reloc_mode, 0); + } + +- /* NB: Workaround for [BZ #20839] which doesn't remove the NODELETE +- object when _dl_open_check throws an exception. Move it after +- relocation to avoid leaving the NODELETE object mapped without +- relocation. */ +- _dl_open_check (new); +- + /* This only performs the memory allocations. The actual update of + the scopes happens below, after failure is impossible. */ + resize_scopes (new); diff --git a/glibc-rh1410154-11.patch b/glibc-rh1410154-11.patch new file mode 100755 index 0000000..c3a16f3 --- /dev/null +++ b/glibc-rh1410154-11.patch @@ -0,0 +1,27 @@ +commit 61a7c9df71ee4e6f94b56c20f0d37c6e17d5f284 +Author: Florian Weimer +Date: Mon Dec 2 14:53:16 2019 +0100 + + elf/tst-dlopenfail: Disable --no-as-needed for tst-dlopenfailmod1.so + + Otherwise, the shared object dependency which triggers the load + failure is dropped, invalidating the test. + +diff --git a/elf/Makefile b/elf/Makefile +index bf7c41f38be42184..467e810e784bb96d 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -1543,8 +1543,11 @@ LDFLAGS-tst-finilazyfailmod.so = \ + $(objpfx)tst-dlopenfail: $(libdl) + $(objpfx)tst-dlopenfail.out: \ + $(objpfx)tst-dlopenfailmod1.so $(objpfx)tst-dlopenfailmod2.so +-# Order matters here. tst-dlopenfaillinkmod.so's soname ensures +-# a run-time loader failure. ++# Order matters here. tst-dlopenfaillinkmod.so's soname ensures a ++# run-time loader failure. --as-needed breaks this test because ++# nothing actually references tst-dlopenfailmod2.so (with its soname ++# tst-dlopenfail-missingmod.so). ++LDFLAGS-tst-dlopenfailmod1.so = -Wl,--no-as-needed + $(objpfx)tst-dlopenfailmod1.so: \ + $(shared-thread-library) $(objpfx)tst-dlopenfaillinkmod.so + LDFLAGS-tst-dlopenfaillinkmod.so = -Wl,-soname,tst-dlopenfail-missingmod.so diff --git a/glibc-rh1410154-12.patch b/glibc-rh1410154-12.patch new file mode 100755 index 0000000..48dcfc3 --- /dev/null +++ b/glibc-rh1410154-12.patch @@ -0,0 +1,1229 @@ +commit 365624e2d2a342cdb693b4cc35d2312169959e28 +Author: Florian Weimer +Date: Fri Dec 13 10:18:24 2019 +0100 + + dlopen: Fix issues related to NODELETE handling and relocations + + The assumption behind the assert in activate_nodelete was wrong: + + Inconsistency detected by ld.so: dl-open.c: 459: activate_nodelete: + Assertion `!imap->l_init_called || imap->l_type != lt_loaded' failed! (edit) + + It can happen that an already-loaded object that is in the local + scope is promoted to NODELETE status, via binding to a unique + symbol. + + Similarly, it is possible that such NODELETE promotion occurs to + an already-loaded object from the global scope. This is why the + loop in activate_nodelete has to cover all objects in the namespace + of the new object. + + In do_lookup_unique, it could happen that the NODELETE status of + an already-loaded object was overwritten with a pending NODELETE + status. As a result, if dlopen fails, this could cause a loss of + the NODELETE status of the affected object, eventually resulting + in an incorrect unload. + + Fixes commit f63b73814f74032c0e5d0a83300e3d864ef905e5 ("Remove all + loaded objects if dlopen fails, ignoring NODELETE [BZ #20839]"). + +diff --git a/elf/Makefile b/elf/Makefile +index 467e810e784bb96d..16a3e8dcda19b4ba 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -185,7 +185,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-audit1 tst-audit2 tst-audit8 tst-audit9 \ + tst-addr1 tst-thrlock \ + tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \ +- tst-nodelete) \ ++ tst-nodelete tst-dlopen-nodelete-reloc) \ + tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \ + tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \ + tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \ +@@ -266,7 +266,24 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-auditmod9a tst-auditmod9b \ + $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \ + tst-nodelete-uniquemod tst-nodelete-rtldmod \ +- tst-nodelete-zmod) \ ++ tst-nodelete-zmod \ ++ tst-dlopen-nodelete-reloc-mod1 \ ++ tst-dlopen-nodelete-reloc-mod2 \ ++ tst-dlopen-nodelete-reloc-mod3 \ ++ tst-dlopen-nodelete-reloc-mod4 \ ++ tst-dlopen-nodelete-reloc-mod5 \ ++ tst-dlopen-nodelete-reloc-mod6 \ ++ tst-dlopen-nodelete-reloc-mod7 \ ++ tst-dlopen-nodelete-reloc-mod8 \ ++ tst-dlopen-nodelete-reloc-mod9 \ ++ tst-dlopen-nodelete-reloc-mod10 \ ++ tst-dlopen-nodelete-reloc-mod11 \ ++ tst-dlopen-nodelete-reloc-mod12 \ ++ tst-dlopen-nodelete-reloc-mod13 \ ++ tst-dlopen-nodelete-reloc-mod14 \ ++ tst-dlopen-nodelete-reloc-mod15 \ ++ tst-dlopen-nodelete-reloc-mod16 \ ++ tst-dlopen-nodelete-reloc-mod17) \ + tst-initordera1 tst-initorderb1 \ + tst-initordera2 tst-initorderb2 \ + tst-initordera3 tst-initordera4 \ +@@ -1552,3 +1569,48 @@ $(objpfx)tst-dlopenfailmod1.so: \ + $(shared-thread-library) $(objpfx)tst-dlopenfaillinkmod.so + LDFLAGS-tst-dlopenfaillinkmod.so = -Wl,-soname,tst-dlopenfail-missingmod.so + $(objpfx)tst-dlopenfailmod2.so: $(shared-thread-library) ++ ++$(objpfx)tst-dlopen-nodelete-reloc: $(libdl) ++$(objpfx)tst-dlopen-nodelete-reloc.out: \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod1.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod2.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod3.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod4.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod5.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod6.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod7.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod8.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod9.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod10.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod11.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod12.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod13.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod14.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod15.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod16.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod17.so ++tst-dlopen-nodelete-reloc-mod2.so-no-z-defs = yes ++LDFLAGS-tst-dlopen-nodelete-reloc-mod2.so = -Wl,-z,nodelete ++$(objpfx)tst-dlopen-nodelete-reloc-mod4.so: \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod3.so ++LDFLAGS-tst-dlopen-nodelete-reloc-mod4.so = -Wl,--no-as-needed ++$(objpfx)tst-dlopen-nodelete-reloc-mod5.so: \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod4.so ++LDFLAGS-tst-dlopen-nodelete-reloc-mod5.so = -Wl,-z,nodelete,--no-as-needed ++tst-dlopen-nodelete-reloc-mod5.so-no-z-defs = yes ++tst-dlopen-nodelete-reloc-mod7.so-no-z-defs = yes ++$(objpfx)tst-dlopen-nodelete-reloc-mod8.so: $(libdl) ++$(objpfx)tst-dlopen-nodelete-reloc-mod10.so: $(libdl) ++tst-dlopen-nodelete-reloc-mod11.so-no-z-defs = yes ++$(objpfx)tst-dlopen-nodelete-reloc-mod13.so: \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod12.so ++$(objpfx)tst-dlopen-nodelete-reloc-mod15.so: \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod14.so ++tst-dlopen-nodelete-reloc-mod16.so-no-z-defs = yes ++$(objpfx)tst-dlopen-nodelete-reloc-mod16.so: \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod15.so ++LDFLAGS-tst-dlopen-nodelete-reloc-mod16.so = -Wl,--no-as-needed ++$(objpfx)tst-dlopen-nodelete-reloc-mod17.so: \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod15.so \ ++ $(objpfx)tst-dlopen-nodelete-reloc-mod16.so ++LDFLAGS-tst-dlopen-nodelete-reloc-mod17.so = -Wl,--no-as-needed +diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c +index c5e5857fb1fe2808..35a3f96a6296294a 100644 +--- a/elf/dl-lookup.c ++++ b/elf/dl-lookup.c +@@ -311,12 +311,12 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash, + enter_unique_sym (entries, size, + new_hash, strtab + sym->st_name, sym, map); + +- if (map->l_type == lt_loaded) ++ if (map->l_type == lt_loaded ++ && map->l_nodelete == link_map_nodelete_inactive) + { + /* Make sure we don't unload this object by + setting the appropriate flag. */ +- if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS) +- && map->l_nodelete == link_map_nodelete_inactive) ++ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS)) + _dl_debug_printf ("\ + marking %s [%lu] as NODELETE due to unique symbol\n", + map->l_name, map->l_ns); +diff --git a/elf/dl-open.c b/elf/dl-open.c +index e13968d4d7c4c83f..c7ed85b7ee99a296 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -433,34 +433,21 @@ TLS generation counter wrapped! Please report this.")); + after dlopen failure is not possible, so that _dl_close can clean + up objects if necessary. */ + static void +-activate_nodelete (struct link_map *new, int mode) ++activate_nodelete (struct link_map *new) + { +- if (mode & RTLD_NODELETE || new->l_nodelete == link_map_nodelete_pending) +- { +- if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES)) +- _dl_debug_printf ("activating NODELETE for %s [%lu]\n", +- new->l_name, new->l_ns); +- new->l_nodelete = link_map_nodelete_active; +- } +- +- for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) +- { +- struct link_map *imap = new->l_searchlist.r_list[i]; +- if (imap->l_nodelete == link_map_nodelete_pending) +- { +- if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES)) +- _dl_debug_printf ("activating NODELETE for %s [%lu]\n", +- imap->l_name, imap->l_ns); +- +- /* Only new objects should have set +- link_map_nodelete_pending. Existing objects should not +- have gained any new dependencies and therefore cannot +- reach NODELETE status. */ +- assert (!imap->l_init_called || imap->l_type != lt_loaded); ++ /* It is necessary to traverse the entire namespace. References to ++ objects in the global scope and unique symbol bindings can force ++ NODELETE status for objects outside the local scope. */ ++ for (struct link_map *l = GL (dl_ns)[new->l_ns]._ns_loaded; l != NULL; ++ l = l->l_next) ++ if (l->l_nodelete == link_map_nodelete_pending) ++ { ++ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf ("activating NODELETE for %s [%lu]\n", ++ l->l_name, l->l_ns); + +- imap->l_nodelete = link_map_nodelete_active; +- } +- } ++ l->l_nodelete = link_map_nodelete_active; ++ } + } + + /* struct dl_init_args and call_dl_init are used to call _dl_init with +@@ -718,7 +705,7 @@ dl_open_worker (void *a) + All memory allocations for new objects must have happened + before. */ + +- activate_nodelete (new, mode); ++ activate_nodelete (new); + + /* Second stage after resize_scopes: Actually perform the scope + update. After this, dlsym and lazy binding can bind to new +diff --git a/elf/tst-dlopen-nodelete-reloc-mod1.c b/elf/tst-dlopen-nodelete-reloc-mod1.c +new file mode 100644 +index 0000000000000000..397d60a2d5ea62d9 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod1.c +@@ -0,0 +1,39 @@ ++/* Test propagation of NODELETE to an already-loaded object via relocation. ++ Non-NODELETE helper module. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++/* Globally exported. Set by the main program to true before ++ termination, and used by tst-dlopen-nodelete-reloc-mod2.so to ++ trigger marking this module as NODELETE (and also for its destructor ++ check). */ ++bool may_finalize_mod1 = false; ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ if (!may_finalize_mod1) ++ { ++ puts ("error: tst-dlopen-nodelete-reloc-mod1.so destructor" ++ " called too early"); ++ _exit (1); ++ } ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod10.c b/elf/tst-dlopen-nodelete-reloc-mod10.c +new file mode 100644 +index 0000000000000000..30748b73ec7daed3 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod10.c +@@ -0,0 +1,41 @@ ++/* Helper module to load tst-dlopen-nodelete-reloc-mod11.so. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++static void *handle; ++ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ handle = dlopen ("tst-dlopen-nodelete-reloc-mod11.so", RTLD_NOW); ++ if (handle == NULL) ++ { ++ printf ("error: dlopen in module 10: %s\n", dlerror ()); ++ _exit (1); ++ } ++} ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ dlclose (handle); ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod11.cc b/elf/tst-dlopen-nodelete-reloc-mod11.cc +new file mode 100644 +index 0000000000000000..48c910403e782c83 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod11.cc +@@ -0,0 +1,49 @@ ++/* Second module defining a unique symbol (loaded indirectly). ++ 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 ++ . */ ++ ++#include "tst-dlopen-nodelete-reloc.h" ++ ++#include ++#include ++#include ++ ++/* Just a flag here, not used for NODELETE processing. */ ++bool may_finalize_mod11 = false; ++ ++/* Trigger the creation of a unique symbol reference. This should ++ cause tst-dlopen-nodelete-reloc-mod9.so to be marked as ++ NODELETE. */ ++ ++extern template struct unique_symbol<9>; ++ ++int ++global_function_mod11 (void) ++{ ++ return unique_symbol<9>::value; ++} ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ if (!may_finalize_mod11) ++ { ++ puts ("error: tst-dlopen-nodelete-reloc-mod11.so destructor" ++ " called too early"); ++ _exit (1); ++ } ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod12.cc b/elf/tst-dlopen-nodelete-reloc-mod12.cc +new file mode 100644 +index 0000000000000000..5c093fd02d1fd0c7 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod12.cc +@@ -0,0 +1,42 @@ ++/* First module for NODELETE test defining a unique symbol (with DT_NEEDED). ++ 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 ++ . */ ++ ++#include "tst-dlopen-nodelete-reloc.h" ++ ++#include ++#include ++#include ++ ++/* Just a flag here, not used for NODELETE processing. */ ++bool may_finalize_mod12 = false; ++ ++/* Explicit instantiation. This produces a unique symbol definition ++ which is not referenced by the library itself, so the library is ++ not marked NODELETE. */ ++template struct unique_symbol<12>; ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ if (!may_finalize_mod12) ++ { ++ puts ("error: tst-dlopen-nodelete-reloc-mod12.so destructor" ++ " called too early"); ++ _exit (1); ++ } ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod13.cc b/elf/tst-dlopen-nodelete-reloc-mod13.cc +new file mode 100644 +index 0000000000000000..caf4fd1cc9e1c1e1 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod13.cc +@@ -0,0 +1,48 @@ ++/* Second module for NODELETE test defining a unique symbol (with DT_NEEDED). ++ 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 ++ . */ ++ ++#include "tst-dlopen-nodelete-reloc.h" ++ ++#include ++#include ++#include ++ ++/* Just a flag here, not used for NODELETE processing. */ ++bool may_finalize_mod13 = false; ++ ++extern template struct unique_symbol<12>; ++ ++/* Trigger the creation of a unique symbol reference. This should ++ cause tst-dlopen-nodelete-reloc-mod12.so to be marked as ++ NODELETE. */ ++int ++global_function_mod13 (void) ++{ ++ return unique_symbol<12>::value; ++} ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ if (!may_finalize_mod13) ++ { ++ puts ("error: tst-dlopen-nodelete-reloc-mod13.so destructor" ++ " called too early"); ++ _exit (1); ++ } ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod13.h b/elf/tst-dlopen-nodelete-reloc-mod13.h +new file mode 100644 +index 0000000000000000..5d338481a34a5714 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod13.h +@@ -0,0 +1,24 @@ ++/* Inline function which produces a unique symbol. ++ 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 ++ . */ ++ ++inline char * ++third_function_with_local_static (void) ++{ ++ static char local; ++ return &local; ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod14.cc b/elf/tst-dlopen-nodelete-reloc-mod14.cc +new file mode 100644 +index 0000000000000000..e67621a2a2f8509a +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod14.cc +@@ -0,0 +1,42 @@ ++/* This object must retain NODELETE status after a dlopen failure. ++ 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 ++ . */ ++ ++#include "tst-dlopen-nodelete-reloc.h" ++ ++#include ++#include ++#include ++ ++/* Just a flag here, not used for NODELETE processing. */ ++bool may_finalize_mod14 = false; ++ ++/* Explicit instantiation. This produces a unique symbol definition ++ which is not referenced by the library itself, so the library is ++ not marked NODELETE. */ ++template struct unique_symbol<14>; ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ if (!may_finalize_mod14) ++ { ++ puts ("error: tst-dlopen-nodelete-reloc-mod14.so destructor" ++ " called too early"); ++ _exit (1); ++ } ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod15.cc b/elf/tst-dlopen-nodelete-reloc-mod15.cc +new file mode 100644 +index 0000000000000000..ead362bfdbb90eef +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod15.cc +@@ -0,0 +1,42 @@ ++/* Helper object to mark tst-dlopen-nodelete-reloc-mod14.so as NODELETE. ++ 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 ++ . */ ++ ++#include "tst-dlopen-nodelete-reloc.h" ++ ++#include ++#include ++#include ++ ++extern template struct unique_symbol<14>; ++ ++/* Trigger the creation of a unique symbol reference. This should ++ cause tst-dlopen-nodelete-reloc-mod14.so to be marked as ++ NODELETE. */ ++int ++global_function_mod15 (void) ++{ ++ return unique_symbol<14>::value; ++} ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ /* This object is never loaded completely. */ ++ puts ("error: tst-dlopen-nodelete-reloc-mod15.so destructor invoked"); ++ _exit (1); ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod16.c b/elf/tst-dlopen-nodelete-reloc-mod16.c +new file mode 100644 +index 0000000000000000..fa2ed1461b42c82c +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod16.c +@@ -0,0 +1,27 @@ ++/* Object with an undefined symbol to trigger a relocation failure. ++ 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 ++ . */ ++ ++/* The reference to undefined_mod16 triggers a relocation failure. */ ++ ++extern int undefined_mod16; ++ ++int ++global_function_mod16 (void) ++{ ++ return undefined_mod16; ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod17.c b/elf/tst-dlopen-nodelete-reloc-mod17.c +new file mode 100644 +index 0000000000000000..426562edd9a3ffee +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod17.c +@@ -0,0 +1,19 @@ ++/* Top-level object with dependency on an object that fails relocation. ++ 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 ++ . */ ++ ++/* The dependencies do all the work. */ +diff --git a/elf/tst-dlopen-nodelete-reloc-mod2.c b/elf/tst-dlopen-nodelete-reloc-mod2.c +new file mode 100644 +index 0000000000000000..81ea8e5af2d00b93 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod2.c +@@ -0,0 +1,38 @@ ++/* Test propagation of NODELETE to an already-loaded object via relocation. ++ NODELETE helper module. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++/* Defined in tst-dlopen-nodelete-reloc-mod1.so. This dependency is ++ not expressed via DT_NEEDED, so this reference marks the other ++ object as NODELETE dynamically, during initially relocation. */ ++extern bool may_finalize_mod1; ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ if (!may_finalize_mod1) ++ { ++ puts ("error: tst-dlopen-nodelete-reloc-mod2.so destructor" ++ " called too early"); ++ _exit (1); ++ } ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod3.c b/elf/tst-dlopen-nodelete-reloc-mod3.c +new file mode 100644 +index 0000000000000000..d33f4ec7630c6a1e +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod3.c +@@ -0,0 +1,38 @@ ++/* Test propagation of NODELETE to an already-loaded object via relocation. ++ Non-NODELETE helper module. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++/* Globally exported. Set by the main program to true before ++ termination, and used by tst-dlopen-nodelete-reloc-mod4.so, ++ tst-dlopen-nodelete-reloc-mod5.so. */ ++bool may_finalize_mod3 = false; ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ if (!may_finalize_mod3) ++ { ++ puts ("error: tst-dlopen-nodelete-reloc-mod3.so destructor" ++ " called too early"); ++ _exit (1); ++ } ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod4.c b/elf/tst-dlopen-nodelete-reloc-mod4.c +new file mode 100644 +index 0000000000000000..7e6633aebb1e2f00 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod4.c +@@ -0,0 +1,37 @@ ++/* Test propagation of NODELETE to an already-loaded object via relocation. ++ Intermediate helper module. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++/* Defined in tst-dlopen-nodelete-reloc-mod3.so. The dependency is ++ expressed via DT_NEEDED. */ ++extern bool may_finalize_mod3; ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ if (!may_finalize_mod3) ++ { ++ puts ("error: tst-dlopen-nodelete-reloc-mod4.so destructor" ++ " called too early"); ++ _exit (1); ++ } ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod5.c b/elf/tst-dlopen-nodelete-reloc-mod5.c +new file mode 100644 +index 0000000000000000..22aa16f855dc75a8 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod5.c +@@ -0,0 +1,38 @@ ++/* Test propagation of NODELETE to an already-loaded object via relocation. ++ NODELETE helper module. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++/* Defined in tst-dlopen-nodelete-reloc-mod3.so. The dependency is ++ expressed via DT_NEEDED on the intermediate DSO ++ tst-dlopen-nodelete-reloc-mod3.so. */ ++extern bool may_finalize_mod3; ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ if (!may_finalize_mod3) ++ { ++ puts ("error: tst-dlopen-nodelete-reloc-mod5.so destructor" ++ " called too early"); ++ _exit (1); ++ } ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod6.cc b/elf/tst-dlopen-nodelete-reloc-mod6.cc +new file mode 100644 +index 0000000000000000..180f5b5842f1c2b0 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod6.cc +@@ -0,0 +1,42 @@ ++/* First module for NODELETE test defining a unique symbol. ++ 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 ++ . */ ++ ++#include "tst-dlopen-nodelete-reloc.h" ++ ++#include ++#include ++#include ++ ++/* Just a flag here, not used for NODELETE processing. */ ++bool may_finalize_mod6 = false; ++ ++/* Explicit instantiation. This produces a unique symbol definition ++ which is not referenced by the library itself, so the library is ++ not marked NODELETE. */ ++template struct unique_symbol<6>; ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ if (!may_finalize_mod6) ++ { ++ puts ("error: tst-dlopen-nodelete-reloc-mod6.so destructor" ++ " called too early"); ++ _exit (1); ++ } ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod7.cc b/elf/tst-dlopen-nodelete-reloc-mod7.cc +new file mode 100644 +index 0000000000000000..c85e7c991b098bf5 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod7.cc +@@ -0,0 +1,48 @@ ++/* Second module for NODELETE test defining a unique symbol. ++ 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 ++ . */ ++ ++#include "tst-dlopen-nodelete-reloc.h" ++ ++#include ++#include ++#include ++ ++/* Just a flag here, not used for NODELETE processing. */ ++bool may_finalize_mod7 = false; ++ ++extern template struct unique_symbol<6>; ++ ++/* Trigger the creation of a unique symbol reference. This should ++ cause tst-dlopen-nodelete-reloc-mod6.so to be marked as ++ NODELETE. */ ++int ++global_function_mod7 (void) ++{ ++ return unique_symbol<6>::value; ++} ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ if (!may_finalize_mod7) ++ { ++ puts ("error: tst-dlopen-nodelete-reloc-mod7.so destructor" ++ " called too early"); ++ _exit (1); ++ } ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod8.c b/elf/tst-dlopen-nodelete-reloc-mod8.c +new file mode 100644 +index 0000000000000000..ebb1c35fab57e319 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod8.c +@@ -0,0 +1,41 @@ ++/* Helper module to load tst-dlopen-nodelete-reloc-mod9.so. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++static void *handle; ++ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ handle = dlopen ("tst-dlopen-nodelete-reloc-mod9.so", RTLD_NOW); ++ if (handle == NULL) ++ { ++ printf ("error: dlopen in module 8: %s\n", dlerror ()); ++ _exit (1); ++ } ++} ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ dlclose (handle); ++} +diff --git a/elf/tst-dlopen-nodelete-reloc-mod9.cc b/elf/tst-dlopen-nodelete-reloc-mod9.cc +new file mode 100644 +index 0000000000000000..06fb49cdf753cb41 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc-mod9.cc +@@ -0,0 +1,42 @@ ++/* First module defining a unique symbol (loaded indirectly). ++ 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 ++ . */ ++ ++#include "tst-dlopen-nodelete-reloc.h" ++ ++#include ++#include ++#include ++ ++/* Just a flag here, not used for NODELETE processing. */ ++bool may_finalize_mod9 = false; ++ ++/* Explicit instantiation. This produces a unique symbol definition ++ which is not referenced by the library itself, so the library is ++ not marked NODELETE. */ ++template struct unique_symbol<9>; ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ if (!may_finalize_mod9) ++ { ++ puts ("error: tst-dlopen-nodelete-reloc-mod9.so destructor" ++ " called too early"); ++ _exit (1); ++ } ++} +diff --git a/elf/tst-dlopen-nodelete-reloc.c b/elf/tst-dlopen-nodelete-reloc.c +new file mode 100644 +index 0000000000000000..291ac9eb8385a92e +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc.c +@@ -0,0 +1,179 @@ ++/* Test interactions of dlopen, NODELETE, and relocations. ++ 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 ++ . */ ++ ++/* This test exercises NODELETE propagation due to data relocations ++ and unique symbols, and the interaction with already-loaded ++ objects. Some test objects are written in C++, to produce unique ++ symbol definitions. ++ ++ First test: Global scope variant, data relocation as the NODELETE ++ trigger. mod1 is loaded first with a separate dlopen call. ++ ++ mod2 ---(may_finalize_mod1 relocation dependency)---> mod1 ++ (NODELETE) (marked as NODELETE) ++ ++ Second test: Local scope variant, data relocation. mod3 is loaded ++ first, then mod5. ++ ++ mod5 ---(DT_NEEDED)---> mod4 ---(DT_NEEDED)---> mod3 ++ (NODELETE) (not NODELETE) ^ ++ \ / (marked as ++ `--(may_finalize_mod3 relocation dependency)--/ NODELETE) ++ ++ Third test: Shared local scope with unique symbol. mod6 is loaded ++ first, then mod7. No explicit dependencies between the two ++ objects, so first object has to be opened with RTLD_GLOBAL. ++ ++ mod7 ---(unique symbol)---> mod6 ++ (marked as NODELETE) ++ ++ Forth test: Non-shared scopes with unique symbol. mod8 and mod10 ++ are loaded from the main program. mod8 loads mod9 from an ELF ++ constructor, mod10 loads mod11. There are no DT_NEEDED ++ dependencies. mod9 is promoted to the global scope form the main ++ program. The unique symbol dependency is: ++ ++ mod9 ---(unique symbol)---> mod11 ++ (marked as NODELETE) ++ ++ Fifth test: Shared local scope with unique symbol, like test 3, but ++ this time, there is also a DT_NEEDED dependency (so no RTLD_GLOBAL ++ needed): ++ ++ DT_NEEDED ++ mod13 ---(unique symbol)---> mod12 ++ (marked as NODELETE) ++ ++ Sixth test: NODELETE status is retained after relocation failure ++ with unique symbol dependency. The object graph ensures that the ++ unique symbol binding is processed before the dlopen failure. ++ ++ DT_NEEDED ++ mod17 --(DT_NEEDED)--> mod15 --(unique symbol)--> mod14 ++ \ ^ (RTLD_NODELETE) ++ \ (DT_NEEDED) ++ \ | ++ `---(DT_NEEDED)--> mod16 ++ (fails to relocate) ++ ++ mod14 is loaded first, and the loading mod17 is attempted. ++ mod14 must remain NODELETE after opening mod17 failed. */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* First case: global scope, regular data symbol. Open the object ++ which is not NODELETE initially. */ ++ void *mod1 = xdlopen ("tst-dlopen-nodelete-reloc-mod1.so", ++ RTLD_NOW | RTLD_GLOBAL); ++ /* This is used to indicate that the ELF destructor may be ++ called. */ ++ bool *may_finalize_mod1 = xdlsym (mod1, "may_finalize_mod1"); ++ /* Open the NODELETE object. */ ++ void *mod2 = xdlopen ("tst-dlopen-nodelete-reloc-mod2.so", RTLD_NOW); ++ /* This has no effect because the DSO is directly marked as ++ NODELETE. */ ++ xdlclose (mod2); ++ /* This has no effect because the DSO has been indirectly marked as ++ NODELETE due to a relocation dependency. */ ++ xdlclose (mod1); ++ ++ /* Second case: local scope, regular data symbol. Open the object ++ which is not NODELETE initially. */ ++ void *mod3 = xdlopen ("tst-dlopen-nodelete-reloc-mod3.so", RTLD_NOW); ++ bool *may_finalize_mod3 = xdlsym (mod3, "may_finalize_mod3"); ++ /* Open the NODELETE object. */ ++ void *mod5 = xdlopen ("tst-dlopen-nodelete-reloc-mod5.so", RTLD_NOW); ++ /* Again those have no effect because of NODELETE. */ ++ xdlclose (mod5); ++ xdlclose (mod3); ++ ++ /* Third case: Unique symbol. */ ++ void *mod6 = xdlopen ("tst-dlopen-nodelete-reloc-mod6.so", ++ RTLD_NOW | RTLD_GLOBAL); ++ bool *may_finalize_mod6 = xdlsym (mod6, "may_finalize_mod6"); ++ void *mod7 = xdlopen ("tst-dlopen-nodelete-reloc-mod7.so", RTLD_NOW); ++ bool *may_finalize_mod7 = xdlsym (mod7, "may_finalize_mod7"); ++ /* This should not have any effect because of the unique symbol and ++ the resulting NODELETE status. */ ++ xdlclose (mod6); ++ /* mod7 is not NODELETE and can be closed. */ ++ *may_finalize_mod7 = true; ++ xdlclose (mod7); ++ ++ /* Fourth case: Unique symbol, indirect loading. */ ++ void *mod8 = xdlopen ("tst-dlopen-nodelete-reloc-mod8.so", RTLD_NOW); ++ /* Also promote to global scope. */ ++ void *mod9 = xdlopen ("tst-dlopen-nodelete-reloc-mod9.so", ++ RTLD_NOW | RTLD_NOLOAD | RTLD_GLOBAL); ++ bool *may_finalize_mod9 = xdlsym (mod9, "may_finalize_mod9"); ++ xdlclose (mod9); /* Drop mod9 reference. */ ++ void *mod10 = xdlopen ("tst-dlopen-nodelete-reloc-mod10.so", RTLD_NOW); ++ void *mod11 = xdlopen ("tst-dlopen-nodelete-reloc-mod11.so", ++ RTLD_NOW | RTLD_NOLOAD); ++ bool *may_finalize_mod11 = xdlsym (mod11, "may_finalize_mod11"); ++ xdlclose (mod11); /* Drop mod11 reference. */ ++ /* mod11 is not NODELETE and can be closed. */ ++ *may_finalize_mod11 = true; ++ /* Trigger closing of mod11, too. */ ++ xdlclose (mod10); ++ /* Does not trigger closing of mod9. */ ++ xdlclose (mod8); ++ ++ /* Fifth case: Unique symbol, with DT_NEEDED dependency. */ ++ void *mod12 = xdlopen ("tst-dlopen-nodelete-reloc-mod12.so", RTLD_NOW); ++ bool *may_finalize_mod12 = xdlsym (mod12, "may_finalize_mod12"); ++ void *mod13 = xdlopen ("tst-dlopen-nodelete-reloc-mod13.so", RTLD_NOW); ++ bool *may_finalize_mod13 = xdlsym (mod13, "may_finalize_mod13"); ++ /* This should not have any effect because of the unique symbol. */ ++ xdlclose (mod12); ++ /* mod13 is not NODELETE and can be closed. */ ++ *may_finalize_mod13 = true; ++ xdlclose (mod13); ++ ++ /* Sixth case: Unique symbol binding must not cause loss of NODELETE ++ status. */ ++ void *mod14 = xdlopen ("tst-dlopen-nodelete-reloc-mod14.so", ++ RTLD_NOW | RTLD_NODELETE); ++ bool *may_finalize_mod14 = xdlsym (mod14, "may_finalize_mod14"); ++ TEST_VERIFY (dlopen ("tst-dlopen-nodelete-reloc-mod17.so", RTLD_NOW) ++ == NULL); ++ const char *message = dlerror (); ++ printf ("info: test 6 message: %s\n", message); ++ /* This must not close the object, it must still be NODELETE. */ ++ xdlclose (mod14); ++ xdlopen ("tst-dlopen-nodelete-reloc-mod14.so", RTLD_NOW | RTLD_NOLOAD); ++ ++ /* Prepare for process exit. Destructors for NODELETE objects will ++ be invoked. */ ++ *may_finalize_mod1 = true; ++ *may_finalize_mod3 = true; ++ *may_finalize_mod6 = true; ++ *may_finalize_mod9 = true; ++ *may_finalize_mod12 = true; ++ *may_finalize_mod14 = true; ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-dlopen-nodelete-reloc.h b/elf/tst-dlopen-nodelete-reloc.h +new file mode 100644 +index 0000000000000000..8844de622631f575 +--- /dev/null ++++ b/elf/tst-dlopen-nodelete-reloc.h +@@ -0,0 +1,35 @@ ++/* Template to produce unique symbols. ++ 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 ++ . */ ++ ++/* This template produces a unique symbol definition for an explicit ++ template instantiation (without also incorporating a reference), ++ and an extern template declaration can be used to reference that ++ symbol from another object. The modid parameter is just a ++ placeholder to create different symbols (because it affects the ++ name mangling of the static value member). By convention, it ++ should match the number of the module that contains the ++ definition. */ ++ ++template ++struct unique_symbol ++{ ++ static int value; ++}; ++ ++template ++int unique_symbol::value; diff --git a/glibc-rh1410154-13.patch b/glibc-rh1410154-13.patch new file mode 100755 index 0000000..1ec1768 --- /dev/null +++ b/glibc-rh1410154-13.patch @@ -0,0 +1,328 @@ +commit f8ed116aa574435c6e28260f21963233682d3b57 +Author: Florian Weimer +Date: Fri Dec 13 10:18:46 2019 +0100 + + dlopen: Rework handling of pending NODELETE status + + Commit a2e8aa0d9ea648068d8be52dd7b15f1b6a008e23 ("Block signals during + the initial part of dlopen") was deemed necessary because of + read-modify-write operations like the one in add_dependency in + elf/dl-lookup.c. In the old code, we check for any kind of NODELETE + status and bail out: + + /* Redo the NODELETE check, as when dl_load_lock wasn't held + yet this could have changed. */ + if (map->l_nodelete != link_map_nodelete_inactive) + goto out; + + And then set pending status (during relocation): + + if (flags & DL_LOOKUP_FOR_RELOCATE) + map->l_nodelete = link_map_nodelete_pending; + else + map->l_nodelete = link_map_nodelete_active; + + If a signal arrives during relocation and the signal handler, through + lazy binding, adds a global scope dependency on the same map, it will + set map->l_nodelete to link_map_nodelete_active. This will be + overwritten with link_map_nodelete_pending by the dlopen relocation + code. + + To avoid such problems in relation to the l_nodelete member, this + commit introduces two flags for active NODELETE status (irrevocable) + and pending NODELETE status (revocable until activate_nodelete is + invoked). As a result, NODELETE processing in dlopen does not + introduce further reasons why lazy binding from signal handlers + is unsafe during dlopen, and a subsequent commit can remove signal + blocking from dlopen. + + This does not address pre-existing issues (unrelated to the NODELETE + changes) which make lazy binding in a signal handler during dlopen + unsafe, such as the use of malloc in both cases. + + Reviewed-by: Adhemerval Zanella + Reviewed-by: Carlos O'Donell + +diff --git a/elf/dl-close.c b/elf/dl-close.c +index 243a028c443173c1..fa7f3e8174576e46 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -197,7 +197,7 @@ _dl_close_worker (struct link_map *map, bool force) + /* Check whether this object is still used. */ + if (l->l_type == lt_loaded + && l->l_direct_opencount == 0 +- && l->l_nodelete != link_map_nodelete_active ++ && !l->l_nodelete_active + /* See CONCURRENCY NOTES in cxa_thread_atexit_impl.c to know why + acquire is sufficient and correct. */ + && atomic_load_acquire (&l->l_tls_dtor_count) == 0 +@@ -279,8 +279,7 @@ _dl_close_worker (struct link_map *map, bool force) + + if (!used[i]) + { +- assert (imap->l_type == lt_loaded +- && imap->l_nodelete != link_map_nodelete_active); ++ assert (imap->l_type == lt_loaded && !imap->l_nodelete_active); + + /* Call its termination function. Do not do it for + half-cooked objects. Temporarily disable exception +@@ -820,7 +819,7 @@ _dl_close (void *_map) + before we took the lock. There is no way to detect this (see below) + so we proceed assuming this isn't the case. First see whether we + can remove the object at all. */ +- if (__glibc_unlikely (map->l_nodelete == link_map_nodelete_active)) ++ if (__glibc_unlikely (map->l_nodelete_active)) + { + /* Nope. Do nothing. */ + __rtld_lock_unlock_recursive (GL(dl_load_lock)); +diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c +index 35a3f96a6296294a..01724a54f8840f9f 100644 +--- a/elf/dl-lookup.c ++++ b/elf/dl-lookup.c +@@ -187,6 +187,28 @@ enter_unique_sym (struct unique_sym *table, size_t size, + table[idx].map = map; + } + ++/* Mark MAP as NODELETE according to the lookup mode in FLAGS. During ++ initial relocation, NODELETE state is pending only. */ ++static void ++mark_nodelete (struct link_map *map, int flags) ++{ ++ if (flags & DL_LOOKUP_FOR_RELOCATE) ++ map->l_nodelete_pending = true; ++ else ++ map->l_nodelete_active = true; ++} ++ ++/* Return true if MAP is marked as NODELETE according to the lookup ++ mode in FLAGS> */ ++static bool ++is_nodelete (struct link_map *map, int flags) ++{ ++ /* Non-pending NODELETE always counts. Pending NODELETE only counts ++ during initial relocation processing. */ ++ return map->l_nodelete_active ++ || ((flags & DL_LOOKUP_FOR_RELOCATE) && map->l_nodelete_pending); ++} ++ + /* Utility function for do_lookup_x. Lookup an STB_GNU_UNIQUE symbol + in the unique symbol table, creating a new entry if necessary. + Return the matching symbol in RESULT. */ +@@ -311,8 +333,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash, + enter_unique_sym (entries, size, + new_hash, strtab + sym->st_name, sym, map); + +- if (map->l_type == lt_loaded +- && map->l_nodelete == link_map_nodelete_inactive) ++ if (map->l_type == lt_loaded && !is_nodelete (map, flags)) + { + /* Make sure we don't unload this object by + setting the appropriate flag. */ +@@ -320,10 +341,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash, + _dl_debug_printf ("\ + marking %s [%lu] as NODELETE due to unique symbol\n", + map->l_name, map->l_ns); +- if (flags & DL_LOOKUP_FOR_RELOCATE) +- map->l_nodelete = link_map_nodelete_pending; +- else +- map->l_nodelete = link_map_nodelete_active; ++ mark_nodelete (map, flags); + } + } + ++tab->n_elements; +@@ -586,7 +604,7 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags) + dependencies may pick an dependency which can be dlclose'd, but + such IFUNC resolvers are undefined anyway. */ + assert (map->l_type == lt_loaded); +- if (map->l_nodelete != link_map_nodelete_inactive) ++ if (is_nodelete (map, flags)) + return 0; + + struct link_map_reldeps *l_reldeps +@@ -694,17 +712,16 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags) + + /* Redo the NODELETE check, as when dl_load_lock wasn't held + yet this could have changed. */ +- if (map->l_nodelete != link_map_nodelete_inactive) ++ if (is_nodelete (map, flags)) + goto out; + + /* If the object with the undefined reference cannot be removed ever + just make sure the same is true for the object which contains the + definition. */ +- if (undef_map->l_type != lt_loaded +- || (undef_map->l_nodelete != link_map_nodelete_inactive)) ++ if (undef_map->l_type != lt_loaded || is_nodelete (map, flags)) + { + if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS) +- && map->l_nodelete == link_map_nodelete_inactive) ++ && !is_nodelete (map, flags)) + { + if (undef_map->l_name[0] == '\0') + _dl_debug_printf ("\ +@@ -716,11 +733,7 @@ marking %s [%lu] as NODELETE due to reference to %s [%lu]\n", + map->l_name, map->l_ns, + undef_map->l_name, undef_map->l_ns); + } +- +- if (flags & DL_LOOKUP_FOR_RELOCATE) +- map->l_nodelete = link_map_nodelete_pending; +- else +- map->l_nodelete = link_map_nodelete_active; ++ mark_nodelete (map, flags); + goto out; + } + +@@ -746,17 +759,14 @@ marking %s [%lu] as NODELETE due to reference to %s [%lu]\n", + cannot be unloaded. This is semantically the correct + behavior. */ + if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS) +- && map->l_nodelete == link_map_nodelete_inactive) ++ && !is_nodelete (map, flags)) + _dl_debug_printf ("\ + marking %s [%lu] as NODELETE due to memory allocation failure\n", + map->l_name, map->l_ns); +- if (flags & DL_LOOKUP_FOR_RELOCATE) +- /* In case of non-lazy binding, we could actually +- report the memory allocation error, but for now, we +- use the conservative approximation as well. */ +- map->l_nodelete = link_map_nodelete_pending; +- else +- map->l_nodelete = link_map_nodelete_active; ++ /* In case of non-lazy binding, we could actually report ++ the memory allocation error, but for now, we use the ++ conservative approximation as well. */ ++ mark_nodelete (map, flags); + goto out; + } + else +diff --git a/elf/dl-open.c b/elf/dl-open.c +index c7ed85b7ee99a296..a382bfae8aa3a2f8 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -440,13 +440,17 @@ activate_nodelete (struct link_map *new) + NODELETE status for objects outside the local scope. */ + for (struct link_map *l = GL (dl_ns)[new->l_ns]._ns_loaded; l != NULL; + l = l->l_next) +- if (l->l_nodelete == link_map_nodelete_pending) ++ if (l->l_nodelete_pending) + { + if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES)) + _dl_debug_printf ("activating NODELETE for %s [%lu]\n", + l->l_name, l->l_ns); + +- l->l_nodelete = link_map_nodelete_active; ++ l->l_nodelete_active = true; ++ ++ /* This is just a debugging aid, to indicate that ++ activate_nodelete has run for this map. */ ++ l->l_nodelete_pending = false; + } + } + +@@ -549,10 +553,10 @@ dl_open_worker (void *a) + if (__glibc_unlikely (mode & RTLD_NODELETE)) + { + if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES) +- && new->l_nodelete == link_map_nodelete_inactive) ++ && !new->l_nodelete_active) + _dl_debug_printf ("marking %s [%lu] as NODELETE\n", + new->l_name, new->l_ns); +- new->l_nodelete = link_map_nodelete_active; ++ new->l_nodelete_active = true; + } + + /* Finalize the addition to the global scope. */ +@@ -568,7 +572,7 @@ dl_open_worker (void *a) + /* Schedule NODELETE marking for the directly loaded object if + requested. */ + if (__glibc_unlikely (mode & RTLD_NODELETE)) +- new->l_nodelete = link_map_nodelete_pending; ++ new->l_nodelete_pending = true; + + /* Load that object's dependencies. */ + _dl_map_object_deps (new, NULL, 0, 0, +@@ -680,7 +684,7 @@ dl_open_worker (void *a) + _dl_start_profile (); + + /* Prevent unloading the object. */ +- GL(dl_profile_map)->l_nodelete = link_map_nodelete_active; ++ GL(dl_profile_map)->l_nodelete_active = true; + } + } + else +@@ -879,9 +883,9 @@ no more namespaces available for dlmopen()")); + happens inside dl_open_worker. */ + __libc_signal_restore_set (&args.original_signal_mask); + +- /* All link_map_nodelete_pending objects should have been +- deleted at this point, which is why it is not necessary +- to reset the flag here. */ ++ /* All l_nodelete_pending objects should have been deleted ++ at this point, which is why it is not necessary to reset ++ the flag here. */ + } + else + __libc_signal_restore_set (&args.original_signal_mask); +diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h +index ea286abaea0128d1..78ba7e76db9706cc 100644 +--- a/elf/get-dynamic-info.h ++++ b/elf/get-dynamic-info.h +@@ -164,7 +164,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) + { + l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val; + if (l->l_flags_1 & DF_1_NODELETE) +- l->l_nodelete = link_map_nodelete_pending; ++ l->l_nodelete_pending = true; + + /* Only DT_1_SUPPORTED_MASK bits are supported, and we would like + to assert this, but we can't. Users have been setting +diff --git a/include/link.h b/include/link.h +index a277b77cad6b52b1..e90fa79a0b332087 100644 +--- a/include/link.h ++++ b/include/link.h +@@ -79,22 +79,6 @@ struct r_search_path_struct + int malloced; + }; + +-/* Type used by the l_nodelete member. */ +-enum link_map_nodelete +-{ +- /* This link map can be deallocated. */ +- link_map_nodelete_inactive = 0, /* Zero-initialized in _dl_new_object. */ +- +- /* This link map cannot be deallocated. */ +- link_map_nodelete_active, +- +- /* This link map cannot be deallocated after dlopen has succeded. +- dlopen turns this into link_map_nodelete_active. dlclose treats +- this intermediate state as link_map_nodelete_active. */ +- link_map_nodelete_pending, +-}; +- +- + /* Structure describing a loaded shared object. The `l_next' and `l_prev' + members form a chain of all the shared objects loaded at startup. + +@@ -218,10 +202,17 @@ struct link_map + freed, ie. not allocated with + the dummy malloc in ld.so. */ + +- /* Actually of type enum link_map_nodelete. Separate byte due to +- a read in add_dependency in elf/dl-lookup.c outside the loader +- lock. Only valid for l_type == lt_loaded. */ +- unsigned char l_nodelete; ++ /* NODELETE status of the map. Only valid for maps of type ++ lt_loaded. Lazy binding sets l_nodelete_active directly, ++ potentially from signal handlers. Initial loading of an ++ DF_1_NODELETE object set l_nodelete_pending. Relocation may ++ set l_nodelete_pending as well. l_nodelete_pending maps are ++ promoted to l_nodelete_active status in the final stages of ++ dlopen, prior to calling ELF constructors. dlclose only ++ refuses to unload l_nodelete_active maps, the pending status is ++ ignored. */ ++ bool l_nodelete_active; ++ bool l_nodelete_pending; + + #include + diff --git a/glibc-rh1410154-14.patch b/glibc-rh1410154-14.patch new file mode 100755 index 0000000..ac4d1e2 --- /dev/null +++ b/glibc-rh1410154-14.patch @@ -0,0 +1,134 @@ +commit f7649d5780aa4682393b9daedd653e4d9c12784c +Author: Florian Weimer +Date: Fri Dec 13 10:23:10 2019 +0100 + + dlopen: Do not block signals + + Blocking signals causes issues with certain anti-malware solutions + which rely on an unblocked SIGSYS signal for system calls they + intercept. + + This reverts commit a2e8aa0d9ea648068d8be52dd7b15f1b6a008e23 + ("Block signals during the initial part of dlopen") and adds + comments related to async signal safety to active_nodelete and + its caller. + + Note that this does not make lazy binding async-signal-safe with regards + to dlopen. It merely avoids introducing new async-signal-safety hazards + as part of the NODELETE changes. + + Reviewed-by: Adhemerval Zanella + Reviewed-by: Carlos O'Donell + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index a382bfae8aa3a2f8..d834b89754d2b073 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -34,7 +34,6 @@ + #include + #include + #include +-#include + + #include + #include +@@ -53,10 +52,6 @@ struct dl_open_args + /* Namespace ID. */ + Lmid_t nsid; + +- /* Original signal mask. Used for unblocking signal handlers before +- running ELF constructors. */ +- sigset_t original_signal_mask; +- + /* Original value of _ns_global_scope_pending_adds. Set by + dl_open_worker. Only valid if nsid is a real namespace + (non-negative). */ +@@ -446,6 +441,9 @@ activate_nodelete (struct link_map *new) + _dl_debug_printf ("activating NODELETE for %s [%lu]\n", + l->l_name, l->l_ns); + ++ /* The flag can already be true at this point, e.g. a signal ++ handler may have triggered lazy binding and set NODELETE ++ status immediately. */ + l->l_nodelete_active = true; + + /* This is just a debugging aid, to indicate that +@@ -520,16 +518,12 @@ dl_open_worker (void *a) + if (new == NULL) + { + assert (mode & RTLD_NOLOAD); +- __libc_signal_restore_set (&args->original_signal_mask); + return; + } + + if (__glibc_unlikely (mode & __RTLD_SPROF)) +- { +- /* This happens only if we load a DSO for 'sprof'. */ +- __libc_signal_restore_set (&args->original_signal_mask); +- return; +- } ++ /* This happens only if we load a DSO for 'sprof'. */ ++ return; + + /* This object is directly loaded. */ + ++new->l_direct_opencount; +@@ -565,7 +559,6 @@ dl_open_worker (void *a) + + assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT); + +- __libc_signal_restore_set (&args->original_signal_mask); + return; + } + +@@ -709,6 +702,12 @@ dl_open_worker (void *a) + All memory allocations for new objects must have happened + before. */ + ++ /* Finalize the NODELETE status first. This comes before ++ update_scopes, so that lazy binding will not see pending NODELETE ++ state for newly loaded objects. There is a compiler barrier in ++ update_scopes which ensures that the changes from ++ activate_nodelete are visible before new objects show up in the ++ local scope. */ + activate_nodelete (new); + + /* Second stage after resize_scopes: Actually perform the scope +@@ -742,10 +741,6 @@ dl_open_worker (void *a) + if (mode & RTLD_GLOBAL) + add_to_global_resize (new); + +- /* Unblock signals. Data structures are now consistent, and +- application code may run. */ +- __libc_signal_restore_set (&args->original_signal_mask); +- + /* Run the initializer functions of new objects. Temporarily + disable the exception handler, so that lazy binding failures are + fatal. */ +@@ -835,10 +830,6 @@ no more namespaces available for dlmopen()")); + args.argv = argv; + args.env = env; + +- /* Recursive lazy binding during manipulation of the dynamic loader +- structures may result in incorrect behavior. */ +- __libc_signal_block_all (&args.original_signal_mask); +- + struct dl_exception exception; + int errcode = _dl_catch_exception (&exception, dl_open_worker, &args); + +@@ -879,16 +870,10 @@ no more namespaces available for dlmopen()")); + + _dl_close_worker (args.map, true); + +- /* Restore the signal mask. In the success case, this +- happens inside dl_open_worker. */ +- __libc_signal_restore_set (&args.original_signal_mask); +- + /* All l_nodelete_pending objects should have been deleted + at this point, which is why it is not necessary to reset + the flag here. */ + } +- else +- __libc_signal_restore_set (&args.original_signal_mask); + + assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT); + diff --git a/glibc-rh1410154-15.patch b/glibc-rh1410154-15.patch new file mode 100755 index 0000000..bf58563 --- /dev/null +++ b/glibc-rh1410154-15.patch @@ -0,0 +1,27 @@ +commit 5177d85b0c050a2333a0c4165c938dd422013d05 +Author: H.J. Lu +Date: Thu Jan 16 06:45:36 2020 -0800 + + Clear GL(dl_initfirst) when freeing its link_map memory [BZ# 25396] + + We should clear GL(dl_initfirst) when freeing its link_map memory. + + Tested on Fedora 31/x86-64 with CET. + + Reviewed-by: Florian Weimer + +diff --git a/elf/dl-close.c b/elf/dl-close.c +index fa7f3e8174576e46..a9ecdff62dba88fb 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -749,6 +749,10 @@ _dl_close_worker (struct link_map *map, bool force) + if (imap->l_runpath_dirs.dirs != (void *) -1) + free (imap->l_runpath_dirs.dirs); + ++ /* Clear GL(dl_initfirst) when freeing its link_map memory. */ ++ if (imap == GL(dl_initfirst)) ++ GL(dl_initfirst) = NULL; ++ + free (imap); + } + } diff --git a/glibc-rh1410154-16.patch b/glibc-rh1410154-16.patch new file mode 100755 index 0000000..d3e0386 --- /dev/null +++ b/glibc-rh1410154-16.patch @@ -0,0 +1,143 @@ +commit a332bd1518af518c984fad73eba6f46dc5b2b2d4 +Author: Florian Weimer +Date: Thu Jan 16 16:53:58 2020 +0100 + + elf: Add elf/tst-dlopenfail-2 [BZ #25396] + + Without CET, a jump into a newly loaded object through an overwritten + link map often does not crash, it just executes some random code. + CET detects this in some cases because the function pointer does not + point to the start of a function in the replacement shared object, + so there is no ENDBR instruction. + + The new test uses a small shared object and the existing dangling + link map to trigger the bug. + + Reviewed-by: Siddhesh Poyarekar + +Conflicts: + elf/Makefile + (Test backport differences.) + +diff --git a/elf/Makefile b/elf/Makefile +index 16a3e8dcda19b4ba..f1a16fe8ca594c57 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -192,7 +192,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \ + tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \ + tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail \ +- tst-dlopenfail ++ tst-dlopenfail tst-dlopenfail-2 + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -301,7 +301,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-sonamemove-linkmod1 \ + tst-sonamemove-runmod1 tst-sonamemove-runmod2 \ + tst-initlazyfailmod tst-finilazyfailmod \ +- tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 ++ tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \ ++ tst-dlopenfailmod3 + + ifeq (yes,$(have-mtls-dialect-gnu2)) + tests += tst-gnu2-tls1 +@@ -1569,6 +1570,10 @@ $(objpfx)tst-dlopenfailmod1.so: \ + $(shared-thread-library) $(objpfx)tst-dlopenfaillinkmod.so + LDFLAGS-tst-dlopenfaillinkmod.so = -Wl,-soname,tst-dlopenfail-missingmod.so + $(objpfx)tst-dlopenfailmod2.so: $(shared-thread-library) ++$(objpfx)tst-dlopenfail-2: $(libdl) ++$(objpfx)tst-dlopenfail.out: \ ++ $(objpfx)tst-dlopenfailmod1.so $(objpfx)tst-dlopenfailmod2.so \ ++ $(objpfx)tst-dlopenfailmod3.so + + $(objpfx)tst-dlopen-nodelete-reloc: $(libdl) + $(objpfx)tst-dlopen-nodelete-reloc.out: \ +diff --git a/elf/tst-dlopenfail-2.c b/elf/tst-dlopenfail-2.c +new file mode 100644 +index 0000000000000000..35bbde64abbb6603 +--- /dev/null ++++ b/elf/tst-dlopenfail-2.c +@@ -0,0 +1,59 @@ ++/* Test unrelated dlopen after dlopen failure involving NODELETE. ++ Copyright (C) 2019-2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* This test uses libpthread as the canonical NODELETE module. If ++ libpthread is no longer NODELETE because it has been merged into ++ libc, the test needs to be updated. */ ++ TEST_VERIFY (dlsym (NULL, "pthread_create") == NULL); ++ ++ /* This is expected to fail because of the missing dependency. */ ++ puts ("info: attempting to load tst-dlopenfailmod1.so"); ++ TEST_VERIFY (dlopen ("tst-dlopenfailmod1.so", RTLD_LAZY) == NULL); ++ const char *message = dlerror (); ++ TEST_COMPARE_STRING (message, ++ "tst-dlopenfail-missingmod.so:" ++ " cannot open shared object file:" ++ " No such file or directory"); ++ ++ /* Open a small shared object. With a dangling GL (dl_initfirst) ++ pointer, this is likely to crash because there is no longer any ++ mapped text segment there (bug 25396). */ ++ ++ puts ("info: attempting to load tst-dlopenfailmod3.so"); ++ xdlclose (xdlopen ("tst-dlopenfailmod3.so", RTLD_NOW)); ++ ++ return 0; ++} ++ ++/* Do not perturb the dangling link map. With M_PERTURB, the link map ++ appears to have l_init_called set, so there are no constructor ++ calls and no crashes. */ ++#define TEST_NO_MALLOPT ++#include +diff --git a/elf/tst-dlopenfailmod3.c b/elf/tst-dlopenfailmod3.c +new file mode 100644 +index 0000000000000000..636e971264292110 +--- /dev/null ++++ b/elf/tst-dlopenfailmod3.c +@@ -0,0 +1,17 @@ ++/* Empty module for the tst-dlopenfail-2 test. ++ Copyright (C) 2020 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 ++ . */ diff --git a/glibc-rh1410154-2.patch b/glibc-rh1410154-2.patch new file mode 100755 index 0000000..84269e7 --- /dev/null +++ b/glibc-rh1410154-2.patch @@ -0,0 +1,33 @@ +commit ca136bb0a36d0a7056c926bfe5126873566efe40 +Author: Florian Weimer +Date: Thu Oct 31 13:28:26 2019 +0100 + + Clarify purpose of assert in _dl_lookup_symbol_x + + Only one of the currently defined flags is incompatible with versioned + symbol lookups, so it makes sense to check for that flag and not its + complement. + + Reviewed-by: Carlos O'Donell + Reviewed-by: Gabriel F. T. Gomes + Change-Id: I3384349cef90cfd91862ebc34a4053f0c0a99404 + +diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c +index 1d046caf017b582b..efbdb8deb3c0a9d4 100644 +--- a/elf/dl-lookup.c ++++ b/elf/dl-lookup.c +@@ -792,11 +792,9 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, + + bump_num_relocations (); + +- /* No other flag than DL_LOOKUP_ADD_DEPENDENCY or DL_LOOKUP_GSCOPE_LOCK +- is allowed if we look up a versioned symbol. */ +- assert (version == NULL +- || (flags & ~(DL_LOOKUP_ADD_DEPENDENCY | DL_LOOKUP_GSCOPE_LOCK)) +- == 0); ++ /* DL_LOOKUP_RETURN_NEWEST does not make sense for versioned ++ lookups. */ ++ assert (version == NULL || !(flags & DL_LOOKUP_RETURN_NEWEST)); + + size_t i = 0; + if (__glibc_unlikely (skip_map != NULL)) diff --git a/glibc-rh1410154-3.patch b/glibc-rh1410154-3.patch new file mode 100755 index 0000000..34afb62 --- /dev/null +++ b/glibc-rh1410154-3.patch @@ -0,0 +1,54 @@ +commit 2a764c6ee848dfe92cb2921ed3b14085f15d9e79 +Author: Florian Weimer +Date: Thu Oct 31 13:23:06 2019 +0100 + + Enhance _dl_catch_exception to allow disabling exception handling + + In some cases, it is necessary to introduce noexcept regions + where raised dynamic loader exceptions (e.g., from lazy binding) + are fatal, despite being nested in a code region with an active + exception handler. This change enhances _dl_catch_exception with + to provide such a capability. The existing function is reused, + so that it is not necessary to introduce yet another function with + a similar purpose. + + Change-Id: Iec1bf642ff95a349fdde8040e9baf851ac7b8904 + +diff --git a/elf/dl-error-skeleton.c b/elf/dl-error-skeleton.c +index d5f418ab1848f0c4..9cb002ccfed2c7b4 100644 +--- a/elf/dl-error-skeleton.c ++++ b/elf/dl-error-skeleton.c +@@ -173,6 +173,18 @@ int + _dl_catch_exception (struct dl_exception *exception, + void (*operate) (void *), void *args) + { ++ /* If exception is NULL, temporarily disable exception handling. ++ Exceptions during operate (args) are fatal. */ ++ if (exception == NULL) ++ { ++ struct catch *const old = catch_hook; ++ catch_hook = NULL; ++ operate (args); ++ /* If we get here, the operation was successful. */ ++ catch_hook = old; ++ return 0; ++ } ++ + /* We need not handle `receiver' since setting a `catch' is handled + before it. */ + +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 95dc87519b80e0ec..cc2484033fe0d902 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -852,7 +852,9 @@ libc_hidden_proto (_dl_catch_error) + + /* Call OPERATE (ARGS). If no error occurs, set *EXCEPTION to zero. + Otherwise, store a copy of the raised exception in *EXCEPTION, +- which has to be freed by _dl_exception_free. */ ++ which has to be freed by _dl_exception_free. As a special case, if ++ EXCEPTION is null, call OPERATE (ARGS) with exception handling ++ disabled (so that exceptions are fatal). */ + int _dl_catch_exception (struct dl_exception *exception, + void (*operate) (void *), void *args); + libc_hidden_proto (_dl_catch_exception) diff --git a/glibc-rh1410154-4.patch b/glibc-rh1410154-4.patch new file mode 100755 index 0000000..fa3cc53 --- /dev/null +++ b/glibc-rh1410154-4.patch @@ -0,0 +1,42 @@ +commit fcb04b9aed26a737159ef7be9c5a6ad0994437dc +Author: Florian Weimer +Date: Thu Oct 31 13:28:49 2019 +0100 + + Introduce DL_LOOKUP_FOR_RELOCATE flag for _dl_lookup_symbol_x + + This will allow changes in dependency processing during non-lazy + binding, for more precise processing of NODELETE objects: During + initial relocation in dlopen, the fate of NODELETE objects is still + unclear, so objects which are depended upon by NODELETE objects + cannot immediately be marked as NODELETE. + + Change-Id: Ic7b94a3f7c4719a00ca8e6018088567824da0658 + +diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c +index 053916eeae50467c..afeace4d3e49180c 100644 +--- a/elf/dl-reloc.c ++++ b/elf/dl-reloc.c +@@ -248,7 +248,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + v = (version); \ + _lr = _dl_lookup_symbol_x (strtab + (*ref)->st_name, l, (ref), \ + scope, v, _tc, \ +- DL_LOOKUP_ADD_DEPENDENCY, NULL); \ ++ DL_LOOKUP_ADD_DEPENDENCY \ ++ | DL_LOOKUP_FOR_RELOCATE, NULL); \ + l->l_lookup_cache.ret = (*ref); \ + l->l_lookup_cache.value = _lr; })) \ + : l) +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index cc2484033fe0d902..6c5298a80bff8e96 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -908,6 +908,9 @@ enum + DL_LOOKUP_RETURN_NEWEST = 2, + /* Set if dl_lookup* called with GSCOPE lock held. */ + DL_LOOKUP_GSCOPE_LOCK = 4, ++ /* Set if dl_lookup is called for non-lazy relocation processing ++ from _dl_relocate_object in elf/dl-reloc.c. */ ++ DL_LOOKUP_FOR_RELOCATE = 8, + }; + + /* Lookup versioned symbol. */ diff --git a/glibc-rh1410154-5.patch b/glibc-rh1410154-5.patch new file mode 100755 index 0000000..6879fb3 --- /dev/null +++ b/glibc-rh1410154-5.patch @@ -0,0 +1,343 @@ +commit 79e0cd7b3c997e211fad44a81fd839dc5b2546e8 +Author: Florian Weimer +Date: Wed Nov 27 16:20:47 2019 +0100 + + Lazy binding failures during dlopen/dlclose must be fatal [BZ #24304] + + If a lazy binding failure happens during the execution of an ELF + constructor or destructor, the dynamic loader catches the error + and reports it using the dlerror mechanism. This is undesirable + because there could be other constructors and destructors that + need processing (which are skipped), and the process is in an + inconsistent state at this point. Therefore, we have to issue + a fatal dynamic loader error error and terminate the process. + + Note that the _dl_catch_exception in _dl_open is just an inner catch, + to roll back some state locally. If called from dlopen, there is + still an outer catch, which is why calling _dl_init via call_dl_init + and a no-exception is required and cannot be avoiding by moving the + _dl_init call directly into _dl_open. + + _dl_fini does not need changes because it does not install an error + handler, so errors are already fatal there. + + Change-Id: I6b1addfe2e30f50a1781595f046f44173db9491a + +Conflicts: + elf/Makefile + (Usual conflicts due to test backport differences.) + +diff --git a/elf/Makefile b/elf/Makefile +index 74a240b3a68ff5e2..b752f6366400d221 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -191,7 +191,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + 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-sonamemove-link tst-sonamemove-dlopen ++ tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -281,7 +281,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \ + tst-absolute-zero-lib tst-big-note-lib \ + tst-sonamemove-linkmod1 \ +- tst-sonamemove-runmod1 tst-sonamemove-runmod2 ++ tst-sonamemove-runmod1 tst-sonamemove-runmod2 \ ++ tst-initlazyfailmod tst-finilazyfailmod + + ifeq (yes,$(have-mtls-dialect-gnu2)) + tests += tst-gnu2-tls1 +@@ -1526,3 +1527,13 @@ tst-libc_dlvsym-static-ENV = \ + $(objpfx)tst-libc_dlvsym-static.out: $(objpfx)tst-libc_dlvsym-dso.so + + $(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so ++ ++$(objpfx)tst-initfinilazyfail: $(libdl) ++$(objpfx)tst-initfinilazyfail.out: \ ++ $(objpfx)tst-initlazyfailmod.so $(objpfx)tst-finilazyfailmod.so ++# Override -z defs, so that we can reference an undefined symbol. ++# Force lazy binding for the same reason. ++LDFLAGS-tst-initlazyfailmod.so = \ ++ -Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all ++LDFLAGS-tst-finilazyfailmod.so = \ ++ -Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all +diff --git a/elf/dl-close.c b/elf/dl-close.c +index ecd6729704ea3294..88aeea25839a34e0 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -106,6 +106,30 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp, + return false; + } + ++/* Invoke dstructors for CLOSURE (a struct link_map *). Called with ++ exception handling temporarily disabled, to make errors fatal. */ ++static void ++call_destructors (void *closure) ++{ ++ struct link_map *map = closure; ++ ++ if (map->l_info[DT_FINI_ARRAY] != NULL) ++ { ++ ElfW(Addr) *array = ++ (ElfW(Addr) *) (map->l_addr ++ + map->l_info[DT_FINI_ARRAY]->d_un.d_ptr); ++ unsigned int sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val ++ / sizeof (ElfW(Addr))); ++ ++ while (sz-- > 0) ++ ((fini_t) array[sz]) (); ++ } ++ ++ /* Next try the old-style destructor. */ ++ if (map->l_info[DT_FINI] != NULL) ++ DL_CALL_DT_FINI (map, ((void *) map->l_addr ++ + map->l_info[DT_FINI]->d_un.d_ptr)); ++} + + void + _dl_close_worker (struct link_map *map, bool force) +@@ -267,7 +291,8 @@ _dl_close_worker (struct link_map *map, bool force) + && (imap->l_flags_1 & DF_1_NODELETE) == 0); + + /* Call its termination function. Do not do it for +- half-cooked objects. */ ++ half-cooked objects. Temporarily disable exception ++ handling, so that errors are fatal. */ + if (imap->l_init_called) + { + /* When debugging print a message first. */ +@@ -276,22 +301,9 @@ _dl_close_worker (struct link_map *map, bool force) + _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n", + imap->l_name, nsid); + +- if (imap->l_info[DT_FINI_ARRAY] != NULL) +- { +- ElfW(Addr) *array = +- (ElfW(Addr) *) (imap->l_addr +- + imap->l_info[DT_FINI_ARRAY]->d_un.d_ptr); +- unsigned int sz = (imap->l_info[DT_FINI_ARRAYSZ]->d_un.d_val +- / sizeof (ElfW(Addr))); +- +- while (sz-- > 0) +- ((fini_t) array[sz]) (); +- } +- +- /* Next try the old-style destructor. */ +- if (imap->l_info[DT_FINI] != NULL) +- DL_CALL_DT_FINI (imap, ((void *) imap->l_addr +- + imap->l_info[DT_FINI]->d_un.d_ptr)); ++ if (imap->l_info[DT_FINI_ARRAY] != NULL ++ || imap->l_info[DT_FINI] != NULL) ++ _dl_catch_exception (NULL, call_destructors, imap); + } + + #ifdef SHARED +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 518a6cad699ec6d0..c9c0254ee74c4f4b 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -177,6 +177,23 @@ _dl_find_dso_for_object (const ElfW(Addr) addr) + } + rtld_hidden_def (_dl_find_dso_for_object); + ++/* struct dl_init_args and call_dl_init are used to call _dl_init with ++ exception handling disabled. */ ++struct dl_init_args ++{ ++ struct link_map *new; ++ int argc; ++ char **argv; ++ char **env; ++}; ++ ++static void ++call_dl_init (void *closure) ++{ ++ struct dl_init_args *args = closure; ++ _dl_init (args->new, args->argc, args->argv, args->env); ++} ++ + static void + dl_open_worker (void *a) + { +@@ -506,8 +523,19 @@ TLS generation counter wrapped! Please report this.")); + DL_STATIC_INIT (new); + #endif + +- /* Run the initializer functions of new objects. */ +- _dl_init (new, args->argc, args->argv, args->env); ++ /* Run the initializer functions of new objects. Temporarily ++ disable the exception handler, so that lazy binding failures are ++ fatal. */ ++ { ++ struct dl_init_args init_args = ++ { ++ .new = new, ++ .argc = args->argc, ++ .argv = args->argv, ++ .env = args->env ++ }; ++ _dl_catch_exception (NULL, call_dl_init, &init_args); ++ } + + /* Now we can make the new map available in the global scope. */ + if (mode & RTLD_GLOBAL) +diff --git a/elf/tst-finilazyfailmod.c b/elf/tst-finilazyfailmod.c +new file mode 100644 +index 0000000000000000..2670bd1a9400d0ef +--- /dev/null ++++ b/elf/tst-finilazyfailmod.c +@@ -0,0 +1,27 @@ ++/* Helper module for tst-initfinilazyfail: lazy binding failure in destructor. ++ 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 ++ . */ ++ ++/* An undefined function. Calling it will cause a lazy binding ++ failure. */ ++void undefined_function (void); ++ ++static void __attribute__ ((destructor)) ++fini (void) ++{ ++ undefined_function (); ++} +diff --git a/elf/tst-initfinilazyfail.c b/elf/tst-initfinilazyfail.c +new file mode 100644 +index 0000000000000000..9b4a3d0c0ffbb7c6 +--- /dev/null ++++ b/elf/tst-initfinilazyfail.c +@@ -0,0 +1,84 @@ ++/* Test that lazy binding failures in constructors and destructors are fatal. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static void ++test_constructor (void *closure) ++{ ++ void *handle = dlopen ("tst-initlazyfailmod.so", RTLD_LAZY); ++ if (handle == NULL) ++ FAIL_EXIT (2, "dlopen did not terminate the process: %s", dlerror ()); ++ else ++ FAIL_EXIT (2, "dlopen did not terminate the process (%p)", handle); ++} ++ ++static void ++test_destructor (void *closure) ++{ ++ void *handle = xdlopen ("tst-finilazyfailmod.so", RTLD_LAZY); ++ int ret = dlclose (handle); ++ const char *message = dlerror (); ++ if (message != NULL) ++ FAIL_EXIT (2, "dlclose did not terminate the process: %d, %s", ++ ret, message); ++ else ++ FAIL_EXIT (2, "dlopen did not terminate the process: %d", ret); ++} ++ ++static int ++do_test (void) ++{ ++ { ++ struct support_capture_subprocess proc ++ = support_capture_subprocess (test_constructor, NULL); ++ support_capture_subprocess_check (&proc, "constructor", 127, ++ sc_allow_stderr); ++ printf ("info: constructor failure output: [[%s]]\n", proc.err.buffer); ++ TEST_VERIFY (strstr (proc.err.buffer, ++ "tst-initfinilazyfail: symbol lookup error: ") ++ != NULL); ++ TEST_VERIFY (strstr (proc.err.buffer, ++ "tst-initlazyfailmod.so: undefined symbol:" ++ " undefined_function\n") != NULL); ++ support_capture_subprocess_free (&proc); ++ } ++ ++ { ++ struct support_capture_subprocess proc ++ = support_capture_subprocess (test_destructor, NULL); ++ support_capture_subprocess_check (&proc, "destructor", 127, ++ sc_allow_stderr); ++ printf ("info: destructor failure output: [[%s]]\n", proc.err.buffer); ++ TEST_VERIFY (strstr (proc.err.buffer, ++ "tst-initfinilazyfail: symbol lookup error: ") ++ != NULL); ++ TEST_VERIFY (strstr (proc.err.buffer, ++ "tst-finilazyfailmod.so: undefined symbol:" ++ " undefined_function\n") != NULL); ++ support_capture_subprocess_free (&proc); ++ } ++ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-initlazyfailmod.c b/elf/tst-initlazyfailmod.c +new file mode 100644 +index 0000000000000000..36348b58d634d2bb +--- /dev/null ++++ b/elf/tst-initlazyfailmod.c +@@ -0,0 +1,27 @@ ++/* Helper module for tst-initfinilazyfail: lazy binding failure in constructor. ++ 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 ++ . */ ++ ++/* An undefined function. Calling it will cause a lazy binding ++ failure. */ ++void undefined_function (void); ++ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ undefined_function (); ++} diff --git a/glibc-rh1410154-6.patch b/glibc-rh1410154-6.patch new file mode 100755 index 0000000..3b05076 --- /dev/null +++ b/glibc-rh1410154-6.patch @@ -0,0 +1,308 @@ +commit 440b7f8653e4ed8f6e1425145208050b795e9a6c +Author: Florian Weimer +Date: Thu Oct 31 18:25:39 2019 +0100 + + Avoid late failure in dlopen in global scope update [BZ #25112] + + The call to add_to_global in dl_open_worker happens after running ELF + constructors for new objects. At this point, proper recovery from + malloc failure would be quite complicated: We would have to run the + ELF destructors and close all opened objects, something that we + currently do not do. + + Instead, this change splits add_to_global into two phases, + add_to_global_resize (which can raise an exception, called before ELF + constructors run), and add_to_global_update (which cannot, called + after ELF constructors). A complication arises due to recursive + dlopen: After the inner dlopen consumes some space, the pre-allocation + in the outer dlopen may no longer be sufficient. A new member in the + namespace structure, _ns_global_scope_pending_adds keeps track of the + maximum number of objects that need to be added to the global scope. + This enables the inner add_to_global_resize call to take into account + the needs of an outer dlopen. + + Most code in the dynamic linker assumes that the number of global + scope entries fits into an unsigned int (matching the r_nlist member + of struct r_scop_elem). Therefore, change the type of + _ns_global_scope_alloc to unsigned int (from size_t), and add overflow + checks. + + Change-Id: Ie08e2f318510d5a6a4bcb1c315f46791b5b77524 + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index c9c0254ee74c4f4b..85db4f0ecb5f29ce 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -50,22 +50,38 @@ struct dl_open_args + struct link_map *map; + /* Namespace ID. */ + Lmid_t nsid; ++ ++ /* Original value of _ns_global_scope_pending_adds. Set by ++ dl_open_worker. Only valid if nsid is a real namespace ++ (non-negative). */ ++ unsigned int original_global_scope_pending_adds; ++ + /* Original parameters to the program and the current environment. */ + int argc; + char **argv; + char **env; + }; + ++/* Called in case the global scope cannot be extended. */ ++static void __attribute__ ((noreturn)) ++add_to_global_resize_failure (struct link_map *new) ++{ ++ _dl_signal_error (ENOMEM, new->l_libname->name, NULL, ++ N_ ("cannot extend global scope")); ++} + +-static int +-add_to_global (struct link_map *new) ++/* Grow the global scope array for the namespace, so that all the new ++ global objects can be added later in add_to_global_update, without ++ risk of memory allocation failure. add_to_global_resize raises ++ exceptions for memory allocation errors. */ ++static void ++add_to_global_resize (struct link_map *new) + { +- struct link_map **new_global; +- unsigned int to_add = 0; +- unsigned int cnt; ++ struct link_namespaces *ns = &GL (dl_ns)[new->l_ns]; + + /* Count the objects we have to put in the global scope. */ +- for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt) ++ unsigned int to_add = 0; ++ for (unsigned int cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt) + if (new->l_searchlist.r_list[cnt]->l_global == 0) + ++to_add; + +@@ -83,47 +99,51 @@ add_to_global (struct link_map *new) + in an realloc() call. Therefore we allocate a completely new + array the first time we have to add something to the locale scope. */ + +- struct link_namespaces *ns = &GL(dl_ns)[new->l_ns]; ++ if (__builtin_add_overflow (ns->_ns_global_scope_pending_adds, to_add, ++ &ns->_ns_global_scope_pending_adds)) ++ add_to_global_resize_failure (new); ++ ++ unsigned int new_size = 0; /* 0 means no new allocation. */ ++ void *old_global = NULL; /* Old allocation if free-able. */ ++ ++ /* Minimum required element count for resizing. Adjusted below for ++ an exponential resizing policy. */ ++ size_t required_new_size; ++ if (__builtin_add_overflow (ns->_ns_main_searchlist->r_nlist, ++ ns->_ns_global_scope_pending_adds, ++ &required_new_size)) ++ add_to_global_resize_failure (new); ++ + if (ns->_ns_global_scope_alloc == 0) + { +- /* This is the first dynamic object given global scope. */ +- ns->_ns_global_scope_alloc +- = ns->_ns_main_searchlist->r_nlist + to_add + 8; +- new_global = (struct link_map **) +- malloc (ns->_ns_global_scope_alloc * sizeof (struct link_map *)); +- if (new_global == NULL) +- { +- ns->_ns_global_scope_alloc = 0; +- nomem: +- _dl_signal_error (ENOMEM, new->l_libname->name, NULL, +- N_("cannot extend global scope")); +- return 1; +- } ++ if (__builtin_add_overflow (required_new_size, 8, &new_size)) ++ add_to_global_resize_failure (new); ++ } ++ else if (required_new_size > ns->_ns_global_scope_alloc) ++ { ++ if (__builtin_mul_overflow (required_new_size, 2, &new_size)) ++ add_to_global_resize_failure (new); + +- /* Copy over the old entries. */ +- ns->_ns_main_searchlist->r_list +- = memcpy (new_global, ns->_ns_main_searchlist->r_list, +- (ns->_ns_main_searchlist->r_nlist +- * sizeof (struct link_map *))); ++ /* The old array was allocated with our malloc, not the minimal ++ malloc. */ ++ old_global = ns->_ns_main_searchlist->r_list; + } +- else if (ns->_ns_main_searchlist->r_nlist + to_add +- > ns->_ns_global_scope_alloc) ++ ++ if (new_size > 0) + { +- /* We have to extend the existing array of link maps in the +- main map. */ +- struct link_map **old_global +- = GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list; +- size_t new_nalloc = ((ns->_ns_global_scope_alloc + to_add) * 2); +- +- new_global = (struct link_map **) +- malloc (new_nalloc * sizeof (struct link_map *)); ++ size_t allocation_size; ++ if (__builtin_mul_overflow (new_size, sizeof (struct link_map *), ++ &allocation_size)) ++ add_to_global_resize_failure (new); ++ struct link_map **new_global = malloc (allocation_size); + if (new_global == NULL) +- goto nomem; ++ add_to_global_resize_failure (new); + +- memcpy (new_global, old_global, +- ns->_ns_global_scope_alloc * sizeof (struct link_map *)); ++ /* Copy over the old entries. */ ++ memcpy (new_global, ns->_ns_main_searchlist->r_list, ++ ns->_ns_main_searchlist->r_nlist * sizeof (struct link_map *)); + +- ns->_ns_global_scope_alloc = new_nalloc; ++ ns->_ns_global_scope_alloc = new_size; + ns->_ns_main_searchlist->r_list = new_global; + + if (!RTLD_SINGLE_THREAD_P) +@@ -131,16 +151,28 @@ add_to_global (struct link_map *new) + + free (old_global); + } ++} ++ ++/* Actually add the new global objects to the global scope. Must be ++ called after add_to_global_resize. This function cannot fail. */ ++static void ++add_to_global_update (struct link_map *new) ++{ ++ struct link_namespaces *ns = &GL (dl_ns)[new->l_ns]; + + /* Now add the new entries. */ + unsigned int new_nlist = ns->_ns_main_searchlist->r_nlist; +- for (cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt) ++ for (unsigned int cnt = 0; cnt < new->l_searchlist.r_nlist; ++cnt) + { + struct link_map *map = new->l_searchlist.r_list[cnt]; + + if (map->l_global == 0) + { + map->l_global = 1; ++ ++ /* The array has been resized by add_to_global_resize. */ ++ assert (new_nlist < ns->_ns_global_scope_alloc); ++ + ns->_ns_main_searchlist->r_list[new_nlist++] = map; + + /* We modify the global scope. Report this. */ +@@ -149,10 +181,15 @@ add_to_global (struct link_map *new) + map->l_name, map->l_ns); + } + } ++ ++ /* Some of the pending adds have been performed by the loop above. ++ Adjust the counter accordingly. */ ++ unsigned int added = new_nlist - ns->_ns_main_searchlist->r_nlist; ++ assert (added <= ns->_ns_global_scope_pending_adds); ++ ns->_ns_global_scope_pending_adds -= added; ++ + atomic_write_barrier (); + ns->_ns_main_searchlist->r_nlist = new_nlist; +- +- return 0; + } + + /* Search link maps in all namespaces for the DSO that contains the object at +@@ -225,6 +262,10 @@ dl_open_worker (void *a) + args->nsid = call_map->l_ns; + } + ++ /* Retain the old value, so that it can be restored. */ ++ args->original_global_scope_pending_adds ++ = GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds; ++ + /* One might be tempted to assert that we are RT_CONSISTENT at this point, but that + may not be true if this is a recursive call to dlopen. */ + _dl_debug_initialize (0, args->nsid); +@@ -266,7 +307,10 @@ dl_open_worker (void *a) + /* If the user requested the object to be in the global namespace + but it is not so far, add it now. */ + if ((mode & RTLD_GLOBAL) && new->l_global == 0) +- (void) add_to_global (new); ++ { ++ add_to_global_resize (new); ++ add_to_global_update (new); ++ } + + assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT); + +@@ -523,6 +567,11 @@ TLS generation counter wrapped! Please report this.")); + DL_STATIC_INIT (new); + #endif + ++ /* Perform the necessary allocations for adding new global objects ++ to the global scope below, via add_to_global_update. */ ++ if (mode & RTLD_GLOBAL) ++ add_to_global_resize (new); ++ + /* Run the initializer functions of new objects. Temporarily + disable the exception handler, so that lazy binding failures are + fatal. */ +@@ -539,10 +588,7 @@ TLS generation counter wrapped! Please report this.")); + + /* Now we can make the new map available in the global scope. */ + if (mode & RTLD_GLOBAL) +- /* Move the object in the global namespace. */ +- if (add_to_global (new) != 0) +- /* It failed. */ +- return; ++ add_to_global_update (new); + + #ifndef SHARED + /* We must be the static _dl_open in libc.a. A static program that +@@ -556,7 +602,6 @@ TLS generation counter wrapped! Please report this.")); + new->l_name, new->l_ns, new->l_direct_opencount); + } + +- + void * + _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid, + int argc, char *argv[], char *env[]) +@@ -624,6 +669,19 @@ no more namespaces available for dlmopen()")); + _dl_unload_cache (); + #endif + ++ /* Do this for both the error and success cases. The old value has ++ only been determined if the namespace ID was assigned (i.e., it ++ is not __LM_ID_CALLER). In the success case, we actually may ++ have consumed more pending adds than planned (because the local ++ scopes overlap in case of a recursive dlopen, the inner dlopen ++ doing some of the globalization work of the outer dlopen), so the ++ old pending adds value is larger than absolutely necessary. ++ Since it is just a conservative upper bound, this is harmless. ++ The top-level dlopen call will restore the field to zero. */ ++ if (args.nsid >= 0) ++ GL (dl_ns)[args.nsid]._ns_global_scope_pending_adds ++ = args.original_global_scope_pending_adds; ++ + /* See if an error occurred during loading. */ + if (__glibc_unlikely (exception.errstring != NULL)) + { +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 6c5298a80bff8e96..57fbefea3cb841e9 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -311,7 +311,14 @@ struct rtld_global + /* This is zero at program start to signal that the global scope map is + allocated by rtld. Later it keeps the size of the map. It might be + reset if in _dl_close if the last global object is removed. */ +- size_t _ns_global_scope_alloc; ++ unsigned int _ns_global_scope_alloc; ++ ++ /* During dlopen, this is the number of objects that still need to ++ be added to the global scope map. It has to be taken into ++ account when resizing the map, for future map additions after ++ recursive dlopen calls from ELF constructors. */ ++ unsigned int _ns_global_scope_pending_adds; ++ + /* Search table for unique objects. */ + struct unique_sym_table + { diff --git a/glibc-rh1410154-7.patch b/glibc-rh1410154-7.patch new file mode 100755 index 0000000..977a011 --- /dev/null +++ b/glibc-rh1410154-7.patch @@ -0,0 +1,490 @@ +commit a509eb117fac1d764b15eba64993f4bdb63d7f3c +Author: Florian Weimer +Date: Wed Nov 27 16:37:17 2019 +0100 + + Avoid late dlopen failure due to scope, TLS slotinfo updates [BZ #25112] + + This change splits the scope and TLS slotinfo updates in dlopen into + two parts: one to resize the data structures, and one to actually apply + the update. The call to add_to_global_resize in dl_open_worker is moved + before the demarcation point at which no further memory allocations are + allowed. + + _dl_add_to_slotinfo is adjusted to make the list update optional. There + is some optimization possibility here because we could grow the slotinfo + list of arrays in a single call, one the largest TLS modid is known. + + This commit does not fix the fatal meory allocation failure in + _dl_update_slotinfo. Ideally, this error during dlopen should be + recoverable. + + The update order of scopes and TLS data structures is retained, although + it appears to be more correct to fully initialize TLS first, and then + expose symbols in the newly loaded objects via the scope update. + + Tested on x86_64-linux-gnu. + + Change-Id: I240c58387dabda3ca1bcab48b02115175fa83d6c + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 85db4f0ecb5f29ce..b330cff7d349224a 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -214,6 +215,215 @@ _dl_find_dso_for_object (const ElfW(Addr) addr) + } + rtld_hidden_def (_dl_find_dso_for_object); + ++/* Return true if NEW is found in the scope for MAP. */ ++static size_t ++scope_has_map (struct link_map *map, struct link_map *new) ++{ ++ size_t cnt; ++ for (cnt = 0; map->l_scope[cnt] != NULL; ++cnt) ++ if (map->l_scope[cnt] == &new->l_searchlist) ++ return true; ++ return false; ++} ++ ++/* Return the length of the scope for MAP. */ ++static size_t ++scope_size (struct link_map *map) ++{ ++ size_t cnt; ++ for (cnt = 0; map->l_scope[cnt] != NULL; ) ++ ++cnt; ++ return cnt; ++} ++ ++/* Resize the scopes of depended-upon objects, so that the new object ++ can be added later without further allocation of memory. This ++ function can raise an exceptions due to malloc failure. */ ++static void ++resize_scopes (struct link_map *new) ++{ ++ /* If the file is not loaded now as a dependency, add the search ++ list of the newly loaded object to the scope. */ ++ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) ++ { ++ struct link_map *imap = new->l_searchlist.r_list[i]; ++ ++ /* If the initializer has been called already, the object has ++ not been loaded here and now. */ ++ if (imap->l_init_called && imap->l_type == lt_loaded) ++ { ++ if (scope_has_map (imap, new)) ++ /* Avoid duplicates. */ ++ continue; ++ ++ size_t cnt = scope_size (imap); ++ if (__glibc_unlikely (cnt + 1 >= imap->l_scope_max)) ++ { ++ /* The l_scope array is too small. Allocate a new one ++ dynamically. */ ++ size_t new_size; ++ struct r_scope_elem **newp; ++ ++ if (imap->l_scope != imap->l_scope_mem ++ && imap->l_scope_max < array_length (imap->l_scope_mem)) ++ { ++ /* If the current l_scope memory is not pointing to ++ the static memory in the structure, but the ++ static memory in the structure is large enough to ++ use for cnt + 1 scope entries, then switch to ++ using the static memory. */ ++ new_size = array_length (imap->l_scope_mem); ++ newp = imap->l_scope_mem; ++ } ++ else ++ { ++ new_size = imap->l_scope_max * 2; ++ newp = (struct r_scope_elem **) ++ malloc (new_size * sizeof (struct r_scope_elem *)); ++ if (newp == NULL) ++ _dl_signal_error (ENOMEM, "dlopen", NULL, ++ N_("cannot create scope list")); ++ } ++ ++ /* Copy the array and the terminating NULL. */ ++ memcpy (newp, imap->l_scope, ++ (cnt + 1) * sizeof (imap->l_scope[0])); ++ struct r_scope_elem **old = imap->l_scope; ++ ++ imap->l_scope = newp; ++ ++ if (old != imap->l_scope_mem) ++ _dl_scope_free (old); ++ ++ imap->l_scope_max = new_size; ++ } ++ } ++ } ++} ++ ++/* Second stage of resize_scopes: Add NEW to the scopes. Also print ++ debugging information about scopes if requested. ++ ++ This function cannot raise an exception because all required memory ++ has been allocated by a previous call to resize_scopes. */ ++static void ++update_scopes (struct link_map *new) ++{ ++ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) ++ { ++ struct link_map *imap = new->l_searchlist.r_list[i]; ++ int from_scope = 0; ++ ++ if (imap->l_init_called && imap->l_type == lt_loaded) ++ { ++ if (scope_has_map (imap, new)) ++ /* Avoid duplicates. */ ++ continue; ++ ++ size_t cnt = scope_size (imap); ++ /* Assert that resize_scopes has sufficiently enlarged the ++ array. */ ++ assert (cnt + 1 < imap->l_scope_max); ++ ++ /* First terminate the extended list. Otherwise a thread ++ might use the new last element and then use the garbage ++ at offset IDX+1. */ ++ imap->l_scope[cnt + 1] = NULL; ++ atomic_write_barrier (); ++ imap->l_scope[cnt] = &new->l_searchlist; ++ ++ from_scope = cnt; ++ } ++ ++ /* Print scope information. */ ++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) ++ _dl_show_scope (imap, from_scope); ++ } ++} ++ ++/* Call _dl_add_to_slotinfo with DO_ADD set to false, to allocate ++ space in GL (dl_tls_dtv_slotinfo_list). This can raise an ++ exception. The return value is true if any of the new objects use ++ TLS. */ ++static bool ++resize_tls_slotinfo (struct link_map *new) ++{ ++ bool any_tls = false; ++ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) ++ { ++ struct link_map *imap = new->l_searchlist.r_list[i]; ++ ++ /* Only add TLS memory if this object is loaded now and ++ therefore is not yet initialized. */ ++ if (! imap->l_init_called && imap->l_tls_blocksize > 0) ++ { ++ _dl_add_to_slotinfo (imap, false); ++ any_tls = true; ++ } ++ } ++ return any_tls; ++} ++ ++/* Second stage of TLS update, after resize_tls_slotinfo. This ++ function does not raise any exception. It should only be called if ++ resize_tls_slotinfo returned true. */ ++static void ++update_tls_slotinfo (struct link_map *new) ++{ ++ unsigned int first_static_tls = new->l_searchlist.r_nlist; ++ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) ++ { ++ struct link_map *imap = new->l_searchlist.r_list[i]; ++ ++ /* Only add TLS memory if this object is loaded now and ++ therefore is not yet initialized. */ ++ if (! imap->l_init_called && imap->l_tls_blocksize > 0) ++ { ++ _dl_add_to_slotinfo (imap, true); ++ ++ if (imap->l_need_tls_init ++ && first_static_tls == new->l_searchlist.r_nlist) ++ first_static_tls = i; ++ } ++ } ++ ++ if (__builtin_expect (++GL(dl_tls_generation) == 0, 0)) ++ _dl_fatal_printf (N_("\ ++TLS generation counter wrapped! Please report this.")); ++ ++ /* We need a second pass for static tls data, because ++ _dl_update_slotinfo must not be run while calls to ++ _dl_add_to_slotinfo are still pending. */ ++ for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i) ++ { ++ struct link_map *imap = new->l_searchlist.r_list[i]; ++ ++ if (imap->l_need_tls_init ++ && ! imap->l_init_called ++ && imap->l_tls_blocksize > 0) ++ { ++ /* For static TLS we have to allocate the memory here and ++ now, but we can delay updating the DTV. */ ++ imap->l_need_tls_init = 0; ++#ifdef SHARED ++ /* Update the slot information data for at least the ++ generation of the DSO we are allocating data for. */ ++ ++ /* FIXME: This can terminate the process on memory ++ allocation failure. It is not possible to raise ++ exceptions from this context; to fix this bug, ++ _dl_update_slotinfo would have to be split into two ++ operations, similar to resize_scopes and update_scopes ++ above. This is related to bug 16134. */ ++ _dl_update_slotinfo (imap->l_tls_modid); ++#endif ++ ++ GL(dl_init_static_tls) (imap); ++ assert (imap->l_need_tls_init == 0); ++ } ++ } ++} ++ + /* struct dl_init_args and call_dl_init are used to call _dl_init with + exception handling disabled. */ + struct dl_init_args +@@ -431,133 +641,40 @@ dl_open_worker (void *a) + relocation. */ + _dl_open_check (new); + +- /* If the file is not loaded now as a dependency, add the search +- list of the newly loaded object to the scope. */ +- bool any_tls = false; +- unsigned int first_static_tls = new->l_searchlist.r_nlist; +- for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) +- { +- struct link_map *imap = new->l_searchlist.r_list[i]; +- int from_scope = 0; ++ /* This only performs the memory allocations. The actual update of ++ the scopes happens below, after failure is impossible. */ ++ resize_scopes (new); + +- /* If the initializer has been called already, the object has +- not been loaded here and now. */ +- if (imap->l_init_called && imap->l_type == lt_loaded) +- { +- struct r_scope_elem **runp = imap->l_scope; +- size_t cnt = 0; +- +- while (*runp != NULL) +- { +- if (*runp == &new->l_searchlist) +- break; +- ++cnt; +- ++runp; +- } +- +- if (*runp != NULL) +- /* Avoid duplicates. */ +- continue; +- +- if (__glibc_unlikely (cnt + 1 >= imap->l_scope_max)) +- { +- /* The 'r_scope' array is too small. Allocate a new one +- dynamically. */ +- size_t new_size; +- struct r_scope_elem **newp; +- +-#define SCOPE_ELEMS(imap) \ +- (sizeof (imap->l_scope_mem) / sizeof (imap->l_scope_mem[0])) ++ /* Increase the size of the GL (dl_tls_dtv_slotinfo_list) data ++ structure. */ ++ bool any_tls = resize_tls_slotinfo (new); + +- if (imap->l_scope != imap->l_scope_mem +- && imap->l_scope_max < SCOPE_ELEMS (imap)) +- { +- new_size = SCOPE_ELEMS (imap); +- newp = imap->l_scope_mem; +- } +- else +- { +- new_size = imap->l_scope_max * 2; +- newp = (struct r_scope_elem **) +- malloc (new_size * sizeof (struct r_scope_elem *)); +- if (newp == NULL) +- _dl_signal_error (ENOMEM, "dlopen", NULL, +- N_("cannot create scope list")); +- } +- +- memcpy (newp, imap->l_scope, cnt * sizeof (imap->l_scope[0])); +- struct r_scope_elem **old = imap->l_scope; +- +- imap->l_scope = newp; +- +- if (old != imap->l_scope_mem) +- _dl_scope_free (old); +- +- imap->l_scope_max = new_size; +- } +- +- /* First terminate the extended list. Otherwise a thread +- might use the new last element and then use the garbage +- at offset IDX+1. */ +- imap->l_scope[cnt + 1] = NULL; +- atomic_write_barrier (); +- imap->l_scope[cnt] = &new->l_searchlist; +- +- /* Print only new scope information. */ +- from_scope = cnt; +- } +- /* Only add TLS memory if this object is loaded now and +- therefore is not yet initialized. */ +- else if (! imap->l_init_called +- /* Only if the module defines thread local data. */ +- && __builtin_expect (imap->l_tls_blocksize > 0, 0)) +- { +- /* Now that we know the object is loaded successfully add +- modules containing TLS data to the slot info table. We +- might have to increase its size. */ +- _dl_add_to_slotinfo (imap); +- +- if (imap->l_need_tls_init +- && first_static_tls == new->l_searchlist.r_nlist) +- first_static_tls = i; +- +- /* We have to bump the generation counter. */ +- any_tls = true; +- } +- +- /* Print scope information. */ +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) +- _dl_show_scope (imap, from_scope); +- } +- +- /* Bump the generation number if necessary. */ +- if (any_tls && __builtin_expect (++GL(dl_tls_generation) == 0, 0)) +- _dl_fatal_printf (N_("\ +-TLS generation counter wrapped! Please report this.")); +- +- /* We need a second pass for static tls data, because _dl_update_slotinfo +- must not be run while calls to _dl_add_to_slotinfo are still pending. */ +- for (unsigned int i = first_static_tls; i < new->l_searchlist.r_nlist; ++i) +- { +- struct link_map *imap = new->l_searchlist.r_list[i]; +- +- if (imap->l_need_tls_init +- && ! imap->l_init_called +- && imap->l_tls_blocksize > 0) +- { +- /* For static TLS we have to allocate the memory here and +- now, but we can delay updating the DTV. */ +- imap->l_need_tls_init = 0; +-#ifdef SHARED +- /* Update the slot information data for at least the +- generation of the DSO we are allocating data for. */ +- _dl_update_slotinfo (imap->l_tls_modid); +-#endif ++ /* Perform the necessary allocations for adding new global objects ++ to the global scope below. */ ++ if (mode & RTLD_GLOBAL) ++ add_to_global_resize (new); + +- GL(dl_init_static_tls) (imap); +- assert (imap->l_need_tls_init == 0); +- } +- } ++ /* Demarcation point: After this, no recoverable errors are allowed. ++ All memory allocations for new objects must have happened ++ before. */ ++ ++ /* Second stage after resize_scopes: Actually perform the scope ++ update. After this, dlsym and lazy binding can bind to new ++ objects. */ ++ update_scopes (new); ++ ++ /* FIXME: It is unclear whether the order here is correct. ++ Shouldn't new objects be made available for binding (and thus ++ execution) only after there TLS data has been set up fully? ++ Fixing bug 16134 will likely make this distinction less ++ important. */ ++ ++ /* Second stage after resize_tls_slotinfo: Update the slotinfo data ++ structures. */ ++ if (any_tls) ++ /* FIXME: This calls _dl_update_slotinfo, which aborts the process ++ on memory allocation failure. See bug 16134. */ ++ update_tls_slotinfo (new); + + /* Notify the debugger all new objects have been relocated. */ + if (relocation_in_progress) +diff --git a/elf/dl-tls.c b/elf/dl-tls.c +index c87caf13d6a97ba4..a2def280b7096960 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -883,7 +883,7 @@ _dl_tls_get_addr_soft (struct link_map *l) + + + void +-_dl_add_to_slotinfo (struct link_map *l) ++_dl_add_to_slotinfo (struct link_map *l, bool do_add) + { + /* Now that we know the object is loaded successfully add + modules containing TLS data to the dtv info table. We +@@ -939,6 +939,9 @@ cannot create TLS data structures")); + } + + /* Add the information into the slotinfo data structure. */ +- listp->slotinfo[idx].map = l; +- listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1; ++ if (do_add) ++ { ++ listp->slotinfo[idx].map = l; ++ listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1; ++ } + } +diff --git a/elf/rtld.c b/elf/rtld.c +index 4ec26a79cbb0aa4f..0aa1a2a19f649e16 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2167,7 +2167,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + + /* Add object to slot information data if necessasy. */ + if (l->l_tls_blocksize != 0 && tls_init_tp_called) +- _dl_add_to_slotinfo (l); ++ _dl_add_to_slotinfo (l, true); + } + } + else +@@ -2215,7 +2215,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + + /* Add object to slot information data if necessasy. */ + if (l->l_tls_blocksize != 0 && tls_init_tp_called) +- _dl_add_to_slotinfo (l); ++ _dl_add_to_slotinfo (l, true); + } + HP_TIMING_NOW (stop); + +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 57fbefea3cb841e9..c6b7e61badbfd513 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1135,8 +1135,15 @@ extern void *_dl_open (const char *name, int mode, const void *caller, + old scope, OLD can't be freed until no thread is using it. */ + extern int _dl_scope_free (void *) attribute_hidden; + +-/* Add module to slot information data. */ +-extern void _dl_add_to_slotinfo (struct link_map *l) attribute_hidden; ++ ++/* Add module to slot information data. If DO_ADD is false, only the ++ required memory is allocated. Must be called with GL ++ (dl_load_lock) acquired. If the function has already been called ++ for the link map L with !do_add, then this function will not raise ++ an exception, otherwise it is possible that it encounters a memory ++ allocation failure. */ ++extern void _dl_add_to_slotinfo (struct link_map *l, bool do_add) ++ attribute_hidden; + + /* Update slot information data for at least the generation of the + module with the given index. */ diff --git a/glibc-rh1410154-8.patch b/glibc-rh1410154-8.patch new file mode 100755 index 0000000..c22f32a --- /dev/null +++ b/glibc-rh1410154-8.patch @@ -0,0 +1,619 @@ +commit f63b73814f74032c0e5d0a83300e3d864ef905e5 +Author: Florian Weimer +Date: Wed Nov 13 15:44:56 2019 +0100 + + Remove all loaded objects if dlopen fails, ignoring NODELETE [BZ #20839] + + This introduces a “pending NODELETE” state in the link map, which is + flipped to the persistent NODELETE state late in dlopen, via + activate_nodelete. During initial relocation, symbol binding + records pending NODELETE state only. dlclose ignores pending NODELETE + state. Taken together, this results that a partially completed dlopen + is rolled back completely because new NODELETE mappings are unloaded. + + Tested on x86_64-linux-gnu and i386-linux-gnu. + + Change-Id: Ib2a3d86af6f92d75baca65431d74783ee0dbc292 + +Conflicts: + elf/Makefile + (Usual conflicts due to test backport differences.) + +diff --git a/elf/Makefile b/elf/Makefile +index b752f6366400d221..bf7c41f38be42184 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -191,7 +191,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + 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-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail ++ tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail \ ++ tst-dlopenfail + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -282,7 +283,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-absolute-zero-lib tst-big-note-lib \ + tst-sonamemove-linkmod1 \ + tst-sonamemove-runmod1 tst-sonamemove-runmod2 \ +- tst-initlazyfailmod tst-finilazyfailmod ++ tst-initlazyfailmod tst-finilazyfailmod \ ++ tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 + + ifeq (yes,$(have-mtls-dialect-gnu2)) + tests += tst-gnu2-tls1 +@@ -1537,3 +1539,13 @@ LDFLAGS-tst-initlazyfailmod.so = \ + -Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all + LDFLAGS-tst-finilazyfailmod.so = \ + -Wl,-z,lazy -Wl,--unresolved-symbols=ignore-all ++ ++$(objpfx)tst-dlopenfail: $(libdl) ++$(objpfx)tst-dlopenfail.out: \ ++ $(objpfx)tst-dlopenfailmod1.so $(objpfx)tst-dlopenfailmod2.so ++# Order matters here. tst-dlopenfaillinkmod.so's soname ensures ++# a run-time loader failure. ++$(objpfx)tst-dlopenfailmod1.so: \ ++ $(shared-thread-library) $(objpfx)tst-dlopenfaillinkmod.so ++LDFLAGS-tst-dlopenfaillinkmod.so = -Wl,-soname,tst-dlopenfail-missingmod.so ++$(objpfx)tst-dlopenfailmod2.so: $(shared-thread-library) +diff --git a/elf/dl-close.c b/elf/dl-close.c +index 88aeea25839a34e0..243a028c443173c1 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -168,14 +168,6 @@ _dl_close_worker (struct link_map *map, bool force) + char done[nloaded]; + struct link_map *maps[nloaded]; + +- /* Clear DF_1_NODELETE to force object deletion. We don't need to touch +- l_tls_dtor_count because forced object deletion only happens when an +- error occurs during object load. Destructor registration for TLS +- non-POD objects should not have happened till then for this +- object. */ +- if (force) +- map->l_flags_1 &= ~DF_1_NODELETE; +- + /* Run over the list and assign indexes to the link maps and enter + them into the MAPS array. */ + int idx = 0; +@@ -205,7 +197,7 @@ _dl_close_worker (struct link_map *map, bool force) + /* Check whether this object is still used. */ + if (l->l_type == lt_loaded + && l->l_direct_opencount == 0 +- && (l->l_flags_1 & DF_1_NODELETE) == 0 ++ && l->l_nodelete != link_map_nodelete_active + /* See CONCURRENCY NOTES in cxa_thread_atexit_impl.c to know why + acquire is sufficient and correct. */ + && atomic_load_acquire (&l->l_tls_dtor_count) == 0 +@@ -288,7 +280,7 @@ _dl_close_worker (struct link_map *map, bool force) + if (!used[i]) + { + assert (imap->l_type == lt_loaded +- && (imap->l_flags_1 & DF_1_NODELETE) == 0); ++ && imap->l_nodelete != link_map_nodelete_active); + + /* Call its termination function. Do not do it for + half-cooked objects. Temporarily disable exception +@@ -828,7 +820,7 @@ _dl_close (void *_map) + before we took the lock. There is no way to detect this (see below) + so we proceed assuming this isn't the case. First see whether we + can remove the object at all. */ +- if (__glibc_unlikely (map->l_flags_1 & DF_1_NODELETE)) ++ if (__glibc_unlikely (map->l_nodelete == link_map_nodelete_active)) + { + /* Nope. Do nothing. */ + __rtld_lock_unlock_recursive (GL(dl_load_lock)); +diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c +index efbdb8deb3c0a9d4..c5e5857fb1fe2808 100644 +--- a/elf/dl-lookup.c ++++ b/elf/dl-lookup.c +@@ -192,9 +192,10 @@ enter_unique_sym (struct unique_sym *table, size_t size, + Return the matching symbol in RESULT. */ + static void + do_lookup_unique (const char *undef_name, uint_fast32_t new_hash, +- const struct link_map *map, struct sym_val *result, ++ struct link_map *map, struct sym_val *result, + int type_class, const ElfW(Sym) *sym, const char *strtab, +- const ElfW(Sym) *ref, const struct link_map *undef_map) ++ const ElfW(Sym) *ref, const struct link_map *undef_map, ++ int flags) + { + /* We have to determine whether we already found a symbol with this + name before. If not then we have to add it to the search table. +@@ -222,7 +223,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash, + copy from the copy addressed through the + relocation. */ + result->s = sym; +- result->m = (struct link_map *) map; ++ result->m = map; + } + else + { +@@ -311,9 +312,19 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash, + new_hash, strtab + sym->st_name, sym, map); + + if (map->l_type == lt_loaded) +- /* Make sure we don't unload this object by +- setting the appropriate flag. */ +- ((struct link_map *) map)->l_flags_1 |= DF_1_NODELETE; ++ { ++ /* Make sure we don't unload this object by ++ setting the appropriate flag. */ ++ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS) ++ && map->l_nodelete == link_map_nodelete_inactive) ++ _dl_debug_printf ("\ ++marking %s [%lu] as NODELETE due to unique symbol\n", ++ map->l_name, map->l_ns); ++ if (flags & DL_LOOKUP_FOR_RELOCATE) ++ map->l_nodelete = link_map_nodelete_pending; ++ else ++ map->l_nodelete = link_map_nodelete_active; ++ } + } + ++tab->n_elements; + +@@ -525,8 +536,9 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash, + return 1; + + case STB_GNU_UNIQUE:; +- do_lookup_unique (undef_name, new_hash, map, result, type_class, +- sym, strtab, ref, undef_map); ++ do_lookup_unique (undef_name, new_hash, (struct link_map *) map, ++ result, type_class, sym, strtab, ref, ++ undef_map, flags); + return 1; + + default: +@@ -568,9 +580,13 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags) + if (undef_map == map) + return 0; + +- /* Avoid references to objects which cannot be unloaded anyway. */ ++ /* Avoid references to objects which cannot be unloaded anyway. We ++ do not need to record dependencies if this object goes away ++ during dlopen failure, either. IFUNC resolvers with relocation ++ dependencies may pick an dependency which can be dlclose'd, but ++ such IFUNC resolvers are undefined anyway. */ + assert (map->l_type == lt_loaded); +- if ((map->l_flags_1 & DF_1_NODELETE) != 0) ++ if (map->l_nodelete != link_map_nodelete_inactive) + return 0; + + struct link_map_reldeps *l_reldeps +@@ -678,16 +694,33 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags) + + /* Redo the NODELETE check, as when dl_load_lock wasn't held + yet this could have changed. */ +- if ((map->l_flags_1 & DF_1_NODELETE) != 0) ++ if (map->l_nodelete != link_map_nodelete_inactive) + goto out; + + /* If the object with the undefined reference cannot be removed ever + just make sure the same is true for the object which contains the + definition. */ + if (undef_map->l_type != lt_loaded +- || (undef_map->l_flags_1 & DF_1_NODELETE) != 0) ++ || (undef_map->l_nodelete != link_map_nodelete_inactive)) + { +- map->l_flags_1 |= DF_1_NODELETE; ++ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS) ++ && map->l_nodelete == link_map_nodelete_inactive) ++ { ++ if (undef_map->l_name[0] == '\0') ++ _dl_debug_printf ("\ ++marking %s [%lu] as NODELETE due to reference to main program\n", ++ map->l_name, map->l_ns); ++ else ++ _dl_debug_printf ("\ ++marking %s [%lu] as NODELETE due to reference to %s [%lu]\n", ++ map->l_name, map->l_ns, ++ undef_map->l_name, undef_map->l_ns); ++ } ++ ++ if (flags & DL_LOOKUP_FOR_RELOCATE) ++ map->l_nodelete = link_map_nodelete_pending; ++ else ++ map->l_nodelete = link_map_nodelete_active; + goto out; + } + +@@ -712,7 +745,18 @@ add_dependency (struct link_map *undef_map, struct link_map *map, int flags) + no fatal problem. We simply make sure the referenced object + cannot be unloaded. This is semantically the correct + behavior. */ +- map->l_flags_1 |= DF_1_NODELETE; ++ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_BINDINGS) ++ && map->l_nodelete == link_map_nodelete_inactive) ++ _dl_debug_printf ("\ ++marking %s [%lu] as NODELETE due to memory allocation failure\n", ++ map->l_name, map->l_ns); ++ if (flags & DL_LOOKUP_FOR_RELOCATE) ++ /* In case of non-lazy binding, we could actually ++ report the memory allocation error, but for now, we ++ use the conservative approximation as well. */ ++ map->l_nodelete = link_map_nodelete_pending; ++ else ++ map->l_nodelete = link_map_nodelete_active; + goto out; + } + else +diff --git a/elf/dl-open.c b/elf/dl-open.c +index b330cff7d349224a..79c6e4c8ed1c9dfa 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -424,6 +424,40 @@ TLS generation counter wrapped! Please report this.")); + } + } + ++/* Mark the objects as NODELETE if required. This is delayed until ++ after dlopen failure is not possible, so that _dl_close can clean ++ up objects if necessary. */ ++static void ++activate_nodelete (struct link_map *new, int mode) ++{ ++ if (mode & RTLD_NODELETE || new->l_nodelete == link_map_nodelete_pending) ++ { ++ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf ("activating NODELETE for %s [%lu]\n", ++ new->l_name, new->l_ns); ++ new->l_nodelete = link_map_nodelete_active; ++ } ++ ++ for (unsigned int i = 0; i < new->l_searchlist.r_nlist; ++i) ++ { ++ struct link_map *imap = new->l_searchlist.r_list[i]; ++ if (imap->l_nodelete == link_map_nodelete_pending) ++ { ++ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES)) ++ _dl_debug_printf ("activating NODELETE for %s [%lu]\n", ++ imap->l_name, imap->l_ns); ++ ++ /* Only new objects should have set ++ link_map_nodelete_pending. Existing objects should not ++ have gained any new dependencies and therefore cannot ++ reach NODELETE status. */ ++ assert (!imap->l_init_called || imap->l_type != lt_loaded); ++ ++ imap->l_nodelete = link_map_nodelete_active; ++ } ++ } ++} ++ + /* struct dl_init_args and call_dl_init are used to call _dl_init with + exception handling disabled. */ + struct dl_init_args +@@ -493,12 +527,6 @@ dl_open_worker (void *a) + return; + } + +- /* Mark the object as not deletable if the RTLD_NODELETE flags was passed. +- Do this early so that we don't skip marking the object if it was +- already loaded. */ +- if (__glibc_unlikely (mode & RTLD_NODELETE)) +- new->l_flags_1 |= DF_1_NODELETE; +- + if (__glibc_unlikely (mode & __RTLD_SPROF)) + /* This happens only if we load a DSO for 'sprof'. */ + return; +@@ -514,19 +542,37 @@ dl_open_worker (void *a) + _dl_debug_printf ("opening file=%s [%lu]; direct_opencount=%u\n\n", + new->l_name, new->l_ns, new->l_direct_opencount); + +- /* If the user requested the object to be in the global namespace +- but it is not so far, add it now. */ ++ /* If the user requested the object to be in the global ++ namespace but it is not so far, prepare to add it now. This ++ can raise an exception to do a malloc failure. */ + if ((mode & RTLD_GLOBAL) && new->l_global == 0) ++ add_to_global_resize (new); ++ ++ /* Mark the object as not deletable if the RTLD_NODELETE flags ++ was passed. */ ++ if (__glibc_unlikely (mode & RTLD_NODELETE)) + { +- add_to_global_resize (new); +- add_to_global_update (new); ++ if (__glibc_unlikely (GLRO (dl_debug_mask) & DL_DEBUG_FILES) ++ && new->l_nodelete == link_map_nodelete_inactive) ++ _dl_debug_printf ("marking %s [%lu] as NODELETE\n", ++ new->l_name, new->l_ns); ++ new->l_nodelete = link_map_nodelete_active; + } + ++ /* Finalize the addition to the global scope. */ ++ if ((mode & RTLD_GLOBAL) && new->l_global == 0) ++ add_to_global_update (new); ++ + assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT); + + return; + } + ++ /* Schedule NODELETE marking for the directly loaded object if ++ requested. */ ++ if (__glibc_unlikely (mode & RTLD_NODELETE)) ++ new->l_nodelete = link_map_nodelete_pending; ++ + /* Load that object's dependencies. */ + _dl_map_object_deps (new, NULL, 0, 0, + mode & (__RTLD_DLOPEN | RTLD_DEEPBIND | __RTLD_AUDIT)); +@@ -598,6 +644,14 @@ dl_open_worker (void *a) + + int relocation_in_progress = 0; + ++ /* Perform relocation. This can trigger lazy binding in IFUNC ++ resolvers. For NODELETE mappings, these dependencies are not ++ recorded because the flag has not been applied to the newly ++ loaded objects. This means that upon dlopen failure, these ++ NODELETE objects can be unloaded despite existing references to ++ them. However, such relocation dependencies in IFUNC resolvers ++ are undefined anyway, so this is not a problem. */ ++ + for (unsigned int i = nmaps; i-- > 0; ) + { + l = maps[i]; +@@ -627,7 +681,7 @@ dl_open_worker (void *a) + _dl_start_profile (); + + /* Prevent unloading the object. */ +- GL(dl_profile_map)->l_flags_1 |= DF_1_NODELETE; ++ GL(dl_profile_map)->l_nodelete = link_map_nodelete_active; + } + } + else +@@ -658,6 +712,8 @@ dl_open_worker (void *a) + All memory allocations for new objects must have happened + before. */ + ++ activate_nodelete (new, mode); ++ + /* Second stage after resize_scopes: Actually perform the scope + update. After this, dlsym and lazy binding can bind to new + objects. */ +@@ -817,6 +873,10 @@ no more namespaces available for dlmopen()")); + GL(dl_tls_dtv_gaps) = true; + + _dl_close_worker (args.map, true); ++ ++ /* All link_map_nodelete_pending objects should have been ++ deleted at this point, which is why it is not necessary ++ to reset the flag here. */ + } + + assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT); +diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h +index 4b1ea7c4078ee947..ea286abaea0128d1 100644 +--- a/elf/get-dynamic-info.h ++++ b/elf/get-dynamic-info.h +@@ -163,6 +163,8 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) + if (info[VERSYMIDX (DT_FLAGS_1)] != NULL) + { + l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val; ++ if (l->l_flags_1 & DF_1_NODELETE) ++ l->l_nodelete = link_map_nodelete_pending; + + /* Only DT_1_SUPPORTED_MASK bits are supported, and we would like + to assert this, but we can't. Users have been setting +diff --git a/elf/tst-dlopenfail.c b/elf/tst-dlopenfail.c +new file mode 100644 +index 0000000000000000..ce3140c899562ca8 +--- /dev/null ++++ b/elf/tst-dlopenfail.c +@@ -0,0 +1,79 @@ ++/* Test dlopen rollback after failures involving NODELETE objects (bug 20839). ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* This test uses libpthread as the canonical NODELETE module. If ++ libpthread is no longer NODELETE because it has been merged into ++ libc, the test needs to be updated. */ ++ TEST_VERIFY (dlsym (NULL, "pthread_create") == NULL); ++ ++ /* This is expected to fail because of the missing dependency. */ ++ puts ("info: attempting to load tst-dlopenfailmod1.so"); ++ TEST_VERIFY (dlopen ("tst-dlopenfailmod1.so", RTLD_LAZY) == NULL); ++ const char *message = dlerror (); ++ TEST_COMPARE_STRING (message, ++ "tst-dlopenfail-missingmod.so:" ++ " cannot open shared object file:" ++ " No such file or directory"); ++ ++ /* Do not probe for the presence of libpthread at this point because ++ that might trigger relocation if bug 20839 is present, obscuring ++ a subsequent crash. */ ++ ++ /* This is expected to succeed. */ ++ puts ("info: loading tst-dlopenfailmod2.so"); ++ void *handle = xdlopen ("tst-dlopenfailmod2.so", RTLD_NOW); ++ xdlclose (handle); ++ ++ /* libpthread should remain loaded. */ ++ TEST_VERIFY (dlopen (LIBPTHREAD_SO, RTLD_LAZY | RTLD_NOLOAD) != NULL); ++ TEST_VERIFY (dlsym (NULL, "pthread_create") == NULL); ++ ++ /* We can make libpthread global, and then the symbol should become ++ available. */ ++ TEST_VERIFY (dlopen (LIBPTHREAD_SO, RTLD_LAZY | RTLD_GLOBAL) != NULL); ++ TEST_VERIFY (dlsym (NULL, "pthread_create") != NULL); ++ ++ /* sem_open is sufficiently complex to depend on relocations. */ ++ void *(*sem_open_ptr) (const char *, int flag, ...) ++ = dlsym (NULL, "sem_open"); ++ if (sem_open_ptr == NULL) ++ /* Hurd does not implement sem_open. */ ++ puts ("warning: sem_open not found, further testing not possible"); ++ else ++ { ++ errno = 0; ++ TEST_VERIFY (sem_open_ptr ("/", 0) == NULL); ++ TEST_COMPARE (errno, EINVAL); ++ } ++ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-dlopenfaillinkmod.c b/elf/tst-dlopenfaillinkmod.c +new file mode 100644 +index 0000000000000000..3b14b02bc9a12c0b +--- /dev/null ++++ b/elf/tst-dlopenfaillinkmod.c +@@ -0,0 +1,17 @@ ++/* Empty module with a soname which is not available at run time. ++ 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 ++ . */ +diff --git a/elf/tst-dlopenfailmod1.c b/elf/tst-dlopenfailmod1.c +new file mode 100644 +index 0000000000000000..6ef48829899a5a64 +--- /dev/null ++++ b/elf/tst-dlopenfailmod1.c +@@ -0,0 +1,36 @@ ++/* Module which depends on two modules: one NODELETE, one missing. ++ 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 ++ . */ ++ ++/* Note: Due to the missing second module, this object cannot be ++ loaded at run time. */ ++ ++#include ++#include ++#include ++ ++/* Force linking against libpthread. */ ++void *pthread_create_reference = pthread_create; ++ ++/* The constructor will never be executed because the module cannot be ++ loaded. */ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ puts ("tst-dlopenfailmod1 constructor executed"); ++ _exit (1); ++} +diff --git a/elf/tst-dlopenfailmod2.c b/elf/tst-dlopenfailmod2.c +new file mode 100644 +index 0000000000000000..7d600386c13b98bd +--- /dev/null ++++ b/elf/tst-dlopenfailmod2.c +@@ -0,0 +1,29 @@ ++/* Module which depends on on a NODELETE module, and can be loaded. ++ 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 ++ . */ ++ ++#include ++#include ++ ++/* Force linking against libpthread. */ ++void *pthread_create_reference = pthread_create; ++ ++static void __attribute__ ((constructor)) ++init (void) ++{ ++ puts ("info: tst-dlopenfailmod2.so constructor invoked"); ++} +diff --git a/include/link.h b/include/link.h +index 83b1c34b7b4db8f3..a277b77cad6b52b1 100644 +--- a/include/link.h ++++ b/include/link.h +@@ -79,6 +79,21 @@ struct r_search_path_struct + int malloced; + }; + ++/* Type used by the l_nodelete member. */ ++enum link_map_nodelete ++{ ++ /* This link map can be deallocated. */ ++ link_map_nodelete_inactive = 0, /* Zero-initialized in _dl_new_object. */ ++ ++ /* This link map cannot be deallocated. */ ++ link_map_nodelete_active, ++ ++ /* This link map cannot be deallocated after dlopen has succeded. ++ dlopen turns this into link_map_nodelete_active. dlclose treats ++ this intermediate state as link_map_nodelete_active. */ ++ link_map_nodelete_pending, ++}; ++ + + /* Structure describing a loaded shared object. The `l_next' and `l_prev' + members form a chain of all the shared objects loaded at startup. +@@ -203,6 +218,11 @@ struct link_map + freed, ie. not allocated with + the dummy malloc in ld.so. */ + ++ /* Actually of type enum link_map_nodelete. Separate byte due to ++ a read in add_dependency in elf/dl-lookup.c outside the loader ++ lock. Only valid for l_type == lt_loaded. */ ++ unsigned char l_nodelete; ++ + #include + + /* Collected information about own RPATH directories. */ diff --git a/glibc-rh1410154-9.patch b/glibc-rh1410154-9.patch new file mode 100755 index 0000000..ab5a3df --- /dev/null +++ b/glibc-rh1410154-9.patch @@ -0,0 +1,104 @@ +commit a2e8aa0d9ea648068d8be52dd7b15f1b6a008e23 +Author: Florian Weimer +Date: Thu Oct 31 19:30:19 2019 +0100 + + Block signals during the initial part of dlopen + + Lazy binding in a signal handler that interrupts a dlopen sees + intermediate dynamic linker state. This has likely been always + unsafe, but with the new pending NODELETE state, this is clearly + incorrect. Other threads are excluded via the loader lock, but the + current thread is not. Blocking signals until right before ELF + constructors run is the safe thing to do. + + Change-Id: Iad079080ebe7442c13313ba11dc2797953faef35 + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 79c6e4c8ed1c9dfa..25838b073ac1edaf 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -52,6 +53,10 @@ struct dl_open_args + /* Namespace ID. */ + Lmid_t nsid; + ++ /* Original signal mask. Used for unblocking signal handlers before ++ running ELF constructors. */ ++ sigset_t original_signal_mask; ++ + /* Original value of _ns_global_scope_pending_adds. Set by + dl_open_worker. Only valid if nsid is a real namespace + (non-negative). */ +@@ -524,12 +529,16 @@ dl_open_worker (void *a) + if (new == NULL) + { + assert (mode & RTLD_NOLOAD); ++ __libc_signal_restore_set (&args->original_signal_mask); + return; + } + + if (__glibc_unlikely (mode & __RTLD_SPROF)) +- /* This happens only if we load a DSO for 'sprof'. */ +- return; ++ { ++ /* This happens only if we load a DSO for 'sprof'. */ ++ __libc_signal_restore_set (&args->original_signal_mask); ++ return; ++ } + + /* This object is directly loaded. */ + ++new->l_direct_opencount; +@@ -565,6 +574,7 @@ dl_open_worker (void *a) + + assert (_dl_debug_initialize (0, args->nsid)->r_state == RT_CONSISTENT); + ++ __libc_signal_restore_set (&args->original_signal_mask); + return; + } + +@@ -745,6 +755,10 @@ dl_open_worker (void *a) + if (mode & RTLD_GLOBAL) + add_to_global_resize (new); + ++ /* Unblock signals. Data structures are now consistent, and ++ application code may run. */ ++ __libc_signal_restore_set (&args->original_signal_mask); ++ + /* Run the initializer functions of new objects. Temporarily + disable the exception handler, so that lazy binding failures are + fatal. */ +@@ -834,6 +848,10 @@ no more namespaces available for dlmopen()")); + args.argv = argv; + args.env = env; + ++ /* Recursive lazy binding during manipulation of the dynamic loader ++ structures may result in incorrect behavior. */ ++ __libc_signal_block_all (&args.original_signal_mask); ++ + struct dl_exception exception; + int errcode = _dl_catch_exception (&exception, dl_open_worker, &args); + +@@ -874,10 +892,16 @@ no more namespaces available for dlmopen()")); + + _dl_close_worker (args.map, true); + ++ /* Restore the signal mask. In the success case, this ++ happens inside dl_open_worker. */ ++ __libc_signal_restore_set (&args.original_signal_mask); ++ + /* All link_map_nodelete_pending objects should have been + deleted at this point, which is why it is not necessary + to reset the flag here. */ + } ++ else ++ __libc_signal_restore_set (&args.original_signal_mask); + + assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT); + diff --git a/glibc-rh1577365.patch b/glibc-rh1577365.patch new file mode 100755 index 0000000..c1e30d4 --- /dev/null +++ b/glibc-rh1577365.patch @@ -0,0 +1,22 @@ +Please see the following bug for a complete summary: +https://bugzilla.redhat.com/show_bug.cgi?id=1615608 + +Index: glibc-2.28/manual/startup.texi +=================================================================== +--- glibc-2.28.orig/manual/startup.texi ++++ glibc-2.28/manual/startup.texi +@@ -1005,14 +1005,6 @@ This function actually terminates the pr + intercept this signal; see @ref{Signal Handling}. + @end deftypefun + +-@c Put in by rms. Don't remove. +-@cartouche +-@strong{Future Change Warning:} Proposed Federal censorship regulations +-may prohibit us from giving you information about the possibility of +-calling this function. We would be required to say that this is not an +-acceptable way of terminating a program. +-@end cartouche +- + @node Termination Internals + @subsection Termination Internals + diff --git a/glibc-rh1577438.patch b/glibc-rh1577438.patch new file mode 100755 index 0000000..aab01cc --- /dev/null +++ b/glibc-rh1577438.patch @@ -0,0 +1,24 @@ +Patch by Hanataka Shinya from +. Confirmed by TAMUKI +Shoichi's patch in +. + +The official announcement by the Japanese Prime Minister in + uses U+4EE4 U+548C +as well. + +diff --git a/localedata/locales/ja_JP b/localedata/locales/ja_JP +index 1fd2fee44b2879d9..30190b624856cc53 100644 +--- a/localedata/locales/ja_JP ++++ b/localedata/locales/ja_JP +@@ -14946,7 +14946,9 @@ am_pm "";"" + + t_fmt_ampm "%p%I%M%S" + +-era "+:2:1990//01//01:+*::%EC%Ey";/ ++era "+:2:2020//01//01:+*::%EC%Ey";/ ++ "+:1:2019//05//01:2019//12//31::%EC";/ ++ "+:2:1990//01//01:2019//04//30::%EC%Ey";/ + "+:1:1989//01//08:1989//12//31::%EC";/ + "+:2:1927//01//01:1989//01//07::%EC%Ey";/ + "+:1:1926//12//25:1926//12//31::%EC";/ diff --git a/glibc-rh1614253.patch b/glibc-rh1614253.patch new file mode 100755 index 0000000..ae4b43d --- /dev/null +++ b/glibc-rh1614253.patch @@ -0,0 +1,254 @@ +commit 4b25485f03158959cff45379eecc1d73c7dcdd11 +Author: Florian Weimer +Date: Fri Aug 10 11:19:26 2018 +0200 + + Linux: Rewrite __old_getdents64 [BZ #23497] + + Commit 298d0e3129c0b5137f4989275b13fe30d0733c4d ("Consolidate Linux + getdents{64} implementation") broke the implementation because it does + not take into account struct offset differences. + + The new implementation is close to the old one, before the + consolidation, but has been cleaned up slightly. + + (cherry picked from commit 690652882b499defb3d950dfeff8fe421d13cab5) + +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index f71cc39c7e257a0a..773aaea0e980bdd6 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -161,6 +161,7 @@ inhibit-glue = yes + + ifeq ($(subdir),dirent) + sysdep_routines += getdirentries getdirentries64 ++tests-internal += tst-readdir64-compat + endif + + ifeq ($(subdir),nis) +diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c +index 3bde0cf4f0226f95..bc140b5a7fac3040 100644 +--- a/sysdeps/unix/sysv/linux/getdents64.c ++++ b/sysdeps/unix/sysv/linux/getdents64.c +@@ -33,41 +33,80 @@ strong_alias (__getdents64, __getdents) + # include + + # if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) +-# include ++# include ++# include + +-/* kernel definition of as of 3.2. */ +-struct compat_linux_dirent ++static ssize_t ++handle_overflow (int fd, __off64_t offset, ssize_t count) + { +- /* Both d_ino and d_off are compat_ulong_t which are defined in all +- architectures as 'u32'. */ +- uint32_t d_ino; +- uint32_t d_off; +- unsigned short d_reclen; +- char d_name[1]; +-}; ++ /* If this is the first entry in the buffer, we can report the ++ error. */ ++ if (count == 0) ++ { ++ __set_errno (EOVERFLOW); ++ return -1; ++ } ++ ++ /* Otherwise, seek to the overflowing entry, so that the next call ++ will report the error, and return the data read so far.. */ ++ if (__lseek64 (fd, offset, SEEK_SET) != 0) ++ return -1; ++ return count; ++} + + ssize_t + __old_getdents64 (int fd, char *buf, size_t nbytes) + { +- ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, buf, nbytes); ++ /* We do not move the individual directory entries. This is only ++ possible if the target type (struct __old_dirent64) is smaller ++ than the source type. */ ++ _Static_assert (offsetof (struct __old_dirent64, d_name) ++ <= offsetof (struct dirent64, d_name), ++ "__old_dirent64 is larger than dirent64"); ++ _Static_assert (__alignof__ (struct __old_dirent64) ++ <= __alignof__ (struct dirent64), ++ "alignment of __old_dirent64 is larger than dirent64"); + +- /* The kernel added the d_type value after the name. Change this now. */ +- if (retval != -1) ++ ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes); ++ if (retval > 0) + { +- union +- { +- struct compat_linux_dirent k; +- struct dirent u; +- } *kbuf = (void *) buf; +- +- while ((char *) kbuf < buf + retval) ++ char *p = buf; ++ char *end = buf + retval; ++ while (p < end) + { +- char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1); +- memmove (kbuf->u.d_name, kbuf->k.d_name, +- strlen (kbuf->k.d_name) + 1); +- kbuf->u.d_type = d_type; ++ struct dirent64 *source = (struct dirent64 *) p; ++ ++ /* Copy out the fixed-size data. */ ++ __ino_t ino = source->d_ino; ++ __off64_t offset = source->d_off; ++ unsigned int reclen = source->d_reclen; ++ unsigned char type = source->d_type; ++ ++ /* Check for ino_t overflow. */ ++ if (__glibc_unlikely (ino != source->d_ino)) ++ return handle_overflow (fd, offset, p - buf); ++ ++ /* Convert to the target layout. Use a separate struct and ++ memcpy to side-step aliasing issues. */ ++ struct __old_dirent64 result; ++ result.d_ino = ino; ++ result.d_off = offset; ++ result.d_reclen = reclen; ++ result.d_type = type; ++ ++ /* Write the fixed-sized part of the result to the ++ buffer. */ ++ size_t result_name_offset = offsetof (struct __old_dirent64, d_name); ++ memcpy (p, &result, result_name_offset); ++ ++ /* Adjust the position of the name if necessary. Copy ++ everything until the end of the record, including the ++ terminating NUL byte. */ ++ if (result_name_offset != offsetof (struct dirent64, d_name)) ++ memmove (p + result_name_offset, source->d_name, ++ reclen - offsetof (struct dirent64, d_name)); + +- kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen); ++ p += reclen; + } + } + return retval; +diff --git a/sysdeps/unix/sysv/linux/tst-readdir64-compat.c b/sysdeps/unix/sysv/linux/tst-readdir64-compat.c +new file mode 100644 +index 0000000000000000..43c4a8477c7403c5 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-readdir64-compat.c +@@ -0,0 +1,111 @@ ++/* Test readdir64 compatibility symbol. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Copied from . */ ++struct __old_dirent64 ++ { ++ __ino_t d_ino; ++ __off64_t d_off; ++ unsigned short int d_reclen; ++ unsigned char d_type; ++ char d_name[256]; ++ }; ++ ++typedef struct __old_dirent64 *(*compat_readdir64_type) (DIR *); ++ ++#if TEST_COMPAT (libc, GLIBC_2_1, GLIBC_2_2) ++struct __old_dirent64 *compat_readdir64 (DIR *); ++compat_symbol_reference (libc, compat_readdir64, readdir64, GLIBC_2_1); ++#endif ++ ++static int ++do_test (void) ++{ ++#if TEST_COMPAT (libc, GLIBC_2_1, GLIBC_2_2) ++ ++ /* Directory stream using the non-compat readdir64 symbol. The test ++ checks against this. */ ++ DIR *dir_reference = opendir ("."); ++ TEST_VERIFY_EXIT (dir_reference != NULL); ++ DIR *dir_test = opendir ("."); ++ TEST_VERIFY_EXIT (dir_test != NULL); ++ ++ /* This loop assumes that the enumeration order is consistent for ++ two different handles. Nothing should write to the current ++ directory (in the source tree) while this test runs, so there ++ should not be any difference due to races. */ ++ size_t count = 0; ++ while (true) ++ { ++ errno = 0; ++ struct dirent64 *entry_reference = readdir64 (dir_reference); ++ if (entry_reference == NULL && errno != 0) ++ FAIL_EXIT1 ("readdir64 entry %zu: %m\n", count); ++ struct __old_dirent64 *entry_test = compat_readdir64 (dir_test); ++ if (entry_reference == NULL) ++ { ++ if (errno == EOVERFLOW) ++ { ++ TEST_VERIFY (entry_reference->d_ino ++ != (__ino_t) entry_reference->d_ino); ++ printf ("info: inode number overflow at entry %zu\n", count); ++ break; ++ } ++ if (errno != 0) ++ FAIL_EXIT1 ("compat readdir64 entry %zu: %m\n", count); ++ } ++ ++ /* Check that both streams end at the same time. */ ++ if (entry_reference == NULL) ++ { ++ TEST_VERIFY (entry_test == NULL); ++ break; ++ } ++ else ++ TEST_VERIFY_EXIT (entry_test != NULL); ++ ++ /* Check that the entries are the same. */ ++ TEST_COMPARE_BLOB (entry_reference->d_name, ++ strlen (entry_reference->d_name), ++ entry_test->d_name, strlen (entry_test->d_name)); ++ TEST_COMPARE (entry_reference->d_ino, entry_test->d_ino); ++ TEST_COMPARE (entry_reference->d_off, entry_test->d_off); ++ TEST_COMPARE (entry_reference->d_type, entry_test->d_type); ++ TEST_COMPARE (entry_reference->d_reclen, entry_test->d_reclen); ++ ++ ++count; ++ } ++ printf ("info: %zu directory entries found\n", count); ++ TEST_VERIFY (count >= 3); /* ".", "..", and some source files. */ ++ ++ TEST_COMPARE (closedir (dir_test), 0); ++ TEST_COMPARE (closedir (dir_reference), 0); ++#endif ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1614979.patch b/glibc-rh1614979.patch new file mode 100755 index 0000000..c97ae2c --- /dev/null +++ b/glibc-rh1614979.patch @@ -0,0 +1,154 @@ +commit d524fa6c35e675eedbd8fe6cdf4db0b49c658026 +Author: H.J. Lu +Date: Thu Nov 8 10:06:58 2018 -0800 + + Check multiple NT_GNU_PROPERTY_TYPE_0 notes [BZ #23509] + + Linkers group input note sections with the same name into one output + note section with the same name. One output note section is placed in + one PT_NOTE segment. Since new linkers merge input .note.gnu.property + sections into one output .note.gnu.property section, there is only + one NT_GNU_PROPERTY_TYPE_0 note in one PT_NOTE segment with new linkers. + Since older linkers treat input .note.gnu.property section as a generic + note section and just concatenate all input .note.gnu.property sections + into one output .note.gnu.property section without merging them, we may + see multiple NT_GNU_PROPERTY_TYPE_0 notes in one PT_NOTE segment with + older linkers. + + When an older linker is used to created the program on CET-enabled OS, + the linker output has a single .note.gnu.property section with multiple + NT_GNU_PROPERTY_TYPE_0 notes, some of which have IBT and SHSTK enable + bits set even if the program isn't CET enabled. Such programs will + crash on CET-enabled machines. This patch updates the note parser: + + 1. Skip note parsing if a NT_GNU_PROPERTY_TYPE_0 note has been processed. + 2. Check multiple NT_GNU_PROPERTY_TYPE_0 notes. + + [BZ #23509] + * sysdeps/x86/dl-prop.h (_dl_process_cet_property_note): Skip + note parsing if a NT_GNU_PROPERTY_TYPE_0 note has been processed. + Update the l_cet field when processing NT_GNU_PROPERTY_TYPE_0 note. + Check multiple NT_GNU_PROPERTY_TYPE_0 notes. + * sysdeps/x86/link_map.h (l_cet): Expand to 3 bits, Add + lc_unknown. + +diff --git a/sysdeps/x86/dl-prop.h b/sysdeps/x86/dl-prop.h +index 26c3131ac5e2d080..9ab890d12bb99133 100644 +--- a/sysdeps/x86/dl-prop.h ++++ b/sysdeps/x86/dl-prop.h +@@ -49,6 +49,10 @@ _dl_process_cet_property_note (struct link_map *l, + const ElfW(Addr) align) + { + #if CET_ENABLED ++ /* Skip if we have seen a NT_GNU_PROPERTY_TYPE_0 note before. */ ++ if (l->l_cet != lc_unknown) ++ return; ++ + /* The NT_GNU_PROPERTY_TYPE_0 note must be aliged to 4 bytes in + 32-bit objects and to 8 bytes in 64-bit objects. Skip notes + with incorrect alignment. */ +@@ -57,6 +61,9 @@ _dl_process_cet_property_note (struct link_map *l, + + const ElfW(Addr) start = (ElfW(Addr)) note; + ++ unsigned int feature_1 = 0; ++ unsigned int last_type = 0; ++ + while ((ElfW(Addr)) (note + 1) - start < size) + { + /* Find the NT_GNU_PROPERTY_TYPE_0 note. */ +@@ -64,10 +71,18 @@ _dl_process_cet_property_note (struct link_map *l, + && note->n_type == NT_GNU_PROPERTY_TYPE_0 + && memcmp (note + 1, "GNU", 4) == 0) + { ++ /* Stop if we see more than one GNU property note which may ++ be generated by the older linker. */ ++ if (l->l_cet != lc_unknown) ++ return; ++ ++ /* Check CET status now. */ ++ l->l_cet = lc_none; ++ + /* Check for invalid property. */ + if (note->n_descsz < 8 + || (note->n_descsz % sizeof (ElfW(Addr))) != 0) +- break; ++ return; + + /* Start and end of property array. */ + unsigned char *ptr = (unsigned char *) (note + 1) + 4; +@@ -78,9 +93,15 @@ _dl_process_cet_property_note (struct link_map *l, + unsigned int type = *(unsigned int *) ptr; + unsigned int datasz = *(unsigned int *) (ptr + 4); + ++ /* Property type must be in ascending order. */ ++ if (type < last_type) ++ return; ++ + ptr += 8; + if ((ptr + datasz) > ptr_end) +- break; ++ return; ++ ++ last_type = type; + + if (type == GNU_PROPERTY_X86_FEATURE_1_AND) + { +@@ -89,14 +110,18 @@ _dl_process_cet_property_note (struct link_map *l, + we stop the search regardless if its size is correct + or not. There is no point to continue if this note + is ill-formed. */ +- if (datasz == 4) +- { +- unsigned int feature_1 = *(unsigned int *) ptr; +- if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT)) +- l->l_cet |= lc_ibt; +- if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) +- l->l_cet |= lc_shstk; +- } ++ if (datasz != 4) ++ return; ++ ++ feature_1 = *(unsigned int *) ptr; ++ ++ /* Keep searching for the next GNU property note ++ generated by the older linker. */ ++ break; ++ } ++ else if (type > GNU_PROPERTY_X86_FEATURE_1_AND) ++ { ++ /* Stop since property type is in ascending order. */ + return; + } + +@@ -112,6 +137,12 @@ _dl_process_cet_property_note (struct link_map *l, + + ELF_NOTE_NEXT_OFFSET (note->n_namesz, note->n_descsz, + align)); + } ++ ++ /* We get here only if there is one or no GNU property note. */ ++ if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_IBT)) ++ l->l_cet |= lc_ibt; ++ if ((feature_1 & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) ++ l->l_cet |= lc_shstk; + #endif + } + +diff --git a/sysdeps/x86/link_map.h b/sysdeps/x86/link_map.h +index ef1206a9d2396a6f..9367ed08896794a4 100644 +--- a/sysdeps/x86/link_map.h ++++ b/sysdeps/x86/link_map.h +@@ -19,8 +19,9 @@ + /* If this object is enabled with CET. */ + enum + { +- lc_none = 0, /* Not enabled with CET. */ +- lc_ibt = 1 << 0, /* Enabled with IBT. */ +- lc_shstk = 1 << 1, /* Enabled with STSHK. */ ++ lc_unknown = 0, /* Unknown CET status. */ ++ lc_none = 1 << 0, /* Not enabled with CET. */ ++ lc_ibt = 1 << 1, /* Enabled with IBT. */ ++ lc_shstk = 1 << 2, /* Enabled with STSHK. */ + lc_ibt_and_shstk = lc_ibt | lc_shstk /* Enabled with both. */ +- } l_cet:2; ++ } l_cet:3; diff --git a/glibc-rh1615781.patch b/glibc-rh1615781.patch new file mode 100755 index 0000000..a12ea17 --- /dev/null +++ b/glibc-rh1615781.patch @@ -0,0 +1,28 @@ +commit d05b05d1570ba3ae354a2f5a3cfeefb373b09979 +Author: Florian Weimer +Date: Mon Aug 13 14:28:07 2018 +0200 + + error, error_at_line: Add missing va_end calls + + (cherry picked from commit b7b52b9dec337a08a89bc67638773be652eba332) + +diff --git a/misc/error.c b/misc/error.c +index b4e8b6c93886b737..03378e2f2aa6251e 100644 +--- a/misc/error.c ++++ b/misc/error.c +@@ -319,6 +319,7 @@ error (int status, int errnum, const char *message, ...) + + va_start (args, message); + error_tail (status, errnum, message, args); ++ va_end (args); + + #ifdef _LIBC + _IO_funlockfile (stderr); +@@ -390,6 +391,7 @@ error_at_line (int status, int errnum, const char *file_name, + + va_start (args, message); + error_tail (status, errnum, message, args); ++ va_end (args); + + #ifdef _LIBC + _IO_funlockfile (stderr); diff --git a/glibc-rh1615784.patch b/glibc-rh1615784.patch new file mode 100755 index 0000000..0c12c9c --- /dev/null +++ b/glibc-rh1615784.patch @@ -0,0 +1,35 @@ +commit bfcfa22589f2b4277a65e60c6b736b6bbfbd87d0 +Author: Florian Weimer +Date: Tue Aug 14 10:51:07 2018 +0200 + + nscd: Deallocate existing user names in file parser + + This avoids a theoretical memory leak (theoretical because it depends on + multiple server-user/stat-user directives in the configuration file). + + (cherry picked from commit 2d7acfac3ebf266dcbc82d0d6cc576f626953a03) + +diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c +index 265a02434dd26c29..7293b795b6bcf71e 100644 +--- a/nscd/nscd_conf.c ++++ b/nscd/nscd_conf.c +@@ -190,7 +190,10 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) + if (!arg1) + error (0, 0, _("Must specify user name for server-user option")); + else +- server_user = xstrdup (arg1); ++ { ++ free ((char *) server_user); ++ server_user = xstrdup (arg1); ++ } + } + else if (strcmp (entry, "stat-user") == 0) + { +@@ -198,6 +201,7 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) + error (0, 0, _("Must specify user name for stat-user option")); + else + { ++ free ((char *) stat_user); + stat_user = xstrdup (arg1); + + struct passwd *pw = getpwnam (stat_user); diff --git a/glibc-rh1615790.patch b/glibc-rh1615790.patch new file mode 100755 index 0000000..f0fbdc7 --- /dev/null +++ b/glibc-rh1615790.patch @@ -0,0 +1,306 @@ +commit 2f498f3d140ab5152bd784df2be7af7d9c5e63ed +Author: Florian Weimer +Date: Tue Aug 14 10:57:48 2018 +0200 + + nss_files: Fix file stream leak in aliases lookup [BZ #23521] + + In order to get a clean test case, it was necessary to fix partially + fixed bug 23522 as well. + + (cherry picked from commit e95c6f61920a0f9237cfb292fa44ad500e1df09b) + +diff --git a/nss/Makefile b/nss/Makefile +index 66fac7f5b8a4c0d8..5209fc0456dd6786 100644 +--- a/nss/Makefile ++++ b/nss/Makefile +@@ -65,6 +65,7 @@ ifeq (yes,$(build-shared)) + tests += tst-nss-files-hosts-erange + tests += tst-nss-files-hosts-multi + tests += tst-nss-files-hosts-getent ++tests += tst-nss-files-alias-leak + endif + + # If we have a thread library then we can test cancellation against +@@ -171,3 +172,5 @@ endif + $(objpfx)tst-nss-files-hosts-erange: $(libdl) + $(objpfx)tst-nss-files-hosts-multi: $(libdl) + $(objpfx)tst-nss-files-hosts-getent: $(libdl) ++$(objpfx)tst-nss-files-alias-leak: $(libdl) ++$(objpfx)tst-nss-files-alias-leak.out: $(objpfx)/libnss_files.so +diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c +index cfd34b66b921bbff..35b0bfc5d2479ab6 100644 +--- a/nss/nss_files/files-alias.c ++++ b/nss/nss_files/files-alias.c +@@ -221,6 +221,13 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, + { + while (! feof_unlocked (listfile)) + { ++ if (room_left < 2) ++ { ++ free (old_line); ++ fclose (listfile); ++ goto no_more_room; ++ } ++ + first_unused[room_left - 1] = '\xff'; + line = fgets_unlocked (first_unused, room_left, + listfile); +@@ -229,6 +236,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, + if (first_unused[room_left - 1] != '\xff') + { + free (old_line); ++ fclose (listfile); + goto no_more_room; + } + +@@ -256,6 +264,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, + + __alignof__ (char *))) + { + free (old_line); ++ fclose (listfile); + goto no_more_room; + } + room_left -= ((first_unused - cp) +diff --git a/nss/tst-nss-files-alias-leak.c b/nss/tst-nss-files-alias-leak.c +new file mode 100644 +index 0000000000000000..26d38e2dba1ddaf3 +--- /dev/null ++++ b/nss/tst-nss-files-alias-leak.c +@@ -0,0 +1,237 @@ ++/* Check for file descriptor leak in alias :include: processing (bug 23521). ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static struct support_chroot *chroot_env; ++ ++/* Number of the aliases for the "many" user. This must be large ++ enough to trigger reallocation for the pointer array, but result in ++ answers below the maximum size tried in do_test. */ ++enum { many_aliases = 30 }; ++ ++static void ++prepare (int argc, char **argv) ++{ ++ chroot_env = support_chroot_create ++ ((struct support_chroot_configuration) { } ); ++ ++ char *path = xasprintf ("%s/etc/aliases", chroot_env->path_chroot); ++ add_temp_file (path); ++ support_write_file_string ++ (path, ++ "user1: :include:/etc/aliases.user1\n" ++ "user2: :include:/etc/aliases.user2\n" ++ "comment: comment1, :include:/etc/aliases.comment\n" ++ "many: :include:/etc/aliases.many\n"); ++ free (path); ++ ++ path = xasprintf ("%s/etc/aliases.user1", chroot_env->path_chroot); ++ add_temp_file (path); ++ support_write_file_string (path, "alias1\n"); ++ free (path); ++ ++ path = xasprintf ("%s/etc/aliases.user2", chroot_env->path_chroot); ++ add_temp_file (path); ++ support_write_file_string (path, "alias1a, alias2\n"); ++ free (path); ++ ++ path = xasprintf ("%s/etc/aliases.comment", chroot_env->path_chroot); ++ add_temp_file (path); ++ support_write_file_string ++ (path, ++ /* The line must be longer than the line with the :include: ++ directive in /etc/aliases. */ ++ "# Long line. ##############################################\n" ++ "comment2\n"); ++ free (path); ++ ++ path = xasprintf ("%s/etc/aliases.many", chroot_env->path_chroot); ++ add_temp_file (path); ++ FILE *fp = xfopen (path, "w"); ++ for (int i = 0; i < many_aliases; ++i) ++ fprintf (fp, "a%d\n", i); ++ TEST_VERIFY_EXIT (! ferror (fp)); ++ xfclose (fp); ++ free (path); ++} ++ ++/* The names of the users to test. */ ++static const char *users[] = { "user1", "user2", "comment", "many" }; ++ ++static void ++check_aliases (int id, const struct aliasent *e) ++{ ++ TEST_VERIFY_EXIT (id >= 0 || id < array_length (users)); ++ const char *name = users[id]; ++ TEST_COMPARE_BLOB (e->alias_name, strlen (e->alias_name), ++ name, strlen (name)); ++ ++ switch (id) ++ { ++ case 0: ++ TEST_COMPARE (e->alias_members_len, 1); ++ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]), ++ "alias1", strlen ("alias1")); ++ break; ++ ++ case 1: ++ TEST_COMPARE (e->alias_members_len, 2); ++ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]), ++ "alias1a", strlen ("alias1a")); ++ TEST_COMPARE_BLOB (e->alias_members[1], strlen (e->alias_members[1]), ++ "alias2", strlen ("alias2")); ++ break; ++ ++ case 2: ++ TEST_COMPARE (e->alias_members_len, 2); ++ TEST_COMPARE_BLOB (e->alias_members[0], strlen (e->alias_members[0]), ++ "comment1", strlen ("comment1")); ++ TEST_COMPARE_BLOB (e->alias_members[1], strlen (e->alias_members[1]), ++ "comment2", strlen ("comment2")); ++ break; ++ ++ case 3: ++ TEST_COMPARE (e->alias_members_len, many_aliases); ++ for (int i = 0; i < e->alias_members_len; ++i) ++ { ++ char alias[30]; ++ int len = snprintf (alias, sizeof (alias), "a%d", i); ++ TEST_VERIFY_EXIT (len > 0); ++ TEST_COMPARE_BLOB (e->alias_members[i], strlen (e->alias_members[i]), ++ alias, len); ++ } ++ break; ++ } ++} ++ ++static int ++do_test (void) ++{ ++ /* Make sure we don't try to load the module in the chroot. */ ++ if (dlopen (LIBNSS_FILES_SO, RTLD_NOW) == NULL) ++ FAIL_EXIT1 ("could not load " LIBNSS_FILES_SO ": %s", dlerror ()); ++ ++ /* Some of these descriptors will become unavailable if there is a ++ file descriptor leak. 10 is chosen somewhat arbitrarily. The ++ array must be longer than the number of files opened by nss_files ++ at the same time (currently that number is 2). */ ++ int next_descriptors[10]; ++ for (size_t i = 0; i < array_length (next_descriptors); ++i) ++ { ++ next_descriptors[i] = dup (0); ++ TEST_VERIFY_EXIT (next_descriptors[i] > 0); ++ } ++ for (size_t i = 0; i < array_length (next_descriptors); ++i) ++ xclose (next_descriptors[i]); ++ ++ support_become_root (); ++ if (!support_can_chroot ()) ++ return EXIT_UNSUPPORTED; ++ ++ __nss_configure_lookup ("aliases", "files"); ++ ++ xchroot (chroot_env->path_chroot); ++ ++ /* Attempt various buffer sizes. If the operation succeeds, we ++ expect correct data. */ ++ for (int id = 0; id < array_length (users); ++id) ++ { ++ bool found = false; ++ for (size_t size = 1; size <= 1000; ++size) ++ { ++ void *buffer = malloc (size); ++ struct aliasent result; ++ struct aliasent *res; ++ errno = EINVAL; ++ int ret = getaliasbyname_r (users[id], &result, buffer, size, &res); ++ if (ret == 0) ++ { ++ if (res != NULL) ++ { ++ found = true; ++ check_aliases (id, res); ++ } ++ else ++ { ++ support_record_failure (); ++ printf ("error: failed lookup for user \"%s\", size %zu\n", ++ users[id], size); ++ } ++ } ++ else if (ret != ERANGE) ++ { ++ support_record_failure (); ++ printf ("error: invalid return code %d (user \%s\", size %zu)\n", ++ ret, users[id], size); ++ } ++ free (buffer); ++ ++ /* Make sure that we did not have a file descriptor leak. */ ++ for (size_t i = 0; i < array_length (next_descriptors); ++i) ++ { ++ int new_fd = dup (0); ++ if (new_fd != next_descriptors[i]) ++ { ++ support_record_failure (); ++ printf ("error: descriptor %d at index %zu leaked" ++ " (user \"%s\", size %zu)\n", ++ next_descriptors[i], i, users[id], size); ++ ++ /* Close unexpected descriptor, the leak probing ++ descriptors, and the leaked descriptor ++ next_descriptors[i]. */ ++ xclose (new_fd); ++ for (size_t j = 0; j <= i; ++j) ++ xclose (next_descriptors[j]); ++ goto next_size; ++ } ++ } ++ for (size_t i = 0; i < array_length (next_descriptors); ++i) ++ xclose (next_descriptors[i]); ++ ++ next_size: ++ ; ++ } ++ if (!found) ++ { ++ support_record_failure (); ++ printf ("error: user %s not found\n", users[id]); ++ } ++ } ++ ++ support_chroot_free (chroot_env); ++ return 0; ++} ++ ++#define PREPARE prepare ++#include diff --git a/glibc-rh1622675.patch b/glibc-rh1622675.patch new file mode 100755 index 0000000..ba473cd --- /dev/null +++ b/glibc-rh1622675.patch @@ -0,0 +1,27 @@ +commit aa8a3e4cdef20c50cb20f008864fff05cbfbdf29 +Author: Martin Kuchta +Date: Mon Aug 27 18:54:46 2018 +0200 + + pthread_cond_broadcast: Fix waiters-after-spinning case [BZ #23538] + + (cherry picked from commit 99ea93ca31795469d2a1f1570f17a5c39c2eb7e2) + +diff --git a/nptl/pthread_cond_common.c b/nptl/pthread_cond_common.c +index 8e425eb01eceabec..479e54febb417675 100644 +--- a/nptl/pthread_cond_common.c ++++ b/nptl/pthread_cond_common.c +@@ -405,8 +405,12 @@ __condvar_quiesce_and_switch_g1 (pthread_cond_t *cond, uint64_t wseq, + { + /* There is still a waiter after spinning. Set the wake-request + flag and block. Relaxed MO is fine because this is just about +- this futex word. */ +- r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1); ++ this futex word. ++ ++ Update r to include the set wake-request flag so that the upcoming ++ futex_wait only blocks if the flag is still set (otherwise, we'd ++ violate the basic client-side futex protocol). */ ++ r = atomic_fetch_or_relaxed (cond->__data.__g_refs + g1, 1) | 1; + + if ((r >> 1) > 0) + futex_wait_simple (cond->__data.__g_refs + g1, r, private); diff --git a/glibc-rh1622678-1.patch b/glibc-rh1622678-1.patch new file mode 100755 index 0000000..4d94590 --- /dev/null +++ b/glibc-rh1622678-1.patch @@ -0,0 +1,41 @@ +commit 58559f14437d2aa71753a29fed435efa06aa4576 +Author: Paul Eggert +Date: Tue Aug 28 21:54:28 2018 +0200 + + regex: fix uninitialized memory access + + I introduced this bug into gnulib in commit + 8335a4d6c7b4448cd0bcb6d0bebf1d456bcfdb17 dated 2006-04-10; + eventually it was merged into glibc. The bug was found by + project-repo and reported here: + https://lists.gnu.org/r/sed-devel/2018-08/msg00017.html + Diagnosis and draft fix reported by Assaf Gordon here: + https://lists.gnu.org/r/bug-gnulib/2018-08/msg00071.html + https://lists.gnu.org/r/bug-gnulib/2018-08/msg00142.html + * posix/regex_internal.c (build_wcs_upper_buffer): + Fix bug when mbrtowc returns 0. + + (cherry picked from commit bc680b336971305cb39896b30d72dc7101b62242) + +diff --git a/posix/regex_internal.c b/posix/regex_internal.c +index 7f0083b918de6530..b10588f1ccbb1992 100644 +--- a/posix/regex_internal.c ++++ b/posix/regex_internal.c +@@ -317,7 +317,7 @@ build_wcs_upper_buffer (re_string_t *pstr) + mbclen = __mbrtowc (&wc, + ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx + + byte_idx), remain_len, &pstr->cur_state); +- if (BE (mbclen < (size_t) -2, 1)) ++ if (BE (0 < mbclen && mbclen < (size_t) -2, 1)) + { + wchar_t wcu = __towupper (wc); + if (wcu != wc) +@@ -386,7 +386,7 @@ build_wcs_upper_buffer (re_string_t *pstr) + else + p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; + mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); +- if (BE (mbclen < (size_t) -2, 1)) ++ if (BE (0 < mbclen && mbclen < (size_t) -2, 1)) + { + wchar_t wcu = __towupper (wc); + if (wcu != wc) diff --git a/glibc-rh1622678-2.patch b/glibc-rh1622678-2.patch new file mode 100755 index 0000000..ecf37f7 --- /dev/null +++ b/glibc-rh1622678-2.patch @@ -0,0 +1,226 @@ +commit 0b79004569e5ce1669136b8c41564c3809730f15 +Author: Florian Weimer +Date: Tue Aug 28 12:57:46 2018 +0200 + + regex: Add test tst-regcomp-truncated [BZ #23578] + + (cherry picked from commit 761404b74d9853ce1608195e24f25b78a910591a) + +diff --git a/posix/Makefile b/posix/Makefile +index 00c62841a282f15a..83162123f9c927a0 100644 +--- a/posix/Makefile ++++ b/posix/Makefile +@@ -96,7 +96,7 @@ tests := test-errno tstgetopt testfnm runtests runptests \ + tst-posix_fadvise tst-posix_fadvise64 \ + tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \ + tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \ +- bug-regex38 ++ bug-regex38 tst-regcomp-truncated + tests-internal := bug-regex5 bug-regex20 bug-regex33 \ + tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 \ + tst-glob_lstat_compat tst-spawn4-compat +@@ -194,6 +194,7 @@ $(objpfx)tst-regex2.out: $(gen-locales) + $(objpfx)tst-regexloc.out: $(gen-locales) + $(objpfx)tst-rxspencer.out: $(gen-locales) + $(objpfx)tst-rxspencer-no-utf8.out: $(gen-locales) ++$(objpfx)tst-regcomp-truncated.out: $(gen-locales) + endif + + # If we will use the generic uname implementation, we must figure out what +diff --git a/posix/tst-regcomp-truncated.c b/posix/tst-regcomp-truncated.c +new file mode 100644 +index 0000000000000000..a4a1581bbc2b39eb +--- /dev/null ++++ b/posix/tst-regcomp-truncated.c +@@ -0,0 +1,191 @@ ++/* Test compilation of truncated regular expressions. ++ Copyright (C) 2018 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 ++ . */ ++ ++/* This test constructs various patterns in an attempt to trigger ++ over-reading the regular expression compiler, such as bug ++ 23578. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Locales to test. */ ++static const char locales[][17] = ++ { ++ "C", ++ "en_US.UTF-8", ++ "de_DE.ISO-8859-1", ++ }; ++ ++/* Syntax options. Will be combined with other flags. */ ++static const reg_syntax_t syntaxes[] = ++ { ++ RE_SYNTAX_EMACS, ++ RE_SYNTAX_AWK, ++ RE_SYNTAX_GNU_AWK, ++ RE_SYNTAX_POSIX_AWK, ++ RE_SYNTAX_GREP, ++ RE_SYNTAX_EGREP, ++ RE_SYNTAX_POSIX_EGREP, ++ RE_SYNTAX_POSIX_BASIC, ++ RE_SYNTAX_POSIX_EXTENDED, ++ RE_SYNTAX_POSIX_MINIMAL_EXTENDED, ++ }; ++ ++/* Trailing characters placed after the initial character. */ ++static const char trailing_strings[][4] = ++ { ++ "", ++ "[", ++ "\\", ++ "[\\", ++ "(", ++ "(\\", ++ "\\(", ++ }; ++ ++static int ++do_test (void) ++{ ++ /* Staging buffer for the constructed regular expression. */ ++ char buffer[16]; ++ ++ /* Allocation used to detect over-reading by the regular expression ++ compiler. */ ++ struct support_next_to_fault ntf ++ = support_next_to_fault_allocate (sizeof (buffer)); ++ ++ /* Arbitrary Unicode codepoint at which we stop generating ++ characters. We do not probe the whole range because that would ++ take too long due to combinatorical exploision as the result of ++ combination with other flags. */ ++ static const wchar_t last_character = 0xfff; ++ ++ for (size_t locale_idx = 0; locale_idx < array_length (locales); ++ ++ locale_idx) ++ { ++ if (setlocale (LC_ALL, locales[locale_idx]) == NULL) ++ { ++ support_record_failure (); ++ printf ("error: setlocale (\"%s\"): %m", locales[locale_idx]); ++ continue; ++ } ++ if (test_verbose > 0) ++ printf ("info: testing locale \"%s\"\n", locales[locale_idx]); ++ ++ for (wchar_t wc = 0; wc <= last_character; ++wc) ++ { ++ char *after_wc; ++ if (wc == 0) ++ { ++ /* wcrtomb treats L'\0' in a special way. */ ++ *buffer = '\0'; ++ after_wc = &buffer[1]; ++ } ++ else ++ { ++ mbstate_t ps = { }; ++ size_t ret = wcrtomb (buffer, wc, &ps); ++ if (ret == (size_t) -1) ++ { ++ /* EILSEQ means that the target character set ++ cannot encode the character. */ ++ if (errno != EILSEQ) ++ { ++ support_record_failure (); ++ printf ("error: wcrtomb (0x%x) failed: %m\n", ++ (unsigned) wc); ++ } ++ continue; ++ } ++ TEST_VERIFY_EXIT (ret != 0); ++ after_wc = &buffer[ret]; ++ } ++ ++ for (size_t trailing_idx = 0; ++ trailing_idx < array_length (trailing_strings); ++ ++trailing_idx) ++ { ++ char *after_trailing ++ = stpcpy (after_wc, trailing_strings[trailing_idx]); ++ ++ for (int do_nul = 0; do_nul < 2; ++do_nul) ++ { ++ char *after_nul; ++ if (do_nul) ++ { ++ *after_trailing = '\0'; ++ after_nul = &after_trailing[1]; ++ } ++ else ++ after_nul = after_trailing; ++ ++ size_t length = after_nul - buffer; ++ ++ /* Make sure that the faulting region starts ++ after the used portion of the buffer. */ ++ char *ntf_start = ntf.buffer + sizeof (buffer) - length; ++ memcpy (ntf_start, buffer, length); ++ ++ for (const reg_syntax_t *psyntax = syntaxes; ++ psyntax < array_end (syntaxes); ++psyntax) ++ for (int do_icase = 0; do_icase < 2; ++do_icase) ++ { ++ re_syntax_options = *psyntax; ++ if (do_icase) ++ re_syntax_options |= RE_ICASE; ++ ++ regex_t reg; ++ memset (®, 0, sizeof (reg)); ++ const char *msg = re_compile_pattern ++ (ntf_start, length, ®); ++ if (msg != NULL) ++ { ++ if (test_verbose > 0) ++ { ++ char *quoted = support_quote_blob ++ (buffer, length); ++ printf ("info: compilation failed for pattern" ++ " \"%s\", syntax 0x%lx: %s\n", ++ quoted, re_syntax_options, msg); ++ free (quoted); ++ } ++ } ++ else ++ regfree (®); ++ } ++ } ++ } ++ } ++ } ++ ++ support_next_to_fault_free (&ntf); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1623536-2.patch b/glibc-rh1623536-2.patch new file mode 100755 index 0000000..63d141b --- /dev/null +++ b/glibc-rh1623536-2.patch @@ -0,0 +1,34 @@ +commit 3a67c72c1512f778304a5644dea2fcf5bdece274 +Author: Andreas Schwab +Date: Thu Sep 27 12:37:06 2018 +0200 + + Fix stack overflow in tst-setcontext9 (bug 23717) + + The function f1a, executed on a stack of size 32k, allocates an object of + size 32k on the stack. Make the stack variables static to reduce + excessive stack usage. + + (cherry picked from commit f841c97e515a1673485a2b12b3c280073d737890) + +diff --git a/stdlib/tst-setcontext9.c b/stdlib/tst-setcontext9.c +index db8355766ca7b906..009928235dd5987e 100644 +--- a/stdlib/tst-setcontext9.c ++++ b/stdlib/tst-setcontext9.c +@@ -58,7 +58,7 @@ f1b (void) + static void + f1a (void) + { +- char st2[32768]; ++ static char st2[32768]; + puts ("start f1a"); + if (getcontext (&ctx[2]) != 0) + { +@@ -93,7 +93,7 @@ f1a (void) + static int + do_test (void) + { +- char st1[32768]; ++ static char st1[32768]; + puts ("making contexts"); + if (getcontext (&ctx[0]) != 0) + { diff --git a/glibc-rh1623536.patch b/glibc-rh1623536.patch new file mode 100755 index 0000000..8352b3d --- /dev/null +++ b/glibc-rh1623536.patch @@ -0,0 +1,100 @@ +commit a55e109709af55e6ed67d3f9536cac5d929c982e +Author: Carlos O'Donell +Date: Wed Sep 5 01:16:42 2018 -0400 + + Fix tst-setcontext9 for optimized small stacks. + + If the compiler reduces the stack usage in function f1 before calling + into function f2, then when we swapcontext back to f1 and continue + execution we may overwrite registers that were spilled to the stack + while f2 was executing. Later when we return to f2 the corrupt + registers will be reloaded from the stack and the test will crash. This + was most commonly observed on i686 with __x86.get_pc_thunk.dx and + needing to save and restore $edx. Overall i686 has few registers and + the spilling to the stack is bound to happen, therefore the solution to + making this test robust is to split function f1 into two parts f1a and + f1b, and allocate f1b it's own stack such that subsequent execution does + not overwrite the stack in use by function f2. + + Tested on i686 and x86_64. + + Signed-off-by: Carlos O'Donell + (cherry picked from commit 791b350dc725545e3f9b5db0f97ebdbc60c9735f) + +diff --git a/stdlib/tst-setcontext9.c b/stdlib/tst-setcontext9.c +index 4636ce9030fa38a7..db8355766ca7b906 100644 +--- a/stdlib/tst-setcontext9.c ++++ b/stdlib/tst-setcontext9.c +@@ -41,26 +41,55 @@ f2 (void) + } + + static void +-f1 (void) ++f1b (void) + { +- puts ("start f1"); +- if (getcontext (&ctx[2]) != 0) +- { +- printf ("%s: getcontext: %m\n", __FUNCTION__); +- exit (EXIT_FAILURE); +- } + if (done) + { +- puts ("set context in f1"); ++ puts ("set context in f1b"); + if (setcontext (&ctx[3]) != 0) + { + printf ("%s: setcontext: %m\n", __FUNCTION__); + exit (EXIT_FAILURE); + } + } ++ exit (EXIT_FAILURE); ++} ++ ++static void ++f1a (void) ++{ ++ char st2[32768]; ++ puts ("start f1a"); ++ if (getcontext (&ctx[2]) != 0) ++ { ++ printf ("%s: getcontext: %m\n", __FUNCTION__); ++ exit (EXIT_FAILURE); ++ } ++ ctx[2].uc_stack.ss_sp = st2; ++ ctx[2].uc_stack.ss_size = sizeof st2; ++ ctx[2].uc_link = &ctx[0]; ++ makecontext (&ctx[2], (void (*) (void)) f1b, 0); + f2 (); + } + ++/* The execution path through the test looks like this: ++ do_test (call) ++ -> "making contexts" ++ -> "swap contexts" ++ f1a (via swapcontext to ctx[1], with alternate stack) ++ -> "start f1a" ++ f2 (call) ++ -> "swap contexts in f2" ++ f1b (via swapcontext to ctx[2], with alternate stack) ++ -> "set context in f1b" ++ do_test (via setcontext to ctx[3], main stack) ++ -> "setcontext" ++ f2 (via setcontext to ctx[4], with alternate stack) ++ -> "end f2" ++ ++ We must use an alternate stack for f1b, because if we don't then the ++ result of executing an earlier caller may overwrite registers ++ spilled to the stack in f2. */ + static int + do_test (void) + { +@@ -79,7 +108,7 @@ do_test (void) + ctx[1].uc_stack.ss_sp = st1; + ctx[1].uc_stack.ss_size = sizeof st1; + ctx[1].uc_link = &ctx[0]; +- makecontext (&ctx[1], (void (*) (void)) f1, 0); ++ makecontext (&ctx[1], (void (*) (void)) f1a, 0); + puts ("swap contexts"); + if (swapcontext (&ctx[3], &ctx[1]) != 0) + { diff --git a/glibc-rh1623537.patch b/glibc-rh1623537.patch new file mode 100755 index 0000000..5165785 --- /dev/null +++ b/glibc-rh1623537.patch @@ -0,0 +1,61 @@ +commit b297581acb66f80b513996c1580158b0fb12d469 +Author: Tulio Magno Quites Machado Filho +Date: Mon Jan 14 17:54:44 2019 -0200 + + Add XFAIL_ROUNDING_IBM128_LIBGCC to more fma() tests + + Ignore 16 errors in math/test-ldouble-fma and 4 errors in + math/test-ildouble-fma when IBM 128-bit long double used. + These errors are caused by spurious overflows from libgcc. + + * math/libm-test-fma.inc (fma_test_data): Set + XFAIL_ROUNDING_IBM128_LIBGCC to more tests. + + Signed-off-by: Tulio Magno Quites Machado Filho + (cherry picked from commit ecdacd34a2ac3b6d5a529ff218b29261d9d98a7a) + +diff --git a/math/libm-test-fma.inc b/math/libm-test-fma.inc +index 5b29fb820194e055..a7ee40992420c1ab 100644 +--- a/math/libm-test-fma.inc ++++ b/math/libm-test-fma.inc +@@ -119,32 +119,32 @@ static const struct test_fff_f_data fma_test_data[] = + TEST_fff_f (fma, plus_infty, plus_infty, -min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, plus_infty, min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, plus_infty, -min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, plus_infty, plus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, plus_infty, plus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), ++ TEST_fff_f (fma, plus_infty, plus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), ++ TEST_fff_f (fma, plus_infty, plus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), + TEST_fff_f (fma, plus_infty, minus_infty, plus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, minus_infty, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, minus_infty, min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, minus_infty, -min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, minus_infty, min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, plus_infty, minus_infty, -min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, plus_infty, minus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, plus_infty, minus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), ++ TEST_fff_f (fma, plus_infty, minus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), ++ TEST_fff_f (fma, plus_infty, minus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), + TEST_fff_f (fma, minus_infty, plus_infty, plus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, plus_infty, minus_zero, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, plus_infty, min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, plus_infty, -min_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, plus_infty, min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, plus_infty, -min_subnorm_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, minus_infty, plus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, minus_infty, plus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), ++ TEST_fff_f (fma, minus_infty, plus_infty, max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), ++ TEST_fff_f (fma, minus_infty, plus_infty, -max_value, minus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), + TEST_fff_f (fma, minus_infty, minus_infty, plus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, minus_infty, minus_zero, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, minus_infty, min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, minus_infty, -min_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, minus_infty, min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), + TEST_fff_f (fma, minus_infty, minus_infty, -min_subnorm_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, minus_infty, minus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), +- TEST_fff_f (fma, minus_infty, minus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED), ++ TEST_fff_f (fma, minus_infty, minus_infty, max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), ++ TEST_fff_f (fma, minus_infty, minus_infty, -max_value, plus_infty, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED|XFAIL_ROUNDING_IBM128_LIBGCC), + + AUTO_TESTS_fff_f (fma), + }; diff --git a/glibc-rh1631293-1.patch b/glibc-rh1631293-1.patch new file mode 100755 index 0000000..fc2a74e --- /dev/null +++ b/glibc-rh1631293-1.patch @@ -0,0 +1,29 @@ +commit e7d22db29cfdd2f1fb97a70a76fa53d151569945 +Author: Mingli Yu +Date: Thu Sep 20 12:41:13 2018 +0200 + + Linux gethostid: Check for NULL value from gethostbyname_r [BZ #23679] + + A NULL value can happen with certain gethostbyname_r failures. + + (cherry picked from commit 1214ba06e6771acb953a190091b0f6055c64fd25) + +diff --git a/sysdeps/unix/sysv/linux/gethostid.c b/sysdeps/unix/sysv/linux/gethostid.c +index 2e20f034dc134cc7..ee0190e7f945db1f 100644 +--- a/sysdeps/unix/sysv/linux/gethostid.c ++++ b/sysdeps/unix/sysv/linux/gethostid.c +@@ -102,12 +102,12 @@ gethostid (void) + { + int ret = __gethostbyname_r (hostname, &hostbuf, + tmpbuf.data, tmpbuf.length, &hp, &herr); +- if (ret == 0) ++ if (ret == 0 && hp != NULL) + break; + else + { + /* Enlarge the buffer on ERANGE. */ +- if (herr == NETDB_INTERNAL && errno == ERANGE) ++ if (ret != 0 && herr == NETDB_INTERNAL && errno == ERANGE) + { + if (!scratch_buffer_grow (&tmpbuf)) + return 0; diff --git a/glibc-rh1631293-2.patch b/glibc-rh1631293-2.patch new file mode 100755 index 0000000..4eef814 --- /dev/null +++ b/glibc-rh1631293-2.patch @@ -0,0 +1,146 @@ +commit 307d04334d516bb180f484a2b283f97310bfee66 +Author: Florian Weimer +Date: Thu Sep 20 12:03:01 2018 +0200 + + misc: New test misc/tst-gethostid + + The empty /etc/hosts file used to trigger bug 23679. + + (cherry picked from commit db9a8ad4ff3fc58e3773a9a4d0cabe3c1bc9c94c) + +diff --git a/misc/Makefile b/misc/Makefile +index b7be2bc19a6f7ed5..c9f81515ac9aef2c 100644 +--- a/misc/Makefile ++++ b/misc/Makefile +@@ -86,6 +86,11 @@ tests := tst-dirname tst-tsearch tst-fdset tst-efgcvt tst-mntent tst-hsearch \ + tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \ + tst-preadvwritev2 tst-preadvwritev64v2 + ++# Tests which need libdl. ++ifeq (yes,$(build-shared)) ++tests += tst-gethostid ++endif ++ + tests-internal := tst-atomic tst-atomic-long tst-allocate_once + tests-static := tst-empty + +@@ -145,3 +150,5 @@ tst-allocate_once-ENV = MALLOC_TRACE=$(objpfx)tst-allocate_once.mtrace + $(objpfx)tst-allocate_once-mem.out: $(objpfx)tst-allocate_once.out + $(common-objpfx)malloc/mtrace $(objpfx)tst-allocate_once.mtrace > $@; \ + $(evaluate-test) ++ ++$(objpfx)tst-gethostid: $(libdl) +diff --git a/misc/tst-gethostid.c b/misc/tst-gethostid.c +new file mode 100644 +index 0000000000000000..1490aaf3f517ff1d +--- /dev/null ++++ b/misc/tst-gethostid.c +@@ -0,0 +1,108 @@ ++/* Basic test for gethostid. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Initial test is run outside a chroot, to increase the likelihood of ++ success. */ ++static void ++outside_chroot (void *closure) ++{ ++ long id = gethostid (); ++ printf ("info: host ID outside chroot: 0x%lx\n", id); ++} ++ ++/* The same, but this time perform a chroot operation. */ ++static void ++in_chroot (void *closure) ++{ ++ const char *chroot_path = closure; ++ xchroot (chroot_path); ++ long id = gethostid (); ++ printf ("info: host ID in chroot: 0x%lx\n", id); ++} ++ ++static int ++do_test (void) ++{ ++ support_isolate_in_subprocess (outside_chroot, NULL); ++ ++ /* Now run the test inside a chroot. */ ++ support_become_root (); ++ if (!support_can_chroot ()) ++ /* Cannot perform further tests. */ ++ return 0; ++ ++ /* Only use nss_files. */ ++ __nss_configure_lookup ("hosts", "files"); ++ ++ /* Load the DSO outside of the chroot. */ ++ xdlopen (LIBNSS_FILES_SO, RTLD_LAZY); ++ ++ char *chroot_dir = support_create_temp_directory ("tst-gethostid-"); ++ support_isolate_in_subprocess (in_chroot, chroot_dir); ++ ++ /* Tests with /etc/hosts in the chroot. */ ++ { ++ char *path = xasprintf ("%s/etc", chroot_dir); ++ add_temp_file (path); ++ xmkdir (path, 0777); ++ free (path); ++ path = xasprintf ("%s/etc/hosts", chroot_dir); ++ add_temp_file (path); ++ ++ FILE *fp = xfopen (path, "w"); ++ xfclose (fp); ++ printf ("info: chroot test with an empty /etc/hosts file\n"); ++ support_isolate_in_subprocess (in_chroot, chroot_dir); ++ ++ char hostname[1024]; ++ int ret = gethostname (hostname, sizeof (hostname)); ++ if (ret < 0) ++ printf ("warning: invalid result from gethostname: %d\n", ret); ++ else if (strlen (hostname) == 0) ++ puts ("warning: gethostname returned empty string"); ++ else ++ { ++ printf ("info: chroot test with IPv6 address in /etc/hosts for: %s\n", ++ hostname); ++ fp = xfopen (path, "w"); ++ /* Use an IPv6 address to induce another lookup failure. */ ++ fprintf (fp, "2001:db8::1 %s\n", hostname); ++ xfclose (fp); ++ support_isolate_in_subprocess (in_chroot, chroot_dir); ++ } ++ free (path); ++ } ++ free (chroot_dir); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1631722.patch b/glibc-rh1631722.patch new file mode 100755 index 0000000..30d9ea5 --- /dev/null +++ b/glibc-rh1631722.patch @@ -0,0 +1,108 @@ +commit 0ef2f4400c06927af34c515555f68840a70ba409 +Author: Wilco Dijkstra +Date: Wed Sep 19 16:50:18 2018 +0100 + + Fix strstr bug with huge needles (bug 23637) + + The generic strstr in GLIBC 2.28 fails to match huge needles. The optimized + AVAILABLE macro reads ahead a large fixed amount to reduce the overhead of + repeatedly checking for the end of the string. However if the needle length + is larger than this, two_way_long_needle may confuse this as meaning the end + of the string and return NULL. This is fixed by adding the needle length to + the amount to read ahead. + + [BZ #23637] + * string/test-strstr.c (pr23637): New function. + (test_main): Add tests with longer needles. + * string/strcasestr.c (AVAILABLE): Fix readahead distance. + * string/strstr.c (AVAILABLE): Likewise. + + (cherry picked from commit 83a552b0bb9fc2a5e80a0ab3723c0a80ce1db9f2) + +diff --git a/string/strcasestr.c b/string/strcasestr.c +index 5909fe3cdba88e47..421764bd1b0ff22e 100644 +--- a/string/strcasestr.c ++++ b/string/strcasestr.c +@@ -37,8 +37,9 @@ + /* Two-Way algorithm. */ + #define RETURN_TYPE char * + #define AVAILABLE(h, h_l, j, n_l) \ +- (((j) + (n_l) <= (h_l)) || ((h_l) += __strnlen ((void*)((h) + (h_l)), 512), \ +- (j) + (n_l) <= (h_l))) ++ (((j) + (n_l) <= (h_l)) \ ++ || ((h_l) += __strnlen ((void*)((h) + (h_l)), (n_l) + 512), \ ++ (j) + (n_l) <= (h_l))) + #define CHECK_EOL (1) + #define RET0_IF_0(a) if (!a) goto ret0 + #define CANON_ELEMENT(c) TOLOWER (c) +diff --git a/string/strstr.c b/string/strstr.c +index 265e9f310ce507ce..79ebcc75329d0b17 100644 +--- a/string/strstr.c ++++ b/string/strstr.c +@@ -33,8 +33,9 @@ + + #define RETURN_TYPE char * + #define AVAILABLE(h, h_l, j, n_l) \ +- (((j) + (n_l) <= (h_l)) || ((h_l) += __strnlen ((void*)((h) + (h_l)), 512), \ +- (j) + (n_l) <= (h_l))) ++ (((j) + (n_l) <= (h_l)) \ ++ || ((h_l) += __strnlen ((void*)((h) + (h_l)), (n_l) + 512), \ ++ (j) + (n_l) <= (h_l))) + #define CHECK_EOL (1) + #define RET0_IF_0(a) if (!a) goto ret0 + #define FASTSEARCH(S,C,N) (void*) strchr ((void*)(S), (C)) +diff --git a/string/test-strstr.c b/string/test-strstr.c +index 8d99716ff39cc2c2..5861b01b73e4c315 100644 +--- a/string/test-strstr.c ++++ b/string/test-strstr.c +@@ -151,6 +151,32 @@ check2 (void) + } + } + ++#define N 1024 ++ ++static void ++pr23637 (void) ++{ ++ char *h = (char*) buf1; ++ char *n = (char*) buf2; ++ ++ for (int i = 0; i < N; i++) ++ { ++ n[i] = 'x'; ++ h[i] = ' '; ++ h[i + N] = 'x'; ++ } ++ ++ n[N] = '\0'; ++ h[N * 2] = '\0'; ++ ++ /* Ensure we don't match at the first 'x'. */ ++ h[0] = 'x'; ++ ++ char *exp_result = stupid_strstr (h, n); ++ FOR_EACH_IMPL (impl, 0) ++ check_result (impl, h, n, exp_result); ++} ++ + static int + test_main (void) + { +@@ -158,6 +184,7 @@ test_main (void) + + check1 (); + check2 (); ++ pr23637 (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) +@@ -202,6 +229,9 @@ test_main (void) + do_test (15, 9, hlen, klen, 1); + do_test (15, 15, hlen, klen, 0); + do_test (15, 15, hlen, klen, 1); ++ ++ do_test (15, 15, hlen + klen * 4, klen * 4, 0); ++ do_test (15, 15, hlen + klen * 4, klen * 4, 1); + } + + do_test (0, 0, page_size - 1, 16, 0); diff --git a/glibc-rh1631730.patch b/glibc-rh1631730.patch new file mode 100755 index 0000000..cc59bac --- /dev/null +++ b/glibc-rh1631730.patch @@ -0,0 +1,82 @@ +commit 2339d6a55eb7a7e040ae888e906adc49eeb59eab +Author: H.J. Lu +Date: Wed Sep 12 08:40:59 2018 -0700 + + i386: Use ENTRY and END in start.S [BZ #23606] + + Wrapping the _start function with ENTRY and END to insert ENDBR32 at + function entry when CET is enabled. Since _start now includes CFI, + without "cfi_undefined (eip)", unwinder may not terminate at _start + and we will get + + Program received signal SIGSEGV, Segmentation fault. + 0xf7dc661e in ?? () from /lib/libgcc_s.so.1 + Missing separate debuginfos, use: dnf debuginfo-install libgcc-8.2.1-3.0.fc28.i686 + (gdb) bt + #0 0xf7dc661e in ?? () from /lib/libgcc_s.so.1 + #1 0xf7dc7c18 in _Unwind_Backtrace () from /lib/libgcc_s.so.1 + #2 0xf7f0d809 in __GI___backtrace (array=array@entry=0xffffc7d0, + size=size@entry=20) at ../sysdeps/i386/backtrace.c:127 + #3 0x08049254 in compare (p1=p1@entry=0xffffcad0, p2=p2@entry=0xffffcad4) + at backtrace-tst.c:12 + #4 0xf7e2a28c in msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0, + n=n@entry=2) at msort.c:65 + #5 0xf7e29f64 in msort_with_tmp (n=2, b=0xffffcad0, p=0xffffca5c) + at msort.c:53 + #6 msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0, n=n@entry=5) + at msort.c:53 + #7 0xf7e29f64 in msort_with_tmp (n=5, b=0xffffcad0, p=0xffffca5c) + at msort.c:53 + #8 msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0, n=n@entry=10) + at msort.c:53 + #9 0xf7e29f64 in msort_with_tmp (n=10, b=0xffffcad0, p=0xffffca5c) + at msort.c:53 + #10 msort_with_tmp (p=p@entry=0xffffca5c, b=b@entry=0xffffcad0, n=n@entry=20) + at msort.c:53 + #11 0xf7e2a5b6 in msort_with_tmp (n=20, b=0xffffcad0, p=0xffffca5c) + at msort.c:297 + #12 __GI___qsort_r (b=b@entry=0xffffcad0, n=n@entry=20, s=s@entry=4, + cmp=cmp@entry=0x8049230 , arg=arg@entry=0x0) at msort.c:297 + #13 0xf7e2a84d in __GI_qsort (b=b@entry=0xffffcad0, n=n@entry=20, s=s@entry=4, + cmp=cmp@entry=0x8049230 ) at msort.c:308 + #14 0x080490f6 in main (argc=2, argv=0xffffcbd4) at backtrace-tst.c:39 + + FAIL: debug/backtrace-tst + + [BZ #23606] + * sysdeps/i386/start.S: Include + (_start): Use ENTRY/END to insert ENDBR32 at entry when CET is + enabled. Add cfi_undefined (eip). + + Signed-off-by: H.J. Lu + + (cherry picked from commit 5a274db4ea363d6b0b92933f085a92daaf1be2f2) + +diff --git a/sysdeps/i386/start.S b/sysdeps/i386/start.S +index 91035fa83fb7ee38..e35e9bd31b2cea30 100644 +--- a/sysdeps/i386/start.S ++++ b/sysdeps/i386/start.S +@@ -52,10 +52,11 @@ + NULL + */ + +- .text +- .globl _start +- .type _start,@function +-_start: ++#include ++ ++ENTRY (_start) ++ /* Clearing frame pointer is insufficient, use CFI. */ ++ cfi_undefined (eip) + /* Clear the frame pointer. The ABI suggests this be done, to mark + the outermost frame obviously. */ + xorl %ebp, %ebp +@@ -131,6 +132,7 @@ _start: + 1: movl (%esp), %ebx + ret + #endif ++END (_start) + + /* To fulfill the System V/i386 ABI we need this symbol. Yuck, it's so + meaningless since we don't support machines < 80386. */ diff --git a/glibc-rh1635779.patch b/glibc-rh1635779.patch new file mode 100755 index 0000000..e79fc37 --- /dev/null +++ b/glibc-rh1635779.patch @@ -0,0 +1,483 @@ +commit e5d262effe3a87164308a3f37e61b32d0348692a +Author: Tulio Magno Quites Machado Filho +Date: Fri Nov 30 18:05:32 2018 -0200 + + Fix _dl_profile_fixup data-dependency issue (Bug 23690) + + There is a data-dependency between the fields of struct l_reloc_result + and the field used as the initialization guard. Users of the guard + expect writes to the structure to be observable when they also observe + the guard initialized. The solution for this problem is to use an acquire + and release load and store to ensure previous writes to the structure are + observable if the guard is initialized. + + The previous implementation used DL_FIXUP_VALUE_ADDR (l_reloc_result->addr) + as the initialization guard, making it impossible for some architectures + to load and store it atomically, i.e. hppa and ia64, due to its larger size. + + This commit adds an unsigned int to l_reloc_result to be used as the new + initialization guard of the struct, making it possible to load and store + it atomically in all architectures. The fix ensures that the values + observed in l_reloc_result are consistent and do not lead to crashes. + The algorithm is documented in the code in elf/dl-runtime.c + (_dl_profile_fixup). Not all data races have been eliminated. + + Tested with build-many-glibcs and on powerpc, powerpc64, and powerpc64le. + + [BZ #23690] + * elf/dl-runtime.c (_dl_profile_fixup): Guarantee memory + modification order when accessing reloc_result->addr. + * include/link.h (reloc_result): Add field init. + * nptl/Makefile (tests): Add tst-audit-threads. + (modules-names): Add tst-audit-threads-mod1 and + tst-audit-threads-mod2. + Add rules to build tst-audit-threads. + * nptl/tst-audit-threads-mod1.c: New file. + * nptl/tst-audit-threads-mod2.c: Likewise. + * nptl/tst-audit-threads.c: Likewise. + * nptl/tst-audit-threads.h: Likewise. + + Signed-off-by: Tulio Magno Quites Machado Filho + Reviewed-by: Carlos O'Donell + +diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c +index 63bbc89776..3d2f4a7a76 100644 +--- a/elf/dl-runtime.c ++++ b/elf/dl-runtime.c +@@ -183,10 +183,36 @@ _dl_profile_fixup ( + /* This is the address in the array where we store the result of previous + relocations. */ + struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index]; +- DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr; + +- DL_FIXUP_VALUE_TYPE value = *resultp; +- if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0) ++ /* CONCURRENCY NOTES: ++ ++ Multiple threads may be calling the same PLT sequence and with ++ LD_AUDIT enabled they will be calling into _dl_profile_fixup to ++ update the reloc_result with the result of the lazy resolution. ++ The reloc_result guard variable is reloc_init, and we use ++ acquire/release loads and store to it to ensure that the results of ++ the structure are consistent with the loaded value of the guard. ++ This does not fix all of the data races that occur when two or more ++ threads read reloc_result->reloc_init with a value of zero and read ++ and write to that reloc_result concurrently. The expectation is ++ generally that while this is a data race it works because the ++ threads write the same values. Until the data races are fixed ++ there is a potential for problems to arise from these data races. ++ The reloc result updates should happen in parallel but there should ++ be an atomic RMW which does the final update to the real result ++ entry (see bug 23790). ++ ++ The following code uses reloc_result->init set to 0 to indicate if it is ++ the first time this object is being relocated, otherwise 1 which ++ indicates the object has already been relocated. ++ ++ Reading/Writing from/to reloc_result->reloc_init must not happen ++ before previous writes to reloc_result complete as they could ++ end-up with an incomplete struct. */ ++ DL_FIXUP_VALUE_TYPE value; ++ unsigned int init = atomic_load_acquire (&reloc_result->init); ++ ++ if (init == 0) + { + /* This is the first time we have to relocate this object. */ + const ElfW(Sym) *const symtab +@@ -346,19 +372,31 @@ _dl_profile_fixup ( + + /* Store the result for later runs. */ + if (__glibc_likely (! GLRO(dl_bind_not))) +- *resultp = value; ++ { ++ reloc_result->addr = value; ++ /* Guarantee all previous writes complete before ++ init is updated. See CONCURRENCY NOTES earlier */ ++ atomic_store_release (&reloc_result->init, 1); ++ } ++ init = 1; + } ++ else ++ value = reloc_result->addr; + + /* By default we do not call the pltexit function. */ + long int framesize = -1; + ++ + #ifdef SHARED + /* Auditing checkpoint: report the PLT entering and allow the + auditors to change the value. */ +- if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0 ++ if (GLRO(dl_naudit) > 0 + /* Don't do anything if no auditor wants to intercept this call. */ + && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0) + { ++ /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been ++ initialized earlier in this function or in another thread. */ ++ assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0); + ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, + l_info[DT_SYMTAB]) + + reloc_result->boundndx); +diff --git a/include/link.h b/include/link.h +index 5924594548..83b1c34b7b 100644 +--- a/include/link.h ++++ b/include/link.h +@@ -216,6 +216,10 @@ struct link_map + unsigned int boundndx; + uint32_t enterexit; + unsigned int flags; ++ /* CONCURRENCY NOTE: This is used to guard the concurrent initialization ++ of the relocation result across multiple threads. See the more ++ detailed notes in elf/dl-runtime.c. */ ++ unsigned int init; + } *l_reloc_result; + + /* Pointer to the version information if available. */ +diff --git a/nptl/Makefile b/nptl/Makefile +index 982e43adfa..98b0aa01c7 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -382,7 +382,8 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \ + tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 \ + tst-oncex3 tst-oncex4 + ifeq ($(build-shared),yes) +-tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder ++tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder \ ++ tst-audit-threads + tests-internal += tst-tls3 tst-tls3-malloc tst-tls5 tst-stackguard1 + tests-nolibpthread += tst-fini1 + ifeq ($(have-z-execstack),yes) +@@ -394,7 +395,8 @@ modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \ + tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \ + tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \ + tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \ +- tst-join7mod tst-compat-forwarder-mod ++ tst-join7mod tst-compat-forwarder-mod tst-audit-threads-mod1 \ ++ tst-audit-threads-mod2 + extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) \ + tst-cleanup4aux.o tst-cleanupx4aux.o + test-extras += tst-cleanup4aux tst-cleanupx4aux +@@ -712,6 +714,14 @@ $(objpfx)tst-compat-forwarder: $(objpfx)tst-compat-forwarder-mod.so + + tst-mutex10-ENV = GLIBC_TUNABLES=glibc.elision.enable=1 + ++# Protect against a build using -Wl,-z,now. ++LDFLAGS-tst-audit-threads-mod1.so = -Wl,-z,lazy ++LDFLAGS-tst-audit-threads-mod2.so = -Wl,-z,lazy ++LDFLAGS-tst-audit-threads = -Wl,-z,lazy ++$(objpfx)tst-audit-threads: $(objpfx)tst-audit-threads-mod2.so ++$(objpfx)tst-audit-threads.out: $(objpfx)tst-audit-threads-mod1.so ++tst-audit-threads-ENV = LD_AUDIT=$(objpfx)tst-audit-threads-mod1.so ++ + # The tests here better do not run in parallel + ifneq ($(filter %tests,$(MAKECMDGOALS)),) + .NOTPARALLEL: +diff --git a/nptl/tst-audit-threads-mod1.c b/nptl/tst-audit-threads-mod1.c +new file mode 100644 +index 0000000000..615d5ee512 +--- /dev/null ++++ b/nptl/tst-audit-threads-mod1.c +@@ -0,0 +1,74 @@ ++/* Dummy audit library for test-audit-threads. ++ ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* We must use a dummy LD_AUDIT module to force the dynamic loader to ++ *not* update the real PLT, and instead use a cached value for the ++ lazy resolution result. It is the update of that cached value that ++ we are testing for correctness by doing this. */ ++ ++/* Library to be audited. */ ++#define LIB "tst-audit-threads-mod2.so" ++/* CALLNUM is the number of retNum functions. */ ++#define CALLNUM 7999 ++ ++#define CONCATX(a, b) __CONCAT (a, b) ++ ++static int previous = 0; ++ ++unsigned int ++la_version (unsigned int ver) ++{ ++ return 1; ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ return LA_FLG_BINDTO | LA_FLG_BINDFROM; ++} ++ ++uintptr_t ++CONCATX(la_symbind, __ELF_NATIVE_CLASS) (ElfW(Sym) *sym, ++ unsigned int ndx, ++ uintptr_t *refcook, ++ uintptr_t *defcook, ++ unsigned int *flags, ++ const char *symname) ++{ ++ const char * retnum = "retNum"; ++ char * num = strstr (symname, retnum); ++ int n; ++ /* Validate if the symbols are getting called in the correct order. ++ This code is here to verify binutils does not optimize out the PLT ++ entries that require the symbol binding. */ ++ if (num != NULL) ++ { ++ n = atoi (num); ++ assert (n >= previous); ++ assert (n <= CALLNUM); ++ previous = n; ++ } ++ return sym->st_value; ++} +diff --git a/nptl/tst-audit-threads-mod2.c b/nptl/tst-audit-threads-mod2.c +new file mode 100644 +index 0000000000..f9817dd3dc +--- /dev/null ++++ b/nptl/tst-audit-threads-mod2.c +@@ -0,0 +1,22 @@ ++/* Shared object with a huge number of functions for test-audit-threads. ++ ++ Copyright (C) 2018 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 ++ . */ ++ ++/* Define all the retNumN functions in a library. */ ++#define definenum ++#include "tst-audit-threads.h" +diff --git a/nptl/tst-audit-threads.c b/nptl/tst-audit-threads.c +new file mode 100644 +index 0000000000..e4bf433bd8 +--- /dev/null ++++ b/nptl/tst-audit-threads.c +@@ -0,0 +1,97 @@ ++/* Test multi-threading using LD_AUDIT. ++ ++ Copyright (C) 2018 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 ++ . */ ++ ++/* This test uses a dummy LD_AUDIT library (test-audit-threads-mod1) and a ++ library with a huge number of functions in order to validate lazy symbol ++ binding with an audit library. We use one thread per CPU to test that ++ concurrent lazy resolution does not have any defects which would cause ++ the process to fail. We use an LD_AUDIT library to force the testing of ++ the relocation resolution caching code in the dynamic loader i.e. ++ _dl_runtime_profile and _dl_profile_fixup. */ ++ ++#include ++#include ++#include ++#include ++ ++static int do_test (void); ++ ++/* This test usually takes less than 3s to run. However, there are cases that ++ take up to 30s. */ ++#define TIMEOUT 60 ++#define TEST_FUNCTION do_test () ++#include "../test-skeleton.c" ++ ++/* Declare the functions we are going to call. */ ++#define externnum ++#include "tst-audit-threads.h" ++#undef externnum ++ ++int num_threads; ++pthread_barrier_t barrier; ++ ++void ++sync_all (int num) ++{ ++ pthread_barrier_wait (&barrier); ++} ++ ++void ++call_all_ret_nums (void) ++{ ++ /* Call each function one at a time from all threads. */ ++#define callnum ++#include "tst-audit-threads.h" ++#undef callnum ++} ++ ++void * ++thread_main (void *unused) ++{ ++ call_all_ret_nums (); ++ return NULL; ++} ++ ++#define STR2(X) #X ++#define STR(X) STR2(X) ++ ++static int ++do_test (void) ++{ ++ int i; ++ pthread_t *threads; ++ ++ num_threads = get_nprocs (); ++ if (num_threads <= 1) ++ num_threads = 2; ++ ++ /* Used to synchronize all the threads after calling each retNumN. */ ++ xpthread_barrier_init (&barrier, NULL, num_threads); ++ ++ threads = (pthread_t *) xcalloc (num_threads, sizeof(pthread_t)); ++ for (i = 0; i < num_threads; i++) ++ threads[i] = xpthread_create(NULL, thread_main, NULL); ++ ++ for (i = 0; i < num_threads; i++) ++ xpthread_join(threads[i]); ++ ++ free (threads); ++ ++ return 0; ++} +diff --git a/nptl/tst-audit-threads.h b/nptl/tst-audit-threads.h +new file mode 100644 +index 0000000000..1c9ecc08df +--- /dev/null ++++ b/nptl/tst-audit-threads.h +@@ -0,0 +1,92 @@ ++/* Helper header for test-audit-threads. ++ ++ Copyright (C) 2018 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 ++ . */ ++ ++/* We use this helper to create a large number of functions, all of ++ which will be resolved lazily and thus have their PLT updated. ++ This is done to provide enough functions that we can statistically ++ observe a thread vs. PLT resolution failure if one exists. */ ++ ++#define CONCAT(a, b) a ## b ++#define NUM(x, y) CONCAT (x, y) ++ ++#define FUNC10(x) \ ++ FUNC (NUM (x, 0)); \ ++ FUNC (NUM (x, 1)); \ ++ FUNC (NUM (x, 2)); \ ++ FUNC (NUM (x, 3)); \ ++ FUNC (NUM (x, 4)); \ ++ FUNC (NUM (x, 5)); \ ++ FUNC (NUM (x, 6)); \ ++ FUNC (NUM (x, 7)); \ ++ FUNC (NUM (x, 8)); \ ++ FUNC (NUM (x, 9)) ++ ++#define FUNC100(x) \ ++ FUNC10 (NUM (x, 0)); \ ++ FUNC10 (NUM (x, 1)); \ ++ FUNC10 (NUM (x, 2)); \ ++ FUNC10 (NUM (x, 3)); \ ++ FUNC10 (NUM (x, 4)); \ ++ FUNC10 (NUM (x, 5)); \ ++ FUNC10 (NUM (x, 6)); \ ++ FUNC10 (NUM (x, 7)); \ ++ FUNC10 (NUM (x, 8)); \ ++ FUNC10 (NUM (x, 9)) ++ ++#define FUNC1000(x) \ ++ FUNC100 (NUM (x, 0)); \ ++ FUNC100 (NUM (x, 1)); \ ++ FUNC100 (NUM (x, 2)); \ ++ FUNC100 (NUM (x, 3)); \ ++ FUNC100 (NUM (x, 4)); \ ++ FUNC100 (NUM (x, 5)); \ ++ FUNC100 (NUM (x, 6)); \ ++ FUNC100 (NUM (x, 7)); \ ++ FUNC100 (NUM (x, 8)); \ ++ FUNC100 (NUM (x, 9)) ++ ++#define FUNC7000() \ ++ FUNC1000 (1); \ ++ FUNC1000 (2); \ ++ FUNC1000 (3); \ ++ FUNC1000 (4); \ ++ FUNC1000 (5); \ ++ FUNC1000 (6); \ ++ FUNC1000 (7); ++ ++#ifdef FUNC ++# undef FUNC ++#endif ++ ++#ifdef externnum ++# define FUNC(x) extern int CONCAT (retNum, x) (void) ++#endif ++ ++#ifdef definenum ++# define FUNC(x) int CONCAT (retNum, x) (void) { return x; } ++#endif ++ ++#ifdef callnum ++# define FUNC(x) CONCAT (retNum, x) (); sync_all (x) ++#endif ++ ++/* A value of 7000 functions is chosen as an arbitrarily large ++ number of functions that will allow us enough attempts to ++ verify lazy resolution operation. */ ++FUNC7000 (); diff --git a/glibc-rh1638520.patch b/glibc-rh1638520.patch new file mode 100755 index 0000000..e52b7e5 --- /dev/null +++ b/glibc-rh1638520.patch @@ -0,0 +1,35 @@ +commit ed643089cd3251038863d32e67ec47b94cd557f3 +Author: Szabolcs Nagy +Date: Tue Oct 9 14:31:28 2018 +0100 + + Increase timeout of libio/tst-readline + + Increase timeout from the default 20s to 100s. This test makes close to + 20 million syscalls with distribution: + + 12327675 read + 4143204 lseek + 929475 close + 929471 openat + 92817 fstat + 1431 write + ... + + The default timeout assumes each can finish in 1us on average which + is not true on slow machines. + + Reviewed-by: Carlos O'Donell + + * libio/tst-readline.c (TIMEOUT): Define. + +diff --git a/libio/tst-readline.c b/libio/tst-readline.c +index 9322ef68da5e38a9..63f5227760d88c63 100644 +--- a/libio/tst-readline.c ++++ b/libio/tst-readline.c +@@ -232,5 +232,6 @@ do_test (void) + return 0; + } + ++#define TIMEOUT 100 + #define PREPARE prepare + #include diff --git a/glibc-rh1638523-1.patch b/glibc-rh1638523-1.patch new file mode 100755 index 0000000..bee0ab0 --- /dev/null +++ b/glibc-rh1638523-1.patch @@ -0,0 +1,2823 @@ +This patch backports the support/ directory as of the upstream commit +below. (It does not include the required Makefile changes to enable +test-in-container builds.) + +commit 00c86a37d1b63044e3169d1f2ebec23447c73f79 +Author: Adhemerval Zanella +Date: Wed Nov 7 11:09:02 2018 -0200 + + support: Fix printf format for TEST_COMPARE_STRING + + Fix the following on 32 bits targets: + + support_test_compare_string.c: In function ‘support_test_compare_string’: + support_test_compare_string.c:80:37: error: format ‘%lu’ expects argument of + type ‘long unsigned int’, but argument 2 has type ‘size_t’ {aka ‘unsigned int’} + [-Werror=format=] + printf (" string length: %lu bytes\n", left_length); + ~~^ ~~~~~~~~~~~ + %u + Checked on arm-linux-gnueabihf. + + * support/support_test_compare_string.c + (support_test_compare_string): Fix printf format. + +diff --git a/support/Makefile b/support/Makefile +index 652d2cdf6945b2eb..2b663fbbfa334ea2 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -25,6 +25,7 @@ extra-libs-others = $(extra-libs) + extra-libs-noinstall := $(extra-libs) + + libsupport-routines = \ ++ blob_repeat \ + check \ + check_addrinfo \ + check_dns_packet \ +@@ -43,6 +44,8 @@ libsupport-routines = \ + support_capture_subprocess \ + support_capture_subprocess_check \ + support_chroot \ ++ support_copy_file_range \ ++ support_descriptor_supports_holes \ + support_enter_mount_namespace \ + support_enter_network_namespace \ + support_format_address_family \ +@@ -53,12 +56,14 @@ libsupport-routines = \ + support_format_netent \ + support_isolate_in_subprocess \ + support_openpty \ ++ support_paths \ + support_quote_blob \ + support_record_failure \ + support_run_diff \ + support_shared_allocate \ + support_test_compare_blob \ + support_test_compare_failure \ ++ support_test_compare_string \ + support_write_file_string \ + support_test_main \ + support_test_verify_impl \ +@@ -72,6 +77,7 @@ libsupport-routines = \ + xchroot \ + xclose \ + xconnect \ ++ xcopy_file_range \ + xdlfcn \ + xdup2 \ + xfclose \ +@@ -84,6 +90,7 @@ libsupport-routines = \ + xmalloc \ + xmemstream \ + xmkdir \ ++ xmkdirp \ + xmmap \ + xmprotect \ + xmunmap \ +@@ -139,6 +146,7 @@ libsupport-routines = \ + xsocket \ + xstrdup \ + xstrndup \ ++ xsymlink \ + xsysconf \ + xunlink \ + xwaitpid \ +@@ -151,15 +159,47 @@ ifeq ($(build-shared),yes) + libsupport-inhibit-o += .o + endif + ++CFLAGS-support_paths.c = \ ++ -DSRCDIR_PATH=\"`cd .. ; pwd`\" \ ++ -DOBJDIR_PATH=\"`cd $(objpfx)/..; pwd`\" \ ++ -DOBJDIR_ELF_LDSO_PATH=\"`cd $(objpfx)/..; pwd`/elf/$(rtld-installed-name)\" \ ++ -DINSTDIR_PATH=\"$(prefix)\" \ ++ -DLIBDIR_PATH=\"$(libdir)\" ++ ++ifeq (,$(CXX)) ++LINKS_DSO_PROGRAM = links-dso-program-c ++else ++LINKS_DSO_PROGRAM = links-dso-program ++LDLIBS-links-dso-program = -lstdc++ -lgcc -lgcc_s $(libunwind) ++endif ++ ++LDLIBS-test-container = $(libsupport) ++ ++others += test-container ++others-noinstall += test-container ++ ++others += shell-container echo-container true-container ++others-noinstall += shell-container echo-container true-container ++ ++others += $(LINKS_DSO_PROGRAM) ++others-noinstall += $(LINKS_DSO_PROGRAM) ++ ++$(objpfx)test-container : $(libsupport) ++$(objpfx)shell-container : $(libsupport) ++$(objpfx)echo-container : $(libsupport) ++$(objpfx)true-container : $(libsupport) ++ + tests = \ + README-testing \ + tst-support-namespace \ ++ tst-support_blob_repeat \ + tst-support_capture_subprocess \ + tst-support_format_dns_packet \ + tst-support_quote_blob \ + tst-support_record_failure \ + tst-test_compare \ + tst-test_compare_blob \ ++ tst-test_compare_string \ + tst-xreadlink \ + + ifeq ($(run-built-tests),yes) +diff --git a/support/blob_repeat.c b/support/blob_repeat.c +new file mode 100644 +index 0000000000000000..16c1e448b990e386 +--- /dev/null ++++ b/support/blob_repeat.c +@@ -0,0 +1,282 @@ ++/* Repeating a memory blob, with alias mapping optimization. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Small allocations should use malloc directly instead of the mmap ++ optimization because mappings carry a lot of overhead. */ ++static const size_t maximum_small_size = 4 * 1024 * 1024; ++ ++/* Internal helper for fill. */ ++static void ++fill0 (char *target, const char *element, size_t element_size, ++ size_t count) ++{ ++ while (count > 0) ++ { ++ memcpy (target, element, element_size); ++ target += element_size; ++ --count; ++ } ++} ++ ++/* Fill the buffer at TARGET with COUNT copies of the ELEMENT_SIZE ++ bytes starting at ELEMENT. */ ++static void ++fill (char *target, const char *element, size_t element_size, ++ size_t count) ++{ ++ if (element_size == 0 || count == 0) ++ return; ++ else if (element_size == 1) ++ memset (target, element[0], count); ++ else if (element_size == sizeof (wchar_t)) ++ { ++ wchar_t wc; ++ memcpy (&wc, element, sizeof (wc)); ++ wmemset ((wchar_t *) target, wc, count); ++ } ++ else if (element_size < 1024 && count > 4096) ++ { ++ /* Use larger copies for really small element sizes. */ ++ char buffer[8192]; ++ size_t buffer_count = sizeof (buffer) / element_size; ++ fill0 (buffer, element, element_size, buffer_count); ++ while (count > 0) ++ { ++ size_t copy_count = buffer_count; ++ if (copy_count > count) ++ copy_count = count; ++ size_t copy_bytes = copy_count * element_size; ++ memcpy (target, buffer, copy_bytes); ++ target += copy_bytes; ++ count -= copy_count; ++ } ++ } ++ else ++ fill0 (target, element, element_size, count); ++} ++ ++/* Use malloc instead of mmap for small allocations and unusual size ++ combinations. */ ++static struct support_blob_repeat ++allocate_malloc (size_t total_size, const void *element, size_t element_size, ++ size_t count) ++{ ++ void *buffer = malloc (total_size); ++ if (buffer == NULL) ++ return (struct support_blob_repeat) { 0 }; ++ fill (buffer, element, element_size, count); ++ return (struct support_blob_repeat) ++ { ++ .start = buffer, ++ .size = total_size, ++ .use_malloc = true ++ }; ++} ++ ++/* Return the least common multiple of PAGE_SIZE and ELEMENT_SIZE, ++ avoiding overflow. This assumes that PAGE_SIZE is a power of ++ two. */ ++static size_t ++minimum_stride_size (size_t page_size, size_t element_size) ++{ ++ TEST_VERIFY_EXIT (page_size > 0); ++ TEST_VERIFY_EXIT (element_size > 0); ++ ++ /* Compute the number of trailing zeros common to both sizes. */ ++ unsigned int common_zeros = __builtin_ctzll (page_size | element_size); ++ ++ /* In the product, this power of two appears twice, but in the least ++ common multiple, it appears only once. Therefore, shift one ++ factor. */ ++ size_t multiple; ++ if (__builtin_mul_overflow (page_size >> common_zeros, element_size, ++ &multiple)) ++ return 0; ++ return multiple; ++} ++ ++/* Allocations larger than maximum_small_size potentially use mmap ++ with alias mappings. */ ++static struct support_blob_repeat ++allocate_big (size_t total_size, const void *element, size_t element_size, ++ size_t count) ++{ ++ unsigned long page_size = xsysconf (_SC_PAGESIZE); ++ size_t stride_size = minimum_stride_size (page_size, element_size); ++ if (stride_size == 0) ++ { ++ errno = EOVERFLOW; ++ return (struct support_blob_repeat) { 0 }; ++ } ++ ++ /* Ensure that the stride size is at least maximum_small_size. This ++ is necessary to reduce the number of distinct mappings. */ ++ if (stride_size < maximum_small_size) ++ stride_size ++ = ((maximum_small_size + stride_size - 1) / stride_size) * stride_size; ++ ++ if (stride_size > total_size) ++ /* The mmap optimization would not save anything. */ ++ return allocate_malloc (total_size, element, element_size, count); ++ ++ /* Reserve the memory region. If we cannot create the mapping, ++ there is no reason to set up the backing file. */ ++ void *target = mmap (NULL, total_size, PROT_NONE, ++ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ++ if (target == MAP_FAILED) ++ return (struct support_blob_repeat) { 0 }; ++ ++ /* Create the backing file for the repeated mapping. Call mkstemp ++ directly to remove the resources backing the temporary file ++ immediately, once support_blob_repeat_free is called. Using ++ create_temp_file would result in a warning during post-test ++ cleanup. */ ++ int fd; ++ { ++ char *temppath = xasprintf ("%s/support_blob_repeat-XXXXXX", test_dir); ++ fd = mkstemp (temppath); ++ if (fd < 0) ++ FAIL_EXIT1 ("mkstemp (\"%s\"): %m", temppath); ++ xunlink (temppath); ++ free (temppath); ++ } ++ ++ /* Make sure that there is backing storage, so that the fill ++ operation will not fault. */ ++ if (posix_fallocate (fd, 0, stride_size) != 0) ++ FAIL_EXIT1 ("posix_fallocate (%zu): %m", stride_size); ++ ++ /* The stride size must still be a multiple of the page size and ++ element size. */ ++ TEST_VERIFY_EXIT ((stride_size % page_size) == 0); ++ TEST_VERIFY_EXIT ((stride_size % element_size) == 0); ++ ++ /* Fill the backing store. */ ++ { ++ void *ptr = mmap (target, stride_size, PROT_READ | PROT_WRITE, ++ MAP_FIXED | MAP_FILE | MAP_SHARED, fd, 0); ++ if (ptr == MAP_FAILED) ++ { ++ int saved_errno = errno; ++ xmunmap (target, total_size); ++ xclose (fd); ++ errno = saved_errno; ++ return (struct support_blob_repeat) { 0 }; ++ } ++ if (ptr != target) ++ FAIL_EXIT1 ("mapping of %zu bytes moved from %p to %p", ++ stride_size, target, ptr); ++ ++ /* Write the repeating data. */ ++ fill (target, element, element_size, stride_size / element_size); ++ ++ /* Return to a PROT_NONE mapping, just to be on the safe side. */ ++ ptr = mmap (target, stride_size, PROT_NONE, ++ MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ++ if (ptr == MAP_FAILED) ++ FAIL_EXIT1 ("Failed to reinstate PROT_NONE mapping: %m"); ++ if (ptr != target) ++ FAIL_EXIT1 ("PROT_NONE mapping of %zu bytes moved from %p to %p", ++ stride_size, target, ptr); ++ } ++ ++ /* Create the alias mappings. */ ++ { ++ size_t remaining_size = total_size; ++ char *current = target; ++ int flags = MAP_FIXED | MAP_FILE | MAP_PRIVATE; ++#ifdef MAP_NORESERVE ++ flags |= MAP_NORESERVE; ++#endif ++ while (remaining_size > 0) ++ { ++ size_t to_map = stride_size; ++ if (to_map > remaining_size) ++ to_map = remaining_size; ++ void *ptr = mmap (current, to_map, PROT_READ | PROT_WRITE, ++ flags, fd, 0); ++ if (ptr == MAP_FAILED) ++ { ++ int saved_errno = errno; ++ xmunmap (target, total_size); ++ xclose (fd); ++ errno = saved_errno; ++ return (struct support_blob_repeat) { 0 }; ++ } ++ if (ptr != current) ++ FAIL_EXIT1 ("MAP_PRIVATE mapping of %zu bytes moved from %p to %p", ++ to_map, target, ptr); ++ remaining_size -= to_map; ++ current += to_map; ++ } ++ } ++ ++ xclose (fd); ++ ++ return (struct support_blob_repeat) ++ { ++ .start = target, ++ .size = total_size, ++ .use_malloc = false ++ }; ++} ++ ++struct support_blob_repeat ++support_blob_repeat_allocate (const void *element, size_t element_size, ++ size_t count) ++{ ++ size_t total_size; ++ if (__builtin_mul_overflow (element_size, count, &total_size)) ++ { ++ errno = EOVERFLOW; ++ return (struct support_blob_repeat) { 0 }; ++ } ++ if (total_size <= maximum_small_size) ++ return allocate_malloc (total_size, element, element_size, count); ++ else ++ return allocate_big (total_size, element, element_size, count); ++} ++ ++void ++support_blob_repeat_free (struct support_blob_repeat *blob) ++{ ++ if (blob->size > 0) ++ { ++ int saved_errno = errno; ++ if (blob->use_malloc) ++ free (blob->start); ++ else ++ xmunmap (blob->start, blob->size); ++ errno = saved_errno; ++ } ++ *blob = (struct support_blob_repeat) { 0 }; ++} +diff --git a/support/blob_repeat.h b/support/blob_repeat.h +new file mode 100644 +index 0000000000000000..8e9d7ff5f1e01f66 +--- /dev/null ++++ b/support/blob_repeat.h +@@ -0,0 +1,44 @@ ++/* Repeating a memory blob, with alias mapping optimization. ++ Copyright (C) 2018 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 ++ . */ ++ ++#ifndef SUPPORT_BLOB_REPEAT_H ++#define SUPPORT_BLOB_REPEAT_H ++ ++#include ++#include ++ ++struct support_blob_repeat ++{ ++ void *start; ++ size_t size; ++ bool use_malloc; ++}; ++ ++/* Return an allocation of COUNT elements, each of ELEMENT_SIZE bytes, ++ initialized with the bytes starting at ELEMENT. The memory is ++ writable (and thus counts towards the commit charge). In case of ++ on error, all members of the return struct are zero-initialized, ++ and errno is set accordingly. */ ++struct support_blob_repeat support_blob_repeat_allocate (const void *element, ++ size_t element_size, ++ size_t count); ++ ++/* Deallocate the blob created by support_blob_repeat_allocate. */ ++void support_blob_repeat_free (struct support_blob_repeat *); ++ ++#endif /* SUPPORT_BLOB_REPEAT_H */ +diff --git a/support/check.h b/support/check.h +index b3a4645e9255e90d..e6765289f2492501 100644 +--- a/support/check.h ++++ b/support/check.h +@@ -163,6 +163,19 @@ void support_test_compare_blob (const void *left, + const char *right_exp, + const char *right_len_exp); + ++/* Compare the strings LEFT and RIGHT and report a test failure if ++ they are different. Also report failure if one of the arguments is ++ a null pointer and the other is not. The strings should be ++ reasonably short because on mismatch, both are printed. */ ++#define TEST_COMPARE_STRING(left, right) \ ++ (support_test_compare_string (left, right, __FILE__, __LINE__, \ ++ #left, #right)) ++ ++void support_test_compare_string (const char *left, const char *right, ++ const char *file, int line, ++ const char *left_expr, ++ const char *right_expr); ++ + /* Internal function called by the test driver. */ + int support_report_failure (int status) + __attribute__ ((weak, warn_unused_result)); +diff --git a/support/echo-container.c b/support/echo-container.c +new file mode 100644 +index 0000000000000000..e4d48df95722af2e +--- /dev/null ++++ b/support/echo-container.c +@@ -0,0 +1,34 @@ ++/* Minimal /bin/echo for in-container use. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++ ++int ++main (int argc, const char **argv) ++{ ++ int i; ++ ++ for (i = 1; i < argc; i++) ++ { ++ if (i > 1) ++ putchar (' '); ++ fputs (argv[i], stdout); ++ } ++ putchar ('\n'); ++ return 0; ++} +diff --git a/support/links-dso-program-c.c b/support/links-dso-program-c.c +new file mode 100644 +index 0000000000000000..d28a28a0d09c743c +--- /dev/null ++++ b/support/links-dso-program-c.c +@@ -0,0 +1,9 @@ ++#include ++ ++int ++main (int argc, char **argv) ++{ ++ /* Complexity to keep gcc from optimizing this away. */ ++ printf ("This is a test %s.\n", argc > 1 ? argv[1] : "null"); ++ return 0; ++} +diff --git a/support/links-dso-program.cc b/support/links-dso-program.cc +new file mode 100644 +index 0000000000000000..dba6976c0609a332 +--- /dev/null ++++ b/support/links-dso-program.cc +@@ -0,0 +1,11 @@ ++#include ++ ++using namespace std; ++ ++int ++main (int argc, char **argv) ++{ ++ /* Complexity to keep gcc from optimizing this away. */ ++ cout << (argc > 1 ? argv[1] : "null"); ++ return 0; ++} +diff --git a/support/shell-container.c b/support/shell-container.c +new file mode 100644 +index 0000000000000000..9bd90d3f60529079 +--- /dev/null ++++ b/support/shell-container.c +@@ -0,0 +1,395 @@ ++/* Minimal /bin/sh for in-container use. ++ Copyright (C) 2018 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 ++ . */ ++ ++#define _FILE_OFFSET_BITS 64 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++/* Design considerations ++ ++ General rule: optimize for developer time, not run time. ++ ++ Specifically: ++ ++ * Don't worry about slow algorithms ++ * Don't worry about free'ing memory ++ * Don't implement anything the testsuite doesn't need. ++ * Line and argument counts are limited, see below. ++ ++*/ ++ ++#define MAX_ARG_COUNT 100 ++#define MAX_LINE_LENGTH 1000 ++ ++/* Debugging is enabled via --debug, which must be the first argument. */ ++static int debug_mode = 0; ++#define dprintf if (debug_mode) fprintf ++ ++/* Emulate the "/bin/true" command. Arguments are ignored. */ ++static int ++true_func (char **argv) ++{ ++ return 0; ++} ++ ++/* Emulate the "/bin/echo" command. Options are ignored, arguments ++ are printed to stdout. */ ++static int ++echo_func (char **argv) ++{ ++ int i; ++ ++ for (i = 0; argv[i]; i++) ++ { ++ if (i > 0) ++ putchar (' '); ++ fputs (argv[i], stdout); ++ } ++ putchar ('\n'); ++ ++ return 0; ++} ++ ++/* Emulate the "/bin/cp" command. Options are ignored. Only copies ++ one source file to one destination file. Directory destinations ++ are not supported. */ ++static int ++copy_func (char **argv) ++{ ++ char *sname = argv[0]; ++ char *dname = argv[1]; ++ int sfd, dfd; ++ struct stat st; ++ ++ sfd = open (sname, O_RDONLY); ++ if (sfd < 0) ++ { ++ fprintf (stderr, "cp: unable to open %s for reading: %s\n", ++ sname, strerror (errno)); ++ return 1; ++ } ++ ++ if (fstat (sfd, &st) < 0) ++ { ++ fprintf (stderr, "cp: unable to fstat %s: %s\n", ++ sname, strerror (errno)); ++ return 1; ++ } ++ ++ dfd = open (dname, O_WRONLY | O_TRUNC | O_CREAT, 0600); ++ if (dfd < 0) ++ { ++ fprintf (stderr, "cp: unable to open %s for writing: %s\n", ++ dname, strerror (errno)); ++ return 1; ++ } ++ ++ if (support_copy_file_range (sfd, 0, dfd, 0, st.st_size, 0) != st.st_size) ++ { ++ fprintf (stderr, "cp: cannot copy file %s to %s: %s\n", ++ sname, dname, strerror (errno)); ++ return 1; ++ } ++ ++ close (sfd); ++ close (dfd); ++ ++ chmod (dname, st.st_mode & 0777); ++ ++ return 0; ++ ++} ++ ++/* This is a list of all the built-in commands we understand. */ ++static struct { ++ const char *name; ++ int (*func) (char **argv); ++} builtin_funcs[] = { ++ { "true", true_func }, ++ { "echo", echo_func }, ++ { "cp", copy_func }, ++ { NULL, NULL } ++}; ++ ++/* Run one tokenized command. argv[0] is the command. argv is ++ NULL-terminated. */ ++static void ++run_command_array (char **argv) ++{ ++ int i, j; ++ pid_t pid; ++ int status; ++ int (*builtin_func) (char **args); ++ ++ if (argv[0] == NULL) ++ return; ++ ++ builtin_func = NULL; ++ ++ int new_stdin = 0; ++ int new_stdout = 1; ++ int new_stderr = 2; ++ ++ dprintf (stderr, "run_command_array starting\n"); ++ for (i = 0; argv[i]; i++) ++ dprintf (stderr, " argv [%d] `%s'\n", i, argv[i]); ++ ++ for (j = i = 0; argv[i]; i++) ++ { ++ if (strcmp (argv[i], "<") == 0 && argv[i + 1]) ++ { ++ new_stdin = open (argv[i + 1], O_WRONLY|O_CREAT|O_TRUNC, 0777); ++ ++i; ++ continue; ++ } ++ if (strcmp (argv[i], ">") == 0 && argv[i + 1]) ++ { ++ new_stdout = open (argv[i + 1], O_WRONLY|O_CREAT|O_TRUNC, 0777); ++ ++i; ++ continue; ++ } ++ if (strcmp (argv[i], ">>") == 0 && argv[i + 1]) ++ { ++ new_stdout = open (argv[i + 1], O_WRONLY|O_CREAT|O_APPEND, 0777); ++ ++i; ++ continue; ++ } ++ if (strcmp (argv[i], "2>") == 0 && argv[i + 1]) ++ { ++ new_stderr = open (argv[i + 1], O_WRONLY|O_CREAT|O_TRUNC, 0777); ++ ++i; ++ continue; ++ } ++ argv[j++] = argv[i]; ++ } ++ argv[j] = NULL; ++ ++ ++ for (i = 0; builtin_funcs[i].name != NULL; i++) ++ if (strcmp (argv[0], builtin_funcs[i].name) == 0) ++ builtin_func = builtin_funcs[i].func; ++ ++ dprintf (stderr, "builtin %p argv0 `%s'\n", builtin_func, argv[0]); ++ ++ pid = fork (); ++ if (pid < 0) ++ { ++ fprintf (stderr, "sh: fork failed\n"); ++ exit (1); ++ } ++ ++ if (pid == 0) ++ { ++ if (new_stdin != 0) ++ { ++ dup2 (new_stdin, 0); ++ close (new_stdin); ++ } ++ if (new_stdout != 1) ++ { ++ dup2 (new_stdout, 1); ++ close (new_stdout); ++ } ++ if (new_stderr != 2) ++ { ++ dup2 (new_stderr, 2); ++ close (new_stdout); ++ } ++ ++ if (builtin_func != NULL) ++ exit (builtin_func (argv + 1)); ++ ++ execvp (argv[0], argv); ++ ++ fprintf (stderr, "sh: execing %s failed: %s", ++ argv[0], strerror (errno)); ++ exit (1); ++ } ++ ++ waitpid (pid, &status, 0); ++ ++ dprintf (stderr, "exiting run_command_array\n"); ++ ++ if (WIFEXITED (status)) ++ { ++ int rv = WEXITSTATUS (status); ++ if (rv) ++ exit (rv); ++ } ++ else ++ exit (1); ++} ++ ++/* Run one command-as-a-string, by tokenizing it. Limited to ++ MAX_ARG_COUNT arguments. Simple substitution is done of $1 to $9 ++ (as whole separate tokens) from iargs[]. Quoted strings work if ++ the quotes wrap whole tokens; i.e. "foo bar" but not foo" bar". */ ++static void ++run_command_string (const char *cmdline, const char **iargs) ++{ ++ char *args[MAX_ARG_COUNT+1]; ++ int ap = 0; ++ const char *start, *end; ++ int nargs; ++ ++ for (nargs = 0; iargs[nargs] != NULL; ++nargs) ++ ; ++ ++ dprintf (stderr, "run_command_string starting: '%s'\n", cmdline); ++ ++ while (ap < MAX_ARG_COUNT) ++ { ++ /* If the argument is quoted, this is the quote character, else NUL. */ ++ int in_quote = 0; ++ ++ /* Skip whitespace up to the next token. */ ++ while (*cmdline && isspace (*cmdline)) ++ cmdline ++; ++ if (*cmdline == 0) ++ break; ++ ++ start = cmdline; ++ /* Check for quoted argument. */ ++ in_quote = (*cmdline == '\'' || *cmdline == '"') ? *cmdline : 0; ++ ++ /* Skip to end of token; either by whitespace or matching quote. */ ++ dprintf (stderr, "in_quote %d\n", in_quote); ++ while (*cmdline ++ && (!isspace (*cmdline) || in_quote)) ++ { ++ if (*cmdline == in_quote ++ && cmdline != start) ++ in_quote = 0; ++ dprintf (stderr, "[%c]%d ", *cmdline, in_quote); ++ cmdline ++; ++ } ++ dprintf (stderr, "\n"); ++ ++ /* Allocate space for this token and store it in args[]. */ ++ end = cmdline; ++ dprintf (stderr, "start<%s> end<%s>\n", start, end); ++ args[ap] = (char *) xmalloc (end - start + 1); ++ memcpy (args[ap], start, end - start); ++ args[ap][end - start] = 0; ++ ++ /* Strip off quotes, if found. */ ++ dprintf (stderr, "args[%d] = <%s>\n", ap, args[ap]); ++ if (args[ap][0] == '\'' ++ && args[ap][strlen (args[ap])-1] == '\'') ++ { ++ args[ap][strlen (args[ap])-1] = 0; ++ args[ap] ++; ++ } ++ ++ else if (args[ap][0] == '"' ++ && args[ap][strlen (args[ap])-1] == '"') ++ { ++ args[ap][strlen (args[ap])-1] = 0; ++ args[ap] ++; ++ } ++ ++ /* Replace positional parameters like $4. */ ++ else if (args[ap][0] == '$' ++ && isdigit (args[ap][1]) ++ && args[ap][2] == 0) ++ { ++ int a = args[ap][1] - '1'; ++ if (0 <= a && a < nargs) ++ args[ap] = strdup (iargs[a]); ++ } ++ ++ ap ++; ++ ++ if (*cmdline == 0) ++ break; ++ } ++ ++ /* Lastly, NULL terminate the array and run it. */ ++ args[ap] = NULL; ++ run_command_array (args); ++} ++ ++/* Run a script by reading lines and passing them to the above ++ function. */ ++static void ++run_script (const char *filename, const char **args) ++{ ++ char line[MAX_LINE_LENGTH + 1]; ++ dprintf (stderr, "run_script starting: '%s'\n", filename); ++ FILE *f = fopen (filename, "r"); ++ if (f == NULL) ++ { ++ fprintf (stderr, "sh: %s: %s\n", filename, strerror (errno)); ++ exit (1); ++ } ++ while (fgets (line, sizeof (line), f) != NULL) ++ { ++ if (line[0] == '#') ++ { ++ dprintf (stderr, "comment: %s\n", line); ++ continue; ++ } ++ run_command_string (line, args); ++ } ++ fclose (f); ++} ++ ++int ++main (int argc, const char **argv) ++{ ++ int i; ++ ++ if (strcmp (argv[1], "--debug") == 0) ++ { ++ debug_mode = 1; ++ --argc; ++ ++argv; ++ } ++ ++ dprintf (stderr, "container-sh starting:\n"); ++ for (i = 0; i < argc; i++) ++ dprintf (stderr, " argv[%d] is `%s'\n", i, argv[i]); ++ ++ if (strcmp (argv[1], "-c") == 0) ++ run_command_string (argv[2], argv+3); ++ else ++ run_script (argv[1], argv+2); ++ ++ dprintf (stderr, "normal exit 0\n"); ++ return 0; ++} +diff --git a/support/support.h b/support/support.h +index b61fe0735c9204de..9418cd11ef6e684d 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -25,6 +25,10 @@ + + #include + #include ++/* For mode_t. */ ++#include ++/* For ssize_t and off64_t. */ ++#include + + __BEGIN_DECLS + +@@ -65,6 +69,12 @@ void support_write_file_string (const char *path, const char *contents); + the result). */ + char *support_quote_blob (const void *blob, size_t length); + ++/* Returns non-zero if the file descriptor is a regular file on a file ++ system which supports holes (that is, seeking and writing does not ++ allocate storage for the range of zeros). FD must refer to a ++ regular file open for writing, and initially empty. */ ++int support_descriptor_supports_holes (int fd); ++ + /* Error-checking wrapper functions which terminate the process on + error. */ + +@@ -76,6 +86,23 @@ char *xasprintf (const char *format, ...) + char *xstrdup (const char *); + char *xstrndup (const char *, size_t); + ++/* These point to the TOP of the source/build tree, not your (or ++ support's) subdirectory. */ ++extern const char support_srcdir_root[]; ++extern const char support_objdir_root[]; ++ ++/* Corresponds to the path to the runtime linker used by the testsuite, ++ e.g. OBJDIR_PATH/elf/ld-linux-x86-64.so.2 */ ++extern const char support_objdir_elf_ldso[]; ++ ++/* Corresponds to the --prefix= passed to configure. */ ++extern const char support_install_prefix[]; ++/* Corresponds to the install's lib/ or lib64/ directory. */ ++extern const char support_libdir_prefix[]; ++ ++extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *, ++ size_t, unsigned int); ++ + __END_DECLS + + #endif /* SUPPORT_H */ +diff --git a/support/support_copy_file_range.c b/support/support_copy_file_range.c +new file mode 100644 +index 0000000000000000..9a1e39773e0481c9 +--- /dev/null ++++ b/support/support_copy_file_range.c +@@ -0,0 +1,143 @@ ++/* Simplified copy_file_range with cross-device copy. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ssize_t ++support_copy_file_range (int infd, __off64_t *pinoff, ++ int outfd, __off64_t *poutoff, ++ size_t length, unsigned int flags) ++{ ++ if (flags != 0) ++ { ++ errno = EINVAL; ++ return -1; ++ } ++ ++ struct stat64 instat; ++ struct stat64 outstat; ++ if (fstat64 (infd, &instat) != 0 || fstat64 (outfd, &outstat) != 0) ++ return -1; ++ if (S_ISDIR (instat.st_mode) || S_ISDIR (outstat.st_mode)) ++ { ++ errno = EISDIR; ++ return -1; ++ } ++ if (!S_ISREG (instat.st_mode) || !S_ISREG (outstat.st_mode)) ++ { ++ /* We need a regular input file so that the we can seek ++ backwards in case of a write failure. */ ++ errno = EINVAL; ++ return -1; ++ } ++ ++ /* The output descriptor must not have O_APPEND set. */ ++ if (fcntl (outfd, F_GETFL) & O_APPEND) ++ { ++ errno = EBADF; ++ return -1; ++ } ++ ++ /* Avoid an overflow in the result. */ ++ if (length > SSIZE_MAX) ++ length = SSIZE_MAX; ++ ++ /* Main copying loop. The buffer size is arbitrary and is a ++ trade-off between stack size consumption, cache usage, and ++ amortization of system call overhead. */ ++ size_t copied = 0; ++ char buf[8192]; ++ while (length > 0) ++ { ++ size_t to_read = length; ++ if (to_read > sizeof (buf)) ++ to_read = sizeof (buf); ++ ++ /* Fill the buffer. */ ++ ssize_t read_count; ++ if (pinoff == NULL) ++ read_count = read (infd, buf, to_read); ++ else ++ read_count = pread64 (infd, buf, to_read, *pinoff); ++ if (read_count == 0) ++ /* End of file reached prematurely. */ ++ return copied; ++ if (read_count < 0) ++ { ++ if (copied > 0) ++ /* Report the number of bytes copied so far. */ ++ return copied; ++ return -1; ++ } ++ if (pinoff != NULL) ++ *pinoff += read_count; ++ ++ /* Write the buffer part which was read to the destination. */ ++ char *end = buf + read_count; ++ for (char *p = buf; p < end; ) ++ { ++ ssize_t write_count; ++ if (poutoff == NULL) ++ write_count = write (outfd, p, end - p); ++ else ++ write_count = pwrite64 (outfd, p, end - p, *poutoff); ++ if (write_count < 0) ++ { ++ /* Adjust the input read position to match what we have ++ written, so that the caller can pick up after the ++ error. */ ++ size_t written = p - buf; ++ /* NB: This needs to be signed so that we can form the ++ negative value below. */ ++ ssize_t overread = read_count - written; ++ if (pinoff == NULL) ++ { ++ if (overread > 0) ++ { ++ /* We are on an error recovery path, so we ++ cannot deal with failure here. */ ++ int save_errno = errno; ++ (void) lseek64 (infd, -overread, SEEK_CUR); ++ errno = save_errno; ++ } ++ } ++ else /* pinoff != NULL */ ++ *pinoff -= overread; ++ ++ if (copied + written > 0) ++ /* Report the number of bytes copied so far. */ ++ return copied + written; ++ return -1; ++ } ++ p += write_count; ++ if (poutoff != NULL) ++ *poutoff += write_count; ++ } /* Write loop. */ ++ ++ copied += read_count; ++ length -= read_count; ++ } ++ return copied; ++} +diff --git a/support/support_descriptor_supports_holes.c b/support/support_descriptor_supports_holes.c +new file mode 100644 +index 0000000000000000..c7099ca67caf803c +--- /dev/null ++++ b/support/support_descriptor_supports_holes.c +@@ -0,0 +1,87 @@ ++/* Test for file system hole support. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++int ++support_descriptor_supports_holes (int fd) ++{ ++ enum ++ { ++ /* Write offset for the enlarged file. This value is arbitrary ++ and hopefully large enough to trigger the creation of holes. ++ We cannot use the file system block size as a reference here ++ because it is incorrect for network file systems. */ ++ write_offset = 16 * 1024 * 1024, ++ ++ /* Our write may add this number of additional blocks (see ++ block_limit below). */ ++ block_headroom = 8, ++ }; ++ ++ struct stat64 st; ++ xfstat (fd, &st); ++ if (!S_ISREG (st.st_mode)) ++ FAIL_EXIT1 ("descriptor %d does not refer to a regular file", fd); ++ if (st.st_size != 0) ++ FAIL_EXIT1 ("descriptor %d does not refer to an empty file", fd); ++ if (st.st_blocks > block_headroom) ++ FAIL_EXIT1 ("descriptor %d refers to a pre-allocated file (%lld blocks)", ++ fd, (long long int) st.st_blocks); ++ ++ /* Write a single byte at the start of the file to compute the block ++ usage for a single byte. */ ++ xlseek (fd, 0, SEEK_SET); ++ char b = '@'; ++ xwrite (fd, &b, 1); ++ /* Attempt to bypass delayed allocation. */ ++ TEST_COMPARE (fsync (fd), 0); ++ xfstat (fd, &st); ++ ++ /* This limit is arbitrary. The file system needs to store ++ somewhere that data exists at the write offset, and this may ++ moderately increase the number of blocks used by the file, in ++ proportion to the initial block count, but not in proportion to ++ the write offset. */ ++ unsigned long long int block_limit = 2 * st.st_blocks + block_headroom; ++ ++ /* Write a single byte at 16 megabytes. */ ++ xlseek (fd, write_offset, SEEK_SET); ++ xwrite (fd, &b, 1); ++ /* Attempt to bypass delayed allocation. */ ++ TEST_COMPARE (fsync (fd), 0); ++ xfstat (fd, &st); ++ bool supports_holes = st.st_blocks <= block_limit; ++ ++ /* Also check that extending the file does not fill up holes. */ ++ xftruncate (fd, 2 * write_offset); ++ /* Attempt to bypass delayed allocation. */ ++ TEST_COMPARE (fsync (fd), 0); ++ xfstat (fd, &st); ++ supports_holes = supports_holes && st.st_blocks <= block_limit; ++ ++ /* Return to a zero-length file. */ ++ xftruncate (fd, 0); ++ xlseek (fd, 0, SEEK_SET); ++ ++ return supports_holes; ++} +diff --git a/support/support_paths.c b/support/support_paths.c +new file mode 100644 +index 0000000000000000..6d0beb102c9b4bed +--- /dev/null ++++ b/support/support_paths.c +@@ -0,0 +1,59 @@ ++/* Various paths that might be needed. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++ ++/* The idea here is to make various makefile-level paths available to ++ support programs, as canonicalized absolute paths. */ ++ ++/* These point to the TOP of the source/build tree, not your (or ++ support's) subdirectory. */ ++#ifdef SRCDIR_PATH ++const char support_srcdir_root[] = SRCDIR_PATH; ++#else ++# error please -DSRCDIR_PATH=something in the Makefile ++#endif ++ ++#ifdef OBJDIR_PATH ++const char support_objdir_root[] = OBJDIR_PATH; ++#else ++# error please -DOBJDIR_PATH=something in the Makefile ++#endif ++ ++#ifdef OBJDIR_ELF_LDSO_PATH ++/* Corresponds to the path to the runtime linker used by the testsuite, ++ e.g. OBJDIR_PATH/elf/ld-linux-x86-64.so.2 */ ++const char support_objdir_elf_ldso[] = OBJDIR_ELF_LDSO_PATH; ++#else ++# error please -DOBJDIR_ELF_LDSO_PATH=something in the Makefile ++#endif ++ ++#ifdef INSTDIR_PATH ++/* Corresponds to the --prefix= passed to configure. */ ++const char support_install_prefix[] = INSTDIR_PATH; ++#else ++# error please -DINSTDIR_PATH=something in the Makefile ++#endif ++ ++#ifdef LIBDIR_PATH ++/* Corresponds to the install's lib/ or lib64/ directory. */ ++const char support_libdir_prefix[] = LIBDIR_PATH; ++#else ++# error please -DLIBDIR_PATH=something in the Makefile ++#endif +diff --git a/support/support_test_compare_string.c b/support/support_test_compare_string.c +new file mode 100644 +index 0000000000000000..a76ba8eda7782d9d +--- /dev/null ++++ b/support/support_test_compare_string.c +@@ -0,0 +1,91 @@ ++/* Check two strings for equality. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void ++report_length (const char *what, const char *str, size_t length) ++{ ++ if (str == NULL) ++ printf (" %s string: NULL\n", what); ++ else ++ printf (" %s string: %zu bytes\n", what, length); ++} ++ ++static void ++report_string (const char *what, const unsigned char *blob, ++ size_t length, const char *expr) ++{ ++ if (length > 0) ++ { ++ printf (" %s (evaluated from %s):\n", what, expr); ++ char *quoted = support_quote_blob (blob, length); ++ printf (" \"%s\"\n", quoted); ++ free (quoted); ++ ++ fputs (" ", stdout); ++ for (size_t i = 0; i < length; ++i) ++ printf (" %02X", blob[i]); ++ putc ('\n', stdout); ++ } ++} ++ ++static size_t ++string_length_or_zero (const char *str) ++{ ++ if (str == NULL) ++ return 0; ++ else ++ return strlen (str); ++} ++ ++void ++support_test_compare_string (const char *left, const char *right, ++ const char *file, int line, ++ const char *left_expr, const char *right_expr) ++{ ++ /* Two null pointers are accepted. */ ++ if (left == NULL && right == NULL) ++ return; ++ ++ size_t left_length = string_length_or_zero (left); ++ size_t right_length = string_length_or_zero (right); ++ ++ if (left_length != right_length || left == NULL || right == NULL ++ || memcmp (left, right, left_length) != 0) ++ { ++ support_record_failure (); ++ printf ("%s:%d: error: blob comparison failed\n", file, line); ++ if (left_length == right_length && right != NULL && left != NULL) ++ printf (" string length: %zu bytes\n", left_length); ++ else ++ { ++ report_length ("left", left, left_length); ++ report_length ("right", right, right_length); ++ } ++ report_string ("left", (const unsigned char *) left, ++ left_length, left_expr); ++ report_string ("right", (const unsigned char *) right, ++ right_length, right_expr); ++ } ++} +diff --git a/support/test-container.c b/support/test-container.c +new file mode 100644 +index 0000000000000000..b58f0f7b3d1d4859 +--- /dev/null ++++ b/support/test-container.c +@@ -0,0 +1,988 @@ ++/* Run a test case in an isolated namespace. ++ Copyright (C) 2018 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 ++ . */ ++ ++#define _FILE_OFFSET_BITS 64 ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef __linux__ ++#include ++#endif ++ ++#include ++#include ++#include "check.h" ++#include "test-driver.h" ++ ++#ifndef __linux__ ++#define mount(s,t,fs,f,d) no_mount() ++int no_mount (void) ++{ ++ FAIL_UNSUPPORTED("mount not supported; port needed"); ++} ++#endif ++ ++int verbose = 0; ++ ++/* Running a test in a container is tricky. There are two main ++ categories of things to do: ++ ++ 1. "Once" actions, like setting up the container and doing an ++ install into it. ++ ++ 2. "Per-test" actions, like copying in support files and ++ configuring the container. ++ ++ ++ "Once" actions: ++ ++ * mkdir $buildroot/testroot.pristine/ ++ * install into it ++ * rsync to $buildroot/testroot.root/ ++ ++ "Per-test" actions: ++ * maybe rsync to $buildroot/testroot.root/ ++ * copy support files and test binary ++ * chroot/unshare ++ * set up any mounts (like /proc) ++ ++ Magic files: ++ ++ For test $srcdir/foo/mytest.c we look for $srcdir/foo/mytest.root ++ and, if found... ++ ++ * mytest.root/ is rsync'd into container ++ * mytest.root/preclean.req causes fresh rsync (with delete) before ++ test if present ++ * mytest.root/mytset.script has a list of "commands" to run: ++ syntax: ++ # comment ++ mv FILE FILE ++ cp FILE FILE ++ rm FILE ++ FILE must start with $B/, $S/, $I/, $L/, or / ++ (expands to build dir, source dir, install dir, library dir ++ (in container), or container's root) ++ * mytest.root/postclean.req causes fresh rsync (with delete) after ++ test if present ++ ++ Note that $srcdir/foo/mytest.script may be used instead of a ++ $srcdir/foo/mytest.root/mytest.script in the sysroot template, if ++ there is no other reason for a sysroot. ++ ++ Design goals: ++ ++ * independent of other packages which may not be installed (like ++ rsync or Docker, or even "cp") ++ ++ * Simple, easy to review code (i.e. prefer simple naive code over ++ complex efficient code) ++ ++ * The current implementation ist parallel-make-safe, but only in ++ that it uses a lock to prevent parallel access to the testroot. */ ++ ++ ++/* Utility Functions */ ++ ++/* Like xunlink, but it's OK if the file already doesn't exist. */ ++void ++maybe_xunlink (const char *path) ++{ ++ int rv = unlink (path); ++ if (rv < 0 && errno != ENOENT) ++ FAIL_EXIT1 ("unlink (\"%s\"): %m", path); ++} ++ ++/* Like xmkdir, but it's OK if the directory already exists. */ ++void ++maybe_xmkdir (const char *path, mode_t mode) ++{ ++ struct stat st; ++ ++ if (stat (path, &st) == 0 ++ && S_ISDIR (st.st_mode)) ++ return; ++ xmkdir (path, mode); ++} ++ ++/* Temporarily concatenate multiple strings into one. Allows up to 10 ++ temporary results; use strdup () if you need them to be ++ permanent. */ ++static char * ++concat (const char *str, ...) ++{ ++ /* Assume initialized to NULL/zero. */ ++ static char *bufs[10]; ++ static size_t buflens[10]; ++ static int bufn = 0; ++ int n; ++ size_t len; ++ va_list ap, ap2; ++ char *cp; ++ char *next; ++ ++ va_start (ap, str); ++ va_copy (ap2, ap); ++ ++ n = bufn; ++ bufn = (bufn + 1) % 10; ++ len = strlen (str); ++ ++ while ((next = va_arg (ap, char *)) != NULL) ++ len = len + strlen (next); ++ ++ va_end (ap); ++ ++ if (bufs[n] == NULL) ++ { ++ bufs[n] = xmalloc (len + 1); /* NUL */ ++ buflens[n] = len + 1; ++ } ++ else if (buflens[n] < len + 1) ++ { ++ bufs[n] = xrealloc (bufs[n], len + 1); /* NUL */ ++ buflens[n] = len + 1; ++ } ++ ++ strcpy (bufs[n], str); ++ cp = strchr (bufs[n], '\0'); ++ while ((next = va_arg (ap2, char *)) != NULL) ++ { ++ strcpy (cp, next); ++ cp = strchr (cp, '\0'); ++ } ++ *cp = 0; ++ va_end (ap2); ++ ++ return bufs[n]; ++} ++ ++/* Try to mount SRC onto DEST. */ ++static void ++trymount (const char *src, const char *dest) ++{ ++ if (mount (src, dest, "", MS_BIND, NULL) < 0) ++ FAIL_EXIT1 ("can't mount %s onto %s\n", src, dest); ++} ++ ++/* Special case of above for devices like /dev/zero where we have to ++ mount a device over a device, not a directory over a directory. */ ++static void ++devmount (const char *new_root_path, const char *which) ++{ ++ int fd; ++ fd = open (concat (new_root_path, "/dev/", which, NULL), ++ O_CREAT | O_TRUNC | O_RDWR, 0777); ++ xclose (fd); ++ ++ trymount (concat ("/dev/", which, NULL), ++ concat (new_root_path, "/dev/", which, NULL)); ++} ++ ++/* Returns true if the string "looks like" an environement variable ++ being set. */ ++static int ++is_env_setting (const char *a) ++{ ++ int count_name = 0; ++ ++ while (*a) ++ { ++ if (isalnum (*a) || *a == '_') ++ ++count_name; ++ else if (*a == '=' && count_name > 0) ++ return 1; ++ else ++ return 0; ++ ++a; ++ } ++ return 0; ++} ++ ++/* Break the_line into words and store in the_words. Max nwords, ++ returns actual count. */ ++static int ++tokenize (char *the_line, char **the_words, int nwords) ++{ ++ int rv = 0; ++ ++ while (nwords > 0) ++ { ++ /* Skip leading whitespace, if any. */ ++ while (*the_line && isspace (*the_line)) ++ ++the_line; ++ ++ /* End of line? */ ++ if (*the_line == 0) ++ return rv; ++ ++ /* THE_LINE points to a non-whitespace character, so we have a ++ word. */ ++ *the_words = the_line; ++ ++the_words; ++ nwords--; ++ ++rv; ++ ++ /* Skip leading whitespace, if any. */ ++ while (*the_line && ! isspace (*the_line)) ++ ++the_line; ++ ++ /* We now point at the trailing NUL *or* some whitespace. */ ++ if (*the_line == 0) ++ return rv; ++ ++ /* It was whitespace, skip and keep tokenizing. */ ++ *the_line++ = 0; ++ } ++ ++ /* We get here if we filled the words buffer. */ ++ return rv; ++} ++ ++ ++/* Mini-RSYNC implementation. Optimize later. */ ++ ++/* A few routines for an "rsync buffer" which stores the paths we're ++ working on. We continuously grow and shrink the paths in each ++ buffer so there's lot of re-use. */ ++ ++/* We rely on "initialized to zero" to set these up. */ ++typedef struct ++{ ++ char *buf; ++ size_t len; ++ size_t size; ++} path_buf; ++ ++static path_buf spath, dpath; ++ ++static void ++r_setup (char *path, path_buf * pb) ++{ ++ size_t len = strlen (path); ++ if (pb->buf == NULL || pb->size < len + 1) ++ { ++ /* Round up. This is an arbitrary number, just to keep from ++ reallocing too often. */ ++ size_t sz = ALIGN_UP (len + 1, 512); ++ if (pb->buf == NULL) ++ pb->buf = (char *) xmalloc (sz); ++ else ++ pb->buf = (char *) xrealloc (pb->buf, sz); ++ if (pb->buf == NULL) ++ FAIL_EXIT1 ("Out of memory while rsyncing\n"); ++ ++ pb->size = sz; ++ } ++ strcpy (pb->buf, path); ++ pb->len = len; ++} ++ ++static void ++r_append (const char *path, path_buf * pb) ++{ ++ size_t len = strlen (path) + pb->len; ++ if (pb->size < len + 1) ++ { ++ /* Round up */ ++ size_t sz = ALIGN_UP (len + 1, 512); ++ pb->buf = (char *) xrealloc (pb->buf, sz); ++ if (pb->buf == NULL) ++ FAIL_EXIT1 ("Out of memory while rsyncing\n"); ++ ++ pb->size = sz; ++ } ++ strcpy (pb->buf + pb->len, path); ++ pb->len = len; ++} ++ ++static int ++file_exists (char *path) ++{ ++ struct stat st; ++ if (lstat (path, &st) == 0) ++ return 1; ++ return 0; ++} ++ ++static void ++recursive_remove (char *path) ++{ ++ pid_t child; ++ int status; ++ ++ child = fork (); ++ ++ switch (child) { ++ case -1: ++ FAIL_EXIT1 ("Unable to fork"); ++ case 0: ++ /* Child. */ ++ execlp ("rm", "rm", "-rf", path, NULL); ++ default: ++ /* Parent. */ ++ waitpid (child, &status, 0); ++ /* "rm" would have already printed a suitable error message. */ ++ if (! WIFEXITED (status) ++ || WEXITSTATUS (status) != 0) ++ exit (1); ++ ++ break; ++ } ++} ++ ++/* Used for both rsync and the mytest.script "cp" command. */ ++static void ++copy_one_file (const char *sname, const char *dname) ++{ ++ int sfd, dfd; ++ struct stat st; ++ struct utimbuf times; ++ ++ sfd = open (sname, O_RDONLY); ++ if (sfd < 0) ++ FAIL_EXIT1 ("unable to open %s for reading\n", sname); ++ ++ if (fstat (sfd, &st) < 0) ++ FAIL_EXIT1 ("unable to fstat %s\n", sname); ++ ++ dfd = open (dname, O_WRONLY | O_TRUNC | O_CREAT, 0600); ++ if (dfd < 0) ++ FAIL_EXIT1 ("unable to open %s for writing\n", dname); ++ ++ xcopy_file_range (sfd, 0, dfd, 0, st.st_size, 0); ++ ++ xclose (sfd); ++ xclose (dfd); ++ ++ if (chmod (dname, st.st_mode & 0777) < 0) ++ FAIL_EXIT1 ("chmod %s: %s\n", dname, strerror (errno)); ++ ++ times.actime = st.st_atime; ++ times.modtime = st.st_mtime; ++ if (utime (dname, ×) < 0) ++ FAIL_EXIT1 ("utime %s: %s\n", dname, strerror (errno)); ++} ++ ++/* We don't check *everything* about the two files to see if a copy is ++ needed, just the minimum to make sure we get the latest copy. */ ++static int ++need_sync (char *ap, char *bp, struct stat *a, struct stat *b) ++{ ++ if ((a->st_mode & S_IFMT) != (b->st_mode & S_IFMT)) ++ return 1; ++ ++ if (S_ISLNK (a->st_mode)) ++ { ++ int rv; ++ char *al, *bl; ++ ++ if (a->st_size != b->st_size) ++ return 1; ++ ++ al = xreadlink (ap); ++ bl = xreadlink (bp); ++ rv = strcmp (al, bl); ++ free (al); ++ free (bl); ++ if (rv == 0) ++ return 0; /* links are same */ ++ return 1; /* links differ */ ++ } ++ ++ if (verbose) ++ { ++ if (a->st_size != b->st_size) ++ printf ("SIZE\n"); ++ if ((a->st_mode & 0777) != (b->st_mode & 0777)) ++ printf ("MODE\n"); ++ if (a->st_mtime != b->st_mtime) ++ printf ("TIME\n"); ++ } ++ ++ if (a->st_size == b->st_size ++ && ((a->st_mode & 0777) == (b->st_mode & 0777)) ++ && a->st_mtime == b->st_mtime) ++ return 0; ++ ++ return 1; ++} ++ ++static void ++rsync_1 (path_buf * src, path_buf * dest, int and_delete) ++{ ++ DIR *dir; ++ struct dirent *de; ++ struct stat s, d; ++ ++ r_append ("/", src); ++ r_append ("/", dest); ++ ++ if (verbose) ++ printf ("sync %s to %s %s\n", src->buf, dest->buf, ++ and_delete ? "and delete" : ""); ++ ++ size_t staillen = src->len; ++ ++ size_t dtaillen = dest->len; ++ ++ dir = opendir (src->buf); ++ ++ while ((de = readdir (dir)) != NULL) ++ { ++ if (strcmp (de->d_name, ".") == 0 ++ || strcmp (de->d_name, "..") == 0) ++ continue; ++ ++ src->len = staillen; ++ r_append (de->d_name, src); ++ dest->len = dtaillen; ++ r_append (de->d_name, dest); ++ ++ s.st_mode = ~0; ++ d.st_mode = ~0; ++ ++ if (lstat (src->buf, &s) != 0) ++ FAIL_EXIT1 ("%s obtained by readdir, but stat failed.\n", src->buf); ++ ++ /* It's OK if this one fails, since we know the file might be ++ missing. */ ++ lstat (dest->buf, &d); ++ ++ if (! need_sync (src->buf, dest->buf, &s, &d)) ++ { ++ if (S_ISDIR (s.st_mode)) ++ rsync_1 (src, dest, and_delete); ++ continue; ++ } ++ ++ if (d.st_mode != ~0) ++ switch (d.st_mode & S_IFMT) ++ { ++ case S_IFDIR: ++ if (!S_ISDIR (s.st_mode)) ++ { ++ if (verbose) ++ printf ("-D %s\n", dest->buf); ++ recursive_remove (dest->buf); ++ } ++ break; ++ ++ default: ++ if (verbose) ++ printf ("-F %s\n", dest->buf); ++ maybe_xunlink (dest->buf); ++ break; ++ } ++ ++ switch (s.st_mode & S_IFMT) ++ { ++ case S_IFREG: ++ if (verbose) ++ printf ("+F %s\n", dest->buf); ++ copy_one_file (src->buf, dest->buf); ++ break; ++ ++ case S_IFDIR: ++ if (verbose) ++ printf ("+D %s\n", dest->buf); ++ maybe_xmkdir (dest->buf, (s.st_mode & 0777) | 0700); ++ rsync_1 (src, dest, and_delete); ++ break; ++ ++ case S_IFLNK: ++ { ++ char *lp; ++ if (verbose) ++ printf ("+L %s\n", dest->buf); ++ lp = xreadlink (src->buf); ++ xsymlink (lp, dest->buf); ++ free (lp); ++ break; ++ } ++ ++ default: ++ break; ++ } ++ } ++ ++ closedir (dir); ++ src->len = staillen; ++ src->buf[staillen] = 0; ++ dest->len = dtaillen; ++ dest->buf[dtaillen] = 0; ++ ++ if (!and_delete) ++ return; ++ ++ /* The rest of this function removes any files/directories in DEST ++ that do not exist in SRC. This is triggered as part of a ++ preclean or postsclean step. */ ++ ++ dir = opendir (dest->buf); ++ ++ while ((de = readdir (dir)) != NULL) ++ { ++ if (strcmp (de->d_name, ".") == 0 ++ || strcmp (de->d_name, "..") == 0) ++ continue; ++ ++ src->len = staillen; ++ r_append (de->d_name, src); ++ dest->len = dtaillen; ++ r_append (de->d_name, dest); ++ ++ s.st_mode = ~0; ++ d.st_mode = ~0; ++ ++ lstat (src->buf, &s); ++ ++ if (lstat (dest->buf, &d) != 0) ++ FAIL_EXIT1 ("%s obtained by readdir, but stat failed.\n", dest->buf); ++ ++ if (s.st_mode == ~0) ++ { ++ /* dest exists and src doesn't, clean it. */ ++ switch (d.st_mode & S_IFMT) ++ { ++ case S_IFDIR: ++ if (!S_ISDIR (s.st_mode)) ++ { ++ if (verbose) ++ printf ("-D %s\n", dest->buf); ++ recursive_remove (dest->buf); ++ } ++ break; ++ ++ default: ++ if (verbose) ++ printf ("-F %s\n", dest->buf); ++ maybe_xunlink (dest->buf); ++ break; ++ } ++ } ++ } ++ ++ closedir (dir); ++} ++ ++static void ++rsync (char *src, char *dest, int and_delete) ++{ ++ r_setup (src, &spath); ++ r_setup (dest, &dpath); ++ ++ rsync_1 (&spath, &dpath, and_delete); ++} ++ ++ ++int ++main (int argc, char **argv) ++{ ++ pid_t child; ++ char *pristine_root_path; ++ char *new_root_path; ++ char *new_cwd_path; ++ char *new_objdir_path; ++ char *new_srcdir_path; ++ char **new_child_proc; ++ char *command_root; ++ char *command_base; ++ char *command_basename; ++ char *so_base; ++ int do_postclean = 0; ++ ++ uid_t original_uid; ++ gid_t original_gid; ++ int UMAP; ++ int GMAP; ++ /* Used for "%lld %lld 1" so need not be large. */ ++ char tmp[100]; ++ struct stat st; ++ int lock_fd; ++ ++ setbuf (stdout, NULL); ++ ++ /* The command line we're expecting looks like this: ++ env ld.so test-binary ++ ++ We need to peel off any "env" or "ld.so" portion of the command ++ line, and keep track of which env vars we should preserve and ++ which we drop. */ ++ ++ if (argc < 2) ++ { ++ fprintf (stderr, "Usage: containerize \n"); ++ exit (1); ++ } ++ ++ if (strcmp (argv[1], "-v") == 0) ++ { ++ verbose = 1; ++ ++argv; ++ --argc; ++ } ++ ++ if (strcmp (argv[1], "env") == 0) ++ { ++ ++argv; ++ --argc; ++ while (is_env_setting (argv[1])) ++ { ++ /* If there are variables we do NOT want to propogate, this ++ is where the test for them goes. */ ++ { ++ /* Need to keep these. Note that putenv stores a ++ pointer to our argv. */ ++ putenv (argv[1]); ++ } ++ ++argv; ++ --argc; ++ } ++ } ++ ++ if (strcmp (argv[1], support_objdir_elf_ldso) == 0) ++ { ++ ++argv; ++ --argc; ++ while (argv[1][0] == '-') ++ { ++ if (strcmp (argv[1], "--library-path") == 0) ++ { ++ ++argv; ++ --argc; ++ } ++ ++argv; ++ --argc; ++ } ++ } ++ ++ pristine_root_path = strdup (concat (support_objdir_root, ++ "/testroot.pristine", NULL)); ++ new_root_path = strdup (concat (support_objdir_root, ++ "/testroot.root", NULL)); ++ new_cwd_path = get_current_dir_name (); ++ new_child_proc = argv + 1; ++ ++ lock_fd = open (concat (pristine_root_path, "/lock.fd", NULL), ++ O_CREAT | O_TRUNC | O_RDWR, 0666); ++ if (lock_fd < 0) ++ FAIL_EXIT1 ("Cannot create testroot lock.\n"); ++ ++ while (flock (lock_fd, LOCK_EX) != 0) ++ { ++ if (errno != EINTR) ++ FAIL_EXIT1 ("Cannot lock testroot.\n"); ++ } ++ ++ xmkdirp (new_root_path, 0755); ++ ++ /* We look for extra setup info in a subdir in the same spot as the ++ test, with the same name but a ".root" extension. This is that ++ directory. We try to look in the source tree if the path we're ++ given refers to the build tree, but we rely on the path to be ++ absolute. This is what the glibc makefiles do. */ ++ command_root = concat (argv[1], ".root", NULL); ++ if (strncmp (command_root, support_objdir_root, ++ strlen (support_objdir_root)) == 0 ++ && command_root[strlen (support_objdir_root)] == '/') ++ command_root = concat (support_srcdir_root, ++ argv[1] + strlen (support_objdir_root), ++ ".root", NULL); ++ command_root = strdup (command_root); ++ ++ /* This cuts off the ".root" we appended above. */ ++ command_base = strdup (command_root); ++ command_base[strlen (command_base) - 5] = 0; ++ ++ /* This is the basename of the test we're running. */ ++ command_basename = strrchr (command_base, '/'); ++ if (command_basename == NULL) ++ command_basename = command_base; ++ else ++ ++command_basename; ++ ++ /* Shared object base directory. */ ++ so_base = strdup (argv[1]); ++ if (strrchr (so_base, '/') != NULL) ++ strrchr (so_base, '/')[1] = 0; ++ ++ if (file_exists (concat (command_root, "/postclean.req", NULL))) ++ do_postclean = 1; ++ ++ rsync (pristine_root_path, new_root_path, ++ file_exists (concat (command_root, "/preclean.req", NULL))); ++ ++ if (stat (command_root, &st) >= 0 ++ && S_ISDIR (st.st_mode)) ++ rsync (command_root, new_root_path, 0); ++ ++ new_objdir_path = strdup (concat (new_root_path, ++ support_objdir_root, NULL)); ++ new_srcdir_path = strdup (concat (new_root_path, ++ support_srcdir_root, NULL)); ++ ++ /* new_cwd_path starts with '/' so no "/" needed between the two. */ ++ xmkdirp (concat (new_root_path, new_cwd_path, NULL), 0755); ++ xmkdirp (new_srcdir_path, 0755); ++ xmkdirp (new_objdir_path, 0755); ++ ++ original_uid = getuid (); ++ original_gid = getgid (); ++ ++ /* Handle the cp/mv/rm "script" here. */ ++ { ++ char *the_line = NULL; ++ size_t line_len = 0; ++ char *fname = concat (command_root, "/", ++ command_basename, ".script", NULL); ++ char *the_words[3]; ++ FILE *f = fopen (fname, "r"); ++ ++ if (verbose && f) ++ fprintf (stderr, "running %s\n", fname); ++ ++ if (f == NULL) ++ { ++ /* Try foo.script instead of foo.root/foo.script, as a shortcut. */ ++ fname = concat (command_base, ".script", NULL); ++ f = fopen (fname, "r"); ++ if (verbose && f) ++ fprintf (stderr, "running %s\n", fname); ++ } ++ ++ /* Note that we do NOT look for a Makefile-generated foo.script in ++ the build directory. If that is ever needed, this is the place ++ to add it. */ ++ ++ /* This is where we "interpret" the mini-script which is .script. */ ++ if (f != NULL) ++ { ++ while (getline (&the_line, &line_len, f) > 0) ++ { ++ int nt = tokenize (the_line, the_words, 3); ++ int i; ++ ++ for (i = 1; i < nt; ++i) ++ { ++ if (memcmp (the_words[i], "$B/", 3) == 0) ++ the_words[i] = concat (support_objdir_root, ++ the_words[i] + 2, NULL); ++ else if (memcmp (the_words[i], "$S/", 3) == 0) ++ the_words[i] = concat (support_srcdir_root, ++ the_words[i] + 2, NULL); ++ else if (memcmp (the_words[i], "$I/", 3) == 0) ++ the_words[i] = concat (new_root_path, ++ support_install_prefix, ++ the_words[i] + 2, NULL); ++ else if (memcmp (the_words[i], "$L/", 3) == 0) ++ the_words[i] = concat (new_root_path, ++ support_libdir_prefix, ++ the_words[i] + 2, NULL); ++ else if (the_words[i][0] == '/') ++ the_words[i] = concat (new_root_path, ++ the_words[i], NULL); ++ } ++ ++ if (nt == 3 && the_words[2][strlen (the_words[2]) - 1] == '/') ++ { ++ char *r = strrchr (the_words[1], '/'); ++ if (r) ++ the_words[2] = concat (the_words[2], r + 1, NULL); ++ else ++ the_words[2] = concat (the_words[2], the_words[1], NULL); ++ } ++ ++ if (nt == 2 && strcmp (the_words[0], "so") == 0) ++ { ++ the_words[2] = concat (new_root_path, support_libdir_prefix, ++ "/", the_words[1], NULL); ++ the_words[1] = concat (so_base, the_words[1], NULL); ++ copy_one_file (the_words[1], the_words[2]); ++ } ++ else if (nt == 3 && strcmp (the_words[0], "cp") == 0) ++ { ++ copy_one_file (the_words[1], the_words[2]); ++ } ++ else if (nt == 3 && strcmp (the_words[0], "mv") == 0) ++ { ++ if (rename (the_words[1], the_words[2]) < 0) ++ FAIL_EXIT1 ("rename %s -> %s: %s", the_words[1], ++ the_words[2], strerror (errno)); ++ } ++ else if (nt == 3 && strcmp (the_words[0], "chmod") == 0) ++ { ++ long int m; ++ m = strtol (the_words[1], NULL, 0); ++ if (chmod (the_words[2], m) < 0) ++ FAIL_EXIT1 ("chmod %s: %s\n", ++ the_words[2], strerror (errno)); ++ ++ } ++ else if (nt == 2 && strcmp (the_words[0], "rm") == 0) ++ { ++ maybe_xunlink (the_words[1]); ++ } ++ else if (nt > 0 && the_words[0][0] != '#') ++ { ++ printf ("\033[31minvalid [%s]\033[0m\n", the_words[0]); ++ } ++ } ++ fclose (f); ++ } ++ } ++ ++#ifdef CLONE_NEWNS ++ /* The unshare here gives us our own spaces and capabilities. */ ++ if (unshare (CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNS) < 0) ++ { ++ /* Older kernels may not support all the options, or security ++ policy may block this call. */ ++ if (errno == EINVAL || errno == EPERM) ++ FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (errno)); ++ else ++ FAIL_EXIT1 ("unable to unshare user/fs: %s", strerror (errno)); ++ } ++#else ++ /* Some targets may not support unshare at all. */ ++ FAIL_UNSUPPORTED ("unshare support missing"); ++#endif ++ ++ /* Some systems, by default, all mounts leak out of the namespace. */ ++ if (mount ("none", "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0) ++ FAIL_EXIT1 ("could not create a private mount namespace\n"); ++ ++ trymount (support_srcdir_root, new_srcdir_path); ++ trymount (support_objdir_root, new_objdir_path); ++ ++ xmkdirp (concat (new_root_path, "/dev", NULL), 0755); ++ devmount (new_root_path, "null"); ++ devmount (new_root_path, "zero"); ++ devmount (new_root_path, "urandom"); ++ ++ /* We're done with the "old" root, switch to the new one. */ ++ if (chroot (new_root_path) < 0) ++ FAIL_EXIT1 ("Can't chroot to %s - ", new_root_path); ++ ++ if (chdir (new_cwd_path) < 0) ++ FAIL_EXIT1 ("Can't cd to new %s - ", new_cwd_path); ++ ++ /* To complete the containerization, we need to fork () at least ++ once. We can't exec, nor can we somehow link the new child to ++ our parent. So we run the child and propogate it's exit status ++ up. */ ++ child = fork (); ++ if (child < 0) ++ FAIL_EXIT1 ("Unable to fork"); ++ else if (child > 0) ++ { ++ /* Parent. */ ++ int status; ++ waitpid (child, &status, 0); ++ ++ /* There's a bit of magic here, since the buildroot is mounted ++ in our space, the paths are still valid, and since the mounts ++ aren't recursive, it sees *only* the built root, not anything ++ we would normally se if we rsync'd to "/" like mounted /dev ++ files. */ ++ if (do_postclean) ++ rsync (pristine_root_path, new_root_path, 1); ++ ++ if (WIFEXITED (status)) ++ exit (WEXITSTATUS (status)); ++ ++ if (WIFSIGNALED (status)) ++ { ++ printf ("%%SIGNALLED%%\n"); ++ exit (77); ++ } ++ ++ printf ("%%EXITERROR%%\n"); ++ exit (78); ++ } ++ ++ /* The rest is the child process, which is now PID 1 and "in" the ++ new root. */ ++ ++ maybe_xmkdir ("/tmp", 0755); ++ ++ /* Now that we're pid 1 (effectively "root") we can mount /proc */ ++ maybe_xmkdir ("/proc", 0777); ++ if (mount ("proc", "/proc", "proc", 0, NULL) < 0) ++ FAIL_EXIT1 ("Unable to mount /proc: "); ++ ++ /* We map our original UID to the same UID in the container so we ++ can own our own files normally. */ ++ UMAP = open ("/proc/self/uid_map", O_WRONLY); ++ if (UMAP < 0) ++ FAIL_EXIT1 ("can't write to /proc/self/uid_map\n"); ++ ++ sprintf (tmp, "%lld %lld 1\n", ++ (long long) original_uid, (long long) original_uid); ++ write (UMAP, tmp, strlen (tmp)); ++ xclose (UMAP); ++ ++ /* We must disable setgroups () before we can map our groups, else we ++ get EPERM. */ ++ GMAP = open ("/proc/self/setgroups", O_WRONLY); ++ if (GMAP >= 0) ++ { ++ /* We support kernels old enough to not have this. */ ++ write (GMAP, "deny\n", 5); ++ xclose (GMAP); ++ } ++ ++ /* We map our original GID to the same GID in the container so we ++ can own our own files normally. */ ++ GMAP = open ("/proc/self/gid_map", O_WRONLY); ++ if (GMAP < 0) ++ FAIL_EXIT1 ("can't write to /proc/self/gid_map\n"); ++ ++ sprintf (tmp, "%lld %lld 1\n", ++ (long long) original_gid, (long long) original_gid); ++ write (GMAP, tmp, strlen (tmp)); ++ xclose (GMAP); ++ ++ /* Now run the child. */ ++ execvp (new_child_proc[0], new_child_proc); ++ ++ /* Or don't run the child? */ ++ FAIL_EXIT1 ("Unable to exec %s\n", new_child_proc[0]); ++ ++ /* Because gcc won't know error () never returns... */ ++ exit (EXIT_UNSUPPORTED); ++} +diff --git a/support/true-container.c b/support/true-container.c +new file mode 100644 +index 0000000000000000..57dc57e252a96acc +--- /dev/null ++++ b/support/true-container.c +@@ -0,0 +1,26 @@ ++/* Minimal /bin/true for in-container use. ++ Copyright (C) 2018 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 ++ . */ ++ ++/* Implements the in-container /bin/true, which always returns true ++ (0). */ ++ ++int ++main (void) ++{ ++ return 0; ++} +diff --git a/support/tst-support_blob_repeat.c b/support/tst-support_blob_repeat.c +new file mode 100644 +index 0000000000000000..1978c14488106ff2 +--- /dev/null ++++ b/support/tst-support_blob_repeat.c +@@ -0,0 +1,85 @@ ++/* Tests for ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ struct support_blob_repeat repeat ++ = support_blob_repeat_allocate ("5", 1, 5); ++ TEST_COMPARE_BLOB (repeat.start, repeat.size, "55555", 5); ++ support_blob_repeat_free (&repeat); ++ ++ repeat = support_blob_repeat_allocate ("ABC", 3, 3); ++ TEST_COMPARE_BLOB (repeat.start, repeat.size, "ABCABCABC", 9); ++ support_blob_repeat_free (&repeat); ++ ++ repeat = support_blob_repeat_allocate ("abc", 4, 3); ++ TEST_COMPARE_BLOB (repeat.start, repeat.size, "abc\0abc\0abc", 12); ++ support_blob_repeat_free (&repeat); ++ ++ size_t gigabyte = 1U << 30; ++ repeat = support_blob_repeat_allocate ("X", 1, gigabyte + 1); ++ if (repeat.start == NULL) ++ puts ("warning: not enough memory for 1 GiB mapping"); ++ else ++ { ++ TEST_COMPARE (repeat.size, gigabyte + 1); ++ { ++ unsigned char *p = repeat.start; ++ for (size_t i = 0; i < gigabyte + 1; ++i) ++ if (p[i] != 'X') ++ FAIL_EXIT1 ("invalid byte 0x%02x at %zu", p[i], i); ++ ++ /* Check that there is no sharing across the mapping. */ ++ p[0] = 'Y'; ++ p[1U << 24] = 'Z'; ++ for (size_t i = 0; i < gigabyte + 1; ++i) ++ if (i == 0) ++ TEST_COMPARE (p[i], 'Y'); ++ else if (i == 1U << 24) ++ TEST_COMPARE (p[i], 'Z'); ++ else if (p[i] != 'X') ++ FAIL_EXIT1 ("invalid byte 0x%02x at %zu", p[i], i); ++ } ++ } ++ support_blob_repeat_free (&repeat); ++ ++ repeat = support_blob_repeat_allocate ("012345678", 9, 10 * 1000 * 1000); ++ if (repeat.start == NULL) ++ puts ("warning: not enough memory for large mapping"); ++ else ++ { ++ unsigned char *p = repeat.start; ++ for (int i = 0; i < 10 * 1000 * 1000; ++i) ++ for (int j = 0; j <= 8; ++j) ++ if (p[i * 9 + j] != '0' + j) ++ { ++ printf ("error: element %d index %d\n", i, j); ++ TEST_COMPARE (p[i * 9 + j], '0' + j); ++ } ++ } ++ support_blob_repeat_free (&repeat); ++ ++ return 0; ++} ++ ++#include +diff --git a/support/tst-test_compare_string.c b/support/tst-test_compare_string.c +new file mode 100644 +index 0000000000000000..2a4b258587a7c8ec +--- /dev/null ++++ b/support/tst-test_compare_string.c +@@ -0,0 +1,107 @@ ++/* Basic test for the TEST_COMPARE_STRING macro. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++ ++static void ++subprocess (void *closure) ++{ ++ /* These tests should fail. They were chosen to cover differences ++ in length (with the same contents), single-bit mismatches, and ++ mismatching null pointers. */ ++ TEST_COMPARE_STRING ("", NULL); /* Line 29. */ ++ TEST_COMPARE_STRING ("X", ""); /* Line 30. */ ++ TEST_COMPARE_STRING (NULL, "X"); /* Line 31. */ ++ TEST_COMPARE_STRING ("abcd", "abcD"); /* Line 32. */ ++ TEST_COMPARE_STRING ("abcd", NULL); /* Line 33. */ ++ TEST_COMPARE_STRING (NULL, "abcd"); /* Line 34. */ ++} ++ ++/* Same contents, different addresses. */ ++char buffer_abc_1[] = "abc"; ++char buffer_abc_2[] = "abc"; ++ ++static int ++do_test (void) ++{ ++ /* This should succeed. Even if the pointers and array contents are ++ different, zero-length inputs are not different. */ ++ TEST_COMPARE_STRING (NULL, NULL); ++ TEST_COMPARE_STRING ("", ""); ++ TEST_COMPARE_STRING (buffer_abc_1, buffer_abc_2); ++ TEST_COMPARE_STRING (buffer_abc_1, "abc"); ++ ++ struct support_capture_subprocess proc = support_capture_subprocess ++ (&subprocess, NULL); ++ ++ /* Discard the reported error. */ ++ support_record_failure_reset (); ++ ++ puts ("info: *** subprocess output starts ***"); ++ fputs (proc.out.buffer, stdout); ++ puts ("info: *** subprocess output ends ***"); ++ ++ TEST_VERIFY ++ (strcmp (proc.out.buffer, ++"tst-test_compare_string.c:29: error: blob comparison failed\n" ++" left string: 0 bytes\n" ++" right string: NULL\n" ++"tst-test_compare_string.c:30: error: blob comparison failed\n" ++" left string: 1 bytes\n" ++" right string: 0 bytes\n" ++" left (evaluated from \"X\"):\n" ++" \"X\"\n" ++" 58\n" ++"tst-test_compare_string.c:31: error: blob comparison failed\n" ++" left string: NULL\n" ++" right string: 1 bytes\n" ++" right (evaluated from \"X\"):\n" ++" \"X\"\n" ++" 58\n" ++"tst-test_compare_string.c:32: error: blob comparison failed\n" ++" string length: 4 bytes\n" ++" left (evaluated from \"abcd\"):\n" ++" \"abcd\"\n" ++" 61 62 63 64\n" ++" right (evaluated from \"abcD\"):\n" ++" \"abcD\"\n" ++" 61 62 63 44\n" ++"tst-test_compare_string.c:33: error: blob comparison failed\n" ++" left string: 4 bytes\n" ++" right string: NULL\n" ++" left (evaluated from \"abcd\"):\n" ++" \"abcd\"\n" ++" 61 62 63 64\n" ++"tst-test_compare_string.c:34: error: blob comparison failed\n" ++" left string: NULL\n" ++" right string: 4 bytes\n" ++" right (evaluated from \"abcd\"):\n" ++" \"abcd\"\n" ++" 61 62 63 64\n" ++ ) == 0); ++ ++ /* Check that there is no output on standard error. */ ++ support_capture_subprocess_check (&proc, "TEST_COMPARE_STRING", ++ 0, sc_allow_stdout); ++ ++ return 0; ++} ++ ++#include +diff --git a/support/xcopy_file_range.c b/support/xcopy_file_range.c +new file mode 100644 +index 0000000000000000..b3501a4d5ec3fdfd +--- /dev/null ++++ b/support/xcopy_file_range.c +@@ -0,0 +1,32 @@ ++/* copy_file_range with error checking. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++ ++ssize_t ++xcopy_file_range (int infd, off64_t *pinoff, int outfd, off64_t *poutoff, ++ size_t length, unsigned int flags) ++{ ++ ssize_t status = support_copy_file_range (infd, pinoff, outfd, ++ poutoff, length, flags); ++ if (status == -1) ++ FAIL_EXIT1 ("cannot copy file: %m\n"); ++ return status; ++} +diff --git a/support/xmkdirp.c b/support/xmkdirp.c +new file mode 100644 +index 0000000000000000..fada0452eafe269e +--- /dev/null ++++ b/support/xmkdirp.c +@@ -0,0 +1,66 @@ ++/* Error-checking replacement for "mkdir -p". ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* Equivalent of "mkdir -p". Any failures cause FAIL_EXIT1 so no ++ return code is needed. */ ++ ++void ++xmkdirp (const char *path, mode_t mode) ++{ ++ struct stat s; ++ const char *slash_p; ++ int rv; ++ ++ if (path[0] == 0) ++ return; ++ ++ if (stat (path, &s) == 0) ++ { ++ if (S_ISDIR (s.st_mode)) ++ return; ++ errno = EEXIST; ++ FAIL_EXIT1 ("mkdir_p (\"%s\", 0%o): %m", path, mode); ++ } ++ ++ slash_p = strrchr (path, '/'); ++ if (slash_p != NULL) ++ { ++ while (slash_p > path && slash_p[-1] == '/') ++ --slash_p; ++ if (slash_p > path) ++ { ++ char *parent = xstrndup (path, slash_p - path); ++ xmkdirp (parent, mode); ++ free (parent); ++ } ++ } ++ ++ rv = mkdir (path, mode); ++ if (rv != 0) ++ FAIL_EXIT1 ("mkdir_p (\"%s\", 0%o): %m", path, mode); ++ ++ return; ++} +diff --git a/support/xsymlink.c b/support/xsymlink.c +new file mode 100644 +index 0000000000000000..0f3edf640a1a99a6 +--- /dev/null ++++ b/support/xsymlink.c +@@ -0,0 +1,29 @@ ++/* Error-checking replacement for "symlink". ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++ ++#include ++ ++void ++xsymlink (const char *target, const char *linkpath) ++{ ++ if (symlink (target, linkpath) < 0) ++ FAIL_EXIT1 ("symlink (\"%s\", \"%s\")", target, linkpath); ++} +diff --git a/support/xunistd.h b/support/xunistd.h +index 5fe5dae818def4ec..f99f362cb4763c5b 100644 +--- a/support/xunistd.h ++++ b/support/xunistd.h +@@ -43,6 +43,10 @@ void xunlink (const char *path); + long xsysconf (int name); + long long xlseek (int fd, long long offset, int whence); + void xftruncate (int fd, long long length); ++void xsymlink (const char *target, const char *linkpath); ++ ++/* Equivalent of "mkdir -p". */ ++void xmkdirp (const char *, mode_t); + + /* Read the link at PATH. The caller should free the returned string + with free. */ +@@ -60,6 +64,9 @@ void *xmmap (void *addr, size_t length, int prot, int flags, int fd); + void xmprotect (void *addr, size_t length, int prot); + void xmunmap (void *addr, size_t length); + ++ssize_t xcopy_file_range(int fd_in, loff_t *off_in, int fd_out, ++ loff_t *off_out, size_t len, unsigned int flags); ++ + __END_DECLS + + #endif /* SUPPORT_XUNISTD_H */ diff --git a/glibc-rh1638523-2.patch b/glibc-rh1638523-2.patch new file mode 100755 index 0000000..cf3ade5 --- /dev/null +++ b/glibc-rh1638523-2.patch @@ -0,0 +1,80 @@ +commit 6c3a8a9d868a8deddf0d6dcc785b6d120de90523 +Author: Paul Pluzhnikov +Date: Fri Aug 24 18:08:51 2018 -0700 + + Fix BZ#23400 (creating temporary files in source tree), and undefined behavior in test. + +diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c +index e7837f98c19fc4bf..d1aa69106ccf6ac5 100644 +--- a/stdlib/test-bz22786.c ++++ b/stdlib/test-bz22786.c +@@ -26,28 +26,20 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + + static int + do_test (void) + { +- const char dir[] = "bz22786"; +- const char lnk[] = "bz22786/symlink"; ++ const char *dir = support_create_temp_directory ("bz22786."); ++ const char *lnk = xasprintf ("%s/symlink", dir); ++ const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1; + +- rmdir (dir); +- if (mkdir (dir, 0755) != 0 && errno != EEXIST) +- { +- printf ("mkdir %s: %m\n", dir); +- return EXIT_FAILURE; +- } +- if (symlink (".", lnk) != 0 && errno != EEXIST) +- { +- printf ("symlink (%s, %s): %m\n", dir, lnk); +- return EXIT_FAILURE; +- } +- +- const size_t path_len = (size_t) INT_MAX + 1; ++ TEST_VERIFY_EXIT (symlink (".", lnk) == 0); + + DIAG_PUSH_NEEDS_COMMENT; + #if __GNUC_PREREQ (7, 0) +@@ -55,20 +47,14 @@ do_test (void) + allocation to succeed for the test to work. */ + DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); + #endif +- char *path = malloc (path_len); ++ char *path = xmalloc (path_len); + DIAG_POP_NEEDS_COMMENT; + +- if (path == NULL) +- { +- printf ("malloc (%zu): %m\n", path_len); +- return EXIT_UNSUPPORTED; +- } +- +- /* Construct very long path = "bz22786/symlink/aaaa....." */ +- char *p = mempcpy (path, lnk, sizeof (lnk) - 1); ++ /* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */ ++ char *p = mempcpy (path, lnk, strlen (lnk)); + *(p++) = '/'; +- memset (p, 'a', path_len - (path - p) - 2); +- p[path_len - (path - p) - 1] = '\0'; ++ memset (p, 'a', path_len - (p - path) - 2); ++ p[path_len - (p - path) - 1] = '\0'; + + /* This call crashes before the fix for bz22786 on 32-bit platforms. */ + p = realpath (path, NULL); +@@ -81,7 +67,6 @@ do_test (void) + + /* Cleanup. */ + unlink (lnk); +- rmdir (dir); + + return 0; + } diff --git a/glibc-rh1638523-3.patch b/glibc-rh1638523-3.patch new file mode 100755 index 0000000..8ad2241 --- /dev/null +++ b/glibc-rh1638523-3.patch @@ -0,0 +1,55 @@ +commit 3bad2358d67d371497079bba4f8eca9c0096f4e2 +Author: Stefan Liebler +Date: Thu Aug 30 08:44:32 2018 +0200 + + Test stdlib/test-bz22786 exits now with unsupported if malloc fails. + + The test tries to allocate more than 2^31 bytes which will always fail on s390 + as it has maximum 2^31bit of memory. + Before commit 6c3a8a9d868a8deddf0d6dcc785b6d120de90523, this test returned + unsupported if malloc fails. This patch re enables this behaviour. + + Furthermore support_delete_temp_files() failed to remove the temp directory + in this case as it is not empty due to the created symlink. + Thus the creation of the symlink is moved behind malloc. + + Reviewed-by: Carlos O'Donell + + ChangeLog: + + * stdlib/test-bz22786.c (do_test): Return EXIT_UNSUPPORTED + if malloc fails. + +diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c +index d1aa69106ccf6ac5..777bf9180f4b5022 100644 +--- a/stdlib/test-bz22786.c ++++ b/stdlib/test-bz22786.c +@@ -39,16 +39,25 @@ do_test (void) + const char *lnk = xasprintf ("%s/symlink", dir); + const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1; + +- TEST_VERIFY_EXIT (symlink (".", lnk) == 0); +- + DIAG_PUSH_NEEDS_COMMENT; + #if __GNUC_PREREQ (7, 0) + /* GCC 7 warns about too-large allocations; here we need such + allocation to succeed for the test to work. */ + DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); + #endif +- char *path = xmalloc (path_len); ++ char *path = malloc (path_len); + DIAG_POP_NEEDS_COMMENT; ++ if (path == NULL) ++ { ++ printf ("malloc (%zu): %m\n", path_len); ++ /* On 31-bit s390 the malloc will always fail as we do not have ++ so much memory, and we want to mark the test unsupported. ++ Likewise on systems with little physical memory the test will ++ fail and should be unsupported. */ ++ return EXIT_UNSUPPORTED; ++ } ++ ++ TEST_VERIFY_EXIT (symlink (".", lnk) == 0); + + /* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */ + char *p = mempcpy (path, lnk, strlen (lnk)); diff --git a/glibc-rh1638523-4.patch b/glibc-rh1638523-4.patch new file mode 100755 index 0000000..d5e0efb --- /dev/null +++ b/glibc-rh1638523-4.patch @@ -0,0 +1,65 @@ +commit f5e7e95921847bd83186bfe621fc2b48c4de5477 +Author: Florian Weimer +Date: Tue Oct 30 13:11:47 2018 +0100 + + stdlib/test-bz22786: Avoid spurious test failures using alias mappings + + On systems without enough random-access memory, stdlib/test-bz22786 + will go deeply into swap and time out, even with a substantial + TIMEOUTFACTOR. This commit adds a facility to construct repeating + strings with alias mappings, so that the requirement for physical + memory, and uses it in stdlib/test-bz22786. + +Adjusted here for conflicts due to the previous support/ backport in +glibc-rh1638523-1.patch. + +diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c +index 777bf9180f4b5022..bb1e04f2debe9042 100644 +--- a/stdlib/test-bz22786.c ++++ b/stdlib/test-bz22786.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -39,17 +40,12 @@ do_test (void) + const char *lnk = xasprintf ("%s/symlink", dir); + const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1; + +- DIAG_PUSH_NEEDS_COMMENT; +-#if __GNUC_PREREQ (7, 0) +- /* GCC 7 warns about too-large allocations; here we need such +- allocation to succeed for the test to work. */ +- DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); +-#endif +- char *path = malloc (path_len); +- DIAG_POP_NEEDS_COMMENT; ++ struct support_blob_repeat repeat ++ = support_blob_repeat_allocate ("a", 1, path_len); ++ char *path = repeat.start; + if (path == NULL) + { +- printf ("malloc (%zu): %m\n", path_len); ++ printf ("Repeated allocation (%zu bytes): %m\n", path_len); + /* On 31-bit s390 the malloc will always fail as we do not have + so much memory, and we want to mark the test unsupported. + Likewise on systems with little physical memory the test will +@@ -62,7 +58,6 @@ do_test (void) + /* Construct very long path = "/tmp/bz22786.XXXX/symlink/aaaa....." */ + char *p = mempcpy (path, lnk, strlen (lnk)); + *(p++) = '/'; +- memset (p, 'a', path_len - (p - path) - 2); + p[path_len - (p - path) - 1] = '\0'; + + /* This call crashes before the fix for bz22786 on 32-bit platforms. */ +@@ -76,6 +71,7 @@ do_test (void) + + /* Cleanup. */ + unlink (lnk); ++ support_blob_repeat_free (&repeat); + + return 0; + } diff --git a/glibc-rh1638523-5.patch b/glibc-rh1638523-5.patch new file mode 100755 index 0000000..c0ed47d --- /dev/null +++ b/glibc-rh1638523-5.patch @@ -0,0 +1,51 @@ +commit 07da99aad93c9364acb7efdab47c27ba698f6313 +Author: Florian Weimer +Date: Tue Oct 30 13:55:01 2018 +0100 + + stdlib/tst-strtod-overflow: Switch to support_blob_repeat + + This is another test with an avoidable large memory allocation. + +diff --git a/stdlib/tst-strtod-overflow.c b/stdlib/tst-strtod-overflow.c +index d14638d68ef4f471..dc53c1e521443e1d 100644 +--- a/stdlib/tst-strtod-overflow.c ++++ b/stdlib/tst-strtod-overflow.c +@@ -19,6 +19,8 @@ + #include + #include + #include ++#include ++#include + + #define EXPONENT "e-2147483649" + #define SIZE 214748364 +@@ -26,21 +28,23 @@ + static int + do_test (void) + { +- char *p = malloc (1 + SIZE + sizeof (EXPONENT)); +- if (p == NULL) ++ struct support_blob_repeat repeat = support_blob_repeat_allocate ++ ("0", 1, 1 + SIZE + sizeof (EXPONENT)); ++ if (repeat.size == 0) + { +- puts ("malloc failed, cannot test for overflow"); +- return 0; ++ puts ("warning: memory allocation failed, cannot test for overflow"); ++ return EXIT_UNSUPPORTED; + } ++ char *p = repeat.start; + p[0] = '1'; +- memset (p + 1, '0', SIZE); + memcpy (p + 1 + SIZE, EXPONENT, sizeof (EXPONENT)); + double d = strtod (p, NULL); + if (d != 0) + { +- printf ("strtod returned wrong value: %a\n", d); ++ printf ("error: strtod returned wrong value: %a\n", d); + return 1; + } ++ support_blob_repeat_free (&repeat); + return 0; + } + diff --git a/glibc-rh1638523-6.patch b/glibc-rh1638523-6.patch new file mode 100755 index 0000000..ea8509f --- /dev/null +++ b/glibc-rh1638523-6.patch @@ -0,0 +1,30 @@ +commit 60708030536df82616c16aa2f14f533c4362b969 +Author: Florian Weimer +Date: Tue Oct 30 13:56:40 2018 +0100 + + stdlib/test-bz22786: Avoid memory leaks in the test itself + +diff --git a/stdlib/test-bz22786.c b/stdlib/test-bz22786.c +index bb1e04f2debe9042..8035e8a394e7d034 100644 +--- a/stdlib/test-bz22786.c ++++ b/stdlib/test-bz22786.c +@@ -36,8 +36,8 @@ + static int + do_test (void) + { +- const char *dir = support_create_temp_directory ("bz22786."); +- const char *lnk = xasprintf ("%s/symlink", dir); ++ char *dir = support_create_temp_directory ("bz22786."); ++ char *lnk = xasprintf ("%s/symlink", dir); + const size_t path_len = (size_t) INT_MAX + strlen (lnk) + 1; + + struct support_blob_repeat repeat +@@ -72,6 +72,8 @@ do_test (void) + /* Cleanup. */ + unlink (lnk); + support_blob_repeat_free (&repeat); ++ free (lnk); ++ free (dir); + + return 0; + } diff --git a/glibc-rh1639343-1.patch b/glibc-rh1639343-1.patch new file mode 100755 index 0000000..51d2226 --- /dev/null +++ b/glibc-rh1639343-1.patch @@ -0,0 +1,35 @@ +commit f9b645b4b0a10c43753296ce3fa40053fa44606a +Author: Mike Frysinger +Date: Wed Apr 24 13:32:22 2019 +0200 + + memusagestat: use local glibc when linking [BZ #18465] + + The memusagestat is the only binary that has its own link line which + causes it to be linked against the existing installed C library. It + has been this way since it was originally committed in 1999, but I + don't see any reason as to why. Since we want all the programs we + build locally to be against the new copy of glibc, change the build + to be like all other programs. + +diff --git a/malloc/Makefile b/malloc/Makefile +index 388cf7e9ee3a2569..228a1279a5960d8c 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -131,6 +131,7 @@ ifneq ($(cross-compiling),yes) + # If the gd library is available we build the `memusagestat' program. + ifneq ($(LIBGD),no) + others: $(objpfx)memusage ++others += memusagestat + install-bin = memusagestat + install-bin-script += memusage + generated += memusagestat memusage +@@ -154,8 +155,7 @@ cpp-srcs-left := $(memusagestat-modules) + lib := memusagestat + include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left)) + +-$(objpfx)memusagestat: $(memusagestat-modules:%=$(objpfx)%.o) +- $(LINK.o) -o $@ $^ $(libgd-LDFLAGS) -lgd -lpng -lz -lm ++LDLIBS-memusagestat = $(libgd-LDFLAGS) -lgd -lpng -lz -lm + + ifeq ($(run-built-tests),yes) + ifeq (yes,$(build-shared)) diff --git a/glibc-rh1639343-2.patch b/glibc-rh1639343-2.patch new file mode 100755 index 0000000..c5e4aa5 --- /dev/null +++ b/glibc-rh1639343-2.patch @@ -0,0 +1,90 @@ +commit 94a4e9e4f401ffe829a992820439977ead0a0ce7 +Author: Florian Weimer +Date: Thu Apr 25 10:41:43 2019 +0200 + + Extend BIND_NOW to installed programs with --enable-bind-now + + Commit 2d6ab5df3b675e96ee587ae6a8c2ce004c6b1ba9 ("Document and fix + --enable-bind-now [BZ #21015]") extended BIND_NOW to all installed + shared objects. This change also covers installed programs. + + Reviewed-by: Carlos O'Donell + +diff --git a/INSTALL b/INSTALL +index d6c8e899fbb47dac..d56e102ec9ed3281 100644 +--- a/INSTALL ++++ b/INSTALL +@@ -169,10 +169,10 @@ if 'CFLAGS' is specified it must enable optimization. For example: + protection. + + '--enable-bind-now' +- Disable lazy binding for installed shared objects. This provides +- additional security hardening because it enables full RELRO and a +- read-only global offset table (GOT), at the cost of slightly +- increased program load times. ++ Disable lazy binding for installed shared objects and programs. ++ This provides additional security hardening because it enables full ++ RELRO and a read-only global offset table (GOT), at the cost of ++ slightly increased program load times. + + '--enable-pt_chown' + The file 'pt_chown' is a helper binary for 'grantpt' (*note +diff --git a/Makeconfig b/Makeconfig +index 8dc2fec9dc683416..742c0c0783a14bfa 100644 +--- a/Makeconfig ++++ b/Makeconfig +@@ -398,6 +398,8 @@ endif + # test modules. + ifeq ($(bind-now),yes) + LDFLAGS-lib.so += -Wl,-z,now ++# Extra flags for dynamically linked non-test main programs. ++link-extra-flags += -Wl,-z,now + endif + + # Command to run after every final link (executable or shared object). +@@ -426,7 +428,7 @@ ifndef +link-pie + $(link-extra-libs) + +link-pie-after-libc = $(+postctorS) $(+postinit) + define +link-pie +-$(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-libc) $(+link-pie-after-libc) ++$(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) $(+link-pie-after-libc) + $(call after-link,$@) + endef + define +link-pie-tests +@@ -454,7 +456,7 @@ ifndef +link-static + $(link-extra-libs-static) + +link-static-after-libc = $(+postctorT) $(+postinit) + define +link-static +-$(+link-static-before-libc) $(link-libc-static) $(+link-static-after-libc) ++$(+link-static-before-libc) $(link-extra-flags) $(link-libc-static) $(+link-static-after-libc) + $(call after-link,$@) + endef + define +link-static-tests +@@ -485,7 +487,7 @@ else # not build-pie-default + $(link-extra-libs) + +link-after-libc = $(+postctor) $(+postinit) + define +link +-$(+link-before-libc) $(rtld-LDFLAGS) $(link-libc) $(+link-after-libc) ++$(+link-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) $(+link-after-libc) + $(call after-link,$@) + endef + define +link-tests +diff --git a/manual/install.texi b/manual/install.texi +index e757891dc2eebb2e..351d67c68b255f62 100644 +--- a/manual/install.texi ++++ b/manual/install.texi +@@ -199,10 +199,10 @@ number of routines called directly from assembler are excluded from this + protection. + + @item --enable-bind-now +-Disable lazy binding for installed shared objects. This provides +-additional security hardening because it enables full RELRO and a +-read-only global offset table (GOT), at the cost of slightly increased +-program load times. ++Disable lazy binding for installed shared objects and programs. This ++provides additional security hardening because it enables full RELRO ++and a read-only global offset table (GOT), at the cost of slightly ++increased program load times. + + @pindex pt_chown + @findex grantpt diff --git a/glibc-rh1639343-3.patch b/glibc-rh1639343-3.patch new file mode 100755 index 0000000..4e4e146 --- /dev/null +++ b/glibc-rh1639343-3.patch @@ -0,0 +1,43 @@ +commit b5ffdc48c20ae865b197b67e5a9068a528fbc198 +Author: Florian Weimer +Date: Thu Apr 25 10:41:52 2019 +0200 + + benchtests: Enable BIND_NOW if configured with --enable-bind-now + + Benchmarks should reflect distribution build policies, so it makes + sense to honor the BIND_NOW configuration for them. + + This commit keeps using $(+link-tests), so that the benchmarks are + linked according to the --enable-hardcoded-path-in-tests configure + option. + + Reviewed-by: Carlos O'Donell + +diff --git a/benchtests/Makefile b/benchtests/Makefile +index bcd6a9c26d9a0005..28d6b0c43f5bd390 100644 +--- a/benchtests/Makefile ++++ b/benchtests/Makefile +@@ -235,13 +235,21 @@ bench-func: $(binaries-bench) + scripts/benchout.schema.json; \ + fi + +-$(timing-type) $(binaries-bench) $(binaries-benchset) \ +- $(binaries-bench-malloc): %: %.o $(objpfx)json-lib.o \ ++ifeq ($(bind-now),yes) ++link-bench-bind-now = -Wl,-z,now ++endif ++ ++bench-link-targets = $(timing-type) $(binaries-bench) $(binaries-benchset) \ ++ $(binaries-bench-malloc) ++ ++$(bench-link-targets): %: %.o $(objpfx)json-lib.o \ + $(link-extra-libs-tests) \ + $(sort $(filter $(common-objpfx)lib%,$(link-libc))) \ + $(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit) + $(+link-tests) + ++$(bench-link-targets): LDFLAGS += $(link-bench-bind-now) ++ + $(objpfx)bench-%.c: %-inputs $(bench-deps) + { if [ -n "$($*-INCLUDE)" ]; then \ + cat $($*-INCLUDE); \ diff --git a/glibc-rh1639343-4.patch b/glibc-rh1639343-4.patch new file mode 100755 index 0000000..10d4b48 --- /dev/null +++ b/glibc-rh1639343-4.patch @@ -0,0 +1,100 @@ +commit e30fb31c0ad8d31babd1d0d0f05e37c6579a870b +Author: Florian Weimer +Date: Fri Apr 26 07:16:47 2019 +0200 + + Makeconfig: Move $(CC) to +link command variables + + This change is needed to add linker flags which come very early in the + command linke (before LDFLAGS) and are not applied to test programs + (only to installed programs). + +diff --git a/Makeconfig b/Makeconfig +index 742c0c0783a14bfa..1ad25fc5a7251aea 100644 +--- a/Makeconfig ++++ b/Makeconfig +@@ -415,7 +415,7 @@ link-extra-libs-tests = $(libsupport) + + # Command for linking PIE programs with the C library. + ifndef +link-pie +-+link-pie-before-libc = $(CC) $(if $($(@F)-no-pie),$(no-pie-ldflag),-pie) \ +++link-pie-before-libc = $(if $($(@F)-no-pie),$(no-pie-ldflag),-pie) \ + -Wl,-O1 -nostdlib -nostartfiles -o $@ \ + $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ + $(combreloc-LDFLAGS) $(relro-LDFLAGS) $(hashstyle-LDFLAGS) \ +@@ -428,23 +428,24 @@ ifndef +link-pie + $(link-extra-libs) + +link-pie-after-libc = $(+postctorS) $(+postinit) + define +link-pie +-$(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) $(+link-pie-after-libc) ++$(CC) $(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) \ ++ $(link-libc) $(+link-pie-after-libc) + $(call after-link,$@) + endef + define +link-pie-tests +-$(+link-pie-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \ +- $(+link-pie-after-libc) ++$(CC) $(+link-pie-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \ ++ $(+link-pie-after-libc) + $(call after-link,$@) + endef + define +link-pie-printers-tests +-$(+link-pie-before-libc) $(built-rtld-LDFLAGS) $(link-libc-printers-tests) \ +- $(+link-pie-after-libc) ++$(CC) $(+link-pie-before-libc) $(built-rtld-LDFLAGS) \ ++ $(link-libc-printers-tests) $(+link-pie-after-libc) + $(call after-link,$@) + endef + endif + # Command for statically linking programs with the C library. + ifndef +link-static +-+link-static-before-libc = $(CC) -nostdlib -nostartfiles -static -o $@ \ +++link-static-before-libc = -nostdlib -nostartfiles -static -o $@ \ + $(if $($(@F)-no-pie),$(no-pie-ldflag),$(default-pie-ldflag)) \ + $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ + $(firstword $(CRT-$(@F)) $(csu-objpfx)$(real-static-start-installed-name)) \ +@@ -456,11 +457,13 @@ ifndef +link-static + $(link-extra-libs-static) + +link-static-after-libc = $(+postctorT) $(+postinit) + define +link-static +-$(+link-static-before-libc) $(link-extra-flags) $(link-libc-static) $(+link-static-after-libc) ++$(CC) $(+link-static-before-libc) $(link-extra-flags) $(link-libc-static) \ ++ $(+link-static-after-libc) + $(call after-link,$@) + endef + define +link-static-tests +-$(+link-static-before-libc) $(link-libc-static-tests) $(+link-static-after-libc) ++$(CC) $(+link-static-before-libc) $(link-libc-static-tests) \ ++ $(+link-static-after-libc) + $(call after-link,$@) + endef + endif +@@ -475,7 +478,7 @@ ifeq (yes,$(build-pie-default)) + +link-tests = $(+link-pie-tests) + +link-printers-tests = $(+link-pie-printers-tests) + else # not build-pie-default +-+link-before-libc = $(CC) -nostdlib -nostartfiles -o $@ \ +++link-before-libc = -nostdlib -nostartfiles -o $@ \ + $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ + $(combreloc-LDFLAGS) $(relro-LDFLAGS) $(hashstyle-LDFLAGS) \ + $(firstword $(CRT-$(@F)) $(csu-objpfx)$(start-installed-name)) \ +@@ -487,16 +490,17 @@ else # not build-pie-default + $(link-extra-libs) + +link-after-libc = $(+postctor) $(+postinit) + define +link +-$(+link-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) $(+link-after-libc) ++$(CC) $(+link-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) \ ++ $(+link-after-libc) + $(call after-link,$@) + endef + define +link-tests +-$(+link-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \ ++$(CC) $(+link-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \ + $(+link-after-libc) + $(call after-link,$@) + endef + define +link-printers-tests +-$(+link-before-libc) $(built-rtld-LDFLAGS) $(link-libc-printers-tests) \ ++$(CC) $(+link-before-libc) $(built-rtld-LDFLAGS) $(link-libc-printers-tests) \ + $(+link-after-libc) + $(call after-link,$@) + endef diff --git a/glibc-rh1639343-5.patch b/glibc-rh1639343-5.patch new file mode 100755 index 0000000..cefd167 --- /dev/null +++ b/glibc-rh1639343-5.patch @@ -0,0 +1,74 @@ +commit a8ff215e56050a907189e713fd449bcafe99ff6b +Author: Florian Weimer +Date: Fri Apr 26 07:16:30 2019 +0200 + + Makeconfig: Move -Wl,-rpath-link options before library references + + Previously, the -Wl,-rpath-link options came after the libraries + injected using LDLIBS-* variables on the link editor command line for + main programs. As a result, it could happen that installed libraries + that reference glibc libraries used the installed glibc from the system + directories, instead of the glibc from the build tree. This can lead to + link failures if the wrong version of libpthread.so.0 is used, for + instance, due to differences in the internal GLIBC_PRIVATE interfaces, + as seen with memusagestat and -lgd after commit + f9b645b4b0a10c43753296ce3fa40053fa44606a ("memusagestat: use local glibc + when linking [BZ #18465]"). + + The isolation is necessarily imperfect because these installed + libraries are linked against the installed glibc in the system + directories. However, in most cases, the built glibc will be newer + than the installed glibc, and this link is permitted because of the + ABI backwards compatibility glibc provides. + +diff --git a/Makeconfig b/Makeconfig +index 1ad25fc5a7251aea..e315fb8a75ca5063 100644 +--- a/Makeconfig ++++ b/Makeconfig +@@ -428,8 +428,8 @@ ifndef +link-pie + $(link-extra-libs) + +link-pie-after-libc = $(+postctorS) $(+postinit) + define +link-pie +-$(CC) $(+link-pie-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) \ +- $(link-libc) $(+link-pie-after-libc) ++$(CC) $(link-libc-rpath-link) $(+link-pie-before-libc) $(rtld-LDFLAGS) \ ++ $(link-extra-flags) $(link-libc) $(+link-pie-after-libc) + $(call after-link,$@) + endef + define +link-pie-tests +@@ -490,8 +490,8 @@ else # not build-pie-default + $(link-extra-libs) + +link-after-libc = $(+postctor) $(+postinit) + define +link +-$(CC) $(+link-before-libc) $(rtld-LDFLAGS) $(link-extra-flags) $(link-libc) \ +- $(+link-after-libc) ++$(CC) $(link-libc-rpath-link) $(+link-before-libc) $(rtld-LDFLAGS) \ ++ $(link-extra-flags) $(link-libc) $(+link-after-libc) + $(call after-link,$@) + endef + define +link-tests +@@ -552,6 +552,15 @@ ifeq (yes,$(build-shared)) + link-libc-rpath = -Wl,-rpath=$(rpath-link) + link-libc-rpath-link = -Wl,-rpath-link=$(rpath-link) + ++# For programs which are not tests, $(link-libc-rpath-link) is added ++# directly in $(+link), $(+link-pie) above, so that -Wl,-rpath-link ++# comes before the expansion of LDLIBS-* and affects libraries added ++# there. For shared objects, -Wl,-rpath-link is added via ++# $(build-shlib-helper) and $(build-module-helper) in Makerules (also ++# before the expansion of LDLIBS-* variables). ++ ++# Tests use -Wl,-rpath instead of -Wl,-rpath-link for ++# build-hardcoded-path-in-tests. + ifeq (yes,$(build-hardcoded-path-in-tests)) + link-libc-tests-rpath-link = $(link-libc-rpath) + else +@@ -562,7 +571,7 @@ link-libc-before-gnulib = $(common-objpfx)libc.so$(libc.so-version) \ + $(common-objpfx)$(patsubst %,$(libtype.oS),c) \ + $(as-needed) $(elf-objpfx)ld.so \ + $(no-as-needed) +-link-libc = $(link-libc-rpath-link) $(link-libc-before-gnulib) $(gnulib) ++link-libc = $(link-libc-before-gnulib) $(gnulib) + + link-libc-tests-after-rpath-link = $(link-libc-before-gnulib) $(gnulib-tests) + link-libc-tests = $(link-libc-tests-rpath-link) \ diff --git a/glibc-rh1639343-6.patch b/glibc-rh1639343-6.patch new file mode 100755 index 0000000..643e192 --- /dev/null +++ b/glibc-rh1639343-6.patch @@ -0,0 +1,25 @@ +commit c57afec0a9b318bb691e0f5fa4e9681cf30df7a4 +Author: Florian Weimer +Date: Fri Apr 26 07:16:56 2019 +0200 + + elf: Link sotruss-lib.so with BIND_NOW for --enable-bind-now + + The audit module itself can be linked with BIND_NOW; it does not + affect its functionality. + + This should complete the leftovers from commit + 2d6ab5df3b675e96ee587ae6a8c2ce004c6b1ba9 ("Document and fix + --enable-bind-now [BZ #21015]"). + +diff --git a/elf/Makefile b/elf/Makefile +index f5285b99e22fe84d..9194339836900b9d 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -133,6 +133,7 @@ install-others += $(inst_auditdir)/sotruss-lib.so + install-bin-script += sotruss + generated += sotruss + libof-sotruss-lib = extramodules ++LDFLAGS-sotruss-lib.so += $(z-now-$(bind-now)) + $(objpfx)sotruss-lib.so: $(objpfx)sotruss-lib.os + $(build-module-asneeded) + $(objpfx)sotruss-lib.so: $(common-objpfx)libc.so $(objpfx)ld.so \ diff --git a/glibc-rh1641982.patch b/glibc-rh1641982.patch new file mode 100755 index 0000000..937abfd --- /dev/null +++ b/glibc-rh1641982.patch @@ -0,0 +1,41 @@ +commit c3d8dc45c9df199b8334599a6cbd98c9950dba62 +Author: Adhemerval Zanella +Date: Thu Oct 11 15:18:40 2018 -0300 + + x86: Fix Haswell strong flags (BZ#23709) + + Th commit 'Disable TSX on some Haswell processors.' (2702856bf4) changed the + default flags for Haswell models. Previously, new models were handled by the + default switch path, which assumed a Core i3/i5/i7 if AVX is available. After + the patch, Haswell models (0x3f, 0x3c, 0x45, 0x46) do not set the flags + Fast_Rep_String, Fast_Unaligned_Load, Fast_Unaligned_Copy, and + Prefer_PMINUB_for_stringop (only the TSX one). + + This patch fixes it by disentangle the TSX flag handling from the memory + optimization ones. The strstr case cited on patch now selects the + __strstr_sse2_unaligned as expected for the Haswell cpu. + + Checked on x86_64-linux-gnu. + + [BZ #23709] + * sysdeps/x86/cpu-features.c (init_cpu_features): Set TSX bits + independently of other flags. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index ea0b64fdb962a934..4695ac80d4148327 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -316,7 +316,13 @@ init_cpu_features (struct cpu_features *cpu_features) + | bit_arch_Fast_Unaligned_Copy + | bit_arch_Prefer_PMINUB_for_stringop); + break; ++ } + ++ /* Disable TSX on some Haswell processors to avoid TSX on kernels that ++ weren't updated with the latest microcode package (which disables ++ broken feature by default). */ ++ switch (model) ++ { + case 0x3f: + /* Xeon E7 v3 with stepping >= 4 has working TSX. */ + if (stepping >= 4) diff --git a/glibc-rh1642094-1.patch b/glibc-rh1642094-1.patch new file mode 100755 index 0000000..2fd093c --- /dev/null +++ b/glibc-rh1642094-1.patch @@ -0,0 +1,230 @@ +commit bcdaad21d4635931d1bd3b54a7894276925d081d +Author: DJ Delorie +Date: Tue Nov 20 13:24:09 2018 -0500 + + malloc: tcache double free check + + * malloc/malloc.c (tcache_entry): Add key field. + (tcache_put): Set it. + (tcache_get): Likewise. + (_int_free): Check for double free in tcache. + * malloc/tst-tcfree1.c: New. + * malloc/tst-tcfree2.c: New. + * malloc/Makefile: Run the new tests. + * manual/probes.texi: Document memory_tcache_double_free probe. + + * dlfcn/dlerror.c (check_free): Prevent double frees. + +diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c +index 33574faab65628ff..96bf92533335036b 100644 +--- a/dlfcn/dlerror.c ++++ b/dlfcn/dlerror.c +@@ -198,7 +198,10 @@ check_free (struct dl_action_result *rec) + Dl_info info; + if (_dl_addr (check_free, &info, &map, NULL) != 0 && map->l_ns == 0) + #endif +- free ((char *) rec->errstring); ++ { ++ free ((char *) rec->errstring); ++ rec->errstring = NULL; ++ } + } + } + +diff --git a/malloc/Makefile b/malloc/Makefile +index 7d54bad866f63cb8..e6dfbfc14cb3d140 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -38,6 +38,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ + tst-malloc_info \ + tst-malloc-too-large \ + tst-malloc-stats-cancellation \ ++ tst-tcfree1 tst-tcfree2 \ + + tests-static := \ + tst-interpose-static-nothread \ +diff --git a/malloc/malloc.c b/malloc/malloc.c +index e247c77b7d4de26e..c6b0282e783eaeea 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -2888,6 +2888,8 @@ mremap_chunk (mchunkptr p, size_t new_size) + typedef struct tcache_entry + { + struct tcache_entry *next; ++ /* This field exists to detect double frees. */ ++ struct tcache_perthread_struct *key; + } tcache_entry; + + /* There is one of these for each thread, which contains the +@@ -2911,6 +2913,11 @@ tcache_put (mchunkptr chunk, size_t tc_idx) + { + tcache_entry *e = (tcache_entry *) chunk2mem (chunk); + assert (tc_idx < TCACHE_MAX_BINS); ++ ++ /* Mark this chunk as "in the tcache" so the test in _int_free will ++ detect a double free. */ ++ e->key = tcache; ++ + e->next = tcache->entries[tc_idx]; + tcache->entries[tc_idx] = e; + ++(tcache->counts[tc_idx]); +@@ -2926,6 +2933,7 @@ tcache_get (size_t tc_idx) + assert (tcache->entries[tc_idx] > 0); + tcache->entries[tc_idx] = e->next; + --(tcache->counts[tc_idx]); ++ e->key = NULL; + return (void *) e; + } + +@@ -4152,6 +4160,26 @@ _int_free (mstate av, mchunkptr p, int have_lock) + { + size_t tc_idx = csize2tidx (size); + ++ /* Check to see if it's already in the tcache. */ ++ tcache_entry *e = (tcache_entry *) chunk2mem (p); ++ ++ /* This test succeeds on double free. However, we don't 100% ++ trust it (it also matches random payload data at a 1 in ++ 2^ chance), so verify it's not an unlikely coincidence ++ before aborting. */ ++ if (__glibc_unlikely (e->key == tcache && tcache)) ++ { ++ tcache_entry *tmp; ++ LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx); ++ for (tmp = tcache->entries[tc_idx]; ++ tmp; ++ tmp = tmp->next) ++ if (tmp == e) ++ malloc_printerr ("free(): double free detected in tcache 2"); ++ /* If we get here, it was a coincidence. We've wasted a few ++ cycles, but don't abort. */ ++ } ++ + if (tcache + && tc_idx < mp_.tcache_bins + && tcache->counts[tc_idx] < mp_.tcache_count) +diff --git a/malloc/tst-tcfree1.c b/malloc/tst-tcfree1.c +new file mode 100644 +index 0000000000000000..bc29375ce77304ac +--- /dev/null ++++ b/malloc/tst-tcfree1.c +@@ -0,0 +1,42 @@ ++/* Test that malloc tcache catches double free. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* Do one allocation of any size that fits in tcache. */ ++ char * volatile x = malloc (32); ++ ++ free (x); // puts in tcache ++ free (x); // should abort ++ ++ printf("FAIL: tcache double free not detected\n"); ++ return 1; ++} ++ ++#define TEST_FUNCTION do_test ++#define EXPECTED_SIGNAL SIGABRT ++#include +diff --git a/malloc/tst-tcfree2.c b/malloc/tst-tcfree2.c +new file mode 100644 +index 0000000000000000..17f06bacd411c315 +--- /dev/null ++++ b/malloc/tst-tcfree2.c +@@ -0,0 +1,48 @@ ++/* Test that malloc tcache catches double free. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ char * volatile ptrs[20]; ++ int i; ++ ++ /* Allocate enough small chunks so that when we free them all, the tcache ++ is full, and the first one we freed is at the end of its linked list. */ ++#define COUNT 20 ++ for (i=0; i +diff --git a/manual/probes.texi b/manual/probes.texi +index ab2a3102bb350ef4..0ea560ed78bcfd7e 100644 +--- a/manual/probes.texi ++++ b/manual/probes.texi +@@ -243,6 +243,18 @@ This probe is triggered when the + value of this tunable. + @end deftp + ++@deftp Probe memory_tcache_double_free (void *@var{$arg1}, int @var{$arg2}) ++This probe is triggered when @code{free} determines that the memory ++being freed has probably already been freed, and resides in the ++per-thread cache. Note that there is an extremely unlikely chance ++that this probe will trigger due to random payload data remaining in ++the allocated memory matching the key used to detect double frees. ++This probe actually indicates that an expensive linear search of the ++tcache, looking for a double free, has happened. Argument @var{$arg1} ++is the memory location as passed to @code{free}, Argument @var{$arg2} ++is the tcache bin it resides in. ++@end deftp ++ + @node Mathematical Function Probes + @section Mathematical Function Probes + diff --git a/glibc-rh1642094-2.patch b/glibc-rh1642094-2.patch new file mode 100755 index 0000000..aa3d2ea --- /dev/null +++ b/glibc-rh1642094-2.patch @@ -0,0 +1,73 @@ +commit affec03b713c82c43a5b025dddc21bde3334f41e +Author: Florian Weimer +Date: Mon Nov 26 20:06:37 2018 +0100 + + malloc: tcache: Validate tc_idx before checking for double-frees [BZ #23907] + + The previous check could read beyond the end of the tcache entry + array. If the e->key == tcache cookie check happened to pass, this + would result in crashes. + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index c6b0282e783eaeea..13c52f376859562d 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -4159,33 +4159,33 @@ _int_free (mstate av, mchunkptr p, int have_lock) + #if USE_TCACHE + { + size_t tc_idx = csize2tidx (size); +- +- /* Check to see if it's already in the tcache. */ +- tcache_entry *e = (tcache_entry *) chunk2mem (p); +- +- /* This test succeeds on double free. However, we don't 100% +- trust it (it also matches random payload data at a 1 in +- 2^ chance), so verify it's not an unlikely coincidence +- before aborting. */ +- if (__glibc_unlikely (e->key == tcache && tcache)) ++ if (tcache != NULL && tc_idx < mp_.tcache_bins) + { +- tcache_entry *tmp; +- LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx); +- for (tmp = tcache->entries[tc_idx]; +- tmp; +- tmp = tmp->next) +- if (tmp == e) +- malloc_printerr ("free(): double free detected in tcache 2"); +- /* If we get here, it was a coincidence. We've wasted a few +- cycles, but don't abort. */ +- } ++ /* Check to see if it's already in the tcache. */ ++ tcache_entry *e = (tcache_entry *) chunk2mem (p); ++ ++ /* This test succeeds on double free. However, we don't 100% ++ trust it (it also matches random payload data at a 1 in ++ 2^ chance), so verify it's not an unlikely ++ coincidence before aborting. */ ++ if (__glibc_unlikely (e->key == tcache)) ++ { ++ tcache_entry *tmp; ++ LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx); ++ for (tmp = tcache->entries[tc_idx]; ++ tmp; ++ tmp = tmp->next) ++ if (tmp == e) ++ malloc_printerr ("free(): double free detected in tcache 2"); ++ /* If we get here, it was a coincidence. We've wasted a ++ few cycles, but don't abort. */ ++ } + +- if (tcache +- && tc_idx < mp_.tcache_bins +- && tcache->counts[tc_idx] < mp_.tcache_count) +- { +- tcache_put (p, tc_idx); +- return; ++ if (tcache->counts[tc_idx] < mp_.tcache_count) ++ { ++ tcache_put (p, tc_idx); ++ return; ++ } + } + } + #endif diff --git a/glibc-rh1642094-3.patch b/glibc-rh1642094-3.patch new file mode 100755 index 0000000..50a41ef --- /dev/null +++ b/glibc-rh1642094-3.patch @@ -0,0 +1,89 @@ +commit 7c9a7c68363051cfc5fa1ebb96b3b2c1f82dcb76 +Author: DJ Delorie +Date: Fri Nov 30 22:13:09 2018 -0500 + + malloc: Add another test for tcache double free check. + + This one tests for BZ#23907 where the double free + test didn't check the tcache bin bounds before dereferencing + the bin. + + [BZ #23907] + * malloc/tst-tcfree3.c: New. + * malloc/Makefile: Add it. + +diff --git a/malloc/Makefile b/malloc/Makefile +index e6dfbfc14cb3d140..388cf7e9ee3a2569 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -38,7 +38,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ + tst-malloc_info \ + tst-malloc-too-large \ + tst-malloc-stats-cancellation \ +- tst-tcfree1 tst-tcfree2 \ ++ tst-tcfree1 tst-tcfree2 tst-tcfree3 \ + + tests-static := \ + tst-interpose-static-nothread \ +diff --git a/malloc/tst-tcfree3.c b/malloc/tst-tcfree3.c +new file mode 100644 +index 0000000000000000..016d30ddd8114082 +--- /dev/null ++++ b/malloc/tst-tcfree3.c +@@ -0,0 +1,56 @@ ++/* Test that malloc tcache catches double free. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++ ++/* Prevent GCC from optimizing away any malloc/free pairs. */ ++#pragma GCC optimize ("O0") ++ ++static int ++do_test (void) ++{ ++ /* Do two allocation of any size that fit in tcache, and one that ++ doesn't. */ ++ int ** volatile a = malloc (32); ++ int ** volatile b = malloc (32); ++ /* This is just under the mmap threshold. */ ++ int ** volatile c = malloc (127 * 1024); ++ ++ /* The invalid "tcache bucket" we might dereference will likely end ++ up somewhere within this memory block, so make all the accidental ++ "next" pointers cause segfaults. BZ #23907. */ ++ memset (c, 0xff, 127 * 1024); ++ ++ free (a); // puts in tcache ++ ++ /* A is now free and contains the key we use to detect in-tcache. ++ Copy the key to the other chunks. */ ++ memcpy (b, a, 32); ++ memcpy (c, a, 32); ++ ++ /* This free tests the "are we in the tcache already" loop with a ++ VALID bin but "coincidental" matching key. */ ++ free (b); // should NOT abort ++ /* This free tests the "is it a valid tcache bin" test. */ ++ free (c); // should NOT abort ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1642150-1.patch b/glibc-rh1642150-1.patch new file mode 100755 index 0000000..381ad0b --- /dev/null +++ b/glibc-rh1642150-1.patch @@ -0,0 +1,176 @@ +commit a803367bab167f5ec4fde1f0d0ec447707c29520 +Author: Florian Weimer +Date: Fri Feb 14 20:55:39 2020 +0100 + + powerpc64: Add memory protection key support [BZ #23202] + + The 32-bit protection key behavior is somewhat unclear on 32-bit powerpc, + so this change is restricted to the 64-bit variants. + + Flag translation is needed because of hardware differences between the + POWER implementation (read and write flags) and the Intel implementation + (write and read+write flags). + +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h +new file mode 100644 +index 0000000000000000..623b073d5a585d51 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h +@@ -0,0 +1,55 @@ ++/* Helper functions for manipulating memory protection keys, for powerpc64. ++ Copyright (C) 2017-2020 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 ++ . */ ++ ++#ifndef _ARCH_PKEY_H ++#define _ARCH_PKEY_H ++ ++/* Read and write access bits in the AMR register. Needs to be ++ translated from and to PKEY_DISABLE_* flags. */ ++#define PKEY_AMR_READ 1UL ++#define PKEY_AMR_WRITE 2UL ++ ++/* Return the value of the AMR register. */ ++static inline unsigned long int ++pkey_read (void) ++{ ++ unsigned long int result; ++ __asm__ volatile ("mfspr %0, 13" : "=r" (result)); ++ return result; ++} ++ ++/* Overwrite the AMR register with VALUE. */ ++static inline void ++pkey_write (unsigned long int value) ++{ ++ __asm__ volatile ("mtspr 13, %0" : : "r" (value)); ++} ++ ++/* Number of the largest supported key. This depends on the width of ++ the AMR register. */ ++#define PKEY_MAX (sizeof (unsigned long int) * 8 / 2 - 1) ++_Static_assert (PKEY_MAX == 15 || PKEY_MAX == 31, "PKEY_MAX value"); ++ ++/* Translate key number into AMR index position. */ ++static inline int ++pkey_index (int key) ++{ ++ return 2 * (PKEY_MAX - key); ++} ++ ++#endif /* _ARCH_PKEY_H */ +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_get.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_get.c +new file mode 100644 +index 0000000000000000..856ba061b90eabd2 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_get.c +@@ -0,0 +1,42 @@ ++/* Reading the per-thread memory protection key, powerpc64 version. ++ Copyright (C) 2017-2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++int ++pkey_get (int key) ++{ ++ if (key < 0 || key > PKEY_MAX) ++ { ++ __set_errno (EINVAL); ++ return -1; ++ } ++ unsigned int index = pkey_index (key); ++ unsigned long int amr = pkey_read (); ++ unsigned int bits = (amr >> index) & 3; ++ ++ /* Translate from AMR values. PKEY_AMR_READ standing alone is not ++ currently representable. */ ++ if (bits & PKEY_AMR_READ) ++ return PKEY_DISABLE_ACCESS; ++ else if (bits == PKEY_AMR_WRITE) ++ return PKEY_DISABLE_WRITE; ++ return 0; ++} +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_set.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_set.c +new file mode 100644 +index 0000000000000000..20b372ee2983abd5 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/pkey_set.c +@@ -0,0 +1,48 @@ ++/* Changing the per-thread memory protection key, powerpc64 version. ++ Copyright (C) 2017-2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++int ++pkey_set (int key, unsigned int rights) ++{ ++ if (key < 0 || key > PKEY_MAX || rights > 3) ++ { ++ __set_errno (EINVAL); ++ return -1; ++ } ++ ++ /* Translate to AMR bit values. */ ++ unsigned long int bits; ++ if (rights & PKEY_DISABLE_ACCESS) ++ /* The PKEY_DISABLE_WRITE bit does not matter. */ ++ bits = PKEY_AMR_READ | PKEY_AMR_WRITE; ++ else if (rights == PKEY_DISABLE_WRITE) ++ bits = PKEY_AMR_WRITE; ++ else ++ bits = 0; ++ ++ unsigned int index = pkey_index (key); ++ unsigned long int mask = 3UL << index; ++ unsigned long int amr = pkey_read (); ++ amr = (amr & ~mask) | (bits << index); ++ pkey_write (amr); ++ return 0; ++} diff --git a/glibc-rh1642150-2.patch b/glibc-rh1642150-2.patch new file mode 100755 index 0000000..129ed9d --- /dev/null +++ b/glibc-rh1642150-2.patch @@ -0,0 +1,53 @@ +commit 8d42bf859a289944749d9f978c076cd318119867 +Author: Lucas A. M. Magalhaes +Date: Mon Feb 17 09:09:52 2020 -0300 + + Fix tst-pkey expectations on pkey_get [BZ #23202] + + From the GNU C Library manual, the pkey_set can receive a combination of + PKEY_DISABLE_WRITE and PKEY_DISABLE_ACCESS. However PKEY_DISABLE_ACCESS + is more restrictive than PKEY_DISABLE_WRITE and includes its behavior. + + The test expects that after setting + (PKEY_DISABLE_WRITE|PKEY_DISABLE_ACCESS) pkey_get should return the + same. This may not be true as PKEY_DISABLE_ACCESS will succeed in + describing the state of the key in this case. + + The pkey behavior during signal handling is different between x86 and + POWER. This change make the test compatible with both architectures. + + Reviewed-by: Tulio Magno Quites Machado Filho + +diff --git a/sysdeps/unix/sysv/linux/tst-pkey.c b/sysdeps/unix/sysv/linux/tst-pkey.c +index 5f721d4444490945..600b6f0098def773 100644 +--- a/sysdeps/unix/sysv/linux/tst-pkey.c ++++ b/sysdeps/unix/sysv/linux/tst-pkey.c +@@ -37,7 +37,7 @@ static pthread_barrier_t barrier; + + /* The keys used for testing. These have been allocated with access + rights set based on their array index. */ +-enum { key_count = 4 }; ++enum { key_count = 3 }; + static int keys[key_count]; + static volatile int *pages[key_count]; + +@@ -111,14 +111,16 @@ check_page_access (int page, bool write) + } + + static volatile sig_atomic_t sigusr1_handler_ran; +- +-/* Used to check that access is revoked in signal handlers. */ ++/* Used to check the behavior in signal handlers. In x86 all access are ++ revoked during signal handling. In PowerPC the key permissions are ++ inherited by the interrupted thread. This test accept both approaches. */ + static void + sigusr1_handler (int signum) + { + TEST_COMPARE (signum, SIGUSR1); + for (int i = 0; i < key_count; ++i) +- TEST_COMPARE (pkey_get (keys[i]), PKEY_DISABLE_ACCESS); ++ TEST_VERIFY (pkey_get (keys[i]) == PKEY_DISABLE_ACCESS ++ || pkey_get (keys[i]) == i); + sigusr1_handler_ran = 1; + } + diff --git a/glibc-rh1642150-3.patch b/glibc-rh1642150-3.patch new file mode 100755 index 0000000..84a2191 --- /dev/null +++ b/glibc-rh1642150-3.patch @@ -0,0 +1,46 @@ +commit 70ba28f7ab2923d4e36ffc9d5d2e32357353b25c +Author: Lucas A. M. Magalhaes +Date: Thu Jan 16 10:39:12 2020 -0300 + + Fix tst-pkey.c pkey_alloc return checks and manual + + This test was failing in some powerpc systems as it was not checking + for ENOSPC return. + + As said on the Linux man-pages and can be observed by the implementation + at mm/mprotect.c in the Linux Kernel source. The syscall pkey_alloc can + return EINVAL or ENOSPC. ENOSPC will indicate either that all keys are + in use or that the kernel does not support pkeys. + + Reviewed-by: Gabriel F. T. Gomes + +diff --git a/manual/memory.texi b/manual/memory.texi +index a1435aad1acd3239..4731a38bcc5701e0 100644 +--- a/manual/memory.texi ++++ b/manual/memory.texi +@@ -3289,6 +3289,10 @@ in which memory protection keys are disabled. + + @item ENOSPC + All available protection keys already have been allocated. ++ ++The system does not implement memory protection keys or runs in a mode ++in which memory protection keys are disabled. ++ + @end table + @end deftypefun + +diff --git a/sysdeps/unix/sysv/linux/tst-pkey.c b/sysdeps/unix/sysv/linux/tst-pkey.c +index 600b6f0098def773..40d7e9f24dec3e57 100644 +--- a/sysdeps/unix/sysv/linux/tst-pkey.c ++++ b/sysdeps/unix/sysv/linux/tst-pkey.c +@@ -199,6 +199,10 @@ do_test (void) + if (errno == EINVAL) + FAIL_UNSUPPORTED + ("CPU does not support memory protection keys: %m"); ++ if (errno == ENOSPC) ++ FAIL_UNSUPPORTED ++ ("no keys available or kernel does not support memory" ++ " protection keys"); + FAIL_EXIT1 ("pkey_alloc: %m"); + } + TEST_COMPARE (pkey_get (keys[0]), 0); diff --git a/glibc-rh1642150-4.patch b/glibc-rh1642150-4.patch new file mode 100755 index 0000000..b4d53e5 --- /dev/null +++ b/glibc-rh1642150-4.patch @@ -0,0 +1,36 @@ +commit e627106266ad8785457fadbf5bf67ed604d2a353 +Author: Florian Weimer +Date: Mon May 11 11:20:02 2020 +0200 + + POWER: Add context-synchronizing instructions to pkey_write [BZ #25954] + + Sandipan Das reported that, + + "The Power ISA mandates that all writes to the Authority + Mask Register (AMR) must always be preceded as well as + succeeded by a context-synchronizing instruction. This + applies to both the privileged and unprivileged variants + of the Move To AMR instruction. + + This [requirement] is from Table 6 of Chapter 11 in page 1134 of Power + ISA 3.0B. The document can be found here: + + " + + See this kernel patch submission: + + + +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h +index 623b073d5a585d51..25d080c9a6f30942 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-pkey.h +@@ -37,7 +37,7 @@ pkey_read (void) + static inline void + pkey_write (unsigned long int value) + { +- __asm__ volatile ("mtspr 13, %0" : : "r" (value)); ++ __asm__ volatile ("isync; mtspr 13, %0; isync" : : "r" (value)); + } + + /* Number of the largest supported key. This depends on the width of diff --git a/glibc-rh1645593.patch b/glibc-rh1645593.patch new file mode 100755 index 0000000..d2b5cc2 --- /dev/null +++ b/glibc-rh1645593.patch @@ -0,0 +1,34 @@ +commit 28669f86f6780a18daca264f32d66b1428c9c6f1 +Author: Stefan Liebler +Date: Thu Sep 6 14:27:03 2018 +0200 + + Fix segfault in maybe_script_execute. + + If glibc is built with gcc 8 and -march=z900, + the testcase posix/tst-spawn4-compat crashes with a segfault. + + In function maybe_script_execute, the new_argv array is dynamically + initialized on stack with (argc + 1) elements. + The function wants to add _PATH_BSHELL as the first argument + and writes out of bounds of new_argv. + There is an off-by-one because maybe_script_execute fails to count + the terminating NULL when sizing new_argv. + + ChangeLog: + + * sysdeps/unix/sysv/linux/spawni.c (maybe_script_execute): + Increment size of new_argv by one. + +diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c +index cf0213ece55c675d..85239cedbf2a5ab5 100644 +--- a/sysdeps/unix/sysv/linux/spawni.c ++++ b/sysdeps/unix/sysv/linux/spawni.c +@@ -101,7 +101,7 @@ maybe_script_execute (struct posix_spawn_args *args) + ptrdiff_t argc = args->argc; + + /* Construct an argument list for the shell. */ +- char *new_argv[argc + 1]; ++ char *new_argv[argc + 2]; + new_argv[0] = (char *) _PATH_BSHELL; + new_argv[1] = (char *) args->file; + if (argc > 1) diff --git a/glibc-rh1645596.patch b/glibc-rh1645596.patch new file mode 100755 index 0000000..36e4b9a --- /dev/null +++ b/glibc-rh1645596.patch @@ -0,0 +1,193 @@ +commit 7a16bdbb9ff4122af0a28dc20996c95352011fdd +Author: Adhemerval Zanella +Date: Wed Aug 29 16:36:44 2018 -0300 + + Fix misreported errno on preadv2/pwritev2 (BZ#23579) + + The fallback code of Linux wrapper for preadv2/pwritev2 executes + regardless of the errno code for preadv2, instead of the case where + the syscall is not supported. + + This fixes it by calling the fallback code iff errno is ENOSYS. The + patch also adds tests for both invalid file descriptor and invalid + iov_len and vector count. + + The only discrepancy between preadv2 and fallback code regarding + error reporting is when an invalid flags are used. The fallback code + bails out earlier with ENOTSUP instead of EINVAL/EBADF when the syscall + is used. + + Checked on x86_64-linux-gnu on a 4.4.0 and 4.15.0 kernel. + + [BZ #23579] + * misc/tst-preadvwritev2-common.c (do_test_with_invalid_fd): New + test. + * misc/tst-preadvwritev2.c, misc/tst-preadvwritev64v2.c (do_test): + Call do_test_with_invalid_fd. + * sysdeps/unix/sysv/linux/preadv2.c (preadv2): Use fallback code iff + errno is ENOSYS. + * sysdeps/unix/sysv/linux/preadv64v2.c (preadv64v2): Likewise. + * sysdeps/unix/sysv/linux/pwritev2.c (pwritev2): Likewise. + * sysdeps/unix/sysv/linux/pwritev64v2.c (pwritev64v2): Likewise. + +diff --git a/misc/tst-preadvwritev2-common.c b/misc/tst-preadvwritev2-common.c +index f889a21544947042..50b9da3fea56d288 100644 +--- a/misc/tst-preadvwritev2-common.c ++++ b/misc/tst-preadvwritev2-common.c +@@ -19,9 +19,6 @@ + #include + #include + +-static void +-do_test_with_invalid_flags (void) +-{ + #ifndef RWF_HIPRI + # define RWF_HIPRI 0 + #endif +@@ -39,6 +36,68 @@ do_test_with_invalid_flags (void) + #endif + #define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT \ + | RWF_APPEND) ++ ++static void ++do_test_with_invalid_fd (void) ++{ ++ char buf[256]; ++ struct iovec iov = { buf, sizeof buf }; ++ ++ /* Check with flag being 0 to use the fallback code which calls pwritev ++ or writev. */ ++ TEST_VERIFY (preadv2 (-1, &iov, 1, -1, 0) == -1); ++ TEST_COMPARE (errno, EBADF); ++ TEST_VERIFY (pwritev2 (-1, &iov, 1, -1, 0) == -1); ++ TEST_COMPARE (errno, EBADF); ++ ++ /* Same tests as before but with flags being different than 0. Since ++ there is no emulation for any flag value, fallback code returns ++ ENOTSUP. This is different running on a kernel with preadv2/pwritev2 ++ support, where EBADF is returned). */ ++ TEST_VERIFY (preadv2 (-1, &iov, 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EBADF || errno == ENOTSUP); ++ TEST_VERIFY (pwritev2 (-1, &iov, 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EBADF || errno == ENOTSUP); ++} ++ ++static void ++do_test_with_invalid_iov (void) ++{ ++ { ++ char buf[256]; ++ struct iovec iov; ++ ++ iov.iov_base = buf; ++ iov.iov_len = (size_t)SSIZE_MAX + 1; ++ ++ TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, 0) == -1); ++ TEST_COMPARE (errno, EINVAL); ++ TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, 0) == -1); ++ TEST_COMPARE (errno, EINVAL); ++ ++ /* Same as for invalid file descriptor tests, emulation fallback ++ first checks for flag value and return ENOTSUP. */ ++ TEST_VERIFY (preadv2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); ++ TEST_VERIFY (pwritev2 (temp_fd, &iov, 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); ++ } ++ ++ { ++ /* An invalid iovec buffer should trigger an invalid memory access ++ or an error (Linux for instance returns EFAULT). */ ++ struct iovec iov[IOV_MAX+1] = { 0 }; ++ ++ TEST_VERIFY (preadv2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); ++ TEST_VERIFY (pwritev2 (temp_fd, iov, IOV_MAX + 1, 0, RWF_HIPRI) == -1); ++ TEST_VERIFY (errno == EINVAL || errno == ENOTSUP); ++ } ++} ++ ++static void ++do_test_with_invalid_flags (void) ++{ + /* Set the next bit from the mask of all supported flags. */ + int invalid_flag = RWF_SUPPORTED != 0 ? __builtin_clz (RWF_SUPPORTED) : 2; + invalid_flag = 0x1 << ((sizeof (int) * CHAR_BIT) - invalid_flag); +diff --git a/misc/tst-preadvwritev2.c b/misc/tst-preadvwritev2.c +index be22802dbe00317f..cb58cbe41ecc639d 100644 +--- a/misc/tst-preadvwritev2.c ++++ b/misc/tst-preadvwritev2.c +@@ -30,6 +30,8 @@ do_test (void) + { + do_test_with_invalid_flags (); + do_test_without_offset (); ++ do_test_with_invalid_fd (); ++ do_test_with_invalid_iov (); + + return do_test_with_offset (0); + } +diff --git a/misc/tst-preadvwritev64v2.c b/misc/tst-preadvwritev64v2.c +index 8d3cc32b284dbf4c..6a9de54c786acc53 100644 +--- a/misc/tst-preadvwritev64v2.c ++++ b/misc/tst-preadvwritev64v2.c +@@ -32,6 +32,8 @@ do_test (void) + { + do_test_with_invalid_flags (); + do_test_without_offset (); ++ do_test_with_invalid_fd (); ++ do_test_with_invalid_iov (); + + return do_test_with_offset (0); + } +diff --git a/sysdeps/unix/sysv/linux/preadv2.c b/sysdeps/unix/sysv/linux/preadv2.c +index c8bf0764ef2629fc..bb08cbc5fd96962e 100644 +--- a/sysdeps/unix/sysv/linux/preadv2.c ++++ b/sysdeps/unix/sysv/linux/preadv2.c +@@ -32,7 +32,7 @@ preadv2 (int fd, const struct iovec *vector, int count, off_t offset, + # ifdef __NR_preadv2 + ssize_t result = SYSCALL_CANCEL (preadv2, fd, vector, count, + LO_HI_LONG (offset), flags); +- if (result >= 0) ++ if (result >= 0 || errno != ENOSYS) + return result; + # endif + /* Trying to emulate the preadv2 syscall flags is troublesome: +diff --git a/sysdeps/unix/sysv/linux/preadv64v2.c b/sysdeps/unix/sysv/linux/preadv64v2.c +index d7400a0252a8c6a1..b72a047347b1db0e 100644 +--- a/sysdeps/unix/sysv/linux/preadv64v2.c ++++ b/sysdeps/unix/sysv/linux/preadv64v2.c +@@ -30,7 +30,7 @@ preadv64v2 (int fd, const struct iovec *vector, int count, off64_t offset, + #ifdef __NR_preadv64v2 + ssize_t result = SYSCALL_CANCEL (preadv64v2, fd, vector, count, + LO_HI_LONG (offset), flags); +- if (result >= 0) ++ if (result >= 0 || errno != ENOSYS) + return result; + #endif + /* Trying to emulate the preadv2 syscall flags is troublesome: +diff --git a/sysdeps/unix/sysv/linux/pwritev2.c b/sysdeps/unix/sysv/linux/pwritev2.c +index 29c2264c8f3d949a..26333ebd43c5f0af 100644 +--- a/sysdeps/unix/sysv/linux/pwritev2.c ++++ b/sysdeps/unix/sysv/linux/pwritev2.c +@@ -28,7 +28,7 @@ pwritev2 (int fd, const struct iovec *vector, int count, off_t offset, + # ifdef __NR_pwritev2 + ssize_t result = SYSCALL_CANCEL (pwritev2, fd, vector, count, + LO_HI_LONG (offset), flags); +- if (result >= 0) ++ if (result >= 0 || errno != ENOSYS) + return result; + # endif + /* Trying to emulate the pwritev2 syscall flags is troublesome: +diff --git a/sysdeps/unix/sysv/linux/pwritev64v2.c b/sysdeps/unix/sysv/linux/pwritev64v2.c +index 42da321149bce40d..17ea905aa6a8db94 100644 +--- a/sysdeps/unix/sysv/linux/pwritev64v2.c ++++ b/sysdeps/unix/sysv/linux/pwritev64v2.c +@@ -30,7 +30,7 @@ pwritev64v2 (int fd, const struct iovec *vector, int count, off64_t offset, + #ifdef __NR_pwritev64v2 + ssize_t result = SYSCALL_CANCEL (pwritev64v2, fd, vector, count, + LO_HI_LONG (offset), flags); +- if (result >= 0) ++ if (result >= 0 || errno != ENOSYS) + return result; + #endif + /* Trying to emulate the pwritev2 syscall flags is troublesome: diff --git a/glibc-rh1645597.patch b/glibc-rh1645597.patch new file mode 100755 index 0000000..eee0633 --- /dev/null +++ b/glibc-rh1645597.patch @@ -0,0 +1,33 @@ +commit dae3ed958c3d0090838e49ff4f78c201262b1cf0 +Author: Rafal Luzynski +Date: Tue Oct 2 23:34:18 2018 +0200 + + kl_GL: Fix spelling of Sunday, should be "sapaat" (bug 20209). + + Although CLDR says otherwise, it is confirmed by Oqaasileriffik, the + official Greenlandic language regulator, that this change is correct. + + [BZ #20209] + * localedata/locales/kl_GL: (abday): Fix spelling of Sun (Sunday), + should be "sap" rather than "sab". + (day): Fix spelling of Sunday, should be "sapaat" rather than + "sabaat". + +diff --git a/localedata/locales/kl_GL b/localedata/locales/kl_GL +index 5ab14a31aade8644..5723ce7dcf9c5742 100644 +--- a/localedata/locales/kl_GL ++++ b/localedata/locales/kl_GL +@@ -70,11 +70,11 @@ copy "da_DK" + END LC_NUMERIC + + LC_TIME +-abday "sab";"ata";/ ++abday "sap";"ata";/ + "mar";"pin";/ + "sis";"tal";/ + "arf" +-day "sabaat";/ ++day "sapaat";/ + "ataasinngorneq";/ + "marlunngorneq";/ + "pingasunngorneq";/ diff --git a/glibc-rh1645601.patch b/glibc-rh1645601.patch new file mode 100755 index 0000000..6b1804e --- /dev/null +++ b/glibc-rh1645601.patch @@ -0,0 +1,134 @@ +commit 7b1f9406761331cf35fe521fbdb592beecf68a2c +Author: H.J. Lu +Date: Fri Sep 28 13:31:19 2018 -0700 + + i386: Use _dl_runtime_[resolve|profile]_shstk for SHSTK [BZ #23716] + + When elf_machine_runtime_setup is called to set up resolver, it should + use _dl_runtime_resolve_shstk or _dl_runtime_profile_shstk if SHSTK is + enabled by kernel. + + Tested on i686 with and without --enable-cet as well as on CET emulator + with --enable-cet. + + [BZ #23716] + * sysdeps/i386/dl-cet.c: Removed. + * sysdeps/i386/dl-machine.h (_dl_runtime_resolve_shstk): New + prototype. + (_dl_runtime_profile_shstk): Likewise. + (elf_machine_runtime_setup): Use _dl_runtime_profile_shstk or + _dl_runtime_resolve_shstk if SHSTK is enabled by kernel. + + Signed-off-by: H.J. Lu + +diff --git a/sysdeps/i386/dl-cet.c b/sysdeps/i386/dl-cet.c +deleted file mode 100644 +index 5d9a4e8d5179b572..0000000000000000 +--- a/sysdeps/i386/dl-cet.c ++++ /dev/null +@@ -1,67 +0,0 @@ +-/* Linux/i386 CET initializers function. +- Copyright (C) 2018 Free Software Foundation, Inc. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +- +-#define LINKAGE static inline +-#define _dl_cet_check cet_check +-#include +-#undef _dl_cet_check +- +-#ifdef SHARED +-void +-_dl_cet_check (struct link_map *main_map, const char *program) +-{ +- cet_check (main_map, program); +- +- if ((GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK)) +- { +- /* Replace _dl_runtime_resolve and _dl_runtime_profile with +- _dl_runtime_resolve_shstk and _dl_runtime_profile_shstk, +- respectively if SHSTK is enabled. */ +- extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden; +- extern void _dl_runtime_resolve_shstk (Elf32_Word) attribute_hidden; +- extern void _dl_runtime_profile (Elf32_Word) attribute_hidden; +- extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden; +- unsigned int i; +- struct link_map *l; +- Elf32_Addr *got; +- +- if (main_map->l_info[DT_JMPREL]) +- { +- got = (Elf32_Addr *) D_PTR (main_map, l_info[DT_PLTGOT]); +- if (got[2] == (Elf32_Addr) &_dl_runtime_resolve) +- got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk; +- else if (got[2] == (Elf32_Addr) &_dl_runtime_profile) +- got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk; +- } +- +- i = main_map->l_searchlist.r_nlist; +- while (i-- > 0) +- { +- l = main_map->l_initfini[i]; +- if (l->l_info[DT_JMPREL]) +- { +- got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]); +- if (got[2] == (Elf32_Addr) &_dl_runtime_resolve) +- got[2] = (Elf32_Addr) &_dl_runtime_resolve_shstk; +- else if (got[2] == (Elf32_Addr) &_dl_runtime_profile) +- got[2] = (Elf32_Addr) &_dl_runtime_profile_shstk; +- } +- } +- } +-} +-#endif +diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h +index 1afdcbd9ea2626e4..f6cfb90e21015250 100644 +--- a/sysdeps/i386/dl-machine.h ++++ b/sysdeps/i386/dl-machine.h +@@ -67,6 +67,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + Elf32_Addr *got; + extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden; + extern void _dl_runtime_profile (Elf32_Word) attribute_hidden; ++ extern void _dl_runtime_resolve_shstk (Elf32_Word) attribute_hidden; ++ extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden; ++ /* Check if SHSTK is enabled by kernel. */ ++ bool shstk_enabled ++ = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0; + + if (l->l_info[DT_JMPREL] && lazy) + { +@@ -93,7 +98,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + end in this function. */ + if (__glibc_unlikely (profile)) + { +- got[2] = (Elf32_Addr) &_dl_runtime_profile; ++ got[2] = (shstk_enabled ++ ? (Elf32_Addr) &_dl_runtime_profile_shstk ++ : (Elf32_Addr) &_dl_runtime_profile); + + if (GLRO(dl_profile) != NULL + && _dl_name_match_p (GLRO(dl_profile), l)) +@@ -104,7 +111,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + else + /* This function will get called to fix up the GOT entry indicated by + the offset on the stack, and then jump to the resolved address. */ +- got[2] = (Elf32_Addr) &_dl_runtime_resolve; ++ got[2] = (shstk_enabled ++ ? (Elf32_Addr) &_dl_runtime_resolve_shstk ++ : (Elf32_Addr) &_dl_runtime_resolve); + } + + return lazy; diff --git a/glibc-rh1645604.patch b/glibc-rh1645604.patch new file mode 100755 index 0000000..f5c287b --- /dev/null +++ b/glibc-rh1645604.patch @@ -0,0 +1,738 @@ +commit 403b4feb22dcbc85ace72a361d2a951380372471 +Author: Stefan Liebler +Date: Wed Oct 17 12:23:04 2018 +0200 + + Fix race in pthread_mutex_lock while promoting to PTHREAD_MUTEX_ELISION_NP [BZ #23275] + + The race leads either to pthread_mutex_destroy returning EBUSY + or triggering an assertion (See description in bugzilla). + + This patch is fixing the race by ensuring that the elision path is + used in all cases if elision is enabled by the GLIBC_TUNABLES framework. + + The __kind variable in struct __pthread_mutex_s is accessed concurrently. + Therefore we are now using the atomic macros. + + The new testcase tst-mutex10 is triggering the race on s390x and intel. + Presumably also on power, but I don't have access to a power machine + with lock-elision. At least the code for power is the same as on the other + two architectures. + + ChangeLog: + + [BZ #23275] + * nptl/tst-mutex10.c: New File. + * nptl/Makefile (tests): Add tst-mutex10. + (tst-mutex10-ENV): New variable. + * sysdeps/unix/sysv/linux/s390/force-elision.h: (FORCE_ELISION): + Ensure that elision path is used if elision is available. + * sysdeps/unix/sysv/linux/powerpc/force-elision.h (FORCE_ELISION): + Likewise. + * sysdeps/unix/sysv/linux/x86/force-elision.h: (FORCE_ELISION): + Likewise. + * nptl/pthreadP.h (PTHREAD_MUTEX_TYPE, PTHREAD_MUTEX_TYPE_ELISION) + (PTHREAD_MUTEX_PSHARED): Use atomic_load_relaxed. + * nptl/pthread_mutex_consistent.c (pthread_mutex_consistent): Likewise. + * nptl/pthread_mutex_getprioceiling.c (pthread_mutex_getprioceiling): + Likewise. + * nptl/pthread_mutex_lock.c (__pthread_mutex_lock_full) + (__pthread_mutex_cond_lock_adjust): Likewise. + * nptl/pthread_mutex_setprioceiling.c (pthread_mutex_setprioceiling): + Likewise. + * nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock): Likewise. + * nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock): Likewise. + * nptl/pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Likewise. + * sysdeps/nptl/bits/thread-shared-types.h (struct __pthread_mutex_s): + Add comments. + * nptl/pthread_mutex_destroy.c (__pthread_mutex_destroy): + Use atomic_load_relaxed and atomic_store_relaxed. + * nptl/pthread_mutex_init.c (__pthread_mutex_init): + Use atomic_store_relaxed. + +diff --git a/nptl/Makefile b/nptl/Makefile +index be8066524cdc57db..49b6faa330c492e0 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -241,9 +241,9 @@ LDLIBS-tst-minstack-throw = -lstdc++ + + tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \ + tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \ +- tst-mutex7 tst-mutex9 tst-mutex5a tst-mutex7a tst-mutex7robust \ +- tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \ +- tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \ ++ tst-mutex7 tst-mutex9 tst-mutex10 tst-mutex5a tst-mutex7a \ ++ tst-mutex7robust tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 \ ++ tst-mutexpi5 tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \ + tst-mutexpi9 \ + tst-spin1 tst-spin2 tst-spin3 tst-spin4 \ + tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ +@@ -709,6 +709,8 @@ endif + + $(objpfx)tst-compat-forwarder: $(objpfx)tst-compat-forwarder-mod.so + ++tst-mutex10-ENV = GLIBC_TUNABLES=glibc.elision.enable=1 ++ + # The tests here better do not run in parallel + ifneq ($(filter %tests,$(MAKECMDGOALS)),) + .NOTPARALLEL: +diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h +index 13bdb11133536195..19efe1e35feed5be 100644 +--- a/nptl/pthreadP.h ++++ b/nptl/pthreadP.h +@@ -110,19 +110,23 @@ enum + }; + #define PTHREAD_MUTEX_PSHARED_BIT 128 + ++/* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ + #define PTHREAD_MUTEX_TYPE(m) \ +- ((m)->__data.__kind & 127) ++ (atomic_load_relaxed (&((m)->__data.__kind)) & 127) + /* Don't include NO_ELISION, as that type is always the same + as the underlying lock type. */ + #define PTHREAD_MUTEX_TYPE_ELISION(m) \ +- ((m)->__data.__kind & (127|PTHREAD_MUTEX_ELISION_NP)) ++ (atomic_load_relaxed (&((m)->__data.__kind)) \ ++ & (127 | PTHREAD_MUTEX_ELISION_NP)) + + #if LLL_PRIVATE == 0 && LLL_SHARED == 128 + # define PTHREAD_MUTEX_PSHARED(m) \ +- ((m)->__data.__kind & 128) ++ (atomic_load_relaxed (&((m)->__data.__kind)) & 128) + #else + # define PTHREAD_MUTEX_PSHARED(m) \ +- (((m)->__data.__kind & 128) ? LLL_SHARED : LLL_PRIVATE) ++ ((atomic_load_relaxed (&((m)->__data.__kind)) & 128) \ ++ ? LLL_SHARED : LLL_PRIVATE) + #endif + + /* The kernel when waking robust mutexes on exit never uses +diff --git a/nptl/pthread_mutex_consistent.c b/nptl/pthread_mutex_consistent.c +index 85b8e1a6cb027e9b..4fbd875430439e4d 100644 +--- a/nptl/pthread_mutex_consistent.c ++++ b/nptl/pthread_mutex_consistent.c +@@ -23,8 +23,11 @@ + int + pthread_mutex_consistent (pthread_mutex_t *mutex) + { +- /* Test whether this is a robust mutex with a dead owner. */ +- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0 ++ /* Test whether this is a robust mutex with a dead owner. ++ See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ if ((atomic_load_relaxed (&(mutex->__data.__kind)) ++ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0 + || mutex->__data.__owner != PTHREAD_MUTEX_INCONSISTENT) + return EINVAL; + +diff --git a/nptl/pthread_mutex_destroy.c b/nptl/pthread_mutex_destroy.c +index 5a22611541995778..713ea684962fefc1 100644 +--- a/nptl/pthread_mutex_destroy.c ++++ b/nptl/pthread_mutex_destroy.c +@@ -27,12 +27,17 @@ __pthread_mutex_destroy (pthread_mutex_t *mutex) + { + LIBC_PROBE (mutex_destroy, 1, mutex); + +- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0 ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ if ((atomic_load_relaxed (&(mutex->__data.__kind)) ++ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0 + && mutex->__data.__nusers != 0) + return EBUSY; + +- /* Set to an invalid value. */ +- mutex->__data.__kind = -1; ++ /* Set to an invalid value. Relaxed MO is enough as it is undefined behavior ++ if the mutex is used after it has been destroyed. But you can reinitialize ++ it with pthread_mutex_init. */ ++ atomic_store_relaxed (&(mutex->__data.__kind), -1); + + return 0; + } +diff --git a/nptl/pthread_mutex_getprioceiling.c b/nptl/pthread_mutex_getprioceiling.c +index efa37b0d99201f57..ee85949578475f3a 100644 +--- a/nptl/pthread_mutex_getprioceiling.c ++++ b/nptl/pthread_mutex_getprioceiling.c +@@ -24,7 +24,9 @@ + int + pthread_mutex_getprioceiling (const pthread_mutex_t *mutex, int *prioceiling) + { +- if (__builtin_expect ((mutex->__data.__kind ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ if (__builtin_expect ((atomic_load_relaxed (&(mutex->__data.__kind)) + & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0, 0)) + return EINVAL; + +diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c +index d8fe4737289c0bd7..5cf290c272e27915 100644 +--- a/nptl/pthread_mutex_init.c ++++ b/nptl/pthread_mutex_init.c +@@ -101,7 +101,7 @@ __pthread_mutex_init (pthread_mutex_t *mutex, + memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T); + + /* Copy the values from the attribute. */ +- mutex->__data.__kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS; ++ int mutex_kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS; + + if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0) + { +@@ -111,17 +111,17 @@ __pthread_mutex_init (pthread_mutex_t *mutex, + return ENOTSUP; + #endif + +- mutex->__data.__kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP; ++ mutex_kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP; + } + + switch (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK) + { + case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: +- mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP; ++ mutex_kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP; + break; + + case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: +- mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP; ++ mutex_kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP; + + int ceiling = (imutexattr->mutexkind + & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK) +@@ -145,7 +145,11 @@ __pthread_mutex_init (pthread_mutex_t *mutex, + FUTEX_PRIVATE_FLAG FUTEX_WAKE. */ + if ((imutexattr->mutexkind & (PTHREAD_MUTEXATTR_FLAG_PSHARED + | PTHREAD_MUTEXATTR_FLAG_ROBUST)) != 0) +- mutex->__data.__kind |= PTHREAD_MUTEX_PSHARED_BIT; ++ mutex_kind |= PTHREAD_MUTEX_PSHARED_BIT; ++ ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ atomic_store_relaxed (&(mutex->__data.__kind), mutex_kind); + + /* Default values: mutex not used yet. */ + // mutex->__count = 0; already done by memset +diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c +index 1519c142bd6ec5cc..29cc143e6cbf2421 100644 +--- a/nptl/pthread_mutex_lock.c ++++ b/nptl/pthread_mutex_lock.c +@@ -62,6 +62,8 @@ static int __pthread_mutex_lock_full (pthread_mutex_t *mutex) + int + __pthread_mutex_lock (pthread_mutex_t *mutex) + { ++ /* See concurrency notes regarding mutex type which is loaded from __kind ++ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */ + unsigned int type = PTHREAD_MUTEX_TYPE_ELISION (mutex); + + LIBC_PROBE (mutex_entry, 1, mutex); +@@ -350,8 +352,14 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + { +- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; +- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; ++ int kind, robust; ++ { ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind)); ++ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP; ++ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; ++ } + + if (robust) + { +@@ -502,7 +510,10 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) + case PTHREAD_MUTEX_PP_NORMAL_NP: + case PTHREAD_MUTEX_PP_ADAPTIVE_NP: + { +- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ int kind = atomic_load_relaxed (&(mutex->__data.__kind)) ++ & PTHREAD_MUTEX_KIND_MASK_NP; + + oldval = mutex->__data.__lock; + +@@ -607,15 +618,18 @@ hidden_def (__pthread_mutex_lock) + void + __pthread_mutex_cond_lock_adjust (pthread_mutex_t *mutex) + { +- assert ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0); +- assert ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0); +- assert ((mutex->__data.__kind & PTHREAD_MUTEX_PSHARED_BIT) == 0); ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind)); ++ assert ((mutex_kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0); ++ assert ((mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0); ++ assert ((mutex_kind & PTHREAD_MUTEX_PSHARED_BIT) == 0); + + /* Record the ownership. */ + pid_t id = THREAD_GETMEM (THREAD_SELF, tid); + mutex->__data.__owner = id; + +- if (mutex->__data.__kind == PTHREAD_MUTEX_PI_RECURSIVE_NP) ++ if (mutex_kind == PTHREAD_MUTEX_PI_RECURSIVE_NP) + ++mutex->__data.__count; + } + #endif +diff --git a/nptl/pthread_mutex_setprioceiling.c b/nptl/pthread_mutex_setprioceiling.c +index 8594874f8588b7a8..8306cabcf4e56174 100644 +--- a/nptl/pthread_mutex_setprioceiling.c ++++ b/nptl/pthread_mutex_setprioceiling.c +@@ -27,9 +27,10 @@ int + pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling, + int *old_ceiling) + { +- /* The low bits of __kind aren't ever changed after pthread_mutex_init, +- so we don't need a lock yet. */ +- if ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0) ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ if ((atomic_load_relaxed (&(mutex->__data.__kind)) ++ & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0) + return EINVAL; + + /* See __init_sched_fifo_prio. */ +diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c +index 28237b0e58cfcaf5..888c12fe28b2ebfd 100644 +--- a/nptl/pthread_mutex_timedlock.c ++++ b/nptl/pthread_mutex_timedlock.c +@@ -53,6 +53,8 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex, + /* We must not check ABSTIME here. If the thread does not block + abstime must not be checked for a valid value. */ + ++ /* See concurrency notes regarding mutex type which is loaded from __kind ++ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */ + switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex), + PTHREAD_MUTEX_TIMED_NP)) + { +@@ -338,8 +340,14 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex, + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + { +- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; +- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; ++ int kind, robust; ++ { ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind)); ++ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP; ++ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; ++ } + + if (robust) + { +@@ -509,7 +517,10 @@ __pthread_mutex_timedlock (pthread_mutex_t *mutex, + case PTHREAD_MUTEX_PP_NORMAL_NP: + case PTHREAD_MUTEX_PP_ADAPTIVE_NP: + { +- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ int kind = atomic_load_relaxed (&(mutex->__data.__kind)) ++ & PTHREAD_MUTEX_KIND_MASK_NP; + + oldval = mutex->__data.__lock; + +diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c +index 7de61f4f688c1537..fa90c1d1e6f5afc2 100644 +--- a/nptl/pthread_mutex_trylock.c ++++ b/nptl/pthread_mutex_trylock.c +@@ -36,6 +36,8 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + int oldval; + pid_t id = THREAD_GETMEM (THREAD_SELF, tid); + ++ /* See concurrency notes regarding mutex type which is loaded from __kind ++ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */ + switch (__builtin_expect (PTHREAD_MUTEX_TYPE_ELISION (mutex), + PTHREAD_MUTEX_TIMED_NP)) + { +@@ -199,8 +201,14 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + { +- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; +- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; ++ int kind, robust; ++ { ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind)); ++ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP; ++ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; ++ } + + if (robust) + /* Note: robust PI futexes are signaled by setting bit 0. */ +@@ -325,7 +333,10 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex) + case PTHREAD_MUTEX_PP_NORMAL_NP: + case PTHREAD_MUTEX_PP_ADAPTIVE_NP: + { +- int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ int kind = atomic_load_relaxed (&(mutex->__data.__kind)) ++ & PTHREAD_MUTEX_KIND_MASK_NP; + + oldval = mutex->__data.__lock; + +diff --git a/nptl/pthread_mutex_unlock.c b/nptl/pthread_mutex_unlock.c +index 9ea62943b7c6b159..68d04d53955584e5 100644 +--- a/nptl/pthread_mutex_unlock.c ++++ b/nptl/pthread_mutex_unlock.c +@@ -35,6 +35,8 @@ int + attribute_hidden + __pthread_mutex_unlock_usercnt (pthread_mutex_t *mutex, int decr) + { ++ /* See concurrency notes regarding mutex type which is loaded from __kind ++ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */ + int type = PTHREAD_MUTEX_TYPE_ELISION (mutex); + if (__builtin_expect (type & + ~(PTHREAD_MUTEX_KIND_MASK_NP|PTHREAD_MUTEX_ELISION_FLAGS_NP), 0)) +@@ -222,13 +224,19 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr) + /* If the previous owner died and the caller did not succeed in + making the state consistent, mark the mutex as unrecoverable + and make all waiters. */ +- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0 ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ if ((atomic_load_relaxed (&(mutex->__data.__kind)) ++ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0 + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_INCONSISTENT, 0)) + pi_notrecoverable: + newowner = PTHREAD_MUTEX_NOTRECOVERABLE; + +- if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0) ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ if ((atomic_load_relaxed (&(mutex->__data.__kind)) ++ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0) + { + continue_pi_robust: + /* Remove mutex from the list. +@@ -251,7 +259,10 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr) + /* Unlock. Load all necessary mutex data before releasing the mutex + to not violate the mutex destruction requirements (see + lll_unlock). */ +- int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; ++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s ++ in sysdeps/nptl/bits/thread-shared-types.h. */ ++ int robust = atomic_load_relaxed (&(mutex->__data.__kind)) ++ & PTHREAD_MUTEX_ROBUST_NORMAL_NP; + private = (robust + ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) + : PTHREAD_MUTEX_PSHARED (mutex)); +diff --git a/nptl/tst-mutex10.c b/nptl/tst-mutex10.c +new file mode 100644 +index 0000000000000000..e1113ca60a7c8db5 +--- /dev/null ++++ b/nptl/tst-mutex10.c +@@ -0,0 +1,109 @@ ++/* Testing race while enabling lock elision. ++ Copyright (C) 2018 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 ++ . */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static pthread_barrier_t barrier; ++static pthread_mutex_t mutex; ++static long long int iteration_count = 1000000; ++static unsigned int thread_count = 3; ++ ++static void * ++thr_func (void *arg) ++{ ++ long long int i; ++ for (i = 0; i < iteration_count; i++) ++ { ++ if ((uintptr_t) arg == 0) ++ { ++ xpthread_mutex_destroy (&mutex); ++ xpthread_mutex_init (&mutex, NULL); ++ } ++ ++ xpthread_barrier_wait (&barrier); ++ ++ /* Test if enabling lock elision works if it is enabled concurrently. ++ There was a race in FORCE_ELISION macro which leads to either ++ pthread_mutex_destroy returning EBUSY as the owner was recorded ++ by pthread_mutex_lock - in "normal mutex" code path - but was not ++ resetted in pthread_mutex_unlock - in "elision" code path. ++ Or it leads to the assertion in nptl/pthread_mutex_lock.c: ++ assert (mutex->__data.__owner == 0); ++ Please ensure that the test is run with lock elision: ++ export GLIBC_TUNABLES=glibc.elision.enable=1 */ ++ xpthread_mutex_lock (&mutex); ++ xpthread_mutex_unlock (&mutex); ++ ++ xpthread_barrier_wait (&barrier); ++ } ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ unsigned int i; ++ printf ("Starting %d threads to run %lld iterations.\n", ++ thread_count, iteration_count); ++ ++ pthread_t *threads = xmalloc (thread_count * sizeof (pthread_t)); ++ xpthread_barrier_init (&barrier, NULL, thread_count); ++ xpthread_mutex_init (&mutex, NULL); ++ ++ for (i = 0; i < thread_count; i++) ++ threads[i] = xpthread_create (NULL, thr_func, (void *) (uintptr_t) i); ++ ++ for (i = 0; i < thread_count; i++) ++ xpthread_join (threads[i]); ++ ++ xpthread_barrier_destroy (&barrier); ++ free (threads); ++ ++ return EXIT_SUCCESS; ++} ++ ++#define OPT_ITERATIONS 10000 ++#define OPT_THREADS 10001 ++#define CMDLINE_OPTIONS \ ++ { "iterations", required_argument, NULL, OPT_ITERATIONS }, \ ++ { "threads", required_argument, NULL, OPT_THREADS }, ++static void ++cmdline_process (int c) ++{ ++ long long int arg = strtoll (optarg, NULL, 0); ++ switch (c) ++ { ++ case OPT_ITERATIONS: ++ if (arg > 0) ++ iteration_count = arg; ++ break; ++ case OPT_THREADS: ++ if (arg > 0 && arg < 100) ++ thread_count = arg; ++ break; ++ } ++} ++#define CMDLINE_PROCESS cmdline_process ++#define TIMEOUT 50 ++#include +diff --git a/sysdeps/nptl/bits/thread-shared-types.h b/sysdeps/nptl/bits/thread-shared-types.h +index 1e2092a05d5610f7..05c94e7a710c0eb9 100644 +--- a/sysdeps/nptl/bits/thread-shared-types.h ++++ b/sysdeps/nptl/bits/thread-shared-types.h +@@ -124,7 +124,27 @@ struct __pthread_mutex_s + unsigned int __nusers; + #endif + /* KIND must stay at this position in the structure to maintain +- binary compatibility with static initializers. */ ++ binary compatibility with static initializers. ++ ++ Concurrency notes: ++ The __kind of a mutex is initialized either by the static ++ PTHREAD_MUTEX_INITIALIZER or by a call to pthread_mutex_init. ++ ++ After a mutex has been initialized, the __kind of a mutex is usually not ++ changed. BUT it can be set to -1 in pthread_mutex_destroy or elision can ++ be enabled. This is done concurrently in the pthread_mutex_*lock functions ++ by using the macro FORCE_ELISION. This macro is only defined for ++ architectures which supports lock elision. ++ ++ For elision, there are the flags PTHREAD_MUTEX_ELISION_NP and ++ PTHREAD_MUTEX_NO_ELISION_NP which can be set in addition to the already set ++ type of a mutex. ++ Before a mutex is initialized, only PTHREAD_MUTEX_NO_ELISION_NP can be set ++ with pthread_mutexattr_settype. ++ After a mutex has been initialized, the functions pthread_mutex_*lock can ++ enable elision - if the mutex-type and the machine supports it - by setting ++ the flag PTHREAD_MUTEX_ELISION_NP. This is done concurrently. Afterwards ++ the lock / unlock functions are using specific elision code-paths. */ + int __kind; + __PTHREAD_COMPAT_PADDING_MID + #if __PTHREAD_MUTEX_NUSERS_AFTER_KIND +diff --git a/sysdeps/unix/sysv/linux/powerpc/force-elision.h b/sysdeps/unix/sysv/linux/powerpc/force-elision.h +index fe5d6ceade2bad36..d8f5a4b1c7713bd4 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/force-elision.h ++++ b/sysdeps/unix/sysv/linux/powerpc/force-elision.h +@@ -18,9 +18,45 @@ + + /* Automatically enable elision for existing user lock kinds. */ + #define FORCE_ELISION(m, s) \ +- if (__pthread_force_elision \ +- && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \ ++ if (__pthread_force_elision) \ + { \ +- mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \ +- s; \ ++ /* See concurrency notes regarding __kind in \ ++ struct __pthread_mutex_s in \ ++ sysdeps/nptl/bits/thread-shared-types.h. \ ++ \ ++ There are the following cases for the kind of a mutex \ ++ (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags \ ++ PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where \ ++ only one of both flags can be set): \ ++ - both flags are not set: \ ++ This is the first lock operation for this mutex. Enable \ ++ elision as it is not enabled so far. \ ++ Note: It can happen that multiple threads are calling e.g. \ ++ pthread_mutex_lock at the same time as the first lock \ ++ operation for this mutex. Then elision is enabled for this \ ++ mutex by multiple threads. Storing with relaxed MO is enough \ ++ as all threads will store the same new value for the kind of \ ++ the mutex. But we have to ensure that we always use the \ ++ elision path regardless if this thread has enabled elision or \ ++ another one. \ ++ \ ++ - PTHREAD_MUTEX_ELISION_NP flag is set: \ ++ Elision was already enabled for this mutex by a previous lock \ ++ operation. See case above. Just use the elision path. \ ++ \ ++ - PTHREAD_MUTEX_NO_ELISION_NP flag is set: \ ++ Elision was explicitly disabled by pthread_mutexattr_settype. \ ++ Do not use the elision path. \ ++ Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be \ ++ changed after mutex initialization. */ \ ++ int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind)); \ ++ if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \ ++ { \ ++ mutex_kind |= PTHREAD_MUTEX_ELISION_NP; \ ++ atomic_store_relaxed (&((m)->__data.__kind), mutex_kind); \ ++ } \ ++ if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0) \ ++ { \ ++ s; \ ++ } \ + } +diff --git a/sysdeps/unix/sysv/linux/s390/force-elision.h b/sysdeps/unix/sysv/linux/s390/force-elision.h +index d8a1b9972f739cfe..71f32367dd6b6489 100644 +--- a/sysdeps/unix/sysv/linux/s390/force-elision.h ++++ b/sysdeps/unix/sysv/linux/s390/force-elision.h +@@ -18,9 +18,45 @@ + + /* Automatically enable elision for existing user lock kinds. */ + #define FORCE_ELISION(m, s) \ +- if (__pthread_force_elision \ +- && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \ ++ if (__pthread_force_elision) \ + { \ +- mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \ +- s; \ ++ /* See concurrency notes regarding __kind in \ ++ struct __pthread_mutex_s in \ ++ sysdeps/nptl/bits/thread-shared-types.h. \ ++ \ ++ There are the following cases for the kind of a mutex \ ++ (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags \ ++ PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where \ ++ only one of both flags can be set): \ ++ - both flags are not set: \ ++ This is the first lock operation for this mutex. Enable \ ++ elision as it is not enabled so far. \ ++ Note: It can happen that multiple threads are calling e.g. \ ++ pthread_mutex_lock at the same time as the first lock \ ++ operation for this mutex. Then elision is enabled for this \ ++ mutex by multiple threads. Storing with relaxed MO is enough \ ++ as all threads will store the same new value for the kind of \ ++ the mutex. But we have to ensure that we always use the \ ++ elision path regardless if this thread has enabled elision or \ ++ another one. \ ++ \ ++ - PTHREAD_MUTEX_ELISION_NP flag is set: \ ++ Elision was already enabled for this mutex by a previous lock \ ++ operation. See case above. Just use the elision path. \ ++ \ ++ - PTHREAD_MUTEX_NO_ELISION_NP flag is set: \ ++ Elision was explicitly disabled by pthread_mutexattr_settype. \ ++ Do not use the elision path. \ ++ Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be \ ++ changed after mutex initialization. */ \ ++ int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind)); \ ++ if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \ ++ { \ ++ mutex_kind |= PTHREAD_MUTEX_ELISION_NP; \ ++ atomic_store_relaxed (&((m)->__data.__kind), mutex_kind); \ ++ } \ ++ if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0) \ ++ { \ ++ s; \ ++ } \ + } +diff --git a/sysdeps/unix/sysv/linux/x86/force-elision.h b/sysdeps/unix/sysv/linux/x86/force-elision.h +index dd659c908f3046c1..61282d6678d89787 100644 +--- a/sysdeps/unix/sysv/linux/x86/force-elision.h ++++ b/sysdeps/unix/sysv/linux/x86/force-elision.h +@@ -18,9 +18,45 @@ + + /* Automatically enable elision for existing user lock kinds. */ + #define FORCE_ELISION(m, s) \ +- if (__pthread_force_elision \ +- && (m->__data.__kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \ ++ if (__pthread_force_elision) \ + { \ +- mutex->__data.__kind |= PTHREAD_MUTEX_ELISION_NP; \ +- s; \ ++ /* See concurrency notes regarding __kind in \ ++ struct __pthread_mutex_s in \ ++ sysdeps/nptl/bits/thread-shared-types.h. \ ++ \ ++ There are the following cases for the kind of a mutex \ ++ (The mask PTHREAD_MUTEX_ELISION_FLAGS_NP covers the flags \ ++ PTHREAD_MUTEX_ELISION_NP and PTHREAD_MUTEX_NO_ELISION_NP where \ ++ only one of both flags can be set): \ ++ - both flags are not set: \ ++ This is the first lock operation for this mutex. Enable \ ++ elision as it is not enabled so far. \ ++ Note: It can happen that multiple threads are calling e.g. \ ++ pthread_mutex_lock at the same time as the first lock \ ++ operation for this mutex. Then elision is enabled for this \ ++ mutex by multiple threads. Storing with relaxed MO is enough \ ++ as all threads will store the same new value for the kind of \ ++ the mutex. But we have to ensure that we always use the \ ++ elision path regardless if this thread has enabled elision or \ ++ another one. \ ++ \ ++ - PTHREAD_MUTEX_ELISION_NP flag is set: \ ++ Elision was already enabled for this mutex by a previous lock \ ++ operation. See case above. Just use the elision path. \ ++ \ ++ - PTHREAD_MUTEX_NO_ELISION_NP flag is set: \ ++ Elision was explicitly disabled by pthread_mutexattr_settype. \ ++ Do not use the elision path. \ ++ Note: The flag PTHREAD_MUTEX_NO_ELISION_NP will never be \ ++ changed after mutex initialization. */ \ ++ int mutex_kind = atomic_load_relaxed (&((m)->__data.__kind)); \ ++ if ((mutex_kind & PTHREAD_MUTEX_ELISION_FLAGS_NP) == 0) \ ++ { \ ++ mutex_kind |= PTHREAD_MUTEX_ELISION_NP; \ ++ atomic_store_relaxed (&((m)->__data.__kind), mutex_kind); \ ++ } \ ++ if ((mutex_kind & PTHREAD_MUTEX_ELISION_NP) != 0) \ ++ { \ ++ s; \ ++ } \ + } diff --git a/glibc-rh1646379.patch b/glibc-rh1646379.patch new file mode 100755 index 0000000..bc8865a --- /dev/null +++ b/glibc-rh1646379.patch @@ -0,0 +1,24 @@ +commit bd3b0fbae33a9a4cc5e2daf049443d5cf03d4251 +Author: Andreas Schwab +Date: Mon Nov 5 12:47:30 2018 +0100 + + libanl: properly cleanup if first helper thread creation failed (bug 22927) + +diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c +index e7c3b63cc5725b4f..80a2cff8353fcb6c 100644 +--- a/resolv/gai_misc.c ++++ b/resolv/gai_misc.c +@@ -261,8 +261,11 @@ __gai_enqueue_request (struct gaicb *gaicbp) + /* We cannot create a thread in the moment and there is + also no thread running. This is a problem. `errno' is + set to EAGAIN if this is only a temporary problem. */ +- assert (lastp->next == newp); +- lastp->next = NULL; ++ assert (requests == newp || lastp->next == newp); ++ if (lastp != NULL) ++ lastp->next = NULL; ++ else ++ requests = NULL; + requests_tail = lastp; + + newp->next = freelist; diff --git a/glibc-rh1650560-1.patch b/glibc-rh1650560-1.patch new file mode 100755 index 0000000..f6724c2 --- /dev/null +++ b/glibc-rh1650560-1.patch @@ -0,0 +1,48 @@ +commit 17b26500f9bb926d85e86821d014f7c1bb88043c +Author: Joseph Myers +Date: Mon Aug 13 21:35:27 2018 +0000 + + Update syscall-names.list for Linux 4.18. + + This patch updates sysdeps/unix/sysv/linux/syscall-names.list for + Linux 4.18. The io_pgetevents and rseq syscalls are added to the + kernel on various architectures, so need to be mentioned in this file. + + Tested with build-many-glibcs.py. + + * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel + version to 4.18. + (io_pgetevents): New syscall. + (rseq): Likewise. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 5306d538e6448163..9982a6334d46ae62 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -22,8 +22,8 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 4.17. +-kernel 4.17 ++# The list of system calls is current as of Linux 4.18. ++kernel 4.18 + + FAST_atomic_update + FAST_cmpxchg +@@ -186,6 +186,7 @@ inotify_rm_watch + io_cancel + io_destroy + io_getevents ++io_pgetevents + io_setup + io_submit + ioctl +@@ -431,6 +432,7 @@ renameat2 + request_key + restart_syscall + rmdir ++rseq + rt_sigaction + rt_sigpending + rt_sigprocmask diff --git a/glibc-rh1650560-2.patch b/glibc-rh1650560-2.patch new file mode 100755 index 0000000..1fe8f3b --- /dev/null +++ b/glibc-rh1650560-2.patch @@ -0,0 +1,30 @@ +commit 029ad711b8ad4cf0e5d98e0c138a35a23a376a74 +Author: Joseph Myers +Date: Mon Oct 22 23:26:37 2018 +0000 + + Update kernel version in syscall-names.list to 4.19. + + Linux 4.19 does not add any new syscalls (some existing ones are added + to more architectures); this patch updates the version number in + syscall-names.list to reflect that it's still current for 4.19. + + Tested with build-many-glibcs.py. + + * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel + version to 4.19. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 9982a6334d46ae62..f88001c9c38d5fc7 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -22,8 +22,8 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 4.18. +-kernel 4.18 ++# The list of system calls is current as of Linux 4.19. ++kernel 4.19 + + FAST_atomic_update + FAST_cmpxchg diff --git a/glibc-rh1650563.patch b/glibc-rh1650563.patch new file mode 100755 index 0000000..020bddf --- /dev/null +++ b/glibc-rh1650563.patch @@ -0,0 +1,127 @@ +commit 745664bd798ec8fd50438605948eea594179fba1 +Author: Florian Weimer +Date: Tue Aug 28 13:19:27 2018 +0200 + + nscd: Fix use-after-free in addgetnetgrentX [BZ #23520] + + addinnetgrX may use the heap-allocated buffer, so free the buffer + in this function. + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index 2b35389cc816c3c8..87059fb28042f0a5 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -113,7 +113,8 @@ do_notfound (struct database_dyn *db, int fd, request_header *req, + static time_t + addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + const char *key, uid_t uid, struct hashentry *he, +- struct datahead *dh, struct dataset **resultp) ++ struct datahead *dh, struct dataset **resultp, ++ void **tofreep) + { + if (__glibc_unlikely (debug_level > 0)) + { +@@ -139,6 +140,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + size_t group_len = strlen (key) + 1; + struct name_list *first_needed + = alloca (sizeof (struct name_list) + group_len); ++ *tofreep = NULL; + + if (netgroup_database == NULL + && __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database)) +@@ -151,6 +153,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + + memset (&data, '\0', sizeof (data)); + buffer = xmalloc (buflen); ++ *tofreep = buffer; + first_needed->next = first_needed; + memcpy (first_needed->name, key, group_len); + data.needed_groups = first_needed; +@@ -439,8 +442,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + } + + out: +- free (buffer); +- + *resultp = dataset; + + return timeout; +@@ -477,8 +478,12 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + group, group_len, + db, uid); + time_t timeout; ++ void *tofree; + if (result != NULL) +- timeout = result->head.timeout; ++ { ++ timeout = result->head.timeout; ++ tofree = NULL; ++ } + else + { + request_header req_get = +@@ -487,7 +492,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + .key_len = group_len + }; + timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL, +- &result); ++ &result, &tofree); + } + + struct indataset +@@ -560,7 +565,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + ++dh->nreloads; + if (cacheable) + pthread_rwlock_unlock (&db->lock); +- return timeout; ++ goto out; + } + + if (he == NULL) +@@ -596,17 +601,30 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, + dh->usable = false; + } + ++ out: ++ free (tofree); + return timeout; + } + + ++static time_t ++addgetnetgrentX_ignore (struct database_dyn *db, int fd, request_header *req, ++ const char *key, uid_t uid, struct hashentry *he, ++ struct datahead *dh) ++{ ++ struct dataset *ignore; ++ void *tofree; ++ time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, ++ &ignore, &tofree); ++ free (tofree); ++ return timeout; ++} ++ + void + addgetnetgrent (struct database_dyn *db, int fd, request_header *req, + void *key, uid_t uid) + { +- struct dataset *ignore; +- +- addgetnetgrentX (db, fd, req, key, uid, NULL, NULL, &ignore); ++ addgetnetgrentX_ignore (db, fd, req, key, uid, NULL, NULL); + } + + +@@ -619,10 +637,8 @@ readdgetnetgrent (struct database_dyn *db, struct hashentry *he, + .type = GETNETGRENT, + .key_len = he->len + }; +- struct dataset *ignore; +- +- return addgetnetgrentX (db, -1, &req, db->data + he->key, he->owner, he, dh, +- &ignore); ++ return addgetnetgrentX_ignore ++ (db, -1, &req, db->data + he->key, he->owner, he, dh); + } + + diff --git a/glibc-rh1650566.patch b/glibc-rh1650566.patch new file mode 100755 index 0000000..4aef679 --- /dev/null +++ b/glibc-rh1650566.patch @@ -0,0 +1,234 @@ +commit a6e8926f8d49a213a9abb1a61f6af964f612ab7f +Author: Paul Pluzhnikov +Date: Fri Aug 31 18:04:32 2018 -0700 + + [BZ #20271] Add newlines in __libc_fatal calls. + +diff --git a/grp/initgroups.c b/grp/initgroups.c +index f056fbf5aa6aa14c..93e7f5814da6286d 100644 +--- a/grp/initgroups.c ++++ b/grp/initgroups.c +@@ -128,7 +128,7 @@ internal_getgrouplist (const char *user, gid_t group, long int *size, + + /* This is really only for debugging. */ + if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN) +- __libc_fatal ("illegal status in internal_getgrouplist"); ++ __libc_fatal ("Illegal status in internal_getgrouplist.\n"); + + /* For compatibility reason we will continue to look for more + entries using the next service even though data has already +diff --git a/include/stdio.h b/include/stdio.h +index 9162d4e24717e31a..7a5c09089fc4d348 100644 +--- a/include/stdio.h ++++ b/include/stdio.h +@@ -98,7 +98,8 @@ enum __libc_message_action + do_backtrace = 1 << 1 /* Backtrace. */ + }; + +-/* Print out MESSAGE on the error output and abort. */ ++/* Print out MESSAGE (which should end with a newline) on the error output ++ and abort. */ + extern void __libc_fatal (const char *__message) + __attribute__ ((__noreturn__)); + extern void __libc_message (enum __libc_message_action action, +diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c +index 3e1105418210288e..ebf07ca82d87de7d 100644 +--- a/nptl/pthread_cond_wait.c ++++ b/nptl/pthread_cond_wait.c +@@ -516,7 +516,7 @@ __pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex, + struct timespec rt; + if (__clock_gettime (CLOCK_MONOTONIC, &rt) != 0) + __libc_fatal ("clock_gettime does not support " +- "CLOCK_MONOTONIC"); ++ "CLOCK_MONOTONIC\n"); + /* Convert the absolute timeout value to a relative + timeout. */ + rt.tv_sec = abstime->tv_sec - rt.tv_sec; +diff --git a/nscd/initgrcache.c b/nscd/initgrcache.c +index 2c74951f579f4afd..4764f14a45f68e0a 100644 +--- a/nscd/initgrcache.c ++++ b/nscd/initgrcache.c +@@ -159,7 +159,7 @@ addinitgroupsX (struct database_dyn *db, int fd, request_header *req, + + /* This is really only for debugging. */ + if (NSS_STATUS_TRYAGAIN > status || status > NSS_STATUS_RETURN) +- __libc_fatal ("illegal status in internal_getgrouplist"); ++ __libc_fatal ("Illegal status in internal_getgrouplist.\n"); + + any_success |= status == NSS_STATUS_SUCCESS; + +diff --git a/nss/nsswitch.c b/nss/nsswitch.c +index ee46f24424bc1ca2..3c48b4b85e881cdb 100644 +--- a/nss/nsswitch.c ++++ b/nss/nsswitch.c +@@ -235,7 +235,7 @@ __nss_next2 (service_user **ni, const char *fct_name, const char *fct2_name, + /* This is really only for debugging. */ + if (__builtin_expect (NSS_STATUS_TRYAGAIN > status + || status > NSS_STATUS_RETURN, 0)) +- __libc_fatal ("illegal status in __nss_next"); ++ __libc_fatal ("Illegal status in __nss_next.\n"); + + if (nss_next_action (*ni, status) == NSS_ACTION_RETURN) + return 1; +diff --git a/sysdeps/aarch64/dl-irel.h b/sysdeps/aarch64/dl-irel.h +index 5889ee187b7a1eaf..bef71ed0f31a6387 100644 +--- a/sysdeps/aarch64/dl-irel.h ++++ b/sysdeps/aarch64/dl-irel.h +@@ -47,7 +47,7 @@ elf_irela (const ElfW(Rela) *reloc) + *reloc_addr = value; + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif +diff --git a/sysdeps/arm/dl-irel.h b/sysdeps/arm/dl-irel.h +index a7b6456075659baf..be6eb7743eb5f08d 100644 +--- a/sysdeps/arm/dl-irel.h ++++ b/sysdeps/arm/dl-irel.h +@@ -46,7 +46,7 @@ elf_irel (const Elf32_Rel *reloc) + *reloc_addr = value; + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/generic/unwind-dw2.c b/sysdeps/generic/unwind-dw2.c +index 082609b34a3f773b..724c16a7f0bf465b 100644 +--- a/sysdeps/generic/unwind-dw2.c ++++ b/sysdeps/generic/unwind-dw2.c +@@ -843,7 +843,7 @@ execute_cfa_program (const unsigned char *insn_ptr, + struct frame_state_reg_info *old_rs = fs->regs.prev; + #ifdef _LIBC + if (old_rs == NULL) +- __libc_fatal ("invalid DWARF unwind data"); ++ __libc_fatal ("Invalid DWARF unwind data.\n"); + else + #endif + { +diff --git a/sysdeps/i386/dl-irel.h b/sysdeps/i386/dl-irel.h +index 55303180c7aca495..bcaf0668acf8e2f2 100644 +--- a/sysdeps/i386/dl-irel.h ++++ b/sysdeps/i386/dl-irel.h +@@ -45,7 +45,7 @@ elf_irel (const Elf32_Rel *reloc) + *reloc_addr = value; + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/nptl/futex-internal.h b/sysdeps/nptl/futex-internal.h +index 1a5624789d4ab117..6fd27f0df6c27b69 100644 +--- a/sysdeps/nptl/futex-internal.h ++++ b/sysdeps/nptl/futex-internal.h +@@ -197,7 +197,7 @@ futex_wake (unsigned int* futex_word, int processes_to_wake, int private); + static __always_inline __attribute__ ((__noreturn__)) void + futex_fatal_error (void) + { +- __libc_fatal ("The futex facility returned an unexpected error code."); ++ __libc_fatal ("The futex facility returned an unexpected error code.\n"); + } + + #endif /* futex-internal.h */ +diff --git a/sysdeps/powerpc/powerpc32/dl-irel.h b/sysdeps/powerpc/powerpc32/dl-irel.h +index a7368b25829618cb..61d0e4cf61ec45d3 100644 +--- a/sysdeps/powerpc/powerpc32/dl-irel.h ++++ b/sysdeps/powerpc/powerpc32/dl-irel.h +@@ -46,7 +46,7 @@ elf_irela (const Elf32_Rela *reloc) + *reloc_addr = value; + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/powerpc/powerpc64/dl-irel.h b/sysdeps/powerpc/powerpc64/dl-irel.h +index ab13c04358868270..2fd0ee8a86e85ba0 100644 +--- a/sysdeps/powerpc/powerpc64/dl-irel.h ++++ b/sysdeps/powerpc/powerpc64/dl-irel.h +@@ -57,7 +57,7 @@ elf_irela (const Elf64_Rela *reloc) + #endif + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/s390/dl-irel.h b/sysdeps/s390/dl-irel.h +index d8ba7ba42709f45c..ecb24f0a9be0daa7 100644 +--- a/sysdeps/s390/dl-irel.h ++++ b/sysdeps/s390/dl-irel.h +@@ -46,7 +46,7 @@ elf_irela (const ElfW(Rela) *reloc) + *reloc_addr = value; + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/sparc/sparc32/dl-irel.h b/sysdeps/sparc/sparc32/dl-irel.h +index ffca36864f24d1fb..cf47cda8345b1a39 100644 +--- a/sysdeps/sparc/sparc32/dl-irel.h ++++ b/sysdeps/sparc/sparc32/dl-irel.h +@@ -56,7 +56,7 @@ elf_irela (const Elf32_Rela *reloc) + else if (r_type == R_SPARC_NONE) + ; + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/sparc/sparc64/dl-irel.h b/sysdeps/sparc/sparc64/dl-irel.h +index c5cd3057aca1baf6..446fed18365cfd13 100644 +--- a/sysdeps/sparc/sparc64/dl-irel.h ++++ b/sysdeps/sparc/sparc64/dl-irel.h +@@ -59,7 +59,7 @@ elf_irela (const Elf64_Rela *reloc) + else if (r_type == R_SPARC_NONE) + ; + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ +diff --git a/sysdeps/unix/sysv/linux/netlink_assert_response.c b/sysdeps/unix/sysv/linux/netlink_assert_response.c +index f31ccb52ffa56436..6afc3a17ced18e1c 100644 +--- a/sysdeps/unix/sysv/linux/netlink_assert_response.c ++++ b/sysdeps/unix/sysv/linux/netlink_assert_response.c +@@ -72,12 +72,12 @@ __netlink_assert_response (int fd, ssize_t result) + char message[200]; + if (family < 0) + __snprintf (message, sizeof (message), +- "Unexpected error %d on netlink descriptor %d", ++ "Unexpected error %d on netlink descriptor %d.\n", + error_code, fd); + else + __snprintf (message, sizeof (message), + "Unexpected error %d on netlink descriptor %d" +- " (address family %d)", ++ " (address family %d).\n", + error_code, fd, family); + __libc_fatal (message); + } +diff --git a/sysdeps/x86_64/dl-irel.h b/sysdeps/x86_64/dl-irel.h +index 6ecc50fb42333c19..33f100d8b1781ea7 100644 +--- a/sysdeps/x86_64/dl-irel.h ++++ b/sysdeps/x86_64/dl-irel.h +@@ -45,7 +45,7 @@ elf_irela (const ElfW(Rela) *reloc) + *reloc_addr = value; + } + else +- __libc_fatal ("unexpected reloc type in static binary"); ++ __libc_fatal ("Unexpected reloc type in static binary.\n"); + } + + #endif /* dl-irel.h */ diff --git a/glibc-rh1650571.patch b/glibc-rh1650571.patch new file mode 100755 index 0000000..927e0dc --- /dev/null +++ b/glibc-rh1650571.patch @@ -0,0 +1,24 @@ +commit e4e4fde51a309801af5eed72d3494cbf4b7737aa +Author: Paul Eggert +Date: Tue Sep 18 15:02:10 2018 -0700 + + Fix tzfile low-memory assertion failure + + [BZ #21716] + * time/tzfile.c (__tzfile_read): Check for memory exhaustion + when registering time zone abbreviations. + +diff --git a/time/tzfile.c b/time/tzfile.c +index 2a385b92bcdefec0..ea6e94030392fc75 100644 +--- a/time/tzfile.c ++++ b/time/tzfile.c +@@ -410,7 +410,8 @@ __tzfile_read (const char *file, size_t extra, char **extrap) + + /* First "register" all timezone names. */ + for (i = 0; i < num_types; ++i) +- (void) __tzstring (&zone_names[types[i].idx]); ++ if (__tzstring (&zone_names[types[i].idx]) == NULL) ++ goto ret_free_transitions; + + /* Find the standard and daylight time offsets used by the rule file. + We choose the offsets in the types of each flavor that are diff --git a/glibc-rh1651274.patch b/glibc-rh1651274.patch new file mode 100755 index 0000000..d65cb0a --- /dev/null +++ b/glibc-rh1651274.patch @@ -0,0 +1,70 @@ +commit 35e3fbc4512c880fccb35b8e3abd132d4be18480 +Author: Florian Weimer +Date: Mon Nov 19 15:35:03 2018 +0100 + + support: Print timestamps in timeout handler + + This is sometimes useful to determine if a test truly got stuck, or if + it was making progress (logging information to standard output) and + was merely slow to finish. + +diff --git a/support/support_test_main.c b/support/support_test_main.c +index 23429779aca85613..fa3c2e06dee5ae0f 100644 +--- a/support/support_test_main.c ++++ b/support/support_test_main.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -86,6 +87,19 @@ static pid_t test_pid; + /* The cleanup handler passed to test_main. */ + static void (*cleanup_function) (void); + ++static void ++print_timestamp (const char *what, struct timeval tv) ++{ ++ struct tm tm; ++ if (gmtime_r (&tv.tv_sec, &tm) == NULL) ++ printf ("%s: %lld.%06d\n", ++ what, (long long int) tv.tv_sec, (int) tv.tv_usec); ++ else ++ printf ("%s: %04d-%02d-%02dT%02d:%02d:%02d.%06d\n", ++ what, 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday, ++ tm.tm_hour, tm.tm_min, tm.tm_sec, (int) tv.tv_usec); ++} ++ + /* Timeout handler. We kill the child and exit with an error. */ + static void + __attribute__ ((noreturn)) +@@ -94,6 +108,13 @@ signal_handler (int sig) + int killed; + int status; + ++ /* Do this first to avoid further interference from the ++ subprocess. */ ++ struct timeval now; ++ bool now_available = gettimeofday (&now, NULL) == 0; ++ struct stat64 st; ++ bool st_available = fstat64 (STDOUT_FILENO, &st) == 0 && st.st_mtime != 0; ++ + assert (test_pid > 1); + /* Kill the whole process group. */ + kill (-test_pid, SIGKILL); +@@ -144,6 +165,13 @@ signal_handler (int sig) + printf ("Timed out: killed the child process but it exited %d\n", + WEXITSTATUS (status)); + ++ if (now_available) ++ print_timestamp ("Termination time", now); ++ if (st_available) ++ print_timestamp ("Last write to standard output", ++ (struct timeval) { st.st_mtim.tv_sec, ++ st.st_mtim.tv_nsec / 1000 }); ++ + /* Exit with an error. */ + exit (1); + } diff --git a/glibc-rh1651283-1.patch b/glibc-rh1651283-1.patch new file mode 100755 index 0000000..cd7e903 --- /dev/null +++ b/glibc-rh1651283-1.patch @@ -0,0 +1,31 @@ +commit d6db68e66dff25d12c3bc5641b60cbd7fb6ab44f +Author: Moritz Eckert +Date: Thu Aug 16 21:08:36 2018 -0400 + + malloc: Mitigate null-byte overflow attacks + + * malloc/malloc.c (_int_free): Check for corrupt prev_size vs size. + (malloc_consolidate): Likewise. + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 13c52f376859562d..e450597e2e527fb7 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -4306,6 +4306,8 @@ _int_free (mstate av, mchunkptr p, int have_lock) + prevsize = prev_size (p); + size += prevsize; + p = chunk_at_offset(p, -((long) prevsize)); ++ if (__glibc_unlikely (chunksize(p) != prevsize)) ++ malloc_printerr ("corrupted size vs. prev_size while consolidating"); + unlink(av, p, bck, fwd); + } + +@@ -4467,6 +4469,8 @@ static void malloc_consolidate(mstate av) + prevsize = prev_size (p); + size += prevsize; + p = chunk_at_offset(p, -((long) prevsize)); ++ if (__glibc_unlikely (chunksize(p) != prevsize)) ++ malloc_printerr ("corrupted size vs. prev_size in fastbins"); + unlink(av, p, bck, fwd); + } + diff --git a/glibc-rh1651283-2.patch b/glibc-rh1651283-2.patch new file mode 100755 index 0000000..ad64396 --- /dev/null +++ b/glibc-rh1651283-2.patch @@ -0,0 +1,30 @@ +commit 30a17d8c95fbfb15c52d1115803b63aaa73a285c +Author: Pochang Chen +Date: Thu Aug 16 15:24:24 2018 -0400 + + malloc: Verify size of top chunk. + + The House of Force is a well-known technique to exploit heap + overflow. In essence, this exploit takes three steps: + 1. Overwrite the size of top chunk with very large value (e.g. -1). + 2. Request x bytes from top chunk. As the size of top chunk + is corrupted, x can be arbitrarily large and top chunk will + still be offset by x. + 3. The next allocation from top chunk will thus be controllable. + + If we verify the size of top chunk at step 2, we can stop such attack. + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index e450597e2e527fb7..d8d4581a9dcea80a 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -4084,6 +4084,9 @@ _int_malloc (mstate av, size_t bytes) + victim = av->top; + size = chunksize (victim); + ++ if (__glibc_unlikely (size > av->system_mem)) ++ malloc_printerr ("malloc(): corrupted top size"); ++ + if ((unsigned long) (size) >= (unsigned long) (nb + MINSIZE)) + { + remainder_size = size - nb; diff --git a/glibc-rh1651283-3.patch b/glibc-rh1651283-3.patch new file mode 100755 index 0000000..65a07db --- /dev/null +++ b/glibc-rh1651283-3.patch @@ -0,0 +1,122 @@ +commit b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c +Author: Istvan Kurucsai +Date: Tue Jan 16 14:54:32 2018 +0100 + + malloc: Additional checks for unsorted bin integrity I. + + On Thu, Jan 11, 2018 at 3:50 PM, Florian Weimer wrote: + > On 11/07/2017 04:27 PM, Istvan Kurucsai wrote: + >> + >> + next = chunk_at_offset (victim, size); + > + > + > For new code, we prefer declarations with initializers. + + Noted. + + >> + if (__glibc_unlikely (chunksize_nomask (victim) <= 2 * SIZE_SZ) + >> + || __glibc_unlikely (chunksize_nomask (victim) > + >> av->system_mem)) + >> + malloc_printerr("malloc(): invalid size (unsorted)"); + >> + if (__glibc_unlikely (chunksize_nomask (next) < 2 * SIZE_SZ) + >> + || __glibc_unlikely (chunksize_nomask (next) > + >> av->system_mem)) + >> + malloc_printerr("malloc(): invalid next size (unsorted)"); + >> + if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) != + >> size)) + >> + malloc_printerr("malloc(): mismatching next->prev_size + >> (unsorted)"); + > + > + > I think this check is redundant because prev_size (next) and chunksize + > (victim) are loaded from the same memory location. + + I'm fairly certain that it compares mchunk_size of victim against + mchunk_prev_size of the next chunk, i.e. the size of victim in its + header and footer. + + >> + if (__glibc_unlikely (bck->fd != victim) + >> + || __glibc_unlikely (victim->fd != unsorted_chunks (av))) + >> + malloc_printerr("malloc(): unsorted double linked list + >> corrupted"); + >> + if (__glibc_unlikely (prev_inuse(next))) + >> + malloc_printerr("malloc(): invalid next->prev_inuse + >> (unsorted)"); + > + > + > There's a missing space after malloc_printerr. + + Noted. + + > Why do you keep using chunksize_nomask? We never investigated why the + > original code uses it. It may have been an accident. + + You are right, I don't think it makes a difference in these checks. So + the size local can be reused for the checks against victim. For next, + leaving it as such avoids the masking operation. + + > Again, for non-main arenas, the checks against av->system_mem could be made + > tighter (against the heap size). Maybe you could put the condition into a + > separate inline function? + + We could also do a chunk boundary check similar to what I proposed in + the thread for the first patch in the series to be even more strict. + I'll gladly try to implement either but believe that refining these + checks would bring less benefits than in the case of the top chunk. + Intra-arena or intra-heap overlaps would still be doable here with + unsorted chunks and I don't see any way to counter that besides more + generic measures like randomizing allocations and your metadata + encoding patches. + + I've attached a revised version with the above comments incorporated + but without the refined checks. + + Thanks, + Istvan + + From a12d5d40fd7aed5fa10fc444dcb819947b72b315 Mon Sep 17 00:00:00 2001 + From: Istvan Kurucsai + Date: Tue, 16 Jan 2018 14:48:16 +0100 + Subject: [PATCH v2 1/1] malloc: Additional checks for unsorted bin integrity + I. + + Ensure the following properties of chunks encountered during binning: + - victim chunk has reasonable size + - next chunk has reasonable size + - next->prev_size == victim->size + - valid double linked list + - PREV_INUSE of next chunk is unset + + * malloc/malloc.c (_int_malloc): Additional binning code checks. + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index d8d4581a9dcea80a..dad0e73735789530 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -3724,11 +3724,22 @@ _int_malloc (mstate av, size_t bytes) + while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av)) + { + bck = victim->bk; +- if (__builtin_expect (chunksize_nomask (victim) <= 2 * SIZE_SZ, 0) +- || __builtin_expect (chunksize_nomask (victim) +- > av->system_mem, 0)) +- malloc_printerr ("malloc(): memory corruption"); + size = chunksize (victim); ++ mchunkptr next = chunk_at_offset (victim, size); ++ ++ if (__glibc_unlikely (size <= 2 * SIZE_SZ) ++ || __glibc_unlikely (size > av->system_mem)) ++ malloc_printerr ("malloc(): invalid size (unsorted)"); ++ if (__glibc_unlikely (chunksize_nomask (next) < 2 * SIZE_SZ) ++ || __glibc_unlikely (chunksize_nomask (next) > av->system_mem)) ++ malloc_printerr ("malloc(): invalid next size (unsorted)"); ++ if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) != size)) ++ malloc_printerr ("malloc(): mismatching next->prev_size (unsorted)"); ++ if (__glibc_unlikely (bck->fd != victim) ++ || __glibc_unlikely (victim->fd != unsorted_chunks (av))) ++ malloc_printerr ("malloc(): unsorted double linked list corrupted"); ++ if (__glibc_unlikely (prev_inuse(next))) ++ malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)"); + + /* + If a small request, try to use last remainder if it is the diff --git a/glibc-rh1651283-4.patch b/glibc-rh1651283-4.patch new file mode 100755 index 0000000..fcec8ee --- /dev/null +++ b/glibc-rh1651283-4.patch @@ -0,0 +1,26 @@ +The below commit contains only a whitespace change and was backported in +order to avoid future conflicts. + +commit 35cfefd96062145eeb8aee6bd72d07e0909a6b2e +Author: Florian Weimer +Date: Mon Aug 20 14:57:13 2018 +0200 + + malloc: Add ChangeLog for accidentally committed change + + Commit b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c ("malloc: Additional + checks for unsorted bin integrity I.") was committed without a + whitespace fix, so it is adjusted here as well. + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index c07463001a65af90..eb6a8ff33c0c313b 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -3745,7 +3745,7 @@ _int_malloc (mstate av, size_t bytes) + if (__glibc_unlikely (bck->fd != victim) + || __glibc_unlikely (victim->fd != unsorted_chunks (av))) + malloc_printerr ("malloc(): unsorted double linked list corrupted"); +- if (__glibc_unlikely (prev_inuse(next))) ++ if (__glibc_unlikely (prev_inuse (next))) + malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)"); + + /* diff --git a/glibc-rh1651283-5.patch b/glibc-rh1651283-5.patch new file mode 100755 index 0000000..e18b513 --- /dev/null +++ b/glibc-rh1651283-5.patch @@ -0,0 +1,38 @@ +commit ebe544bf6e8eec35e754fd49efb027c6f161b6cb +Author: Istvan Kurucsai +Date: Thu Dec 20 23:30:07 2018 -0500 + + malloc: Add more integrity checks to mremap_chunk. + + * malloc/malloc.c (mremap_chunk): Additional checks. + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index eb6a8ff33c0c313b..4df5cb4862a7b854 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -2856,16 +2856,22 @@ mremap_chunk (mchunkptr p, size_t new_size) + char *cp; + + assert (chunk_is_mmapped (p)); +- assert (((size + offset) & (GLRO (dl_pagesize) - 1)) == 0); ++ ++ uintptr_t block = (uintptr_t) p - offset; ++ uintptr_t mem = (uintptr_t) chunk2mem(p); ++ size_t total_size = offset + size; ++ if (__glibc_unlikely ((block | total_size) & (pagesize - 1)) != 0 ++ || __glibc_unlikely (!powerof2 (mem & (pagesize - 1)))) ++ malloc_printerr("mremap_chunk(): invalid pointer"); + + /* Note the extra SIZE_SZ overhead as in mmap_chunk(). */ + new_size = ALIGN_UP (new_size + offset + SIZE_SZ, pagesize); + + /* No need to remap if the number of pages does not change. */ +- if (size + offset == new_size) ++ if (total_size == new_size) + return p; + +- cp = (char *) __mremap ((char *) p - offset, size + offset, new_size, ++ cp = (char *) __mremap ((char *) block, total_size, new_size, + MREMAP_MAYMOVE); + + if (cp == MAP_FAILED) diff --git a/glibc-rh1651283-6.patch b/glibc-rh1651283-6.patch new file mode 100755 index 0000000..c578d11 --- /dev/null +++ b/glibc-rh1651283-6.patch @@ -0,0 +1,38 @@ +commit c0e82f117357a941e4d40fcc08babbd6a3c3a1b5 +Author: Istvan Kurucsai +Date: Fri Dec 21 00:13:01 2018 -0500 + + malloc: Check the alignment of mmapped chunks before unmapping. + + * malloc/malloc.c (munmap_chunk): Verify chunk alignment. + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 4df5cb4862a7b854..4412a4ffc83b013b 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -2817,6 +2817,7 @@ systrim (size_t pad, mstate av) + static void + munmap_chunk (mchunkptr p) + { ++ size_t pagesize = GLRO (dl_pagesize); + INTERNAL_SIZE_T size = chunksize (p); + + assert (chunk_is_mmapped (p)); +@@ -2826,6 +2827,7 @@ munmap_chunk (mchunkptr p) + if (DUMPED_MAIN_ARENA_CHUNK (p)) + return; + ++ uintptr_t mem = (uintptr_t) chunk2mem (p); + uintptr_t block = (uintptr_t) p - prev_size (p); + size_t total_size = prev_size (p) + size; + /* Unfortunately we have to do the compilers job by hand here. Normally +@@ -2833,7 +2835,8 @@ munmap_chunk (mchunkptr p) + page size. But gcc does not recognize the optimization possibility + (in the moment at least) so we combine the two values into one before + the bit test. */ +- if (__builtin_expect (((block | total_size) & (GLRO (dl_pagesize) - 1)) != 0, 0)) ++ if (__glibc_unlikely ((block | total_size) & (pagesize - 1)) != 0 ++ || __glibc_unlikely (!powerof2 (mem & (pagesize - 1)))) + malloc_printerr ("munmap_chunk(): invalid pointer"); + + atomic_decrement (&mp_.n_mmaps); diff --git a/glibc-rh1651283-7.patch b/glibc-rh1651283-7.patch new file mode 100755 index 0000000..af0f92b --- /dev/null +++ b/glibc-rh1651283-7.patch @@ -0,0 +1,31 @@ +commit 5b06f538c5aee0389ed034f60d90a8884d6d54de +Author: Adam Maris +Date: Thu Mar 14 16:51:16 2019 -0400 + + malloc: Check for large bin list corruption when inserting unsorted chunk + + Fixes bug 24216. This patch adds security checks for bk and bk_nextsize pointers + of chunks in large bin when inserting chunk from unsorted bin. It was possible + to write the pointer to victim (newly inserted chunk) to arbitrary memory + locations if bk or bk_nextsize pointers of the next large bin chunk + got corrupted. + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 4412a4ffc83b013b..723d393f529bdb4c 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -3876,10 +3876,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 diff --git a/glibc-rh1651742.patch b/glibc-rh1651742.patch new file mode 100755 index 0000000..1851691 --- /dev/null +++ b/glibc-rh1651742.patch @@ -0,0 +1,307 @@ +commit f0458cf4f9ff3d870c43b624e6dccaaf657d5e83 +Author: Adhemerval Zanella +Date: Mon Aug 27 09:42:50 2018 -0300 + + powerpc: Only enable TLE with PPC_FEATURE2_HTM_NOSC + + Linux from 3.9 through 4.2 does not abort HTM transaction on syscalls, + instead it suspend and resume it when leaving the kernel. The + side-effects of the syscall will always remain visible, even if the + transaction is aborted. This is an issue when transaction is used along + with futex syscall, on pthread_cond_wait for instance, where the futex + call might succeed but the transaction is rolled back leading the + pthread_cond object in an inconsistent state. + + Glibc used to prevent it by always aborting a transaction before issuing + a syscall. Linux 4.2 also decided to abort active transaction in + syscalls which makes the glibc workaround superfluous. Worse, glibc + transaction abortion leads to a performance issue on recent kernels + where the HTM state is saved/restore lazily (v4.9). By aborting a + transaction on every syscalls, regardless whether a transaction has being + initiated before, GLIBS makes the kernel always save/restore HTM state + (it can not even lazily disable it after a certain number of syscall + iterations). + + Because of this shortcoming, Transactional Lock Elision is just enabled + when it has been explicitly set (either by tunables of by a configure + switch) and if kernel aborts HTM transactions on syscalls + (PPC_FEATURE2_HTM_NOSC). It is reported that using simple benchmark [1], + the context-switch is about 5% faster by not issuing a tabort in every + syscall in newer kernels. + + Checked on powerpc64le-linux-gnu with 4.4.0 kernel (Ubuntu 16.04). + + * NEWS: Add note about new TLE support on powerpc64le. + * sysdeps/powerpc/nptl/tcb-offsets.sym (TM_CAPABLE): Remove. + * sysdeps/powerpc/nptl/tls.h (tcbhead_t): Rename tm_capable to + __ununsed1. + (TLS_INIT_TP, TLS_DEFINE_INIT_TP): Remove tm_capable setup. + (THREAD_GET_TM_CAPABLE, THREAD_SET_TM_CAPABLE): Remove macros. + * sysdeps/powerpc/powerpc32/sysdep.h, + sysdeps/powerpc/powerpc64/sysdep.h (ABORT_TRANSACTION_IMPL, + ABORT_TRANSACTION): Remove macros. + * sysdeps/powerpc/sysdep.h (ABORT_TRANSACTION): Likewise. + * sysdeps/unix/sysv/linux/powerpc/elision-conf.c (elision_init): Set + __pthread_force_elision iff PPC_FEATURE2_HTM_NOSC is set. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h, + sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h + sysdeps/unix/sysv/linux/powerpc/syscall.S (ABORT_TRANSACTION): Remove + usage. + * sysdeps/unix/sysv/linux/powerpc/not-errno.h: Remove file. + + Reported-by: Breno Leitão + +diff --git a/sysdeps/powerpc/nptl/tcb-offsets.sym b/sysdeps/powerpc/nptl/tcb-offsets.sym +index e5bb2b3..4c01615 100644 +--- a/sysdeps/powerpc/nptl/tcb-offsets.sym ++++ b/sysdeps/powerpc/nptl/tcb-offsets.sym +@@ -21,7 +21,6 @@ DSO_SLOT2 (offsetof (tcbhead_t, dso_slot2) - TLS_TCB_OFFSET - sizeof (tcbhead_ + #ifdef __powerpc64__ + TCB_AT_PLATFORM (offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t)) + #endif +-TM_CAPABLE (offsetof (tcbhead_t, tm_capable) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) + #ifndef __powerpc64__ + TCB_AT_PLATFORM (offsetof (tcbhead_t, at_platform) - TLS_TCB_OFFSET - sizeof(tcbhead_t)) + PADDING (offsetof (tcbhead_t, padding) - TLS_TCB_OFFSET - sizeof(tcbhead_t)) +diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h +index f88fed5..8317ca7 100644 +--- a/sysdeps/powerpc/nptl/tls.h ++++ b/sysdeps/powerpc/nptl/tls.h +@@ -67,8 +67,7 @@ typedef struct + uint32_t padding; + uint32_t at_platform; + #endif +- /* Indicate if HTM capable (ISA 2.07). */ +- uint32_t tm_capable; ++ uint32_t __unused; + /* Reservation for AT_PLATFORM data - powerpc64. */ + #ifdef __powerpc64__ + uint32_t at_platform; +@@ -142,7 +141,6 @@ register void *__thread_register __asm__ ("r13"); + # define TLS_INIT_TP(tcbp) \ + ({ \ + __thread_register = (void *) (tcbp) + TLS_TCB_OFFSET; \ +- THREAD_SET_TM_CAPABLE (__tcb_hwcap & PPC_FEATURE2_HAS_HTM ? 1 : 0); \ + THREAD_SET_HWCAP (__tcb_hwcap); \ + THREAD_SET_AT_PLATFORM (__tcb_platform); \ + NULL; \ +@@ -151,8 +149,6 @@ register void *__thread_register __asm__ ("r13"); + /* Value passed to 'clone' for initialization of the thread register. */ + # define TLS_DEFINE_INIT_TP(tp, pd) \ + void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE; \ +- (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].tm_capable) = \ +- THREAD_GET_TM_CAPABLE (); \ + (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].hwcap) = \ + THREAD_GET_HWCAP (); \ + (((tcbhead_t *) ((char *) tp - TLS_TCB_OFFSET))[-1].at_platform) = \ +@@ -210,13 +206,6 @@ register void *__thread_register __asm__ ("r13"); + + TLS_PRE_TCB_SIZE))[-1].pointer_guard \ + = THREAD_GET_POINTER_GUARD()) + +-/* tm_capable field in TCB head. */ +-# define THREAD_GET_TM_CAPABLE() \ +- (((tcbhead_t *) ((char *) __thread_register \ +- - TLS_TCB_OFFSET))[-1].tm_capable) +-# define THREAD_SET_TM_CAPABLE(value) \ +- (THREAD_GET_TM_CAPABLE () = (value)) +- + /* hwcap field in TCB head. */ + # define THREAD_GET_HWCAP() \ + (((tcbhead_t *) ((char *) __thread_register \ +diff --git a/sysdeps/powerpc/powerpc32/sysdep.h b/sysdeps/powerpc/powerpc32/sysdep.h +index 5f1294e..93097c5 100644 +--- a/sysdeps/powerpc/powerpc32/sysdep.h ++++ b/sysdeps/powerpc/powerpc32/sysdep.h +@@ -90,24 +90,7 @@ GOT_LABEL: ; \ + cfi_endproc; \ + ASM_SIZE_DIRECTIVE(name) + +-#if !IS_IN(rtld) && !defined(__SPE__) +-# define ABORT_TRANSACTION_IMPL \ +- cmpwi 2,0; \ +- beq 1f; \ +- lwz 0,TM_CAPABLE(2); \ +- cmpwi 0,0; \ +- beq 1f; \ +- li 11,_ABORT_SYSCALL; \ +- tabort. 11; \ +- .align 4; \ +-1: +-#else +-# define ABORT_TRANSACTION_IMPL +-#endif +-#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL +- + #define DO_CALL(syscall) \ +- ABORT_TRANSACTION \ + li 0,syscall; \ + sc + +diff --git a/sysdeps/powerpc/powerpc64/sysdep.h b/sysdeps/powerpc/powerpc64/sysdep.h +index 2df1d9b..50e64f9 100644 +--- a/sysdeps/powerpc/powerpc64/sysdep.h ++++ b/sysdeps/powerpc/powerpc64/sysdep.h +@@ -263,24 +263,7 @@ LT_LABELSUFFIX(name,_name_end): ; \ + TRACEBACK_MASK(name,mask); \ + END_2(name) + +-#if !IS_IN(rtld) +-# define ABORT_TRANSACTION_IMPL \ +- cmpdi 13,0; \ +- beq 1f; \ +- lwz 0,TM_CAPABLE(13); \ +- cmpwi 0,0; \ +- beq 1f; \ +- li 11,_ABORT_SYSCALL; \ +- tabort. 11; \ +- .p2align 4; \ +-1: +-#else +-# define ABORT_TRANSACTION_IMPL +-#endif +-#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL +- + #define DO_CALL(syscall) \ +- ABORT_TRANSACTION \ + li 0,syscall; \ + sc + +diff --git a/sysdeps/powerpc/sysdep.h b/sysdeps/powerpc/sysdep.h +index 8a6d236..c8bf25e 100644 +--- a/sysdeps/powerpc/sysdep.h ++++ b/sysdeps/powerpc/sysdep.h +@@ -21,8 +21,6 @@ + */ + #define _SYSDEPS_SYSDEP_H 1 + #include +-#include +-#include + + #define PPC_FEATURE_970 (PPC_FEATURE_POWER4 + PPC_FEATURE_HAS_ALTIVEC) + +@@ -166,22 +164,4 @@ + #define ALIGNARG(log2) log2 + #define ASM_SIZE_DIRECTIVE(name) .size name,.-name + +-#else +- +-/* Linux kernel powerpc documentation [1] states issuing a syscall inside a +- transaction is not recommended and may lead to undefined behavior. It +- also states syscalls do not abort transactions. To avoid such traps, +- we abort transaction just before syscalls. +- +- [1] Documentation/powerpc/transactional_memory.txt [Syscalls] */ +-#if !IS_IN(rtld) && !defined(__SPE__) +-# define ABORT_TRANSACTION \ +- ({ \ +- if (THREAD_GET_TM_CAPABLE ()) \ +- __libc_tabort (_ABORT_SYSCALL); \ +- }) +-#else +-# define ABORT_TRANSACTION +-#endif +- + #endif /* __ASSEMBLER__ */ +diff --git a/sysdeps/unix/sysv/linux/powerpc/elision-conf.c b/sysdeps/unix/sysv/linux/powerpc/elision-conf.c +index 906882a..fc82bd1 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/elision-conf.c ++++ b/sysdeps/unix/sysv/linux/powerpc/elision-conf.c +@@ -127,6 +127,26 @@ elision_init (int argc __attribute__ ((unused)), + TUNABLE_CALLBACK (set_elision_skip_trylock_internal_abort)); + #endif + ++ /* Linux from 3.9 through 4.2 do not abort HTM transaction on syscalls, ++ instead it suspends the transaction and resumes it when returning to ++ usercode. The side-effects of the syscall will always remain visible, ++ even if the transaction is aborted. This is an issue when a transaction ++ is used along with futex syscall, on pthread_cond_wait for instance, ++ where futex might succeed but the transaction is rolled back leading ++ the condition variable object in an inconsistent state. ++ ++ Glibc used to prevent it by always aborting a transaction before issuing ++ a syscall. Linux 4.2 also decided to abort active transaction in ++ syscalls which makes the glibc workaround superflours. Worse, glibc ++ transaction abortions leads to a performance issues on recent kernels. ++ ++ So Lock Elision is just enabled when it has been explict set (either ++ by tunables of by a configure switch) and if kernel aborts HTM ++ transactions on syscalls (PPC_FEATURE2_HTM_NOSC) */ ++ ++ __pthread_force_elision = (__pthread_force_elision ++ && GLRO (dl_hwcap2) & PPC_FEATURE2_HTM_NOSC); ++ + if (!__pthread_force_elision) + __elision_aconf.try_tbegin = 0; /* Disable elision on rwlocks. */ + } +diff --git a/sysdeps/unix/sysv/linux/powerpc/not-errno.h b/sysdeps/unix/sysv/linux/powerpc/not-errno.h +deleted file mode 100644 +index 27da21b..0000000 +--- a/sysdeps/unix/sysv/linux/powerpc/not-errno.h ++++ /dev/null +@@ -1,30 +0,0 @@ +-/* Syscall wrapper that do not set errno. Linux powerpc version. +- Copyright (C) 2018 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 +- . */ +- +-/* __access_noerrno is used during process initialization in elf/dl-tunables.c +- before the TCB is initialized, prohibiting the usage of +- ABORT_TRANSACTION. */ +-#undef ABORT_TRANSACTION +-#define ABORT_TRANSACTION +- +-#include "sysdeps/unix/sysv/linux/not-errno.h" +- +-/* Recover ABORT_TRANSACTION's previous value, in order to not affect +- other syscalls. */ +-#undef ABORT_TRANSACTION +-#define ABORT_TRANSACTION ABORT_TRANSACTION_IMPL +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h +index f7277d5..ec5c525 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h +@@ -109,7 +109,6 @@ + register long int r11 __asm__ ("r11"); \ + register long int r12 __asm__ ("r12"); \ + LOADARGS_##nr(name, args); \ +- ABORT_TRANSACTION; \ + __asm__ __volatile__ \ + ("sc \n\t" \ + "mfcr %0" \ +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h +index 0956cf0..1f17f7b 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h +@@ -131,7 +131,6 @@ + register long int r7 __asm__ ("r7"); \ + register long int r8 __asm__ ("r8"); \ + LOADARGS_##nr (name, ##args); \ +- ABORT_TRANSACTION; \ + __asm__ __volatile__ \ + ("sc\n\t" \ + "mfcr %0\n\t" \ +diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S +index 2da9172..bbab613 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/syscall.S ++++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S +@@ -18,7 +18,6 @@ + #include + + ENTRY (syscall) +- ABORT_TRANSACTION + mr r0,r3 + mr r3,r4 + mr r4,r5 diff --git a/glibc-rh1654010-1.patch b/glibc-rh1654010-1.patch new file mode 100755 index 0000000..b32ce03 --- /dev/null +++ b/glibc-rh1654010-1.patch @@ -0,0 +1,35 @@ +commit d527c860f5a3f0ed687bd03f0cb464612dc23408 +Author: Florian Weimer +Date: Tue Nov 27 16:12:43 2018 +0100 + + CVE-2018-19591: if_nametoindex: Fix descriptor for overlong name [BZ #23927] + +diff --git a/sysdeps/unix/sysv/linux/if_index.c b/sysdeps/unix/sysv/linux/if_index.c +index e3d08982d9931108..782fc5e1750e9ead 100644 +--- a/sysdeps/unix/sysv/linux/if_index.c ++++ b/sysdeps/unix/sysv/linux/if_index.c +@@ -38,11 +38,6 @@ __if_nametoindex (const char *ifname) + return 0; + #else + struct ifreq ifr; +- int fd = __opensock (); +- +- if (fd < 0) +- return 0; +- + if (strlen (ifname) >= IFNAMSIZ) + { + __set_errno (ENODEV); +@@ -50,6 +45,12 @@ __if_nametoindex (const char *ifname) + } + + strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); ++ ++ int fd = __opensock (); ++ ++ if (fd < 0) ++ return 0; ++ + if (__ioctl (fd, SIOCGIFINDEX, &ifr) < 0) + { + int saved_errno = errno; diff --git a/glibc-rh1654010-2.patch b/glibc-rh1654010-2.patch new file mode 100755 index 0000000..5e8faa2 --- /dev/null +++ b/glibc-rh1654010-2.patch @@ -0,0 +1,142 @@ +commit c74a91deaa5de416237c02bbb3e41bda76ca4c7b +Author: Florian Weimer +Date: Tue Nov 27 21:35:56 2018 +0100 + + support: Implement support_quote_string + + Reviewed-by: Jonathan Nieder + +diff --git a/support/Makefile b/support/Makefile +index 2b663fbbfa334ea2..a2536980d1d5a89b 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -58,6 +58,7 @@ libsupport-routines = \ + support_openpty \ + support_paths \ + support_quote_blob \ ++ support_quote_string \ + support_record_failure \ + support_run_diff \ + support_shared_allocate \ +@@ -196,6 +197,7 @@ tests = \ + tst-support_capture_subprocess \ + tst-support_format_dns_packet \ + tst-support_quote_blob \ ++ tst-support_quote_string \ + tst-support_record_failure \ + tst-test_compare \ + tst-test_compare_blob \ +diff --git a/support/support.h b/support/support.h +index 9418cd11ef6e684d..835e7173eb566355 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -69,6 +69,11 @@ void support_write_file_string (const char *path, const char *contents); + the result). */ + char *support_quote_blob (const void *blob, size_t length); + ++/* Quote the contents of the at STR, in such a way that the result ++ string can be included in a C literal (in single/double quotes, ++ without putting the quotes into the result). */ ++char *support_quote_string (const char *str); ++ + /* Returns non-zero if the file descriptor is a regular file on a file + system which supports holes (that is, seeking and writing does not + allocate storage for the range of zeros). FD must refer to a +diff --git a/support/support_quote_string.c b/support/support_quote_string.c +new file mode 100644 +index 0000000000000000..d324371b133a4d66 +--- /dev/null ++++ b/support/support_quote_string.c +@@ -0,0 +1,26 @@ ++/* Quote a string so that it can be used in C literals. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++ ++char * ++support_quote_string (const char *str) ++{ ++ return support_quote_blob (str, strlen (str)); ++} +diff --git a/support/tst-support_quote_string.c b/support/tst-support_quote_string.c +new file mode 100644 +index 0000000000000000..3c004759b76e21d7 +--- /dev/null ++++ b/support/tst-support_quote_string.c +@@ -0,0 +1,60 @@ ++/* Test the support_quote_string function. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ char *p = support_quote_string (""); ++ TEST_COMPARE (strlen (p), 0); ++ free (p); ++ p = support_quote_string ("X"); ++ TEST_COMPARE (strlen (p), 1); ++ TEST_COMPARE (p[0], 'X'); ++ free (p); ++ ++ /* Check escaping of backslash-escaped characters, and lack of ++ escaping for other shell meta-characters. */ ++ p = support_quote_string ("$()*?`@[]{}~\'\"X"); ++ TEST_COMPARE (strcmp (p, "$()*?`@[]{}~\\'\\\"X"), 0); ++ free (p); ++ ++ /* Check lack of escaping for letters and digits. */ ++#define LETTERS_AND_DIGTS \ ++ "abcdefghijklmnopqrstuvwxyz" \ ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ ++ "0123456789" ++ p = support_quote_string (LETTERS_AND_DIGTS "@"); ++ TEST_COMPARE (strcmp (p, LETTERS_AND_DIGTS "@"), 0); ++ free (p); ++ ++ /* Check escaping of control characters and other non-printable ++ characters. */ ++ p = support_quote_string ("\r\n\t\a\b\f\v\1\177\200\377@"); ++ TEST_COMPARE (strcmp (p, "\\r\\n\\t\\a\\b\\f\\v\\001" ++ "\\177\\200\\377@"), 0); ++ free (p); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1654010-3.patch b/glibc-rh1654010-3.patch new file mode 100755 index 0000000..d28ea27 --- /dev/null +++ b/glibc-rh1654010-3.patch @@ -0,0 +1,26 @@ +commit 47d8d9a2172f827a8dde7695f415aa6f78a82d0e +Author: Florian Weimer +Date: Wed Nov 28 07:00:48 2018 +0100 + + support_quote_string: Do not use str parameter name + + This avoids a build failure if this identifier is used as a macro + in a test. + +diff --git a/support/support.h b/support/support.h +index 835e7173eb566355..c3ad76901e352ee7 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -69,10 +69,10 @@ void support_write_file_string (const char *path, const char *contents); + the result). */ + char *support_quote_blob (const void *blob, size_t length); + +-/* Quote the contents of the at STR, in such a way that the result ++/* Quote the contents of the string, in such a way that the result + string can be included in a C literal (in single/double quotes, + without putting the quotes into the result). */ +-char *support_quote_string (const char *str); ++char *support_quote_string (const char *); + + /* Returns non-zero if the file descriptor is a regular file on a file + system which supports holes (that is, seeking and writing does not diff --git a/glibc-rh1654010-4.patch b/glibc-rh1654010-4.patch new file mode 100755 index 0000000..709bb84 --- /dev/null +++ b/glibc-rh1654010-4.patch @@ -0,0 +1,32 @@ +commit 02cd5c1a8d033d7f91fea12a66bb44d1bbf85f76 +Author: Florian Weimer +Date: Sat Dec 1 21:43:36 2018 +0100 + + support: Close original descriptors in support_capture_subprocess + +diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c +index 6d2029e13bd6ae73..93f6ea310290000a 100644 +--- a/support/support_capture_subprocess.c ++++ b/support/support_capture_subprocess.c +@@ -59,8 +59,12 @@ support_capture_subprocess (void (*callback) (void *), void *closure) + + 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); +@@ -72,6 +76,8 @@ support_capture_subprocess (void (*callback) (void *), void *closure) + 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); + } diff --git a/glibc-rh1654010-5.patch b/glibc-rh1654010-5.patch new file mode 100755 index 0000000..9dbfb9d --- /dev/null +++ b/glibc-rh1654010-5.patch @@ -0,0 +1,594 @@ +commit f255336a9301619519045548acb2e1027065a837 +Author: Florian Weimer +Date: Thu Dec 6 15:39:42 2018 +0100 + + support: Implement to track file descriptors + +diff --git a/support/Makefile b/support/Makefile +index a2536980d1d5a89b..93a514301654132e 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -46,6 +46,7 @@ libsupport-routines = \ + support_chroot \ + support_copy_file_range \ + support_descriptor_supports_holes \ ++ support_descriptors \ + support_enter_mount_namespace \ + support_enter_network_namespace \ + support_format_address_family \ +@@ -195,6 +196,7 @@ tests = \ + tst-support-namespace \ + tst-support_blob_repeat \ + tst-support_capture_subprocess \ ++ tst-support_descriptors \ + tst-support_format_dns_packet \ + tst-support_quote_blob \ + tst-support_quote_string \ +diff --git a/support/check.h b/support/check.h +index e6765289f2492501..7ea9a86a9c7ed055 100644 +--- a/support/check.h ++++ b/support/check.h +@@ -183,6 +183,10 @@ int support_report_failure (int status) + /* Internal function used to test the failure recording framework. */ + void support_record_failure_reset (void); + ++/* Returns true or false depending on whether there have been test ++ failures or not. */ ++int support_record_failure_is_failed (void); ++ + __END_DECLS + + #endif /* SUPPORT_CHECK_H */ +diff --git a/support/descriptors.h b/support/descriptors.h +new file mode 100644 +index 0000000000000000..8ec4cbbdfb8f1770 +--- /dev/null ++++ b/support/descriptors.h +@@ -0,0 +1,47 @@ ++/* Monitoring file descriptor usage. ++ Copyright (C) 2018 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 ++ . */ ++ ++#ifndef SUPPORT_DESCRIPTORS_H ++#define SUPPORT_DESCRIPTORS_H ++ ++#include ++ ++/* Opaque pointer, for capturing file descriptor lists. */ ++struct support_descriptors; ++ ++/* Record the currently open file descriptors and store them in the ++ returned list. Terminate the process if the listing operation ++ fails. */ ++struct support_descriptors *support_descriptors_list (void); ++ ++/* Deallocate the list of descriptors. */ ++void support_descriptors_free (struct support_descriptors *); ++ ++/* Write the list of descriptors to STREAM, adding PREFIX to each ++ line. */ ++void support_descriptors_dump (struct support_descriptors *, ++ const char *prefix, FILE *stream); ++ ++/* Check for file descriptor leaks and other file descriptor changes: ++ Compare the current list of descriptors with the passed list. ++ Record a test failure if there are additional open descriptors, ++ descriptors have been closed, or if a change in file descriptor can ++ be detected. */ ++void support_descriptors_check (struct support_descriptors *); ++ ++#endif /* SUPPORT_DESCRIPTORS_H */ +diff --git a/support/support_descriptors.c b/support/support_descriptors.c +new file mode 100644 +index 0000000000000000..d66cf550800201c5 +--- /dev/null ++++ b/support/support_descriptors.c +@@ -0,0 +1,274 @@ ++/* Monitoring file descriptor usage. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct procfs_descriptor ++{ ++ int fd; ++ char *link_target; ++ dev_t dev; ++ ino64_t ino; ++}; ++ ++/* Used with qsort. */ ++static int ++descriptor_compare (const void *l, const void *r) ++{ ++ const struct procfs_descriptor *left = l; ++ const struct procfs_descriptor *right = r; ++ /* Cannot overflow due to limited file descriptor range. */ ++ return left->fd - right->fd; ++} ++ ++#define DYNARRAY_STRUCT descriptor_list ++#define DYNARRAY_ELEMENT struct procfs_descriptor ++#define DYNARRAY_PREFIX descriptor_list_ ++#define DYNARRAY_ELEMENT_FREE(e) free ((e)->link_target) ++#define DYNARRAY_INITIAL_SIZE 0 ++#include ++ ++struct support_descriptors ++{ ++ struct descriptor_list list; ++}; ++ ++struct support_descriptors * ++support_descriptors_list (void) ++{ ++ struct support_descriptors *result = xmalloc (sizeof (*result)); ++ descriptor_list_init (&result->list); ++ ++ DIR *fds = opendir ("/proc/self/fd"); ++ if (fds == NULL) ++ FAIL_EXIT1 ("opendir (\"/proc/self/fd\"): %m"); ++ ++ while (true) ++ { ++ errno = 0; ++ struct dirent64 *e = readdir64 (fds); ++ if (e == NULL) ++ { ++ if (errno != 0) ++ FAIL_EXIT1 ("readdir: %m"); ++ break; ++ } ++ ++ if (e->d_name[0] == '.') ++ continue; ++ ++ char *endptr; ++ long int fd = strtol (e->d_name, &endptr, 10); ++ if (*endptr != '\0' || fd < 0 || fd > INT_MAX) ++ FAIL_EXIT1 ("readdir: invalid file descriptor name: /proc/self/fd/%s", ++ e->d_name); ++ ++ /* Skip the descriptor which is used to enumerate the ++ descriptors. */ ++ if (fd == dirfd (fds)) ++ continue; ++ ++ char *target; ++ { ++ char *path = xasprintf ("/proc/self/fd/%ld", fd); ++ target = xreadlink (path); ++ free (path); ++ } ++ struct stat64 st; ++ if (fstat64 (fd, &st) != 0) ++ FAIL_EXIT1 ("readdir: fstat64 (%ld) failed: %m", fd); ++ ++ struct procfs_descriptor *item = descriptor_list_emplace (&result->list); ++ if (item == NULL) ++ FAIL_EXIT1 ("descriptor_list_emplace: %m"); ++ item->fd = fd; ++ item->link_target = target; ++ item->dev = st.st_dev; ++ item->ino = st.st_ino; ++ } ++ ++ closedir (fds); ++ ++ /* Perform a merge join between descrs and current. This assumes ++ that the arrays are sorted by file descriptor. */ ++ ++ qsort (descriptor_list_begin (&result->list), ++ descriptor_list_size (&result->list), ++ sizeof (struct procfs_descriptor), descriptor_compare); ++ ++ return result; ++} ++ ++void ++support_descriptors_free (struct support_descriptors *descrs) ++{ ++ descriptor_list_free (&descrs->list); ++ free (descrs); ++} ++ ++void ++support_descriptors_dump (struct support_descriptors *descrs, ++ const char *prefix, FILE *fp) ++{ ++ struct procfs_descriptor *end = descriptor_list_end (&descrs->list); ++ for (struct procfs_descriptor *d = descriptor_list_begin (&descrs->list); ++ d != end; ++d) ++ { ++ char *quoted = support_quote_string (d->link_target); ++ fprintf (fp, "%s%d: target=\"%s\" major=%lld minor=%lld ino=%lld\n", ++ prefix, d->fd, quoted, ++ (long long int) major (d->dev), ++ (long long int) minor (d->dev), ++ (long long int) d->ino); ++ free (quoted); ++ } ++} ++ ++static void ++dump_mismatch (bool *first, ++ struct support_descriptors *descrs, ++ struct support_descriptors *current) ++{ ++ if (*first) ++ *first = false; ++ else ++ return; ++ ++ puts ("error: Differences found in descriptor set"); ++ puts ("Reference descriptor set:"); ++ support_descriptors_dump (descrs, " ", stdout); ++ puts ("Current descriptor set:"); ++ support_descriptors_dump (current, " ", stdout); ++ puts ("Differences:"); ++} ++ ++static void ++report_closed_descriptor (bool *first, ++ struct support_descriptors *descrs, ++ struct support_descriptors *current, ++ struct procfs_descriptor *left) ++{ ++ support_record_failure (); ++ dump_mismatch (first, descrs, current); ++ printf ("error: descriptor %d was closed\n", left->fd); ++} ++ ++static void ++report_opened_descriptor (bool *first, ++ struct support_descriptors *descrs, ++ struct support_descriptors *current, ++ struct procfs_descriptor *right) ++{ ++ support_record_failure (); ++ dump_mismatch (first, descrs, current); ++ char *quoted = support_quote_string (right->link_target); ++ printf ("error: descriptor %d was opened (\"%s\")\n", right->fd, quoted); ++ free (quoted); ++} ++ ++void ++support_descriptors_check (struct support_descriptors *descrs) ++{ ++ struct support_descriptors *current = support_descriptors_list (); ++ ++ /* Perform a merge join between descrs and current. This assumes ++ that the arrays are sorted by file descriptor. */ ++ ++ struct procfs_descriptor *left = descriptor_list_begin (&descrs->list); ++ struct procfs_descriptor *left_end = descriptor_list_end (&descrs->list); ++ struct procfs_descriptor *right = descriptor_list_begin (¤t->list); ++ struct procfs_descriptor *right_end = descriptor_list_end (¤t->list); ++ ++ bool first = true; ++ while (left != left_end && right != right_end) ++ { ++ if (left->fd == right->fd) ++ { ++ if (strcmp (left->link_target, right->link_target) != 0) ++ { ++ support_record_failure (); ++ char *left_quoted = support_quote_string (left->link_target); ++ char *right_quoted = support_quote_string (right->link_target); ++ dump_mismatch (&first, descrs, current); ++ printf ("error: descriptor %d changed from \"%s\" to \"%s\"\n", ++ left->fd, left_quoted, right_quoted); ++ free (left_quoted); ++ free (right_quoted); ++ } ++ if (left->dev != right->dev) ++ { ++ support_record_failure (); ++ dump_mismatch (&first, descrs, current); ++ printf ("error: descriptor %d changed device" ++ " from %lld:%lld to %lld:%lld\n", ++ left->fd, ++ (long long int) major (left->dev), ++ (long long int) minor (left->dev), ++ (long long int) major (right->dev), ++ (long long int) minor (right->dev)); ++ } ++ if (left->ino != right->ino) ++ { ++ support_record_failure (); ++ dump_mismatch (&first, descrs, current); ++ printf ("error: descriptor %d changed ino from %lld to %lld\n", ++ left->fd, ++ (long long int) left->ino, (long long int) right->ino); ++ } ++ ++left; ++ ++right; ++ } ++ else if (left->fd < right->fd) ++ { ++ /* Gap on the right. */ ++ report_closed_descriptor (&first, descrs, current, left); ++ ++left; ++ } ++ else ++ { ++ /* Gap on the left. */ ++ TEST_VERIFY_EXIT (left->fd > right->fd); ++ report_opened_descriptor (&first, descrs, current, right); ++ ++right; ++ } ++ } ++ ++ while (left != left_end) ++ { ++ /* Closed descriptors (more descriptors on the left). */ ++ report_closed_descriptor (&first, descrs, current, left); ++ ++left; ++ } ++ ++ while (right != right_end) ++ { ++ /* Opened descriptors (more descriptors on the right). */ ++ report_opened_descriptor (&first, descrs, current, right); ++ ++right; ++ } ++ ++ support_descriptors_free (current); ++} +diff --git a/support/support_record_failure.c b/support/support_record_failure.c +index 356798f55608ca71..17ab1d80ef2bbdea 100644 +--- a/support/support_record_failure.c ++++ b/support/support_record_failure.c +@@ -104,3 +104,11 @@ support_record_failure_reset (void) + __atomic_store_n (&state->failed, 0, __ATOMIC_RELAXED); + __atomic_add_fetch (&state->counter, 0, __ATOMIC_RELAXED); + } ++ ++int ++support_record_failure_is_failed (void) ++{ ++ /* Relaxed MO is sufficient because we need (blocking) external ++ synchronization for reliable test error reporting anyway. */ ++ return __atomic_load_n (&state->failed, __ATOMIC_RELAXED); ++} +diff --git a/support/tst-support_descriptors.c b/support/tst-support_descriptors.c +new file mode 100644 +index 0000000000000000..5e9e824bc3820499 +--- /dev/null ++++ b/support/tst-support_descriptors.c +@@ -0,0 +1,198 @@ ++/* Tests for monitoring file descriptor usage. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* This is the next free descriptor that the subprocess will pick. */ ++static int free_descriptor; ++ ++static void ++subprocess_no_change (void *closure) ++{ ++ struct support_descriptors *descrs = support_descriptors_list (); ++ int fd = xopen ("/dev/null", O_WRONLY, 0); ++ TEST_COMPARE (fd, free_descriptor); ++ xclose (fd); ++ support_descriptors_free (descrs); ++} ++ ++static void ++subprocess_closed_descriptor (void *closure) ++{ ++ int fd = xopen ("/dev/null", O_WRONLY, 0); ++ TEST_COMPARE (fd, free_descriptor); ++ struct support_descriptors *descrs = support_descriptors_list (); ++ xclose (fd); ++ support_descriptors_check (descrs); /* Will report failure. */ ++ puts ("EOT"); ++ support_descriptors_free (descrs); ++} ++ ++static void ++subprocess_opened_descriptor (void *closure) ++{ ++ struct support_descriptors *descrs = support_descriptors_list (); ++ int fd = xopen ("/dev/null", O_WRONLY, 0); ++ TEST_COMPARE (fd, free_descriptor); ++ support_descriptors_check (descrs); /* Will report failure. */ ++ puts ("EOT"); ++ support_descriptors_free (descrs); ++} ++ ++static void ++subprocess_changed_descriptor (void *closure) ++{ ++ int fd = xopen ("/dev/null", O_WRONLY, 0); ++ TEST_COMPARE (fd, free_descriptor); ++ struct support_descriptors *descrs = support_descriptors_list (); ++ xclose (fd); ++ TEST_COMPARE (xopen ("/dev", O_DIRECTORY | O_RDONLY, 0), fd); ++ support_descriptors_check (descrs); /* Will report failure. */ ++ puts ("EOT"); ++ support_descriptors_free (descrs); ++} ++ ++static void ++report_subprocess_output (const char *name, ++ struct support_capture_subprocess *proc) ++{ ++ printf ("info: BEGIN %s output\n" ++ "%s" ++ "info: END %s output\n", ++ name, proc->out.buffer, name); ++} ++ ++/* Use an explicit flag to preserve failure status across ++ support_record_failure_reset calls. */ ++static bool good = true; ++ ++static void ++test_run (void) ++{ ++ struct support_capture_subprocess proc = support_capture_subprocess ++ (&subprocess_no_change, NULL); ++ support_capture_subprocess_check (&proc, "subprocess_no_change", ++ 0, sc_allow_none); ++ support_capture_subprocess_free (&proc); ++ ++ char *expected = xasprintf ("\nDifferences:\n" ++ "error: descriptor %d was closed\n" ++ "EOT\n", ++ free_descriptor); ++ good = good && !support_record_failure_is_failed (); ++ proc = support_capture_subprocess (&subprocess_closed_descriptor, NULL); ++ good = good && support_record_failure_is_failed (); ++ support_record_failure_reset (); /* Discard the reported error. */ ++ report_subprocess_output ("subprocess_closed_descriptor", &proc); ++ TEST_VERIFY (strstr (proc.out.buffer, expected) != NULL); ++ support_capture_subprocess_check (&proc, "subprocess_closed_descriptor", ++ 0, sc_allow_stdout); ++ support_capture_subprocess_free (&proc); ++ free (expected); ++ ++ expected = xasprintf ("\nDifferences:\n" ++ "error: descriptor %d was opened (\"/dev/null\")\n" ++ "EOT\n", ++ free_descriptor); ++ good = good && !support_record_failure_is_failed (); ++ proc = support_capture_subprocess (&subprocess_opened_descriptor, NULL); ++ good = good && support_record_failure_is_failed (); ++ support_record_failure_reset (); /* Discard the reported error. */ ++ report_subprocess_output ("subprocess_opened_descriptor", &proc); ++ TEST_VERIFY (strstr (proc.out.buffer, expected) != NULL); ++ support_capture_subprocess_check (&proc, "subprocess_opened_descriptor", ++ 0, sc_allow_stdout); ++ support_capture_subprocess_free (&proc); ++ free (expected); ++ ++ expected = xasprintf ("\nDifferences:\n" ++ "error: descriptor %d changed from \"/dev/null\"" ++ " to \"/dev\"\n" ++ "error: descriptor %d changed ino ", ++ free_descriptor, free_descriptor); ++ good = good && !support_record_failure_is_failed (); ++ proc = support_capture_subprocess (&subprocess_changed_descriptor, NULL); ++ good = good && support_record_failure_is_failed (); ++ support_record_failure_reset (); /* Discard the reported error. */ ++ report_subprocess_output ("subprocess_changed_descriptor", &proc); ++ TEST_VERIFY (strstr (proc.out.buffer, expected) != NULL); ++ support_capture_subprocess_check (&proc, "subprocess_changed_descriptor", ++ 0, sc_allow_stdout); ++ support_capture_subprocess_free (&proc); ++ free (expected); ++} ++ ++static int ++do_test (void) ++{ ++ puts ("info: initial descriptor set"); ++ { ++ struct support_descriptors *descrs = support_descriptors_list (); ++ support_descriptors_dump (descrs, "info: ", stdout); ++ support_descriptors_free (descrs); ++ } ++ ++ free_descriptor = xopen ("/dev/null", O_WRONLY, 0); ++ puts ("info: descriptor set with additional free descriptor"); ++ { ++ struct support_descriptors *descrs = support_descriptors_list (); ++ support_descriptors_dump (descrs, "info: ", stdout); ++ support_descriptors_free (descrs); ++ } ++ TEST_VERIFY (free_descriptor >= 3); ++ xclose (free_descriptor); ++ ++ /* Initial test run without a sentinel descriptor. The presence of ++ such a descriptor exercises different conditions in the list ++ comparison in support_descriptors_check. */ ++ test_run (); ++ ++ /* Allocate a sentinel descriptor at the end of the descriptor list, ++ after free_descriptor. */ ++ int sentinel_fd; ++ { ++ int fd = xopen ("/dev/full", O_WRONLY, 0); ++ TEST_COMPARE (fd, free_descriptor); ++ sentinel_fd = dup (fd); ++ TEST_VERIFY_EXIT (sentinel_fd > fd); ++ xclose (fd); ++ } ++ puts ("info: descriptor set with sentinel descriptor"); ++ { ++ struct support_descriptors *descrs = support_descriptors_list (); ++ support_descriptors_dump (descrs, "info: ", stdout); ++ support_descriptors_free (descrs); ++ } ++ ++ /* Second test run with sentinel descriptor. */ ++ test_run (); ++ ++ xclose (sentinel_fd); ++ ++ return !good; ++} ++ ++#include diff --git a/glibc-rh1654010-6.patch b/glibc-rh1654010-6.patch new file mode 100755 index 0000000..bf6a137 --- /dev/null +++ b/glibc-rh1654010-6.patch @@ -0,0 +1,86 @@ +commit 899478c2bfa00c5df8d8bedb52effbb065700278 +Author: Florian Weimer +Date: Thu Dec 6 15:39:50 2018 +0100 + + inet/tst-if_index-long: New test case for CVE-2018-19591 [BZ #23927] + +diff --git a/inet/Makefile b/inet/Makefile +index 09f5ba78fc5f3120..7782913b4c06f057 100644 +--- a/inet/Makefile ++++ b/inet/Makefile +@@ -52,7 +52,7 @@ aux := check_pf check_native ifreq + tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \ + tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \ + tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-checks-posix \ +- tst-sockaddr test-hnto-types ++ tst-sockaddr test-hnto-types tst-if_index-long + + # tst-deadline must be linked statically so that we can access + # internal functions. +diff --git a/inet/tst-if_index-long.c b/inet/tst-if_index-long.c +new file mode 100644 +index 0000000000000000..3dc74874e5310945 +--- /dev/null ++++ b/inet/tst-if_index-long.c +@@ -0,0 +1,61 @@ ++/* Check for descriptor leak in if_nametoindex with a long interface name. ++ Copyright (C) 2018 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 ++ . */ ++ ++/* This test checks for a descriptor leak in case of a long interface ++ name (CVE-2018-19591, bug 23927). */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ struct support_descriptors *descrs = support_descriptors_list (); ++ ++ /* Prepare a name which is just as long as required for trigging the ++ bug. */ ++ char name[IFNAMSIZ + 1]; ++ memset (name, 'A', IFNAMSIZ); ++ name[IFNAMSIZ] = '\0'; ++ TEST_COMPARE (strlen (name), IFNAMSIZ); ++ struct ifreq ifr; ++ TEST_COMPARE (strlen (name), sizeof (ifr.ifr_name)); ++ ++ /* Test directly via if_nametoindex. */ ++ TEST_COMPARE (if_nametoindex (name), 0); ++ TEST_COMPARE (errno, ENODEV); ++ support_descriptors_check (descrs); ++ ++ /* Same test via getaddrinfo. */ ++ char *host = xasprintf ("fea0::%%%s", name); ++ struct addrinfo hints = { .ai_flags = AI_NUMERICHOST, }; ++ struct addrinfo *ai; ++ TEST_COMPARE (getaddrinfo (host, NULL, &hints, &ai), EAI_NONAME); ++ support_descriptors_check (descrs); ++ ++ support_descriptors_free (descrs); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1654872-1.patch b/glibc-rh1654872-1.patch new file mode 100755 index 0000000..38b6412 --- /dev/null +++ b/glibc-rh1654872-1.patch @@ -0,0 +1,446 @@ +commit 3d265911c2aac65d978f679101594f9071024874 +Author: Andreas Schwab +Date: Mon Nov 12 11:11:40 2018 +0100 + + Reindent nptl/pthread_rwlock_common.c + +diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c +index a290d08332b802a5..5dd534271aed6b41 100644 +--- a/nptl/pthread_rwlock_common.c ++++ b/nptl/pthread_rwlock_common.c +@@ -34,7 +34,7 @@ + + A thread is allowed to acquire a read lock recursively (i.e., have rdlock + critical sections that overlap in sequenced-before) unless the kind of the +- rwlock is set to PTHREAD_RWLOCK_PREFER_WRITERS_NONRECURSIVE_NP. ++ rwlock is set to PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP. + + This lock is built so that workloads of mostly readers can be executed with + low runtime overheads. This matches that the default kind of the lock is +@@ -46,7 +46,7 @@ + An uncontended write lock acquisition is as fast as for a normal + exclusive mutex but writer contention is somewhat more costly due to + keeping track of the exact number of writers. If the rwlock kind requests +- writers to be preferred (i.e., PTHREAD_RWLOCK_PREFER_WRITERS_NP or the ++ writers to be preferred (i.e., PTHREAD_RWLOCK_PREFER_WRITER_NP or the + no-recursive-readers variant of it), then writer--to--writer lock ownership + hand-over is fairly fast and bypasses lock acquisition attempts by readers. + The costs of lock ownership transfer between readers and writers vary. If +@@ -251,7 +251,7 @@ __pthread_rwlock_rdunlock (pthread_rwlock_t *rwlock) + the first reader's store to __wrphase_futex (or a later value) if + the writer observes that a write phase has been started. */ + if (atomic_compare_exchange_weak_release (&rwlock->__data.__readers, +- &r, rnew)) ++ &r, rnew)) + break; + /* TODO Back-off. */ + } +@@ -285,7 +285,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, + /* Make sure we are not holding the rwlock as a writer. This is a deadlock + situation we recognize and report. */ + if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer) +- == THREAD_GETMEM (THREAD_SELF, tid))) ++ == THREAD_GETMEM (THREAD_SELF, tid))) + return EDEADLK; + + /* If we prefer writers, recursive rdlock is disallowed, we are in a read +@@ -299,9 +299,9 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, + if (rwlock->__data.__flags == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP) + { + r = atomic_load_relaxed (&rwlock->__data.__readers); +- while (((r & PTHREAD_RWLOCK_WRPHASE) == 0) +- && ((r & PTHREAD_RWLOCK_WRLOCKED) != 0) +- && ((r >> PTHREAD_RWLOCK_READER_SHIFT) > 0)) ++ while ((r & PTHREAD_RWLOCK_WRPHASE) == 0 ++ && (r & PTHREAD_RWLOCK_WRLOCKED) != 0 ++ && (r >> PTHREAD_RWLOCK_READER_SHIFT) > 0) + { + /* TODO Spin first. */ + /* Try setting the flag signaling that we are waiting without having +@@ -315,11 +315,11 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, + __readers, and all threads set the flag under the same + conditions. */ + while ((atomic_load_relaxed (&rwlock->__data.__readers) +- & PTHREAD_RWLOCK_RWAITING) != 0) ++ & PTHREAD_RWLOCK_RWAITING) != 0) + { + int private = __pthread_rwlock_get_private (rwlock); + int err = futex_abstimed_wait (&rwlock->__data.__readers, +- r, abstime, private); ++ r, abstime, private); + /* We ignore EAGAIN and EINTR. On time-outs, we can just + return because we don't need to clean up anything. */ + if (err == ETIMEDOUT) +@@ -338,8 +338,9 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, + expected value for future operations. Acquire MO so we synchronize with + prior writers as well as the last reader of the previous read phase (see + below). */ +- r = atomic_fetch_add_acquire (&rwlock->__data.__readers, +- (1 << PTHREAD_RWLOCK_READER_SHIFT)) + (1 << PTHREAD_RWLOCK_READER_SHIFT); ++ r = (atomic_fetch_add_acquire (&rwlock->__data.__readers, ++ (1 << PTHREAD_RWLOCK_READER_SHIFT)) ++ + (1 << PTHREAD_RWLOCK_READER_SHIFT)); + + /* Check whether there is an overflow in the number of readers. We assume + that the total number of threads is less than half the maximum number +@@ -359,8 +360,9 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, + /* Relaxed MO is okay because we just want to undo our registration and + cannot have changed the rwlock state substantially if the CAS + succeeds. */ +- if (atomic_compare_exchange_weak_relaxed (&rwlock->__data.__readers, &r, +- r - (1 << PTHREAD_RWLOCK_READER_SHIFT))) ++ if (atomic_compare_exchange_weak_relaxed ++ (&rwlock->__data.__readers, ++ &r, r - (1 << PTHREAD_RWLOCK_READER_SHIFT))) + return EAGAIN; + } + +@@ -378,15 +380,15 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, + /* Otherwise, if we were in a write phase (states #6 or #8), we must wait + for explicit hand-over of the read phase; the only exception is if we + can start a read phase if there is no primary writer currently. */ +- while (((r & PTHREAD_RWLOCK_WRPHASE) != 0) +- && ((r & PTHREAD_RWLOCK_WRLOCKED) == 0)) ++ while ((r & PTHREAD_RWLOCK_WRPHASE) != 0 ++ && (r & PTHREAD_RWLOCK_WRLOCKED) == 0) + { +- /* Try to enter a read phase: If the CAS below succeeds, we have ++ /* Try to enter a read phase: If the CAS below succeeds, we have + ownership; if it fails, we will simply retry and reassess the + situation. + Acquire MO so we synchronize with prior writers. */ + if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, &r, +- r ^ PTHREAD_RWLOCK_WRPHASE)) ++ r ^ PTHREAD_RWLOCK_WRPHASE)) + { + /* We started the read phase, so we are also responsible for + updating the write-phase futex. Relaxed MO is sufficient. +@@ -397,7 +399,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, + (but we can pretend to do the setting and unsetting of WRLOCKED + atomically, and thus can skip this step). */ + if ((atomic_exchange_relaxed (&rwlock->__data.__wrphase_futex, 0) +- & PTHREAD_RWLOCK_FUTEX_USED) != 0) ++ & PTHREAD_RWLOCK_FUTEX_USED) != 0) + { + int private = __pthread_rwlock_get_private (rwlock); + futex_wake (&rwlock->__data.__wrphase_futex, INT_MAX, private); +@@ -435,16 +437,17 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, + for (;;) + { + while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex)) +- | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED)) ++ | PTHREAD_RWLOCK_FUTEX_USED) == (1 | PTHREAD_RWLOCK_FUTEX_USED)) + { + int private = __pthread_rwlock_get_private (rwlock); + if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0) +- && !atomic_compare_exchange_weak_relaxed ++ && (!atomic_compare_exchange_weak_relaxed + (&rwlock->__data.__wrphase_futex, +- &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED)) ++ &wpf, wpf | PTHREAD_RWLOCK_FUTEX_USED))) + continue; + int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex, +- 1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private); ++ 1 | PTHREAD_RWLOCK_FUTEX_USED, ++ abstime, private); + if (err == ETIMEDOUT) + { + /* If we timed out, we need to unregister. If no read phase +@@ -477,8 +480,8 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, + in this case and thus make the spin-waiting we need + unnecessarily expensive. */ + while ((atomic_load_relaxed (&rwlock->__data.__wrphase_futex) +- | PTHREAD_RWLOCK_FUTEX_USED) +- == (1 | PTHREAD_RWLOCK_FUTEX_USED)) ++ | PTHREAD_RWLOCK_FUTEX_USED) ++ == (1 | PTHREAD_RWLOCK_FUTEX_USED)) + { + /* TODO Back-off? */ + } +@@ -495,7 +498,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, + release of the writer, and so that we observe a recent value of + __wrphase_futex (see below). */ + if ((atomic_load_acquire (&rwlock->__data.__readers) +- & PTHREAD_RWLOCK_WRPHASE) == 0) ++ & PTHREAD_RWLOCK_WRPHASE) == 0) + /* We are in a read phase now, so the least recent modification of + __wrphase_futex we can read from is the store by the writer + with value 1. Thus, only now we can assume that if we observe +@@ -516,8 +519,9 @@ __pthread_rwlock_wrunlock (pthread_rwlock_t *rwlock) + atomic_store_relaxed (&rwlock->__data.__cur_writer, 0); + /* Disable waiting by writers. We will wake up after we decided how to + proceed. */ +- bool wake_writers = ((atomic_exchange_relaxed +- (&rwlock->__data.__writers_futex, 0) & PTHREAD_RWLOCK_FUTEX_USED) != 0); ++ bool wake_writers ++ = ((atomic_exchange_relaxed (&rwlock->__data.__writers_futex, 0) ++ & PTHREAD_RWLOCK_FUTEX_USED) != 0); + + if (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP) + { +@@ -529,8 +533,8 @@ __pthread_rwlock_wrunlock (pthread_rwlock_t *rwlock) + synchronize with us and thus can take over our view of + __readers (including, for example, whether we are in a write + phase or not). */ +- if (atomic_compare_exchange_weak_release (&rwlock->__data.__writers, +- &w, w | PTHREAD_RWLOCK_WRHANDOVER)) ++ if (atomic_compare_exchange_weak_release ++ (&rwlock->__data.__writers, &w, w | PTHREAD_RWLOCK_WRHANDOVER)) + /* Another writer will take over. */ + goto done; + /* TODO Back-off. */ +@@ -543,9 +547,10 @@ __pthread_rwlock_wrunlock (pthread_rwlock_t *rwlock) + unsigned int r = atomic_load_relaxed (&rwlock->__data.__readers); + /* Release MO so that subsequent readers or writers synchronize with us. */ + while (!atomic_compare_exchange_weak_release +- (&rwlock->__data.__readers, &r, (r ^ PTHREAD_RWLOCK_WRLOCKED) +- ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0 +- : PTHREAD_RWLOCK_WRPHASE))) ++ (&rwlock->__data.__readers, &r, ++ ((r ^ PTHREAD_RWLOCK_WRLOCKED) ++ ^ ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0 ? 0 ++ : PTHREAD_RWLOCK_WRPHASE)))) + { + /* TODO Back-off. */ + } +@@ -574,7 +579,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + /* Make sure we are not holding the rwlock as a writer. This is a deadlock + situation we recognize and report. */ + if (__glibc_unlikely (atomic_load_relaxed (&rwlock->__data.__cur_writer) +- == THREAD_GETMEM (THREAD_SELF, tid))) ++ == THREAD_GETMEM (THREAD_SELF, tid))) + return EDEADLK; + + /* First we try to acquire the role of primary writer by setting WRLOCKED; +@@ -593,12 +598,12 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + this could be less scalable if readers arrive and leave frequently. */ + bool may_share_futex_used_flag = false; + unsigned int r = atomic_fetch_or_acquire (&rwlock->__data.__readers, +- PTHREAD_RWLOCK_WRLOCKED); ++ PTHREAD_RWLOCK_WRLOCKED); + if (__glibc_unlikely ((r & PTHREAD_RWLOCK_WRLOCKED) != 0)) + { + /* There is another primary writer. */ +- bool prefer_writer = +- (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP); ++ bool prefer_writer ++ = (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP); + if (prefer_writer) + { + /* We register as a waiting writer, so that we can make use of +@@ -617,8 +622,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + /* Try to become the primary writer or retry. Acquire MO as in + the fetch_or above. */ + if (atomic_compare_exchange_weak_acquire +- (&rwlock->__data.__readers, &r, +- r | PTHREAD_RWLOCK_WRLOCKED)) ++ (&rwlock->__data.__readers, &r, r | PTHREAD_RWLOCK_WRLOCKED)) + { + if (prefer_writer) + { +@@ -633,8 +637,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + __writers). + ??? Perhaps this is not strictly necessary for + reasons we do not yet know of. */ +- atomic_fetch_add_relaxed (&rwlock->__data.__writers, +- -1); ++ atomic_fetch_add_relaxed (&rwlock->__data.__writers, -1); + } + break; + } +@@ -646,8 +649,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + succeed, we own WRLOCKED. */ + if (prefer_writer) + { +- unsigned int w = atomic_load_relaxed +- (&rwlock->__data.__writers); ++ unsigned int w = atomic_load_relaxed (&rwlock->__data.__writers); + if ((w & PTHREAD_RWLOCK_WRHANDOVER) != 0) + { + /* Acquire MO is required here so that we synchronize with +@@ -677,13 +679,13 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + /* We did not acquire WRLOCKED nor were able to use writer--writer + hand-over, so we block on __writers_futex. */ + int private = __pthread_rwlock_get_private (rwlock); +- unsigned int wf = atomic_load_relaxed +- (&rwlock->__data.__writers_futex); ++ unsigned int wf ++ = atomic_load_relaxed (&rwlock->__data.__writers_futex); + if (((wf & ~(unsigned int) PTHREAD_RWLOCK_FUTEX_USED) != 1) + || ((wf != (1 | PTHREAD_RWLOCK_FUTEX_USED)) +- && !atomic_compare_exchange_weak_relaxed ++ && (!atomic_compare_exchange_weak_relaxed + (&rwlock->__data.__writers_futex, &wf, +- 1 | PTHREAD_RWLOCK_FUTEX_USED))) ++ 1 | PTHREAD_RWLOCK_FUTEX_USED)))) + { + /* If we cannot block on __writers_futex because there is no + primary writer, or we cannot set PTHREAD_RWLOCK_FUTEX_USED, +@@ -704,7 +706,8 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + in this group. */ + may_share_futex_used_flag = true; + int err = futex_abstimed_wait (&rwlock->__data.__writers_futex, +- 1 | PTHREAD_RWLOCK_FUTEX_USED, abstime, private); ++ 1 | PTHREAD_RWLOCK_FUTEX_USED, ++ abstime, private); + if (err == ETIMEDOUT) + { + if (prefer_writer) +@@ -716,10 +719,10 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + that this happened before the timeout; see + pthread_rwlock_rdlock_full for the full reasoning.) + Also see the similar code above. */ +- unsigned int w = atomic_load_relaxed +- (&rwlock->__data.__writers); ++ unsigned int w ++ = atomic_load_relaxed (&rwlock->__data.__writers); + while (!atomic_compare_exchange_weak_acquire +- (&rwlock->__data.__writers, &w, ++ (&rwlock->__data.__writers, &w, + (w == PTHREAD_RWLOCK_WRHANDOVER + 1 ? 0 : w - 1))) + { + /* TODO Back-off. */ +@@ -751,7 +754,8 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + modifications of __readers ensures that this store happens after the + store of value 0 by the previous primary writer. */ + atomic_store_relaxed (&rwlock->__data.__writers_futex, +- 1 | (may_share_futex_used_flag ? PTHREAD_RWLOCK_FUTEX_USED : 0)); ++ 1 | (may_share_futex_used_flag ++ ? PTHREAD_RWLOCK_FUTEX_USED : 0)); + + /* If we are in a write phase, we have acquired the lock. */ + if ((r & PTHREAD_RWLOCK_WRPHASE) != 0) +@@ -759,15 +763,15 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + + /* If we are in a read phase and there are no readers, try to start a write + phase. */ +- while (((r & PTHREAD_RWLOCK_WRPHASE) == 0) +- && ((r >> PTHREAD_RWLOCK_READER_SHIFT) == 0)) ++ while ((r & PTHREAD_RWLOCK_WRPHASE) == 0 ++ && (r >> PTHREAD_RWLOCK_READER_SHIFT) == 0) + { + /* Acquire MO so that we synchronize with prior writers and do + not interfere with their updates to __writers_futex, as well + as regarding prior readers and their updates to __wrphase_futex, + respectively. */ + if (atomic_compare_exchange_weak_acquire (&rwlock->__data.__readers, +- &r, r | PTHREAD_RWLOCK_WRPHASE)) ++ &r, r | PTHREAD_RWLOCK_WRPHASE)) + { + /* We have started a write phase, so need to enable readers to wait. + See the similar case in __pthread_rwlock_rdlock_full. Unlike in +@@ -792,24 +796,24 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + for (;;) + { + while (((wpf = atomic_load_relaxed (&rwlock->__data.__wrphase_futex)) +- | PTHREAD_RWLOCK_FUTEX_USED) == PTHREAD_RWLOCK_FUTEX_USED) ++ | PTHREAD_RWLOCK_FUTEX_USED) == PTHREAD_RWLOCK_FUTEX_USED) + { + int private = __pthread_rwlock_get_private (rwlock); +- if (((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0) +- && !atomic_compare_exchange_weak_relaxed ++ if ((wpf & PTHREAD_RWLOCK_FUTEX_USED) == 0 ++ && (!atomic_compare_exchange_weak_relaxed + (&rwlock->__data.__wrphase_futex, &wpf, +- PTHREAD_RWLOCK_FUTEX_USED)) ++ PTHREAD_RWLOCK_FUTEX_USED))) + continue; + int err = futex_abstimed_wait (&rwlock->__data.__wrphase_futex, +- PTHREAD_RWLOCK_FUTEX_USED, abstime, private); ++ PTHREAD_RWLOCK_FUTEX_USED, ++ abstime, private); + if (err == ETIMEDOUT) + { +- if (rwlock->__data.__flags +- != PTHREAD_RWLOCK_PREFER_READER_NP) ++ if (rwlock->__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP) + { + /* We try writer--writer hand-over. */ +- unsigned int w = atomic_load_relaxed +- (&rwlock->__data.__writers); ++ unsigned int w ++ = atomic_load_relaxed (&rwlock->__data.__writers); + if (w != 0) + { + /* We are about to hand over WRLOCKED, so we must +@@ -823,13 +827,13 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + Release MO so that another writer that gets + WRLOCKED from us can take over our view of + __readers. */ +- unsigned int wf = atomic_exchange_relaxed +- (&rwlock->__data.__writers_futex, 0); ++ unsigned int wf ++ = atomic_exchange_relaxed (&rwlock->__data.__writers_futex, 0); + while (w != 0) + { + if (atomic_compare_exchange_weak_release + (&rwlock->__data.__writers, &w, +- w | PTHREAD_RWLOCK_WRHANDOVER)) ++ w | PTHREAD_RWLOCK_WRHANDOVER)) + { + /* Wake other writers. */ + if ((wf & PTHREAD_RWLOCK_FUTEX_USED) != 0) +@@ -844,8 +848,7 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + again. Make sure we don't loose the flag that + signals whether there are threads waiting on + this futex. */ +- atomic_store_relaxed +- (&rwlock->__data.__writers_futex, wf); ++ atomic_store_relaxed (&rwlock->__data.__writers_futex, wf); + } + } + /* If we timed out and we are not in a write phase, we can +@@ -857,8 +860,8 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + /* We are about to release WRLOCKED, so we must release + __writers_futex too; see the handling of + writer--writer hand-over above. */ +- unsigned int wf = atomic_exchange_relaxed +- (&rwlock->__data.__writers_futex, 0); ++ unsigned int wf ++ = atomic_exchange_relaxed (&rwlock->__data.__writers_futex, 0); + while ((r & PTHREAD_RWLOCK_WRPHASE) == 0) + { + /* While we don't need to make anything from a +@@ -877,11 +880,11 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + /* Wake other writers. */ + if ((wf & PTHREAD_RWLOCK_FUTEX_USED) != 0) + futex_wake (&rwlock->__data.__writers_futex, +- 1, private); ++ 1, private); + /* Wake waiting readers. */ + if ((r & PTHREAD_RWLOCK_RWAITING) != 0) + futex_wake (&rwlock->__data.__readers, +- INT_MAX, private); ++ INT_MAX, private); + return ETIMEDOUT; + } + } +@@ -898,10 +901,9 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + atomic_thread_fence_acquire (); + /* We still need to wait for explicit hand-over, but we must + not use futex_wait anymore. */ +- while ((atomic_load_relaxed +- (&rwlock->__data.__wrphase_futex) +- | PTHREAD_RWLOCK_FUTEX_USED) +- == PTHREAD_RWLOCK_FUTEX_USED) ++ while ((atomic_load_relaxed (&rwlock->__data.__wrphase_futex) ++ | PTHREAD_RWLOCK_FUTEX_USED) ++ == PTHREAD_RWLOCK_FUTEX_USED) + { + /* TODO Back-off. */ + } +@@ -915,12 +917,12 @@ __pthread_rwlock_wrlock_full (pthread_rwlock_t *rwlock, + if (ready) + break; + if ((atomic_load_acquire (&rwlock->__data.__readers) +- & PTHREAD_RWLOCK_WRPHASE) != 0) ++ & PTHREAD_RWLOCK_WRPHASE) != 0) + ready = true; + } + + done: + atomic_store_relaxed (&rwlock->__data.__cur_writer, +- THREAD_GETMEM (THREAD_SELF, tid)); ++ THREAD_GETMEM (THREAD_SELF, tid)); + return 0; + } diff --git a/glibc-rh1654872-2.patch b/glibc-rh1654872-2.patch new file mode 100755 index 0000000..04c40ee --- /dev/null +++ b/glibc-rh1654872-2.patch @@ -0,0 +1,134 @@ +commit f21e8f8ca466320fed38bdb71526c574dae98026 +Author: Andreas Schwab +Date: Thu Nov 8 14:28:22 2018 +0100 + + Fix rwlock stall with PREFER_WRITER_NONRECURSIVE_NP (bug 23861) + + In the read lock function (__pthread_rwlock_rdlock_full) there was a + code path which would fail to reload __readers while waiting for + PTHREAD_RWLOCK_RWAITING to change. This failure to reload __readers + into a local value meant that various conditionals used the old value + of __readers and with only two threads left it could result in an + indefinite stall of one of the readers (waiting for PTHREAD_RWLOCK_RWAITING + to go to zero, but it never would). + +diff --git a/nptl/Makefile b/nptl/Makefile +index ee720960d18f33d1..2d2db648f730db61 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -318,7 +318,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \ + tst-minstack-throw \ + 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-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \ ++ tst-rwlock-pwn + + tests-internal := tst-rwlock19 tst-rwlock20 \ + tst-sem11 tst-sem12 tst-sem13 \ +diff --git a/nptl/pthread_rwlock_common.c b/nptl/pthread_rwlock_common.c +index 5dd534271aed6b41..85fc1bcfc7f5e60d 100644 +--- a/nptl/pthread_rwlock_common.c ++++ b/nptl/pthread_rwlock_common.c +@@ -314,7 +314,7 @@ __pthread_rwlock_rdlock_full (pthread_rwlock_t *rwlock, + harmless because the flag is just about the state of + __readers, and all threads set the flag under the same + conditions. */ +- while ((atomic_load_relaxed (&rwlock->__data.__readers) ++ while (((r = atomic_load_relaxed (&rwlock->__data.__readers)) + & PTHREAD_RWLOCK_RWAITING) != 0) + { + int private = __pthread_rwlock_get_private (rwlock); +diff --git a/nptl/tst-rwlock-pwn.c b/nptl/tst-rwlock-pwn.c +new file mode 100644 +index 0000000000000000..c39dd70973f1a76e +--- /dev/null ++++ b/nptl/tst-rwlock-pwn.c +@@ -0,0 +1,87 @@ ++/* Test rwlock with PREFER_WRITER_NONRECURSIVE_NP (bug 23861). ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* We choose 10 iterations because this happens to be able to trigger the ++ stall on contemporary hardware. */ ++#define LOOPS 10 ++/* We need 3 threads to trigger bug 23861. One thread as a writer, and ++ two reader threads. The test verifies that the second-to-last reader ++ is able to notify the *last* reader that it should be done waiting. ++ If the second-to-last reader fails to notify the last reader or does ++ so incorrectly then the last reader may stall indefinitely. */ ++#define NTHREADS 3 ++ ++_Atomic int do_exit; ++pthread_rwlockattr_t mylock_attr; ++pthread_rwlock_t mylock; ++ ++void * ++run_loop (void *a) ++{ ++ while (!do_exit) ++ { ++ if (random () & 1) ++ { ++ xpthread_rwlock_wrlock (&mylock); ++ xpthread_rwlock_unlock (&mylock); ++ } ++ else ++ { ++ xpthread_rwlock_rdlock (&mylock); ++ xpthread_rwlock_unlock (&mylock); ++ } ++ } ++ return NULL; ++} ++ ++int ++do_test (void) ++{ ++ xpthread_rwlockattr_init (&mylock_attr); ++ xpthread_rwlockattr_setkind_np (&mylock_attr, ++ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); ++ xpthread_rwlock_init (&mylock, &mylock_attr); ++ ++ for (int n = 0; n < LOOPS; n++) ++ { ++ pthread_t tids[NTHREADS]; ++ do_exit = 0; ++ for (int i = 0; i < NTHREADS; i++) ++ tids[i] = xpthread_create (NULL, run_loop, NULL); ++ /* Let the threads run for some time. */ ++ sleep (1); ++ printf ("Exiting..."); ++ fflush (stdout); ++ do_exit = 1; ++ for (int i = 0; i < NTHREADS; i++) ++ xpthread_join (tids[i]); ++ printf ("done.\n"); ++ } ++ pthread_rwlock_destroy (&mylock); ++ pthread_rwlockattr_destroy (&mylock_attr); ++ return 0; ++} ++ ++#define TIMEOUT (DEFAULT_TIMEOUT + 3 * LOOPS) ++#include diff --git a/glibc-rh1658901.patch b/glibc-rh1658901.patch new file mode 100755 index 0000000..59d7cab --- /dev/null +++ b/glibc-rh1658901.patch @@ -0,0 +1,140 @@ +Upstream commit 1d880d4a9bf7608c2cd33bbe954ce6995f79121a + +From: Tulio Magno Quites Machado Filho +Date: Wed, 12 Dec 2018 12:41:52 +0000 (-0200) +Subject: powerpc: Add missing CFI register information (bug #23614) +X-Git-Tag: glibc-2.29~210 +X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=1d880d4a9bf7608c2cd33bbe954ce6995f79121a + +powerpc: Add missing CFI register information (bug #23614) + +Add CFI information about the offset of registers stored in the stack +frame. + + [BZ #23614] + * sysdeps/powerpc/powerpc64/addmul_1.S (FUNC): Add CFI offset for + registers saved in the stack frame. + * sysdeps/powerpc/powerpc64/lshift.S (__mpn_lshift): Likewise. + * sysdeps/powerpc/powerpc64/mul_1.S (__mpn_mul_1): Likewise. + +Signed-off-by: Tulio Magno Quites Machado Filho +Reviewed-by: Gabriel F. T. Gomes +--- + +diff --git a/sysdeps/powerpc/powerpc64/addmul_1.S b/sysdeps/powerpc/powerpc64/addmul_1.S +index 48e3b1b..e450d6a 100644 +--- a/sysdeps/powerpc/powerpc64/addmul_1.S ++++ b/sysdeps/powerpc/powerpc64/addmul_1.S +@@ -34,16 +34,27 @@ + #define N r5 + #define VL r6 + ++#define R27SAVE (-40) ++#define R28SAVE (-32) ++#define R29SAVE (-24) ++#define R30SAVE (-16) ++#define R31SAVE (-8) ++ + ENTRY_TOCLESS (FUNC, 5) +- std r31, -8(r1) ++ std r31, R31SAVE(r1) + rldicl. r0, N, 0, 62 +- std r30, -16(r1) ++ std r30, R30SAVE(r1) + cmpdi VL, r0, 2 +- std r29, -24(r1) ++ std r29, R29SAVE(r1) + addi N, N, 3 +- std r28, -32(r1) ++ std r28, R28SAVE(r1) + srdi N, N, 2 +- std r27, -40(r1) ++ std r27, R27SAVE(r1) ++ cfi_offset(r31, R31SAVE) ++ cfi_offset(r30, R30SAVE) ++ cfi_offset(r29, R29SAVE) ++ cfi_offset(r28, R28SAVE) ++ cfi_offset(r27, R27SAVE) + mtctr N + beq cr0, L(b00) + blt cr6, L(b01) +@@ -199,10 +210,10 @@ L(end): mulld r0, r9, VL + addic r11, r11, 1 + #endif + addze RP, r8 +- ld r31, -8(r1) +- ld r30, -16(r1) +- ld r29, -24(r1) +- ld r28, -32(r1) +- ld r27, -40(r1) ++ ld r31, R31SAVE(r1) ++ ld r30, R30SAVE(r1) ++ ld r29, R29SAVE(r1) ++ ld r28, R28SAVE(r1) ++ ld r27, R27SAVE(r1) + blr + END(FUNC) +diff --git a/sysdeps/powerpc/powerpc64/lshift.S b/sysdeps/powerpc/powerpc64/lshift.S +index 8b6396e..855d6f2 100644 +--- a/sysdeps/powerpc/powerpc64/lshift.S ++++ b/sysdeps/powerpc/powerpc64/lshift.S +@@ -26,11 +26,15 @@ + #define TNC r0 + #define U0 r30 + #define U1 r31 ++#define U0SAVE (-16) ++#define U1SAVE (-8) + #define RETVAL r5 + + ENTRY_TOCLESS (__mpn_lshift, 5) +- std U1, -8(r1) +- std U0, -16(r1) ++ std U1, U1SAVE(r1) ++ std U0, U0SAVE(r1) ++ cfi_offset(U1, U1SAVE) ++ cfi_offset(U0, U0SAVE) + subfic TNC, CNT, 64 + sldi r7, N, RP + add UP, UP, r7 +@@ -170,8 +174,8 @@ L(cj3): or r10, r12, r7 + L(cj2): std r10, -32(RP) + std r8, -40(RP) + +-L(ret): ld U1, -8(r1) +- ld U0, -16(r1) ++L(ret): ld U1, U1SAVE(r1) ++ ld U0, U0SAVE(r1) + mr RP, RETVAL + blr + END(__mpn_lshift) +diff --git a/sysdeps/powerpc/powerpc64/mul_1.S b/sysdeps/powerpc/powerpc64/mul_1.S +index 953ded8..cade365 100644 +--- a/sysdeps/powerpc/powerpc64/mul_1.S ++++ b/sysdeps/powerpc/powerpc64/mul_1.S +@@ -24,9 +24,14 @@ + #define N r5 + #define VL r6 + ++#define R26SAVE (-48) ++#define R27SAVE (-40) ++ + ENTRY_TOCLESS (__mpn_mul_1, 5) +- std r27, -40(r1) +- std r26, -48(r1) ++ std r27, R27SAVE(r1) ++ std r26, R26SAVE(r1) ++ cfi_offset(r27, R27SAVE) ++ cfi_offset(r26, R26SAVE) + li r12, 0 + ld r26, 0(UP) + +@@ -129,7 +134,7 @@ L(end): mulld r0, r26, VL + std r0, 0(RP) + std r7, 8(RP) + L(ret): addze RP, r8 +- ld r27, -40(r1) +- ld r26, -48(r1) ++ ld r27, R27SAVE(r1) ++ ld r26, R26SAVE(r1) + blr + END(__mpn_mul_1) diff --git a/glibc-rh1659293-1.patch b/glibc-rh1659293-1.patch new file mode 100755 index 0000000..cf8ca21 --- /dev/null +++ b/glibc-rh1659293-1.patch @@ -0,0 +1,663 @@ +nptl: Fix pthread_rwlock_try*lock stalls (Bug 23844) + +For a full analysis of both the pthread_rwlock_tryrdlock() stall +and the pthread_rwlock_trywrlock() stall see: +https://sourceware.org/bugzilla/show_bug.cgi?id=23844#c14 + +In the pthread_rwlock_trydlock() function we fail to inspect for +PTHREAD_RWLOCK_FUTEX_USED in __wrphase_futex and wake the waiting +readers. + +In the pthread_rwlock_trywrlock() function we write 1 to +__wrphase_futex and loose the setting of the PTHREAD_RWLOCK_FUTEX_USED +bit, again failing to wake waiting readers during unlock. + +The fix in the case of pthread_rwlock_trydlock() is to check for +PTHREAD_RWLOCK_FUTEX_USED and wake the readers. + +The fix in the case of pthread_rwlock_trywrlock() is to only write +1 to __wrphase_futex if we installed the write phase, since all other +readers would be spinning waiting for this step. + +We add two new tests, one exercises the stall for +pthread_rwlock_trywrlock() which is easy to exercise, and one exercises +the stall for pthread_rwlock_trydlock() which is harder to exercise. + +The pthread_rwlock_trywrlock() test fails consistently without the fix, +and passes after. The pthread_rwlock_tryrdlock() test fails roughly +5-10% of the time without the fix, and passes all the time after. + +Signed-off-by: Carlos O'Donell +Signed-off-by: Torvald Riegel +Signed-off-by: Rik Prohaska +Co-authored-by: Torvald Riegel +Co-authored-by: Rik Prohaska +(cherry picked from commit 5fc9ed4c4058bfbdf51ad6e7aac7d209b580e8c4) + +diff --git a/ChangeLog b/ChangeLog +index 08b42bd2f56471e3..ed1a2ffe8356fd96 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,20 @@ ++2019-01-31 Carlos O'Donell ++ Torvald Riegel ++ Rik Prohaska ++ ++ [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. ++ + 2018-08-01 Carlos O'Donel + + * version.h (RELEASE): Set to "stable". +diff --git a/nptl/Makefile b/nptl/Makefile +index 2d2db648f730db61..b1003cf56b31ddfa 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_rwlock_tryrdlock.c b/nptl/pthread_rwlock_tryrdlock.c +index 4aec1fc15acb2448..31a88d33a6e8f256 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 5a73eba756077297..f2e3443466a2554f 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/tst-rwlock-tryrdlock-stall.c b/nptl/tst-rwlock-tryrdlock-stall.c +new file mode 100644 +index 0000000000000000..5e476da2b8d00c6a +--- /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 ++ . */ ++ ++/* 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 ++#include ++#include ++#include ++#include ++#include ++ ++/* 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 +diff --git a/nptl/tst-rwlock-trywrlock-stall.c b/nptl/tst-rwlock-trywrlock-stall.c +new file mode 100644 +index 0000000000000000..14d27cbcbc882cb1 +--- /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 ++ . */ ++ ++/* 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 ++#include ++#include ++#include ++#include ++#include ++ ++/* 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 +diff --git a/support/Makefile b/support/Makefile +index 93a514301654132e..41da4abaaa5a645a 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -129,6 +129,7 @@ libsupport-routines = \ + xpthread_mutexattr_settype \ + xpthread_once \ + xpthread_rwlock_init \ ++ xpthread_rwlock_destroy \ + xpthread_rwlock_rdlock \ + xpthread_rwlock_unlock \ + xpthread_rwlock_wrlock \ +diff --git a/support/xpthread_rwlock_destroy.c b/support/xpthread_rwlock_destroy.c +new file mode 100644 +index 0000000000000000..6d6e95356963b47f +--- /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 ++ . */ ++ ++#include ++ ++void ++xpthread_rwlock_destroy (pthread_rwlock_t *rwlock) ++{ ++ xpthread_check_return ("pthread_rwlock_destroy", ++ pthread_rwlock_destroy (rwlock)); ++} +diff --git a/support/xthread.h b/support/xthread.h +index 623f5ad0acb895ef..1af77280871464c2 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/glibc-rh1659293-2.patch b/glibc-rh1659293-2.patch new file mode 100755 index 0000000..eca43d2 --- /dev/null +++ b/glibc-rh1659293-2.patch @@ -0,0 +1,61 @@ +nptl/tst-rwlock14: Test pthread_rwlock_timedwrlock correctly + +(cherry picked from commit 82849fde3b8cb9b9396fa8cadf842dc2b1d2cced) + +diff --git a/ChangeLog b/ChangeLog +index ed1a2ffe8356fd96..74e634670c62d5c2 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,10 @@ ++2019-03-25 Mike Crowe ++ ++ * nptl/tst-rwlock14.c (do_test): Replace duplicate calls to ++ pthread_rwlock_timedrdlock with calls to ++ pthread_rwlock_timedwrlock to ensure that the latter is tested ++ too. Use new function name in diagnostic messages too. ++ + 2019-01-31 Carlos O'Donell + Torvald Riegel + Rik Prohaska +diff --git a/nptl/tst-rwlock14.c b/nptl/tst-rwlock14.c +index d6fda87c61e9aed4..073e6c98d2f5cc12 100644 +--- a/nptl/tst-rwlock14.c ++++ b/nptl/tst-rwlock14.c +@@ -117,15 +117,15 @@ do_test (void) + result = 1; + } + +- e = pthread_rwlock_timedrdlock (&r, &ts); ++ e = pthread_rwlock_timedwrlock (&r, &ts); + if (e == 0) + { +- puts ("second rwlock_timedrdlock did not fail"); ++ puts ("second rwlock_timedwrlock did not fail"); + result = 1; + } + else if (e != EINVAL) + { +- puts ("second rwlock_timedrdlock did not return EINVAL"); ++ puts ("second rwlock_timedwrlock did not return EINVAL"); + result = 1; + } + +@@ -145,15 +145,15 @@ do_test (void) + result = 1; + } + +- e = pthread_rwlock_timedrdlock (&r, &ts); ++ e = pthread_rwlock_timedwrlock (&r, &ts); + if (e == 0) + { +- puts ("third rwlock_timedrdlock did not fail"); ++ puts ("third rwlock_timedwrlock did not fail"); + result = 1; + } + else if (e != EINVAL) + { +- puts ("third rwlock_timedrdlock did not return EINVAL"); ++ puts ("third rwlock_timedwrlock did not return EINVAL"); + result = 1; + } + diff --git a/glibc-rh1659438-1.patch b/glibc-rh1659438-1.patch new file mode 100755 index 0000000..6e22946 --- /dev/null +++ b/glibc-rh1659438-1.patch @@ -0,0 +1,118 @@ +commit b8686c0d7098168481a246f8199ab2d865f52d3d +Author: Stefan Liebler +Date: Tue Dec 18 13:57:03 2018 +0100 + + S390: Add configure check to detect z10 as mininum architecture level set. + + Add a configure check for z10 in the same way as done for z196. + + ChangeLog: + + * config.h.in (HAVE_S390_MIN_Z10_ZARCH_ASM_SUPPORT): New undefine. + * sysdeps/s390/configure.ac: Add check for z10 support. + * sysdeps/s390/configure: Regenerated. + +diff --git a/config.h.in b/config.h.in +index 141db213a9046eb4..beecc39d5b8c3f4a 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -62,6 +62,9 @@ + /* Define if assembler supports AVX512DQ. */ + #undef HAVE_AVX512DQ_ASM_SUPPORT + ++/* Define if assembler supports z10 zarch instructions as default on S390. */ ++#undef HAVE_S390_MIN_Z10_ZARCH_ASM_SUPPORT ++ + /* Define if assembler supports z196 zarch instructions as default on S390. */ + #undef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT + +diff --git a/sysdeps/s390/configure b/sysdeps/s390/configure +index 74b415f2ab0fa982..f30f8644361f474a 100644 +--- a/sysdeps/s390/configure ++++ b/sysdeps/s390/configure +@@ -112,6 +112,45 @@ then + + fi + ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 z10 zarch instruction support as default" >&5 ++$as_echo_n "checking for S390 z10 zarch instruction support as default... " >&6; } ++if ${libc_cv_asm_s390_min_z10_zarch+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat > conftest.c <<\EOF ++void testinsn (void *a, void *b, int n) ++{ ++ __asm__ ("exrl %2,1f \n\t" ++ "j 2f \n\t" ++ "1: mvc 0(1,%0),0(%1) \n\t" ++ "2:" ++ : : "a" (a), "a" (b), "d" (n) ++ : "memory", "cc"); ++} ++EOF ++if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c ++ -o conftest.o &> /dev/null' ++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } ; ++then ++ libc_cv_asm_s390_min_z10_zarch=yes ++else ++ libc_cv_asm_s390_min_z10_zarch=no ++fi ++rm -f conftest* ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_s390_min_z10_zarch" >&5 ++$as_echo "$libc_cv_asm_s390_min_z10_zarch" >&6; } ++ ++if test "$libc_cv_asm_s390_min_z10_zarch" = yes ; ++then ++ $as_echo "#define HAVE_S390_MIN_Z10_ZARCH_ASM_SUPPORT 1" >>confdefs.h ++ ++fi ++ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 z196 zarch instruction support as default" >&5 + $as_echo_n "checking for S390 z196 zarch instruction support as default... " >&6; } + if ${libc_cv_asm_s390_min_z196_zarch+:} false; then : +diff --git a/sysdeps/s390/configure.ac b/sysdeps/s390/configure.ac +index 1cdb0212825a3f18..981f7a79dd7066fc 100644 +--- a/sysdeps/s390/configure.ac ++++ b/sysdeps/s390/configure.ac +@@ -80,6 +80,35 @@ then + AC_DEFINE(HAVE_S390_VX_GCC_SUPPORT) + fi + ++AC_CACHE_CHECK(for S390 z10 zarch instruction support as default, ++ libc_cv_asm_s390_min_z10_zarch, [dnl ++cat > conftest.c <<\EOF ++void testinsn (void *a, void *b, int n) ++{ ++ __asm__ ("exrl %2,1f \n\t" ++ "j 2f \n\t" ++ "1: mvc 0(1,%0),0(%1) \n\t" ++ "2:" ++ : : "a" (a), "a" (b), "d" (n) ++ : "memory", "cc"); ++} ++EOF ++dnl ++dnl test, if assembler supports S390 z10 zarch instructions as default ++if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c ++ -o conftest.o &> /dev/null]) ; ++then ++ libc_cv_asm_s390_min_z10_zarch=yes ++else ++ libc_cv_asm_s390_min_z10_zarch=no ++fi ++rm -f conftest* ]) ++ ++if test "$libc_cv_asm_s390_min_z10_zarch" = yes ; ++then ++ AC_DEFINE(HAVE_S390_MIN_Z10_ZARCH_ASM_SUPPORT) ++fi ++ + AC_CACHE_CHECK(for S390 z196 zarch instruction support as default, + libc_cv_asm_s390_min_z196_zarch, [dnl + cat > conftest.c <<\EOF diff --git a/glibc-rh1659438-10.patch b/glibc-rh1659438-10.patch new file mode 100755 index 0000000..729f1b5 --- /dev/null +++ b/glibc-rh1659438-10.patch @@ -0,0 +1,189 @@ +commit e099aab060df178a7fcd5a55282650fe45ccea66 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:07 2018 +0100 + + S390: Remove s390 specific implementation of bcopy. + + Nowadays gcc is automatically replacing a call to bcopy + with a call to memmove. Thus only old binaries will call + the s390 specific bcopy implementation. + + The s390 specific implementation is using an own + implementation for memcpy in the forward case and is + relying on memmove in the backward case. + + After removing the s390 specific bcopy, the common code + bcopy is used. It just performs a tail call to memmove. + + ChangeLog: + * sysdeps/s390/s390-32/bcopy.S: Remove. + * sysdeps/s390/s390-64/bcopy.S: Likewise. + +diff --git a/sysdeps/s390/s390-32/bcopy.S b/sysdeps/s390/s390-32/bcopy.S +deleted file mode 100644 +index 560e04fdee93dafb..0000000000000000 +--- a/sysdeps/s390/s390-32/bcopy.S ++++ /dev/null +@@ -1,85 +0,0 @@ +-/* bcopy -- copy a block from source to destination. S/390 version. +- This file is part of the GNU C Library. +- Copyright (C) 2000-2018 Free Software Foundation, Inc. +- Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). +- +- 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 +- . */ +- +-/* INPUT PARAMETERS +- %r2 = address of source +- %r3 = address of destination +- %r4 = number of bytes to copy. */ +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +- .text +-ENTRY(__bcopy) +- ltr %r1,%r4 # zero bcopy ? +- jz .L4 +- clr %r2,%r3 # check against destructive overlap +- jnl .L0 +- alr %r1,%r2 +- clr %r1,%r3 +- jh .L7 +-.L0: ahi %r4,-1 # length - 1 +- lr %r1,%r4 +- srl %r1,8 +- ltr %r1,%r1 # < 256 bytes to move ? +- jz .L2 +- chi %r1,255 # > 1MB to move ? +- jh .L5 +-.L1: mvc 0(256,%r3),0(%r2) # move in 256 byte chunks +- la %r2,256(%r2) +- la %r3,256(%r3) +- brct %r1,.L1 +-.L2: bras %r1,.L3 # setup base pointer for execute +- mvc 0(1,%r3),0(%r2) # instruction for execute +-.L3: ex %r4,0(%r1) # execute mvc with length ((%r4)&255)+1 +-.L4: br %r14 +- +- # data copies > 1MB are faster with mvcle. +-.L5: ahi %r4,1 # length + 1 +- lr %r5,%r4 # source length +- lr %r4,%r2 # source address +- lr %r2,%r3 # set destination +- lr %r3,%r5 # destination length = source length +-.L6: mvcle %r2,%r4,0 # thats it, MVCLE is your friend +- jo .L6 +- br %r14 +-.L7: # destructive overlay, can not use mvcle +- lr %r1,%r2 # bcopy is called with source,dest +- lr %r2,%r3 # memmove with dest,source! Oh, well... +- lr %r3,%r1 +- basr %r1,0 +-.L8: +-#ifdef PIC +- al %r1,.L9-.L8(%r1) # get address of global offset table +- # load address of memmove +- l %r1,memmove@GOT(%r1) +- br %r1 +-.L9: .long _GLOBAL_OFFSET_TABLE_-.L8 +-#else +- al %r1,.L9-.L8(%r1) # load address of memmove +- br %r1 # jump to memmove +-.L9: .long memmove-.L8 +-#endif +- +-END(__bcopy) +- +-#ifndef NO_WEAK_ALIAS +-weak_alias (__bcopy, bcopy) +-#endif +- +diff --git a/sysdeps/s390/s390-64/bcopy.S b/sysdeps/s390/s390-64/bcopy.S +deleted file mode 100644 +index 806dd15d0203d32a..0000000000000000 +--- a/sysdeps/s390/s390-64/bcopy.S ++++ /dev/null +@@ -1,71 +0,0 @@ +-/* bcopy -- copy a block from source to destination. 64 bit S/390 version. +- This file is part of the GNU C Library. +- Copyright (C) 2000-2018 Free Software Foundation, Inc. +- Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). +- +- 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 +- . */ +- +-/* INPUT PARAMETERS +- %r2 = address of source +- %r3 = address of destination +- %r4 = number of bytes to copy. */ +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +- .text +-ENTRY(__bcopy) +- ltgr %r1,%r4 # zero bcopy ? +- jz .L4 +- clgr %r2,%r3 # check against destructive overlap +- jnl .L0 +- algr %r1,%r2 +- clgr %r1,%r3 +- jh .L7 +-.L0: aghi %r4,-1 # length - 1 +- srlg %r1,%r4,8 +- ltgr %r1,%r1 # < 256 bytes to move ? +- jz .L2 +- cghi %r1,255 # > 1MB to move ? +- jh .L5 +-.L1: mvc 0(256,%r3),0(%r2) # move in 256 byte chunks +- la %r2,256(%r2) +- la %r3,256(%r3) +- brctg %r1,.L1 +-.L2: bras %r1,.L3 # setup base pointer for execute +- mvc 0(1,%r3),0(%r2) # instruction for execute +-.L3: ex %r4,0(%r1) # execute mvc with length ((%r4)&255)+1 +-.L4: br %r14 +- # data copies > 1MB are faster with mvcle. +-.L5: aghi %r4,1 # length + 1 +- lgr %r5,%r4 # source length +- lgr %r4,%r2 # source address +- lgr %r2,%r3 # set destination +- lgr %r3,%r5 # destination length = source length +-.L6: mvcle %r2,%r4,0 # thats it, MVCLE is your friend +- jo .L6 +- br %r14 +-.L7: # destructive overlay, can not use mvcle +- lgr %r1,%r2 # bcopy is called with source,dest +- lgr %r2,%r3 # memmove with dest,source! Oh, well... +- lgr %r3,%r1 +- jg HIDDEN_BUILTIN_JUMPTARGET(memmove) +- +-END(__bcopy) +- +-#ifndef NO_WEAK_ALIAS +-weak_alias (__bcopy, bcopy) +-#endif +- diff --git a/glibc-rh1659438-11.patch b/glibc-rh1659438-11.patch new file mode 100755 index 0000000..71d20a3 --- /dev/null +++ b/glibc-rh1659438-11.patch @@ -0,0 +1,43 @@ +commit d097d97626e44bc6e76d5daf80ce3ff7d147b623 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:07 2018 +0100 + + S390: Use memcpy for forward cases in memmove. + + The s390/s390x memcpy implementations are safe to be + used by memmove. Starting with this commit, memmove is + using memcpy for the forward cases on s390. + + ChangeLog: + + * sysdeps/s390/memcopy.h: New file. + +diff --git a/sysdeps/s390/memcopy.h b/sysdeps/s390/memcopy.h +new file mode 100644 +index 0000000000000000..9a76196502f25bbf +--- /dev/null ++++ b/sysdeps/s390/memcopy.h +@@ -0,0 +1,23 @@ ++/* memcopy.h -- definitions for memory copy functions. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++ ++/* The s390/s390x memcpy implementations are safe to be used by memmove. */ ++#undef MEMCPY_OK_FOR_FWD_MEMMOVE ++#define MEMCPY_OK_FOR_FWD_MEMMOVE 1 diff --git a/glibc-rh1659438-12.patch b/glibc-rh1659438-12.patch new file mode 100755 index 0000000..e257c4e --- /dev/null +++ b/glibc-rh1659438-12.patch @@ -0,0 +1,114 @@ +commit 2ee1bc57ab50737ee2ab88c4d796b90e08b4bf93 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:08 2018 +0100 + + S390: Add configure check to detect z13 as mininum architecture level set. + + Add a configure check for z13 in the same way as done for z196. + + ChangeLog: + + * config.h.in (HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT): New undefine. + * sysdeps/s390/configure.ac: Add check for z13 support. + * sysdeps/s390/configure: Regenerated. + +diff --git a/config.h.in b/config.h.in +index beecc39d5b8c3f4a..422a6036ab16e3b6 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -68,6 +68,9 @@ + /* Define if assembler supports z196 zarch instructions as default on S390. */ + #undef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT + ++/* Define if assembler supports z13 zarch instructions as default on S390. */ ++#undef HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++ + /* Define if assembler supports vector instructions on S390. */ + #undef HAVE_S390_VX_ASM_SUPPORT + +diff --git a/sysdeps/s390/configure b/sysdeps/s390/configure +index f30f8644361f474a..4a44775e3083d8c3 100644 +--- a/sysdeps/s390/configure ++++ b/sysdeps/s390/configure +@@ -187,5 +187,43 @@ then + + fi + ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 z13 zarch instruction support as default" >&5 ++$as_echo_n "checking for S390 z13 zarch instruction support as default... " >&6; } ++if ${libc_cv_asm_s390_min_z13_zarch+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat > conftest.c <<\EOF ++int testinsn (void) ++{ ++ int i; ++ __asm__ ("vl %%v16,0(%%r15)\n\t" ++ "vlgvf %0,%%v16,0" ++ : "=d" (i) : : "memory", "v16"); ++ return i; ++} ++EOF ++if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c ++ -o conftest.o &> /dev/null' ++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } ; ++then ++ libc_cv_asm_s390_min_z13_zarch=yes ++else ++ libc_cv_asm_s390_min_z13_zarch=no ++fi ++rm -f conftest* ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_s390_min_z13_zarch" >&5 ++$as_echo "$libc_cv_asm_s390_min_z13_zarch" >&6; } ++ ++if test "$libc_cv_asm_s390_min_z13_zarch" = yes ; ++then ++ $as_echo "#define HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT 1" >>confdefs.h ++ ++fi ++ + test -n "$critic_missing" && as_fn_error $? " + *** $critic_missing" "$LINENO" 5 +diff --git a/sysdeps/s390/configure.ac b/sysdeps/s390/configure.ac +index 981f7a79dd7066fc..4dfb5574b49d5949 100644 +--- a/sysdeps/s390/configure.ac ++++ b/sysdeps/s390/configure.ac +@@ -135,5 +135,33 @@ then + AC_DEFINE(HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT) + fi + ++AC_CACHE_CHECK(for S390 z13 zarch instruction support as default, ++ libc_cv_asm_s390_min_z13_zarch, [dnl ++cat > conftest.c <<\EOF ++int testinsn (void) ++{ ++ int i; ++ __asm__ ("vl %%v16,0(%%r15)\n\t" ++ "vlgvf %0,%%v16,0" ++ : "=d" (i) : : "memory", "v16"); ++ return i; ++} ++EOF ++dnl ++dnl test, if assembler supports S390 z13 zarch instructions as default ++if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c ++ -o conftest.o &> /dev/null]) ; ++then ++ libc_cv_asm_s390_min_z13_zarch=yes ++else ++ libc_cv_asm_s390_min_z13_zarch=no ++fi ++rm -f conftest* ]) ++ ++if test "$libc_cv_asm_s390_min_z13_zarch" = yes ; ++then ++ AC_DEFINE(HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT) ++fi ++ + test -n "$critic_missing" && AC_MSG_ERROR([ + *** $critic_missing]) diff --git a/glibc-rh1659438-13.patch b/glibc-rh1659438-13.patch new file mode 100755 index 0000000..4f8aa88 --- /dev/null +++ b/glibc-rh1659438-13.patch @@ -0,0 +1,327 @@ +commit cdd927d98cc38acf55e1c6594b5c9451df8f239f +Author: Stefan Liebler +Date: Tue Dec 18 13:57:08 2018 +0100 + + S390: Add z13 memmove ifunc variant. + + This patch introduces a z13 specific ifunc variant for memmove. + As the common code implementation, it checks if we can copy from + the beginning to the end - with z196 memcpy implementation - or + if we have to copy from the end to the beginning. + The latter case is done by using vector load/store instructions. + + If vector instructions are not available, the common-code is + used as fallback. Therefore it is implemented in memmove-c with + a different name. + Furthermore the ifunc logic decides if we need the common-code + implementation at all. If vector instructions are supported + due to the minimum architecture level set we can skip the + common-code ifunc variant. + + ChangeLog: + + * sysdeps/s390/Makefile (sysdep_routines): Add memmove-c. + * sysdeps/s390/ifunc-memcpy.h (HAVE_MEMMOVE_IFUNC, + HAVE_MEMMOVE_IFUNC_AND_VX_SUPPORT, MEMMOVE_DEFAULT, + HAVE_MEMMOVE_C, MEMMOVE_C, HAVE_MEMMOVE_Z13, MEMMOVE_Z13): + New defines. + * sysdeps/s390/memcpy-z900.S: Add z13 memmove implementation. + * sysdeps/s390/memmove-c.c: New file. + * sysdeps/s390/memmove.c: Likewise. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Add ifunc variants for memmove. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 838950a5ab958e31..3a7cccdf8f147398 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -33,5 +33,6 @@ endif + ifeq ($(subdir),string) + sysdep_routines += bzero memset memset-z900 \ + memcmp memcmp-z900 \ +- mempcpy memcpy memcpy-z900 ++ mempcpy memcpy memcpy-z900 \ ++ memmove memmove-c + endif +diff --git a/sysdeps/s390/ifunc-memcpy.h b/sysdeps/s390/ifunc-memcpy.h +index 51c71baa2c0b0452..0e701968c8f39014 100644 +--- a/sysdeps/s390/ifunc-memcpy.h ++++ b/sysdeps/s390/ifunc-memcpy.h +@@ -43,6 +43,29 @@ + # define HAVE_MEMCPY_Z196 HAVE_MEMCPY_IFUNC + #endif + ++#if defined SHARED && defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_MEMMOVE_IFUNC 1 ++#else ++# define HAVE_MEMMOVE_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_MEMMOVE_IFUNC_AND_VX_SUPPORT HAVE_MEMMOVE_IFUNC ++#else ++# define HAVE_MEMMOVE_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define MEMMOVE_DEFAULT MEMMOVE_Z13 ++# define HAVE_MEMMOVE_C 0 ++# define HAVE_MEMMOVE_Z13 1 ++#else ++# define MEMMOVE_DEFAULT MEMMOVE_C ++# define HAVE_MEMMOVE_C 1 ++# define HAVE_MEMMOVE_Z13 HAVE_MEMMOVE_IFUNC_AND_VX_SUPPORT ++#endif ++ + #if HAVE_MEMCPY_Z900_G5 + # define MEMCPY_Z900_G5 __memcpy_default + # define MEMPCPY_Z900_G5 __mempcpy_default +@@ -66,3 +89,15 @@ + # define MEMCPY_Z196 NULL + # define MEMPCPY_Z196 NULL + #endif ++ ++#if HAVE_MEMMOVE_C ++# define MEMMOVE_C __memmove_c ++#else ++# define MEMMOVE_C NULL ++#endif ++ ++#if HAVE_MEMMOVE_Z13 ++# define MEMMOVE_Z13 __memmove_z13 ++#else ++# define MEMMOVE_Z13 NULL ++#endif +diff --git a/sysdeps/s390/memcpy-z900.S b/sysdeps/s390/memcpy-z900.S +index 3a50cf44d85d2417..bd3b1950ee442c0c 100644 +--- a/sysdeps/s390/memcpy-z900.S ++++ b/sysdeps/s390/memcpy-z900.S +@@ -182,6 +182,7 @@ ENTRY(MEMCPY_Z196) + # endif /* !defined __s390x__ */ + ltgr %r4,%r4 + je .L_Z196_4 ++.L_Z196_start2: + aghi %r4,-1 + srlg %r5,%r4,8 + ltgr %r5,%r5 +@@ -207,6 +208,75 @@ ENTRY(MEMCPY_Z196) + END(MEMCPY_Z196) + #endif /* HAVE_MEMCPY_Z196 */ + ++#if HAVE_MEMMOVE_Z13 ++ENTRY(MEMMOVE_Z13) ++ .machine "z13" ++ .machinemode "zarch_nohighgprs" ++# if !defined __s390x__ ++ /* Note: The 31bit dst and src pointers are prefixed with zeroes. */ ++ llgfr %r4,%r4 ++ llgfr %r3,%r3 ++ llgfr %r2,%r2 ++# endif /* !defined __s390x__ */ ++ sgrk %r0,%r2,%r3 ++ clgijh %r4,16,.L_MEMMOVE_Z13_LARGE ++ aghik %r5,%r4,-1 ++.L_MEMMOVE_Z13_SMALL: ++ jl .L_MEMMOVE_Z13_END /* Jump away if len was zero. */ ++ /* Store up to 16 bytes with vll/vstl which needs the index ++ instead of lengths. */ ++ vll %v16,%r5,0(%r3) ++ vstl %v16,%r5,0(%r2) ++.L_MEMMOVE_Z13_END: ++ br %r14 ++.L_MEMMOVE_Z13_LARGE: ++ lgr %r1,%r2 /* For memcpy: r1: Use as dest ; ++ r2: Return dest */ ++ /* The unsigned comparison (dst - src >= len) determines if we can ++ execute the forward case with memcpy. */ ++#if ! HAVE_MEMCPY_Z196 ++# error The z13 variant of memmove needs the z196 variant of memcpy! ++#endif ++ clgrjhe %r0,%r4,.L_Z196_start2 ++ risbgn %r5,%r4,4,128+63,60 /* r5 = r4 / 16 */ ++ aghi %r4,-16 ++ clgijhe %r5,8,.L_MEMMOVE_Z13_LARGE_64B ++.L_MEMMOVE_Z13_LARGE_16B_LOOP: ++ /* Store at least 16 bytes with vl/vst. The number of 16byte blocks ++ is stored in r5. */ ++ vl %v16,0(%r4,%r3) ++ vst %v16,0(%r4,%r2) ++ aghi %r4,-16 ++ brctg %r5,.L_MEMMOVE_Z13_LARGE_16B_LOOP ++ aghik %r5,%r4,15 ++ j .L_MEMMOVE_Z13_SMALL ++.L_MEMMOVE_Z13_LARGE_64B: ++ /* Store at least 128 bytes with 4x vl/vst. The number of 64byte blocks ++ will be stored in r0. */ ++ aghi %r4,-48 ++ srlg %r0,%r5,2 /* r5 = %r0 / 4 ++ => Number of 64byte blocks. */ ++.L_MEMMOVE_Z13_LARGE_64B_LOOP: ++ vl %v20,48(%r4,%r3) ++ vl %v19,32(%r4,%r3) ++ vl %v18,16(%r4,%r3) ++ vl %v17,0(%r4,%r3) ++ vst %v20,48(%r4,%r2) ++ vst %v19,32(%r4,%r2) ++ vst %v18,16(%r4,%r2) ++ vst %v17,0(%r4,%r2) ++ aghi %r4,-64 ++ brctg %r0,.L_MEMMOVE_Z13_LARGE_64B_LOOP ++ aghi %r4,48 ++ /* Recalculate the number of 16byte blocks. */ ++ risbg %r5,%r5,62,128+63,0 /* r5 = r5 & 3 ++ => Remaining 16byte blocks. */ ++ jne .L_MEMMOVE_Z13_LARGE_16B_LOOP ++ aghik %r5,%r4,15 ++ j .L_MEMMOVE_Z13_SMALL ++END(MEMMOVE_Z13) ++#endif /* HAVE_MEMMOVE_Z13 */ ++ + #if ! HAVE_MEMCPY_IFUNC + /* If we don't use ifunc, define an alias for mem[p]cpy here. + Otherwise see sysdeps/s390/mem[p]cpy.c. */ +@@ -215,10 +285,27 @@ strong_alias (MEMPCPY_DEFAULT, __mempcpy) + weak_alias (__mempcpy, mempcpy) + #endif + ++#if ! HAVE_MEMMOVE_IFUNC ++/* If we don't use ifunc, define an alias for memmove here. ++ Otherwise see sysdeps/s390/memmove.c. */ ++# if ! HAVE_MEMMOVE_C ++/* If the c variant is needed, then sysdeps/s390/memmove-c.c ++ defines memmove. ++ Otherwise MEMMOVE_DEFAULT is implemented here and we have to define it. */ ++strong_alias (MEMMOVE_DEFAULT, memmove) ++# endif ++#endif ++ + #if defined SHARED && IS_IN (libc) + /* Defines the internal symbols. + Compare to libc_hidden_[builtin_]def (mem[p]cpy) in string/mem[p]cpy.c. */ + strong_alias (MEMCPY_DEFAULT, __GI_memcpy) + strong_alias (MEMPCPY_DEFAULT, __GI_mempcpy) + strong_alias (MEMPCPY_DEFAULT, __GI___mempcpy) ++# if ! HAVE_MEMMOVE_C ++/* If the c variant is needed, then sysdeps/s390/memmove-c.c ++ defines the internal symbol. ++ Otherwise MEMMOVE_DEFAULT is implemented here and we have to define it. */ ++strong_alias (MEMMOVE_DEFAULT, __GI_memmove) ++# endif + #endif +diff --git a/sysdeps/s390/memmove-c.c b/sysdeps/s390/memmove-c.c +new file mode 100644 +index 0000000000000000..be571093e019a38d +--- /dev/null ++++ b/sysdeps/s390/memmove-c.c +@@ -0,0 +1,37 @@ ++/* Fallback C version of memmove. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++ ++#if HAVE_MEMMOVE_C ++# if HAVE_MEMMOVE_IFUNC ++/* If we use ifunc, then the memmove symbol is defined ++ in sysdeps/s390/memmove.c and we use a different name here. ++ Otherwise, we have to define memmove here or in ++ sysdeps/s390/memcpy.S depending on the used default implementation. */ ++# define MEMMOVE MEMMOVE_C ++# if defined SHARED && IS_IN (libc) ++/* Define the internal symbol. */ ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) \ ++ __hidden_ver1 (__memmove_c, __GI_memmove, __memmove_c); ++# endif ++# endif ++ ++# include ++#endif +diff --git a/sysdeps/s390/memmove.c b/sysdeps/s390/memmove.c +new file mode 100644 +index 0000000000000000..ac34edf80f2678cd +--- /dev/null ++++ b/sysdeps/s390/memmove.c +@@ -0,0 +1,44 @@ ++/* Multiple versions of memmove. ++ Copyright (C) 2016-2018 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 ++ . */ ++ ++#include ++ ++#if HAVE_MEMMOVE_IFUNC ++/* If we don't use ifunc, an alias is defined for memmove ++ in sysdeps/s390/memmove-c.c or sysdeps/s390/memcpy.S ++ depending on the used default implementation. */ ++# undef memmove ++# define memmove __redirect_memmove ++# include ++# include ++# undef memmove ++ ++# if HAVE_MEMMOVE_C ++extern __typeof (__redirect_memmove) MEMMOVE_C attribute_hidden; ++# endif ++ ++# if HAVE_MEMMOVE_Z13 ++extern __typeof (__redirect_memmove) MEMMOVE_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect_memmove, memmove, ++ (HAVE_MEMMOVE_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? MEMMOVE_Z13 ++ : MEMMOVE_DEFAULT ++ ) ++#endif +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 6969c480cc40e0e2..c05c63e00608dcd7 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -126,6 +126,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_MEMCPY_IFUNC */ + ++#if HAVE_MEMMOVE_IFUNC ++ IFUNC_IMPL (i, name, memmove, ++# if HAVE_MEMMOVE_Z13 ++ IFUNC_IMPL_ADD (array, i, memmove, ++ dl_hwcap & HWCAP_S390_VX, MEMMOVE_Z13) ++# endif ++# if HAVE_MEMMOVE_C ++ IFUNC_IMPL_ADD (array, i, memmove, 1, MEMMOVE_C) ++# endif ++ ) ++#endif /* HAVE_MEMMOVE_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ diff --git a/glibc-rh1659438-14.patch b/glibc-rh1659438-14.patch new file mode 100755 index 0000000..7209f89 --- /dev/null +++ b/glibc-rh1659438-14.patch @@ -0,0 +1,263 @@ +commit 8c25dddd2e32bce47dfe01ca51c8aab535dbe23d +Author: Stefan Liebler +Date: Tue Dec 18 13:57:09 2018 +0100 + + S390: Add z13 strstr ifunc variant. + + The new vector variant of strstr is using the common code + implementation, but instead of calling the default + str* / mem* functions, the vector variants are called. + + ChangeLog: + + * sysdeps/s390/Makefile (sysdep_routines): Add strstr variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Add ifunc variants for strstr. + * sysdeps/s390/ifunc-strstr.h: New file. + * sysdeps/s390/strstr.c: Likewise. + * sysdeps/s390/strstr-c.c: Likewise. + * sysdeps/s390/strstr-vx.c: Likewise. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 3a7cccdf8f147398..4441e7a5cf6fa167 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -34,5 +34,6 @@ ifeq ($(subdir),string) + sysdep_routines += bzero memset memset-z900 \ + memcmp memcmp-z900 \ + mempcpy memcpy memcpy-z900 \ +- memmove memmove-c ++ memmove memmove-c \ ++ strstr strstr-vx strstr-c + endif +diff --git a/sysdeps/s390/ifunc-strstr.h b/sysdeps/s390/ifunc-strstr.h +new file mode 100644 +index 0000000000000000..e6ccfd4e44a1a790 +--- /dev/null ++++ b/sysdeps/s390/ifunc-strstr.h +@@ -0,0 +1,52 @@ ++/* strstr variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRSTR_IFUNC 1 ++#else ++# define HAVE_STRSTR_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRSTR_IFUNC_AND_VX_SUPPORT HAVE_STRSTR_IFUNC ++#else ++# define HAVE_STRSTR_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRSTR_DEFAULT STRSTR_Z13 ++# define HAVE_STRSTR_C 0 ++# define HAVE_STRSTR_Z13 1 ++#else ++# define STRSTR_DEFAULT STRSTR_C ++# define HAVE_STRSTR_C 1 ++# define HAVE_STRSTR_Z13 HAVE_STRSTR_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRSTR_C ++# define STRSTR_C __strstr_c ++#else ++# define STRSTR_C NULL ++#endif ++ ++#if HAVE_STRSTR_Z13 ++# define STRSTR_Z13 __strstr_vx ++#else ++# define STRSTR_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index c05c63e00608dcd7..14727f8fef5431dd 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -138,6 +139,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_MEMMOVE_IFUNC */ + ++#if HAVE_STRSTR_IFUNC ++ IFUNC_IMPL (i, name, strstr, ++# if HAVE_STRSTR_Z13 ++ IFUNC_IMPL_ADD (array, i, strstr, ++ dl_hwcap & HWCAP_S390_VX, STRSTR_Z13) ++# endif ++# if HAVE_STRSTR_C ++ IFUNC_IMPL_ADD (array, i, strstr, 1, STRSTR_C) ++# endif ++ ) ++#endif /* HAVE_STRSTR_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +diff --git a/sysdeps/s390/strstr-c.c b/sysdeps/s390/strstr-c.c +new file mode 100644 +index 0000000000000000..53717bfb276fed3d +--- /dev/null ++++ b/sysdeps/s390/strstr-c.c +@@ -0,0 +1,32 @@ ++/* Default strstr implementation for S/390. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++ ++#if HAVE_STRSTR_C ++# if HAVE_STRSTR_IFUNC ++# define STRSTR STRSTR_C ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) \ ++ __hidden_ver1 (__strstr_c, __GI_strstr, __strstr_c); ++# endif ++# endif ++ ++# include ++#endif +diff --git a/sysdeps/s390/strstr-vx.c b/sysdeps/s390/strstr-vx.c +new file mode 100644 +index 0000000000000000..effae9d5eb7d2fb1 +--- /dev/null ++++ b/sysdeps/s390/strstr-vx.c +@@ -0,0 +1,52 @@ ++/* Default strstr implementation with vector string functions for S/390. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++ ++#if HAVE_STRSTR_Z13 ++# if HAVE_STRSTR_IFUNC ++# define STRSTR STRSTR_Z13 ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_builtin_def ++# if HAVE_STRSTR_C ++# define libc_hidden_builtin_def(name) ++# else ++# define libc_hidden_builtin_def(name) \ ++ __hidden_ver1 (__strstr_vx, __GI_strstr, __strstr_vx); ++# endif ++# endif ++# endif ++ ++# include ++ ++# ifdef USE_MULTIARCH ++extern __typeof (strchr) __strchr_vx attribute_hidden; ++# define strchr __strchr_vx ++ ++extern __typeof (strlen) __strlen_vx attribute_hidden; ++# define strlen __strlen_vx ++ ++extern __typeof (__strnlen) __strnlen_vx attribute_hidden; ++# define __strnlen __strnlen_vx ++ ++extern __typeof (memcmp) __memcmp_z196 attribute_hidden; ++# define memcmp __memcmp_z196 ++# endif ++ ++# include ++#endif +diff --git a/sysdeps/s390/strstr.c b/sysdeps/s390/strstr.c +new file mode 100644 +index 0000000000000000..f8432349a7254cc6 +--- /dev/null ++++ b/sysdeps/s390/strstr.c +@@ -0,0 +1,40 @@ ++/* Multiple versions of strstr. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++ ++#if HAVE_STRSTR_IFUNC ++# define strstr __redirect_strstr ++# include ++# include ++# undef strstr ++ ++# if HAVE_STRSTR_C ++extern __typeof (__redirect_strstr) STRSTR_C attribute_hidden; ++# endif ++ ++# if HAVE_STRSTR_Z13 ++extern __typeof (__redirect_strstr) STRSTR_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect_strstr, strstr, ++ (HAVE_STRSTR_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRSTR_Z13 ++ : STRSTR_DEFAULT ++ ) ++#endif diff --git a/glibc-rh1659438-15.patch b/glibc-rh1659438-15.patch new file mode 100755 index 0000000..0cb1dbe --- /dev/null +++ b/glibc-rh1659438-15.patch @@ -0,0 +1,290 @@ +commit d2c4c403feddd6f0b9dbf31ca7541b37f90ee30a +Author: Stefan Liebler +Date: Tue Dec 18 13:57:09 2018 +0100 + + S390: Add z13 memmem ifunc variant. + + The new vector variant of memmem is using the common code + implementation, but instead of calling the default + mem* functions, the vector variants are called. + + ChangeLog: + + * sysdeps/s390/Makefile (sysdep_routines): Add memmem variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Add ifunc variants for memmem. + * sysdeps/s390/ifunc-memmem.h: New file. + * sysdeps/s390/memmem.c: Likewise. + * sysdeps/s390/memmem-c.c: Likewise. + * sysdeps/s390/memmem-vx.c: Likewise. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 4441e7a5cf6fa167..47d606d3d5d99274 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -35,5 +35,6 @@ sysdep_routines += bzero memset memset-z900 \ + memcmp memcmp-z900 \ + mempcpy memcpy memcpy-z900 \ + memmove memmove-c \ +- strstr strstr-vx strstr-c ++ strstr strstr-vx strstr-c \ ++ memmem memmem-vx memmem-c + endif +diff --git a/sysdeps/s390/ifunc-memmem.h b/sysdeps/s390/ifunc-memmem.h +new file mode 100644 +index 0000000000000000..0f860d8d40080acf +--- /dev/null ++++ b/sysdeps/s390/ifunc-memmem.h +@@ -0,0 +1,52 @@ ++/* memmem variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_MEMMEM_IFUNC 1 ++#else ++# define HAVE_MEMMEM_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_MEMMEM_IFUNC_AND_VX_SUPPORT HAVE_MEMMEM_IFUNC ++#else ++# define HAVE_MEMMEM_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define MEMMEM_DEFAULT MEMMEM_Z13 ++# define HAVE_MEMMEM_C 0 ++# define HAVE_MEMMEM_Z13 1 ++#else ++# define MEMMEM_DEFAULT MEMMEM_C ++# define HAVE_MEMMEM_C 1 ++# define HAVE_MEMMEM_Z13 HAVE_MEMMEM_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_MEMMEM_C ++# define MEMMEM_C __memmem_c ++#else ++# define MEMMEM_C NULL ++#endif ++ ++#if HAVE_MEMMEM_Z13 ++# define MEMMEM_Z13 __memmem_vx ++#else ++# define MEMMEM_Z13 NULL ++#endif +diff --git a/sysdeps/s390/memmem-c.c b/sysdeps/s390/memmem-c.c +new file mode 100644 +index 0000000000000000..1d8ffefcb840b8d2 +--- /dev/null ++++ b/sysdeps/s390/memmem-c.c +@@ -0,0 +1,47 @@ ++/* Default memmem implementation for S/390. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++ ++#if HAVE_MEMMEM_C ++# if HAVE_MEMMEM_IFUNC ++# include ++ ++# ifndef _LIBC ++# define memmem MEMMEM_C ++# else ++# define __memmem MEMMEM_C ++# endif ++ ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_def ++# define libc_hidden_def(name) \ ++ strong_alias (__memmem_c, __memmem_c_1); \ ++ __hidden_ver1 (__memmem_c, __GI___memmem, __memmem_c); ++ ++# undef libc_hidden_weak ++# define libc_hidden_weak(name) \ ++ __hidden_ver1 (__memmem_c_1, __GI_memmem, __memmem_c_1) __attribute__((weak)); ++# endif ++ ++# undef weak_alias ++# define weak_alias(a, b) ++# endif ++ ++# include ++#endif +diff --git a/sysdeps/s390/memmem-vx.c b/sysdeps/s390/memmem-vx.c +new file mode 100644 +index 0000000000000000..af6e200e4e0af1a5 +--- /dev/null ++++ b/sysdeps/s390/memmem-vx.c +@@ -0,0 +1,61 @@ ++/* Default memmem implementation with vector string functions for S/390. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++ ++#if HAVE_MEMMEM_Z13 ++# include ++# if HAVE_MEMMEM_IFUNC ++ ++# ifndef _LIBC ++# define memmem MEMMEM_Z13 ++# else ++# define __memmem MEMMEM_Z13 ++# endif ++ ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_def ++# undef libc_hidden_weak ++ ++# if HAVE_MEMMEM_C ++# define libc_hidden_def(name) ++# define libc_hidden_weak(name) ++# else ++# define libc_hidden_def(name) \ ++ strong_alias (__memmem_vx, __memmem_vx_1); \ ++ __hidden_ver1 (__memmem_vx, __GI___memmem, __memmem_vx); ++ ++# define libc_hidden_weak(name) \ ++ __hidden_ver1 (__memmem_vx_1, __GI_memmem, __memmem_vx_1) __attribute__((weak)); ++# endif ++# endif ++ ++# undef weak_alias ++# define weak_alias(a, b) ++# endif ++ ++# ifdef USE_MULTIARCH ++extern __typeof (memchr) __memchr_vx attribute_hidden; ++# define memchr __memchr_vx ++ ++extern __typeof (memcmp) __memcmp_z196 attribute_hidden; ++# define memcmp __memcmp_z196 ++# endif ++ ++# include ++#endif +diff --git a/sysdeps/s390/memmem.c b/sysdeps/s390/memmem.c +new file mode 100644 +index 0000000000000000..8c50b3f403eb8d1f +--- /dev/null ++++ b/sysdeps/s390/memmem.c +@@ -0,0 +1,43 @@ ++/* Multiple versions of memmem. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++ ++#if HAVE_MEMMEM_IFUNC ++# define memmem __redirect_memmem ++# define __memmem __redirect___memmem ++# include ++# include ++# undef memmem ++# undef __memmem ++ ++# if HAVE_MEMMEM_C ++extern __typeof (__redirect_memmem) MEMMEM_C attribute_hidden; ++# endif ++ ++# if HAVE_MEMMEM_Z13 ++extern __typeof (__redirect_memmem) MEMMEM_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect_memmem, __memmem, ++ (HAVE_MEMMEM_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? MEMMEM_Z13 ++ : MEMMEM_DEFAULT ++ ) ++weak_alias (__memmem, memmem) ++#endif +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 14727f8fef5431dd..da8696d917abf51c 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -151,6 +152,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRSTR_IFUNC */ + ++#if HAVE_MEMMEM_IFUNC ++ IFUNC_IMPL (i, name, memmem, ++# if HAVE_MEMMEM_Z13 ++ IFUNC_IMPL_ADD (array, i, memmem, ++ dl_hwcap & HWCAP_S390_VX, MEMMEM_Z13) ++# endif ++# if HAVE_MEMMEM_C ++ IFUNC_IMPL_ADD (array, i, memmem, 1, MEMMEM_C) ++# endif ++ ) ++#endif /* HAVE_MEMMEM_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ diff --git a/glibc-rh1659438-16.patch b/glibc-rh1659438-16.patch new file mode 100755 index 0000000..b55bebc --- /dev/null +++ b/glibc-rh1659438-16.patch @@ -0,0 +1,259 @@ +commit ff3ca3743a00af749258cc242457b648d65a1537 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:10 2018 +0100 + + S390: Refactor strlen ifunc handling. + + The ifunc handling for strlen is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strlen variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strlen variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strlen. + * sysdeps/s390/multiarch/strlen-c.c: Move to ... + * sysdeps/s390/strlen-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strlen-vx.S: Move to ... + * sysdeps/s390/strlen-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strlen.c: Move to ... + * sysdeps/s390/strlen.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strlen.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 47d606d3d5d99274..600d8e629df7090e 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -36,5 +36,6 @@ sysdep_routines += bzero memset memset-z900 \ + mempcpy memcpy memcpy-z900 \ + memmove memmove-c \ + strstr strstr-vx strstr-c \ +- memmem memmem-vx memmem-c ++ memmem memmem-vx memmem-c \ ++ strlen strlen-vx strlen-c + endif +diff --git a/sysdeps/s390/ifunc-strlen.h b/sysdeps/s390/ifunc-strlen.h +new file mode 100644 +index 0000000000000000..f2070596636f29a9 +--- /dev/null ++++ b/sysdeps/s390/ifunc-strlen.h +@@ -0,0 +1,52 @@ ++/* strlen variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRLEN_IFUNC 1 ++#else ++# define HAVE_STRLEN_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRLEN_IFUNC_AND_VX_SUPPORT HAVE_STRLEN_IFUNC ++#else ++# define HAVE_STRLEN_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRLEN_DEFAULT STRLEN_Z13 ++# define HAVE_STRLEN_C 0 ++# define HAVE_STRLEN_Z13 1 ++#else ++# define STRLEN_DEFAULT STRLEN_C ++# define HAVE_STRLEN_C 1 ++# define HAVE_STRLEN_Z13 HAVE_STRLEN_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRLEN_C ++# define STRLEN_C __strlen_c ++#else ++# define STRLEN_C NULL ++#endif ++ ++#if HAVE_STRLEN_Z13 ++# define STRLEN_Z13 __strlen_vx ++#else ++# define STRLEN_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 24949cd3a88b8015..601523919c235f76 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strlen strlen-vx strlen-c \ +- strnlen strnlen-vx strnlen-c \ ++sysdep_routines += strnlen strnlen-vx strnlen-c \ + strcpy strcpy-vx \ + stpcpy stpcpy-vx stpcpy-c \ + strncpy strncpy-vx \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index da8696d917abf51c..c531be4bc7eb3f55 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -164,6 +165,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_MEMMEM_IFUNC */ + ++#if HAVE_STRLEN_IFUNC ++ IFUNC_IMPL (i, name, strlen, ++# if HAVE_STRLEN_Z13 ++ IFUNC_IMPL_ADD (array, i, strlen, ++ dl_hwcap & HWCAP_S390_VX, STRLEN_Z13) ++# endif ++# if HAVE_STRLEN_C ++ IFUNC_IMPL_ADD (array, i, strlen, 1, STRLEN_C) ++# endif ++ ) ++#endif /* HAVE_STRLEN_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -172,7 +185,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (strlen); + IFUNC_VX_IMPL (wcslen); + + IFUNC_VX_IMPL (strnlen); +diff --git a/sysdeps/s390/multiarch/strlen-c.c b/sysdeps/s390/strlen-c.c +similarity index 78% +rename from sysdeps/s390/multiarch/strlen-c.c +rename to sysdeps/s390/strlen-c.c +index a2c8e43624a9bc91..b4569701af96f4a9 100644 +--- a/sysdeps/s390/multiarch/strlen-c.c ++++ b/sysdeps/s390/strlen-c.c +@@ -16,13 +16,17 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define STRLEN __strlen_c +-# ifdef SHARED +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) \ ++#include ++ ++#if HAVE_STRLEN_C ++# if HAVE_STRLEN_IFUNC ++# define STRLEN STRLEN_C ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) \ + __hidden_ver1 (__strlen_c, __GI_strlen, __strlen_c); +-# endif /* SHARED */ ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/strlen-vx.S b/sysdeps/s390/strlen-vx.S +similarity index 90% +rename from sysdeps/s390/multiarch/strlen-vx.S +rename to sysdeps/s390/strlen-vx.S +index 9308b332371dcdaa..39ef43107d11ec73 100644 +--- a/sysdeps/s390/multiarch/strlen-vx.S ++++ b/sysdeps/s390/strlen-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_STRLEN_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -34,7 +35,7 @@ + -r5=current_len and return_value + -v16=part of s + */ +-ENTRY(__strlen_vx) ++ENTRY(STRLEN_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -80,5 +81,13 @@ ENTRY(__strlen_vx) + vlgvb %r2,%v16,7 /* Load byte index of zero. */ + algr %r2,%r5 + br %r14 +-END(__strlen_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(STRLEN_Z13) ++ ++# if ! HAVE_STRLEN_IFUNC ++strong_alias (STRLEN_Z13, strlen) ++# endif ++ ++# if ! HAVE_STRLEN_C && defined SHARED && IS_IN (libc) ++strong_alias (STRLEN_Z13, __GI_strlen) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/strlen.c b/sysdeps/s390/strlen.c +similarity index 69% +rename from sysdeps/s390/multiarch/strlen.c +rename to sysdeps/s390/strlen.c +index 0edf8b7d0231cf31..6ba0fe86fe9789f0 100644 +--- a/sysdeps/s390/multiarch/strlen.c ++++ b/sysdeps/s390/strlen.c +@@ -16,14 +16,25 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRLEN_IFUNC + # define strlen __redirect_strlen + # include + # include + # undef strlen + +-s390_vx_libc_ifunc2_redirected (__redirect_strlen, __strlen, strlen) ++# if HAVE_STRLEN_C ++extern __typeof (__redirect_strlen) STRLEN_C attribute_hidden; ++# endif ++ ++# if HAVE_STRLEN_Z13 ++extern __typeof (__redirect_strlen) STRLEN_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (__redirect_strlen, strlen, ++ (HAVE_STRLEN_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRLEN_Z13 ++ : STRLEN_DEFAULT ++ ) ++#endif diff --git a/glibc-rh1659438-17.patch b/glibc-rh1659438-17.patch new file mode 100755 index 0000000..da43ae2 --- /dev/null +++ b/glibc-rh1659438-17.patch @@ -0,0 +1,269 @@ +commit de10e44dda686e3ed6a7a1463869df846ea39825 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:10 2018 +0100 + + S390: Refactor strnlen ifunc handling. + + The ifunc handling for strnlen is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strnlen variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strnlen variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strnlen. + * sysdeps/s390/multiarch/strnlen-c.c: Move to ... + * sysdeps/s390/strnlen-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strnlen-vx.S: Move to ... + * sysdeps/s390/strnlen-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strnlen.c: Move to ... + * sysdeps/s390/strnlen.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strnlen.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 600d8e629df7090e..f092355743e3908f 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -37,5 +37,6 @@ sysdep_routines += bzero memset memset-z900 \ + memmove memmove-c \ + strstr strstr-vx strstr-c \ + memmem memmem-vx memmem-c \ +- strlen strlen-vx strlen-c ++ strlen strlen-vx strlen-c \ ++ strnlen strnlen-vx strnlen-c + endif +diff --git a/sysdeps/s390/ifunc-strnlen.h b/sysdeps/s390/ifunc-strnlen.h +new file mode 100644 +index 0000000000000000..e92329888773304d +--- /dev/null ++++ b/sysdeps/s390/ifunc-strnlen.h +@@ -0,0 +1,52 @@ ++/* strnlen variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRNLEN_IFUNC 1 ++#else ++# define HAVE_STRNLEN_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRNLEN_IFUNC_AND_VX_SUPPORT HAVE_STRNLEN_IFUNC ++#else ++# define HAVE_STRNLEN_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRNLEN_DEFAULT STRNLEN_Z13 ++# define HAVE_STRNLEN_C 0 ++# define HAVE_STRNLEN_Z13 1 ++#else ++# define STRNLEN_DEFAULT STRNLEN_C ++# define HAVE_STRNLEN_C 1 ++# define HAVE_STRNLEN_Z13 HAVE_STRNLEN_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRNLEN_C ++# define STRNLEN_C __strnlen_c ++#else ++# define STRNLEN_C NULL ++#endif ++ ++#if HAVE_STRNLEN_Z13 ++# define STRNLEN_Z13 __strnlen_vx ++#else ++# define STRNLEN_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 601523919c235f76..35ba223c5d4fb52f 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strnlen strnlen-vx strnlen-c \ +- strcpy strcpy-vx \ ++sysdep_routines += strcpy strcpy-vx \ + stpcpy stpcpy-vx stpcpy-c \ + strncpy strncpy-vx \ + stpncpy stpncpy-vx stpncpy-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index c531be4bc7eb3f55..680e5b738bfb7f32 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -177,6 +178,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRLEN_IFUNC */ + ++#if HAVE_STRNLEN_IFUNC ++ IFUNC_IMPL (i, name, strnlen, ++# if HAVE_STRNLEN_Z13 ++ IFUNC_IMPL_ADD (array, i, strnlen, ++ dl_hwcap & HWCAP_S390_VX, STRNLEN_Z13) ++# endif ++# if HAVE_STRNLEN_C ++ IFUNC_IMPL_ADD (array, i, strnlen, 1, STRNLEN_C) ++# endif ++ ) ++#endif /* HAVE_STRNLEN_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -187,7 +200,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcslen); + +- IFUNC_VX_IMPL (strnlen); + IFUNC_VX_IMPL (wcsnlen); + + IFUNC_VX_IMPL (strcpy); +diff --git a/sysdeps/s390/multiarch/strnlen-c.c b/sysdeps/s390/strnlen-c.c +similarity index 81% +rename from sysdeps/s390/multiarch/strnlen-c.c +rename to sysdeps/s390/strnlen-c.c +index 353e83ed356ca080..c2d887f1e4f504e8 100644 +--- a/sysdeps/s390/multiarch/strnlen-c.c ++++ b/sysdeps/s390/strnlen-c.c +@@ -16,15 +16,19 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define STRNLEN __strnlen_c +-# ifdef SHARED +-# undef libc_hidden_def +-# define libc_hidden_def(name) \ ++#include ++ ++#if HAVE_STRNLEN_C ++# if HAVE_STRNLEN_IFUNC ++# define STRNLEN STRNLEN_C ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_def ++# define libc_hidden_def(name) \ + __hidden_ver1 (__strnlen_c, __GI_strnlen, __strnlen_c); \ + strong_alias (__strnlen_c, __strnlen_c_1); \ + __hidden_ver1 (__strnlen_c_1, __GI___strnlen, __strnlen_c_1); +-# endif /* SHARED */ ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/strnlen-vx.S b/sysdeps/s390/strnlen-vx.S +similarity index 90% +rename from sysdeps/s390/multiarch/strnlen-vx.S +rename to sysdeps/s390/strnlen-vx.S +index fc659a956cfc1fa1..0b8fe3da342f6803 100644 +--- a/sysdeps/s390/multiarch/strnlen-vx.S ++++ b/sysdeps/s390/strnlen-vx.S +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRNLEN_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -34,7 +36,7 @@ + -r5=current_len and return_value + -v16=part of s + */ +-ENTRY(__strnlen_vx) ++ENTRY(STRNLEN_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -130,5 +132,16 @@ ENTRY(__strnlen_vx) + clgrjl %r1,%r3,.Lloop64 + + j .Llt64 +-END(__strnlen_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(STRNLEN_Z13) ++ ++# if ! HAVE_STRNLEN_IFUNC ++strong_alias (STRNLEN_Z13, __strnlen) ++weak_alias (__strnlen, strnlen) ++# endif ++ ++# if ! HAVE_STRNLEN_C && defined SHARED && IS_IN (libc) ++strong_alias (STRNLEN_Z13, __GI_strnlen) ++strong_alias (STRNLEN_Z13, __GI___strnlen) ++# endif ++ ++#endif /* HAVE_STRNLEN_Z13 */ +diff --git a/sysdeps/s390/multiarch/strnlen.c b/sysdeps/s390/strnlen.c +similarity index 69% +rename from sysdeps/s390/multiarch/strnlen.c +rename to sysdeps/s390/strnlen.c +index 0f9cff5d69b017ae..aa4953d5035bc2fc 100644 +--- a/sysdeps/s390/multiarch/strnlen.c ++++ b/sysdeps/s390/strnlen.c +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRNLEN_IFUNC + # define strnlen __redirect_strnlen + # define __strnlen __redirect___strnlen + # include +@@ -24,9 +26,18 @@ + # undef __strnlen + # include + +-s390_vx_libc_ifunc_redirected (__redirect___strnlen, __strnlen) +-weak_alias (__strnlen, strnlen) ++# if HAVE_STRNLEN_C ++extern __typeof (__redirect_strnlen) STRNLEN_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_STRNLEN_Z13 ++extern __typeof (__redirect_strnlen) STRNLEN_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect___strnlen, __strnlen, ++ (HAVE_STRNLEN_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRNLEN_Z13 ++ : STRNLEN_DEFAULT ++ ) ++weak_alias (__strnlen, strnlen) ++#endif /* HAVE_STRNLEN_IFUNC */ diff --git a/glibc-rh1659438-18.patch b/glibc-rh1659438-18.patch new file mode 100755 index 0000000..bcd7958 --- /dev/null +++ b/glibc-rh1659438-18.patch @@ -0,0 +1,398 @@ +commit 914a4e05572e108201d71dcd3e47da8aeeecd70d +Author: Stefan Liebler +Date: Tue Dec 18 13:57:10 2018 +0100 + + S390: Refactor strcpy ifunc handling. + + The ifunc handling for strcpy is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + Note: The fallback s390-32/s390-64 ifunc variants with mvst instruction + are now moved to the unified strcpy-z900.S file which can be used for + 31/64bit. The s390-32/s390-64 files multiarch/strcpy.c and strcpy.S + are deleted. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strcpy variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strcpy variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strcpy. + * sysdeps/s390/multiarch/strcpy-vx.S: Move to ... + * sysdeps/s390/strcpy-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strcpy.c: Move to ... + * sysdeps/s390/strcpy.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strcpy.h: New file. + * sysdeps/s390/s390-64/strcpy.S: Move to ... + * sysdeps/s390/strcpy-z900.S: ... here and adjust to be usable + for 31/64bit and ifunc handling. + * sysdeps/s390/s390-32/multiarch/strcpy.c: Delete file. + * sysdeps/s390/s390-64/multiarch/strcpy.c: Likewise. + * sysdeps/s390/s390-32/strcpy.S: Likewise. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index f092355743e3908f..e4191319531ecb01 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -38,5 +38,6 @@ sysdep_routines += bzero memset memset-z900 \ + strstr strstr-vx strstr-c \ + memmem memmem-vx memmem-c \ + strlen strlen-vx strlen-c \ +- strnlen strnlen-vx strnlen-c ++ strnlen strnlen-vx strnlen-c \ ++ strcpy strcpy-vx strcpy-z900 + endif +diff --git a/sysdeps/s390/ifunc-strcpy.h b/sysdeps/s390/ifunc-strcpy.h +new file mode 100644 +index 0000000000000000..85e45556e6a61dd5 +--- /dev/null ++++ b/sysdeps/s390/ifunc-strcpy.h +@@ -0,0 +1,52 @@ ++/* strcpy variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRCPY_IFUNC 1 ++#else ++# define HAVE_STRCPY_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRCPY_IFUNC_AND_VX_SUPPORT HAVE_STRCPY_IFUNC ++#else ++# define HAVE_STRCPY_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRCPY_DEFAULT STRCPY_Z13 ++# define HAVE_STRCPY_Z900_G5 0 ++# define HAVE_STRCPY_Z13 1 ++#else ++# define STRCPY_DEFAULT STRCPY_Z900_G5 ++# define HAVE_STRCPY_Z900_G5 1 ++# define HAVE_STRCPY_Z13 HAVE_STRCPY_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRCPY_Z900_G5 ++# define STRCPY_Z900_G5 __strcpy_default ++#else ++# define STRCPY_Z900_G5 NULL ++#endif ++ ++#if HAVE_STRCPY_Z13 ++# define STRCPY_Z13 __strcpy_vx ++#else ++# define STRCPY_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 35ba223c5d4fb52f..50f7f0b78df723bb 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strcpy strcpy-vx \ +- stpcpy stpcpy-vx stpcpy-c \ ++sysdep_routines += stpcpy stpcpy-vx stpcpy-c \ + strncpy strncpy-vx \ + stpncpy stpncpy-vx stpncpy-c \ + strcat strcat-vx strcat-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 680e5b738bfb7f32..1784372db9828463 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -190,6 +191,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRNLEN_IFUNC */ + ++#if HAVE_STRCPY_IFUNC ++ IFUNC_IMPL (i, name, strcpy, ++# if HAVE_STRCPY_Z13 ++ IFUNC_IMPL_ADD (array, i, strcpy, ++ dl_hwcap & HWCAP_S390_VX, STRCPY_Z13) ++# endif ++# if HAVE_STRCPY_Z900_G5 ++ IFUNC_IMPL_ADD (array, i, strcpy, 1, STRCPY_Z900_G5) ++# endif ++ ) ++#endif /* HAVE_STRCPY_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -202,7 +215,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcsnlen); + +- IFUNC_VX_IMPL (strcpy); + IFUNC_VX_IMPL (wcscpy); + + IFUNC_VX_IMPL (stpcpy); +diff --git a/sysdeps/s390/s390-32/multiarch/strcpy.c b/sysdeps/s390/s390-32/multiarch/strcpy.c +deleted file mode 100644 +index 6a22e31a03c8c1c4..0000000000000000 +--- a/sysdeps/s390/s390-32/multiarch/strcpy.c ++++ /dev/null +@@ -1,21 +0,0 @@ +-/* Multiple versions of strcpy. +- Copyright (C) 2015-2018 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 +- . */ +- +-/* This wrapper-file is needed, because otherwise file +- sysdeps/s390/s390-[32|64]/strcpy.S will be used. */ +-#include +diff --git a/sysdeps/s390/s390-32/strcpy.S b/sysdeps/s390/s390-32/strcpy.S +deleted file mode 100644 +index d49136ee92b83378..0000000000000000 +--- a/sysdeps/s390/s390-32/strcpy.S ++++ /dev/null +@@ -1,36 +0,0 @@ +-/* strcpy - copy a string from source to destination. For IBM S390 +- This file is part of the GNU C Library. +- Copyright (C) 2000-2018 Free Software Foundation, Inc. +- Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). +- +- 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 +- . */ +- +-/* +- * R2 = address of destination +- * R3 = address of source +- */ +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +- .text +-ENTRY(strcpy) +- slr %r0,%r0 +- lr %r1,%r2 +-0: mvst %r1,%r3 +- jo 0b +- br %r14 +-END(strcpy) +-libc_hidden_builtin_def (strcpy) +diff --git a/sysdeps/s390/s390-64/multiarch/strcpy.c b/sysdeps/s390/s390-64/multiarch/strcpy.c +deleted file mode 100644 +index 6a22e31a03c8c1c4..0000000000000000 +--- a/sysdeps/s390/s390-64/multiarch/strcpy.c ++++ /dev/null +@@ -1,21 +0,0 @@ +-/* Multiple versions of strcpy. +- Copyright (C) 2015-2018 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 +- . */ +- +-/* This wrapper-file is needed, because otherwise file +- sysdeps/s390/s390-[32|64]/strcpy.S will be used. */ +-#include +diff --git a/sysdeps/s390/multiarch/strcpy-vx.S b/sysdeps/s390/strcpy-vx.S +similarity index 85% +rename from sysdeps/s390/multiarch/strcpy-vx.S +rename to sysdeps/s390/strcpy-vx.S +index 52197f57f7b5d5cf..844d23e4fee32c9b 100644 +--- a/sysdeps/s390/multiarch/strcpy-vx.S ++++ b/sysdeps/s390/strcpy-vx.S +@@ -16,13 +16,13 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +- +-# include "sysdep.h" +-# include "asm-syntax.h" ++#include ++#include "sysdep.h" ++#include "asm-syntax.h" + + .text + ++#if HAVE_STRCPY_Z13 + /* char * strcpy (const char *dest, const char *src) + Copy string src to dest. + +@@ -36,7 +36,7 @@ + -v17=index of zero + -v18=part of src + */ +-ENTRY(__strcpy_vx) ++ENTRY(STRCPY_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -97,13 +97,13 @@ ENTRY(__strcpy_vx) + .Lfound_align: + vstl %v16,%r5,0(%r2) /* Copy characters including zero. */ + br %r14 +-END(__strcpy_vx) ++END(STRCPY_Z13) + +-/* Use mvst-strcpy-implementation as default implementation. */ +-# define strcpy __strcpy_c +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) strong_alias(__strcpy_c, __GI_strcpy) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++# if ! HAVE_STRCPY_IFUNC ++strong_alias (STRCPY_Z13, strcpy) ++# endif + +-/* Include mvst-strcpy-implementation in s390-32/s390-64 subdirectory. */ +-#include ++# if ! HAVE_STRCPY_Z900_G5 && defined SHARED && IS_IN (libc) ++strong_alias (STRCPY_Z13, __GI_strcpy) ++# endif ++#endif +diff --git a/sysdeps/s390/s390-64/strcpy.S b/sysdeps/s390/strcpy-z900.S +similarity index 66% +rename from sysdeps/s390/s390-64/strcpy.S +rename to sysdeps/s390/strcpy-z900.S +index 203c73c905d0d86c..42798b1fd5c51187 100644 +--- a/sysdeps/s390/s390-64/strcpy.S ++++ b/sysdeps/s390/strcpy-z900.S +@@ -1,4 +1,4 @@ +-/* strcpy - copy a string from source to destination. 64 bit S/390 version. ++/* strcpy - copy a string from source to destination. 64/31 bit S/390 version. + Copyright (C) 2001-2018 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU C Library. +@@ -21,15 +21,36 @@ + %r2 = address of destination + %r3 = address of source. */ + ++#include + #include "sysdep.h" + #include "asm-syntax.h" + ++#if HAVE_STRCPY_Z900_G5 ++# if defined __s390x__ ++# define SLGR slgr ++# define LGR lgr ++# else ++# define SLGR slr ++# define LGR lr ++# endif /* ! defined __s390x__ */ ++ + .text +-ENTRY(strcpy) +- slgr %r0,%r0 +- lgr %r1,%r2 ++ENTRY(STRCPY_Z900_G5) ++ SLGR %r0,%r0 ++ LGR %r1,%r2 + 0: mvst %r1,%r3 + jo 0b + br %r14 +-END(strcpy) +-libc_hidden_builtin_def (strcpy) ++END(STRCPY_Z900_G5) ++ ++# undef SLGR ++# undef LGR ++ ++# if ! HAVE_STRCPY_IFUNC ++strong_alias (STRCPY_Z900_G5, strcpy) ++# endif ++ ++# if defined SHARED && IS_IN (libc) ++strong_alias (STRCPY_Z900_G5, __GI_strcpy) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/strcpy.c b/sysdeps/s390/strcpy.c +similarity index 69% +rename from sysdeps/s390/multiarch/strcpy.c +rename to sysdeps/s390/strcpy.c +index 8f32a13f6730c427..f4e28e24c85b7162 100644 +--- a/sysdeps/s390/multiarch/strcpy.c ++++ b/sysdeps/s390/strcpy.c +@@ -16,12 +16,25 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRCPY_IFUNC + # define strcpy __redirect_strcpy + # include + # undef strcpy + # include + +-s390_vx_libc_ifunc2_redirected (__redirect_strcpy, __strcpy, strcpy) ++# if HAVE_STRCPY_Z900_G5 ++extern __typeof (__redirect_strcpy) STRCPY_Z900_G5 attribute_hidden; ++# endif ++ ++# if HAVE_STRCPY_Z13 ++extern __typeof (__redirect_strcpy) STRCPY_Z13 attribute_hidden; ++# endif + ++s390_libc_ifunc_expr (__redirect_strcpy, strcpy, ++ (HAVE_STRCPY_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRCPY_Z13 ++ : STRCPY_DEFAULT ++ ) + #endif diff --git a/glibc-rh1659438-19.patch b/glibc-rh1659438-19.patch new file mode 100755 index 0000000..b80b640 --- /dev/null +++ b/glibc-rh1659438-19.patch @@ -0,0 +1,279 @@ +commit 970449311ded3cacb6058c96143dd4c057900589 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:11 2018 +0100 + + S390: Refactor stpcpy ifunc handling. + + The ifunc handling for stpcpy is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove stpcpy variants. + * sysdeps/s390/Makefile (sysdep_routines): Add stpcpy variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for stpcpy. + * sysdeps/s390/multiarch/stpcpy-c.c: Move to ... + * sysdeps/s390/stpcpy-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/stpcpy-vx.S: Move to ... + * sysdeps/s390/stpcpy-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/stpcpy.c: Move to ... + * sysdeps/s390/stpcpy.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-stpcpy.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index e4191319531ecb01..b7e1bc8aecf2f8c9 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -39,5 +39,6 @@ sysdep_routines += bzero memset memset-z900 \ + memmem memmem-vx memmem-c \ + strlen strlen-vx strlen-c \ + strnlen strnlen-vx strnlen-c \ +- strcpy strcpy-vx strcpy-z900 ++ strcpy strcpy-vx strcpy-z900 \ ++ stpcpy stpcpy-vx stpcpy-c + endif +diff --git a/sysdeps/s390/ifunc-stpcpy.h b/sysdeps/s390/ifunc-stpcpy.h +new file mode 100644 +index 0000000000000000..9a70cd7c8c4f4582 +--- /dev/null ++++ b/sysdeps/s390/ifunc-stpcpy.h +@@ -0,0 +1,52 @@ ++/* stpcpy variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STPCPY_IFUNC 1 ++#else ++# define HAVE_STPCPY_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STPCPY_IFUNC_AND_VX_SUPPORT HAVE_STPCPY_IFUNC ++#else ++# define HAVE_STPCPY_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STPCPY_DEFAULT STPCPY_Z13 ++# define HAVE_STPCPY_C 0 ++# define HAVE_STPCPY_Z13 1 ++#else ++# define STPCPY_DEFAULT STPCPY_C ++# define HAVE_STPCPY_C 1 ++# define HAVE_STPCPY_Z13 HAVE_STPCPY_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STPCPY_C ++# define STPCPY_C __stpcpy_c ++#else ++# define STPCPY_C NULL ++#endif ++ ++#if HAVE_STPCPY_Z13 ++# define STPCPY_Z13 __stpcpy_vx ++#else ++# define STPCPY_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 50f7f0b78df723bb..9517417dcbe1c701 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += stpcpy stpcpy-vx stpcpy-c \ +- strncpy strncpy-vx \ ++sysdep_routines += strncpy strncpy-vx \ + stpncpy stpncpy-vx stpncpy-c \ + strcat strcat-vx strcat-c \ + strncat strncat-vx strncat-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 1784372db9828463..678ed13833332f11 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -203,6 +204,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRCPY_IFUNC */ + ++#if HAVE_STPCPY_IFUNC ++ IFUNC_IMPL (i, name, stpcpy, ++# if HAVE_STPCPY_Z13 ++ IFUNC_IMPL_ADD (array, i, stpcpy, ++ dl_hwcap & HWCAP_S390_VX, STPCPY_Z13) ++# endif ++# if HAVE_STPCPY_C ++ IFUNC_IMPL_ADD (array, i, stpcpy, 1, STPCPY_C) ++# endif ++ ) ++#endif /* HAVE_STPCPY_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -217,7 +230,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcscpy); + +- IFUNC_VX_IMPL (stpcpy); + IFUNC_VX_IMPL (wcpcpy); + + IFUNC_VX_IMPL (strncpy); +diff --git a/sysdeps/s390/multiarch/stpcpy-c.c b/sysdeps/s390/stpcpy-c.c +similarity index 74% +rename from sysdeps/s390/multiarch/stpcpy-c.c +rename to sysdeps/s390/stpcpy-c.c +index 4a1c3e5832c9b544..76ec88462717799c 100644 +--- a/sysdeps/s390/multiarch/stpcpy-c.c ++++ b/sysdeps/s390/stpcpy-c.c +@@ -16,20 +16,25 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define STPCPY __stpcpy_c +-# undef weak_alias +-# define weak_alias(a, b) +-# ifdef SHARED +-# undef libc_hidden_def +-# define libc_hidden_def(name) \ ++#include ++ ++#if HAVE_STPCPY_C ++# if HAVE_STPCPY_IFUNC ++# define STPCPY STPCPY_C ++ ++# undef weak_alias ++# define weak_alias(a, b) ++ ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_def ++# define libc_hidden_def(name) \ + __hidden_ver1 (__stpcpy_c, __GI___stpcpy, __stpcpy_c); +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) \ ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) \ + strong_alias (__stpcpy_c, __stpcpy_c_1); \ + __hidden_ver1 (__stpcpy_c_1, __GI_stpcpy, __stpcpy_c_1); +-# endif /* SHARED */ +- ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/stpcpy-vx.S b/sysdeps/s390/stpcpy-vx.S +similarity index 90% +rename from sysdeps/s390/multiarch/stpcpy-vx.S +rename to sysdeps/s390/stpcpy-vx.S +index 6c17def0fc35d60d..d2db02d0cd714d27 100644 +--- a/sysdeps/s390/multiarch/stpcpy-vx.S ++++ b/sysdeps/s390/stpcpy-vx.S +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STPCPY_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -36,7 +38,7 @@ + -v17=index of zero + -v18=part of src + */ +-ENTRY(__stpcpy_vx) ++ENTRY(STPCPY_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -100,5 +102,15 @@ ENTRY(__stpcpy_vx) + vstl %v16,%r5,0(%r2) /* Copy characters including zero. */ + la %r2,0(%r5,%r2) /* Return pointer to zero. */ + br %r14 +-END(__stpcpy_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(STPCPY_Z13) ++ ++# if ! HAVE_STPCPY_IFUNC ++strong_alias (STPCPY_Z13, __stpcpy) ++weak_alias (__stpcpy, stpcpy) ++# endif ++ ++# if ! HAVE_STPCPY_C && defined SHARED && IS_IN (libc) ++strong_alias (STPCPY_Z13, __GI_stpcpy) ++strong_alias (STPCPY_Z13, __GI___stpcpy) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/stpcpy.c b/sysdeps/s390/stpcpy.c +similarity index 74% +rename from sysdeps/s390/multiarch/stpcpy.c +rename to sysdeps/s390/stpcpy.c +index 654f9dfbef512e34..670604e2de3806b7 100644 +--- a/sysdeps/s390/multiarch/stpcpy.c ++++ b/sysdeps/s390/stpcpy.c +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STPCPY_IFUNC + # define stpcpy __redirect_stpcpy + # define __stpcpy __redirect___stpcpy + /* Omit the stpcpy inline definitions because it would redefine stpcpy. */ +@@ -27,9 +29,18 @@ + # undef __stpcpy + # include + +-s390_vx_libc_ifunc_redirected (__redirect___stpcpy, __stpcpy); +-weak_alias (__stpcpy, stpcpy) ++# if HAVE_STPCPY_C ++extern __typeof (__redirect_stpcpy) STPCPY_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_STPCPY_Z13 ++extern __typeof (__redirect_stpcpy) STPCPY_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect___stpcpy, __stpcpy, ++ (HAVE_STPCPY_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STPCPY_Z13 ++ : STPCPY_DEFAULT ++ ) ++weak_alias (__stpcpy, stpcpy) ++#endif diff --git a/glibc-rh1659438-2.patch b/glibc-rh1659438-2.patch new file mode 100755 index 0000000..855686c --- /dev/null +++ b/glibc-rh1659438-2.patch @@ -0,0 +1,58 @@ +commit e8023f2685c9f97e72bbe9d2a9c968e0d8438371 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:03 2018 +0100 + + S390: Use hwcap instead of dl_hwcap in ifunc-resolvers. + + The renaming of hwcap arguments in ifunc-resolvers is needed + in order to prepare for further commits which refactors + ifunc handling for memset, memcmp, and memcpy. Now you are able + to use s390_libc_ifunc_init which stores the stfle bits + within the expression for an ifunc-resolver generated by + s390_libc_ifunc_expr. + + ChangeLog: + + * sysdeps/s390/multiarch/ifunc-resolve.h + (s390_libc_ifunc_init, s390_libc_ifunc, + s390_vx_libc_ifunc2_redirected): Use hwcap instead of dl_hwcap. + +diff --git a/sysdeps/s390/multiarch/ifunc-resolve.h b/sysdeps/s390/multiarch/ifunc-resolve.h +index b42ed922fd27834b..b7e20abc59638251 100644 +--- a/sysdeps/s390/multiarch/ifunc-resolve.h ++++ b/sysdeps/s390/multiarch/ifunc-resolve.h +@@ -42,9 +42,9 @@ + : : "cc"); + #define s390_libc_ifunc_init() \ + unsigned long long stfle_bits = 0ULL; \ +- if (__glibc_likely((dl_hwcap & HWCAP_S390_STFLE) \ +- && (dl_hwcap & HWCAP_S390_ZARCH) \ +- && (dl_hwcap & HWCAP_S390_HIGH_GPRS))) \ ++ if (__glibc_likely ((hwcap & HWCAP_S390_STFLE) \ ++ && (hwcap & HWCAP_S390_ZARCH) \ ++ && (hwcap & HWCAP_S390_HIGH_GPRS))) \ + { \ + S390_STORE_STFLE (stfle_bits); \ + } +@@ -61,7 +61,7 @@ + : __glibc_likely (S390_IS_Z10 (stfle_bits)) \ + ? RESOLVERFUNC##_z10 \ + : RESOLVERFUNC##_default, \ +- unsigned long int dl_hwcap, s390_libc_ifunc_init); ++ unsigned long int hwcap, s390_libc_ifunc_init); + + #define s390_vx_libc_ifunc(FUNC) \ + s390_vx_libc_ifunc2_redirected(FUNC, FUNC, FUNC) +@@ -79,10 +79,10 @@ + extern __typeof (TYPE_FUNC) RESOLVERFUNC##_vx attribute_hidden; \ + extern __typeof (TYPE_FUNC) RESOLVERFUNC##_c attribute_hidden; \ + __ifunc (TYPE_FUNC, FUNC, \ +- (dl_hwcap & HWCAP_S390_VX) \ ++ (hwcap & HWCAP_S390_VX) \ + ? RESOLVERFUNC##_vx \ + : RESOLVERFUNC##_c, \ +- unsigned long int dl_hwcap, s390_vx_libc_ifunc_init); ++ unsigned long int hwcap, s390_vx_libc_ifunc_init); + + #define s390_libc_ifunc_expr_init() + #define s390_libc_ifunc_expr(TYPE_FUNC, FUNC, EXPR) \ diff --git a/glibc-rh1659438-20.patch b/glibc-rh1659438-20.patch new file mode 100755 index 0000000..855354d --- /dev/null +++ b/glibc-rh1659438-20.patch @@ -0,0 +1,378 @@ +commit d1bdbf380908c34f31ba145ec9afebade3f1418f +Author: Stefan Liebler +Date: Tue Dec 18 13:57:11 2018 +0100 + + S390: Refactor strncpy ifunc handling. + + The ifunc handling for strncpy is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + Note: The fallback s390-32/s390-64 ifunc variants are now moved to + the strncpy-z900.S files. The s390-32/s390-64 files multiarch/strncpy.c + and strncpy.S are deleted. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strncpy variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strncpy variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strncpy. + * sysdeps/s390/multiarch/strncpy-vx.S: Move to ... + * sysdeps/s390/strncpy-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strncpy.c: Move to ... + * sysdeps/s390/strncpy.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strncpy.h: New file. + * sysdeps/s390/s390-64/strncpy.S: Move to ... + * sysdeps/s390/s390-64/strncpy-z900.S: ... here + and adjust ifunc handling. + * sysdeps/s390/s390-32/strncpy.S: Move to ... + * sysdeps/s390/s390-32/strncpy-z900.S: ... here + and adjust ifunc handling. + * sysdeps/s390/s390-32/multiarch/strncpy.c: Delete file. + * sysdeps/s390/s390-64/multiarch/strncpy.c: Likewise. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index b7e1bc8aecf2f8c9..db060c81aade84ca 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -40,5 +40,6 @@ sysdep_routines += bzero memset memset-z900 \ + strlen strlen-vx strlen-c \ + strnlen strnlen-vx strnlen-c \ + strcpy strcpy-vx strcpy-z900 \ +- stpcpy stpcpy-vx stpcpy-c ++ stpcpy stpcpy-vx stpcpy-c \ ++ strncpy strncpy-vx strncpy-z900 + endif +diff --git a/sysdeps/s390/ifunc-strncpy.h b/sysdeps/s390/ifunc-strncpy.h +new file mode 100644 +index 0000000000000000..31e87e93c529c443 +--- /dev/null ++++ b/sysdeps/s390/ifunc-strncpy.h +@@ -0,0 +1,52 @@ ++/* strncpy variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRNCPY_IFUNC 1 ++#else ++# define HAVE_STRNCPY_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRNCPY_IFUNC_AND_VX_SUPPORT HAVE_STRNCPY_IFUNC ++#else ++# define HAVE_STRNCPY_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRNCPY_DEFAULT STRNCPY_Z13 ++# define HAVE_STRNCPY_Z900_G5 0 ++# define HAVE_STRNCPY_Z13 1 ++#else ++# define STRNCPY_DEFAULT STRNCPY_Z900_G5 ++# define HAVE_STRNCPY_Z900_G5 1 ++# define HAVE_STRNCPY_Z13 HAVE_STRNCPY_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRNCPY_Z900_G5 ++# define STRNCPY_Z900_G5 __strncpy_default ++#else ++# define STRNCPY_Z900_G5 NULL ++#endif ++ ++#if HAVE_STRNCPY_Z13 ++# define STRNCPY_Z13 __strncpy_vx ++#else ++# define STRNCPY_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 9517417dcbe1c701..c5189b556cf3762d 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strncpy strncpy-vx \ +- stpncpy stpncpy-vx stpncpy-c \ ++sysdep_routines += stpncpy stpncpy-vx stpncpy-c \ + strcat strcat-vx strcat-c \ + strncat strncat-vx strncat-c \ + strcmp strcmp-vx \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 678ed13833332f11..d598fc5c22050da2 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -216,6 +217,19 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STPCPY_IFUNC */ + ++#if HAVE_STRNCPY_IFUNC ++ IFUNC_IMPL (i, name, strncpy, ++# if HAVE_STRNCPY_Z13 ++ IFUNC_IMPL_ADD (array, i, strncpy, ++ dl_hwcap & HWCAP_S390_VX, STRNCPY_Z13) ++# endif ++# if HAVE_STRNCPY_Z900_G5 ++ IFUNC_IMPL_ADD (array, i, strncpy, 1, STRNCPY_Z900_G5) ++# endif ++ ) ++#endif /* HAVE_STRNCPY_IFUNC */ ++ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -232,7 +246,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcpcpy); + +- IFUNC_VX_IMPL (strncpy); + IFUNC_VX_IMPL (wcsncpy); + + IFUNC_VX_IMPL (stpncpy); +diff --git a/sysdeps/s390/s390-32/multiarch/strncpy.c b/sysdeps/s390/s390-32/multiarch/strncpy.c +deleted file mode 100644 +index 57f9df18d12c1959..0000000000000000 +--- a/sysdeps/s390/s390-32/multiarch/strncpy.c ++++ /dev/null +@@ -1,21 +0,0 @@ +-/* Multiple versions of strncpy. +- Copyright (C) 2015-2018 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 +- . */ +- +-/* This wrapper-file is needed, because otherwise file +- sysdeps/s390/s390-[32|64]/strncpy.S will be used. */ +-#include +diff --git a/sysdeps/s390/s390-32/strncpy.S b/sysdeps/s390/s390-32/strncpy-z900.S +similarity index 89% +rename from sysdeps/s390/s390-32/strncpy.S +rename to sysdeps/s390/s390-32/strncpy-z900.S +index 9086eb1c707bdfb3..ebdaba015214bc59 100644 +--- a/sysdeps/s390/s390-32/strncpy.S ++++ b/sysdeps/s390/s390-32/strncpy-z900.S +@@ -24,10 +24,12 @@ + * R4 = max of bytes to copy + */ + ++#include + #include "sysdep.h" + #include "asm-syntax.h" + +-ENTRY(strncpy) ++#if HAVE_STRNCPY_Z900_G5 ++ENTRY(STRNCPY_Z900_G5) + .text + st %r2,24(%r15) # save dst pointer + slr %r2,%r3 # %r3 points to src, %r2+%r3 to dst +@@ -75,5 +77,13 @@ ENTRY(strncpy) + jo .L9 + .Lexit: l %r2,24(%r15) # return dst pointer + br %r14 +-END(strncpy) +-libc_hidden_builtin_def (strncpy) ++END(STRNCPY_Z900_G5) ++ ++# if ! HAVE_STRNCPY_IFUNC ++strong_alias (STRNCPY_Z900_G5, strncpy) ++# endif ++ ++# if defined SHARED && IS_IN (libc) ++strong_alias (STRNCPY_Z900_G5, __GI_strncpy) ++# endif ++#endif +diff --git a/sysdeps/s390/s390-64/multiarch/strncpy.c b/sysdeps/s390/s390-64/multiarch/strncpy.c +deleted file mode 100644 +index 57f9df18d12c1959..0000000000000000 +--- a/sysdeps/s390/s390-64/multiarch/strncpy.c ++++ /dev/null +@@ -1,21 +0,0 @@ +-/* Multiple versions of strncpy. +- Copyright (C) 2015-2018 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 +- . */ +- +-/* This wrapper-file is needed, because otherwise file +- sysdeps/s390/s390-[32|64]/strncpy.S will be used. */ +-#include +diff --git a/sysdeps/s390/s390-64/strncpy.S b/sysdeps/s390/s390-64/strncpy-z900.S +similarity index 90% +rename from sysdeps/s390/s390-64/strncpy.S +rename to sysdeps/s390/s390-64/strncpy-z900.S +index be40aa32d5d9a2df..5732e6d83b5e8f30 100644 +--- a/sysdeps/s390/s390-64/strncpy.S ++++ b/sysdeps/s390/s390-64/strncpy-z900.S +@@ -23,10 +23,12 @@ + %r3 = address of source (src) + %r4 = max of bytes to copy. */ + ++#include + #include "sysdep.h" + #include "asm-syntax.h" + +-ENTRY(strncpy) ++#if HAVE_STRNCPY_Z900_G5 ++ENTRY(STRNCPY_Z900_G5) + .text + stg %r2,48(%r15) # save dst pointer + slgr %r2,%r3 # %r3 points to src, %r2+%r3 to dst +@@ -86,5 +88,13 @@ ENTRY(strncpy) + jo .L13 + .Lexit: lg %r2,48(%r15) # return dst pointer + br %r14 +-END(strncpy) +-libc_hidden_builtin_def (strncpy) ++END(STRNCPY_Z900_G5) ++ ++# if ! HAVE_STRNCPY_IFUNC ++strong_alias (STRNCPY_Z900_G5, strncpy) ++# endif ++ ++# if defined SHARED && IS_IN (libc) ++strong_alias (STRNCPY_Z900_G5, __GI_strncpy) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/strncpy-vx.S b/sysdeps/s390/strncpy-vx.S +similarity index 93% +rename from sysdeps/s390/multiarch/strncpy-vx.S +rename to sysdeps/s390/strncpy-vx.S +index 2a37b7b84e0a2514..be09ddf092388c72 100644 +--- a/sysdeps/s390/multiarch/strncpy-vx.S ++++ b/sysdeps/s390/strncpy-vx.S +@@ -16,13 +16,13 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +- +-# include "sysdep.h" +-# include "asm-syntax.h" ++#include ++#include "sysdep.h" ++#include "asm-syntax.h" + + .text + ++#if HAVE_STRNCPY_Z13 + /* char * strncpy (const char *dest, const char *src, size_t n) + Copy at most n characters of string src to dest. + +@@ -40,7 +40,7 @@ + -v18=part of src + -v31=register save area for r6, r7 + */ +-ENTRY(__strncpy_vx) ++ENTRY(STRNCPY_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -196,12 +196,13 @@ ENTRY(__strncpy_vx) + + vl %v16,0(%r5,%r3) /* Load s. */ + j .Llt64 +-END(__strncpy_vx) ++END(STRNCPY_Z13) + +-# define strncpy __strncpy_c +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) strong_alias(__strncpy_c, __GI_strncpy) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++# if ! HAVE_STRNCPY_IFUNC ++strong_alias (STRNCPY_Z13, strncpy) ++# endif + +-/* Include strncpy-implementation in s390-32/s390-64 subdirectory. */ +-#include ++# if ! HAVE_STRNCPY_Z900_G5 && defined SHARED && IS_IN (libc) ++strong_alias (STRNCPY_Z13, __GI_strncpy) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/strncpy.c b/sysdeps/s390/strncpy.c +similarity index 71% +rename from sysdeps/s390/multiarch/strncpy.c +rename to sysdeps/s390/strncpy.c +index 2d4c456d96dad0d6..ec8a26471b6536e8 100644 +--- a/sysdeps/s390/multiarch/strncpy.c ++++ b/sysdeps/s390/strncpy.c +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRNCPY_IFUNC + # define strncpy __redirect_strncpy + /* Omit the strncpy inline definitions because it would redefine strncpy. */ + # define __NO_STRING_INLINES +@@ -24,6 +26,17 @@ + # undef strncpy + # include + +-s390_vx_libc_ifunc2_redirected (__redirect_strncpy, __strncpy, strncpy); ++# if HAVE_STRNCPY_Z900_G5 ++extern __typeof (__redirect_strncpy) STRNCPY_Z900_G5 attribute_hidden; ++# endif ++ ++# if HAVE_STRNCPY_Z13 ++extern __typeof (__redirect_strncpy) STRNCPY_Z13 attribute_hidden; ++# endif + ++s390_libc_ifunc_expr (__redirect_strncpy, strncpy, ++ (HAVE_STRNCPY_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRNCPY_Z13 ++ : STRNCPY_DEFAULT ++ ) + #endif diff --git a/glibc-rh1659438-21.patch b/glibc-rh1659438-21.patch new file mode 100755 index 0000000..91393ae --- /dev/null +++ b/glibc-rh1659438-21.patch @@ -0,0 +1,267 @@ +commit 25218822bdbfb49b8ea0f419e8a20d2b9bd47cd0 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:11 2018 +0100 + + S390: Refactor stpncpy ifunc handling. + + The ifunc handling for stpncpy is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove stpncpy variants. + * sysdeps/s390/Makefile (sysdep_routines): Add stpncpy variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for stpncpy. + * sysdeps/s390/multiarch/stpncpy-c.c: Move to ... + * sysdeps/s390/stpncpy-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/stpncpy-vx.S: Move to ... + * sysdeps/s390/stpncpy-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/stpncpy.c: Move to ... + * sysdeps/s390/stpncpy.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-stpncpy.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index db060c81aade84ca..a9882b3996c30322 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -41,5 +41,6 @@ sysdep_routines += bzero memset memset-z900 \ + strnlen strnlen-vx strnlen-c \ + strcpy strcpy-vx strcpy-z900 \ + stpcpy stpcpy-vx stpcpy-c \ +- strncpy strncpy-vx strncpy-z900 ++ strncpy strncpy-vx strncpy-z900 \ ++ stpncpy stpncpy-vx stpncpy-c + endif +diff --git a/sysdeps/s390/ifunc-stpncpy.h b/sysdeps/s390/ifunc-stpncpy.h +new file mode 100644 +index 0000000000000000..46e57334e8439c1c +--- /dev/null ++++ b/sysdeps/s390/ifunc-stpncpy.h +@@ -0,0 +1,52 @@ ++/* stpncpy variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STPNCPY_IFUNC 1 ++#else ++# define HAVE_STPNCPY_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STPNCPY_IFUNC_AND_VX_SUPPORT HAVE_STPNCPY_IFUNC ++#else ++# define HAVE_STPNCPY_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STPNCPY_DEFAULT STPNCPY_Z13 ++# define HAVE_STPNCPY_C 0 ++# define HAVE_STPNCPY_Z13 1 ++#else ++# define STPNCPY_DEFAULT STPNCPY_C ++# define HAVE_STPNCPY_C 1 ++# define HAVE_STPNCPY_Z13 HAVE_STPNCPY_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STPNCPY_C ++# define STPNCPY_C __stpncpy_c ++#else ++# define STPNCPY_C NULL ++#endif ++ ++#if HAVE_STPNCPY_Z13 ++# define STPNCPY_Z13 __stpncpy_vx ++#else ++# define STPNCPY_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index c5189b556cf3762d..3d97d21da1fc852b 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += stpncpy stpncpy-vx stpncpy-c \ +- strcat strcat-vx strcat-c \ ++sysdep_routines += strcat strcat-vx strcat-c \ + strncat strncat-vx strncat-c \ + strcmp strcmp-vx \ + strncmp strncmp-vx strncmp-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index d598fc5c22050da2..021e9f247fff44df 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -229,6 +230,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRNCPY_IFUNC */ + ++#if HAVE_STPNCPY_IFUNC ++ IFUNC_IMPL (i, name, stpncpy, ++# if HAVE_STPNCPY_Z13 ++ IFUNC_IMPL_ADD (array, i, stpncpy, ++ dl_hwcap & HWCAP_S390_VX, STPNCPY_Z13) ++# endif ++# if HAVE_STPNCPY_C ++ IFUNC_IMPL_ADD (array, i, stpncpy, 1, STPNCPY_C) ++# endif ++ ) ++#endif /* HAVE_STPNCPY_IFUNC */ ++ + + #ifdef HAVE_S390_VX_ASM_SUPPORT + +@@ -248,7 +261,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcsncpy); + +- IFUNC_VX_IMPL (stpncpy); + IFUNC_VX_IMPL (wcpncpy); + + IFUNC_VX_IMPL (strcat); +diff --git a/sysdeps/s390/multiarch/stpncpy-c.c b/sysdeps/s390/stpncpy-c.c +similarity index 74% +rename from sysdeps/s390/multiarch/stpncpy-c.c +rename to sysdeps/s390/stpncpy-c.c +index 45e50aa9e7df0b5e..e5d1ae867562da6c 100644 +--- a/sysdeps/s390/multiarch/stpncpy-c.c ++++ b/sysdeps/s390/stpncpy-c.c +@@ -16,13 +16,18 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define STPNCPY __stpncpy_c +-# ifdef SHARED +-# undef libc_hidden_def +-# define libc_hidden_def(name) \ +- __hidden_ver1 (__stpncpy_c, __GI___stpncpy, __stpncpy_c); +-# endif /* SHARED */ ++#include ++ ++#if HAVE_STPNCPY_C ++# if HAVE_STPNCPY_IFUNC ++# define STPNCPY STPNCPY_C ++ ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_def ++# define libc_hidden_def(name) \ ++ __hidden_ver1 (__stpncpy_c, __GI___stpncpy, __stpncpy_c); ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/stpncpy-vx.S b/sysdeps/s390/stpncpy-vx.S +similarity index 95% +rename from sysdeps/s390/multiarch/stpncpy-vx.S +rename to sysdeps/s390/stpncpy-vx.S +index 922bd7a355a2d8a0..3dccc10be3b58d8d 100644 +--- a/sysdeps/s390/multiarch/stpncpy-vx.S ++++ b/sysdeps/s390/stpncpy-vx.S +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STPNCPY_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -38,7 +40,7 @@ + -%r6 = loaded bytes + -%r7 = border, tmp + */ +-ENTRY(__stpncpy_vx) ++ENTRY(STPNCPY_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -196,5 +198,14 @@ ENTRY(__stpncpy_vx) + + vl %v16,0(%r5,%r3) /* Load s. */ + j .Llt64 +-END(__stpncpy_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(STPNCPY_Z13) ++ ++# if ! HAVE_STPNCPY_IFUNC ++strong_alias (STPNCPY_Z13, __stpncpy) ++weak_alias (__stpncpy, stpncpy) ++# endif ++ ++# if ! HAVE_STPNCPY_C && defined SHARED && IS_IN (libc) ++strong_alias (STPNCPY_Z13, __GI___stpncpy) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/stpncpy.c b/sysdeps/s390/stpncpy.c +similarity index 70% +rename from sysdeps/s390/multiarch/stpncpy.c +rename to sysdeps/s390/stpncpy.c +index f7f9d51a50db47d7..250dc68ed19bf6d9 100644 +--- a/sysdeps/s390/multiarch/stpncpy.c ++++ b/sysdeps/s390/stpncpy.c +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STPNCPY_IFUNC + # define stpncpy __redirect_stpncpy + # define __stpncpy __redirect___stpncpy + # include +@@ -24,9 +26,18 @@ + # undef __stpncpy + # include + +-s390_vx_libc_ifunc_redirected (__redirect___stpncpy, __stpncpy) +-weak_alias (__stpncpy, stpncpy) ++# if HAVE_STPNCPY_C ++extern __typeof (__redirect_stpncpy) STPNCPY_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_STPNCPY_Z13 ++extern __typeof (__redirect_stpncpy) STPNCPY_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect___stpncpy, __stpncpy, ++ (HAVE_STPNCPY_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STPNCPY_Z13 ++ : STPNCPY_DEFAULT ++ ) ++weak_alias (__stpncpy, stpncpy) ++#endif diff --git a/glibc-rh1659438-22.patch b/glibc-rh1659438-22.patch new file mode 100755 index 0000000..3e74480 --- /dev/null +++ b/glibc-rh1659438-22.patch @@ -0,0 +1,259 @@ +commit 8e5a0afbbf0a96fb873e27aa064c9bacc9cfd9c6 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:12 2018 +0100 + + S390: Refactor strcat ifunc handling. + + The ifunc handling for strcat is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strcat variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strcat variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strcat. + * sysdeps/s390/multiarch/strcat-c.c: Move to ... + * sysdeps/s390/strcat-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strcat-vx.S: Move to ... + * sysdeps/s390/strcat-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strcat.c: Move to ... + * sysdeps/s390/strcat.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strcat.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index a9882b3996c30322..de2d5e5652dde412 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -42,5 +42,6 @@ sysdep_routines += bzero memset memset-z900 \ + strcpy strcpy-vx strcpy-z900 \ + stpcpy stpcpy-vx stpcpy-c \ + strncpy strncpy-vx strncpy-z900 \ +- stpncpy stpncpy-vx stpncpy-c ++ stpncpy stpncpy-vx stpncpy-c \ ++ strcat strcat-vx strcat-c + endif +diff --git a/sysdeps/s390/ifunc-strcat.h b/sysdeps/s390/ifunc-strcat.h +new file mode 100644 +index 0000000000000000..6fd2f7dd31fff64f +--- /dev/null ++++ b/sysdeps/s390/ifunc-strcat.h +@@ -0,0 +1,52 @@ ++/* strcat variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRCAT_IFUNC 1 ++#else ++# define HAVE_STRCAT_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRCAT_IFUNC_AND_VX_SUPPORT HAVE_STRCAT_IFUNC ++#else ++# define HAVE_STRCAT_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRCAT_DEFAULT STRCAT_Z13 ++# define HAVE_STRCAT_C 0 ++# define HAVE_STRCAT_Z13 1 ++#else ++# define STRCAT_DEFAULT STRCAT_C ++# define HAVE_STRCAT_C 1 ++# define HAVE_STRCAT_Z13 HAVE_STRCAT_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRCAT_C ++# define STRCAT_C __strcat_c ++#else ++# define STRCAT_C NULL ++#endif ++ ++#if HAVE_STRCAT_Z13 ++# define STRCAT_Z13 __strcat_vx ++#else ++# define STRCAT_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 3d97d21da1fc852b..9b66237aaf9eb47e 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strcat strcat-vx strcat-c \ +- strncat strncat-vx strncat-c \ ++sysdep_routines += strncat strncat-vx strncat-c \ + strcmp strcmp-vx \ + strncmp strncmp-vx strncmp-c \ + strchr strchr-vx strchr-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 021e9f247fff44df..1b7f3df3a3cfe561 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -32,6 +32,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -242,6 +243,17 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STPNCPY_IFUNC */ + ++#if HAVE_STRCAT_IFUNC ++ IFUNC_IMPL (i, name, strcat, ++# if HAVE_STRCAT_Z13 ++ IFUNC_IMPL_ADD (array, i, strcat, ++ dl_hwcap & HWCAP_S390_VX, STRCAT_Z13) ++# endif ++# if HAVE_STRCAT_C ++ IFUNC_IMPL_ADD (array, i, strcat, 1, STRCAT_C) ++# endif ++ ) ++#endif /* HAVE_STRCAT_IFUNC */ + + #ifdef HAVE_S390_VX_ASM_SUPPORT + +@@ -263,7 +275,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcpncpy); + +- IFUNC_VX_IMPL (strcat); + IFUNC_VX_IMPL (wcscat); + + IFUNC_VX_IMPL (strncat); +diff --git a/sysdeps/s390/multiarch/strcat-c.c b/sysdeps/s390/strcat-c.c +similarity index 73% +rename from sysdeps/s390/multiarch/strcat-c.c +rename to sysdeps/s390/strcat-c.c +index f871faa7b563e74b..7accc6c7ef80ecf2 100644 +--- a/sysdeps/s390/multiarch/strcat-c.c ++++ b/sysdeps/s390/strcat-c.c +@@ -16,13 +16,17 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define STRCAT __strcat_c +-# ifdef SHARED +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) \ +- __hidden_ver1 (__strcat_c, __GI_strcat, __strcat_c); +-# endif /* SHARED */ ++#include ++ ++#if HAVE_STRCAT_C ++# if HAVE_STRCAT_IFUNC ++# define STRCAT STRCAT_C ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) \ ++ __hidden_ver1 (__strcat_c, __GI_strcat, __strcat_c); ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/strcat-vx.S b/sysdeps/s390/strcat-vx.S +similarity index 94% +rename from sysdeps/s390/multiarch/strcat-vx.S +rename to sysdeps/s390/strcat-vx.S +index 3abbbcccedad0eb4..218e301f10c6abe3 100644 +--- a/sysdeps/s390/multiarch/strcat-vx.S ++++ b/sysdeps/s390/strcat-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_STRCAT_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -37,7 +38,7 @@ + -v17=index of zero + -v18=part of src + */ +-ENTRY(__strcat_vx) ++ENTRY(STRCAT_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -157,5 +158,13 @@ ENTRY(__strcat_vx) + vstl %v16,%r5,0(%r2) /* Copy characters including zero. */ + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 +-END(__strcat_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(STRCAT_Z13) ++ ++# if ! HAVE_STRCAT_IFUNC ++strong_alias (STRCAT_Z13, strcat) ++# endif ++ ++# if ! HAVE_STRCAT_C && defined SHARED && IS_IN (libc) ++strong_alias (STRCAT_Z13, __GI_strcat) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/strcat.c b/sysdeps/s390/strcat.c +similarity index 69% +rename from sysdeps/s390/multiarch/strcat.c +rename to sysdeps/s390/strcat.c +index 7d4126b44f23679a..d378519c8af59620 100644 +--- a/sysdeps/s390/multiarch/strcat.c ++++ b/sysdeps/s390/strcat.c +@@ -16,14 +16,25 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRCAT_IFUNC + # define strcat __redirect_strcat + # include + # undef strcat + # include + +-s390_vx_libc_ifunc2_redirected (__redirect_strcat, __strcat, strcat) ++# if HAVE_STRCAT_C ++extern __typeof (__redirect_strcat) STRCAT_C attribute_hidden; ++# endif ++ ++# if HAVE_STRCAT_Z13 ++extern __typeof (__redirect_strcat) STRCAT_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (__redirect_strcat, strcat, ++ (HAVE_STRCAT_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRCAT_Z13 ++ : STRCAT_DEFAULT ++ ) ++#endif diff --git a/glibc-rh1659438-23.patch b/glibc-rh1659438-23.patch new file mode 100755 index 0000000..46f3173 --- /dev/null +++ b/glibc-rh1659438-23.patch @@ -0,0 +1,252 @@ +commit b935335155d65971fe2a54e32c0eb74303d4e4fc +Author: Stefan Liebler +Date: Tue Dec 18 13:57:12 2018 +0100 + + S390: Refactor strncat ifunc handling. + + The ifunc handling for strncat is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strncat variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strncat variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strncat. + * sysdeps/s390/multiarch/strncat-c.c: Move to ... + * sysdeps/s390/strncat-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strncat-vx.S: Move to ... + * sysdeps/s390/strncat-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strncat.c: Move to ... + * sysdeps/s390/strncat.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strncat.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index de2d5e5652dde412..cb5dc1d4f95fd11c 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -43,5 +43,6 @@ sysdep_routines += bzero memset memset-z900 \ + stpcpy stpcpy-vx stpcpy-c \ + strncpy strncpy-vx strncpy-z900 \ + stpncpy stpncpy-vx stpncpy-c \ +- strcat strcat-vx strcat-c ++ strcat strcat-vx strcat-c \ ++ strncat strncat-vx strncat-c + endif +diff --git a/sysdeps/s390/ifunc-strncat.h b/sysdeps/s390/ifunc-strncat.h +new file mode 100644 +index 0000000000000000..bb164dcc32905b18 +--- /dev/null ++++ b/sysdeps/s390/ifunc-strncat.h +@@ -0,0 +1,52 @@ ++/* strncat variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRNCAT_IFUNC 1 ++#else ++# define HAVE_STRNCAT_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRNCAT_IFUNC_AND_VX_SUPPORT HAVE_STRNCAT_IFUNC ++#else ++# define HAVE_STRNCAT_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRNCAT_DEFAULT STRNCAT_Z13 ++# define HAVE_STRNCAT_C 0 ++# define HAVE_STRNCAT_Z13 1 ++#else ++# define STRNCAT_DEFAULT STRNCAT_C ++# define HAVE_STRNCAT_C 1 ++# define HAVE_STRNCAT_Z13 HAVE_STRNCAT_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRNCAT_C ++# define STRNCAT_C __strncat_c ++#else ++# define STRNCAT_C NULL ++#endif ++ ++#if HAVE_STRNCAT_Z13 ++# define STRNCAT_Z13 __strncat_vx ++#else ++# define STRNCAT_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 9b66237aaf9eb47e..24be3eac5131fd4a 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strncat strncat-vx strncat-c \ +- strcmp strcmp-vx \ ++sysdep_routines += strcmp strcmp-vx \ + strncmp strncmp-vx strncmp-c \ + strchr strchr-vx strchr-c \ + strchrnul strchrnul-vx strchrnul-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 1b7f3df3a3cfe561..3abcaf08e0ccd385 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -255,6 +256,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRCAT_IFUNC */ + ++#if HAVE_STRNCAT_IFUNC ++ IFUNC_IMPL (i, name, strncat, ++# if HAVE_STRNCAT_Z13 ++ IFUNC_IMPL_ADD (array, i, strncat, ++ dl_hwcap & HWCAP_S390_VX, STRNCAT_Z13) ++# endif ++# if HAVE_STRNCAT_C ++ IFUNC_IMPL_ADD (array, i, strncat, 1, STRNCAT_C) ++# endif ++ ) ++#endif /* HAVE_STRNCAT_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -277,7 +290,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcscat); + +- IFUNC_VX_IMPL (strncat); + IFUNC_VX_IMPL (wcsncat); + + IFUNC_VX_IMPL (strcmp); +diff --git a/sysdeps/s390/multiarch/strncat-c.c b/sysdeps/s390/strncat-c.c +similarity index 86% +rename from sysdeps/s390/multiarch/strncat-c.c +rename to sysdeps/s390/strncat-c.c +index 9e6c245ccbbc2e23..86df89887c7b6293 100644 +--- a/sysdeps/s390/multiarch/strncat-c.c ++++ b/sysdeps/s390/strncat-c.c +@@ -16,8 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define STRNCAT __strncat_c +-# define STRNCAT_PRIMARY ++#include ++ ++#if HAVE_STRNCAT_C ++# if HAVE_STRNCAT_IFUNC ++# define STRNCAT STRNCAT_C ++# define STRNCAT_PRIMARY ++# endif + # include + #endif +diff --git a/sysdeps/s390/multiarch/strncat-vx.S b/sysdeps/s390/strncat-vx.S +similarity index 94% +rename from sysdeps/s390/multiarch/strncat-vx.S +rename to sysdeps/s390/strncat-vx.S +index e6584d0f438f0e38..76345e7dd702dd85 100644 +--- a/sysdeps/s390/multiarch/strncat-vx.S ++++ b/sysdeps/s390/strncat-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_STRNCAT_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -40,7 +41,7 @@ + -v18=part of src + -v31=register save area for r6, r7 + */ +-ENTRY(__strncat_vx) ++ENTRY(STRNCAT_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -235,5 +236,17 @@ ENTRY(__strncat_vx) + + vl %v16,0(%r5,%r3) /* Load s. */ + j .Lcpy_lt64 +-END(__strncat_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(STRNCAT_Z13) ++ ++# if ! HAVE_STRNCAT_IFUNC ++strong_alias (STRNCAT_Z13, strncat) ++# endif ++ ++# if ! HAVE_STRNCAT_C ++/* See string/strncat.c and define STRNCAT_PRIMARY. */ ++strong_alias (STRNCAT_Z13, __strncat) ++# if defined SHARED && IS_IN (libc) ++strong_alias (__strncat, __GI___strncat) ++# endif ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/strncat.c b/sysdeps/s390/strncat.c +similarity index 69% +rename from sysdeps/s390/multiarch/strncat.c +rename to sysdeps/s390/strncat.c +index 94b8dffa85420cfa..b4b3656c5ae9c535 100644 +--- a/sysdeps/s390/multiarch/strncat.c ++++ b/sysdeps/s390/strncat.c +@@ -16,12 +16,23 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRNCAT_IFUNC + # include + # include + +-s390_vx_libc_ifunc2 (__strncat, strncat) ++# if HAVE_STRNCAT_C ++extern __typeof (__strncat) STRNCAT_C attribute_hidden; ++# endif ++ ++# if HAVE_STRNCAT_Z13 ++extern __typeof (__strncat) STRNCAT_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (__strncat, strncat, ++ (HAVE_STRNCAT_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRNCAT_Z13 ++ : STRNCAT_DEFAULT ++ ) ++#endif diff --git a/glibc-rh1659438-24.patch b/glibc-rh1659438-24.patch new file mode 100755 index 0000000..b0f4be8 --- /dev/null +++ b/glibc-rh1659438-24.patch @@ -0,0 +1,394 @@ +commit cdab85fe33b0443a645509cbb5b929a0d3307f18 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:13 2018 +0100 + + S390: Refactor strcmp ifunc handling. + + The ifunc handling for strcmp is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + Note: The fallback s390-32/s390-64 ifunc variants with clst instruction + are now moved to the unified strcmp-z900.S file which can be used for + 31/64bit. The s390-32/s390-64 files multiarch/strcmp.c and strcmp.S + are deleted. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strcmp variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strcmp variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strcmp. + * sysdeps/s390/multiarch/strcmp-vx.S: Move to ... + * sysdeps/s390/strcmp-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strcmp.c: Move to ... + * sysdeps/s390/strcmp.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strcmp.h: New file. + * sysdeps/s390/s390-64/strcmp.S: Move to ... + * sysdeps/s390/strcmp-z900.S: ... here and adjust to be usable + for 31/64bit and ifunc handling. + * sysdeps/s390/s390-32/multiarch/strcmp.c: Delete file. + * sysdeps/s390/s390-64/multiarch/strcmp.c: Likewise. + * sysdeps/s390/s390-32/strcmp.S: Likewise. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index cb5dc1d4f95fd11c..71a4658b43aeb745 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -44,5 +44,6 @@ sysdep_routines += bzero memset memset-z900 \ + strncpy strncpy-vx strncpy-z900 \ + stpncpy stpncpy-vx stpncpy-c \ + strcat strcat-vx strcat-c \ +- strncat strncat-vx strncat-c ++ strncat strncat-vx strncat-c \ ++ strcmp strcmp-vx strcmp-z900 + endif +diff --git a/sysdeps/s390/ifunc-strcmp.h b/sysdeps/s390/ifunc-strcmp.h +new file mode 100644 +index 0000000000000000..86ffe686ade52b64 +--- /dev/null ++++ b/sysdeps/s390/ifunc-strcmp.h +@@ -0,0 +1,52 @@ ++/* strcmp variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRCMP_IFUNC 1 ++#else ++# define HAVE_STRCMP_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRCMP_IFUNC_AND_VX_SUPPORT HAVE_STRCMP_IFUNC ++#else ++# define HAVE_STRCMP_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRCMP_DEFAULT STRCMP_Z13 ++# define HAVE_STRCMP_Z900_G5 0 ++# define HAVE_STRCMP_Z13 1 ++#else ++# define STRCMP_DEFAULT STRCMP_Z900_G5 ++# define HAVE_STRCMP_Z900_G5 1 ++# define HAVE_STRCMP_Z13 HAVE_STRCMP_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRCMP_Z900_G5 ++# define STRCMP_Z900_G5 __strcmp_default ++#else ++# define STRCMP_Z900_G5 NULL ++#endif ++ ++#if HAVE_STRCMP_Z13 ++# define STRCMP_Z13 __strcmp_vx ++#else ++# define STRCMP_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 24be3eac5131fd4a..97421a499625c7f2 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strcmp strcmp-vx \ +- strncmp strncmp-vx strncmp-c \ ++sysdep_routines += strncmp strncmp-vx strncmp-c \ + strchr strchr-vx strchr-c \ + strchrnul strchrnul-vx strchrnul-c \ + strrchr strrchr-vx strrchr-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 3abcaf08e0ccd385..44637c431b144c66 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -268,6 +269,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRNCAT_IFUNC */ + ++#if HAVE_STRCMP_IFUNC ++ IFUNC_IMPL (i, name, strcmp, ++# if HAVE_STRCMP_Z13 ++ IFUNC_IMPL_ADD (array, i, strcmp, ++ dl_hwcap & HWCAP_S390_VX, STRCMP_Z13) ++# endif ++# if HAVE_STRCMP_Z900_G5 ++ IFUNC_IMPL_ADD (array, i, strcmp, 1, STRCMP_Z900_G5) ++# endif ++ ) ++#endif /* HAVE_STRCMP_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -292,7 +305,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcsncat); + +- IFUNC_VX_IMPL (strcmp); + IFUNC_VX_IMPL (wcscmp); + + IFUNC_VX_IMPL (strncmp); +diff --git a/sysdeps/s390/s390-32/multiarch/strcmp.c b/sysdeps/s390/s390-32/multiarch/strcmp.c +deleted file mode 100644 +index d06b0f3436b2abfd..0000000000000000 +--- a/sysdeps/s390/s390-32/multiarch/strcmp.c ++++ /dev/null +@@ -1,21 +0,0 @@ +-/* Multiple versions of strcmp. +- Copyright (C) 2015-2018 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 +- . */ +- +-/* This wrapper-file is needed, because otherwise file +- sysdeps/s390/s390-[32|64]/strcmp.S will be used. */ +-#include +diff --git a/sysdeps/s390/s390-32/strcmp.S b/sysdeps/s390/s390-32/strcmp.S +deleted file mode 100644 +index 3cf3f239fddccce8..0000000000000000 +--- a/sysdeps/s390/s390-32/strcmp.S ++++ /dev/null +@@ -1,41 +0,0 @@ +-/* strcmp - compare two string. S/390 version. +- This file is part of the GNU C Library. +- Copyright (C) 2001-2018 Free Software Foundation, Inc. +- Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). +- +- 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 +- . */ +- +-/* INPUT PARAMETERS +- %r2 = address of string 1 +- %r3 = address of string 2. */ +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +- .text +-ENTRY(strcmp) +- slr %r0,%r0 +-0: clst %r2,%r3 +- jo 0b +- jp 1f +- jm 2f +- slr %r2,%r2 +- br %r14 +-1: lhi %r2,1 +- br %r14 +-2: lhi %r2,-1 +- br %r14 +-END(strcmp) +-libc_hidden_builtin_def (strcmp) +diff --git a/sysdeps/s390/s390-64/multiarch/strcmp.c b/sysdeps/s390/s390-64/multiarch/strcmp.c +deleted file mode 100644 +index d06b0f3436b2abfd..0000000000000000 +--- a/sysdeps/s390/s390-64/multiarch/strcmp.c ++++ /dev/null +@@ -1,21 +0,0 @@ +-/* Multiple versions of strcmp. +- Copyright (C) 2015-2018 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 +- . */ +- +-/* This wrapper-file is needed, because otherwise file +- sysdeps/s390/s390-[32|64]/strcmp.S will be used. */ +-#include +diff --git a/sysdeps/s390/multiarch/strcmp-vx.S b/sysdeps/s390/strcmp-vx.S +similarity index 90% +rename from sysdeps/s390/multiarch/strcmp-vx.S +rename to sysdeps/s390/strcmp-vx.S +index bcaeb564d47c58ff..801ad9d32bbd76c0 100644 +--- a/sysdeps/s390/multiarch/strcmp-vx.S ++++ b/sysdeps/s390/strcmp-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_STRCMP_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -36,7 +37,7 @@ + -v17=part of s2 + -v18=index of unequal + */ +-ENTRY(__strcmp_vx) ++ENTRY(STRCMP_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -106,11 +107,13 @@ ENTRY(__strcmp_vx) + .Lend_equal: + lghi %r2,0 + br %r14 +-END(__strcmp_vx) ++END(STRCMP_Z13) + +-# define strcmp __strcmp_c +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) strong_alias(__strcmp_c, __GI_strcmp) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++# if ! HAVE_STRCMP_IFUNC ++strong_alias (STRCMP_Z13, strcmp) ++# endif + +-#include ++# if ! HAVE_STRCMP_Z900_G5 && defined SHARED && IS_IN (libc) ++strong_alias (STRCMP_Z13, __GI_strcmp) ++# endif ++#endif +diff --git a/sysdeps/s390/s390-64/strcmp.S b/sysdeps/s390/strcmp-z900.S +similarity index 70% +rename from sysdeps/s390/s390-64/strcmp.S +rename to sysdeps/s390/strcmp-z900.S +index 6cf1addd8bdf1a19..67b3c8b2e5989cd2 100644 +--- a/sysdeps/s390/s390-64/strcmp.S ++++ b/sysdeps/s390/strcmp-z900.S +@@ -21,21 +21,39 @@ + %r2 = address of string 1 + %r3 = address of string 2. */ + ++#include + #include "sysdep.h" + #include "asm-syntax.h" + ++#if HAVE_STRCMP_Z900_G5 ++# if defined __s390x__ ++# define SLGR slgr ++# define LGHI lghi ++# else ++# define SLGR slr ++# define LGHI lhi ++# endif /* ! defined __s390x__ */ ++ + .text +-ENTRY(strcmp) +- slr %r0,%r0 ++ENTRY(STRCMP_Z900_G5) ++ SLGR %r0,%r0 + 0: clst %r2,%r3 + jo 0b + jp 1f + jm 2f +- slgr %r2,%r2 ++ SLGR %r2,%r2 + br %r14 +-1: lghi %r2,1 ++1: LGHI %r2,1 + br %r14 +-2: lghi %r2,-1 ++2: LGHI %r2,-1 + br %r14 +-END(strcmp) +-libc_hidden_builtin_def (strcmp) ++END(STRCMP_Z900_G5) ++ ++# if ! HAVE_STRCMP_IFUNC ++strong_alias (STRCMP_Z900_G5, strcmp) ++# endif ++ ++# if defined SHARED && IS_IN (libc) ++strong_alias (STRCMP_Z900_G5, __GI_strcmp) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/strcmp.c b/sysdeps/s390/strcmp.c +similarity index 71% +rename from sysdeps/s390/multiarch/strcmp.c +rename to sysdeps/s390/strcmp.c +index 7c8b17b3041dd549..9efa30acaf21f4e8 100644 +--- a/sysdeps/s390/multiarch/strcmp.c ++++ b/sysdeps/s390/strcmp.c +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRCMP_IFUNC + # define strcmp __redirect_strcmp + /* Omit the strcmp inline definitions because it would redefine strcmp. */ + # define __NO_STRING_INLINES +@@ -24,6 +26,17 @@ + # include + # undef strcmp + +-s390_vx_libc_ifunc2_redirected (__redirect_strcmp, __strcmp, strcmp) ++# if HAVE_STRCMP_Z900_G5 ++extern __typeof (__redirect_strcmp) STRCMP_Z900_G5 attribute_hidden; ++# endif ++ ++# if HAVE_STRCMP_Z13 ++extern __typeof (__redirect_strcmp) STRCMP_Z13 attribute_hidden; ++# endif + ++s390_libc_ifunc_expr (__redirect_strcmp, strcmp, ++ (HAVE_STRCMP_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRCMP_Z13 ++ : STRCMP_DEFAULT ++ ) + #endif diff --git a/glibc-rh1659438-25.patch b/glibc-rh1659438-25.patch new file mode 100755 index 0000000..afe7ad0 --- /dev/null +++ b/glibc-rh1659438-25.patch @@ -0,0 +1,263 @@ +commit 316b88421993d540513a6b25b59ec16df267e9b4 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:13 2018 +0100 + + S390: Refactor strncmp ifunc handling. + + The ifunc handling for strncmp is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strncmp variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strncmp variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strncmp. + * sysdeps/s390/multiarch/strncmp-c.c: Move to ... + * sysdeps/s390/strncmp-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strncmp-vx.S: Move to ... + * sysdeps/s390/strncmp-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strncmp.c: Move to ... + * sysdeps/s390/strncmp.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strncmp.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 71a4658b43aeb745..adf3521876725ac8 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -45,5 +45,6 @@ sysdep_routines += bzero memset memset-z900 \ + stpncpy stpncpy-vx stpncpy-c \ + strcat strcat-vx strcat-c \ + strncat strncat-vx strncat-c \ +- strcmp strcmp-vx strcmp-z900 ++ strcmp strcmp-vx strcmp-z900 \ ++ strncmp strncmp-vx strncmp-c + endif +diff --git a/sysdeps/s390/ifunc-strncmp.h b/sysdeps/s390/ifunc-strncmp.h +new file mode 100644 +index 0000000000000000..511b3e9720520a0c +--- /dev/null ++++ b/sysdeps/s390/ifunc-strncmp.h +@@ -0,0 +1,52 @@ ++/* strncmp variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRNCMP_IFUNC 1 ++#else ++# define HAVE_STRNCMP_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRNCMP_IFUNC_AND_VX_SUPPORT HAVE_STRNCMP_IFUNC ++#else ++# define HAVE_STRNCMP_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRNCMP_DEFAULT STRNCMP_Z13 ++# define HAVE_STRNCMP_C 0 ++# define HAVE_STRNCMP_Z13 1 ++#else ++# define STRNCMP_DEFAULT STRNCMP_C ++# define HAVE_STRNCMP_C 1 ++# define HAVE_STRNCMP_Z13 HAVE_STRNCMP_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRNCMP_C ++# define STRNCMP_C __strncmp_c ++#else ++# define STRNCMP_C NULL ++#endif ++ ++#if HAVE_STRNCMP_Z13 ++# define STRNCMP_Z13 __strncmp_vx ++#else ++# define STRNCMP_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 97421a499625c7f2..381376bf9fcb0f58 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strncmp strncmp-vx strncmp-c \ +- strchr strchr-vx strchr-c \ ++sysdep_routines += strchr strchr-vx strchr-c \ + strchrnul strchrnul-vx strchrnul-c \ + strrchr strrchr-vx strrchr-c \ + strspn strspn-vx strspn-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 44637c431b144c66..d982de5788c0b5d5 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -281,6 +282,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRCMP_IFUNC */ + ++#if HAVE_STRNCMP_IFUNC ++ IFUNC_IMPL (i, name, strncmp, ++# if HAVE_STRNCMP_Z13 ++ IFUNC_IMPL_ADD (array, i, strncmp, ++ dl_hwcap & HWCAP_S390_VX, STRNCMP_Z13) ++# endif ++# if HAVE_STRNCMP_C ++ IFUNC_IMPL_ADD (array, i, strncmp, 1, STRNCMP_C) ++# endif ++ ) ++#endif /* HAVE_STRNCMP_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -307,7 +320,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcscmp); + +- IFUNC_VX_IMPL (strncmp); + IFUNC_VX_IMPL (wcsncmp); + + IFUNC_VX_IMPL (strchr); +diff --git a/sysdeps/s390/multiarch/strncmp-c.c b/sysdeps/s390/strncmp-c.c +similarity index 78% +rename from sysdeps/s390/multiarch/strncmp-c.c +rename to sysdeps/s390/strncmp-c.c +index e54277ec1b10f8d7..c7ffdb03e37dc8d8 100644 +--- a/sysdeps/s390/multiarch/strncmp-c.c ++++ b/sysdeps/s390/strncmp-c.c +@@ -16,13 +16,17 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define STRNCMP __strncmp_c +-# ifdef SHARED +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) \ ++#include ++ ++#if HAVE_STRNCMP_C ++# if HAVE_STRNCMP_IFUNC ++# define STRNCMP STRNCMP_C ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) \ + __hidden_ver1 (__strncmp_c, __GI_strncmp, __strncmp_c); +-# endif /* SHARED */ ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/strncmp-vx.S b/sysdeps/s390/strncmp-vx.S +similarity index 93% +rename from sysdeps/s390/multiarch/strncmp-vx.S +rename to sysdeps/s390/strncmp-vx.S +index 168fd657da2a1173..f557afb336d418ff 100644 +--- a/sysdeps/s390/multiarch/strncmp-vx.S ++++ b/sysdeps/s390/strncmp-vx.S +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRNCMP_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -37,7 +39,7 @@ + -v17=part of s2 + -v18=index of unequal + */ +-ENTRY(__strncmp_vx) ++ENTRY(STRNCMP_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -133,5 +135,14 @@ ENTRY(__strncmp_vx) + .Lend_equal: + lghi %r2,0 + br %r14 +-END(__strncmp_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(STRNCMP_Z13) ++ ++# if ! HAVE_STRNCMP_IFUNC ++strong_alias (STRNCMP_Z13, strncmp) ++# endif ++ ++# if ! HAVE_STRNCMP_C && defined SHARED && IS_IN (libc) ++strong_alias (STRNCMP_Z13, __GI_strncmp) ++# endif ++ ++#endif /* HAVE_STRNCMP_Z13 */ +diff --git a/sysdeps/s390/multiarch/strncmp.c b/sysdeps/s390/strncmp.c +similarity index 70% +rename from sysdeps/s390/multiarch/strncmp.c +rename to sysdeps/s390/strncmp.c +index 0ec472c3b03419a3..71351273c4058129 100644 +--- a/sysdeps/s390/multiarch/strncmp.c ++++ b/sysdeps/s390/strncmp.c +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRNCMP_IFUNC + # define strncmp __redirect_strncmp + /* Omit the strncmp inline definitions because it would redefine strncmp. */ + # define __NO_STRING_INLINES +@@ -24,8 +26,17 @@ + # undef strncmp + # include + +-s390_vx_libc_ifunc2_redirected (__redirect_strncmp, __strncmp, strncmp) ++# if HAVE_STRNCMP_C ++extern __typeof (__redirect_strncmp) STRNCMP_C attribute_hidden; ++# endif ++ ++# if HAVE_STRNCMP_Z13 ++extern __typeof (__redirect_strncmp) STRNCMP_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (__redirect_strncmp, strncmp, ++ (HAVE_STRNCMP_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRNCMP_Z13 ++ : STRNCMP_DEFAULT ++ ) ++#endif /* HAVE_STRNCMP_IFUNC */ diff --git a/glibc-rh1659438-26.patch b/glibc-rh1659438-26.patch new file mode 100755 index 0000000..65995ca --- /dev/null +++ b/glibc-rh1659438-26.patch @@ -0,0 +1,268 @@ +commit 32f12653d4ea2fbff409351bf8067f9a0b4a3963 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:14 2018 +0100 + + S390: Refactor strchr ifunc handling. + + The ifunc handling for strchr is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strchr variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strchr variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strchr. + * sysdeps/s390/multiarch/strchr-c.c: Move to ... + * sysdeps/s390/strchr-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strchr-vx.S: Move to ... + * sysdeps/s390/strchr-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strchr.c: Move to ... + * sysdeps/s390/strchr.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strchr.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index adf3521876725ac8..8bb396f498e0b0b0 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -46,5 +46,6 @@ sysdep_routines += bzero memset memset-z900 \ + strcat strcat-vx strcat-c \ + strncat strncat-vx strncat-c \ + strcmp strcmp-vx strcmp-z900 \ +- strncmp strncmp-vx strncmp-c ++ strncmp strncmp-vx strncmp-c \ ++ strchr strchr-vx strchr-c + endif +diff --git a/sysdeps/s390/ifunc-strchr.h b/sysdeps/s390/ifunc-strchr.h +new file mode 100644 +index 0000000000000000..cfeb00eeda890512 +--- /dev/null ++++ b/sysdeps/s390/ifunc-strchr.h +@@ -0,0 +1,52 @@ ++/* strchr variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRCHR_IFUNC 1 ++#else ++# define HAVE_STRCHR_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRCHR_IFUNC_AND_VX_SUPPORT HAVE_STRCHR_IFUNC ++#else ++# define HAVE_STRCHR_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRCHR_DEFAULT STRCHR_Z13 ++# define HAVE_STRCHR_C 0 ++# define HAVE_STRCHR_Z13 1 ++#else ++# define STRCHR_DEFAULT STRCHR_C ++# define HAVE_STRCHR_C 1 ++# define HAVE_STRCHR_Z13 HAVE_STRCHR_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRCHR_C ++# define STRCHR_C __strchr_c ++#else ++# define STRCHR_C NULL ++#endif ++ ++#if HAVE_STRCHR_Z13 ++# define STRCHR_Z13 __strchr_vx ++#else ++# define STRCHR_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 381376bf9fcb0f58..a8e9d0acd9ebf986 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strchr strchr-vx strchr-c \ +- strchrnul strchrnul-vx strchrnul-c \ ++sysdep_routines += strchrnul strchrnul-vx strchrnul-c \ + strrchr strrchr-vx strrchr-c \ + strspn strspn-vx strspn-c \ + strpbrk strpbrk-vx strpbrk-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index d982de5788c0b5d5..e809ca3bacb18aa9 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -294,6 +295,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRNCMP_IFUNC */ + ++#if HAVE_STRCHR_IFUNC ++ IFUNC_IMPL (i, name, strchr, ++# if HAVE_STRCHR_Z13 ++ IFUNC_IMPL_ADD (array, i, strchr, ++ dl_hwcap & HWCAP_S390_VX, STRCHR_Z13) ++# endif ++# if HAVE_STRCHR_C ++ IFUNC_IMPL_ADD (array, i, strchr, 1, STRCHR_C) ++# endif ++ ) ++#endif /* HAVE_STRCHR_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -322,7 +335,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcsncmp); + +- IFUNC_VX_IMPL (strchr); + IFUNC_VX_IMPL (wcschr); + + IFUNC_VX_IMPL (strchrnul); +diff --git a/sysdeps/s390/multiarch/strchr-c.c b/sysdeps/s390/strchr-c.c +similarity index 77% +rename from sysdeps/s390/multiarch/strchr-c.c +rename to sysdeps/s390/strchr-c.c +index 606cb56788966153..3d3579a1d3bc06d0 100644 +--- a/sysdeps/s390/multiarch/strchr-c.c ++++ b/sysdeps/s390/strchr-c.c +@@ -16,14 +16,18 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define STRCHR __strchr_c +-# undef weak_alias +-# ifdef SHARED +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) \ ++#include ++ ++#if HAVE_STRCHR_C ++# if HAVE_STRCHR_IFUNC ++# define STRCHR STRCHR_C ++# undef weak_alias ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) \ + __hidden_ver1 (__strchr_c, __GI_strchr, __strchr_c); +-# endif /* SHARED */ ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/strchr-vx.S b/sysdeps/s390/strchr-vx.S +similarity index 90% +rename from sysdeps/s390/multiarch/strchr-vx.S +rename to sysdeps/s390/strchr-vx.S +index 6e744fb82f3249a6..6ffa06f78c14c8da 100644 +--- a/sysdeps/s390/multiarch/strchr-vx.S ++++ b/sysdeps/s390/strchr-vx.S +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRCHR_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -36,7 +38,7 @@ + -v17=index of unequal + -v18=replicated c + */ +-ENTRY(__strchr_vx) ++ENTRY(STRCHR_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -96,5 +98,15 @@ ENTRY(__strchr_vx) + clije %r3,0,.Lcharacter /* Found zero and c is zero. */ + lghi %r2,0 /* Return null if character not found. */ + br %r14 +-END(__strchr_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(STRCHR_Z13) ++ ++# if ! HAVE_STRCHR_IFUNC ++strong_alias (STRCHR_Z13, strchr) ++weak_alias (strchr, index) ++# endif ++ ++# if ! HAVE_STRCHR_C && defined SHARED && IS_IN (libc) ++strong_alias (STRCHR_Z13, __GI_strchr) ++# endif ++ ++#endif /* HAVE_STRCHR_Z13 */ +diff --git a/sysdeps/s390/multiarch/strchr.c b/sysdeps/s390/strchr.c +similarity index 71% +rename from sysdeps/s390/multiarch/strchr.c +rename to sysdeps/s390/strchr.c +index 8aa33a51cc7e91de..a106c6106dcd5307 100644 +--- a/sysdeps/s390/multiarch/strchr.c ++++ b/sysdeps/s390/strchr.c +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRCHR_IFUNC + # define strchr __redirect_strchr + /* Omit the strchr inline definitions because it would redefine strchr. */ + # define __NO_STRING_INLINES +@@ -24,9 +26,18 @@ + # undef strchr + # include + +-s390_vx_libc_ifunc2_redirected (__redirect_strchr, __strchr, strchr) +-weak_alias (strchr, index) ++# if HAVE_STRCHR_C ++extern __typeof (__redirect_strchr) STRCHR_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_STRCHR_Z13 ++extern __typeof (__redirect_strchr) STRCHR_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect_strchr, strchr, ++ (HAVE_STRCHR_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRCHR_Z13 ++ : STRCHR_DEFAULT ++ ) ++weak_alias (strchr, index) ++#endif /* HAVE_STRCHR_IFUNC */ diff --git a/glibc-rh1659438-27.patch b/glibc-rh1659438-27.patch new file mode 100755 index 0000000..9fb75a4 --- /dev/null +++ b/glibc-rh1659438-27.patch @@ -0,0 +1,253 @@ +commit a1361e65617c660a3ba7d561e081dcd18762a688 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:14 2018 +0100 + + S390: Refactor strchrnul ifunc handling. + + The ifunc handling for strchrnul is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strchrnul variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strchrnul variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strchrnul. + * sysdeps/s390/multiarch/strchrnul-c.c: Move to ... + * sysdeps/s390/strchrnul-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strchrnul-vx.S: Move to ... + * sysdeps/s390/strchrnul-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strchrnul.c: Move to ... + * sysdeps/s390/strchrnul.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strchrnul.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 8bb396f498e0b0b0..c54bb82f4d4f8a67 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -47,5 +47,6 @@ sysdep_routines += bzero memset memset-z900 \ + strncat strncat-vx strncat-c \ + strcmp strcmp-vx strcmp-z900 \ + strncmp strncmp-vx strncmp-c \ +- strchr strchr-vx strchr-c ++ strchr strchr-vx strchr-c \ ++ strchrnul strchrnul-vx strchrnul-c + endif +diff --git a/sysdeps/s390/ifunc-strchrnul.h b/sysdeps/s390/ifunc-strchrnul.h +new file mode 100644 +index 0000000000000000..cac817e6f0a9406d +--- /dev/null ++++ b/sysdeps/s390/ifunc-strchrnul.h +@@ -0,0 +1,52 @@ ++/* strchrnul variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRCHRNUL_IFUNC 1 ++#else ++# define HAVE_STRCHRNUL_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRCHRNUL_IFUNC_AND_VX_SUPPORT HAVE_STRCHRNUL_IFUNC ++#else ++# define HAVE_STRCHRNUL_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRCHRNUL_DEFAULT STRCHRNUL_Z13 ++# define HAVE_STRCHRNUL_C 0 ++# define HAVE_STRCHRNUL_Z13 1 ++#else ++# define STRCHRNUL_DEFAULT STRCHRNUL_C ++# define HAVE_STRCHRNUL_C 1 ++# define HAVE_STRCHRNUL_Z13 HAVE_STRCHRNUL_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRCHRNUL_C ++# define STRCHRNUL_C __strchrnul_c ++#else ++# define STRCHRNUL_C NULL ++#endif ++ ++#if HAVE_STRCHRNUL_Z13 ++# define STRCHRNUL_Z13 __strchrnul_vx ++#else ++# define STRCHRNUL_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index a8e9d0acd9ebf986..999a979fee1417b2 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strchrnul strchrnul-vx strchrnul-c \ +- strrchr strrchr-vx strrchr-c \ ++sysdep_routines += strrchr strrchr-vx strrchr-c \ + strspn strspn-vx strspn-c \ + strpbrk strpbrk-vx strpbrk-c \ + strcspn strcspn-vx strcspn-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index e809ca3bacb18aa9..0a47ffeac3492b3e 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -307,6 +308,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRCHR_IFUNC */ + ++#if HAVE_STRCHRNUL_IFUNC ++ IFUNC_IMPL (i, name, strchrnul, ++# if HAVE_STRCHRNUL_Z13 ++ IFUNC_IMPL_ADD (array, i, strchrnul, ++ dl_hwcap & HWCAP_S390_VX, STRCHRNUL_Z13) ++# endif ++# if HAVE_STRCHRNUL_C ++ IFUNC_IMPL_ADD (array, i, strchrnul, 1, STRCHRNUL_C) ++# endif ++ ) ++#endif /* HAVE_STRCHRNUL_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -337,7 +350,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcschr); + +- IFUNC_VX_IMPL (strchrnul); + IFUNC_VX_IMPL (wcschrnul); + + IFUNC_VX_IMPL (strrchr); +diff --git a/sysdeps/s390/multiarch/strchrnul-c.c b/sysdeps/s390/strchrnul-c.c +similarity index 81% +rename from sysdeps/s390/multiarch/strchrnul-c.c +rename to sysdeps/s390/strchrnul-c.c +index 020cebcf3e275b07..585273f5de8b82bc 100644 +--- a/sysdeps/s390/multiarch/strchrnul-c.c ++++ b/sysdeps/s390/strchrnul-c.c +@@ -16,11 +16,15 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define STRCHRNUL __strchrnul_c +-# define __strchrnul STRCHRNUL +-# undef weak_alias +-# define weak_alias(name, alias) ++#include ++ ++#if HAVE_STRCHRNUL_C ++# if HAVE_STRCHRNUL_IFUNC ++# define STRCHRNUL STRCHRNUL_C ++# define __strchrnul STRCHRNUL ++# undef weak_alias ++# define weak_alias(name, alias) ++# endif + + # include + #endif +diff --git a/sysdeps/s390/multiarch/strchrnul-vx.S b/sysdeps/s390/strchrnul-vx.S +similarity index 91% +rename from sysdeps/s390/multiarch/strchrnul-vx.S +rename to sysdeps/s390/strchrnul-vx.S +index d561825e0432458c..0cd587bc32cf811f 100644 +--- a/sysdeps/s390/multiarch/strchrnul-vx.S ++++ b/sysdeps/s390/strchrnul-vx.S +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRCHRNUL_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -35,7 +37,7 @@ + -v16=part of s + -v18=vector with c replicated in every byte + */ +-ENTRY(__strchrnul_vx) ++ENTRY(STRCHRNUL_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -89,5 +91,11 @@ ENTRY(__strchrnul_vx) + + .Lend: + br %r14 +-END(__strchrnul_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(STRCHRNUL_Z13) ++ ++# if ! HAVE_STRCHRNUL_IFUNC ++strong_alias (STRCHRNUL_Z13, __strchrnul) ++weak_alias (__strchrnul, strchrnul) ++# endif ++ ++#endif /* HAVE_STRCHRNUL_Z13 */ +diff --git a/sysdeps/s390/multiarch/strchrnul.c b/sysdeps/s390/strchrnul.c +similarity index 67% +rename from sysdeps/s390/multiarch/strchrnul.c +rename to sysdeps/s390/strchrnul.c +index 62dfc6bd90638b60..e9fefe1bdc77f038 100644 +--- a/sysdeps/s390/multiarch/strchrnul.c ++++ b/sysdeps/s390/strchrnul.c +@@ -16,13 +16,24 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRCHRNUL_IFUNC + # include + # include + +-s390_vx_libc_ifunc (__strchrnul) +-weak_alias (__strchrnul, strchrnul) ++# if HAVE_STRCHRNUL_C ++extern __typeof (__strchrnul) STRCHRNUL_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_STRCHRNUL_Z13 ++extern __typeof (__strchrnul) STRCHRNUL_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__strchrnul, __strchrnul, ++ (HAVE_STRCHRNUL_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRCHRNUL_Z13 ++ : STRCHRNUL_DEFAULT ++ ) ++weak_alias (__strchrnul, strchrnul) ++#endif /* HAVE_STRCHRNUL_IFUNC */ diff --git a/glibc-rh1659438-28.patch b/glibc-rh1659438-28.patch new file mode 100755 index 0000000..2e29a54 --- /dev/null +++ b/glibc-rh1659438-28.patch @@ -0,0 +1,266 @@ +commit 26ea8760877cf03272e98c21eb1a7745ceca76c4 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:14 2018 +0100 + + S390: Refactor strrchr ifunc handling. + + The ifunc handling for strrchr is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strrchr variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strrchr variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strrchr. + * sysdeps/s390/multiarch/strrchr-c.c: Move to ... + * sysdeps/s390/strrchr-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strrchr-vx.S: Move to ... + * sysdeps/s390/strrchr-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strrchr.c: Move to ... + * sysdeps/s390/strrchr.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strrchr.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index c54bb82f4d4f8a67..3ad44c997e9f1f6b 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -48,5 +48,6 @@ sysdep_routines += bzero memset memset-z900 \ + strcmp strcmp-vx strcmp-z900 \ + strncmp strncmp-vx strncmp-c \ + strchr strchr-vx strchr-c \ +- strchrnul strchrnul-vx strchrnul-c ++ strchrnul strchrnul-vx strchrnul-c \ ++ strrchr strrchr-vx strrchr-c + endif +diff --git a/sysdeps/s390/ifunc-strrchr.h b/sysdeps/s390/ifunc-strrchr.h +new file mode 100644 +index 0000000000000000..7185fc32601f7388 +--- /dev/null ++++ b/sysdeps/s390/ifunc-strrchr.h +@@ -0,0 +1,52 @@ ++/* strrchr variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRRCHR_IFUNC 1 ++#else ++# define HAVE_STRRCHR_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRRCHR_IFUNC_AND_VX_SUPPORT HAVE_STRRCHR_IFUNC ++#else ++# define HAVE_STRRCHR_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRRCHR_DEFAULT STRRCHR_Z13 ++# define HAVE_STRRCHR_C 0 ++# define HAVE_STRRCHR_Z13 1 ++#else ++# define STRRCHR_DEFAULT STRRCHR_C ++# define HAVE_STRRCHR_C 1 ++# define HAVE_STRRCHR_Z13 HAVE_STRRCHR_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRRCHR_C ++# define STRRCHR_C __strrchr_c ++#else ++# define STRRCHR_C NULL ++#endif ++ ++#if HAVE_STRRCHR_Z13 ++# define STRRCHR_Z13 __strrchr_vx ++#else ++# define STRRCHR_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 999a979fee1417b2..c8267555585b617e 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strrchr strrchr-vx strrchr-c \ +- strspn strspn-vx strspn-c \ ++sysdep_routines += strspn strspn-vx strspn-c \ + strpbrk strpbrk-vx strpbrk-c \ + strcspn strcspn-vx strcspn-c \ + memchr memchr-vx \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 0a47ffeac3492b3e..60cd705ffa4e2c35 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -320,6 +321,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRCHRNUL_IFUNC */ + ++#if HAVE_STRRCHR_IFUNC ++ IFUNC_IMPL (i, name, strrchr, ++# if HAVE_STRRCHR_Z13 ++ IFUNC_IMPL_ADD (array, i, strrchr, ++ dl_hwcap & HWCAP_S390_VX, STRRCHR_Z13) ++# endif ++# if HAVE_STRRCHR_C ++ IFUNC_IMPL_ADD (array, i, strrchr, 1, STRRCHR_C) ++# endif ++ ) ++#endif /* HAVE_STRRCHR_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -352,7 +365,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcschrnul); + +- IFUNC_VX_IMPL (strrchr); + IFUNC_VX_IMPL (wcsrchr); + + IFUNC_VX_IMPL (strspn); +diff --git a/sysdeps/s390/multiarch/strrchr-c.c b/sysdeps/s390/strrchr-c.c +similarity index 77% +rename from sysdeps/s390/multiarch/strrchr-c.c +rename to sysdeps/s390/strrchr-c.c +index 53ceb8086f0711c8..615f16da7d9db5ef 100644 +--- a/sysdeps/s390/multiarch/strrchr-c.c ++++ b/sysdeps/s390/strrchr-c.c +@@ -16,14 +16,18 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define STRRCHR __strrchr_c +-# undef weak_alias +-# ifdef SHARED +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) \ ++#include ++ ++#if HAVE_STRRCHR_C ++# if HAVE_STRRCHR_IFUNC ++# define STRRCHR STRRCHR_C ++# undef weak_alias ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) \ + __hidden_ver1 (__strrchr_c, __GI_strrchr, __strrchr_c); +-# endif /* SHARED */ ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/strrchr-vx.S b/sysdeps/s390/strrchr-vx.S +similarity index 94% +rename from sysdeps/s390/multiarch/strrchr-vx.S +rename to sysdeps/s390/strrchr-vx.S +index 8b3b989631f23de5..5f4ac14ee338c790 100644 +--- a/sysdeps/s390/multiarch/strrchr-vx.S ++++ b/sysdeps/s390/strrchr-vx.S +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRRCHR_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -39,7 +41,7 @@ + -v19=part of s with last occurence of c. + -v20=permute pattern + */ +-ENTRY(__strrchr_vx) ++ENTRY(STRRCHR_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -176,5 +178,15 @@ ENTRY(__strrchr_vx) + .Lpermute_mask: + .byte 0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08 + .byte 0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00 +-END(__strrchr_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(STRRCHR_Z13) ++ ++# if ! HAVE_STRRCHR_IFUNC ++strong_alias (STRRCHR_Z13, strrchr) ++weak_alias (strrchr, rindex) ++# endif ++ ++# if ! HAVE_STRRCHR_C && defined SHARED && IS_IN (libc) ++strong_alias (STRRCHR_Z13, __GI_strrchr) ++# endif ++ ++#endif /* HAVE_STRRCHR_Z13 */ +diff --git a/sysdeps/s390/multiarch/strrchr.c b/sysdeps/s390/strrchr.c +similarity index 66% +rename from sysdeps/s390/multiarch/strrchr.c +rename to sysdeps/s390/strrchr.c +index e00e25a3a4f51b1e..9a8cecff0b29c057 100644 +--- a/sysdeps/s390/multiarch/strrchr.c ++++ b/sysdeps/s390/strrchr.c +@@ -16,15 +16,26 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRRCHR_IFUNC + # define strrchr __redirect_strrchr + # include + # undef strrchr + # include + +-s390_vx_libc_ifunc2_redirected (__redirect_strrchr, __strrchr, strrchr) +-weak_alias (strrchr, rindex); ++# if HAVE_STRRCHR_C ++extern __typeof (__redirect_strrchr) STRRCHR_C attribute_hidden; ++# endif ++ ++# if HAVE_STRRCHR_Z13 ++extern __typeof (__redirect_strrchr) STRRCHR_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (__redirect_strrchr, strrchr, ++ (HAVE_STRRCHR_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRRCHR_Z13 ++ : STRRCHR_DEFAULT ++ ) ++weak_alias (strrchr, rindex) ++#endif /* HAVE_STRRCHR_IFUNC */ diff --git a/glibc-rh1659438-29.patch b/glibc-rh1659438-29.patch new file mode 100755 index 0000000..edb4940 --- /dev/null +++ b/glibc-rh1659438-29.patch @@ -0,0 +1,263 @@ +commit 483fc56978d11c7118326f92ea678bea2f092300 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:15 2018 +0100 + + S390: Refactor strspn ifunc handling. + + The ifunc handling for strspn is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strspn variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strspn variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strspn. + * sysdeps/s390/multiarch/strspn-c.c: Move to ... + * sysdeps/s390/strspn-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strspn-vx.S: Move to ... + * sysdeps/s390/strspn-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strspn.c: Move to ... + * sysdeps/s390/strspn.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strspn.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 3ad44c997e9f1f6b..c0a402117197b87f 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -49,5 +49,6 @@ sysdep_routines += bzero memset memset-z900 \ + strncmp strncmp-vx strncmp-c \ + strchr strchr-vx strchr-c \ + strchrnul strchrnul-vx strchrnul-c \ +- strrchr strrchr-vx strrchr-c ++ strrchr strrchr-vx strrchr-c \ ++ strspn strspn-vx strspn-c + endif +diff --git a/sysdeps/s390/ifunc-strspn.h b/sysdeps/s390/ifunc-strspn.h +new file mode 100644 +index 0000000000000000..1152ba1f3d3b9b62 +--- /dev/null ++++ b/sysdeps/s390/ifunc-strspn.h +@@ -0,0 +1,52 @@ ++/* strspn variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRSPN_IFUNC 1 ++#else ++# define HAVE_STRSPN_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRSPN_IFUNC_AND_VX_SUPPORT HAVE_STRSPN_IFUNC ++#else ++# define HAVE_STRSPN_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRSPN_DEFAULT STRSPN_Z13 ++# define HAVE_STRSPN_C 0 ++# define HAVE_STRSPN_Z13 1 ++#else ++# define STRSPN_DEFAULT STRSPN_C ++# define HAVE_STRSPN_C 1 ++# define HAVE_STRSPN_Z13 HAVE_STRSPN_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRSPN_C ++# define STRSPN_C __strspn_c ++#else ++# define STRSPN_C NULL ++#endif ++ ++#if HAVE_STRSPN_Z13 ++# define STRSPN_Z13 __strspn_vx ++#else ++# define STRSPN_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index c8267555585b617e..9b141e338ca551ec 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strspn strspn-vx strspn-c \ +- strpbrk strpbrk-vx strpbrk-c \ ++sysdep_routines += strpbrk strpbrk-vx strpbrk-c \ + strcspn strcspn-vx strcspn-c \ + memchr memchr-vx \ + rawmemchr rawmemchr-vx rawmemchr-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 60cd705ffa4e2c35..c39e1f793aad530c 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -333,6 +334,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRRCHR_IFUNC */ + ++#if HAVE_STRSPN_IFUNC ++ IFUNC_IMPL (i, name, strspn, ++# if HAVE_STRSPN_Z13 ++ IFUNC_IMPL_ADD (array, i, strspn, ++ dl_hwcap & HWCAP_S390_VX, STRSPN_Z13) ++# endif ++# if HAVE_STRSPN_C ++ IFUNC_IMPL_ADD (array, i, strspn, 1, STRSPN_C) ++# endif ++ ) ++#endif /* HAVE_STRSPN_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -367,7 +380,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcsrchr); + +- IFUNC_VX_IMPL (strspn); + IFUNC_VX_IMPL (wcsspn); + + IFUNC_VX_IMPL (strpbrk); +diff --git a/sysdeps/s390/multiarch/strspn-c.c b/sysdeps/s390/strspn-c.c +similarity index 78% +rename from sysdeps/s390/multiarch/strspn-c.c +rename to sysdeps/s390/strspn-c.c +index 0efe61bfb2f89caf..506f6683212f03ab 100644 +--- a/sysdeps/s390/multiarch/strspn-c.c ++++ b/sysdeps/s390/strspn-c.c +@@ -16,13 +16,17 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define STRSPN __strspn_c +-# ifdef SHARED +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) \ ++#include ++ ++#if HAVE_STRSPN_C ++# if HAVE_STRSPN_IFUNC ++# define STRSPN STRSPN_C ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) \ + __hidden_ver1 (__strspn_c, __GI_strspn, __strspn_c); +-# endif /* SHARED */ ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/strspn-vx.S b/sysdeps/s390/strspn-vx.S +similarity index 97% +rename from sysdeps/s390/multiarch/strspn-vx.S +rename to sysdeps/s390/strspn-vx.S +index 6aa823e63b1189c3..ae5529b567ee7435 100644 +--- a/sysdeps/s390/multiarch/strspn-vx.S ++++ b/sysdeps/s390/strspn-vx.S +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRSPN_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -57,7 +59,7 @@ + otherwise =0; + r9: loaded byte count of vlbb accept-string + */ +-ENTRY(__strspn_vx) ++ENTRY(STRSPN_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -252,5 +254,14 @@ ENTRY(__strspn_vx) + Check for zero is in jump-target. */ + j .Lslow_next_acc_notonbb /* ... and search for zero in + fully loaded vreg again. */ +-END(__strspn_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(STRSPN_Z13) ++ ++# if ! HAVE_STRSPN_IFUNC ++strong_alias (STRSPN_Z13, strspn) ++# endif ++ ++# if ! HAVE_STRSPN_C && defined SHARED && IS_IN (libc) ++strong_alias (STRSPN_Z13, __GI_strspn) ++# endif ++ ++#endif /* HAVE_STRSPN_Z13 */ +diff --git a/sysdeps/s390/multiarch/strspn.c b/sysdeps/s390/strspn.c +similarity index 70% +rename from sysdeps/s390/multiarch/strspn.c +rename to sysdeps/s390/strspn.c +index bedbe98cfc4ab14d..91401fdaf89ed8a2 100644 +--- a/sysdeps/s390/multiarch/strspn.c ++++ b/sysdeps/s390/strspn.c +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRSPN_IFUNC + # define strspn __redirect_strspn + /* Omit the strspn inline definitions because it would redefine strspn. */ + # define __NO_STRING_INLINES +@@ -24,8 +26,17 @@ + # undef strspn + # include + +-s390_vx_libc_ifunc2_redirected (__redirect_strspn, __strspn, strspn) ++# if HAVE_STRSPN_C ++extern __typeof (__redirect_strspn) STRSPN_C attribute_hidden; ++# endif ++ ++# if HAVE_STRSPN_Z13 ++extern __typeof (__redirect_strspn) STRSPN_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (__redirect_strspn, strspn, ++ (HAVE_STRSPN_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRSPN_Z13 ++ : STRSPN_DEFAULT ++ ) ++#endif /* HAVE_STRSPN_IFUNC */ diff --git a/glibc-rh1659438-3.patch b/glibc-rh1659438-3.patch new file mode 100755 index 0000000..161448c --- /dev/null +++ b/glibc-rh1659438-3.patch @@ -0,0 +1,440 @@ +commit 5f1743d118047ff1fbefe713f2397090e0418deb +Author: Stefan Liebler +Date: Tue Dec 18 13:57:04 2018 +0100 + + S390: Unify 31/64bit memset. + + The implementation of memset for s390-32 (31bit) and + s390-64 (64bit) is nearly the same. + This patch unifies it for maintability reasons. + + __memset_z10 and __memset_z196 differs between 31 and 64bit: + -31bit needs .machinemode "zarch_nohighgprs" and llgfr %r4,%r4 + -lr vs lgr and some other instructions: + But lgr and co can be also used on 31bit as this ifunc variant + is only called if we are on a zarch machine. + + __memset_default differs between 31 and 64bit: + -Some 31bit vs 64bit instructions (e.g. ltr vs ltgr. + Solved with 31/64 specific instruction macros). + -The address of mvc instruction is setup in different ways + (larl vs bras). Solved with #if defined __s390x__. + + Otherwise 31/64bit implementation has the same structure of the code. + + ChangeLog: + + * sysdeps/s390/s390-64/memset.S: Move to ... + * sysdeps/s390/memset.S: ... here. + Adjust to be usable for 31/64bit. + * sysdeps/s390/s390-32/memset.S: Delete File. + * sysdeps/s390/multiarch/Makefile (sysdep_routines): Add memset. + * sysdeps/s390/s390-32/multiarch/Makefile (sysdep_routines): + Remove memset. + * sysdeps/s390/s390-64/multiarch/Makefile: Likewise. + * sysdeps/s390/s390-64/multiarch/memset-s390x.S: Move to ... + * sysdeps/s390/multiarch/memset-s390x.S: ... here. + Adjust to be usable for 31/64bit. + * sysdeps/s390/s390-32/multiarch/memset-s390.S: Delete File. + * sysdeps/s390/s390-64/multiarch/memset.c: Move to ... + * sysdeps/s390/multiarch/memset.c: ... here. + * sysdeps/s390/s390-32/multiarch/memset.c: Delete File. + +diff --git a/sysdeps/s390/s390-64/memset.S b/sysdeps/s390/memset.S +similarity index 58% +rename from sysdeps/s390/s390-64/memset.S +rename to sysdeps/s390/memset.S +index 8799c6592ce2dacf..72e7c5a42efbaf6c 100644 +--- a/sysdeps/s390/s390-64/memset.S ++++ b/sysdeps/s390/memset.S +@@ -1,4 +1,4 @@ +-/* Set a block of memory to some byte value. 64 bit S/390 version. ++/* Set a block of memory to some byte value. 31/64 bit S/390 version. + Copyright (C) 2001-2018 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU C Library. +@@ -28,33 +28,60 @@ + + .text + ++#if defined __s390x__ ++# define LTGR ltgr ++# define CGHI cghi ++# define LGR lgr ++# define AGHI aghi ++# define BRCTG brctg ++#else ++# define LTGR ltr ++# define CGHI chi ++# define LGR lr ++# define AGHI ahi ++# define BRCTG brct ++#endif /* ! defined __s390x__ */ ++ + #ifdef USE_MULTIARCH + ENTRY(__memset_default) + #else + ENTRY(memset) + #endif ++#if defined __s390x__ + .machine "z900" +- ltgr %r4,%r4 +- je .L_Z900_4 ++#else ++ .machine "g5" ++#endif /* ! defined __s390x__ */ ++ LTGR %r4,%r4 ++ je .L_Z900_G5_4 + stc %r3,0(%r2) +- cghi %r4,1 +- lgr %r1,%r2 +- je .L_Z900_4 +- aghi %r4,-2 ++ CGHI %r4,1 ++ LGR %r1,%r2 ++ je .L_Z900_G5_4 ++ AGHI %r4,-2 ++#if defined __s390x__ ++ larl %r5,.L_Z900_G5_18 + srlg %r3,%r4,8 +- ltgr %r3,%r3 +- jne .L_Z900_14 +-.L_Z900_3: +- larl %r3,.L_Z900_18 +- ex %r4,0(%r3) +-.L_Z900_4: ++# define Z900_G5_EX_D 0 ++#else ++ basr %r5,0 ++.L_Z900_G5_19: ++# define Z900_G5_EX_D .L_Z900_G5_18-.L_Z900_G5_19 ++ lr %r3,%r4 ++ srl %r3,8 ++#endif /* ! defined __s390x__ */ ++ LTGR %r3,%r3 ++ jne .L_Z900_G5_14 ++.L_Z900_G5_3: ++ ex %r4,Z900_G5_EX_D(%r5) ++.L_Z900_G5_4: + br %r14 +-.L_Z900_14: ++.L_Z900_G5_14: + mvc 1(256,%r1),0(%r1) + la %r1,256(%r1) +- brctg %r3,.L_Z900_14 +- j .L_Z900_3 +-.L_Z900_18: ++ BRCTG %r3,.L_Z900_G5_14 ++ j .L_Z900_G5_3 ++.L_Z900_G5_18: + mvc 1(1,%r1),0(%r1) + #ifdef USE_MULTIARCH + END(__memset_default) +@@ -62,3 +89,9 @@ END(__memset_default) + END(memset) + libc_hidden_builtin_def (memset) + #endif ++ ++#undef LTGR ++#undef CGHI ++#undef LGR ++#undef AGHI ++#undef BRCTG +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index c893ebc5659fd4ae..93ad21bfa2686ee5 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -19,7 +19,8 @@ sysdep_routines += strlen strlen-vx strlen-c \ + rawmemchr rawmemchr-vx rawmemchr-c \ + memccpy memccpy-vx memccpy-c \ + memrchr memrchr-vx memrchr-c \ +- mempcpy ++ mempcpy \ ++ memset memset-s390x + endif + + ifeq ($(subdir),wcsmbs) +diff --git a/sysdeps/s390/s390-64/multiarch/memset-s390x.S b/sysdeps/s390/multiarch/memset-s390x.S +similarity index 90% +rename from sysdeps/s390/s390-64/multiarch/memset-s390x.S +rename to sysdeps/s390/multiarch/memset-s390x.S +index 0c5aaef34fdf47e6..aca3ac3fda1dd228 100644 +--- a/sysdeps/s390/s390-64/multiarch/memset-s390x.S ++++ b/sysdeps/s390/multiarch/memset-s390x.S +@@ -1,4 +1,4 @@ +-/* Set a block of memory to some byte value. 64 bit S/390 version. ++/* Set a block of memory to some byte value. 31/64 bit S/390 version. + Copyright (C) 2012-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + +@@ -31,6 +31,10 @@ + + ENTRY(__memset_z196) + .machine "z196" ++ .machinemode "zarch_nohighgprs" ++# if !defined __s390x__ ++ llgfr %r4,%r4 ++# endif /* !defined __s390x__ */ + ltgr %r4,%r4 + je .L_Z196_4 + stc %r3,0(%r2) +@@ -61,6 +65,10 @@ END(__memset_z196) + + ENTRY(__memset_z10) + .machine "z10" ++ .machinemode "zarch_nohighgprs" ++# if !defined __s390x__ ++ llgfr %r4,%r4 ++# endif /* !defined __s390x__ */ + cgije %r4,0,.L_Z10_4 + stc %r3,0(%r2) + lgr %r1,%r2 +diff --git a/sysdeps/s390/s390-32/multiarch/memset.c b/sysdeps/s390/multiarch/memset.c +similarity index 100% +rename from sysdeps/s390/s390-32/multiarch/memset.c +rename to sysdeps/s390/multiarch/memset.c +diff --git a/sysdeps/s390/s390-32/memset.S b/sysdeps/s390/s390-32/memset.S +deleted file mode 100644 +index 57f08e1cae1abd01..0000000000000000 +--- a/sysdeps/s390/s390-32/memset.S ++++ /dev/null +@@ -1,65 +0,0 @@ +-/* Set a block of memory to some byte value. For IBM S390 +- Copyright (C) 2012-2018 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 +- . */ +- +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +-/* INPUT PARAMETERS +- %r2 = address to memory area +- %r3 = byte to fill memory with +- %r4 = number of bytes to fill. */ +- +- .text +- +-#ifdef USE_MULTIARCH +-ENTRY(__memset_default) +-#else +-ENTRY(memset) +-#endif +- .machine "g5" +- basr %r5,0 +-.L_G5_19: +- ltr %r4,%r4 +- je .L_G5_4 +- stc %r3,0(%r2) +- chi %r4,1 +- lr %r1,%r2 +- je .L_G5_4 +- ahi %r4,-2 +- lr %r3,%r4 +- srl %r3,8 +- ltr %r3,%r3 +- jne .L_G5_14 +- ex %r4,.L_G5_20-.L_G5_19(%r5) +-.L_G5_4: +- br %r14 +-.L_G5_14: +- mvc 1(256,%r1),0(%r1) +- la %r1,256(%r1) +- brct %r3,.L_G5_14 +- ex %r4,.L_G5_20-.L_G5_19(%r5) +- j .L_G5_4 +-.L_G5_20: +- mvc 1(1,%r1),0(%r1) +-#ifdef USE_MULTIARCH +-END(__memset_default) +-#else +-END(memset) +-libc_hidden_builtin_def (memset) +-#endif +diff --git a/sysdeps/s390/s390-32/multiarch/Makefile b/sysdeps/s390/s390-32/multiarch/Makefile +index f8aee14bbd4736ad..4b11e28656ac19ab 100644 +--- a/sysdeps/s390/s390-32/multiarch/Makefile ++++ b/sysdeps/s390/s390-32/multiarch/Makefile +@@ -1,4 +1,3 @@ + ifeq ($(subdir),string) +-sysdep_routines += memset memset-s390 memcpy memcpy-s390 \ +- memcmp memcmp-s390 ++sysdep_routines += memcpy memcpy-s390 memcmp memcmp-s390 + endif +diff --git a/sysdeps/s390/s390-32/multiarch/memset-s390.S b/sysdeps/s390/s390-32/multiarch/memset-s390.S +deleted file mode 100644 +index b092073d6bef6b56..0000000000000000 +--- a/sysdeps/s390/s390-32/multiarch/memset-s390.S ++++ /dev/null +@@ -1,116 +0,0 @@ +-/* Set a block of memory to some byte value. 32 bit S/390 version. +- Copyright (C) 2012-2018 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 +- . */ +- +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +-/* INPUT PARAMETERS +- %r2 = address of memory area +- %r3 = byte to fill memory with +- %r4 = number of bytes to fill. */ +- +- .text +- +-#if IS_IN (libc) +- +-ENTRY(__memset_z196) +- .machine "z196" +- .machinemode "zarch_nohighgprs" +- llgfr %r4,%r4 +- ltgr %r4,%r4 +- je .L_Z196_4 +- stc %r3,0(%r2) +- lr %r1,%r2 +- cghi %r4,1 +- je .L_Z196_4 +- aghi %r4,-2 +- srlg %r5,%r4,8 +- ltgr %r5,%r5 +- jne .L_Z196_1 +-.L_Z196_3: +- exrl %r4,.L_Z196_17 +-.L_Z196_4: +- br %r14 +-.L_Z196_1: +- cgfi %r5,1048576 +- jh __memset_mvcle # Switch to mvcle for >256MB +-.L_Z196_2: +- pfd 2,1024(%r1) +- mvc 1(256,%r1),0(%r1) +- aghi %r5,-1 +- la %r1,256(%r1) +- jne .L_Z196_2 +- j .L_Z196_3 +-.L_Z196_17: +- mvc 1(1,%r1),0(%r1) +-END(__memset_z196) +- +-ENTRY(__memset_z10) +- .machine "z10" +- .machinemode "zarch_nohighgprs" +- llgfr %r4,%r4 +- cgije %r4,0,.L_Z10_4 +- stc %r3,0(%r2) +- lr %r1,%r2 +- cgije %r4,1,.L_Z10_4 +- aghi %r4,-2 +- srlg %r5,%r4,8 +- cgijlh %r5,0,.L_Z10_15 +-.L_Z10_3: +- exrl %r4,.L_Z10_18 +-.L_Z10_4: +- br %r14 +-.L_Z10_15: +- cgfi %r5,163840 # Switch to mvcle for >40MB +- jh __memset_mvcle +-.L_Z10_14: +- pfd 2,1024(%r1) +- mvc 1(256,%r1),0(%r1) +- la %r1,256(%r1) +- brctg %r5,.L_Z10_14 +- j .L_Z10_3 +-.L_Z10_18: +- mvc 1(1,%r1),0(%r1) +-END(__memset_z10) +- +-ENTRY(__memset_mvcle) +- ahi %r4,2 # take back the change done by the caller +- lr %r0,%r2 # save source address +- lr %r1,%r3 # move pad byte to R1 +- lr %r3,%r4 +- sr %r4,%r4 # no source for MVCLE, only a pad byte +- sr %r5,%r5 +-.L0: mvcle %r2,%r4,0(%r1) # thats it, MVCLE is your friend +- jo .L0 +- lr %r2,%r0 # return value is source address +-.L1: +- br %r14 +-END(__memset_mvcle) +- +-#endif /* IS_IN (libc) */ +- +-#include "../memset.S" +- +-#if !IS_IN (libc) +-.globl memset +-.set memset,__memset_default +-#elif defined SHARED && IS_IN (libc) +-.globl __GI_memset +-.set __GI_memset,__memset_default +-#endif +diff --git a/sysdeps/s390/s390-64/multiarch/Makefile b/sysdeps/s390/s390-64/multiarch/Makefile +index 91053b536420aabb..e4870c7ee177ad0d 100644 +--- a/sysdeps/s390/s390-64/multiarch/Makefile ++++ b/sysdeps/s390/s390-64/multiarch/Makefile +@@ -1,4 +1,3 @@ + ifeq ($(subdir),string) +-sysdep_routines += memset memset-s390x memcpy memcpy-s390x \ +- memcmp memcmp-s390x ++sysdep_routines += memcpy memcpy-s390x memcmp memcmp-s390x + endif +diff --git a/sysdeps/s390/s390-64/multiarch/memset.c b/sysdeps/s390/s390-64/multiarch/memset.c +deleted file mode 100644 +index 760b3e9df201b8b4..0000000000000000 +--- a/sysdeps/s390/s390-64/multiarch/memset.c ++++ /dev/null +@@ -1,26 +0,0 @@ +-/* Multiple versions of memset. +- Copyright (C) 2015-2018 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 +- . */ +- +-#if IS_IN (libc) +-# define memset __redirect_memset +-# include +-# undef memset +-# include +- +-s390_libc_ifunc (__redirect_memset, __memset, memset) +-#endif diff --git a/glibc-rh1659438-30.patch b/glibc-rh1659438-30.patch new file mode 100755 index 0000000..9e7db8e --- /dev/null +++ b/glibc-rh1659438-30.patch @@ -0,0 +1,264 @@ +commit 572cca93fafa59d641c11372a9556722d95b038c +Author: Stefan Liebler +Date: Tue Dec 18 13:57:15 2018 +0100 + + S390: Refactor strpbrk ifunc handling. + + The ifunc handling for strpbrk is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strpbrk variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strpbrk variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strpbrk. + * sysdeps/s390/multiarch/strpbrk-c.c: Move to ... + * sysdeps/s390/strpbrk-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strpbrk-vx.S: Move to ... + * sysdeps/s390/strpbrk-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strpbrk.c: Move to ... + * sysdeps/s390/strpbrk.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strpbrk.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index c0a402117197b87f..a21fa7507b1d64a1 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -50,5 +50,6 @@ sysdep_routines += bzero memset memset-z900 \ + strchr strchr-vx strchr-c \ + strchrnul strchrnul-vx strchrnul-c \ + strrchr strrchr-vx strrchr-c \ +- strspn strspn-vx strspn-c ++ strspn strspn-vx strspn-c \ ++ strpbrk strpbrk-vx strpbrk-c + endif +diff --git a/sysdeps/s390/ifunc-strpbrk.h b/sysdeps/s390/ifunc-strpbrk.h +new file mode 100644 +index 0000000000000000..4a3138c6bf377286 +--- /dev/null ++++ b/sysdeps/s390/ifunc-strpbrk.h +@@ -0,0 +1,52 @@ ++/* strpbrk variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRPBRK_IFUNC 1 ++#else ++# define HAVE_STRPBRK_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRPBRK_IFUNC_AND_VX_SUPPORT HAVE_STRPBRK_IFUNC ++#else ++# define HAVE_STRPBRK_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRPBRK_DEFAULT STRPBRK_Z13 ++# define HAVE_STRPBRK_C 0 ++# define HAVE_STRPBRK_Z13 1 ++#else ++# define STRPBRK_DEFAULT STRPBRK_C ++# define HAVE_STRPBRK_C 1 ++# define HAVE_STRPBRK_Z13 HAVE_STRPBRK_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRPBRK_C ++# define STRPBRK_C __strpbrk_c ++#else ++# define STRPBRK_C NULL ++#endif ++ ++#if HAVE_STRPBRK_Z13 ++# define STRPBRK_Z13 __strpbrk_vx ++#else ++# define STRPBRK_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 9b141e338ca551ec..1a3fed9fc88012d1 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strpbrk strpbrk-vx strpbrk-c \ +- strcspn strcspn-vx strcspn-c \ ++sysdep_routines += strcspn strcspn-vx strcspn-c \ + memchr memchr-vx \ + rawmemchr rawmemchr-vx rawmemchr-c \ + memccpy memccpy-vx memccpy-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index c39e1f793aad530c..8e23416730f8a8d5 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -40,6 +40,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -346,6 +347,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRSPN_IFUNC */ + ++#if HAVE_STRPBRK_IFUNC ++ IFUNC_IMPL (i, name, strpbrk, ++# if HAVE_STRPBRK_Z13 ++ IFUNC_IMPL_ADD (array, i, strpbrk, ++ dl_hwcap & HWCAP_S390_VX, STRPBRK_Z13) ++# endif ++# if HAVE_STRPBRK_C ++ IFUNC_IMPL_ADD (array, i, strpbrk, 1, STRPBRK_C) ++# endif ++ ) ++#endif /* HAVE_STRPBRK_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -382,7 +395,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcsspn); + +- IFUNC_VX_IMPL (strpbrk); + IFUNC_VX_IMPL (wcspbrk); + + IFUNC_VX_IMPL (strcspn); +diff --git a/sysdeps/s390/multiarch/strpbrk-c.c b/sysdeps/s390/strpbrk-c.c +similarity index 73% +rename from sysdeps/s390/multiarch/strpbrk-c.c +rename to sysdeps/s390/strpbrk-c.c +index 2c0517aeb52985b3..70cc5db672adb6c9 100644 +--- a/sysdeps/s390/multiarch/strpbrk-c.c ++++ b/sysdeps/s390/strpbrk-c.c +@@ -16,13 +16,17 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define STRPBRK __strpbrk_c +-# ifdef SHARED +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) \ +- __hidden_ver1 (__strpbrk_c, __GI_strpbrk, __strpbrk_c); +-# endif /* SHARED */ ++#include ++ ++#if HAVE_STRPBRK_C ++# if HAVE_STRPBRK_IFUNC ++# define STRPBRK STRPBRK_C ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) \ ++ __hidden_ver1 (__strpbrk_c, __GI_strpbrk, __strpbrk_c); ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/strpbrk-vx.S b/sysdeps/s390/strpbrk-vx.S +similarity index 97% +rename from sysdeps/s390/multiarch/strpbrk-vx.S +rename to sysdeps/s390/strpbrk-vx.S +index e19c550ed404a9a8..0fc7dc143337779f 100644 +--- a/sysdeps/s390/multiarch/strpbrk-vx.S ++++ b/sysdeps/s390/strpbrk-vx.S +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRPBRK_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -59,7 +61,7 @@ + otherwise =0; + r9: loaded byte count of vlbb accept-string + */ +-ENTRY(__strpbrk_vx) ++ENTRY(STRPBRK_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -298,5 +300,14 @@ ENTRY(__strpbrk_vx) + vlgvg %r9,%v31,1 + lgr %r2,%r1 + br %r14 +-END(__strpbrk_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(STRPBRK_Z13) ++ ++# if ! HAVE_STRPBRK_IFUNC ++strong_alias (STRPBRK_Z13, strpbrk) ++# endif ++ ++# if ! HAVE_STRPBRK_C && defined SHARED && IS_IN (libc) ++strong_alias (STRPBRK_Z13, __GI_strpbrk) ++# endif ++ ++#endif /* HAVE_STRPBRK_Z13 */ +diff --git a/sysdeps/s390/multiarch/strpbrk.c b/sysdeps/s390/strpbrk.c +similarity index 70% +rename from sysdeps/s390/multiarch/strpbrk.c +rename to sysdeps/s390/strpbrk.c +index 11afc268f702ce09..41ce00a1aedf0020 100644 +--- a/sysdeps/s390/multiarch/strpbrk.c ++++ b/sysdeps/s390/strpbrk.c +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRPBRK_IFUNC + # define strpbrk __redirect_strpbrk + /* Omit the strpbrk inline definitions because it would redefine strpbrk. */ + # define __NO_STRING_INLINES +@@ -24,8 +26,17 @@ + # undef strpbrk + # include + +-s390_vx_libc_ifunc2_redirected (__redirect_strpbrk, __strpbrk, strpbrk) ++# if HAVE_STRPBRK_C ++extern __typeof (__redirect_strpbrk) STRPBRK_C attribute_hidden; ++# endif ++ ++# if HAVE_STRPBRK_Z13 ++extern __typeof (__redirect_strpbrk) STRPBRK_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (__redirect_strpbrk, strpbrk, ++ (HAVE_STRPBRK_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRPBRK_Z13 ++ : STRPBRK_DEFAULT ++ ) ++#endif /* HAVE_STRPBRK_IFUNC */ diff --git a/glibc-rh1659438-31.patch b/glibc-rh1659438-31.patch new file mode 100755 index 0000000..e448fc9 --- /dev/null +++ b/glibc-rh1659438-31.patch @@ -0,0 +1,264 @@ +commit 5d2ec20a997b87c1667e0e71b3ff1e9df96eac15 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:15 2018 +0100 + + S390: Refactor strcspn ifunc handling. + + The ifunc handling for strcspn is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove strcspn variants. + * sysdeps/s390/Makefile (sysdep_routines): Add strcspn variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for strcspn. + * sysdeps/s390/multiarch/strcspn-c.c: Move to ... + * sysdeps/s390/strcspn-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strcspn-vx.S: Move to ... + * sysdeps/s390/strcspn-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/strcspn.c: Move to ... + * sysdeps/s390/strcspn.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-strcspn.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index a21fa7507b1d64a1..092d55826fbd15a5 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -51,5 +51,6 @@ sysdep_routines += bzero memset memset-z900 \ + strchrnul strchrnul-vx strchrnul-c \ + strrchr strrchr-vx strrchr-c \ + strspn strspn-vx strspn-c \ +- strpbrk strpbrk-vx strpbrk-c ++ strpbrk strpbrk-vx strpbrk-c \ ++ strcspn strcspn-vx strcspn-c + endif +diff --git a/sysdeps/s390/ifunc-strcspn.h b/sysdeps/s390/ifunc-strcspn.h +new file mode 100644 +index 0000000000000000..9b7032509a2fb9a8 +--- /dev/null ++++ b/sysdeps/s390/ifunc-strcspn.h +@@ -0,0 +1,52 @@ ++/* strcspn variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_STRCSPN_IFUNC 1 ++#else ++# define HAVE_STRCSPN_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_STRCSPN_IFUNC_AND_VX_SUPPORT HAVE_STRCSPN_IFUNC ++#else ++# define HAVE_STRCSPN_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define STRCSPN_DEFAULT STRCSPN_Z13 ++# define HAVE_STRCSPN_C 0 ++# define HAVE_STRCSPN_Z13 1 ++#else ++# define STRCSPN_DEFAULT STRCSPN_C ++# define HAVE_STRCSPN_C 1 ++# define HAVE_STRCSPN_Z13 HAVE_STRCSPN_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_STRCSPN_C ++# define STRCSPN_C __strcspn_c ++#else ++# define STRCSPN_C NULL ++#endif ++ ++#if HAVE_STRCSPN_Z13 ++# define STRCSPN_Z13 __strcspn_vx ++#else ++# define STRCSPN_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 1a3fed9fc88012d1..1578f21af4a1bd06 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += strcspn strcspn-vx strcspn-c \ +- memchr memchr-vx \ ++sysdep_routines += memchr memchr-vx \ + rawmemchr rawmemchr-vx rawmemchr-c \ + memccpy memccpy-vx memccpy-c \ + memrchr memrchr-vx memrchr-c +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 8e23416730f8a8d5..2d48c99c8d5663fe 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -359,6 +360,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRPBRK_IFUNC */ + ++#if HAVE_STRCSPN_IFUNC ++ IFUNC_IMPL (i, name, strcspn, ++# if HAVE_STRCSPN_Z13 ++ IFUNC_IMPL_ADD (array, i, strcspn, ++ dl_hwcap & HWCAP_S390_VX, STRCSPN_Z13) ++# endif ++# if HAVE_STRCSPN_C ++ IFUNC_IMPL_ADD (array, i, strcspn, 1, STRCSPN_C) ++# endif ++ ) ++#endif /* HAVE_STRCSPN_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -397,7 +410,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcspbrk); + +- IFUNC_VX_IMPL (strcspn); + IFUNC_VX_IMPL (wcscspn); + + IFUNC_VX_IMPL (memchr); +diff --git a/sysdeps/s390/multiarch/strcspn-c.c b/sysdeps/s390/strcspn-c.c +similarity index 73% +rename from sysdeps/s390/multiarch/strcspn-c.c +rename to sysdeps/s390/strcspn-c.c +index 7b454f5b56077abc..9f51f92bdbd49a67 100644 +--- a/sysdeps/s390/multiarch/strcspn-c.c ++++ b/sysdeps/s390/strcspn-c.c +@@ -16,13 +16,17 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define STRCSPN __strcspn_c +-# ifdef SHARED +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) \ +- __hidden_ver1 (__strcspn_c, __GI_strcspn, __strcspn_c); +-# endif /* SHARED */ ++#include ++ ++#if HAVE_STRCSPN_C ++# if HAVE_STRCSPN_IFUNC ++# define STRCSPN STRCSPN_C ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) \ ++ __hidden_ver1 (__strcspn_c, __GI_strcspn, __strcspn_c); ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/strcspn-vx.S b/sysdeps/s390/strcspn-vx.S +similarity index 97% +rename from sysdeps/s390/multiarch/strcspn-vx.S +rename to sysdeps/s390/strcspn-vx.S +index ea1668742bd1c7ff..ff5b1be549e6e210 100644 +--- a/sysdeps/s390/multiarch/strcspn-vx.S ++++ b/sysdeps/s390/strcspn-vx.S +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRCSPN_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -58,7 +60,7 @@ + otherwise =0; + r9: loaded byte count of vlbb reject-string + */ +-ENTRY(__strcspn_vx) ++ENTRY(STRCSPN_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -277,5 +279,14 @@ ENTRY(__strcspn_vx) + vlgvg %r8,%v31,0 + vlgvg %r9,%v31,1 + br %r14 +-END(__strcspn_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(STRCSPN_Z13) ++ ++# if ! HAVE_STRCSPN_IFUNC ++strong_alias (STRCSPN_Z13, strcspn) ++# endif ++ ++# if ! HAVE_STRCSPN_C && defined SHARED && IS_IN (libc) ++strong_alias (STRCSPN_Z13, __GI_strcspn) ++# endif ++ ++#endif /* HAVE_STRCSPN_Z13 */ +diff --git a/sysdeps/s390/multiarch/strcspn.c b/sysdeps/s390/strcspn.c +similarity index 70% +rename from sysdeps/s390/multiarch/strcspn.c +rename to sysdeps/s390/strcspn.c +index 418ffcdded76fe50..a3f35d39c50dd5e5 100644 +--- a/sysdeps/s390/multiarch/strcspn.c ++++ b/sysdeps/s390/strcspn.c +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_STRCSPN_IFUNC + # define strcspn __redirect_strcspn + /* Omit the strcspn inline definitions because it would redefine strcspn. */ + # define __NO_STRING_INLINES +@@ -24,8 +26,17 @@ + # undef strcspn + # include + +-s390_vx_libc_ifunc2_redirected (__redirect_strcspn, __strcspn, strcspn) ++# if HAVE_STRCSPN_C ++extern __typeof (__redirect_strcspn) STRCSPN_C attribute_hidden; ++# endif ++ ++# if HAVE_STRCSPN_Z13 ++extern __typeof (__redirect_strcspn) STRCSPN_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (__redirect_strcspn, strcspn, ++ (HAVE_STRCSPN_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? STRCSPN_Z13 ++ : STRCSPN_DEFAULT ++ ) ++#endif /* HAVE_STRCSPN_IFUNC */ diff --git a/glibc-rh1659438-32.patch b/glibc-rh1659438-32.patch new file mode 100755 index 0000000..85327b9 --- /dev/null +++ b/glibc-rh1659438-32.patch @@ -0,0 +1,403 @@ +commit 581a051c2e09a847332d4750f6132de0f0ad15b6 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:16 2018 +0100 + + S390: Refactor memchr ifunc handling. + + The ifunc handling for memchr is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + Note: The fallback s390-32/s390-64 ifunc variants with srst instruction + are now moved to the unified memchr-z900.S file which can be used for + 31/64bit. The s390-32/s390-64 files multiarch/memchr.c and memchr.S + are deleted. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove memchr variants. + * sysdeps/s390/Makefile (sysdep_routines): Add memchr variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for memchr. + * sysdeps/s390/multiarch/memchr-vx.S: Move to ... + * sysdeps/s390/memchr-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/memchr.c: Move to ... + * sysdeps/s390/memchr.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-memchr.h: New file. + * sysdeps/s390/s390-64/memchr.S: Move to ... + * sysdeps/s390/memchr-z900.S: ... here and adjust to be usable + for 31/64bit and ifunc handling. + * sysdeps/s390/s390-32/multiarch/memchr.c: Delete file. + * sysdeps/s390/s390-64/multiarch/memchr.c: Likewise. + * sysdeps/s390/s390-32/memchr.S: Likewise. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 092d55826fbd15a5..816b2fccdc75e4cf 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -52,5 +52,6 @@ sysdep_routines += bzero memset memset-z900 \ + strrchr strrchr-vx strrchr-c \ + strspn strspn-vx strspn-c \ + strpbrk strpbrk-vx strpbrk-c \ +- strcspn strcspn-vx strcspn-c ++ strcspn strcspn-vx strcspn-c \ ++ memchr memchr-vx memchr-z900 + endif +diff --git a/sysdeps/s390/ifunc-memchr.h b/sysdeps/s390/ifunc-memchr.h +new file mode 100644 +index 0000000000000000..5d1327b45353322b +--- /dev/null ++++ b/sysdeps/s390/ifunc-memchr.h +@@ -0,0 +1,52 @@ ++/* memchr variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_MEMCHR_IFUNC 1 ++#else ++# define HAVE_MEMCHR_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_MEMCHR_IFUNC_AND_VX_SUPPORT HAVE_MEMCHR_IFUNC ++#else ++# define HAVE_MEMCHR_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define MEMCHR_DEFAULT MEMCHR_Z13 ++# define HAVE_MEMCHR_Z900_G5 0 ++# define HAVE_MEMCHR_Z13 1 ++#else ++# define MEMCHR_DEFAULT MEMCHR_Z900_G5 ++# define HAVE_MEMCHR_Z900_G5 1 ++# define HAVE_MEMCHR_Z13 HAVE_MEMCHR_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_MEMCHR_Z900_G5 ++# define MEMCHR_Z900_G5 __memchr_default ++#else ++# define MEMCHR_Z900_G5 NULL ++#endif ++ ++#if HAVE_MEMCHR_Z13 ++# define MEMCHR_Z13 __memchr_vx ++#else ++# define MEMCHR_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/memchr-vx.S b/sysdeps/s390/memchr-vx.S +similarity index 92% +rename from sysdeps/s390/multiarch/memchr-vx.S +rename to sysdeps/s390/memchr-vx.S +index 77d31e0036915665..274e7971ca7e9413 100644 +--- a/sysdeps/s390/multiarch/memchr-vx.S ++++ b/sysdeps/s390/memchr-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_MEMCHR_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -38,7 +39,7 @@ + -v17=index of found c + -v18=c replicated + */ +-ENTRY(__memchr_vx) ++ENTRY(MEMCHR_Z13) + + .machine "z13" + .machinemode "zarch_nohighgprs" +@@ -149,11 +150,14 @@ ENTRY(__memchr_vx) + clgrjl %r0,%r4,.Lloop64 + + j .Llt64 +-END(__memchr_vx) ++END(MEMCHR_Z13) + +-# define memchr __memchr_c +-# undef libc_hidden_builtin_def +-# define libc_hidden_builtin_def(name) strong_alias(__memchr_c, __GI_memchr) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++# if ! HAVE_MEMCHR_IFUNC ++strong_alias (MEMCHR_Z13, __memchr) ++weak_alias (__memchr, memchr) ++# endif + +-#include ++# if ! HAVE_MEMCHR_Z900_G5 && defined SHARED && IS_IN (libc) ++strong_alias (MEMCHR_Z13, __GI_memchr) ++# endif ++#endif +diff --git a/sysdeps/s390/s390-64/memchr.S b/sysdeps/s390/memchr-z900.S +similarity index 63% +rename from sysdeps/s390/s390-64/memchr.S +rename to sysdeps/s390/memchr-z900.S +index a19fcafa147dc338..c016bc41c61be2dc 100644 +--- a/sysdeps/s390/s390-64/memchr.S ++++ b/sysdeps/s390/memchr-z900.S +@@ -1,4 +1,4 @@ +-/* Search a character in a block of memory. 64 bit S/390 version. ++/* Search a character in a block of memory. 31/64 bit S/390 version. + Copyright (C) 2001-2018 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU C Library. +@@ -22,19 +22,42 @@ + %r3 = character to find + %r4 = number of bytes to search. */ + ++#include + #include "sysdep.h" + #include "asm-syntax.h" + ++#if HAVE_MEMCHR_Z900_G5 ++# if defined __s390x__ ++# define SLGR slgr ++# define LGHI lghi ++# define NGR ngr ++# define LGR lgr ++# else ++# define SLGR slr ++# define LGHI lhi ++# define NGR nr ++# define LGR lr ++# endif /* ! defined __s390x__ */ ++ + .text +-ENTRY(memchr) +- lghi %r0,0xff +- ngr %r0,%r3 +- lgr %r1,%r2 ++ENTRY(MEMCHR_Z900_G5) ++ LGHI %r0,0xff ++ NGR %r0,%r3 ++ LGR %r1,%r2 + la %r2,0(%r4,%r1) + 0: srst %r2,%r1 + jo 0b + brc 13,1f +- slgr %r2,%r2 ++ SLGR %r2,%r2 + 1: br %r14 +-END(memchr) +-libc_hidden_builtin_def (memchr) ++END(MEMCHR_Z900_G5) ++ ++# if ! HAVE_MEMCHR_IFUNC ++strong_alias (MEMCHR_Z900_G5, __memchr) ++weak_alias (__memchr, memchr) ++# endif ++ ++# if defined SHARED && IS_IN (libc) ++strong_alias (MEMCHR_Z900_G5, __GI_memchr) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/memchr.c b/sysdeps/s390/memchr.c +similarity index 68% +rename from sysdeps/s390/multiarch/memchr.c +rename to sysdeps/s390/memchr.c +index 3885ebaa4d90ed1a..490f1b66002aae05 100644 +--- a/sysdeps/s390/multiarch/memchr.c ++++ b/sysdeps/s390/memchr.c +@@ -16,12 +16,26 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_MEMCHR_IFUNC + # define memchr __redirect_memchr + # include + # undef memchr + # include + +-s390_vx_libc_ifunc2_redirected (__redirect_memchr, __memchr, memchr) ++# if HAVE_MEMCHR_Z900_G5 ++extern __typeof (__redirect_memchr) MEMCHR_Z900_G5 attribute_hidden; ++# endif ++ ++# if HAVE_MEMCHR_Z13 ++extern __typeof (__redirect_memchr) MEMCHR_Z13 attribute_hidden; ++# endif + ++s390_libc_ifunc_expr (__redirect_memchr, __memchr, ++ (HAVE_MEMCHR_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? MEMCHR_Z13 ++ : MEMCHR_DEFAULT ++ ) ++weak_alias (__memchr, memchr) + #endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 1578f21af4a1bd06..fa1f7b81db912be0 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += memchr memchr-vx \ +- rawmemchr rawmemchr-vx rawmemchr-c \ ++sysdep_routines += rawmemchr rawmemchr-vx rawmemchr-c \ + memccpy memccpy-vx memccpy-c \ + memrchr memrchr-vx memrchr-c + endif +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 2d48c99c8d5663fe..b4be0140424aed69 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -372,6 +373,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_STRCSPN_IFUNC */ + ++#if HAVE_MEMCHR_IFUNC ++ IFUNC_IMPL (i, name, memchr, ++# if HAVE_MEMCHR_Z13 ++ IFUNC_IMPL_ADD (array, i, memchr, ++ dl_hwcap & HWCAP_S390_VX, MEMCHR_Z13) ++# endif ++# if HAVE_MEMCHR_Z900_G5 ++ IFUNC_IMPL_ADD (array, i, memchr, 1, MEMCHR_Z900_G5) ++# endif ++ ) ++#endif /* HAVE_MEMCHR_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -412,7 +425,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wcscspn); + +- IFUNC_VX_IMPL (memchr); + IFUNC_VX_IMPL (wmemchr); + IFUNC_VX_IMPL (rawmemchr); + +diff --git a/sysdeps/s390/s390-32/memchr.S b/sysdeps/s390/s390-32/memchr.S +deleted file mode 100644 +index 54f9b85f578fa1c7..0000000000000000 +--- a/sysdeps/s390/s390-32/memchr.S ++++ /dev/null +@@ -1,41 +0,0 @@ +-/* Search a character in a block of memory. For IBM S390 +- Copyright (C) 2000-2018 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). +- +- 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 +- . */ +- +-/* +- * R2 = address to memory area +- * R3 = character to find +- * R4 = number of bytes to search +- */ +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +- .text +-ENTRY(memchr) +- lhi %r0,0xff +- nr %r0,%r3 +- lr %r1,%r2 +- la %r2,0(%r4,%r1) +-0: srst %r2,%r1 +- jo 0b +- brc 13,1f +- slr %r2,%r2 +-1: br %r14 +-END(memchr) +-libc_hidden_builtin_def (memchr) +diff --git a/sysdeps/s390/s390-32/multiarch/memchr.c b/sysdeps/s390/s390-32/multiarch/memchr.c +deleted file mode 100644 +index 5e1610afa43ee549..0000000000000000 +--- a/sysdeps/s390/s390-32/multiarch/memchr.c ++++ /dev/null +@@ -1,21 +0,0 @@ +-/* Multiple versions of memchr. +- Copyright (C) 2015-2018 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 +- . */ +- +-/* This wrapper-file is needed, because otherwise file +- sysdeps/s390/s390-[32|64]/memchr.S will be used. */ +-#include +diff --git a/sysdeps/s390/s390-64/multiarch/memchr.c b/sysdeps/s390/s390-64/multiarch/memchr.c +deleted file mode 100644 +index 5e1610afa43ee549..0000000000000000 +--- a/sysdeps/s390/s390-64/multiarch/memchr.c ++++ /dev/null +@@ -1,21 +0,0 @@ +-/* Multiple versions of memchr. +- Copyright (C) 2015-2018 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 +- . */ +- +-/* This wrapper-file is needed, because otherwise file +- sysdeps/s390/s390-[32|64]/memchr.S will be used. */ +-#include diff --git a/glibc-rh1659438-33.patch b/glibc-rh1659438-33.patch new file mode 100755 index 0000000..b2b59ee --- /dev/null +++ b/glibc-rh1659438-33.patch @@ -0,0 +1,287 @@ +commit 4c7b3cec113d9bb7dfc004e22c7a98e310ab9bcc +Author: Stefan Liebler +Date: Tue Dec 18 13:57:16 2018 +0100 + + S390: Refactor rawmemchr ifunc handling. + + The ifunc handling for rawmemchr is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove rawmemchr variants. + * sysdeps/s390/Makefile (sysdep_routines): Add rawmemchr variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for rawmemchr. + * sysdeps/s390/multiarch/rawmemchr-c.c: Move to ... + * sysdeps/s390/rawmemchr-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/rawmemchr-vx.S: Move to ... + * sysdeps/s390/rawmemchr-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/rawmemchr.c: Move to ... + * sysdeps/s390/rawmemchr.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-rawmemchr.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 816b2fccdc75e4cf..9b38b461b34176b0 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -53,5 +53,6 @@ sysdep_routines += bzero memset memset-z900 \ + strspn strspn-vx strspn-c \ + strpbrk strpbrk-vx strpbrk-c \ + strcspn strcspn-vx strcspn-c \ +- memchr memchr-vx memchr-z900 ++ memchr memchr-vx memchr-z900 \ ++ rawmemchr rawmemchr-vx rawmemchr-c + endif +diff --git a/sysdeps/s390/ifunc-rawmemchr.h b/sysdeps/s390/ifunc-rawmemchr.h +new file mode 100644 +index 0000000000000000..bfcbeae802fb372e +--- /dev/null ++++ b/sysdeps/s390/ifunc-rawmemchr.h +@@ -0,0 +1,52 @@ ++/* rawmemchr variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_RAWMEMCHR_IFUNC 1 ++#else ++# define HAVE_RAWMEMCHR_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_RAWMEMCHR_IFUNC_AND_VX_SUPPORT HAVE_RAWMEMCHR_IFUNC ++#else ++# define HAVE_RAWMEMCHR_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define RAWMEMCHR_DEFAULT RAWMEMCHR_Z13 ++# define HAVE_RAWMEMCHR_C 0 ++# define HAVE_RAWMEMCHR_Z13 1 ++#else ++# define RAWMEMCHR_DEFAULT RAWMEMCHR_C ++# define HAVE_RAWMEMCHR_C 1 ++# define HAVE_RAWMEMCHR_Z13 HAVE_RAWMEMCHR_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_RAWMEMCHR_C ++# define RAWMEMCHR_C __rawmemchr_c ++#else ++# define RAWMEMCHR_C NULL ++#endif ++ ++#if HAVE_RAWMEMCHR_Z13 ++# define RAWMEMCHR_Z13 __rawmemchr_vx ++#else ++# define RAWMEMCHR_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index fa1f7b81db912be0..ac6cfcf9c7dbbc3a 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += rawmemchr rawmemchr-vx rawmemchr-c \ +- memccpy memccpy-vx memccpy-c \ ++sysdep_routines += memccpy memccpy-vx memccpy-c \ + memrchr memrchr-vx memrchr-c + endif + +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index b4be0140424aed69..bf3b40e111a6bd31 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -385,6 +386,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_MEMCHR_IFUNC */ + ++#if HAVE_RAWMEMCHR_IFUNC ++ IFUNC_IMPL (i, name, rawmemchr, ++# if HAVE_RAWMEMCHR_Z13 ++ IFUNC_IMPL_ADD (array, i, rawmemchr, ++ dl_hwcap & HWCAP_S390_VX, RAWMEMCHR_Z13) ++# endif ++# if HAVE_RAWMEMCHR_C ++ IFUNC_IMPL_ADD (array, i, rawmemchr, 1, RAWMEMCHR_C) ++# endif ++ ) ++#endif /* HAVE_RAWMEMCHR_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -426,7 +439,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_VX_IMPL (wcscspn); + + IFUNC_VX_IMPL (wmemchr); +- IFUNC_VX_IMPL (rawmemchr); + + IFUNC_VX_IMPL (memccpy); + +diff --git a/sysdeps/s390/multiarch/rawmemchr.c b/sysdeps/s390/rawmemchr-c.c +similarity index 67% +rename from sysdeps/s390/multiarch/rawmemchr.c +rename to sysdeps/s390/rawmemchr-c.c +index 5fdb2252df7f8fa1..8b8208e542092383 100644 +--- a/sysdeps/s390/multiarch/rawmemchr.c ++++ b/sysdeps/s390/rawmemchr-c.c +@@ -1,4 +1,4 @@ +-/* Multiple versions of rawmemchr. ++/* Default rawmemchr implementation for S/390. + Copyright (C) 2015-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + +@@ -16,16 +16,19 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define __rawmemchr __redirect___rawmemchr +-# include +-# undef __rawmemchr +-# include ++#include + +-s390_vx_libc_ifunc2_redirected (__redirect___rawmemchr, __rawmemchr +- , __rawmemchr) +-weak_alias (__rawmemchr, rawmemchr) ++#if HAVE_RAWMEMCHR_C ++# if HAVE_RAWMEMCHR_IFUNC ++# define RAWMEMCHR RAWMEMCHR_C ++# undef weak_alias ++# define weak_alias(a, b) ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_def ++# define libc_hidden_def(name) \ ++ __hidden_ver1 (__rawmemchr_c, __GI___rawmemchr, __rawmemchr_c); ++# endif ++# endif + +-#else + # include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++#endif +diff --git a/sysdeps/s390/multiarch/rawmemchr-vx.S b/sysdeps/s390/rawmemchr-vx.S +similarity index 87% +rename from sysdeps/s390/multiarch/rawmemchr-vx.S +rename to sysdeps/s390/rawmemchr-vx.S +index d5778be068394394..f04c0e8b616a76ea 100644 +--- a/sysdeps/s390/multiarch/rawmemchr-vx.S ++++ b/sysdeps/s390/rawmemchr-vx.S +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_RAWMEMCHR_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -37,7 +39,7 @@ + -v17=index of unequal + -v18=c replicated + */ +-ENTRY(__rawmemchr_vx) ++ENTRY(RAWMEMCHR_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -88,5 +90,15 @@ ENTRY(__rawmemchr_vx) + .Lend_found: + la %r2,0(%r5,%r2) /* Return pointer to character. */ + br %r14 +-END(__rawmemchr_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(RAWMEMCHR_Z13) ++ ++# if ! HAVE_RAWMEMCHR_IFUNC ++strong_alias (RAWMEMCHR_Z13, __rawmemchr) ++weak_alias (__rawmemchr, rawmemchr) ++# endif ++ ++# if ! HAVE_RAWMEMCHR_C && defined SHARED && IS_IN (libc) ++strong_alias (RAWMEMCHR_Z13, __GI___rawmemchr) ++# endif ++ ++#endif /* HAVE_RAWMEMCHR_Z13 */ +diff --git a/sysdeps/s390/multiarch/rawmemchr-c.c b/sysdeps/s390/rawmemchr.c +similarity index 56% +rename from sysdeps/s390/multiarch/rawmemchr-c.c +rename to sysdeps/s390/rawmemchr.c +index f43c883a76e52480..d9263ce208ea6361 100644 +--- a/sysdeps/s390/multiarch/rawmemchr-c.c ++++ b/sysdeps/s390/rawmemchr.c +@@ -1,4 +1,4 @@ +-/* Default rawmemchr implementation for S/390. ++/* Multiple versions of rawmemchr. + Copyright (C) 2015-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + +@@ -16,19 +16,26 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_RAWMEMCHR_IFUNC ++# define __rawmemchr __redirect___rawmemchr + # include ++# undef __rawmemchr ++# include + +-# define RAWMEMCHR __rawmemchr_c +-# undef weak_alias +-# define weak_alias(a, b) +-# ifdef SHARED +-# undef libc_hidden_def +-# define libc_hidden_def(name) \ +- __hidden_ver1 (__rawmemchr_c, __GI___rawmemchr, __rawmemchr_c); +-# endif /* SHARED */ ++# if HAVE_RAWMEMCHR_C ++extern __typeof (__redirect___rawmemchr) RAWMEMCHR_C attribute_hidden; ++# endif + +-extern __typeof (rawmemchr) __rawmemchr_c attribute_hidden; ++# if HAVE_RAWMEMCHR_Z13 ++extern __typeof (__redirect___rawmemchr) RAWMEMCHR_Z13 attribute_hidden; ++# endif + +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (__redirect___rawmemchr, __rawmemchr, ++ (HAVE_RAWMEMCHR_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? RAWMEMCHR_Z13 ++ : RAWMEMCHR_DEFAULT ++ ) ++weak_alias (__rawmemchr, rawmemchr) ++#endif /* HAVE_RAWMEMCHR_IFUNC */ diff --git a/glibc-rh1659438-34.patch b/glibc-rh1659438-34.patch new file mode 100755 index 0000000..f2fbe7f --- /dev/null +++ b/glibc-rh1659438-34.patch @@ -0,0 +1,252 @@ +commit 196655ba54ebdcdcc0468bcb6e136757b013d350 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:16 2018 +0100 + + S390: Refactor memccpy ifunc handling. + + The ifunc handling for memccpy is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove memccpy variants. + * sysdeps/s390/Makefile (sysdep_routines): Add memccpy variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for memccpy. + * sysdeps/s390/multiarch/memccpy-c.c: Move to ... + * sysdeps/s390/memccpy-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/memccpy-vx.S: Move to ... + * sysdeps/s390/memccpy-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/memccpy.c: Move to ... + * sysdeps/s390/memccpy.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-memccpy.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 9b38b461b34176b0..239426dbc1ce9d09 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -54,5 +54,6 @@ sysdep_routines += bzero memset memset-z900 \ + strpbrk strpbrk-vx strpbrk-c \ + strcspn strcspn-vx strcspn-c \ + memchr memchr-vx memchr-z900 \ +- rawmemchr rawmemchr-vx rawmemchr-c ++ rawmemchr rawmemchr-vx rawmemchr-c \ ++ memccpy memccpy-vx memccpy-c + endif +diff --git a/sysdeps/s390/ifunc-memccpy.h b/sysdeps/s390/ifunc-memccpy.h +new file mode 100644 +index 0000000000000000..8f7a1d0f9fffe106 +--- /dev/null ++++ b/sysdeps/s390/ifunc-memccpy.h +@@ -0,0 +1,52 @@ ++/* memccpy variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_MEMCCPY_IFUNC 1 ++#else ++# define HAVE_MEMCCPY_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_MEMCCPY_IFUNC_AND_VX_SUPPORT HAVE_MEMCCPY_IFUNC ++#else ++# define HAVE_MEMCCPY_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define MEMCCPY_DEFAULT MEMCCPY_Z13 ++# define HAVE_MEMCCPY_C 0 ++# define HAVE_MEMCCPY_Z13 1 ++#else ++# define MEMCCPY_DEFAULT MEMCCPY_C ++# define HAVE_MEMCCPY_C 1 ++# define HAVE_MEMCCPY_Z13 HAVE_MEMCCPY_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_MEMCCPY_C ++# define MEMCCPY_C __memccpy_c ++#else ++# define MEMCCPY_C NULL ++#endif ++ ++#if HAVE_MEMCCPY_Z13 ++# define MEMCCPY_Z13 __memccpy_vx ++#else ++# define MEMCCPY_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/memccpy-c.c b/sysdeps/s390/memccpy-c.c +similarity index 85% +rename from sysdeps/s390/multiarch/memccpy-c.c +rename to sysdeps/s390/memccpy-c.c +index 1f4c5481991fcb70..2b2f81eb9cfe9369 100644 +--- a/sysdeps/s390/multiarch/memccpy-c.c ++++ b/sysdeps/s390/memccpy-c.c +@@ -16,10 +16,14 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define MEMCCPY __memccpy_c ++#include ++ ++#if HAVE_MEMCCPY_C ++# if HAVE_MEMCCPY_IFUNC ++# define MEMCCPY MEMCCPY_C ++# undef weak_alias ++# define weak_alias(a, b) ++#endif + +-# include +-extern __typeof (__memccpy) __memccpy_c; + # include + #endif +diff --git a/sysdeps/s390/multiarch/memccpy-vx.S b/sysdeps/s390/memccpy-vx.S +similarity index 95% +rename from sysdeps/s390/multiarch/memccpy-vx.S +rename to sysdeps/s390/memccpy-vx.S +index 150aa0e4a48ca181..44f7bc582410ba22 100644 +--- a/sysdeps/s390/multiarch/memccpy-vx.S ++++ b/sysdeps/s390/memccpy-vx.S +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_MEMCCPY_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -42,7 +44,7 @@ + -v19=part #2 of s + -v31=save area for r6 + */ +-ENTRY(__memccpy_vx) ++ENTRY(MEMCCPY_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -152,5 +154,11 @@ ENTRY(__memccpy_vx) + vlgvg %r7,%v31,1 + lghi %r2,0 /* Return null. */ + br %r14 +-END(__memccpy_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(MEMCCPY_Z13) ++ ++# if ! HAVE_MEMCCPY_IFUNC ++strong_alias (MEMCCPY_Z13, __memccpy) ++weak_alias (__memccpy, memccpy) ++# endif ++ ++#endif /* HAVE_MEMCCPY_Z13 */ +diff --git a/sysdeps/s390/multiarch/memccpy.c b/sysdeps/s390/memccpy.c +similarity index 68% +rename from sysdeps/s390/multiarch/memccpy.c +rename to sysdeps/s390/memccpy.c +index 30aae82321048b7d..bcfeb31e86c56115 100644 +--- a/sysdeps/s390/multiarch/memccpy.c ++++ b/sysdeps/s390/memccpy.c +@@ -16,13 +16,24 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_MEMCCPY_IFUNC + # include + # include + +-s390_vx_libc_ifunc (__memccpy) +-weak_alias (__memccpy, memccpy) ++# if HAVE_MEMCCPY_C ++extern __typeof (__memccpy) MEMCCPY_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_MEMCCPY_Z13 ++extern __typeof (__memccpy) MEMCCPY_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__memccpy, __memccpy, ++ (HAVE_MEMCCPY_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? MEMCCPY_Z13 ++ : MEMCCPY_DEFAULT ++ ) ++weak_alias (__memccpy, memccpy) ++#endif /* HAVE_MEMCCPY_IFUNC */ +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index ac6cfcf9c7dbbc3a..d5a32fc309ba4b3c 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),string) +-sysdep_routines += memccpy memccpy-vx memccpy-c \ +- memrchr memrchr-vx memrchr-c ++sysdep_routines += memrchr memrchr-vx memrchr-c + endif + + ifeq ($(subdir),wcsmbs) +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index bf3b40e111a6bd31..b8917747f0f23cd9 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -44,6 +44,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -398,6 +399,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_RAWMEMCHR_IFUNC */ + ++#if HAVE_MEMCCPY_IFUNC ++ IFUNC_IMPL (i, name, memccpy, ++# if HAVE_MEMCCPY_Z13 ++ IFUNC_IMPL_ADD (array, i, memccpy, ++ dl_hwcap & HWCAP_S390_VX, MEMCCPY_Z13) ++# endif ++# if HAVE_MEMCCPY_C ++ IFUNC_IMPL_ADD (array, i, memccpy, 1, MEMCCPY_C) ++# endif ++ ) ++#endif /* HAVE_MEMCCPY_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -440,8 +453,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wmemchr); + +- IFUNC_VX_IMPL (memccpy); +- + IFUNC_VX_IMPL (wmemset); + + IFUNC_VX_IMPL (wmemcmp); diff --git a/glibc-rh1659438-35.patch b/glibc-rh1659438-35.patch new file mode 100755 index 0000000..53091b6 --- /dev/null +++ b/glibc-rh1659438-35.patch @@ -0,0 +1,250 @@ +commit 89bfcbdf9d3d36eff0d544f655991149a7ae680b +Author: Stefan Liebler +Date: Tue Dec 18 13:57:17 2018 +0100 + + S390: Refactor memrchr ifunc handling. + + The ifunc handling for memrchr is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove memrchr variants. + * sysdeps/s390/Makefile (sysdep_routines): Add memrchr variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for memrchr. + * sysdeps/s390/multiarch/memrchr-c.c: Move to ... + * sysdeps/s390/memrchr-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/memrchr-vx.S: Move to ... + * sysdeps/s390/memrchr-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/memrchr.c: Move to ... + * sysdeps/s390/memrchr.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-memrchr.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 239426dbc1ce9d09..9a16ce1692e51607 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -55,5 +55,6 @@ sysdep_routines += bzero memset memset-z900 \ + strcspn strcspn-vx strcspn-c \ + memchr memchr-vx memchr-z900 \ + rawmemchr rawmemchr-vx rawmemchr-c \ +- memccpy memccpy-vx memccpy-c ++ memccpy memccpy-vx memccpy-c \ ++ memrchr memrchr-vx memrchr-c + endif +diff --git a/sysdeps/s390/ifunc-memrchr.h b/sysdeps/s390/ifunc-memrchr.h +new file mode 100644 +index 0000000000000000..9d80d5528dc92dab +--- /dev/null ++++ b/sysdeps/s390/ifunc-memrchr.h +@@ -0,0 +1,52 @@ ++/* memrchr variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_MEMRCHR_IFUNC 1 ++#else ++# define HAVE_MEMRCHR_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_MEMRCHR_IFUNC_AND_VX_SUPPORT HAVE_MEMRCHR_IFUNC ++#else ++# define HAVE_MEMRCHR_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define MEMRCHR_DEFAULT MEMRCHR_Z13 ++# define HAVE_MEMRCHR_C 0 ++# define HAVE_MEMRCHR_Z13 1 ++#else ++# define MEMRCHR_DEFAULT MEMRCHR_C ++# define HAVE_MEMRCHR_C 1 ++# define HAVE_MEMRCHR_Z13 HAVE_MEMRCHR_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_MEMRCHR_C ++# define MEMRCHR_C __memrchr_c ++#else ++# define MEMRCHR_C NULL ++#endif ++ ++#if HAVE_MEMRCHR_Z13 ++# define MEMRCHR_Z13 __memrchr_vx ++#else ++# define MEMRCHR_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/memrchr-c.c b/sysdeps/s390/memrchr-c.c +similarity index 85% +rename from sysdeps/s390/multiarch/memrchr-c.c +rename to sysdeps/s390/memrchr-c.c +index 1e3c914a5d61dbc5..333c0fc8d1855323 100644 +--- a/sysdeps/s390/multiarch/memrchr-c.c ++++ b/sysdeps/s390/memrchr-c.c +@@ -16,10 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define MEMRCHR __memrchr_c ++#include ++ ++#if HAVE_MEMRCHR_C ++# if HAVE_MEMRCHR_IFUNC ++# define MEMRCHR MEMRCHR_C ++# endif + +-# include +-extern __typeof (__memrchr) __memrchr_c; + # include + #endif +diff --git a/sysdeps/s390/multiarch/memrchr-vx.S b/sysdeps/s390/memrchr-vx.S +similarity index 94% +rename from sysdeps/s390/multiarch/memrchr-vx.S +rename to sysdeps/s390/memrchr-vx.S +index 8e81f5ed7519c2cc..ba832f1b21ad5a4c 100644 +--- a/sysdeps/s390/multiarch/memrchr-vx.S ++++ b/sysdeps/s390/memrchr-vx.S +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_MEMRCHR_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -40,7 +42,7 @@ + -v18=c replicated + -v20=permute pattern + */ +-ENTRY(__memrchr_vx) ++ENTRY(MEMRCHR_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -156,5 +158,11 @@ ENTRY(__memrchr_vx) + + clgijhe %r4,64,.Lloop64 /* If n >= 64 -> loop64. */ + j .Llt64 +-END(__memrchr_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(MEMRCHR_Z13) ++ ++# if ! HAVE_MEMRCHR_IFUNC ++strong_alias (MEMRCHR_Z13, __memrchr) ++weak_alias (__memrchr, memrchr) ++# endif ++ ++#endif /* HAVE_MEMRCHR_Z13 */ +diff --git a/sysdeps/s390/multiarch/memrchr.c b/sysdeps/s390/memrchr.c +similarity index 68% +rename from sysdeps/s390/multiarch/memrchr.c +rename to sysdeps/s390/memrchr.c +index 43a44abcf6cc3bdc..d995e9961c1cc9eb 100644 +--- a/sysdeps/s390/multiarch/memrchr.c ++++ b/sysdeps/s390/memrchr.c +@@ -16,13 +16,24 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_MEMRCHR_IFUNC + # include + # include + +-s390_vx_libc_ifunc (__memrchr) +-weak_alias (__memrchr, memrchr) ++# if HAVE_MEMRCHR_C ++extern __typeof (__memrchr) MEMRCHR_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_MEMRCHR_Z13 ++extern __typeof (__memrchr) MEMRCHR_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__memrchr, __memrchr, ++ (HAVE_MEMRCHR_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? MEMRCHR_Z13 ++ : MEMRCHR_DEFAULT ++ ) ++weak_alias (__memrchr, memrchr) ++#endif /* HAVE_MEMRCHR_IFUNC */ +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index d5a32fc309ba4b3c..260b514936b93306 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,7 +1,3 @@ +-ifeq ($(subdir),string) +-sysdep_routines += memrchr memrchr-vx memrchr-c +-endif +- + ifeq ($(subdir),wcsmbs) + sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcsnlen wcsnlen-vx wcsnlen-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index b8917747f0f23cd9..0f01b99691002be0 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -411,6 +412,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_MEMCCPY_IFUNC */ + ++#if HAVE_MEMRCHR_IFUNC ++ IFUNC_IMPL (i, name, memrchr, ++# if HAVE_MEMRCHR_Z13 ++ IFUNC_IMPL_ADD (array, i, memrchr, ++ dl_hwcap & HWCAP_S390_VX, MEMRCHR_Z13) ++# endif ++# if HAVE_MEMRCHR_C ++ IFUNC_IMPL_ADD (array, i, memrchr, 1, MEMRCHR_C) ++# endif ++ ) ++#endif /* HAVE_MEMRCHR_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -457,8 +470,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + IFUNC_VX_IMPL (wmemcmp); + +- IFUNC_VX_IMPL (memrchr); +- + #endif /* HAVE_S390_VX_ASM_SUPPORT */ + + return i; diff --git a/glibc-rh1659438-36.patch b/glibc-rh1659438-36.patch new file mode 100755 index 0000000..146d137 --- /dev/null +++ b/glibc-rh1659438-36.patch @@ -0,0 +1,252 @@ +commit 2e02d0b7a9bf3421638d2d0f2526275a1df5c0da +Author: Stefan Liebler +Date: Tue Dec 18 13:57:17 2018 +0100 + + S390: Refactor wcslen ifunc handling. + + The ifunc handling for wcslen is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcslen variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcslen variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcslen. + * sysdeps/s390/multiarch/wcslen-c.c: Move to ... + * sysdeps/s390/wcslen-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcslen-vx.S: Move to ... + * sysdeps/s390/wcslen-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcslen.c: Move to ... + * sysdeps/s390/wcslen.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcslen.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 9a16ce1692e51607..65e89118936bb668 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -58,3 +58,7 @@ sysdep_routines += bzero memset memset-z900 \ + memccpy memccpy-vx memccpy-c \ + memrchr memrchr-vx memrchr-c + endif ++ ++ifeq ($(subdir),wcsmbs) ++sysdep_routines += wcslen wcslen-vx wcslen-c ++endif +diff --git a/sysdeps/s390/ifunc-wcslen.h b/sysdeps/s390/ifunc-wcslen.h +new file mode 100644 +index 0000000000000000..50d879caf2b8186b +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcslen.h +@@ -0,0 +1,53 @@ ++/* wcslen variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSLEN_IFUNC 1 ++#else ++# define HAVE_WCSLEN_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSLEN_IFUNC_AND_VX_SUPPORT HAVE_WCSLEN_IFUNC ++#else ++# define HAVE_WCSLEN_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSLEN_DEFAULT WCSLEN_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCSLEN_C 1 ++# define HAVE_WCSLEN_Z13 1 ++#else ++# define WCSLEN_DEFAULT WCSLEN_C ++# define HAVE_WCSLEN_C 1 ++# define HAVE_WCSLEN_Z13 HAVE_WCSLEN_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSLEN_C ++# define WCSLEN_C __wcslen_c ++#else ++# define WCSLEN_C NULL ++#endif ++ ++#if HAVE_WCSLEN_Z13 ++# define WCSLEN_Z13 __wcslen_vx ++#else ++# define WCSLEN_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 260b514936b93306..421d40d020b81560 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcslen wcslen-vx wcslen-c \ +- wcsnlen wcsnlen-vx wcsnlen-c \ ++sysdep_routines += wcsnlen wcsnlen-vx wcsnlen-c \ + wcscpy wcscpy-vx wcscpy-c \ + wcpcpy wcpcpy-vx wcpcpy-c \ + wcsncpy wcsncpy-vx wcsncpy-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 0f01b99691002be0..7bf5f14c015b54fe 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -424,6 +425,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_MEMRCHR_IFUNC */ + ++#if HAVE_WCSLEN_IFUNC ++ IFUNC_IMPL (i, name, wcslen, ++# if HAVE_WCSLEN_Z13 ++ IFUNC_IMPL_ADD (array, i, wcslen, ++ dl_hwcap & HWCAP_S390_VX, WCSLEN_Z13) ++# endif ++# if HAVE_WCSLEN_C ++ IFUNC_IMPL_ADD (array, i, wcslen, 1, WCSLEN_C) ++# endif ++ ) ++#endif /* HAVE_WCSLEN_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -432,8 +445,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcslen); +- + IFUNC_VX_IMPL (wcsnlen); + + IFUNC_VX_IMPL (wcscpy); +diff --git a/sysdeps/s390/multiarch/wcslen-c.c b/sysdeps/s390/wcslen-c.c +similarity index 86% +rename from sysdeps/s390/multiarch/wcslen-c.c +rename to sysdeps/s390/wcslen-c.c +index 32a23e206d2e9cf9..45399cff3a127b5e 100644 +--- a/sysdeps/s390/multiarch/wcslen-c.c ++++ b/sysdeps/s390/wcslen-c.c +@@ -16,10 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSLEN __wcslen_c ++#include ++ ++#if HAVE_WCSLEN_C ++# if HAVE_WCSLEN_IFUNC || HAVE_WCSLEN_Z13 ++# define WCSLEN WCSLEN_C ++# endif + +-# include +-extern __typeof (__wcslen) __wcslen_c; + # include + #endif +diff --git a/sysdeps/s390/multiarch/wcslen-vx.S b/sysdeps/s390/wcslen-vx.S +similarity index 92% +rename from sysdeps/s390/multiarch/wcslen-vx.S +rename to sysdeps/s390/wcslen-vx.S +index 337cbed6ec21db76..114f7ef743b10c63 100644 +--- a/sysdeps/s390/multiarch/wcslen-vx.S ++++ b/sysdeps/s390/wcslen-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSLEN_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -34,7 +35,7 @@ + -r5=current_len and return_value + -v16=part of s + */ +-ENTRY(__wcslen_vx) ++ENTRY(WCSLEN_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -86,6 +87,11 @@ ENTRY(__wcslen_vx) + srlg %r2,%r2,2 /* Convert byte-count to character-count. */ + br %r14 + .Lfallback: +- jg __wcslen_c +-END(__wcslen_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCSLEN_C ++END(WCSLEN_Z13) ++ ++# if ! HAVE_WCSLEN_IFUNC ++strong_alias (WCSLEN_Z13, __wcslen) ++weak_alias (__wcslen, wcslen) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcslen.c b/sysdeps/s390/wcslen.c +similarity index 70% +rename from sysdeps/s390/multiarch/wcslen.c +rename to sysdeps/s390/wcslen.c +index 3a1d1a32c9a99749..a5eee83f6cae7166 100644 +--- a/sysdeps/s390/multiarch/wcslen.c ++++ b/sysdeps/s390/wcslen.c +@@ -16,13 +16,24 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSLEN_IFUNC + # include + # include + +-s390_vx_libc_ifunc (__wcslen) +-weak_alias (__wcslen, wcslen) ++# if HAVE_WCSLEN_C ++extern __typeof (__wcslen) WCSLEN_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_WCSLEN_Z13 ++extern __typeof (__wcslen) WCSLEN_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__wcslen, __wcslen, ++ (HAVE_WCSLEN_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSLEN_Z13 ++ : WCSLEN_DEFAULT ++ ) ++weak_alias (__wcslen, wcslen) ++#endif diff --git a/glibc-rh1659438-37.patch b/glibc-rh1659438-37.patch new file mode 100755 index 0000000..827d82d --- /dev/null +++ b/glibc-rh1659438-37.patch @@ -0,0 +1,253 @@ +commit c7e7cd266ed123b6dfb722f599934ca5dcfd3e93 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:18 2018 +0100 + + S390: Refactor wcsnlen ifunc handling. + + The ifunc handling for wcsnlen is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + Glibc internal calls will use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcsnlen variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcsnlen variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcsnlen. + * sysdeps/s390/multiarch/wcsnlen-c.c: Move to ... + * sysdeps/s390/wcsnlen-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcsnlen-vx.S: Move to ... + * sysdeps/s390/wcsnlen-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcsnlen.c: Move to ... + * sysdeps/s390/wcsnlen.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcsnlen.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 65e89118936bb668..f5983815479a76da 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -60,5 +60,6 @@ sysdep_routines += bzero memset memset-z900 \ + endif + + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcslen wcslen-vx wcslen-c ++sysdep_routines += wcslen wcslen-vx wcslen-c \ ++ wcsnlen wcsnlen-vx wcsnlen-c + endif +diff --git a/sysdeps/s390/ifunc-wcsnlen.h b/sysdeps/s390/ifunc-wcsnlen.h +new file mode 100644 +index 0000000000000000..b5b21da2f17d9cd9 +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcsnlen.h +@@ -0,0 +1,53 @@ ++/* wcsnlen variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSNLEN_IFUNC 1 ++#else ++# define HAVE_WCSNLEN_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSNLEN_IFUNC_AND_VX_SUPPORT HAVE_WCSNLEN_IFUNC ++#else ++# define HAVE_WCSNLEN_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSNLEN_DEFAULT WCSNLEN_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCSNLEN_C 1 ++# define HAVE_WCSNLEN_Z13 1 ++#else ++# define WCSNLEN_DEFAULT WCSNLEN_C ++# define HAVE_WCSNLEN_C 1 ++# define HAVE_WCSNLEN_Z13 HAVE_WCSNLEN_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSNLEN_C ++# define WCSNLEN_C __wcsnlen_c ++#else ++# define WCSNLEN_C NULL ++#endif ++ ++#if HAVE_WCSNLEN_Z13 ++# define WCSNLEN_Z13 __wcsnlen_vx ++#else ++# define WCSNLEN_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 421d40d020b81560..ce2e7ce5f4eef0fa 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcsnlen wcsnlen-vx wcsnlen-c \ +- wcscpy wcscpy-vx wcscpy-c \ ++sysdep_routines += wcscpy wcscpy-vx wcscpy-c \ + wcpcpy wcpcpy-vx wcpcpy-c \ + wcsncpy wcsncpy-vx wcsncpy-c \ + wcpncpy wcpncpy-vx wcpncpy-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 7bf5f14c015b54fe..c199fd0e0b43e4b4 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -47,6 +47,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -437,6 +438,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSLEN_IFUNC */ + ++#if HAVE_WCSNLEN_IFUNC ++ IFUNC_IMPL (i, name, wcsnlen, ++# if HAVE_WCSNLEN_Z13 ++ IFUNC_IMPL_ADD (array, i, wcsnlen, ++ dl_hwcap & HWCAP_S390_VX, WCSNLEN_Z13) ++# endif ++# if HAVE_WCSNLEN_C ++ IFUNC_IMPL_ADD (array, i, wcsnlen, 1, WCSNLEN_C) ++# endif ++ ) ++#endif /* HAVE_WCSNLEN_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -445,8 +458,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcsnlen); +- + IFUNC_VX_IMPL (wcscpy); + + IFUNC_VX_IMPL (wcpcpy); +diff --git a/sysdeps/s390/multiarch/wcsnlen-c.c b/sysdeps/s390/wcsnlen-c.c +similarity index 85% +rename from sysdeps/s390/multiarch/wcsnlen-c.c +rename to sysdeps/s390/wcsnlen-c.c +index 8f43f5104f2eab3f..7495a6f97cfeca62 100644 +--- a/sysdeps/s390/multiarch/wcsnlen-c.c ++++ b/sysdeps/s390/wcsnlen-c.c +@@ -16,10 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSNLEN __wcsnlen_c ++#include ++ ++#if HAVE_WCSNLEN_C ++# if HAVE_WCSNLEN_IFUNC || HAVE_WCSNLEN_Z13 ++# define WCSNLEN WCSNLEN_C ++# endif + +-# include +-extern __typeof (__wcsnlen) __wcsnlen_c; + # include + #endif +diff --git a/sysdeps/s390/multiarch/wcsnlen-vx.S b/sysdeps/s390/wcsnlen-vx.S +similarity index 95% +rename from sysdeps/s390/multiarch/wcsnlen-vx.S +rename to sysdeps/s390/wcsnlen-vx.S +index 420f29fbc0d2965a..47f4ca82840538d9 100644 +--- a/sysdeps/s390/multiarch/wcsnlen-vx.S ++++ b/sysdeps/s390/wcsnlen-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSNLEN_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -34,7 +35,7 @@ + -r5=current_len and return_value + -v16=part of s + */ +-ENTRY(__wcsnlen_vx) ++ENTRY(WCSNLEN_Z13) + + .machine "z13" + .machinemode "zarch_nohighgprs" +@@ -146,6 +147,11 @@ ENTRY(__wcsnlen_vx) + j .Llt64 + + .Lfallback: +- jg __wcsnlen_c +-END(__wcsnlen_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCSNLEN_C ++END(WCSNLEN_Z13) ++ ++# if ! HAVE_WCSNLEN_IFUNC ++strong_alias (WCSNLEN_Z13, __wcsnlen) ++weak_alias (__wcsnlen, wcsnlen) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcsnlen.c b/sysdeps/s390/wcsnlen.c +similarity index 70% +rename from sysdeps/s390/multiarch/wcsnlen.c +rename to sysdeps/s390/wcsnlen.c +index 5234074b1fce8ca1..b5c8ad9fde5a9752 100644 +--- a/sysdeps/s390/multiarch/wcsnlen.c ++++ b/sysdeps/s390/wcsnlen.c +@@ -16,13 +16,24 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSNLEN_IFUNC + # include + # include + +-s390_vx_libc_ifunc (__wcsnlen) +-weak_alias (__wcsnlen, wcsnlen) ++# if HAVE_WCSNLEN_C ++extern __typeof (__wcsnlen) WCSNLEN_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_WCSNLEN_Z13 ++extern __typeof (__wcsnlen) WCSNLEN_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__wcsnlen, __wcsnlen, ++ (HAVE_WCSNLEN_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSNLEN_Z13 ++ : WCSNLEN_DEFAULT ++ ) ++weak_alias (__wcsnlen, wcsnlen) ++#endif diff --git a/glibc-rh1659438-38.patch b/glibc-rh1659438-38.patch new file mode 100755 index 0000000..7549d69 --- /dev/null +++ b/glibc-rh1659438-38.patch @@ -0,0 +1,249 @@ +commit 804f2e5c73b1363836ce5db29a0abb3d36e1286a +Author: Stefan Liebler +Date: Tue Dec 18 13:57:18 2018 +0100 + + S390: Refactor wcscpy ifunc handling. + + The ifunc handling for wcscpy is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcscpy variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcscpy variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcscpy. + * sysdeps/s390/multiarch/wcscpy-c.c: Move to ... + * sysdeps/s390/wcscpy-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcscpy-vx.S: Move to ... + * sysdeps/s390/wcscpy-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcscpy.c: Move to ... + * sysdeps/s390/wcscpy.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcscpy.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index f5983815479a76da..8bdbd1b5d8e9df01 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -61,5 +61,6 @@ endif + + ifeq ($(subdir),wcsmbs) + sysdep_routines += wcslen wcslen-vx wcslen-c \ +- wcsnlen wcsnlen-vx wcsnlen-c ++ wcsnlen wcsnlen-vx wcsnlen-c \ ++ wcscpy wcscpy-vx wcscpy-c + endif +diff --git a/sysdeps/s390/ifunc-wcscpy.h b/sysdeps/s390/ifunc-wcscpy.h +new file mode 100644 +index 0000000000000000..fba7c9c7a7c354d1 +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcscpy.h +@@ -0,0 +1,53 @@ ++/* wcscpy variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSCPY_IFUNC 1 ++#else ++# define HAVE_WCSCPY_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSCPY_IFUNC_AND_VX_SUPPORT HAVE_WCSCPY_IFUNC ++#else ++# define HAVE_WCSCPY_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSCPY_DEFAULT WCSCPY_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCSCPY_C 1 ++# define HAVE_WCSCPY_Z13 1 ++#else ++# define WCSCPY_DEFAULT WCSCPY_C ++# define HAVE_WCSCPY_C 1 ++# define HAVE_WCSCPY_Z13 HAVE_WCSCPY_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSCPY_C ++# define WCSCPY_C __wcscpy_c ++#else ++# define WCSCPY_C NULL ++#endif ++ ++#if HAVE_WCSCPY_Z13 ++# define WCSCPY_Z13 __wcscpy_vx ++#else ++# define WCSCPY_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index ce2e7ce5f4eef0fa..8828897a59ae580c 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcscpy wcscpy-vx wcscpy-c \ +- wcpcpy wcpcpy-vx wcpcpy-c \ ++sysdep_routines += wcpcpy wcpcpy-vx wcpcpy-c \ + wcsncpy wcsncpy-vx wcsncpy-c \ + wcpncpy wcpncpy-vx wcpncpy-c \ + wcscat wcscat-vx wcscat-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index c199fd0e0b43e4b4..aac8f4ea4671d0cf 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -48,6 +48,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -450,6 +451,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSNLEN_IFUNC */ + ++#if HAVE_WCSCPY_IFUNC ++ IFUNC_IMPL (i, name, wcscpy, ++# if HAVE_WCSCPY_Z13 ++ IFUNC_IMPL_ADD (array, i, wcscpy, ++ dl_hwcap & HWCAP_S390_VX, WCSCPY_Z13) ++# endif ++# if HAVE_WCSCPY_C ++ IFUNC_IMPL_ADD (array, i, wcscpy, 1, WCSCPY_C) ++# endif ++ ) ++#endif /* HAVE_WCSCPY_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -458,8 +471,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcscpy); +- + IFUNC_VX_IMPL (wcpcpy); + + IFUNC_VX_IMPL (wcsncpy); +diff --git a/sysdeps/s390/multiarch/wcscpy-c.c b/sysdeps/s390/wcscpy-c.c +similarity index 86% +rename from sysdeps/s390/multiarch/wcscpy-c.c +rename to sysdeps/s390/wcscpy-c.c +index 4a510f466be80679..db2967f47d7bc3cc 100644 +--- a/sysdeps/s390/multiarch/wcscpy-c.c ++++ b/sysdeps/s390/wcscpy-c.c +@@ -16,10 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSCPY __wcscpy_c ++#include ++ ++#if HAVE_WCSCPY_C ++# if HAVE_WCSCPY_IFUNC || HAVE_WCSCPY_Z13 ++# define WCSCPY WCSCPY_C ++# endif + +-# include +-extern __typeof (wcscpy) __wcscpy_c; + # include + #endif +diff --git a/sysdeps/s390/multiarch/wcscpy-vx.S b/sysdeps/s390/wcscpy-vx.S +similarity index 95% +rename from sysdeps/s390/multiarch/wcscpy-vx.S +rename to sysdeps/s390/wcscpy-vx.S +index c2e81055be958907..8fe12f4d8b3e66a8 100644 +--- a/sysdeps/s390/multiarch/wcscpy-vx.S ++++ b/sysdeps/s390/wcscpy-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSCPY_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -37,7 +38,7 @@ + -v17=index of zero + -v18=part of src + */ +-ENTRY(__wcscpy_vx) ++ENTRY(WCSCPY_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -106,6 +107,10 @@ ENTRY(__wcscpy_vx) + br %r14 + + .Lfallback: +- jg __wcscpy_c +-END(__wcscpy_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCSCPY_C ++END(WCSCPY_Z13) ++ ++# if ! HAVE_WCSCPY_IFUNC ++strong_alias (WCSCPY_Z13, wcscpy) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcscpy.c b/sysdeps/s390/wcscpy.c +similarity index 70% +rename from sysdeps/s390/multiarch/wcscpy.c +rename to sysdeps/s390/wcscpy.c +index e69baa6c59906df3..51f07327da1bec74 100644 +--- a/sysdeps/s390/multiarch/wcscpy.c ++++ b/sysdeps/s390/wcscpy.c +@@ -16,12 +16,23 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSCPY_IFUNC + # include + # include + +-s390_vx_libc_ifunc2 (__wcscpy, wcscpy) ++# if HAVE_WCSCPY_C ++extern __typeof (wcscpy) WCSCPY_C attribute_hidden; ++# endif ++ ++# if HAVE_WCSCPY_Z13 ++extern __typeof (wcscpy) WCSCPY_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (wcscpy, wcscpy, ++ (HAVE_WCSCPY_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSCPY_Z13 ++ : WCSCPY_DEFAULT ++ ) ++#endif diff --git a/glibc-rh1659438-39.patch b/glibc-rh1659438-39.patch new file mode 100755 index 0000000..8fe2754 --- /dev/null +++ b/glibc-rh1659438-39.patch @@ -0,0 +1,252 @@ +commit 0582e4284529b4ea0fcd1a8973ccab7d95ec0e87 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:19 2018 +0100 + + S390: Refactor wcpcpy ifunc handling. + + The ifunc handling for wcpcpy is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcpcpy variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcpcpy variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcpcpy. + * sysdeps/s390/multiarch/wcpcpy-c.c: Move to ... + * sysdeps/s390/wcpcpy-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcpcpy-vx.S: Move to ... + * sysdeps/s390/wcpcpy-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcpcpy.c: Move to ... + * sysdeps/s390/wcpcpy.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcpcpy.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 8bdbd1b5d8e9df01..5b6446f55299af03 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -62,5 +62,6 @@ endif + ifeq ($(subdir),wcsmbs) + sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcsnlen wcsnlen-vx wcsnlen-c \ +- wcscpy wcscpy-vx wcscpy-c ++ wcscpy wcscpy-vx wcscpy-c \ ++ wcpcpy wcpcpy-vx wcpcpy-c + endif +diff --git a/sysdeps/s390/ifunc-wcpcpy.h b/sysdeps/s390/ifunc-wcpcpy.h +new file mode 100644 +index 0000000000000000..0d5e2ba1a0b09905 +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcpcpy.h +@@ -0,0 +1,53 @@ ++/* wcpcpy variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCPCPY_IFUNC 1 ++#else ++# define HAVE_WCPCPY_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCPCPY_IFUNC_AND_VX_SUPPORT HAVE_WCPCPY_IFUNC ++#else ++# define HAVE_WCPCPY_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCPCPY_DEFAULT WCPCPY_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCPCPY_C 1 ++# define HAVE_WCPCPY_Z13 1 ++#else ++# define WCPCPY_DEFAULT WCPCPY_C ++# define HAVE_WCPCPY_C 1 ++# define HAVE_WCPCPY_Z13 HAVE_WCPCPY_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCPCPY_C ++# define WCPCPY_C __wcpcpy_c ++#else ++# define WCPCPY_C NULL ++#endif ++ ++#if HAVE_WCPCPY_Z13 ++# define WCPCPY_Z13 __wcpcpy_vx ++#else ++# define WCPCPY_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 8828897a59ae580c..7d7b05dcf21cff7d 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcpcpy wcpcpy-vx wcpcpy-c \ +- wcsncpy wcsncpy-vx wcsncpy-c \ ++sysdep_routines += wcsncpy wcsncpy-vx wcsncpy-c \ + wcpncpy wcpncpy-vx wcpncpy-c \ + wcscat wcscat-vx wcscat-c \ + wcsncat wcsncat-vx wcsncat-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index aac8f4ea4671d0cf..656ab59db66dbb48 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -463,6 +464,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSCPY_IFUNC */ + ++#if HAVE_WCPCPY_IFUNC ++ IFUNC_IMPL (i, name, wcpcpy, ++# if HAVE_WCPCPY_Z13 ++ IFUNC_IMPL_ADD (array, i, wcpcpy, ++ dl_hwcap & HWCAP_S390_VX, WCPCPY_Z13) ++# endif ++# if HAVE_WCPCPY_C ++ IFUNC_IMPL_ADD (array, i, wcpcpy, 1, WCPCPY_C) ++# endif ++ ) ++#endif /* HAVE_WCPCPY_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -471,8 +484,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcpcpy); +- + IFUNC_VX_IMPL (wcsncpy); + + IFUNC_VX_IMPL (wcpncpy); +diff --git a/sysdeps/s390/multiarch/wcpcpy-c.c b/sysdeps/s390/wcpcpy-c.c +similarity index 86% +rename from sysdeps/s390/multiarch/wcpcpy-c.c +rename to sysdeps/s390/wcpcpy-c.c +index e3282fde19c5262a..ed1539cde2f6f858 100644 +--- a/sysdeps/s390/multiarch/wcpcpy-c.c ++++ b/sysdeps/s390/wcpcpy-c.c +@@ -16,10 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCPCPY __wcpcpy_c ++#include ++ ++#if HAVE_WCPCPY_C ++# if HAVE_WCPCPY_IFUNC || HAVE_WCPCPY_Z13 ++# define WCPCPY WCPCPY_C ++# endif + +-# include +-extern __typeof (__wcpcpy) __wcpcpy_c; + # include + #endif +diff --git a/sysdeps/s390/multiarch/wcpcpy-vx.S b/sysdeps/s390/wcpcpy-vx.S +similarity index 94% +rename from sysdeps/s390/multiarch/wcpcpy-vx.S +rename to sysdeps/s390/wcpcpy-vx.S +index bff6e8562884066c..5154ad44610c1ed1 100644 +--- a/sysdeps/s390/multiarch/wcpcpy-vx.S ++++ b/sysdeps/s390/wcpcpy-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCPCPY_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -37,7 +38,7 @@ + -v17=index of zero + -v18=part of src + */ +-ENTRY(__wcpcpy_vx) ++ENTRY(WCPCPY_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -109,6 +110,11 @@ ENTRY(__wcpcpy_vx) + br %r14 + + .Lfallback: +- jg __wcpcpy_c +-END(__wcpcpy_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCPCPY_C ++END(WCPCPY_Z13) ++ ++# if ! HAVE_WCPCPY_IFUNC ++strong_alias (WCPCPY_Z13, __wcpcpy) ++weak_alias (__wcpcpy, wcpcpy) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcpcpy.c b/sysdeps/s390/wcpcpy.c +similarity index 70% +rename from sysdeps/s390/multiarch/wcpcpy.c +rename to sysdeps/s390/wcpcpy.c +index f19d376d8530d0a4..34ac68b31fedcb09 100644 +--- a/sysdeps/s390/multiarch/wcpcpy.c ++++ b/sysdeps/s390/wcpcpy.c +@@ -16,13 +16,24 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCPCPY_IFUNC + # include + # include + +-s390_vx_libc_ifunc (__wcpcpy) +-weak_alias (__wcpcpy, wcpcpy) ++# if HAVE_WCPCPY_C ++extern __typeof (__wcpcpy) WCPCPY_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_WCPCPY_Z13 ++extern __typeof (__wcpcpy) WCPCPY_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__wcpcpy, __wcpcpy, ++ (HAVE_WCPCPY_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCPCPY_Z13 ++ : WCPCPY_DEFAULT ++ ) ++weak_alias (__wcpcpy, wcpcpy) ++#endif diff --git a/glibc-rh1659438-4.patch b/glibc-rh1659438-4.patch new file mode 100755 index 0000000..38bf785 --- /dev/null +++ b/glibc-rh1659438-4.patch @@ -0,0 +1,521 @@ +commit 712a254a97ade7f48fb7a434339faa05c048ce1f +Author: Stefan Liebler +Date: Tue Dec 18 13:57:04 2018 +0100 + + S390: Refactor memset ifunc handling. + + This patch moves all ifunc variants for memset + to sysdeps/s390/memset-z900.S. The configure-check/preprocessor logic + in sysdeps/s390/ifunc-memset.h decides if ifunc is needed at all + and which ifunc variants should be available. + E.g. if the compiler/assembler already supports z196 by default, + the older ifunc variants are not included. + If we only need the newest ifunc variant, + then we can skip ifunc at all. + + Therefore the ifunc-resolvers and __libc_ifunc_impl_list are adjusted + in order to handle only the available ifunc variants. + + ChangeLog: + + * sysdeps/s390/ifunc-memset.h: New File. + * sysdeps/s390/memset.S: Move to ... + * sysdeps/s390/memset-z900.S ... here. + Move implementations from memset-s390x.s to here. + * sysdeps/s390/multiarch/memset-s390x.S: Delete File. + * sysdeps/s390/multiarch/Makefile (sysdep_routines): + Remove memset variants. + * sysdeps/s390/Makefile (sysdep_routines): + Add memset variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Adjust ifunc variants for + memset. + * sysdeps/s390/multiarch/memset.c: Move ifunc resolver + to ... + * sysdeps/s390/memset.c: ... here. + Adjust ifunc variants for memset. + +Conflicts: + sysdeps/s390/Makefile + Missing backport of commit 69e2444ab1444ab8210598abbcb4822701d368b9 + ("S390: Test that lazy binding does not clobber R0"). + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 8a54f88cd7ac880e..360838e172f4ca37 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -29,3 +29,7 @@ $(inst_gconvdir)/%.so: $(objpfx)%.so $(+force) + + sysdeps-gconv-modules = ../sysdeps/s390/gconv-modules + endif ++ ++ifeq ($(subdir),string) ++sysdep_routines += memset memset-z900 ++endif +diff --git a/sysdeps/s390/ifunc-memset.h b/sysdeps/s390/ifunc-memset.h +new file mode 100644 +index 0000000000000000..9a13b1001fed9979 +--- /dev/null ++++ b/sysdeps/s390/ifunc-memset.h +@@ -0,0 +1,65 @@ ++/* memset variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# define HAVE_MEMSET_IFUNC 1 ++#else ++# define HAVE_MEMSET_IFUNC 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# define MEMSET_DEFAULT MEMSET_Z196 ++# define HAVE_MEMSET_Z900_G5 0 ++# define HAVE_MEMSET_Z10 0 ++# define HAVE_MEMSET_Z196 1 ++#elif defined HAVE_S390_MIN_Z10_ZARCH_ASM_SUPPORT ++# define MEMSET_DEFAULT MEMSET_Z10 ++# define HAVE_MEMSET_Z900_G5 0 ++# define HAVE_MEMSET_Z10 1 ++# define HAVE_MEMSET_Z196 HAVE_MEMSET_IFUNC ++#else ++# define MEMSET_DEFAULT MEMSET_Z900_G5 ++# define HAVE_MEMSET_Z900_G5 1 ++# define HAVE_MEMSET_Z10 HAVE_MEMSET_IFUNC ++# define HAVE_MEMSET_Z196 HAVE_MEMSET_IFUNC ++#endif ++ ++#if HAVE_MEMSET_Z10 || HAVE_MEMSET_Z196 ++# define HAVE_MEMSET_MVCLE 1 ++#else ++# define HAVE_MEMSET_MVCLE 0 ++#endif ++ ++#if HAVE_MEMSET_Z900_G5 ++# define MEMSET_Z900_G5 __memset_default ++#else ++# define MEMSET_Z900_G5 NULL ++#endif ++ ++#if HAVE_MEMSET_Z10 ++# define MEMSET_Z10 __memset_z10 ++#else ++# define MEMSET_Z10 NULL ++#endif ++ ++#if HAVE_MEMSET_Z196 ++# define MEMSET_Z196 __memset_z196 ++#else ++# define MEMSET_Z196 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/memset-s390x.S b/sysdeps/s390/memset-z900.S +similarity index 57% +rename from sysdeps/s390/multiarch/memset-s390x.S +rename to sysdeps/s390/memset-z900.S +index aca3ac3fda1dd228..eaf13402bd3e251d 100644 +--- a/sysdeps/s390/multiarch/memset-s390x.S ++++ b/sysdeps/s390/memset-z900.S +@@ -1,5 +1,6 @@ + /* Set a block of memory to some byte value. 31/64 bit S/390 version. +- Copyright (C) 2012-2018 Free Software Foundation, Inc. ++ Copyright (C) 2001-2018 Free Software Foundation, Inc. ++ Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -17,8 +18,9 @@ + . */ + + +-#include "sysdep.h" ++#include + #include "asm-syntax.h" ++#include + + /* INPUT PARAMETERS + %r2 = address of memory area +@@ -27,43 +29,68 @@ + + .text + +-#if IS_IN (libc) ++#if HAVE_MEMSET_Z900_G5 ++# if defined __s390x__ ++# define LTGR ltgr ++# define CGHI cghi ++# define LGR lgr ++# define AGHI aghi ++# define BRCTG brctg ++# else ++# define LTGR ltr ++# define CGHI chi ++# define LGR lr ++# define AGHI ahi ++# define BRCTG brct ++# endif /* ! defined __s390x__ */ + +-ENTRY(__memset_z196) +- .machine "z196" +- .machinemode "zarch_nohighgprs" +-# if !defined __s390x__ +- llgfr %r4,%r4 +-# endif /* !defined __s390x__ */ +- ltgr %r4,%r4 +- je .L_Z196_4 ++ENTRY(MEMSET_Z900_G5) ++#if defined __s390x__ ++ .machine "z900" ++#else ++ .machine "g5" ++#endif /* ! defined __s390x__ */ ++ LTGR %r4,%r4 ++ je .L_Z900_G5_4 + stc %r3,0(%r2) +- lgr %r1,%r2 +- cghi %r4,1 +- je .L_Z196_4 +- aghi %r4,-2 +- srlg %r5,%r4,8 +- ltgr %r5,%r5 +- jne .L_Z196_1 +-.L_Z196_3: +- exrl %r4,.L_Z196_17 +-.L_Z196_4: ++ CGHI %r4,1 ++ LGR %r1,%r2 ++ je .L_Z900_G5_4 ++ AGHI %r4,-2 ++#if defined __s390x__ ++ larl %r5,.L_Z900_G5_18 ++ srlg %r3,%r4,8 ++# define Z900_G5_EX_D 0 ++#else ++ basr %r5,0 ++.L_Z900_G5_19: ++# define Z900_G5_EX_D .L_Z900_G5_18-.L_Z900_G5_19 ++ lr %r3,%r4 ++ srl %r3,8 ++#endif /* ! defined __s390x__ */ ++ LTGR %r3,%r3 ++ jne .L_Z900_G5_14 ++.L_Z900_G5_3: ++ ex %r4,Z900_G5_EX_D(%r5) ++.L_Z900_G5_4: + br %r14 +-.L_Z196_1: +- cgfi %r5,1048576 +- jh __memset_mvcle # Switch to mvcle for >256MB +-.L_Z196_2: +- pfd 2,1024(%r1) ++.L_Z900_G5_14: + mvc 1(256,%r1),0(%r1) +- aghi %r5,-1 + la %r1,256(%r1) +- jne .L_Z196_2 +- j .L_Z196_3 +-.L_Z196_17: ++ BRCTG %r3,.L_Z900_G5_14 ++ j .L_Z900_G5_3 ++.L_Z900_G5_18: + mvc 1(1,%r1),0(%r1) +-END(__memset_z196) ++END(MEMSET_Z900_G5) ++# undef LTGR ++# undef CGHI ++# undef LGR ++# undef AGHI ++# undef BRCTG ++#endif /* HAVE_MEMSET_Z900_G5 */ + +-ENTRY(__memset_z10) ++#if HAVE_MEMSET_Z10 ++ENTRY(MEMSET_Z10) + .machine "z10" + .machinemode "zarch_nohighgprs" + # if !defined __s390x__ +@@ -91,8 +118,46 @@ ENTRY(__memset_z10) + j .L_Z10_3 + .L_Z10_18: + mvc 1(1,%r1),0(%r1) +-END(__memset_z10) ++END(MEMSET_Z10) ++#endif /* HAVE_MEMSET_Z10 */ ++ ++#if HAVE_MEMSET_Z196 ++ENTRY(MEMSET_Z196) ++ .machine "z196" ++ .machinemode "zarch_nohighgprs" ++# if !defined __s390x__ ++ llgfr %r4,%r4 ++# endif /* !defined __s390x__ */ ++ ltgr %r4,%r4 ++ je .L_Z196_4 ++ stc %r3,0(%r2) ++ lgr %r1,%r2 ++ cghi %r4,1 ++ je .L_Z196_4 ++ aghi %r4,-2 ++ srlg %r5,%r4,8 ++ ltgr %r5,%r5 ++ jne .L_Z196_1 ++.L_Z196_3: ++ exrl %r4,.L_Z196_17 ++.L_Z196_4: ++ br %r14 ++.L_Z196_1: ++ cgfi %r5,1048576 ++ jh __memset_mvcle # Switch to mvcle for >256MB ++.L_Z196_2: ++ pfd 2,1024(%r1) ++ mvc 1(256,%r1),0(%r1) ++ aghi %r5,-1 ++ la %r1,256(%r1) ++ jne .L_Z196_2 ++ j .L_Z196_3 ++.L_Z196_17: ++ mvc 1(1,%r1),0(%r1) ++END(MEMSET_Z196) ++#endif /* HAVE_MEMSET_Z196 */ + ++#if HAVE_MEMSET_MVCLE + ENTRY(__memset_mvcle) + aghi %r4,2 # take back the change done by the caller + lgr %r0,%r2 # save source address +@@ -106,15 +171,16 @@ ENTRY(__memset_mvcle) + .L1: + br %r14 + END(__memset_mvcle) ++#endif /* HAVE_MEMSET_MVCLE */ + +-#endif /* IS_IN (libc) */ +- +-#include "../memset.S" ++#if ! HAVE_MEMSET_IFUNC ++/* If we don't use ifunc, define an alias for memset here. ++ Otherwise see sysdeps/s390/memset.c. */ ++strong_alias (MEMSET_DEFAULT, memset) ++#endif + +-#if !IS_IN (libc) +-.globl memset +-.set memset,__memset_default +-#elif defined SHARED && IS_IN (libc) +-.globl __GI_memset +-.set __GI_memset,__memset_default ++#if defined SHARED && IS_IN (libc) ++/* Defines the internal symbol. ++ Compare to libc_hidden_builtin_def (memset) in string/memset.c. */ ++strong_alias (MEMSET_DEFAULT, __GI_memset) + #endif +diff --git a/sysdeps/s390/memset.S b/sysdeps/s390/memset.S +deleted file mode 100644 +index 72e7c5a42efbaf6c..0000000000000000 +--- a/sysdeps/s390/memset.S ++++ /dev/null +@@ -1,97 +0,0 @@ +-/* Set a block of memory to some byte value. 31/64 bit S/390 version. +- Copyright (C) 2001-2018 Free Software Foundation, Inc. +- Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). +- 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 +- . */ +- +- +-#include +-#include "asm-syntax.h" +- +-/* INPUT PARAMETERS +- %r2 = address of memory area +- %r3 = byte to fill memory with +- %r4 = number of bytes to fill. */ +- +- .text +- +-#if defined __s390x__ +-# define LTGR ltgr +-# define CGHI cghi +-# define LGR lgr +-# define AGHI aghi +-# define BRCTG brctg +-#else +-# define LTGR ltr +-# define CGHI chi +-# define LGR lr +-# define AGHI ahi +-# define BRCTG brct +-#endif /* ! defined __s390x__ */ +- +-#ifdef USE_MULTIARCH +-ENTRY(__memset_default) +-#else +-ENTRY(memset) +-#endif +-#if defined __s390x__ +- .machine "z900" +-#else +- .machine "g5" +-#endif /* ! defined __s390x__ */ +- LTGR %r4,%r4 +- je .L_Z900_G5_4 +- stc %r3,0(%r2) +- CGHI %r4,1 +- LGR %r1,%r2 +- je .L_Z900_G5_4 +- AGHI %r4,-2 +-#if defined __s390x__ +- larl %r5,.L_Z900_G5_18 +- srlg %r3,%r4,8 +-# define Z900_G5_EX_D 0 +-#else +- basr %r5,0 +-.L_Z900_G5_19: +-# define Z900_G5_EX_D .L_Z900_G5_18-.L_Z900_G5_19 +- lr %r3,%r4 +- srl %r3,8 +-#endif /* ! defined __s390x__ */ +- LTGR %r3,%r3 +- jne .L_Z900_G5_14 +-.L_Z900_G5_3: +- ex %r4,Z900_G5_EX_D(%r5) +-.L_Z900_G5_4: +- br %r14 +-.L_Z900_G5_14: +- mvc 1(256,%r1),0(%r1) +- la %r1,256(%r1) +- BRCTG %r3,.L_Z900_G5_14 +- j .L_Z900_G5_3 +-.L_Z900_G5_18: +- mvc 1(1,%r1),0(%r1) +-#ifdef USE_MULTIARCH +-END(__memset_default) +-#else +-END(memset) +-libc_hidden_builtin_def (memset) +-#endif +- +-#undef LTGR +-#undef CGHI +-#undef LGR +-#undef AGHI +-#undef BRCTG +diff --git a/sysdeps/s390/multiarch/memset.c b/sysdeps/s390/memset.c +similarity index 60% +rename from sysdeps/s390/multiarch/memset.c +rename to sysdeps/s390/memset.c +index 760b3e9df201b8b4..57a35aebc7d3c794 100644 +--- a/sysdeps/s390/multiarch/memset.c ++++ b/sysdeps/s390/memset.c +@@ -16,11 +16,33 @@ + License along with the GNU C Library; if not, see + . */ + +-#if IS_IN (libc) ++#include ++#if HAVE_MEMSET_IFUNC + # define memset __redirect_memset + # include + # undef memset + # include + +-s390_libc_ifunc (__redirect_memset, __memset, memset) ++# if HAVE_MEMSET_Z900_G5 ++extern __typeof (__redirect_memset) MEMSET_Z900_G5 attribute_hidden; ++# endif ++ ++# if HAVE_MEMSET_Z10 ++extern __typeof (__redirect_memset) MEMSET_Z10 attribute_hidden; ++# endif ++ ++# if HAVE_MEMSET_Z196 ++extern __typeof (__redirect_memset) MEMSET_Z196 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect_memset, memset, ++ ({ ++ s390_libc_ifunc_init (); ++ (HAVE_MEMSET_Z196 && S390_IS_Z196 (stfle_bits)) ++ ? MEMSET_Z196 ++ : (HAVE_MEMSET_Z10 && S390_IS_Z10 (stfle_bits)) ++ ? MEMSET_Z10 ++ : MEMSET_DEFAULT; ++ }) ++ ) + #endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 93ad21bfa2686ee5..c893ebc5659fd4ae 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -19,8 +19,7 @@ sysdep_routines += strlen strlen-vx strlen-c \ + rawmemchr rawmemchr-vx rawmemchr-c \ + memccpy memccpy-vx memccpy-c \ + memrchr memrchr-vx memrchr-c \ +- mempcpy \ +- memset memset-s390x ++ mempcpy + endif + + ifeq ($(subdir),wcsmbs) +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index ec3373ae2653d66e..2f671eac1f4f1ffd 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -46,12 +47,21 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + S390_STORE_STFLE (stfle_bits); + } + ++#if HAVE_MEMSET_IFUNC + IFUNC_IMPL (i, name, memset, ++# if HAVE_MEMSET_Z196 + IFUNC_IMPL_ADD (array, i, memset, +- S390_IS_Z196 (stfle_bits), __memset_z196) ++ S390_IS_Z196 (stfle_bits), MEMSET_Z196) ++# endif ++# if HAVE_MEMSET_Z10 + IFUNC_IMPL_ADD (array, i, memset, +- S390_IS_Z10 (stfle_bits), __memset_z10) +- IFUNC_IMPL_ADD (array, i, memset, 1, __memset_default)) ++ S390_IS_Z10 (stfle_bits), MEMSET_Z10) ++# endif ++# if HAVE_MEMSET_Z900_G5 ++ IFUNC_IMPL_ADD (array, i, memset, 1, MEMSET_Z900_G5) ++# endif ++ ) ++#endif /* HAVE_MEMSET_IFUNC */ + + IFUNC_IMPL (i, name, memcmp, + IFUNC_IMPL_ADD (array, i, memcmp, diff --git a/glibc-rh1659438-40.patch b/glibc-rh1659438-40.patch new file mode 100755 index 0000000..3eddef4 --- /dev/null +++ b/glibc-rh1659438-40.patch @@ -0,0 +1,253 @@ +commit 0966dd86896d7cd6c107c751ba7d3b69542ca11d +Author: Stefan Liebler +Date: Tue Dec 18 13:57:19 2018 +0100 + + S390: Refactor wcsncpy ifunc handling. + + The ifunc handling for wcsncpy is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcsncpy variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcsncpy variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcsncpy. + * sysdeps/s390/multiarch/wcsncpy-c.c: Move to ... + * sysdeps/s390/wcsncpy-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcsncpy-vx.S: Move to ... + * sysdeps/s390/wcsncpy-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcsncpy.c: Move to ... + * sysdeps/s390/wcsncpy.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcsncpy.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 5b6446f55299af03..cc8357361e1f2574 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -63,5 +63,6 @@ ifeq ($(subdir),wcsmbs) + sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcsnlen wcsnlen-vx wcsnlen-c \ + wcscpy wcscpy-vx wcscpy-c \ +- wcpcpy wcpcpy-vx wcpcpy-c ++ wcpcpy wcpcpy-vx wcpcpy-c \ ++ wcsncpy wcsncpy-vx wcsncpy-c + endif +diff --git a/sysdeps/s390/ifunc-wcsncpy.h b/sysdeps/s390/ifunc-wcsncpy.h +new file mode 100644 +index 0000000000000000..d7beca128aaaebc8 +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcsncpy.h +@@ -0,0 +1,53 @@ ++/* wcsncpy variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSNCPY_IFUNC 1 ++#else ++# define HAVE_WCSNCPY_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSNCPY_IFUNC_AND_VX_SUPPORT HAVE_WCSNCPY_IFUNC ++#else ++# define HAVE_WCSNCPY_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSNCPY_DEFAULT WCSNCPY_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCSNCPY_C 1 ++# define HAVE_WCSNCPY_Z13 1 ++#else ++# define WCSNCPY_DEFAULT WCSNCPY_C ++# define HAVE_WCSNCPY_C 1 ++# define HAVE_WCSNCPY_Z13 HAVE_WCSNCPY_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSNCPY_C ++# define WCSNCPY_C __wcsncpy_c ++#else ++# define WCSNCPY_C NULL ++#endif ++ ++#if HAVE_WCSNCPY_Z13 ++# define WCSNCPY_Z13 __wcsncpy_vx ++#else ++# define WCSNCPY_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 7d7b05dcf21cff7d..6631fd14d32fde72 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcsncpy wcsncpy-vx wcsncpy-c \ +- wcpncpy wcpncpy-vx wcpncpy-c \ ++sysdep_routines += wcpncpy wcpncpy-vx wcpncpy-c \ + wcscat wcscat-vx wcscat-c \ + wcsncat wcsncat-vx wcsncat-c \ + wcscmp wcscmp-vx wcscmp-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 656ab59db66dbb48..9ebaf4de6f2eb841 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -50,6 +50,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -476,6 +477,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCPCPY_IFUNC */ + ++#if HAVE_WCSNCPY_IFUNC ++ IFUNC_IMPL (i, name, wcsncpy, ++# if HAVE_WCSNCPY_Z13 ++ IFUNC_IMPL_ADD (array, i, wcsncpy, ++ dl_hwcap & HWCAP_S390_VX, WCSNCPY_Z13) ++# endif ++# if HAVE_WCSNCPY_C ++ IFUNC_IMPL_ADD (array, i, wcsncpy, 1, WCSNCPY_C) ++# endif ++ ) ++#endif /* HAVE_WCSNCPY_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -484,8 +497,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcsncpy); +- + IFUNC_VX_IMPL (wcpncpy); + + IFUNC_VX_IMPL (wcscat); +diff --git a/sysdeps/s390/multiarch/wcsncpy-c.c b/sysdeps/s390/wcsncpy-c.c +similarity index 85% +rename from sysdeps/s390/multiarch/wcsncpy-c.c +rename to sysdeps/s390/wcsncpy-c.c +index 6b89b8c14bf58198..4d0ddb09ecb1c849 100644 +--- a/sysdeps/s390/multiarch/wcsncpy-c.c ++++ b/sysdeps/s390/wcsncpy-c.c +@@ -16,10 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSNCPY __wcsncpy_c ++#include ++ ++#if HAVE_WCSNCPY_C ++# if HAVE_WCSNCPY_IFUNC || HAVE_WCSNCPY_Z13 ++# define WCSNCPY WCSNCPY_C ++# endif + +-# include +-extern __typeof (__wcsncpy) __wcsncpy_c; + # include + #endif +diff --git a/sysdeps/s390/multiarch/wcsncpy-vx.S b/sysdeps/s390/wcsncpy-vx.S +similarity index 97% +rename from sysdeps/s390/multiarch/wcsncpy-vx.S +rename to sysdeps/s390/wcsncpy-vx.S +index b3400d50d9ab3324..9bcbdbf3229033da 100644 +--- a/sysdeps/s390/multiarch/wcsncpy-vx.S ++++ b/sysdeps/s390/wcsncpy-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSNCPY_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -40,7 +41,7 @@ + -v18=part of src + -v31=register save area for r6, r7 + */ +-ENTRY(__wcsncpy_vx) ++ENTRY(WCSNCPY_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -217,7 +218,11 @@ ENTRY(__wcsncpy_vx) + j .Llt64 + + .Lfallback: +- jg __wcsncpy_c +-END(__wcsncpy_vx) +- +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCSNCPY_C ++END(WCSNCPY_Z13) ++ ++# if ! HAVE_WCSNCPY_IFUNC ++strong_alias (WCSNCPY_Z13, __wcsncpy) ++weak_alias (__wcsncpy, wcsncpy) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcsncpy.c b/sysdeps/s390/wcsncpy.c +similarity index 70% +rename from sysdeps/s390/multiarch/wcsncpy.c +rename to sysdeps/s390/wcsncpy.c +index 7209c7d4310d6013..e011de7ee7652bec 100644 +--- a/sysdeps/s390/multiarch/wcsncpy.c ++++ b/sysdeps/s390/wcsncpy.c +@@ -16,13 +16,24 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSNCPY_IFUNC + # include + # include + +-s390_vx_libc_ifunc (__wcsncpy) +-weak_alias (__wcsncpy, wcsncpy) ++# if HAVE_WCSNCPY_C ++extern __typeof (__wcsncpy) WCSNCPY_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_WCSNCPY_Z13 ++extern __typeof (__wcsncpy) WCSNCPY_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__wcsncpy, __wcsncpy, ++ (HAVE_WCSNCPY_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSNCPY_Z13 ++ : WCSNCPY_DEFAULT ++ ) ++weak_alias (__wcsncpy, wcsncpy) ++#endif diff --git a/glibc-rh1659438-41.patch b/glibc-rh1659438-41.patch new file mode 100755 index 0000000..ee4a97f --- /dev/null +++ b/glibc-rh1659438-41.patch @@ -0,0 +1,252 @@ +commit c3081bcbd91a619115f047c2ceea90a9090d5216 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:19 2018 +0100 + + S390: Refactor wcpncpy ifunc handling. + + The ifunc handling for wcpncpy is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcpncpy variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcpncpy variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcpncpy. + * sysdeps/s390/multiarch/wcpncpy-c.c: Move to ... + * sysdeps/s390/wcpncpy-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcpncpy-vx.S: Move to ... + * sysdeps/s390/wcpncpy-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcpncpy.c: Move to ... + * sysdeps/s390/wcpncpy.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcpncpy.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index cc8357361e1f2574..640177370382235f 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -64,5 +64,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcsnlen wcsnlen-vx wcsnlen-c \ + wcscpy wcscpy-vx wcscpy-c \ + wcpcpy wcpcpy-vx wcpcpy-c \ +- wcsncpy wcsncpy-vx wcsncpy-c ++ wcsncpy wcsncpy-vx wcsncpy-c \ ++ wcpncpy wcpncpy-vx wcpncpy-c + endif +diff --git a/sysdeps/s390/ifunc-wcpncpy.h b/sysdeps/s390/ifunc-wcpncpy.h +new file mode 100644 +index 0000000000000000..0dd5633aa9cd780b +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcpncpy.h +@@ -0,0 +1,53 @@ ++/* wcpncpy variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCPNCPY_IFUNC 1 ++#else ++# define HAVE_WCPNCPY_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCPNCPY_IFUNC_AND_VX_SUPPORT HAVE_WCPNCPY_IFUNC ++#else ++# define HAVE_WCPNCPY_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCPNCPY_DEFAULT WCPNCPY_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCPNCPY_C 1 ++# define HAVE_WCPNCPY_Z13 1 ++#else ++# define WCPNCPY_DEFAULT WCPNCPY_C ++# define HAVE_WCPNCPY_C 1 ++# define HAVE_WCPNCPY_Z13 HAVE_WCPNCPY_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCPNCPY_C ++# define WCPNCPY_C __wcpncpy_c ++#else ++# define WCPNCPY_C NULL ++#endif ++ ++#if HAVE_WCPNCPY_Z13 ++# define WCPNCPY_Z13 __wcpncpy_vx ++#else ++# define WCPNCPY_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 6631fd14d32fde72..158fb495523438b4 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcpncpy wcpncpy-vx wcpncpy-c \ +- wcscat wcscat-vx wcscat-c \ ++sysdep_routines += wcscat wcscat-vx wcscat-c \ + wcsncat wcsncat-vx wcsncat-c \ + wcscmp wcscmp-vx wcscmp-c \ + wcsncmp wcsncmp-vx wcsncmp-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 9ebaf4de6f2eb841..e60238fcde4dcd4f 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -51,6 +51,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -489,6 +490,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSNCPY_IFUNC */ + ++#if HAVE_WCPNCPY_IFUNC ++ IFUNC_IMPL (i, name, wcpncpy, ++# if HAVE_WCPNCPY_Z13 ++ IFUNC_IMPL_ADD (array, i, wcpncpy, ++ dl_hwcap & HWCAP_S390_VX, WCPNCPY_Z13) ++# endif ++# if HAVE_WCPNCPY_C ++ IFUNC_IMPL_ADD (array, i, wcpncpy, 1, WCPNCPY_C) ++# endif ++ ) ++#endif /* HAVE_WCPNCPY_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -497,8 +510,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcpncpy); +- + IFUNC_VX_IMPL (wcscat); + + IFUNC_VX_IMPL (wcsncat); +diff --git a/sysdeps/s390/multiarch/wcpncpy-c.c b/sysdeps/s390/wcpncpy-c.c +similarity index 85% +rename from sysdeps/s390/multiarch/wcpncpy-c.c +rename to sysdeps/s390/wcpncpy-c.c +index 1f44bacea9b65d44..d03359217e98a1f3 100644 +--- a/sysdeps/s390/multiarch/wcpncpy-c.c ++++ b/sysdeps/s390/wcpncpy-c.c +@@ -16,10 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCPNCPY __wcpncpy_c ++#include ++ ++#if HAVE_WCPNCPY_C ++# if HAVE_WCPNCPY_IFUNC || HAVE_WCPNCPY_Z13 ++# define WCPNCPY WCPNCPY_C ++# endif + +-# include +-extern __typeof (__wcpncpy) __wcpncpy_c; + # include + #endif +diff --git a/sysdeps/s390/multiarch/wcpncpy-vx.S b/sysdeps/s390/wcpncpy-vx.S +similarity index 97% +rename from sysdeps/s390/multiarch/wcpncpy-vx.S +rename to sysdeps/s390/wcpncpy-vx.S +index 004f512e1f1a7982..7b5e4ad32d42d44b 100644 +--- a/sysdeps/s390/multiarch/wcpncpy-vx.S ++++ b/sysdeps/s390/wcpncpy-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCPNCPY_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -38,7 +39,7 @@ + -%r6 = loaded bytes + -%r7 = border, tmp + */ +-ENTRY(__wcpncpy_vx) ++ENTRY(WCPNCPY_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -217,6 +218,11 @@ ENTRY(__wcpncpy_vx) + j .Llt64 + + .Lfallback: +- jg __wcpncpy_c +-END(__wcpncpy_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCPNCPY_C ++END(WCPNCPY_Z13) ++ ++# if ! HAVE_WCPNCPY_IFUNC ++strong_alias (WCPNCPY_Z13, __wcpncpy) ++weak_alias (__wcpncpy, wcpncpy) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcpncpy.c b/sysdeps/s390/wcpncpy.c +similarity index 70% +rename from sysdeps/s390/multiarch/wcpncpy.c +rename to sysdeps/s390/wcpncpy.c +index b72265fbe9df65d0..08d097dd2cb6dfd7 100644 +--- a/sysdeps/s390/multiarch/wcpncpy.c ++++ b/sysdeps/s390/wcpncpy.c +@@ -16,13 +16,24 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCPNCPY_IFUNC + # include + # include + +-s390_vx_libc_ifunc (__wcpncpy) +-weak_alias (__wcpncpy, wcpncpy) ++# if HAVE_WCPNCPY_C ++extern __typeof (__wcpncpy) WCPNCPY_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_WCPNCPY_Z13 ++extern __typeof (__wcpncpy) WCPNCPY_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__wcpncpy, __wcpncpy, ++ (HAVE_WCPNCPY_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCPNCPY_Z13 ++ : WCPNCPY_DEFAULT ++ ) ++weak_alias (__wcpncpy, wcpncpy) ++#endif diff --git a/glibc-rh1659438-42.patch b/glibc-rh1659438-42.patch new file mode 100755 index 0000000..49b154b --- /dev/null +++ b/glibc-rh1659438-42.patch @@ -0,0 +1,252 @@ +commit 3389cae427b4032c3a991cb32b5178a85a652d84 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:20 2018 +0100 + + S390: Refactor wcscat ifunc handling. + + The ifunc handling for wcscat is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcscat variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcscat variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcscat. + * sysdeps/s390/multiarch/wcscat-c.c: Move to ... + * sysdeps/s390/wcscat-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcscat-vx.S: Move to ... + * sysdeps/s390/wcscat-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcscat.c: Move to ... + * sysdeps/s390/wcscat.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcscat.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 640177370382235f..5fd00ad4a8661c4c 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -65,5 +65,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcscpy wcscpy-vx wcscpy-c \ + wcpcpy wcpcpy-vx wcpcpy-c \ + wcsncpy wcsncpy-vx wcsncpy-c \ +- wcpncpy wcpncpy-vx wcpncpy-c ++ wcpncpy wcpncpy-vx wcpncpy-c \ ++ wcscat wcscat-vx wcscat-c + endif +diff --git a/sysdeps/s390/ifunc-wcscat.h b/sysdeps/s390/ifunc-wcscat.h +new file mode 100644 +index 0000000000000000..fecae21403e4c664 +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcscat.h +@@ -0,0 +1,53 @@ ++/* wcscat variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSCAT_IFUNC 1 ++#else ++# define HAVE_WCSCAT_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSCAT_IFUNC_AND_VX_SUPPORT HAVE_WCSCAT_IFUNC ++#else ++# define HAVE_WCSCAT_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSCAT_DEFAULT WCSCAT_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCSCAT_C 1 ++# define HAVE_WCSCAT_Z13 1 ++#else ++# define WCSCAT_DEFAULT WCSCAT_C ++# define HAVE_WCSCAT_C 1 ++# define HAVE_WCSCAT_Z13 HAVE_WCSCAT_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSCAT_C ++# define WCSCAT_C __wcscat_c ++#else ++# define WCSCAT_C NULL ++#endif ++ ++#if HAVE_WCSCAT_Z13 ++# define WCSCAT_Z13 __wcscat_vx ++#else ++# define WCSCAT_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 158fb495523438b4..617017496c79e2ca 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcscat wcscat-vx wcscat-c \ +- wcsncat wcsncat-vx wcsncat-c \ ++sysdep_routines += wcsncat wcsncat-vx wcsncat-c \ + wcscmp wcscmp-vx wcscmp-c \ + wcsncmp wcsncmp-vx wcsncmp-c \ + wcschr wcschr-vx wcschr-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index e60238fcde4dcd4f..b05bd35fd898d0a6 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -52,6 +52,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -502,6 +503,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCPNCPY_IFUNC */ + ++#if HAVE_WCSCAT_IFUNC ++ IFUNC_IMPL (i, name, wcscat, ++# if HAVE_WCSCAT_Z13 ++ IFUNC_IMPL_ADD (array, i, wcscat, ++ dl_hwcap & HWCAP_S390_VX, WCSCAT_Z13) ++# endif ++# if HAVE_WCSCAT_C ++ IFUNC_IMPL_ADD (array, i, wcscat, 1, WCSCAT_C) ++# endif ++ ) ++#endif /* HAVE_WCSCAT_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -510,8 +523,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcscat); +- + IFUNC_VX_IMPL (wcsncat); + + IFUNC_VX_IMPL (wcscmp); +diff --git a/sysdeps/s390/multiarch/wcscat-c.c b/sysdeps/s390/wcscat-c.c +similarity index 86% +rename from sysdeps/s390/multiarch/wcscat-c.c +rename to sysdeps/s390/wcscat-c.c +index 9a31c65a0ba668e5..bc1a50b1a52da259 100644 +--- a/sysdeps/s390/multiarch/wcscat-c.c ++++ b/sysdeps/s390/wcscat-c.c +@@ -16,10 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSCAT __wcscat_c ++#include ++ ++#if HAVE_WCSCAT_C ++# if HAVE_WCSCAT_IFUNC || HAVE_WCSCAT_Z13 ++# define WCSCAT WCSCAT_C ++# endif + +-# include +-extern __typeof (__wcscat) __wcscat_c; + # include + #endif +diff --git a/sysdeps/s390/multiarch/wcscat-vx.S b/sysdeps/s390/wcscat-vx.S +similarity index 96% +rename from sysdeps/s390/multiarch/wcscat-vx.S +rename to sysdeps/s390/wcscat-vx.S +index 2164a8da411eadaa..4e40d69e8417d6d1 100644 +--- a/sysdeps/s390/multiarch/wcscat-vx.S ++++ b/sysdeps/s390/wcscat-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSCAT_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -37,7 +38,7 @@ + -v17=index of zero + -v18=part of src + */ +-ENTRY(__wcscat_vx) ++ENTRY(WCSCAT_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -170,6 +171,11 @@ ENTRY(__wcscat_vx) + lgr %r2,%r0 /* Load saved dest-ptr. */ + br %r14 + .Lfallback: +- jg __wcscat_c +-END(__wcscat_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCSCAT_C ++END(WCSCAT_Z13) ++ ++# if ! HAVE_WCSCAT_IFUNC ++strong_alias (WCSCAT_Z13, __wcscat) ++weak_alias (__wcscat, wcscat) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcscat.c b/sysdeps/s390/wcscat.c +similarity index 70% +rename from sysdeps/s390/multiarch/wcscat.c +rename to sysdeps/s390/wcscat.c +index 33e4f6da3ff8eea7..3741210a177f8029 100644 +--- a/sysdeps/s390/multiarch/wcscat.c ++++ b/sysdeps/s390/wcscat.c +@@ -16,13 +16,24 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSCAT_IFUNC + # include + # include + +-s390_vx_libc_ifunc (__wcscat) +-weak_alias (__wcscat, wcscat) ++# if HAVE_WCSCAT_C ++extern __typeof (__wcscat) WCSCAT_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_WCSCAT_Z13 ++extern __typeof (__wcscat) WCSCAT_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__wcscat, __wcscat, ++ (HAVE_WCSCAT_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSCAT_Z13 ++ : WCSCAT_DEFAULT ++ ) ++weak_alias (__wcscat, wcscat) ++#endif diff --git a/glibc-rh1659438-43.patch b/glibc-rh1659438-43.patch new file mode 100755 index 0000000..df2053a --- /dev/null +++ b/glibc-rh1659438-43.patch @@ -0,0 +1,249 @@ +commit 814a76e1bcc59e6c4899279ede887bf9fecf5a40 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:20 2018 +0100 + + S390: Refactor wcsncat ifunc handling. + + The ifunc handling for wcsncat is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcsncat variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcsncat variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcsncat. + * sysdeps/s390/multiarch/wcsncat-c.c: Move to ... + * sysdeps/s390/wcsncat-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcsncat-vx.S: Move to ... + * sysdeps/s390/wcsncat-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcsncat.c: Move to ... + * sysdeps/s390/wcsncat.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcsncat.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 5fd00ad4a8661c4c..cafabe62165f0213 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -66,5 +66,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcpcpy wcpcpy-vx wcpcpy-c \ + wcsncpy wcsncpy-vx wcsncpy-c \ + wcpncpy wcpncpy-vx wcpncpy-c \ +- wcscat wcscat-vx wcscat-c ++ wcscat wcscat-vx wcscat-c \ ++ wcsncat wcsncat-vx wcsncat-c + endif +diff --git a/sysdeps/s390/ifunc-wcsncat.h b/sysdeps/s390/ifunc-wcsncat.h +new file mode 100644 +index 0000000000000000..99495e0e640611ca +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcsncat.h +@@ -0,0 +1,53 @@ ++/* wcsncat variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSNCAT_IFUNC 1 ++#else ++# define HAVE_WCSNCAT_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSNCAT_IFUNC_AND_VX_SUPPORT HAVE_WCSNCAT_IFUNC ++#else ++# define HAVE_WCSNCAT_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSNCAT_DEFAULT WCSNCAT_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCSNCAT_C 1 ++# define HAVE_WCSNCAT_Z13 1 ++#else ++# define WCSNCAT_DEFAULT WCSNCAT_C ++# define HAVE_WCSNCAT_C 1 ++# define HAVE_WCSNCAT_Z13 HAVE_WCSNCAT_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSNCAT_C ++# define WCSNCAT_C __wcsncat_c ++#else ++# define WCSNCAT_C NULL ++#endif ++ ++#if HAVE_WCSNCAT_Z13 ++# define WCSNCAT_Z13 __wcsncat_vx ++#else ++# define WCSNCAT_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 617017496c79e2ca..6cb75950c2c453f6 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcsncat wcsncat-vx wcsncat-c \ +- wcscmp wcscmp-vx wcscmp-c \ ++sysdep_routines += wcscmp wcscmp-vx wcscmp-c \ + wcsncmp wcsncmp-vx wcsncmp-c \ + wcschr wcschr-vx wcschr-c \ + wcschrnul wcschrnul-vx wcschrnul-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index b05bd35fd898d0a6..7b7b1e7497ec1a4f 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -53,6 +53,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -515,6 +516,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSCAT_IFUNC */ + ++#if HAVE_WCSNCAT_IFUNC ++ IFUNC_IMPL (i, name, wcsncat, ++# if HAVE_WCSNCAT_Z13 ++ IFUNC_IMPL_ADD (array, i, wcsncat, ++ dl_hwcap & HWCAP_S390_VX, WCSNCAT_Z13) ++# endif ++# if HAVE_WCSNCAT_C ++ IFUNC_IMPL_ADD (array, i, wcsncat, 1, WCSNCAT_C) ++# endif ++ ) ++#endif /* HAVE_WCSNCAT_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -523,8 +536,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcsncat); +- + IFUNC_VX_IMPL (wcscmp); + + IFUNC_VX_IMPL (wcsncmp); +diff --git a/sysdeps/s390/multiarch/wcsncat-c.c b/sysdeps/s390/wcsncat-c.c +similarity index 85% +rename from sysdeps/s390/multiarch/wcsncat-c.c +rename to sysdeps/s390/wcsncat-c.c +index 2cf1a76385932c64..5782d5cb28c9e7f6 100644 +--- a/sysdeps/s390/multiarch/wcsncat-c.c ++++ b/sysdeps/s390/wcsncat-c.c +@@ -16,10 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSNCAT __wcsncat_c ++#include ++ ++#if HAVE_WCSNCAT_C ++# if HAVE_WCSNCAT_IFUNC || HAVE_WCSNCAT_Z13 ++# define WCSNCAT WCSNCAT_C ++# endif + +-# include +-extern __typeof (wcsncat) __wcsncat_c; + # include + #endif +diff --git a/sysdeps/s390/multiarch/wcsncat-vx.S b/sysdeps/s390/wcsncat-vx.S +similarity index 97% +rename from sysdeps/s390/multiarch/wcsncat-vx.S +rename to sysdeps/s390/wcsncat-vx.S +index 1d3935690d9f91a3..7c89d3d856faee24 100644 +--- a/sysdeps/s390/multiarch/wcsncat-vx.S ++++ b/sysdeps/s390/wcsncat-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSNCAT_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -40,7 +41,7 @@ + -v18=part of src + -v31=register save area for r6, r7 + */ +-ENTRY(__wcsncat_vx) ++ENTRY(WCSNCAT_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -260,6 +261,10 @@ ENTRY(__wcsncat_vx) + j .Lcpy_lt64 + + .Lfallback: +- jg __wcsncat_c +-END(__wcsncat_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCSNCAT_C ++END(WCSNCAT_Z13) ++ ++# if ! HAVE_WCSNCAT_IFUNC ++strong_alias (WCSNCAT_Z13, wcsncat) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcsncat.c b/sysdeps/s390/wcsncat.c +similarity index 69% +rename from sysdeps/s390/multiarch/wcsncat.c +rename to sysdeps/s390/wcsncat.c +index c49b8ff78671cb99..722429fd5b5b4d9d 100644 +--- a/sysdeps/s390/multiarch/wcsncat.c ++++ b/sysdeps/s390/wcsncat.c +@@ -16,12 +16,23 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSNCAT_IFUNC + # include + # include + +-s390_vx_libc_ifunc2 (__wcsncat, wcsncat) ++# if HAVE_WCSNCAT_C ++extern __typeof (wcsncat) WCSNCAT_C attribute_hidden; ++# endif ++ ++# if HAVE_WCSNCAT_Z13 ++extern __typeof (wcsncat) WCSNCAT_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (wcsncat, wcsncat, ++ (HAVE_WCSNCAT_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSNCAT_Z13 ++ : WCSNCAT_DEFAULT ++ ) ++#endif diff --git a/glibc-rh1659438-44.patch b/glibc-rh1659438-44.patch new file mode 100755 index 0000000..c49fa9a --- /dev/null +++ b/glibc-rh1659438-44.patch @@ -0,0 +1,269 @@ +commit 3459e23dd4ae4aa8999df7111d833a0bb9add7cd +Author: Stefan Liebler +Date: Tue Dec 18 13:57:21 2018 +0100 + + S390: Refactor wcscmp ifunc handling. + + The ifunc handling for wcscmp is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + Glibc internal calls will then also use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcscmp variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcscmp variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcscmp. + * sysdeps/s390/multiarch/wcscmp-c.c: Move to ... + * sysdeps/s390/wcscmp-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcscmp-vx.S: Move to ... + * sysdeps/s390/wcscmp-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcscmp.c: Move to ... + * sysdeps/s390/wcscmp.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcscmp.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index cafabe62165f0213..fb104af231c48d3a 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -67,5 +67,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcsncpy wcsncpy-vx wcsncpy-c \ + wcpncpy wcpncpy-vx wcpncpy-c \ + wcscat wcscat-vx wcscat-c \ +- wcsncat wcsncat-vx wcsncat-c ++ wcsncat wcsncat-vx wcsncat-c \ ++ wcscmp wcscmp-vx wcscmp-c + endif +diff --git a/sysdeps/s390/ifunc-wcscmp.h b/sysdeps/s390/ifunc-wcscmp.h +new file mode 100644 +index 0000000000000000..99fe0213021458ae +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcscmp.h +@@ -0,0 +1,52 @@ ++/* wcscmp variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSCMP_IFUNC 1 ++#else ++# define HAVE_WCSCMP_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSCMP_IFUNC_AND_VX_SUPPORT HAVE_WCSCMP_IFUNC ++#else ++# define HAVE_WCSCMP_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSCMP_DEFAULT WCSCMP_Z13 ++# define HAVE_WCSCMP_C 0 ++# define HAVE_WCSCMP_Z13 1 ++#else ++# define WCSCMP_DEFAULT WCSCMP_C ++# define HAVE_WCSCMP_C 1 ++# define HAVE_WCSCMP_Z13 HAVE_WCSCMP_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSCMP_C ++# define WCSCMP_C __wcscmp_c ++#else ++# define WCSCMP_C NULL ++#endif ++ ++#if HAVE_WCSCMP_Z13 ++# define WCSCMP_Z13 __wcscmp_vx ++#else ++# define WCSCMP_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 6cb75950c2c453f6..70162d0eaa6a0dee 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcscmp wcscmp-vx wcscmp-c \ +- wcsncmp wcsncmp-vx wcsncmp-c \ ++sysdep_routines += wcsncmp wcsncmp-vx wcsncmp-c \ + wcschr wcschr-vx wcschr-c \ + wcschrnul wcschrnul-vx wcschrnul-c \ + wcsrchr wcsrchr-vx wcsrchr-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 7b7b1e7497ec1a4f..f461063c80b364fb 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -54,6 +54,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -528,6 +529,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSNCAT_IFUNC */ + ++#if HAVE_WCSCMP_IFUNC ++ IFUNC_IMPL (i, name, wcscmp, ++# if HAVE_WCSCMP_Z13 ++ IFUNC_IMPL_ADD (array, i, wcscmp, ++ dl_hwcap & HWCAP_S390_VX, WCSCMP_Z13) ++# endif ++# if HAVE_WCSCMP_C ++ IFUNC_IMPL_ADD (array, i, wcscmp, 1, WCSCMP_C) ++# endif ++ ) ++#endif /* HAVE_WCSCMP_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -536,8 +549,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcscmp); +- + IFUNC_VX_IMPL (wcsncmp); + + IFUNC_VX_IMPL (wcschr); +diff --git a/sysdeps/s390/multiarch/wcscmp-c.c b/sysdeps/s390/wcscmp-c.c +similarity index 72% +rename from sysdeps/s390/multiarch/wcscmp-c.c +rename to sysdeps/s390/wcscmp-c.c +index ce0817ae97deab77..643ba7a682469e73 100644 +--- a/sysdeps/s390/multiarch/wcscmp-c.c ++++ b/sysdeps/s390/wcscmp-c.c +@@ -16,17 +16,19 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSCMP __wcscmp_c ++#include + +-# include +-extern __typeof (wcscmp) __wcscmp_c; +-# undef weak_alias +-# define weak_alias(name, alias) +-# ifdef SHARED +-# undef libc_hidden_def +-# define libc_hidden_def(name) \ ++#if HAVE_WCSCMP_C ++# if HAVE_WCSCMP_IFUNC ++# define WCSCMP WCSCMP_C ++# undef weak_alias ++# define weak_alias(name, alias) ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_def ++# define libc_hidden_def(name) \ + __hidden_ver1 (__wcscmp_c, __GI___wcscmp, __wcscmp_c); +-# endif /* SHARED */ ++# endif ++# endif ++ + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/wcscmp-vx.S b/sysdeps/s390/wcscmp-vx.S +similarity index 92% +rename from sysdeps/s390/multiarch/wcscmp-vx.S +rename to sysdeps/s390/wcscmp-vx.S +index 14267dbfc7d9b936..a2789d8a693802cc 100644 +--- a/sysdeps/s390/multiarch/wcscmp-vx.S ++++ b/sysdeps/s390/wcscmp-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSCMP_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -36,7 +37,7 @@ + -v17=part of s2 + -v18=index of unequal + */ +-ENTRY(__wcscmp_vx) ++ENTRY(WCSCMP_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -127,5 +128,14 @@ ENTRY(__wcscmp_vx) + .Lend_equal: + lghi %r2,0 + br %r14 +-END(__wcscmp_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(WCSCMP_Z13) ++ ++# if ! HAVE_WCSCMP_IFUNC ++strong_alias (WCSCMP_Z13, __wcscmp) ++weak_alias (__wcscmp, wcscmp) ++# endif ++ ++# if ! HAVE_WCSCMP_C && defined SHARED && IS_IN (libc) ++strong_alias (WCSCMP_Z13, __GI___wcscmp) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcscmp.c b/sysdeps/s390/wcscmp.c +similarity index 70% +rename from sysdeps/s390/multiarch/wcscmp.c +rename to sysdeps/s390/wcscmp.c +index 5ee0fd4d881db9cb..769c73506e40c3a0 100644 +--- a/sysdeps/s390/multiarch/wcscmp.c ++++ b/sysdeps/s390/wcscmp.c +@@ -16,15 +16,26 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSCMP_IFUNC + # define __wcscmp __redirect___wcscmp + # include + # undef __wcscmp + # include + +-s390_vx_libc_ifunc_redirected (__redirect___wcscmp, __wcscmp) +-weak_alias (__wcscmp, wcscmp) ++# if HAVE_WCSCMP_C ++extern __typeof (__redirect___wcscmp) WCSCMP_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_WCSCMP_Z13 ++extern __typeof (__redirect___wcscmp) WCSCMP_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect___wcscmp, __wcscmp, ++ (HAVE_WCSCMP_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSCMP_Z13 ++ : WCSCMP_DEFAULT ++ ) ++weak_alias (__wcscmp, wcscmp) ++#endif diff --git a/glibc-rh1659438-45.patch b/glibc-rh1659438-45.patch new file mode 100755 index 0000000..a4233ac --- /dev/null +++ b/glibc-rh1659438-45.patch @@ -0,0 +1,245 @@ +commit e9873e1d47c870d707117ada91c9be21e3bf1537 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:21 2018 +0100 + + S390: Refactor wcsncmp ifunc handling. + + The ifunc handling for wcsncmp is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcsncmp variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcsncmp variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcsncmp. + * sysdeps/s390/multiarch/wcsncmp-c.c: Move to ... + * sysdeps/s390/wcsncmp-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcsncmp-vx.S: Move to ... + * sysdeps/s390/wcsncmp-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcsncmp.c: Move to ... + * sysdeps/s390/wcsncmp.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcsncmp.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index fb104af231c48d3a..9146b32a939fd5bd 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -68,5 +68,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcpncpy wcpncpy-vx wcpncpy-c \ + wcscat wcscat-vx wcscat-c \ + wcsncat wcsncat-vx wcsncat-c \ +- wcscmp wcscmp-vx wcscmp-c ++ wcscmp wcscmp-vx wcscmp-c \ ++ wcsncmp wcsncmp-vx wcsncmp-c + endif +diff --git a/sysdeps/s390/ifunc-wcsncmp.h b/sysdeps/s390/ifunc-wcsncmp.h +new file mode 100644 +index 0000000000000000..3a22bc9c126107ad +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcsncmp.h +@@ -0,0 +1,52 @@ ++/* wcsncmp variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSNCMP_IFUNC 1 ++#else ++# define HAVE_WCSNCMP_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSNCMP_IFUNC_AND_VX_SUPPORT HAVE_WCSNCMP_IFUNC ++#else ++# define HAVE_WCSNCMP_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSNCMP_DEFAULT WCSNCMP_Z13 ++# define HAVE_WCSNCMP_C 0 ++# define HAVE_WCSNCMP_Z13 1 ++#else ++# define WCSNCMP_DEFAULT WCSNCMP_C ++# define HAVE_WCSNCMP_C 1 ++# define HAVE_WCSNCMP_Z13 HAVE_WCSNCMP_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSNCMP_C ++# define WCSNCMP_C __wcsncmp_c ++#else ++# define WCSNCMP_C NULL ++#endif ++ ++#if HAVE_WCSNCMP_Z13 ++# define WCSNCMP_Z13 __wcsncmp_vx ++#else ++# define WCSNCMP_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 70162d0eaa6a0dee..d1740fa8e4f5faa8 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcsncmp wcsncmp-vx wcsncmp-c \ +- wcschr wcschr-vx wcschr-c \ ++sysdep_routines += wcschr wcschr-vx wcschr-c \ + wcschrnul wcschrnul-vx wcschrnul-c \ + wcsrchr wcsrchr-vx wcsrchr-c \ + wcsspn wcsspn-vx wcsspn-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index f461063c80b364fb..8c9e788ae5962e2a 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -55,6 +55,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -541,6 +542,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSCMP_IFUNC */ + ++#if HAVE_WCSNCMP_IFUNC ++ IFUNC_IMPL (i, name, wcsncmp, ++# if HAVE_WCSNCMP_Z13 ++ IFUNC_IMPL_ADD (array, i, wcsncmp, ++ dl_hwcap & HWCAP_S390_VX, WCSNCMP_Z13) ++# endif ++# if HAVE_WCSNCMP_C ++ IFUNC_IMPL_ADD (array, i, wcsncmp, 1, WCSNCMP_C) ++# endif ++ ) ++#endif /* HAVE_WCSNCMP_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -549,8 +562,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcsncmp); +- + IFUNC_VX_IMPL (wcschr); + + IFUNC_VX_IMPL (wcschrnul); +diff --git a/sysdeps/s390/multiarch/wcsncmp-c.c b/sysdeps/s390/wcsncmp-c.c +similarity index 85% +rename from sysdeps/s390/multiarch/wcsncmp-c.c +rename to sysdeps/s390/wcsncmp-c.c +index 92ab5e8b50bd93d0..a9ccb8de8276e97c 100644 +--- a/sysdeps/s390/multiarch/wcsncmp-c.c ++++ b/sysdeps/s390/wcsncmp-c.c +@@ -16,10 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSNCMP __wcsncmp_c ++#include ++ ++#if HAVE_WCSNCMP_C ++# if HAVE_WCSNCMP_IFUNC ++# define WCSNCMP WCSNCMP_C ++# endif + +-# include +-extern __typeof (wcsncmp) __wcsncmp_c; + # include + #endif +diff --git a/sysdeps/s390/multiarch/wcsncmp-vx.S b/sysdeps/s390/wcsncmp-vx.S +similarity index 97% +rename from sysdeps/s390/multiarch/wcsncmp-vx.S +rename to sysdeps/s390/wcsncmp-vx.S +index 34c203bc90b2b012..9bdd21acefc2d44d 100644 +--- a/sysdeps/s390/multiarch/wcsncmp-vx.S ++++ b/sysdeps/s390/wcsncmp-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSNCMP_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -37,7 +38,7 @@ + -v17=part of s2 + -v18=index of unequal + */ +-ENTRY(__wcsncmp_vx) ++ENTRY(WCSNCMP_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -173,5 +174,9 @@ ENTRY(__wcsncmp_vx) + lghi %r1,-1 + locgrl %r2,%r1 + br %r14 +-END(__wcsncmp_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(WCSNCMP_Z13) ++ ++# if ! HAVE_WCSNCMP_IFUNC ++strong_alias (WCSNCMP_Z13, wcsncmp) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcsncmp.c b/sysdeps/s390/wcsncmp.c +similarity index 69% +rename from sysdeps/s390/multiarch/wcsncmp.c +rename to sysdeps/s390/wcsncmp.c +index ee5f08c1e4106495..101db445918b0f7d 100644 +--- a/sysdeps/s390/multiarch/wcsncmp.c ++++ b/sysdeps/s390/wcsncmp.c +@@ -16,12 +16,23 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSNCMP_IFUNC + # include + # include + +-s390_vx_libc_ifunc2 (__wcsncmp, wcsncmp) ++# if HAVE_WCSNCMP_C ++extern __typeof (wcsncmp) WCSNCMP_C attribute_hidden; ++# endif ++ ++# if HAVE_WCSNCMP_Z13 ++extern __typeof (wcsncmp) WCSNCMP_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (wcsncmp, wcsncmp, ++ (HAVE_WCSNCMP_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSNCMP_Z13 ++ : WCSNCMP_DEFAULT ++ ) ++#endif diff --git a/glibc-rh1659438-46.patch b/glibc-rh1659438-46.patch new file mode 100755 index 0000000..a4a0eb0 --- /dev/null +++ b/glibc-rh1659438-46.patch @@ -0,0 +1,292 @@ +commit cf3ccc31a3d76a9b4db410d3087055c3aff2b71b +Author: Stefan Liebler +Date: Tue Dec 18 13:57:22 2018 +0100 + + S390: Refactor wcschr ifunc handling. + + The ifunc handling for wcschr is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + Glibc internal calls will use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcschr variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcschr variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcschr. + * sysdeps/s390/multiarch/wcschr-c.c: Move to ... + * sysdeps/s390/wcschr-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcschr-vx.S: Move to ... + * sysdeps/s390/wcschr-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcschr.c: Move to ... + * sysdeps/s390/wcschr.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcschr.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 9146b32a939fd5bd..91ee84a54b713e4a 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -69,5 +69,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcscat wcscat-vx wcscat-c \ + wcsncat wcsncat-vx wcsncat-c \ + wcscmp wcscmp-vx wcscmp-c \ +- wcsncmp wcsncmp-vx wcsncmp-c ++ wcsncmp wcsncmp-vx wcsncmp-c \ ++ wcschr wcschr-vx wcschr-c + endif +diff --git a/sysdeps/s390/ifunc-wcschr.h b/sysdeps/s390/ifunc-wcschr.h +new file mode 100644 +index 0000000000000000..2fe9110f7c9564d2 +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcschr.h +@@ -0,0 +1,53 @@ ++/* wcschr variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSCHR_IFUNC 1 ++#else ++# define HAVE_WCSCHR_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSCHR_IFUNC_AND_VX_SUPPORT HAVE_WCSCHR_IFUNC ++#else ++# define HAVE_WCSCHR_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSCHR_DEFAULT WCSCHR_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCSCHR_C 1 ++# define HAVE_WCSCHR_Z13 1 ++#else ++# define WCSCHR_DEFAULT WCSCHR_C ++# define HAVE_WCSCHR_C 1 ++# define HAVE_WCSCHR_Z13 HAVE_WCSCHR_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSCHR_C ++# define WCSCHR_C __wcschr_c ++#else ++# define WCSCHR_C NULL ++#endif ++ ++#if HAVE_WCSCHR_Z13 ++# define WCSCHR_Z13 __wcschr_vx ++#else ++# define WCSCHR_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index d1740fa8e4f5faa8..b282613b4705bb14 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcschr wcschr-vx wcschr-c \ +- wcschrnul wcschrnul-vx wcschrnul-c \ ++sysdep_routines += wcschrnul wcschrnul-vx wcschrnul-c \ + wcsrchr wcsrchr-vx wcsrchr-c \ + wcsspn wcsspn-vx wcsspn-c \ + wcspbrk wcspbrk-vx wcspbrk-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 8c9e788ae5962e2a..c69165465dc97111 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -56,6 +56,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -554,6 +555,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSNCMP_IFUNC */ + ++#if HAVE_WCSCHR_IFUNC ++ IFUNC_IMPL (i, name, wcschr, ++# if HAVE_WCSCHR_Z13 ++ IFUNC_IMPL_ADD (array, i, wcschr, ++ dl_hwcap & HWCAP_S390_VX, WCSCHR_Z13) ++# endif ++# if HAVE_WCSCHR_C ++ IFUNC_IMPL_ADD (array, i, wcschr, 1, WCSCHR_C) ++# endif ++ ) ++#endif /* HAVE_WCSCHR_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -562,8 +575,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcschr); +- + IFUNC_VX_IMPL (wcschrnul); + + IFUNC_VX_IMPL (wcsrchr); +diff --git a/sysdeps/s390/multiarch/wcschr-c.c b/sysdeps/s390/wcschr-c.c +similarity index 61% +rename from sysdeps/s390/multiarch/wcschr-c.c +rename to sysdeps/s390/wcschr-c.c +index 8d6679c7f2f89864..4908492a0a72ed28 100644 +--- a/sysdeps/s390/multiarch/wcschr-c.c ++++ b/sysdeps/s390/wcschr-c.c +@@ -16,22 +16,29 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSCHR __wcschr_c +- +-# include +-extern __typeof (__wcschr) __wcschr_c; +-# undef weak_alias +-# define weak_alias(name, alias) +-# ifdef SHARED +-# undef libc_hidden_def +-# define libc_hidden_def(name) \ +- __hidden_ver1 (__wcschr_c, __GI_wcschr, __wcschr_c); \ +- strong_alias (__wcschr_c, __wcschr_c_1); \ ++#include ++ ++#if HAVE_WCSCHR_C ++# if HAVE_WCSCHR_IFUNC || HAVE_WCSCHR_Z13 ++# define WCSCHR WCSCHR_C ++ ++# undef weak_alias ++# define weak_alias(name, alias) ++ ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_weak ++# define libc_hidden_weak(name) ++# undef libc_hidden_def ++# if ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define libc_hidden_def(name) \ ++ __hidden_ver1 (__wcschr_c, __GI_wcschr, __wcschr_c) __attribute__((weak)); \ ++ strong_alias (__wcschr_c, __wcschr_c_1); \ + __hidden_ver1 (__wcschr_c_1, __GI___wcschr, __wcschr_c_1); +-# undef libc_hidden_weak +-# define libc_hidden_weak(name) +-# endif /* SHARED */ ++# else ++# define libc_hidden_def(name) ++# endif ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/wcschr-vx.S b/sysdeps/s390/wcschr-vx.S +similarity index 88% +rename from sysdeps/s390/multiarch/wcschr-vx.S +rename to sysdeps/s390/wcschr-vx.S +index 94e5df7f365aa361..dd24998390c7e2e6 100644 +--- a/sysdeps/s390/multiarch/wcschr-vx.S ++++ b/sysdeps/s390/wcschr-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSCHR_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -36,7 +37,7 @@ + -v17=index of unequal + -v18=replicated c + */ +-ENTRY(__wcschr_vx) ++ENTRY(WCSCHR_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -98,6 +99,17 @@ ENTRY(__wcschr_vx) + lghi %r2,0 /* Return null if character not found. */ + br %r14 + .Lfallback: +- jg __wcschr_c +-END(__wcschr_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCSCHR_C ++END(WCSCHR_Z13) ++ ++# if ! HAVE_WCSCHR_IFUNC ++strong_alias (WCSCHR_Z13, __wcschr) ++weak_alias (__wcschr, wcschr) ++# endif ++ ++# if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT \ ++ && defined SHARED && IS_IN (libc) ++strong_alias (WCSCHR_Z13, __GI___wcschr) ++weak_alias (WCSCHR_Z13, __GI_wcschr) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcschr.c b/sysdeps/s390/wcschr.c +similarity index 71% +rename from sysdeps/s390/multiarch/wcschr.c +rename to sysdeps/s390/wcschr.c +index f44138f771f9f9cb..9923864ff8f5ef1f 100644 +--- a/sysdeps/s390/multiarch/wcschr.c ++++ b/sysdeps/s390/wcschr.c +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSCHR_IFUNC + # define wcschr __redirect_wcschr + # define __wcschr __redirect___wcschr + # include +@@ -24,9 +26,18 @@ + # undef __wcschr + # include + +-s390_vx_libc_ifunc_redirected (__redirect___wcschr, __wcschr) +-weak_alias (__wcschr, wcschr) ++# if HAVE_WCSCHR_C ++extern __typeof (__redirect___wcschr) WCSCHR_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_WCSCHR_Z13 ++extern __typeof (__redirect___wcschr) WCSCHR_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect___wcschr, __wcschr, ++ (HAVE_WCSCHR_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSCHR_Z13 ++ : WCSCHR_DEFAULT ++ ) ++weak_alias (__wcschr, wcschr) ++#endif diff --git a/glibc-rh1659438-47.patch b/glibc-rh1659438-47.patch new file mode 100755 index 0000000..d79d982 --- /dev/null +++ b/glibc-rh1659438-47.patch @@ -0,0 +1,252 @@ +commit c09c1b6f014a45f6c4ba189f5ae94b1fb1a2982a +Author: Stefan Liebler +Date: Tue Dec 18 13:57:22 2018 +0100 + + S390: Refactor wcschrnul ifunc handling. + + The ifunc handling for wcschrnul is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcschrnul variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcschrnul variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcschrnul. + * sysdeps/s390/multiarch/wcschrnul-c.c: Move to ... + * sysdeps/s390/wcschrnul-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcschrnul-vx.S: Move to ... + * sysdeps/s390/wcschrnul-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcschrnul.c: Move to ... + * sysdeps/s390/wcschrnul.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcschrnul.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 91ee84a54b713e4a..a6ebf11ad1913cc4 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -70,5 +70,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcsncat wcsncat-vx wcsncat-c \ + wcscmp wcscmp-vx wcscmp-c \ + wcsncmp wcsncmp-vx wcsncmp-c \ +- wcschr wcschr-vx wcschr-c ++ wcschr wcschr-vx wcschr-c \ ++ wcschrnul wcschrnul-vx wcschrnul-c + endif +diff --git a/sysdeps/s390/ifunc-wcschrnul.h b/sysdeps/s390/ifunc-wcschrnul.h +new file mode 100644 +index 0000000000000000..39d4120eb3cfafdf +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcschrnul.h +@@ -0,0 +1,53 @@ ++/* wcschrnul variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSCHRNUL_IFUNC 1 ++#else ++# define HAVE_WCSCHRNUL_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSCHRNUL_IFUNC_AND_VX_SUPPORT HAVE_WCSCHRNUL_IFUNC ++#else ++# define HAVE_WCSCHRNUL_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSCHRNUL_DEFAULT WCSCHRNUL_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCSCHRNUL_C 1 ++# define HAVE_WCSCHRNUL_Z13 1 ++#else ++# define WCSCHRNUL_DEFAULT WCSCHRNUL_C ++# define HAVE_WCSCHRNUL_C 1 ++# define HAVE_WCSCHRNUL_Z13 HAVE_WCSCHRNUL_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSCHRNUL_C ++# define WCSCHRNUL_C __wcschrnul_c ++#else ++# define WCSCHRNUL_C NULL ++#endif ++ ++#if HAVE_WCSCHRNUL_Z13 ++# define WCSCHRNUL_Z13 __wcschrnul_vx ++#else ++# define WCSCHRNUL_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index b282613b4705bb14..0eb01d5d84c60408 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcschrnul wcschrnul-vx wcschrnul-c \ +- wcsrchr wcsrchr-vx wcsrchr-c \ ++sysdep_routines += wcsrchr wcsrchr-vx wcsrchr-c \ + wcsspn wcsspn-vx wcsspn-c \ + wcspbrk wcspbrk-vx wcspbrk-c \ + wcscspn wcscspn-vx wcscspn-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index c69165465dc97111..553a76c39ecc87ae 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -57,6 +57,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -567,6 +568,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSCHR_IFUNC */ + ++#if HAVE_WCSCHRNUL_IFUNC ++ IFUNC_IMPL (i, name, wcschrnul, ++# if HAVE_WCSCHRNUL_Z13 ++ IFUNC_IMPL_ADD (array, i, wcschrnul, ++ dl_hwcap & HWCAP_S390_VX, WCSCHRNUL_Z13) ++# endif ++# if HAVE_WCSCHRNUL_C ++ IFUNC_IMPL_ADD (array, i, wcschrnul, 1, WCSCHRNUL_C) ++# endif ++ ) ++#endif /* HAVE_WCSCHRNUL_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -575,8 +588,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcschrnul); +- + IFUNC_VX_IMPL (wcsrchr); + + IFUNC_VX_IMPL (wcsspn); +diff --git a/sysdeps/s390/multiarch/wcschrnul-c.c b/sysdeps/s390/wcschrnul-c.c +similarity index 85% +rename from sysdeps/s390/multiarch/wcschrnul-c.c +rename to sysdeps/s390/wcschrnul-c.c +index 00e776a3adc11e67..410cee1399a67914 100644 +--- a/sysdeps/s390/multiarch/wcschrnul-c.c ++++ b/sysdeps/s390/wcschrnul-c.c +@@ -16,10 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSCHRNUL __wcschrnul_c ++#include ++ ++#if HAVE_WCSCHRNUL_C ++# if HAVE_WCSCHRNUL_IFUNC || HAVE_WCSCHRNUL_Z13 ++# define WCSCHRNUL WCSCHRNUL_C ++# endif + +-# include +-extern __typeof (__wcschrnul) __wcschrnul_c; + # include + #endif +diff --git a/sysdeps/s390/multiarch/wcschrnul-vx.S b/sysdeps/s390/wcschrnul-vx.S +similarity index 92% +rename from sysdeps/s390/multiarch/wcschrnul-vx.S +rename to sysdeps/s390/wcschrnul-vx.S +index ebcd32b8703608d6..4ffb937c6bbd7008 100644 +--- a/sysdeps/s390/multiarch/wcschrnul-vx.S ++++ b/sysdeps/s390/wcschrnul-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSCHRNUL_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -35,7 +36,7 @@ + -v16=part of s + -v18=vector with c replicated in every byte + */ +-ENTRY(__wcschrnul_vx) ++ENTRY(WCSCHRNUL_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -92,6 +93,11 @@ ENTRY(__wcschrnul_vx) + .Lend: + br %r14 + .Lfallback: +- jg __wcschrnul_c +-END(__wcschrnul_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCSCHRNUL_C ++END(WCSCHRNUL_Z13) ++ ++# if ! HAVE_WCSCHRNUL_IFUNC ++strong_alias (WCSCHRNUL_Z13, __wcschrnul) ++weak_alias (__wcschrnul, wcschrnul) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcschrnul.c b/sysdeps/s390/wcschrnul.c +similarity index 68% +rename from sysdeps/s390/multiarch/wcschrnul.c +rename to sysdeps/s390/wcschrnul.c +index 807d7ee08963a601..ab5aaf04020bb571 100644 +--- a/sysdeps/s390/multiarch/wcschrnul.c ++++ b/sysdeps/s390/wcschrnul.c +@@ -16,13 +16,24 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSCHRNUL_IFUNC + # include + # include + +-s390_vx_libc_ifunc (__wcschrnul) +-weak_alias (__wcschrnul, wcschrnul) ++# if HAVE_WCSCHRNUL_C ++extern __typeof (__wcschrnul) WCSCHRNUL_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_WCSCHRNUL_Z13 ++extern __typeof (__wcschrnul) WCSCHRNUL_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__wcschrnul, __wcschrnul, ++ (HAVE_WCSCHRNUL_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSCHRNUL_Z13 ++ : WCSCHRNUL_DEFAULT ++ ) ++weak_alias (__wcschrnul, wcschrnul) ++#endif diff --git a/glibc-rh1659438-48.patch b/glibc-rh1659438-48.patch new file mode 100755 index 0000000..f786c3b --- /dev/null +++ b/glibc-rh1659438-48.patch @@ -0,0 +1,249 @@ +commit 4753713aaed400d88cfc598e25d504478120b065 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:22 2018 +0100 + + S390: Refactor wcsrchr ifunc handling. + + The ifunc handling for wcsrchr is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcsrchr variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcsrchr variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcsrchr. + * sysdeps/s390/multiarch/wcsrchr-c.c: Move to ... + * sysdeps/s390/wcsrchr-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcsrchr-vx.S: Move to ... + * sysdeps/s390/wcsrchr-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcsrchr.c: Move to ... + * sysdeps/s390/wcsrchr.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcsrchr.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index a6ebf11ad1913cc4..19a556eccf285e2f 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -71,5 +71,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcscmp wcscmp-vx wcscmp-c \ + wcsncmp wcsncmp-vx wcsncmp-c \ + wcschr wcschr-vx wcschr-c \ +- wcschrnul wcschrnul-vx wcschrnul-c ++ wcschrnul wcschrnul-vx wcschrnul-c \ ++ wcsrchr wcsrchr-vx wcsrchr-c + endif +diff --git a/sysdeps/s390/ifunc-wcsrchr.h b/sysdeps/s390/ifunc-wcsrchr.h +new file mode 100644 +index 0000000000000000..4eec0c17074c99fc +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcsrchr.h +@@ -0,0 +1,53 @@ ++/* wcsrchr variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSRCHR_IFUNC 1 ++#else ++# define HAVE_WCSRCHR_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSRCHR_IFUNC_AND_VX_SUPPORT HAVE_WCSRCHR_IFUNC ++#else ++# define HAVE_WCSRCHR_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSRCHR_DEFAULT WCSRCHR_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCSRCHR_C 1 ++# define HAVE_WCSRCHR_Z13 1 ++#else ++# define WCSRCHR_DEFAULT WCSRCHR_C ++# define HAVE_WCSRCHR_C 1 ++# define HAVE_WCSRCHR_Z13 HAVE_WCSRCHR_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSRCHR_C ++# define WCSRCHR_C __wcsrchr_c ++#else ++# define WCSRCHR_C NULL ++#endif ++ ++#if HAVE_WCSRCHR_Z13 ++# define WCSRCHR_Z13 __wcsrchr_vx ++#else ++# define WCSRCHR_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 0eb01d5d84c60408..3d72cbb5f32e68f3 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcsrchr wcsrchr-vx wcsrchr-c \ +- wcsspn wcsspn-vx wcsspn-c \ ++sysdep_routines += wcsspn wcsspn-vx wcsspn-c \ + wcspbrk wcspbrk-vx wcspbrk-c \ + wcscspn wcscspn-vx wcscspn-c \ + wmemchr wmemchr-vx wmemchr-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 553a76c39ecc87ae..ffb4d5b6872ef9db 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -58,6 +58,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -580,6 +581,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSCHRNUL_IFUNC */ + ++#if HAVE_WCSRCHR_IFUNC ++ IFUNC_IMPL (i, name, wcsrchr, ++# if HAVE_WCSRCHR_Z13 ++ IFUNC_IMPL_ADD (array, i, wcsrchr, ++ dl_hwcap & HWCAP_S390_VX, WCSRCHR_Z13) ++# endif ++# if HAVE_WCSRCHR_C ++ IFUNC_IMPL_ADD (array, i, wcsrchr, 1, WCSRCHR_C) ++# endif ++ ) ++#endif /* HAVE_WCSRCHR_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -588,8 +601,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcsrchr); +- + IFUNC_VX_IMPL (wcsspn); + + IFUNC_VX_IMPL (wcspbrk); +diff --git a/sysdeps/s390/multiarch/wcsrchr-c.c b/sysdeps/s390/wcsrchr-c.c +similarity index 85% +rename from sysdeps/s390/multiarch/wcsrchr-c.c +rename to sysdeps/s390/wcsrchr-c.c +index 615250358ba9c00a..65164a897fb773f7 100644 +--- a/sysdeps/s390/multiarch/wcsrchr-c.c ++++ b/sysdeps/s390/wcsrchr-c.c +@@ -16,10 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSRCHR __wcsrchr_c ++#include ++ ++#if HAVE_WCSRCHR_C ++# if HAVE_WCSRCHR_IFUNC || HAVE_WCSRCHR_Z13 ++# define WCSRCHR WCSRCHR_C ++# endif + +-# include +-extern __typeof (wcsrchr) __wcsrchr_c; + # include + #endif +diff --git a/sysdeps/s390/multiarch/wcsrchr-vx.S b/sysdeps/s390/wcsrchr-vx.S +similarity index 97% +rename from sysdeps/s390/multiarch/wcsrchr-vx.S +rename to sysdeps/s390/wcsrchr-vx.S +index e40a554e5d9a216d..c7b6585beaeaef53 100644 +--- a/sysdeps/s390/multiarch/wcsrchr-vx.S ++++ b/sysdeps/s390/wcsrchr-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSRCHR_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -39,7 +40,7 @@ + -v19=part of s with last occurence of c. + -v20=permute pattern + */ +-ENTRY(__wcsrchr_vx) ++ENTRY(WCSRCHR_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -185,6 +186,10 @@ ENTRY(__wcsrchr_vx) + .byte 0x0C,0x0D,0x0E,0x0F,0x08,0x09,0x0A,0x0B + .byte 0x04,0x05,0x06,0x07,0x00,0x01,0x02,0x03 + .Lfallback: +- jg __wcsrchr_c +-END(__wcsrchr_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCSRCHR_C ++END(WCSRCHR_Z13) ++ ++# if ! HAVE_WCSRCHR_IFUNC ++strong_alias (WCSRCHR_Z13, wcsrchr) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcsrchr.c b/sysdeps/s390/wcsrchr.c +similarity index 69% +rename from sysdeps/s390/multiarch/wcsrchr.c +rename to sysdeps/s390/wcsrchr.c +index aa0b8a8f82545f64..eb70f270383880f2 100644 +--- a/sysdeps/s390/multiarch/wcsrchr.c ++++ b/sysdeps/s390/wcsrchr.c +@@ -16,12 +16,23 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSRCHR_IFUNC + # include + # include + +-s390_vx_libc_ifunc2 (__wcsrchr, wcsrchr) ++# if HAVE_WCSRCHR_C ++extern __typeof (wcsrchr) WCSRCHR_C attribute_hidden; ++# endif ++ ++# if HAVE_WCSRCHR_Z13 ++extern __typeof (wcsrchr) WCSRCHR_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (wcsrchr, wcsrchr, ++ (HAVE_WCSRCHR_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSRCHR_Z13 ++ : WCSRCHR_DEFAULT ++ ) ++#endif diff --git a/glibc-rh1659438-49.patch b/glibc-rh1659438-49.patch new file mode 100755 index 0000000..3508d5e --- /dev/null +++ b/glibc-rh1659438-49.patch @@ -0,0 +1,271 @@ +commit 8507e831907ff46d06382fe453c6832db2594e0b +Author: Stefan Liebler +Date: Tue Dec 18 13:57:23 2018 +0100 + + S390: Refactor wcsspn ifunc handling. + + The ifunc handling for wcsspn is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + Glibc internal calls will use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcsspn variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcsspn variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcsspn. + * sysdeps/s390/multiarch/wcsspn-c.c: Move to ... + * sysdeps/s390/wcsspn-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcsspn-vx.S: Move to ... + * sysdeps/s390/wcsspn-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcsspn.c: Move to ... + * sysdeps/s390/wcsspn.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcsspn.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 19a556eccf285e2f..38dbba8ccfd3cd66 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -72,5 +72,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcsncmp wcsncmp-vx wcsncmp-c \ + wcschr wcschr-vx wcschr-c \ + wcschrnul wcschrnul-vx wcschrnul-c \ +- wcsrchr wcsrchr-vx wcsrchr-c ++ wcsrchr wcsrchr-vx wcsrchr-c \ ++ wcsspn wcsspn-vx wcsspn-c + endif +diff --git a/sysdeps/s390/ifunc-wcsspn.h b/sysdeps/s390/ifunc-wcsspn.h +new file mode 100644 +index 0000000000000000..1189c6b93ff9fbec +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcsspn.h +@@ -0,0 +1,53 @@ ++/* wcsspn variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSSPN_IFUNC 1 ++#else ++# define HAVE_WCSSPN_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSSPN_IFUNC_AND_VX_SUPPORT HAVE_WCSSPN_IFUNC ++#else ++# define HAVE_WCSSPN_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSSPN_DEFAULT WCSSPN_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCSSPN_C 1 ++# define HAVE_WCSSPN_Z13 1 ++#else ++# define WCSSPN_DEFAULT WCSSPN_C ++# define HAVE_WCSSPN_C 1 ++# define HAVE_WCSSPN_Z13 HAVE_WCSSPN_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSSPN_C ++# define WCSSPN_C __wcsspn_c ++#else ++# define WCSSPN_C NULL ++#endif ++ ++#if HAVE_WCSSPN_Z13 ++# define WCSSPN_Z13 __wcsspn_vx ++#else ++# define WCSSPN_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 3d72cbb5f32e68f3..091f5150847a404a 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcsspn wcsspn-vx wcsspn-c \ +- wcspbrk wcspbrk-vx wcspbrk-c \ ++sysdep_routines += wcspbrk wcspbrk-vx wcspbrk-c \ + wcscspn wcscspn-vx wcscspn-c \ + wmemchr wmemchr-vx wmemchr-c \ + wmemset wmemset-vx wmemset-c \ +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index ffb4d5b6872ef9db..6f4de2845ba0a378 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -59,6 +59,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -593,6 +594,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSRCHR_IFUNC */ + ++#if HAVE_WCSSPN_IFUNC ++ IFUNC_IMPL (i, name, wcsspn, ++# if HAVE_WCSSPN_Z13 ++ IFUNC_IMPL_ADD (array, i, wcsspn, ++ dl_hwcap & HWCAP_S390_VX, WCSSPN_Z13) ++# endif ++# if HAVE_WCSSPN_C ++ IFUNC_IMPL_ADD (array, i, wcsspn, 1, WCSSPN_C) ++# endif ++ ) ++#endif /* HAVE_WCSSPN_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -601,8 +614,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcsspn); +- + IFUNC_VX_IMPL (wcspbrk); + + IFUNC_VX_IMPL (wcscspn); +diff --git a/sysdeps/s390/multiarch/wcsspn-c.c b/sysdeps/s390/wcsspn-c.c +similarity index 72% +rename from sysdeps/s390/multiarch/wcsspn-c.c +rename to sysdeps/s390/wcsspn-c.c +index 2c0bd0f4e69516de..db3bdb9b9f09e500 100644 +--- a/sysdeps/s390/multiarch/wcsspn-c.c ++++ b/sysdeps/s390/wcsspn-c.c +@@ -16,16 +16,22 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSSPN __wcsspn_c ++#include + +-# include +-extern __typeof (wcsspn) __wcsspn_c; +-# ifdef SHARED +-# undef libc_hidden_def +-# define libc_hidden_def(name) \ ++#if HAVE_WCSSPN_C ++# if HAVE_WCSSPN_IFUNC || HAVE_WCSSPN_Z13 ++# define WCSSPN WCSSPN_C ++ ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_def ++# if ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define libc_hidden_def(name) \ + __hidden_ver1 (__wcsspn_c, __GI_wcsspn, __wcsspn_c); +-# endif /* SHARED */ ++# else ++# define libc_hidden_def(name) ++# endif ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/wcsspn-vx.S b/sysdeps/s390/wcsspn-vx.S +similarity index 97% +rename from sysdeps/s390/multiarch/wcsspn-vx.S +rename to sysdeps/s390/wcsspn-vx.S +index 548f2ad1644c8e88..61f7d6d0902125b7 100644 +--- a/sysdeps/s390/multiarch/wcsspn-vx.S ++++ b/sysdeps/s390/wcsspn-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSSPN_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -57,7 +58,7 @@ + otherwise =0; + r9: loaded byte count of vlbb accept-string + */ +-ENTRY(__wcsspn_vx) ++ENTRY(WCSSPN_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -265,6 +266,15 @@ ENTRY(__wcsspn_vx) + j .Lslow_next_acc_notonbb /* ... and search for zero in + fully loaded vreg again. */ + .Lfallback: +- jg __wcsspn_c +-END(__wcsspn_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCSSPN_C ++END(WCSSPN_Z13) ++ ++# if ! HAVE_WCSSPN_IFUNC ++strong_alias (WCSSPN_Z13, wcsspn) ++# endif ++ ++# if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT \ ++ && defined SHARED && IS_IN (libc) ++strong_alias (WCSSPN_Z13, __GI_wcsspn) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcsspn.c b/sysdeps/s390/wcsspn.c +similarity index 69% +rename from sysdeps/s390/multiarch/wcsspn.c +rename to sysdeps/s390/wcsspn.c +index 7743144a8ca7c2ee..e916b1e4414e774d 100644 +--- a/sysdeps/s390/multiarch/wcsspn.c ++++ b/sysdeps/s390/wcsspn.c +@@ -16,14 +16,24 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSSPN_IFUNC + # define wcsspn __redirect_wcsspn + # include + # undef wcsspn + # include ++# if HAVE_WCSSPN_C ++extern __typeof (__redirect_wcsspn) WCSSPN_C attribute_hidden; ++# endif + +-s390_vx_libc_ifunc2_redirected (__redirect_wcsspn, __wcsspn, wcsspn) ++# if HAVE_WCSSPN_Z13 ++extern __typeof (__redirect_wcsspn) WCSSPN_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (__redirect_wcsspn, wcsspn, ++ (HAVE_WCSSPN_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSSPN_Z13 ++ : WCSSPN_DEFAULT ++ ) ++#endif diff --git a/glibc-rh1659438-5.patch b/glibc-rh1659438-5.patch new file mode 100755 index 0000000..440659f --- /dev/null +++ b/glibc-rh1659438-5.patch @@ -0,0 +1,306 @@ +commit 07be392807ac78330da90f01408aa7e042a97a88 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:05 2018 +0100 + + S390: Implement bzero with memset. + + This patch removes the bzero s390 implementation with mvcle and + adds entry points for bzero in memset ifunc variants. + Therefore an ifunc resolver is implemented for bzero, too. + + ChangeLog: + + * sysdeps/s390/s390-32/bzero.S: Delete file. + * sysdeps/s390/s390-64/bzero.S: Likewise. + * sysdeps/s390/Makefile (sysdep_routines): Add bzero. + * sysdeps/s390/bzero.c: New file. + * sysdeps/s390/memset-z900.S: Add bzero entry points. + * sysdeps/s390/ifunc-memset.h: Add bzero function macros. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Add bzero ifunc variants. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 360838e172f4ca37..e40e5bd982e54d89 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -31,5 +31,5 @@ sysdeps-gconv-modules = ../sysdeps/s390/gconv-modules + endif + + ifeq ($(subdir),string) +-sysdep_routines += memset memset-z900 ++sysdep_routines += bzero memset memset-z900 + endif +diff --git a/sysdeps/s390/s390-32/bzero.S b/sysdeps/s390/bzero.c +similarity index 52% +rename from sysdeps/s390/s390-32/bzero.S +rename to sysdeps/s390/bzero.c +index 897aa2154a861b7f..9f8d95781bf2fb68 100644 +--- a/sysdeps/s390/s390-32/bzero.S ++++ b/sysdeps/s390/bzero.c +@@ -1,7 +1,6 @@ +-/* bzero -- set a block of memory to zero. IBM S390 version ++/* Multiple versions of bzero. ++ Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. +- Copyright (C) 2000-2018 Free Software Foundation, Inc. +- Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public +@@ -17,26 +16,32 @@ + License along with the GNU C Library; if not, see + . */ + +-/* +- * R2 = address to memory area +- * R3 = number of bytes to fill +- */ +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +- .text +-ENTRY(__bzero) +- ltr %r3,%r3 +- jz .L1 +- sr %r1,%r1 # set pad byte to zero +- sr %r4,%r4 # no source for MVCLE, only a pad byte +- sr %r5,%r5 +-.L0: mvcle %r2,%r4,0(%r1) # thats it, MVCLE is your friend +- jo .L0 +-.L1: br %r14 +-END(__bzero) +- +-#ifndef NO_WEAK_ALIAS ++#include ++#if HAVE_MEMSET_IFUNC ++# include ++# include ++ ++# if HAVE_MEMSET_Z900_G5 ++extern __typeof (__bzero) BZERO_Z900_G5 attribute_hidden; ++# endif ++ ++# if HAVE_MEMSET_Z10 ++extern __typeof (__bzero) BZERO_Z10 attribute_hidden; ++# endif ++ ++# if HAVE_MEMSET_Z196 ++extern __typeof (__bzero) BZERO_Z196 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__bzero, __bzero, ++ ({ ++ s390_libc_ifunc_init (); ++ (HAVE_MEMSET_Z196 && S390_IS_Z196 (stfle_bits)) ++ ? BZERO_Z196 ++ : (HAVE_MEMSET_Z10 && S390_IS_Z10 (stfle_bits)) ++ ? BZERO_Z10 ++ : BZERO_DEFAULT; ++ }) ++ ) + weak_alias (__bzero, bzero) + #endif +diff --git a/sysdeps/s390/ifunc-memset.h b/sysdeps/s390/ifunc-memset.h +index 9a13b1001fed9979..32bc155f7e79fa26 100644 +--- a/sysdeps/s390/ifunc-memset.h ++++ b/sysdeps/s390/ifunc-memset.h +@@ -25,16 +25,19 @@ + + #if defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT + # define MEMSET_DEFAULT MEMSET_Z196 ++# define BZERO_DEFAULT BZERO_Z196 + # define HAVE_MEMSET_Z900_G5 0 + # define HAVE_MEMSET_Z10 0 + # define HAVE_MEMSET_Z196 1 + #elif defined HAVE_S390_MIN_Z10_ZARCH_ASM_SUPPORT + # define MEMSET_DEFAULT MEMSET_Z10 ++# define BZERO_DEFAULT BZERO_Z10 + # define HAVE_MEMSET_Z900_G5 0 + # define HAVE_MEMSET_Z10 1 + # define HAVE_MEMSET_Z196 HAVE_MEMSET_IFUNC + #else + # define MEMSET_DEFAULT MEMSET_Z900_G5 ++# define BZERO_DEFAULT BZERO_Z900_G5 + # define HAVE_MEMSET_Z900_G5 1 + # define HAVE_MEMSET_Z10 HAVE_MEMSET_IFUNC + # define HAVE_MEMSET_Z196 HAVE_MEMSET_IFUNC +@@ -48,18 +51,24 @@ + + #if HAVE_MEMSET_Z900_G5 + # define MEMSET_Z900_G5 __memset_default ++# define BZERO_Z900_G5 __bzero_default + #else + # define MEMSET_Z900_G5 NULL ++# define BZERO_Z900_G5 NULL + #endif + + #if HAVE_MEMSET_Z10 + # define MEMSET_Z10 __memset_z10 ++# define BZERO_Z10 __bzero_z10 + #else + # define MEMSET_Z10 NULL ++# define BZERO_Z10 NULL + #endif + + #if HAVE_MEMSET_Z196 + # define MEMSET_Z196 __memset_z196 ++# define BZERO_Z196 __bzero_z196 + #else + # define MEMSET_Z196 NULL ++# define BZERO_Z196 NULL + #endif +diff --git a/sysdeps/s390/memset-z900.S b/sysdeps/s390/memset-z900.S +index eaf13402bd3e251d..bfc659ae0b029eb4 100644 +--- a/sysdeps/s390/memset-z900.S ++++ b/sysdeps/s390/memset-z900.S +@@ -22,10 +22,14 @@ + #include "asm-syntax.h" + #include + +-/* INPUT PARAMETERS ++/* INPUT PARAMETERS - MEMSET + %r2 = address of memory area + %r3 = byte to fill memory with +- %r4 = number of bytes to fill. */ ++ %r4 = number of bytes to fill. ++ ++ INPUT PARAMETERS - BZERO ++ %r2 = address of memory area ++ %r3 = number of bytes to fill. */ + + .text + +@@ -44,7 +48,14 @@ + # define BRCTG brct + # endif /* ! defined __s390x__ */ + ++ENTRY(BZERO_Z900_G5) ++ LGR %r4,%r3 ++ xr %r3,%r3 ++ j .L_Z900_G5_start ++END(BZERO_Z900_G5) ++ + ENTRY(MEMSET_Z900_G5) ++.L_Z900_G5_start: + #if defined __s390x__ + .machine "z900" + #else +@@ -90,7 +101,16 @@ END(MEMSET_Z900_G5) + #endif /* HAVE_MEMSET_Z900_G5 */ + + #if HAVE_MEMSET_Z10 ++ENTRY(BZERO_Z10) ++ .machine "z10" ++ .machinemode "zarch_nohighgprs" ++ lgr %r4,%r3 ++ xr %r3,%r3 ++ j .L_Z10_start ++END(BZERO_Z10) ++ + ENTRY(MEMSET_Z10) ++.L_Z10_start: + .machine "z10" + .machinemode "zarch_nohighgprs" + # if !defined __s390x__ +@@ -122,7 +142,16 @@ END(MEMSET_Z10) + #endif /* HAVE_MEMSET_Z10 */ + + #if HAVE_MEMSET_Z196 ++ENTRY(BZERO_Z196) ++ .machine "z196" ++ .machinemode "zarch_nohighgprs" ++ lgr %r4,%r3 ++ xr %r3,%r3 ++ j .L_Z196_start ++END(BZERO_Z196) ++ + ENTRY(MEMSET_Z196) ++.L_Z196_start: + .machine "z196" + .machinemode "zarch_nohighgprs" + # if !defined __s390x__ +@@ -177,6 +206,10 @@ END(__memset_mvcle) + /* If we don't use ifunc, define an alias for memset here. + Otherwise see sysdeps/s390/memset.c. */ + strong_alias (MEMSET_DEFAULT, memset) ++/* Same for bzero. If ifunc is used, see ++ sysdeps/s390/bzero.c. */ ++strong_alias (BZERO_DEFAULT, __bzero) ++weak_alias (__bzero, bzero) + #endif + + #if defined SHARED && IS_IN (libc) +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 2f671eac1f4f1ffd..253f36045b57cc3c 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -59,6 +59,21 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + # endif + # if HAVE_MEMSET_Z900_G5 + IFUNC_IMPL_ADD (array, i, memset, 1, MEMSET_Z900_G5) ++# endif ++ ) ++ ++ /* Note: bzero is implemented in memset. */ ++ IFUNC_IMPL (i, name, bzero, ++# if HAVE_MEMSET_Z196 ++ IFUNC_IMPL_ADD (array, i, bzero, ++ S390_IS_Z196 (stfle_bits), BZERO_Z196) ++# endif ++# if HAVE_MEMSET_Z10 ++ IFUNC_IMPL_ADD (array, i, bzero, ++ S390_IS_Z10 (stfle_bits), BZERO_Z10) ++# endif ++# if HAVE_MEMSET_Z900_G5 ++ IFUNC_IMPL_ADD (array, i, bzero, 1, BZERO_Z900_G5) + # endif + ) + #endif /* HAVE_MEMSET_IFUNC */ +diff --git a/sysdeps/s390/s390-64/bzero.S b/sysdeps/s390/s390-64/bzero.S +deleted file mode 100644 +index b3216652985cc239..0000000000000000 +--- a/sysdeps/s390/s390-64/bzero.S ++++ /dev/null +@@ -1,41 +0,0 @@ +-/* bzero -- set a block of memory to zero. 64 bit S/390 version. +- This file is part of the GNU C Library. +- Copyright (C) 2001-2018 Free Software Foundation, Inc. +- Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). +- +- 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 +- . */ +- +-/* INPUT PARAMETERS +- %r2 = address of memory area +- %r3 = number of bytes to fill. */ +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +- .text +-ENTRY(__bzero) +- ltgr %r3,%r3 +- jz .L1 +- sgr %r1,%r1 # set pad byte to zero +- sgr %r4,%r4 # no source for MVCLE, only a pad byte +- sgr %r5,%r5 +-.L0: mvcle %r2,%r4,0(%r1) # thats it, MVCLE is your friend +- jo .L0 +-.L1: br %r14 +-END(__bzero) +- +-#ifndef NO_WEAK_ALIAS +-weak_alias (__bzero, bzero) +-#endif diff --git a/glibc-rh1659438-50.patch b/glibc-rh1659438-50.patch new file mode 100755 index 0000000..41d29db --- /dev/null +++ b/glibc-rh1659438-50.patch @@ -0,0 +1,271 @@ +commit 8e87c1f6d45a63dc2175825c2dc5d66192a13aab +Author: Stefan Liebler +Date: Tue Dec 18 13:57:23 2018 +0100 + + S390: Refactor wcspbrk ifunc handling. + + The ifunc handling for wcspbrk is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + Glibc internal calls will use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcspbrk variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcspbrk variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcspbrk. + * sysdeps/s390/multiarch/wcspbrk-c.c: Move to ... + * sysdeps/s390/wcspbrk-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcspbrk-vx.S: Move to ... + * sysdeps/s390/wcspbrk-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcspbrk.c: Move to ... + * sysdeps/s390/wcspbrk.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcspbrk.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 38dbba8ccfd3cd66..af595050d43c63ed 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -73,5 +73,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcschr wcschr-vx wcschr-c \ + wcschrnul wcschrnul-vx wcschrnul-c \ + wcsrchr wcsrchr-vx wcsrchr-c \ +- wcsspn wcsspn-vx wcsspn-c ++ wcsspn wcsspn-vx wcsspn-c \ ++ wcspbrk wcspbrk-vx wcspbrk-c + endif +diff --git a/sysdeps/s390/ifunc-wcspbrk.h b/sysdeps/s390/ifunc-wcspbrk.h +new file mode 100644 +index 0000000000000000..d3b9b7363a73fab0 +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcspbrk.h +@@ -0,0 +1,53 @@ ++/* wcspbrk variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSPBRK_IFUNC 1 ++#else ++# define HAVE_WCSPBRK_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSPBRK_IFUNC_AND_VX_SUPPORT HAVE_WCSPBRK_IFUNC ++#else ++# define HAVE_WCSPBRK_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSPBRK_DEFAULT WCSPBRK_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCSPBRK_C 1 ++# define HAVE_WCSPBRK_Z13 1 ++#else ++# define WCSPBRK_DEFAULT WCSPBRK_C ++# define HAVE_WCSPBRK_C 1 ++# define HAVE_WCSPBRK_Z13 HAVE_WCSPBRK_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSPBRK_C ++# define WCSPBRK_C __wcspbrk_c ++#else ++# define WCSPBRK_C NULL ++#endif ++ ++#if HAVE_WCSPBRK_Z13 ++# define WCSPBRK_Z13 __wcspbrk_vx ++#else ++# define WCSPBRK_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 091f5150847a404a..e1e2d9dc7495ebdc 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcspbrk wcspbrk-vx wcspbrk-c \ +- wcscspn wcscspn-vx wcscspn-c \ ++sysdep_routines += wcscspn wcscspn-vx wcscspn-c \ + wmemchr wmemchr-vx wmemchr-c \ + wmemset wmemset-vx wmemset-c \ + wmemcmp wmemcmp-vx wmemcmp-c +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 6f4de2845ba0a378..89d6e8ad7e323fec 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -60,6 +60,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -606,6 +607,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSSPN_IFUNC */ + ++#if HAVE_WCSPBRK_IFUNC ++ IFUNC_IMPL (i, name, wcspbrk, ++# if HAVE_WCSPBRK_Z13 ++ IFUNC_IMPL_ADD (array, i, wcspbrk, ++ dl_hwcap & HWCAP_S390_VX, WCSPBRK_Z13) ++# endif ++# if HAVE_WCSPBRK_C ++ IFUNC_IMPL_ADD (array, i, wcspbrk, 1, WCSPBRK_C) ++# endif ++ ) ++#endif /* HAVE_WCSPBRK_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -614,8 +627,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcspbrk); +- + IFUNC_VX_IMPL (wcscspn); + + IFUNC_VX_IMPL (wmemchr); +diff --git a/sysdeps/s390/multiarch/wcspbrk-c.c b/sysdeps/s390/wcspbrk-c.c +similarity index 72% +rename from sysdeps/s390/multiarch/wcspbrk-c.c +rename to sysdeps/s390/wcspbrk-c.c +index 6b6e7aade46942ed..e79c6a85503dc32b 100644 +--- a/sysdeps/s390/multiarch/wcspbrk-c.c ++++ b/sysdeps/s390/wcspbrk-c.c +@@ -16,16 +16,22 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSPBRK __wcspbrk_c ++#include + +-# include +-extern __typeof (wcspbrk) __wcspbrk_c; +-# ifdef SHARED +-# undef libc_hidden_def +-# define libc_hidden_def(name) \ ++#if HAVE_WCSPBRK_C ++# if HAVE_WCSPBRK_IFUNC || HAVE_WCSPBRK_Z13 ++# define WCSPBRK WCSPBRK_C ++ ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_def ++# if ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define libc_hidden_def(name) \ + __hidden_ver1 (__wcspbrk_c, __GI_wcspbrk, __wcspbrk_c); +-# endif /* SHARED */ ++# else ++# define libc_hidden_def(name) ++# endif ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/wcspbrk-vx.S b/sysdeps/s390/wcspbrk-vx.S +similarity index 97% +rename from sysdeps/s390/multiarch/wcspbrk-vx.S +rename to sysdeps/s390/wcspbrk-vx.S +index 5c89ec5d336c1acd..5870c4684d140ab0 100644 +--- a/sysdeps/s390/multiarch/wcspbrk-vx.S ++++ b/sysdeps/s390/wcspbrk-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSPBRK_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -59,7 +60,7 @@ + otherwise =0; + r9: loaded byte count of vlbb accept-string + */ +-ENTRY(__wcspbrk_vx) ++ENTRY(WCSPBRK_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -310,6 +311,15 @@ ENTRY(__wcspbrk_vx) + lgr %r2,%r1 + br %r14 + .Lfallback: +- jg __wcspbrk_c +-END(__wcspbrk_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCSPBRK_C ++END(WCSPBRK_Z13) ++ ++# if ! HAVE_WCSPBRK_IFUNC ++strong_alias (WCSPBRK_Z13, wcspbrk) ++# endif ++ ++# if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT \ ++ && defined SHARED && IS_IN (libc) ++strong_alias (WCSPBRK_Z13, __GI_wcspbrk) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcspbrk.c b/sysdeps/s390/wcspbrk.c +similarity index 69% +rename from sysdeps/s390/multiarch/wcspbrk.c +rename to sysdeps/s390/wcspbrk.c +index 97876328b5ad9425..84ab911a24fba3c4 100644 +--- a/sysdeps/s390/multiarch/wcspbrk.c ++++ b/sysdeps/s390/wcspbrk.c +@@ -16,14 +16,24 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSPBRK_IFUNC + # define wcspbrk __redirect_wcspbrk + # include + # undef wcspbrk + # include ++# if HAVE_WCSPBRK_C ++extern __typeof (__redirect_wcspbrk) WCSPBRK_C attribute_hidden; ++# endif + +-s390_vx_libc_ifunc2_redirected (__redirect_wcspbrk, __wcspbrk, wcspbrk) ++# if HAVE_WCSPBRK_Z13 ++extern __typeof (__redirect_wcspbrk) WCSPBRK_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (__redirect_wcspbrk, wcspbrk, ++ (HAVE_WCSPBRK_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSPBRK_Z13 ++ : WCSPBRK_DEFAULT ++ ) ++#endif diff --git a/glibc-rh1659438-51.patch b/glibc-rh1659438-51.patch new file mode 100755 index 0000000..264a0e1 --- /dev/null +++ b/glibc-rh1659438-51.patch @@ -0,0 +1,249 @@ +commit 79b44cf61115bd48006227bb325b709f294c56f9 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:23 2018 +0100 + + S390: Refactor wcscspn ifunc handling. + + The ifunc handling for wcscspn is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wcscspn variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wcscspn variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wcscspn. + * sysdeps/s390/multiarch/wcscspn-c.c: Move to ... + * sysdeps/s390/wcscspn-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcscspn-vx.S: Move to ... + * sysdeps/s390/wcscspn-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wcscspn.c: Move to ... + * sysdeps/s390/wcscspn.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wcscspn.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index af595050d43c63ed..da96ac3a36bd7f4e 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -74,5 +74,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcschrnul wcschrnul-vx wcschrnul-c \ + wcsrchr wcsrchr-vx wcsrchr-c \ + wcsspn wcsspn-vx wcsspn-c \ +- wcspbrk wcspbrk-vx wcspbrk-c ++ wcspbrk wcspbrk-vx wcspbrk-c \ ++ wcscspn wcscspn-vx wcscspn-c + endif +diff --git a/sysdeps/s390/ifunc-wcscspn.h b/sysdeps/s390/ifunc-wcscspn.h +new file mode 100644 +index 0000000000000000..23f3667ba3823e99 +--- /dev/null ++++ b/sysdeps/s390/ifunc-wcscspn.h +@@ -0,0 +1,53 @@ ++/* wcscspn variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WCSCSPN_IFUNC 1 ++#else ++# define HAVE_WCSCSPN_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WCSCSPN_IFUNC_AND_VX_SUPPORT HAVE_WCSCSPN_IFUNC ++#else ++# define HAVE_WCSCSPN_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WCSCSPN_DEFAULT WCSCSPN_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WCSCSPN_C 1 ++# define HAVE_WCSCSPN_Z13 1 ++#else ++# define WCSCSPN_DEFAULT WCSCSPN_C ++# define HAVE_WCSCSPN_C 1 ++# define HAVE_WCSCSPN_Z13 HAVE_WCSCSPN_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WCSCSPN_C ++# define WCSCSPN_C __wcscspn_c ++#else ++# define WCSCSPN_C NULL ++#endif ++ ++#if HAVE_WCSCSPN_Z13 ++# define WCSCSPN_Z13 __wcscspn_vx ++#else ++# define WCSCSPN_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index e1e2d9dc7495ebdc..5be635542361b355 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wcscspn wcscspn-vx wcscspn-c \ +- wmemchr wmemchr-vx wmemchr-c \ ++sysdep_routines += wmemchr wmemchr-vx wmemchr-c \ + wmemset wmemset-vx wmemset-c \ + wmemcmp wmemcmp-vx wmemcmp-c + endif +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 89d6e8ad7e323fec..7d8031a069bd23ba 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -61,6 +61,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -619,6 +620,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSPBRK_IFUNC */ + ++#if HAVE_WCSCSPN_IFUNC ++ IFUNC_IMPL (i, name, wcscspn, ++# if HAVE_WCSCSPN_Z13 ++ IFUNC_IMPL_ADD (array, i, wcscspn, ++ dl_hwcap & HWCAP_S390_VX, WCSCSPN_Z13) ++# endif ++# if HAVE_WCSCSPN_C ++ IFUNC_IMPL_ADD (array, i, wcscspn, 1, WCSCSPN_C) ++# endif ++ ) ++#endif /* HAVE_WCSCSPN_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -627,8 +640,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wcscspn); +- + IFUNC_VX_IMPL (wmemchr); + + IFUNC_VX_IMPL (wmemset); +diff --git a/sysdeps/s390/multiarch/wcscspn-c.c b/sysdeps/s390/wcscspn-c.c +similarity index 86% +rename from sysdeps/s390/multiarch/wcscspn-c.c +rename to sysdeps/s390/wcscspn-c.c +index 161e52e686c73907..d47cb6b75be14e14 100644 +--- a/sysdeps/s390/multiarch/wcscspn-c.c ++++ b/sysdeps/s390/wcscspn-c.c +@@ -16,11 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WCSCSPN __wcscspn_c ++#include + +-# include +-extern __typeof (wcscspn) __wcscspn_c; ++#if HAVE_WCSCSPN_C ++# if HAVE_WCSCSPN_IFUNC || HAVE_WCSCSPN_Z13 ++# define WCSCSPN WCSCSPN_C ++# endif + + # include + #endif +diff --git a/sysdeps/s390/multiarch/wcscspn-vx.S b/sysdeps/s390/wcscspn-vx.S +similarity index 98% +rename from sysdeps/s390/multiarch/wcscspn-vx.S +rename to sysdeps/s390/wcscspn-vx.S +index 06bc4e25d0456aea..882cb93fb807caa1 100644 +--- a/sysdeps/s390/multiarch/wcscspn-vx.S ++++ b/sysdeps/s390/wcscspn-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WCSCSPN_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -57,7 +58,7 @@ + otherwise =0; + r9: loaded byte count of vlbb reject-string + */ +-ENTRY(__wcscspn_vx) ++ENTRY(WCSCSPN_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -288,6 +289,10 @@ ENTRY(__wcscspn_vx) + vlgvg %r9,%v31,1 + br %r14 + .Lfallback: +- jg __wcscspn_c +-END(__wcscspn_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WCSCSPN_C ++END(WCSCSPN_Z13) ++ ++# if ! HAVE_WCSCSPN_IFUNC ++strong_alias (WCSCSPN_Z13, wcscspn) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wcscspn.c b/sysdeps/s390/wcscspn.c +similarity index 69% +rename from sysdeps/s390/multiarch/wcscspn.c +rename to sysdeps/s390/wcscspn.c +index 707327522ad20287..0ce31b8aabf3b429 100644 +--- a/sysdeps/s390/multiarch/wcscspn.c ++++ b/sysdeps/s390/wcscspn.c +@@ -16,12 +16,23 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WCSCSPN_IFUNC + # include + # include + +-s390_vx_libc_ifunc2 (__wcscspn, wcscspn) ++# if HAVE_WCSCSPN_C ++extern __typeof (wcscspn) WCSCSPN_C attribute_hidden; ++# endif ++ ++# if HAVE_WCSCSPN_Z13 ++extern __typeof (wcscspn) WCSCSPN_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (wcscspn, wcscspn, ++ (HAVE_WCSCSPN_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WCSCSPN_Z13 ++ : WCSCSPN_DEFAULT ++ ) ++#endif diff --git a/glibc-rh1659438-52.patch b/glibc-rh1659438-52.patch new file mode 100755 index 0000000..c46c2ec --- /dev/null +++ b/glibc-rh1659438-52.patch @@ -0,0 +1,292 @@ +commit c62534ae524111eae48b2c2adf3f9a2ca90824f5 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:24 2018 +0100 + + S390: Refactor wmemchr ifunc handling. + + The ifunc handling for wmemchr is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + Glibc internal calls will use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wmemchr variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wmemchr variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wmemchr. + * sysdeps/s390/multiarch/wmemchr-c.c: Move to ... + * sysdeps/s390/wmemchr-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wmemchr-vx.S: Move to ... + * sysdeps/s390/wmemchr-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wmemchr.c: Move to ... + * sysdeps/s390/wmemchr.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wmemchr.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index da96ac3a36bd7f4e..fdfd1c605c28ddc7 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -75,5 +75,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcsrchr wcsrchr-vx wcsrchr-c \ + wcsspn wcsspn-vx wcsspn-c \ + wcspbrk wcspbrk-vx wcspbrk-c \ +- wcscspn wcscspn-vx wcscspn-c ++ wcscspn wcscspn-vx wcscspn-c \ ++ wmemchr wmemchr-vx wmemchr-c + endif +diff --git a/sysdeps/s390/ifunc-wmemchr.h b/sysdeps/s390/ifunc-wmemchr.h +new file mode 100644 +index 0000000000000000..0610cfb5d4a7fb18 +--- /dev/null ++++ b/sysdeps/s390/ifunc-wmemchr.h +@@ -0,0 +1,53 @@ ++/* wmemchr variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WMEMCHR_IFUNC 1 ++#else ++# define HAVE_WMEMCHR_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WMEMCHR_IFUNC_AND_VX_SUPPORT HAVE_WMEMCHR_IFUNC ++#else ++# define HAVE_WMEMCHR_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WMEMCHR_DEFAULT WMEMCHR_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WMEMCHR_C 1 ++# define HAVE_WMEMCHR_Z13 1 ++#else ++# define WMEMCHR_DEFAULT WMEMCHR_C ++# define HAVE_WMEMCHR_C 1 ++# define HAVE_WMEMCHR_Z13 HAVE_WMEMCHR_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WMEMCHR_C ++# define WMEMCHR_C __wmemchr_c ++#else ++# define WMEMCHR_C NULL ++#endif ++ ++#if HAVE_WMEMCHR_Z13 ++# define WMEMCHR_Z13 __wmemchr_vx ++#else ++# define WMEMCHR_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 5be635542361b355..92e28dc45ddbae37 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wmemchr wmemchr-vx wmemchr-c \ +- wmemset wmemset-vx wmemset-c \ ++sysdep_routines += wmemset wmemset-vx wmemset-c \ + wmemcmp wmemcmp-vx wmemcmp-c + endif + +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 7d8031a069bd23ba..b5f55deb7faae9c4 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -62,6 +62,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -632,6 +633,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WCSCSPN_IFUNC */ + ++#if HAVE_WMEMCHR_IFUNC ++ IFUNC_IMPL (i, name, wmemchr, ++# if HAVE_WMEMCHR_Z13 ++ IFUNC_IMPL_ADD (array, i, wmemchr, ++ dl_hwcap & HWCAP_S390_VX, WMEMCHR_Z13) ++# endif ++# if HAVE_WMEMCHR_C ++ IFUNC_IMPL_ADD (array, i, wmemchr, 1, WMEMCHR_C) ++# endif ++ ) ++#endif /* HAVE_WMEMCHR_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -640,8 +653,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wmemchr); +- + IFUNC_VX_IMPL (wmemset); + + IFUNC_VX_IMPL (wmemcmp); +diff --git a/sysdeps/s390/multiarch/wmemchr-c.c b/sysdeps/s390/wmemchr-c.c +similarity index 59% +rename from sysdeps/s390/multiarch/wmemchr-c.c +rename to sysdeps/s390/wmemchr-c.c +index 089392b512d29187..bb2526e76c41d0c7 100644 +--- a/sysdeps/s390/multiarch/wmemchr-c.c ++++ b/sysdeps/s390/wmemchr-c.c +@@ -16,22 +16,29 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WMEMCHR __wmemchr_c +- +-# include +-extern __typeof (wmemchr) __wmemchr_c; +-# undef weak_alias +-# define weak_alias(name, alias) +-# ifdef SHARED +-# undef libc_hidden_def +-# define libc_hidden_def(name) \ +- __hidden_ver1 (__wmemchr_c, __GI___wmemchr, __wmemchr_c); +-# undef libc_hidden_weak +-# define libc_hidden_weak(name) \ ++#include ++ ++#if HAVE_WMEMCHR_C ++# if HAVE_WMEMCHR_IFUNC || HAVE_WMEMCHR_Z13 ++# define WMEMCHR WMEMCHR_C ++ ++# undef weak_alias ++# define weak_alias(name, alias) ++ ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_weak ++# define libc_hidden_weak(name) ++# undef libc_hidden_def ++# if ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define libc_hidden_def(name) \ ++ __hidden_ver1 (__wmemchr_c, __GI_wmemchr, __wmemchr_c) __attribute__((weak)); \ + strong_alias (__wmemchr_c, __wmemchr_c_1); \ +- __hidden_ver1 (__wmemchr_c_1, __GI_wmemchr, __wmemchr_c_1); +-# endif /* SHARED */ ++ __hidden_ver1 (__wmemchr_c_1, __GI___wmemchr, __wmemchr_c_1); ++# else ++# define libc_hidden_def(name) ++# endif ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/wmemchr-vx.S b/sysdeps/s390/wmemchr-vx.S +similarity index 92% +rename from sysdeps/s390/multiarch/wmemchr-vx.S +rename to sysdeps/s390/wmemchr-vx.S +index db057b579a7230f0..72e9ef59af77b8f7 100644 +--- a/sysdeps/s390/multiarch/wmemchr-vx.S ++++ b/sysdeps/s390/wmemchr-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WMEMCHR_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -38,7 +39,7 @@ + -v17=index of found c + -v18=c replicated + */ +-ENTRY(__wmemchr_vx) ++ENTRY(WMEMCHR_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -161,6 +162,17 @@ ENTRY(__wmemchr_vx) + + j .Llt64 + .Lfallback: +- jg __wmemchr_c +-END(__wmemchr_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WMEMCHR_C ++END(WMEMCHR_Z13) ++ ++# if ! HAVE_WMEMCHR_IFUNC ++strong_alias (WMEMCHR_Z13, __wmemchr) ++weak_alias (__wmemchr, wmemchr) ++# endif ++ ++# if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT \ ++ && defined SHARED && IS_IN (libc) ++strong_alias (WMEMCHR_Z13, __GI___wmemchr) ++weak_alias (WMEMCHR_Z13, __GI_wmemchr) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wmemchr.c b/sysdeps/s390/wmemchr.c +similarity index 70% +rename from sysdeps/s390/multiarch/wmemchr.c +rename to sysdeps/s390/wmemchr.c +index 6b55c1d7fa10afb9..0d2fbb22c6d65a97 100644 +--- a/sysdeps/s390/multiarch/wmemchr.c ++++ b/sysdeps/s390/wmemchr.c +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WMEMCHR_IFUNC + # define wmemchr __redirect_wmemchr + # define __wmemchr __redirect___wmemchr + # include +@@ -24,9 +26,18 @@ + # undef __wmemchr + # include + +-s390_vx_libc_ifunc_redirected (__redirect___wmemchr, __wmemchr) +-weak_alias (__wmemchr, wmemchr) ++# if HAVE_WMEMCHR_C ++extern __typeof (__redirect___wmemchr) WMEMCHR_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_WMEMCHR_Z13 ++extern __typeof (__redirect___wmemchr) WMEMCHR_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect___wmemchr, __wmemchr, ++ (HAVE_WMEMCHR_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WMEMCHR_Z13 ++ : WMEMCHR_DEFAULT ++ ) ++weak_alias (__wmemchr, wmemchr) ++#endif diff --git a/glibc-rh1659438-53.patch b/glibc-rh1659438-53.patch new file mode 100755 index 0000000..7d8150d --- /dev/null +++ b/glibc-rh1659438-53.patch @@ -0,0 +1,292 @@ +commit d2a7436c1c6144bbba2eb2a7b25db9b90515f0e6 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:24 2018 +0100 + + S390: Refactor wmemset ifunc handling. + + The ifunc handling for wmemset is adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Unfortunately the c ifunc variant can't be omitted at all as it is used + by the z13 ifunc variant as fallback if the pointers are not 4-byte aligned. + Glibc internal calls will use the "newer" ifunc variant. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wmemset variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wmemset variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wmemset. + * sysdeps/s390/multiarch/wmemset-c.c: Move to ... + * sysdeps/s390/wmemset-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wmemset-vx.S: Move to ... + * sysdeps/s390/wmemset-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wmemset.c: Move to ... + * sysdeps/s390/wmemset.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wmemset.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index fdfd1c605c28ddc7..f9a71276331b396a 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -76,5 +76,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcsspn wcsspn-vx wcsspn-c \ + wcspbrk wcspbrk-vx wcspbrk-c \ + wcscspn wcscspn-vx wcscspn-c \ +- wmemchr wmemchr-vx wmemchr-c ++ wmemchr wmemchr-vx wmemchr-c \ ++ wmemset wmemset-vx wmemset-c + endif +diff --git a/sysdeps/s390/ifunc-wmemset.h b/sysdeps/s390/ifunc-wmemset.h +new file mode 100644 +index 0000000000000000..c9d1d17c3bfc7e9e +--- /dev/null ++++ b/sysdeps/s390/ifunc-wmemset.h +@@ -0,0 +1,53 @@ ++/* wmemset variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WMEMSET_IFUNC 1 ++#else ++# define HAVE_WMEMSET_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WMEMSET_IFUNC_AND_VX_SUPPORT HAVE_WMEMSET_IFUNC ++#else ++# define HAVE_WMEMSET_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WMEMSET_DEFAULT WMEMSET_Z13 ++/* The z13 ifunc variant is using the common code variant as fallback! */ ++# define HAVE_WMEMSET_C 1 ++# define HAVE_WMEMSET_Z13 1 ++#else ++# define WMEMSET_DEFAULT WMEMSET_C ++# define HAVE_WMEMSET_C 1 ++# define HAVE_WMEMSET_Z13 HAVE_WMEMSET_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WMEMSET_C ++# define WMEMSET_C __wmemset_c ++#else ++# define WMEMSET_C NULL ++#endif ++ ++#if HAVE_WMEMSET_Z13 ++# define WMEMSET_Z13 __wmemset_vx ++#else ++# define WMEMSET_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 92e28dc45ddbae37..cc6dd7adb10ee8ad 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,6 +1,5 @@ + ifeq ($(subdir),wcsmbs) +-sysdep_routines += wmemset wmemset-vx wmemset-c \ +- wmemcmp wmemcmp-vx wmemcmp-c ++sysdep_routines += wmemcmp wmemcmp-vx wmemcmp-c + endif + + ifeq ($(subdir),iconvdata) +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index b5f55deb7faae9c4..7040959269c1612b 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -63,6 +63,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -645,6 +646,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WMEMCHR_IFUNC */ + ++#if HAVE_WMEMSET_IFUNC ++ IFUNC_IMPL (i, name, wmemset, ++# if HAVE_WMEMSET_Z13 ++ IFUNC_IMPL_ADD (array, i, wmemset, ++ dl_hwcap & HWCAP_S390_VX, WMEMSET_Z13) ++# endif ++# if HAVE_WMEMSET_C ++ IFUNC_IMPL_ADD (array, i, wmemset, 1, WMEMSET_C) ++# endif ++ ) ++#endif /* HAVE_WMEMSET_IFUNC */ ++ + #ifdef HAVE_S390_VX_ASM_SUPPORT + + # define IFUNC_VX_IMPL(FUNC) \ +@@ -653,8 +666,6 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __##FUNC##_vx) \ + IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) + +- IFUNC_VX_IMPL (wmemset); +- + IFUNC_VX_IMPL (wmemcmp); + + #endif /* HAVE_S390_VX_ASM_SUPPORT */ +diff --git a/sysdeps/s390/multiarch/wmemset-c.c b/sysdeps/s390/wmemset-c.c +similarity index 59% +rename from sysdeps/s390/multiarch/wmemset-c.c +rename to sysdeps/s390/wmemset-c.c +index 1969cf93dcf08892..01e625496d8c2e4e 100644 +--- a/sysdeps/s390/multiarch/wmemset-c.c ++++ b/sysdeps/s390/wmemset-c.c +@@ -16,22 +16,29 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WMEMSET __wmemset_c +- +-# include +-extern __typeof (__wmemset) __wmemset_c; +-# undef weak_alias +-# define weak_alias(name, alias) +-# ifdef SHARED +-# undef libc_hidden_def +-# define libc_hidden_def(name) \ +- __hidden_ver1 (__wmemset_c, __GI___wmemset, __wmemset_c); +-# undef libc_hidden_weak +-# define libc_hidden_weak(name) \ ++#include ++ ++#if HAVE_WMEMSET_C ++# if HAVE_WMEMSET_IFUNC || HAVE_WMEMSET_Z13 ++# define WMEMSET WMEMSET_C ++ ++# undef weak_alias ++# define weak_alias(name, alias) ++ ++# if defined SHARED && IS_IN (libc) ++# undef libc_hidden_weak ++# define libc_hidden_weak(name) ++# undef libc_hidden_def ++# if ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define libc_hidden_def(name) \ ++ __hidden_ver1 (__wmemset_c, __GI_wmemset, __wmemset_c) __attribute__((weak)); \ + strong_alias (__wmemset_c, __wmemset_c_1); \ +- __hidden_ver1 (__wmemset_c_1, __GI_wmemset, __wmemset_c_1); +-# endif /* SHARED */ ++ __hidden_ver1 (__wmemset_c_1, __GI___wmemset, __wmemset_c_1); ++# else ++# define libc_hidden_def(name) ++# endif ++# endif ++# endif + + # include +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++#endif +diff --git a/sysdeps/s390/multiarch/wmemset-vx.S b/sysdeps/s390/wmemset-vx.S +similarity index 91% +rename from sysdeps/s390/multiarch/wmemset-vx.S +rename to sysdeps/s390/wmemset-vx.S +index 0c2f6337b0e554ec..4b6050b5accd732b 100644 +--- a/sysdeps/s390/multiarch/wmemset-vx.S ++++ b/sysdeps/s390/wmemset-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WMEMSET_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -38,7 +39,7 @@ + -v17,v18,v19=copy of v16 for vstm + -v31=saved dest for return + */ +-ENTRY(__wmemset_vx) ++ENTRY(WMEMSET_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -137,6 +138,17 @@ ENTRY(__wmemset_vx) + br %r14 + .Lfallback: + srlg %r4,%r4,2 /* Convert byte-count to character-count. */ +- jg __wmemset_c +-END(__wmemset_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++ jg WMEMSET_C ++END(WMEMSET_Z13) ++ ++# if ! HAVE_WMEMSET_IFUNC ++strong_alias (WMEMSET_Z13, __wmemset) ++weak_alias (__wmemset, wmemset) ++# endif ++ ++# if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT \ ++ && defined SHARED && IS_IN (libc) ++strong_alias (WMEMSET_Z13, __GI___wmemset) ++weak_alias (WMEMSET_Z13, __GI_wmemset) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wmemset.c b/sysdeps/s390/wmemset.c +similarity index 70% +rename from sysdeps/s390/multiarch/wmemset.c +rename to sysdeps/s390/wmemset.c +index 149b4814708d820a..6118754d1df71948 100644 +--- a/sysdeps/s390/multiarch/wmemset.c ++++ b/sysdeps/s390/wmemset.c +@@ -16,7 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WMEMSET_IFUNC + # define wmemset __redirect_wmemset + # define __wmemset __redirect___wmemset + # include +@@ -24,9 +26,18 @@ + # undef __wmemset + # include + +-s390_vx_libc_ifunc_redirected (__redirect___wmemset, __wmemset) +-weak_alias (__wmemset, wmemset) ++# if HAVE_WMEMSET_C ++extern __typeof (__redirect___wmemset) WMEMSET_C attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++# if HAVE_WMEMSET_Z13 ++extern __typeof (__redirect___wmemset) WMEMSET_Z13 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect___wmemset, __wmemset, ++ (HAVE_WMEMSET_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WMEMSET_Z13 ++ : WMEMSET_DEFAULT ++ ) ++weak_alias (__wmemset, wmemset) ++#endif diff --git a/glibc-rh1659438-54.patch b/glibc-rh1659438-54.patch new file mode 100755 index 0000000..2bd37c0 --- /dev/null +++ b/glibc-rh1659438-54.patch @@ -0,0 +1,246 @@ +commit 25654a8c74dce51e162c29749c6bd6d2a67490e6 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:25 2018 +0100 + + S390: Refactor wmemcmp ifunc handling. + + The ifunc handling for wmemcmp is adjusted in order to omit ifunc + variants if those will never be used as the minimum architecture level + already supports newer CPUs by default. + + ChangeLog: + + * sysdeps/s390/multiarch/Makefile + (sysdep_routines): Remove wmemcmp variants. + * sysdeps/s390/Makefile (sysdep_routines): Add wmemcmp variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Refactor ifunc handling for wmemcmp. + * sysdeps/s390/multiarch/wmemcmp-c.c: Move to ... + * sysdeps/s390/wmemcmp-c.c: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wmemcmp-vx.S: Move to ... + * sysdeps/s390/wmemcmp-vx.S: ... here and adjust ifunc handling. + * sysdeps/s390/multiarch/wmemcmp.c: Move to ... + * sysdeps/s390/wmemcmp.c: ... here and adjust ifunc handling. + * sysdeps/s390/ifunc-wmemcmp.h: New file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index f9a71276331b396a..3f7de6613c343819 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -77,5 +77,6 @@ sysdep_routines += wcslen wcslen-vx wcslen-c \ + wcspbrk wcspbrk-vx wcspbrk-c \ + wcscspn wcscspn-vx wcscspn-c \ + wmemchr wmemchr-vx wmemchr-c \ +- wmemset wmemset-vx wmemset-c ++ wmemset wmemset-vx wmemset-c \ ++ wmemcmp wmemcmp-vx wmemcmp-c + endif +diff --git a/sysdeps/s390/ifunc-wmemcmp.h b/sysdeps/s390/ifunc-wmemcmp.h +new file mode 100644 +index 0000000000000000..1b38a014590ec060 +--- /dev/null ++++ b/sysdeps/s390/ifunc-wmemcmp.h +@@ -0,0 +1,52 @@ ++/* wmemcmp variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define HAVE_WMEMCMP_IFUNC 1 ++#else ++# define HAVE_WMEMCMP_IFUNC 0 ++#endif ++ ++#ifdef HAVE_S390_VX_ASM_SUPPORT ++# define HAVE_WMEMCMP_IFUNC_AND_VX_SUPPORT HAVE_WMEMCMP_IFUNC ++#else ++# define HAVE_WMEMCMP_IFUNC_AND_VX_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++# define WMEMCMP_DEFAULT WMEMCMP_Z13 ++# define HAVE_WMEMCMP_C 0 ++# define HAVE_WMEMCMP_Z13 1 ++#else ++# define WMEMCMP_DEFAULT WMEMCMP_C ++# define HAVE_WMEMCMP_C 1 ++# define HAVE_WMEMCMP_Z13 HAVE_WMEMCMP_IFUNC_AND_VX_SUPPORT ++#endif ++ ++#if HAVE_WMEMCMP_C ++# define WMEMCMP_C __wmemcmp_c ++#else ++# define WMEMCMP_C NULL ++#endif ++ ++#if HAVE_WMEMCMP_Z13 ++# define WMEMCMP_Z13 __wmemcmp_vx ++#else ++# define WMEMCMP_Z13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index cc6dd7adb10ee8ad..fec36153047e4585 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -1,7 +1,3 @@ +-ifeq ($(subdir),wcsmbs) +-sysdep_routines += wmemcmp wmemcmp-vx wmemcmp-c +-endif +- + ifeq ($(subdir),iconvdata) + override define generate-8bit-table + $(make-target-directory) +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 7040959269c1612b..177c5fd6fe269d9b 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -64,6 +64,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -658,17 +659,17 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_WMEMSET_IFUNC */ + +-#ifdef HAVE_S390_VX_ASM_SUPPORT +- +-# define IFUNC_VX_IMPL(FUNC) \ +- IFUNC_IMPL (i, name, FUNC, \ +- IFUNC_IMPL_ADD (array, i, FUNC, dl_hwcap & HWCAP_S390_VX, \ +- __##FUNC##_vx) \ +- IFUNC_IMPL_ADD (array, i, FUNC, 1, __##FUNC##_c)) +- +- IFUNC_VX_IMPL (wmemcmp); +- +-#endif /* HAVE_S390_VX_ASM_SUPPORT */ ++#if HAVE_WMEMCMP_IFUNC ++ IFUNC_IMPL (i, name, wmemcmp, ++# if HAVE_WMEMCMP_Z13 ++ IFUNC_IMPL_ADD (array, i, wmemcmp, ++ dl_hwcap & HWCAP_S390_VX, WMEMCMP_Z13) ++# endif ++# if HAVE_WMEMCMP_C ++ IFUNC_IMPL_ADD (array, i, wmemcmp, 1, WMEMCMP_C) ++# endif ++ ) ++#endif /* HAVE_WMEMCMP_IFUNC */ + + return i; + } +diff --git a/sysdeps/s390/multiarch/wmemcmp-c.c b/sysdeps/s390/wmemcmp-c.c +similarity index 85% +rename from sysdeps/s390/multiarch/wmemcmp-c.c +rename to sysdeps/s390/wmemcmp-c.c +index 2fd39d501360e6f8..0c73636adda82f8b 100644 +--- a/sysdeps/s390/multiarch/wmemcmp-c.c ++++ b/sysdeps/s390/wmemcmp-c.c +@@ -16,11 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) +-# define WMEMCMP __wmemcmp_c ++#include + +-# include +-extern __typeof (wmemcmp) __wmemcmp_c; ++#if HAVE_WMEMCMP_C ++# if HAVE_WMEMCMP_IFUNC ++# define WMEMCMP WMEMCMP_C ++# endif + + # include + #endif +diff --git a/sysdeps/s390/multiarch/wmemcmp-vx.S b/sysdeps/s390/wmemcmp-vx.S +similarity index 95% +rename from sysdeps/s390/multiarch/wmemcmp-vx.S +rename to sysdeps/s390/wmemcmp-vx.S +index e2fc21e4192b0dd8..87ae21b4f13c5d69 100644 +--- a/sysdeps/s390/multiarch/wmemcmp-vx.S ++++ b/sysdeps/s390/wmemcmp-vx.S +@@ -16,7 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++#if HAVE_WMEMCMP_Z13 + + # include "sysdep.h" + # include "asm-syntax.h" +@@ -37,7 +38,7 @@ + -v17=part of s2 + -v18=index of unequal + */ +-ENTRY(__wmemcmp_vx) ++ENTRY(WMEMCMP_Z13) + .machine "z13" + .machinemode "zarch_nohighgprs" + +@@ -145,5 +146,9 @@ ENTRY(__wmemcmp_vx) + la %r2,0(%r5,%r2) + la %r3,0(%r5,%r3) + j .Lremaining +-END(__wmemcmp_vx) +-#endif /* HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) */ ++END(WMEMCMP_Z13) ++ ++# if ! HAVE_WMEMCMP_IFUNC ++strong_alias (WMEMCMP_Z13, wmemcmp) ++# endif ++#endif +diff --git a/sysdeps/s390/multiarch/wmemcmp.c b/sysdeps/s390/wmemcmp.c +similarity index 69% +rename from sysdeps/s390/multiarch/wmemcmp.c +rename to sysdeps/s390/wmemcmp.c +index a4cb440c452fd6a9..6c8ca5f0e8ffdb50 100644 +--- a/sysdeps/s390/multiarch/wmemcmp.c ++++ b/sysdeps/s390/wmemcmp.c +@@ -16,12 +16,23 @@ + License along with the GNU C Library; if not, see + . */ + +-#if defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc) ++#include ++ ++#if HAVE_WMEMCMP_IFUNC + # include + # include + +-s390_vx_libc_ifunc2 (__wmemcmp, wmemcmp) ++# if HAVE_WMEMCMP_C ++extern __typeof (wmemcmp) WMEMCMP_C attribute_hidden; ++# endif ++ ++# if HAVE_WMEMCMP_Z13 ++extern __typeof (wmemcmp) WMEMCMP_Z13 attribute_hidden; ++# endif + +-#else +-# include +-#endif /* !(defined HAVE_S390_VX_ASM_SUPPORT && IS_IN (libc)) */ ++s390_libc_ifunc_expr (wmemcmp, wmemcmp, ++ (HAVE_WMEMCMP_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? WMEMCMP_Z13 ++ : WMEMCMP_DEFAULT ++ ) ++#endif diff --git a/glibc-rh1659438-55.patch b/glibc-rh1659438-55.patch new file mode 100755 index 0000000..e4be220 --- /dev/null +++ b/glibc-rh1659438-55.patch @@ -0,0 +1,53 @@ +commit 12f0dcb8da2c7c74d673583ec3286c0354273f52 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:25 2018 +0100 + + S390: Refactor gconv_simple ifunc handling. + + The ifunc handling for various __gconv_transform_* functions + which are using IFUNC on s390x are adjusted in order to omit ifunc + if the minimum architecture level already supports newer CPUs by default. + Instead those functions are just an alias to the vector variants. + + Furthermore the ifunc-macro s390_libc_ifunc_expr is now used instead of + s390_vx_libc_ifunc. + + ChangeLog: + + * sysdeps/s390/multiarch/gconv_simple.c (ICONV_VX_IFUNC): + Define macro dependent on HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT. + +diff --git a/sysdeps/s390/multiarch/gconv_simple.c b/sysdeps/s390/multiarch/gconv_simple.c +index aaa1ebf74acf4dde..078d992c13eb548c 100644 +--- a/sysdeps/s390/multiarch/gconv_simple.c ++++ b/sysdeps/s390/multiarch/gconv_simple.c +@@ -27,17 +27,18 @@ + + # define ICONV_C_NAME(NAME) __##NAME##_c + # define ICONV_VX_NAME(NAME) __##NAME##_vx +-# define ICONV_VX_IFUNC(FUNC) \ +- extern __typeof (ICONV_C_NAME (FUNC)) __##FUNC; \ +- s390_vx_libc_ifunc (__##FUNC) \ +- int FUNC (struct __gconv_step *step, struct __gconv_step_data *data, \ +- const unsigned char **inptrp, const unsigned char *inend, \ +- unsigned char **outbufstart, size_t *irreversible, \ +- int do_flush, int consume_incomplete) \ +- { \ +- return __##FUNC (step, data, inptrp, inend,outbufstart, \ +- irreversible, do_flush, consume_incomplete); \ +- } ++# ifdef HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++/* We support z13 instructions by default -> Just use the vector variant. */ ++# define ICONV_VX_IFUNC(FUNC) strong_alias (ICONV_VX_NAME (FUNC), FUNC) ++# else ++/* We have to use ifunc to determine if z13 instructions are supported. */ ++# define ICONV_VX_IFUNC(FUNC) \ ++ s390_libc_ifunc_expr (ICONV_C_NAME (FUNC), FUNC, \ ++ (hwcap & HWCAP_S390_VX) \ ++ ? ICONV_VX_NAME (FUNC) \ ++ : ICONV_C_NAME (FUNC) \ ++ ) ++# endif + # define ICONV_VX_SINGLE(NAME) \ + static __typeof (NAME##_single) __##NAME##_vx_single __attribute__((alias(#NAME "_single"))); + diff --git a/glibc-rh1659438-56.patch b/glibc-rh1659438-56.patch new file mode 100755 index 0000000..934b8da --- /dev/null +++ b/glibc-rh1659438-56.patch @@ -0,0 +1,152 @@ +commit 80190d2b0e3f48d973724218f37d2da5bf1a20ab +Author: Stefan Liebler +Date: Tue Dec 18 13:57:25 2018 +0100 + + S390: Cleanup ifunc-resolve.h. + + The ifunc macros s390_vx_libc* are no longer used and + can be removed as all users are now relying on + s390_libc_ifunc_expr. + + The same applies to s390_libc_ifunc. The macro + s390_libc_ifunc_init is now renamed to + s390_libc_ifunc_expr_stfle_init and the users are + adjusted accordingly. + + ChangeLog: + + * sysdeps/s390/multiarch/ifunc-resolve.h + (s390_vx_libc_ifunc, s390_vx_libc_ifunc_redirected, + s390_vx_libc_ifunc2, s390_vx_libc_ifunc_init, + s390_vx_libc_ifunc2_redirected, s390_libc_ifunc): + Delete macro definition. + (s390_libc_ifunc_init): Rename to + s390_libc_ifunc_expr_stfle_init. + * sysdeps/s390/bzero: Use + s390_libc_ifunc_expr_stfle_init instead of + s390_libc_ifunc_init. + * sysdeps/s390/memcmp.c: Likewise. + * sysdeps/s390/memcpy.c: Likewise. + * sysdeps/s390/mempcpy.c: Likewise. + * sysdeps/s390/memset.c: Likewise. + +diff --git a/sysdeps/s390/bzero.c b/sysdeps/s390/bzero.c +index 9f8d95781bf2fb68..6b5d471c40250543 100644 +--- a/sysdeps/s390/bzero.c ++++ b/sysdeps/s390/bzero.c +@@ -35,7 +35,7 @@ extern __typeof (__bzero) BZERO_Z196 attribute_hidden; + + s390_libc_ifunc_expr (__bzero, __bzero, + ({ +- s390_libc_ifunc_init (); ++ s390_libc_ifunc_expr_stfle_init (); + (HAVE_MEMSET_Z196 && S390_IS_Z196 (stfle_bits)) + ? BZERO_Z196 + : (HAVE_MEMSET_Z10 && S390_IS_Z10 (stfle_bits)) +diff --git a/sysdeps/s390/memcmp.c b/sysdeps/s390/memcmp.c +index 952ff6af7364fd92..6d9276320abbe332 100644 +--- a/sysdeps/s390/memcmp.c ++++ b/sysdeps/s390/memcmp.c +@@ -37,7 +37,7 @@ extern __typeof (__redirect_memcmp) MEMCMP_Z196 attribute_hidden; + + s390_libc_ifunc_expr (__redirect_memcmp, memcmp, + ({ +- s390_libc_ifunc_init (); ++ s390_libc_ifunc_expr_stfle_init (); + (HAVE_MEMCMP_Z196 && S390_IS_Z196 (stfle_bits)) + ? MEMCMP_Z196 + : (HAVE_MEMCMP_Z10 && S390_IS_Z10 (stfle_bits)) +diff --git a/sysdeps/s390/memcpy.c b/sysdeps/s390/memcpy.c +index 90a53ac27d4be755..0ff24f18cf3600da 100644 +--- a/sysdeps/s390/memcpy.c ++++ b/sysdeps/s390/memcpy.c +@@ -38,7 +38,7 @@ extern __typeof (__redirect_memcpy) MEMCPY_Z196 attribute_hidden; + + s390_libc_ifunc_expr (__redirect_memcpy, memcpy, + ({ +- s390_libc_ifunc_init (); ++ s390_libc_ifunc_expr_stfle_init (); + (HAVE_MEMCPY_Z196 && S390_IS_Z196 (stfle_bits)) + ? MEMCPY_Z196 + : (HAVE_MEMCPY_Z10 && S390_IS_Z10 (stfle_bits)) +diff --git a/sysdeps/s390/mempcpy.c b/sysdeps/s390/mempcpy.c +index a6a237312659c2c1..b687b3362034bfb0 100644 +--- a/sysdeps/s390/mempcpy.c ++++ b/sysdeps/s390/mempcpy.c +@@ -42,7 +42,7 @@ extern __typeof (__redirect___mempcpy) MEMPCPY_Z196 attribute_hidden; + + s390_libc_ifunc_expr (__redirect___mempcpy, __mempcpy, + ({ +- s390_libc_ifunc_init (); ++ s390_libc_ifunc_expr_stfle_init (); + (HAVE_MEMCPY_Z196 && S390_IS_Z196 (stfle_bits)) + ? MEMPCPY_Z196 + : (HAVE_MEMCPY_Z10 && S390_IS_Z10 (stfle_bits)) +diff --git a/sysdeps/s390/memset.c b/sysdeps/s390/memset.c +index 57a35aebc7d3c794..75b011f1a24f39bc 100644 +--- a/sysdeps/s390/memset.c ++++ b/sysdeps/s390/memset.c +@@ -37,7 +37,7 @@ extern __typeof (__redirect_memset) MEMSET_Z196 attribute_hidden; + + s390_libc_ifunc_expr (__redirect_memset, memset, + ({ +- s390_libc_ifunc_init (); ++ s390_libc_ifunc_expr_stfle_init (); + (HAVE_MEMSET_Z196 && S390_IS_Z196 (stfle_bits)) + ? MEMSET_Z196 + : (HAVE_MEMSET_Z10 && S390_IS_Z10 (stfle_bits)) +diff --git a/sysdeps/s390/multiarch/ifunc-resolve.h b/sysdeps/s390/multiarch/ifunc-resolve.h +index b7e20abc59638251..b2be015401313d4b 100644 +--- a/sysdeps/s390/multiarch/ifunc-resolve.h ++++ b/sysdeps/s390/multiarch/ifunc-resolve.h +@@ -40,7 +40,7 @@ + ".machine pop" "\n" \ + : "=QS" (STFLE_BITS), "+d" (reg0) \ + : : "cc"); +-#define s390_libc_ifunc_init() \ ++#define s390_libc_ifunc_expr_stfle_init() \ + unsigned long long stfle_bits = 0ULL; \ + if (__glibc_likely ((hwcap & HWCAP_S390_STFLE) \ + && (hwcap & HWCAP_S390_ZARCH) \ +@@ -49,41 +49,6 @@ + S390_STORE_STFLE (stfle_bits); \ + } + +-#define s390_libc_ifunc(TYPE_FUNC, RESOLVERFUNC, FUNC) \ +- /* Make the declarations of the optimized functions hidden in order +- to prevent GOT slots being generated for them. */ \ +- extern __typeof (TYPE_FUNC) RESOLVERFUNC##_z196 attribute_hidden; \ +- extern __typeof (TYPE_FUNC) RESOLVERFUNC##_z10 attribute_hidden; \ +- extern __typeof (TYPE_FUNC) RESOLVERFUNC##_default attribute_hidden; \ +- __ifunc (TYPE_FUNC, FUNC, \ +- __glibc_likely (S390_IS_Z196 (stfle_bits)) \ +- ? RESOLVERFUNC##_z196 \ +- : __glibc_likely (S390_IS_Z10 (stfle_bits)) \ +- ? RESOLVERFUNC##_z10 \ +- : RESOLVERFUNC##_default, \ +- unsigned long int hwcap, s390_libc_ifunc_init); +- +-#define s390_vx_libc_ifunc(FUNC) \ +- s390_vx_libc_ifunc2_redirected(FUNC, FUNC, FUNC) +- +-#define s390_vx_libc_ifunc_redirected(TYPE_FUNC, FUNC) \ +- s390_vx_libc_ifunc2_redirected(TYPE_FUNC, FUNC, FUNC) +- +-#define s390_vx_libc_ifunc2(RESOLVERFUNC, FUNC) \ +- s390_vx_libc_ifunc2_redirected(FUNC, RESOLVERFUNC, FUNC) +- +-#define s390_vx_libc_ifunc_init() +-#define s390_vx_libc_ifunc2_redirected(TYPE_FUNC, RESOLVERFUNC, FUNC) \ +- /* Make the declarations of the optimized functions hidden in order +- to prevent GOT slots being generated for them. */ \ +- extern __typeof (TYPE_FUNC) RESOLVERFUNC##_vx attribute_hidden; \ +- extern __typeof (TYPE_FUNC) RESOLVERFUNC##_c attribute_hidden; \ +- __ifunc (TYPE_FUNC, FUNC, \ +- (hwcap & HWCAP_S390_VX) \ +- ? RESOLVERFUNC##_vx \ +- : RESOLVERFUNC##_c, \ +- unsigned long int hwcap, s390_vx_libc_ifunc_init); +- + #define s390_libc_ifunc_expr_init() + #define s390_libc_ifunc_expr(TYPE_FUNC, FUNC, EXPR) \ + __ifunc (TYPE_FUNC, FUNC, EXPR, unsigned long int hwcap, \ diff --git a/glibc-rh1659438-57.patch b/glibc-rh1659438-57.patch new file mode 100755 index 0000000..50b5945 --- /dev/null +++ b/glibc-rh1659438-57.patch @@ -0,0 +1,29 @@ +commit 61f5e9470fb397a4c334938ac5a667427d9047df +Author: Stefan Liebler +Date: Thu Mar 21 09:14:26 2019 +0100 + + S390: Mark vx and vxe as important hwcap. + + This patch adds vx and vxe as important hwcaps + which allows one to provide shared libraries + tuned for platforms with non-vx/-vxe, vx or vxe. + + ChangeLog: + + * sysdeps/s390/dl-procinfo.h (HWCAP_IMPORTANT): + Add HWCAP_S390_VX and HWCAP_S390_VXE. + +diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h +index b0383bfb4cef7972..f71d64c3ab24e715 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/glibc-rh1659438-58.patch b/glibc-rh1659438-58.patch new file mode 100755 index 0000000..3f16140 --- /dev/null +++ b/glibc-rh1659438-58.patch @@ -0,0 +1,88 @@ +commit 1a7df49c92f62e14d8727f083fd055eba7c91ad9 +Author: Stefan Liebler +Date: Fri Mar 22 11:14:07 2019 +0100 + + S390: Add new hwcap values for new cpu architecture arch13. + + The new hwcap values indicate support for: + -"Vector-Enhancements Facility 2" (tag "vxe2", hwcap 2^15) + -"Vector-Packed-Decimal-Enhancement Facility" (tag "vxp", hwcap 2^16) + -"Enhanced-Sort Facility" (tag "sort", hwcap 2^17) + -"Deflate-Conversion Facility" (tag "dflt", hwcap 2^18) + + The vxe2 hwcap is also marked as important hwcap. + + ChangeLog: + + * sysdeps/s390/dl-procinfo.c (_dl_s390_cap_flags): + Add vxe2, vxp, dflt, sort flags. + * sysdeps/s390/dl-procinfo.h: Add HWCAP_S390_VXRS_EXT2, + HWCAP_S390_VXRS_PDE, HWCAP_S390_SORT, HWCAP_S390_DFLT + capabilities. + (HWCAP_IMPORTANT): Add HWCAP_S390_VXRS_EXT2. + * sysdeps/unix/sysv/linux/s390/bits/hwcap.h + (HWCAP_S390_VXRS_EXT2, HWCAP_S390_VXRS_PDE, HWCAP_S390_SORT, + HWCAP_S390_DFLT): Define. + +diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c +index 86c964caff6a1bc4..6ea220a171d8fab7 100644 +--- a/sysdeps/s390/dl-procinfo.c ++++ b/sysdeps/s390/dl-procinfo.c +@@ -46,12 +46,12 @@ + #if !defined PROCINFO_DECL && defined SHARED + ._dl_s390_cap_flags + #else +-PROCINFO_CLASS const char _dl_s390_cap_flags[15][9] ++PROCINFO_CLASS const char _dl_s390_cap_flags[19][9] + #endif + #ifndef PROCINFO_DECL + = { + "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh", +- "highgprs", "te", "vx", "vxd", "vxe", "gs" ++ "highgprs", "te", "vx", "vxd", "vxe", "gs", "vxe2", "vxp", "sort", "dflt" + } + #endif + #if !defined SHARED || defined PROCINFO_DECL +diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h +index f71d64c3ab24e715..d03c69fffdbd06de 100644 +--- a/sysdeps/s390/dl-procinfo.h ++++ b/sysdeps/s390/dl-procinfo.h +@@ -21,7 +21,7 @@ + #define _DL_PROCINFO_H 1 + #include + +-#define _DL_HWCAP_COUNT 15 ++#define _DL_HWCAP_COUNT 19 + + #define _DL_PLATFORMS_COUNT 9 + +@@ -54,11 +54,16 @@ enum + HWCAP_S390_VXD = 1 << 12, + HWCAP_S390_VXE = 1 << 13, + HWCAP_S390_GS = 1 << 14, ++ HWCAP_S390_VXRS_EXT2 = 1 << 15, ++ HWCAP_S390_VXRS_PDE = 1 << 16, ++ HWCAP_S390_SORT = 1 << 17, ++ HWCAP_S390_DFLT = 1 << 18, + }; + + #define HWCAP_IMPORTANT (HWCAP_S390_ZARCH | HWCAP_S390_LDISP \ + | HWCAP_S390_EIMM | HWCAP_S390_DFP \ +- | HWCAP_S390_VX | HWCAP_S390_VXE) ++ | HWCAP_S390_VX | HWCAP_S390_VXE \ ++ | HWCAP_S390_VXRS_EXT2) + + /* We cannot provide a general printing function. */ + #define _dl_procinfo(type, word) -1 +diff --git a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h +index 2564712399948375..6b9b59522e3d3bec 100644 +--- a/sysdeps/unix/sysv/linux/s390/bits/hwcap.h ++++ b/sysdeps/unix/sysv/linux/s390/bits/hwcap.h +@@ -39,3 +39,7 @@ + #define HWCAP_S390_VXD 4096 + #define HWCAP_S390_VXE 8192 + #define HWCAP_S390_GS 16384 ++#define HWCAP_S390_VXRS_EXT2 32768 ++#define HWCAP_S390_VXRS_PDE 65536 ++#define HWCAP_S390_SORT 131072 ++#define HWCAP_S390_DFLT 262144 diff --git a/glibc-rh1659438-59.patch b/glibc-rh1659438-59.patch new file mode 100755 index 0000000..8cb861c --- /dev/null +++ b/glibc-rh1659438-59.patch @@ -0,0 +1,195 @@ +commit a899a5512f618d5c4093a2d65e8dee07c791b0ab +Author: Stefan Liebler +Date: Fri Mar 22 11:14:08 2019 +0100 + + S390: Add configure check to detect support for arch13. + + Add two configure checks which detect if arch13 is supported + by the assembler at all - by explicitely setting the machine - + and if it is supported with default settings. + + ChangeLog: + + * config.h.in (HAVE_S390_MIN_ARCH13_ZARCH_ASM_SUPPORT, + HAVE_S390_ARCH13_ASM_SUPPORT): New undefine. + * sysdeps/s390/configure.ac: Add checks for arch13 support. + * sysdeps/s390/configure: Regenerated. + +diff --git a/config.h.in b/config.h.in +index 422a6036ab16e3b6..f63f6c8442914aa1 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -71,6 +71,9 @@ + /* Define if assembler supports z13 zarch instructions as default on S390. */ + #undef HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT + ++/* Define if assembler supports arch13 zarch instruction as default on S390. */ ++#undef HAVE_S390_MIN_ARCH13_ZARCH_ASM_SUPPORT ++ + /* Define if assembler supports vector instructions on S390. */ + #undef HAVE_S390_VX_ASM_SUPPORT + +@@ -78,6 +81,9 @@ + on S390. */ + #undef HAVE_S390_VX_GCC_SUPPORT + ++/* Define if assembler supports arch13 instructions on S390. */ ++#undef HAVE_S390_ARCH13_ASM_SUPPORT ++ + /* Define if assembler supports Intel MPX. */ + #undef HAVE_MPX_SUPPORT + +diff --git a/sysdeps/s390/configure b/sysdeps/s390/configure +index 4a44775e3083d8c3..fa46e9e351e37e55 100644 +--- a/sysdeps/s390/configure ++++ b/sysdeps/s390/configure +@@ -112,6 +112,43 @@ then + + fi + ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 arch13 zarch instruction support" >&5 ++$as_echo_n "checking for S390 arch13 zarch instruction support... " >&6; } ++if ${libc_cv_asm_s390_arch13+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat > conftest.c <<\EOF ++void testinsn (char *buf) ++{ ++ __asm__ (".machine \"arch13\" \n\t" ++ ".machinemode \"zarch_nohighgprs\" \n\t" ++ "lghi %%r0,16 \n\t" ++ "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0"); ++} ++EOF ++if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c ++ -o conftest.o &> /dev/null' ++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } ; ++then ++ libc_cv_asm_s390_arch13=yes ++else ++ libc_cv_asm_s390_arch13=no ++fi ++rm -f conftest* ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_s390_arch13" >&5 ++$as_echo "$libc_cv_asm_s390_arch13" >&6; } ++if test "$libc_cv_asm_s390_arch13" = yes ; ++then ++ $as_echo "#define HAVE_S390_ARCH13_ASM_SUPPORT 1" >>confdefs.h ++ ++fi ++ ++ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 z10 zarch instruction support as default" >&5 + $as_echo_n "checking for S390 z10 zarch instruction support as default... " >&6; } + if ${libc_cv_asm_s390_min_z10_zarch+:} false; then : +@@ -225,5 +262,39 @@ then + + fi + ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for S390 arch13 zarch instruction support as default" >&5 ++$as_echo_n "checking for S390 arch13 zarch instruction support as default... " >&6; } ++if ${libc_cv_asm_s390_min_arch13_zarch+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat > conftest.c <<\EOF ++void testinsn (char *buf) ++{ ++ __asm__ ("lghi %%r0,16 \n\t" ++ "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0"); ++} ++EOF ++if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c ++ -o conftest.o &> /dev/null' ++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } ; ++then ++ libc_cv_asm_s390_min_arch13_zarch=yes ++else ++ libc_cv_asm_s390_min_arch13_zarch=no ++fi ++rm -f conftest* ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_s390_min_arch13_zarch" >&5 ++$as_echo "$libc_cv_asm_s390_min_arch13_zarch" >&6; } ++if test "$libc_cv_asm_s390_min_arch13_zarch" = yes ; ++then ++ $as_echo "#define HAVE_S390_MIN_ARCH13_ZARCH_ASM_SUPPORT 1" >>confdefs.h ++ ++fi ++ + test -n "$critic_missing" && as_fn_error $? " + *** $critic_missing" "$LINENO" 5 +diff --git a/sysdeps/s390/configure.ac b/sysdeps/s390/configure.ac +index 4dfb5574b49d5949..3ed5a8ef87f9694b 100644 +--- a/sysdeps/s390/configure.ac ++++ b/sysdeps/s390/configure.ac +@@ -80,6 +80,32 @@ then + AC_DEFINE(HAVE_S390_VX_GCC_SUPPORT) + fi + ++AC_CACHE_CHECK(for S390 arch13 zarch instruction support, ++ libc_cv_asm_s390_arch13, [dnl ++cat > conftest.c <<\EOF ++void testinsn (char *buf) ++{ ++ __asm__ (".machine \"arch13\" \n\t" ++ ".machinemode \"zarch_nohighgprs\" \n\t" ++ "lghi %%r0,16 \n\t" ++ "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0"); ++} ++EOF ++dnl test, if assembler supports S390 arch13 instructions ++if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c ++ -o conftest.o &> /dev/null]) ; ++then ++ libc_cv_asm_s390_arch13=yes ++else ++ libc_cv_asm_s390_arch13=no ++fi ++rm -f conftest* ]) ++if test "$libc_cv_asm_s390_arch13" = yes ; ++then ++ AC_DEFINE(HAVE_S390_ARCH13_ASM_SUPPORT) ++fi ++ ++ + AC_CACHE_CHECK(for S390 z10 zarch instruction support as default, + libc_cv_asm_s390_min_z10_zarch, [dnl + cat > conftest.c <<\EOF +@@ -163,5 +189,28 @@ then + AC_DEFINE(HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT) + fi + ++AC_CACHE_CHECK(for S390 arch13 zarch instruction support as default, ++ libc_cv_asm_s390_min_arch13_zarch, [dnl ++cat > conftest.c <<\EOF ++void testinsn (char *buf) ++{ ++ __asm__ ("lghi %%r0,16 \n\t" ++ "mvcrl 0(%0),32(%0)" : : "a" (buf) : "memory", "r0"); ++} ++EOF ++dnl test, if assembler supports S390 arch13 zarch instructions as default ++if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS --shared conftest.c ++ -o conftest.o &> /dev/null]) ; ++then ++ libc_cv_asm_s390_min_arch13_zarch=yes ++else ++ libc_cv_asm_s390_min_arch13_zarch=no ++fi ++rm -f conftest* ]) ++if test "$libc_cv_asm_s390_min_arch13_zarch" = yes ; ++then ++ AC_DEFINE(HAVE_S390_MIN_ARCH13_ZARCH_ASM_SUPPORT) ++fi ++ + test -n "$critic_missing" && AC_MSG_ERROR([ + *** $critic_missing]) diff --git a/glibc-rh1659438-6.patch b/glibc-rh1659438-6.patch new file mode 100755 index 0000000..9f4157d --- /dev/null +++ b/glibc-rh1659438-6.patch @@ -0,0 +1,429 @@ +commit 6c6b8c747096d74b900e2711b9b0d463677f6d31 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:05 2018 +0100 + + S390: Unify 31/64bit memcmp. + + The implementation of memcmp for s390-32 (31bit) and + s390-64 (64bit) is nearly the same. + This patch unifies it for maintability reasons. + + __memcmp_z10 and __memcmp_z196 differs between 31 and 64bit: + -31bit needs .machinemode "zarch_nohighgprs" and llgfr %r4,%r4 + -lr vs lgr and some other instructions: + But lgr and co can be also used on 31bit as this ifunc variant + is only called if we are on a zarch machine. + + __memcmp_default differs between 31 and 64bit: + -Some 31bit vs 64bit instructions (e.g. ltr vs ltgr. + Solved with 31/64 specific instruction macros). + -The address of mvc instruction is setup in different ways + (larl vs bras). Solved with #if defined __s390x__. + + Otherwise 31/64bit implementation has the same structure of the code. + + ChangeLog: + + * sysdeps/s390/s390-64/memcmp.S: Move to ... + * sysdeps/s390/memcmp.S: ... here. + Adjust to be usable for 31/64bit. + * sysdeps/s390/s390-32/memcmp.S: Delete File. + * sysdeps/s390/multiarch/Makefile (sysdep_routines): Add memcmp. + * sysdeps/s390/s390-32/multiarch/Makefile (sysdep_routines): + Remove memcmp. + * sysdeps/s390/s390-64/multiarch/Makefile: Likewise. + * sysdeps/s390/s390-64/multiarch/memcmp-s390x.S: Move to ... + * sysdeps/s390/multiarch/memcmp-s390x.S: ... here. + Adjust to be usable for 31/64bit. + * sysdeps/s390/s390-32/multiarch/memcmp-s390.S: Delete File. + * sysdeps/s390/s390-64/multiarch/memcmp.c: Move to ... + * sysdeps/s390/multiarch/memcmp.c: ... here. + * sysdeps/s390/s390-32/multiarch/memcmp.c: Delete File. + +diff --git a/sysdeps/s390/s390-64/memcmp.S b/sysdeps/s390/memcmp.S +similarity index 60% +rename from sysdeps/s390/s390-64/memcmp.S +rename to sysdeps/s390/memcmp.S +index 005b19de45fcd883..751293a99e34f530 100644 +--- a/sysdeps/s390/s390-64/memcmp.S ++++ b/sysdeps/s390/memcmp.S +@@ -1,4 +1,4 @@ +-/* memcmp - compare two memory blocks. 64 bit S/390 version. ++/* memcmp - compare two memory blocks. 31/64 bit S/390 version. + Copyright (C) 2012-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + +@@ -26,34 +26,62 @@ + %r4 = number of bytes to compare. */ + + .text ++#if defined __s390x__ ++# define LTGR ltgr ++# define AGHI aghi ++# define BRCTG brctg ++#else ++# define LTGR ltr ++# define AGHI ahi ++# define BRCTG brct ++#endif /* ! defined __s390x__ */ ++ + #ifdef USE_MULTIARCH + ENTRY(__memcmp_default) + #else + ENTRY(memcmp) + #endif ++#if defined __s390x__ + .machine "z900" +- ltgr %r4,%r4 +- je .L_Z900_4 +- aghi %r4,-1 ++#else ++ .machine "g5" ++ basr %r5,0 ++.L_Z900_G5_16: ++# define Z900_G5_EX_D .L_Z900_G5_15-.L_Z900_G5_16 ++#endif /* ! defined __s390x__ */ ++ LTGR %r4,%r4 ++ je .L_Z900_G5_4 ++ AGHI %r4,-1 ++#if defined __s390x__ + srlg %r1,%r4,8 +- ltgr %r1,%r1 +- jne .L_Z900_12 +-.L_Z900_3: +- larl %r1,.L_Z900_15 +- ex %r4,0(%r1) +-.L_Z900_4: ++ larl %r5,.L_Z900_G5_15 ++# define Z900_G5_EX_D 0 ++#else ++ lr %r1,%r4 ++ srl %r1,8 ++#endif /* ! defined __s390x__ */ ++ LTGR %r1,%r1 ++ jne .L_Z900_G5_12 ++.L_Z900_G5_3: ++ ex %r4,Z900_G5_EX_D(%r5) ++.L_Z900_G5_4: + ipm %r2 ++#if defined __s390x__ + sllg %r2,%r2,34 + srag %r2,%r2,62 ++#else ++ sll %r2,2 ++ sra %r2,30 ++#endif /* ! defined __s390x__ */ + br %r14 +-.L_Z900_12: ++.L_Z900_G5_12: + clc 0(256,%r3),0(%r2) +- jne .L_Z900_4 ++ jne .L_Z900_G5_4 + la %r3,256(%r3) + la %r2,256(%r2) +- brctg %r1,.L_Z900_12 +- j .L_Z900_3 +-.L_Z900_15: ++ BRCTG %r1,.L_Z900_G5_12 ++ j .L_Z900_G5_3 ++.L_Z900_G5_15: + clc 0(1,%r3),0(%r2) + #ifdef USE_MULTIARCH + END(__memcmp_default) +@@ -62,3 +90,7 @@ END(memcmp) + libc_hidden_builtin_def (memcmp) + weak_alias (memcmp, bcmp) + #endif ++ ++#undef LTGR ++#undef AGHI ++#undef BRCTG +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index c893ebc5659fd4ae..53dd8654d73677db 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -19,7 +19,8 @@ sysdep_routines += strlen strlen-vx strlen-c \ + rawmemchr rawmemchr-vx rawmemchr-c \ + memccpy memccpy-vx memccpy-c \ + memrchr memrchr-vx memrchr-c \ +- mempcpy ++ mempcpy \ ++ memcmp memcmp-s390x + endif + + ifeq ($(subdir),wcsmbs) +diff --git a/sysdeps/s390/s390-64/multiarch/memcmp-s390x.S b/sysdeps/s390/multiarch/memcmp-s390x.S +similarity index 89% +rename from sysdeps/s390/s390-64/multiarch/memcmp-s390x.S +rename to sysdeps/s390/multiarch/memcmp-s390x.S +index 35f9bf9cf72da503..6321737acec821ec 100644 +--- a/sysdeps/s390/s390-64/multiarch/memcmp-s390x.S ++++ b/sysdeps/s390/multiarch/memcmp-s390x.S +@@ -1,4 +1,4 @@ +-/* CPU specific memcmp implementations. 64 bit S/390 version. ++/* CPU specific memcmp implementations. 31/64 bit S/390 version. + Copyright (C) 2012-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + +@@ -31,6 +31,10 @@ + + ENTRY(__memcmp_z196) + .machine "z196" ++ .machinemode "zarch_nohighgprs" ++# if !defined __s390x__ ++ llgfr %r4,%r4 ++# endif /* !defined __s390x__ */ + ltgr %r4,%r4 + je .L_Z196_4 + aghi %r4,-1 +@@ -64,6 +68,10 @@ END(__memcmp_z196) + + ENTRY(__memcmp_z10) + .machine "z10" ++ .machinemode "zarch_nohighgprs" ++# if !defined __s390x__ ++ llgfr %r4,%r4 ++# endif /* !defined __s390x__ */ + ltgr %r4,%r4 + je .L_Z10_4 + aghi %r4,-1 +diff --git a/sysdeps/s390/s390-32/multiarch/memcmp.c b/sysdeps/s390/multiarch/memcmp.c +similarity index 100% +rename from sysdeps/s390/s390-32/multiarch/memcmp.c +rename to sysdeps/s390/multiarch/memcmp.c +diff --git a/sysdeps/s390/s390-32/memcmp.S b/sysdeps/s390/s390-32/memcmp.S +deleted file mode 100644 +index f9ad0bc745daf05f..0000000000000000 +--- a/sysdeps/s390/s390-32/memcmp.S ++++ /dev/null +@@ -1,66 +0,0 @@ +-/* memcmp - compare two memory blocks. 32 bit S/390 version. +- Copyright (C) 2012-2018 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 +- . */ +- +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +-/* INPUT PARAMETERS +- %r2 = address of first memory area +- %r3 = address of second memory area +- %r4 = number of bytes to compare. */ +- +- .text +-#ifdef USE_MULTIARCH +-ENTRY(__memcmp_default) +-#else +-ENTRY(memcmp) +-#endif +- .machine "g5" +- basr %r5,0 +-.L_G5_16: +- ltr %r4,%r4 +- je .L_G5_4 +- ahi %r4,-1 +- lr %r1,%r4 +- srl %r1,8 +- ltr %r1,%r1 +- jne .L_G5_12 +- ex %r4,.L_G5_17-.L_G5_16(%r5) +-.L_G5_4: +- ipm %r2 +- sll %r2,2 +- sra %r2,30 +- br %r14 +-.L_G5_12: +- clc 0(256,%r3),0(%r2) +- jne .L_G5_4 +- la %r3,256(%r3) +- la %r2,256(%r2) +- brct %r1,.L_G5_12 +- ex %r4,.L_G5_17-.L_G5_16(%r5) +- j .L_G5_4 +-.L_G5_17: +- clc 0(1,%r3),0(%r2) +-#ifdef USE_MULTIARCH +-END(__memcmp_default) +-#else +-END(memcmp) +-libc_hidden_builtin_def (memcmp) +-weak_alias(memcmp, bcmp) +-#endif +diff --git a/sysdeps/s390/s390-32/multiarch/Makefile b/sysdeps/s390/s390-32/multiarch/Makefile +index 4b11e28656ac19ab..82a7492eb8436479 100644 +--- a/sysdeps/s390/s390-32/multiarch/Makefile ++++ b/sysdeps/s390/s390-32/multiarch/Makefile +@@ -1,3 +1,3 @@ + ifeq ($(subdir),string) +-sysdep_routines += memcpy memcpy-s390 memcmp memcmp-s390 ++sysdep_routines += memcpy memcpy-s390 + endif +diff --git a/sysdeps/s390/s390-32/multiarch/memcmp-s390.S b/sysdeps/s390/s390-32/multiarch/memcmp-s390.S +deleted file mode 100644 +index e53b508c98bebeba..0000000000000000 +--- a/sysdeps/s390/s390-32/multiarch/memcmp-s390.S ++++ /dev/null +@@ -1,107 +0,0 @@ +-/* CPU specific memcmp implementations. 32 bit S/390 version. +- Copyright (C) 2012-2018 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 +- . */ +- +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +-/* INPUT PARAMETERS +- %r2 = address of first memory area +- %r3 = address of second memory area +- %r4 = number of bytes to compare. */ +- +- .text +- +-#if IS_IN (libc) +- +-ENTRY(__memcmp_z196) +- .machine "z196" +- .machinemode "zarch_nohighgprs" +- ltr %r4,%r4 +- je .L_Z196_4 +- ahi %r4,-1 +- srlk %r1,%r4,8 +- ltr %r1,%r1 +- jne .L_Z196_2 +-.L_Z196_3: +- exrl %r4,.L_Z196_14 +-.L_Z196_4: +- ipm %r2 +- sll %r2,2 +- sra %r2,30 +- br %r14 +-.L_Z196_17: +- la %r3,256(%r3) +- la %r2,256(%r2) +- ahi %r1,-1 +- je .L_Z196_3 +-.L_Z196_2: +- pfd 1,512(%r3) +- pfd 1,512(%r2) +- clc 0(256,%r3),0(%r2) +- je .L_Z196_17 +- ipm %r2 +- sll %r2,2 +- sra %r2,30 +- br %r14 +-.L_Z196_14: +- clc 0(1,%r3),0(%r2) +-END(__memcmp_z196) +- +-ENTRY(__memcmp_z10) +- .machine "z10" +- .machinemode "zarch_nohighgprs" +- ltr %r4,%r4 +- je .L_Z10_4 +- ahi %r4,-1 +- lr %r1,%r4 +- srl %r1,8 +- cijlh %r1,0,.L_Z10_12 +-.L_Z10_3: +- exrl %r4,.L_Z10_15 +-.L_Z10_4: +- ipm %r2 +- sll %r2,2 +- sra %r2,30 +- br %r14 +-.L_Z10_12: +- pfd 1,512(%r3) +- pfd 1,512(%r2) +- clc 0(256,%r3),0(%r2) +- jne .L_Z10_4 +- la %r3,256(%r3) +- la %r2,256(%r2) +- brct %r1,.L_Z10_12 +- j .L_Z10_3 +-.L_Z10_15: +- clc 0(1,%r3),0(%r2) +-END(__memcmp_z10) +- +-#endif /* IS_IN (libc) */ +- +-#include "../memcmp.S" +- +-#if !IS_IN (libc) +-.globl memcmp +-.set memcmp,__memcmp_default +-.weak bcmp +-.set bcmp,__memcmp_default +-#elif defined SHARED && IS_IN (libc) +-.globl __GI_memcmp +-.set __GI_memcmp,__memcmp_default +-#endif +diff --git a/sysdeps/s390/s390-64/multiarch/Makefile b/sysdeps/s390/s390-64/multiarch/Makefile +index e4870c7ee177ad0d..8a043e3327a1527a 100644 +--- a/sysdeps/s390/s390-64/multiarch/Makefile ++++ b/sysdeps/s390/s390-64/multiarch/Makefile +@@ -1,3 +1,3 @@ + ifeq ($(subdir),string) +-sysdep_routines += memcpy memcpy-s390x memcmp memcmp-s390x ++sysdep_routines += memcpy memcpy-s390x + endif +diff --git a/sysdeps/s390/s390-64/multiarch/memcmp.c b/sysdeps/s390/s390-64/multiarch/memcmp.c +deleted file mode 100644 +index 1e6f31806e172d7d..0000000000000000 +--- a/sysdeps/s390/s390-64/multiarch/memcmp.c ++++ /dev/null +@@ -1,27 +0,0 @@ +-/* Multiple versions of memcmp. +- Copyright (C) 2015-2018 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 +- . */ +- +-#if IS_IN (libc) +-# define memcmp __redirect_memcmp +-# include +-# undef memcmp +-# include +- +-s390_libc_ifunc (__redirect_memcmp, __memcmp, memcmp) +-weak_alias (memcmp, bcmp); +-#endif diff --git a/glibc-rh1659438-60.patch b/glibc-rh1659438-60.patch new file mode 100755 index 0000000..6eacc7f --- /dev/null +++ b/glibc-rh1659438-60.patch @@ -0,0 +1,202 @@ +commit 96fbb9a328232e42814334d6e29a9a9c7995c01d +Author: Stefan Liebler +Date: Fri Mar 22 11:14:08 2019 +0100 + + S390: Add arch13 memmove ifunc variant. + + This patch introduces the new arch13 ifunc variant for memmove. + For the forward or non-overlapping case it is just using memcpy. + For the backward case it relies on the new instruction mvcrl. + The instruction copies up to 256 bytes at once. + In case of an overlap, it copies the bytes like copying them + one by one starting from right to left. + + ChangeLog: + + * sysdeps/s390/ifunc-memcpy.h (HAVE_MEMMOVE_ARCH13, MEMMOVE_ARCH13 + HAVE_MEMMOVE_IFUNC_AND_ARCH13_SUPPORT): New defines. + * sysdeps/s390/memcpy-z900.S: Add arch13 memmove implementation. + * sysdeps/s390/memmove.c (memmove): Add arch13 variant in + ifunc selector. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Add ifunc variant for arch13 memmove. + * sysdeps/s390/multiarch/ifunc-resolve.h (S390_STFLE_BITS_ARCH13_MIE3, + S390_IS_ARCH13_MIE3): New defines. + +diff --git a/sysdeps/s390/ifunc-memcpy.h b/sysdeps/s390/ifunc-memcpy.h +index 0e701968c8f39014..e8cd794587b44922 100644 +--- a/sysdeps/s390/ifunc-memcpy.h ++++ b/sysdeps/s390/ifunc-memcpy.h +@@ -44,7 +44,7 @@ + #endif + + #if defined SHARED && defined USE_MULTIARCH && IS_IN (libc) \ +- && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++ && ! defined HAVE_S390_MIN_ARCH13_ZARCH_ASM_SUPPORT + # define HAVE_MEMMOVE_IFUNC 1 + #else + # define HAVE_MEMMOVE_IFUNC 0 +@@ -56,14 +56,27 @@ + # define HAVE_MEMMOVE_IFUNC_AND_VX_SUPPORT 0 + #endif + +-#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++#ifdef HAVE_S390_ARCH13_ASM_SUPPORT ++# define HAVE_MEMMOVE_IFUNC_AND_ARCH13_SUPPORT HAVE_MEMMOVE_IFUNC ++#else ++# define HAVE_MEMMOVE_IFUNC_AND_ARCH13_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_ARCH13_ZARCH_ASM_SUPPORT ++# define MEMMOVE_DEFAULT MEMMOVE_ARCH13 ++# define HAVE_MEMMOVE_C 0 ++# define HAVE_MEMMOVE_Z13 0 ++# define HAVE_MEMMOVE_ARCH13 1 ++#elif defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT + # define MEMMOVE_DEFAULT MEMMOVE_Z13 + # define HAVE_MEMMOVE_C 0 + # define HAVE_MEMMOVE_Z13 1 ++# define HAVE_MEMMOVE_ARCH13 HAVE_MEMMOVE_IFUNC_AND_ARCH13_SUPPORT + #else + # define MEMMOVE_DEFAULT MEMMOVE_C + # define HAVE_MEMMOVE_C 1 + # define HAVE_MEMMOVE_Z13 HAVE_MEMMOVE_IFUNC_AND_VX_SUPPORT ++# define HAVE_MEMMOVE_ARCH13 HAVE_MEMMOVE_IFUNC_AND_ARCH13_SUPPORT + #endif + + #if HAVE_MEMCPY_Z900_G5 +@@ -101,3 +114,9 @@ + #else + # define MEMMOVE_Z13 NULL + #endif ++ ++#if HAVE_MEMMOVE_ARCH13 ++# define MEMMOVE_ARCH13 __memmove_arch13 ++#else ++# define MEMMOVE_ARCH13 NULL ++#endif +diff --git a/sysdeps/s390/memcpy-z900.S b/sysdeps/s390/memcpy-z900.S +index bd3b1950ee442c0c..45eddc67a48e991e 100644 +--- a/sysdeps/s390/memcpy-z900.S ++++ b/sysdeps/s390/memcpy-z900.S +@@ -277,6 +277,61 @@ ENTRY(MEMMOVE_Z13) + END(MEMMOVE_Z13) + #endif /* HAVE_MEMMOVE_Z13 */ + ++#if HAVE_MEMMOVE_ARCH13 ++ENTRY(MEMMOVE_ARCH13) ++ .machine "arch13" ++ .machinemode "zarch_nohighgprs" ++# if ! defined __s390x__ ++ /* Note: The 31bit dst and src pointers are prefixed with zeroes. */ ++ llgfr %r4,%r4 ++ llgfr %r3,%r3 ++ llgfr %r2,%r2 ++# endif /* ! defined __s390x__ */ ++ sgrk %r5,%r2,%r3 ++ aghik %r0,%r4,-1 /* Both vstl and mvcrl needs highest index. */ ++ clgijh %r4,16,.L_MEMMOVE_ARCH13_LARGE ++.L_MEMMOVE_ARCH13_SMALL: ++ jl .L_MEMMOVE_ARCH13_END /* Return if len was zero (cc of aghik). */ ++ /* Store up to 16 bytes with vll/vstl (needs highest index). */ ++ vll %v16,%r0,0(%r3) ++ vstl %v16,%r0,0(%r2) ++.L_MEMMOVE_ARCH13_END: ++ br %r14 ++.L_MEMMOVE_ARCH13_LARGE: ++ lgr %r1,%r2 /* For memcpy: r1: Use as dest ; r2: Return dest */ ++ /* The unsigned comparison (dst - src >= len) determines if we can ++ execute the forward case with memcpy. */ ++#if ! HAVE_MEMCPY_Z196 ++# error The arch13 variant of memmove needs the z196 variant of memcpy! ++#endif ++ /* Backward case. */ ++ clgrjhe %r5,%r4,.L_Z196_start2 ++ clgijh %r0,255,.L_MEMMOVE_ARCH13_LARGER_256B ++ /* Move up to 256bytes with mvcrl (move right to left). */ ++ mvcrl 0(%r1),0(%r3) /* Move (r0 + 1) bytes from r3 to r1. */ ++ br %r14 ++.L_MEMMOVE_ARCH13_LARGER_256B: ++ /* First move the "remaining" block of up to 256 bytes at the end of ++ src/dst buffers. Then move blocks of 256bytes in a loop starting ++ with the block at the end. ++ (If src/dst pointers are aligned e.g. to 256 bytes, then the pointers ++ passed to mvcrl instructions are aligned, too) */ ++ risbgn %r5,%r0,8,128+63,56 /* r5 = r0 / 256 */ ++ risbgn %r0,%r0,56,128+63,0 /* r0 = r0 & 0xFF */ ++ slgr %r4,%r0 ++ lay %r1,-1(%r4,%r1) ++ lay %r3,-1(%r4,%r3) ++ mvcrl 0(%r1),0(%r3) /* Move (r0 + 1) bytes from r3 to r1. */ ++ lghi %r0,255 /* Always copy 256 bytes in the loop below! */ ++.L_MEMMOVE_ARCH13_LARGE_256B_LOOP: ++ aghi %r1,-256 ++ aghi %r3,-256 ++ mvcrl 0(%r1),0(%r3) /* Move (r0 + 1) bytes from r3 to r1. */ ++ brctg %r5,.L_MEMMOVE_ARCH13_LARGE_256B_LOOP ++ br %r14 ++END(MEMMOVE_ARCH13) ++#endif /* HAVE_MEMMOVE_ARCH13 */ ++ + #if ! HAVE_MEMCPY_IFUNC + /* If we don't use ifunc, define an alias for mem[p]cpy here. + Otherwise see sysdeps/s390/mem[p]cpy.c. */ +diff --git a/sysdeps/s390/memmove.c b/sysdeps/s390/memmove.c +index ac34edf80f2678cd..f6d31a4fcd56355b 100644 +--- a/sysdeps/s390/memmove.c ++++ b/sysdeps/s390/memmove.c +@@ -36,9 +36,19 @@ extern __typeof (__redirect_memmove) MEMMOVE_C attribute_hidden; + extern __typeof (__redirect_memmove) MEMMOVE_Z13 attribute_hidden; + # endif + ++# if HAVE_MEMMOVE_ARCH13 ++extern __typeof (__redirect_memmove) MEMMOVE_ARCH13 attribute_hidden; ++# endif ++ + s390_libc_ifunc_expr (__redirect_memmove, memmove, +- (HAVE_MEMMOVE_Z13 && (hwcap & HWCAP_S390_VX)) +- ? MEMMOVE_Z13 +- : MEMMOVE_DEFAULT ++ ({ ++ s390_libc_ifunc_expr_stfle_init (); ++ (HAVE_MEMMOVE_ARCH13 ++ && S390_IS_ARCH13_MIE3 (stfle_bits)) ++ ? MEMMOVE_ARCH13 ++ : (HAVE_MEMMOVE_Z13 && (hwcap & HWCAP_S390_VX)) ++ ? MEMMOVE_Z13 ++ : MEMMOVE_DEFAULT; ++ }) + ) + #endif +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 177c5fd6fe269d9b..c24bfc95f2d7a22d 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -169,6 +169,11 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + #if HAVE_MEMMOVE_IFUNC + IFUNC_IMPL (i, name, memmove, ++# if HAVE_MEMMOVE_ARCH13 ++ IFUNC_IMPL_ADD (array, i, memmove, ++ S390_IS_ARCH13_MIE3 (stfle_bits), ++ MEMMOVE_ARCH13) ++# endif + # if HAVE_MEMMOVE_Z13 + IFUNC_IMPL_ADD (array, i, memmove, + dl_hwcap & HWCAP_S390_VX, MEMMOVE_Z13) +diff --git a/sysdeps/s390/multiarch/ifunc-resolve.h b/sysdeps/s390/multiarch/ifunc-resolve.h +index b2be015401313d4b..db735bb341ab6b86 100644 +--- a/sysdeps/s390/multiarch/ifunc-resolve.h ++++ b/sysdeps/s390/multiarch/ifunc-resolve.h +@@ -22,6 +22,11 @@ + + #define S390_STFLE_BITS_Z10 34 /* General instructions extension */ + #define S390_STFLE_BITS_Z196 45 /* Distinct operands, pop ... */ ++#define S390_STFLE_BITS_ARCH13_MIE3 61 /* Miscellaneous-Instruction-Extensions ++ Facility 3, e.g. mvcrl. */ ++ ++#define S390_IS_ARCH13_MIE3(STFLE_BITS) \ ++ ((STFLE_BITS & (1ULL << (63 - S390_STFLE_BITS_ARCH13_MIE3))) != 0) + + #define S390_IS_Z196(STFLE_BITS) \ + ((STFLE_BITS & (1ULL << (63 - S390_STFLE_BITS_Z196))) != 0) diff --git a/glibc-rh1659438-61.patch b/glibc-rh1659438-61.patch new file mode 100755 index 0000000..32e535a --- /dev/null +++ b/glibc-rh1659438-61.patch @@ -0,0 +1,332 @@ +commit 6f47401bd5fc71209219779a0426170a9a7395b0 +Author: Stefan Liebler +Date: Fri Mar 22 11:14:08 2019 +0100 + + S390: Add arch13 strstr ifunc variant. + + This patch introduces the new arch13 ifunc variant for strstr. + For needles longer than 9 charachters it is relying on the common-code + implementation. For shorter needles it is using the new vstrs instruction + which is able to search a substring within a vector register. + + ChangeLog: + + * sysdeps/s390/Makefile (sysdep_routines): Add strstr-arch13. + * sysdeps/s390/ifunc-strstr.h (HAVE_STRSTR_ARCH13, STRSTR_ARCH13, + STRSTR_Z13_ONLY_USED_AS_FALLBACK, HAVE_STRSTR_IFUNC_AND_ARCH13_SUPPORT): + New defines. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Add ifunc variant for arch13 strstr. + * sysdeps/s390/strstr-arch13.S: New file. + * sysdeps/s390/strstr-vx.c: Omit GI symbol for z13 strstr ifunc variant + if it is only used as fallback. + * sysdeps/s390/strstr.c (strstr): Add arch13 variant in ifunc selector. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 3f7de6613c343819..7287b1833da9500f 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -35,7 +35,7 @@ sysdep_routines += bzero memset memset-z900 \ + memcmp memcmp-z900 \ + mempcpy memcpy memcpy-z900 \ + memmove memmove-c \ +- strstr strstr-vx strstr-c \ ++ strstr strstr-arch13 strstr-vx strstr-c \ + memmem memmem-vx memmem-c \ + strlen strlen-vx strlen-c \ + strnlen strnlen-vx strnlen-c \ +diff --git a/sysdeps/s390/ifunc-strstr.h b/sysdeps/s390/ifunc-strstr.h +index e6ccfd4e44a1a790..809184d425ad06b0 100644 +--- a/sysdeps/s390/ifunc-strstr.h ++++ b/sysdeps/s390/ifunc-strstr.h +@@ -17,7 +17,7 @@ + . */ + + #if defined USE_MULTIARCH && IS_IN (libc) \ +- && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++ && ! defined HAVE_S390_MIN_ARCH13_ZARCH_ASM_SUPPORT + # define HAVE_STRSTR_IFUNC 1 + #else + # define HAVE_STRSTR_IFUNC 0 +@@ -29,14 +29,32 @@ + # define HAVE_STRSTR_IFUNC_AND_VX_SUPPORT 0 + #endif + +-#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++#ifdef HAVE_S390_ARCH13_ASM_SUPPORT ++# define HAVE_STRSTR_IFUNC_AND_ARCH13_SUPPORT HAVE_STRSTR_IFUNC ++#else ++# define HAVE_STRSTR_IFUNC_AND_ARCH13_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_ARCH13_ZARCH_ASM_SUPPORT ++# define STRSTR_DEFAULT STRSTR_ARCH13 ++# define HAVE_STRSTR_C 0 ++# define HAVE_STRSTR_Z13 1 ++# define STRSTR_Z13_ONLY_USED_AS_FALLBACK 1 ++# define HAVE_STRSTR_ARCH13 1 ++#elif defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT + # define STRSTR_DEFAULT STRSTR_Z13 + # define HAVE_STRSTR_C 0 + # define HAVE_STRSTR_Z13 1 ++# define HAVE_STRSTR_ARCH13 HAVE_STRSTR_IFUNC_AND_ARCH13_SUPPORT + #else + # define STRSTR_DEFAULT STRSTR_C + # define HAVE_STRSTR_C 1 + # define HAVE_STRSTR_Z13 HAVE_STRSTR_IFUNC_AND_VX_SUPPORT ++# define HAVE_STRSTR_ARCH13 HAVE_STRSTR_IFUNC_AND_ARCH13_SUPPORT ++#endif ++ ++#ifndef STRSTR_Z13_ONLY_USED_AS_FALLBACK ++# define STRSTR_Z13_ONLY_USED_AS_FALLBACK 0 + #endif + + #if HAVE_STRSTR_C +@@ -50,3 +68,9 @@ + #else + # define STRSTR_Z13 NULL + #endif ++ ++#if HAVE_STRSTR_ARCH13 ++# define STRSTR_ARCH13 __strstr_arch13 ++#else ++# define STRSTR_ARCH13 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index c24bfc95f2d7a22d..67a6a9c94afccd48 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -186,6 +186,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + #if HAVE_STRSTR_IFUNC + IFUNC_IMPL (i, name, strstr, ++# if HAVE_STRSTR_ARCH13 ++ IFUNC_IMPL_ADD (array, i, strstr, ++ dl_hwcap & HWCAP_S390_VXRS_EXT2, STRSTR_ARCH13) ++# endif + # if HAVE_STRSTR_Z13 + IFUNC_IMPL_ADD (array, i, strstr, + dl_hwcap & HWCAP_S390_VX, STRSTR_Z13) +diff --git a/sysdeps/s390/strstr-arch13.S b/sysdeps/s390/strstr-arch13.S +new file mode 100644 +index 0000000000000000..929b026adfeba740 +--- /dev/null ++++ b/sysdeps/s390/strstr-arch13.S +@@ -0,0 +1,179 @@ ++/* Vector optimized 32/64 bit S/390 version of strstr. ++ 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 ++ . */ ++ ++#include ++#if HAVE_STRSTR_ARCH13 ++# include "sysdep.h" ++# include "asm-syntax.h" ++ .text ++ ++/* char *strstr (const char *haystack=r2, const char *needle=r3) ++ Locate a substring. */ ++ENTRY(STRSTR_ARCH13) ++ .machine "arch13" ++ .machinemode "zarch_nohighgprs" ++ lcbb %r1,0(%r3),6 ++ jo .Lneedle_on_bb /* Needle on block-boundary? */ ++ vl %v18,0(%r3),6 /* Load needle. */ ++ vfenezb %v19,%v18,%v18 /* v19[7] contains the length of needle. */ ++.Lneedle_loaded: ++ vlgvb %r4,%v19,7 /* Get index of zero or 16 if not found. */ ++ lghi %r5,17 /* See below: min-skip-partial-match-index. */ ++ cgibe %r4,0,0(%r14) /* Test if needle is zero and return. */ ++ ++ /* The vstrs instruction is able to handle needles up to a length of 16, ++ but then we may have to load the next part of haystack with a ++ small offset. This will be slow - see examples: ++ haystack =mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm...mmmmmmmmmmmmmmmmmmma ++ needle = mmmmmmmmmmmmmma0 ++ => needle_len=15; vstrs reports a partial match; haystack+=2 ++ haystack =mmmmmmmmmmmmmmmm mmmmmmmmmmmmmmmmmm...mmmmmmmmmmmmmmmmmmma ++ needle = mmmmmmmma0000000 ++ => needle_len=9; vstrs reports a partial match; haystack+=8 */ ++# if ! HAVE_STRSTR_Z13 ++# error The arch13 variant of strstr needs the z13 variant of strstr! ++# endif ++ clgfi %r4,9 ++ jh STRSTR_Z13 ++ ++ /* In case of a partial match, the vstrs instruction returns the index ++ of the partial match in a vector-register. Then we have to ++ reload the string at the "current-position plus this index" and run ++ vstrs again in order to determine if it was a full match or no match. ++ Transferring this index from vr to gr, compute the haystack-address ++ and loading with vl is quite slow as all instructions have data ++ dependencies. Thus we assume, that a partial match is always at the ++ first possible index and just load the next part of haystack from ++ there instead of waiting until the correct index is computed: ++ min-skip-partial-match-index = (16 - n_len) + 1 */ ++ sgr %r5,%r4 ++ ++.Lloop: ++ lcbb %r1,0(%r2),6 ++ jo .Lloop_haystack_on_bb /* Haystack on block-boundary? */ ++ vl %v16,0(%r2) /* Load next part of haystack. */ ++.Lloop_haystack_loaded: ++ /* Vector string search with zero search (cc=0 => no match). */ ++ vstrs %v20,%v16,%v18,%v19,0,2 ++ jne .Lloop_vstrs_nonzero_cc ++ lcbb %r1,16(%r2),6 /* Next part of haystack. */ ++ jo .Lloop_haystack_on_bb16 ++ vl %v16,16(%r2) ++ vstrs %v20,%v16,%v18,%v19,0,2 ++ jne .Lloop_vstrs_nonzero_cc16 ++ lcbb %r1,32(%r2),6 /* Next part of haystack. */ ++ jo .Lloop_haystack_on_bb32 ++ vl %v16,32(%r2) ++ vstrs %v20,%v16,%v18,%v19,0,2 ++ jne .Lloop_vstrs_nonzero_cc32 ++ lcbb %r1,48(%r2),6 /* Next part of haystack. */ ++ jo .Lloop_haystack_on_bb48 ++ vl %v16,48(%r2) ++ vstrs %v20,%v16,%v18,%v19,0,2 ++ jne .Lloop_vstrs_nonzero_cc48 ++ la %r2,64(%r2) ++ j .Lloop ++ ++.Lloop_vstrs_nonzero_cc48: ++ la %r2,16(%r2) ++.Lloop_vstrs_nonzero_cc32: ++ la %r2,16(%r2) ++.Lloop_vstrs_nonzero_cc16: ++ la %r2,16(%r2) ++.Lloop_vstrs_nonzero_cc: ++ jh .Lend_match_found /* cc == 2 (full match) */ ++ jl .Lend_no_match /* cc == 1 (no match, end of string) */ ++ /* cc == 3 (partial match) See above: min-skip-partial-match-index! */ ++ lcbb %r1,0(%r5,%r2),6 ++ la %r2,0(%r5,%r2) ++ jo .Lloop_haystack_on_bb ++ vl %v16,0(%r2) ++ vstrs %v20,%v16,%v18,%v19,0,2 ++.Lloop_vstrs_nonzero_cc_loop: ++ jh .Lend_match_found ++ jl .Lend_no_match ++ la %r2,0(%r5,%r2) ++ je .Lloop ++ lcbb %r1,0(%r2),6 /* Next part of haystack. */ ++ jo .Lloop_haystack_on_bb ++ vl %v16,0(%r2) ++ vstrs %v20,%v16,%v18,%v19,0,2 ++ jh .Lend_match_found ++ jl .Lend_no_match ++ la %r2,0(%r5,%r2) ++ je .Lloop ++ lcbb %r1,0(%r2),6 /* Next part of haystack. */ ++ jo .Lloop_haystack_on_bb ++ vl %v16,0(%r2) ++ vstrs %v20,%v16,%v18,%v19,0,2 ++ jh .Lend_match_found ++ jl .Lend_no_match ++ la %r2,0(%r5,%r2) ++ je .Lloop ++ lcbb %r1,0(%r2),6 /* Next part of haystack. */ ++ jo .Lloop_haystack_on_bb ++ vl %v16,0(%r2) ++ vstrs %v20,%v16,%v18,%v19,0,2 ++ j .Lloop_vstrs_nonzero_cc_loop ++ ++.Lend_no_match: ++ lghi %r2,0 ++ br %r14 ++.Lend_match_found: ++ vlgvb %r4,%v20,7 ++ la %r2,0(%r4,%r2) ++ br %r14 ++ ++.Lloop_haystack_on_bb48: ++ la %r2,16(%r2) ++.Lloop_haystack_on_bb32: ++ la %r2,16(%r2) ++.Lloop_haystack_on_bb16: ++ la %r2,16(%r2) ++.Lloop_haystack_on_bb: ++ /* Haystack located on page-boundary. */ ++ ahi %r1,-1 /* vll needs highest index instead of count. */ ++ vll %v16,%r1,0(%r2) ++ vlvgb %v21,%r1,7 ++ vfenezb %v17,%v16,%v16 /* Search zero in loaded haystack bytes. */ ++ veclb %v17,%v21 /* Zero index <= loaded byte index? */ ++ jle .Lloop_haystack_loaded /* -> v16 contains full haystack. */ ++ vl %v16,0(%r2) /* Load haystack beyond page boundary. */ ++ j .Lloop_haystack_loaded ++ ++.Lneedle_on_bb: ++ /* Needle located on page-boundary. */ ++ ahi %r1,-1 /* vll needs highest index instead of count. */ ++ vll %v18,%r1,0(%r3) ++ vlvgb %v21,%r1,7 ++ vfenezb %v19,%v18,%v18 /* Search zero in loaded needle bytes. */ ++ veclb %v19,%v21 /* Zero index <= max loaded byte index? */ ++ jle .Lneedle_loaded /* -> v18 contains full needle. */ ++ vl %v16,0(%r3) /* Load needle beyond page boundary. */ ++ vfenezb %v19,%v18,%v18 ++ j .Lneedle_loaded ++END(STRSTR_ARCH13) ++ ++# if ! HAVE_STRSTR_IFUNC ++strong_alias (STRSTR_ARCH13, strstr) ++# endif ++ ++# if STRSTR_Z13_ONLY_USED_AS_FALLBACK && defined SHARED && IS_IN (libc) ++strong_alias (STRSTR_ARCH13, __GI_strstr) ++# endif ++#endif +diff --git a/sysdeps/s390/strstr-vx.c b/sysdeps/s390/strstr-vx.c +index effae9d5eb7d2fb1..f69159ffc198b10b 100644 +--- a/sysdeps/s390/strstr-vx.c ++++ b/sysdeps/s390/strstr-vx.c +@@ -19,11 +19,11 @@ + #include + + #if HAVE_STRSTR_Z13 +-# if HAVE_STRSTR_IFUNC ++# if HAVE_STRSTR_IFUNC || STRSTR_Z13_ONLY_USED_AS_FALLBACK + # define STRSTR STRSTR_Z13 + # if defined SHARED && IS_IN (libc) + # undef libc_hidden_builtin_def +-# if HAVE_STRSTR_C ++# if HAVE_STRSTR_C || STRSTR_Z13_ONLY_USED_AS_FALLBACK + # define libc_hidden_builtin_def(name) + # else + # define libc_hidden_builtin_def(name) \ +diff --git a/sysdeps/s390/strstr.c b/sysdeps/s390/strstr.c +index f8432349a7254cc6..d2969fd0a68fadbf 100644 +--- a/sysdeps/s390/strstr.c ++++ b/sysdeps/s390/strstr.c +@@ -32,8 +32,14 @@ extern __typeof (__redirect_strstr) STRSTR_C attribute_hidden; + extern __typeof (__redirect_strstr) STRSTR_Z13 attribute_hidden; + # endif + ++# if HAVE_STRSTR_ARCH13 ++extern __typeof (__redirect_strstr) STRSTR_ARCH13 attribute_hidden; ++# endif ++ + s390_libc_ifunc_expr (__redirect_strstr, strstr, +- (HAVE_STRSTR_Z13 && (hwcap & HWCAP_S390_VX)) ++ (HAVE_STRSTR_ARCH13 && (hwcap & HWCAP_S390_VXRS_EXT2)) ++ ? STRSTR_ARCH13 ++ : (HAVE_STRSTR_Z13 && (hwcap & HWCAP_S390_VX)) + ? STRSTR_Z13 + : STRSTR_DEFAULT + ) diff --git a/glibc-rh1659438-62.patch b/glibc-rh1659438-62.patch new file mode 100755 index 0000000..9d430c0 --- /dev/null +++ b/glibc-rh1659438-62.patch @@ -0,0 +1,318 @@ +commit 421749d693c4147017bc55f5ac3227c3a6e4bf31 +Author: Stefan Liebler +Date: Fri Mar 22 11:14:09 2019 +0100 + + S390: Add arch13 memmem ifunc variant. + + This patch introduces the new arch13 ifunc variant for memmem. + For needles longer than 9 bytes it is relying on the common-code + implementation. For shorter needles it is using the new vstrs instruction + which is able to search a substring within a vector register. + + ChangeLog: + + * sysdeps/s390/Makefile (sysdep_routines): Add memmem-arch13. + * sysdeps/s390/ifunc-memmem.h (HAVE_MEMMEM_ARCH13, MEMMEM_ARCH13, + MEMMEM_Z13_ONLY_USED_AS_FALLBACK, HAVE_MEMMEM_IFUNC_AND_ARCH13_SUPPORT): + New defines. + * sysdeps/s390/memmem-arch13.S: New file. + * sysdeps/s390/memmem-vx.c: Omit GI symbol for z13 memmem ifunc variant + if it is only used as fallback. + * sysdeps/s390/memmem.c (memmem): Add arch13 variant in ifunc selector. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Add ifunc variant for arch13 memmem. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 7287b1833da9500f..8bc82e523f9049db 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -36,7 +36,7 @@ sysdep_routines += bzero memset memset-z900 \ + mempcpy memcpy memcpy-z900 \ + memmove memmove-c \ + strstr strstr-arch13 strstr-vx strstr-c \ +- memmem memmem-vx memmem-c \ ++ memmem memmem-arch13 memmem-vx memmem-c \ + strlen strlen-vx strlen-c \ + strnlen strnlen-vx strnlen-c \ + strcpy strcpy-vx strcpy-z900 \ +diff --git a/sysdeps/s390/ifunc-memmem.h b/sysdeps/s390/ifunc-memmem.h +index 0f860d8d40080acf..48079b22b070f381 100644 +--- a/sysdeps/s390/ifunc-memmem.h ++++ b/sysdeps/s390/ifunc-memmem.h +@@ -17,7 +17,7 @@ + . */ + + #if defined USE_MULTIARCH && IS_IN (libc) \ +- && ! defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++ && ! defined HAVE_S390_MIN_ARCH13_ZARCH_ASM_SUPPORT + # define HAVE_MEMMEM_IFUNC 1 + #else + # define HAVE_MEMMEM_IFUNC 0 +@@ -29,14 +29,32 @@ + # define HAVE_MEMMEM_IFUNC_AND_VX_SUPPORT 0 + #endif + +-#if defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT ++#ifdef HAVE_S390_ARCH13_ASM_SUPPORT ++# define HAVE_MEMMEM_IFUNC_AND_ARCH13_SUPPORT HAVE_MEMMEM_IFUNC ++#else ++# define HAVE_MEMMEM_IFUNC_AND_ARCH13_SUPPORT 0 ++#endif ++ ++#if defined HAVE_S390_MIN_ARCH13_ZARCH_ASM_SUPPORT ++# define MEMMEM_DEFAULT MEMMEM_ARCH13 ++# define HAVE_MEMMEM_C 0 ++# define HAVE_MEMMEM_Z13 1 ++# define MEMMEM_Z13_ONLY_USED_AS_FALLBACK 1 ++# define HAVE_MEMMEM_ARCH13 1 ++#elif defined HAVE_S390_MIN_Z13_ZARCH_ASM_SUPPORT + # define MEMMEM_DEFAULT MEMMEM_Z13 + # define HAVE_MEMMEM_C 0 + # define HAVE_MEMMEM_Z13 1 ++# define HAVE_MEMMEM_ARCH13 HAVE_MEMMEM_IFUNC_AND_ARCH13_SUPPORT + #else + # define MEMMEM_DEFAULT MEMMEM_C + # define HAVE_MEMMEM_C 1 + # define HAVE_MEMMEM_Z13 HAVE_MEMMEM_IFUNC_AND_VX_SUPPORT ++# define HAVE_MEMMEM_ARCH13 HAVE_MEMMEM_IFUNC_AND_ARCH13_SUPPORT ++#endif ++ ++#ifndef MEMMEM_Z13_ONLY_USED_AS_FALLBACK ++# define MEMMEM_Z13_ONLY_USED_AS_FALLBACK 0 + #endif + + #if HAVE_MEMMEM_C +@@ -50,3 +68,9 @@ + #else + # define MEMMEM_Z13 NULL + #endif ++ ++#if HAVE_MEMMEM_ARCH13 ++# define MEMMEM_ARCH13 __memmem_arch13 ++#else ++# define MEMMEM_ARCH13 NULL ++#endif +diff --git a/sysdeps/s390/memmem-arch13.S b/sysdeps/s390/memmem-arch13.S +new file mode 100644 +index 0000000000000000..b59d60acf0f6aaa0 +--- /dev/null ++++ b/sysdeps/s390/memmem-arch13.S +@@ -0,0 +1,161 @@ ++/* Vector optimized 32/64 bit S/390 version of memmem. ++ 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 ++ . */ ++ ++#include ++#if HAVE_MEMMEM_ARCH13 ++# include "sysdep.h" ++# include "asm-syntax.h" ++ .text ++ ++/* void *memmem(const void *haystack=r2, size_t haystacklen=r3, ++ const void *needle=r4, size_t needlelen=r5); ++ Locate a substring. */ ++ENTRY(MEMMEM_ARCH13) ++ .machine "arch13" ++ .machinemode "zarch_nohighgprs" ++# if ! defined __s390x__ ++ llgfr %r3,%r3 ++ llgfr %r5,%r5 ++ llgfr %r4,%r4 ++ llgfr %r2,%r2 ++# endif /* ! defined __s390x__ */ ++ clgrjl %r3,%r5,.Lend_no_match /* Haystack < needle? */ ++ ++ /* Jump to fallback if needle > 9. See also strstr-arch13.S. */ ++# if ! HAVE_MEMMEM_Z13 ++# error The arch13 variant of memmem needs the z13 variant of memmem! ++# endif ++ clgfi %r5,9 ++ jh MEMMEM_Z13 ++ ++ aghik %r0,%r5,-1 /* vll needs highest index. */ ++ bc 4,0(%r14) /* cc==1: return if needle-len == 0. */ ++ vll %v18,%r0,0(%r4) /* Load needle. */ ++ vlvgb %v19,%r5,7 /* v19[7] contains length of needle. */ ++ ++ clgijh %r3,16,.Lhaystack_larger_16 ++.Lhaystack_smaller_16_on_bb: ++ aghik %r0,%r3,-1 /* vll needs highest index. */ ++ vll %v16,%r0,0(%r2) /* Load haystack. */ ++.Lhaystack_smaller_16: ++ sgr %r3,%r5 /* r3 = largest valid match-index. */ ++ jl .Lend_no_match /* Haystack-len < needle-len? */ ++ vstrs %v20,%v16,%v18,%v19,0,0 ++ /* Vector string search without zero search where v20 will contain ++ the index of a partial/full match or 16 (index is named k). ++ cc=0 (no match; k=16): .Lend_no_match ++ cc=1 (only available with zero-search): Ignore ++ cc=2 (full match; k<16): Needle found, but could be beyond haystack! ++ cc=3 (partial match; k<16): Always at end of v16 and thus beyond! */ ++ brc 9,.Lend_no_match /* Jump away if cc == 0 || cc == 3. */ ++ vlgvb %r1,%v20,7 ++ /* Verify that the full-match (cc=2) is valid! */ ++ clgrjh %r1,%r3,.Lend_no_match /* Jump away if match is beyond. */ ++ la %r2,0(%r1,%r2) ++ br %r14 ++.Lend_no_match: ++ lghi %r2,0 ++ br %r14 ++ ++.Lhaystack_larger_16: ++ vl %v16,0(%r2) ++ lghi %r1,17 ++ lay %r4,-16(%r3,%r2) /* Boundary for loading with vl. */ ++ lay %r0,-64(%r3,%r2) /* Boundary for loading with 4xvl. */ ++ /* See also strstr-arch13.S: ++ min-skip-partial-match-index = (16 - n_len) + 1 */ ++ sgr %r1,%r5 ++ clgfi %r3,64 /* Set Boundary to zero ... */ ++ la %r3,0(%r3,%r2) ++ locghil %r0,0 /* ... if haystack < 64bytes. */ ++ jh .Lloop64 ++.Lloop: ++ la %r2,16(%r2) ++ /* Vector string search with zero search. cc=0 => no match. */ ++ vstrs %v20,%v16,%v18,%v19,0,0 ++ jne .Lloop_vstrs_nonzero_cc ++ clgrjh %r2,%r4,.Lhaystack_too_small ++.Lloop16: ++ vl %v16,0(%r2) ++ la %r2,16(%r2) ++ vstrs %v20,%v16,%v18,%v19,0,0 ++ jne .Lloop_vstrs_nonzero_cc ++ clgrjle %r2,%r4,.Lloop16 ++.Lhaystack_too_small: ++ sgr %r3,%r2 /* r3 = (haystack + len) - curr_pos */ ++ je .Lend_no_match /* Remaining haystack is empty. */ ++ lcbb %r0,0(%r2),6 ++ jo .Lhaystack_smaller_16_on_bb ++ vl %v16,0(%r2) /* Load haystack. */ ++ j .Lhaystack_smaller_16 ++ ++.Lend_match_found: ++ vlgvb %r4,%v20,7 ++ sgr %r2,%r1 ++ la %r2,0(%r4,%r2) ++ br %r14 ++ ++.Lloop_vstrs_nonzero_cc32: ++ la %r2,16(%r2) ++.Lloop_vstrs_nonzero_cc16: ++ la %r2,16(%r2) ++.Lloop_vstrs_nonzero_cc0: ++ la %r2,16(%r2) ++.Lloop_vstrs_nonzero_cc: ++ lay %r2,-16(%r1,%r2) /* Compute next load address. */ ++ jh .Lend_match_found /* cc == 2 (full match) */ ++ clgrjh %r2,%r4,.Lhaystack_too_small ++ vl %v16,0(%r2) ++.Lloop_vstrs_nonzero_cc_loop: ++ la %r2,0(%r1,%r2) ++ vstrs %v20,%v16,%v18,%v19,0,0 ++ jh .Lend_match_found ++ clgrjh %r2,%r4,.Lhaystack_too_small ++ vl %v16,0(%r2) /* Next part of haystack. */ ++ jo .Lloop_vstrs_nonzero_cc_loop ++ /* Case: no-match. */ ++ clgrjh %r2,%r0,.Lloop /* Jump away if haystack has less than 64b. */ ++.Lloop64: ++ vstrs %v20,%v16,%v18,%v19,0,0 ++ jne .Lloop_vstrs_nonzero_cc0 ++ vl %v16,16(%r2) /* Next part of haystack. */ ++ vstrs %v20,%v16,%v18,%v19,0,0 ++ jne .Lloop_vstrs_nonzero_cc16 ++ vl %v16,32(%r2) /* Next part of haystack. */ ++ vstrs %v20,%v16,%v18,%v19,0,0 ++ jne .Lloop_vstrs_nonzero_cc32 ++ vl %v16,48(%r2) /* Next part of haystack. */ ++ la %r2,64(%r2) ++ vstrs %v20,%v16,%v18,%v19,0,0 ++ jne .Lloop_vstrs_nonzero_cc ++ clgrjh %r2,%r4,.Lhaystack_too_small ++ vl %v16,0(%r2) /* Next part of haystack. */ ++ clgrjle %r2,%r0,.Lloop64 ++ j .Lloop ++END(MEMMEM_ARCH13) ++ ++# if ! HAVE_MEMMEM_IFUNC ++strong_alias (MEMMEM_ARCH13, __memmem) ++weak_alias (__memmem, memmem) ++# endif ++ ++# if MEMMEM_Z13_ONLY_USED_AS_FALLBACK && defined SHARED && IS_IN (libc) ++weak_alias (MEMMEM_ARCH13, __GI_memmem) ++strong_alias (MEMMEM_ARCH13, __GI___memmem) ++# endif ++#endif +diff --git a/sysdeps/s390/memmem-vx.c b/sysdeps/s390/memmem-vx.c +index af6e200e4e0af1a5..e5608be77f05f2a9 100644 +--- a/sysdeps/s390/memmem-vx.c ++++ b/sysdeps/s390/memmem-vx.c +@@ -20,7 +20,7 @@ + + #if HAVE_MEMMEM_Z13 + # include +-# if HAVE_MEMMEM_IFUNC ++# if HAVE_MEMMEM_IFUNC || MEMMEM_Z13_ONLY_USED_AS_FALLBACK + + # ifndef _LIBC + # define memmem MEMMEM_Z13 +@@ -32,7 +32,7 @@ + # undef libc_hidden_def + # undef libc_hidden_weak + +-# if HAVE_MEMMEM_C ++# if HAVE_MEMMEM_C || MEMMEM_Z13_ONLY_USED_AS_FALLBACK + # define libc_hidden_def(name) + # define libc_hidden_weak(name) + # else +diff --git a/sysdeps/s390/memmem.c b/sysdeps/s390/memmem.c +index 8c50b3f403eb8d1f..28871cd4b24868cc 100644 +--- a/sysdeps/s390/memmem.c ++++ b/sysdeps/s390/memmem.c +@@ -34,8 +34,14 @@ extern __typeof (__redirect_memmem) MEMMEM_C attribute_hidden; + extern __typeof (__redirect_memmem) MEMMEM_Z13 attribute_hidden; + # endif + ++# if HAVE_MEMMEM_ARCH13 ++extern __typeof (__redirect_memmem) MEMMEM_ARCH13 attribute_hidden; ++# endif ++ + s390_libc_ifunc_expr (__redirect_memmem, __memmem, +- (HAVE_MEMMEM_Z13 && (hwcap & HWCAP_S390_VX)) ++ (HAVE_MEMMEM_ARCH13 && (hwcap & HWCAP_S390_VXRS_EXT2)) ++ ? MEMMEM_ARCH13 ++ : (HAVE_MEMMEM_Z13 && (hwcap & HWCAP_S390_VX)) + ? MEMMEM_Z13 + : MEMMEM_DEFAULT + ) +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 67a6a9c94afccd48..787d40688f4110ff 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -202,6 +202,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + #if HAVE_MEMMEM_IFUNC + IFUNC_IMPL (i, name, memmem, ++# if HAVE_MEMMEM_ARCH13 ++ IFUNC_IMPL_ADD (array, i, memmem, ++ dl_hwcap & HWCAP_S390_VXRS_EXT2, MEMMEM_ARCH13) ++# endif + # if HAVE_MEMMEM_Z13 + IFUNC_IMPL_ADD (array, i, memmem, + dl_hwcap & HWCAP_S390_VX, MEMMEM_Z13) diff --git a/glibc-rh1659438-7.patch b/glibc-rh1659438-7.patch new file mode 100755 index 0000000..bad570b --- /dev/null +++ b/glibc-rh1659438-7.patch @@ -0,0 +1,503 @@ +commit b7e024a838452a85870256d8f1ab946dc8f931cd +Author: Stefan Liebler +Date: Tue Dec 18 13:57:05 2018 +0100 + + S390: Refactor memcmp ifunc handling. + + This patch moves all ifunc variants for memcmp + to sysdeps/s390/memcmp-z900.S. The configure-check/preprocessor logic + in sysdeps/s390/ifunc-memcmp.h decides if ifunc is needed at all + and which ifunc variants should be available. + E.g. if the compiler/assembler already supports z196 by default, + the older ifunc variants are not included. + If we only need the newest ifunc variant, + then we can skip ifunc at all. + + Therefore the ifunc-resolvers and __libc_ifunc_impl_list are adjusted + in order to handle only the available ifunc variants. + + ChangeLog: + + * sysdeps/s390/ifunc-memcmp.h: New File. + * sysdeps/s390/memcmp.S: Move to ... + * sysdeps/s390/memcmp-z900.S ... here. + Move implementations from memcmp-s390x.s to here. + * sysdeps/s390/multiarch/memcmp-s390x.S: Delete File. + * sysdeps/s390/multiarch/Makefile (sysdep_routines): + Remove memcmp variants. + * sysdeps/s390/Makefile (sysdep_routines): + Add memcmp variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Adjust ifunc variants for + memcmp. + * sysdeps/s390/multiarch/memcmp.c: Move ifunc resolver + to ... + * sysdeps/s390/memcmp.c: ... here. + Adjust ifunc variants for memcmp. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index e40e5bd982e54d89..c59cbdc25aad408a 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -31,5 +31,6 @@ sysdeps-gconv-modules = ../sysdeps/s390/gconv-modules + endif + + ifeq ($(subdir),string) +-sysdep_routines += bzero memset memset-z900 ++sysdep_routines += bzero memset memset-z900 \ ++ memcmp memcmp-z900 + endif +diff --git a/sysdeps/s390/ifunc-memcmp.h b/sysdeps/s390/ifunc-memcmp.h +new file mode 100644 +index 0000000000000000..536ac455d177c027 +--- /dev/null ++++ b/sysdeps/s390/ifunc-memcmp.h +@@ -0,0 +1,59 @@ ++/* memcmp variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# define HAVE_MEMCMP_IFUNC 1 ++#else ++# define HAVE_MEMCMP_IFUNC 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# define MEMCMP_DEFAULT MEMCMP_Z196 ++# define HAVE_MEMCMP_Z900_G5 0 ++# define HAVE_MEMCMP_Z10 0 ++# define HAVE_MEMCMP_Z196 1 ++#elif defined HAVE_S390_MIN_Z10_ZARCH_ASM_SUPPORT ++# define MEMCMP_DEFAULT MEMCMP_Z10 ++# define HAVE_MEMCMP_Z900_G5 0 ++# define HAVE_MEMCMP_Z10 1 ++# define HAVE_MEMCMP_Z196 HAVE_MEMCMP_IFUNC ++#else ++# define MEMCMP_DEFAULT MEMCMP_Z900_G5 ++# define HAVE_MEMCMP_Z900_G5 1 ++# define HAVE_MEMCMP_Z10 HAVE_MEMCMP_IFUNC ++# define HAVE_MEMCMP_Z196 HAVE_MEMCMP_IFUNC ++#endif ++ ++#if HAVE_MEMCMP_Z900_G5 ++# define MEMCMP_Z900_G5 __memcmp_default ++#else ++# define MEMCMP_Z900_G5 NULL ++#endif ++ ++#if HAVE_MEMCMP_Z10 ++# define MEMCMP_Z10 __memcmp_z10 ++#else ++# define MEMCMP_Z10 NULL ++#endif ++ ++#if HAVE_MEMCMP_Z196 ++# define MEMCMP_Z196 __memcmp_z196 ++#else ++# define MEMCMP_Z196 NULL ++#endif +diff --git a/sysdeps/s390/multiarch/memcmp-s390x.S b/sysdeps/s390/memcmp-z900.S +similarity index 54% +rename from sysdeps/s390/multiarch/memcmp-s390x.S +rename to sysdeps/s390/memcmp-z900.S +index 6321737acec821ec..c3b3677ba78264ee 100644 +--- a/sysdeps/s390/multiarch/memcmp-s390x.S ++++ b/sysdeps/s390/memcmp-z900.S +@@ -1,4 +1,4 @@ +-/* CPU specific memcmp implementations. 31/64 bit S/390 version. ++/* memcmp - compare two memory blocks. 31/64 bit S/390 version. + Copyright (C) 2012-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + +@@ -17,8 +17,9 @@ + . */ + + +-#include "sysdep.h" ++#include + #include "asm-syntax.h" ++#include + + /* INPUT PARAMETERS + %r2 = address of first memory area +@@ -27,46 +28,67 @@ + + .text + +-#if IS_IN (libc) +- +-ENTRY(__memcmp_z196) +- .machine "z196" +- .machinemode "zarch_nohighgprs" +-# if !defined __s390x__ +- llgfr %r4,%r4 +-# endif /* !defined __s390x__ */ +- ltgr %r4,%r4 +- je .L_Z196_4 +- aghi %r4,-1 ++#if HAVE_MEMCMP_Z900_G5 ++# if defined __s390x__ ++# define LTGR ltgr ++# define AGHI aghi ++# define BRCTG brctg ++# else ++# define LTGR ltr ++# define AGHI ahi ++# define BRCTG brct ++# endif /* ! defined __s390x__ */ ++ENTRY(MEMCMP_Z900_G5) ++# if defined __s390x__ ++ .machine "z900" ++# else ++ .machine "g5" ++ basr %r5,0 ++.L_Z900_G5_16: ++# define Z900_G5_EX_D .L_Z900_G5_15-.L_Z900_G5_16 ++# endif /* ! defined __s390x__ */ ++ LTGR %r4,%r4 ++ je .L_Z900_G5_4 ++ AGHI %r4,-1 ++# if defined __s390x__ + srlg %r1,%r4,8 +- ltgr %r1,%r1 +- jne .L_Z196_2 +-.L_Z196_3: +- exrl %r4,.L_Z196_14 +-.L_Z196_4: ++ larl %r5,.L_Z900_G5_15 ++# define Z900_G5_EX_D 0 ++# else ++ lr %r1,%r4 ++ srl %r1,8 ++# endif /* ! defined __s390x__ */ ++ LTGR %r1,%r1 ++ jne .L_Z900_G5_12 ++.L_Z900_G5_3: ++ ex %r4,Z900_G5_EX_D(%r5) ++.L_Z900_G5_4: + ipm %r2 ++# if defined __s390x__ + sllg %r2,%r2,34 + srag %r2,%r2,62 ++# else ++ sll %r2,2 ++ sra %r2,30 ++# endif /* ! defined __s390x__ */ + br %r14 +-.L_Z196_17: ++.L_Z900_G5_12: ++ clc 0(256,%r3),0(%r2) ++ jne .L_Z900_G5_4 + la %r3,256(%r3) + la %r2,256(%r2) +- aghi %r1,-1 +- je .L_Z196_3 +-.L_Z196_2: +- pfd 1,512(%r3) +- pfd 1,512(%r2) +- clc 0(256,%r3),0(%r2) +- je .L_Z196_17 +- ipm %r2 +- sllg %r2,%r2,34 +- srag %r2,%r2,62 +- br %r14 +-.L_Z196_14: ++ BRCTG %r1,.L_Z900_G5_12 ++ j .L_Z900_G5_3 ++.L_Z900_G5_15: + clc 0(1,%r3),0(%r2) +-END(__memcmp_z196) ++END(MEMCMP_Z900_G5) ++# undef LTGR ++# undef AGHI ++# undef BRCTG ++#endif /* HAVE_MEMCMP_Z900_G5 */ + +-ENTRY(__memcmp_z10) ++#if HAVE_MEMCMP_Z10 ++ENTRY(MEMCMP_Z10) + .machine "z10" + .machinemode "zarch_nohighgprs" + # if !defined __s390x__ +@@ -95,18 +117,57 @@ ENTRY(__memcmp_z10) + j .L_Z10_3 + .L_Z10_15: + clc 0(1,%r3),0(%r2) +-END(__memcmp_z10) ++END(MEMCMP_Z10) ++#endif /* HAVE_MEMCMP_Z10 */ + +-#endif /* IS_IN (libc) */ ++#if HAVE_MEMCMP_Z196 ++ENTRY(MEMCMP_Z196) ++ .machine "z196" ++ .machinemode "zarch_nohighgprs" ++# if !defined __s390x__ ++ llgfr %r4,%r4 ++# endif /* !defined __s390x__ */ ++ ltgr %r4,%r4 ++ je .L_Z196_4 ++ aghi %r4,-1 ++ srlg %r1,%r4,8 ++ ltgr %r1,%r1 ++ jne .L_Z196_2 ++.L_Z196_3: ++ exrl %r4,.L_Z196_14 ++.L_Z196_4: ++ ipm %r2 ++ sllg %r2,%r2,34 ++ srag %r2,%r2,62 ++ br %r14 ++.L_Z196_17: ++ la %r3,256(%r3) ++ la %r2,256(%r2) ++ aghi %r1,-1 ++ je .L_Z196_3 ++.L_Z196_2: ++ pfd 1,512(%r3) ++ pfd 1,512(%r2) ++ clc 0(256,%r3),0(%r2) ++ je .L_Z196_17 ++ ipm %r2 ++ sllg %r2,%r2,34 ++ srag %r2,%r2,62 ++ br %r14 ++.L_Z196_14: ++ clc 0(1,%r3),0(%r2) ++END(MEMCMP_Z196) ++#endif /* HAVE_MEMCMP_Z196 */ + +-#include "../memcmp.S" ++#if ! HAVE_MEMCMP_IFUNC ++/* If we don't use ifunc, define an alias for memcmp here. ++ Otherwise see sysdeps/s390/memcmp.c. */ ++strong_alias (MEMCMP_DEFAULT, memcmp) ++weak_alias (memcmp, bcmp) ++#endif + +-#if !IS_IN (libc) +-.globl memcmp +-.set memcmp,__memcmp_default +-.weak bcmp +-.set bcmp,__memcmp_default +-#elif defined SHARED && IS_IN (libc) +-.globl __GI_memcmp +-.set __GI_memcmp,__memcmp_default ++#if defined SHARED && IS_IN (libc) ++/* Defines the internal symbols. ++ Compare to libc_hidden_builtin_def (memcmp) in string/memcmp.c. */ ++strong_alias (MEMCMP_DEFAULT, __GI_memcmp) + #endif +diff --git a/sysdeps/s390/memcmp.S b/sysdeps/s390/memcmp.S +deleted file mode 100644 +index 751293a99e34f530..0000000000000000 +--- a/sysdeps/s390/memcmp.S ++++ /dev/null +@@ -1,96 +0,0 @@ +-/* memcmp - compare two memory blocks. 31/64 bit S/390 version. +- Copyright (C) 2012-2018 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 +- . */ +- +- +-#include +-#include "asm-syntax.h" +- +-/* INPUT PARAMETERS +- %r2 = address of first memory area +- %r3 = address of second memory area +- %r4 = number of bytes to compare. */ +- +- .text +-#if defined __s390x__ +-# define LTGR ltgr +-# define AGHI aghi +-# define BRCTG brctg +-#else +-# define LTGR ltr +-# define AGHI ahi +-# define BRCTG brct +-#endif /* ! defined __s390x__ */ +- +-#ifdef USE_MULTIARCH +-ENTRY(__memcmp_default) +-#else +-ENTRY(memcmp) +-#endif +-#if defined __s390x__ +- .machine "z900" +-#else +- .machine "g5" +- basr %r5,0 +-.L_Z900_G5_16: +-# define Z900_G5_EX_D .L_Z900_G5_15-.L_Z900_G5_16 +-#endif /* ! defined __s390x__ */ +- LTGR %r4,%r4 +- je .L_Z900_G5_4 +- AGHI %r4,-1 +-#if defined __s390x__ +- srlg %r1,%r4,8 +- larl %r5,.L_Z900_G5_15 +-# define Z900_G5_EX_D 0 +-#else +- lr %r1,%r4 +- srl %r1,8 +-#endif /* ! defined __s390x__ */ +- LTGR %r1,%r1 +- jne .L_Z900_G5_12 +-.L_Z900_G5_3: +- ex %r4,Z900_G5_EX_D(%r5) +-.L_Z900_G5_4: +- ipm %r2 +-#if defined __s390x__ +- sllg %r2,%r2,34 +- srag %r2,%r2,62 +-#else +- sll %r2,2 +- sra %r2,30 +-#endif /* ! defined __s390x__ */ +- br %r14 +-.L_Z900_G5_12: +- clc 0(256,%r3),0(%r2) +- jne .L_Z900_G5_4 +- la %r3,256(%r3) +- la %r2,256(%r2) +- BRCTG %r1,.L_Z900_G5_12 +- j .L_Z900_G5_3 +-.L_Z900_G5_15: +- clc 0(1,%r3),0(%r2) +-#ifdef USE_MULTIARCH +-END(__memcmp_default) +-#else +-END(memcmp) +-libc_hidden_builtin_def (memcmp) +-weak_alias (memcmp, bcmp) +-#endif +- +-#undef LTGR +-#undef AGHI +-#undef BRCTG +diff --git a/sysdeps/s390/multiarch/memcmp.c b/sysdeps/s390/memcmp.c +similarity index 60% +rename from sysdeps/s390/multiarch/memcmp.c +rename to sysdeps/s390/memcmp.c +index 1e6f31806e172d7d..952ff6af7364fd92 100644 +--- a/sysdeps/s390/multiarch/memcmp.c ++++ b/sysdeps/s390/memcmp.c +@@ -16,12 +16,34 @@ + License along with the GNU C Library; if not, see + . */ + +-#if IS_IN (libc) ++#include ++#if HAVE_MEMCMP_IFUNC + # define memcmp __redirect_memcmp + # include + # undef memcmp + # include + +-s390_libc_ifunc (__redirect_memcmp, __memcmp, memcmp) ++# if HAVE_MEMCMP_Z900_G5 ++extern __typeof (__redirect_memcmp) MEMCMP_Z900_G5 attribute_hidden; ++# endif ++ ++# if HAVE_MEMCMP_Z10 ++extern __typeof (__redirect_memcmp) MEMCMP_Z10 attribute_hidden; ++# endif ++ ++# if HAVE_MEMCMP_Z196 ++extern __typeof (__redirect_memcmp) MEMCMP_Z196 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect_memcmp, memcmp, ++ ({ ++ s390_libc_ifunc_init (); ++ (HAVE_MEMCMP_Z196 && S390_IS_Z196 (stfle_bits)) ++ ? MEMCMP_Z196 ++ : (HAVE_MEMCMP_Z10 && S390_IS_Z10 (stfle_bits)) ++ ? MEMCMP_Z10 ++ : MEMCMP_DEFAULT; ++ }) ++ ) + weak_alias (memcmp, bcmp); + #endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 53dd8654d73677db..c893ebc5659fd4ae 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -19,8 +19,7 @@ sysdep_routines += strlen strlen-vx strlen-c \ + rawmemchr rawmemchr-vx rawmemchr-c \ + memccpy memccpy-vx memccpy-c \ + memrchr memrchr-vx memrchr-c \ +- mempcpy \ +- memcmp memcmp-s390x ++ mempcpy + endif + + ifeq ($(subdir),wcsmbs) +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 253f36045b57cc3c..2e57d01abc21522e 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -78,12 +79,21 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_MEMSET_IFUNC */ + ++#if HAVE_MEMCMP_IFUNC + IFUNC_IMPL (i, name, memcmp, ++# if HAVE_MEMCMP_Z196 + IFUNC_IMPL_ADD (array, i, memcmp, +- S390_IS_Z196 (stfle_bits), __memcmp_z196) ++ S390_IS_Z196 (stfle_bits), MEMCMP_Z196) ++# endif ++# if HAVE_MEMCMP_Z10 + IFUNC_IMPL_ADD (array, i, memcmp, +- S390_IS_Z10 (stfle_bits), __memcmp_z10) +- IFUNC_IMPL_ADD (array, i, memcmp, 1, __memcmp_default)) ++ S390_IS_Z10 (stfle_bits), MEMCMP_Z10) ++# endif ++# if HAVE_MEMCMP_Z900_G5 ++ IFUNC_IMPL_ADD (array, i, memcmp, 1, MEMCMP_Z900_G5) ++# endif ++ ) ++#endif /* HAVE_MEMCMP_IFUNC */ + + #ifdef SHARED + diff --git a/glibc-rh1659438-8.patch b/glibc-rh1659438-8.patch new file mode 100755 index 0000000..464f5d2 --- /dev/null +++ b/glibc-rh1659438-8.patch @@ -0,0 +1,538 @@ +commit df3eb8de31a530f285f54f3c41cd7b636816c062 +Author: Stefan Liebler +Date: Tue Dec 18 13:57:06 2018 +0100 + + S390: Unify 31/64bit memcpy. + + The implementation of memcpy/mempcpy for s390-32 (31bit) + and s390-64 (64bit) is nearly the same. + This patch unifies it for maintability reasons. + + __mem[p]cpy_z10 and __mem[p]cpy_z196 differs between 31 and 64bit: + -31bit needs .machinemode "zarch_nohighgprs" and llgfr %r4,%r4 + -lr vs lgr; lgr can be also used on 31bit as this ifunc variant + is only called if we are on a zarch machine. + + __mem[p]cpy_default differs between 31 and 64bit: + -Some 31bit vs 64bit instructions (e.g. ltr vs ltgr. + Solved with 31/64 specific instruction macros). + -The address of mvc instruction is setup in different ways + (larl vs bras). Solved with #if defined __s390x__. + + __memcpy_mvcle differs between 31 and 64bit: + -lr vs lgr; ahi vs aghi; + Solved with 31/64bit specific instruction macros. + + Otherwise 31/64bit implementation has the same structure of the code. + + ChangeLog: + + * sysdeps/s390/s390-64/memcpy.S: Move to ... + * sysdeps/s390/memcpy.S: ... here. + Adjust to be usable for 31/64bit. + * sysdeps/s390/s390-32/memcpy.S: Delete File. + * sysdeps/s390/multiarch/Makefile (sysdep_routines): Add memcpy. + * sysdeps/s390/s390-32/multiarch/Makefile: Delete file. + * sysdeps/s390/s390-64/multiarch/Makefile: Likewise. + * sysdeps/s390/s390-64/multiarch/memcpy-s390x.S: Move to ... + * sysdeps/s390/multiarch/memcpy-s390x.S: ... here. + Adjust to be usable for 31/64bit. + * sysdeps/s390/s390-32/multiarch/memcpy-s390.S: Delete File. + * sysdeps/s390/s390-64/multiarch/memcpy.c: Move to ... + * sysdeps/s390/multiarch/memcpy.c: ... here. + * sysdeps/s390/s390-32/multiarch/memcpy.c: Delete File. + +diff --git a/sysdeps/s390/s390-64/memcpy.S b/sysdeps/s390/memcpy.S +similarity index 52% +rename from sysdeps/s390/s390-64/memcpy.S +rename to sysdeps/s390/memcpy.S +index 2e5490df23d64325..2a6c6b750377c7bb 100644 +--- a/sysdeps/s390/s390-64/memcpy.S ++++ b/sysdeps/s390/memcpy.S +@@ -1,4 +1,4 @@ +-/* memcpy - copy a block from source to destination. 64 bit S/390 version. ++/* memcpy - copy a block from source to destination. 31/64 bit S/390 version. + Copyright (C) 2012-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + +@@ -25,13 +25,31 @@ + %r3 = address of source memory area + %r4 = number of bytes to copy. */ + +- + .text ++ ++#if defined __s390x__ ++# define LTGR ltgr ++# define CGHI cghi ++# define LGR lgr ++# define AGHI aghi ++# define BRCTG brctg ++#else ++# define LTGR ltr ++# define CGHI chi ++# define LGR lr ++# define AGHI ahi ++# define BRCTG brct ++#endif /* ! defined __s390x__ */ ++ + ENTRY(__mempcpy) ++#if defined __s390x__ + .machine "z900" +- lgr %r1,%r2 # Use as dest ++#else ++ .machine "g5" ++#endif /* ! defined __s390x__ */ ++ LGR %r1,%r2 # Use as dest + la %r2,0(%r4,%r2) # Return dest + n +- j .L_Z900_start ++ j .L_Z900_G5_start + END(__mempcpy) + #ifndef USE_MULTIARCH + libc_hidden_def (__mempcpy) +@@ -40,30 +58,46 @@ libc_hidden_builtin_def (mempcpy) + #endif + + ENTRY(memcpy) ++#if defined __s390x__ + .machine "z900" +- lgr %r1,%r2 # r1: Use as dest ; r2: Return dest +-.L_Z900_start: +- ltgr %r4,%r4 +- je .L_Z900_4 +- aghi %r4,-1 +- srlg %r5,%r4,8 +- ltgr %r5,%r5 +- jne .L_Z900_13 +-.L_Z900_3: +- larl %r5,.L_Z900_15 +- ex %r4,0(%r5) +-.L_Z900_4: ++#else ++ .machine "g5" ++#endif /* ! defined __s390x__ */ ++ LGR %r1,%r2 # r1: Use as dest ; r2: Return dest ++.L_Z900_G5_start: ++ LTGR %r4,%r4 ++ je .L_Z900_G5_4 ++ AGHI %r4,-1 ++#if defined __s390x__ ++ srlg %r5,%r4,8 ++#else ++ lr %r5,%r4 ++ srl %r5,8 ++#endif /* ! defined __s390x__ */ ++ LTGR %r5,%r5 ++ jne .L_Z900_G5_13 ++.L_Z900_G5_3: ++#if defined __s390x__ ++ larl %r5,.L_Z900_G5_15 ++# define Z900_G5_EX_D 0 ++#else ++ basr %r5,0 ++.L_Z900_G5_14: ++# define Z900_G5_EX_D .L_Z900_G5_15-.L_Z900_G5_14 ++#endif /* ! defined __s390x__ */ ++ ex %r4,Z900_G5_EX_D(%r5) ++.L_Z900_G5_4: + br %r14 +-.L_Z900_13: +- cghi %r5,4096 # Switch to mvcle for copies >1MB ++.L_Z900_G5_13: ++ CGHI %r5,4096 # Switch to mvcle for copies >1MB + jh __memcpy_mvcle +-.L_Z900_12: ++.L_Z900_G5_12: + mvc 0(256,%r1),0(%r3) + la %r1,256(%r1) + la %r3,256(%r3) +- brctg %r5,.L_Z900_12 +- j .L_Z900_3 +-.L_Z900_15: ++ BRCTG %r5,.L_Z900_G5_12 ++ j .L_Z900_G5_3 ++.L_Z900_G5_15: + mvc 0(1,%r1),0(%r3) + END(memcpy) + #ifndef USE_MULTIARCH +@@ -74,15 +108,21 @@ ENTRY(__memcpy_mvcle) + # Using as standalone function will result in unexpected + # results since the length field is incremented by 1 in order to + # compensate the changes already done in the functions above. +- lgr %r0,%r2 # backup return dest [ + n ] +- aghi %r4,1 # length + 1 +- lgr %r5,%r4 # source length +- lgr %r4,%r3 # source address +- lgr %r2,%r1 # destination address +- lgr %r3,%r5 # destination length = source length ++ LGR %r0,%r2 # backup return dest [ + n ] ++ AGHI %r4,1 # length + 1 ++ LGR %r5,%r4 # source length ++ LGR %r4,%r3 # source address ++ LGR %r2,%r1 # destination address ++ LGR %r3,%r5 # destination length = source length + .L_MVCLE_1: + mvcle %r2,%r4,0 # thats it, MVCLE is your friend + jo .L_MVCLE_1 +- lgr %r2,%r0 # return destination address ++ LGR %r2,%r0 # return destination address + br %r14 + END(__memcpy_mvcle) ++ ++#undef LTGR ++#undef CGHI ++#undef LGR ++#undef AGHI ++#undef BRCTG +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index c893ebc5659fd4ae..3cbd5fad69e355a5 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -19,7 +19,7 @@ sysdep_routines += strlen strlen-vx strlen-c \ + rawmemchr rawmemchr-vx rawmemchr-c \ + memccpy memccpy-vx memccpy-c \ + memrchr memrchr-vx memrchr-c \ +- mempcpy ++ mempcpy memcpy memcpy-s390x + endif + + ifeq ($(subdir),wcsmbs) +diff --git a/sysdeps/s390/s390-64/multiarch/memcpy-s390x.S b/sysdeps/s390/multiarch/memcpy-s390x.S +similarity index 89% +rename from sysdeps/s390/s390-64/multiarch/memcpy-s390x.S +rename to sysdeps/s390/multiarch/memcpy-s390x.S +index 6d60a70834c32120..b38caac72b8742e6 100644 +--- a/sysdeps/s390/s390-64/multiarch/memcpy-s390x.S ++++ b/sysdeps/s390/multiarch/memcpy-s390x.S +@@ -1,4 +1,4 @@ +-/* CPU specific memcpy implementations. 64 bit S/390 version. ++/* CPU specific memcpy implementations. 31/64 bit S/390 version. + Copyright (C) 2012-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + +@@ -31,6 +31,7 @@ + + ENTRY(____mempcpy_z196) + .machine "z196" ++ .machinemode "zarch_nohighgprs" + lgr %r1,%r2 # Use as dest + la %r2,0(%r4,%r2) # Return dest + n + j .L_Z196_start +@@ -38,8 +39,12 @@ END(____mempcpy_z196) + + ENTRY(__memcpy_z196) + .machine "z196" ++ .machinemode "zarch_nohighgprs" + lgr %r1,%r2 # r1: Use as dest ; r2: Return dest + .L_Z196_start: ++# if !defined __s390x__ ++ llgfr %r4,%r4 ++# endif /* !defined __s390x__ */ + ltgr %r4,%r4 + je .L_Z196_4 + aghi %r4,-1 +@@ -68,6 +73,7 @@ END(__memcpy_z196) + + ENTRY(____mempcpy_z10) + .machine "z10" ++ .machinemode "zarch_nohighgprs" + lgr %r1,%r2 # Use as dest + la %r2,0(%r4,%r2) # Return dest + n + j .L_Z10_start +@@ -75,8 +81,12 @@ END(____mempcpy_z10) + + ENTRY(__memcpy_z10) + .machine "z10" ++ .machinemode "zarch_nohighgprs" + lgr %r1,%r2 # r1: Use as dest ; r2: Return dest + .L_Z10_start: ++# if !defined __s390x__ ++ llgfr %r4,%r4 ++# endif /* !defined __s390x__ */ + cgije %r4,0,.L_Z10_4 + aghi %r4,-1 + srlg %r5,%r4,8 +diff --git a/sysdeps/s390/s390-32/multiarch/memcpy.c b/sysdeps/s390/multiarch/memcpy.c +similarity index 100% +rename from sysdeps/s390/s390-32/multiarch/memcpy.c +rename to sysdeps/s390/multiarch/memcpy.c +diff --git a/sysdeps/s390/s390-32/memcpy.S b/sysdeps/s390/s390-32/memcpy.S +deleted file mode 100644 +index 493cc18aba67d6ec..0000000000000000 +--- a/sysdeps/s390/s390-32/memcpy.S ++++ /dev/null +@@ -1,89 +0,0 @@ +-/* memcpy - copy a block from source to destination. S/390 version. +- Copyright (C) 2012-2018 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 +- . */ +- +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +-/* INPUT PARAMETERS +- %r2 = address of destination memory area +- %r3 = address of source memory area +- %r4 = number of bytes to copy. */ +- +- .text +-ENTRY(__mempcpy) +- .machine "g5" +- lr %r1,%r2 # Use as dest +- la %r2,0(%r4,%r2) # Return dest + n +- j .L_G5_start +-END(__mempcpy) +-#ifndef USE_MULTIARCH +-libc_hidden_def (__mempcpy) +-weak_alias (__mempcpy, mempcpy) +-libc_hidden_builtin_def (mempcpy) +-#endif +- +-ENTRY(memcpy) +- .machine "g5" +- lr %r1,%r2 # r1: Use as dest ; r2: Return dest +-.L_G5_start: +- ltr %r4,%r4 +- je .L_G5_99 +- ahi %r4,-1 +- lr %r5,%r4 +- srl %r5,8 +- ltr %r5,%r5 +- jne .L_G5_13 +-.L_G5_4: +- basr %r5,0 +-.L_G5_16: +- ex %r4,.L_G5_17-.L_G5_16(%r5) +-.L_G5_99: +- br %r14 +-.L_G5_13: +- chi %r5,4096 # Switch to mvcle for copies >1MB +- jh __memcpy_mvcle +-.L_G5_12: +- mvc 0(256,%r1),0(%r3) +- la %r1,256(%r1) +- la %r3,256(%r3) +- brct %r5,.L_G5_12 +- j .L_G5_4 +-.L_G5_17: +- mvc 0(1,%r1),0(%r3) +-END(memcpy) +-#ifndef USE_MULTIARCH +-libc_hidden_builtin_def (memcpy) +-#endif +- +-ENTRY(__memcpy_mvcle) +- # Using as standalone function will result in unexpected +- # results since the length field is incremented by 1 in order to +- # compensate the changes already done in the functions above. +- lr %r0,%r2 # backup return dest [ + n ] +- ahi %r4,1 # length + 1 +- lr %r5,%r4 # source length +- lr %r4,%r3 # source address +- lr %r2,%r1 # destination address +- lr %r3,%r5 # destination length = source length +-.L_MVCLE_1: +- mvcle %r2,%r4,0 # thats it, MVCLE is your friend +- jo .L_MVCLE_1 +- lr %r2,%r0 # return destination address +- br %r14 +-END(__memcpy_mvcle) +diff --git a/sysdeps/s390/s390-32/multiarch/Makefile b/sysdeps/s390/s390-32/multiarch/Makefile +deleted file mode 100644 +index 82a7492eb8436479..0000000000000000 +--- a/sysdeps/s390/s390-32/multiarch/Makefile ++++ /dev/null +@@ -1,3 +0,0 @@ +-ifeq ($(subdir),string) +-sysdep_routines += memcpy memcpy-s390 +-endif +diff --git a/sysdeps/s390/s390-32/multiarch/memcpy-s390.S b/sysdeps/s390/s390-32/multiarch/memcpy-s390.S +deleted file mode 100644 +index aad13bd07c31dab9..0000000000000000 +--- a/sysdeps/s390/s390-32/multiarch/memcpy-s390.S ++++ /dev/null +@@ -1,128 +0,0 @@ +-/* CPU specific memcpy implementations. 32 bit S/390 version. +- Copyright (C) 2012-2018 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 +- . */ +- +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +-/* INPUT PARAMETERS +- %r2 = target operands address +- %r3 = source operands address +- %r4 = number of bytes to copy. */ +- +- .text +- +-#if defined SHARED && IS_IN (libc) +- +-ENTRY(____mempcpy_z196) +- .machine "z196" +- .machinemode "zarch_nohighgprs" +- lr %r1,%r2 # Use as dest +- la %r2,0(%r4,%r2) # Return dest + n +- j .L_Z196_start +-END(____mempcpy_z196) +- +-ENTRY(__memcpy_z196) +- .machine "z196" +- .machinemode "zarch_nohighgprs" +- lr %r1,%r2 # r1: Use as dest ; r2: Return dest +-.L_Z196_start: +- llgfr %r4,%r4 +- ltgr %r4,%r4 +- je .L_Z196_4 +- aghi %r4,-1 +- srlg %r5,%r4,8 +- ltgr %r5,%r5 +- jne .L_Z196_5 +-.L_Z196_3: +- exrl %r4,.L_Z196_14 +-.L_Z196_4: +- br %r14 +-.L_Z196_5: +- cgfi %r5,262144 # Switch to mvcle for copies >64MB +- jh __memcpy_mvcle +-.L_Z196_2: +- pfd 1,768(%r3) +- pfd 2,768(%r1) +- mvc 0(256,%r1),0(%r3) +- aghi %r5,-1 +- la %r1,256(%r1) +- la %r3,256(%r3) +- jne .L_Z196_2 +- j .L_Z196_3 +-.L_Z196_14: +- mvc 0(1,%r1),0(%r3) +-END(__memcpy_z196) +- +-ENTRY(____mempcpy_z10) +- .machine "z10" +- .machinemode "zarch_nohighgprs" +- lr %r1,%r2 # Use as dest +- la %r2,0(%r4,%r2) # Return dest + n +- j .L_Z10_start +-END(____mempcpy_z10) +- +-ENTRY(__memcpy_z10) +- .machine "z10" +- .machinemode "zarch_nohighgprs" +- lr %r1,%r2 # r1: Use as dest ; r2: Return dest +-.L_Z10_start: +- llgfr %r4,%r4 +- cgije %r4,0,.L_Z10_4 +- aghi %r4,-1 +- srlg %r5,%r4,8 +- cgijlh %r5,0,.L_Z10_13 +-.L_Z10_3: +- exrl %r4,.L_Z10_15 +-.L_Z10_4: +- br %r14 +-.L_Z10_13: +- cgfi %r5,65535 # Switch to mvcle for copies >16MB +- jh __memcpy_mvcle +-.L_Z10_12: +- pfd 1,768(%r3) +- pfd 2,768(%r1) +- mvc 0(256,%r1),0(%r3) +- la %r1,256(%r1) +- la %r3,256(%r3) +- brctg %r5,.L_Z10_12 +- j .L_Z10_3 +-.L_Z10_15: +- mvc 0(1,%r1),0(%r3) +-END(__memcpy_z10) +- +-# define __mempcpy ____mempcpy_default +-#endif /* SHARED && IS_IN (libc) */ +- +-#define memcpy __memcpy_default +-#include "../memcpy.S" +-#undef memcpy +- +-#if defined SHARED && IS_IN (libc) +-.globl __GI_memcpy +-.set __GI_memcpy,__memcpy_default +-.globl __GI_mempcpy +-.set __GI_mempcpy,____mempcpy_default +-.globl __GI___mempcpy +-.set __GI___mempcpy,____mempcpy_default +-#else +-.globl memcpy +-.set memcpy,__memcpy_default +-.weak mempcpy +-.set mempcpy,__mempcpy +-#endif +diff --git a/sysdeps/s390/s390-64/multiarch/Makefile b/sysdeps/s390/s390-64/multiarch/Makefile +deleted file mode 100644 +index 8a043e3327a1527a..0000000000000000 +--- a/sysdeps/s390/s390-64/multiarch/Makefile ++++ /dev/null +@@ -1,3 +0,0 @@ +-ifeq ($(subdir),string) +-sysdep_routines += memcpy memcpy-s390x +-endif +diff --git a/sysdeps/s390/s390-64/multiarch/memcpy.c b/sysdeps/s390/s390-64/multiarch/memcpy.c +deleted file mode 100644 +index c9577a854a0c7e68..0000000000000000 +--- a/sysdeps/s390/s390-64/multiarch/memcpy.c ++++ /dev/null +@@ -1,27 +0,0 @@ +-/* Multiple versions of memcpy. +- Copyright (C) 2015-2018 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 +- . */ +- +-/* In the static lib memcpy is needed before the reloc is resolved. */ +-#if defined SHARED && IS_IN (libc) +-# define memcpy __redirect_memcpy +-# include +-# undef memcpy +-# include +- +-s390_libc_ifunc (__redirect_memcpy, __memcpy, memcpy) +-#endif diff --git a/glibc-rh1659438-9.patch b/glibc-rh1659438-9.patch new file mode 100755 index 0000000..d3387ca --- /dev/null +++ b/glibc-rh1659438-9.patch @@ -0,0 +1,656 @@ +commit 18eb862d454a41012ccdd5127715ef7cd2a711ec +Author: Stefan Liebler +Date: Tue Dec 18 13:57:06 2018 +0100 + + S390: Refactor memcpy/mempcpy ifunc handling. + + This patch moves all ifunc variants for memcpy/mempcpy + to sysdeps/s390/memcpy-z900.S. The configure-check/preprocessor logic + in sysdeps/s390/ifunc-memcpy.h decides if ifunc is needed at all + and which ifunc variants should be available. + E.g. if the compiler/assembler already supports z196 by default, + the older ifunc variants are not included. + If we only need the newest ifunc variant, + then we can skip ifunc at all. + + Therefore the ifunc-resolvers and __libc_ifunc_impl_list are adjusted + in order to handle only the available ifunc variants. + + ChangeLog: + + * sysdeps/s390/ifunc-memcpy.h: New File. + * sysdeps/s390/memcpy.S: Move to ... + * sysdeps/s390/memcpy-z900.S ... here. + Move implementations from memcpy-s390x.s to here. + * sysdeps/s390/multiarch/memcpy-s390x.S: Delete File. + * sysdeps/s390/multiarch/Makefile (sysdep_routines): + Remove memcpy/mempcpy variants. + * sysdeps/s390/Makefile (sysdep_routines): + Add memcpy/mempcpy variants. + * sysdeps/s390/multiarch/ifunc-impl-list.c + (__libc_ifunc_impl_list): Adjust ifunc variants for + memcpy and mempcpy. + * sysdeps/s390/multiarch/memcpy.c: Move ifunc resolver + to ... + * sysdeps/s390/memcpy.c: ... here. + Adjust ifunc variants for memcpy. + * sysdeps/s390/multiarch/mempcpy.c: Move to ... + * sysdeps/s390/mempcpy.c: ... here. + Adjust ifunc variants for mempcpy. + * sysdeps/s390/mempcpy.S: Delete file. + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index c59cbdc25aad408a..838950a5ab958e31 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -32,5 +32,6 @@ endif + + ifeq ($(subdir),string) + sysdep_routines += bzero memset memset-z900 \ +- memcmp memcmp-z900 ++ memcmp memcmp-z900 \ ++ mempcpy memcpy memcpy-z900 + endif +diff --git a/sysdeps/s390/ifunc-memcpy.h b/sysdeps/s390/ifunc-memcpy.h +new file mode 100644 +index 0000000000000000..51c71baa2c0b0452 +--- /dev/null ++++ b/sysdeps/s390/ifunc-memcpy.h +@@ -0,0 +1,68 @@ ++/* memcpy variant information on S/390 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#if defined SHARED && defined USE_MULTIARCH && IS_IN (libc) \ ++ && ! defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# define HAVE_MEMCPY_IFUNC 1 ++#else ++# define HAVE_MEMCPY_IFUNC 0 ++#endif ++ ++#if defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# define MEMCPY_DEFAULT MEMCPY_Z196 ++# define MEMPCPY_DEFAULT MEMPCPY_Z196 ++# define HAVE_MEMCPY_Z900_G5 0 ++# define HAVE_MEMCPY_Z10 0 ++# define HAVE_MEMCPY_Z196 1 ++#elif defined HAVE_S390_MIN_Z10_ZARCH_ASM_SUPPORT ++# define MEMCPY_DEFAULT MEMCPY_Z10 ++# define MEMPCPY_DEFAULT MEMPCPY_Z10 ++# define HAVE_MEMCPY_Z900_G5 0 ++# define HAVE_MEMCPY_Z10 1 ++# define HAVE_MEMCPY_Z196 HAVE_MEMCPY_IFUNC ++#else ++# define MEMCPY_DEFAULT MEMCPY_Z900_G5 ++# define MEMPCPY_DEFAULT MEMPCPY_Z900_G5 ++# define HAVE_MEMCPY_Z900_G5 1 ++# define HAVE_MEMCPY_Z10 HAVE_MEMCPY_IFUNC ++# define HAVE_MEMCPY_Z196 HAVE_MEMCPY_IFUNC ++#endif ++ ++#if HAVE_MEMCPY_Z900_G5 ++# define MEMCPY_Z900_G5 __memcpy_default ++# define MEMPCPY_Z900_G5 __mempcpy_default ++#else ++# define MEMCPY_Z900_G5 NULL ++# define MEMPCPY_Z900_G5 NULL ++#endif ++ ++#if HAVE_MEMCPY_Z10 ++# define MEMCPY_Z10 __memcpy_z10 ++# define MEMPCPY_Z10 __mempcpy_z10 ++#else ++# define MEMCPY_Z10 NULL ++# define MEMPCPY_Z10 NULL ++#endif ++ ++#if HAVE_MEMCPY_Z196 ++# define MEMCPY_Z196 __memcpy_z196 ++# define MEMPCPY_Z196 __mempcpy_z196 ++#else ++# define MEMCPY_Z196 NULL ++# define MEMPCPY_Z196 NULL ++#endif +diff --git a/sysdeps/s390/memcpy.S b/sysdeps/s390/memcpy-z900.S +similarity index 50% +rename from sysdeps/s390/memcpy.S +rename to sysdeps/s390/memcpy-z900.S +index 2a6c6b750377c7bb..3a50cf44d85d2417 100644 +--- a/sysdeps/s390/memcpy.S ++++ b/sysdeps/s390/memcpy-z900.S +@@ -19,6 +19,7 @@ + + #include + #include "asm-syntax.h" ++#include + + /* INPUT PARAMETERS + %r2 = address of destination memory area +@@ -41,50 +42,46 @@ + # define BRCTG brct + #endif /* ! defined __s390x__ */ + +-ENTRY(__mempcpy) +-#if defined __s390x__ ++#if HAVE_MEMCPY_Z900_G5 ++ENTRY(MEMPCPY_Z900_G5) ++# if defined __s390x__ + .machine "z900" +-#else ++# else + .machine "g5" +-#endif /* ! defined __s390x__ */ ++# endif /* ! defined __s390x__ */ + LGR %r1,%r2 # Use as dest + la %r2,0(%r4,%r2) # Return dest + n + j .L_Z900_G5_start +-END(__mempcpy) +-#ifndef USE_MULTIARCH +-libc_hidden_def (__mempcpy) +-weak_alias (__mempcpy, mempcpy) +-libc_hidden_builtin_def (mempcpy) +-#endif ++END(MEMPCPY_Z900_G5) + +-ENTRY(memcpy) +-#if defined __s390x__ ++ENTRY(MEMCPY_Z900_G5) ++# if defined __s390x__ + .machine "z900" +-#else ++# else + .machine "g5" +-#endif /* ! defined __s390x__ */ ++# endif /* ! defined __s390x__ */ + LGR %r1,%r2 # r1: Use as dest ; r2: Return dest + .L_Z900_G5_start: + LTGR %r4,%r4 + je .L_Z900_G5_4 + AGHI %r4,-1 +-#if defined __s390x__ ++# if defined __s390x__ + srlg %r5,%r4,8 +-#else ++# else + lr %r5,%r4 + srl %r5,8 +-#endif /* ! defined __s390x__ */ ++# endif /* ! defined __s390x__ */ + LTGR %r5,%r5 + jne .L_Z900_G5_13 + .L_Z900_G5_3: +-#if defined __s390x__ ++# if defined __s390x__ + larl %r5,.L_Z900_G5_15 +-# define Z900_G5_EX_D 0 +-#else ++# define Z900_G5_EX_D 0 ++# else + basr %r5,0 + .L_Z900_G5_14: +-# define Z900_G5_EX_D .L_Z900_G5_15-.L_Z900_G5_14 +-#endif /* ! defined __s390x__ */ ++# define Z900_G5_EX_D .L_Z900_G5_15-.L_Z900_G5_14 ++# endif /* ! defined __s390x__ */ + ex %r4,Z900_G5_EX_D(%r5) + .L_Z900_G5_4: + br %r14 +@@ -99,10 +96,8 @@ ENTRY(memcpy) + j .L_Z900_G5_3 + .L_Z900_G5_15: + mvc 0(1,%r1),0(%r3) +-END(memcpy) +-#ifndef USE_MULTIARCH +-libc_hidden_builtin_def (memcpy) +-#endif ++END(MEMCPY_Z900_G5) ++#endif /* HAVE_MEMCPY_Z900_G5 */ + + ENTRY(__memcpy_mvcle) + # Using as standalone function will result in unexpected +@@ -126,3 +121,104 @@ END(__memcpy_mvcle) + #undef LGR + #undef AGHI + #undef BRCTG ++ ++#if HAVE_MEMCPY_Z10 ++ENTRY(MEMPCPY_Z10) ++ .machine "z10" ++ .machinemode "zarch_nohighgprs" ++ lgr %r1,%r2 # Use as dest ++ la %r2,0(%r4,%r2) # Return dest + n ++ j .L_Z10_start ++END(MEMPCPY_Z10) ++ ++ENTRY(MEMCPY_Z10) ++ .machine "z10" ++ .machinemode "zarch_nohighgprs" ++ lgr %r1,%r2 # r1: Use as dest ; r2: Return dest ++.L_Z10_start: ++# if !defined __s390x__ ++ llgfr %r4,%r4 ++# endif /* !defined __s390x__ */ ++ cgije %r4,0,.L_Z10_4 ++ aghi %r4,-1 ++ srlg %r5,%r4,8 ++ cgijlh %r5,0,.L_Z10_13 ++.L_Z10_3: ++ exrl %r4,.L_Z10_15 ++.L_Z10_4: ++ br %r14 ++.L_Z10_13: ++ cgfi %r5,65535 # Switch to mvcle for copies >16MB ++ jh __memcpy_mvcle ++.L_Z10_12: ++ pfd 1,768(%r3) ++ pfd 2,768(%r1) ++ mvc 0(256,%r1),0(%r3) ++ la %r1,256(%r1) ++ la %r3,256(%r3) ++ brctg %r5,.L_Z10_12 ++ j .L_Z10_3 ++.L_Z10_15: ++ mvc 0(1,%r1),0(%r3) ++END(MEMCPY_Z10) ++#endif /* HAVE_MEMCPY_Z10 */ ++ ++#if HAVE_MEMCPY_Z196 ++ENTRY(MEMPCPY_Z196) ++ .machine "z196" ++ .machinemode "zarch_nohighgprs" ++ lgr %r1,%r2 # Use as dest ++ la %r2,0(%r4,%r2) # Return dest + n ++ j .L_Z196_start ++END(MEMPCPY_Z196) ++ ++ENTRY(MEMCPY_Z196) ++ .machine "z196" ++ .machinemode "zarch_nohighgprs" ++ lgr %r1,%r2 # r1: Use as dest ; r2: Return dest ++.L_Z196_start: ++# if !defined __s390x__ ++ llgfr %r4,%r4 ++# endif /* !defined __s390x__ */ ++ ltgr %r4,%r4 ++ je .L_Z196_4 ++ aghi %r4,-1 ++ srlg %r5,%r4,8 ++ ltgr %r5,%r5 ++ jne .L_Z196_5 ++.L_Z196_3: ++ exrl %r4,.L_Z196_14 ++.L_Z196_4: ++ br %r14 ++.L_Z196_5: ++ cgfi %r5,262144 # Switch to mvcle for copies >64MB ++ jh __memcpy_mvcle ++.L_Z196_2: ++ pfd 1,768(%r3) ++ pfd 2,768(%r1) ++ mvc 0(256,%r1),0(%r3) ++ aghi %r5,-1 ++ la %r1,256(%r1) ++ la %r3,256(%r3) ++ jne .L_Z196_2 ++ j .L_Z196_3 ++.L_Z196_14: ++ mvc 0(1,%r1),0(%r3) ++END(MEMCPY_Z196) ++#endif /* HAVE_MEMCPY_Z196 */ ++ ++#if ! HAVE_MEMCPY_IFUNC ++/* If we don't use ifunc, define an alias for mem[p]cpy here. ++ Otherwise see sysdeps/s390/mem[p]cpy.c. */ ++strong_alias (MEMCPY_DEFAULT, memcpy) ++strong_alias (MEMPCPY_DEFAULT, __mempcpy) ++weak_alias (__mempcpy, mempcpy) ++#endif ++ ++#if defined SHARED && IS_IN (libc) ++/* Defines the internal symbols. ++ Compare to libc_hidden_[builtin_]def (mem[p]cpy) in string/mem[p]cpy.c. */ ++strong_alias (MEMCPY_DEFAULT, __GI_memcpy) ++strong_alias (MEMPCPY_DEFAULT, __GI_mempcpy) ++strong_alias (MEMPCPY_DEFAULT, __GI___mempcpy) ++#endif +diff --git a/sysdeps/s390/multiarch/memcpy.c b/sysdeps/s390/memcpy.c +similarity index 60% +rename from sysdeps/s390/multiarch/memcpy.c +rename to sysdeps/s390/memcpy.c +index c9577a854a0c7e68..90a53ac27d4be755 100644 +--- a/sysdeps/s390/multiarch/memcpy.c ++++ b/sysdeps/s390/memcpy.c +@@ -16,12 +16,34 @@ + License along with the GNU C Library; if not, see + . */ + +-/* In the static lib memcpy is needed before the reloc is resolved. */ +-#if defined SHARED && IS_IN (libc) ++#include ++ ++#if HAVE_MEMCPY_IFUNC + # define memcpy __redirect_memcpy + # include + # undef memcpy + # include + +-s390_libc_ifunc (__redirect_memcpy, __memcpy, memcpy) ++# if HAVE_MEMCPY_Z900_G5 ++extern __typeof (__redirect_memcpy) MEMCPY_Z900_G5 attribute_hidden; ++# endif ++ ++# if HAVE_MEMCPY_Z10 ++extern __typeof (__redirect_memcpy) MEMCPY_Z10 attribute_hidden; ++# endif ++ ++# if HAVE_MEMCPY_Z196 ++extern __typeof (__redirect_memcpy) MEMCPY_Z196 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect_memcpy, memcpy, ++ ({ ++ s390_libc_ifunc_init (); ++ (HAVE_MEMCPY_Z196 && S390_IS_Z196 (stfle_bits)) ++ ? MEMCPY_Z196 ++ : (HAVE_MEMCPY_Z10 && S390_IS_Z10 (stfle_bits)) ++ ? MEMCPY_Z10 ++ : MEMCPY_DEFAULT; ++ }) ++ ) + #endif +diff --git a/sysdeps/s390/mempcpy.S b/sysdeps/s390/mempcpy.S +deleted file mode 100644 +index 18ef29213e26e76d..0000000000000000 +--- a/sysdeps/s390/mempcpy.S ++++ /dev/null +@@ -1,19 +0,0 @@ +-/* CPU specific mempcpy without multiarch - 32/64 bit S/390 version. +- Copyright (C) 2016-2018 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 +- . */ +- +-/* mempcpy is implemented in memcpy.S. */ +diff --git a/sysdeps/s390/multiarch/mempcpy.c b/sysdeps/s390/mempcpy.c +similarity index 63% +rename from sysdeps/s390/multiarch/mempcpy.c +rename to sysdeps/s390/mempcpy.c +index 363fe47aefb80978..a6a237312659c2c1 100644 +--- a/sysdeps/s390/multiarch/mempcpy.c ++++ b/sysdeps/s390/mempcpy.c +@@ -16,8 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + +-#if defined SHARED && IS_IN (libc) ++#if HAVE_MEMCPY_IFUNC + # define mempcpy __redirect_mempcpy + # define __mempcpy __redirect___mempcpy + # define __NO_STRING_INLINES +@@ -27,6 +28,27 @@ + # undef __mempcpy + # include + +-s390_libc_ifunc (__redirect___mempcpy, ____mempcpy, __mempcpy) ++# if HAVE_MEMCPY_Z900_G5 ++extern __typeof (__redirect___mempcpy) MEMPCPY_Z900_G5 attribute_hidden; ++# endif ++ ++# if HAVE_MEMCPY_Z10 ++extern __typeof (__redirect___mempcpy) MEMPCPY_Z10 attribute_hidden; ++# endif ++ ++# if HAVE_MEMCPY_Z196 ++extern __typeof (__redirect___mempcpy) MEMPCPY_Z196 attribute_hidden; ++# endif ++ ++s390_libc_ifunc_expr (__redirect___mempcpy, __mempcpy, ++ ({ ++ s390_libc_ifunc_init (); ++ (HAVE_MEMCPY_Z196 && S390_IS_Z196 (stfle_bits)) ++ ? MEMPCPY_Z196 ++ : (HAVE_MEMCPY_Z10 && S390_IS_Z10 (stfle_bits)) ++ ? MEMPCPY_Z10 ++ : MEMPCPY_DEFAULT; ++ }) ++ ) + weak_alias (__mempcpy, mempcpy); + #endif +diff --git a/sysdeps/s390/multiarch/Makefile b/sysdeps/s390/multiarch/Makefile +index 3cbd5fad69e355a5..24949cd3a88b8015 100644 +--- a/sysdeps/s390/multiarch/Makefile ++++ b/sysdeps/s390/multiarch/Makefile +@@ -18,8 +18,7 @@ sysdep_routines += strlen strlen-vx strlen-c \ + memchr memchr-vx \ + rawmemchr rawmemchr-vx rawmemchr-c \ + memccpy memccpy-vx memccpy-c \ +- memrchr memrchr-vx memrchr-c \ +- mempcpy memcpy memcpy-s390x ++ memrchr memrchr-vx memrchr-c + endif + + ifeq ($(subdir),wcsmbs) +diff --git a/sysdeps/s390/multiarch/ifunc-impl-list.c b/sysdeps/s390/multiarch/ifunc-impl-list.c +index 2e57d01abc21522e..6969c480cc40e0e2 100644 +--- a/sysdeps/s390/multiarch/ifunc-impl-list.c ++++ b/sysdeps/s390/multiarch/ifunc-impl-list.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + /* Maximum number of IFUNC implementations. */ + #define MAX_IFUNC 3 +@@ -95,23 +96,35 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + ) + #endif /* HAVE_MEMCMP_IFUNC */ + +-#ifdef SHARED +- ++#if HAVE_MEMCPY_IFUNC + IFUNC_IMPL (i, name, memcpy, ++# if HAVE_MEMCPY_Z196 + IFUNC_IMPL_ADD (array, i, memcpy, +- S390_IS_Z196 (stfle_bits), __memcpy_z196) ++ S390_IS_Z196 (stfle_bits), MEMCPY_Z196) ++# endif ++# if HAVE_MEMCPY_Z10 + IFUNC_IMPL_ADD (array, i, memcpy, +- S390_IS_Z10 (stfle_bits), __memcpy_z10) +- IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_default)) ++ S390_IS_Z10 (stfle_bits), MEMCPY_Z10) ++# endif ++# if HAVE_MEMCPY_Z900_G5 ++ IFUNC_IMPL_ADD (array, i, memcpy, 1, MEMCPY_Z900_G5) ++# endif ++ ) + + IFUNC_IMPL (i, name, mempcpy, ++# if HAVE_MEMCPY_Z196 + IFUNC_IMPL_ADD (array, i, mempcpy, +- S390_IS_Z196 (stfle_bits), ____mempcpy_z196) ++ S390_IS_Z196 (stfle_bits), MEMPCPY_Z196) ++# endif ++# if HAVE_MEMCPY_Z10 + IFUNC_IMPL_ADD (array, i, mempcpy, +- S390_IS_Z10 (stfle_bits), ____mempcpy_z10) +- IFUNC_IMPL_ADD (array, i, mempcpy, 1, ____mempcpy_default)) +- +-#endif /* SHARED */ ++ S390_IS_Z10 (stfle_bits), MEMPCPY_Z10) ++# endif ++# if HAVE_MEMCPY_Z900_G5 ++ IFUNC_IMPL_ADD (array, i, mempcpy, 1, MEMPCPY_Z900_G5) ++# endif ++ ) ++#endif /* HAVE_MEMCPY_IFUNC */ + + #ifdef HAVE_S390_VX_ASM_SUPPORT + +diff --git a/sysdeps/s390/multiarch/memcpy-s390x.S b/sysdeps/s390/multiarch/memcpy-s390x.S +deleted file mode 100644 +index b38caac72b8742e6..0000000000000000 +--- a/sysdeps/s390/multiarch/memcpy-s390x.S ++++ /dev/null +@@ -1,132 +0,0 @@ +-/* CPU specific memcpy implementations. 31/64 bit S/390 version. +- Copyright (C) 2012-2018 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 +- . */ +- +- +-#include "sysdep.h" +-#include "asm-syntax.h" +- +-/* INPUT PARAMETERS +- %r2 = target operands address +- %r3 = source operands address +- %r4 = number of bytes to copy. */ +- +- .text +- +-#if defined SHARED && IS_IN (libc) +- +-ENTRY(____mempcpy_z196) +- .machine "z196" +- .machinemode "zarch_nohighgprs" +- lgr %r1,%r2 # Use as dest +- la %r2,0(%r4,%r2) # Return dest + n +- j .L_Z196_start +-END(____mempcpy_z196) +- +-ENTRY(__memcpy_z196) +- .machine "z196" +- .machinemode "zarch_nohighgprs" +- lgr %r1,%r2 # r1: Use as dest ; r2: Return dest +-.L_Z196_start: +-# if !defined __s390x__ +- llgfr %r4,%r4 +-# endif /* !defined __s390x__ */ +- ltgr %r4,%r4 +- je .L_Z196_4 +- aghi %r4,-1 +- srlg %r5,%r4,8 +- ltgr %r5,%r5 +- jne .L_Z196_5 +-.L_Z196_3: +- exrl %r4,.L_Z196_14 +-.L_Z196_4: +- br %r14 +-.L_Z196_5: +- cgfi %r5,262144 # Switch to mvcle for copies >64MB +- jh __memcpy_mvcle +-.L_Z196_2: +- pfd 1,768(%r3) +- pfd 2,768(%r1) +- mvc 0(256,%r1),0(%r3) +- aghi %r5,-1 +- la %r1,256(%r1) +- la %r3,256(%r3) +- jne .L_Z196_2 +- j .L_Z196_3 +-.L_Z196_14: +- mvc 0(1,%r1),0(%r3) +-END(__memcpy_z196) +- +-ENTRY(____mempcpy_z10) +- .machine "z10" +- .machinemode "zarch_nohighgprs" +- lgr %r1,%r2 # Use as dest +- la %r2,0(%r4,%r2) # Return dest + n +- j .L_Z10_start +-END(____mempcpy_z10) +- +-ENTRY(__memcpy_z10) +- .machine "z10" +- .machinemode "zarch_nohighgprs" +- lgr %r1,%r2 # r1: Use as dest ; r2: Return dest +-.L_Z10_start: +-# if !defined __s390x__ +- llgfr %r4,%r4 +-# endif /* !defined __s390x__ */ +- cgije %r4,0,.L_Z10_4 +- aghi %r4,-1 +- srlg %r5,%r4,8 +- cgijlh %r5,0,.L_Z10_13 +-.L_Z10_3: +- exrl %r4,.L_Z10_15 +-.L_Z10_4: +- br %r14 +-.L_Z10_13: +- cgfi %r5,65535 # Switch to mvcle for copies >16MB +- jh __memcpy_mvcle +-.L_Z10_12: +- pfd 1,768(%r3) +- pfd 2,768(%r1) +- mvc 0(256,%r1),0(%r3) +- la %r1,256(%r1) +- la %r3,256(%r3) +- brctg %r5,.L_Z10_12 +- j .L_Z10_3 +-.L_Z10_15: +- mvc 0(1,%r1),0(%r3) +-END(__memcpy_z10) +- +-# define __mempcpy ____mempcpy_default +-#endif /* SHARED && IS_IN (libc) */ +- +-#define memcpy __memcpy_default +-#include "../memcpy.S" +-#undef memcpy +- +-#if defined SHARED && IS_IN (libc) +-.globl __GI_memcpy +-.set __GI_memcpy,__memcpy_default +-.globl __GI_mempcpy +-.set __GI_mempcpy,____mempcpy_default +-.globl __GI___mempcpy +-.set __GI___mempcpy,____mempcpy_default +-#else +-.globl memcpy +-.set memcpy,__memcpy_default +-.weak mempcpy +-.set mempcpy,__mempcpy +-#endif diff --git a/glibc-rh1659512-1.patch b/glibc-rh1659512-1.patch new file mode 100755 index 0000000..71956e9 --- /dev/null +++ b/glibc-rh1659512-1.patch @@ -0,0 +1,312 @@ +commit c70271662aa53aee0c4794d480dca6d9ba3ccc3d +Author: Adhemerval Zanella +Date: Wed Sep 19 11:12:05 2018 -0700 + + Use libsupport for tst-spawn.c + + No function changes is done. Checked on x86_64-linux-gnu. + + * posix/tst-spawn.c (do_prepare, handle_restart, do_test): + Use libsupport. + +diff --git a/posix/tst-spawn.c b/posix/tst-spawn.c +index 7c785c430c..41f1a65243 100644 +--- a/posix/tst-spawn.c ++++ b/posix/tst-spawn.c +@@ -17,16 +17,20 @@ + License along with the GNU C Library; if not, see + . */ + ++#include ++#include + #include + #include + #include + #include + #include + #include +-#include + #include ++ + #include + #include ++#include ++#include + + + /* Nonzero if the program gets called via `exec'. */ +@@ -36,16 +40,6 @@ static int restart; + #define CMDLINE_OPTIONS \ + { "restart", no_argument, &restart, 1 }, + +-/* Prototype for our test function. */ +-extern void do_prepare (int argc, char *argv[]); +-extern int do_test (int argc, char *argv[]); +- +-/* We have a preparation function. */ +-#define PREPARE do_prepare +- +-#include "../test-skeleton.c" +- +- + /* Name of the temporary files. */ + static char *name1; + static char *name2; +@@ -63,19 +57,18 @@ static const char fd3string[] = "This file will be opened"; + + + /* We have a preparation function. */ +-void ++static void + do_prepare (int argc, char *argv[]) + { + /* We must not open any files in the restart case. */ + if (restart) + return; + +- temp_fd1 = create_temp_file ("spawn", &name1); +- temp_fd2 = create_temp_file ("spawn", &name2); +- temp_fd3 = create_temp_file ("spawn", &name3); +- if (temp_fd1 < 0 || temp_fd2 < 0 || temp_fd3 < 0) +- exit (1); ++ TEST_VERIFY_EXIT ((temp_fd1 = create_temp_file ("spawn", &name1)) != -1); ++ TEST_VERIFY_EXIT ((temp_fd2 = create_temp_file ("spawn", &name2)) != -1); ++ TEST_VERIFY_EXIT ((temp_fd3 = create_temp_file ("spawn", &name3)) != -1); + } ++#define PREPARE do_prepare + + + static int +@@ -95,64 +88,45 @@ handle_restart (const char *fd1s, const char *fd2s, const char *fd3s, + fd4 = atol (fd4s); + + /* Sanity check. */ +- if (fd1 == fd2) +- error (EXIT_FAILURE, 0, "value of fd1 and fd2 is the same"); +- if (fd1 == fd3) +- error (EXIT_FAILURE, 0, "value of fd1 and fd3 is the same"); +- if (fd1 == fd4) +- error (EXIT_FAILURE, 0, "value of fd1 and fd4 is the same"); +- if (fd2 == fd3) +- error (EXIT_FAILURE, 0, "value of fd2 and fd3 is the same"); +- if (fd2 == fd4) +- error (EXIT_FAILURE, 0, "value of fd2 and fd4 is the same"); +- if (fd3 == fd4) +- error (EXIT_FAILURE, 0, "value of fd3 and fd4 is the same"); ++ TEST_VERIFY_EXIT (fd1 != fd2); ++ TEST_VERIFY_EXIT (fd1 != fd3); ++ TEST_VERIFY_EXIT (fd1 != fd4); ++ TEST_VERIFY_EXIT (fd2 != fd3); ++ TEST_VERIFY_EXIT (fd2 != fd4); ++ TEST_VERIFY_EXIT (fd3 != fd4); + + /* First the easy part: read from the file descriptor which is + supposed to be open. */ +- if (lseek (fd2, 0, SEEK_CUR) != strlen (fd2string)) +- error (EXIT_FAILURE, errno, "file 2 not in right position"); ++ TEST_COMPARE (xlseek (fd2, 0, SEEK_CUR), strlen (fd2string)); + /* The duped descriptor must have the same position. */ +- if (lseek (fd4, 0, SEEK_CUR) != strlen (fd2string)) +- error (EXIT_FAILURE, errno, "file 4 not in right position"); +- if (lseek (fd2, 0, SEEK_SET) != 0) +- error (EXIT_FAILURE, 0, "cannot reset position in file 2"); +- if (lseek (fd4, 0, SEEK_CUR) != 0) +- error (EXIT_FAILURE, errno, "file 4 not set back, too"); +- if (read (fd2, buf, sizeof buf) != strlen (fd2string)) +- error (EXIT_FAILURE, 0, "cannot read file 2"); +- if (memcmp (fd2string, buf, strlen (fd2string)) != 0) +- error (EXIT_FAILURE, 0, "file 2 does not match"); ++ TEST_COMPARE (xlseek (fd4, 0, SEEK_CUR), strlen (fd2string)); ++ TEST_COMPARE (xlseek (fd2, 0, SEEK_SET), 0); ++ TEST_COMPARE (xlseek (fd4, 0, SEEK_CUR), 0); ++ TEST_COMPARE (read (fd2, buf, sizeof buf), strlen (fd2string)); ++ TEST_COMPARE_BLOB (fd2string, strlen (fd2string), buf, strlen (fd2string)); + + /* Now read from the third file. */ +- if (read (fd3, buf, sizeof buf) != strlen (fd3string)) +- error (EXIT_FAILURE, 0, "cannot read file 3"); +- if (memcmp (fd3string, buf, strlen (fd3string)) != 0) +- error (EXIT_FAILURE, 0, "file 3 does not match"); ++ TEST_COMPARE (read (fd3, buf, sizeof buf), strlen (fd3string)); ++ TEST_COMPARE_BLOB (fd3string, strlen (fd3string), buf, strlen (fd3string)); + /* Try to write to the file. This should not be allowed. */ +- if (write (fd3, "boo!", 4) != -1 || errno != EBADF) +- error (EXIT_FAILURE, 0, "file 3 is writable"); ++ TEST_COMPARE (write (fd3, "boo!", 4), -1); ++ TEST_COMPARE (errno, EBADF); + + /* Now try to read the first file. First make sure it is not opened. */ +- if (lseek (fd1, 0, SEEK_CUR) != (off_t) -1 || errno != EBADF) +- error (EXIT_FAILURE, 0, "file 1 (%d) is not closed", fd1); ++ TEST_COMPARE (lseek (fd1, 0, SEEK_CUR), (off_t) -1); ++ TEST_COMPARE (errno, EBADF); + + /* Now open the file and read it. */ +- fd1 = open (name, O_RDONLY); +- if (fd1 == -1) +- error (EXIT_FAILURE, errno, +- "cannot open first file \"%s\" for verification", name); ++ fd1 = xopen (name, O_RDONLY, 0600); + +- if (read (fd1, buf, sizeof buf) != strlen (fd1string)) +- error (EXIT_FAILURE, errno, "cannot read file 1"); +- if (memcmp (fd1string, buf, strlen (fd1string)) != 0) +- error (EXIT_FAILURE, 0, "file 1 does not match"); ++ TEST_COMPARE (read (fd1, buf, sizeof buf), strlen (fd1string)); ++ TEST_COMPARE_BLOB (fd1string, strlen (fd1string), buf, strlen (fd1string)); + + return 0; + } + + +-int ++static int + do_test (int argc, char *argv[]) + { + pid_t pid; +@@ -181,7 +155,7 @@ do_test (int argc, char *argv[]) + + the name of the closed descriptor + */ + if (argc != (restart ? 6 : 2) && argc != (restart ? 6 : 5)) +- error (EXIT_FAILURE, 0, "wrong number of arguments (%d)", argc); ++ FAIL_EXIT1 ("wrong number of arguments (%d)", argc); + + if (restart) + return handle_restart (argv[1], argv[2], argv[3], argv[4], argv[5]); +@@ -189,77 +163,73 @@ do_test (int argc, char *argv[]) + /* Prepare the test. We are creating two files: one which file descriptor + will be marked with FD_CLOEXEC, another which is not. */ + +- /* Write something in the files. */ +- if (write (temp_fd1, fd1string, strlen (fd1string)) != strlen (fd1string)) +- error (EXIT_FAILURE, errno, "cannot write to first file"); +- if (write (temp_fd2, fd2string, strlen (fd2string)) != strlen (fd2string)) +- error (EXIT_FAILURE, errno, "cannot write to second file"); +- if (write (temp_fd3, fd3string, strlen (fd3string)) != strlen (fd3string)) +- error (EXIT_FAILURE, errno, "cannot write to third file"); +- +- /* Close the third file. It'll be opened by `spawn'. */ +- close (temp_fd3); +- +- /* Tell `spawn' what to do. */ +- if (posix_spawn_file_actions_init (&actions) != 0) +- error (EXIT_FAILURE, errno, "posix_spawn_file_actions_init"); +- /* Close `temp_fd1'. */ +- if (posix_spawn_file_actions_addclose (&actions, temp_fd1) != 0) +- error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addclose"); +- /* We want to open the third file. */ +- name3_copy = strdup (name3); +- if (name3_copy == NULL) +- error (EXIT_FAILURE, errno, "strdup"); +- if (posix_spawn_file_actions_addopen (&actions, temp_fd3, name3_copy, +- O_RDONLY, 0666) != 0) +- error (EXIT_FAILURE, errno, "posix_spawn_file_actions_addopen"); +- /* Overwrite the name to check that a copy has been made. */ +- memset (name3_copy, 'X', strlen (name3_copy)); +- +- /* We dup the second descriptor. */ +- fd4 = MAX (2, MAX (temp_fd1, MAX (temp_fd2, temp_fd3))) + 1; +- if (posix_spawn_file_actions_adddup2 (&actions, temp_fd2, fd4) != 0) +- error (EXIT_FAILURE, errno, "posix_spawn_file_actions_adddup2"); +- +- /* Now spawn the process. */ +- snprintf (fd1name, sizeof fd1name, "%d", temp_fd1); +- snprintf (fd2name, sizeof fd2name, "%d", temp_fd2); +- snprintf (fd3name, sizeof fd3name, "%d", temp_fd3); +- snprintf (fd4name, sizeof fd4name, "%d", fd4); +- +- for (i = 0; i < (argc == (restart ? 6 : 5) ? 4 : 1); i++) +- spargv[i] = argv[i + 1]; +- spargv[i++] = (char *) "--direct"; +- spargv[i++] = (char *) "--restart"; +- spargv[i++] = fd1name; +- spargv[i++] = fd2name; +- spargv[i++] = fd3name; +- spargv[i++] = fd4name; +- spargv[i++] = name1; +- spargv[i] = NULL; +- +- if (posix_spawn (&pid, argv[1], &actions, NULL, spargv, environ) != 0) +- error (EXIT_FAILURE, errno, "posix_spawn"); +- +- /* Same test but with a NULL pid argument. */ +- if (posix_spawn (NULL, argv[1], &actions, NULL, spargv, environ) != 0) +- error (EXIT_FAILURE, errno, "posix_spawn"); +- +- /* Cleanup. */ +- if (posix_spawn_file_actions_destroy (&actions) != 0) +- error (EXIT_FAILURE, errno, "posix_spawn_file_actions_destroy"); +- free (name3_copy); ++ /* Write something in the files. */ ++ xwrite (temp_fd1, fd1string, strlen (fd1string)); ++ xwrite (temp_fd2, fd2string, strlen (fd2string)); ++ xwrite (temp_fd3, fd3string, strlen (fd3string)); ++ ++ /* Close the third file. It'll be opened by `spawn'. */ ++ xclose (temp_fd3); ++ ++ /* Tell `spawn' what to do. */ ++ TEST_COMPARE (posix_spawn_file_actions_init (&actions), 0); ++ /* Close `temp_fd1'. */ ++ TEST_COMPARE (posix_spawn_file_actions_addclose (&actions, temp_fd1), 0); ++ /* We want to open the third file. */ ++ name3_copy = xstrdup (name3); ++ TEST_COMPARE (posix_spawn_file_actions_addopen (&actions, temp_fd3, ++ name3_copy, ++ O_RDONLY, 0666), ++ 0); ++ /* Overwrite the name to check that a copy has been made. */ ++ memset (name3_copy, 'X', strlen (name3_copy)); ++ ++ /* We dup the second descriptor. */ ++ fd4 = MAX (2, MAX (temp_fd1, MAX (temp_fd2, temp_fd3))) + 1; ++ TEST_COMPARE (posix_spawn_file_actions_adddup2 (&actions, temp_fd2, fd4), ++ 0); ++ ++ /* Now spawn the process. */ ++ snprintf (fd1name, sizeof fd1name, "%d", temp_fd1); ++ snprintf (fd2name, sizeof fd2name, "%d", temp_fd2); ++ snprintf (fd3name, sizeof fd3name, "%d", temp_fd3); ++ snprintf (fd4name, sizeof fd4name, "%d", fd4); ++ ++ for (i = 0; i < (argc == (restart ? 6 : 5) ? 4 : 1); i++) ++ spargv[i] = argv[i + 1]; ++ spargv[i++] = (char *) "--direct"; ++ spargv[i++] = (char *) "--restart"; ++ spargv[i++] = fd1name; ++ spargv[i++] = fd2name; ++ spargv[i++] = fd3name; ++ spargv[i++] = fd4name; ++ spargv[i++] = name1; ++ spargv[i] = NULL; ++ ++ TEST_COMPARE (posix_spawn (&pid, argv[1], &actions, NULL, spargv, environ), ++ 0); ++ ++ /* Same test but with a NULL pid argument. */ ++ TEST_COMPARE (posix_spawn (NULL, argv[1], &actions, NULL, spargv, environ), ++ 0); ++ ++ /* Cleanup. */ ++ TEST_COMPARE (posix_spawn_file_actions_destroy (&actions), 0); ++ free (name3_copy); + + /* Wait for the children. */ +- TEST_VERIFY (xwaitpid (pid, &status, 0) == pid); ++ TEST_COMPARE (xwaitpid (pid, &status, 0), pid); + TEST_VERIFY (WIFEXITED (status)); + TEST_VERIFY (!WIFSIGNALED (status)); +- TEST_VERIFY (WEXITSTATUS (status) == 0); ++ TEST_COMPARE (WEXITSTATUS (status), 0); + + xwaitpid (-1, &status, 0); + TEST_VERIFY (WIFEXITED (status)); + TEST_VERIFY (!WIFSIGNALED (status)); +- TEST_VERIFY (WEXITSTATUS (status) == 0); ++ TEST_COMPARE (WEXITSTATUS (status), 0); + + return 0; + } ++ ++#define TEST_FUNCTION_ARGV do_test ++#include diff --git a/glibc-rh1659512-2.patch b/glibc-rh1659512-2.patch new file mode 100755 index 0000000..ac36900 --- /dev/null +++ b/glibc-rh1659512-2.patch @@ -0,0 +1,62 @@ +commit 114f792eaea2505cd8aee02d330aad37238da6a5 +Author: Stefan Liebler +Date: Fri Feb 1 11:03:35 2019 +0100 + + posix/tst-spawn: Fix racy tests in spawned processes. + + From time to time I get fails in tst-spawn like: + tst-spawn.c:111: numeric comparison failure + left: 0 (0x0); from: xlseek (fd2, 0, SEEK_CUR) + right: 28 (0x1c); from: strlen (fd2string) + error: 1 test failures + tst-spawn.c:252: numeric comparison failure + left: 1 (0x1); from: WEXITSTATUS (status) + right: 0 (0x0); from: 0 + error: 1 test failures + + It turned out, that a child process is testing it's open file descriptors + with e.g. a sequence of testing the current position, setting the position + to zero and reading a specific amount of bytes. + + Unfortunately starting with commit 2a69f853c03034c2e383e0f9c35b5402ce8b5473 + the test is spawning a second child process which is sharing some of the + file descriptors. If the test sequence as mentioned above is running in parallel + it leads to test failures. + + As the second call of posix_spawn shall test a NULL pid argument, + this patch is just moving the waitpid of the first child + before the posix_spawn of the second child. + + ChangeLog: + + * posix/tst-spawn do_test(): Move waitpid before posix_spawn. + +diff --git a/posix/tst-spawn.c b/posix/tst-spawn.c +index eea5addbf3..9aa7e621e6 100644 +--- a/posix/tst-spawn.c ++++ b/posix/tst-spawn.c +@@ -237,6 +237,12 @@ do_test (int argc, char *argv[]) + TEST_COMPARE (posix_spawn (&pid, argv[1], &actions, NULL, spargv, environ), + 0); + ++ /* Wait for the children. */ ++ TEST_COMPARE (xwaitpid (pid, &status, 0), pid); ++ TEST_VERIFY (WIFEXITED (status)); ++ TEST_VERIFY (!WIFSIGNALED (status)); ++ TEST_COMPARE (WEXITSTATUS (status), 0); ++ + /* Same test but with a NULL pid argument. */ + TEST_COMPARE (posix_spawn (NULL, argv[1], &actions, NULL, spargv, environ), + 0); +@@ -246,11 +252,6 @@ do_test (int argc, char *argv[]) + free (name3_copy); + + /* Wait for the children. */ +- TEST_COMPARE (xwaitpid (pid, &status, 0), pid); +- TEST_VERIFY (WIFEXITED (status)); +- TEST_VERIFY (!WIFSIGNALED (status)); +- TEST_COMPARE (WEXITSTATUS (status), 0); +- + xwaitpid (-1, &status, 0); + TEST_VERIFY (WIFEXITED (status)); + TEST_VERIFY (!WIFSIGNALED (status)); diff --git a/glibc-rh1662843-1.patch b/glibc-rh1662843-1.patch new file mode 100755 index 0000000..5261045 --- /dev/null +++ b/glibc-rh1662843-1.patch @@ -0,0 +1,206 @@ +commit 1ecba1fafc160ca70f81211b23f688df8676e612 +Author: Florian Weimer +Date: Mon Nov 12 14:15:14 2018 +0100 + + malloc: Convert the unlink macro to the unlink_chunk function + + This commit is in preparation of turning the macro into a proper + function. The output arguments of the macro were in fact unused. + + Also clean up uses of __builtin_expect. + +diff --git a/malloc/arena.c b/malloc/arena.c +index 497ae475e7a85902..ff8fd5d2a7e51ac8 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -596,7 +596,7 @@ heap_trim (heap_info *heap, size_t pad) + { + mstate ar_ptr = heap->ar_ptr; + unsigned long pagesz = GLRO (dl_pagesize); +- mchunkptr top_chunk = top (ar_ptr), p, bck, fwd; ++ mchunkptr top_chunk = top (ar_ptr), p; + heap_info *prev_heap; + long new_size, top_size, top_area, extra, prev_size, misalign; + +@@ -625,7 +625,7 @@ heap_trim (heap_info *heap, size_t pad) + if (!prev_inuse (p)) /* consolidate backward */ + { + p = prev_chunk (p); +- unlink (ar_ptr, p, bck, fwd); ++ unlink_chunk (ar_ptr, p); + } + assert (((unsigned long) ((char *) p + new_size) & (pagesz - 1)) == 0); + assert (((char *) p + new_size) == ((char *) heap + heap->size)); +diff --git a/malloc/malloc.c b/malloc/malloc.c +index e450597e2e527fb7..7bfa66a56786d110 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -1384,39 +1384,6 @@ typedef struct malloc_chunk *mbinptr; + #define first(b) ((b)->fd) + #define last(b) ((b)->bk) + +-/* Take a chunk off a bin list */ +-#define unlink(AV, P, BK, FD) { \ +- if (__builtin_expect (chunksize(P) != prev_size (next_chunk(P)), 0)) \ +- malloc_printerr ("corrupted size vs. prev_size"); \ +- FD = P->fd; \ +- BK = P->bk; \ +- if (__builtin_expect (FD->bk != P || BK->fd != P, 0)) \ +- malloc_printerr ("corrupted double-linked list"); \ +- else { \ +- FD->bk = BK; \ +- BK->fd = FD; \ +- if (!in_smallbin_range (chunksize_nomask (P)) \ +- && __builtin_expect (P->fd_nextsize != NULL, 0)) { \ +- if (__builtin_expect (P->fd_nextsize->bk_nextsize != P, 0) \ +- || __builtin_expect (P->bk_nextsize->fd_nextsize != P, 0)) \ +- malloc_printerr ("corrupted double-linked list (not small)"); \ +- if (FD->fd_nextsize == NULL) { \ +- if (P->fd_nextsize == P) \ +- FD->fd_nextsize = FD->bk_nextsize = FD; \ +- else { \ +- FD->fd_nextsize = P->fd_nextsize; \ +- FD->bk_nextsize = P->bk_nextsize; \ +- P->fd_nextsize->bk_nextsize = FD; \ +- P->bk_nextsize->fd_nextsize = FD; \ +- } \ +- } else { \ +- P->fd_nextsize->bk_nextsize = P->bk_nextsize; \ +- P->bk_nextsize->fd_nextsize = P->fd_nextsize; \ +- } \ +- } \ +- } \ +-} +- + /* + Indexing + +@@ -1489,6 +1456,46 @@ typedef struct malloc_chunk *mbinptr; + #define bin_index(sz) \ + ((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz)) + ++/* Take a chunk off a bin list. */ ++static void ++unlink_chunk (mstate av, mchunkptr p) ++{ ++ if (chunksize (p) != prev_size (next_chunk (p))) ++ malloc_printerr ("corrupted size vs. prev_size"); ++ ++ mchunkptr fd = p->fd; ++ mchunkptr bk = p->bk; ++ ++ if (__builtin_expect (fd->bk != p || bk->fd != p, 0)) ++ malloc_printerr ("corrupted double-linked list"); ++ ++ fd->bk = bk; ++ bk->fd = fd; ++ if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL) ++ { ++ if (p->fd_nextsize->bk_nextsize != p ++ || p->bk_nextsize->fd_nextsize != p) ++ malloc_printerr ("corrupted double-linked list (not small)"); ++ ++ if (fd->fd_nextsize == NULL) ++ { ++ if (p->fd_nextsize == p) ++ fd->fd_nextsize = fd->bk_nextsize = fd; ++ else ++ { ++ fd->fd_nextsize = p->fd_nextsize; ++ fd->bk_nextsize = p->bk_nextsize; ++ p->fd_nextsize->bk_nextsize = fd; ++ p->bk_nextsize->fd_nextsize = fd; ++ } ++ } ++ else ++ { ++ p->fd_nextsize->bk_nextsize = p->bk_nextsize; ++ p->bk_nextsize->fd_nextsize = p->fd_nextsize; ++ } ++ } ++} + + /* + Unsorted chunks +@@ -3917,7 +3924,7 @@ _int_malloc (mstate av, size_t bytes) + victim = victim->fd; + + remainder_size = size - nb; +- unlink (av, victim, bck, fwd); ++ unlink_chunk (av, victim); + + /* Exhaust */ + if (remainder_size < MINSIZE) +@@ -4019,7 +4026,7 @@ _int_malloc (mstate av, size_t bytes) + remainder_size = size - nb; + + /* unlink */ +- unlink (av, victim, bck, fwd); ++ unlink_chunk (av, victim); + + /* Exhaust */ + if (remainder_size < MINSIZE) +@@ -4308,7 +4315,7 @@ _int_free (mstate av, mchunkptr p, int have_lock) + p = chunk_at_offset(p, -((long) prevsize)); + if (__glibc_unlikely (chunksize(p) != prevsize)) + malloc_printerr ("corrupted size vs. prev_size while consolidating"); +- unlink(av, p, bck, fwd); ++ unlink_chunk (av, p); + } + + if (nextchunk != av->top) { +@@ -4317,7 +4324,7 @@ _int_free (mstate av, mchunkptr p, int have_lock) + + /* consolidate forward */ + if (!nextinuse) { +- unlink(av, nextchunk, bck, fwd); ++ unlink_chunk (av, nextchunk); + size += nextsize; + } else + clear_inuse_bit_at_offset(nextchunk, 0); +@@ -4430,8 +4437,6 @@ static void malloc_consolidate(mstate av) + INTERNAL_SIZE_T nextsize; + INTERNAL_SIZE_T prevsize; + int nextinuse; +- mchunkptr bck; +- mchunkptr fwd; + + atomic_store_relaxed (&av->have_fastchunks, false); + +@@ -4471,7 +4476,7 @@ static void malloc_consolidate(mstate av) + p = chunk_at_offset(p, -((long) prevsize)); + if (__glibc_unlikely (chunksize(p) != prevsize)) + malloc_printerr ("corrupted size vs. prev_size in fastbins"); +- unlink(av, p, bck, fwd); ++ unlink_chunk (av, p); + } + + if (nextchunk != av->top) { +@@ -4479,7 +4484,7 @@ static void malloc_consolidate(mstate av) + + if (!nextinuse) { + size += nextsize; +- unlink(av, nextchunk, bck, fwd); ++ unlink_chunk (av, nextchunk); + } else + clear_inuse_bit_at_offset(nextchunk, 0); + +@@ -4527,9 +4532,6 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, + mchunkptr remainder; /* extra space at end of newp */ + unsigned long remainder_size; /* its size */ + +- mchunkptr bck; /* misc temp for linking */ +- mchunkptr fwd; /* misc temp for linking */ +- + unsigned long copysize; /* bytes to copy */ + unsigned int ncopies; /* INTERNAL_SIZE_T words to copy */ + INTERNAL_SIZE_T* s; /* copy source */ +@@ -4579,7 +4581,7 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, + (unsigned long) (nb)) + { + newp = oldp; +- unlink (av, next, bck, fwd); ++ unlink_chunk (av, next); + } + + /* allocate, copy, free */ diff --git a/glibc-rh1662843-2.patch b/glibc-rh1662843-2.patch new file mode 100755 index 0000000..27fe8c8 --- /dev/null +++ b/glibc-rh1662843-2.patch @@ -0,0 +1,73 @@ +commit b50dd3bc8cbb1efe85399b03d7e6c0310c2ead84 +Author: Florian Weimer +Date: Mon Dec 31 22:04:36 2018 +0100 + + malloc: Always call memcpy in _int_realloc [BZ #24027] + + This commit removes the custom memcpy implementation from _int_realloc + for small chunk sizes. The ncopies variable has the wrong type, and + an integer wraparound could cause the existing code to copy too few + elements (leaving the new memory region mostly uninitialized). + Therefore, removing this code fixes bug 24027. + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 7bfa66a56786d110..0234d968c0ce65a0 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -4532,11 +4532,6 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, + mchunkptr remainder; /* extra space at end of newp */ + unsigned long remainder_size; /* its size */ + +- unsigned long copysize; /* bytes to copy */ +- unsigned int ncopies; /* INTERNAL_SIZE_T words to copy */ +- INTERNAL_SIZE_T* s; /* copy source */ +- INTERNAL_SIZE_T* d; /* copy destination */ +- + /* oldmem size */ + if (__builtin_expect (chunksize_nomask (oldp) <= 2 * SIZE_SZ, 0) + || __builtin_expect (oldsize >= av->system_mem, 0)) +@@ -4604,43 +4599,7 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize, + } + else + { +- /* +- Unroll copy of <= 36 bytes (72 if 8byte sizes) +- We know that contents have an odd number of +- INTERNAL_SIZE_T-sized words; minimally 3. +- */ +- +- copysize = oldsize - SIZE_SZ; +- s = (INTERNAL_SIZE_T *) (chunk2mem (oldp)); +- d = (INTERNAL_SIZE_T *) (newmem); +- ncopies = copysize / sizeof (INTERNAL_SIZE_T); +- assert (ncopies >= 3); +- +- if (ncopies > 9) +- memcpy (d, s, copysize); +- +- else +- { +- *(d + 0) = *(s + 0); +- *(d + 1) = *(s + 1); +- *(d + 2) = *(s + 2); +- if (ncopies > 4) +- { +- *(d + 3) = *(s + 3); +- *(d + 4) = *(s + 4); +- if (ncopies > 6) +- { +- *(d + 5) = *(s + 5); +- *(d + 6) = *(s + 6); +- if (ncopies > 8) +- { +- *(d + 7) = *(s + 7); +- *(d + 8) = *(s + 8); +- } +- } +- } +- } +- ++ memcpy (newmem, chunk2mem (oldp), oldsize - SIZE_SZ); + _int_free (av, oldp, 1); + check_inuse_chunk (av, newp); + return chunk2mem (newp); diff --git a/glibc-rh1663035.patch b/glibc-rh1663035.patch new file mode 100755 index 0000000..ec38f0a --- /dev/null +++ b/glibc-rh1663035.patch @@ -0,0 +1,22 @@ +commit 8c1aafc1f34d090a5b41dc527c33e8687f6a1287 +Author: Florian Weimer +Date: Fri Dec 21 16:08:55 2018 +0100 + + intl: Do not return NULL on asprintf failure in gettext [BZ #24018] + + Fixes commit 9695dd0c9309712ed8e9c17a7040fe7af347f2dc ("DCIGETTEXT: + Use getcwd, asprintf to construct absolute pathname"). + +diff --git a/intl/dcigettext.c b/intl/dcigettext.c +index 2a5036994824875b..25f47c5bd3b0ea04 100644 +--- a/intl/dcigettext.c ++++ b/intl/dcigettext.c +@@ -631,7 +631,7 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, + int ret = __asprintf (&xdirname, "%s/%s", cwd, dirname); + free (cwd); + if (ret < 0) +- return NULL; ++ goto return_untranslated; + dirname = xdirname; + } + #ifndef IN_LIBGLOCALE diff --git a/glibc-rh1664408.patch b/glibc-rh1664408.patch new file mode 100755 index 0000000..f2f960f --- /dev/null +++ b/glibc-rh1664408.patch @@ -0,0 +1,131 @@ +commit 2ef427168818ce04b03cecb7b739f9db0156e3e4 +Author: Aurelien Jarno +Date: Thu Jan 3 15:51:37 2019 +0100 + + Only build libm with -fno-math-errno (bug 24024) + + Commit 1294b1892e ("Add support for sqrt asm redirects") added the + -fno-math-errno flag to build most of the glibc in order to enable GCC + to inline math functions. Due to GCC bug #88576, saving and restoring + errno around calls to malloc are optimized-out. In turn this causes + strerror to set errno to ENOMEM if it get passed an invalid error number + and if malloc sets errno to ENOMEM (which might happen even if it + succeeds). This is not allowed by POSIX. + + This patch changes the build flags, building only libm with + -fno-math-errno and all the remaining code with -fno-math-errno. This + should be safe as libm doesn't contain any code saving and restoring + errno around malloc. This patch can probably be reverted once the GCC + bug is fixed and available in stable releases. + + Tested on x86-64, no regression in the testsuite. + + Changelog: + [BZ #24024] + * Makeconfig: Build libm with -fno-math-errno but build the remaining + code with -fmath-errno. + * string/Makefile [$(build-shared)] (tests): Add test-strerror-errno. + [$(build-shared)] (LDLIBS-test-strerror-errno): New variable. + * string/test-strerror-errno.c: New file. + +diff --git a/Makeconfig b/Makeconfig +index 92e76d6200bbcd5b..8dc2fec9dc683416 100644 +--- a/Makeconfig ++++ b/Makeconfig +@@ -831,8 +831,10 @@ endif + # disable any optimization that assume default rounding mode. + +math-flags = -frounding-math + +-# Build libc/libm using -fno-math-errno, but run testsuite with -fmath-errno. +-+extra-math-flags = $(if $(filter libnldbl nonlib testsuite,$(in-module)),-fmath-errno,-fno-math-errno) ++# Logically only "libnldbl", "nonlib" and "testsuite" should be using ++# -fno-math-errno. However due to GCC bug #88576, only "libm" can use ++# -fno-math-errno. +++extra-math-flags = $(if $(filter libm,$(in-module)),-fno-math-errno,-fmath-errno) + + # We might want to compile with some stack-protection flag. + ifneq ($(stack-protector),) +diff --git a/string/Makefile b/string/Makefile +index 680431f92185f914..aa2da9ca72262886 100644 +--- a/string/Makefile ++++ b/string/Makefile +@@ -64,6 +64,12 @@ tests := tester inl-tester noinl-tester testcopy test-ffs \ + # This test allocates a lot of memory and can run for a long time. + xtests = tst-strcoll-overflow + ++# This test needs libdl. ++ifeq (yes,$(build-shared)) ++tests += test-strerror-errno ++LDLIBS-test-strerror-errno = $(libdl) ++endif ++ + ifeq ($(run-built-tests),yes) + tests-special += $(objpfx)tst-svc-cmp.out + endif +diff --git a/string/test-strerror-errno.c b/string/test-strerror-errno.c +new file mode 100644 +index 0000000000000000..8e744e7ed9df5924 +--- /dev/null ++++ b/string/test-strerror-errno.c +@@ -0,0 +1,61 @@ ++/* BZ #24024 strerror and errno test. ++ ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++/* malloc is allowed to change errno to a value different than 0, even when ++ there is no actual error. This happens for example when the memory ++ allocation through sbrk fails. Simulate this by interposing our own ++ malloc implementation which sets errno to ENOMEM and calls the original ++ malloc. */ ++void ++*malloc (size_t size) ++{ ++ static void *(*real_malloc) (size_t size); ++ ++ if (!real_malloc) ++ real_malloc = dlsym (RTLD_NEXT, "malloc"); ++ ++ errno = ENOMEM; ++ ++ return (*real_malloc) (size); ++} ++ ++/* strerror must not change the value of errno. Unfortunately due to GCC bug ++ #88576, this happens when -fmath-errno is used. This simple test checks ++ that it doesn't happen. */ ++static int ++do_test (void) ++{ ++ char *msg; ++ ++ errno = 0; ++ msg = strerror (-3); ++ (void) msg; ++ TEST_COMPARE (errno, 0); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1670043-1.patch b/glibc-rh1670043-1.patch new file mode 100755 index 0000000..73939d9 --- /dev/null +++ b/glibc-rh1670043-1.patch @@ -0,0 +1,104 @@ +commit 08504de71813ddbd447bfbca4a325cbe8ce8bcda +Author: Florian Weimer +Date: Tue Mar 12 11:40:47 2019 +0100 + + resolv: Enable full ICMP errors for UDP DNS sockets [BZ #24047] + + The Linux kernel suppresses some ICMP error messages by default for + UDP sockets. This commit enables full ICMP error reporting, + hopefully resulting in faster failover to working name servers. + +diff --git a/resolv/Makefile b/resolv/Makefile +index 8f22e6a154..ebe1b733f2 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -105,7 +105,7 @@ libresolv-routines := res_comp res_debug \ + res_data res_mkquery res_query res_send \ + inet_net_ntop inet_net_pton inet_neta base64 \ + ns_parse ns_name ns_netint ns_ttl ns_print \ +- ns_samedomain ns_date \ ++ ns_samedomain ns_date res_enable_icmp \ + compat-hooks compat-gethnamaddr + + libanl-routines := gai_cancel gai_error gai_misc gai_notify gai_suspend \ +diff --git a/resolv/res_enable_icmp.c b/resolv/res_enable_icmp.c +new file mode 100644 +index 0000000000..bdc9220f08 +--- /dev/null ++++ b/resolv/res_enable_icmp.c +@@ -0,0 +1,37 @@ ++/* Enable full ICMP errors on a socket. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++int ++__res_enable_icmp (int family, int fd) ++{ ++ int one = 1; ++ switch (family) ++ { ++ case AF_INET: ++ return setsockopt (fd, SOL_IP, IP_RECVERR, &one, sizeof (one)); ++ case AF_INET6: ++ return setsockopt (fd, SOL_IPV6, IPV6_RECVERR, &one, sizeof (one)); ++ default: ++ __set_errno (EAFNOSUPPORT); ++ return -1; ++ } ++} +diff --git a/resolv/res_send.c b/resolv/res_send.c +index fa040c1198..0f6ec83a7b 100644 +--- a/resolv/res_send.c ++++ b/resolv/res_send.c +@@ -943,6 +943,18 @@ reopen (res_state statp, int *terrno, int ns) + return (-1); + } + ++ /* Enable full ICMP error reporting for this ++ socket. */ ++ if (__res_enable_icmp (nsap->sa_family, ++ EXT (statp).nssocks[ns]) < 0) ++ { ++ int saved_errno = errno; ++ __res_iclose (statp, false); ++ __set_errno (saved_errno); ++ *terrno = saved_errno; ++ return -1; ++ } ++ + /* + * On a 4.3BSD+ machine (client and server, + * actually), sending to a nameserver datagram +diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h +index 6ab8f2af09..1500adc607 100644 +--- a/resolv/resolv-internal.h ++++ b/resolv/resolv-internal.h +@@ -100,4 +100,10 @@ libc_hidden_proto (__inet_pton_length) + /* Called as part of the thread shutdown sequence. */ + void __res_thread_freeres (void) attribute_hidden; + ++/* The Linux kernel does not enable all ICMP messages on a UDP socket ++ by default. A call this function enables full error reporting for ++ the socket FD. FAMILY must be AF_INET or AF_INET6. Returns 0 on ++ success, -1 on failure. */ ++int __res_enable_icmp (int family, int fd) attribute_hidden; ++ + #endif /* _RESOLV_INTERNAL_H */ diff --git a/glibc-rh1670043-2.patch b/glibc-rh1670043-2.patch new file mode 100755 index 0000000..d73d211 --- /dev/null +++ b/glibc-rh1670043-2.patch @@ -0,0 +1,47 @@ +commit 043440e761d395e1f507d9faa6e82b3fe4536c3f +Author: Florian Weimer +Date: Wed Mar 13 14:58:58 2019 +0100 + + hurd: Add no-op version of __res_enable_icmp [BZ #24047] + + Mach does not support IP_RECVERR, so replace this function with a + stub in a sysdeps override for Hurd. + + This fixes commit 08504de71813ddbd447bfbca4a325cbe8ce8bcda + ("resolv: Enable full ICMP errors for UDP DNS sockets [BZ #24047]"). + + Reviewed-by: Carlos O'Donell + +diff --git a/sysdeps/mach/hurd/res_enable_icmp.c b/sysdeps/mach/hurd/res_enable_icmp.c +new file mode 100644 +index 0000000000..4b0456340c +--- /dev/null ++++ b/sysdeps/mach/hurd/res_enable_icmp.c +@@ -0,0 +1,27 @@ ++/* Enable full ICMP errors on a socket. No-op version for Hurd. ++ 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 ++ . */ ++ ++/* Mach does not support the IP_RECVERR extension. */ ++ ++#include ++ ++int ++__res_enable_icmp (int family, int fd) ++{ ++ return 0; ++} diff --git a/glibc-rh1672773.patch b/glibc-rh1672773.patch new file mode 100755 index 0000000..1e34531 --- /dev/null +++ b/glibc-rh1672773.patch @@ -0,0 +1,199 @@ +commit 823624bdc47f1f80109c9c52dee7939b9386d708 +Author: Stefan Liebler +Date: Thu Feb 7 15:18:36 2019 +0100 + + Add compiler barriers around modifications of the robust mutex list for pthread_mutex_trylock. [BZ #24180] + + While debugging a kernel warning, Thomas Gleixner, Sebastian Sewior and + Heiko Carstens found a bug in pthread_mutex_trylock due to misordered + instructions: + 140: a5 1b 00 01 oill %r1,1 + 144: e5 48 a0 f0 00 00 mvghi 240(%r10),0 <--- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + 14a: e3 10 a0 e0 00 24 stg %r1,224(%r10) <--- last THREAD_SETMEM of ENQUEUE_MUTEX_PI + + vs (with compiler barriers): + 140: a5 1b 00 01 oill %r1,1 + 144: e3 10 a0 e0 00 24 stg %r1,224(%r10) + 14a: e5 48 a0 f0 00 00 mvghi 240(%r10),0 + + Please have a look at the discussion: + "Re: WARN_ON_ONCE(!new_owner) within wake_futex_pi() triggerede" + (https://lore.kernel.org/lkml/20190202112006.GB3381@osiris/) + + This patch is introducing the same compiler barriers and comments + for pthread_mutex_trylock as introduced for pthread_mutex_lock and + pthread_mutex_timedlock by commit 8f9450a0b7a9e78267e8ae1ab1000ebca08e473e + "Add compiler barriers around modifications of the robust mutex list." + + ChangeLog: + + [BZ #24180] + * nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock): + +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/glibc-rh1682954.patch b/glibc-rh1682954.patch new file mode 100755 index 0000000..4892f52 --- /dev/null +++ b/glibc-rh1682954.patch @@ -0,0 +1,545 @@ +From 0d3905b110000463775b3fb189213833acaebf81 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Mon, 1 Jul 2019 12:23:10 -0700 +Subject: Call _dl_open_check after relocation [BZ #24259] + +This is a workaround for [BZ #20839] which doesn't remove the NODELETE +object when _dl_open_check throws an exception. Move it after relocation +in dl_open_worker to avoid leaving the NODELETE object mapped without +relocation. + + [BZ #24259] + * elf/dl-open.c (dl_open_worker): Call _dl_open_check after + relocation. + * sysdeps/x86/Makefile (tests): Add tst-cet-legacy-5a, + tst-cet-legacy-5b, tst-cet-legacy-6a and tst-cet-legacy-6b. + (modules-names): Add tst-cet-legacy-mod-5a, tst-cet-legacy-mod-5b, + tst-cet-legacy-mod-5c, tst-cet-legacy-mod-6a, tst-cet-legacy-mod-6b + and tst-cet-legacy-mod-6c. + (CFLAGS-tst-cet-legacy-5a.c): New. + (CFLAGS-tst-cet-legacy-5b.c): Likewise. + (CFLAGS-tst-cet-legacy-mod-5a.c): Likewise. + (CFLAGS-tst-cet-legacy-mod-5b.c): Likewise. + (CFLAGS-tst-cet-legacy-mod-5c.c): Likewise. + (CFLAGS-tst-cet-legacy-6a.c): Likewise. + (CFLAGS-tst-cet-legacy-6b.c): Likewise. + (CFLAGS-tst-cet-legacy-mod-6a.c): Likewise. + (CFLAGS-tst-cet-legacy-mod-6b.c): Likewise. + (CFLAGS-tst-cet-legacy-mod-6c.c): Likewise. + ($(objpfx)tst-cet-legacy-5a): Likewise. + ($(objpfx)tst-cet-legacy-5a.out): Likewise. + ($(objpfx)tst-cet-legacy-mod-5a.so): Likewise. + ($(objpfx)tst-cet-legacy-mod-5b.so): Likewise. + ($(objpfx)tst-cet-legacy-5b): Likewise. + ($(objpfx)tst-cet-legacy-5b.out): Likewise. + (tst-cet-legacy-5b-ENV): Likewise. + ($(objpfx)tst-cet-legacy-6a): Likewise. + ($(objpfx)tst-cet-legacy-6a.out): Likewise. + ($(objpfx)tst-cet-legacy-mod-6a.so): Likewise. + ($(objpfx)tst-cet-legacy-mod-6b.so): Likewise. + ($(objpfx)tst-cet-legacy-6b): Likewise. + ($(objpfx)tst-cet-legacy-6b.out): Likewise. + (tst-cet-legacy-6b-ENV): Likewise. + * sysdeps/x86/tst-cet-legacy-5.c: New file. + * sysdeps/x86/tst-cet-legacy-5a.c: Likewise. + * sysdeps/x86/tst-cet-legacy-5b.c: Likewise. + * sysdeps/x86/tst-cet-legacy-6.c: Likewise. + * sysdeps/x86/tst-cet-legacy-6a.c: Likewise. + * sysdeps/x86/tst-cet-legacy-6b.c: Likewise. + * sysdeps/x86/tst-cet-legacy-mod-5.c: Likewise. + * sysdeps/x86/tst-cet-legacy-mod-5a.c: Likewise. + * sysdeps/x86/tst-cet-legacy-mod-5b.c: Likewise. + * sysdeps/x86/tst-cet-legacy-mod-5c.c: Likewise. + * sysdeps/x86/tst-cet-legacy-mod-6.c: Likewise. + * sysdeps/x86/tst-cet-legacy-mod-6a.c: Likewise. + * sysdeps/x86/tst-cet-legacy-mod-6b.c: Likewise. + * sysdeps/x86/tst-cet-legacy-mod-6c.c: Likewise. + +(cherry picked from commit d0093c5cefb7f7a4143f3bb03743633823229cc6) + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index f6c8ef1043..518a6cad69 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -292,8 +292,6 @@ dl_open_worker (void *a) + _dl_debug_state (); + LIBC_PROBE (map_complete, 3, args->nsid, r, new); + +- _dl_open_check (new); +- + /* Print scope information. */ + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_SCOPES)) + _dl_show_scope (new, 0); +@@ -366,6 +364,12 @@ dl_open_worker (void *a) + _dl_relocate_object (l, l->l_scope, reloc_mode, 0); + } + ++ /* NB: Workaround for [BZ #20839] which doesn't remove the NODELETE ++ object when _dl_open_check throws an exception. Move it after ++ relocation to avoid leaving the NODELETE object mapped without ++ relocation. */ ++ _dl_open_check (new); ++ + /* If the file is not loaded now as a dependency, add the search + list of the newly loaded object to the scope. */ + bool any_tls = false; +diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile +index 337b0b63dc..43ad4a79ff 100644 +--- a/sysdeps/x86/Makefile ++++ b/sysdeps/x86/Makefile +@@ -19,12 +19,17 @@ ifeq ($(subdir),elf) + sysdep-dl-routines += dl-cet + + tests += tst-cet-legacy-1 tst-cet-legacy-2 tst-cet-legacy-2a \ +- tst-cet-legacy-3 tst-cet-legacy-4 ++ tst-cet-legacy-3 tst-cet-legacy-4 \ ++ tst-cet-legacy-5a tst-cet-legacy-6a + ifneq (no,$(have-tunables)) +-tests += tst-cet-legacy-4a tst-cet-legacy-4b tst-cet-legacy-4c ++tests += tst-cet-legacy-4a tst-cet-legacy-4b tst-cet-legacy-4c \ ++ tst-cet-legacy-5b tst-cet-legacy-6b + endif + modules-names += tst-cet-legacy-mod-1 tst-cet-legacy-mod-2 \ +- tst-cet-legacy-mod-4 ++ tst-cet-legacy-mod-4 tst-cet-legacy-mod-5a \ ++ tst-cet-legacy-mod-5b tst-cet-legacy-mod-5c \ ++ tst-cet-legacy-mod-6a tst-cet-legacy-mod-6b \ ++ tst-cet-legacy-mod-6c + + CFLAGS-tst-cet-legacy-2.c += -fcf-protection=branch + CFLAGS-tst-cet-legacy-2a.c += -fcf-protection +@@ -35,6 +40,16 @@ CFLAGS-tst-cet-legacy-4.c += -fcf-protection=branch + CFLAGS-tst-cet-legacy-4a.c += -fcf-protection + CFLAGS-tst-cet-legacy-4b.c += -fcf-protection + CFLAGS-tst-cet-legacy-mod-4.c += -fcf-protection=none ++CFLAGS-tst-cet-legacy-5a.c += -fcf-protection ++CFLAGS-tst-cet-legacy-5b.c += -fcf-protection ++CFLAGS-tst-cet-legacy-mod-5a.c += -fcf-protection=none ++CFLAGS-tst-cet-legacy-mod-5b.c += -fcf-protection ++CFLAGS-tst-cet-legacy-mod-5c.c += -fcf-protection ++CFLAGS-tst-cet-legacy-6a.c += -fcf-protection ++CFLAGS-tst-cet-legacy-6b.c += -fcf-protection ++CFLAGS-tst-cet-legacy-mod-6a.c += -fcf-protection=none ++CFLAGS-tst-cet-legacy-mod-6b.c += -fcf-protection ++CFLAGS-tst-cet-legacy-mod-6c.c += -fcf-protection + + $(objpfx)tst-cet-legacy-1: $(objpfx)tst-cet-legacy-mod-1.so \ + $(objpfx)tst-cet-legacy-mod-2.so +@@ -44,6 +59,17 @@ $(objpfx)tst-cet-legacy-2a: $(objpfx)tst-cet-legacy-mod-2.so $(libdl) + $(objpfx)tst-cet-legacy-2a.out: $(objpfx)tst-cet-legacy-mod-1.so + $(objpfx)tst-cet-legacy-4: $(libdl) + $(objpfx)tst-cet-legacy-4.out: $(objpfx)tst-cet-legacy-mod-4.so ++$(objpfx)tst-cet-legacy-5a: $(libdl) ++$(objpfx)tst-cet-legacy-5a.out: $(objpfx)tst-cet-legacy-mod-5a.so \ ++ $(objpfx)tst-cet-legacy-mod-5b.so ++$(objpfx)tst-cet-legacy-mod-5a.so: $(objpfx)tst-cet-legacy-mod-5c.so ++$(objpfx)tst-cet-legacy-mod-5b.so: $(objpfx)tst-cet-legacy-mod-5c.so ++$(objpfx)tst-cet-legacy-6a: $(libdl) ++$(objpfx)tst-cet-legacy-6a.out: $(objpfx)tst-cet-legacy-mod-6a.so \ ++ $(objpfx)tst-cet-legacy-mod-6b.so ++$(objpfx)tst-cet-legacy-mod-6a.so: $(objpfx)tst-cet-legacy-mod-6c.so ++$(objpfx)tst-cet-legacy-mod-6b.so: $(objpfx)tst-cet-legacy-mod-6c.so ++LDFLAGS-tst-cet-legacy-mod-6c.so = -Wl,--enable-new-dtags,-z,nodelete + ifneq (no,$(have-tunables)) + $(objpfx)tst-cet-legacy-4a: $(libdl) + $(objpfx)tst-cet-legacy-4a.out: $(objpfx)tst-cet-legacy-mod-4.so +@@ -54,6 +80,14 @@ tst-cet-legacy-4b-ENV = GLIBC_TUNABLES=glibc.tune.x86_shstk=on + $(objpfx)tst-cet-legacy-4c: $(libdl) + $(objpfx)tst-cet-legacy-4c.out: $(objpfx)tst-cet-legacy-mod-4.so + tst-cet-legacy-4c-ENV = GLIBC_TUNABLES=glibc.tune.x86_shstk=off ++$(objpfx)tst-cet-legacy-5b: $(libdl) ++$(objpfx)tst-cet-legacy-5b.out: $(objpfx)tst-cet-legacy-mod-5a.so \ ++ $(objpfx)tst-cet-legacy-mod-5b.so ++tst-cet-legacy-5b-ENV = GLIBC_TUNABLES=glibc.tune.x86_ibt=off:glibc.tune.x86_shstk=off ++$(objpfx)tst-cet-legacy-6b: $(libdl) ++$(objpfx)tst-cet-legacy-6b.out: $(objpfx)tst-cet-legacy-mod-6a.so \ ++ $(objpfx)tst-cet-legacy-mod-6b.so ++tst-cet-legacy-6b-ENV = GLIBC_TUNABLES=glibc.tune.x86_ibt=off:glibc.tune.x86_shstk=off + endif + endif + +diff --git a/sysdeps/x86/tst-cet-legacy-5.c b/sysdeps/x86/tst-cet-legacy-5.c +new file mode 100644 +index 0000000000..fbf640f664 +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-5.c +@@ -0,0 +1,76 @@ ++/* Check compatibility of CET-enabled executable with dlopened legacy ++ shared object. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static void ++do_test_1 (const char *modname, bool fail) ++{ ++ int (*fp) (void); ++ void *h; ++ ++ h = dlopen (modname, RTLD_LAZY); ++ if (h == NULL) ++ { ++ if (fail) ++ { ++ const char *err = dlerror (); ++ if (strstr (err, "shadow stack isn't enabled") == NULL) ++ { ++ printf ("incorrect dlopen '%s' error: %s\n", modname, ++ dlerror ()); ++ exit (1); ++ } ++ ++ return; ++ } ++ ++ printf ("cannot open '%s': %s\n", modname, dlerror ()); ++ exit (1); ++ } ++ ++ fp = dlsym (h, "test"); ++ if (fp == NULL) ++ { ++ printf ("cannot get symbol 'test': %s\n", dlerror ()); ++ exit (1); ++ } ++ ++ if (fp () != 0) ++ { ++ puts ("test () != 0"); ++ exit (1); ++ } ++ ++ dlclose (h); ++} ++ ++static int ++do_test (void) ++{ ++ do_test_1 ("tst-cet-legacy-mod-5a.so", true); ++ do_test_1 ("tst-cet-legacy-mod-5b.so", false); ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/x86/tst-cet-legacy-5a.c b/sysdeps/x86/tst-cet-legacy-5a.c +new file mode 100644 +index 0000000000..fc5a609dff +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-5a.c +@@ -0,0 +1 @@ ++#include "tst-cet-legacy-5.c" +diff --git a/sysdeps/x86/tst-cet-legacy-5b.c b/sysdeps/x86/tst-cet-legacy-5b.c +new file mode 100644 +index 0000000000..fc5a609dff +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-5b.c +@@ -0,0 +1 @@ ++#include "tst-cet-legacy-5.c" +diff --git a/sysdeps/x86/tst-cet-legacy-6.c b/sysdeps/x86/tst-cet-legacy-6.c +new file mode 100644 +index 0000000000..9151225264 +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-6.c +@@ -0,0 +1,76 @@ ++/* Check compatibility of CET-enabled executable with dlopened legacy ++ shared object. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static void ++do_test_1 (const char *modname, bool fail) ++{ ++ int (*fp) (void); ++ void *h; ++ ++ h = dlopen (modname, RTLD_LAZY); ++ if (h == NULL) ++ { ++ if (fail) ++ { ++ const char *err = dlerror (); ++ if (strstr (err, "shadow stack isn't enabled") == NULL) ++ { ++ printf ("incorrect dlopen '%s' error: %s\n", modname, ++ dlerror ()); ++ exit (1); ++ } ++ ++ return; ++ } ++ ++ printf ("cannot open '%s': %s\n", modname, dlerror ()); ++ exit (1); ++ } ++ ++ fp = dlsym (h, "test"); ++ if (fp == NULL) ++ { ++ printf ("cannot get symbol 'test': %s\n", dlerror ()); ++ exit (1); ++ } ++ ++ if (fp () != 0) ++ { ++ puts ("test () != 0"); ++ exit (1); ++ } ++ ++ dlclose (h); ++} ++ ++static int ++do_test (void) ++{ ++ do_test_1 ("tst-cet-legacy-mod-6a.so", true); ++ do_test_1 ("tst-cet-legacy-mod-6b.so", false); ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/x86/tst-cet-legacy-6a.c b/sysdeps/x86/tst-cet-legacy-6a.c +new file mode 100644 +index 0000000000..2d1546d36b +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-6a.c +@@ -0,0 +1 @@ ++#include "tst-cet-legacy-6.c" +diff --git a/sysdeps/x86/tst-cet-legacy-6b.c b/sysdeps/x86/tst-cet-legacy-6b.c +new file mode 100644 +index 0000000000..2d1546d36b +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-6b.c +@@ -0,0 +1 @@ ++#include "tst-cet-legacy-6.c" +diff --git a/sysdeps/x86/tst-cet-legacy-mod-5.c b/sysdeps/x86/tst-cet-legacy-mod-5.c +new file mode 100644 +index 0000000000..3c1071c2ef +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-mod-5.c +@@ -0,0 +1,31 @@ ++/* Check compatibility of CET-enabled executable with dlopened legacy ++ shared object. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++extern void foo (void); ++ ++int ++test (void) ++{ ++ foo (); ++ return 0; ++} +diff --git a/sysdeps/x86/tst-cet-legacy-mod-5a.c b/sysdeps/x86/tst-cet-legacy-mod-5a.c +new file mode 100644 +index 0000000000..daa43e4e8d +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-mod-5a.c +@@ -0,0 +1 @@ ++#include "tst-cet-legacy-mod-5.c" +diff --git a/sysdeps/x86/tst-cet-legacy-mod-5b.c b/sysdeps/x86/tst-cet-legacy-mod-5b.c +new file mode 100644 +index 0000000000..daa43e4e8d +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-mod-5b.c +@@ -0,0 +1 @@ ++#include "tst-cet-legacy-mod-5.c" +diff --git a/sysdeps/x86/tst-cet-legacy-mod-5c.c b/sysdeps/x86/tst-cet-legacy-mod-5c.c +new file mode 100644 +index 0000000000..e529a42ac0 +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-mod-5c.c +@@ -0,0 +1,36 @@ ++/* Check compatibility of CET-enabled executable with dlopened legacy ++ shared object. ++ 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 ++ . */ ++ ++#include ++ ++static int called = 0; ++ ++static void ++__attribute__ ((constructor)) ++init (void) ++{ ++ called = 1; ++} ++ ++void ++foo (void) ++{ ++ if (!called) ++ abort (); ++} +diff --git a/sysdeps/x86/tst-cet-legacy-mod-6.c b/sysdeps/x86/tst-cet-legacy-mod-6.c +new file mode 100644 +index 0000000000..3c1071c2ef +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-mod-6.c +@@ -0,0 +1,31 @@ ++/* Check compatibility of CET-enabled executable with dlopened legacy ++ shared object. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++extern void foo (void); ++ ++int ++test (void) ++{ ++ foo (); ++ return 0; ++} +diff --git a/sysdeps/x86/tst-cet-legacy-mod-6a.c b/sysdeps/x86/tst-cet-legacy-mod-6a.c +new file mode 100644 +index 0000000000..c89b8fe8ff +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-mod-6a.c +@@ -0,0 +1 @@ ++#include "tst-cet-legacy-mod-6.c" +diff --git a/sysdeps/x86/tst-cet-legacy-mod-6b.c b/sysdeps/x86/tst-cet-legacy-mod-6b.c +new file mode 100644 +index 0000000000..c89b8fe8ff +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-mod-6b.c +@@ -0,0 +1 @@ ++#include "tst-cet-legacy-mod-6.c" +diff --git a/sysdeps/x86/tst-cet-legacy-mod-6c.c b/sysdeps/x86/tst-cet-legacy-mod-6c.c +new file mode 100644 +index 0000000000..e529a42ac0 +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-mod-6c.c +@@ -0,0 +1,36 @@ ++/* Check compatibility of CET-enabled executable with dlopened legacy ++ shared object. ++ 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 ++ . */ ++ ++#include ++ ++static int called = 0; ++ ++static void ++__attribute__ ((constructor)) ++init (void) ++{ ++ called = 1; ++} ++ ++void ++foo (void) ++{ ++ if (!called) ++ abort (); ++} +diff --git a/sysdeps/x86/tst-cet-legacy-mod-6d.c b/sysdeps/x86/tst-cet-legacy-mod-6d.c +new file mode 100644 +index 0000000000..eb233a1d10 +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-mod-6d.c +@@ -0,0 +1 @@ ++#include "tst-cet-legacy-mod-6c.c" diff --git a/glibc-rh1691528-1.patch b/glibc-rh1691528-1.patch new file mode 100755 index 0000000..9f07b78 --- /dev/null +++ b/glibc-rh1691528-1.patch @@ -0,0 +1,48 @@ +commit ac64195ccd4f320659fd0058bc7524c6fd0b37b4 +Author: DJ Delorie +Date: Wed Mar 20 23:56:59 2019 -0400 + + iconv, localedef: avoid floating point rounding differences [BZ #24372] + + Two cases of "int * 1.4" may result in imprecise results, which + in at least one case resulted in i686 and x86-64 producing + different locale files. This replaced that floating point multiply + with integer operations. While the hash table margin is increased + from 40% to 50%, testing shows only 2% increase in overall size + of the locale archive. + + https://bugzilla.redhat.com/show_bug.cgi?id=1311954 + + Reviewed-by: Carlos O'Donell + +diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c +index d5e8e714233f78d8..696fc8d31231ca2d 100644 +--- a/iconv/iconvconfig.c ++++ b/iconv/iconvconfig.c +@@ -1079,9 +1079,9 @@ write_output (void) + + /* Create the hashing table. We know how many strings we have. + Creating a perfect hash table is not reasonable here. Therefore +- we use open hashing and a table size which is the next prime 40% ++ we use open hashing and a table size which is the next prime 50% + larger than the number of strings. */ +- hash_size = next_prime (nnames * 1.4); ++ hash_size = next_prime (nnames + nnames >> 1); + hash_table = (struct hash_entry *) xcalloc (hash_size, + sizeof (struct hash_entry)); + /* Fill the hash table. */ +diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c +index d2eebcfdbb0677e5..9a1639b999d0e2aa 100644 +--- a/locale/programs/ld-collate.c ++++ b/locale/programs/ld-collate.c +@@ -2401,8 +2401,8 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap, + + runp = runp->next; + } +- /* Add 40% and find the next prime number. */ +- elem_size = next_prime (elem_size * 1.4); ++ /* Add 50% and find the next prime number. */ ++ elem_size = next_prime (elem_size + elem_size >> 1); + + /* Allocate the table. Each entry consists of two words: the hash + value and an index in a secondary table which provides the index diff --git a/glibc-rh1691528-2.patch b/glibc-rh1691528-2.patch new file mode 100755 index 0000000..568320e --- /dev/null +++ b/glibc-rh1691528-2.patch @@ -0,0 +1,49 @@ +commit 5abcddd7949270998c6e8d99fdbbba821b664f8b +Author: Gabriel F. T. Gomes +Date: Thu Mar 21 17:24:30 2019 -0300 + + Fix parentheses error in iconvconfig.c and ld-collate.c [BZ #24372] + + When -Werror=parentheses is in use, iconvconfig.c builds fail with: + + iconvconfig.c: In function ‘write_output’: + iconvconfig.c:1084:34: error: suggest parentheses around ‘+’ inside ‘>>’ [-Werror=parentheses] + hash_size = next_prime (nnames + nnames >> 1); + ~~~~~~~^~~~~~~~ + + This patch adds parentheses to the expression. Not where suggested by + the compiler warning, but where it produces the expected result, i.e.: + where it has the effect of multiplying nnames by 1.5. + + Likewise for elem_size in ld-collate.c. + + Tested for powerpc64le. + + Reviewed-by: Carlos O'Donell + +diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c +index 696fc8d31231ca2d..b6fef1553cbbdd3d 100644 +--- a/iconv/iconvconfig.c ++++ b/iconv/iconvconfig.c +@@ -1081,7 +1081,7 @@ write_output (void) + Creating a perfect hash table is not reasonable here. Therefore + we use open hashing and a table size which is the next prime 50% + larger than the number of strings. */ +- hash_size = next_prime (nnames + nnames >> 1); ++ hash_size = next_prime (nnames + (nnames >> 1)); + hash_table = (struct hash_entry *) xcalloc (hash_size, + sizeof (struct hash_entry)); + /* Fill the hash table. */ +diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c +index 9a1639b999d0e2aa..a5530655fd5638b5 100644 +--- a/locale/programs/ld-collate.c ++++ b/locale/programs/ld-collate.c +@@ -2402,7 +2402,7 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap, + runp = runp->next; + } + /* Add 50% and find the next prime number. */ +- elem_size = next_prime (elem_size + elem_size >> 1); ++ elem_size = next_prime (elem_size + (elem_size >> 1)); + + /* Allocate the table. Each entry consists of two words: the hash + value and an index in a secondary table which provides the index diff --git a/glibc-rh1699194-1.patch b/glibc-rh1699194-1.patch new file mode 100755 index 0000000..3db05de --- /dev/null +++ b/glibc-rh1699194-1.patch @@ -0,0 +1,23 @@ +commit 4e75c2a43bb3208f32556a2b19c939cfe1f54ba6 +Author: Florian Weimer +Date: Wed Jun 12 10:41:19 2019 +0200 + + : Add __glibc_has_include macro + +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index 3f6fe3cc8563b493..0500779d0c1b64c2 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -412,6 +412,12 @@ + # define __glibc_has_attribute(attr) 0 + #endif + ++#ifdef __has_include ++# define __glibc_has_include(header) __has_include (header) ++#else ++# define __glibc_has_include(header) 0 ++#endif ++ + #if (!defined _Noreturn \ + && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \ + && !__GNUC_PREREQ (4,7)) diff --git a/glibc-rh1699194-2.patch b/glibc-rh1699194-2.patch new file mode 100755 index 0000000..e292641 --- /dev/null +++ b/glibc-rh1699194-2.patch @@ -0,0 +1,383 @@ +commit 5dad6ffbb2b76215cfcd38c3001778536ada8e8a +Author: Florian Weimer +Date: Wed Jun 12 12:04:09 2019 +0200 + + : Use Linux UAPI header for statx if available and useful + + This will automatically import new STATX_* constants. It also avoids + a conflict between and . + +Conflicts: + io/bits/statx.h + (Year range in copyright header.) + +diff --git a/include/bits/statx-generic.h b/include/bits/statx-generic.h +new file mode 100644 +index 0000000000000000..21674721b6d85265 +--- /dev/null ++++ b/include/bits/statx-generic.h +@@ -0,0 +1 @@ ++#include +diff --git a/include/bits/types/struct_statx.h b/include/bits/types/struct_statx.h +new file mode 100644 +index 0000000000000000..82add6484f2ee963 +--- /dev/null ++++ b/include/bits/types/struct_statx.h +@@ -0,0 +1 @@ ++#include +diff --git a/include/bits/types/struct_statx_timestamp.h b/include/bits/types/struct_statx_timestamp.h +new file mode 100644 +index 0000000000000000..9fbedd5749fc1172 +--- /dev/null ++++ b/include/bits/types/struct_statx_timestamp.h +@@ -0,0 +1 @@ ++#include +diff --git a/io/Makefile b/io/Makefile +index ec5c6d7a2fb87914..787a5c550ab64b17 100644 +--- a/io/Makefile ++++ b/io/Makefile +@@ -25,7 +25,9 @@ include ../Makeconfig + headers := sys/stat.h bits/stat.h sys/statfs.h bits/statfs.h sys/vfs.h \ + sys/statvfs.h bits/statvfs.h fcntl.h sys/fcntl.h bits/fcntl.h \ + poll.h sys/poll.h bits/poll.h bits/fcntl2.h bits/poll2.h \ +- bits/statx.h utime.h ftw.h fts.h sys/sendfile.h ++ bits/statx.h bits/statx-generic.h bits/types/struct_statx.h \ ++ bits/types/struct_statx_timestamp.h \ ++ utime.h ftw.h fts.h sys/sendfile.h + + routines := \ + utime \ +diff --git a/io/bits/statx-generic.h b/io/bits/statx-generic.h +new file mode 100644 +index 0000000000000000..1f5abbf148681e9b +--- /dev/null ++++ b/io/bits/statx-generic.h +@@ -0,0 +1,60 @@ ++/* Generic statx-related definitions and declarations. ++ 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 ++ . */ ++ ++/* This interface is based on in Linux. */ ++ ++#ifndef _SYS_STAT_H ++# error Never include directly, include instead. ++#endif ++ ++#include ++#include ++ ++#ifndef STATX_TYPE ++# define STATX_TYPE 0x0001U ++# define STATX_MODE 0x0002U ++# define STATX_NLINK 0x0004U ++# define STATX_UID 0x0008U ++# define STATX_GID 0x0010U ++# define STATX_ATIME 0x0020U ++# define STATX_MTIME 0x0040U ++# define STATX_CTIME 0x0080U ++# define STATX_INO 0x0100U ++# define STATX_SIZE 0x0200U ++# define STATX_BLOCKS 0x0400U ++# define STATX_BASIC_STATS 0x07ffU ++# define STATX_ALL 0x0fffU ++# define STATX_BTIME 0x0800U ++# define STATX__RESERVED 0x80000000U ++ ++# define STATX_ATTR_COMPRESSED 0x0004 ++# define STATX_ATTR_IMMUTABLE 0x0010 ++# define STATX_ATTR_APPEND 0x0020 ++# define STATX_ATTR_NODUMP 0x0040 ++# define STATX_ATTR_ENCRYPTED 0x0800 ++# define STATX_ATTR_AUTOMOUNT 0x1000 ++#endif /* !STATX_TYPE */ ++ ++__BEGIN_DECLS ++ ++/* Fill *BUF with information about PATH in DIRFD. */ ++int statx (int __dirfd, const char *__restrict __path, int __flags, ++ unsigned int __mask, struct statx *__restrict __buf) ++ __THROW __nonnull ((2, 5)); ++ ++__END_DECLS +diff --git a/io/bits/statx.h b/io/bits/statx.h +index e31254e3617bb17b..b3147bfa8af1818f 100644 +--- a/io/bits/statx.h ++++ b/io/bits/statx.h +@@ -1,5 +1,5 @@ +-/* statx-related definitions and declarations. +- Copyright (C) 2018 Free Software Foundation, Inc. ++/* statx-related definitions and declarations. Generic version. ++ 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 +@@ -19,73 +19,8 @@ + /* This interface is based on in Linux. */ + + #ifndef _SYS_STAT_H +-# error Never include directly, include instead. ++# error Never include directly, include instead. + #endif + +-struct statx_timestamp +-{ +- __int64_t tv_sec; +- __uint32_t tv_nsec; +- __int32_t __statx_timestamp_pad1[1]; +-}; +- +-/* Warning: The kernel may add additional fields to this struct in the +- future. Only use this struct for calling the statx function, not +- for storing data. (Expansion will be controlled by the mask +- argument of the statx function.) */ +-struct statx +-{ +- __uint32_t stx_mask; +- __uint32_t stx_blksize; +- __uint64_t stx_attributes; +- __uint32_t stx_nlink; +- __uint32_t stx_uid; +- __uint32_t stx_gid; +- __uint16_t stx_mode; +- __uint16_t __statx_pad1[1]; +- __uint64_t stx_ino; +- __uint64_t stx_size; +- __uint64_t stx_blocks; +- __uint64_t stx_attributes_mask; +- struct statx_timestamp stx_atime; +- struct statx_timestamp stx_btime; +- struct statx_timestamp stx_ctime; +- struct statx_timestamp stx_mtime; +- __uint32_t stx_rdev_major; +- __uint32_t stx_rdev_minor; +- __uint32_t stx_dev_major; +- __uint32_t stx_dev_minor; +- __uint64_t __statx_pad2[14]; +-}; +- +-#define STATX_TYPE 0x0001U +-#define STATX_MODE 0x0002U +-#define STATX_NLINK 0x0004U +-#define STATX_UID 0x0008U +-#define STATX_GID 0x0010U +-#define STATX_ATIME 0x0020U +-#define STATX_MTIME 0x0040U +-#define STATX_CTIME 0x0080U +-#define STATX_INO 0x0100U +-#define STATX_SIZE 0x0200U +-#define STATX_BLOCKS 0x0400U +-#define STATX_BASIC_STATS 0x07ffU +-#define STATX_ALL 0x0fffU +-#define STATX_BTIME 0x0800U +-#define STATX__RESERVED 0x80000000U +- +-#define STATX_ATTR_COMPRESSED 0x0004 +-#define STATX_ATTR_IMMUTABLE 0x0010 +-#define STATX_ATTR_APPEND 0x0020 +-#define STATX_ATTR_NODUMP 0x0040 +-#define STATX_ATTR_ENCRYPTED 0x0800 +-#define STATX_ATTR_AUTOMOUNT 0x1000 +- +-__BEGIN_DECLS +- +-/* Fill *BUF with information about PATH in DIRFD. */ +-int statx (int __dirfd, const char *__restrict __path, int __flags, +- unsigned int __mask, struct statx *__restrict __buf) +- __THROW __nonnull ((2, 5)); +- +-__END_DECLS ++/* Use the generic definitions. */ ++#include +diff --git a/io/bits/types/struct_statx.h b/io/bits/types/struct_statx.h +new file mode 100644 +index 0000000000000000..4f3ae3ece62a0ad2 +--- /dev/null ++++ b/io/bits/types/struct_statx.h +@@ -0,0 +1,55 @@ ++/* Definition of the generic version of struct statx. ++ 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 ++ . */ ++ ++#ifndef _SYS_STAT_H ++# error Never include directly, include instead. ++#endif ++ ++#ifndef __statx_defined ++#define __statx_defined 1 ++ ++/* Warning: The kernel may add additional fields to this struct in the ++ future. Only use this struct for calling the statx function, not ++ for storing data. (Expansion will be controlled by the mask ++ argument of the statx function.) */ ++struct statx ++{ ++ __uint32_t stx_mask; ++ __uint32_t stx_blksize; ++ __uint64_t stx_attributes; ++ __uint32_t stx_nlink; ++ __uint32_t stx_uid; ++ __uint32_t stx_gid; ++ __uint16_t stx_mode; ++ __uint16_t __statx_pad1[1]; ++ __uint64_t stx_ino; ++ __uint64_t stx_size; ++ __uint64_t stx_blocks; ++ __uint64_t stx_attributes_mask; ++ struct statx_timestamp stx_atime; ++ struct statx_timestamp stx_btime; ++ struct statx_timestamp stx_ctime; ++ struct statx_timestamp stx_mtime; ++ __uint32_t stx_rdev_major; ++ __uint32_t stx_rdev_minor; ++ __uint32_t stx_dev_major; ++ __uint32_t stx_dev_minor; ++ __uint64_t __statx_pad2[14]; ++}; ++ ++#endif /* __statx_defined */ +diff --git a/io/bits/types/struct_statx_timestamp.h b/io/bits/types/struct_statx_timestamp.h +new file mode 100644 +index 0000000000000000..0f104ef84ed7d356 +--- /dev/null ++++ b/io/bits/types/struct_statx_timestamp.h +@@ -0,0 +1,33 @@ ++/* Definition of the generic version of struct statx_timestamp. ++ 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 ++ . */ ++ ++#ifndef _SYS_STAT_H ++# error Never include directly, include instead. ++#endif ++ ++#ifndef __statx_timestamp_defined ++#define __statx_timestamp_defined 1 ++ ++struct statx_timestamp ++{ ++ __int64_t tv_sec; ++ __uint32_t tv_nsec; ++ __int32_t __statx_timestamp_pad1[1]; ++}; ++ ++#endif /* __statx_timestamp_defined */ +diff --git a/io/statx_generic.c b/io/statx_generic.c +index df327f8c525f748c..987c84fb45f5db63 100644 +--- a/io/statx_generic.c ++++ b/io/statx_generic.c +@@ -18,9 +18,16 @@ + + #include + #include ++#include + #include + #include + ++/* Obtain the original definition of struct statx. */ ++#undef __statx_defined ++#define statx original_statx ++#include ++#undef statx ++ + static inline struct statx_timestamp + statx_convert_timestamp (struct timespec tv) + { +@@ -57,7 +64,7 @@ statx_generic (int fd, const char *path, int flags, + /* The interface is defined in such a way that unused (padding) + fields have to be cleared. STATX_BASIC_STATS corresponds to the + data which is available via fstatat64. */ +- *buf = (struct statx) ++ struct original_statx obuf = + { + .stx_mask = STATX_BASIC_STATS, + .stx_blksize = st.st_blksize, +@@ -76,6 +83,8 @@ statx_generic (int fd, const char *path, int flags, + .stx_dev_major = major (st.st_dev), + .stx_dev_minor = minor (st.st_dev), + }; ++ _Static_assert (sizeof (*buf) >= sizeof (obuf), "struct statx size"); ++ memcpy (buf, &obuf, sizeof (obuf)); + + return 0; + } +diff --git a/sysdeps/unix/sysv/linux/bits/statx.h b/sysdeps/unix/sysv/linux/bits/statx.h +new file mode 100644 +index 0000000000000000..d36f44efc60a0bed +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/bits/statx.h +@@ -0,0 +1,34 @@ ++/* statx-related definitions and declarations. Linux version. ++ 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 ++ . */ ++ ++/* This interface is based on in Linux. */ ++ ++#ifndef _SYS_STAT_H ++# error Never include directly, include instead. ++#endif ++ ++/* Use the Linux kernel header if available. */ ++#if __glibc_has_include () ++# include ++# ifdef STATX_TYPE ++# define __statx_timestamp_defined 1 ++# define __statx_defined 1 ++# endif ++#endif ++ ++#include diff --git a/glibc-rh1699194-3.patch b/glibc-rh1699194-3.patch new file mode 100755 index 0000000..ced417e --- /dev/null +++ b/glibc-rh1699194-3.patch @@ -0,0 +1,28 @@ +commit 8d141877e07cc594e9fefc3795b8ba729288093c +Author: Florian Weimer +Date: Fri Jun 14 15:46:02 2019 +0200 + + : Inhibit macro expansion for __glibc_has_include + + This is currently ineffective with GCC because of GCC PR 80005, but + it makes sense to anticipate a fix for this defect. + + Suggested by Zack Weinberg. + + Reviewed-by: Carlos O'Donell + +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index 0500779d0c1b64c2..9e840e602f815d86 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -413,7 +413,9 @@ + #endif + + #ifdef __has_include +-# define __glibc_has_include(header) __has_include (header) ++/* Do not use a function-like macro, so that __has_include can inhibit ++ macro expansion. */ ++# define __glibc_has_include __has_include + #else + # define __glibc_has_include(header) 0 + #endif diff --git a/glibc-rh1699194-4.patch b/glibc-rh1699194-4.patch new file mode 100755 index 0000000..1892855 --- /dev/null +++ b/glibc-rh1699194-4.patch @@ -0,0 +1,37 @@ +commit 48c3c1238925410b4e777dc94e2fde4cc9132d44 +Author: Florian Weimer +Date: Fri Jun 14 16:28:41 2019 +0200 + + Linux: Fix __glibc_has_include use for and statx + + The identifier linux is used as a predefined macro, so the actually + used path is 1/stat.h or 1/stat64.h. Using the quote-based version + triggers a file lookup for /usr/include/bits/linux/stat.h (or whatever + directory is used to store bits/statx.h), but since bits/ is pretty + much reserved by glibc, this appears to be acceptable. + + This is related to GCC PR 80005: incorrect macro expansion of the + argument of __has_include. + + Suggested by Zack Weinberg. + + Reviewed-by: Carlos O'Donell + +diff --git a/sysdeps/unix/sysv/linux/bits/statx.h b/sysdeps/unix/sysv/linux/bits/statx.h +index d36f44efc60a0bed..206878723fd37881 100644 +--- a/sysdeps/unix/sysv/linux/bits/statx.h ++++ b/sysdeps/unix/sysv/linux/bits/statx.h +@@ -23,8 +23,11 @@ + #endif + + /* Use the Linux kernel header if available. */ +-#if __glibc_has_include () +-# include ++ ++/* Use "" to work around incorrect macro expansion of the ++ __has_include argument (GCC PR 80005). */ ++#if __glibc_has_include ("linux/stat.h") ++# include "linux/stat.h" + # ifdef STATX_TYPE + # define __statx_timestamp_defined 1 + # define __statx_defined 1 diff --git a/glibc-rh1701605-1.patch b/glibc-rh1701605-1.patch new file mode 100755 index 0000000..b21720c --- /dev/null +++ b/glibc-rh1701605-1.patch @@ -0,0 +1,298 @@ +commit e485b2b6e006a7efa5d73e6be7e357a395c77fe3 +Author: Florian Weimer +Date: Tue Apr 23 18:16:26 2019 +0200 + + locale: Add LOCPATH diagnostics to the locale program + + The implementation of quote_string is based on support_quote_blob. + + Reviewed-by: Carlos O'Donell + +diff --git a/locale/Makefile b/locale/Makefile +index fd9972279ba7fe0b..42bb36c7d374eebe 100644 +--- a/locale/Makefile ++++ b/locale/Makefile +@@ -28,6 +28,7 @@ routines = setlocale findlocale loadlocale loadarchive \ + localeconv nl_langinfo nl_langinfo_l mb_cur_max \ + newlocale duplocale freelocale uselocale + tests = tst-C-locale tst-locname tst-duplocale ++tests-special = $(objpfx)tst-locale-locpath.out + categories = ctype messages monetary numeric time paper name \ + address telephone measurement identification collate + aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name \ +@@ -104,3 +105,7 @@ cpp-srcs-left := $(localedef-modules) $(localedef-aux) $(locale-modules) \ + $(lib-modules) + lib := locale-programs + include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left)) ++ ++$(objpfx)tst-locale-locpath.out : tst-locale-locpath.sh $(objpfx)locale ++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' '$(test-wrapper-env)' > $@; \ ++ $(evaluate-test) +diff --git a/locale/programs/locale.c b/locale/programs/locale.c +index 86941e4ef6e67d78..0e2e3e4e5788246f 100644 +--- a/locale/programs/locale.c ++++ b/locale/programs/locale.c +@@ -173,6 +173,9 @@ static int write_archive_locales (void **all_datap, char *linebuf); + static void write_charmaps (void); + static void show_locale_vars (void); + static void show_info (const char *name); ++static void try_setlocale (int category, const char *category_name); ++static char *quote_string (const char *input); ++static void setlocale_diagnostics (void); + + + int +@@ -186,10 +189,8 @@ main (int argc, char *argv[]) + + /* Set locale. Do not set LC_ALL because the other categories must + not be affected (according to POSIX.2). */ +- if (setlocale (LC_CTYPE, "") == NULL) +- error (0, errno, gettext ("Cannot set LC_CTYPE to default locale")); +- if (setlocale (LC_MESSAGES, "") == NULL) +- error (0, errno, gettext ("Cannot set LC_MESSAGES to default locale")); ++ try_setlocale (LC_CTYPE, "LC_CTYPE"); ++ try_setlocale (LC_MESSAGES, "LC_MESSAGES"); + + /* Initialize the message catalog. */ + textdomain (PACKAGE); +@@ -200,9 +201,8 @@ main (int argc, char *argv[]) + /* `-a' requests the names of all available locales. */ + if (do_all != 0) + { +- if (setlocale (LC_COLLATE, "") == NULL) +- error (0, errno, +- gettext ("Cannot set LC_COLLATE to default locale")); ++ setlocale_diagnostics (); ++ try_setlocale (LC_COLLATE, "LC_COLLATE"); + write_locales (); + exit (EXIT_SUCCESS); + } +@@ -211,14 +211,15 @@ main (int argc, char *argv[]) + used for the -f argument to localedef(1). */ + if (do_charmaps != 0) + { ++ setlocale_diagnostics (); + write_charmaps (); + exit (EXIT_SUCCESS); + } + + /* Specific information about the current locale are requested. + Change to this locale now. */ +- if (setlocale (LC_ALL, "") == NULL) +- error (0, errno, gettext ("Cannot set LC_ALL to default locale")); ++ try_setlocale (LC_ALL, "LC_ALL"); ++ setlocale_diagnostics (); + + /* If no real argument is given we have to print the contents of the + current locale definition variables. These are LANG and the LC_*. */ +@@ -983,3 +984,121 @@ show_info (const char *name) + For testing and perhaps advanced use allow some more symbols. */ + locale_special (name, show_category_name, show_keyword_name); + } ++ ++/* Set to true by try_setlocale if setlocale fails. Used by ++ setlocale_diagnostics. */ ++static bool setlocale_failed; ++ ++/* Call setlocale, with non-fatal error reporting. */ ++static void ++try_setlocale (int category, const char *category_name) ++{ ++ if (setlocale (category, "") == NULL) ++ { ++ error (0, errno, gettext ("Cannot set %s to default locale"), ++ category_name); ++ setlocale_failed = true; ++ } ++} ++ ++/* Return a quoted version of the passed string, or NULL on error. */ ++static char * ++quote_string (const char *input) ++{ ++ char *buffer; ++ size_t length; ++ FILE *stream = open_memstream (&buffer, &length); ++ if (stream == NULL) ++ return NULL; ++ ++ while (true) ++ { ++ unsigned char ch = *input++; ++ if (ch == '\0') ++ break; ++ ++ /* Use C backslash escapes for those control characters for ++ which they are defined. */ ++ switch (ch) ++ { ++ case '\a': ++ putc_unlocked ('\\', stream); ++ putc_unlocked ('a', stream); ++ break; ++ case '\b': ++ putc_unlocked ('\\', stream); ++ putc_unlocked ('b', stream); ++ break; ++ case '\f': ++ putc_unlocked ('\\', stream); ++ putc_unlocked ('f', stream); ++ break; ++ case '\n': ++ putc_unlocked ('\\', stream); ++ putc_unlocked ('n', stream); ++ break; ++ case '\r': ++ putc_unlocked ('\\', stream); ++ putc_unlocked ('r', stream); ++ break; ++ case '\t': ++ putc_unlocked ('\\', stream); ++ putc_unlocked ('t', stream); ++ break; ++ case '\v': ++ putc_unlocked ('\\', stream); ++ putc_unlocked ('v', stream); ++ break; ++ case '\\': ++ case '\'': ++ case '\"': ++ putc_unlocked ('\\', stream); ++ putc_unlocked (ch, stream); ++ break; ++ default: ++ if (ch < ' ' || ch > '~') ++ /* Use octal sequences because they are fixed width, ++ unlike hexadecimal sequences. */ ++ fprintf (stream, "\\%03o", ch); ++ else ++ putc_unlocked (ch, stream); ++ } ++ } ++ ++ if (ferror (stream)) ++ { ++ fclose (stream); ++ free (buffer); ++ return NULL; ++ } ++ if (fclose (stream) != 0) ++ { ++ free (buffer); ++ return NULL; ++ } ++ ++ return buffer; ++} ++ ++/* Print additional information if there was a setlocale error (during ++ try_setlocale). */ ++static void ++setlocale_diagnostics (void) ++{ ++ if (setlocale_failed) ++ { ++ const char *locpath = getenv ("LOCPATH"); ++ if (locpath != NULL) ++ { ++ char *quoted = quote_string (locpath); ++ if (quoted != NULL) ++ fprintf (stderr, ++ gettext ("\ ++warning: The LOCPATH variable is set to \"%s\"\n"), ++ quoted); ++ else ++ fputs ("warning: The LOCPATH variable is set\n", stderr); ++ free (quoted); ++ } ++ } ++} +diff --git a/locale/tst-locale-locpath.sh b/locale/tst-locale-locpath.sh +new file mode 100644 +index 0000000000000000..b83de90a39121af6 +--- /dev/null ++++ b/locale/tst-locale-locpath.sh +@@ -0,0 +1,83 @@ ++#!/bin/sh ++# Test that locale prints LOCPATH on failure. ++# 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 ++# . ++ ++set -ex ++ ++common_objpfx=$1 ++test_wrapper_env=$2 ++run_program_env=$3 ++ ++LIBPATH="$common_objpfx" ++ ++testroot="${common_objpfx}locale/tst-locale-locpath-directory" ++cleanup () { ++ rm -rf "$testroot" ++} ++trap cleanup 0 ++ ++rm -rf "$testroot" ++mkdir -p $testroot ++ ++unset LANG ++ ++${test_wrapper_env} \ ++${run_program_env} LC_ALL=invalid-locale LOCPATH=does-not-exist \ ++${common_objpfx}elf/ld.so --library-path "$LIBPATH" \ ++ "${common_objpfx}locale/locale" \ ++ > "$testroot/stdout" 2> "$testroot/stderr" ++ ++echo "* standard error" ++cat "$testroot/stderr" ++echo "* standard output" ++cat "$testroot/stdout" ++ ++cat > "$testroot/stderr-expected" < "$testroot/stdout-expected" < +Date: Wed Apr 24 07:31:29 2019 +0200 + + locale/tst-locale-locpath: Run test only for $(run-built-tests) == yes + +diff --git a/locale/Makefile b/locale/Makefile +index 42bb36c7d374eebe..23a71321b6646c49 100644 +--- a/locale/Makefile ++++ b/locale/Makefile +@@ -28,7 +28,6 @@ routines = setlocale findlocale loadlocale loadarchive \ + localeconv nl_langinfo nl_langinfo_l mb_cur_max \ + newlocale duplocale freelocale uselocale + tests = tst-C-locale tst-locname tst-duplocale +-tests-special = $(objpfx)tst-locale-locpath.out + categories = ctype messages monetary numeric time paper name \ + address telephone measurement identification collate + aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name \ +@@ -61,6 +60,10 @@ lib-modules := charmap-dir simple-hash xmalloc xstrdup \ + GPERF = gperf + GPERFFLAGS = -acCgopt -k1,2,5,9,$$ -L ANSI-C + ++ifeq ($(run-built-tests),yes) ++tests-special += $(objpfx)tst-locale-locpath.out ++endif ++ + include ../Rules + + CFLAGS-md5.c += -I../crypt diff --git a/glibc-rh1702539-1.patch b/glibc-rh1702539-1.patch new file mode 100755 index 0000000..8023b6c --- /dev/null +++ b/glibc-rh1702539-1.patch @@ -0,0 +1,789 @@ +This patch is a rework of the following upstream patch: + +commit 0e169691290a6d2187a4ff41495fc5678cbfdcdc +Author: Adhemerval Zanella +Date: Fri Apr 12 17:39:53 2019 -0300 + + support: Add support_capture_subprogram + + Its API is similar to support_capture_subprocess, but rather creates a + new process based on the input path and arguments. Under the hoods it + uses posix_spawn to create the new process. + + It also allows the use of other support_capture_* functions to check + for expected results and free the resources. + + Checked on x86_64-linux-gnu. + + * 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. + + Reviewed-by: Carlos O'Donell + + + +diff -Nrup a/support/capture_subprocess.h b/support/capture_subprocess.h +--- a/support/capture_subprocess.h 2018-08-01 01:10:47.000000000 -0400 ++++ b/support/capture_subprocess.h 2019-05-16 23:37:19.903845257 -0400 +@@ -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 -Nrup a/support/Makefile b/support/Makefile +--- a/support/Makefile 2019-05-16 23:36:51.066665814 -0400 ++++ b/support/Makefile 2019-05-17 10:31:24.268313761 -0400 +@@ -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 \ +@@ -147,6 +148,9 @@ libsupport-routines = \ + xsigaction \ + xsignal \ + xsocket \ ++ xposix_spawn \ ++ xposix_spawn_file_actions_addclose \ ++ xposix_spawn_file_actions_adddup2 \ + xstrdup \ + xstrndup \ + xsymlink \ +@@ -221,4 +225,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 -Nrup a/support/subprocess.h b/support/subprocess.h +--- a/support/subprocess.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/support/subprocess.h 2019-05-16 23:37:19.903845257 -0400 +@@ -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 ++ . */ ++ ++#ifndef SUPPORT_SUBPROCESS_H ++#define SUPPORT_SUBPROCESS_H ++ ++#include ++ ++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 -Nrup a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c +--- a/support/support_capture_subprocess.c 2019-05-16 23:36:50.672677025 -0400 ++++ b/support/support_capture_subprocess.c 2019-05-16 23:38:34.298728367 -0400 +@@ -16,6 +16,7 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + + #include +@@ -23,6 +24,7 @@ + #include + #include + #include ++#include + + static void + transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream) +@@ -50,59 +52,52 @@ transfer (const char *what, struct pollf + } + } + +-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); ++ ++ 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); + +- xfclose_memstream (&result.out); +- xfclose_memstream (&result.err); +- xwaitpid (pid, &result.status, 0); ++ support_capture_poll (&result, &proc); + return result; + } + +diff -Nrup a/support/support_subprocess.c b/support/support_subprocess.c +--- a/support/support_subprocess.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/support/support_subprocess.c 2019-05-16 23:37:19.903845257 -0400 +@@ -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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 -Nrup a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c +--- a/support/tst-support_capture_subprocess.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/support/tst-support_capture_subprocess.c 2019-05-16 23:37:19.904845228 -0400 +@@ -23,8 +23,20 @@ + #include + #include + #include ++#include + #include + #include ++#include ++#include ++#include ++#include ++#include ++ ++/* 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 f + 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 st + } + } + ++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); + if (test.signal != 0) +@@ -185,4 +302,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 +diff -Nrup a/support/xposix_spawn.c b/support/xposix_spawn.c +--- a/support/xposix_spawn.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/support/xposix_spawn.c 2019-05-16 23:37:19.904845228 -0400 +@@ -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 ++ . */ ++ ++#include ++#include ++ ++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 -Nrup a/support/xposix_spawn_file_actions_addclose.c b/support/xposix_spawn_file_actions_addclose.c +--- a/support/xposix_spawn_file_actions_addclose.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/support/xposix_spawn_file_actions_addclose.c 2019-05-16 23:37:19.904845228 -0400 +@@ -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 ++ . */ ++ ++#include ++#include ++ ++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 -Nrup a/support/xposix_spawn_file_actions_adddup2.c b/support/xposix_spawn_file_actions_adddup2.c +--- a/support/xposix_spawn_file_actions_adddup2.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/support/xposix_spawn_file_actions_adddup2.c 2019-05-16 23:37:19.904845228 -0400 +@@ -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 ++ . */ ++ ++#include ++#include ++ ++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 -Nrup a/support/xspawn.h b/support/xspawn.h +--- a/support/xspawn.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/support/xspawn.h 2019-05-16 23:37:19.904845228 -0400 +@@ -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 ++ . */ ++ ++#ifndef SUPPORT_XSPAWN_H ++#define SUPPORT_XSPAWN_H ++ ++#include ++ ++__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/glibc-rh1702539-2.patch b/glibc-rh1702539-2.patch new file mode 100755 index 0000000..1c1b8bb --- /dev/null +++ b/glibc-rh1702539-2.patch @@ -0,0 +1,558 @@ +This patch is a rework of the following upstream patch: + +commit 1a4c27355e146b6d8cc6487b998462c7fdd1048f +Author: Adhemerval Zanella +Date: Thu Apr 11 18:12:00 2019 -0300 + + elf: Fix pldd (BZ#18035) + + Since 9182aa67994 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map + for executable itself and loader will have both l_name and l_libname->name + holding the same value due: + + elf/dl-object.c + + 95 new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1; + + Since newname->name points to new->l_libname->name. + + This leads to pldd to an infinite call at: + + elf/pldd-xx.c + + 203 again: + 204 while (1) + 205 { + 206 ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset); + + 228 /* Try the l_libname element. */ + 229 struct E(libname_list) ln; + 230 if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln)) + 231 { + 232 name_offset = ln.name; + 233 goto again; + 234 } + + Since the value at ln.name (l_libname->name) will be the same as previously + read. The straightforward fix is just avoid the check and read the new list + entry. + + I checked also against binaries issues with old loaders with fix for BZ#387, + and pldd could dump the shared objects. + + Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and + powerpc64le-linux-gnu. + +diff -Nrup a/elf/Makefile b/elf/Makefile +--- a/elf/Makefile 2019-05-17 12:35:12.663074766 -0400 ++++ b/elf/Makefile 2019-05-17 12:35:45.816147975 -0400 +@@ -201,6 +201,7 @@ tests-internal += loadtest unload unload + neededtest neededtest2 neededtest3 neededtest4 \ + tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \ + tst-ptrguard1 tst-stackguard1 tst-libc_dlvsym ++tests-container += tst-pldd + ifeq ($(build-hardcoded-path-in-tests),yes) + tests += tst-dlopen-aout + tst-dlopen-aout-no-pie = yes +diff -Nrup a/elf/pldd.c b/elf/pldd.c +--- a/elf/pldd.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/elf/pldd.c 2019-05-17 12:35:45.817147947 -0400 +@@ -17,23 +17,17 @@ + License along with the GNU C Library; if not, see + . */ + +-#include ++#define _FILE_OFFSET_BITS 64 ++ + #include +-#include + #include +-#include +-#include + #include + #include + #include +-#include +-#include + #include + #include +-#include + #include + #include +-#include + #include + #include + +@@ -76,14 +70,8 @@ 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 +90,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 +109,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 *) ""; ++ /* Default stack allocation is at least 1024. */ ++ snprintf (exe.data, exe.length, ""); + 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 +144,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 +171,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 +179,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 +275,10 @@ warranty; not even for MERCHANTABILITY o + + + 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//mem file. */ ++ int memfd = openat (dfd, "mem", O_RDONLY); + if (memfd == -1) + goto no_info; + +@@ -333,9 +328,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 -Nrup a/elf/pldd-xx.c b/elf/pldd-xx.c +--- a/elf/pldd-xx.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/elf/pldd-xx.c 2019-05-17 13:05:29.587147445 -0400 +@@ -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, siz + 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, siz + 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, siz + } + 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, siz + 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, siz + 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, siz + } + while (list != 0); + +- out: + scratch_buffer_free (&tmpbuf); + return status; + } +diff -Nrup a/elf/tst-pldd.c b/elf/tst-pldd.c +--- a/elf/tst-pldd.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/elf/tst-pldd.c 2019-05-17 12:35:45.817147947 -0400 +@@ -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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++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 : */ ++ 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 diff --git a/glibc-rh1704868-1.patch b/glibc-rh1704868-1.patch new file mode 100755 index 0000000..324aaf1 --- /dev/null +++ b/glibc-rh1704868-1.patch @@ -0,0 +1,1365 @@ +commit 91927b7c76437db860cd86a7714476b56bb39d07 +Author: Arjun Shankar +Date: Tue Jul 7 20:31:48 2020 +0200 + + Rewrite iconv option parsing [BZ #19519] + + This commit replaces string manipulation during `iconv_open' and iconv_prog + option parsing with a structured, flag based conversion specification. In + doing so, it alters the internal `__gconv_open' interface and accordingly + adjusts its uses. + + This change fixes several hangs in the iconv program and therefore includes + a new test to exercise iconv_prog options that originally led to these hangs. + It also includes a new regression test for option handling in the iconv + function. + + Reviewed-by: Florian Weimer + Reviewed-by: Siddhesh Poyarekar + Reviewed-by: Carlos O'Donell + +diff --git a/iconv/Makefile b/iconv/Makefile +index d71319b39e772fde..d09b8ac842731780 100644 +--- a/iconv/Makefile ++++ b/iconv/Makefile +@@ -26,7 +26,7 @@ headers = iconv.h gconv.h + routines = iconv_open iconv iconv_close \ + gconv_open gconv gconv_close gconv_db gconv_conf \ + gconv_builtin gconv_simple gconv_trans gconv_cache +-routines += gconv_dl ++routines += gconv_dl gconv_charset + + vpath %.c ../locale/programs ../intl + +@@ -43,7 +43,8 @@ CFLAGS-charmap.c += -DCHARMAP_PATH='"$(i18ndir)/charmaps"' \ + CFLAGS-linereader.c += -DNO_TRANSLITERATION + CFLAGS-simple-hash.c += -I../locale + +-tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 ++tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 \ ++ tst-iconv-opt + + others = iconv_prog iconvconfig + install-others-programs = $(inst_bindir)/iconv +@@ -60,6 +61,7 @@ include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left)) + + ifeq ($(run-built-tests),yes) + xtests-special += $(objpfx)test-iconvconfig.out ++tests-special += $(objpfx)tst-iconv_prog.out + endif + + # Make a copy of the file because gconv module names are constructed +@@ -78,6 +80,13 @@ endif + + include ../Rules + ++ifeq ($(run-built-tests),yes) ++LOCALES := en_US.UTF-8 ++include ../gen-locales.mk ++ ++$(objpfx)tst-iconv-opt.out: $(gen-locales) ++endif ++ + $(inst_bindir)/iconv: $(objpfx)iconv_prog $(+force) + $(do-install-program) + +@@ -92,3 +101,8 @@ $(objpfx)test-iconvconfig.out: /dev/null $(objpfx)iconvconfig + cmp $$tmp $(inst_gconvdir)/gconv-modules.cache; \ + rm -f $$tmp) > $@; \ + $(evaluate-test) ++ ++$(objpfx)tst-iconv_prog.out: tst-iconv_prog.sh $(objpfx)iconv_prog ++ $(BASH) $< $(common-objdir) '$(test-wrapper-env)' \ ++ '$(run-program-env)' > $@; \ ++ $(evaluate-test) +diff --git a/iconv/Versions b/iconv/Versions +index 60ab10a277588515..8a5f4cf780b18925 100644 +--- a/iconv/Versions ++++ b/iconv/Versions +@@ -6,6 +6,7 @@ libc { + GLIBC_PRIVATE { + # functions shared with iconv program + __gconv_get_alias_db; __gconv_get_cache; __gconv_get_modules_db; ++ __gconv_open; __gconv_create_spec; + + # function used by the gconv modules + __gconv_transliterate; +diff --git a/iconv/gconv_charset.c b/iconv/gconv_charset.c +new file mode 100644 +index 0000000000000000..6ccd0773ccb6cd27 +--- /dev/null ++++ b/iconv/gconv_charset.c +@@ -0,0 +1,218 @@ ++/* Charset name normalization. ++ Copyright (C) 2020 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 ++ . */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "gconv_int.h" ++#include "gconv_charset.h" ++ ++ ++/* This function returns a pointer to the last suffix in a conversion code ++ string. Valid suffixes matched by this function are of the form: '/' or ',' ++ followed by arbitrary text that doesn't contain '/' or ','. It does not ++ edit the string in any way. The caller is expected to parse the suffix and ++ remove it (by e.g. truncating the string) before the next call. */ ++static char * ++find_suffix (char *s) ++{ ++ /* The conversion code is in the form of a triplet, separated by '/' chars. ++ The third component of the triplet contains suffixes. If we don't have two ++ slashes, we don't have a suffix. */ ++ ++ int slash_count = 0; ++ char *suffix_term = NULL; ++ ++ for (int i = 0; s[i] != '\0'; i++) ++ switch (s[i]) ++ { ++ case '/': ++ slash_count++; ++ /* Fallthrough */ ++ case ',': ++ suffix_term = &s[i]; ++ } ++ ++ if (slash_count >= 2) ++ return suffix_term; ++ ++ return NULL; ++} ++ ++ ++struct gconv_parsed_code ++{ ++ char *code; ++ bool translit; ++ bool ignore; ++}; ++ ++ ++/* This function parses an iconv_open encoding PC.CODE, strips any suffixes ++ (such as TRANSLIT or IGNORE) from it and sets corresponding flags in it. */ ++static void ++gconv_parse_code (struct gconv_parsed_code *pc) ++{ ++ pc->translit = false; ++ pc->ignore = false; ++ ++ while (1) ++ { ++ /* First drop any trailing whitespaces and separators. */ ++ size_t len = strlen (pc->code); ++ while ((len > 0) ++ && (isspace (pc->code[len - 1]) ++ || pc->code[len - 1] == ',' ++ || pc->code[len - 1] == '/')) ++ len--; ++ ++ pc->code[len] = '\0'; ++ ++ if (len == 0) ++ return; ++ ++ char * suffix = find_suffix (pc->code); ++ if (suffix == NULL) ++ { ++ /* At this point, we have processed and removed all suffixes from the ++ code and what remains of the code is suffix free. */ ++ return; ++ } ++ else ++ { ++ /* A suffix is processed from the end of the code array going ++ backwards, one suffix at a time. The suffix is an index into the ++ code character array and points to: one past the end of the code ++ and any unprocessed suffixes, and to the beginning of the suffix ++ currently being processed during this iteration. We must process ++ this suffix and then drop it from the code by terminating the ++ preceding text with NULL. ++ ++ We want to allow and recognize suffixes such as: ++ ++ "/TRANSLIT" i.e. single suffix ++ "//TRANSLIT" i.e. single suffix and multiple separators ++ "//TRANSLIT/IGNORE" i.e. suffixes separated by "/" ++ "/TRANSLIT//IGNORE" i.e. suffixes separated by "//" ++ "//IGNORE,TRANSLIT" i.e. suffixes separated by "," ++ "//IGNORE," i.e. trailing "," ++ "//TRANSLIT/" i.e. trailing "/" ++ "//TRANSLIT//" i.e. trailing "//" ++ "/" i.e. empty suffix. ++ ++ Unknown suffixes are silently discarded and ignored. */ ++ ++ if ((__strcasecmp_l (suffix, ++ GCONV_TRIPLE_SEPARATOR ++ GCONV_TRANSLIT_SUFFIX, ++ _nl_C_locobj_ptr) == 0) ++ || (__strcasecmp_l (suffix, ++ GCONV_SUFFIX_SEPARATOR ++ GCONV_TRANSLIT_SUFFIX, ++ _nl_C_locobj_ptr) == 0)) ++ pc->translit = true; ++ ++ if ((__strcasecmp_l (suffix, ++ GCONV_TRIPLE_SEPARATOR ++ GCONV_IGNORE_ERRORS_SUFFIX, ++ _nl_C_locobj_ptr) == 0) ++ || (__strcasecmp_l (suffix, ++ GCONV_SUFFIX_SEPARATOR ++ GCONV_IGNORE_ERRORS_SUFFIX, ++ _nl_C_locobj_ptr) == 0)) ++ pc->ignore = true; ++ ++ /* We just processed this suffix. We can now drop it from the ++ code string by truncating it at the suffix's position. */ ++ suffix[0] = '\0'; ++ } ++ } ++} ++ ++ ++/* This function accepts the charset names of the source and destination of the ++ conversion and populates *conv_spec with an equivalent conversion ++ specification that may later be used by __gconv_open. The charset names ++ might contain options in the form of suffixes that alter the conversion, ++ e.g. "ISO-10646/UTF-8/TRANSLIT". It processes the charset names, ignoring ++ and truncating any suffix options in fromcode, and processing and truncating ++ any suffix options in tocode. Supported suffix options ("TRANSLIT" or ++ "IGNORE") when found in tocode lead to the corresponding flag in *conv_spec ++ to be set to true. Unrecognized suffix options are silently discarded. If ++ the function succeeds, it returns conv_spec back to the caller. It returns ++ NULL upon failure. conv_spec must be allocated and freed by the caller. */ ++struct gconv_spec * ++__gconv_create_spec (struct gconv_spec *conv_spec, const char *fromcode, ++ const char *tocode) ++{ ++ struct gconv_parsed_code pfc, ptc; ++ struct gconv_spec *ret = NULL; ++ ++ pfc.code = __strdup (fromcode); ++ ptc.code = __strdup (tocode); ++ ++ if ((pfc.code == NULL) ++ || (ptc.code == NULL)) ++ goto out; ++ ++ gconv_parse_code (&pfc); ++ gconv_parse_code (&ptc); ++ ++ /* We ignore suffixes in the fromcode because that is how the current ++ implementation has always handled them. Only suffixes in the tocode are ++ processed and handled. The reality is that invalid input in the input ++ character set should only be ignored if the fromcode specifies IGNORE. ++ The current implementation ignores invalid intput in the input character ++ set if the tocode contains IGNORE. We preserve this behavior for ++ backwards compatibility. In the future we may split the handling of ++ IGNORE to allow a finer grained specification of ignorning invalid input ++ and/or ignoring invalid output. */ ++ conv_spec->translit = ptc.translit; ++ conv_spec->ignore = ptc.ignore; ++ ++ /* 3 extra bytes because 1 extra for '\0', and 2 extra so strip might ++ be able to add one or two trailing '/' characters if necessary. */ ++ conv_spec->fromcode = malloc (strlen (fromcode) + 3); ++ if (conv_spec->fromcode == NULL) ++ goto out; ++ ++ conv_spec->tocode = malloc (strlen (tocode) + 3); ++ if (conv_spec->tocode == NULL) ++ { ++ free (conv_spec->fromcode); ++ conv_spec->fromcode = NULL; ++ goto out; ++ } ++ ++ /* Strip unrecognized characters and ensure that the code has two '/' ++ characters as per conversion code triplet specification. */ ++ strip (conv_spec->fromcode, pfc.code); ++ strip (conv_spec->tocode, ptc.code); ++ ret = conv_spec; ++ ++out: ++ free (pfc.code); ++ free (ptc.code); ++ ++ return ret; ++} ++libc_hidden_def (__gconv_create_spec) +diff --git a/iconv/gconv_charset.h b/iconv/gconv_charset.h +index 123e2a62cefdc017..b85d80313030b649 100644 +--- a/iconv/gconv_charset.h ++++ b/iconv/gconv_charset.h +@@ -19,9 +19,68 @@ + + #include + #include ++#include ++#include ++#include ++#include ++#include "gconv_int.h" + + +-static void ++/* An iconv encoding is in the form of a triplet, with parts separated by ++ a '/' character. The first part is the standard name, the second part is ++ the character set, and the third part is the error handler. If the first ++ part is sufficient to identify both the standard and the character set ++ then the second part can be empty e.g. UTF-8//. If the first part is not ++ sufficient to identify both the standard and the character set then the ++ second part is required e.g. ISO-10646/UTF8/. If neither the first or ++ second parts are provided e.g. //, then the current locale is used. ++ The actual values used in the first and second parts are not entirely ++ relevant to the implementation. The values themselves are used in a hash ++ table to lookup modules and so the naming convention of the first two parts ++ is somewhat arbitrary and only helps locate the entries in the cache. ++ The third part is the error handler and is comprised of a ',' or '/' ++ separated list of suffixes. Currently, we support "TRANSLIT" for ++ transliteration and "IGNORE" for ignoring conversion errors due to ++ unrecognized input characters. */ ++#define GCONV_TRIPLE_SEPARATOR "/" ++#define GCONV_SUFFIX_SEPARATOR "," ++#define GCONV_TRANSLIT_SUFFIX "TRANSLIT" ++#define GCONV_IGNORE_ERRORS_SUFFIX "IGNORE" ++ ++ ++/* This function accepts the charset names of the source and destination of the ++ conversion and populates *conv_spec with an equivalent conversion ++ specification that may later be used by __gconv_open. The charset names ++ might contain options in the form of suffixes that alter the conversion, ++ e.g. "ISO-10646/UTF-8/TRANSLIT". It processes the charset names, ignoring ++ and truncating any suffix options in fromcode, and processing and truncating ++ any suffix options in tocode. Supported suffix options ("TRANSLIT" or ++ "IGNORE") when found in tocode lead to the corresponding flag in *conv_spec ++ to be set to true. Unrecognized suffix options are silently discarded. If ++ the function succeeds, it returns conv_spec back to the caller. It returns ++ NULL upon failure. */ ++struct gconv_spec * ++__gconv_create_spec (struct gconv_spec *conv_spec, const char *fromcode, ++ const char *tocode); ++libc_hidden_proto (__gconv_create_spec) ++ ++ ++/* This function frees all heap memory allocated by __gconv_create_spec. */ ++static void __attribute__ ((unused)) ++gconv_destroy_spec (struct gconv_spec *conv_spec) ++{ ++ free (conv_spec->fromcode); ++ free (conv_spec->tocode); ++ return; ++} ++ ++ ++/* This function copies in-order, characters from the source 's' that are ++ either alpha-numeric or one in one of these: "_-.,:/" - into the destination ++ 'wp' while dropping all other characters. In the process, it converts all ++ alphabetical characters to upper case. It then appends up to two '/' ++ characters so that the total number of '/'es in the destination is 2. */ ++static inline void __attribute__ ((unused, always_inline)) + strip (char *wp, const char *s) + { + int slash_count = 0; +diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h +index 3742557caed05c9a..4748e9b1fa3b5426 100644 +--- a/iconv/gconv_int.h ++++ b/iconv/gconv_int.h +@@ -92,6 +92,15 @@ struct gconv_module + }; + + ++/* The specification of the conversion that needs to be performed. */ ++struct gconv_spec ++{ ++ char *fromcode; ++ char *tocode; ++ bool translit; ++ bool ignore; ++}; ++ + /* Flags for `gconv_open'. */ + enum + { +@@ -154,10 +163,12 @@ __libc_lock_define (extern, __gconv_lock attribute_hidden) + }) + + +-/* Return in *HANDLE decriptor for transformation from FROMSET to TOSET. */ +-extern int __gconv_open (const char *toset, const char *fromset, +- __gconv_t *handle, int flags) +- attribute_hidden; ++/* Return in *HANDLE, a decriptor for the transformation. The function expects ++ the specification of the transformation in the structure pointed to by ++ CONV_SPEC. It only reads *CONV_SPEC and does not take ownership of it. */ ++extern int __gconv_open (struct gconv_spec *conv_spec, ++ __gconv_t *handle, int flags); ++libc_hidden_proto (__gconv_open) + + /* Free resources associated with transformation descriptor CD. */ + extern int __gconv_close (__gconv_t cd) +diff --git a/iconv/gconv_open.c b/iconv/gconv_open.c +index f739561f6edba8a8..002faa111a0b9016 100644 +--- a/iconv/gconv_open.c ++++ b/iconv/gconv_open.c +@@ -27,7 +27,7 @@ + + + int +-__gconv_open (const char *toset, const char *fromset, __gconv_t *handle, ++__gconv_open (struct gconv_spec *conv_spec, __gconv_t *handle, + int flags) + { + struct __gconv_step *steps; +@@ -36,77 +36,38 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle, + size_t cnt = 0; + int res; + int conv_flags = 0; +- const char *errhand; +- const char *ignore; + bool translit = false; ++ char *tocode, *fromcode; + + /* Find out whether any error handling method is specified. */ +- errhand = strchr (toset, '/'); +- if (errhand != NULL) +- errhand = strchr (errhand + 1, '/'); +- if (__glibc_likely (errhand != NULL)) +- { +- if (*++errhand == '\0') +- errhand = NULL; +- else +- { +- /* Make copy without the error handling description. */ +- char *newtoset = (char *) alloca (errhand - toset + 1); +- char *tok; +- char *ptr = NULL /* Work around a bogus warning */; +- +- newtoset[errhand - toset] = '\0'; +- toset = memcpy (newtoset, toset, errhand - toset); ++ translit = conv_spec->translit; + +- /* Find the appropriate transliteration handlers. */ +- tok = strdupa (errhand); ++ if (conv_spec->ignore) ++ conv_flags |= __GCONV_IGNORE_ERRORS; + +- tok = __strtok_r (tok, ",", &ptr); +- while (tok != NULL) +- { +- if (__strcasecmp_l (tok, "TRANSLIT", _nl_C_locobj_ptr) == 0) +- translit = true; +- else if (__strcasecmp_l (tok, "IGNORE", _nl_C_locobj_ptr) == 0) +- /* Set the flag to ignore all errors. */ +- conv_flags |= __GCONV_IGNORE_ERRORS; +- +- tok = __strtok_r (NULL, ",", &ptr); +- } +- } +- } +- +- /* For the source character set we ignore the error handler specification. +- XXX Is this really always the best? */ +- ignore = strchr (fromset, '/'); +- if (ignore != NULL && (ignore = strchr (ignore + 1, '/')) != NULL +- && *++ignore != '\0') +- { +- char *newfromset = (char *) alloca (ignore - fromset + 1); +- +- newfromset[ignore - fromset] = '\0'; +- fromset = memcpy (newfromset, fromset, ignore - fromset); +- } ++ tocode = conv_spec->tocode; ++ fromcode = conv_spec->fromcode; + + /* If the string is empty define this to mean the charset of the + currently selected locale. */ +- if (strcmp (toset, "//") == 0) ++ if (strcmp (tocode, "//") == 0) + { + const char *codeset = _NL_CURRENT (LC_CTYPE, CODESET); + size_t len = strlen (codeset); + char *dest; +- toset = dest = (char *) alloca (len + 3); ++ tocode = dest = (char *) alloca (len + 3); + memcpy (__mempcpy (dest, codeset, len), "//", 3); + } +- if (strcmp (fromset, "//") == 0) ++ if (strcmp (fromcode, "//") == 0) + { + const char *codeset = _NL_CURRENT (LC_CTYPE, CODESET); + size_t len = strlen (codeset); + char *dest; +- fromset = dest = (char *) alloca (len + 3); ++ fromcode = dest = (char *) alloca (len + 3); + memcpy (__mempcpy (dest, codeset, len), "//", 3); + } + +- res = __gconv_find_transform (toset, fromset, &steps, &nsteps, flags); ++ res = __gconv_find_transform (tocode, fromcode, &steps, &nsteps, flags); + if (res == __GCONV_OK) + { + /* Allocate room for handle. */ +@@ -205,3 +166,4 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle, + *handle = result; + return res; + } ++libc_hidden_def (__gconv_open) +diff --git a/iconv/iconv_open.c b/iconv/iconv_open.c +index 9f5c32c02096254a..59d1ef4f07ed1022 100644 +--- a/iconv/iconv_open.c ++++ b/iconv/iconv_open.c +@@ -31,49 +31,15 @@ + iconv_t + iconv_open (const char *tocode, const char *fromcode) + { +- /* Normalize the name. We remove all characters beside alpha-numeric, +- '_', '-', '/', '.', and ':'. */ +- size_t tocode_len = strlen (tocode) + 3; +- char *tocode_conv; +- bool tocode_usealloca = __libc_use_alloca (tocode_len); +- if (tocode_usealloca) +- tocode_conv = (char *) alloca (tocode_len); +- else +- { +- tocode_conv = (char *) malloc (tocode_len); +- if (tocode_conv == NULL) +- return (iconv_t) -1; +- } +- strip (tocode_conv, tocode); +- tocode = (tocode_conv[2] == '\0' && tocode[0] != '\0' +- ? upstr (tocode_conv, tocode) : tocode_conv); ++ __gconv_t cd; ++ struct gconv_spec conv_spec; + +- size_t fromcode_len = strlen (fromcode) + 3; +- char *fromcode_conv; +- bool fromcode_usealloca = __libc_use_alloca (fromcode_len); +- if (fromcode_usealloca) +- fromcode_conv = (char *) alloca (fromcode_len); +- else +- { +- fromcode_conv = (char *) malloc (fromcode_len); +- if (fromcode_conv == NULL) +- { +- if (! tocode_usealloca) +- free (tocode_conv); +- return (iconv_t) -1; +- } +- } +- strip (fromcode_conv, fromcode); +- fromcode = (fromcode_conv[2] == '\0' && fromcode[0] != '\0' +- ? upstr (fromcode_conv, fromcode) : fromcode_conv); ++ if (__gconv_create_spec (&conv_spec, fromcode, tocode) == NULL) ++ return (iconv_t) -1; + +- __gconv_t cd; +- int res = __gconv_open (tocode, fromcode, &cd, 0); ++ int res = __gconv_open (&conv_spec, &cd, 0); + +- if (! fromcode_usealloca) +- free (fromcode_conv); +- if (! tocode_usealloca) +- free (tocode_conv); ++ gconv_destroy_spec (&conv_spec); + + if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK) + { +diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c +index 52e9d3f3ddec3b2e..552efac81660e82a 100644 +--- a/iconv/iconv_prog.c ++++ b/iconv/iconv_prog.c +@@ -39,6 +39,7 @@ + #include + #include "iconv_prog.h" + #include "iconvconfig.h" ++#include "gconv_charset.h" + + /* Get libc version number. */ + #include "../version.h" +@@ -118,8 +119,7 @@ main (int argc, char *argv[]) + { + int status = EXIT_SUCCESS; + int remaining; +- iconv_t cd; +- const char *orig_to_code; ++ __gconv_t cd; + struct charmap_t *from_charmap = NULL; + struct charmap_t *to_charmap = NULL; + +@@ -139,39 +139,6 @@ main (int argc, char *argv[]) + exit (EXIT_SUCCESS); + } + +- /* If we have to ignore errors make sure we use the appropriate name for +- the to-character-set. */ +- orig_to_code = to_code; +- if (omit_invalid) +- { +- const char *errhand = strchrnul (to_code, '/'); +- int nslash = 2; +- char *newp; +- char *cp; +- +- if (*errhand == '/') +- { +- --nslash; +- errhand = strchrnul (errhand + 1, '/'); +- +- if (*errhand == '/') +- { +- --nslash; +- errhand = strchr (errhand, '\0'); +- } +- } +- +- newp = (char *) alloca (errhand - to_code + nslash + 7 + 1); +- cp = mempcpy (newp, to_code, errhand - to_code); +- while (nslash-- > 0) +- *cp++ = '/'; +- if (cp[-1] != '/') +- *cp++ = ','; +- memcpy (cp, "IGNORE", sizeof ("IGNORE")); +- +- to_code = newp; +- } +- + /* POSIX 1003.2b introduces a silly thing: the arguments to -t anf -f + can be file names of charmaps. In this case iconv will have to read + those charmaps and use them to do the conversion. But there are +@@ -184,10 +151,10 @@ main (int argc, char *argv[]) + file. */ + from_charmap = charmap_read (from_code, /*0, 1*/1, 0, 0, 0); + +- if (strchr (orig_to_code, '/') != NULL) ++ if (strchr (to_code, '/') != NULL) + /* The to-name might be a charmap file name. Try reading the + file. */ +- to_charmap = charmap_read (orig_to_code, /*0, 1,*/1, 0, 0, 0); ++ to_charmap = charmap_read (to_code, /*0, 1,*/1, 0, 0, 0); + + + /* At this point we have to handle two cases. The first one is +@@ -201,9 +168,25 @@ main (int argc, char *argv[]) + argc, remaining, argv, output_file); + else + { ++ struct gconv_spec conv_spec; ++ int res; ++ ++ if (__gconv_create_spec (&conv_spec, from_code, to_code) == NULL) ++ { ++ error (EXIT_FAILURE, errno, ++ _("failed to start conversion processing")); ++ exit (1); ++ } ++ ++ if (omit_invalid) ++ conv_spec.ignore = true; ++ + /* Let's see whether we have these coded character sets. */ +- cd = iconv_open (to_code, from_code); +- if (cd == (iconv_t) -1) ++ res = __gconv_open (&conv_spec, &cd, 0); ++ ++ gconv_destroy_spec (&conv_spec); ++ ++ if (res != __GCONV_OK) + { + if (errno == EINVAL) + { +@@ -221,7 +204,7 @@ main (int argc, char *argv[]) + const char *from_pretty = + (from_code[0] ? from_code : nl_langinfo (CODESET)); + const char *to_pretty = +- (orig_to_code[0] ? orig_to_code : nl_langinfo (CODESET)); ++ (to_code[0] ? to_code : nl_langinfo (CODESET)); + + if (from_wrong) + { +diff --git a/iconv/tst-iconv-opt.c b/iconv/tst-iconv-opt.c +new file mode 100644 +index 0000000000000000..669d812a6a9b8749 +--- /dev/null ++++ b/iconv/tst-iconv-opt.c +@@ -0,0 +1,347 @@ ++/* Test iconv's TRANSLIT and IGNORE option handling ++ ++ Copyright (C) 2020 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 ++ . */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++/* Run one iconv test. Arguments: ++ to: destination character set and options ++ from: source character set ++ input: input string to be converted ++ exp_in: expected number of bytes consumed ++ exp_ret: expected return value (error or number of irreversible conversions) ++ exp_out: expected output string ++ exp_err: expected value of `errno' after iconv returns. */ ++static void ++test_iconv (const char *to, const char *from, char *input, size_t exp_in, ++ size_t exp_ret, const char *exp_out, int exp_err) ++{ ++ iconv_t cd; ++ char outbuf[500]; ++ size_t inlen, outlen; ++ char *inptr, *outptr; ++ size_t n; ++ ++ cd = iconv_open (to, from); ++ TEST_VERIFY (cd != (iconv_t) -1); ++ ++ inlen = strlen (input); ++ outlen = sizeof (outbuf); ++ inptr = input; ++ outptr = outbuf; ++ ++ errno = 0; ++ n = iconv (cd, &inptr, &inlen, &outptr, &outlen); ++ ++ TEST_COMPARE (n, exp_ret); ++ TEST_VERIFY (inptr == input + exp_in); ++ TEST_COMPARE (errno, exp_err); ++ TEST_COMPARE_BLOB (outbuf, outptr - outbuf, exp_out, strlen (exp_out)); ++ TEST_VERIFY (iconv_close (cd) == 0); ++} ++ ++ ++/* We test option parsing by converting UTF-8 inputs to ASCII under various ++ option combinations. The UTF-8 inputs fall into three categories: ++ - ASCII-only, ++ - non-ASCII, ++ - non-ASCII with invalid UTF-8 characters. */ ++ ++/* 1. */ ++char ascii[] = "Just some ASCII text"; ++ ++/* 2. Valid UTF-8 input and some corresponding expected outputs with various ++ options. The two non-ASCII characters below are accented alphabets: ++ an `a' then an `o'. */ ++char utf8[] = "UTF-8 text with \u00E1 couple \u00F3f non-ASCII characters"; ++char u2a[] = "UTF-8 text with "; ++char u2a_translit[] = "UTF-8 text with a couple of non-ASCII characters"; ++char u2a_ignore[] = "UTF-8 text with couple f non-ASCII characters"; ++ ++/* 3. Invalid UTF-8 input and some corresponding expected outputs. \xff is ++ invalid UTF-8. It's followed by some valid but non-ASCII UTF-8. */ ++char iutf8[] = "Invalid UTF-8 \xff\u27E6text\u27E7"; ++char iu2a[] = "Invalid UTF-8 "; ++char iu2a_ignore[] = "Invalid UTF-8 text"; ++char iu2a_both[] = "Invalid UTF-8 [|text|]"; ++ ++/* 4. Another invalid UTF-8 input and corresponding expected outputs. This time ++ the valid non-ASCII UTF-8 characters appear before the invalid \xff. */ ++char jutf8[] = "Invalid \u27E6UTF-8\u27E7 \xfftext"; ++char ju2a[] = "Invalid "; ++char ju2a_translit[] = "Invalid [|UTF-8|] "; ++char ju2a_ignore[] = "Invalid UTF-8 text"; ++char ju2a_both[] = "Invalid [|UTF-8|] text"; ++ ++/* We also test option handling for character set names that have the form ++ "A/B". In this test, we test conversions "ISO-10646/UTF-8", and either ++ ISO-8859-1 or ASCII. */ ++ ++/* 5. Accented 'A' and 'a' characters in ISO-8859-1 and UTF-8, and an ++ equivalent ASCII transliteration. */ ++char iso8859_1_a[] = {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, /* Accented A's. */ ++ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, /* Accented a's. */ ++ 0x00}; ++char utf8_a[] = "\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5" ++ "\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5"; ++char ascii_a[] = "AAAAAAaaaaaa"; ++ ++/* 6. An invalid ASCII string where [0] is invalid and [1] is '~'. */ ++char iascii [] = {0x80, '~', '\0'}; ++char empty[] = ""; ++char ia2u_ignore[] = "~"; ++ ++static int ++do_test (void) ++{ ++ xsetlocale (LC_ALL, "en_US.UTF-8"); ++ ++ ++ /* 0. iconv_open should gracefully fail for invalid character sets. */ ++ ++ TEST_VERIFY (iconv_open ("INVALID", "UTF-8") == (iconv_t) -1); ++ TEST_VERIFY (iconv_open ("UTF-8", "INVALID") == (iconv_t) -1); ++ TEST_VERIFY (iconv_open ("INVALID", "INVALID") == (iconv_t) -1); ++ ++ ++ /* 1. ASCII-only UTF-8 input should convert to ASCII with no changes: */ ++ ++ test_iconv ("ASCII", "UTF-8", ascii, strlen (ascii), 0, ascii, 0); ++ test_iconv ("ASCII//", "UTF-8", ascii, strlen (ascii), 0, ascii, 0); ++ test_iconv ("ASCII//TRANSLIT", "UTF-8", ascii, strlen (ascii), 0, ascii, 0); ++ test_iconv ("ASCII//TRANSLIT//", "UTF-8", ascii, strlen (ascii), 0, ascii, ++ 0); ++ test_iconv ("ASCII//IGNORE", "UTF-8", ascii, strlen (ascii), 0, ascii, 0); ++ test_iconv ("ASCII//IGNORE//", "UTF-8", ascii, strlen (ascii), 0, ascii, 0); ++ ++ ++ /* 2. Valid UTF-8 input with non-ASCII characters: */ ++ ++ /* EILSEQ when converted to ASCII. */ ++ test_iconv ("ASCII", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a, EILSEQ); ++ ++ /* Converted without error with TRANSLIT enabled. */ ++ test_iconv ("ASCII//TRANSLIT", "UTF-8", utf8, strlen (utf8), 2, u2a_translit, ++ 0); ++ ++ /* EILSEQ with IGNORE enabled. Non-ASCII chars dropped from output. */ ++ test_iconv ("ASCII//IGNORE", "UTF-8", utf8, strlen (utf8), (size_t) -1, ++ u2a_ignore, EILSEQ); ++ ++ /* With TRANSLIT and IGNORE enabled, transliterated without error. We test ++ four combinations. */ ++ ++ test_iconv ("ASCII//TRANSLIT,IGNORE", "UTF-8", utf8, strlen (utf8), 2, ++ u2a_translit, 0); ++ test_iconv ("ASCII//TRANSLIT//IGNORE", "UTF-8", utf8, strlen (utf8), 2, ++ u2a_translit, 0); ++ test_iconv ("ASCII//IGNORE,TRANSLIT", "UTF-8", utf8, strlen (utf8), 2, ++ u2a_translit, 0); ++ /* Due to bug 19519, iconv was ignoring TRANSLIT for the following input. */ ++ test_iconv ("ASCII//IGNORE//TRANSLIT", "UTF-8", utf8, strlen (utf8), 2, ++ u2a_translit, 0); ++ ++ /* Misspellings of TRANSLIT and IGNORE are ignored, but conversion still ++ works while respecting any other correctly spelled options. */ ++ ++ test_iconv ("ASCII//T", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a, ++ EILSEQ); ++ test_iconv ("ASCII//TRANSLITERATE", "UTF-8", utf8, strlen (u2a), (size_t) -1, ++ u2a, EILSEQ); ++ test_iconv ("ASCII//I", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a, ++ EILSEQ); ++ test_iconv ("ASCII//IGNORED", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a, ++ EILSEQ); ++ test_iconv ("ASCII//TRANSLITERATE//IGNORED", "UTF-8", utf8, strlen (u2a), ++ (size_t) -1, u2a, EILSEQ); ++ test_iconv ("ASCII//IGNORED,TRANSLITERATE", "UTF-8", utf8, strlen (u2a), ++ (size_t) -1, u2a, EILSEQ); ++ test_iconv ("ASCII//T//I", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a, ++ EILSEQ); ++ ++ test_iconv ("ASCII//TRANSLIT//I", "UTF-8", utf8, strlen (utf8), 2, ++ u2a_translit, 0); ++ /* Due to bug 19519, iconv was ignoring TRANSLIT for the following input. */ ++ test_iconv ("ASCII//I//TRANSLIT", "UTF-8", utf8, strlen (utf8), 2, ++ u2a_translit, 0); ++ test_iconv ("ASCII//IGNORED,TRANSLIT", "UTF-8", utf8, strlen (utf8), 2, ++ u2a_translit, 0); ++ test_iconv ("ASCII//TRANSLIT,IGNORED", "UTF-8", utf8, strlen (utf8), 2, ++ u2a_translit, 0); ++ ++ test_iconv ("ASCII//IGNORE,T", "UTF-8", utf8, strlen (utf8), (size_t) -1, ++ u2a_ignore, EILSEQ); ++ test_iconv ("ASCII//T,IGNORE", "UTF-8", utf8, strlen (utf8), (size_t) -1, ++ u2a_ignore, EILSEQ); ++ /* Due to bug 19519, iconv was ignoring IGNORE for the following input. */ ++ test_iconv ("ASCII//TRANSLITERATE//IGNORE", "UTF-8", utf8, strlen (utf8), ++ (size_t) -1, u2a_ignore, EILSEQ); ++ test_iconv ("ASCII//IGNORE//TRANSLITERATE", "UTF-8", utf8, strlen (utf8), ++ (size_t) -1, u2a_ignore, EILSEQ); ++ ++ ++ /* 3. Invalid UTF-8 followed by some valid non-ASCII UTF-8 characters: */ ++ ++ /* EILSEQ; output is truncated at the first invalid UTF-8 character. */ ++ test_iconv ("ASCII", "UTF-8", iutf8, strlen (iu2a), (size_t) -1, iu2a, ++ EILSEQ); ++ ++ /* With TRANSLIT enabled: EILSEQ; output still truncated at the first invalid ++ UTF-8 character. */ ++ test_iconv ("ASCII//TRANSLIT", "UTF-8", iutf8, strlen (iu2a), (size_t) -1, ++ iu2a, EILSEQ); ++ ++ /* With IGNORE enabled: EILSEQ; output omits invalid UTF-8 characters and ++ valid UTF-8 non-ASCII characters. */ ++ test_iconv ("ASCII//IGNORE", "UTF-8", iutf8, strlen (iutf8), (size_t) -1, ++ iu2a_ignore, EILSEQ); ++ ++ /* With TRANSLIT and IGNORE enabled, output omits only invalid UTF-8 ++ characters and transliterates valid non-ASCII UTF-8 characters. We test ++ four combinations. */ ++ ++ test_iconv ("ASCII//TRANSLIT,IGNORE", "UTF-8", iutf8, strlen (iutf8), 2, ++ iu2a_both, 0); ++ /* Due to bug 19519, iconv was ignoring IGNORE for the following input. */ ++ test_iconv ("ASCII//TRANSLIT//IGNORE", "UTF-8", iutf8, strlen (iutf8), 2, ++ iu2a_both, 0); ++ test_iconv ("ASCII//IGNORE,TRANSLIT", "UTF-8", iutf8, strlen (iutf8), 2, ++ iu2a_both, 0); ++ /* Due to bug 19519, iconv was ignoring TRANSLIT for the following input. */ ++ test_iconv ("ASCII//IGNORE//TRANSLIT", "UTF-8", iutf8, strlen (iutf8), 2, ++ iu2a_both, 0); ++ ++ ++ /* 4. Invalid UTF-8 with valid non-ASCII UTF-8 chars appearing first: */ ++ ++ /* EILSEQ; output is truncated at the first non-ASCII character. */ ++ test_iconv ("ASCII", "UTF-8", jutf8, strlen (ju2a), (size_t) -1, ju2a, ++ EILSEQ); ++ ++ /* With TRANSLIT enabled: EILSEQ; output now truncated at the first invalid ++ UTF-8 character. */ ++ test_iconv ("ASCII//TRANSLIT", "UTF-8", jutf8, strlen (jutf8) - 5, ++ (size_t) -1, ju2a_translit, EILSEQ); ++ test_iconv ("ASCII//translit", "UTF-8", jutf8, strlen (jutf8) - 5, ++ (size_t) -1, ju2a_translit, EILSEQ); ++ ++ /* With IGNORE enabled: EILSEQ; output omits invalid UTF-8 characters and ++ valid UTF-8 non-ASCII characters. */ ++ test_iconv ("ASCII//IGNORE", "UTF-8", jutf8, strlen (jutf8), (size_t) -1, ++ ju2a_ignore, EILSEQ); ++ test_iconv ("ASCII//ignore", "UTF-8", jutf8, strlen (jutf8), (size_t) -1, ++ ju2a_ignore, EILSEQ); ++ ++ /* With TRANSLIT and IGNORE enabled, output omits only invalid UTF-8 ++ characters and transliterates valid non-ASCII UTF-8 characters. We test ++ several combinations. */ ++ ++ test_iconv ("ASCII//TRANSLIT,IGNORE", "UTF-8", jutf8, strlen (jutf8), 2, ++ ju2a_both, 0); ++ /* Due to bug 19519, iconv was ignoring IGNORE for the following input. */ ++ test_iconv ("ASCII//TRANSLIT//IGNORE", "UTF-8", jutf8, strlen (jutf8), 2, ++ ju2a_both, 0); ++ test_iconv ("ASCII//IGNORE,TRANSLIT", "UTF-8", jutf8, strlen (jutf8), 2, ++ ju2a_both, 0); ++ /* Due to bug 19519, iconv was ignoring TRANSLIT for the following input. */ ++ test_iconv ("ASCII//IGNORE//TRANSLIT", "UTF-8", jutf8, strlen (jutf8), 2, ++ ju2a_both, 0); ++ test_iconv ("ASCII//translit,ignore", "UTF-8", jutf8, strlen (jutf8), 2, ++ ju2a_both, 0); ++ /* Trailing whitespace and separators should be ignored. */ ++ test_iconv ("ASCII//IGNORE,TRANSLIT ", "UTF-8", jutf8, strlen (jutf8), 2, ++ ju2a_both, 0); ++ test_iconv ("ASCII//IGNORE,TRANSLIT/", "UTF-8", jutf8, strlen (jutf8), 2, ++ ju2a_both, 0); ++ test_iconv ("ASCII//IGNORE,TRANSLIT//", "UTF-8", jutf8, strlen (jutf8), 2, ++ ju2a_both, 0); ++ test_iconv ("ASCII//IGNORE,TRANSLIT,", "UTF-8", jutf8, strlen (jutf8), 2, ++ ju2a_both, 0); ++ test_iconv ("ASCII//IGNORE,TRANSLIT,,", "UTF-8", jutf8, strlen (jutf8), 2, ++ ju2a_both, 0); ++ test_iconv ("ASCII//IGNORE,TRANSLIT /,", "UTF-8", jutf8, strlen (jutf8), 2, ++ ju2a_both, 0); ++ ++ /* TRANSLIT or IGNORE suffixes in fromcode should be ignored. */ ++ test_iconv ("ASCII", "UTF-8//TRANSLIT", jutf8, strlen (ju2a), (size_t) -1, ++ ju2a, EILSEQ); ++ test_iconv ("ASCII", "UTF-8//IGNORE", jutf8, strlen (ju2a), (size_t) -1, ++ ju2a, EILSEQ); ++ test_iconv ("ASCII", "UTF-8//TRANSLIT,IGNORE", jutf8, strlen (ju2a), ++ (size_t) -1, ju2a, EILSEQ); ++ ++ ++ /* 5. Charset names of the form "A/B/": */ ++ ++ /* ISO-8859-1 is converted to UTF-8 without needing transliteration. */ ++ test_iconv ("ISO-10646/UTF-8", "ISO-8859-1", iso8859_1_a, ++ strlen (iso8859_1_a), 0, utf8_a, 0); ++ test_iconv ("ISO-10646/UTF-8/", "ISO-8859-1", iso8859_1_a, ++ strlen (iso8859_1_a), 0, utf8_a, 0); ++ test_iconv ("ISO-10646/UTF-8/IGNORE", "ISO-8859-1", iso8859_1_a, ++ strlen (iso8859_1_a), 0, utf8_a, 0); ++ test_iconv ("ISO-10646/UTF-8//IGNORE", "ISO-8859-1", iso8859_1_a, ++ strlen (iso8859_1_a), 0, utf8_a, 0); ++ test_iconv ("ISO-10646/UTF-8/TRANSLIT", "ISO-8859-1", iso8859_1_a, ++ strlen (iso8859_1_a), 0, utf8_a, 0); ++ test_iconv ("ISO-10646/UTF-8//TRANSLIT", "ISO-8859-1", iso8859_1_a, ++ strlen (iso8859_1_a), 0, utf8_a, 0); ++ test_iconv ("ISO-10646/UTF-8//TRANSLIT/IGNORE", "ISO-8859-1", iso8859_1_a, ++ strlen (iso8859_1_a), 0, utf8_a, 0); ++ test_iconv ("ISO-10646/UTF-8//TRANSLIT//IGNORE", "ISO-8859-1", iso8859_1_a, ++ strlen (iso8859_1_a), 0, utf8_a, 0); ++ test_iconv ("ISO-10646/UTF-8/TRANSLIT,IGNORE", "ISO-8859-1", iso8859_1_a, ++ strlen (iso8859_1_a), 0, utf8_a, 0); ++ ++ /* UTF-8 with accented A's is converted to ASCII with transliteration. */ ++ test_iconv ("ASCII", "ISO-10646/UTF-8", utf8_a, ++ 0, (size_t) -1, empty, EILSEQ); ++ test_iconv ("ASCII//IGNORE", "ISO-10646/UTF-8", utf8_a, ++ strlen (utf8_a), (size_t) -1, empty, EILSEQ); ++ test_iconv ("ASCII//TRANSLIT", "ISO-10646/UTF-8", utf8_a, ++ strlen (utf8_a), 12, ascii_a, 0); ++ ++ /* Invalid ASCII is converted to UTF-8 only with IGNORE. */ ++ test_iconv ("ISO-10646/UTF-8", "ASCII", iascii, strlen (empty), (size_t) -1, ++ empty, EILSEQ); ++ test_iconv ("ISO-10646/UTF-8/TRANSLIT", "ASCII", iascii, strlen (empty), ++ (size_t) -1, empty, EILSEQ); ++ test_iconv ("ISO-10646/UTF-8/IGNORE", "ASCII", iascii, strlen (iascii), ++ (size_t) -1, ia2u_ignore, EILSEQ); ++ test_iconv ("ISO-10646/UTF-8/TRANSLIT,IGNORE", "ASCII", iascii, ++ strlen (iascii), (size_t) -1, ia2u_ignore, EILSEQ); ++ /* Due to bug 19519, iconv was ignoring IGNORE for the following three ++ inputs: */ ++ test_iconv ("ISO-10646/UTF-8/TRANSLIT/IGNORE", "ASCII", iascii, ++ strlen (iascii), (size_t) -1, ia2u_ignore, EILSEQ); ++ test_iconv ("ISO-10646/UTF-8//TRANSLIT,IGNORE", "ASCII", iascii, ++ strlen (iascii), (size_t) -1, ia2u_ignore, EILSEQ); ++ test_iconv ("ISO-10646/UTF-8//TRANSLIT//IGNORE", "ASCII", iascii, ++ strlen (iascii), (size_t) -1, ia2u_ignore, EILSEQ); ++ ++ return 0; ++} ++ ++#include +diff --git a/iconv/tst-iconv_prog.sh b/iconv/tst-iconv_prog.sh +new file mode 100644 +index 0000000000000000..8298136b7f45d855 +--- /dev/null ++++ b/iconv/tst-iconv_prog.sh +@@ -0,0 +1,280 @@ ++#!/bin/bash ++# Test for some known iconv(1) hangs from bug 19519, and miscellaneous ++# iconv(1) program error conditions. ++# Copyright (C) 2020 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 ++# . ++ ++codir=$1 ++test_wrapper_env="$2" ++run_program_env="$3" ++ ++# We have to have some directories in the library path. ++LIBPATH=$codir:$codir/iconvdata ++ ++# How the start the iconv(1) program. $from is not defined/expanded yet. ++ICONV=' ++$codir/elf/ld.so --library-path $LIBPATH --inhibit-rpath ${from}.so ++$codir/iconv/iconv_prog ++' ++ICONV="$test_wrapper_env $run_program_env $ICONV" ++ ++# List of known hangs; ++# Gathered by running an exhaustive 2 byte input search against glibc-2.28 ++hangarray=( ++"\x00\x23;-c;ANSI_X3.110;UTF-8//TRANSLIT//IGNORE" ++"\x00\xa1;-c;ARMSCII-8;UTF-8//TRANSLIT//IGNORE" ++"\x00\xa1;-c;ASMO_449;UTF-8//TRANSLIT//IGNORE" ++"\x00\x81;-c;BIG5;UTF-8//TRANSLIT//IGNORE" ++"\x00\xff;-c;BIG5HKSCS;UTF-8//TRANSLIT//IGNORE" ++"\x00\xff;-c;BRF;UTF-8//TRANSLIT//IGNORE" ++"\x00\xff;-c;BS_4730;UTF-8//TRANSLIT//IGNORE" ++"\x00\x81;-c;CP1250;UTF-8//TRANSLIT//IGNORE" ++"\x00\x98;-c;CP1251;UTF-8//TRANSLIT//IGNORE" ++"\x00\x81;-c;CP1252;UTF-8//TRANSLIT//IGNORE" ++"\x00\x81;-c;CP1253;UTF-8//TRANSLIT//IGNORE" ++"\x00\x81;-c;CP1254;UTF-8//TRANSLIT//IGNORE" ++"\x00\x81;-c;CP1255;UTF-8//TRANSLIT//IGNORE" ++"\x00\x81;-c;CP1257;UTF-8//TRANSLIT//IGNORE" ++"\x00\x81;-c;CP1258;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;CP932;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;CSA_Z243.4-1985-1;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;CSA_Z243.4-1985-2;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;DEC-MCS;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;DIN_66003;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;DS_2089;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-AT-DE;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-AT-DE-A;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-CA-FR;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-DK-NO;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-DK-NO-A;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-ES;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-ES-A;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-ES-S;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-FI-SE;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-FI-SE-A;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-FR;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-IS-FRISS;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-IT;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-PT;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-UK;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;EBCDIC-US;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ES;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ES2;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;EUC-CN;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;EUC-JISX0213;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;EUC-JP;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;EUC-JP-MS;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;EUC-KR;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;EUC-TW;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;GB18030;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;GB_1988-80;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;GBK;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;GOST_19768-74;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;GREEK7;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;GREEK7-OLD;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;GREEK-CCITT;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;HP-GREEK8;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;HP-ROMAN8;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;HP-ROMAN9;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;HP-THAI8;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;HP-TURKISH8;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;IBM038;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;IBM1004;UTF-8//TRANSLIT//IGNORE" ++"\x00\xff;-c;IBM1008;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;IBM1046;UTF-8//TRANSLIT//IGNORE" ++"\x00\x51;-c;IBM1132;UTF-8//TRANSLIT//IGNORE" ++"\x00\xa0;-c;IBM1133;UTF-8//TRANSLIT//IGNORE" ++"\x00\xce;-c;IBM1137;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;IBM1161;UTF-8//TRANSLIT//IGNORE" ++"\x00\xdb;-c;IBM1162;UTF-8//TRANSLIT//IGNORE" ++"\x00\x70;-c;IBM12712;UTF-8//TRANSLIT//IGNORE" ++# These are known hangs that are yet to be fixed: ++# "\x00\x0f;-c;IBM1364;UTF-8" ++# "\x00\x0f;-c;IBM1371;UTF-8" ++# "\x00\x0f;-c;IBM1388;UTF-8" ++# "\x00\x0f;-c;IBM1390;UTF-8" ++# "\x00\x0f;-c;IBM1399;UTF-8" ++"\x00\x53;-c;IBM16804;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;IBM274;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;IBM275;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;IBM281;UTF-8//TRANSLIT//IGNORE" ++"\x00\x57;-c;IBM290;UTF-8//TRANSLIT//IGNORE" ++"\x00\x45;-c;IBM420;UTF-8//TRANSLIT//IGNORE" ++"\x00\x68;-c;IBM423;UTF-8//TRANSLIT//IGNORE" ++"\x00\x70;-c;IBM424;UTF-8//TRANSLIT//IGNORE" ++"\x00\x53;-c;IBM4517;UTF-8//TRANSLIT//IGNORE" ++"\x00\x53;-c;IBM4899;UTF-8//TRANSLIT//IGNORE" ++"\x00\xa5;-c;IBM4909;UTF-8//TRANSLIT//IGNORE" ++"\x00\xdc;-c;IBM4971;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;IBM803;UTF-8//TRANSLIT//IGNORE" ++"\x00\x91;-c;IBM851;UTF-8//TRANSLIT//IGNORE" ++"\x00\x9b;-c;IBM856;UTF-8//TRANSLIT//IGNORE" ++"\x00\xd5;-c;IBM857;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;IBM864;UTF-8//TRANSLIT//IGNORE" ++"\x00\x94;-c;IBM868;UTF-8//TRANSLIT//IGNORE" ++"\x00\x94;-c;IBM869;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;IBM874;UTF-8//TRANSLIT//IGNORE" ++"\x00\x6a;-c;IBM875;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;IBM880;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;IBM891;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;IBM903;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;IBM904;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;IBM905;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;IBM9066;UTF-8//TRANSLIT//IGNORE" ++"\x00\x48;-c;IBM918;UTF-8//TRANSLIT//IGNORE" ++"\x00\x57;-c;IBM930;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;IBM932;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;IBM933;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;IBM935;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;IBM937;UTF-8//TRANSLIT//IGNORE" ++"\x00\x41;-c;IBM939;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;IBM943;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;INIS;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;INIS-8;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;INIS-CYRILLIC;UTF-8//TRANSLIT//IGNORE" ++"\x00\xec;-c;ISIRI-3342;UTF-8//TRANSLIT//IGNORE" ++"\x00\xec;-c;ISO_10367-BOX;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO-2022-CN;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO-2022-CN-EXT;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO-2022-JP;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO-2022-JP-2;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO-2022-JP-3;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO-2022-KR;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO_2033;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO_5427;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO_5427-EXT;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO_5428;UTF-8//TRANSLIT//IGNORE" ++"\x00\xa4;-c;ISO_6937;UTF-8//TRANSLIT//IGNORE" ++"\x00\xa0;-c;ISO_6937-2;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO-8859-11;UTF-8//TRANSLIT//IGNORE" ++"\x00\xa5;-c;ISO-8859-3;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO-8859-6;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO-8859-7;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;ISO-8859-8;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;ISO-IR-197;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;ISO-IR-209;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;IT;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;JIS_C6220-1969-RO;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;JIS_C6229-1984-B;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;JOHAB;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;JUS_I.B1.002;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;KOI-8;UTF-8//TRANSLIT//IGNORE" ++"\x00\x88;-c;KOI8-T;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;KSC5636;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;LATIN-GREEK;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;LATIN-GREEK-1;UTF-8//TRANSLIT//IGNORE" ++"\x00\xf6;-c;MAC-IS;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;MSZ_7795.3;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;NATS-DANO;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;NATS-SEFI;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;NC_NC00-10;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;NF_Z_62-010;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;NF_Z_62-010_1973;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;NS_4551-1;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;NS_4551-2;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;PT;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;PT2;UTF-8//TRANSLIT//IGNORE" ++"\x00\x98;-c;RK1048;UTF-8//TRANSLIT//IGNORE" ++"\x00\x98;-c;SEN_850200_B;UTF-8//TRANSLIT//IGNORE" ++"\x00\x98;-c;SEN_850200_C;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;Shift_JISX0213;UTF-8//TRANSLIT//IGNORE" ++"\x00\x80;-c;SJIS;UTF-8//TRANSLIT//IGNORE" ++"\x00\x23;-c;T.61-8BIT;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;TIS-620;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;TSCII;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;UHC;UTF-8//TRANSLIT//IGNORE" ++"\x00\xd8;-c;UNICODE;UTF-8//TRANSLIT//IGNORE" ++"\x00\xdc;-c;UTF-16;UTF-8//TRANSLIT//IGNORE" ++"\xdc\x00;-c;UTF-16BE;UTF-8//TRANSLIT//IGNORE" ++"\x00\xdc;-c;UTF-16LE;UTF-8//TRANSLIT//IGNORE" ++"\xff\xff;-c;UTF-7;UTF-8//TRANSLIT//IGNORE" ++"\x00\x81;-c;WIN-SAMI-2;UTF-8//TRANSLIT//IGNORE" ++) ++ ++# List of option combinations that *should* lead to an error ++errorarray=( ++# Converting from/to invalid character sets should cause error ++"\x00\x00;;INVALID;INVALID" ++"\x00\x00;;INVALID;UTF-8" ++"\x00\x00;;UTF-8;INVALID" ++) ++ ++# Requires $twobyte input, $c flag, $from, and $to to be set; sets $ret ++execute_test () ++{ ++ eval PROG=\"$ICONV\" ++ echo -en "$twobyte" \ ++ | timeout -k 4 3 $PROG $c -f $from -t "$to" &>/dev/null ++ ret=$? ++} ++ ++check_hangtest_result () ++{ ++ if [ "$ret" -eq "124" ] || [ "$ret" -eq "137" ]; then # timeout/hang ++ result="HANG" ++ else ++ if [ "$ret" -eq "139" ]; then # segfault ++ result="SEGFAULT" ++ else ++ if [ "$ret" -gt "127" ]; then # unexpected error ++ result="UNEXPECTED" ++ else ++ result="OK" ++ fi ++ fi ++ fi ++ ++ echo -n "$result: from: \"$from\", to: \"$to\"," ++ echo " input \"$twobyte\", flags \"$c\"" ++ ++ if [ "$result" != "OK" ]; then ++ exit 1 ++ fi ++} ++ ++for hangcommand in "${hangarray[@]}"; do ++ twobyte="$(echo "$hangcommand" | cut -d";" -f 1)" ++ c="$(echo "$hangcommand" | cut -d";" -f 2)" ++ from="$(echo "$hangcommand" | cut -d";" -f 3)" ++ to="$(echo "$hangcommand" | cut -d";" -f 4)" ++ execute_test ++ check_hangtest_result ++done ++ ++check_errtest_result () ++{ ++ if [ "$ret" -eq "1" ]; then # we errored out as expected ++ result="PASS" ++ else ++ result="FAIL" ++ fi ++ echo -n "$result: from: \"$from\", to: \"$to\"," ++ echo " input \"$twobyte\", flags \"$c\", return code $ret" ++ ++ if [ "$result" != "PASS" ]; then ++ exit 1 ++ fi ++} ++ ++for errorcommand in "${errorarray[@]}"; do ++ twobyte="$(echo "$errorcommand" | cut -d";" -f 1)" ++ c="$(echo "$errorcommand" | cut -d";" -f 2)" ++ from="$(echo "$errorcommand" | cut -d";" -f 3)" ++ to="$(echo "$errorcommand" | cut -d";" -f 4)" ++ execute_test ++ check_errtest_result ++done +diff --git a/intl/dcigettext.c b/intl/dcigettext.c +index 25f47c5bd3b0ea04..ed48fc8d3e96c7ba 100644 +--- a/intl/dcigettext.c ++++ b/intl/dcigettext.c +@@ -1120,11 +1120,16 @@ _nl_find_msg (struct loaded_l10nfile *domain_file, + outcharset = encoding; + + # ifdef _LIBC +- /* We always want to use transliteration. */ +- outcharset = norm_add_slashes (outcharset, "TRANSLIT"); +- charset = norm_add_slashes (charset, ""); +- int r = __gconv_open (outcharset, charset, &convd->conv, +- GCONV_AVOID_NOCONV); ++ ++ struct gconv_spec conv_spec ++ = { .fromcode = norm_add_slashes (charset, ""), ++ .tocode = norm_add_slashes (outcharset, ""), ++ /* We always want to use transliteration. */ ++ .translit = true, ++ .ignore = false ++ }; ++ int r = __gconv_open (&conv_spec, &convd->conv, ++ GCONV_AVOID_NOCONV); + if (__builtin_expect (r != __GCONV_OK, 0)) + { + /* If the output encoding is the same there is diff --git a/glibc-rh1704868-2.patch b/glibc-rh1704868-2.patch new file mode 100755 index 0000000..50b7ad7 --- /dev/null +++ b/glibc-rh1704868-2.patch @@ -0,0 +1,235 @@ +commit 7d4ec75e111291851620c6aa2c4460647b7fd50d +Author: Arjun Shankar +Date: Fri Sep 25 14:47:06 2020 +0200 + + intl: Handle translation output codesets with suffixes [BZ #26383] + + Commit 91927b7c7643 (Rewrite iconv option parsing [BZ #19519]) did not + handle cases where the output codeset for translations (via the `gettext' + family of functions) might have a caller specified encoding suffix such as + TRANSLIT or IGNORE. This led to a regression where translations did not + work when the codeset had a suffix. + + This commit fixes the above issue by parsing any suffixes passed to + __dcigettext and adds two new test-cases to intl/tst-codeset.c to + verify correct behaviour. The iconv-internal function __gconv_create_spec + and the static iconv-internal function gconv_destroy_spec are now visible + internally within glibc and used in intl/dcigettext.c. + +diff --git a/iconv/Versions b/iconv/Versions +index 8a5f4cf780b18925..d51af52fa34b8793 100644 +--- a/iconv/Versions ++++ b/iconv/Versions +@@ -6,7 +6,9 @@ libc { + GLIBC_PRIVATE { + # functions shared with iconv program + __gconv_get_alias_db; __gconv_get_cache; __gconv_get_modules_db; +- __gconv_open; __gconv_create_spec; ++ ++ # functions used elsewhere in glibc ++ __gconv_open; __gconv_create_spec; __gconv_destroy_spec; + + # function used by the gconv modules + __gconv_transliterate; +diff --git a/iconv/gconv_charset.c b/iconv/gconv_charset.c +index 6ccd0773ccb6cd27..4ba0aa99f5dae7f7 100644 +--- a/iconv/gconv_charset.c ++++ b/iconv/gconv_charset.c +@@ -216,3 +216,13 @@ out: + return ret; + } + libc_hidden_def (__gconv_create_spec) ++ ++ ++void ++__gconv_destroy_spec (struct gconv_spec *conv_spec) ++{ ++ free (conv_spec->fromcode); ++ free (conv_spec->tocode); ++ return; ++} ++libc_hidden_def (__gconv_destroy_spec) +diff --git a/iconv/gconv_charset.h b/iconv/gconv_charset.h +index b85d80313030b649..4b98073389bd8707 100644 +--- a/iconv/gconv_charset.h ++++ b/iconv/gconv_charset.h +@@ -48,33 +48,6 @@ + #define GCONV_IGNORE_ERRORS_SUFFIX "IGNORE" + + +-/* This function accepts the charset names of the source and destination of the +- conversion and populates *conv_spec with an equivalent conversion +- specification that may later be used by __gconv_open. The charset names +- might contain options in the form of suffixes that alter the conversion, +- e.g. "ISO-10646/UTF-8/TRANSLIT". It processes the charset names, ignoring +- and truncating any suffix options in fromcode, and processing and truncating +- any suffix options in tocode. Supported suffix options ("TRANSLIT" or +- "IGNORE") when found in tocode lead to the corresponding flag in *conv_spec +- to be set to true. Unrecognized suffix options are silently discarded. If +- the function succeeds, it returns conv_spec back to the caller. It returns +- NULL upon failure. */ +-struct gconv_spec * +-__gconv_create_spec (struct gconv_spec *conv_spec, const char *fromcode, +- const char *tocode); +-libc_hidden_proto (__gconv_create_spec) +- +- +-/* This function frees all heap memory allocated by __gconv_create_spec. */ +-static void __attribute__ ((unused)) +-gconv_destroy_spec (struct gconv_spec *conv_spec) +-{ +- free (conv_spec->fromcode); +- free (conv_spec->tocode); +- return; +-} +- +- + /* This function copies in-order, characters from the source 's' that are + either alpha-numeric or one in one of these: "_-.,:/" - into the destination + 'wp' while dropping all other characters. In the process, it converts all +diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h +index 4748e9b1fa3b5426..8067a341b0903e1b 100644 +--- a/iconv/gconv_int.h ++++ b/iconv/gconv_int.h +@@ -170,6 +170,27 @@ extern int __gconv_open (struct gconv_spec *conv_spec, + __gconv_t *handle, int flags); + libc_hidden_proto (__gconv_open) + ++/* This function accepts the charset names of the source and destination of the ++ conversion and populates *conv_spec with an equivalent conversion ++ specification that may later be used by __gconv_open. The charset names ++ might contain options in the form of suffixes that alter the conversion, ++ e.g. "ISO-10646/UTF-8/TRANSLIT". It processes the charset names, ignoring ++ and truncating any suffix options in fromcode, and processing and truncating ++ any suffix options in tocode. Supported suffix options ("TRANSLIT" or ++ "IGNORE") when found in tocode lead to the corresponding flag in *conv_spec ++ to be set to true. Unrecognized suffix options are silently discarded. If ++ the function succeeds, it returns conv_spec back to the caller. It returns ++ NULL upon failure. */ ++extern struct gconv_spec * ++__gconv_create_spec (struct gconv_spec *conv_spec, const char *fromcode, ++ const char *tocode); ++libc_hidden_proto (__gconv_create_spec) ++ ++/* This function frees all heap memory allocated by __gconv_create_spec. */ ++extern void ++__gconv_destroy_spec (struct gconv_spec *conv_spec); ++libc_hidden_proto (__gconv_destroy_spec) ++ + /* Free resources associated with transformation descriptor CD. */ + extern int __gconv_close (__gconv_t cd) + attribute_hidden; +diff --git a/iconv/iconv_open.c b/iconv/iconv_open.c +index 59d1ef4f07ed1022..46da33bca6c24af0 100644 +--- a/iconv/iconv_open.c ++++ b/iconv/iconv_open.c +@@ -39,7 +39,7 @@ iconv_open (const char *tocode, const char *fromcode) + + int res = __gconv_open (&conv_spec, &cd, 0); + +- gconv_destroy_spec (&conv_spec); ++ __gconv_destroy_spec (&conv_spec); + + if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK) + { +diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c +index 552efac81660e82a..e26e9d02ca4121a7 100644 +--- a/iconv/iconv_prog.c ++++ b/iconv/iconv_prog.c +@@ -184,7 +184,7 @@ main (int argc, char *argv[]) + /* Let's see whether we have these coded character sets. */ + res = __gconv_open (&conv_spec, &cd, 0); + +- gconv_destroy_spec (&conv_spec); ++ __gconv_destroy_spec (&conv_spec); + + if (res != __GCONV_OK) + { +diff --git a/intl/dcigettext.c b/intl/dcigettext.c +index ed48fc8d3e96c7ba..7ebe67b4ac2113e9 100644 +--- a/intl/dcigettext.c ++++ b/intl/dcigettext.c +@@ -1121,15 +1121,18 @@ _nl_find_msg (struct loaded_l10nfile *domain_file, + + # ifdef _LIBC + +- struct gconv_spec conv_spec +- = { .fromcode = norm_add_slashes (charset, ""), +- .tocode = norm_add_slashes (outcharset, ""), +- /* We always want to use transliteration. */ +- .translit = true, +- .ignore = false +- }; ++ struct gconv_spec conv_spec; ++ ++ __gconv_create_spec (&conv_spec, charset, outcharset); ++ ++ /* We always want to use transliteration. */ ++ conv_spec.translit = true; ++ + int r = __gconv_open (&conv_spec, &convd->conv, + GCONV_AVOID_NOCONV); ++ ++ __gconv_destroy_spec (&conv_spec); ++ + if (__builtin_expect (r != __GCONV_OK, 0)) + { + /* If the output encoding is the same there is +diff --git a/intl/tst-codeset.c b/intl/tst-codeset.c +index e71382aeeeca477b..52e4aaa6ffd3afdb 100644 +--- a/intl/tst-codeset.c ++++ b/intl/tst-codeset.c +@@ -22,13 +22,11 @@ + #include + #include + #include ++#include + + static int + do_test (void) + { +- char *s; +- int result = 0; +- + unsetenv ("LANGUAGE"); + unsetenv ("OUTPUT_CHARSET"); + setlocale (LC_ALL, "de_DE.ISO-8859-1"); +@@ -36,25 +34,21 @@ do_test (void) + bindtextdomain ("codeset", OBJPFX "domaindir"); + + /* Here we expect output in ISO-8859-1. */ +- s = gettext ("cheese"); +- if (strcmp (s, "K\344se")) +- { +- printf ("call 1 returned: %s\n", s); +- result = 1; +- } ++ TEST_COMPARE_STRING (gettext ("cheese"), "K\344se"); + ++ /* Here we expect output in UTF-8. */ + bind_textdomain_codeset ("codeset", "UTF-8"); ++ TEST_COMPARE_STRING (gettext ("cheese"), "K\303\244se"); + +- /* Here we expect output in UTF-8. */ +- s = gettext ("cheese"); +- if (strcmp (s, "K\303\244se")) +- { +- printf ("call 2 returned: %s\n", s); +- result = 1; +- } +- +- return result; ++ /* `a with umlaut' is transliterated to `ae'. */ ++ bind_textdomain_codeset ("codeset", "ASCII//TRANSLIT"); ++ TEST_COMPARE_STRING (gettext ("cheese"), "Kaese"); ++ ++ /* Transliteration also works by default even if not set. */ ++ bind_textdomain_codeset ("codeset", "ASCII"); ++ TEST_COMPARE_STRING (gettext ("cheese"), "Kaese"); ++ ++ return 0; + } + +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" ++#include diff --git a/glibc-rh1704868-3.patch b/glibc-rh1704868-3.patch new file mode 100755 index 0000000..c5b79c2 --- /dev/null +++ b/glibc-rh1704868-3.patch @@ -0,0 +1,77 @@ +commit 9a99c682144bdbd40792ebf822fe9264e0376fb5 +Author: Arjun Shankar +Date: Wed Nov 4 12:19:38 2020 +0100 + + iconv: Accept redundant shift sequences in IBM1364 [BZ #26224] + + The IBM1364, IBM1371, IBM1388, IBM1390 and IBM1399 character sets + share converter logic (iconvdata/ibm1364.c) which would reject + redundant shift sequences when processing input in these character + sets. This led to a hang in the iconv program (CVE-2020-27618). + + This commit adjusts the converter to ignore redundant shift sequences + and adds test cases for iconv_prog hangs that would be triggered upon + their rejection. This brings the implementation in line with other + converters that also ignore redundant shift sequences (e.g. IBM930 + etc., fixed in commit 692de4b3960d). + + Reviewed-by: Carlos O'Donell + +diff --git a/iconv/tst-iconv_prog.sh b/iconv/tst-iconv_prog.sh +index 8298136b7f45d855..d8db7b335c1fcca2 100644 +--- a/iconv/tst-iconv_prog.sh ++++ b/iconv/tst-iconv_prog.sh +@@ -102,12 +102,16 @@ hangarray=( + "\x00\x80;-c;IBM1161;UTF-8//TRANSLIT//IGNORE" + "\x00\xdb;-c;IBM1162;UTF-8//TRANSLIT//IGNORE" + "\x00\x70;-c;IBM12712;UTF-8//TRANSLIT//IGNORE" +-# These are known hangs that are yet to be fixed: +-# "\x00\x0f;-c;IBM1364;UTF-8" +-# "\x00\x0f;-c;IBM1371;UTF-8" +-# "\x00\x0f;-c;IBM1388;UTF-8" +-# "\x00\x0f;-c;IBM1390;UTF-8" +-# "\x00\x0f;-c;IBM1399;UTF-8" ++"\x00\x0f;-c;IBM1364;UTF-8" ++"\x0e\x0e;-c;IBM1364;UTF-8" ++"\x00\x0f;-c;IBM1371;UTF-8" ++"\x0e\x0e;-c;IBM1371;UTF-8" ++"\x00\x0f;-c;IBM1388;UTF-8" ++"\x0e\x0e;-c;IBM1388;UTF-8" ++"\x00\x0f;-c;IBM1390;UTF-8" ++"\x0e\x0e;-c;IBM1390;UTF-8" ++"\x00\x0f;-c;IBM1399;UTF-8" ++"\x0e\x0e;-c;IBM1399;UTF-8" + "\x00\x53;-c;IBM16804;UTF-8//TRANSLIT//IGNORE" + "\x00\x41;-c;IBM274;UTF-8//TRANSLIT//IGNORE" + "\x00\x41;-c;IBM275;UTF-8//TRANSLIT//IGNORE" +diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c +index 517fe60813be0472..ecc3f8ddddbdbc8c 100644 +--- a/iconvdata/ibm1364.c ++++ b/iconvdata/ibm1364.c +@@ -158,24 +158,14 @@ enum + \ + if (__builtin_expect (ch, 0) == SO) \ + { \ +- /* Shift OUT, change to DBCS converter. */ \ +- if (curcs == db) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift OUT, change to DBCS converter (redundant escape okay). */ \ + curcs = db; \ + ++inptr; \ + continue; \ + } \ + if (__builtin_expect (ch, 0) == SI) \ + { \ +- /* Shift IN, change to SBCS converter. */ \ +- if (curcs == sb) \ +- { \ +- result = __GCONV_ILLEGAL_INPUT; \ +- break; \ +- } \ ++ /* Shift IN, change to SBCS converter (redundant escape okay). */ \ + curcs = sb; \ + ++inptr; \ + continue; \ diff --git a/glibc-rh1704868-4.patch b/glibc-rh1704868-4.patch new file mode 100755 index 0000000..7bfb219 --- /dev/null +++ b/glibc-rh1704868-4.patch @@ -0,0 +1,66 @@ +commit cce35a50c1de0cec5cd1f6c18979ff6ee3ea1dd1 +Author: Arjun Shankar +Date: Mon Nov 11 14:57:23 2019 +0100 + + support: Add xsetlocale function + +diff --git a/support/Makefile b/support/Makefile +index 37d5dcc92a5c6dee..6afaa6836c944398 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -148,6 +148,7 @@ libsupport-routines = \ + xrealloc \ + xrecvfrom \ + xsendto \ ++ xsetlocale \ + xsetsockopt \ + xsigaction \ + xsignal \ +diff --git a/support/support.h b/support/support.h +index 61a10c34982134ff..97d142e9b6f68188 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -91,6 +91,7 @@ char *xasprintf (const char *format, ...) + __attribute__ ((format (printf, 1, 2), malloc)); + char *xstrdup (const char *); + char *xstrndup (const char *, size_t); ++char *xsetlocale (int category, const char *locale); + + /* These point to the TOP of the source/build tree, not your (or + support's) subdirectory. */ +diff --git a/support/xsetlocale.c b/support/xsetlocale.c +new file mode 100644 +index 0000000000000000..063ed4b0d63af884 +--- /dev/null ++++ b/support/xsetlocale.c +@@ -0,0 +1,30 @@ ++/* setlocale 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 ++ . */ ++ ++#include ++ ++#include ++ ++char * ++xsetlocale (int category, const char *locale) ++{ ++ char *p = setlocale (category, locale); ++ if (p == NULL) ++ FAIL_EXIT1 ("error: setlocale (%d, \"%s\")\n", category, locale); ++ return p; ++} diff --git a/glibc-rh1704868-5.patch b/glibc-rh1704868-5.patch new file mode 100755 index 0000000..1ffdb97 --- /dev/null +++ b/glibc-rh1704868-5.patch @@ -0,0 +1,35 @@ +The patch (glibc-rh1704868-1.patch) for commit 91927b7c7643 +(Rewrite iconv option parsing) contains a test that depends on +commit 513aaa0d782f (Add Transliterations for Unicode Misc. +Mathematical Symbols-A/B), which is not applied in RHEL-8. This +patch edits the test so as not to depend on the unapplied patch +and its additional transliterations. + +diff --git a/iconv/tst-iconv-opt.c b/iconv/tst-iconv-opt.c +index 669d812a6a9b8749..21e6d887501450a7 100644 +--- a/iconv/tst-iconv-opt.c ++++ b/iconv/tst-iconv-opt.c +@@ -82,18 +82,18 @@ char u2a_ignore[] = "UTF-8 text with couple f non-ASCII characters"; + + /* 3. Invalid UTF-8 input and some corresponding expected outputs. \xff is + invalid UTF-8. It's followed by some valid but non-ASCII UTF-8. */ +-char iutf8[] = "Invalid UTF-8 \xff\u27E6text\u27E7"; ++char iutf8[] = "Invalid UTF-8 \xff\u00B7text\u00B7"; + char iu2a[] = "Invalid UTF-8 "; + char iu2a_ignore[] = "Invalid UTF-8 text"; +-char iu2a_both[] = "Invalid UTF-8 [|text|]"; ++char iu2a_both[] = "Invalid UTF-8 .text."; + + /* 4. Another invalid UTF-8 input and corresponding expected outputs. This time + the valid non-ASCII UTF-8 characters appear before the invalid \xff. */ +-char jutf8[] = "Invalid \u27E6UTF-8\u27E7 \xfftext"; ++char jutf8[] = "Invalid \u00B7UTF-8\u00B7 \xfftext"; + char ju2a[] = "Invalid "; +-char ju2a_translit[] = "Invalid [|UTF-8|] "; ++char ju2a_translit[] = "Invalid .UTF-8. "; + char ju2a_ignore[] = "Invalid UTF-8 text"; +-char ju2a_both[] = "Invalid [|UTF-8|] text"; ++char ju2a_both[] = "Invalid .UTF-8. text"; + + /* We also test option handling for character set names that have the form + "A/B". In this test, we test conversions "ISO-10646/UTF-8", and either diff --git a/glibc-rh1706777.patch b/glibc-rh1706777.patch new file mode 100755 index 0000000..9e64daa --- /dev/null +++ b/glibc-rh1706777.patch @@ -0,0 +1,44 @@ +commit 38b0593e9a862c3b35392a0f5b202696b8116aa3 +Author: Tobias Klauser +Date: Tue Aug 21 17:22:53 2018 +0000 + + Add PF_XDP, AF_XDP and SOL_XDP from Linux 4.18 to bits/socket.h. + + This patch adds the PF_XDP, AF_XDP and SOL_XDP macros from Linux 4.18 to + sysdeps/unix/sysv/linux/bits/socket.h. + + * sysdeps/unix/sysv/linux/bits/socket.h (PF_MAX): Set to 45. + (PF_XDP): New macro. + (AF_XDP): New macro. + (SOL_XDP): New macro. + +diff --git a/sysdeps/unix/sysv/linux/bits/socket.h b/sysdeps/unix/sysv/linux/bits/socket.h +index fa409f0fabc22d33..c3fbb2110296273c 100644 +--- a/sysdeps/unix/sysv/linux/bits/socket.h ++++ b/sysdeps/unix/sysv/linux/bits/socket.h +@@ -85,7 +85,8 @@ typedef __socklen_t socklen_t; + #define PF_KCM 41 /* Kernel Connection Multiplexor. */ + #define PF_QIPCRTR 42 /* Qualcomm IPC Router. */ + #define PF_SMC 43 /* SMC sockets. */ +-#define PF_MAX 44 /* For now.. */ ++#define PF_XDP 44 /* XDP sockets. */ ++#define PF_MAX 45 /* For now.. */ + + /* Address families. */ + #define AF_UNSPEC PF_UNSPEC +@@ -135,6 +136,7 @@ typedef __socklen_t socklen_t; + #define AF_KCM PF_KCM + #define AF_QIPCRTR PF_QIPCRTR + #define AF_SMC PF_SMC ++#define AF_XDP PF_XDP + #define AF_MAX PF_MAX + + /* Socket level values. Others are defined in the appropriate headers. +@@ -164,6 +166,7 @@ typedef __socklen_t socklen_t; + #define SOL_NFC 280 + #define SOL_KCM 281 + #define SOL_TLS 282 ++#define SOL_XDP 283 + + /* Maximum queue length specifiable by listen. */ + #define SOMAXCONN 128 diff --git a/glibc-rh1710478.patch b/glibc-rh1710478.patch new file mode 100755 index 0000000..3546690 --- /dev/null +++ b/glibc-rh1710478.patch @@ -0,0 +1,107 @@ +commit 32ff397533715988c19cbf3675dcbd727ec13e18 +Author: Andreas Schwab +Date: Tue May 14 17:14:59 2019 +0200 + + Fix crash in _IO_wfile_sync (bug 20568) + + When computing the length of the converted part of the stdio buffer, use + the number of consumed wide characters, not the (negative) distance to the + end of the wide buffer. + +Conflicts: + libio/Makefile + (Usual conflict when adding tests due to missing backports.) + +diff --git a/libio/Makefile b/libio/Makefile +index cab0eae946b1f307..cbfaf3832a45fc22 100644 +--- a/libio/Makefile ++++ b/libio/Makefile +@@ -64,7 +64,8 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ + bug-memstream1 bug-wmemstream1 \ + 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-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof \ ++ tst-wfile-sync + + tests-internal = tst-vtables tst-vtables-interposed tst-readline + +@@ -207,6 +208,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 +diff --git a/libio/tst-wfile-sync.c b/libio/tst-wfile-sync.c +new file mode 100644 +index 0000000000000000..618682064da4035c +--- /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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++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 +diff --git a/libio/tst-wfile-sync.input b/libio/tst-wfile-sync.input +new file mode 100644 +index 0000000000000000..12d0958f7aaa3865 +--- /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 63cb687652c72ce1..10e7343f8fdb8781 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/glibc-rh1710894.patch b/glibc-rh1710894.patch new file mode 100755 index 0000000..790d27a --- /dev/null +++ b/glibc-rh1710894.patch @@ -0,0 +1,310 @@ +commit a9368c34d70cef91ca59b09941f496df11d6b146 +Author: Florian Weimer +Date: Wed May 15 13:51:35 2019 +0200 + + nss: Turn __nss_database_lookup into a compatibility symbol + + The function uses the internal service_user type, so it is not + really usable from the outside of glibc. Rename the function + to __nss_database_lookup2 for internal use, and change + __nss_database_lookup to always indicate failure to the caller. + + __nss_next already was a compatibility symbol. The new + implementation always fails and no longer calls __nss_next2. + + unscd, the alternative nscd implementation, does not use + __nss_database_lookup, so it is not affected by this change. + +DJ - Added 2.30 clause to nss/Versions as RHEL 8 will always be 2.28. + +diff -rup a/grp/initgroups.c b/grp/initgroups.c +--- a/grp/initgroups.c 2019-06-06 17:15:32.184092617 -0400 ++++ b/grp/initgroups.c 2019-06-06 17:16:59.136114679 -0400 +@@ -79,12 +79,12 @@ internal_getgrouplist (const char *user, + + if (__nss_initgroups_database == NULL) + { +- if (__nss_database_lookup ("initgroups", NULL, "", +- &__nss_initgroups_database) < 0) ++ if (__nss_database_lookup2 ("initgroups", NULL, "", ++ &__nss_initgroups_database) < 0) + { + if (__nss_group_database == NULL) +- no_more = __nss_database_lookup ("group", NULL, DEFAULT_CONFIG, +- &__nss_group_database); ++ no_more = __nss_database_lookup2 ("group", NULL, DEFAULT_CONFIG, ++ &__nss_group_database); + + __nss_initgroups_database = __nss_group_database; + } +diff -rup a/nscd/aicache.c b/nscd/aicache.c +--- a/nscd/aicache.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nscd/aicache.c 2019-06-06 17:16:59.501114771 -0400 +@@ -93,9 +93,9 @@ addhstaiX (struct database_dyn *db, int + int herrno = 0; + + if (hosts_database == NULL) +- no_more = __nss_database_lookup ("hosts", NULL, +- "dns [!UNAVAIL=return] files", +- &hosts_database); ++ no_more = __nss_database_lookup2 ("hosts", NULL, ++ "dns [!UNAVAIL=return] files", ++ &hosts_database); + else + no_more = 0; + nip = hosts_database; +diff -rup a/nscd/initgrcache.c b/nscd/initgrcache.c +--- a/nscd/initgrcache.c 2019-06-06 17:15:32.205092622 -0400 ++++ b/nscd/initgrcache.c 2019-06-06 17:16:59.510114774 -0400 +@@ -88,8 +88,8 @@ addinitgroupsX (struct database_dyn *db, + int no_more; + + if (group_database == NULL) +- no_more = __nss_database_lookup ("group", NULL, DEFAULT_CONFIG, +- &group_database); ++ no_more = __nss_database_lookup2 ("group", NULL, DEFAULT_CONFIG, ++ &group_database); + else + no_more = 0; + nip = group_database; +diff -rup a/nscd/netgroupcache.c b/nscd/netgroupcache.c +--- a/nscd/netgroupcache.c 2019-06-06 17:15:32.151092608 -0400 ++++ b/nscd/netgroupcache.c 2019-06-06 17:16:59.514114775 -0400 +@@ -143,7 +143,7 @@ addgetnetgrentX (struct database_dyn *db + *tofreep = NULL; + + if (netgroup_database == NULL +- && __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database)) ++ && __nss_database_lookup2 ("netgroup", NULL, NULL, &netgroup_database)) + { + /* No such service. */ + cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout, +diff -rup a/nss/Versions b/nss/Versions +--- a/nss/Versions 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/Versions 2019-06-10 16:59:34.920054974 -0400 +@@ -1,21 +1,26 @@ + libc { + GLIBC_2.0 { +- # functions used in other libraries ++ __nss_configure_lookup; ++ ++ # Functions exported as no-op compat symbols. + __nss_passwd_lookup; __nss_group_lookup; __nss_hosts_lookup; __nss_next; +- __nss_database_lookup; __nss_configure_lookup; ++ __nss_database_lookup; + } + GLIBC_2.2.2 { + __nss_hostname_digits_dots; + } + GLIBC_2.27 { + } ++ GLIBC_2.30 { ++ # Added for rhbz 1710894 ++ } + GLIBC_PRIVATE { + _nss_files_parse_grent; _nss_files_parse_pwent; _nss_files_parse_spent; + __nss_disable_nscd; __nss_lookup_function; _nss_files_parse_sgent; + + __nss_passwd_lookup2; __nss_group_lookup2; __nss_hosts_lookup2; + __nss_services_lookup2; __nss_next2; __nss_lookup; +- __nss_hash; ++ __nss_hash; __nss_database_lookup2; + } + } + +diff -rup a/nss/XXX-lookup.c b/nss/XXX-lookup.c +--- a/nss/XXX-lookup.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/XXX-lookup.c 2019-06-06 17:16:59.562114786 -0400 +@@ -57,8 +57,8 @@ DB_LOOKUP_FCT (service_user **ni, const + void **fctp) + { + if (DATABASE_NAME_SYMBOL == NULL +- && __nss_database_lookup (DATABASE_NAME_STRING, ALTERNATE_NAME_STRING, +- DEFAULT_CONFIG, &DATABASE_NAME_SYMBOL) < 0) ++ && __nss_database_lookup2 (DATABASE_NAME_STRING, ALTERNATE_NAME_STRING, ++ DEFAULT_CONFIG, &DATABASE_NAME_SYMBOL) < 0) + return -1; + + *ni = DATABASE_NAME_SYMBOL; +diff -rup a/nss/compat-lookup.c b/nss/compat-lookup.c +--- a/nss/compat-lookup.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/compat-lookup.c 2019-06-07 22:14:09.057668330 -0400 +@@ -16,11 +16,12 @@ + License along with the GNU C Library; if not, see + . */ + ++#include ++ + #include + #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_27) + + # include +-# include + + /* On i386, the function calling convention changed from the standard + ABI calling convention to three register parameters in glibc 2.8. +@@ -40,3 +41,31 @@ strong_alias (__nss_passwd_lookup, __nss + compat_symbol (libc, __nss_hosts_lookup, __nss_hosts_lookup, GLIBC_2_0); + + #endif /* SHLIB_COMPAT */ ++ ++ ++#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_30) ++ ++/* These functions were exported under a non-GLIBC_PRIVATE version, ++ even though it is not usable externally due to the service_user ++ type dependency. */ ++ ++int ++attribute_compat_text_section ++__nss_next (service_user **ni, const char *fct_name, void **fctp, int status, ++ int all_values) ++{ ++ return -1; ++} ++compat_symbol (libc, __nss_next, __nss_next, GLIBC_2_0); ++ ++int ++attribute_compat_text_section ++__nss_database_lookup (const char *database, const char *alternate_name, ++ const char *defconfig, service_user **ni) ++{ ++ *ni = NULL; ++ return -1; ++} ++compat_symbol (libc, __nss_database_lookup, __nss_database_lookup, GLIBC_2_0); ++ ++#endif /* SHLIB_COMPAT */ +diff -rup a/nss/nss_compat/compat-grp.c b/nss/nss_compat/compat-grp.c +--- a/nss/nss_compat/compat-grp.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/nss_compat/compat-grp.c 2019-06-06 17:16:59.618114799 -0400 +@@ -78,7 +78,7 @@ static bool in_blacklist (const char *, + static void + init_nss_interface (void) + { +- if (__nss_database_lookup ("group_compat", NULL, "nis", &ni) >= 0) ++ if (__nss_database_lookup2 ("group_compat", NULL, "nis", &ni) >= 0) + { + nss_setgrent = __nss_lookup_function (ni, "setgrent"); + nss_getgrnam_r = __nss_lookup_function (ni, "getgrnam_r"); +diff -rup a/nss/nss_compat/compat-initgroups.c b/nss/nss_compat/compat-initgroups.c +--- a/nss/nss_compat/compat-initgroups.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/nss_compat/compat-initgroups.c 2019-06-06 17:16:59.646114807 -0400 +@@ -89,7 +89,7 @@ init_nss_interface (void) + + /* Retest. */ + if (ni == NULL +- && __nss_database_lookup ("group_compat", NULL, "nis", &ni) >= 0) ++ && __nss_database_lookup2 ("group_compat", NULL, "nis", &ni) >= 0) + { + nss_initgroups_dyn = __nss_lookup_function (ni, "initgroups_dyn"); + nss_getgrnam_r = __nss_lookup_function (ni, "getgrnam_r"); +diff -rup a/nss/nss_compat/compat-pwd.c b/nss/nss_compat/compat-pwd.c +--- a/nss/nss_compat/compat-pwd.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/nss_compat/compat-pwd.c 2019-06-06 17:16:59.654114809 -0400 +@@ -88,7 +88,7 @@ static bool in_blacklist (const char *, + static void + init_nss_interface (void) + { +- if (__nss_database_lookup ("passwd_compat", NULL, "nis", &ni) >= 0) ++ if (__nss_database_lookup2 ("passwd_compat", NULL, "nis", &ni) >= 0) + { + nss_setpwent = __nss_lookup_function (ni, "setpwent"); + nss_getpwnam_r = __nss_lookup_function (ni, "getpwnam_r"); +diff -rup a/nss/nss_compat/compat-spwd.c b/nss/nss_compat/compat-spwd.c +--- a/nss/nss_compat/compat-spwd.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/nss_compat/compat-spwd.c 2019-06-06 17:16:59.668114812 -0400 +@@ -85,8 +85,8 @@ static bool in_blacklist (const char *, + static void + init_nss_interface (void) + { +- if (__nss_database_lookup ("shadow_compat", "passwd_compat", +- "nis", &ni) >= 0) ++ if (__nss_database_lookup2 ("shadow_compat", "passwd_compat", ++ "nis", &ni) >= 0) + { + nss_setspent = __nss_lookup_function (ni, "setspent"); + nss_getspnam_r = __nss_lookup_function (ni, "getspnam_r"); +diff -rup a/nss/nsswitch.c b/nss/nsswitch.c +--- a/nss/nsswitch.c 2019-06-06 17:15:32.210092623 -0400 ++++ b/nss/nsswitch.c 2019-06-06 17:16:59.672114813 -0400 +@@ -115,8 +115,8 @@ static void (*nscd_init_cb) (size_t, str + /* -1 == database not found + 0 == database entry pointer stored */ + int +-__nss_database_lookup (const char *database, const char *alternate_name, +- const char *defconfig, service_user **ni) ++__nss_database_lookup2 (const char *database, const char *alternate_name, ++ const char *defconfig, service_user **ni) + { + /* Prevent multiple threads to change the service table. */ + __libc_lock_lock (lock); +@@ -185,7 +185,7 @@ __nss_database_lookup (const char *datab + + return *ni != NULL ? 0 : -1; + } +-libc_hidden_def (__nss_database_lookup) ++libc_hidden_def (__nss_database_lookup2) + + + /* -1 == not found +@@ -260,16 +260,6 @@ __nss_next2 (service_user **ni, const ch + } + libc_hidden_def (__nss_next2) + +- +-int +-attribute_compat_text_section +-__nss_next (service_user **ni, const char *fct_name, void **fctp, int status, +- int all_values) +-{ +- return __nss_next2 (ni, fct_name, NULL, fctp, status, all_values); +-} +- +- + int + __nss_configure_lookup (const char *dbname, const char *service_line) + { +@@ -835,7 +825,7 @@ nss_load_all_libraries (const char *serv + { + service_user *ni = NULL; + +- if (__nss_database_lookup (service, NULL, def, &ni) == 0) ++ if (__nss_database_lookup2 (service, NULL, def, &ni) == 0) + while (ni != NULL) + { + nss_load_library (ni); +diff -rup a/nss/nsswitch.h b/nss/nsswitch.h +--- a/nss/nsswitch.h 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/nsswitch.h 2019-06-06 17:16:59.691114818 -0400 +@@ -125,10 +125,10 @@ extern bool __nss_database_custom[NSS_DB + If there is no configuration for this database in the file, + parse a service list from DEFCONFIG and use that. More + than one function can use the database. */ +-extern int __nss_database_lookup (const char *database, +- const char *alternative_name, +- const char *defconfig, service_user **ni); +-libc_hidden_proto (__nss_database_lookup) ++extern int __nss_database_lookup2 (const char *database, ++ const char *alternative_name, ++ const char *defconfig, service_user **ni); ++libc_hidden_proto (__nss_database_lookup2) + + /* Put first function with name FCT_NAME for SERVICE in FCTP. The + position is remembered in NI. The function returns a value < 0 if +diff -rup a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +--- a/sysdeps/posix/getaddrinfo.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/sysdeps/posix/getaddrinfo.c 2019-06-06 17:16:59.724114827 -0400 +@@ -737,9 +737,9 @@ gaih_inet (const char *name, const struc + #endif + + if (__nss_hosts_database == NULL) +- no_more = __nss_database_lookup ("hosts", NULL, +- "dns [!UNAVAIL=return] files", +- &__nss_hosts_database); ++ no_more = __nss_database_lookup2 ("hosts", NULL, ++ "dns [!UNAVAIL=return] files", ++ &__nss_hosts_database); + else + no_more = 0; + nip = __nss_hosts_database; diff --git a/glibc-rh1717438.patch b/glibc-rh1717438.patch new file mode 100755 index 0000000..8bfaec8 --- /dev/null +++ b/glibc-rh1717438.patch @@ -0,0 +1,71 @@ +commit 11b451c8868d8a2b0edc5dfd44fc58d9ee538be0 +Author: Mark Wielaard +Date: Wed May 15 17:14:01 2019 +0200 + + dlfcn: Guard __dlerror_main_freeres with __libc_once_get (once) [BZ# 24476] + + dlerror.c (__dlerror_main_freeres) will try to free resources which only + have been initialized when init () has been called. That function is + called when resources are needed using __libc_once (once, init) where + once is a __libc_once_define (static, once) in the dlerror.c file. + Trying to free those resources if init () hasn't been called will + produce errors under valgrind memcheck. So guard the freeing of those + resources using __libc_once_get (once) and make sure we have a valid + key. Also add a similar guard to __dlerror (). + + * dlfcn/dlerror.c (__dlerror_main_freeres): Guard using + __libc_once_get (once) and static_bug == NULL. + (__dlerror): Check we have a valid key, set result to static_buf + otherwise. + + Reviewed-by: Carlos O'Donell + +diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c +index 96bf92533335036b..06732460ea1512cd 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/glibc-rh1722215.patch b/glibc-rh1722215.patch new file mode 100755 index 0000000..cbda401 --- /dev/null +++ b/glibc-rh1722215.patch @@ -0,0 +1,186 @@ +commit 21cc130b78a4db9113fb6695e2b951e697662440 +Author: Dmitry V. Levin +Date: Wed Feb 13 01:20:51 2019 +0000 + + libio: do not attempt to free wide buffers of legacy streams [BZ #24228] + + Commit a601b74d31ca086de38441d316a3dee24c866305 aka glibc-2.23~693 + ("In preparation for fixing BZ#16734, fix failure in misc/tst-error1-mem + when _G_HAVE_MMAP is turned off.") introduced a regression: + _IO_unbuffer_all now invokes _IO_wsetb to free wide buffers of all + files, including legacy standard files which are small statically + allocated objects that do not have wide buffers and the _mode member, + causing memory corruption. + + Another memory corruption in _IO_unbuffer_all happens when -1 + is assigned to the _mode member of legacy standard files that + do not have it. + + [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. + +# Conflicts: +# libio/Makefile + +diff --git a/libio/Makefile b/libio/Makefile +index cbfaf3832a45fc22..314e03d5ce72be2d 100644 +--- a/libio/Makefile ++++ b/libio/Makefile +@@ -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 + +@@ -153,11 +156,14 @@ CFLAGS-oldtmpfile.c += -fexceptions + + CFLAGS-tst_putwc.c += -DOBJPFX=\"$(objpfx)\" + ++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 +@@ -166,6 +172,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 + +@@ -180,7 +187,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 + +@@ -232,3 +240,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 2fec221b99729718..a8241dd26640bbcb 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 0000000000000000..6a74500d473ceeab +--- /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 ++ . */ ++ ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ mtrace (); ++ return 0; ++} ++ ++#include +diff --git a/libio/tst-bz24228.map b/libio/tst-bz24228.map +new file mode 100644 +index 0000000000000000..4383e0817d7f5583 +--- /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/glibc-rh1724975.patch b/glibc-rh1724975.patch new file mode 100755 index 0000000..7ea3267 --- /dev/null +++ b/glibc-rh1724975.patch @@ -0,0 +1,1013 @@ +commit 5a659ccc0ec217ab02a4c273a1f6d346a359560a +Author: Florian Weimer +Date: Fri Jun 28 09:39:21 2019 +0200 + + io: Remove copy_file_range emulation [BZ #24744] + + The kernel is evolving this interface (e.g., removal of the + restriction on cross-device copies), and keeping up with that + is difficult. Applications which need the function should + run kernels which support the system call instead of relying on + the imperfect glibc emulation. + + Reviewed-by: Adhemerval Zanella + +# Conflicts: +# io/copy_file_range-compat.c +# io/copy_file_range.c +# io/tst-copy_file_range-compat.c +# io/tst-copy_file_range.c +# sysdeps/unix/sysv/linux/arm/kernel-features.h +# sysdeps/unix/sysv/linux/microblaze/kernel-features.h +# sysdeps/unix/sysv/linux/sh/kernel-features.h + +diff --git a/io/Makefile b/io/Makefile +index 787a5c550ab64b17..62e71b4cbe879dbc 100644 +--- a/io/Makefile ++++ b/io/Makefile +@@ -75,11 +75,6 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \ + tst-fts tst-fts-lfs tst-open-tmpfile \ + tst-copy_file_range tst-getcwd-abspath \ + +-# This test includes the compat implementation of copy_file_range, +-# which uses internal, unexported libc functions. +-tests-static += tst-copy_file_range-compat +-tests-internal += tst-copy_file_range-compat +- + # Likewise for statx, but we do not need static linking here. + tests-internal += tst-statx + +diff --git a/io/copy_file_range-compat.c b/io/copy_file_range-compat.c +deleted file mode 100644 +index 4ab22cad19146ca9..0000000000000000 +--- a/io/copy_file_range-compat.c ++++ /dev/null +@@ -1,160 +0,0 @@ +-/* Emulation of copy_file_range. +- Copyright (C) 2017-2018 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 +- . */ +- +-/* The following macros should be defined before including this +- file: +- +- COPY_FILE_RANGE_DECL Declaration specifiers for the function below. +- COPY_FILE_RANGE Name of the function to define. */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-COPY_FILE_RANGE_DECL +-ssize_t +-COPY_FILE_RANGE (int infd, __off64_t *pinoff, +- int outfd, __off64_t *poutoff, +- size_t length, unsigned int flags) +-{ +- if (flags != 0) +- { +- __set_errno (EINVAL); +- return -1; +- } +- +- { +- struct stat64 instat; +- struct stat64 outstat; +- if (fstat64 (infd, &instat) != 0 || fstat64 (outfd, &outstat) != 0) +- return -1; +- if (S_ISDIR (instat.st_mode) || S_ISDIR (outstat.st_mode)) +- { +- __set_errno (EISDIR); +- return -1; +- } +- if (!S_ISREG (instat.st_mode) || !S_ISREG (outstat.st_mode)) +- { +- /* We need a regular input file so that the we can seek +- backwards in case of a write failure. */ +- __set_errno (EINVAL); +- return -1; +- } +- if (instat.st_dev != outstat.st_dev) +- { +- /* Cross-device copies are not supported. */ +- __set_errno (EXDEV); +- return -1; +- } +- } +- +- /* The output descriptor must not have O_APPEND set. */ +- { +- int flags = __fcntl (outfd, F_GETFL); +- if (flags & O_APPEND) +- { +- __set_errno (EBADF); +- return -1; +- } +- } +- +- /* Avoid an overflow in the result. */ +- if (length > SSIZE_MAX) +- length = SSIZE_MAX; +- +- /* Main copying loop. The buffer size is arbitrary and is a +- trade-off between stack size consumption, cache usage, and +- amortization of system call overhead. */ +- size_t copied = 0; +- char buf[8192]; +- while (length > 0) +- { +- size_t to_read = length; +- if (to_read > sizeof (buf)) +- to_read = sizeof (buf); +- +- /* Fill the buffer. */ +- ssize_t read_count; +- if (pinoff == NULL) +- read_count = read (infd, buf, to_read); +- else +- read_count = __libc_pread64 (infd, buf, to_read, *pinoff); +- if (read_count == 0) +- /* End of file reached prematurely. */ +- return copied; +- if (read_count < 0) +- { +- if (copied > 0) +- /* Report the number of bytes copied so far. */ +- return copied; +- return -1; +- } +- if (pinoff != NULL) +- *pinoff += read_count; +- +- /* Write the buffer part which was read to the destination. */ +- char *end = buf + read_count; +- for (char *p = buf; p < end; ) +- { +- ssize_t write_count; +- if (poutoff == NULL) +- write_count = write (outfd, p, end - p); +- else +- write_count = __libc_pwrite64 (outfd, p, end - p, *poutoff); +- if (write_count < 0) +- { +- /* Adjust the input read position to match what we have +- written, so that the caller can pick up after the +- error. */ +- size_t written = p - buf; +- /* NB: This needs to be signed so that we can form the +- negative value below. */ +- ssize_t overread = read_count - written; +- if (pinoff == NULL) +- { +- if (overread > 0) +- { +- /* We are on an error recovery path, so we +- cannot deal with failure here. */ +- int save_errno = errno; +- (void) __libc_lseek64 (infd, -overread, SEEK_CUR); +- __set_errno (save_errno); +- } +- } +- else /* pinoff != NULL */ +- *pinoff -= overread; +- +- if (copied + written > 0) +- /* Report the number of bytes copied so far. */ +- return copied + written; +- return -1; +- } +- p += write_count; +- if (poutoff != NULL) +- *poutoff += write_count; +- } /* Write loop. */ +- +- copied += read_count; +- length -= read_count; +- } +- return copied; +-} +diff --git a/io/copy_file_range.c b/io/copy_file_range.c +index 98bff8bd2615b214..59fb979773b2b202 100644 +--- a/io/copy_file_range.c ++++ b/io/copy_file_range.c +@@ -1,5 +1,5 @@ +-/* Generic implementation of copy_file_range. +- Copyright (C) 2017-2018 Free Software Foundation, Inc. ++/* Stub implementation of copy_file_range. ++ Copyright (C) 2017-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 +@@ -16,7 +16,15 @@ + License along with the GNU C Library; if not, see + . */ + +-#define COPY_FILE_RANGE_DECL +-#define COPY_FILE_RANGE copy_file_range ++#include ++#include + +-#include ++ssize_t ++copy_file_range (int infd, __off64_t *pinoff, ++ int outfd, __off64_t *poutoff, ++ size_t length, unsigned int flags) ++{ ++ __set_errno (ENOSYS); ++ return -1; ++} ++stub_warning (copy_file_range) +diff --git a/io/tst-copy_file_range-compat.c b/io/tst-copy_file_range-compat.c +deleted file mode 100644 +index 00c109a74d3c9d64..0000000000000000 +--- a/io/tst-copy_file_range-compat.c ++++ /dev/null +@@ -1,30 +0,0 @@ +-/* Test the fallback implementation of copy_file_range. +- Copyright (C) 2017-2018 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 +- . */ +- +-/* Get the declaration of the official copy_of_range function. */ +-#include +- +-/* Compile a local version of copy_file_range. */ +-#define COPY_FILE_RANGE_DECL static +-#define COPY_FILE_RANGE copy_file_range_compat +-#include +- +-/* Re-use the test, but run it against copy_file_range_compat defined +- above. */ +-#define copy_file_range copy_file_range_compat +-#include "tst-copy_file_range.c" +diff --git a/io/tst-copy_file_range.c b/io/tst-copy_file_range.c +index 3d531a19370911e5..4504020d2ee7d2ee 100644 +--- a/io/tst-copy_file_range.c ++++ b/io/tst-copy_file_range.c +@@ -20,22 +20,15 @@ + #include + #include + #include +-#include +-#include +-#include + #include + #include + #include + #include + #include +-#include + #include + #include + #include + #include +-#ifdef CLONE_NEWNS +-# include +-#endif + + /* Boolean flags which indicate whether to use pointers with explicit + output flags. */ +@@ -49,10 +42,6 @@ static int infd; + static char *outfile; + static int outfd; + +-/* Like the above, but on a different file system. xdevfile can be +- NULL if no suitable file system has been found. */ +-static char *xdevfile; +- + /* Input and output offsets. Set according to do_inoff and do_outoff + before the test. The offsets themselves are always set to + zero. */ +@@ -61,13 +50,10 @@ static off64_t *pinoff; + static off64_t outoff; + static off64_t *poutoff; + +-/* These are a collection of copy sizes used in tests. The selection +- takes into account that the fallback implementation uses an +- internal buffer of 8192 bytes. */ ++/* These are a collection of copy sizes used in tests. */ + enum { maximum_size = 99999 }; + static const int typical_sizes[] = +- { 0, 1, 2, 3, 1024, 2048, 4096, 8191, 8192, 8193, 16383, 16384, 16385, +- maximum_size }; ++ { 0, 1, 2, 3, 1024, 2048, 4096, 8191, 8192, 8193, maximum_size }; + + /* The random contents of this array can be used as a pattern to check + for correct write operations. */ +@@ -76,101 +62,6 @@ static unsigned char random_data[maximum_size]; + /* The size chosen by the test harness. */ + static int current_size; + +-/* Maximum writable file offset. Updated by find_maximum_offset +- below. */ +-static off64_t maximum_offset; +- +-/* Error code when crossing the offset. */ +-static int maximum_offset_errno; +- +-/* If true: Writes which cross the limit will fail. If false: Writes +- which cross the limit will result in a partial write. */ +-static bool maximum_offset_hard_limit; +- +-/* Fills maximum_offset etc. above. Truncates outfd as a side +- effect. */ +-static void +-find_maximum_offset (void) +-{ +- xftruncate (outfd, 0); +- if (maximum_offset != 0) +- return; +- +- uint64_t upper = -1; +- upper >>= 1; /* Maximum of off64_t. */ +- TEST_VERIFY ((off64_t) upper > 0); +- TEST_VERIFY ((off64_t) (upper + 1) < 0); +- if (lseek64 (outfd, upper, SEEK_SET) >= 0) +- { +- if (write (outfd, "", 1) == 1) +- FAIL_EXIT1 ("created a file larger than the off64_t range"); +- } +- +- uint64_t lower = 1024 * 1024; /* A reasonable minimum file size. */ +- /* Loop invariant: writing at lower succeeds, writing at upper fails. */ +- while (lower + 1 < upper) +- { +- uint64_t middle = (lower + upper) / 2; +- if (test_verbose > 0) +- printf ("info: %s: remaining test range %" PRIu64 " .. %" PRIu64 +- ", probe at %" PRIu64 "\n", __func__, lower, upper, middle); +- xftruncate (outfd, 0); +- if (lseek64 (outfd, middle, SEEK_SET) >= 0 +- && write (outfd, "", 1) == 1) +- lower = middle; +- else +- upper = middle; +- } +- TEST_VERIFY (lower + 1 == upper); +- maximum_offset = lower; +- printf ("info: maximum writable file offset: %" PRIu64 " (%" PRIx64 ")\n", +- lower, lower); +- +- /* Check that writing at the valid offset actually works. */ +- xftruncate (outfd, 0); +- xlseek (outfd, lower, SEEK_SET); +- TEST_COMPARE (write (outfd, "", 1), 1); +- +- /* Cross the boundary with a two-byte write. This can either result +- in a short write, or a failure. */ +- xlseek (outfd, lower, SEEK_SET); +- ssize_t ret = write (outfd, " ", 2); +- if (ret < 0) +- { +- maximum_offset_errno = errno; +- maximum_offset_hard_limit = true; +- } +- else +- maximum_offset_hard_limit = false; +- +- /* Check that writing at the next offset actually fails. This also +- obtains the expected errno value. */ +- xftruncate (outfd, 0); +- const char *action; +- if (lseek64 (outfd, lower + 1, SEEK_SET) != 0) +- { +- if (write (outfd, "", 1) != -1) +- FAIL_EXIT1 ("write to impossible offset %" PRIu64 " succeeded", +- lower + 1); +- action = "writing"; +- int errno_copy = errno; +- if (maximum_offset_hard_limit) +- TEST_COMPARE (errno_copy, maximum_offset_errno); +- else +- maximum_offset_errno = errno_copy; +- } +- else +- { +- action = "seeking"; +- maximum_offset_errno = errno; +- } +- printf ("info: %s out of range fails with %m (%d)\n", +- action, maximum_offset_errno); +- +- xftruncate (outfd, 0); +- xlseek (outfd, 0, SEEK_SET); +-} +- + /* Perform a copy of a file. */ + static void + simple_file_copy (void) +@@ -247,390 +138,6 @@ simple_file_copy (void) + free (bytes); + } + +-/* Test that reading from a pipe willfails. */ +-static void +-pipe_as_source (void) +-{ +- int pipefds[2]; +- xpipe (pipefds); +- +- for (int length = 0; length < 2; ++length) +- { +- if (test_verbose > 0) +- printf ("info: %s: length=%d\n", __func__, length); +- +- /* Make sure that there is something to copy in the pipe. */ +- xwrite (pipefds[1], "@", 1); +- +- TEST_COMPARE (copy_file_range (pipefds[0], pinoff, outfd, poutoff, +- length, 0), -1); +- /* Linux 4.10 and later return EINVAL. Older kernels return +- EXDEV. */ +- TEST_VERIFY (errno == EINVAL || errno == EXDEV); +- TEST_COMPARE (inoff, 0); +- TEST_COMPARE (outoff, 0); +- TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), 0); +- +- /* Make sure that nothing was read. */ +- char buf = 'A'; +- TEST_COMPARE (read (pipefds[0], &buf, 1), 1); +- TEST_COMPARE (buf, '@'); +- } +- +- xclose (pipefds[0]); +- xclose (pipefds[1]); +-} +- +-/* Test that writing to a pipe fails. */ +-static void +-pipe_as_destination (void) +-{ +- /* Make sure that there is something to read in the input file. */ +- xwrite (infd, "abc", 3); +- xlseek (infd, 0, SEEK_SET); +- +- int pipefds[2]; +- xpipe (pipefds); +- +- for (int length = 0; length < 2; ++length) +- { +- if (test_verbose > 0) +- printf ("info: %s: length=%d\n", __func__, length); +- +- TEST_COMPARE (copy_file_range (infd, pinoff, pipefds[1], poutoff, +- length, 0), -1); +- /* Linux 4.10 and later return EINVAL. Older kernels return +- EXDEV. */ +- TEST_VERIFY (errno == EINVAL || errno == EXDEV); +- TEST_COMPARE (inoff, 0); +- TEST_COMPARE (outoff, 0); +- TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0); +- +- /* Make sure that nothing was written. */ +- struct pollfd pollfd = { .fd = pipefds[0], .events = POLLIN, }; +- TEST_COMPARE (poll (&pollfd, 1, 0), 0); +- } +- +- xclose (pipefds[0]); +- xclose (pipefds[1]); +-} +- +-/* Test a write failure after (potentially) writing some bytes. +- Failure occurs near the start of the buffer. */ +-static void +-delayed_write_failure_beginning (void) +-{ +- /* We need to write something to provoke the error. */ +- if (current_size == 0) +- return; +- xwrite (infd, random_data, sizeof (random_data)); +- xlseek (infd, 0, SEEK_SET); +- +- /* Write failure near the start. The actual error code varies among +- file systems. */ +- find_maximum_offset (); +- off64_t where = maximum_offset; +- +- if (current_size == 1) +- ++where; +- outoff = where; +- if (do_outoff) +- xlseek (outfd, 1, SEEK_SET); +- else +- xlseek (outfd, where, SEEK_SET); +- if (maximum_offset_hard_limit || where > maximum_offset) +- { +- TEST_COMPARE (copy_file_range (infd, pinoff, outfd, poutoff, +- sizeof (random_data), 0), -1); +- TEST_COMPARE (errno, maximum_offset_errno); +- TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0); +- TEST_COMPARE (inoff, 0); +- if (do_outoff) +- TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), 1); +- else +- TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), where); +- TEST_COMPARE (outoff, where); +- struct stat64 st; +- xfstat (outfd, &st); +- TEST_COMPARE (st.st_size, 0); +- } +- else +- { +- /* The offset is not a hard limit. This means we write one +- byte. */ +- TEST_COMPARE (copy_file_range (infd, pinoff, outfd, poutoff, +- sizeof (random_data), 0), 1); +- if (do_inoff) +- { +- TEST_COMPARE (inoff, 1); +- TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0); +- } +- else +- { +- TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 1); +- TEST_COMPARE (inoff, 0); +- } +- if (do_outoff) +- { +- TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), 1); +- TEST_COMPARE (outoff, where + 1); +- } +- else +- { +- TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), where + 1); +- TEST_COMPARE (outoff, where); +- } +- struct stat64 st; +- xfstat (outfd, &st); +- TEST_COMPARE (st.st_size, where + 1); +- } +-} +- +-/* Test a write failure after (potentially) writing some bytes. +- Failure occurs near the end of the buffer. */ +-static void +-delayed_write_failure_end (void) +-{ +- if (current_size <= 1) +- /* This would be same as the first test because there is not +- enough data to write to make a difference. */ +- return; +- xwrite (infd, random_data, sizeof (random_data)); +- xlseek (infd, 0, SEEK_SET); +- +- find_maximum_offset (); +- off64_t where = maximum_offset - current_size + 1; +- if (current_size == sizeof (random_data)) +- /* Otherwise we do not reach the non-writable byte. */ +- ++where; +- outoff = where; +- if (do_outoff) +- xlseek (outfd, 1, SEEK_SET); +- else +- xlseek (outfd, where, SEEK_SET); +- ssize_t ret = copy_file_range (infd, pinoff, outfd, poutoff, +- sizeof (random_data), 0); +- if (ret < 0) +- { +- TEST_COMPARE (ret, -1); +- TEST_COMPARE (errno, maximum_offset_errno); +- struct stat64 st; +- xfstat (outfd, &st); +- TEST_COMPARE (st.st_size, 0); +- } +- else +- { +- /* The first copy succeeded. This happens in the emulation +- because the internal buffer of limited size does not +- necessarily cross the off64_t boundary on the first write +- operation. */ +- if (test_verbose > 0) +- printf ("info: copy_file_range (%zu) returned %zd\n", +- sizeof (random_data), ret); +- TEST_VERIFY (ret > 0); +- TEST_VERIFY (ret < maximum_size); +- struct stat64 st; +- xfstat (outfd, &st); +- TEST_COMPARE (st.st_size, where + ret); +- if (do_inoff) +- { +- TEST_COMPARE (inoff, ret); +- TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0); +- } +- else +- TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), ret); +- +- char *buffer = xmalloc (ret); +- TEST_COMPARE (pread64 (outfd, buffer, ret, where), ret); +- TEST_VERIFY (memcmp (buffer, random_data, ret) == 0); +- free (buffer); +- +- /* The second copy fails. */ +- TEST_COMPARE (copy_file_range (infd, pinoff, outfd, poutoff, +- sizeof (random_data), 0), -1); +- TEST_COMPARE (errno, maximum_offset_errno); +- } +-} +- +-/* Test a write failure across devices. */ +-static void +-cross_device_failure (void) +-{ +- if (xdevfile == NULL) +- /* Subtest not supported due to missing cross-device file. */ +- return; +- +- /* We need something to write. */ +- xwrite (infd, random_data, sizeof (random_data)); +- xlseek (infd, 0, SEEK_SET); +- +- int xdevfd = xopen (xdevfile, O_RDWR | O_LARGEFILE, 0); +- TEST_COMPARE (copy_file_range (infd, pinoff, xdevfd, poutoff, +- current_size, 0), -1); +- TEST_COMPARE (errno, EXDEV); +- TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0); +- struct stat64 st; +- xfstat (xdevfd, &st); +- TEST_COMPARE (st.st_size, 0); +- +- xclose (xdevfd); +-} +- +-/* Try to exercise ENOSPC behavior with a tempfs file system (so that +- we do not have to fill up a regular file system to get the error). +- This function runs in a subprocess, so that we do not change the +- mount namespace of the actual test process. */ +-static void +-enospc_failure_1 (void *closure) +-{ +-#ifdef CLONE_NEWNS +- support_become_root (); +- +- /* Make sure that we do not alter the file system mounts of the +- parents. */ +- if (! support_enter_mount_namespace ()) +- { +- printf ("warning: ENOSPC test skipped\n"); +- return; +- } +- +- char *mountpoint = closure; +- if (mount ("none", mountpoint, "tmpfs", MS_NODEV | MS_NOEXEC, +- "size=500k") != 0) +- { +- printf ("warning: could not mount tmpfs at %s: %m\n", mountpoint); +- return; +- } +- +- /* The source file must reside on the same file system. */ +- char *intmpfsfile = xasprintf ("%s/%s", mountpoint, "in"); +- int intmpfsfd = xopen (intmpfsfile, O_RDWR | O_CREAT | O_LARGEFILE, 0600); +- xwrite (intmpfsfd, random_data, sizeof (random_data)); +- xlseek (intmpfsfd, 1, SEEK_SET); +- inoff = 1; +- +- char *outtmpfsfile = xasprintf ("%s/%s", mountpoint, "out"); +- int outtmpfsfd = xopen (outtmpfsfile, O_RDWR | O_CREAT | O_LARGEFILE, 0600); +- +- /* Fill the file with data until ENOSPC is reached. */ +- while (true) +- { +- ssize_t ret = write (outtmpfsfd, random_data, sizeof (random_data)); +- if (ret < 0 && errno != ENOSPC) +- FAIL_EXIT1 ("write to %s: %m", outtmpfsfile); +- if (ret < sizeof (random_data)) +- break; +- } +- TEST_COMPARE (write (outtmpfsfd, "", 1), -1); +- TEST_COMPARE (errno, ENOSPC); +- off64_t maxsize = xlseek (outtmpfsfd, 0, SEEK_CUR); +- TEST_VERIFY_EXIT (maxsize > sizeof (random_data)); +- +- /* Constructed the expected file contents. */ +- char *expected = xmalloc (maxsize); +- TEST_COMPARE (pread64 (outtmpfsfd, expected, maxsize, 0), maxsize); +- /* Go back a little, so some bytes can be written. */ +- enum { offset = 20000 }; +- TEST_VERIFY_EXIT (offset < maxsize); +- TEST_VERIFY_EXIT (offset < sizeof (random_data)); +- memcpy (expected + maxsize - offset, random_data + 1, offset); +- +- if (do_outoff) +- { +- outoff = maxsize - offset; +- xlseek (outtmpfsfd, 2, SEEK_SET); +- } +- else +- xlseek (outtmpfsfd, -offset, SEEK_CUR); +- +- /* First call is expected to succeed because we made room for some +- bytes. */ +- TEST_COMPARE (copy_file_range (intmpfsfd, pinoff, outtmpfsfd, poutoff, +- maximum_size, 0), offset); +- if (do_inoff) +- { +- TEST_COMPARE (inoff, 1 + offset); +- TEST_COMPARE (xlseek (intmpfsfd, 0, SEEK_CUR), 1); +- } +- else +- TEST_COMPARE (xlseek (intmpfsfd, 0, SEEK_CUR), 1 + offset); +- if (do_outoff) +- { +- TEST_COMPARE (outoff, maxsize); +- TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_CUR), 2); +- } +- else +- TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_CUR), maxsize); +- struct stat64 st; +- xfstat (outtmpfsfd, &st); +- TEST_COMPARE (st.st_size, maxsize); +- char *actual = xmalloc (st.st_size); +- TEST_COMPARE (pread64 (outtmpfsfd, actual, st.st_size, 0), st.st_size); +- TEST_VERIFY (memcmp (expected, actual, maxsize) == 0); +- +- /* Second call should fail with ENOSPC. */ +- TEST_COMPARE (copy_file_range (intmpfsfd, pinoff, outtmpfsfd, poutoff, +- maximum_size, 0), -1); +- TEST_COMPARE (errno, ENOSPC); +- +- /* Offsets should be unchanged. */ +- if (do_inoff) +- { +- TEST_COMPARE (inoff, 1 + offset); +- TEST_COMPARE (xlseek (intmpfsfd, 0, SEEK_CUR), 1); +- } +- else +- TEST_COMPARE (xlseek (intmpfsfd, 0, SEEK_CUR), 1 + offset); +- if (do_outoff) +- { +- TEST_COMPARE (outoff, maxsize); +- TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_CUR), 2); +- } +- else +- TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_CUR), maxsize); +- TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_END), maxsize); +- TEST_COMPARE (pread64 (outtmpfsfd, actual, maxsize, 0), maxsize); +- TEST_VERIFY (memcmp (expected, actual, maxsize) == 0); +- +- free (actual); +- free (expected); +- +- xclose (intmpfsfd); +- xclose (outtmpfsfd); +- free (intmpfsfile); +- free (outtmpfsfile); +- +-#else /* !CLONE_NEWNS */ +- puts ("warning: ENOSPC test skipped (no mount namespaces)"); +-#endif +-} +- +-/* Call enospc_failure_1 in a subprocess. */ +-static void +-enospc_failure (void) +-{ +- char *mountpoint +- = support_create_temp_directory ("tst-copy_file_range-enospc-"); +- support_isolate_in_subprocess (enospc_failure_1, mountpoint); +- free (mountpoint); +-} +- +-/* The target file descriptor must have O_APPEND enabled. */ +-static void +-oappend_failure (void) +-{ +- /* Add data, to make sure we do not fail because there is +- insufficient input data. */ +- xwrite (infd, random_data, current_size); +- xlseek (infd, 0, SEEK_SET); +- +- xclose (outfd); +- outfd = xopen (outfile, O_RDWR | O_APPEND, 0); +- TEST_COMPARE (copy_file_range (infd, pinoff, outfd, poutoff, +- current_size, 0), -1); +- TEST_COMPARE (errno, EBADF); +-} +- + /* Test that a short input file results in a shortened copy. */ + static void + short_copy (void) +@@ -721,14 +228,6 @@ struct test_case + static struct test_case tests[] = + { + { "simple_file_copy", simple_file_copy, .sizes = true }, +- { "pipe_as_source", pipe_as_source, }, +- { "pipe_as_destination", pipe_as_destination, }, +- { "delayed_write_failure_beginning", delayed_write_failure_beginning, +- .sizes = true }, +- { "delayed_write_failure_end", delayed_write_failure_end, .sizes = true }, +- { "cross_device_failure", cross_device_failure, .sizes = true }, +- { "enospc_failure", enospc_failure, }, +- { "oappend_failure", oappend_failure, .sizes = true }, + { "short_copy", short_copy, .sizes = true }, + }; + +@@ -739,53 +238,18 @@ do_test (void) + *p = rand () >> 24; + + infd = create_temp_file ("tst-copy_file_range-in-", &infile); +- xclose (create_temp_file ("tst-copy_file_range-out-", &outfile)); +- +- /* Try to find a different directory from the default input/output +- file. */ ++ outfd = create_temp_file ("tst-copy_file_range-out-", &outfile); + { +- struct stat64 instat; +- xfstat (infd, &instat); +- static const char *const candidates[] = +- { NULL, "/var/tmp", "/dev/shm" }; +- for (const char *const *c = candidates; c < array_end (candidates); ++c) +- { +- const char *path = *c; +- char *to_free = NULL; +- if (path == NULL) +- { +- to_free = xreadlink ("/proc/self/exe"); +- path = dirname (to_free); +- } +- +- struct stat64 cstat; +- xstat (path, &cstat); +- if (cstat.st_dev == instat.st_dev) +- { +- free (to_free); +- continue; +- } +- +- printf ("info: using alternate temporary files directory: %s\n", path); +- xdevfile = xasprintf ("%s/tst-copy_file_range-xdev-XXXXXX", path); +- free (to_free); +- break; +- } +- if (xdevfile != NULL) ++ ssize_t ret = copy_file_range (infd, NULL, outfd, NULL, 0, 0); ++ if (ret != 0) + { +- int xdevfd = mkstemp (xdevfile); +- if (xdevfd < 0) +- FAIL_EXIT1 ("mkstemp (\"%s\"): %m", xdevfile); +- struct stat64 xdevst; +- xfstat (xdevfd, &xdevst); +- TEST_VERIFY (xdevst.st_dev != instat.st_dev); +- add_temp_file (xdevfile); +- xclose (xdevfd); ++ if (errno == ENOSYS) ++ FAIL_UNSUPPORTED ("copy_file_range is not support on this system"); ++ FAIL_EXIT1 ("copy_file_range probing call: %m"); + } +- else +- puts ("warning: no alternate directory on different file system found"); + } + xclose (infd); ++ xclose (outfd); + + for (do_inoff = 0; do_inoff < 2; ++do_inoff) + for (do_outoff = 0; do_outoff < 2; ++do_outoff) +@@ -827,7 +291,6 @@ do_test (void) + + free (infile); + free (outfile); +- free (xdevfile); + + return 0; + } +diff --git a/manual/llio.texi b/manual/llio.texi +index 2733b9cb7331df07..26f7d2cb3ea220d9 100644 +--- a/manual/llio.texi ++++ b/manual/llio.texi +@@ -1404,10 +1404,13 @@ failure occurs. The return value is zero if the end of the input file + is encountered immediately. + + If no bytes can be copied, to report an error, @code{copy_file_range} +-returns the value @math{-1} and sets @code{errno}. The following +-@code{errno} error conditions are specific to this function: ++returns the value @math{-1} and sets @code{errno}. The table below ++lists some of the error conditions for this function. + + @table @code ++@item ENOSYS ++The kernel does not implement the required functionality. ++ + @item EISDIR + At least one of the descriptors @var{inputfd} or @var{outputfd} refers + to a directory. +@@ -1437,9 +1440,6 @@ reading. + + The argument @var{outputfd} is not a valid file descriptor open for + writing, or @var{outputfd} has been opened with @code{O_APPEND}. +- +-@item EXDEV +-The input and output files reside on different file systems. + @end table + + In addition, @code{copy_file_range} can fail with the error codes +diff --git a/sysdeps/unix/sysv/linux/alpha/kernel-features.h b/sysdeps/unix/sysv/linux/alpha/kernel-features.h +index 402d2573d75794d5..26344cd610a1f8e7 100644 +--- a/sysdeps/unix/sysv/linux/alpha/kernel-features.h ++++ b/sysdeps/unix/sysv/linux/alpha/kernel-features.h +@@ -48,7 +48,6 @@ + /* Support for copy_file_range, statx was added in kernel 4.13. */ + #if __LINUX_KERNEL_VERSION < 0x040D00 + # undef __ASSUME_MLOCK2 +-# undef __ASSUME_COPY_FILE_RANGE + # undef __ASSUME_STATX + #endif + +diff --git a/sysdeps/unix/sysv/linux/copy_file_range.c b/sysdeps/unix/sysv/linux/copy_file_range.c +index 7b1a50f7529f2a84..b88b7c9e2ecd825f 100644 +--- a/sysdeps/unix/sysv/linux/copy_file_range.c ++++ b/sysdeps/unix/sysv/linux/copy_file_range.c +@@ -20,27 +20,16 @@ + #include + #include + +-/* Include the fallback implementation. */ +-#ifndef __ASSUME_COPY_FILE_RANGE +-#define COPY_FILE_RANGE_DECL static +-#define COPY_FILE_RANGE copy_file_range_compat +-#include +-#endif +- + ssize_t + copy_file_range (int infd, __off64_t *pinoff, + int outfd, __off64_t *poutoff, + size_t length, unsigned int flags) + { + #ifdef __NR_copy_file_range +- ssize_t ret = SYSCALL_CANCEL (copy_file_range, infd, pinoff, outfd, poutoff, +- length, flags); +-# ifndef __ASSUME_COPY_FILE_RANGE +- if (ret == -1 && errno == ENOSYS) +- ret = copy_file_range_compat (infd, pinoff, outfd, poutoff, length, flags); +-# endif +- return ret; +-#else /* !__NR_copy_file_range */ +- return copy_file_range_compat (infd, pinoff, outfd, poutoff, length, flags); ++ return SYSCALL_CANCEL (copy_file_range, infd, pinoff, outfd, poutoff, ++ length, flags); ++#else ++ __set_errno (ENOSYS); ++ return -1; + #endif + } +diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h +index 5543d92d7e32e501..7a74835495250268 100644 +--- a/sysdeps/unix/sysv/linux/kernel-features.h ++++ b/sysdeps/unix/sysv/linux/kernel-features.h +@@ -111,10 +111,6 @@ + # define __ASSUME_MLOCK2 1 + #endif + +-#if __LINUX_KERNEL_VERSION >= 0x040500 +-# define __ASSUME_COPY_FILE_RANGE 1 +-#endif +- + /* Support for statx was added in kernel 4.11. */ + #if __LINUX_KERNEL_VERSION >= 0x040B00 + # define __ASSUME_STATX 1 +diff --git a/sysdeps/unix/sysv/linux/microblaze/kernel-features.h b/sysdeps/unix/sysv/linux/microblaze/kernel-features.h +index e8e2ac6a873126ac..1c49f099b7993f1d 100644 +--- a/sysdeps/unix/sysv/linux/microblaze/kernel-features.h ++++ b/sysdeps/unix/sysv/linux/microblaze/kernel-features.h +@@ -58,11 +58,6 @@ + # undef __ASSUME_EXECVEAT + #endif + +-/* Support for the copy_file_range syscall was added in 4.10. */ +-#if __LINUX_KERNEL_VERSION < 0x040A00 +-# undef __ASSUME_COPY_FILE_RANGE +-#endif +- + /* Support for statx was added in kernel 4.12. */ + #if __LINUX_KERNEL_VERSION < 0X040C00 + # undef __ASSUME_STATX diff --git a/glibc-rh1726638-1.patch b/glibc-rh1726638-1.patch new file mode 100755 index 0000000..96c2b21 --- /dev/null +++ b/glibc-rh1726638-1.patch @@ -0,0 +1,35 @@ +commit 55f82d328d2dd1c7c13c1992f4b9bf9c95b57551 +Author: Szabolcs Nagy +Date: Thu Apr 25 15:35:35 2019 +0100 + + aarch64: add STO_AARCH64_VARIANT_PCS and DT_AARCH64_VARIANT_PCS + + STO_AARCH64_VARIANT_PCS is a non-visibility st_other flag for marking + symbols that reference functions that may follow a variant PCS with + different register usage convention from the base PCS. + + DT_AARCH64_VARIANT_PCS is a dynamic tag that marks ELF modules that + have R_*_JUMP_SLOT relocations for symbols marked with + STO_AARCH64_VARIANT_PCS (i.e. have variant PCS calls via a PLT). + + * elf/elf.h (STO_AARCH64_VARIANT_PCS): Define. + (DT_AARCH64_VARIANT_PCS): Define. + +diff --git a/elf/elf.h b/elf/elf.h +index 7e2b072a7f75451c..74f7f479ce817040 100644 +--- a/elf/elf.h ++++ b/elf/elf.h +@@ -2847,6 +2847,13 @@ enum + #define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */ + #define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */ + ++/* AArch64 specific values for the Dyn d_tag field. */ ++#define DT_AARCH64_VARIANT_PCS (DT_LOPROC + 5) ++#define DT_AARCH64_NUM 6 ++ ++/* AArch64 specific values for the st_other field. */ ++#define STO_AARCH64_VARIANT_PCS 0x80 ++ + /* ARM relocs. */ + + #define R_ARM_NONE 0 /* No reloc */ diff --git a/glibc-rh1726638-2.patch b/glibc-rh1726638-2.patch new file mode 100755 index 0000000..f321c7a --- /dev/null +++ b/glibc-rh1726638-2.patch @@ -0,0 +1,138 @@ +commit 82bc69c012838a381c4167c156a06f4598f34227 +Author: Szabolcs Nagy +Date: Thu Apr 25 15:35:35 2019 +0100 + + aarch64: handle STO_AARCH64_VARIANT_PCS + + Avoid lazy binding of symbols that may follow a variant PCS with different + register usage convention from the base PCS. + + Currently the lazy binding entry code does not preserve all the registers + required for AdvSIMD and SVE vector calls. Saving and restoring all + registers unconditionally may break existing binaries, even if they never + use vector calls, because of the larger stack requirement for lazy + resolution, which can be significant on an SVE system. + + The solution is to mark all symbols in the symbol table that may follow + a variant PCS so the dynamic linker can handle them specially. In this + patch such symbols are always resolved at load time, not lazily. + + So currently LD_AUDIT for variant PCS symbols are not supported, for that + the _dl_runtime_profile entry needs to be changed e.g. to unconditionally + save/restore all registers (but pass down arg and retval registers to + pltentry/exit callbacks according to the base PCS). + + This patch also removes a __builtin_expect from the modified code because + the branch prediction hint did not seem useful. + + * sysdeps/aarch64/dl-dtprocnum.h: New file. + * sysdeps/aarch64/dl-machine.h (DT_AARCH64): Define. + (elf_machine_runtime_setup): Handle DT_AARCH64_VARIANT_PCS. + (elf_machine_lazy_rel): Check STO_AARCH64_VARIANT_PCS and bind such + symbols at load time. + * sysdeps/aarch64/linkmap.h (struct link_map_machine): Add variant_pcs. + +diff --git a/sysdeps/aarch64/dl-dtprocnum.h b/sysdeps/aarch64/dl-dtprocnum.h +new file mode 100644 +index 0000000000000000..4ac2adf23458e02d +--- /dev/null ++++ b/sysdeps/aarch64/dl-dtprocnum.h +@@ -0,0 +1,21 @@ ++/* Configuration of lookup functions. AArch64 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 ++ . */ ++ ++/* Number of extra dynamic section entries for this architecture. By ++ default there are none. */ ++#define DT_THISPROCNUM DT_AARCH64_NUM +diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h +index 4935aa7c543876db..d4494852b32b8783 100644 +--- a/sysdeps/aarch64/dl-machine.h ++++ b/sysdeps/aarch64/dl-machine.h +@@ -27,6 +27,9 @@ + #include + #include + ++/* Translate a processor specific dynamic tag to the index in l_info array. */ ++#define DT_AARCH64(x) (DT_AARCH64_##x - DT_LOPROC + DT_NUM) ++ + /* Return nonzero iff ELF header is compatible with the running host. */ + static inline int __attribute__ ((unused)) + elf_machine_matches_host (const ElfW(Ehdr) *ehdr) +@@ -102,6 +105,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + } + } + ++ /* Check if STO_AARCH64_VARIANT_PCS needs to be handled. */ ++ if (l->l_info[DT_AARCH64 (VARIANT_PCS)]) ++ l->l_mach.variant_pcs = 1; ++ + return lazy; + } + +@@ -388,10 +395,37 @@ elf_machine_lazy_rel (struct link_map *map, + /* Check for unexpected PLT reloc type. */ + if (__builtin_expect (r_type == AARCH64_R(JUMP_SLOT), 1)) + { +- if (__builtin_expect (map->l_mach.plt, 0) == 0) +- *reloc_addr += l_addr; +- else +- *reloc_addr = map->l_mach.plt; ++ if (map->l_mach.plt == 0) ++ { ++ /* Prelinking. */ ++ *reloc_addr += l_addr; ++ return; ++ } ++ ++ if (__glibc_unlikely (map->l_mach.variant_pcs)) ++ { ++ /* Check the symbol table for variant PCS symbols. */ ++ const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info); ++ const ElfW (Sym) *symtab = ++ (const void *)D_PTR (map, l_info[DT_SYMTAB]); ++ const ElfW (Sym) *sym = &symtab[symndx]; ++ if (__glibc_unlikely (sym->st_other & STO_AARCH64_VARIANT_PCS)) ++ { ++ /* Avoid lazy resolution of variant PCS symbols. */ ++ const struct r_found_version *version = NULL; ++ if (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL) ++ { ++ const ElfW (Half) *vernum = ++ (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); ++ version = &map->l_versions[vernum[symndx] & 0x7fff]; ++ } ++ elf_machine_rela (map, reloc, sym, version, reloc_addr, ++ skip_ifunc); ++ return; ++ } ++ } ++ ++ *reloc_addr = map->l_mach.plt; + } + else if (__builtin_expect (r_type == AARCH64_R(TLSDESC), 1)) + { +diff --git a/sysdeps/aarch64/linkmap.h b/sysdeps/aarch64/linkmap.h +index 6852f343a1efd150..dd8597470c3d2174 100644 +--- a/sysdeps/aarch64/linkmap.h ++++ b/sysdeps/aarch64/linkmap.h +@@ -20,4 +20,5 @@ struct link_map_machine + { + ElfW(Addr) plt; /* Address of .plt */ + void *tlsdesc_table; /* Address of TLS descriptor hash table. */ ++ int variant_pcs; /* If set, PLT calls may follow a variant PCS. */ + }; diff --git a/glibc-rh1726638-3.patch b/glibc-rh1726638-3.patch new file mode 100755 index 0000000..6c37873 --- /dev/null +++ b/glibc-rh1726638-3.patch @@ -0,0 +1,49 @@ +commit 30ba0375464f34e4bf8129f3d3dc14d0c09add17 +Author: Szabolcs Nagy +Date: Tue Jul 9 12:11:39 2019 +0100 + + aarch64: simplify the DT_AARCH64_VARIANT_PCS handling code + + Remove unnecessary variant_pcs field: the dynamic tag can be checked + directly. + + * sysdeps/aarch64/dl-machine.h (elf_machine_runtime_setup): Remove the + DT_AARCH64_VARIANT_PCS check. + (elf_machine_lazy_rel): Use l_info[DT_AARCH64 (VARIANT_PCS)]. + * sysdeps/aarch64/linkmap.h (struct link_map_machine): Remove + variant_pcs. + +diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h +index d4494852b32b8783..b39eae4acf4086ee 100644 +--- a/sysdeps/aarch64/dl-machine.h ++++ b/sysdeps/aarch64/dl-machine.h +@@ -105,10 +105,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + } + } + +- /* Check if STO_AARCH64_VARIANT_PCS needs to be handled. */ +- if (l->l_info[DT_AARCH64 (VARIANT_PCS)]) +- l->l_mach.variant_pcs = 1; +- + return lazy; + } + +@@ -402,7 +398,7 @@ elf_machine_lazy_rel (struct link_map *map, + return; + } + +- if (__glibc_unlikely (map->l_mach.variant_pcs)) ++ if (__glibc_unlikely (map->l_info[DT_AARCH64 (VARIANT_PCS)] != NULL)) + { + /* Check the symbol table for variant PCS symbols. */ + const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info); +diff --git a/sysdeps/aarch64/linkmap.h b/sysdeps/aarch64/linkmap.h +index dd8597470c3d2174..6852f343a1efd150 100644 +--- a/sysdeps/aarch64/linkmap.h ++++ b/sysdeps/aarch64/linkmap.h +@@ -20,5 +20,4 @@ struct link_map_machine + { + ElfW(Addr) plt; /* Address of .plt */ + void *tlsdesc_table; /* Address of TLS descriptor hash table. */ +- int variant_pcs; /* If set, PLT calls may follow a variant PCS. */ + }; diff --git a/glibc-rh1727152.patch b/glibc-rh1727152.patch new file mode 100755 index 0000000..8a5ed92 --- /dev/null +++ b/glibc-rh1727152.patch @@ -0,0 +1,22 @@ +commit 61595e3d36ded374f97961503e843a314b0203c2 +Author: Andreas Schwab +Date: Tue May 15 14:42:37 2018 +0200 + + nscd: avoid assertion failure during persistent db check + + nscd should not abort when it finds inconsistencies in the persistent db. + +diff --git a/nscd/connections.c b/nscd/connections.c +index 47fbb9923aa2aac7..98182007646a33d5 100644 +--- a/nscd/connections.c ++++ b/nscd/connections.c +@@ -304,7 +304,8 @@ static int + check_use (const char *data, nscd_ssize_t first_free, uint8_t *usemap, + enum usekey use, ref_t start, size_t len) + { +- assert (len >= 2); ++ if (len < 2) ++ return 0; + + if (start > first_free || start + len > first_free + || (start & BLOCK_ALIGN_M1)) diff --git a/glibc-rh1727241-1.patch b/glibc-rh1727241-1.patch new file mode 100755 index 0000000..5842b08 --- /dev/null +++ b/glibc-rh1727241-1.patch @@ -0,0 +1,221 @@ +commit 5e30b8ef0758763effa115634e0ed7d8938e4bc0 +Author: Florian Weimer +Date: Mon Jan 21 08:59:42 2019 +0100 + + resolv: Reformat inet_addr, inet_aton to GNU style + +diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c +index 022f7ea0841b6bae..32f58b0e13598b32 100644 +--- a/resolv/inet_addr.c ++++ b/resolv/inet_addr.c +@@ -1,3 +1,21 @@ ++/* Legacy IPv4 text-to-address functions. ++ 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 ++ . */ ++ + /* + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. +@@ -78,105 +96,97 @@ + #include + #include + +-/* +- * Ascii internet address interpretation routine. +- * The value returned is in network order. +- */ ++/* ASCII IPv4 Internet address interpretation routine. The value ++ returned is in network order. */ + in_addr_t +-__inet_addr(const char *cp) { +- struct in_addr val; ++__inet_addr (const char *cp) ++{ ++ struct in_addr val; + +- if (__inet_aton(cp, &val)) +- return (val.s_addr); +- return (INADDR_NONE); ++ if (__inet_aton (cp, &val)) ++ return val.s_addr; ++ return INADDR_NONE; + } + weak_alias (__inet_addr, inet_addr) + +-/* +- * Check whether "cp" is a valid ascii representation +- * of an Internet address and convert to a binary address. +- * Returns 1 if the address is valid, 0 if not. +- * This replaces inet_addr, the return value from which +- * cannot distinguish between failure and a local broadcast address. +- */ ++/* Check whether "cp" is a valid ASCII representation of an IPv4 ++ Internet address and convert it to a binary address. Returns 1 if ++ the address is valid, 0 if not. This replaces inet_addr, the ++ return value from which cannot distinguish between failure and a ++ local broadcast address. */ + int +-__inet_aton(const char *cp, struct in_addr *addr) ++__inet_aton (const char *cp, struct in_addr *addr) + { +- static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff }; +- in_addr_t val; +- char c; +- union iaddr { +- uint8_t bytes[4]; +- uint32_t word; +- } res; +- uint8_t *pp = res.bytes; +- int digit; +- +- int saved_errno = errno; +- __set_errno (0); +- +- res.word = 0; +- +- c = *cp; +- for (;;) { +- /* +- * Collect number up to ``.''. +- * Values are specified as for C: +- * 0x=hex, 0=octal, isdigit=decimal. +- */ +- if (!isdigit(c)) +- goto ret_0; +- { +- char *endp; +- unsigned long ul = strtoul (cp, (char **) &endp, 0); +- if (ul == ULONG_MAX && errno == ERANGE) +- goto ret_0; +- if (ul > 0xfffffffful) +- goto ret_0; +- val = ul; +- digit = cp != endp; +- cp = endp; +- } +- c = *cp; +- if (c == '.') { +- /* +- * Internet format: +- * a.b.c.d +- * a.b.c (with c treated as 16 bits) +- * a.b (with b treated as 24 bits) +- */ +- if (pp > res.bytes + 2 || val > 0xff) +- goto ret_0; +- *pp++ = val; +- c = *++cp; +- } else +- break; +- } +- /* +- * Check for trailing characters. +- */ +- if (c != '\0' && (!isascii(c) || !isspace(c))) +- goto ret_0; +- /* +- * Did we get a valid digit? +- */ +- if (!digit) +- goto ret_0; +- +- /* Check whether the last part is in its limits depending on +- the number of parts in total. */ +- if (val > max[pp - res.bytes]) ++ static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff }; ++ in_addr_t val; ++ char c; ++ union iaddr ++ { ++ uint8_t bytes[4]; ++ uint32_t word; ++ } res; ++ uint8_t *pp = res.bytes; ++ int digit; ++ ++ int saved_errno = errno; ++ __set_errno (0); ++ ++ res.word = 0; ++ ++ c = *cp; ++ for (;;) ++ { ++ /* Collect number up to ``.''. Values are specified as for C: ++ 0x=hex, 0=octal, isdigit=decimal. */ ++ if (!isdigit (c)) ++ goto ret_0; ++ { ++ char *endp; ++ unsigned long ul = strtoul (cp, &endp, 0); ++ if (ul == ULONG_MAX && errno == ERANGE) + goto ret_0; +- +- if (addr != NULL) +- addr->s_addr = res.word | htonl (val); +- +- __set_errno (saved_errno); +- return (1); +- +-ret_0: +- __set_errno (saved_errno); +- return (0); ++ if (ul > 0xfffffffful) ++ goto ret_0; ++ val = ul; ++ digit = cp != endp; ++ cp = endp; ++ } ++ c = *cp; ++ if (c == '.') ++ { ++ /* Internet format: ++ a.b.c.d ++ a.b.c (with c treated as 16 bits) ++ a.b (with b treated as 24 bits). */ ++ if (pp > res.bytes + 2 || val > 0xff) ++ goto ret_0; ++ *pp++ = val; ++ c = *++cp; ++ } ++ else ++ break; ++ } ++ /* Check for trailing characters. */ ++ if (c != '\0' && (!isascii (c) || !isspace (c))) ++ goto ret_0; ++ /* Did we get a valid digit? */ ++ if (!digit) ++ goto ret_0; ++ ++ /* Check whether the last part is in its limits depending on the ++ number of parts in total. */ ++ if (val > max[pp - res.bytes]) ++ goto ret_0; ++ ++ if (addr != NULL) ++ addr->s_addr = res.word | htonl (val); ++ ++ __set_errno (saved_errno); ++ return 1; ++ ++ ret_0: ++ __set_errno (saved_errno); ++ return 0; + } + weak_alias (__inet_aton, inet_aton) + libc_hidden_def (__inet_aton) diff --git a/glibc-rh1727241-2.patch b/glibc-rh1727241-2.patch new file mode 100755 index 0000000..7f9f417 --- /dev/null +++ b/glibc-rh1727241-2.patch @@ -0,0 +1,80 @@ +commit 6ca53a2453598804a2559a548a08424fca96434a +Author: Florian Weimer +Date: Mon Jan 21 09:26:41 2019 +0100 + + resolv: Do not send queries for non-host-names in nss_dns [BZ #24112] + + Before this commit, nss_dns would send a query which did not contain a + host name as the query name (such as invalid\032name.example.com) and + then reject the answer in getanswer_r and gaih_getanswer_slice, using + a check based on res_hnok. With this commit, no query is sent, and a + host-not-found error is returned to NSS without network interaction. + +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index 5dc2829cd148a568..99c3b61e1cee4d42 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -274,11 +274,26 @@ gethostbyname3_context (struct resolv_context *ctx, + return status; + } + ++/* Verify that the name looks like a host name. There is no point in ++ sending a query which will not produce a usable name in the ++ response. */ ++static enum nss_status ++check_name (const char *name, int *h_errnop) ++{ ++ if (res_hnok (name)) ++ return NSS_STATUS_SUCCESS; ++ *h_errnop = HOST_NOT_FOUND; ++ return NSS_STATUS_NOTFOUND; ++} ++ + enum nss_status + _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result, + char *buffer, size_t buflen, int *errnop, + int *h_errnop) + { ++ enum nss_status status = check_name (name, h_errnop); ++ if (status != NSS_STATUS_SUCCESS) ++ return status; + return _nss_dns_gethostbyname3_r (name, af, result, buffer, buflen, errnop, + h_errnop, NULL, NULL); + } +@@ -289,6 +304,9 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result, + char *buffer, size_t buflen, int *errnop, + int *h_errnop) + { ++ enum nss_status status = check_name (name, h_errnop); ++ if (status != NSS_STATUS_SUCCESS) ++ return status; + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { +@@ -296,7 +314,7 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result, + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } +- enum nss_status status = NSS_STATUS_NOTFOUND; ++ status = NSS_STATUS_NOTFOUND; + if (res_use_inet6 ()) + status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer, + buflen, errnop, h_errnop, NULL, NULL); +@@ -313,6 +331,9 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, + char *buffer, size_t buflen, int *errnop, + int *herrnop, int32_t *ttlp) + { ++ enum nss_status status = check_name (name, herrnop); ++ if (status != NSS_STATUS_SUCCESS) ++ return status; + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { +@@ -347,7 +368,6 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, + int ans2p_malloced = 0; + + int olderr = errno; +- enum nss_status status; + int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA, + host_buffer.buf->buf, 2048, &host_buffer.ptr, + &ans2p, &nans2p, &resplen2, &ans2p_malloced); diff --git a/glibc-rh1727241-3.patch b/glibc-rh1727241-3.patch new file mode 100755 index 0000000..f578ebd --- /dev/null +++ b/glibc-rh1727241-3.patch @@ -0,0 +1,698 @@ +commit 108bc4049f8ae82710aec26a92ffdb4b439c83fd +Author: Florian Weimer +Date: Mon Jan 21 21:26:03 2019 +0100 + + CVE-2016-10739: getaddrinfo: Fully parse IPv4 address strings [BZ #20018] + + The IPv4 address parser in the getaddrinfo function is changed so that + it does not ignore trailing whitespace and all characters after it. + For backwards compatibility, the getaddrinfo function still recognizes + legacy name syntax, such as 192.000.002.010 interpreted as 192.0.2.8 + (octal). + + This commit does not change the behavior of inet_addr and inet_aton. + gethostbyname already had additional sanity checks (but is switched + over to the new __inet_aton_exact function for completeness as well). + + To avoid sending the problematic query names over DNS, commit + 6ca53a2453598804a2559a548a08424fca96434a ("resolv: Do not send queries + for non-host-names in nss_dns [BZ #24112]") is needed. + +diff --git a/include/arpa/inet.h b/include/arpa/inet.h +index c3f28f2baaa2ed66..19aec74275069a45 100644 +--- a/include/arpa/inet.h ++++ b/include/arpa/inet.h +@@ -1,10 +1,10 @@ + #include + + #ifndef _ISOMAC +-extern int __inet_aton (const char *__cp, struct in_addr *__inp); +-libc_hidden_proto (__inet_aton) ++/* Variant of inet_aton which rejects trailing garbage. */ ++extern int __inet_aton_exact (const char *__cp, struct in_addr *__inp); ++libc_hidden_proto (__inet_aton_exact) + +-libc_hidden_proto (inet_aton) + libc_hidden_proto (inet_ntop) + libc_hidden_proto (inet_pton) + extern __typeof (inet_pton) __inet_pton; +diff --git a/nscd/gai.c b/nscd/gai.c +index 24bdfee1db3791e2..f57f396f574a6e52 100644 +--- a/nscd/gai.c ++++ b/nscd/gai.c +@@ -19,7 +19,6 @@ + + /* This file uses the getaddrinfo code but it compiles it without NSCD + support. We just need a few symbol renames. */ +-#define __inet_aton inet_aton + #define __ioctl ioctl + #define __getsockname getsockname + #define __socket socket +diff --git a/nscd/gethstbynm3_r.c b/nscd/gethstbynm3_r.c +index 7beb9dce9f4b350c..f792c4fcd042d13d 100644 +--- a/nscd/gethstbynm3_r.c ++++ b/nscd/gethstbynm3_r.c +@@ -38,8 +38,6 @@ + #define HAVE_LOOKUP_BUFFER 1 + #define HAVE_AF 1 + +-#define __inet_aton inet_aton +- + /* We are nscd, so we don't want to be talking to ourselves. */ + #undef USE_NSCD + +diff --git a/nss/digits_dots.c b/nss/digits_dots.c +index 39bff38865a1ac5b..5441bce16ea8b2e9 100644 +--- a/nss/digits_dots.c ++++ b/nss/digits_dots.c +@@ -29,7 +29,6 @@ + #include "nsswitch.h" + + #ifdef USE_NSCD +-# define inet_aton __inet_aton + # include + #endif + +@@ -160,7 +159,7 @@ __nss_hostname_digits_dots_context (struct resolv_context *ctx, + 255.255.255.255? The test below will succeed + spuriously... ??? */ + if (af == AF_INET) +- ok = __inet_aton (name, (struct in_addr *) host_addr); ++ ok = __inet_aton_exact (name, (struct in_addr *) host_addr); + else + { + assert (af == AF_INET6); +diff --git a/resolv/Makefile b/resolv/Makefile +index 56718654eeab85a3..72a0f196506ac489 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -34,6 +34,9 @@ routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \ + tests = tst-aton tst-leaks tst-inet_ntop + xtests = tst-leaks2 + ++tests-internal += tst-inet_aton_exact ++ ++ + generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace + + extra-libs := libresolv libnss_dns +@@ -54,8 +57,10 @@ tests += \ + tst-resolv-binary \ + tst-resolv-edns \ + tst-resolv-network \ ++ tst-resolv-nondecimal \ + tst-resolv-res_init-multi \ + tst-resolv-search \ ++ tst-resolv-trailing \ + + # These tests need libdl. + ifeq (yes,$(build-shared)) +@@ -190,9 +195,11 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \ + $(shared-thread-library) + $(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \ + $(shared-thread-library) ++$(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library) ++$(objpfx)tst-resolv-trailing: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-threads: \ + $(libdl) $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-canonname: \ +diff --git a/resolv/Versions b/resolv/Versions +index b05778d9654aa0f2..9a82704af75f789b 100644 +--- a/resolv/Versions ++++ b/resolv/Versions +@@ -27,6 +27,7 @@ libc { + __h_errno; __resp; + + __res_iclose; ++ __inet_aton_exact; + __inet_pton_length; + __resolv_context_get; + __resolv_context_get_preinit; +diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c +index 32f58b0e13598b32..41b6166a5bd5a44b 100644 +--- a/resolv/inet_addr.c ++++ b/resolv/inet_addr.c +@@ -96,26 +96,14 @@ + #include + #include + +-/* ASCII IPv4 Internet address interpretation routine. The value +- returned is in network order. */ +-in_addr_t +-__inet_addr (const char *cp) +-{ +- struct in_addr val; +- +- if (__inet_aton (cp, &val)) +- return val.s_addr; +- return INADDR_NONE; +-} +-weak_alias (__inet_addr, inet_addr) +- + /* Check whether "cp" is a valid ASCII representation of an IPv4 + Internet address and convert it to a binary address. Returns 1 if + the address is valid, 0 if not. This replaces inet_addr, the + return value from which cannot distinguish between failure and a +- local broadcast address. */ +-int +-__inet_aton (const char *cp, struct in_addr *addr) ++ local broadcast address. Write a pointer to the first ++ non-converted character to *endp. */ ++static int ++inet_aton_end (const char *cp, struct in_addr *addr, const char **endp) + { + static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff }; + in_addr_t val; +@@ -180,6 +168,7 @@ __inet_aton (const char *cp, struct in_addr *addr) + + if (addr != NULL) + addr->s_addr = res.word | htonl (val); ++ *endp = cp; + + __set_errno (saved_errno); + return 1; +@@ -188,6 +177,41 @@ __inet_aton (const char *cp, struct in_addr *addr) + __set_errno (saved_errno); + return 0; + } +-weak_alias (__inet_aton, inet_aton) +-libc_hidden_def (__inet_aton) +-libc_hidden_weak (inet_aton) ++ ++int ++__inet_aton_exact (const char *cp, struct in_addr *addr) ++{ ++ struct in_addr val; ++ const char *endp; ++ /* Check that inet_aton_end parsed the entire string. */ ++ if (inet_aton_end (cp, &val, &endp) != 0 && *endp == 0) ++ { ++ *addr = val; ++ return 1; ++ } ++ else ++ return 0; ++} ++libc_hidden_def (__inet_aton_exact) ++ ++/* inet_aton ignores trailing garbage. */ ++int ++__inet_aton_ignore_trailing (const char *cp, struct in_addr *addr) ++{ ++ const char *endp; ++ return inet_aton_end (cp, addr, &endp); ++} ++weak_alias (__inet_aton_ignore_trailing, inet_aton) ++ ++/* ASCII IPv4 Internet address interpretation routine. The value ++ returned is in network order. */ ++in_addr_t ++__inet_addr (const char *cp) ++{ ++ struct in_addr val; ++ const char *endp; ++ if (inet_aton_end (cp, &val, &endp)) ++ return val.s_addr; ++ return INADDR_NONE; ++} ++weak_alias (__inet_addr, inet_addr) +diff --git a/resolv/res_init.c b/resolv/res_init.c +index f5e52cbbb9377762..94743a252e39d64a 100644 +--- a/resolv/res_init.c ++++ b/resolv/res_init.c +@@ -399,8 +399,16 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + cp = parser->buffer + sizeof ("nameserver") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; ++ ++ /* Ignore trailing contents on the name server line. */ ++ { ++ char *el; ++ if ((el = strpbrk (cp, " \t\n")) != NULL) ++ *el = '\0'; ++ } ++ + struct sockaddr *sa; +- if ((*cp != '\0') && (*cp != '\n') && __inet_aton (cp, &a)) ++ if ((*cp != '\0') && (*cp != '\n') && __inet_aton_exact (cp, &a)) + { + sa = allocate_address_v4 (a, NAMESERVER_PORT); + if (sa == NULL) +@@ -410,9 +418,6 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + { + struct in6_addr a6; + char *el; +- +- if ((el = strpbrk (cp, " \t\n")) != NULL) +- *el = '\0'; + if ((el = strchr (cp, SCOPE_DELIMITER)) != NULL) + *el = '\0'; + if ((*cp != '\0') && (__inet_pton (AF_INET6, cp, &a6) > 0)) +@@ -472,7 +477,7 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + char separator = *cp; + *cp = 0; + struct resolv_sortlist_entry e; +- if (__inet_aton (net, &a)) ++ if (__inet_aton_exact (net, &a)) + { + e.addr = a; + if (is_sort_mask (separator)) +@@ -484,7 +489,7 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + cp++; + separator = *cp; + *cp = 0; +- if (__inet_aton (net, &a)) ++ if (__inet_aton_exact (net, &a)) + e.mask = a.s_addr; + else + e.mask = net_mask (e.addr); +diff --git a/resolv/tst-aton.c b/resolv/tst-aton.c +index 08110a007af909ff..eb734d7758d6ed87 100644 +--- a/resolv/tst-aton.c ++++ b/resolv/tst-aton.c +@@ -1,11 +1,29 @@ ++/* Test legacy IPv4 text-to-address function inet_aton. ++ Copyright (C) 1998-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 ++ . */ ++ ++#include + #include + #include + #include + #include + #include + +- +-static struct tests ++static const struct tests + { + const char *input; + int valid; +@@ -16,6 +34,7 @@ static struct tests + { "-1", 0, 0 }, + { "256", 1, 0x00000100 }, + { "256.", 0, 0 }, ++ { "255a", 0, 0 }, + { "256a", 0, 0 }, + { "0x100", 1, 0x00000100 }, + { "0200.0x123456", 1, 0x80123456 }, +@@ -40,7 +59,12 @@ static struct tests + { "1.2.256.4", 0, 0 }, + { "1.2.3.0x100", 0, 0 }, + { "323543357756889", 0, 0 }, +- { "10.1.2.3.4", 0, 0}, ++ { "10.1.2.3.4", 0, 0 }, ++ { "192.0.2.1", 1, 0xc0000201 }, ++ { "192.0.2.2\nX", 1, 0xc0000202 }, ++ { "192.0.2.3 Y", 1, 0xc0000203 }, ++ { "192.0.2.3Z", 0, 0 }, ++ { "192.000.002.010", 1, 0xc0000208 }, + }; + + +@@ -50,7 +74,7 @@ do_test (void) + int result = 0; + size_t cnt; + +- for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt) ++ for (cnt = 0; cnt < array_length (tests); ++cnt) + { + struct in_addr addr; + +@@ -73,5 +97,4 @@ do_test (void) + return result; + } + +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" ++#include +diff --git a/resolv/tst-inet_aton_exact.c b/resolv/tst-inet_aton_exact.c +new file mode 100644 +index 0000000000000000..0fdfa3d6aa9aef91 +--- /dev/null ++++ b/resolv/tst-inet_aton_exact.c +@@ -0,0 +1,47 @@ ++/* Test internal legacy IPv4 text-to-address function __inet_aton_exact. ++ 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 ++ . */ ++ ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ struct in_addr addr = { }; ++ ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.1", &addr), 1); ++ TEST_COMPARE (ntohl (addr.s_addr), 0xC0000201); ++ ++ TEST_COMPARE (__inet_aton_exact ("192.000.002.010", &addr), 1); ++ TEST_COMPARE (ntohl (addr.s_addr), 0xC0000208); ++ TEST_COMPARE (__inet_aton_exact ("0xC0000234", &addr), 1); ++ TEST_COMPARE (ntohl (addr.s_addr), 0xC0000234); ++ ++ /* Trailing content is not accepted. */ ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.2X", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.3 Y", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.4\nZ", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.5\tT", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.6 Y", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.7\n", &addr), 0); ++ TEST_COMPARE (__inet_aton_exact ("192.0.2.8\t", &addr), 0); ++ ++ return 0; ++} ++ ++#include +diff --git a/resolv/tst-resolv-nondecimal.c b/resolv/tst-resolv-nondecimal.c +new file mode 100644 +index 0000000000000000..a0df6f332ae8faf7 +--- /dev/null ++++ b/resolv/tst-resolv-nondecimal.c +@@ -0,0 +1,139 @@ ++/* Test name resolution behavior for octal, hexadecimal IPv4 addresses. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void ++response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ /* The tests are not supposed send any DNS queries. */ ++ FAIL_EXIT1 ("unexpected DNS query for %s/%d/%d", qname, qclass, qtype); ++} ++ ++static void ++run_query_addrinfo (const char *query, const char *address) ++{ ++ char *quoted_query = support_quote_string (query); ++ ++ struct addrinfo *ai; ++ struct addrinfo hints = ++ { ++ .ai_socktype = SOCK_STREAM, ++ .ai_protocol = IPPROTO_TCP, ++ }; ++ ++ char *context = xasprintf ("getaddrinfo \"%s\" AF_INET", quoted_query); ++ char *expected = xasprintf ("address: STREAM/TCP %s 80\n", address); ++ hints.ai_family = AF_INET; ++ int ret = getaddrinfo (query, "80", &hints, &ai); ++ check_addrinfo (context, ai, ret, expected); ++ if (ret == 0) ++ freeaddrinfo (ai); ++ free (context); ++ ++ context = xasprintf ("getaddrinfo \"%s\" AF_UNSPEC", quoted_query); ++ hints.ai_family = AF_UNSPEC; ++ ret = getaddrinfo (query, "80", &hints, &ai); ++ check_addrinfo (context, ai, ret, expected); ++ if (ret == 0) ++ freeaddrinfo (ai); ++ free (expected); ++ free (context); ++ ++ context = xasprintf ("getaddrinfo \"%s\" AF_INET6", quoted_query); ++ expected = xasprintf ("flags: AI_V4MAPPED\n" ++ "address: STREAM/TCP ::ffff:%s 80\n", ++ address); ++ hints.ai_family = AF_INET6; ++ hints.ai_flags = AI_V4MAPPED; ++ ret = getaddrinfo (query, "80", &hints, &ai); ++ check_addrinfo (context, ai, ret, expected); ++ if (ret == 0) ++ freeaddrinfo (ai); ++ free (expected); ++ free (context); ++ ++ free (quoted_query); ++} ++ ++static void ++run_query (const char *query, const char *address) ++{ ++ char *quoted_query = support_quote_string (query); ++ char *context = xasprintf ("gethostbyname (\"%s\")", quoted_query); ++ char *expected = xasprintf ("name: %s\n" ++ "address: %s\n", query, address); ++ check_hostent (context, gethostbyname (query), expected); ++ free (context); ++ ++ context = xasprintf ("gethostbyname_r \"%s\"", quoted_query); ++ struct hostent storage; ++ char buf[4096]; ++ struct hostent *e = NULL; ++ TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ check_hostent (context, e, expected); ++ free (context); ++ ++ context = xasprintf ("gethostbyname2 (\"%s\", AF_INET)", quoted_query); ++ check_hostent (context, gethostbyname2 (query, AF_INET), expected); ++ free (context); ++ ++ context = xasprintf ("gethostbyname2_r \"%s\" AF_INET", quoted_query); ++ e = NULL; ++ TEST_COMPARE (gethostbyname2_r (query, AF_INET, &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ check_hostent (context, e, expected); ++ free (context); ++ free (expected); ++ ++ free (quoted_query); ++ ++ /* The gethostbyname tests are always valid for getaddrinfo, but not ++ vice versa. */ ++ run_query_addrinfo (query, address); ++} ++ ++static int ++do_test (void) ++{ ++ struct resolv_test *aux = resolv_test_start ++ ((struct resolv_redirect_config) ++ { ++ .response_callback = response, ++ }); ++ ++ run_query ("192.000.002.010", "192.0.2.8"); ++ ++ /* Hexadecimal numbers are not accepted by gethostbyname. */ ++ run_query_addrinfo ("0xc0000210", "192.0.2.16"); ++ run_query_addrinfo ("192.0x234", "192.0.2.52"); ++ ++ resolv_test_end (aux); ++ ++ return 0; ++} ++ ++#include +diff --git a/resolv/tst-resolv-trailing.c b/resolv/tst-resolv-trailing.c +new file mode 100644 +index 0000000000000000..7504bdae572ed8d0 +--- /dev/null ++++ b/resolv/tst-resolv-trailing.c +@@ -0,0 +1,136 @@ ++/* Test name resolution behavior with trailing characters. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void ++response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ /* The tests are not supposed send any DNS queries. */ ++ FAIL_EXIT1 ("unexpected DNS query for %s/%d/%d", qname, qclass, qtype); ++} ++ ++static int ++do_test (void) ++{ ++ struct resolv_test *aux = resolv_test_start ++ ((struct resolv_redirect_config) ++ { ++ .response_callback = response, ++ }); ++ ++ static const char *const queries[] = ++ { ++ "192.0.2.1 ", ++ "192.0.2.2\t", ++ "192.0.2.3\n", ++ "192.0.2.4 X", ++ "192.0.2.5\tY", ++ "192.0.2.6\nZ", ++ "192.0.2. ", ++ "192.0.2.\t", ++ "192.0.2.\n", ++ "192.0.2. X", ++ "192.0.2.\tY", ++ "192.0.2.\nZ", ++ "2001:db8::1 ", ++ "2001:db8::2\t", ++ "2001:db8::3\n", ++ "2001:db8::4 X", ++ "2001:db8::5\tY", ++ "2001:db8::6\nZ", ++ }; ++ for (size_t query_idx = 0; query_idx < array_length (queries); ++query_idx) ++ { ++ const char *query = queries[query_idx]; ++ struct hostent storage; ++ char buf[4096]; ++ struct hostent *e; ++ ++ h_errno = 0; ++ TEST_VERIFY (gethostbyname (query) == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ e = NULL; ++ TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ TEST_VERIFY (e == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ TEST_VERIFY (gethostbyname2 (query, AF_INET) == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ e = NULL; ++ TEST_COMPARE (gethostbyname2_r (query, AF_INET, ++ &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ TEST_VERIFY (e == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ TEST_VERIFY (gethostbyname2 (query, AF_INET6) == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ h_errno = 0; ++ e = NULL; ++ TEST_COMPARE (gethostbyname2_r (query, AF_INET6, ++ &storage, buf, sizeof (buf), ++ &e, &h_errno), 0); ++ TEST_VERIFY (e == NULL); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ ++ static const int gai_flags[] = ++ { ++ 0, ++ AI_ADDRCONFIG, ++ AI_NUMERICHOST, ++ AI_IDN, ++ AI_IDN | AI_NUMERICHOST, ++ AI_V4MAPPED, ++ AI_V4MAPPED | AI_NUMERICHOST, ++ }; ++ for (size_t gai_flags_idx; gai_flags_idx < array_length (gai_flags); ++ ++gai_flags_idx) ++ { ++ struct addrinfo hints = { .ai_flags = gai_flags[gai_flags_idx], }; ++ struct addrinfo *ai; ++ hints.ai_family = AF_INET; ++ TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME); ++ hints.ai_family = AF_INET6; ++ TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME); ++ hints.ai_family = AF_UNSPEC; ++ TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME); ++ } ++ }; ++ ++ resolv_test_end (aux); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 00e0d94a8f5bb30d..6a5805c9e63a257c 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -488,7 +488,7 @@ gaih_inet (const char *name, const struct gaih_service *service, + malloc_name = true; + } + +- if (__inet_aton (name, (struct in_addr *) at->addr) != 0) ++ if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0) + { + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET) + at->family = AF_INET; diff --git a/glibc-rh1735747-1.patch b/glibc-rh1735747-1.patch new file mode 100755 index 0000000..04c4136 --- /dev/null +++ b/glibc-rh1735747-1.patch @@ -0,0 +1,25 @@ +commit 6d750b18999b52ec74102c046cd27181f943bda8 +Author: Florian Weimer +Date: Thu Aug 1 14:06:24 2019 +0200 + + malloc: Remove unwanted leading whitespace in malloc_info [BZ #24867] + + It was introduced in commit 6c8dbf00f536d78b1937b5af6f57be47fd376344 + ("Reformat malloc to gnu style."). + + Reviewed-by: Carlos O'Donell + (cherry picked from commit b0f6679bcd738ea244a14acd879d974901e56c8e) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index e6a483d5cf7c4312..4fc7f175fe42d6c6 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -5518,7 +5518,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, "\ + \n", + sizes[i].from, sizes[i].to, sizes[i].total, sizes[i].count); + diff --git a/glibc-rh1735747-2.patch b/glibc-rh1735747-2.patch new file mode 100755 index 0000000..e2afd28 --- /dev/null +++ b/glibc-rh1735747-2.patch @@ -0,0 +1,35 @@ +commit 91d5989356325759503311df67e750b358ef4148 +Author: Niklas Hambüchen +Date: Thu Aug 8 22:02:27 2019 +0200 + + malloc: Fix missing accounting of top chunk in malloc_info [BZ #24026] + + Fixes ` incorrectly showing as 0 most + of the time. + + The rest value being wrong is significant because to compute the + actual amount of memory handed out via malloc, the user must subtract + it from . That result being wrong + makes investigating memory fragmentation issues like + close to + impossible. + + (cherry picked from commit b6d2c4475d5abc05dd009575b90556bdd3c78ad0) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 4fc7f175fe42d6c6..fcf480acdaea1b86 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -5433,6 +5433,12 @@ __malloc_info (int options, FILE *fp) + + __libc_lock_lock (ar_ptr->mutex); + ++ /* Account for top chunk. The top-most available chunk is ++ treated specially and is never in any bin. See "initial_top" ++ comments. */ ++ avail = chunksize (ar_ptr->top); ++ nblocks = 1; /* Top always exists. */ ++ + for (size_t i = 0; i < NFASTBINS; ++i) + { + mchunkptr p = fastbin (ar_ptr, i); diff --git a/glibc-rh1743445-1.patch b/glibc-rh1743445-1.patch new file mode 100755 index 0000000..759879a --- /dev/null +++ b/glibc-rh1743445-1.patch @@ -0,0 +1,151 @@ +From: Ian Kent +Date: Mon, 2 Sep 2019 11:26:14 +0000 (+0200) +Subject: Use autofs "ignore" mount hint in getmntent_r/getmntent +X-Git-Tag: changelog-ends-here~75 +X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=08b7e9988272113ca5640cf5e115ea51449fb392 + +Use autofs "ignore" mount hint in getmntent_r/getmntent + +Historically autofs mounts were not included in mount table +listings. This is the case in other SysV autofs implementations +and was also the case with Linux autofs. + +But now that /etc/mtab is a symlink to the proc filesystem +mount table the autofs mount entries appear in the mount table +on Linux. + +Prior to the symlinking of /etc/mtab mount table it was +sufficient to call mount(2) and simply not update /etc/mtab +to exclude autofs mounts from mount listings. + +Also, with the symlinking of /etc/mtab we have seen a shift in +usage toward using the proc mount tables directly. + +But the autofs mount entries need to be retained when coming +from the proc file system for applications that need them +(largely autofs file system users themselves) so filtering out +these entries within the kernel itself can't be done. So it +needs be done in user space. + +There are three reasons to omit the autofs mount entries. + +One is that certain types of auto-mounts have an autofs mount +for every entry in their autofs mount map and these maps can +be quite large. This leads to mount table listings containing +a lot of unnecessary entries. + +Also, this change in behaviour between autofs implementations +can cause problems for applications that use getmntent(3) in +other OS implementations as well as Linux. + +Lastly, there's very little that user space can do with autofs +mount entries since this must be left to the autofs mount owner, +typically the automount daemon. But it can also lead to attempts +to access automount managed paths resulting mounts being triggered +when they aren't needed or mounts staying mounted for much longer +thay they need be. While the point of this change ins't to help +with these problems (and it can be quite a problem) it may be +a welcome side effect. + +So the Linux autofs file system has been modified to accept a +pseudo mount option of "ignore" (as is used in other OS +implementations) so that user space can use this as a hint to +skip autofs entries on reading the mount table. + +The Linux autofs automount daemon used getmntent(3) itself and +has been modified to use the proc file system directly so that +it can "ignore" mount option. + +The use of this mount option is opt-in and a configuration +option has been added which defaults to not use this option +so if there are applications that need these entries, other +than autofs itself, they can be retained. Also, since this +filtering is based on an added mount option earlier versions +of Linux autofs iand other autofs file system users will not +use the option and so won't be affected by the change. +--- + +diff --git a/misc/mntent_r.c b/misc/mntent_r.c +index 5d88c45c6f..d90e8d7087 100644 +--- a/misc/mntent_r.c ++++ b/misc/mntent_r.c +@@ -18,6 +18,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -112,26 +113,18 @@ decode_name (char *buf) + return buf; + } + +- +-/* Read one mount table entry from STREAM. Returns a pointer to storage +- reused on the next call, or null for EOF or error (use feof/ferror to +- check). */ +-struct mntent * +-__getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz) ++static bool ++get_mnt_entry (FILE *stream, struct mntent *mp, char *buffer, int bufsiz) + { + char *cp; + char *head; + +- flockfile (stream); + do + { + char *end_ptr; + + if (__fgets_unlocked (buffer, bufsiz, stream) == NULL) +- { +- funlockfile (stream); +- return NULL; +- } ++ return false; + + end_ptr = strchr (buffer, '\n'); + if (end_ptr != NULL) /* chop newline */ +@@ -181,9 +174,40 @@ __getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz) + case 2: + break; + } ++ ++ return true; ++} ++ ++/* Read one mount table entry from STREAM. Returns a pointer to storage ++ reused on the next call, or null for EOF or error (use feof/ferror to ++ check). */ ++struct mntent * ++__getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz) ++{ ++ struct mntent *result; ++ ++ flockfile (stream); ++ while (true) ++ if (get_mnt_entry (stream, mp, buffer, bufsiz)) ++ { ++ /* If the file system is autofs look for a mount option hint ++ ("ignore") to skip the entry. */ ++ if (strcmp (mp->mnt_type, "autofs") == 0 && __hasmntopt (mp, "ignore")) ++ memset (mp, 0, sizeof (*mp)); ++ else ++ { ++ result = mp; ++ break; ++ } ++ } ++ else ++ { ++ result = NULL; ++ break; ++ } + funlockfile (stream); + +- return mp; ++ return result; + } + libc_hidden_def (__getmntent_r) + weak_alias (__getmntent_r, getmntent_r) diff --git a/glibc-rh1743445-2.patch b/glibc-rh1743445-2.patch new file mode 100755 index 0000000..a14fe60 --- /dev/null +++ b/glibc-rh1743445-2.patch @@ -0,0 +1,169 @@ +From: Florian Weimer +Date: Mon, 2 Sep 2019 10:40:38 +0000 (+0200) +Subject: Add misc/tst-mntent-autofs, testing autofs "ignore" filtering +X-Git-Tag: changelog-ends-here~74 +X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=9a1e7257a4292d3aea45c8317df3956f4331d8ce + +Add misc/tst-mntent-autofs, testing autofs "ignore" filtering +--- + +diff -rup a/misc/Makefile b/misc/Makefile +--- a/misc/Makefile 2020-03-25 18:30:42.275895917 -0400 ++++ b/misc/Makefile 2020-03-25 18:37:55.527738814 -0400 +@@ -84,7 +84,8 @@ tests := tst-dirname tst-tsearch tst-fds + tst-error1 tst-pselect tst-insremque tst-mntent2 bug-hsearch1 \ + tst-mntent-blank-corrupt tst-mntent-blank-passno bug18240 \ + tst-preadvwritev tst-preadvwritev64 tst-makedev tst-empty \ +- tst-preadvwritev2 tst-preadvwritev64v2 ++ tst-preadvwritev2 tst-preadvwritev64v2 \ ++ tst-mntent-autofs + + # Tests which need libdl. + ifeq (yes,$(build-shared)) +diff --git a/misc/tst-mntent-autofs.c b/misc/tst-mntent-autofs.c +new file mode 100644 +index 0000000000..bf4d4e73b4 +--- /dev/null ++++ b/misc/tst-mntent-autofs.c +@@ -0,0 +1,141 @@ ++/* Test autofs "ignore" filtering for getment_r. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct test_case ++{ ++ const char *line; ++ struct ++ { ++ /* Like struct mntent, but with const pointers. */ ++ const char *mnt_fsname; ++ const char *mnt_dir; ++ const char *mnt_type; ++ const char *mnt_opts; ++ int mnt_freq; ++ int mnt_passno; ++ } expected; ++}; ++ ++static struct test_case test_cases[] = ++ { ++ { "/etc/auto.direct /mnt/auto/1 autofs defaults 0 0", ++ { "/etc/auto.direct", "/mnt/auto/1", "autofs", "defaults", 0, 0 } }, ++ ++ /* These entries are filtered out. */ ++ { "/etc/auto.2 /mnt/auto/2 autofs ignore 0 0", { NULL, } }, ++ { "/etc/auto.3 /mnt/auto/3 autofs ignore,other 1 2", { NULL, } }, ++ { "/etc/auto.4 /mnt/auto/4 autofs other,ignore 3 4", { NULL, } }, ++ { "/etc/auto.5 /mnt/auto/5 autofs opt1,ignore,opt2 5 6", { NULL, } }, ++ ++ /* Dummy entry to make the desynchronization more obvious. */ ++ { "/dev/sda1 / xfs defaults 0 0", ++ { "/dev/sda1", "/", "xfs", "defaults", 0, 0 } }, ++ ++ /* These are not filtered because the file system is not autofs. */ ++ { "/etc/auto.direct /mnt/auto/6 autofs1 ignore 0 0", ++ { "/etc/auto.direct", "/mnt/auto/6", "autofs1", "ignore", 0, 0 } }, ++ { "/etc/auto.direct /mnt/auto/7 autofs1 ignore,other 0 0", ++ { "/etc/auto.direct", "/mnt/auto/7", "autofs1", "ignore,other", 0, 0 } }, ++ { "/etc/auto.direct /mnt/auto/8 autofs1 other,ignore 0 0", ++ { "/etc/auto.direct", "/mnt/auto/8", "autofs1", "other,ignore", 0, 0 } }, ++ { "/etc/auto.direct /mnt/auto/9 autofs1 opt1,ignore,opt2 0 0", ++ { "/etc/auto.direct", "/mnt/auto/9", "autofs1", "opt1,ignore,opt2", } }, ++ ++ /* These are not filtered because the string "ignore" is not an ++ option name. */ ++ { "/etc/auto.direct /mnt/auto/10 autofs noignore 1 2", ++ { "/etc/auto.direct", "/mnt/auto/10", "autofs", "noignore", 1, 2 } }, ++ { "/etc/auto.direct /mnt/auto/11 autofs noignore,other 0 0", ++ { "/etc/auto.direct", "/mnt/auto/11", "autofs", "noignore,other", } }, ++ { "/etc/auto.direct /mnt/auto/12 autofs other,noignore 0 0", ++ { "/etc/auto.direct", "/mnt/auto/12", "autofs", "other,noignore", } }, ++ { "/etc/auto.direct /mnt/auto/13 autofs errors=ignore 0 0", ++ { "/etc/auto.direct", "/mnt/auto/13", "autofs", "errors=ignore", } }, ++ { "/etc/auto.direct /mnt/auto/14 autofs errors=ignore,other 0 0", ++ { "/etc/auto.direct", "/mnt/auto/14", "autofs", ++ "errors=ignore,other", } }, ++ { "/etc/auto.direct /mnt/auto/15 autofs other,errors=ignore 0 0", ++ { "/etc/auto.direct", "/mnt/auto/15", "autofs", ++ "other,errors=ignore", } }, ++ ++ /* These are not filtered because the string is escaped. '\151' ++ is 'i', but it is not actually decoded by the parser. */ ++ { "/etc/auto.\\151gnore /mnt/auto/16 autofs \\151gnore 0 0", ++ { "/etc/auto.\\151gnore", "/mnt/auto/16", "autofs", ++ "\\151gnore", } }, ++ }; ++ ++static int ++do_test (void) ++{ ++ char *path; ++ xclose (create_temp_file ("tst-mntent-autofs-", &path)); ++ ++ /* Write the test file. */ ++ FILE *fp = xfopen (path, "w"); ++ for (size_t i = 0; i < array_length (test_cases); ++i) ++ fprintf (fp, "%s\n", test_cases[i].line); ++ xfclose (fp); ++ ++ /* Open the test file again, this time for parsing. */ ++ fp = setmntent (path, "r"); ++ TEST_VERIFY_EXIT (fp != NULL); ++ char buffer[512]; ++ struct mntent me; ++ ++ for (size_t i = 0; i < array_length (test_cases); ++i) ++ { ++ if (test_cases[i].expected.mnt_type == NULL) ++ continue; ++ ++ memset (buffer, 0xcc, sizeof (buffer)); ++ memset (&me, 0xcc, sizeof (me)); ++ struct mntent *pme = getmntent_r (fp, &me, buffer, sizeof (buffer)); ++ TEST_VERIFY_EXIT (pme != NULL); ++ TEST_VERIFY (pme == &me); ++ TEST_COMPARE_STRING (test_cases[i].expected.mnt_fsname, me.mnt_fsname); ++ TEST_COMPARE_STRING (test_cases[i].expected.mnt_dir, me.mnt_dir); ++ TEST_COMPARE_STRING (test_cases[i].expected.mnt_type, me.mnt_type); ++ TEST_COMPARE_STRING (test_cases[i].expected.mnt_opts, me.mnt_opts); ++ TEST_COMPARE (test_cases[i].expected.mnt_freq, me.mnt_freq); ++ TEST_COMPARE (test_cases[i].expected.mnt_passno, me.mnt_passno); ++ } ++ ++ TEST_VERIFY (getmntent_r (fp, &me, buffer, sizeof (buffer)) == NULL); ++ ++ TEST_COMPARE (feof (fp), 1); ++ TEST_COMPARE (ferror (fp), 0); ++ errno = 0; ++ TEST_COMPARE (endmntent (fp), 1); ++ TEST_COMPARE (errno, 0); ++ free (path); ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1746928.patch b/glibc-rh1746928.patch new file mode 100755 index 0000000..c21eb1d --- /dev/null +++ b/glibc-rh1746928.patch @@ -0,0 +1,117 @@ +commit 669ff911e2571f74a2668493e326ac9a505776bd +Author: Florian Weimer +Date: Fri Feb 8 12:46:19 2019 +0100 + + nptl: Avoid fork handler lock for async-signal-safe fork [BZ #24161] + + Commit 27761a1042daf01987e7d79636d0c41511c6df3c ("Refactor atfork + handlers") introduced a lock, atfork_lock, around fork handler list + accesses. It turns out that this lock occasionally results in + self-deadlocks in malloc/tst-mallocfork2: + + (gdb) bt + #0 __lll_lock_wait_private () + at ../sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:63 + #1 0x00007f160c6f927a in __run_fork_handlers (who=(unknown: 209394016), + who@entry=atfork_run_prepare) at register-atfork.c:116 + #2 0x00007f160c6b7897 in __libc_fork () at ../sysdeps/nptl/fork.c:58 + #3 0x00000000004027d6 in sigusr1_handler (signo=) + at tst-mallocfork2.c:80 + #4 sigusr1_handler (signo=) at tst-mallocfork2.c:64 + #5 + #6 0x00007f160c6f92e4 in __run_fork_handlers (who=who@entry=atfork_run_parent) + at register-atfork.c:136 + #7 0x00007f160c6b79a2 in __libc_fork () at ../sysdeps/nptl/fork.c:152 + #8 0x0000000000402567 in do_test () at tst-mallocfork2.c:156 + #9 0x0000000000402dd2 in support_test_main (argc=1, argv=0x7ffc81ef1ab0, + config=config@entry=0x7ffc81ef1970) at support_test_main.c:350 + #10 0x0000000000402362 in main (argc=, argv=) + at ../support/test-driver.c:168 + + If no locking happens in the single-threaded case (where fork is + expected to be async-signal-safe), this deadlock is avoided. + (pthread_atfork is not required to be async-signal-safe, so a fork + call from a signal handler interrupting pthread_atfork is not + a problem.) + +diff --git a/nptl/register-atfork.c b/nptl/register-atfork.c +index bc797b7..80a1bec 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/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c +index bd68f18..14b69a6 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 a1c3b26..99ed760 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/glibc-rh1746933-1.patch b/glibc-rh1746933-1.patch new file mode 100755 index 0000000..4697916 --- /dev/null +++ b/glibc-rh1746933-1.patch @@ -0,0 +1,60 @@ +commit 58d2672f64176fcb323859d3bd5240fb1cf8f25c +Author: Wilco Dijkstra +Date: Fri May 10 16:38:21 2019 +0100 + + Fix tcache count maximum (BZ #24531) + + The tcache counts[] array is a char, which has a very small range and thus + may overflow. When setting tcache_count tunable, there is no overflow check. + However the tunable must not be larger than the maximum value of the tcache + counts[] array, otherwise it can overflow when filling the tcache. + + [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. + + (cherry picked from commit 5ad533e8e65092be962e414e0417112c65d154fb) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 723d393f529bdb4c..92239b3324584060 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; + +@@ -5124,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/manual/tunables.texi b/manual/tunables.texi +index bb4819bdf1de273e..9dccf2ee7f8eec17 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -188,8 +188,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/glibc-rh1746933-2.patch b/glibc-rh1746933-2.patch new file mode 100755 index 0000000..97fc261 --- /dev/null +++ b/glibc-rh1746933-2.patch @@ -0,0 +1,37 @@ +commit 3640758943c856268bc12a3307838c2a65d2f9ea +Author: Joseph Myers +Date: Mon Feb 4 23:46:58 2019 +0000 + + Fix assertion in malloc.c:tcache_get. + + One of the warnings that appears with -Wextra is "ordered comparison + of pointer with integer zero" in malloc.c:tcache_get, for the + assertion: + + assert (tcache->entries[tc_idx] > 0); + + Indeed, a "> 0" comparison does not make sense for + tcache->entries[tc_idx], which is a pointer. My guess is that + tcache->counts[tc_idx] is what's intended here, and this patch changes + the assertion accordingly. + + Tested for x86_64. + + * malloc/malloc.c (tcache_get): Compare tcache->counts[tc_idx] + with 0, not tcache->entries[tc_idx]. + + (cherry picked from commit 77dc0d8643aa99c92bf671352b0a8adde705896f) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 92239b3324584060..998879aededf0d7c 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -2948,7 +2948,7 @@ tcache_get (size_t tc_idx) + { + tcache_entry *e = tcache->entries[tc_idx]; + assert (tc_idx < TCACHE_MAX_BINS); +- assert (tcache->entries[tc_idx] > 0); ++ assert (tcache->counts[tc_idx] > 0); + tcache->entries[tc_idx] = e->next; + --(tcache->counts[tc_idx]); + e->key = NULL; diff --git a/glibc-rh1746933-3.patch b/glibc-rh1746933-3.patch new file mode 100755 index 0000000..f4c1c95 --- /dev/null +++ b/glibc-rh1746933-3.patch @@ -0,0 +1,92 @@ +commit f88c59f4657ac2e0bab8f51f60022ecbe7f12e2e +Author: Wilco Dijkstra +Date: Fri May 17 18:16:20 2019 +0100 + + Small tcache improvements + + Change the tcache->counts[] entries to uint16_t - this removes + the limit set by char and allows a larger tcache. Remove a few + redundant asserts. + + bench-malloc-thread with 4 threads is ~15% faster on Cortex-A72. + + Reviewed-by: DJ Delorie + + * malloc/malloc.c (MAX_TCACHE_COUNT): Increase to UINT16_MAX. + (tcache_put): Remove redundant assert. + (tcache_get): Remove redundant asserts. + (__libc_malloc): Check tcache count is not zero. + * manual/tunables.texi (glibc.malloc.tcache_count): Update maximum. + + (cherry picked from commit 1f50f2ad854c84ead522bfc7331b46dbe6057d53) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 998879aededf0d7c..e6a483d5cf7c4312 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -321,6 +321,10 @@ __malloc_assert (const char *assertion, const char *file, unsigned int line, + /* This is another arbitrary limit, which tunables can change. Each + tcache bin will hold at most this number of chunks. */ + # define TCACHE_FILL_COUNT 7 ++ ++/* Maximum chunks in tcache bins for tunables. This value must fit the range ++ of tcache->counts[] entries, else they may overflow. */ ++# define MAX_TCACHE_COUNT UINT16_MAX + #endif + + +@@ -2915,12 +2919,10 @@ typedef struct tcache_entry + time), this is for performance reasons. */ + typedef struct tcache_perthread_struct + { +- char counts[TCACHE_MAX_BINS]; ++ uint16_t counts[TCACHE_MAX_BINS]; + 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; + +@@ -2930,7 +2932,6 @@ static __always_inline void + tcache_put (mchunkptr chunk, size_t tc_idx) + { + tcache_entry *e = (tcache_entry *) chunk2mem (chunk); +- assert (tc_idx < TCACHE_MAX_BINS); + + /* Mark this chunk as "in the tcache" so the test in _int_free will + detect a double free. */ +@@ -2947,8 +2948,6 @@ static __always_inline void * + tcache_get (size_t tc_idx) + { + tcache_entry *e = tcache->entries[tc_idx]; +- assert (tc_idx < TCACHE_MAX_BINS); +- assert (tcache->counts[tc_idx] > 0); + tcache->entries[tc_idx] = e->next; + --(tcache->counts[tc_idx]); + e->key = NULL; +@@ -3053,9 +3052,8 @@ __libc_malloc (size_t bytes) + + DIAG_PUSH_NEEDS_COMMENT; + if (tc_idx < mp_.tcache_bins +- /*&& tc_idx < TCACHE_MAX_BINS*/ /* to appease gcc */ + && tcache +- && tcache->entries[tc_idx] != NULL) ++ && tcache->counts[tc_idx] > 0) + { + return tcache_get (tc_idx); + } +diff --git a/manual/tunables.texi b/manual/tunables.texi +index 9dccf2ee7f8eec17..f6c49250e3889ddd 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -188,7 +188,7 @@ 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. +-The upper limit is 127. If set to zero, the per-thread cache is effectively ++The upper limit is 65535. If set to zero, the per-thread cache is effectively + disabled. + + The approximate maximum overhead of the per-thread cache is thus equal diff --git a/glibc-rh1747453.patch b/glibc-rh1747453.patch new file mode 100755 index 0000000..d02b6b2 --- /dev/null +++ b/glibc-rh1747453.patch @@ -0,0 +1,156 @@ +commit 8692ebdb1259be60c545fa509d4852b26703777e +Author: David Newall +Date: Mon Feb 4 13:35:11 2019 +0100 + + elf: Implement --preload option for the dynamic linker + +diff --git a/elf/Makefile b/elf/Makefile +index 9cf5cd8dfd..db6a2a0c29 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -354,7 +354,8 @@ endif + + ifeq (yes,$(build-shared)) + ifeq ($(run-built-tests),yes) +-tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out ++tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \ ++ $(objpfx)tst-rtld-preload.out + endif + tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \ + $(objpfx)check-localplt.out $(objpfx)check-initfini.out +@@ -883,6 +884,15 @@ $(objpfx)tst-rtld-load-self.out: tst-rtld-load-self.sh $(objpfx)ld.so + $(SHELL) $^ '$(test-wrapper)' '$(test-wrapper-env)' > $@; \ + $(evaluate-test) + ++tst-rtld-preload-OBJS = $(subst $(empty) ,:,$(strip $(preloadtest-preloads:=.so))) ++$(objpfx)tst-rtld-preload.out: tst-rtld-preload.sh $(objpfx)ld.so \ ++ $(objpfx)preloadtest \ ++ $(preloadtest-preloads:%=$(objpfx)%.so) ++ $(SHELL) $< $(objpfx)ld.so $(objpfx)preloadtest \ ++ '$(test-wrapper)' '$(test-wrapper-env)' '$(run_program_env)' \ ++ '$(rpath-link)' '$(tst-rtld-preload-OBJS)' > $@; \ ++ $(evaluate-test) ++ + $(objpfx)initfirst: $(libdl) + $(objpfx)initfirst.out: $(objpfx)firstobj.so + +diff --git a/elf/rtld.c b/elf/rtld.c +index 5d97f41b7b..5a90e78ed6 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -826,15 +826,18 @@ static const char *library_path attribute_relro; + static const char *preloadlist attribute_relro; + /* Nonzero if information about versions has to be printed. */ + static int version_info attribute_relro; ++/* The preload list passed as a command argument. */ ++static const char *preloadarg attribute_relro; + + /* The LD_PRELOAD environment variable gives list of libraries + separated by white space or colons that are loaded before the + executable's dependencies and prepended to the global scope list. + (If the binary is running setuid all elements containing a '/' are + ignored since it is insecure.) Return the number of preloads +- performed. */ ++ performed. Ditto for --preload command argument. */ + unsigned int +-handle_ld_preload (const char *preloadlist, struct link_map *main_map) ++handle_preload_list (const char *preloadlist, struct link_map *main_map, ++ const char *where) + { + unsigned int npreloads = 0; + const char *p = preloadlist; +@@ -858,7 +861,7 @@ handle_ld_preload (const char *preloadlist, struct link_map *main_map) + ++p; + + if (dso_name_valid_for_suid (fname)) +- npreloads += do_preload (fname, main_map, "LD_PRELOAD"); ++ npreloads += do_preload (fname, main_map, where); + } + return npreloads; + } +@@ -974,6 +977,13 @@ dl_main (const ElfW(Phdr) *phdr, + { + process_dl_audit (_dl_argv[2]); + ++ _dl_skip_args += 2; ++ _dl_argc -= 2; ++ _dl_argv += 2; ++ } ++ else if (! strcmp (_dl_argv[1], "--preload") && _dl_argc > 2) ++ { ++ preloadarg = _dl_argv[2]; + _dl_skip_args += 2; + _dl_argc -= 2; + _dl_argv += 2; +@@ -1006,7 +1016,8 @@ of this helper program; chances are you did not intend to run this program.\n\ + variable LD_LIBRARY_PATH\n\ + --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\ + in LIST\n\ +- --audit LIST use objects named in LIST as auditors\n"); ++ --audit LIST use objects named in LIST as auditors\n\ ++ --preload LIST preload objects named in LIST\n"); + + ++_dl_skip_args; + --_dl_argc; +@@ -1620,7 +1631,16 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", + if (__glibc_unlikely (preloadlist != NULL)) + { + HP_TIMING_NOW (start); +- npreloads += handle_ld_preload (preloadlist, main_map); ++ npreloads += handle_preload_list (preloadlist, main_map, "LD_PRELOAD"); ++ HP_TIMING_NOW (stop); ++ HP_TIMING_DIFF (diff, start, stop); ++ HP_TIMING_ACCUM_NT (load_time, diff); ++ } ++ ++ if (__glibc_unlikely (preloadarg != NULL)) ++ { ++ HP_TIMING_NOW (start); ++ npreloads += handle_preload_list (preloadarg, main_map, "--preload"); + HP_TIMING_NOW (stop); + HP_TIMING_DIFF (diff, start, stop); + HP_TIMING_ACCUM_NT (load_time, diff); +diff --git a/elf/tst-rtld-preload.sh b/elf/tst-rtld-preload.sh +new file mode 100755 +index 0000000000..f0c0ca11ba +--- /dev/null ++++ b/elf/tst-rtld-preload.sh +@@ -0,0 +1,38 @@ ++#!/bin/sh ++# Test --preload argument ld.so. ++# 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 ++# . ++ ++set -e ++ ++rtld=$1 ++test_program=$2 ++test_wrapper=$3 ++test_wrapper_env=$4 ++run_program_env=$5 ++library_path=$6 ++preload=$7 ++ ++echo "# [${test_wrapper}] [$rtld] [--library-path] [$library_path]" \ ++ "[--preload] [$preload] [$test_program]" ++${test_wrapper_env} \ ++${run_program_env} \ ++${test_wrapper} $rtld --library-path "$library_path" \ ++ --preload "$preload" $test_program 2>&1 && rc=0 || rc=$? ++echo "# exit status $rc" ++ ++exit $rc diff --git a/glibc-rh1747502-1.patch b/glibc-rh1747502-1.patch new file mode 100755 index 0000000..b57f046 --- /dev/null +++ b/glibc-rh1747502-1.patch @@ -0,0 +1,168 @@ +commit 561b0bec4448f0302cb4915bf67c919bde4a1c57 +Author: DJ Delorie +Date: Fri Jul 6 01:10:41 2018 -0400 + + Add test-in-container infrastructure. + + * Makefile (testroot.pristine): New rules to initialize the + test-in-container "testroot". + * Makerules (all-testsuite): Add tests-container. + * Rules (tests-expected): Add tests-container. + (binaries-all-tests): Likewise. + (tests-container): New, run these tests in the testroot container. + * support/links-dso-program-c.c: New. + * support/links-dso-program.cc: New. + * support/test-container.c: New. + * support/shell-container.c: New. + * support/echo-container.c: New. + * support/true-container.c: New. + * support/xmkdirp.c: New. + * support/xsymlink.c: New. + * support/support_paths.c: New. + * support/support.h: Add support paths prototypes. + * support/xunistd.h: Add xmkdirp () and xsymlink (). + + * nss/tst-nss-test3.c: Convert to test-in-container. + * nss/tst-nss-test3.root/: New. + +(note: support/ already present, not needed; sample test not included) + +diff --git a/Makefile b/Makefile +index d3f25a5..3df55e6 100644 +--- a/Makefile ++++ b/Makefile +@@ -340,6 +340,62 @@ define summarize-tests + @! egrep -q -v '^(X?PASS|XFAIL|UNSUPPORTED):' $(objpfx)$1 + endef + ++# The intention here is to do ONE install of our build into the ++# testroot.pristine/ directory, then rsync (internal to ++# support/test-container) that to testroot.root/ at the start of each ++# test. That way we can promise each test a "clean" install, without ++# having to do the install for each test. ++# ++# In addition, we have to copy some files (which we build) into this ++# root in addition to what glibc installs. For example, many tests ++# require additional programs including /bin/sh, /bin/true, and ++# /bin/echo, all of which we build below to limit library dependencies ++# to just those things in glibc and language support libraries which ++# we also copy into the into the rootfs. To determine what language ++# support libraries we need we build a "test" program in either C or ++# (if available) C++ just so we can copy in any shared objects ++# (which we do not build) that GCC-compiled programs depend on. ++ ++ ++ifeq (,$(CXX)) ++LINKS_DSO_PROGRAM = links-dso-program-c ++else ++LINKS_DSO_PROGRAM = links-dso-program ++endif ++ ++$(tests-container) $(addsuffix /tests,$(subdirs)) : \ ++ $(objpfx)testroot.pristine/install.stamp ++$(objpfx)testroot.pristine/install.stamp : ++ test -d $(objpfx)testroot.pristine || \ ++ mkdir $(objpfx)testroot.pristine ++ # We need a working /bin/sh for some of the tests. ++ test -d $(objpfx)testroot.pristine/bin || \ ++ mkdir $(objpfx)testroot.pristine/bin ++ cp $(objpfx)support/shell-container $(objpfx)testroot.pristine/bin/sh ++ cp $(objpfx)support/echo-container $(objpfx)testroot.pristine/bin/echo ++ cp $(objpfx)support/true-container $(objpfx)testroot.pristine/bin/true ++ # Copy these DSOs first so we can overwrite them with our own. ++ for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \ ++ $(objpfx)elf/$(rtld-installed-name) \ ++ $(objpfx)testroot.pristine/bin/sh \ ++ | grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\ ++ do \ ++ test -d `dirname $(objpfx)testroot.pristine$$dso` || \ ++ mkdir -p `dirname $(objpfx)testroot.pristine$$dso` ;\ ++ $(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\ ++ done ++ for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \ ++ $(objpfx)elf/$(rtld-installed-name) \ ++ $(objpfx)support/$(LINKS_DSO_PROGRAM) \ ++ | grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\ ++ do \ ++ test -d `dirname $(objpfx)testroot.pristine$$dso` || \ ++ mkdir -p `dirname $(objpfx)testroot.pristine$$dso` ;\ ++ $(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\ ++ done ++ $(MAKE) install DESTDIR=$(objpfx)testroot.pristine ++ touch $(objpfx)testroot.pristine/install.stamp ++ + tests-special-notdir = $(patsubst $(objpfx)%, %, $(tests-special)) + tests: $(tests-special) + $(..)scripts/merge-test-results.sh -s $(objpfx) "" \ +diff --git a/Makerules b/Makerules +index a10a0b4..5d6434c 100644 +--- a/Makerules ++++ b/Makerules +@@ -1369,7 +1369,8 @@ xcheck: xtests + # The only difference between MODULE_NAME=testsuite and MODULE_NAME=nonlib is + # that almost all internal declarations from config.h, libc-symbols.h, and + # include/*.h are not available to 'testsuite' code, but are to 'nonlib' code. +-all-testsuite := $(strip $(tests) $(xtests) $(test-srcs) $(test-extras)) ++all-testsuite := $(strip $(tests) $(xtests) $(test-srcs) $(test-extras) \ ++ $(tests-container)) + ifneq (,$(all-testsuite)) + cpp-srcs-left = $(all-testsuite) + lib := testsuite +diff --git a/Rules b/Rules +index 706c8a7..5abb727 100644 +--- a/Rules ++++ b/Rules +@@ -130,12 +130,14 @@ others: $(py-const) + + ifeq ($(run-built-tests),no) + tests: $(addprefix $(objpfx),$(filter-out $(tests-unsupported), \ +- $(tests) $(tests-internal)) \ ++ $(tests) $(tests-internal) \ ++ $(tests-container)) \ + $(test-srcs)) $(tests-special) \ + $(tests-printers-programs) + xtests: tests $(xtests-special) + else + tests: $(tests:%=$(objpfx)%.out) $(tests-internal:%=$(objpfx)%.out) \ ++ $(tests-container:%=$(objpfx)%.out) \ + $(tests-special) $(tests-printers-out) + xtests: tests $(xtests:%=$(objpfx)%.out) $(xtests-special) + endif +@@ -145,7 +147,8 @@ xtests-special-notdir = $(patsubst $(objpfx)%, %, $(xtests-special)) + ifeq ($(run-built-tests),no) + tests-expected = + else +-tests-expected = $(tests) $(tests-internal) $(tests-printers) ++tests-expected = $(tests) $(tests-internal) $(tests-printers) \ ++ $(tests-container) + endif + tests: + $(..)scripts/merge-test-results.sh -s $(objpfx) $(subdir) \ +@@ -158,7 +161,8 @@ xtests: + + ifeq ($(build-programs),yes) + binaries-all-notests = $(others) $(sysdep-others) +-binaries-all-tests = $(tests) $(tests-internal) $(xtests) $(test-srcs) ++binaries-all-tests = $(tests) $(tests-internal) $(xtests) $(test-srcs) \ ++ $(tests-container) + binaries-all = $(binaries-all-notests) $(binaries-all-tests) + binaries-static-notests = $(others-static) + binaries-static-tests = $(tests-static) $(xtests-static) +@@ -248,6 +252,17 @@ $(objpfx)%.out: /dev/null $(objpfx)% # Make it 2nd arg for canned sequence. + $(make-test-out) > $@; \ + $(evaluate-test) + ++ ++# Any tests that require an isolated container (filesystem, network ++# and pid namespaces) in which to run, should be added to ++# tests-container. ++$(tests-container:%=$(objpfx)%.out): $(objpfx)%.out : $(if $(wildcard $(objpfx)%.files),$(objpfx)%.files,/dev/null) $(objpfx)% ++ $(test-wrapper-env) $(run-program-env) $(run-via-rtld-prefix) \ ++ $(common-objpfx)support/test-container env $(run-program-env) $($*-ENV) \ ++ $(host-test-program-cmd) $($*-ARGS) > $@; \ ++ $(evaluate-test) ++ ++ + # tests-unsupported lists tests that we will not try to build at all in + # this configuration. Note this runs every time because it does not + # actually create its target. The dependency on Makefile is meant to diff --git a/glibc-rh1747502-2.patch b/glibc-rh1747502-2.patch new file mode 100755 index 0000000..17a53e1 --- /dev/null +++ b/glibc-rh1747502-2.patch @@ -0,0 +1,48 @@ +commit bd598da9f454bc1091b4ebe0303b07e6f96ca130 +Author: Joseph Myers +Date: Tue Dec 4 16:52:39 2018 +0000 + + Stop test-in-container trying to run other-OS binaries. + + I noticed that, now that build-many-glibcs.py no longer copies glibc + sources, I was getting core dumps in my glibc source directories. The + cause appears to be, from the i686-gnu build: + + for dso in ` env LD_TRACE_LOADED_OBJECTS=1 \ + /scratch/jmyers/glibc-bot/build/glibcs/i686-gnu/glibc/elf/ld.so.1 \ + /scratch/jmyers/glibc-bot/build/glibcs/i686-gnu/glibc/testroot.pristine/bin/sh \ + [...] + Segmentation fault (core dumped) + + In this case, the x86 architecture means the binary executes, but + dumps core rather than actually working. + + Anything involving running the newly built glibc should only be done + ifeq ($(run-built-tests),yes). This patch conditions the relevant + part of the testroot setup accordingly. + + Tested for x86_64, and with build-many-glibcs.py for i686-gnu. + + * Makefile ($(objpfx)testroot.pristine/install.stamp): Do not run + dynamic linker unless [$(run-built-tests) = yes]. + +diff --git a/Makefile b/Makefile +index b4703e4..fd73d9b 100644 +--- a/Makefile ++++ b/Makefile +@@ -374,6 +374,7 @@ $(objpfx)testroot.pristine/install.stamp : + cp $(objpfx)support/shell-container $(objpfx)testroot.pristine/bin/sh + cp $(objpfx)support/echo-container $(objpfx)testroot.pristine/bin/echo + cp $(objpfx)support/true-container $(objpfx)testroot.pristine/bin/true ++ifeq ($(run-built-tests),yes) + # Copy these DSOs first so we can overwrite them with our own. + for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \ + $(objpfx)elf/$(rtld-installed-name) \ +@@ -393,6 +394,7 @@ $(objpfx)testroot.pristine/install.stamp : + mkdir -p `dirname $(objpfx)testroot.pristine$$dso` ;\ + $(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\ + done ++endif + $(MAKE) install DESTDIR=$(objpfx)testroot.pristine + touch $(objpfx)testroot.pristine/install.stamp + diff --git a/glibc-rh1747502-3.patch b/glibc-rh1747502-3.patch new file mode 100755 index 0000000..f0c5027 --- /dev/null +++ b/glibc-rh1747502-3.patch @@ -0,0 +1,40 @@ +commit 95da14dac04b494149290d85bc5306226e30839e +Author: Tulio Magno Quites Machado Filho +Date: Mon Jul 22 16:30:45 2019 -0300 + + test-container: Avoid copying unintended system libraries + + Some DSOs are distributed in hardware capability directories, e.g. + /usr/lib64/power7/libc.so.6 + Whenever the processor is able to use one of these hardware-enabled + DSOs, testroot.pristine ends up with copies of glibc-provided libraries + from the system because it can't overwrite or remove them. + + This patch avoids the unintended copies by executing ld.so with the same + arguments passed to each glibc test. + + * Makefile (testroot.pristine/install.stamp): Execute ld.so with + the same arguments used in all tests. + +diff --git a/Makefile b/Makefile +index dc5de7a..a4ed747 100644 +--- a/Makefile ++++ b/Makefile +@@ -383,7 +383,7 @@ $(objpfx)testroot.pristine/install.stamp : + ifeq ($(run-built-tests),yes) + # Copy these DSOs first so we can overwrite them with our own. + for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \ +- $(objpfx)elf/$(rtld-installed-name) \ ++ $(rtld-prefix) \ + $(objpfx)testroot.pristine/bin/sh \ + | grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\ + do \ +@@ -392,7 +392,7 @@ ifeq ($(run-built-tests),yes) + $(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\ + done + for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \ +- $(objpfx)elf/$(rtld-installed-name) \ ++ $(rtld-prefix) \ + $(objpfx)support/$(LINKS_DSO_PROGRAM) \ + | grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\ + do \ diff --git a/glibc-rh1747502-4.patch b/glibc-rh1747502-4.patch new file mode 100755 index 0000000..2e25309 --- /dev/null +++ b/glibc-rh1747502-4.patch @@ -0,0 +1,31 @@ +commit 35e038c1d2ccb3a75395662f9c4f28d85a61444f +Author: Tulio Magno Quites Machado Filho +Date: Mon Jul 22 17:34:13 2019 -0300 + + test-container: Install with $(all-subdirs) [BZ #24794] + + Whenever a sub-make is created, it inherits the variable subdirs from its + parent. This is also true when make check is called with a restricted + list of subdirs. In this scenario, make install is executed "partially" + and testroot.pristine ends up with an incomplete installation. + + [BZ #24794] + * Makefile (testroot.pristine/install.stamp): Pass + subdirs='$(all-subdirs)' to make install. + + Reviewed-by: DJ Delorie + +diff --git a/Makefile b/Makefile +index a4ed747..9fbf705 100644 +--- a/Makefile ++++ b/Makefile +@@ -401,7 +401,8 @@ ifeq ($(run-built-tests),yes) + $(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\ + done + endif +- $(MAKE) install DESTDIR=$(objpfx)testroot.pristine ++ $(MAKE) install DESTDIR=$(objpfx)testroot.pristine \ ++ subdirs='$(all-subdirs)' + touch $(objpfx)testroot.pristine/install.stamp + + tests-special-notdir = $(patsubst $(objpfx)%, %, $(tests-special)) diff --git a/glibc-rh1747502-5.patch b/glibc-rh1747502-5.patch new file mode 100755 index 0000000..30dd75e --- /dev/null +++ b/glibc-rh1747502-5.patch @@ -0,0 +1,56 @@ +commit 7db1fe38de21831d53ceab9ae83493d8d1aec601 +Author: Joseph Myers +Date: Tue Oct 22 20:24:10 2019 +0000 + + Fix testroot.pristine creation copying dynamic linker. + + This patch addresses an issue reported in + where the + creation of testroot.pristine, on encountering + LD_TRACE_LOADED_OBJECTS=1 of the form + + libc.so.6 => /scratch/jmyers/glibc/mbs/obj/glibc-8-0-mips64-linux-gnu-x86_64-linux-gnu/default/libc.so.6 (0x772dd000) + /lib32/ld.so.1 => /scratch/jmyers/glibc/mbs/obj/glibc-8-0-mips64-linux-gnu-x86_64-linux-gnu/default/elf/ld.so.1 (0x7747b000) + + tries to copy /lib32/ld.so.1 (which does not exist) into the testroot + instead of copying the path on the RHS of "=>", which does exist, + because the Makefile logic assumes that the path on such a line with + '/' should be copied, when if there are such paths on both the LHS and + the RHS of "=>", only the one on the RHS necessarily exists and so + only that should be copied. The patch follows the approach suggested + by DJ in , + with the suggestion from Andreas in + of a + single sed command in place of pipeline of grep and three sed + commands. + + Tested for x86_64, with and without --enable-hardcoded-path-in-tests; + a previous version with multiple sed commands, implementing the same + logic, also tested for MIPS, with and without + --enable-hardcoded-path-in-tests, to confirm it fixes the original + problem. + + Co-authored-by: DJ Delorie + +diff --git a/Makefile b/Makefile +index d7e4be9..0711b97 100644 +--- a/Makefile ++++ b/Makefile +@@ -564,7 +564,7 @@ ifeq ($(run-built-tests),yes) + for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \ + $(rtld-prefix) \ + $(objpfx)testroot.pristine/bin/sh \ +- | grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\ ++ | sed -n '/\//{s@.*=> /@/@;s/^[^/]*//;s/ .*//p;}'` ;\ + do \ + test -d `dirname $(objpfx)testroot.pristine$$dso` || \ + mkdir -p `dirname $(objpfx)testroot.pristine$$dso` ;\ +@@ -573,7 +573,7 @@ ifeq ($(run-built-tests),yes) + for dso in `$(test-wrapper-env) LD_TRACE_LOADED_OBJECTS=1 \ + $(rtld-prefix) \ + $(objpfx)support/$(LINKS_DSO_PROGRAM) \ +- | grep / | sed 's/^[^/]*//' | sed 's/ .*//'` ;\ ++ | sed -n '/\//{s@.*=> /@/@;s/^[^/]*//;s/ .*//p;}'` ;\ + do \ + test -d `dirname $(objpfx)testroot.pristine$$dso` || \ + mkdir -p `dirname $(objpfx)testroot.pristine$$dso` ;\ diff --git a/glibc-rh1747502-6.patch b/glibc-rh1747502-6.patch new file mode 100755 index 0000000..c84940c --- /dev/null +++ b/glibc-rh1747502-6.patch @@ -0,0 +1,56 @@ +commit c7ac9caaae6f8d02d4e0c7618d4991324a084c66 +Author: Adhemerval Zanella +Date: Mon May 13 13:57:37 2019 -0300 + + support: Export bindir path on support_path + + Checked on x86_64-linux-gnu. + + * support/Makefile (CFLAGS-support_paths.c): Add -DBINDIR_PATH. + * support/support.h (support_bindir_prefix): New variable. + * support/support_paths.c [BINDIR_PATH] (support_bindir_prefix): + + Reviewed-by: DJ Delorie + +diff --git a/support/Makefile b/support/Makefile +index 64044f6..fe416cd 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -179,7 +179,8 @@ CFLAGS-support_paths.c = \ + -DOBJDIR_PATH=\"`cd $(objpfx)/..; pwd`\" \ + -DOBJDIR_ELF_LDSO_PATH=\"`cd $(objpfx)/..; pwd`/elf/$(rtld-installed-name)\" \ + -DINSTDIR_PATH=\"$(prefix)\" \ +- -DLIBDIR_PATH=\"$(libdir)\" ++ -DLIBDIR_PATH=\"$(libdir)\" \ ++ -DBINDIR_PATH=\"$(bindir)\" + + ifeq (,$(CXX)) + LINKS_DSO_PROGRAM = links-dso-program-c +diff --git a/support/support.h b/support/support.h +index 97fef2c..b162491 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -105,6 +105,8 @@ extern const char support_objdir_elf_ldso[]; + extern const char support_install_prefix[]; + /* Corresponds to the install's lib/ or lib64/ directory. */ + extern const char support_libdir_prefix[]; ++/* Corresponds to the install's bin/ directory. */ ++extern const char support_bindir_prefix[]; + + extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *, + size_t, unsigned int); +diff --git a/support/support_paths.c b/support/support_paths.c +index 937e6e1..75634aa 100644 +--- a/support/support_paths.c ++++ b/support/support_paths.c +@@ -57,3 +57,10 @@ const char support_libdir_prefix[] = LIBDIR_PATH; + #else + # error please -DLIBDIR_PATH=something in the Makefile + #endif ++ ++#ifdef BINDIR_PATH ++/* Corresponds to the install's bin/ directory. */ ++const char support_bindir_prefix[] = BINDIR_PATH; ++#else ++# error please -DBINDIR_PATH=something in the Makefile ++#endif diff --git a/glibc-rh1747502-7.patch b/glibc-rh1747502-7.patch new file mode 100755 index 0000000..fa6a63d --- /dev/null +++ b/glibc-rh1747502-7.patch @@ -0,0 +1,46 @@ +From 354e4c1adddb1da19c1043e3e5db61ee2148d912 Mon Sep 17 00:00:00 2001 +From: Tulio Magno Quites Machado Filho +Date: Wed, 24 Jul 2019 19:49:00 -0300 +Subject: test-container: Install with $(sorted-subdirs) [BZ #24794] + +Commit 35e038c1d2ccb3a75395662f9c4f28d85a61444f started to use an +incomplete list of subdirs based on $(all-subdirs) causing +testroot.pristine to miss files from nss. + +Tested if the list of files in testroot.pristine remains the same. + + [BZ #24794] + * Makeconfig (all-subdirs): Improved source comments. + * Makefile (testroot.pristine/install.stamp): Pass + subdirs='$(sorted-subdirs)' to make install. + +diff --git a/Makeconfig b/Makeconfig +index 0e386fbc19..fd36c58c04 100644 +--- a/Makeconfig ++++ b/Makeconfig +@@ -1267,9 +1267,9 @@ else + libsupport = $(common-objpfx)support/libsupport.a + endif + +-# These are the subdirectories containing the library source. The order +-# is more or less arbitrary. The sorting step will take care of the +-# dependencies. ++# This is a partial list of subdirectories containing the library source. ++# The order is more or less arbitrary. The sorting step will take care of the ++# dependencies and generate sorted-subdirs dynamically. + all-subdirs = csu assert ctype locale intl catgets math setjmp signal \ + stdlib stdio-common libio malloc string wcsmbs time dirent \ + grp pwd posix io termios resource misc socket sysvipc gmon \ +diff --git a/Makefile b/Makefile +index 9fbf705200..ac1125853b 100644 +--- a/Makefile ++++ b/Makefile +@@ -402,7 +402,7 @@ ifeq ($(run-built-tests),yes) + done + endif + $(MAKE) install DESTDIR=$(objpfx)testroot.pristine \ +- subdirs='$(all-subdirs)' ++ subdirs='$(sorted-subdirs)' + touch $(objpfx)testroot.pristine/install.stamp + + tests-special-notdir = $(patsubst $(objpfx)%, %, $(tests-special)) diff --git a/glibc-rh1747502-8.patch b/glibc-rh1747502-8.patch new file mode 100755 index 0000000..16f6bf7 --- /dev/null +++ b/glibc-rh1747502-8.patch @@ -0,0 +1,50 @@ +commit d50f09181eca10a91fd9035bb90711b265770dc9 +Author: Alexandra Hájková +Date: Mon May 13 19:31:53 2019 +0200 + + support: Add support_install_rootsbindir + + Reviewed by: Adhemerval Zanella + +diff --git a/support/Makefile b/support/Makefile +index fe416cd..18d39f5 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -180,7 +180,8 @@ CFLAGS-support_paths.c = \ + -DOBJDIR_ELF_LDSO_PATH=\"`cd $(objpfx)/..; pwd`/elf/$(rtld-installed-name)\" \ + -DINSTDIR_PATH=\"$(prefix)\" \ + -DLIBDIR_PATH=\"$(libdir)\" \ +- -DBINDIR_PATH=\"$(bindir)\" ++ -DBINDIR_PATH=\"$(bindir)\" \ ++ -DROOTSBINDIR_PATH=\"$(rootsbindir)\" + + ifeq (,$(CXX)) + LINKS_DSO_PROGRAM = links-dso-program-c +diff --git a/support/support.h b/support/support.h +index b162491..13076b7 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -107,6 +107,8 @@ extern const char support_install_prefix[]; + extern const char support_libdir_prefix[]; + /* Corresponds to the install's bin/ directory. */ + extern const char support_bindir_prefix[]; ++/* Corresponds to the install's sbin/ directory. */ ++extern const char support_install_rootsbindir[]; + + extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *, + size_t, unsigned int); +diff --git a/support/support_paths.c b/support/support_paths.c +index 75634aa..1fe3283 100644 +--- a/support/support_paths.c ++++ b/support/support_paths.c +@@ -64,3 +64,10 @@ const char support_bindir_prefix[] = BINDIR_PATH; + #else + # error please -DBINDIR_PATH=something in the Makefile + #endif ++ ++#ifdef ROOTSBINDIR_PATH ++/* Corresponds to the install's sbin/ directory. */ ++const char support_install_rootsbindir[] = ROOTSBINDIR_PATH; ++#else ++# error please -DROOTSBINDIR_PATH=something in the Makefile ++#endif diff --git a/glibc-rh1747502-9.patch b/glibc-rh1747502-9.patch new file mode 100755 index 0000000..8bf528d --- /dev/null +++ b/glibc-rh1747502-9.patch @@ -0,0 +1,86 @@ +From 304c61a24f909168c16793ccf7c686237e53d003 Mon Sep 17 00:00:00 2001 +From: DJ Delorie +Date: Wed, 5 Dec 2018 12:39:47 -0500 +Subject: test-container: move postclean outside of namespace changes + +During postclean.req testing it was found that the fork in the +parent process (after the unshare syscall) would fail with ENOMEM +(see recursive_remove() in test-container.c). While failing with +ENOMEM is certainly unexpected, it is simply easier to refactor +the design and have the parent remain outside of the namespace. +This change moves the postclean.req processing to a distinct +process (the parent) that then forks the test process (which will +have to fork once more to complete uid/gid transitions). When the +test process exists the cleanup process will ensure all files are +deleted when a post clean is requested. + +Signed-off-by: DJ Delorie +Reviewed-by: Carlos O'Donell + +[BZ #23948] +* support/test-container.c: Move postclean step to before we +change namespaces. + +diff --git a/support/test-container.c b/support/test-container.c +index df450adfdb..1d1aebeaf3 100644 +--- a/support/test-container.c ++++ b/support/test-container.c +@@ -921,6 +921,43 @@ main (int argc, char **argv) + } + } + ++ if (do_postclean) ++ { ++ pid_t pc_pid = fork (); ++ ++ if (pc_pid < 0) ++ { ++ FAIL_EXIT1 ("Can't fork for post-clean"); ++ } ++ else if (pc_pid > 0) ++ { ++ /* Parent. */ ++ int status; ++ waitpid (pc_pid, &status, 0); ++ ++ /* Child has exited, we can post-clean the test root. */ ++ printf("running post-clean rsync\n"); ++ rsync (pristine_root_path, new_root_path, 1); ++ ++ if (WIFEXITED (status)) ++ exit (WEXITSTATUS (status)); ++ ++ if (WIFSIGNALED (status)) ++ { ++ printf ("%%SIGNALLED%%\n"); ++ exit (77); ++ } ++ ++ printf ("%%EXITERROR%%\n"); ++ exit (78); ++ } ++ ++ /* Child continues. */ ++ } ++ ++ /* This is the last point in the program where we're still in the ++ "normal" namespace. */ ++ + #ifdef CLONE_NEWNS + /* The unshare here gives us our own spaces and capabilities. */ + if (unshare (CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNS) < 0) +@@ -974,14 +1011,6 @@ main (int argc, char **argv) + int status; + waitpid (child, &status, 0); + +- /* There's a bit of magic here, since the buildroot is mounted +- in our space, the paths are still valid, and since the mounts +- aren't recursive, it sees *only* the built root, not anything +- we would normally se if we rsync'd to "/" like mounted /dev +- files. */ +- if (do_postclean) +- rsync (pristine_root_path, new_root_path, 1); +- + if (WIFEXITED (status)) + exit (WEXITSTATUS (status)); + diff --git a/glibc-rh1747502.patch b/glibc-rh1747502.patch new file mode 100755 index 0000000..e28de98 --- /dev/null +++ b/glibc-rh1747502.patch @@ -0,0 +1,268 @@ +commit 99135114ba23c3110b7e4e650fabdc5e639746b7 +Author: DJ Delorie +Date: Fri Jun 28 18:30:00 2019 -0500 + + nss_db: fix endent wrt NULL mappings [BZ #24695] [BZ #24696] + + nss_db allows for getpwent et al to be called without a set*ent, + but it only works once. After the last get*ent a set*ent is + required to restart, because the end*ent did not properly reset + the module. Resetting it to NULL allows for a proper restart. + + If the database doesn't exist, however, end*ent erroniously called + munmap which set errno. + + The test case runs "makedb" inside the testroot, so needs selinux + DSOs installed. + +diff -rupN a/nss/Makefile b/nss/Makefile +--- a/nss/Makefile 2019-11-04 15:14:16.721221038 -0500 ++++ b/nss/Makefile 2019-11-04 15:15:46.447544678 -0500 +@@ -60,6 +60,10 @@ tests = test-netdb test-digits-dots ts + tst-nss-test5 + xtests = bug-erange + ++tests-container = \ ++ tst-nss-db-endpwent \ ++ tst-nss-db-endgrent ++ + # Tests which need libdl + ifeq (yes,$(build-shared)) + tests += tst-nss-files-hosts-erange +diff -rupN a/nss/nss_db/db-open.c b/nss/nss_db/db-open.c +--- a/nss/nss_db/db-open.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/nss_db/db-open.c 2019-11-04 15:15:10.520213846 -0500 +@@ -63,5 +63,9 @@ internal_setent (const char *file, struc + void + internal_endent (struct nss_db_map *mapping) + { +- munmap (mapping->header, mapping->len); ++ if (mapping->header != NULL) ++ { ++ munmap (mapping->header, mapping->len); ++ mapping->header = NULL; ++ } + } +diff -rupN a/nss/tst-nss-db-endgrent.c b/nss/tst-nss-db-endgrent.c +--- a/nss/tst-nss-db-endgrent.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/nss/tst-nss-db-endgrent.c 2019-11-04 15:15:10.526214069 -0500 +@@ -0,0 +1,54 @@ ++/* Test for endgrent changing errno for BZ #24696 ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++/* The following test verifies that if the db NSS Service is initialized ++ with no database (getgrent), that a subsequent closure (endgrent) does ++ not set errno. In the case of the db service it is not an error to close ++ the service and so it should not set errno. */ ++ ++static int ++do_test (void) ++{ ++ /* Just make sure it's not there, although usually it won't be. */ ++ unlink ("/var/db/group.db"); ++ ++ /* This, in conjunction with the testroot's nsswitch.conf, causes ++ the nss_db module to be "connected" and initialized - but the ++ testroot has no group.db, so no mapping will be created. */ ++ getgrent (); ++ ++ errno = 0; ++ ++ /* Before the fix, this would call munmap (NULL) and set errno. */ ++ endgrent (); ++ ++ if (errno != 0) ++ FAIL_EXIT1 ("endgrent set errno to %d\n", errno); ++ ++ return 0; ++} ++#include +diff -rupN a/nss/tst-nss-db-endgrent.root/etc/nsswitch.conf b/nss/tst-nss-db-endgrent.root/etc/nsswitch.conf +--- a/nss/tst-nss-db-endgrent.root/etc/nsswitch.conf 1969-12-31 19:00:00.000000000 -0500 ++++ b/nss/tst-nss-db-endgrent.root/etc/nsswitch.conf 2019-11-04 15:15:10.539214550 -0500 +@@ -0,0 +1 @@ ++group : db files +diff -rupN a/nss/tst-nss-db-endpwent.c b/nss/tst-nss-db-endpwent.c +--- a/nss/tst-nss-db-endpwent.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/nss/tst-nss-db-endpwent.c 2019-11-04 15:15:10.545214772 -0500 +@@ -0,0 +1,66 @@ ++/* Test for endpwent->getpwent crash for BZ #24695 ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++/* It is entirely allowed to start with a getpwent call without ++ resetting the state of the service via a call to setpwent. ++ You can also call getpwent more times than you have entries in ++ the service, and it should not fail. This test iteratates the ++ database once, gets to the end, and then attempts a second ++ iteration to look for crashes. */ ++ ++static void ++try_it (void) ++{ ++ struct passwd *pw; ++ ++ /* setpwent is intentionally omitted here. The first call to ++ getpwent detects that it's first and initializes. The second ++ time try_it is called, this "first call" was not detected before ++ the fix, and getpwent would crash. */ ++ ++ while ((pw = getpwent ()) != NULL) ++ ; ++ ++ /* We only care if this segfaults or not. */ ++ endpwent (); ++} ++ ++static int ++do_test (void) ++{ ++ char *cmd; ++ ++ cmd = xasprintf ("%s/makedb -o /var/db/passwd.db /var/db/passwd.in", ++ support_bindir_prefix); ++ system (cmd); ++ free (cmd); ++ ++ try_it (); ++ try_it (); ++ ++ return 0; ++} ++#include +diff -rupN a/nss/tst-nss-db-endpwent.root/etc/nsswitch.conf b/nss/tst-nss-db-endpwent.root/etc/nsswitch.conf +--- a/nss/tst-nss-db-endpwent.root/etc/nsswitch.conf 1969-12-31 19:00:00.000000000 -0500 ++++ b/nss/tst-nss-db-endpwent.root/etc/nsswitch.conf 2019-11-04 15:15:10.556215180 -0500 +@@ -0,0 +1 @@ ++passwd: db +diff -rupN a/nss/tst-nss-db-endpwent.root/var/db/passwd.in b/nss/tst-nss-db-endpwent.root/var/db/passwd.in +--- a/nss/tst-nss-db-endpwent.root/var/db/passwd.in 1969-12-31 19:00:00.000000000 -0500 ++++ b/nss/tst-nss-db-endpwent.root/var/db/passwd.in 2019-11-04 15:15:10.567215588 -0500 +@@ -0,0 +1,4 @@ ++.root root:x:0:0:root:/root:/bin/bash ++=0 root:x:0:0:root:/root:/bin/bash ++.bin bin:x:1:1:bin:/bin:/sbin/nologin ++=1 bin:x:1:1:bin:/bin:/sbin/nologin +diff -rupN a/support/Makefile b/support/Makefile +--- a/support/Makefile 2019-11-04 15:14:20.416357911 -0500 ++++ b/support/Makefile 2019-11-04 15:15:10.574215847 -0500 +@@ -180,6 +180,11 @@ LINKS_DSO_PROGRAM = links-dso-program + LDLIBS-links-dso-program = -lstdc++ -lgcc -lgcc_s $(libunwind) + endif + ++ifeq (yes,$(have-selinux)) ++LDLIBS-$(LINKS_DSO_PROGRAM) += -lselinux ++endif ++ ++ + LDLIBS-test-container = $(libsupport) + + others += test-container +diff -rupN a/support/links-dso-program-c.c b/support/links-dso-program-c.c +--- a/support/links-dso-program-c.c 2019-11-04 15:14:17.073234077 -0500 ++++ b/support/links-dso-program-c.c 2019-11-04 15:15:10.580216069 -0500 +@@ -1,9 +1,26 @@ + #include + ++/* makedb needs selinux dso's. */ ++#ifdef HAVE_SELINUX ++# include ++#endif ++ ++/* The purpose of this file is to indicate to the build system which ++ shared objects need to be copied into the testroot, such as gcc or ++ selinux support libraries. This program is never executed, only ++ scanned for dependencies on shared objects, so the code below may ++ seem weird - it's written to survive gcc optimization and force ++ such dependencies. ++*/ ++ + int + main (int argc, char **argv) + { + /* Complexity to keep gcc from optimizing this away. */ + printf ("This is a test %s.\n", argc > 1 ? argv[1] : "null"); ++#ifdef HAVE_SELINUX ++ /* This exists to force libselinux.so to be required. */ ++ printf ("selinux %d\n", is_selinux_enabled ()); ++#endif + return 0; + } +diff -rupN a/support/links-dso-program.cc b/support/links-dso-program.cc +--- a/support/links-dso-program.cc 2019-11-04 15:14:17.079234300 -0500 ++++ b/support/links-dso-program.cc 2019-11-04 15:15:10.587216328 -0500 +@@ -1,11 +1,28 @@ + #include + ++/* makedb needs selinux dso's. */ ++#ifdef HAVE_SELINUX ++# include ++#endif ++ + using namespace std; + ++/* The purpose of this file is to indicate to the build system which ++ shared objects need to be copied into the testroot, such as gcc or ++ selinux support libraries. This program is never executed, only ++ scanned for dependencies on shared objects, so the code below may ++ seem weird - it's written to survive gcc optimization and force ++ such dependencies. ++*/ ++ + int + main (int argc, char **argv) + { + /* Complexity to keep gcc from optimizing this away. */ + cout << (argc > 1 ? argv[1] : "null"); ++#ifdef HAVE_SELINUX ++ /* This exists to force libselinux.so to be required. */ ++ cout << "selinux " << is_selinux_enabled (); ++#endif + return 0; + } diff --git a/glibc-rh1747505-1.patch b/glibc-rh1747505-1.patch new file mode 100755 index 0000000..7569dff --- /dev/null +++ b/glibc-rh1747505-1.patch @@ -0,0 +1,196 @@ +commit 4b7c74179c8928d971d370e1137d202f891a4cf5 +Author: Carlos O'Donell +Date: Wed Mar 20 12:40:18 2019 -0400 + + nss: Make nsswitch.conf more distribution friendly. + + The current default nsswitch.conf file provided by glibc is not very + distribution friendly. The file contains some minimal directives that no + real distribution uses. This update aims to provide a rich set of + comments which are useful for all distributions, and a broader set of + service defines which should work for all distributions. + + Tested defaults on x86_64 and they work. The nsswitch.conf file more + closely matches what we have in Fedora now, and I'll adjust Fedora to + use this version with minor changes to enable Fedora-specific service + providers. + + v2 + - Add missing databases to manual. + - Add link to manual from default nsswitch.conf. + - Sort nsswitch.conf according to most used database first. + + v3 + - Only mention implemented services in 'NSS Basics.' + - Mention 'automount' in 'Services in the NSS configuration.' + - Sort services in alphabetical order. + + v4 + - Project name is 'Samba'. + + v5 + - Fix typo in manual/nss.texi. + + v6 + - Fix another typo in manual/nss.texi. Ran spell checker this time. + +diff --git a/manual/nss.texi b/manual/nss.texi +index 164ae33246..821469a78a 100644 +--- a/manual/nss.texi ++++ b/manual/nss.texi +@@ -56,13 +56,17 @@ functions to access the databases. + @noindent + The databases available in the NSS are + ++@cindex aliases + @cindex ethers + @cindex group ++@cindex gshadow + @cindex hosts ++@cindex initgroups + @cindex netgroup + @cindex networks +-@cindex protocols + @cindex passwd ++@cindex protocols ++@cindex publickey + @cindex rpc + @cindex services + @cindex shadow +@@ -75,16 +79,22 @@ Ethernet numbers, + @comment @pxref{Ethernet Numbers}. + @item group + Groups of users, @pxref{Group Database}. ++@item gshadow ++Group passphrase hashes and related information. + @item hosts + Host names and numbers, @pxref{Host Names}. ++@item initgroups ++Supplementary group access list. + @item netgroup + Network wide list of host and users, @pxref{Netgroup Database}. + @item networks + Network names and numbers, @pxref{Networks Database}. +-@item protocols +-Network protocols, @pxref{Protocols Database}. + @item passwd + User identities, @pxref{User Database}. ++@item protocols ++Network protocols, @pxref{Protocols Database}. ++@item publickey ++Public keys for Secure RPC. + @item rpc + Remote procedure call names and numbers. + @comment @pxref{RPC Database}. +@@ -96,8 +106,8 @@ User passphrase hashes and related information. + @end table + + @noindent +-There will be some more added later (@code{automount}, @code{bootparams}, +-@code{netmasks}, and @code{publickey}). ++@c We currently don't implement automount, netmasks, or bootparams. ++More databases may be added later. + + @node NSS Configuration File, NSS Module Internals, NSS Basics, Name Service Switch + @section The NSS Configuration File +@@ -159,6 +169,10 @@ these files since they should be placed in a directory where they are + found automatically. Only the names of all available services are + important. + ++Lastly, some system software may make use of the NSS configuration file ++to store their own configuration for similar purposes. Examples of this ++include the @code{automount} service which is used by @code{autofs}. ++ + @node Actions in the NSS configuration, Notes on NSS Configuration File, Services in the NSS configuration, NSS Configuration File + @subsection Actions in the NSS configuration + +diff --git a/nss/nsswitch.conf b/nss/nsswitch.conf +index 39ca88bf51..f553588114 100644 +--- a/nss/nsswitch.conf ++++ b/nss/nsswitch.conf +@@ -1,20 +1,69 @@ ++# + # /etc/nsswitch.conf + # +-# Example configuration of GNU Name Service Switch functionality. ++# An example Name Service Switch config file. This file should be ++# sorted with the most-used services at the beginning. + # ++# Valid databases are: aliases, ethers, group, gshadow, hosts, ++# initgroups, netgroup, networks, passwd, protocols, publickey, ++# rpc, services, and shadow. ++# ++# Valid service provider entries include (in alphabetical order): ++# ++# compat Use /etc files plus *_compat pseudo-db ++# db Use the pre-processed /var/db files ++# dns Use DNS (Domain Name Service) ++# files Use the local files in /etc ++# hesiod Use Hesiod (DNS) for user lookups ++# nis Use NIS (NIS version 2), also called YP ++# nisplus Use NIS+ (NIS version 3) ++# ++# See `info libc 'NSS Basics'` for more information. ++# ++# Commonly used alternative service providers (may need installation): ++# ++# ldap Use LDAP directory server ++# myhostname Use systemd host names ++# mymachines Use systemd machine names ++# mdns*, mdns*_minimal Use Avahi mDNS/DNS-SD ++# resolve Use systemd resolved resolver ++# sss Use System Security Services Daemon (sssd) ++# systemd Use systemd for dynamic user option ++# winbind Use Samba winbind support ++# wins Use Samba wins support ++# wrapper Use wrapper module for testing ++# ++# Notes: ++# ++# 'sssd' performs its own 'files'-based caching, so it should generally ++# come before 'files'. ++# ++# WARNING: Running nscd with a secondary caching service like sssd may ++# lead to unexpected behaviour, especially with how long ++# entries are cached. ++# ++# Installation instructions: ++# ++# To use 'db', install the appropriate package(s) (provide 'makedb' and ++# libnss_db.so.*), and place the 'db' in front of 'files' for entries ++# you want to be looked up first in the databases, like this: ++# ++# passwd: db files ++# shadow: db files ++# group: db files + +-passwd: db files +-group: db files +-initgroups: db [SUCCESS=continue] files +-shadow: db files +-gshadow: files +- +-hosts: files dns +-networks: files dns +- +-protocols: db files +-services: db files +-ethers: db files +-rpc: db files +- +-netgroup: db files ++# In alphabetical order. Re-order as required to optimize peformance. ++aliases: files ++ethers: files ++group: files ++gshadow: files ++hosts: files dns ++initgroups: files ++netgroup: files ++networks: files dns ++passwd: files ++protocols: files ++publickey: files ++rpc: files ++shadow: files ++services: files diff --git a/glibc-rh1747505-2.patch b/glibc-rh1747505-2.patch new file mode 100755 index 0000000..085c2c3 --- /dev/null +++ b/glibc-rh1747505-2.patch @@ -0,0 +1,38 @@ +commit d34d4c80226b3f5a1b51a8e5b005a52fba07d7ba +Author: Carlos O'Donell +Date: Wed Mar 20 22:11:32 2019 -0400 + + nscd: Improve nscd.conf comments. + + This change adds a warning to nscd.conf about running multiple caching + services together and that it may lead to unexpected behaviours. Also we + add a note that enabling the 'shared' option will cause cache hit rates + to be misreported (a side effect of the implementation). + + v2 + - Rewrite comment to avoid implementation details. + +diff --git a/nscd/nscd.conf b/nscd/nscd.conf +index 39b875912d..487ffe461d 100644 +--- a/nscd/nscd.conf ++++ b/nscd/nscd.conf +@@ -3,6 +3,9 @@ + # + # An example Name Service Cache config file. This file is needed by nscd. + # ++# WARNING: Running nscd with a secondary caching service like sssd may lead to ++# unexpected behaviour, especially with how long entries are cached. ++# + # Legal entries are: + # + # logfile +@@ -23,6 +26,9 @@ + # check-files + # persistent + # shared ++# NOTE: Setting 'shared' to a value of 'yes' will accelerate the lookup, ++# but those lookups will not be counted as cache hits ++# i.e. 'nscd -g' may show '0%'. + # max-db-size + # auto-propagate + # diff --git a/glibc-rh1747505-3.patch b/glibc-rh1747505-3.patch new file mode 100755 index 0000000..01e4959 --- /dev/null +++ b/glibc-rh1747505-3.patch @@ -0,0 +1,40 @@ +diff -Nrup a/nss/nsswitch.conf b/nss/nsswitch.conf +--- a/nss/nsswitch.conf 2019-10-25 12:14:09.255834866 -0400 ++++ b/nss/nsswitch.conf 2019-10-25 12:50:08.425769248 -0400 +@@ -1,7 +1,7 @@ + # + # /etc/nsswitch.conf + # +-# An example Name Service Switch config file. This file should be ++# Name Service Switch config file. This file should be + # sorted with the most-used services at the beginning. + # + # Valid databases are: aliases, ethers, group, gshadow, hosts, +@@ -52,18 +52,20 @@ + # shadow: db files + # group: db files + +-# In alphabetical order. Re-order as required to optimize peformance. ++# In order of likelihood of use to accelerate lookup. ++passwd: sss files ++shadow: files sss ++group: sss files ++hosts: files dns myhostname ++services: files sss ++netgroup: sss ++automount: files sss ++ + aliases: files + ethers: files +-group: files + gshadow: files +-hosts: files dns + initgroups: files +-netgroup: files + networks: files dns +-passwd: files + protocols: files + publickey: files + rpc: files +-shadow: files +-services: files diff --git a/glibc-rh1747505-4.patch b/glibc-rh1747505-4.patch new file mode 100755 index 0000000..c0a9b7f --- /dev/null +++ b/glibc-rh1747505-4.patch @@ -0,0 +1,27 @@ +commit eed1f6fcdb0526498223ebfe95f91ef5dec2172a +Author: Carlos O'Donell +Date: Tue Oct 29 11:58:03 2019 -0400 + + Comment out initgroups from example nsswitch.conf (Bug 25146) + + In commit 4b7c74179c8928d971d370e1137d202f891a4cf5 the nsswitch.conf + file was harmonized with downstream distributions, but this change + included adding "initgroups: files". We should not add initgroups by + default, we can have it, but it should be commented out to allow it + to inherit the settings for group. The problem is principally that + downstream authconfig won't update initgroups and it will get out of + sync with the setting for group. + +diff -Nrup a/nss/nsswitch.conf b/nss/nsswitch.conf +--- a/nss/nsswitch.conf 2019-10-29 14:13:15.883199544 -0400 ++++ b/nss/nsswitch.conf 2019-10-29 14:15:44.860978858 -0400 +@@ -64,7 +64,8 @@ automount: files sss + aliases: files + ethers: files + gshadow: files +-initgroups: files ++# Allow initgroups to default to the setting for group. ++# initgroups: files + networks: files dns + protocols: files + publickey: files diff --git a/glibc-rh1748197-1.patch b/glibc-rh1748197-1.patch new file mode 100755 index 0000000..4a68281 --- /dev/null +++ b/glibc-rh1748197-1.patch @@ -0,0 +1,18 @@ +commit 27cec9aed97447dff887a88f4241604fffd8c525 +Author: Florian Weimer +Date: Tue Jul 2 16:45:52 2019 +0200 + + malloc: Add nptl, htl dependency for the subdirectory [BZ #24757] + + memusagestat may indirectly link against libpthread. The built + libpthread should be used, but that is only possible if it has been + built before the malloc programs. + +diff --git a/malloc/Depend b/malloc/Depend +index 910c6d915211870f..f5e248047c4c46dd 100644 +--- a/malloc/Depend ++++ b/malloc/Depend +@@ -1 +1,3 @@ + dlfcn ++nptl ++htl diff --git a/glibc-rh1748197-2.patch b/glibc-rh1748197-2.patch new file mode 100755 index 0000000..483c4f9 --- /dev/null +++ b/glibc-rh1748197-2.patch @@ -0,0 +1,996 @@ +commit 41d6f74e6cb6a92ab428c11ee1e408b2a16aa1b0 +Author: Florian Weimer +Date: Tue Jul 2 15:12:20 2019 +0200 + + nptl: Remove vfork IFUNC-based forwarder from libpthread [BZ #20188] + + With commit f0b2132b35248c1f4a80f62a2c38cddcc802aa8c ("ld.so: + Support moving versioned symbols between sonames [BZ #24741]"), the + dynamic linker will find the definition of vfork in libc and binds + a vfork reference to that symbol, even if the soname in the version + reference says that the symbol should be located in libpthread. + + As a result, the forwarder (whether it's IFUNC-based or a duplicate + of the libc implementation) is no longer necessary. + + On older architectures, a placeholder symbol is required, to make sure + that the GLIBC_2.1.2 symbol version does not go away, or is turned in + to a weak symbol definition by the link editor. (The symbol version + needs to preserved so that the symbol coverage check in + elf/dl-version.c does not fail for old binaries.) + + mips32 is an outlier: It defined __vfork@@GLIBC_2.2, but the + baseline is GLIBC_2.0. Since there are other @@GLIBC_2.2 symbols, + the placeholder symbol is not needed there. + +Conflicts: + nptl/Makefile + (Missing lll_timedwait_tid removal, missing pthread_mutex_conf.) + nptl/pt-vfork.c + sysdeps/unix/sysv/linux/aarch64/pt-vfork.c + sysdeps/unix/sysv/linux/alpha/pt-vfork.S + sysdeps/unix/sysv/linux/hppa/pt-vfork.S + sysdeps/unix/sysv/linux/ia64/pt-vfork.S + sysdeps/unix/sysv/linux/microblaze/pt-vfork.S + (Removal after copyright year change upstream.) + +diff --git a/nptl/Makefile b/nptl/Makefile +index 071c53866d14d2fe..447dce0590295c9c 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -121,7 +121,7 @@ libpthread-routines = nptl-init nptlfreeres vars events version pt-interp \ + cancellation \ + lowlevellock \ + lll_timedlock_wait lll_timedwait_tid \ +- pt-fork pt-vfork pt-fcntl \ ++ pt-fork pt-fcntl \ + $(pthread-compat-wrappers) \ + pt-raise pt-system \ + flockfile ftrylockfile funlockfile \ +@@ -145,7 +145,8 @@ libpthread-routines = nptl-init nptlfreeres vars events version pt-interp \ + mtx_destroy mtx_init mtx_lock mtx_timedlock \ + mtx_trylock mtx_unlock call_once cnd_broadcast \ + cnd_destroy cnd_init cnd_signal cnd_timedwait cnd_wait \ +- tss_create tss_delete tss_get tss_set ++ tss_create tss_delete tss_get tss_set \ ++ libpthread-compat + # pthread_setuid pthread_seteuid pthread_setreuid \ + # pthread_setresuid \ + # pthread_setgid pthread_setegid pthread_setregid \ +diff --git a/nptl/Versions b/nptl/Versions +index e7f691da7a15e9c3..6007fd03e7ed117c 100644 +--- a/nptl/Versions ++++ b/nptl/Versions +@@ -36,7 +36,6 @@ libc { + __libc_alloca_cutoff; + # Internal libc interface to libpthread + __libc_dl_error_tsd; +- __libc_vfork; + __libc_pthread_init; + __libc_current_sigrtmin_private; __libc_current_sigrtmax_private; + __libc_allocate_rtsig_private; +@@ -98,7 +97,7 @@ libpthread { + sem_destroy; sem_getvalue; sem_init; sem_post; sem_trywait; sem_wait; + + # Special fork handling. +- fork; __fork; vfork; ++ fork; __fork; + + # Cancellation points. + close; __close; fcntl; __fcntl; read; __read; write; __write; accept; +@@ -152,7 +151,7 @@ libpthread { + } + + GLIBC_2.1.2 { +- __vfork; ++ __libpthread_version_placeholder; + } + + GLIBC_2.2 { +diff --git a/nptl/libpthread-compat.c b/nptl/libpthread-compat.c +new file mode 100644 +index 0000000000000000..ea29e9f47b698a25 +--- /dev/null ++++ b/nptl/libpthread-compat.c +@@ -0,0 +1,37 @@ ++/* Placeholder definitions to pull in removed symbol versions. ++ 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 ++ . */ ++ ++#include ++ ++/* This is an unused compatibility symbol definition, to prevent ld ++ from creating a weak version definition for GLIBC_2.1.2. (__vfork ++ used to be defined at that version, but it is now provided by libc, ++ and there are no versions left in libpthread for that symbol ++ version.) If the ABI baseline for glibc is the GLIBC_2.2 symbol ++ version or later, the placeholder symbol is not needed because ++ there are plenty of other symbols which populate those later ++ versions. */ ++#if (SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_2)) ++void ++attribute_compat_text_section ++__libpthread_version_placeholder (void) ++{ ++} ++compat_symbol (libpthread, __libpthread_version_placeholder, ++ __libpthread_version_placeholder, GLIBC_2_1_2); ++#endif +diff --git a/nptl/pt-vfork.c b/nptl/pt-vfork.c +deleted file mode 100644 +index 2f890d3f3070d0e2..0000000000000000 +--- a/nptl/pt-vfork.c ++++ /dev/null +@@ -1,65 +0,0 @@ +-/* vfork ABI-compatibility entry points for libpthread. +- Copyright (C) 2014-2018 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 +- . */ +- +-#include +-#include +- +-/* libpthread used to have its own vfork implementation that differed +- from libc's only in having a pointless micro-optimization. There +- is no longer any use to having a separate copy in libpthread, but +- the historical ABI requires it. For static linking, there is no +- need to provide anything here--the libc version will be linked in. +- For shared library ABI compatibility, there must be __vfork and +- vfork symbols in libpthread.so; so we define them using IFUNC to +- redirect to the libc function. */ +- +-/* Note! If the architecture doesn't support IFUNC, then we need an +- alternate target-specific mechanism to implement this. So we just +- assume IFUNC here and require that the target override this file +- if necessary. +- +- If the architecture can assume all supported versions of gcc will +- produce a tail-call to __libc_vfork, consider including the version +- in sysdeps/unix/sysv/linux/aarch64/pt-vfork.c. */ +- +-#if !HAVE_IFUNC +-# error "must write pt-vfork for this machine or get IFUNC support" +-#endif +- +-#if (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \ +- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)) +- +-extern __typeof (vfork) __libc_vfork; /* Defined in libc. */ +- +-# undef INIT_ARCH +-# define INIT_ARCH() +-# define DEFINE_VFORK(name) libc_ifunc (name, &__libc_vfork) +- +-#endif +- +-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) +-extern __typeof(vfork) vfork_ifunc; +-DEFINE_VFORK (vfork_ifunc) +-compat_symbol (libpthread, vfork_ifunc, vfork, GLIBC_2_0); +-#endif +- +-#if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20) +-extern __typeof(vfork) __vfork_ifunc; +-DEFINE_VFORK (__vfork_ifunc) +-compat_symbol (libpthread, __vfork_ifunc, __vfork, GLIBC_2_1_2); +-#endif +diff --git a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist +index 9a9e4cee85b18a35..6945b7cbe4c2bde8 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/aarch64/libpthread.abilist +@@ -45,7 +45,6 @@ GLIBC_2.17 __read F + GLIBC_2.17 __res_state F + GLIBC_2.17 __send F + GLIBC_2.17 __sigaction F +-GLIBC_2.17 __vfork F + GLIBC_2.17 __wait F + GLIBC_2.17 __write F + GLIBC_2.17 _pthread_cleanup_pop F +@@ -216,7 +215,6 @@ GLIBC_2.17 siglongjmp F + GLIBC_2.17 sigwait F + GLIBC_2.17 system F + GLIBC_2.17 tcdrain F +-GLIBC_2.17 vfork F + GLIBC_2.17 wait F + GLIBC_2.17 waitpid F + GLIBC_2.17 write F +diff --git a/sysdeps/unix/sysv/linux/aarch64/pt-vfork.c b/sysdeps/unix/sysv/linux/aarch64/pt-vfork.c +deleted file mode 100644 +index 2b277f25ec200be2..0000000000000000 +--- a/sysdeps/unix/sysv/linux/aarch64/pt-vfork.c ++++ /dev/null +@@ -1,54 +0,0 @@ +-/* vfork ABI-compatibility entry points for libpthread. +- Copyright (C) 2014-2018 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 +- . */ +- +-#include +- +-/* libpthread used to have its own vfork implementation that differed +- from libc's only in having a pointless micro-optimization. There +- is no longer any use to having a separate copy in libpthread, but +- the historical ABI requires it. For static linking, there is no +- need to provide anything here--the libc version will be linked in. +- For shared library ABI compatibility, there must be __vfork and +- vfork symbols in libpthread.so. */ +- +-#if HAVE_IFUNC +-# include +-#elif (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \ +- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)) +- +-/* Thankfully, on AArch64 we can rely on the compiler generating +- a tail call here. */ +- +-extern void __libc_vfork (void); +- +-void +-vfork_compat (void) +-{ +- __libc_vfork (); +-} +- +-# if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) +-compat_symbol (libpthread, vfork_compat, vfork, GLIBC_2_0); +-# endif +- +-# if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20) +-strong_alias (vfork_compat, vfork_compat2) +-compat_symbol (libpthread, vfork_compat2, __vfork, GLIBC_2_1_2); +-# endif +- +-#endif +diff --git a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist +index b413007ccbd2b7b3..2d9b958efa99feb8 100644 +--- a/sysdeps/unix/sysv/linux/alpha/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/alpha/libpthread.abilist +@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F + GLIBC_2.0 sigwait F + GLIBC_2.0 system F + GLIBC_2.0 tcdrain F +-GLIBC_2.0 vfork F + GLIBC_2.0 wait F + GLIBC_2.0 waitpid F + GLIBC_2.0 write F +@@ -155,7 +154,7 @@ GLIBC_2.1 sem_wait F + GLIBC_2.1.1 sem_close F + GLIBC_2.1.1 sem_open F + GLIBC_2.1.1 sem_unlink F +-GLIBC_2.1.2 __vfork F ++GLIBC_2.1.2 __libpthread_version_placeholder F + GLIBC_2.11 pthread_sigqueue F + GLIBC_2.12 pthread_getname_np F + GLIBC_2.12 pthread_mutex_consistent F +diff --git a/sysdeps/unix/sysv/linux/alpha/pt-vfork.S b/sysdeps/unix/sysv/linux/alpha/pt-vfork.S +deleted file mode 100644 +index 7ecaa78dd0eda2fe..0000000000000000 +--- a/sysdeps/unix/sysv/linux/alpha/pt-vfork.S ++++ /dev/null +@@ -1,43 +0,0 @@ +-/* vfork ABI-compatibility entry points for libpthread. +- Copyright (C) 2014-2018 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 +- . */ +- +-#include +- +-/* libpthread used to have its own vfork implementation that differed +- from libc's only in having a pointless micro-optimization. There +- is no longer any use to having a separate copy in libpthread, but +- the historical ABI requires it. For static linking, there is no +- need to provide anything here--the libc version will be linked in. +- For shared library ABI compatibility, there must be __vfork and +- vfork symbols in libpthread.so. */ +- +-#if (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \ +- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)) +- +-#include +- +-#endif +- +-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) +-compat_symbol (libpthread, __libc_vfork, vfork, GLIBC_2_0); +-#endif +- +-#if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20) +-strong_alias (__libc_vfork, __vfork_compat) +-compat_symbol (libpthread, __vfork_compat, __vfork, GLIBC_2_1_2); +-#endif +diff --git a/sysdeps/unix/sysv/linux/arm/libpthread.abilist b/sysdeps/unix/sysv/linux/arm/libpthread.abilist +index af82a4c632988185..ee3d0290d01f184e 100644 +--- a/sysdeps/unix/sysv/linux/arm/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/arm/libpthread.abilist +@@ -74,7 +74,6 @@ GLIBC_2.4 __read F + GLIBC_2.4 __res_state F + GLIBC_2.4 __send F + GLIBC_2.4 __sigaction F +-GLIBC_2.4 __vfork F + GLIBC_2.4 __wait F + GLIBC_2.4 __write F + GLIBC_2.4 _pthread_cleanup_pop F +@@ -239,7 +238,6 @@ GLIBC_2.4 siglongjmp F + GLIBC_2.4 sigwait F + GLIBC_2.4 system F + GLIBC_2.4 tcdrain F +-GLIBC_2.4 vfork F + GLIBC_2.4 wait F + GLIBC_2.4 waitpid F + GLIBC_2.4 write F +diff --git a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist +index bcba07f57558174f..e9b3be6ac8e8f367 100644 +--- a/sysdeps/unix/sysv/linux/hppa/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/hppa/libpthread.abilist +@@ -46,7 +46,6 @@ GLIBC_2.2 __read F + GLIBC_2.2 __res_state F + GLIBC_2.2 __send F + GLIBC_2.2 __sigaction F +-GLIBC_2.2 __vfork F + GLIBC_2.2 __wait F + GLIBC_2.2 __write F + GLIBC_2.2 _pthread_cleanup_pop F +@@ -192,7 +191,6 @@ GLIBC_2.2 siglongjmp F + GLIBC_2.2 sigwait F + GLIBC_2.2 system F + GLIBC_2.2 tcdrain F +-GLIBC_2.2 vfork F + GLIBC_2.2 wait F + GLIBC_2.2 waitpid F + GLIBC_2.2 write F +diff --git a/sysdeps/unix/sysv/linux/hppa/localplt.data b/sysdeps/unix/sysv/linux/hppa/localplt.data +index 5f3475de191778f6..867413f0c54d3d71 100644 +--- a/sysdeps/unix/sysv/linux/hppa/localplt.data ++++ b/sysdeps/unix/sysv/linux/hppa/localplt.data +@@ -10,7 +10,6 @@ libc.so: __sigsetjmp + libc.so: _IO_funlockfile + libc.so: __errno_location + libm.so: matherr +-libpthread.so: __errno_location + # The main malloc is interposed into the dynamic linker, for + # allocations after the initial link (when dlopen is used). + ld.so: malloc +diff --git a/sysdeps/unix/sysv/linux/hppa/pt-vfork.S b/sysdeps/unix/sysv/linux/hppa/pt-vfork.S +deleted file mode 100644 +index 45f7620d90cb5b8f..0000000000000000 +--- a/sysdeps/unix/sysv/linux/hppa/pt-vfork.S ++++ /dev/null +@@ -1,82 +0,0 @@ +-/* Copyright (C) 2005-2018 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 +- . */ +- +-#include +-#define _ERRNO_H 1 +-#include +-#include +- +-/* Clone the calling process, but without copying the whole address space. +- The calling process is suspended until the new process exits or is +- replaced by a call to `execve'. Return -1 for errors, 0 to the new process, +- and the process ID of the new process to the old process. */ +- +-.Lthread_start: ASM_LINE_SEP +- +- /* r26, r25, r24, r23 are free since vfork has no arguments */ +-ENTRY(__vfork) +- /* We must not create a frame. When the child unwinds to call +- exec it will clobber the same frame that the parent +- needs to unwind. */ +- +- /* Save the PIC register. */ +-#ifdef PIC +- copy %r19, %r25 /* parent */ +-#endif +- +- /* Syscall saves and restores all register states */ +- ble 0x100(%sr2,%r0) +- ldi __NR_vfork,%r20 +- +- /* Check for error */ +- ldi -4096,%r1 +- comclr,>>= %r1,%ret0,%r0 /* Note: unsigned compare. */ +- b,n .Lerror +- +- /* Return, and DO NOT restore rp. The child may have called +- functions that updated the frame's rp. This works because +- the kernel ensures rp is preserved across the vfork +- syscall. */ +- bv,n %r0(%rp) +- +-.Lerror: +- /* Now we need a stack to call a function. We are assured +- that there is no child now, so it's safe to create +- a frame. */ +- stw %rp, -20(%sp) +- .cfi_offset 2, -20 +- stwm %r3, 64(%sp) +- .cfi_def_cfa_offset -64 +- .cfi_offset 3, 0 +- stw %sp, -4(%sp) +- +- sub %r0,%ret0,%r3 +- SYSCALL_ERROR_HANDLER +- /* Restore the PIC register (in delay slot) on error */ +-#ifdef PIC +- copy %r25, %r19 /* parent */ +-#else +- nop +-#endif +- /* Write syscall return into errno location */ +- stw %r3, 0(%ret0) +- ldw -84(%sp), %rp +- bv %r0(%rp) +- ldwm -64(%sp), %r3 +-PSEUDO_END (__vfork) +-libc_hidden_def (__vfork) +-weak_alias (__vfork, vfork) +diff --git a/sysdeps/unix/sysv/linux/i386/libpthread.abilist b/sysdeps/unix/sysv/linux/i386/libpthread.abilist +index bece86d24624ea26..7199aae573649f49 100644 +--- a/sysdeps/unix/sysv/linux/i386/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/i386/libpthread.abilist +@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F + GLIBC_2.0 sigwait F + GLIBC_2.0 system F + GLIBC_2.0 tcdrain F +-GLIBC_2.0 vfork F + GLIBC_2.0 wait F + GLIBC_2.0 waitpid F + GLIBC_2.0 write F +@@ -155,7 +154,7 @@ GLIBC_2.1 sem_wait F + GLIBC_2.1.1 sem_close F + GLIBC_2.1.1 sem_open F + GLIBC_2.1.1 sem_unlink F +-GLIBC_2.1.2 __vfork F ++GLIBC_2.1.2 __libpthread_version_placeholder F + GLIBC_2.11 pthread_sigqueue F + GLIBC_2.12 pthread_getname_np F + GLIBC_2.12 pthread_mutex_consistent F +diff --git a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist +index ccc94498268a5c74..e8a65642caec7ff1 100644 +--- a/sysdeps/unix/sysv/linux/ia64/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/ia64/libpthread.abilist +@@ -46,7 +46,6 @@ GLIBC_2.2 __read F + GLIBC_2.2 __res_state F + GLIBC_2.2 __send F + GLIBC_2.2 __sigaction F +-GLIBC_2.2 __vfork F + GLIBC_2.2 __wait F + GLIBC_2.2 __write F + GLIBC_2.2 _pthread_cleanup_pop F +@@ -192,7 +191,6 @@ GLIBC_2.2 siglongjmp F + GLIBC_2.2 sigwait F + GLIBC_2.2 system F + GLIBC_2.2 tcdrain F +-GLIBC_2.2 vfork F + GLIBC_2.2 wait F + GLIBC_2.2 waitpid F + GLIBC_2.2 write F +diff --git a/sysdeps/unix/sysv/linux/ia64/pt-vfork.S b/sysdeps/unix/sysv/linux/ia64/pt-vfork.S +deleted file mode 100644 +index 61f3e387b455d731..0000000000000000 +--- a/sysdeps/unix/sysv/linux/ia64/pt-vfork.S ++++ /dev/null +@@ -1,48 +0,0 @@ +-/* vfork ABI-compatibility entry points for libpthread. IA64 version. +- Copyright (C) 2014-2018 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 +- . */ +- +-#include +-#include +- +-/* libpthread used to have its own vfork implementation that differed +- from libc's only in having a pointless micro-optimization. There +- is no longer any use to having a separate copy in libpthread, but +- the historical ABI requires it. For static linking, there is no +- need to provide anything here--the libc version will be linked in. +- For shared library ABI compatibility, there must be __vfork and +- vfork symbols in libpthread.so. */ +- +-#if (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \ +- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)) +- +-LOCAL_LEAF (vfork_compat) +- br __libc_vfork +- ;; +-END (vfork_compat) +- +-#endif +- +-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) +-weak_alias (vfork_compat, vfork) +-compat_symbol (libpthread, vfork_compat, vfork, GLIBC_2_0); +-#endif +- +-#if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20) +-strong_alias (vfork_compat, __vfork_compat) +-compat_symbol (libpthread, __vfork_compat, __vfork, GLIBC_2_1_2); +-#endif +diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist +index af82a4c632988185..ee3d0290d01f184e 100644 +--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libpthread.abilist +@@ -74,7 +74,6 @@ GLIBC_2.4 __read F + GLIBC_2.4 __res_state F + GLIBC_2.4 __send F + GLIBC_2.4 __sigaction F +-GLIBC_2.4 __vfork F + GLIBC_2.4 __wait F + GLIBC_2.4 __write F + GLIBC_2.4 _pthread_cleanup_pop F +@@ -239,7 +238,6 @@ GLIBC_2.4 siglongjmp F + GLIBC_2.4 sigwait F + GLIBC_2.4 system F + GLIBC_2.4 tcdrain F +-GLIBC_2.4 vfork F + GLIBC_2.4 wait F + GLIBC_2.4 waitpid F + GLIBC_2.4 write F +diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist +index bece86d24624ea26..7199aae573649f49 100644 +--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libpthread.abilist +@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F + GLIBC_2.0 sigwait F + GLIBC_2.0 system F + GLIBC_2.0 tcdrain F +-GLIBC_2.0 vfork F + GLIBC_2.0 wait F + GLIBC_2.0 waitpid F + GLIBC_2.0 write F +@@ -155,7 +154,7 @@ GLIBC_2.1 sem_wait F + GLIBC_2.1.1 sem_close F + GLIBC_2.1.1 sem_open F + GLIBC_2.1.1 sem_unlink F +-GLIBC_2.1.2 __vfork F ++GLIBC_2.1.2 __libpthread_version_placeholder F + GLIBC_2.11 pthread_sigqueue F + GLIBC_2.12 pthread_getname_np F + GLIBC_2.12 pthread_mutex_consistent F +diff --git a/sysdeps/unix/sysv/linux/m68k/pt-vfork.c b/sysdeps/unix/sysv/linux/m68k/pt-vfork.c +deleted file mode 100644 +index 5fbc6526aa2af493..0000000000000000 +--- a/sysdeps/unix/sysv/linux/m68k/pt-vfork.c ++++ /dev/null +@@ -1 +0,0 @@ +-#include +diff --git a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist +index 5067375d237a0c9f..e0fbe6848f7945bd 100644 +--- a/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/microblaze/libpthread.abilist +@@ -45,7 +45,6 @@ GLIBC_2.18 __read F + GLIBC_2.18 __res_state F + GLIBC_2.18 __send F + GLIBC_2.18 __sigaction F +-GLIBC_2.18 __vfork F + GLIBC_2.18 __wait F + GLIBC_2.18 __write F + GLIBC_2.18 _pthread_cleanup_pop F +@@ -218,7 +217,6 @@ GLIBC_2.18 siglongjmp F + GLIBC_2.18 sigwait F + GLIBC_2.18 system F + GLIBC_2.18 tcdrain F +-GLIBC_2.18 vfork F + GLIBC_2.18 wait F + GLIBC_2.18 waitpid F + GLIBC_2.18 write F +diff --git a/sysdeps/unix/sysv/linux/microblaze/pt-vfork.S b/sysdeps/unix/sysv/linux/microblaze/pt-vfork.S +deleted file mode 100644 +index 74bc1cdf7455f597..0000000000000000 +--- a/sysdeps/unix/sysv/linux/microblaze/pt-vfork.S ++++ /dev/null +@@ -1,49 +0,0 @@ +-/* vfork ABI-compatibility entry points for libpthread. +- Copyright (C) 2014-2018 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 +- . */ +- +-#include +-#include +- +-/* libpthread used to have its own vfork implementation that differed +- from libc's only in having a pointless micro-optimization. There +- is no longer any use to having a separate copy in libpthread, but +- the historical ABI requires it. For static linking, there is no +- need to provide anything here--the libc version will be linked in. +- For shared library ABI compatibility, there must be __vfork and +- vfork symbols in libpthread.so. +- +- As of GCC 7, microblaze can *not* rely on the compiler to generate +- a tail call from this vfork to __libc_vfork. */ +- +-#if (SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) \ +- || SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20)) +- +-ENTRY (vfork_compat) +- bri __libc_vfork@PLT +-END (vfork_compat) +- +-#endif +- +-#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_20) +-compat_symbol (libpthread, vfork_compat, vfork, GLIBC_2_0) +-#endif +- +-#if SHLIB_COMPAT (libpthread, GLIBC_2_1_2, GLIBC_2_20) +-strong_alias (vfork_compat, vfork_compat2) +-compat_symbol (libpthread, vfork_compat2, __vfork, GLIBC_2_1_2) +-#endif +diff --git a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist +index 02144967c638cdbe..f60b22efb5b5f683 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips32/libpthread.abilist +@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F + GLIBC_2.0 sigwait F + GLIBC_2.0 system F + GLIBC_2.0 tcdrain F +-GLIBC_2.0 vfork F + GLIBC_2.0 wait F + GLIBC_2.0 waitpid F + GLIBC_2.0 write F +@@ -140,7 +139,6 @@ GLIBC_2.2 __pthread_rwlock_unlock F + GLIBC_2.2 __pthread_rwlock_wrlock F + GLIBC_2.2 __pwrite64 F + GLIBC_2.2 __res_state F +-GLIBC_2.2 __vfork F + GLIBC_2.2 lseek64 F + GLIBC_2.2 open64 F + GLIBC_2.2 pread F +diff --git a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist +index 02144967c638cdbe..f60b22efb5b5f683 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips64/libpthread.abilist +@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F + GLIBC_2.0 sigwait F + GLIBC_2.0 system F + GLIBC_2.0 tcdrain F +-GLIBC_2.0 vfork F + GLIBC_2.0 wait F + GLIBC_2.0 waitpid F + GLIBC_2.0 write F +@@ -140,7 +139,6 @@ GLIBC_2.2 __pthread_rwlock_unlock F + GLIBC_2.2 __pthread_rwlock_wrlock F + GLIBC_2.2 __pwrite64 F + GLIBC_2.2 __res_state F +-GLIBC_2.2 __vfork F + GLIBC_2.2 lseek64 F + GLIBC_2.2 open64 F + GLIBC_2.2 pread F +diff --git a/sysdeps/unix/sysv/linux/mips/pt-vfork.S b/sysdeps/unix/sysv/linux/mips/pt-vfork.S +deleted file mode 100644 +index 65cc3823ac872b35..0000000000000000 +--- a/sysdeps/unix/sysv/linux/mips/pt-vfork.S ++++ /dev/null +@@ -1 +0,0 @@ +-#include +diff --git a/sysdeps/unix/sysv/linux/nios2/pt-vfork.S b/sysdeps/unix/sysv/linux/nios2/pt-vfork.S +deleted file mode 100644 +index 147427a42d2d74a7..0000000000000000 +--- a/sysdeps/unix/sysv/linux/nios2/pt-vfork.S ++++ /dev/null +@@ -1 +0,0 @@ +-# Nios2 does not require a stub for vfork in libpthread. +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist +index 09e8447b06f828be..c7d9b7898640730d 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/libpthread.abilist +@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F + GLIBC_2.0 sigwait F + GLIBC_2.0 system F + GLIBC_2.0 tcdrain F +-GLIBC_2.0 vfork F + GLIBC_2.0 wait F + GLIBC_2.0 waitpid F + GLIBC_2.0 write F +@@ -155,7 +154,7 @@ GLIBC_2.1 sem_wait F + GLIBC_2.1.1 sem_close F + GLIBC_2.1.1 sem_open F + GLIBC_2.1.1 sem_unlink F +-GLIBC_2.1.2 __vfork F ++GLIBC_2.1.2 __libpthread_version_placeholder F + GLIBC_2.11 pthread_sigqueue F + GLIBC_2.12 pthread_getname_np F + GLIBC_2.12 pthread_mutex_consistent F +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread-le.abilist +index 9a9e4cee85b18a35..6945b7cbe4c2bde8 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread-le.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread-le.abilist +@@ -45,7 +45,6 @@ GLIBC_2.17 __read F + GLIBC_2.17 __res_state F + GLIBC_2.17 __send F + GLIBC_2.17 __sigaction F +-GLIBC_2.17 __vfork F + GLIBC_2.17 __wait F + GLIBC_2.17 __write F + GLIBC_2.17 _pthread_cleanup_pop F +@@ -216,7 +215,6 @@ GLIBC_2.17 siglongjmp F + GLIBC_2.17 sigwait F + GLIBC_2.17 system F + GLIBC_2.17 tcdrain F +-GLIBC_2.17 vfork F + GLIBC_2.17 wait F + GLIBC_2.17 waitpid F + GLIBC_2.17 write F +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread.abilist +index 8300958d4721d6a6..3500cce6c1124996 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libpthread.abilist +@@ -68,7 +68,6 @@ GLIBC_2.3 __read F + GLIBC_2.3 __res_state F + GLIBC_2.3 __send F + GLIBC_2.3 __sigaction F +-GLIBC_2.3 __vfork F + GLIBC_2.3 __wait F + GLIBC_2.3 __write F + GLIBC_2.3 _pthread_cleanup_pop F +@@ -214,7 +213,6 @@ GLIBC_2.3 siglongjmp F + GLIBC_2.3 sigwait F + GLIBC_2.3 system F + GLIBC_2.3 tcdrain F +-GLIBC_2.3 vfork F + GLIBC_2.3 wait F + GLIBC_2.3 waitpid F + GLIBC_2.3 write F +diff --git a/sysdeps/unix/sysv/linux/riscv/pt-vfork.S b/sysdeps/unix/sysv/linux/riscv/pt-vfork.S +deleted file mode 100644 +index 1cc8931700702e65..0000000000000000 +--- a/sysdeps/unix/sysv/linux/riscv/pt-vfork.S ++++ /dev/null +@@ -1 +0,0 @@ +-/* Not needed. */ +diff --git a/sysdeps/unix/sysv/linux/s390/pt-vfork.S b/sysdeps/unix/sysv/linux/s390/pt-vfork.S +deleted file mode 100644 +index 65cc3823ac872b35..0000000000000000 +--- a/sysdeps/unix/sysv/linux/s390/pt-vfork.S ++++ /dev/null +@@ -1 +0,0 @@ +-#include +diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist +index d05468f3b2732e92..f093634d7edce2f2 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/s390/s390-32/libpthread.abilist +@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F + GLIBC_2.0 sigwait F + GLIBC_2.0 system F + GLIBC_2.0 tcdrain F +-GLIBC_2.0 vfork F + GLIBC_2.0 wait F + GLIBC_2.0 waitpid F + GLIBC_2.0 write F +@@ -155,7 +154,7 @@ GLIBC_2.1 sem_wait F + GLIBC_2.1.1 sem_close F + GLIBC_2.1.1 sem_open F + GLIBC_2.1.1 sem_unlink F +-GLIBC_2.1.2 __vfork F ++GLIBC_2.1.2 __libpthread_version_placeholder F + GLIBC_2.11 pthread_sigqueue F + GLIBC_2.12 pthread_getname_np F + GLIBC_2.12 pthread_mutex_consistent F +diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist +index e8161aa747402b72..47204f166c29a773 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/s390/s390-64/libpthread.abilist +@@ -48,7 +48,6 @@ GLIBC_2.2 __read F + GLIBC_2.2 __res_state F + GLIBC_2.2 __send F + GLIBC_2.2 __sigaction F +-GLIBC_2.2 __vfork F + GLIBC_2.2 __wait F + GLIBC_2.2 __write F + GLIBC_2.2 _pthread_cleanup_pop F +@@ -194,7 +193,6 @@ GLIBC_2.2 siglongjmp F + GLIBC_2.2 sigwait F + GLIBC_2.2 system F + GLIBC_2.2 tcdrain F +-GLIBC_2.2 vfork F + GLIBC_2.2 wait F + GLIBC_2.2 waitpid F + GLIBC_2.2 write F +diff --git a/sysdeps/unix/sysv/linux/sh/libpthread.abilist b/sysdeps/unix/sysv/linux/sh/libpthread.abilist +index bcba07f57558174f..e9b3be6ac8e8f367 100644 +--- a/sysdeps/unix/sysv/linux/sh/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/sh/libpthread.abilist +@@ -46,7 +46,6 @@ GLIBC_2.2 __read F + GLIBC_2.2 __res_state F + GLIBC_2.2 __send F + GLIBC_2.2 __sigaction F +-GLIBC_2.2 __vfork F + GLIBC_2.2 __wait F + GLIBC_2.2 __write F + GLIBC_2.2 _pthread_cleanup_pop F +@@ -192,7 +191,6 @@ GLIBC_2.2 siglongjmp F + GLIBC_2.2 sigwait F + GLIBC_2.2 system F + GLIBC_2.2 tcdrain F +-GLIBC_2.2 vfork F + GLIBC_2.2 wait F + GLIBC_2.2 waitpid F + GLIBC_2.2 write F +diff --git a/sysdeps/unix/sysv/linux/sh/pt-vfork.S b/sysdeps/unix/sysv/linux/sh/pt-vfork.S +deleted file mode 100644 +index 65cc3823ac872b35..0000000000000000 +--- a/sysdeps/unix/sysv/linux/sh/pt-vfork.S ++++ /dev/null +@@ -1 +0,0 @@ +-#include +diff --git a/sysdeps/unix/sysv/linux/sparc/pt-vfork.S b/sysdeps/unix/sysv/linux/sparc/pt-vfork.S +deleted file mode 100644 +index 65cc3823ac872b35..0000000000000000 +--- a/sysdeps/unix/sysv/linux/sparc/pt-vfork.S ++++ /dev/null +@@ -1 +0,0 @@ +-#include +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist +index b413007ccbd2b7b3..2d9b958efa99feb8 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libpthread.abilist +@@ -114,7 +114,6 @@ GLIBC_2.0 siglongjmp F + GLIBC_2.0 sigwait F + GLIBC_2.0 system F + GLIBC_2.0 tcdrain F +-GLIBC_2.0 vfork F + GLIBC_2.0 wait F + GLIBC_2.0 waitpid F + GLIBC_2.0 write F +@@ -155,7 +154,7 @@ GLIBC_2.1 sem_wait F + GLIBC_2.1.1 sem_close F + GLIBC_2.1.1 sem_open F + GLIBC_2.1.1 sem_unlink F +-GLIBC_2.1.2 __vfork F ++GLIBC_2.1.2 __libpthread_version_placeholder F + GLIBC_2.11 pthread_sigqueue F + GLIBC_2.12 pthread_getname_np F + GLIBC_2.12 pthread_mutex_consistent F +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist +index ccc94498268a5c74..e8a65642caec7ff1 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libpthread.abilist +@@ -46,7 +46,6 @@ GLIBC_2.2 __read F + GLIBC_2.2 __res_state F + GLIBC_2.2 __send F + GLIBC_2.2 __sigaction F +-GLIBC_2.2 __vfork F + GLIBC_2.2 __wait F + GLIBC_2.2 __write F + GLIBC_2.2 _pthread_cleanup_pop F +@@ -192,7 +191,6 @@ GLIBC_2.2 siglongjmp F + GLIBC_2.2 sigwait F + GLIBC_2.2 system F + GLIBC_2.2 tcdrain F +-GLIBC_2.2 vfork F + GLIBC_2.2 wait F + GLIBC_2.2 waitpid F + GLIBC_2.2 write F +diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist +index 931c8277a859999e..4fbb72ffb37ba689 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist +@@ -46,7 +46,6 @@ GLIBC_2.2.5 __read F + GLIBC_2.2.5 __res_state F + GLIBC_2.2.5 __send F + GLIBC_2.2.5 __sigaction F +-GLIBC_2.2.5 __vfork F + GLIBC_2.2.5 __wait F + GLIBC_2.2.5 __write F + GLIBC_2.2.5 _pthread_cleanup_pop F +@@ -193,7 +192,6 @@ GLIBC_2.2.5 siglongjmp F + GLIBC_2.2.5 sigwait F + GLIBC_2.2.5 system F + GLIBC_2.2.5 tcdrain F +-GLIBC_2.2.5 vfork F + GLIBC_2.2.5 wait F + GLIBC_2.2.5 waitpid F + GLIBC_2.2.5 write F +diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist +index c09c9b015a66f8f9..eec4b99b8bb69d74 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/x32/libpthread.abilist +@@ -45,7 +45,6 @@ GLIBC_2.16 __read F + GLIBC_2.16 __res_state F + GLIBC_2.16 __send F + GLIBC_2.16 __sigaction F +-GLIBC_2.16 __vfork F + GLIBC_2.16 __wait F + GLIBC_2.16 __write F + GLIBC_2.16 _pthread_cleanup_pop F +@@ -216,7 +215,6 @@ GLIBC_2.16 siglongjmp F + GLIBC_2.16 sigwait F + GLIBC_2.16 system F + GLIBC_2.16 tcdrain F +-GLIBC_2.16 vfork F + GLIBC_2.16 wait F + GLIBC_2.16 waitpid F + GLIBC_2.16 write F diff --git a/glibc-rh1748197-3.patch b/glibc-rh1748197-3.patch new file mode 100755 index 0000000..dbc4b09 --- /dev/null +++ b/glibc-rh1748197-3.patch @@ -0,0 +1,51 @@ +commit f289e656ec8221756519a601042bc9fbe1b310fb +Author: Florian Weimer +Date: Fri Feb 8 10:21:56 2019 +0100 + + rt: Turn forwards from librt to libc into compat symbols [BZ #24194] + + As the result of commit 6e6249d0b461b952d0f544792372663feb6d792a + ("BZ#14743: Move clock_* symbols from librt to libc."), in glibc 2.17, + clock_gettime, clock_getres, clock_settime, clock_getcpuclockid, + clock_nanosleep were added to libc, and the file rt/clock-compat.c + was added with forwarders to the actual implementations in libc. + These forwarders were wrapped in + + #if SHLIB_COMPAT (librt, GLIBC_2_2, GLIBC_2_17) + + so that they are not present for newer architectures (such as + powerpc64le) with a 2.17 or later ABI baseline. But the forwarders + were not marked as compatibility symbols. As a result, on older + architectures, historic configure checks such as + + AC_CHECK_LIB(rt, clock_gettime) + + still cause linking against librt, even though this is completely + unnecessary. It also creates a needless porting hazard because + architectures behave differently when it comes to symbol availability. + + Reviewed-by: Carlos O'Donell + +diff --git a/rt/clock-compat.c b/rt/clock-compat.c +index f816973c05c29d5d..11e71aa89019b173 100644 +--- a/rt/clock-compat.c ++++ b/rt/clock-compat.c +@@ -30,14 +30,16 @@ + #if HAVE_IFUNC + # undef INIT_ARCH + # define INIT_ARCH() +-# define COMPAT_REDIRECT(name, proto, arglist) libc_ifunc (name, &__##name) ++# define COMPAT_REDIRECT(name, proto, arglist) libc_ifunc (name, &__##name) \ ++ compat_symbol (librt, name, name, GLIBC_2_2); + #else + # define COMPAT_REDIRECT(name, proto, arglist) \ + int \ + name proto \ + { \ + return __##name arglist; \ +- } ++ } \ ++ compat_symbol (librt, name, name, GLIBC_2_2); + #endif + + COMPAT_REDIRECT (clock_getres, diff --git a/glibc-rh1748197-4.patch b/glibc-rh1748197-4.patch new file mode 100755 index 0000000..795f673 --- /dev/null +++ b/glibc-rh1748197-4.patch @@ -0,0 +1,256 @@ +commit b06f4c0094d3c68be39ada0ed26ae99d51f48013 +Author: Wilco Dijkstra +Date: Fri Feb 1 12:19:42 2019 +0000 + + Cleanup clock_*time includes + + Clock_gettime, settime and getres implementations are unncessarily + complex due to using defines and C file inclusion. Simplify the + code by replacing the redundant defines and removing the inclusion, + making it much easier to understand. No functional changes. + + * sysdeps/posix/clock_getres.c (__clock_getres): Cleanup. + * sysdeps/unix/clock_gettime.c (__clock_gettime): Cleanup. + * sysdeps/unix/clock_settime.c (__clock_settime): Cleanup. + * sysdeps/unix/sysv/linux/clock_getres.c (__clock_getres): Cleanup. + * sysdeps/unix/sysv/linux/clock_gettime.c (__clock_gettime): Cleanup. + * sysdeps/unix/sysv/linux/clock_settime.c (__clock_settime): Cleanup. + +diff --git a/sysdeps/posix/clock_getres.c b/sysdeps/posix/clock_getres.c +index e7924e0891b0a476..43228c381e6a73f1 100644 +--- a/sysdeps/posix/clock_getres.c ++++ b/sysdeps/posix/clock_getres.c +@@ -82,20 +82,11 @@ __clock_getres (clockid_t clock_id, struct timespec *res) + + switch (clock_id) + { +-#ifdef SYSDEP_GETRES +- SYSDEP_GETRES; +-#endif +- +-#ifndef HANDLED_REALTIME + case CLOCK_REALTIME: + retval = realtime_getres (res); + break; +-#endif /* handled REALTIME */ + + default: +-#ifdef SYSDEP_GETRES_CPU +- SYSDEP_GETRES_CPU; +-#endif + #if HP_TIMING_AVAIL + if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1)) + == CLOCK_THREAD_CPUTIME_ID) +@@ -105,7 +96,7 @@ __clock_getres (clockid_t clock_id, struct timespec *res) + __set_errno (EINVAL); + break; + +-#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME ++#if HP_TIMING_AVAIL + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_THREAD_CPUTIME_ID: + retval = hp_timing_getres (res); +diff --git a/sysdeps/unix/clock_gettime.c b/sysdeps/unix/clock_gettime.c +index 96df78ab1ed09c04..f19fdf7e5f310973 100644 +--- a/sysdeps/unix/clock_gettime.c ++++ b/sysdeps/unix/clock_gettime.c +@@ -95,11 +95,6 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp) + + switch (clock_id) + { +-#ifdef SYSDEP_GETTIME +- SYSDEP_GETTIME; +-#endif +- +-#ifndef HANDLED_REALTIME + case CLOCK_REALTIME: + { + struct timeval tv; +@@ -108,12 +103,8 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp) + TIMEVAL_TO_TIMESPEC (&tv, tp); + } + break; +-#endif + + default: +-#ifdef SYSDEP_GETTIME_CPU +- SYSDEP_GETTIME_CPU (clock_id, tp); +-#endif + #if HP_TIMING_AVAIL + if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1)) + == CLOCK_THREAD_CPUTIME_ID) +@@ -123,7 +114,7 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp) + __set_errno (EINVAL); + break; + +-#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME ++#if HP_TIMING_AVAIL + case CLOCK_PROCESS_CPUTIME_ID: + retval = hp_timing_gettime (clock_id, tp); + break; +diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/unix/clock_settime.c +index 38813eddf7b66ca1..9d5857e61b966b44 100644 +--- a/sysdeps/unix/clock_settime.c ++++ b/sysdeps/unix/clock_settime.c +@@ -21,7 +21,7 @@ + #include + + +-#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME ++#if HP_TIMING_AVAIL + /* Clock frequency of the processor. We make it a 64-bit variable + because some jokers are already playing with processors with more + than 4GHz. */ +@@ -84,29 +84,15 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp) + + switch (clock_id) + { +-#define HANDLE_REALTIME \ +- do { \ +- struct timeval tv; \ +- TIMESPEC_TO_TIMEVAL (&tv, tp); \ +- \ +- retval = __settimeofday (&tv, NULL); \ +- } while (0) +- +-#ifdef SYSDEP_SETTIME +- SYSDEP_SETTIME; +-#endif +- +-#ifndef HANDLED_REALTIME + case CLOCK_REALTIME: +- HANDLE_REALTIME; ++ { ++ struct timeval tv; ++ TIMESPEC_TO_TIMEVAL (&tv, tp); ++ retval = __settimeofday (&tv, NULL); ++ } + break; +-#endif + + default: +-#ifdef SYSDEP_SETTIME_CPU +- SYSDEP_SETTIME_CPU; +-#endif +-#ifndef HANDLED_CPUTIME + # if HP_TIMING_AVAIL + if (CPUCLOCK_WHICH (clock_id) == CLOCK_PROCESS_CPUTIME_ID + || CPUCLOCK_WHICH (clock_id) == CLOCK_THREAD_CPUTIME_ID) +@@ -117,7 +103,6 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp) + __set_errno (EINVAL); + retval = -1; + } +-#endif + break; + } + +diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c +index 5d94f59afee80fa9..2517e66910a79d93 100644 +--- a/sysdeps/unix/sysv/linux/clock_getres.c ++++ b/sysdeps/unix/sysv/linux/clock_getres.c +@@ -26,26 +26,10 @@ + #endif + #include + +-#define SYSCALL_GETRES \ +- retval = INLINE_VSYSCALL (clock_getres, 2, clock_id, res); \ +- break +- +-/* The REALTIME and MONOTONIC clock are definitely supported in the +- kernel. */ +-#define SYSDEP_GETRES \ +- SYSDEP_GETRES_CPUTIME \ +- case CLOCK_REALTIME: \ +- case CLOCK_MONOTONIC: \ +- case CLOCK_MONOTONIC_RAW: \ +- case CLOCK_REALTIME_COARSE: \ +- case CLOCK_MONOTONIC_COARSE: \ +- SYSCALL_GETRES +- +-/* We handled the REALTIME clock here. */ +-#define HANDLED_REALTIME 1 +-#define HANDLED_CPUTIME 1 +- +-#define SYSDEP_GETRES_CPU SYSCALL_GETRES +-#define SYSDEP_GETRES_CPUTIME /* Default catches them too. */ +- +-#include ++/* Get resolution of clock. */ ++int ++__clock_getres (clockid_t clock_id, struct timespec *res) ++{ ++ return INLINE_VSYSCALL (clock_getres, 2, clock_id, res); ++} ++weak_alias (__clock_getres, clock_getres) +diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c +index d837fa36b1b901e5..dadfc518b74baea0 100644 +--- a/sysdeps/unix/sysv/linux/clock_gettime.c ++++ b/sysdeps/unix/sysv/linux/clock_gettime.c +@@ -26,22 +26,11 @@ + #endif + #include + +-/* The REALTIME and MONOTONIC clock are definitely supported in the +- kernel. */ +-#define SYSDEP_GETTIME \ +- SYSDEP_GETTIME_CPUTIME; \ +- case CLOCK_REALTIME: \ +- case CLOCK_MONOTONIC: \ +- retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); \ +- break +- +-/* We handled the REALTIME clock here. */ +-#define HANDLED_REALTIME 1 +-#define HANDLED_CPUTIME 1 +- +-#define SYSDEP_GETTIME_CPU(clock_id, tp) \ +- retval = INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); \ +- break +-#define SYSDEP_GETTIME_CPUTIME /* Default catches them too. */ +- +-#include ++/* Get current value of CLOCK and store it in TP. */ ++int ++__clock_gettime (clockid_t clock_id, struct timespec *tp) ++{ ++ return INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); ++} ++weak_alias (__clock_gettime, clock_gettime) ++libc_hidden_def (__clock_gettime) +diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c +index 5f3f22f74b3e745c..c71461a4f6deac5a 100644 +--- a/sysdeps/unix/sysv/linux/clock_settime.c ++++ b/sysdeps/unix/sysv/linux/clock_settime.c +@@ -21,18 +21,17 @@ + + #include "kernel-posix-cpu-timers.h" + +- +-/* The REALTIME clock is definitely supported in the kernel. */ +-#define SYSDEP_SETTIME \ +- case CLOCK_REALTIME: \ +- retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp); \ +- break +- +-/* We handled the REALTIME clock here. */ +-#define HANDLED_REALTIME 1 +- +-#define HANDLED_CPUTIME 1 +-#define SYSDEP_SETTIME_CPU \ +- retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp) +- +-#include ++/* Set CLOCK to value TP. */ ++int ++__clock_settime (clockid_t clock_id, const struct timespec *tp) ++{ ++ /* Make sure the time cvalue is OK. */ ++ if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000) ++ { ++ __set_errno (EINVAL); ++ return -1; ++ } ++ ++ return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp); ++} ++weak_alias (__clock_settime, clock_settime) diff --git a/glibc-rh1748197-5.patch b/glibc-rh1748197-5.patch new file mode 100755 index 0000000..4a98157 --- /dev/null +++ b/glibc-rh1748197-5.patch @@ -0,0 +1,735 @@ +commit 38cc11daa43b11b12a7774405accee1007de1adf +Author: Adhemerval Zanella +Date: Wed Jan 16 16:22:29 2019 +0000 + + nptl: Remove pthread_clock_gettime pthread_clock_settime + + This patch removes CLOCK_THREAD_CPUTIME_ID and CLOCK_PROCESS_CPUTIME_ID support + from clock_gettime and clock_settime generic implementation. For Linux, kernel + already provides supports through the syscall and Hurd HTL lacks + __pthread_clock_gettime and __pthread_clock_settime internal implementation. + + As described in clock_gettime man-page [1] on 'Historical note for SMP + system', implementing CLOCK_{THREAD,PROCESS}_CPUTIME_ID with timer registers + is error-prone and susceptible to timing and accurary issues that the libc + can not deal without kernel support. + + This allows removes unused code which, however, still incur in some runtime + overhead in thread creation (the struct pthread cpuclock_offset + initialization). + + If hurd eventually wants to support them it should either either implement as + a kernel facility (or something related due its architecture) or in system + specific implementation. + + Checked on aarch64-linux-gnu, x86_64-linux-gnu, and i686-linux-gnu. I also + checked on a i686-gnu build. + + * nptl/Makefile (libpthread-routines): Remove pthread_clock_gettime and + pthread_clock_settime. + * nptl/pthreadP.h (__find_thread_by_id): Remove prototype. + * elf/dl-support.c [!HP_TIMING_NOAVAIL] (_dl_cpuclock_offset): Remove. + (_dl_non_dynamic_init): Remove _dl_cpuclock_offset setting. + * elf/rtld.c (_dl_start_final): Likewise. + * nptl/allocatestack.c (__find_thread_by_id): Remove function. + * sysdeps/generic/ldsodefs.h [!HP_TIMING_NOAVAIL] (_dl_cpuclock_offset): + Remove. + * sysdeps/mach/hurd/dl-sysdep.c [!HP_TIMING_NOAVAIL] + (_dl_cpuclock_offset): Remove. + * nptl/descr.h (struct pthread): Rename cpuclock_offset to + cpuclock_offset_ununsed. + * nptl/nptl-init.c (__pthread_initialize_minimal_internal): Remove + cpuclock_offset set. + * nptl/pthread_create.c (START_THREAD_DEFN): Likewise. + * sysdeps/nptl/fork.c (__libc_fork): Likewise. + * nptl/pthread_clock_gettime.c: Remove file. + * nptl/pthread_clock_settime.c: Likewise. + * sysdeps/unix/clock_gettime.c (hp_timing_gettime): Remove function. + [HP_TIMING_AVAIL] (realtime_gettime): Remove CLOCK_THREAD_CPUTIME_ID + and CLOCK_PROCESS_CPUTIME_ID support. + * sysdeps/unix/clock_settime.c (hp_timing_gettime): Likewise. + [HP_TIMING_AVAIL] (realtime_gettime): Likewise. + * sysdeps/posix/clock_getres.c (hp_timing_getres): Likewise. + [HP_TIMING_AVAIL] (__clock_getres): Likewise. + * sysdeps/unix/clock_nanosleep.c (CPUCLOCK_P, INVALID_CLOCK_P): + Likewise. + (__clock_nanosleep): Remove CPUCLOCK_P and INVALID_CLOCK_P usage. + + [1] http://man7.org/linux/man-pages/man2/clock_gettime.2.html + +Conflicts: + nptl/pthread_clock_gettime.c + nptl/pthread_clock_settime.c + (Removal after copyright year update upstream.) + +diff --git a/elf/dl-support.c b/elf/dl-support.c +index c8439fcc53d126f3..ef5455b91c17ca30 100644 +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -127,11 +127,6 @@ void *_dl_random; + #include + #include + +-/* Initial value of the CPU clock. */ +-#ifndef HP_TIMING_NONAVAIL +-hp_timing_t _dl_cpuclock_offset; +-#endif +- + void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls; + + size_t _dl_pagesize = EXEC_PAGESIZE; +@@ -312,9 +307,6 @@ _dl_non_dynamic_init (void) + _dl_main_map.l_phdr = GL(dl_phdr); + _dl_main_map.l_phnum = GL(dl_phnum); + +- if (HP_SMALL_TIMING_AVAIL) +- HP_TIMING_NOW (_dl_cpuclock_offset); +- + _dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1; + + /* Set up the data structures for the system-supplied DSO early, +diff --git a/elf/rtld.c b/elf/rtld.c +index 0aa1a2a19f649e16..e107bd14f9478a90 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -401,8 +401,6 @@ _dl_start_final (void *arg, struct dl_start_final_info *info) + # endif + #endif + +- HP_TIMING_NOW (GL(dl_cpuclock_offset)); +- + /* Initialize the stack end variable. */ + __libc_stack_end = __builtin_frame_address (0); + +diff --git a/nptl/Makefile b/nptl/Makefile +index 447dce0590295c9c..d6b37b6efd3b7d78 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -109,7 +109,6 @@ libpthread-routines = nptl-init nptlfreeres vars events version pt-interp \ + pthread_once \ + old_pthread_atfork \ + pthread_getcpuclockid \ +- pthread_clock_gettime pthread_clock_settime \ + shm-directory \ + sem_init sem_destroy \ + sem_open sem_close sem_unlink \ +diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c +index d0971a97fdbe098e..5fa45b19987717e1 100644 +--- a/nptl/allocatestack.c ++++ b/nptl/allocatestack.c +@@ -964,54 +964,6 @@ __reclaim_stacks (void) + } + + +-#if HP_TIMING_AVAIL +-# undef __find_thread_by_id +-/* Find a thread given the thread ID. */ +-attribute_hidden +-struct pthread * +-__find_thread_by_id (pid_t tid) +-{ +- struct pthread *result = NULL; +- +- lll_lock (stack_cache_lock, LLL_PRIVATE); +- +- /* Iterate over the list with system-allocated threads first. */ +- list_t *runp; +- list_for_each (runp, &stack_used) +- { +- struct pthread *curp; +- +- curp = list_entry (runp, struct pthread, list); +- +- if (curp->tid == tid) +- { +- result = curp; +- goto out; +- } +- } +- +- /* Now the list with threads using user-allocated stacks. */ +- list_for_each (runp, &__stack_user) +- { +- struct pthread *curp; +- +- curp = list_entry (runp, struct pthread, list); +- +- if (curp->tid == tid) +- { +- result = curp; +- goto out; +- } +- } +- +- out: +- lll_unlock (stack_cache_lock, LLL_PRIVATE); +- +- return result; +-} +-#endif +- +- + #ifdef SIGSETXID + static void + setxid_mark_thread (struct xid_command *cmdp, struct pthread *t) +diff --git a/nptl/descr.h b/nptl/descr.h +index 9c01e1b9863b178c..c3b81d8b27839502 100644 +--- a/nptl/descr.h ++++ b/nptl/descr.h +@@ -343,8 +343,7 @@ struct pthread + unsigned int setxid_futex; + + #if HP_TIMING_AVAIL +- /* Offset of the CPU clock at start thread start time. */ +- hp_timing_t cpuclock_offset; ++ hp_timing_t cpuclock_offset_ununsed; + #endif + + /* If the thread waits to join another one the ID of the latter is +diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c +index 907411d5bca2af79..098bc059f4771ef2 100644 +--- a/nptl/nptl-init.c ++++ b/nptl/nptl-init.c +@@ -275,9 +275,6 @@ __pthread_initialize_minimal_internal (void) + THREAD_SETMEM (pd, user_stack, true); + if (LLL_LOCK_INITIALIZER != 0) + THREAD_SETMEM (pd, lock, LLL_LOCK_INITIALIZER); +-#if HP_TIMING_AVAIL +- THREAD_SETMEM (pd, cpuclock_offset, GL(dl_cpuclock_offset)); +-#endif + + /* Initialize the robust mutex data. */ + { +diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h +index 19efe1e35feed5be..00be8f92793e8710 100644 +--- a/nptl/pthreadP.h ++++ b/nptl/pthreadP.h +@@ -406,16 +406,6 @@ extern int __pthread_multiple_threads attribute_hidden; + extern int *__libc_multiple_threads_ptr attribute_hidden; + #endif + +-/* Find a thread given its TID. */ +-extern struct pthread *__find_thread_by_id (pid_t tid) attribute_hidden +-#ifdef SHARED +-; +-#else +-weak_function; +-#define __find_thread_by_id(tid) \ +- (__find_thread_by_id ? (__find_thread_by_id) (tid) : (struct pthread *) NULL) +-#endif +- + extern void __pthread_init_static_tls (struct link_map *) attribute_hidden; + + extern size_t __pthread_get_minstack (const pthread_attr_t *attr); +diff --git a/nptl/pthread_clock_gettime.c b/nptl/pthread_clock_gettime.c +deleted file mode 100644 +index 6bc75cfe3f1ff856..0000000000000000 +--- a/nptl/pthread_clock_gettime.c ++++ /dev/null +@@ -1,67 +0,0 @@ +-/* Copyright (C) 2001-2018 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; see the file COPYING.LIB. If +- not, see . */ +- +-#include +-#include +-#include +-#include "pthreadP.h" +- +- +-#if HP_TIMING_AVAIL +-int +-__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq, +- struct timespec *tp) +-{ +- hp_timing_t tsc; +- +- /* Get the current counter. */ +- HP_TIMING_NOW (tsc); +- +- /* This is the ID of the thread we are looking for. */ +- pid_t tid = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE; +- +- /* Compute the offset since the start time of the process. */ +- if (tid == 0 || tid == THREAD_GETMEM (THREAD_SELF, tid)) +- /* Our own clock. */ +- tsc -= THREAD_GETMEM (THREAD_SELF, cpuclock_offset); +- else +- { +- /* This is more complicated. We have to locate the thread based +- on the ID. This means walking the list of existing +- threads. */ +- struct pthread *thread = __find_thread_by_id (tid); +- if (thread == NULL) +- { +- __set_errno (EINVAL); +- return -1; +- } +- +- /* There is a race here. The thread might terminate and the stack +- become unusable. But this is the user's problem. */ +- tsc -= thread->cpuclock_offset; +- } +- +- /* Compute the seconds. */ +- tp->tv_sec = tsc / freq; +- +- /* And the nanoseconds. This computation should be stable until +- we get machines with about 16GHz frequency. */ +- tp->tv_nsec = ((tsc % freq) * 1000000000ull) / freq; +- +- return 0; +-} +-#endif +diff --git a/nptl/pthread_clock_settime.c b/nptl/pthread_clock_settime.c +deleted file mode 100644 +index 29d35c64cfa817a3..0000000000000000 +--- a/nptl/pthread_clock_settime.c ++++ /dev/null +@@ -1,54 +0,0 @@ +-/* Copyright (C) 2001-2018 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; see the file COPYING.LIB. If +- not, see . */ +- +-#include +-#include +-#include +-#include "pthreadP.h" +- +- +-#if HP_TIMING_AVAIL +-int +-__pthread_clock_settime (clockid_t clock_id, hp_timing_t offset) +-{ +- /* This is the ID of the thread we are looking for. */ +- pid_t tid = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE; +- +- /* Compute the offset since the start time of the process. */ +- if (tid == 0 || tid == THREAD_GETMEM (THREAD_SELF, tid)) +- /* Our own clock. */ +- THREAD_SETMEM (THREAD_SELF, cpuclock_offset, offset); +- else +- { +- /* This is more complicated. We have to locate the thread based +- on the ID. This means walking the list of existing +- threads. */ +- struct pthread *thread = __find_thread_by_id (tid); +- if (thread == NULL) +- { +- __set_errno (EINVAL); +- return -1; +- } +- +- /* There is a race here. The thread might terminate and the stack +- become unusable. But this is the user's problem. */ +- thread->cpuclock_offset = offset; +- } +- +- return 0; +-} +-#endif +diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c +index fe75d04113b8aa3f..f58a15cd1c7bbb6f 100644 +--- a/nptl/pthread_create.c ++++ b/nptl/pthread_create.c +@@ -379,13 +379,6 @@ START_THREAD_DEFN + { + struct pthread *pd = START_THREAD_SELF; + +-#if HP_TIMING_AVAIL +- /* Remember the time when the thread was started. */ +- hp_timing_t now; +- HP_TIMING_NOW (now); +- THREAD_SETMEM (pd, cpuclock_offset, now); +-#endif +- + /* Initialize resolver state pointer. */ + __resp = &pd->res; + +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index c6b7e61badbfd513..f0185ce0d16c0f69 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -359,11 +359,6 @@ struct rtld_global + /* The object to be initialized first. */ + EXTERN struct link_map *_dl_initfirst; + +-#if HP_SMALL_TIMING_AVAIL +- /* Start time on CPU clock. */ +- EXTERN hp_timing_t _dl_cpuclock_offset; +-#endif +- + /* Map of shared object to be profiled. */ + EXTERN struct link_map *_dl_profile_map; + +diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c +index b72913d3baaed1d9..7bd1d70c96c229e0 100644 +--- a/sysdeps/mach/hurd/dl-sysdep.c ++++ b/sysdeps/mach/hurd/dl-sysdep.c +@@ -62,10 +62,6 @@ int __libc_multiple_libcs = 0; /* Defining this here avoids the inclusion + void *__libc_stack_end = NULL; + rtld_hidden_data_def(__libc_stack_end) + +-#if HP_TIMING_AVAIL +-hp_timing_t _dl_cpuclock_offset; +-#endif +- + /* TODO: Initialize. */ + void *_dl_random attribute_relro = NULL; + +@@ -246,10 +242,6 @@ unfmh(); /* XXX */ + /* Initialize frequently used global variable. */ + GLRO(dl_pagesize) = __getpagesize (); + +-#if HP_TIMING_AVAIL +- HP_TIMING_NOW (_dl_cpuclock_offset); +-#endif +- + fmh(); /* XXX */ + + /* See hurd/hurdstartup.c; this deals with getting information +diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c +index 1a9429b579cd346e..37db30f3d1e846b6 100644 +--- a/sysdeps/nptl/fork.c ++++ b/sysdeps/nptl/fork.c +@@ -83,14 +83,6 @@ __libc_fork (void) + if (__fork_generation_pointer != NULL) + *__fork_generation_pointer += __PTHREAD_ONCE_FORK_GEN_INCR; + +-#if HP_TIMING_AVAIL +- /* The CPU clock of the thread and process have to be set to zero. */ +- hp_timing_t now; +- HP_TIMING_NOW (now); +- THREAD_SETMEM (self, cpuclock_offset, now); +- GL(dl_cpuclock_offset) = now; +-#endif +- + #ifdef __NR_set_robust_list + /* Initialize the robust mutex list setting in the kernel which has + been reset during the fork. We do not check for errors because if +diff --git a/sysdeps/posix/clock_getres.c b/sysdeps/posix/clock_getres.c +index 43228c381e6a73f1..5b0d8eb8a1a0593e 100644 +--- a/sysdeps/posix/clock_getres.c ++++ b/sysdeps/posix/clock_getres.c +@@ -24,37 +24,6 @@ + #include + + +-#if HP_TIMING_AVAIL +-static long int nsec; /* Clock frequency of the processor. */ +- +-static int +-hp_timing_getres (struct timespec *res) +-{ +- if (__glibc_unlikely (nsec == 0)) +- { +- hp_timing_t freq; +- +- /* This can only happen if we haven't initialized the `nsec' +- variable yet. Do this now. We don't have to protect this +- code against multiple execution since all of them should +- lead to the same result. */ +- freq = __get_clockfreq (); +- if (__glibc_unlikely (freq == 0)) +- /* Something went wrong. */ +- return -1; +- +- nsec = MAX (UINT64_C (1000000000) / freq, 1); +- } +- +- /* Fill in the values. +- The seconds are always zero (unless we have a 1Hz machine). */ +- res->tv_sec = 0; +- res->tv_nsec = nsec; +- +- return 0; +-} +-#endif +- + static inline int + realtime_getres (struct timespec *res) + { +@@ -87,21 +56,8 @@ __clock_getres (clockid_t clock_id, struct timespec *res) + break; + + default: +-#if HP_TIMING_AVAIL +- if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1)) +- == CLOCK_THREAD_CPUTIME_ID) +- retval = hp_timing_getres (res); +- else +-#endif +- __set_errno (EINVAL); +- break; +- +-#if HP_TIMING_AVAIL +- case CLOCK_PROCESS_CPUTIME_ID: +- case CLOCK_THREAD_CPUTIME_ID: +- retval = hp_timing_getres (res); ++ __set_errno (EINVAL); + break; +-#endif + } + + return retval; +diff --git a/sysdeps/unix/clock_gettime.c b/sysdeps/unix/clock_gettime.c +index f19fdf7e5f310973..f3ebbe15ccc2e95e 100644 +--- a/sysdeps/unix/clock_gettime.c ++++ b/sysdeps/unix/clock_gettime.c +@@ -24,57 +24,6 @@ + #include + + +-#if HP_TIMING_AVAIL +-/* Clock frequency of the processor. We make it a 64-bit variable +- because some jokers are already playing with processors with more +- than 4GHz. */ +-static hp_timing_t freq; +- +- +-/* This function is defined in the thread library. */ +-extern int __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq, +- struct timespec *tp) +- __attribute__ ((__weak__)); +- +-static int +-hp_timing_gettime (clockid_t clock_id, struct timespec *tp) +-{ +- hp_timing_t tsc; +- +- if (__glibc_unlikely (freq == 0)) +- { +- /* This can only happen if we haven't initialized the `freq' +- variable yet. Do this now. We don't have to protect this +- code against multiple execution since all of them should +- lead to the same result. */ +- freq = __get_clockfreq (); +- if (__glibc_unlikely (freq == 0)) +- /* Something went wrong. */ +- return -1; +- } +- +- if (clock_id != CLOCK_PROCESS_CPUTIME_ID +- && __pthread_clock_gettime != NULL) +- return __pthread_clock_gettime (clock_id, freq, tp); +- +- /* Get the current counter. */ +- HP_TIMING_NOW (tsc); +- +- /* Compute the offset since the start time of the process. */ +- tsc -= GL(dl_cpuclock_offset); +- +- /* Compute the seconds. */ +- tp->tv_sec = tsc / freq; +- +- /* And the nanoseconds. This computation should be stable until +- we get machines with about 16GHz frequency. */ +- tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq; +- +- return 0; +-} +-#endif +- +- + static inline int + realtime_gettime (struct timespec *tp) + { +@@ -105,20 +54,8 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp) + break; + + default: +-#if HP_TIMING_AVAIL +- if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1)) +- == CLOCK_THREAD_CPUTIME_ID) +- retval = hp_timing_gettime (clock_id, tp); +- else +-#endif +- __set_errno (EINVAL); +- break; +- +-#if HP_TIMING_AVAIL +- case CLOCK_PROCESS_CPUTIME_ID: +- retval = hp_timing_gettime (clock_id, tp); ++ __set_errno (EINVAL); + break; +-#endif + } + + return retval; +diff --git a/sysdeps/unix/clock_nanosleep.c b/sysdeps/unix/clock_nanosleep.c +index 97b3d6b6ab9e4581..13dd0f4b905ec631 100644 +--- a/sysdeps/unix/clock_nanosleep.c ++++ b/sysdeps/unix/clock_nanosleep.c +@@ -19,23 +19,8 @@ + #include + #include + #include +-#include + #include + +-#if HP_TIMING_AVAIL +-# define CPUCLOCK_P(clock) \ +- ((clock) == CLOCK_PROCESS_CPUTIME_ID \ +- || ((clock) & ((1 << CLOCK_IDFIELD_SIZE) - 1)) == CLOCK_THREAD_CPUTIME_ID) +-#else +-# define CPUCLOCK_P(clock) 0 +-#endif +- +-#ifndef INVALID_CLOCK_P +-# define INVALID_CLOCK_P(cl) \ +- ((cl) < CLOCK_REALTIME || (cl) > CLOCK_THREAD_CPUTIME_ID) +-#endif +- +- + /* This implementation assumes that these is only a `nanosleep' system + call. So we have to remap all other activities. */ + int +@@ -51,14 +36,7 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req, + if (clock_id == CLOCK_THREAD_CPUTIME_ID) + return EINVAL; /* POSIX specifies EINVAL for this case. */ + +-#ifdef SYSDEP_NANOSLEEP +- SYSDEP_NANOSLEEP; +-#endif +- +- if (CPUCLOCK_P (clock_id)) +- return ENOTSUP; +- +- if (INVALID_CLOCK_P (clock_id)) ++ if (clock_id < CLOCK_REALTIME || clock_id > CLOCK_THREAD_CPUTIME_ID) + return EINVAL; + + /* If we got an absolute time, remap it. */ +@@ -71,7 +49,7 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req, + assert (sizeof (sec) >= sizeof (now.tv_sec)); + + /* Get the current time for this clock. */ +- if (__builtin_expect (__clock_gettime (clock_id, &now), 0) != 0) ++ if (__clock_gettime (clock_id, &now) != 0) + return errno; + + /* Compute the difference. */ +@@ -90,12 +68,12 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req, + /* Make sure we are not modifying the struct pointed to by REM. */ + rem = NULL; + } +- else if (__builtin_expect (flags, 0) != 0) ++ else if (flags != 0) + return EINVAL; + else if (clock_id != CLOCK_REALTIME) + /* Not supported. */ + return ENOTSUP; + +- return __builtin_expect (__nanosleep (req, rem), 0) ? errno : 0; ++ return __nanosleep (req, rem), 0 ? errno : 0; + } + weak_alias (__clock_nanosleep, clock_nanosleep) +diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/unix/clock_settime.c +index 9d5857e61b966b44..4f5640f67047cef6 100644 +--- a/sysdeps/unix/clock_settime.c ++++ b/sysdeps/unix/clock_settime.c +@@ -21,59 +21,11 @@ + #include + + +-#if HP_TIMING_AVAIL +-/* Clock frequency of the processor. We make it a 64-bit variable +- because some jokers are already playing with processors with more +- than 4GHz. */ +-static hp_timing_t freq; +- +- +-/* This function is defined in the thread library. */ +-extern void __pthread_clock_settime (clockid_t clock_id, hp_timing_t offset) +- __attribute__ ((__weak__)); +- +- +-static int +-hp_timing_settime (clockid_t clock_id, const struct timespec *tp) +-{ +- hp_timing_t tsc; +- hp_timing_t usertime; +- +- /* First thing is to get the current time. */ +- HP_TIMING_NOW (tsc); +- +- if (__glibc_unlikely (freq == 0)) +- { +- /* This can only happen if we haven't initialized the `freq' +- variable yet. Do this now. We don't have to protect this +- code against multiple execution since all of them should lead +- to the same result. */ +- freq = __get_clockfreq (); +- if (__glibc_unlikely (freq == 0)) +- /* Something went wrong. */ +- return -1; +- } +- +- /* Convert the user-provided time into CPU ticks. */ +- usertime = tp->tv_sec * freq + (tp->tv_nsec * freq) / 1000000000ull; +- +- /* Determine the offset and use it as the new base value. */ +- if (clock_id == CLOCK_PROCESS_CPUTIME_ID +- || __pthread_clock_settime == NULL) +- GL(dl_cpuclock_offset) = tsc - usertime; +- else +- __pthread_clock_settime (clock_id, tsc - usertime); +- +- return 0; +-} +-#endif +- +- + /* Set CLOCK to value TP. */ + int + __clock_settime (clockid_t clock_id, const struct timespec *tp) + { +- int retval; ++ int retval = -1; + + /* Make sure the time cvalue is OK. */ + if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000) +@@ -93,16 +45,7 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp) + break; + + default: +-# if HP_TIMING_AVAIL +- if (CPUCLOCK_WHICH (clock_id) == CLOCK_PROCESS_CPUTIME_ID +- || CPUCLOCK_WHICH (clock_id) == CLOCK_THREAD_CPUTIME_ID) +- retval = hp_timing_settime (clock_id, tp); +- else +-# endif +- { +- __set_errno (EINVAL); +- retval = -1; +- } ++ __set_errno (EINVAL); + break; + } + diff --git a/glibc-rh1748197-6.patch b/glibc-rh1748197-6.patch new file mode 100755 index 0000000..65b59c9 --- /dev/null +++ b/glibc-rh1748197-6.patch @@ -0,0 +1,745 @@ +commit 6e8ba7fd574f530afb9681f21604475d5756d773 +Author: Adhemerval Zanella +Date: Fri Feb 8 16:53:40 2019 +0000 + + Remove __get_clockfreq + + With clock_getres, clock_gettime, and clock_settime refactor to remove the + generic CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID support through + hp-timing, there is no usage of internal __get_clockfreq. This patch removes + both generic and Linux implementation.. + + Checked with a build against aarch64-linux-gnu, i686-linux-gnu, ia64-linux-gnu, + sparc64-linux-gnu, powerpc-linux-gnu-power4. + + * include/libc-internal.h (__get_clockfreq): Remove prototype. + * rt/Makefile (clock-routines): Remove get_clockfreq. + * rt/get_clockfreq.c: Remove file. + * sysdeps/unix/sysv/linux/i386/get_clockfreq.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/get_clockfreq.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c: Move code to ... + * sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c: ... here. + +Conflicts: + rt/get_clockfreq.c + sysdeps/unix/sysv/linux/i386/get_clockfreq.c + sysdeps/unix/sysv/linux/ia64/get_clockfreq.c + sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c + (Removal after copyright year change upstream.) + sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c + (Likewise. Missing backport of aa0e46636a5b71 ("Break + further lines before not after operators.").) + +diff --git a/include/libc-internal.h b/include/libc-internal.h +index 2167990c52bd708b..2ec07d9355db1808 100644 +--- a/include/libc-internal.h ++++ b/include/libc-internal.h +@@ -36,9 +36,6 @@ libc_hidden_proto (__profile_frequency) + extern void __cyg_profile_func_enter (void *this_fn, void *call_site); + extern void __cyg_profile_func_exit (void *this_fn, void *call_site); + +-/* Get frequency of the system processor. */ +-extern hp_timing_t __get_clockfreq (void); +- + /* Free all allocated resources. */ + extern void __libc_freeres (void); + libc_hidden_proto (__libc_freeres) +diff --git a/rt/Makefile b/rt/Makefile +index 6d6b896ee9817c5c..14f38ef74d262188 100644 +--- a/rt/Makefile ++++ b/rt/Makefile +@@ -28,7 +28,7 @@ aio-routines := aio_cancel aio_error aio_fsync aio_misc aio_read \ + aio_read64 aio_return aio_suspend aio_write \ + aio_write64 lio_listio lio_listio64 aio_sigqueue \ + aio_notify +-clock-routines := get_clockfreq clock_getcpuclockid \ ++clock-routines := clock_getcpuclockid \ + clock_getres clock_gettime clock_settime \ + clock_nanosleep + timer-routines := timer_create timer_delete timer_getoverr \ +diff --git a/rt/get_clockfreq.c b/rt/get_clockfreq.c +deleted file mode 100644 +index e695a6018c0b8322..0000000000000000 +--- a/rt/get_clockfreq.c ++++ /dev/null +@@ -1,27 +0,0 @@ +-/* Get frequency of the system processor. +- Copyright (C) 2000-2018 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 +- . */ +- +-#include +- +-hp_timing_t +-__get_clockfreq (void) +-{ +- /* There is no generic way to find this out since we have in general +- no counter register either. */ +- return 0; +-} +diff --git a/sysdeps/unix/sysv/linux/i386/get_clockfreq.c b/sysdeps/unix/sysv/linux/i386/get_clockfreq.c +deleted file mode 100644 +index 633f186be80f10b0..0000000000000000 +--- a/sysdeps/unix/sysv/linux/i386/get_clockfreq.c ++++ /dev/null +@@ -1,88 +0,0 @@ +-/* Get frequency of the system processor. i386/Linux version. +- Copyright (C) 2000-2018 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 +- . */ +- +-#include +-#include +-#include +-#include +- +-hp_timing_t +-__get_clockfreq (void) +-{ +- /* We read the information from the /proc filesystem. It contains at +- least one line like +- cpu MHz : 497.840237 +- or also +- cpu MHz : 497.841 +- We search for this line and convert the number in an integer. */ +- static hp_timing_t result; +- int fd; +- +- /* If this function was called before, we know the result. */ +- if (result != 0) +- return result; +- +- fd = __open ("/proc/cpuinfo", O_RDONLY); +- if (__glibc_likely (fd != -1)) +- { +- /* XXX AFAIK the /proc filesystem can generate "files" only up +- to a size of 4096 bytes. */ +- char buf[4096]; +- ssize_t n; +- +- n = __read (fd, buf, sizeof buf); +- if (__builtin_expect (n, 1) > 0) +- { +- char *mhz = memmem (buf, n, "cpu MHz", 7); +- +- if (__glibc_likely (mhz != NULL)) +- { +- char *endp = buf + n; +- int seen_decpoint = 0; +- int ndigits = 0; +- +- /* Search for the beginning of the string. */ +- while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n') +- ++mhz; +- +- while (mhz < endp && *mhz != '\n') +- { +- if (*mhz >= '0' && *mhz <= '9') +- { +- result *= 10; +- result += *mhz - '0'; +- if (seen_decpoint) +- ++ndigits; +- } +- else if (*mhz == '.') +- seen_decpoint = 1; +- +- ++mhz; +- } +- +- /* Compensate for missing digits at the end. */ +- while (ndigits++ < 6) +- result *= 10; +- } +- } +- +- __close (fd); +- } +- +- return result; +-} +diff --git a/sysdeps/unix/sysv/linux/ia64/get_clockfreq.c b/sysdeps/unix/sysv/linux/ia64/get_clockfreq.c +deleted file mode 100644 +index f9d683a90247ac60..0000000000000000 +--- a/sysdeps/unix/sysv/linux/ia64/get_clockfreq.c ++++ /dev/null +@@ -1,87 +0,0 @@ +-/* Get frequency of the system processor. IA-64/Linux version. +- Copyright (C) 2001-2018 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 +- . */ +- +-#include +-#include +-#include +-#include +- +- +-hp_timing_t +-__get_clockfreq (void) +-{ +- /* We read the information from the /proc filesystem. It contains at +- least one line like +- itc MHz : 733.390988 +- We search for this line and convert the number in an integer. */ +- static hp_timing_t result; +- int fd; +- +- /* If this function was called before, we know the result. */ +- if (result != 0) +- return result; +- +- fd = __open ("/proc/cpuinfo", O_RDONLY); +- if (__builtin_expect (fd != -1, 1)) +- { +- /* XXX AFAIK the /proc filesystem can generate "files" only up +- to a size of 4096 bytes. */ +- char buf[4096]; +- ssize_t n; +- +- n = __read (fd, buf, sizeof buf); +- if (__builtin_expect (n, 1) > 0) +- { +- char *mhz = memmem (buf, n, "itc MHz", 7); +- +- if (__builtin_expect (mhz != NULL, 1)) +- { +- char *endp = buf + n; +- int seen_decpoint = 0; +- int ndigits = 0; +- +- /* Search for the beginning of the string. */ +- while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n') +- ++mhz; +- +- while (mhz < endp && *mhz != '\n') +- { +- if (*mhz >= '0' && *mhz <= '9') +- { +- result *= 10; +- result += *mhz - '0'; +- if (seen_decpoint) +- ++ndigits; +- } +- else if (*mhz == '.') +- seen_decpoint = 1; +- +- ++mhz; +- } +- +- /* Compensate for missing digits at the end. */ +- while (ndigits++ < 6) +- result *= 10; +- } +- } +- +- __close (fd); +- } +- +- return result; +-} +diff --git a/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c b/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c +deleted file mode 100644 +index 3a2216021bfb5408..0000000000000000 +--- a/sysdeps/unix/sysv/linux/powerpc/get_clockfreq.c ++++ /dev/null +@@ -1,107 +0,0 @@ +-/* Get frequency of the system processor. powerpc/Linux version. +- Copyright (C) 2000-2018 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 +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-hp_timing_t +-__get_clockfreq (void) +-{ +- hp_timing_t result = 0L; +- +-#ifdef SHARED +- /* The vDSO does not return an error (it clear cr0.so on returning). */ +- INTERNAL_SYSCALL_DECL (err); +- result = +- INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK (get_tbfreq, err, uint64_t, 0); +-#else +- /* We read the information from the /proc filesystem. /proc/cpuinfo +- contains at least one line like: +- timebase : 33333333 +- We search for this line and convert the number into an integer. */ +- int fd = __open_nocancel ("/proc/cpuinfo", O_RDONLY); +- if (__glibc_likely (fd != -1)) +- return result; +- +- /* The timebase will be in the 1st 1024 bytes for systems with up +- to 8 processors. If the first read returns less then 1024 +- bytes read, we have the whole cpuinfo and can start the scan. +- Otherwise we will have to read more to insure we have the +- timebase value in the scan. */ +- char buf[1024]; +- ssize_t n; +- +- n = __read_nocancel (fd, buf, sizeof (buf)); +- if (n == sizeof (buf)) +- { +- /* We are here because the 1st read returned exactly sizeof +- (buf) bytes. This implies that we are not at EOF and may +- not have read the timebase value yet. So we need to read +- more bytes until we know we have EOF. We copy the lower +- half of buf to the upper half and read sizeof (buf)/2 +- bytes into the lower half of buf and repeat until we +- reach EOF. We can assume that the timebase will be in +- the last 512 bytes of cpuinfo, so two 512 byte half_bufs +- will be sufficient to contain the timebase and will +- handle the case where the timebase spans the half_buf +- boundry. */ +- const ssize_t half_buf = sizeof (buf) / 2; +- while (n >= half_buf) +- { +- memcpy (buf, buf + half_buf, half_buf); +- n = __read_nocancel (fd, buf + half_buf, half_buf); +- } +- if (n >= 0) +- n += half_buf; +- } +- __close_nocancel (fd); +- +- if (__glibc_likely (n > 0)) +- { +- char *mhz = memmem (buf, n, "timebase", 7); +- +- if (__glibc_likely (mhz != NULL)) +- { +- char *endp = buf + n; +- +- /* Search for the beginning of the string. */ +- while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n') +- ++mhz; +- +- while (mhz < endp && *mhz != '\n') +- { +- if (*mhz >= '0' && *mhz <= '9') +- { +- result *= 10; +- result += *mhz - '0'; +- } +- +- ++mhz; +- } +- } +- } +-#endif +- +- return result; +-} +diff --git a/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c b/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c +index 6435e1f31529c7de..1177ccbc8faeafe7 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c ++++ b/sysdeps/unix/sysv/linux/powerpc/get_timebase_freq.c +@@ -17,11 +17,90 @@ + . */ + + #include ++#include ++ + #include ++#include ++#include + + uint64_t + __get_timebase_freq (void) + { +- return (uint64_t) __get_clockfreq (); ++ hp_timing_t result = 0L; ++ ++#ifdef SHARED ++ /* The vDSO does not return an error (it clear cr0.so on returning). */ ++ INTERNAL_SYSCALL_DECL (err); ++ result = ++ INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK (get_tbfreq, err, uint64_t, 0); ++#else ++ /* We read the information from the /proc filesystem. /proc/cpuinfo ++ contains at least one line like: ++ timebase : 33333333 ++ We search for this line and convert the number into an integer. */ ++ int fd = __open_nocancel ("/proc/cpuinfo", O_RDONLY); ++ if (__glibc_likely (fd != -1)) ++ return result; ++ ++ /* The timebase will be in the 1st 1024 bytes for systems with up ++ to 8 processors. If the first read returns less then 1024 ++ bytes read, we have the whole cpuinfo and can start the scan. ++ Otherwise we will have to read more to insure we have the ++ timebase value in the scan. */ ++ char buf[1024]; ++ ssize_t n; ++ ++ n = __read_nocancel (fd, buf, sizeof (buf)); ++ if (n == sizeof (buf)) ++ { ++ /* We are here because the 1st read returned exactly sizeof ++ (buf) bytes. This implies that we are not at EOF and may ++ not have read the timebase value yet. So we need to read ++ more bytes until we know we have EOF. We copy the lower ++ half of buf to the upper half and read sizeof (buf)/2 ++ bytes into the lower half of buf and repeat until we ++ reach EOF. We can assume that the timebase will be in ++ the last 512 bytes of cpuinfo, so two 512 byte half_bufs ++ will be sufficient to contain the timebase and will ++ handle the case where the timebase spans the half_buf ++ boundry. */ ++ const ssize_t half_buf = sizeof (buf) / 2; ++ while (n >= half_buf) ++ { ++ memcpy (buf, buf + half_buf, half_buf); ++ n = __read_nocancel (fd, buf + half_buf, half_buf); ++ } ++ if (n >= 0) ++ n += half_buf; ++ } ++ __close_nocancel (fd); ++ ++ if (__glibc_likely (n > 0)) ++ { ++ char *mhz = memmem (buf, n, "timebase", 7); ++ ++ if (__glibc_likely (mhz != NULL)) ++ { ++ char *endp = buf + n; ++ ++ /* Search for the beginning of the string. */ ++ while (mhz < endp && (*mhz < '0' || *mhz > '9') && *mhz != '\n') ++ ++mhz; ++ ++ while (mhz < endp && *mhz != '\n') ++ { ++ if (*mhz >= '0' && *mhz <= '9') ++ { ++ result *= 10; ++ result += *mhz - '0'; ++ } ++ ++ ++mhz; ++ } ++ } ++ } ++#endif ++ ++ return result; + } + weak_alias (__get_timebase_freq, __ppc_get_timebase_freq) +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c b/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c +deleted file mode 100644 +index 6838a77a769ddae8..0000000000000000 +--- a/sysdeps/unix/sysv/linux/sparc/sparc64/get_clockfreq.c ++++ /dev/null +@@ -1,250 +0,0 @@ +-/* Get frequency of the system processor. sparc64 version. +- Copyright (C) 2001-2018 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 +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-static hp_timing_t +-__get_clockfreq_via_cpuinfo (void) +-{ +- hp_timing_t result; +- int fd; +- +- result = 0; +- +- fd = __open ("/proc/cpuinfo", O_RDONLY); +- if (fd != -1) +- { +- char buf[8192]; +- ssize_t n; +- +- n = __read (fd, buf, sizeof buf); +- if (n > 0) +- { +- char *mhz = memmem (buf, n, "Cpu0ClkTck", 7); +- +- if (mhz != NULL) +- { +- char *endp = buf + n; +- +- /* Search for the beginning of the string. */ +- while (mhz < endp +- && (*mhz < '0' || *mhz > '9') +- && (*mhz < 'a' || *mhz > 'f') +- && *mhz != '\n') +- ++mhz; +- +- while (mhz < endp && *mhz != '\n') +- { +- if ((*mhz >= '0' && *mhz <= '9') || +- (*mhz >= 'a' && *mhz <= 'f')) +- { +- result <<= 4; +- if (*mhz >= '0' && *mhz <= '9') +- result += *mhz - '0'; +- else +- result += (*mhz - 'a') + 10; +- } +- ++mhz; +- } +- } +- } +- +- __close (fd); +- } +- +- return result; +-} +- +-static hp_timing_t +-__get_clockfreq_via_proc_openprom (void) +-{ +- hp_timing_t result; +- int obp_fd; +- +- result = 0; +- +- obp_fd = __open ("/proc/openprom", O_RDONLY); +- if (obp_fd != -1) +- { +- unsigned long int buf[4096 / sizeof (unsigned long int)]; +- struct dirent64 *dirp = (struct dirent64 *) buf; +- ssize_t len; +- +- while ((len = __getdents64 (obp_fd, (char *) dirp, sizeof (buf))) > 0) +- { +- struct dirent64 *this_dirp = dirp; +- +- while (len > 0) +- { +- char node[strlen ("/proc/openprom/") +- + _D_ALLOC_NAMLEN (this_dirp) +- + strlen ("/clock-frequency")]; +- char *prop; +- int fd; +- +- /* Note that +- strlen("/clock-frequency") > strlen("/device_type") +- */ +- __stpcpy (prop = __stpcpy (__stpcpy (node, "/proc/openprom/"), +- this_dirp->d_name), +- "/device_type"); +- fd = __open (node, O_RDONLY); +- if (fd != -1) +- { +- char type_string[128]; +- int ret; +- +- ret = __read (fd, type_string, sizeof (type_string)); +- if (ret > 0 && strncmp (type_string, "'cpu'", 5) == 0) +- { +- int clkfreq_fd; +- +- __stpcpy (prop, "/clock-frequency"); +- clkfreq_fd = __open (node, O_RDONLY); +- if (clkfreq_fd != -1) +- { +- if (__read (clkfreq_fd, type_string, +- sizeof (type_string)) > 0) +- result = (hp_timing_t) +- strtoumax (type_string, NULL, 16); +- __close (clkfreq_fd); +- } +- } +- __close (fd); +- } +- +- if (result != 0) +- break; +- +- len -= this_dirp->d_reclen; +- this_dirp = (struct dirent64 *) +- ((char *) this_dirp + this_dirp->d_reclen); +- } +- if (result != 0) +- break; +- } +- __close (obp_fd); +- } +- +- return result; +-} +- +-static void set_obp_int (struct openpromio *op, int val) +-{ +- char *cp = op->oprom_array; +- int *ip = (int *) cp; +- +- *ip = val; +-} +- +-static int get_obp_int (struct openpromio *op) +-{ +- char *cp = op->oprom_array; +- int *ip = (int *) cp; +- +- return *ip; +-} +- +-static hp_timing_t +-__get_clockfreq_via_dev_openprom (void) +-{ +- hp_timing_t result; +- int obp_dev_fd; +- +- result = 0; +- +- obp_dev_fd = __open ("/dev/openprom", O_RDONLY); +- if (obp_dev_fd != -1) +- { +- char obp_buf[8192]; +- struct openpromio *obp_cmd = (struct openpromio *)obp_buf; +- int ret; +- +- obp_cmd->oprom_size = +- sizeof (obp_buf) - sizeof (unsigned int); +- set_obp_int (obp_cmd, 0); +- ret = __ioctl (obp_dev_fd, OPROMCHILD, (char *) obp_cmd); +- if (ret == 0) +- { +- int cur_node = get_obp_int (obp_cmd); +- +- while (cur_node != 0 && cur_node != -1) +- { +- obp_cmd->oprom_size = sizeof (obp_buf) - sizeof (unsigned int); +- strcpy (obp_cmd->oprom_array, "device_type"); +- ret = __ioctl (obp_dev_fd, OPROMGETPROP, (char *) obp_cmd); +- if (ret == 0 +- && strncmp (obp_cmd->oprom_array, "cpu", 3) == 0) +- { +- obp_cmd->oprom_size = (sizeof (obp_buf) +- - sizeof (unsigned int)); +- strcpy (obp_cmd->oprom_array, "clock-frequency"); +- ret = __ioctl (obp_dev_fd, OPROMGETPROP, (char *) obp_cmd); +- if (ret == 0) +- result = (hp_timing_t) get_obp_int (obp_cmd); +- } +- obp_cmd->oprom_size = sizeof (obp_buf) - sizeof (unsigned int); +- set_obp_int (obp_cmd, cur_node); +- ret = __ioctl (obp_dev_fd, OPROMNEXT, (char *) obp_cmd); +- if (ret < 0) +- break; +- cur_node = get_obp_int (obp_cmd); +- } +- } +- } +- +- return result; +-} +- +-hp_timing_t +-__get_clockfreq (void) +-{ +- static hp_timing_t result; +- +- /* If this function was called before, we know the result. */ +- if (result != 0) +- return result; +- +- /* We first read the information from the /proc/cpuinfo file. +- It contains at least one line like +- Cpu0ClkTick : 000000002cb41780 +- We search for this line and convert the number in an integer. */ +- result = __get_clockfreq_via_cpuinfo (); +- if (result != 0) +- return result; +- +- /* If that did not work, try to find an OpenPROM node +- with device_type equal to 'cpu' using /dev/openprom +- and fetch the clock-frequency property from there. */ +- result = __get_clockfreq_via_dev_openprom (); +- if (result != 0) +- return result; +- +- /* Finally, try the same lookup as above but using /proc/openprom. */ +- result = __get_clockfreq_via_proc_openprom (); +- +- return result; +-} diff --git a/glibc-rh1748197-7.patch b/glibc-rh1748197-7.patch new file mode 100755 index 0000000..805da52 --- /dev/null +++ b/glibc-rh1748197-7.patch @@ -0,0 +1,1335 @@ +commit 7b5af2d8f2a2b858319a792678b15a0db08764c7 +Author: Zack Weinberg +Date: Wed Sep 4 08:18:57 2019 +0200 + + Finish move of clock_* functions to libc. [BZ #24959] + + In glibc 2.17, the functions clock_getcpuclockid, clock_getres, + clock_gettime, clock_nanosleep, and clock_settime were moved from + librt.so to libc.so, leaving compatibility stubs behind. Now that the + dynamic linker no longer insists on finding versioned symbols in the + same library that originally defined them, we do not need the stubs + anymore, and this means we don't need GLIBC_PRIVATE __-prefix aliases + for most of the functions anymore either. (clock_gettime still needs + one.) For ports added before 2.17, libc.so needs to provide two + symbol versions for each, the default at GLIBC_2.17 plus a compat + version matching what librt had. + + While I'm at it, move the clock_*.c files and their tests from rt/ to + time/. + + Conflicts: + rt/clock-compat.c + (Removal after copyright year update upstream.) + sysdeps/unix/sysv/linux/arm/be/libc.abilist + sysdeps/unix/sysv/linux/arm/le/librt.abilist + sysdeps/unix/sysv/linux/microblaze/le/librt.abilist + sysdeps/unix/sysv/linux/sh/be/libc.abilist + sysdeps/unix/sysv/linux/sh/le/librt.abilist + (These ABI lists were split into be/le variants upstream. + The choice of files here reflects the decision of the Git + rename detection for the source of the unsplit ABI list + update.) + time/Makefile + (Missing tests downstream.) + +diff --git a/include/time.h b/include/time.h +index 23d2580528b02490..832ee6896e1ca537 100644 +--- a/include/time.h ++++ b/include/time.h +@@ -16,12 +16,10 @@ libc_hidden_proto (localtime) + libc_hidden_proto (strftime) + libc_hidden_proto (strptime) + +-extern __typeof (clock_getres) __clock_getres; + extern __typeof (clock_gettime) __clock_gettime; + libc_hidden_proto (__clock_gettime) + extern __typeof (clock_settime) __clock_settime; +-extern __typeof (clock_nanosleep) __clock_nanosleep; +-extern __typeof (clock_getcpuclockid) __clock_getcpuclockid; ++libc_hidden_proto (__clock_settime) + + /* Now define the internal interfaces. */ + struct tm; +diff --git a/rt/Makefile b/rt/Makefile +index 14f38ef74d262188..de53133cedc778f6 100644 +--- a/rt/Makefile ++++ b/rt/Makefile +@@ -28,9 +28,6 @@ aio-routines := aio_cancel aio_error aio_fsync aio_misc aio_read \ + aio_read64 aio_return aio_suspend aio_write \ + aio_write64 lio_listio lio_listio64 aio_sigqueue \ + aio_notify +-clock-routines := clock_getcpuclockid \ +- clock_getres clock_gettime clock_settime \ +- clock_nanosleep + timer-routines := timer_create timer_delete timer_getoverr \ + timer_gettime timer_settime + shm-routines := shm_open shm_unlink +@@ -38,22 +35,18 @@ mq-routines := mq_open mq_close mq_unlink mq_getattr mq_setattr \ + mq_notify mq_send mq_receive mq_timedsend \ + mq_timedreceive + +-routines = $(clock-routines) +- + librt-routines = $(aio-routines) \ + $(timer-routines) \ +- $(shm-routines) $(mq-routines) \ +- clock-compat ++ $(shm-routines) $(mq-routines) + +-tests := tst-shm tst-clock tst-clock_nanosleep tst-timer tst-timer2 \ ++tests := tst-shm tst-timer tst-timer2 \ + tst-aio tst-aio64 tst-aio2 tst-aio3 tst-aio4 tst-aio5 tst-aio6 \ + tst-aio7 tst-aio8 tst-aio9 tst-aio10 \ + tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \ + tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-mqueue8 tst-mqueue9 \ + tst-timer3 tst-timer4 tst-timer5 \ +- tst-cpuclock1 tst-cpuclock2 \ +- tst-cputimer1 tst-cputimer2 tst-cputimer3 \ +- tst-clock2 tst-shm-cancel ++ tst-cpuclock2 tst-cputimer1 tst-cputimer2 tst-cputimer3 \ ++ tst-shm-cancel + + extra-libs := librt + extra-libs-others := $(extra-libs) +diff --git a/rt/Versions b/rt/Versions +index 91e3fd2a204ded9c..84d1345420dc4dc4 100644 +--- a/rt/Versions ++++ b/rt/Versions +@@ -1,15 +1,3 @@ +-libc { +- GLIBC_2.17 { +- # c* +- clock_getres; clock_gettime; clock_settime; clock_getcpuclockid; +- clock_nanosleep; +- } +- GLIBC_PRIVATE { +- __clock_getres; __clock_gettime; __clock_settime; __clock_getcpuclockid; +- __clock_nanosleep; +- } +-} +- + librt { + GLIBC_2.1 { + # AIO functions. +@@ -18,10 +6,6 @@ librt { + aio_suspend64; aio_write; aio_write64; lio_listio; lio_listio64; + } + GLIBC_2.2 { +- # These have moved to libc and are still here only for compatibility. +- clock_getres; clock_gettime; clock_settime; clock_getcpuclockid; +- clock_nanosleep; +- + # s* + shm_open; shm_unlink; + +diff --git a/rt/clock-compat.c b/rt/clock-compat.c +deleted file mode 100644 +index 11e71aa89019b173..0000000000000000 +--- a/rt/clock-compat.c ++++ /dev/null +@@ -1,63 +0,0 @@ +-/* ABI compatibility redirects for clock_* symbols in librt. +- Copyright (C) 2012-2018 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 +- . */ +- +-#include +- +-/* The clock_* symbols were originally defined in librt and so +- are part of its ABI. As of 2.17, they have moved to libc. +- So we supply definitions for librt that just redirect to +- their libc counterparts. */ +- +-#if SHLIB_COMPAT (librt, GLIBC_2_2, GLIBC_2_17) +- +-#include +- +-#if HAVE_IFUNC +-# undef INIT_ARCH +-# define INIT_ARCH() +-# define COMPAT_REDIRECT(name, proto, arglist) libc_ifunc (name, &__##name) \ +- compat_symbol (librt, name, name, GLIBC_2_2); +-#else +-# define COMPAT_REDIRECT(name, proto, arglist) \ +- int \ +- name proto \ +- { \ +- return __##name arglist; \ +- } \ +- compat_symbol (librt, name, name, GLIBC_2_2); +-#endif +- +-COMPAT_REDIRECT (clock_getres, +- (clockid_t clock_id, struct timespec *res), +- (clock_id, res)) +-COMPAT_REDIRECT (clock_gettime, +- (clockid_t clock_id, struct timespec *tp), +- (clock_id, tp)) +-COMPAT_REDIRECT (clock_settime, +- (clockid_t clock_id, const struct timespec *tp), +- (clock_id, tp)) +-COMPAT_REDIRECT (clock_getcpuclockid, +- (pid_t pid, clockid_t *clock_id), +- (pid, clock_id)) +-COMPAT_REDIRECT (clock_nanosleep, +- (clockid_t clock_id, int flags, +- const struct timespec *req, +- struct timespec *rem), +- (clock_id, flags, req, rem)) +- +-#endif +diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist +index e3fc05137b18194b..f89ef9a43251c164 100644 +--- a/sysdeps/mach/hurd/i386/libc.abilist ++++ b/sysdeps/mach/hurd/i386/libc.abilist +@@ -711,6 +711,11 @@ GLIBC_2.2.6 clntudp_bufcreate F + GLIBC_2.2.6 clntudp_create F + GLIBC_2.2.6 clntunix_create F + GLIBC_2.2.6 clock F ++GLIBC_2.2.6 clock_getcpuclockid F ++GLIBC_2.2.6 clock_getres F ++GLIBC_2.2.6 clock_gettime F ++GLIBC_2.2.6 clock_nanosleep F ++GLIBC_2.2.6 clock_settime F + GLIBC_2.2.6 close F + GLIBC_2.2.6 closedir F + GLIBC_2.2.6 closelog F +diff --git a/sysdeps/mach/hurd/i386/librt.abilist b/sysdeps/mach/hurd/i386/librt.abilist +index d5fe32b3a9917254..3726e41f06cc500c 100644 +--- a/sysdeps/mach/hurd/i386/librt.abilist ++++ b/sysdeps/mach/hurd/i386/librt.abilist +@@ -13,11 +13,6 @@ GLIBC_2.2.6 aio_suspend F + GLIBC_2.2.6 aio_suspend64 F + GLIBC_2.2.6 aio_write F + GLIBC_2.2.6 aio_write64 F +-GLIBC_2.2.6 clock_getcpuclockid F +-GLIBC_2.2.6 clock_getres F +-GLIBC_2.2.6 clock_gettime F +-GLIBC_2.2.6 clock_nanosleep F +-GLIBC_2.2.6 clock_settime F + GLIBC_2.2.6 lio_listio F + GLIBC_2.2.6 lio_listio64 F + GLIBC_2.2.6 shm_open F +diff --git a/sysdeps/posix/clock_getres.c b/sysdeps/posix/clock_getres.c +index 5b0d8eb8a1a0593e..7408197420b14aad 100644 +--- a/sysdeps/posix/clock_getres.c ++++ b/sysdeps/posix/clock_getres.c +@@ -22,7 +22,7 @@ + #include + #include + #include +- ++#include + + static inline int + realtime_getres (struct timespec *res) +@@ -62,4 +62,11 @@ __clock_getres (clockid_t clock_id, struct timespec *res) + + return retval; + } +-weak_alias (__clock_getres, clock_getres) ++ ++versioned_symbol (libc, __clock_getres, clock_getres, GLIBC_2_17); ++/* clock_getres moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_getres, __clock_getres_2); ++compat_symbol (libc, __clock_getres_2, clock_getres, GLIBC_2_2); ++#endif +diff --git a/sysdeps/unix/clock_gettime.c b/sysdeps/unix/clock_gettime.c +index f3ebbe15ccc2e95e..3ad8ea87bb7d379b 100644 +--- a/sysdeps/unix/clock_gettime.c ++++ b/sysdeps/unix/clock_gettime.c +@@ -17,24 +17,9 @@ + . */ + + #include +-#include + #include + #include +-#include +-#include +- +- +-static inline int +-realtime_gettime (struct timespec *tp) +-{ +- struct timeval tv; +- int retval = __gettimeofday (&tv, NULL); +- if (retval == 0) +- /* Convert into `timespec'. */ +- TIMEVAL_TO_TIMESPEC (&tv, tp); +- return retval; +-} +- ++#include + + /* Get current value of CLOCK and store it in TP. */ + int +@@ -60,5 +45,12 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp) + + return retval; + } +-weak_alias (__clock_gettime, clock_gettime) + libc_hidden_def (__clock_gettime) ++ ++versioned_symbol (libc, __clock_gettime, clock_gettime, GLIBC_2_17); ++/* clock_gettime moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_gettime, __clock_gettime_2); ++compat_symbol (libc, __clock_gettime_2, clock_gettime, GLIBC_2_2); ++#endif +diff --git a/sysdeps/unix/clock_nanosleep.c b/sysdeps/unix/clock_nanosleep.c +index 13dd0f4b905ec631..6513e2d64614c561 100644 +--- a/sysdeps/unix/clock_nanosleep.c ++++ b/sysdeps/unix/clock_nanosleep.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + + /* This implementation assumes that these is only a `nanosleep' system + call. So we have to remap all other activities. */ +@@ -76,4 +77,11 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req, + + return __nanosleep (req, rem), 0 ? errno : 0; + } +-weak_alias (__clock_nanosleep, clock_nanosleep) ++ ++versioned_symbol (libc, __clock_nanosleep, clock_nanosleep, GLIBC_2_17); ++/* clock_nanosleep moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_nanosleep, __clock_nanosleep_2); ++compat_symbol (libc, __clock_nanosleep_2, clock_nanosleep, GLIBC_2_2); ++#endif +diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/unix/clock_settime.c +index 4f5640f67047cef6..123b6f44ee3831d9 100644 +--- a/sysdeps/unix/clock_settime.c ++++ b/sysdeps/unix/clock_settime.c +@@ -18,8 +18,7 @@ + #include + #include + #include +-#include +- ++#include + + /* Set CLOCK to value TP. */ + int +@@ -51,4 +50,12 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp) + + return retval; + } +-weak_alias (__clock_settime, clock_settime) ++libc_hidden_def (__clock_settime) ++ ++versioned_symbol (libc, __clock_settime, clock_settime, GLIBC_2_17); ++/* clock_settime moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_settime, __clock_settime_2); ++compat_symbol (libc, __clock_settime_2, clock_settime, GLIBC_2_2); ++#endif +diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist +index e22b91655dd5f7e0..77f0432d0f1f5aab 100644 +--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist ++++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist +@@ -1863,6 +1863,11 @@ GLIBC_2.2 __xpg_sigpause F + GLIBC_2.2 _flushlbf F + GLIBC_2.2 _res_hconf D 0x48 + GLIBC_2.2 bind_textdomain_codeset F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 dcngettext F + GLIBC_2.2 dngettext F + GLIBC_2.2 fgetpos F +diff --git a/sysdeps/unix/sysv/linux/alpha/librt.abilist b/sysdeps/unix/sysv/linux/alpha/librt.abilist +index d7a049cf600e2966..71f86e03ce67fd19 100644 +--- a/sysdeps/unix/sysv/linux/alpha/librt.abilist ++++ b/sysdeps/unix/sysv/linux/alpha/librt.abilist +@@ -15,11 +15,6 @@ GLIBC_2.1 aio_write F + GLIBC_2.1 aio_write64 F + GLIBC_2.1 lio_listio F + GLIBC_2.1 lio_listio64 F +-GLIBC_2.2 clock_getcpuclockid F +-GLIBC_2.2 clock_getres F +-GLIBC_2.2 clock_gettime F +-GLIBC_2.2 clock_nanosleep F +-GLIBC_2.2 clock_settime F + GLIBC_2.2 shm_open F + GLIBC_2.2 shm_unlink F + GLIBC_2.2 timer_create F +diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist +index a231812eea6dc556..e748ec28912ce773 100644 +--- a/sysdeps/unix/sysv/linux/arm/libc.abilist ++++ b/sysdeps/unix/sysv/linux/arm/libc.abilist +@@ -759,6 +759,11 @@ GLIBC_2.4 clntudp_bufcreate F + GLIBC_2.4 clntudp_create F + GLIBC_2.4 clntunix_create F + GLIBC_2.4 clock F ++GLIBC_2.4 clock_getcpuclockid F ++GLIBC_2.4 clock_getres F ++GLIBC_2.4 clock_gettime F ++GLIBC_2.4 clock_nanosleep F ++GLIBC_2.4 clock_settime F + GLIBC_2.4 clone F + GLIBC_2.4 close F + GLIBC_2.4 closedir F +diff --git a/sysdeps/unix/sysv/linux/arm/librt.abilist b/sysdeps/unix/sysv/linux/arm/librt.abilist +index cfbbd2755765e720..3c0647b2516bb51d 100644 +--- a/sysdeps/unix/sysv/linux/arm/librt.abilist ++++ b/sysdeps/unix/sysv/linux/arm/librt.abilist +@@ -13,11 +13,6 @@ GLIBC_2.4 aio_suspend F + GLIBC_2.4 aio_suspend64 F + GLIBC_2.4 aio_write F + GLIBC_2.4 aio_write64 F +-GLIBC_2.4 clock_getcpuclockid F +-GLIBC_2.4 clock_getres F +-GLIBC_2.4 clock_gettime F +-GLIBC_2.4 clock_nanosleep F +-GLIBC_2.4 clock_settime F + GLIBC_2.4 lio_listio F + GLIBC_2.4 lio_listio64 F + GLIBC_2.4 mq_close F +diff --git a/sysdeps/unix/sysv/linux/clock_getcpuclockid.c b/sysdeps/unix/sysv/linux/clock_getcpuclockid.c +index 190a47950eb1d177..877f4f3c7916a534 100644 +--- a/sysdeps/unix/sysv/linux/clock_getcpuclockid.c ++++ b/sysdeps/unix/sysv/linux/clock_getcpuclockid.c +@@ -20,6 +20,7 @@ + #include + #include + #include "kernel-posix-cpu-timers.h" ++#include + + int + __clock_getcpuclockid (pid_t pid, clockid_t *clock_id) +@@ -45,4 +46,11 @@ __clock_getcpuclockid (pid_t pid, clockid_t *clock_id) + else + return INTERNAL_SYSCALL_ERRNO (r, err); + } +-weak_alias (__clock_getcpuclockid, clock_getcpuclockid) ++ ++versioned_symbol (libc, __clock_getcpuclockid, clock_getcpuclockid, GLIBC_2_17); ++/* clock_getcpuclockid moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_getcpuclockid, __clock_getcpuclockid_2); ++compat_symbol (libc, __clock_getcpuclockid_2, clock_getcpuclockid, GLIBC_2_2); ++#endif +diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c +index 2517e66910a79d93..1fbb638097ba4a80 100644 +--- a/sysdeps/unix/sysv/linux/clock_getres.c ++++ b/sysdeps/unix/sysv/linux/clock_getres.c +@@ -26,10 +26,19 @@ + #endif + #include + ++#include ++ + /* Get resolution of clock. */ + int + __clock_getres (clockid_t clock_id, struct timespec *res) + { + return INLINE_VSYSCALL (clock_getres, 2, clock_id, res); + } +-weak_alias (__clock_getres, clock_getres) ++ ++versioned_symbol (libc, __clock_getres, clock_getres, GLIBC_2_17); ++/* clock_getres moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_getres, __clock_getres_2); ++compat_symbol (libc, __clock_getres_2, clock_getres, GLIBC_2_2); ++#endif +diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c +index dadfc518b74baea0..3f8feb37a1795306 100644 +--- a/sysdeps/unix/sysv/linux/clock_gettime.c ++++ b/sysdeps/unix/sysv/linux/clock_gettime.c +@@ -26,11 +26,20 @@ + #endif + #include + ++#include ++ + /* Get current value of CLOCK and store it in TP. */ + int + __clock_gettime (clockid_t clock_id, struct timespec *tp) + { + return INLINE_VSYSCALL (clock_gettime, 2, clock_id, tp); + } +-weak_alias (__clock_gettime, clock_gettime) + libc_hidden_def (__clock_gettime) ++ ++versioned_symbol (libc, __clock_gettime, clock_gettime, GLIBC_2_17); ++/* clock_gettime moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_gettime, __clock_gettime_2); ++compat_symbol (libc, __clock_gettime_2, clock_gettime, GLIBC_2_2); ++#endif +diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c +index 93d5d6ef120ca9ef..a90da63069b7f0f8 100644 +--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c ++++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c +@@ -21,6 +21,7 @@ + #include + #include "kernel-posix-cpu-timers.h" + ++#include + + /* We can simply use the syscall. The CPU clocks are not supported + with this function. */ +@@ -51,4 +52,11 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req, + return (INTERNAL_SYSCALL_ERROR_P (r, err) + ? INTERNAL_SYSCALL_ERRNO (r, err) : 0); + } +-weak_alias (__clock_nanosleep, clock_nanosleep) ++ ++versioned_symbol (libc, __clock_nanosleep, clock_nanosleep, GLIBC_2_17); ++/* clock_nanosleep moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_nanosleep, __clock_nanosleep_2); ++compat_symbol (libc, __clock_nanosleep_2, clock_nanosleep, GLIBC_2_2); ++#endif +diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c +index c71461a4f6deac5a..21efc6c982c084b4 100644 +--- a/sysdeps/unix/sysv/linux/clock_settime.c ++++ b/sysdeps/unix/sysv/linux/clock_settime.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + + #include "kernel-posix-cpu-timers.h" + +@@ -34,4 +35,12 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp) + + return INLINE_SYSCALL_CALL (clock_settime, clock_id, tp); + } +-weak_alias (__clock_settime, clock_settime) ++libc_hidden_def (__clock_settime) ++ ++versioned_symbol (libc, __clock_settime, clock_settime, GLIBC_2_17); ++/* clock_settime moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_settime, __clock_settime_2); ++compat_symbol (libc, __clock_settime_2, clock_settime, GLIBC_2_2); ++#endif +diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist +index 24b11b15c0e71140..d34f040d85cc5bb2 100644 +--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist ++++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist +@@ -615,6 +615,11 @@ GLIBC_2.2 clntudp_bufcreate F + GLIBC_2.2 clntudp_create F + GLIBC_2.2 clntunix_create F + GLIBC_2.2 clock F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 clone F + GLIBC_2.2 close F + GLIBC_2.2 closedir F +diff --git a/sysdeps/unix/sysv/linux/hppa/librt.abilist b/sysdeps/unix/sysv/linux/hppa/librt.abilist +index 595f1b712a4e8d70..bb03781dcc04d219 100644 +--- a/sysdeps/unix/sysv/linux/hppa/librt.abilist ++++ b/sysdeps/unix/sysv/linux/hppa/librt.abilist +@@ -15,11 +15,6 @@ GLIBC_2.1 aio_write F + GLIBC_2.1 aio_write64 F + GLIBC_2.1 lio_listio F + GLIBC_2.1 lio_listio64 F +-GLIBC_2.2 clock_getcpuclockid F +-GLIBC_2.2 clock_getres F +-GLIBC_2.2 clock_gettime F +-GLIBC_2.2 clock_nanosleep F +-GLIBC_2.2 clock_settime F + GLIBC_2.2 shm_open F + GLIBC_2.2 shm_unlink F + GLIBC_2.2 timer_create F +diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist +index 9762c81365b0abcd..48e838fc2813df0d 100644 +--- a/sysdeps/unix/sysv/linux/i386/libc.abilist ++++ b/sysdeps/unix/sysv/linux/i386/libc.abilist +@@ -1869,6 +1869,11 @@ GLIBC_2.2 _flushlbf F + GLIBC_2.2 _res_hconf D 0x30 + GLIBC_2.2 alphasort64 F + GLIBC_2.2 bind_textdomain_codeset F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 dcngettext F + GLIBC_2.2 dngettext F + GLIBC_2.2 fgetpos F +diff --git a/sysdeps/unix/sysv/linux/i386/librt.abilist b/sysdeps/unix/sysv/linux/i386/librt.abilist +index 595f1b712a4e8d70..bb03781dcc04d219 100644 +--- a/sysdeps/unix/sysv/linux/i386/librt.abilist ++++ b/sysdeps/unix/sysv/linux/i386/librt.abilist +@@ -15,11 +15,6 @@ GLIBC_2.1 aio_write F + GLIBC_2.1 aio_write64 F + GLIBC_2.1 lio_listio F + GLIBC_2.1 lio_listio64 F +-GLIBC_2.2 clock_getcpuclockid F +-GLIBC_2.2 clock_getres F +-GLIBC_2.2 clock_gettime F +-GLIBC_2.2 clock_nanosleep F +-GLIBC_2.2 clock_settime F + GLIBC_2.2 shm_open F + GLIBC_2.2 shm_unlink F + GLIBC_2.2 timer_create F +diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist +index 50c94adff93b5bb4..e9fe0697b784be64 100644 +--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist ++++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist +@@ -627,6 +627,11 @@ GLIBC_2.2 clntudp_bufcreate F + GLIBC_2.2 clntudp_create F + GLIBC_2.2 clntunix_create F + GLIBC_2.2 clock F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 close F + GLIBC_2.2 closedir F + GLIBC_2.2 closelog F +diff --git a/sysdeps/unix/sysv/linux/ia64/librt.abilist b/sysdeps/unix/sysv/linux/ia64/librt.abilist +index 804622a14abd8ea9..08384c906518837d 100644 +--- a/sysdeps/unix/sysv/linux/ia64/librt.abilist ++++ b/sysdeps/unix/sysv/linux/ia64/librt.abilist +@@ -15,11 +15,6 @@ GLIBC_2.1 aio_write F + GLIBC_2.1 aio_write64 F + GLIBC_2.1 lio_listio F + GLIBC_2.1 lio_listio64 F +-GLIBC_2.2 clock_getcpuclockid F +-GLIBC_2.2 clock_getres F +-GLIBC_2.2 clock_gettime F +-GLIBC_2.2 clock_nanosleep F +-GLIBC_2.2 clock_settime F + GLIBC_2.2 shm_open F + GLIBC_2.2 shm_unlink F + GLIBC_2.2 timer_create F +diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist +index f57be98e494d0701..98f07b79918d1c17 100644 +--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist ++++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist +@@ -748,6 +748,11 @@ GLIBC_2.4 clntudp_bufcreate F + GLIBC_2.4 clntudp_create F + GLIBC_2.4 clntunix_create F + GLIBC_2.4 clock F ++GLIBC_2.4 clock_getcpuclockid F ++GLIBC_2.4 clock_getres F ++GLIBC_2.4 clock_gettime F ++GLIBC_2.4 clock_nanosleep F ++GLIBC_2.4 clock_settime F + GLIBC_2.4 clone F + GLIBC_2.4 close F + GLIBC_2.4 closedir F +diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/librt.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/librt.abilist +index cfbbd2755765e720..3c0647b2516bb51d 100644 +--- a/sysdeps/unix/sysv/linux/m68k/coldfire/librt.abilist ++++ b/sysdeps/unix/sysv/linux/m68k/coldfire/librt.abilist +@@ -13,11 +13,6 @@ GLIBC_2.4 aio_suspend F + GLIBC_2.4 aio_suspend64 F + GLIBC_2.4 aio_write F + GLIBC_2.4 aio_write64 F +-GLIBC_2.4 clock_getcpuclockid F +-GLIBC_2.4 clock_getres F +-GLIBC_2.4 clock_gettime F +-GLIBC_2.4 clock_nanosleep F +-GLIBC_2.4 clock_settime F + GLIBC_2.4 lio_listio F + GLIBC_2.4 lio_listio64 F + GLIBC_2.4 mq_close F +diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist +index ddc7ebca673a466c..6a60d7876120f2f2 100644 +--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist ++++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist +@@ -1825,6 +1825,11 @@ GLIBC_2.2 _flushlbf F + GLIBC_2.2 _res_hconf D 0x30 + GLIBC_2.2 alphasort64 F + GLIBC_2.2 bind_textdomain_codeset F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 dcngettext F + GLIBC_2.2 dngettext F + GLIBC_2.2 fgetpos F +diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/librt.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/librt.abilist +index 595f1b712a4e8d70..bb03781dcc04d219 100644 +--- a/sysdeps/unix/sysv/linux/m68k/m680x0/librt.abilist ++++ b/sysdeps/unix/sysv/linux/m68k/m680x0/librt.abilist +@@ -15,11 +15,6 @@ GLIBC_2.1 aio_write F + GLIBC_2.1 aio_write64 F + GLIBC_2.1 lio_listio F + GLIBC_2.1 lio_listio64 F +-GLIBC_2.2 clock_getcpuclockid F +-GLIBC_2.2 clock_getres F +-GLIBC_2.2 clock_gettime F +-GLIBC_2.2 clock_nanosleep F +-GLIBC_2.2 clock_settime F + GLIBC_2.2 shm_open F + GLIBC_2.2 shm_unlink F + GLIBC_2.2 timer_create F +diff --git a/sysdeps/unix/sysv/linux/microblaze/librt.abilist b/sysdeps/unix/sysv/linux/microblaze/librt.abilist +index fb85d8729e1bc69d..889dfbc0eef5e75a 100644 +--- a/sysdeps/unix/sysv/linux/microblaze/librt.abilist ++++ b/sysdeps/unix/sysv/linux/microblaze/librt.abilist +@@ -14,11 +14,6 @@ GLIBC_2.18 aio_suspend F + GLIBC_2.18 aio_suspend64 F + GLIBC_2.18 aio_write F + GLIBC_2.18 aio_write64 F +-GLIBC_2.18 clock_getcpuclockid F +-GLIBC_2.18 clock_getres F +-GLIBC_2.18 clock_gettime F +-GLIBC_2.18 clock_nanosleep F +-GLIBC_2.18 clock_settime F + GLIBC_2.18 lio_listio F + GLIBC_2.18 lio_listio64 F + GLIBC_2.18 mq_close F +diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist +index dda9797e0ea736f6..34a24582ca7a4a08 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist +@@ -1612,6 +1612,11 @@ GLIBC_2.2 capget F + GLIBC_2.2 capset F + GLIBC_2.2 cbc_crypt F + GLIBC_2.2 clntunix_create F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 creat64 F + GLIBC_2.2 dcngettext F + GLIBC_2.2 des_setparity F +diff --git a/sysdeps/unix/sysv/linux/mips/mips32/librt.abilist b/sysdeps/unix/sysv/linux/mips/mips32/librt.abilist +index 84837c8a2ef02e1b..1539c1cef92bccfd 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips32/librt.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips32/librt.abilist +@@ -13,11 +13,6 @@ GLIBC_2.2 aio_suspend F + GLIBC_2.2 aio_suspend64 F + GLIBC_2.2 aio_write F + GLIBC_2.2 aio_write64 F +-GLIBC_2.2 clock_getcpuclockid F +-GLIBC_2.2 clock_getres F +-GLIBC_2.2 clock_gettime F +-GLIBC_2.2 clock_nanosleep F +-GLIBC_2.2 clock_settime F + GLIBC_2.2 lio_listio F + GLIBC_2.2 lio_listio64 F + GLIBC_2.2 shm_open F +diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist +index 42e930d56595083e..176a57298a45d492 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist +@@ -1610,6 +1610,11 @@ GLIBC_2.2 capget F + GLIBC_2.2 capset F + GLIBC_2.2 cbc_crypt F + GLIBC_2.2 clntunix_create F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 creat64 F + GLIBC_2.2 dcngettext F + GLIBC_2.2 des_setparity F +diff --git a/sysdeps/unix/sysv/linux/mips/mips64/librt.abilist b/sysdeps/unix/sysv/linux/mips/mips64/librt.abilist +index 84837c8a2ef02e1b..1539c1cef92bccfd 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips64/librt.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips64/librt.abilist +@@ -13,11 +13,6 @@ GLIBC_2.2 aio_suspend F + GLIBC_2.2 aio_suspend64 F + GLIBC_2.2 aio_write F + GLIBC_2.2 aio_write64 F +-GLIBC_2.2 clock_getcpuclockid F +-GLIBC_2.2 clock_getres F +-GLIBC_2.2 clock_gettime F +-GLIBC_2.2 clock_nanosleep F +-GLIBC_2.2 clock_settime F + GLIBC_2.2 lio_listio F + GLIBC_2.2 lio_listio64 F + GLIBC_2.2 shm_open F +diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist +index f89b44f3a14d0f85..5a66ffd67e5cf364 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist +@@ -1611,6 +1611,11 @@ GLIBC_2.2 capget F + GLIBC_2.2 capset F + GLIBC_2.2 cbc_crypt F + GLIBC_2.2 clntunix_create F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 creat64 F + GLIBC_2.2 dcngettext F + GLIBC_2.2 des_setparity F +diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist +index 1486af11d755d37e..a817f33695a5230f 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist +@@ -1607,6 +1607,11 @@ GLIBC_2.2 capget F + GLIBC_2.2 capset F + GLIBC_2.2 cbc_crypt F + GLIBC_2.2 clntunix_create F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 creat64 F + GLIBC_2.2 dcngettext F + GLIBC_2.2 des_setparity F +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist +index 45839ed25b0fde5f..d5e121b76e583f4c 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist +@@ -1830,6 +1830,11 @@ GLIBC_2.2 __xstat64 F + GLIBC_2.2 _flushlbf F + GLIBC_2.2 _res_hconf D 0x30 + GLIBC_2.2 bind_textdomain_codeset F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 dcngettext F + GLIBC_2.2 dngettext F + GLIBC_2.2 fgetpos F +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist +index 595f1b712a4e8d70..bb03781dcc04d219 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/librt.abilist +@@ -15,11 +15,6 @@ GLIBC_2.1 aio_write F + GLIBC_2.1 aio_write64 F + GLIBC_2.1 lio_listio F + GLIBC_2.1 lio_listio64 F +-GLIBC_2.2 clock_getcpuclockid F +-GLIBC_2.2 clock_getres F +-GLIBC_2.2 clock_gettime F +-GLIBC_2.2 clock_nanosleep F +-GLIBC_2.2 clock_settime F + GLIBC_2.2 shm_open F + GLIBC_2.2 shm_unlink F + GLIBC_2.2 timer_create F +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist +index 344e5ae87c5d76b2..3dfddbddb3a11180 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist +@@ -1834,6 +1834,11 @@ GLIBC_2.2 __xstat64 F + GLIBC_2.2 _flushlbf F + GLIBC_2.2 _res_hconf D 0x30 + GLIBC_2.2 bind_textdomain_codeset F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 dcngettext F + GLIBC_2.2 dngettext F + GLIBC_2.2 fgetpos F +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist +index 8c1781adf49a7432..06ce341194a37dd4 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist +@@ -670,6 +670,11 @@ GLIBC_2.3 clntudp_bufcreate F + GLIBC_2.3 clntudp_create F + GLIBC_2.3 clntunix_create F + GLIBC_2.3 clock F ++GLIBC_2.3 clock_getcpuclockid F ++GLIBC_2.3 clock_getres F ++GLIBC_2.3 clock_gettime F ++GLIBC_2.3 clock_nanosleep F ++GLIBC_2.3 clock_settime F + GLIBC_2.3 clone F + GLIBC_2.3 close F + GLIBC_2.3 closedir F +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/librt.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/librt.abilist +index e76b7eb49566718b..6a5bd96963e67109 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/librt.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/librt.abilist +@@ -13,11 +13,6 @@ GLIBC_2.3 aio_suspend F + GLIBC_2.3 aio_suspend64 F + GLIBC_2.3 aio_write F + GLIBC_2.3 aio_write64 F +-GLIBC_2.3 clock_getcpuclockid F +-GLIBC_2.3 clock_getres F +-GLIBC_2.3 clock_gettime F +-GLIBC_2.3 clock_nanosleep F +-GLIBC_2.3 clock_settime F + GLIBC_2.3 lio_listio F + GLIBC_2.3 lio_listio64 F + GLIBC_2.3 shm_open F +diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist +index 3a5ec2a1e47b5da5..02ff949c33197774 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist ++++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist +@@ -1829,6 +1829,11 @@ GLIBC_2.2 _flushlbf F + GLIBC_2.2 _res_hconf D 0x30 + GLIBC_2.2 alphasort64 F + GLIBC_2.2 bind_textdomain_codeset F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 dcngettext F + GLIBC_2.2 dngettext F + GLIBC_2.2 fgetpos F +diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/librt.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/librt.abilist +index 595f1b712a4e8d70..bb03781dcc04d219 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-32/librt.abilist ++++ b/sysdeps/unix/sysv/linux/s390/s390-32/librt.abilist +@@ -15,11 +15,6 @@ GLIBC_2.1 aio_write F + GLIBC_2.1 aio_write64 F + GLIBC_2.1 lio_listio F + GLIBC_2.1 lio_listio64 F +-GLIBC_2.2 clock_getcpuclockid F +-GLIBC_2.2 clock_getres F +-GLIBC_2.2 clock_gettime F +-GLIBC_2.2 clock_nanosleep F +-GLIBC_2.2 clock_settime F + GLIBC_2.2 shm_open F + GLIBC_2.2 shm_unlink F + GLIBC_2.2 timer_create F +diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist +index 3b5465558b72f166..96693d41df267e1b 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist ++++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist +@@ -632,6 +632,11 @@ GLIBC_2.2 clntudp_bufcreate F + GLIBC_2.2 clntudp_create F + GLIBC_2.2 clntunix_create F + GLIBC_2.2 clock F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 clone F + GLIBC_2.2 close F + GLIBC_2.2 closedir F +diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/librt.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/librt.abilist +index 41be3bb84b6e4df0..5905498a488359d7 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-64/librt.abilist ++++ b/sysdeps/unix/sysv/linux/s390/s390-64/librt.abilist +@@ -13,11 +13,6 @@ GLIBC_2.2 aio_suspend F + GLIBC_2.2 aio_suspend64 F + GLIBC_2.2 aio_write F + GLIBC_2.2 aio_write64 F +-GLIBC_2.2 clock_getcpuclockid F +-GLIBC_2.2 clock_getres F +-GLIBC_2.2 clock_gettime F +-GLIBC_2.2 clock_nanosleep F +-GLIBC_2.2 clock_settime F + GLIBC_2.2 lio_listio F + GLIBC_2.2 lio_listio64 F + GLIBC_2.2 shm_open F +diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist +index 1f4e648baade9c47..b126bda07a9cc58c 100644 +--- a/sysdeps/unix/sysv/linux/sh/libc.abilist ++++ b/sysdeps/unix/sysv/linux/sh/libc.abilist +@@ -618,6 +618,11 @@ GLIBC_2.2 clntudp_bufcreate F + GLIBC_2.2 clntudp_create F + GLIBC_2.2 clntunix_create F + GLIBC_2.2 clock F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 clone F + GLIBC_2.2 close F + GLIBC_2.2 closedir F +diff --git a/sysdeps/unix/sysv/linux/sh/librt.abilist b/sysdeps/unix/sysv/linux/sh/librt.abilist +index 595f1b712a4e8d70..bb03781dcc04d219 100644 +--- a/sysdeps/unix/sysv/linux/sh/librt.abilist ++++ b/sysdeps/unix/sysv/linux/sh/librt.abilist +@@ -15,11 +15,6 @@ GLIBC_2.1 aio_write F + GLIBC_2.1 aio_write64 F + GLIBC_2.1 lio_listio F + GLIBC_2.1 lio_listio64 F +-GLIBC_2.2 clock_getcpuclockid F +-GLIBC_2.2 clock_getres F +-GLIBC_2.2 clock_gettime F +-GLIBC_2.2 clock_nanosleep F +-GLIBC_2.2 clock_settime F + GLIBC_2.2 shm_open F + GLIBC_2.2 shm_unlink F + GLIBC_2.2 timer_create F +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist +index d308ac8b0527cb3f..63b78d80b333d4b4 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist ++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist +@@ -1826,6 +1826,11 @@ GLIBC_2.2 __xstat64 F + GLIBC_2.2 _flushlbf F + GLIBC_2.2 _res_hconf D 0x30 + GLIBC_2.2 bind_textdomain_codeset F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 dcngettext F + GLIBC_2.2 dngettext F + GLIBC_2.2 fgetpos F +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/librt.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/librt.abilist +index cb874f41477109c3..38f0aad791793010 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc32/librt.abilist ++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/librt.abilist +@@ -15,11 +15,6 @@ GLIBC_2.1 aio_write F + GLIBC_2.1 aio_write64 F + GLIBC_2.1 lio_listio F + GLIBC_2.1 lio_listio64 F +-GLIBC_2.2 clock_getcpuclockid F +-GLIBC_2.2 clock_getres F +-GLIBC_2.2 clock_gettime F +-GLIBC_2.2 clock_nanosleep F +-GLIBC_2.2 clock_settime F + GLIBC_2.2 shm_open F + GLIBC_2.2 shm_unlink F + GLIBC_2.2 timer_create F +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist +index 6731ebfc2877c5c6..a899eb6a92215b47 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist ++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist +@@ -660,6 +660,11 @@ GLIBC_2.2 clntudp_bufcreate F + GLIBC_2.2 clntudp_create F + GLIBC_2.2 clntunix_create F + GLIBC_2.2 clock F ++GLIBC_2.2 clock_getcpuclockid F ++GLIBC_2.2 clock_getres F ++GLIBC_2.2 clock_gettime F ++GLIBC_2.2 clock_nanosleep F ++GLIBC_2.2 clock_settime F + GLIBC_2.2 clone F + GLIBC_2.2 close F + GLIBC_2.2 closedir F +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/librt.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/librt.abilist +index d7a049cf600e2966..71f86e03ce67fd19 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc64/librt.abilist ++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/librt.abilist +@@ -15,11 +15,6 @@ GLIBC_2.1 aio_write F + GLIBC_2.1 aio_write64 F + GLIBC_2.1 lio_listio F + GLIBC_2.1 lio_listio64 F +-GLIBC_2.2 clock_getcpuclockid F +-GLIBC_2.2 clock_getres F +-GLIBC_2.2 clock_gettime F +-GLIBC_2.2 clock_nanosleep F +-GLIBC_2.2 clock_settime F + GLIBC_2.2 shm_open F + GLIBC_2.2 shm_unlink F + GLIBC_2.2 timer_create F +diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +index 816e4a742632ad44..0ebb018e2089c70a 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +@@ -621,6 +621,11 @@ GLIBC_2.2.5 clntudp_bufcreate F + GLIBC_2.2.5 clntudp_create F + GLIBC_2.2.5 clntunix_create F + GLIBC_2.2.5 clock F ++GLIBC_2.2.5 clock_getcpuclockid F ++GLIBC_2.2.5 clock_getres F ++GLIBC_2.2.5 clock_gettime F ++GLIBC_2.2.5 clock_nanosleep F ++GLIBC_2.2.5 clock_settime F + GLIBC_2.2.5 clone F + GLIBC_2.2.5 close F + GLIBC_2.2.5 closedir F +diff --git a/sysdeps/unix/sysv/linux/x86_64/64/librt.abilist b/sysdeps/unix/sysv/linux/x86_64/64/librt.abilist +index e2e8b60bf8e29f55..95e3f22daa06b237 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/64/librt.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/64/librt.abilist +@@ -13,11 +13,6 @@ GLIBC_2.2.5 aio_suspend F + GLIBC_2.2.5 aio_suspend64 F + GLIBC_2.2.5 aio_write F + GLIBC_2.2.5 aio_write64 F +-GLIBC_2.2.5 clock_getcpuclockid F +-GLIBC_2.2.5 clock_getres F +-GLIBC_2.2.5 clock_gettime F +-GLIBC_2.2.5 clock_nanosleep F +-GLIBC_2.2.5 clock_settime F + GLIBC_2.2.5 lio_listio F + GLIBC_2.2.5 lio_listio64 F + GLIBC_2.2.5 shm_open F +diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +index 6fee16a850adc7b8..0b6b3fa98183e5af 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +@@ -660,6 +660,11 @@ GLIBC_2.16 clntudp_create F + GLIBC_2.16 clntunix_create F + GLIBC_2.16 clock F + GLIBC_2.16 clock_adjtime F ++GLIBC_2.16 clock_getcpuclockid F ++GLIBC_2.16 clock_getres F ++GLIBC_2.16 clock_gettime F ++GLIBC_2.16 clock_nanosleep F ++GLIBC_2.16 clock_settime F + GLIBC_2.16 clone F + GLIBC_2.16 close F + GLIBC_2.16 closedir F +diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/librt.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/librt.abilist +index 94e84e4dcfaa85dc..66969fb9ab887756 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/x32/librt.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/x32/librt.abilist +@@ -14,11 +14,6 @@ GLIBC_2.16 aio_suspend F + GLIBC_2.16 aio_suspend64 F + GLIBC_2.16 aio_write F + GLIBC_2.16 aio_write64 F +-GLIBC_2.16 clock_getcpuclockid F +-GLIBC_2.16 clock_getres F +-GLIBC_2.16 clock_gettime F +-GLIBC_2.16 clock_nanosleep F +-GLIBC_2.16 clock_settime F + GLIBC_2.16 lio_listio F + GLIBC_2.16 lio_listio64 F + GLIBC_2.16 mq_close F +diff --git a/time/Makefile b/time/Makefile +index ec3e39dcea75ee51..6a68481a5de1b148 100644 +--- a/time/Makefile ++++ b/time/Makefile +@@ -36,14 +36,18 @@ routines := offtime asctime clock ctime ctime_r difftime \ + stime dysize timegm ftime \ + getdate strptime strptime_l \ + strftime wcsftime strftime_l wcsftime_l \ +- timespec_get ++ timespec_get \ ++ clock_getcpuclockid clock_getres \ ++ clock_gettime clock_settime clock_nanosleep ++ + aux := era alt_digit lc-time-cleanup + + tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \ + tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \ + tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 \ + tst-strptime3 bug-getdate1 tst-strptime-whitespace tst-ftime \ +- tst-tzname tst-y2039 ++ tst-tzname tst-y2039 \ ++ tst-clock tst-clock2 tst-clock_nanosleep tst-cpuclock1 + + include ../Rules + +diff --git a/time/Versions b/time/Versions +index fd838181e4f0969d..8788e192ce358d77 100644 +--- a/time/Versions ++++ b/time/Versions +@@ -49,6 +49,10 @@ libc { + GLIBC_2.2 { + # w* + wcsftime; ++ ++ # c*; actually in librt in version 2.2, moved to libc in 2.17 ++ clock_getres; clock_gettime; clock_settime; clock_getcpuclockid; ++ clock_nanosleep; + } + GLIBC_2.3 { + # these internal names are used by libstdc++ +@@ -65,4 +69,13 @@ libc { + GLIBC_2.16 { + timespec_get; + } ++ GLIBC_2.17 { ++ # c* ++ clock_getres; clock_gettime; clock_settime; clock_getcpuclockid; ++ clock_nanosleep; ++ } ++ GLIBC_PRIVATE { ++ # same as clock_gettime; used in other libraries ++ __clock_gettime; ++ } + } +diff --git a/rt/clock_getcpuclockid.c b/time/clock_getcpuclockid.c +similarity index 75% +rename from rt/clock_getcpuclockid.c +rename to time/clock_getcpuclockid.c +index 6bc42a0863d92d5a..81b86241f7adc6c9 100644 +--- a/rt/clock_getcpuclockid.c ++++ b/time/clock_getcpuclockid.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + int + __clock_getcpuclockid (pid_t pid, clockid_t *clock_id) +@@ -37,4 +38,10 @@ __clock_getcpuclockid (pid_t pid, clockid_t *clock_id) + return ENOENT; + #endif + } +-weak_alias (__clock_getcpuclockid, clock_getcpuclockid) ++versioned_symbol (libc, __clock_getcpuclockid, clock_getcpuclockid, GLIBC_2_17); ++/* clock_getcpuclockid moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_getcpuclockid, __clock_getcpuclockid_2); ++compat_symbol (libc, __clock_getcpuclockid_2, clock_getcpuclockid, GLIBC_2_2); ++#endif +diff --git a/rt/clock_getres.c b/time/clock_getres.c +similarity index 73% +rename from rt/clock_getres.c +rename to time/clock_getres.c +index 816f7b2a907e27ce..e8315393e560b186 100644 +--- a/rt/clock_getres.c ++++ b/time/clock_getres.c +@@ -18,6 +18,7 @@ + + #include + #include ++#include + + /* Get resolution of clock. */ + int +@@ -26,5 +27,13 @@ __clock_getres (clockid_t clock_id, struct timespec *res) + __set_errno (ENOSYS); + return -1; + } +-weak_alias (__clock_getres, clock_getres) ++ ++versioned_symbol (libc, __clock_getres, clock_getres, GLIBC_2_17); ++/* clock_getres moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_getres, __clock_getres_2); ++compat_symbol (libc, __clock_getres_2, clock_getres, GLIBC_2_2); ++#endif ++ + stub_warning (clock_getres) +diff --git a/rt/clock_gettime.c b/time/clock_gettime.c +similarity index 74% +rename from rt/clock_gettime.c +rename to time/clock_gettime.c +index 30a012473f5bc821..4a5f808845351156 100644 +--- a/rt/clock_gettime.c ++++ b/time/clock_gettime.c +@@ -18,6 +18,7 @@ + + #include + #include ++#include + + /* Get current value of CLOCK and store it in TP. */ + int +@@ -26,6 +27,14 @@ __clock_gettime (clockid_t clock_id, struct timespec *tp) + __set_errno (ENOSYS); + return -1; + } +-weak_alias (__clock_gettime, clock_gettime) + libc_hidden_def (__clock_gettime) ++ ++versioned_symbol (libc, __clock_gettime, clock_gettime, GLIBC_2_17); ++/* clock_gettime moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_gettime, __clock_gettime_2); ++compat_symbol (libc, __clock_gettime_2, clock_gettime, GLIBC_2_2); ++#endif ++ + stub_warning (clock_gettime) +diff --git a/rt/clock_nanosleep.c b/time/clock_nanosleep.c +similarity index 76% +rename from rt/clock_nanosleep.c +rename to time/clock_nanosleep.c +index 15aa6f7c4f22e197..a314b169a9455e0d 100644 +--- a/rt/clock_nanosleep.c ++++ b/time/clock_nanosleep.c +@@ -18,6 +18,7 @@ + + #include + #include ++#include + + int + __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req, +@@ -33,5 +34,13 @@ __clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req, + /* Not implemented. */ + return ENOSYS; + } +-weak_alias (__clock_nanosleep, clock_nanosleep) ++ ++versioned_symbol (libc, __clock_nanosleep, clock_nanosleep, GLIBC_2_17); ++/* clock_nanosleep moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_nanosleep, __clock_nanosleep_2); ++compat_symbol (libc, __clock_nanosleep_2, clock_nanosleep, GLIBC_2_2); ++#endif ++ + stub_warning (clock_nanosleep) +diff --git a/rt/clock_settime.c b/time/clock_settime.c +similarity index 71% +rename from rt/clock_settime.c +rename to time/clock_settime.c +index 0b6d4b2a2a0dc46c..2091239448e307f2 100644 +--- a/rt/clock_settime.c ++++ b/time/clock_settime.c +@@ -18,6 +18,7 @@ + + #include + #include ++#include + + /* Set CLOCK to value TP. */ + int +@@ -26,5 +27,14 @@ __clock_settime (clockid_t clock_id, const struct timespec *tp) + __set_errno (ENOSYS); + return -1; + } +-weak_alias (__clock_settime, clock_settime) ++libc_hidden_def (__clock_settime) ++ ++versioned_symbol (libc, __clock_settime, clock_settime, GLIBC_2_17); ++/* clock_settime moved to libc in version 2.17; ++ old binaries may expect the symbol version it had in librt. */ ++#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) ++strong_alias (__clock_settime, __clock_settime_2); ++compat_symbol (libc, __clock_settime_2, clock_settime, GLIBC_2_2); ++#endif ++ + stub_warning (clock_settime) +diff --git a/rt/tst-clock.c b/time/tst-clock.c +similarity index 100% +rename from rt/tst-clock.c +rename to time/tst-clock.c +diff --git a/rt/tst-clock2.c b/time/tst-clock2.c +similarity index 100% +rename from rt/tst-clock2.c +rename to time/tst-clock2.c +diff --git a/rt/tst-clock_nanosleep.c b/time/tst-clock_nanosleep.c +similarity index 100% +rename from rt/tst-clock_nanosleep.c +rename to time/tst-clock_nanosleep.c +diff --git a/rt/tst-cpuclock1.c b/time/tst-cpuclock1.c +similarity index 100% +rename from rt/tst-cpuclock1.c +rename to time/tst-cpuclock1.c diff --git a/glibc-rh1749439-1.patch b/glibc-rh1749439-1.patch new file mode 100755 index 0000000..18b7195 --- /dev/null +++ b/glibc-rh1749439-1.patch @@ -0,0 +1,512 @@ +commit 1a7fe2ebe52b3c8bf465d1756e69452d05c1c103 +Author: Florian Weimer +Date: Mon Aug 5 15:54:10 2019 +0200 + + login: Remove utmp backend jump tables [BZ #23518] + + There is just one file-based implementation, so this dispatch + mechanism is unnecessary. Instead of the vtable pointer + __libc_utmp_jump_table, use a non-negative file_fd as the indicator + that the backend is initialized. + +diff --git a/login/getutent_r.c b/login/getutent_r.c +index 6a244ba6e0b86da7..44239ecb81bacea4 100644 +--- a/login/getutent_r.c ++++ b/login/getutent_r.c +@@ -23,115 +23,16 @@ + + #include "utmp-private.h" + +- +-/* Functions defined here. */ +-static int setutent_unknown (void); +-static int getutent_r_unknown (struct utmp *buffer, struct utmp **result); +-static int getutid_r_unknown (const struct utmp *line, struct utmp *buffer, +- struct utmp **result); +-static int getutline_r_unknown (const struct utmp *id, struct utmp *buffer, +- struct utmp **result); +-static struct utmp *pututline_unknown (const struct utmp *data); +-static void endutent_unknown (void); +- +-/* Initial Jump table. */ +-const struct utfuncs __libc_utmp_unknown_functions = +-{ +- setutent_unknown, +- getutent_r_unknown, +- getutid_r_unknown, +- getutline_r_unknown, +- pututline_unknown, +- endutent_unknown, +- NULL +-}; +- +-/* Currently selected backend. */ +-const struct utfuncs *__libc_utmp_jump_table = &__libc_utmp_unknown_functions; +- + /* We need to protect the opening of the file. */ + __libc_lock_define_initialized (, __libc_utmp_lock attribute_hidden) + + +-static int +-setutent_unknown (void) +-{ +- int result; +- +- result = (*__libc_utmp_file_functions.setutent) (); +- if (result) +- __libc_utmp_jump_table = &__libc_utmp_file_functions; +- +- return result; +-} +- +- +-static int +-getutent_r_unknown (struct utmp *buffer, struct utmp **result) +-{ +- /* The backend was not yet initialized. */ +- if (setutent_unknown ()) +- return (*__libc_utmp_jump_table->getutent_r) (buffer, result); +- +- /* Not available. */ +- *result = NULL; +- return -1; +-} +- +- +-static int +-getutid_r_unknown (const struct utmp *id, struct utmp *buffer, +- struct utmp **result) +-{ +- /* The backend was not yet initialized. */ +- if (setutent_unknown ()) +- return (*__libc_utmp_jump_table->getutid_r) (id, buffer, result); +- +- /* Not available. */ +- *result = NULL; +- return -1; +-} +- +- +-static int +-getutline_r_unknown (const struct utmp *line, struct utmp *buffer, +- struct utmp **result) +-{ +- /* The backend was not yet initialized. */ +- if (setutent_unknown ()) +- return (*__libc_utmp_jump_table->getutline_r) (line, buffer, result); +- +- /* Not available. */ +- *result = NULL; +- return -1; +-} +- +- +-static struct utmp * +-pututline_unknown (const struct utmp *data) +-{ +- /* The backend was not yet initialized. */ +- if (setutent_unknown ()) +- return (*__libc_utmp_jump_table->pututline) (data); +- +- /* Not available. */ +- return NULL; +-} +- +- +-static void +-endutent_unknown (void) +-{ +- /* Nothing to do. */ +-} +- +- + void + __setutent (void) + { + __libc_lock_lock (__libc_utmp_lock); + +- (*__libc_utmp_jump_table->setutent) (); ++ __libc_setutent (); + + __libc_lock_unlock (__libc_utmp_lock); + } +@@ -145,7 +46,7 @@ __getutent_r (struct utmp *buffer, struct utmp **result) + + __libc_lock_lock (__libc_utmp_lock); + +- retval = (*__libc_utmp_jump_table->getutent_r) (buffer, result); ++ retval = __libc_getutent_r (buffer, result); + + __libc_lock_unlock (__libc_utmp_lock); + +@@ -162,7 +63,7 @@ __pututline (const struct utmp *data) + + __libc_lock_lock (__libc_utmp_lock); + +- buffer = (*__libc_utmp_jump_table->pututline) (data); ++ buffer = __libc_pututline (data); + + __libc_lock_unlock (__libc_utmp_lock); + +@@ -177,8 +78,7 @@ __endutent (void) + { + __libc_lock_lock (__libc_utmp_lock); + +- (*__libc_utmp_jump_table->endutent) (); +- __libc_utmp_jump_table = &__libc_utmp_unknown_functions; ++ __libc_endutent (); + + __libc_lock_unlock (__libc_utmp_lock); + } +diff --git a/login/getutid_r.c b/login/getutid_r.c +index b7d3dbac75774b0a..8cb6b16d735e8265 100644 +--- a/login/getutid_r.c ++++ b/login/getutid_r.c +@@ -49,7 +49,7 @@ __getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result) + + __libc_lock_lock (__libc_utmp_lock); + +- retval = (*__libc_utmp_jump_table->getutid_r) (id, buffer, result); ++ retval = __libc_getutid_r (id, buffer, result); + + __libc_lock_unlock (__libc_utmp_lock); + +diff --git a/login/getutline_r.c b/login/getutline_r.c +index 6996887f76b28816..5607c19ed2e1ca66 100644 +--- a/login/getutline_r.c ++++ b/login/getutline_r.c +@@ -36,7 +36,7 @@ __getutline_r (const struct utmp *line, struct utmp *buffer, + + __libc_lock_lock (__libc_utmp_lock); + +- retval = (*__libc_utmp_jump_table->getutline_r) (line, buffer, result); ++ retval = __libc_getutline_r (line, buffer, result); + + __libc_lock_unlock (__libc_utmp_lock); + +diff --git a/login/updwtmp.c b/login/updwtmp.c +index 56fb41916a776c0a..7ae96224ca789b6d 100644 +--- a/login/updwtmp.c ++++ b/login/updwtmp.c +@@ -29,7 +29,7 @@ __updwtmp (const char *wtmp_file, const struct utmp *utmp) + { + const char *file_name = TRANSFORM_UTMP_FILE_NAME (wtmp_file); + +- (*__libc_utmp_file_functions.updwtmp) (file_name, utmp); ++ __libc_updwtmp (file_name, utmp); + } + libc_hidden_def (__updwtmp) + weak_alias (__updwtmp, updwtmp) +diff --git a/login/utmp-private.h b/login/utmp-private.h +index bd8773984cfc56de..5c2048ee52dc3cee 100644 +--- a/login/utmp-private.h ++++ b/login/utmp-private.h +@@ -24,24 +24,17 @@ + #include + #include + +-/* The structure describing the functions in a backend. */ +-struct utfuncs +-{ +- int (*setutent) (void); +- int (*getutent_r) (struct utmp *, struct utmp **); +- int (*getutid_r) (const struct utmp *, struct utmp *, struct utmp **); +- int (*getutline_r) (const struct utmp *, struct utmp *, struct utmp **); +- struct utmp *(*pututline) (const struct utmp *); +- void (*endutent) (void); +- int (*updwtmp) (const char *, const struct utmp *); +-}; +- +-/* The tables from the services. */ +-extern const struct utfuncs __libc_utmp_file_functions attribute_hidden; +-extern const struct utfuncs __libc_utmp_unknown_functions attribute_hidden; +- +-/* Currently selected backend. */ +-extern const struct utfuncs *__libc_utmp_jump_table attribute_hidden; ++/* These functions check for initialization, but not perform any ++ locking. */ ++int __libc_setutent (void) attribute_hidden; ++int __libc_getutent_r (struct utmp *, struct utmp **) attribute_hidden; ++int __libc_getutid_r (const struct utmp *, struct utmp *, struct utmp **) ++ attribute_hidden; ++int __libc_getutline_r (const struct utmp *, struct utmp *, struct utmp **) ++ attribute_hidden; ++struct utmp *__libc_pututline (const struct utmp *) attribute_hidden; ++void __libc_endutent (void) attribute_hidden; ++int __libc_updwtmp (const char *, const struct utmp *) attribute_hidden; + + /* Current file name. */ + extern const char *__libc_utmp_file_name attribute_hidden; +diff --git a/login/utmp_file.c b/login/utmp_file.c +index 040a5057116bb69d..069e6d0452e333ad 100644 +--- a/login/utmp_file.c ++++ b/login/utmp_file.c +@@ -105,37 +105,12 @@ static void timeout_handler (int signum) {}; + alarm (old_timeout); \ + } while (0) + +- +-/* Functions defined here. */ +-static int setutent_file (void); +-static int getutent_r_file (struct utmp *buffer, struct utmp **result); +-static int getutid_r_file (const struct utmp *key, struct utmp *buffer, +- struct utmp **result); +-static int getutline_r_file (const struct utmp *key, struct utmp *buffer, +- struct utmp **result); +-static struct utmp *pututline_file (const struct utmp *data); +-static void endutent_file (void); +-static int updwtmp_file (const char *file, const struct utmp *utmp); +- +-/* Jump table for file functions. */ +-const struct utfuncs __libc_utmp_file_functions = +-{ +- setutent_file, +- getutent_r_file, +- getutid_r_file, +- getutline_r_file, +- pututline_file, +- endutent_file, +- updwtmp_file +-}; +- +- + #ifndef TRANSFORM_UTMP_FILE_NAME + # define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name) + #endif + +-static int +-setutent_file (void) ++int ++__libc_setutent (void) + { + if (file_fd < 0) + { +@@ -166,15 +141,19 @@ setutent_file (void) + return 1; + } + ++/* Preform initialization if necessary. */ ++static bool ++maybe_setutent (void) ++{ ++ return file_fd >= 0 || __libc_setutent (); ++} + +-static int +-getutent_r_file (struct utmp *buffer, struct utmp **result) ++int ++__libc_getutent_r (struct utmp *buffer, struct utmp **result) + { + ssize_t nbytes; + +- assert (file_fd >= 0); +- +- if (file_offset == -1l) ++ if (!maybe_setutent () || file_offset == -1l) + { + /* Not available. */ + *result = NULL; +@@ -279,13 +258,11 @@ unlock_return: + + /* For implementing this function we don't use the getutent_r function + because we can avoid the reposition on every new entry this way. */ +-static int +-getutid_r_file (const struct utmp *id, struct utmp *buffer, +- struct utmp **result) ++int ++__libc_getutid_r (const struct utmp *id, struct utmp *buffer, ++ struct utmp **result) + { +- assert (file_fd >= 0); +- +- if (file_offset == -1l) ++ if (!maybe_setutent () || file_offset == -1l) + { + *result = NULL; + return -1; +@@ -309,13 +286,11 @@ getutid_r_file (const struct utmp *id, struct utmp *buffer, + + /* For implementing this function we don't use the getutent_r function + because we can avoid the reposition on every new entry this way. */ +-static int +-getutline_r_file (const struct utmp *line, struct utmp *buffer, +- struct utmp **result) ++int ++__libc_getutline_r (const struct utmp *line, struct utmp *buffer, ++ struct utmp **result) + { +- assert (file_fd >= 0); +- +- if (file_offset == -1l) ++ if (!maybe_setutent () || file_offset == -1l) + { + *result = NULL; + return -1; +@@ -361,15 +336,16 @@ unlock_return: + } + + +-static struct utmp * +-pututline_file (const struct utmp *data) ++struct utmp * ++__libc_pututline (const struct utmp *data) + { ++ if (!maybe_setutent ()) ++ return NULL; ++ + struct utmp buffer; + struct utmp *pbuf; + int found; + +- assert (file_fd >= 0); +- + if (! file_writable) + { + /* We must make the file descriptor writable before going on. */ +@@ -467,18 +443,19 @@ pututline_file (const struct utmp *data) + } + + +-static void +-endutent_file (void) ++void ++__libc_endutent (void) + { +- assert (file_fd >= 0); +- +- __close_nocancel_nostatus (file_fd); +- file_fd = -1; ++ if (file_fd >= 0) ++ { ++ __close_nocancel_nostatus (file_fd); ++ file_fd = -1; ++ } + } + + +-static int +-updwtmp_file (const char *file, const struct utmp *utmp) ++int ++__libc_updwtmp (const char *file, const struct utmp *utmp) + { + int result = -1; + off64_t offset; +diff --git a/login/utmpname.c b/login/utmpname.c +index 21cb890a1a2fdc92..73b19c33ceab4dd7 100644 +--- a/login/utmpname.c ++++ b/login/utmpname.c +@@ -42,8 +42,7 @@ __utmpname (const char *file) + __libc_lock_lock (__libc_utmp_lock); + + /* Close the old file. */ +- (*__libc_utmp_jump_table->endutent) (); +- __libc_utmp_jump_table = &__libc_utmp_unknown_functions; ++ __libc_endutent (); + + if (strcmp (file, __libc_utmp_file_name) != 0) + { +diff --git a/manual/users.texi b/manual/users.texi +index 4ed79ba26fc8e9d0..a006bb58acfd0568 100644 +--- a/manual/users.texi ++++ b/manual/users.texi +@@ -894,9 +894,9 @@ The @code{getlogin} function is declared in @file{unistd.h}, while + @c ttyname_r dup @ascuheap @acsmem @acsfd + @c strncpy dup ok + @c libc_lock_lock dup @asulock @aculock +-@c *libc_utmp_jump_table->setutent dup @mtasurace:utent @acsfd +-@c *libc_utmp_jump_table->getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer +-@c *libc_utmp_jump_table->endutent dup @mtasurace:utent @asulock @aculock ++@c __libc_setutent dup @mtasurace:utent @acsfd ++@c __libc_getutline_r dup @mtasurace:utent @mtascusig:ALRM @mtascutimer ++@c __libc_endutent dup @mtasurace:utent @asulock @aculock + @c libc_lock_unlock dup ok + @c strlen dup ok + @c memcpy dup ok +@@ -1111,7 +1111,7 @@ compatibility only, @file{utmp.h} defines @code{ut_time} as an alias for + + @c setutent @mtasurace:utent @asulock @aculock @acsfd + @c libc_lock_lock dup @asulock @aculock +-@c *libc_utmp_jump_table->setutent @mtasurace:utent @acsfd ++@c __libc_setutent @mtasurace:utent @acsfd + @c setutent_unknown @mtasurace:utent @acsfd + @c *libc_utmp_file_functions.setutent = setutent_file @mtasurace:utent @acsfd + @c open_not_cancel_2 dup @acsfd +@@ -1152,7 +1152,7 @@ A null pointer is returned in case no further entry is available. + @safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} + @c endutent @mtasurace:utent @asulock @aculock @acsfd + @c libc_lock_lock dup @asulock @aculock +-@c *libc_utmp_jump_table->endutent @mtasurace:utent @acsfd ++@c __libc_endutent @mtasurace:utent @acsfd + @c endutent_unknown ok + @c endutent_file @mtasurace:utent @acsfd + @c close_not_cancel_no_status dup @acsfd +@@ -1230,7 +1230,7 @@ over again. + @safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} + @c pututline @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd + @c libc_lock_lock dup @asulock @aculock +-@c *libc_utmp_jump_table->pututline @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd ++@c __libc_pututline @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd + @c pututline_unknown @mtasurace:utent @acsfd + @c setutent_unknown dup @mtasurace:utent @acsfd + @c pututline_file @mtascusig:ALRM @mtascutimer @acsfd +@@ -1282,7 +1282,7 @@ user-provided buffer. + @safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} + @c getutent_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd + @c libc_lock_lock dup @asulock @aculock +-@c *libc_utmp_jump_table->getutent_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd ++@c __libc_getutent_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd + @c getutent_r_unknown @mtasurace:utent @acsfd + @c setutent_unknown dup @mtasurace:utent @acsfd + @c getutent_r_file @mtasurace:utent @mtascusig:ALRM @mtascutimer +@@ -1319,7 +1319,7 @@ This function is a GNU extension. + @safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} + @c getutid_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd + @c libc_lock_lock dup @asulock @aculock +-@c *libc_utmp_jump_table->getutid_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd ++@c __libc_getutid_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd + @c getutid_r_unknown @mtasurace:utent @acsfd + @c setutent_unknown dup @mtasurace:utent @acsfd + @c getutid_r_file @mtascusig:ALRM @mtascutimer +@@ -1349,7 +1349,7 @@ This function is a GNU extension. + @safety{@prelim{}@mtunsafe{@mtasurace{:utent} @mtascusig{:ALRM} @mtascutimer{}}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{}}} + @c getutline_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @asulock @aculock @acsfd + @c libc_lock_lock dup @asulock @aculock +-@c *libc_utmp_jump_table->getutline_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd ++@c __libc_getutline_r @mtasurace:utent @mtascusig:ALRM @mtascutimer @acsfd + @c getutline_r_unknown @mtasurace:utent @acsfd + @c setutent_unknown dup @mtasurace:utent @acsfd + @c getutline_r_file @mtasurace:utent @mtascusig:ALRM @mtascutimer +@@ -1393,7 +1393,7 @@ be used. + @safety{@prelim{}@mtunsafe{@mtasurace{:utent}}@asunsafe{@asulock{} @ascuheap{}}@acunsafe{@aculock{} @acsmem{}}} + @c utmpname @mtasurace:utent @asulock @ascuheap @aculock @acsmem + @c libc_lock_lock dup @asulock @aculock +-@c *libc_utmp_jump_table->endutent dup @mtasurace:utent ++@c __libc_endutent dup @mtasurace:utent + @c strcmp dup ok + @c free dup @ascuheap @acsmem + @c strdup dup @ascuheap @acsmem +diff --git a/sysdeps/unix/getlogin_r.c b/sysdeps/unix/getlogin_r.c +index 444df7e4d3210cf6..180c0bbca13d0f87 100644 +--- a/sysdeps/unix/getlogin_r.c ++++ b/sysdeps/unix/getlogin_r.c +@@ -64,8 +64,8 @@ __getlogin_r (char *name, size_t name_len) + held so that our search is thread-safe. */ + + __libc_lock_lock (__libc_utmp_lock); +- (*__libc_utmp_jump_table->setutent) (); +- result = (*__libc_utmp_jump_table->getutline_r) (&line, &buffer, &ut); ++ __libc_setutent (); ++ result = __libc_getutline_r (&line, &buffer, &ut); + if (result < 0) + { + if (errno == ESRCH) +@@ -74,8 +74,7 @@ __getlogin_r (char *name, size_t name_len) + else + result = errno; + } +- (*__libc_utmp_jump_table->endutent) (); +- __libc_utmp_jump_table = &__libc_utmp_unknown_functions; ++ __libc_endutent (); + __libc_lock_unlock (__libc_utmp_lock); + + if (result == 0) diff --git a/glibc-rh1749439-10.patch b/glibc-rh1749439-10.patch new file mode 100755 index 0000000..92741c7 --- /dev/null +++ b/glibc-rh1749439-10.patch @@ -0,0 +1,389 @@ +commit be6b16d975683e6cca57852cd4cfe715b2a9d8b1 +Author: Florian Weimer +Date: Thu Nov 7 18:15:18 2019 +0100 + + login: Acquire write lock early in pututline [BZ #24882] + + It has been reported that due to lack of fairness in POSIX file + locking, the current reader-to-writer lock upgrade can result in + lack of forward progress. Acquiring the write lock directly + hopefully avoids this issue if there are only writers. + + This also fixes bug 24882 due to the cache revalidation in + __libc_pututline. + + Reviewed-by: Carlos O'Donell + Change-Id: I57e31ae30719e609a53505a0924dda101d46372e + +diff --git a/login/Makefile b/login/Makefile +index 82132c83fd799357..030cf489b2e037d4 100644 +--- a/login/Makefile ++++ b/login/Makefile +@@ -44,7 +44,7 @@ subdir-dirs = programs + vpath %.c programs + + tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx \ +- tst-pututxline-lockfail ++ tst-pututxline-lockfail tst-pututxline-cache + + # Build the -lutil library with these extra functions. + extra-libs := libutil +@@ -74,3 +74,4 @@ $(inst_libexecdir)/pt_chown: $(objpfx)pt_chown $(+force) + -$(INSTALL_PROGRAM) -m 4755 -o root $< $@ + + $(objpfx)tst-pututxline-lockfail: $(shared-thread-library) ++$(objpfx)tst-pututxline-cache: $(shared-thread-library) +diff --git a/login/tst-pututxline-cache.c b/login/tst-pututxline-cache.c +new file mode 100644 +index 0000000000000000..3f30dd1776711769 +--- /dev/null ++++ b/login/tst-pututxline-cache.c +@@ -0,0 +1,193 @@ ++/* Test case for cache invalidation after concurrent write (bug 24882). ++ 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; see the file COPYING.LIB. If ++ not, see . */ ++ ++/* This test writes an entry to the utmpx file, reads it (so that it ++ is cached) in process1, and overwrites the same entry in process2 ++ with something that does not match the search criteria. At this ++ point, the cache of the first process is stale, and when process1 ++ attempts to write a new record which would have gone to the same ++ place (as indicated by the cache), it needs to realize that it has ++ to pick a different slot because the old slot is now used for ++ something else. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Set to the path of the utmp file. */ ++static char *utmp_file; ++ ++/* Used to synchronize the subprocesses. The barrier itself is ++ allocated in shared memory. */ ++static pthread_barrier_t *barrier; ++ ++/* setutxent with error checking. */ ++static void ++xsetutxent (void) ++{ ++ errno = 0; ++ setutxent (); ++ TEST_COMPARE (errno, 0); ++} ++ ++/* getutxent with error checking. */ ++static struct utmpx * ++xgetutxent (void) ++{ ++ errno = 0; ++ struct utmpx *result = getutxent (); ++ if (result == NULL) ++ FAIL_EXIT1 ("getutxent: %m"); ++ return result; ++} ++ ++static void ++put_entry (const char *id, pid_t pid, const char *user, const char *line) ++{ ++ struct utmpx ut = ++ { ++ .ut_type = LOGIN_PROCESS, ++ .ut_pid = pid, ++ .ut_host = "localhost", ++ }; ++ strcpy (ut.ut_id, id); ++ strncpy (ut.ut_user, user, sizeof (ut.ut_user)); ++ strncpy (ut.ut_line, line, sizeof (ut.ut_line)); ++ TEST_VERIFY (pututxline (&ut) != NULL); ++} ++ ++/* Use two cooperating subprocesses to avoid issues related to ++ unlock-on-close semantics of POSIX advisory locks. */ ++ ++static __attribute__ ((noreturn)) void ++process1 (void) ++{ ++ TEST_COMPARE (utmpname (utmp_file), 0); ++ ++ /* Create an entry. */ ++ xsetutxent (); ++ put_entry ("1", 101, "root", "process1"); ++ ++ /* Retrieve the entry. This will fill the internal cache. */ ++ { ++ errno = 0; ++ setutxent (); ++ TEST_COMPARE (errno, 0); ++ struct utmpx ut = ++ { ++ .ut_type = LOGIN_PROCESS, ++ .ut_line = "process1", ++ }; ++ struct utmpx *result = getutxline (&ut); ++ if (result == NULL) ++ FAIL_EXIT1 ("getutxline (\"process1\"): %m"); ++ TEST_COMPARE (result->ut_pid, 101); ++ } ++ ++ /* Signal the other process to overwrite the entry. */ ++ xpthread_barrier_wait (barrier); ++ ++ /* Wait for the other process to complete the write operation. */ ++ xpthread_barrier_wait (barrier); ++ ++ /* Add another entry. Note: This time, there is no setutxent call. */ ++ put_entry ("1", 103, "root", "process1"); ++ ++ _exit (0); ++} ++ ++static void ++process2 (void *closure) ++{ ++ /* Wait for the first process to write its entry. */ ++ xpthread_barrier_wait (barrier); ++ ++ /* Truncate the file. The glibc interface does not support ++ re-purposing records, but an external expiration mechanism may ++ trigger this. */ ++ TEST_COMPARE (truncate64 (utmp_file, 0), 0); ++ ++ /* Write the replacement entry. */ ++ TEST_COMPARE (utmpname (utmp_file), 0); ++ xsetutxent (); ++ put_entry ("2", 102, "user", "process2"); ++ ++ /* Signal the other process that the entry has been replaced. */ ++ xpthread_barrier_wait (barrier); ++} ++ ++static int ++do_test (void) ++{ ++ xclose (create_temp_file ("tst-tumpx-cache-write-", &utmp_file)); ++ { ++ pthread_barrierattr_t attr; ++ xpthread_barrierattr_init (&attr); ++ xpthread_barrierattr_setpshared (&attr, PTHREAD_SCOPE_PROCESS); ++ barrier = support_shared_allocate (sizeof (*barrier)); ++ xpthread_barrier_init (barrier, &attr, 2); ++ } ++ ++ /* Run both subprocesses in parallel. */ ++ { ++ pid_t pid1 = xfork (); ++ if (pid1 == 0) ++ process1 (); ++ support_isolate_in_subprocess (process2, NULL); ++ int status; ++ xwaitpid (pid1, &status, 0); ++ TEST_COMPARE (status, 0); ++ } ++ ++ /* Check that the utmpx database contains the expected records. */ ++ { ++ TEST_COMPARE (utmpname (utmp_file), 0); ++ xsetutxent (); ++ ++ struct utmpx *ut = xgetutxent (); ++ TEST_COMPARE_STRING (ut->ut_id, "2"); ++ TEST_COMPARE (ut->ut_pid, 102); ++ TEST_COMPARE_STRING (ut->ut_user, "user"); ++ TEST_COMPARE_STRING (ut->ut_line, "process2"); ++ ++ ut = xgetutxent (); ++ TEST_COMPARE_STRING (ut->ut_id, "1"); ++ TEST_COMPARE (ut->ut_pid, 103); ++ TEST_COMPARE_STRING (ut->ut_user, "root"); ++ TEST_COMPARE_STRING (ut->ut_line, "process1"); ++ ++ if (getutxent () != NULL) ++ FAIL_EXIT1 ("additional utmpx entry"); ++ } ++ ++ xpthread_barrier_destroy (barrier); ++ support_shared_free (barrier); ++ free (utmp_file); ++ ++ return 0; ++} ++ ++#include +diff --git a/login/utmp_file.c b/login/utmp_file.c +index 9ad80364682bae92..6bba120db9cc574e 100644 +--- a/login/utmp_file.c ++++ b/login/utmp_file.c +@@ -186,19 +186,11 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result) + + + /* Search for *ID, updating last_entry and file_offset. Return 0 on +- success and -1 on failure. If the locking operation failed, write +- true to *LOCK_FAILED. */ ++ success and -1 on failure. Does not perform locking; for that see ++ internal_getut_r below. */ + static int +-internal_getut_r (const struct utmp *id, bool *lock_failed) ++internal_getut_nolock (const struct utmp *id) + { +- int result = -1; +- +- if (try_file_lock (file_fd, F_RDLCK)) +- { +- *lock_failed = true; +- return -1; +- } +- + if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME + || id->ut_type == OLD_TIME || id->ut_type == NEW_TIME) + { +@@ -213,7 +205,7 @@ internal_getut_r (const struct utmp *id, bool *lock_failed) + { + __set_errno (ESRCH); + file_offset = -1l; +- goto unlock_return; ++ return -1; + } + file_offset += sizeof (struct utmp); + +@@ -234,7 +226,7 @@ internal_getut_r (const struct utmp *id, bool *lock_failed) + { + __set_errno (ESRCH); + file_offset = -1l; +- goto unlock_return; ++ return -1; + } + file_offset += sizeof (struct utmp); + +@@ -243,15 +235,26 @@ internal_getut_r (const struct utmp *id, bool *lock_failed) + } + } + +- result = 0; ++ return 0; ++} + +-unlock_return: +- file_unlock (file_fd); ++/* Search for *ID, updating last_entry and file_offset. Return 0 on ++ success and -1 on failure. If the locking operation failed, write ++ true to *LOCK_FAILED. */ ++static int ++internal_getut_r (const struct utmp *id, bool *lock_failed) ++{ ++ if (try_file_lock (file_fd, F_RDLCK)) ++ { ++ *lock_failed = true; ++ return -1; ++ } + ++ int result = internal_getut_nolock (id); ++ file_unlock (file_fd); + return result; + } + +- + /* For implementing this function we don't use the getutent_r function + because we can avoid the reposition on every new entry this way. */ + int +@@ -279,7 +282,6 @@ __libc_getutid_r (const struct utmp *id, struct utmp *buffer, + return 0; + } + +- + /* For implementing this function we don't use the getutent_r function + because we can avoid the reposition on every new entry this way. */ + int +@@ -336,7 +338,6 @@ __libc_pututline (const struct utmp *data) + return NULL; + + struct utmp *pbuf; +- int found; + + if (! file_writable) + { +@@ -358,7 +359,12 @@ __libc_pututline (const struct utmp *data) + file_writable = true; + } + ++ /* Exclude other writers before validating the cache. */ ++ if (try_file_lock (file_fd, F_WRLCK)) ++ return NULL; ++ + /* Find the correct place to insert the data. */ ++ bool found = false; + if (file_offset > 0 + && ((last_entry.ut_type == data->ut_type + && (last_entry.ut_type == RUN_LVL +@@ -366,23 +372,30 @@ __libc_pututline (const struct utmp *data) + || last_entry.ut_type == OLD_TIME + || last_entry.ut_type == NEW_TIME)) + || __utmp_equal (&last_entry, data))) +- found = 1; +- else + { +- bool lock_failed = false; +- found = internal_getut_r (data, &lock_failed); +- +- if (__builtin_expect (lock_failed, false)) ++ if (__lseek64 (file_fd, file_offset, SEEK_SET) < 0) + { +- __set_errno (EAGAIN); ++ file_unlock (file_fd); + return NULL; + } ++ if (__read_nocancel (file_fd, &last_entry, sizeof (last_entry)) ++ != sizeof (last_entry)) ++ { ++ if (__lseek64 (file_fd, file_offset, SEEK_SET) < 0) ++ { ++ file_unlock (file_fd); ++ return NULL; ++ } ++ found = false; ++ } ++ else ++ found = __utmp_equal (&last_entry, data); + } + +- if (try_file_lock (file_fd, F_WRLCK)) +- return NULL; ++ if (!found) ++ found = internal_getut_nolock (data) >= 0; + +- if (found < 0) ++ if (!found) + { + /* We append the next entry. */ + file_offset = __lseek64 (file_fd, 0, SEEK_END); +@@ -411,7 +424,7 @@ __libc_pututline (const struct utmp *data) + { + /* If we appended a new record this is only partially written. + Remove it. */ +- if (found < 0) ++ if (!found) + (void) __ftruncate64 (file_fd, file_offset); + pbuf = NULL; + } diff --git a/glibc-rh1749439-11.patch b/glibc-rh1749439-11.patch new file mode 100755 index 0000000..d1289d6 --- /dev/null +++ b/glibc-rh1749439-11.patch @@ -0,0 +1,138 @@ +commit 76a7c103eb9060f9e3ba01d073ae4621a17d8b46 +Author: Florian Weimer +Date: Tue Nov 12 12:02:57 2019 +0100 + + login: Introduce matches_last_entry to utmp processing + + This simplifies internal_getut_nolock and fixes a regression, + introduced in commit be6b16d975683e6cca57852cd4cfe715b2a9d8b1 + ("login: Acquire write lock early in pututline [BZ #24882]") + in pututxline because __utmp_equal can only compare process-related + utmp entries. + + Fixes: be6b16d975683e6cca57852cd4cfe715b2a9d8b1 + Change-Id: Ib8a85002f7f87ee41590846d16d7e52bdb82f5a5 + +diff --git a/login/utmp_file.c b/login/utmp_file.c +index 6bba120db9cc574e..e653d14967c4fb7a 100644 +--- a/login/utmp_file.c ++++ b/login/utmp_file.c +@@ -43,6 +43,25 @@ static off64_t file_offset; + /* Cache for the last read entry. */ + static struct utmp last_entry; + ++/* Returns true if *ENTRY matches last_entry, based on ++ data->ut_type. */ ++static bool ++matches_last_entry (const struct utmp *data) ++{ ++ if (file_offset <= 0) ++ /* Nothing has been read. last_entry is stale and cannot match. */ ++ return false; ++ ++ if (data->ut_type == RUN_LVL ++ || data->ut_type == BOOT_TIME ++ || data->ut_type == OLD_TIME ++ || data->ut_type == NEW_TIME) ++ /* For some entry types, only a type match is required. */ ++ return data->ut_type == last_entry.ut_type; ++ else ++ /* For the process-related entries, a full match is needed. */ ++ return __utmp_equal (&last_entry, data); ++} + + /* Locking timeout. */ + #ifndef TIMEOUT +@@ -133,9 +152,6 @@ __libc_setutent (void) + __lseek64 (file_fd, 0, SEEK_SET); + file_offset = 0; + +- /* Make sure the entry won't match. */ +- last_entry.ut_type = -1; +- + return 1; + } + +@@ -191,48 +207,20 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result) + static int + internal_getut_nolock (const struct utmp *id) + { +- if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME +- || id->ut_type == OLD_TIME || id->ut_type == NEW_TIME) ++ while (1) + { +- /* Search for next entry with type RUN_LVL, BOOT_TIME, +- OLD_TIME, or NEW_TIME. */ +- +- while (1) ++ /* Read the next entry. */ ++ if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp)) ++ != sizeof (struct utmp)) + { +- /* Read the next entry. */ +- if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp)) +- != sizeof (struct utmp)) +- { +- __set_errno (ESRCH); +- file_offset = -1l; +- return -1; +- } +- file_offset += sizeof (struct utmp); +- +- if (id->ut_type == last_entry.ut_type) +- break; ++ __set_errno (ESRCH); ++ file_offset = -1l; ++ return -1; + } +- } +- else +- { +- /* Search for the next entry with the specified ID and with type +- INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, or DEAD_PROCESS. */ +- +- while (1) +- { +- /* Read the next entry. */ +- if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp)) +- != sizeof (struct utmp)) +- { +- __set_errno (ESRCH); +- file_offset = -1l; +- return -1; +- } +- file_offset += sizeof (struct utmp); ++ file_offset += sizeof (struct utmp); + +- if (__utmp_equal (&last_entry, id)) +- break; +- } ++ if (matches_last_entry (id)) ++ break; + } + + return 0; +@@ -365,13 +353,7 @@ __libc_pututline (const struct utmp *data) + + /* Find the correct place to insert the data. */ + bool found = false; +- if (file_offset > 0 +- && ((last_entry.ut_type == data->ut_type +- && (last_entry.ut_type == RUN_LVL +- || last_entry.ut_type == BOOT_TIME +- || last_entry.ut_type == OLD_TIME +- || last_entry.ut_type == NEW_TIME)) +- || __utmp_equal (&last_entry, data))) ++ if (matches_last_entry (data)) + { + if (__lseek64 (file_fd, file_offset, SEEK_SET) < 0) + { +@@ -389,7 +371,7 @@ __libc_pututline (const struct utmp *data) + found = false; + } + else +- found = __utmp_equal (&last_entry, data); ++ found = matches_last_entry (data); + } + + if (!found) diff --git a/glibc-rh1749439-12.patch b/glibc-rh1749439-12.patch new file mode 100755 index 0000000..0308708 --- /dev/null +++ b/glibc-rh1749439-12.patch @@ -0,0 +1,114 @@ +commit fed33b0fb03d1942a6713286176d42869c0f1580 +Author: Leandro Pereira +Date: Wed Oct 2 12:42:28 2019 -0400 + + Add nocancel version of pread64() + + This is in preparation for changes in the dynamic linker so that + pread() is used instead of lseek()+read(). + + Reviewed-by: Carlos O'Donell + +Conflicts: + sysdeps/unix/sysv/linux/Makefile + (Textual conflict in routines list.) + +diff --git a/sysdeps/generic/not-cancel.h b/sysdeps/generic/not-cancel.h +index d9f8a75dbda85ed5..260e6e4081f5fe16 100644 +--- a/sysdeps/generic/not-cancel.h ++++ b/sysdeps/generic/not-cancel.h +@@ -41,6 +41,8 @@ + (void) __close (fd) + #define __read_nocancel(fd, buf, n) \ + __read (fd, buf, n) ++#define __pread64_nocancel(fd, buf, count, offset) \ ++ __pread64 (fd, buf, count, offset) + #define __write_nocancel(fd, buf, n) \ + __write (fd, buf, n) + #define __writev_nocancel_nostatus(fd, iov, n) \ +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index 773aaea0e980bdd6..fb4ccd63ddec7eca 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -174,7 +174,8 @@ sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \ + close_nocancel fcntl_nocancel nanosleep_nocancel \ + open_nocancel open64_nocancel \ + openat_nocancel openat64_nocancel \ +- pause_nocancel read_nocancel waitpid_nocancel write_nocancel ++ pause_nocancel read_nocancel pread64_nocancel \ ++ waitpid_nocancel write_nocancel + + sysdep_headers += bits/fcntl-linux.h + +diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions +index 336c13b57dba727a..95759bead1b0b3ca 100644 +--- a/sysdeps/unix/sysv/linux/Versions ++++ b/sysdeps/unix/sysv/linux/Versions +@@ -176,6 +176,7 @@ libc { + __syscall_rt_sigqueueinfo; + __open_nocancel; + __read_nocancel; ++ __pread64_nocancel; + __close_nocancel; + __sigtimedwait; + # functions used by nscd +diff --git a/sysdeps/unix/sysv/linux/not-cancel.h b/sysdeps/unix/sysv/linux/not-cancel.h +index 09de92dee9437d98..e58db475682a8c6a 100644 +--- a/sysdeps/unix/sysv/linux/not-cancel.h ++++ b/sysdeps/unix/sysv/linux/not-cancel.h +@@ -43,6 +43,9 @@ __typeof (openat64) __openat64_nocancel; + /* Non cancellable read syscall. */ + __typeof (__read) __read_nocancel; + ++/* Non cancellable pread syscall (LFS version). */ ++__typeof (__pread64) __pread64_nocancel; ++ + /* Uncancelable write. */ + __typeof (__write) __write_nocancel; + +@@ -84,6 +87,7 @@ hidden_proto (__open64_nocancel) + hidden_proto (__openat_nocancel) + hidden_proto (__openat64_nocancel) + hidden_proto (__read_nocancel) ++hidden_proto (__pread64_nocancel) + hidden_proto (__write_nocancel) + hidden_proto (__close_nocancel) + hidden_proto (__waitpid_nocancel) +diff --git a/sysdeps/unix/sysv/linux/pread64_nocancel.c b/sysdeps/unix/sysv/linux/pread64_nocancel.c +new file mode 100644 +index 0000000000000000..dab61260e5db43b5 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/pread64_nocancel.c +@@ -0,0 +1,32 @@ ++/* Linux pread64() syscall implementation -- non-cancellable. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++#ifndef __NR_pread64 ++# define __NR_pread64 __NR_pread ++#endif ++ ++ssize_t ++__pread64_nocancel (int fd, void *buf, size_t count, off64_t offset) ++{ ++ return INLINE_SYSCALL_CALL (pread64, fd, buf, count, SYSCALL_LL64_PRW (offset)); ++} ++hidden_def (__pread64_nocancel) diff --git a/glibc-rh1749439-13.patch b/glibc-rh1749439-13.patch new file mode 100755 index 0000000..333f1f6 --- /dev/null +++ b/glibc-rh1749439-13.patch @@ -0,0 +1,307 @@ +commit d4625a19fe64f664119a541b317fb83de01bb273 +Author: Florian Weimer +Date: Tue Nov 12 12:25:49 2019 +0100 + + login: Use pread64 in utmp implementation + + This reduces the possible error scenarios considerably because + no longer can file seek fail, leaving the file descriptor in an + inconsistent state and out of sync with the cache. + + As a result, it is possible to avoid setting file_offset to -1 + to make an error persistent. Instead, subsequent calls will retry + the operation and report any errors returned by the kernel. + + This change also avoids reading the file from the start if pututline + is called multiple times, to work around lock acquisition failures + due to timeouts. + + Change-Id: If21ea0c162c38830a89331ea93cddec14c0974de + +diff --git a/login/utmp_file.c b/login/utmp_file.c +index e653d14967c4fb7a..c828a28ac54c150e 100644 +--- a/login/utmp_file.c ++++ b/login/utmp_file.c +@@ -162,12 +162,35 @@ maybe_setutent (void) + return file_fd >= 0 || __libc_setutent (); + } + ++/* Reads the entry at file_offset, storing it in last_entry and ++ updating file_offset on success. Returns -1 for a read error, 0 ++ for EOF, and 1 for a successful read. last_entry and file_offset ++ are only updated on a successful and complete read. */ ++static ssize_t ++read_last_entry (void) ++{ ++ struct utmp buffer; ++ ssize_t nbytes = __pread64_nocancel (file_fd, &buffer, sizeof (buffer), ++ file_offset); ++ if (nbytes < 0) ++ return -1; ++ else if (nbytes != sizeof (buffer)) ++ /* Assume EOF. */ ++ return 0; ++ else ++ { ++ last_entry = buffer; ++ file_offset += sizeof (buffer); ++ return 1; ++ } ++} ++ + int + __libc_getutent_r (struct utmp *buffer, struct utmp **result) + { +- ssize_t nbytes; ++ int saved_errno = errno; + +- if (!maybe_setutent () || file_offset == -1l) ++ if (!maybe_setutent ()) + { + /* Not available. */ + *result = NULL; +@@ -175,25 +198,22 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result) + } + + if (try_file_lock (file_fd, F_RDLCK)) +- nbytes = 0; +- else +- { +- /* Read the next entry. */ +- nbytes = __read_nocancel (file_fd, &last_entry, sizeof (struct utmp)); +- file_unlock (file_fd); +- } ++ return -1; + +- if (nbytes != sizeof (struct utmp)) ++ ssize_t nbytes = read_last_entry (); ++ file_unlock (file_fd); ++ ++ if (nbytes <= 0) /* Read error or EOF. */ + { +- if (nbytes != 0) +- file_offset = -1l; ++ if (nbytes == 0) ++ /* errno should be unchanged to indicate success. A premature ++ EOF is treated like an EOF (missing complete record at the ++ end). */ ++ __set_errno (saved_errno); + *result = NULL; + return -1; + } + +- /* Update position pointer. */ +- file_offset += sizeof (struct utmp); +- + memcpy (buffer, &last_entry, sizeof (struct utmp)); + *result = buffer; + +@@ -209,15 +229,15 @@ internal_getut_nolock (const struct utmp *id) + { + while (1) + { +- /* Read the next entry. */ +- if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp)) +- != sizeof (struct utmp)) ++ ssize_t nbytes = read_last_entry (); ++ if (nbytes < 0) ++ return -1; ++ if (nbytes == 0) + { ++ /* End of file reached. */ + __set_errno (ESRCH); +- file_offset = -1l; + return -1; + } +- file_offset += sizeof (struct utmp); + + if (matches_last_entry (id)) + break; +@@ -249,7 +269,7 @@ int + __libc_getutid_r (const struct utmp *id, struct utmp *buffer, + struct utmp **result) + { +- if (!maybe_setutent () || file_offset == -1l) ++ if (!maybe_setutent ()) + { + *result = NULL; + return -1; +@@ -276,7 +296,7 @@ int + __libc_getutline_r (const struct utmp *line, struct utmp *buffer, + struct utmp **result) + { +- if (!maybe_setutent () || file_offset == -1l) ++ if (!maybe_setutent ()) + { + *result = NULL; + return -1; +@@ -290,16 +310,21 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer, + + while (1) + { +- /* Read the next entry. */ +- if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp)) +- != sizeof (struct utmp)) ++ ssize_t nbytes = read_last_entry (); ++ if (nbytes < 0) + { ++ file_unlock (file_fd); ++ *result = NULL; ++ return -1; ++ } ++ if (nbytes == 0) ++ { ++ /* End of file reached. */ ++ file_unlock (file_fd); + __set_errno (ESRCH); +- file_offset = -1l; + *result = NULL; +- goto unlock_return; ++ return -1; + } +- file_offset += sizeof (struct utmp); + + /* Stop if we found a user or login entry. */ + if ((last_entry.ut_type == USER_PROCESS +@@ -309,20 +334,18 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer, + break; + } + ++ file_unlock (file_fd); + memcpy (buffer, &last_entry, sizeof (struct utmp)); + *result = buffer; + +-unlock_return: +- file_unlock (file_fd); +- +- return ((*result == NULL) ? -1 : 0); ++ return 0; + } + + + struct utmp * + __libc_pututline (const struct utmp *data) + { +- if (!maybe_setutent () || file_offset == -1l) ++ if (!maybe_setutent ()) + return NULL; + + struct utmp *pbuf; +@@ -337,8 +360,7 @@ __libc_pututline (const struct utmp *data) + if (new_fd == -1) + return NULL; + +- if (__lseek64 (new_fd, __lseek64 (file_fd, 0, SEEK_CUR), SEEK_SET) == -1 +- || __dup2 (new_fd, file_fd) < 0) ++ if (__dup2 (new_fd, file_fd) < 0) + { + __close_nocancel_nostatus (new_fd); + return NULL; +@@ -355,69 +377,70 @@ __libc_pututline (const struct utmp *data) + bool found = false; + if (matches_last_entry (data)) + { +- if (__lseek64 (file_fd, file_offset, SEEK_SET) < 0) ++ /* Read back the entry under the write lock. */ ++ file_offset -= sizeof (last_entry); ++ ssize_t nbytes = read_last_entry (); ++ if (nbytes < 0) + { + file_unlock (file_fd); + return NULL; + } +- if (__read_nocancel (file_fd, &last_entry, sizeof (last_entry)) +- != sizeof (last_entry)) +- { +- if (__lseek64 (file_fd, file_offset, SEEK_SET) < 0) +- { +- file_unlock (file_fd); +- return NULL; +- } +- found = false; +- } ++ ++ if (nbytes == 0) ++ /* End of file reached. */ ++ found = false; + else + found = matches_last_entry (data); + } + + if (!found) ++ /* Search forward for the entry. */ + found = internal_getut_nolock (data) >= 0; + ++ off64_t write_offset; + if (!found) + { + /* We append the next entry. */ +- file_offset = __lseek64 (file_fd, 0, SEEK_END); +- if (file_offset % sizeof (struct utmp) != 0) +- { +- file_offset -= file_offset % sizeof (struct utmp); +- __ftruncate64 (file_fd, file_offset); +- +- if (__lseek64 (file_fd, 0, SEEK_END) < 0) +- { +- pbuf = NULL; +- goto unlock_return; +- } +- } ++ write_offset = __lseek64 (file_fd, 0, SEEK_END); ++ ++ /* Round down to the next multiple of the entry size. This ++ ensures any partially-written record is overwritten by the ++ new record. */ ++ write_offset = (write_offset / sizeof (struct utmp) ++ * sizeof (struct utmp)); + } + else ++ /* Overwrite last_entry. */ ++ write_offset = file_offset - sizeof (struct utmp); ++ ++ /* Write the new data. */ ++ ssize_t nbytes; ++ if (__lseek64 (file_fd, write_offset, SEEK_SET) < 0 ++ || (nbytes = __write_nocancel (file_fd, data, sizeof (struct utmp))) < 0) + { +- /* We replace the just read entry. */ +- file_offset -= sizeof (struct utmp); +- __lseek64 (file_fd, file_offset, SEEK_SET); ++ /* There is no need to recover the file position because all ++ reads use pread64, and any future write is preceded by ++ another seek. */ ++ file_unlock (file_fd); ++ return NULL; + } + +- /* Write the new data. */ +- if (__write_nocancel (file_fd, data, sizeof (struct utmp)) +- != sizeof (struct utmp)) ++ if (nbytes != sizeof (struct utmp)) + { + /* If we appended a new record this is only partially written. + Remove it. */ + if (!found) +- (void) __ftruncate64 (file_fd, file_offset); +- pbuf = NULL; +- } +- else +- { +- file_offset += sizeof (struct utmp); +- pbuf = (struct utmp *) data; ++ (void) __ftruncate64 (file_fd, write_offset); ++ file_unlock (file_fd); ++ /* Assume that the write failure was due to missing disk ++ space. */ ++ __set_errno (ENOSPC); ++ return NULL; + } + +- unlock_return: + file_unlock (file_fd); ++ file_offset = write_offset + sizeof (struct utmp); ++ pbuf = (struct utmp *) data; + + return pbuf; + } diff --git a/glibc-rh1749439-2.patch b/glibc-rh1749439-2.patch new file mode 100755 index 0000000..f00334c --- /dev/null +++ b/glibc-rh1749439-2.patch @@ -0,0 +1,676 @@ +commit a33b817f13170b5c24263b92e7e09880fe797d7e +Author: Florian Weimer +Date: Tue Aug 13 12:09:32 2019 +0200 + + login: Assume that _HAVE_UT_* constants are true + + Make the GNU version of bits/utmp.h the generic version because + all remaining ports use it (with a sysdeps override for + Linux s390/s390x). + +Conflicts: + bits/utmp.h + sysdeps/gnu/bits/utmp.h + (Upstream copyright year change.) + +diff --git a/bits/utmp.h b/bits/utmp.h +index 6e8695fbf072e5f1..3c02dd4f3fe4e99b 100644 +--- a/bits/utmp.h ++++ b/bits/utmp.h +@@ -1,5 +1,5 @@ +-/* The `struct utmp' type, describing entries in the utmp file. Generic/BSDish +- Copyright (C) 1993-2018 Free Software Foundation, Inc. ++/* The `struct utmp' type, describing entries in the utmp file. ++ Copyright (C) 1993-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 +@@ -21,29 +21,106 @@ + #endif + + #include +-#include ++#include ++#include ++#include + + +-#define UT_NAMESIZE 8 +-#define UT_LINESIZE 8 +-#define UT_HOSTSIZE 16 ++#define UT_LINESIZE 32 ++#define UT_NAMESIZE 32 ++#define UT_HOSTSIZE 256 + + ++/* The structure describing an entry in the database of ++ previous logins. */ + struct lastlog + { +- time_t ll_time; ++#if __WORDSIZE_TIME64_COMPAT32 ++ int32_t ll_time; ++#else ++ __time_t ll_time; ++#endif + char ll_line[UT_LINESIZE]; + char ll_host[UT_HOSTSIZE]; + }; + +-struct utmp ++ ++/* The structure describing the status of a terminated process. This ++ type is used in `struct utmp' below. */ ++struct exit_status + { +- char ut_line[UT_LINESIZE]; +- char ut_user[UT_NAMESIZE]; +-#define ut_name ut_user +- char ut_host[UT_HOSTSIZE]; +- long int ut_time; ++ short int e_termination; /* Process termination status. */ ++ short int e_exit; /* Process exit status. */ + }; + + +-#define _HAVE_UT_HOST 1 /* We have the ut_host field. */ ++/* The structure describing an entry in the user accounting database. */ ++struct utmp ++{ ++ short int ut_type; /* Type of login. */ ++ pid_t ut_pid; /* Process ID of login process. */ ++ char ut_line[UT_LINESIZE] ++ __attribute_nonstring__; /* Devicename. */ ++ char ut_id[4]; /* Inittab ID. */ ++ char ut_user[UT_NAMESIZE] ++ __attribute_nonstring__; /* Username. */ ++ char ut_host[UT_HOSTSIZE] ++ __attribute_nonstring__; /* Hostname for remote login. */ ++ struct exit_status ut_exit; /* Exit status of a process marked ++ as DEAD_PROCESS. */ ++/* The ut_session and ut_tv fields must be the same size when compiled ++ 32- and 64-bit. This allows data files and shared memory to be ++ shared between 32- and 64-bit applications. */ ++#if __WORDSIZE_TIME64_COMPAT32 ++ int32_t ut_session; /* Session ID, used for windowing. */ ++ struct ++ { ++ int32_t tv_sec; /* Seconds. */ ++ int32_t tv_usec; /* Microseconds. */ ++ } ut_tv; /* Time entry was made. */ ++#else ++ long int ut_session; /* Session ID, used for windowing. */ ++ struct timeval ut_tv; /* Time entry was made. */ ++#endif ++ ++ int32_t ut_addr_v6[4]; /* Internet address of remote host. */ ++ char __glibc_reserved[20]; /* Reserved for future use. */ ++}; ++ ++/* Backwards compatibility hacks. */ ++#define ut_name ut_user ++#ifndef _NO_UT_TIME ++/* We have a problem here: `ut_time' is also used otherwise. Define ++ _NO_UT_TIME if the compiler complains. */ ++# define ut_time ut_tv.tv_sec ++#endif ++#define ut_xtime ut_tv.tv_sec ++#define ut_addr ut_addr_v6[0] ++ ++ ++/* Values for the `ut_type' field of a `struct utmp'. */ ++#define EMPTY 0 /* No valid user accounting information. */ ++ ++#define RUN_LVL 1 /* The system's runlevel. */ ++#define BOOT_TIME 2 /* Time of system boot. */ ++#define NEW_TIME 3 /* Time after system clock changed. */ ++#define OLD_TIME 4 /* Time when system clock changed. */ ++ ++#define INIT_PROCESS 5 /* Process spawned by the init process. */ ++#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */ ++#define USER_PROCESS 7 /* Normal process. */ ++#define DEAD_PROCESS 8 /* Terminated process. */ ++ ++#define ACCOUNTING 9 ++ ++/* Old Linux name for the EMPTY type. */ ++#define UT_UNKNOWN EMPTY ++ ++ ++/* Tell the user that we have a modern system with UT_HOST, UT_PID, ++ UT_TYPE, UT_ID and UT_TV fields. */ ++#define _HAVE_UT_TYPE 1 ++#define _HAVE_UT_PID 1 ++#define _HAVE_UT_ID 1 ++#define _HAVE_UT_TV 1 ++#define _HAVE_UT_HOST 1 +diff --git a/login/getutid_r.c b/login/getutid_r.c +index 8cb6b16d735e8265..11b288e99be6ee50 100644 +--- a/login/getutid_r.c ++++ b/login/getutid_r.c +@@ -32,7 +32,6 @@ __libc_lock_define (extern, __libc_utmp_lock attribute_hidden) + int + __getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result) + { +-#if (_HAVE_UT_ID - 0) && (_HAVE_UT_TYPE - 0) + int retval; + + /* Test whether ID has any of the legal types. */ +@@ -54,10 +53,6 @@ __getutid_r (const struct utmp *id, struct utmp *buffer, struct utmp **result) + __libc_lock_unlock (__libc_utmp_lock); + + return retval; +-#else /* !_HAVE_UT_ID && !_HAVE_UT_TYPE */ +- __set_errno (ENOSYS); +- return -1; +-#endif + } + libc_hidden_def (__getutid_r) + weak_alias (__getutid_r, getutid_r) +diff --git a/login/getutmp.c b/login/getutmp.c +index 481150d5ef5a0bf0..32468ecae699fbf7 100644 +--- a/login/getutmp.c ++++ b/login/getutmp.c +@@ -23,23 +23,11 @@ + void + getutmp (const struct utmpx *utmpx, struct utmp *utmp) + { +-#if _HAVE_UT_TYPE - 0 + utmp->ut_type = utmpx->ut_type; +-#endif +-#if _HAVE_UT_PID - 0 + utmp->ut_pid = utmpx->ut_pid; +-#endif + memcpy (utmp->ut_line, utmpx->ut_line, sizeof (utmp->ut_line)); + memcpy (utmp->ut_user, utmpx->ut_user, sizeof (utmp->ut_user)); +-#if _HAVE_UT_ID - 0 + memcpy (utmp->ut_id, utmpx->ut_id, sizeof (utmp->ut_id)); +-#endif +-#if _HAVE_UT_HOST - 0 + memcpy (utmp->ut_host, utmpx->ut_host, sizeof (utmp->ut_host)); +-#endif +-#if _HAVE_UT_TV - 0 + utmp->ut_tv = utmpx->ut_tv; +-#else +- utmp->ut_time = utmpx->ut_time; +-#endif + } +diff --git a/login/getutmpx.c b/login/getutmpx.c +index 34145fe8db71faf0..92a182698e2be438 100644 +--- a/login/getutmpx.c ++++ b/login/getutmpx.c +@@ -24,24 +24,11 @@ void + getutmpx (const struct utmp *utmp, struct utmpx *utmpx) + { + memset (utmpx, 0, sizeof (struct utmpx)); +- +-#if _HAVE_UT_TYPE - 0 + utmpx->ut_type = utmp->ut_type; +-#endif +-#if _HAVE_UT_PID - 0 + utmpx->ut_pid = utmp->ut_pid; +-#endif + memcpy (utmpx->ut_line, utmp->ut_line, sizeof (utmp->ut_line)); + memcpy (utmpx->ut_user, utmp->ut_user, sizeof (utmp->ut_user)); +-#if _HAVE_UT_ID - 0 + memcpy (utmpx->ut_id, utmp->ut_id, sizeof (utmp->ut_id)); +-#endif +-#if _HAVE_UT_HOST - 0 + memcpy (utmpx->ut_host, utmp->ut_host, sizeof (utmp->ut_host)); +-#endif +-#if _HAVE_UT_TV - 0 + utmpx->ut_tv = utmp->ut_tv; +-#else +- utmpx->ut_time = utmp->ut_time; +-#endif + } +diff --git a/login/login.c b/login/login.c +index 5d48cd487f237ca0..1729fc070fcc1e4b 100644 +--- a/login/login.c ++++ b/login/login.c +@@ -91,12 +91,8 @@ login (const struct utmp *ut) + struct utmp copy = *ut; + + /* Fill in those fields we supply. */ +-#if _HAVE_UT_TYPE - 0 + copy.ut_type = USER_PROCESS; +-#endif +-#if _HAVE_UT_PID - 0 + copy.ut_pid = getpid (); +-#endif + + /* Seek tty. */ + found_tty = tty_name (STDIN_FILENO, &tty, sizeof (_tty)); +diff --git a/login/logout.c b/login/logout.c +index d49bc4ecac9a8379..4d76ecf1b40d306a 100644 +--- a/login/logout.c ++++ b/login/logout.c +@@ -36,9 +36,7 @@ logout (const char *line) + setutent (); + + /* Fill in search information. */ +-#if _HAVE_UT_TYPE - 0 + tmp.ut_type = USER_PROCESS; +-#endif + strncpy (tmp.ut_line, line, sizeof tmp.ut_line); + + /* Read the record. */ +@@ -46,20 +44,12 @@ logout (const char *line) + { + /* Clear information about who & from where. */ + memset (ut->ut_name, '\0', sizeof ut->ut_name); +-#if _HAVE_UT_HOST - 0 + memset (ut->ut_host, '\0', sizeof ut->ut_host); +-#endif +-#if _HAVE_UT_TV - 0 + struct timeval tv; + __gettimeofday (&tv, NULL); + ut->ut_tv.tv_sec = tv.tv_sec; + ut->ut_tv.tv_usec = tv.tv_usec; +-#else +- ut->ut_time = time (NULL); +-#endif +-#if _HAVE_UT_TYPE - 0 + ut->ut_type = DEAD_PROCESS; +-#endif + + if (pututline (ut) != NULL) + result = 1; +diff --git a/login/logwtmp.c b/login/logwtmp.c +index a19da4ab5ef7a624..e0b52b23e3603b7c 100644 +--- a/login/logwtmp.c ++++ b/login/logwtmp.c +@@ -30,26 +30,16 @@ logwtmp (const char *line, const char *name, const char *host) + + /* Set information in new entry. */ + memset (&ut, 0, sizeof (ut)); +-#if _HAVE_UT_PID - 0 + ut.ut_pid = getpid (); +-#endif +-#if _HAVE_UT_TYPE - 0 + ut.ut_type = name[0] ? USER_PROCESS : DEAD_PROCESS; +-#endif + strncpy (ut.ut_line, line, sizeof ut.ut_line); + strncpy (ut.ut_name, name, sizeof ut.ut_name); +-#if _HAVE_UT_HOST - 0 + strncpy (ut.ut_host, host, sizeof ut.ut_host); +-#endif + +-#if _HAVE_UT_TV - 0 + struct timeval tv; + __gettimeofday (&tv, NULL); + ut.ut_tv.tv_sec = tv.tv_sec; + ut.ut_tv.tv_usec = tv.tv_usec; +-#else +- ut.ut_time = time (NULL); +-#endif + + updwtmp (_PATH_WTMP, &ut); + } +diff --git a/login/programs/utmpdump.c b/login/programs/utmpdump.c +index dccdb669f5fb9c74..1763e55af2f03d8d 100644 +--- a/login/programs/utmpdump.c ++++ b/login/programs/utmpdump.c +@@ -37,47 +37,11 @@ print_entry (struct utmp *up) + temp_tv.tv_sec = up->ut_tv.tv_sec; + temp_tv.tv_usec = up->ut_tv.tv_usec; + +- (printf) ( +- /* The format string. */ +-#if _HAVE_UT_TYPE +- "[%d] " +-#endif +-#if _HAVE_UT_PID +- "[%05d] " +-#endif +-#if _HAVE_UT_ID +- "[%-4.4s] " +-#endif +- "[%-8.8s] [%-12.12s]" +-#if _HAVE_UT_HOST +- " [%-16.16s]" +-#endif +- " [%-15.15s]" +-#if _HAVE_UT_TV +- " [%ld]" +-#endif +- "\n" +- /* The arguments. */ +-#if _HAVE_UT_TYPE +- , up->ut_type +-#endif +-#if _HAVE_UT_PID +- , up->ut_pid +-#endif +-#if _HAVE_UT_ID +- , up->ut_id +-#endif +- , up->ut_user, up->ut_line +-#if _HAVE_UT_HOST +- , up->ut_host +-#endif +-#if _HAVE_UT_TV +- , 4 + ctime (&temp_tv.tv_sec) +- , (long int) temp_tv.tv_usec +-#else +- , 4 + ctime (&up->ut_time) +-#endif +- ); ++ printf ("[%d] [%05d] [%-4.4s] [%-8.8s] [%-12.12s] [%-16.16s] [%-15.15s]" ++ " [%ld]\n", ++ up->ut_type, up->ut_pid, up->ut_id, up->ut_user, up->ut_line, ++ up->ut_host, 4 + ctime (&temp_tv.tv_sec), ++ (long int) temp_tv.tv_usec); + } + + int +diff --git a/login/tst-utmp.c b/login/tst-utmp.c +index 8cc7aafa89c0ea8c..49b0cbda2a719643 100644 +--- a/login/tst-utmp.c ++++ b/login/tst-utmp.c +@@ -39,8 +39,6 @@ + #endif + + +-#if defined UTMPX || _HAVE_UT_TYPE +- + /* Prototype for our test function. */ + static int do_test (int argc, char *argv[]); + +@@ -75,11 +73,7 @@ do_prepare (int argc, char *argv[]) + + struct utmp entry[] = + { +-#if defined UTMPX || _HAVE_UT_TV + #define UT(a) .ut_tv = { .tv_sec = (a)} +-#else +-#define UT(a) .ut_time = (a) +-#endif + + { .ut_type = BOOT_TIME, .ut_pid = 1, UT(1000) }, + { .ut_type = RUN_LVL, .ut_pid = 1, UT(2000) }, +@@ -167,11 +161,7 @@ simulate_login (const char *line, const char *user) + entry[n].ut_pid = (entry_pid += 27); + entry[n].ut_type = USER_PROCESS; + strncpy (entry[n].ut_user, user, sizeof (entry[n].ut_user)); +-#if defined UTMPX || _HAVE_UT_TV - 0 + entry[n].ut_tv.tv_sec = (entry_time += 1000); +-#else +- entry[n].ut_time = (entry_time += 1000); +-#endif + setutent (); + + if (pututline (&entry[n]) == NULL) +@@ -201,11 +191,7 @@ simulate_logout (const char *line) + { + entry[n].ut_type = DEAD_PROCESS; + strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user)); +-#if defined UTMPX || _HAVE_UT_TV - 0 + entry[n].ut_tv.tv_sec = (entry_time += 1000); +-#else +- entry[n].ut_time = (entry_time += 1000); +-#endif + setutent (); + + if (pututline (&entry[n]) == NULL) +@@ -390,14 +376,3 @@ do_test (int argc, char *argv[]) + + return result; + } +- +-#else +- +-/* No field 'ut_type' in struct utmp. */ +-int +-main (void) +-{ +- return 0; +-} +- +-#endif +diff --git a/login/utmp_file.c b/login/utmp_file.c +index 069e6d0452e333ad..da1baa6948d0eb39 100644 +--- a/login/utmp_file.c ++++ b/login/utmp_file.c +@@ -129,14 +129,7 @@ __libc_setutent (void) + file_offset = 0; + + /* Make sure the entry won't match. */ +-#if _HAVE_UT_TYPE - 0 + last_entry.ut_type = -1; +-#else +- last_entry.ut_line[0] = '\177'; +-# if _HAVE_UT_ID - 0 +- last_entry.ut_id[0] = '\0'; +-# endif +-#endif + + return 1; + } +@@ -201,7 +194,6 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer, + LOCKING_FAILED (); + } + +-#if _HAVE_UT_TYPE - 0 + if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME + || id->ut_type == OLD_TIME || id->ut_type == NEW_TIME) + { +@@ -225,7 +217,6 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer, + } + } + else +-#endif /* _HAVE_UT_TYPE */ + { + /* Search for the next entry with the specified ID and with type + INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, or DEAD_PROCESS. */ +@@ -316,13 +307,10 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer, + file_offset += sizeof (struct utmp); + + /* Stop if we found a user or login entry. */ +- if ( +-#if _HAVE_UT_TYPE - 0 +- (last_entry.ut_type == USER_PROCESS ++ if ((last_entry.ut_type == USER_PROCESS + || last_entry.ut_type == LOGIN_PROCESS) +- && +-#endif +- !strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line)) ++ && (strncmp (line->ut_line, last_entry.ut_line, sizeof line->ut_line) ++ == 0)) + break; + } + +@@ -368,16 +356,12 @@ __libc_pututline (const struct utmp *data) + + /* Find the correct place to insert the data. */ + if (file_offset > 0 +- && ( +-#if _HAVE_UT_TYPE - 0 +- (last_entry.ut_type == data->ut_type ++ && ((last_entry.ut_type == data->ut_type + && (last_entry.ut_type == RUN_LVL + || last_entry.ut_type == BOOT_TIME + || last_entry.ut_type == OLD_TIME + || last_entry.ut_type == NEW_TIME)) +- || +-#endif +- __utmp_equal (&last_entry, data))) ++ || __utmp_equal (&last_entry, data))) + found = 1; + else + { +diff --git a/sysdeps/generic/utmp-equal.h b/sysdeps/generic/utmp-equal.h +index 8b5c2e2cd2c4cf95..39993af192ab66ce 100644 +--- a/sysdeps/generic/utmp-equal.h ++++ b/sysdeps/generic/utmp-equal.h +@@ -27,26 +27,16 @@ + static int + __utmp_equal (const struct utmp *entry, const struct utmp *match) + { +- return +- ( +-#if _HAVE_UT_TYPE - 0 +- (entry->ut_type == INIT_PROCESS +- || entry->ut_type == LOGIN_PROCESS +- || entry->ut_type == USER_PROCESS +- || entry->ut_type == DEAD_PROCESS) +- && +- (match->ut_type == INIT_PROCESS +- || match->ut_type == LOGIN_PROCESS +- || match->ut_type == USER_PROCESS +- || match->ut_type == DEAD_PROCESS) +- && +-#endif +-#if _HAVE_UT_ID - 0 +- (entry->ut_id[0] && match->ut_id[0] +- ? strncmp (entry->ut_id, match->ut_id, sizeof match->ut_id) == 0 +- : strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) == 0) +-#else +- strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) == 0 +-#endif +- ); ++ return (entry->ut_type == INIT_PROCESS ++ || entry->ut_type == LOGIN_PROCESS ++ || entry->ut_type == USER_PROCESS ++ || entry->ut_type == DEAD_PROCESS) ++ && (match->ut_type == INIT_PROCESS ++ || match->ut_type == LOGIN_PROCESS ++ || match->ut_type == USER_PROCESS ++ || match->ut_type == DEAD_PROCESS) ++ && (entry->ut_id[0] && match->ut_id[0] ++ ? strncmp (entry->ut_id, match->ut_id, sizeof match->ut_id) == 0 ++ : (strncmp (entry->ut_line, match->ut_line, sizeof match->ut_line) ++ == 0)); + } +diff --git a/sysdeps/gnu/bits/utmp.h b/sysdeps/gnu/bits/utmp.h +deleted file mode 100644 +index 47a6082eacc56b4d..0000000000000000 +--- a/sysdeps/gnu/bits/utmp.h ++++ /dev/null +@@ -1,126 +0,0 @@ +-/* The `struct utmp' type, describing entries in the utmp file. GNU version. +- Copyright (C) 1993-2018 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 +- . */ +- +-#ifndef _UTMP_H +-# error "Never include directly; use instead." +-#endif +- +-#include +-#include +-#include +-#include +- +- +-#define UT_LINESIZE 32 +-#define UT_NAMESIZE 32 +-#define UT_HOSTSIZE 256 +- +- +-/* The structure describing an entry in the database of +- previous logins. */ +-struct lastlog +- { +-#if __WORDSIZE_TIME64_COMPAT32 +- int32_t ll_time; +-#else +- __time_t ll_time; +-#endif +- char ll_line[UT_LINESIZE]; +- char ll_host[UT_HOSTSIZE]; +- }; +- +- +-/* The structure describing the status of a terminated process. This +- type is used in `struct utmp' below. */ +-struct exit_status +- { +- short int e_termination; /* Process termination status. */ +- short int e_exit; /* Process exit status. */ +- }; +- +- +-/* The structure describing an entry in the user accounting database. */ +-struct utmp +-{ +- short int ut_type; /* Type of login. */ +- pid_t ut_pid; /* Process ID of login process. */ +- char ut_line[UT_LINESIZE] +- __attribute_nonstring__; /* Devicename. */ +- char ut_id[4]; /* Inittab ID. */ +- char ut_user[UT_NAMESIZE] +- __attribute_nonstring__; /* Username. */ +- char ut_host[UT_HOSTSIZE] +- __attribute_nonstring__; /* Hostname for remote login. */ +- struct exit_status ut_exit; /* Exit status of a process marked +- as DEAD_PROCESS. */ +-/* The ut_session and ut_tv fields must be the same size when compiled +- 32- and 64-bit. This allows data files and shared memory to be +- shared between 32- and 64-bit applications. */ +-#if __WORDSIZE_TIME64_COMPAT32 +- int32_t ut_session; /* Session ID, used for windowing. */ +- struct +- { +- int32_t tv_sec; /* Seconds. */ +- int32_t tv_usec; /* Microseconds. */ +- } ut_tv; /* Time entry was made. */ +-#else +- long int ut_session; /* Session ID, used for windowing. */ +- struct timeval ut_tv; /* Time entry was made. */ +-#endif +- +- int32_t ut_addr_v6[4]; /* Internet address of remote host. */ +- char __glibc_reserved[20]; /* Reserved for future use. */ +-}; +- +-/* Backwards compatibility hacks. */ +-#define ut_name ut_user +-#ifndef _NO_UT_TIME +-/* We have a problem here: `ut_time' is also used otherwise. Define +- _NO_UT_TIME if the compiler complains. */ +-# define ut_time ut_tv.tv_sec +-#endif +-#define ut_xtime ut_tv.tv_sec +-#define ut_addr ut_addr_v6[0] +- +- +-/* Values for the `ut_type' field of a `struct utmp'. */ +-#define EMPTY 0 /* No valid user accounting information. */ +- +-#define RUN_LVL 1 /* The system's runlevel. */ +-#define BOOT_TIME 2 /* Time of system boot. */ +-#define NEW_TIME 3 /* Time after system clock changed. */ +-#define OLD_TIME 4 /* Time when system clock changed. */ +- +-#define INIT_PROCESS 5 /* Process spawned by the init process. */ +-#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */ +-#define USER_PROCESS 7 /* Normal process. */ +-#define DEAD_PROCESS 8 /* Terminated process. */ +- +-#define ACCOUNTING 9 +- +-/* Old Linux name for the EMPTY type. */ +-#define UT_UNKNOWN EMPTY +- +- +-/* Tell the user that we have a modern system with UT_HOST, UT_PID, +- UT_TYPE, UT_ID and UT_TV fields. */ +-#define _HAVE_UT_TYPE 1 +-#define _HAVE_UT_PID 1 +-#define _HAVE_UT_ID 1 +-#define _HAVE_UT_TV 1 +-#define _HAVE_UT_HOST 1 diff --git a/glibc-rh1749439-3.patch b/glibc-rh1749439-3.patch new file mode 100755 index 0000000..7a18d19 --- /dev/null +++ b/glibc-rh1749439-3.patch @@ -0,0 +1,260 @@ +commit 5a3afa9738f3dbbaf8c0a35665318c1af782111b +Author: Florian Weimer +Date: Tue Aug 13 15:53:19 2019 +0200 + + login: Replace macro-based control flow with function calls in utmp + +diff --git a/login/utmp_file.c b/login/utmp_file.c +index da1baa6948d0eb39..812de8fd3d099ce9 100644 +--- a/login/utmp_file.c ++++ b/login/utmp_file.c +@@ -52,58 +52,71 @@ static struct utmp last_entry; + /* Do-nothing handler for locking timeout. */ + static void timeout_handler (int signum) {}; + +-/* LOCK_FILE(fd, type) failure_statement +- attempts to get a lock on the utmp file referenced by FD. If it fails, +- the failure_statement is executed, otherwise it is skipped. +- LOCKING_FAILED() +- jumps into the UNLOCK_FILE macro and ensures cleanup of LOCK_FILE. +- UNLOCK_FILE(fd) +- unlocks the utmp file referenced by FD and performs the cleanup of +- LOCK_FILE. +- */ +-#define LOCK_FILE(fd, type) \ +-{ \ +- struct flock fl; \ +- struct sigaction action, old_action; \ +- unsigned int old_timeout; \ +- \ +- /* Cancel any existing alarm. */ \ +- old_timeout = alarm (0); \ +- \ +- /* Establish signal handler. */ \ +- action.sa_handler = timeout_handler; \ +- __sigemptyset (&action.sa_mask); \ +- action.sa_flags = 0; \ +- __sigaction (SIGALRM, &action, &old_action); \ +- \ +- alarm (TIMEOUT); \ +- \ +- /* Try to get the lock. */ \ +- memset (&fl, '\0', sizeof (struct flock)); \ +- fl.l_type = (type); \ +- fl.l_whence = SEEK_SET; \ +- if (__fcntl64_nocancel ((fd), F_SETLKW, &fl) < 0) +- +-#define LOCKING_FAILED() \ +- goto unalarm_return +- +-#define UNLOCK_FILE(fd) \ +- /* Unlock the file. */ \ +- fl.l_type = F_UNLCK; \ +- __fcntl64_nocancel ((fd), F_SETLKW, &fl); \ +- \ +- unalarm_return: \ +- /* Reset the signal handler and alarm. We must reset the alarm \ +- before resetting the handler so our alarm does not generate a \ +- spurious SIGALRM seen by the user. However, we cannot just set \ +- the user's old alarm before restoring the handler, because then \ +- it's possible our handler could catch the user alarm's SIGARLM \ +- and then the user would never see the signal he expected. */ \ +- alarm (0); \ +- __sigaction (SIGALRM, &old_action, NULL); \ +- if (old_timeout != 0) \ +- alarm (old_timeout); \ +-} while (0) ++ ++/* try_file_lock (LOCKING, FD, TYPE) returns true if the locking ++ operation failed and recovery needs to be performed. ++ (file_lock_restore (LOCKING) still needs to be called.) ++ ++ file_unlock (FD) removes the lock (which must have been ++ acquired). ++ ++ file_lock_restore (LOCKING) is needed to clean up in both ++ cases. */ ++ ++struct file_locking ++{ ++ struct sigaction old_action; ++ unsigned int old_timeout; ++}; ++ ++static bool ++try_file_lock (struct file_locking *locking, int fd, int type) ++{ ++ /* Cancel any existing alarm. */ ++ locking->old_timeout = alarm (0); ++ ++ /* Establish signal handler. */ ++ struct sigaction action; ++ action.sa_handler = timeout_handler; ++ __sigemptyset (&action.sa_mask); ++ action.sa_flags = 0; ++ __sigaction (SIGALRM, &action, &locking->old_action); ++ ++ alarm (TIMEOUT); ++ ++ /* Try to get the lock. */ ++ struct flock fl = ++ { ++ .l_type = type, ++ fl.l_whence = SEEK_SET, ++ }; ++ return __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0; ++} ++ ++static void ++file_unlock (int fd) ++{ ++ struct flock fl = ++ { ++ .l_type = F_UNLCK, ++ }; ++ __fcntl64_nocancel (fd, F_SETLKW, &fl); ++} ++ ++static void ++file_lock_restore (struct file_locking *locking) ++{ ++ /* Reset the signal handler and alarm. We must reset the alarm ++ before resetting the handler so our alarm does not generate a ++ spurious SIGALRM seen by the user. However, we cannot just set ++ the user's old alarm before restoring the handler, because then ++ it's possible our handler could catch the user alarm's SIGARLM ++ and then the user would never see the signal he expected. */ ++ alarm (0); ++ __sigaction (SIGALRM, &locking->old_action, NULL); ++ if (locking->old_timeout != 0) ++ alarm (locking->old_timeout); ++} + + #ifndef TRANSFORM_UTMP_FILE_NAME + # define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name) +@@ -153,16 +166,16 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result) + return -1; + } + +- LOCK_FILE (file_fd, F_RDLCK) ++ struct file_locking fl; ++ if (try_file_lock (&fl, file_fd, F_RDLCK)) ++ nbytes = 0; ++ else + { +- nbytes = 0; +- LOCKING_FAILED (); ++ /* Read the next entry. */ ++ nbytes = __read_nocancel (file_fd, &last_entry, sizeof (struct utmp)); ++ file_unlock (file_fd); + } +- +- /* Read the next entry. */ +- nbytes = __read_nocancel (file_fd, &last_entry, sizeof (struct utmp)); +- +- UNLOCK_FILE (file_fd); ++ file_lock_restore (&fl); + + if (nbytes != sizeof (struct utmp)) + { +@@ -188,10 +201,12 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer, + { + int result = -1; + +- LOCK_FILE (file_fd, F_RDLCK) ++ struct file_locking fl; ++ if (try_file_lock (&fl, file_fd, F_RDLCK)) + { + *lock_failed = true; +- LOCKING_FAILED (); ++ file_lock_restore (&fl); ++ return -1; + } + + if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME +@@ -241,7 +256,8 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer, + result = 0; + + unlock_return: +- UNLOCK_FILE (file_fd); ++ file_unlock (file_fd); ++ file_lock_restore (&fl); + + return result; + } +@@ -287,10 +303,12 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer, + return -1; + } + +- LOCK_FILE (file_fd, F_RDLCK) ++ struct file_locking fl; ++ if (try_file_lock (&fl, file_fd, F_RDLCK)) + { + *result = NULL; +- LOCKING_FAILED (); ++ file_lock_restore (&fl); ++ return -1; + } + + while (1) +@@ -318,7 +336,8 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer, + *result = buffer; + + unlock_return: +- UNLOCK_FILE (file_fd); ++ file_unlock (file_fd); ++ file_lock_restore (&fl); + + return ((*result == NULL) ? -1 : 0); + } +@@ -375,10 +394,11 @@ __libc_pututline (const struct utmp *data) + } + } + +- LOCK_FILE (file_fd, F_WRLCK) ++ struct file_locking fl; ++ if (try_file_lock (&fl, file_fd, F_WRLCK)) + { +- pbuf = NULL; +- LOCKING_FAILED (); ++ file_lock_restore (&fl); ++ return NULL; + } + + if (found < 0) +@@ -421,7 +441,8 @@ __libc_pututline (const struct utmp *data) + } + + unlock_return: +- UNLOCK_FILE (file_fd); ++ file_unlock (file_fd); ++ file_lock_restore (&fl); + + return pbuf; + } +@@ -450,8 +471,13 @@ __libc_updwtmp (const char *file, const struct utmp *utmp) + if (fd < 0) + return -1; + +- LOCK_FILE (fd, F_WRLCK) +- LOCKING_FAILED (); ++ struct file_locking fl; ++ if (try_file_lock (&fl, fd, F_WRLCK)) ++ { ++ file_lock_restore (&fl); ++ __close_nocancel_nostatus (fd); ++ return -1; ++ } + + /* Remember original size of log file. */ + offset = __lseek64 (fd, 0, SEEK_END); +@@ -477,7 +503,8 @@ __libc_updwtmp (const char *file, const struct utmp *utmp) + result = 0; + + unlock_return: +- UNLOCK_FILE (fd); ++ file_unlock (file_fd); ++ file_lock_restore (&fl); + + /* Close WTMP file. */ + __close_nocancel_nostatus (fd); diff --git a/glibc-rh1749439-4.patch b/glibc-rh1749439-4.patch new file mode 100755 index 0000000..b2c7972 --- /dev/null +++ b/glibc-rh1749439-4.patch @@ -0,0 +1,155 @@ +commit 341da5b4b6253de9a7581a066f33f89cacb44dec +Author: Florian Weimer +Date: Thu Aug 15 10:30:23 2019 +0200 + + login: Fix updwtmp, updwtmx unlocking + + Commit 5a3afa9738f3dbbaf8c0a35665318c1af782111b (login: Replace + macro-based control flow with function calls in utmp) introduced + a regression because after it, __libc_updwtmp attempts to unlock + the wrong file descriptor. + +diff --git a/login/Makefile b/login/Makefile +index 8b31991be835fa8e..81986ab6bd8560ea 100644 +--- a/login/Makefile ++++ b/login/Makefile +@@ -43,7 +43,7 @@ endif + subdir-dirs = programs + vpath %.c programs + +-tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin ++tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx + + # Build the -lutil library with these extra functions. + extra-libs := libutil +diff --git a/login/tst-updwtmpx.c b/login/tst-updwtmpx.c +new file mode 100644 +index 0000000000000000..0a4a27daeb0440fd +--- /dev/null ++++ b/login/tst-updwtmpx.c +@@ -0,0 +1,112 @@ ++/* Basic test coverage for updwtmpx. ++ 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; see the file COPYING.LIB. If ++ not, see . */ ++ ++/* This program runs a series of tests. Each one calls updwtmpx ++ twice, to write two records, optionally with misalignment in the ++ file, and reads back the results. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* Two entries filled with an arbitrary bit pattern. */ ++ struct utmpx entries[2]; ++ unsigned char pad; ++ { ++ unsigned char *p = (unsigned char *) &entries[0]; ++ for (size_t i = 0; i < sizeof (entries); ++i) ++ { ++ p[i] = i; ++ } ++ /* Make sure that the first and second entry and the padding are ++ different. */ ++ p[sizeof (struct utmpx)] = p[0] + 1; ++ pad = p[0] + 2; ++ } ++ ++ char *path; ++ int fd = create_temp_file ("tst-updwtmpx-", &path); ++ ++ /* Used to check that updwtmpx does not leave an open file ++ descriptor around. */ ++ struct support_descriptors *descriptors = support_descriptors_list (); ++ ++ /* updwtmpx is expected to remove misalignment. Optionally insert ++ one byte of misalignment at the start and in the middle (after ++ the first entry). */ ++ for (int misaligned_start = 0; misaligned_start < 2; ++misaligned_start) ++ for (int misaligned_middle = 0; misaligned_middle < 2; ++misaligned_middle) ++ { ++ if (test_verbose > 0) ++ printf ("info: misaligned_start=%d misaligned_middle=%d\n", ++ misaligned_start, misaligned_middle); ++ ++ xftruncate (fd, 0); ++ TEST_COMPARE (pwrite64 (fd, &pad, misaligned_start, 0), ++ misaligned_start); ++ ++ /* Write first entry and check it. */ ++ errno = 0; ++ updwtmpx (path, &entries[0]); ++ TEST_COMPARE (errno, 0); ++ support_descriptors_check (descriptors); ++ TEST_COMPARE (xlseek (fd, 0, SEEK_END), sizeof (struct utmpx)); ++ struct utmpx buffer; ++ TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), 0), ++ sizeof (buffer)); ++ TEST_COMPARE_BLOB (&entries[0], sizeof (entries[0]), ++ &buffer, sizeof (buffer)); ++ ++ /* Middle mis-alignmet. */ ++ TEST_COMPARE (pwrite64 (fd, &pad, misaligned_middle, ++ sizeof (struct utmpx)), misaligned_middle); ++ ++ /* Write second entry and check both entries. */ ++ errno = 0; ++ updwtmpx (path, &entries[1]); ++ TEST_COMPARE (errno, 0); ++ support_descriptors_check (descriptors); ++ TEST_COMPARE (xlseek (fd, 0, SEEK_END), 2 * sizeof (struct utmpx)); ++ TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), 0), ++ sizeof (buffer)); ++ TEST_COMPARE_BLOB (&entries[0], sizeof (entries[0]), ++ &buffer, sizeof (buffer)); ++ TEST_COMPARE (pread64 (fd, &buffer, sizeof (buffer), sizeof (buffer)), ++ sizeof (buffer)); ++ TEST_COMPARE_BLOB (&entries[1], sizeof (entries[1]), ++ &buffer, sizeof (buffer)); ++ } ++ ++ support_descriptors_free (descriptors); ++ free (path); ++ xclose (fd); ++ ++ return 0; ++} ++ ++#include +diff --git a/login/utmp_file.c b/login/utmp_file.c +index 812de8fd3d099ce9..54f424fd6165bae7 100644 +--- a/login/utmp_file.c ++++ b/login/utmp_file.c +@@ -503,7 +503,7 @@ __libc_updwtmp (const char *file, const struct utmp *utmp) + result = 0; + + unlock_return: +- file_unlock (file_fd); ++ file_unlock (fd); + file_lock_restore (&fl); + + /* Close WTMP file. */ diff --git a/glibc-rh1749439-5.patch b/glibc-rh1749439-5.patch new file mode 100755 index 0000000..b9cfe31 --- /dev/null +++ b/glibc-rh1749439-5.patch @@ -0,0 +1,33 @@ +commit 0d5b2917530ccaf8ad312dfbb7bce69d569c23ad +Author: Florian Weimer +Date: Thu Aug 15 16:09:20 2019 +0200 + + login: Use struct flock64 in utmp [BZ #24880] + + Commit 06ab719d30b01da401150068054d3b8ea93dd12f ("Fix Linux fcntl OFD + locks for non-LFS architectures (BZ#20251)") introduced the use of + fcntl64 into the utmp implementation. However, the lock file + structure was not updated to struct flock64 at that point. + +diff --git a/login/utmp_file.c b/login/utmp_file.c +index 54f424fd6165bae7..8b6fee96b623fa90 100644 +--- a/login/utmp_file.c ++++ b/login/utmp_file.c +@@ -85,7 +85,7 @@ try_file_lock (struct file_locking *locking, int fd, int type) + alarm (TIMEOUT); + + /* Try to get the lock. */ +- struct flock fl = ++ struct flock64 fl = + { + .l_type = type, + fl.l_whence = SEEK_SET, +@@ -96,7 +96,7 @@ try_file_lock (struct file_locking *locking, int fd, int type) + static void + file_unlock (int fd) + { +- struct flock fl = ++ struct flock64 fl = + { + .l_type = F_UNLCK, + }; diff --git a/glibc-rh1749439-6.patch b/glibc-rh1749439-6.patch new file mode 100755 index 0000000..3a8ad22 --- /dev/null +++ b/glibc-rh1749439-6.patch @@ -0,0 +1,204 @@ +commit 628598be7e1bfaa04f34df71ef6678f2c5103dfd +Author: Florian Weimer +Date: Thu Aug 15 16:09:05 2019 +0200 + + login: Disarm timer after utmp lock acquisition [BZ #24879] + + If the file processing takes a long time for some reason, SIGALRM can + arrive while the file is still being processed. At that point, file + access will fail with EINTR. Disarming the timer after lock + acquisition avoids that. (If there was a previous alarm, it is the + responsibility of the caller to deal with the EINTR error.) + +diff --git a/login/utmp_file.c b/login/utmp_file.c +index 8b6fee96b623fa90..a736d3d25e005920 100644 +--- a/login/utmp_file.c ++++ b/login/utmp_file.c +@@ -55,32 +55,23 @@ static void timeout_handler (int signum) {}; + + /* try_file_lock (LOCKING, FD, TYPE) returns true if the locking + operation failed and recovery needs to be performed. +- (file_lock_restore (LOCKING) still needs to be called.) + + file_unlock (FD) removes the lock (which must have been +- acquired). +- +- file_lock_restore (LOCKING) is needed to clean up in both +- cases. */ +- +-struct file_locking +-{ +- struct sigaction old_action; +- unsigned int old_timeout; +-}; ++ successfully acquired). */ + + static bool +-try_file_lock (struct file_locking *locking, int fd, int type) ++try_file_lock (int fd, int type) + { + /* Cancel any existing alarm. */ +- locking->old_timeout = alarm (0); ++ int old_timeout = alarm (0); + + /* Establish signal handler. */ ++ struct sigaction old_action; + struct sigaction action; + action.sa_handler = timeout_handler; + __sigemptyset (&action.sa_mask); + action.sa_flags = 0; +- __sigaction (SIGALRM, &action, &locking->old_action); ++ __sigaction (SIGALRM, &action, &old_action); + + alarm (TIMEOUT); + +@@ -90,7 +81,23 @@ try_file_lock (struct file_locking *locking, int fd, int type) + .l_type = type, + fl.l_whence = SEEK_SET, + }; +- return __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0; ++ ++ bool status = __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0; ++ int saved_errno = errno; ++ ++ /* Reset the signal handler and alarm. We must reset the alarm ++ before resetting the handler so our alarm does not generate a ++ spurious SIGALRM seen by the user. However, we cannot just set ++ the user's old alarm before restoring the handler, because then ++ it's possible our handler could catch the user alarm's SIGARLM and ++ then the user would never see the signal he expected. */ ++ alarm (0); ++ __sigaction (SIGALRM, &old_action, NULL); ++ if (old_timeout != 0) ++ alarm (old_timeout); ++ ++ __set_errno (saved_errno); ++ return status; + } + + static void +@@ -103,21 +110,6 @@ file_unlock (int fd) + __fcntl64_nocancel (fd, F_SETLKW, &fl); + } + +-static void +-file_lock_restore (struct file_locking *locking) +-{ +- /* Reset the signal handler and alarm. We must reset the alarm +- before resetting the handler so our alarm does not generate a +- spurious SIGALRM seen by the user. However, we cannot just set +- the user's old alarm before restoring the handler, because then +- it's possible our handler could catch the user alarm's SIGARLM +- and then the user would never see the signal he expected. */ +- alarm (0); +- __sigaction (SIGALRM, &locking->old_action, NULL); +- if (locking->old_timeout != 0) +- alarm (locking->old_timeout); +-} +- + #ifndef TRANSFORM_UTMP_FILE_NAME + # define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name) + #endif +@@ -166,8 +158,7 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result) + return -1; + } + +- struct file_locking fl; +- if (try_file_lock (&fl, file_fd, F_RDLCK)) ++ if (try_file_lock (file_fd, F_RDLCK)) + nbytes = 0; + else + { +@@ -175,7 +166,6 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result) + nbytes = __read_nocancel (file_fd, &last_entry, sizeof (struct utmp)); + file_unlock (file_fd); + } +- file_lock_restore (&fl); + + if (nbytes != sizeof (struct utmp)) + { +@@ -201,11 +191,9 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer, + { + int result = -1; + +- struct file_locking fl; +- if (try_file_lock (&fl, file_fd, F_RDLCK)) ++ if (try_file_lock (file_fd, F_RDLCK)) + { + *lock_failed = true; +- file_lock_restore (&fl); + return -1; + } + +@@ -257,7 +245,6 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer, + + unlock_return: + file_unlock (file_fd); +- file_lock_restore (&fl); + + return result; + } +@@ -303,11 +290,9 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer, + return -1; + } + +- struct file_locking fl; +- if (try_file_lock (&fl, file_fd, F_RDLCK)) ++ if (try_file_lock (file_fd, F_RDLCK)) + { + *result = NULL; +- file_lock_restore (&fl); + return -1; + } + +@@ -337,7 +322,6 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer, + + unlock_return: + file_unlock (file_fd); +- file_lock_restore (&fl); + + return ((*result == NULL) ? -1 : 0); + } +@@ -394,12 +378,8 @@ __libc_pututline (const struct utmp *data) + } + } + +- struct file_locking fl; +- if (try_file_lock (&fl, file_fd, F_WRLCK)) +- { +- file_lock_restore (&fl); +- return NULL; +- } ++ if (try_file_lock (file_fd, F_WRLCK)) ++ return NULL; + + if (found < 0) + { +@@ -442,7 +422,6 @@ __libc_pututline (const struct utmp *data) + + unlock_return: + file_unlock (file_fd); +- file_lock_restore (&fl); + + return pbuf; + } +@@ -471,10 +450,8 @@ __libc_updwtmp (const char *file, const struct utmp *utmp) + if (fd < 0) + return -1; + +- struct file_locking fl; +- if (try_file_lock (&fl, fd, F_WRLCK)) ++ if (try_file_lock (fd, F_WRLCK)) + { +- file_lock_restore (&fl); + __close_nocancel_nostatus (fd); + return -1; + } +@@ -504,7 +481,6 @@ __libc_updwtmp (const char *file, const struct utmp *utmp) + + unlock_return: + file_unlock (fd); +- file_lock_restore (&fl); + + /* Close WTMP file. */ + __close_nocancel_nostatus (fd); diff --git a/glibc-rh1749439-7.patch b/glibc-rh1749439-7.patch new file mode 100755 index 0000000..370dab2 --- /dev/null +++ b/glibc-rh1749439-7.patch @@ -0,0 +1,309 @@ +commit 61d3db428176d9d0822e4e680305fe34285edff2 +Author: Florian Weimer +Date: Wed Aug 28 11:59:45 2019 +0200 + + login: pututxline could fail to overwrite existing entries [BZ #24902] + + The internal_getut_r function updates the file_offset variable and + therefore must always update last_entry as well. + + Previously, if pututxline could not upgrade the read lock to a + write lock, internal_getut_r would update file_offset only, + without updating last_entry, and a subsequent call would not + overwrite the existing utmpx entry at file_offset, instead + creating a new entry. This has been observed to cause unbounded + file growth in high-load situations. + + This commit removes the buffer argument to internal_getut_r and + updates the last_entry variable directly, along with file_offset. + + Initially reported and fixed by Ondřej Lysoněk. + + Reviewed-by: Gabriel F. T. Gomes + +diff --git a/login/Makefile b/login/Makefile +index 81986ab6bd8560ea..82132c83fd799357 100644 +--- a/login/Makefile ++++ b/login/Makefile +@@ -43,7 +43,8 @@ endif + subdir-dirs = programs + vpath %.c programs + +-tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx ++tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx \ ++ tst-pututxline-lockfail + + # Build the -lutil library with these extra functions. + extra-libs := libutil +@@ -71,3 +72,5 @@ endif + $(inst_libexecdir)/pt_chown: $(objpfx)pt_chown $(+force) + $(make-target-directory) + -$(INSTALL_PROGRAM) -m 4755 -o root $< $@ ++ ++$(objpfx)tst-pututxline-lockfail: $(shared-thread-library) +diff --git a/login/tst-pututxline-lockfail.c b/login/tst-pututxline-lockfail.c +new file mode 100644 +index 0000000000000000..47c25dc0658d3c60 +--- /dev/null ++++ b/login/tst-pututxline-lockfail.c +@@ -0,0 +1,176 @@ ++/* Test the lock upgrade path in tst-pututxline. ++ 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; see the file COPYING.LIB. If ++ not, see . */ ++ ++/* pututxline upgrades the read lock on the file to a write lock. ++ This test verifies that if the lock upgrade fails, the utmp ++ subsystem remains in a consistent state, so that pututxline can be ++ called again. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Path to the temporary utmp file. */ ++static char *path; ++ ++/* Used to synchronize the subprocesses. The barrier itself is ++ allocated in shared memory. */ ++static pthread_barrier_t *barrier; ++ ++/* Use pututxline to write an entry for PID. */ ++static struct utmpx * ++write_entry (pid_t pid) ++{ ++ struct utmpx ut = ++ { ++ .ut_type = LOGIN_PROCESS, ++ .ut_id = "1", ++ .ut_user = "root", ++ .ut_pid = pid, ++ .ut_line = "entry", ++ .ut_host = "localhost", ++ }; ++ return pututxline (&ut); ++} ++ ++/* Create the initial entry in a subprocess, so that the utmp ++ subsystem in the original process is not disturbed. */ ++static void ++subprocess_create_entry (void *closure) ++{ ++ TEST_COMPARE (utmpname (path), 0); ++ TEST_VERIFY (write_entry (101) != NULL); ++} ++ ++/* Acquire an advisory read lock on PATH. */ ++__attribute__ ((noreturn)) static void ++subprocess_lock_file (void) ++{ ++ int fd = xopen (path, O_RDONLY, 0); ++ ++ struct flock64 fl = ++ { ++ .l_type = F_RDLCK, ++ fl.l_whence = SEEK_SET, ++ }; ++ TEST_COMPARE (fcntl64 (fd, F_SETLKW, &fl), 0); ++ ++ /* Signal to the main process that the lock has been acquired. */ ++ xpthread_barrier_wait (barrier); ++ ++ /* Wait for the unlock request from the main process. */ ++ xpthread_barrier_wait (barrier); ++ ++ /* Implicitly unlock the file. */ ++ xclose (fd); ++ ++ /* Overwrite the existing entry. */ ++ TEST_COMPARE (utmpname (path), 0); ++ errno = 0; ++ setutxent (); ++ TEST_COMPARE (errno, 0); ++ TEST_VERIFY (write_entry (102) != NULL); ++ errno = 0; ++ endutxent (); ++ TEST_COMPARE (errno, 0); ++ ++ _exit (0); ++} ++ ++static int ++do_test (void) ++{ ++ xclose (create_temp_file ("tst-pututxline-lockfail-", &path)); ++ ++ { ++ pthread_barrierattr_t attr; ++ xpthread_barrierattr_init (&attr); ++ xpthread_barrierattr_setpshared (&attr, PTHREAD_SCOPE_PROCESS); ++ barrier = support_shared_allocate (sizeof (*barrier)); ++ xpthread_barrier_init (barrier, &attr, 2); ++ xpthread_barrierattr_destroy (&attr); ++ } ++ ++ /* Write the initial entry. */ ++ support_isolate_in_subprocess (subprocess_create_entry, NULL); ++ ++ pid_t locker_pid = xfork (); ++ if (locker_pid == 0) ++ subprocess_lock_file (); ++ ++ /* Wait for the file locking to complete. */ ++ xpthread_barrier_wait (barrier); ++ ++ /* Try to add another entry. This attempt will fail, with EINTR or ++ EAGAIN. */ ++ TEST_COMPARE (utmpname (path), 0); ++ TEST_VERIFY (write_entry (102) == NULL); ++ if (errno != EINTR) ++ TEST_COMPARE (errno, EAGAIN); ++ ++ /* Signal the subprocess to overwrite the entry. */ ++ xpthread_barrier_wait (barrier); ++ ++ /* Wait for write and unlock to complete. */ ++ { ++ int status; ++ xwaitpid (locker_pid, &status, 0); ++ TEST_COMPARE (status, 0); ++ } ++ ++ /* The file is no longer locked, so this operation will succeed. */ ++ TEST_VERIFY (write_entry (103) != NULL); ++ errno = 0; ++ endutxent (); ++ TEST_COMPARE (errno, 0); ++ ++ /* Check that there is just one entry with the expected contents. ++ If pututxline becomes desynchronized internally, the entry is not ++ overwritten (bug 24902). */ ++ errno = 0; ++ setutxent (); ++ TEST_COMPARE (errno, 0); ++ struct utmpx *ut = getutxent (); ++ TEST_VERIFY_EXIT (ut != NULL); ++ TEST_COMPARE (ut->ut_type, LOGIN_PROCESS); ++ TEST_COMPARE_STRING (ut->ut_id, "1"); ++ TEST_COMPARE_STRING (ut->ut_user, "root"); ++ TEST_COMPARE (ut->ut_pid, 103); ++ TEST_COMPARE_STRING (ut->ut_line, "entry"); ++ TEST_COMPARE_STRING (ut->ut_host, "localhost"); ++ TEST_VERIFY (getutxent () == NULL); ++ errno = 0; ++ endutxent (); ++ TEST_COMPARE (errno, 0); ++ ++ xpthread_barrier_destroy (barrier); ++ support_shared_free (barrier); ++ free (path); ++ return 0; ++} ++ ++#include +diff --git a/login/utmp_file.c b/login/utmp_file.c +index a736d3d25e005920..cbc53d06de280af9 100644 +--- a/login/utmp_file.c ++++ b/login/utmp_file.c +@@ -185,9 +185,11 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result) + } + + ++/* Search for *ID, updating last_entry and file_offset. Return 0 on ++ success and -1 on failure. If the locking operation failed, write ++ true to *LOCK_FAILED. */ + static int +-internal_getut_r (const struct utmp *id, struct utmp *buffer, +- bool *lock_failed) ++internal_getut_r (const struct utmp *id, bool *lock_failed) + { + int result = -1; + +@@ -206,7 +208,7 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer, + while (1) + { + /* Read the next entry. */ +- if (__read_nocancel (file_fd, buffer, sizeof (struct utmp)) ++ if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp)) + != sizeof (struct utmp)) + { + __set_errno (ESRCH); +@@ -215,7 +217,7 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer, + } + file_offset += sizeof (struct utmp); + +- if (id->ut_type == buffer->ut_type) ++ if (id->ut_type == last_entry.ut_type) + break; + } + } +@@ -227,7 +229,7 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer, + while (1) + { + /* Read the next entry. */ +- if (__read_nocancel (file_fd, buffer, sizeof (struct utmp)) ++ if (__read_nocancel (file_fd, &last_entry, sizeof (struct utmp)) + != sizeof (struct utmp)) + { + __set_errno (ESRCH); +@@ -236,7 +238,7 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer, + } + file_offset += sizeof (struct utmp); + +- if (__utmp_equal (buffer, id)) ++ if (__utmp_equal (&last_entry, id)) + break; + } + } +@@ -265,7 +267,7 @@ __libc_getutid_r (const struct utmp *id, struct utmp *buffer, + /* We don't have to distinguish whether we can lock the file or + whether there is no entry. */ + bool lock_failed = false; +- if (internal_getut_r (id, &last_entry, &lock_failed) < 0) ++ if (internal_getut_r (id, &lock_failed) < 0) + { + *result = NULL; + return -1; +@@ -330,10 +332,9 @@ unlock_return: + struct utmp * + __libc_pututline (const struct utmp *data) + { +- if (!maybe_setutent ()) ++ if (!maybe_setutent () || file_offset == -1l) + return NULL; + +- struct utmp buffer; + struct utmp *pbuf; + int found; + +@@ -369,7 +370,7 @@ __libc_pututline (const struct utmp *data) + else + { + bool lock_failed = false; +- found = internal_getut_r (data, &buffer, &lock_failed); ++ found = internal_getut_r (data, &lock_failed); + + if (__builtin_expect (lock_failed, false)) + { diff --git a/glibc-rh1749439-8.patch b/glibc-rh1749439-8.patch new file mode 100755 index 0000000..3fc23cf --- /dev/null +++ b/glibc-rh1749439-8.patch @@ -0,0 +1,86 @@ +commit c2adefbafcdd2519ff43eca6891c77cd7b29ab62 +Author: Florian Weimer +Date: Thu Aug 15 16:09:43 2019 +0200 + + login: Add nonstring attributes to struct utmp, struct utmpx [BZ #24899] + + Commit 7532837d7b03b3ca5b9a63d77a5bd81dd23f3d9c ("The + -Wstringop-truncation option new in GCC 8 detects common misuses") + added __attribute_nonstring__ to bits/utmp.h, but it did not update + the parallel bits/utmpx.h header. In struct utmp, the nonstring + attribute for ut_id was missing. + +diff --git a/bits/utmp.h b/bits/utmp.h +index 3c02dd4f3fe4e99b..854b342164b785e0 100644 +--- a/bits/utmp.h ++++ b/bits/utmp.h +@@ -61,7 +61,8 @@ struct utmp + pid_t ut_pid; /* Process ID of login process. */ + char ut_line[UT_LINESIZE] + __attribute_nonstring__; /* Devicename. */ +- char ut_id[4]; /* Inittab ID. */ ++ char ut_id[4] ++ __attribute_nonstring__; /* Inittab ID. */ + char ut_user[UT_NAMESIZE] + __attribute_nonstring__; /* Username. */ + char ut_host[UT_HOSTSIZE] +diff --git a/sysdeps/gnu/bits/utmpx.h b/sysdeps/gnu/bits/utmpx.h +index 2a77efc607ae2ac0..71c743ebfcd41194 100644 +--- a/sysdeps/gnu/bits/utmpx.h ++++ b/sysdeps/gnu/bits/utmpx.h +@@ -56,10 +56,14 @@ struct utmpx + { + short int ut_type; /* Type of login. */ + __pid_t ut_pid; /* Process ID of login process. */ +- char ut_line[__UT_LINESIZE]; /* Devicename. */ +- char ut_id[4]; /* Inittab ID. */ +- char ut_user[__UT_NAMESIZE]; /* Username. */ +- char ut_host[__UT_HOSTSIZE]; /* Hostname for remote login. */ ++ char ut_line[__UT_LINESIZE] ++ __attribute_nonstring__; /* Devicename. */ ++ char ut_id[4] ++ __attribute_nonstring__; /* Inittab ID. */ ++ char ut_user[__UT_NAMESIZE] ++ __attribute_nonstring__; /* Username. */ ++ char ut_host[__UT_HOSTSIZE] ++ __attribute_nonstring__; /* Hostname for remote login. */ + struct __exit_status ut_exit; /* Exit status of a process marked + as DEAD_PROCESS. */ + +diff --git a/sysdeps/unix/sysv/linux/s390/bits/utmp.h b/sysdeps/unix/sysv/linux/s390/bits/utmp.h +index b3fa362f478ae6fe..82e8d17e2e8cc031 100644 +--- a/sysdeps/unix/sysv/linux/s390/bits/utmp.h ++++ b/sysdeps/unix/sysv/linux/s390/bits/utmp.h +@@ -61,7 +61,8 @@ struct utmp + pid_t ut_pid; /* Process ID of login process. */ + char ut_line[UT_LINESIZE] + __attribute_nonstring__; /* Devicename. */ +- char ut_id[4]; /* Inittab ID. */ ++ char ut_id[4] ++ __attribute_nonstring__; /* Inittab ID. */ + char ut_user[UT_NAMESIZE] + __attribute_nonstring__; /* Username. */ + char ut_host[UT_HOSTSIZE] +diff --git a/sysdeps/unix/sysv/linux/s390/bits/utmpx.h b/sysdeps/unix/sysv/linux/s390/bits/utmpx.h +index 3d3036c3b91e6f57..3818ed3aa4df1e65 100644 +--- a/sysdeps/unix/sysv/linux/s390/bits/utmpx.h ++++ b/sysdeps/unix/sysv/linux/s390/bits/utmpx.h +@@ -56,10 +56,14 @@ struct utmpx + { + short int ut_type; /* Type of login. */ + __pid_t ut_pid; /* Process ID of login process. */ +- char ut_line[__UT_LINESIZE]; /* Devicename. */ +- char ut_id[4]; /* Inittab ID. */ +- char ut_user[__UT_NAMESIZE]; /* Username. */ +- char ut_host[__UT_HOSTSIZE]; /* Hostname for remote login. */ ++ char ut_line[__UT_LINESIZE] ++ __attribute_nonstring__; /* Devicename. */ ++ char ut_id[4] ++ __attribute_nonstring__; /* Inittab ID. */ ++ char ut_user[__UT_NAMESIZE] ++ __attribute_nonstring__; /* Username. */ ++ char ut_host[__UT_HOSTSIZE] ++ __attribute_nonstring__; /* Hostname for remote login. */ + struct __exit_status ut_exit; /* Exit status of a process marked + as DEAD_PROCESS. */ + diff --git a/glibc-rh1749439-9.patch b/glibc-rh1749439-9.patch new file mode 100755 index 0000000..0a8470b --- /dev/null +++ b/glibc-rh1749439-9.patch @@ -0,0 +1,26 @@ +commit b0a83ae71b2588bd2a9e6b40f95191602940e01e +Author: Florian Weimer +Date: Thu Nov 7 09:53:41 2019 +0100 + + login: Remove double-assignment of fl.l_whence in try_file_lock + + Since l_whence is the second member of struct flock, it is written + twice. The double-assignment is technically undefined behavior due to + the lack of a sequence point. + + Reviewed-by: Carlos O'Donell + Change-Id: I2baf9e70690e723c61051b25ccbd510aec15976c + +diff --git a/login/utmp_file.c b/login/utmp_file.c +index cbc53d06de280af9..9ad80364682bae92 100644 +--- a/login/utmp_file.c ++++ b/login/utmp_file.c +@@ -79,7 +79,7 @@ try_file_lock (int fd, int type) + struct flock64 fl = + { + .l_type = type, +- fl.l_whence = SEEK_SET, ++ .l_whence = SEEK_SET, + }; + + bool status = __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0; diff --git a/glibc-rh1757354.patch b/glibc-rh1757354.patch new file mode 100755 index 0000000..d159b26 --- /dev/null +++ b/glibc-rh1757354.patch @@ -0,0 +1,1163 @@ +commit 8e42fc6811ba94a01e194d46572c3cf803b3aae0 +Author: Mike FABIAN +Date: Tue Sep 17 17:20:32 2019 +0200 + + Sync "language", "lang_name", "territory", "country_name" with CLDR/langtable + + Sync these values with CLDR and langtable as much as possible. Add + missing values. + + If possible, take the values from CLDR, if CLDR does not have it, + take it from langtable. The values from langtable which are not from + CLDR are from Wikipedia or native speakers. + +diff --git a/localedata/locales/az_AZ b/localedata/locales/az_AZ +index 6fe8839f25cc7450..3c0db0be3de1e6d3 100644 +--- a/localedata/locales/az_AZ ++++ b/localedata/locales/az_AZ +@@ -243,7 +243,7 @@ country_ab3 "AZE" + country_num 031 + country_car "AZ" + % Azərbaycanca +-lang_name "azrbaycan dili" ++lang_name "azrbaycan" + lang_ab "az" + lang_term "aze" + lang_lib "aze" +diff --git a/localedata/locales/be_BY@latin b/localedata/locales/be_BY@latin +index 43b13cc27812aaa0..fef339f6247a0eb6 100644 +--- a/localedata/locales/be_BY@latin ++++ b/localedata/locales/be_BY@latin +@@ -156,7 +156,7 @@ country_ab2 "BY" + country_ab3 "BLR" + country_num 112 + country_car "BY" +-lang_name "biearuskaja mova" ++lang_name "biearuskaja" + lang_ab "be" + lang_term "bel" + lang_lib "bel" +diff --git a/localedata/locales/ber_DZ b/localedata/locales/ber_DZ +index 79f3d289b1ee771c..4fa1bdfff94b9efd 100644 +--- a/localedata/locales/ber_DZ ++++ b/localedata/locales/ber_DZ +@@ -8,7 +8,7 @@ escape_char / + % exempt you from the conditions of the license if your use would + % otherwise be governed by that license. + +-% Amazigh Language Locale for Algeria (latin) ++% Berber Language Locale for Algeria (latin) + % Source: + % Contact: Pablo Saratxaga + % Email: +@@ -20,14 +20,14 @@ escape_char / + % Users: general + + LC_IDENTIFICATION +-title "Amazigh language locale for Algeria (latin)" ++title "Berber language locale for Algeria (latin)" + source "" + address "" + contact "Pablo Saratxaga" + email "pablo@mandrakesoft.com" + tel "" + fax "" +-language "Amazigh" ++language "Berber" + territory "Algeria" + revision "0.1" + date "2002-04-16" +@@ -253,14 +253,15 @@ LC_ADDRESS + % This is the ISO_IEC TR14652 Locale definition for the + % LC_ADDRESS + postal_fmt "%z%c%T%s%b%e%r" ++country_name "Lezzayer" + %country_post "" + country_ab2 "DZ" + country_ab3 "DZA" + country_num 012 + %country_isbn "" + country_car "DZ" +-% ⵜⴰⵎⴰⵣⵉⵖⵜ +-lang_name "" ++% Tamaziɣt ++lang_name "Tamazit" + %lang_ab + lang_term "ber" + lang_lib "ber" +diff --git a/localedata/locales/ber_MA b/localedata/locales/ber_MA +index b9bd64868cda3412..5d19354ad65069eb 100644 +--- a/localedata/locales/ber_MA ++++ b/localedata/locales/ber_MA +@@ -8,7 +8,7 @@ escape_char / + % exempt you from the conditions of the license if your use would + % otherwise be governed by that license. + +-% Amazigh Language Locale for Morocco (tifinagh) ++% Berber Language Locale for Morocco (tifinagh) + % Source: + % Contact: Pablo Saratxaga + % Email: +@@ -20,14 +20,14 @@ escape_char / + % Users: general + + LC_IDENTIFICATION +-title "Amazigh language locale for Morocco (tifinagh)" ++title "Berber language locale for Morocco (tifinagh)" + source "" + address "" + contact "Pablo Saratxaga" + email "pablo@mandrakesoft.com" + tel "" + fax "" +-language "Amazigh" ++language "Berber" + territory "Morocco" + revision "0.1" + date "2002-06-26" +@@ -204,6 +204,8 @@ LC_ADDRESS + % This is the ISO_IEC TR14652 Locale definition for the + % LC_ADDRESS + postal_fmt "%z%c%T%s%b%e%r" ++% https://en.wikipedia.org/wiki/Morocco ⵜⴰⴳⵍⴷⵉⵜ ⵏ ⵍⵎⵖⵔⵉⴱ ++country_name " " + %country_post "" + country_ab2 "MA" + country_ab3 "MAR" +@@ -211,7 +213,7 @@ country_num 504 + %country_isbn "" + country_car "MA" + % ⵜⴰⵎⴰⵣⵉⵖⵜ +-lang_name "" ++lang_name "" + % lang_ab + lang_term "ber" + lang_lib "ber" +diff --git a/localedata/locales/bhb_IN b/localedata/locales/bhb_IN +index 549974de2cfd4843..80d590d068582de6 100644 +--- a/localedata/locales/bhb_IN ++++ b/localedata/locales/bhb_IN +@@ -145,11 +145,13 @@ LC_ADDRESS + % This is the ISO_IEC TR14652 Locale definition for the LC_ADDRESS category + % generated by IBM Basic CountryPack Transformer. + postal_fmt "%z%c%T%s%b%e%r" ++country_name "" + country_ab2 "IN" + country_ab3 "IND" + country_car "IND" + country_num 356 +-lang_name "bhili" ++% भीली ++lang_name "" + lang_ab "" + lang_term "bhb" + lang_lib "bhb" +diff --git a/localedata/locales/bho_IN b/localedata/locales/bho_IN +index 99a91c2553ecdeae..4a0f25d6aceaa023 100644 +--- a/localedata/locales/bho_IN ++++ b/localedata/locales/bho_IN +@@ -147,6 +147,7 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%z%c%T%s%b%e%r" ++country_name "" + country_ab2 "IN" + country_ab3 "IND" + country_num 356 +diff --git a/localedata/locales/chr_US b/localedata/locales/chr_US +index 290d1b24551dd3ba..86868c02e9ae2e1c 100644 +--- a/localedata/locales/chr_US ++++ b/localedata/locales/chr_US +@@ -113,7 +113,7 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%a%N%f%N%d%N%b%N%h %s %e %r%N%T, %S %z%N%c%N" +-country_name "" ++country_name "" + country_post "USA" + country_ab2 "US" + country_ab3 "USA" +diff --git a/localedata/locales/crh_UA b/localedata/locales/crh_UA +index b2ac8c66d78521b0..86281a27db1cc64d 100644 +--- a/localedata/locales/crh_UA ++++ b/localedata/locales/crh_UA +@@ -198,8 +198,8 @@ country_ab2 "UA" + country_ab3 "UKR" + country_num 804 + country_car "UA" +-% Qırımtatarca +-lang_name "Qrmtatarca" ++% qırımtatar tili ++lang_name "qrmtatar tili" + lang_term "crh" + lang_lib "crh" + END LC_ADDRESS +diff --git a/localedata/locales/csb_PL b/localedata/locales/csb_PL +index c8572f8fc54853b3..662dcefa15a2cae3 100644 +--- a/localedata/locales/csb_PL ++++ b/localedata/locales/csb_PL +@@ -210,6 +210,7 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%z %T%N%c%N" ++country_name "Plsk" + country_ab2 "PL" + country_ab3 "POL" + country_num 616 +diff --git a/localedata/locales/doi_IN b/localedata/locales/doi_IN +index 0428ae50a9bf60e8..df9dfc6e2a428abb 100644 +--- a/localedata/locales/doi_IN ++++ b/localedata/locales/doi_IN +@@ -156,6 +156,7 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%z%c%T%s%b%e%r" ++country_name "" + country_ab2 "IN" + country_ab3 "IND" + country_num 356 +diff --git a/localedata/locales/dv_MV b/localedata/locales/dv_MV +index 0d7842f39f7edf85..ab78fa5ce33cfe0e 100644 +--- a/localedata/locales/dv_MV ++++ b/localedata/locales/dv_MV +@@ -182,9 +182,8 @@ country_ab2 "MV" + country_ab3 "MDV" + country_num 462 + country_car "MV" +-% lang_name FIXME +-% Cannot represent Dhivehi in Thaana script +-% http://en.wikipedia.org/wiki/Maldivian_language ++% ދިވެހި ++lang_name "" + lang_ab "dv" + lang_term "div" + lang_lib "div" +diff --git a/localedata/locales/eo b/localedata/locales/eo +index 33a81033e23caadd..b2ad5758004b67d8 100644 +--- a/localedata/locales/eo ++++ b/localedata/locales/eo +@@ -206,7 +206,7 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%%z %T%N%c%N" +-lang_name "Esperanto" ++lang_name "esperanto" + lang_ab "eo" + lang_term "epo" + END LC_ADDRESS +diff --git a/localedata/locales/hak_TW b/localedata/locales/hak_TW +index f62937e91b634416..87f2a00489d1574e 100644 +--- a/localedata/locales/hak_TW ++++ b/localedata/locales/hak_TW +@@ -187,8 +187,8 @@ country_ab3 "TWN" + country_num 158 + country_car "RC" + country_isbn 957 +-% 漢語客家語 +-lang_name "" ++% 客家語 ++lang_name "" + lang_term "hak" + lang_lib "hak" + END LC_ADDRESS +diff --git a/localedata/locales/hif_FJ b/localedata/locales/hif_FJ +index 5433bb4a2a54636e..a6868b791025c8f4 100644 +--- a/localedata/locales/hif_FJ ++++ b/localedata/locales/hif_FJ +@@ -176,7 +176,8 @@ country_car "FJI" + country_num 242 + % https://en.wikipedia.org/wiki/ISO_3166-1_numeric + % https://en.wikipedia.org/wiki/Fiji_Hindi +-lang_name "Fiji Baat" ++% फ़िजी बात ++lang_name "" + % iso-639-1 + lang_ab "" + % iso-639-3 +diff --git a/localedata/locales/hne_IN b/localedata/locales/hne_IN +index 7abec636304b9e67..d8b83610165a6844 100644 +--- a/localedata/locales/hne_IN ++++ b/localedata/locales/hne_IN +@@ -154,6 +154,7 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%z%c%T%s%b%e%r" ++country_name "" + country_ab2 "IN" + country_ab3 "IND" + country_num 356 +diff --git a/localedata/locales/ia_FR b/localedata/locales/ia_FR +index f3fbf213a3f7f267..4ce7c7fe4a416541 100644 +--- a/localedata/locales/ia_FR ++++ b/localedata/locales/ia_FR +@@ -127,7 +127,7 @@ country_ab3 "FRA" + country_num 250 + country_isbn "979-10" + country_car "F" +-lang_name "Interlingua" ++lang_name "interlingua" + lang_ab "ia" + lang_term "ina" + lang_lib "ina" +diff --git a/localedata/locales/id_ID b/localedata/locales/id_ID +index 3ddd8d07daed6697..92ff81df23b059a0 100644 +--- a/localedata/locales/id_ID ++++ b/localedata/locales/id_ID +@@ -155,7 +155,7 @@ country_ab2 "ID" + country_ab3 "IDN" + country_num 360 + country_car "RI" +-lang_name "Bahasa Indonesia" ++lang_name "Indonesia" + lang_ab "id" + lang_term "ind" + lang_lib "ind" +diff --git a/localedata/locales/ig_NG b/localedata/locales/ig_NG +index bddd2ccde523dca8..113294a0f58ab576 100644 +--- a/localedata/locales/ig_NG ++++ b/localedata/locales/ig_NG +@@ -321,11 +321,11 @@ LC_ADDRESS + % "end of line + postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%z %T%N%c%N" + +-% Country name in Igbo - "Nigeria" +-country_name "Nigeria" ++% Country name in Igbo - "Naịjịrịa" ++country_name "Najra" + +-% Language name in Igbo - "Igbo" +-lang_name "Igbo" ++% Language name in Igbo - "Asụsụ Igbo" ++lang_name "Ass Igbo" + + % CEPT MAILCODES are suggested + % Alternatively use the code found on your countries postal item tracking number +diff --git a/localedata/locales/kab_DZ b/localedata/locales/kab_DZ +index a165f53f01370c94..ef572357c22615f7 100644 +--- a/localedata/locales/kab_DZ ++++ b/localedata/locales/kab_DZ +@@ -154,7 +154,7 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%z %T%N%c%N" +-country_name "Zzayer" ++country_name "Lezzayer" + country_ab2 "DZ" + country_ab3 "DZA" + country_num 012 +diff --git a/localedata/locales/ks_IN b/localedata/locales/ks_IN +index 6992a5536887d9f6..e1efea342d4b55a0 100644 +--- a/localedata/locales/ks_IN ++++ b/localedata/locales/ks_IN +@@ -167,7 +167,7 @@ LC_ADDRESS + % This is the ISO_IEC TR14652 Locale definition for the LC_ADDRESS category + % generated by IBM Basic CountryPack Transformer. + postal_fmt "%z%c%T%s%b%e%r" +-country_name "" ++country_name "" + country_ab2 "IN" + country_ab3 "IND" + country_num 356 +diff --git a/localedata/locales/ku_TR b/localedata/locales/ku_TR +index 595cdb14bc9ef29d..f6a8925608ea046d 100644 +--- a/localedata/locales/ku_TR ++++ b/localedata/locales/ku_TR +@@ -182,14 +182,14 @@ END LC_NAME + LC_ADDRESS + postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%z %T%N%c%N" + % TODO +-country_name "Turkey" ++country_name "Tirkiye" + country_post "TR" + country_ab2 "TR" + country_ab3 "TUR" + country_num 792 + country_isbn 975 + country_car "TR" +-lang_name "kurdi" ++lang_name "kurd" + lang_ab "ku" + lang_term "kur" + lang_lib "kur" +diff --git a/localedata/locales/mag_IN b/localedata/locales/mag_IN +index b8f65f70e26f4481..c86d9ba075ef2577 100644 +--- a/localedata/locales/mag_IN ++++ b/localedata/locales/mag_IN +@@ -152,6 +152,7 @@ END LC_NAME + LC_ADDRESS + + postal_fmt "%z%c%T%s%b%e%r" ++country_name "" + country_ab2 "IN" + country_ab3 "IND" + country_num 356 +diff --git a/localedata/locales/mfe_MU b/localedata/locales/mfe_MU +index 7415e9250fb78d50..7fabc5f80d9ae5e5 100644 +--- a/localedata/locales/mfe_MU ++++ b/localedata/locales/mfe_MU +@@ -170,7 +170,7 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%f%N%h%s%N%T" +-country_name "Mauritius" ++country_name "Moris" + country_ab2 "MU" + country_ab3 "MUS" + country_num 480 +diff --git a/localedata/locales/mhr_RU b/localedata/locales/mhr_RU +index 85ac21b35af25c87..02bec3e9aed6fddc 100644 +--- a/localedata/locales/mhr_RU ++++ b/localedata/locales/mhr_RU +@@ -159,6 +159,8 @@ country_ab2 "RU" + country_ab3 "RUS" + country_num 643 + country_car "RUS" ++% марий йылме ++lang_name " " + lang_term "mhr" + lang_lib "mhr" + END LC_ADDRESS +diff --git a/localedata/locales/mi_NZ b/localedata/locales/mi_NZ +index 782f02359cb096d4..d08bc249427581c2 100644 +--- a/localedata/locales/mi_NZ ++++ b/localedata/locales/mi_NZ +@@ -157,7 +157,7 @@ country_ab2 "NZ" + country_ab3 "NZL" + country_num 554 + country_car "NZ" +-lang_name "Te Reo" ++lang_name "Mori" + lang_ab "mi" + lang_term "mri" + lang_lib "mao" +diff --git a/localedata/locales/ms_MY b/localedata/locales/ms_MY +index 66b5dd98e99e5da3..8ffe9156b6e3d022 100644 +--- a/localedata/locales/ms_MY ++++ b/localedata/locales/ms_MY +@@ -184,7 +184,7 @@ country_ab3 "MYS" + country_num 458 + country_car "MAL" + % Bahasa Melayu +-lang_name "Bahasa Melayu" ++lang_name "Melayu" + lang_ab "ms" + lang_term "msa" + lang_lib "may" +diff --git a/localedata/locales/my_MM b/localedata/locales/my_MM +index d612e5305aff7e2b..846363223883723b 100644 +--- a/localedata/locales/my_MM ++++ b/localedata/locales/my_MM +@@ -309,7 +309,8 @@ country_ab2 "MM" + country_num 104 + country_car "MYA" + lang_ab "my" +-lang_name "" ++% မြန်မာ ++lang_name "" + lang_term "mya" + lang_lib "bur" + END LC_ADDRESS +diff --git a/localedata/locales/nan_TW b/localedata/locales/nan_TW +index f5bc5d1642c2ce9b..53884e02ffd16d2c 100644 +--- a/localedata/locales/nan_TW ++++ b/localedata/locales/nan_TW +@@ -188,8 +188,8 @@ country_ab3 "TWN" + country_num 158 + country_car "RC" + country_isbn 957 +-% 漢語閩南語 +-lang_name "" ++% 閩南語 ++lang_name "" + lang_term "nan" + lang_lib "nan" + END LC_ADDRESS +diff --git a/localedata/locales/nan_TW@latin b/localedata/locales/nan_TW@latin +index d4579a4cdf032d4c..104f4152a98b37ab 100644 +--- a/localedata/locales/nan_TW@latin ++++ b/localedata/locales/nan_TW@latin +@@ -165,8 +165,8 @@ country_ab3 "TWN" + country_num 158 + country_car "RC" + country_isbn 957 +-%lang_name "Bân-lâm-gú, Hō-ló-oē" +-lang_name "Bn-lm-g, H-l-o" ++%lang_name "Bân-lâm-gú" ++lang_name "Bn-lm-g" + lang_term "nan" + lang_lib "nan" + END LC_ADDRESS +diff --git a/localedata/locales/nds_DE b/localedata/locales/nds_DE +index 232f9e4455ca74cc..d6200b7972b6b820 100644 +--- a/localedata/locales/nds_DE ++++ b/localedata/locales/nds_DE +@@ -45,7 +45,7 @@ country_ab3 "DEU" + country_car "D" + country_num 276 + country_isbn "3" +-lang_name "Neddersassisch" ++lang_name "Neddersasssch" + %lang_ab + lang_term "nds" + lang_lib "nds" +diff --git a/localedata/locales/nds_NL b/localedata/locales/nds_NL +index 8c8bebd93530938f..9fd50fb6256d3823 100644 +--- a/localedata/locales/nds_NL ++++ b/localedata/locales/nds_NL +@@ -44,7 +44,7 @@ country_ab3 "NLD" + country_car "NL" + country_num 528 + country_isbn "3" +-lang_name "Neddersassisch" ++lang_name "Neddersasssch" + %lang_ab + lang_term "nds" + lang_lib "nds" +diff --git a/localedata/locales/nhn_MX b/localedata/locales/nhn_MX +index 88a89765e88f060b..2dbfcb3c6572cd0c 100644 +--- a/localedata/locales/nhn_MX ++++ b/localedata/locales/nhn_MX +@@ -133,11 +133,12 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%z %T%N%c%N" ++country_name "Mexihco" + country_ab2 "MX" + country_ab3 "MEX" + country_num 484 + country_car "MEX" +-lang_name "Tlaxcala-Puebla Nahuatl" ++lang_name "Tlahco nhuatlahtlli" + lang_term "nhn" + lang_lib "nhn" + END LC_ADDRESS +diff --git a/localedata/locales/niu_NU b/localedata/locales/niu_NU +index 553c5d9edcddfc86..387e109109fc0374 100644 +--- a/localedata/locales/niu_NU ++++ b/localedata/locales/niu_NU +@@ -163,10 +163,12 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%z %T%N%c%N" ++country_name "Niu" + country_post "NU" + country_ab2 "NU" + country_ab3 "NIU" + country_num 570 ++lang_name "ko e vagahau Niu" + lang_term "niu" + lang_lib "niu" + END LC_ADDRESS +diff --git a/localedata/locales/niu_NZ b/localedata/locales/niu_NZ +index 560101b447c22251..2eba7d2630f8a46d 100644 +--- a/localedata/locales/niu_NZ ++++ b/localedata/locales/niu_NZ +@@ -99,6 +99,7 @@ country_ab2 "NZ" + country_ab3 "NZL" + country_num 554 + country_car "NZ" ++lang_name "ko e vagahau Niu" + lang_term "niu" + lang_lib "niu" + END LC_ADDRESS +diff --git a/localedata/locales/nr_ZA b/localedata/locales/nr_ZA +index 7de6420a6b52977e..f64434fadbad4e69 100644 +--- a/localedata/locales/nr_ZA ++++ b/localedata/locales/nr_ZA +@@ -225,7 +225,7 @@ country_car "ZA" + country_num 710 + + % Language name in Southern Ndebele +-lang_name "IsiNdebele" ++lang_name "isiNdebele" + + % ISO 639 two and three letter language names + % see http://www.loc.gov/standards/iso639-2/englangn.html +diff --git a/localedata/locales/oc_FR b/localedata/locales/oc_FR +index 707927ee2662ac91..a106f8d1c1152959 100644 +--- a/localedata/locales/oc_FR ++++ b/localedata/locales/oc_FR +@@ -44,7 +44,7 @@ country_ab3 "FRA" + country_num 250 + country_isbn "979-10" + country_car "F" +-lang_name "Occitan" ++lang_name "occitan" + lang_ab "oc" + lang_term "oci" + lang_lib "oci" +diff --git a/localedata/locales/or_IN b/localedata/locales/or_IN +index ef28b58895c342b6..2e4975e7b710b592 100644 +--- a/localedata/locales/or_IN ++++ b/localedata/locales/or_IN +@@ -20,7 +20,7 @@ contact "" + email "bug-glibc@gnu.org" + tel "" + fax "" +-language "Oriya" ++language "Odia" + territory "India" + revision "1.0" + date "2006-05-25" +diff --git a/localedata/locales/pa_PK b/localedata/locales/pa_PK +index 1f49bdc90d7ce637..0a584114b8f06590 100644 +--- a/localedata/locales/pa_PK ++++ b/localedata/locales/pa_PK +@@ -173,7 +173,7 @@ END LC_NAME + LC_ADDRESS + % FIXME + postal_fmt "%a%N%f%N%d%N%b%N%h %s %e %r%N%T %z%N%c%N" +-country_name "" ++country_name "" + country_ab2 "PK" + country_ab3 "PAK" + country_num 586 +diff --git a/localedata/locales/ps_AF b/localedata/locales/ps_AF +index 66f560ef4406be61..23dc86dcf1c1453b 100644 +--- a/localedata/locales/ps_AF ++++ b/localedata/locales/ps_AF +@@ -308,8 +308,7 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N" +-country_name "/ +-" ++country_name "" + country_post "AF" + country_ab2 "AF" + country_ab3 "AFG" +diff --git a/localedata/locales/quz_PE b/localedata/locales/quz_PE +index f6b1956b937100df..9ed890cbb0e6c762 100644 +--- a/localedata/locales/quz_PE ++++ b/localedata/locales/quz_PE +@@ -10,7 +10,7 @@ escape_char / + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % +-% Quechua (Cusco-Collao) language locale for Peru ++% Cusco Quechua language locale for Peru + % + % Prepared and contributed to glibc by Chris Leonard + % and Amos Batto +@@ -25,14 +25,14 @@ escape_char / + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + LC_IDENTIFICATION +-title "Quechua (Cusco-Collao) locale for Peru" ++title "Cusco Quechua locale for Peru" + source "Sugar Labs // OLPC" + address "" + contact "sugarlabs.org" + email "libc-alpha@sourceware.org" + tel "" + fax "" +-language "Quechua (Cusco-Collao)" ++language "Cusco Quechua" + territory "Peru" + revision "1.0" + date "2013-08-24" +@@ -144,7 +144,7 @@ country_ab2 "PE" + country_ab3 "PER" + country_num 604 + country_car "PE" +-lang_name "Quechua (Cusco)" ++lang_name "Qusqu runasimi" + lang_term "quz" + lang_lib "quz" + END LC_ADDRESS +diff --git a/localedata/locales/raj_IN b/localedata/locales/raj_IN +index ece080223e8de94b..ce009e406ab5c332 100644 +--- a/localedata/locales/raj_IN ++++ b/localedata/locales/raj_IN +@@ -158,7 +158,16 @@ name_ms "" + END LC_NAME + + LC_ADDRESS +-copy "hi_IN" ++postal_fmt "%z%c%T%s%b%e%r" ++country_name "" ++country_ab2 "IN" ++country_ab3 "IND" ++country_num 356 ++country_car "IND" ++% राजस्थानी ++lang_name "" ++lang_term "raj" ++lang_lib "raj" + END LC_ADDRESS + + LC_TELEPHONE +diff --git a/localedata/locales/rw_RW b/localedata/locales/rw_RW +index e0bc763c5a484c15..31cb4673dfa4a3aa 100644 +--- a/localedata/locales/rw_RW ++++ b/localedata/locales/rw_RW +@@ -132,7 +132,7 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%z %T%N%c%N" +-country_name "Rwanda" ++country_name "U Rwanda" + country_ab2 "RW" + country_ab3 "RWA" + country_num 646 +diff --git a/localedata/locales/sah_RU b/localedata/locales/sah_RU +index 80f67219c39cceb2..2b5a4b7bd660fb6e 100644 +--- a/localedata/locales/sah_RU ++++ b/localedata/locales/sah_RU +@@ -1,7 +1,7 @@ + escape_char / + comment_char % + +-% Yakut (Sakha) locale for Russian Federation ++% Sakha (Yakut) locale for Russian Federation + % Source: Valery Timiriliyev + % Email: timiriliyev@gmail.com + % Tel: +@@ -13,14 +13,14 @@ comment_char % + % Users: general + + LC_IDENTIFICATION +-title "Yakut (Sakha) locale for Russian Federation" ++title "Sakha (Yakut) locale for Russian Federation" + source "Valery Timiriliyev" + address "" + contact "Valery Timiriliyev" + email "timiriliyev@gmail.com" + tel "" + fax "" +-language "Yakut" ++language "Sakha" + territory "Russian Federation" + revision "1.1.0" + date "2018-07-06" +@@ -264,11 +264,11 @@ END LC_NAME + LC_ADDRESS + postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%z %T%N%c%N" + +-% Россия +-country_name "" ++% Арассыыйа ++country_name "" + +-% Саха тыла +-lang_name " " ++% саха тыла ++lang_name "" + + % UN Geneve 1949:68 Distinguishing signs of vehicles in international traffic + % RUS +diff --git a/localedata/locales/sat_IN b/localedata/locales/sat_IN +index 134eb8a572c836a7..e1775a4072ff7d9c 100644 +--- a/localedata/locales/sat_IN ++++ b/localedata/locales/sat_IN +@@ -158,12 +158,13 @@ END LC_NAME + LC_ADDRESS + + postal_fmt "%z%c%T%s%b%e%r" ++country_name "" + country_ab2 "IN" + country_ab3 "IND" + country_num 356 + country_car "IND" +-% Satār +-lang_name "Satr" ++% ᱥᱟᱱᱛᱟᱲᱤ ++lang_name "" + lang_term "sat" + lang_lib "sat" + END LC_ADDRESS +diff --git a/localedata/locales/sc_IT b/localedata/locales/sc_IT +index 1488744575dae32a..32626404d2956e8c 100644 +--- a/localedata/locales/sc_IT ++++ b/localedata/locales/sc_IT +@@ -144,7 +144,7 @@ country_ab3 "ITA" + country_num 380 + country_isbn "978-88,979-12" + country_car "I" +-lang_name "Sardu" ++lang_name "sardu" + lang_ab "sc" + lang_term "srd" + lang_lib "srd" +diff --git a/localedata/locales/sd_IN b/localedata/locales/sd_IN +index 66aa0e254cefe0d7..64c5366c31dcd818 100644 +--- a/localedata/locales/sd_IN ++++ b/localedata/locales/sd_IN +@@ -164,12 +164,14 @@ LC_ADDRESS + % This is the ISO_IEC TR14652 Locale definition for the LC_ADDRESS category + % generated by IBM Basic CountryPack Transformer. + postal_fmt "%z%c%T%s%b%e%r" +-% https://sd.wikipedia.org/wiki/%DA%80%D8%A7%D8%B1%D8%AA : "ڀارت" +-country_name "" ++% From cldr: انڊيا ++country_name "" + country_ab2 "IN" + country_ab3 "IND" + country_num 356 + country_car "IND" ++% سنڌي ++lang_name "" + lang_ab "sd" + lang_term "snd" + lang_lib "snd" +diff --git a/localedata/locales/sd_IN@devanagari b/localedata/locales/sd_IN@devanagari +index b1ce87df93f9c3d6..97357e08559ea64f 100644 +--- a/localedata/locales/sd_IN@devanagari ++++ b/localedata/locales/sd_IN@devanagari +@@ -167,6 +167,8 @@ country_ab2 "IN" + country_ab3 "IND" + country_num 356 + country_car "IND" ++% सिन्धी ++lang_name "" + lang_ab "sd" + lang_term "snd" + lang_lib "snd" +diff --git a/localedata/locales/shn_MM b/localedata/locales/shn_MM +index 4212c50ec5ae0066..a837f5fb394b1bb5 100644 +--- a/localedata/locales/shn_MM ++++ b/localedata/locales/shn_MM +@@ -281,7 +281,8 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%a%N%d%N%f%N%b%N%h%t%r%t%e%t%s%N%T%t%z%N%c%N" +-country_name "" ++% https://shn.wikipedia.org/wiki/%E1%80%99%E1%80%AD%E1%80%B0%E1%80%84%E1%80%BA%E1%80%B8%E1%80%99%E1%81%A2%E1%81%BC%E1%80%BA%E1%82%88 မိူင်းမၢၼ်ႈ ++country_name "" + country_post "Myanmar" + country_ab2 "MM" + country_num 104 +diff --git a/localedata/locales/shs_CA b/localedata/locales/shs_CA +index a5b675a316945608..ab48d600ef72ba75 100644 +--- a/localedata/locales/shs_CA ++++ b/localedata/locales/shs_CA +@@ -8,7 +8,7 @@ escape_char / + % exempt you from the conditions of the license if your use would + % otherwise be governed by that license. + +-% Secwepemctsin (Shuswap) language locale for Canada ++% Shuswap language locale for Canada + % sorting according to CAN/CSA-Z243.4.1-1992 + % Source: Neskie Manuel + % Address: 745 Ska-Hiish Dr +@@ -25,14 +25,14 @@ escape_char / + % Users: general + + LC_IDENTIFICATION +-title "Secwepemctsin locale for Canada" ++title "Shuswap locale for Canada" + source "Neskie Manuel" + address "745 Ska-Hiish Dr, Chase BC V0E 1M3" + contact "" + email "bug-glibc-locales@gnu.org" + tel "" + fax "" +-language "Secwepemctsin" ++language "Shuswap" + territory "Canada" + revision "1.0" + date "2008-01-15" +@@ -155,7 +155,7 @@ country_ab2 "CA" + country_ab3 "CAN" + country_num 124 + country_car "CDN" +-lang_name "Secwepemctsin" ++lang_name "Secwepemctsn" + lang_term "shs" + lang_lib "shs" + END LC_ADDRESS +diff --git a/localedata/locales/sm_WS b/localedata/locales/sm_WS +index 6058fbdc38283bb2..2823005c0635b6cf 100644 +--- a/localedata/locales/sm_WS ++++ b/localedata/locales/sm_WS +@@ -159,7 +159,7 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%a%N%f%N%d%N%b%N%h %s %e %r%N%T, %S %z%N%c%N" +-country_name "Samoa" ++country_name "Smoa" + country_post "%a %N %f %N %d %N %b %N %h %s %e %/ + r %N %T, %c %N" + % http://laendercode.net/en/2-letter-list.html +diff --git a/localedata/locales/ss_ZA b/localedata/locales/ss_ZA +index 7532a1940b3556f9..8e08a85f461aed9b 100644 +--- a/localedata/locales/ss_ZA ++++ b/localedata/locales/ss_ZA +@@ -228,7 +228,7 @@ country_car "ZA" + % country_isbn "" + + % Language name in Swati +-lang_name "SiSwati" ++lang_name "siSwati" + + % ISO 639 two and three letter language names + % see http://www.loc.gov/standards/iso639-2/englangn.html +diff --git a/localedata/locales/szl_PL b/localedata/locales/szl_PL +index 8d5de2112e54b7ad..88f1df4e905c5bdf 100644 +--- a/localedata/locales/szl_PL ++++ b/localedata/locales/szl_PL +@@ -188,6 +188,7 @@ END LC_NAME + + LC_ADDRESS + postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%z %T%N%c%N" ++country_name "Polska" + country_ab2 "PL" + country_ab3 "POL" + country_num 616 +diff --git a/localedata/locales/te_IN b/localedata/locales/te_IN +index fb5bb21b09ae0647..cb1b1109690b20bb 100644 +--- a/localedata/locales/te_IN ++++ b/localedata/locales/te_IN +@@ -177,7 +177,7 @@ LC_ADDRESS + % generated by IBM Basic CountryPack Transformer. + + postal_fmt "%a%N%d%N%f%N%r%t%e%N%h%t%b%N%s%t%N%T%t%z%N%S%N%c" +-country_name " " ++country_name "" + country_ab2 "IN" + country_ab3 "IND" + country_num 356 +diff --git a/localedata/locales/tg_TJ b/localedata/locales/tg_TJ +index 35dfca4574d4b5b9..6d1e4d8ab339501f 100644 +--- a/localedata/locales/tg_TJ ++++ b/localedata/locales/tg_TJ +@@ -222,6 +222,8 @@ country_ab2 "TJ" + country_ab3 "TJK" + country_num 762 + country_car "TJ" ++% тоҷикӣ ++lang_name "" + lang_ab "tg" + lang_term "tgk" + lang_lib "tgk" +diff --git a/localedata/locales/the_NP b/localedata/locales/the_NP +index 993e62fbfc5cea64..296e9970885ee490 100644 +--- a/localedata/locales/the_NP ++++ b/localedata/locales/the_NP +@@ -162,10 +162,14 @@ LC_ADDRESS + postal_fmt "%z%c%T%s%b%e%r" + lang_term "the" + lang_lib "the" ++% नेपाल ++country_name "" + country_ab2 "NP" + country_ab3 "NPL" + country_num 524 + country_car "NEP" ++% थारु ++lang_name "" + END LC_ADDRESS + + +diff --git a/localedata/locales/tk_TM b/localedata/locales/tk_TM +index 410afaf6c76c920b..e29ae20408763196 100644 +--- a/localedata/locales/tk_TM ++++ b/localedata/locales/tk_TM +@@ -399,7 +399,7 @@ country_num 795 + country_ab2 "TM" + country_ab3 "TKM" + % Türkmençe +-lang_name "trkmene" ++lang_name "trkmen dili" + lang_term "tuk" + lang_lib "tuk" + lang_ab "tk" +diff --git a/localedata/locales/tl_PH b/localedata/locales/tl_PH +index 40fd71d96095be12..03b8350749ab2c0a 100644 +--- a/localedata/locales/tl_PH ++++ b/localedata/locales/tl_PH +@@ -138,6 +138,7 @@ country_ab2 "PH" + country_ab3 "PHL" + country_num 608 + country_car "RP" ++lang_name "Tagalog" + lang_ab "tl" + lang_term "tgl" + lang_lib "tgl" +diff --git a/localedata/locales/to_TO b/localedata/locales/to_TO +index 7abe8685df8488cf..403a1219126bb189 100644 +--- a/localedata/locales/to_TO ++++ b/localedata/locales/to_TO +@@ -169,7 +169,7 @@ country_ab3 "TON" + country_car "TON" + country_num 776 + % Tongan +-lang_name "Tonga" ++lang_name "lea fakatonga" + % https://en.wikipedia.org/wiki/Tongan_language + lang_ab "to" + lang_term "ton" +diff --git a/localedata/locales/tpi_PG b/localedata/locales/tpi_PG +index 3315c27633ba58c6..885481974c8b531b 100644 +--- a/localedata/locales/tpi_PG ++++ b/localedata/locales/tpi_PG +@@ -172,7 +172,8 @@ END LC_NAME + LC_ADDRESS + % http://www.addressexamples.com/papua-new-guinea-address-format/ + postal_fmt "%a%s%z%C" +-country_name "Papua New Guinea" ++% https://tpi.wikipedia.org/wiki/Papua_Niugini ++country_name "Papua Niugini" + country_post "" + country_ab2 "PG" + country_ab3 "PNG" +@@ -180,7 +181,7 @@ country_car "PNG" + % https://en.wikipedia.org/wiki/ISO_3166-1_numeric + country_num 598 + % Tok Pisin +-lang_name "Tok Pisin" ++lang_name "Tok Pisin" + % https://en.wikipedia.org/wiki/Tok_Pisin + lang_ab "" + lang_term "tpi" +diff --git a/localedata/locales/tt_RU@iqtelif b/localedata/locales/tt_RU@iqtelif +index d4737c888e41352b..b52b1299946f372f 100644 +--- a/localedata/locales/tt_RU@iqtelif ++++ b/localedata/locales/tt_RU@iqtelif +@@ -155,10 +155,12 @@ END LC_MEASUREMENT + + LC_ADDRESS + postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%z %T%N%c%N" ++country_name "Urs Patahlq" + country_ab2 "RU" + country_ab3 "RUS" + country_num 643 + country_car "RUS" ++lang_name "tatar tele" + lang_ab "tt" + lang_term "tat" + lang_lib "tat" +diff --git a/localedata/locales/ug_CN b/localedata/locales/ug_CN +index 1ba583c588e074d2..acb8b68239c4a653 100644 +--- a/localedata/locales/ug_CN ++++ b/localedata/locales/ug_CN +@@ -195,6 +195,8 @@ country_ab3 "CHN" + country_num 156 + country_car "CHN" + country_isbn 7 ++% ئۇيغۇرچە ++lang_name "" + lang_ab "ug" + lang_term "uig" + lang_lib "uig" +diff --git a/localedata/locales/unm_US b/localedata/locales/unm_US +index 1e62c60443b83ec6..ef458e22dc195809 100644 +--- a/localedata/locales/unm_US ++++ b/localedata/locales/unm_US +@@ -139,7 +139,7 @@ country_ab3 "USA" + country_num 840 + country_car "USA" + country_isbn 0 +-% lang_name "" ++lang_name "Lenape" + % lang_ab "" + lang_term "unm" + lang_lib "unm" +diff --git a/localedata/locales/wa_BE b/localedata/locales/wa_BE +index e97493089eb287b0..afec10f41c8b1612 100644 +--- a/localedata/locales/wa_BE ++++ b/localedata/locales/wa_BE +@@ -44,7 +44,7 @@ country_ab3 "BEL" + country_num 056 + country_isbn "2" + country_car "B" +-lang_name "Walon" ++lang_name "walon" + lang_ab "wa" + lang_term "wln" + lang_lib "wln" +diff --git a/localedata/locales/wo_SN b/localedata/locales/wo_SN +index 47263d2eab6db94e..20190925034c9ab4 100644 +--- a/localedata/locales/wo_SN ++++ b/localedata/locales/wo_SN +@@ -161,6 +161,7 @@ country_ab2 "SN" + country_ab3 "SEN" + country_num 686 + country_car "SN" ++lang_name "Wolof" + lang_ab "wo" + lang_term "wol" + lang_lib "wol" +diff --git a/localedata/locales/xh_ZA b/localedata/locales/xh_ZA +index 4564137e851b0cda..327f7250987aaa57 100644 +--- a/localedata/locales/xh_ZA ++++ b/localedata/locales/xh_ZA +@@ -209,13 +209,13 @@ END LC_NAME + + LC_ADDRESS + % https://xh.wikipedia.org/wiki/UMzantsi_Afrika +-country_name "UMzantsi Afrika" ++country_name "uMzantsi Afrika" + % + % Abbreviated country postal name + country_post "ZA" + % + % Language name in Sotho +-lang_name "IsiXhosa" ++lang_name "isiXhosa" + + % UN Geneve 1949:68 Distinguishing signs of vehicles in international traffic + % http://www.unece.org/trans/conventn/disting-signs-5-2001.pdf +diff --git a/localedata/locales/yo_NG b/localedata/locales/yo_NG +index ec72d078bb7eab6d..a3102270bf0fd38b 100644 +--- a/localedata/locales/yo_NG ++++ b/localedata/locales/yo_NG +@@ -271,8 +271,8 @@ LC_ADDRESS + % "country designation for the keyword", + % "end of line + postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%z %T%N%c%N" +- +-country_name "Orlde Njr" ++% https://yo.wikipedia.org/wiki/N%C3%A0%C3%ACj%C3%ADr%C3%AD%C3%A0 and CLDR: Orilẹ̀-èdè Nàìjíríà ++country_name "Orild Njr" + + % Language name in Yoruba - "Yorùbá" + lang_name "d Yorb" +diff --git a/localedata/locales/yuw_PG b/localedata/locales/yuw_PG +index 0cb3cadf4ae485a1..55e787a5cdfc559f 100644 +--- a/localedata/locales/yuw_PG ++++ b/localedata/locales/yuw_PG +@@ -16,7 +16,7 @@ contact "Hannah Sarvasy" + email "nungon.localization@gmail.com" + tel "" + fax "" +-language "Yau/Nungon" ++language "Yau" + territory "Papua New Guinea" + revision "1.0" + date "2016-12-07" +@@ -133,8 +133,8 @@ country_ab2 "PG" + country_ab3 "PNG" + % ISO 3166-1 numeric code for PNG + country_num 598 +-% Yau/Nungon +-lang_name "Yau/Nungon" ++% See: https://en.wikipedia.org/wiki/Yau_language, the endonym seems to be Uruwa ++lang_name "Uruwa" + country_car "PNG" + lang_ab "" + lang_term "yuw" +diff --git a/localedata/locales/zh_HK b/localedata/locales/zh_HK +index c130878f3d6e0ace..e8097d6ed0704670 100644 +--- a/localedata/locales/zh_HK ++++ b/localedata/locales/zh_HK +@@ -178,6 +178,7 @@ country_ab2 "HK" + country_ab3 "HKG" + country_num 344 + country_car "HK" ++lang_name "" + lang_ab "zh" + lang_term "zho" + lang_lib "chi" +diff --git a/localedata/locales/zh_SG b/localedata/locales/zh_SG +index 2427cd3ead3583dc..472843c7f77b8ed6 100644 +--- a/localedata/locales/zh_SG ++++ b/localedata/locales/zh_SG +@@ -175,6 +175,7 @@ country_ab3 "SGP" + country_num 702 + % SGP + country_car "SGP" ++lang_name "" + lang_ab "zh" + lang_term "zho" + lang_lib "chi" diff --git a/glibc-rh1764214.patch b/glibc-rh1764214.patch new file mode 100755 index 0000000..fb7703c --- /dev/null +++ b/glibc-rh1764214.patch @@ -0,0 +1,305 @@ +commit bc79db3fd487daea36e7c130f943cfb9826a41b4 +Author: Stefan Liebler +Date: Wed Feb 6 09:06:34 2019 +0100 + + Fix alignment of TLS variables for tls variant TLS_TCB_AT_TP [BZ #23403] + + The alignment of TLS variables is wrong if accessed from within a thread + for architectures with tls variant TLS_TCB_AT_TP. + For the main thread the static tls data is properly aligned. + For other threads the alignment depends on the alignment of the thread + pointer as the static tls data is located relative to this pointer. + + This patch adds this alignment for TLS_TCB_AT_TP variants in the same way + as it is already done for TLS_DTV_AT_TP. The thread pointer is also already + properly aligned if the user provides its own stack for the new thread. + + This patch extends the testcase nptl/tst-tls1.c in order to check the + alignment of the tls variables and it adds a pthread_create invocation + with a user provided stack. + The test itself is migrated from test-skeleton.c to test-driver.c + and the missing support functions xpthread_attr_setstack and xposix_memalign + are added. + + ChangeLog: + + [BZ #23403] + * nptl/allocatestack.c (allocate_stack): Align pointer pd for + TLS_TCB_AT_TP tls variant. + * nptl/tst-tls1.c: Migrate to support/test-driver.c. + Add alignment checks. + * support/Makefile (libsupport-routines): Add xposix_memalign and + xpthread_setstack. + * support/support.h: Add xposix_memalign. + * support/xthread.h: Add xpthread_attr_setstack. + * support/xposix_memalign.c: New File. + * support/xpthread_attr_setstack.c: Likewise. + +diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c +index 670cb8ffe6..590350647b 100644 +--- a/nptl/allocatestack.c ++++ b/nptl/allocatestack.c +@@ -572,7 +572,9 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, + + /* Place the thread descriptor at the end of the stack. */ + #if TLS_TCB_AT_TP +- pd = (struct pthread *) ((char *) mem + size) - 1; ++ pd = (struct pthread *) ((((uintptr_t) mem + size) ++ - TLS_TCB_SIZE) ++ & ~__static_tls_align_m1); + #elif TLS_DTV_AT_TP + pd = (struct pthread *) ((((uintptr_t) mem + size + - __static_tls_size) +diff --git a/nptl/tst-tls1.c b/nptl/tst-tls1.c +index 00489e23e9..1a915224a7 100644 +--- a/nptl/tst-tls1.c ++++ b/nptl/tst-tls1.c +@@ -19,12 +19,16 @@ + #include + #include + #include +- ++#include ++#include ++#include ++#include ++#include + + struct test_s + { +- int a; +- int b; ++ __attribute__ ((aligned(0x20))) int a; ++ __attribute__ ((aligned(0x200))) int b; + }; + + #define INIT_A 1 +@@ -36,15 +40,34 @@ __thread struct test_s s __attribute__ ((tls_model ("initial-exec"))) = + .b = INIT_B + }; + ++/* Use noinline in combination with not static to ensure that the ++ alignment check is really done. Otherwise it was optimized out! */ ++__attribute__ ((noinline)) void ++check_alignment (const char *thr_name, const char *ptr_name, ++ int *ptr, int alignment) ++{ ++ uintptr_t offset_aligment = ((uintptr_t) ptr) & (alignment - 1); ++ if (offset_aligment) ++ { ++ FAIL_EXIT1 ("%s (%p) is not 0x%x-byte aligned in %s thread\n", ++ ptr_name, ptr, alignment, thr_name); ++ } ++} ++ ++static void ++check_s (const char *thr_name) ++{ ++ if (s.a != INIT_A || s.b != INIT_B) ++ FAIL_EXIT1 ("initial value of s in %s thread wrong\n", thr_name); ++ ++ check_alignment (thr_name, "s.a", &s.a, 0x20); ++ check_alignment (thr_name, "s.b", &s.b, 0x200); ++} + + static void * + tf (void *arg) + { +- if (s.a != INIT_A || s.b != INIT_B) +- { +- puts ("initial value of s in child thread wrong"); +- exit (1); +- } ++ check_s ("child"); + + ++s.a; + +@@ -55,25 +78,14 @@ tf (void *arg) + int + do_test (void) + { +- if (s.a != INIT_A || s.b != INIT_B) +- { +- puts ("initial value of s in main thread wrong"); +- exit (1); +- } ++ check_s ("main"); + + pthread_attr_t a; + +- if (pthread_attr_init (&a) != 0) +- { +- puts ("attr_init failed"); +- exit (1); +- } ++ xpthread_attr_init (&a); + +- if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0) +- { +- puts ("attr_setstacksize failed"); +- return 1; +- } ++#define STACK_SIZE (1 * 1024 * 1024) ++ xpthread_attr_setstacksize (&a, STACK_SIZE); + + #define N 10 + int i; +@@ -83,29 +95,25 @@ do_test (void) + pthread_t th[M]; + int j; + for (j = 0; j < M; ++j, ++s.a) +- if (pthread_create (&th[j], &a, tf, NULL) != 0) +- { +- puts ("pthread_create failed"); +- exit (1); +- } ++ th[j] = xpthread_create (&a, tf, NULL); + + for (j = 0; j < M; ++j) +- if (pthread_join (th[j], NULL) != 0) +- { +- puts ("pthread_join failed"); +- exit (1); +- } ++ xpthread_join (th[j]); + } + +- if (pthread_attr_destroy (&a) != 0) +- { +- puts ("attr_destroy failed"); +- exit (1); +- } ++ /* Also check the alignment of the tls variables if a misaligned stack is ++ specified. */ ++ pthread_t th; ++ void *thr_stack = NULL; ++ thr_stack = xposix_memalign (0x200, STACK_SIZE + 1); ++ xpthread_attr_setstack (&a, thr_stack + 1, STACK_SIZE); ++ th = xpthread_create (&a, tf, NULL); ++ xpthread_join (th); ++ free (thr_stack); ++ ++ xpthread_attr_destroy (&a); + + return 0; + } + +- +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" ++#include +diff --git a/support/Makefile b/support/Makefile +index c15b93647c..9ff0ec3fff 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -99,10 +99,12 @@ libsupport-routines = \ + xopen \ + xpipe \ + xpoll \ ++ xposix_memalign \ + xpthread_attr_destroy \ + xpthread_attr_init \ + xpthread_attr_setdetachstate \ + xpthread_attr_setguardsize \ ++ xpthread_attr_setstack \ + xpthread_attr_setstacksize \ + xpthread_barrier_destroy \ + xpthread_barrier_init \ +diff --git a/support/support.h b/support/support.h +index 119495e5a9..97fef2cd23 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -86,6 +86,7 @@ int support_descriptor_supports_holes (int fd); + void *xmalloc (size_t) __attribute__ ((malloc)); + void *xcalloc (size_t n, size_t s) __attribute__ ((malloc)); + void *xrealloc (void *p, size_t n); ++void *xposix_memalign (size_t alignment, size_t n); + char *xasprintf (const char *format, ...) + __attribute__ ((format (printf, 1, 2), malloc)); + char *xstrdup (const char *); +diff --git a/support/xposix_memalign.c b/support/xposix_memalign.c +new file mode 100644 +index 0000000000..5501a0846a +--- /dev/null ++++ b/support/xposix_memalign.c +@@ -0,0 +1,35 @@ ++/* Error-checking wrapper for posix_memalign. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++void * ++xposix_memalign (size_t alignment, size_t n) ++{ ++ void *p = NULL; ++ ++ int ret = posix_memalign (&p, alignment, n); ++ if (ret) ++ { ++ errno = ret; ++ oom_error ("posix_memalign", n); ++ } ++ return p; ++} +diff --git a/support/xpthread_attr_setstack.c b/support/xpthread_attr_setstack.c +new file mode 100644 +index 0000000000..c3772e240b +--- /dev/null ++++ b/support/xpthread_attr_setstack.c +@@ -0,0 +1,26 @@ ++/* pthread_attr_setstack 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 ++ . */ ++ ++#include ++ ++void ++xpthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, size_t stacksize) ++{ ++ xpthread_check_return ("pthread_attr_setstack", ++ pthread_attr_setstack (attr, stackaddr, stacksize)); ++} +diff --git a/support/xthread.h b/support/xthread.h +index 9fe1f68b3b..5204f78ed2 100644 +--- a/support/xthread.h ++++ b/support/xthread.h +@@ -68,6 +68,8 @@ void xpthread_attr_destroy (pthread_attr_t *attr); + void xpthread_attr_init (pthread_attr_t *attr); + void xpthread_attr_setdetachstate (pthread_attr_t *attr, + int detachstate); ++void xpthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, ++ size_t stacksize); + void xpthread_attr_setstacksize (pthread_attr_t *attr, + size_t stacksize); + void xpthread_attr_setguardsize (pthread_attr_t *attr, diff --git a/glibc-rh1764218-1.patch b/glibc-rh1764218-1.patch new file mode 100755 index 0000000..583f7a7 --- /dev/null +++ b/glibc-rh1764218-1.patch @@ -0,0 +1,192 @@ +commit cb89ba9c72f66327f5d66034681eb1d46eedf96f +Author: DJ Delorie +Date: Thu Aug 8 19:09:43 2019 -0400 + + Add glibc.malloc.mxfast tunable + + * elf/dl-tunables.list: Add glibc.malloc.mxfast. + * manual/tunables.texi: Document it. + * malloc/malloc.c (do_set_mxfast): New. + (__libc_mallopt): Call it. + * malloc/arena.c: Add mxfast tunable. + * malloc/tst-mxfast.c: New. + * malloc/Makefile: Add it. + + Reviewed-by: Carlos O'Donell + (cherry picked from commit c48d92b430c480de06762f80c104922239416826) + +diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list +index 1f8ecb8437a0460f..1ff6fcb6f24f93a8 100644 +--- a/elf/dl-tunables.list ++++ b/elf/dl-tunables.list +@@ -85,6 +85,11 @@ glibc { + tcache_unsorted_limit { + type: SIZE_T + } ++ mxfast { ++ type: SIZE_T ++ minval: 0 ++ security_level: SXID_IGNORE ++ } + } + tune { + hwcap_mask { +diff --git a/malloc/Makefile b/malloc/Makefile +index 228a1279a5960d8c..bf9a53cb7c5ebacb 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -39,6 +39,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ + tst-malloc-too-large \ + tst-malloc-stats-cancellation \ + tst-tcfree1 tst-tcfree2 tst-tcfree3 \ ++ tst-mxfast \ + + tests-static := \ + tst-interpose-static-nothread \ +@@ -196,6 +197,8 @@ tst-malloc-usable-static-ENV = $(tst-malloc-usable-ENV) + tst-malloc-usable-tunables-ENV = GLIBC_TUNABLES=glibc.malloc.check=3 + tst-malloc-usable-static-tunables-ENV = $(tst-malloc-usable-tunables-ENV) + ++tst-mxfast-ENV = GLIBC_TUNABLES=glibc.malloc.tcache_count=0:glibc.malloc.mxfast=0 ++ + ifeq ($(experimental-malloc),yes) + CPPFLAGS-malloc.c += -DUSE_TCACHE=1 + else +diff --git a/malloc/arena.c b/malloc/arena.c +index ff8fd5d2a7e51ac8..f5c7ad4570ad6186 100644 +--- a/malloc/arena.c ++++ b/malloc/arena.c +@@ -237,6 +237,7 @@ TUNABLE_CALLBACK_FNDECL (set_tcache_max, size_t) + TUNABLE_CALLBACK_FNDECL (set_tcache_count, size_t) + TUNABLE_CALLBACK_FNDECL (set_tcache_unsorted_limit, size_t) + #endif ++TUNABLE_CALLBACK_FNDECL (set_mxfast, size_t) + #else + /* Initialization routine. */ + #include +@@ -324,6 +325,7 @@ ptmalloc_init (void) + TUNABLE_GET (tcache_unsorted_limit, size_t, + TUNABLE_CALLBACK (set_tcache_unsorted_limit)); + # endif ++ TUNABLE_GET (mxfast, size_t, TUNABLE_CALLBACK (set_mxfast)); + #else + const char *s = NULL; + if (__glibc_likely (_environ != NULL)) +diff --git a/malloc/malloc.c b/malloc/malloc.c +index fcf480acdaea1b86..9756ed0a0d28c5f6 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -5142,6 +5142,19 @@ do_set_tcache_unsorted_limit (size_t value) + } + #endif + ++static inline int ++__always_inline ++do_set_mxfast (size_t value) ++{ ++ if (value >= 0 && value <= MAX_FAST_SIZE) ++ { ++ LIBC_PROBE (memory_mallopt_mxfast, 2, value, get_max_fast ()); ++ set_max_fast (value); ++ return 1; ++ } ++ return 0; ++} ++ + int + __libc_mallopt (int param_number, int value) + { +@@ -5161,13 +5174,7 @@ __libc_mallopt (int param_number, int value) + switch (param_number) + { + case M_MXFAST: +- if (value >= 0 && value <= MAX_FAST_SIZE) +- { +- LIBC_PROBE (memory_mallopt_mxfast, 2, value, get_max_fast ()); +- set_max_fast (value); +- } +- else +- res = 0; ++ do_set_mxfast (value); + break; + + case M_TRIM_THRESHOLD: +diff --git a/malloc/tst-mxfast.c b/malloc/tst-mxfast.c +new file mode 100644 +index 0000000000000000..7a371d2f9d2f0005 +--- /dev/null ++++ b/malloc/tst-mxfast.c +@@ -0,0 +1,50 @@ ++/* Test that glibc.malloc.mxfast tunable works. ++ 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 ++ . */ ++ ++/* This test verifies that setting the glibc.malloc.mxfast tunable to ++ zero results in free'd blocks being returned to the small bins, not ++ the fast bins. */ ++ ++#include ++#include ++ ++int ++do_test(void) ++{ ++ struct mallinfo m; ++ char * volatile p1; ++ char * volatile p2; ++ ++ /* Arbitrary value; must be in default fastbin range. */ ++ p1 = malloc (3); ++ /* Something large so that p1 isn't a "top block" */ ++ p2 = malloc (512); ++ free (p1); ++ ++ m = mallinfo(); ++ ++ /* This will fail if there are any blocks in the fastbins. */ ++ assert (m.smblks == 0); ++ ++ /* To keep gcc happy. */ ++ free (p2); ++ ++ return 0; ++} ++ ++#include +diff --git a/manual/tunables.texi b/manual/tunables.texi +index f6c49250e3889ddd..3dc6f9a44592c030 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -213,6 +213,18 @@ pre-fill the per-thread cache with. The default, or when set to zero, + is no limit. + @end deftp + ++@deftp Tunable glibc.malloc.mxfast ++One of the optimizations malloc uses is to maintain a series of ``fast ++bins'' that hold chunks up to a specific size. The default and ++maximum size which may be held this way is 80 bytes on 32-bit systems ++or 160 bytes on 64-bit systems. Applications which value size over ++speed may choose to reduce the size of requests which are serviced ++from fast bins with this tunable. Note that the value specified ++includes malloc's internal overhead, which is normally the size of one ++pointer, so add 4 on 32-bit systems or 8 on 64-bit systems to the size ++passed to @code{malloc} for the largest bin size to enable. ++@end deftp ++ + @node Elision Tunables + @section Elision Tunables + @cindex elision tunables diff --git a/glibc-rh1764218-2.patch b/glibc-rh1764218-2.patch new file mode 100755 index 0000000..8408975 --- /dev/null +++ b/glibc-rh1764218-2.patch @@ -0,0 +1,72 @@ +commit 5dab5eafb3dc2f72aaab911084d127d1af45a08c +Author: Florian Weimer +Date: Thu Aug 15 11:37:18 2019 +0200 + + malloc: Various cleanups for malloc/tst-mxfast + + (cherry picked from commit f9769a239784772453d595bc2f4bed8739810e06) + +diff --git a/malloc/Makefile b/malloc/Makefile +index bf9a53cb7c5ebacb..19c2a846ed8ce049 100644 +--- a/malloc/Makefile ++++ b/malloc/Makefile +@@ -39,7 +39,6 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ + tst-malloc-too-large \ + tst-malloc-stats-cancellation \ + tst-tcfree1 tst-tcfree2 tst-tcfree3 \ +- tst-mxfast \ + + tests-static := \ + tst-interpose-static-nothread \ +@@ -55,7 +54,7 @@ tests-internal += \ + tst-dynarray-at-fail \ + + ifneq (no,$(have-tunables)) +-tests += tst-malloc-usable-tunables ++tests += tst-malloc-usable-tunables tst-mxfast + tests-static += tst-malloc-usable-static-tunables + endif + +diff --git a/malloc/tst-mxfast.c b/malloc/tst-mxfast.c +index 7a371d2f9d2f0005..7a7750bc71024bfb 100644 +--- a/malloc/tst-mxfast.c ++++ b/malloc/tst-mxfast.c +@@ -1,5 +1,5 @@ + /* Test that glibc.malloc.mxfast tunable works. +- Copyright (C) 2018, 2019 Free Software Foundation, Inc. ++ 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 +@@ -21,14 +21,14 @@ + the fast bins. */ + + #include +-#include ++#include + + int +-do_test(void) ++do_test (void) + { + struct mallinfo m; +- char * volatile p1; +- char * volatile p2; ++ char *volatile p1; ++ char *volatile p2; + + /* Arbitrary value; must be in default fastbin range. */ + p1 = malloc (3); +@@ -36,10 +36,10 @@ do_test(void) + p2 = malloc (512); + free (p1); + +- m = mallinfo(); ++ m = mallinfo (); + + /* This will fail if there are any blocks in the fastbins. */ +- assert (m.smblks == 0); ++ TEST_COMPARE (m.smblks, 0); + + /* To keep gcc happy. */ + free (p2); diff --git a/glibc-rh1764218-3.patch b/glibc-rh1764218-3.patch new file mode 100755 index 0000000..ba35b8e --- /dev/null +++ b/glibc-rh1764218-3.patch @@ -0,0 +1,31 @@ +commit f144981490bd2ab13189d85902ca74beecb307e4 +Author: DJ Delorie +Date: Wed Oct 30 18:03:14 2019 -0400 + + Base max_fast on alignment, not width, of bins (Bug 24903) + + set_max_fast sets the "impossibly small" value based on, + eventually, MALLOC_ALIGNMENT. The comparisons for the smallest + chunk used is, eventually, MIN_CHUNK_SIZE. Note that i386 + is the only platform where these are the same, so a smallest + chunk *would* be put in a no-fastbins fastbin. + + This change calculates the "impossibly small" value + based on MIN_CHUNK_SIZE instead, so that we can know it will + always be impossibly small. + + (cherry picked from commit ff12e0fb91b9072800f031cb21fb2651ee7b6251) + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 9756ed0a0d28c5f6..90825b2aaed53761 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -1635,7 +1635,7 @@ static INTERNAL_SIZE_T global_max_fast; + + #define set_max_fast(s) \ + global_max_fast = (((s) == 0) \ +- ? SMALLBIN_WIDTH : ((s + SIZE_SZ) & ~MALLOC_ALIGN_MASK)) ++ ? MIN_CHUNK_SIZE / 2 : ((s + SIZE_SZ) & ~MALLOC_ALIGN_MASK)) + + static inline INTERNAL_SIZE_T + get_max_fast (void) diff --git a/glibc-rh1764223.patch b/glibc-rh1764223.patch new file mode 100755 index 0000000..372efaf --- /dev/null +++ b/glibc-rh1764223.patch @@ -0,0 +1,142 @@ +commit 2c75b545de6fe3c44138799c68217a94bc669a88 +Author: Florian Weimer +Date: Tue Jun 18 16:42:10 2019 +0200 + + elf: Refuse to dlopen PIE objects [BZ #24323] + + Another executable has already been mapped, so the dynamic linker + cannot perform relocations correctly for the second executable. + +diff --git a/elf/Makefile b/elf/Makefile +index 08e2f99..27a2fa8 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -310,7 +310,7 @@ test-xfail-tst-protected1b = yes + endif + ifeq (yesyes,$(have-fpie)$(build-shared)) + modules-names += tst-piemod1 +-tests += tst-pie1 tst-pie2 ++tests += tst-pie1 tst-pie2 tst-dlopen-pie + tests-pie += tst-pie1 tst-pie2 + ifeq (yes,$(have-protected-data)) + tests += vismain +@@ -1084,6 +1084,8 @@ CFLAGS-tst-pie2.c += $(pie-ccflag) + + $(objpfx)tst-piemod1.so: $(libsupport) + $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so ++$(objpfx)tst-dlopen-pie: $(libdl) ++$(objpfx)tst-dlopen-pie.out: $(objpfx)tst-pie1 + + ifeq (yes,$(build-shared)) + # NB: Please keep cet-built-dso in sysdeps/x86/Makefile in sync with +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 2bbef81..5abeb86 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -1158,6 +1158,10 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + goto call_lose; + } + ++ /* dlopen of an executable is not valid because it is not possible ++ to perform proper relocations, handle static TLS, or run the ++ ELF constructors. For PIE, the check needs the dynamic ++ section, so there is another check below. */ + if (__glibc_unlikely (type != ET_DYN) + && __glibc_unlikely ((mode & __RTLD_OPENEXEC) == 0)) + { +@@ -1194,9 +1198,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + elf_get_dynamic_info (l, NULL); + + /* Make sure we are not dlopen'ing an object that has the +- DF_1_NOOPEN flag set. */ +- if (__glibc_unlikely (l->l_flags_1 & DF_1_NOOPEN) +- && (mode & __RTLD_DLOPEN)) ++ DF_1_NOOPEN flag set, or a PIE object. */ ++ if ((__glibc_unlikely (l->l_flags_1 & DF_1_NOOPEN) ++ && (mode & __RTLD_DLOPEN)) ++ || (__glibc_unlikely (l->l_flags_1 & DF_1_PIE) ++ && __glibc_unlikely ((mode & __RTLD_OPENEXEC) == 0))) + { + /* We are not supposed to load this object. Free all resources. */ + _dl_unmap_segments (l); +@@ -1207,7 +1213,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + if (l->l_phdr_allocated) + free ((void *) l->l_phdr); + +- errstring = N_("shared object cannot be dlopen()ed"); ++ if (l->l_flags_1 & DF_1_PIE) ++ errstring ++ = N_("cannot dynamically load position-independent executable"); ++ else ++ errstring = N_("shared object cannot be dlopen()ed"); + goto call_lose; + } + +diff --git a/elf/tst-dlopen-pie.c b/elf/tst-dlopen-pie.c +new file mode 100644 +index 0000000..6a41c73 +--- /dev/null ++++ b/elf/tst-dlopen-pie.c +@@ -0,0 +1,49 @@ ++/* dlopen test for PIE objects. ++ 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 ++ . */ ++ ++/* This test attempts to open the (otherwise unrelated) PIE test ++ program elf/tst-pie1 and expects the attempt to fail. */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static void ++test_mode (int mode) ++{ ++ char *pie_path = xasprintf ("%s/elf/tst-pie1", support_objdir_root); ++ if (dlopen (pie_path, mode) != NULL) ++ FAIL_EXIT1 ("dlopen succeeded unexpectedly (%d)", mode); ++ const char *message = dlerror (); ++ const char *expected ++ = "cannot dynamically load position-independent executable"; ++ if (strstr (message, expected) == NULL) ++ FAIL_EXIT1 ("unexpected error message (mode %d): %s", mode, message); ++} ++ ++static int ++do_test (void) ++{ ++ test_mode (RTLD_LAZY); ++ test_mode (RTLD_NOW); ++ return 0; ++} ++ ++#include +diff --git a/include/elf.h b/include/elf.h +index ab76aaf..14ed67f 100644 +--- a/include/elf.h ++++ b/include/elf.h +@@ -23,7 +23,7 @@ + # endif + # define DT_1_SUPPORTED_MASK \ + (DF_1_NOW | DF_1_NODELETE | DF_1_INITFIRST | DF_1_NOOPEN \ +- | DF_1_ORIGIN | DF_1_NODEFLIB) ++ | DF_1_ORIGIN | DF_1_NODEFLIB | DF_1_PIE) + + #endif /* !_ISOMAC */ + #endif /* elf.h */ diff --git a/glibc-rh1764226-1.patch b/glibc-rh1764226-1.patch new file mode 100755 index 0000000..44035fe --- /dev/null +++ b/glibc-rh1764226-1.patch @@ -0,0 +1,82 @@ +commit 6c29942cbf059aca47fd4bbd852ea42c9d46b71f +Author: Stefan Liebler +Date: Mon Feb 18 16:12:01 2019 +0100 + + misc/tst-clone3: Fix waiting for exited thread. + + From time to time the test misc/tst-clone3 fails with a timeout. + Then futex_wait is blocking. Usually ctid should be set to zero + due to CLONE_CHILD_CLEARTID and the futex should be waken up. + But the fail occures if the thread has already exited before + ctid is set to the return value of clone(). Then futex_wait() will + block as there will be nobody who wakes the futex up again. + + This patch initializes ctid to a known value before calling clone + and the kernel is the only one who updates the value to zero after clone. + If futex_wait is called then it is either waked up due to the exited thread + or the futex syscall fails as *ctid_ptr is already zero instead of the + specified value 1. + + ChangeLog: + + * sysdeps/unix/sysv/linux/tst-clone3.c (do_test): + Initialize ctid with a known value and remove update of ctid + after clone. + (wait_tid): Adjust arguments and call futex_wait with ctid_val + as assumed current value of ctid_ptr. + +diff --git a/sysdeps/unix/sysv/linux/tst-clone3.c b/sysdeps/unix/sysv/linux/tst-clone3.c +index 784ce18f5343ec72..9f1ed6355e7acffd 100644 +--- a/sysdeps/unix/sysv/linux/tst-clone3.c ++++ b/sysdeps/unix/sysv/linux/tst-clone3.c +@@ -27,6 +27,7 @@ + + #include /* For _STACK_GROWS_{UP,DOWN}. */ + #include ++#include + + /* Test if clone call with CLONE_THREAD does not call exit_group. The 'f' + function returns '1', which will be used by clone thread to call the +@@ -42,11 +43,14 @@ f (void *a) + + /* Futex wait for TID argument, similar to pthread_join internal + implementation. */ +-#define wait_tid(tid) \ +- do { \ +- __typeof (tid) __tid; \ +- while ((__tid = (tid)) != 0) \ +- futex_wait (&(tid), __tid); \ ++#define wait_tid(ctid_ptr, ctid_val) \ ++ do { \ ++ __typeof (*(ctid_ptr)) __tid; \ ++ /* We need acquire MO here so that we synchronize with the \ ++ kernel's store to 0 when the clone terminates. */ \ ++ while ((__tid = atomic_load_explicit (ctid_ptr, \ ++ memory_order_acquire)) != 0) \ ++ futex_wait (ctid_ptr, ctid_val); \ + } while (0) + + static inline int +@@ -64,7 +68,11 @@ do_test (void) + clone_flags |= CLONE_VM | CLONE_SIGHAND; + /* We will used ctid to call on futex to wait for thread exit. */ + clone_flags |= CLONE_CHILD_CLEARTID; +- pid_t ctid, tid; ++ /* Initialize with a known value. ctid is set to zero by the kernel after the ++ cloned thread has exited. */ ++#define CTID_INIT_VAL 1 ++ pid_t ctid = CTID_INIT_VAL; ++ pid_t tid; + + #ifdef __ia64__ + extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base, +@@ -86,8 +94,7 @@ do_test (void) + if (tid == -1) + FAIL_EXIT1 ("clone failed: %m"); + +- ctid = tid; +- wait_tid (ctid); ++ wait_tid (&ctid, CTID_INIT_VAL); + + return 2; + } diff --git a/glibc-rh1764226-2.patch b/glibc-rh1764226-2.patch new file mode 100755 index 0000000..69902cc --- /dev/null +++ b/glibc-rh1764226-2.patch @@ -0,0 +1,159 @@ +commit 481c30cb9573a280649fbf27251e6a0f4af1b2b1 +Author: Alexandra Hájková +Date: Thu May 9 13:51:40 2019 +0200 + + elf: Add tst-ldconfig-bad-aux-cache test [BZ #18093] + + This test corrupts /var/cache/ldconfig/aux-cache and executes ldconfig + to check it will not segfault using the corrupted aux_cache. The test + uses the test-in-container framework. Verified no regressions on + x86_64. + +diff --git a/elf/Makefile b/elf/Makefile +index 139d072e136284e1..8e907e69eb35e089 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -156,6 +156,9 @@ tests-static-internal := tst-tls1-static tst-tls2-static \ + CRT-tst-tls1-static-non-pie := $(csu-objpfx)crt1.o + tst-tls1-static-non-pie-no-pie = yes + ++tests-container = \ ++ tst-ldconfig-bad-aux-cache ++ + tests := tst-tls9 tst-leaks1 \ + tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \ + tst-auxv +diff --git a/elf/tst-ldconfig-bad-aux-cache.c b/elf/tst-ldconfig-bad-aux-cache.c +new file mode 100644 +index 0000000000000000..68ce90a95648f6ab +--- /dev/null ++++ b/elf/tst-ldconfig-bad-aux-cache.c +@@ -0,0 +1,117 @@ ++/* Test ldconfig does not segfault when aux-cache is corrupted (Bug 18093). ++ 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; see the file COPYING.LIB. If ++ not, see . */ ++ ++/* This test does the following: ++ Run ldconfig to create the caches. ++ Corrupt the caches. ++ Run ldconfig again. ++ At each step we verify that ldconfig does not crash. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++static int ++display_info (const char *fpath, const struct stat *sb, ++ int tflag, struct FTW *ftwbuf) ++{ ++ printf ("info: %-3s %2d %7jd %-40s %d %s\n", ++ (tflag == FTW_D) ? "d" : (tflag == FTW_DNR) ? "dnr" : ++ (tflag == FTW_DP) ? "dp" : (tflag == FTW_F) ? "f" : ++ (tflag == FTW_NS) ? "ns" : (tflag == FTW_SL) ? "sl" : ++ (tflag == FTW_SLN) ? "sln" : "???", ++ ftwbuf->level, (intmax_t) sb->st_size, ++ fpath, ftwbuf->base, fpath + ftwbuf->base); ++ /* To tell nftw to continue. */ ++ return 0; ++} ++ ++/* Run ldconfig with a corrupt aux-cache, in particular we test for size ++ truncation that might happen if a previous ldconfig run failed or if ++ there were storage or power issues while we were writing the file. ++ We want ldconfig not to crash, and it should be able to do so by ++ computing the expected size of the file (bug 18093). */ ++static int ++do_test (void) ++{ ++ char *prog = xasprintf ("%s/ldconfig", support_install_rootsbindir); ++ char *const args[] = { prog, NULL }; ++ const char *path = "/var/cache/ldconfig/aux-cache"; ++ struct stat64 fs; ++ long int size, new_size, i; ++ int status; ++ pid_t pid; ++ ++ /* Create the needed directories. */ ++ xmkdirp ("/var/cache/ldconfig", 0777); ++ ++ pid = xfork (); ++ /* Run ldconfig fist to generate the aux-cache. */ ++ if (pid == 0) ++ { ++ execv (args[0], args); ++ _exit (1); ++ } ++ else ++ { ++ xwaitpid (pid, &status, 0); ++ TEST_COMPARE(status, 0); ++ xstat (path, &fs); ++ ++ size = fs.st_size; ++ /* Run 3 tests, each truncating aux-cache shorter and shorter. */ ++ for (i = 3; i > 0; i--) ++ { ++ new_size = size * i / 4; ++ if (truncate (path, new_size)) ++ FAIL_EXIT1 ("truncation failed: %m"); ++ if (nftw (path, display_info, 1000, 0) == -1) ++ FAIL_EXIT1 ("nftw failed."); ++ ++ pid = xfork (); ++ /* Verify that ldconfig can run with a truncated ++ aux-cache and doesn't crash. */ ++ if (pid == 0) ++ { ++ execv (args[0], args); ++ _exit (1); ++ } ++ else ++ { ++ xwaitpid (pid, &status, 0); ++ TEST_COMPARE(status, 0); ++ } ++ } ++ } ++ ++ free (prog); ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-ldconfig-bad-aux-cache.root/etc/ld.so.conf b/elf/tst-ldconfig-bad-aux-cache.root/etc/ld.so.conf +new file mode 100644 +index 0000000000000000..e1e74dbda2bf3dfa +--- /dev/null ++++ b/elf/tst-ldconfig-bad-aux-cache.root/etc/ld.so.conf +@@ -0,0 +1,2 @@ ++# This file was created to suppress a warning from ldconfig: ++# /sbin/ldconfig: Warning: ignoring configuration file that cannot be opened: /etc/ld.so.conf: No such file or directory +diff --git a/elf/tst-ldconfig-bad-aux-cache.root/postclean.req b/elf/tst-ldconfig-bad-aux-cache.root/postclean.req +new file mode 100644 +index 0000000000000000..e69de29bb2d1d643 diff --git a/glibc-rh1764226-3.patch b/glibc-rh1764226-3.patch new file mode 100755 index 0000000..cda312f --- /dev/null +++ b/glibc-rh1764226-3.patch @@ -0,0 +1,112 @@ +commit a6c1ce778e5c05a2e6925883b410157ef47654fd +Author: Alexandra Hájková +Date: Mon Aug 5 13:18:57 2019 +0200 + + elf: tst-ldconfig-bad-aux-cache: use support_capture_subprocess + +diff --git a/elf/tst-ldconfig-bad-aux-cache.c b/elf/tst-ldconfig-bad-aux-cache.c +index 68ce90a95648f6ab..6e22ff815eaaa817 100644 +--- a/elf/tst-ldconfig-bad-aux-cache.c ++++ b/elf/tst-ldconfig-bad-aux-cache.c +@@ -31,6 +31,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -52,6 +53,15 @@ display_info (const char *fpath, const struct stat *sb, + return 0; + } + ++static void ++execv_wrapper (void *args) ++{ ++ char **argv = args; ++ ++ execv (argv[0], argv); ++ FAIL_EXIT1 ("execv: %m"); ++} ++ + /* Run ldconfig with a corrupt aux-cache, in particular we test for size + truncation that might happen if a previous ldconfig run failed or if + there were storage or power issues while we were writing the file. +@@ -61,53 +71,38 @@ static int + do_test (void) + { + char *prog = xasprintf ("%s/ldconfig", support_install_rootsbindir); +- char *const args[] = { prog, NULL }; ++ char *args[] = { prog, NULL }; + const char *path = "/var/cache/ldconfig/aux-cache"; + struct stat64 fs; + long int size, new_size, i; +- int status; +- pid_t pid; + + /* Create the needed directories. */ + xmkdirp ("/var/cache/ldconfig", 0777); + +- pid = xfork (); +- /* Run ldconfig fist to generate the aux-cache. */ +- if (pid == 0) +- { +- execv (args[0], args); +- _exit (1); +- } +- else ++ /* Run ldconfig first to generate the aux-cache. */ ++ struct support_capture_subprocess result; ++ result = support_capture_subprocess (execv_wrapper, args); ++ support_capture_subprocess_check (&result, "execv", 0, sc_allow_none); ++ support_capture_subprocess_free (&result); ++ ++ xstat (path, &fs); ++ ++ size = fs.st_size; ++ /* Run 3 tests, each truncating aux-cache shorter and shorter. */ ++ for (i = 3; i > 0; i--) + { +- xwaitpid (pid, &status, 0); +- TEST_COMPARE(status, 0); +- xstat (path, &fs); +- +- size = fs.st_size; +- /* Run 3 tests, each truncating aux-cache shorter and shorter. */ +- for (i = 3; i > 0; i--) +- { +- new_size = size * i / 4; +- if (truncate (path, new_size)) +- FAIL_EXIT1 ("truncation failed: %m"); +- if (nftw (path, display_info, 1000, 0) == -1) +- FAIL_EXIT1 ("nftw failed."); +- +- pid = xfork (); +- /* Verify that ldconfig can run with a truncated +- aux-cache and doesn't crash. */ +- if (pid == 0) +- { +- execv (args[0], args); +- _exit (1); +- } +- else +- { +- xwaitpid (pid, &status, 0); +- TEST_COMPARE(status, 0); +- } +- } ++ new_size = size * i / 4; ++ if (truncate (path, new_size)) ++ FAIL_EXIT1 ("truncation failed: %m"); ++ if (nftw (path, display_info, 1000, 0) == -1) ++ FAIL_EXIT1 ("nftw failed."); ++ ++ /* Verify that ldconfig can run with a truncated ++ aux-cache and doesn't crash. */ ++ struct support_capture_subprocess result; ++ result = support_capture_subprocess (execv_wrapper, args); ++ support_capture_subprocess_check (&result, "execv", 0, sc_allow_none); ++ support_capture_subprocess_free (&result); + } + + free (prog); diff --git a/glibc-rh1764231-1.patch b/glibc-rh1764231-1.patch new file mode 100755 index 0000000..f879427 --- /dev/null +++ b/glibc-rh1764231-1.patch @@ -0,0 +1,49 @@ +commit 17432d7150bdab3bce2ea66c70ad6c920f54077a +Author: Florian Weimer +Date: Fri Jun 28 10:15:30 2019 +0200 + + support: Add xdlvsym function + +diff --git a/support/xdlfcn.c b/support/xdlfcn.c +index f34bb059c00f27f7..b4a6b85649d181c8 100644 +--- a/support/xdlfcn.c ++++ b/support/xdlfcn.c +@@ -48,6 +48,26 @@ xdlsym (void *handle, const char *symbol) + return sym; + } + ++void * ++xdlvsym (void *handle, const char *symbol, const char *version) ++{ ++ /* Clear any pending errors. */ ++ dlerror (); ++ ++ void *sym = dlvsym (handle, symbol, version); ++ ++ if (sym == NULL) ++ { ++ const char *error = dlerror (); ++ if (error != NULL) ++ FAIL_EXIT1 ("error: dlvsym: %s\n", error); ++ /* If there was no error, we found a NULL symbol. Return the ++ NULL value in this case. */ ++ } ++ ++ return sym; ++} ++ + void + xdlclose (void *handle) + { +diff --git a/support/xdlfcn.h b/support/xdlfcn.h +index 5ab7494e70924f52..ab1cbb3cb9bb1cc7 100644 +--- a/support/xdlfcn.h ++++ b/support/xdlfcn.h +@@ -26,6 +26,7 @@ __BEGIN_DECLS + /* Each of these terminates process on failure with relevant error message. */ + void *xdlopen (const char *filename, int flags); + void *xdlsym (void *handle, const char *symbol); ++void *xdlvsym (void *handle, const char *symbol, const char *version); + void xdlclose (void *handle); + + diff --git a/glibc-rh1764231-2.patch b/glibc-rh1764231-2.patch new file mode 100755 index 0000000..aaff767 --- /dev/null +++ b/glibc-rh1764231-2.patch @@ -0,0 +1,342 @@ +commit f0b2132b35248c1f4a80f62a2c38cddcc802aa8c +Author: Florian Weimer +Date: Fri Jun 28 10:12:50 2019 +0200 + + ld.so: Support moving versioned symbols between sonames [BZ #24741] + + This change should be fully backwards-compatible because the old + code aborted the load if a soname mismatch was encountered + (instead of searching further for a matching symbol). This means + that no different symbols are found. + + The soname check was explicitly disabled for the skip_map != NULL + case. However, this only happens with dl(v)sym and RTLD_NEXT, + and those lookups do not come with a verneed entry that could be used + for the check. + + The error check was already explicitly disabled for the skip_map != + NULL case, that is, when dl(v)sym was called with RTLD_NEXT. But + _dl_vsym always sets filename in the struct r_found_version argument + to NULL, so the check was not active anyway. This means that + symbol lookup results for the skip_map != NULL case do not change, + either. + +Conflicts: + elf/Makefile + (usual missing backports) + +diff --git a/elf/Makefile b/elf/Makefile +index 29aa3a96738e4176..73f9e25ea5efd63a 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -187,7 +187,8 @@ 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-absolute-sym tst-absolute-zero tst-big-note \ ++ tst-sonamemove-link tst-sonamemove-dlopen + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -275,7 +276,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + 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-absolute-zero-lib tst-big-note-lib \ ++ tst-sonamemove-linkmod1 \ ++ tst-sonamemove-runmod1 tst-sonamemove-runmod2 + + ifeq (yes,$(have-mtls-dialect-gnu2)) + tests += tst-gnu2-tls1 +@@ -1374,6 +1377,28 @@ tst-audit12-ENV = LD_AUDIT=$(objpfx)tst-auditmod12.so + $(objpfx)tst-audit12mod1.so: $(objpfx)tst-audit12mod2.so + LDFLAGS-tst-audit12mod2.so = -Wl,--version-script=tst-audit12mod2.map + ++# tst-sonamemove links against an older implementation of the library. ++LDFLAGS-tst-sonamemove-linkmod1.so = \ ++ -Wl,--version-script=tst-sonamemove-linkmod1.map \ ++ -Wl,-soname,tst-sonamemove-runmod1.so ++LDFLAGS-tst-sonamemove-runmod1.so = -Wl,--no-as-needed \ ++ -Wl,--version-script=tst-sonamemove-runmod1.map \ ++ -Wl,-soname,tst-sonamemove-runmod1.so ++LDFLAGS-tst-sonamemove-runmod2.so = \ ++ -Wl,--version-script=tst-sonamemove-runmod2.map \ ++ -Wl,-soname,tst-sonamemove-runmod2.so ++$(objpfx)tst-sonamemove-runmod1.so: $(objpfx)tst-sonamemove-runmod2.so ++# Link against the link module, but depend on the run-time modules ++# for execution. ++$(objpfx)tst-sonamemove-link: $(objpfx)tst-sonamemove-linkmod1.so ++$(objpfx)tst-sonamemove-link.out: \ ++ $(objpfx)tst-sonamemove-runmod1.so \ ++ $(objpfx)tst-sonamemove-runmod2.so ++$(objpfx)tst-sonamemove-dlopen: $(libdl) ++$(objpfx)tst-sonamemove-dlopen.out: \ ++ $(objpfx)tst-sonamemove-runmod1.so \ ++ $(objpfx)tst-sonamemove-runmod2.so ++ + # Override -z defs, so that we can reference an undefined symbol. + # Force lazy binding for the same reason. + LDFLAGS-tst-latepthreadmod.so = \ +diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c +index 68ecc6179f608547..1d046caf017b582b 100644 +--- a/elf/dl-lookup.c ++++ b/elf/dl-lookup.c +@@ -536,11 +536,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash, + } + + skip: +- /* If this current map is the one mentioned in the verneed entry +- and we have not found a weak entry, it is a bug. */ +- if (symidx == STN_UNDEF && version != NULL && version->filename != NULL +- && __glibc_unlikely (_dl_name_match_p (version->filename, map))) +- return -1; ++ ; + } + while (++i < n); + +@@ -810,34 +806,10 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map, + + /* Search the relevant loaded objects for a definition. */ + for (size_t start = i; *scope != NULL; start = 0, ++scope) +- { +- int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref, +- ¤t_value, *scope, start, version, flags, +- skip_map, type_class, undef_map); +- if (res > 0) +- break; +- +- if (__glibc_unlikely (res < 0) && skip_map == NULL) +- { +- /* Oh, oh. The file named in the relocation entry does not +- contain the needed symbol. This code is never reached +- for unversioned lookups. */ +- assert (version != NULL); +- const char *reference_name = undef_map ? undef_map->l_name : ""; +- struct dl_exception exception; +- /* XXX We cannot translate the message. */ +- _dl_exception_create_format +- (&exception, DSO_FILENAME (reference_name), +- "symbol %s version %s not defined in file %s" +- " with link time reference%s", +- undef_name, version->name, version->filename, +- res == -2 ? " (no version symbols)" : ""); +- _dl_signal_cexception (0, &exception, N_("relocation error")); +- _dl_exception_free (&exception); +- *ref = NULL; +- return 0; +- } +- } ++ if (do_lookup_x (undef_name, new_hash, &old_hash, *ref, ++ ¤t_value, *scope, start, version, flags, ++ skip_map, type_class, undef_map) != 0) ++ break; + + if (__glibc_unlikely (current_value.s == NULL)) + { +diff --git a/elf/tst-sonamemove-dlopen.c b/elf/tst-sonamemove-dlopen.c +new file mode 100644 +index 0000000000000000..c496705044cdd53c +--- /dev/null ++++ b/elf/tst-sonamemove-dlopen.c +@@ -0,0 +1,35 @@ ++/* Check that a moved versioned symbol can be found using dlsym, dlvsym. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* tst-sonamemove-runmod1.so does not define moved_function, but it ++ depends on tst-sonamemove-runmod2.so, which does. */ ++ void *handle = xdlopen ("tst-sonamemove-runmod1.so", RTLD_NOW); ++ TEST_VERIFY (xdlsym (handle, "moved_function") != NULL); ++ TEST_VERIFY (xdlvsym (handle, "moved_function", "SONAME_MOVE") != NULL); ++ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-sonamemove-link.c b/elf/tst-sonamemove-link.c +new file mode 100644 +index 0000000000000000..4bc3bf32f88f97a9 +--- /dev/null ++++ b/elf/tst-sonamemove-link.c +@@ -0,0 +1,41 @@ ++/* Check that a versioned symbol can move from one library to another. ++ 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 ++ . */ ++ ++/* At link time, moved_function is bound to the symbol version ++ SONAME_MOVE in tst-sonamemove-runmod1.so, using the ++ tst-sonamemove-linkmod1.so stub object. ++ ++ At run time, the process loads the real tst-sonamemove-runmod1.so, ++ which depends on tst-sonamemove-runmod2.so. ++ tst-sonamemove-runmod1.so does not define moved_function, but ++ tst-sonamemove-runmod2.so does. ++ ++ The net effect is that the versioned symbol ++ moved_function@SONAME_MOVE moved from the soname ++ tst-sonamemove-linkmod1.so at link time to the soname ++ tst-sonamemove-linkmod2.so at run time. */ ++void moved_function (void); ++ ++static int ++do_test (void) ++{ ++ moved_function (); ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-sonamemove-linkmod1.c b/elf/tst-sonamemove-linkmod1.c +new file mode 100644 +index 0000000000000000..b8a354e5e394f566 +--- /dev/null ++++ b/elf/tst-sonamemove-linkmod1.c +@@ -0,0 +1,25 @@ ++/* Link interface for (lack of) soname matching in versioned symbol refs. ++ 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 ++ . */ ++ ++/* This function moved from tst-sonamemove-runmod1.so. This module is ++ intended for linking only, to simulate an old application which was ++ linked against an older version of the library. */ ++void ++moved_function (void) ++{ ++} +diff --git a/elf/tst-sonamemove-linkmod1.map b/elf/tst-sonamemove-linkmod1.map +new file mode 100644 +index 0000000000000000..8fe5904018972009 +--- /dev/null ++++ b/elf/tst-sonamemove-linkmod1.map +@@ -0,0 +1,3 @@ ++SONAME_MOVE { ++ global: moved_function; ++}; +diff --git a/elf/tst-sonamemove-runmod1.c b/elf/tst-sonamemove-runmod1.c +new file mode 100644 +index 0000000000000000..5c409e22898bc836 +--- /dev/null ++++ b/elf/tst-sonamemove-runmod1.c +@@ -0,0 +1,23 @@ ++/* Run-time module whose moved_function moved to a library dependency. ++ 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 ++ . */ ++ ++/* Dummy function to add the required symbol version. */ ++void ++other_function (void) ++{ ++} +diff --git a/elf/tst-sonamemove-runmod1.map b/elf/tst-sonamemove-runmod1.map +new file mode 100644 +index 0000000000000000..2ea81c6e6ffae2be +--- /dev/null ++++ b/elf/tst-sonamemove-runmod1.map +@@ -0,0 +1,3 @@ ++SONAME_MOVE { ++ global: other_function; ++}; +diff --git a/elf/tst-sonamemove-runmod2.c b/elf/tst-sonamemove-runmod2.c +new file mode 100644 +index 0000000000000000..b5e482eff57d7d83 +--- /dev/null ++++ b/elf/tst-sonamemove-runmod2.c +@@ -0,0 +1,24 @@ ++/* Run-time module with the actual implementation of moved_function. ++ 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 ++ . */ ++ ++/* In the test scenario, this function was originally in ++ tst-sonamemove-runmod1.so. */ ++void ++moved_function (void) ++{ ++} +diff --git a/elf/tst-sonamemove-runmod2.map b/elf/tst-sonamemove-runmod2.map +new file mode 100644 +index 0000000000000000..8fe5904018972009 +--- /dev/null ++++ b/elf/tst-sonamemove-runmod2.map +@@ -0,0 +1,3 @@ ++SONAME_MOVE { ++ global: moved_function; ++}; diff --git a/glibc-rh1764234-1.patch b/glibc-rh1764234-1.patch new file mode 100755 index 0000000..0bbcf35 --- /dev/null +++ b/glibc-rh1764234-1.patch @@ -0,0 +1,40 @@ +commit 47ad5e1a2a3ab8eeda491454cbef3b1c5239dc02 +Author: Joseph Myers +Date: Tue Jan 1 02:01:02 2019 +0000 + + Update syscall-names.list for Linux 4.20. + + This patch updates sysdeps/unix/sysv/linux/syscall-names.list for + Linux 4.20. Although there are no new syscalls, the + riscv_flush_icache syscall has moved to asm/unistd.h (previously in + asm/syscalls.h) and so now needs to be added to the list. + + Tested with build-many-glibcs.py. + + * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel + version to 4.20. + (riscv_flush_icache): New syscall. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 698069a52d..b650dc07cc 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -22,8 +22,8 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 4.19. +-kernel 4.19 ++# The list of system calls is current as of Linux 4.20. ++kernel 4.20 + + FAST_atomic_update + FAST_cmpxchg +@@ -431,6 +431,7 @@ renameat + renameat2 + request_key + restart_syscall ++riscv_flush_icache + rmdir + rseq + rt_sigaction diff --git a/glibc-rh1764234-2.patch b/glibc-rh1764234-2.patch new file mode 100755 index 0000000..d8d5245 --- /dev/null +++ b/glibc-rh1764234-2.patch @@ -0,0 +1,43 @@ +commit 477e739b324349df854209117047779ac3142130 +Author: Joseph Myers +Date: Fri Mar 15 18:18:40 2019 +0000 + + Update syscall-names.list for Linux 5.0. + + This patch updates sysdeps/unix/sysv/linux/syscall-names.list for + Linux 5.0. Based on testing with build-many-glibcs.py, the only new + entry needed is for old_getpagesize (a newly added __NR_* name for an + old syscall on ia64). (Because 5.0 changes how syscall tables are + handled in the kernel, checking diffs wasn't a useful way of looking + for new syscalls in 5.0 as most of the syscall tables were moved to + the new representation without actually adding any syscalls to them.) + + Tested with build-many-glibcs.py. + + * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel + version to 5.0. + (old_getpagesize): New syscall. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index b650dc07cc..0227e52a5f 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -22,8 +22,8 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 4.20. +-kernel 4.20 ++# The list of system calls is current as of Linux 5.0. ++kernel 5.0 + + FAST_atomic_update + FAST_cmpxchg +@@ -261,6 +261,7 @@ nfsservctl + ni_syscall + nice + old_adjtimex ++old_getpagesize + oldfstat + oldlstat + oldolduname diff --git a/glibc-rh1764234-3.patch b/glibc-rh1764234-3.patch new file mode 100755 index 0000000..a336060 --- /dev/null +++ b/glibc-rh1764234-3.patch @@ -0,0 +1,181 @@ +commit 7621676f7a5130c030f7fff1cab72dbf2993b837 +Author: Joseph Myers +Date: Tue May 7 23:57:26 2019 +0000 + + Update syscall-names.list for Linux 5.1. + + This patch updates syscall-names.list for Linux 5.1 (which has many + new syscalls, mainly but not entirely ones for 64-bit time). + + Tested with build-many-glibcs.py (before the revert of the move to + Linux 5.1 there; verified there were no tst-syscall-list failures). + + * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel + version to 5.1. + (clock_adjtime64) New syscall. + (clock_getres_time64) Likewise. + (clock_gettime64) Likewise. + (clock_nanosleep_time64) Likewise. + (clock_settime64) Likewise. + (futex_time64) Likewise. + (io_pgetevents_time64) Likewise. + (io_uring_enter) Likewise. + (io_uring_register) Likewise. + (io_uring_setup) Likewise. + (mq_timedreceive_time64) Likewise. + (mq_timedsend_time64) Likewise. + (pidfd_send_signal) Likewise. + (ppoll_time64) Likewise. + (pselect6_time64) Likewise. + (recvmmsg_time64) Likewise. + (rt_sigtimedwait_time64) Likewise. + (sched_rr_get_interval_time64) Likewise. + (semtimedop_time64) Likewise. + (timer_gettime64) Likewise. + (timer_settime64) Likewise. + (timerfd_gettime64) Likewise. + (timerfd_settime64) Likewise. + (utimensat_time64) Likewise. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 0227e52a5f..2d0354b8b3 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -22,8 +22,8 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 5.0. +-kernel 5.0 ++# The list of system calls is current as of Linux 5.1. ++kernel 5.1 + + FAST_atomic_update + FAST_cmpxchg +@@ -63,10 +63,15 @@ chown + chown32 + chroot + clock_adjtime ++clock_adjtime64 + clock_getres ++clock_getres_time64 + clock_gettime ++clock_gettime64 + clock_nanosleep ++clock_nanosleep_time64 + clock_settime ++clock_settime64 + clone + clone2 + close +@@ -128,6 +133,7 @@ ftime + ftruncate + ftruncate64 + futex ++futex_time64 + futimesat + get_kernel_syms + get_mempolicy +@@ -187,8 +193,12 @@ io_cancel + io_destroy + io_getevents + io_pgetevents ++io_pgetevents_time64 + io_setup + io_submit ++io_uring_enter ++io_uring_register ++io_uring_setup + ioctl + ioperm + iopl +@@ -242,7 +252,9 @@ mq_getsetattr + mq_notify + mq_open + mq_timedreceive ++mq_timedreceive_time64 + mq_timedsend ++mq_timedsend_time64 + mq_unlink + mremap + msgctl +@@ -389,6 +401,7 @@ perf_event_open + perfctr + perfmonctl + personality ++pidfd_send_signal + pipe + pipe2 + pivot_root +@@ -397,6 +410,7 @@ pkey_free + pkey_mprotect + poll + ppoll ++ppoll_time64 + prctl + pread64 + preadv +@@ -407,6 +421,7 @@ process_vm_writev + prof + profil + pselect6 ++pselect6_time64 + ptrace + putpmsg + pwrite64 +@@ -424,6 +439,7 @@ reboot + recv + recvfrom + recvmmsg ++recvmmsg_time64 + recvmsg + remap_file_pages + removexattr +@@ -442,6 +458,7 @@ rt_sigqueueinfo + rt_sigreturn + rt_sigsuspend + rt_sigtimedwait ++rt_sigtimedwait_time64 + rt_tgsigqueueinfo + rtas + s390_guarded_storage +@@ -457,6 +474,7 @@ sched_getattr + sched_getparam + sched_getscheduler + sched_rr_get_interval ++sched_rr_get_interval_time64 + sched_set_affinity + sched_setaffinity + sched_setattr +@@ -470,6 +488,7 @@ semctl + semget + semop + semtimedop ++semtimedop_time64 + send + sendfile + sendfile64 +@@ -567,11 +586,15 @@ timer_create + timer_delete + timer_getoverrun + timer_gettime ++timer_gettime64 + timer_settime ++timer_settime64 + timerfd + timerfd_create + timerfd_gettime ++timerfd_gettime64 + timerfd_settime ++timerfd_settime64 + times + tkill + truncate +@@ -591,6 +614,7 @@ userfaultfd + ustat + utime + utimensat ++utimensat_time64 + utimes + utrap_install + vfork diff --git a/glibc-rh1764234-4.patch b/glibc-rh1764234-4.patch new file mode 100755 index 0000000..5488fe1 --- /dev/null +++ b/glibc-rh1764234-4.patch @@ -0,0 +1,58 @@ +commit 0bb8f8c791862a4ff38a584af23bbb5bf3f90acd +Author: Florian Weimer +Date: Fri May 31 13:52:16 2019 +0200 + + Linux: Add oddly-named arm syscalls to syscall-names.list + + on arm defines the following macros: + + #define __ARM_NR_breakpoint (__ARM_NR_BASE+1) + #define __ARM_NR_cacheflush (__ARM_NR_BASE+2) + #define __ARM_NR_usr26 (__ARM_NR_BASE+3) + #define __ARM_NR_usr32 (__ARM_NR_BASE+4) + #define __ARM_NR_set_tls (__ARM_NR_BASE+5) + #define __ARM_NR_get_tls (__ARM_NR_BASE+6) + + These do not follow the regular __NR_* naming convention and + have so far been ignored by the syscall-names.list consistency + checks. This commit adds these names to the file, preparing + for the availability of these names in the regular __NR_* + namespace. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 2d0354b8b3..ae8adabb70 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -52,6 +52,7 @@ bdflush + bind + bpf + break ++breakpoint + brk + cachectl + cacheflush +@@ -139,6 +140,7 @@ get_kernel_syms + get_mempolicy + get_robust_list + get_thread_area ++get_tls + getcpu + getcwd + getdents +@@ -499,6 +501,7 @@ set_mempolicy + set_robust_list + set_thread_area + set_tid_address ++set_tls + setdomainname + setfsgid + setfsgid32 +@@ -611,6 +614,8 @@ unlinkat + unshare + uselib + userfaultfd ++usr26 ++usr32 + ustat + utime + utimensat diff --git a/glibc-rh1764234-5.patch b/glibc-rh1764234-5.patch new file mode 100755 index 0000000..53988c6 --- /dev/null +++ b/glibc-rh1764234-5.patch @@ -0,0 +1,30 @@ +commit a63b96fbddbf97feaa068a9efed3b5623a1a1e78 +Author: Vincent Chen +Date: Wed Jun 26 17:30:11 2019 +0800 + + Linux: Add nds32 specific syscalls to syscall-names.list + + The nds32 creates two specific syscalls, udftrap and fp_udfiex_crtl, in + kernel v5.0 and v5.2, respectively. Add these two syscalls to + syscall-names.list. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index ae8adabb70..95aa3ec7a5 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -121,6 +121,7 @@ finit_module + flistxattr + flock + fork ++fp_udfiex_crtl + free_hugepages + fremovexattr + fsetxattr +@@ -603,6 +604,7 @@ tkill + truncate + truncate64 + tuxcall ++udftrap + ugetrlimit + ulimit + umask diff --git a/glibc-rh1764234-6.patch b/glibc-rh1764234-6.patch new file mode 100755 index 0000000..5f29118 --- /dev/null +++ b/glibc-rh1764234-6.patch @@ -0,0 +1,52 @@ +commit 1f7097d09ce628878107ed30341cfc1eb3649a81 +Author: Florian Weimer +Date: Fri Jul 19 08:53:04 2019 +0200 + + Linux: Update syscall-names.list to Linux 5.2 + + This adds the system call names fsconfig, fsmount, fsopen, fspick, + move_mount, open_tree. + + Tested with build-many-glibcs.py. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 95aa3ec7a5..21bf37c627 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -23,7 +23,7 @@ + # them. + + # The list of system calls is current as of Linux 5.1. +-kernel 5.1 ++kernel 5.2 + + FAST_atomic_update + FAST_cmpxchg +@@ -124,7 +124,11 @@ fork + fp_udfiex_crtl + free_hugepages + fremovexattr ++fsconfig + fsetxattr ++fsmount ++fsopen ++fspick + fstat + fstat64 + fstatat64 +@@ -248,6 +252,7 @@ mmap + mmap2 + modify_ldt + mount ++move_mount + move_pages + mprotect + mpx +@@ -285,6 +290,7 @@ oldumount + olduname + open + open_by_handle_at ++open_tree + openat + osf_adjtime + osf_afs_syscall diff --git a/glibc-rh1764234-7.patch b/glibc-rh1764234-7.patch new file mode 100755 index 0000000..9322a53 --- /dev/null +++ b/glibc-rh1764234-7.patch @@ -0,0 +1,24 @@ +commit 9c37bde5a2067e5b4dc878bac0291d6b207b8add +Author: Joseph Myers +Date: Fri Aug 2 15:08:02 2019 +0000 + + Update kernel version in comment in syscall-names.list. + + This patch updates the Linux kernel version in a comment in + syscall-names.list to agree with the following "kernel" line. + + * sysdeps/unix/sysv/linux/syscall-names.list: Update comment. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 21bf37c627..9dcdd293d3 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -22,7 +22,7 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 5.1. ++# The list of system calls is current as of Linux 5.2. + kernel 5.2 + + FAST_atomic_update diff --git a/glibc-rh1764234-8.patch b/glibc-rh1764234-8.patch new file mode 100755 index 0000000..1728729 --- /dev/null +++ b/glibc-rh1764234-8.patch @@ -0,0 +1,47 @@ +commit 0f02b6cfc44af73d4d4363c46b3cbb18b8ff9171 +Author: Joseph Myers +Date: Wed Sep 18 22:57:46 2019 +0000 + + Update syscall-names.list for Linux 5.3. + + This patch updates syscall-names.list for Linux 5.3, adding two new + syscalls. + + Tested with build-many-glibcs.py. + + * sysdeps/unix/sysv/linux/syscall-names.list: Update kernel + version to 5.3. + (clone3): New syscall. + (pidfd_open): Likewise. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index e2382d3414..b55ffbc2a0 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -22,8 +22,8 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 5.2. +-kernel 5.2 ++# The list of system calls is current as of Linux 5.3. ++kernel 5.3 + + FAST_atomic_update + FAST_cmpxchg +@@ -75,6 +75,7 @@ clock_settime + clock_settime64 + clone + clone2 ++clone3 + close + cmpxchg_badaddr + connect +@@ -410,6 +411,7 @@ perf_event_open + perfctr + perfmonctl + personality ++pidfd_open + pidfd_send_signal + pipe + pipe2 diff --git a/glibc-rh1764235.patch b/glibc-rh1764235.patch new file mode 100755 index 0000000..1b783b9 --- /dev/null +++ b/glibc-rh1764235.patch @@ -0,0 +1,165 @@ +commit e621246ec6393ea08ae50310f9d5e72500f8c9bc +Author: Carlos O'Donell +Date: Mon Apr 8 17:35:05 2019 -0400 + + malloc: Set and reset all hooks for tracing (Bug 16573) + + If an error occurs during the tracing operation, particularly during a + call to lock_and_info() which calls _dl_addr, we may end up calling back + into the malloc-subsystem and relock the loader lock and deadlock. For + all intents and purposes the call to _dl_addr can call any of the malloc + family API functions and so we should disable all tracing before calling + such loader functions. This is similar to the strategy that the new + malloc tracer takes when calling the real malloc, namely that all + tracing ceases at the boundary to the real function and any faults at + that point are the purvue of the library (though the new tracer does + this on a per-thread basis in an MT-safe fashion). Since the new tracer + and the hook deprecation are not yet complete we must fix these issues + where we can. + + Tested on x86_64 with no regressions. + + Co-authored-by: Kwok Cheung Yeung + Reviewed-by: DJ Delorie + +diff --git a/malloc/mtrace.c b/malloc/mtrace.c +index 9064f209ec3b24c6..546d37a26018bf41 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/glibc-rh1764238-1.patch b/glibc-rh1764238-1.patch new file mode 100755 index 0000000..63fc994 --- /dev/null +++ b/glibc-rh1764238-1.patch @@ -0,0 +1,92 @@ +commit dc0afac3252d0c53716ccaf0b424f7769a66d695 +Author: marxin +Date: Wed Feb 20 14:54:35 2019 +0100 + + Add new Fortran vector math header file. + +diff --git a/bits/math-vector-fortran.h b/bits/math-vector-fortran.h +new file mode 100644 +index 0000000000000000..7c1e095094e24571 +--- /dev/null ++++ b/bits/math-vector-fortran.h +@@ -0,0 +1,19 @@ ++! Platform-specific declarations of SIMD math functions for Fortran. -*- f90 -*- ++! 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 ++! . ++ ++! No SIMD math functions are available for this platform. +diff --git a/math/Makefile b/math/Makefile +index 90b3b68916e12d85..16e68754fc863ea2 100644 +--- a/math/Makefile ++++ b/math/Makefile +@@ -26,6 +26,7 @@ headers := math.h bits/mathcalls.h bits/mathinline.h \ + fpu_control.h complex.h bits/cmathcalls.h fenv.h \ + bits/fenv.h bits/fenvinline.h bits/mathdef.h tgmath.h \ + bits/math-finite.h bits/math-vector.h \ ++ bits/math-vector-fortran.h \ + bits/libm-simd-decl-stubs.h bits/iscanonical.h \ + bits/flt-eval-method.h bits/fp-fast.h bits/fp-logb.h \ + bits/long-double.h bits/mathcalls-helper-functions.h \ +diff --git a/sysdeps/x86/fpu/bits/math-vector-fortran.h b/sysdeps/x86/fpu/bits/math-vector-fortran.h +new file mode 100644 +index 0000000000000000..36051cc73ea03602 +--- /dev/null ++++ b/sysdeps/x86/fpu/bits/math-vector-fortran.h +@@ -0,0 +1,43 @@ ++! Platform-specific declarations of SIMD math functions for Fortran. -*- f90 -*- ++! 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 ++! . ++ ++!GCC$ builtin (cos) attributes simd (notinbranch) if('x86_64') ++!GCC$ builtin (cosf) attributes simd (notinbranch) if('x86_64') ++!GCC$ builtin (sin) attributes simd (notinbranch) if('x86_64') ++!GCC$ builtin (sinf) attributes simd (notinbranch) if('x86_64') ++!GCC$ builtin (sincos) attributes simd (notinbranch) if('x86_64') ++!GCC$ builtin (sincosf) attributes simd (notinbranch) if('x86_64') ++!GCC$ builtin (log) attributes simd (notinbranch) if('x86_64') ++!GCC$ builtin (logf) attributes simd (notinbranch) if('x86_64') ++!GCC$ builtin (exp) attributes simd (notinbranch) if('x86_64') ++!GCC$ builtin (expf) attributes simd (notinbranch) if('x86_64') ++!GCC$ builtin (pow) attributes simd (notinbranch) if('x86_64') ++!GCC$ builtin (powf) attributes simd (notinbranch) if('x86_64') ++ ++!GCC$ builtin (cos) attributes simd (notinbranch) if('x32') ++!GCC$ builtin (cosf) attributes simd (notinbranch) if('x32') ++!GCC$ builtin (sin) attributes simd (notinbranch) if('x32') ++!GCC$ builtin (sinf) attributes simd (notinbranch) if('x32') ++!GCC$ builtin (sincos) attributes simd (notinbranch) if('x32') ++!GCC$ builtin (sincosf) attributes simd (notinbranch) if('x32') ++!GCC$ builtin (log) attributes simd (notinbranch) if('x32') ++!GCC$ builtin (logf) attributes simd (notinbranch) if('x32') ++!GCC$ builtin (exp) attributes simd (notinbranch) if('x32') ++!GCC$ builtin (expf) attributes simd (notinbranch) if('x32') ++!GCC$ builtin (pow) attributes simd (notinbranch) if('x32') ++!GCC$ builtin (powf) attributes simd (notinbranch) if('x32') diff --git a/glibc-rh1764238-2.patch b/glibc-rh1764238-2.patch new file mode 100755 index 0000000..5cafd01 --- /dev/null +++ b/glibc-rh1764238-2.patch @@ -0,0 +1,56 @@ +commit ae514971341dcc08ec7f8622493a65e7eb1ef9d2 +Author: marxin +Date: Thu Mar 7 09:39:55 2019 +0100 + + Fix location where math-vector-fortran.h is installed. + + 2019-03-07 Martin Liska + + * math/Makefile: Change location where math-vector-fortran.h is + installed. + * math/finclude/math-vector-fortran.h: Move from bits/math-vector-fortran.h. + * sysdeps/x86/fpu/finclude/math-vector-fortran.h: Move + from sysdeps/x86/fpu/bits/math-vector-fortran.h. + * scripts/check-installed-headers.sh: Skip Fortran header files. + * scripts/check-wrapper-headers.py: Likewise. + +Conflicts: + scripts/check-wrapper-headers.py + (Script does not exist downstream, change dropped.) + +diff --git a/math/Makefile b/math/Makefile +index 16e68754fc863ea2..df73d70840b61cd7 100644 +--- a/math/Makefile ++++ b/math/Makefile +@@ -26,7 +26,7 @@ headers := math.h bits/mathcalls.h bits/mathinline.h \ + fpu_control.h complex.h bits/cmathcalls.h fenv.h \ + bits/fenv.h bits/fenvinline.h bits/mathdef.h tgmath.h \ + bits/math-finite.h bits/math-vector.h \ +- bits/math-vector-fortran.h \ ++ finclude/math-vector-fortran.h \ + bits/libm-simd-decl-stubs.h bits/iscanonical.h \ + bits/flt-eval-method.h bits/fp-fast.h bits/fp-logb.h \ + bits/long-double.h bits/mathcalls-helper-functions.h \ +diff --git a/bits/math-vector-fortran.h b/math/finclude/math-vector-fortran.h +similarity index 100% +rename from bits/math-vector-fortran.h +rename to math/finclude/math-vector-fortran.h +diff --git a/scripts/check-installed-headers.sh b/scripts/check-installed-headers.sh +index 4a062e9cdaa57978..7a1969b43a144ebb 100644 +--- a/scripts/check-installed-headers.sh ++++ b/scripts/check-installed-headers.sh +@@ -84,6 +84,10 @@ for header in "$@"; do + (sys/elf.h) + continue;; + ++ # Skip Fortran headers. ++ (finclude/*) ++ continue;; ++ + # sys/sysctl.h is unsupported for x32. + (sys/sysctl.h) + case "$is_x32" in +diff --git a/sysdeps/x86/fpu/bits/math-vector-fortran.h b/sysdeps/x86/fpu/finclude/math-vector-fortran.h +similarity index 100% +rename from sysdeps/x86/fpu/bits/math-vector-fortran.h +rename to sysdeps/x86/fpu/finclude/math-vector-fortran.h diff --git a/glibc-rh1764241.patch b/glibc-rh1764241.patch new file mode 100755 index 0000000..9044857 --- /dev/null +++ b/glibc-rh1764241.patch @@ -0,0 +1,544 @@ +commit 09e1b0e3f6facc1af2dbcfef204f0aaa8718772b +Author: Florian Weimer +Date: Mon May 20 21:54:57 2019 +0200 + + libio: Remove codecvt vtable [BZ #24588] + + The codecvt vtable is not a real vtable because it also contains the + conversion state data. Furthermore, wide stream support was added to + GCC 3.0, after a C++ ABI bump, so there is no compatibility + requirement with libstdc++. + + This change removes several unmangled function pointers which could + be used with a corrupted FILE object to redirect execution. (libio + vtable verification did not cover the codecvt vtable.) + + Reviewed-by: Yann Droneaud + Reviewed-by: Adhemerval Zanella + +diff --git a/libio/fileops.c b/libio/fileops.c +index d2070a856e..daa5a05877 100644 +--- a/libio/fileops.c ++++ b/libio/fileops.c +@@ -331,9 +331,6 @@ _IO_new_file_fopen (FILE *fp, const char *filename, const char *mode, + + cc = fp->_codecvt = &fp->_wide_data->_codecvt; + +- /* The functions are always the same. */ +- *cc = __libio_codecvt; +- + cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps; + cc->__cd_in.__cd.__steps = fcts.towc; + +diff --git a/libio/iofgetpos.c b/libio/iofgetpos.c +index 8032192440..388c4a0708 100644 +--- a/libio/iofgetpos.c ++++ b/libio/iofgetpos.c +@@ -70,8 +70,7 @@ _IO_new_fgetpos (FILE *fp, __fpos_t *posp) + else + { + posp->__pos = pos; +- if (fp->_mode > 0 +- && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0) ++ if (fp->_mode > 0 && __libio_codecvt_encoding (fp->_codecvt) < 0) + /* This is a stateful encoding, safe the state. */ + posp->__state = fp->_wide_data->_IO_state; + } +diff --git a/libio/iofgetpos64.c b/libio/iofgetpos64.c +index 54de6a8205..6a0ba50d29 100644 +--- a/libio/iofgetpos64.c ++++ b/libio/iofgetpos64.c +@@ -54,8 +54,7 @@ _IO_new_fgetpos64 (FILE *fp, __fpos64_t *posp) + else + { + posp->__pos = pos; +- if (fp->_mode > 0 +- && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0) ++ if (fp->_mode > 0 && __libio_codecvt_encoding (fp->_codecvt) < 0) + /* This is a stateful encoding, safe the state. */ + posp->__state = fp->_wide_data->_IO_state; + } +diff --git a/libio/iofsetpos.c b/libio/iofsetpos.c +index d7b1abbc61..4df1aae082 100644 +--- a/libio/iofsetpos.c ++++ b/libio/iofsetpos.c +@@ -58,8 +58,7 @@ _IO_new_fsetpos (FILE *fp, const __fpos_t *posp) + else + { + result = 0; +- if (fp->_mode > 0 +- && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0) ++ if (fp->_mode > 0 && __libio_codecvt_encoding (fp->_codecvt) < 0) + /* This is a stateful encoding, restore the state. */ + fp->_wide_data->_IO_state = posp->__state; + } +diff --git a/libio/iofsetpos64.c b/libio/iofsetpos64.c +index d1865b728e..f382ba0dc1 100644 +--- a/libio/iofsetpos64.c ++++ b/libio/iofsetpos64.c +@@ -48,8 +48,7 @@ _IO_new_fsetpos64 (FILE *fp, const fpos64_t *posp) + else + { + result = 0; +- if (fp->_mode > 0 +- && (*fp->_codecvt->__codecvt_do_encoding) (fp->_codecvt) < 0) ++ if (fp->_mode > 0 && __libio_codecvt_encoding (fp->_codecvt) < 0) + /* This is a stateful encoding, safe the state. */ + fp->_wide_data->_IO_state = posp->__state; + } +diff --git a/libio/iofwide.c b/libio/iofwide.c +index 247cfde3d0..80cb2d5074 100644 +--- a/libio/iofwide.c ++++ b/libio/iofwide.c +@@ -39,44 +39,6 @@ + #include + + +-/* Prototypes of libio's codecvt functions. */ +-static enum __codecvt_result do_out (struct _IO_codecvt *codecvt, +- __mbstate_t *statep, +- const wchar_t *from_start, +- const wchar_t *from_end, +- const wchar_t **from_stop, char *to_start, +- char *to_end, char **to_stop); +-static enum __codecvt_result do_unshift (struct _IO_codecvt *codecvt, +- __mbstate_t *statep, char *to_start, +- char *to_end, char **to_stop); +-static enum __codecvt_result do_in (struct _IO_codecvt *codecvt, +- __mbstate_t *statep, +- const char *from_start, +- const char *from_end, +- const char **from_stop, wchar_t *to_start, +- wchar_t *to_end, wchar_t **to_stop); +-static int do_encoding (struct _IO_codecvt *codecvt); +-static int do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep, +- const char *from_start, +- const char *from_end, size_t max); +-static int do_max_length (struct _IO_codecvt *codecvt); +-static int do_always_noconv (struct _IO_codecvt *codecvt); +- +- +-/* The functions used in `codecvt' for libio are always the same. */ +-const struct _IO_codecvt __libio_codecvt = +-{ +- .__codecvt_destr = NULL, /* Destructor, never used. */ +- .__codecvt_do_out = do_out, +- .__codecvt_do_unshift = do_unshift, +- .__codecvt_do_in = do_in, +- .__codecvt_do_encoding = do_encoding, +- .__codecvt_do_always_noconv = do_always_noconv, +- .__codecvt_do_length = do_length, +- .__codecvt_do_max_length = do_max_length +-}; +- +- + /* Return orientation of stream. If mode is nonzero try to change + the orientation first. */ + #undef _IO_fwide +@@ -118,9 +80,6 @@ _IO_fwide (FILE *fp, int mode) + assert (fcts.towc_nsteps == 1); + assert (fcts.tomb_nsteps == 1); + +- /* The functions are always the same. */ +- *cc = __libio_codecvt; +- + cc->__cd_in.__cd.__nsteps = fcts.towc_nsteps; + cc->__cd_in.__cd.__steps = fcts.towc; + +@@ -150,11 +109,11 @@ _IO_fwide (FILE *fp, int mode) + } + + +-static enum __codecvt_result +-do_out (struct _IO_codecvt *codecvt, __mbstate_t *statep, +- const wchar_t *from_start, const wchar_t *from_end, +- const wchar_t **from_stop, char *to_start, char *to_end, +- char **to_stop) ++enum __codecvt_result ++__libio_codecvt_out (struct _IO_codecvt *codecvt, __mbstate_t *statep, ++ const wchar_t *from_start, const wchar_t *from_end, ++ const wchar_t **from_stop, char *to_start, char *to_end, ++ char **to_stop) + { + enum __codecvt_result result; + +@@ -202,57 +161,11 @@ do_out (struct _IO_codecvt *codecvt, __mbstate_t *statep, + } + + +-static enum __codecvt_result +-do_unshift (struct _IO_codecvt *codecvt, __mbstate_t *statep, +- char *to_start, char *to_end, char **to_stop) +-{ +- enum __codecvt_result result; +- +- struct __gconv_step *gs = codecvt->__cd_out.__cd.__steps; +- int status; +- size_t dummy; +- +- codecvt->__cd_out.__cd.__data[0].__outbuf = (unsigned char *) to_start; +- codecvt->__cd_out.__cd.__data[0].__outbufend = (unsigned char *) to_end; +- codecvt->__cd_out.__cd.__data[0].__statep = statep; +- +- __gconv_fct fct = gs->__fct; +-#ifdef PTR_DEMANGLE +- if (gs->__shlib_handle != NULL) +- PTR_DEMANGLE (fct); +-#endif +- +- status = DL_CALL_FCT (fct, +- (gs, codecvt->__cd_out.__cd.__data, NULL, NULL, +- NULL, &dummy, 1, 0)); +- +- *to_stop = (char *) codecvt->__cd_out.__cd.__data[0].__outbuf; +- +- switch (status) +- { +- case __GCONV_OK: +- case __GCONV_EMPTY_INPUT: +- result = __codecvt_ok; +- break; +- +- case __GCONV_FULL_OUTPUT: +- case __GCONV_INCOMPLETE_INPUT: +- result = __codecvt_partial; +- break; +- +- default: +- result = __codecvt_error; +- break; +- } +- +- return result; +-} +- +- +-static enum __codecvt_result +-do_in (struct _IO_codecvt *codecvt, __mbstate_t *statep, +- const char *from_start, const char *from_end, const char **from_stop, +- wchar_t *to_start, wchar_t *to_end, wchar_t **to_stop) ++enum __codecvt_result ++__libio_codecvt_in (struct _IO_codecvt *codecvt, __mbstate_t *statep, ++ const char *from_start, const char *from_end, ++ const char **from_stop, ++ wchar_t *to_start, wchar_t *to_end, wchar_t **to_stop) + { + enum __codecvt_result result; + +@@ -300,8 +213,8 @@ do_in (struct _IO_codecvt *codecvt, __mbstate_t *statep, + } + + +-static int +-do_encoding (struct _IO_codecvt *codecvt) ++int ++__libio_codecvt_encoding (struct _IO_codecvt *codecvt) + { + /* See whether the encoding is stateful. */ + if (codecvt->__cd_in.__cd.__steps[0].__stateful) +@@ -317,16 +230,10 @@ do_encoding (struct _IO_codecvt *codecvt) + } + + +-static int +-do_always_noconv (struct _IO_codecvt *codecvt) +-{ +- return 0; +-} +- +- +-static int +-do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep, +- const char *from_start, const char *from_end, size_t max) ++int ++__libio_codecvt_length (struct _IO_codecvt *codecvt, __mbstate_t *statep, ++ const char *from_start, const char *from_end, ++ size_t max) + { + int result; + const unsigned char *cp = (const unsigned char *) from_start; +@@ -353,10 +260,3 @@ do_length (struct _IO_codecvt *codecvt, __mbstate_t *statep, + + return result; + } +- +- +-static int +-do_max_length (struct _IO_codecvt *codecvt) +-{ +- return codecvt->__cd_in.__cd.__steps[0].__max_needed_from; +-} +diff --git a/libio/libio.h b/libio/libio.h +index c38095ff77..b985c386a2 100644 +--- a/libio/libio.h ++++ b/libio/libio.h +@@ -116,40 +116,8 @@ struct _IO_marker { + int _pos; + }; + +-/* This is the structure from the libstdc++ codecvt class. */ +-enum __codecvt_result +-{ +- __codecvt_ok, +- __codecvt_partial, +- __codecvt_error, +- __codecvt_noconv +-}; +- +-/* The order of the elements in the following struct must match the order +- of the virtual functions in the libstdc++ codecvt class. */ + struct _IO_codecvt + { +- void (*__codecvt_destr) (struct _IO_codecvt *); +- enum __codecvt_result (*__codecvt_do_out) (struct _IO_codecvt *, +- __mbstate_t *, +- const wchar_t *, +- const wchar_t *, +- const wchar_t **, char *, +- char *, char **); +- enum __codecvt_result (*__codecvt_do_unshift) (struct _IO_codecvt *, +- __mbstate_t *, char *, +- char *, char **); +- enum __codecvt_result (*__codecvt_do_in) (struct _IO_codecvt *, +- __mbstate_t *, +- const char *, const char *, +- const char **, wchar_t *, +- wchar_t *, wchar_t **); +- int (*__codecvt_do_encoding) (struct _IO_codecvt *); +- int (*__codecvt_do_always_noconv) (struct _IO_codecvt *); +- int (*__codecvt_do_length) (struct _IO_codecvt *, __mbstate_t *, +- const char *, const char *, size_t); +- int (*__codecvt_do_max_length) (struct _IO_codecvt *); +- + _IO_iconv_t __cd_in; + _IO_iconv_t __cd_out; + }; +diff --git a/libio/libioP.h b/libio/libioP.h +index 7bdec86a62..66afaa8968 100644 +--- a/libio/libioP.h ++++ b/libio/libioP.h +@@ -476,7 +476,6 @@ extern const struct _IO_jump_t _IO_streambuf_jumps; + extern const struct _IO_jump_t _IO_old_proc_jumps attribute_hidden; + extern const struct _IO_jump_t _IO_str_jumps attribute_hidden; + extern const struct _IO_jump_t _IO_wstr_jumps attribute_hidden; +-extern const struct _IO_codecvt __libio_codecvt attribute_hidden; + extern int _IO_do_write (FILE *, const char *, size_t); + libc_hidden_proto (_IO_do_write) + extern int _IO_new_do_write (FILE *, const char *, size_t); +@@ -932,4 +931,32 @@ IO_validate_vtable (const struct _IO_jump_t *vtable) + return vtable; + } + ++/* Character set conversion. */ ++ ++enum __codecvt_result ++{ ++ __codecvt_ok, ++ __codecvt_partial, ++ __codecvt_error, ++ __codecvt_noconv ++}; ++ ++enum __codecvt_result __libio_codecvt_out (struct _IO_codecvt *, ++ __mbstate_t *, ++ const wchar_t *, ++ const wchar_t *, ++ const wchar_t **, char *, ++ char *, char **) ++ attribute_hidden; ++enum __codecvt_result __libio_codecvt_in (struct _IO_codecvt *, ++ __mbstate_t *, ++ const char *, const char *, ++ const char **, wchar_t *, ++ wchar_t *, wchar_t **) ++ attribute_hidden; ++int __libio_codecvt_encoding (struct _IO_codecvt *) attribute_hidden; ++int __libio_codecvt_length (struct _IO_codecvt *, __mbstate_t *, ++ const char *, const char *, size_t) ++ attribute_hidden; ++ + #endif /* libioP.h. */ +diff --git a/libio/wfileops.c b/libio/wfileops.c +index 69fbb62a02..f1863db638 100644 +--- a/libio/wfileops.c ++++ b/libio/wfileops.c +@@ -72,11 +72,11 @@ _IO_wdo_write (FILE *fp, const wchar_t *data, size_t to_do) + } + + /* Now convert from the internal format into the external buffer. */ +- result = (*cc->__codecvt_do_out) (cc, &fp->_wide_data->_IO_state, +- data, data + to_do, &new_data, +- write_ptr, +- buf_end, +- &write_ptr); ++ result = __libio_codecvt_out (cc, &fp->_wide_data->_IO_state, ++ data, data + to_do, &new_data, ++ write_ptr, ++ buf_end, ++ &write_ptr); + + /* Write out what we produced so far. */ + if (_IO_new_do_write (fp, write_base, write_ptr - write_base) == EOF) +@@ -140,12 +140,12 @@ _IO_wfile_underflow (FILE *fp) + fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr = + fp->_wide_data->_IO_buf_base; +- status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, +- fp->_IO_read_ptr, fp->_IO_read_end, +- &read_stop, +- fp->_wide_data->_IO_read_ptr, +- fp->_wide_data->_IO_buf_end, +- &fp->_wide_data->_IO_read_end); ++ status = __libio_codecvt_in (cd, &fp->_wide_data->_IO_state, ++ fp->_IO_read_ptr, fp->_IO_read_end, ++ &read_stop, ++ fp->_wide_data->_IO_read_ptr, ++ fp->_wide_data->_IO_buf_end, ++ &fp->_wide_data->_IO_read_end); + + fp->_IO_read_base = fp->_IO_read_ptr; + fp->_IO_read_ptr = (char *) read_stop; +@@ -266,11 +266,11 @@ _IO_wfile_underflow (FILE *fp) + naccbuf += to_copy; + from = accbuf; + } +- status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, +- from, to, &read_ptr_copy, +- fp->_wide_data->_IO_read_end, +- fp->_wide_data->_IO_buf_end, +- &fp->_wide_data->_IO_read_end); ++ status = __libio_codecvt_in (cd, &fp->_wide_data->_IO_state, ++ from, to, &read_ptr_copy, ++ fp->_wide_data->_IO_read_end, ++ fp->_wide_data->_IO_buf_end, ++ &fp->_wide_data->_IO_read_end); + + if (__glibc_unlikely (naccbuf != 0)) + fp->_IO_read_ptr += MAX (0, read_ptr_copy - &accbuf[naccbuf - to_copy]); +@@ -372,12 +372,12 @@ _IO_wfile_underflow_mmap (FILE *fp) + fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr = + fp->_wide_data->_IO_buf_base; +- (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, +- fp->_IO_read_ptr, fp->_IO_read_end, +- &read_stop, +- fp->_wide_data->_IO_read_ptr, +- fp->_wide_data->_IO_buf_end, +- &fp->_wide_data->_IO_read_end); ++ __libio_codecvt_in (cd, &fp->_wide_data->_IO_state, ++ fp->_IO_read_ptr, fp->_IO_read_end, ++ &read_stop, ++ fp->_wide_data->_IO_read_ptr, ++ fp->_wide_data->_IO_buf_end, ++ &fp->_wide_data->_IO_read_end); + + fp->_IO_read_ptr = (char *) read_stop; + +@@ -495,7 +495,7 @@ _IO_wfile_sync (FILE *fp) + struct _IO_codecvt *cv = fp->_codecvt; + off64_t new_pos; + +- int clen = (*cv->__codecvt_do_encoding) (cv); ++ int clen = __libio_codecvt_encoding (cv); + + if (clen > 0) + /* It is easy, a fixed number of input bytes are used for each +@@ -511,9 +511,9 @@ _IO_wfile_sync (FILE *fp) + 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, wnread); ++ nread = __libio_codecvt_length (cv, &fp->_wide_data->_IO_state, ++ fp->_IO_read_base, ++ fp->_IO_read_end, wnread); + fp->_IO_read_ptr = fp->_IO_read_base + nread; + delta = -(fp->_IO_read_end - fp->_IO_read_base - nread); + } +@@ -548,7 +548,7 @@ adjust_wide_data (FILE *fp, bool do_convert) + { + struct _IO_codecvt *cv = fp->_codecvt; + +- int clen = (*cv->__codecvt_do_encoding) (cv); ++ int clen = __libio_codecvt_encoding (cv); + + /* Take the easy way out for constant length encodings if we don't need to + convert. */ +@@ -565,12 +565,12 @@ adjust_wide_data (FILE *fp, bool do_convert) + { + + fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; +- status = (*cv->__codecvt_do_in) (cv, &fp->_wide_data->_IO_state, +- fp->_IO_read_base, fp->_IO_read_ptr, +- &read_stop, +- fp->_wide_data->_IO_read_base, +- fp->_wide_data->_IO_buf_end, +- &fp->_wide_data->_IO_read_end); ++ status = __libio_codecvt_in (cv, &fp->_wide_data->_IO_state, ++ fp->_IO_read_base, fp->_IO_read_ptr, ++ &read_stop, ++ fp->_wide_data->_IO_read_base, ++ fp->_wide_data->_IO_buf_end, ++ &fp->_wide_data->_IO_read_end); + + /* Should we return EILSEQ? */ + if (__glibc_unlikely (status == __codecvt_error)) +@@ -648,7 +648,7 @@ do_ftell_wide (FILE *fp) + } + + struct _IO_codecvt *cv = fp->_codecvt; +- int clen = (*cv->__codecvt_do_encoding) (cv); ++ int clen = __libio_codecvt_encoding (cv); + + if (!unflushed_writes) + { +@@ -663,9 +663,9 @@ do_ftell_wide (FILE *fp) + + size_t delta = wide_read_ptr - wide_read_base; + __mbstate_t state = fp->_wide_data->_IO_last_state; +- nread = (*cv->__codecvt_do_length) (cv, &state, +- fp->_IO_read_base, +- fp->_IO_read_end, delta); ++ nread = __libio_codecvt_length (cv, &state, ++ fp->_IO_read_base, ++ fp->_IO_read_end, delta); + offset -= fp->_IO_read_end - fp->_IO_read_base - nread; + } + } +@@ -688,9 +688,8 @@ do_ftell_wide (FILE *fp) + enum __codecvt_result status; + + __mbstate_t state = fp->_wide_data->_IO_last_state; +- status = (*cv->__codecvt_do_out) (cv, &state, +- in, in + delta, &in, +- out, out + outsize, &outstop); ++ status = __libio_codecvt_out (cv, &state, in, in + delta, &in, ++ out, out + outsize, &outstop); + + /* We don't check for __codecvt_partial because it can be + returned on one of two conditions: either the output +@@ -801,7 +800,7 @@ _IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode) + find out which position in the external buffer corresponds to + the current position in the internal buffer. */ + cv = fp->_codecvt; +- clen = (*cv->__codecvt_do_encoding) (cv); ++ clen = __libio_codecvt_encoding (cv); + + if (mode != 0 || !was_writing) + { +@@ -819,10 +818,10 @@ _IO_wfile_seekoff (FILE *fp, off64_t offset, int dir, int mode) + delta = (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); ++ nread = __libio_codecvt_length (cv, ++ &fp->_wide_data->_IO_state, ++ fp->_IO_read_base, ++ fp->_IO_read_end, delta); + fp->_IO_read_ptr = fp->_IO_read_base + nread; + fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr; + offset -= fp->_IO_read_end - fp->_IO_read_base - nread; diff --git a/glibc-rh1764242.patch b/glibc-rh1764242.patch new file mode 100755 index 0000000..b8c9a2f --- /dev/null +++ b/glibc-rh1764242.patch @@ -0,0 +1,81 @@ +commit 4997e8f31e7415652c3dedec672c0e9bf8caa9ca +Author: Adhemerval Zanella +Date: Fri Feb 1 10:39:57 2019 -0200 + + math: Enable some math builtins for clang + + This patch enable the builtin usage for clang for the C99 functions + fpclassify, isfinite, isnormal, isnan, isinf, and sigbit. This allows + clang optimize the calls on frontend instead of call the appropriate + glibc symbols. + + Checked on aarch64-linux-gnu and x86_64-linux-gnu. I checked the supported + version for each builtin based on released version from clang/llvm. + + * math/math.h (fpclassify, isfinite, isnormal, isnan): Use builtin for + clang 2.8. + (signbit): Use builtin for clang 3.3. + (isinf): Use builtin for clang 3.7. + +diff --git a/math/math.h b/math/math.h +index ddee4e408389722f..b3b414f3678e91f7 100644 +--- a/math/math.h ++++ b/math/math.h +@@ -874,7 +874,8 @@ enum + the __SUPPORT_SNAN__ check may be skipped for those versions. */ + + /* Return number of classification appropriate for X. */ +-# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ \ ++# if ((__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \ ++ || __glibc_clang_prereq (2,8)) \ + && (!defined __OPTIMIZE_SIZE__ || defined __cplusplus) + /* The check for __cplusplus allows the use of the builtin, even + when optimization for size is on. This is provided for +@@ -889,7 +890,7 @@ enum + # endif + + /* Return nonzero value if sign of X is negative. */ +-# if __GNUC_PREREQ (6,0) ++# if __GNUC_PREREQ (6,0) || __glibc_clang_prereq (3,3) + # define signbit(x) __builtin_signbit (x) + # elif defined __cplusplus + /* In C++ mode, __MATH_TG cannot be used, because it relies on +@@ -907,14 +908,16 @@ enum + # endif + + /* Return nonzero value if X is not +-Inf or NaN. */ +-# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ ++# if (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \ ++ || __glibc_clang_prereq (2,8) + # define isfinite(x) __builtin_isfinite (x) + # else + # define isfinite(x) __MATH_TG ((x), __finite, (x)) + # endif + + /* Return nonzero value if X is neither zero, subnormal, Inf, nor NaN. */ +-# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ ++# if (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \ ++ || __glibc_clang_prereq (2,8) + # define isnormal(x) __builtin_isnormal (x) + # else + # define isnormal(x) (fpclassify (x) == FP_NORMAL) +@@ -922,7 +925,8 @@ enum + + /* Return nonzero value if X is a NaN. We could use `fpclassify' but + we already have this functions `__isnan' and it is faster. */ +-# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ ++# if (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \ ++ || __glibc_clang_prereq (2,8) + # define isnan(x) __builtin_isnan (x) + # else + # define isnan(x) __MATH_TG ((x), __isnan, (x)) +@@ -939,7 +943,8 @@ enum + # define isinf(x) \ + (__builtin_types_compatible_p (__typeof (x), _Float128) \ + ? __isinff128 (x) : __builtin_isinf_sign (x)) +-# elif __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__ ++# elif (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \ ++ || __glibc_clang_prereq (3,7) + # define isinf(x) __builtin_isinf_sign (x) + # else + # define isinf(x) __MATH_TG ((x), __isinf, (x)) diff --git a/glibc-rh1769304.patch b/glibc-rh1769304.patch new file mode 100755 index 0000000..e78c759 --- /dev/null +++ b/glibc-rh1769304.patch @@ -0,0 +1,740 @@ +commit 711a322a235d4c8177713f11aa59156603b94aeb +Author: Zack Weinberg +Date: Mon Mar 11 10:59:27 2019 -0400 + + Use a proper C tokenizer to implement the obsolete typedefs test. + + The test for obsolete typedefs in installed headers was implemented + using grep, and could therefore get false positives on e.g. “ulong” + in a comment. It was also scanning all of the headers included by + our headers, and therefore testing headers we don’t control, e.g. + Linux kernel headers. + + This patch splits the obsolete-typedef test from + scripts/check-installed-headers.sh to a separate program, + scripts/check-obsolete-constructs.py. Being implemented in Python, + it is feasible to make it tokenize C accurately enough to avoid false + positives on the contents of comments and strings. It also only + examines $(headers) in each subdirectory--all the headers we install, + but not any external dependencies of those headers. Headers whose + installed name starts with finclude/ are ignored, on the assumption + that they contain Fortran. + + It is also feasible to make the new test understand the difference + between _defining_ the obsolete typedefs and _using_ the obsolete + typedefs, which means posix/{bits,sys}/types.h no longer need to be + exempted. This uncovered an actual bug in bits/types.h: __quad_t and + __u_quad_t were being used to define __S64_TYPE, __U64_TYPE, + __SQUAD_TYPE and __UQUAD_TYPE. These are changed to __int64_t and + __uint64_t respectively. This is a safe change, despite the comments + in bits/types.h claiming a difference between __quad_t and __int64_t, + because those comments are incorrect. In all current ABIs, both + __quad_t and __int64_t are ‘long’ when ‘long’ is a 64-bit type, and + ‘long long’ when ‘long’ is a 32-bit type, and similarly for __u_quad_t + and __uint64_t. (Changing the types to be what the comments say they + are would be an ABI break, as it affects C++ name mangling.) This + patch includes a minimal change to make the comments not completely + wrong. + + sys/types.h was defining the legacy BSD u_intN_t typedefs using a + construct that was not necessarily consistent with how the C99 uintN_t + typedefs are defined, and is also too complicated for the new script to + understand (it lexes C relatively accurately, but it does not attempt + to expand preprocessor macros, nor does it do any actual parsing). + This patch cuts all of that out and uses bits/types.h's __uintN_t typedefs + to define u_intN_t instead. This is verified to not change the ABI on + any supported architecture, via the c++-types test, which means u_intN_t + and uintN_t were, in fact, consistent on all supported architectures. + + Reviewed-by: Carlos O'Donell + + * 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. + +Conflicts: + Rules + (textual conflicts due to lack of check-wrapper-headers test.) + +diff --git a/Rules b/Rules +index 5abb7270aa8e24aa..a07dbb8d978b5769 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: \ +@@ -101,8 +104,19 @@ $(objpfx)check-installed-headers-cxx.out: \ + "$(CXX) $(filter-out -std=%,$(CXXFLAGS)) -D_ISOMAC $(+includes)" \ + $(headers) > $@; \ + $(evaluate-test) +-endif +-endif ++endif # $(CXX) ++ ++# Test that none of the headers installed by this directory use certain ++# obsolete constructs (e.g. legacy BSD typedefs superseded by stdint.h). ++# This script does not need $(py-env). ++tests-special += $(objpfx)check-obsolete-constructs.out ++libof-check-obsolete-constructs := testsuite ++$(objpfx)check-obsolete-constructs.out: \ ++ $(..)scripts/check-obsolete-constructs.py $(headers) ++ $(PYTHON) $^ > $@ 2>&1; \ ++ $(evaluate-test) ++ ++endif # $(headers) + + # This makes all the auxiliary and test programs. + +diff --git a/posix/bits/types.h b/posix/bits/types.h +index 5e22ce41bf4c29b3..64f344c6e7897491 100644 +--- a/posix/bits/types.h ++++ b/posix/bits/types.h +@@ -86,7 +86,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 + +@@ -112,14 +112,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/sys/types.h b/posix/sys/types.h +index db524d6cd13f0379..47eff1a7b1a91c81 100644 +--- a/posix/sys/types.h ++++ b/posix/sys/types.h +@@ -154,37 +154,20 @@ typedef unsigned int uint; + + #include + +-#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 7a1969b43a144ebb..c2aeea5aabcc7ffd 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 + # . + +-# 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 +@@ -155,22 +142,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 0000000000000000..ce5c72251f4d7cc0 +--- /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 ++# . ++ ++"""Verifies that installed headers do not use any obsolete constructs: ++ * legacy BSD typedefs superseded by : ++ 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 \"(?:[^\"\\\r\n]|\\(?:[\r\n -~]|\r\n))*\") ++ |(?P \"(?:[^\"\\\r\n]|\\[ -~])*) ++ |(?P \'(?:[^\'\\\r\n]|\\(?:[\r\n -~]|\r\n))*\') ++ |(?P \'(?:[^\'\\\r\n]|\\[ -~])*) ++ |(?P /\*(?:\*(?!/)|[^*])*\*/) ++ |(?P /\*(?:\*(?!/)|[^*])*\*?) ++ |(?P //[^\r\n]*) ++ |(?P [_a-zA-Z][_a-zA-Z0-9]*) ++ |(?P \.?[0-9](?:[0-9a-df-oq-zA-DF-OQ-Z_.]|[eEpP][+-]?)*) ++ |(?P ++ [,;?~(){}\[\]] ++ | [!*/^=]=? ++ | \#\#? ++ | %(?:[=>]|:(?:%:)?)? ++ | &[=&]? ++ |\|[=|]? ++ |\+[=+]? ++ | -[=->]? ++ |\.(?:\.\.)? ++ | :>? ++ | <(?:[%:]|<(?:=|<=?)?)? ++ | >(?:=|>=?)?) ++ |(?P \\(?:\r|\n|\r\n)) ++ |(?P [ \t\n\r\v\f]+) ++ |(?P .) ++""", 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, ++ '' 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 = "" ++ elif kind == "IDENT" and directive == "": ++ 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/glibc-rh1774021.patch b/glibc-rh1774021.patch new file mode 100755 index 0000000..e298717 --- /dev/null +++ b/glibc-rh1774021.patch @@ -0,0 +1,24 @@ +commit d5dfad4326fc683c813df1e37bbf5cf920591c8e +Author: Marcin Kościelnicki +Date: Thu Nov 21 00:20:15 2019 +0100 + + rtld: Check __libc_enable_secure before honoring LD_PREFER_MAP_32BIT_EXEC (CVE-2019-19126) [BZ #25204] + + The problem was introduced in glibc 2.23, in commit + b9eb92ab05204df772eb4929eccd018637c9f3e9 + ("Add Prefer_MAP_32BIT_EXEC to map executable pages with MAP_32BIT"). + +diff --git a/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h b/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h +index 194369174df08946..ac694c032e7baf87 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h ++++ b/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h +@@ -31,7 +31,8 @@ + environment variable, LD_PREFER_MAP_32BIT_EXEC. */ + #define EXTRA_LD_ENVVARS \ + case 21: \ +- if (memcmp (envline, "PREFER_MAP_32BIT_EXEC", 21) == 0) \ ++ if (!__libc_enable_secure \ ++ && memcmp (envline, "PREFER_MAP_32BIT_EXEC", 21) == 0) \ + GLRO(dl_x86_cpu_features).feature[index_arch_Prefer_MAP_32BIT_EXEC] \ + |= bit_arch_Prefer_MAP_32BIT_EXEC; \ + break; diff --git a/glibc-rh1774114.patch b/glibc-rh1774114.patch new file mode 100755 index 0000000..bdee317 --- /dev/null +++ b/glibc-rh1774114.patch @@ -0,0 +1,85 @@ +commit 58e8f5fd2ba47b6dc47fd4d0a35e4175c7c87aaa +Author: Andreas Schwab +Date: Wed Oct 9 17:46:47 2019 +0200 + + ldconfig: handle .dynstr located in separate segment (bug 25087) + + To determine the load offset of the DT_STRTAB section search for the + segment containing it, instead of using the load offset of the first + segment. + +diff --git a/elf/readelflib.c b/elf/readelflib.c +index 5a1e2dc2dfa36599..8774e779f5abbfbb 100644 +--- a/elf/readelflib.c ++++ b/elf/readelflib.c +@@ -45,7 +45,6 @@ process_elf_file (const char *file_name, const char *lib, int *flag, + { + int i; + unsigned int j; +- ElfW(Addr) loadaddr; + unsigned int dynamic_addr; + size_t dynamic_size; + char *program_interpreter; +@@ -87,7 +86,6 @@ process_elf_file (const char *file_name, const char *lib, int *flag, + libc5/libc6. */ + *flag = FLAG_ELF; + +- loadaddr = -1; + dynamic_addr = 0; + dynamic_size = 0; + program_interpreter = NULL; +@@ -98,11 +96,6 @@ process_elf_file (const char *file_name, const char *lib, int *flag, + + switch (segment->p_type) + { +- case PT_LOAD: +- if (loadaddr == (ElfW(Addr)) -1) +- loadaddr = segment->p_vaddr - segment->p_offset; +- break; +- + case PT_DYNAMIC: + if (dynamic_addr) + error (0, 0, _("more than one dynamic segment\n")); +@@ -176,11 +169,6 @@ process_elf_file (const char *file_name, const char *lib, int *flag, + } + + } +- if (loadaddr == (ElfW(Addr)) -1) +- { +- /* Very strange. */ +- loadaddr = 0; +- } + + /* Now we can read the dynamic sections. */ + if (dynamic_size == 0) +@@ -197,7 +185,29 @@ process_elf_file (const char *file_name, const char *lib, int *flag, + check_ptr (dyn_entry); + if (dyn_entry->d_tag == DT_STRTAB) + { +- dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr); ++ /* Find the file offset of the segment containing the dynamic ++ string table. */ ++ ElfW(Off) loadoff = -1; ++ for (i = 0, segment = elf_pheader; ++ i < elf_header->e_phnum; i++, segment++) ++ { ++ if (segment->p_type == PT_LOAD ++ && dyn_entry->d_un.d_val >= segment->p_vaddr ++ && (dyn_entry->d_un.d_val - segment->p_vaddr ++ < segment->p_filesz)) ++ { ++ loadoff = segment->p_vaddr - segment->p_offset; ++ break; ++ } ++ } ++ if (loadoff == (ElfW(Off)) -1) ++ { ++ /* Very strange. */ ++ loadoff = 0; ++ } ++ ++ dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val ++ - loadoff); + check_ptr (dynamic_strings); + break; + } diff --git a/glibc-rh1774115.patch b/glibc-rh1774115.patch new file mode 100755 index 0000000..a660644 --- /dev/null +++ b/glibc-rh1774115.patch @@ -0,0 +1,103 @@ +Partial backport without the new tst-dlopen-aout-pie test. The test +fails because the a self-dlopen of a PIE binary succeeds, as commit +23d2e5faf0bca6d9b31bef4aa162b95ee64cbfc6 ("elf: Self-dlopen failure +with explict loader invocation [BZ #24900]") has not been backported. + +commit 77523d5e43cb5721c23855eb6045b0607a3b30a0 +Author: Florian Weimer +Date: Fri Oct 4 21:23:51 2019 +0200 + + elf: Assign TLS modid later during dlopen [BZ #24930] + + Commit a42faf59d6d9f82e5293a9ebcc26d9c9e562b12b ("Fix BZ #16634.") + attempted to fix a TLS modid consistency issue by adding additional + checks to the open_verify function. However, this is fragile + because open_verify cannot reliably predict whether + _dl_map_object_from_fd will later fail in the more complex cases + (such as memory allocation failures). Therefore, this commit + assigns the TLS modid as late as possible. At that point, the link + map pointer will eventually be passed to _dl_close, which will undo + the TLS modid assignment. + + Reviewed-by: Gabriel F. T. Gomes + +diff --git a/elf/dl-load.c b/elf/dl-load.c +index bb839ef70ff46f37..b190b28e32e47391 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -1134,27 +1134,21 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + offset. We will adjust it later. */ + l->l_tls_initimage = (void *) ph->p_vaddr; + +- /* If not loading the initial set of shared libraries, +- check whether we should permit loading a TLS segment. */ +- if (__glibc_likely (l->l_type == lt_library) +- /* If GL(dl_tls_dtv_slotinfo_list) == NULL, then rtld.c did +- not set up TLS data structures, so don't use them now. */ +- || __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL)) +- { +- /* Assign the next available module ID. */ +- l->l_tls_modid = _dl_next_tls_modid (); +- break; +- } ++ /* l->l_tls_modid is assigned below, once there is no ++ possibility for failure. */ + ++ if (l->l_type != lt_library ++ && GL(dl_tls_dtv_slotinfo_list) == NULL) ++ { + #ifdef SHARED +- /* We are loading the executable itself when the dynamic +- linker was executed directly. The setup will happen +- later. Otherwise, the TLS data structures are already +- initialized, and we assigned a TLS modid above. */ +- assert (l->l_prev == NULL || (mode & __RTLD_AUDIT) != 0); ++ /* We are loading the executable itself when the dynamic ++ linker was executed directly. The setup will happen ++ later. */ ++ assert (l->l_prev == NULL || (mode & __RTLD_AUDIT) != 0); + #else +- assert (false && "TLS not initialized in static application"); ++ assert (false && "TLS not initialized in static application"); + #endif ++ } + break; + + case PT_GNU_STACK: +@@ -1395,6 +1389,18 @@ cannot enable executable stack as shared object requires"); + add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB]) + + l->l_info[DT_SONAME]->d_un.d_val)); + ++ /* _dl_close can only eventually undo the module ID assignment (via ++ remove_slotinfo) if this function returns a pointer to a link ++ map. Therefore, delay this step until all possibilities for ++ failure have been excluded. */ ++ if (l->l_tls_blocksize > 0 ++ && (__glibc_likely (l->l_type == lt_library) ++ /* If GL(dl_tls_dtv_slotinfo_list) == NULL, then rtld.c did ++ not set up TLS data structures, so don't use them now. */ ++ || __glibc_likely (GL(dl_tls_dtv_slotinfo_list) != NULL))) ++ /* Assign the next available module ID. */ ++ l->l_tls_modid = _dl_next_tls_modid (); ++ + #ifdef DL_AFTER_LOAD + DL_AFTER_LOAD (l); + #endif +@@ -1662,17 +1668,6 @@ open_verify (const char *name, int fd, + errstring = N_("only ET_DYN and ET_EXEC can be loaded"); + goto call_lose; + } +- else if (__glibc_unlikely (ehdr->e_type == ET_EXEC +- && (mode & __RTLD_OPENEXEC) == 0)) +- { +- /* BZ #16634. It is an error to dlopen ET_EXEC (unless +- __RTLD_OPENEXEC is explicitly set). We return error here +- so that code in _dl_map_object_from_fd does not try to set +- l_tls_modid for this module. */ +- +- errstring = N_("cannot dynamically load executable"); +- goto call_lose; +- } + else if (__glibc_unlikely (ehdr->e_phentsize != sizeof (ElfW(Phdr)))) + { + errstring = N_("ELF file's phentsize not the expected size"); diff --git a/glibc-rh1775294.patch b/glibc-rh1775294.patch new file mode 100755 index 0000000..1805d6c --- /dev/null +++ b/glibc-rh1775294.patch @@ -0,0 +1,70 @@ +commit bfa864e1645e140da2e1aae3cf0d0ba0674f6eb5 +Author: Emilio Cobos Álvarez +Date: Tue Nov 12 19:18:32 2019 +0100 + + Don't use a custom wrapper macro around __has_include (bug 25189). + + This causes issues when using clang with -frewrite-includes to e.g., + submit the translation unit to a distributed compiler. + + In my case, I was building Firefox using sccache. + + See [1] for a reduced test-case since I initially thought this was a + clang bug, and [2] for more context. + + Apparently doing this is invalid C++ per [cpp.cond], which mentions [3]: + + > The #ifdef and #ifndef directives, and the defined conditional + > inclusion operator, shall treat __has_include and __has_cpp_attribute + > as if they were the names of defined macros. The identifiers + > __has_include and __has_cpp_attribute shall not appear in any context + > not mentioned in this subclause. + + [1]: https://bugs.llvm.org/show_bug.cgi?id=43982 + [2]: https://bugs.llvm.org/show_bug.cgi?id=37990 + [3]: http://eel.is/c++draft/cpp.cond#7.sentence-2 + + Change-Id: Id4b8ee19176a9e4624b533087ba870c418f27e60 + +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index 9e840e602f815d86..3f6fe3cc8563b493 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -412,14 +412,6 @@ + # define __glibc_has_attribute(attr) 0 + #endif + +-#ifdef __has_include +-/* Do not use a function-like macro, so that __has_include can inhibit +- macro expansion. */ +-# define __glibc_has_include __has_include +-#else +-# define __glibc_has_include(header) 0 +-#endif +- + #if (!defined _Noreturn \ + && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \ + && !__GNUC_PREREQ (4,7)) +diff --git a/sysdeps/unix/sysv/linux/bits/statx.h b/sysdeps/unix/sysv/linux/bits/statx.h +index 206878723fd37881..aaccfdc2dc03a1dc 100644 +--- a/sysdeps/unix/sysv/linux/bits/statx.h ++++ b/sysdeps/unix/sysv/linux/bits/statx.h +@@ -26,11 +26,13 @@ + + /* Use "" to work around incorrect macro expansion of the + __has_include argument (GCC PR 80005). */ +-#if __glibc_has_include ("linux/stat.h") +-# include "linux/stat.h" +-# ifdef STATX_TYPE +-# define __statx_timestamp_defined 1 +-# define __statx_defined 1 ++#ifdef __has_include ++# if __has_include ("linux/stat.h") ++# include "linux/stat.h" ++# ifdef STATX_TYPE ++# define __statx_timestamp_defined 1 ++# define __statx_defined 1 ++# endif + # endif + #endif + diff --git a/glibc-rh1775819.patch b/glibc-rh1775819.patch new file mode 100755 index 0000000..a9e6338 --- /dev/null +++ b/glibc-rh1775819.patch @@ -0,0 +1,33 @@ +commit f55e312bcd6582b5ff68fdcc1781c7017796dc91 +Author: Florian Weimer +Date: Thu Nov 28 14:42:11 2019 +0100 + + libio: Disable vtable validation for pre-2.1 interposed handles [BZ #25203] + + Commit c402355dfa7807b8e0adb27c009135a7e2b9f1b0 ("libio: Disable + vtable validation in case of interposition [BZ #23313]") only covered + the interposable glibc 2.1 handles, in libio/stdfiles.c. The + parallel code in libio/oldstdfiles.c needs similar detection logic. + + Fixes (again) commit db3476aff19b75c4fdefbe65fcd5f0a90588ba51 + ("libio: Implement vtable verification [BZ #20191]"). + + Change-Id: Ief6f9f17e91d1f7263421c56a7dc018f4f595c21 + (cherry picked from commit cb61630ed712d033f54295f776967532d3f4b46a) + +diff --git a/libio/oldstdfiles.c b/libio/oldstdfiles.c +index f3dda89004..9fe809bd68 100644 +--- a/libio/oldstdfiles.c ++++ b/libio/oldstdfiles.c +@@ -87,6 +87,11 @@ _IO_check_libio (void) + stdout->_vtable_offset = stderr->_vtable_offset = + ((int) sizeof (struct _IO_FILE) + - (int) sizeof (struct _IO_FILE_complete)); ++ ++ if (_IO_stdin_.vtable != &_IO_old_file_jumps ++ || _IO_stdout_.vtable != &_IO_old_file_jumps ++ || _IO_stderr_.vtable != &_IO_old_file_jumps) ++ IO_set_accept_foreign_vtables (&_IO_vtable_check); + } + } + diff --git a/glibc-rh1777241.patch b/glibc-rh1777241.patch new file mode 100755 index 0000000..e68afdd --- /dev/null +++ b/glibc-rh1777241.patch @@ -0,0 +1,88 @@ +commit bfdb731438206b0f70fe7afa890681155c30b419 +Author: Stefan Liebler +Date: Wed Nov 27 12:35:40 2019 +0100 + + S390: Fix handling of needles crossing a page in strstr z15 ifunc-variant. [BZ #25226] + + If the specified needle crosses a page-boundary, the s390-z15 ifunc variant of + strstr truncates the needle which results in invalid results. + + This is fixed by loading the needle beyond the page boundary to v18 instead of v16. + The bug is sometimes observable in test-strstr.c in check1 and check2 as the + haystack and needle is stored on stack. Thus the needle can be on a page boundary. + + check2 is now extended to test haystack / needles located on stack, at end of page + and on two pages. + + This bug was introduced with commit 6f47401bd5fc71209219779a0426170a9a7395b0 + ("S390: Add arch13 strstr ifunc variant.") and is already released in glibc 2.30. + +diff --git a/string/test-strstr.c b/string/test-strstr.c +index 5861b01b73e4c315..e9e14c1ee605516e 100644 +--- a/string/test-strstr.c ++++ b/string/test-strstr.c +@@ -138,16 +138,45 @@ check1 (void) + static void + check2 (void) + { +- const char s1[] = ", enable_static, \0, enable_shared, "; ++ const char s1_stack[] = ", enable_static, \0, enable_shared, "; ++ const size_t s1_byte_count = 18; ++ const char *s2_stack = &(s1_stack[s1_byte_count]); ++ const size_t s2_byte_count = 18; + char *exp_result; +- char *s2 = (void *) buf1 + page_size - 18; ++ const size_t page_size_real = getpagesize (); + +- strcpy (s2, s1); +- exp_result = stupid_strstr (s1, s1 + 18); ++ /* Haystack at end of page. The following page is protected. */ ++ char *s1_page_end = (void *) buf1 + page_size - s1_byte_count; ++ strcpy (s1_page_end, s1_stack); ++ ++ /* Haystack which crosses a page boundary. ++ Note: page_size is at least 2 * getpagesize. See test_init. */ ++ char *s1_page_cross = (void *) buf1 + page_size_real - 8; ++ strcpy (s1_page_cross, s1_stack); ++ ++ /* Needle at end of page. The following page is protected. */ ++ char *s2_page_end = (void *) buf2 + page_size - s2_byte_count; ++ strcpy (s2_page_end, s2_stack); ++ ++ /* Needle which crosses a page boundary. ++ Note: page_size is at least 2 * getpagesize. See test_init. */ ++ char *s2_page_cross = (void *) buf2 + page_size_real - 8; ++ strcpy (s2_page_cross, s2_stack); ++ ++ exp_result = stupid_strstr (s1_stack, s2_stack); + FOR_EACH_IMPL (impl, 0) + { +- check_result (impl, s1, s1 + 18, exp_result); +- check_result (impl, s2, s1 + 18, exp_result); ++ check_result (impl, s1_stack, s2_stack, exp_result); ++ check_result (impl, s1_stack, s2_page_end, exp_result); ++ check_result (impl, s1_stack, s2_page_cross, exp_result); ++ ++ check_result (impl, s1_page_end, s2_stack, exp_result); ++ check_result (impl, s1_page_end, s2_page_end, exp_result); ++ check_result (impl, s1_page_end, s2_page_cross, exp_result); ++ ++ check_result (impl, s1_page_cross, s2_stack, exp_result); ++ check_result (impl, s1_page_cross, s2_page_end, exp_result); ++ check_result (impl, s1_page_cross, s2_page_cross, exp_result); + } + } + +diff --git a/sysdeps/s390/strstr-arch13.S b/sysdeps/s390/strstr-arch13.S +index 929b026adfeba740..faa969849e09c2e1 100644 +--- a/sysdeps/s390/strstr-arch13.S ++++ b/sysdeps/s390/strstr-arch13.S +@@ -164,7 +164,7 @@ ENTRY(STRSTR_ARCH13) + vfenezb %v19,%v18,%v18 /* Search zero in loaded needle bytes. */ + veclb %v19,%v21 /* Zero index <= max loaded byte index? */ + jle .Lneedle_loaded /* -> v18 contains full needle. */ +- vl %v16,0(%r3) /* Load needle beyond page boundary. */ ++ vl %v18,0(%r3) /* Load needle beyond page boundary. */ + vfenezb %v19,%v18,%v18 + j .Lneedle_loaded + END(STRSTR_ARCH13) diff --git a/glibc-rh1780204-01.patch b/glibc-rh1780204-01.patch new file mode 100755 index 0000000..33a1752 --- /dev/null +++ b/glibc-rh1780204-01.patch @@ -0,0 +1,48 @@ +From 34e75eb497941f829115e6e8f34e899575f4e342 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Fri, 18 Oct 2019 14:57:14 +0200 +Subject: [PATCH 01/28] S390: Add new s390 platform z15. + +The new IBM z15 is added to platform string array. +The macro _DL_PLATFORMS_COUNT is incremented. + +(cherry picked from commit 2901743568452403849be7295c8732faa7732339) +--- + sysdeps/s390/dl-procinfo.c | 4 ++-- + sysdeps/s390/dl-procinfo.h | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c +index 6ea220a171..6d76d7d008 100644 +--- a/sysdeps/s390/dl-procinfo.c ++++ b/sysdeps/s390/dl-procinfo.c +@@ -63,11 +63,11 @@ PROCINFO_CLASS const char _dl_s390_cap_flags[19][9] + #if !defined PROCINFO_DECL && defined SHARED + ._dl_s390_platforms + #else +-PROCINFO_CLASS const char _dl_s390_platforms[9][7] ++PROCINFO_CLASS const char _dl_s390_platforms[10][7] + #endif + #ifndef PROCINFO_DECL + = { +- "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14" ++ "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14", "z15" + } + #endif + #if !defined SHARED || defined PROCINFO_DECL +diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h +index d03c69fffd..b367bbe8ce 100644 +--- a/sysdeps/s390/dl-procinfo.h ++++ b/sysdeps/s390/dl-procinfo.h +@@ -23,7 +23,7 @@ + + #define _DL_HWCAP_COUNT 19 + +-#define _DL_PLATFORMS_COUNT 9 ++#define _DL_PLATFORMS_COUNT 10 + + /* The kernel provides up to 32 capability bits with elf_hwcap. */ + #define _DL_FIRST_PLATFORM 32 +-- +2.18.2 + diff --git a/glibc-rh1780204-02.patch b/glibc-rh1780204-02.patch new file mode 100755 index 0000000..e9d2ea3 --- /dev/null +++ b/glibc-rh1780204-02.patch @@ -0,0 +1,159 @@ +From 73f98d03d2cde34255c0a39ef18902bffdce0185 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:14 +0100 +Subject: [PATCH 02/28] Always use wordsize-64 version of s_rint.c. + +This patch replaces s_rint.c in sysdeps/dbl-64 with the one in +sysdeps/dbl-64/wordsize-64 and removes the latter one. +The code is not changed except changes in code style. + +Also adjusted the include path in x86_64 file. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit ab48bdd098a675dddb360faafc497a61c4bd4334) +--- + sysdeps/ieee754/dbl-64/s_rint.c | 32 ++++++------ + sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c | 57 --------------------- + sysdeps/x86_64/fpu/multiarch/s_rint-c.c | 2 +- + 3 files changed, 17 insertions(+), 74 deletions(-) + delete mode 100644 sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c + +diff --git a/sysdeps/ieee754/dbl-64/s_rint.c b/sysdeps/ieee754/dbl-64/s_rint.c +index cb0f5ca298..7f3dc87b96 100644 +--- a/sysdeps/ieee754/dbl-64/s_rint.c ++++ b/sysdeps/ieee754/dbl-64/s_rint.c +@@ -1,4 +1,3 @@ +-/* @(#)s_rint.c 5.1 93/09/24 */ + /* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +@@ -25,38 +24,39 @@ + #include + + static const double +- TWO52[2] = { +- 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ +- -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ ++TWO52[2] = { ++ 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ ++ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ + }; + + double + __rint (double x) + { +- int32_t i0, j0, sx; +- double w, t; +- GET_HIGH_WORD (i0, x); +- sx = (i0 >> 31) & 1; +- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; ++ int64_t i0, sx; ++ int32_t j0; ++ EXTRACT_WORDS64 (i0, x); ++ sx = (i0 >> 63) & 1; ++ j0 = ((i0 >> 52) & 0x7ff) - 0x3ff; + if (j0 < 52) + { + if (j0 < 0) + { +- w = TWO52[sx] + x; +- t = w - TWO52[sx]; +- GET_HIGH_WORD (i0, t); +- SET_HIGH_WORD (t, (i0 & 0x7fffffff) | (sx << 31)); ++ double w = TWO52[sx] + x; ++ double t = w - TWO52[sx]; ++ EXTRACT_WORDS64 (i0, t); ++ INSERT_WORDS64 (t, (i0 & UINT64_C (0x7fffffffffffffff)) ++ | (sx << 63)); + return t; + } + } + else + { + if (j0 == 0x400) +- return x + x; /* inf or NaN */ ++ return x + x; /* inf or NaN */ + else +- return x; /* x is integral */ ++ return x; /* x is integral */ + } +- w = TWO52[sx] + x; ++ double w = TWO52[sx] + x; + return w - TWO52[sx]; + } + #ifndef __rint +diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c +deleted file mode 100644 +index 622e479c5f..0000000000 +--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_rint.c ++++ /dev/null +@@ -1,57 +0,0 @@ +-/* +- * ==================================================== +- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +- * +- * Developed at SunPro, a Sun Microsystems, Inc. business. +- * Permission to use, copy, modify, and distribute this +- * software is freely granted, provided that this notice +- * is preserved. +- * ==================================================== +- */ +- +-/* +- * rint(x) +- * Return x rounded to integral value according to the prevailing +- * rounding mode. +- * Method: +- * Using floating addition. +- * Exception: +- * Inexact flag raised if x not equal to rint(x). +- */ +- +-#include +-#include +-#include +- +-static const double +-TWO52[2]={ +- 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ +- -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +-}; +- +-double +-__rint(double x) +-{ +- int64_t i0,sx; +- int32_t j0; +- EXTRACT_WORDS64(i0,x); +- sx = (i0>>63)&1; +- j0 = ((i0>>52)&0x7ff)-0x3ff; +- if(j0<52) { +- if(j0<0) { +- double w = TWO52[sx]+x; +- double t = w-TWO52[sx]; +- EXTRACT_WORDS64(i0,t); +- INSERT_WORDS64(t,(i0&UINT64_C(0x7fffffffffffffff))|(sx<<63)); +- return t; +- } +- } else { +- if(j0==0x400) return x+x; /* inf or NaN */ +- else return x; /* x is integral */ +- } +- double w = TWO52[sx]+x; +- return w-TWO52[sx]; +-} +-#ifndef __rint +-libm_alias_double (__rint, rint) +-#endif +diff --git a/sysdeps/x86_64/fpu/multiarch/s_rint-c.c b/sysdeps/x86_64/fpu/multiarch/s_rint-c.c +index 162a630ff9..b010150f52 100644 +--- a/sysdeps/x86_64/fpu/multiarch/s_rint-c.c ++++ b/sysdeps/x86_64/fpu/multiarch/s_rint-c.c +@@ -1,3 +1,3 @@ + #undef __rint + #define __rint __rint_c +-#include ++#include +-- +2.18.2 + diff --git a/glibc-rh1780204-03.patch b/glibc-rh1780204-03.patch new file mode 100755 index 0000000..1e5d46f --- /dev/null +++ b/glibc-rh1780204-03.patch @@ -0,0 +1,257 @@ +From 7741c9c7f566d09f57db45df9377ac497f6232a5 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:15 +0100 +Subject: [PATCH 03/28] Always use wordsize-64 version of s_floor.c. + +This patch replaces s_floor.c in sysdeps/dbl-64 with the one in +sysdeps/dbl-64/wordsize-64 and removes the latter one. +The code is not changed except changes in code style. + +Also adjusted the include path in x86_64 and sparc64 files. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit 95b0c2c431510013eb2f7385fc078ee2498f83bf) +Note: glibc 2.28 had no NO_MATH_REDIRECT in wordsize-64 version. +--- + sysdeps/ieee754/dbl-64/s_floor.c | 92 +++++++++---------- + sysdeps/ieee754/dbl-64/wordsize-64/s_floor.c | 71 -------------- + .../sparc64/fpu/multiarch/s_floor-generic.c | 2 +- + .../sparc64/fpu/multiarch/s_floor-vis3.c | 2 +- + sysdeps/x86_64/fpu/multiarch/s_floor-c.c | 2 +- + 5 files changed, 45 insertions(+), 124 deletions(-) + delete mode 100644 sysdeps/ieee754/dbl-64/wordsize-64/s_floor.c + +diff --git a/sysdeps/ieee754/dbl-64/s_floor.c b/sysdeps/ieee754/dbl-64/s_floor.c +index f27c6f3ad2..b551a1aafa 100644 +--- a/sysdeps/ieee754/dbl-64/s_floor.c ++++ b/sysdeps/ieee754/dbl-64/s_floor.c +@@ -1,4 +1,24 @@ +-/* @(#)s_floor.c 5.1 93/09/24 */ ++/* Round double to integer away from zero. ++ Copyright (C) 2011-2019 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 2011. ++ ++ 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 ++ . */ ++ ++/* Based on a version which carries the following copyright: */ ++ + /* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +@@ -10,6 +30,11 @@ + * ==================================================== + */ + ++#include ++#include ++#include ++#include ++ + /* + * floor(x) + * Return x rounded toward -inf to integral value +@@ -17,68 +42,35 @@ + * Bit twiddling. + */ + +-#include +-#include +-#include +- + double + __floor (double x) + { +- int32_t i0, i1, j0; +- uint32_t i, j; +- EXTRACT_WORDS (i0, i1, x); +- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; +- if (j0 < 20) ++ int64_t i0; ++ EXTRACT_WORDS64 (i0, x); ++ int32_t j0 = ((i0 >> 52) & 0x7ff) - 0x3ff; ++ if (__glibc_likely (j0 < 52)) + { + if (j0 < 0) + { +- /* return 0*sign(x) if |x|<1 */ ++ /* return 0 * sign (x) if |x| < 1 */ + if (i0 >= 0) +- { +- i0 = i1 = 0; +- } +- else if (((i0 & 0x7fffffff) | i1) != 0) +- { +- i0 = 0xbff00000; i1 = 0; +- } ++ i0 = 0; ++ else if ((i0 & 0x7fffffffffffffffl) != 0) ++ i0 = 0xbff0000000000000l; + } + else + { +- i = (0x000fffff) >> j0; +- if (((i0 & i) | i1) == 0) +- return x; /* x is integral */ ++ uint64_t i = 0x000fffffffffffffl >> j0; ++ if ((i0 & i) == 0) ++ return x; /* x is integral */ + if (i0 < 0) +- i0 += (0x00100000) >> j0; +- i0 &= (~i); i1 = 0; +- } +- } +- else if (j0 > 51) +- { +- if (j0 == 0x400) +- return x + x; /* inf or NaN */ +- else +- return x; /* x is integral */ +- } +- else +- { +- i = ((uint32_t) (0xffffffff)) >> (j0 - 20); +- if ((i1 & i) == 0) +- return x; /* x is integral */ +- if (i0 < 0) +- { +- if (j0 == 20) +- i0 += 1; +- else +- { +- j = i1 + (1 << (52 - j0)); +- if (j < i1) +- i0 += 1; /* got a carry */ +- i1 = j; +- } ++ i0 += 0x0010000000000000l >> j0; ++ i0 &= ~i; + } +- i1 &= (~i); ++ INSERT_WORDS64 (x, i0); + } +- INSERT_WORDS (x, i0, i1); ++ else if (j0 == 0x400) ++ return x + x; /* inf or NaN */ + return x; + } + #ifndef __floor +diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_floor.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_floor.c +deleted file mode 100644 +index f7e0a77ec3..0000000000 +--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_floor.c ++++ /dev/null +@@ -1,71 +0,0 @@ +-/* Round double to integer away from zero. +- Copyright (C) 2011-2018 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 2011. +- +- 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 +- . */ +- +-/* Based on a version which carries the following copyright: */ +- +-/* +- * ==================================================== +- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +- * +- * Developed at SunPro, a Sun Microsystems, Inc. business. +- * Permission to use, copy, modify, and distribute this +- * software is freely granted, provided that this notice +- * is preserved. +- * ==================================================== +- */ +- +-#include +-#include +-#include +-#include +- +-/* +- * floor(x) +- * Return x rounded toward -inf to integral value +- * Method: +- * Bit twiddling. +- */ +- +- +-double +-__floor (double x) +-{ +- int64_t i0; +- EXTRACT_WORDS64(i0,x); +- int32_t j0 = ((i0>>52)&0x7ff)-0x3ff; +- if(__builtin_expect(j0<52, 1)) { +- if(j0<0) { +- /* return 0*sign(x) if |x|<1 */ +- if(i0>=0) {i0=0;} +- else if((i0&0x7fffffffffffffffl)!=0) +- { i0=0xbff0000000000000l;} +- } else { +- uint64_t i = (0x000fffffffffffffl)>>j0; +- if((i0&i)==0) return x; /* x is integral */ +- if(i0<0) i0 += (0x0010000000000000l)>>j0; +- i0 &= (~i); +- } +- INSERT_WORDS64(x,i0); +- } else if (j0==0x400) +- return x+x; /* inf or NaN */ +- return x; +-} +-#ifndef __floor +-libm_alias_double (__floor, floor) +-#endif +diff --git a/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-generic.c b/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-generic.c +index 0f3361a9fb..c92b600df1 100644 +--- a/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-generic.c ++++ b/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-generic.c +@@ -1,2 +1,2 @@ + #define __floor __floor_generic +-#include ++#include +diff --git a/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-vis3.c b/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-vis3.c +index d9974161b0..35564b9139 100644 +--- a/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-vis3.c ++++ b/sysdeps/sparc/sparc64/fpu/multiarch/s_floor-vis3.c +@@ -20,4 +20,4 @@ + + #define __floor __floor_vis3 + +-#include ++#include +diff --git a/sysdeps/x86_64/fpu/multiarch/s_floor-c.c b/sysdeps/x86_64/fpu/multiarch/s_floor-c.c +index 68733b69ef..002d12247e 100644 +--- a/sysdeps/x86_64/fpu/multiarch/s_floor-c.c ++++ b/sysdeps/x86_64/fpu/multiarch/s_floor-c.c +@@ -1,3 +1,3 @@ + #undef __floor + #define __floor __floor_c +-#include ++#include +-- +2.18.2 + diff --git a/glibc-rh1780204-04.patch b/glibc-rh1780204-04.patch new file mode 100755 index 0000000..e447d66 --- /dev/null +++ b/glibc-rh1780204-04.patch @@ -0,0 +1,192 @@ +From d3833cb69c7ff42ac8df68ed7b646c98c3a32eb8 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:16 +0100 +Subject: [PATCH 04/28] Always use wordsize-64 version of s_ceil.c. + +This patch replaces s_ceil.c in sysdeps/dbl-64 with the one in +sysdeps/dbl-64/wordsize-64 and removes the latter one. +The code is not changed except changes in code style. + +Also adjusted the include path in x86_64 and sparc64 files. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit 9f234eafe8698fd9a441ca2309a299d0bd771156) +--- + sysdeps/ieee754/dbl-64/s_ceil.c | 59 ++++++------------- + sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c | 51 ---------------- + .../sparc64/fpu/multiarch/s_ceil-generic.c | 2 +- + .../sparc/sparc64/fpu/multiarch/s_ceil-vis3.c | 2 +- + sysdeps/x86_64/fpu/multiarch/s_ceil-c.c | 2 +- + 5 files changed, 21 insertions(+), 95 deletions(-) + delete mode 100644 sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c + +diff --git a/sysdeps/ieee754/dbl-64/s_ceil.c b/sysdeps/ieee754/dbl-64/s_ceil.c +index 5a7434c737..3becdfc515 100644 +--- a/sysdeps/ieee754/dbl-64/s_ceil.c ++++ b/sysdeps/ieee754/dbl-64/s_ceil.c +@@ -24,61 +24,38 @@ + double + __ceil (double x) + { +- int32_t i0, i1, j0; +- uint32_t i, j; +- EXTRACT_WORDS (i0, i1, x); +- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; +- if (j0 < 20) ++ int64_t i0, i; ++ int32_t j0; ++ EXTRACT_WORDS64 (i0, x); ++ j0 = ((i0 >> 52) & 0x7ff) - 0x3ff; ++ if (j0 <= 51) + { + if (j0 < 0) + { +- /* return 0*sign(x) if |x|<1 */ ++ /* return 0 * sign(x) if |x| < 1 */ + if (i0 < 0) +- { +- i0 = 0x80000000; i1 = 0; +- } +- else if ((i0 | i1) != 0) +- { +- i0 = 0x3ff00000; i1 = 0; +- } ++ i0 = INT64_C (0x8000000000000000); ++ else if (i0 != 0) ++ i0 = INT64_C (0x3ff0000000000000); + } + else + { +- i = (0x000fffff) >> j0; +- if (((i0 & i) | i1) == 0) +- return x; /* x is integral */ ++ i = INT64_C (0x000fffffffffffff) >> j0; ++ if ((i0 & i) == 0) ++ return x; /* x is integral */ + if (i0 > 0) +- i0 += (0x00100000) >> j0; +- i0 &= (~i); i1 = 0; ++ i0 += UINT64_C (0x0010000000000000) >> j0; ++ i0 &= ~i; + } + } +- else if (j0 > 51) ++ else + { + if (j0 == 0x400) +- return x + x; /* inf or NaN */ ++ return x + x; /* inf or NaN */ + else +- return x; /* x is integral */ +- } +- else +- { +- i = ((uint32_t) (0xffffffff)) >> (j0 - 20); +- if ((i1 & i) == 0) +- return x; /* x is integral */ +- if (i0 > 0) +- { +- if (j0 == 20) +- i0 += 1; +- else +- { +- j = i1 + (1 << (52 - j0)); +- if (j < i1) +- i0 += 1; /* got a carry */ +- i1 = j; +- } +- } +- i1 &= (~i); ++ return x; /* x is integral */ + } +- INSERT_WORDS (x, i0, i1); ++ INSERT_WORDS64 (x, i0); + return x; + } + #ifndef __ceil +diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c +deleted file mode 100644 +index b99829d2b0..0000000000 +--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_ceil.c ++++ /dev/null +@@ -1,51 +0,0 @@ +-/* @(#)s_ceil.c 5.1 93/09/24 */ +-/* +- * ==================================================== +- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +- * +- * Developed at SunPro, a Sun Microsystems, Inc. business. +- * Permission to use, copy, modify, and distribute this +- * software is freely granted, provided that this notice +- * is preserved. +- * ==================================================== +- */ +- +-/* +- * ceil(x) +- * Return x rounded toward -inf to integral value +- * Method: +- * Bit twiddling. +- */ +- +-#include +-#include +-#include +- +-double +-__ceil(double x) +-{ +- int64_t i0,i; +- int32_t j0; +- EXTRACT_WORDS64(i0,x); +- j0 = ((i0>>52)&0x7ff)-0x3ff; +- if(j0<=51) { +- if(j0<0) { +- /* return 0*sign(x) if |x|<1 */ +- if(i0<0) {i0=INT64_C(0x8000000000000000);} +- else if(i0!=0) { i0=INT64_C(0x3ff0000000000000);} +- } else { +- i = INT64_C(0x000fffffffffffff)>>j0; +- if((i0&i)==0) return x; /* x is integral */ +- if(i0>0) i0 += UINT64_C(0x0010000000000000)>>j0; +- i0 &= (~i); +- } +- } else { +- if(j0==0x400) return x+x; /* inf or NaN */ +- else return x; /* x is integral */ +- } +- INSERT_WORDS64(x,i0); +- return x; +-} +-#ifndef __ceil +-libm_alias_double (__ceil, ceil) +-#endif +diff --git a/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-generic.c b/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-generic.c +index febea745e1..80f68b6766 100644 +--- a/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-generic.c ++++ b/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-generic.c +@@ -1,2 +1,2 @@ + #define __ceil __ceil_generic +-#include ++#include +diff --git a/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-vis3.c b/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-vis3.c +index a03a0090f0..59822e0f8c 100644 +--- a/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-vis3.c ++++ b/sysdeps/sparc/sparc64/fpu/multiarch/s_ceil-vis3.c +@@ -20,4 +20,4 @@ + + #define __ceil __ceil_vis3 + +-#include ++#include +diff --git a/sysdeps/x86_64/fpu/multiarch/s_ceil-c.c b/sysdeps/x86_64/fpu/multiarch/s_ceil-c.c +index 6a5ea3ff27..ada28baa1a 100644 +--- a/sysdeps/x86_64/fpu/multiarch/s_ceil-c.c ++++ b/sysdeps/x86_64/fpu/multiarch/s_ceil-c.c +@@ -1,2 +1,2 @@ + #define __ceil __ceil_c +-#include ++#include +-- +2.18.2 + diff --git a/glibc-rh1780204-05.patch b/glibc-rh1780204-05.patch new file mode 100755 index 0000000..3c139a2 --- /dev/null +++ b/glibc-rh1780204-05.patch @@ -0,0 +1,157 @@ +From e8f1c08a49d313b210ed4104c20646c105bab6a4 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:17 +0100 +Subject: [PATCH 05/28] Always use wordsize-64 version of s_trunc.c. + +This patch replaces s_trunc.c in sysdeps/dbl-64 with the one in +sysdeps/dbl-64/wordsize-64 and removes the latter one. +The code is not changed except changes in code style. + +Also adjusted the include path in x86_64 and sparc64 files. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit 1c94bf0f0a50ce66c808e2ea9b7e417785798b73) +--- + sysdeps/ieee754/dbl-64/s_trunc.c | 25 ++++----- + sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c | 54 ------------------- + .../sparc64/fpu/multiarch/s_trunc-generic.c | 2 +- + .../sparc64/fpu/multiarch/s_trunc-vis3.c | 2 +- + sysdeps/x86_64/fpu/multiarch/s_trunc-c.c | 2 +- + 5 files changed, 13 insertions(+), 72 deletions(-) + delete mode 100644 sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c + +diff --git a/sysdeps/ieee754/dbl-64/s_trunc.c b/sysdeps/ieee754/dbl-64/s_trunc.c +index 6ffabb410a..38bb33d337 100644 +--- a/sysdeps/ieee754/dbl-64/s_trunc.c ++++ b/sysdeps/ieee754/dbl-64/s_trunc.c +@@ -26,31 +26,26 @@ + double + __trunc (double x) + { +- int32_t i0, j0; +- uint32_t i1; +- int sx; +- +- EXTRACT_WORDS (i0, i1, x); +- sx = i0 & 0x80000000; +- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; +- if (j0 < 20) ++ int64_t i0, j0; ++ int64_t sx; ++ ++ EXTRACT_WORDS64 (i0, x); ++ sx = i0 & UINT64_C (0x8000000000000000); ++ j0 = ((i0 >> 52) & 0x7ff) - 0x3ff; ++ if (j0 < 52) + { + if (j0 < 0) + /* The magnitude of the number is < 1 so the result is +-0. */ +- INSERT_WORDS (x, sx, 0); ++ INSERT_WORDS64 (x, sx); + else +- INSERT_WORDS (x, sx | (i0 & ~(0x000fffff >> j0)), 0); ++ INSERT_WORDS64 (x, sx | (i0 & ~(UINT64_C (0x000fffffffffffff) >> j0))); + } +- else if (j0 > 51) ++ else + { + if (j0 == 0x400) + /* x is inf or NaN. */ + return x + x; + } +- else +- { +- INSERT_WORDS (x, i0, i1 & ~(0xffffffffu >> (j0 - 20))); +- } + + return x; + } +diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c +deleted file mode 100644 +index 19a09b894e..0000000000 +--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_trunc.c ++++ /dev/null +@@ -1,54 +0,0 @@ +-/* Truncate argument to nearest integral value not larger than the argument. +- Copyright (C) 1997-2018 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 1997. +- +- 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 +- . */ +- +-#include +- +-#include +-#include +- +- +-double +-__trunc (double x) +-{ +- int64_t i0, j0; +- int64_t sx; +- +- EXTRACT_WORDS64 (i0, x); +- sx = i0 & UINT64_C(0x8000000000000000); +- j0 = ((i0 >> 52) & 0x7ff) - 0x3ff; +- if (j0 < 52) +- { +- if (j0 < 0) +- /* The magnitude of the number is < 1 so the result is +-0. */ +- INSERT_WORDS64 (x, sx); +- else +- INSERT_WORDS64 (x, sx | (i0 & ~(UINT64_C(0x000fffffffffffff) >> j0))); +- } +- else +- { +- if (j0 == 0x400) +- /* x is inf or NaN. */ +- return x + x; +- } +- +- return x; +-} +-#ifndef __trunc +-libm_alias_double (__trunc, trunc) +-#endif +diff --git a/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-generic.c b/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-generic.c +index 00abd2a643..c198ebb3d5 100644 +--- a/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-generic.c ++++ b/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-generic.c +@@ -1,2 +1,2 @@ + #define __trunc __trunc_generic +-#include ++#include +diff --git a/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-vis3.c b/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-vis3.c +index a89916ba89..766bb22629 100644 +--- a/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-vis3.c ++++ b/sysdeps/sparc/sparc64/fpu/multiarch/s_trunc-vis3.c +@@ -20,4 +20,4 @@ + + #define __trunc __trunc_vis3 + +-#include ++#include +diff --git a/sysdeps/x86_64/fpu/multiarch/s_trunc-c.c b/sysdeps/x86_64/fpu/multiarch/s_trunc-c.c +index 6204ae3c77..8aa499fbb8 100644 +--- a/sysdeps/x86_64/fpu/multiarch/s_trunc-c.c ++++ b/sysdeps/x86_64/fpu/multiarch/s_trunc-c.c +@@ -1,2 +1,2 @@ + #define __trunc __trunc_c +-#include ++#include +-- +2.18.2 + diff --git a/glibc-rh1780204-06.patch b/glibc-rh1780204-06.patch new file mode 100755 index 0000000..b0d1765 --- /dev/null +++ b/glibc-rh1780204-06.patch @@ -0,0 +1,167 @@ +From 577943dac79a5657bdfe51e06e289eb2473c3d2e Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:17 +0100 +Subject: [PATCH 06/28] Always use wordsize-64 version of s_round.c. + +This patch replaces s_round.c in sysdeps/dbl-64 with the one in +sysdeps/dbl-64/wordsize-64 and removes the latter one. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit 36e9acbd5cb2c330c0d53195db4a0ee31f2c3097) +--- + sysdeps/ieee754/dbl-64/s_round.c | 39 ++++-------- + sysdeps/ieee754/dbl-64/wordsize-64/s_round.c | 65 -------------------- + 2 files changed, 12 insertions(+), 92 deletions(-) + delete mode 100644 sysdeps/ieee754/dbl-64/wordsize-64/s_round.c + +diff --git a/sysdeps/ieee754/dbl-64/s_round.c b/sysdeps/ieee754/dbl-64/s_round.c +index fa9e83196e..bf9922edca 100644 +--- a/sysdeps/ieee754/dbl-64/s_round.c ++++ b/sysdeps/ieee754/dbl-64/s_round.c +@@ -21,38 +21,36 @@ + + #include + #include ++#include + + + double + __round (double x) + { +- int32_t i0, j0; +- uint32_t i1; ++ int64_t i0, j0; + +- EXTRACT_WORDS (i0, i1, x); +- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; +- if (j0 < 20) ++ EXTRACT_WORDS64 (i0, x); ++ j0 = ((i0 >> 52) & 0x7ff) - 0x3ff; ++ if (__glibc_likely (j0 < 52)) + { + if (j0 < 0) + { +- i0 &= 0x80000000; ++ i0 &= UINT64_C (0x8000000000000000); + if (j0 == -1) +- i0 |= 0x3ff00000; +- i1 = 0; ++ i0 |= UINT64_C (0x3ff0000000000000); + } + else + { +- uint32_t i = 0x000fffff >> j0; +- if (((i0 & i) | i1) == 0) ++ uint64_t i = UINT64_C (0x000fffffffffffff) >> j0; ++ if ((i0 & i) == 0) + /* X is integral. */ + return x; + +- i0 += 0x00080000 >> j0; ++ i0 += UINT64_C (0x0008000000000000) >> j0; + i0 &= ~i; +- i1 = 0; + } + } +- else if (j0 > 51) ++ else + { + if (j0 == 0x400) + /* Inf or NaN. */ +@@ -60,21 +58,8 @@ __round (double x) + else + return x; + } +- else +- { +- uint32_t i = 0xffffffff >> (j0 - 20); +- if ((i1 & i) == 0) +- /* X is integral. */ +- return x; +- +- uint32_t j = i1 + (1 << (51 - j0)); +- if (j < i1) +- i0 += 1; +- i1 = j; +- i1 &= ~i; +- } + +- INSERT_WORDS (x, i0, i1); ++ INSERT_WORDS64 (x, i0); + return x; + } + libm_alias_double (__round, round) +diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_round.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_round.c +deleted file mode 100644 +index 3323621ce3..0000000000 +--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_round.c ++++ /dev/null +@@ -1,65 +0,0 @@ +-/* Round double to integer away from zero. +- Copyright (C) 1997-2018 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 1997. +- +- 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 +- . */ +- +-#include +- +-#include +-#include +-#include +- +- +-double +-__round (double x) +-{ +- int64_t i0, j0; +- +- EXTRACT_WORDS64 (i0, x); +- j0 = ((i0 >> 52) & 0x7ff) - 0x3ff; +- if (__glibc_likely (j0 < 52)) +- { +- if (j0 < 0) +- { +- i0 &= UINT64_C(0x8000000000000000); +- if (j0 == -1) +- i0 |= UINT64_C(0x3ff0000000000000); +- } +- else +- { +- uint64_t i = UINT64_C(0x000fffffffffffff) >> j0; +- if ((i0 & i) == 0) +- /* X is integral. */ +- return x; +- +- i0 += UINT64_C(0x0008000000000000) >> j0; +- i0 &= ~i; +- } +- } +- else +- { +- if (j0 == 0x400) +- /* Inf or NaN. */ +- return x + x; +- else +- return x; +- } +- +- INSERT_WORDS64 (x, i0); +- return x; +-} +-libm_alias_double (__round, round) +-- +2.18.2 + diff --git a/glibc-rh1780204-07.patch b/glibc-rh1780204-07.patch new file mode 100755 index 0000000..13b3c3e --- /dev/null +++ b/glibc-rh1780204-07.patch @@ -0,0 +1,255 @@ +From 735a36828f349419379f15e942bfdf0c532d58eb Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:18 +0100 +Subject: [PATCH 07/28] Use GCC builtins for nearbyint functions if desired. + +This patch is using the corresponding GCC builtin for nearbyintf, nearbyint, +nearbintl and nearbyintf128 if the USE_FUNCTION_BUILTIN macros are defined to one +in math-use-builtins.h. + +This is the case for s390 if build with at least --march=z196 --mzarch. +Otherwise the generic implementation is used. The code of the generic +implementation is not changed. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit ae3577f607b50bf3ce9b0877e43ad2508c9da61b) +Note: The TWO52 constants are now located in # ! USE_NEARBYINT_BUILTIN +--- + sysdeps/generic/math-use-builtins.h | 29 ++++++++++++ + sysdeps/ieee754/dbl-64/s_nearbyint.c | 17 ++++--- + sysdeps/ieee754/float128/float128_private.h | 4 ++ + sysdeps/ieee754/flt-32/s_nearbyintf.c | 17 ++++--- + sysdeps/ieee754/ldbl-128/s_nearbyintl.c | 17 ++++--- + sysdeps/s390/fpu/math-use-builtins.h | 49 +++++++++++++++++++++ + 6 files changed, 115 insertions(+), 18 deletions(-) + create mode 100644 sysdeps/generic/math-use-builtins.h + create mode 100644 sysdeps/s390/fpu/math-use-builtins.h + +diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h +new file mode 100644 +index 0000000000..e12490ed41 +--- /dev/null ++++ b/sysdeps/generic/math-use-builtins.h +@@ -0,0 +1,29 @@ ++/* Using math gcc builtins instead of generic implementation. 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 ++ . */ ++ ++#ifndef MATH_USE_BUILTINS_H ++#define MATH_USE_BUILTINS_H 1 ++ ++/* Define these macros to 1 to use __builtin_xyz instead of the ++ generic implementation. */ ++#define USE_NEARBYINT_BUILTIN 0 ++#define USE_NEARBYINTF_BUILTIN 0 ++#define USE_NEARBYINTL_BUILTIN 0 ++#define USE_NEARBYINTF128_BUILTIN 0 ++ ++#endif /* math-use-builtins.h */ +diff --git a/sysdeps/ieee754/dbl-64/s_nearbyint.c b/sysdeps/ieee754/dbl-64/s_nearbyint.c +index 903121d456..6b9f44dc8d 100644 +--- a/sysdeps/ieee754/dbl-64/s_nearbyint.c ++++ b/sysdeps/ieee754/dbl-64/s_nearbyint.c +@@ -29,16 +29,20 @@ static char rcsid[] = "$NetBSD: s_rint.c,v 1.8 1995/05/10 20:48:04 jtc Exp $"; + #include + #include + #include +- +-static const double +- TWO52[2] = { +- 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ +- -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +-}; ++#include + + double + __nearbyint (double x) + { ++#if USE_NEARBYINT_BUILTIN ++ return __builtin_nearbyint (x); ++#else ++ /* Use generic implementation. */ ++ static const double ++ TWO52[2] = { ++ 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ ++ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ ++ }; + fenv_t env; + int32_t i0, j0, sx; + double w, t; +@@ -72,5 +76,6 @@ __nearbyint (double x) + math_force_eval (t); + libc_fesetenv (&env); + return t; ++#endif /* ! USE_NEARBYINT_BUILTIN */ + } + libm_alias_double (__nearbyint, nearbyint) +diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h +index 9dd15601e6..0bf6e8dee2 100644 +--- a/sysdeps/ieee754/float128/float128_private.h ++++ b/sysdeps/ieee754/float128/float128_private.h +@@ -138,6 +138,9 @@ + #undef libm_alias_double_ldouble + #define libm_alias_double_ldouble(func) libm_alias_float64_float128 (func) + ++#include ++#undef USE_NEARBYINTL_BUILTIN ++#define USE_NEARBYINTL_BUILTIN USE_NEARBYINTF128_BUILTIN + + /* IEEE function renames. */ + #define __ieee754_acoshl __ieee754_acoshf128 +@@ -339,6 +342,7 @@ + /* Builtin renames. */ + #define __builtin_copysignl __builtin_copysignf128 + #define __builtin_signbitl __builtin_signbit ++#define __builtin_nearbyintl __builtin_nearbyintf128 + + /* Get the constant suffix from bits/floatn-compat.h. */ + #define L(x) __f128 (x) +diff --git a/sysdeps/ieee754/flt-32/s_nearbyintf.c b/sysdeps/ieee754/flt-32/s_nearbyintf.c +index 4dfe491f27..438dcae8cc 100644 +--- a/sysdeps/ieee754/flt-32/s_nearbyintf.c ++++ b/sysdeps/ieee754/flt-32/s_nearbyintf.c +@@ -20,16 +20,20 @@ + #include + #include + #include +- +-static const float +-TWO23[2]={ +- 8.3886080000e+06, /* 0x4b000000 */ +- -8.3886080000e+06, /* 0xcb000000 */ +-}; ++#include + + float + __nearbyintf(float x) + { ++#if USE_NEARBYINTF_BUILTIN ++ return __builtin_nearbyintf (x); ++#else ++ /* Use generic implementation. */ ++ static const float ++ TWO23[2] = { ++ 8.3886080000e+06, /* 0x4b000000 */ ++ -8.3886080000e+06, /* 0xcb000000 */ ++ }; + fenv_t env; + int32_t i0,j0,sx; + float w,t; +@@ -57,5 +61,6 @@ __nearbyintf(float x) + math_force_eval (t); + libc_fesetenvf (&env); + return t; ++#endif /* ! USE_NEARBYINT_BUILTIN */ + } + libm_alias_float (__nearbyint, nearbyint) +diff --git a/sysdeps/ieee754/ldbl-128/s_nearbyintl.c b/sysdeps/ieee754/ldbl-128/s_nearbyintl.c +index f044cb4334..a4ad8e82e5 100644 +--- a/sysdeps/ieee754/ldbl-128/s_nearbyintl.c ++++ b/sysdeps/ieee754/ldbl-128/s_nearbyintl.c +@@ -28,15 +28,19 @@ + #include + #include + #include +- +-static const _Float128 +-TWO112[2]={ +- L(5.19229685853482762853049632922009600E+33), /* 0x406F000000000000, 0 */ +- L(-5.19229685853482762853049632922009600E+33) /* 0xC06F000000000000, 0 */ +-}; ++#include + + _Float128 __nearbyintl(_Float128 x) + { ++#if USE_NEARBYINTL_BUILTIN ++ return __builtin_nearbyintl (x); ++#else ++ /* Use generic implementation. */ ++ static const _Float128 ++ TWO112[2] = { ++ L(5.19229685853482762853049632922009600E+33), /* 0x406F000000000000, 0 */ ++ L(-5.19229685853482762853049632922009600E+33) /* 0xC06F000000000000, 0 */ ++ }; + fenv_t env; + int64_t i0,j0,sx; + uint64_t i1 __attribute__ ((unused)); +@@ -65,5 +69,6 @@ _Float128 __nearbyintl(_Float128 x) + math_force_eval (t); + fesetenv (&env); + return t; ++#endif /* ! USE_NEARBYINTL_BUILTIN */ + } + libm_alias_ldouble (__nearbyint, nearbyint) +diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h +new file mode 100644 +index 0000000000..7abbfb3b50 +--- /dev/null ++++ b/sysdeps/s390/fpu/math-use-builtins.h +@@ -0,0 +1,49 @@ ++/* Using math gcc builtins instead of generic implementation. s390/s390x 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 ++ . */ ++ ++#ifndef MATH_USE_BUILTINS_S390_H ++#define MATH_USE_BUILTINS_S390_H 1 ++ ++#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++ ++# include /* For __GNUC_PREREQ. */ ++ ++/* GCC emits the z196 zarch "load fp integer" instructions for these ++ builtins if build with at least --march=z196 -mzarch. Otherwise a ++ function call to libc is emitted. */ ++# define USE_NEARBYINT_BUILTIN 1 ++# define USE_NEARBYINTF_BUILTIN 1 ++# define USE_NEARBYINTL_BUILTIN 1 ++ ++# if __GNUC_PREREQ (8, 0) ++# define USE_NEARBYINTF128_BUILTIN 1 ++# else ++# define USE_NEARBYINTF128_BUILTIN 0 ++# endif ++ ++#else ++ ++/* Disable the builtins if we do not have the z196 zarch instructions. */ ++# define USE_NEARBYINT_BUILTIN 0 ++# define USE_NEARBYINTF_BUILTIN 0 ++# define USE_NEARBYINTL_BUILTIN 0 ++# define USE_NEARBYINTF128_BUILTIN 0 ++ ++#endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */ ++ ++#endif /* math-use-builtins.h */ +-- +2.18.2 + diff --git a/glibc-rh1780204-08.patch b/glibc-rh1780204-08.patch new file mode 100755 index 0000000..9dd3a6c --- /dev/null +++ b/glibc-rh1780204-08.patch @@ -0,0 +1,210 @@ +From d37e99de7ab1cd8c3d427f74bf8ceb5774795fe5 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:20 +0100 +Subject: [PATCH 08/28] Use GCC builtins for rint functions if desired. + +This patch is using the corresponding GCC builtin for rintf, rint, +rintl and rintf128 if the USE_FUNCTION_BUILTIN macros are defined to one +in math-use-builtins.h. + +This is the case for s390 if build with at least --march=z196 --mzarch. +Otherwise the generic implementation is used. The code of the generic +implementation is not changed. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit a2a9b004297b777758420c952cb6eea5985d37fe) +--- + sysdeps/generic/math-use-builtins.h | 5 +++++ + sysdeps/ieee754/dbl-64/s_rint.c | 17 +++++++++++------ + sysdeps/ieee754/float128/float128_private.h | 3 +++ + sysdeps/ieee754/flt-32/s_rintf.c | 17 +++++++++++------ + sysdeps/ieee754/ldbl-128/s_rintl.c | 17 +++++++++++------ + sysdeps/s390/fpu/math-use-builtins.h | 11 +++++++++++ + 6 files changed, 52 insertions(+), 18 deletions(-) + +diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h +index e12490ed41..64b4a4bb5b 100644 +--- a/sysdeps/generic/math-use-builtins.h ++++ b/sysdeps/generic/math-use-builtins.h +@@ -26,4 +26,9 @@ + #define USE_NEARBYINTL_BUILTIN 0 + #define USE_NEARBYINTF128_BUILTIN 0 + ++#define USE_RINT_BUILTIN 0 ++#define USE_RINTF_BUILTIN 0 ++#define USE_RINTL_BUILTIN 0 ++#define USE_RINTF128_BUILTIN 0 ++ + #endif /* math-use-builtins.h */ +diff --git a/sysdeps/ieee754/dbl-64/s_rint.c b/sysdeps/ieee754/dbl-64/s_rint.c +index 7f3dc87b96..5f4ac7c1e3 100644 +--- a/sysdeps/ieee754/dbl-64/s_rint.c ++++ b/sysdeps/ieee754/dbl-64/s_rint.c +@@ -22,16 +22,20 @@ + #include + #include + #include +- +-static const double +-TWO52[2] = { +- 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ +- -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +-}; ++#include + + double + __rint (double x) + { ++#if USE_RINT_BUILTIN ++ return __builtin_rint (x); ++#else ++ /* Use generic implementation. */ ++ static const double ++ TWO52[2] = { ++ 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ ++ -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ ++ }; + int64_t i0, sx; + int32_t j0; + EXTRACT_WORDS64 (i0, x); +@@ -58,6 +62,7 @@ __rint (double x) + } + double w = TWO52[sx] + x; + return w - TWO52[sx]; ++#endif /* ! USE_RINT_BUILTIN */ + } + #ifndef __rint + libm_alias_double (__rint, rint) +diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h +index 0bf6e8dee2..b872aefbfd 100644 +--- a/sysdeps/ieee754/float128/float128_private.h ++++ b/sysdeps/ieee754/float128/float128_private.h +@@ -141,6 +141,8 @@ + #include + #undef USE_NEARBYINTL_BUILTIN + #define USE_NEARBYINTL_BUILTIN USE_NEARBYINTF128_BUILTIN ++#undef USE_RINTL_BUILTIN ++#define USE_RINTL_BUILTIN USE_RINTF128_BUILTIN + + /* IEEE function renames. */ + #define __ieee754_acoshl __ieee754_acoshf128 +@@ -343,6 +345,7 @@ + #define __builtin_copysignl __builtin_copysignf128 + #define __builtin_signbitl __builtin_signbit + #define __builtin_nearbyintl __builtin_nearbyintf128 ++#define __builtin_rintl __builtin_rintf128 + + /* Get the constant suffix from bits/floatn-compat.h. */ + #define L(x) __f128 (x) +diff --git a/sysdeps/ieee754/flt-32/s_rintf.c b/sysdeps/ieee754/flt-32/s_rintf.c +index db6f260a0b..a266b1999e 100644 +--- a/sysdeps/ieee754/flt-32/s_rintf.c ++++ b/sysdeps/ieee754/flt-32/s_rintf.c +@@ -16,16 +16,20 @@ + #include + #include + #include +- +-static const float +-TWO23[2]={ +- 8.3886080000e+06, /* 0x4b000000 */ +- -8.3886080000e+06, /* 0xcb000000 */ +-}; ++#include + + float + __rintf(float x) + { ++#if USE_RINTF_BUILTIN ++ return __builtin_rintf (x); ++#else ++ /* Use generic implementation. */ ++ static const float ++ TWO23[2] = { ++ 8.3886080000e+06, /* 0x4b000000 */ ++ -8.3886080000e+06, /* 0xcb000000 */ ++ }; + int32_t i0,j0,sx; + float w,t; + GET_FLOAT_WORD(i0,x); +@@ -45,6 +49,7 @@ __rintf(float x) + } + w = TWO23[sx]+x; + return w-TWO23[sx]; ++#endif /* ! USE_RINTF_BUILTIN */ + } + #ifndef __rintf + libm_alias_float (__rint, rint) +diff --git a/sysdeps/ieee754/ldbl-128/s_rintl.c b/sysdeps/ieee754/ldbl-128/s_rintl.c +index 9e6637a225..f060503066 100644 +--- a/sysdeps/ieee754/ldbl-128/s_rintl.c ++++ b/sysdeps/ieee754/ldbl-128/s_rintl.c +@@ -30,15 +30,19 @@ static char rcsid[] = "$NetBSD: $"; + #include + #include + #include +- +-static const _Float128 +-TWO112[2]={ +- 5.19229685853482762853049632922009600E+33L, /* 0x406F000000000000, 0 */ +- -5.19229685853482762853049632922009600E+33L /* 0xC06F000000000000, 0 */ +-}; ++#include + + _Float128 __rintl(_Float128 x) + { ++#if USE_RINTL_BUILTIN ++ return __builtin_rintl (x); ++#else ++ /* Use generic implementation. */ ++ static const _Float128 ++ TWO112[2] = { ++ 5.19229685853482762853049632922009600E+33L, /* 0x406F000000000000, 0 */ ++ -5.19229685853482762853049632922009600E+33L /* 0xC06F000000000000, 0 */ ++ }; + int64_t i0,j0,sx; + uint64_t i1 __attribute__ ((unused)); + _Float128 w,t; +@@ -59,5 +63,6 @@ _Float128 __rintl(_Float128 x) + } + w = TWO112[sx]+x; + return w-TWO112[sx]; ++#endif /* ! USE_RINTL_BUILTIN */ + } + libm_alias_ldouble (__rint, rint) +diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h +index 7abbfb3b50..8b702a6a90 100644 +--- a/sysdeps/s390/fpu/math-use-builtins.h ++++ b/sysdeps/s390/fpu/math-use-builtins.h +@@ -30,10 +30,16 @@ + # define USE_NEARBYINTF_BUILTIN 1 + # define USE_NEARBYINTL_BUILTIN 1 + ++# define USE_RINT_BUILTIN 1 ++# define USE_RINTF_BUILTIN 1 ++# define USE_RINTL_BUILTIN 1 ++ + # if __GNUC_PREREQ (8, 0) + # define USE_NEARBYINTF128_BUILTIN 1 ++# define USE_RINTF128_BUILTIN 1 + # else + # define USE_NEARBYINTF128_BUILTIN 0 ++# define USE_RINTF128_BUILTIN 0 + # endif + + #else +@@ -44,6 +50,11 @@ + # define USE_NEARBYINTL_BUILTIN 0 + # define USE_NEARBYINTF128_BUILTIN 0 + ++# define USE_RINT_BUILTIN 0 ++# define USE_RINTF_BUILTIN 0 ++# define USE_RINTL_BUILTIN 0 ++# define USE_RINTF128_BUILTIN 0 ++ + #endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */ + + #endif /* math-use-builtins.h */ +-- +2.18.2 + diff --git a/glibc-rh1780204-09.patch b/glibc-rh1780204-09.patch new file mode 100755 index 0000000..fa6e2b6 --- /dev/null +++ b/glibc-rh1780204-09.patch @@ -0,0 +1,182 @@ +From 8353881ede286045dc5bdc00af6407560ca5d05b Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:20 +0100 +Subject: [PATCH 09/28] Use GCC builtins for floor functions if desired. + +This patch is using the corresponding GCC builtin for floorf, floor, +floorl and floorf128 if the USE_FUNCTION_BUILTIN macros are defined to one +in math-use-builtins.h. + +This is the case for s390 if build with at least --march=z196 --mzarch. +Otherwise the generic implementation is used. The code of the generic +implementation is not changed. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit 6c1b6a5e8cd91e0e1965509ad91e627e60eb00a3) +--- + sysdeps/generic/math-use-builtins.h | 5 +++++ + sysdeps/ieee754/dbl-64/s_floor.c | 6 ++++++ + sysdeps/ieee754/float128/float128_private.h | 3 +++ + sysdeps/ieee754/flt-32/s_floorf.c | 6 ++++++ + sysdeps/ieee754/ldbl-128/s_floorl.c | 6 ++++++ + sysdeps/s390/fpu/math-use-builtins.h | 11 +++++++++++ + 6 files changed, 37 insertions(+) + +diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h +index 64b4a4bb5b..e1c5df62e4 100644 +--- a/sysdeps/generic/math-use-builtins.h ++++ b/sysdeps/generic/math-use-builtins.h +@@ -31,4 +31,9 @@ + #define USE_RINTL_BUILTIN 0 + #define USE_RINTF128_BUILTIN 0 + ++#define USE_FLOOR_BUILTIN 0 ++#define USE_FLOORF_BUILTIN 0 ++#define USE_FLOORL_BUILTIN 0 ++#define USE_FLOORF128_BUILTIN 0 ++ + #endif /* math-use-builtins.h */ +diff --git a/sysdeps/ieee754/dbl-64/s_floor.c b/sysdeps/ieee754/dbl-64/s_floor.c +index b551a1aafa..693938b708 100644 +--- a/sysdeps/ieee754/dbl-64/s_floor.c ++++ b/sysdeps/ieee754/dbl-64/s_floor.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + /* + * floor(x) +@@ -45,6 +46,10 @@ + double + __floor (double x) + { ++#if USE_FLOOR_BUILTIN ++ return __builtin_floor (x); ++#else ++ /* Use generic implementation. */ + int64_t i0; + EXTRACT_WORDS64 (i0, x); + int32_t j0 = ((i0 >> 52) & 0x7ff) - 0x3ff; +@@ -72,6 +77,7 @@ __floor (double x) + else if (j0 == 0x400) + return x + x; /* inf or NaN */ + return x; ++#endif /* ! USE_FLOOR_BUILTIN */ + } + #ifndef __floor + libm_alias_double (__floor, floor) +diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h +index b872aefbfd..667030ab06 100644 +--- a/sysdeps/ieee754/float128/float128_private.h ++++ b/sysdeps/ieee754/float128/float128_private.h +@@ -143,6 +143,8 @@ + #define USE_NEARBYINTL_BUILTIN USE_NEARBYINTF128_BUILTIN + #undef USE_RINTL_BUILTIN + #define USE_RINTL_BUILTIN USE_RINTF128_BUILTIN ++#undef USE_FLOORL_BUILTIN ++#define USE_FLOORL_BUILTIN USE_FLOORF128_BUILTIN + + /* IEEE function renames. */ + #define __ieee754_acoshl __ieee754_acoshf128 +@@ -346,6 +348,7 @@ + #define __builtin_signbitl __builtin_signbit + #define __builtin_nearbyintl __builtin_nearbyintf128 + #define __builtin_rintl __builtin_rintf128 ++#define __builtin_floorl __builtin_floorf128 + + /* Get the constant suffix from bits/floatn-compat.h. */ + #define L(x) __f128 (x) +diff --git a/sysdeps/ieee754/flt-32/s_floorf.c b/sysdeps/ieee754/flt-32/s_floorf.c +index 12aed343a0..6d37ab90a1 100644 +--- a/sysdeps/ieee754/flt-32/s_floorf.c ++++ b/sysdeps/ieee754/flt-32/s_floorf.c +@@ -23,10 +23,15 @@ + #include + #include + #include ++#include + + float + __floorf(float x) + { ++#if USE_FLOORF_BUILTIN ++ return __builtin_floorf (x); ++#else ++ /* Use generic implementation. */ + int32_t i0,j0; + uint32_t i; + GET_FLOAT_WORD(i0,x); +@@ -49,6 +54,7 @@ __floorf(float x) + } + SET_FLOAT_WORD(x,i0); + return x; ++#endif /* ! USE_FLOORF_BUILTIN */ + } + #ifndef __floorf + libm_alias_float (__floor, floor) +diff --git a/sysdeps/ieee754/ldbl-128/s_floorl.c b/sysdeps/ieee754/ldbl-128/s_floorl.c +index f9c5e014f9..6143fe6ec5 100644 +--- a/sysdeps/ieee754/ldbl-128/s_floorl.c ++++ b/sysdeps/ieee754/ldbl-128/s_floorl.c +@@ -27,9 +27,14 @@ static char rcsid[] = "$NetBSD: $"; + #include + #include + #include ++#include + + _Float128 __floorl(_Float128 x) + { ++#if USE_FLOORL_BUILTIN ++ return __builtin_floorl (x); ++#else ++ /* Use generic implementation. */ + int64_t i0,i1,j0; + uint64_t i,j; + GET_LDOUBLE_WORDS64(i0,i1,x); +@@ -64,5 +69,6 @@ _Float128 __floorl(_Float128 x) + } + SET_LDOUBLE_WORDS64(x,i0,i1); + return x; ++#endif /* ! USE_FLOORL_BUILTIN */ + } + libm_alias_ldouble (__floor, floor) +diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h +index 8b702a6a90..c213c16c6f 100644 +--- a/sysdeps/s390/fpu/math-use-builtins.h ++++ b/sysdeps/s390/fpu/math-use-builtins.h +@@ -34,12 +34,18 @@ + # define USE_RINTF_BUILTIN 1 + # define USE_RINTL_BUILTIN 1 + ++# define USE_FLOOR_BUILTIN 1 ++# define USE_FLOORF_BUILTIN 1 ++# define USE_FLOORL_BUILTIN 1 ++ + # if __GNUC_PREREQ (8, 0) + # define USE_NEARBYINTF128_BUILTIN 1 + # define USE_RINTF128_BUILTIN 1 ++# define USE_FLOORF128_BUILTIN 1 + # else + # define USE_NEARBYINTF128_BUILTIN 0 + # define USE_RINTF128_BUILTIN 0 ++# define USE_FLOORF128_BUILTIN 0 + # endif + + #else +@@ -55,6 +61,11 @@ + # define USE_RINTL_BUILTIN 0 + # define USE_RINTF128_BUILTIN 0 + ++# define USE_FLOOR_BUILTIN 0 ++# define USE_FLOORF_BUILTIN 0 ++# define USE_FLOORL_BUILTIN 0 ++# define USE_FLOORF128_BUILTIN 0 ++ + #endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */ + + #endif /* math-use-builtins.h */ +-- +2.18.2 + diff --git a/glibc-rh1780204-10.patch b/glibc-rh1780204-10.patch new file mode 100755 index 0000000..3504976 --- /dev/null +++ b/glibc-rh1780204-10.patch @@ -0,0 +1,182 @@ +From 6c5e5f498cd004b3f42d97997898018df8f798a4 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:21 +0100 +Subject: [PATCH 10/28] Use GCC builtins for ceil functions if desired. + +This patch is using the corresponding GCC builtin for ceilf, ceil, +ceill and ceilf128 if the USE_FUNCTION_BUILTIN macros are defined to one +in math-use-builtins.h. + +This is the case for s390 if build with at least --march=z196 --mzarch. +Otherwise the generic implementation is used. The code of the generic +implementation is not changed. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit 62560ee84095274bab1050817f42e782df226a17) +--- + sysdeps/generic/math-use-builtins.h | 5 +++++ + sysdeps/ieee754/dbl-64/s_ceil.c | 6 ++++++ + sysdeps/ieee754/float128/float128_private.h | 3 +++ + sysdeps/ieee754/flt-32/s_ceilf.c | 7 ++++++- + sysdeps/ieee754/ldbl-128/s_ceill.c | 6 ++++++ + sysdeps/s390/fpu/math-use-builtins.h | 11 +++++++++++ + 6 files changed, 37 insertions(+), 1 deletion(-) + +diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h +index e1c5df62e4..076ec661b0 100644 +--- a/sysdeps/generic/math-use-builtins.h ++++ b/sysdeps/generic/math-use-builtins.h +@@ -36,4 +36,9 @@ + #define USE_FLOORL_BUILTIN 0 + #define USE_FLOORF128_BUILTIN 0 + ++#define USE_CEIL_BUILTIN 0 ++#define USE_CEILF_BUILTIN 0 ++#define USE_CEILL_BUILTIN 0 ++#define USE_CEILF128_BUILTIN 0 ++ + #endif /* math-use-builtins.h */ +diff --git a/sysdeps/ieee754/dbl-64/s_ceil.c b/sysdeps/ieee754/dbl-64/s_ceil.c +index 3becdfc515..ee4a3abc19 100644 +--- a/sysdeps/ieee754/dbl-64/s_ceil.c ++++ b/sysdeps/ieee754/dbl-64/s_ceil.c +@@ -20,10 +20,15 @@ + #include + #include + #include ++#include + + double + __ceil (double x) + { ++#if USE_CEIL_BUILTIN ++ return __builtin_ceil (x); ++#else ++ /* Use generic implementation. */ + int64_t i0, i; + int32_t j0; + EXTRACT_WORDS64 (i0, x); +@@ -57,6 +62,7 @@ __ceil (double x) + } + INSERT_WORDS64 (x, i0); + return x; ++#endif /* ! USE_CEIL_BUILTIN */ + } + #ifndef __ceil + libm_alias_double (__ceil, ceil) +diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h +index 667030ab06..19352ca26c 100644 +--- a/sysdeps/ieee754/float128/float128_private.h ++++ b/sysdeps/ieee754/float128/float128_private.h +@@ -145,6 +145,8 @@ + #define USE_RINTL_BUILTIN USE_RINTF128_BUILTIN + #undef USE_FLOORL_BUILTIN + #define USE_FLOORL_BUILTIN USE_FLOORF128_BUILTIN ++#undef USE_CEILL_BUILTIN ++#define USE_CEILL_BUILTIN USE_CEILF128_BUILTIN + + /* IEEE function renames. */ + #define __ieee754_acoshl __ieee754_acoshf128 +@@ -349,6 +351,7 @@ + #define __builtin_nearbyintl __builtin_nearbyintf128 + #define __builtin_rintl __builtin_rintf128 + #define __builtin_floorl __builtin_floorf128 ++#define __builtin_ceill __builtin_ceilf128 + + /* Get the constant suffix from bits/floatn-compat.h. */ + #define L(x) __f128 (x) +diff --git a/sysdeps/ieee754/flt-32/s_ceilf.c b/sysdeps/ieee754/flt-32/s_ceilf.c +index f289ec2341..6cab7bdd62 100644 +--- a/sysdeps/ieee754/flt-32/s_ceilf.c ++++ b/sysdeps/ieee754/flt-32/s_ceilf.c +@@ -16,11 +16,15 @@ + #include + #include + #include +- ++#include + + float + __ceilf(float x) + { ++#if USE_CEILF_BUILTIN ++ return __builtin_ceilf (x); ++#else ++ /* Use generic implementation. */ + int32_t i0,j0; + uint32_t i; + +@@ -43,6 +47,7 @@ __ceilf(float x) + } + SET_FLOAT_WORD(x,i0); + return x; ++#endif /* ! USE_CEILF_BUILTIN */ + } + #ifndef __ceilf + libm_alias_float (__ceil, ceil) +diff --git a/sysdeps/ieee754/ldbl-128/s_ceill.c b/sysdeps/ieee754/ldbl-128/s_ceill.c +index e6aba5f2af..d212d86179 100644 +--- a/sysdeps/ieee754/ldbl-128/s_ceill.c ++++ b/sysdeps/ieee754/ldbl-128/s_ceill.c +@@ -27,9 +27,14 @@ static char rcsid[] = "$NetBSD: $"; + #include + #include + #include ++#include + + _Float128 __ceill(_Float128 x) + { ++#if USE_CEILL_BUILTIN ++ return __builtin_ceill (x); ++#else ++ /* Use generic implementation. */ + int64_t i0,i1,j0; + uint64_t i,j; + GET_LDOUBLE_WORDS64(i0,i1,x); +@@ -63,5 +68,6 @@ _Float128 __ceill(_Float128 x) + } + SET_LDOUBLE_WORDS64(x,i0,i1); + return x; ++#endif /* ! USE_CEILL_BUILTIN */ + } + libm_alias_ldouble (__ceil, ceil) +diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h +index c213c16c6f..5435cbb65f 100644 +--- a/sysdeps/s390/fpu/math-use-builtins.h ++++ b/sysdeps/s390/fpu/math-use-builtins.h +@@ -38,14 +38,20 @@ + # define USE_FLOORF_BUILTIN 1 + # define USE_FLOORL_BUILTIN 1 + ++# define USE_CEIL_BUILTIN 1 ++# define USE_CEILF_BUILTIN 1 ++# define USE_CEILL_BUILTIN 1 ++ + # if __GNUC_PREREQ (8, 0) + # define USE_NEARBYINTF128_BUILTIN 1 + # define USE_RINTF128_BUILTIN 1 + # define USE_FLOORF128_BUILTIN 1 ++# define USE_CEILF128_BUILTIN 1 + # else + # define USE_NEARBYINTF128_BUILTIN 0 + # define USE_RINTF128_BUILTIN 0 + # define USE_FLOORF128_BUILTIN 0 ++# define USE_CEILF128_BUILTIN 0 + # endif + + #else +@@ -66,6 +72,11 @@ + # define USE_FLOORL_BUILTIN 0 + # define USE_FLOORF128_BUILTIN 0 + ++# define USE_CEIL_BUILTIN 0 ++# define USE_CEILF_BUILTIN 0 ++# define USE_CEILL_BUILTIN 0 ++# define USE_CEILF128_BUILTIN 0 ++ + #endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */ + + #endif /* math-use-builtins.h */ +-- +2.18.2 + diff --git a/glibc-rh1780204-11.patch b/glibc-rh1780204-11.patch new file mode 100755 index 0000000..533d478 --- /dev/null +++ b/glibc-rh1780204-11.patch @@ -0,0 +1,187 @@ +From abc72a0694c1c3d08354170da343eead8d9afcc1 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:22 +0100 +Subject: [PATCH 11/28] Use GCC builtins for trunc functions if desired. + +This patch is using the corresponding GCC builtin for truncf, trunc, +truncl and truncf128 if the USE_FUNCTION_BUILTIN macros are defined to one +in math-use-builtins.h. + +This is the case for s390 if build with at least --march=z196 --mzarch. +Otherwise the generic implementation is used. The code of the generic +implementation is not changed. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit 1ac9c1cf87216bf9f8ac4f7c9754d025d9f2c4ae) +--- + sysdeps/generic/math-use-builtins.h | 5 +++++ + sysdeps/ieee754/dbl-64/s_trunc.c | 6 ++++++ + sysdeps/ieee754/float128/float128_private.h | 3 +++ + sysdeps/ieee754/flt-32/s_truncf.c | 6 ++++++ + sysdeps/ieee754/ldbl-128/s_truncl.c | 6 ++++++ + sysdeps/s390/fpu/math-use-builtins.h | 11 +++++++++++ + 6 files changed, 37 insertions(+) + +diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h +index 076ec661b0..ab379f45ba 100644 +--- a/sysdeps/generic/math-use-builtins.h ++++ b/sysdeps/generic/math-use-builtins.h +@@ -41,4 +41,9 @@ + #define USE_CEILL_BUILTIN 0 + #define USE_CEILF128_BUILTIN 0 + ++#define USE_TRUNC_BUILTIN 0 ++#define USE_TRUNCF_BUILTIN 0 ++#define USE_TRUNCL_BUILTIN 0 ++#define USE_TRUNCF128_BUILTIN 0 ++ + #endif /* math-use-builtins.h */ +diff --git a/sysdeps/ieee754/dbl-64/s_trunc.c b/sysdeps/ieee754/dbl-64/s_trunc.c +index 38bb33d337..708169c727 100644 +--- a/sysdeps/ieee754/dbl-64/s_trunc.c ++++ b/sysdeps/ieee754/dbl-64/s_trunc.c +@@ -21,11 +21,16 @@ + + #include + #include ++#include + + + double + __trunc (double x) + { ++#if USE_TRUNC_BUILTIN ++ return __builtin_trunc (x); ++#else ++ /* Use generic implementation. */ + int64_t i0, j0; + int64_t sx; + +@@ -48,6 +53,7 @@ __trunc (double x) + } + + return x; ++#endif /* ! USE_TRUNC_BUILTIN */ + } + #ifndef __trunc + libm_alias_double (__trunc, trunc) +diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h +index 19352ca26c..e248600ec2 100644 +--- a/sysdeps/ieee754/float128/float128_private.h ++++ b/sysdeps/ieee754/float128/float128_private.h +@@ -147,6 +147,8 @@ + #define USE_FLOORL_BUILTIN USE_FLOORF128_BUILTIN + #undef USE_CEILL_BUILTIN + #define USE_CEILL_BUILTIN USE_CEILF128_BUILTIN ++#undef USE_TRUNCL_BUILTIN ++#define USE_TRUNCL_BUILTIN USE_TRUNCF128_BUILTIN + + /* IEEE function renames. */ + #define __ieee754_acoshl __ieee754_acoshf128 +@@ -352,6 +354,7 @@ + #define __builtin_rintl __builtin_rintf128 + #define __builtin_floorl __builtin_floorf128 + #define __builtin_ceill __builtin_ceilf128 ++#define __builtin_truncl __builtin_truncf128 + + /* Get the constant suffix from bits/floatn-compat.h. */ + #define L(x) __f128 (x) +diff --git a/sysdeps/ieee754/flt-32/s_truncf.c b/sysdeps/ieee754/flt-32/s_truncf.c +index 2e1464aeac..71491e5175 100644 +--- a/sysdeps/ieee754/flt-32/s_truncf.c ++++ b/sysdeps/ieee754/flt-32/s_truncf.c +@@ -21,11 +21,16 @@ + + #include + #include ++#include + + + float + __truncf (float x) + { ++#if USE_TRUNCF_BUILTIN ++ return __builtin_truncf (x); ++#else ++ /* Use generic implementation. */ + int32_t i0, j0; + int sx; + +@@ -48,6 +53,7 @@ __truncf (float x) + } + + return x; ++#endif /* ! USE_TRUNCF_BUILTIN */ + } + #ifndef __truncf + libm_alias_float (__trunc, trunc) +diff --git a/sysdeps/ieee754/ldbl-128/s_truncl.c b/sysdeps/ieee754/ldbl-128/s_truncl.c +index f858ede3d2..aa49daaf85 100644 +--- a/sysdeps/ieee754/ldbl-128/s_truncl.c ++++ b/sysdeps/ieee754/ldbl-128/s_truncl.c +@@ -22,11 +22,16 @@ + + #include + #include ++#include + + + _Float128 + __truncl (_Float128 x) + { ++#if USE_TRUNCL_BUILTIN ++ return __builtin_truncl (x); ++#else ++ /* Use generic implementation. */ + int32_t j0; + uint64_t i0, i1, sx; + +@@ -53,5 +58,6 @@ __truncl (_Float128 x) + } + + return x; ++#endif /* ! USE_TRUNCL_BUILTIN */ + } + libm_alias_ldouble (__trunc, trunc) +diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h +index 5435cbb65f..a39715c612 100644 +--- a/sysdeps/s390/fpu/math-use-builtins.h ++++ b/sysdeps/s390/fpu/math-use-builtins.h +@@ -42,16 +42,22 @@ + # define USE_CEILF_BUILTIN 1 + # define USE_CEILL_BUILTIN 1 + ++# define USE_TRUNC_BUILTIN 1 ++# define USE_TRUNCF_BUILTIN 1 ++# define USE_TRUNCL_BUILTIN 1 ++ + # if __GNUC_PREREQ (8, 0) + # define USE_NEARBYINTF128_BUILTIN 1 + # define USE_RINTF128_BUILTIN 1 + # define USE_FLOORF128_BUILTIN 1 + # define USE_CEILF128_BUILTIN 1 ++# define USE_TRUNCF128_BUILTIN 1 + # else + # define USE_NEARBYINTF128_BUILTIN 0 + # define USE_RINTF128_BUILTIN 0 + # define USE_FLOORF128_BUILTIN 0 + # define USE_CEILF128_BUILTIN 0 ++# define USE_TRUNCF128_BUILTIN 0 + # endif + + #else +@@ -77,6 +83,11 @@ + # define USE_CEILL_BUILTIN 0 + # define USE_CEILF128_BUILTIN 0 + ++# define USE_TRUNC_BUILTIN 0 ++# define USE_TRUNCF_BUILTIN 0 ++# define USE_TRUNCL_BUILTIN 0 ++# define USE_TRUNCF128_BUILTIN 0 ++ + #endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */ + + #endif /* math-use-builtins.h */ +-- +2.18.2 + diff --git a/glibc-rh1780204-12.patch b/glibc-rh1780204-12.patch new file mode 100755 index 0000000..3b95873 --- /dev/null +++ b/glibc-rh1780204-12.patch @@ -0,0 +1,187 @@ +From f49dd4cc4e295803e517190d1798bd84561d56f4 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:24 +0100 +Subject: [PATCH 12/28] Use GCC builtins for round functions if desired. + +This patch is using the corresponding GCC builtin for roundf, round, +roundl and roundf128 if the USE_FUNCTION_BUILTIN macros are defined to one +in math-use-builtins.h. + +This is the case for s390 if build with at least --march=z196 --mzarch. +Otherwise the generic implementation is used. The code of the generic +implementation is not changed. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit f82996f8159981619ac7ed8a4c1838c2ad72ab61) +--- + sysdeps/generic/math-use-builtins.h | 5 +++++ + sysdeps/ieee754/dbl-64/s_round.c | 6 ++++++ + sysdeps/ieee754/float128/float128_private.h | 3 +++ + sysdeps/ieee754/flt-32/s_roundf.c | 6 ++++++ + sysdeps/ieee754/ldbl-128/s_roundl.c | 6 ++++++ + sysdeps/s390/fpu/math-use-builtins.h | 11 +++++++++++ + 6 files changed, 37 insertions(+) + +diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h +index ab379f45ba..34ca438a8c 100644 +--- a/sysdeps/generic/math-use-builtins.h ++++ b/sysdeps/generic/math-use-builtins.h +@@ -46,4 +46,9 @@ + #define USE_TRUNCL_BUILTIN 0 + #define USE_TRUNCF128_BUILTIN 0 + ++#define USE_ROUND_BUILTIN 0 ++#define USE_ROUNDF_BUILTIN 0 ++#define USE_ROUNDL_BUILTIN 0 ++#define USE_ROUNDF128_BUILTIN 0 ++ + #endif /* math-use-builtins.h */ +diff --git a/sysdeps/ieee754/dbl-64/s_round.c b/sysdeps/ieee754/dbl-64/s_round.c +index bf9922edca..1f8482adf8 100644 +--- a/sysdeps/ieee754/dbl-64/s_round.c ++++ b/sysdeps/ieee754/dbl-64/s_round.c +@@ -22,11 +22,16 @@ + #include + #include + #include ++#include + + + double + __round (double x) + { ++#if USE_ROUND_BUILTIN ++ return __builtin_round (x); ++#else ++ /* Use generic implementation. */ + int64_t i0, j0; + + EXTRACT_WORDS64 (i0, x); +@@ -61,5 +66,6 @@ __round (double x) + + INSERT_WORDS64 (x, i0); + return x; ++#endif /* ! USE_ROUND_BUILTIN */ + } + libm_alias_double (__round, round) +diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h +index e248600ec2..3297a71e44 100644 +--- a/sysdeps/ieee754/float128/float128_private.h ++++ b/sysdeps/ieee754/float128/float128_private.h +@@ -149,6 +149,8 @@ + #define USE_CEILL_BUILTIN USE_CEILF128_BUILTIN + #undef USE_TRUNCL_BUILTIN + #define USE_TRUNCL_BUILTIN USE_TRUNCF128_BUILTIN ++#undef USE_ROUNDL_BUILTIN ++#define USE_ROUNDL_BUILTIN USE_ROUNDF128_BUILTIN + + /* IEEE function renames. */ + #define __ieee754_acoshl __ieee754_acoshf128 +@@ -355,6 +357,7 @@ + #define __builtin_floorl __builtin_floorf128 + #define __builtin_ceill __builtin_ceilf128 + #define __builtin_truncl __builtin_truncf128 ++#define __builtin_roundl __builtin_roundf128 + + /* Get the constant suffix from bits/floatn-compat.h. */ + #define L(x) __f128 (x) +diff --git a/sysdeps/ieee754/flt-32/s_roundf.c b/sysdeps/ieee754/flt-32/s_roundf.c +index 7c95125d9c..6fdfbbbade 100644 +--- a/sysdeps/ieee754/flt-32/s_roundf.c ++++ b/sysdeps/ieee754/flt-32/s_roundf.c +@@ -21,11 +21,16 @@ + + #include + #include ++#include + + + float + __roundf (float x) + { ++#if USE_ROUNDF_BUILTIN ++ return __builtin_roundf (x); ++#else ++ /* Use generic implementation. */ + int32_t i0, j0; + + GET_FLOAT_WORD (i0, x); +@@ -60,5 +65,6 @@ __roundf (float x) + + SET_FLOAT_WORD (x, i0); + return x; ++#endif /* ! USE_ROUNDF_BUILTIN */ + } + libm_alias_float (__round, round) +diff --git a/sysdeps/ieee754/ldbl-128/s_roundl.c b/sysdeps/ieee754/ldbl-128/s_roundl.c +index 22789cedf3..564f8ac1b8 100644 +--- a/sysdeps/ieee754/ldbl-128/s_roundl.c ++++ b/sysdeps/ieee754/ldbl-128/s_roundl.c +@@ -22,11 +22,16 @@ + + #include + #include ++#include + + + _Float128 + __roundl (_Float128 x) + { ++#if USE_ROUNDL_BUILTIN ++ return __builtin_roundl (x); ++#else ++ /* Use generic implementation. */ + int32_t j0; + uint64_t i1, i0; + +@@ -77,5 +82,6 @@ __roundl (_Float128 x) + + SET_LDOUBLE_WORDS64 (x, i0, i1); + return x; ++#endif /* ! USE_ROUNDL_BUILTIN */ + } + libm_alias_ldouble (__round, round) +diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h +index a39715c612..51cb9f91ab 100644 +--- a/sysdeps/s390/fpu/math-use-builtins.h ++++ b/sysdeps/s390/fpu/math-use-builtins.h +@@ -46,18 +46,24 @@ + # define USE_TRUNCF_BUILTIN 1 + # define USE_TRUNCL_BUILTIN 1 + ++# define USE_ROUND_BUILTIN 1 ++# define USE_ROUNDF_BUILTIN 1 ++# define USE_ROUNDL_BUILTIN 1 ++ + # if __GNUC_PREREQ (8, 0) + # define USE_NEARBYINTF128_BUILTIN 1 + # define USE_RINTF128_BUILTIN 1 + # define USE_FLOORF128_BUILTIN 1 + # define USE_CEILF128_BUILTIN 1 + # define USE_TRUNCF128_BUILTIN 1 ++# define USE_ROUNDF128_BUILTIN 1 + # else + # define USE_NEARBYINTF128_BUILTIN 0 + # define USE_RINTF128_BUILTIN 0 + # define USE_FLOORF128_BUILTIN 0 + # define USE_CEILF128_BUILTIN 0 + # define USE_TRUNCF128_BUILTIN 0 ++# define USE_ROUNDF128_BUILTIN 0 + # endif + + #else +@@ -88,6 +94,11 @@ + # define USE_TRUNCL_BUILTIN 0 + # define USE_TRUNCF128_BUILTIN 0 + ++# define USE_ROUND_BUILTIN 0 ++# define USE_ROUNDF_BUILTIN 0 ++# define USE_ROUNDL_BUILTIN 0 ++# define USE_ROUNDF128_BUILTIN 0 ++ + #endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */ + + #endif /* math-use-builtins.h */ +-- +2.18.2 + diff --git a/glibc-rh1780204-13.patch b/glibc-rh1780204-13.patch new file mode 100755 index 0000000..72ed332 --- /dev/null +++ b/glibc-rh1780204-13.patch @@ -0,0 +1,177 @@ +From e93b17fad37a61f7ae9a663c617926b0f510921a Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:24 +0100 +Subject: [PATCH 13/28] Use GCC builtins for copysign functions if desired. + +This patch is always using the corresponding GCC builtin for copysignf, copysign, +and is using the builtin for copysignl, copysignf128 if the USE_FUNCTION_BUILTIN +macros are defined to one in math-use-builtins.h. + +Altough the long double version is enabled by default we still need +the macro and the alternative implementation as the _Float128 version +of the builtin is not available with all supported GCC versions. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit f818afdd3b29d7eef2010448457c9f5c16e684cd) +--- + sysdeps/generic/math-use-builtins.h | 9 +++++++++ + sysdeps/ieee754/dbl-64/s_copysign.c | 9 ++------- + sysdeps/ieee754/float128/float128_private.h | 3 +++ + sysdeps/ieee754/flt-32/s_copysignf.c | 12 ++++-------- + sysdeps/ieee754/ldbl-128/s_copysignl.c | 6 ++++++ + sysdeps/s390/fpu/math-use-builtins.h | 7 +++++++ + 6 files changed, 31 insertions(+), 15 deletions(-) + +diff --git a/sysdeps/generic/math-use-builtins.h b/sysdeps/generic/math-use-builtins.h +index 34ca438a8c..770b54ce61 100644 +--- a/sysdeps/generic/math-use-builtins.h ++++ b/sysdeps/generic/math-use-builtins.h +@@ -19,6 +19,8 @@ + #ifndef MATH_USE_BUILTINS_H + #define MATH_USE_BUILTINS_H 1 + ++#include /* For __GNUC_PREREQ. */ ++ + /* Define these macros to 1 to use __builtin_xyz instead of the + generic implementation. */ + #define USE_NEARBYINT_BUILTIN 0 +@@ -51,4 +53,11 @@ + #define USE_ROUNDL_BUILTIN 0 + #define USE_ROUNDF128_BUILTIN 0 + ++#define USE_COPYSIGNL_BUILTIN 1 ++#if __GNUC_PREREQ (7, 0) ++# define USE_COPYSIGNF128_BUILTIN 1 ++#else ++# define USE_COPYSIGNF128_BUILTIN 0 ++#endif ++ + #endif /* math-use-builtins.h */ +diff --git a/sysdeps/ieee754/dbl-64/s_copysign.c b/sysdeps/ieee754/dbl-64/s_copysign.c +index ab81d732ab..b95f1575d9 100644 +--- a/sysdeps/ieee754/dbl-64/s_copysign.c ++++ b/sysdeps/ieee754/dbl-64/s_copysign.c +@@ -10,7 +10,7 @@ + * ==================================================== + */ + +-#if defined(LIBM_SCCS) && !defined(lint) ++#if defined (LIBM_SCCS) && ! defined (lint) + static char rcsid[] = "$NetBSD: s_copysign.c,v 1.8 1995/05/10 20:46:57 jtc Exp $"; + #endif + +@@ -21,16 +21,11 @@ static char rcsid[] = "$NetBSD: s_copysign.c,v 1.8 1995/05/10 20:46:57 jtc Exp $ + */ + + #include +-#include + #include + + double + __copysign (double x, double y) + { +- uint32_t hx, hy; +- GET_HIGH_WORD (hx, x); +- GET_HIGH_WORD (hy, y); +- SET_HIGH_WORD (x, (hx & 0x7fffffff) | (hy & 0x80000000)); +- return x; ++ return __builtin_copysign (x, y); + } + libm_alias_double (__copysign, copysign) +diff --git a/sysdeps/ieee754/float128/float128_private.h b/sysdeps/ieee754/float128/float128_private.h +index 3297a71e44..077df0e09f 100644 +--- a/sysdeps/ieee754/float128/float128_private.h ++++ b/sysdeps/ieee754/float128/float128_private.h +@@ -151,6 +151,8 @@ + #define USE_TRUNCL_BUILTIN USE_TRUNCF128_BUILTIN + #undef USE_ROUNDL_BUILTIN + #define USE_ROUNDL_BUILTIN USE_ROUNDF128_BUILTIN ++#undef USE_COPYSIGNL_BUILTIN ++#define USE_COPYSIGNL_BUILTIN USE_COPYSIGNF128_BUILTIN + + /* IEEE function renames. */ + #define __ieee754_acoshl __ieee754_acoshf128 +@@ -358,6 +360,7 @@ + #define __builtin_ceill __builtin_ceilf128 + #define __builtin_truncl __builtin_truncf128 + #define __builtin_roundl __builtin_roundf128 ++#define __builtin_copysignl __builtin_copysignf128 + + /* Get the constant suffix from bits/floatn-compat.h. */ + #define L(x) __f128 (x) +diff --git a/sysdeps/ieee754/flt-32/s_copysignf.c b/sysdeps/ieee754/flt-32/s_copysignf.c +index 3c4ac7ce68..0247abd152 100644 +--- a/sysdeps/ieee754/flt-32/s_copysignf.c ++++ b/sysdeps/ieee754/flt-32/s_copysignf.c +@@ -13,7 +13,7 @@ + * ==================================================== + */ + +-#if defined(LIBM_SCCS) && !defined(lint) ++#if defined (LIBM_SCCS) && ! defined (lint) + static char rcsid[] = "$NetBSD: s_copysignf.c,v 1.4 1995/05/10 20:46:59 jtc Exp $"; + #endif + +@@ -24,15 +24,11 @@ static char rcsid[] = "$NetBSD: s_copysignf.c,v 1.4 1995/05/10 20:46:59 jtc Exp + */ + + #include +-#include + #include + +-float __copysignf(float x, float y) ++float ++__copysignf (float x, float y) + { +- uint32_t ix,iy; +- GET_FLOAT_WORD(ix,x); +- GET_FLOAT_WORD(iy,y); +- SET_FLOAT_WORD(x,(ix&0x7fffffff)|(iy&0x80000000)); +- return x; ++ return __builtin_copysignf (x, y); + } + libm_alias_float (__copysign, copysign) +diff --git a/sysdeps/ieee754/ldbl-128/s_copysignl.c b/sysdeps/ieee754/ldbl-128/s_copysignl.c +index d23e0f72ea..4cae8612dc 100644 +--- a/sysdeps/ieee754/ldbl-128/s_copysignl.c ++++ b/sysdeps/ieee754/ldbl-128/s_copysignl.c +@@ -26,14 +26,20 @@ static char rcsid[] = "$NetBSD: $"; + #include + #include + #include ++#include + + _Float128 __copysignl(_Float128 x, _Float128 y) + { ++#if USE_COPYSIGNL_BUILTIN ++ return __builtin_copysignl (x, y); ++#else ++ /* Use generic implementation. */ + uint64_t hx,hy; + GET_LDOUBLE_MSW64(hx,x); + GET_LDOUBLE_MSW64(hy,y); + SET_LDOUBLE_MSW64(x,(hx&0x7fffffffffffffffULL) + |(hy&0x8000000000000000ULL)); + return x; ++#endif /* ! USE_COPYSIGNL_BUILTIN */ + } + libm_alias_ldouble (__copysign, copysign) +diff --git a/sysdeps/s390/fpu/math-use-builtins.h b/sysdeps/s390/fpu/math-use-builtins.h +index 51cb9f91ab..4c4aad2ab5 100644 +--- a/sysdeps/s390/fpu/math-use-builtins.h ++++ b/sysdeps/s390/fpu/math-use-builtins.h +@@ -101,4 +101,11 @@ + + #endif /* ! HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT */ + ++#define USE_COPYSIGNL_BUILTIN 1 ++#if __GNUC_PREREQ (7, 0) ++# define USE_COPYSIGNF128_BUILTIN 1 ++#else ++# define USE_COPYSIGNF128_BUILTIN 0 ++#endif ++ + #endif /* math-use-builtins.h */ +-- +2.18.2 + diff --git a/glibc-rh1780204-14.patch b/glibc-rh1780204-14.patch new file mode 100755 index 0000000..6e58c11 --- /dev/null +++ b/glibc-rh1780204-14.patch @@ -0,0 +1,180 @@ +From bd7c710d3b234a8d3bd77aae358bd7f7a6ce576d Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:25 +0100 +Subject: [PATCH 14/28] Adjust s_nearbyintf.c and s_nearbyintl.c regarding code + style. + +This patch just adjusts the generic implementation regarding code style. +No functional change. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit 6a3866dae98cccc8cd7a0a4c1fb409dba9192a83) +--- + sysdeps/ieee754/flt-32/s_nearbyintf.c | 60 ++++++++++++----------- + sysdeps/ieee754/ldbl-128/s_nearbyintl.c | 63 ++++++++++++++----------- + 2 files changed, 68 insertions(+), 55 deletions(-) + +diff --git a/sysdeps/ieee754/flt-32/s_nearbyintf.c b/sysdeps/ieee754/flt-32/s_nearbyintf.c +index 438dcae8cc..5969e3e5b8 100644 +--- a/sysdeps/ieee754/flt-32/s_nearbyintf.c ++++ b/sysdeps/ieee754/flt-32/s_nearbyintf.c +@@ -23,7 +23,7 @@ + #include + + float +-__nearbyintf(float x) ++__nearbyintf (float x) + { + #if USE_NEARBYINTF_BUILTIN + return __builtin_nearbyintf (x); +@@ -34,33 +34,39 @@ __nearbyintf(float x) + 8.3886080000e+06, /* 0x4b000000 */ + -8.3886080000e+06, /* 0xcb000000 */ + }; +- fenv_t env; +- int32_t i0,j0,sx; +- float w,t; +- GET_FLOAT_WORD(i0,x); +- sx = (i0>>31)&1; +- j0 = ((i0>>23)&0xff)-0x7f; +- if(j0<23) { +- if(j0<0) { +- libc_feholdexceptf (&env); +- w = TWO23[sx] + math_opt_barrier (x); +- t = w-TWO23[sx]; +- math_force_eval (t); +- libc_fesetenvf (&env); +- GET_FLOAT_WORD(i0,t); +- SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31)); +- return t; +- } +- } else { +- if(__builtin_expect(j0==0x80, 0)) return x+x; /* inf or NaN */ +- else return x; /* x is integral */ ++ fenv_t env; ++ int32_t i0, j0, sx; ++ float w, t; ++ GET_FLOAT_WORD (i0, x); ++ sx = (i0 >> 31) & 1; ++ j0 = ((i0 >> 23) & 0xff) - 0x7f; ++ if (j0 < 23) ++ { ++ if (j0 < 0) ++ { ++ libc_feholdexceptf (&env); ++ w = TWO23[sx] + math_opt_barrier (x); ++ t = w - TWO23[sx]; ++ math_force_eval (t); ++ libc_fesetenvf (&env); ++ GET_FLOAT_WORD (i0, t); ++ SET_FLOAT_WORD (t, (i0 & 0x7fffffff) | (sx << 31)); ++ return t; + } +- libc_feholdexceptf (&env); +- w = TWO23[sx] + math_opt_barrier (x); +- t = w-TWO23[sx]; +- math_force_eval (t); +- libc_fesetenvf (&env); +- return t; ++ } ++ else ++ { ++ if (__glibc_unlikely (j0 == 0x80)) ++ return x + x; /* inf or NaN */ ++ else ++ return x; /* x is integral */ ++ } ++ libc_feholdexceptf (&env); ++ w = TWO23[sx] + math_opt_barrier (x); ++ t = w - TWO23[sx]; ++ math_force_eval (t); ++ libc_fesetenvf (&env); ++ return t; + #endif /* ! USE_NEARBYINT_BUILTIN */ + } + libm_alias_float (__nearbyint, nearbyint) +diff --git a/sysdeps/ieee754/ldbl-128/s_nearbyintl.c b/sysdeps/ieee754/ldbl-128/s_nearbyintl.c +index a4ad8e82e5..8d26786f78 100644 +--- a/sysdeps/ieee754/ldbl-128/s_nearbyintl.c ++++ b/sysdeps/ieee754/ldbl-128/s_nearbyintl.c +@@ -30,7 +30,8 @@ + #include + #include + +-_Float128 __nearbyintl(_Float128 x) ++_Float128 ++__nearbyintl (_Float128 x) + { + #if USE_NEARBYINTL_BUILTIN + return __builtin_nearbyintl (x); +@@ -41,34 +42,40 @@ _Float128 __nearbyintl(_Float128 x) + L(5.19229685853482762853049632922009600E+33), /* 0x406F000000000000, 0 */ + L(-5.19229685853482762853049632922009600E+33) /* 0xC06F000000000000, 0 */ + }; +- fenv_t env; +- int64_t i0,j0,sx; +- uint64_t i1 __attribute__ ((unused)); +- _Float128 w,t; +- GET_LDOUBLE_WORDS64(i0,i1,x); +- sx = (((uint64_t)i0)>>63); +- j0 = ((i0>>48)&0x7fff)-0x3fff; +- if(j0<112) { +- if(j0<0) { +- feholdexcept (&env); +- w = TWO112[sx] + math_opt_barrier (x); +- t = w-TWO112[sx]; +- math_force_eval (t); +- fesetenv (&env); +- GET_LDOUBLE_MSW64(i0,t); +- SET_LDOUBLE_MSW64(t,(i0&0x7fffffffffffffffLL)|(sx<<63)); +- return t; +- } +- } else { +- if(j0==0x4000) return x+x; /* inf or NaN */ +- else return x; /* x is integral */ ++ fenv_t env; ++ int64_t i0, j0, sx; ++ uint64_t i1 __attribute__ ((unused)); ++ _Float128 w, t; ++ GET_LDOUBLE_WORDS64 (i0, i1, x); ++ sx = (((uint64_t) i0) >> 63); ++ j0 = ((i0 >> 48) & 0x7fff) - 0x3fff; ++ if (j0 < 112) ++ { ++ if (j0 < 0) ++ { ++ feholdexcept (&env); ++ w = TWO112[sx] + math_opt_barrier (x); ++ t = w - TWO112[sx]; ++ math_force_eval (t); ++ fesetenv (&env); ++ GET_LDOUBLE_MSW64 (i0, t); ++ SET_LDOUBLE_MSW64 (t, (i0 & 0x7fffffffffffffffLL) | (sx << 63)); ++ return t; + } +- feholdexcept (&env); +- w = TWO112[sx] + math_opt_barrier (x); +- t = w-TWO112[sx]; +- math_force_eval (t); +- fesetenv (&env); +- return t; ++ } ++ else ++ { ++ if (j0 == 0x4000) ++ return x + x; /* inf or NaN */ ++ else ++ return x; /* x is integral */ ++ } ++ feholdexcept (&env); ++ w = TWO112[sx] + math_opt_barrier (x); ++ t = w - TWO112[sx]; ++ math_force_eval (t); ++ fesetenv (&env); ++ return t; + #endif /* ! USE_NEARBYINTL_BUILTIN */ + } + libm_alias_ldouble (__nearbyint, nearbyint) +-- +2.18.2 + diff --git a/glibc-rh1780204-15.patch b/glibc-rh1780204-15.patch new file mode 100755 index 0000000..47a5661 --- /dev/null +++ b/glibc-rh1780204-15.patch @@ -0,0 +1,156 @@ +From ce4f299c02be0a06130b70a62aa79b77385f4326 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:26 +0100 +Subject: [PATCH 15/28] Adjust s_rintf.c and s_rintl.c regarding code style. + +This patch just adjusts the generic implementation regarding code style. +No functional change. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit 99b39a83e72f4b58e2f284fd844622df26b3b5fe) +--- + sysdeps/ieee754/flt-32/s_rintf.c | 44 +++++++++++++++------------ + sysdeps/ieee754/ldbl-128/s_rintl.c | 49 +++++++++++++++++------------- + 2 files changed, 53 insertions(+), 40 deletions(-) + +diff --git a/sysdeps/ieee754/flt-32/s_rintf.c b/sysdeps/ieee754/flt-32/s_rintf.c +index a266b1999e..3463a044e1 100644 +--- a/sysdeps/ieee754/flt-32/s_rintf.c ++++ b/sysdeps/ieee754/flt-32/s_rintf.c +@@ -19,7 +19,7 @@ + #include + + float +-__rintf(float x) ++__rintf (float x) + { + #if USE_RINTF_BUILTIN + return __builtin_rintf (x); +@@ -30,25 +30,31 @@ __rintf(float x) + 8.3886080000e+06, /* 0x4b000000 */ + -8.3886080000e+06, /* 0xcb000000 */ + }; +- int32_t i0,j0,sx; +- float w,t; +- GET_FLOAT_WORD(i0,x); +- sx = (i0>>31)&1; +- j0 = ((i0>>23)&0xff)-0x7f; +- if(j0<23) { +- if(j0<0) { +- w = TWO23[sx]+x; +- t = w-TWO23[sx]; +- GET_FLOAT_WORD(i0,t); +- SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31)); +- return t; +- } +- } else { +- if(j0==0x80) return x+x; /* inf or NaN */ +- else return x; /* x is integral */ ++ int32_t i0, j0, sx; ++ float w, t; ++ GET_FLOAT_WORD (i0, x); ++ sx = (i0 >> 31) & 1; ++ j0 = ((i0 >> 23) & 0xff) - 0x7f; ++ if (j0 < 23) ++ { ++ if(j0 < 0) ++ { ++ w = TWO23[sx] + x; ++ t = w - TWO23[sx]; ++ GET_FLOAT_WORD (i0, t); ++ SET_FLOAT_WORD (t, (i0 & 0x7fffffff) | (sx << 31)); ++ return t; + } +- w = TWO23[sx]+x; +- return w-TWO23[sx]; ++ } ++ else ++ { ++ if (j0 == 0x80) ++ return x + x; /* inf or NaN */ ++ else ++ return x; /* x is integral */ ++ } ++ w = TWO23[sx] + x; ++ return w - TWO23[sx]; + #endif /* ! USE_RINTF_BUILTIN */ + } + #ifndef __rintf +diff --git a/sysdeps/ieee754/ldbl-128/s_rintl.c b/sysdeps/ieee754/ldbl-128/s_rintl.c +index f060503066..260f3aa9b9 100644 +--- a/sysdeps/ieee754/ldbl-128/s_rintl.c ++++ b/sysdeps/ieee754/ldbl-128/s_rintl.c +@@ -13,7 +13,7 @@ + * ==================================================== + */ + +-#if defined(LIBM_SCCS) && !defined(lint) ++#if defined (LIBM_SCCS) && ! defined (lint) + static char rcsid[] = "$NetBSD: $"; + #endif + +@@ -32,7 +32,8 @@ static char rcsid[] = "$NetBSD: $"; + #include + #include + +-_Float128 __rintl(_Float128 x) ++_Float128 ++__rintl (_Float128 x) + { + #if USE_RINTL_BUILTIN + return __builtin_rintl (x); +@@ -43,26 +44,32 @@ _Float128 __rintl(_Float128 x) + 5.19229685853482762853049632922009600E+33L, /* 0x406F000000000000, 0 */ + -5.19229685853482762853049632922009600E+33L /* 0xC06F000000000000, 0 */ + }; +- int64_t i0,j0,sx; +- uint64_t i1 __attribute__ ((unused)); +- _Float128 w,t; +- GET_LDOUBLE_WORDS64(i0,i1,x); +- sx = (((uint64_t)i0)>>63); +- j0 = ((i0>>48)&0x7fff)-0x3fff; +- if(j0<112) { +- if(j0<0) { +- w = TWO112[sx]+x; +- t = w-TWO112[sx]; +- GET_LDOUBLE_MSW64(i0,t); +- SET_LDOUBLE_MSW64(t,(i0&0x7fffffffffffffffLL)|(sx<<63)); +- return t; +- } +- } else { +- if(j0==0x4000) return x+x; /* inf or NaN */ +- else return x; /* x is integral */ ++ int64_t i0, j0, sx; ++ uint64_t i1 __attribute__ ((unused)); ++ _Float128 w, t; ++ GET_LDOUBLE_WORDS64 (i0, i1, x); ++ sx = (((uint64_t) i0) >> 63); ++ j0 = ((i0 >> 48) & 0x7fff) - 0x3fff; ++ if (j0 < 112) ++ { ++ if (j0 < 0) ++ { ++ w = TWO112[sx] + x; ++ t = w - TWO112[sx]; ++ GET_LDOUBLE_MSW64 (i0, t); ++ SET_LDOUBLE_MSW64 (t, (i0 & 0x7fffffffffffffffLL) | (sx << 63)); ++ return t; + } +- w = TWO112[sx]+x; +- return w-TWO112[sx]; ++ } ++ else ++ { ++ if (j0 == 0x4000) ++ return x + x; /* inf or NaN */ ++ else ++ return x; /* x is integral */ ++ } ++ w = TWO112[sx] + x; ++ return w - TWO112[sx]; + #endif /* ! USE_RINTL_BUILTIN */ + } + libm_alias_ldouble (__rint, rint) +-- +2.18.2 + diff --git a/glibc-rh1780204-16.patch b/glibc-rh1780204-16.patch new file mode 100755 index 0000000..47d84fd --- /dev/null +++ b/glibc-rh1780204-16.patch @@ -0,0 +1,198 @@ +From e96879644e4a9f4304725d1da9cc76b0c685b0b8 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:26 +0100 +Subject: [PATCH 16/28] Adjust s_floorf.c and s_floorl.c regarding code style. + +This patch just adjusts the generic implementation regarding code style. +No functional change. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit d3a0409ab615e133ff3ea27b492de75a607cff4a) +--- + sysdeps/ieee754/flt-32/s_floorf.c | 55 +++++++++++------- + sysdeps/ieee754/ldbl-128/s_floorl.c | 89 ++++++++++++++++++----------- + 2 files changed, 90 insertions(+), 54 deletions(-) + +diff --git a/sysdeps/ieee754/flt-32/s_floorf.c b/sysdeps/ieee754/flt-32/s_floorf.c +index 6d37ab90a1..c45816e3bd 100644 +--- a/sysdeps/ieee754/flt-32/s_floorf.c ++++ b/sysdeps/ieee754/flt-32/s_floorf.c +@@ -26,34 +26,45 @@ + #include + + float +-__floorf(float x) ++__floorf (float x) + { + #if USE_FLOORF_BUILTIN + return __builtin_floorf (x); + #else + /* Use generic implementation. */ +- int32_t i0,j0; +- uint32_t i; +- GET_FLOAT_WORD(i0,x); +- j0 = ((i0>>23)&0xff)-0x7f; +- if(j0<23) { +- if(j0<0) { +- /* return 0*sign(x) if |x|<1 */ +- if(i0>=0) {i0=0;} +- else if((i0&0x7fffffff)!=0) +- { i0=0xbf800000;} +- } else { +- i = (0x007fffff)>>j0; +- if((i0&i)==0) return x; /* x is integral */ +- if(i0<0) i0 += (0x00800000)>>j0; +- i0 &= (~i); +- } +- } else { +- if(__builtin_expect(j0==0x80, 0)) return x+x; /* inf or NaN */ +- else return x; /* x is integral */ ++ int32_t i0, j0; ++ uint32_t i; ++ GET_FLOAT_WORD (i0, x); ++ j0 = ((i0 >> 23) & 0xff) - 0x7f; ++ if (j0 < 23) ++ { ++ if (j0 < 0) ++ { ++ /* return 0 * sign (x) if |x| < 1 */ ++ if (i0 >= 0) ++ i0 = 0; ++ else if ((i0 & 0x7fffffff) != 0) ++ i0 = 0xbf800000; + } +- SET_FLOAT_WORD(x,i0); +- return x; ++ else ++ { ++ i = (0x007fffff) >> j0; ++ if ((i0 & i) == 0) ++ return x; /* x is integral */ ++ if (i0 < 0) ++ i0 += (0x00800000) >> j0; ++ i0 &= (~i); ++ } ++ } ++ else ++ { ++ if (__glibc_unlikely (j0 == 0x80)) ++ return x + x; /* inf or NaN */ ++ else ++ return x; /* x is integral */ ++ } ++ SET_FLOAT_WORD (x, i0); ++ return x; + #endif /* ! USE_FLOORF_BUILTIN */ + } + #ifndef __floorf +diff --git a/sysdeps/ieee754/ldbl-128/s_floorl.c b/sysdeps/ieee754/ldbl-128/s_floorl.c +index 6143fe6ec5..4fc10992c2 100644 +--- a/sysdeps/ieee754/ldbl-128/s_floorl.c ++++ b/sysdeps/ieee754/ldbl-128/s_floorl.c +@@ -29,46 +29,71 @@ static char rcsid[] = "$NetBSD: $"; + #include + #include + +-_Float128 __floorl(_Float128 x) ++_Float128 ++__floorl (_Float128 x) + { + #if USE_FLOORL_BUILTIN + return __builtin_floorl (x); + #else + /* Use generic implementation. */ +- int64_t i0,i1,j0; +- uint64_t i,j; +- GET_LDOUBLE_WORDS64(i0,i1,x); +- j0 = ((i0>>48)&0x7fff)-0x3fff; +- if(j0<48) { +- if(j0<0) { +- /* return 0*sign(x) if |x|<1 */ +- if(i0>=0) {i0=i1=0;} +- else if(((i0&0x7fffffffffffffffLL)|i1)!=0) +- { i0=0xbfff000000000000ULL;i1=0;} +- } else { +- i = (0x0000ffffffffffffULL)>>j0; +- if(((i0&i)|i1)==0) return x; /* x is integral */ +- if(i0<0) i0 += (0x0001000000000000LL)>>j0; +- i0 &= (~i); i1=0; ++ int64_t i0, i1, j0; ++ uint64_t i, j; ++ GET_LDOUBLE_WORDS64 (i0, i1, x); ++ j0 = ((i0 >> 48) & 0x7fff) - 0x3fff; ++ if (j0 < 48) ++ { ++ if (j0 < 0) ++ { ++ /* return 0 * sign (x) if |x| < 1 */ ++ if (i0 >= 0) ++ { ++ i0 = i1 = 0; + } +- } else if (j0>111) { +- if(j0==0x4000) return x+x; /* inf or NaN */ +- else return x; /* x is integral */ +- } else { +- i = -1ULL>>(j0-48); +- if((i1&i)==0) return x; /* x is integral */ +- if(i0<0) { +- if(j0==48) i0+=1; +- else { +- j = i1+(1LL<<(112-j0)); +- if(j> j0; ++ if (((i0 & i) | i1) == 0) ++ return x; /* x is integral */ ++ if (i0 < 0) ++ i0 += (0x0001000000000000LL) >> j0; ++ i0 &= (~i); ++ i1 = 0; ++ } ++ } ++ else if (j0 > 111) ++ { ++ if (j0 == 0x4000) ++ return x + x; /* inf or NaN */ ++ else ++ return x; /* x is integral */ ++ } ++ else ++ { ++ i = -1ULL >> (j0 - 48); ++ if ((i1 & i) == 0) ++ return x; /* x is integral */ ++ if (i0 < 0) ++ { ++ if (j0 == 48) ++ i0 += 1; ++ else ++ { ++ j = i1 + (1LL << (112 - j0)); ++ if (j < i1) ++ i0 += 1 ; /* got a carry */ ++ i1 = j; ++ } ++ } ++ i1 &= (~i); ++ } ++ SET_LDOUBLE_WORDS64 (x, i0, i1); ++ return x; + #endif /* ! USE_FLOORL_BUILTIN */ + } + libm_alias_ldouble (__floor, floor) +-- +2.18.2 + diff --git a/glibc-rh1780204-17.patch b/glibc-rh1780204-17.patch new file mode 100755 index 0000000..c8e447c --- /dev/null +++ b/glibc-rh1780204-17.patch @@ -0,0 +1,207 @@ +From 77b9cf86bba41d44e084337a11bfbf5ee7c98a38 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:27 +0100 +Subject: [PATCH 17/28] Adjust s_ceilf.c and s_ceill.c regarding code style. + +This patch just adjusts the generic implementation regarding code style. +No functional change. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit 171d23d7cbce7b6f175a6690e625ccf80b647d23) +--- + sysdeps/ieee754/flt-32/s_ceilf.c | 54 +++++++++++------- + sysdeps/ieee754/ldbl-128/s_ceill.c | 91 +++++++++++++++++++----------- + 2 files changed, 92 insertions(+), 53 deletions(-) + +diff --git a/sysdeps/ieee754/flt-32/s_ceilf.c b/sysdeps/ieee754/flt-32/s_ceilf.c +index 6cab7bdd62..f60d0ac1f5 100644 +--- a/sysdeps/ieee754/flt-32/s_ceilf.c ++++ b/sysdeps/ieee754/flt-32/s_ceilf.c +@@ -19,34 +19,46 @@ + #include + + float +-__ceilf(float x) ++__ceilf (float x) + { + #if USE_CEILF_BUILTIN + return __builtin_ceilf (x); + #else + /* Use generic implementation. */ +- int32_t i0,j0; +- uint32_t i; ++ int32_t i0, j0; ++ uint32_t i; + +- GET_FLOAT_WORD(i0,x); +- j0 = ((i0>>23)&0xff)-0x7f; +- if(j0<23) { +- if(j0<0) { +- /* return 0*sign(x) if |x|<1 */ +- if(i0<0) {i0=0x80000000;} +- else if(i0!=0) { i0=0x3f800000;} +- } else { +- i = (0x007fffff)>>j0; +- if((i0&i)==0) return x; /* x is integral */ +- if(i0>0) i0 += (0x00800000)>>j0; +- i0 &= (~i); +- } +- } else { +- if(__builtin_expect(j0==0x80, 0)) return x+x; /* inf or NaN */ +- else return x; /* x is integral */ ++ GET_FLOAT_WORD (i0, x); ++ j0 = ((i0 >> 23) & 0xff) - 0x7f; ++ if (j0 < 23) ++ { ++ if (j0 < 0) ++ { ++ /* return 0 * sign (x) if |x| < 1 */ ++ if (i0 < 0) ++ i0 = 0x80000000; ++ else if (i0 != 0) ++ i0 = 0x3f800000; + } +- SET_FLOAT_WORD(x,i0); +- return x; ++ else ++ { ++ i = (0x007fffff) >> j0; ++ if ((i0 & i) == 0) ++ return x; /* x is integral */ ++ if (i0 > 0) ++ i0 += (0x00800000) >> j0; ++ i0 &= (~i); ++ } ++ } ++ else ++ { ++ if (__glibc_unlikely (j0 == 0x80)) ++ return x + x; /* inf or NaN */ ++ else ++ return x; /* x is integral */ ++ } ++ SET_FLOAT_WORD (x, i0); ++ return x; + #endif /* ! USE_CEILF_BUILTIN */ + } + #ifndef __ceilf +diff --git a/sysdeps/ieee754/ldbl-128/s_ceill.c b/sysdeps/ieee754/ldbl-128/s_ceill.c +index d212d86179..df75dc3008 100644 +--- a/sysdeps/ieee754/ldbl-128/s_ceill.c ++++ b/sysdeps/ieee754/ldbl-128/s_ceill.c +@@ -13,7 +13,7 @@ + * ==================================================== + */ + +-#if defined(LIBM_SCCS) && !defined(lint) ++#if defined (LIBM_SCCS) && ! defined (lint) + static char rcsid[] = "$NetBSD: $"; + #endif + +@@ -29,45 +29,72 @@ static char rcsid[] = "$NetBSD: $"; + #include + #include + +-_Float128 __ceill(_Float128 x) ++_Float128 ++__ceill (_Float128 x) + { + #if USE_CEILL_BUILTIN + return __builtin_ceill (x); + #else + /* Use generic implementation. */ +- int64_t i0,i1,j0; +- uint64_t i,j; +- GET_LDOUBLE_WORDS64(i0,i1,x); +- j0 = ((i0>>48)&0x7fff)-0x3fff; +- if(j0<48) { +- if(j0<0) { +- /* return 0*sign(x) if |x|<1 */ +- if(i0<0) {i0=0x8000000000000000ULL;i1=0;} +- else if((i0|i1)!=0) { i0=0x3fff000000000000ULL;i1=0;} +- } else { +- i = (0x0000ffffffffffffULL)>>j0; +- if(((i0&i)|i1)==0) return x; /* x is integral */ +- if(i0>0) i0 += (0x0001000000000000LL)>>j0; +- i0 &= (~i); i1=0; ++ int64_t i0, i1, j0; ++ uint64_t i, j; ++ GET_LDOUBLE_WORDS64 (i0, i1, x); ++ j0 = ((i0 >> 48) & 0x7fff) - 0x3fff; ++ if (j0 < 48) ++ { ++ if (j0 < 0) ++ { ++ /* return 0 * sign (x) if |x| < 1 */ ++ if (i0 < 0) ++ { ++ i0 = 0x8000000000000000ULL; ++ i1 = 0; + } +- } else if (j0>111) { +- if(j0==0x4000) return x+x; /* inf or NaN */ +- else return x; /* x is integral */ +- } else { +- i = -1ULL>>(j0-48); +- if((i1&i)==0) return x; /* x is integral */ +- if(i0>0) { +- if(j0==48) i0+=1; +- else { +- j = i1+(1LL<<(112-j0)); +- if(j> j0; ++ if (((i0 & i) | i1) == 0) ++ return x; /* x is integral */ ++ if (i0 > 0) ++ i0 += (0x0001000000000000LL) >> j0; ++ i0 &= (~i); ++ i1 = 0; ++ } ++ } ++ else if (j0 > 111) ++ { ++ if (j0 == 0x4000) ++ return x + x; /* inf or NaN */ ++ else ++ return x; /* x is integral */ ++ } ++ else ++ { ++ i = -1ULL >> (j0 - 48); ++ if ((i1 & i) == 0) ++ return x; /* x is integral */ ++ if (i0 > 0) ++ { ++ if (j0 == 48) ++ i0 += 1; ++ else ++ { ++ j = i1 + (1LL << (112 - j0)); ++ if (j < i1) ++ i0 += 1; /* got a carry */ ++ i1 = j; ++ } ++ } ++ i1 &= (~i); ++ } ++ SET_LDOUBLE_WORDS64 (x, i0, i1); ++ return x; + #endif /* ! USE_CEILL_BUILTIN */ + } + libm_alias_ldouble (__ceil, ceil) +-- +2.18.2 + diff --git a/glibc-rh1780204-18.patch b/glibc-rh1780204-18.patch new file mode 100755 index 0000000..feb6f36 --- /dev/null +++ b/glibc-rh1780204-18.patch @@ -0,0 +1,57 @@ +From f6e3f49613f4a31bce8c5f52ae440f9c7b3646fb Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:28 +0100 +Subject: [PATCH 18/28] Adjust s_copysignl.c regarding code style. + +This patch just adjusts the generic implementation regarding code style. +No functional change. + +Reviewed-by: Adhemerval Zanella +(cherry picked from commit 1902d5d5ff04771f16b67648789c75a18af06222) +--- + sysdeps/ieee754/ldbl-128/s_copysignl.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/sysdeps/ieee754/ldbl-128/s_copysignl.c b/sysdeps/ieee754/ldbl-128/s_copysignl.c +index 4cae8612dc..9b0e44cf1d 100644 +--- a/sysdeps/ieee754/ldbl-128/s_copysignl.c ++++ b/sysdeps/ieee754/ldbl-128/s_copysignl.c +@@ -13,7 +13,7 @@ + * ==================================================== + */ + +-#if defined(LIBM_SCCS) && !defined(lint) ++#if defined (LIBM_SCCS) && ! defined (lint) + static char rcsid[] = "$NetBSD: $"; + #endif + +@@ -28,18 +28,19 @@ static char rcsid[] = "$NetBSD: $"; + #include + #include + +-_Float128 __copysignl(_Float128 x, _Float128 y) ++_Float128 ++__copysignl (_Float128 x, _Float128 y) + { + #if USE_COPYSIGNL_BUILTIN + return __builtin_copysignl (x, y); + #else + /* Use generic implementation. */ +- uint64_t hx,hy; +- GET_LDOUBLE_MSW64(hx,x); +- GET_LDOUBLE_MSW64(hy,y); +- SET_LDOUBLE_MSW64(x,(hx&0x7fffffffffffffffULL) +- |(hy&0x8000000000000000ULL)); +- return x; ++ uint64_t hx, hy; ++ GET_LDOUBLE_MSW64 (hx, x); ++ GET_LDOUBLE_MSW64 (hy, y); ++ SET_LDOUBLE_MSW64 (x, (hx & 0x7fffffffffffffffULL) ++ | (hy & 0x8000000000000000ULL)); ++ return x; + #endif /* ! USE_COPYSIGNL_BUILTIN */ + } + libm_alias_ldouble (__copysign, copysign) +-- +2.18.2 + diff --git a/glibc-rh1780204-19.patch b/glibc-rh1780204-19.patch new file mode 100755 index 0000000..bda184c --- /dev/null +++ b/glibc-rh1780204-19.patch @@ -0,0 +1,157 @@ +From 855d045bc26175195dadafc28abf84e7b6613aac Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:28 +0100 +Subject: [PATCH 19/28] S390: Use load-fp-integer instruction for roundeven + functions. + +If compiled with z196 zarch support, the load-fp-integer instruction +is used to implement roundeven, roundevenf, roundevenl. +Otherwise the common-code implementation is used. + +(cherry picked from commit 4399b163376b331773e43917dcf56ce68e43e6a0) +--- + sysdeps/s390/fpu/s_roundeven.c | 39 +++++++++++++++++++++++++++++++++ + sysdeps/s390/fpu/s_roundevenf.c | 38 ++++++++++++++++++++++++++++++++ + sysdeps/s390/fpu/s_roundevenl.c | 39 +++++++++++++++++++++++++++++++++ + 3 files changed, 116 insertions(+) + create mode 100644 sysdeps/s390/fpu/s_roundeven.c + create mode 100644 sysdeps/s390/fpu/s_roundevenf.c + create mode 100644 sysdeps/s390/fpu/s_roundevenl.c + +diff --git a/sysdeps/s390/fpu/s_roundeven.c b/sysdeps/s390/fpu/s_roundeven.c +new file mode 100644 +index 0000000000..95a83a70e8 +--- /dev/null ++++ b/sysdeps/s390/fpu/s_roundeven.c +@@ -0,0 +1,39 @@ ++/* roundeven() - S390 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 ++ . */ ++ ++#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# include ++# include ++ ++double ++__roundeven (double x) ++{ ++ double y; ++ /* The z196 zarch "load fp integer" (fidbra) instruction is rounding ++ x to the nearest integer with "ties to even" rounding mode ++ (M3-field: 4) where inexact exceptions are suppressed (M4-field: 4). */ ++ __asm__ ("fidbra %0,4,%1,4" : "=f" (y) : "f" (x)); ++ return y; ++} ++hidden_def (__roundeven) ++libm_alias_double (__roundeven, roundeven) ++ ++#else ++# include ++#endif +diff --git a/sysdeps/s390/fpu/s_roundevenf.c b/sysdeps/s390/fpu/s_roundevenf.c +new file mode 100644 +index 0000000000..c620a0189c +--- /dev/null ++++ b/sysdeps/s390/fpu/s_roundevenf.c +@@ -0,0 +1,38 @@ ++/* roundevenf() - S390 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 ++ . */ ++ ++#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# include ++# include ++ ++float ++__roundevenf (float x) ++{ ++ float y; ++ /* The z196 zarch "load fp integer" (fiebra) instruction is rounding ++ x to the nearest integer with "ties to even" rounding mode ++ (M3-field: 4) where inexact exceptions are suppressed (M4-field: 4). */ ++ __asm__ ("fiebra %0,4,%1,4" : "=f" (y) : "f" (x)); ++ return y; ++} ++libm_alias_float (__roundeven, roundeven) ++ ++#else ++# include ++#endif +diff --git a/sysdeps/s390/fpu/s_roundevenl.c b/sysdeps/s390/fpu/s_roundevenl.c +new file mode 100644 +index 0000000000..3481af2665 +--- /dev/null ++++ b/sysdeps/s390/fpu/s_roundevenl.c +@@ -0,0 +1,39 @@ ++/* roundevenl() - S390 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 ++ . */ ++ ++#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# include ++# include ++# include ++ ++_Float128 ++__roundevenl (_Float128 x) ++{ ++ _Float128 y; ++ /* The z196 zarch "load fp integer" (fixbra) instruction is rounding ++ x to the nearest integer with "ties to even" rounding mode ++ (M3-field: 4) where inexact exceptions are suppressed (M4-field: 4). */ ++ __asm__ ("fixbra %0,4,%1,4" : "=f" (y) : "f" (x)); ++ return y; ++} ++libm_alias_ldouble (__roundeven, roundeven) ++ ++#else ++# include ++#endif +-- +2.18.2 + diff --git a/glibc-rh1780204-20.patch b/glibc-rh1780204-20.patch new file mode 100755 index 0000000..4967ce3 --- /dev/null +++ b/glibc-rh1780204-20.patch @@ -0,0 +1,207 @@ +From 90e84ac5ac8e774ce0cfd3abc5f7d8834efd2c9b Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:29 +0100 +Subject: [PATCH 20/28] S390: Use convert-to-fixed instruction for lrint + functions. + +If compiled with z196 zarch support, the convert-to-fixed instruction +is used to implement lrint, lrintf, lrintl. +Otherwise the common-code implementation is used. + +(cherry picked from commit e3f07622209c1b4436ef364b134dfd2cd4ca9976) +--- + sysdeps/s390/fpu/s_lrint.c | 55 ++++++++++++++++++++++++++++++++++++ + sysdeps/s390/fpu/s_lrintf.c | 55 ++++++++++++++++++++++++++++++++++++ + sysdeps/s390/fpu/s_lrintl.c | 56 +++++++++++++++++++++++++++++++++++++ + 3 files changed, 166 insertions(+) + create mode 100644 sysdeps/s390/fpu/s_lrint.c + create mode 100644 sysdeps/s390/fpu/s_lrintf.c + create mode 100644 sysdeps/s390/fpu/s_lrintl.c + +diff --git a/sysdeps/s390/fpu/s_lrint.c b/sysdeps/s390/fpu/s_lrint.c +new file mode 100644 +index 0000000000..7be60665b5 +--- /dev/null ++++ b/sysdeps/s390/fpu/s_lrint.c +@@ -0,0 +1,55 @@ ++/* lrint() - S390 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 ++ . */ ++ ++#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# include ++# include ++ ++/* The sizeof (long int) differs between s390x (8byte) and s390 (4byte). ++ Thus we need different instructions as the target size is encoded there. ++ Note: On s390 this instruction is only used if build with -mzarch. */ ++# ifdef __s390x__ ++# define INSN "cgdbra" ++# else ++# define INSN "cfdbra" ++# endif ++ ++long int ++__lrint (double x) ++{ ++ long int y; ++ /* The z196 zarch "convert to fixed" (cgdbra) instruction is rounding ++ according to current rounding mode (M3-field: 0). ++ First convert x with suppressed inexact exception and check if the ++ resulting value is beyond the target limits (indicated by cc=3; ++ Note: a nan is also indicated by cc=3). ++ If the resulting value is within the target limits, redo ++ without suppressing the inexact exception. */ ++ __asm__ (INSN " %0,0,%1,4 \n\t" ++ "jo 1f \n\t" ++ INSN " %0,0,%1,0 \n\t" ++ "1:" ++ : "=&d" (y) : "f" (x) : "cc"); ++ return y; ++} ++libm_alias_double (__lrint, lrint) ++ ++#else ++# include ++#endif +diff --git a/sysdeps/s390/fpu/s_lrintf.c b/sysdeps/s390/fpu/s_lrintf.c +new file mode 100644 +index 0000000000..d6a2a4081a +--- /dev/null ++++ b/sysdeps/s390/fpu/s_lrintf.c +@@ -0,0 +1,55 @@ ++/* lrintf() - S390 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 ++ . */ ++ ++#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# include ++# include ++ ++/* The sizeof (long int) differs between s390x (8byte) and s390 (4byte). ++ Thus we need different instructions as the target size is encoded there. ++ Note: On s390 this instruction is only used if build with -mzarch. */ ++# ifdef __s390x__ ++# define INSN "cgebra" ++# else ++# define INSN "cfebra" ++# endif ++ ++long int ++__lrintf (float x) ++{ ++ long int y; ++ /* The z196 zarch "convert to fixed" (cgebra) instruction is rounding ++ according to current rounding mode (M3-field: 0). ++ First convert x with suppressed inexact exception and check if the ++ resulting value is beyond the target limits (indicated by cc=3; ++ Note: a nan is also indicated by cc=3). ++ If the resulting value is within the target limits, redo ++ without suppressing the inexact exception. */ ++ __asm__ (INSN " %0,0,%1,4 \n\t" ++ "jo 1f \n\t" ++ INSN " %0,0,%1,0 \n\t" ++ "1:" ++ : "=&d" (y) : "f" (x) : "cc"); ++ return y; ++} ++libm_alias_float (__lrint, lrint) ++ ++#else ++# include ++#endif +diff --git a/sysdeps/s390/fpu/s_lrintl.c b/sysdeps/s390/fpu/s_lrintl.c +new file mode 100644 +index 0000000000..2d386ecff9 +--- /dev/null ++++ b/sysdeps/s390/fpu/s_lrintl.c +@@ -0,0 +1,56 @@ ++/* lrintl() - S390 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 ++ . */ ++ ++#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# include ++# include ++# include ++ ++/* The sizeof (long int) differs between s390x (8byte) and s390 (4byte). ++ Thus we need different instructions as the target size is encoded there. ++ Note: On s390 this instruction is only used if build with -mzarch. */ ++# ifdef __s390x__ ++# define INSN "cgxbra" ++# else ++# define INSN "cfxbra" ++# endif ++ ++long int ++__lrintl (_Float128 x) ++{ ++ long int y; ++ /* The z196 zarch "convert to fixed" (cgxbra) instruction is rounding ++ according to current rounding mode (M3-field: 0). ++ First convert x with suppressed inexact exception and check if the ++ resulting value is beyond the target limits (indicated by cc=3; ++ Note: a nan is also indicated by cc=3). ++ If the resulting value is within the target limits, redo ++ without suppressing the inexact exception. */ ++ __asm__ (INSN " %0,0,%1,4 \n\t" ++ "jo 1f \n\t" ++ INSN " %0,0,%1,0 \n\t" ++ "1:" ++ : "=&d" (y) : "f" (x) : "cc"); ++ return y; ++} ++libm_alias_ldouble (__lrint, lrint) ++ ++#else ++# include ++#endif +-- +2.18.2 + diff --git a/glibc-rh1780204-21.patch b/glibc-rh1780204-21.patch new file mode 100755 index 0000000..743e16c --- /dev/null +++ b/glibc-rh1780204-21.patch @@ -0,0 +1,192 @@ +From 429eff12541cc0779c381f84257c8860ece25b12 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:29 +0100 +Subject: [PATCH 21/28] S390: Use convert-to-fixed instruction for llrint + functions. + +If compiled with z196 zarch support, the convert-to-fixed instruction +is used to implement llrint, llrintf, llrintl. +Otherwise the common-code implementation is used. + +(cherry picked from commit f10c1654fe13d797d2fd347dc47f72f93c58cf62) +--- + sysdeps/s390/fpu/s_llrint.c | 50 +++++++++++++++++++++++++++++++++++ + sysdeps/s390/fpu/s_llrintf.c | 50 +++++++++++++++++++++++++++++++++++ + sysdeps/s390/fpu/s_llrintl.c | 51 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 151 insertions(+) + create mode 100644 sysdeps/s390/fpu/s_llrint.c + create mode 100644 sysdeps/s390/fpu/s_llrintf.c + create mode 100644 sysdeps/s390/fpu/s_llrintl.c + +diff --git a/sysdeps/s390/fpu/s_llrint.c b/sysdeps/s390/fpu/s_llrint.c +new file mode 100644 +index 0000000000..edd796ae8c +--- /dev/null ++++ b/sysdeps/s390/fpu/s_llrint.c +@@ -0,0 +1,50 @@ ++/* llrint() - S390 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 ++ . */ ++ ++#if defined __s390x__ && defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++/* We only support s390x as on s390 a long long int refers to a register pair ++ of two 4byte registers instead of a 8byte register which is produced by the ++ instruction. ++ Note: On s390 this instruction would only be used if build with -mzarch. */ ++# include ++# include ++ ++long long int ++__llrint (double x) ++{ ++ long long int y; ++ /* The z196 zarch "convert to fixed" (cgdbra) instruction is rounding ++ according to current rounding mode (M3-field: 0). ++ First convert x with suppressed inexact exception and check if the ++ resulting value is beyond the target limits (indicated by cc=3; ++ Note: a nan is also indicated by cc=3). ++ If the resulting value is within the target limits, redo ++ without suppressing the inexact exception. */ ++ __asm__ ("cgdbra %0,0,%1,4 \n\t" ++ "jo 1f \n\t" ++ "cgdbra %0,0,%1,0 \n\t" ++ "1:" ++ : "=&d" (y) : "f" (x) : "cc"); ++ return y; ++} ++libm_alias_double (__llrint, llrint) ++ ++#else ++# include ++#endif +diff --git a/sysdeps/s390/fpu/s_llrintf.c b/sysdeps/s390/fpu/s_llrintf.c +new file mode 100644 +index 0000000000..3cbe7c581a +--- /dev/null ++++ b/sysdeps/s390/fpu/s_llrintf.c +@@ -0,0 +1,50 @@ ++/* llrintf() - S390 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 ++ . */ ++ ++#if defined __s390x__ && defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++/* We only support s390x as on s390 a long long int refers to a register pair ++ of two 4byte registers instead of a 8byte register which is produced by the ++ instruction. ++ Note: On s390 this instruction would only be used if build with -mzarch. */ ++# include ++# include ++ ++long long int ++__llrintf (float x) ++{ ++ long long int y; ++ /* The z196 zarch "convert to fixed" (cgebra) instruction is rounding ++ according to current rounding mode (M3-field: 0). ++ First convert x with suppressed inexact exception and check if the ++ resulting value is beyond the target limits (indicated by cc=3; ++ Note: a nan is also indicated by cc=3). ++ If the resulting value is within the target limits, redo ++ without suppressing the inexact exception. */ ++ __asm__ ("cgebra %0,0,%1,4 \n\t" ++ "jo 1f \n\t" ++ "cgebra %0,0,%1,0 \n\t" ++ "1:" ++ : "=&d" (y) : "f" (x) : "cc"); ++ return y; ++} ++libm_alias_float (__llrint, llrint) ++ ++#else ++# include ++#endif +diff --git a/sysdeps/s390/fpu/s_llrintl.c b/sysdeps/s390/fpu/s_llrintl.c +new file mode 100644 +index 0000000000..37eea5914f +--- /dev/null ++++ b/sysdeps/s390/fpu/s_llrintl.c +@@ -0,0 +1,51 @@ ++/* llrintl() - S390 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 ++ . */ ++ ++#if defined __s390x__ && defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++/* We only support s390x as on s390 a long long int refers to a register pair ++ of two 4byte registers instead of a 8byte register which is produced by the ++ instruction. ++ Note: On s390 this instruction would only be used if build with -mzarch. */ ++# include ++# include ++# include ++ ++long long int ++__llrintl (_Float128 x) ++{ ++ long long int y; ++ /* The z196 zarch "convert to fixed" (cgxbra) instruction is rounding ++ according to current rounding mode (M3-field: 0). ++ First convert x with suppressed inexact exception and check if the ++ resulting value is beyond the target limits (indicated by cc=3; ++ Note: a nan is also indicated by cc=3). ++ If the resulting value is within the target limits, redo ++ without suppressing the inexact exception. */ ++ __asm__ ("cgxbra %0,0,%1,4 \n\t" ++ "jo 1f \n\t" ++ "cgxbra %0,0,%1,0 \n\t" ++ "1:" ++ : "=&d" (y) : "f" (x) : "cc"); ++ return y; ++} ++libm_alias_ldouble (__llrint, llrint) ++ ++#else ++# include ++#endif +-- +2.18.2 + diff --git a/glibc-rh1780204-22.patch b/glibc-rh1780204-22.patch new file mode 100755 index 0000000..db29fa3 --- /dev/null +++ b/glibc-rh1780204-22.patch @@ -0,0 +1,183 @@ +From 9f3ee7825b1eae00431ea6477fce8210aaced7db Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:30 +0100 +Subject: [PATCH 22/28] S390: Use convert-to-fixed instruction for lround + functions. + +If compiled with z196 zarch support, the convert-to-fixed instruction +is used to implement lround, lroundf, lroundl. +Otherwise the common-code implementation is used. + +(cherry picked from commit 9d9f3527daf65fdca0eb46eaa324b81b8f94d88c) +--- + sysdeps/s390/fpu/s_lround.c | 47 +++++++++++++++++++++++++++++++++++ + sysdeps/s390/fpu/s_lroundf.c | 47 +++++++++++++++++++++++++++++++++++ + sysdeps/s390/fpu/s_lroundl.c | 48 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 142 insertions(+) + create mode 100644 sysdeps/s390/fpu/s_lround.c + create mode 100644 sysdeps/s390/fpu/s_lroundf.c + create mode 100644 sysdeps/s390/fpu/s_lroundl.c + +diff --git a/sysdeps/s390/fpu/s_lround.c b/sysdeps/s390/fpu/s_lround.c +new file mode 100644 +index 0000000000..9290ec32cd +--- /dev/null ++++ b/sysdeps/s390/fpu/s_lround.c +@@ -0,0 +1,47 @@ ++/* lround() - S390 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 ++ . */ ++ ++#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# include ++# include ++ ++/* The sizeof (long int) differs between s390x (8byte) and s390 (4byte). ++ Thus we need different instructions as the target size is encoded there. ++ Note: On s390 this instruction is only used if build with -mzarch. */ ++# ifdef __s390x__ ++# define INSN "cgdbra" ++# else ++# define INSN "cfdbra" ++# endif ++ ++long int ++__lround (double x) ++{ ++ long int y; ++ /* The z196 zarch "convert to fixed" (cgdbra) instruction is rounding ++ x to the nearest integer with "ties away from 0" rounding mode ++ (M3-field: 1) where inexact exceptions are suppressed (M4-field: 4). */ ++ __asm__ (INSN " %0,1,%1,4" : "=d" (y) : "f" (x) : "cc"); ++ return y; ++} ++libm_alias_double (__lround, lround) ++ ++#else ++# include ++#endif +diff --git a/sysdeps/s390/fpu/s_lroundf.c b/sysdeps/s390/fpu/s_lroundf.c +new file mode 100644 +index 0000000000..097b924c91 +--- /dev/null ++++ b/sysdeps/s390/fpu/s_lroundf.c +@@ -0,0 +1,47 @@ ++/* lroundf() - S390 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 ++ . */ ++ ++#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# include ++# include ++ ++/* The sizeof (long int) differs between s390x (8byte) and s390 (4byte). ++ Thus we need different instructions as the target size is encoded there. ++ Note: On s390 this instruction is only used if build with -mzarch. */ ++# ifdef __s390x__ ++# define INSN "cgebra" ++# else ++# define INSN "cfebra" ++# endif ++ ++long int ++__lroundf (float x) ++{ ++ long int y; ++ /* The z196 zarch "convert to fixed" (cgebra) instruction is rounding ++ x to the nearest integer with "ties away from 0" rounding mode ++ (M3-field: 1) where inexact exceptions are suppressed (M4-field: 4). */ ++ __asm__ (INSN " %0,1,%1,4" : "=d" (y) : "f" (x) : "cc"); ++ return y; ++} ++libm_alias_float (__lround, lround) ++ ++#else ++# include ++#endif +diff --git a/sysdeps/s390/fpu/s_lroundl.c b/sysdeps/s390/fpu/s_lroundl.c +new file mode 100644 +index 0000000000..0ef77dc667 +--- /dev/null ++++ b/sysdeps/s390/fpu/s_lroundl.c +@@ -0,0 +1,48 @@ ++/* lroundl() - S390 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 ++ . */ ++ ++#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# include ++# include ++# include ++ ++/* The sizeof (long int) differs between s390x (8byte) and s390 (4byte). ++ Thus we need different instructions as the target size is encoded there. ++ Note: On s390 this instruction is only used if build with -mzarch. */ ++# ifdef __s390x__ ++# define INSN "cgxbra" ++# else ++# define INSN "cfxbra" ++# endif ++ ++long int ++__lroundl (_Float128 x) ++{ ++ long int y; ++ /* The z196 zarch "convert to fixed" (cgxbra) instruction is rounding ++ x to the nearest integer with "ties away from 0" rounding mode ++ (M3-field: 1) where inexact exceptions are suppressed (M4-field: 4). */ ++ __asm__ (INSN " %0,1,%1,4" : "=d" (y) : "f" (x) : "cc"); ++ return y; ++} ++libm_alias_ldouble (__lround, lround) ++ ++#else ++# include ++#endif +-- +2.18.2 + diff --git a/glibc-rh1780204-23.patch b/glibc-rh1780204-23.patch new file mode 100755 index 0000000..bcd8965 --- /dev/null +++ b/glibc-rh1780204-23.patch @@ -0,0 +1,168 @@ +From dd8bfb911e89f3ad1da5cfa5618a8c52c62bb095 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:31 +0100 +Subject: [PATCH 23/28] S390: Use convert-to-fixed instruction for llround + functions. + +If compiled with z196 zarch support, the convert-to-fixed instruction +is used to implement llround, llroundf, llroundl. +Otherwise the common-code implementation is used. + +(cherry picked from commit 7d42d614fdc2c9d9f6ad46111bd6130501d50460) +--- + sysdeps/s390/fpu/s_llround.c | 42 ++++++++++++++++++++++++++++++++++ + sysdeps/s390/fpu/s_llroundf.c | 42 ++++++++++++++++++++++++++++++++++ + sysdeps/s390/fpu/s_llroundl.c | 43 +++++++++++++++++++++++++++++++++++ + 3 files changed, 127 insertions(+) + create mode 100644 sysdeps/s390/fpu/s_llround.c + create mode 100644 sysdeps/s390/fpu/s_llroundf.c + create mode 100644 sysdeps/s390/fpu/s_llroundl.c + +diff --git a/sysdeps/s390/fpu/s_llround.c b/sysdeps/s390/fpu/s_llround.c +new file mode 100644 +index 0000000000..f4a1b21637 +--- /dev/null ++++ b/sysdeps/s390/fpu/s_llround.c +@@ -0,0 +1,42 @@ ++/* llround() - S390 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 ++ . */ ++ ++#if defined __s390x__ && defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++/* We only support s390x as on s390 a long long int refers to a register pair ++ of two 4byte registers instead of a 8byte register which is produced by the ++ instruction. ++ Note: On s390 this instruction would only be used if build with -mzarch. */ ++# include ++# include ++ ++long long int ++__llround (double x) ++{ ++ long long int y; ++ /* The z196 zarch "convert to fixed" (cgdbra) instruction is rounding ++ x to the nearest integer with "ties away from 0" rounding mode ++ (M3-field: 1) where inexact exceptions are suppressed (M4-field: 4). */ ++ __asm__ ("cgdbra %0,1,%1,4" : "=d" (y) : "f" (x) : "cc"); ++ return y; ++} ++libm_alias_double (__llround, llround) ++ ++#else ++# include ++#endif +diff --git a/sysdeps/s390/fpu/s_llroundf.c b/sysdeps/s390/fpu/s_llroundf.c +new file mode 100644 +index 0000000000..d202f4be8c +--- /dev/null ++++ b/sysdeps/s390/fpu/s_llroundf.c +@@ -0,0 +1,42 @@ ++/* llroundf() - S390 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 ++ . */ ++ ++#if defined __s390x__ && defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++/* We only support s390x as on s390 a long long int refers to a register pair ++ of two 4byte registers instead of a 8byte register which is produced by the ++ instruction. ++ Note: On s390 this instruction would only be used if build with -mzarch. */ ++# include ++# include ++ ++long long int ++__llroundf (float x) ++{ ++ long long int y; ++ /* The z196 zarch "convert to fixed" (cgebra) instruction is rounding ++ x to the nearest integer with "ties away from 0" rounding mode ++ (M3-field: 1) where inexact exceptions are suppressed (M4-field: 4). */ ++ __asm__ ("cgebra %0,1,%1,4" : "=d" (y) : "f" (x) : "cc"); ++ return y; ++} ++libm_alias_float (__llround, llround) ++ ++#else ++# include ++#endif +diff --git a/sysdeps/s390/fpu/s_llroundl.c b/sysdeps/s390/fpu/s_llroundl.c +new file mode 100644 +index 0000000000..58976cd5c5 +--- /dev/null ++++ b/sysdeps/s390/fpu/s_llroundl.c +@@ -0,0 +1,43 @@ ++/* llroundl() - S390 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 ++ . */ ++ ++#if defined __s390x__ && defined HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++/* We only support s390x as on s390 a long long int refers to a register pair ++ of two 4byte registers instead of a 8byte register which is produced by the ++ instruction. ++ Note: On s390 this instruction would only be used if build with -mzarch. */ ++# include ++# include ++# include ++ ++long long int ++__llroundl (_Float128 x) ++{ ++ long long int y; ++ /* The z196 zarch "convert to fixed" (cgxbra) instruction is rounding ++ x to the nearest integer with "ties away from 0" rounding mode ++ (M3-field: 1) where inexact exceptions are suppressed (M4-field: 4). */ ++ __asm__ ("cgxbra %0,1,%1,4" : "=d" (y) : "f" (x) : "cc"); ++ return y; ++} ++libm_alias_ldouble (__llround, llround) ++ ++#else ++# include ++#endif +-- +2.18.2 + diff --git a/glibc-rh1780204-24.patch b/glibc-rh1780204-24.patch new file mode 100755 index 0000000..21bfd24 --- /dev/null +++ b/glibc-rh1780204-24.patch @@ -0,0 +1,70 @@ +From 33f3c934e3023b85c3774ee0482ec4da2a10a3b5 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:32 +0100 +Subject: [PATCH 24/28] S390: Implement math-barriers math_opt_barrier and + math_force_eval. + +This patch implements the s390 specific math barriers in order +to omit the store and load from stack if possible. + +(cherry picked from commit 433a2ba68cd91842546e0f0d43d65835634d570d) +--- + sysdeps/s390/fpu/math-barriers.h | 46 ++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + create mode 100644 sysdeps/s390/fpu/math-barriers.h + +diff --git a/sysdeps/s390/fpu/math-barriers.h b/sysdeps/s390/fpu/math-barriers.h +new file mode 100644 +index 0000000000..7c3e6b15e0 +--- /dev/null ++++ b/sysdeps/s390/fpu/math-barriers.h +@@ -0,0 +1,46 @@ ++/* Control when floating-point expressions are evaluated. s390 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 ++ . */ ++ ++#ifndef S390_MATH_BARRIERS_H ++#define S390_MATH_BARRIERS_H 1 ++ ++#ifdef HAVE_S390_VX_GCC_SUPPORT ++# define ASM_CONSTRAINT_VR "v" ++#else ++# define ASM_CONSTRAINT_VR ++#endif ++ ++#define math_opt_barrier(x) \ ++ ({ __typeof (x) __x = (x); \ ++ if (__builtin_types_compatible_p (__typeof (x), _Float128)) \ ++ __asm__ ("# math_opt_barrier_f128 %0" : "+fm" (__x)); \ ++ else \ ++ __asm__ ("# math_opt_barrier %0" \ ++ : "+f" ASM_CONSTRAINT_VR "m" (__x)); \ ++ __x; }) ++#define math_force_eval(x) \ ++ ({ __typeof (x) __x = (x); \ ++ if (__builtin_types_compatible_p (__typeof (x), _Float128)) \ ++ __asm__ __volatile__ ("# math_force_eval_f128 %0" \ ++ : : "fm" (__x)); \ ++ else \ ++ __asm__ __volatile__ ("# math_force_eval %0" \ ++ : : "f" ASM_CONSTRAINT_VR "m" (__x)); \ ++ }) ++ ++#endif +-- +2.18.2 + diff --git a/glibc-rh1780204-25.patch b/glibc-rh1780204-25.patch new file mode 100755 index 0000000..34353ff --- /dev/null +++ b/glibc-rh1780204-25.patch @@ -0,0 +1,79 @@ +From cf5397eb5b33bab37c16bcb2d1bbddbce1a27de2 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:33 +0100 +Subject: [PATCH 25/28] S390: Implement roundtoint and converttoint and define + TOINT_INTRINSICS. + +This patch implements roundtoint and convertoint for s390 +by using the load-fp-integer and convert-to-fixed instructions. +Both functions are using "round to nearest with ties away from zero" +rounding mode and do not raise inexact exceptions. + +(cherry picked from commit 2763d3145a326aa9afa613fe9e1b444cf912a883) +--- + sysdeps/s390/fpu/math_private.h | 53 +++++++++++++++++++++++++++++++++ + 1 file changed, 53 insertions(+) + create mode 100644 sysdeps/s390/fpu/math_private.h + +diff --git a/sysdeps/s390/fpu/math_private.h b/sysdeps/s390/fpu/math_private.h +new file mode 100644 +index 0000000000..a1ae91a87c +--- /dev/null ++++ b/sysdeps/s390/fpu/math_private.h +@@ -0,0 +1,53 @@ ++/* Configure optimized libm functions. S390 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 ++ . */ ++ ++#ifndef S390_MATH_PRIVATE_H ++#define S390_MATH_PRIVATE_H 1 ++ ++#include ++#include ++ ++#ifdef HAVE_S390_MIN_Z196_ZARCH_ASM_SUPPORT ++# define TOINT_INTRINSICS 1 ++ ++static inline double_t ++roundtoint (double_t x) ++{ ++ double_t y; ++ /* The z196 zarch "load fp integer" (fidbra) instruction is rounding ++ x to the nearest integer with ties away from zero (M3-field: 1) ++ where inexact exceptions are suppressed (M4-field: 4). */ ++ __asm__ ("fidbra %0,1,%1,4" : "=f" (y) : "f" (x)); ++ return y; ++} ++ ++static inline int32_t ++converttoint (double_t x) ++{ ++ int32_t y; ++ /* The z196 zarch "convert to fixed" (cfdbra) instruction is rounding ++ x to the nearest integer with ties away from zero (M3-field: 1) ++ where inexact exceptions are suppressed (M4-field: 4). */ ++ __asm__ ("cfdbra %0,1,%1,4" : "=d" (y) : "f" (x) : "cc"); ++ return y; ++} ++#endif ++ ++#include_next ++ ++#endif +-- +2.18.2 + diff --git a/glibc-rh1780204-26.patch b/glibc-rh1780204-26.patch new file mode 100755 index 0000000..0f5a6bc --- /dev/null +++ b/glibc-rh1780204-26.patch @@ -0,0 +1,23 @@ +From 363f9d7a6be5a3b400e3ea3daab583bccfcfa152 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:34 +0100 +Subject: [PATCH 26/28] S390: Use sysdeps/ieee754/dbl-64/wordsize-64 on s390x. + +This patch enables the usage of implementations in +sysdeps/ieee754/dbl-64/wordsize-64 on 64bit s390x. + +(cherry picked from commit fcee34cc373daee6aa5320a6e1897cdf2005ab53) +--- + sysdeps/s390/s390-64/Implies | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sysdeps/s390/s390-64/Implies b/sysdeps/s390/s390-64/Implies +index a8cae95f9d..7603c9859c 100644 +--- a/sysdeps/s390/s390-64/Implies ++++ b/sysdeps/s390/s390-64/Implies +@@ -1 +1,2 @@ + wordsize-64 ++ieee754/dbl-64/wordsize-64 +-- +2.18.2 + diff --git a/glibc-rh1780204-27.patch b/glibc-rh1780204-27.patch new file mode 100755 index 0000000..a90ba6f --- /dev/null +++ b/glibc-rh1780204-27.patch @@ -0,0 +1,294 @@ +From 8e5e36d7ba097b8e110ab45794659156af182f54 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:31 +0100 +Subject: [PATCH 27/28] S390: Implement libc_fe* macros. + +This patch provides the s390 specific implementation for +libc_feholdexcept, libc_fesetround, libc_feholdexcept_setround, +libc_fetestexcept, libc_fesetenv, libc_feupdateenv_test, +libc_feupdateenv, libc_feholdsetround_ctx, libc_feresetround_ctx, +libc_feholdsetround_noex_ctx and libc_feresetround_noex_ctx. + +(cherry picked from commit 7c94d036c17dfd352d11e9bf98e5d84122c1f95e) +Note: glibc-2.28 does not have a generic fenv_private.h. +Therefore include_next does not work. Instead fenv_private.h needs to +be included in the s390 specific mathp_private.h just before including +the generic math_private.h. +As the s390 specific math_private.h is introduced with the backport of +commit "S390: Implement roundtoint and converttoint and define TOINT_INTRINSICS.", +the order of cherry-picking was changed compared to upstream! +--- + sysdeps/s390/fpu/fenv_private.h | 248 ++++++++++++++++++++++++++++++++ + sysdeps/s390/fpu/math_private.h | 1 + + 2 files changed, 249 insertions(+) + create mode 100644 sysdeps/s390/fpu/fenv_private.h + +diff --git a/sysdeps/s390/fpu/fenv_private.h b/sysdeps/s390/fpu/fenv_private.h +new file mode 100644 +index 0000000000..8899f8f434 +--- /dev/null ++++ b/sysdeps/s390/fpu/fenv_private.h +@@ -0,0 +1,248 @@ ++/* Private floating point rounding and exceptions handling. 390/s390x 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 ++ . */ ++ ++#ifndef S390_FENV_PRIVATE_H ++#define S390_FENV_PRIVATE_H 1 ++ ++#include ++#include ++#include ++ ++static __always_inline void ++libc_feholdexcept_s390 (fenv_t *envp) ++{ ++ fpu_control_t fpc, fpc_new; ++ ++ /* Store the environment. */ ++ _FPU_GETCW (fpc); ++ envp->__fpc = fpc; ++ ++ /* Clear the current exception flags and dxc field. ++ Hold from generating fpu exceptions temporarily. */ ++ fpc_new = fpc & ~(FPC_FLAGS_MASK | FPC_DXC_MASK | FPC_EXCEPTION_MASK); ++ ++ /* Only set new environment if it has changed. */ ++ if (fpc_new != fpc) ++ _FPU_SETCW (fpc_new); ++} ++ ++#define libc_feholdexcept libc_feholdexcept_s390 ++#define libc_feholdexceptf libc_feholdexcept_s390 ++#define libc_feholdexceptl libc_feholdexcept_s390 ++ ++static __always_inline void ++libc_fesetround_s390 (int round) ++{ ++ __asm__ __volatile__ ("srnm 0(%0)" : : "a" (round)); ++} ++ ++#define libc_fesetround libc_fesetround_s390 ++#define libc_fesetroundf libc_fesetround_s390 ++#define libc_fesetroundl libc_fesetround_s390 ++ ++static __always_inline void ++libc_feholdexcept_setround_s390 (fenv_t *envp, int r) ++{ ++ fpu_control_t fpc, fpc_new; ++ ++ _FPU_GETCW (fpc); ++ envp->__fpc = fpc; ++ ++ /* Clear the current exception flags and dxc field. ++ Hold from generating fpu exceptions temporarily. ++ Reset rounding mode bits. */ ++ fpc_new = fpc & ~(FPC_FLAGS_MASK | FPC_DXC_MASK | FPC_EXCEPTION_MASK ++ | FPC_RM_MASK); ++ ++ /* Set new rounding mode. */ ++ fpc_new |= (r & FPC_RM_MASK); ++ ++ /* Only set new environment if it has changed. */ ++ if (fpc_new != fpc) ++ _FPU_SETCW (fpc_new); ++} ++ ++#define libc_feholdexcept_setround libc_feholdexcept_setround_s390 ++#define libc_feholdexcept_setroundf libc_feholdexcept_setround_s390 ++#define libc_feholdexcept_setroundl libc_feholdexcept_setround_s390 ++ ++static __always_inline int ++libc_fetestexcept_s390 (int excepts) ++{ ++ int res; ++ fexcept_t fpc; ++ ++ _FPU_GETCW (fpc); ++ ++ /* Get current exceptions. */ ++ res = (fpc >> FPC_FLAGS_SHIFT) & FE_ALL_EXCEPT; ++ if ((fpc & FPC_NOT_FPU_EXCEPTION) == 0) ++ /* Bits 6, 7 of dxc-byte are zero, ++ thus bits 0-5 of dxc-byte correspond to the flag-bits. ++ Evaluate flags and last dxc-exception-code. */ ++ res |= (fpc >> FPC_DXC_SHIFT) & FE_ALL_EXCEPT; ++ ++ return res & excepts; ++} ++ ++#define libc_fetestexcept libc_fetestexcept_s390 ++#define libc_fetestexceptf libc_fetestexcept_s390 ++#define libc_fetestexceptl libc_fetestexcept_s390 ++ ++static __always_inline void ++libc_fesetenv_s390 (const fenv_t *envp) ++{ ++ _FPU_SETCW (envp->__fpc); ++} ++ ++#define libc_fesetenv libc_fesetenv_s390 ++#define libc_fesetenvf libc_fesetenv_s390 ++#define libc_fesetenvl libc_fesetenv_s390 ++ ++static __always_inline int ++libc_feupdateenv_test_s390 (const fenv_t *envp, int ex) ++{ ++ /* Get the currently raised exceptions. */ ++ int excepts; ++ fexcept_t fpc_old; ++ ++ _FPU_GETCW (fpc_old); ++ ++ /* Get current exceptions. */ ++ excepts = (fpc_old >> FPC_FLAGS_SHIFT) & FE_ALL_EXCEPT; ++ if ((fpc_old & FPC_NOT_FPU_EXCEPTION) == 0) ++ /* Bits 6, 7 of dxc-byte are zero, ++ thus bits 0-5 of dxc-byte correspond to the flag-bits. ++ Evaluate flags and last dxc-exception-code. */ ++ excepts |= (fpc_old >> FPC_DXC_SHIFT) & FE_ALL_EXCEPT; ++ ++ /* Merge the currently raised exceptions with those in envp. */ ++ fpu_control_t fpc_new = envp->__fpc; ++ fpc_new |= excepts << FPC_FLAGS_SHIFT; ++ ++ /* Install the new fpc from envp. */ ++ if (fpc_new != fpc_old) ++ _FPU_SETCW (fpc_new); ++ ++ /* Raise the exceptions if enabled in new fpc. */ ++ if (__glibc_unlikely ((fpc_new >> FPC_EXCEPTION_MASK_SHIFT) & excepts)) ++ __feraiseexcept (excepts); ++ ++ return excepts & ex; ++} ++ ++#define libc_feupdateenv_test libc_feupdateenv_test_s390 ++#define libc_feupdateenv_testf libc_feupdateenv_test_s390 ++#define libc_feupdateenv_testl libc_feupdateenv_test_s390 ++ ++static __always_inline void ++libc_feupdateenv_s390 (const fenv_t *envp) ++{ ++ libc_feupdateenv_test_s390 (envp, 0); ++} ++ ++#define libc_feupdateenv libc_feupdateenv_s390 ++#define libc_feupdateenvf libc_feupdateenv_s390 ++#define libc_feupdateenvl libc_feupdateenv_s390 ++ ++static __always_inline fenv_t ++libc_handle_user_fenv_s390 (const fenv_t *envp) ++{ ++ fenv_t env; ++ if (envp == FE_DFL_ENV) ++ { ++ env.__fpc = _FPU_DEFAULT; ++ } ++ else if (envp == FE_NOMASK_ENV) ++ { ++ env.__fpc = FPC_EXCEPTION_MASK; ++ } ++ else ++ env = (*envp); ++ ++ return env; ++} ++ ++/* We have support for rounding mode context. */ ++#define HAVE_RM_CTX 1 ++ ++static __always_inline void ++libc_feholdsetround_s390_ctx (struct rm_ctx *ctx, int r) ++{ ++ fpu_control_t fpc; ++ int round; ++ ++ _FPU_GETCW (fpc); ++ ctx->env.__fpc = fpc; ++ ++ /* Check whether rounding modes are different. */ ++ round = fpc & FPC_RM_MASK; ++ ++ /* Set the rounding mode if changed. */ ++ if (__glibc_unlikely (round != r)) ++ { ++ ctx->updated_status = true; ++ libc_fesetround_s390 (r); ++ } ++ else ++ ctx->updated_status = false; ++} ++ ++#define libc_feholdsetround_ctx libc_feholdsetround_s390_ctx ++#define libc_feholdsetroundf_ctx libc_feholdsetround_s390_ctx ++#define libc_feholdsetroundl_ctx libc_feholdsetround_s390_ctx ++ ++static __always_inline void ++libc_feresetround_s390_ctx (struct rm_ctx *ctx) ++{ ++ /* Restore the rounding mode if updated. */ ++ if (__glibc_unlikely (ctx->updated_status)) ++ { ++ fpu_control_t fpc; ++ _FPU_GETCW (fpc); ++ fpc = ctx->env.__fpc | (fpc & FPC_FLAGS_MASK); ++ _FPU_SETCW (fpc); ++ } ++} ++ ++#define libc_feresetround_ctx libc_feresetround_s390_ctx ++#define libc_feresetroundf_ctx libc_feresetround_s390_ctx ++#define libc_feresetroundl_ctx libc_feresetround_s390_ctx ++ ++static __always_inline void ++libc_feholdsetround_noex_s390_ctx (struct rm_ctx *ctx, int r) ++{ ++ libc_feholdexcept_setround_s390 (&ctx->env, r); ++} ++ ++#define libc_feholdsetround_noex_ctx libc_feholdsetround_noex_s390_ctx ++#define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_s390_ctx ++#define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_s390_ctx ++ ++static __always_inline void ++libc_feresetround_noex_s390_ctx (struct rm_ctx *ctx) ++{ ++ /* Restore exception flags and rounding mode. */ ++ libc_fesetenv_s390 (&ctx->env); ++} ++ ++#define libc_feresetround_noex_ctx libc_feresetround_noex_s390_ctx ++#define libc_feresetround_noexf_ctx libc_feresetround_noex_s390_ctx ++#define libc_feresetround_noexl_ctx libc_feresetround_noex_s390_ctx ++ ++#endif +diff --git a/sysdeps/s390/fpu/math_private.h b/sysdeps/s390/fpu/math_private.h +index a1ae91a87c..f3c770d59a 100644 +--- a/sysdeps/s390/fpu/math_private.h ++++ b/sysdeps/s390/fpu/math_private.h +@@ -48,6 +48,7 @@ converttoint (double_t x) + } + #endif + ++#include + #include_next + + #endif +-- +2.18.2 + diff --git a/glibc-rh1780204-28.patch b/glibc-rh1780204-28.patch new file mode 100755 index 0000000..d2b165a --- /dev/null +++ b/glibc-rh1780204-28.patch @@ -0,0 +1,317 @@ +From 2ab6ce8252a14e6ef0cfb33046dd565ae15085c2 Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:32 +0100 +Subject: [PATCH 28/28] S390: Use libc_fe* macros in fe* functions. + +This patch updates the s390 specific functions fegetround, +fesetround, feholdexcept, fesetenv, feupdateenv, fegetexceptflag, +fetestexcept, fesetexceptflag, fetestexceptflag. +Now those functions are using the libc_fe* macros if possible. + +Furthermore fegetexceptflag is now returning the exception from +dxc field shifted to the usual exception-flags. +Thus a special fetestexceptflag implementation is not needed anymore. + +(cherry picked from commit 238adf59db85646ebae47876819bd896dae597bc) +--- + sysdeps/s390/fpu/fegetround.c | 9 ++------- + sysdeps/s390/fpu/feholdexcpt.c | 12 ++--------- + sysdeps/s390/fpu/fesetenv.c | 21 +++---------------- + sysdeps/s390/fpu/fesetround.c | 9 +++------ + sysdeps/s390/fpu/fetestexceptflag.c | 31 ----------------------------- + sysdeps/s390/fpu/feupdateenv.c | 14 +++---------- + sysdeps/s390/fpu/fgetexcptflg.c | 16 ++------------- + sysdeps/s390/fpu/fsetexcptflg.c | 23 ++++++++++----------- + sysdeps/s390/fpu/ftestexcept.c | 16 ++------------- + 9 files changed, 27 insertions(+), 124 deletions(-) + delete mode 100644 sysdeps/s390/fpu/fetestexceptflag.c + +diff --git a/sysdeps/s390/fpu/fegetround.c b/sysdeps/s390/fpu/fegetround.c +index 3c38bc9189..f1be1d12e1 100644 +--- a/sysdeps/s390/fpu/fegetround.c ++++ b/sysdeps/s390/fpu/fegetround.c +@@ -17,17 +17,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#include +-#include ++#include + + int + __fegetround (void) + { +- fexcept_t cw; +- +- _FPU_GETCW (cw); +- +- return cw & FPC_RM_MASK; ++ return get_rounding_mode (); + } + libm_hidden_def (__fegetround) + weak_alias (__fegetround, fegetround) +diff --git a/sysdeps/s390/fpu/feholdexcpt.c b/sysdeps/s390/fpu/feholdexcpt.c +index 5daee5675d..48af7ff51b 100644 +--- a/sysdeps/s390/fpu/feholdexcpt.c ++++ b/sysdeps/s390/fpu/feholdexcpt.c +@@ -17,19 +17,11 @@ + License along with the GNU C Library; if not, see + . */ + +-#include +-#include ++#include + + int __feholdexcept (fenv_t *envp) + { +- fexcept_t fpc; +- /* Store the environment. */ +- __fegetenv (envp); +- /* Clear the current sticky bits as more than one exception +- may be generated. */ +- fpc = envp->__fpc & ~(FPC_FLAGS_MASK | FPC_DXC_MASK); +- /* Hold from generating fpu exceptions temporarily. */ +- _FPU_SETCW ((fpc & ~(FE_ALL_EXCEPT << FPC_EXCEPTION_MASK_SHIFT))); ++ libc_feholdexcept_s390 (envp); + return 0; + } + libm_hidden_def (__feholdexcept) +diff --git a/sysdeps/s390/fpu/fesetenv.c b/sysdeps/s390/fpu/fesetenv.c +index c6c275d79d..54ba2aa94a 100644 +--- a/sysdeps/s390/fpu/fesetenv.c ++++ b/sysdeps/s390/fpu/fesetenv.c +@@ -17,28 +17,13 @@ + License along with the GNU C Library; if not, see + . */ + +-#include +-#include +-#include +-#include ++#include + + int + __fesetenv (const fenv_t *envp) + { +- fenv_t env; +- +- if (envp == FE_DFL_ENV) +- { +- env.__fpc = _FPU_DEFAULT; +- } +- else if (envp == FE_NOMASK_ENV) +- { +- env.__fpc = FPC_EXCEPTION_MASK; +- } +- else +- env = (*envp); +- +- _FPU_SETCW (env.__fpc); ++ fenv_t env = libc_handle_user_fenv_s390 (envp); ++ libc_fesetenv_s390 (&env); + + /* Success. */ + return 0; +diff --git a/sysdeps/s390/fpu/fesetround.c b/sysdeps/s390/fpu/fesetround.c +index d8a84d2c96..0a7fe2635b 100644 +--- a/sysdeps/s390/fpu/fesetround.c ++++ b/sysdeps/s390/fpu/fesetround.c +@@ -17,21 +17,18 @@ + License along with the GNU C Library; if not, see + . */ + +-#include +-#include ++#include + + int + __fesetround (int round) + { +- if ((round|FPC_RM_MASK) != FPC_RM_MASK) ++ if ((round | FPC_RM_MASK) != FPC_RM_MASK) + { + /* ROUND is not a valid rounding mode. */ + return 1; + } +- __asm__ __volatile__ ("srnm 0(%0)" +- : +- : "a" (round)); + ++ libc_fesetround_s390 (round); + return 0; + } + libm_hidden_def (__fesetround) +diff --git a/sysdeps/s390/fpu/fetestexceptflag.c b/sysdeps/s390/fpu/fetestexceptflag.c +deleted file mode 100644 +index 784d356f7b..0000000000 +--- a/sysdeps/s390/fpu/fetestexceptflag.c ++++ /dev/null +@@ -1,31 +0,0 @@ +-/* Test exception in saved exception state. S/390 version. +- Copyright (C) 2016-2018 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 +- . */ +- +-#include +-#include +- +-int +-fetestexceptflag (const fexcept_t *flagp, int excepts) +-{ +- /* As *flagp is obtained by an earlier call of fegetexceptflag the +- bits 0-5 of dxc-byte are either zero or correspond to the +- flag-bits. Evaluate flags and last dxc-exception-code. */ +- return (((*flagp >> FPC_FLAGS_SHIFT) | (*flagp >> FPC_DXC_SHIFT)) +- & excepts +- & FE_ALL_EXCEPT); +-} +diff --git a/sysdeps/s390/fpu/feupdateenv.c b/sysdeps/s390/fpu/feupdateenv.c +index 4888e1a864..f6b3d7d2de 100644 +--- a/sysdeps/s390/fpu/feupdateenv.c ++++ b/sysdeps/s390/fpu/feupdateenv.c +@@ -18,21 +18,13 @@ + . */ + + +-#include +-#include ++#include + + int + __feupdateenv (const fenv_t *envp) + { +- fexcept_t temp; +- +- _FPU_GETCW (temp); +- temp = (temp & FPC_FLAGS_MASK) >> FPC_FLAGS_SHIFT; +- +- /* Raise the exceptions since the last call to feholdenv */ +- /* re install saved environment. */ +- __fesetenv (envp); +- __feraiseexcept ((int) temp); ++ fenv_t env = libc_handle_user_fenv_s390 (envp); ++ libc_feupdateenv_s390 (&env); + + /* Success. */ + return 0; +diff --git a/sysdeps/s390/fpu/fgetexcptflg.c b/sysdeps/s390/fpu/fgetexcptflg.c +index 2a0f6dc77c..1985b396c9 100644 +--- a/sysdeps/s390/fpu/fgetexcptflg.c ++++ b/sysdeps/s390/fpu/fgetexcptflg.c +@@ -17,24 +17,12 @@ + License along with the GNU C Library; if not, see + . */ + +-#include +-#include ++#include + + int + fegetexceptflag (fexcept_t *flagp, int excepts) + { +- fexcept_t temp, newexcepts; +- +- /* Get the current exceptions. */ +- _FPU_GETCW (temp); +- newexcepts = excepts << FPC_FLAGS_SHIFT; +- if ((temp & FPC_NOT_FPU_EXCEPTION) == 0) +- /* Bits 6, 7 of dxc-byte are zero, +- thus bits 0-5 of dxc-byte correspond to the flag-bits. +- Evaluate flags and last dxc-exception-code. */ +- newexcepts |= excepts << FPC_DXC_SHIFT; +- +- *flagp = temp & newexcepts; ++ *flagp = libc_fetestexcept_s390 (excepts); + + /* Success. */ + return 0; +diff --git a/sysdeps/s390/fpu/fsetexcptflg.c b/sysdeps/s390/fpu/fsetexcptflg.c +index e50684c574..51d258cf17 100644 +--- a/sysdeps/s390/fpu/fsetexcptflg.c ++++ b/sysdeps/s390/fpu/fsetexcptflg.c +@@ -24,29 +24,26 @@ + int + fesetexceptflag (const fexcept_t *flagp, int excepts) + { +- fexcept_t temp, newexcepts; ++ fexcept_t fpc, fpc_new; + + /* Get the current environment. We have to do this since we cannot + separately set the status word. */ +- _FPU_GETCW (temp); +- /* Install the new exception bits in the Accrued Exception Byte. */ +- excepts = excepts & FE_ALL_EXCEPT; +- newexcepts = excepts << FPC_FLAGS_SHIFT; +- temp &= ~newexcepts; +- if ((temp & FPC_NOT_FPU_EXCEPTION) == 0) ++ _FPU_GETCW (fpc); ++ ++ /* Clear the current exception bits. */ ++ fpc_new = fpc & ~((excepts & FE_ALL_EXCEPT) << FPC_FLAGS_SHIFT); ++ if ((fpc & FPC_NOT_FPU_EXCEPTION) == 0) + /* Bits 6, 7 of dxc-byte are zero, + thus bits 0-5 of dxc-byte correspond to the flag-bits. + Clear given exceptions in dxc-field. */ +- temp &= ~(excepts << FPC_DXC_SHIFT); ++ fpc_new &= ~((excepts & FE_ALL_EXCEPT) << FPC_DXC_SHIFT); + +- /* Integrate dxc-byte of flagp into flags. The dxc-byte of flagp contains +- either an ieee-exception or 0 (see fegetexceptflag). */ +- temp |= (*flagp | ((*flagp >> FPC_DXC_SHIFT) << FPC_FLAGS_SHIFT)) +- & newexcepts; ++ /* Set exceptions from flagp in flags-field. */ ++ fpc_new |= (*flagp & excepts & FE_ALL_EXCEPT) << FPC_FLAGS_SHIFT; + + /* Store the new status word (along with the rest of the environment. + Possibly new exceptions are set but they won't get executed. */ +- _FPU_SETCW (temp); ++ _FPU_SETCW (fpc_new); + + /* Success. */ + return 0; +diff --git a/sysdeps/s390/fpu/ftestexcept.c b/sysdeps/s390/fpu/ftestexcept.c +index 727b9b342d..f2acecc1af 100644 +--- a/sysdeps/s390/fpu/ftestexcept.c ++++ b/sysdeps/s390/fpu/ftestexcept.c +@@ -17,23 +17,11 @@ + License along with the GNU C Library; if not, see + . */ + +-#include +-#include ++#include + + int + fetestexcept (int excepts) + { +- fexcept_t temp, res; +- +- /* Get current exceptions. */ +- _FPU_GETCW (temp); +- res = temp >> FPC_FLAGS_SHIFT; +- if ((temp & FPC_NOT_FPU_EXCEPTION) == 0) +- /* Bits 6, 7 of dxc-byte are zero, +- thus bits 0-5 of dxc-byte correspond to the flag-bits. +- Evaluate flags and last dxc-exception-code. */ +- res |= temp >> FPC_DXC_SHIFT; +- +- return res & excepts & FE_ALL_EXCEPT; ++ return libc_fetestexcept_s390 (excepts); + } + libm_hidden_def (fetestexcept) +-- +2.18.2 + diff --git a/glibc-rh1780204-29.patch b/glibc-rh1780204-29.patch new file mode 100755 index 0000000..cf88bee --- /dev/null +++ b/glibc-rh1780204-29.patch @@ -0,0 +1,160 @@ +From af123aa95091d3d2d1b4ff027cf806ca1721d29d Mon Sep 17 00:00:00 2001 +From: Stefan Liebler +Date: Wed, 11 Dec 2019 15:09:14 +0100 +Subject: [PATCH 01/28] Always use wordsize-64 version of s_nearbyint.c. + +This patch replaces s_nearbyint.c in sysdeps/dbl-64 with the one in +sysdeps/dbl-64/wordsize-64 and removes the latter one. +The code is not changed except changes in code style. + +Also adjusted the include path in x86_64 file. + +Reviewed-by: Adhemerval Zanella +--- + sysdeps/ieee754/dbl-64/s_nearbyint.c | 38 ++++++-------- + sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c | 65 ------------------------ + sysdeps/x86_64/fpu/multiarch/s_nearbyint-c.c | 2 +- + 3 files changed, 17 insertions(+), 88 deletions(-) + delete mode 100644 sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c + +Note: tweaked by DJ for backport; some portions handled by glibc-rh1780204-07.patch + +diff -rupN a/sysdeps/ieee754/dbl-64/s_nearbyint.c b/sysdeps/ieee754/dbl-64/s_nearbyint.c +--- a/sysdeps/ieee754/dbl-64/s_nearbyint.c 2020-04-09 21:17:04.281854809 -0400 ++++ b/sysdeps/ieee754/dbl-64/s_nearbyint.c 2020-04-09 21:28:13.380741798 -0400 +@@ -10,10 +10,6 @@ + * ==================================================== + */ + +-#if defined(LIBM_SCCS) && !defined(lint) +-static char rcsid[] = "$NetBSD: s_rint.c,v 1.8 1995/05/10 20:48:04 jtc Exp $"; +-#endif +- + /* + * rint(x) + * Return x rounded to integral value according to the prevailing +@@ -44,35 +40,33 @@ __nearbyint (double x) + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ + }; + fenv_t env; +- int32_t i0, j0, sx; +- double w, t; +- GET_HIGH_WORD (i0, x); +- sx = (i0 >> 31) & 1; +- j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; +- if (j0 < 52) ++ int64_t i0, sx; ++ int32_t j0; ++ EXTRACT_WORDS64 (i0, x); ++ sx = (i0 >> 63) & 1; ++ j0 = ((i0 >> 52) & 0x7ff) - 0x3ff; ++ if (__glibc_likely (j0 < 52)) + { + if (j0 < 0) + { + libc_feholdexcept (&env); +- w = TWO52[sx] + math_opt_barrier (x); +- t = w - TWO52[sx]; ++ double w = TWO52[sx] + math_opt_barrier (x); ++ double t = w - TWO52[sx]; + math_force_eval (t); + libc_fesetenv (&env); +- GET_HIGH_WORD (i0, t); +- SET_HIGH_WORD (t, (i0 & 0x7fffffff) | (sx << 31)); +- return t; ++ return copysign (t, x); + } + } + else + { + if (j0 == 0x400) +- return x + x; /* inf or NaN */ ++ return x + x; /* inf or NaN */ + else +- return x; /* x is integral */ ++ return x; /* x is integral */ + } + libc_feholdexcept (&env); +- w = TWO52[sx] + math_opt_barrier (x); +- t = w - TWO52[sx]; ++ double w = TWO52[sx] + math_opt_barrier (x); ++ double t = w - TWO52[sx]; + math_force_eval (t); + libc_fesetenv (&env); + return t; +diff -rupN a/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c +--- a/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,64 +0,0 @@ +-/* Adapted for use as nearbyint by Ulrich Drepper . */ +-/* +- * ==================================================== +- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +- * +- * Developed at SunPro, a Sun Microsystems, Inc. business. +- * Permission to use, copy, modify, and distribute this +- * software is freely granted, provided that this notice +- * is preserved. +- * ==================================================== +- */ +- +-/* +- * rint(x) +- * Return x rounded to integral value according to the prevailing +- * rounding mode. +- * Method: +- * Using floating addition. +- * Exception: +- * Inexact flag raised if x not equal to rint(x). +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-static const double +-TWO52[2]={ +- 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ +- -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +-}; +- +-double +-__nearbyint(double x) +-{ +- fenv_t env; +- int64_t i0,sx; +- int32_t j0; +- EXTRACT_WORDS64(i0,x); +- sx = (i0>>63)&1; +- j0 = ((i0>>52)&0x7ff)-0x3ff; +- if(__builtin_expect(j0<52, 1)) { +- if(j0<0) { +- libc_feholdexcept (&env); +- double w = TWO52[sx] + math_opt_barrier (x); +- double t = w-TWO52[sx]; +- math_force_eval (t); +- libc_fesetenv (&env); +- return __copysign (t, x); +- } +- } else { +- if(j0==0x400) return x+x; /* inf or NaN */ +- else return x; /* x is integral */ +- } +- libc_feholdexcept (&env); +- double w = TWO52[sx] + math_opt_barrier (x); +- double t = w-TWO52[sx]; +- math_force_eval (t); +- libc_fesetenv (&env); +- return t; +-} +-libm_alias_double (__nearbyint, nearbyint) +diff -rupN a/sysdeps/x86_64/fpu/multiarch/s_nearbyint-c.c b/sysdeps/x86_64/fpu/multiarch/s_nearbyint-c.c +--- a/sysdeps/x86_64/fpu/multiarch/s_nearbyint-c.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/sysdeps/x86_64/fpu/multiarch/s_nearbyint-c.c 2020-04-09 21:28:13.205735274 -0400 +@@ -1,3 +1,3 @@ + #undef __nearbyint + #define __nearbyint __nearbyint_c +-#include ++#include diff --git a/glibc-rh1783303-1.patch b/glibc-rh1783303-1.patch new file mode 100755 index 0000000..89fe806 --- /dev/null +++ b/glibc-rh1783303-1.patch @@ -0,0 +1,1188 @@ +commit 6cac323c8dd78668e65aaa29f044cbd33c1a66a5 +Author: Adhemerval Zanella +Date: Fri Mar 15 18:42:00 2019 +0000 + + powerpc: ceil/ceilf refactor + + This patches consolidates all the powerpc ceil{f} implementations on + the generic sysdeps/powerpc/fpu/s_ceil{f}. The generic implementation + uses either the compiler builts for ISA 2.03+ (which generates the frip + instruction) or a generic implementation which uses FP only operations. + + It adds a generic implementation (round_to_integer.h) which is shared + with other rounding to integer routines. The resulting code should be + similar in term os performance to previous assembly one. + + The IFUNC organization for powerpc64 is also change to be enabled only + for powerpc64 and not for powerpc64le (since minium ISA of 2.08 does not + require the fallback generic implementation). + + Checked on powerpc-linux-gnu (built without --with-cpu, with + --with-cpu=power4 and with --with-cpu=power5+ and --disable-multi-arch), + powerpc64-linux-gnu (built without --with-cp and with --with-cpu=power5+ + and --disable-multi-arch). + + * sysdeps/powerpc/fpu/fenv_libc.h (__fesetround_inline_nocheck): New + function. + * sysdeps/powerpc/fpu/round_to_integer.h: New file. + * sysdeps/powerpc/fpu/s_ceil.c: Likewise. + * sysdeps/powerpc/fpu/s_ceilf.c: Likewise. + * sysdeps/powerpc/powerpc32/fpu/s_ceil.S: Remove file. + * sysdeps/powerpc/powerpc32/fpu/s_ceilf.S: Likewise. + * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/Makefile + (CFLAGS-s_ceil-power5+.c, CFLAGS-s_ceilf-power5+.c): New rule. + * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-power5+.S: + Remove file. + * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-ppc32.S: + Likewise. + * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-power5+.S: + Likewise. + * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-ppc32.S: + Likewise. + * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-power5+.c: + New file. + * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-ppc32.c: + Likewise. + * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-power5+.c: + Likewise. + * sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-ppc32.c: + Likewise. + * sysdeps/powerpc/powerpc32/power5+/fpu/s_ceil.S: Remove file. + * sysdeps/powerpc/powerpc32/power5+/fpu/s_ceilf.S: Likewise. + * sysdeps/powerpc/powerpc64/be/fpu/multiarch/Makefile: New file. + * sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceil-power5+.c: + Likewise. + * sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceil-ppc64.c: + Likewise. + * sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil.c: Move to ... + * sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceil.c: ... here. + * sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceilf-power5+.c: New + file. + * sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceilf-ppc64.c: + Likewise. + * sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf.c: Move to ... + * sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceilf.c: ... + * here. + * sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile + (libm-sysdep_routines): Remove s_ceil-power5+, s_ceil-ppc64, + s_ceilf-power5+, and s_ceilf-ppc64. + * sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil-power5+.S: Remove + file. + * sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil-ppc64.S: Likewise. + * sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf-power5+.S: Likewise. + * sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf-ppc64.S: Likewise. + * sysdeps/powerpc/powerpc64/fpu/s_ceil.S: Likewise. + * sysdeps/powerpc/powerpc64/fpu/s_ceilf.S: Likewise. + * sysdeps/powerpc/powerpc64/power5+/fpu/s_ceil.S: Likewise. + * sysdeps/powerpc/powerpc64/power5+/fpu/s_ceilf.S: Likewise. + + Reviewed-by: Gabriel F. T. Gomes + +Conflicts: + sysdeps/powerpc/powerpc32/fpu/s_ceil.S + sysdeps/powerpc/powerpc32/fpu/s_ceilf.S + sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-power5+.S + sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-ppc32.S + sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-power5+.S + sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-ppc32.S + sysdeps/powerpc/powerpc32/power5+/fpu/s_ceil.S + sysdeps/powerpc/powerpc32/power5+/fpu/s_ceilf.S + sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil-power5+.S + sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil-ppc64.S + sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf-power5+.S + sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf-ppc64.S + sysdeps/powerpc/powerpc64/fpu/s_ceil.S + sysdeps/powerpc/powerpc64/fpu/s_ceilf.S + sysdeps/powerpc/powerpc64/power5+/fpu/s_ceil.S + sysdeps/powerpc/powerpc64/power5+/fpu/s_ceilf.S + (Removal after the copyright year header change upstream.) + +diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h +index 4c19d12b0b31c1f9..a0128c66444a3e46 100644 +--- a/sysdeps/powerpc/fpu/fenv_libc.h ++++ b/sysdeps/powerpc/fpu/fenv_libc.h +@@ -98,6 +98,14 @@ __fesetround_inline (int round) + return 0; + } + ++/* Same as __fesetround_inline, however without runtime check to use DFP ++ mtfsfi syntax (as relax_fenv_state) or if round value is valid. */ ++static inline void ++__fesetround_inline_nocheck (const int round) ++{ ++ asm volatile ("mtfsfi 7,%0" : : "i" (round)); ++} ++ + /* Definitions of all the FPSCR bit numbers */ + enum { + FPSCR_FX = 0, /* exception summary */ +diff --git a/sysdeps/powerpc/fpu/round_to_integer.h b/sysdeps/powerpc/fpu/round_to_integer.h +new file mode 100644 +index 0000000000000000..c70afbb10f600d81 +--- /dev/null ++++ b/sysdeps/powerpc/fpu/round_to_integer.h +@@ -0,0 +1,105 @@ ++/* Round to integer generic 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 Library General Public License as ++ published by the Free Software Foundation; either version 2 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 ++ Library General Public License for more details. ++ ++ You should have received a copy of the GNU Library General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If ++ not, see . */ ++ ++#ifndef _ROUND_TO_INTEGER_H ++#define _ROUND_TO_INTEGER_H ++ ++#include ++ ++enum round_mode ++{ ++ CEIL ++}; ++ ++static inline void ++set_fenv_mode (enum round_mode mode) ++{ ++ int rmode; ++ switch (mode) ++ { ++ case CEIL: rmode = FE_UPWARD; break; ++ default: rmode = FE_TONEAREST; break; ++ } ++ __fesetround_inline_nocheck (rmode); ++} ++ ++static inline float ++round_to_integer_float (enum round_mode mode, float x) ++{ ++ /* Ensure sNaN input is converted to qNaN. */ ++ if (__glibc_unlikely (isnan (x))) ++ return x + x; ++ ++ if (fabs (x) > 0x1p+23) ++ return x; ++ ++ float r = x; ++ ++ /* Save current FPU rounding mode and inexact state. */ ++ fenv_t fe = fegetenv_register (); ++ set_fenv_mode (mode); ++ if (x > 0.0) ++ { ++ r += 0x1p+23; ++ r -= 0x1p+23; ++ r = fabs (r); ++ } ++ else if (x < 0.0) ++ { ++ r -= 0x1p+23; ++ r += 0x1p+23; ++ r = -fabs (r); ++ } ++ __builtin_mtfsf (0xff, fe); ++ ++ return r; ++} ++ ++static inline double ++round_to_integer_double (enum round_mode mode, double x) ++{ ++ /* Ensure sNaN input is converted to qNaN. */ ++ if (__glibc_unlikely (isnan (x))) ++ return x + x; ++ ++ if (fabs (x) > 0x1p+52) ++ return x; ++ ++ double r = x; ++ ++ /* Save current FPU rounding mode and inexact state. */ ++ fenv_t fe = fegetenv_register (); ++ set_fenv_mode (mode); ++ if (x > 0.0) ++ { ++ r += 0x1p+52; ++ r -= 0x1p+52; ++ r = fabs (r); ++ } ++ else if (x < 0.0) ++ { ++ r -= 0x1p+52; ++ r += 0x1p+52; ++ r = -fabs (r); ++ } ++ __builtin_mtfsf (0xff, fe); ++ ++ return r; ++} ++ ++#endif +diff --git a/sysdeps/powerpc/fpu/s_ceil.c b/sysdeps/powerpc/fpu/s_ceil.c +new file mode 100644 +index 0000000000000000..49008c7af87d6d55 +--- /dev/null ++++ b/sysdeps/powerpc/fpu/s_ceil.c +@@ -0,0 +1,35 @@ ++/* Smallest integral value not less than argument. PowerPC 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 Library General Public License as ++ published by the Free Software Foundation; either version 2 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 ++ Library General Public License for more details. ++ ++ You should have received a copy of the GNU Library General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If ++ not, see . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++double ++__ceil (double x) ++{ ++#ifdef _ARCH_PWR5X ++ return __builtin_ceil (x); ++#else ++ return round_to_integer_double (CEIL, x); ++#endif ++} ++#ifndef __ceil ++libm_alias_double (__ceil, ceil) ++#endif +diff --git a/sysdeps/powerpc/fpu/s_ceilf.c b/sysdeps/powerpc/fpu/s_ceilf.c +new file mode 100644 +index 0000000000000000..8c86bf30a34df4cf +--- /dev/null ++++ b/sysdeps/powerpc/fpu/s_ceilf.c +@@ -0,0 +1,35 @@ ++/* Smallest integral value not less than argument. PowerPC 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 Library General Public License as ++ published by the Free Software Foundation; either version 2 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 ++ Library General Public License for more details. ++ ++ You should have received a copy of the GNU Library General Public ++ License along with the GNU C Library; see the file COPYING.LIB. If ++ not, see . */ ++ ++#define NO_MATH_REDIRECT ++#include ++#include ++#include ++ ++float ++__ceilf (float x) ++{ ++#ifdef _ARCH_PWR5X ++ return __builtin_ceilf (x); ++#else ++ return round_to_integer_float (CEIL, x); ++#endif ++} ++#ifndef __ceilf ++libm_alias_float (__ceil, ceil) ++#endif +diff --git a/sysdeps/powerpc/powerpc32/fpu/s_ceil.S b/sysdeps/powerpc/powerpc32/fpu/s_ceil.S +deleted file mode 100644 +index 7f2f97ada1a14a52..0000000000000000 +--- a/sysdeps/powerpc/powerpc32/fpu/s_ceil.S ++++ /dev/null +@@ -1,76 +0,0 @@ +-/* ceil function. PowerPC32 version. +- Copyright (C) 2004-2018 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 +- . */ +- +-#include +-#include +-#include +- +- .section .rodata.cst4,"aM",@progbits,4 +- .align 2 +-.LC0: /* 2**52 */ +- .long 0x59800000 +- +- .section ".text" +-ENTRY (__ceil) +-#ifdef SHARED +- mflr r11 +- cfi_register(lr,r11) +- SETUP_GOT_ACCESS(r9,got_label) +- addis r9,r9,.LC0-got_label@ha +- lfs fp13,.LC0-got_label@l(r9) +- mtlr r11 +- cfi_same_value (lr) +-#else +- lis r9,.LC0@ha +- lfs fp13,.LC0@l(r9) +-#endif +- fabs fp0,fp1 +- fsub fp12,fp13,fp13 /* generate 0.0 */ +- fcmpu cr7,fp0,fp13 /* if (fabs(x) > TWO52) */ +- mffs fp11 /* Save current FPU rounding mode and +- "inexact" state. */ +- fcmpu cr6,fp1,fp12 /* if (x > 0.0) */ +- bnl- cr7,.L10 +- mtfsfi 7,2 /* Set rounding mode toward +inf. */ +- ble- cr6,.L4 +- fadd fp1,fp1,fp13 /* x+= TWO52; */ +- fsub fp1,fp1,fp13 /* x-= TWO52; */ +- fabs fp1,fp1 /* if (x == 0.0) */ +- /* x = 0.0; */ +- mtfsf 0xff,fp11 /* Restore previous rounding mode and +- "inexact" state. */ +- blr +-.L4: +- bge- cr6,.L9 /* if (x < 0.0) */ +- fsub fp1,fp1,fp13 /* x-= TWO52; */ +- fadd fp1,fp1,fp13 /* x+= TWO52; */ +- fnabs fp1,fp1 /* if (x == 0.0) */ +- /* x = -0.0; */ +-.L9: +- mtfsf 0xff,fp11 /* Restore previous rounding mode and +- "inexact" state. */ +- blr +-.L10: +- /* Ensure sNaN input is converted to qNaN. */ +- fcmpu cr7,fp1,fp1 +- beqlr cr7 +- fadd fp1,fp1,fp1 +- blr +- END (__ceil) +- +-libm_alias_double (__ceil, ceil) +diff --git a/sysdeps/powerpc/powerpc32/fpu/s_ceilf.S b/sysdeps/powerpc/powerpc32/fpu/s_ceilf.S +deleted file mode 100644 +index 3f5949004fa51baf..0000000000000000 +--- a/sysdeps/powerpc/powerpc32/fpu/s_ceilf.S ++++ /dev/null +@@ -1,76 +0,0 @@ +-/* float ceil function. PowerPC32 version. +- Copyright (C) 2004-2018 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 +- . */ +- +-#include +-#include +- +- .section .rodata.cst4,"aM",@progbits,4 +- .align 2 +-.LC0: /* 2**23 */ +- .long 0x4b000000 +- +- .section ".text" +-ENTRY (__ceilf) +-#ifdef SHARED +- mflr r11 +- cfi_register(lr,r11) +- SETUP_GOT_ACCESS(r9,got_label) +- addis r9,r9,.LC0-got_label@ha +- lfs fp13,.LC0-got_label@l(r9) +- mtlr r11 +- cfi_same_value (lr) +-#else +- lis r9,.LC0@ha +- lfs fp13,.LC0@l(r9) +-#endif +- fabs fp0,fp1 +- fsubs fp12,fp13,fp13 /* generate 0.0 */ +- fcmpu cr7,fp0,fp13 /* if (fabs(x) > TWO23) */ +- mffs fp11 /* Save current FPU rounding mode and +- "inexact" state. */ +- fcmpu cr6,fp1,fp12 /* if (x > 0.0) */ +- bnl- cr7,.L10 +- mtfsfi 7,2 /* Set rounding mode toward +inf. */ +- ble- cr6,.L4 +- fadds fp1,fp1,fp13 /* x+= TWO23; */ +- fsubs fp1,fp1,fp13 /* x-= TWO23; */ +- fabs fp1,fp1 /* if (x == 0.0) */ +- /* x = 0.0; */ +- mtfsf 0xff,fp11 /* Restore previous rounding mode and +- "inexact" state. */ +- blr +-.L4: +- bge- cr6,.L9 /* if (x < 0.0) */ +- fsubs fp1,fp1,fp13 /* x-= TWO23; */ +- fadds fp1,fp1,fp13 /* x+= TWO23; */ +- fnabs fp1,fp1 /* if (x == 0.0) */ +- /* x = -0.0; */ +-.L9: +- mtfsf 0xff,fp11 /* Restore previous rounding mode and +- "inexact" state. */ +- blr +-.L10: +- /* Ensure sNaN input is converted to qNaN. */ +- fcmpu cr7,fp1,fp1 +- beqlr cr7 +- fadds fp1,fp1,fp1 +- blr +- END (__ceilf) +- +-libm_alias_float (__ceil, ceil) +- +diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/Makefile b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/Makefile +index 4e85021d50831eb6..cf38e347f2da74e9 100644 +--- a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/Makefile +@@ -26,6 +26,8 @@ libm-sysdep_routines += s_llrintf-power6 s_llrintf-ppc32 s_llrint-power6 \ + s_logbf-power7 s_logbf-ppc32 e_hypot-power7 \ + e_hypot-ppc32 e_hypotf-power7 e_hypotf-ppc32 + ++CFLAGS-s_ceil-power5+.c = -mcpu=power5+ ++CFLAGS-s_ceilf-power5+.c = -mcpu=power5+ + CFLAGS-s_modf-power5+.c = -mcpu=power5+ + CFLAGS-s_modff-power5+.c = -mcpu=power5+ + CFLAGS-s_logbl-power7.c = -mcpu=power7 +diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-power5+.S b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-power5+.S +deleted file mode 100644 +index b8181585a869bd8a..0000000000000000 +--- a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-power5+.S ++++ /dev/null +@@ -1,33 +0,0 @@ +-/* ceil function. PowerPC32/power5+ version. +- Copyright (C) 2013-2018 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 +- . */ +- +-#include +-#include +- +-#undef hidden_def +-#define hidden_def(name) +-#undef weak_alias +-#define weak_alias(name, alias) +-#undef strong_alias +-#define strong_alias(name, alias) +-#undef compat_symbol +-#define compat_symbol(lib, name, alias, ver) +- +-#define __ceil __ceil_power5plus +- +-#include +diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-power5+.c b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-power5+.c +new file mode 100644 +index 0000000000000000..87bc66cdb0322c59 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-power5+.c +@@ -0,0 +1,3 @@ ++#include ++#define __ceil __ceil_power5plus ++#include +diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-ppc32.S b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-ppc32.S +deleted file mode 100644 +index cd2bc69b677e76db..0000000000000000 +--- a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-ppc32.S ++++ /dev/null +@@ -1,31 +0,0 @@ +-/* ceil function. PowerPC32 default version. +- Copyright (C) 2013-2018 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 +- . */ +- +-#include +-#include +- +-#undef weak_alias +-#define weak_alias(a,b) +-#undef strong_alias +-#define strong_alias(a,b) +-#undef compat_symbol +-#define compat_symbol(a,b,c,d) +- +-#define __ceil __ceil_ppc32 +- +-#include +diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-ppc32.c b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-ppc32.c +new file mode 100644 +index 0000000000000000..93c098476b915f9d +--- /dev/null ++++ b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceil-ppc32.c +@@ -0,0 +1,3 @@ ++#include ++#define __ceil __ceil_ppc32 ++#include +diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-power5+.S b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-power5+.S +deleted file mode 100644 +index d01aa6e7db3d0b9d..0000000000000000 +--- a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-power5+.S ++++ /dev/null +@@ -1,26 +0,0 @@ +-/* ceilf function. PowerPC32/power5+ version. +- Copyright (C) 2013-2018 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 +- . */ +- +-#include +- +-#undef weak_alias +-#define weak_alias(name, alias) +- +-#define __ceilf __ceilf_power5plus +- +-#include +diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-power5+.c b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-power5+.c +new file mode 100644 +index 0000000000000000..a5bfa98535c088a0 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-power5+.c +@@ -0,0 +1,3 @@ ++#include ++#define __ceilf __ceilf_power5plus ++#include +diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-ppc32.S b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-ppc32.S +deleted file mode 100644 +index 264e032b3b27f9b3..0000000000000000 +--- a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-ppc32.S ++++ /dev/null +@@ -1,27 +0,0 @@ +-/* ceilf function. PowerPC32 default version. +- Copyright (C) 2013-2018 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 +- . */ +- +-#include +-#include +- +-#undef weak_alias +-#define weak_alias(a,b) +- +-#define __ceilf __ceilf_ppc32 +- +-#include +diff --git a/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-ppc32.c b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-ppc32.c +new file mode 100644 +index 0000000000000000..a4dcdcb4069289d6 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc32/power4/fpu/multiarch/s_ceilf-ppc32.c +@@ -0,0 +1,3 @@ ++#include ++#define __ceilf __ceilf_ppc32 ++#include +diff --git a/sysdeps/powerpc/powerpc32/power5+/fpu/s_ceil.S b/sysdeps/powerpc/powerpc32/power5+/fpu/s_ceil.S +deleted file mode 100644 +index 356c7a79edf79940..0000000000000000 +--- a/sysdeps/powerpc/powerpc32/power5+/fpu/s_ceil.S ++++ /dev/null +@@ -1,29 +0,0 @@ +-/* ceil function. PowerPC32/power5+ version. +- Copyright (C) 2006-2018 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 +- . */ +- +-#include +-#include +-#include +- +- .machine "power5" +-EALIGN (__ceil, 4, 0) +- frip fp1, fp1 +- blr +- END (__ceil) +- +-libm_alias_double (__ceil, ceil) +diff --git a/sysdeps/powerpc/powerpc32/power5+/fpu/s_ceilf.S b/sysdeps/powerpc/powerpc32/power5+/fpu/s_ceilf.S +deleted file mode 100644 +index a0bcda17fde0c0f6..0000000000000000 +--- a/sysdeps/powerpc/powerpc32/power5+/fpu/s_ceilf.S ++++ /dev/null +@@ -1,30 +0,0 @@ +-/* ceilf function. PowerPC32/power5+ version. +- Copyright (C) 2006-2018 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 +- . */ +- +-#include +-#include +- +- .machine "power5" +-EALIGN (__ceilf, 4, 0) +- frip fp1, fp1 /* The rounding instructions are double. */ +- frsp fp1, fp1 /* But we need to set ooverflow for float. */ +- blr +- END (__ceilf) +- +-libm_alias_float (__ceil, ceil) +- +diff --git a/sysdeps/powerpc/powerpc64/be/fpu/multiarch/Makefile b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/Makefile +new file mode 100644 +index 0000000000000000..932c3c7e6c6ad27e +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/Makefile +@@ -0,0 +1,9 @@ ++ifeq ($(subdir),math) ++libm-sysdep_routines += s_ceil-power5+ \ ++ s_ceil-ppc64 \ ++ s_ceilf-power5+ \ ++ s_ceilf-ppc64 ++ ++CFLAGS-s_ceil-power5+.c = -mcpu=power5+ ++CFLAGS-s_ceilf-power5+.c = -mcpu=power5+ ++endif +diff --git a/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceil-power5+.c b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceil-power5+.c +new file mode 100644 +index 0000000000000000..87bc66cdb0322c59 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceil-power5+.c +@@ -0,0 +1,3 @@ ++#include ++#define __ceil __ceil_power5plus ++#include +diff --git a/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceil-ppc64.c b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceil-ppc64.c +new file mode 100644 +index 0000000000000000..8711ff3229467026 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceil-ppc64.c +@@ -0,0 +1,3 @@ ++#include ++#define __ceil __ceil_ppc64 ++#include +diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil.c b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceil.c +similarity index 95% +rename from sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil.c +rename to sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceil.c +index 5cde4eb46f26ec82..1abca7ef63d6a852 100644 +--- a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil.c ++++ b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceil.c +@@ -17,10 +17,8 @@ + . */ + + #include +-#include +-#include +-#include "init-arch.h" + #include ++#include "init-arch.h" + + extern __typeof (__ceil) __ceil_ppc64 attribute_hidden; + extern __typeof (__ceil) __ceil_power5plus attribute_hidden; +diff --git a/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceilf-power5+.c b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceilf-power5+.c +new file mode 100644 +index 0000000000000000..a5bfa98535c088a0 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceilf-power5+.c +@@ -0,0 +1,3 @@ ++#include ++#define __ceilf __ceilf_power5plus ++#include +diff --git a/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceilf-ppc64.c b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceilf-ppc64.c +new file mode 100644 +index 0000000000000000..086251dc0937acfa +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceilf-ppc64.c +@@ -0,0 +1,3 @@ ++#include ++#define __ceilf __ceilf_ppc64 ++#include +diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf.c b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceilf.c +similarity index 95% +rename from sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf.c +rename to sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceilf.c +index 18697e52b3ac1616..33245968a86ddcf5 100644 +--- a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf.c ++++ b/sysdeps/powerpc/powerpc64/be/fpu/multiarch/s_ceilf.c +@@ -17,10 +17,8 @@ + . */ + + #include +-#include +-#include +-#include "init-arch.h" + #include ++#include "init-arch.h" + + extern __typeof (__ceilf) __ceilf_ppc64 attribute_hidden; + extern __typeof (__ceilf) __ceilf_power5plus attribute_hidden; +diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile b/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile +index 73f2f693771027a9..2805e4e0d66f3175 100644 +--- a/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/fpu/multiarch/Makefile +@@ -14,8 +14,7 @@ sysdep_calls := s_copysign-power6 s_copysign-ppc64 \ + + sysdep_routines += $(sysdep_calls) + libm-sysdep_routines += s_llround-power6x \ +- s_llround-power5+ s_llround-ppc64 s_ceil-power5+ \ +- s_ceil-ppc64 s_ceilf-power5+ s_ceilf-ppc64 \ ++ s_llround-power5+ s_llround-ppc64 \ + s_floor-power5+ s_floor-ppc64 s_floorf-power5+ \ + s_floorf-ppc64 s_round-power5+ s_round-ppc64 \ + s_roundf-power5+ s_roundf-ppc64 s_trunc-power5+ \ +diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil-power5+.S b/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil-power5+.S +deleted file mode 100644 +index 76651b694c251bb4..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil-power5+.S ++++ /dev/null +@@ -1,30 +0,0 @@ +-/* ceil function. PowerPC64/power5+ version. +- Copyright (C) 2013-2018 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 +- . */ +- +-#include +- +-#undef weak_alias +-#define weak_alias(a,b) +-#undef strong_alias +-#define strong_alias(a,b) +-#undef compat_symbol +-#define compat_symbol(a,b,c,d) +- +-#define __ceil __ceil_power5plus +- +-#include +diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil-ppc64.S b/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil-ppc64.S +deleted file mode 100644 +index c75c66ba3bbf49c8..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceil-ppc64.S ++++ /dev/null +@@ -1,30 +0,0 @@ +-/* ceil function. PowerPC64 default version. +- Copyright (C) 2013-2018 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 +- . */ +- +-#include +- +-#undef weak_alias +-#define weak_alias(a,b) +-#undef strong_alias +-#define strong_alias(a,b) +-#undef compat_symbol +-#define compat_symbol(a,b,c,d) +- +-#define __ceil __ceil_ppc64 +- +-#include +diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf-power5+.S b/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf-power5+.S +deleted file mode 100644 +index b9c9e14fba6ee134..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf-power5+.S ++++ /dev/null +@@ -1,24 +0,0 @@ +-/* ceilf function. PowerPC64/power5+ version. +- Copyright (C) 2013-2018 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 +- . */ +- +-#undef weak_alias +-#define weak_alias(a,b) +- +-#define __ceilf __ceilf_power5plus +- +-#include +diff --git a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf-ppc64.S b/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf-ppc64.S +deleted file mode 100644 +index ce5cc49770fdfdee..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/fpu/multiarch/s_ceilf-ppc64.S ++++ /dev/null +@@ -1,24 +0,0 @@ +-/* ceilf function. PowerPC64 default version. +- Copyright (C) 2013-2018 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 +- . */ +- +-#undef weak_alias +-#define weak_alias(a,b) +- +-#define __ceilf __ceilf_ppc64 +- +-#include +diff --git a/sysdeps/powerpc/powerpc64/fpu/s_ceil.S b/sysdeps/powerpc/powerpc64/fpu/s_ceil.S +deleted file mode 100644 +index 252d94f51ea1a167..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/fpu/s_ceil.S ++++ /dev/null +@@ -1,65 +0,0 @@ +-/* ceil function. PowerPC64 version. +- Copyright (C) 2004-2018 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 +- . */ +- +-#include +-#include +-#include +- +- .section ".toc","aw" +-.LC0: /* 2**52 */ +- .tc FD_43300000_0[TC],0x4330000000000000 +- .section ".text" +- +-ENTRY (__ceil, 4) +- CALL_MCOUNT 0 +- lfd fp13,.LC0@toc(2) +- fabs fp0,fp1 +- fsub fp12,fp13,fp13 /* generate 0.0 */ +- fcmpu cr7,fp0,fp13 /* if (fabs(x) > TWO52) */ +- mffs fp11 /* Save current FPU rounding mode and +- "inexact" state. */ +- fcmpu cr6,fp1,fp12 /* if (x > 0.0) */ +- bnl- cr7,.L10 +- mtfsfi 7,2 /* Set rounding mode toward +inf. */ +- ble- cr6,.L4 +- fadd fp1,fp1,fp13 /* x+= TWO52; */ +- fsub fp1,fp1,fp13 /* x-= TWO52; */ +- fabs fp1,fp1 /* if (x == 0.0) */ +- /* x = 0.0; */ +- mtfsf 0xff,fp11 /* Restore previous rounding mode and +- "inexact" state. */ +- blr +-.L4: +- bge- cr6,.L9 /* if (x < 0.0) */ +- fsub fp1,fp1,fp13 /* x-= TWO52; */ +- fadd fp1,fp1,fp13 /* x+= TWO52; */ +- fnabs fp1,fp1 /* if (x == 0.0) */ +- /* x = -0.0; */ +-.L9: +- mtfsf 0xff,fp11 /* Restore previous rounding mode and +- "inexact" state. */ +- blr +-.L10: +- /* Ensure sNaN input is converted to qNaN. */ +- fcmpu cr7,fp1,fp1 +- beqlr cr7 +- fadd fp1,fp1,fp1 +- blr +- END (__ceil) +- +-libm_alias_double (__ceil, ceil) +diff --git a/sysdeps/powerpc/powerpc64/fpu/s_ceilf.S b/sysdeps/powerpc/powerpc64/fpu/s_ceilf.S +deleted file mode 100644 +index 3c62077c143eeced..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/fpu/s_ceilf.S ++++ /dev/null +@@ -1,67 +0,0 @@ +-/* float ceil function. PowerPC64 version. +- Copyright (C) 2004-2018 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 +- . */ +- +-#include +-#include +- +- .section ".toc","aw" +- .p2align 3 +-.LC0: /* 2**23 */ +- .long 0x4b000000 +- .long 0x0 +- .section ".text" +- +-ENTRY (__ceilf, 4) +- CALL_MCOUNT 0 +- lfs fp13,.LC0@toc(2) +- fabs fp0,fp1 +- fsubs fp12,fp13,fp13 /* generate 0.0 */ +- fcmpu cr7,fp0,fp13 /* if (fabs(x) > TWO23) */ +- mffs fp11 /* Save current FPU rounding mode and +- "inexact" state. */ +- fcmpu cr6,fp1,fp12 /* if (x > 0.0) */ +- bnl- cr7,.L10 +- mtfsfi 7,2 /* Set rounding mode toward +inf. */ +- ble- cr6,.L4 +- fadds fp1,fp1,fp13 /* x+= TWO23; */ +- fsubs fp1,fp1,fp13 /* x-= TWO23; */ +- fabs fp1,fp1 /* if (x == 0.0) */ +- /* x = 0.0; */ +- mtfsf 0xff,fp11 /* Restore previous rounding mode and +- "inexact" state. */ +- blr +-.L4: +- bge- cr6,.L9 /* if (x < 0.0) */ +- fsubs fp1,fp1,fp13 /* x-= TWO23; */ +- fadds fp1,fp1,fp13 /* x+= TWO23; */ +- fnabs fp1,fp1 /* if (x == 0.0) */ +- /* x = -0.0; */ +-.L9: +- mtfsf 0xff,fp11 /* Restore previous rounding mode and +- "inexact" state. */ +- blr +-.L10: +- /* Ensure sNaN input is converted to qNaN. */ +- fcmpu cr7,fp1,fp1 +- beqlr cr7 +- fadds fp1,fp1,fp1 +- blr +- END (__ceilf) +- +-libm_alias_float (__ceil, ceil) +- +diff --git a/sysdeps/powerpc/powerpc64/power5+/fpu/s_ceil.S b/sysdeps/powerpc/powerpc64/power5+/fpu/s_ceil.S +deleted file mode 100644 +index e500932573c07503..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/power5+/fpu/s_ceil.S ++++ /dev/null +@@ -1,30 +0,0 @@ +-/* ceil function. PowerPC64/power5+ version. +- Copyright (C) 2006-2018 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 +- . */ +- +-#include +-#include +-#include +- +- .machine "power5" +-ENTRY_TOCLESS (__ceil, 4) +- CALL_MCOUNT 0 +- frip fp1, fp1 +- blr +- END (__ceil) +- +-libm_alias_double (__ceil, ceil) +diff --git a/sysdeps/powerpc/powerpc64/power5+/fpu/s_ceilf.S b/sysdeps/powerpc/powerpc64/power5+/fpu/s_ceilf.S +deleted file mode 100644 +index d0b2118c2a3f81be..0000000000000000 +--- a/sysdeps/powerpc/powerpc64/power5+/fpu/s_ceilf.S ++++ /dev/null +@@ -1,31 +0,0 @@ +-/* ceilf function. PowerPC64/power5+ version. +- Copyright (C) 2006-2018 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 +- . */ +- +-#include +-#include +- +- .machine "power5" +-ENTRY_TOCLESS (__ceilf, 4) +- CALL_MCOUNT 0 +- frip fp1, fp1 /* The rounding instructions are double. */ +- frsp fp1, fp1 /* But we need to set ooverflow for float. */ +- blr +- END (__ceilf) +- +-libm_alias_float (__ceil, ceil) +- diff --git a/glibc-rh1783303-10.patch b/glibc-rh1783303-10.patch new file mode 100755 index 0000000..33663f6 --- /dev/null +++ b/glibc-rh1783303-10.patch @@ -0,0 +1,57 @@ +commit 0b3c9e57a41d9f7c26fb6aa45b99f671bef9c7e0 +Author: Paul A. Clarke +Date: Tue Aug 20 15:57:35 2019 -0500 + + [powerpc] fegetenv_status: simplify instruction generation + + fegetenv_status() wants to use the lighter weight instruction 'mffsl' + for reading the Floating-Point Status and Control Register (FPSCR). + It currently will use it directly if compiled '-mcpu=power9', and will + perform a runtime check (cpu_supports("arch_3_00")) otherwise. + + Nicely, it turns out that the 'mffsl' instruction will decode to + 'mffs' on architectures older than "arch_3_00" because the additional + bits set for 'mffsl' are "don't care" for 'mffs'. 'mffs' is a superset + of 'mffsl'. + + So, just generate 'mffsl'. + +diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h +index b244770d115ea7bb..e8d40ea256b6c5bc 100644 +--- a/sysdeps/powerpc/fpu/fenv_libc.h ++++ b/sysdeps/powerpc/fpu/fenv_libc.h +@@ -36,9 +36,12 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden; + ({ fenv_t env; asm volatile ("mffs %0" : "=f" (env)); env; }) + + /* Equivalent to fegetenv_register, but only returns bits for +- status, exception enables, and mode. */ +- +-#define fegetenv_status_ISA300() \ ++ status, exception enables, and mode. ++ Nicely, it turns out that the 'mffsl' instruction will decode to ++ 'mffs' on architectures older than "power9" because the additional ++ bits set for 'mffsl' are "don't care" for 'mffs'. 'mffs' is a superset ++ of 'mffsl'. */ ++#define fegetenv_status() \ + ({register double __fr; \ + __asm__ __volatile__ ( \ + ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \ +@@ -46,18 +49,6 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden; + __fr; \ + }) + +-#ifdef _ARCH_PWR9 +-# define fegetenv_status() fegetenv_status_ISA300() +-#elif defined __BUILTIN_CPU_SUPPORTS__ +-# define fegetenv_status() \ +- (__glibc_likely (__builtin_cpu_supports ("arch_3_00")) \ +- ? fegetenv_status_ISA300() \ +- : fegetenv_register() \ +- ) +-#else +-# define fegetenv_status() fegetenv_register () +-#endif +- + /* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */ + #define fesetenv_register(env) \ + do { \ diff --git a/glibc-rh1783303-11.patch b/glibc-rh1783303-11.patch new file mode 100755 index 0000000..2af4f13 --- /dev/null +++ b/glibc-rh1783303-11.patch @@ -0,0 +1,128 @@ +commit f1c56cdff09f650ad721fae026eb6a3651631f3d +Author: Paul A. Clarke +Date: Thu Sep 19 08:35:16 2019 -0500 + + [powerpc] SET_RESTORE_ROUND optimizations and bug fix + + SET_RESTORE_ROUND brackets a block of code, temporarily setting and + restoring the rounding mode and letting everything else, including + exceptions generated within the block, pass through. + + On powerpc, the current code clears the exception enables, which will hide + exceptions generated within the block. This issue was introduced by me + in commit e905212627350d54b58426214b5a54ddc852b0c9. + + Fix this by not clearing exception enable bits in the prologue. + + Also, since we are no longer changing the enable bits in either the + prologue or the epilogue, there is no need to test for entering/exiting + non-stop mode. + + Also, optimize the prologue get/save/set rounding mode operations for + POWER9 and later by using 'mffscrn' when possible. + + Suggested-by: Paul E. Murphy + Reviewed-by: Paul E. Murphy + Fixes: e905212627350d54b58426214b5a54ddc852b0c9 + + 2019-09-19 Paul A. Clarke + + * sysdeps/powerpc/fpu/fenv_libc.h (fegetenv_and_set_rn): New. + (__fe_mffscrn): New. + * sysdeps/powerpc/fpu/fenv_private.h (libc_feholdsetround_ppc_ctx): + Do not clear enable bits, remove obsolete code, use + fegetenv_and_set_rn. + (libc_feresetround_ppc): Remove obsolete code, use + fegetenv_and_set_rn. + +diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h +index e8d40ea256b6c5bc..b10b6a141ded4bfd 100644 +--- a/sysdeps/powerpc/fpu/fenv_libc.h ++++ b/sysdeps/powerpc/fpu/fenv_libc.h +@@ -49,6 +49,38 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden; + __fr; \ + }) + ++#define __fe_mffscrn(rn) \ ++ ({register fenv_union_t __fr; \ ++ if (__builtin_constant_p (rn)) \ ++ __asm__ __volatile__ ( \ ++ ".machine push; .machine \"power9\"; mffscrni %0,%1; .machine pop" \ ++ : "=f" (__fr.fenv) : "i" (rn)); \ ++ else \ ++ { \ ++ __fr.l = (rn); \ ++ __asm__ __volatile__ ( \ ++ ".machine push; .machine \"power9\"; mffscrn %0,%1; .machine pop" \ ++ : "=f" (__fr.fenv) : "f" (__fr.fenv)); \ ++ } \ ++ __fr.fenv; \ ++ }) ++ ++/* Like fegetenv_status, but also sets the rounding mode. */ ++#ifdef _ARCH_PWR9 ++#define fegetenv_and_set_rn(rn) __fe_mffscrn (rn) ++#else ++/* 'mffscrn' will decode to 'mffs' on ARCH < 3_00, which is still necessary ++ but not sufficient, because it does not set the rounding mode. ++ Explicitly set the rounding mode when 'mffscrn' actually doesn't. */ ++#define fegetenv_and_set_rn(rn) \ ++ ({register fenv_union_t __fr; \ ++ __fr.fenv = __fe_mffscrn (rn); \ ++ if (__glibc_unlikely (!(GLRO(dl_hwcap2) & PPC_FEATURE2_ARCH_3_00))) \ ++ __fesetround_inline (rn); \ ++ __fr.fenv; \ ++ }) ++#endif ++ + /* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */ + #define fesetenv_register(env) \ + do { \ +diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h +index b0149aa243e69f5a..30df92c9a4700dee 100644 +--- a/sysdeps/powerpc/fpu/fenv_private.h ++++ b/sysdeps/powerpc/fpu/fenv_private.h +@@ -133,16 +133,7 @@ static __always_inline void + libc_feresetround_ppc (fenv_t *envp) + { + fenv_union_t new = { .fenv = *envp }; +- +- /* If the old env has no enabled exceptions and the new env has any enabled +- exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the +- hardware into "precise mode" and may cause the FPU to run slower on some +- hardware. */ +- if ((new.l & _FPU_ALL_TRAPS) != 0) +- (void) __fe_nomask_env_priv (); +- +- /* Atomically enable and raise (if appropriate) exceptions set in `new'. */ +- fesetenv_mode (new.fenv); ++ fegetenv_and_set_rn (new.l & FPSCR_RN_MASK); + } + + static __always_inline int +@@ -184,22 +175,10 @@ libc_feupdateenv_ppc (fenv_t *e) + static __always_inline void + libc_feholdsetround_ppc_ctx (struct rm_ctx *ctx, int r) + { +- fenv_union_t old, new; ++ fenv_union_t old; + +- old.fenv = fegetenv_status (); +- +- new.l = (old.l & ~(FPSCR_ENABLES_MASK|FPSCR_RN_MASK)) | r; +- +- ctx->env = old.fenv; +- if (__glibc_unlikely (new.l != old.l)) +- { +- if ((old.l & _FPU_ALL_TRAPS) != 0) +- (void) __fe_mask_env (); +- fesetenv_mode (new.fenv); +- ctx->updated_status = true; +- } +- else +- ctx->updated_status = false; ++ ctx->env = old.fenv = fegetenv_and_set_rn (r); ++ ctx->updated_status = (r != (old.l & FPSCR_RN_MASK)); + } + + static __always_inline void diff --git a/glibc-rh1783303-12.patch b/glibc-rh1783303-12.patch new file mode 100755 index 0000000..5113469 --- /dev/null +++ b/glibc-rh1783303-12.patch @@ -0,0 +1,303 @@ +commit e3d85df50b083c9ba68a40f5d45b201cbec4e68b +Author: Paul A. Clarke +Date: Thu Sep 19 09:13:14 2019 -0500 + + [powerpc] fenv_private.h clean up + + fenv_private.h includes unused functions, magic macro constants, and + some replicated common code fragments. + + Remove unused functions, replace magic constants with constants from + fenv_libc.h, and refactor replicated code. + + Suggested-by: Paul E. Murphy + Reviewed-By: Paul E Murphy + +diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c +index 2a776c72fb5a2b70..bdf55ac62f1ffe4f 100644 +--- a/sysdeps/powerpc/fpu/fedisblxcpt.c ++++ b/sysdeps/powerpc/fpu/fedisblxcpt.c +@@ -43,8 +43,7 @@ fedisableexcept (int excepts) + if (fe.l != curr.l) + fesetenv_mode (fe.fenv); + +- if (new == 0 && result != 0) +- (void)__fe_mask_env (); ++ __TEST_AND_ENTER_NON_STOP (-1ULL, fe.l); + + return result; + } +diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c +index 6f5a828e80965bfa..78ebabed9232c0ad 100644 +--- a/sysdeps/powerpc/fpu/feenablxcpt.c ++++ b/sysdeps/powerpc/fpu/feenablxcpt.c +@@ -43,8 +43,7 @@ feenableexcept (int excepts) + if (fe.l != curr.l) + fesetenv_mode (fe.fenv); + +- if (new != 0 && result == 0) +- (void) __fe_nomask_env_priv (); ++ __TEST_AND_EXIT_NON_STOP (0ULL, fe.l); + + return result; + } +diff --git a/sysdeps/powerpc/fpu/feholdexcpt.c b/sysdeps/powerpc/fpu/feholdexcpt.c +index 8ec3fbff82b22f51..9636ecaa0b600b0d 100644 +--- a/sysdeps/powerpc/fpu/feholdexcpt.c ++++ b/sysdeps/powerpc/fpu/feholdexcpt.c +@@ -18,7 +18,6 @@ + + #include + #include +-#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM | _FPU_MASK_XM | _FPU_MASK_IM) + + int + __feholdexcept (fenv_t *envp) +@@ -35,11 +34,7 @@ __feholdexcept (fenv_t *envp) + if (new.l == old.l) + return 0; + +- /* If the old env had any enabled exceptions, then mask SIGFPE in the +- MSR FE0/FE1 bits. This may allow the FPU to run faster because it +- always takes the default action and can not generate SIGFPE. */ +- if ((old.l & _FPU_MASK_ALL) != 0) +- (void)__fe_mask_env (); ++ __TEST_AND_ENTER_NON_STOP (old.l, 0ULL); + + /* Put the new state in effect. */ + fesetenv_register (new.fenv); +diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h +index b10b6a141ded4bfd..36b639c3939586f6 100644 +--- a/sysdeps/powerpc/fpu/fenv_libc.h ++++ b/sysdeps/powerpc/fpu/fenv_libc.h +@@ -27,6 +27,26 @@ extern const fenv_t *__fe_nomask_env_priv (void); + + extern const fenv_t *__fe_mask_env (void) attribute_hidden; + ++/* If the old env had any enabled exceptions and the new env has no enabled ++ exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the ++ FPU to run faster because it always takes the default action and can not ++ generate SIGFPE. */ ++#define __TEST_AND_ENTER_NON_STOP(old, new) \ ++ do { \ ++ if (((old) & FPSCR_ENABLES_MASK) != 0 && ((new) & FPSCR_ENABLES_MASK) == 0) \ ++ (void) __fe_mask_env (); \ ++ } while (0) ++ ++/* If the old env has no enabled exceptions and the new env has any enabled ++ exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the ++ hardware into "precise mode" and may cause the FPU to run slower on some ++ hardware. */ ++#define __TEST_AND_EXIT_NON_STOP(old, new) \ ++ do { \ ++ if (((old) & FPSCR_ENABLES_MASK) == 0 && ((new) & FPSCR_ENABLES_MASK) != 0) \ ++ (void) __fe_nomask_env_priv (); \ ++ } while (0) ++ + /* The sticky bits in the FPSCR indicating exceptions have occurred. */ + #define FPSCR_STICKY_BITS ((FE_ALL_EXCEPT | FE_ALL_INVALID) & ~FE_INVALID) + +diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h +index 30df92c9a4700dee..c236d45db2f399a4 100644 +--- a/sysdeps/powerpc/fpu/fenv_private.h ++++ b/sysdeps/powerpc/fpu/fenv_private.h +@@ -23,73 +23,20 @@ + #include + #include + +-/* Mask for the exception enable bits. */ +-#define _FPU_ALL_TRAPS (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM \ +- | _FPU_MASK_XM | _FPU_MASK_IM) +- +-/* Mask the rounding mode bits. */ +-#define _FPU_MASK_RN 0xfffffffffffffffcLL +- +-/* Mask everything but the rounding modes and non-IEEE arithmetic flags. */ +-#define _FPU_MASK_NOT_RN_NI 0xffffffff00000807LL +- +-/* Mask restore rounding mode and exception enabled. */ +-#define _FPU_MASK_TRAPS_RN 0xffffffffffffff00LL +- +-/* Mask FP result flags, preserve fraction rounded/inexact bits. */ +-#define _FPU_MASK_FRAC_INEX_RET_CC 0xfffffffffff80fffLL +- + static __always_inline void +-__libc_feholdbits_ppc (fenv_t *envp, unsigned long long mask, +- unsigned long long bits) ++libc_feholdexcept_setround_ppc (fenv_t *envp, int r) + { + fenv_union_t old, new; + + old.fenv = *envp = fegetenv_register (); + +- new.l = (old.l & mask) | bits; +- +- /* If the old env had any enabled exceptions, then mask SIGFPE in the +- MSR FE0/FE1 bits. This may allow the FPU to run faster because it +- always takes the default action and can not generate SIGFPE. */ +- if ((old.l & _FPU_ALL_TRAPS) != 0) +- (void) __fe_mask_env (); ++ __TEST_AND_ENTER_NON_STOP (old.l, 0ULL); + ++ /* Clear everything and set the rounding mode. */ ++ new.l = r; + fesetenv_register (new.fenv); + } + +-static __always_inline void +-libc_feholdexcept_ppc (fenv_t *envp) +-{ +- __libc_feholdbits_ppc (envp, _FPU_MASK_NOT_RN_NI, 0LL); +-} +- +-static __always_inline void +-libc_feholdexcept_setround_ppc (fenv_t *envp, int r) +-{ +- __libc_feholdbits_ppc (envp, _FPU_MASK_NOT_RN_NI & _FPU_MASK_RN, r); +-} +- +-static __always_inline void +-libc_fesetround_ppc (int r) +-{ +- __fesetround_inline (r); +-} +- +-static __always_inline int +-libc_fetestexcept_ppc (int e) +-{ +- fenv_union_t u; +- u.fenv = fegetenv_register (); +- return u.l & e; +-} +- +-static __always_inline void +-libc_feholdsetround_ppc (fenv_t *e, int r) +-{ +- __libc_feholdbits_ppc (e, _FPU_MASK_TRAPS_RN, r); +-} +- + static __always_inline unsigned long long + __libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask, + unsigned long long new_mask) +@@ -102,19 +49,8 @@ __libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask, + /* Merge bits while masking unwanted bits from new and old env. */ + new.l = (old.l & old_mask) | (new.l & new_mask); + +- /* If the old env has no enabled exceptions and the new env has any enabled +- exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the +- hardware into "precise mode" and may cause the FPU to run slower on some +- hardware. */ +- if ((old.l & _FPU_ALL_TRAPS) == 0 && (new.l & _FPU_ALL_TRAPS) != 0) +- (void) __fe_nomask_env_priv (); +- +- /* If the old env had any enabled exceptions and the new env has no enabled +- exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the +- FPU to run faster because it always takes the default action and can not +- generate SIGFPE. */ +- if ((old.l & _FPU_ALL_TRAPS) != 0 && (new.l & _FPU_ALL_TRAPS) == 0) +- (void) __fe_mask_env (); ++ __TEST_AND_EXIT_NON_STOP (old.l, new.l); ++ __TEST_AND_ENTER_NON_STOP (old.l, new.l); + + /* Atomically enable and raise (if appropriate) exceptions set in `new'. */ + fesetenv_register (new.fenv); +@@ -139,8 +75,8 @@ libc_feresetround_ppc (fenv_t *envp) + static __always_inline int + libc_feupdateenv_test_ppc (fenv_t *envp, int ex) + { +- return __libc_femergeenv_ppc (envp, _FPU_MASK_TRAPS_RN, +- _FPU_MASK_FRAC_INEX_RET_CC) & ex; ++ return __libc_femergeenv_ppc (envp, ~FPSCR_CONTROL_MASK, ++ ~FPSCR_STATUS_MASK) & ex; + } + + static __always_inline void +@@ -193,8 +129,7 @@ libc_feholdsetround_noex_ppc_ctx (struct rm_ctx *ctx, int r) + ctx->env = old.fenv; + if (__glibc_unlikely (new.l != old.l)) + { +- if ((old.l & _FPU_ALL_TRAPS) != 0) +- (void) __fe_mask_env (); ++ __TEST_AND_ENTER_NON_STOP (old.l, 0ULL); + fesetenv_register (new.fenv); + ctx->updated_status = true; + } +diff --git a/sysdeps/powerpc/fpu/fesetenv.c b/sysdeps/powerpc/fpu/fesetenv.c +index ac927c8f3ada40b4..4eab5045c48105e3 100644 +--- a/sysdeps/powerpc/fpu/fesetenv.c ++++ b/sysdeps/powerpc/fpu/fesetenv.c +@@ -28,19 +28,8 @@ __fesetenv (const fenv_t *envp) + new.fenv = *envp; + old.fenv = fegetenv_status (); + +- /* If the old env has no enabled exceptions and the new env has any enabled +- exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the +- hardware into "precise mode" and may cause the FPU to run slower on some +- hardware. */ +- if ((old.l & FPSCR_ENABLES_MASK) == 0 && (new.l & FPSCR_ENABLES_MASK) != 0) +- (void) __fe_nomask_env_priv (); +- +- /* If the old env had any enabled exceptions and the new env has no enabled +- exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the +- FPU to run faster because it always takes the default action and can not +- generate SIGFPE. */ +- if ((old.l & FPSCR_ENABLES_MASK) != 0 && (new.l & FPSCR_ENABLES_MASK) == 0) +- (void)__fe_mask_env (); ++ __TEST_AND_EXIT_NON_STOP (old.l, new.l); ++ __TEST_AND_ENTER_NON_STOP (old.l, new.l); + + fesetenv_register (new.fenv); + +diff --git a/sysdeps/powerpc/fpu/fesetmode.c b/sysdeps/powerpc/fpu/fesetmode.c +index 29e088d5ab1c0d93..58ba02c0a1e64c27 100644 +--- a/sysdeps/powerpc/fpu/fesetmode.c ++++ b/sysdeps/powerpc/fpu/fesetmode.c +@@ -33,11 +33,8 @@ fesetmode (const femode_t *modep) + if (old.l == new.l) + return 0; + +- if ((old.l & FPSCR_ENABLES_MASK) == 0 && (new.l & FPSCR_ENABLES_MASK) != 0) +- (void) __fe_nomask_env_priv (); +- +- if ((old.l & FPSCR_ENABLES_MASK) != 0 && (new.l & FPSCR_ENABLES_MASK) == 0) +- (void) __fe_mask_env (); ++ __TEST_AND_EXIT_NON_STOP (old.l, new.l); ++ __TEST_AND_ENTER_NON_STOP (old.l, new.l); + + fesetenv_mode (new.fenv); + return 0; +diff --git a/sysdeps/powerpc/fpu/feupdateenv.c b/sysdeps/powerpc/fpu/feupdateenv.c +index 2dbd1c4e9ec65ed0..fdd15651e0101f9e 100644 +--- a/sysdeps/powerpc/fpu/feupdateenv.c ++++ b/sysdeps/powerpc/fpu/feupdateenv.c +@@ -20,8 +20,6 @@ + #include + #include + +-#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM | _FPU_MASK_XM | _FPU_MASK_IM) +- + int + __feupdateenv (const fenv_t *envp) + { +@@ -36,19 +34,8 @@ __feupdateenv (const fenv_t *envp) + unchanged. */ + new.l = (old.l & 0xffffffff1fffff00LL) | (new.l & 0x1ff80fff); + +- /* If the old env has no enabled exceptions and the new env has any enabled +- exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put +- the hardware into "precise mode" and may cause the FPU to run slower on +- some hardware. */ +- if ((old.l & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0) +- (void) __fe_nomask_env_priv (); +- +- /* If the old env had any enabled exceptions and the new env has no enabled +- exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the +- FPU to run faster because it always takes the default action and can not +- generate SIGFPE. */ +- if ((old.l & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0) +- (void)__fe_mask_env (); ++ __TEST_AND_EXIT_NON_STOP (old.l, new.l); ++ __TEST_AND_ENTER_NON_STOP (old.l, new.l); + + /* Atomically enable and raise (if appropriate) exceptions set in `new'. */ + fesetenv_register (new.fenv); diff --git a/glibc-rh1783303-13.patch b/glibc-rh1783303-13.patch new file mode 100755 index 0000000..73d2018 --- /dev/null +++ b/glibc-rh1783303-13.patch @@ -0,0 +1,58 @@ +commit 7413c188c77adb26a15cf0e98e0a991d09d73c65 +Author: Paul A. Clarke +Date: Thu Sep 19 11:18:33 2019 -0500 + + [powerpc] libc_feupdateenv_test: optimize FPSCR access + + ROUND_TO_ODD and a couple of other places use libc_feupdateenv_test to + restore the rounding mode and exception enables, preserve exception flags, + and test whether given exception(s) were generated. + + If the exception flags haven't changed, then it is sufficient and a bit + more efficient to just restore the rounding mode and enables, rather than + writing the full Floating-Point Status and Control Register (FPSCR). + + Reviewed-by: Paul E. Murphy + +diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h +index 36b639c3939586f6..86ae7fda016abd8b 100644 +--- a/sysdeps/powerpc/fpu/fenv_libc.h ++++ b/sysdeps/powerpc/fpu/fenv_libc.h +@@ -257,6 +257,10 @@ enum { + (FPSCR_VE_MASK|FPSCR_OE_MASK|FPSCR_UE_MASK|FPSCR_ZE_MASK|FPSCR_XE_MASK) + #define FPSCR_BASIC_EXCEPTIONS_MASK \ + (FPSCR_VX_MASK|FPSCR_OX_MASK|FPSCR_UX_MASK|FPSCR_ZX_MASK|FPSCR_XX_MASK) ++#define FPSCR_EXCEPTIONS_MASK (FPSCR_BASIC_EXCEPTIONS_MASK| \ ++ FPSCR_VXSNAN_MASK|FPSCR_VXISI_MASK|FPSCR_VXIDI_MASK|FPSCR_VXZDZ_MASK| \ ++ FPSCR_VXIMZ_MASK|FPSCR_VXVC_MASK|FPSCR_VXSOFT_MASK|FPSCR_VXSQRT_MASK| \ ++ FPSCR_VXCVI_MASK) + #define FPSCR_FPRF_MASK \ + (FPSCR_FPRF_C_MASK|FPSCR_FPRF_FL_MASK|FPSCR_FPRF_FG_MASK| \ + FPSCR_FPRF_FE_MASK|FPSCR_FPRF_FU_MASK) +diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h +index c236d45db2f399a4..86a3611b3ef41759 100644 +--- a/sysdeps/powerpc/fpu/fenv_private.h ++++ b/sysdeps/powerpc/fpu/fenv_private.h +@@ -52,8 +52,20 @@ __libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask, + __TEST_AND_EXIT_NON_STOP (old.l, new.l); + __TEST_AND_ENTER_NON_STOP (old.l, new.l); + +- /* Atomically enable and raise (if appropriate) exceptions set in `new'. */ +- fesetenv_register (new.fenv); ++ /* If requesting to keep status, replace control, and merge exceptions, ++ and exceptions haven't changed, we can just set new control instead ++ of the whole FPSCR. */ ++ if ((old_mask & (FPSCR_CONTROL_MASK|FPSCR_STATUS_MASK|FPSCR_EXCEPTIONS_MASK)) ++ == (FPSCR_STATUS_MASK|FPSCR_EXCEPTIONS_MASK) && ++ (new_mask & (FPSCR_CONTROL_MASK|FPSCR_STATUS_MASK|FPSCR_EXCEPTIONS_MASK)) ++ == (FPSCR_CONTROL_MASK|FPSCR_EXCEPTIONS_MASK) && ++ (old.l & FPSCR_EXCEPTIONS_MASK) == (new.l & FPSCR_EXCEPTIONS_MASK)) ++ { ++ fesetenv_mode (new.fenv); ++ } ++ else ++ /* Atomically enable and raise (if appropriate) exceptions set in `new'. */ ++ fesetenv_register (new.fenv); + + return old.l; + } diff --git a/glibc-rh1783303-14.patch b/glibc-rh1783303-14.patch new file mode 100755 index 0000000..b0c5e66 --- /dev/null +++ b/glibc-rh1783303-14.patch @@ -0,0 +1,56 @@ +commit e68b1151f7460d5fa88c3a567c13f66052da79a7 +Author: Paul A. Clarke +Date: Thu Sep 19 11:39:44 2019 -0500 + + [powerpc] __fesetround_inline optimizations + + On POWER9, use more efficient means to update the 2-bit rounding mode + via the 'mffscrn' instruction (instead of two 'mtfsb0/1' instructions + or one 'mtfsfi' instruction that modifies 4 bits). + + Suggested-by: Paul E. Murphy + Reviewed-By: Paul E Murphy + +diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h +index 86ae7fda016abd8b..c3f541c08440b20e 100644 +--- a/sysdeps/powerpc/fpu/fenv_libc.h ++++ b/sysdeps/powerpc/fpu/fenv_libc.h +@@ -149,7 +149,12 @@ typedef union + static inline int + __fesetround_inline (int round) + { +- if ((unsigned int) round < 2) ++#ifdef _ARCH_PWR9 ++ __fe_mffscrn (round); ++#else ++ if (__glibc_likely (GLRO(dl_hwcap2) & PPC_FEATURE2_ARCH_3_00)) ++ __fe_mffscrn (round); ++ else if ((unsigned int) round < 2) + { + asm volatile ("mtfsb0 30"); + if ((unsigned int) round == 0) +@@ -165,7 +170,7 @@ __fesetround_inline (int round) + else + asm volatile ("mtfsb1 31"); + } +- ++#endif + return 0; + } + +@@ -174,7 +179,14 @@ __fesetround_inline (int round) + static inline void + __fesetround_inline_nocheck (const int round) + { +- asm volatile ("mtfsfi 7,%0" : : "i" (round)); ++#ifdef _ARCH_PWR9 ++ __fe_mffscrn (round); ++#else ++ if (__glibc_likely (GLRO(dl_hwcap2) & PPC_FEATURE2_ARCH_3_00)) ++ __fe_mffscrn (round); ++ else ++ asm volatile ("mtfsfi 7,%0" : : "i" (round)); ++#endif + } + + #define FPSCR_MASK(bit) (1 << (31 - (bit))) diff --git a/glibc-rh1783303-15.patch b/glibc-rh1783303-15.patch new file mode 100755 index 0000000..47f85db --- /dev/null +++ b/glibc-rh1783303-15.patch @@ -0,0 +1,123 @@ +commit 81ecb0ee4970865cbe5d1da733c4879b999c528f +Author: Paul A. Clarke +Date: Thu Sep 19 11:58:46 2019 -0500 + + [powerpc] Rename fegetenv_status to fegetenv_control + + fegetenv_status is used variously to retrieve the FPSCR exception enable + bits, rounding mode bits, or both. These are referred to as the control + bits in the POWER ISA. FPSCR status bits are also returned by the + 'mffs' and 'mffsl' instructions, but they are uniformly ignored by all + uses of fegetenv_status. Change the name to be reflective of its + current and expected use. + + Reviewed-By: Paul E Murphy + +diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c +index bdf55ac62f1ffe4f..1273987459655585 100644 +--- a/sysdeps/powerpc/fpu/fedisblxcpt.c ++++ b/sysdeps/powerpc/fpu/fedisblxcpt.c +@@ -26,7 +26,7 @@ fedisableexcept (int excepts) + int result, new; + + /* Get current exception mask to return. */ +- fe.fenv = curr.fenv = fegetenv_status (); ++ fe.fenv = curr.fenv = fegetenv_control (); + result = fenv_reg_to_exceptions (fe.l); + + if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID) +diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c +index 78ebabed9232c0ad..fa233c305aedd5f6 100644 +--- a/sysdeps/powerpc/fpu/feenablxcpt.c ++++ b/sysdeps/powerpc/fpu/feenablxcpt.c +@@ -26,7 +26,7 @@ feenableexcept (int excepts) + int result, new; + + /* Get current exception mask to return. */ +- fe.fenv = curr.fenv = fegetenv_status (); ++ fe.fenv = curr.fenv = fegetenv_control (); + result = fenv_reg_to_exceptions (fe.l); + + if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID) +diff --git a/sysdeps/powerpc/fpu/fegetexcept.c b/sysdeps/powerpc/fpu/fegetexcept.c +index 9d77adea59939ece..6bbf11d9d5df61e5 100644 +--- a/sysdeps/powerpc/fpu/fegetexcept.c ++++ b/sysdeps/powerpc/fpu/fegetexcept.c +@@ -25,7 +25,7 @@ __fegetexcept (void) + fenv_union_t fe; + int result = 0; + +- fe.fenv = fegetenv_status (); ++ fe.fenv = fegetenv_control (); + + if (fe.l & (1 << (31 - FPSCR_XE))) + result |= FE_INEXACT; +diff --git a/sysdeps/powerpc/fpu/fegetmode.c b/sysdeps/powerpc/fpu/fegetmode.c +index 75493e5f24c8b05b..57d6d5275485ebdc 100644 +--- a/sysdeps/powerpc/fpu/fegetmode.c ++++ b/sysdeps/powerpc/fpu/fegetmode.c +@@ -21,6 +21,6 @@ + int + fegetmode (femode_t *modep) + { +- *modep = fegetenv_status (); ++ *modep = fegetenv_control (); + return 0; + } +diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h +index c3f541c08440b20e..b5c8da1adefe93cb 100644 +--- a/sysdeps/powerpc/fpu/fenv_libc.h ++++ b/sysdeps/powerpc/fpu/fenv_libc.h +@@ -61,7 +61,7 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden; + 'mffs' on architectures older than "power9" because the additional + bits set for 'mffsl' are "don't care" for 'mffs'. 'mffs' is a superset + of 'mffsl'. */ +-#define fegetenv_status() \ ++#define fegetenv_control() \ + ({register double __fr; \ + __asm__ __volatile__ ( \ + ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \ +@@ -85,7 +85,7 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden; + __fr.fenv; \ + }) + +-/* Like fegetenv_status, but also sets the rounding mode. */ ++/* Like fegetenv_control, but also sets the rounding mode. */ + #ifdef _ARCH_PWR9 + #define fegetenv_and_set_rn(rn) __fe_mffscrn (rn) + #else +@@ -116,7 +116,7 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden; + + /* Set the last 2 nibbles of the FPSCR, which contain the + exception enables and the rounding mode. +- 'fegetenv_status' retrieves these bits by reading the FPSCR. */ ++ 'fegetenv_control' retrieves these bits by reading the FPSCR. */ + #define fesetenv_mode(env) __builtin_mtfsf (0b00000011, (env)); + + /* This very handy macro: +diff --git a/sysdeps/powerpc/fpu/fesetenv.c b/sysdeps/powerpc/fpu/fesetenv.c +index 4eab5045c48105e3..252114141cd87f8d 100644 +--- a/sysdeps/powerpc/fpu/fesetenv.c ++++ b/sysdeps/powerpc/fpu/fesetenv.c +@@ -26,7 +26,7 @@ __fesetenv (const fenv_t *envp) + + /* get the currently set exceptions. */ + new.fenv = *envp; +- old.fenv = fegetenv_status (); ++ old.fenv = fegetenv_control (); + + __TEST_AND_EXIT_NON_STOP (old.l, new.l); + __TEST_AND_ENTER_NON_STOP (old.l, new.l); +diff --git a/sysdeps/powerpc/fpu/fesetmode.c b/sysdeps/powerpc/fpu/fesetmode.c +index 58ba02c0a1e64c27..e5938af04cb71ca1 100644 +--- a/sysdeps/powerpc/fpu/fesetmode.c ++++ b/sysdeps/powerpc/fpu/fesetmode.c +@@ -27,7 +27,7 @@ fesetmode (const femode_t *modep) + /* Logic regarding enabled exceptions as in fesetenv. */ + + new.fenv = *modep; +- old.fenv = fegetenv_status (); ++ old.fenv = fegetenv_control (); + new.l = (new.l & ~FPSCR_STATUS_MASK) | (old.l & FPSCR_STATUS_MASK); + + if (old.l == new.l) diff --git a/glibc-rh1783303-16.patch b/glibc-rh1783303-16.patch new file mode 100755 index 0000000..c60fb39 --- /dev/null +++ b/glibc-rh1783303-16.patch @@ -0,0 +1,29 @@ +commit 36c17c7079a5243a890ba43affff326a041775a9 +Author: Paul A. Clarke +Date: Thu Sep 19 11:31:31 2019 -0500 + + [powerpc] libc_feholdsetround_noex_ppc_ctx: optimize FPSCR write + + libc_feholdsetround_noex_ppc_ctx currently performs: + 1. Read FPSCR, save to context. + 2. Create new FPSCR value: clear enables and set new rounding mode. + 3. Write new value to FPSCR. + + Since other bits just pass through, there is no need to write them. + + Instead, write just the changed values (enables and rounding mode), + which can be a bit more efficient. + +diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h +index 86a3611b3ef41759..c88142fe3053580f 100644 +--- a/sysdeps/powerpc/fpu/fenv_private.h ++++ b/sysdeps/powerpc/fpu/fenv_private.h +@@ -142,7 +142,7 @@ libc_feholdsetround_noex_ppc_ctx (struct rm_ctx *ctx, int r) + if (__glibc_unlikely (new.l != old.l)) + { + __TEST_AND_ENTER_NON_STOP (old.l, 0ULL); +- fesetenv_register (new.fenv); ++ fesetenv_mode (new.fenv); + ctx->updated_status = true; + } + else diff --git a/glibc-rh1783303-17.patch b/glibc-rh1783303-17.patch new file mode 100755 index 0000000..2c521cc --- /dev/null +++ b/glibc-rh1783303-17.patch @@ -0,0 +1,84 @@ +commit d7a568af5546e0313abbc04060c8e9b0d3f750b4 +Author: Paul A. Clarke +Date: Thu Sep 19 14:04:45 2019 -0500 + + [powerpc] Rename fesetenv_mode to fesetenv_control + + fesetenv_mode is used variously to write the FPSCR exception enable + bits and rounding mode bits. These are referred to as the control + bits in the POWER ISA. Change the name to be reflective of its + current and expected use, and match up well with fegetenv_control. + +diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c +index 1273987459655585..efa9c422fe54f5d8 100644 +--- a/sysdeps/powerpc/fpu/fedisblxcpt.c ++++ b/sysdeps/powerpc/fpu/fedisblxcpt.c +@@ -41,7 +41,7 @@ fedisableexcept (int excepts) + fe.l &= ~new; + + if (fe.l != curr.l) +- fesetenv_mode (fe.fenv); ++ fesetenv_control (fe.fenv); + + __TEST_AND_ENTER_NON_STOP (-1ULL, fe.l); + +diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c +index fa233c305aedd5f6..dfcc6fb7bd24b8db 100644 +--- a/sysdeps/powerpc/fpu/feenablxcpt.c ++++ b/sysdeps/powerpc/fpu/feenablxcpt.c +@@ -41,7 +41,7 @@ feenableexcept (int excepts) + fe.l |= new; + + if (fe.l != curr.l) +- fesetenv_mode (fe.fenv); ++ fesetenv_control (fe.fenv); + + __TEST_AND_EXIT_NON_STOP (0ULL, fe.l); + +diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h +index b5c8da1adefe93cb..287fc9f8f70e051c 100644 +--- a/sysdeps/powerpc/fpu/fenv_libc.h ++++ b/sysdeps/powerpc/fpu/fenv_libc.h +@@ -117,7 +117,7 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden; + /* Set the last 2 nibbles of the FPSCR, which contain the + exception enables and the rounding mode. + 'fegetenv_control' retrieves these bits by reading the FPSCR. */ +-#define fesetenv_mode(env) __builtin_mtfsf (0b00000011, (env)); ++#define fesetenv_control(env) __builtin_mtfsf (0b00000011, (env)); + + /* This very handy macro: + - Sets the rounding mode to 'round to nearest'; +diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h +index c88142fe3053580f..666fbfdd9fef7759 100644 +--- a/sysdeps/powerpc/fpu/fenv_private.h ++++ b/sysdeps/powerpc/fpu/fenv_private.h +@@ -61,7 +61,7 @@ __libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask, + == (FPSCR_CONTROL_MASK|FPSCR_EXCEPTIONS_MASK) && + (old.l & FPSCR_EXCEPTIONS_MASK) == (new.l & FPSCR_EXCEPTIONS_MASK)) + { +- fesetenv_mode (new.fenv); ++ fesetenv_control (new.fenv); + } + else + /* Atomically enable and raise (if appropriate) exceptions set in `new'. */ +@@ -142,7 +142,7 @@ libc_feholdsetround_noex_ppc_ctx (struct rm_ctx *ctx, int r) + if (__glibc_unlikely (new.l != old.l)) + { + __TEST_AND_ENTER_NON_STOP (old.l, 0ULL); +- fesetenv_mode (new.fenv); ++ fesetenv_control (new.fenv); + ctx->updated_status = true; + } + else +diff --git a/sysdeps/powerpc/fpu/fesetmode.c b/sysdeps/powerpc/fpu/fesetmode.c +index e5938af04cb71ca1..fdaecb1a6a25a820 100644 +--- a/sysdeps/powerpc/fpu/fesetmode.c ++++ b/sysdeps/powerpc/fpu/fesetmode.c +@@ -36,6 +36,6 @@ fesetmode (const femode_t *modep) + __TEST_AND_EXIT_NON_STOP (old.l, new.l); + __TEST_AND_ENTER_NON_STOP (old.l, new.l); + +- fesetenv_mode (new.fenv); ++ fesetenv_control (new.fenv); + return 0; + } diff --git a/glibc-rh1783303-18.patch b/glibc-rh1783303-18.patch new file mode 100755 index 0000000..60b6d9d --- /dev/null +++ b/glibc-rh1783303-18.patch @@ -0,0 +1,64 @@ +commit 7b8481b330720d28c019a2e5994492a1923d5daa +Author: Paul A. Clarke +Date: Thu Sep 19 11:11:04 2019 -0500 + + [powerpc] No need to enter "Ignore Exceptions Mode" + + Since at least POWER8, there is no performance advantage to entering + "Ignore Exceptions Mode", and doing so conditionally requires + - the conditional logic, and + - a system call. + + Make it a no-op for uses within glibc. + +diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h +index 666fbfdd9fef7759..e09137e892a8e3f3 100644 +--- a/sysdeps/powerpc/fpu/fenv_private.h ++++ b/sysdeps/powerpc/fpu/fenv_private.h +@@ -23,6 +23,17 @@ + #include + #include + ++#ifdef _ARCH_PWR8 ++/* There is no performance advantage to non-stop mode. */ ++/* The odd syntax here is to innocuously reference the given variables ++ to prevent warnings about unused variables. */ ++#define __TEST_AND_BEGIN_NON_STOP(old, new) do {} while ((old) * (new) * 0 != 0) ++#define __TEST_AND_END_NON_STOP(old, new) do {} while ((old) * (new) * 0 != 0) ++#else ++#define __TEST_AND_BEGIN_NON_STOP __TEST_AND_ENTER_NON_STOP ++#define __TEST_AND_END_NON_STOP __TEST_AND_EXIT_NON_STOP ++#endif ++ + static __always_inline void + libc_feholdexcept_setround_ppc (fenv_t *envp, int r) + { +@@ -30,7 +41,7 @@ libc_feholdexcept_setround_ppc (fenv_t *envp, int r) + + old.fenv = *envp = fegetenv_register (); + +- __TEST_AND_ENTER_NON_STOP (old.l, 0ULL); ++ __TEST_AND_BEGIN_NON_STOP (old.l, 0ULL); + + /* Clear everything and set the rounding mode. */ + new.l = r; +@@ -49,8 +60,8 @@ __libc_femergeenv_ppc (const fenv_t *envp, unsigned long long old_mask, + /* Merge bits while masking unwanted bits from new and old env. */ + new.l = (old.l & old_mask) | (new.l & new_mask); + +- __TEST_AND_EXIT_NON_STOP (old.l, new.l); +- __TEST_AND_ENTER_NON_STOP (old.l, new.l); ++ __TEST_AND_END_NON_STOP (old.l, new.l); ++ __TEST_AND_BEGIN_NON_STOP (old.l, new.l); + + /* If requesting to keep status, replace control, and merge exceptions, + and exceptions haven't changed, we can just set new control instead +@@ -141,7 +152,7 @@ libc_feholdsetround_noex_ppc_ctx (struct rm_ctx *ctx, int r) + ctx->env = old.fenv; + if (__glibc_unlikely (new.l != old.l)) + { +- __TEST_AND_ENTER_NON_STOP (old.l, 0ULL); ++ __TEST_AND_BEGIN_NON_STOP (old.l, 0ULL); + fesetenv_control (new.fenv); + ctx->updated_status = true; + } diff --git a/glibc-rh1783303-2.patch b/glibc-rh1783303-2.patch new file mode 100755 index 0000000..616af07 --- /dev/null +++ b/glibc-rh1783303-2.patch @@ -0,0 +1,105 @@ +commit de751ebc9efa97ce0115e42bd55fa1beeb614380 +Author: Paul A. Clarke +Date: Fri Mar 15 19:04:24 2019 -0400 + + [powerpc] get_rounding_mode: utilize faster method to get rounding mode + + Add support to use 'mffsl' instruction if compiled for POWER9 (or later). + + Also, mask the result to avoid bleeding unrelated bits into the result of + _FPU_GET_RC(). + + Reviewed-by: Tulio Magno Quites Machado Filho + +diff --git a/sysdeps/powerpc/fpu/get-rounding-mode.h b/sysdeps/powerpc/fpu/get-rounding-mode.h +new file mode 100644 +index 0000000000000000..e2fdbbbcce72bd66 +--- /dev/null ++++ b/sysdeps/powerpc/fpu/get-rounding-mode.h +@@ -0,0 +1,33 @@ ++/* Determine floating-point rounding mode within libc. powerpc64 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 ++ . */ ++ ++#ifndef _POWERPC64_GET_ROUNDING_MODE_H ++#define _POWERPC64_GET_ROUNDING_MODE_H 1 ++ ++#include ++#include ++ ++/* Return the floating-point rounding mode. */ ++ ++static inline int ++get_rounding_mode (void) ++{ ++ return _FPU_GET_RC (); ++} ++ ++#endif /* get-rounding-mode.h */ +diff --git a/sysdeps/powerpc/fpu_control.h b/sysdeps/powerpc/fpu_control.h +index 9d0698b4fc3eb595..62c478d72ae660cb 100644 +--- a/sysdeps/powerpc/fpu_control.h ++++ b/sysdeps/powerpc/fpu_control.h +@@ -71,6 +71,8 @@ extern fpu_control_t __fpu_control; + # define _FPU_RC_UP 0x02 + # define _FPU_RC_ZERO 0x01 + ++# define _FPU_MASK_RC (_FPU_RC_NEAREST|_FPU_RC_DOWN|_FPU_RC_UP|_FPU_RC_ZERO) ++ + # define _FPU_MASK_NI 0x04 /* non-ieee mode */ + + /* masking of interrupts */ +@@ -94,15 +96,36 @@ extern fpu_control_t __fpu_control; + typedef unsigned int fpu_control_t; + + /* Macros for accessing the hardware control word. */ ++# define __FPU_MFFS() \ ++ ({register double __fr; \ ++ __asm__ ("mffs %0" : "=f" (__fr)); \ ++ __fr; \ ++ }) ++ + # define _FPU_GETCW(cw) \ + ({union { double __d; unsigned long long __ll; } __u; \ +- register double __fr; \ +- __asm__ ("mffs %0" : "=f" (__fr)); \ +- __u.__d = __fr; \ ++ __u.__d = __FPU_MFFS(); \ + (cw) = (fpu_control_t) __u.__ll; \ + (fpu_control_t) __u.__ll; \ + }) + ++#ifdef _ARCH_PWR9 ++# define __FPU_MFFSL() \ ++ ({register double __fr; \ ++ __asm__ ("mffsl %0" : "=f" (__fr)); \ ++ __fr; \ ++ }) ++#else ++# define __FPU_MFFSL() __FPU_MFFS() ++#endif ++ ++# define _FPU_GET_RC() \ ++ ({union { double __d; unsigned long long __ll; } __u; \ ++ __u.__d = __FPU_MFFSL(); \ ++ __u.__ll &= _FPU_MASK_RC; \ ++ (fpu_control_t) __u.__ll; \ ++ }) ++ + # define _FPU_SETCW(cw) \ + { union { double __d; unsigned long long __ll; } __u; \ + register double __fr; \ diff --git a/glibc-rh1783303-3.patch b/glibc-rh1783303-3.patch new file mode 100755 index 0000000..b653b49 --- /dev/null +++ b/glibc-rh1783303-3.patch @@ -0,0 +1,65 @@ +commit 49bc41b64239c4726f31fa35a1af4f22fb41d51f +Author: Paul A. Clarke +Date: Tue Jun 11 14:37:37 2019 -0500 + + [powerpc] add 'volatile' to asm + + Add 'volatile' keyword to a few asm statements, to force the compiler + to generate the instructions therein. + + Some instances were implicitly volatile, but adding keyword for consistency. + + 2019-06-19 Paul A. Clarke + + * sysdeps/powerpc/fpu/fenv_libc.h (relax_fenv_state): Add 'volatile'. + * sysdeps/powerpc/fpu/fpu_control.h (__FPU_MFFS): Likewise. + (__FPU_MFFSL): Likewise. + (_FPU_SETCW): Likewise. + +diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h +index a0128c66444a3e46..d6945903b525748e 100644 +--- a/sysdeps/powerpc/fpu/fenv_libc.h ++++ b/sysdeps/powerpc/fpu/fenv_libc.h +@@ -57,9 +57,9 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden; + #define relax_fenv_state() \ + do { \ + if (GLRO(dl_hwcap) & PPC_FEATURE_HAS_DFP) \ +- asm (".machine push; .machine \"power6\"; " \ ++ asm volatile (".machine push; .machine \"power6\"; " \ + "mtfsfi 7,0,1; .machine pop"); \ +- asm ("mtfsfi 7,0"); \ ++ asm volatile ("mtfsfi 7,0"); \ + } while(0) + + /* Set/clear a particular FPSCR bit (for instance, +diff --git a/sysdeps/powerpc/fpu_control.h b/sysdeps/powerpc/fpu_control.h +index 62c478d72ae660cb..90063d77bbbf794f 100644 +--- a/sysdeps/powerpc/fpu_control.h ++++ b/sysdeps/powerpc/fpu_control.h +@@ -98,7 +98,7 @@ typedef unsigned int fpu_control_t; + /* Macros for accessing the hardware control word. */ + # define __FPU_MFFS() \ + ({register double __fr; \ +- __asm__ ("mffs %0" : "=f" (__fr)); \ ++ __asm__ __volatile__("mffs %0" : "=f" (__fr)); \ + __fr; \ + }) + +@@ -112,7 +112,7 @@ typedef unsigned int fpu_control_t; + #ifdef _ARCH_PWR9 + # define __FPU_MFFSL() \ + ({register double __fr; \ +- __asm__ ("mffsl %0" : "=f" (__fr)); \ ++ __asm__ __volatile__("mffsl %0" : "=f" (__fr)); \ + __fr; \ + }) + #else +@@ -132,7 +132,7 @@ typedef unsigned int fpu_control_t; + __u.__ll = 0xfff80000LL << 32; /* This is a QNaN. */ \ + __u.__ll |= (cw) & 0xffffffffLL; \ + __fr = __u.__d; \ +- __asm__ ("mtfsf 255,%0" : : "f" (__fr)); \ ++ __asm__ __volatile__("mtfsf 255,%0" : : "f" (__fr)); \ + } + + /* Default control word set at startup. */ diff --git a/glibc-rh1783303-4.patch b/glibc-rh1783303-4.patch new file mode 100755 index 0000000..5475305 --- /dev/null +++ b/glibc-rh1783303-4.patch @@ -0,0 +1,200 @@ +commit 3db85a9814784a74536a1f0e7b7ddbfef7dc84bb +Author: Paul A. Clarke +Date: Thu Jun 20 11:57:18 2019 -0500 + + powerpc: Use faster means to access FPSCR when possible in some cases + + Using 'mffs' instruction to read the Floating Point Status Control Register + (FPSCR) can force a processor flush in some cases, with undesirable + performance impact. If the values of the bits in the FPSCR which force the + flush are not needed, an instruction that is new to POWER9 (ISA version 3.0), + 'mffsl' can be used instead. + + Cases included: get_rounding_mode, fegetround, fegetmode, fegetexcept. + + * sysdeps/powerpc/bits/fenvinline.h (__fegetround): Use + __fegetround_ISA300() or __fegetround_ISA2() as appropriate. + (__fegetround_ISA300) New. + (__fegetround_ISA2) New. + * sysdeps/powerpc/fpu_control.h (IS_ISA300): New. + (_FPU_MFFS): Move implementation... + (_FPU_GETCW): Here. + (_FPU_MFFSL): Move implementation.... + (_FPU_GET_RC_ISA300): Here. New. + (_FPU_GET_RC): Use _FPU_GET_RC_ISA300() or _FPU_GETCW() as appropriate. + * sysdeps/powerpc/fpu/fenv_libc.h (fegetenv_status_ISA300): New. + (fegetenv_status): New. + * sysdeps/powerpc/fpu/fegetmode.c (fegetmode): Use fegetenv_status() + instead of fegetenv_register(). + * sysdeps/powerpc/fpu/fegetexcept.c (__fegetexcept): Likewise. + + Reviewed-by: Tulio Magno Quites Machado Filho + +diff --git a/sysdeps/powerpc/bits/fenvinline.h b/sysdeps/powerpc/bits/fenvinline.h +index 41316386ba75e903..caec8ead6e17219d 100644 +--- a/sysdeps/powerpc/bits/fenvinline.h ++++ b/sysdeps/powerpc/bits/fenvinline.h +@@ -18,13 +18,36 @@ + + #if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_FPRS__ + +-/* Inline definition for fegetround. */ +-# define __fegetround() \ +- (__extension__ ({ int __fegetround_result; \ +- __asm__ __volatile__ \ +- ("mcrfs 7,7 ; mfcr %0" \ +- : "=r"(__fegetround_result) : : "cr7"); \ +- __fegetround_result & 3; })) ++/* Inline definitions for fegetround. */ ++# define __fegetround_ISA300() \ ++ (__extension__ ({ \ ++ union { double __d; unsigned long long __ll; } __u; \ ++ __asm__ __volatile__ ( \ ++ ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \ ++ : "=f" (__u.__d)); \ ++ __u.__ll & 0x0000000000000003LL; \ ++ })) ++ ++# define __fegetround_ISA2() \ ++ (__extension__ ({ \ ++ int __fegetround_result; \ ++ __asm__ __volatile__ ("mcrfs 7,7 ; mfcr %0" \ ++ : "=r"(__fegetround_result) : : "cr7"); \ ++ __fegetround_result & 3; \ ++ })) ++ ++# ifdef _ARCH_PWR9 ++# define __fegetround() __fegetround_ISA300() ++# elif defined __BUILTIN_CPU_SUPPORTS__ ++# define __fegetround() \ ++ (__glibc_likely (__builtin_cpu_supports ("arch_3_00")) \ ++ ? __fegetround_ISA300() \ ++ : __fegetround_ISA2() \ ++ ) ++# else ++# define __fegetround() __fegetround_ISA2() ++# endif ++ + # define fegetround() __fegetround () + + # ifndef __NO_MATH_INLINES +diff --git a/sysdeps/powerpc/fpu/fegetexcept.c b/sysdeps/powerpc/fpu/fegetexcept.c +index a053a32bfe11c0d4..9d77adea59939ece 100644 +--- a/sysdeps/powerpc/fpu/fegetexcept.c ++++ b/sysdeps/powerpc/fpu/fegetexcept.c +@@ -25,7 +25,7 @@ __fegetexcept (void) + fenv_union_t fe; + int result = 0; + +- fe.fenv = fegetenv_register (); ++ fe.fenv = fegetenv_status (); + + if (fe.l & (1 << (31 - FPSCR_XE))) + result |= FE_INEXACT; +diff --git a/sysdeps/powerpc/fpu/fegetmode.c b/sysdeps/powerpc/fpu/fegetmode.c +index b83dc9f625d2248a..75493e5f24c8b05b 100644 +--- a/sysdeps/powerpc/fpu/fegetmode.c ++++ b/sysdeps/powerpc/fpu/fegetmode.c +@@ -21,6 +21,6 @@ + int + fegetmode (femode_t *modep) + { +- *modep = fegetenv_register (); ++ *modep = fegetenv_status (); + return 0; + } +diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h +index d6945903b525748e..cc00df033da47c1a 100644 +--- a/sysdeps/powerpc/fpu/fenv_libc.h ++++ b/sysdeps/powerpc/fpu/fenv_libc.h +@@ -35,6 +35,27 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden; + #define fegetenv_register() \ + ({ fenv_t env; asm volatile ("mffs %0" : "=f" (env)); env; }) + ++/* Equivalent to fegetenv_register, but only returns bits for ++ status, exception enables, and mode. */ ++ ++#define fegetenv_status_ISA300() \ ++ ({register double __fr; \ ++ __asm__ __volatile__ ( \ ++ ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \ ++ : "=f" (__fr)); \ ++ __fr; \ ++ }) ++ ++#ifdef _ARCH_PWR9 ++# define fegetenv_status() fegetenv_status_ISA300() ++#else ++# define fegetenv_status() \ ++ (__glibc_likely (__builtin_cpu_supports ("arch_3_00")) \ ++ ? fegetenv_status_ISA300() \ ++ : fegetenv_register() \ ++ ) ++#endif ++ + /* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */ + #define fesetenv_register(env) \ + do { \ +diff --git a/sysdeps/powerpc/fpu_control.h b/sysdeps/powerpc/fpu_control.h +index 90063d77bbbf794f..e0ee622e246c0d61 100644 +--- a/sysdeps/powerpc/fpu_control.h ++++ b/sysdeps/powerpc/fpu_control.h +@@ -96,35 +96,37 @@ extern fpu_control_t __fpu_control; + typedef unsigned int fpu_control_t; + + /* Macros for accessing the hardware control word. */ +-# define __FPU_MFFS() \ +- ({register double __fr; \ +- __asm__ __volatile__("mffs %0" : "=f" (__fr)); \ +- __fr; \ +- }) +- + # define _FPU_GETCW(cw) \ + ({union { double __d; unsigned long long __ll; } __u; \ +- __u.__d = __FPU_MFFS(); \ ++ __asm__ __volatile__("mffs %0" : "=f" (__u.__d)); \ + (cw) = (fpu_control_t) __u.__ll; \ + (fpu_control_t) __u.__ll; \ + }) + +-#ifdef _ARCH_PWR9 +-# define __FPU_MFFSL() \ +- ({register double __fr; \ +- __asm__ __volatile__("mffsl %0" : "=f" (__fr)); \ +- __fr; \ ++# define _FPU_GET_RC_ISA300() \ ++ ({union { double __d; unsigned long long __ll; } __u; \ ++ __asm__ __volatile__( \ ++ ".machine push; .machine \"power9\"; mffsl %0; .machine pop" \ ++ : "=f" (__u.__d)); \ ++ (fpu_control_t) (__u.__ll & _FPU_MASK_RC); \ + }) +-#else +-# define __FPU_MFFSL() __FPU_MFFS() +-#endif +- +-# define _FPU_GET_RC() \ +- ({union { double __d; unsigned long long __ll; } __u; \ +- __u.__d = __FPU_MFFSL(); \ +- __u.__ll &= _FPU_MASK_RC; \ +- (fpu_control_t) __u.__ll; \ ++ ++# ifdef _ARCH_PWR9 ++# define _FPU_GET_RC() _FPU_GET_RC_ISA300() ++# elif defined __BUILTIN_CPU_SUPPORTS__ ++# define _FPU_GET_RC() \ ++ ({fpu_control_t __rc; \ ++ __rc = __glibc_likely (__builtin_cpu_supports ("arch_3_00")) \ ++ ? _FPU_GET_RC_ISA300 () \ ++ : _FPU_GETCW (__rc) & _FPU_MASK_RC; \ ++ __rc; \ ++ }) ++# else ++# define _FPU_GET_RC() \ ++ ({fpu_control_t __rc = _FPU_GETCW (__rc) & _FPU_MASK_RC; \ ++ __rc; \ + }) ++# endif + + # define _FPU_SETCW(cw) \ + { union { double __d; unsigned long long __ll; } __u; \ diff --git a/glibc-rh1783303-5.patch b/glibc-rh1783303-5.patch new file mode 100755 index 0000000..e8c439e --- /dev/null +++ b/glibc-rh1783303-5.patch @@ -0,0 +1,37 @@ +commit b5232c9f9e6048b8f780d3cbfadbc8e59bb90ce4 +Author: Paul A. Clarke +Date: Mon Jul 8 17:06:19 2019 -0500 + + [powerpc] fenv_libc.h: protect use of __builtin_cpu_supports + + Using __builtin_cpu_supports() requires support in GCC and Glibc. + My recent patch to fenv_libc.h added an unprotected use of + __builtin_cpu_supports(). Compilation of Glibc itself will fail + with a sufficiently new GCC and sufficiently old Glibc: + + ../sysdeps/powerpc/fpu/fegetexcept.c: In function ‘__fegetexcept’: + ../sysdeps/powerpc/fpu/fenv_libc.h:52:20: error: builtin ‘__builtin_cpu_supports’ needs GLIBC (2.23 and newer) that exports hardware capability bits [-Werror] + + Reviewed-by: Florian Weimer + Fixes 3db85a9814784a74536a1f0e7b7ddbfef7dc84bb. + +diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h +index cc00df033da47c1a..9dca6e760cc51946 100644 +--- a/sysdeps/powerpc/fpu/fenv_libc.h ++++ b/sysdeps/powerpc/fpu/fenv_libc.h +@@ -48,12 +48,14 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden; + + #ifdef _ARCH_PWR9 + # define fegetenv_status() fegetenv_status_ISA300() +-#else ++#elif defined __BUILTIN_CPU_SUPPORTS__ + # define fegetenv_status() \ + (__glibc_likely (__builtin_cpu_supports ("arch_3_00")) \ + ? fegetenv_status_ISA300() \ + : fegetenv_register() \ + ) ++#else ++# define fegetenv_status() fegetenv_register () + #endif + + /* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */ diff --git a/glibc-rh1783303-6.patch b/glibc-rh1783303-6.patch new file mode 100755 index 0000000..7313bd6 --- /dev/null +++ b/glibc-rh1783303-6.patch @@ -0,0 +1,185 @@ +commit cd7ce12a027656ad3cda774454088de5a2c7fbfa +Author: Paul A. Clarke +Date: Fri Jul 12 20:13:58 2019 -0500 + + [powerpc] fe{en,dis}ableexcept optimize bit translations + + The exceptions passed to fe{en,dis}ableexcept() are defined in the ABI + as a bitmask, a combination of FE_INVALID, FE_OVERFLOW, etc. + Within the functions, these bits must be translated to/from the corresponding + enable bits in the Floating Point Status Control Register (FPSCR). + This translation is currently done bit-by-bit. The compiler generates + a series of conditional bit operations. Nicely, the "FE" exception + bits are all a uniform offset from the FPSCR enable bits, so the bit-by-bit + operation can instead be performed by a shift with appropriate masking. + +diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c +index 2daed44a419301e8..90bc3d12c6d8558c 100644 +--- a/sysdeps/powerpc/fpu/fedisblxcpt.c ++++ b/sysdeps/powerpc/fpu/fedisblxcpt.c +@@ -33,16 +33,7 @@ fedisableexcept (int excepts) + excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID; + + /* Sets the new exception mask. */ +- if (excepts & FE_INEXACT) +- fe.l &= ~(1 << (31 - FPSCR_XE)); +- if (excepts & FE_DIVBYZERO) +- fe.l &= ~(1 << (31 - FPSCR_ZE)); +- if (excepts & FE_UNDERFLOW) +- fe.l &= ~(1 << (31 - FPSCR_UE)); +- if (excepts & FE_OVERFLOW) +- fe.l &= ~(1 << (31 - FPSCR_OE)); +- if (excepts & FE_INVALID) +- fe.l &= ~(1 << (31 - FPSCR_VE)); ++ fe.l &= ~ fenv_exceptions_to_reg (excepts); + + if (fe.l != curr.l) + fesetenv_register (fe.fenv); +diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c +index 19cfe28e7aa307d4..e029971b9a460c28 100644 +--- a/sysdeps/powerpc/fpu/feenablxcpt.c ++++ b/sysdeps/powerpc/fpu/feenablxcpt.c +@@ -33,16 +33,7 @@ feenableexcept (int excepts) + excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID; + + /* Sets the new exception mask. */ +- if (excepts & FE_INEXACT) +- fe.l |= (1 << (31 - FPSCR_XE)); +- if (excepts & FE_DIVBYZERO) +- fe.l |= (1 << (31 - FPSCR_ZE)); +- if (excepts & FE_UNDERFLOW) +- fe.l |= (1 << (31 - FPSCR_UE)); +- if (excepts & FE_OVERFLOW) +- fe.l |= (1 << (31 - FPSCR_OE)); +- if (excepts & FE_INVALID) +- fe.l |= (1 << (31 - FPSCR_VE)); ++ fe.l |= fenv_exceptions_to_reg (excepts); + + if (fe.l != curr.l) + fesetenv_register (fe.fenv); +diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h +index 9dca6e760cc51946..f9634a64d186c076 100644 +--- a/sysdeps/powerpc/fpu/fenv_libc.h ++++ b/sysdeps/powerpc/fpu/fenv_libc.h +@@ -129,60 +129,108 @@ __fesetround_inline_nocheck (const int round) + asm volatile ("mtfsfi 7,%0" : : "i" (round)); + } + ++#define FPSCR_MASK(bit) (1 << (31 - (bit))) ++ + /* Definitions of all the FPSCR bit numbers */ + enum { + FPSCR_FX = 0, /* exception summary */ ++#define FPSCR_FX_MASK (FPSCR_MASK (FPSCR_FX)) + FPSCR_FEX, /* enabled exception summary */ ++#define FPSCR_FEX_MASK (FPSCR_MASK FPSCR_FEX)) + FPSCR_VX, /* invalid operation summary */ ++#define FPSCR_VX_MASK (FPSCR_MASK (FPSCR_VX)) + FPSCR_OX, /* overflow */ ++#define FPSCR_OX_MASK (FPSCR_MASK (FPSCR_OX)) + FPSCR_UX, /* underflow */ ++#define FPSCR_UX_MASK (FPSCR_MASK (FPSCR_UX)) + FPSCR_ZX, /* zero divide */ ++#define FPSCR_ZX_MASK (FPSCR_MASK (FPSCR_ZX)) + FPSCR_XX, /* inexact */ ++#define FPSCR_XX_MASK (FPSCR_MASK (FPSCR_XX)) + FPSCR_VXSNAN, /* invalid operation for sNaN */ ++#define FPSCR_VXSNAN_MASK (FPSCR_MASK (FPSCR_VXSNAN)) + FPSCR_VXISI, /* invalid operation for Inf-Inf */ ++#define FPSCR_VXISI_MASK (FPSCR_MASK (FPSCR_VXISI)) + FPSCR_VXIDI, /* invalid operation for Inf/Inf */ ++#define FPSCR_VXIDI_MASK (FPSCR_MASK (FPSCR_VXIDI)) + FPSCR_VXZDZ, /* invalid operation for 0/0 */ ++#define FPSCR_VXZDZ_MASK (FPSCR_MASK (FPSCR_VXZDZ)) + FPSCR_VXIMZ, /* invalid operation for Inf*0 */ ++#define FPSCR_VXIMZ_MASK (FPSCR_MASK (FPSCR_VXIMZ)) + FPSCR_VXVC, /* invalid operation for invalid compare */ ++#define FPSCR_VXVC_MASK (FPSCR_MASK (FPSCR_VXVC)) + FPSCR_FR, /* fraction rounded [fraction was incremented by round] */ ++#define FPSCR_FR_MASK (FPSCR_MASK (FPSCR_FR)) + FPSCR_FI, /* fraction inexact */ ++#define FPSCR_FI_MASK (FPSCR_MASK (FPSCR_FI)) + FPSCR_FPRF_C, /* result class descriptor */ ++#define FPSCR_FPRF_C_MASK (FPSCR_MASK (FPSCR_FPRF_C)) + FPSCR_FPRF_FL, /* result less than (usually, less than 0) */ ++#define FPSCR_FPRF_FL_MASK (FPSCR_MASK (FPSCR_FPRF_FL)) + FPSCR_FPRF_FG, /* result greater than */ ++#define FPSCR_FPRF_FG_MASK (FPSCR_MASK (FPSCR_FPRF_FG)) + FPSCR_FPRF_FE, /* result equal to */ ++#define FPSCR_FPRF_FE_MASK (FPSCR_MASK (FPSCR_FPRF_FE)) + FPSCR_FPRF_FU, /* result unordered */ ++#define FPSCR_FPRF_FU_MASK (FPSCR_MASK (FPSCR_FPRF_FU)) + FPSCR_20, /* reserved */ + FPSCR_VXSOFT, /* invalid operation set by software */ ++#define FPSCR_VXSOFT_MASK (FPSCR_MASK (FPSCR_VXSOFT)) + FPSCR_VXSQRT, /* invalid operation for square root */ ++#define FPSCR_VXSQRT_MASK (FPSCR_MASK (FPSCR_VXSQRT)) + FPSCR_VXCVI, /* invalid operation for invalid integer convert */ ++#define FPSCR_VXCVI_MASK (FPSCR_MASK (FPSCR_VXCVI)) + FPSCR_VE, /* invalid operation exception enable */ ++#define FPSCR_VE_MASK (FPSCR_MASK (FPSCR_VE)) + FPSCR_OE, /* overflow exception enable */ ++#define FPSCR_OE_MASK (FPSCR_MASK (FPSCR_OE)) + FPSCR_UE, /* underflow exception enable */ ++#define FPSCR_UE_MASK (FPSCR_MASK (FPSCR_UE)) + FPSCR_ZE, /* zero divide exception enable */ ++#define FPSCR_ZE_MASK (FPSCR_MASK (FPSCR_ZE)) + FPSCR_XE, /* inexact exception enable */ ++#define FPSCR_XE_MASK (FPSCR_MASK (FPSCR_XE)) + #ifdef _ARCH_PWR6 + FPSCR_29, /* Reserved in ISA 2.05 */ ++#define FPSCR_NI_MASK (FPSCR_MASK (FPSCR_29)) + #else +- FPSCR_NI /* non-IEEE mode (typically, no denormalised numbers) */ ++ FPSCR_NI, /* non-IEEE mode (typically, no denormalised numbers) */ ++#define FPSCR_NI_MASK (FPSCR_MASK (FPSCR_NI)) + #endif /* _ARCH_PWR6 */ + /* the remaining two least-significant bits keep the rounding mode */ ++ FPSCR_RN_hi, ++#define FPSCR_RN_hi_MASK (FPSCR_MASK (FPSCR_RN_hi)) ++ FPSCR_RN_lo ++#define FPSCR_RN_lo_MASK (FPSCR_MASK (FPSCR_RN_lo)) + }; + ++#define FPSCR_RN_MASK (FPSCR_RN_hi_MASK|FPSCR_RN_lo_MASK) ++#define FPSCR_ENABLES_MASK \ ++ (FPSCR_VE_MASK|FPSCR_OE_MASK|FPSCR_UE_MASK|FPSCR_ZE_MASK|FPSCR_XE_MASK) ++#define FPSCR_BASIC_EXCEPTIONS_MASK \ ++ (FPSCR_VX_MASK|FPSCR_OX_MASK|FPSCR_UX_MASK|FPSCR_ZX_MASK|FPSCR_XX_MASK) ++ ++#define FPSCR_CONTROL_MASK (FPSCR_ENABLES_MASK|FPSCR_NI_MASK|FPSCR_RN_MASK) ++ ++/* The bits in the FENV(1) ABI for exceptions correspond one-to-one with bits ++ in the FPSCR, albeit shifted to different but corresponding locations. ++ Similarly, the exception indicator bits in the FPSCR correspond one-to-one ++ with the exception enable bits. It is thus possible to map the FENV(1) ++ exceptions directly to the FPSCR enables with a simple mask and shift, ++ and vice versa. */ ++#define FPSCR_EXCEPT_TO_ENABLE_SHIFT 22 ++ + static inline int + fenv_reg_to_exceptions (unsigned long long l) + { +- int result = 0; +- if (l & (1 << (31 - FPSCR_XE))) +- result |= FE_INEXACT; +- if (l & (1 << (31 - FPSCR_ZE))) +- result |= FE_DIVBYZERO; +- if (l & (1 << (31 - FPSCR_UE))) +- result |= FE_UNDERFLOW; +- if (l & (1 << (31 - FPSCR_OE))) +- result |= FE_OVERFLOW; +- if (l & (1 << (31 - FPSCR_VE))) +- result |= FE_INVALID; +- return result; ++ return (((int)l) & FPSCR_ENABLES_MASK) << FPSCR_EXCEPT_TO_ENABLE_SHIFT; ++} ++ ++static inline unsigned long long ++fenv_exceptions_to_reg (int excepts) ++{ ++ return (unsigned long long) ++ (excepts & FE_ALL_EXCEPT) >> FPSCR_EXCEPT_TO_ENABLE_SHIFT; + } + + #ifdef _ARCH_PWR6 diff --git a/glibc-rh1783303-7.patch b/glibc-rh1783303-7.patch new file mode 100755 index 0000000..a74f2eb --- /dev/null +++ b/glibc-rh1783303-7.patch @@ -0,0 +1,174 @@ +commit 3c1766ea10043f2e9625f3cba3bda37c84b32cf0 +Author: Paul A. Clarke +Date: Thu Jul 18 19:37:13 2019 -0500 + + [powerpc] fe{en,dis}ableexcept, fesetmode: optimize FPSCR accesses + + Since fe{en,dis}ableexcept() and fesetmode() read-modify-write just the + "mode" (exception enable and rounding mode) bits of the Floating Point Status + Control Register (FPSCR), the lighter weight 'mffsl' instruction can be used + to read the FPSCR (enables and rounding mode), and 'mtfsf 0b00000011' can be + used to write just those bits back to the FPSCR. The net is better performance. + + In addition, fe{en,dis}ableexcept() read the FPSCR again after writing it, or + they determine that it doesn't need to be written because it is not changing. + In either case, the local variable holds the current values of the enable + bits in the FPSCR. This local variable can be used instead of again reading + the FPSCR. + + Also, that value of the FPSCR which is read the second time is validated + against the requested enables. Since the write can't fail, this validation + step is unnecessary, and can be removed. Instead, the exceptions to be + enabled (or disabled) are transformed into available bits in the FPSCR, + then validated after being transformed back, to ensure that all requested + bits are actually being set. For example, FE_INVALID_SQRT can be + requested, but cannot actually be set. This bit is not mapped during the + transformations, so a test for that bit being set before and after + transformations will show the bit would not be set, and the function will + return -1 for failure. + + Finally, convert the local macros in fesetmode.c to more generally useful + macros in fenv_libc.h. + +diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c +index 90bc3d12c6d8558c..2a776c72fb5a2b70 100644 +--- a/sysdeps/powerpc/fpu/fedisblxcpt.c ++++ b/sysdeps/powerpc/fpu/fedisblxcpt.c +@@ -26,23 +26,25 @@ fedisableexcept (int excepts) + int result, new; + + /* Get current exception mask to return. */ +- fe.fenv = curr.fenv = fegetenv_register (); ++ fe.fenv = curr.fenv = fegetenv_status (); + result = fenv_reg_to_exceptions (fe.l); + + if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID) + excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID; + ++ new = fenv_exceptions_to_reg (excepts); ++ ++ if (fenv_reg_to_exceptions (new) != excepts) ++ return -1; ++ + /* Sets the new exception mask. */ +- fe.l &= ~ fenv_exceptions_to_reg (excepts); ++ fe.l &= ~new; + + if (fe.l != curr.l) +- fesetenv_register (fe.fenv); ++ fesetenv_mode (fe.fenv); + +- new = __fegetexcept (); + if (new == 0 && result != 0) + (void)__fe_mask_env (); + +- if ((new & excepts) != 0) +- result = -1; + return result; + } +diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c +index e029971b9a460c28..6f5a828e80965bfa 100644 +--- a/sysdeps/powerpc/fpu/feenablxcpt.c ++++ b/sysdeps/powerpc/fpu/feenablxcpt.c +@@ -26,24 +26,25 @@ feenableexcept (int excepts) + int result, new; + + /* Get current exception mask to return. */ +- fe.fenv = curr.fenv = fegetenv_register (); ++ fe.fenv = curr.fenv = fegetenv_status (); + result = fenv_reg_to_exceptions (fe.l); + + if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID) + excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID; + ++ new = fenv_exceptions_to_reg (excepts); ++ ++ if (fenv_reg_to_exceptions (new) != excepts) ++ return -1; ++ + /* Sets the new exception mask. */ +- fe.l |= fenv_exceptions_to_reg (excepts); ++ fe.l |= new; + + if (fe.l != curr.l) +- fesetenv_register (fe.fenv); ++ fesetenv_mode (fe.fenv); + +- new = __fegetexcept (); + if (new != 0 && result == 0) + (void) __fe_nomask_env_priv (); + +- if ((new & excepts) != excepts) +- result = -1; +- + return result; + } +diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h +index f9634a64d186c076..b244770d115ea7bb 100644 +--- a/sysdeps/powerpc/fpu/fenv_libc.h ++++ b/sysdeps/powerpc/fpu/fenv_libc.h +@@ -71,6 +71,11 @@ extern const fenv_t *__fe_mask_env (void) attribute_hidden; + asm volatile ("mtfsf 0xff,%0" : : "f" (d)); \ + } while(0) + ++/* Set the last 2 nibbles of the FPSCR, which contain the ++ exception enables and the rounding mode. ++ 'fegetenv_status' retrieves these bits by reading the FPSCR. */ ++#define fesetenv_mode(env) __builtin_mtfsf (0b00000011, (env)); ++ + /* This very handy macro: + - Sets the rounding mode to 'round to nearest'; + - Sets the processor into IEEE mode; and +@@ -209,8 +214,11 @@ enum { + (FPSCR_VE_MASK|FPSCR_OE_MASK|FPSCR_UE_MASK|FPSCR_ZE_MASK|FPSCR_XE_MASK) + #define FPSCR_BASIC_EXCEPTIONS_MASK \ + (FPSCR_VX_MASK|FPSCR_OX_MASK|FPSCR_UX_MASK|FPSCR_ZX_MASK|FPSCR_XX_MASK) +- ++#define FPSCR_FPRF_MASK \ ++ (FPSCR_FPRF_C_MASK|FPSCR_FPRF_FL_MASK|FPSCR_FPRF_FG_MASK| \ ++ FPSCR_FPRF_FE_MASK|FPSCR_FPRF_FU_MASK) + #define FPSCR_CONTROL_MASK (FPSCR_ENABLES_MASK|FPSCR_NI_MASK|FPSCR_RN_MASK) ++#define FPSCR_STATUS_MASK (FPSCR_FR_MASK|FPSCR_FI_MASK|FPSCR_FPRF_MASK) + + /* The bits in the FENV(1) ABI for exceptions correspond one-to-one with bits + in the FPSCR, albeit shifted to different but corresponding locations. +diff --git a/sysdeps/powerpc/fpu/fesetmode.c b/sysdeps/powerpc/fpu/fesetmode.c +index 32203a24ff434a32..29e088d5ab1c0d93 100644 +--- a/sysdeps/powerpc/fpu/fesetmode.c ++++ b/sysdeps/powerpc/fpu/fesetmode.c +@@ -19,11 +19,6 @@ + #include + #include + +-#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM \ +- | _FPU_MASK_XM | _FPU_MASK_IM) +- +-#define FPU_STATUS 0xbffff700ULL +- + int + fesetmode (const femode_t *modep) + { +@@ -32,18 +27,18 @@ fesetmode (const femode_t *modep) + /* Logic regarding enabled exceptions as in fesetenv. */ + + new.fenv = *modep; +- old.fenv = fegetenv_register (); +- new.l = (new.l & ~FPU_STATUS) | (old.l & FPU_STATUS); ++ old.fenv = fegetenv_status (); ++ new.l = (new.l & ~FPSCR_STATUS_MASK) | (old.l & FPSCR_STATUS_MASK); + + if (old.l == new.l) + return 0; + +- if ((old.l & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0) ++ if ((old.l & FPSCR_ENABLES_MASK) == 0 && (new.l & FPSCR_ENABLES_MASK) != 0) + (void) __fe_nomask_env_priv (); + +- if ((old.l & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0) ++ if ((old.l & FPSCR_ENABLES_MASK) != 0 && (new.l & FPSCR_ENABLES_MASK) == 0) + (void) __fe_mask_env (); + +- fesetenv_register (new.fenv); ++ fesetenv_mode (new.fenv); + return 0; + } diff --git a/glibc-rh1783303-8.patch b/glibc-rh1783303-8.patch new file mode 100755 index 0000000..142e3bb --- /dev/null +++ b/glibc-rh1783303-8.patch @@ -0,0 +1,124 @@ +commit e905212627350d54b58426214b5a54ddc852b0c9 +Author: Paul A. Clarke +Date: Fri Aug 2 22:47:57 2019 -0400 + + [powerpc] SET_RESTORE_ROUND improvements + + SET_RESTORE_ROUND uses libc_feholdsetround_ppc_ctx and + libc_feresetround_ppc_ctx to bracket a block of code where the floating point + rounding mode must be set to a certain value. + + For the *prologue*, libc_feholdsetround_ppc_ctx is used and performs: + 1. Read/save FPSCR. + 2. Create new value for FPSCR with new rounding mode and enables cleared. + 3. If new value is different than current value, + a. If transitioning from a state where some exceptions enabled, + enter "ignore exceptions / non-stop" mode. + b. Write new value to FPSCR. + c. Put a mark on the wall indicating the FPSCR was changed. + + (1) uses the 'mffs' instruction. On POWER9, the lighter weight 'mffsl' + instruction can be used, but it doesn't return all of the bits in the FPSCR. + fegetenv_status uses 'mffsl' on POWER9, 'mffs' otherwise, and can thus be + used instead of fegetenv_register. + (3b) uses 'mtfsf 0b11111111' to write the entire FPSCR, so it must + instead use 'mtfsf 0b00000011' to write just the enables and the mode, + because some of the rest of the bits are not valid if 'mffsl' was used. + fesetenv_mode uses 'mtfsf 0b00000011' on POWER9, 'mtfsf 0b11111111' + otherwise. + + For the *epilogue*, libc_feresetround_ppc_ctx checks the mark on the wall, then + calls libc_feresetround_ppc, which just calls __libc_femergeenv_ppc with + parameters such that it performs: + 1. Retreive saved value of FPSCR, saved in prologue above. + 2. Read FPSCR. + 3. Create new value of FPSCR where: + - Summary bits and exception indicators = current OR saved. + - Rounding mode and enables = saved. + - Status bits = current. + 4. If transitioning from some exceptions enabled to none, + enter "ignore exceptions / non-stop" mode. + 5. If transitioning from no exceptions enabled to some, + enter "catch exceptions" mode. + 6. Write new value to FPSCR. + + The summary bits are hardwired to the exception indicators, so there is no + need to restore any saved summary bits. + The exception indicator bits, which are sticky and remain set unless + explicitly cleared, would only need to be restored if the code block + might explicitly clear any of them. This is certainly not expected. + + So, the only bits that need to be restored are the enables and the mode. + If it is the case that only those bits are to be restored, there is no need to + read the FPSCR. Steps (2) and (3) are unnecessary, and step (6) only needs to + write the bits being restored. + + We know we are transitioning out of "ignore exceptions" mode, so step (4) is + unnecessary, and in step (6), we only need to check the state we are + entering. + +diff --git a/sysdeps/powerpc/fpu/fenv_private.h b/sysdeps/powerpc/fpu/fenv_private.h +index 945ab98018450092..b0149aa243e69f5a 100644 +--- a/sysdeps/powerpc/fpu/fenv_private.h ++++ b/sysdeps/powerpc/fpu/fenv_private.h +@@ -132,7 +132,17 @@ libc_fesetenv_ppc (const fenv_t *envp) + static __always_inline void + libc_feresetround_ppc (fenv_t *envp) + { +- __libc_femergeenv_ppc (envp, _FPU_MASK_TRAPS_RN, _FPU_MASK_FRAC_INEX_RET_CC); ++ fenv_union_t new = { .fenv = *envp }; ++ ++ /* If the old env has no enabled exceptions and the new env has any enabled ++ exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the ++ hardware into "precise mode" and may cause the FPU to run slower on some ++ hardware. */ ++ if ((new.l & _FPU_ALL_TRAPS) != 0) ++ (void) __fe_nomask_env_priv (); ++ ++ /* Atomically enable and raise (if appropriate) exceptions set in `new'. */ ++ fesetenv_mode (new.fenv); + } + + static __always_inline int +@@ -176,9 +186,30 @@ libc_feholdsetround_ppc_ctx (struct rm_ctx *ctx, int r) + { + fenv_union_t old, new; + ++ old.fenv = fegetenv_status (); ++ ++ new.l = (old.l & ~(FPSCR_ENABLES_MASK|FPSCR_RN_MASK)) | r; ++ ++ ctx->env = old.fenv; ++ if (__glibc_unlikely (new.l != old.l)) ++ { ++ if ((old.l & _FPU_ALL_TRAPS) != 0) ++ (void) __fe_mask_env (); ++ fesetenv_mode (new.fenv); ++ ctx->updated_status = true; ++ } ++ else ++ ctx->updated_status = false; ++} ++ ++static __always_inline void ++libc_feholdsetround_noex_ppc_ctx (struct rm_ctx *ctx, int r) ++{ ++ fenv_union_t old, new; ++ + old.fenv = fegetenv_register (); + +- new.l = (old.l & _FPU_MASK_TRAPS_RN) | r; ++ new.l = (old.l & ~(FPSCR_ENABLES_MASK|FPSCR_RN_MASK)) | r; + + ctx->env = old.fenv; + if (__glibc_unlikely (new.l != old.l)) +@@ -218,6 +249,9 @@ libc_feresetround_ppc_ctx (struct rm_ctx *ctx) + #define libc_feholdsetround_ctx libc_feholdsetround_ppc_ctx + #define libc_feholdsetroundf_ctx libc_feholdsetround_ppc_ctx + #define libc_feholdsetroundl_ctx libc_feholdsetround_ppc_ctx ++#define libc_feholdsetround_noex_ctx libc_feholdsetround_noex_ppc_ctx ++#define libc_feholdsetround_noexf_ctx libc_feholdsetround_noex_ppc_ctx ++#define libc_feholdsetround_noexl_ctx libc_feholdsetround_noex_ppc_ctx + #define libc_feresetround_ctx libc_feresetround_ppc_ctx + #define libc_feresetroundf_ctx libc_feresetround_ppc_ctx + #define libc_feresetroundl_ctx libc_feresetround_ppc_ctx diff --git a/glibc-rh1783303-9.patch b/glibc-rh1783303-9.patch new file mode 100755 index 0000000..e151082 --- /dev/null +++ b/glibc-rh1783303-9.patch @@ -0,0 +1,61 @@ +commit fec2bd2c2d31bc731cf61623e150d047746954bd +Author: Paul A. Clarke +Date: Tue Aug 6 00:13:45 2019 -0400 + + [powerpc] fesetenv: optimize FPSCR access + + fesetenv() reads the current value of the Floating-Point Status and Control + Register (FPSCR) to determine the difference between the current state of + exception enables and the newly requested state. All of these bits are also + returned by the lighter weight 'mffsl' instruction used by fegetenv_status(). + Use that instead. + + Also, remove a local macro _FPU_MASK_ALL in favor of a common macro, + FPU_ENABLES_MASK from fenv_libc.h. + + Finally, use a local variable ('new') in favor of a pointer dereference + ('*envp'). + +diff --git a/sysdeps/powerpc/fpu/fesetenv.c b/sysdeps/powerpc/fpu/fesetenv.c +index ad9fda15b12f15e3..ac927c8f3ada40b4 100644 +--- a/sysdeps/powerpc/fpu/fesetenv.c ++++ b/sysdeps/powerpc/fpu/fesetenv.c +@@ -19,8 +19,6 @@ + #include + #include + +-#define _FPU_MASK_ALL (_FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM | _FPU_MASK_XM | _FPU_MASK_IM) +- + int + __fesetenv (const fenv_t *envp) + { +@@ -28,25 +26,23 @@ __fesetenv (const fenv_t *envp) + + /* get the currently set exceptions. */ + new.fenv = *envp; +- old.fenv = fegetenv_register (); +- if (old.l == new.l) +- return 0; ++ old.fenv = fegetenv_status (); + + /* If the old env has no enabled exceptions and the new env has any enabled + exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the + hardware into "precise mode" and may cause the FPU to run slower on some + hardware. */ +- if ((old.l & _FPU_MASK_ALL) == 0 && (new.l & _FPU_MASK_ALL) != 0) ++ if ((old.l & FPSCR_ENABLES_MASK) == 0 && (new.l & FPSCR_ENABLES_MASK) != 0) + (void) __fe_nomask_env_priv (); + + /* If the old env had any enabled exceptions and the new env has no enabled + exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the + FPU to run faster because it always takes the default action and can not + generate SIGFPE. */ +- if ((old.l & _FPU_MASK_ALL) != 0 && (new.l & _FPU_MASK_ALL) == 0) ++ if ((old.l & FPSCR_ENABLES_MASK) != 0 && (new.l & FPSCR_ENABLES_MASK) == 0) + (void)__fe_mask_env (); + +- fesetenv_register (*envp); ++ fesetenv_register (new.fenv); + + /* Success. */ + return 0; diff --git a/glibc-rh1784519.patch b/glibc-rh1784519.patch new file mode 100755 index 0000000..c9779d1 --- /dev/null +++ b/glibc-rh1784519.patch @@ -0,0 +1,29 @@ +commit 953ceff17a4a15b10cfdd5edc3c8cae4884c8ec3 +Author: Kamlesh Kumar +Date: Thu Dec 5 16:49:00 2019 +0100 + + : Define __CORRECT_ISO_CPP_STRING_H_PROTO for Clang [BZ #25232] + + Without the asm redirects, strchr et al. are not const-correct. + + libc++ has a wrapper header that works with and without + __CORRECT_ISO_CPP_STRING_H_PROTO (using a Clang extension). But when + Clang is used with libstdc++ or just C headers, the overloaded functions + with the correct types are not declared. + + This change does not impact current GCC (with libstdc++ or libc++). + +diff --git a/string/string.h b/string/string.h +index 73c22a535a..faf997b972 100644 +--- a/string/string.h ++++ b/string/string.h +@@ -33,7 +33,8 @@ __BEGIN_DECLS + #include + + /* Tell the caller that we provide correct C++ prototypes. */ +-#if defined __cplusplus && __GNUC_PREREQ (4, 4) ++#if defined __cplusplus && (__GNUC_PREREQ (4, 4) \ ++ || __glibc_clang_prereq (3, 5)) + # define __CORRECT_ISO_CPP_STRING_H_PROTO + #endif + diff --git a/glibc-rh1784520.patch b/glibc-rh1784520.patch new file mode 100755 index 0000000..90e9d77 --- /dev/null +++ b/glibc-rh1784520.patch @@ -0,0 +1,121 @@ +commit 16554464bcd9d77b07c6ff419dc54f00e394fa50 +Author: DJ Delorie +Date: Tue Dec 3 17:44:36 2019 -0500 + + Correct range checking in mallopt/mxfast/tcache [BZ #25194] + + do_set_tcache_max, do_set_mxfast: + Fix two instances of comparing "size_t < 0" + Both cases have upper limit, so the "negative value" case + is already handled via overflow semantics. + + do_set_tcache_max, do_set_tcache_count: + Fix return value on error. Note: currently not used. + + mallopt: + pass return value of helper functions to user. Behavior should + only be actually changed for mxfast, where we restore the old + (pre-tunables) behavior. + + Reviewed-by: Carlos O'Donell + +diff --git a/malloc/malloc.c b/malloc/malloc.c +index 90825b2aaed53761..00a37f218c0ab3b2 100644 +--- a/malloc/malloc.c ++++ b/malloc/malloc.c +@@ -5111,13 +5111,14 @@ static inline int + __always_inline + do_set_tcache_max (size_t value) + { +- if (value >= 0 && value <= MAX_TCACHE_SIZE) ++ if (value <= MAX_TCACHE_SIZE) + { + LIBC_PROBE (memory_tunable_tcache_max_bytes, 2, value, mp_.tcache_max_bytes); + mp_.tcache_max_bytes = value; + mp_.tcache_bins = csize2tidx (request2size(value)) + 1; ++ return 1; + } +- return 1; ++ return 0; + } + + static inline int +@@ -5128,8 +5129,9 @@ do_set_tcache_count (size_t value) + { + LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count); + mp_.tcache_count = value; ++ return 1; + } +- return 1; ++ return 0; + } + + static inline int +@@ -5146,7 +5148,7 @@ static inline int + __always_inline + do_set_mxfast (size_t value) + { +- if (value >= 0 && value <= MAX_FAST_SIZE) ++ if (value <= MAX_FAST_SIZE) + { + LIBC_PROBE (memory_mallopt_mxfast, 2, value, get_max_fast ()); + set_max_fast (value); +@@ -5171,18 +5173,24 @@ __libc_mallopt (int param_number, int value) + (see definition of set_max_fast). */ + malloc_consolidate (av); + ++ /* Many of these helper functions take a size_t. We do not worry ++ about overflow here, because negative int values will wrap to ++ very large size_t values and the helpers have sufficient range ++ checking for such conversions. Many of these helpers are also ++ used by the tunables macros in arena.c. */ ++ + switch (param_number) + { + case M_MXFAST: +- do_set_mxfast (value); ++ res = do_set_mxfast (value); + break; + + case M_TRIM_THRESHOLD: +- do_set_trim_threshold (value); ++ res = do_set_trim_threshold (value); + break; + + case M_TOP_PAD: +- do_set_top_pad (value); ++ res = do_set_top_pad (value); + break; + + case M_MMAP_THRESHOLD: +@@ -5190,25 +5198,25 @@ __libc_mallopt (int param_number, int value) + break; + + case M_MMAP_MAX: +- do_set_mmaps_max (value); ++ res = do_set_mmaps_max (value); + break; + + case M_CHECK_ACTION: +- do_set_mallopt_check (value); ++ res = do_set_mallopt_check (value); + break; + + case M_PERTURB: +- do_set_perturb_byte (value); ++ res = do_set_perturb_byte (value); + break; + + case M_ARENA_TEST: + if (value > 0) +- do_set_arena_test (value); ++ res = do_set_arena_test (value); + break; + + case M_ARENA_MAX: + if (value > 0) +- do_set_arena_max (value); ++ res = do_set_arena_max (value); + break; + } + __libc_lock_unlock (av->mutex); diff --git a/glibc-rh1784525.patch b/glibc-rh1784525.patch new file mode 100755 index 0000000..3a5f000 --- /dev/null +++ b/glibc-rh1784525.patch @@ -0,0 +1,29 @@ +commit ef21bd2d8c6805c0c186a01f7c5039189f51b8c4 +Author: DJ Delorie +Date: Fri Oct 18 17:15:52 2019 -0400 + + loadarchive: guard against locale-archive corruption (Bug #25115) + + _nl_load_locale_from_archive() checks for a zero size, but + divides by both (size) and (size-2). Extend the check to + guard against a size of two or less. + + Tested by manually corrupting locale-archive and running a program + that calls setlocale() with LOCPATH unset (size is typically very + large). + + Reviewed-by: Carlos O'Donell + +diff --git a/locale/loadarchive.c b/locale/loadarchive.c +index 516d30d8d16bd578..b308fd886f44e1fd 100644 +--- a/locale/loadarchive.c ++++ b/locale/loadarchive.c +@@ -274,7 +274,7 @@ _nl_load_locale_from_archive (int category, const char **namep) + + head->namehash_offset); + + /* Avoid division by 0 if the file is corrupted. */ +- if (__glibc_unlikely (head->namehash_size == 0)) ++ if (__glibc_unlikely (head->namehash_size <= 2)) + goto close_and_out; + + idx = hval % head->namehash_size; diff --git a/glibc-rh1810142-1.patch b/glibc-rh1810142-1.patch new file mode 100755 index 0000000..4a6d2e9 --- /dev/null +++ b/glibc-rh1810142-1.patch @@ -0,0 +1,382 @@ +From: Florian Weimer +Date: Tue, 11 Feb 2020 12:52:06 +0000 (+0100) +Subject: Add internal header file +X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=6c80c6e8767b860a5e18e136d04a80be2a8dce15 + +Add internal header file + +The code started out with bits form resolv/resolv_conf.c, but it +was enhanced to deal with directories and FIFOs in a more predictable +manner. A test case is included as well. + +This will be used to implement the /etc/resolv.conf change detection. + +This currently lives in a header file only. Once there are multiple +users, the implementations should be moved into C files. +--- + +diff -rupN a/include/file_change_detection.h b/include/file_change_detection.h +--- a/include/file_change_detection.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/include/file_change_detection.h 2020-03-25 16:57:24.227929816 -0400 +@@ -0,0 +1,140 @@ ++/* Detecting file changes using modification times. ++ Copyright (C) 2017-2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Items for identifying a particular file version. Excerpt from ++ struct stat64. */ ++struct file_change_detection ++{ ++ /* Special values: 0 if file does not exist. -1 to force mismatch ++ with the next comparison. */ ++ off64_t size; ++ ++ ino64_t ino; ++ struct timespec mtime; ++ struct timespec ctime; ++}; ++ ++/* Returns true if *LEFT and *RIGHT describe the same version of the ++ same file. */ ++static bool __attribute__ ((unused)) ++file_is_unchanged (const struct file_change_detection *left, ++ const struct file_change_detection *right) ++{ ++ if (left->size < 0 || right->size < 0) ++ /* Negative sizes are used as markers and never match. */ ++ return false; ++ else if (left->size == 0 && right->size == 0) ++ /* Both files are empty or do not exist, so they have the same ++ content, no matter what the other fields indicate. */ ++ return true; ++ else ++ return left->size == right->size ++ && left->ino == right->ino ++ && left->mtime.tv_sec == right->mtime.tv_sec ++ && left->mtime.tv_nsec == right->mtime.tv_nsec ++ && left->ctime.tv_sec == right->ctime.tv_sec ++ && left->ctime.tv_nsec == right->ctime.tv_nsec; ++} ++ ++/* Extract file change information to *FILE from the stat buffer ++ *ST. */ ++static void __attribute__ ((unused)) ++file_change_detection_for_stat (struct file_change_detection *file, ++ const struct stat64 *st) ++{ ++ if (S_ISDIR (st->st_mode)) ++ /* Treat as empty file. */ ++ file->size = 0; ++ else if (!S_ISREG (st->st_mode)) ++ /* Non-regular files cannot be cached. */ ++ file->size = -1; ++ else ++ { ++ file->size = st->st_size; ++ file->ino = st->st_ino; ++ file->mtime = st->st_mtim; ++ file->ctime = st->st_ctim; ++ } ++} ++ ++/* Writes file change information for PATH to *FILE. Returns true on ++ success. For benign errors, *FILE is cleared, and true is ++ returned. For errors indicating resource outages and the like, ++ false is returned. */ ++static bool __attribute__ ((unused)) ++file_change_detection_for_path (struct file_change_detection *file, ++ const char *path) ++{ ++ struct stat64 st; ++ if (stat64 (path, &st) != 0) ++ switch (errno) ++ { ++ case EACCES: ++ case EISDIR: ++ case ELOOP: ++ case ENOENT: ++ case ENOTDIR: ++ case EPERM: ++ /* Ignore errors due to file system contents. Instead, treat ++ the file as empty. */ ++ file->size = 0; ++ return true; ++ default: ++ /* Other errors are fatal. */ ++ return false; ++ } ++ else /* stat64 was successfull. */ ++ { ++ file_change_detection_for_stat (file, &st); ++ return true; ++ } ++} ++ ++/* Writes file change information for the stream FP to *FILE. Returns ++ ture on success, false on failure. If FP is NULL, treat the file ++ as non-existing. */ ++static bool __attribute__ ((unused)) ++file_change_detection_for_fp (struct file_change_detection *file, ++ FILE *fp) ++{ ++ if (fp == NULL) ++ { ++ /* The file does not exist. */ ++ file->size = 0; ++ return true; ++ } ++ else ++ { ++ struct stat64 st; ++ if (fstat64 (__fileno (fp), &st) != 0) ++ /* If we already have a file descriptor, all errors are fatal. */ ++ return false; ++ else ++ { ++ file_change_detection_for_stat (file, &st); ++ return true; ++ } ++ } ++} +diff -rupN a/io/Makefile b/io/Makefile +--- a/io/Makefile 2020-03-25 16:55:42.442195992 -0400 ++++ b/io/Makefile 2020-03-25 16:58:48.571023810 -0400 +@@ -74,6 +74,7 @@ tests := test-utime test-stat test-stat + tst-posix_fallocate tst-posix_fallocate64 \ + tst-fts tst-fts-lfs tst-open-tmpfile \ + tst-copy_file_range tst-getcwd-abspath \ ++ tst-file_change_detection + + # Likewise for statx, but we do not need static linking here. + tests-internal += tst-statx +diff -rupN a/io/tst-file_change_detection.c b/io/tst-file_change_detection.c +--- a/io/tst-file_change_detection.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/io/tst-file_change_detection.c 2020-03-25 16:57:24.242930366 -0400 +@@ -0,0 +1,206 @@ ++/* Test for . ++ Copyright (C) 2020 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 ++ . */ ++ ++/* The header uses the internal __fileno symbol, which is not ++ available outside of libc (even to internal tests). */ ++#define __fileno(fp) fileno (fp) ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void ++all_same (struct file_change_detection *array, size_t length) ++{ ++ for (size_t i = 0; i < length; ++i) ++ for (size_t j = 0; j < length; ++j) ++ { ++ if (test_verbose > 0) ++ printf ("info: comparing %zu and %zu\n", i, j); ++ TEST_VERIFY (file_is_unchanged (array + i, array + j)); ++ } ++} ++ ++static void ++all_different (struct file_change_detection *array, size_t length) ++{ ++ for (size_t i = 0; i < length; ++i) ++ for (size_t j = 0; j < length; ++j) ++ { ++ if (i == j) ++ continue; ++ if (test_verbose > 0) ++ printf ("info: comparing %zu and %zu\n", i, j); ++ TEST_VERIFY (!file_is_unchanged (array + i, array + j)); ++ } ++} ++ ++static int ++do_test (void) ++{ ++ /* Use a temporary directory with various paths. */ ++ char *tempdir = support_create_temp_directory ("tst-file_change_detection-"); ++ ++ char *path_dangling = xasprintf ("%s/dangling", tempdir); ++ char *path_does_not_exist = xasprintf ("%s/does-not-exist", tempdir); ++ char *path_empty1 = xasprintf ("%s/empty1", tempdir); ++ char *path_empty2 = xasprintf ("%s/empty2", tempdir); ++ char *path_fifo = xasprintf ("%s/fifo", tempdir); ++ char *path_file1 = xasprintf ("%s/file1", tempdir); ++ char *path_file2 = xasprintf ("%s/file2", tempdir); ++ char *path_loop = xasprintf ("%s/loop", tempdir); ++ char *path_to_empty1 = xasprintf ("%s/to-empty1", tempdir); ++ char *path_to_file1 = xasprintf ("%s/to-file1", tempdir); ++ ++ add_temp_file (path_dangling); ++ add_temp_file (path_empty1); ++ add_temp_file (path_empty2); ++ add_temp_file (path_fifo); ++ add_temp_file (path_file1); ++ add_temp_file (path_file2); ++ add_temp_file (path_loop); ++ add_temp_file (path_to_empty1); ++ add_temp_file (path_to_file1); ++ ++ xsymlink ("target-does-not-exist", path_dangling); ++ support_write_file_string (path_empty1, ""); ++ support_write_file_string (path_empty2, ""); ++ TEST_COMPARE (mknod (path_fifo, 0777 | S_IFIFO, 0), 0); ++ support_write_file_string (path_file1, "line\n"); ++ support_write_file_string (path_file2, "line\n"); ++ xsymlink ("loop", path_loop); ++ xsymlink ("empty1", path_to_empty1); ++ xsymlink ("file1", path_to_file1); ++ ++ FILE *fp_file1 = xfopen (path_file1, "r"); ++ FILE *fp_file2 = xfopen (path_file2, "r"); ++ FILE *fp_empty1 = xfopen (path_empty1, "r"); ++ FILE *fp_empty2 = xfopen (path_empty2, "r"); ++ ++ /* Test for the same (empty) files. */ ++ { ++ struct file_change_detection fcd[10]; ++ int i = 0; ++ /* Two empty files always have the same contents. */ ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_empty1)); ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_empty2)); ++ /* So does a missing file (which is treated as empty). */ ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], ++ path_does_not_exist)); ++ /* And a symbolic link loop. */ ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_loop)); ++ /* And a dangling symbolic link. */ ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_dangling)); ++ /* And a directory. */ ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], tempdir)); ++ /* And a symbolic link to an empty file. */ ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_to_empty1)); ++ /* Likewise for access the file via a FILE *. */ ++ TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], fp_empty1)); ++ TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], fp_empty2)); ++ /* And a NULL FILE * (missing file). */ ++ TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], NULL)); ++ TEST_COMPARE (i, array_length (fcd)); ++ ++ all_same (fcd, array_length (fcd)); ++ } ++ ++ /* Symbolic links are resolved. */ ++ { ++ struct file_change_detection fcd[3]; ++ int i = 0; ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_file1)); ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_to_file1)); ++ TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], fp_file1)); ++ TEST_COMPARE (i, array_length (fcd)); ++ all_same (fcd, array_length (fcd)); ++ } ++ ++ /* Test for different files. */ ++ { ++ struct file_change_detection fcd[5]; ++ int i = 0; ++ /* The other files are not empty. */ ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_empty1)); ++ /* These two files have the same contents, but have different file ++ identity. */ ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_file1)); ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_file2)); ++ /* FIFOs are always different, even with themselves. */ ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_fifo)); ++ TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_fifo)); ++ TEST_COMPARE (i, array_length (fcd)); ++ all_different (fcd, array_length (fcd)); ++ ++ /* Replacing the file with its symbolic link does not make a ++ difference. */ ++ TEST_VERIFY (file_change_detection_for_path (&fcd[1], path_to_file1)); ++ all_different (fcd, array_length (fcd)); ++ } ++ ++ /* Wait for a file change. Depending on file system time stamp ++ resolution, this subtest blocks for a while. */ ++ for (int use_stdio = 0; use_stdio < 2; ++use_stdio) ++ { ++ struct file_change_detection initial; ++ TEST_VERIFY (file_change_detection_for_path (&initial, path_file1)); ++ while (true) ++ { ++ support_write_file_string (path_file1, "line\n"); ++ struct file_change_detection current; ++ if (use_stdio) ++ TEST_VERIFY (file_change_detection_for_fp (¤t, fp_file1)); ++ else ++ TEST_VERIFY (file_change_detection_for_path (¤t, path_file1)); ++ if (!file_is_unchanged (&initial, ¤t)) ++ break; ++ /* Wait for a bit to reduce system load. */ ++ usleep (100 * 1000); ++ } ++ } ++ ++ fclose (fp_empty1); ++ fclose (fp_empty2); ++ fclose (fp_file1); ++ fclose (fp_file2); ++ ++ free (path_dangling); ++ free (path_does_not_exist); ++ free (path_empty1); ++ free (path_empty2); ++ free (path_fifo); ++ free (path_file1); ++ free (path_file2); ++ free (path_loop); ++ free (path_to_empty1); ++ free (path_to_file1); ++ ++ free (tempdir); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1810142-2.patch b/glibc-rh1810142-2.patch new file mode 100755 index 0000000..cd7b4e4 --- /dev/null +++ b/glibc-rh1810142-2.patch @@ -0,0 +1,94 @@ +From: Florian Weimer +Date: Tue, 21 Jan 2020 15:52:33 +0000 (+0100) +Subject: resolv: Use in __resolv_conf_get_current +X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=9642b85fd0dfa5731020a3271c08e33e1dc05c85 + +resolv: Use in __resolv_conf_get_current + +Only minor functional changes (i.e., regarding the handling of +directories, which are now treated as empty files). + +Reviewed-by: Adhemerval Zanella +--- + +diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c +index 08c50ef19e..d954ba9a5a 100644 +--- a/resolv/resolv_conf.c ++++ b/resolv/resolv_conf.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + /* _res._u._ext.__glibc_extension_index is used as an index into a + struct resolv_conf_array object. The intent of this construction +@@ -68,12 +69,8 @@ struct resolv_conf_global + /* Cached current configuration object for /etc/resolv.conf. */ + struct resolv_conf *conf_current; + +- /* These properties of /etc/resolv.conf are used to check if the +- configuration needs reloading. */ +- struct timespec conf_mtime; +- struct timespec conf_ctime; +- off64_t conf_size; +- ino64_t conf_ino; ++ /* File system identification for /etc/resolv.conf. */ ++ struct file_change_detection file_resolve_conf; + }; + + /* Lazily allocated storage for struct resolv_conf_global. */ +@@ -123,37 +120,16 @@ conf_decrement (struct resolv_conf *conf) + struct resolv_conf * + __resolv_conf_get_current (void) + { +- struct stat64 st; +- if (stat64 (_PATH_RESCONF, &st) != 0) +- { +- switch (errno) +- { +- case EACCES: +- case EISDIR: +- case ELOOP: +- case ENOENT: +- case ENOTDIR: +- case EPERM: +- /* Ignore errors due to file system contents. */ +- memset (&st, 0, sizeof (st)); +- break; +- default: +- /* Other errors are fatal. */ +- return NULL; +- } +- } ++ struct file_change_detection initial; ++ if (!file_change_detection_for_path (&initial, _PATH_RESCONF)) ++ return NULL; + + struct resolv_conf_global *global_copy = get_locked_global (); + if (global_copy == NULL) + return NULL; + struct resolv_conf *conf; + if (global_copy->conf_current != NULL +- && (global_copy->conf_mtime.tv_sec == st.st_mtim.tv_sec +- && global_copy->conf_mtime.tv_nsec == st.st_mtim.tv_nsec +- && global_copy->conf_ctime.tv_sec == st.st_ctim.tv_sec +- && global_copy->conf_ctime.tv_nsec == st.st_ctim.tv_nsec +- && global_copy->conf_ino == st.st_ino +- && global_copy->conf_size == st.st_size)) ++ && file_is_unchanged (&initial, &global_copy->file_resolve_conf)) + /* We can reuse the cached configuration object. */ + conf = global_copy->conf_current; + else +@@ -171,10 +147,7 @@ __resolv_conf_get_current (void) + read could be a newer version of the file, but this does + not matter because this will lead to an extraneous reload + later. */ +- global_copy->conf_mtime = st.st_mtim; +- global_copy->conf_ctime = st.st_ctim; +- global_copy->conf_ino = st.st_ino; +- global_copy->conf_size = st.st_size; ++ global_copy->file_resolve_conf = initial; + } + } + diff --git a/glibc-rh1810142-3.patch b/glibc-rh1810142-3.patch new file mode 100755 index 0000000..e13f74d --- /dev/null +++ b/glibc-rh1810142-3.patch @@ -0,0 +1,46 @@ +From: Florian Weimer +Date: Tue, 21 Jan 2020 16:11:01 +0000 (+0100) +Subject: resolv: Fix file handle leak in __resolv_conf_load [BZ #25429] +X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=a1a20f029299dc27170912bb9233070c8403444d + +resolv: Fix file handle leak in __resolv_conf_load [BZ #25429] + +res_vinit_1 did not close the stream on errors, only on success. +This change moves closing the stream to __resolv_conf_load, for both +the success and error cases. + +Fixes commit 89f187a40fc0ad4e22838526bfe34d73f758b776 ("resolv: Use +getline for configuration file reading in res_vinit_1") and commit +3f853f22c87f0b671c0366eb290919719fa56c0e ("resolv: Lift domain search +list limits [BZ #19569] [BZ #21475]"), where memory allocation was +introduced into res_vinit_1. + +Reviewed-by: Adhemerval Zanella +--- + +diff --git a/resolv/res_init.c b/resolv/res_init.c +index 95dce098aa..09345718cd 100644 +--- a/resolv/res_init.c ++++ b/resolv/res_init.c +@@ -508,7 +508,6 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + continue; + } + } +- fclose (fp); + } + if (__glibc_unlikely (nameserver_list_size (&parser->nameserver_list) == 0)) + { +@@ -593,6 +592,13 @@ __resolv_conf_load (struct __res_state *preinit) + } + resolv_conf_parser_free (&parser); + ++ if (fp != NULL) ++ { ++ int saved_errno = errno; ++ fclose (fp); ++ __set_errno (saved_errno); ++ } ++ + return conf; + } + diff --git a/glibc-rh1810142-4.patch b/glibc-rh1810142-4.patch new file mode 100755 index 0000000..3d4ff39 --- /dev/null +++ b/glibc-rh1810142-4.patch @@ -0,0 +1,96 @@ +From: Florian Weimer +Date: Tue, 21 Jan 2020 16:25:39 +0000 (+0100) +Subject: resolv: Enhance __resolv_conf_load to capture file change data +X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=dd0b4df329ff7ff2a656404db271c8ee8379ff9d + +resolv: Enhance __resolv_conf_load to capture file change data + +The data is captured after reading the file. This allows callers +to check the change data against an earlier measurement. + +Reviewed-by: Adhemerval Zanella +--- + +diff --git a/resolv/res_init.c b/resolv/res_init.c +index 09345718cd..98d84f264d 100644 +--- a/resolv/res_init.c ++++ b/resolv/res_init.c +@@ -103,6 +103,7 @@ + #include + #include + #include ++#include + + static uint32_t net_mask (struct in_addr); + +@@ -549,7 +550,8 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) + } + + struct resolv_conf * +-__resolv_conf_load (struct __res_state *preinit) ++__resolv_conf_load (struct __res_state *preinit, ++ struct file_change_detection *change) + { + /* Ensure that /etc/hosts.conf has been loaded (once). */ + _res_hconf_init (); +@@ -577,7 +579,13 @@ __resolv_conf_load (struct __res_state *preinit) + resolv_conf_parser_init (&parser, preinit); + + struct resolv_conf *conf = NULL; +- if (res_vinit_1 (fp, &parser)) ++ bool ok = res_vinit_1 (fp, &parser); ++ if (ok && change != NULL) ++ /* Update the file change information if the configuration was ++ loaded successfully. */ ++ ok = file_change_detection_for_fp (change, fp); ++ ++ if (ok) + { + parser.template.nameserver_list + = nameserver_list_begin (&parser.nameserver_list); +@@ -615,7 +623,7 @@ __res_vinit (res_state statp, int preinit) + if (preinit && has_preinit_values (statp)) + /* For the preinit case, we cannot use the cached configuration + because some settings could be different. */ +- conf = __resolv_conf_load (statp); ++ conf = __resolv_conf_load (statp, NULL); + else + conf = __resolv_conf_get_current (); + if (conf == NULL) +diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c +index d954ba9a5a..bdd2ebb909 100644 +--- a/resolv/resolv_conf.c ++++ b/resolv/resolv_conf.c +@@ -136,7 +136,7 @@ __resolv_conf_get_current (void) + { + /* Parse configuration while holding the lock. This avoids + duplicate work. */ +- conf = __resolv_conf_load (NULL); ++ conf = __resolv_conf_load (NULL, NULL); + if (conf != NULL) + { + if (global_copy->conf_current != NULL) +diff --git a/resolv/resolv_conf.h b/resolv/resolv_conf.h +index 01cbff9111..101e14bfe5 100644 +--- a/resolv/resolv_conf.h ++++ b/resolv/resolv_conf.h +@@ -63,12 +63,16 @@ struct resolv_conf + and the struct resolv_context facility. */ + + struct __res_state; ++struct file_change_detection; + + /* Read /etc/resolv.conf and return a configuration object, or NULL if + /etc/resolv.conf cannot be read due to memory allocation errors. +- If PREINIT is not NULL, some configuration values are taken from the +- struct __res_state object. */ +-struct resolv_conf *__resolv_conf_load (struct __res_state *preinit) ++ If PREINIT is not NULL, some configuration values are taken from ++ the struct __res_state object. If CHANGE is not null, file change ++ detection data is written to *CHANGE, based on the state of the ++ file after reading it. */ ++struct resolv_conf *__resolv_conf_load (struct __res_state *preinit, ++ struct file_change_detection *change) + attribute_hidden __attribute__ ((warn_unused_result)); + + /* Return a configuration object for the current /etc/resolv.conf diff --git a/glibc-rh1810142-5.patch b/glibc-rh1810142-5.patch new file mode 100755 index 0000000..be991b0 --- /dev/null +++ b/glibc-rh1810142-5.patch @@ -0,0 +1,52 @@ +From: Florian Weimer +Date: Tue, 21 Jan 2020 16:38:15 +0000 (+0100) +Subject: resolv: Fix ABA race in /etc/resolv.conf change detection [BZ #25420] +X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=fa00db0a6eb755837ae5d413515e0da582b304f3 + +resolv: Fix ABA race in /etc/resolv.conf change detection [BZ #25420] + +__resolv_conf_get_current should only record the initial file +change data if after verifying that file just read matches the +original measurement. Fixes commit aef16cc8a4c670036d45590877 +("resolv: Automatically reload a changed /etc/resolv.conf file +[BZ #984]"). + +Reviewed-by: Adhemerval Zanella +--- + +diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c +index bdd2ebb909..29a1f4fb94 100644 +--- a/resolv/resolv_conf.c ++++ b/resolv/resolv_conf.c +@@ -136,18 +136,25 @@ __resolv_conf_get_current (void) + { + /* Parse configuration while holding the lock. This avoids + duplicate work. */ +- conf = __resolv_conf_load (NULL, NULL); ++ struct file_change_detection after_load; ++ conf = __resolv_conf_load (NULL, &after_load); + if (conf != NULL) + { + if (global_copy->conf_current != NULL) + conf_decrement (global_copy->conf_current); + global_copy->conf_current = conf; /* Takes ownership. */ + +- /* Update file modification stamps. The configuration we +- read could be a newer version of the file, but this does +- not matter because this will lead to an extraneous reload +- later. */ +- global_copy->file_resolve_conf = initial; ++ /* Update file change detection data, but only if it matches ++ the initial measurement. This avoids an ABA race in case ++ /etc/resolv.conf is temporarily replaced while the file ++ is read (after the initial measurement), and restored to ++ the initial version later. */ ++ if (file_is_unchanged (&initial, &after_load)) ++ global_copy->file_resolve_conf = after_load; ++ else ++ /* If there is a discrepancy, trigger a reload during the ++ next use. */ ++ global_copy->file_resolve_conf.size = -1; + } + } + diff --git a/glibc-rh1810142-6.patch b/glibc-rh1810142-6.patch new file mode 100755 index 0000000..8d96880 --- /dev/null +++ b/glibc-rh1810142-6.patch @@ -0,0 +1,481 @@ +From: Florian Weimer +Date: Tue, 18 Feb 2020 12:44:48 +0000 (+0100) +Subject: Move implementation of into a C file +X-Git-Url: https://sourceware.org/git/?p=glibc.git;a=commitdiff_plain;h=631cf64bc1d8306e011ef39f60b8cb6de91bd271 + +Move implementation of into a C file + +file_change_detection_for_stat partially initialize +struct file_change_detection in some cases, when the size member +alone determines the outcome of all comparisons. This results +in maybe-uninitialized compiler warnings in case of sufficiently +aggressive inlining. + +Once the implementation is moved into a separate C file, this kind +of inlining is no longer possible, so the compiler warnings are gone. +--- + +diff --git a/include/file_change_detection.h b/include/file_change_detection.h +index aaed0a9b6d..767e578555 100644 +--- a/include/file_change_detection.h ++++ b/include/file_change_detection.h +@@ -16,9 +16,10 @@ + License along with the GNU C Library; if not, see + . */ + +-#include ++#ifndef _FILE_CHANGE_DETECTION_H ++#define _FILE_CHANGE_DETECTION_H ++ + #include +-#include + #include + #include + #include +@@ -38,103 +39,32 @@ struct file_change_detection + + /* Returns true if *LEFT and *RIGHT describe the same version of the + same file. */ +-static bool __attribute__ ((unused)) +-file_is_unchanged (const struct file_change_detection *left, +- const struct file_change_detection *right) +-{ +- if (left->size < 0 || right->size < 0) +- /* Negative sizes are used as markers and never match. */ +- return false; +- else if (left->size == 0 && right->size == 0) +- /* Both files are empty or do not exist, so they have the same +- content, no matter what the other fields indicate. */ +- return true; +- else +- return left->size == right->size +- && left->ino == right->ino +- && left->mtime.tv_sec == right->mtime.tv_sec +- && left->mtime.tv_nsec == right->mtime.tv_nsec +- && left->ctime.tv_sec == right->ctime.tv_sec +- && left->ctime.tv_nsec == right->ctime.tv_nsec; +-} ++bool __file_is_unchanged (const struct file_change_detection *left, ++ const struct file_change_detection *right); + + /* Extract file change information to *FILE from the stat buffer + *ST. */ +-static void __attribute__ ((unused)) +-file_change_detection_for_stat (struct file_change_detection *file, +- const struct stat64 *st) +-{ +- if (S_ISDIR (st->st_mode)) +- /* Treat as empty file. */ +- file->size = 0; +- else if (!S_ISREG (st->st_mode)) +- /* Non-regular files cannot be cached. */ +- file->size = -1; +- else +- { +- file->size = st->st_size; +- file->ino = st->st_ino; +- file->mtime = st->st_mtim; +- file->ctime = st->st_ctim; +- } +-} ++void __file_change_detection_for_stat (struct file_change_detection *file, ++ const struct stat64 *st); + + /* Writes file change information for PATH to *FILE. Returns true on + success. For benign errors, *FILE is cleared, and true is + returned. For errors indicating resource outages and the like, + false is returned. */ +-static bool __attribute__ ((unused)) +-file_change_detection_for_path (struct file_change_detection *file, +- const char *path) +-{ +- struct stat64 st; +- if (stat64 (path, &st) != 0) +- switch (errno) +- { +- case EACCES: +- case EISDIR: +- case ELOOP: +- case ENOENT: +- case ENOTDIR: +- case EPERM: +- /* Ignore errors due to file system contents. Instead, treat +- the file as empty. */ +- file->size = 0; +- return true; +- default: +- /* Other errors are fatal. */ +- return false; +- } +- else /* stat64 was successfull. */ +- { +- file_change_detection_for_stat (file, &st); +- return true; +- } +-} ++bool __file_change_detection_for_path (struct file_change_detection *file, ++ const char *path); + + /* Writes file change information for the stream FP to *FILE. Returns + ture on success, false on failure. If FP is NULL, treat the file + as non-existing. */ +-static bool __attribute__ ((unused)) +-file_change_detection_for_fp (struct file_change_detection *file, +- FILE *fp) +-{ +- if (fp == NULL) +- { +- /* The file does not exist. */ +- file->size = 0; +- return true; +- } +- else +- { +- struct stat64 st; +- if (fstat64 (__fileno (fp), &st) != 0) +- /* If we already have a file descriptor, all errors are fatal. */ +- return false; +- else +- { +- file_change_detection_for_stat (file, &st); +- return true; +- } +- } +-} ++bool __file_change_detection_for_fp (struct file_change_detection *file, ++ FILE *fp); ++ ++#ifndef _ISOMAC ++libc_hidden_proto (__file_is_unchanged) ++libc_hidden_proto (__file_change_detection_for_stat) ++libc_hidden_proto (__file_change_detection_for_path) ++libc_hidden_proto (__file_change_detection_for_fp) ++#endif ++ ++#endif /* _FILE_CHANGE_DETECTION_H */ +diff --git a/io/Makefile b/io/Makefile +index 04c4647dc0..cf380f3516 100644 +--- a/io/Makefile ++++ b/io/Makefile +@@ -55,7 +55,7 @@ routines := \ + posix_fadvise posix_fadvise64 \ + posix_fallocate posix_fallocate64 \ + sendfile sendfile64 copy_file_range \ +- utimensat futimens ++ utimensat futimens file_change_detection + + # These routines will be omitted from the libc shared object. + # Instead the static object files will be included in a special archive +diff --git a/io/Versions b/io/Versions +index f7e5dbe49e..ee468055ff 100644 +--- a/io/Versions ++++ b/io/Versions +@@ -137,5 +137,9 @@ libc { + __fcntl_nocancel; + __open64_nocancel; + __write_nocancel; ++ __file_is_unchanged; ++ __file_change_detection_for_stat; ++ __file_change_detection_for_path; ++ __file_change_detection_for_fp; + } + } +diff --git a/io/file_change_detection.c b/io/file_change_detection.c +new file mode 100644 +index 0000000000..c6d700ed05 +--- /dev/null ++++ b/io/file_change_detection.c +@@ -0,0 +1,118 @@ ++/* Detecting file changes using modification times. ++ Copyright (C) 2017-2020 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 ++ . */ ++ ++#include ++ ++#include ++#include ++ ++bool ++__file_is_unchanged (const struct file_change_detection *left, ++ const struct file_change_detection *right) ++{ ++ if (left->size < 0 || right->size < 0) ++ /* Negative sizes are used as markers and never match. */ ++ return false; ++ else if (left->size == 0 && right->size == 0) ++ /* Both files are empty or do not exist, so they have the same ++ content, no matter what the other fields indicate. */ ++ return true; ++ else ++ return left->size == right->size ++ && left->ino == right->ino ++ && left->mtime.tv_sec == right->mtime.tv_sec ++ && left->mtime.tv_nsec == right->mtime.tv_nsec ++ && left->ctime.tv_sec == right->ctime.tv_sec ++ && left->ctime.tv_nsec == right->ctime.tv_nsec; ++} ++libc_hidden_def (__file_is_unchanged) ++ ++void ++__file_change_detection_for_stat (struct file_change_detection *file, ++ const struct stat64 *st) ++{ ++ if (S_ISDIR (st->st_mode)) ++ /* Treat as empty file. */ ++ file->size = 0; ++ else if (!S_ISREG (st->st_mode)) ++ /* Non-regular files cannot be cached. */ ++ file->size = -1; ++ else ++ { ++ file->size = st->st_size; ++ file->ino = st->st_ino; ++ file->mtime = st->st_mtim; ++ file->ctime = st->st_ctim; ++ } ++} ++libc_hidden_def (__file_change_detection_for_stat) ++ ++bool ++__file_change_detection_for_path (struct file_change_detection *file, ++ const char *path) ++{ ++ struct stat64 st; ++ if (stat64 (path, &st) != 0) ++ switch (errno) ++ { ++ case EACCES: ++ case EISDIR: ++ case ELOOP: ++ case ENOENT: ++ case ENOTDIR: ++ case EPERM: ++ /* Ignore errors due to file system contents. Instead, treat ++ the file as empty. */ ++ file->size = 0; ++ return true; ++ default: ++ /* Other errors are fatal. */ ++ return false; ++ } ++ else /* stat64 was successfull. */ ++ { ++ __file_change_detection_for_stat (file, &st); ++ return true; ++ } ++} ++libc_hidden_def (__file_change_detection_for_path) ++ ++bool ++__file_change_detection_for_fp (struct file_change_detection *file, ++ FILE *fp) ++{ ++ if (fp == NULL) ++ { ++ /* The file does not exist. */ ++ file->size = 0; ++ return true; ++ } ++ else ++ { ++ struct stat64 st; ++ if (fstat64 (__fileno (fp), &st) != 0) ++ /* If we already have a file descriptor, all errors are fatal. */ ++ return false; ++ else ++ { ++ __file_change_detection_for_stat (file, &st); ++ return true; ++ } ++ } ++} ++libc_hidden_def (__file_change_detection_for_fp) +diff --git a/io/tst-file_change_detection.c b/io/tst-file_change_detection.c +index 035dd39c4d..6e00e787b1 100644 +--- a/io/tst-file_change_detection.c ++++ b/io/tst-file_change_detection.c +@@ -16,10 +16,6 @@ + License along with the GNU C Library; if not, see + . */ + +-/* The header uses the internal __fileno symbol, which is not +- available outside of libc (even to internal tests). */ +-#define __fileno(fp) fileno (fp) +- + #include + + #include +@@ -40,7 +36,7 @@ all_same (struct file_change_detection *array, size_t length) + { + if (test_verbose > 0) + printf ("info: comparing %zu and %zu\n", i, j); +- TEST_VERIFY (file_is_unchanged (array + i, array + j)); ++ TEST_VERIFY (__file_is_unchanged (array + i, array + j)); + } + } + +@@ -54,7 +50,7 @@ all_different (struct file_change_detection *array, size_t length) + continue; + if (test_verbose > 0) + printf ("info: comparing %zu and %zu\n", i, j); +- TEST_VERIFY (!file_is_unchanged (array + i, array + j)); ++ TEST_VERIFY (!__file_is_unchanged (array + i, array + j)); + } + } + +@@ -105,24 +101,24 @@ do_test (void) + struct file_change_detection fcd[10]; + int i = 0; + /* Two empty files always have the same contents. */ +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_empty1)); +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_empty2)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_empty1)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_empty2)); + /* So does a missing file (which is treated as empty). */ +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], +- path_does_not_exist)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], ++ path_does_not_exist)); + /* And a symbolic link loop. */ +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_loop)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_loop)); + /* And a dangling symbolic link. */ +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_dangling)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_dangling)); + /* And a directory. */ +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], tempdir)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], tempdir)); + /* And a symbolic link to an empty file. */ +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_to_empty1)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_to_empty1)); + /* Likewise for access the file via a FILE *. */ +- TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], fp_empty1)); +- TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], fp_empty2)); ++ TEST_VERIFY (__file_change_detection_for_fp (&fcd[i++], fp_empty1)); ++ TEST_VERIFY (__file_change_detection_for_fp (&fcd[i++], fp_empty2)); + /* And a NULL FILE * (missing file). */ +- TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], NULL)); ++ TEST_VERIFY (__file_change_detection_for_fp (&fcd[i++], NULL)); + TEST_COMPARE (i, array_length (fcd)); + + all_same (fcd, array_length (fcd)); +@@ -132,9 +128,9 @@ do_test (void) + { + struct file_change_detection fcd[3]; + int i = 0; +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_file1)); +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_to_file1)); +- TEST_VERIFY (file_change_detection_for_fp (&fcd[i++], fp_file1)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_file1)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_to_file1)); ++ TEST_VERIFY (__file_change_detection_for_fp (&fcd[i++], fp_file1)); + TEST_COMPARE (i, array_length (fcd)); + all_same (fcd, array_length (fcd)); + } +@@ -144,20 +140,20 @@ do_test (void) + struct file_change_detection fcd[5]; + int i = 0; + /* The other files are not empty. */ +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_empty1)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_empty1)); + /* These two files have the same contents, but have different file + identity. */ +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_file1)); +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_file2)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_file1)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_file2)); + /* FIFOs are always different, even with themselves. */ +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_fifo)); +- TEST_VERIFY (file_change_detection_for_path (&fcd[i++], path_fifo)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_fifo)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[i++], path_fifo)); + TEST_COMPARE (i, array_length (fcd)); + all_different (fcd, array_length (fcd)); + + /* Replacing the file with its symbolic link does not make a + difference. */ +- TEST_VERIFY (file_change_detection_for_path (&fcd[1], path_to_file1)); ++ TEST_VERIFY (__file_change_detection_for_path (&fcd[1], path_to_file1)); + all_different (fcd, array_length (fcd)); + } + +@@ -166,16 +162,17 @@ do_test (void) + for (int use_stdio = 0; use_stdio < 2; ++use_stdio) + { + struct file_change_detection initial; +- TEST_VERIFY (file_change_detection_for_path (&initial, path_file1)); ++ TEST_VERIFY (__file_change_detection_for_path (&initial, path_file1)); + while (true) + { + support_write_file_string (path_file1, "line\n"); + struct file_change_detection current; + if (use_stdio) +- TEST_VERIFY (file_change_detection_for_fp (¤t, fp_file1)); ++ TEST_VERIFY (__file_change_detection_for_fp (¤t, fp_file1)); + else +- TEST_VERIFY (file_change_detection_for_path (¤t, path_file1)); +- if (!file_is_unchanged (&initial, ¤t)) ++ TEST_VERIFY (__file_change_detection_for_path ++ (¤t, path_file1)); ++ if (!__file_is_unchanged (&initial, ¤t)) + break; + /* Wait for a bit to reduce system load. */ + usleep (100 * 1000); +diff --git a/resolv/res_init.c b/resolv/res_init.c +index 98d84f264d..ee5dfdd391 100644 +--- a/resolv/res_init.c ++++ b/resolv/res_init.c +@@ -583,7 +583,7 @@ __resolv_conf_load (struct __res_state *preinit, + if (ok && change != NULL) + /* Update the file change information if the configuration was + loaded successfully. */ +- ok = file_change_detection_for_fp (change, fp); ++ ok = __file_change_detection_for_fp (change, fp); + + if (ok) + { +diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c +index 29a1f4fb94..286149ffad 100644 +--- a/resolv/resolv_conf.c ++++ b/resolv/resolv_conf.c +@@ -121,7 +121,7 @@ struct resolv_conf * + __resolv_conf_get_current (void) + { + struct file_change_detection initial; +- if (!file_change_detection_for_path (&initial, _PATH_RESCONF)) ++ if (!__file_change_detection_for_path (&initial, _PATH_RESCONF)) + return NULL; + + struct resolv_conf_global *global_copy = get_locked_global (); +@@ -129,7 +129,7 @@ __resolv_conf_get_current (void) + return NULL; + struct resolv_conf *conf; + if (global_copy->conf_current != NULL +- && file_is_unchanged (&initial, &global_copy->file_resolve_conf)) ++ && __file_is_unchanged (&initial, &global_copy->file_resolve_conf)) + /* We can reuse the cached configuration object. */ + conf = global_copy->conf_current; + else +@@ -149,7 +149,7 @@ __resolv_conf_get_current (void) + /etc/resolv.conf is temporarily replaced while the file + is read (after the initial measurement), and restored to + the initial version later. */ +- if (file_is_unchanged (&initial, &after_load)) ++ if (__file_is_unchanged (&initial, &after_load)) + global_copy->file_resolve_conf = after_load; + else + /* If there is a discrepancy, trigger a reload during the diff --git a/glibc-rh1810146.patch b/glibc-rh1810146.patch new file mode 100755 index 0000000..da0d6b3 --- /dev/null +++ b/glibc-rh1810146.patch @@ -0,0 +1,28 @@ +commit 8b222fa38700422b4da6731806835f0bbf40920d +Author: Florian Weimer +Date: Mon Jan 20 18:37:13 2020 +0100 + + getaddrinfo: Fix resource leak after strdup failure in gethosts [BZ #25425] + + Filip Ochnik spotted that one of the error jumps in gethosts fails to + call __resolv_context_put to release the resolver context. + + Fixes commit 352f4ff9a268b81ef5d4b2413f582565806e4790 ("resolv: + Introduce struct resolv_context [BZ #21668]") and commit + 964263bb8d650f1681665c55704fb01a8e725621 ("getaddrinfo: Release + resolver context on error in gethosts [BZ #21885]"). + + Reviewed-by: Siddhesh Poyarekar + +diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c +index 6a5805c9e63a257c..fae3dea81f19dba6 100644 +--- a/sysdeps/posix/getaddrinfo.c ++++ b/sysdeps/posix/getaddrinfo.c +@@ -292,6 +292,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, + canonbuf = __strdup (localcanon); \ + if (canonbuf == NULL) \ + { \ ++ __resolv_context_put (res_ctx); \ + result = -EAI_SYSTEM; \ + goto free_and_return; \ + } \ diff --git a/glibc-rh1810223-1.patch b/glibc-rh1810223-1.patch new file mode 100755 index 0000000..6771e16 --- /dev/null +++ b/glibc-rh1810223-1.patch @@ -0,0 +1,170 @@ +commit 0499a353a6e196f468e7ec554cb13c82011f0e36 +Author: Florian Weimer +Date: Mon Mar 2 14:24:27 2020 +0100 + + elf: Add elf/check-wx-segment, a test for the presence of WX segments + + Writable, executable segments defeat security hardening. The + existing check for DT_TEXTREL does not catch this. + + hppa and SPARC currently keep the PLT in an RWX load segment. + +# Conflicts: +# sysdeps/sparc/Makefile + +diff --git a/elf/Makefile b/elf/Makefile +index f1a16fe8ca594c57..a52d9b1f6a4364a7 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -378,6 +378,7 @@ tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \ + $(objpfx)tst-rtld-preload.out + endif + tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \ ++ $(objpfx)check-wx-segment.out \ + $(objpfx)check-localplt.out $(objpfx)check-initfini.out + endif + +@@ -1148,6 +1149,12 @@ $(objpfx)check-execstack.out: $(..)scripts/check-execstack.awk \ + $(evaluate-test) + generated += check-execstack.out + ++$(objpfx)check-wx-segment.out: $(..)scripts/check-wx-segment.py \ ++ $(all-built-dso:=.phdr) ++ $(PYTHON) $^ --xfail="$(check-wx-segment-xfail)" > $@; \ ++ $(evaluate-test) ++generated += check-wx-segment.out ++ + $(objpfx)tst-dlmodcount: $(libdl) + $(objpfx)tst-dlmodcount.out: $(test-modules) + +diff --git a/scripts/check-wx-segment.py b/scripts/check-wx-segment.py +new file mode 100644 +index 0000000000000000..e1fa79387ce22c4b +--- /dev/null ++++ b/scripts/check-wx-segment.py +@@ -0,0 +1,85 @@ ++#!/usr/bin/python3 ++# Check ELF program headers for WX segments. ++# Copyright (C) 2020 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 ++# . ++ ++"""Check that the program headers do not contain write-exec segments.""" ++ ++import argparse ++import os.path ++import re ++import sys ++ ++# Regular expression to extract the RWE flags field. The ++# address/offset columns have varying width. ++RE_LOAD = re.compile( ++ r'^ LOAD +(?:0x[0-9a-fA-F]+ +){5}([R ][W ][ E]) +0x[0-9a-fA-F]+\n\Z') ++ ++def process_file(path, inp, xfail): ++ """Analyze one input file.""" ++ ++ errors = 0 ++ for line in inp: ++ error = None ++ if line.startswith(' LOAD '): ++ match = RE_LOAD.match(line) ++ if match is None: ++ error = 'Invalid LOAD line' ++ else: ++ flags, = match.groups() ++ if 'W' in flags and 'E' in flags: ++ if xfail: ++ print('{}: warning: WX segment (as expected)'.format( ++ path)) ++ else: ++ error = 'WX segment' ++ ++ if error is not None: ++ print('{}: error: {}: {!r}'.format(path, error, line.strip())) ++ errors += 1 ++ ++ if xfail and errors == 0: ++ print('{}: warning: missing expected WX segment'.format(path)) ++ return errors ++ ++ ++def main(): ++ """The main entry point.""" ++ parser = argparse.ArgumentParser(description=__doc__) ++ parser.add_argument('--xfail', ++ help='Mark input files as XFAILed ("*" for all)', ++ type=str, default='') ++ parser.add_argument('phdrs', ++ help='Files containing readelf -Wl output', ++ nargs='*') ++ opts = parser.parse_args(sys.argv) ++ ++ xfails = set(opts.xfail.split(' ')) ++ xfails_all = opts.xfail.strip() == '*' ++ ++ errors = 0 ++ for path in opts.phdrs: ++ xfail = ((os.path.basename(path) + '.phdrs') in xfails ++ or xfails_all) ++ with open(path) as inp: ++ errors += process_file(path, inp, xfail) ++ if errors > 0: ++ sys.exit(1) ++ ++ ++if __name__ == '__main__': ++ main() +diff --git a/sysdeps/sparc/Makefile b/sysdeps/sparc/Makefile +index 3f0c0964002560f0..a1004e819c9b0c38 100644 +--- a/sysdeps/sparc/Makefile ++++ b/sysdeps/sparc/Makefile +@@ -16,5 +16,14 @@ CPPFLAGS-crti.S += -fPIC + CPPFLAGS-crtn.S += -fPIC + endif + ++ifeq ($(subdir),elf) ++ ++# Lazy binding on SPARC rewrites the PLT sequence. See the Solaris ++# Linker and Libraries Guide, section SPARC: Procedure Linkage Table. ++# ++test-xfail-check-wx-segment = * ++ ++endif # $(subdir) == elf ++ + # The assembler on SPARC needs the -fPIC flag even when it's assembler code. + ASFLAGS-.os += -fPIC +diff --git a/sysdeps/unix/sysv/linux/hppa/Makefile b/sysdeps/unix/sysv/linux/hppa/Makefile +index e1637f54f508c007..c89ec8318208205d 100644 +--- a/sysdeps/unix/sysv/linux/hppa/Makefile ++++ b/sysdeps/unix/sysv/linux/hppa/Makefile +@@ -3,9 +3,14 @@ ifeq ($(subdir),stdlib) + gen-as-const-headers += ucontext_i.sym + endif + ++ifeq ($(subdir),elf) + # Supporting non-executable stacks on HPPA requires changes to both + # the Linux kernel and glibc. The kernel currently needs an executable + # stack for syscall restarts and signal returns. +-ifeq ($(subdir),elf) + test-xfail-check-execstack = yes +-endif ++ ++# On hppa, the PLT is executable because it contains an executable ++# trampoline used during lazy binding. ++test-xfail-check-wx-segment = * ++ ++endif # $(subdir) == elf diff --git a/glibc-rh1810223-2.patch b/glibc-rh1810223-2.patch new file mode 100755 index 0000000..4bee60f --- /dev/null +++ b/glibc-rh1810223-2.patch @@ -0,0 +1,49 @@ +commit 279c68ce1336d84d82ce491a4b77086e574ba380 +Author: DJ Delorie +Date: Mon Feb 3 14:57:23 2020 -0500 + + Run nptl/tst-pthread-getattr in a container + + See https://bugzilla.redhat.com/show_bug.cgi?id=1653942 + + This test depends on the kernel's assignment of memory regions, but + running under ld.so explicitly changes those assignments, sometimes + sufficiently to cause the test to fail (esp with address space + randomization). + + The easiest way to "fix" the test, is to run it the way the user would + - without ld.so. Running it in a container does that. + + Reviewed-by: Carlos O'Donell + +diff --git a/nptl/Makefile b/nptl/Makefile +index b1003cf56b31ddfa..071c53866d14d2fe 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -293,7 +293,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \ + tst-exec1 tst-exec2 tst-exec3 tst-exec4 tst-exec5 \ + tst-exit1 tst-exit2 tst-exit3 \ + tst-stdio1 tst-stdio2 \ +- tst-stack1 tst-stack2 tst-stack3 tst-stack4 tst-pthread-getattr \ ++ tst-stack1 tst-stack2 tst-stack3 tst-stack4 \ + tst-pthread-attr-affinity tst-pthread-mutexattr \ + tst-unload \ + tst-dlsym1 \ +@@ -322,6 +322,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 tst-default-attr \ + tst-rwlock-pwn \ + tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall + ++tests-container = tst-pthread-getattr ++ + tests-internal := tst-rwlock19 tst-rwlock20 \ + tst-sem11 tst-sem12 tst-sem13 \ + tst-barrier5 tst-signal7 tst-mutex8 tst-mutex8-static \ +@@ -633,7 +635,7 @@ ifeq ($(build-shared),yes) + $(addprefix $(objpfx), \ + $(filter-out $(tests-static) $(xtests-static) $(tests-reverse) \ + $(tests-nolibpthread), \ +- $(tests) $(tests-internal) $(xtests) $(test-srcs))): \ ++ $(tests) $(tests-internal) $(xtests) $(test-srcs) $(tests-container))): \ + $(objpfx)libpthread.so + $(objpfx)tst-unload: $(libdl) + # $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so, diff --git a/glibc-rh1810224-1.patch b/glibc-rh1810224-1.patch new file mode 100755 index 0000000..a4b671a --- /dev/null +++ b/glibc-rh1810224-1.patch @@ -0,0 +1,28 @@ +commit a331150af65477fc3fa72ab341eed5e0b2daf7f3 +Author: Joseph Myers +Date: Thu Nov 28 20:32:09 2019 +0000 + + Update syscall-names.list for Linux 5.4. + + This patch updates syscall-names.list for Linux 5.4. There are no new + syscalls, so this is just a matter of updating the version number + listed in the file. + + Tested with build-many-glibcs.py. + +Reworked for RHEL 8.3.0. + +diff -Nrup a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +--- a/sysdeps/unix/sysv/linux/syscall-names.list 2020-04-05 20:20:41.471686371 -0400 ++++ b/sysdeps/unix/sysv/linux/syscall-names.list 2020-04-05 20:21:56.871912297 -0400 +@@ -22,8 +22,8 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 5.3. +-kernel 5.3 ++# The list of system calls is current as of Linux 5.4. ++kernel 5.4 + + FAST_atomic_update + FAST_cmpxchg diff --git a/glibc-rh1810224-2.patch b/glibc-rh1810224-2.patch new file mode 100755 index 0000000..df51b1d --- /dev/null +++ b/glibc-rh1810224-2.patch @@ -0,0 +1,29 @@ +commit 5828bc4523230685ac29a4a882967913255f5666 +Author: Joseph Myers +Date: Fri Feb 7 13:54:58 2020 +0000 + + Update syscall lists for Linux 5.5. + + Linux 5.5 has no new syscalls to add to syscall-names.list, but it + does newly enable the clone3 syscall for AArch64. This patch updates + the kernel version listed in syscall-names.list and regenerates the + AArch64 arch-syscall.h. + + Tested with build-many-glibcs.py. + +Modified to only update syscall-names.list for RHEL 8.3.0. + +diff -Nrup a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +--- a/sysdeps/unix/sysv/linux/syscall-names.list 2020-04-06 12:10:47.683272882 -0400 ++++ b/sysdeps/unix/sysv/linux/syscall-names.list 2020-04-06 12:12:41.769598687 -0400 +@@ -22,8 +22,8 @@ + # names are only used if the installed kernel headers also provide + # them. + +-# The list of system calls is current as of Linux 5.4. +-kernel 5.4 ++# The list of system calls is current as of Linux 5.5. ++kernel 5.5 + + FAST_atomic_update + FAST_cmpxchg diff --git a/glibc-rh1810224-3.patch b/glibc-rh1810224-3.patch new file mode 100755 index 0000000..2293e42 --- /dev/null +++ b/glibc-rh1810224-3.patch @@ -0,0 +1,26 @@ +commit 6cf6a91d05d626698f158078961b3bffcb39ff8c +Author: Joseph Myers +Date: Wed Feb 12 13:37:16 2020 +0000 + + Rename RWF_WRITE_LIFE_NOT_SET to RWH_WRITE_LIFE_NOT_SET following Linux 5.5. + + Linux 5.5 renames RWF_WRITE_LIFE_NOT_SET to RWH_WRITE_LIFE_NOT_SET, + with the old name kept as an alias. This patch makes the + corresponding change in glibc. + + Tested for x86_64. + +diff --git a/sysdeps/unix/sysv/linux/bits/fcntl-linux.h b/sysdeps/unix/sysv/linux/bits/fcntl-linux.h +index 07a889d683..b06488a847 100644 +--- a/sysdeps/unix/sysv/linux/bits/fcntl-linux.h ++++ b/sysdeps/unix/sysv/linux/bits/fcntl-linux.h +@@ -290,7 +290,8 @@ struct f_owner_ex + + #ifdef __USE_GNU + /* Hint values for F_{GET,SET}_RW_HINT. */ +-# define RWF_WRITE_LIFE_NOT_SET 0 ++# define RWH_WRITE_LIFE_NOT_SET 0 ++# define RWF_WRITE_LIFE_NOT_SET RWH_WRITE_LIFE_NOT_SET + # define RWH_WRITE_LIFE_NONE 1 + # define RWH_WRITE_LIFE_SHORT 2 + # define RWH_WRITE_LIFE_MEDIUM 3 diff --git a/glibc-rh1810224-4.patch b/glibc-rh1810224-4.patch new file mode 100755 index 0000000..c1205a1 --- /dev/null +++ b/glibc-rh1810224-4.patch @@ -0,0 +1,54 @@ +commit e788beaf093bfafecd6b4456b984bd927c18987a +Author: Joseph Myers +Date: Fri Apr 3 18:07:55 2020 +0000 + + Update syscall lists for Linux 5.6. + + Linux 5.6 has new openat2 and pidfd_getfd syscalls. This patch adds + them to syscall-names.list and regenerates the arch-syscall.h files. + + Tested with build-many-glibcs.py. + +Modified to only update syscall-names.list for RHEL 8.3.0. +Also cleaned up typos in the comments. + +diff -Nrup a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +--- a/sysdeps/unix/sysv/linux/syscall-names.list 2020-04-06 12:27:10.519027866 -0400 ++++ b/sysdeps/unix/sysv/linux/syscall-names.list 2020-04-06 12:31:53.665812810 -0400 +@@ -16,14 +16,13 @@ + # License along with the GNU C Library; if not, see + # . + +-# This file contains the list of system call names names. It has to +-# remain in alphabetica order. Lines which start with # are treated +-# as comments. This file can list all potential system calls. The +-# names are only used if the installed kernel headers also provide +-# them. ++# This file contains the list of system call names. It has to remain in ++# alphabetical order. Lines which start with # are treated as comments. ++# This file can list all potential system calls. The names are only ++# used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.5. +-kernel 5.5 ++# The list of system calls is current as of Linux 5.6. ++kernel 5.6 + + FAST_atomic_update + FAST_cmpxchg +@@ -293,6 +292,7 @@ open + open_by_handle_at + open_tree + openat ++openat2 + osf_adjtime + osf_afs_syscall + osf_alt_plock +@@ -411,6 +411,7 @@ perf_event_open + perfctr + perfmonctl + personality ++pidfd_getfd + pidfd_open + pidfd_send_signal + pipe diff --git a/glibc-rh1811796-1.patch b/glibc-rh1811796-1.patch new file mode 100755 index 0000000..a7b711d --- /dev/null +++ b/glibc-rh1811796-1.patch @@ -0,0 +1,113 @@ +commit 9333498794cde1d5cca518badf79533a24114b6f +Author: Joseph Myers +Date: Wed Feb 12 23:31:56 2020 +0000 + + Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (bug 25487). + + Bug 25487 reports stack corruption in ldbl-96 sinl on a pseudo-zero + argument (an representation where all the significand bits, including + the explicit high bit, are zero, but the exponent is not zero, which + is not a valid representation for the long double type). + + Although this is not a valid long double representation, existing + practice in this area (see bug 4586, originally marked invalid but + subsequently fixed) is that we still seek to avoid invalid memory + accesses as a result, in case of programs that treat arbitrary binary + data as long double representations, although the invalid + representations of the ldbl-96 format do not need to be consistently + handled the same as any particular valid representation. + + This patch makes the range reduction detect pseudo-zero and unnormal + representations that would otherwise go to __kernel_rem_pio2, and + returns a NaN for them instead of continuing with the range reduction + process. (Pseudo-zero and unnormal representations whose unbiased + exponent is less than -1 have already been safely returned from the + function before this point without going through the rest of range + reduction.) Pseudo-zero representations would previously result in + the value passed to __kernel_rem_pio2 being all-zero, which is + definitely unsafe; unnormal representations would previously result in + a value passed whose high bit is zero, which might well be unsafe + since that is not a form of input expected by __kernel_rem_pio2. + + Tested for x86_64. + +Revised for RHEL 8.3.0. + +diff -Nrup a/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c b/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c +--- a/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/sysdeps/ieee754/ldbl-96/e_rem_pio2l.c 2020-04-03 13:05:02.609844427 -0400 +@@ -209,6 +209,18 @@ __ieee754_rem_pio2l (long double x, long + y[1] = y[0]; + return 0; + } ++ ++ if ((i0 & 0x80000000) == 0) ++ { ++ /* Pseudo-zero and unnormal representations are not valid ++ representations of long double. We need to avoid stack ++ corruption in __kernel_rem_pio2, which expects input in a ++ particular normal form, but those representations do not need ++ to be consistently handled like any particular floating-point ++ value. */ ++ y[1] = y[0] = __builtin_nanl (""); ++ return 0; ++ } + + /* Split the 64 bits of the mantissa into three 24-bit integers + stored in a double array. */ +diff -Nrup a/sysdeps/ieee754/ldbl-96/Makefile b/sysdeps/ieee754/ldbl-96/Makefile +--- a/sysdeps/ieee754/ldbl-96/Makefile 2018-08-01 01:10:47.000000000 -0400 ++++ b/sysdeps/ieee754/ldbl-96/Makefile 2020-04-03 13:03:20.233546734 -0400 +@@ -17,5 +17,6 @@ + # . + + ifeq ($(subdir),math) +-tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 ++tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 test-sinl-pseudo ++CFLAGS-test-sinl-pseudo.c += -fstack-protector-all + endif +diff -Nrup a/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c b/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c +--- a/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/sysdeps/ieee754/ldbl-96/test-sinl-pseudo.c 2020-04-03 13:05:37.857952212 -0400 +@@ -0,0 +1,41 @@ ++/* Test sinl for pseudo-zeros and unnormals for ldbl-96 (bug 25487). ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ for (int i = 0; i < 64; i++) ++ { ++ uint64_t sig = i == 63 ? 0 : 1ULL << i; ++ long double ld; ++ SET_LDOUBLE_WORDS (ld, 0x4141, ++ sig >> 32, sig & 0xffffffffULL); ++ /* The requirement is that no stack overflow occurs when the ++ pseudo-zero or unnormal goes through range reduction. */ ++ volatile long double ldr; ++ ldr = sinl (ld); ++ (void) ldr; ++ } ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1811796-2.patch b/glibc-rh1811796-2.patch new file mode 100755 index 0000000..eae8269 --- /dev/null +++ b/glibc-rh1811796-2.patch @@ -0,0 +1,21 @@ +commit c10acd40262486dac597001aecc20ad9d3bd0e4a +Author: Florian Weimer +Date: Thu Feb 13 17:01:15 2020 +0100 + + math/test-sinl-pseudo: Use stack protector only if available + + This fixes commit 9333498794cde1d5cca518bad ("Avoid ldbl-96 stack + corruption from range reduction of pseudo-zero (bug 25487)."). + +diff --git a/sysdeps/ieee754/ldbl-96/Makefile b/sysdeps/ieee754/ldbl-96/Makefile +index 318628aed6..6030adf7e7 100644 +--- a/sysdeps/ieee754/ldbl-96/Makefile ++++ b/sysdeps/ieee754/ldbl-96/Makefile +@@ -18,5 +18,7 @@ + + ifeq ($(subdir),math) + tests += test-canonical-ldbl-96 test-totalorderl-ldbl-96 test-sinl-pseudo ++ifeq ($(have-ssp),yes) + CFLAGS-test-sinl-pseudo.c += -fstack-protector-all + endif ++endif # $(subdir) == math diff --git a/glibc-rh1812756-1.patch b/glibc-rh1812756-1.patch new file mode 100755 index 0000000..7675c1c --- /dev/null +++ b/glibc-rh1812756-1.patch @@ -0,0 +1,517 @@ +commit eb447b7b4bd6177f876ba9420ad9e048c27bae91 +Author: David Kilroy +Date: Wed Feb 12 14:28:15 2020 -0300 + + elf: Allow dlopen of filter object to work [BZ #16272] + + There are two fixes that are needed to be able to dlopen filter + objects. First _dl_map_object_deps cannot assume that map will be at + the beginning of l_searchlist.r_list[], as filtees are inserted before + map. Secondly dl_open_worker needs to ensure that filtees get + relocated. + + In _dl_map_object_deps: + + * avoiding removing relocation dependencies of map by setting + l_reserved to 0 and otherwise processing the rest of the search + list. + + * ensure that map remains at the beginning of l_initfini - the list + of things that need initialisation (and destruction). Do this by + splitting the copy up. This may not be required, but matches the + initialization order without dlopen. + + Modify dl_open_worker to relocate the objects in new->l_inifini. + new->l_initfini is constructed in _dl_map_object_deps, and lists the + objects that need initialization and destruction. Originally the list + of objects in new->l_next are relocated. All of these objects should + also be included in new->l_initfini (both lists are populated with + dependencies in _dl_map_object_deps). We can't use new->l_prev to pick + up filtees, as during a recursive dlopen from an interposed malloc + call, l->prev can contain objects that are not ready for relocation. + + Add tests to verify that symbols resolve to the filtee implementation + when auxiliary and filter objects are used, both as a normal link and + when dlopen'd. + + Tested by running the testsuite on x86_64. + +# Conflicts: +# elf/Makefile + +diff --git a/elf/Makefile b/elf/Makefile +index a52d9b1f6a4364a7..b4b618ce62a9e6df 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -192,7 +192,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \ + tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \ + tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail \ +- tst-dlopenfail tst-dlopenfail-2 ++ tst-dlopenfail tst-dlopenfail-2 \ ++ tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -302,7 +303,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-sonamemove-runmod1 tst-sonamemove-runmod2 \ + tst-initlazyfailmod tst-finilazyfailmod \ + tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \ +- tst-dlopenfailmod3 ++ tst-dlopenfailmod3 \ ++ tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee + + ifeq (yes,$(have-mtls-dialect-gnu2)) + tests += tst-gnu2-tls1 +@@ -1626,3 +1628,15 @@ $(objpfx)tst-dlopen-nodelete-reloc-mod17.so: \ + $(objpfx)tst-dlopen-nodelete-reloc-mod15.so \ + $(objpfx)tst-dlopen-nodelete-reloc-mod16.so + LDFLAGS-tst-dlopen-nodelete-reloc-mod17.so = -Wl,--no-as-needed ++ ++LDFLAGS-tst-filterobj-flt.so = -Wl,--filter=$(objpfx)tst-filterobj-filtee.so ++$(objpfx)tst-filterobj: $(objpfx)tst-filterobj-flt.so ++$(objpfx)tst-filterobj-dlopen: $(libdl) ++$(objpfx)tst-filterobj.out: $(objpfx)tst-filterobj-filtee.so ++$(objpfx)tst-filterobj-dlopen.out: $(objpfx)tst-filterobj-filtee.so ++ ++LDFLAGS-tst-filterobj-aux.so = -Wl,--auxiliary=$(objpfx)tst-filterobj-filtee.so ++$(objpfx)tst-auxobj: $(objpfx)tst-filterobj-aux.so ++$(objpfx)tst-auxobj-dlopen: $(libdl) ++$(objpfx)tst-auxobj.out: $(objpfx)tst-filterobj-filtee.so ++$(objpfx)tst-auxobj-dlopen.out: $(objpfx)tst-filterobj-filtee.so +diff --git a/elf/dl-deps.c b/elf/dl-deps.c +index 9d9b1ba7f244348a..50f053a1586efdc3 100644 +--- a/elf/dl-deps.c ++++ b/elf/dl-deps.c +@@ -485,14 +485,18 @@ _dl_map_object_deps (struct link_map *map, + + map->l_searchlist.r_list = &l_initfini[nlist + 1]; + map->l_searchlist.r_nlist = nlist; ++ unsigned int map_index = UINT_MAX; + + for (nlist = 0, runp = known; runp; runp = runp->next) + { + if (__builtin_expect (trace_mode, 0) && runp->map->l_faked) + /* This can happen when we trace the loading. */ + --map->l_searchlist.r_nlist; +- else ++ else { ++ if (runp->map == map) ++ map_index = nlist; + map->l_searchlist.r_list[nlist++] = runp->map; ++ } + + /* Now clear all the mark bits we set in the objects on the search list + to avoid duplicates, so the next call starts fresh. */ +@@ -550,13 +554,14 @@ Filters not supported with LD_TRACE_PRELINKING")); + } + + /* Maybe we can remove some relocation dependencies now. */ +- assert (map->l_searchlist.r_list[0] == map); + struct link_map_reldeps *l_reldeps = NULL; + if (map->l_reldeps != NULL) + { +- for (i = 1; i < nlist; ++i) ++ for (i = 0; i < nlist; ++i) + map->l_searchlist.r_list[i]->l_reserved = 1; + ++ /* Avoid removing relocation dependencies of the main binary. */ ++ map->l_reserved = 0; + struct link_map **list = &map->l_reldeps->list[0]; + for (i = 0; i < map->l_reldeps->act; ++i) + if (list[i]->l_reserved) +@@ -581,16 +586,30 @@ Filters not supported with LD_TRACE_PRELINKING")); + } + } + +- for (i = 1; i < nlist; ++i) ++ for (i = 0; i < nlist; ++i) + map->l_searchlist.r_list[i]->l_reserved = 0; + } + +- /* Sort the initializer list to take dependencies into account. The binary +- itself will always be initialize last. */ +- memcpy (l_initfini, map->l_searchlist.r_list, +- nlist * sizeof (struct link_map *)); +- /* We can skip looking for the binary itself which is at the front of +- the search list. */ ++ /* Sort the initializer list to take dependencies into account. Always ++ initialize the binary itself last. */ ++ assert (map_index < nlist); ++ if (map_index > 0) ++ { ++ /* Copy the binary into position 0. */ ++ l_initfini[0] = map->l_searchlist.r_list[map_index]; ++ ++ /* Copy the filtees. */ ++ for (i = 0; i < map_index; ++i) ++ l_initfini[i+1] = map->l_searchlist.r_list[i]; ++ ++ /* Copy the remainder. */ ++ for (i = map_index + 1; i < nlist; ++i) ++ l_initfini[i] = map->l_searchlist.r_list[i]; ++ } ++ else ++ memcpy (l_initfini, map->l_searchlist.r_list, ++ nlist * sizeof (struct link_map *)); ++ + _dl_sort_maps (&l_initfini[1], nlist - 1, NULL, false); + + /* Terminate the list of dependencies. */ +diff --git a/elf/dl-open.c b/elf/dl-open.c +index d834b89754d2b073..d31356f7e17dfb14 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -618,22 +618,25 @@ dl_open_worker (void *a) + allows IFUNC relocations to work and it also means copy + relocation of dependencies are if necessary overwritten. */ + unsigned int nmaps = 0; +- struct link_map *l = new; ++ unsigned int j = 0; ++ struct link_map *l = new->l_initfini[0]; + do + { + if (! l->l_real->l_relocated) + ++nmaps; +- l = l->l_next; ++ l = new->l_initfini[++j]; + } + while (l != NULL); ++ /* Stack allocation is limited by the number of loaded objects. */ + struct link_map *maps[nmaps]; + nmaps = 0; +- l = new; ++ j = 0; ++ l = new->l_initfini[0]; + do + { + if (! l->l_real->l_relocated) + maps[nmaps++] = l; +- l = l->l_next; ++ l = new->l_initfini[++j]; + } + while (l != NULL); + _dl_sort_maps (maps, nmaps, NULL, false); +diff --git a/elf/tst-auxobj-dlopen.c b/elf/tst-auxobj-dlopen.c +new file mode 100644 +index 0000000000000000..cb54aba19470a1fe +--- /dev/null ++++ b/elf/tst-auxobj-dlopen.c +@@ -0,0 +1,47 @@ ++/* Test for BZ#16272, dlopen'ing an auxiliary filter object. ++ Ensure that symbols from the resolve correctly. ++ ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++static int do_test (void) ++{ ++ void *lib = xdlopen ("tst-filterobj-aux.so", RTLD_LAZY); ++ char *(*fn)(void) = xdlsym (lib, "get_text"); ++ const char* text = fn (); ++ ++ printf ("%s\n", text); ++ ++ /* Verify the text matches what we expect from the filtee */ ++ TEST_COMPARE_STRING (text, "Hello from filtee (PASS)"); ++ ++ fn = xdlsym (lib, "get_text2"); ++ text = fn (); ++ ++ printf ("%s\n", text); ++ ++ /* Verify the text matches what we expect from the auxiliary object */ ++ TEST_COMPARE_STRING (text, "Hello from auxiliary filter object (PASS)"); ++ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-auxobj.c b/elf/tst-auxobj.c +new file mode 100644 +index 0000000000000000..bdc7713b04b4a79b +--- /dev/null ++++ b/elf/tst-auxobj.c +@@ -0,0 +1,42 @@ ++/* Test that symbols from auxiliary filter objects are resolved to the ++ filtee. ++ ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include "tst-filterobj-filtee.h" ++ ++static int do_test (void) ++{ ++ const char* text = get_text (); ++ printf ("%s\n", text); ++ ++ /* Verify the text matches what we expect from the filtee */ ++ TEST_COMPARE_STRING (text, "Hello from filtee (PASS)"); ++ ++ text = get_text2 (); ++ printf ("%s\n", text); ++ ++ /* Verify the text matches what we expect from the auxiliary object */ ++ TEST_COMPARE_STRING (text, "Hello from auxiliary filter object (PASS)"); ++ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-filterobj-aux.c b/elf/tst-filterobj-aux.c +new file mode 100644 +index 0000000000000000..0b732f2fb3a69a7f +--- /dev/null ++++ b/elf/tst-filterobj-aux.c +@@ -0,0 +1,33 @@ ++/* Auxiliary filter object. ++ Contains symbols to be resolved in filtee, and one which doesn't. ++ ++ Copyright (C) 2020 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 ++ . */ ++ ++#include "tst-filterobj-filtee.h" ++ ++/* We never want to see the output of the auxiliary object. */ ++const char *get_text (void) ++{ ++ return "Hello from auxiliary filter object (FAIL)"; ++} ++ ++/* The filtee doesn't implement this symbol, so this should resolve. */ ++const char *get_text2 (void) ++{ ++ return "Hello from auxiliary filter object (PASS)"; ++} +diff --git a/elf/tst-filterobj-dlopen.c b/elf/tst-filterobj-dlopen.c +new file mode 100644 +index 0000000000000000..c5b5072979802b98 +--- /dev/null ++++ b/elf/tst-filterobj-dlopen.c +@@ -0,0 +1,39 @@ ++/* Test for BZ#16272, dlopen'ing a filter object. ++ Ensure that symbols from the filter object resolve to the filtee. ++ ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++static int do_test (void) ++{ ++ void *lib = xdlopen ("tst-filterobj-flt.so", RTLD_LAZY); ++ char *(*fn)(void) = xdlsym (lib, "get_text"); ++ const char* text = fn (); ++ ++ printf ("%s\n", text); ++ ++ /* Verify the text matches what we expect from the filtee */ ++ TEST_COMPARE_STRING (text, "Hello from filtee (PASS)"); ++ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-filterobj-filtee.c b/elf/tst-filterobj-filtee.c +new file mode 100644 +index 0000000000000000..8fa557cbd251f53c +--- /dev/null ++++ b/elf/tst-filterobj-filtee.c +@@ -0,0 +1,27 @@ ++/* Filtee for BZ#16272 test. ++ Contains desired symbol implementations. ++ ++ Copyright (C) 2020 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 ++ . */ ++ ++#include "tst-filterobj-filtee.h" ++ ++/* This is the real implementation that wants to be called */ ++const char *get_text (void) ++{ ++ return "Hello from filtee (PASS)"; ++} +diff --git a/elf/tst-filterobj-filtee.h b/elf/tst-filterobj-filtee.h +new file mode 100644 +index 0000000000000000..46aee28178b88a77 +--- /dev/null ++++ b/elf/tst-filterobj-filtee.h +@@ -0,0 +1,24 @@ ++/* Filtee header for BZ#16272 test. ++ Contains prototypes for symbols implemented in the filtee. ++ ++ Copyright (C) 2020 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 ++ . */ ++ ++const char *get_text (void); ++ ++/* For testing auxiliary filter object. */ ++const char *get_text2 (void); +diff --git a/elf/tst-filterobj-flt.c b/elf/tst-filterobj-flt.c +new file mode 100644 +index 0000000000000000..5062654be6f14a80 +--- /dev/null ++++ b/elf/tst-filterobj-flt.c +@@ -0,0 +1,27 @@ ++/* Filter object for BZ#16272 test. ++ Contains symbols to be resolved in filtee. ++ ++ Copyright (C) 2020 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 ++ . */ ++ ++#include "tst-filterobj-filtee.h" ++ ++/* We never want to see the output of the filter object */ ++const char *get_text (void) ++{ ++ return "Hello from filter object (FAIL)"; ++} +diff --git a/elf/tst-filterobj.c b/elf/tst-filterobj.c +new file mode 100644 +index 0000000000000000..96bfae019ea670bc +--- /dev/null ++++ b/elf/tst-filterobj.c +@@ -0,0 +1,36 @@ ++/* Test that symbols from filter objects are resolved to the filtee. ++ ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include "tst-filterobj-filtee.h" ++ ++static int do_test (void) ++{ ++ const char* text = get_text (); ++ ++ printf ("%s\n", text); ++ ++ /* Verify the text matches what we expect from the filtee */ ++ TEST_COMPARE_STRING (text, "Hello from filtee (PASS)"); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1812756-2.patch b/glibc-rh1812756-2.patch new file mode 100755 index 0000000..e2df4e4 --- /dev/null +++ b/glibc-rh1812756-2.patch @@ -0,0 +1,37 @@ +commit 71bcfa62451dfaa015326d3524f2a0e2d09d80ed +Author: David Kilroy +Date: Wed Feb 12 14:30:31 2020 -0300 + + elf: avoid redundant sort in dlopen + + l_initfini is already sorted by dependency in _dl_map_object_deps(), + so avoid sorting again in dl_open_worker(). + + Tested by running the testsuite on x86_64. + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index d31356f7e17dfb14..980a28c836ca9a7a 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -614,9 +614,10 @@ dl_open_worker (void *a) + if (GLRO(dl_lazy)) + reloc_mode |= mode & RTLD_LAZY; + +- /* Sort the objects by dependency for the relocation process. This +- allows IFUNC relocations to work and it also means copy +- relocation of dependencies are if necessary overwritten. */ ++ /* Objects must be sorted by dependency for the relocation process. ++ This allows IFUNC relocations to work and it also means copy ++ relocation of dependencies are if necessary overwritten. ++ __dl_map_object_deps has already sorted l_initfini for us. */ + unsigned int nmaps = 0; + unsigned int j = 0; + struct link_map *l = new->l_initfini[0]; +@@ -639,7 +640,6 @@ dl_open_worker (void *a) + l = new->l_initfini[++j]; + } + while (l != NULL); +- _dl_sort_maps (maps, nmaps, NULL, false); + + int relocation_in_progress = 0; + diff --git a/glibc-rh1812756-3.patch b/glibc-rh1812756-3.patch new file mode 100755 index 0000000..93e54e2 --- /dev/null +++ b/glibc-rh1812756-3.patch @@ -0,0 +1,68 @@ +commit 0a8ce6a0966283b17f373f430929bcadef1ae205 +Author: David Kilroy +Date: Wed Feb 12 14:31:17 2020 -0300 + + elf: avoid stack allocation in dl_open_worker + + As the sort was removed, there's no need to keep a separate map of + links. Instead, when relocating objects iterate over l_initfini + directly. + + This allows us to remove the loop copying l_initfini elements into + map. We still need a loop to identify the first and last elements that + need relocation. + + Tested by running the testsuite on x86_64. + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 980a28c836ca9a7a..46a4c1e5a3f8d2dd 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -618,25 +618,18 @@ dl_open_worker (void *a) + This allows IFUNC relocations to work and it also means copy + relocation of dependencies are if necessary overwritten. + __dl_map_object_deps has already sorted l_initfini for us. */ +- unsigned int nmaps = 0; ++ unsigned int first = UINT_MAX; ++ unsigned int last = 0; + unsigned int j = 0; + struct link_map *l = new->l_initfini[0]; + do + { + if (! l->l_real->l_relocated) +- ++nmaps; +- l = new->l_initfini[++j]; +- } +- while (l != NULL); +- /* Stack allocation is limited by the number of loaded objects. */ +- struct link_map *maps[nmaps]; +- nmaps = 0; +- j = 0; +- l = new->l_initfini[0]; +- do +- { +- if (! l->l_real->l_relocated) +- maps[nmaps++] = l; ++ { ++ if (first == UINT_MAX) ++ first = j; ++ last = j + 1; ++ } + l = new->l_initfini[++j]; + } + while (l != NULL); +@@ -651,9 +644,12 @@ dl_open_worker (void *a) + them. However, such relocation dependencies in IFUNC resolvers + are undefined anyway, so this is not a problem. */ + +- for (unsigned int i = nmaps; i-- > 0; ) ++ for (unsigned int i = last; i-- > first; ) + { +- l = maps[i]; ++ l = new->l_initfini[i]; ++ ++ if (l->l_real->l_relocated) ++ continue; + + if (! relocation_in_progress) + { diff --git a/glibc-rh1813398.patch b/glibc-rh1813398.patch new file mode 100755 index 0000000..1355dfa --- /dev/null +++ b/glibc-rh1813398.patch @@ -0,0 +1,58 @@ +commit ddc650e9b3dc916eab417ce9f79e67337b05035c +Author: Andreas Schwab +Date: Wed Feb 19 17:21:46 2020 +0100 + + Fix use-after-free in glob when expanding ~user (bug 25414) + + The value of `end_name' points into the value of `dirname', thus don't + deallocate the latter before the last use of the former. + +diff --git a/posix/glob.c b/posix/glob.c +index cba9cd1819..4580cefb9f 100644 +--- a/posix/glob.c ++++ b/posix/glob.c +@@ -827,31 +827,32 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), + { + size_t home_len = strlen (p->pw_dir); + size_t rest_len = end_name == NULL ? 0 : strlen (end_name); +- char *d; ++ char *d, *newp; ++ bool use_alloca = glob_use_alloca (alloca_used, ++ home_len + rest_len + 1); + +- if (__glibc_unlikely (malloc_dirname)) +- free (dirname); +- malloc_dirname = 0; +- +- if (glob_use_alloca (alloca_used, home_len + rest_len + 1)) +- dirname = alloca_account (home_len + rest_len + 1, +- alloca_used); ++ if (use_alloca) ++ newp = alloca_account (home_len + rest_len + 1, alloca_used); + else + { +- dirname = malloc (home_len + rest_len + 1); +- if (dirname == NULL) ++ newp = malloc (home_len + rest_len + 1); ++ if (newp == NULL) + { + scratch_buffer_free (&pwtmpbuf); + retval = GLOB_NOSPACE; + goto out; + } +- malloc_dirname = 1; + } +- d = mempcpy (dirname, p->pw_dir, home_len); ++ d = mempcpy (newp, p->pw_dir, home_len); + if (end_name != NULL) + d = mempcpy (d, end_name, rest_len); + *d = '\0'; + ++ if (__glibc_unlikely (malloc_dirname)) ++ free (dirname); ++ dirname = newp; ++ malloc_dirname = !use_alloca; ++ + dirlen = home_len + rest_len; + dirname_modified = 1; + } diff --git a/glibc-rh1813399.patch b/glibc-rh1813399.patch new file mode 100755 index 0000000..16ef72d --- /dev/null +++ b/glibc-rh1813399.patch @@ -0,0 +1,59 @@ +commit d93769405996dfc11d216ddbe415946617b5a494 +Author: Andreas Schwab +Date: Mon Jan 20 17:01:50 2020 +0100 + + Fix array overflow in backtrace on PowerPC (bug 25423) + + When unwinding through a signal frame the backtrace function on PowerPC + didn't check array bounds when storing the frame address. Fixes commit + d400dcac5e ("PowerPC: fix backtrace to handle signal trampolines"). + +diff --git a/debug/tst-backtrace5.c b/debug/tst-backtrace5.c +index e7ce410845..b2f46160e7 100644 +--- a/debug/tst-backtrace5.c ++++ b/debug/tst-backtrace5.c +@@ -89,6 +89,18 @@ handle_signal (int signum) + } + /* Symbol names are not available for static functions, so we do not + check do_test. */ ++ ++ /* Check that backtrace does not return more than what fits in the array ++ (bug 25423). */ ++ for (int j = 0; j < NUM_FUNCTIONS; j++) ++ { ++ n = backtrace (addresses, j); ++ if (n > j) ++ { ++ FAIL (); ++ return; ++ } ++ } + } + + NO_INLINE int +diff --git a/sysdeps/powerpc/powerpc32/backtrace.c b/sysdeps/powerpc/powerpc32/backtrace.c +index 7c2d4726f8..d1456c8ae4 100644 +--- a/sysdeps/powerpc/powerpc32/backtrace.c ++++ b/sysdeps/powerpc/powerpc32/backtrace.c +@@ -114,6 +114,8 @@ __backtrace (void **array, int size) + } + if (gregset) + { ++ if (count + 1 == size) ++ break; + array[++count] = (void*)((*gregset)[PT_NIP]); + current = (void*)((*gregset)[PT_R1]); + } +diff --git a/sysdeps/powerpc/powerpc64/backtrace.c b/sysdeps/powerpc/powerpc64/backtrace.c +index 65c260ab76..8a53a1088f 100644 +--- a/sysdeps/powerpc/powerpc64/backtrace.c ++++ b/sysdeps/powerpc/powerpc64/backtrace.c +@@ -87,6 +87,8 @@ __backtrace (void **array, int size) + if (is_sigtramp_address (current->return_address)) + { + struct signal_frame_64 *sigframe = (struct signal_frame_64*) current; ++ if (count + 1 == size) ++ break; + array[++count] = (void*) sigframe->uc.uc_mcontext.gp_regs[PT_NIP]; + current = (void*) sigframe->uc.uc_mcontext.gp_regs[PT_R1]; + } diff --git a/glibc-rh1817513-1.patch b/glibc-rh1817513-1.patch new file mode 100755 index 0000000..5bfd84c --- /dev/null +++ b/glibc-rh1817513-1.patch @@ -0,0 +1,53 @@ +commit 82c80ac2ebf9acc81ec460adfd951d4884836c7c +Author: H.J. Lu +Date: Wed Aug 1 04:57:34 2018 -0700 + + x86: Rename get_common_indeces to get_common_indices + + Reviewed-by: Carlos O'Donell + + * sysdeps/x86/cpu-features.c (get_common_indeces): Renamed to + ... + (get_common_indices): This. + (init_cpu_features): Updated. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index ac74f408343191b0..41f2d15fa5c8a756 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -56,7 +56,7 @@ get_extended_indices (struct cpu_features *cpu_features) + } + + static void +-get_common_indeces (struct cpu_features *cpu_features, ++get_common_indices (struct cpu_features *cpu_features, + unsigned int *family, unsigned int *model, + unsigned int *extended_model, unsigned int *stepping) + { +@@ -234,7 +234,7 @@ init_cpu_features (struct cpu_features *cpu_features) + + kind = arch_kind_intel; + +- get_common_indeces (cpu_features, &family, &model, &extended_model, ++ get_common_indices (cpu_features, &family, &model, &extended_model, + &stepping); + + get_extended_indices (cpu_features); +@@ -356,7 +356,7 @@ init_cpu_features (struct cpu_features *cpu_features) + + kind = arch_kind_amd; + +- get_common_indeces (cpu_features, &family, &model, &extended_model, ++ get_common_indices (cpu_features, &family, &model, &extended_model, + &stepping); + + get_extended_indices (cpu_features); +@@ -393,7 +393,7 @@ init_cpu_features (struct cpu_features *cpu_features) + else + { + kind = arch_kind_other; +- get_common_indeces (cpu_features, NULL, NULL, NULL, NULL); ++ get_common_indices (cpu_features, NULL, NULL, NULL, NULL); + } + + /* Support i586 if CX8 is available. */ diff --git a/glibc-rh1817513-10.patch b/glibc-rh1817513-10.patch new file mode 100755 index 0000000..fe934ce --- /dev/null +++ b/glibc-rh1817513-10.patch @@ -0,0 +1,41 @@ +commit 2dd8e58cc533ee840d37725b11bc0dc0308a5dc0 +Author: H.J. Lu +Date: Sun Oct 21 00:37:11 2018 -0700 + + x86: Don't include + + Use __builtin_ia32_rdtsc directly since including makes + building glibc very slow. On Intel Core i5-6260U, this patch reduces + x86-64 build time from 8 minutes 33 seconds to 3 minutes 48 seconds + with "make -j4" and GCC 8.2.1. + + * sysdeps/x86/hp-timing.h: Don't include . + (HP_TIMING_NOW): Replace _rdtsc with __builtin_ia32_rdtsc. + +diff --git a/sysdeps/x86/hp-timing.h b/sysdeps/x86/hp-timing.h +index 1c20e9d8289cc15b..77a1360748ca4535 100644 +--- a/sysdeps/x86/hp-timing.h ++++ b/sysdeps/x86/hp-timing.h +@@ -22,8 +22,6 @@ + #include + + #if MINIMUM_ISA == 686 || MINIMUM_ISA == 8664 +-# include +- + /* We always assume having the timestamp register. */ + # define HP_TIMING_AVAIL (1) + # define HP_SMALL_TIMING_AVAIL (1) +@@ -38,8 +36,11 @@ typedef unsigned long long int hp_timing_t; + might not be 100% accurate since there might be some more instructions + running in this moment. This could be changed by using a barrier like + 'cpuid' right before the `rdtsc' instruciton. But we are not interested +- in accurate clock cycles here so we don't do this. */ +-# define HP_TIMING_NOW(Var) ((Var) = _rdtsc ()) ++ in accurate clock cycles here so we don't do this. ++ ++ NB: Use __builtin_ia32_rdtsc directly since including ++ makes building glibc very slow. */ ++# define HP_TIMING_NOW(Var) ((Var) = __builtin_ia32_rdtsc ()) + + # include + #else diff --git a/glibc-rh1817513-100.patch b/glibc-rh1817513-100.patch new file mode 100755 index 0000000..9917f06 --- /dev/null +++ b/glibc-rh1817513-100.patch @@ -0,0 +1,82 @@ +commit bb5fd5ce64b598085bdb8a05cb53777480fe093c +Author: Florian Weimer +Date: Fri Oct 9 10:13:14 2020 +0200 + + elf: Do not pass GLRO(dl_platform), GLRO(dl_platformlen) to _dl_important_hwcaps + + In the current code, the function can easily obtain the information + on its own. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c +index ae2e4ca7fe91d407..82ee89c36a1eb4ab 100644 +--- a/elf/dl-hwcaps.c ++++ b/elf/dl-hwcaps.c +@@ -28,13 +28,12 @@ + + /* Return an array of useful/necessary hardware capability names. */ + const struct r_strlenpair * +-_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, +- size_t *max_capstrlen) ++_dl_important_hwcaps (size_t *sz, size_t *max_capstrlen) + { + uint64_t hwcap_mask = GET_HWCAP_MASK(); + /* Determine how many important bits are set. */ + uint64_t masked = GLRO(dl_hwcap) & hwcap_mask; +- size_t cnt = platform != NULL; ++ size_t cnt = GLRO (dl_platform) != NULL; + size_t n, m; + size_t total; + struct r_strlenpair *result; +@@ -60,10 +59,10 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, + masked ^= 1ULL << n; + ++m; + } +- if (platform != NULL) ++ if (GLRO (dl_platform) != NULL) + { +- temp[m].str = platform; +- temp[m].len = platform_len; ++ temp[m].str = GLRO (dl_platform); ++ temp[m].len = GLRO (dl_platformlen); + ++m; + } + +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 2eb4f35b2467f7d8..d2be21ea7d1545fe 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -697,8 +697,7 @@ _dl_init_paths (const char *llp, const char *source) + + #ifdef SHARED + /* Get the capabilities. */ +- capstr = _dl_important_hwcaps (GLRO(dl_platform), GLRO(dl_platformlen), +- &ncapstr, &max_capstrlen); ++ capstr = _dl_important_hwcaps (&ncapstr, &max_capstrlen); + #endif + + /* First set up the rest of the default search directory entries. */ +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index aa006afafaf46dee..2c9fdeb286bdaadf 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1069,12 +1069,12 @@ extern void _dl_show_auxv (void) attribute_hidden; + other. */ + extern char *_dl_next_ld_env_entry (char ***position) attribute_hidden; + +-/* Return an array with the names of the important hardware capabilities. */ +-extern const struct r_strlenpair *_dl_important_hwcaps (const char *platform, +- size_t paltform_len, +- size_t *sz, +- size_t *max_capstrlen) +- attribute_hidden; ++/* Return an array with the names of the important hardware ++ capabilities. The length of the array is written to *SZ, and the ++ maximum of all strings length is written to *MAX_CAPSTRLEN. */ ++const struct r_strlenpair *_dl_important_hwcaps (size_t *sz, ++ size_t *max_capstrlen) ++ attribute_hidden; + + /* Look up NAME in ld.so.cache and return the file name stored there, + or null if none is found. Caller must free returned string. */ diff --git a/glibc-rh1817513-101.patch b/glibc-rh1817513-101.patch new file mode 100755 index 0000000..bcf0aae --- /dev/null +++ b/glibc-rh1817513-101.patch @@ -0,0 +1,65 @@ +commit 7674695cf7e28528be7243ceb30c9a600bbaa7b5 +Author: H.J. Lu +Date: Thu Oct 8 08:19:15 2020 -0700 + + : Add Intel UINTR support + + Add Intel UINTR support to . + +diff --git a/manual/platform.texi b/manual/platform.texi +index 95b0ed0642c9f8a9..0dd12a4353a93bf2 100644 +--- a/manual/platform.texi ++++ b/manual/platform.texi +@@ -583,6 +583,9 @@ using a TSC deadline value. + @item + @code{TSXLDTRK} -- TSXLDTRK instructions. + ++@item ++@code{UINTR} -- User interrupts. ++ + @item + @code{UMIP} -- User-mode instruction prevention. + +diff --git a/sysdeps/x86/sys/platform/x86.h b/sysdeps/x86/sys/platform/x86.h +index bcc81ab5f8ac8265..2760b81a56e6c7d7 100644 +--- a/sysdeps/x86/sys/platform/x86.h ++++ b/sysdeps/x86/sys/platform/x86.h +@@ -241,7 +241,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + #define bit_cpu_AVX512_4VNNIW (1u << 2) + #define bit_cpu_AVX512_4FMAPS (1u << 3) + #define bit_cpu_FSRM (1u << 4) +-#define bit_cpu_INDEX_7_EDX_5 (1u << 5) ++#define bit_cpu_UINTR (1u << 5) + #define bit_cpu_INDEX_7_EDX_6 (1u << 6) + #define bit_cpu_INDEX_7_EDX_7 (1u << 7) + #define bit_cpu_AVX512_VP2INTERSECT (1u << 8) +@@ -460,7 +460,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + #define index_cpu_AVX512_4VNNIW COMMON_CPUID_INDEX_7 + #define index_cpu_AVX512_4FMAPS COMMON_CPUID_INDEX_7 + #define index_cpu_FSRM COMMON_CPUID_INDEX_7 +-#define index_cpu_INDEX_7_EDX_5 COMMON_CPUID_INDEX_7 ++#define index_cpu_UINTR COMMON_CPUID_INDEX_7 + #define index_cpu_INDEX_7_EDX_6 COMMON_CPUID_INDEX_7 + #define index_cpu_INDEX_7_EDX_7 COMMON_CPUID_INDEX_7 + #define index_cpu_AVX512_VP2INTERSECT COMMON_CPUID_INDEX_7 +@@ -679,7 +679,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + #define reg_AVX512_4VNNIW edx + #define reg_AVX512_4FMAPS edx + #define reg_FSRM edx +-#define reg_INDEX_7_EDX_5 edx ++#define reg_UINTR edx + #define reg_INDEX_7_EDX_6 edx + #define reg_INDEX_7_EDX_7 edx + #define reg_AVX512_VP2INTERSECT edx +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index 3ec94e0c9a191f36..6fa092a8c10486a0 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -180,6 +180,7 @@ do_test (void) + CHECK_CPU_FEATURE (AVX512_4VNNIW); + CHECK_CPU_FEATURE (AVX512_4FMAPS); + CHECK_CPU_FEATURE (FSRM); ++ CHECK_CPU_FEATURE (UINTR); + CHECK_CPU_FEATURE (AVX512_VP2INTERSECT); + CHECK_CPU_FEATURE (MD_CLEAR); + CHECK_CPU_FEATURE (SERIALIZE); diff --git a/glibc-rh1817513-102.patch b/glibc-rh1817513-102.patch new file mode 100755 index 0000000..73fa041 --- /dev/null +++ b/glibc-rh1817513-102.patch @@ -0,0 +1,86 @@ +commit ebe454bcca6a5421512ad228595a5391506e990a +Author: H.J. Lu +Date: Thu Oct 8 08:24:47 2020 -0700 + + : Add AVX512_FP16 support + + Add AVX512_FP16 support to . + +diff --git a/manual/platform.texi b/manual/platform.texi +index 0dd12a4353a93bf2..4f5fdff9d9ef16fd 100644 +--- a/manual/platform.texi ++++ b/manual/platform.texi +@@ -210,6 +210,9 @@ The supported processor features are: + @item + @code{AVX512_BITALG} -- The AVX512_BITALG instruction extensions. + ++@item ++@code{AVX512_FP16} -- The AVX512_FP16 instruction extensions. ++ + @item + @code{AVX512_IFMA} -- The AVX512_IFMA instruction extensions. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 7f2ff00f2b4b45f2..67f137259fccf4ad 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -175,6 +175,8 @@ update_usable (struct cpu_features *cpu_features) + AVX512_VP2INTERSECT); + /* Determine if AVX512_BF16 is usable. */ + CPU_FEATURE_SET_USABLE (cpu_features, AVX512_BF16); ++ /* Determine if AVX512_FP16 is usable. */ ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512_FP16); + } + } + } +diff --git a/sysdeps/x86/sys/platform/x86.h b/sysdeps/x86/sys/platform/x86.h +index 2760b81a56e6c7d7..0b18257e20105ea4 100644 +--- a/sysdeps/x86/sys/platform/x86.h ++++ b/sysdeps/x86/sys/platform/x86.h +@@ -259,7 +259,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + #define bit_cpu_IBT (1u << 20) + #define bit_cpu_INDEX_7_EDX_21 (1u << 21) + #define bit_cpu_AMX_BF16 (1u << 22) +-#define bit_cpu_INDEX_7_EDX_23 (1u << 23) ++#define bit_cpu_AVX512_FP16 (1u << 23) + #define bit_cpu_AMX_TILE (1u << 24) + #define bit_cpu_AMX_INT8 (1u << 25) + #define bit_cpu_IBRS_IBPB (1u << 26) +@@ -478,7 +478,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + #define index_cpu_IBT COMMON_CPUID_INDEX_7 + #define index_cpu_INDEX_7_EDX_21 COMMON_CPUID_INDEX_7 + #define index_cpu_AMX_BF16 COMMON_CPUID_INDEX_7 +-#define index_cpu_INDEX_7_EDX_23 COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512_FP16 COMMON_CPUID_INDEX_7 + #define index_cpu_AMX_TILE COMMON_CPUID_INDEX_7 + #define index_cpu_AMX_INT8 COMMON_CPUID_INDEX_7 + #define index_cpu_IBRS_IBPB COMMON_CPUID_INDEX_7 +@@ -697,7 +697,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + #define reg_IBT edx + #define reg_INDEX_7_EDX_21 edx + #define reg_AMX_BF16 edx +-#define reg_INDEX_7_EDX_23 edx ++#define reg_AVX512_FP16 edx + #define reg_AMX_TILE edx + #define reg_AMX_INT8 edx + #define reg_IBRS_IBPB edx +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index 6fa092a8c10486a0..bcdeb243a82c4adc 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -189,6 +189,7 @@ do_test (void) + CHECK_CPU_FEATURE (PCONFIG); + CHECK_CPU_FEATURE (IBT); + CHECK_CPU_FEATURE (AMX_BF16); ++ CHECK_CPU_FEATURE (AVX512_FP16); + CHECK_CPU_FEATURE (AMX_TILE); + CHECK_CPU_FEATURE (AMX_INT8); + CHECK_CPU_FEATURE (IBRS_IBPB); +@@ -343,6 +344,7 @@ do_test (void) + CHECK_CPU_FEATURE_USABLE (TSXLDTRK); + CHECK_CPU_FEATURE_USABLE (PCONFIG); + CHECK_CPU_FEATURE_USABLE (AMX_BF16); ++ CHECK_CPU_FEATURE_USABLE (AVX512_FP16); + CHECK_CPU_FEATURE_USABLE (AMX_TILE); + CHECK_CPU_FEATURE_USABLE (AMX_INT8); + CHECK_CPU_FEATURE_USABLE (IBRS_IBPB); diff --git a/glibc-rh1817513-103.patch b/glibc-rh1817513-103.patch new file mode 100755 index 0000000..0c4db8f --- /dev/null +++ b/glibc-rh1817513-103.patch @@ -0,0 +1,83 @@ +commit 875a50ff63b2c86af770949d563ee851d08eb46e +Author: H.J. Lu +Date: Thu Oct 8 08:33:45 2020 -0700 + + : Add AVX-VNNI support + + Add AVX-VNNI support to . + +diff --git a/manual/platform.texi b/manual/platform.texi +index 4f5fdff9d9ef16fd..283f255679643d3e 100644 +--- a/manual/platform.texi ++++ b/manual/platform.texi +@@ -198,6 +198,9 @@ The supported processor features are: + @item + @code{AVX2} -- The AVX2 instruction extensions. + ++@item ++@code{AVX_VNNI} -- The AVX-VNNI instruction extensions. ++ + @item + @code{AVX512_4FMAPS} -- The AVX512_4FMAPS instruction extensions. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 67f137259fccf4ad..3e5b9341c9756009 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -119,6 +119,8 @@ update_usable (struct cpu_features *cpu_features) + cpu_features->preferred[index_arch_AVX_Fast_Unaligned_Load] + |= bit_arch_AVX_Fast_Unaligned_Load; + } ++ /* Determine if AVX-VNNI is usable. */ ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX_VNNI); + /* Determine if FMA is usable. */ + CPU_FEATURE_SET_USABLE (cpu_features, FMA); + /* Determine if VAES is usable. */ +diff --git a/sysdeps/x86/sys/platform/x86.h b/sysdeps/x86/sys/platform/x86.h +index 0b18257e20105ea4..0942ad7a7f7d4ce2 100644 +--- a/sysdeps/x86/sys/platform/x86.h ++++ b/sysdeps/x86/sys/platform/x86.h +@@ -311,6 +311,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + /* COMMON_CPUID_INDEX_7_ECX_1. */ + + /* EAX. */ ++#define bit_cpu_AVX_VNNI (1u << 4) + #define bit_cpu_AVX512_BF16 (1u << 5) + + /* COMMON_CPUID_INDEX_19. */ +@@ -530,6 +531,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + /* COMMON_CPUID_INDEX_7_ECX_1. */ + + /* EAX. */ ++#define index_cpu_AVX_VNNI COMMON_CPUID_INDEX_7_ECX_1 + #define index_cpu_AVX512_BF16 COMMON_CPUID_INDEX_7_ECX_1 + + /* COMMON_CPUID_INDEX_19. */ +@@ -749,6 +751,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + /* COMMON_CPUID_INDEX_7_ECX_1. */ + + /* EAX. */ ++#define reg_AVX_VNNI eax + #define reg_AVX512_BF16 eax + + /* COMMON_CPUID_INDEX_19. */ +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index bcdeb243a82c4adc..8894d9f08ac36633 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -219,6 +219,7 @@ do_test (void) + CHECK_CPU_FEATURE (XFD); + CHECK_CPU_FEATURE (INVARIANT_TSC); + CHECK_CPU_FEATURE (WBNOINVD); ++ CHECK_CPU_FEATURE (AVX_VNNI); + CHECK_CPU_FEATURE (AVX512_BF16); + CHECK_CPU_FEATURE (AESKLE); + CHECK_CPU_FEATURE (WIDE_KL); +@@ -374,6 +375,7 @@ do_test (void) + CHECK_CPU_FEATURE_USABLE (XFD); + CHECK_CPU_FEATURE_USABLE (INVARIANT_TSC); + CHECK_CPU_FEATURE_USABLE (WBNOINVD); ++ CHECK_CPU_FEATURE_USABLE (AVX_VNNI); + CHECK_CPU_FEATURE_USABLE (AVX512_BF16); + CHECK_CPU_FEATURE_USABLE (AESKLE); + CHECK_CPU_FEATURE_USABLE (WIDE_KL); diff --git a/glibc-rh1817513-104.patch b/glibc-rh1817513-104.patch new file mode 100755 index 0000000..8e0f358 --- /dev/null +++ b/glibc-rh1817513-104.patch @@ -0,0 +1,62 @@ +commit c712401bc641b66d9bd558884751d8979e2e0e96 +Author: H.J. Lu +Date: Thu Oct 8 08:38:03 2020 -0700 + + : Add Intel HRESET support + + Add Intel HRESET support to . + +diff --git a/manual/platform.texi b/manual/platform.texi +index 283f255679643d3e..1e44525552f5bda5 100644 +--- a/manual/platform.texi ++++ b/manual/platform.texi +@@ -346,6 +346,9 @@ extensions. + @item + @code{HTT} -- Max APIC IDs reserved field is Valid. + ++@item ++@code{HRESET} -- History reset. ++ + @item + @code{HYBRID} -- Hybrid processor. + +diff --git a/sysdeps/x86/sys/platform/x86.h b/sysdeps/x86/sys/platform/x86.h +index 0942ad7a7f7d4ce2..357c6f1c5605d82d 100644 +--- a/sysdeps/x86/sys/platform/x86.h ++++ b/sysdeps/x86/sys/platform/x86.h +@@ -313,6 +313,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + /* EAX. */ + #define bit_cpu_AVX_VNNI (1u << 4) + #define bit_cpu_AVX512_BF16 (1u << 5) ++#define bit_cpu_HRESET (1u << 22) + + /* COMMON_CPUID_INDEX_19. */ + +@@ -533,6 +534,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + /* EAX. */ + #define index_cpu_AVX_VNNI COMMON_CPUID_INDEX_7_ECX_1 + #define index_cpu_AVX512_BF16 COMMON_CPUID_INDEX_7_ECX_1 ++#define index_cpu_HRESET COMMON_CPUID_INDEX_7_ECX_1 + + /* COMMON_CPUID_INDEX_19. */ + +@@ -753,6 +755,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + /* EAX. */ + #define reg_AVX_VNNI eax + #define reg_AVX512_BF16 eax ++#define reg_HRESET eax + + /* COMMON_CPUID_INDEX_19. */ + +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index 8894d9f08ac36633..1516af1d461a801b 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -221,6 +221,7 @@ do_test (void) + CHECK_CPU_FEATURE (WBNOINVD); + CHECK_CPU_FEATURE (AVX_VNNI); + CHECK_CPU_FEATURE (AVX512_BF16); ++ CHECK_CPU_FEATURE (HRESET); + CHECK_CPU_FEATURE (AESKLE); + CHECK_CPU_FEATURE (WIDE_KL); + diff --git a/glibc-rh1817513-105.patch b/glibc-rh1817513-105.patch new file mode 100755 index 0000000..5767dbc --- /dev/null +++ b/glibc-rh1817513-105.patch @@ -0,0 +1,107 @@ +commit 428985c436f442e91e27173bccaf28f547233586 +Author: H.J. Lu +Date: Thu Oct 8 08:50:44 2020 -0700 + + : Add FSRCS/FSRS/FZLRM support + + Add Fast Short REP CMP and SCA (FSRCS), Fast Short REP STO (FSRS) and + Fast Zero-Length REP MOV (FZLRM) support to . + +diff --git a/manual/platform.texi b/manual/platform.texi +index 1e44525552f5bda5..8fec2933d6442823 100644 +--- a/manual/platform.texi ++++ b/manual/platform.texi +@@ -331,12 +331,21 @@ extensions. + @item + @code{FSGSBASE} -- RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE instructions. + ++@item ++@code{FSRCS} -- Fast Short REP CMP and SCA. ++ + @item + @code{FSRM} -- Fast Short REP MOV. + ++@item ++@code{FSRS} -- Fast Short REP STO. ++ + @item + @code{FXSR} -- FXSAVE and FXRSTOR instructions. + ++@item ++@code{FZLRM} -- Fast Zero-Length REP MOV. ++ + @item + @code{GFNI} -- GFNI instruction extensions. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 3e5b9341c9756009..5f0548fe08134236 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -93,6 +93,9 @@ update_usable (struct cpu_features *cpu_features) + CPU_FEATURE_SET_USABLE (cpu_features, TBM); + CPU_FEATURE_SET_USABLE (cpu_features, RDTSCP); + CPU_FEATURE_SET_USABLE (cpu_features, WBNOINVD); ++ CPU_FEATURE_SET_USABLE (cpu_features, FZLRM); ++ CPU_FEATURE_SET_USABLE (cpu_features, FSRS); ++ CPU_FEATURE_SET_USABLE (cpu_features, FSRCS); + + /* Can we call xgetbv? */ + if (CPU_FEATURES_CPU_P (cpu_features, OSXSAVE)) +diff --git a/sysdeps/x86/sys/platform/x86.h b/sysdeps/x86/sys/platform/x86.h +index 357c6f1c5605d82d..e5cc7c683a20b5a0 100644 +--- a/sysdeps/x86/sys/platform/x86.h ++++ b/sysdeps/x86/sys/platform/x86.h +@@ -313,6 +313,9 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + /* EAX. */ + #define bit_cpu_AVX_VNNI (1u << 4) + #define bit_cpu_AVX512_BF16 (1u << 5) ++#define bit_cpu_FZLRM (1u << 10) ++#define bit_cpu_FSRS (1u << 11) ++#define bit_cpu_FSRCS (1u << 12) + #define bit_cpu_HRESET (1u << 22) + + /* COMMON_CPUID_INDEX_19. */ +@@ -534,6 +537,9 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + /* EAX. */ + #define index_cpu_AVX_VNNI COMMON_CPUID_INDEX_7_ECX_1 + #define index_cpu_AVX512_BF16 COMMON_CPUID_INDEX_7_ECX_1 ++#define index_cpu_FZLRM COMMON_CPUID_INDEX_7_ECX_1 ++#define index_cpu_FSRS COMMON_CPUID_INDEX_7_ECX_1 ++#define index_cpu_FSRCS COMMON_CPUID_INDEX_7_ECX_1 + #define index_cpu_HRESET COMMON_CPUID_INDEX_7_ECX_1 + + /* COMMON_CPUID_INDEX_19. */ +@@ -755,6 +761,9 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + /* EAX. */ + #define reg_AVX_VNNI eax + #define reg_AVX512_BF16 eax ++#define reg_FZLRM eax ++#define reg_FSRS eax ++#define reg_FSRCS eax + #define reg_HRESET eax + + /* COMMON_CPUID_INDEX_19. */ +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index 1516af1d461a801b..2763deb6d008597f 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -221,6 +221,9 @@ do_test (void) + CHECK_CPU_FEATURE (WBNOINVD); + CHECK_CPU_FEATURE (AVX_VNNI); + CHECK_CPU_FEATURE (AVX512_BF16); ++ CHECK_CPU_FEATURE (FZLRM); ++ CHECK_CPU_FEATURE (FSRS); ++ CHECK_CPU_FEATURE (FSRCS); + CHECK_CPU_FEATURE (HRESET); + CHECK_CPU_FEATURE (AESKLE); + CHECK_CPU_FEATURE (WIDE_KL); +@@ -378,6 +381,9 @@ do_test (void) + CHECK_CPU_FEATURE_USABLE (WBNOINVD); + CHECK_CPU_FEATURE_USABLE (AVX_VNNI); + CHECK_CPU_FEATURE_USABLE (AVX512_BF16); ++ CHECK_CPU_FEATURE_USABLE (FZLRM); ++ CHECK_CPU_FEATURE_USABLE (FSRS); ++ CHECK_CPU_FEATURE_USABLE (FSRCS); + CHECK_CPU_FEATURE_USABLE (AESKLE); + CHECK_CPU_FEATURE_USABLE (WIDE_KL); + diff --git a/glibc-rh1817513-106.patch b/glibc-rh1817513-106.patch new file mode 100755 index 0000000..9e30fb5 --- /dev/null +++ b/glibc-rh1817513-106.patch @@ -0,0 +1,18 @@ +commit 21181d1c7b181c4bb71e587c7944e100d923b393 +Author: Matheus Castanho +Date: Mon Oct 12 11:28:18 2020 +0200 + + elf: Add missing header to elf/dl-usage.c + +diff --git a/elf/dl-usage.c b/elf/dl-usage.c +index c07f43835bd771cf..796ad38b43c2211b 100644 +--- a/elf/dl-usage.c ++++ b/elf/dl-usage.c +@@ -22,6 +22,7 @@ + #include + #include "version.h" + ++#include + #include + + void diff --git a/glibc-rh1817513-107.patch b/glibc-rh1817513-107.patch new file mode 100755 index 0000000..ac33688 --- /dev/null +++ b/glibc-rh1817513-107.patch @@ -0,0 +1,2017 @@ +commit 0f09154c64005e78b61484ae87b5ea2028051ea0 +Author: H.J. Lu +Date: Sat Jul 4 06:35:49 2020 -0700 + + x86: Initialize CPU info via IFUNC relocation [BZ 26203] + + X86 CPU features in ld.so are initialized by init_cpu_features, which is + invoked by DL_PLATFORM_INIT from _dl_sysdep_start. But when ld.so is + loaded by static executable, DL_PLATFORM_INIT is never called. Also + x86 cache info in libc.o and libc.a is initialized by a constructor + which may be called too late. Since some fields in _rtld_global_ro + in ld.so are initialized by dynamic relocation, we can also initialize + x86 CPU features in _rtld_global_ro in ld.so and cache info in libc.so + by initializing dummy function pointers in ld.so and libc.so via IFUNC + relocation. + + Key points: + + 1. IFUNC is always supported, independent of --enable-multi-arch or + --disable-multi-arch. Linker generates IFUNC relocations from input + IFUNC objects and ld.so performs IFUNC relocations. + 2. There are no IFUNC dependencies in ld.so before dynamic relocation + have been performed, + 3. The x86 CPU features in ld.so is initialized by DL_PLATFORM_INIT + in dynamic executable and by IFUNC relocation in dlopen in static + executable. + 4. The x86 cache info in libc.o is initialized by IFUNC relocation. + 5. In libc.a, both x86 CPU features and cache info are initialized from + ARCH_INIT_CPU_FEATURES, not by IFUNC relocation, before __libc_early_init + is called. + + Note: _dl_x86_init_cpu_features can be called more than once from + DL_PLATFORM_INIT and during relocation in ld.so. + +Conflicts: + sysdeps/x86/cacheinfo.c + (Copyright year difference, and AMD Zen cache computation + backports downstream. These changes were reapplied to + sysdeps/x86/cacheinfo.h, mirroring the upstream refactoring + in the backported commit.) + sysdeps/x86/dl-get-cpu-features.c + (Copyright year difference.) + +diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h +index 8c959e39457c8c41..e5776ef7bc8ad749 100644 +--- a/sysdeps/i386/dl-machine.h ++++ b/sysdeps/i386/dl-machine.h +@@ -25,7 +25,6 @@ + #include + #include + #include +-#include + + /* Return nonzero iff ELF header is compatible with the running host. */ + static inline int __attribute__ ((unused)) +@@ -248,9 +247,9 @@ static inline void __attribute__ ((unused)) + dl_platform_init (void) + { + #if IS_IN (rtld) +- /* init_cpu_features has been called early from __libc_start_main in +- static executable. */ +- init_cpu_features (&GLRO(dl_x86_cpu_features)); ++ /* _dl_x86_init_cpu_features is a wrapper for init_cpu_features which ++ has been called early from __libc_start_main in static executable. */ ++ _dl_x86_init_cpu_features (); + #else + if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0') + /* Avoid an empty string which would disturb us. */ +diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c +index fdfe2684759d968c..84b10f6dd8d23a51 100644 +--- a/sysdeps/x86/cacheinfo.c ++++ b/sysdeps/x86/cacheinfo.c +@@ -1,5 +1,5 @@ +-/* x86_64 cache info. +- Copyright (C) 2003-2018 Free Software Foundation, Inc. ++/* x86 cache info. ++ Copyright (C) 2003-2020 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 +@@ -19,473 +19,10 @@ + #if IS_IN (libc) + + #include +-#include +-#include + #include + #include +-#include +- +-static const struct intel_02_cache_info +-{ +- unsigned char idx; +- unsigned char assoc; +- unsigned char linesize; +- unsigned char rel_name; +- unsigned int size; +-} intel_02_known [] = +- { +-#define M(sc) ((sc) - _SC_LEVEL1_ICACHE_SIZE) +- { 0x06, 4, 32, M(_SC_LEVEL1_ICACHE_SIZE), 8192 }, +- { 0x08, 4, 32, M(_SC_LEVEL1_ICACHE_SIZE), 16384 }, +- { 0x09, 4, 32, M(_SC_LEVEL1_ICACHE_SIZE), 32768 }, +- { 0x0a, 2, 32, M(_SC_LEVEL1_DCACHE_SIZE), 8192 }, +- { 0x0c, 4, 32, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, +- { 0x0d, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, +- { 0x0e, 6, 64, M(_SC_LEVEL1_DCACHE_SIZE), 24576 }, +- { 0x21, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, +- { 0x22, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 524288 }, +- { 0x23, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 1048576 }, +- { 0x25, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, +- { 0x29, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, +- { 0x2c, 8, 64, M(_SC_LEVEL1_DCACHE_SIZE), 32768 }, +- { 0x30, 8, 64, M(_SC_LEVEL1_ICACHE_SIZE), 32768 }, +- { 0x39, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, +- { 0x3a, 6, 64, M(_SC_LEVEL2_CACHE_SIZE), 196608 }, +- { 0x3b, 2, 64, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, +- { 0x3c, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, +- { 0x3d, 6, 64, M(_SC_LEVEL2_CACHE_SIZE), 393216 }, +- { 0x3e, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, +- { 0x3f, 2, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, +- { 0x41, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, +- { 0x42, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, +- { 0x43, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, +- { 0x44, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, +- { 0x45, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 2097152 }, +- { 0x46, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, +- { 0x47, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, +- { 0x48, 12, 64, M(_SC_LEVEL2_CACHE_SIZE), 3145728 }, +- { 0x49, 16, 64, M(_SC_LEVEL2_CACHE_SIZE), 4194304 }, +- { 0x4a, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 6291456 }, +- { 0x4b, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, +- { 0x4c, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 12582912 }, +- { 0x4d, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 16777216 }, +- { 0x4e, 24, 64, M(_SC_LEVEL2_CACHE_SIZE), 6291456 }, +- { 0x60, 8, 64, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, +- { 0x66, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 8192 }, +- { 0x67, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, +- { 0x68, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 32768 }, +- { 0x78, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, +- { 0x79, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, +- { 0x7a, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, +- { 0x7b, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, +- { 0x7c, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, +- { 0x7d, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 2097152 }, +- { 0x7f, 2, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, +- { 0x80, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, +- { 0x82, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, +- { 0x83, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, +- { 0x84, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, +- { 0x85, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 2097152 }, +- { 0x86, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, +- { 0x87, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, +- { 0xd0, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 524288 }, +- { 0xd1, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 1048576 }, +- { 0xd2, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, +- { 0xd6, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 1048576 }, +- { 0xd7, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, +- { 0xd8, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, +- { 0xdc, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, +- { 0xdd, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, +- { 0xde, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, +- { 0xe2, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, +- { 0xe3, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, +- { 0xe4, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, +- { 0xea, 24, 64, M(_SC_LEVEL3_CACHE_SIZE), 12582912 }, +- { 0xeb, 24, 64, M(_SC_LEVEL3_CACHE_SIZE), 18874368 }, +- { 0xec, 24, 64, M(_SC_LEVEL3_CACHE_SIZE), 25165824 }, +- }; +- +-#define nintel_02_known (sizeof (intel_02_known) / sizeof (intel_02_known [0])) +- +-static int +-intel_02_known_compare (const void *p1, const void *p2) +-{ +- const struct intel_02_cache_info *i1; +- const struct intel_02_cache_info *i2; +- +- i1 = (const struct intel_02_cache_info *) p1; +- i2 = (const struct intel_02_cache_info *) p2; +- +- if (i1->idx == i2->idx) +- return 0; +- +- return i1->idx < i2->idx ? -1 : 1; +-} +- +- +-static long int +-__attribute__ ((noinline)) +-intel_check_word (int name, unsigned int value, bool *has_level_2, +- bool *no_level_2_or_3, +- const struct cpu_features *cpu_features) +-{ +- if ((value & 0x80000000) != 0) +- /* The register value is reserved. */ +- return 0; +- +- /* Fold the name. The _SC_ constants are always in the order SIZE, +- ASSOC, LINESIZE. */ +- int folded_rel_name = (M(name) / 3) * 3; +- +- while (value != 0) +- { +- unsigned int byte = value & 0xff; +- +- if (byte == 0x40) +- { +- *no_level_2_or_3 = true; +- +- if (folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)) +- /* No need to look further. */ +- break; +- } +- else if (byte == 0xff) +- { +- /* CPUID leaf 0x4 contains all the information. We need to +- iterate over it. */ +- unsigned int eax; +- unsigned int ebx; +- unsigned int ecx; +- unsigned int edx; +- +- unsigned int round = 0; +- while (1) +- { +- __cpuid_count (4, round, eax, ebx, ecx, edx); +- +- enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f; +- if (type == null) +- /* That was the end. */ +- break; +- +- unsigned int level = (eax >> 5) & 0x7; +- +- if ((level == 1 && type == data +- && folded_rel_name == M(_SC_LEVEL1_DCACHE_SIZE)) +- || (level == 1 && type == inst +- && folded_rel_name == M(_SC_LEVEL1_ICACHE_SIZE)) +- || (level == 2 && folded_rel_name == M(_SC_LEVEL2_CACHE_SIZE)) +- || (level == 3 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)) +- || (level == 4 && folded_rel_name == M(_SC_LEVEL4_CACHE_SIZE))) +- { +- unsigned int offset = M(name) - folded_rel_name; +- +- if (offset == 0) +- /* Cache size. */ +- return (((ebx >> 22) + 1) +- * (((ebx >> 12) & 0x3ff) + 1) +- * ((ebx & 0xfff) + 1) +- * (ecx + 1)); +- if (offset == 1) +- return (ebx >> 22) + 1; +- +- assert (offset == 2); +- return (ebx & 0xfff) + 1; +- } +- +- ++round; +- } +- /* There is no other cache information anywhere else. */ +- break; +- } +- else +- { +- if (byte == 0x49 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)) +- { +- /* Intel reused this value. For family 15, model 6 it +- specifies the 3rd level cache. Otherwise the 2nd +- level cache. */ +- unsigned int family = cpu_features->basic.family; +- unsigned int model = cpu_features->basic.model; +- +- if (family == 15 && model == 6) +- { +- /* The level 3 cache is encoded for this model like +- the level 2 cache is for other models. Pretend +- the caller asked for the level 2 cache. */ +- name = (_SC_LEVEL2_CACHE_SIZE +- + (name - _SC_LEVEL3_CACHE_SIZE)); +- folded_rel_name = M(_SC_LEVEL2_CACHE_SIZE); +- } +- } +- +- struct intel_02_cache_info *found; +- struct intel_02_cache_info search; +- +- search.idx = byte; +- found = bsearch (&search, intel_02_known, nintel_02_known, +- sizeof (intel_02_known[0]), intel_02_known_compare); +- if (found != NULL) +- { +- if (found->rel_name == folded_rel_name) +- { +- unsigned int offset = M(name) - folded_rel_name; +- +- if (offset == 0) +- /* Cache size. */ +- return found->size; +- if (offset == 1) +- return found->assoc; +- +- assert (offset == 2); +- return found->linesize; +- } +- +- if (found->rel_name == M(_SC_LEVEL2_CACHE_SIZE)) +- *has_level_2 = true; +- } +- } +- +- /* Next byte for the next round. */ +- value >>= 8; +- } +- +- /* Nothing found. */ +- return 0; +-} +- +- +-static long int __attribute__ ((noinline)) +-handle_intel (int name, const struct cpu_features *cpu_features) +-{ +- unsigned int maxidx = cpu_features->basic.max_cpuid; +- +- /* Return -1 for older CPUs. */ +- if (maxidx < 2) +- return -1; +- +- /* OK, we can use the CPUID instruction to get all info about the +- caches. */ +- unsigned int cnt = 0; +- unsigned int max = 1; +- long int result = 0; +- bool no_level_2_or_3 = false; +- bool has_level_2 = false; +- +- while (cnt++ < max) +- { +- unsigned int eax; +- unsigned int ebx; +- unsigned int ecx; +- unsigned int edx; +- __cpuid (2, eax, ebx, ecx, edx); +- +- /* The low byte of EAX in the first round contain the number of +- rounds we have to make. At least one, the one we are already +- doing. */ +- if (cnt == 1) +- { +- max = eax & 0xff; +- eax &= 0xffffff00; +- } +- +- /* Process the individual registers' value. */ +- result = intel_check_word (name, eax, &has_level_2, +- &no_level_2_or_3, cpu_features); +- if (result != 0) +- return result; +- +- result = intel_check_word (name, ebx, &has_level_2, +- &no_level_2_or_3, cpu_features); +- if (result != 0) +- return result; +- +- result = intel_check_word (name, ecx, &has_level_2, +- &no_level_2_or_3, cpu_features); +- if (result != 0) +- return result; +- +- result = intel_check_word (name, edx, &has_level_2, +- &no_level_2_or_3, cpu_features); +- if (result != 0) +- return result; +- } +- +- if (name >= _SC_LEVEL2_CACHE_SIZE && name <= _SC_LEVEL3_CACHE_LINESIZE +- && no_level_2_or_3) +- return -1; +- +- return 0; +-} +- +- +-static long int __attribute__ ((noinline)) +-handle_amd (int name) +-{ +- unsigned int eax; +- unsigned int ebx; +- unsigned int ecx; +- unsigned int edx; +- __cpuid (0x80000000, eax, ebx, ecx, edx); +- +- /* No level 4 cache (yet). */ +- if (name > _SC_LEVEL3_CACHE_LINESIZE) +- return 0; +- +- unsigned int fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE); +- if (eax < fn) +- return 0; +- +- __cpuid (fn, eax, ebx, ecx, edx); +- +- if (name < _SC_LEVEL1_DCACHE_SIZE) +- { +- name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE; +- ecx = edx; +- } +- +- switch (name) +- { +- case _SC_LEVEL1_DCACHE_SIZE: +- return (ecx >> 14) & 0x3fc00; +- +- case _SC_LEVEL1_DCACHE_ASSOC: +- ecx >>= 16; +- if ((ecx & 0xff) == 0xff) +- /* Fully associative. */ +- return (ecx << 2) & 0x3fc00; +- return ecx & 0xff; +- +- case _SC_LEVEL1_DCACHE_LINESIZE: +- return ecx & 0xff; +- +- case _SC_LEVEL2_CACHE_SIZE: +- return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00; +- +- case _SC_LEVEL2_CACHE_ASSOC: +- switch ((ecx >> 12) & 0xf) +- { +- case 0: +- case 1: +- case 2: +- case 4: +- return (ecx >> 12) & 0xf; +- case 6: +- return 8; +- case 8: +- return 16; +- case 10: +- return 32; +- case 11: +- return 48; +- case 12: +- return 64; +- case 13: +- return 96; +- case 14: +- return 128; +- case 15: +- return ((ecx >> 6) & 0x3fffc00) / (ecx & 0xff); +- default: +- return 0; +- } +- /* NOTREACHED */ +- +- case _SC_LEVEL2_CACHE_LINESIZE: +- return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff; +- +- case _SC_LEVEL3_CACHE_SIZE: +- return (edx & 0xf000) == 0 ? 0 : (edx & 0x3ffc0000) << 1; +- +- case _SC_LEVEL3_CACHE_ASSOC: +- switch ((edx >> 12) & 0xf) +- { +- case 0: +- case 1: +- case 2: +- case 4: +- return (edx >> 12) & 0xf; +- case 6: +- return 8; +- case 8: +- return 16; +- case 10: +- return 32; +- case 11: +- return 48; +- case 12: +- return 64; +- case 13: +- return 96; +- case 14: +- return 128; +- case 15: +- return ((edx & 0x3ffc0000) << 1) / (edx & 0xff); +- default: +- return 0; +- } +- /* NOTREACHED */ +- +- case _SC_LEVEL3_CACHE_LINESIZE: +- return (edx & 0xf000) == 0 ? 0 : edx & 0xff; +- +- default: +- assert (! "cannot happen"); +- } +- return -1; +-} +- +- +-static long int __attribute__ ((noinline)) +-handle_zhaoxin (int name) +-{ +- unsigned int eax; +- unsigned int ebx; +- unsigned int ecx; +- unsigned int edx; +- +- int folded_rel_name = (M(name) / 3) * 3; +- +- unsigned int round = 0; +- while (1) +- { +- __cpuid_count (4, round, eax, ebx, ecx, edx); +- +- enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f; +- if (type == null) +- break; +- +- unsigned int level = (eax >> 5) & 0x7; +- +- if ((level == 1 && type == data +- && folded_rel_name == M(_SC_LEVEL1_DCACHE_SIZE)) +- || (level == 1 && type == inst +- && folded_rel_name == M(_SC_LEVEL1_ICACHE_SIZE)) +- || (level == 2 && folded_rel_name == M(_SC_LEVEL2_CACHE_SIZE)) +- || (level == 3 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE))) +- { +- unsigned int offset = M(name) - folded_rel_name; +- +- if (offset == 0) +- /* Cache size. */ +- return (((ebx >> 22) + 1) +- * (((ebx >> 12) & 0x3ff) + 1) +- * ((ebx & 0xfff) + 1) +- * (ecx + 1)); +- if (offset == 1) +- return (ebx >> 22) + 1; +- +- assert (offset == 2); +- return (ebx & 0xfff) + 1; +- } +- +- ++round; +- } +- +- /* Nothing found. */ +- return 0; +-} +- ++#include ++#include + + /* Get the value of the system variable NAME. */ + long int +@@ -509,409 +46,18 @@ __cache_sysconf (int name) + return 0; + } + ++# ifdef SHARED ++/* NB: In libc.a, cacheinfo.h is included in libc-start.c. In libc.so, ++ cacheinfo.h is included here and call init_cacheinfo by initializing ++ a dummy function pointer via IFUNC relocation after CPU features in ++ ld.so have been initialized by DL_PLATFORM_INIT or IFUNC relocation. */ ++# include ++# include + +-/* Data cache size for use in memory and string routines, typically +- L1 size, rounded to multiple of 256 bytes. */ +-long int __x86_data_cache_size_half attribute_hidden = 32 * 1024 / 2; +-long int __x86_data_cache_size attribute_hidden = 32 * 1024; +-/* Similar to __x86_data_cache_size_half, but not rounded. */ +-long int __x86_raw_data_cache_size_half attribute_hidden = 32 * 1024 / 2; +-/* Similar to __x86_data_cache_size, but not rounded. */ +-long int __x86_raw_data_cache_size attribute_hidden = 32 * 1024; +-/* Shared cache size for use in memory and string routines, typically +- L2 or L3 size, rounded to multiple of 256 bytes. */ +-long int __x86_shared_cache_size_half attribute_hidden = 1024 * 1024 / 2; +-long int __x86_shared_cache_size attribute_hidden = 1024 * 1024; +-/* Similar to __x86_shared_cache_size_half, but not rounded. */ +-long int __x86_raw_shared_cache_size_half attribute_hidden = 1024 * 1024 / 2; +-/* Similar to __x86_shared_cache_size, but not rounded. */ +-long int __x86_raw_shared_cache_size attribute_hidden = 1024 * 1024; +- +-/* Threshold to use non temporal store. */ +-long int __x86_shared_non_temporal_threshold attribute_hidden; +- +-/* Threshold to use Enhanced REP MOVSB. */ +-long int __x86_rep_movsb_threshold attribute_hidden = 2048; +- +-/* Threshold to use Enhanced REP STOSB. */ +-long int __x86_rep_stosb_threshold attribute_hidden = 2048; +- +- +-static void +-get_common_cache_info (long int *shared_ptr, unsigned int *threads_ptr, +- long int core) +-{ +- unsigned int eax; +- unsigned int ebx; +- unsigned int ecx; +- unsigned int edx; +- +- /* Number of logical processors sharing L2 cache. */ +- int threads_l2; +- +- /* Number of logical processors sharing L3 cache. */ +- int threads_l3; +- +- const struct cpu_features *cpu_features = __get_cpu_features (); +- int max_cpuid = cpu_features->basic.max_cpuid; +- unsigned int family = cpu_features->basic.family; +- unsigned int model = cpu_features->basic.model; +- long int shared = *shared_ptr; +- unsigned int threads = *threads_ptr; +- bool inclusive_cache = true; +- bool support_count_mask = true; +- +- /* Try L3 first. */ +- unsigned int level = 3; +- +- if (cpu_features->basic.kind == arch_kind_zhaoxin && family == 6) +- support_count_mask = false; +- +- if (shared <= 0) +- { +- /* Try L2 otherwise. */ +- level = 2; +- shared = core; +- threads_l2 = 0; +- threads_l3 = -1; +- } +- else +- { +- threads_l2 = 0; +- threads_l3 = 0; +- } +- +- /* A value of 0 for the HTT bit indicates there is only a single +- logical processor. */ +- if (CPU_FEATURE_USABLE (HTT)) +- { +- /* Figure out the number of logical threads that share the +- highest cache level. */ +- if (max_cpuid >= 4) +- { +- int i = 0; +- +- /* Query until cache level 2 and 3 are enumerated. */ +- int check = 0x1 | (threads_l3 == 0) << 1; +- do +- { +- __cpuid_count (4, i++, eax, ebx, ecx, edx); +- +- /* There seems to be a bug in at least some Pentium Ds +- which sometimes fail to iterate all cache parameters. +- Do not loop indefinitely here, stop in this case and +- assume there is no such information. */ +- if (cpu_features->basic.kind == arch_kind_intel +- && (eax & 0x1f) == 0 ) +- goto intel_bug_no_cache_info; +- +- switch ((eax >> 5) & 0x7) +- { +- default: +- break; +- case 2: +- if ((check & 0x1)) +- { +- /* Get maximum number of logical processors +- sharing L2 cache. */ +- threads_l2 = (eax >> 14) & 0x3ff; +- check &= ~0x1; +- } +- break; +- case 3: +- if ((check & (0x1 << 1))) +- { +- /* Get maximum number of logical processors +- sharing L3 cache. */ +- threads_l3 = (eax >> 14) & 0x3ff; +- +- /* Check if L2 and L3 caches are inclusive. */ +- inclusive_cache = (edx & 0x2) != 0; +- check &= ~(0x1 << 1); +- } +- break; +- } +- } +- while (check); +- +- /* If max_cpuid >= 11, THREADS_L2/THREADS_L3 are the maximum +- numbers of addressable IDs for logical processors sharing +- the cache, instead of the maximum number of threads +- sharing the cache. */ +- if (max_cpuid >= 11 && support_count_mask) +- { +- /* Find the number of logical processors shipped in +- one core and apply count mask. */ +- i = 0; +- +- /* Count SMT only if there is L3 cache. Always count +- core if there is no L3 cache. */ +- int count = ((threads_l2 > 0 && level == 3) +- | ((threads_l3 > 0 +- || (threads_l2 > 0 && level == 2)) << 1)); +- +- while (count) +- { +- __cpuid_count (11, i++, eax, ebx, ecx, edx); +- +- int shipped = ebx & 0xff; +- int type = ecx & 0xff00; +- if (shipped == 0 || type == 0) +- break; +- else if (type == 0x100) +- { +- /* Count SMT. */ +- if ((count & 0x1)) +- { +- int count_mask; +- +- /* Compute count mask. */ +- asm ("bsr %1, %0" +- : "=r" (count_mask) : "g" (threads_l2)); +- count_mask = ~(-1 << (count_mask + 1)); +- threads_l2 = (shipped - 1) & count_mask; +- count &= ~0x1; +- } +- } +- else if (type == 0x200) +- { +- /* Count core. */ +- if ((count & (0x1 << 1))) +- { +- int count_mask; +- int threads_core +- = (level == 2 ? threads_l2 : threads_l3); +- +- /* Compute count mask. */ +- asm ("bsr %1, %0" +- : "=r" (count_mask) : "g" (threads_core)); +- count_mask = ~(-1 << (count_mask + 1)); +- threads_core = (shipped - 1) & count_mask; +- if (level == 2) +- threads_l2 = threads_core; +- else +- threads_l3 = threads_core; +- count &= ~(0x1 << 1); +- } +- } +- } +- } +- if (threads_l2 > 0) +- threads_l2 += 1; +- if (threads_l3 > 0) +- threads_l3 += 1; +- if (level == 2) +- { +- if (threads_l2) +- { +- threads = threads_l2; +- if (cpu_features->basic.kind == arch_kind_intel +- && threads > 2 +- && family == 6) +- switch (model) +- { +- case 0x37: +- case 0x4a: +- case 0x4d: +- case 0x5a: +- case 0x5d: +- /* Silvermont has L2 cache shared by 2 cores. */ +- threads = 2; +- break; +- default: +- break; +- } +- } +- } +- else if (threads_l3) +- threads = threads_l3; +- } +- else +- { +-intel_bug_no_cache_info: +- /* Assume that all logical threads share the highest cache +- level. */ +- threads +- = ((cpu_features->features[COMMON_CPUID_INDEX_1].cpuid.ebx +- >> 16) & 0xff); +- } +- +- /* Cap usage of highest cache level to the number of supported +- threads. */ +- if (shared > 0 && threads > 0) +- shared /= threads; +- } +- +- /* Account for non-inclusive L2 and L3 caches. */ +- if (!inclusive_cache) +- { +- if (threads_l2 > 0) +- core /= threads_l2; +- shared += core; +- } +- +- *shared_ptr = shared; +- *threads_ptr = threads; +-} +- +- +-static void +-__attribute__((constructor)) +-init_cacheinfo (void) +-{ +- /* Find out what brand of processor. */ +- unsigned int ebx; +- unsigned int ecx; +- unsigned int edx; +- int max_cpuid_ex; +- long int data = -1; +- long int shared = -1; +- long int core; +- unsigned int threads = 0; +- const struct cpu_features *cpu_features = __get_cpu_features (); +- +- if (cpu_features->basic.kind == arch_kind_intel) +- { +- data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, cpu_features); +- core = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features); +- shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, cpu_features); +- +- get_common_cache_info (&shared, &threads, core); +- } +- else if (cpu_features->basic.kind == arch_kind_zhaoxin) +- { +- data = handle_zhaoxin (_SC_LEVEL1_DCACHE_SIZE); +- core = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE); +- shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE); +- +- get_common_cache_info (&shared, &threads, core); +- } +- else if (cpu_features->basic.kind == arch_kind_amd) +- { +- data = handle_amd (_SC_LEVEL1_DCACHE_SIZE); +- long int core = handle_amd (_SC_LEVEL2_CACHE_SIZE); +- shared = handle_amd (_SC_LEVEL3_CACHE_SIZE); ++extern void __x86_cacheinfo (void) attribute_hidden; ++const void (*__x86_cacheinfo_p) (void) attribute_hidden ++ = __x86_cacheinfo; + +- /* Get maximum extended function. */ +- __cpuid (0x80000000, max_cpuid_ex, ebx, ecx, edx); +- +- if (shared <= 0) +- /* No shared L3 cache. All we have is the L2 cache. */ +- shared = core; +- else +- { +- /* Figure out the number of logical threads that share L3. */ +- if (max_cpuid_ex >= 0x80000008) +- { +- /* Get width of APIC ID. */ +- __cpuid (0x80000008, max_cpuid_ex, ebx, ecx, edx); +- threads = 1 << ((ecx >> 12) & 0x0f); +- } +- +- if (threads == 0 || cpu_features->basic.family >= 0x17) +- { +- /* If APIC ID width is not available, use logical +- processor count. */ +- __cpuid (0x00000001, max_cpuid_ex, ebx, ecx, edx); +- +- if ((edx & (1 << 28)) != 0) +- threads = (ebx >> 16) & 0xff; +- } +- +- /* Cap usage of highest cache level to the number of +- supported threads. */ +- if (threads > 0) +- shared /= threads; +- +- /* Get shared cache per ccx for Zen architectures. */ +- if (cpu_features->basic.family >= 0x17) +- { +- unsigned int eax; +- +- /* Get number of threads share the L3 cache in CCX. */ +- __cpuid_count (0x8000001D, 0x3, eax, ebx, ecx, edx); +- +- unsigned int threads_per_ccx = ((eax >> 14) & 0xfff) + 1; +- shared *= threads_per_ccx; +- } +- else +- { +- /* Account for exclusive L2 and L3 caches. */ +- shared += core; +- } +- } +- } +- +- if (cpu_features->data_cache_size != 0) +- data = cpu_features->data_cache_size; +- +- if (data > 0) +- { +- __x86_raw_data_cache_size_half = data / 2; +- __x86_raw_data_cache_size = data; +- /* Round data cache size to multiple of 256 bytes. */ +- data = data & ~255L; +- __x86_data_cache_size_half = data / 2; +- __x86_data_cache_size = data; +- } +- +- if (cpu_features->shared_cache_size != 0) +- shared = cpu_features->shared_cache_size; +- +- if (shared > 0) +- { +- __x86_raw_shared_cache_size_half = shared / 2; +- __x86_raw_shared_cache_size = shared; +- /* Round shared cache size to multiple of 256 bytes. */ +- shared = shared & ~255L; +- __x86_shared_cache_size_half = shared / 2; +- __x86_shared_cache_size = shared; +- } +- +- /* The default setting for the non_temporal threshold is 3/4 of one +- thread's share of the chip's cache. For most Intel and AMD processors +- with an initial release date between 2017 and 2020, a thread's typical +- share of the cache is from 500 KBytes to 2 MBytes. Using the 3/4 +- threshold leaves 125 KBytes to 500 KBytes of the thread's data +- in cache after a maximum temporal copy, which will maintain +- in cache a reasonable portion of the thread's stack and other +- active data. If the threshold is set higher than one thread's +- share of the cache, it has a substantial risk of negatively +- impacting the performance of other threads running on the chip. */ +- __x86_shared_non_temporal_threshold +- = (cpu_features->non_temporal_threshold != 0 +- ? cpu_features->non_temporal_threshold +- : __x86_shared_cache_size * 3 / 4); +- +- /* NB: The REP MOVSB threshold must be greater than VEC_SIZE * 8. */ +- unsigned int minimum_rep_movsb_threshold; +- /* NB: The default REP MOVSB threshold is 2048 * (VEC_SIZE / 16). */ +- unsigned int rep_movsb_threshold; +- if (CPU_FEATURE_USABLE_P (cpu_features, AVX512F) +- && !CPU_FEATURE_PREFERRED_P (cpu_features, Prefer_No_AVX512)) +- { +- rep_movsb_threshold = 2048 * (64 / 16); +- minimum_rep_movsb_threshold = 64 * 8; +- } +- else if (CPU_FEATURE_PREFERRED_P (cpu_features, +- AVX_Fast_Unaligned_Load)) +- { +- rep_movsb_threshold = 2048 * (32 / 16); +- minimum_rep_movsb_threshold = 32 * 8; +- } +- else +- { +- rep_movsb_threshold = 2048 * (16 / 16); +- minimum_rep_movsb_threshold = 16 * 8; +- } +- if (cpu_features->rep_movsb_threshold > minimum_rep_movsb_threshold) +- __x86_rep_movsb_threshold = cpu_features->rep_movsb_threshold; +- else +- __x86_rep_movsb_threshold = rep_movsb_threshold; +- +-# if HAVE_TUNABLES +- __x86_rep_stosb_threshold = cpu_features->rep_stosb_threshold; ++__ifunc (__x86_cacheinfo, __x86_cacheinfo, NULL, void, init_cacheinfo); + # endif +-} +- + #endif +diff --git a/sysdeps/x86/cacheinfo.h b/sysdeps/x86/cacheinfo.h +new file mode 100644 +index 0000000000000000..0255696163b7b8ff +--- /dev/null ++++ b/sysdeps/x86/cacheinfo.h +@@ -0,0 +1,427 @@ ++/* x86 cache info. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++ ++/* Data cache size for use in memory and string routines, typically ++ L1 size, rounded to multiple of 256 bytes. */ ++long int __x86_data_cache_size_half attribute_hidden = 32 * 1024 / 2; ++long int __x86_data_cache_size attribute_hidden = 32 * 1024; ++/* Similar to __x86_data_cache_size_half, but not rounded. */ ++long int __x86_raw_data_cache_size_half attribute_hidden = 32 * 1024 / 2; ++/* Similar to __x86_data_cache_size, but not rounded. */ ++long int __x86_raw_data_cache_size attribute_hidden = 32 * 1024; ++/* Shared cache size for use in memory and string routines, typically ++ L2 or L3 size, rounded to multiple of 256 bytes. */ ++long int __x86_shared_cache_size_half attribute_hidden = 1024 * 1024 / 2; ++long int __x86_shared_cache_size attribute_hidden = 1024 * 1024; ++/* Similar to __x86_shared_cache_size_half, but not rounded. */ ++long int __x86_raw_shared_cache_size_half attribute_hidden = 1024 * 1024 / 2; ++/* Similar to __x86_shared_cache_size, but not rounded. */ ++long int __x86_raw_shared_cache_size attribute_hidden = 1024 * 1024; ++ ++/* Threshold to use non temporal store. */ ++long int __x86_shared_non_temporal_threshold attribute_hidden; ++ ++/* Threshold to use Enhanced REP MOVSB. */ ++long int __x86_rep_movsb_threshold attribute_hidden = 2048; ++ ++/* Threshold to use Enhanced REP STOSB. */ ++long int __x86_rep_stosb_threshold attribute_hidden = 2048; ++ ++static void ++get_common_cache_info (long int *shared_ptr, unsigned int *threads_ptr, ++ long int core) ++{ ++ unsigned int eax; ++ unsigned int ebx; ++ unsigned int ecx; ++ unsigned int edx; ++ ++ /* Number of logical processors sharing L2 cache. */ ++ int threads_l2; ++ ++ /* Number of logical processors sharing L3 cache. */ ++ int threads_l3; ++ ++ const struct cpu_features *cpu_features = __get_cpu_features (); ++ int max_cpuid = cpu_features->basic.max_cpuid; ++ unsigned int family = cpu_features->basic.family; ++ unsigned int model = cpu_features->basic.model; ++ long int shared = *shared_ptr; ++ unsigned int threads = *threads_ptr; ++ bool inclusive_cache = true; ++ bool support_count_mask = true; ++ ++ /* Try L3 first. */ ++ unsigned int level = 3; ++ ++ if (cpu_features->basic.kind == arch_kind_zhaoxin && family == 6) ++ support_count_mask = false; ++ ++ if (shared <= 0) ++ { ++ /* Try L2 otherwise. */ ++ level = 2; ++ shared = core; ++ threads_l2 = 0; ++ threads_l3 = -1; ++ } ++ else ++ { ++ threads_l2 = 0; ++ threads_l3 = 0; ++ } ++ ++ /* A value of 0 for the HTT bit indicates there is only a single ++ logical processor. */ ++ if (HAS_CPU_FEATURE (HTT)) ++ { ++ /* Figure out the number of logical threads that share the ++ highest cache level. */ ++ if (max_cpuid >= 4) ++ { ++ int i = 0; ++ ++ /* Query until cache level 2 and 3 are enumerated. */ ++ int check = 0x1 | (threads_l3 == 0) << 1; ++ do ++ { ++ __cpuid_count (4, i++, eax, ebx, ecx, edx); ++ ++ /* There seems to be a bug in at least some Pentium Ds ++ which sometimes fail to iterate all cache parameters. ++ Do not loop indefinitely here, stop in this case and ++ assume there is no such information. */ ++ if (cpu_features->basic.kind == arch_kind_intel ++ && (eax & 0x1f) == 0 ) ++ goto intel_bug_no_cache_info; ++ ++ switch ((eax >> 5) & 0x7) ++ { ++ default: ++ break; ++ case 2: ++ if ((check & 0x1)) ++ { ++ /* Get maximum number of logical processors ++ sharing L2 cache. */ ++ threads_l2 = (eax >> 14) & 0x3ff; ++ check &= ~0x1; ++ } ++ break; ++ case 3: ++ if ((check & (0x1 << 1))) ++ { ++ /* Get maximum number of logical processors ++ sharing L3 cache. */ ++ threads_l3 = (eax >> 14) & 0x3ff; ++ ++ /* Check if L2 and L3 caches are inclusive. */ ++ inclusive_cache = (edx & 0x2) != 0; ++ check &= ~(0x1 << 1); ++ } ++ break; ++ } ++ } ++ while (check); ++ ++ /* If max_cpuid >= 11, THREADS_L2/THREADS_L3 are the maximum ++ numbers of addressable IDs for logical processors sharing ++ the cache, instead of the maximum number of threads ++ sharing the cache. */ ++ if (max_cpuid >= 11 && support_count_mask) ++ { ++ /* Find the number of logical processors shipped in ++ one core and apply count mask. */ ++ i = 0; ++ ++ /* Count SMT only if there is L3 cache. Always count ++ core if there is no L3 cache. */ ++ int count = ((threads_l2 > 0 && level == 3) ++ | ((threads_l3 > 0 ++ || (threads_l2 > 0 && level == 2)) << 1)); ++ ++ while (count) ++ { ++ __cpuid_count (11, i++, eax, ebx, ecx, edx); ++ ++ int shipped = ebx & 0xff; ++ int type = ecx & 0xff00; ++ if (shipped == 0 || type == 0) ++ break; ++ else if (type == 0x100) ++ { ++ /* Count SMT. */ ++ if ((count & 0x1)) ++ { ++ int count_mask; ++ ++ /* Compute count mask. */ ++ asm ("bsr %1, %0" ++ : "=r" (count_mask) : "g" (threads_l2)); ++ count_mask = ~(-1 << (count_mask + 1)); ++ threads_l2 = (shipped - 1) & count_mask; ++ count &= ~0x1; ++ } ++ } ++ else if (type == 0x200) ++ { ++ /* Count core. */ ++ if ((count & (0x1 << 1))) ++ { ++ int count_mask; ++ int threads_core ++ = (level == 2 ? threads_l2 : threads_l3); ++ ++ /* Compute count mask. */ ++ asm ("bsr %1, %0" ++ : "=r" (count_mask) : "g" (threads_core)); ++ count_mask = ~(-1 << (count_mask + 1)); ++ threads_core = (shipped - 1) & count_mask; ++ if (level == 2) ++ threads_l2 = threads_core; ++ else ++ threads_l3 = threads_core; ++ count &= ~(0x1 << 1); ++ } ++ } ++ } ++ } ++ if (threads_l2 > 0) ++ threads_l2 += 1; ++ if (threads_l3 > 0) ++ threads_l3 += 1; ++ if (level == 2) ++ { ++ if (threads_l2) ++ { ++ threads = threads_l2; ++ if (cpu_features->basic.kind == arch_kind_intel ++ && threads > 2 ++ && family == 6) ++ switch (model) ++ { ++ case 0x37: ++ case 0x4a: ++ case 0x4d: ++ case 0x5a: ++ case 0x5d: ++ /* Silvermont has L2 cache shared by 2 cores. */ ++ threads = 2; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ else if (threads_l3) ++ threads = threads_l3; ++ } ++ else ++ { ++intel_bug_no_cache_info: ++ /* Assume that all logical threads share the highest cache ++ level. */ ++ threads ++ = ((cpu_features->features[COMMON_CPUID_INDEX_1].cpuid.ebx ++ >> 16) & 0xff); ++ } ++ ++ /* Cap usage of highest cache level to the number of supported ++ threads. */ ++ if (shared > 0 && threads > 0) ++ shared /= threads; ++ } ++ ++ /* Account for non-inclusive L2 and L3 caches. */ ++ if (!inclusive_cache) ++ { ++ if (threads_l2 > 0) ++ core /= threads_l2; ++ shared += core; ++ } ++ ++ *shared_ptr = shared; ++ *threads_ptr = threads; ++} ++ ++static void ++init_cacheinfo (void) ++{ ++ /* Find out what brand of processor. */ ++ unsigned int ebx; ++ unsigned int ecx; ++ unsigned int edx; ++ int max_cpuid_ex; ++ long int data = -1; ++ long int shared = -1; ++ long int core; ++ unsigned int threads = 0; ++ const struct cpu_features *cpu_features = __get_cpu_features (); ++ ++ /* NB: In libc.so, cpu_features is defined in ld.so and is initialized ++ by DL_PLATFORM_INIT or IFUNC relocation before init_cacheinfo is ++ called by IFUNC relocation. In libc.a, init_cacheinfo is called ++ from init_cpu_features by ARCH_INIT_CPU_FEATURES. */ ++ assert (cpu_features->basic.kind != arch_kind_unknown); ++ ++ if (cpu_features->basic.kind == arch_kind_intel) ++ { ++ data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, cpu_features); ++ core = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features); ++ shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, cpu_features); ++ ++ get_common_cache_info (&shared, &threads, core); ++ } ++ else if (cpu_features->basic.kind == arch_kind_zhaoxin) ++ { ++ data = handle_zhaoxin (_SC_LEVEL1_DCACHE_SIZE); ++ core = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE); ++ shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE); ++ ++ get_common_cache_info (&shared, &threads, core); ++ } ++ else if (cpu_features->basic.kind == arch_kind_amd) ++ { ++ data = handle_amd (_SC_LEVEL1_DCACHE_SIZE); ++ long int core = handle_amd (_SC_LEVEL2_CACHE_SIZE); ++ shared = handle_amd (_SC_LEVEL3_CACHE_SIZE); ++ ++ /* Get maximum extended function. */ ++ __cpuid (0x80000000, max_cpuid_ex, ebx, ecx, edx); ++ ++ if (shared <= 0) ++ /* No shared L3 cache. All we have is the L2 cache. */ ++ shared = core; ++ else ++ { ++ /* Figure out the number of logical threads that share L3. */ ++ if (max_cpuid_ex >= 0x80000008) ++ { ++ /* Get width of APIC ID. */ ++ __cpuid (0x80000008, max_cpuid_ex, ebx, ecx, edx); ++ threads = 1 << ((ecx >> 12) & 0x0f); ++ } ++ ++ if (threads == 0 || cpu_features->basic.family >= 0x17) ++ { ++ /* If APIC ID width is not available, use logical ++ processor count. */ ++ __cpuid (0x00000001, max_cpuid_ex, ebx, ecx, edx); ++ ++ if ((edx & (1 << 28)) != 0) ++ threads = (ebx >> 16) & 0xff; ++ } ++ ++ /* Cap usage of highest cache level to the number of ++ supported threads. */ ++ if (threads > 0) ++ shared /= threads; ++ ++ /* Get shared cache per ccx for Zen architectures. */ ++ if (cpu_features->basic.family >= 0x17) ++ { ++ unsigned int eax; ++ ++ /* Get number of threads share the L3 cache in CCX. */ ++ __cpuid_count (0x8000001D, 0x3, eax, ebx, ecx, edx); ++ ++ unsigned int threads_per_ccx = ((eax >> 14) & 0xfff) + 1; ++ shared *= threads_per_ccx; ++ } ++ else ++ { ++ /* Account for exclusive L2 and L3 caches. */ ++ shared += core; ++ } ++ } ++ } ++ ++ if (cpu_features->data_cache_size != 0) ++ data = cpu_features->data_cache_size; ++ ++ if (data > 0) ++ { ++ __x86_raw_data_cache_size_half = data / 2; ++ __x86_raw_data_cache_size = data; ++ /* Round data cache size to multiple of 256 bytes. */ ++ data = data & ~255L; ++ __x86_data_cache_size_half = data / 2; ++ __x86_data_cache_size = data; ++ } ++ ++ if (cpu_features->shared_cache_size != 0) ++ shared = cpu_features->shared_cache_size; ++ ++ if (shared > 0) ++ { ++ __x86_raw_shared_cache_size_half = shared / 2; ++ __x86_raw_shared_cache_size = shared; ++ /* Round shared cache size to multiple of 256 bytes. */ ++ shared = shared & ~255L; ++ __x86_shared_cache_size_half = shared / 2; ++ __x86_shared_cache_size = shared; ++ } ++ ++ /* The default setting for the non_temporal threshold is 3/4 of one ++ thread's share of the chip's cache. For most Intel and AMD processors ++ with an initial release date between 2017 and 2020, a thread's typical ++ share of the cache is from 500 KBytes to 2 MBytes. Using the 3/4 ++ threshold leaves 125 KBytes to 500 KBytes of the thread's data ++ in cache after a maximum temporal copy, which will maintain ++ in cache a reasonable portion of the thread's stack and other ++ active data. If the threshold is set higher than one thread's ++ share of the cache, it has a substantial risk of negatively ++ impacting the performance of other threads running on the chip. */ ++ __x86_shared_non_temporal_threshold ++ = (cpu_features->non_temporal_threshold != 0 ++ ? cpu_features->non_temporal_threshold ++ : __x86_shared_cache_size * 3 / 4); ++ ++ /* NB: The REP MOVSB threshold must be greater than VEC_SIZE * 8. */ ++ unsigned int minimum_rep_movsb_threshold; ++ /* NB: The default REP MOVSB threshold is 2048 * (VEC_SIZE / 16). */ ++ unsigned int rep_movsb_threshold; ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX512F) ++ && !CPU_FEATURE_PREFERRED_P (cpu_features, Prefer_No_AVX512)) ++ { ++ rep_movsb_threshold = 2048 * (64 / 16); ++ minimum_rep_movsb_threshold = 64 * 8; ++ } ++ else if (CPU_FEATURE_PREFERRED_P (cpu_features, ++ AVX_Fast_Unaligned_Load)) ++ { ++ rep_movsb_threshold = 2048 * (32 / 16); ++ minimum_rep_movsb_threshold = 32 * 8; ++ } ++ else ++ { ++ rep_movsb_threshold = 2048 * (16 / 16); ++ minimum_rep_movsb_threshold = 16 * 8; ++ } ++ if (cpu_features->rep_movsb_threshold > minimum_rep_movsb_threshold) ++ __x86_rep_movsb_threshold = cpu_features->rep_movsb_threshold; ++ else ++ __x86_rep_movsb_threshold = rep_movsb_threshold; ++ ++# if HAVE_TUNABLES ++ __x86_rep_stosb_threshold = cpu_features->rep_stosb_threshold; ++# endif ++} +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 5f0548fe08134236..4c9c15a44b618fed 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -17,9 +17,14 @@ + . */ + + #include +-#include + #include + #include ++#if IS_IN (libc) && !defined SHARED ++# include ++# include ++# include ++# include ++#endif + + #if HAVE_TUNABLES + # define TUNABLE_NAMESPACE cpu +@@ -752,4 +757,9 @@ no_cpuid: + # endif + } + #endif ++ ++#ifndef SHARED ++ /* NB: In libc.a, call init_cacheinfo. */ ++ init_cacheinfo (); ++#endif + } +diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h +new file mode 100644 +index 0000000000000000..b2b90074b0e98a60 +--- /dev/null ++++ b/sysdeps/x86/dl-cacheinfo.h +@@ -0,0 +1,478 @@ ++/* Initialize x86 cache info. ++ Copyright (C) 2020 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 ++ . */ ++ ++static const struct intel_02_cache_info ++{ ++ unsigned char idx; ++ unsigned char assoc; ++ unsigned char linesize; ++ unsigned char rel_name; ++ unsigned int size; ++} intel_02_known [] = ++ { ++#define M(sc) ((sc) - _SC_LEVEL1_ICACHE_SIZE) ++ { 0x06, 4, 32, M(_SC_LEVEL1_ICACHE_SIZE), 8192 }, ++ { 0x08, 4, 32, M(_SC_LEVEL1_ICACHE_SIZE), 16384 }, ++ { 0x09, 4, 32, M(_SC_LEVEL1_ICACHE_SIZE), 32768 }, ++ { 0x0a, 2, 32, M(_SC_LEVEL1_DCACHE_SIZE), 8192 }, ++ { 0x0c, 4, 32, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, ++ { 0x0d, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, ++ { 0x0e, 6, 64, M(_SC_LEVEL1_DCACHE_SIZE), 24576 }, ++ { 0x21, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, ++ { 0x22, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 524288 }, ++ { 0x23, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 1048576 }, ++ { 0x25, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, ++ { 0x29, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, ++ { 0x2c, 8, 64, M(_SC_LEVEL1_DCACHE_SIZE), 32768 }, ++ { 0x30, 8, 64, M(_SC_LEVEL1_ICACHE_SIZE), 32768 }, ++ { 0x39, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, ++ { 0x3a, 6, 64, M(_SC_LEVEL2_CACHE_SIZE), 196608 }, ++ { 0x3b, 2, 64, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, ++ { 0x3c, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, ++ { 0x3d, 6, 64, M(_SC_LEVEL2_CACHE_SIZE), 393216 }, ++ { 0x3e, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, ++ { 0x3f, 2, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, ++ { 0x41, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, ++ { 0x42, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, ++ { 0x43, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, ++ { 0x44, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, ++ { 0x45, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 2097152 }, ++ { 0x46, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, ++ { 0x47, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, ++ { 0x48, 12, 64, M(_SC_LEVEL2_CACHE_SIZE), 3145728 }, ++ { 0x49, 16, 64, M(_SC_LEVEL2_CACHE_SIZE), 4194304 }, ++ { 0x4a, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 6291456 }, ++ { 0x4b, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, ++ { 0x4c, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 12582912 }, ++ { 0x4d, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 16777216 }, ++ { 0x4e, 24, 64, M(_SC_LEVEL2_CACHE_SIZE), 6291456 }, ++ { 0x60, 8, 64, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, ++ { 0x66, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 8192 }, ++ { 0x67, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, ++ { 0x68, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 32768 }, ++ { 0x78, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, ++ { 0x79, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, ++ { 0x7a, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, ++ { 0x7b, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, ++ { 0x7c, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, ++ { 0x7d, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 2097152 }, ++ { 0x7f, 2, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, ++ { 0x80, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, ++ { 0x82, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, ++ { 0x83, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, ++ { 0x84, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, ++ { 0x85, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 2097152 }, ++ { 0x86, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, ++ { 0x87, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, ++ { 0xd0, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 524288 }, ++ { 0xd1, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 1048576 }, ++ { 0xd2, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, ++ { 0xd6, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 1048576 }, ++ { 0xd7, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, ++ { 0xd8, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, ++ { 0xdc, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, ++ { 0xdd, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, ++ { 0xde, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, ++ { 0xe2, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, ++ { 0xe3, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, ++ { 0xe4, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, ++ { 0xea, 24, 64, M(_SC_LEVEL3_CACHE_SIZE), 12582912 }, ++ { 0xeb, 24, 64, M(_SC_LEVEL3_CACHE_SIZE), 18874368 }, ++ { 0xec, 24, 64, M(_SC_LEVEL3_CACHE_SIZE), 25165824 }, ++ }; ++ ++#define nintel_02_known (sizeof (intel_02_known) / sizeof (intel_02_known [0])) ++ ++static int ++intel_02_known_compare (const void *p1, const void *p2) ++{ ++ const struct intel_02_cache_info *i1; ++ const struct intel_02_cache_info *i2; ++ ++ i1 = (const struct intel_02_cache_info *) p1; ++ i2 = (const struct intel_02_cache_info *) p2; ++ ++ if (i1->idx == i2->idx) ++ return 0; ++ ++ return i1->idx < i2->idx ? -1 : 1; ++} ++ ++ ++static long int ++__attribute__ ((noinline)) ++intel_check_word (int name, unsigned int value, bool *has_level_2, ++ bool *no_level_2_or_3, ++ const struct cpu_features *cpu_features) ++{ ++ if ((value & 0x80000000) != 0) ++ /* The register value is reserved. */ ++ return 0; ++ ++ /* Fold the name. The _SC_ constants are always in the order SIZE, ++ ASSOC, LINESIZE. */ ++ int folded_rel_name = (M(name) / 3) * 3; ++ ++ while (value != 0) ++ { ++ unsigned int byte = value & 0xff; ++ ++ if (byte == 0x40) ++ { ++ *no_level_2_or_3 = true; ++ ++ if (folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)) ++ /* No need to look further. */ ++ break; ++ } ++ else if (byte == 0xff) ++ { ++ /* CPUID leaf 0x4 contains all the information. We need to ++ iterate over it. */ ++ unsigned int eax; ++ unsigned int ebx; ++ unsigned int ecx; ++ unsigned int edx; ++ ++ unsigned int round = 0; ++ while (1) ++ { ++ __cpuid_count (4, round, eax, ebx, ecx, edx); ++ ++ enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f; ++ if (type == null) ++ /* That was the end. */ ++ break; ++ ++ unsigned int level = (eax >> 5) & 0x7; ++ ++ if ((level == 1 && type == data ++ && folded_rel_name == M(_SC_LEVEL1_DCACHE_SIZE)) ++ || (level == 1 && type == inst ++ && folded_rel_name == M(_SC_LEVEL1_ICACHE_SIZE)) ++ || (level == 2 && folded_rel_name == M(_SC_LEVEL2_CACHE_SIZE)) ++ || (level == 3 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)) ++ || (level == 4 && folded_rel_name == M(_SC_LEVEL4_CACHE_SIZE))) ++ { ++ unsigned int offset = M(name) - folded_rel_name; ++ ++ if (offset == 0) ++ /* Cache size. */ ++ return (((ebx >> 22) + 1) ++ * (((ebx >> 12) & 0x3ff) + 1) ++ * ((ebx & 0xfff) + 1) ++ * (ecx + 1)); ++ if (offset == 1) ++ return (ebx >> 22) + 1; ++ ++ assert (offset == 2); ++ return (ebx & 0xfff) + 1; ++ } ++ ++ ++round; ++ } ++ /* There is no other cache information anywhere else. */ ++ break; ++ } ++ else ++ { ++ if (byte == 0x49 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)) ++ { ++ /* Intel reused this value. For family 15, model 6 it ++ specifies the 3rd level cache. Otherwise the 2nd ++ level cache. */ ++ unsigned int family = cpu_features->basic.family; ++ unsigned int model = cpu_features->basic.model; ++ ++ if (family == 15 && model == 6) ++ { ++ /* The level 3 cache is encoded for this model like ++ the level 2 cache is for other models. Pretend ++ the caller asked for the level 2 cache. */ ++ name = (_SC_LEVEL2_CACHE_SIZE ++ + (name - _SC_LEVEL3_CACHE_SIZE)); ++ folded_rel_name = M(_SC_LEVEL2_CACHE_SIZE); ++ } ++ } ++ ++ struct intel_02_cache_info *found; ++ struct intel_02_cache_info search; ++ ++ search.idx = byte; ++ found = bsearch (&search, intel_02_known, nintel_02_known, ++ sizeof (intel_02_known[0]), intel_02_known_compare); ++ if (found != NULL) ++ { ++ if (found->rel_name == folded_rel_name) ++ { ++ unsigned int offset = M(name) - folded_rel_name; ++ ++ if (offset == 0) ++ /* Cache size. */ ++ return found->size; ++ if (offset == 1) ++ return found->assoc; ++ ++ assert (offset == 2); ++ return found->linesize; ++ } ++ ++ if (found->rel_name == M(_SC_LEVEL2_CACHE_SIZE)) ++ *has_level_2 = true; ++ } ++ } ++ ++ /* Next byte for the next round. */ ++ value >>= 8; ++ } ++ ++ /* Nothing found. */ ++ return 0; ++} ++ ++ ++static long int __attribute__ ((noinline)) ++handle_intel (int name, const struct cpu_features *cpu_features) ++{ ++ unsigned int maxidx = cpu_features->basic.max_cpuid; ++ ++ /* Return -1 for older CPUs. */ ++ if (maxidx < 2) ++ return -1; ++ ++ /* OK, we can use the CPUID instruction to get all info about the ++ caches. */ ++ unsigned int cnt = 0; ++ unsigned int max = 1; ++ long int result = 0; ++ bool no_level_2_or_3 = false; ++ bool has_level_2 = false; ++ ++ while (cnt++ < max) ++ { ++ unsigned int eax; ++ unsigned int ebx; ++ unsigned int ecx; ++ unsigned int edx; ++ __cpuid (2, eax, ebx, ecx, edx); ++ ++ /* The low byte of EAX in the first round contain the number of ++ rounds we have to make. At least one, the one we are already ++ doing. */ ++ if (cnt == 1) ++ { ++ max = eax & 0xff; ++ eax &= 0xffffff00; ++ } ++ ++ /* Process the individual registers' value. */ ++ result = intel_check_word (name, eax, &has_level_2, ++ &no_level_2_or_3, cpu_features); ++ if (result != 0) ++ return result; ++ ++ result = intel_check_word (name, ebx, &has_level_2, ++ &no_level_2_or_3, cpu_features); ++ if (result != 0) ++ return result; ++ ++ result = intel_check_word (name, ecx, &has_level_2, ++ &no_level_2_or_3, cpu_features); ++ if (result != 0) ++ return result; ++ ++ result = intel_check_word (name, edx, &has_level_2, ++ &no_level_2_or_3, cpu_features); ++ if (result != 0) ++ return result; ++ } ++ ++ if (name >= _SC_LEVEL2_CACHE_SIZE && name <= _SC_LEVEL3_CACHE_LINESIZE ++ && no_level_2_or_3) ++ return -1; ++ ++ return 0; ++} ++ ++ ++static long int __attribute__ ((noinline)) ++handle_amd (int name) ++{ ++ unsigned int eax; ++ unsigned int ebx; ++ unsigned int ecx; ++ unsigned int edx; ++ __cpuid (0x80000000, eax, ebx, ecx, edx); ++ ++ /* No level 4 cache (yet). */ ++ if (name > _SC_LEVEL3_CACHE_LINESIZE) ++ return 0; ++ ++ unsigned int fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE); ++ if (eax < fn) ++ return 0; ++ ++ __cpuid (fn, eax, ebx, ecx, edx); ++ ++ if (name < _SC_LEVEL1_DCACHE_SIZE) ++ { ++ name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE; ++ ecx = edx; ++ } ++ ++ switch (name) ++ { ++ case _SC_LEVEL1_DCACHE_SIZE: ++ return (ecx >> 14) & 0x3fc00; ++ ++ case _SC_LEVEL1_DCACHE_ASSOC: ++ ecx >>= 16; ++ if ((ecx & 0xff) == 0xff) ++ /* Fully associative. */ ++ return (ecx << 2) & 0x3fc00; ++ return ecx & 0xff; ++ ++ case _SC_LEVEL1_DCACHE_LINESIZE: ++ return ecx & 0xff; ++ ++ case _SC_LEVEL2_CACHE_SIZE: ++ return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00; ++ ++ case _SC_LEVEL2_CACHE_ASSOC: ++ switch ((ecx >> 12) & 0xf) ++ { ++ case 0: ++ case 1: ++ case 2: ++ case 4: ++ return (ecx >> 12) & 0xf; ++ case 6: ++ return 8; ++ case 8: ++ return 16; ++ case 10: ++ return 32; ++ case 11: ++ return 48; ++ case 12: ++ return 64; ++ case 13: ++ return 96; ++ case 14: ++ return 128; ++ case 15: ++ return ((ecx >> 6) & 0x3fffc00) / (ecx & 0xff); ++ default: ++ return 0; ++ } ++ /* NOTREACHED */ ++ ++ case _SC_LEVEL2_CACHE_LINESIZE: ++ return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff; ++ ++ case _SC_LEVEL3_CACHE_SIZE: ++ return (edx & 0xf000) == 0 ? 0 : (edx & 0x3ffc0000) << 1; ++ ++ case _SC_LEVEL3_CACHE_ASSOC: ++ switch ((edx >> 12) & 0xf) ++ { ++ case 0: ++ case 1: ++ case 2: ++ case 4: ++ return (edx >> 12) & 0xf; ++ case 6: ++ return 8; ++ case 8: ++ return 16; ++ case 10: ++ return 32; ++ case 11: ++ return 48; ++ case 12: ++ return 64; ++ case 13: ++ return 96; ++ case 14: ++ return 128; ++ case 15: ++ return ((edx & 0x3ffc0000) << 1) / (edx & 0xff); ++ default: ++ return 0; ++ } ++ /* NOTREACHED */ ++ ++ case _SC_LEVEL3_CACHE_LINESIZE: ++ return (edx & 0xf000) == 0 ? 0 : edx & 0xff; ++ ++ default: ++ assert (! "cannot happen"); ++ } ++ return -1; ++} ++ ++ ++static long int __attribute__ ((noinline)) ++handle_zhaoxin (int name) ++{ ++ unsigned int eax; ++ unsigned int ebx; ++ unsigned int ecx; ++ unsigned int edx; ++ ++ int folded_rel_name = (M(name) / 3) * 3; ++ ++ unsigned int round = 0; ++ while (1) ++ { ++ __cpuid_count (4, round, eax, ebx, ecx, edx); ++ ++ enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f; ++ if (type == null) ++ break; ++ ++ unsigned int level = (eax >> 5) & 0x7; ++ ++ if ((level == 1 && type == data ++ && folded_rel_name == M(_SC_LEVEL1_DCACHE_SIZE)) ++ || (level == 1 && type == inst ++ && folded_rel_name == M(_SC_LEVEL1_ICACHE_SIZE)) ++ || (level == 2 && folded_rel_name == M(_SC_LEVEL2_CACHE_SIZE)) ++ || (level == 3 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE))) ++ { ++ unsigned int offset = M(name) - folded_rel_name; ++ ++ if (offset == 0) ++ /* Cache size. */ ++ return (((ebx >> 22) + 1) ++ * (((ebx >> 12) & 0x3ff) + 1) ++ * ((ebx & 0xfff) + 1) ++ * (ecx + 1)); ++ if (offset == 1) ++ return (ebx >> 22) + 1; ++ ++ assert (offset == 2); ++ return (ebx & 0xfff) + 1; ++ } ++ ++ ++round; ++ } ++ ++ /* Nothing found. */ ++ return 0; ++} +diff --git a/sysdeps/x86/dl-get-cpu-features.c b/sysdeps/x86/dl-get-cpu-features.c +index 2aba0d167129b336..82772cc12f0c7e54 100644 +--- a/sysdeps/x86/dl-get-cpu-features.c ++++ b/sysdeps/x86/dl-get-cpu-features.c +@@ -1,5 +1,5 @@ +-/* This file is part of the GNU C Library. +- Copyright (C) 2015-2018 Free Software Foundation, Inc. ++/* Initialize CPU feature data via IFUNC relocation. ++ Copyright (C) 2015-2020 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public +@@ -18,6 +18,31 @@ + + #include + ++#ifdef SHARED ++# include ++ ++/* NB: Normally, DL_PLATFORM_INIT calls init_cpu_features to initialize ++ CPU features in dynamic executable. But when loading ld.so inside of ++ static executable, DL_PLATFORM_INIT isn't called and IFUNC relocation ++ is used to call init_cpu_features. In static executable, it is called ++ once by IFUNC relocation. In dynamic executable, it is called twice ++ by DL_PLATFORM_INIT and by IFUNC relocation. */ ++extern void __x86_cpu_features (void) attribute_hidden; ++const void (*__x86_cpu_features_p) (void) attribute_hidden ++ = __x86_cpu_features; ++ ++void ++_dl_x86_init_cpu_features (void) ++{ ++ struct cpu_features *cpu_features = __get_cpu_features (); ++ if (cpu_features->basic.kind == arch_kind_unknown) ++ init_cpu_features (cpu_features); ++} ++ ++__ifunc (__x86_cpu_features, __x86_cpu_features, NULL, void, ++ _dl_x86_init_cpu_features); ++#endif ++ + #undef __x86_get_cpu_features + + const struct cpu_features * +diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h +index dcf29b6fe8578078..f62be0b9b3746675 100644 +--- a/sysdeps/x86/include/cpu-features.h ++++ b/sysdeps/x86/include/cpu-features.h +@@ -159,6 +159,7 @@ struct cpu_features + /* Unused for x86. */ + # define INIT_ARCH() + # define __x86_get_cpu_features(max) (&GLRO(dl_x86_cpu_features)) ++extern void _dl_x86_init_cpu_features (void) attribute_hidden; + # endif + + # ifdef __x86_64__ +diff --git a/sysdeps/x86/libc-start.c b/sysdeps/x86/libc-start.c +index eb5335c154096384..60f2c34ab5511350 100644 +--- a/sysdeps/x86/libc-start.c ++++ b/sysdeps/x86/libc-start.c +@@ -20,7 +20,6 @@ + PIE. */ + # include + # include +-# include + # include + + extern struct cpu_features _dl_x86_cpu_features; +diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h +index d58298d787ef352c..e308b662d245cc63 100644 +--- a/sysdeps/x86_64/dl-machine.h ++++ b/sysdeps/x86_64/dl-machine.h +@@ -26,7 +26,6 @@ + #include + #include + #include +-#include + + /* Return nonzero iff ELF header is compatible with the running host. */ + static inline int __attribute__ ((unused)) +@@ -223,9 +222,9 @@ static inline void __attribute__ ((unused)) + dl_platform_init (void) + { + #if IS_IN (rtld) +- /* init_cpu_features has been called early from __libc_start_main in +- static executable. */ +- init_cpu_features (&GLRO(dl_x86_cpu_features)); ++ /* _dl_x86_init_cpu_features is a wrapper for init_cpu_features which ++ has been called early from __libc_start_main in static executable. */ ++ _dl_x86_init_cpu_features (); + #else + if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0') + /* Avoid an empty string which would disturb us. */ diff --git a/glibc-rh1817513-108.patch b/glibc-rh1817513-108.patch new file mode 100755 index 0000000..b6dabc9 --- /dev/null +++ b/glibc-rh1817513-108.patch @@ -0,0 +1,364 @@ +commit de1a9197af7f67a89f929dcadb8ceca8c3846b1c +Author: Florian Weimer +Date: Fri Oct 30 11:57:59 2020 +0100 + + elf: Unify old and new format cache handling code in ld.so + + struct file_entry_new starts with the fields of struct file_entry, + so the code can be shared if the size computation is made dynamic. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-cache.c b/elf/dl-cache.c +index ef37ca18fa9fb6e0..366a051dfcd26132 100644 +--- a/elf/dl-cache.c ++++ b/elf/dl-cache.c +@@ -35,103 +35,141 @@ static struct cache_file *cache; + static struct cache_file_new *cache_new; + static size_t cachesize; + +-/* 1 if cache_data + PTR points into the cache. */ +-#define _dl_cache_verify_ptr(ptr) (ptr < cache_data_size) +- +-#define SEARCH_CACHE(cache) \ +-/* We use binary search since the table is sorted in the cache file. \ +- The first matching entry in the table is returned. \ +- It is important to use the same algorithm as used while generating \ +- the cache file. */ \ +-do \ +- { \ +- left = 0; \ +- right = cache->nlibs - 1; \ +- \ +- while (left <= right) \ +- { \ +- __typeof__ (cache->libs[0].key) key; \ +- \ +- middle = (left + right) / 2; \ +- \ +- key = cache->libs[middle].key; \ +- \ +- /* Make sure string table indices are not bogus before using \ +- them. */ \ +- if (! _dl_cache_verify_ptr (key)) \ +- { \ +- cmpres = 1; \ +- break; \ +- } \ +- \ +- /* Actually compare the entry with the key. */ \ +- cmpres = _dl_cache_libcmp (name, cache_data + key); \ +- if (__glibc_unlikely (cmpres == 0)) \ +- { \ +- /* Found it. LEFT now marks the last entry for which we \ +- know the name is correct. */ \ +- left = middle; \ +- \ +- /* There might be entries with this name before the one we \ +- found. So we have to find the beginning. */ \ +- while (middle > 0) \ +- { \ +- __typeof__ (cache->libs[0].key) key; \ +- \ +- key = cache->libs[middle - 1].key; \ +- /* Make sure string table indices are not bogus before \ +- using them. */ \ +- if (! _dl_cache_verify_ptr (key) \ +- /* Actually compare the entry. */ \ +- || _dl_cache_libcmp (name, cache_data + key) != 0) \ +- break; \ +- --middle; \ +- } \ +- \ +- do \ +- { \ +- int flags; \ +- __typeof__ (cache->libs[0]) *lib = &cache->libs[middle]; \ +- \ +- /* Only perform the name test if necessary. */ \ +- if (middle > left \ +- /* We haven't seen this string so far. Test whether the \ +- index is ok and whether the name matches. Otherwise \ +- we are done. */ \ +- && (! _dl_cache_verify_ptr (lib->key) \ +- || (_dl_cache_libcmp (name, cache_data + lib->key) \ +- != 0))) \ +- break; \ +- \ +- flags = lib->flags; \ +- if (_dl_cache_check_flags (flags) \ +- && _dl_cache_verify_ptr (lib->value)) \ +- { \ +- if (best == NULL || flags == GLRO(dl_correct_cache_id)) \ +- { \ +- HWCAP_CHECK; \ +- best = cache_data + lib->value; \ +- \ +- if (flags == GLRO(dl_correct_cache_id)) \ +- /* We've found an exact match for the shared \ +- object and no general `ELF' release. Stop \ +- searching. */ \ +- break; \ +- } \ +- } \ +- } \ +- while (++middle <= right); \ +- break; \ +- } \ +- \ +- if (cmpres < 0) \ +- left = middle + 1; \ +- else \ +- right = middle - 1; \ +- } \ +- } \ +-while (0) ++/* True if PTR is a valid string table index. */ ++static inline bool ++_dl_cache_verify_ptr (uint32_t ptr, size_t string_table_size) ++{ ++ return ptr < string_table_size; ++} ++ ++/* Compute the address of the element INDEX of the array at LIBS. ++ Conceptually, this is &LIBS[INDEX], but use ENTRY_SIZE for the size ++ of *LIBS. */ ++static inline const struct file_entry * ++_dl_cache_file_entry (const struct file_entry *libs, size_t entry_size, ++ size_t index) ++{ ++ return (const void *) libs + index * entry_size; ++} ++ ++/* We use binary search since the table is sorted in the cache file. ++ The first matching entry in the table is returned. It is important ++ to use the same algorithm as used while generating the cache file. ++ STRING_TABLE_SIZE indicates the maximum offset in STRING_TABLE at ++ which data is mapped; it is not exact. */ ++static const char * ++search_cache (const char *string_table, uint32_t string_table_size, ++ struct file_entry *libs, uint32_t nlibs, uint32_t entry_size, ++ const char *name) ++{ ++ /* Used by the HWCAP check in the struct file_entry_new case. */ ++ uint64_t platform = _dl_string_platform (GLRO (dl_platform)); ++ if (platform != (uint64_t) -1) ++ platform = 1ULL << platform; ++ uint64_t hwcap_mask = GET_HWCAP_MASK (); ++#define _DL_HWCAP_TLS_MASK (1LL << 63) ++ uint64_t hwcap_exclude = ~((GLRO (dl_hwcap) & hwcap_mask) ++ | _DL_HWCAP_PLATFORM | _DL_HWCAP_TLS_MASK); ++ ++ int left = 0; ++ int right = nlibs - 1; ++ const char *best = NULL; ++ ++ while (left <= right) ++ { ++ int middle = (left + right) / 2; ++ uint32_t key = _dl_cache_file_entry (libs, entry_size, middle)->key; ++ ++ /* Make sure string table indices are not bogus before using ++ them. */ ++ if (!_dl_cache_verify_ptr (key, string_table_size)) ++ return NULL; ++ ++ /* Actually compare the entry with the key. */ ++ int cmpres = _dl_cache_libcmp (name, string_table + key); ++ if (__glibc_unlikely (cmpres == 0)) ++ { ++ /* Found it. LEFT now marks the last entry for which we ++ know the name is correct. */ ++ left = middle; ++ ++ /* There might be entries with this name before the one we ++ found. So we have to find the beginning. */ ++ while (middle > 0) ++ { ++ key = _dl_cache_file_entry (libs, entry_size, middle - 1)->key; ++ /* Make sure string table indices are not bogus before ++ using them. */ ++ if (!_dl_cache_verify_ptr (key, string_table_size) ++ /* Actually compare the entry. */ ++ || _dl_cache_libcmp (name, string_table + key) != 0) ++ break; ++ --middle; ++ } ++ ++ do ++ { ++ int flags; ++ const struct file_entry *lib ++ = _dl_cache_file_entry (libs, entry_size, middle); ++ ++ /* Only perform the name test if necessary. */ ++ if (middle > left ++ /* We haven't seen this string so far. Test whether the ++ index is ok and whether the name matches. Otherwise ++ we are done. */ ++ && (! _dl_cache_verify_ptr (lib->key, string_table_size) ++ || (_dl_cache_libcmp (name, string_table + lib->key) ++ != 0))) ++ break; ++ ++ flags = lib->flags; ++ if (_dl_cache_check_flags (flags) ++ && _dl_cache_verify_ptr (lib->value, string_table_size)) ++ { ++ if (best == NULL || flags == GLRO (dl_correct_cache_id)) ++ { ++ if (entry_size >= sizeof (struct file_entry_new)) ++ { ++ /* The entry is large enough to include ++ HWCAP data. Check it. */ ++ struct file_entry_new *libnew ++ = (struct file_entry_new *) lib; ++ ++ if (libnew->hwcap & hwcap_exclude) ++ continue; ++ if (GLRO (dl_osversion) ++ && libnew->osversion > GLRO (dl_osversion)) ++ continue; ++ if (_DL_PLATFORMS_COUNT ++ && (libnew->hwcap & _DL_HWCAP_PLATFORM) != 0 ++ && ((libnew->hwcap & _DL_HWCAP_PLATFORM) ++ != platform)) ++ continue; ++ } ++ ++ best = string_table + lib->value; ++ ++ if (flags == GLRO (dl_correct_cache_id)) ++ /* We've found an exact match for the shared ++ object and no general `ELF' release. Stop ++ searching. */ ++ break; ++ } ++ } ++ } ++ while (++middle <= right); ++ break; ++ } + ++ if (cmpres < 0) ++ left = middle + 1; ++ else ++ right = middle - 1; ++ } ++ ++ return best; ++} + + int + _dl_cache_libcmp (const char *p1, const char *p2) +@@ -182,12 +220,6 @@ _dl_cache_libcmp (const char *p1, const char *p2) + char * + _dl_load_cache_lookup (const char *name) + { +- int left, right, middle; +- int cmpres; +- const char *cache_data; +- uint32_t cache_data_size; +- const char *best; +- + /* Print a message if the loading of libs is traced. */ + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) + _dl_debug_printf (" search cache=%s\n", LD_SO_CACHE); +@@ -247,51 +279,22 @@ _dl_load_cache_lookup (const char *name) + /* Previously looked for the cache file and didn't find it. */ + return NULL; + +- best = NULL; +- ++ const char *best; + if (cache_new != (void *) -1) + { +- uint64_t platform; +- +- /* This is where the strings start. */ +- cache_data = (const char *) cache_new; +- +- /* Now we can compute how large the string table is. */ +- cache_data_size = (const char *) cache + cachesize - cache_data; +- +- platform = _dl_string_platform (GLRO(dl_platform)); +- if (platform != (uint64_t) -1) +- platform = 1ULL << platform; +- +- uint64_t hwcap_mask = GET_HWCAP_MASK(); +- +-#define _DL_HWCAP_TLS_MASK (1LL << 63) +- uint64_t hwcap_exclude = ~((GLRO(dl_hwcap) & hwcap_mask) +- | _DL_HWCAP_PLATFORM | _DL_HWCAP_TLS_MASK); +- +- /* Only accept hwcap if it's for the right platform. */ +-#define HWCAP_CHECK \ +- if (lib->hwcap & hwcap_exclude) \ +- continue; \ +- if (GLRO(dl_osversion) && lib->osversion > GLRO(dl_osversion)) \ +- continue; \ +- if (_DL_PLATFORMS_COUNT \ +- && (lib->hwcap & _DL_HWCAP_PLATFORM) != 0 \ +- && (lib->hwcap & _DL_HWCAP_PLATFORM) != platform) \ +- continue +- SEARCH_CACHE (cache_new); ++ const char *string_table = (const char *) cache_new; ++ best = search_cache (string_table, cachesize, ++ &cache_new->libs[0].entry, cache_new->nlibs, ++ sizeof (cache_new->libs[0]), name); + } + else + { +- /* This is where the strings start. */ +- cache_data = (const char *) &cache->libs[cache->nlibs]; +- +- /* Now we can compute how large the string table is. */ +- cache_data_size = (const char *) cache + cachesize - cache_data; +- +-#undef HWCAP_CHECK +-#define HWCAP_CHECK do {} while (0) +- SEARCH_CACHE (cache); ++ const char *string_table = (const char *) &cache->libs[cache->nlibs]; ++ uint32_t string_table_size ++ = (const char *) cache + cachesize - string_table; ++ best = search_cache (string_table, string_table_size, ++ &cache->libs[0], cache->nlibs, ++ sizeof (cache->libs[0]), name); + } + + /* Print our result if wanted. */ +diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h +index cf43f1cf3b441bc7..3c5730dfe42c7c88 100644 +--- a/sysdeps/generic/dl-cache.h ++++ b/sysdeps/generic/dl-cache.h +@@ -59,8 +59,8 @@ + */ + struct file_entry + { +- int flags; /* This is 1 for an ELF library. */ +- unsigned int key, value; /* String table indices. */ ++ int32_t flags; /* This is 1 for an ELF library. */ ++ uint32_t key, value; /* String table indices. */ + }; + + struct cache_file +@@ -77,8 +77,17 @@ struct cache_file + + struct file_entry_new + { +- int32_t flags; /* This is 1 for an ELF library. */ +- uint32_t key, value; /* String table indices. */ ++ union ++ { ++ /* Fields shared with struct file_entry. */ ++ struct file_entry entry; ++ /* Also expose these fields directly. */ ++ struct ++ { ++ int32_t flags; /* This is 1 for an ELF library. */ ++ uint32_t key, value; /* String table indices. */ ++ }; ++ }; + uint32_t osversion; /* Required OS version. */ + uint64_t hwcap; /* Hwcap entry. */ + }; diff --git a/glibc-rh1817513-109.patch b/glibc-rh1817513-109.patch new file mode 100755 index 0000000..f53c03b --- /dev/null +++ b/glibc-rh1817513-109.patch @@ -0,0 +1,67 @@ +commit 5e598c2bbf938eac0f4045f5143f9dd723646672 +Author: Florian Weimer +Date: Fri Oct 30 18:40:28 2020 +0100 + + elf: In ldconfig, extract the new_sub_entry function from search_dir + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/ldconfig.c b/elf/ldconfig.c +index 7c8fd29387463a8a..be730ceb075f6c1f 100644 +--- a/elf/ldconfig.c ++++ b/elf/ldconfig.c +@@ -328,6 +328,23 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ + "Andreas Jaeger"); + } + ++/* Allocate a new subdirectory with full path PATH under ENTRY, using ++ inode data from *ST. */ ++static struct dir_entry * ++new_sub_entry (const struct dir_entry *entry, const char *path, ++ const struct stat64 *st) ++{ ++ struct dir_entry *new_entry = xmalloc (sizeof (struct dir_entry)); ++ new_entry->from_file = entry->from_file; ++ new_entry->from_line = entry->from_line; ++ new_entry->path = xstrdup (path); ++ new_entry->flag = entry->flag; ++ new_entry->next = NULL; ++ new_entry->ino = st->st_ino; ++ new_entry->dev = st->st_dev; ++ return new_entry; ++} ++ + /* Add a single directory entry. */ + static void + add_single_dir (struct dir_entry *entry, int verbose) +@@ -823,26 +840,17 @@ search_dir (const struct dir_entry *entry) + + if (is_dir && is_hwcap_platform (direntry->d_name)) + { +- /* Handle subdirectory later. */ +- struct dir_entry *new_entry; +- +- new_entry = xmalloc (sizeof (struct dir_entry)); +- new_entry->from_file = entry->from_file; +- new_entry->from_line = entry->from_line; +- new_entry->path = xstrdup (file_name); +- new_entry->flag = entry->flag; +- new_entry->next = NULL; + if (!is_link + && direntry->d_type != DT_UNKNOWN + && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0)) + { + error (0, errno, _("Cannot lstat %s"), file_name); +- free (new_entry->path); +- free (new_entry); + continue; + } +- new_entry->ino = lstat_buf.st_ino; +- new_entry->dev = lstat_buf.st_dev; ++ ++ /* Handle subdirectory later. */ ++ struct dir_entry *new_entry = new_sub_entry (entry, file_name, ++ &lstat_buf); + add_single_dir (new_entry, 0); + continue; + } diff --git a/glibc-rh1817513-11.patch b/glibc-rh1817513-11.patch new file mode 100755 index 0000000..be54271 --- /dev/null +++ b/glibc-rh1817513-11.patch @@ -0,0 +1,79 @@ +commit 7cc65773f04e0f4252428c40dcbb784a39b58cd1 +Author: H.J. Lu +Date: Wed Oct 24 02:19:15 2018 -0700 + + x86: Support RDTSCP for benchtests + + RDTSCP waits until all previous instructions have executed and all + previous loads are globally visible before reading the counter. RDTSC + doesn't wait until all previous instructions have been executed before + reading the counter. All x86 processors since 2010 support RDTSCP + instruction. This patch adds RDTSCP support to benchtests. + + * benchtests/Makefile (CPPFLAGS-nonlib): Add -DUSE_RDTSCP if + USE_RDTSCP is defined. + * sysdeps/x86/hp-timing.h (HP_TIMING_NOW): Use RDTSCP if + USE_RDTSCP is defined. + +diff --git a/benchtests/Makefile b/benchtests/Makefile +index 28d6b0c43f5bd390..bde0caf140e8cf17 100644 +--- a/benchtests/Makefile ++++ b/benchtests/Makefile +@@ -131,6 +131,12 @@ CPPFLAGS-nonlib += -DDURATION=$(BENCH_DURATION) -D_ISOMAC + # HP_TIMING if it is available. + ifdef USE_CLOCK_GETTIME + CPPFLAGS-nonlib += -DUSE_CLOCK_GETTIME ++else ++# On x86 processors, use RDTSCP, instead of RDTSC, to measure performance ++# of functions. All x86 processors since 2010 support RDTSCP instruction. ++ifdef USE_RDTSCP ++CPPFLAGS-nonlib += -DUSE_RDTSCP ++endif + endif + + DETAILED_OPT := +diff --git a/benchtests/README b/benchtests/README +index 4ddff794d136f65f..aaf0b659e2b25627 100644 +--- a/benchtests/README ++++ b/benchtests/README +@@ -34,6 +34,15 @@ the benchmark to use clock_gettime by invoking make as follows: + + Again, one must run `make bench-clean' before changing the measurement method. + ++On x86 processors, RDTSCP instruction provides more precise timing data ++than RDTSC instruction. All x86 processors since 2010 support RDTSCP ++instruction. One can force the benchmark to use RDTSCP by invoking make ++as follows: ++ ++ $ make USE_RDTSCP=1 bench ++ ++One must run `make bench-clean' before changing the measurement method. ++ + Running benchmarks on another target: + ==================================== + +diff --git a/sysdeps/x86/hp-timing.h b/sysdeps/x86/hp-timing.h +index 77a1360748ca4535..0aa6f5e3f83e0d34 100644 +--- a/sysdeps/x86/hp-timing.h ++++ b/sysdeps/x86/hp-timing.h +@@ -40,7 +40,19 @@ typedef unsigned long long int hp_timing_t; + + NB: Use __builtin_ia32_rdtsc directly since including + makes building glibc very slow. */ +-# define HP_TIMING_NOW(Var) ((Var) = __builtin_ia32_rdtsc ()) ++# ifdef USE_RDTSCP ++/* RDTSCP waits until all previous instructions have executed and all ++ previous loads are globally visible before reading the counter. ++ RDTSC doesn't wait until all previous instructions have been executed ++ before reading the counter. */ ++# define HP_TIMING_NOW(Var) \ ++ (__extension__ ({ \ ++ unsigned int __aux; \ ++ (Var) = __builtin_ia32_rdtscp (&__aux); \ ++ })) ++# else ++# define HP_TIMING_NOW(Var) ((Var) = __builtin_ia32_rdtsc ()) ++# endif + + # include + #else diff --git a/glibc-rh1817513-110.patch b/glibc-rh1817513-110.patch new file mode 100755 index 0000000..57d0c15 --- /dev/null +++ b/glibc-rh1817513-110.patch @@ -0,0 +1,22 @@ +commit df5f473ed5ee95e3179fcb239e33e971619626cd +Author: Shuo Wang +Date: Tue Nov 24 16:42:18 2020 -0300 + + elf: Fix uninitialized variable for _dl_write + + Variable ret in elf/dl-write.c is uninitialized, which should get + return value from __writev. + +diff --git a/elf/dl-write.c b/elf/dl-write.c +index 7350aff0035d4fbc..9b741c8a8fe12f6c 100644 +--- a/elf/dl-write.c ++++ b/elf/dl-write.c +@@ -41,7 +41,7 @@ _dl_write (int fd, const void *buffer, size_t length) + else + { + __rtld_lock_lock_recursive (GL(dl_load_lock)); +- __writev (fd, &iov, 1); ++ ret = __writev (fd, &iov, 1); + if (ret < 0) + ret = -errno; + __rtld_lock_unlock_recursive (GL(dl_load_lock)); diff --git a/glibc-rh1817513-111.patch b/glibc-rh1817513-111.patch new file mode 100755 index 0000000..e194ff1 --- /dev/null +++ b/glibc-rh1817513-111.patch @@ -0,0 +1,85 @@ +commit 603ae243f6fe03208a3bb92adecf72403367bd95 +Author: Florian Weimer +Date: Thu Nov 26 16:59:44 2020 +0100 + + support: Add support_copy_file + + Reviewed-by: Adhemerval Zanella + +diff --git a/support/Makefile b/support/Makefile +index 895b83a426369b0c..35b21b19a248ba7f 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -46,6 +46,7 @@ libsupport-routines = \ + support_capture_subprocess \ + support_capture_subprocess_check \ + support_chroot \ ++ support_copy_file \ + support_copy_file_range \ + support_descriptor_supports_holes \ + support_descriptors \ +diff --git a/support/support.h b/support/support.h +index 3af87f85fe1b762d..6f7f804847f67600 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -115,6 +115,11 @@ extern const char support_install_rootsbindir[]; + /* Corresponds to the install's compiled locale directory. */ + extern const char support_complocaledir_prefix[]; + ++/* Copies the file at the path FROM to TO. If TO does not exist, it ++ is created. If TO is a regular file, it is truncated before ++ copying. The file mode is copied, but the permissions are not. */ ++extern void support_copy_file (const char *from, const char *to); ++ + extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *, + size_t, unsigned int); + +diff --git a/support/support_copy_file.c b/support/support_copy_file.c +new file mode 100644 +index 0000000000000000..c93e1e58c81b749d +--- /dev/null ++++ b/support/support_copy_file.c +@@ -0,0 +1,43 @@ ++/* Copy a file from one path to another. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++void ++support_copy_file (const char *from, const char *to) ++{ ++ struct stat64 st; ++ xstat (from, &st); ++ int fd_from = xopen (from, O_RDONLY, 0); ++ mode_t mode = st.st_mode & 0777; ++ int fd_to = xopen (to, O_WRONLY | O_TRUNC | O_CREAT, mode); ++ ssize_t ret = support_copy_file_range (fd_from, NULL, fd_to, NULL, ++ st.st_size, 0); ++ if (ret < 0) ++ FAIL_EXIT1 ("copying from \"%s\" to \"%s\": %m", from, to); ++ if (ret != st.st_size) ++ FAIL_EXIT1 ("copying from \"%s\" to \"%s\": only %zd of %llu bytes copied", ++ from, to, ret, (unsigned long long int) st.st_size); ++ if (fchmod (fd_to, mode) < 0) ++ FAIL_EXIT1 ("fchmod on %s to 0%o: %m", to, mode); ++ xclose (fd_to); ++ xclose (fd_from); ++} diff --git a/glibc-rh1817513-112.patch b/glibc-rh1817513-112.patch new file mode 100755 index 0000000..80f1c38 --- /dev/null +++ b/glibc-rh1817513-112.patch @@ -0,0 +1,152 @@ +commit db07fae8250401adb2b97ab3e53d41da2a6bd767 +Author: Florian Weimer +Date: Thu Nov 26 16:59:44 2020 +0100 + + elf: Introduce enum opt_format in the ldconfig implementation + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/cache.c b/elf/cache.c +index c4cd825c30e00e8e..edcdd4b7cc1a6a0b 100644 +--- a/elf/cache.c ++++ b/elf/cache.c +@@ -321,13 +321,13 @@ save_cache (const char *cache_name) + struct cache_file *file_entries = NULL; + size_t file_entries_size = 0; + +- if (opt_format != 2) ++ if (opt_format != opt_format_new) + { + /* struct cache_file_new is 64-bit aligned on some arches while + only 32-bit aligned on other arches. Duplicate last old + cache entry so that new cache in ld.so.cache can be used by + both. */ +- if (opt_format != 0) ++ if (opt_format != opt_format_old) + cache_entry_old_count = (cache_entry_old_count + 1) & ~1; + + /* And the list of all entries in the old format. */ +@@ -345,7 +345,7 @@ save_cache (const char *cache_name) + struct cache_file_new *file_entries_new = NULL; + size_t file_entries_new_size = 0; + +- if (opt_format != 0) ++ if (opt_format != opt_format_old) + { + /* And the list of all entries in the new format. */ + file_entries_new_size = sizeof (struct cache_file_new) +@@ -370,7 +370,7 @@ save_cache (const char *cache_name) + table, we have to adjust all string indices for this so that + old libc5/glibc 2 dynamic linkers just ignore them. */ + unsigned int str_offset; +- if (opt_format != 0) ++ if (opt_format != opt_format_old) + str_offset = file_entries_new_size; + else + str_offset = 0; +@@ -385,13 +385,13 @@ save_cache (const char *cache_name) + entry = entry->next, ++idx_new) + { + /* First the library. */ +- if (opt_format != 2 && entry->hwcap == 0) ++ if (opt_format != opt_format_new && entry->hwcap == 0) + { + file_entries->libs[idx_old].flags = entry->flags; + /* XXX: Actually we can optimize here and remove duplicates. */ + file_entries->libs[idx_old].key = str_offset + pad; + } +- if (opt_format != 0) ++ if (opt_format != opt_format_old) + { + /* We could subtract file_entries_new_size from str_offset - + not doing so makes the code easier, the string table +@@ -407,9 +407,9 @@ save_cache (const char *cache_name) + str = mempcpy (str, entry->lib, len); + str_offset += len; + /* Then the path. */ +- if (opt_format != 2 && entry->hwcap == 0) ++ if (opt_format != opt_format_new && entry->hwcap == 0) + file_entries->libs[idx_old].value = str_offset + pad; +- if (opt_format != 0) ++ if (opt_format != opt_format_old) + file_entries_new->libs[idx_new].value = str_offset; + len = strlen (entry->path) + 1; + str = mempcpy (str, entry->path, len); +@@ -420,7 +420,7 @@ save_cache (const char *cache_name) + } + + /* Duplicate last old cache entry if needed. */ +- if (opt_format != 2 ++ if (opt_format != opt_format_new + && idx_old < cache_entry_old_count) + file_entries->libs[idx_old] = file_entries->libs[idx_old - 1]; + +@@ -438,16 +438,16 @@ save_cache (const char *cache_name) + temp_name); + + /* Write contents. */ +- if (opt_format != 2) ++ if (opt_format != opt_format_new) + { + if (write (fd, file_entries, file_entries_size) + != (ssize_t) file_entries_size) + error (EXIT_FAILURE, errno, _("Writing of cache data failed")); + } +- if (opt_format != 0) ++ if (opt_format != opt_format_old) + { + /* Align cache. */ +- if (opt_format != 2) ++ if (opt_format != opt_format_new) + { + char zero[pad]; + memset (zero, '\0', pad); +diff --git a/elf/ldconfig.c b/elf/ldconfig.c +index be730ceb075f6c1f..0fa5aef83f9cd86c 100644 +--- a/elf/ldconfig.c ++++ b/elf/ldconfig.c +@@ -100,8 +100,7 @@ static int opt_print_cache; + int opt_verbose; + + /* Format to support. */ +-/* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2. */ +-int opt_format = 2; ++enum opt_format opt_format = opt_format_new; + + /* Build cache. */ + static int opt_build_cache = 1; +@@ -281,11 +280,11 @@ parse_opt (int key, char *arg, struct argp_state *state) + break; + case 'c': + if (strcmp (arg, "old") == 0) +- opt_format = 0; ++ opt_format = opt_format_old; + else if (strcmp (arg, "compat") == 0) +- opt_format = 1; ++ opt_format = opt_format_compat; + else if (strcmp (arg, "new") == 0) +- opt_format = 2; ++ opt_format = opt_format_new; + break; + default: + return ARGP_ERR_UNKNOWN; +diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h +index 6774212110d23eae..b15b142511829436 100644 +--- a/sysdeps/generic/ldconfig.h ++++ b/sysdeps/generic/ldconfig.h +@@ -90,7 +90,14 @@ extern char *chroot_canon (const char *chroot, const char *name); + /* Declared in ldconfig.c. */ + extern int opt_verbose; + +-extern int opt_format; ++enum opt_format ++ { ++ opt_format_old = 0, /* Use struct cache_file. */ ++ opt_format_compat = 1, /* Use both, old format followed by new. */ ++ opt_format_new = 2, /* Use struct cache_file_new. */ ++ }; ++ ++extern enum opt_format opt_format; + + /* Prototypes for a few program-wide used functions. */ + #include diff --git a/glibc-rh1817513-113.patch b/glibc-rh1817513-113.patch new file mode 100755 index 0000000..c37d4df --- /dev/null +++ b/glibc-rh1817513-113.patch @@ -0,0 +1,1111 @@ +commit dad90d528259b669342757c37dedefa8577e2636 +Author: Florian Weimer +Date: Fri Dec 4 09:13:43 2020 +0100 + + elf: Add glibc-hwcaps support for LD_LIBRARY_PATH + + This hacks non-power-set processing into _dl_important_hwcaps. + Once the legacy hwcaps handling goes away, the subdirectory + handling needs to be reworked, but it is premature to do this + while both approaches are still supported. + + ld.so supports two new arguments, --glibc-hwcaps-prepend and + --glibc-hwcaps-mask. Each accepts a colon-separated list of + glibc-hwcaps subdirectory names. The prepend option adds additional + subdirectories that are searched first, in the specified order. The + mask option restricts the automatically selected subdirectories to + those listed in the option argument. For example, on systems where + /usr/lib64 is on the library search path, + --glibc-hwcaps-prepend=valgrind:debug causes the dynamic loader to + search the directories /usr/lib64/glibc-hwcaps/valgrind and + /usr/lib64/glibc-hwcaps/debug just before /usr/lib64 is searched. + + Reviewed-by: Adhemerval Zanella + +Conflicts: + elf/Makefile + (Test backport differences.) + +diff --git a/elf/Makefile b/elf/Makefile +index bc96b8fd65e376cc..f795617780b393ec 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -59,7 +59,8 @@ elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ + # ld.so uses those routines, plus some special stuff for being the program + # interpreter and operating independent of libc. + rtld-routines = rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal \ +- dl-error-minimal dl-conflict dl-hwcaps dl-usage ++ dl-error-minimal dl-conflict dl-hwcaps dl-hwcaps_split dl-hwcaps-subdirs \ ++ dl-usage + all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines) + + CFLAGS-dl-runtime.c += -fexceptions -fasynchronous-unwind-tables +@@ -199,13 +200,14 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \ + tst-audit14 tst-audit15 tst-audit16 \ + tst-tls-ie tst-tls-ie-dlmopen \ +- argv0test ++ argv0test \ ++ tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ + tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \ + tst-ptrguard1 tst-stackguard1 tst-libc_dlvsym \ +- tst-create_format1 tst-tls-surplus ++ tst-create_format1 tst-tls-surplus tst-dl-hwcaps_split + tests-container += tst-pldd + ifeq ($(build-hardcoded-path-in-tests),yes) + tests += tst-dlopen-aout +@@ -318,7 +320,10 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-auditlogmod-1 tst-auditlogmod-2 tst-auditlogmod-3 \ + tst-tls-ie-mod0 tst-tls-ie-mod1 tst-tls-ie-mod2 \ + tst-tls-ie-mod3 tst-tls-ie-mod4 tst-tls-ie-mod5 \ +- tst-tls-ie-mod6 ++ tst-tls-ie-mod6 libmarkermod1-1 libmarkermod1-2 libmarkermod1-3 \ ++ libmarkermod2-1 libmarkermod2-2 \ ++ libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \ ++ libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \ + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +@@ -1732,3 +1737,60 @@ $(objpfx)argv0test.out: tst-rtld-argv0.sh $(objpfx)ld.so \ + '$(test-wrapper-env)' '$(run_program_env)' \ + '$(rpath-link)' 'test-argv0' > $@; \ + $(evaluate-test) ++ ++# A list containing the name of the most likely searched subdirectory ++# of the glibc-hwcaps directory, for each supported architecture (in ++# other words, the oldest hardware level recognized by the ++# glibc-hwcaps mechanism for this architecture). Used to obtain test ++# coverage for some glibc-hwcaps tests for the widest possible range ++# of systems. ++glibc-hwcaps-first-subdirs-for-tests = ++ ++# The test modules are parameterized by preprocessor macros. ++LDFLAGS-libmarkermod1-1.so += -Wl,-soname,libmarkermod1.so ++LDFLAGS-libmarkermod2-1.so += -Wl,-soname,libmarkermod2.so ++LDFLAGS-libmarkermod3-1.so += -Wl,-soname,libmarkermod3.so ++LDFLAGS-libmarkermod4-1.so += -Wl,-soname,libmarkermod4.so ++$(objpfx)libmarkermod%.os : markermodMARKER-VALUE.c ++ $(compile-command.c) \ ++ -DMARKER=marker$(firstword $(subst -, ,$*)) \ ++ -DVALUE=$(lastword $(subst -, ,$*)) ++$(objpfx)libmarkermod1.so: $(objpfx)libmarkermod1-1.so ++ cp $< $@ ++$(objpfx)libmarkermod2.so: $(objpfx)libmarkermod2-1.so ++ cp $< $@ ++$(objpfx)libmarkermod3.so: $(objpfx)libmarkermod3-1.so ++ cp $< $@ ++$(objpfx)libmarkermod4.so: $(objpfx)libmarkermod4-1.so ++ cp $< $@ ++ ++# tst-glibc-hwcaps-prepend checks that --glibc-hwcaps-prepend is ++# preferred over auto-detected subdirectories. ++$(objpfx)tst-glibc-hwcaps-prepend: $(objpfx)libmarkermod1-1.so ++$(objpfx)glibc-hwcaps/prepend-markermod1/libmarkermod1.so: \ ++ $(objpfx)libmarkermod1-2.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/%/libmarkermod1.so: $(objpfx)libmarkermod1-3.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)tst-glibc-hwcaps-prepend.out: \ ++ $(objpfx)tst-glibc-hwcaps-prepend $(objpfx)libmarkermod1.so \ ++ $(patsubst %,$(objpfx)glibc-hwcaps/%/libmarkermod1.so,prepend-markermod1 \ ++ $(glibc-hwcaps-first-subdirs-for-tests)) ++ $(test-wrapper) $(rtld-prefix) \ ++ --glibc-hwcaps-prepend prepend-markermod1 \ ++ $< > $@; \ ++ $(evaluate-test) ++ ++# tst-glibc-hwcaps-mask checks that --glibc-hwcaps-mask can be used to ++# suppress all auto-detected subdirectories. ++$(objpfx)tst-glibc-hwcaps-mask: $(objpfx)libmarkermod1-1.so ++$(objpfx)tst-glibc-hwcaps-mask.out: \ ++ $(objpfx)tst-glibc-hwcaps-mask $(objpfx)libmarkermod1.so \ ++ $(patsubst %,$(objpfx)glibc-hwcaps/%/libmarkermod1.so,\ ++ $(glibc-hwcaps-first-subdirs-for-tests)) ++ $(test-wrapper) $(rtld-prefix) \ ++ --glibc-hwcaps-mask does-not-exist \ ++ $< > $@; \ ++ $(evaluate-test) +diff --git a/elf/dl-hwcaps-subdirs.c b/elf/dl-hwcaps-subdirs.c +new file mode 100644 +index 0000000000000000..60c6d59731ee3188 +--- /dev/null ++++ b/elf/dl-hwcaps-subdirs.c +@@ -0,0 +1,29 @@ ++/* Architecture-specific glibc-hwcaps subdirectories. Generic version. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++ ++/* In the generic version, there are no subdirectories defined. */ ++ ++const char _dl_hwcaps_subdirs[] = ""; ++ ++uint32_t ++_dl_hwcaps_subdirs_active (void) ++{ ++ return 0; ++} +diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c +index 82ee89c36a1eb4ab..e57d0d2d41741021 100644 +--- a/elf/dl-hwcaps.c ++++ b/elf/dl-hwcaps.c +@@ -26,20 +26,97 @@ + #include + #include + ++/* This is the result of counting the substrings in a colon-separated ++ hwcaps string. */ ++struct hwcaps_counts ++{ ++ /* Number of substrings. */ ++ size_t count; ++ ++ /* Sum of the individual substring lengths (without separators or ++ null terminators). */ ++ size_t total_length; ++ ++ /* Maximum length of an individual substring. */ ++ size_t maximum_length; ++}; ++ ++/* Update *COUNTS according to the contents of HWCAPS. Skip over ++ entries whose bit is not set in MASK. */ ++static void ++update_hwcaps_counts (struct hwcaps_counts *counts, const char *hwcaps, ++ uint32_t bitmask, const char *mask) ++{ ++ struct dl_hwcaps_split_masked sp; ++ _dl_hwcaps_split_masked_init (&sp, hwcaps, bitmask, mask); ++ while (_dl_hwcaps_split_masked (&sp)) ++ { ++ ++counts->count; ++ counts->total_length += sp.split.length; ++ if (sp.split.length > counts->maximum_length) ++ counts->maximum_length = sp.split.length; ++ } ++} ++ ++/* State for copy_hwcaps. Must be initialized to point to ++ the storage areas for the array and the strings themselves. */ ++struct copy_hwcaps ++{ ++ struct r_strlenpair *next_pair; ++ char *next_string; ++}; ++ ++/* Copy HWCAPS into the string pairs and strings, advancing *TARGET. ++ Skip over entries whose bit is not set in MASK. */ ++static void ++copy_hwcaps (struct copy_hwcaps *target, const char *hwcaps, ++ uint32_t bitmask, const char *mask) ++{ ++ struct dl_hwcaps_split_masked sp; ++ _dl_hwcaps_split_masked_init (&sp, hwcaps, bitmask, mask); ++ while (_dl_hwcaps_split_masked (&sp)) ++ { ++ target->next_pair->str = target->next_string; ++ char *slash = __mempcpy (__mempcpy (target->next_string, ++ GLIBC_HWCAPS_PREFIX, ++ strlen (GLIBC_HWCAPS_PREFIX)), ++ sp.split.segment, sp.split.length); ++ *slash = '/'; ++ target->next_pair->len ++ = strlen (GLIBC_HWCAPS_PREFIX) + sp.split.length + 1; ++ ++target->next_pair; ++ target->next_string = slash + 1; ++ } ++} ++ + /* Return an array of useful/necessary hardware capability names. */ + const struct r_strlenpair * +-_dl_important_hwcaps (size_t *sz, size_t *max_capstrlen) ++_dl_important_hwcaps (const char *glibc_hwcaps_prepend, ++ const char *glibc_hwcaps_mask, ++ size_t *sz, size_t *max_capstrlen) + { + uint64_t hwcap_mask = GET_HWCAP_MASK(); + /* Determine how many important bits are set. */ + uint64_t masked = GLRO(dl_hwcap) & hwcap_mask; + size_t cnt = GLRO (dl_platform) != NULL; + size_t n, m; +- size_t total; + struct r_strlenpair *result; + struct r_strlenpair *rp; + char *cp; + ++ /* glibc-hwcaps subdirectories. These are exempted from the power ++ set construction below. */ ++ uint32_t hwcaps_subdirs_active = _dl_hwcaps_subdirs_active (); ++ struct hwcaps_counts hwcaps_counts = { 0, }; ++ update_hwcaps_counts (&hwcaps_counts, glibc_hwcaps_prepend, -1, NULL); ++ update_hwcaps_counts (&hwcaps_counts, _dl_hwcaps_subdirs, ++ hwcaps_subdirs_active, glibc_hwcaps_mask); ++ ++ /* Each hwcaps subdirectory has a GLIBC_HWCAPS_PREFIX string prefix ++ and a "/" suffix once stored in the result. */ ++ size_t total = (hwcaps_counts.count * (strlen (GLIBC_HWCAPS_PREFIX) + 1) ++ + hwcaps_counts.total_length); ++ + /* Count the number of bits set in the masked value. */ + for (n = 0; (~((1ULL << n) - 1) & masked) != 0; ++n) + if ((masked & (1ULL << n)) != 0) +@@ -74,10 +151,10 @@ _dl_important_hwcaps (size_t *sz, size_t *max_capstrlen) + + /* Determine the total size of all strings together. */ + if (cnt == 1) +- total = temp[0].len + 1; ++ total += temp[0].len + 1; + else + { +- total = temp[0].len + temp[cnt - 1].len + 2; ++ total += temp[0].len + temp[cnt - 1].len + 2; + if (cnt > 2) + { + total <<= 1; +@@ -94,26 +171,48 @@ _dl_important_hwcaps (size_t *sz, size_t *max_capstrlen) + } + } + +- /* The result structure: we use a very compressed way to store the +- various combinations of capability names. */ +- *sz = 1 << cnt; +- result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total); +- if (result == NULL) ++ *sz = hwcaps_counts.count + (1 << cnt); ++ ++ /* This is the overall result, including both glibc-hwcaps ++ subdirectories and the legacy hwcaps subdirectories using the ++ power set construction. */ ++ struct r_strlenpair *overall_result ++ = malloc (*sz * sizeof (*result) + total); ++ if (overall_result == NULL) + _dl_signal_error (ENOMEM, NULL, NULL, + N_("cannot create capability list")); + ++ /* Fill in the glibc-hwcaps subdirectories. */ ++ { ++ struct copy_hwcaps target; ++ target.next_pair = overall_result; ++ target.next_string = (char *) (overall_result + *sz); ++ copy_hwcaps (&target, glibc_hwcaps_prepend, -1, NULL); ++ copy_hwcaps (&target, _dl_hwcaps_subdirs, ++ hwcaps_subdirs_active, glibc_hwcaps_mask); ++ /* Set up the write target for the power set construction. */ ++ result = target.next_pair; ++ cp = target.next_string; ++ } ++ ++ ++ /* Power set construction begins here. We use a very compressed way ++ to store the various combinations of capability names. */ ++ + if (cnt == 1) + { +- result[0].str = (char *) (result + *sz); ++ result[0].str = cp; + result[0].len = temp[0].len + 1; +- result[1].str = (char *) (result + *sz); ++ result[1].str = cp; + result[1].len = 0; +- cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len); ++ cp = __mempcpy (cp, temp[0].str, temp[0].len); + *cp = '/'; +- *sz = 2; +- *max_capstrlen = result[0].len; ++ if (result[0].len > hwcaps_counts.maximum_length) ++ *max_capstrlen = result[0].len; ++ else ++ *max_capstrlen = hwcaps_counts.maximum_length; + +- return result; ++ return overall_result; + } + + /* Fill in the information. This follows the following scheme +@@ -124,7 +223,7 @@ _dl_important_hwcaps (size_t *sz, size_t *max_capstrlen) + #3: 0, 3 1001 + This allows the representation of all possible combinations of + capability names in the string. First generate the strings. */ +- result[1].str = result[0].str = cp = (char *) (result + *sz); ++ result[1].str = result[0].str = cp; + #define add(idx) \ + cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1); + if (cnt == 2) +@@ -191,7 +290,10 @@ _dl_important_hwcaps (size_t *sz, size_t *max_capstrlen) + while (--n != 0); + + /* The maximum string length. */ +- *max_capstrlen = result[0].len; ++ if (result[0].len > hwcaps_counts.maximum_length) ++ *max_capstrlen = result[0].len; ++ else ++ *max_capstrlen = hwcaps_counts.maximum_length; + +- return result; ++ return overall_result; + } +diff --git a/elf/dl-hwcaps.h b/elf/dl-hwcaps.h +index d69ee11dc27bb5e5..3fcfbceb1a8fc1c8 100644 +--- a/elf/dl-hwcaps.h ++++ b/elf/dl-hwcaps.h +@@ -16,6 +16,11 @@ + License along with the GNU C Library; if not, see + . */ + ++#ifndef _DL_HWCAPS_H ++#define _DL_HWCAPS_H ++ ++#include ++ + #include + + #if HAVE_TUNABLES +@@ -28,3 +33,103 @@ + # define GET_HWCAP_MASK() (0) + # endif + #endif ++ ++#define GLIBC_HWCAPS_SUBDIRECTORY "glibc-hwcaps" ++#define GLIBC_HWCAPS_PREFIX GLIBC_HWCAPS_SUBDIRECTORY "/" ++ ++/* Used by _dl_hwcaps_split below, to split strings at ':' ++ separators. */ ++struct dl_hwcaps_split ++{ ++ const char *segment; /* Start of the current segment. */ ++ size_t length; /* Number of bytes until ':' or NUL. */ ++}; ++ ++/* Prepare *S to parse SUBJECT, for future _dl_hwcaps_split calls. If ++ SUBJECT is NULL, it is treated as the empty string. */ ++static inline void ++_dl_hwcaps_split_init (struct dl_hwcaps_split *s, const char *subject) ++{ ++ s->segment = subject; ++ /* The initial call to _dl_hwcaps_split will not skip anything. */ ++ s->length = 0; ++} ++ ++/* Extract the next non-empty string segment, up to ':' or the null ++ terminator. Return true if one more segment was found, or false if ++ the end of the string was reached. On success, S->segment is the ++ start of the segment found, and S->length is its length. ++ (Typically, S->segment[S->length] is not null.) */ ++_Bool _dl_hwcaps_split (struct dl_hwcaps_split *s) attribute_hidden; ++ ++/* Similar to dl_hwcaps_split, but with bit-based and name-based ++ masking. */ ++struct dl_hwcaps_split_masked ++{ ++ struct dl_hwcaps_split split; ++ ++ /* For used by the iterator implementation. */ ++ const char *mask; ++ uint32_t bitmask; ++}; ++ ++/* Prepare *S for iteration with _dl_hwcaps_split_masked. Only HWCAP ++ names in SUBJECT whose bit is set in BITMASK and whose name is in ++ MASK will be returned. SUBJECT must not contain empty HWCAP names. ++ If MASK is NULL, no name-based masking is applied. Likewise for ++ BITMASK if BITMASK is -1 (infinite number of bits). */ ++static inline void ++_dl_hwcaps_split_masked_init (struct dl_hwcaps_split_masked *s, ++ const char *subject, ++ uint32_t bitmask, const char *mask) ++{ ++ _dl_hwcaps_split_init (&s->split, subject); ++ s->bitmask = bitmask; ++ s->mask = mask; ++} ++ ++/* Like _dl_hwcaps_split, but apply masking. */ ++_Bool _dl_hwcaps_split_masked (struct dl_hwcaps_split_masked *s) ++ attribute_hidden; ++ ++/* Returns true if the colon-separated HWCAP list HWCAPS contains the ++ capability NAME (with length NAME_LENGTH). If HWCAPS is NULL, the ++ function returns true. */ ++_Bool _dl_hwcaps_contains (const char *hwcaps, const char *name, ++ size_t name_length) attribute_hidden; ++ ++/* Colon-separated string of glibc-hwcaps subdirectories, without the ++ "glibc-hwcaps/" prefix. The most preferred subdirectory needs to ++ be listed first. Up to 32 subdirectories are supported, limited by ++ the width of the uint32_t mask. */ ++extern const char _dl_hwcaps_subdirs[] attribute_hidden; ++ ++/* Returns a bitmap of active subdirectories in _dl_hwcaps_subdirs. ++ Bit 0 (the LSB) corresponds to the first substring in ++ _dl_hwcaps_subdirs, bit 1 to the second substring, and so on. ++ There is no direct correspondence between HWCAP bitmasks and this ++ bitmask. */ ++uint32_t _dl_hwcaps_subdirs_active (void) attribute_hidden; ++ ++/* Returns a bitmask that marks the last ACTIVE subdirectories in a ++ _dl_hwcaps_subdirs_active string (containing SUBDIRS directories in ++ total) as active. Intended for use in _dl_hwcaps_subdirs_active ++ implementations (if a contiguous tail of the list in ++ _dl_hwcaps_subdirs is selected). */ ++static inline uint32_t ++_dl_hwcaps_subdirs_build_bitmask (int subdirs, int active) ++{ ++ /* Leading subdirectories that are not active. */ ++ int inactive = subdirs - active; ++ if (inactive == 32) ++ return 0; ++ ++ uint32_t mask; ++ if (subdirs != 32) ++ mask = (1U << subdirs) - 1; ++ else ++ mask = -1; ++ return mask ^ ((1U << inactive) - 1); ++} ++ ++#endif /* _DL_HWCAPS_H */ +diff --git a/elf/dl-hwcaps_split.c b/elf/dl-hwcaps_split.c +new file mode 100644 +index 0000000000000000..95225e9f409ca229 +--- /dev/null ++++ b/elf/dl-hwcaps_split.c +@@ -0,0 +1,77 @@ ++/* Hardware capability support for run-time dynamic loader. String splitting. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++_Bool ++_dl_hwcaps_split (struct dl_hwcaps_split *s) ++{ ++ if (s->segment == NULL) ++ return false; ++ ++ /* Skip over the previous segment. */ ++ s->segment += s->length; ++ ++ /* Consume delimiters. This also avoids returning an empty ++ segment. */ ++ while (*s->segment == ':') ++ ++s->segment; ++ if (*s->segment == '\0') ++ return false; ++ ++ /* This could use strchrnul, but we would have to link the function ++ into ld.so for that. */ ++ const char *colon = strchr (s->segment, ':'); ++ if (colon == NULL) ++ s->length = strlen (s->segment); ++ else ++ s->length = colon - s->segment; ++ return true; ++} ++ ++_Bool ++_dl_hwcaps_split_masked (struct dl_hwcaps_split_masked *s) ++{ ++ while (true) ++ { ++ if (!_dl_hwcaps_split (&s->split)) ++ return false; ++ bool active = s->bitmask & 1; ++ s->bitmask >>= 1; ++ if (active && _dl_hwcaps_contains (s->mask, ++ s->split.segment, s->split.length)) ++ return true; ++ } ++} ++ ++_Bool ++_dl_hwcaps_contains (const char *hwcaps, const char *name, size_t name_length) ++{ ++ if (hwcaps == NULL) ++ return true; ++ ++ struct dl_hwcaps_split split; ++ _dl_hwcaps_split_init (&split, hwcaps); ++ while (_dl_hwcaps_split (&split)) ++ if (split.length == name_length ++ && memcmp (split.segment, name, name_length) == 0) ++ return true; ++ return false; ++} +diff --git a/elf/dl-load.c b/elf/dl-load.c +index d2be21ea7d1545fe..fee08d7816714178 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -682,7 +682,9 @@ cache_rpath (struct link_map *l, + + + void +-_dl_init_paths (const char *llp, const char *source) ++_dl_init_paths (const char *llp, const char *source, ++ const char *glibc_hwcaps_prepend, ++ const char *glibc_hwcaps_mask) + { + size_t idx; + const char *strp; +@@ -697,7 +699,8 @@ _dl_init_paths (const char *llp, const char *source) + + #ifdef SHARED + /* Get the capabilities. */ +- capstr = _dl_important_hwcaps (&ncapstr, &max_capstrlen); ++ capstr = _dl_important_hwcaps (glibc_hwcaps_prepend, glibc_hwcaps_mask, ++ &ncapstr, &max_capstrlen); + #endif + + /* First set up the rest of the default search directory entries. */ +diff --git a/elf/dl-main.h b/elf/dl-main.h +index b51256d3b48230b0..566713a0d10cfdb7 100644 +--- a/elf/dl-main.h ++++ b/elf/dl-main.h +@@ -84,6 +84,14 @@ struct dl_main_state + /* The preload list passed as a command argument. */ + const char *preloadarg; + ++ /* Additional glibc-hwcaps subdirectories to search first. ++ Colon-separated list. */ ++ const char *glibc_hwcaps_prepend; ++ ++ /* Mask for the internal glibc-hwcaps subdirectories. ++ Colon-separated list. */ ++ const char *glibc_hwcaps_mask; ++ + enum rtld_mode mode; + + /* True if any of the debugging options is enabled. */ +@@ -98,7 +106,8 @@ struct dl_main_state + static inline void + call_init_paths (const struct dl_main_state *state) + { +- _dl_init_paths (state->library_path, state->library_path_source); ++ _dl_init_paths (state->library_path, state->library_path_source, ++ state->glibc_hwcaps_prepend, state->glibc_hwcaps_mask); + } + + /* Print ld.so usage information and exit. */ +diff --git a/elf/dl-support.c b/elf/dl-support.c +index fb9672367f8d6abd..34be8e5babfb6af3 100644 +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -315,7 +315,10 @@ _dl_non_dynamic_init (void) + + /* Initialize the data structures for the search paths for shared + objects. */ +- _dl_init_paths (getenv ("LD_LIBRARY_PATH"), "LD_LIBRARY_PATH"); ++ _dl_init_paths (getenv ("LD_LIBRARY_PATH"), "LD_LIBRARY_PATH", ++ /* No glibc-hwcaps selection support in statically ++ linked binaries. */ ++ NULL, NULL); + + /* Remember the last search directory added at startup. */ + _dl_init_all_dirs = GL(dl_all_dirs); +diff --git a/elf/dl-usage.c b/elf/dl-usage.c +index 796ad38b43c2211b..e22a9c39427187d1 100644 +--- a/elf/dl-usage.c ++++ b/elf/dl-usage.c +@@ -83,7 +83,7 @@ print_search_path_for_help (struct dl_main_state *state) + { + if (__rtld_search_dirs.dirs == NULL) + /* The run-time search paths have not yet been initialized. */ +- _dl_init_paths (state->library_path, state->library_path_source); ++ call_init_paths (state); + + _dl_printf ("\nShared library search path:\n"); + +@@ -132,6 +132,67 @@ print_hwcap_1_finish (bool *first) + _dl_printf (")\n"); + } + ++/* Print the header for print_hwcaps_subdirectories. */ ++static void ++print_hwcaps_subdirectories_header (bool *nothing_printed) ++{ ++ if (*nothing_printed) ++ { ++ _dl_printf ("\n\ ++Subdirectories of glibc-hwcaps directories, in priority order:\n"); ++ *nothing_printed = false; ++ } ++} ++ ++/* Print the HWCAP name itself, indented. */ ++static void ++print_hwcaps_subdirectories_name (const struct dl_hwcaps_split *split) ++{ ++ _dl_write (STDOUT_FILENO, " ", 2); ++ _dl_write (STDOUT_FILENO, split->segment, split->length); ++} ++ ++/* Print the list of recognized glibc-hwcaps subdirectories. */ ++static void ++print_hwcaps_subdirectories (const struct dl_main_state *state) ++{ ++ bool nothing_printed = true; ++ struct dl_hwcaps_split split; ++ ++ /* The prepended glibc-hwcaps subdirectories. */ ++ _dl_hwcaps_split_init (&split, state->glibc_hwcaps_prepend); ++ while (_dl_hwcaps_split (&split)) ++ { ++ print_hwcaps_subdirectories_header (¬hing_printed); ++ print_hwcaps_subdirectories_name (&split); ++ bool first = true; ++ print_hwcap_1 (&first, true, "searched"); ++ print_hwcap_1_finish (&first); ++ } ++ ++ /* The built-in glibc-hwcaps subdirectories. Do the filtering ++ manually, so that more precise diagnostics are possible. */ ++ uint32_t mask = _dl_hwcaps_subdirs_active (); ++ _dl_hwcaps_split_init (&split, _dl_hwcaps_subdirs); ++ while (_dl_hwcaps_split (&split)) ++ { ++ print_hwcaps_subdirectories_header (¬hing_printed); ++ print_hwcaps_subdirectories_name (&split); ++ bool first = true; ++ print_hwcap_1 (&first, mask & 1, "supported"); ++ bool listed = _dl_hwcaps_contains (state->glibc_hwcaps_mask, ++ split.segment, split.length); ++ print_hwcap_1 (&first, !listed, "masked"); ++ print_hwcap_1 (&first, (mask & 1) && listed, "searched"); ++ print_hwcap_1_finish (&first); ++ mask >>= 1; ++ } ++ ++ if (nothing_printed) ++ _dl_printf ("\n\ ++No subdirectories of glibc-hwcaps directories are searched.\n"); ++} ++ + /* Write a list of hwcap subdirectories to standard output. See + _dl_important_hwcaps in dl-hwcaps.c. */ + static void +@@ -186,6 +247,10 @@ setting environment variables (which would be inherited by subprocesses).\n\ + --inhibit-cache Do not use " LD_SO_CACHE "\n\ + --library-path PATH use given PATH instead of content of the environment\n\ + variable LD_LIBRARY_PATH\n\ ++ --glibc-hwcaps-prepend LIST\n\ ++ search glibc-hwcaps subdirectories in LIST\n\ ++ --glibc-hwcaps-mask LIST\n\ ++ only search built-in subdirectories if in LIST\n\ + --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\ + in LIST\n\ + --audit LIST use objects named in LIST as auditors\n\ +@@ -198,6 +263,7 @@ This program interpreter self-identifies as: " RTLD "\n\ + ", + argv0); + print_search_path_for_help (state); ++ print_hwcaps_subdirectories (state); + print_legacy_hwcap_directories (); + _exit (EXIT_SUCCESS); + } +diff --git a/elf/markermodMARKER-VALUE.c b/elf/markermodMARKER-VALUE.c +new file mode 100644 +index 0000000000000000..99bdcf71a4e219c6 +--- /dev/null ++++ b/elf/markermodMARKER-VALUE.c +@@ -0,0 +1,29 @@ ++/* Source file template for building shared objects with marker functions. ++ Copyright (C) 2020 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 ++ . */ ++ ++/* MARKER and VALUE must be set on the compiler command line. */ ++ ++#ifndef MARKER ++# error MARKER not defined ++#endif ++ ++int ++MARKER (void) ++{ ++ return VALUE; ++} +diff --git a/elf/rtld.c b/elf/rtld.c +index da1eef108508b95f..fde5a6a4a485207e 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -287,6 +287,8 @@ dl_main_state_init (struct dl_main_state *state) + state->library_path_source = NULL; + state->preloadlist = NULL; + state->preloadarg = NULL; ++ state->glibc_hwcaps_prepend = NULL; ++ state->glibc_hwcaps_mask = NULL; + state->mode = rtld_mode_normal; + state->any_debug = false; + state->version_info = false; +@@ -1238,6 +1240,22 @@ dl_main (const ElfW(Phdr) *phdr, + { + argv0 = _dl_argv[2]; + ++ _dl_skip_args += 2; ++ _dl_argc -= 2; ++ _dl_argv += 2; ++ } ++ else if (strcmp (_dl_argv[1], "--glibc-hwcaps-prepend") == 0 ++ && _dl_argc > 2) ++ { ++ state.glibc_hwcaps_prepend = _dl_argv[2]; ++ _dl_skip_args += 2; ++ _dl_argc -= 2; ++ _dl_argv += 2; ++ } ++ else if (strcmp (_dl_argv[1], "--glibc-hwcaps-mask") == 0 ++ && _dl_argc > 2) ++ { ++ state.glibc_hwcaps_mask = _dl_argv[2]; + _dl_skip_args += 2; + _dl_argc -= 2; + _dl_argv += 2; +diff --git a/elf/tst-dl-hwcaps_split.c b/elf/tst-dl-hwcaps_split.c +new file mode 100644 +index 0000000000000000..364159427074bd1c +--- /dev/null ++++ b/elf/tst-dl-hwcaps_split.c +@@ -0,0 +1,148 @@ ++/* Unit tests for dl-hwcaps.c. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++static void ++check_split_masked (const char *input, int32_t bitmask, const char *mask, ++ const char *expected[], size_t expected_length) ++{ ++ struct dl_hwcaps_split_masked split; ++ _dl_hwcaps_split_masked_init (&split, input, bitmask, mask); ++ size_t index = 0; ++ while (_dl_hwcaps_split_masked (&split)) ++ { ++ TEST_VERIFY_EXIT (index < expected_length); ++ TEST_COMPARE_BLOB (expected[index], strlen (expected[index]), ++ split.split.segment, split.split.length); ++ ++index; ++ } ++ TEST_COMPARE (index, expected_length); ++} ++ ++static void ++check_split (const char *input, ++ const char *expected[], size_t expected_length) ++{ ++ struct dl_hwcaps_split split; ++ _dl_hwcaps_split_init (&split, input); ++ size_t index = 0; ++ while (_dl_hwcaps_split (&split)) ++ { ++ TEST_VERIFY_EXIT (index < expected_length); ++ TEST_COMPARE_BLOB (expected[index], strlen (expected[index]), ++ split.segment, split.length); ++ ++index; ++ } ++ TEST_COMPARE (index, expected_length); ++ ++ /* Reuse the test cases with masking that does not actually remove ++ anything. */ ++ check_split_masked (input, -1, NULL, expected, expected_length); ++ check_split_masked (input, -1, input, expected, expected_length); ++} ++ ++static int ++do_test (void) ++{ ++ /* Splitting tests, without masking. */ ++ check_split (NULL, NULL, 0); ++ check_split ("", NULL, 0); ++ check_split (":", NULL, 0); ++ check_split ("::", NULL, 0); ++ ++ { ++ const char *expected[] = { "first" }; ++ check_split ("first", expected, array_length (expected)); ++ check_split (":first", expected, array_length (expected)); ++ check_split ("first:", expected, array_length (expected)); ++ check_split (":first:", expected, array_length (expected)); ++ } ++ ++ { ++ const char *expected[] = { "first", "second" }; ++ check_split ("first:second", expected, array_length (expected)); ++ check_split ("first::second", expected, array_length (expected)); ++ check_split (":first:second", expected, array_length (expected)); ++ check_split ("first:second:", expected, array_length (expected)); ++ check_split (":first:second:", expected, array_length (expected)); ++ } ++ ++ /* Splitting tests with masking. */ ++ { ++ const char *expected[] = { "first" }; ++ check_split_masked ("first", 3, "first:second", ++ expected, array_length (expected)); ++ check_split_masked ("first:second", 3, "first:", ++ expected, array_length (expected)); ++ check_split_masked ("first:second", 1, NULL, ++ expected, array_length (expected)); ++ } ++ { ++ const char *expected[] = { "second" }; ++ check_split_masked ("first:second", 3, "second", ++ expected, array_length (expected)); ++ check_split_masked ("first:second:third", -1, "second:", ++ expected, array_length (expected)); ++ check_split_masked ("first:second", 2, NULL, ++ expected, array_length (expected)); ++ check_split_masked ("first:second:third", 2, "first:second", ++ expected, array_length (expected)); ++ } ++ ++ /* Tests for _dl_hwcaps_contains. */ ++ TEST_VERIFY (_dl_hwcaps_contains (NULL, "first", strlen ("first"))); ++ TEST_VERIFY (_dl_hwcaps_contains (NULL, "", 0)); ++ TEST_VERIFY (! _dl_hwcaps_contains ("", "first", strlen ("first"))); ++ TEST_VERIFY (! _dl_hwcaps_contains ("firs", "first", strlen ("first"))); ++ TEST_VERIFY (_dl_hwcaps_contains ("firs", "first", strlen ("first") - 1)); ++ for (int i = 0; i < strlen ("first"); ++i) ++ TEST_VERIFY (! _dl_hwcaps_contains ("first", "first", i)); ++ TEST_VERIFY (_dl_hwcaps_contains ("first", "first", strlen ("first"))); ++ TEST_VERIFY (_dl_hwcaps_contains ("first:", "first", strlen ("first"))); ++ TEST_VERIFY (_dl_hwcaps_contains ("first:second", ++ "first", strlen ("first"))); ++ TEST_VERIFY (_dl_hwcaps_contains (":first:second", "first", ++ strlen ("first"))); ++ TEST_VERIFY (_dl_hwcaps_contains ("first:second", "second", ++ strlen ("second"))); ++ TEST_VERIFY (_dl_hwcaps_contains ("first:second:", "second", ++ strlen ("second"))); ++ TEST_VERIFY (_dl_hwcaps_contains ("first::second:", "second", ++ strlen ("second"))); ++ TEST_VERIFY (_dl_hwcaps_contains ("first:second::", "second", ++ strlen ("second"))); ++ for (int i = 0; i < strlen ("second"); ++i) ++ { ++ TEST_VERIFY (!_dl_hwcaps_contains ("first:second", "second", i)); ++ TEST_VERIFY (!_dl_hwcaps_contains ("first:second:", "second", i)); ++ TEST_VERIFY (!_dl_hwcaps_contains ("first:second::", "second", i)); ++ TEST_VERIFY (!_dl_hwcaps_contains ("first::second", "second", i)); ++ } ++ ++ return 0; ++} ++ ++#include ++ ++/* Rebuild the sources here because the object file is built for ++ inclusion into the dynamic loader. */ ++#include "dl-hwcaps_split.c" +diff --git a/elf/tst-glibc-hwcaps-mask.c b/elf/tst-glibc-hwcaps-mask.c +new file mode 100644 +index 0000000000000000..27b09b358caf7853 +--- /dev/null ++++ b/elf/tst-glibc-hwcaps-mask.c +@@ -0,0 +1,31 @@ ++/* Test that --glibc-hwcaps-mask works. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++ ++extern int marker1 (void); ++ ++static int ++do_test (void) ++{ ++ /* The marker1 function in elf/markermod1.so returns 1. */ ++ TEST_COMPARE (marker1 (), 1); ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-glibc-hwcaps-prepend.c b/elf/tst-glibc-hwcaps-prepend.c +new file mode 100644 +index 0000000000000000..57d7319f1484ca4b +--- /dev/null ++++ b/elf/tst-glibc-hwcaps-prepend.c +@@ -0,0 +1,32 @@ ++/* Test that --glibc-hwcaps-prepend works. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++ ++extern int marker1 (void); ++ ++static int ++do_test (void) ++{ ++ /* The marker1 function in ++ glibc-hwcaps/prepend-markermod1/markermod1.so returns 2. */ ++ TEST_COMPARE (marker1 (), 2); ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-glibc-hwcaps.c b/elf/tst-glibc-hwcaps.c +new file mode 100644 +index 0000000000000000..28f47cf8914a1f2a +--- /dev/null ++++ b/elf/tst-glibc-hwcaps.c +@@ -0,0 +1,28 @@ ++/* Stub test for glibc-hwcaps. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++ ++static int ++do_test (void) ++{ ++ puts ("info: generic tst-glibc-hwcaps (tests nothing)"); ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 2c9fdeb286bdaadf..77923499d3de4366 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1045,8 +1045,13 @@ extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) + attribute_hidden; + + /* Initialize the basic data structure for the search paths. SOURCE +- is either "LD_LIBRARY_PATH" or "--library-path". */ +-extern void _dl_init_paths (const char *library_path, const char *source) ++ is either "LD_LIBRARY_PATH" or "--library-path". ++ GLIBC_HWCAPS_PREPEND adds additional glibc-hwcaps subdirectories to ++ search. GLIBC_HWCAPS_MASK is used to filter the built-in ++ subdirectories if not NULL. */ ++extern void _dl_init_paths (const char *library_path, const char *source, ++ const char *glibc_hwcaps_prepend, ++ const char *glibc_hwcaps_mask) + attribute_hidden; + + /* Gather the information needed to install the profiling tables and start +@@ -1070,9 +1075,14 @@ extern void _dl_show_auxv (void) attribute_hidden; + extern char *_dl_next_ld_env_entry (char ***position) attribute_hidden; + + /* Return an array with the names of the important hardware +- capabilities. The length of the array is written to *SZ, and the +- maximum of all strings length is written to *MAX_CAPSTRLEN. */ +-const struct r_strlenpair *_dl_important_hwcaps (size_t *sz, ++ capabilities. PREPEND is a colon-separated list of glibc-hwcaps ++ directories to search first. MASK is a colon-separated list used ++ to filter the built-in glibc-hwcaps subdirectories. The length of ++ the array is written to *SZ, and the maximum of all strings length ++ is written to *MAX_CAPSTRLEN. */ ++const struct r_strlenpair *_dl_important_hwcaps (const char *prepend, ++ const char *mask, ++ size_t *sz, + size_t *max_capstrlen) + attribute_hidden; + diff --git a/glibc-rh1817513-114.patch b/glibc-rh1817513-114.patch new file mode 100755 index 0000000..26cd1b6 --- /dev/null +++ b/glibc-rh1817513-114.patch @@ -0,0 +1,190 @@ +commit 84ba719b260551918965d0a433914de683087645 +Author: Florian Weimer +Date: Fri Dec 4 09:13:43 2020 +0100 + + elf: Add endianness markup to ld.so.cache (bug 27008) + + Use a reserved byte in the new format cache header to indicate whether + the file is in little endian or big endian format. Eventually, this + information could be used to provide a unified cache for qemu-user + and similiar scenarios. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/cache.c b/elf/cache.c +index edcdd4b7cc1a6a0b..28e4889d006d2f0b 100644 +--- a/elf/cache.c ++++ b/elf/cache.c +@@ -152,6 +152,14 @@ print_entry (const char *lib, int flag, unsigned int osversion, + printf (") => %s\n", key); + } + ++/* Print an error and exit if the new-file cache is internally ++ inconsistent. */ ++static void ++check_new_cache (struct cache_file_new *cache) ++{ ++ if (! cache_file_new_matches_endian (cache)) ++ error (EXIT_FAILURE, 0, _("Cache file has wrong endianness.\n")); ++} + + /* Print the whole cache file, if a file contains the new cache format + hidden in the old one, print the contents of the new format. */ +@@ -193,6 +201,7 @@ print_cache (const char *cache_name) + || memcmp (cache_new->version, CACHE_VERSION, + sizeof CACHE_VERSION - 1)) + error (EXIT_FAILURE, 0, _("File is not a cache file.\n")); ++ check_new_cache (cache_new); + format = 1; + /* This is where the strings start. */ + cache_data = (const char *) cache_new; +@@ -222,6 +231,7 @@ print_cache (const char *cache_name) + && memcmp (cache_new->version, CACHE_VERSION, + sizeof CACHE_VERSION - 1) == 0) + { ++ check_new_cache (cache_new); + cache_data = (const char *) cache_new; + format = 1; + } +@@ -361,6 +371,7 @@ save_cache (const char *cache_name) + + file_entries_new->nlibs = cache_entry_count; + file_entries_new->len_strings = total_strlen; ++ file_entries_new->flags = cache_file_new_flags_endian_current; + } + + /* Pad for alignment of cache_file_new. */ +diff --git a/elf/dl-cache.c b/elf/dl-cache.c +index 366a051dfcd26132..de063faa8b2c88ae 100644 +--- a/elf/dl-cache.c ++++ b/elf/dl-cache.c +@@ -242,6 +242,11 @@ _dl_load_cache_lookup (const char *name) + && ((cachesize - sizeof *cache_new) / sizeof (struct file_entry_new) + >= ((struct cache_file_new *) file)->nlibs)) + { ++ if (! cache_file_new_matches_endian (file)) ++ { ++ __munmap (file, cachesize); ++ file = (void *) -1; ++ } + cache_new = file; + cache = file; + } +@@ -263,7 +268,20 @@ _dl_load_cache_lookup (const char *name) + if (cachesize < (offset + sizeof (struct cache_file_new)) + || memcmp (cache_new->magic, CACHEMAGIC_VERSION_NEW, + sizeof CACHEMAGIC_VERSION_NEW - 1) != 0) +- cache_new = (void *) -1; ++ cache_new = (void *) -1; ++ else ++ { ++ if (! cache_file_new_matches_endian (cache_new)) ++ { ++ /* The old-format part of the cache is bogus as well ++ if the endianness does not match. (But it is ++ unclear how the new header can be located if the ++ endianess does not match.) */ ++ cache = (void *) -1; ++ cache_new = (void *) -1; ++ __munmap (file, cachesize); ++ } ++ } + } + else + { +diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h +index 3c5730dfe42c7c88..6ecfd6da0e59329c 100644 +--- a/sysdeps/generic/dl-cache.h ++++ b/sysdeps/generic/dl-cache.h +@@ -16,6 +16,11 @@ + License along with the GNU C Library; if not, see + . */ + ++#ifndef _DL_CACHE_H ++#define _DL_CACHE_H ++ ++#include ++#include + #include + + #ifndef _DL_CACHE_DEFAULT_ID +@@ -92,17 +97,72 @@ struct file_entry_new + uint64_t hwcap; /* Hwcap entry. */ + }; + ++/* See flags member of struct cache_file_new below. */ ++enum ++ { ++ /* No endianness information available. An old ldconfig version ++ without endianness support wrote the file. */ ++ cache_file_new_flags_endian_unset = 0, ++ ++ /* Cache is invalid and should be ignored. */ ++ cache_file_new_flags_endian_invalid = 1, ++ ++ /* Cache format is little endian. */ ++ cache_file_new_flags_endian_little = 2, ++ ++ /* Cache format is big endian. */ ++ cache_file_new_flags_endian_big = 3, ++ ++ /* Bit mask to extract the cache_file_new_flags_endian_* ++ values. */ ++ cache_file_new_flags_endian_mask = 3, ++ ++ /* Expected value of the endian bits in the flags member for the ++ current architecture. */ ++ cache_file_new_flags_endian_current ++ = (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ++ ? cache_file_new_flags_endian_little ++ : cache_file_new_flags_endian_big), ++ }; ++ + struct cache_file_new + { + char magic[sizeof CACHEMAGIC_NEW - 1]; + char version[sizeof CACHE_VERSION - 1]; + uint32_t nlibs; /* Number of entries. */ + uint32_t len_strings; /* Size of string table. */ +- uint32_t unused[5]; /* Leave space for future extensions ++ ++ /* flags & cache_file_new_flags_endian_mask is one of the values ++ cache_file_new_flags_endian_unset, cache_file_new_flags_endian_invalid, ++ cache_file_new_flags_endian_little, cache_file_new_flags_endian_big. ++ ++ The remaining bits are unused and should be generated as zero and ++ ignored by readers. */ ++ uint8_t flags; ++ ++ uint8_t padding_unsed[3]; /* Not used, for future extensions. */ ++ ++ uint32_t unused[4]; /* Leave space for future extensions + and align to 8 byte boundary. */ + struct file_entry_new libs[0]; /* Entries describing libraries. */ + /* After this the string table of size len_strings is found. */ + }; ++_Static_assert (sizeof (struct cache_file_new) == 48, ++ "size of struct cache_file_new"); ++ ++/* Returns false if *CACHE has the wrong endianness for this ++ architecture, and true if the endianness matches (or is ++ unknown). */ ++static inline bool ++cache_file_new_matches_endian (const struct cache_file_new *cache) ++{ ++ /* A zero value for cache->flags means that no endianness ++ information is available. */ ++ return cache->flags == 0 ++ || ((cache->flags & cache_file_new_flags_endian_big) ++ == cache_file_new_flags_endian_current); ++} ++ + + /* Used to align cache_file_new. */ + #define ALIGN_CACHE(addr) \ +@@ -110,3 +170,5 @@ struct cache_file_new + & (~(__alignof__ (struct cache_file_new) - 1))) + + extern int _dl_cache_libcmp (const char *p1, const char *p2) attribute_hidden; ++ ++#endif /* _DL_CACHE_H */ diff --git a/glibc-rh1817513-115.patch b/glibc-rh1817513-115.patch new file mode 100755 index 0000000..3b0db56 --- /dev/null +++ b/glibc-rh1817513-115.patch @@ -0,0 +1,312 @@ +commit dfb3f101c5ef23adf60d389058a2b33e23303d04 +Author: Florian Weimer +Date: Fri Dec 4 09:13:43 2020 +0100 + + elf: Add extension mechanism to ld.so.cache + + A previously unused new-format header field is used to record + the address of an extension directory. + + This change adds a demo extension which records the version of + ldconfig which builds a file. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/cache.c b/elf/cache.c +index 28e4889d006d2f0b..5a8f1ad70cc3fead 100644 +--- a/elf/cache.c ++++ b/elf/cache.c +@@ -15,6 +15,7 @@ + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + ++#include + #include + #include + #include +@@ -33,6 +34,7 @@ + + #include + #include ++#include + + struct cache_entry + { +@@ -161,6 +163,21 @@ check_new_cache (struct cache_file_new *cache) + error (EXIT_FAILURE, 0, _("Cache file has wrong endianness.\n")); + } + ++/* Print the extension information at the cache at start address ++ FILE_BASE, of length FILE_SIZE bytes. The new-format cache header ++ is at CACHE, and the file name for diagnostics is CACHE_NAME. */ ++static void ++print_extensions (struct cache_extension_all_loaded *ext) ++{ ++ if (ext->sections[cache_extension_tag_generator].base != NULL) ++ { ++ fputs (_("Cache generated by: "), stdout); ++ fwrite (ext->sections[cache_extension_tag_generator].base, 1, ++ ext->sections[cache_extension_tag_generator].size, stdout); ++ putchar ('\n'); ++ } ++} ++ + /* Print the whole cache file, if a file contains the new cache format + hidden in the old one, print the contents of the new format. */ + void +@@ -250,6 +267,11 @@ print_cache (const char *cache_name) + } + else if (format == 1) + { ++ struct cache_extension_all_loaded ext; ++ if (!cache_extension_load (cache_new, cache, cache_size, &ext)) ++ error (EXIT_FAILURE, 0, ++ _("Malformed extension data in cache file %s\n"), cache_name); ++ + printf (_("%d libs found in cache `%s'\n"), + cache_new->nlibs, cache_name); + +@@ -260,6 +282,7 @@ print_cache (const char *cache_name) + cache_new->libs[i].osversion, + cache_new->libs[i].hwcap, + cache_data + cache_new->libs[i].value); ++ print_extensions (&ext); + } + /* Cleanup. */ + munmap (cache, cache_size); +@@ -301,6 +324,45 @@ compare (const struct cache_entry *e1, const struct cache_entry *e2) + return res; + } + ++/* Size of the cache extension directory. All tags are assumed to be ++ present. */ ++enum ++ { ++ cache_extension_size = (offsetof (struct cache_extension, sections) ++ + (cache_extension_count ++ * sizeof (struct cache_extension_section))) ++ }; ++ ++/* Write the cache extensions to FD. The extension directory is ++ assumed to be located at CACHE_EXTENSION_OFFSET. */ ++static void ++write_extensions (int fd, uint32_t cache_extension_offset) ++{ ++ assert ((cache_extension_offset % 4) == 0); ++ ++ struct cache_extension *ext = xmalloc (cache_extension_size); ++ ext->magic = cache_extension_magic; ++ ext->count = cache_extension_count; ++ ++ for (int i = 0; i < cache_extension_count; ++i) ++ { ++ ext->sections[i].tag = i; ++ ext->sections[i].flags = 0; ++ } ++ ++ const char *generator ++ = "ldconfig " PKGVERSION RELEASE " release version " VERSION; ++ ext->sections[cache_extension_tag_generator].offset ++ = cache_extension_offset + cache_extension_size; ++ ext->sections[cache_extension_tag_generator].size = strlen (generator); ++ ++ if (write (fd, ext, cache_extension_size) != cache_extension_size ++ || write (fd, generator, strlen (generator)) != strlen (generator)) ++ error (EXIT_FAILURE, errno, _("Writing of cache extension data failed")); ++ ++ free (ext); ++} ++ + /* Save the contents of the cache. */ + void + save_cache (const char *cache_name) +@@ -435,6 +497,25 @@ save_cache (const char *cache_name) + && idx_old < cache_entry_old_count) + file_entries->libs[idx_old] = file_entries->libs[idx_old - 1]; + ++ /* Compute the location of the extension directory. This ++ implementation puts the directory after the string table. The ++ size computation matches the write calls below. The extension ++ directory does not exist with format 0, so the value does not ++ matter. */ ++ uint32_t extension_offset = 0; ++ if (opt_format != opt_format_new) ++ extension_offset += file_entries_size; ++ if (opt_format != opt_format_old) ++ { ++ if (opt_format != opt_format_new) ++ extension_offset += pad; ++ extension_offset += file_entries_new_size; ++ } ++ extension_offset += total_strlen; ++ extension_offset = roundup (extension_offset, 4); /* Provide alignment. */ ++ if (opt_format != opt_format_old) ++ file_entries_new->extension_offset = extension_offset; ++ + /* Write out the cache. */ + + /* Write cache first to a temporary file and rename it later. */ +@@ -473,6 +554,14 @@ save_cache (const char *cache_name) + if (write (fd, strings, total_strlen) != (ssize_t) total_strlen) + error (EXIT_FAILURE, errno, _("Writing of cache data failed")); + ++ if (opt_format != opt_format_old) ++ { ++ /* Align file position to 4. */ ++ off64_t old_offset = lseek64 (fd, extension_offset, SEEK_SET); ++ assert ((unsigned long long int) (extension_offset - old_offset) < 4); ++ write_extensions (fd, extension_offset); ++ } ++ + /* Make sure user can always read cache file */ + if (chmod (temp_name, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR)) + error (EXIT_FAILURE, errno, +diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h +index 6ecfd6da0e59329c..259e843724531630 100644 +--- a/sysdeps/generic/dl-cache.h ++++ b/sysdeps/generic/dl-cache.h +@@ -21,7 +21,9 @@ + + #include + #include ++#include + #include ++#include + + #ifndef _DL_CACHE_DEFAULT_ID + # define _DL_CACHE_DEFAULT_ID 3 +@@ -142,7 +144,11 @@ struct cache_file_new + + uint8_t padding_unsed[3]; /* Not used, for future extensions. */ + +- uint32_t unused[4]; /* Leave space for future extensions ++ /* File offset of the extension directory. See struct ++ cache_extension below. Must be a multiple of four. */ ++ uint32_t extension_offset; ++ ++ uint32_t unused[3]; /* Leave space for future extensions + and align to 8 byte boundary. */ + struct file_entry_new libs[0]; /* Entries describing libraries. */ + /* After this the string table of size len_strings is found. */ +@@ -164,6 +170,121 @@ cache_file_new_matches_endian (const struct cache_file_new *cache) + } + + ++/* Randomly chosen magic value, which allows for additional ++ consistency verification. */ ++enum { cache_extension_magic = (uint32_t) -358342284 }; ++ ++/* Tag values for different kinds of extension sections. Similar to ++ SHT_* constants. */ ++enum cache_extension_tag ++ { ++ /* Array of bytes containing the glibc version that generated this ++ cache file. */ ++ cache_extension_tag_generator, ++ ++ /* Total number of known cache extension tags. */ ++ cache_extension_count ++ }; ++ ++/* Element in the array following struct cache_extension. Similar to ++ an ELF section header. */ ++struct cache_extension_section ++{ ++ /* Type of the extension section. A enum cache_extension_tag value. */ ++ uint32_t tag; ++ ++ /* Extension-specific flags. Currently generated as zero. */ ++ uint32_t flags; ++ ++ /* Offset from the start of the file for the data in this extension ++ section. Specific extensions can have alignment constraints. */ ++ uint32_t offset; ++ ++ /* Length in bytes of the extension data. Specific extensions may ++ have size requirements. */ ++ uint32_t size; ++}; ++ ++/* The extension directory in the cache. An array of struct ++ cache_extension_section entries. */ ++struct cache_extension ++{ ++ uint32_t magic; /* Always cache_extension_magic. */ ++ uint32_t count; /* Number of following entries. */ ++ ++ /* count section descriptors of type struct cache_extension_section ++ follow. */ ++ struct cache_extension_section sections[]; ++}; ++ ++/* A relocated version of struct cache_extension_section. */ ++struct cache_extension_loaded ++{ ++ /* Address and size of this extension section. base is NULL if the ++ section is missing from the file. */ ++ const void *base; ++ size_t size; ++ ++ /* Flags from struct cache_extension_section. */ ++ uint32_t flags; ++}; ++ ++/* All supported extension sections, relocated. Filled in by ++ cache_extension_load below. */ ++struct cache_extension_all_loaded ++{ ++ struct cache_extension_loaded sections[cache_extension_count]; ++}; ++ ++static bool __attribute__ ((unused)) ++cache_extension_load (const struct cache_file_new *cache, ++ const void *file_base, size_t file_size, ++ struct cache_extension_all_loaded *loaded) ++{ ++ memset (loaded, 0, sizeof (*loaded)); ++ if (cache->extension_offset == 0) ++ /* No extensions present. This is not a format error. */ ++ return true; ++ if ((cache->extension_offset % 4) != 0) ++ /* Extension offset is misaligned. */ ++ return false; ++ size_t size_tmp; ++ if (__builtin_add_overflow (cache->extension_offset, ++ sizeof (struct cache_extension), &size_tmp) ++ || size_tmp > file_size) ++ /* Extension extends beyond the end of the file. */ ++ return false; ++ const struct cache_extension *ext = file_base + cache->extension_offset; ++ if (ext->magic != cache_extension_magic) ++ return false; ++ if (__builtin_mul_overflow (ext->count, ++ sizeof (struct cache_extension_section), ++ &size_tmp) ++ || __builtin_add_overflow (cache->extension_offset ++ + sizeof (struct cache_extension), size_tmp, ++ &size_tmp) ++ || size_tmp > file_size) ++ /* Extension array extends beyond the end of the file. */ ++ return false; ++ for (uint32_t i = 0; i < ext->count; ++i) ++ { ++ if (__builtin_add_overflow (ext->sections[i].offset, ++ ext->sections[i].size, &size_tmp) ++ || size_tmp > file_size) ++ /* Extension data extends beyond the end of the file. */ ++ return false; ++ ++ uint32_t tag = ext->sections[i].tag; ++ if (tag >= cache_extension_count) ++ /* Tag is out of range and unrecognized. */ ++ continue; ++ loaded->sections[tag].base = file_base + ext->sections[i].offset; ++ loaded->sections[tag].size = ext->sections[i].size; ++ loaded->sections[tag].flags = ext->sections[i].flags; ++ } ++ return true; ++} ++ + /* Used to align cache_file_new. */ + #define ALIGN_CACHE(addr) \ + (((addr) + __alignof__ (struct cache_file_new) -1) \ diff --git a/glibc-rh1817513-116.patch b/glibc-rh1817513-116.patch new file mode 100755 index 0000000..e5f927f --- /dev/null +++ b/glibc-rh1817513-116.patch @@ -0,0 +1,544 @@ +commit 785969a047ad2f23f758901c6816422573544453 +Author: Florian Weimer +Date: Fri Dec 4 09:13:43 2020 +0100 + + elf: Implement a string table for ldconfig, with tail merging + + This will be used in ldconfig to reduce the ld.so.cache size slightly. + + Tail merging is an optimization where a pointer points into another + string if the first string is a suffix of the second string. + + The hash function FNV-1a was chosen because it is simple and achieves + good dispersion even for short strings (so that the hash table bucket + count can be a power of two). It is clearly superior to the hsearch + hash and the ELF hash in this regard. + + The hash table uses chaining for collision resolution. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/Makefile b/elf/Makefile +index f795617780b393ec..abb3e9d1179ef5cd 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -163,7 +163,7 @@ tests-container = \ + + tests := tst-tls9 tst-leaks1 \ + tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \ +- tst-auxv ++ tst-auxv tst-stringtable + tests-internal := tst-tls1 tst-tls2 $(tests-static-internal) + tests-static := $(tests-static-normal) $(tests-static-internal) + +diff --git a/elf/stringtable.c b/elf/stringtable.c +new file mode 100644 +index 0000000000000000..099347d73ee70b8f +--- /dev/null ++++ b/elf/stringtable.c +@@ -0,0 +1,209 @@ ++/* String tables for ld.so.cache construction. Implementation. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published ++ by the Free Software Foundation; version 2 of the License, or ++ (at your option) any later version. ++ ++ This program 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 General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, see . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void ++stringtable_init (struct stringtable *table) ++{ ++ table->count = 0; ++ ++ /* This needs to be a power of two. 128 is sufficient to keep track ++ of 42 DSOs without resizing (assuming two strings per DSOs). ++ glibc itself comes with more than 20 DSOs, so 64 would likely to ++ be too small. */ ++ table->allocated = 128; ++ ++ table->entries = xcalloc (table->allocated, sizeof (table->entries[0])); ++} ++ ++/* 32-bit FNV-1a hash function. */ ++static uint32_t ++fnv1a (const char *string, size_t length) ++{ ++ const unsigned char *p = (const unsigned char *) string; ++ uint32_t hash = 2166136261U; ++ for (size_t i = 0; i < length; ++i) ++ { ++ hash ^= p[i]; ++ hash *= 16777619U; ++ } ++ return hash; ++} ++ ++/* Double the capacity of the hash table. */ ++static void ++stringtable_rehash (struct stringtable *table) ++{ ++ /* This computation cannot overflow because the old total in-memory ++ size of the hash table is larger than the computed value. */ ++ uint32_t new_allocated = table->allocated * 2; ++ struct stringtable_entry **new_entries ++ = xcalloc (new_allocated, sizeof (table->entries[0])); ++ ++ uint32_t mask = new_allocated - 1; ++ for (uint32_t i = 0; i < table->allocated; ++i) ++ for (struct stringtable_entry *e = table->entries[i]; e != NULL; ) ++ { ++ struct stringtable_entry *next = e->next; ++ uint32_t hash = fnv1a (e->string, e->length); ++ uint32_t new_index = hash & mask; ++ e->next = new_entries[new_index]; ++ new_entries[new_index] = e; ++ e = next; ++ } ++ ++ free (table->entries); ++ table->entries = new_entries; ++ table->allocated = new_allocated; ++} ++ ++struct stringtable_entry * ++stringtable_add (struct stringtable *table, const char *string) ++{ ++ /* Check for a zero-initialized table. */ ++ if (table->allocated == 0) ++ stringtable_init (table); ++ ++ size_t length = strlen (string); ++ if (length > (1U << 30)) ++ error (EXIT_FAILURE, 0, _("String table string is too long")); ++ uint32_t hash = fnv1a (string, length); ++ ++ /* Return a previously-existing entry. */ ++ for (struct stringtable_entry *e ++ = table->entries[hash & (table->allocated - 1)]; ++ e != NULL; e = e->next) ++ if (e->length == length && memcmp (e->string, string, length) == 0) ++ return e; ++ ++ /* Increase the size of the table if necessary. Keep utilization ++ below two thirds. */ ++ if (table->count >= (1U << 30)) ++ error (EXIT_FAILURE, 0, _("String table has too many entries")); ++ if (table->count * 3 > table->allocated * 2) ++ stringtable_rehash (table); ++ ++ /* Add the new table entry. */ ++ ++table->count; ++ struct stringtable_entry *e ++ = xmalloc (offsetof (struct stringtable_entry, string) + length + 1); ++ uint32_t index = hash & (table->allocated - 1); ++ e->next = table->entries[index]; ++ table->entries[index] = e; ++ e->length = length; ++ e->offset = 0; ++ memcpy (e->string, string, length + 1); ++ return e; ++} ++ ++/* Sort reversed strings in reverse lexicographic order. This is used ++ for tail merging. */ ++static int ++finalize_compare (const void *l, const void *r) ++{ ++ struct stringtable_entry *left = *(struct stringtable_entry **) l; ++ struct stringtable_entry *right = *(struct stringtable_entry **) r; ++ size_t to_compare; ++ if (left->length < right->length) ++ to_compare = left->length; ++ else ++ to_compare = right->length; ++ for (size_t i = 1; i <= to_compare; ++i) ++ { ++ unsigned char lch = left->string[left->length - i]; ++ unsigned char rch = right->string[right->length - i]; ++ if (lch != rch) ++ return rch - lch; ++ } ++ if (left->length == right->length) ++ return 0; ++ else if (left->length < right->length) ++ /* Longer strings should come first. */ ++ return 1; ++ else ++ return -1; ++} ++ ++void ++stringtable_finalize (struct stringtable *table, ++ struct stringtable_finalized *result) ++{ ++ if (table->count == 0) ++ { ++ result->strings = xstrdup (""); ++ result->size = 0; ++ return; ++ } ++ ++ /* Optimize the order of the strings. */ ++ struct stringtable_entry **array = xcalloc (table->count, sizeof (*array)); ++ { ++ size_t j = 0; ++ for (uint32_t i = 0; i < table->allocated; ++i) ++ for (struct stringtable_entry *e = table->entries[i]; e != NULL; ++ e = e->next) ++ { ++ array[j] = e; ++ ++j; ++ } ++ assert (j == table->count); ++ } ++ qsort (array, table->count, sizeof (*array), finalize_compare); ++ ++ /* Assign offsets, using tail merging (sharing suffixes) if possible. */ ++ array[0]->offset = 0; ++ for (uint32_t j = 1; j < table->count; ++j) ++ { ++ struct stringtable_entry *previous = array[j - 1]; ++ struct stringtable_entry *current = array[j]; ++ if (previous->length >= current->length ++ && memcmp (&previous->string[previous->length - current->length], ++ current->string, current->length) == 0) ++ current->offset = (previous->offset + previous->length ++ - current->length); ++ else if (__builtin_add_overflow (previous->offset, ++ previous->length + 1, ++ ¤t->offset)) ++ error (EXIT_FAILURE, 0, _("String table is too large")); ++ } ++ ++ /* Allocate the result string. */ ++ { ++ struct stringtable_entry *last = array[table->count - 1]; ++ if (__builtin_add_overflow (last->offset, last->length + 1, ++ &result->size)) ++ error (EXIT_FAILURE, 0, _("String table is too large")); ++ } ++ /* The strings are copied from the hash table, so the array is no ++ longer needed. */ ++ free (array); ++ result->strings = xcalloc (result->size, 1); ++ ++ /* Copy the strings. */ ++ for (uint32_t i = 0; i < table->allocated; ++i) ++ for (struct stringtable_entry *e = table->entries[i]; e != NULL; ++ e = e->next) ++ if (result->strings[e->offset] == '\0') ++ memcpy (&result->strings[e->offset], e->string, e->length + 1); ++} +diff --git a/elf/stringtable.h b/elf/stringtable.h +new file mode 100644 +index 0000000000000000..7d57d1bda9602947 +--- /dev/null ++++ b/elf/stringtable.h +@@ -0,0 +1,64 @@ ++/* String tables for ld.so.cache construction. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published ++ by the Free Software Foundation; version 2 of the License, or ++ (at your option) any later version. ++ ++ This program 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 General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, see . */ ++ ++#ifndef _STRINGTABLE_H ++#define _STRINGTABLE_H ++ ++#include ++#include ++ ++/* An entry in the string table. Only the length and string fields are ++ expected to be used outside the string table code. */ ++struct stringtable_entry ++{ ++ struct stringtable_entry *next; /* For collision resolution. */ ++ uint32_t length; /* Length of then string. */ ++ uint32_t offset; /* From start of finalized table. */ ++ char string[]; /* Null-terminated string. */ ++}; ++ ++/* A string table. Zero-initialization produces a valid atable. */ ++struct stringtable ++{ ++ struct stringtable_entry **entries; /* Array of hash table buckets. */ ++ uint32_t count; /* Number of elements in the table. */ ++ uint32_t allocated; /* Length of the entries array. */ ++}; ++ ++/* Adds STRING to TABLE. May return the address of an existing entry. */ ++struct stringtable_entry *stringtable_add (struct stringtable *table, ++ const char *string); ++ ++/* Result of stringtable_finalize. SIZE bytes at STRINGS should be ++ written to the file. */ ++struct stringtable_finalized ++{ ++ char *strings; ++ size_t size; ++}; ++ ++/* Assigns offsets to string table entries and computes the serialized ++ form of the string table. */ ++void stringtable_finalize (struct stringtable *table, ++ struct stringtable_finalized *result); ++ ++/* Deallocate the string table (but not the TABLE pointer itself). ++ (The table can be re-used for adding more strings without ++ initialization.) */ ++void stringtable_free (struct stringtable *table); ++ ++#endif /* _STRINGTABLE_H */ +diff --git a/elf/stringtable_free.c b/elf/stringtable_free.c +new file mode 100644 +index 0000000000000000..8588a254705d4df8 +--- /dev/null ++++ b/elf/stringtable_free.c +@@ -0,0 +1,33 @@ ++/* String tables for ld.so.cache construction. Deallocation (for tests only). ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published ++ by the Free Software Foundation; version 2 of the License, or ++ (at your option) any later version. ++ ++ This program 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 General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, see . */ ++ ++#include ++#include ++ ++void ++stringtable_free (struct stringtable *table) ++{ ++ for (uint32_t i = 0; i < table->allocated; ++i) ++ for (struct stringtable_entry *e = table->entries[i]; e != NULL; ) ++ { ++ struct stringtable_entry *next = e->next; ++ free (e); ++ e = next; ++ } ++ free (table->entries); ++ *table = (struct stringtable) { 0, }; ++} +diff --git a/elf/tst-stringtable.c b/elf/tst-stringtable.c +new file mode 100644 +index 0000000000000000..3731086037567d57 +--- /dev/null ++++ b/elf/tst-stringtable.c +@@ -0,0 +1,181 @@ ++/* Unit test for ldconfig string tables. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published ++ by the Free Software Foundation; version 2 of the License, or ++ (at your option) any later version. ++ ++ This program 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 General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, see . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* Empty string table. */ ++ { ++ struct stringtable s = { 0, }; ++ struct stringtable_finalized f; ++ stringtable_finalize (&s, &f); ++ TEST_COMPARE_STRING (f.strings, ""); ++ TEST_COMPARE (f.size, 0); ++ free (f.strings); ++ stringtable_free (&s); ++ } ++ ++ /* String table with one empty string. */ ++ { ++ struct stringtable s = { 0, }; ++ struct stringtable_entry *e = stringtable_add (&s, ""); ++ TEST_COMPARE_STRING (e->string, ""); ++ TEST_COMPARE (e->length, 0); ++ TEST_COMPARE (s.count, 1); ++ ++ struct stringtable_finalized f; ++ stringtable_finalize (&s, &f); ++ TEST_COMPARE (e->offset, 0); ++ TEST_COMPARE_STRING (f.strings, ""); ++ TEST_COMPARE (f.size, 1); ++ free (f.strings); ++ stringtable_free (&s); ++ } ++ ++ /* String table with one non-empty string. */ ++ { ++ struct stringtable s = { 0, }; ++ struct stringtable_entry *e = stringtable_add (&s, "name"); ++ TEST_COMPARE_STRING (e->string, "name"); ++ TEST_COMPARE (e->length, 4); ++ TEST_COMPARE (s.count, 1); ++ ++ struct stringtable_finalized f; ++ stringtable_finalize (&s, &f); ++ TEST_COMPARE (e->offset, 0); ++ TEST_COMPARE_STRING (f.strings, "name"); ++ TEST_COMPARE (f.size, 5); ++ free (f.strings); ++ stringtable_free (&s); ++ } ++ ++ /* Two strings, one is a prefix of the other. Tail-merging can only ++ happen in one way in this case. */ ++ { ++ struct stringtable s = { 0, }; ++ struct stringtable_entry *suffix = stringtable_add (&s, "suffix"); ++ TEST_COMPARE_STRING (suffix->string, "suffix"); ++ TEST_COMPARE (suffix->length, 6); ++ TEST_COMPARE (s.count, 1); ++ ++ struct stringtable_entry *prefix ++ = stringtable_add (&s, "prefix-suffix"); ++ TEST_COMPARE_STRING (prefix->string, "prefix-suffix"); ++ TEST_COMPARE (prefix->length, strlen ("prefix-suffix")); ++ TEST_COMPARE (s.count, 2); ++ ++ struct stringtable_finalized f; ++ stringtable_finalize (&s, &f); ++ TEST_COMPARE (prefix->offset, 0); ++ TEST_COMPARE (suffix->offset, strlen ("prefix-")); ++ TEST_COMPARE_STRING (f.strings, "prefix-suffix"); ++ TEST_COMPARE (f.size, sizeof ("prefix-suffix")); ++ free (f.strings); ++ stringtable_free (&s); ++ } ++ ++ /* String table with various shared prefixes. Triggers hash ++ resizing. */ ++ { ++ enum { count = 1500 }; ++ char *strings[2 * count]; ++ struct stringtable_entry *entries[2 * count]; ++ struct stringtable s = { 0, }; ++ for (int i = 0; i < count; ++i) ++ { ++ strings[i] = xasprintf ("%d", i); ++ entries[i] = stringtable_add (&s, strings[i]); ++ TEST_COMPARE (entries[i]->length, strlen (strings[i])); ++ TEST_COMPARE_STRING (entries[i]->string, strings[i]); ++ strings[i + count] = xasprintf ("prefix/%d", i); ++ entries[i + count] = stringtable_add (&s, strings[i + count]); ++ TEST_COMPARE (entries[i + count]->length, strlen (strings[i + count])); ++ TEST_COMPARE_STRING (entries[i + count]->string, strings[i + count]); ++ } ++ ++ struct stringtable_finalized f; ++ stringtable_finalize (&s, &f); ++ ++ for (int i = 0; i < 2 * count; ++i) ++ { ++ TEST_COMPARE (entries[i]->length, strlen (strings[i])); ++ TEST_COMPARE_STRING (entries[i]->string, strings[i]); ++ TEST_COMPARE_STRING (f.strings + entries[i]->offset, strings[i]); ++ free (strings[i]); ++ } ++ ++ free (f.strings); ++ stringtable_free (&s); ++ } ++ ++ /* Verify that maximum tail merging happens. */ ++ { ++ struct stringtable s = { 0, }; ++ const char *strings[] = { ++ "", ++ "a", ++ "b", ++ "aa", ++ "aaa", ++ "aa", ++ "bb", ++ "b", ++ "a", ++ "ba", ++ "baa", ++ }; ++ struct stringtable_entry *entries[array_length (strings)]; ++ for (int i = 0; i < array_length (strings); ++i) ++ entries[i] = stringtable_add (&s, strings[i]); ++ for (int i = 0; i < array_length (strings); ++i) ++ TEST_COMPARE_STRING (entries[i]->string, strings[i]); ++ ++ struct stringtable_finalized f; ++ stringtable_finalize (&s, &f); ++ ++ /* There are only four different strings, "aaa", "ba", "baa", ++ "bb". The rest is shared in an unspecified fashion. */ ++ TEST_COMPARE (f.size, 4 + 3 + 4 + 3); ++ ++ for (int i = 0; i < array_length (strings); ++i) ++ { ++ TEST_COMPARE_STRING (entries[i]->string, strings[i]); ++ TEST_COMPARE_STRING (f.strings + entries[i]->offset, strings[i]); ++ } ++ ++ free (f.strings); ++ stringtable_free (&s); ++ } ++ ++ return 0; ++} ++ ++#include ++ ++/* Re-compile the string table implementation here. It is not ++ possible to link against the actual build because it was built for ++ use in ldconfig. */ ++#define _(arg) arg ++#include "stringtable.c" ++#include "stringtable_free.c" diff --git a/glibc-rh1817513-117.patch b/glibc-rh1817513-117.patch new file mode 100755 index 0000000..65516f4 --- /dev/null +++ b/glibc-rh1817513-117.patch @@ -0,0 +1,209 @@ +commit 73b6e50a22dea9ae6144beaaa675d2ac62c281ca +Author: Florian Weimer +Date: Fri Dec 4 09:13:43 2020 +0100 + + elf: Implement tail merging of strings in ldconfig + + This simplifies the string table construction in elf/cache.c + because there is no more need to keep track of offsets explicitly; + the string table implementation does this internally. + + This change slightly reduces the size of the cache on disk. The + file format does not change as a result. The strings are + null-terminated, without explicit length, so tail merging is + transparent to readers. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/Makefile b/elf/Makefile +index abb3e9d1179ef5cd..a3e802a9a99b759c 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -112,7 +112,8 @@ others-static += ldconfig + others += ldconfig + install-rootsbin += ldconfig + +-ldconfig-modules := cache readlib xmalloc xstrdup chroot_canon static-stubs ++ldconfig-modules := cache readlib xmalloc xstrdup chroot_canon static-stubs \ ++ stringtable + extra-objs += $(ldconfig-modules:=.o) + others-extras = $(ldconfig-modules) + endif +diff --git a/elf/cache.c b/elf/cache.c +index 5a8f1ad70cc3fead..f773cacacf26db1c 100644 +--- a/elf/cache.c ++++ b/elf/cache.c +@@ -35,11 +35,15 @@ + #include + #include + #include ++#include ++ ++/* Used to store library names, paths, and other strings. */ ++static struct stringtable strings; + + struct cache_entry + { +- char *lib; /* Library name. */ +- char *path; /* Path to find library. */ ++ struct stringtable_entry *lib; /* Library name. */ ++ struct stringtable_entry *path; /* Path to find library. */ + int flags; /* Flags to indicate kind of library. */ + unsigned int osversion; /* Required OS version. */ + uint64_t hwcap; /* Important hardware capabilities. */ +@@ -300,7 +304,7 @@ static int + compare (const struct cache_entry *e1, const struct cache_entry *e2) + { + /* We need to swap entries here to get the correct sort order. */ +- int res = _dl_cache_libcmp (e2->lib, e1->lib); ++ int res = _dl_cache_libcmp (e2->lib->string, e1->lib->string); + if (res == 0) + { + if (e1->flags < e2->flags) +@@ -369,26 +373,24 @@ save_cache (const char *cache_name) + { + /* The cache entries are sorted already, save them in this order. */ + +- /* Count the length of all strings. */ +- /* The old format doesn't contain hwcap entries and doesn't contain +- libraries in subdirectories with hwcaps entries. Count therefore +- also all entries with hwcap == 0. */ +- size_t total_strlen = 0; + struct cache_entry *entry; + /* Number of cache entries. */ + int cache_entry_count = 0; +- /* Number of normal cache entries. */ ++ /* The old format doesn't contain hwcap entries and doesn't contain ++ libraries in subdirectories with hwcaps entries. Count therefore ++ also all entries with hwcap == 0. */ + int cache_entry_old_count = 0; + + for (entry = entries; entry != NULL; entry = entry->next) + { +- /* Account the final NULs. */ +- total_strlen += strlen (entry->lib) + strlen (entry->path) + 2; + ++cache_entry_count; + if (entry->hwcap == 0) + ++cache_entry_old_count; + } + ++ struct stringtable_finalized strings_finalized; ++ stringtable_finalize (&strings, &strings_finalized); ++ + /* Create the on disk cache structure. */ + struct cache_file *file_entries = NULL; + size_t file_entries_size = 0; +@@ -432,7 +434,7 @@ save_cache (const char *cache_name) + sizeof CACHE_VERSION - 1); + + file_entries_new->nlibs = cache_entry_count; +- file_entries_new->len_strings = total_strlen; ++ file_entries_new->len_strings = strings_finalized.size; + file_entries_new->flags = cache_file_new_flags_endian_current; + } + +@@ -449,20 +451,20 @@ save_cache (const char *cache_name) + str_offset = 0; + + /* An array for all strings. */ +- char *strings = xmalloc (total_strlen); +- char *str = strings; + int idx_old; + int idx_new; + + for (idx_old = 0, idx_new = 0, entry = entries; entry != NULL; + entry = entry->next, ++idx_new) + { +- /* First the library. */ + if (opt_format != opt_format_new && entry->hwcap == 0) + { + file_entries->libs[idx_old].flags = entry->flags; + /* XXX: Actually we can optimize here and remove duplicates. */ + file_entries->libs[idx_old].key = str_offset + pad; ++ file_entries->libs[idx_new].key = str_offset + entry->lib->offset; ++ file_entries->libs[idx_new].value ++ = str_offset + entry->path->offset; + } + if (opt_format != opt_format_old) + { +@@ -473,20 +475,12 @@ save_cache (const char *cache_name) + file_entries_new->libs[idx_new].flags = entry->flags; + file_entries_new->libs[idx_new].osversion = entry->osversion; + file_entries_new->libs[idx_new].hwcap = entry->hwcap; +- file_entries_new->libs[idx_new].key = str_offset; ++ file_entries_new->libs[idx_new].key ++ = str_offset + entry->lib->offset; ++ file_entries_new->libs[idx_new].value ++ = str_offset + entry->path->offset; + } + +- size_t len = strlen (entry->lib) + 1; +- str = mempcpy (str, entry->lib, len); +- str_offset += len; +- /* Then the path. */ +- if (opt_format != opt_format_new && entry->hwcap == 0) +- file_entries->libs[idx_old].value = str_offset + pad; +- if (opt_format != opt_format_old) +- file_entries_new->libs[idx_new].value = str_offset; +- len = strlen (entry->path) + 1; +- str = mempcpy (str, entry->path, len); +- str_offset += len; + /* Ignore entries with hwcap for old format. */ + if (entry->hwcap == 0) + ++idx_old; +@@ -511,7 +505,7 @@ save_cache (const char *cache_name) + extension_offset += pad; + extension_offset += file_entries_new_size; + } +- extension_offset += total_strlen; ++ extension_offset += strings_finalized.size; + extension_offset = roundup (extension_offset, 4); /* Provide alignment. */ + if (opt_format != opt_format_old) + file_entries_new->extension_offset = extension_offset; +@@ -551,7 +545,8 @@ save_cache (const char *cache_name) + error (EXIT_FAILURE, errno, _("Writing of cache data failed")); + } + +- if (write (fd, strings, total_strlen) != (ssize_t) total_strlen) ++ if (write (fd, strings_finalized.strings, strings_finalized.size) ++ != (ssize_t) strings_finalized.size) + error (EXIT_FAILURE, errno, _("Writing of cache data failed")); + + if (opt_format != opt_format_old) +@@ -580,7 +575,7 @@ save_cache (const char *cache_name) + /* Free all allocated memory. */ + free (file_entries_new); + free (file_entries); +- free (strings); ++ free (strings_finalized.strings); + + while (entries) + { +@@ -596,14 +591,19 @@ void + add_to_cache (const char *path, const char *lib, int flags, + unsigned int osversion, uint64_t hwcap) + { +- size_t liblen = strlen (lib) + 1; +- size_t len = liblen + strlen (path) + 1; +- struct cache_entry *new_entry +- = xmalloc (sizeof (struct cache_entry) + liblen + len); +- +- new_entry->lib = memcpy ((char *) (new_entry + 1), lib, liblen); +- new_entry->path = new_entry->lib + liblen; +- snprintf (new_entry->path, len, "%s/%s", path, lib); ++ struct cache_entry *new_entry = xmalloc (sizeof (*new_entry)); ++ ++ struct stringtable_entry *path_interned; ++ { ++ char *p; ++ if (asprintf (&p, "%s/%s", path, lib) < 0) ++ error (EXIT_FAILURE, errno, _("Could not create library path")); ++ path_interned = stringtable_add (&strings, p); ++ free (p); ++ } ++ ++ new_entry->lib = stringtable_add (&strings, lib); ++ new_entry->path = path_interned; + new_entry->flags = flags; + new_entry->osversion = osversion; + new_entry->hwcap = hwcap; diff --git a/glibc-rh1817513-118.patch b/glibc-rh1817513-118.patch new file mode 100755 index 0000000..92620f5 --- /dev/null +++ b/glibc-rh1817513-118.patch @@ -0,0 +1,778 @@ +commit b44ac4f4c7a8bbe5eaa2701aa9452eaf2c96e1dd +Author: Florian Weimer +Date: Fri Dec 4 09:13:43 2020 +0100 + + elf: Process glibc-hwcaps subdirectories in ldconfig + + Libraries from these subdirectories are added to the cache + with a special hwcap bit DL_CACHE_HWCAP_EXTENSION, so that + they are ignored by older dynamic loaders. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/cache.c b/elf/cache.c +index f773cacacf26db1c..dde3d7fefa4105f9 100644 +--- a/elf/cache.c ++++ b/elf/cache.c +@@ -40,6 +40,105 @@ + /* Used to store library names, paths, and other strings. */ + static struct stringtable strings; + ++/* Keeping track of "glibc-hwcaps" subdirectories. During cache ++ construction, a linear search by name is performed to deduplicate ++ entries. */ ++struct glibc_hwcaps_subdirectory ++{ ++ struct glibc_hwcaps_subdirectory *next; ++ ++ /* Interned string with the subdirectory name. */ ++ struct stringtable_entry *name; ++ ++ /* Array index in the cache_extension_tag_glibc_hwcaps section in ++ the stored cached file. This is computed after all the ++ subdirectories have been processed, so that subdirectory names in ++ the extension section can be sorted. */ ++ uint32_t section_index; ++ ++ /* True if the subdirectory is actually used for anything. */ ++ bool used; ++}; ++ ++const char * ++glibc_hwcaps_subdirectory_name (const struct glibc_hwcaps_subdirectory *dir) ++{ ++ return dir->name->string; ++} ++ ++/* Linked list of known hwcaps subdirecty names. */ ++static struct glibc_hwcaps_subdirectory *hwcaps; ++ ++struct glibc_hwcaps_subdirectory * ++new_glibc_hwcaps_subdirectory (const char *name) ++{ ++ struct stringtable_entry *name_interned = stringtable_add (&strings, name); ++ for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next) ++ if (p->name == name_interned) ++ return p; ++ struct glibc_hwcaps_subdirectory *p = xmalloc (sizeof (*p)); ++ p->next = hwcaps; ++ p->name = name_interned; ++ p->section_index = 0; ++ p->used = false; ++ hwcaps = p; ++ return p; ++} ++ ++/* Helper for sorting struct glibc_hwcaps_subdirectory elements by ++ name. */ ++static int ++assign_glibc_hwcaps_indices_compare (const void *l, const void *r) ++{ ++ const struct glibc_hwcaps_subdirectory *left ++ = *(struct glibc_hwcaps_subdirectory **)l; ++ const struct glibc_hwcaps_subdirectory *right ++ = *(struct glibc_hwcaps_subdirectory **)r; ++ return strcmp (glibc_hwcaps_subdirectory_name (left), ++ glibc_hwcaps_subdirectory_name (right)); ++} ++ ++/* Count the number of hwcaps subdirectories which are actually ++ used. */ ++static size_t ++glibc_hwcaps_count (void) ++{ ++ size_t count = 0; ++ for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next) ++ if (p->used) ++ ++count; ++ return count; ++} ++ ++/* Compute the section_index fields for all */ ++static void ++assign_glibc_hwcaps_indices (void) ++{ ++ /* Convert the linked list into an array, so that we can use qsort. ++ Only copy the subdirectories which are actually used. */ ++ size_t count = glibc_hwcaps_count (); ++ struct glibc_hwcaps_subdirectory **array ++ = xmalloc (sizeof (*array) * count); ++ { ++ size_t i = 0; ++ for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next) ++ if (p->used) ++ { ++ array[i] = p; ++ ++i; ++ } ++ assert (i == count); ++ } ++ ++ qsort (array, count, sizeof (*array), assign_glibc_hwcaps_indices_compare); ++ ++ /* Assign the array indices. */ ++ for (size_t i = 0; i < count; ++i) ++ array[i]->section_index = i; ++ ++ free (array); ++} ++ + struct cache_entry + { + struct stringtable_entry *lib; /* Library name. */ +@@ -48,6 +147,10 @@ struct cache_entry + unsigned int osversion; /* Required OS version. */ + uint64_t hwcap; /* Important hardware capabilities. */ + int bits_hwcap; /* Number of bits set in hwcap. */ ++ ++ /* glibc-hwcaps subdirectory. If not NULL, hwcap must be zero. */ ++ struct glibc_hwcaps_subdirectory *hwcaps; ++ + struct cache_entry *next; /* Next entry in list. */ + }; + +@@ -60,7 +163,7 @@ static const char *flag_descr[] = + /* Print a single entry. */ + static void + print_entry (const char *lib, int flag, unsigned int osversion, +- uint64_t hwcap, const char *key) ++ uint64_t hwcap, const char *hwcap_string, const char *key) + { + printf ("\t%s (", lib); + switch (flag & FLAG_TYPE_MASK) +@@ -132,7 +235,9 @@ print_entry (const char *lib, int flag, unsigned int osversion, + printf (",%d", flag & FLAG_REQUIRED_MASK); + break; + } +- if (hwcap != 0) ++ if (hwcap_string != NULL) ++ printf (", hwcap: \"%s\"", hwcap_string); ++ else if (hwcap != 0) + printf (", hwcap: %#.16" PRIx64, hwcap); + if (osversion != 0) + { +@@ -158,6 +263,29 @@ print_entry (const char *lib, int flag, unsigned int osversion, + printf (") => %s\n", key); + } + ++/* Returns the string with the name of the glibcs-hwcaps subdirectory ++ associated with ENTRY->hwcap. file_base must be the base address ++ for string table indices. */ ++static const char * ++glibc_hwcaps_string (struct cache_extension_all_loaded *ext, ++ const void *file_base, size_t file_size, ++ struct file_entry_new *entry) ++{ ++ const uint32_t *hwcaps_array ++ = ext->sections[cache_extension_tag_glibc_hwcaps].base; ++ if (dl_cache_hwcap_extension (entry) && hwcaps_array != NULL) ++ { ++ uint32_t index = (uint32_t) entry->hwcap; ++ if (index < ext->sections[cache_extension_tag_glibc_hwcaps].size / 4) ++ { ++ uint32_t string_table_index = hwcaps_array[index]; ++ if (string_table_index < file_size) ++ return file_base + string_table_index; ++ } ++ } ++ return NULL; ++} ++ + /* Print an error and exit if the new-file cache is internally + inconsistent. */ + static void +@@ -167,9 +295,7 @@ check_new_cache (struct cache_file_new *cache) + error (EXIT_FAILURE, 0, _("Cache file has wrong endianness.\n")); + } + +-/* Print the extension information at the cache at start address +- FILE_BASE, of length FILE_SIZE bytes. The new-format cache header +- is at CACHE, and the file name for diagnostics is CACHE_NAME. */ ++/* Print the extension information in *EXT. */ + static void + print_extensions (struct cache_extension_all_loaded *ext) + { +@@ -266,7 +392,7 @@ print_cache (const char *cache_name) + /* Print everything. */ + for (unsigned int i = 0; i < cache->nlibs; i++) + print_entry (cache_data + cache->libs[i].key, +- cache->libs[i].flags, 0, 0, ++ cache->libs[i].flags, 0, 0, NULL, + cache_data + cache->libs[i].value); + } + else if (format == 1) +@@ -281,11 +407,16 @@ print_cache (const char *cache_name) + + /* Print everything. */ + for (unsigned int i = 0; i < cache_new->nlibs; i++) +- print_entry (cache_data + cache_new->libs[i].key, +- cache_new->libs[i].flags, +- cache_new->libs[i].osversion, +- cache_new->libs[i].hwcap, +- cache_data + cache_new->libs[i].value); ++ { ++ const char *hwcaps_string ++ = glibc_hwcaps_string (&ext, cache, cache_size, ++ &cache_new->libs[i]); ++ print_entry (cache_data + cache_new->libs[i].key, ++ cache_new->libs[i].flags, ++ cache_new->libs[i].osversion, ++ cache_new->libs[i].hwcap, hwcaps_string, ++ cache_data + cache_new->libs[i].value); ++ } + print_extensions (&ext); + } + /* Cleanup. */ +@@ -311,8 +442,23 @@ compare (const struct cache_entry *e1, const struct cache_entry *e2) + return 1; + else if (e1->flags > e2->flags) + return -1; ++ /* Keep the glibc-hwcaps extension entries before the regular ++ entries, and sort them by their names. search_cache in ++ dl-cache.c stops searching once the first non-extension entry ++ is found, so the extension entries need to come first. */ ++ else if (e1->hwcaps != NULL && e2->hwcaps == NULL) ++ return -1; ++ else if (e1->hwcaps == NULL && e2->hwcaps != NULL) ++ return 1; ++ else if (e1->hwcaps != NULL && e2->hwcaps != NULL) ++ { ++ res = strcmp (glibc_hwcaps_subdirectory_name (e1->hwcaps), ++ glibc_hwcaps_subdirectory_name (e2->hwcaps)); ++ if (res != 0) ++ return res; ++ } + /* Sort by most specific hwcap. */ +- else if (e2->bits_hwcap > e1->bits_hwcap) ++ if (e2->bits_hwcap > e1->bits_hwcap) + return 1; + else if (e2->bits_hwcap < e1->bits_hwcap) + return -1; +@@ -337,30 +483,65 @@ enum + * sizeof (struct cache_extension_section))) + }; + +-/* Write the cache extensions to FD. The extension directory is +- assumed to be located at CACHE_EXTENSION_OFFSET. */ ++/* Write the cache extensions to FD. The string table is shifted by ++ STRING_TABLE_OFFSET. The extension directory is assumed to be ++ located at CACHE_EXTENSION_OFFSET. assign_glibc_hwcaps_indices ++ must have been called. */ + static void +-write_extensions (int fd, uint32_t cache_extension_offset) ++write_extensions (int fd, uint32_t str_offset, ++ uint32_t cache_extension_offset) + { + assert ((cache_extension_offset % 4) == 0); + ++ /* The length and contents of the glibc-hwcaps section. */ ++ uint32_t hwcaps_count = glibc_hwcaps_count (); ++ uint32_t hwcaps_offset = cache_extension_offset + cache_extension_size; ++ uint32_t hwcaps_size = hwcaps_count * sizeof (uint32_t); ++ uint32_t *hwcaps_array = xmalloc (hwcaps_size); ++ for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next) ++ if (p->used) ++ hwcaps_array[p->section_index] = str_offset + p->name->offset; ++ ++ /* This is the offset of the generator string. */ ++ uint32_t generator_offset = hwcaps_offset; ++ if (hwcaps_count == 0) ++ /* There is no section for the hwcaps subdirectories. */ ++ generator_offset -= sizeof (struct cache_extension_section); ++ else ++ /* The string table indices for the hwcaps subdirectories shift ++ the generator string backwards. */ ++ generator_offset += hwcaps_size; ++ + struct cache_extension *ext = xmalloc (cache_extension_size); + ext->magic = cache_extension_magic; +- ext->count = cache_extension_count; + +- for (int i = 0; i < cache_extension_count; ++i) +- { +- ext->sections[i].tag = i; +- ext->sections[i].flags = 0; +- } ++ /* Extension index current being filled. */ ++ size_t xid = 0; + + const char *generator + = "ldconfig " PKGVERSION RELEASE " release version " VERSION; +- ext->sections[cache_extension_tag_generator].offset +- = cache_extension_offset + cache_extension_size; +- ext->sections[cache_extension_tag_generator].size = strlen (generator); ++ ext->sections[xid].tag = cache_extension_tag_generator; ++ ext->sections[xid].flags = 0; ++ ext->sections[xid].offset = generator_offset; ++ ext->sections[xid].size = strlen (generator); ++ ++ if (hwcaps_count > 0) ++ { ++ ++xid; ++ ext->sections[xid].tag = cache_extension_tag_glibc_hwcaps; ++ ext->sections[xid].flags = 0; ++ ext->sections[xid].offset = hwcaps_offset; ++ ext->sections[xid].size = hwcaps_size; ++ } ++ ++ ++xid; ++ ext->count = xid; ++ assert (xid <= cache_extension_count); + +- if (write (fd, ext, cache_extension_size) != cache_extension_size ++ size_t ext_size = (offsetof (struct cache_extension, sections) ++ + xid * sizeof (struct cache_extension_section)); ++ if (write (fd, ext, ext_size) != ext_size ++ || write (fd, hwcaps_array, hwcaps_size) != hwcaps_size + || write (fd, generator, strlen (generator)) != strlen (generator)) + error (EXIT_FAILURE, errno, _("Writing of cache extension data failed")); + +@@ -373,6 +554,8 @@ save_cache (const char *cache_name) + { + /* The cache entries are sorted already, save them in this order. */ + ++ assign_glibc_hwcaps_indices (); ++ + struct cache_entry *entry; + /* Number of cache entries. */ + int cache_entry_count = 0; +@@ -474,7 +657,11 @@ save_cache (const char *cache_name) + struct. */ + file_entries_new->libs[idx_new].flags = entry->flags; + file_entries_new->libs[idx_new].osversion = entry->osversion; +- file_entries_new->libs[idx_new].hwcap = entry->hwcap; ++ if (entry->hwcaps == NULL) ++ file_entries_new->libs[idx_new].hwcap = entry->hwcap; ++ else ++ file_entries_new->libs[idx_new].hwcap ++ = DL_CACHE_HWCAP_EXTENSION | entry->hwcaps->section_index; + file_entries_new->libs[idx_new].key + = str_offset + entry->lib->offset; + file_entries_new->libs[idx_new].value +@@ -554,7 +741,7 @@ save_cache (const char *cache_name) + /* Align file position to 4. */ + off64_t old_offset = lseek64 (fd, extension_offset, SEEK_SET); + assert ((unsigned long long int) (extension_offset - old_offset) < 4); +- write_extensions (fd, extension_offset); ++ write_extensions (fd, str_offset, extension_offset); + } + + /* Make sure user can always read cache file */ +@@ -588,27 +775,35 @@ save_cache (const char *cache_name) + + /* Add one library to the cache. */ + void +-add_to_cache (const char *path, const char *lib, int flags, +- unsigned int osversion, uint64_t hwcap) ++add_to_cache (const char *path, const char *filename, const char *soname, ++ int flags, unsigned int osversion, uint64_t hwcap, ++ struct glibc_hwcaps_subdirectory *hwcaps) + { + struct cache_entry *new_entry = xmalloc (sizeof (*new_entry)); + + struct stringtable_entry *path_interned; + { + char *p; +- if (asprintf (&p, "%s/%s", path, lib) < 0) ++ if (asprintf (&p, "%s/%s", path, filename) < 0) + error (EXIT_FAILURE, errno, _("Could not create library path")); + path_interned = stringtable_add (&strings, p); + free (p); + } + +- new_entry->lib = stringtable_add (&strings, lib); ++ new_entry->lib = stringtable_add (&strings, soname); + new_entry->path = path_interned; + new_entry->flags = flags; + new_entry->osversion = osversion; + new_entry->hwcap = hwcap; ++ new_entry->hwcaps = hwcaps; + new_entry->bits_hwcap = 0; + ++ if (hwcaps != NULL) ++ { ++ assert (hwcap == 0); ++ hwcaps->used = true; ++ } ++ + /* Count the number of bits set in the masked value. */ + for (size_t i = 0; + (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i) +diff --git a/elf/ldconfig.c b/elf/ldconfig.c +index 0fa5aef83f9cd86c..8c66d7e5426d8cc4 100644 +--- a/elf/ldconfig.c ++++ b/elf/ldconfig.c +@@ -16,6 +16,7 @@ + along with this program; if not, see . */ + + #define PROCINFO_CLASS static ++#include + #include + #include + #include +@@ -41,6 +42,7 @@ + + #include + #include ++#include + + #include + +@@ -85,6 +87,10 @@ struct dir_entry + dev_t dev; + const char *from_file; + int from_line; ++ ++ /* Non-NULL for subdirectories under a glibc-hwcaps subdirectory. */ ++ struct glibc_hwcaps_subdirectory *hwcaps; ++ + struct dir_entry *next; + }; + +@@ -338,17 +344,20 @@ new_sub_entry (const struct dir_entry *entry, const char *path, + new_entry->from_line = entry->from_line; + new_entry->path = xstrdup (path); + new_entry->flag = entry->flag; ++ new_entry->hwcaps = NULL; + new_entry->next = NULL; + new_entry->ino = st->st_ino; + new_entry->dev = st->st_dev; + return new_entry; + } + +-/* Add a single directory entry. */ +-static void ++/* Add a single directory entry. Return true if the directory is ++ actually added (because it is not a duplicate). */ ++static bool + add_single_dir (struct dir_entry *entry, int verbose) + { + struct dir_entry *ptr, *prev; ++ bool added = true; + + ptr = dir_entries; + prev = ptr; +@@ -368,6 +377,7 @@ add_single_dir (struct dir_entry *entry, int verbose) + ptr->flag = entry->flag; + free (entry->path); + free (entry); ++ added = false; + break; + } + prev = ptr; +@@ -378,6 +388,73 @@ add_single_dir (struct dir_entry *entry, int verbose) + dir_entries = entry; + else if (ptr == NULL) + prev->next = entry; ++ return added; ++} ++ ++/* Check if PATH contains a "glibc-hwcaps" subdirectory. If so, queue ++ its subdirectories for glibc-hwcaps processing. */ ++static void ++add_glibc_hwcaps_subdirectories (struct dir_entry *entry, const char *path) ++{ ++ /* glibc-hwcaps subdirectories do not nest. */ ++ assert (entry->hwcaps == NULL); ++ ++ char *glibc_hwcaps; ++ if (asprintf (&glibc_hwcaps, "%s/" GLIBC_HWCAPS_SUBDIRECTORY, path) < 0) ++ error (EXIT_FAILURE, errno, _("Could not form glibc-hwcaps path")); ++ ++ DIR *dir = opendir (glibc_hwcaps); ++ if (dir != NULL) ++ { ++ while (true) ++ { ++ errno = 0; ++ struct dirent64 *e = readdir64 (dir); ++ if (e == NULL) ++ { ++ if (errno == 0) ++ break; ++ else ++ error (EXIT_FAILURE, errno, _("Listing directory %s"), path); ++ } ++ ++ /* Ignore hidden subdirectories, including "." and "..", and ++ regular files. File names containing a ':' cannot be ++ looked up by the dynamic loader, so skip those as ++ well. */ ++ if (e->d_name[0] == '.' || e->d_type == DT_REG ++ || strchr (e->d_name, ':') != NULL) ++ continue; ++ ++ /* See if this entry eventually resolves to a directory. */ ++ struct stat64 st; ++ if (fstatat64 (dirfd (dir), e->d_name, &st, 0) < 0) ++ /* Ignore unreadable entries. */ ++ continue; ++ ++ if (S_ISDIR (st.st_mode)) ++ { ++ /* This is a directory, so it needs to be scanned for ++ libraries, associated with the hwcaps implied by the ++ subdirectory name. */ ++ char *new_path; ++ if (asprintf (&new_path, "%s/" GLIBC_HWCAPS_SUBDIRECTORY "/%s", ++ /* Use non-canonicalized path here. */ ++ entry->path, e->d_name) < 0) ++ error (EXIT_FAILURE, errno, ++ _("Could not form glibc-hwcaps path")); ++ struct dir_entry *new_entry = new_sub_entry (entry, new_path, ++ &st); ++ free (new_path); ++ new_entry->hwcaps = new_glibc_hwcaps_subdirectory (e->d_name); ++ add_single_dir (new_entry, 0); ++ } ++ } ++ ++ closedir (dir); ++ } ++ ++ free (glibc_hwcaps); + } + + /* Add one directory to the list of directories to process. */ +@@ -386,6 +463,7 @@ add_dir_1 (const char *line, const char *from_file, int from_line) + { + unsigned int i; + struct dir_entry *entry = xmalloc (sizeof (struct dir_entry)); ++ entry->hwcaps = NULL; + entry->next = NULL; + + entry->from_file = strdup (from_file); +@@ -443,7 +521,9 @@ add_dir_1 (const char *line, const char *from_file, int from_line) + entry->ino = stat_buf.st_ino; + entry->dev = stat_buf.st_dev; + +- add_single_dir (entry, 1); ++ if (add_single_dir (entry, 1)) ++ /* Add glibc-hwcaps subdirectories if present. */ ++ add_glibc_hwcaps_subdirectories (entry, path); + } + + if (opt_chroot) +@@ -695,15 +775,27 @@ struct dlib_entry + static void + search_dir (const struct dir_entry *entry) + { +- uint64_t hwcap = path_hwcap (entry->path); +- if (opt_verbose) ++ uint64_t hwcap; ++ if (entry->hwcaps == NULL) + { +- if (hwcap != 0) +- printf ("%s: (hwcap: %#.16" PRIx64 ")", entry->path, hwcap); +- else +- printf ("%s:", entry->path); +- printf (_(" (from %s:%d)\n"), entry->from_file, entry->from_line); ++ hwcap = path_hwcap (entry->path); ++ if (opt_verbose) ++ { ++ if (hwcap != 0) ++ printf ("%s: (hwcap: %#.16" PRIx64 ")", entry->path, hwcap); ++ else ++ printf ("%s:", entry->path); ++ } + } ++ else ++ { ++ hwcap = 0; ++ if (opt_verbose) ++ printf ("%s: (hwcap: \"%s\")", entry->path, ++ glibc_hwcaps_subdirectory_name (entry->hwcaps)); ++ } ++ if (opt_verbose) ++ printf (_(" (from %s:%d)\n"), entry->from_file, entry->from_line); + + char *dir_name; + char *real_file_name; +@@ -745,13 +837,15 @@ search_dir (const struct dir_entry *entry) + && direntry->d_type != DT_DIR) + continue; + /* Does this file look like a shared library or is it a hwcap +- subdirectory? The dynamic linker is also considered as ++ subdirectory (if not already processing a glibc-hwcaps ++ subdirectory)? The dynamic linker is also considered as + shared library. */ + if (((strncmp (direntry->d_name, "lib", 3) != 0 + && strncmp (direntry->d_name, "ld-", 3) != 0) + || strstr (direntry->d_name, ".so") == NULL) + && (direntry->d_type == DT_REG +- || !is_hwcap_platform (direntry->d_name))) ++ || (entry->hwcaps == NULL ++ && !is_hwcap_platform (direntry->d_name)))) + continue; + + size_t len = strlen (direntry->d_name); +@@ -799,7 +893,7 @@ search_dir (const struct dir_entry *entry) + } + + struct stat64 stat_buf; +- int is_dir; ++ bool is_dir; + int is_link = S_ISLNK (lstat_buf.st_mode); + if (is_link) + { +@@ -837,7 +931,10 @@ search_dir (const struct dir_entry *entry) + else + is_dir = S_ISDIR (lstat_buf.st_mode); + +- if (is_dir && is_hwcap_platform (direntry->d_name)) ++ /* No descending into subdirectories if this directory is a ++ glibc-hwcaps subdirectory (which are not recursive). */ ++ if (entry->hwcaps == NULL ++ && is_dir && is_hwcap_platform (direntry->d_name)) + { + if (!is_link + && direntry->d_type != DT_UNKNOWN +@@ -1028,13 +1125,31 @@ search_dir (const struct dir_entry *entry) + struct dlib_entry *dlib_ptr; + for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next) + { +- /* Don't create links to links. */ +- if (dlib_ptr->is_link == 0) +- create_links (dir_name, entry->path, dlib_ptr->name, +- dlib_ptr->soname); ++ /* The cached file name is the soname for non-glibc-hwcaps ++ subdirectories (relying on symbolic links; this helps with ++ library updates that change the file name), and the actual ++ file for glibc-hwcaps subdirectories. */ ++ const char *filename; ++ if (entry->hwcaps == NULL) ++ { ++ /* Don't create links to links. */ ++ if (dlib_ptr->is_link == 0) ++ create_links (dir_name, entry->path, dlib_ptr->name, ++ dlib_ptr->soname); ++ filename = dlib_ptr->soname; ++ } ++ else ++ { ++ /* Do not create links in glibc-hwcaps subdirectories, but ++ still log the cache addition. */ ++ if (opt_verbose) ++ printf ("\t%s -> %s\n", dlib_ptr->soname, dlib_ptr->name); ++ filename = dlib_ptr->name; ++ } + if (opt_build_cache) +- add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag, +- dlib_ptr->osversion, hwcap); ++ add_to_cache (entry->path, filename, dlib_ptr->soname, ++ dlib_ptr->flag, dlib_ptr->osversion, ++ hwcap, entry->hwcaps); + } + + /* Free all resources. */ +diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h +index 259e843724531630..6adbe3c79a32a4ec 100644 +--- a/sysdeps/generic/dl-cache.h ++++ b/sysdeps/generic/dl-cache.h +@@ -99,6 +99,23 @@ struct file_entry_new + uint64_t hwcap; /* Hwcap entry. */ + }; + ++/* This bit in the hwcap field of struct file_entry_new indicates that ++ the lower 32 bits contain an index into the ++ cache_extension_tag_glibc_hwcaps section. Older glibc versions do ++ not know about this HWCAP bit, so they will ignore these ++ entries. */ ++#define DL_CACHE_HWCAP_EXTENSION (1ULL << 62) ++ ++/* Return true if the ENTRY->hwcap value indicates that ++ DL_CACHE_HWCAP_EXTENSION is used. */ ++static inline bool ++dl_cache_hwcap_extension (struct file_entry_new *entry) ++{ ++ /* If DL_CACHE_HWCAP_EXTENSION is set, but other bits as well, this ++ is a different kind of extension. */ ++ return (entry->hwcap >> 32) == (DL_CACHE_HWCAP_EXTENSION >> 32); ++} ++ + /* See flags member of struct cache_file_new below. */ + enum + { +@@ -182,6 +199,17 @@ enum cache_extension_tag + cache file. */ + cache_extension_tag_generator, + ++ /* glibc-hwcaps subdirectory information. An array of uint32_t ++ values, which are indices into the string table. The strings ++ are sorted lexicographically (according to strcmp). The extra ++ level of indirection (instead of using string table indices ++ directly) allows the dynamic loader to compute the preference ++ order of the hwcaps names more efficiently. ++ ++ For this section, 4-byte alignment is required, and the section ++ size must be a multiple of 4. */ ++ cache_extension_tag_glibc_hwcaps, ++ + /* Total number of known cache extension tags. */ + cache_extension_count + }; +@@ -236,6 +264,27 @@ struct cache_extension_all_loaded + struct cache_extension_loaded sections[cache_extension_count]; + }; + ++/* Performs basic data validation based on section tag, and removes ++ the sections which are invalid. */ ++static void ++cache_extension_verify (struct cache_extension_all_loaded *loaded) ++{ ++ { ++ /* Section must not be empty, it must be aligned at 4 bytes, and ++ the size must be a multiple of 4. */ ++ struct cache_extension_loaded *hwcaps ++ = &loaded->sections[cache_extension_tag_glibc_hwcaps]; ++ if (hwcaps->size == 0 ++ || ((uintptr_t) hwcaps->base % 4) != 0 ++ || (hwcaps->size % 4) != 0) ++ { ++ hwcaps->base = NULL; ++ hwcaps->size = 0; ++ hwcaps->flags = 0; ++ } ++ } ++} ++ + static bool __attribute__ ((unused)) + cache_extension_load (const struct cache_file_new *cache, + const void *file_base, size_t file_size, +@@ -282,6 +331,7 @@ cache_extension_load (const struct cache_file_new *cache, + loaded->sections[tag].size = ext->sections[i].size; + loaded->sections[tag].flags = ext->sections[i].flags; + } ++ cache_extension_verify (loaded); + return true; + } + +diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h +index b15b142511829436..a8d22f143f867a3e 100644 +--- a/sysdeps/generic/ldconfig.h ++++ b/sysdeps/generic/ldconfig.h +@@ -57,8 +57,22 @@ extern void init_cache (void); + + extern void save_cache (const char *cache_name); + +-extern void add_to_cache (const char *path, const char *lib, int flags, +- unsigned int osversion, uint64_t hwcap); ++struct glibc_hwcaps_subdirectory; ++ ++/* Return a struct describing the subdirectory for NAME. Reuse an ++ existing struct if it exists. */ ++struct glibc_hwcaps_subdirectory *new_glibc_hwcaps_subdirectory ++ (const char *name); ++ ++/* Returns the name that was specified when ++ add_glibc_hwcaps_subdirectory was called. */ ++const char *glibc_hwcaps_subdirectory_name ++ (const struct glibc_hwcaps_subdirectory *); ++ ++extern void add_to_cache (const char *path, const char *filename, ++ const char *soname, ++ int flags, unsigned int osversion, uint64_t hwcap, ++ struct glibc_hwcaps_subdirectory *); + + extern void init_aux_cache (void); + diff --git a/glibc-rh1817513-119.patch b/glibc-rh1817513-119.patch new file mode 100755 index 0000000..adb64de --- /dev/null +++ b/glibc-rh1817513-119.patch @@ -0,0 +1,659 @@ +commit 600d9e0c87940da9b0fdeff492bf888df852d40c +Author: Florian Weimer +Date: Fri Dec 4 09:13:43 2020 +0100 + + elf: Add glibc-hwcaps subdirectory support to ld.so cache processing + + This recognizes the DL_CACHE_HWCAP_EXTENSION flag in cache entries, + and picks the supported cache entry with the highest priority. + + The elf/tst-glibc-hwcaps-prepend-cache test documents a non-desired + aspect of the current cache implementation: If the cache selects a DSO + that does not exist on disk, _dl_map_object falls back to open_path, + which may or may not find an alternative implementation. This is an + existing limitation that also applies to the legacy hwcaps processing + for ld.so.cache. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/Makefile b/elf/Makefile +index a3e802a9a99b759c..f67b231c0f8e3aff 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -162,6 +162,12 @@ tst-tls1-static-non-pie-no-pie = yes + tests-container = \ + tst-ldconfig-bad-aux-cache + ++ifeq (no,$(build-hardcoded-path-in-tests)) ++# This is an ld.so.cache test, and RPATH/RUNPATH in the executable ++# interferes with its test objectives. ++tests-container += tst-glibc-hwcaps-prepend-cache ++endif ++ + tests := tst-tls9 tst-leaks1 \ + tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \ + tst-auxv tst-stringtable +@@ -1784,6 +1790,14 @@ $(objpfx)tst-glibc-hwcaps-prepend.out: \ + $< > $@; \ + $(evaluate-test) + ++# Like tst-glibc-hwcaps-prepend, but uses a container and loads the ++# library via ld.so.cache. Test setup is contained in the test ++# itself. ++$(objpfx)tst-glibc-hwcaps-prepend-cache: $(libdl) ++$(objpfx)tst-glibc-hwcaps-prepend-cache.out: \ ++ $(objpfx)tst-glibc-hwcaps-prepend-cache $(objpfx)libmarkermod1-1.so \ ++ $(objpfx)libmarkermod1-2.so $(objpfx)libmarkermod1-3.so ++ + # tst-glibc-hwcaps-mask checks that --glibc-hwcaps-mask can be used to + # suppress all auto-detected subdirectories. + $(objpfx)tst-glibc-hwcaps-mask: $(objpfx)libmarkermod1-1.so +@@ -1795,3 +1809,7 @@ $(objpfx)tst-glibc-hwcaps-mask.out: \ + --glibc-hwcaps-mask does-not-exist \ + $< > $@; \ + $(evaluate-test) ++ ++# Generic dependency for sysdeps implementation of ++# tst-glibc-hwcaps-cache. ++$(objpfx)tst-glibc-hwcaps-cache.out: $(objpfx)tst-glibc-hwcaps +diff --git a/elf/dl-cache.c b/elf/dl-cache.c +index de063faa8b2c88ae..e75afdaee23226e6 100644 +--- a/elf/dl-cache.c ++++ b/elf/dl-cache.c +@@ -35,6 +35,144 @@ static struct cache_file *cache; + static struct cache_file_new *cache_new; + static size_t cachesize; + ++#ifdef SHARED ++/* This is used to cache the priorities of glibc-hwcaps ++ subdirectories. The elements of _dl_cache_priorities correspond to ++ the strings in the cache_extension_tag_glibc_hwcaps section. */ ++static uint32_t *glibc_hwcaps_priorities; ++static uint32_t glibc_hwcaps_priorities_length; ++static uint32_t glibc_hwcaps_priorities_allocated; ++ ++/* True if the full malloc was used to allocated the array. */ ++static bool glibc_hwcaps_priorities_malloced; ++ ++/* Deallocate the glibc_hwcaps_priorities array. */ ++static void ++glibc_hwcaps_priorities_free (void) ++{ ++ /* When the minimal malloc is in use, free does not do anything, ++ so it does not make sense to call it. */ ++ if (glibc_hwcaps_priorities_malloced) ++ free (glibc_hwcaps_priorities); ++ glibc_hwcaps_priorities = NULL; ++ glibc_hwcaps_priorities_allocated = 0; ++} ++ ++/* Ordered comparison of a hwcaps string from the cache on the left ++ (identified by its string table index) and a _dl_hwcaps_priorities ++ element on the right. */ ++static int ++glibc_hwcaps_compare (uint32_t left_index, struct dl_hwcaps_priority *right) ++{ ++ const char *left_name = (const char *) cache + left_index; ++ uint32_t left_name_length = strlen (left_name); ++ uint32_t to_compare; ++ if (left_name_length < right->name_length) ++ to_compare = left_name_length; ++ else ++ to_compare = right->name_length; ++ int cmp = memcmp (left_name, right->name, to_compare); ++ if (cmp != 0) ++ return cmp; ++ if (left_name_length < right->name_length) ++ return -1; ++ else if (left_name_length > right->name_length) ++ return 1; ++ else ++ return 0; ++} ++ ++/* Initialize the glibc_hwcaps_priorities array and its length, ++ glibc_hwcaps_priorities_length. */ ++static void ++glibc_hwcaps_priorities_init (void) ++{ ++ struct cache_extension_all_loaded ext; ++ if (!cache_extension_load (cache_new, cache, cachesize, &ext)) ++ return; ++ ++ uint32_t length = (ext.sections[cache_extension_tag_glibc_hwcaps].size ++ / sizeof (uint32_t)); ++ if (length > glibc_hwcaps_priorities_allocated) ++ { ++ glibc_hwcaps_priorities_free (); ++ ++ uint32_t *new_allocation = malloc (length * sizeof (uint32_t)); ++ if (new_allocation == NULL) ++ /* This effectively disables hwcaps on memory allocation ++ errors. */ ++ return; ++ ++ glibc_hwcaps_priorities = new_allocation; ++ glibc_hwcaps_priorities_allocated = length; ++ glibc_hwcaps_priorities_malloced = __rtld_malloc_is_complete (); ++ } ++ ++ /* Compute the priorities for the subdirectories by merging the ++ array in the cache with the dl_hwcaps_priorities array. */ ++ const uint32_t *left = ext.sections[cache_extension_tag_glibc_hwcaps].base; ++ const uint32_t *left_end = left + length; ++ struct dl_hwcaps_priority *right = _dl_hwcaps_priorities; ++ struct dl_hwcaps_priority *right_end = right + _dl_hwcaps_priorities_length; ++ uint32_t *result = glibc_hwcaps_priorities; ++ ++ while (left < left_end && right < right_end) ++ { ++ if (*left < cachesize) ++ { ++ int cmp = glibc_hwcaps_compare (*left, right); ++ if (cmp == 0) ++ { ++ *result = right->priority; ++ ++result; ++ ++left; ++ ++right; ++ } ++ else if (cmp < 0) ++ { ++ *result = 0; ++ ++result; ++ ++left; ++ } ++ else ++ ++right; ++ } ++ else ++ { ++ *result = 0; ++ ++result; ++ } ++ } ++ while (left < left_end) ++ { ++ *result = 0; ++ ++result; ++ ++left; ++ } ++ ++ glibc_hwcaps_priorities_length = length; ++} ++ ++/* Return the priority of the cache_extension_tag_glibc_hwcaps section ++ entry at INDEX. Zero means do not use. Otherwise, lower values ++ indicate greater preference. */ ++static uint32_t ++glibc_hwcaps_priority (uint32_t index) ++{ ++ /* This does not need to repeated initialization attempts because ++ this function is only called if there is glibc-hwcaps data in the ++ cache, so the first call initializes the glibc_hwcaps_priorities ++ array. */ ++ if (glibc_hwcaps_priorities_length == 0) ++ glibc_hwcaps_priorities_init (); ++ ++ if (index < glibc_hwcaps_priorities_length) ++ return glibc_hwcaps_priorities[index]; ++ else ++ return 0; ++} ++#endif /* SHARED */ ++ + /* True if PTR is a valid string table index. */ + static inline bool + _dl_cache_verify_ptr (uint32_t ptr, size_t string_table_size) +@@ -74,6 +212,9 @@ search_cache (const char *string_table, uint32_t string_table_size, + int left = 0; + int right = nlibs - 1; + const char *best = NULL; ++#ifdef SHARED ++ uint32_t best_priority = 0; ++#endif + + while (left <= right) + { +@@ -129,6 +270,11 @@ search_cache (const char *string_table, uint32_t string_table_size, + { + if (best == NULL || flags == GLRO (dl_correct_cache_id)) + { ++ /* Named/extension hwcaps get slightly different ++ treatment: We keep searching for a better ++ match. */ ++ bool named_hwcap = false; ++ + if (entry_size >= sizeof (struct file_entry_new)) + { + /* The entry is large enough to include +@@ -136,7 +282,18 @@ search_cache (const char *string_table, uint32_t string_table_size, + struct file_entry_new *libnew + = (struct file_entry_new *) lib; + +- if (libnew->hwcap & hwcap_exclude) ++#ifdef SHARED ++ named_hwcap = dl_cache_hwcap_extension (libnew); ++#endif ++ ++ /* The entries with named/extension hwcaps ++ have been exhausted. Return the best ++ match encountered so far if there is ++ one. */ ++ if (!named_hwcap && best != NULL) ++ break; ++ ++ if ((libnew->hwcap & hwcap_exclude) && !named_hwcap) + continue; + if (GLRO (dl_osversion) + && libnew->osversion > GLRO (dl_osversion)) +@@ -146,14 +303,41 @@ search_cache (const char *string_table, uint32_t string_table_size, + && ((libnew->hwcap & _DL_HWCAP_PLATFORM) + != platform)) + continue; ++ ++#ifdef SHARED ++ /* For named hwcaps, determine the priority ++ and see if beats what has been found so ++ far. */ ++ if (named_hwcap) ++ { ++ uint32_t entry_priority ++ = glibc_hwcaps_priority (libnew->hwcap); ++ if (entry_priority == 0) ++ /* Not usable at all. Skip. */ ++ continue; ++ else if (best == NULL ++ || entry_priority < best_priority) ++ /* This entry is of higher priority ++ than the previous one, or it is the ++ first entry. */ ++ best_priority = entry_priority; ++ else ++ /* An entry has already been found, ++ but it is a better match. */ ++ continue; ++ } ++#endif /* SHARED */ + } + + best = string_table + lib->value; + +- if (flags == GLRO (dl_correct_cache_id)) ++ if (flags == GLRO (dl_correct_cache_id) ++ && !named_hwcap) + /* We've found an exact match for the shared + object and no general `ELF' release. Stop +- searching. */ ++ searching, but not if a named (extension) ++ hwcap is used. In this case, an entry with ++ a higher priority may come up later. */ + break; + } + } +@@ -346,5 +530,9 @@ _dl_unload_cache (void) + __munmap (cache, cachesize); + cache = NULL; + } ++#ifdef SHARED ++ /* This marks the glibc_hwcaps_priorities array as out-of-date. */ ++ glibc_hwcaps_priorities_length = 0; ++#endif + } + #endif +diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c +index e57d0d2d41741021..098173a84c43c1fd 100644 +--- a/elf/dl-hwcaps.c ++++ b/elf/dl-hwcaps.c +@@ -89,6 +89,81 @@ copy_hwcaps (struct copy_hwcaps *target, const char *hwcaps, + } + } + ++struct dl_hwcaps_priority *_dl_hwcaps_priorities; ++uint32_t _dl_hwcaps_priorities_length; ++ ++/* Allocate _dl_hwcaps_priorities and fill it with data. */ ++static void ++compute_priorities (size_t total_count, const char *prepend, ++ uint32_t bitmask, const char *mask) ++{ ++ _dl_hwcaps_priorities = malloc (total_count ++ * sizeof (*_dl_hwcaps_priorities)); ++ if (_dl_hwcaps_priorities == NULL) ++ _dl_signal_error (ENOMEM, NULL, NULL, ++ N_("cannot create HWCAP priorities")); ++ _dl_hwcaps_priorities_length = total_count; ++ ++ /* First the prepended subdirectories. */ ++ size_t i = 0; ++ { ++ struct dl_hwcaps_split sp; ++ _dl_hwcaps_split_init (&sp, prepend); ++ while (_dl_hwcaps_split (&sp)) ++ { ++ _dl_hwcaps_priorities[i].name = sp.segment; ++ _dl_hwcaps_priorities[i].name_length = sp.length; ++ _dl_hwcaps_priorities[i].priority = i + 1; ++ ++i; ++ } ++ } ++ ++ /* Then the built-in subdirectories that are actually active. */ ++ { ++ struct dl_hwcaps_split_masked sp; ++ _dl_hwcaps_split_masked_init (&sp, _dl_hwcaps_subdirs, bitmask, mask); ++ while (_dl_hwcaps_split_masked (&sp)) ++ { ++ _dl_hwcaps_priorities[i].name = sp.split.segment; ++ _dl_hwcaps_priorities[i].name_length = sp.split.length; ++ _dl_hwcaps_priorities[i].priority = i + 1; ++ ++i; ++ } ++ } ++ assert (i == total_count); ++} ++ ++/* Sort the _dl_hwcaps_priorities array by name. */ ++static void ++sort_priorities_by_name (void) ++{ ++ /* Insertion sort. There is no need to link qsort into the dynamic ++ loader for such a short array. */ ++ for (size_t i = 1; i < _dl_hwcaps_priorities_length; ++i) ++ for (size_t j = i; j > 0; --j) ++ { ++ struct dl_hwcaps_priority *previous = _dl_hwcaps_priorities + j - 1; ++ struct dl_hwcaps_priority *current = _dl_hwcaps_priorities + j; ++ ++ /* Bail out if current is greater or equal to the previous ++ value. */ ++ uint32_t to_compare; ++ if (current->name_length < previous->name_length) ++ to_compare = current->name_length; ++ else ++ to_compare = previous->name_length; ++ int cmp = memcmp (current->name, previous->name, to_compare); ++ if (cmp >= 0 ++ || (cmp == 0 && current->name_length >= previous->name_length)) ++ break; ++ ++ /* Swap *previous and *current. */ ++ struct dl_hwcaps_priority tmp = *previous; ++ *previous = *current; ++ *current = tmp; ++ } ++} ++ + /* Return an array of useful/necessary hardware capability names. */ + const struct r_strlenpair * + _dl_important_hwcaps (const char *glibc_hwcaps_prepend, +@@ -111,6 +186,9 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend, + update_hwcaps_counts (&hwcaps_counts, glibc_hwcaps_prepend, -1, NULL); + update_hwcaps_counts (&hwcaps_counts, _dl_hwcaps_subdirs, + hwcaps_subdirs_active, glibc_hwcaps_mask); ++ compute_priorities (hwcaps_counts.count, glibc_hwcaps_prepend, ++ hwcaps_subdirs_active, glibc_hwcaps_mask); ++ sort_priorities_by_name (); + + /* Each hwcaps subdirectory has a GLIBC_HWCAPS_PREFIX string prefix + and a "/" suffix once stored in the result. */ +diff --git a/elf/dl-hwcaps.h b/elf/dl-hwcaps.h +index 3fcfbceb1a8fc1c8..769ecab3f886c6c4 100644 +--- a/elf/dl-hwcaps.h ++++ b/elf/dl-hwcaps.h +@@ -132,4 +132,23 @@ _dl_hwcaps_subdirs_build_bitmask (int subdirs, int active) + return mask ^ ((1U << inactive) - 1); + } + ++/* Pre-computed glibc-hwcaps subdirectory priorities. Used in ++ dl-cache.c to quickly find the proprieties for the stored HWCAP ++ names. */ ++struct dl_hwcaps_priority ++{ ++ /* The name consists of name_length bytes at name (not necessarily ++ null-terminated). */ ++ const char *name; ++ uint32_t name_length; ++ ++ /* Priority of this name. A positive number. */ ++ uint32_t priority; ++}; ++ ++/* Pre-computed hwcaps priorities. Set up by ++ _dl_important_hwcaps. */ ++extern struct dl_hwcaps_priority *_dl_hwcaps_priorities attribute_hidden; ++extern uint32_t _dl_hwcaps_priorities_length attribute_hidden; ++ + #endif /* _DL_HWCAPS_H */ +diff --git a/elf/tst-glibc-hwcaps-cache.c b/elf/tst-glibc-hwcaps-cache.c +new file mode 100644 +index 0000000000000000..4bad56afc03451fc +--- /dev/null ++++ b/elf/tst-glibc-hwcaps-cache.c +@@ -0,0 +1,45 @@ ++/* Wrapper to invoke tst-glibc-hwcaps in a container, to test ld.so.cache. ++ Copyright (C) 2020 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 ++ . */ ++ ++/* This program is just a wrapper that runs ldconfig followed by ++ tst-glibc-hwcaps. The actual test is provided via an ++ implementation in a sysdeps subdirectory. */ ++ ++#include ++#include ++#include ++#include ++ ++int ++main (int argc, char **argv) ++{ ++ /* Run ldconfig to populate the cache. */ ++ { ++ char *command = xasprintf ("%s/ldconfig", support_install_rootsbindir); ++ if (system (command) != 0) ++ return 1; ++ free (command); ++ } ++ ++ /* Reuse tst-glibc-hwcaps. Since this code is running in a ++ container, we can launch it directly. */ ++ char *path = xasprintf ("%s/elf/tst-glibc-hwcaps", support_objdir_root); ++ execv (path, argv); ++ printf ("error: execv of %s failed: %m\n", path); ++ return 1; ++} +diff --git a/elf/tst-glibc-hwcaps-cache.root/etc/ld.so.conf b/elf/tst-glibc-hwcaps-cache.root/etc/ld.so.conf +new file mode 100644 +index 0000000000000000..e1e74dbda2bf3dfa +--- /dev/null ++++ b/elf/tst-glibc-hwcaps-cache.root/etc/ld.so.conf +@@ -0,0 +1,2 @@ ++# This file was created to suppress a warning from ldconfig: ++# /sbin/ldconfig: Warning: ignoring configuration file that cannot be opened: /etc/ld.so.conf: No such file or directory +diff --git a/elf/tst-glibc-hwcaps-cache.root/postclean.req b/elf/tst-glibc-hwcaps-cache.root/postclean.req +new file mode 100644 +index 0000000000000000..e69de29bb2d1d643 +diff --git a/elf/tst-glibc-hwcaps-cache.script b/elf/tst-glibc-hwcaps-cache.script +new file mode 100644 +index 0000000000000000..6356d152089cdd9a +--- /dev/null ++++ b/elf/tst-glibc-hwcaps-cache.script +@@ -0,0 +1,6 @@ ++# test-container does not support scripts in sysdeps directories, so ++# collect everything in one file. ++ ++cp $B/elf/libmarkermod2-1.so $L/libmarkermod2.so ++cp $B/elf/libmarkermod3-1.so $L/libmarkermod3.so ++cp $B/elf/libmarkermod4-1.so $L/libmarkermod4.so +diff --git a/elf/tst-glibc-hwcaps-prepend-cache.c b/elf/tst-glibc-hwcaps-prepend-cache.c +new file mode 100644 +index 0000000000000000..40509cebe2b5ba27 +--- /dev/null ++++ b/elf/tst-glibc-hwcaps-prepend-cache.c +@@ -0,0 +1,149 @@ ++/* Test that --glibc-hwcaps-prepend works, using dlopen and /etc/ld.so.cache. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Invoke /sbin/ldconfig with some error checking. */ ++static void ++run_ldconfig (void) ++{ ++ char *command = xasprintf ("%s/ldconfig", support_install_rootsbindir); ++ TEST_COMPARE (system (command), 0); ++ free (command); ++} ++ ++/* The library under test. */ ++#define SONAME "libmarkermod1.so" ++ ++static int ++do_test (void) ++{ ++ if (dlopen (SONAME, RTLD_NOW) != NULL) ++ FAIL_EXIT1 (SONAME " is already on the search path"); ++ ++ /* Install the default implementation of libmarkermod1.so. */ ++ xmkdirp ("/etc", 0777); ++ support_write_file_string ("/etc/ld.so.conf", "/glibc-test/lib\n"); ++ xmkdirp ("/glibc-test/lib/glibc-hwcaps/prepend2", 0777); ++ xmkdirp ("/glibc-test/lib/glibc-hwcaps/prepend3", 0777); ++ { ++ char *src = xasprintf ("%s/elf/libmarkermod1-1.so", support_objdir_root); ++ support_copy_file (src, "/glibc-test/lib/" SONAME); ++ free (src); ++ } ++ run_ldconfig (); ++ { ++ /* The default implementation can now be loaded. */ ++ void *handle = xdlopen (SONAME, RTLD_NOW); ++ int (*marker1) (void) = xdlsym (handle, "marker1"); ++ TEST_COMPARE (marker1 (), 1); ++ xdlclose (handle); ++ } ++ ++ /* Add the first override to the directory that is searched last. */ ++ { ++ char *src = xasprintf ("%s/elf/libmarkermod1-2.so", support_objdir_root); ++ support_copy_file (src, "/glibc-test/lib/glibc-hwcaps/prepend2/" ++ SONAME); ++ free (src); ++ } ++ { ++ /* This is still the first implementation. The cache has not been ++ updated. */ ++ void *handle = xdlopen (SONAME, RTLD_NOW); ++ int (*marker1) (void) = xdlsym (handle, "marker1"); ++ TEST_COMPARE (marker1 (), 1); ++ xdlclose (handle); ++ } ++ run_ldconfig (); ++ { ++ /* After running ldconfig, it is the second implementation. */ ++ void *handle = xdlopen (SONAME, RTLD_NOW); ++ int (*marker1) (void) = xdlsym (handle, "marker1"); ++ TEST_COMPARE (marker1 (), 2); ++ xdlclose (handle); ++ } ++ ++ /* Add the second override to the directory that is searched first. */ ++ { ++ char *src = xasprintf ("%s/elf/libmarkermod1-3.so", support_objdir_root); ++ support_copy_file (src, "/glibc-test/lib/glibc-hwcaps/prepend3/" ++ SONAME); ++ free (src); ++ } ++ { ++ /* This is still the second implementation. */ ++ void *handle = xdlopen (SONAME, RTLD_NOW); ++ int (*marker1) (void) = xdlsym (handle, "marker1"); ++ TEST_COMPARE (marker1 (), 2); ++ xdlclose (handle); ++ } ++ run_ldconfig (); ++ { ++ /* After running ldconfig, it is the third implementation. */ ++ void *handle = xdlopen (SONAME, RTLD_NOW); ++ int (*marker1) (void) = xdlsym (handle, "marker1"); ++ TEST_COMPARE (marker1 (), 3); ++ xdlclose (handle); ++ } ++ ++ /* Remove the second override again, without running ldconfig. ++ Ideally, this would revert to implementation 2. However, in the ++ current implementation, the cache returns exactly one file name ++ which does not exist after unlinking, so the dlopen fails. */ ++ xunlink ("/glibc-test/lib/glibc-hwcaps/prepend3/" SONAME); ++ TEST_VERIFY (dlopen (SONAME, RTLD_NOW) == NULL); ++ run_ldconfig (); ++ { ++ /* After running ldconfig, the second implementation is available ++ once more. */ ++ void *handle = xdlopen (SONAME, RTLD_NOW); ++ int (*marker1) (void) = xdlsym (handle, "marker1"); ++ TEST_COMPARE (marker1 (), 2); ++ xdlclose (handle); ++ } ++ ++ return 0; ++} ++ ++static void ++prepare (int argc, char **argv) ++{ ++ const char *no_restart = "no-restart"; ++ if (argc == 2 && strcmp (argv[1], no_restart) == 0) ++ return; ++ /* Re-execute the test with an explicit loader invocation. */ ++ execl (support_objdir_elf_ldso, ++ support_objdir_elf_ldso, ++ "--glibc-hwcaps-prepend", "prepend3:prepend2", ++ argv[0], no_restart, ++ NULL); ++ printf ("error: execv of %s failed: %m\n", argv[0]); ++ _exit (1); ++} ++ ++#define PREPARE prepare ++#include +diff --git a/elf/tst-glibc-hwcaps-prepend-cache.root/postclean.req b/elf/tst-glibc-hwcaps-prepend-cache.root/postclean.req +new file mode 100644 +index 0000000000000000..e69de29bb2d1d643 diff --git a/glibc-rh1817513-12.patch b/glibc-rh1817513-12.patch new file mode 100755 index 0000000..b755c39 --- /dev/null +++ b/glibc-rh1817513-12.patch @@ -0,0 +1,38 @@ +commit 2954daf00bb4dc27c69a48e6798d5960ea320741 +Author: Andreas Schwab +Date: Tue Oct 23 09:40:14 2018 +0200 + + Add more checks for valid ld.so.cache file (bug 18093) + +diff --git a/elf/cache.c b/elf/cache.c +index e63979da7d25560c..c4cd825c30e00e8e 100644 +--- a/elf/cache.c ++++ b/elf/cache.c +@@ -199,6 +199,11 @@ print_cache (const char *cache_name) + } + else + { ++ /* Check for corruption, avoiding overflow. */ ++ if ((cache_size - sizeof (struct cache_file)) / sizeof (struct file_entry) ++ < cache->nlibs) ++ error (EXIT_FAILURE, 0, _("File is not a cache file.\n")); ++ + size_t offset = ALIGN_CACHE (sizeof (struct cache_file) + + (cache->nlibs + * sizeof (struct file_entry))); +diff --git a/elf/dl-cache.c b/elf/dl-cache.c +index 6ee5153ff9514872..6dd99a35b9f97cfb 100644 +--- a/elf/dl-cache.c ++++ b/elf/dl-cache.c +@@ -204,7 +204,10 @@ _dl_load_cache_lookup (const char *name) + - only the new format + The following checks if the cache contains any of these formats. */ + if (file != MAP_FAILED && cachesize > sizeof *cache +- && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0) ++ && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0 ++ /* Check for corruption, avoiding overflow. */ ++ && ((cachesize - sizeof *cache) / sizeof (struct file_entry) ++ >= ((struct cache_file *) file)->nlibs)) + { + size_t offset; + /* Looks ok. */ diff --git a/glibc-rh1817513-120.patch b/glibc-rh1817513-120.patch new file mode 100755 index 0000000..6c5d566 --- /dev/null +++ b/glibc-rh1817513-120.patch @@ -0,0 +1,249 @@ +commit f267e1c9dd7fb8852cc32d6eafd96bbcfd5cbb2b +Author: Florian Weimer +Date: Fri Dec 4 09:13:43 2020 +0100 + + x86_64: Add glibc-hwcaps support + + The subdirectories match those in the x86-64 psABI: + + https://gitlab.com/x86-psABIs/x86-64-ABI/-/commit/77566eb03bc6a326811cb7e9a6b9396884b67c7c + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/Makefile b/elf/Makefile +index f67b231c0f8e3aff..7f2fc73877f0a4c8 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -1751,7 +1751,7 @@ $(objpfx)argv0test.out: tst-rtld-argv0.sh $(objpfx)ld.so \ + # glibc-hwcaps mechanism for this architecture). Used to obtain test + # coverage for some glibc-hwcaps tests for the widest possible range + # of systems. +-glibc-hwcaps-first-subdirs-for-tests = ++glibc-hwcaps-first-subdirs-for-tests = x86-64-v2 + + # The test modules are parameterized by preprocessor macros. + LDFLAGS-libmarkermod1-1.so += -Wl,-soname,libmarkermod1.so +diff --git a/elf/tst-glibc-hwcaps-cache.script b/elf/tst-glibc-hwcaps-cache.script +index 6356d152089cdd9a..66d6942402b7233b 100644 +--- a/elf/tst-glibc-hwcaps-cache.script ++++ b/elf/tst-glibc-hwcaps-cache.script +@@ -4,3 +4,13 @@ + cp $B/elf/libmarkermod2-1.so $L/libmarkermod2.so + cp $B/elf/libmarkermod3-1.so $L/libmarkermod3.so + cp $B/elf/libmarkermod4-1.so $L/libmarkermod4.so ++ ++mkdirp 0770 $L/glibc-hwcaps/x86-64-v2 ++cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod2.so ++mkdirp 0770 $L/glibc-hwcaps/x86-64-v3 ++cp $B/elf/libmarkermod3-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod3.so ++cp $B/elf/libmarkermod3-3.so $L/glibc-hwcaps/x86-64-v3/libmarkermod3.so ++mkdirp 0770 $L/glibc-hwcaps/x86-64-v4 ++cp $B/elf/libmarkermod4-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod4.so ++cp $B/elf/libmarkermod4-3.so $L/glibc-hwcaps/x86-64-v3/libmarkermod4.so ++cp $B/elf/libmarkermod4-4.so $L/glibc-hwcaps/x86-64-v4/libmarkermod4.so +diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile +index 42b97c5cc73892cc..d1d7cb9d2eeca9c5 100644 +--- a/sysdeps/x86_64/Makefile ++++ b/sysdeps/x86_64/Makefile +@@ -144,8 +144,47 @@ CFLAGS-tst-auditmod10b.c += $(AVX512-CFLAGS) + CFLAGS-tst-avx512-aux.c += $(AVX512-CFLAGS) + CFLAGS-tst-avx512mod.c += $(AVX512-CFLAGS) + endif ++ ++$(objpfx)tst-glibc-hwcaps: $(objpfx)libmarkermod2-1.so \ ++ $(objpfx)libmarkermod3-1.so $(objpfx)libmarkermod4-1.so ++$(objpfx)tst-glibc-hwcaps.out: \ ++ $(objpfx)libmarkermod2.so \ ++ $(objpfx)glibc-hwcaps/x86-64-v2/libmarkermod2.so \ ++ $(objpfx)libmarkermod3.so \ ++ $(objpfx)glibc-hwcaps/x86-64-v2/libmarkermod3.so \ ++ $(objpfx)glibc-hwcaps/x86-64-v3/libmarkermod3.so \ ++ $(objpfx)libmarkermod4.so \ ++ $(objpfx)glibc-hwcaps/x86-64-v2/libmarkermod4.so \ ++ $(objpfx)glibc-hwcaps/x86-64-v3/libmarkermod4.so \ ++ $(objpfx)glibc-hwcaps/x86-64-v4/libmarkermod4.so \ ++ ++$(objpfx)glibc-hwcaps/x86-64-v2/libmarkermod2.so: $(objpfx)libmarkermod2-2.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/x86-64-v2/libmarkermod3.so: $(objpfx)libmarkermod3-2.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/x86-64-v3/libmarkermod3.so: $(objpfx)libmarkermod3-3.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/x86-64-v2/libmarkermod4.so: $(objpfx)libmarkermod4-2.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/x86-64-v3/libmarkermod4.so: $(objpfx)libmarkermod4-3.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/x86-64-v4/libmarkermod4.so: $(objpfx)libmarkermod4-4.so ++ $(make-target-directory) ++ cp $< $@ ++ ++ifeq (no,$(build-hardcoded-path-in-tests)) ++# This is an ld.so.cache test, and RPATH/RUNPATH in the executable ++# interferes with its test objectives. ++tests-container += tst-glibc-hwcaps-cache + endif + ++endif # $(subdir) == elf ++ + ifeq ($(subdir),csu) + gen-as-const-headers += tlsdesc.sym rtld-offsets.sym + endif +diff --git a/sysdeps/x86_64/dl-hwcaps-subdirs.c b/sysdeps/x86_64/dl-hwcaps-subdirs.c +new file mode 100644 +index 0000000000000000..8810a822efe36962 +--- /dev/null ++++ b/sysdeps/x86_64/dl-hwcaps-subdirs.c +@@ -0,0 +1,66 @@ ++/* Architecture-specific glibc-hwcaps subdirectories. x86 version. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++ ++const char _dl_hwcaps_subdirs[] = "x86-64-v4:x86-64-v3:x86-64-v2"; ++enum { subdirs_count = 3 }; /* Number of components in _dl_hwcaps_subdirs. */ ++ ++uint32_t ++_dl_hwcaps_subdirs_active (void) ++{ ++ int active = 0; ++ ++ /* Test in reverse preference order. */ ++ ++ /* x86-64-v2. */ ++ if (!(CPU_FEATURE_USABLE (CMPXCHG16B) ++ && CPU_FEATURE_USABLE (LAHF64_SAHF64) ++ && CPU_FEATURE_USABLE (POPCNT) ++ && CPU_FEATURE_USABLE (SSE3) ++ && CPU_FEATURE_USABLE (SSE4_1) ++ && CPU_FEATURE_USABLE (SSE4_2) ++ && CPU_FEATURE_USABLE (SSSE3))) ++ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); ++ ++active; ++ ++ /* x86-64-v3. */ ++ if (!(CPU_FEATURE_USABLE (AVX) ++ && CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (BMI1) ++ && CPU_FEATURE_USABLE (BMI2) ++ && CPU_FEATURE_USABLE (F16C) ++ && CPU_FEATURE_USABLE (FMA) ++ && CPU_FEATURE_USABLE (LZCNT) ++ && CPU_FEATURE_USABLE (MOVBE) ++ && CPU_FEATURE_USABLE (OSXSAVE))) ++ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); ++ ++active; ++ ++ /* x86-64-v4. */ ++ if (!(CPU_FEATURE_USABLE (AVX512F) ++ && CPU_FEATURE_USABLE (AVX512BW) ++ && CPU_FEATURE_USABLE (AVX512CD) ++ && CPU_FEATURE_USABLE (AVX512DQ) ++ && CPU_FEATURE_USABLE (AVX512VL))) ++ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); ++ ++active; ++ ++ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); ++} +diff --git a/sysdeps/x86_64/tst-glibc-hwcaps.c b/sysdeps/x86_64/tst-glibc-hwcaps.c +new file mode 100644 +index 0000000000000000..3075a8286dc30768 +--- /dev/null ++++ b/sysdeps/x86_64/tst-glibc-hwcaps.c +@@ -0,0 +1,76 @@ ++/* glibc-hwcaps subdirectory test. x86_64 version. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++extern int marker2 (void); ++extern int marker3 (void); ++extern int marker4 (void); ++ ++/* Return the x86-64-vN level, 1 for the baseline. */ ++static int ++compute_level (void) ++{ ++ const struct cpu_features *cpu_features ++ = __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX); ++ ++ if (!(CPU_FEATURE_USABLE_P (cpu_features, CMPXCHG16B) ++ && CPU_FEATURE_USABLE_P (cpu_features, LAHF64_SAHF64) ++ && CPU_FEATURE_USABLE_P (cpu_features, POPCNT) ++ && CPU_FEATURE_USABLE_P (cpu_features, MMX) ++ && CPU_FEATURE_USABLE_P (cpu_features, SSE) ++ && CPU_FEATURE_USABLE_P (cpu_features, SSE2) ++ && CPU_FEATURE_USABLE_P (cpu_features, SSE3) ++ && CPU_FEATURE_USABLE_P (cpu_features, SSSE3) ++ && CPU_FEATURE_USABLE_P (cpu_features, SSE4_1) ++ && CPU_FEATURE_USABLE_P (cpu_features, SSE4_2))) ++ return 1; ++ if (!(CPU_FEATURE_USABLE_P (cpu_features, AVX) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2) ++ && CPU_FEATURE_USABLE_P (cpu_features, BMI1) ++ && CPU_FEATURE_USABLE_P (cpu_features, BMI2) ++ && CPU_FEATURE_USABLE_P (cpu_features, F16C) ++ && CPU_FEATURE_USABLE_P (cpu_features, FMA) ++ && CPU_FEATURE_USABLE_P (cpu_features, LZCNT) ++ && CPU_FEATURE_USABLE_P (cpu_features, MOVBE) ++ && CPU_FEATURE_USABLE_P (cpu_features, OSXSAVE))) ++ return 2; ++ if (!(CPU_FEATURE_USABLE_P (cpu_features, AVX512F) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX512CD) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX512DQ) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX512VL))) ++ return 3; ++ return 4; ++} ++ ++static int ++do_test (void) ++{ ++ int level = compute_level (); ++ printf ("info: detected x86-64 micro-architecture level: %d\n", level); ++ TEST_COMPARE (marker2 (), MIN (level, 2)); ++ TEST_COMPARE (marker3 (), MIN (level, 3)); ++ TEST_COMPARE (marker4 (), MIN (level, 4)); ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1817513-121.patch b/glibc-rh1817513-121.patch new file mode 100755 index 0000000..5280b4b --- /dev/null +++ b/glibc-rh1817513-121.patch @@ -0,0 +1,21 @@ +commit 4f4bd9e47ba98ccfeeaa8c600c0b0c8bbabcebb3 +Author: Matheus Castanho +Date: Fri Dec 4 09:48:56 2020 -0300 + + elf: Add missing header to elf/dl-hwcaps.h + + The lack of this header makes size_t unavailable on builds configured + with --disable-tunables, causing compilation errors. + +diff --git a/elf/dl-hwcaps.h b/elf/dl-hwcaps.h +index 769ecab3f886c6c4..9a34088c17e97d7f 100644 +--- a/elf/dl-hwcaps.h ++++ b/elf/dl-hwcaps.h +@@ -20,6 +20,7 @@ + #define _DL_HWCAPS_H + + #include ++#include + + #include + diff --git a/glibc-rh1817513-122.patch b/glibc-rh1817513-122.patch new file mode 100755 index 0000000..bc3388d --- /dev/null +++ b/glibc-rh1817513-122.patch @@ -0,0 +1,20 @@ +commit 2976082a385a7fb3d0294c6acf745b4f93e834ee +Author: H.J. Lu +Date: Thu Dec 3 15:02:44 2020 -0800 + + x86: Set RDRAND usable if CPU supports RDRAND + + Set RDRAND usable if CPU supports RDRAND. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 4c9c15a44b618fed..805d00a43309fc23 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -85,6 +85,7 @@ update_usable (struct cpu_features *cpu_features) + CPU_FEATURE_SET_USABLE (cpu_features, WAITPKG); + CPU_FEATURE_SET_USABLE (cpu_features, GFNI); + CPU_FEATURE_SET_USABLE (cpu_features, RDPID); ++ CPU_FEATURE_SET_USABLE (cpu_features, RDRAND); + CPU_FEATURE_SET_USABLE (cpu_features, CLDEMOTE); + CPU_FEATURE_SET_USABLE (cpu_features, MOVDIRI); + CPU_FEATURE_SET_USABLE (cpu_features, MOVDIR64B); diff --git a/glibc-rh1817513-123.patch b/glibc-rh1817513-123.patch new file mode 100755 index 0000000..1aa9cb7 --- /dev/null +++ b/glibc-rh1817513-123.patch @@ -0,0 +1,65 @@ +commit 93fda28693f0d9060b0aa71eeacaacfe9f16896e +Author: H.J. Lu +Date: Thu Dec 3 15:02:44 2020 -0800 + + x86: Adjust tst-cpu-features-supports.c for GCC 11 + + Check HAS_CPU_FEATURE instead of CPU_FEATURE_USABLE for FSGSBASE, IBT, + LM, SHSTK and XSAVES since FSGSBASE requires kernel support, IBT/SHSTK/LM + require OS support and XSAVES is supervisor-mode only. + +diff --git a/sysdeps/x86/tst-cpu-features-supports.c b/sysdeps/x86/tst-cpu-features-supports.c +index bf881b531f4bc2ed..287cf01fbdfaeda1 100644 +--- a/sysdeps/x86/tst-cpu-features-supports.c ++++ b/sysdeps/x86/tst-cpu-features-supports.c +@@ -40,6 +40,11 @@ check_supports (int supports, int usable, const char *supports_name, + #define CHECK_SUPPORTS(str, name) \ + check_supports (__builtin_cpu_supports (#str), \ + CPU_FEATURE_USABLE (name), \ ++ #str, "CPU_FEATURE_USABLE (" #name ")"); ++ ++#define CHECK_CPU_SUPPORTS(str, name) \ ++ check_supports (__builtin_cpu_supports (#str), \ ++ HAS_CPU_FEATURE (name), \ + #str, "HAS_CPU_FEATURE (" #name ")"); + + static int +@@ -118,7 +123,7 @@ do_test (int argc, char **argv) + fails += CHECK_SUPPORTS (fma4, FMA4); + #endif + #if __GNUC_PREREQ (11, 0) +- fails += CHECK_SUPPORTS (fsgsbase, FSGSBASE); ++ fails += CHECK_CPU_SUPPORTS (fsgsbase, FSGSBASE); + fails += CHECK_SUPPORTS (fxsave, FXSR); + #endif + #if __GNUC_PREREQ (8, 0) +@@ -126,9 +131,9 @@ do_test (int argc, char **argv) + #endif + #if __GNUC_PREREQ (11, 0) + fails += CHECK_SUPPORTS (hle, HLE); +- fails += CHECK_SUPPORTS (ibt, IBT); ++ fails += CHECK_CPU_SUPPORTS (ibt, IBT); + fails += CHECK_SUPPORTS (lahf_lm, LAHF64_SAHF64); +- fails += CHECK_SUPPORTS (lm, LM); ++ fails += CHECK_CPU_SUPPORTS (lm, LM); + fails += CHECK_SUPPORTS (lwp, LWP); + fails += CHECK_SUPPORTS (lzcnt, LZCNT); + #endif +@@ -150,7 +155,7 @@ do_test (int argc, char **argv) + fails += CHECK_SUPPORTS (rtm, RTM); + fails += CHECK_SUPPORTS (serialize, SERIALIZE); + fails += CHECK_SUPPORTS (sha, SHA); +- fails += CHECK_SUPPORTS (shstk, SHSTK); ++ fails += CHECK_CPU_SUPPORTS (shstk, SHSTK); + #endif + fails += CHECK_SUPPORTS (sse, SSE); + fails += CHECK_SUPPORTS (sse2, SSE2); +@@ -180,7 +185,7 @@ do_test (int argc, char **argv) + fails += CHECK_SUPPORTS (xsave, XSAVE); + fails += CHECK_SUPPORTS (xsavec, XSAVEC); + fails += CHECK_SUPPORTS (xsaveopt, XSAVEOPT); +- fails += CHECK_SUPPORTS (xsaves, XSAVES); ++ fails += CHECK_CPU_SUPPORTS (xsaves, XSAVES); + #endif + + printf ("%d differences between __builtin_cpu_supports and glibc code.\n", diff --git a/glibc-rh1817513-124.patch b/glibc-rh1817513-124.patch new file mode 100755 index 0000000..ec9e96d --- /dev/null +++ b/glibc-rh1817513-124.patch @@ -0,0 +1,187 @@ +commit 4c38c1a229bc3628269ad98bd7e8d31d118d91f6 +Author: Florian Weimer +Date: Fri Dec 4 09:13:43 2020 +0100 + + powerpc64le: Add glibc-hwcaps support + + The "power10" and "power9" subdirectories are selected in a way + that matches the -mcpu=power10 and -mcpu=power9 options of GCC. + +diff --git a/elf/Makefile b/elf/Makefile +index 7f2fc73877f0a4c8..57e3a8982297f79a 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -1751,7 +1751,7 @@ $(objpfx)argv0test.out: tst-rtld-argv0.sh $(objpfx)ld.so \ + # glibc-hwcaps mechanism for this architecture). Used to obtain test + # coverage for some glibc-hwcaps tests for the widest possible range + # of systems. +-glibc-hwcaps-first-subdirs-for-tests = x86-64-v2 ++glibc-hwcaps-first-subdirs-for-tests = power9 x86-64-v2 + + # The test modules are parameterized by preprocessor macros. + LDFLAGS-libmarkermod1-1.so += -Wl,-soname,libmarkermod1.so +diff --git a/elf/tst-glibc-hwcaps-cache.script b/elf/tst-glibc-hwcaps-cache.script +index 66d6942402b7233b..6a4675f9bd30e02f 100644 +--- a/elf/tst-glibc-hwcaps-cache.script ++++ b/elf/tst-glibc-hwcaps-cache.script +@@ -5,6 +5,12 @@ cp $B/elf/libmarkermod2-1.so $L/libmarkermod2.so + cp $B/elf/libmarkermod3-1.so $L/libmarkermod3.so + cp $B/elf/libmarkermod4-1.so $L/libmarkermod4.so + ++mkdirp 0770 $L/glibc-hwcaps/power9 ++cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/power9/libmarkermod2.so ++mkdirp 0770 $L/glibc-hwcaps/power10 ++cp $B/elf/libmarkermod3-2.so $L/glibc-hwcaps/power9/libmarkermod3.so ++cp $B/elf/libmarkermod3-3.so $L/glibc-hwcaps/power10/libmarkermod3.so ++ + mkdirp 0770 $L/glibc-hwcaps/x86-64-v2 + cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod2.so + mkdirp 0770 $L/glibc-hwcaps/x86-64-v3 +diff --git a/sysdeps/powerpc/powerpc64/le/Makefile b/sysdeps/powerpc/powerpc64/le/Makefile +index f59db1ca3c8ed454..7a4be6bfef729914 100644 +--- a/sysdeps/powerpc/powerpc64/le/Makefile ++++ b/sysdeps/powerpc/powerpc64/le/Makefile +@@ -82,3 +82,31 @@ CFLAGS-printf_fp.c = -mfloat128 + CFLAGS-printf_fphex.c = -mfloat128 + CFLAGS-printf_size.c = -mfloat128 + endif ++ ++ifeq ($(subdir),elf) ++$(objpfx)tst-glibc-hwcaps: \ ++ $(objpfx)libmarkermod2-1.so $(objpfx)libmarkermod3-1.so ++$(objpfx)tst-glibc-hwcaps.out: \ ++ $(objpfx)libmarkermod2.so \ ++ $(objpfx)glibc-hwcaps/power9/libmarkermod2.so \ ++ $(objpfx)libmarkermod3.so \ ++ $(objpfx)glibc-hwcaps/power9/libmarkermod3.so \ ++ $(objpfx)glibc-hwcaps/power10/libmarkermod3.so \ ++ ++$(objpfx)glibc-hwcaps/power9/libmarkermod2.so: $(objpfx)libmarkermod2-2.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/power9/libmarkermod3.so: $(objpfx)libmarkermod3-2.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/power10/libmarkermod3.so: $(objpfx)libmarkermod3-3.so ++ $(make-target-directory) ++ cp $< $@ ++ ++ifeq (no,$(build-hardcoded-path-in-tests)) ++# This is an ld.so.cache test, and RPATH/RUNPATH in the executable ++# interferes with its test objectives. ++tests-container += tst-glibc-hwcaps-cache ++endif ++ ++endif # $(subdir) == elf +diff --git a/sysdeps/powerpc/powerpc64/le/dl-hwcaps-subdirs.c b/sysdeps/powerpc/powerpc64/le/dl-hwcaps-subdirs.c +new file mode 100644 +index 0000000000000000..6a21d77649f44dd4 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/dl-hwcaps-subdirs.c +@@ -0,0 +1,46 @@ ++/* Architecture-specific glibc-hwcaps subdirectories. powerpc64le version. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++ ++const char _dl_hwcaps_subdirs[] = "power10:power9"; ++enum { subdirs_count = 2 }; /* Number of components in _dl_hwcaps_subdirs. */ ++ ++uint32_t ++_dl_hwcaps_subdirs_active (void) ++{ ++ int active = 0; ++ ++ /* Test in reverse preference order. Altivec and VSX are implied by ++ the powerpc64le ABI definition. */ ++ ++ /* POWER9. GCC enables float128 hardware support for -mcpu=power9. */ ++ if ((GLRO (dl_hwcap2) & PPC_FEATURE2_ARCH_3_00) == 0 ++ || (GLRO (dl_hwcap2) & PPC_FEATURE2_HAS_IEEE128) == 0) ++ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); ++ ++active; ++ ++ /* POWER10. GCC defines __MMA__ for -mcpu=power10. */ ++ if ((GLRO (dl_hwcap2) & PPC_FEATURE2_ARCH_3_1) == 0 ++ || (GLRO (dl_hwcap2) & PPC_FEATURE2_MMA) == 0) ++ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); ++ ++active; ++ ++ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); ++} +diff --git a/sysdeps/powerpc/powerpc64/le/tst-glibc-hwcaps.c b/sysdeps/powerpc/powerpc64/le/tst-glibc-hwcaps.c +new file mode 100644 +index 0000000000000000..e510fca80a22aaeb +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/tst-glibc-hwcaps.c +@@ -0,0 +1,54 @@ ++/* glibc-hwcaps subdirectory test. powerpc64le version. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++extern int marker2 (void); ++extern int marker3 (void); ++ ++/* Return the POWER level, 8 for the baseline. */ ++static int ++compute_level (void) ++{ ++ const char *platform = (const char *) getauxval (AT_PLATFORM); ++ if (strcmp (platform, "power8") == 0) ++ return 8; ++ if (strcmp (platform, "power9") == 0) ++ return 9; ++ if (strcmp (platform, "power10") == 0) ++ return 10; ++ printf ("warning: unrecognized AT_PLATFORM value: %s\n", platform); ++ /* Assume that the new platform supports POWER10. */ ++ return 10; ++} ++ ++static int ++do_test (void) ++{ ++ int level = compute_level (); ++ printf ("info: detected POWER level: %d\n", level); ++ TEST_COMPARE (marker2 (), MIN (level - 7, 2)); ++ TEST_COMPARE (marker3 (), MIN (level - 7, 3)); ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1817513-125.patch b/glibc-rh1817513-125.patch new file mode 100755 index 0000000..648b205 --- /dev/null +++ b/glibc-rh1817513-125.patch @@ -0,0 +1,21 @@ +commit 0d4ed9d40efa84e8dc88e64cf337c8e95af7b045 +Author: Florian Weimer +Date: Wed Dec 9 18:56:14 2020 +0100 + + elf: Fix incorrect comparison in sort_priorities_by_name + + Reported-By: Stefan Liebler + +diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c +index 098173a84c43c1fd..50d764ae8707f46d 100644 +--- a/elf/dl-hwcaps.c ++++ b/elf/dl-hwcaps.c +@@ -153,7 +153,7 @@ sort_priorities_by_name (void) + else + to_compare = previous->name_length; + int cmp = memcmp (current->name, previous->name, to_compare); +- if (cmp >= 0 ++ if (cmp > 0 + || (cmp == 0 && current->name_length >= previous->name_length)) + break; + diff --git a/glibc-rh1817513-126.patch b/glibc-rh1817513-126.patch new file mode 100755 index 0000000..6d04ee2 --- /dev/null +++ b/glibc-rh1817513-126.patch @@ -0,0 +1,25 @@ +commit 1bb8d05b9c751f6909e85ee96f6c78d536987bfd +Author: Florian Weimer +Date: Thu Dec 10 12:24:53 2020 +0100 + + elf: Fix run-time dependencies of tst-dlopen-fail-2 + + The misattributed dependencies can cause failures in parallel testing + if the dependencies have not been built yet. + + Fixes commit a332bd1518af518c984fad73eba6f46dc5b2b2d4 + ("elf: Add elf/tst-dlopenfail-2 [BZ #25396]"). + +diff --git a/elf/Makefile b/elf/Makefile +index 57e3a8982297f79a..63c61ad63677ec63 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -1655,7 +1655,7 @@ $(objpfx)tst-dlopenfailmod1.so: \ + LDFLAGS-tst-dlopenfaillinkmod.so = -Wl,-soname,tst-dlopenfail-missingmod.so + $(objpfx)tst-dlopenfailmod2.so: $(shared-thread-library) + $(objpfx)tst-dlopenfail-2: $(libdl) +-$(objpfx)tst-dlopenfail.out: \ ++$(objpfx)tst-dlopenfail-2.out: \ + $(objpfx)tst-dlopenfailmod1.so $(objpfx)tst-dlopenfailmod2.so \ + $(objpfx)tst-dlopenfailmod3.so + diff --git a/glibc-rh1817513-127.patch b/glibc-rh1817513-127.patch new file mode 100755 index 0000000..892276f --- /dev/null +++ b/glibc-rh1817513-127.patch @@ -0,0 +1,241 @@ +commit fdf8fbca455ca3ef57235bde907bcc6a624ac5aa +Author: Florian Weimer +Date: Thu Dec 10 13:51:18 2020 +0100 + + s390x: Add glibc-hwcaps support + + Subdirectories z13, z14, z15 can be selected, mostly based on the + level of support for vector instructions. + + Co-Authored-By: Stefan Liebler + +diff --git a/elf/Makefile b/elf/Makefile +index 63c61ad63677ec63..67029930dd2cb461 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -1751,7 +1751,7 @@ $(objpfx)argv0test.out: tst-rtld-argv0.sh $(objpfx)ld.so \ + # glibc-hwcaps mechanism for this architecture). Used to obtain test + # coverage for some glibc-hwcaps tests for the widest possible range + # of systems. +-glibc-hwcaps-first-subdirs-for-tests = power9 x86-64-v2 ++glibc-hwcaps-first-subdirs-for-tests = power9 x86-64-v2 z13 + + # The test modules are parameterized by preprocessor macros. + LDFLAGS-libmarkermod1-1.so += -Wl,-soname,libmarkermod1.so +diff --git a/elf/tst-glibc-hwcaps-cache.script b/elf/tst-glibc-hwcaps-cache.script +index 6a4675f9bd30e02f..c3271f61f9e50f2e 100644 +--- a/elf/tst-glibc-hwcaps-cache.script ++++ b/elf/tst-glibc-hwcaps-cache.script +@@ -11,6 +11,16 @@ mkdirp 0770 $L/glibc-hwcaps/power10 + cp $B/elf/libmarkermod3-2.so $L/glibc-hwcaps/power9/libmarkermod3.so + cp $B/elf/libmarkermod3-3.so $L/glibc-hwcaps/power10/libmarkermod3.so + ++mkdirp 0770 $L/glibc-hwcaps/z13 ++cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/z13/libmarkermod2.so ++mkdirp 0770 $L/glibc-hwcaps/z14 ++cp $B/elf/libmarkermod3-2.so $L/glibc-hwcaps/z13/libmarkermod3.so ++cp $B/elf/libmarkermod3-3.so $L/glibc-hwcaps/z14/libmarkermod3.so ++mkdirp 0770 $L/glibc-hwcaps/z15 ++cp $B/elf/libmarkermod4-2.so $L/glibc-hwcaps/z13/libmarkermod4.so ++cp $B/elf/libmarkermod4-3.so $L/glibc-hwcaps/z14/libmarkermod4.so ++cp $B/elf/libmarkermod4-4.so $L/glibc-hwcaps/z15/libmarkermod4.so ++ + mkdirp 0770 $L/glibc-hwcaps/x86-64-v2 + cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod2.so + mkdirp 0770 $L/glibc-hwcaps/x86-64-v3 +diff --git a/sysdeps/s390/s390-64/Makefile b/sysdeps/s390/s390-64/Makefile +index b4d793bb3dd1f703..e5da26871c862e63 100644 +--- a/sysdeps/s390/s390-64/Makefile ++++ b/sysdeps/s390/s390-64/Makefile +@@ -6,4 +6,43 @@ ifeq ($(subdir),elf) + CFLAGS-rtld.c += -Wno-uninitialized -Wno-unused + CFLAGS-dl-load.c += -Wno-unused + CFLAGS-dl-reloc.c += -Wno-unused ++ ++$(objpfx)tst-glibc-hwcaps: $(objpfx)libmarkermod2-1.so \ ++ $(objpfx)libmarkermod3-1.so $(objpfx)libmarkermod4-1.so ++$(objpfx)tst-glibc-hwcaps.out: \ ++ $(objpfx)libmarkermod2.so \ ++ $(objpfx)glibc-hwcaps/z13/libmarkermod2.so \ ++ $(objpfx)libmarkermod3.so \ ++ $(objpfx)glibc-hwcaps/z13/libmarkermod3.so \ ++ $(objpfx)glibc-hwcaps/z14/libmarkermod3.so \ ++ $(objpfx)libmarkermod4.so \ ++ $(objpfx)glibc-hwcaps/z13/libmarkermod4.so \ ++ $(objpfx)glibc-hwcaps/z14/libmarkermod4.so \ ++ $(objpfx)glibc-hwcaps/z15/libmarkermod4.so \ ++ ++$(objpfx)glibc-hwcaps/z13/libmarkermod2.so: $(objpfx)libmarkermod2-2.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/z13/libmarkermod3.so: $(objpfx)libmarkermod3-2.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/z14/libmarkermod3.so: $(objpfx)libmarkermod3-3.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/z13/libmarkermod4.so: $(objpfx)libmarkermod4-2.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/z14/libmarkermod4.so: $(objpfx)libmarkermod4-3.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/z15/libmarkermod4.so: $(objpfx)libmarkermod4-4.so ++ $(make-target-directory) ++ cp $< $@ ++ ++ifeq (no,$(build-hardcoded-path-in-tests)) ++# This is an ld.so.cache test, and RPATH/RUNPATH in the executable ++# interferes with its test objectives. ++tests-container += tst-glibc-hwcaps-cache + endif ++ ++endif # $(subdir) == elf +diff --git a/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c b/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c +new file mode 100644 +index 0000000000000000..3673808a458350ad +--- /dev/null ++++ b/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c +@@ -0,0 +1,54 @@ ++/* Architecture-specific glibc-hwcaps subdirectories. s390x version. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++ ++const char _dl_hwcaps_subdirs[] = "z15:z14:z13"; ++enum { subdirs_count = 3 }; /* Number of components in _dl_hwcaps_subdirs. */ ++ ++uint32_t ++_dl_hwcaps_subdirs_active (void) ++{ ++ int active = 0; ++ ++ /* Test in reverse preference order. */ ++ ++ /* z13. */ ++ if (!(GLRO (dl_hwcap) & HWCAP_S390_VX)) ++ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); ++ ++active; ++ ++ /* z14. */ ++ if (!((GLRO (dl_hwcap) & HWCAP_S390_VXD) ++ && (GLRO (dl_hwcap) & HWCAP_S390_VXE) ++ && (GLRO (dl_hwcap) & HWCAP_S390_GS))) ++ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); ++ ++active; ++ ++ /* z15. ++ Note: We do not list HWCAP_S390_SORT and HWCAP_S390_DFLT here as, ++ according to the Principles of Operation, those may be replaced or removed ++ in future. */ ++ if (!((GLRO (dl_hwcap) & HWCAP_S390_VXRS_EXT2) ++ && (GLRO (dl_hwcap) & HWCAP_S390_VXRS_PDE))) ++ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); ++ ++active; ++ ++ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); ++} +diff --git a/sysdeps/s390/s390-64/tst-glibc-hwcaps.c b/sysdeps/s390/s390-64/tst-glibc-hwcaps.c +new file mode 100644 +index 0000000000000000..690f0d5fab36eb59 +--- /dev/null ++++ b/sysdeps/s390/s390-64/tst-glibc-hwcaps.c +@@ -0,0 +1,82 @@ ++/* glibc-hwcaps subdirectory test. s390x version. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++extern int marker2 (void); ++extern int marker3 (void); ++extern int marker4 (void); ++ ++/* Return the arch level, 10 for the baseline libmarkermod*.so's. */ ++static int ++compute_level (void) ++{ ++ const char *platform = (const char *) getauxval (AT_PLATFORM); ++ ++ /* The arch* versions refer to the edition of the Principles of ++ Operation, and they are off by two when compared with the recent ++ product names. (The code below should not be considered an ++ accurate mapping to Principles of Operation editions for earlier ++ AT_PLATFORM strings). */ ++ if (strcmp (platform, "z900") == 0) ++ return 10; ++ if (strcmp (platform, "z990") == 0) ++ return 10; ++ if (strcmp (platform, "z9-109") == 0) ++ return 10; ++ if (strcmp (platform, "z10") == 0) ++ return 10; ++ if (strcmp (platform, "z196") == 0) ++ return 10; ++ if (strcmp (platform, "zEC12") == 0) ++ return 10; ++ ++ /* If we are running on z13 or newer and the kernel was booted with novx, ++ then AT_PLATFORM is z13 or newer, but _dl_hwcaps_subdirs_active will ++ return zero and the _dl_hwcaps_subdirs are not searched. */ ++ const unsigned long int hwcap = getauxval (AT_HWCAP); ++ if ((hwcap & HWCAP_S390_VX) == 0) ++ return 10; ++ ++ if (strcmp (platform, "z13") == 0) ++ return 11; ++ if (strcmp (platform, "z14") == 0) ++ return 12; ++ if (strcmp (platform, "z15") == 0) ++ return 13; ++ printf ("warning: unrecognized AT_PLATFORM value: %s\n", platform); ++ /* Assume that the new platform supports z15. */ ++ return 13; ++} ++ ++static int ++do_test (void) ++{ ++ int level = compute_level (); ++ printf ("info: detected architecture level: arch%d\n", level); ++ TEST_COMPARE (marker2 (), MIN (level - 9, 2)); ++ TEST_COMPARE (marker3 (), MIN (level - 9, 3)); ++ TEST_COMPARE (marker4 (), MIN (level - 9, 4)); ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1817513-128.patch b/glibc-rh1817513-128.patch new file mode 100755 index 0000000..a6a4106 --- /dev/null +++ b/glibc-rh1817513-128.patch @@ -0,0 +1,83 @@ +commit 97476447edff96e526daa1a22d6ed3665181ff93 +Author: DJ Delorie +Date: Wed Oct 23 17:52:26 2019 -0400 + + Install charmaps uncompressed in testroot + + The testroot does not have a gunzip command, so the charmap files + should not be installed gzipped else they cannot be used (and thus + tested). With this patch, installing with INSTALL_UNCOMPRESSED=yes + installs uncompressed charmaps instead. + + Note that we must purge the $(symbolic_link_list) as it contains + references to $(DESTDIR), which we change during the testroot + installation. + + Reviewed-by: Carlos O'Donell + +diff --git a/Makefile b/Makefile +index 3748d6f7cfb6223b..6d73241bbc811c13 100644 +--- a/Makefile ++++ b/Makefile +@@ -398,8 +398,15 @@ ifeq ($(run-built-tests),yes) + $(test-wrapper) cp $$dso $(objpfx)testroot.pristine$$dso ;\ + done + endif ++ # $(symbolic-link-list) is a file that encodes $(DESTDIR) so we ++ # have to purge it ++ rm -f $(symbolic-link-list) ++ # Setting INSTALL_UNCOMPRESSED causes localedata/Makefile to ++ # install the charmaps uncompressed, as the testroot does not ++ # provide a gunzip program. + $(MAKE) install DESTDIR=$(objpfx)testroot.pristine \ +- subdirs='$(sorted-subdirs)' ++ INSTALL_UNCOMPRESSED=yes subdirs='$(sorted-subdirs)' ++ rm -f $(symbolic-link-list) + touch $(objpfx)testroot.pristine/install.stamp + + tests-special-notdir = $(patsubst $(objpfx)%, %, $(tests-special)) +diff --git a/localedata/Makefile b/localedata/Makefile +index 0fed95dcae6a9183..14fcc37fed21e740 100644 +--- a/localedata/Makefile ++++ b/localedata/Makefile +@@ -167,9 +167,17 @@ endif + endif + + # Files to install. ++ifeq ($(INSTALL_UNCOMPRESSED),yes) ++# This option is for testing inside the testroot container, as the ++# container does not include a working gunzip program. ++install-others := $(addprefix $(inst_i18ndir)/, \ ++ $(charmaps) \ ++ $(locales)) ++else + install-others := $(addprefix $(inst_i18ndir)/, \ + $(addsuffix .gz, $(charmaps)) \ + $(locales)) ++endif + + tests: $(objdir)/iconvdata/gconv-modules + +@@ -282,12 +290,22 @@ endif + + include ../Rules + ++ifeq ($(INSTALL_UNCOMPRESSED),yes) ++# Install the charmap files as-is. This option is for testing inside ++# the testroot container, as the container does not include a working ++# gunzip program. ++$(inst_i18ndir)/charmaps/%: charmaps/% $(+force) ++ $(make-target-directory) ++ rm -f $@ ++ $(INSTALL_DATA) $< $@ ++else + # Install the charmap files in gzipped format. + $(inst_i18ndir)/charmaps/%.gz: charmaps/% $(+force) + $(make-target-directory) + rm -f $(@:.gz=) $@ + $(INSTALL_DATA) $< $(@:.gz=) + gzip -9n $(@:.gz=) ++endif + + # Install the locale source files in the appropriate directory. + $(inst_i18ndir)/locales/%: locales/% $(+force); $(do-install) diff --git a/glibc-rh1817513-129.patch b/glibc-rh1817513-129.patch new file mode 100755 index 0000000..b34711e --- /dev/null +++ b/glibc-rh1817513-129.patch @@ -0,0 +1,121 @@ +commit de42613540de8d3d70b5f14a14923cab7bd694d0 +Author: Florian Weimer +Date: Mon May 25 18:17:27 2020 +0200 + + elf: Turn _dl_printf, _dl_error_printf, _dl_fatal_printf into functions + + This change makes it easier to set a breakpoint on these calls. + + This also addresses the issue that including without + does not result usable _dl_*printf macros because of the + use of the STD*_FILENO macros there. + + (The private symbol for _dl_fatal_printf will go away again + once the exception handling implementation is unified between + libc and ld.so.) + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/Versions b/elf/Versions +index 3be879c4adfa74c7..be88c48e6d45a937 100644 +--- a/elf/Versions ++++ b/elf/Versions +@@ -58,7 +58,7 @@ ld { + _dl_allocate_tls; _dl_allocate_tls_init; + _dl_argv; _dl_find_dso_for_object; _dl_get_tls_static_info; + _dl_deallocate_tls; _dl_make_stack_executable; +- _dl_rtld_di_serinfo; _dl_starting_up; ++ _dl_rtld_di_serinfo; _dl_starting_up; _dl_fatal_printf; + _rtld_global; _rtld_global_ro; + + # Only here for gdb while a better method is developed. +diff --git a/elf/dl-misc.c b/elf/dl-misc.c +index 3f28de3ee9d68368..508630e444d2a00c 100644 +--- a/elf/dl-misc.c ++++ b/elf/dl-misc.c +@@ -302,6 +302,37 @@ _dl_dprintf (int fd, const char *fmt, ...) + va_end (arg); + } + ++void ++_dl_printf (const char *fmt, ...) ++{ ++ va_list arg; ++ ++ va_start (arg, fmt); ++ _dl_debug_vdprintf (STDOUT_FILENO, 0, fmt, arg); ++ va_end (arg); ++} ++ ++void ++_dl_error_printf (const char *fmt, ...) ++{ ++ va_list arg; ++ ++ va_start (arg, fmt); ++ _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg); ++ va_end (arg); ++} ++ ++void ++_dl_fatal_printf (const char *fmt, ...) ++{ ++ va_list arg; ++ ++ va_start (arg, fmt); ++ _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg); ++ va_end (arg); ++ _exit (127); ++} ++rtld_hidden_def (_dl_fatal_printf) + + /* Test whether given NAME matches any of the names of the given object. */ + int +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 77923499d3de4366..6cbbaa808a596f77 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -762,24 +762,19 @@ ssize_t _dl_write (int fd, const void *buffer, size_t length) + + /* Write a message on the specified descriptor standard output. The + parameters are interpreted as for a `printf' call. */ +-#define _dl_printf(fmt, args...) \ +- _dl_dprintf (STDOUT_FILENO, fmt, ##args) ++void _dl_printf (const char *fmt, ...) ++ attribute_hidden __attribute__ ((__format__ (__printf__, 1, 2))); + + /* Write a message on the specified descriptor standard error. The + parameters are interpreted as for a `printf' call. */ +-#define _dl_error_printf(fmt, args...) \ +- _dl_dprintf (STDERR_FILENO, fmt, ##args) ++void _dl_error_printf (const char *fmt, ...) ++ attribute_hidden __attribute__ ((__format__ (__printf__, 1, 2))); + + /* Write a message on the specified descriptor standard error and exit + the program. The parameters are interpreted as for a `printf' call. */ +-#define _dl_fatal_printf(fmt, args...) \ +- do \ +- { \ +- _dl_dprintf (STDERR_FILENO, fmt, ##args); \ +- _exit (127); \ +- } \ +- while (1) +- ++void _dl_fatal_printf (const char *fmt, ...) ++ __attribute__ ((__format__ (__printf__, 1, 2), __noreturn__)); ++rtld_hidden_proto (_dl_fatal_printf) + + /* An exception raised by the _dl_signal_error function family and + caught by _dl_catch_error function family. Exceptions themselves +diff --git a/sysdeps/mach/hurd/i386/localplt.data b/sysdeps/mach/hurd/i386/localplt.data +index 4b9dbf5acc088cff..eb79216e3b494486 100644 +--- a/sysdeps/mach/hurd/i386/localplt.data ++++ b/sysdeps/mach/hurd/i386/localplt.data +@@ -43,6 +43,7 @@ ld.so: _dl_allocate_tls_init + ld.so: _dl_exception_create + ld.so: _dl_exception_create_format + ld.so: _dl_exception_free ++ld.so: _dl_fatal_printf + ld.so: _dl_find_dso_for_object + ld.so: _dl_init_first + ld.so: _dl_mcount diff --git a/glibc-rh1817513-13.patch b/glibc-rh1817513-13.patch new file mode 100755 index 0000000..6267bb6 --- /dev/null +++ b/glibc-rh1817513-13.patch @@ -0,0 +1,199 @@ +commit a5275ba5378c9256d18e582572b4315e8edfcbfb +Author: H.J. Lu +Date: Thu Nov 29 14:15:01 2018 -0800 + + _dl_exception_create_format: Support %x/%lx/%zx + + Add support for %x, %lx and %zx to _dl_exception_create_format and pad + to the full width with 0. + + * elf/Makefile (tests-internal): Add tst-create_format1. + * elf/dl-exception.c (_dl_exception_create_format): Support + %x, %lx and %zx. + * elf/tst-create_format1.c: New file. + +Conflicts: + elf/Makefile + (Different backport order of tests.) + +diff --git a/elf/Makefile b/elf/Makefile +index 89dff92adfc417f5..6d1962b2e4deb871 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -198,7 +198,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ + tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \ +- tst-ptrguard1 tst-stackguard1 tst-libc_dlvsym ++ 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 +diff --git a/elf/dl-exception.c b/elf/dl-exception.c +index 1c63e4a3a65b6d55..1e41d89a7db52683 100644 +--- a/elf/dl-exception.c ++++ b/elf/dl-exception.c +@@ -111,6 +111,20 @@ _dl_exception_create_format (struct dl_exception *exception, const char *objname + case 's': + length += strlen (va_arg (ap, const char *)); + break; ++ /* Recognize the l modifier. It is only important on some ++ platforms where long and int have a different size. We ++ can use the same code for size_t. */ ++ case 'l': ++ case 'z': ++ if (p[1] == 'x') ++ { ++ length += LONG_WIDTH / 4; ++ ++p; ++ break; ++ } ++ case 'x': ++ length += INT_WIDTH / 4; ++ break; + default: + /* Assumed to be '%'. */ + ++length; +@@ -167,6 +181,32 @@ _dl_exception_create_format (struct dl_exception *exception, const char *objname + *wptr = '%'; + ++wptr; + break; ++ case 'x': ++ { ++ unsigned long int num = va_arg (ap, unsigned int); ++ char *start = wptr; ++ wptr += INT_WIDTH / 4; ++ char *cp = _itoa (num, wptr, 16, 0); ++ /* Pad to the full width with 0. */ ++ while (cp != start) ++ *--cp = '0'; ++ } ++ break; ++ case 'l': ++ case 'z': ++ if (p[1] == 'x') ++ { ++ unsigned long int num = va_arg (ap, unsigned long int); ++ char *start = wptr; ++ wptr += LONG_WIDTH / 4; ++ char *cp = _itoa (num, wptr, 16, 0); ++ /* Pad to the full width with 0. */ ++ while (cp != start) ++ *--cp = '0'; ++ ++p; ++ break; ++ } ++ /* FALLTHROUGH */ + default: + _dl_fatal_printf ("Fatal error:" + " invalid format in exception string\n"); +diff --git a/elf/tst-create_format1.c b/elf/tst-create_format1.c +new file mode 100644 +index 0000000000000000..8b9edfdc69ea4ced +--- /dev/null ++++ b/elf/tst-create_format1.c +@@ -0,0 +1,103 @@ ++/* Check _dl_exception_create_format. ++ Copyright (C) 2018 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 ++ . */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define TEST(es, objn, fmt, ...) \ ++ ({ \ ++ struct dl_exception exception; \ ++ _dl_exception_create_format (&exception, objn, fmt, __VA_ARGS__); \ ++ TEST_COMPARE_STRING (exception.objname, objn == NULL ? "" : objn); \ ++ TEST_COMPARE_STRING (exception.errstring, es); \ ++ _dl_exception_free (&exception); \ ++ }) ++ ++static void ++do_test_invalid_conversion (void *closure) ++{ ++ TEST ("(null)", NULL, "%p", NULL); ++} ++ ++/* Exit status after abnormal termination. */ ++static int invalid_status; ++ ++static void ++init_invalid_status (void) ++{ ++ pid_t pid = xfork (); ++ if (pid == 0) ++ _exit (127); ++ xwaitpid (pid, &invalid_status, 0); ++ if (WIFEXITED (invalid_status)) ++ invalid_status = WEXITSTATUS (invalid_status); ++} ++ ++static int ++do_test (void) ++{ ++ init_invalid_status (); ++ ++ TEST ("test", NULL, "%s", "test"); ++ TEST ("test-test", NULL, "%s-test", "test"); ++ TEST ("test", "test", "%s", "test"); ++ TEST ("test-test", "test", "%s-test", "test"); ++ ++ TEST ("test%", NULL, "%s%%", "test"); ++ TEST ("test%-test", NULL, "%s%%-test", "test"); ++ TEST ("test%", "test", "%s%%", "test"); ++ TEST ("test%-test", "test", "%s%%-test", "test"); ++ ++ TEST ("0000007b", NULL, "%x", 123); ++ TEST ("0000007b-test", NULL, "%x-test", 123); ++ TEST ("0000007b", "test", "%x", 123); ++ TEST ("0000007b-test", "test", "%x-test", 123); ++ ++#define TEST_LONG(es, objn, fmt, ...) \ ++ ({ \ ++ if (sizeof (int) == sizeof (long int)) \ ++ TEST (es, objn, fmt, __VA_ARGS__); \ ++ else \ ++ TEST ("ffffffff" es, objn, fmt, __VA_ARGS__); \ ++ }) ++ ++ TEST_LONG ("fffffffd", NULL, "%lx", (long int)~2ul); ++ TEST_LONG ("fffffffd-test", NULL, "%lx-test", (long int)~2ul); ++ TEST_LONG ("fffffffd", "test", "%lx", (long int)~2ul); ++ TEST_LONG ("fffffffd-test", "test", "%lx-test", (long int)~2ul); ++ ++ TEST_LONG ("fffffffe", NULL, "%zx", (size_t)~1ul); ++ TEST_LONG ("fffffffe-test", NULL, "%zx-test", (size_t)~1ul); ++ TEST_LONG ("fffffffe", "test", "%zx", (size_t)~1ul); ++ TEST_LONG ("fffffffe-test", "test", "%zx-test", (size_t)~1ul); ++ ++ struct support_capture_subprocess result; ++ result = support_capture_subprocess (do_test_invalid_conversion, NULL); ++ support_capture_subprocess_check (&result, "dl-exception", ++ invalid_status, sc_allow_stderr); ++ TEST_COMPARE_STRING (result.err.buffer, ++ "Fatal error: invalid format in exception string\n"); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1817513-130.patch b/glibc-rh1817513-130.patch new file mode 100755 index 0000000..d06b247 --- /dev/null +++ b/glibc-rh1817513-130.patch @@ -0,0 +1,22 @@ +commit 8dddf0bd5a3d57fba8da27e93f3d1a7032fce184 +Author: Florian Weimer +Date: Wed Oct 30 17:44:09 2019 +0100 + + resolv/tst-idna_name_classify: Isolate from system libraries + + Loading NSS modules from static binaries uses installed system + libraries if LD_LIBRARY_PATH is not set. + +diff --git a/inet/Makefile b/inet/Makefile +index 7782913b4c06f057..62d25f853538bb08 100644 +--- a/inet/Makefile ++++ b/inet/Makefile +@@ -112,4 +112,8 @@ ifeq ($(build-static-nss),yes) + CFLAGS += -DSTATIC_NSS + endif + ++# The test uses dlopen indirectly and would otherwise load system ++# objects. ++tst-idna_name_classify-ENV = \ ++ LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)elf + $(objpfx)tst-idna_name_classify.out: $(gen-locales) diff --git a/glibc-rh1817513-131.patch b/glibc-rh1817513-131.patch new file mode 100755 index 0000000..7f650e5 --- /dev/null +++ b/glibc-rh1817513-131.patch @@ -0,0 +1,21 @@ +commit 880433de13fa31e52587720f81b762a6c7797e4e +Author: Florian Weimer +Date: Thu Dec 10 15:47:26 2020 +0100 + + elf: Include in cache.c + + The roundup macro is defined there. Relying on an indirect + definition is brittle. + +diff --git a/elf/cache.c b/elf/cache.c +index dde3d7fefa4105f9..fdfedb0964bcd217 100644 +--- a/elf/cache.c ++++ b/elf/cache.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include + #include + diff --git a/glibc-rh1817513-132.patch b/glibc-rh1817513-132.patch new file mode 100755 index 0000000..914292e --- /dev/null +++ b/glibc-rh1817513-132.patch @@ -0,0 +1,33 @@ +commit 2ee7711bdd7de9dd30073b223ce29d5cd50320f6 +Author: H.J. Lu +Date: Sun Dec 13 04:56:41 2020 -0800 + + x86: Remove the default REP MOVSB threshold tunable value [BZ #27061] + + Since we can't tell if the tunable value is set by user or not: + + https://sourceware.org/bugzilla/show_bug.cgi?id=27069 + + remove the default REP MOVSB threshold tunable value so that the correct + default value will be set correctly by init_cacheinfo (). + + Reviewed-by: Carlos O'Donell + +diff --git a/sysdeps/x86/dl-tunables.list b/sysdeps/x86/dl-tunables.list +index e066313a1d1dd009..89bf296626658900 100644 +--- a/sysdeps/x86/dl-tunables.list ++++ b/sysdeps/x86/dl-tunables.list +@@ -39,9 +39,11 @@ glibc { + # REP MOVSB. Since larger register size can move more data with a + # single load and store, the threshold is higher with larger register + # size. Note: Since the REP MOVSB threshold must be greater than 8 +- # times of vector size, the minium value must be updated at run-time. ++ # times of vector size and the default value is 2048 * (vector size ++ # / 16), the default value and the minimum value must be updated at ++ # run-time. NB: Don't set the default value since we can't tell if ++ # the tunable value is set by user or not [BZ #27069]. + minval: 1 +- default: 2048 + } + x86_rep_stosb_threshold { + type: SIZE_T diff --git a/glibc-rh1817513-133.patch b/glibc-rh1817513-133.patch new file mode 100755 index 0000000..a714822 --- /dev/null +++ b/glibc-rh1817513-133.patch @@ -0,0 +1,18 @@ +commit 8a30bb4e0604aefcf28f20360fc8ba8ef8604b9c +Author: Florian Weimer +Date: Wed Dec 23 12:07:20 2020 +0100 + + elf: Account for glibc-hwcaps/ prefix in _dl_important_hwcaps + +diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c +index 50d764ae8707f46d..2fc4ae67a0f5d051 100644 +--- a/elf/dl-hwcaps.c ++++ b/elf/dl-hwcaps.c +@@ -192,6 +192,7 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend, + + /* Each hwcaps subdirectory has a GLIBC_HWCAPS_PREFIX string prefix + and a "/" suffix once stored in the result. */ ++ hwcaps_counts.maximum_length += strlen (GLIBC_HWCAPS_PREFIX) + 1; + size_t total = (hwcaps_counts.count * (strlen (GLIBC_HWCAPS_PREFIX) + 1) + + hwcaps_counts.total_length); + diff --git a/glibc-rh1817513-14.patch b/glibc-rh1817513-14.patch new file mode 100755 index 0000000..0186fde --- /dev/null +++ b/glibc-rh1817513-14.patch @@ -0,0 +1,22 @@ +commit ce7387cc250a408d3fbb7a6fff7ad4d977166b00 +Author: H.J. Lu +Date: Thu Nov 29 20:03:46 2018 -0800 + + elf/dl-exception.c: Include <_itoa.h> for _itoa prototype + + Tested with build-many-glibcs.py. + + * elf/dl-exception.c: Include <_itoa.h>. + +diff --git a/elf/dl-exception.c b/elf/dl-exception.c +index 1e41d89a7db52683..3e8e0ba3f1442005 100644 +--- a/elf/dl-exception.c ++++ b/elf/dl-exception.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include <_itoa.h> + + /* This message we return as a last resort. We define the string in a + variable since we have to avoid freeing it and so have to enable diff --git a/glibc-rh1817513-15.patch b/glibc-rh1817513-15.patch new file mode 100755 index 0000000..d9ef9ef --- /dev/null +++ b/glibc-rh1817513-15.patch @@ -0,0 +1,1820 @@ +commit c22e4c2a1431c5e77bf4288d35bf7629f2f093aa +Author: H.J. Lu +Date: Mon Dec 3 05:54:43 2018 -0800 + + x86: Extend CPUID support in struct cpu_features + + Extend CPUID support for all feature bits from CPUID. Add a new macro, + CPU_FEATURE_USABLE, which can be used to check if a feature is usable at + run-time, instead of HAS_CPU_FEATURE and HAS_ARCH_FEATURE. + + Add COMMON_CPUID_INDEX_D_ECX_1, COMMON_CPUID_INDEX_80000007 and + COMMON_CPUID_INDEX_80000008 to check CPU feature bits in them. + + Tested on i686 and x86-64 as well as using build-many-glibcs.py with + x86 targets. + + * sysdeps/x86/cacheinfo.c (intel_check_word): Updated for + cpu_features_basic. + (__cache_sysconf): Likewise. + (init_cacheinfo): Likewise. + * sysdeps/x86/cpu-features.c (get_extended_indeces): Also + populate COMMON_CPUID_INDEX_80000007 and + COMMON_CPUID_INDEX_80000008. + (get_common_indices): Also populate COMMON_CPUID_INDEX_D_ECX_1. + Use CPU_FEATURES_CPU_P (cpu_features, XSAVEC) to check if + XSAVEC is available. Set the bit_arch_XXX_Usable bits. + (init_cpu_features): Use _Static_assert on + index_arch_Fast_Unaligned_Load. + __get_cpuid_registers and __get_arch_feature. Updated for + cpu_features_basic. Set stepping in cpu_features. + * sysdeps/x86/cpu-features.h: (FEATURE_INDEX_1): Changed to enum. + (FEATURE_INDEX_2): New. + (FEATURE_INDEX_MAX): Changed to enum. + (COMMON_CPUID_INDEX_D_ECX_1): New. + (COMMON_CPUID_INDEX_80000007): Likewise. + (COMMON_CPUID_INDEX_80000008): Likewise. + (cpuid_registers): Likewise. + (cpu_features_basic): Likewise. + (CPU_FEATURE_USABLE): Likewise. + (bit_arch_XXX_Usable): Likewise. + (cpu_features): Use cpuid_registers and cpu_features_basic. + (bit_arch_XXX): Reweritten. + (bit_cpu_XXX): Likewise. + (index_cpu_XXX): Likewise. + (reg_XXX): Likewise. + * sysdeps/x86/tst-get-cpu-features.c: Include and + . + (CHECK_CPU_FEATURE): New. + (CHECK_CPU_FEATURE_USABLE): Likewise. + (cpu_kinds): Likewise. + (do_test): Print vendor, family, model and stepping. Check + HAS_CPU_FEATURE and CPU_FEATURE_USABLE. + (TEST_FUNCTION): Removed. + Include instead of + "../../test-skeleton.c". + * sysdeps/x86_64/multiarch/sched_cpucount.c (__sched_cpucount): + Check POPCNT instead of POPCOUNT. + * sysdeps/x86_64/multiarch/test-multiarch.c (do_test): Likewise. + +Backport difference: Adjustments to previous cache sizing +backports (which happened later upstream). + +diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c +index 57c36d030a76c8b2..f1125f30223f5ca3 100644 +--- a/sysdeps/x86/cacheinfo.c ++++ b/sysdeps/x86/cacheinfo.c +@@ -205,8 +205,8 @@ intel_check_word (int name, unsigned int value, bool *has_level_2, + /* Intel reused this value. For family 15, model 6 it + specifies the 3rd level cache. Otherwise the 2nd + level cache. */ +- unsigned int family = cpu_features->family; +- unsigned int model = cpu_features->model; ++ unsigned int family = cpu_features->basic.family; ++ unsigned int model = cpu_features->basic.model; + + if (family == 15 && model == 6) + { +@@ -258,7 +258,7 @@ intel_check_word (int name, unsigned int value, bool *has_level_2, + static long int __attribute__ ((noinline)) + handle_intel (int name, const struct cpu_features *cpu_features) + { +- unsigned int maxidx = cpu_features->max_cpuid; ++ unsigned int maxidx = cpu_features->basic.max_cpuid; + + /* Return -1 for older CPUs. */ + if (maxidx < 2) +@@ -443,10 +443,10 @@ __cache_sysconf (int name) + { + const struct cpu_features *cpu_features = __get_cpu_features (); + +- if (cpu_features->kind == arch_kind_intel) ++ if (cpu_features->basic.kind == arch_kind_intel) + return handle_intel (name, cpu_features); + +- if (cpu_features->kind == arch_kind_amd) ++ if (cpu_features->basic.kind == arch_kind_amd) + return handle_amd (name); + + // XXX Fill in more vendors. +@@ -497,9 +497,9 @@ init_cacheinfo (void) + unsigned int level; + unsigned int threads = 0; + const struct cpu_features *cpu_features = __get_cpu_features (); +- int max_cpuid = cpu_features->max_cpuid; ++ int max_cpuid = cpu_features->basic.max_cpuid; + +- if (cpu_features->kind == arch_kind_intel) ++ if (cpu_features->basic.kind == arch_kind_intel) + { + data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, cpu_features); + +@@ -538,8 +538,8 @@ init_cacheinfo (void) + highest cache level. */ + if (max_cpuid >= 4) + { +- unsigned int family = cpu_features->family; +- unsigned int model = cpu_features->model; ++ unsigned int family = cpu_features->basic.family; ++ unsigned int model = cpu_features->basic.model; + + int i = 0; + +@@ -700,7 +700,7 @@ intel_bug_no_cache_info: + shared += core; + } + } +- else if (cpu_features->kind == arch_kind_amd) ++ else if (cpu_features->basic.kind == arch_kind_amd) + { + data = handle_amd (_SC_LEVEL1_DCACHE_SIZE); + long int core = handle_amd (_SC_LEVEL2_CACHE_SIZE); +@@ -722,7 +722,7 @@ intel_bug_no_cache_info: + threads = 1 << ((ecx >> 12) & 0x0f); + } + +- if (threads == 0 || cpu_features->family >= 0x17) ++ if (threads == 0 || cpu_features->basic.family >= 0x17) + { + /* If APIC ID width is not available, use logical + processor count. */ +@@ -738,7 +738,7 @@ intel_bug_no_cache_info: + shared /= threads; + + /* Get shared cache per ccx for Zen architectures. */ +- if (cpu_features->family >= 0x17) ++ if (cpu_features->basic.family >= 0x17) + { + unsigned int eax; + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 3b268efbce627e6c..3a02a9c7d08f9603 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -52,7 +52,18 @@ get_extended_indices (struct cpu_features *cpu_features) + cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].ebx, + cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].ecx, + cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].edx); +- ++ if (eax >= 0x80000007) ++ __cpuid (0x80000007, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_80000007].eax, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_80000007].ebx, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_80000007].ecx, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_80000007].edx); ++ if (eax >= 0x80000008) ++ __cpuid (0x80000008, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_80000008].eax, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_80000008].ebx, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_80000008].ecx, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_80000008].edx); + } + + static void +@@ -78,13 +89,20 @@ get_common_indices (struct cpu_features *cpu_features, + } + } + +- if (cpu_features->max_cpuid >= 7) ++ if (cpu_features->basic.max_cpuid >= 7) + __cpuid_count (7, 0, + cpu_features->cpuid[COMMON_CPUID_INDEX_7].eax, + cpu_features->cpuid[COMMON_CPUID_INDEX_7].ebx, + cpu_features->cpuid[COMMON_CPUID_INDEX_7].ecx, + cpu_features->cpuid[COMMON_CPUID_INDEX_7].edx); + ++ if (cpu_features->basic.max_cpuid >= 0xd) ++ __cpuid_count (0xd, 1, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_D_ECX_1].eax, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_D_ECX_1].ebx, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_D_ECX_1].ecx, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_D_ECX_1].edx); ++ + /* Can we call xgetbv? */ + if (CPU_FEATURES_CPU_P (cpu_features, OSXSAVE)) + { +@@ -116,6 +134,18 @@ get_common_indices (struct cpu_features *cpu_features, + if (CPU_FEATURES_CPU_P (cpu_features, FMA)) + cpu_features->feature[index_arch_FMA_Usable] + |= bit_arch_FMA_Usable; ++ /* Determine if VAES is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, VAES)) ++ cpu_features->feature[index_arch_VAES_Usable] ++ |= bit_arch_VAES_Usable; ++ /* Determine if VPCLMULQDQ is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, VPCLMULQDQ)) ++ cpu_features->feature[index_arch_VPCLMULQDQ_Usable] ++ |= bit_arch_VPCLMULQDQ_Usable; ++ /* Determine if XOP is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, XOP)) ++ cpu_features->feature[index_arch_XOP_Usable] ++ |= bit_arch_XOP_Usable; + } + + /* Check if OPMASK state, upper 256-bit of ZMM0-ZMM15 and +@@ -129,17 +159,69 @@ get_common_indices (struct cpu_features *cpu_features, + { + cpu_features->feature[index_arch_AVX512F_Usable] + |= bit_arch_AVX512F_Usable; ++ /* Determine if AVX512CD is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512CD)) ++ cpu_features->feature[index_arch_AVX512CD_Usable] ++ |= bit_arch_AVX512CD_Usable; ++ /* Determine if AVX512ER is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512ER)) ++ cpu_features->feature[index_arch_AVX512ER_Usable] ++ |= bit_arch_AVX512ER_Usable; ++ /* Determine if AVX512PF is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512PF)) ++ cpu_features->feature[index_arch_AVX512PF_Usable] ++ |= bit_arch_AVX512PF_Usable; ++ /* Determine if AVX512VL is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512VL)) ++ cpu_features->feature[index_arch_AVX512VL_Usable] ++ |= bit_arch_AVX512VL_Usable; + /* Determine if AVX512DQ is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512DQ)) + cpu_features->feature[index_arch_AVX512DQ_Usable] + |= bit_arch_AVX512DQ_Usable; ++ /* Determine if AVX512BW is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512BW)) ++ cpu_features->feature[index_arch_AVX512BW_Usable] ++ |= bit_arch_AVX512BW_Usable; ++ /* Determine if AVX512_4FMAPS is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512_4FMAPS)) ++ cpu_features->feature[index_arch_AVX512_4FMAPS_Usable] ++ |= bit_arch_AVX512_4FMAPS_Usable; ++ /* Determine if AVX512_4VNNIW is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512_4VNNIW)) ++ cpu_features->feature[index_arch_AVX512_4VNNIW_Usable] ++ |= bit_arch_AVX512_4VNNIW_Usable; ++ /* Determine if AVX512_BITALG is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512_BITALG)) ++ cpu_features->feature[index_arch_AVX512_BITALG_Usable] ++ |= bit_arch_AVX512_BITALG_Usable; ++ /* Determine if AVX512_IFMA is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512_IFMA)) ++ cpu_features->feature[index_arch_AVX512_IFMA_Usable] ++ |= bit_arch_AVX512_IFMA_Usable; ++ /* Determine if AVX512_VBMI is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VBMI)) ++ cpu_features->feature[index_arch_AVX512_VBMI_Usable] ++ |= bit_arch_AVX512_VBMI_Usable; ++ /* Determine if AVX512_VBMI2 is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VBMI2)) ++ cpu_features->feature[index_arch_AVX512_VBMI2_Usable] ++ |= bit_arch_AVX512_VBMI2_Usable; ++ /* Determine if is AVX512_VNNI usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VNNI)) ++ cpu_features->feature[index_arch_AVX512_VNNI_Usable] ++ |= bit_arch_AVX512_VNNI_Usable; ++ /* Determine if AVX512_VPOPCNTDQ is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VPOPCNTDQ)) ++ cpu_features->feature[index_arch_AVX512_VPOPCNTDQ_Usable] ++ |= bit_arch_AVX512_VPOPCNTDQ_Usable; + } + } + } + + /* For _dl_runtime_resolve, set xsave_state_size to xsave area + size + integer register save size and align it to 64 bytes. */ +- if (cpu_features->max_cpuid >= 0xd) ++ if (cpu_features->basic.max_cpuid >= 0xd) + { + unsigned int eax, ebx, ecx, edx; + +@@ -154,10 +236,8 @@ get_common_indices (struct cpu_features *cpu_features, + cpu_features->xsave_state_full_size + = xsave_state_full_size; + +- __cpuid_count (0xd, 1, eax, ebx, ecx, edx); +- + /* Check if XSAVEC is available. */ +- if ((eax & (1 << 1)) != 0) ++ if (CPU_FEATURES_CPU_P (cpu_features, XSAVEC)) + { + unsigned int xstate_comp_offsets[32]; + unsigned int xstate_comp_sizes[32]; +@@ -209,12 +289,25 @@ get_common_indices (struct cpu_features *cpu_features, + } + } + ++_Static_assert (((index_arch_Fast_Unaligned_Load ++ == index_arch_Fast_Unaligned_Copy) ++ && (index_arch_Fast_Unaligned_Load ++ == index_arch_Prefer_PMINUB_for_stringop) ++ && (index_arch_Fast_Unaligned_Load ++ == index_arch_Slow_SSE4_2) ++ && (index_arch_Fast_Unaligned_Load ++ == index_arch_Fast_Rep_String) ++ && (index_arch_Fast_Unaligned_Load ++ == index_arch_Fast_Copy_Backward)), ++ "Incorrect index_arch_Fast_Unaligned_Load"); ++ + static inline void + init_cpu_features (struct cpu_features *cpu_features) + { + unsigned int ebx, ecx, edx; + unsigned int family = 0; + unsigned int model = 0; ++ unsigned int stepping = 0; + enum cpu_features_kind kind; + + #if !HAS_CPUID +@@ -225,12 +318,12 @@ init_cpu_features (struct cpu_features *cpu_features) + } + #endif + +- __cpuid (0, cpu_features->max_cpuid, ebx, ecx, edx); ++ __cpuid (0, cpu_features->basic.max_cpuid, ebx, ecx, edx); + + /* This spells out "GenuineIntel". */ + if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69) + { +- unsigned int extended_model, stepping; ++ unsigned int extended_model; + + kind = arch_kind_intel; + +@@ -269,15 +362,6 @@ init_cpu_features (struct cpu_features *cpu_features) + case 0x5d: + /* Unaligned load versions are faster than SSSE3 + on Silvermont. */ +-#if index_arch_Fast_Unaligned_Load != index_arch_Prefer_PMINUB_for_stringop +-# error index_arch_Fast_Unaligned_Load != index_arch_Prefer_PMINUB_for_stringop +-#endif +-#if index_arch_Fast_Unaligned_Load != index_arch_Slow_SSE4_2 +-# error index_arch_Fast_Unaligned_Load != index_arch_Slow_SSE4_2 +-#endif +-#if index_arch_Fast_Unaligned_Load != index_arch_Fast_Unaligned_Copy +-# error index_arch_Fast_Unaligned_Load != index_arch_Fast_Unaligned_Copy +-#endif + cpu_features->feature[index_arch_Fast_Unaligned_Load] + |= (bit_arch_Fast_Unaligned_Load + | bit_arch_Fast_Unaligned_Copy +@@ -300,15 +384,6 @@ init_cpu_features (struct cpu_features *cpu_features) + case 0x2f: + /* Rep string instructions, unaligned load, unaligned copy, + and pminub are fast on Intel Core i3, i5 and i7. */ +-#if index_arch_Fast_Rep_String != index_arch_Fast_Unaligned_Load +-# error index_arch_Fast_Rep_String != index_arch_Fast_Unaligned_Load +-#endif +-#if index_arch_Fast_Rep_String != index_arch_Prefer_PMINUB_for_stringop +-# error index_arch_Fast_Rep_String != index_arch_Prefer_PMINUB_for_stringop +-#endif +-#if index_arch_Fast_Rep_String != index_arch_Fast_Unaligned_Copy +-# error index_arch_Fast_Rep_String != index_arch_Fast_Unaligned_Copy +-#endif + cpu_features->feature[index_arch_Fast_Rep_String] + |= (bit_arch_Fast_Rep_String + | bit_arch_Fast_Unaligned_Load +@@ -352,7 +427,7 @@ init_cpu_features (struct cpu_features *cpu_features) + /* This spells out "AuthenticAMD". */ + else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65) + { +- unsigned int extended_model, stepping; ++ unsigned int extended_model; + + kind = arch_kind_amd; + +@@ -374,9 +449,6 @@ init_cpu_features (struct cpu_features *cpu_features) + + if (family == 0x15) + { +-#if index_arch_Fast_Unaligned_Load != index_arch_Fast_Copy_Backward +-# error index_arch_Fast_Unaligned_Load != index_arch_Fast_Copy_Backward +-#endif + /* "Excavator" */ + if (model >= 0x60 && model <= 0x7f) + { +@@ -408,9 +480,10 @@ init_cpu_features (struct cpu_features *cpu_features) + no_cpuid: + #endif + +- cpu_features->family = family; +- cpu_features->model = model; +- cpu_features->kind = kind; ++ cpu_features->basic.kind = kind; ++ cpu_features->basic.family = family; ++ cpu_features->basic.model = model; ++ cpu_features->basic.stepping = stepping; + + #if HAVE_TUNABLES + TUNABLE_GET (hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps)); +@@ -431,7 +504,7 @@ no_cpuid: + + #ifdef __x86_64__ + GLRO(dl_hwcap) = HWCAP_X86_64; +- if (cpu_features->kind == arch_kind_intel) ++ if (cpu_features->basic.kind == arch_kind_intel) + { + const char *platform = NULL; + +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index fb22d7b9d6226a92..4917182e99a8ee90 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -18,108 +18,58 @@ + #ifndef cpu_features_h + #define cpu_features_h + +-#define bit_arch_Fast_Rep_String (1 << 0) +-#define bit_arch_Fast_Copy_Backward (1 << 1) +-#define bit_arch_Slow_BSF (1 << 2) +-#define bit_arch_Fast_Unaligned_Load (1 << 4) +-#define bit_arch_Prefer_PMINUB_for_stringop (1 << 5) +-#define bit_arch_AVX_Usable (1 << 6) +-#define bit_arch_FMA_Usable (1 << 7) +-#define bit_arch_FMA4_Usable (1 << 8) +-#define bit_arch_Slow_SSE4_2 (1 << 9) +-#define bit_arch_AVX2_Usable (1 << 10) +-#define bit_arch_AVX_Fast_Unaligned_Load (1 << 11) +-#define bit_arch_AVX512F_Usable (1 << 12) +-#define bit_arch_AVX512DQ_Usable (1 << 13) +-#define bit_arch_I586 (1 << 14) +-#define bit_arch_I686 (1 << 15) +-#define bit_arch_Prefer_MAP_32BIT_EXEC (1 << 16) +-#define bit_arch_Prefer_No_VZEROUPPER (1 << 17) +-#define bit_arch_Fast_Unaligned_Copy (1 << 18) +-#define bit_arch_Prefer_ERMS (1 << 19) +-#define bit_arch_Prefer_No_AVX512 (1 << 20) +-#define bit_arch_MathVec_Prefer_No_AVX512 (1 << 21) +-#define bit_arch_XSAVEC_Usable (1 << 22) +-#define bit_arch_Prefer_FSRM (1 << 23) +- +-/* CPUID Feature flags. */ +- +-/* COMMON_CPUID_INDEX_1. */ +-#define bit_cpu_CX8 (1 << 8) +-#define bit_cpu_CMOV (1 << 15) +-#define bit_cpu_SSE (1 << 25) +-#define bit_cpu_SSE2 (1 << 26) +-#define bit_cpu_SSSE3 (1 << 9) +-#define bit_cpu_SSE4_1 (1 << 19) +-#define bit_cpu_SSE4_2 (1 << 20) +-#define bit_cpu_OSXSAVE (1 << 27) +-#define bit_cpu_AVX (1 << 28) +-#define bit_cpu_POPCOUNT (1 << 23) +-#define bit_cpu_FMA (1 << 12) +-#define bit_cpu_FMA4 (1 << 16) +-#define bit_cpu_HTT (1 << 28) +-#define bit_cpu_LZCNT (1 << 5) +-#define bit_cpu_MOVBE (1 << 22) +-#define bit_cpu_POPCNT (1 << 23) +- +-/* COMMON_CPUID_INDEX_7. */ +-#define bit_cpu_BMI1 (1 << 3) +-#define bit_cpu_BMI2 (1 << 8) +-#define bit_cpu_ERMS (1 << 9) +-#define bit_cpu_RTM (1 << 11) +-#define bit_cpu_AVX2 (1 << 5) +-#define bit_cpu_AVX512F (1 << 16) +-#define bit_cpu_AVX512DQ (1 << 17) +-#define bit_cpu_AVX512PF (1 << 26) +-#define bit_cpu_AVX512ER (1 << 27) +-#define bit_cpu_AVX512CD (1 << 28) +-#define bit_cpu_AVX512BW (1 << 30) +-#define bit_cpu_AVX512VL (1u << 31) +-#define bit_cpu_IBT (1u << 20) +-#define bit_cpu_SHSTK (1u << 7) +-#define bit_cpu_FSRM (1 << 4) +- +-/* XCR0 Feature flags. */ +-#define bit_XMM_state (1 << 1) +-#define bit_YMM_state (1 << 2) +-#define bit_Opmask_state (1 << 5) +-#define bit_ZMM0_15_state (1 << 6) +-#define bit_ZMM16_31_state (1 << 7) ++enum ++{ ++ /* The integer bit array index for the first set of internal feature ++ bits. */ ++ FEATURE_INDEX_1 = 0, ++ FEATURE_INDEX_2, ++ /* The current maximum size of the feature integer bit array. */ ++ FEATURE_INDEX_MAX ++}; + +-/* The integer bit array index for the first set of internal feature bits. */ +-#define FEATURE_INDEX_1 0 ++enum ++{ ++ COMMON_CPUID_INDEX_1 = 0, ++ COMMON_CPUID_INDEX_7, ++ COMMON_CPUID_INDEX_80000001, ++ COMMON_CPUID_INDEX_D_ECX_1, ++ COMMON_CPUID_INDEX_80000007, ++ COMMON_CPUID_INDEX_80000008, ++ /* Keep the following line at the end. */ ++ COMMON_CPUID_INDEX_MAX ++}; + +-/* The current maximum size of the feature integer bit array. */ +-#define FEATURE_INDEX_MAX 1 ++struct cpuid_registers ++{ ++ unsigned int eax; ++ unsigned int ebx; ++ unsigned int ecx; ++ unsigned int edx; ++}; + +-enum +- { +- COMMON_CPUID_INDEX_1 = 0, +- COMMON_CPUID_INDEX_7, +- COMMON_CPUID_INDEX_80000001, +- /* Keep the following line at the end. */ +- COMMON_CPUID_INDEX_MAX +- }; ++enum cpu_features_kind ++{ ++ arch_kind_unknown = 0, ++ arch_kind_intel, ++ arch_kind_amd, ++ arch_kind_other ++}; + +-struct cpu_features ++struct cpu_features_basic + { +- enum cpu_features_kind +- { +- arch_kind_unknown = 0, +- arch_kind_intel, +- arch_kind_amd, +- arch_kind_other +- } kind; ++ enum cpu_features_kind kind; + int max_cpuid; +- struct cpuid_registers +- { +- unsigned int eax; +- unsigned int ebx; +- unsigned int ecx; +- unsigned int edx; +- } cpuid[COMMON_CPUID_INDEX_MAX]; + unsigned int family; + unsigned int model; ++ unsigned int stepping; ++}; ++ ++struct cpu_features ++{ ++ struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX]; ++ unsigned int feature[FEATURE_INDEX_MAX]; ++ struct cpu_features_basic basic; + /* The state size for XSAVEC or XSAVE. The type must be unsigned long + int so that we use + +@@ -132,7 +82,6 @@ struct cpu_features + GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable + */ + unsigned int xsave_state_full_size; +- unsigned int feature[FEATURE_INDEX_MAX]; + /* Data cache size for use in memory and string routines, typically + L1 size. */ + unsigned long int data_cache_size; +@@ -148,112 +97,838 @@ struct cpu_features + extern const struct cpu_features *__get_cpu_features (void) + __attribute__ ((const)); + +-# if defined (_LIBC) && !IS_IN (nonlib) +-/* Unused for x86. */ +-# define INIT_ARCH() +-# define __get_cpu_features() (&GLRO(dl_x86_cpu_features)) +-# endif +- +- + /* Only used directly in cpu-features.c. */ + # define CPU_FEATURES_CPU_P(ptr, name) \ + ((ptr->cpuid[index_cpu_##name].reg_##name & (bit_cpu_##name)) != 0) + # define CPU_FEATURES_ARCH_P(ptr, name) \ + ((ptr->feature[index_arch_##name] & (bit_arch_##name)) != 0) + +-/* HAS_* evaluates to true if we may use the feature at runtime. */ +-# define HAS_CPU_FEATURE(name) \ +- CPU_FEATURES_CPU_P (__get_cpu_features (), name) ++/* HAS_CPU_FEATURE evaluates to true if CPU supports the feature. */ ++#define HAS_CPU_FEATURE(name) \ ++ CPU_FEATURES_CPU_P (__get_cpu_features (), name) ++/* HAS_ARCH_FEATURE evaluates to true if we may use the feature at ++ runtime. */ + # define HAS_ARCH_FEATURE(name) \ +- CPU_FEATURES_ARCH_P (__get_cpu_features (), name) +- +-# define index_cpu_CX8 COMMON_CPUID_INDEX_1 +-# define index_cpu_CMOV COMMON_CPUID_INDEX_1 +-# define index_cpu_SSE COMMON_CPUID_INDEX_1 +-# define index_cpu_SSE2 COMMON_CPUID_INDEX_1 +-# define index_cpu_SSSE3 COMMON_CPUID_INDEX_1 +-# define index_cpu_SSE4_1 COMMON_CPUID_INDEX_1 +-# define index_cpu_SSE4_2 COMMON_CPUID_INDEX_1 +-# define index_cpu_AVX COMMON_CPUID_INDEX_1 +-# define index_cpu_AVX2 COMMON_CPUID_INDEX_7 +-# define index_cpu_AVX512F COMMON_CPUID_INDEX_7 +-# define index_cpu_AVX512DQ COMMON_CPUID_INDEX_7 +-# define index_cpu_AVX512PF COMMON_CPUID_INDEX_7 +-# define index_cpu_AVX512ER COMMON_CPUID_INDEX_7 +-# define index_cpu_AVX512CD COMMON_CPUID_INDEX_7 +-# define index_cpu_AVX512BW COMMON_CPUID_INDEX_7 +-# define index_cpu_AVX512VL COMMON_CPUID_INDEX_7 +-# define index_cpu_ERMS COMMON_CPUID_INDEX_7 +-# define index_cpu_RTM COMMON_CPUID_INDEX_7 +-# define index_cpu_FMA COMMON_CPUID_INDEX_1 +-# define index_cpu_FMA4 COMMON_CPUID_INDEX_80000001 +-# define index_cpu_POPCOUNT COMMON_CPUID_INDEX_1 +-# define index_cpu_OSXSAVE COMMON_CPUID_INDEX_1 +-# define index_cpu_HTT COMMON_CPUID_INDEX_1 +-# define index_cpu_BMI1 COMMON_CPUID_INDEX_7 +-# define index_cpu_BMI2 COMMON_CPUID_INDEX_7 +-# define index_cpu_LZCNT COMMON_CPUID_INDEX_80000001 +-# define index_cpu_MOVBE COMMON_CPUID_INDEX_1 +-# define index_cpu_POPCNT COMMON_CPUID_INDEX_1 +-# define index_cpu_IBT COMMON_CPUID_INDEX_7 +-# define index_cpu_SHSTK COMMON_CPUID_INDEX_7 +-# define index_cpu_FSRM COMMON_CPUID_INDEX_7 +- +-# define reg_CX8 edx +-# define reg_CMOV edx +-# define reg_SSE edx +-# define reg_SSE2 edx +-# define reg_SSSE3 ecx +-# define reg_SSE4_1 ecx +-# define reg_SSE4_2 ecx +-# define reg_AVX ecx +-# define reg_AVX2 ebx +-# define reg_AVX512F ebx +-# define reg_AVX512DQ ebx +-# define reg_AVX512PF ebx +-# define reg_AVX512ER ebx +-# define reg_AVX512CD ebx +-# define reg_AVX512BW ebx +-# define reg_AVX512VL ebx +-# define reg_ERMS ebx +-# define reg_RTM ebx +-# define reg_FMA ecx +-# define reg_FMA4 ecx +-# define reg_POPCOUNT ecx +-# define reg_OSXSAVE ecx +-# define reg_HTT edx +-# define reg_BMI1 ebx +-# define reg_BMI2 ebx +-# define reg_LZCNT ecx +-# define reg_MOVBE ecx +-# define reg_POPCNT ecx +-# define reg_IBT edx +-# define reg_SHSTK ecx +-# define reg_FSRM edx +- +-# define index_arch_Fast_Rep_String FEATURE_INDEX_1 +-# define index_arch_Fast_Copy_Backward FEATURE_INDEX_1 +-# define index_arch_Slow_BSF FEATURE_INDEX_1 +-# define index_arch_Fast_Unaligned_Load FEATURE_INDEX_1 +-# define index_arch_Prefer_PMINUB_for_stringop FEATURE_INDEX_1 +-# define index_arch_AVX_Usable FEATURE_INDEX_1 +-# define index_arch_FMA_Usable FEATURE_INDEX_1 +-# define index_arch_FMA4_Usable FEATURE_INDEX_1 +-# define index_arch_Slow_SSE4_2 FEATURE_INDEX_1 +-# define index_arch_AVX2_Usable FEATURE_INDEX_1 +-# define index_arch_AVX_Fast_Unaligned_Load FEATURE_INDEX_1 +-# define index_arch_AVX512F_Usable FEATURE_INDEX_1 +-# define index_arch_AVX512DQ_Usable FEATURE_INDEX_1 +-# define index_arch_I586 FEATURE_INDEX_1 +-# define index_arch_I686 FEATURE_INDEX_1 +-# define index_arch_Prefer_MAP_32BIT_EXEC FEATURE_INDEX_1 +-# define index_arch_Prefer_No_VZEROUPPER FEATURE_INDEX_1 +-# define index_arch_Fast_Unaligned_Copy FEATURE_INDEX_1 +-# define index_arch_Prefer_ERMS FEATURE_INDEX_1 +-# define index_arch_Prefer_No_AVX512 FEATURE_INDEX_1 +-# define index_arch_MathVec_Prefer_No_AVX512 FEATURE_INDEX_1 +-# define index_arch_XSAVEC_Usable FEATURE_INDEX_1 +-# define index_arch_Prefer_FSRM FEATURE_INDEX_1 ++ CPU_FEATURES_ARCH_P (__get_cpu_features (), name) ++/* CPU_FEATURE_USABLE evaluates to true if the feature is usable. */ ++#define CPU_FEATURE_USABLE(name) \ ++ ((need_arch_feature_##name && HAS_ARCH_FEATURE (name##_Usable)) \ ++ || (!need_arch_feature_##name && HAS_CPU_FEATURE(name))) ++ ++/* Architecture features. */ ++ ++/* FEATURE_INDEX_1. */ ++#define bit_arch_AVX_Usable (1u << 0) ++#define bit_arch_AVX2_Usable (1u << 1) ++#define bit_arch_AVX512F_Usable (1u << 2) ++#define bit_arch_AVX512CD_Usable (1u << 3) ++#define bit_arch_AVX512ER_Usable (1u << 4) ++#define bit_arch_AVX512PF_Usable (1u << 5) ++#define bit_arch_AVX512VL_Usable (1u << 6) ++#define bit_arch_AVX512DQ_Usable (1u << 7) ++#define bit_arch_AVX512BW_Usable (1u << 8) ++#define bit_arch_AVX512_4FMAPS_Usable (1u << 9) ++#define bit_arch_AVX512_4VNNIW_Usable (1u << 10) ++#define bit_arch_AVX512_BITALG_Usable (1u << 11) ++#define bit_arch_AVX512_IFMA_Usable (1u << 12) ++#define bit_arch_AVX512_VBMI_Usable (1u << 13) ++#define bit_arch_AVX512_VBMI2_Usable (1u << 14) ++#define bit_arch_AVX512_VNNI_Usable (1u << 15) ++#define bit_arch_AVX512_VPOPCNTDQ_Usable (1u << 16) ++#define bit_arch_FMA_Usable (1u << 17) ++#define bit_arch_FMA4_Usable (1u << 18) ++#define bit_arch_VAES_Usable (1u << 19) ++#define bit_arch_VPCLMULQDQ_Usable (1u << 20) ++#define bit_arch_XOP_Usable (1u << 21) ++#define bit_arch_XSAVEC_Usable (1u << 22) ++ ++#define index_arch_AVX_Usable FEATURE_INDEX_1 ++#define index_arch_AVX2_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512F_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512CD_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512ER_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512PF_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512VL_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512BW_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512DQ_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512_4FMAPS_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512_4VNNIW_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512_BITALG_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512_IFMA_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512_VBMI_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512_VBMI2_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512_VNNI_Usable FEATURE_INDEX_1 ++#define index_arch_AVX512_VPOPCNTDQ_Usable FEATURE_INDEX_1 ++#define index_arch_FMA_Usable FEATURE_INDEX_1 ++#define index_arch_FMA4_Usable FEATURE_INDEX_1 ++#define index_arch_VAES_Usable FEATURE_INDEX_1 ++#define index_arch_VPCLMULQDQ_Usable FEATURE_INDEX_1 ++#define index_arch_XOP_Usable FEATURE_INDEX_1 ++#define index_arch_XSAVEC_Usable FEATURE_INDEX_1 ++ ++/* Unused. Compiler will optimize them out. */ ++#define bit_arch_SSE3_Usable (1u << 0) ++#define bit_arch_PCLMULQDQ_Usable (1u << 0) ++#define bit_arch_SSSE3_Usable (1u << 0) ++#define bit_arch_CMPXCHG16B_Usable (1u << 0) ++#define bit_arch_SSE4_1_Usable (1u << 0) ++#define bit_arch_SSE4_2_Usable (1u << 0) ++#define bit_arch_MOVBE_Usable (1u << 0) ++#define bit_arch_POPCNT_Usable (1u << 0) ++#define bit_arch_AES_Usable (1u << 0) ++#define bit_arch_XSAVE_Usable (1u << 0) ++#define bit_arch_OSXSAVE_Usable (1u << 0) ++#define bit_arch_F16C_Usable (1u << 0) ++#define bit_arch_RDRAND_Usable (1u << 0) ++#define bit_arch_FPU_Usable (1u << 0) ++#define bit_arch_TSC_Usable (1u << 0) ++#define bit_arch_MSR_Usable (1u << 0) ++#define bit_arch_CX8_Usable (1u << 0) ++#define bit_arch_SEP_Usable (1u << 0) ++#define bit_arch_CMOV_Usable (1u << 0) ++#define bit_arch_CLFSH_Usable (1u << 0) ++#define bit_arch_MMX_Usable (1u << 0) ++#define bit_arch_FXSR_Usable (1u << 0) ++#define bit_arch_SSE_Usable (1u << 0) ++#define bit_arch_SSE2_Usable (1u << 0) ++#define bit_arch_FSGSBASE_Usable (1u << 0) ++#define bit_arch_BMI1_Usable (1u << 0) ++#define bit_arch_HLE_Usable (1u << 0) ++#define bit_arch_BMI2_Usable (1u << 0) ++#define bit_arch_ERMS_Usable (1u << 0) ++#define bit_arch_RTM_Usable (1u << 0) ++#define bit_arch_RDSEED_Usable (1u << 0) ++#define bit_arch_ADX_Usable (1u << 0) ++#define bit_arch_CLFLUSHOPT_Usable (1u << 0) ++#define bit_arch_CLWB_Usable (1u << 0) ++#define bit_arch_SHA_Usable (1u << 0) ++#define bit_arch_PREFETCHWT1_Usable (1u << 0) ++#define bit_arch_GFNI_Usable (1u << 0) ++#define bit_arch_RDPID_Usable (1u << 0) ++#define bit_arch_CLDEMOTE_Usable (1u << 0) ++#define bit_arch_MOVDIRI_Usable (1u << 0) ++#define bit_arch_MOVDIR64B_Usable (1u << 0) ++#define bit_arch_FSRM_Usable (1u << 0) ++#define bit_arch_LAHF64_SAHF64_Usable (1u << 0) ++#define bit_arch_SVM_Usable (1u << 0) ++#define bit_arch_LZCNT_Usable (1u << 0) ++#define bit_arch_SSE4A_Usable (1u << 0) ++#define bit_arch_PREFETCHW_Usable (1u << 0) ++#define bit_arch_TBM_Usable (1u << 0) ++#define bit_arch_SYSCALL_SYSRET_Usable (1u << 0) ++#define bit_arch_RDTSCP_Usable (1u << 0) ++#define bit_arch_XSAVEOPT_Usable (1u << 0) ++#define bit_arch_XGETBV_ECX_1_Usable (1u << 0) ++#define bit_arch_XSAVES_Usable (1u << 0) ++#define bit_arch_INVARIANT_TSC_Usable (1u << 0) ++#define bit_arch_WBNOINVD_Usable (1u << 0) ++ ++/* Unused. Compiler will optimize them out. */ ++#define index_arch_SSE3_Usable FEATURE_INDEX_1 ++#define index_arch_PCLMULQDQ_Usable FEATURE_INDEX_1 ++#define index_arch_SSSE3_Usable FEATURE_INDEX_1 ++#define index_arch_CMPXCHG16B_Usable FEATURE_INDEX_1 ++#define index_arch_SSE4_1_Usable FEATURE_INDEX_1 ++#define index_arch_SSE4_2_Usable FEATURE_INDEX_1 ++#define index_arch_MOVBE_Usable FEATURE_INDEX_1 ++#define index_arch_POPCNT_Usable FEATURE_INDEX_1 ++#define index_arch_AES_Usable FEATURE_INDEX_1 ++#define index_arch_XSAVE_Usable FEATURE_INDEX_1 ++#define index_arch_OSXSAVE_Usable FEATURE_INDEX_1 ++#define index_arch_F16C_Usable FEATURE_INDEX_1 ++#define index_arch_RDRAND_Usable FEATURE_INDEX_1 ++#define index_arch_FPU_Usable FEATURE_INDEX_1 ++#define index_arch_TSC_Usable FEATURE_INDEX_1 ++#define index_arch_MSR_Usable FEATURE_INDEX_1 ++#define index_arch_CX8_Usable FEATURE_INDEX_1 ++#define index_arch_SEP_Usable FEATURE_INDEX_1 ++#define index_arch_CMOV_Usable FEATURE_INDEX_1 ++#define index_arch_CLFSH_Usable FEATURE_INDEX_1 ++#define index_arch_MMX_Usable FEATURE_INDEX_1 ++#define index_arch_FXSR_Usable FEATURE_INDEX_1 ++#define index_arch_SSE_Usable FEATURE_INDEX_1 ++#define index_arch_SSE2_Usable FEATURE_INDEX_1 ++#define index_arch_FSGSBASE_Usable FEATURE_INDEX_1 ++#define index_arch_BMI1_Usable FEATURE_INDEX_1 ++#define index_arch_HLE_Usable FEATURE_INDEX_1 ++#define index_arch_BMI2_Usable FEATURE_INDEX_1 ++#define index_arch_ERMS_Usable FEATURE_INDEX_1 ++#define index_arch_RTM_Usable FEATURE_INDEX_1 ++#define index_arch_RDSEED_Usable FEATURE_INDEX_1 ++#define index_arch_ADX_Usable FEATURE_INDEX_1 ++#define index_arch_CLFLUSHOPT_Usable FEATURE_INDEX_1 ++#define index_arch_CLWB_Usable FEATURE_INDEX_1 ++#define index_arch_SHA_Usable FEATURE_INDEX_1 ++#define index_arch_PREFETCHWT1_Usable FEATURE_INDEX_1 ++#define index_arch_GFNI_Usable FEATURE_INDEX_1 ++#define index_arch_RDPID_Usable FEATURE_INDEX_1 ++#define index_arch_CLDEMOTE_Usable FEATURE_INDEX_1 ++#define index_arch_MOVDIRI_Usable FEATURE_INDEX_1 ++#define index_arch_MOVDIR64B_Usable FEATURE_INDEX_1 ++#define index_arch_FSRM_Usable FEATURE_INDEX_1 ++#define index_arch_LAHF64_SAHF64_Usable FEATURE_INDEX_1 ++#define index_arch_LZCNT_Usable FEATURE_INDEX_1 ++#define index_arch_SSE4A_Usable FEATURE_INDEX_1 ++#define index_arch_PREFETCHW_Usable FEATURE_INDEX_1 ++#define index_arch_TBM_Usable FEATURE_INDEX_1 ++#define index_arch_SYSCALL_SYSRET_Usable FEATURE_INDEX_1 ++#define index_arch_RDTSCP_Usable FEATURE_INDEX_1 ++#define index_arch_XSAVEOPT_Usable FEATURE_INDEX_1 ++#define index_arch_XGETBV_ECX_1_Usable FEATURE_INDEX_1 ++#define index_arch_XSAVES_Usable FEATURE_INDEX_1 ++#define index_arch_INVARIANT_TSC_Usable FEATURE_INDEX_1 ++#define index_arch_WBNOINVD_Usable FEATURE_INDEX_1 ++ ++/* COMMON_CPUID_INDEX_1. */ ++ ++/* ECX. */ ++#define need_arch_feature_SSE3 0 ++#define need_arch_feature_PCLMULQDQ 0 ++#define need_arch_feature_SSSE3 0 ++#define need_arch_feature_FMA 1 ++#define need_arch_feature_CMPXCHG16B 0 ++#define need_arch_feature_SSE4_1 0 ++#define need_arch_feature_SSE4_2 0 ++#define need_arch_feature_MOVBE 0 ++#define need_arch_feature_POPCNT 0 ++#define need_arch_feature_AES 0 ++#define need_arch_feature_XSAVE 0 ++#define need_arch_feature_OSXSAVE 0 ++#define need_arch_feature_AVX 1 ++#define need_arch_feature_F16C 0 ++#define need_arch_feature_RDRAND 0 ++ ++/* EDX. */ ++#define need_arch_feature_FPU 0 ++#define need_arch_feature_TSC 0 ++#define need_arch_feature_MSR 0 ++#define need_arch_feature_CX8 0 ++#define need_arch_feature_SEP 0 ++#define need_arch_feature_CMOV 0 ++#define need_arch_feature_CLFSH 0 ++#define need_arch_feature_MMX 0 ++#define need_arch_feature_FXSR 0 ++#define need_arch_feature_SSE 0 ++#define need_arch_feature_SSE2 0 ++ ++/* COMMON_CPUID_INDEX_7. */ ++ ++/* EBX. */ ++#define need_arch_feature_FSGSBASE 0 ++#define need_arch_feature_BMI1 0 ++#define need_arch_feature_HLE 0 ++#define need_arch_feature_AVX2 1 ++#define need_arch_feature_BMI2 0 ++#define need_arch_feature_ERMS 0 ++#define need_arch_feature_RTM 0 ++#define need_arch_feature_AVX512F 1 ++#define need_arch_feature_AVX512DQ 1 ++#define need_arch_feature_RDSEED 0 ++#define need_arch_feature_ADX 0 ++#define need_arch_feature_AVX512_IFMA 1 ++#define need_arch_feature_CLFLUSHOPT 0 ++#define need_arch_feature_CLWB 0 ++#define need_arch_feature_AVX512PF 1 ++#define need_arch_feature_AVX512ER 1 ++#define need_arch_feature_AVX512CD 1 ++#define need_arch_feature_SHA 0 ++#define need_arch_feature_AVX512BW 1 ++#define need_arch_feature_AVX512VL 1 ++ ++/* ECX. */ ++#define need_arch_feature_PREFETCHWT1 0 ++#define need_arch_feature_AVX512_VBMI 1 ++#define need_arch_feature_AVX512_VBMI2 1 ++#define need_arch_feature_GFNI 0 ++#define need_arch_feature_VAES 1 ++#define need_arch_feature_VPCLMULQDQ 1 ++#define need_arch_feature_AVX512_VNNI 1 ++#define need_arch_feature_AVX512_BITALG 1 ++#define need_arch_feature_AVX512_VPOPCNTDQ 1 ++#define need_arch_feature_RDPID 0 ++#define need_arch_feature_CLDEMOTE 0 ++#define need_arch_feature_MOVDIRI 0 ++#define need_arch_feature_MOVDIR64B 0 ++ ++/* EDX. */ ++#define need_arch_feature_AVX512_4VNNIW 1 ++#define need_arch_feature_AVX512_4FMAPS 1 ++#define need_arch_feature_FSRM 0 ++ ++/* COMMON_CPUID_INDEX_80000001. */ ++ ++/* ECX. */ ++#define need_arch_feature_LAHF64_SAHF64 0 ++#define need_arch_feature_LZCNT 0 ++#define need_arch_feature_SSE4A 0 ++#define need_arch_feature_PREFETCHW 0 ++#define need_arch_feature_XOP 1 ++#define need_arch_feature_FMA4 1 ++#define need_arch_feature_TBM 0 ++#define need_arch_feature_SYSCALL_SYSRET 0 ++#define need_arch_feature_RDTSCP 0 ++#define need_arch_feature_XSAVEOPT 0 ++#define need_arch_feature_XSAVEC 1 ++#define need_arch_feature_XGETBV_ECX_1 0 ++#define need_arch_feature_XSAVES 0 ++#define need_arch_feature_INVARIANT_TSC 0 ++#define need_arch_feature_WBNOINVD 0 ++ ++/* CPU features. */ ++ ++/* COMMON_CPUID_INDEX_1. */ ++ ++/* ECX. */ ++#define bit_cpu_SSE3 (1u << 0) ++#define bit_cpu_PCLMULQDQ (1u << 1) ++#define bit_cpu_DTES64 (1u << 2) ++#define bit_cpu_MONITOR (1u << 3) ++#define bit_cpu_DS_CPL (1u << 4) ++#define bit_cpu_VMX (1u << 5) ++#define bit_cpu_SMX (1u << 6) ++#define bit_cpu_EST (1u << 7) ++#define bit_cpu_TM2 (1u << 8) ++#define bit_cpu_SSSE3 (1u << 9) ++#define bit_cpu_CNXT_ID (1u << 10) ++#define bit_cpu_SDBG (1u << 11) ++#define bit_cpu_FMA (1u << 12) ++#define bit_cpu_CMPXCHG16B (1u << 13) ++#define bit_cpu_XTPRUPDCTRL (1u << 14) ++#define bit_cpu_PDCM (1u << 15) ++#define bit_cpu_PCID (1u << 17) ++#define bit_cpu_DCA (1u << 18) ++#define bit_cpu_SSE4_1 (1u << 19) ++#define bit_cpu_SSE4_2 (1u << 20) ++#define bit_cpu_X2APIC (1u << 21) ++#define bit_cpu_MOVBE (1u << 22) ++#define bit_cpu_POPCNT (1u << 23) ++#define bit_cpu_TSC_DEADLINE (1u << 24) ++#define bit_cpu_AES (1u << 25) ++#define bit_cpu_XSAVE (1u << 26) ++#define bit_cpu_OSXSAVE (1u << 27) ++#define bit_cpu_AVX (1u << 28) ++#define bit_cpu_F16C (1u << 29) ++#define bit_cpu_RDRAND (1u << 30) ++ ++/* EDX. */ ++#define bit_cpu_FPU (1u << 0) ++#define bit_cpu_VME (1u << 1) ++#define bit_cpu_DE (1u << 2) ++#define bit_cpu_PSE (1u << 3) ++#define bit_cpu_TSC (1u << 4) ++#define bit_cpu_MSR (1u << 5) ++#define bit_cpu_PAE (1u << 6) ++#define bit_cpu_MCE (1u << 7) ++#define bit_cpu_CX8 (1u << 8) ++#define bit_cpu_APIC (1u << 9) ++#define bit_cpu_SEP (1u << 11) ++#define bit_cpu_MTRR (1u << 12) ++#define bit_cpu_PGE (1u << 13) ++#define bit_cpu_MCA (1u << 14) ++#define bit_cpu_CMOV (1u << 15) ++#define bit_cpu_PAT (1u << 16) ++#define bit_cpu_PSE_36 (1u << 17) ++#define bit_cpu_PSN (1u << 18) ++#define bit_cpu_CLFSH (1u << 20) ++#define bit_cpu_DS (1u << 21) ++#define bit_cpu_ACPI (1u << 22) ++#define bit_cpu_MMX (1u << 23) ++#define bit_cpu_FXSR (1u << 24) ++#define bit_cpu_SSE (1u << 25) ++#define bit_cpu_SSE2 (1u << 26) ++#define bit_cpu_SS (1u << 27) ++#define bit_cpu_HTT (1u << 28) ++#define bit_cpu_TM (1u << 29) ++#define bit_cpu_PBE (1u << 31) ++ ++/* COMMON_CPUID_INDEX_7. */ ++ ++/* EBX. */ ++#define bit_cpu_FSGSBASE (1u << 0) ++#define bit_cpu_TSC_ADJUST (1u << 1) ++#define bit_cpu_SGX (1u << 2) ++#define bit_cpu_BMI1 (1u << 3) ++#define bit_cpu_HLE (1u << 4) ++#define bit_cpu_AVX2 (1u << 5) ++#define bit_cpu_SMEP (1u << 7) ++#define bit_cpu_BMI2 (1u << 8) ++#define bit_cpu_ERMS (1u << 9) ++#define bit_cpu_INVPCID (1u << 10) ++#define bit_cpu_RTM (1u << 11) ++#define bit_cpu_PQM (1u << 12) ++#define bit_cpu_MPX (1u << 14) ++#define bit_cpu_PQE (1u << 15) ++#define bit_cpu_AVX512F (1u << 16) ++#define bit_cpu_AVX512DQ (1u << 17) ++#define bit_cpu_RDSEED (1u << 18) ++#define bit_cpu_ADX (1u << 19) ++#define bit_cpu_SMAP (1u << 20) ++#define bit_cpu_AVX512_IFMA (1u << 21) ++#define bit_cpu_CLFLUSHOPT (1u << 22) ++#define bit_cpu_CLWB (1u << 24) ++#define bit_cpu_TRACE (1u << 25) ++#define bit_cpu_AVX512PF (1u << 26) ++#define bit_cpu_AVX512ER (1u << 27) ++#define bit_cpu_AVX512CD (1u << 28) ++#define bit_cpu_SHA (1u << 29) ++#define bit_cpu_AVX512BW (1u << 30) ++#define bit_cpu_AVX512VL (1u << 31) ++ ++/* ECX. */ ++#define bit_cpu_PREFETCHWT1 (1u << 0) ++#define bit_cpu_AVX512_VBMI (1u << 1) ++#define bit_cpu_UMIP (1u << 2) ++#define bit_cpu_PKU (1u << 3) ++#define bit_cpu_OSPKE (1u << 4) ++#define bit_cpu_WAITPKG (1u << 5) ++#define bit_cpu_AVX512_VBMI2 (1u << 6) ++#define bit_cpu_SHSTK (1u << 7) ++#define bit_cpu_GFNI (1u << 8) ++#define bit_cpu_VAES (1u << 9) ++#define bit_cpu_VPCLMULQDQ (1u << 10) ++#define bit_cpu_AVX512_VNNI (1u << 11) ++#define bit_cpu_AVX512_BITALG (1u << 12) ++#define bit_cpu_AVX512_VPOPCNTDQ (1u << 14) ++#define bit_cpu_RDPID (1u << 22) ++#define bit_cpu_CLDEMOTE (1u << 25) ++#define bit_cpu_MOVDIRI (1u << 27) ++#define bit_cpu_MOVDIR64B (1u << 28) ++#define bit_cpu_SGX_LC (1u << 30) ++ ++/* EDX. */ ++#define bit_cpu_AVX512_4VNNIW (1u << 2) ++#define bit_cpu_AVX512_4FMAPS (1u << 3) ++#define bit_cpu_FSRM (1u << 4) ++#define bit_cpu_PCONFIG (1u << 18) ++#define bit_cpu_IBT (1u << 20) ++#define bit_cpu_IBRS_IBPB (1u << 26) ++#define bit_cpu_STIBP (1u << 27) ++#define bit_cpu_CAPABILITIES (1u << 29) ++#define bit_cpu_SSBD (1u << 31) ++ ++/* COMMON_CPUID_INDEX_80000001. */ ++ ++/* ECX. */ ++#define bit_cpu_LAHF64_SAHF64 (1u << 0) ++#define bit_cpu_SVM (1u << 2) ++#define bit_cpu_LZCNT (1u << 5) ++#define bit_cpu_SSE4A (1u << 6) ++#define bit_cpu_PREFETCHW (1u << 8) ++#define bit_cpu_XOP (1u << 11) ++#define bit_cpu_LWP (1u << 15) ++#define bit_cpu_FMA4 (1u << 16) ++#define bit_cpu_TBM (1u << 21) ++ ++/* EDX. */ ++#define bit_cpu_SYSCALL_SYSRET (1u << 11) ++#define bit_cpu_NX (1u << 20) ++#define bit_cpu_PAGE1GB (1u << 26) ++#define bit_cpu_RDTSCP (1u << 27) ++#define bit_cpu_LM (1u << 29) ++ ++/* COMMON_CPUID_INDEX_D_ECX_1. */ ++ ++/* EAX. */ ++#define bit_cpu_XSAVEOPT (1u << 0) ++#define bit_cpu_XSAVEC (1u << 1) ++#define bit_cpu_XGETBV_ECX_1 (1u << 2) ++#define bit_cpu_XSAVES (1u << 3) ++ ++/* COMMON_CPUID_INDEX_80000007. */ ++ ++/* EDX. */ ++#define bit_cpu_INVARIANT_TSC (1u << 8) ++ ++/* COMMON_CPUID_INDEX_80000008. */ ++ ++/* EBX. */ ++#define bit_cpu_WBNOINVD (1u << 9) ++ ++/* COMMON_CPUID_INDEX_1. */ ++ ++/* ECX. */ ++#define index_cpu_SSE3 COMMON_CPUID_INDEX_1 ++#define index_cpu_PCLMULQDQ COMMON_CPUID_INDEX_1 ++#define index_cpu_DTES64 COMMON_CPUID_INDEX_1 ++#define index_cpu_MONITOR COMMON_CPUID_INDEX_1 ++#define index_cpu_DS_CPL COMMON_CPUID_INDEX_1 ++#define index_cpu_VMX COMMON_CPUID_INDEX_1 ++#define index_cpu_SMX COMMON_CPUID_INDEX_1 ++#define index_cpu_EST COMMON_CPUID_INDEX_1 ++#define index_cpu_TM2 COMMON_CPUID_INDEX_1 ++#define index_cpu_SSSE3 COMMON_CPUID_INDEX_1 ++#define index_cpu_CNXT_ID COMMON_CPUID_INDEX_1 ++#define index_cpu_SDBG COMMON_CPUID_INDEX_1 ++#define index_cpu_FMA COMMON_CPUID_INDEX_1 ++#define index_cpu_CMPXCHG16B COMMON_CPUID_INDEX_1 ++#define index_cpu_XTPRUPDCTRL COMMON_CPUID_INDEX_1 ++#define index_cpu_PDCM COMMON_CPUID_INDEX_1 ++#define index_cpu_PCID COMMON_CPUID_INDEX_1 ++#define index_cpu_DCA COMMON_CPUID_INDEX_1 ++#define index_cpu_SSE4_1 COMMON_CPUID_INDEX_1 ++#define index_cpu_SSE4_2 COMMON_CPUID_INDEX_1 ++#define index_cpu_X2APIC COMMON_CPUID_INDEX_1 ++#define index_cpu_MOVBE COMMON_CPUID_INDEX_1 ++#define index_cpu_POPCNT COMMON_CPUID_INDEX_1 ++#define index_cpu_TSC_DEADLINE COMMON_CPUID_INDEX_1 ++#define index_cpu_AES COMMON_CPUID_INDEX_1 ++#define index_cpu_XSAVE COMMON_CPUID_INDEX_1 ++#define index_cpu_OSXSAVE COMMON_CPUID_INDEX_1 ++#define index_cpu_AVX COMMON_CPUID_INDEX_1 ++#define index_cpu_F16C COMMON_CPUID_INDEX_1 ++#define index_cpu_RDRAND COMMON_CPUID_INDEX_1 ++ ++/* ECX. */ ++#define index_cpu_FPU COMMON_CPUID_INDEX_1 ++#define index_cpu_VME COMMON_CPUID_INDEX_1 ++#define index_cpu_DE COMMON_CPUID_INDEX_1 ++#define index_cpu_PSE COMMON_CPUID_INDEX_1 ++#define index_cpu_TSC COMMON_CPUID_INDEX_1 ++#define index_cpu_MSR COMMON_CPUID_INDEX_1 ++#define index_cpu_PAE COMMON_CPUID_INDEX_1 ++#define index_cpu_MCE COMMON_CPUID_INDEX_1 ++#define index_cpu_CX8 COMMON_CPUID_INDEX_1 ++#define index_cpu_APIC COMMON_CPUID_INDEX_1 ++#define index_cpu_SEP COMMON_CPUID_INDEX_1 ++#define index_cpu_MTRR COMMON_CPUID_INDEX_1 ++#define index_cpu_PGE COMMON_CPUID_INDEX_1 ++#define index_cpu_MCA COMMON_CPUID_INDEX_1 ++#define index_cpu_CMOV COMMON_CPUID_INDEX_1 ++#define index_cpu_PAT COMMON_CPUID_INDEX_1 ++#define index_cpu_PSE_36 COMMON_CPUID_INDEX_1 ++#define index_cpu_PSN COMMON_CPUID_INDEX_1 ++#define index_cpu_CLFSH COMMON_CPUID_INDEX_1 ++#define index_cpu_DS COMMON_CPUID_INDEX_1 ++#define index_cpu_ACPI COMMON_CPUID_INDEX_1 ++#define index_cpu_MMX COMMON_CPUID_INDEX_1 ++#define index_cpu_FXSR COMMON_CPUID_INDEX_1 ++#define index_cpu_SSE COMMON_CPUID_INDEX_1 ++#define index_cpu_SSE2 COMMON_CPUID_INDEX_1 ++#define index_cpu_SS COMMON_CPUID_INDEX_1 ++#define index_cpu_HTT COMMON_CPUID_INDEX_1 ++#define index_cpu_TM COMMON_CPUID_INDEX_1 ++#define index_cpu_PBE COMMON_CPUID_INDEX_1 ++ ++/* COMMON_CPUID_INDEX_7. */ ++ ++/* EBX. */ ++#define index_cpu_FSGSBASE COMMON_CPUID_INDEX_7 ++#define index_cpu_TSC_ADJUST COMMON_CPUID_INDEX_7 ++#define index_cpu_SGX COMMON_CPUID_INDEX_7 ++#define index_cpu_BMI1 COMMON_CPUID_INDEX_7 ++#define index_cpu_HLE COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX2 COMMON_CPUID_INDEX_7 ++#define index_cpu_SMEP COMMON_CPUID_INDEX_7 ++#define index_cpu_BMI2 COMMON_CPUID_INDEX_7 ++#define index_cpu_ERMS COMMON_CPUID_INDEX_7 ++#define index_cpu_INVPCID COMMON_CPUID_INDEX_7 ++#define index_cpu_RTM COMMON_CPUID_INDEX_7 ++#define index_cpu_PQM COMMON_CPUID_INDEX_7 ++#define index_cpu_MPX COMMON_CPUID_INDEX_7 ++#define index_cpu_PQE COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512F COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512DQ COMMON_CPUID_INDEX_7 ++#define index_cpu_RDSEED COMMON_CPUID_INDEX_7 ++#define index_cpu_ADX COMMON_CPUID_INDEX_7 ++#define index_cpu_SMAP COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512_IFMA COMMON_CPUID_INDEX_7 ++#define index_cpu_CLFLUSHOPT COMMON_CPUID_INDEX_7 ++#define index_cpu_CLWB COMMON_CPUID_INDEX_7 ++#define index_cpu_TRACE COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512PF COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512ER COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512CD COMMON_CPUID_INDEX_7 ++#define index_cpu_SHA COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512BW COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512VL COMMON_CPUID_INDEX_7 ++ ++/* ECX. */ ++#define index_cpu_PREFETCHWT1 COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512_VBMI COMMON_CPUID_INDEX_7 ++#define index_cpu_UMIP COMMON_CPUID_INDEX_7 ++#define index_cpu_PKU COMMON_CPUID_INDEX_7 ++#define index_cpu_OSPKE COMMON_CPUID_INDEX_7 ++#define index_cpu_WAITPKG COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512_VBMI2 COMMON_CPUID_INDEX_7 ++#define index_cpu_SHSTK COMMON_CPUID_INDEX_7 ++#define index_cpu_GFNI COMMON_CPUID_INDEX_7 ++#define index_cpu_VAES COMMON_CPUID_INDEX_7 ++#define index_cpu_VPCLMULQDQ COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512_VNNI COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512_BITALG COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512_VPOPCNTDQ COMMON_CPUID_INDEX_7 ++#define index_cpu_RDPID COMMON_CPUID_INDEX_7 ++#define index_cpu_CLDEMOTE COMMON_CPUID_INDEX_7 ++#define index_cpu_MOVDIRI COMMON_CPUID_INDEX_7 ++#define index_cpu_MOVDIR64B COMMON_CPUID_INDEX_7 ++#define index_cpu_SGX_LC COMMON_CPUID_INDEX_7 ++ ++/* EDX. */ ++#define index_cpu_AVX512_4VNNIW COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512_4FMAPS COMMON_CPUID_INDEX_7 ++#define index_cpu_FSRM COMMON_CPUID_INDEX_7 ++#define index_cpu_PCONFIG COMMON_CPUID_INDEX_7 ++#define index_cpu_IBT COMMON_CPUID_INDEX_7 ++#define index_cpu_IBRS_IBPB COMMON_CPUID_INDEX_7 ++#define index_cpu_STIBP COMMON_CPUID_INDEX_7 ++#define index_cpu_CAPABILITIES COMMON_CPUID_INDEX_7 ++#define index_cpu_SSBD COMMON_CPUID_INDEX_7 ++ ++/* COMMON_CPUID_INDEX_80000001. */ ++ ++/* ECX. */ ++#define index_cpu_LAHF64_SAHF64 COMMON_CPUID_INDEX_80000001 ++#define index_cpu_SVM COMMON_CPUID_INDEX_80000001 ++#define index_cpu_LZCNT COMMON_CPUID_INDEX_80000001 ++#define index_cpu_SSE4A COMMON_CPUID_INDEX_80000001 ++#define index_cpu_PREFETCHW COMMON_CPUID_INDEX_80000001 ++#define index_cpu_XOP COMMON_CPUID_INDEX_80000001 ++#define index_cpu_LWP COMMON_CPUID_INDEX_80000001 ++#define index_cpu_FMA4 COMMON_CPUID_INDEX_80000001 ++#define index_cpu_TBM COMMON_CPUID_INDEX_80000001 ++ ++/* EDX. */ ++#define index_cpu_SYSCALL_SYSRET COMMON_CPUID_INDEX_80000001 ++#define index_cpu_NX COMMON_CPUID_INDEX_80000001 ++#define index_cpu_PAGE1GB COMMON_CPUID_INDEX_80000001 ++#define index_cpu_RDTSCP COMMON_CPUID_INDEX_80000001 ++#define index_cpu_LM COMMON_CPUID_INDEX_80000001 ++ ++/* COMMON_CPUID_INDEX_D_ECX_1. */ ++ ++/* EAX. */ ++#define index_cpu_XSAVEOPT COMMON_CPUID_INDEX_D_ECX_1 ++#define index_cpu_XSAVEC COMMON_CPUID_INDEX_D_ECX_1 ++#define index_cpu_XGETBV_ECX_1 COMMON_CPUID_INDEX_D_ECX_1 ++#define index_cpu_XSAVES COMMON_CPUID_INDEX_D_ECX_1 ++ ++/* COMMON_CPUID_INDEX_80000007. */ ++ ++/* EDX. */ ++#define index_cpu_INVARIANT_TSC COMMON_CPUID_INDEX_80000007 ++ ++/* COMMON_CPUID_INDEX_80000008. */ ++ ++/* EBX. */ ++#define index_cpu_WBNOINVD COMMON_CPUID_INDEX_80000008 ++ ++/* COMMON_CPUID_INDEX_1. */ ++ ++/* ECX. */ ++#define reg_SSE3 ecx ++#define reg_PCLMULQDQ ecx ++#define reg_DTES64 ecx ++#define reg_MONITOR ecx ++#define reg_DS_CPL ecx ++#define reg_VMX ecx ++#define reg_SMX ecx ++#define reg_EST ecx ++#define reg_TM2 ecx ++#define reg_SSSE3 ecx ++#define reg_CNXT_ID ecx ++#define reg_SDBG ecx ++#define reg_FMA ecx ++#define reg_CMPXCHG16B ecx ++#define reg_XTPRUPDCTRL ecx ++#define reg_PDCM ecx ++#define reg_PCID ecx ++#define reg_DCA ecx ++#define reg_SSE4_1 ecx ++#define reg_SSE4_2 ecx ++#define reg_X2APIC ecx ++#define reg_MOVBE ecx ++#define reg_POPCNT ecx ++#define reg_TSC_DEADLINE ecx ++#define reg_AES ecx ++#define reg_XSAVE ecx ++#define reg_OSXSAVE ecx ++#define reg_AVX ecx ++#define reg_F16C ecx ++#define reg_RDRAND ecx ++ ++/* EDX. */ ++#define reg_FPU edx ++#define reg_VME edx ++#define reg_DE edx ++#define reg_PSE edx ++#define reg_TSC edx ++#define reg_MSR edx ++#define reg_PAE edx ++#define reg_MCE edx ++#define reg_CX8 edx ++#define reg_APIC edx ++#define reg_SEP edx ++#define reg_MTRR edx ++#define reg_PGE edx ++#define reg_MCA edx ++#define reg_CMOV edx ++#define reg_PAT edx ++#define reg_PSE_36 edx ++#define reg_PSN edx ++#define reg_CLFSH edx ++#define reg_DS edx ++#define reg_ACPI edx ++#define reg_MMX edx ++#define reg_FXSR edx ++#define reg_SSE edx ++#define reg_SSE2 edx ++#define reg_SS edx ++#define reg_HTT edx ++#define reg_TM edx ++#define reg_PBE edx ++ ++/* COMMON_CPUID_INDEX_7. */ ++ ++/* EBX. */ ++#define reg_FSGSBASE ebx ++#define reg_TSC_ADJUST ebx ++#define reg_SGX ebx ++#define reg_BMI1 ebx ++#define reg_HLE ebx ++#define reg_BMI2 ebx ++#define reg_AVX2 ebx ++#define reg_SMEP ebx ++#define reg_ERMS ebx ++#define reg_INVPCID ebx ++#define reg_RTM ebx ++#define reg_PQM ebx ++#define reg_MPX ebx ++#define reg_PQE ebx ++#define reg_AVX512F ebx ++#define reg_AVX512DQ ebx ++#define reg_RDSEED ebx ++#define reg_ADX ebx ++#define reg_SMAP ebx ++#define reg_AVX512_IFMA ebx ++#define reg_CLFLUSHOPT ebx ++#define reg_CLWB ebx ++#define reg_TRACE ebx ++#define reg_AVX512PF ebx ++#define reg_AVX512ER ebx ++#define reg_AVX512CD ebx ++#define reg_SHA ebx ++#define reg_AVX512BW ebx ++#define reg_AVX512VL ebx ++ ++/* ECX. */ ++#define reg_PREFETCHWT1 ecx ++#define reg_AVX512_VBMI ecx ++#define reg_UMIP ecx ++#define reg_PKU ecx ++#define reg_OSPKE ecx ++#define reg_WAITPKG ecx ++#define reg_AVX512_VBMI2 ecx ++#define reg_SHSTK ecx ++#define reg_GFNI ecx ++#define reg_VAES ecx ++#define reg_VPCLMULQDQ ecx ++#define reg_AVX512_VNNI ecx ++#define reg_AVX512_BITALG ecx ++#define reg_AVX512_VPOPCNTDQ ecx ++#define reg_RDPID ecx ++#define reg_CLDEMOTE ecx ++#define reg_MOVDIRI ecx ++#define reg_MOVDIR64B ecx ++#define reg_SGX_LC ecx ++ ++/* EDX. */ ++#define reg_AVX512_4VNNIW edx ++#define reg_AVX512_4FMAPS edx ++#define reg_FSRM edx ++#define reg_PCONFIG edx ++#define reg_IBT edx ++#define reg_IBRS_IBPB edx ++#define reg_STIBP edx ++#define reg_CAPABILITIES edx ++#define reg_SSBD edx ++ ++/* COMMON_CPUID_INDEX_80000001. */ ++ ++/* ECX. */ ++#define reg_LAHF64_SAHF64 ecx ++#define reg_SVM ecx ++#define reg_LZCNT ecx ++#define reg_SSE4A ecx ++#define reg_PREFETCHW ecx ++#define reg_XOP ecx ++#define reg_LWP ecx ++#define reg_FMA4 ecx ++#define reg_TBM ecx ++ ++/* EDX. */ ++#define reg_SYSCALL_SYSRET edx ++#define reg_NX edx ++#define reg_PAGE1GB edx ++#define reg_RDTSCP edx ++#define reg_LM edx ++ ++/* COMMON_CPUID_INDEX_D_ECX_1. */ ++ ++/* EAX. */ ++#define reg_XSAVEOPT eax ++#define reg_XSAVEC eax ++#define reg_XGETBV_ECX_1 eax ++#define reg_XSAVES eax ++ ++/* COMMON_CPUID_INDEX_80000007. */ ++ ++/* EDX. */ ++#define reg_INVARIANT_TSC edx ++ ++/* COMMON_CPUID_INDEX_80000008. */ ++ ++/* EBX. */ ++#define reg_WBNOINVD ebx ++ ++/* FEATURE_INDEX_2. */ ++#define bit_arch_I586 (1u << 0) ++#define bit_arch_I686 (1u << 1) ++#define bit_arch_Fast_Rep_String (1u << 2) ++#define bit_arch_Fast_Copy_Backward (1u << 3) ++#define bit_arch_Fast_Unaligned_Load (1u << 4) ++#define bit_arch_Fast_Unaligned_Copy (1u << 5) ++#define bit_arch_Slow_BSF (1u << 6) ++#define bit_arch_Slow_SSE4_2 (1u << 7) ++#define bit_arch_AVX_Fast_Unaligned_Load (1u << 8) ++#define bit_arch_Prefer_MAP_32BIT_EXEC (1u << 9) ++#define bit_arch_Prefer_PMINUB_for_stringop (1u << 10) ++#define bit_arch_Prefer_No_VZEROUPPER (1u << 11) ++#define bit_arch_Prefer_ERMS (1u << 12) ++#define bit_arch_Prefer_FSRM (1u << 13) ++#define bit_arch_Prefer_No_AVX512 (1u << 14) ++#define bit_arch_MathVec_Prefer_No_AVX512 (1u << 15) ++ ++#define index_arch_Fast_Rep_String FEATURE_INDEX_2 ++#define index_arch_Fast_Copy_Backward FEATURE_INDEX_2 ++#define index_arch_Slow_BSF FEATURE_INDEX_2 ++#define index_arch_Fast_Unaligned_Load FEATURE_INDEX_2 ++#define index_arch_Prefer_PMINUB_for_stringop FEATURE_INDEX_2 ++#define index_arch_Fast_Unaligned_Copy FEATURE_INDEX_2 ++#define index_arch_I586 FEATURE_INDEX_2 ++#define index_arch_I686 FEATURE_INDEX_2 ++#define index_arch_Slow_SSE4_2 FEATURE_INDEX_2 ++#define index_arch_AVX_Fast_Unaligned_Load FEATURE_INDEX_2 ++#define index_arch_Prefer_MAP_32BIT_EXEC FEATURE_INDEX_2 ++#define index_arch_Prefer_No_VZEROUPPER FEATURE_INDEX_2 ++#define index_arch_Prefer_ERMS FEATURE_INDEX_2 ++#define index_arch_Prefer_No_AVX512 FEATURE_INDEX_2 ++#define index_arch_MathVec_Prefer_No_AVX512 FEATURE_INDEX_2 ++#define index_arch_Prefer_FSRM FEATURE_INDEX_2 ++ ++/* XCR0 Feature flags. */ ++#define bit_XMM_state (1u << 1) ++#define bit_YMM_state (1u << 2) ++#define bit_Opmask_state (1u << 5) ++#define bit_ZMM0_15_state (1u << 6) ++#define bit_ZMM16_31_state (1u << 7) ++ ++# if defined (_LIBC) && !IS_IN (nonlib) ++/* Unused for x86. */ ++# define INIT_ARCH() ++# define __get_cpu_features() (&GLRO(dl_x86_cpu_features)) ++# define x86_get_cpuid_registers(i) \ ++ (&(GLRO(dl_x86_cpu_features).cpuid[i])) ++# endif + + #ifdef __x86_64__ + # define HAS_CPUID 1 +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index b2fac197dac7708e..64a7fd6157242bdd 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -17,15 +17,271 @@ + . */ + + #include ++#include + #include ++#include ++ ++#define CHECK_CPU_FEATURE(name) \ ++ { \ ++ if (HAS_CPU_FEATURE (name)) \ ++ printf (" " #name "\n"); \ ++ } ++ ++#define CHECK_CPU_FEATURE_USABLE(name) \ ++ { \ ++ if (CPU_FEATURE_USABLE(name)) \ ++ printf (" " #name "\n"); \ ++ } ++ ++static const char * const cpu_kinds[] = ++{ ++ "Unknown", ++ "Intel", ++ "AMD", ++ "Other", ++}; + + static int + do_test (void) + { +- if (__get_cpu_features ()->kind == arch_kind_unknown) +- abort (); ++ const struct cpu_features *cpu_features = __get_cpu_features (); ++ ++ switch (cpu_features->basic.kind) ++ { ++ case arch_kind_intel: ++ case arch_kind_amd: ++ case arch_kind_other: ++ printf ("Vendor: %s\n", cpu_kinds[cpu_features->basic.kind]); ++ printf ("Family: 0x%x\n", cpu_features->basic.family); ++ printf ("Model: 0x%x\n", cpu_features->basic.model); ++ printf ("Stepping: 0x%x\n", cpu_features->basic.stepping); ++ break; ++ ++ default: ++ abort (); ++ } ++ ++#ifdef __SSE2__ ++ TEST_VERIFY_EXIT (HAS_CPU_FEATURE (SSE2)); ++#endif ++ ++ printf ("CPU features:\n"); ++ CHECK_CPU_FEATURE (SSE3); ++ CHECK_CPU_FEATURE (PCLMULQDQ); ++ CHECK_CPU_FEATURE (DTES64); ++ CHECK_CPU_FEATURE (MONITOR); ++ CHECK_CPU_FEATURE (DS_CPL); ++ CHECK_CPU_FEATURE (VMX); ++ CHECK_CPU_FEATURE (SMX); ++ CHECK_CPU_FEATURE (EST); ++ CHECK_CPU_FEATURE (TM2); ++ CHECK_CPU_FEATURE (SSSE3); ++ CHECK_CPU_FEATURE (CNXT_ID); ++ CHECK_CPU_FEATURE (SDBG); ++ CHECK_CPU_FEATURE (FMA); ++ CHECK_CPU_FEATURE (CMPXCHG16B); ++ CHECK_CPU_FEATURE (XTPRUPDCTRL); ++ CHECK_CPU_FEATURE (PDCM); ++ CHECK_CPU_FEATURE (PCID); ++ CHECK_CPU_FEATURE (DCA); ++ CHECK_CPU_FEATURE (SSE4_1); ++ CHECK_CPU_FEATURE (SSE4_2); ++ CHECK_CPU_FEATURE (X2APIC); ++ CHECK_CPU_FEATURE (MOVBE); ++ CHECK_CPU_FEATURE (POPCNT); ++ CHECK_CPU_FEATURE (TSC_DEADLINE); ++ CHECK_CPU_FEATURE (AES); ++ CHECK_CPU_FEATURE (XSAVE); ++ CHECK_CPU_FEATURE (OSXSAVE); ++ CHECK_CPU_FEATURE (AVX); ++ CHECK_CPU_FEATURE (F16C); ++ CHECK_CPU_FEATURE (RDRAND); ++ CHECK_CPU_FEATURE (FPU); ++ CHECK_CPU_FEATURE (VME); ++ CHECK_CPU_FEATURE (DE); ++ CHECK_CPU_FEATURE (PSE); ++ CHECK_CPU_FEATURE (TSC); ++ CHECK_CPU_FEATURE (MSR); ++ CHECK_CPU_FEATURE (PAE); ++ CHECK_CPU_FEATURE (MCE); ++ CHECK_CPU_FEATURE (CX8); ++ CHECK_CPU_FEATURE (APIC); ++ CHECK_CPU_FEATURE (SEP); ++ CHECK_CPU_FEATURE (MTRR); ++ CHECK_CPU_FEATURE (PGE); ++ CHECK_CPU_FEATURE (MCA); ++ CHECK_CPU_FEATURE (CMOV); ++ CHECK_CPU_FEATURE (PAT); ++ CHECK_CPU_FEATURE (PSE_36); ++ CHECK_CPU_FEATURE (PSN); ++ CHECK_CPU_FEATURE (CLFSH); ++ CHECK_CPU_FEATURE (DS); ++ CHECK_CPU_FEATURE (ACPI); ++ CHECK_CPU_FEATURE (MMX); ++ CHECK_CPU_FEATURE (FXSR); ++ CHECK_CPU_FEATURE (SSE); ++ CHECK_CPU_FEATURE (SSE2); ++ CHECK_CPU_FEATURE (SS); ++ CHECK_CPU_FEATURE (HTT); ++ CHECK_CPU_FEATURE (TM); ++ CHECK_CPU_FEATURE (PBE); ++ CHECK_CPU_FEATURE (FSGSBASE); ++ CHECK_CPU_FEATURE (TSC_ADJUST); ++ CHECK_CPU_FEATURE (SGX); ++ CHECK_CPU_FEATURE (BMI1); ++ CHECK_CPU_FEATURE (HLE); ++ CHECK_CPU_FEATURE (AVX2); ++ CHECK_CPU_FEATURE (SMEP); ++ CHECK_CPU_FEATURE (BMI2); ++ CHECK_CPU_FEATURE (ERMS); ++ CHECK_CPU_FEATURE (INVPCID); ++ CHECK_CPU_FEATURE (RTM); ++ CHECK_CPU_FEATURE (PQM); ++ CHECK_CPU_FEATURE (MPX); ++ CHECK_CPU_FEATURE (PQE); ++ CHECK_CPU_FEATURE (AVX512F); ++ CHECK_CPU_FEATURE (AVX512DQ); ++ CHECK_CPU_FEATURE (RDSEED); ++ CHECK_CPU_FEATURE (ADX); ++ CHECK_CPU_FEATURE (SMAP); ++ CHECK_CPU_FEATURE (AVX512_IFMA); ++ CHECK_CPU_FEATURE (CLFLUSHOPT); ++ CHECK_CPU_FEATURE (CLWB); ++ CHECK_CPU_FEATURE (TRACE); ++ CHECK_CPU_FEATURE (AVX512PF); ++ CHECK_CPU_FEATURE (AVX512ER); ++ CHECK_CPU_FEATURE (AVX512CD); ++ CHECK_CPU_FEATURE (SHA); ++ CHECK_CPU_FEATURE (AVX512BW); ++ CHECK_CPU_FEATURE (AVX512VL); ++ CHECK_CPU_FEATURE (PREFETCHWT1); ++ CHECK_CPU_FEATURE (AVX512_VBMI); ++ CHECK_CPU_FEATURE (UMIP); ++ CHECK_CPU_FEATURE (PKU); ++ CHECK_CPU_FEATURE (OSPKE); ++ CHECK_CPU_FEATURE (WAITPKG); ++ CHECK_CPU_FEATURE (AVX512_VBMI2); ++ CHECK_CPU_FEATURE (SHSTK); ++ CHECK_CPU_FEATURE (GFNI); ++ CHECK_CPU_FEATURE (VAES); ++ CHECK_CPU_FEATURE (VPCLMULQDQ); ++ CHECK_CPU_FEATURE (AVX512_VNNI); ++ CHECK_CPU_FEATURE (AVX512_BITALG); ++ CHECK_CPU_FEATURE (AVX512_VPOPCNTDQ); ++ CHECK_CPU_FEATURE (RDPID); ++ CHECK_CPU_FEATURE (CLDEMOTE); ++ CHECK_CPU_FEATURE (MOVDIRI); ++ CHECK_CPU_FEATURE (MOVDIR64B); ++ CHECK_CPU_FEATURE (SGX_LC); ++ CHECK_CPU_FEATURE (AVX512_4VNNIW); ++ CHECK_CPU_FEATURE (AVX512_4FMAPS); ++ CHECK_CPU_FEATURE (FSRM); ++ CHECK_CPU_FEATURE (PCONFIG); ++ CHECK_CPU_FEATURE (IBT); ++ CHECK_CPU_FEATURE (IBRS_IBPB); ++ CHECK_CPU_FEATURE (STIBP); ++ CHECK_CPU_FEATURE (CAPABILITIES); ++ CHECK_CPU_FEATURE (SSBD); ++ CHECK_CPU_FEATURE (LAHF64_SAHF64); ++ CHECK_CPU_FEATURE (SVM); ++ CHECK_CPU_FEATURE (LZCNT); ++ CHECK_CPU_FEATURE (SSE4A); ++ CHECK_CPU_FEATURE (PREFETCHW); ++ CHECK_CPU_FEATURE (XOP); ++ CHECK_CPU_FEATURE (LWP); ++ CHECK_CPU_FEATURE (FMA4); ++ CHECK_CPU_FEATURE (TBM); ++ CHECK_CPU_FEATURE (SYSCALL_SYSRET); ++ CHECK_CPU_FEATURE (NX); ++ CHECK_CPU_FEATURE (PAGE1GB); ++ CHECK_CPU_FEATURE (RDTSCP); ++ CHECK_CPU_FEATURE (LM); ++ CHECK_CPU_FEATURE (XSAVEOPT); ++ CHECK_CPU_FEATURE (XSAVEC); ++ CHECK_CPU_FEATURE (XGETBV_ECX_1); ++ CHECK_CPU_FEATURE (XSAVES); ++ CHECK_CPU_FEATURE (INVARIANT_TSC); ++ CHECK_CPU_FEATURE (WBNOINVD); ++ ++ printf ("Usable CPU features:\n"); ++ CHECK_CPU_FEATURE_USABLE (SSE3); ++ CHECK_CPU_FEATURE_USABLE (PCLMULQDQ); ++ CHECK_CPU_FEATURE_USABLE (SSSE3); ++ CHECK_CPU_FEATURE_USABLE (FMA); ++ CHECK_CPU_FEATURE_USABLE (CMPXCHG16B); ++ CHECK_CPU_FEATURE_USABLE (SSE4_1); ++ CHECK_CPU_FEATURE_USABLE (SSE4_2); ++ CHECK_CPU_FEATURE_USABLE (MOVBE); ++ CHECK_CPU_FEATURE_USABLE (POPCNT); ++ CHECK_CPU_FEATURE_USABLE (AES); ++ CHECK_CPU_FEATURE_USABLE (XSAVE); ++ CHECK_CPU_FEATURE_USABLE (OSXSAVE); ++ CHECK_CPU_FEATURE_USABLE (AVX); ++ CHECK_CPU_FEATURE_USABLE (F16C); ++ CHECK_CPU_FEATURE_USABLE (RDRAND); ++ CHECK_CPU_FEATURE_USABLE (FPU); ++ CHECK_CPU_FEATURE_USABLE (TSC); ++ CHECK_CPU_FEATURE_USABLE (MSR); ++ CHECK_CPU_FEATURE_USABLE (CX8); ++ CHECK_CPU_FEATURE_USABLE (SEP); ++ CHECK_CPU_FEATURE_USABLE (CMOV); ++ CHECK_CPU_FEATURE_USABLE (CLFSH); ++ CHECK_CPU_FEATURE_USABLE (MMX); ++ CHECK_CPU_FEATURE_USABLE (FXSR); ++ CHECK_CPU_FEATURE_USABLE (SSE); ++ CHECK_CPU_FEATURE_USABLE (SSE2); ++ CHECK_CPU_FEATURE_USABLE (FSGSBASE); ++ CHECK_CPU_FEATURE_USABLE (BMI1); ++ CHECK_CPU_FEATURE_USABLE (HLE); ++ CHECK_CPU_FEATURE_USABLE (AVX2); ++ CHECK_CPU_FEATURE_USABLE (BMI2); ++ CHECK_CPU_FEATURE_USABLE (ERMS); ++ CHECK_CPU_FEATURE_USABLE (AVX512F); ++ CHECK_CPU_FEATURE_USABLE (AVX512DQ); ++ CHECK_CPU_FEATURE_USABLE (RDSEED); ++ CHECK_CPU_FEATURE_USABLE (ADX); ++ CHECK_CPU_FEATURE_USABLE (AVX512_IFMA); ++ CHECK_CPU_FEATURE_USABLE (CLFLUSHOPT); ++ CHECK_CPU_FEATURE_USABLE (CLWB); ++ CHECK_CPU_FEATURE_USABLE (AVX512PF); ++ CHECK_CPU_FEATURE_USABLE (AVX512ER); ++ CHECK_CPU_FEATURE_USABLE (AVX512CD); ++ CHECK_CPU_FEATURE_USABLE (SHA); ++ CHECK_CPU_FEATURE_USABLE (AVX512BW); ++ CHECK_CPU_FEATURE_USABLE (AVX512VL); ++ CHECK_CPU_FEATURE_USABLE (PREFETCHWT1); ++ CHECK_CPU_FEATURE_USABLE (AVX512_VBMI); ++ CHECK_CPU_FEATURE_USABLE (AVX512_VBMI2); ++ CHECK_CPU_FEATURE_USABLE (GFNI); ++ CHECK_CPU_FEATURE_USABLE (VAES); ++ CHECK_CPU_FEATURE_USABLE (VPCLMULQDQ); ++ CHECK_CPU_FEATURE_USABLE (AVX512_VNNI); ++ CHECK_CPU_FEATURE_USABLE (AVX512_BITALG); ++ CHECK_CPU_FEATURE_USABLE (AVX512_VPOPCNTDQ); ++ CHECK_CPU_FEATURE_USABLE (RDPID); ++ CHECK_CPU_FEATURE_USABLE (CLDEMOTE); ++ CHECK_CPU_FEATURE_USABLE (MOVDIRI); ++ CHECK_CPU_FEATURE_USABLE (MOVDIR64B); ++ CHECK_CPU_FEATURE_USABLE (AVX512_4VNNIW); ++ CHECK_CPU_FEATURE_USABLE (AVX512_4FMAPS); ++ CHECK_CPU_FEATURE_USABLE (FSRM); ++ CHECK_CPU_FEATURE_USABLE (LAHF64_SAHF64); ++ CHECK_CPU_FEATURE_USABLE (LZCNT); ++ CHECK_CPU_FEATURE_USABLE (SSE4A); ++ CHECK_CPU_FEATURE_USABLE (PREFETCHW); ++ CHECK_CPU_FEATURE_USABLE (XOP); ++ CHECK_CPU_FEATURE_USABLE (FMA4); ++ CHECK_CPU_FEATURE_USABLE (TBM); ++ CHECK_CPU_FEATURE_USABLE (SYSCALL_SYSRET); ++ CHECK_CPU_FEATURE_USABLE (RDTSCP); ++ CHECK_CPU_FEATURE_USABLE (XSAVEOPT); ++ CHECK_CPU_FEATURE_USABLE (XSAVEC); ++ CHECK_CPU_FEATURE_USABLE (XGETBV_ECX_1); ++ CHECK_CPU_FEATURE_USABLE (XSAVES); ++ CHECK_CPU_FEATURE_USABLE (INVARIANT_TSC); ++ CHECK_CPU_FEATURE_USABLE (WBNOINVD); ++ + return 0; + } + +-#define TEST_FUNCTION do_test () +-#include "../../test-skeleton.c" ++#include +diff --git a/sysdeps/x86_64/multiarch/sched_cpucount.c b/sysdeps/x86_64/multiarch/sched_cpucount.c +index d10d74ae21e05d47..7949119dcdb5a94b 100644 +--- a/sysdeps/x86_64/multiarch/sched_cpucount.c ++++ b/sysdeps/x86_64/multiarch/sched_cpucount.c +@@ -33,4 +33,4 @@ + #undef __sched_cpucount + + libc_ifunc (__sched_cpucount, +- HAS_CPU_FEATURE (POPCOUNT) ? popcount_cpucount : generic_cpucount); ++ HAS_CPU_FEATURE (POPCNT) ? popcount_cpucount : generic_cpucount); +diff --git a/sysdeps/x86_64/multiarch/test-multiarch.c b/sysdeps/x86_64/multiarch/test-multiarch.c +index aa872f27dbe7ea2f..417147c3d5f325a5 100644 +--- a/sysdeps/x86_64/multiarch/test-multiarch.c ++++ b/sysdeps/x86_64/multiarch/test-multiarch.c +@@ -85,8 +85,8 @@ do_test (int argc, char **argv) + , "HAS_CPU_FEATURE (SSE4_1)"); + fails += check_proc ("ssse3", HAS_CPU_FEATURE (SSSE3), + "HAS_CPU_FEATURE (SSSE3)"); +- fails += check_proc ("popcnt", HAS_CPU_FEATURE (POPCOUNT), +- "HAS_CPU_FEATURE (POPCOUNT)"); ++ fails += check_proc ("popcnt", HAS_CPU_FEATURE (POPCNT), ++ "HAS_CPU_FEATURE (POPCNT)"); + + printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails); + diff --git a/glibc-rh1817513-16.patch b/glibc-rh1817513-16.patch new file mode 100755 index 0000000..2698a30 --- /dev/null +++ b/glibc-rh1817513-16.patch @@ -0,0 +1,146 @@ +commit b2e93de0ffedcfe2cfba100d47a4d4f6f85cea0b +Author: DJ Delorie +Date: Tue Dec 4 00:03:12 2018 -0500 + + test-container: add "su" command to run test as root, add unshare hints + + * support/test-container.c (check_for_unshare_hints): New. + (main): Call it if unshare fails. Add support for "su" scriptlet + command. + +diff --git a/support/test-container.c b/support/test-container.c +index fe0ebbd07df83da7..1d1aebeaf3412573 100644 +--- a/support/test-container.c ++++ b/support/test-container.c +@@ -88,15 +88,22 @@ int verbose = 0; + * mytest.root/ is rsync'd into container + * mytest.root/preclean.req causes fresh rsync (with delete) before + test if present +- * mytest.root/mytset.script has a list of "commands" to run: ++ * mytest.root/mytest.script has a list of "commands" to run: + syntax: + # comment ++ su + mv FILE FILE + cp FILE FILE + rm FILE + FILE must start with $B/, $S/, $I/, $L/, or / + (expands to build dir, source dir, install dir, library dir + (in container), or container's root) ++ details: ++ - '#': A comment. ++ - 'su': Enables running test as root in the container. ++ - 'mv': A minimal move files command. ++ - 'cp': A minimal copy files command. ++ - 'rm': A minimal remove files command. + * mytest.root/postclean.req causes fresh rsync (with delete) after + test if present + +@@ -349,6 +356,7 @@ recursive_remove (char *path) + + switch (child) { + case -1: ++ perror("fork"); + FAIL_EXIT1 ("Unable to fork"); + case 0: + /* Child. */ +@@ -610,6 +618,47 @@ rsync (char *src, char *dest, int and_delete) + } + + ++ ++/* See if we can detect what the user needs to do to get unshare ++ support working for us. */ ++void ++check_for_unshare_hints (void) ++{ ++ FILE *f; ++ int i; ++ ++ /* Default Debian Linux disables user namespaces, but allows a way ++ to enable them. */ ++ f = fopen ("/proc/sys/kernel/unprivileged_userns_clone", "r"); ++ if (f != NULL) ++ { ++ i = 99; /* Sentinel. */ ++ fscanf (f, "%d", &i); ++ if (i == 0) ++ { ++ printf ("To enable test-container, please run this as root:\n"); ++ printf (" echo 1 > /proc/sys/kernel/unprivileged_userns_clone\n"); ++ } ++ fclose (f); ++ return; ++ } ++ ++ /* ALT Linux has an alternate way of doing the same. */ ++ f = fopen ("/proc/sys/kernel/userns_restrict", "r"); ++ if (f != NULL) ++ { ++ i = 99; /* Sentinel. */ ++ fscanf (f, "%d", &i); ++ if (i == 1) ++ { ++ printf ("To enable test-container, please run this as root:\n"); ++ printf (" echo 0 > /proc/sys/kernel/userns_restrict\n"); ++ } ++ fclose (f); ++ return; ++ } ++} ++ + int + main (int argc, char **argv) + { +@@ -628,6 +677,8 @@ main (int argc, char **argv) + + uid_t original_uid; + gid_t original_gid; ++ /* If set, the test runs as root instead of the user running the testsuite. */ ++ int be_su = 0; + int UMAP; + int GMAP; + /* Used for "%lld %lld 1" so need not be large. */ +@@ -857,6 +908,10 @@ main (int argc, char **argv) + { + maybe_xunlink (the_words[1]); + } ++ else if (nt == 1 && strcmp (the_words[0], "su") == 0) ++ { ++ be_su = 1; ++ } + else if (nt > 0 && the_words[0][0] != '#') + { + printf ("\033[31minvalid [%s]\033[0m\n", the_words[0]); +@@ -910,7 +965,12 @@ main (int argc, char **argv) + /* Older kernels may not support all the options, or security + policy may block this call. */ + if (errno == EINVAL || errno == EPERM) +- FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (errno)); ++ { ++ int saved_errno = errno; ++ if (errno == EPERM) ++ check_for_unshare_hints (); ++ FAIL_UNSUPPORTED ("unable to unshare user/fs: %s", strerror (saved_errno)); ++ } + else + FAIL_EXIT1 ("unable to unshare user/fs: %s", strerror (errno)); + } +@@ -981,7 +1041,7 @@ main (int argc, char **argv) + FAIL_EXIT1 ("can't write to /proc/self/uid_map\n"); + + sprintf (tmp, "%lld %lld 1\n", +- (long long) original_uid, (long long) original_uid); ++ (long long) (be_su ? 0 : original_uid), (long long) original_uid); + write (UMAP, tmp, strlen (tmp)); + xclose (UMAP); + +@@ -1002,7 +1062,7 @@ main (int argc, char **argv) + FAIL_EXIT1 ("can't write to /proc/self/gid_map\n"); + + sprintf (tmp, "%lld %lld 1\n", +- (long long) original_gid, (long long) original_gid); ++ (long long) (be_su ? 0 : original_gid), (long long) original_gid); + write (GMAP, tmp, strlen (tmp)); + xclose (GMAP); + diff --git a/glibc-rh1817513-17.patch b/glibc-rh1817513-17.patch new file mode 100755 index 0000000..faeb2bd --- /dev/null +++ b/glibc-rh1817513-17.patch @@ -0,0 +1,1559 @@ +commit 1a153e47fcc9401d8ea424ad86569a57ed0f8c52 +Author: Leonardo Sandoval +Date: Mon Oct 8 08:59:50 2018 -0500 + + x86-64: Optimize strcat/strncat, strcpy/strncpy and stpcpy/stpncpy with AVX2 + + Optimize x86-64 strcat/strncat, strcpy/strncpy and stpcpy/stpncpy with AVX2. + It uses vector comparison as much as possible. In general, the larger the + source string, the greater performance gain observed, reaching speedups of + 1.6x compared to SSE2 unaligned routines. Select AVX2 strcat/strncat, + strcpy/strncpy and stpcpy/stpncpy on AVX2 machines where vzeroupper is + preferred and AVX unaligned load is fast. + + * sysdeps/x86_64/multiarch/Makefile (sysdep_routines): Add + strcat-avx2, strncat-avx2, strcpy-avx2, strncpy-avx2, + stpcpy-avx2 and stpncpy-avx2. + * sysdeps/x86_64/multiarch/ifunc-impl-list.c: + (__libc_ifunc_impl_list): Add tests for __strcat_avx2, + __strncat_avx2, __strcpy_avx2, __strncpy_avx2, __stpcpy_avx2 + and __stpncpy_avx2. + * sysdeps/x86_64/multiarch/{ifunc-unaligned-ssse3.h => + ifunc-strcpy.h}: rename header for a more generic name. + * sysdeps/x86_64/multiarch/ifunc-strcpy.h: + (IFUNC_SELECTOR): Return OPTIMIZE (avx2) on AVX 2 machines if + AVX unaligned load is fast and vzeroupper is preferred. + * sysdeps/x86_64/multiarch/stpcpy-avx2.S: New file + * sysdeps/x86_64/multiarch/stpncpy-avx2.S: Likewise + * sysdeps/x86_64/multiarch/strcat-avx2.S: Likewise + * sysdeps/x86_64/multiarch/strcpy-avx2.S: Likewise + * sysdeps/x86_64/multiarch/strncat-avx2.S: Likewise + * sysdeps/x86_64/multiarch/strncpy-avx2.S: Likewise + +diff --git a/sysdeps/x86_64/multiarch/Makefile b/sysdeps/x86_64/multiarch/Makefile +index bb5e97073520ee51..395e432c092ca17c 100644 +--- a/sysdeps/x86_64/multiarch/Makefile ++++ b/sysdeps/x86_64/multiarch/Makefile +@@ -24,11 +24,14 @@ sysdep_routines += strncat-c stpncpy-c strncpy-c \ + strchr-sse2 strchrnul-sse2 strchr-avx2 strchrnul-avx2 \ + strrchr-sse2 strrchr-avx2 \ + strlen-sse2 strnlen-sse2 strlen-avx2 strnlen-avx2 \ ++ strcat-avx2 strncat-avx2 \ + strcat-ssse3 strncat-ssse3\ ++ strcpy-avx2 strncpy-avx2 \ + strcpy-sse2 stpcpy-sse2 \ + strcpy-ssse3 strncpy-ssse3 stpcpy-ssse3 stpncpy-ssse3 \ + strcpy-sse2-unaligned strncpy-sse2-unaligned \ + stpcpy-sse2-unaligned stpncpy-sse2-unaligned \ ++ stpcpy-avx2 stpncpy-avx2 \ + strcat-sse2 \ + strcat-sse2-unaligned strncat-sse2-unaligned \ + strchr-sse2-no-bsf memcmp-ssse3 strstr-sse2-unaligned \ +diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +index 9aaaef7251b8edfe..8b55bb6954000cc2 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +@@ -199,6 +199,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_IMPL (i, name, stpncpy, + IFUNC_IMPL_ADD (array, i, stpncpy, HAS_CPU_FEATURE (SSSE3), + __stpncpy_ssse3) ++ IFUNC_IMPL_ADD (array, i, stpncpy, HAS_ARCH_FEATURE (AVX2_Usable), ++ __stpncpy_avx2) + IFUNC_IMPL_ADD (array, i, stpncpy, 1, + __stpncpy_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, stpncpy, 1, __stpncpy_sse2)) +@@ -207,6 +209,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_IMPL (i, name, stpcpy, + IFUNC_IMPL_ADD (array, i, stpcpy, HAS_CPU_FEATURE (SSSE3), + __stpcpy_ssse3) ++ IFUNC_IMPL_ADD (array, i, stpcpy, HAS_ARCH_FEATURE (AVX2_Usable), ++ __stpcpy_avx2) + IFUNC_IMPL_ADD (array, i, stpcpy, 1, __stpcpy_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, stpcpy, 1, __stpcpy_sse2)) + +@@ -239,6 +243,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/x86_64/multiarch/strcat.c. */ + IFUNC_IMPL (i, name, strcat, ++ IFUNC_IMPL_ADD (array, i, strcat, HAS_ARCH_FEATURE (AVX2_Usable), ++ __strcat_avx2) + IFUNC_IMPL_ADD (array, i, strcat, HAS_CPU_FEATURE (SSSE3), + __strcat_ssse3) + IFUNC_IMPL_ADD (array, i, strcat, 1, __strcat_sse2_unaligned) +@@ -280,6 +286,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/x86_64/multiarch/strcpy.c. */ + IFUNC_IMPL (i, name, strcpy, ++ IFUNC_IMPL_ADD (array, i, strcpy, HAS_ARCH_FEATURE (AVX2_Usable), ++ __strcpy_avx2) + IFUNC_IMPL_ADD (array, i, strcpy, HAS_CPU_FEATURE (SSSE3), + __strcpy_ssse3) + IFUNC_IMPL_ADD (array, i, strcpy, 1, __strcpy_sse2_unaligned) +@@ -321,6 +329,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/x86_64/multiarch/strncat.c. */ + IFUNC_IMPL (i, name, strncat, ++ IFUNC_IMPL_ADD (array, i, strncat, HAS_ARCH_FEATURE (AVX2_Usable), ++ __strncat_avx2) + IFUNC_IMPL_ADD (array, i, strncat, HAS_CPU_FEATURE (SSSE3), + __strncat_ssse3) + IFUNC_IMPL_ADD (array, i, strncat, 1, +@@ -329,6 +339,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/x86_64/multiarch/strncpy.c. */ + IFUNC_IMPL (i, name, strncpy, ++ IFUNC_IMPL_ADD (array, i, strncpy, HAS_ARCH_FEATURE (AVX2_Usable), ++ __strncpy_avx2) + IFUNC_IMPL_ADD (array, i, strncpy, HAS_CPU_FEATURE (SSSE3), + __strncpy_ssse3) + IFUNC_IMPL_ADD (array, i, strncpy, 1, +diff --git a/sysdeps/x86_64/multiarch/ifunc-unaligned-ssse3.h b/sysdeps/x86_64/multiarch/ifunc-strcpy.h +similarity index 83% +rename from sysdeps/x86_64/multiarch/ifunc-unaligned-ssse3.h +rename to sysdeps/x86_64/multiarch/ifunc-strcpy.h +index 81805f9832345923..4f2286fefccda069 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-unaligned-ssse3.h ++++ b/sysdeps/x86_64/multiarch/ifunc-strcpy.h +@@ -24,12 +24,18 @@ extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2) attribute_hidden; + extern __typeof (REDIRECT_NAME) OPTIMIZE (sse2_unaligned) + attribute_hidden; + extern __typeof (REDIRECT_NAME) OPTIMIZE (ssse3) attribute_hidden; ++extern __typeof (REDIRECT_NAME) OPTIMIZE (avx2) attribute_hidden; + + static inline void * + IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + ++ if (!CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_VZEROUPPER) ++ && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable) ++ && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) ++ return OPTIMIZE (avx2); ++ + if (CPU_FEATURES_ARCH_P (cpu_features, Fast_Unaligned_Load)) + return OPTIMIZE (sse2_unaligned); + +diff --git a/sysdeps/x86_64/multiarch/stpcpy-avx2.S b/sysdeps/x86_64/multiarch/stpcpy-avx2.S +new file mode 100644 +index 0000000000000000..f0bd3029fe3047ed +--- /dev/null ++++ b/sysdeps/x86_64/multiarch/stpcpy-avx2.S +@@ -0,0 +1,3 @@ ++#define USE_AS_STPCPY ++#define STRCPY __stpcpy_avx2 ++#include "strcpy-avx2.S" +diff --git a/sysdeps/x86_64/multiarch/stpcpy.c b/sysdeps/x86_64/multiarch/stpcpy.c +index 1e340fca991a021c..8ffd13b48c83ca8e 100644 +--- a/sysdeps/x86_64/multiarch/stpcpy.c ++++ b/sysdeps/x86_64/multiarch/stpcpy.c +@@ -28,7 +28,7 @@ + # undef __stpcpy + + # define SYMBOL_NAME stpcpy +-# include "ifunc-unaligned-ssse3.h" ++# include "ifunc-strcpy.h" + + libc_ifunc_redirected (__redirect_stpcpy, __stpcpy, IFUNC_SELECTOR ()); + +diff --git a/sysdeps/x86_64/multiarch/stpncpy-avx2.S b/sysdeps/x86_64/multiarch/stpncpy-avx2.S +new file mode 100644 +index 0000000000000000..032b0407d08c6a9d +--- /dev/null ++++ b/sysdeps/x86_64/multiarch/stpncpy-avx2.S +@@ -0,0 +1,4 @@ ++#define USE_AS_STPCPY ++#define USE_AS_STRNCPY ++#define STRCPY __stpncpy_avx2 ++#include "strcpy-avx2.S" +diff --git a/sysdeps/x86_64/multiarch/stpncpy.c b/sysdeps/x86_64/multiarch/stpncpy.c +index 28842ece2b0998e3..f3e203f78cca2e61 100644 +--- a/sysdeps/x86_64/multiarch/stpncpy.c ++++ b/sysdeps/x86_64/multiarch/stpncpy.c +@@ -26,7 +26,7 @@ + # undef __stpncpy + + # define SYMBOL_NAME stpncpy +-# include "ifunc-unaligned-ssse3.h" ++# include "ifunc-strcpy.h" + + libc_ifunc_redirected (__redirect_stpncpy, __stpncpy, IFUNC_SELECTOR ()); + +diff --git a/sysdeps/x86_64/multiarch/strcat-avx2.S b/sysdeps/x86_64/multiarch/strcat-avx2.S +new file mode 100644 +index 0000000000000000..b062356427677ca6 +--- /dev/null ++++ b/sysdeps/x86_64/multiarch/strcat-avx2.S +@@ -0,0 +1,275 @@ ++/* strcat with AVX2 ++ Copyright (C) 2011-2018 Free Software Foundation, Inc. ++ Contributed by Intel Corporation. ++ 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 ++ . */ ++ ++#if IS_IN (libc) ++ ++# include ++ ++# ifndef STRCAT ++# define STRCAT __strcat_avx2 ++# endif ++ ++# define USE_AS_STRCAT ++ ++/* Number of bytes in a vector register */ ++# define VEC_SIZE 32 ++ ++ .section .text.avx,"ax",@progbits ++ENTRY (STRCAT) ++ mov %rdi, %r9 ++# ifdef USE_AS_STRNCAT ++ mov %rdx, %r8 ++# endif ++ ++ xor %eax, %eax ++ mov %edi, %ecx ++ and $((VEC_SIZE * 4) - 1), %ecx ++ vpxor %xmm6, %xmm6, %xmm6 ++ cmp $(VEC_SIZE * 3), %ecx ++ ja L(fourth_vector_boundary) ++ vpcmpeqb (%rdi), %ymm6, %ymm0 ++ vpmovmskb %ymm0, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_first_vector) ++ mov %rdi, %rax ++ and $-VEC_SIZE, %rax ++ jmp L(align_vec_size_start) ++L(fourth_vector_boundary): ++ mov %rdi, %rax ++ and $-VEC_SIZE, %rax ++ vpcmpeqb (%rax), %ymm6, %ymm0 ++ mov $-1, %r10d ++ sub %rax, %rcx ++ shl %cl, %r10d ++ vpmovmskb %ymm0, %edx ++ and %r10d, %edx ++ jnz L(exit) ++ ++L(align_vec_size_start): ++ vpcmpeqb VEC_SIZE(%rax), %ymm6, %ymm0 ++ vpmovmskb %ymm0, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_second_vector) ++ ++ vpcmpeqb (VEC_SIZE * 2)(%rax), %ymm6, %ymm1 ++ vpmovmskb %ymm1, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_third_vector) ++ ++ vpcmpeqb (VEC_SIZE * 3)(%rax), %ymm6, %ymm2 ++ vpmovmskb %ymm2, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_fourth_vector) ++ ++ vpcmpeqb (VEC_SIZE * 4)(%rax), %ymm6, %ymm3 ++ vpmovmskb %ymm3, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_fifth_vector) ++ ++ vpcmpeqb (VEC_SIZE * 5)(%rax), %ymm6, %ymm0 ++ add $(VEC_SIZE * 4), %rax ++ vpmovmskb %ymm0, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_second_vector) ++ ++ vpcmpeqb (VEC_SIZE * 2)(%rax), %ymm6, %ymm1 ++ vpmovmskb %ymm1, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_third_vector) ++ ++ vpcmpeqb (VEC_SIZE * 3)(%rax), %ymm6, %ymm2 ++ vpmovmskb %ymm2, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_fourth_vector) ++ ++ vpcmpeqb (VEC_SIZE * 4)(%rax), %ymm6, %ymm3 ++ vpmovmskb %ymm3, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_fifth_vector) ++ ++ vpcmpeqb (VEC_SIZE * 5)(%rax), %ymm6, %ymm0 ++ add $(VEC_SIZE * 4), %rax ++ vpmovmskb %ymm0, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_second_vector) ++ ++ vpcmpeqb (VEC_SIZE * 2)(%rax), %ymm6, %ymm1 ++ vpmovmskb %ymm1, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_third_vector) ++ ++ vpcmpeqb (VEC_SIZE * 3)(%rax), %ymm6, %ymm2 ++ vpmovmskb %ymm2, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_fourth_vector) ++ ++ vpcmpeqb (VEC_SIZE * 4)(%rax), %ymm6, %ymm3 ++ vpmovmskb %ymm3, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_fifth_vector) ++ ++ vpcmpeqb (VEC_SIZE * 5)(%rax), %ymm6, %ymm0 ++ add $(VEC_SIZE * 4), %rax ++ vpmovmskb %ymm0, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_second_vector) ++ ++ vpcmpeqb (VEC_SIZE * 2)(%rax), %ymm6, %ymm1 ++ vpmovmskb %ymm1, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_third_vector) ++ ++ vpcmpeqb (VEC_SIZE * 3)(%rax), %ymm6, %ymm2 ++ vpmovmskb %ymm2, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_fourth_vector) ++ ++ vpcmpeqb (VEC_SIZE * 4)(%rax), %ymm6, %ymm3 ++ vpmovmskb %ymm3, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_fifth_vector) ++ ++ test $((VEC_SIZE * 4) - 1), %rax ++ jz L(align_four_vec_loop) ++ ++ vpcmpeqb (VEC_SIZE * 5)(%rax), %ymm6, %ymm0 ++ add $(VEC_SIZE * 5), %rax ++ vpmovmskb %ymm0, %edx ++ test %edx, %edx ++ jnz L(exit) ++ ++ test $((VEC_SIZE * 4) - 1), %rax ++ jz L(align_four_vec_loop) ++ ++ vpcmpeqb VEC_SIZE(%rax), %ymm6, %ymm1 ++ add $VEC_SIZE, %rax ++ vpmovmskb %ymm1, %edx ++ test %edx, %edx ++ jnz L(exit) ++ ++ test $((VEC_SIZE * 4) - 1), %rax ++ jz L(align_four_vec_loop) ++ ++ vpcmpeqb VEC_SIZE(%rax), %ymm6, %ymm2 ++ add $VEC_SIZE, %rax ++ vpmovmskb %ymm2, %edx ++ test %edx, %edx ++ jnz L(exit) ++ ++ test $((VEC_SIZE * 4) - 1), %rax ++ jz L(align_four_vec_loop) ++ ++ vpcmpeqb VEC_SIZE(%rax), %ymm6, %ymm3 ++ add $VEC_SIZE, %rax ++ vpmovmskb %ymm3, %edx ++ test %edx, %edx ++ jnz L(exit) ++ ++ add $VEC_SIZE, %rax ++ ++ .p2align 4 ++L(align_four_vec_loop): ++ vmovaps (%rax), %ymm4 ++ vpminub VEC_SIZE(%rax), %ymm4, %ymm4 ++ vmovaps (VEC_SIZE * 2)(%rax), %ymm5 ++ vpminub (VEC_SIZE * 3)(%rax), %ymm5, %ymm5 ++ add $(VEC_SIZE * 4), %rax ++ vpminub %ymm4, %ymm5, %ymm5 ++ vpcmpeqb %ymm5, %ymm6, %ymm5 ++ vpmovmskb %ymm5, %edx ++ test %edx, %edx ++ jz L(align_four_vec_loop) ++ ++ vpcmpeqb -(VEC_SIZE * 4)(%rax), %ymm6, %ymm0 ++ sub $(VEC_SIZE * 5), %rax ++ vpmovmskb %ymm0, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_second_vector) ++ ++ vpcmpeqb (VEC_SIZE * 2)(%rax), %ymm6, %ymm1 ++ vpmovmskb %ymm1, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_third_vector) ++ ++ vpcmpeqb (VEC_SIZE * 3)(%rax), %ymm6, %ymm2 ++ vpmovmskb %ymm2, %edx ++ test %edx, %edx ++ jnz L(exit_null_on_fourth_vector) ++ ++ vpcmpeqb (VEC_SIZE * 4)(%rax), %ymm6, %ymm3 ++ vpmovmskb %ymm3, %edx ++ sub %rdi, %rax ++ bsf %rdx, %rdx ++ add %rdx, %rax ++ add $(VEC_SIZE * 4), %rax ++ jmp L(StartStrcpyPart) ++ ++ .p2align 4 ++L(exit): ++ sub %rdi, %rax ++L(exit_null_on_first_vector): ++ bsf %rdx, %rdx ++ add %rdx, %rax ++ jmp L(StartStrcpyPart) ++ ++ .p2align 4 ++L(exit_null_on_second_vector): ++ sub %rdi, %rax ++ bsf %rdx, %rdx ++ add %rdx, %rax ++ add $VEC_SIZE, %rax ++ jmp L(StartStrcpyPart) ++ ++ .p2align 4 ++L(exit_null_on_third_vector): ++ sub %rdi, %rax ++ bsf %rdx, %rdx ++ add %rdx, %rax ++ add $(VEC_SIZE * 2), %rax ++ jmp L(StartStrcpyPart) ++ ++ .p2align 4 ++L(exit_null_on_fourth_vector): ++ sub %rdi, %rax ++ bsf %rdx, %rdx ++ add %rdx, %rax ++ add $(VEC_SIZE * 3), %rax ++ jmp L(StartStrcpyPart) ++ ++ .p2align 4 ++L(exit_null_on_fifth_vector): ++ sub %rdi, %rax ++ bsf %rdx, %rdx ++ add %rdx, %rax ++ add $(VEC_SIZE * 4), %rax ++ ++ .p2align 4 ++L(StartStrcpyPart): ++ lea (%r9, %rax), %rdi ++ mov %rsi, %rcx ++ mov %r9, %rax /* save result */ ++ ++# ifdef USE_AS_STRNCAT ++ test %r8, %r8 ++ jz L(ExitZero) ++# define USE_AS_STRNCPY ++# endif ++ ++# include "strcpy-avx2.S" ++#endif +diff --git a/sysdeps/x86_64/multiarch/strcat.c b/sysdeps/x86_64/multiarch/strcat.c +index 1f7f6263f35ba402..694b9b2405827bd4 100644 +--- a/sysdeps/x86_64/multiarch/strcat.c ++++ b/sysdeps/x86_64/multiarch/strcat.c +@@ -24,7 +24,7 @@ + # undef strcat + + # define SYMBOL_NAME strcat +-# include "ifunc-unaligned-ssse3.h" ++# include "ifunc-strcpy.h" + + libc_ifunc_redirected (__redirect_strcat, strcat, IFUNC_SELECTOR ()); + +diff --git a/sysdeps/x86_64/multiarch/strcpy-avx2.S b/sysdeps/x86_64/multiarch/strcpy-avx2.S +new file mode 100644 +index 0000000000000000..81677f9060773a49 +--- /dev/null ++++ b/sysdeps/x86_64/multiarch/strcpy-avx2.S +@@ -0,0 +1,1022 @@ ++/* strcpy with AVX2 ++ Copyright (C) 2011-2018 Free Software Foundation, Inc. ++ Contributed by Intel Corporation. ++ 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 ++ . */ ++ ++#if IS_IN (libc) ++ ++# ifndef USE_AS_STRCAT ++# include ++ ++# ifndef STRCPY ++# define STRCPY __strcpy_avx2 ++# endif ++ ++# endif ++ ++/* Number of bytes in a vector register */ ++# ifndef VEC_SIZE ++# define VEC_SIZE 32 ++# endif ++ ++# ifndef VZEROUPPER ++# define VZEROUPPER vzeroupper ++# endif ++ ++/* zero register */ ++#define xmmZ xmm0 ++#define ymmZ ymm0 ++ ++/* mask register */ ++#define ymmM ymm1 ++ ++# ifndef USE_AS_STRCAT ++ ++ .section .text.avx,"ax",@progbits ++ENTRY (STRCPY) ++# ifdef USE_AS_STRNCPY ++ mov %rdx, %r8 ++ test %r8, %r8 ++ jz L(ExitZero) ++# endif ++ mov %rsi, %rcx ++# ifndef USE_AS_STPCPY ++ mov %rdi, %rax /* save result */ ++# endif ++ ++# endif ++ ++ vpxor %xmmZ, %xmmZ, %xmmZ ++ ++ and $((VEC_SIZE * 4) - 1), %ecx ++ cmp $(VEC_SIZE * 2), %ecx ++ jbe L(SourceStringAlignmentLessTwoVecSize) ++ ++ and $-VEC_SIZE, %rsi ++ and $(VEC_SIZE - 1), %ecx ++ ++ vpcmpeqb (%rsi), %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ shr %cl, %rdx ++ ++# ifdef USE_AS_STRNCPY ++# if defined USE_AS_STPCPY || defined USE_AS_STRCAT ++ mov $VEC_SIZE, %r10 ++ sub %rcx, %r10 ++ cmp %r10, %r8 ++# else ++ mov $(VEC_SIZE + 1), %r10 ++ sub %rcx, %r10 ++ cmp %r10, %r8 ++# endif ++ jbe L(CopyVecSizeTailCase2OrCase3) ++# endif ++ test %edx, %edx ++ jnz L(CopyVecSizeTail) ++ ++ vpcmpeqb VEC_SIZE(%rsi), %ymmZ, %ymm2 ++ vpmovmskb %ymm2, %edx ++ ++# ifdef USE_AS_STRNCPY ++ add $VEC_SIZE, %r10 ++ cmp %r10, %r8 ++ jbe L(CopyTwoVecSizeCase2OrCase3) ++# endif ++ test %edx, %edx ++ jnz L(CopyTwoVecSize) ++ ++ vmovdqu (%rsi, %rcx), %ymm2 /* copy VEC_SIZE bytes */ ++ vmovdqu %ymm2, (%rdi) ++ ++/* If source address alignment != destination address alignment */ ++ .p2align 4 ++L(UnalignVecSizeBoth): ++ sub %rcx, %rdi ++# ifdef USE_AS_STRNCPY ++ add %rcx, %r8 ++ sbb %rcx, %rcx ++ or %rcx, %r8 ++# endif ++ mov $VEC_SIZE, %rcx ++ vmovdqa (%rsi, %rcx), %ymm2 ++ vmovdqu %ymm2, (%rdi, %rcx) ++ vmovdqa VEC_SIZE(%rsi, %rcx), %ymm2 ++ vpcmpeqb %ymm2, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ add $VEC_SIZE, %rcx ++# ifdef USE_AS_STRNCPY ++ sub $(VEC_SIZE * 3), %r8 ++ jbe L(CopyVecSizeCase2OrCase3) ++# endif ++ test %edx, %edx ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ jnz L(CopyVecSizeUnalignedVec2) ++# else ++ jnz L(CopyVecSize) ++# endif ++ ++ vmovdqu %ymm2, (%rdi, %rcx) ++ vmovdqa VEC_SIZE(%rsi, %rcx), %ymm3 ++ vpcmpeqb %ymm3, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ add $VEC_SIZE, %rcx ++# ifdef USE_AS_STRNCPY ++ sub $VEC_SIZE, %r8 ++ jbe L(CopyVecSizeCase2OrCase3) ++# endif ++ test %edx, %edx ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ jnz L(CopyVecSizeUnalignedVec3) ++# else ++ jnz L(CopyVecSize) ++# endif ++ ++ vmovdqu %ymm3, (%rdi, %rcx) ++ vmovdqa VEC_SIZE(%rsi, %rcx), %ymm4 ++ vpcmpeqb %ymm4, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ add $VEC_SIZE, %rcx ++# ifdef USE_AS_STRNCPY ++ sub $VEC_SIZE, %r8 ++ jbe L(CopyVecSizeCase2OrCase3) ++# endif ++ test %edx, %edx ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ jnz L(CopyVecSizeUnalignedVec4) ++# else ++ jnz L(CopyVecSize) ++# endif ++ ++ vmovdqu %ymm4, (%rdi, %rcx) ++ vmovdqa VEC_SIZE(%rsi, %rcx), %ymm2 ++ vpcmpeqb %ymm2, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ add $VEC_SIZE, %rcx ++# ifdef USE_AS_STRNCPY ++ sub $VEC_SIZE, %r8 ++ jbe L(CopyVecSizeCase2OrCase3) ++# endif ++ test %edx, %edx ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ jnz L(CopyVecSizeUnalignedVec2) ++# else ++ jnz L(CopyVecSize) ++# endif ++ ++ vmovdqu %ymm2, (%rdi, %rcx) ++ vmovdqa VEC_SIZE(%rsi, %rcx), %ymm2 ++ vpcmpeqb %ymm2, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ add $VEC_SIZE, %rcx ++# ifdef USE_AS_STRNCPY ++ sub $VEC_SIZE, %r8 ++ jbe L(CopyVecSizeCase2OrCase3) ++# endif ++ test %edx, %edx ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ jnz L(CopyVecSizeUnalignedVec2) ++# else ++ jnz L(CopyVecSize) ++# endif ++ ++ vmovdqa VEC_SIZE(%rsi, %rcx), %ymm3 ++ vmovdqu %ymm2, (%rdi, %rcx) ++ vpcmpeqb %ymm3, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ add $VEC_SIZE, %rcx ++# ifdef USE_AS_STRNCPY ++ sub $VEC_SIZE, %r8 ++ jbe L(CopyVecSizeCase2OrCase3) ++# endif ++ test %edx, %edx ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ jnz L(CopyVecSizeUnalignedVec3) ++# else ++ jnz L(CopyVecSize) ++# endif ++ ++ vmovdqu %ymm3, (%rdi, %rcx) ++ mov %rsi, %rdx ++ lea VEC_SIZE(%rsi, %rcx), %rsi ++ and $-(VEC_SIZE * 4), %rsi ++ sub %rsi, %rdx ++ sub %rdx, %rdi ++# ifdef USE_AS_STRNCPY ++ lea (VEC_SIZE * 8)(%r8, %rdx), %r8 ++# endif ++L(UnalignedFourVecSizeLoop): ++ vmovdqa (%rsi), %ymm4 ++ vmovdqa VEC_SIZE(%rsi), %ymm5 ++ vmovdqa (VEC_SIZE * 2)(%rsi), %ymm6 ++ vmovdqa (VEC_SIZE * 3)(%rsi), %ymm7 ++ vpminub %ymm5, %ymm4, %ymm2 ++ vpminub %ymm7, %ymm6, %ymm3 ++ vpminub %ymm2, %ymm3, %ymm3 ++ vpcmpeqb %ymmM, %ymm3, %ymm3 ++ vpmovmskb %ymm3, %edx ++# ifdef USE_AS_STRNCPY ++ sub $(VEC_SIZE * 4), %r8 ++ jbe L(UnalignedLeaveCase2OrCase3) ++# endif ++ test %edx, %edx ++ jnz L(UnalignedFourVecSizeLeave) ++ ++L(UnalignedFourVecSizeLoop_start): ++ add $(VEC_SIZE * 4), %rdi ++ add $(VEC_SIZE * 4), %rsi ++ vmovdqu %ymm4, -(VEC_SIZE * 4)(%rdi) ++ vmovdqa (%rsi), %ymm4 ++ vmovdqu %ymm5, -(VEC_SIZE * 3)(%rdi) ++ vmovdqa VEC_SIZE(%rsi), %ymm5 ++ vpminub %ymm5, %ymm4, %ymm2 ++ vmovdqu %ymm6, -(VEC_SIZE * 2)(%rdi) ++ vmovdqa (VEC_SIZE * 2)(%rsi), %ymm6 ++ vmovdqu %ymm7, -VEC_SIZE(%rdi) ++ vmovdqa (VEC_SIZE * 3)(%rsi), %ymm7 ++ vpminub %ymm7, %ymm6, %ymm3 ++ vpminub %ymm2, %ymm3, %ymm3 ++ vpcmpeqb %ymmM, %ymm3, %ymm3 ++ vpmovmskb %ymm3, %edx ++# ifdef USE_AS_STRNCPY ++ sub $(VEC_SIZE * 4), %r8 ++ jbe L(UnalignedLeaveCase2OrCase3) ++# endif ++ test %edx, %edx ++ jz L(UnalignedFourVecSizeLoop_start) ++ ++L(UnalignedFourVecSizeLeave): ++ vpcmpeqb %ymm4, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ test %edx, %edx ++ jnz L(CopyVecSizeUnaligned_0) ++ ++ vpcmpeqb %ymm5, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %ecx ++ test %ecx, %ecx ++ jnz L(CopyVecSizeUnaligned_16) ++ ++ vpcmpeqb %ymm6, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ test %edx, %edx ++ jnz L(CopyVecSizeUnaligned_32) ++ ++ vpcmpeqb %ymm7, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %ecx ++ bsf %ecx, %edx ++ vmovdqu %ymm4, (%rdi) ++ vmovdqu %ymm5, VEC_SIZE(%rdi) ++ vmovdqu %ymm6, (VEC_SIZE * 2)(%rdi) ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++# ifdef USE_AS_STPCPY ++ lea (VEC_SIZE * 3)(%rdi, %rdx), %rax ++# endif ++ vmovdqu %ymm7, (VEC_SIZE * 3)(%rdi) ++ add $(VEC_SIZE - 1), %r8 ++ sub %rdx, %r8 ++ lea ((VEC_SIZE * 3) + 1)(%rdi, %rdx), %rdi ++ jmp L(StrncpyFillTailWithZero) ++# else ++ add $(VEC_SIZE * 3), %rsi ++ add $(VEC_SIZE * 3), %rdi ++ jmp L(CopyVecSizeExit) ++# endif ++ ++/* If source address alignment == destination address alignment */ ++ ++L(SourceStringAlignmentLessTwoVecSize): ++ vmovdqu (%rsi), %ymm3 ++ vmovdqu VEC_SIZE(%rsi), %ymm2 ++ vpcmpeqb %ymm3, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ ++# ifdef USE_AS_STRNCPY ++# if defined USE_AS_STPCPY || defined USE_AS_STRCAT ++ cmp $VEC_SIZE, %r8 ++# else ++ cmp $(VEC_SIZE + 1), %r8 ++# endif ++ jbe L(CopyVecSizeTail1Case2OrCase3) ++# endif ++ test %edx, %edx ++ jnz L(CopyVecSizeTail1) ++ ++ vmovdqu %ymm3, (%rdi) ++ vpcmpeqb %ymm2, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ ++# ifdef USE_AS_STRNCPY ++# if defined USE_AS_STPCPY || defined USE_AS_STRCAT ++ cmp $(VEC_SIZE * 2), %r8 ++# else ++ cmp $((VEC_SIZE * 2) + 1), %r8 ++# endif ++ jbe L(CopyTwoVecSize1Case2OrCase3) ++# endif ++ test %edx, %edx ++ jnz L(CopyTwoVecSize1) ++ ++ and $-VEC_SIZE, %rsi ++ and $(VEC_SIZE - 1), %ecx ++ jmp L(UnalignVecSizeBoth) ++ ++/*------End of main part with loops---------------------*/ ++ ++/* Case1 */ ++ ++# if (!defined USE_AS_STRNCPY) || (defined USE_AS_STRCAT) ++ .p2align 4 ++L(CopyVecSize): ++ add %rcx, %rdi ++# endif ++L(CopyVecSizeTail): ++ add %rcx, %rsi ++L(CopyVecSizeTail1): ++ bsf %edx, %edx ++L(CopyVecSizeExit): ++ cmp $32, %edx ++ jae L(Exit32_63) ++ cmp $16, %edx ++ jae L(Exit16_31) ++ cmp $8, %edx ++ jae L(Exit8_15) ++ cmp $4, %edx ++ jae L(Exit4_7) ++ cmp $3, %edx ++ je L(Exit3) ++ cmp $1, %edx ++ ja L(Exit2) ++ je L(Exit1) ++ movb $0, (%rdi) ++# ifdef USE_AS_STPCPY ++ lea (%rdi), %rax ++# endif ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ sub $1, %r8 ++ lea 1(%rdi), %rdi ++ jnz L(StrncpyFillTailWithZero) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(CopyTwoVecSize1): ++ add $VEC_SIZE, %rsi ++ add $VEC_SIZE, %rdi ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ sub $VEC_SIZE, %r8 ++# endif ++ jmp L(CopyVecSizeTail1) ++ ++ .p2align 4 ++L(CopyTwoVecSize): ++ bsf %edx, %edx ++ add %rcx, %rsi ++ add $VEC_SIZE, %edx ++ sub %ecx, %edx ++ jmp L(CopyVecSizeExit) ++ ++ .p2align 4 ++L(CopyVecSizeUnaligned_0): ++ bsf %edx, %edx ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++# ifdef USE_AS_STPCPY ++ lea (%rdi, %rdx), %rax ++# endif ++ vmovdqu %ymm4, (%rdi) ++ add $((VEC_SIZE * 4) - 1), %r8 ++ sub %rdx, %r8 ++ lea 1(%rdi, %rdx), %rdi ++ jmp L(StrncpyFillTailWithZero) ++# else ++ jmp L(CopyVecSizeExit) ++# endif ++ ++ .p2align 4 ++L(CopyVecSizeUnaligned_16): ++ bsf %ecx, %edx ++ vmovdqu %ymm4, (%rdi) ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++# ifdef USE_AS_STPCPY ++ lea VEC_SIZE(%rdi, %rdx), %rax ++# endif ++ vmovdqu %ymm5, VEC_SIZE(%rdi) ++ add $((VEC_SIZE * 3) - 1), %r8 ++ sub %rdx, %r8 ++ lea (VEC_SIZE + 1)(%rdi, %rdx), %rdi ++ jmp L(StrncpyFillTailWithZero) ++# else ++ add $VEC_SIZE, %rsi ++ add $VEC_SIZE, %rdi ++ jmp L(CopyVecSizeExit) ++# endif ++ ++ .p2align 4 ++L(CopyVecSizeUnaligned_32): ++ bsf %edx, %edx ++ vmovdqu %ymm4, (%rdi) ++ vmovdqu %ymm5, VEC_SIZE(%rdi) ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++# ifdef USE_AS_STPCPY ++ lea (VEC_SIZE * 2)(%rdi, %rdx), %rax ++# endif ++ vmovdqu %ymm6, (VEC_SIZE * 2)(%rdi) ++ add $((VEC_SIZE * 2) - 1), %r8 ++ sub %rdx, %r8 ++ lea ((VEC_SIZE * 2) + 1)(%rdi, %rdx), %rdi ++ jmp L(StrncpyFillTailWithZero) ++# else ++ add $(VEC_SIZE * 2), %rsi ++ add $(VEC_SIZE * 2), %rdi ++ jmp L(CopyVecSizeExit) ++# endif ++ ++# ifdef USE_AS_STRNCPY ++# ifndef USE_AS_STRCAT ++ .p2align 4 ++L(CopyVecSizeUnalignedVec6): ++ vmovdqu %ymm6, (%rdi, %rcx) ++ jmp L(CopyVecSizeVecExit) ++ ++ .p2align 4 ++L(CopyVecSizeUnalignedVec5): ++ vmovdqu %ymm5, (%rdi, %rcx) ++ jmp L(CopyVecSizeVecExit) ++ ++ .p2align 4 ++L(CopyVecSizeUnalignedVec4): ++ vmovdqu %ymm4, (%rdi, %rcx) ++ jmp L(CopyVecSizeVecExit) ++ ++ .p2align 4 ++L(CopyVecSizeUnalignedVec3): ++ vmovdqu %ymm3, (%rdi, %rcx) ++ jmp L(CopyVecSizeVecExit) ++# endif ++ ++/* Case2 */ ++ ++ .p2align 4 ++L(CopyVecSizeCase2): ++ add $VEC_SIZE, %r8 ++ add %rcx, %rdi ++ add %rcx, %rsi ++ bsf %edx, %edx ++ cmp %r8d, %edx ++ jb L(CopyVecSizeExit) ++ jmp L(StrncpyExit) ++ ++ .p2align 4 ++L(CopyTwoVecSizeCase2): ++ add %rcx, %rsi ++ bsf %edx, %edx ++ add $VEC_SIZE, %edx ++ sub %ecx, %edx ++ cmp %r8d, %edx ++ jb L(CopyVecSizeExit) ++ jmp L(StrncpyExit) ++ ++L(CopyVecSizeTailCase2): ++ add %rcx, %rsi ++ bsf %edx, %edx ++ cmp %r8d, %edx ++ jb L(CopyVecSizeExit) ++ jmp L(StrncpyExit) ++ ++L(CopyVecSizeTail1Case2): ++ bsf %edx, %edx ++ cmp %r8d, %edx ++ jb L(CopyVecSizeExit) ++ jmp L(StrncpyExit) ++ ++/* Case2 or Case3, Case3 */ ++ ++ .p2align 4 ++L(CopyVecSizeCase2OrCase3): ++ test %rdx, %rdx ++ jnz L(CopyVecSizeCase2) ++L(CopyVecSizeCase3): ++ add $VEC_SIZE, %r8 ++ add %rcx, %rdi ++ add %rcx, %rsi ++ jmp L(StrncpyExit) ++ ++ .p2align 4 ++L(CopyTwoVecSizeCase2OrCase3): ++ test %rdx, %rdx ++ jnz L(CopyTwoVecSizeCase2) ++ add %rcx, %rsi ++ jmp L(StrncpyExit) ++ ++ .p2align 4 ++L(CopyVecSizeTailCase2OrCase3): ++ test %rdx, %rdx ++ jnz L(CopyVecSizeTailCase2) ++ add %rcx, %rsi ++ jmp L(StrncpyExit) ++ ++ .p2align 4 ++L(CopyTwoVecSize1Case2OrCase3): ++ add $VEC_SIZE, %rdi ++ add $VEC_SIZE, %rsi ++ sub $VEC_SIZE, %r8 ++L(CopyVecSizeTail1Case2OrCase3): ++ test %rdx, %rdx ++ jnz L(CopyVecSizeTail1Case2) ++ jmp L(StrncpyExit) ++# endif ++ ++/*------------End labels regarding with copying 1-VEC_SIZE bytes--and 1-(VEC_SIZE*2) bytes----*/ ++ ++ .p2align 4 ++L(Exit1): ++ movzwl (%rsi), %edx ++ mov %dx, (%rdi) ++# ifdef USE_AS_STPCPY ++ lea 1(%rdi), %rax ++# endif ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ sub $2, %r8 ++ lea 2(%rdi), %rdi ++ jnz L(StrncpyFillTailWithZero) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(Exit2): ++ movzwl (%rsi), %ecx ++ mov %cx, (%rdi) ++ movb $0, 2(%rdi) ++# ifdef USE_AS_STPCPY ++ lea 2(%rdi), %rax ++# endif ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ sub $3, %r8 ++ lea 3(%rdi), %rdi ++ jnz L(StrncpyFillTailWithZero) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(Exit3): ++ mov (%rsi), %edx ++ mov %edx, (%rdi) ++# ifdef USE_AS_STPCPY ++ lea 3(%rdi), %rax ++# endif ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ sub $4, %r8 ++ lea 4(%rdi), %rdi ++ jnz L(StrncpyFillTailWithZero) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(Exit4_7): ++ mov (%rsi), %ecx ++ mov %ecx, (%rdi) ++ mov -3(%rsi, %rdx), %ecx ++ mov %ecx, -3(%rdi, %rdx) ++# ifdef USE_AS_STPCPY ++ lea (%rdi, %rdx), %rax ++# endif ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ sub %rdx, %r8 ++ sub $1, %r8 ++ lea 1(%rdi, %rdx), %rdi ++ jnz L(StrncpyFillTailWithZero) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(Exit8_15): ++ mov (%rsi), %rcx ++ mov -7(%rsi, %rdx), %r9 ++ mov %rcx, (%rdi) ++ mov %r9, -7(%rdi, %rdx) ++# ifdef USE_AS_STPCPY ++ lea (%rdi, %rdx), %rax ++# endif ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ sub %rdx, %r8 ++ sub $1, %r8 ++ lea 1(%rdi, %rdx), %rdi ++ jnz L(StrncpyFillTailWithZero) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(Exit16_31): ++ vmovdqu (%rsi), %xmm2 ++ vmovdqu -15(%rsi, %rdx), %xmm3 ++ vmovdqu %xmm2, (%rdi) ++ vmovdqu %xmm3, -15(%rdi, %rdx) ++# ifdef USE_AS_STPCPY ++ lea (%rdi, %rdx), %rax ++# endif ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ sub %rdx, %r8 ++ sub $1, %r8 ++ lea 1(%rdi, %rdx), %rdi ++ jnz L(StrncpyFillTailWithZero) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(Exit32_63): ++ vmovdqu (%rsi), %ymm2 ++ vmovdqu -31(%rsi, %rdx), %ymm3 ++ vmovdqu %ymm2, (%rdi) ++ vmovdqu %ymm3, -31(%rdi, %rdx) ++# ifdef USE_AS_STPCPY ++ lea (%rdi, %rdx), %rax ++# endif ++# if defined USE_AS_STRNCPY && !defined USE_AS_STRCAT ++ sub %rdx, %r8 ++ sub $1, %r8 ++ lea 1(%rdi, %rdx), %rdi ++ jnz L(StrncpyFillTailWithZero) ++# endif ++ VZEROUPPER ++ ret ++ ++# ifdef USE_AS_STRNCPY ++ ++ .p2align 4 ++L(StrncpyExit1): ++ movzbl (%rsi), %edx ++ mov %dl, (%rdi) ++# ifdef USE_AS_STPCPY ++ lea 1(%rdi), %rax ++# endif ++# ifdef USE_AS_STRCAT ++ movb $0, 1(%rdi) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(StrncpyExit2): ++ movzwl (%rsi), %edx ++ mov %dx, (%rdi) ++# ifdef USE_AS_STPCPY ++ lea 2(%rdi), %rax ++# endif ++# ifdef USE_AS_STRCAT ++ movb $0, 2(%rdi) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(StrncpyExit3_4): ++ movzwl (%rsi), %ecx ++ movzwl -2(%rsi, %r8), %edx ++ mov %cx, (%rdi) ++ mov %dx, -2(%rdi, %r8) ++# ifdef USE_AS_STPCPY ++ lea (%rdi, %r8), %rax ++# endif ++# ifdef USE_AS_STRCAT ++ movb $0, (%rdi, %r8) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(StrncpyExit5_8): ++ mov (%rsi), %ecx ++ mov -4(%rsi, %r8), %edx ++ mov %ecx, (%rdi) ++ mov %edx, -4(%rdi, %r8) ++# ifdef USE_AS_STPCPY ++ lea (%rdi, %r8), %rax ++# endif ++# ifdef USE_AS_STRCAT ++ movb $0, (%rdi, %r8) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(StrncpyExit9_16): ++ mov (%rsi), %rcx ++ mov -8(%rsi, %r8), %rdx ++ mov %rcx, (%rdi) ++ mov %rdx, -8(%rdi, %r8) ++# ifdef USE_AS_STPCPY ++ lea (%rdi, %r8), %rax ++# endif ++# ifdef USE_AS_STRCAT ++ movb $0, (%rdi, %r8) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(StrncpyExit17_32): ++ vmovdqu (%rsi), %xmm2 ++ vmovdqu -16(%rsi, %r8), %xmm3 ++ vmovdqu %xmm2, (%rdi) ++ vmovdqu %xmm3, -16(%rdi, %r8) ++# ifdef USE_AS_STPCPY ++ lea (%rdi, %r8), %rax ++# endif ++# ifdef USE_AS_STRCAT ++ movb $0, (%rdi, %r8) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(StrncpyExit33_64): ++ /* 0/32, 31/16 */ ++ vmovdqu (%rsi), %ymm2 ++ vmovdqu -VEC_SIZE(%rsi, %r8), %ymm3 ++ vmovdqu %ymm2, (%rdi) ++ vmovdqu %ymm3, -VEC_SIZE(%rdi, %r8) ++# ifdef USE_AS_STPCPY ++ lea (%rdi, %r8), %rax ++# endif ++# ifdef USE_AS_STRCAT ++ movb $0, (%rdi, %r8) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(StrncpyExit65): ++ /* 0/32, 32/32, 64/1 */ ++ vmovdqu (%rsi), %ymm2 ++ vmovdqu 32(%rsi), %ymm3 ++ mov 64(%rsi), %cl ++ vmovdqu %ymm2, (%rdi) ++ vmovdqu %ymm3, 32(%rdi) ++ mov %cl, 64(%rdi) ++# ifdef USE_AS_STPCPY ++ lea 65(%rdi), %rax ++# endif ++# ifdef USE_AS_STRCAT ++ movb $0, 65(%rdi) ++# endif ++ VZEROUPPER ++ ret ++ ++# ifndef USE_AS_STRCAT ++ ++ .p2align 4 ++L(Fill1): ++ mov %dl, (%rdi) ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(Fill2): ++ mov %dx, (%rdi) ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(Fill3_4): ++ mov %dx, (%rdi) ++ mov %dx, -2(%rdi, %r8) ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(Fill5_8): ++ mov %edx, (%rdi) ++ mov %edx, -4(%rdi, %r8) ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(Fill9_16): ++ mov %rdx, (%rdi) ++ mov %rdx, -8(%rdi, %r8) ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(Fill17_32): ++ vmovdqu %xmmZ, (%rdi) ++ vmovdqu %xmmZ, -16(%rdi, %r8) ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(CopyVecSizeUnalignedVec2): ++ vmovdqu %ymm2, (%rdi, %rcx) ++ ++ .p2align 4 ++L(CopyVecSizeVecExit): ++ bsf %edx, %edx ++ add $(VEC_SIZE - 1), %r8 ++ add %rcx, %rdi ++# ifdef USE_AS_STPCPY ++ lea (%rdi, %rdx), %rax ++# endif ++ sub %rdx, %r8 ++ lea 1(%rdi, %rdx), %rdi ++ ++ .p2align 4 ++L(StrncpyFillTailWithZero): ++ xor %edx, %edx ++ sub $VEC_SIZE, %r8 ++ jbe L(StrncpyFillExit) ++ ++ vmovdqu %ymmZ, (%rdi) ++ add $VEC_SIZE, %rdi ++ ++ mov %rdi, %rsi ++ and $(VEC_SIZE - 1), %esi ++ sub %rsi, %rdi ++ add %rsi, %r8 ++ sub $(VEC_SIZE * 4), %r8 ++ jb L(StrncpyFillLessFourVecSize) ++ ++L(StrncpyFillLoopVmovdqa): ++ vmovdqa %ymmZ, (%rdi) ++ vmovdqa %ymmZ, VEC_SIZE(%rdi) ++ vmovdqa %ymmZ, (VEC_SIZE * 2)(%rdi) ++ vmovdqa %ymmZ, (VEC_SIZE * 3)(%rdi) ++ add $(VEC_SIZE * 4), %rdi ++ sub $(VEC_SIZE * 4), %r8 ++ jae L(StrncpyFillLoopVmovdqa) ++ ++L(StrncpyFillLessFourVecSize): ++ add $(VEC_SIZE * 2), %r8 ++ jl L(StrncpyFillLessTwoVecSize) ++ vmovdqa %ymmZ, (%rdi) ++ vmovdqa %ymmZ, VEC_SIZE(%rdi) ++ add $(VEC_SIZE * 2), %rdi ++ sub $VEC_SIZE, %r8 ++ jl L(StrncpyFillExit) ++ vmovdqa %ymmZ, (%rdi) ++ add $VEC_SIZE, %rdi ++ jmp L(Fill) ++ ++ .p2align 4 ++L(StrncpyFillLessTwoVecSize): ++ add $VEC_SIZE, %r8 ++ jl L(StrncpyFillExit) ++ vmovdqa %ymmZ, (%rdi) ++ add $VEC_SIZE, %rdi ++ jmp L(Fill) ++ ++ .p2align 4 ++L(StrncpyFillExit): ++ add $VEC_SIZE, %r8 ++L(Fill): ++ cmp $17, %r8d ++ jae L(Fill17_32) ++ cmp $9, %r8d ++ jae L(Fill9_16) ++ cmp $5, %r8d ++ jae L(Fill5_8) ++ cmp $3, %r8d ++ jae L(Fill3_4) ++ cmp $1, %r8d ++ ja L(Fill2) ++ je L(Fill1) ++ VZEROUPPER ++ ret ++ ++/* end of ifndef USE_AS_STRCAT */ ++# endif ++ ++ .p2align 4 ++L(UnalignedLeaveCase2OrCase3): ++ test %rdx, %rdx ++ jnz L(UnalignedFourVecSizeLeaveCase2) ++L(UnalignedFourVecSizeLeaveCase3): ++ lea (VEC_SIZE * 4)(%r8), %rcx ++ and $-VEC_SIZE, %rcx ++ add $(VEC_SIZE * 3), %r8 ++ jl L(CopyVecSizeCase3) ++ vmovdqu %ymm4, (%rdi) ++ sub $VEC_SIZE, %r8 ++ jb L(CopyVecSizeCase3) ++ vmovdqu %ymm5, VEC_SIZE(%rdi) ++ sub $VEC_SIZE, %r8 ++ jb L(CopyVecSizeCase3) ++ vmovdqu %ymm6, (VEC_SIZE * 2)(%rdi) ++ sub $VEC_SIZE, %r8 ++ jb L(CopyVecSizeCase3) ++ vmovdqu %ymm7, (VEC_SIZE * 3)(%rdi) ++# ifdef USE_AS_STPCPY ++ lea (VEC_SIZE * 4)(%rdi), %rax ++# endif ++# ifdef USE_AS_STRCAT ++ movb $0, (VEC_SIZE * 4)(%rdi) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(UnalignedFourVecSizeLeaveCase2): ++ xor %ecx, %ecx ++ vpcmpeqb %ymm4, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ add $(VEC_SIZE * 3), %r8 ++ jle L(CopyVecSizeCase2OrCase3) ++ test %edx, %edx ++# ifndef USE_AS_STRCAT ++ jnz L(CopyVecSizeUnalignedVec4) ++# else ++ jnz L(CopyVecSize) ++# endif ++ vpcmpeqb %ymm5, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ vmovdqu %ymm4, (%rdi) ++ add $VEC_SIZE, %rcx ++ sub $VEC_SIZE, %r8 ++ jbe L(CopyVecSizeCase2OrCase3) ++ test %edx, %edx ++# ifndef USE_AS_STRCAT ++ jnz L(CopyVecSizeUnalignedVec5) ++# else ++ jnz L(CopyVecSize) ++# endif ++ ++ vpcmpeqb %ymm6, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ vmovdqu %ymm5, VEC_SIZE(%rdi) ++ add $VEC_SIZE, %rcx ++ sub $VEC_SIZE, %r8 ++ jbe L(CopyVecSizeCase2OrCase3) ++ test %edx, %edx ++# ifndef USE_AS_STRCAT ++ jnz L(CopyVecSizeUnalignedVec6) ++# else ++ jnz L(CopyVecSize) ++# endif ++ ++ vpcmpeqb %ymm7, %ymmZ, %ymmM ++ vpmovmskb %ymmM, %edx ++ vmovdqu %ymm6, (VEC_SIZE * 2)(%rdi) ++ lea VEC_SIZE(%rdi, %rcx), %rdi ++ lea VEC_SIZE(%rsi, %rcx), %rsi ++ bsf %edx, %edx ++ cmp %r8d, %edx ++ jb L(CopyVecSizeExit) ++L(StrncpyExit): ++ cmp $65, %r8d ++ je L(StrncpyExit65) ++ cmp $33, %r8d ++ jae L(StrncpyExit33_64) ++ cmp $17, %r8d ++ jae L(StrncpyExit17_32) ++ cmp $9, %r8d ++ jae L(StrncpyExit9_16) ++ cmp $5, %r8d ++ jae L(StrncpyExit5_8) ++ cmp $3, %r8d ++ jae L(StrncpyExit3_4) ++ cmp $1, %r8d ++ ja L(StrncpyExit2) ++ je L(StrncpyExit1) ++# ifdef USE_AS_STPCPY ++ mov %rdi, %rax ++# endif ++# ifdef USE_AS_STRCAT ++ movb $0, (%rdi) ++# endif ++ VZEROUPPER ++ ret ++ ++ .p2align 4 ++L(ExitZero): ++# ifndef USE_AS_STRCAT ++ mov %rdi, %rax ++# endif ++ VZEROUPPER ++ ret ++ ++# endif ++ ++# ifndef USE_AS_STRCAT ++END (STRCPY) ++# else ++END (STRCAT) ++# endif ++#endif +diff --git a/sysdeps/x86_64/multiarch/strcpy.c b/sysdeps/x86_64/multiarch/strcpy.c +index 12e0e3ffe20602c6..ecf90d4b044a1b01 100644 +--- a/sysdeps/x86_64/multiarch/strcpy.c ++++ b/sysdeps/x86_64/multiarch/strcpy.c +@@ -24,7 +24,7 @@ + # undef strcpy + + # define SYMBOL_NAME strcpy +-# include "ifunc-unaligned-ssse3.h" ++# include "ifunc-strcpy.h" + + libc_ifunc_redirected (__redirect_strcpy, strcpy, IFUNC_SELECTOR ()); + +diff --git a/sysdeps/x86_64/multiarch/strncat-avx2.S b/sysdeps/x86_64/multiarch/strncat-avx2.S +new file mode 100644 +index 0000000000000000..bfefa659bb6281fa +--- /dev/null ++++ b/sysdeps/x86_64/multiarch/strncat-avx2.S +@@ -0,0 +1,3 @@ ++#define USE_AS_STRNCAT ++#define STRCAT __strncat_avx2 ++#include "strcat-avx2.S" +diff --git a/sysdeps/x86_64/multiarch/strncat.c b/sysdeps/x86_64/multiarch/strncat.c +index 841c165565add132..74f7d028ae23d700 100644 +--- a/sysdeps/x86_64/multiarch/strncat.c ++++ b/sysdeps/x86_64/multiarch/strncat.c +@@ -24,7 +24,7 @@ + # undef strncat + + # define SYMBOL_NAME strncat +-# include "ifunc-unaligned-ssse3.h" ++# include "ifunc-strcpy.h" + + libc_ifunc_redirected (__redirect_strncat, strncat, IFUNC_SELECTOR ()); + strong_alias (strncat, __strncat); +diff --git a/sysdeps/x86_64/multiarch/strncpy-avx2.S b/sysdeps/x86_64/multiarch/strncpy-avx2.S +new file mode 100644 +index 0000000000000000..9ef8c87627dc4924 +--- /dev/null ++++ b/sysdeps/x86_64/multiarch/strncpy-avx2.S +@@ -0,0 +1,3 @@ ++#define USE_AS_STRNCPY ++#define STRCPY __strncpy_avx2 ++#include "strcpy-avx2.S" +diff --git a/sysdeps/x86_64/multiarch/strncpy.c b/sysdeps/x86_64/multiarch/strncpy.c +index 3c3de8b18ebb177f..93dfb4cfde79467a 100644 +--- a/sysdeps/x86_64/multiarch/strncpy.c ++++ b/sysdeps/x86_64/multiarch/strncpy.c +@@ -24,7 +24,7 @@ + # undef strncpy + + # define SYMBOL_NAME strncpy +-# include "ifunc-unaligned-ssse3.h" ++# include "ifunc-strcpy.h" + + libc_ifunc_redirected (__redirect_strncpy, strncpy, IFUNC_SELECTOR ()); + diff --git a/glibc-rh1817513-18.patch b/glibc-rh1817513-18.patch new file mode 100755 index 0000000..d7d84b7 --- /dev/null +++ b/glibc-rh1817513-18.patch @@ -0,0 +1,191 @@ +commit 32db86d558193ad4ad5a00926ce3c350c89eb8df +Author: Joseph Myers +Date: Tue Feb 12 10:30:34 2019 +0000 + + Add fall-through comments. + + This patch adds fall-through comments in some cases where -Wextra + produces implicit-fallthrough warnings. + + The patch is non-exhaustive. Apart from architecture-specific code + for non-x86_64 architectures, it does not change sunrpc/xdr.c (legacy + code, probably should have such changes, but left to be dealt with + separately), or places that already had comments about the + fall-through but not matching the form expected by + -Wimplicit-fallthrough=3 (the default level with -Wextra; my + inclination is to adjust those comments to match rather than + downgrading to -Wimplicit-fallthrough=1 to allow any comment), or one + place where I thought the implicit fallthrough was not correct and so + should be handled separately as a bug fix. I think the key thing to + consider in review of this patch is whether the fall-through is indeed + intended and correct in each place where such a comment is added. + + Tested for x86_64. + + * elf/dl-exception.c (_dl_exception_create_format): Add + fall-through comments. + * elf/ldconfig.c (parse_conf_include): Likewise. + * elf/rtld.c (print_statistics): Likewise. + * locale/programs/charmap.c (parse_charmap): Likewise. + * misc/mntent_r.c (__getmntent_r): Likewise. + * posix/wordexp.c (parse_arith): Likewise. + (parse_backtick): Likewise. + * resolv/ns_ttl.c (ns_parse_ttl): Likewise. + * sysdeps/x86/cpu-features.c (init_cpu_features): Likewise. + * sysdeps/x86_64/dl-machine.h (elf_machine_rela): Likewise. + +diff --git a/elf/dl-exception.c b/elf/dl-exception.c +index 3e8e0ba3f1442005..d24bf30a5cf39bc2 100644 +--- a/elf/dl-exception.c ++++ b/elf/dl-exception.c +@@ -123,6 +123,7 @@ _dl_exception_create_format (struct dl_exception *exception, const char *objname + ++p; + break; + } ++ /* Fall through. */ + case 'x': + length += INT_WIDTH / 4; + break; +diff --git a/elf/ldconfig.c b/elf/ldconfig.c +index fbdd814edf59bc77..ed7d9ab0412d93fd 100644 +--- a/elf/ldconfig.c ++++ b/elf/ldconfig.c +@@ -1228,6 +1228,7 @@ parse_conf_include (const char *config_file, unsigned int lineno, + + case GLOB_NOSPACE: + errno = ENOMEM; ++ /* Fall through. */ + case GLOB_ABORTED: + if (opt_verbose) + error (0, errno, _("%s:%u: cannot read directory %s"), +diff --git a/elf/rtld.c b/elf/rtld.c +index 7f030f75a22c532e..8bb5f548a0ff8eb4 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2734,8 +2734,10 @@ print_statistics (hp_timing_t *rtld_total_timep) + { + case 3: + *wp++ = *cp++; ++ /* Fall through. */ + case 2: + *wp++ = *cp++; ++ /* Fall through. */ + case 1: + *wp++ = '.'; + *wp++ = *cp++; +@@ -2797,8 +2799,10 @@ print_statistics (hp_timing_t *rtld_total_timep) + { + case 3: + *wp++ = *cp++; ++ /* Fall through. */ + case 2: + *wp++ = *cp++; ++ /* Fall through. */ + case 1: + *wp++ = '.'; + *wp++ = *cp++; +diff --git a/locale/programs/charmap.c b/locale/programs/charmap.c +index 2d54dd3c027d11d2..8041a0e5d292f3f5 100644 +--- a/locale/programs/charmap.c ++++ b/locale/programs/charmap.c +@@ -713,6 +713,7 @@ only WIDTH definitions are allowed to follow the CHARMAP definition")); + state = 95; + continue; + } ++ /* Fall through. */ + + case 96: + if (nowtok != tok_number) +diff --git a/misc/mntent_r.c b/misc/mntent_r.c +index 7bb224f044150ab4..add39d4537eaccb5 100644 +--- a/misc/mntent_r.c ++++ b/misc/mntent_r.c +@@ -167,8 +167,10 @@ get_mnt_entry (FILE *stream, struct mntent *mp, char *buffer, int bufsiz) + { + case 0: + mp->mnt_freq = 0; ++ /* Fall through. */ + case 1: + mp->mnt_passno = 0; ++ /* Fall through. */ + case 2: + break; + } +diff --git a/posix/wordexp.c b/posix/wordexp.c +index 7548e0329fdeafaa..048a8068544c81fa 100644 +--- a/posix/wordexp.c ++++ b/posix/wordexp.c +@@ -799,6 +799,7 @@ parse_arith (char **word, size_t *word_length, size_t *max_length, + + case '(': + ++paren_depth; ++ /* Fall through. */ + default: + expr = w_addchar (expr, &expr_length, &expr_maxlen, words[*offset]); + if (expr == NULL) +@@ -2127,6 +2128,7 @@ parse_backtick (char **word, size_t *word_length, size_t *max_length, + + case '\'': + squoting = 1 - squoting; ++ /* Fall through. */ + default: + comm = w_addchar (comm, &comm_length, &comm_maxlen, words[*offset]); + if (comm == NULL) +diff --git a/resolv/ns_ttl.c b/resolv/ns_ttl.c +index 079948790b94b05e..d29d9dc00cfcab2c 100644 +--- a/resolv/ns_ttl.c ++++ b/resolv/ns_ttl.c +@@ -113,9 +113,13 @@ ns_parse_ttl(const char *src, u_long *dst) { + ch = toupper(ch); + switch (ch) { + case 'W': tmp *= 7; ++ /* Fall through. */ + case 'D': tmp *= 24; ++ /* Fall through. */ + case 'H': tmp *= 60; ++ /* Fall through. */ + case 'M': tmp *= 60; ++ /* Fall through. */ + case 'S': break; + default: goto einval; + } +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 3a02a9c7d08f9603..ade37a9bb3de86cc 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -374,6 +374,7 @@ init_cpu_features (struct cpu_features *cpu_features) + of Core i3/i5/i7 processors if AVX is available. */ + if (!CPU_FEATURES_CPU_P (cpu_features, AVX)) + break; ++ /* Fall through. */ + + case 0x1a: + case 0x1e: +@@ -401,6 +402,7 @@ init_cpu_features (struct cpu_features *cpu_features) + /* Xeon E7 v3 with stepping >= 4 has working TSX. */ + if (stepping >= 4) + break; ++ /* Fall through. */ + case 0x3c: + case 0x45: + case 0x46: +diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h +index 1942ed5061d18c68..23afb3c05dbe17d6 100644 +--- a/sysdeps/x86_64/dl-machine.h ++++ b/sysdeps/x86_64/dl-machine.h +@@ -347,6 +347,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, + /* Set to symbol size plus addend. */ + value = sym->st_size; + # endif ++ /* Fall through. */ + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + *reloc_addr = value + reloc->r_addend; +@@ -460,6 +461,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, + /* Set to symbol size plus addend. */ + value = sym->st_size; + # endif ++ /* Fall through. */ + case R_X86_64_32: + value += reloc->r_addend; + *(unsigned int *) reloc_addr = value; diff --git a/glibc-rh1817513-19.patch b/glibc-rh1817513-19.patch new file mode 100755 index 0000000..674aa43 --- /dev/null +++ b/glibc-rh1817513-19.patch @@ -0,0 +1,408 @@ +commit 3b856d093f5197637a5927c37d6c07dad8c86d45 +Author: Florian Weimer +Date: Tue Feb 12 13:36:56 2019 +0100 + + elf: Ignore LD_AUDIT interfaces if la_version returns 0 [BZ #24122] + + This change moves the audit module loading and early notification into + separate functions out of dl_main. + + It restores the bug fix from commit + 8e889c5da3c5981c5a46a93fec02de40131ac5a6 ("elf: Fix LD_AUDIT for + modules with invalid version (BZ#24122)") which was reverted in commit + 83e6b59625f45db1eee93e5684091f740c52a083 ("[elf] Revert 8e889c5da3 + (BZ#24122)"). + + The actual bug fix is the separate error message for the case when + la_version returns zero. The dynamic linker error message (which is + NULL in this case) is no longer used. Based on the intended use of + version zero (ignore this module due to explicit request), the message + is only printed if debugging is enabled. + +diff --git a/elf/rtld.c b/elf/rtld.c +index 8bb5f548a0ff8eb4..375e0de8fa2e049e 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -864,6 +864,205 @@ handle_preload_list (const char *preloadlist, struct link_map *main_map, + return npreloads; + } + ++/* Called if the audit DSO cannot be used: if it does not have the ++ appropriate interfaces, or it expects a more recent version library ++ version than what the dynamic linker provides. */ ++static void ++unload_audit_module (struct link_map *map, int original_tls_idx) ++{ ++#ifndef NDEBUG ++ Lmid_t ns = map->l_ns; ++#endif ++ _dl_close (map); ++ ++ /* Make sure the namespace has been cleared entirely. */ ++ assert (GL(dl_ns)[ns]._ns_loaded == NULL); ++ assert (GL(dl_ns)[ns]._ns_nloaded == 0); ++ ++ GL(dl_tls_max_dtv_idx) = original_tls_idx; ++} ++ ++/* Called to print an error message if loading of an audit module ++ failed. */ ++static void ++report_audit_module_load_error (const char *name, const char *err_str, ++ bool malloced) ++{ ++ _dl_error_printf ("\ ++ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", ++ name, err_str); ++ if (malloced) ++ free ((char *) err_str); ++} ++ ++/* Load one audit module. */ ++static void ++load_audit_module (const char *name, struct audit_ifaces **last_audit) ++{ ++ int original_tls_idx = GL(dl_tls_max_dtv_idx); ++ ++ struct dlmopen_args dlmargs; ++ dlmargs.fname = name; ++ dlmargs.map = NULL; ++ ++ const char *objname; ++ const char *err_str = NULL; ++ bool malloced; ++ _dl_catch_error (&objname, &err_str, &malloced, dlmopen_doit, &dlmargs); ++ if (__glibc_unlikely (err_str != NULL)) ++ { ++ report_audit_module_load_error (name, err_str, malloced); ++ return; ++ } ++ ++ struct lookup_args largs; ++ largs.name = "la_version"; ++ largs.map = dlmargs.map; ++ _dl_catch_error (&objname, &err_str, &malloced, lookup_doit, &largs); ++ if (__glibc_likely (err_str != NULL)) ++ { ++ unload_audit_module (dlmargs.map, original_tls_idx); ++ report_audit_module_load_error (name, err_str, malloced); ++ return; ++ } ++ ++ unsigned int (*laversion) (unsigned int) = largs.result; ++ ++ /* A null symbol indicates that something is very wrong with the ++ loaded object because defined symbols are supposed to have a ++ valid, non-null address. */ ++ assert (laversion != NULL); ++ ++ unsigned int lav = laversion (LAV_CURRENT); ++ if (lav == 0) ++ { ++ /* Only print an error message if debugging because this can ++ happen deliberately. */ ++ if (GLRO(dl_debug_mask) & DL_DEBUG_FILES) ++ _dl_debug_printf ("\ ++file=%s [%lu]; audit interface function la_version returned zero; ignored.\n", ++ dlmargs.map->l_name, dlmargs.map->l_ns); ++ unload_audit_module (dlmargs.map, original_tls_idx); ++ return; ++ } ++ ++ if (lav > LAV_CURRENT) ++ { ++ _dl_debug_printf ("\ ++ERROR: audit interface '%s' requires version %d (maximum supported version %d); ignored.\n", ++ name, lav, LAV_CURRENT); ++ unload_audit_module (dlmargs.map, original_tls_idx); ++ return; ++ } ++ ++ enum { naudit_ifaces = 8 }; ++ union ++ { ++ struct audit_ifaces ifaces; ++ void (*fptr[naudit_ifaces]) (void); ++ } *newp = malloc (sizeof (*newp)); ++ if (newp == NULL) ++ _dl_fatal_printf ("Out of memory while loading audit modules\n"); ++ ++ /* Names of the auditing interfaces. All in one ++ long string. */ ++ static const char audit_iface_names[] = ++ "la_activity\0" ++ "la_objsearch\0" ++ "la_objopen\0" ++ "la_preinit\0" ++#if __ELF_NATIVE_CLASS == 32 ++ "la_symbind32\0" ++#elif __ELF_NATIVE_CLASS == 64 ++ "la_symbind64\0" ++#else ++# error "__ELF_NATIVE_CLASS must be defined" ++#endif ++#define STRING(s) __STRING (s) ++ "la_" STRING (ARCH_LA_PLTENTER) "\0" ++ "la_" STRING (ARCH_LA_PLTEXIT) "\0" ++ "la_objclose\0"; ++ unsigned int cnt = 0; ++ const char *cp = audit_iface_names; ++ do ++ { ++ largs.name = cp; ++ _dl_catch_error (&objname, &err_str, &malloced, lookup_doit, &largs); ++ ++ /* Store the pointer. */ ++ if (err_str == NULL && largs.result != NULL) ++ { ++ newp->fptr[cnt] = largs.result; ++ ++ /* The dynamic linker link map is statically allocated, ++ initialize the data now. */ ++ GL(dl_rtld_map).l_audit[cnt].cookie = (intptr_t) &GL(dl_rtld_map); ++ } ++ else ++ newp->fptr[cnt] = NULL; ++ ++cnt; ++ ++ cp = rawmemchr (cp, '\0') + 1; ++ } ++ while (*cp != '\0'); ++ assert (cnt == naudit_ifaces); ++ ++ /* Now append the new auditing interface to the list. */ ++ newp->ifaces.next = NULL; ++ if (*last_audit == NULL) ++ *last_audit = GLRO(dl_audit) = &newp->ifaces; ++ else ++ *last_audit = (*last_audit)->next = &newp->ifaces; ++ ++GLRO(dl_naudit); ++ ++ /* Mark the DSO as being used for auditing. */ ++ dlmargs.map->l_auditing = 1; ++} ++ ++/* Notify the the audit modules that the object MAP has already been ++ loaded. */ ++static void ++notify_audit_modules_of_loaded_object (struct link_map *map) ++{ ++ struct audit_ifaces *afct = GLRO(dl_audit); ++ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ { ++ if (afct->objopen != NULL) ++ { ++ map->l_audit[cnt].bindflags ++ = afct->objopen (map, LM_ID_BASE, &map->l_audit[cnt].cookie); ++ map->l_audit_any_plt |= map->l_audit[cnt].bindflags != 0; ++ } ++ ++ afct = afct->next; ++ } ++} ++ ++/* Load all audit modules. */ ++static void ++load_audit_modules (struct link_map *main_map) ++{ ++ struct audit_ifaces *last_audit = NULL; ++ struct audit_list_iter al_iter; ++ audit_list_iter_init (&al_iter); ++ ++ while (true) ++ { ++ const char *name = audit_list_iter_next (&al_iter); ++ if (name == NULL) ++ break; ++ load_audit_module (name, &last_audit); ++ } ++ ++ /* Notify audit modules of the initially loaded modules (the main ++ program and the dynamic linker itself). */ ++ if (GLRO(dl_naudit) > 0) ++ { ++ notify_audit_modules_of_loaded_object (main_map); ++ notify_audit_modules_of_loaded_object (&GL(dl_rtld_map)); ++ } ++} ++ + static void + dl_main (const ElfW(Phdr) *phdr, + ElfW(Word) phnum, +@@ -1402,10 +1601,6 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + if (__glibc_unlikely (audit_list != NULL) + || __glibc_unlikely (audit_list_string != NULL)) + { +- struct audit_ifaces *last_audit = NULL; +- struct audit_list_iter al_iter; +- audit_list_iter_init (&al_iter); +- + /* Since we start using the auditing DSOs right away we need to + initialize the data structures now. */ + tcbp = init_tls (); +@@ -1417,164 +1612,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + security_init (); + need_security_init = false; + +- while (true) +- { +- const char *name = audit_list_iter_next (&al_iter); +- if (name == NULL) +- break; +- +- int tls_idx = GL(dl_tls_max_dtv_idx); +- +- /* Now it is time to determine the layout of the static TLS +- block and allocate it for the initial thread. Note that we +- always allocate the static block, we never defer it even if +- no DF_STATIC_TLS bit is set. The reason is that we know +- glibc will use the static model. */ +- struct dlmopen_args dlmargs; +- dlmargs.fname = name; +- dlmargs.map = NULL; +- +- const char *objname; +- const char *err_str = NULL; +- bool malloced; +- (void) _dl_catch_error (&objname, &err_str, &malloced, dlmopen_doit, +- &dlmargs); +- if (__glibc_unlikely (err_str != NULL)) +- { +- not_loaded: +- _dl_error_printf ("\ +-ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n", +- name, err_str); +- if (malloced) +- free ((char *) err_str); +- } +- else +- { +- struct lookup_args largs; +- largs.name = "la_version"; +- largs.map = dlmargs.map; +- +- /* Check whether the interface version matches. */ +- (void) _dl_catch_error (&objname, &err_str, &malloced, +- lookup_doit, &largs); +- +- unsigned int (*laversion) (unsigned int); +- unsigned int lav; +- if (err_str == NULL +- && (laversion = largs.result) != NULL +- && (lav = laversion (LAV_CURRENT)) > 0 +- && lav <= LAV_CURRENT) +- { +- /* Allocate structure for the callback function pointers. +- This call can never fail. */ +- union +- { +- struct audit_ifaces ifaces; +-#define naudit_ifaces 8 +- void (*fptr[naudit_ifaces]) (void); +- } *newp = malloc (sizeof (*newp)); +- +- /* Names of the auditing interfaces. All in one +- long string. */ +- static const char audit_iface_names[] = +- "la_activity\0" +- "la_objsearch\0" +- "la_objopen\0" +- "la_preinit\0" +-#if __ELF_NATIVE_CLASS == 32 +- "la_symbind32\0" +-#elif __ELF_NATIVE_CLASS == 64 +- "la_symbind64\0" +-#else +-# error "__ELF_NATIVE_CLASS must be defined" +-#endif +-#define STRING(s) __STRING (s) +- "la_" STRING (ARCH_LA_PLTENTER) "\0" +- "la_" STRING (ARCH_LA_PLTEXIT) "\0" +- "la_objclose\0"; +- unsigned int cnt = 0; +- const char *cp = audit_iface_names; +- do +- { +- largs.name = cp; +- (void) _dl_catch_error (&objname, &err_str, &malloced, +- lookup_doit, &largs); +- +- /* Store the pointer. */ +- if (err_str == NULL && largs.result != NULL) +- { +- newp->fptr[cnt] = largs.result; +- +- /* The dynamic linker link map is statically +- allocated, initialize the data now. */ +- GL(dl_rtld_map).l_audit[cnt].cookie +- = (intptr_t) &GL(dl_rtld_map); +- } +- else +- newp->fptr[cnt] = NULL; +- ++cnt; +- +- cp = (char *) rawmemchr (cp, '\0') + 1; +- } +- while (*cp != '\0'); +- assert (cnt == naudit_ifaces); +- +- /* Now append the new auditing interface to the list. */ +- newp->ifaces.next = NULL; +- if (last_audit == NULL) +- last_audit = GLRO(dl_audit) = &newp->ifaces; +- else +- last_audit = last_audit->next = &newp->ifaces; +- ++GLRO(dl_naudit); +- +- /* Mark the DSO as being used for auditing. */ +- dlmargs.map->l_auditing = 1; +- } +- else +- { +- /* We cannot use the DSO, it does not have the +- appropriate interfaces or it expects something +- more recent. */ +-#ifndef NDEBUG +- Lmid_t ns = dlmargs.map->l_ns; +-#endif +- _dl_close (dlmargs.map); +- +- /* Make sure the namespace has been cleared entirely. */ +- assert (GL(dl_ns)[ns]._ns_loaded == NULL); +- assert (GL(dl_ns)[ns]._ns_nloaded == 0); +- +- GL(dl_tls_max_dtv_idx) = tls_idx; +- goto not_loaded; +- } +- } +- } +- +- /* If we have any auditing modules, announce that we already +- have two objects loaded. */ +- if (__glibc_unlikely (GLRO(dl_naudit) > 0)) +- { +- struct link_map *ls[2] = { main_map, &GL(dl_rtld_map) }; +- +- for (unsigned int outer = 0; outer < 2; ++outer) +- { +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->objopen != NULL) +- { +- ls[outer]->l_audit[cnt].bindflags +- = afct->objopen (ls[outer], LM_ID_BASE, +- &ls[outer]->l_audit[cnt].cookie); +- +- ls[outer]->l_audit_any_plt +- |= ls[outer]->l_audit[cnt].bindflags != 0; +- } +- +- afct = afct->next; +- } +- } +- } ++ load_audit_modules (main_map); + } + + /* Keep track of the currently loaded modules to count how many diff --git a/glibc-rh1817513-2.patch b/glibc-rh1817513-2.patch new file mode 100755 index 0000000..f477471 --- /dev/null +++ b/glibc-rh1817513-2.patch @@ -0,0 +1,401 @@ +commit dce452dc5278f2985d21315721a6ba802537b862 +Author: Siddhesh Poyarekar +Date: Thu Aug 2 23:49:19 2018 +0530 + + Rename the glibc.tune namespace to glibc.cpu + + The glibc.tune namespace is vaguely named since it is a 'tunable', so + give it a more specific name that describes what it refers to. Rename + the tunable namespace to 'cpu' to more accurately reflect what it + encompasses. Also rename glibc.tune.cpu to glibc.cpu.name since + glibc.cpu.cpu is weird. + + * NEWS: Mention the change. + * elf/dl-tunables.list: Rename tune namespace to cpu. + * sysdeps/powerpc/dl-tunables.list: Likewise. + * sysdeps/x86/dl-tunables.list: Likewise. + * sysdeps/aarch64/dl-tunables.list: Rename tune.cpu to + cpu.name. + * elf/dl-hwcaps.c (_dl_important_hwcaps): Adjust. + * elf/dl-hwcaps.h (GET_HWCAP_MASK): Likewise. + * manual/README.tunables: Likewise. + * manual/tunables.texi: Likewise. + * sysdeps/powerpc/cpu-features.c: Likewise. + * sysdeps/unix/sysv/linux/aarch64/cpu-features.c + (init_cpu_features): Likewise. + * sysdeps/x86/cpu-features.c: Likewise. + * sysdeps/x86/cpu-features.h: Likewise. + * sysdeps/x86/cpu-tunables.c: Likewise. + * sysdeps/x86_64/Makefile: Likewise. + * sysdeps/x86/dl-cet.c: Likewise. + + Reviewed-by: Carlos O'Donell + +Conflicts: + manual/tunables.texi + (Earlier backport of non-temporal memcpy threshold.) + sysdeps/x86/Makefile + (Earlier CET backports.) + +diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c +index 23482a88a1c9bca9..ecf00b457760e517 100644 +--- a/elf/dl-hwcaps.c ++++ b/elf/dl-hwcaps.c +@@ -140,7 +140,7 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, + string and bit like you can ignore an OS-supplied HWCAP bit. */ + hwcap_mask |= (uint64_t) mask << _DL_FIRST_EXTRA; + #if HAVE_TUNABLES +- TUNABLE_SET (glibc, tune, hwcap_mask, uint64_t, hwcap_mask); ++ TUNABLE_SET (glibc, cpu, hwcap_mask, uint64_t, hwcap_mask); + #else + GLRO(dl_hwcap_mask) = hwcap_mask; + #endif +diff --git a/elf/dl-hwcaps.h b/elf/dl-hwcaps.h +index 17f0da4c73772425..d69ee11dc27bb5e5 100644 +--- a/elf/dl-hwcaps.h ++++ b/elf/dl-hwcaps.h +@@ -19,7 +19,7 @@ + #include + + #if HAVE_TUNABLES +-# define GET_HWCAP_MASK() TUNABLE_GET (glibc, tune, hwcap_mask, uint64_t, NULL) ++# define GET_HWCAP_MASK() TUNABLE_GET (glibc, cpu, hwcap_mask, uint64_t, NULL) + #else + # ifdef SHARED + # define GET_HWCAP_MASK() GLRO(dl_hwcap_mask) +diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list +index 1ff6fcb6f24f93a8..b7cc79f8bfe0a7c6 100644 +--- a/elf/dl-tunables.list ++++ b/elf/dl-tunables.list +@@ -91,7 +91,7 @@ glibc { + security_level: SXID_IGNORE + } + } +- tune { ++ cpu { + hwcap_mask { + type: UINT_64 + env_alias: LD_HWCAP_MASK +diff --git a/manual/README.tunables b/manual/README.tunables +index 3967679f432a6378..f87a31a65e0a3455 100644 +--- a/manual/README.tunables ++++ b/manual/README.tunables +@@ -105,11 +105,11 @@ where 'check' is the tunable name, 'int32_t' is the C type of the tunable and + To get and set tunables in a different namespace from that module, use the full + form of the macros as follows: + +- val = TUNABLE_GET_FULL (glibc, tune, hwcap_mask, uint64_t, NULL) ++ val = TUNABLE_GET_FULL (glibc, cpu, hwcap_mask, uint64_t, NULL) + +- TUNABLE_SET_FULL (glibc, tune, hwcap_mask, uint64_t, val) ++ TUNABLE_SET_FULL (glibc, cpu, hwcap_mask, uint64_t, val) + +-where 'glibc' is the top namespace, 'tune' is the tunable namespace and the ++where 'glibc' is the top namespace, 'cpu' is the tunable namespace and the + remaining arguments are the same as the short form macros. + + When TUNABLE_NAMESPACE is not defined in a module, TUNABLE_GET is equivalent to +diff --git a/manual/tunables.texi b/manual/tunables.texi +index 3e1e519dff153b09..ef10d2872cfc244e 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -307,23 +307,23 @@ The default value of this tunable is @samp{3}. + @cindex non_temporal_threshold tunables + @cindex tunables, non_temporal_threshold + +-@deftp {Tunable namespace} glibc.tune ++@deftp {Tunable namespace} glibc.cpu + Behavior of @theglibc{} can be tuned to assume specific hardware capabilities +-by setting the following tunables in the @code{tune} namespace: ++by setting the following tunables in the @code{cpu} namespace: + @end deftp + +-@deftp Tunable glibc.tune.hwcap_mask ++@deftp Tunable glibc.cpu.hwcap_mask + This tunable supersedes the @env{LD_HWCAP_MASK} environment variable and is + identical in features. + + The @code{AT_HWCAP} key in the Auxiliary Vector specifies instruction set + extensions available in the processor at runtime for some architectures. The +-@code{glibc.tune.hwcap_mask} tunable allows the user to mask out those ++@code{glibc.cpu.hwcap_mask} tunable allows the user to mask out those + capabilities at runtime, thus disabling use of those extensions. + @end deftp + +-@deftp Tunable glibc.tune.hwcaps +-The @code{glibc.tune.hwcaps=-xxx,yyy,-zzz...} tunable allows the user to ++@deftp Tunable glibc.cpu.hwcaps ++The @code{glibc.cpu.hwcaps=-xxx,yyy,-zzz...} tunable allows the user to + enable CPU/ARCH feature @code{yyy}, disable CPU/ARCH feature @code{xxx} + and @code{zzz} where the feature name is case-sensitive and has to match + the ones in @code{sysdeps/x86/cpu-features.h}. +@@ -331,8 +331,8 @@ the ones in @code{sysdeps/x86/cpu-features.h}. + This tunable is specific to i386 and x86-64. + @end deftp + +-@deftp Tunable glibc.tune.cached_memopt +-The @code{glibc.tune.cached_memopt=[0|1]} tunable allows the user to ++@deftp Tunable glibc.cpu.cached_memopt ++The @code{glibc.cpu.cached_memopt=[0|1]} tunable allows the user to + enable optimizations recommended for cacheable memory. If set to + @code{1}, @theglibc{} assumes that the process memory image consists + of cacheable (non-device) memory only. The default, @code{0}, +@@ -341,8 +341,8 @@ indicates that the process may use device memory. + This tunable is specific to powerpc, powerpc64 and powerpc64le. + @end deftp + +-@deftp Tunable glibc.tune.cpu +-The @code{glibc.tune.cpu=xxx} tunable allows the user to tell @theglibc{} to ++@deftp Tunable glibc.cpu.name ++The @code{glibc.cpu.name=xxx} tunable allows the user to tell @theglibc{} to + assume that the CPU is @code{xxx} where xxx may have one of these values: + @code{generic}, @code{falkor}, @code{thunderxt88}, @code{thunderx2t99}, + @code{thunderx2t99p1}. +@@ -350,20 +350,20 @@ assume that the CPU is @code{xxx} where xxx may have one of these values: + This tunable is specific to aarch64. + @end deftp + +-@deftp Tunable glibc.tune.x86_data_cache_size +-The @code{glibc.tune.x86_data_cache_size} tunable allows the user to set ++@deftp Tunable glibc.cpu.x86_data_cache_size ++The @code{glibc.cpu.x86_data_cache_size} tunable allows the user to set + data cache size in bytes for use in memory and string routines. + + This tunable is specific to i386 and x86-64. + @end deftp + +-@deftp Tunable glibc.tune.x86_shared_cache_size +-The @code{glibc.tune.x86_shared_cache_size} tunable allows the user to ++@deftp Tunable glibc.cpu.x86_shared_cache_size ++The @code{glibc.cpu.x86_shared_cache_size} tunable allows the user to + set shared cache size in bytes for use in memory and string routines. + @end deftp + +-@deftp Tunable glibc.tune.x86_non_temporal_threshold +-The @code{glibc.tune.x86_non_temporal_threshold} tunable allows the user ++@deftp Tunable glibc.cpu.x86_non_temporal_threshold ++The @code{glibc.cpu.x86_non_temporal_threshold} tunable allows the user + to set threshold in bytes for non temporal store. Non temporal stores + give a hint to the hardware to move data directly to memory without + displacing other data from the cache. This tunable is used by some +@@ -373,8 +373,8 @@ like memmove and memcpy. + This tunable is specific to i386 and x86-64. + @end deftp + +-@deftp Tunable glibc.tune.x86_ibt +-The @code{glibc.tune.x86_ibt} tunable allows the user to control how ++@deftp Tunable glibc.cpu.x86_ibt ++The @code{glibc.cpu.x86_ibt} tunable allows the user to control how + indirect branch tracking (IBT) should be enabled. Accepted values are + @code{on}, @code{off}, and @code{permissive}. @code{on} always turns + on IBT regardless of whether IBT is enabled in the executable and its +@@ -386,8 +386,8 @@ IBT on non-CET executables and shared libraries. + This tunable is specific to i386 and x86-64. + @end deftp + +-@deftp Tunable glibc.tune.x86_shstk +-The @code{glibc.tune.x86_shstk} tunable allows the user to control how ++@deftp Tunable glibc.cpu.x86_shstk ++The @code{glibc.cpu.x86_shstk} tunable allows the user to control how + the shadow stack (SHSTK) should be enabled. Accepted values are + @code{on}, @code{off}, and @code{permissive}. @code{on} always turns on + SHSTK regardless of whether SHSTK is enabled in the executable and its +diff --git a/sysdeps/aarch64/dl-tunables.list b/sysdeps/aarch64/dl-tunables.list +index f6a88168cc5ec7e6..cfcf940ebd15a9aa 100644 +--- a/sysdeps/aarch64/dl-tunables.list ++++ b/sysdeps/aarch64/dl-tunables.list +@@ -17,8 +17,8 @@ + # . + + glibc { +- tune { +- cpu { ++ cpu { ++ name { + type: STRING + } + } +diff --git a/sysdeps/powerpc/cpu-features.c b/sysdeps/powerpc/cpu-features.c +index 955d4778a69db607..ad809b9815eb68f0 100644 +--- a/sysdeps/powerpc/cpu-features.c ++++ b/sysdeps/powerpc/cpu-features.c +@@ -30,7 +30,7 @@ init_cpu_features (struct cpu_features *cpu_features) + tunables is enable, since for this case user can explicit disable + unaligned optimizations. */ + #if HAVE_TUNABLES +- int32_t cached_memfunc = TUNABLE_GET (glibc, tune, cached_memopt, int32_t, ++ int32_t cached_memfunc = TUNABLE_GET (glibc, cpu, cached_memopt, int32_t, + NULL); + cpu_features->use_cached_memopt = (cached_memfunc > 0); + #else +diff --git a/sysdeps/powerpc/dl-tunables.list b/sysdeps/powerpc/dl-tunables.list +index d26636a16bfcd6d9..b3372555f75f8e38 100644 +--- a/sysdeps/powerpc/dl-tunables.list ++++ b/sysdeps/powerpc/dl-tunables.list +@@ -17,7 +17,7 @@ + # . + + glibc { +- tune { ++ cpu { + cached_memopt { + type: INT_32 + minval: 0 +diff --git a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c +index 39eba0186f55b5de..b4f348509eb1c6b3 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/cpu-features.c ++++ b/sysdeps/unix/sysv/linux/aarch64/cpu-features.c +@@ -57,7 +57,7 @@ init_cpu_features (struct cpu_features *cpu_features) + + #if HAVE_TUNABLES + /* Get the tunable override. */ +- const char *mcpu = TUNABLE_GET (glibc, tune, cpu, const char *, NULL); ++ const char *mcpu = TUNABLE_GET (glibc, cpu, name, const char *, NULL); + if (mcpu != NULL) + midr = get_midr_from_mcpu (mcpu); + #endif +diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile +index d5f821e0831997ac..a936134a577e42a5 100644 +--- a/sysdeps/x86/Makefile ++++ b/sysdeps/x86/Makefile +@@ -84,21 +84,21 @@ LDFLAGS-tst-cet-legacy-mod-6c.so = -Wl,--enable-new-dtags,-z,nodelete + ifneq (no,$(have-tunables)) + $(objpfx)tst-cet-legacy-4a: $(libdl) + $(objpfx)tst-cet-legacy-4a.out: $(objpfx)tst-cet-legacy-mod-4.so +-tst-cet-legacy-4a-ENV = GLIBC_TUNABLES=glibc.tune.x86_shstk=permissive ++tst-cet-legacy-4a-ENV = GLIBC_TUNABLES=glibc.cpu.x86_shstk=permissive + $(objpfx)tst-cet-legacy-4b: $(libdl) + $(objpfx)tst-cet-legacy-4b.out: $(objpfx)tst-cet-legacy-mod-4.so +-tst-cet-legacy-4b-ENV = GLIBC_TUNABLES=glibc.tune.x86_shstk=on ++tst-cet-legacy-4b-ENV = GLIBC_TUNABLES=glibc.cpu.x86_shstk=on + $(objpfx)tst-cet-legacy-4c: $(libdl) + $(objpfx)tst-cet-legacy-4c.out: $(objpfx)tst-cet-legacy-mod-4.so +-tst-cet-legacy-4c-ENV = GLIBC_TUNABLES=glibc.tune.x86_shstk=off ++tst-cet-legacy-4c-ENV = GLIBC_TUNABLES=glibc.cpu.x86_shstk=off + $(objpfx)tst-cet-legacy-5b: $(libdl) + $(objpfx)tst-cet-legacy-5b.out: $(objpfx)tst-cet-legacy-mod-5a.so \ + $(objpfx)tst-cet-legacy-mod-5b.so +-tst-cet-legacy-5b-ENV = GLIBC_TUNABLES=glibc.tune.x86_ibt=off:glibc.tune.x86_shstk=off ++tst-cet-legacy-5b-ENV = GLIBC_TUNABLES=glibc.cpu.x86_ibt=off:glibc.cpu.x86_shstk=off + $(objpfx)tst-cet-legacy-6b: $(libdl) + $(objpfx)tst-cet-legacy-6b.out: $(objpfx)tst-cet-legacy-mod-6a.so \ + $(objpfx)tst-cet-legacy-mod-6b.so +-tst-cet-legacy-6b-ENV = GLIBC_TUNABLES=glibc.tune.x86_ibt=off:glibc.tune.x86_shstk=off ++tst-cet-legacy-6b-ENV = GLIBC_TUNABLES=glibc.cpu.x86_ibt=off:glibc.cpu.x86_shstk=off + endif + endif + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 41f2d15fa5c8a756..3b268efbce627e6c 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -22,7 +22,7 @@ + #include + + #if HAVE_TUNABLES +-# define TUNABLE_NAMESPACE tune ++# define TUNABLE_NAMESPACE cpu + # include /* Get STDOUT_FILENO for _dl_printf. */ + # include + +@@ -424,7 +424,7 @@ no_cpuid: + + /* Reuse dl_platform, dl_hwcap and dl_hwcap_mask for x86. */ + #if !HAVE_TUNABLES && defined SHARED +- /* The glibc.tune.hwcap_mask tunable is initialized already, so no need to do ++ /* The glibc.cpu.hwcap_mask tunable is initialized already, so no need to do + this. */ + GLRO(dl_hwcap_mask) = HWCAP_IMPORTANT; + #endif +@@ -499,7 +499,7 @@ no_cpuid: + /* Disable IBT and/or SHSTK if they are enabled by kernel, but + disabled by environment variable: + +- GLIBC_TUNABLES=glibc.tune.hwcaps=-IBT,-SHSTK ++ GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK + */ + unsigned int cet_feature = 0; + if (!HAS_CPU_FEATURE (IBT)) +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index 347a4b118d007fd8..4c6d08c709eea204 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -141,7 +141,7 @@ struct cpu_features + unsigned long int xsave_state_size; + /* The full state size for XSAVE when XSAVEC is disabled by + +- GLIBC_TUNABLES=glibc.tune.hwcaps=-XSAVEC_Usable ++ GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable + */ + unsigned int xsave_state_full_size; + unsigned int feature[FEATURE_INDEX_MAX]; +diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c +index fad6726882fa7e2d..2e5d37753713e975 100644 +--- a/sysdeps/x86/cpu-tunables.c ++++ b/sysdeps/x86/cpu-tunables.c +@@ -17,7 +17,7 @@ + . */ + + #if HAVE_TUNABLES +-# define TUNABLE_NAMESPACE tune ++# define TUNABLE_NAMESPACE cpu + # include + # include + # include /* Get STDOUT_FILENO for _dl_printf. */ +@@ -116,7 +116,7 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp) + the hardware which wasn't available when the selection was made. + The environment variable: + +- GLIBC_TUNABLES=glibc.tune.hwcaps=-xxx,yyy,-zzz,.... ++ GLIBC_TUNABLES=glibc.cpu.hwcaps=-xxx,yyy,-zzz,.... + + can be used to enable CPU/ARCH feature yyy, disable CPU/ARCH feature + yyy and zzz, where the feature name is case-sensitive and has to +diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c +index ebc0d577e414c807..d481bddc27e5d7cc 100644 +--- a/sysdeps/x86/dl-cet.c ++++ b/sysdeps/x86/dl-cet.c +@@ -72,7 +72,7 @@ dl_cet_check (struct link_map *m, const char *program) + /* Enable IBT and SHSTK only if they are enabled in executable. + NB: IBT and SHSTK may be disabled by environment variable: + +- GLIBC_TUNABLES=glibc.tune.hwcaps=-IBT,-SHSTK ++ GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK + */ + enable_ibt &= (HAS_CPU_FEATURE (IBT) + && (enable_ibt_type == cet_always_on +diff --git a/sysdeps/x86/dl-tunables.list b/sysdeps/x86/dl-tunables.list +index 73886b1352316854..2a457d0eec9c3122 100644 +--- a/sysdeps/x86/dl-tunables.list ++++ b/sysdeps/x86/dl-tunables.list +@@ -17,7 +17,7 @@ + # . + + glibc { +- tune { ++ cpu { + hwcaps { + type: STRING + } +diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile +index 9f1562f1b25a2df5..d51cf03ac92ebcc2 100644 +--- a/sysdeps/x86_64/Makefile ++++ b/sysdeps/x86_64/Makefile +@@ -57,7 +57,7 @@ modules-names += x86_64/tst-x86_64mod-1 + LDFLAGS-tst-x86_64mod-1.so = -Wl,-soname,tst-x86_64mod-1.so + ifneq (no,$(have-tunables)) + # Test the state size for XSAVE when XSAVEC is disabled. +-tst-x86_64-1-ENV = GLIBC_TUNABLES=glibc.tune.hwcaps=-XSAVEC_Usable ++tst-x86_64-1-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable + endif + + $(objpfx)tst-x86_64-1: $(objpfx)x86_64/tst-x86_64mod-1.so +@@ -74,7 +74,7 @@ $(objpfx)tst-platform-1.out: $(objpfx)x86_64/tst-platformmod-2.so + # Turn off AVX512F_Usable and AVX2_Usable so that GLRO(dl_platform) is + # always set to x86_64. + tst-platform-1-ENV = LD_PRELOAD=$(objpfx)\$$PLATFORM/tst-platformmod-2.so \ +- GLIBC_TUNABLES=glibc.tune.hwcaps=-AVX512F_Usable,-AVX2_Usable ++ GLIBC_TUNABLES=glibc.cpu.hwcaps=-AVX512F_Usable,-AVX2_Usable + endif + + tests += tst-audit3 tst-audit4 tst-audit5 tst-audit6 tst-audit7 \ diff --git a/glibc-rh1817513-20.patch b/glibc-rh1817513-20.patch new file mode 100755 index 0000000..f111f46 --- /dev/null +++ b/glibc-rh1817513-20.patch @@ -0,0 +1,179 @@ +commit b3fbfe81961a1d14d7b54d1c9757e1f487073bcb +Author: Adhemerval Zanella +Date: Tue Feb 12 13:51:43 2019 +0100 + + elf: Test for LD_AUDIT module returning zero from la_version [BZ #24122] + + This includes the original test case from commit + 8e889c5da3c5981c5a46a93fec02de40131ac5a6 ("elf: Fix LD_AUDIT for + modules with invalid version (BZ#24122)). + +Conflicts: + elf/Makefile + (Different backport order of tests.) + +diff --git a/elf/Makefile b/elf/Makefile +index 6d1962b2e4deb871..4e1356b9172aee02 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -191,6 +191,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + 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-audit13 \ + tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail \ + tst-dlopenfail tst-dlopenfail-2 \ + tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen +@@ -300,7 +301,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + 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-sonamemove-linkmod1 \ ++ tst-audit13mod1 tst-sonamemove-linkmod1 \ + tst-sonamemove-runmod1 tst-sonamemove-runmod2 \ + tst-initlazyfailmod tst-finilazyfailmod \ + tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \ +@@ -1428,6 +1429,10 @@ tst-audit12-ENV = LD_AUDIT=$(objpfx)tst-auditmod12.so + $(objpfx)tst-audit12mod1.so: $(objpfx)tst-audit12mod2.so + LDFLAGS-tst-audit12mod2.so = -Wl,--version-script=tst-audit12mod2.map + ++$(objpfx)tst-audit13.out: $(objpfx)tst-audit13mod1.so ++LDFLAGS-tst-audit13mod1.so = -Wl,-z,lazy ++tst-audit13-ENV = LD_AUDIT=$(objpfx)tst-audit13mod1.so ++ + # tst-sonamemove links against an older implementation of the library. + LDFLAGS-tst-sonamemove-linkmod1.so = \ + -Wl,--version-script=tst-sonamemove-linkmod1.map \ +diff --git a/elf/tst-audit13.c b/elf/tst-audit13.c +new file mode 100644 +index 0000000000000000..6f587baf581ce32c +--- /dev/null ++++ b/elf/tst-audit13.c +@@ -0,0 +1,28 @@ ++/* Check for invalid audit version (BZ#24122). ++ 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 ++ . */ ++ ++#include ++ ++static int ++do_test (void) ++{ ++ puts ("plt call"); ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-audit13mod1.c b/elf/tst-audit13mod1.c +new file mode 100644 +index 0000000000000000..cf017e235c7ae030 +--- /dev/null ++++ b/elf/tst-audit13mod1.c +@@ -0,0 +1,93 @@ ++/* Check for invalid audit version (BZ#24122). ++ 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 ++ . */ ++ ++#include ++#include ++ ++unsigned int ++la_version (unsigned int version) ++{ ++ /* The audit specification says that a version of 0 or a version ++ greater than any version supported by the dynamic loader shall ++ cause the module to be ignored. */ ++ return 0; ++} ++ ++void ++la_activity (uintptr_t *cookie, unsigned int flag) ++{ ++ exit (EXIT_FAILURE); ++} ++ ++char * ++la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) ++{ ++ exit (EXIT_FAILURE); ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t * cookie) ++{ ++ exit (EXIT_FAILURE); ++} ++ ++void ++la_preinit (uintptr_t * cookie) ++{ ++ exit (EXIT_FAILURE); ++} ++ ++uintptr_t ++#if __ELF_NATIVE_CLASS == 32 ++la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook, ++ uintptr_t *defcook, unsigned int *flags, const char *symname) ++#else ++la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, ++ uintptr_t *defcook, unsigned int *flags, const char *symname) ++#endif ++{ ++ exit (EXIT_FAILURE); ++} ++ ++unsigned int ++la_objclose (uintptr_t * cookie) ++{ ++ exit (EXIT_FAILURE); ++} ++ ++#include ++#if (!defined (pltenter) || !defined (pltexit) || !defined (La_regs) \ ++ || !defined (La_retval) || !defined (int_retval)) ++# error "architecture specific code needed in sysdeps/CPU/tst-audit.h" ++#endif ++ ++ElfW(Addr) ++pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, ++ uintptr_t *defcook, La_regs *regs, unsigned int *flags, ++ const char *symname, long int *framesizep) ++{ ++ exit (EXIT_FAILURE); ++} ++ ++unsigned int ++pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, ++ uintptr_t *defcook, const La_regs *inregs, La_retval *outregs, ++ const char *symname) ++{ ++ exit (EXIT_FAILURE); ++} diff --git a/glibc-rh1817513-21.patch b/glibc-rh1817513-21.patch new file mode 100755 index 0000000..c7550dc --- /dev/null +++ b/glibc-rh1817513-21.patch @@ -0,0 +1,29 @@ +commit 86140c6223b5d14d773cf3050ffd0d14977c2c2d +Author: Joseph Myers +Date: Wed Feb 13 13:34:24 2019 +0000 + + Avoid fall-through in test-container if execlp fails. + + One of the implicit-fallthrough warnings from compiling glibc with + -Wextra appears to indicate an actual bug: the test-container code + could fall through inappropriately if execlp returns (which only + occurs on error). This patch adds appropriate error handling in this + case to avoid that fall-through. + + Tested for x86_64. + + * support/test-container.c (recursive_remove): Use FAIL_EXIT1 if + execlp returns. + +diff --git a/support/test-container.c b/support/test-container.c +index 1d1aebeaf3412573..f0d9e3060e80bda5 100644 +--- a/support/test-container.c ++++ b/support/test-container.c +@@ -361,6 +361,7 @@ recursive_remove (char *path) + case 0: + /* Child. */ + execlp ("rm", "rm", "-rf", path, NULL); ++ FAIL_EXIT1 ("exec rm: %m"); + default: + /* Parent. */ + waitpid (child, &status, 0); diff --git a/glibc-rh1817513-22.patch b/glibc-rh1817513-22.patch new file mode 100755 index 0000000..f7b0320 --- /dev/null +++ b/glibc-rh1817513-22.patch @@ -0,0 +1,223 @@ +commit 77b6f5534778b5403c87fa5415625aeb4c3cbf44 +Author: Adhemerval Zanella +Date: Wed Jan 16 17:30:07 2019 +0000 + + linux: Assume clock_getres CLOCK_{PROCESS,THREAD}_CPUTIME_ID + + The Linux 3.2 clock_getres kernel code (kernel/posix-cpu-timers.c) + issued for clock_getres CLOCK_PROCESS_CPUTIME_ID (process_cpu_clock_getres) + and CLOCK_THREAD_CPUTIME_ID (thread_cpu_clock_getres) call + posix_cpu_clock_getres. And it fails on check_clock only if an invalid + clock is used (not the case) or if we pass an invalid the pid/tid in + 29 msb of clock_id (not the case either). + + This patch assumes that clock_getres syscall always support + CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID, so there is no need + to fallback to hp-timing support for _SC_MONOTONIC_CLOCK neither to issue + the syscall to certify the clock_id is supported bt the kernel. This + allows simplify the sysconf support to always use the syscall. + + it also removes ia64 itc drift check and assume kernel handles it correctly. + + Checked on aarch64-linux-gnu, x86_64-linux-gnu, and i686-linux-gnu. + + * sysdeps/unix/sysv/linux/ia64/has_cpuclock.c: Remove file. + * sysdeps/unix/sysv/linux/ia64/sysconf.c: Likewise. + * sysdeps/unix/sysv/linux/sysconf.c (has_cpuclock): Remove function. + (__sysconf): Assume kernel support for _SC_MONOTONIC_CLOCK, + _SC_CPUTIME, and _SC_THREAD_CPUTIME. + +Conflicts: + sysdeps/unix/sysv/linux/ia64/has_cpuclock.c + sysdeps/unix/sysv/linux/ia64/sysconf.c + (Removal after copyright year update.) + +diff --git a/sysdeps/unix/sysv/linux/ia64/has_cpuclock.c b/sysdeps/unix/sysv/linux/ia64/has_cpuclock.c +deleted file mode 100644 +index 75f3ef9f4d1366fb..0000000000000000 +--- a/sysdeps/unix/sysv/linux/ia64/has_cpuclock.c ++++ /dev/null +@@ -1,51 +0,0 @@ +-/* Copyright (C) 2000-2018 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 +- . */ +- +-#include +-#include +-#include +-#include +-#include +-#include +- +-static int itc_usable; +- +-static int +-has_cpuclock (void) +-{ +- if (__builtin_expect (itc_usable == 0, 0)) +- { +- int newval = 1; +- int fd = __open_nocancel ("/proc/sal/itc_drift", O_RDONLY); +- if (__builtin_expect (fd != -1, 1)) +- { +- char buf[16]; +- /* We expect the file to contain a single digit followed by +- a newline. If the format changes we better not rely on +- the file content. */ +- if (__read_nocancel (fd, buf, sizeof buf) != 2 +- || buf[0] != '0' || buf[1] != '\n') +- newval = -1; +- +- __close_nocancel_nostatus (fd); +- } +- +- itc_usable = newval; +- } +- +- return itc_usable; +-} +diff --git a/sysdeps/unix/sysv/linux/ia64/sysconf.c b/sysdeps/unix/sysv/linux/ia64/sysconf.c +deleted file mode 100644 +index 6c39db5a4af3e15a..0000000000000000 +--- a/sysdeps/unix/sysv/linux/ia64/sysconf.c ++++ /dev/null +@@ -1,30 +0,0 @@ +-/* Get file-specific information about a file. Linux/ia64 version. +- Copyright (C) 2003-2018 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 +- . */ +- +-#include +-#include +-#include +-#include +- +- +-#include "has_cpuclock.c" +-#define HAS_CPUCLOCK(name) (has_cpuclock () ? _POSIX_VERSION : -1) +- +- +-/* Now the generic Linux version. */ +-#include +diff --git a/sysdeps/unix/sysv/linux/sysconf.c b/sysdeps/unix/sysv/linux/sysconf.c +index 4e49ebaa7a25748c..6fab1601034e4724 100644 +--- a/sysdeps/unix/sysv/linux/sysconf.c ++++ b/sysdeps/unix/sysv/linux/sysconf.c +@@ -35,34 +35,6 @@ + static long int posix_sysconf (int name); + + +-#ifndef HAS_CPUCLOCK +-static long int +-has_cpuclock (int name) +-{ +-# if defined __NR_clock_getres || HP_TIMING_AVAIL +- /* If we have HP_TIMING, we will fall back on that if the system +- call does not work, so we support it either way. */ +-# if !HP_TIMING_AVAIL +- /* Check using the clock_getres system call. */ +- struct timespec ts; +- INTERNAL_SYSCALL_DECL (err); +- int r = INTERNAL_SYSCALL (clock_getres, err, 2, +- (name == _SC_CPUTIME +- ? CLOCK_PROCESS_CPUTIME_ID +- : CLOCK_THREAD_CPUTIME_ID), +- &ts); +- if (INTERNAL_SYSCALL_ERROR_P (r, err)) +- return -1; +-# endif +- return _POSIX_VERSION; +-# else +- return -1; +-# endif +-} +-# define HAS_CPUCLOCK(name) has_cpuclock (name) +-#endif +- +- + /* Get the value of the system variable NAME. */ + long int + __sysconf (int name) +@@ -71,29 +43,20 @@ __sysconf (int name) + + switch (name) + { +- struct rlimit rlimit; +-#ifdef __NR_clock_getres + case _SC_MONOTONIC_CLOCK: +- /* Check using the clock_getres system call. */ +- { +- struct timespec ts; +- INTERNAL_SYSCALL_DECL (err); +- int r; +- r = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts); +- return INTERNAL_SYSCALL_ERROR_P (r, err) ? -1 : _POSIX_VERSION; +- } +-#endif +- + case _SC_CPUTIME: + case _SC_THREAD_CPUTIME: +- return HAS_CPUCLOCK (name); ++ return _POSIX_VERSION; + + case _SC_ARG_MAX: +- /* Use getrlimit to get the stack limit. */ +- if (__getrlimit (RLIMIT_STACK, &rlimit) == 0) +- return MAX (legacy_ARG_MAX, rlimit.rlim_cur / 4); ++ { ++ struct rlimit rlimit; ++ /* Use getrlimit to get the stack limit. */ ++ if (__getrlimit (RLIMIT_STACK, &rlimit) == 0) ++ return MAX (legacy_ARG_MAX, rlimit.rlim_cur / 4); + +- return legacy_ARG_MAX; ++ return legacy_ARG_MAX; ++ } + + case _SC_NGROUPS_MAX: + /* Try to read the information from the /proc/sys/kernel/ngroups_max +@@ -102,11 +65,14 @@ __sysconf (int name) + break; + + case _SC_SIGQUEUE_MAX: +- if (__getrlimit (RLIMIT_SIGPENDING, &rlimit) == 0) +- return rlimit.rlim_cur; ++ { ++ struct rlimit rlimit; ++ if (__getrlimit (RLIMIT_SIGPENDING, &rlimit) == 0) ++ return rlimit.rlim_cur; + +- /* The /proc/sys/kernel/rtsig-max file contains the answer. */ +- procfname = "/proc/sys/kernel/rtsig-max"; ++ /* The /proc/sys/kernel/rtsig-max file contains the answer. */ ++ procfname = "/proc/sys/kernel/rtsig-max"; ++ } + break; + + default: diff --git a/glibc-rh1817513-23.patch b/glibc-rh1817513-23.patch new file mode 100755 index 0000000..91ccdfa --- /dev/null +++ b/glibc-rh1817513-23.patch @@ -0,0 +1,211 @@ +commit 359653aaacad463d916323f03c0ac3c47405aafa +Author: Adhemerval Zanella +Date: Wed Jan 16 18:10:56 2019 +0000 + + Do not use HP_TIMING_NOW for random bits + + This patch removes the HP_TIMING_BITS usage for fast random bits and replace + with clock_gettime (CLOCK_MONOTONIC). It has unspecified starting time and + nano-second accuracy, so its randomness is significantly better than + gettimeofday. + + Althoug it should incur in more overhead (specially for architecture that + support hp-timing), the symbol is also common implemented as a vDSO. + + Checked on aarch64-linux-gnu, x86_64-linux-gnu, and i686-linux-gnu. I also + checked on a i686-gnu build. + + * include/random-bits.h: New file. + * resolv/res_mkquery.c [HP_TIMING_AVAIL] (RANDOM_BITS, + (__res_context_mkquery): Remove usage hp-timing usage and replace with + random_bits. + * resolv/res_send.c [HP_TIMING_AVAIL] (nameserver_offset): Likewise. + * sysdeps/posix/tempname.c [HP_TIMING_AVAIL] (__gen_tempname): + Likewise. + +diff --git a/include/random-bits.h b/include/random-bits.h +new file mode 100644 +index 0000000000000000..a0651a5a34f80a8d +--- /dev/null ++++ b/include/random-bits.h +@@ -0,0 +1,41 @@ ++/* Fast pseudo-random bits based on clock_gettime. ++ 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 ++ . */ ++ ++#ifndef _RANDOM_BITS_H ++# define _RANDOM_BITS_H ++ ++#include ++#include ++ ++/* Provides fast pseudo-random bits through clock_gettime. It has unspecified ++ starting time, nano-second accuracy, its randomness is significantly better ++ than gettimeofday, and for mostly architectures it is implemented through ++ vDSO instead of a syscall. Since the source is a system clock, the upper ++ bits will have less entropy. */ ++static inline uint32_t ++random_bits (void) ++{ ++ struct timespec tv; ++ __clock_gettime (CLOCK_MONOTONIC, &tv); ++ /* Shuffle the lower bits to minimize the clock bias. */ ++ uint32_t ret = tv.tv_nsec ^ tv.tv_sec; ++ ret ^= (ret << 24) | (ret >> 8); ++ return ret; ++} ++ ++#endif +diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c +index 213abeefadf7ece5..4471a8838b1de7ee 100644 +--- a/resolv/res_mkquery.c ++++ b/resolv/res_mkquery.c +@@ -82,6 +82,7 @@ + * SOFTWARE. + */ + ++#include + #include + #include + #include +@@ -92,12 +93,7 @@ + #include + #include + #include +- +-#include +-#include +-#if HP_TIMING_AVAIL +-# define RANDOM_BITS(Var) { uint64_t v64; HP_TIMING_NOW (v64); Var = v64; } +-#endif ++#include + + int + __res_context_mkquery (struct resolv_context *ctx, int op, const char *dname, +@@ -120,16 +116,7 @@ __res_context_mkquery (struct resolv_context *ctx, int op, const char *dname, + /* We randomize the IDs every time. The old code just incremented + by one after the initial randomization which still predictable if + the application does multiple requests. */ +- int randombits; +-#ifdef RANDOM_BITS +- RANDOM_BITS (randombits); +-#else +- struct timeval tv; +- __gettimeofday (&tv, NULL); +- randombits = (tv.tv_sec << 8) ^ tv.tv_usec; +-#endif +- +- hp->id = randombits; ++ hp->id = random_bits (); + hp->opcode = op; + hp->rd = (ctx->resp->options & RES_RECURSE) != 0; + hp->rcode = NOERROR; +diff --git a/resolv/res_send.c b/resolv/res_send.c +index ac19627634281c2f..55e7fa438e7baac1 100644 +--- a/resolv/res_send.c ++++ b/resolv/res_send.c +@@ -109,7 +109,7 @@ + #include + #include + #include +-#include ++#include + + #if PACKETSZ > 65536 + #define MAXPACKET PACKETSZ +@@ -309,15 +309,7 @@ nameserver_offset (struct __res_state *statp) + if ((offset & 1) == 0) + { + /* Initialization is required. */ +-#if HP_TIMING_AVAIL +- uint64_t ticks; +- HP_TIMING_NOW (ticks); +- offset = ticks; +-#else +- struct timeval tv; +- __gettimeofday (&tv, NULL); +- offset = ((tv.tv_sec << 8) ^ tv.tv_usec); +-#endif ++ offset = random_bits (); + /* The lowest bit is the most random. Preserve it. */ + offset <<= 1; + +diff --git a/sysdeps/posix/tempname.c b/sysdeps/posix/tempname.c +index 432262a03b6ecc23..3d26f378021680ae 100644 +--- a/sysdeps/posix/tempname.c ++++ b/sysdeps/posix/tempname.c +@@ -71,22 +71,15 @@ + #endif + + #ifdef _LIBC +-# include +-# if HP_TIMING_AVAIL +-# define RANDOM_BITS(Var) \ +- if (__glibc_unlikely (value == UINT64_C (0))) \ +- { \ +- /* If this is the first time this function is used initialize \ +- the variable we accumulate the value in to some somewhat \ +- random value. If we'd not do this programs at startup time \ +- might have a reduced set of possible names, at least on slow \ +- machines. */ \ +- struct timeval tv; \ +- __gettimeofday (&tv, NULL); \ +- value = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ +- } \ +- HP_TIMING_NOW (Var) +-# endif ++# include ++# define RANDOM_BITS(Var) ((Var) = random_bits ()) ++# else ++# define RANDOM_BITS(Var) \ ++ { \ ++ struct timeval tv; \ ++ __gettimeofday (&tv, NULL); \ ++ (Var) = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; \ ++ } + #endif + + /* Use the widest available unsigned type if uint64_t is not +@@ -193,8 +186,7 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind) + { + int len; + char *XXXXXX; +- static uint64_t value; +- uint64_t random_time_bits; ++ uint64_t value; + unsigned int count; + int fd = -1; + int save_errno = errno; +@@ -227,16 +219,8 @@ __gen_tempname (char *tmpl, int suffixlen, int flags, int kind) + XXXXXX = &tmpl[len - 6 - suffixlen]; + + /* Get some more or less random data. */ +-#ifdef RANDOM_BITS +- RANDOM_BITS (random_time_bits); +-#else +- { +- struct timeval tv; +- __gettimeofday (&tv, NULL); +- random_time_bits = ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec; +- } +-#endif +- value += random_time_bits ^ __getpid (); ++ RANDOM_BITS (value); ++ value ^= (uint64_t)__getpid () << 32; + + for (count = 0; count < attempts; value += 7777, ++count) + { diff --git a/glibc-rh1817513-24.patch b/glibc-rh1817513-24.patch new file mode 100755 index 0000000..3347d97 --- /dev/null +++ b/glibc-rh1817513-24.patch @@ -0,0 +1,702 @@ +commit 1e372ded4f83362509c8672ff501cba871bb1edc +Author: Adhemerval Zanella +Date: Thu Jan 24 12:46:59 2019 +0000 + + Refactor hp-timing rtld usage + + This patch refactor how hp-timing is used on loader code for statistics + report. The HP_TIMING_AVAIL and HP_SMALL_TIMING_AVAIL are removed and + HP_TIMING_INLINE is used instead to check for hp-timing avaliability. + For alpha, which only defines HP_SMALL_TIMING_AVAIL, the HP_TIMING_INLINE + is set iff for IS_IN(rtld). + + Checked on aarch64-linux-gnu, x86_64-linux-gnu, and i686-linux-gnu. I also + checked the builds for all afected ABIs. + + * benchtests/bench-timing.h: Replace HP_TIMING_AVAIL with + HP_TIMING_INLINE. + * nptl/descr.h: Likewise. + * elf/rtld.c (RLTD_TIMING_DECLARE, RTLD_TIMING_NOW, RTLD_TIMING_DIFF, + RTLD_TIMING_ACCUM_NT, RTLD_TIMING_SET): Define. + (dl_start_final_info, _dl_start_final, dl_main, print_statistics): + Abstract hp-timing usage with RTLD_* macros. + * sysdeps/alpha/hp-timing.h (HP_TIMING_INLINE): Define iff IS_IN(rtld). + (HP_TIMING_AVAIL, HP_SMALL_TIMING_AVAIL): Remove. + * sysdeps/generic/hp-timing.h (HP_TIMING_AVAIL, HP_SMALL_TIMING_AVAIL, + HP_TIMING_NONAVAIL): Likewise. + * sysdeps/ia64/hp-timing.h (HP_TIMING_AVAIL, HP_SMALL_TIMING_AVAIL): + Likewise. + * sysdeps/powerpc/powerpc32/power4/hp-timing.h (HP_TIMING_AVAIL, + HP_SMALL_TIMING_AVAIL): Likewise. + * sysdeps/powerpc/powerpc64/hp-timing.h (HP_TIMING_AVAIL, + HP_SMALL_TIMING_AVAIL): Likewise. + * sysdeps/sparc/sparc32/sparcv9/hp-timing.h (HP_TIMING_AVAIL, + HP_SMALL_TIMING_AVAIL): Likewise. + * sysdeps/sparc/sparc64/hp-timing.h (HP_TIMING_AVAIL, + HP_SMALL_TIMING_AVAIL): Likewise. + * sysdeps/x86/hp-timing.h (HP_TIMING_AVAIL, HP_SMALL_TIMING_AVAIL): + Likewise. + * sysdeps/generic/hp-timing-common.h: Update comment with + HP_TIMING_AVAIL removal. + +diff --git a/benchtests/bench-timing.h b/benchtests/bench-timing.h +index 96cde1e8be2e0c2f..8ba6be51d5b6d4e1 100644 +--- a/benchtests/bench-timing.h ++++ b/benchtests/bench-timing.h +@@ -21,7 +21,7 @@ + #include + #include + +-#if HP_TIMING_AVAIL && !defined USE_CLOCK_GETTIME ++#if HP_TIMING_INLINE && !defined USE_CLOCK_GETTIME + # define GL(x) _##x + # define GLRO(x) _##x + typedef hp_timing_t timing_t; +diff --git a/elf/rtld.c b/elf/rtld.c +index 375e0de8fa2e049e..ffbd8f4553bb3425 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -46,6 +46,49 @@ + + #include + ++/* Only enables rtld profiling for architectures which provides non generic ++ hp-timing support. The generic support requires either syscall ++ (clock_gettime), which will incur in extra overhead on loading time. ++ Using vDSO is also an option, but it will require extra support on loader ++ to setup the vDSO pointer before its usage. */ ++#if HP_TIMING_INLINE ++# define RLTD_TIMING_DECLARE(var, classifier,...) \ ++ classifier hp_timing_t var __VA_ARGS__ ++# define RTLD_TIMING_VAR(var) RLTD_TIMING_DECLARE (var, ) ++# define RTLD_TIMING_SET(var, value) (var) = (value) ++# define RTLD_TIMING_REF(var) &(var) ++ ++static inline void ++rtld_timer_start (hp_timing_t *var) ++{ ++ HP_TIMING_NOW (*var); ++} ++ ++static inline void ++rtld_timer_stop (hp_timing_t *var, hp_timing_t start) ++{ ++ hp_timing_t stop; ++ HP_TIMING_NOW (stop); ++ HP_TIMING_DIFF (*var, start, stop); ++} ++ ++static inline void ++rtld_timer_accum (hp_timing_t *sum, hp_timing_t start) ++{ ++ hp_timing_t stop; ++ rtld_timer_stop (&stop, start); ++ HP_TIMING_ACCUM_NT(*sum, stop); ++} ++#else ++# define RLTD_TIMING_DECLARE(var, classifier...) ++# define RTLD_TIMING_SET(var, value) ++# define RTLD_TIMING_VAR(var) ++# define RTLD_TIMING_REF(var) 0 ++# define rtld_timer_start(var) ++# define rtld_timer_stop(var, start) ++# define rtld_timer_accum(sum, start) ++#endif ++ + /* Avoid PLT use for our local calls at startup. */ + extern __typeof (__mempcpy) __mempcpy attribute_hidden; + +@@ -62,7 +105,7 @@ static void print_missing_version (int errcode, const char *objname, + const char *errsting); + + /* Print the various times we collected. */ +-static void print_statistics (hp_timing_t *total_timep); ++static void print_statistics (const hp_timing_t *total_timep); + + /* Add audit objects. */ + static void process_dl_audit (char *str); +@@ -303,11 +346,9 @@ static struct libname_list _dl_rtld_libname; + static struct libname_list _dl_rtld_libname2; + + /* Variable for statistics. */ +-#ifndef HP_TIMING_NONAVAIL +-static hp_timing_t relocate_time; +-static hp_timing_t load_time attribute_relro; +-static hp_timing_t start_time attribute_relro; +-#endif ++RLTD_TIMING_DECLARE (relocate_time, static); ++RLTD_TIMING_DECLARE (load_time, static, attribute_relro); ++RLTD_TIMING_DECLARE (start_time, static, attribute_relro); + + /* Additional definitions needed by TLS initialization. */ + #ifdef TLS_INIT_HELPER +@@ -335,9 +376,7 @@ static ElfW(Addr) _dl_start_final (void *arg); + struct dl_start_final_info + { + struct link_map l; +-#if !defined HP_TIMING_NONAVAIL && HP_TIMING_INLINE +- hp_timing_t start_time; +-#endif ++ RTLD_TIMING_VAR (start_time); + }; + static ElfW(Addr) _dl_start_final (void *arg, + struct dl_start_final_info *info); +@@ -371,16 +410,11 @@ _dl_start_final (void *arg, struct dl_start_final_info *info) + { + ElfW(Addr) start_addr; + +- if (HP_SMALL_TIMING_AVAIL) +- { +- /* If it hasn't happen yet record the startup time. */ +- if (! HP_TIMING_INLINE) +- HP_TIMING_NOW (start_time); +-#if !defined DONT_USE_BOOTSTRAP_MAP && !defined HP_TIMING_NONAVAIL +- else +- start_time = info->start_time; ++ /* If it hasn't happen yet record the startup time. */ ++ rtld_timer_start (&start_time); ++#if !defined DONT_USE_BOOTSTRAP_MAP ++ RTLD_TIMING_SET (start_time, info->start_time); + #endif +- } + + /* Transfer data about ourselves to the permanent link_map structure. */ + #ifndef DONT_USE_BOOTSTRAP_MAP +@@ -412,27 +446,11 @@ _dl_start_final (void *arg, struct dl_start_final_info *info) + entry point on the same stack we entered on. */ + start_addr = _dl_sysdep_start (arg, &dl_main); + +-#ifndef HP_TIMING_NONAVAIL +- hp_timing_t rtld_total_time; +- if (HP_SMALL_TIMING_AVAIL) +- { +- hp_timing_t end_time; +- +- /* Get the current time. */ +- HP_TIMING_NOW (end_time); +- +- /* Compute the difference. */ +- HP_TIMING_DIFF (rtld_total_time, start_time, end_time); +- } +-#endif +- + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS)) + { +-#ifndef HP_TIMING_NONAVAIL +- print_statistics (&rtld_total_time); +-#else +- print_statistics (NULL); +-#endif ++ RTLD_TIMING_VAR (rtld_total_time); ++ rtld_timer_stop (&rtld_total_time, start_time); ++ print_statistics (RTLD_TIMING_REF(rtld_total_time)); + } + + return start_addr; +@@ -457,11 +475,10 @@ _dl_start (void *arg) + #define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP + #include "dynamic-link.h" + +- if (HP_TIMING_INLINE && HP_SMALL_TIMING_AVAIL) + #ifdef DONT_USE_BOOTSTRAP_MAP +- HP_TIMING_NOW (start_time); ++ rtld_timer_start (&start_time); + #else +- HP_TIMING_NOW (info.start_time); ++ rtld_timer_start (&info.start_time); + #endif + + /* Partly clean the `bootstrap_map' structure up. Don't use +@@ -1078,11 +1095,6 @@ dl_main (const ElfW(Phdr) *phdr, + unsigned int i; + bool prelinked = false; + bool rtld_is_main = false; +-#ifndef HP_TIMING_NONAVAIL +- hp_timing_t start; +- hp_timing_t stop; +- hp_timing_t diff; +-#endif + void *tcbp = NULL; + + GL(dl_init_static_tls) = &_dl_nothread_init_static_tls; +@@ -1256,12 +1268,11 @@ of this helper program; chances are you did not intend to run this program.\n\ + } + else + { +- HP_TIMING_NOW (start); ++ RTLD_TIMING_VAR (start); ++ rtld_timer_start (&start); + _dl_map_object (NULL, rtld_progname, lt_executable, 0, + __RTLD_OPENEXEC, LM_ID_BASE); +- HP_TIMING_NOW (stop); +- +- HP_TIMING_DIFF (load_time, start, stop); ++ rtld_timer_stop (&load_time, start); + } + + /* Now the map for the main executable is available. */ +@@ -1664,20 +1675,18 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + + if (__glibc_unlikely (preloadlist != NULL)) + { +- HP_TIMING_NOW (start); ++ RTLD_TIMING_VAR (start); ++ rtld_timer_start (&start); + npreloads += handle_preload_list (preloadlist, main_map, "LD_PRELOAD"); +- HP_TIMING_NOW (stop); +- HP_TIMING_DIFF (diff, start, stop); +- HP_TIMING_ACCUM_NT (load_time, diff); ++ rtld_timer_accum (&load_time, start); + } + + if (__glibc_unlikely (preloadarg != NULL)) + { +- HP_TIMING_NOW (start); ++ RTLD_TIMING_VAR (start); ++ rtld_timer_start (&start); + npreloads += handle_preload_list (preloadarg, main_map, "--preload"); +- HP_TIMING_NOW (stop); +- HP_TIMING_DIFF (diff, start, stop); +- HP_TIMING_ACCUM_NT (load_time, diff); ++ rtld_timer_accum (&load_time, start); + } + + /* There usually is no ld.so.preload file, it should only be used +@@ -1737,7 +1746,8 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + file[file_size - 1] = '\0'; + } + +- HP_TIMING_NOW (start); ++ RTLD_TIMING_VAR (start); ++ rtld_timer_start (&start); + + if (file != problem) + { +@@ -1755,9 +1765,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + npreloads += do_preload (p, main_map, preload_file); + } + +- HP_TIMING_NOW (stop); +- HP_TIMING_DIFF (diff, start, stop); +- HP_TIMING_ACCUM_NT (load_time, diff); ++ rtld_timer_accum (&load_time, start); + + /* We don't need the file anymore. */ + __munmap (file, file_size); +@@ -1781,11 +1789,12 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + /* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD + specified some libraries to load, these are inserted before the actual + dependencies in the executable's searchlist for symbol resolution. */ +- HP_TIMING_NOW (start); +- _dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0); +- HP_TIMING_NOW (stop); +- HP_TIMING_DIFF (diff, start, stop); +- HP_TIMING_ACCUM_NT (load_time, diff); ++ { ++ RTLD_TIMING_VAR (start); ++ rtld_timer_start (&start); ++ _dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0); ++ rtld_timer_accum (&load_time, start); ++ } + + /* Mark all objects as being in the global scope. */ + for (i = main_map->l_searchlist.r_nlist; i > 0; ) +@@ -2178,12 +2187,10 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL) + { + ElfW(Rela) *conflict, *conflictend; +-#ifndef HP_TIMING_NONAVAIL +- hp_timing_t start; +- hp_timing_t stop; +-#endif + +- HP_TIMING_NOW (start); ++ RTLD_TIMING_VAR (start); ++ rtld_timer_start (&start); ++ + assert (main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)] != NULL); + conflict = (ElfW(Rela) *) + main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)]->d_un.d_ptr; +@@ -2191,8 +2198,8 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + ((char *) conflict + + main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)]->d_un.d_val); + _dl_resolve_conflicts (main_map, conflict, conflictend); +- HP_TIMING_NOW (stop); +- HP_TIMING_DIFF (relocate_time, start, stop); ++ ++ rtld_timer_stop (&relocate_time, start); + } + + +@@ -2220,15 +2227,12 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + know that because it is self-contained). */ + + int consider_profiling = GLRO(dl_profile) != NULL; +-#ifndef HP_TIMING_NONAVAIL +- hp_timing_t start; +- hp_timing_t stop; +-#endif + + /* If we are profiling we also must do lazy reloaction. */ + GLRO(dl_lazy) |= consider_profiling; + +- HP_TIMING_NOW (start); ++ RTLD_TIMING_VAR (start); ++ rtld_timer_start (&start); + unsigned i = main_map->l_searchlist.r_nlist; + while (i-- > 0) + { +@@ -2255,9 +2259,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + if (l->l_tls_blocksize != 0 && tls_init_tp_called) + _dl_add_to_slotinfo (l, true); + } +- HP_TIMING_NOW (stop); +- +- HP_TIMING_DIFF (relocate_time, start, stop); ++ rtld_timer_stop (&relocate_time, start); + + /* Now enable profiling if needed. Like the previous call, + this has to go here because the calls it makes should use the +@@ -2300,19 +2302,14 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + re-relocation, we might call a user-supplied function + (e.g. calloc from _dl_relocate_object) that uses TLS data. */ + +-#ifndef HP_TIMING_NONAVAIL +- hp_timing_t start; +- hp_timing_t stop; +- hp_timing_t add; +-#endif ++ RTLD_TIMING_VAR (start); ++ rtld_timer_start (&start); + +- HP_TIMING_NOW (start); + /* Mark the link map as not yet relocated again. */ + GL(dl_rtld_map).l_relocated = 0; + _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0); +- HP_TIMING_NOW (stop); +- HP_TIMING_DIFF (add, start, stop); +- HP_TIMING_ACCUM_NT (relocate_time, add); ++ ++ rtld_timer_accum (&relocate_time, start); + } + + /* Do any necessary cleanups for the startup OS interface code. +@@ -2744,46 +2741,51 @@ process_envvars (enum mode *modep) + } + } + ++#if HP_TIMING_INLINE ++static void ++print_statistics_item (const char *title, hp_timing_t time, ++ hp_timing_t total) ++{ ++ char cycles[HP_TIMING_PRINT_SIZE]; ++ HP_TIMING_PRINT (cycles, sizeof (cycles), time); ++ ++ char relative[3 * sizeof (hp_timing_t) + 2]; ++ char *cp = _itoa ((1000ULL * time) / total, relative + sizeof (relative), ++ 10, 0); ++ /* Sets the decimal point. */ ++ char *wp = relative; ++ switch (relative + sizeof (relative) - cp) ++ { ++ case 3: ++ *wp++ = *cp++; ++ /* Fall through. */ ++ case 2: ++ *wp++ = *cp++; ++ /* Fall through. */ ++ case 1: ++ *wp++ = '.'; ++ *wp++ = *cp++; ++ } ++ *wp = '\0'; ++ _dl_debug_printf ("%s: %s cycles (%s%%)\n", title, cycles, relative); ++} ++#endif + + /* Print the various times we collected. */ + static void + __attribute ((noinline)) +-print_statistics (hp_timing_t *rtld_total_timep) ++print_statistics (const hp_timing_t *rtld_total_timep) + { +-#ifndef HP_TIMING_NONAVAIL +- char buf[200]; +- char *cp; +- char *wp; +- +- /* Total time rtld used. */ +- if (HP_SMALL_TIMING_AVAIL) +- { +- HP_TIMING_PRINT (buf, sizeof (buf), *rtld_total_timep); +- _dl_debug_printf ("\nruntime linker statistics:\n" +- " total startup time in dynamic loader: %s\n", buf); +- +- /* Print relocation statistics. */ +- char pbuf[30]; +- HP_TIMING_PRINT (buf, sizeof (buf), relocate_time); +- cp = _itoa ((1000ULL * relocate_time) / *rtld_total_timep, +- pbuf + sizeof (pbuf), 10, 0); +- wp = pbuf; +- switch (pbuf + sizeof (pbuf) - cp) +- { +- case 3: +- *wp++ = *cp++; +- /* Fall through. */ +- case 2: +- *wp++ = *cp++; +- /* Fall through. */ +- case 1: +- *wp++ = '.'; +- *wp++ = *cp++; +- } +- *wp = '\0'; +- _dl_debug_printf ("\ +- time needed for relocation: %s (%s%%)\n", buf, pbuf); +- } ++#if HP_TIMING_INLINE ++ { ++ char cycles[HP_TIMING_PRINT_SIZE]; ++ HP_TIMING_PRINT (cycles, sizeof (cycles), *rtld_total_timep); ++ _dl_debug_printf ("\nruntime linker statistics:\n" ++ " total startup time in dynamic loader: %s cycles\n", ++ cycles); ++ print_statistics_item (" time needed for relocation", ++ relocate_time, *rtld_total_timep); ++ } + #endif + + unsigned long int num_relative_relocations = 0; +@@ -2824,31 +2826,8 @@ print_statistics (hp_timing_t *rtld_total_timep) + GL(dl_num_cache_relocations), + num_relative_relocations); + +-#ifndef HP_TIMING_NONAVAIL +- /* Time spend while loading the object and the dependencies. */ +- if (HP_SMALL_TIMING_AVAIL) +- { +- char pbuf[30]; +- HP_TIMING_PRINT (buf, sizeof (buf), load_time); +- cp = _itoa ((1000ULL * load_time) / *rtld_total_timep, +- pbuf + sizeof (pbuf), 10, 0); +- wp = pbuf; +- switch (pbuf + sizeof (pbuf) - cp) +- { +- case 3: +- *wp++ = *cp++; +- /* Fall through. */ +- case 2: +- *wp++ = *cp++; +- /* Fall through. */ +- case 1: +- *wp++ = '.'; +- *wp++ = *cp++; +- } +- *wp = '\0'; +- _dl_debug_printf ("\ +- time needed to load objects: %s (%s%%)\n", +- buf, pbuf); +- } ++#if HP_TIMING_INLINE ++ print_statistics_item (" time needed to load objects", ++ load_time, *rtld_total_timep); + #endif + } +diff --git a/nptl/descr.h b/nptl/descr.h +index c3b81d8b27839502..98ba730bfeb7e4dd 100644 +--- a/nptl/descr.h ++++ b/nptl/descr.h +@@ -342,7 +342,7 @@ struct pthread + /* Lock for synchronizing setxid calls. */ + unsigned int setxid_futex; + +-#if HP_TIMING_AVAIL ++#if HP_TIMING_INLINE + hp_timing_t cpuclock_offset_ununsed; + #endif + +diff --git a/sysdeps/alpha/hp-timing.h b/sysdeps/alpha/hp-timing.h +index 62284e003acbca64..d6b603e2c51d1688 100644 +--- a/sysdeps/alpha/hp-timing.h ++++ b/sysdeps/alpha/hp-timing.h +@@ -17,16 +17,13 @@ + License along with the GNU C Library. If not, see + . */ + +-#ifndef _HP_TIMING_H +-#define _HP_TIMING_H 1 ++#ifndef _HP_TIMING_ALPHA_H ++#define _HP_TIMING_ALPHA_H 1 + ++#if IS_IN(rtld) + /* We always have the timestamp register, but it's got only a 4 second + range. Use it for ld.so profiling only. */ +-#define HP_TIMING_AVAIL (0) +-#define HP_SMALL_TIMING_AVAIL (1) +- +-/* We indeed have inlined functions. */ +-#define HP_TIMING_INLINE (1) ++# define HP_TIMING_INLINE (1) + + /* We use 32 bit values for the times. */ + typedef unsigned int hp_timing_t; +@@ -34,13 +31,16 @@ typedef unsigned int hp_timing_t; + /* The "rpcc" instruction returns a 32-bit counting half and a 32-bit + "virtual cycle counter displacement". Subtracting the two gives us + a virtual cycle count. */ +-#define HP_TIMING_NOW(VAR) \ ++# define HP_TIMING_NOW(VAR) \ + do { \ + unsigned long int x_; \ + asm volatile ("rpcc %0" : "=r"(x_)); \ + (VAR) = (int) (x_) - (int) (x_ >> 32); \ + } while (0) ++# include + +-#include ++#else ++# include ++#endif /* IS_IN(rtld) */ + + #endif /* hp-timing.h */ +diff --git a/sysdeps/generic/hp-timing-common.h b/sysdeps/generic/hp-timing-common.h +index 505c6bf5d2ee9395..ce338c990bd9fccd 100644 +--- a/sysdeps/generic/hp-timing-common.h ++++ b/sysdeps/generic/hp-timing-common.h +@@ -20,8 +20,6 @@ + /* In case a platform supports timers in the hardware the following macros + and types must be defined: + +- - HP_TIMING_AVAIL: test for availability. +- + - HP_TIMING_INLINE: this macro is non-zero if the functionality is not + implemented using function calls but instead uses some inlined code + which might simply consist of a few assembler instructions. We have to +@@ -47,16 +45,16 @@ + /* Accumulate ADD into SUM. No attempt is made to be thread-safe. */ + #define HP_TIMING_ACCUM_NT(Sum, Diff) ((Sum) += (Diff)) + ++#define HP_TIMING_PRINT_SIZE (3 * sizeof (hp_timing_t) + 1) ++ + /* Write a decimal representation of the timing value into the given string. */ + #define HP_TIMING_PRINT(Dest, Len, Val) \ + do { \ +- char __buf[20]; \ ++ char __buf[HP_TIMING_PRINT_SIZE]; \ + char *__dest = (Dest); \ + size_t __len = (Len); \ + char *__cp = _itoa ((Val), __buf + sizeof (__buf), 10, 0); \ + size_t __cp_len = MIN (__buf + sizeof (__buf) - __cp, __len); \ + memcpy (__dest, __cp, __cp_len); \ +- memcpy (__dest + __cp_len, " cycles", \ +- MIN (__len - __cp_len, sizeof (" cycles"))); \ + __dest[__len - 1] = '\0'; \ + } while (0) +diff --git a/sysdeps/generic/hp-timing.h b/sysdeps/generic/hp-timing.h +index e2c02c2bc0fd1564..97598099db29d69d 100644 +--- a/sysdeps/generic/hp-timing.h ++++ b/sysdeps/generic/hp-timing.h +@@ -25,8 +25,6 @@ + the system call might be too high. */ + + /* Provide dummy definitions. */ +-#define HP_TIMING_AVAIL (0) +-#define HP_SMALL_TIMING_AVAIL (0) + #define HP_TIMING_INLINE (0) + typedef int hp_timing_t; + #define HP_TIMING_NOW(var) +@@ -34,7 +32,4 @@ typedef int hp_timing_t; + #define HP_TIMING_ACCUM_NT(Sum, Diff) + #define HP_TIMING_PRINT(Buf, Len, Val) + +-/* Since this implementation is not available we tell the user about it. */ +-#define HP_TIMING_NONAVAIL 1 +- + #endif /* hp-timing.h */ +diff --git a/sysdeps/ia64/hp-timing.h b/sysdeps/ia64/hp-timing.h +index d8d1d7bf2c21f6e6..5ebbbc45746d5cf2 100644 +--- a/sysdeps/ia64/hp-timing.h ++++ b/sysdeps/ia64/hp-timing.h +@@ -20,10 +20,6 @@ + #ifndef _HP_TIMING_H + #define _HP_TIMING_H 1 + +-/* We always assume having the timestamp register. */ +-#define HP_TIMING_AVAIL (1) +-#define HP_SMALL_TIMING_AVAIL (1) +- + /* We indeed have inlined functions. */ + #define HP_TIMING_INLINE (1) + +diff --git a/sysdeps/powerpc/powerpc32/power4/hp-timing.h b/sysdeps/powerpc/powerpc32/power4/hp-timing.h +index 10efcac481349ee3..0e81f4fe6a46ab86 100644 +--- a/sysdeps/powerpc/powerpc32/power4/hp-timing.h ++++ b/sysdeps/powerpc/powerpc32/power4/hp-timing.h +@@ -20,10 +20,6 @@ + #ifndef _HP_TIMING_H + #define _HP_TIMING_H 1 + +-/* We always assume having the timestamp register. */ +-#define HP_TIMING_AVAIL (1) +-#define HP_SMALL_TIMING_AVAIL (1) +- + /* We indeed have inlined functions. */ + #define HP_TIMING_INLINE (1) + +diff --git a/sysdeps/powerpc/powerpc64/hp-timing.h b/sysdeps/powerpc/powerpc64/hp-timing.h +index c0aa3642f6ff1a42..77fe5e85bb32c163 100644 +--- a/sysdeps/powerpc/powerpc64/hp-timing.h ++++ b/sysdeps/powerpc/powerpc64/hp-timing.h +@@ -20,10 +20,6 @@ + #ifndef _HP_TIMING_H + #define _HP_TIMING_H 1 + +-/* We always assume having the timestamp register. */ +-#define HP_TIMING_AVAIL (1) +-#define HP_SMALL_TIMING_AVAIL (1) +- + /* We indeed have inlined functions. */ + #define HP_TIMING_INLINE (1) + +diff --git a/sysdeps/sparc/sparc32/sparcv9/hp-timing.h b/sysdeps/sparc/sparc32/sparcv9/hp-timing.h +index 42451966f6192bcb..aedf9c031a0daad9 100644 +--- a/sysdeps/sparc/sparc32/sparcv9/hp-timing.h ++++ b/sysdeps/sparc/sparc32/sparcv9/hp-timing.h +@@ -20,8 +20,6 @@ + #ifndef _HP_TIMING_H + #define _HP_TIMING_H 1 + +-#define HP_TIMING_AVAIL (1) +-#define HP_SMALL_TIMING_AVAIL (1) + #define HP_TIMING_INLINE (1) + + typedef unsigned long long int hp_timing_t; +diff --git a/sysdeps/sparc/sparc64/hp-timing.h b/sysdeps/sparc/sparc64/hp-timing.h +index 66325641067e1198..ee22729063745944 100644 +--- a/sysdeps/sparc/sparc64/hp-timing.h ++++ b/sysdeps/sparc/sparc64/hp-timing.h +@@ -20,8 +20,6 @@ + #ifndef _HP_TIMING_H + #define _HP_TIMING_H 1 + +-#define HP_TIMING_AVAIL (1) +-#define HP_SMALL_TIMING_AVAIL (1) + #define HP_TIMING_INLINE (1) + + typedef unsigned long int hp_timing_t; +diff --git a/sysdeps/x86/hp-timing.h b/sysdeps/x86/hp-timing.h +index 0aa6f5e3f83e0d34..4dbd2aa8af69f95e 100644 +--- a/sysdeps/x86/hp-timing.h ++++ b/sysdeps/x86/hp-timing.h +@@ -22,10 +22,6 @@ + #include + + #if MINIMUM_ISA == 686 || MINIMUM_ISA == 8664 +-/* We always assume having the timestamp register. */ +-# define HP_TIMING_AVAIL (1) +-# define HP_SMALL_TIMING_AVAIL (1) +- + /* We indeed have inlined functions. */ + # define HP_TIMING_INLINE (1) + diff --git a/glibc-rh1817513-25.patch b/glibc-rh1817513-25.patch new file mode 100755 index 0000000..91c0bf1 --- /dev/null +++ b/glibc-rh1817513-25.patch @@ -0,0 +1,113 @@ +commit b2af6fb2ed23930c148bae382ca85fad4d1cf32e +Author: Adhemerval Zanella +Date: Tue Apr 30 16:11:57 2019 -0300 + + elf: Fix elf/tst-pldd with --enable-hardcoded-path-in-tests (BZ#24506) + + The elf/tst-pldd (added by 1a4c27355e146 to fix BZ#18035) test does + not expect the hardcoded paths that are output by pldd when the test + is built with --enable-hardcoded-path-in-tests. Instead of showing + the ABI installed library names for loader and libc (such as + ld-linux-x86-64.so.2 and libc.so.6 for x86_64), pldd shows the default + built ld.so and libc.so. + + It makes the tests fail with an invalid expected loader/libc name. + + This patch fixes the elf-pldd test by adding the canonical ld.so and + libc.so names in the expected list of possible outputs when parsing + the result output from pldd. The test now handles both default + build and --enable-hardcoded-path-in-tests option. + + Checked on x86_64-linux-gnu (built with and without + --enable-hardcoded-path-in-tests) and i686-linux-gnu. + + * elf/tst-pldd.c (in_str_list): New function. + (do_test): Add default names for ld and libc as one option. + + Reviewed-by: Carlos O'Donell + +Conflicts: + elf/tst-pldd.c + (Original backport uses spaces instead of tabs.) + +diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c +index 0f51c95935ffb2cf..40abee9efb9e7484 100644 +--- a/elf/tst-pldd.c ++++ b/elf/tst-pldd.c +@@ -20,7 +20,6 @@ + #include + #include + #include +-#include + #include + + #include +@@ -39,6 +38,15 @@ target_process (void *arg) + /* The test runs in a container because pldd does not support tracing + a binary started by the loader iself (as with testrun.sh). */ + ++static bool ++in_str_list (const char *libname, const char *const strlist[]) ++{ ++ for (const char *const *str = strlist; *str != NULL; str++) ++ if (strcmp (libname, *str) == 0) ++ return true; ++ return false; ++} ++ + static int + do_test (void) + { +@@ -82,26 +90,32 @@ do_test (void) + { + /* 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; +- } ++ 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'; ++ ++ const char *libname = basename (buffer); ++ ++ /* It checks for default names in case of build configure with ++ --enable-hardcoded-path-in-tests (BZ #24506). */ ++ if (in_str_list (libname, ++ (const char *const []) { "ld.so", LD_SO, NULL })) ++ { ++ TEST_COMPARE (interpreter_found, false); ++ interpreter_found = true; ++ continue; ++ } ++ ++ if (in_str_list (libname, ++ (const char *const []) { "libc.so", LIBC_SO, NULL })) ++ { ++ TEST_COMPARE (libc_found, false); ++ libc_found = true; ++ continue; ++ } + } + TEST_COMPARE (interpreter_found, true); + TEST_COMPARE (libc_found, true); diff --git a/glibc-rh1817513-26.patch b/glibc-rh1817513-26.patch new file mode 100755 index 0000000..ff53662 --- /dev/null +++ b/glibc-rh1817513-26.patch @@ -0,0 +1,54 @@ +commit da2b83ef6ba6f4c974664f69e715cc85b9173938 +Author: Adhemerval Zanella +Date: Mon May 13 13:13:46 2019 -0300 + + elf: Fix tst-pldd for non-default --prefix and/or --bindir (BZ#24544) + + Use a new libsupport support_bindir_prefix instead of a hardcoded + /usr/bin to create the pldd path on container directory. + + Checked on x86_64-linux-gnu with default and non-default --prefix and + --bindir paths, as well with --enable-hardcoded-path-in-tests. + + [BZ #24544] + * elf/tst-pldd.c (do_test): Use support_bindir_prefix instead of + pre-defined value. + + Reviewed-by: DJ Delorie + +diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c +index 40abee9efb9e7484..e2de31282a131166 100644 +--- a/elf/tst-pldd.c ++++ b/elf/tst-pldd.c +@@ -18,6 +18,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -28,6 +29,7 @@ + #include + #include + #include ++#include + + static void + target_process (void *arg) +@@ -60,12 +62,14 @@ do_test (void) + char pid[3 * sizeof (uint32_t) + 1]; + snprintf (pid, array_length (pid), "%d", target.pid); + +- const char prog[] = "/usr/bin/pldd"; ++ char *prog = xasprintf ("%s/pldd", support_bindir_prefix); + + pldd = support_capture_subprogram (prog, + (char *const []) { (char *) prog, pid, NULL }); + + support_capture_subprocess_check (&pldd, "pldd", 0, sc_allow_stdout); ++ ++ free (prog); + } + + /* Check 'pldd' output. The test is expected to be linked against only diff --git a/glibc-rh1817513-27.patch b/glibc-rh1817513-27.patch new file mode 100755 index 0000000..48e5930 --- /dev/null +++ b/glibc-rh1817513-27.patch @@ -0,0 +1,49 @@ +commit 75c51570c710aa9c6df6b7a1e131392e1408c63f +Author: Florian Weimer +Date: Mon May 20 21:08:40 2019 +0200 + + support: Expose sbindir as support_sbindir_prefix + +diff --git a/support/Makefile b/support/Makefile +index 6afaa6836c944398..65b16299573af1ed 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -178,6 +178,7 @@ CFLAGS-support_paths.c = \ + -DINSTDIR_PATH=\"$(prefix)\" \ + -DLIBDIR_PATH=\"$(libdir)\" \ + -DBINDIR_PATH=\"$(bindir)\" \ ++ -DSBINDIR_PATH=\"$(sbindir)\" \ + -DROOTSBINDIR_PATH=\"$(rootsbindir)\" + + ifeq (,$(CXX)) +diff --git a/support/support.h b/support/support.h +index 97d142e9b6f68188..121cc9e9b7c98ca6 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -109,6 +109,8 @@ extern const char support_libdir_prefix[]; + /* Corresponds to the install's bin/ directory. */ + extern const char support_bindir_prefix[]; + /* Corresponds to the install's sbin/ directory. */ ++extern const char support_sbindir_prefix[]; ++/* Corresponds to the install's sbin/ directory (without prefix). */ + extern const char support_install_rootsbindir[]; + + extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *, +diff --git a/support/support_paths.c b/support/support_paths.c +index a37a0720dc7339f0..eb2390227433aa70 100644 +--- a/support/support_paths.c ++++ b/support/support_paths.c +@@ -65,6 +65,13 @@ const char support_bindir_prefix[] = BINDIR_PATH; + # error please -DBINDIR_PATH=something in the Makefile + #endif + ++#ifdef SBINDIR_PATH ++/* Corresponds to the install's bin/ directory. */ ++const char support_sbindir_prefix[] = SBINDIR_PATH; ++#else ++# error please -DSBINDIR_PATH=something in the Makefile ++#endif ++ + #ifdef ROOTSBINDIR_PATH + /* Corresponds to the install's sbin/ directory. */ + const char support_install_rootsbindir[] = ROOTSBINDIR_PATH; diff --git a/glibc-rh1817513-28.patch b/glibc-rh1817513-28.patch new file mode 100755 index 0000000..c52ed81 --- /dev/null +++ b/glibc-rh1817513-28.patch @@ -0,0 +1,58 @@ +commit d039da1c00e01f8d3c3d74f439a971eb73e3045e +Author: H.J. Lu +Date: Wed Jun 26 15:07:18 2019 -0700 + + x86: Add sysdeps/x86/dl-lookupcfg.h + + Since sysdeps/i386/dl-lookupcfg.h and sysdeps/x86_64/dl-lookupcfg.h are + identical, we can replace them with sysdeps/x86/dl-lookupcfg.h. + + * sysdeps/i386/dl-lookupcfg.h: Moved to ... + * sysdeps/x86/dl-lookupcfg.h: Here. + * sysdeps/x86_64/dl-lookupcfg.h: Removed. + +Conflicts: + sysdeps/x86_64/dl-lookupcfg.h + (Removal after copyright year update.) + +diff --git a/sysdeps/i386/dl-lookupcfg.h b/sysdeps/x86/dl-lookupcfg.h +similarity index 100% +rename from sysdeps/i386/dl-lookupcfg.h +rename to sysdeps/x86/dl-lookupcfg.h +diff --git a/sysdeps/x86_64/dl-lookupcfg.h b/sysdeps/x86_64/dl-lookupcfg.h +deleted file mode 100644 +index 5399cf25abde592d..0000000000000000 +--- a/sysdeps/x86_64/dl-lookupcfg.h ++++ /dev/null +@@ -1,31 +0,0 @@ +-/* Configuration of lookup functions. +- Copyright (C) 2005-2018 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 +- . */ +- +-#define DL_UNMAP_IS_SPECIAL +- +-#include_next +- +-/* Address of protected data defined in the shared library may be +- external due to copy relocation. */ +-#define DL_EXTERN_PROTECTED_DATA +- +-struct link_map; +- +-extern void _dl_unmap (struct link_map *map) attribute_hidden; +- +-#define DL_UNMAP(map) _dl_unmap (map) diff --git a/glibc-rh1817513-29.patch b/glibc-rh1817513-29.patch new file mode 100755 index 0000000..bc9a8f4 --- /dev/null +++ b/glibc-rh1817513-29.patch @@ -0,0 +1,109 @@ +commit 23d2e5faf0bca6d9b31bef4aa162b95ee64cbfc6 +Author: Florian Weimer +Date: Thu Aug 15 14:37:50 2019 +0200 + + elf: Self-dlopen failure with explict loader invocation [BZ #24900] + + In case of an explicit loader invocation, ld.so essentially performs + a dlopen call to load the main executable. Since the pathname of + the executable is known at this point, it gets stored in the link + map. In regular mode, the pathname is not known and "" is used + instead. + + As a result, if a program calls dlopen on the pathname of the main + program, the dlopen call succeeds and returns a handle for the main + map. This results in an unnecessary difference between glibc + testing (without --enable-hardcoded-path-in-tests) and production + usage. + + This commit discards the names when building the link map in + _dl_new_object for the main executable, but it still determines + the origin at this point in case of an explict loader invocation. + The reason is that the specified pathname has to be used; the kernel + has a different notion of the main executable. + +Conflicts: + elf/Makefile + elf/tst-dlopen-aout.c + (Differences due to the complicated history of the test. + The new test elf/tst-dlopen-aout-container is not backported + here.) + +diff --git a/elf/dl-object.c b/elf/dl-object.c +index b37bcc1295f475f6..f6544a8fec45bdce 100644 +--- a/elf/dl-object.c ++++ b/elf/dl-object.c +@@ -57,14 +57,30 @@ struct link_map * + _dl_new_object (char *realname, const char *libname, int type, + struct link_map *loader, int mode, Lmid_t nsid) + { ++#ifdef SHARED ++ unsigned int naudit; ++ if (__glibc_unlikely ((mode & __RTLD_OPENEXEC) != 0)) ++ { ++ assert (type == lt_executable); ++ assert (nsid == LM_ID_BASE); ++ ++ /* Ignore the specified libname for the main executable. It is ++ only known with an explicit loader invocation. */ ++ libname = ""; ++ ++ /* We create the map for the executable before we know whether ++ we have auditing libraries and if yes, how many. Assume the ++ worst. */ ++ naudit = DL_NNS; ++ } ++ else ++ naudit = GLRO (dl_naudit); ++#endif ++ + size_t libname_len = strlen (libname) + 1; + struct link_map *new; + struct libname_list *newname; + #ifdef SHARED +- /* We create the map for the executable before we know whether we have +- auditing libraries and if yes, how many. Assume the worst. */ +- unsigned int naudit = GLRO(dl_naudit) ?: ((mode & __RTLD_OPENEXEC) +- ? DL_NNS : 0); + size_t audit_space = naudit * sizeof (new->l_audit[0]); + #else + # define audit_space 0 +@@ -91,8 +107,20 @@ _dl_new_object (char *realname, const char *libname, int type, + and won't get dumped during core file generation. Therefore to assist + gdb and to create more self-contained core files we adjust l_name to + point at the newly allocated copy (which will get dumped) instead of +- the ld.so rodata copy. */ +- new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1; ++ the ld.so rodata copy. ++ ++ Furthermore, in case of explicit loader invocation, discard the ++ name of the main executable, to match the regular behavior, where ++ name of the executable is not known. */ ++#ifdef SHARED ++ if (*realname != '\0' && (mode & __RTLD_OPENEXEC) == 0) ++#else ++ if (*realname != '\0') ++#endif ++ new->l_name = realname; ++ else ++ new->l_name = (char *) newname->name + libname_len - 1; ++ + new->l_type = type; + /* If we set the bit now since we know it is never used we avoid + dirtying the cache line later. */ +@@ -149,7 +177,14 @@ _dl_new_object (char *realname, const char *libname, int type, + + new->l_local_scope[0] = &new->l_searchlist; + +- /* Don't try to find the origin for the main map which has the name "". */ ++ /* Determine the origin. If allocating the link map for the main ++ executable, the realname is not known and "". In this case, the ++ origin needs to be determined by other means. However, in case ++ of an explicit loader invocation, the pathname of the main ++ executable is known and needs to be processed here: From the ++ point of view of the kernel, the main executable is the ++ dynamic loader, and this would lead to a computation of the wrong ++ origin. */ + if (realname[0] != '\0') + { + size_t realname_len = strlen (realname) + 1; diff --git a/glibc-rh1817513-3.patch b/glibc-rh1817513-3.patch new file mode 100755 index 0000000..f6eccb4 --- /dev/null +++ b/glibc-rh1817513-3.patch @@ -0,0 +1,56 @@ +commit ae67f2e562603a0b58f59aef4f31aa33de05ba88 +Author: H.J. Lu +Date: Fri Aug 3 06:40:48 2018 -0700 + + x86: Cleanup cpu-features-offsets.sym + + Remove the unused macros. There is no code changes in libc.so nor + ld.so on i686 and x86-64. + + * sysdeps/x86/cpu-features-offsets.sym + (rtld_global_ro_offsetof): Removed. + (CPU_FEATURES_SIZE): Likewise. + (CPUID_OFFSET): Likewise. + (CPUID_SIZE): Likewise. + (CPUID_EAX_OFFSET): Likewise. + (CPUID_EBX_OFFSET): Likewise. + (CPUID_ECX_OFFSET): Likewise. + (CPUID_EDX_OFFSET): Likewise. + (FAMILY_OFFSET): Likewise. + (MODEL_OFFSET): Likewise. + (FEATURE_OFFSET): Likewise. + (FEATURE_SIZ): Likewise. + (COMMON_CPUID_INDEX_1): Likewise. + (COMMON_CPUID_INDEX_7): Likewise. + (FEATURE_INDEX_1): Likewise. + (RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET): Updated. + +diff --git a/sysdeps/x86/cpu-features-offsets.sym b/sysdeps/x86/cpu-features-offsets.sym +index 33dd094e37f0fec7..6d03cea8e8fcdc36 100644 +--- a/sysdeps/x86/cpu-features-offsets.sym ++++ b/sysdeps/x86/cpu-features-offsets.sym +@@ -2,23 +2,5 @@ + + #include + +-#define rtld_global_ro_offsetof(mem) offsetof (struct rtld_global_ro, mem) +- +-RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET rtld_global_ro_offsetof (_dl_x86_cpu_features) +- +-CPU_FEATURES_SIZE sizeof (struct cpu_features) +-CPUID_OFFSET offsetof (struct cpu_features, cpuid) +-CPUID_SIZE sizeof (struct cpuid_registers) +-CPUID_EAX_OFFSET offsetof (struct cpuid_registers, eax) +-CPUID_EBX_OFFSET offsetof (struct cpuid_registers, ebx) +-CPUID_ECX_OFFSET offsetof (struct cpuid_registers, ecx) +-CPUID_EDX_OFFSET offsetof (struct cpuid_registers, edx) +-FAMILY_OFFSET offsetof (struct cpu_features, family) +-MODEL_OFFSET offsetof (struct cpu_features, model) ++RTLD_GLOBAL_RO_DL_X86_CPU_FEATURES_OFFSET offsetof (struct rtld_global_ro, _dl_x86_cpu_features) + XSAVE_STATE_SIZE_OFFSET offsetof (struct cpu_features, xsave_state_size) +-FEATURE_OFFSET offsetof (struct cpu_features, feature) +-FEATURE_SIZE sizeof (unsigned int) +- +-COMMON_CPUID_INDEX_1 +-COMMON_CPUID_INDEX_7 +-FEATURE_INDEX_1 diff --git a/glibc-rh1817513-30.patch b/glibc-rh1817513-30.patch new file mode 100755 index 0000000..8fe1e89 --- /dev/null +++ b/glibc-rh1817513-30.patch @@ -0,0 +1,141 @@ +commit edd8d70b91e1ccef549a7c668499596cc4d56ad1 +Author: Mihailo Stojanovic +Date: Fri Aug 23 16:47:27 2019 +0000 + + [MIPS] Raise highest supported EI_ABIVERSION value [BZ #24916] + + This bumps the highest valid EI_ABIVERSION value to ABSOLUTE ABI. + + New testcase loads the symbol from the GOT with the "lb" instruction + so that the EI_ABIVERSION header field of the shared object is set + to ABSOLUTE (it doesn't actually check the value of the symbol), and + makes sure that the main executable is executed without "ABI version + invalid" error. + + Tested for all three ABIs (o32, n32, n64) using both static linker which + handles undefined weak symbols correctly [1] (and sets the EI_ABIVERSION + of the test module) and the one that doesn't (EI_ABIVERSION left as 0). + + [1] https://sourceware.org/ml/binutils/2018-07/msg00268.html + + [BZ #24916] + * sysdeps/mips/Makefile [$(subdir) = elf] (tests): Add + tst-undefined-weak. + [$(subdir) = elf] (modules-names): Add tst-undefined-weak-lib. + [$(subdir) = elf] ($(objpfx)tst-undefined-weak): Add dependency. + * sysdeps/mips/tst-undefined-weak-lib.S: New file. + * sysdeps/mips/tst-undefined-weak.c: Likewise. + * sysdeps/unix/sysv/linux/mips/ldsodefs.h (VALID_ELF_ABIVERSION): + Increment highest valid ABIVERSION value. + +diff --git a/sysdeps/mips/Makefile b/sysdeps/mips/Makefile +index 7ac6fa50311d60b7..6ad69e9ef9e88728 100644 +--- a/sysdeps/mips/Makefile ++++ b/sysdeps/mips/Makefile +@@ -82,3 +82,10 @@ $(objpfx)tst-mode-switch-2: $(shared-thread-library) + endif + endif + endif ++ ++ifeq ($(subdir),elf) ++tests += tst-undefined-weak ++modules-names += tst-undefined-weak-lib ++ ++$(objpfx)tst-undefined-weak: $(objpfx)tst-undefined-weak-lib.so ++endif +diff --git a/sysdeps/mips/tst-undefined-weak-lib.S b/sysdeps/mips/tst-undefined-weak-lib.S +new file mode 100644 +index 0000000000000000..a175ebf90e01b372 +--- /dev/null ++++ b/sysdeps/mips/tst-undefined-weak-lib.S +@@ -0,0 +1,43 @@ ++/* Undefined weak symbol loading shared module. ++ 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 ++ . */ ++ ++#include ++ ++ .text ++ .globl x ++ .set nomips16 ++ .set nomicromips ++ .ent x ++ .type x, @function ++x: ++ .set noreorder ++#if _MIPS_SIM == _ABIO32 ++ .cpload $25 ++ jr $31 ++ lb $2,%got(a)($28) ++#else ++ .cpsetup $25,$24,x ++ lb $2,%got_disp(a)($28) ++ jr $31 ++ .cpreturn ++#endif ++ .set reorder ++ .end x ++ .size x, .-x ++ .weak a ++ .hidden a +diff --git a/sysdeps/mips/tst-undefined-weak.c b/sysdeps/mips/tst-undefined-weak.c +new file mode 100644 +index 0000000000000000..1231da6912508c19 +--- /dev/null ++++ b/sysdeps/mips/tst-undefined-weak.c +@@ -0,0 +1,28 @@ ++/* Undefined weak symbol loading main executable. ++ 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 ++ . */ ++ ++int *x (void); ++ ++int ++do_test (void) ++{ ++ x (); ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/unix/sysv/linux/mips/ldsodefs.h b/sysdeps/unix/sysv/linux/mips/ldsodefs.h +index 68a0a99bb1f1ec85..d2912cadabfd6877 100644 +--- a/sysdeps/unix/sysv/linux/mips/ldsodefs.h ++++ b/sysdeps/unix/sysv/linux/mips/ldsodefs.h +@@ -34,7 +34,7 @@ extern void _dl_static_init (struct link_map *map); + #undef VALID_ELF_ABIVERSION + #define VALID_ELF_ABIVERSION(osabi,ver) \ + (ver == 0 \ +- || (osabi == ELFOSABI_SYSV && ver < 4) \ ++ || (osabi == ELFOSABI_SYSV && ver < 5) \ + || (osabi == ELFOSABI_GNU && ver < LIBC_ABI_MAX)) + + #endif /* ldsodefs.h */ diff --git a/glibc-rh1817513-31.patch b/glibc-rh1817513-31.patch new file mode 100755 index 0000000..2081d6b --- /dev/null +++ b/glibc-rh1817513-31.patch @@ -0,0 +1,241 @@ +commit 23c1c256ae7b0f010d0fcaff60682b620887b164 +Author: Mihailo Stojanovic +Date: Thu Aug 29 20:11:42 2019 +0000 + + MIPS support for GNU hash + + This patch is a reimplementation of [1], which was submitted back in + 2015. Copyright issue has been sorted [2] last year. It proposed a new + section (.gnu.xhash) and related dynamic tag (GT_GNU_XHASH). The new + section would be virtually identical to the existing .gnu.hash except + for the translation table (xlat) which would contain correct MIPS + .dynsym indexes corresponding to the hashvals in chains. This is because + MIPS ABI imposes a different ordering of the dynsyms than the one + expected by the .gnu.hash section. Another addition would be a leading + word at the beggining of the section, which would contain the number of + entries in the translation table. + + In this patch, the new section name and dynamic tag are changed to + reflect the fact that the section should be treated as MIPS specific + (.MIPS.xhash and DT_MIPS_XHASH). + + This patch addresses the alignment issue reported in [3] which is caused + by the leading word of the .MIPS.xhash section. Leading word is now + removed in the corresponding binutils patch, and the number of entries + in the translation table is computed using DT_MIPS_SYMTABNO dynamic tag. + + Since the MIPS specific dl-lookup.c file was removed following the + initial patch submission, I opted for the definition of three new macros + in the generic ldsodefs.h. ELF_MACHINE_GNU_HASH_ADDRIDX defines the + index of the dynamic tag in the l_info array. ELF_MACHINE_HASH_SYMIDX is + used to calculate the index of a symbol in GNU hash. On MIPS, it is + defined to look up the symbol index in the translation table. + ELF_MACHINE_XHASH_SETUP is defined for MIPS only. It initializes the + .MIPS.xhash pointer in the link_map_machine struct. + + The other major change is bumping the highest EI_ABIVERSION value for + MIPS to suggest that the dynamic linker now supports GNU hash. + + The patch was tested by running the glibc testsuite for the three MIPS + ABIs (o32, n32 and n64) and for x86_64-linux-gnu. + + [1] https://sourceware.org/ml/binutils/2015-10/msg00057.html + [2] https://sourceware.org/ml/binutils/2018-03/msg00025.html + [3] https://sourceware.org/ml/binutils/2016-01/msg00006.html + + * elf/dl-addr.c (determine_info): Calculate the symbol index + using the newly defined ELF_MACHINE_HASH_SYMIDX macro. + * elf/dl-lookup.c (do_lookup_x): Ditto. + (_dl_setup_hash): Initialize MIPS xhash translation table. + * elf/elf.h (SHT_MIPS_XHASH): New define. + (DT_MIPS_XHASH): New define. + * sysdeps/generic/ldsodefs.h (ELF_MACHINE_GNU_HASH_ADDRIDX): New + define. + (ELF_MACHINE_HASH_SYMIDX): Ditto. + (ELF_MACHINE_XHASH_SETUP): Ditto. + * sysdeps/mips/ldsodefs.h (ELF_MACHINE_GNU_HASH_ADDRIDX): New + define. + (ELF_MACHINE_HASH_SYMIDX): Ditto. + (ELF_MACHINE_XHASH_SETUP): Ditto. + * sysdeps/mips/linkmap.h (struct link_map_machine): New member. + * sysdeps/unix/sysv/linux/mips/ldsodefs.h: Increment valid ABI + version. + * sysdeps/unix/sysv/linux/mips/libc-abis: New ABI version. + +diff --git a/elf/dl-addr.c b/elf/dl-addr.c +index e6c7d020945c51d2..b146fed09a46ff76 100644 +--- a/elf/dl-addr.c ++++ b/elf/dl-addr.c +@@ -42,7 +42,7 @@ determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info, + ElfW(Word) strtabsize = match->l_info[DT_STRSZ]->d_un.d_val; + + const ElfW(Sym) *matchsym = NULL; +- if (match->l_info[ADDRIDX (DT_GNU_HASH)] != NULL) ++ if (match->l_info[ELF_MACHINE_GNU_HASH_ADDRIDX] != NULL) + { + /* We look at all symbol table entries referenced by the hash + table. */ +@@ -57,6 +57,7 @@ determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info, + { + /* The hash table never references local symbols so + we can omit that test here. */ ++ symndx = ELF_MACHINE_HASH_SYMIDX (match, hasharr); + if ((symtab[symndx].st_shndx != SHN_UNDEF + || symtab[symndx].st_value != 0) + && symtab[symndx].st_shndx != SHN_ABS +@@ -65,8 +66,6 @@ determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info, + matchsym, addr) + && symtab[symndx].st_name < strtabsize) + matchsym = (ElfW(Sym) *) &symtab[symndx]; +- +- ++symndx; + } + while ((*hasharr++ & 1u) == 0); + } +diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c +index 01724a54f8840f9f..42fdaed99296137f 100644 +--- a/elf/dl-lookup.c ++++ b/elf/dl-lookup.c +@@ -432,7 +432,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash, + do + if (((*hasharr ^ new_hash) >> 1) == 0) + { +- symidx = hasharr - map->l_gnu_chain_zero; ++ symidx = ELF_MACHINE_HASH_SYMIDX (map, hasharr); + sym = check_match (undef_name, ref, version, flags, + type_class, &symtab[symidx], symidx, + strtab, map, &versioned_sym, +@@ -961,10 +961,10 @@ _dl_setup_hash (struct link_map *map) + { + Elf_Symndx *hash; + +- if (__glibc_likely (map->l_info[ADDRIDX (DT_GNU_HASH)] != NULL)) ++ if (__glibc_likely (map->l_info[ELF_MACHINE_GNU_HASH_ADDRIDX] != NULL)) + { + Elf32_Word *hash32 +- = (void *) D_PTR (map, l_info[ADDRIDX (DT_GNU_HASH)]); ++ = (void *) D_PTR (map, l_info[ELF_MACHINE_GNU_HASH_ADDRIDX]); + map->l_nbuckets = *hash32++; + Elf32_Word symbias = *hash32++; + Elf32_Word bitmask_nwords = *hash32++; +@@ -979,6 +979,10 @@ _dl_setup_hash (struct link_map *map) + map->l_gnu_buckets = hash32; + hash32 += map->l_nbuckets; + map->l_gnu_chain_zero = hash32 - symbias; ++ ++ /* Initialize MIPS xhash translation table. */ ++ ELF_MACHINE_XHASH_SETUP (hash32, symbias, map); ++ + return; + } + +diff --git a/elf/elf.h b/elf/elf.h +index 74f7f479ce817040..d6506ea1c7160dea 100644 +--- a/elf/elf.h ++++ b/elf/elf.h +@@ -1698,6 +1698,7 @@ typedef struct + #define SHT_MIPS_EH_REGION 0x70000027 + #define SHT_MIPS_XLATE_OLD 0x70000028 + #define SHT_MIPS_PDR_EXCEPTION 0x70000029 ++#define SHT_MIPS_XHASH 0x7000002b + + /* Legal values for sh_flags field of Elf32_Shdr. */ + +@@ -1945,7 +1946,9 @@ typedef struct + in a PIE as it stores a relative offset from the address of the tag + rather than an absolute address. */ + #define DT_MIPS_RLD_MAP_REL 0x70000035 +-#define DT_MIPS_NUM 0x36 ++/* GNU-style hash table with xlat. */ ++#define DT_MIPS_XHASH 0x70000036 ++#define DT_MIPS_NUM 0x37 + + /* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ + +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index f0185ce0d16c0f69..3bdbdd6e67dacc85 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -47,6 +47,23 @@ __BEGIN_DECLS + #define ADDRIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \ + + DT_EXTRANUM + DT_VALNUM + DT_ADDRTAGIDX (tag)) + ++/* Type of GNU hash which the machine uses. */ ++#ifndef ELF_MACHINE_GNU_HASH_ADDRIDX ++# define ELF_MACHINE_GNU_HASH_ADDRIDX ADDRIDX (DT_GNU_HASH) ++#endif ++ ++/* Calculate the index of a symbol in GNU hash. */ ++#ifndef ELF_MACHINE_HASH_SYMIDX ++# define ELF_MACHINE_HASH_SYMIDX(map, hasharr) \ ++ ((hasharr) - (map)->l_gnu_chain_zero) ++#endif ++ ++/* Setup MIPS xhash. Defined only for MIPS. */ ++#ifndef ELF_MACHINE_XHASH_SETUP ++# define ELF_MACHINE_XHASH_SETUP(hash32, symbias, map) \ ++ ((void) (hash32), (void) (symbias), (void) (map)) ++#endif ++ + /* We use this macro to refer to ELF types independent of the native wordsize. + `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */ + #define ELFW(type) _ElfW (ELF, __ELF_NATIVE_CLASS, type) +diff --git a/sysdeps/mips/ldsodefs.h b/sysdeps/mips/ldsodefs.h +index c6e5ce7e660325c1..35043b7c6d416c50 100644 +--- a/sysdeps/mips/ldsodefs.h ++++ b/sysdeps/mips/ldsodefs.h +@@ -26,6 +26,21 @@ struct La_mips_32_retval; + struct La_mips_64_regs; + struct La_mips_64_retval; + ++#define ELF_MACHINE_GNU_HASH_ADDRIDX (DT_MIPS_XHASH - DT_LOPROC + DT_NUM) ++ ++/* Calculate the index of a symbol in MIPS xhash. */ ++#define ELF_MACHINE_HASH_SYMIDX(map, hasharr) \ ++ ((map)->l_mach.mips_xlat_zero[(hasharr) - (map)->l_gnu_chain_zero]) ++ ++/* Setup MIPS xhash. */ ++#define ELF_MACHINE_XHASH_SETUP(hash32, symbias, map) \ ++ do \ ++ { \ ++ (hash32) += (map)->l_info[DT_MIPS (SYMTABNO)]->d_un.d_val - (symbias); \ ++ (map)->l_mach.mips_xlat_zero = (hash32) - (symbias); \ ++ } \ ++ while (0) ++ + #define ARCH_PLTENTER_MEMBERS \ + Elf32_Addr (*mips_o32_gnu_pltenter) (Elf32_Sym *, unsigned int, \ + uintptr_t *, uintptr_t *, \ +diff --git a/sysdeps/mips/linkmap.h b/sysdeps/mips/linkmap.h +index 1fb9678a6d1625fd..1e640c3ba9bd18e4 100644 +--- a/sysdeps/mips/linkmap.h ++++ b/sysdeps/mips/linkmap.h +@@ -3,4 +3,5 @@ struct link_map_machine + ElfW(Addr) plt; /* Address of .plt */ + ElfW(Word) fpabi; /* FP ABI of the object */ + unsigned int odd_spreg; /* Does the object require odd_spreg support? */ ++ const Elf32_Word *mips_xlat_zero; /* .MIPS.xhash */ + }; +diff --git a/sysdeps/unix/sysv/linux/mips/ldsodefs.h b/sysdeps/unix/sysv/linux/mips/ldsodefs.h +index d2912cadabfd6877..03f3e12f202a0563 100644 +--- a/sysdeps/unix/sysv/linux/mips/ldsodefs.h ++++ b/sysdeps/unix/sysv/linux/mips/ldsodefs.h +@@ -34,7 +34,7 @@ extern void _dl_static_init (struct link_map *map); + #undef VALID_ELF_ABIVERSION + #define VALID_ELF_ABIVERSION(osabi,ver) \ + (ver == 0 \ +- || (osabi == ELFOSABI_SYSV && ver < 5) \ ++ || (osabi == ELFOSABI_SYSV && ver < 6) \ + || (osabi == ELFOSABI_GNU && ver < LIBC_ABI_MAX)) + + #endif /* ldsodefs.h */ +diff --git a/sysdeps/unix/sysv/linux/mips/libc-abis b/sysdeps/unix/sysv/linux/mips/libc-abis +index eaea558720f42a48..c0b67dae3ece1511 100644 +--- a/sysdeps/unix/sysv/linux/mips/libc-abis ++++ b/sysdeps/unix/sysv/linux/mips/libc-abis +@@ -16,3 +16,5 @@ UNIQUE + MIPS_O32_FP64 mips*-*-linux* + # Absolute (SHN_ABS) symbols working correctly. + ABSOLUTE ++# GNU-style hash table with translation table. ++MIPS_XHASH diff --git a/glibc-rh1817513-32.patch b/glibc-rh1817513-32.patch new file mode 100755 index 0000000..4f68439 --- /dev/null +++ b/glibc-rh1817513-32.patch @@ -0,0 +1,254 @@ +commit 2f9046fb059e94fe254c9a4ff5bcd52182069e44 +Author: Stefan Liebler +Date: Wed Sep 18 12:40:00 2019 +0200 + + Add UNSUPPORTED check in elf/tst-pldd. + + The testcase forks a child process and runs pldd with PID of + this child. On systems where /proc/sys/kernel/yama/ptrace_scope + differs from zero, pldd will fail with + /usr/bin/pldd: cannot attach to process 3: Operation not permitted + + This patch checks if ptrace_scope exists, is zero "classic ptrace permissions" + or one "restricted ptrace". If ptrace_scope exists and has a higher + restriction, then the test is marked as UNSUPPORTED. + + The case "restricted ptrace" is handled by rearranging the processes involved + during the test. Now we have the following process tree: + -parent: do_test (performs output checks) + --subprocess 1: pldd_process (becomes pldd via execve) + ---subprocess 2: target_process (ptraced via pldd) + + ChangeLog: + + * elf/tst-pldd.c (do_test): Add UNSUPPORTED check. + Rearrange subprocesses. + (pldd_process): New function. + * support/Makefile (libsupport-routines): Add support_ptrace. + * support/xptrace.h: New file. + * support/support_ptrace.c: Likewise. + +Conflicts: + elf/tst-pldd.c + (Original backport uses spaces instead of tabs.) + +diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c +index e2de31282a131166..f381cb0fa7e6b93d 100644 +--- a/elf/tst-pldd.c ++++ b/elf/tst-pldd.c +@@ -30,6 +30,11 @@ + #include + #include + #include ++#include ++#include ++#include ++#include ++#include + + static void + target_process (void *arg) +@@ -37,6 +42,34 @@ target_process (void *arg) + pause (); + } + ++static void ++pldd_process (void *arg) ++{ ++ pid_t *target_pid_ptr = (pid_t *) arg; ++ ++ /* Create a copy of current test to check with pldd. As the ++ target_process is a child of this pldd_process, pldd is also able ++ to attach to target_process if YAMA is configured to 1 = ++ "restricted ptrace". */ ++ struct support_subprocess target = support_subprocess (target_process, NULL); ++ ++ /* Store the pid of target-process as do_test needs it in order to ++ e.g. terminate it at end of the test. */ ++ *target_pid_ptr = target.pid; ++ ++ /* Three digits per byte plus null terminator. */ ++ char pid[3 * sizeof (uint32_t) + 1]; ++ snprintf (pid, array_length (pid), "%d", target.pid); ++ ++ char *prog = xasprintf ("%s/pldd", support_bindir_prefix); ++ ++ /* Run pldd and use the pid of target_process as argument. */ ++ execve (prog, (char *const []) { (char *) prog, pid, NULL }, ++ (char *const []) { NULL }); ++ ++ FAIL_EXIT1 ("Returned from execve: errno=%d=%m\n", errno); ++} ++ + /* The test runs in a container because pldd does not support tracing + a binary started by the loader iself (as with testrun.sh). */ + +@@ -52,25 +85,22 @@ in_str_list (const char *libname, const char *const strlist[]) + 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; ++ /* Check if our subprocess can be debugged with ptrace. */ + { +- /* Three digits per byte plus null terminator. */ +- char pid[3 * sizeof (uint32_t) + 1]; +- snprintf (pid, array_length (pid), "%d", target.pid); +- +- char *prog = xasprintf ("%s/pldd", support_bindir_prefix); +- +- pldd = support_capture_subprogram (prog, +- (char *const []) { (char *) prog, pid, NULL }); ++ int ptrace_scope = support_ptrace_scope (); ++ if (ptrace_scope >= 2) ++ FAIL_UNSUPPORTED ("/proc/sys/kernel/yama/ptrace_scope >= 2"); ++ } + +- support_capture_subprocess_check (&pldd, "pldd", 0, sc_allow_stdout); ++ pid_t *target_pid_ptr = (pid_t *) xmmap (NULL, sizeof (pid_t), ++ PROT_READ | PROT_WRITE, ++ MAP_SHARED | MAP_ANONYMOUS, -1); + +- free (prog); +- } ++ /* Run 'pldd' on test subprocess which will be created in pldd_process. ++ The pid of the subprocess will be written to target_pid_ptr. */ ++ struct support_capture_subprocess pldd; ++ pldd = support_capture_subprocess (pldd_process, target_pid_ptr); ++ 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. */ +@@ -85,15 +115,15 @@ do_test (void) + /* First line is in the form of : */ + TEST_COMPARE (fscanf (out, "%u: " STRINPUT (512), &pid, buffer), 2); + +- TEST_COMPARE (pid, target.pid); ++ TEST_COMPARE (pid, *target_pid_ptr); + 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] != '/') ++ /* Ignore vDSO. */ ++ if (buffer[0] != '/') + continue; + + /* Remove newline so baseline (buffer) can compare against the +@@ -128,7 +158,9 @@ do_test (void) + } + + support_capture_subprocess_free (&pldd); +- support_process_terminate (&target); ++ if (kill (*target_pid_ptr, SIGKILL) != 0) ++ FAIL_EXIT1 ("Unable to kill target_process: errno=%d=%m\n", errno); ++ xmunmap (target_pid_ptr, sizeof (pid_t)); + + return 0; + } +diff --git a/support/Makefile b/support/Makefile +index 65b16299573af1ed..79d03bd6bfe02540 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -58,6 +58,7 @@ libsupport-routines = \ + support_format_hostent \ + support_format_netent \ + support_isolate_in_subprocess \ ++ support_ptrace \ + support_openpty \ + support_paths \ + support_quote_blob \ +diff --git a/support/support_ptrace.c b/support/support_ptrace.c +new file mode 100644 +index 0000000000000000..616b08cff33022ef +--- /dev/null ++++ b/support/support_ptrace.c +@@ -0,0 +1,44 @@ ++/* Support functions handling ptrace_scope. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++int ++support_ptrace_scope (void) ++{ ++ int ptrace_scope = -1; ++ ++#ifdef __linux__ ++ /* YAMA may be not enabled. Otherwise it contains a value from 0 to 3: ++ - 0 classic ptrace permissions ++ - 1 restricted ptrace ++ - 2 admin-only attach ++ - 3 no attach */ ++ FILE *f = fopen ("/proc/sys/kernel/yama/ptrace_scope", "r"); ++ if (f != NULL) ++ { ++ TEST_COMPARE (fscanf (f, "%d", &ptrace_scope), 1); ++ xfclose (f); ++ } ++#endif ++ ++ return ptrace_scope; ++} +diff --git a/support/xptrace.h b/support/xptrace.h +new file mode 100644 +index 0000000000000000..7af892680578fffd +--- /dev/null ++++ b/support/xptrace.h +@@ -0,0 +1,32 @@ ++/* Support functions handling ptrace_scope. ++ 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 ++ . */ ++ ++#ifndef SUPPORT_PTRACE_H ++#define SUPPORT_PTRACE_H ++ ++#include ++ ++__BEGIN_DECLS ++ ++/* Return the current YAMA mode set on the machine (0 to 3) or -1 ++ if YAMA is not supported. */ ++int support_ptrace_scope (void); ++ ++__END_DECLS ++ ++#endif diff --git a/glibc-rh1817513-33.patch b/glibc-rh1817513-33.patch new file mode 100755 index 0000000..db77728 --- /dev/null +++ b/glibc-rh1817513-33.patch @@ -0,0 +1,29 @@ +commit 64fab3633aecc8eadc1338aa8953f8b2f37e3ebf +Author: Stefan Liebler +Date: Thu Sep 19 12:26:18 2019 +0200 + + Fix building support_ptrace.c on i686-gnu. + + On i686-gnu the build is broken: + In file included from support_ptrace.c:22: + ../include/sys/prctl.h:2:15: fatal error: sys/prctl.h: No such file or directory + #include_next + + This patch just removes the unused prctl.h inclusion. + + ChangeLog: + + * support/support_ptrace.c: Remove inclusion of sys/prctl.h. + +diff --git a/support/support_ptrace.c b/support/support_ptrace.c +index 616b08cff33022ef..a733adf2c8dfd073 100644 +--- a/support/support_ptrace.c ++++ b/support/support_ptrace.c +@@ -19,7 +19,6 @@ + #include + #include + #include +-#include + + int + support_ptrace_scope (void) diff --git a/glibc-rh1817513-34.patch b/glibc-rh1817513-34.patch new file mode 100755 index 0000000..1d8b561 --- /dev/null +++ b/glibc-rh1817513-34.patch @@ -0,0 +1,155 @@ +commit 4052fa22f69c0964bb42c0f13daa791617253de5 +Author: DJ Delorie +Date: Wed Oct 2 14:46:46 2019 -0400 + + Add wait-for-debugger test harness hooks + + If WAIT_FOR_DEBUGGER is set to a non-zero value in the environment, + any test that runs will print some useful gdb information and wait + for gdb to attach to it and clear the "wait_for_debugger" variable. + + Reviewed-by: Carlos O'Donell + +diff --git a/support/support_test_main.c b/support/support_test_main.c +index fa3c2e06dee5ae0f..def84d803928176b 100644 +--- a/support/support_test_main.c ++++ b/support/support_test_main.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -36,6 +37,8 @@ + #include + #include + ++#include ++ + static const struct option default_options[] = + { + TEST_DEFAULT_OPTIONS +@@ -176,10 +179,55 @@ signal_handler (int sig) + exit (1); + } + ++/* This must be volatile as it will be modified by the debugger. */ ++static volatile int wait_for_debugger = 0; ++ + /* Run test_function or test_function_argv. */ + static int + run_test_function (int argc, char **argv, const struct test_config *config) + { ++ const char *wfd = getenv("WAIT_FOR_DEBUGGER"); ++ if (wfd != NULL) ++ wait_for_debugger = atoi (wfd); ++ if (wait_for_debugger) ++ { ++ pid_t mypid; ++ FILE *gdb_script; ++ char *gdb_script_name; ++ int inside_container = 0; ++ ++ mypid = getpid(); ++ if (mypid < 3) ++ { ++ const char *outside_pid = getenv("PID_OUTSIDE_CONTAINER"); ++ if (outside_pid) ++ { ++ mypid = atoi (outside_pid); ++ inside_container = 1; ++ } ++ } ++ ++ gdb_script_name = (char *) xmalloc (strlen (argv[0]) + strlen (".gdb") + 1); ++ sprintf (gdb_script_name, "%s.gdb", argv[0]); ++ gdb_script = xfopen (gdb_script_name, "w"); ++ ++ fprintf (stderr, "Waiting for debugger, test process is pid %d\n", mypid); ++ fprintf (stderr, "gdb -x %s\n", gdb_script_name); ++ if (inside_container) ++ fprintf (gdb_script, "set sysroot %s/testroot.root\n", support_objdir_root); ++ fprintf (gdb_script, "file\n"); ++ fprintf (gdb_script, "file %s\n", argv[0]); ++ fprintf (gdb_script, "symbol-file %s\n", argv[0]); ++ fprintf (gdb_script, "exec-file %s\n", argv[0]); ++ fprintf (gdb_script, "attach %ld\n", (long int) mypid); ++ fprintf (gdb_script, "set wait_for_debugger = 0\n"); ++ fclose (gdb_script); ++ } ++ ++ /* Wait for the debugger to set wait_for_debugger to zero. */ ++ while (wait_for_debugger) ++ usleep (1000); ++ + if (config->test_function != NULL) + return config->test_function (); + else if (config->test_function_argv != NULL) +@@ -229,6 +277,11 @@ support_test_main (int argc, char **argv, const struct test_config *config) + unsigned int timeoutfactor = 1; + pid_t termpid; + ++ /* If we're debugging the test, we need to disable timeouts and use ++ the initial pid (esp if we're running inside a container). */ ++ if (getenv("WAIT_FOR_DEBUGGER") != NULL) ++ direct = 1; ++ + if (!config->no_mallopt) + { + /* Make uses of freed and uninitialized memory known. Do not +diff --git a/support/test-container.c b/support/test-container.c +index f0d9e3060e80bda5..6503cea90309b9b0 100644 +--- a/support/test-container.c ++++ b/support/test-container.c +@@ -676,6 +676,9 @@ main (int argc, char **argv) + char *so_base; + int do_postclean = 0; + ++ int pipes[2]; ++ char pid_buf[20]; ++ + uid_t original_uid; + gid_t original_gid; + /* If set, the test runs as root instead of the user running the testsuite. */ +@@ -999,6 +1002,11 @@ main (int argc, char **argv) + if (chdir (new_cwd_path) < 0) + FAIL_EXIT1 ("Can't cd to new %s - ", new_cwd_path); + ++ /* This is to pass the "outside" PID to the child, which will be PID ++ 1. */ ++ if (pipe2 (pipes, O_CLOEXEC) < 0) ++ FAIL_EXIT1 ("Can't create pid pipe"); ++ + /* To complete the containerization, we need to fork () at least + once. We can't exec, nor can we somehow link the new child to + our parent. So we run the child and propogate it's exit status +@@ -1010,6 +1018,12 @@ main (int argc, char **argv) + { + /* Parent. */ + int status; ++ ++ /* Send the child's "outside" pid to it. */ ++ write (pipes[1], &child, sizeof(child)); ++ close (pipes[0]); ++ close (pipes[1]); ++ + waitpid (child, &status, 0); + + if (WIFEXITED (status)) +@@ -1028,6 +1042,14 @@ main (int argc, char **argv) + /* The rest is the child process, which is now PID 1 and "in" the + new root. */ + ++ /* Get our "outside" pid from our parent. We use this to help with ++ debugging from outside the container. */ ++ read (pipes[0], &child, sizeof(child)); ++ close (pipes[0]); ++ close (pipes[1]); ++ sprintf (pid_buf, "%lu", (long unsigned)child); ++ setenv ("PID_OUTSIDE_CONTAINER", pid_buf, 0); ++ + maybe_xmkdir ("/tmp", 0755); + + /* Now that we're pid 1 (effectively "root") we can mount /proc */ diff --git a/glibc-rh1817513-35.patch b/glibc-rh1817513-35.patch new file mode 100755 index 0000000..4cea796 --- /dev/null +++ b/glibc-rh1817513-35.patch @@ -0,0 +1,421 @@ +commit c7bf5ceab6ec776ac7350d3b0190776bf532ac54 +Author: Florian Weimer +Date: Sat Nov 2 21:55:35 2019 +0100 + + Properly initialize audit cookie for the dynamic loader [BZ #25157] + + The l_audit array is indexed by audit module, not audit function. + + Change-Id: I180eb3573dc1c57433750f5d8cb18271460ba5f2 + +Conflicts: + elf/Makefile + (Test backport differences.) + +diff --git a/elf/Makefile b/elf/Makefile +index 4e1356b9172aee02..4ab73dc48d9ac126 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -192,7 +192,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \ + tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \ + tst-audit13 \ +- tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail \ ++ tst-sonamemove-link tst-sonamemove-dlopen \ ++ tst-auditmany tst-initfinilazyfail \ + tst-dlopenfail tst-dlopenfail-2 \ + tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen + # reldep9 +@@ -303,6 +304,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-absolute-zero-lib tst-big-note-lib \ + tst-audit13mod1 tst-sonamemove-linkmod1 \ + tst-sonamemove-runmod1 tst-sonamemove-runmod2 \ ++ tst-auditmanymod1 tst-auditmanymod2 tst-auditmanymod3 \ ++ tst-auditmanymod4 tst-auditmanymod5 tst-auditmanymod6 \ ++ tst-auditmanymod7 tst-auditmanymod8 tst-auditmanymod9 \ + tst-initlazyfailmod tst-finilazyfailmod \ + tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \ + tst-dlopenfailmod3 \ +@@ -1433,6 +1437,14 @@ $(objpfx)tst-audit13.out: $(objpfx)tst-audit13mod1.so + LDFLAGS-tst-audit13mod1.so = -Wl,-z,lazy + tst-audit13-ENV = LD_AUDIT=$(objpfx)tst-audit13mod1.so + ++$(objpfx)tst-auditmany.out: $(objpfx)tst-auditmanymod1.so \ ++ $(objpfx)tst-auditmanymod2.so $(objpfx)tst-auditmanymod3.so \ ++ $(objpfx)tst-auditmanymod4.so $(objpfx)tst-auditmanymod5.so \ ++ $(objpfx)tst-auditmanymod6.so $(objpfx)tst-auditmanymod7.so \ ++ $(objpfx)tst-auditmanymod8.so $(objpfx)tst-auditmanymod9.so ++tst-auditmany-ENV = \ ++ LD_AUDIT=tst-auditmanymod1.so:tst-auditmanymod2.so:tst-auditmanymod3.so:tst-auditmanymod4.so:tst-auditmanymod5.so:tst-auditmanymod6.so:tst-auditmanymod7.so:tst-auditmanymod8.so:tst-auditmanymod9.so ++ + # tst-sonamemove links against an older implementation of the library. + LDFLAGS-tst-sonamemove-linkmod1.so = \ + -Wl,--version-script=tst-sonamemove-linkmod1.map \ +diff --git a/elf/rtld.c b/elf/rtld.c +index ffbd8f4553bb3425..f557f39a70669c09 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1008,13 +1008,7 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d); + + /* Store the pointer. */ + if (err_str == NULL && largs.result != NULL) +- { +- newp->fptr[cnt] = largs.result; +- +- /* The dynamic linker link map is statically allocated, +- initialize the data now. */ +- GL(dl_rtld_map).l_audit[cnt].cookie = (intptr_t) &GL(dl_rtld_map); +- } ++ newp->fptr[cnt] = largs.result; + else + newp->fptr[cnt] = NULL; + ++cnt; +@@ -1030,6 +1024,12 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d); + *last_audit = GLRO(dl_audit) = &newp->ifaces; + else + *last_audit = (*last_audit)->next = &newp->ifaces; ++ ++ /* The dynamic linker link map is statically allocated, initialize ++ the data now. */ ++ GL (dl_rtld_map).l_audit[GLRO (dl_naudit)].cookie ++ = (intptr_t) &GL (dl_rtld_map); ++ + ++GLRO(dl_naudit); + + /* Mark the DSO as being used for auditing. */ +diff --git a/elf/tst-auditmany.c b/elf/tst-auditmany.c +new file mode 100644 +index 0000000000000000..9d68105b9e707b46 +--- /dev/null ++++ b/elf/tst-auditmany.c +@@ -0,0 +1,26 @@ ++/* Check cookie initialization for many auditors. Main 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 ++ . */ ++ ++/* It does not make sense to use the test harness for this test ++ because the testing happens in auditors. */ ++ ++int ++main (void) ++{ ++ return 0; ++} +diff --git a/elf/tst-auditmanymod.h b/elf/tst-auditmanymod.h +new file mode 100644 +index 0000000000000000..d1d89e08431ce32f +--- /dev/null ++++ b/elf/tst-auditmanymod.h +@@ -0,0 +1,64 @@ ++/* Check cookie initialization for many auditors. Auditor template. ++ 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 ++ . */ ++ ++/* The macro MOD must be defined to the number of this auditor (an ++ integer) before including this file. */ ++ ++#include ++#include ++#include ++ ++/* Error counter for delayed error reporting. */ ++static int errors; ++ ++unsigned int ++la_version (unsigned int version) ++{ ++ return version; ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, ++ uintptr_t *cookie) ++{ ++ struct link_map *cookie_map = (struct link_map *) *cookie; ++ printf ("info: %d, la_objopen: map=%p name=%s cookie=%p:%p diff=%td\n", ++ MOD, map, map->l_name, cookie, cookie_map, ++ (char *) cookie - (char *) map); ++ fflush (stdout); ++ if (map != cookie_map) ++ { ++ printf ("error: %d, la_objopen:" ++ " map address does not match cookie value\n", ++ MOD); ++ fflush (stdout); ++ ++errors; ++ } ++ return 0; ++} ++ ++extern unsigned int ++la_objclose (uintptr_t *__cookie) ++{ ++ if (errors != 0) ++ { ++ printf ("error: exiting due to previous errors"); ++ _exit (1); ++ } ++ return 0; ++} +diff --git a/elf/tst-auditmanymod1.c b/elf/tst-auditmanymod1.c +new file mode 100644 +index 0000000000000000..c7de49d446a7e52d +--- /dev/null ++++ b/elf/tst-auditmanymod1.c +@@ -0,0 +1,20 @@ ++/* Check cookie initialization for many auditors. Auditor 1. ++ 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 ++ . */ ++ ++#define MOD 1 ++#include "tst-auditmanymod.h" +diff --git a/elf/tst-auditmanymod2.c b/elf/tst-auditmanymod2.c +new file mode 100644 +index 0000000000000000..4254f022a177b844 +--- /dev/null ++++ b/elf/tst-auditmanymod2.c +@@ -0,0 +1,20 @@ ++/* Check cookie initialization for many auditors. Auditor 2. ++ 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 ++ . */ ++ ++#define MOD 2 ++#include "tst-auditmanymod.h" +diff --git a/elf/tst-auditmanymod3.c b/elf/tst-auditmanymod3.c +new file mode 100644 +index 0000000000000000..ee90f4eb3a5c1b35 +--- /dev/null ++++ b/elf/tst-auditmanymod3.c +@@ -0,0 +1,20 @@ ++/* Check cookie initialization for many auditors. Auditor 3. ++ 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 ++ . */ ++ ++#define MOD 3 ++#include "tst-auditmanymod.h" +diff --git a/elf/tst-auditmanymod4.c b/elf/tst-auditmanymod4.c +new file mode 100644 +index 0000000000000000..6379fa1d55014998 +--- /dev/null ++++ b/elf/tst-auditmanymod4.c +@@ -0,0 +1,20 @@ ++/* Check cookie initialization for many auditors. Auditor 4. ++ 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 ++ . */ ++ ++#define MOD 4 ++#include "tst-auditmanymod.h" +diff --git a/elf/tst-auditmanymod5.c b/elf/tst-auditmanymod5.c +new file mode 100644 +index 0000000000000000..17c0f617aa4d1893 +--- /dev/null ++++ b/elf/tst-auditmanymod5.c +@@ -0,0 +1,20 @@ ++/* Check cookie initialization for many auditors. Auditor 5. ++ 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 ++ . */ ++ ++#define MOD 5 ++#include "tst-auditmanymod.h" +diff --git a/elf/tst-auditmanymod6.c b/elf/tst-auditmanymod6.c +new file mode 100644 +index 0000000000000000..86bc6801a4454742 +--- /dev/null ++++ b/elf/tst-auditmanymod6.c +@@ -0,0 +1,20 @@ ++/* Check cookie initialization for many auditors. Auditor 6. ++ 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 ++ . */ ++ ++#define MOD 6 ++#include "tst-auditmanymod.h" +diff --git a/elf/tst-auditmanymod7.c b/elf/tst-auditmanymod7.c +new file mode 100644 +index 0000000000000000..92b0bf6006876dff +--- /dev/null ++++ b/elf/tst-auditmanymod7.c +@@ -0,0 +1,20 @@ ++/* Check cookie initialization for many auditors. Auditor 7. ++ 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 ++ . */ ++ ++#define MOD 7 ++#include "tst-auditmanymod.h" +diff --git a/elf/tst-auditmanymod8.c b/elf/tst-auditmanymod8.c +new file mode 100644 +index 0000000000000000..d42f884d2f24f4c0 +--- /dev/null ++++ b/elf/tst-auditmanymod8.c +@@ -0,0 +1,20 @@ ++/* Check cookie initialization for many auditors. Auditor 8. ++ 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 ++ . */ ++ ++#define MOD 8 ++#include "tst-auditmanymod.h" +diff --git a/elf/tst-auditmanymod9.c b/elf/tst-auditmanymod9.c +new file mode 100644 +index 0000000000000000..6bee81d69c6d3c22 +--- /dev/null ++++ b/elf/tst-auditmanymod9.c +@@ -0,0 +1,20 @@ ++/* Check cookie initialization for many auditors. Auditor 9. ++ 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 ++ . */ ++ ++#define MOD 9 ++#include "tst-auditmanymod.h" diff --git a/glibc-rh1817513-36.patch b/glibc-rh1817513-36.patch new file mode 100755 index 0000000..a7ac8c7 --- /dev/null +++ b/glibc-rh1817513-36.patch @@ -0,0 +1,340 @@ +commit e1d559f337de2c8ab68a6749dfe873477c883807 +Author: Florian Weimer +Date: Sat Nov 2 20:04:02 2019 +0100 + + Introduce link_map_audit_state accessor function + + To improve GCC 10 compatibility, it is necessary to remove the l_audit + zero-length array from the end of struct link_map. In preparation of + that, this commit introduces an accessor function for the audit state, + so that it is possible to change the representation of the audit state + without adjusting the code that accesses it. + + Tested on x86_64-linux-gnu. Built on i686-gnu. + + Change-Id: Id815673c29950fc011ae5301d7cde12624f658df + +diff --git a/csu/libc-start.c b/csu/libc-start.c +index 494132368f8fe486..dfbf195328239a17 100644 +--- a/csu/libc-start.c ++++ b/csu/libc-start.c +@@ -272,7 +272,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + if (afct->preinit != NULL) +- afct->preinit (&head->l_audit[cnt].cookie); ++ afct->preinit (&link_map_audit_state (head, cnt)->cookie); + + afct = afct->next; + } +diff --git a/elf/dl-close.c b/elf/dl-close.c +index a9ecdff62dba88fb..1ece0ae1dd062d1e 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -305,8 +305,12 @@ _dl_close_worker (struct link_map *map, bool force) + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + if (afct->objclose != NULL) +- /* Return value is ignored. */ +- (void) afct->objclose (&imap->l_audit[cnt].cookie); ++ { ++ struct auditstate *state ++ = link_map_audit_state (imap, cnt); ++ /* Return value is ignored. */ ++ (void) afct->objclose (&state->cookie); ++ } + + afct = afct->next; + } +@@ -481,7 +485,10 @@ _dl_close_worker (struct link_map *map, bool force) + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + if (afct->activity != NULL) +- afct->activity (&head->l_audit[cnt].cookie, LA_ACT_DELETE); ++ { ++ struct auditstate *state = link_map_audit_state (head, cnt); ++ afct->activity (&state->cookie, LA_ACT_DELETE); ++ } + + afct = afct->next; + } +@@ -781,7 +788,10 @@ _dl_close_worker (struct link_map *map, bool force) + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + if (afct->activity != NULL) +- afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT); ++ { ++ struct auditstate *state = link_map_audit_state (head, cnt); ++ afct->activity (&state->cookie, LA_ACT_CONSISTENT); ++ } + + afct = afct->next; + } +diff --git a/elf/dl-fini.c b/elf/dl-fini.c +index 3cfc262400da4db9..915ceb104e1c81d6 100644 +--- a/elf/dl-fini.c ++++ b/elf/dl-fini.c +@@ -152,9 +152,12 @@ _dl_fini (void) + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + if (afct->objclose != NULL) +- /* Return value is ignored. */ +- (void) afct->objclose (&l->l_audit[cnt].cookie); +- ++ { ++ struct auditstate *state ++ = link_map_audit_state (l, cnt); ++ /* Return value is ignored. */ ++ (void) afct->objclose (&state->cookie); ++ } + afct = afct->next; + } + } +diff --git a/elf/dl-load.c b/elf/dl-load.c +index b190b28e32e47391..8f8869ff524ab9f2 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -979,7 +979,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + if (afct->activity != NULL) +- afct->activity (&head->l_audit[cnt].cookie, LA_ACT_ADD); ++ afct->activity (&link_map_audit_state (head, cnt)->cookie, ++ LA_ACT_ADD); + + afct = afct->next; + } +@@ -1418,10 +1419,9 @@ cannot enable executable stack as shared object requires"); + { + if (afct->objopen != NULL) + { +- l->l_audit[cnt].bindflags +- = afct->objopen (l, nsid, &l->l_audit[cnt].cookie); +- +- l->l_audit_any_plt |= l->l_audit[cnt].bindflags != 0; ++ struct auditstate *state = link_map_audit_state (l, cnt); ++ state->bindflags = afct->objopen (l, nsid, &state->cookie); ++ l->l_audit_any_plt |= state->bindflags != 0; + } + + afct = afct->next; +@@ -1527,8 +1527,8 @@ open_verify (const char *name, int fd, + { + if (afct->objsearch != NULL) + { +- name = afct->objsearch (name, &loader->l_audit[cnt].cookie, +- whatcode); ++ struct auditstate *state = link_map_audit_state (loader, cnt); ++ name = afct->objsearch (name, &state->cookie, whatcode); + if (name == NULL) + /* Ignore the path. */ + return -1; +@@ -1998,8 +1998,8 @@ _dl_map_object (struct link_map *loader, const char *name, + if (afct->objsearch != NULL) + { + const char *before = name; +- name = afct->objsearch (name, &loader->l_audit[cnt].cookie, +- LA_SER_ORIG); ++ struct auditstate *state = link_map_audit_state (loader, cnt); ++ name = afct->objsearch (name, &state->cookie, LA_SER_ORIG); + if (name == NULL) + { + /* Do not try anything further. */ +diff --git a/elf/dl-object.c b/elf/dl-object.c +index f6544a8fec45bdce..05a7750c65305771 100644 +--- a/elf/dl-object.c ++++ b/elf/dl-object.c +@@ -81,7 +81,7 @@ _dl_new_object (char *realname, const char *libname, int type, + struct link_map *new; + struct libname_list *newname; + #ifdef SHARED +- size_t audit_space = naudit * sizeof (new->l_audit[0]); ++ size_t audit_space = naudit * sizeof (struct auditstate); + #else + # define audit_space 0 + #endif +@@ -134,10 +134,8 @@ _dl_new_object (char *realname, const char *libname, int type, + + #ifdef SHARED + for (unsigned int cnt = 0; cnt < naudit; ++cnt) +- { +- new->l_audit[cnt].cookie = (uintptr_t) new; +- /* new->l_audit[cnt].bindflags = 0; */ +- } ++ /* No need to initialize bindflags due to calloc. */ ++ link_map_audit_state (new, cnt)->cookie = (uintptr_t) new; + #endif + + /* new->l_global = 0; We use calloc therefore not necessary. */ +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 46a4c1e5a3f8d2dd..7113c4a04f0fddbc 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -589,7 +589,10 @@ dl_open_worker (void *a) + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + if (afct->activity != NULL) +- afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT); ++ { ++ struct auditstate *state = link_map_audit_state (head, cnt); ++ afct->activity (&state->cookie, LA_ACT_CONSISTENT); ++ } + + afct = afct->next; + } +diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c +index 3d2f4a7a76e616e3..72b03e000dcf190e 100644 +--- a/elf/dl-runtime.c ++++ b/elf/dl-runtime.c +@@ -325,15 +325,18 @@ _dl_profile_fixup ( + { + /* XXX Check whether both DSOs must request action or + only one */ +- if ((l->l_audit[cnt].bindflags & LA_FLG_BINDFROM) != 0 +- && (result->l_audit[cnt].bindflags & LA_FLG_BINDTO) != 0) ++ struct auditstate *l_state = link_map_audit_state (l, cnt); ++ struct auditstate *result_state ++ = link_map_audit_state (result, cnt); ++ if ((l_state->bindflags & LA_FLG_BINDFROM) != 0 ++ && (result_state->bindflags & LA_FLG_BINDTO) != 0) + { + if (afct->symbind != NULL) + { + uintptr_t new_value + = afct->symbind (&sym, reloc_result->boundndx, +- &l->l_audit[cnt].cookie, +- &result->l_audit[cnt].cookie, ++ &l_state->cookie, ++ &result_state->cookie, + &flags, + strtab2 + defsym->st_name); + if (new_value != (uintptr_t) sym.st_value) +@@ -421,10 +424,13 @@ _dl_profile_fixup ( + & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0) + { + long int new_framesize = -1; ++ struct auditstate *l_state = link_map_audit_state (l, cnt); ++ struct auditstate *bound_state ++ = link_map_audit_state (reloc_result->bound, cnt); + uintptr_t new_value + = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx, +- &l->l_audit[cnt].cookie, +- &reloc_result->bound->l_audit[cnt].cookie, ++ &l_state->cookie, ++ &bound_state->cookie, + regs, &flags, symname, + &new_framesize); + if (new_value != (uintptr_t) sym.st_value) +@@ -504,9 +510,11 @@ _dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg, + && (reloc_result->enterexit + & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0) + { ++ struct auditstate *l_state = link_map_audit_state (l, cnt); ++ struct auditstate *bound_state ++ = link_map_audit_state (reloc_result->bound, cnt); + afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx, +- &l->l_audit[cnt].cookie, +- &reloc_result->bound->l_audit[cnt].cookie, ++ &l_state->cookie, &bound_state->cookie, + inregs, outregs, symname); + } + +diff --git a/elf/dl-sym.c b/elf/dl-sym.c +index 189628adc05aedf1..286cf7e27fd59f20 100644 +--- a/elf/dl-sym.c ++++ b/elf/dl-sym.c +@@ -198,17 +198,20 @@ RTLD_NEXT used in code not dynamically loaded")); + + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { ++ struct auditstate *match_audit ++ = link_map_audit_state (match, cnt); ++ struct auditstate *result_audit ++ = link_map_audit_state (result, cnt); + if (afct->symbind != NULL +- && ((match->l_audit[cnt].bindflags & LA_FLG_BINDFROM) +- != 0 +- || ((result->l_audit[cnt].bindflags & LA_FLG_BINDTO) ++ && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0 ++ || ((result_audit->bindflags & LA_FLG_BINDTO) + != 0))) + { + unsigned int flags = altvalue | LA_SYMB_DLSYM; + uintptr_t new_value + = afct->symbind (&sym, ndx, +- &match->l_audit[cnt].cookie, +- &result->l_audit[cnt].cookie, ++ &match_audit->cookie, ++ &result_audit->cookie, + &flags, strtab + ref->st_name); + if (new_value != (uintptr_t) sym.st_value) + { +diff --git a/elf/rtld.c b/elf/rtld.c +index f557f39a70669c09..18335bc666f2b89d 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1025,9 +1025,9 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d); + else + *last_audit = (*last_audit)->next = &newp->ifaces; + +- /* The dynamic linker link map is statically allocated, initialize +- the data now. */ +- GL (dl_rtld_map).l_audit[GLRO (dl_naudit)].cookie ++ /* The dynamic linker link map is statically allocated, so the ++ cookie in _dl_new_object has not happened. */ ++ link_map_audit_state (&GL (dl_rtld_map), GLRO (dl_naudit))->cookie + = (intptr_t) &GL (dl_rtld_map); + + ++GLRO(dl_naudit); +@@ -1046,9 +1046,9 @@ notify_audit_modules_of_loaded_object (struct link_map *map) + { + if (afct->objopen != NULL) + { +- map->l_audit[cnt].bindflags +- = afct->objopen (map, LM_ID_BASE, &map->l_audit[cnt].cookie); +- map->l_audit_any_plt |= map->l_audit[cnt].bindflags != 0; ++ struct auditstate *state = link_map_audit_state (map, cnt); ++ state->bindflags = afct->objopen (map, LM_ID_BASE, &state->cookie); ++ map->l_audit_any_plt |= state->bindflags != 0; + } + + afct = afct->next; +@@ -1660,7 +1660,8 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + if (afct->activity != NULL) +- afct->activity (&main_map->l_audit[cnt].cookie, LA_ACT_ADD); ++ afct->activity (&link_map_audit_state (main_map, cnt)->cookie, ++ LA_ACT_ADD); + + afct = afct->next; + } +@@ -2331,7 +2332,8 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + if (afct->activity != NULL) +- afct->activity (&head->l_audit[cnt].cookie, LA_ACT_CONSISTENT); ++ afct->activity (&link_map_audit_state (head, cnt)->cookie, ++ LA_ACT_CONSISTENT); + + afct = afct->next; + } +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 3bdbdd6e67dacc85..a8fb0d211426e4b1 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1197,7 +1197,13 @@ rtld_active (void) + initialized and active ld.so copy. */ + return GLRO(dl_init_all_dirs) != NULL; + } +-#endif ++ ++static inline struct auditstate * ++link_map_audit_state (struct link_map *l, size_t index) ++{ ++ return &l->l_audit[index]; ++} ++#endif /* SHARED */ + + __END_DECLS + diff --git a/glibc-rh1817513-37.patch b/glibc-rh1817513-37.patch new file mode 100755 index 0000000..33008bf --- /dev/null +++ b/glibc-rh1817513-37.patch @@ -0,0 +1,80 @@ +commit 4a2ab5843a5cc4a5db1b3b79916a520ea8b115dc +Author: Florian Weimer +Date: Fri Nov 8 15:48:51 2019 +0100 + + dlsym: Do not determine caller link map if not needed + + Obtaining the link map is potentially very slow because it requires + iterating over all loaded objects in the current implementation. If + the caller supplied an explicit handle (i.e., not one of the RTLD_* + constants), the dlsym implementation does not need the identity of the + caller (except in the special case of auditing), so this change + avoids computing it in that case. + + Even in the minimal case (dlsym called from a main program linked with + -dl), this shows a small speedup, perhaps around five percent. The + performance improvement can be arbitrarily large in principle (if + _dl_find_dso_for_object has to iterate over many link maps). + + Change-Id: Ide5d9e2cc7ac25a0ffae8fb4c26def0c898efa29 + +diff --git a/elf/dl-sym.c b/elf/dl-sym.c +index 286cf7e27fd59f20..b133850a3c6657a4 100644 +--- a/elf/dl-sym.c ++++ b/elf/dl-sym.c +@@ -80,6 +80,18 @@ call_dl_lookup (void *ptr) + args->flags, NULL); + } + ++/* Return the link map containing the caller address. */ ++static inline struct link_map * ++find_caller_link_map (ElfW(Addr) caller) ++{ ++ struct link_map *l = _dl_find_dso_for_object (caller); ++ if (l != NULL) ++ return l; ++ else ++ /* If the address is not recognized the call comes from the main ++ program (we hope). */ ++ return GL(dl_ns)[LM_ID_BASE]._ns_loaded; ++} + + static void * + do_sym (void *handle, const char *name, void *who, +@@ -89,13 +101,13 @@ do_sym (void *handle, const char *name, void *who, + lookup_t result; + ElfW(Addr) caller = (ElfW(Addr)) who; + +- struct link_map *l = _dl_find_dso_for_object (caller); +- /* If the address is not recognized the call comes from the main +- program (we hope). */ +- struct link_map *match = l ? l : GL(dl_ns)[LM_ID_BASE]._ns_loaded; ++ /* Link map of the caller if needed. */ ++ struct link_map *match = NULL; + + if (handle == RTLD_DEFAULT) + { ++ match = find_caller_link_map (caller); ++ + /* Search the global scope. We have the simple case where + we look up in the scope of an object which was part of + the initial binary. And then the more complex part +@@ -128,6 +140,8 @@ do_sym (void *handle, const char *name, void *who, + } + else if (handle == RTLD_NEXT) + { ++ match = find_caller_link_map (caller); ++ + if (__glibc_unlikely (match == GL(dl_ns)[LM_ID_BASE]._ns_loaded)) + { + if (match == NULL +@@ -187,6 +201,9 @@ RTLD_NEXT used in code not dynamically loaded")); + unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result, + l_info[DT_SYMTAB])); + ++ if (match == NULL) ++ match = find_caller_link_map (caller); ++ + if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0) + { + unsigned int altvalue = 0; diff --git a/glibc-rh1817513-38.patch b/glibc-rh1817513-38.patch new file mode 100755 index 0000000..4700cf4 --- /dev/null +++ b/glibc-rh1817513-38.patch @@ -0,0 +1,211 @@ +commit 4f79b3e2fb3eba003240ec38a0e68702b9a60b86 +Author: DJ Delorie +Date: Mon Feb 3 14:49:25 2020 -0500 + + test-container: add exec, cwd + + exec [optional_argv_0] + + copies test binary to specified location and runs it from + there. If the second argument is provided, that will + be used for argv[0] + + cwd + + attempts to chdir(directory) before running test + + Note: "cwd" not "cd" as it takes effect just before the + test binary runs, not when it's encountered in the script, + so it can't be used as a path shortcut like "cd" would imply. + + cleanup: use xstrdup() instead of strdup() + + Reviewed-by: Carlos O'Donell + +diff --git a/support/test-container.c b/support/test-container.c +index 6503cea90309b9b0..9488ec7b4a824380 100644 +--- a/support/test-container.c ++++ b/support/test-container.c +@@ -95,6 +95,8 @@ int verbose = 0; + mv FILE FILE + cp FILE FILE + rm FILE ++ cwd PATH ++ exec FILE + FILE must start with $B/, $S/, $I/, $L/, or / + (expands to build dir, source dir, install dir, library dir + (in container), or container's root) +@@ -104,6 +106,8 @@ int verbose = 0; + - 'mv': A minimal move files command. + - 'cp': A minimal copy files command. + - 'rm': A minimal remove files command. ++ - 'cwd': set test working directory ++ - 'exec': change test binary location (may end in /) + * mytest.root/postclean.req causes fresh rsync (with delete) after + test if present + +@@ -147,7 +151,7 @@ maybe_xmkdir (const char *path, mode_t mode) + } + + /* Temporarily concatenate multiple strings into one. Allows up to 10 +- temporary results; use strdup () if you need them to be ++ temporary results; use xstrdup () if you need them to be + permanent. */ + static char * + concat (const char *str, ...) +@@ -670,11 +674,13 @@ main (int argc, char **argv) + char *new_objdir_path; + char *new_srcdir_path; + char **new_child_proc; ++ char *new_child_exec; + char *command_root; + char *command_base; + char *command_basename; + char *so_base; + int do_postclean = 0; ++ char *change_cwd = NULL; + + int pipes[2]; + char pid_buf[20]; +@@ -701,7 +707,7 @@ main (int argc, char **argv) + + if (argc < 2) + { +- fprintf (stderr, "Usage: containerize \n"); ++ fprintf (stderr, "Usage: test-container \n"); + exit (1); + } + +@@ -746,12 +752,13 @@ main (int argc, char **argv) + } + } + +- pristine_root_path = strdup (concat (support_objdir_root, ++ pristine_root_path = xstrdup (concat (support_objdir_root, + "/testroot.pristine", NULL)); +- new_root_path = strdup (concat (support_objdir_root, ++ new_root_path = xstrdup (concat (support_objdir_root, + "/testroot.root", NULL)); + new_cwd_path = get_current_dir_name (); + new_child_proc = argv + 1; ++ new_child_exec = argv[1]; + + lock_fd = open (concat (pristine_root_path, "/lock.fd", NULL), + O_CREAT | O_TRUNC | O_RDWR, 0666); +@@ -778,10 +785,10 @@ main (int argc, char **argv) + command_root = concat (support_srcdir_root, + argv[1] + strlen (support_objdir_root), + ".root", NULL); +- command_root = strdup (command_root); ++ command_root = xstrdup (command_root); + + /* This cuts off the ".root" we appended above. */ +- command_base = strdup (command_root); ++ command_base = xstrdup (command_root); + command_base[strlen (command_base) - 5] = 0; + + /* This is the basename of the test we're running. */ +@@ -792,7 +799,7 @@ main (int argc, char **argv) + ++command_basename; + + /* Shared object base directory. */ +- so_base = strdup (argv[1]); ++ so_base = xstrdup (argv[1]); + if (strrchr (so_base, '/') != NULL) + strrchr (so_base, '/')[1] = 0; + +@@ -806,9 +813,9 @@ main (int argc, char **argv) + && S_ISDIR (st.st_mode)) + rsync (command_root, new_root_path, 0); + +- new_objdir_path = strdup (concat (new_root_path, ++ new_objdir_path = xstrdup (concat (new_root_path, + support_objdir_root, NULL)); +- new_srcdir_path = strdup (concat (new_root_path, ++ new_srcdir_path = xstrdup (concat (new_root_path, + support_srcdir_root, NULL)); + + /* new_cwd_path starts with '/' so no "/" needed between the two. */ +@@ -868,7 +875,10 @@ main (int argc, char **argv) + the_words[i] = concat (new_root_path, + support_libdir_prefix, + the_words[i] + 2, NULL); +- else if (the_words[i][0] == '/') ++ /* "exec" and "cwd" use inside-root paths. */ ++ else if (strcmp (the_words[0], "exec") != 0 ++ && strcmp (the_words[0], "cwd") != 0 ++ && the_words[i][0] == '/') + the_words[i] = concat (new_root_path, + the_words[i], NULL); + } +@@ -912,13 +922,49 @@ main (int argc, char **argv) + { + maybe_xunlink (the_words[1]); + } ++ else if (nt >= 2 && strcmp (the_words[0], "exec") == 0) ++ { ++ /* The first argument is the desired location and name ++ of the test binary as we wish to exec it; we will ++ copy the binary there. The second (optional) ++ argument is the value to pass as argv[0], it ++ defaults to the same as the first argument. */ ++ char *new_exec_path = the_words[1]; ++ ++ /* If the new exec path ends with a slash, that's the ++ * directory, and use the old test base name. */ ++ if (new_exec_path [strlen(new_exec_path) - 1] == '/') ++ new_exec_path = concat (new_exec_path, ++ basename (new_child_proc[0]), ++ NULL); ++ ++ ++ /* new_child_proc is in the build tree, so has the ++ same path inside the chroot as outside. The new ++ exec path is, by definition, relative to the ++ chroot. */ ++ copy_one_file (new_child_proc[0], concat (new_root_path, ++ new_exec_path, ++ NULL)); ++ ++ new_child_exec = xstrdup (new_exec_path); ++ if (the_words[2]) ++ new_child_proc[0] = xstrdup (the_words[2]); ++ else ++ new_child_proc[0] = new_child_exec; ++ } ++ else if (nt == 2 && strcmp (the_words[0], "cwd") == 0) ++ { ++ change_cwd = xstrdup (the_words[1]); ++ } + else if (nt == 1 && strcmp (the_words[0], "su") == 0) + { + be_su = 1; + } + else if (nt > 0 && the_words[0][0] != '#') + { +- printf ("\033[31minvalid [%s]\033[0m\n", the_words[0]); ++ fprintf (stderr, "\033[31minvalid [%s]\033[0m\n", the_words[0]); ++ exit (1); + } + } + fclose (f); +@@ -1089,11 +1135,17 @@ main (int argc, char **argv) + write (GMAP, tmp, strlen (tmp)); + xclose (GMAP); + ++ if (change_cwd) ++ { ++ if (chdir (change_cwd) < 0) ++ FAIL_EXIT1 ("Can't cd to %s inside container - ", change_cwd); ++ } ++ + /* Now run the child. */ +- execvp (new_child_proc[0], new_child_proc); ++ execvp (new_child_exec, new_child_proc); + + /* Or don't run the child? */ +- FAIL_EXIT1 ("Unable to exec %s\n", new_child_proc[0]); ++ FAIL_EXIT1 ("Unable to exec %s\n", new_child_exec); + + /* Because gcc won't know error () never returns... */ + exit (EXIT_UNSUPPORTED); diff --git a/glibc-rh1817513-39.patch b/glibc-rh1817513-39.patch new file mode 100755 index 0000000..d514b49 --- /dev/null +++ b/glibc-rh1817513-39.patch @@ -0,0 +1,50 @@ +commit abcc039d2e26b3c9c723d6419e086753a791b3d5 +Author: Florian Weimer +Date: Fri Feb 7 20:06:32 2020 +0100 + + elf: Introduce the rtld-stubbed-symbols makefile variable + + This generalizes a mechanism used for stack-protector support, so + that it can be applied to other symbols if required. + + Reviewed-by: Carlos O'Donell + +diff --git a/elf/Makefile b/elf/Makefile +index 4ab73dc48d9ac126..a1ea44f231d8cec5 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -474,21 +474,25 @@ $(objpfx)dl-allobjs.os: $(all-rtld-routines:%=$(objpfx)%.os) + # are compiled with special flags, and puts these modules into rtld-libc.a + # for us. Then we do the real link using rtld-libc.a instead of libc_pic.a. + +-# If the compiler can do SSP, build the mapfile with dummy __stack_chk_fail +-# and __stack_chk_fail_local symbols defined, to prevent the real things +-# being dragged into rtld even though rtld is never built with stack- +-# protection. ++# These symbols need to be stubbed out during symbol discovery because ++# their implementation is provided differently in rtld, and the symbol ++# discovery mechanism is not compatible with the libc implementation ++# when compiled for libc. ++rtld-stubbed-symbols = ++ ++# The GCC arguments that implement $(rtld-stubbed-symbols). ++rtld-stubbed-symbols-args = \ ++ $(patsubst %,-Wl$(comma)--defsym=%=0, $(rtld-stubbed-symbols)) + + ifeq ($(have-ssp),yes) +-dummy-stack-chk-fail := -Wl,--defsym='__stack_chk_fail=0' \ +- -Wl,--defsym='__stack_chk_fail_local=0' +-else +-dummy-stack-chk-fail := ++# rtld is not built with the stack protector, so these references will ++# go away in the rebuilds. ++rtld-stubbed-symbols += __stack_chk_fail __stack_chk_fail_local + endif + + $(objpfx)librtld.map: $(objpfx)dl-allobjs.os $(common-objpfx)libc_pic.a + @-rm -f $@T +- $(reloc-link) -o $@.o $(dummy-stack-chk-fail) \ ++ $(reloc-link) -o $@.o $(rtld-stubbed-symbols-args) \ + '-Wl,-(' $^ -lgcc '-Wl,-)' -Wl,-Map,$@T + rm -f $@.o + mv -f $@T $@ diff --git a/glibc-rh1817513-4.patch b/glibc-rh1817513-4.patch new file mode 100755 index 0000000..b3b1c74 --- /dev/null +++ b/glibc-rh1817513-4.patch @@ -0,0 +1,64 @@ +commit 430388d5dc0e1861b869096f4f5d946d7d74232a +Author: H.J. Lu +Date: Fri Aug 3 08:04:49 2018 -0700 + + x86: Don't include in assembly codes + + There is no need to include in assembly codes since all + x86 IFUNC selector functions are written in C. Tested on i686 and + x86-64. There is no code change in libc.so, ld.so and libmvec.so. + + * sysdeps/i386/i686/multiarch/bzero-ia32.S: Don't include + . + * sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core-avx2.S: Likewise. + * sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core-avx2.S: Likewise. + * sysdeps/x86_64/multiarch/memset-sse2-unaligned-erms.S: Likewise. + +diff --git a/sysdeps/i386/i686/multiarch/bzero-ia32.S b/sysdeps/i386/i686/multiarch/bzero-ia32.S +index 68ff9e1e903f7c4c..94d13e88f7532bc0 100644 +--- a/sysdeps/i386/i686/multiarch/bzero-ia32.S ++++ b/sysdeps/i386/i686/multiarch/bzero-ia32.S +@@ -17,7 +17,6 @@ + . */ + + #include +-#include + + #if IS_IN (libc) + # define __bzero __bzero_ia32 +diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core-avx2.S b/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core-avx2.S +index b64c3390d6169d18..87536a06a3ed54c6 100644 +--- a/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core-avx2.S ++++ b/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core-avx2.S +@@ -17,7 +17,6 @@ + . */ + + #include +-#include + + #define _ZGVeN8v_sin _ZGVeN8v_sin_avx2_wrapper + #include "../svml_d_sin8_core.S" +diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core-avx2.S b/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core-avx2.S +index e0b7fd787fa6428d..16713ba7142ecad6 100644 +--- a/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core-avx2.S ++++ b/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core-avx2.S +@@ -17,7 +17,6 @@ + . */ + + #include +-#include + + #define _ZGVeN16v_expf _ZGVeN16v_expf_avx2_wrapper + #include "../svml_s_expf16_core.S" +diff --git a/sysdeps/x86_64/multiarch/memset-sse2-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-sse2-unaligned-erms.S +index be6671759beaaa84..56b81f5cc5288808 100644 +--- a/sysdeps/x86_64/multiarch/memset-sse2-unaligned-erms.S ++++ b/sysdeps/x86_64/multiarch/memset-sse2-unaligned-erms.S +@@ -19,7 +19,6 @@ + + #include + #include +-#include + + #if IS_IN (libc) + # define MEMSET_SYMBOL(p,s) p##_sse2_##s diff --git a/glibc-rh1817513-40.patch b/glibc-rh1817513-40.patch new file mode 100755 index 0000000..d30002b --- /dev/null +++ b/glibc-rh1817513-40.patch @@ -0,0 +1,248 @@ +commit c76147afe917ef7d309ee893f8f017a3c2934aac +Author: Florian Weimer +Date: Sat Feb 8 15:00:28 2020 +0100 + + elf: Extract _dl_sym_post, _dl_sym_find_caller_map from elf/dl-sym.c + + The definitions are moved into a new file, elf/dl-sym-post.h, so that + this code can be used by the dynamic loader as well. + + Reviewed-by: Carlos O'Donell + +diff --git a/elf/dl-sym-post.h b/elf/dl-sym-post.h +new file mode 100644 +index 0000000000000000..4c4f574633497789 +--- /dev/null ++++ b/elf/dl-sym-post.h +@@ -0,0 +1,106 @@ ++/* Post-processing of a symbol produced by dlsym, dlvsym. ++ Copyright (C) 1999-2020 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 ++ . */ ++ ++ ++/* Return the link map containing the caller address. */ ++static struct link_map * ++_dl_sym_find_caller_link_map (ElfW(Addr) caller) ++{ ++ struct link_map *l = _dl_find_dso_for_object (caller); ++ if (l != NULL) ++ return l; ++ else ++ /* If the address is not recognized the call comes from the main ++ program (we hope). */ ++ return GL(dl_ns)[LM_ID_BASE]._ns_loaded; ++} ++ ++/* Translates RESULT, *REF, VALUE into a symbol address from the point ++ of view of MATCH. Performs IFUNC resolution and auditing if ++ necessary. If MATCH is NULL, CALLER is used to determine it. */ ++static void * ++_dl_sym_post (lookup_t result, const ElfW(Sym) *ref, void *value, ++ ElfW(Addr) caller, struct link_map *match) ++{ ++ /* Resolve indirect function address. */ ++ if (__glibc_unlikely (ELFW(ST_TYPE) (ref->st_info) == STT_GNU_IFUNC)) ++ { ++ DL_FIXUP_VALUE_TYPE fixup ++ = DL_FIXUP_MAKE_VALUE (result, (ElfW(Addr)) value); ++ fixup = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (fixup)); ++ value = (void *) DL_FIXUP_VALUE_CODE_ADDR (fixup); ++ } ++ ++#ifdef SHARED ++ /* Auditing checkpoint: we have a new binding. Provide the ++ auditing libraries the possibility to change the value and ++ tell us whether further auditing is wanted. */ ++ if (__glibc_unlikely (GLRO(dl_naudit) > 0)) ++ { ++ const char *strtab = (const char *) D_PTR (result, ++ l_info[DT_STRTAB]); ++ /* Compute index of the symbol entry in the symbol table of ++ the DSO with the definition. */ ++ unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result, ++ l_info[DT_SYMTAB])); ++ ++ if (match == NULL) ++ match = _dl_sym_find_caller_link_map (caller); ++ ++ if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0) ++ { ++ unsigned int altvalue = 0; ++ struct audit_ifaces *afct = GLRO(dl_audit); ++ /* Synthesize a symbol record where the st_value field is ++ the result. */ ++ ElfW(Sym) sym = *ref; ++ sym.st_value = (ElfW(Addr)) value; ++ ++ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ { ++ struct auditstate *match_audit ++ = link_map_audit_state (match, cnt); ++ struct auditstate *result_audit ++ = link_map_audit_state (result, cnt); ++ if (afct->symbind != NULL ++ && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0 ++ || ((result_audit->bindflags & LA_FLG_BINDTO) ++ != 0))) ++ { ++ unsigned int flags = altvalue | LA_SYMB_DLSYM; ++ uintptr_t new_value ++ = afct->symbind (&sym, ndx, ++ &match_audit->cookie, ++ &result_audit->cookie, ++ &flags, strtab + ref->st_name); ++ if (new_value != (uintptr_t) sym.st_value) ++ { ++ altvalue = LA_SYMB_ALTVALUE; ++ sym.st_value = new_value; ++ } ++ } ++ ++ afct = afct->next; ++ } ++ ++ value = (void *) sym.st_value; ++ } ++ } ++#endif ++ return value; ++} +diff --git a/elf/dl-sym.c b/elf/dl-sym.c +index b133850a3c6657a4..5698fd7874a0ce48 100644 +--- a/elf/dl-sym.c ++++ b/elf/dl-sym.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + + + #ifdef SHARED +@@ -80,19 +81,6 @@ call_dl_lookup (void *ptr) + args->flags, NULL); + } + +-/* Return the link map containing the caller address. */ +-static inline struct link_map * +-find_caller_link_map (ElfW(Addr) caller) +-{ +- struct link_map *l = _dl_find_dso_for_object (caller); +- if (l != NULL) +- return l; +- else +- /* If the address is not recognized the call comes from the main +- program (we hope). */ +- return GL(dl_ns)[LM_ID_BASE]._ns_loaded; +-} +- + static void * + do_sym (void *handle, const char *name, void *who, + struct r_found_version *vers, int flags) +@@ -106,7 +94,7 @@ do_sym (void *handle, const char *name, void *who, + + if (handle == RTLD_DEFAULT) + { +- match = find_caller_link_map (caller); ++ match = _dl_sym_find_caller_link_map (caller); + + /* Search the global scope. We have the simple case where + we look up in the scope of an object which was part of +@@ -140,7 +128,7 @@ do_sym (void *handle, const char *name, void *who, + } + else if (handle == RTLD_NEXT) + { +- match = find_caller_link_map (caller); ++ match = _dl_sym_find_caller_link_map (caller); + + if (__glibc_unlikely (match == GL(dl_ns)[LM_ID_BASE]._ns_loaded)) + { +@@ -179,73 +167,7 @@ RTLD_NEXT used in code not dynamically loaded")); + #endif + value = DL_SYMBOL_ADDRESS (result, ref); + +- /* Resolve indirect function address. */ +- if (__glibc_unlikely (ELFW(ST_TYPE) (ref->st_info) == STT_GNU_IFUNC)) +- { +- DL_FIXUP_VALUE_TYPE fixup +- = DL_FIXUP_MAKE_VALUE (result, (ElfW(Addr)) value); +- fixup = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (fixup)); +- value = (void *) DL_FIXUP_VALUE_CODE_ADDR (fixup); +- } +- +-#ifdef SHARED +- /* Auditing checkpoint: we have a new binding. Provide the +- auditing libraries the possibility to change the value and +- tell us whether further auditing is wanted. */ +- if (__glibc_unlikely (GLRO(dl_naudit) > 0)) +- { +- const char *strtab = (const char *) D_PTR (result, +- l_info[DT_STRTAB]); +- /* Compute index of the symbol entry in the symbol table of +- the DSO with the definition. */ +- unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result, +- l_info[DT_SYMTAB])); +- +- if (match == NULL) +- match = find_caller_link_map (caller); +- +- if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0) +- { +- unsigned int altvalue = 0; +- struct audit_ifaces *afct = GLRO(dl_audit); +- /* Synthesize a symbol record where the st_value field is +- the result. */ +- ElfW(Sym) sym = *ref; +- sym.st_value = (ElfW(Addr)) value; +- +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- struct auditstate *match_audit +- = link_map_audit_state (match, cnt); +- struct auditstate *result_audit +- = link_map_audit_state (result, cnt); +- if (afct->symbind != NULL +- && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0 +- || ((result_audit->bindflags & LA_FLG_BINDTO) +- != 0))) +- { +- unsigned int flags = altvalue | LA_SYMB_DLSYM; +- uintptr_t new_value +- = afct->symbind (&sym, ndx, +- &match_audit->cookie, +- &result_audit->cookie, +- &flags, strtab + ref->st_name); +- if (new_value != (uintptr_t) sym.st_value) +- { +- altvalue = LA_SYMB_ALTVALUE; +- sym.st_value = new_value; +- } +- } +- +- afct = afct->next; +- } +- +- value = (void *) sym.st_value; +- } +- } +-#endif +- +- return value; ++ return _dl_sym_post (result, ref, value, caller, match); + } + + return NULL; diff --git a/glibc-rh1817513-41.patch b/glibc-rh1817513-41.patch new file mode 100755 index 0000000..0c00b3a --- /dev/null +++ b/glibc-rh1817513-41.patch @@ -0,0 +1,1102 @@ +commit 3a0ecccb599a6b1ad4b149dc569c0080e92d057b +Author: Florian Weimer +Date: Sat Feb 8 19:58:43 2020 +0100 + + ld.so: Do not export free/calloc/malloc/realloc functions [BZ #25486] + + Exporting functions and relying on symbol interposition from libc.so + makes the choice of implementation dependent on DT_NEEDED order, which + is not what some compiler drivers expect. + + This commit replaces one magic mechanism (symbol interposition) with + another one (preprocessor-/compiler-based redirection). This makes + the hand-over from the minimal malloc to the full malloc more + explicit. + + Removing the ABI symbols is backwards-compatible because libc.so is + always in scope, and the dynamic loader will find the malloc-related + symbols there since commit f0b2132b35248c1f4a80f62a2c38cddcc802aa8c + ("ld.so: Support moving versioned symbols between sonames + [BZ #24741]"). + + Reviewed-by: Carlos O'Donell + +Conflicts: + sysdeps/unix/sysv/linux/arm/le/ld.abilist + sysdeps/unix/sysv/linux/sh/le/ld.abilist + (Missing abilist split.) + sysdeps/unix/sysv/linux/csky/ld.abilist + sysdeps/unix/sysv/linux/csky/localplt.data + (Missing architecture.) + +diff --git a/elf/Makefile b/elf/Makefile +index a1ea44f231d8cec5..5b0aeccb0a53c182 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -478,7 +478,11 @@ $(objpfx)dl-allobjs.os: $(all-rtld-routines:%=$(objpfx)%.os) + # their implementation is provided differently in rtld, and the symbol + # discovery mechanism is not compatible with the libc implementation + # when compiled for libc. +-rtld-stubbed-symbols = ++rtld-stubbed-symbols = \ ++ calloc \ ++ free \ ++ malloc \ ++ realloc \ + + # The GCC arguments that implement $(rtld-stubbed-symbols). + rtld-stubbed-symbols-args = \ +diff --git a/elf/Versions b/elf/Versions +index 3b09901f6c31e3d4..705489fc51f4ac5f 100644 +--- a/elf/Versions ++++ b/elf/Versions +@@ -35,9 +35,6 @@ libc { + + ld { + GLIBC_2.0 { +- # Functions which are interposed from libc.so. +- calloc; free; malloc; realloc; +- + _r_debug; + } + GLIBC_2.1 { +diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c +index 42fdaed99296137f..e4c479de9a1fd6ec 100644 +--- a/elf/dl-lookup.c ++++ b/elf/dl-lookup.c +@@ -291,7 +291,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash, + tab->size = newsize; + size = newsize; + entries = tab->entries = newentries; +- tab->free = free; ++ tab->free = __rtld_free; + } + } + else +@@ -322,7 +322,7 @@ do_lookup_unique (const char *undef_name, uint_fast32_t new_hash, + + tab->entries = entries; + tab->size = size; +- tab->free = free; ++ tab->free = __rtld_free; + } + + if ((type_class & ELF_RTYPE_CLASS_COPY) != 0) +diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c +index 25ceded6fe120b07..95ea7b024044864f 100644 +--- a/elf/dl-minimal.c ++++ b/elf/dl-minimal.c +@@ -26,11 +26,87 @@ + #include + #include + #include ++#include ++#include ++#include + #include <_itoa.h> + #include + + #include + ++/* The rtld startup code calls __rtld_malloc_init_stubs after the ++ first self-relocation to adjust the pointers to the minimal ++ implementation below. Before the final relocation, ++ __rtld_malloc_init_real is called to replace the pointers with the ++ real implementation. */ ++__typeof (calloc) *__rtld_calloc; ++__typeof (free) *__rtld_free; ++__typeof (malloc) *__rtld_malloc; ++__typeof (realloc) *__rtld_realloc; ++ ++/* Defined below. */ ++static __typeof (calloc) rtld_calloc attribute_relro; ++static __typeof (free) rtld_free attribute_relro; ++static __typeof (malloc) rtld_malloc attribute_relro; ++static __typeof (realloc) rtld_realloc attribute_relro; ++ ++void ++__rtld_malloc_init_stubs (void) ++{ ++ __rtld_calloc = &rtld_calloc; ++ __rtld_free = &rtld_free; ++ __rtld_malloc = &rtld_malloc; ++ __rtld_realloc = &rtld_realloc; ++} ++ ++/* Lookup NAME at VERSION in the scope of MATCH. */ ++static void * ++lookup_malloc_symbol (struct link_map *main_map, const char *name, ++ struct r_found_version *version) ++{ ++ ++ const ElfW(Sym) *ref = NULL; ++ lookup_t result = _dl_lookup_symbol_x (name, main_map, &ref, ++ main_map->l_scope, ++ version, 0, 0, NULL); ++ ++ assert (ELFW(ST_TYPE) (ref->st_info) != STT_TLS); ++ void *value = DL_SYMBOL_ADDRESS (result, ref); ++ ++ return _dl_sym_post (result, ref, value, 0, main_map); ++} ++ ++void ++__rtld_malloc_init_real (struct link_map *main_map) ++{ ++ /* We cannot use relocations and initializers for this because the ++ changes made by __rtld_malloc_init_stubs break REL-style ++ (non-RELA) relocations that depend on the previous pointer ++ contents. Also avoid direct relocation depedencies for the ++ malloc symbols so this function can be called before the final ++ rtld relocation (which enables RELRO, after which the pointer ++ variables cannot be written to). */ ++ ++ struct r_found_version version; ++ version.name = symbol_version_string (libc, GLIBC_2_0); ++ version.hidden = 0; ++ version.hash = _dl_elf_hash (version.name); ++ version.filename = NULL; ++ ++ void *new_calloc = lookup_malloc_symbol (main_map, "calloc", &version); ++ void *new_free = lookup_malloc_symbol (main_map, "free", &version); ++ void *new_malloc = lookup_malloc_symbol (main_map, "malloc", &version); ++ void *new_realloc = lookup_malloc_symbol (main_map, "realloc", &version); ++ ++ /* Update the pointers in one go, so that any internal allocations ++ performed by lookup_malloc_symbol see a consistent ++ implementation. */ ++ __rtld_calloc = new_calloc; ++ __rtld_free = new_free; ++ __rtld_malloc = new_malloc; ++ __rtld_realloc = new_realloc; ++} ++ + /* Minimal malloc allocator for used during initial link. After the + initial link, a full malloc implementation is interposed, either + the one in libc, or a different one supplied by the user through +@@ -38,14 +114,9 @@ + + static void *alloc_ptr, *alloc_end, *alloc_last_block; + +-/* Declarations of global functions. */ +-extern void weak_function free (void *ptr); +-extern void * weak_function realloc (void *ptr, size_t n); +- +- + /* Allocate an aligned memory block. */ +-void * weak_function +-malloc (size_t n) ++static void * ++rtld_malloc (size_t n) + { + if (alloc_end == 0) + { +@@ -87,8 +158,8 @@ malloc (size_t n) + /* We use this function occasionally since the real implementation may + be optimized when it can assume the memory it returns already is + set to NUL. */ +-void * weak_function +-calloc (size_t nmemb, size_t size) ++static void * ++rtld_calloc (size_t nmemb, size_t size) + { + /* New memory from the trivial malloc above is always already cleared. + (We make sure that's true in the rare occasion it might not be, +@@ -104,8 +175,8 @@ calloc (size_t nmemb, size_t size) + } + + /* This will rarely be called. */ +-void weak_function +-free (void *ptr) ++void ++rtld_free (void *ptr) + { + /* We can free only the last block allocated. */ + if (ptr == alloc_last_block) +@@ -118,8 +189,8 @@ free (void *ptr) + } + + /* This is only called with the most recent block returned by malloc. */ +-void * weak_function +-realloc (void *ptr, size_t n) ++void * ++rtld_realloc (void *ptr, size_t n) + { + if (ptr == NULL) + return malloc (n); +diff --git a/elf/rtld.c b/elf/rtld.c +index 18335bc666f2b89d..f755dc30331f799f 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -532,6 +532,9 @@ _dl_start (void *arg) + header table in core. Put the rest of _dl_start into a separate + function, that way the compiler cannot put accesses to the GOT + before ELF_DYNAMIC_RELOCATE. */ ++ ++ __rtld_malloc_init_stubs (); ++ + { + #ifdef DONT_USE_BOOTSTRAP_MAP + ElfW(Addr) entry = _dl_start_final (arg); +@@ -2203,6 +2206,10 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + rtld_timer_stop (&relocate_time, start); + } + ++ /* The library defining malloc has already been relocated due to ++ prelinking. Resolve the malloc symbols for the dynamic ++ loader. */ ++ __rtld_malloc_init_real (main_map); + + /* Mark all the objects so we know they have been already relocated. */ + for (struct link_map *l = main_map; l != NULL; l = l->l_next) +@@ -2303,6 +2310,11 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + re-relocation, we might call a user-supplied function + (e.g. calloc from _dl_relocate_object) that uses TLS data. */ + ++ /* The malloc implementation has been relocated, so resolving ++ its symbols (and potentially calling IFUNC resolvers) is safe ++ at this point. */ ++ __rtld_malloc_init_real (main_map); ++ + RTLD_TIMING_VAR (start); + rtld_timer_start (&start); + +diff --git a/include/inline-hashtab.h b/include/inline-hashtab.h +index ad73650ecc59dec1..b658e4a54b9c8187 100644 +--- a/include/inline-hashtab.h ++++ b/include/inline-hashtab.h +@@ -53,7 +53,7 @@ htab_create (void) + return NULL; + ht->size = 3; + ht->entries = malloc (sizeof (void *) * ht->size); +- ht->free = free; ++ ht->free = __rtld_free; + if (! ht->entries) + { + if (ht->free) +@@ -172,7 +172,7 @@ htab_expand (struct hashtab *htab, int (*hash_fn) (void *)) + + /* Use the free() corresponding to the malloc() above to free this + up. */ +- htab->free = free; ++ htab->free = __rtld_free; + + return 1; + } +diff --git a/include/libc-symbols.h b/include/libc-symbols.h +index 8b9273c13a19f265..41436050d060b89f 100644 +--- a/include/libc-symbols.h ++++ b/include/libc-symbols.h +@@ -413,7 +413,14 @@ for linking") + # define _default_symbol_version(real, name, version) \ + __asm__ (".symver " #real "," #name "@@" #version) + # endif +-#else ++ ++/* Evalutes to a string literal for VERSION in LIB. */ ++# define symbol_version_string(lib, version) \ ++ _symbol_version_stringify_1 (VERSION_##lib##_##version) ++# define _symbol_version_stringify_1(arg) _symbol_version_stringify_2 (arg) ++# define _symbol_version_stringify_2(arg) #arg ++ ++#else /* !SHARED */ + # define symbol_version(real, name, version) + # define default_symbol_version(real, name, version) \ + strong_alias(real, name) +diff --git a/include/malloc.h b/include/malloc.h +index d4cd9a5ffc929a96..e528718ac0734e5e 100644 +--- a/include/malloc.h ++++ b/include/malloc.h +@@ -1,7 +1,9 @@ + #ifndef _MALLOC_H ++ + #include + + # ifndef _ISOMAC ++# include + + /* In the GNU libc we rename the global variable + `__malloc_initialized' to `__libc_malloc_initialized'. */ +diff --git a/include/rtld-malloc.h b/include/rtld-malloc.h +new file mode 100644 +index 0000000000000000..b026a3270cd24819 +--- /dev/null ++++ b/include/rtld-malloc.h +@@ -0,0 +1,85 @@ ++/* Redirection of malloc inside the dynamic linker. ++ Copyright (C) 2020 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 ++ . */ ++ ++/* The dynamic linker needs to use its own minimal malloc before libc ++ has been relocated, and the libc malloc afterwards. The active ++ malloc implementation is reached via the __rtld_* function pointers ++ declared below. They are initialized to the minimal malloc by ++ __rtld_malloc_init_stubs, and set to the final implementation by ++ __rtld_malloc_init_real. */ ++ ++#ifndef _RTLD_MALLOC_H ++#define _RTLD_MALLOC_H ++ ++#if IS_IN (rtld) ++ ++extern __typeof (calloc) *__rtld_calloc attribute_hidden; ++extern __typeof (free) *__rtld_free attribute_hidden; ++extern __typeof (malloc) *__rtld_malloc attribute_hidden; ++extern __typeof (realloc) *__rtld_realloc attribute_hidden; ++ ++/* Wrapper functions which call through the function pointers above. ++ Note that it is not supported to take the address of those ++ functions. Instead the function pointers must be used ++ directly. */ ++ ++__extern_inline void * ++calloc (size_t a, size_t b) ++{ ++ return __rtld_calloc (a, b); ++} ++ ++__extern_inline void ++free (void *ptr) ++{ ++ __rtld_free (ptr); ++} ++ ++__extern_inline void * ++malloc (size_t size) ++{ ++ return __rtld_malloc (size); ++} ++ ++__extern_inline void * ++realloc (void *ptr, size_t size) ++{ ++ return __rtld_realloc (ptr, size); ++} ++ ++/* Called after the first self-relocation to activate the minimal malloc ++ implementation. */ ++void __rtld_malloc_init_stubs (void) attribute_hidden; ++ ++/* Called shortly before the final self-relocation (when RELRO ++ variables are still writable) to activate the real malloc ++ implementation. MAIN_MAP is the link map of the executable. */ ++struct link_map; ++void __rtld_malloc_init_real (struct link_map *main_map) attribute_hidden; ++ ++#else /* !IS_IN (rtld) */ ++ ++/* This allows static/non-rtld builds to get a pointer to the ++ functions, in the same way that is required inside rtld. */ ++# define __rtld_calloc (&calloc) ++# define __rtld_free (&free) ++# define __rtld_malloc (&malloc) ++# define __rtld_realloc (&realloc) ++ ++#endif /* !IS_IN (rtld) */ ++#endif /* _RTLD_MALLOC_H */ +diff --git a/include/stdlib.h b/include/stdlib.h +index 114e12d255977676..d7720967448f2a8f 100644 +--- a/include/stdlib.h ++++ b/include/stdlib.h +@@ -9,6 +9,8 @@ + #if !defined _ISOMAC + # include + ++# include ++ + extern __typeof (strtol_l) __strtol_l; + extern __typeof (strtoul_l) __strtoul_l; + extern __typeof (strtoll_l) __strtoll_l; +diff --git a/sysdeps/generic/localplt.data b/sysdeps/generic/localplt.data +index 2d5c66ae28a2e851..e2083c0ce6869572 100644 +--- a/sysdeps/generic/localplt.data ++++ b/sysdeps/generic/localplt.data +@@ -7,12 +7,6 @@ libc.so: malloc + libc.so: memalign + libc.so: realloc + libm.so: matherr +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/mach/hurd/i386/ld.abilist b/sysdeps/mach/hurd/i386/ld.abilist +index c76b913486acf6d8..6f591b249699e10c 100644 +--- a/sysdeps/mach/hurd/i386/ld.abilist ++++ b/sysdeps/mach/hurd/i386/ld.abilist +@@ -16,10 +16,6 @@ GLIBC_2.2.6 _dl_mcount F + GLIBC_2.2.6 _hurd_intr_rpc_mach_msg F + GLIBC_2.2.6 _r_debug D 0x14 + GLIBC_2.2.6 abort F +-GLIBC_2.2.6 calloc F +-GLIBC_2.2.6 free F +-GLIBC_2.2.6 malloc F +-GLIBC_2.2.6 realloc F + GLIBC_2.3 ___tls_get_addr F + GLIBC_2.3 __tls_get_addr F + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/mach/hurd/i386/localplt.data b/sysdeps/mach/hurd/i386/localplt.data +index a5b5241b84812425..4b9dbf5acc088cff 100644 +--- a/sysdeps/mach/hurd/i386/localplt.data ++++ b/sysdeps/mach/hurd/i386/localplt.data +@@ -9,12 +9,6 @@ libc.so: malloc + REL R_386_GLOB_DAT + libc.so: memalign + REL R_386_GLOB_DAT + libc.so: realloc + REL R_386_GLOB_DAT + libm.so: matherr + REL R_386_GLOB_DAT +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc + REL R_386_GLOB_DAT +-ld.so: calloc + REL R_386_GLOB_DAT +-ld.so: realloc + REL R_386_GLOB_DAT +-ld.so: free + REL R_386_GLOB_DAT + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + REL R_386_GLOB_DAT + ld.so: _dl_catch_error + REL R_386_GLOB_DAT +diff --git a/sysdeps/unix/sysv/linux/aarch64/ld.abilist b/sysdeps/unix/sysv/linux/aarch64/ld.abilist +index 4ffe688649ca02e2..80b2fe672541c6e9 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/aarch64/ld.abilist +@@ -3,7 +3,3 @@ GLIBC_2.17 __stack_chk_guard D 0x8 + GLIBC_2.17 __tls_get_addr F + GLIBC_2.17 _dl_mcount F + GLIBC_2.17 _r_debug D 0x28 +-GLIBC_2.17 calloc F +-GLIBC_2.17 free F +-GLIBC_2.17 malloc F +-GLIBC_2.17 realloc F +diff --git a/sysdeps/unix/sysv/linux/aarch64/localplt.data b/sysdeps/unix/sysv/linux/aarch64/localplt.data +index 08af68b5e840b5d8..2c14b652efbfdf44 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/localplt.data ++++ b/sysdeps/unix/sysv/linux/aarch64/localplt.data +@@ -12,12 +12,6 @@ libm.so: matherr + libc.so: __getauxval ? + # The dynamic loader needs __tls_get_addr for TLS. + ld.so: __tls_get_addr +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/alpha/ld.abilist b/sysdeps/unix/sysv/linux/alpha/ld.abilist +index 98b66edabf1a79c7..98a03f611f98f3a4 100644 +--- a/sysdeps/unix/sysv/linux/alpha/ld.abilist ++++ b/sysdeps/unix/sysv/linux/alpha/ld.abilist +@@ -1,8 +1,4 @@ + GLIBC_2.0 _r_debug D 0x28 +-GLIBC_2.0 calloc F +-GLIBC_2.0 free F +-GLIBC_2.0 malloc F +-GLIBC_2.0 realloc F + GLIBC_2.1 __libc_stack_end D 0x8 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/alpha/localplt.data b/sysdeps/unix/sysv/linux/alpha/localplt.data +index c69eb04ce53e292e..43f6fdaea18b25f3 100644 +--- a/sysdeps/unix/sysv/linux/alpha/localplt.data ++++ b/sysdeps/unix/sysv/linux/alpha/localplt.data +@@ -26,12 +26,6 @@ libm.so: matherr + RELA R_ALPHA_GLOB_DAT + libm.so: __atan2 + # The dynamic loader needs __tls_get_addr for TLS. + ld.so: __tls_get_addr ? +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc + RELA R_ALPHA_GLOB_DAT +-ld.so: calloc + RELA R_ALPHA_GLOB_DAT +-ld.so: realloc + RELA R_ALPHA_GLOB_DAT +-ld.so: free + RELA R_ALPHA_GLOB_DAT + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + RELA R_ALPHA_GLOB_DAT + ld.so: _dl_catch_error + RELA R_ALPHA_GLOB_DAT +diff --git a/sysdeps/unix/sysv/linux/arm/ld.abilist b/sysdeps/unix/sysv/linux/arm/ld.abilist +index a301c6ebc49db1d7..cc8825c3bc68ad4a 100644 +--- a/sysdeps/unix/sysv/linux/arm/ld.abilist ++++ b/sysdeps/unix/sysv/linux/arm/ld.abilist +@@ -3,7 +3,3 @@ GLIBC_2.4 __stack_chk_guard D 0x4 + GLIBC_2.4 __tls_get_addr F + GLIBC_2.4 _dl_mcount F + GLIBC_2.4 _r_debug D 0x14 +-GLIBC_2.4 calloc F +-GLIBC_2.4 free F +-GLIBC_2.4 malloc F +-GLIBC_2.4 realloc F +diff --git a/sysdeps/unix/sysv/linux/arm/localplt.data b/sysdeps/unix/sysv/linux/arm/localplt.data +index 7bd541c28a842526..0c3af0c64e95df4b 100644 +--- a/sysdeps/unix/sysv/linux/arm/localplt.data ++++ b/sysdeps/unix/sysv/linux/arm/localplt.data +@@ -8,12 +8,6 @@ libm.so: matherr + libpthread.so: raise + # The dynamic loader needs __tls_get_addr for TLS. + ld.so: __tls_get_addr +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/hppa/ld.abilist b/sysdeps/unix/sysv/linux/hppa/ld.abilist +index 0387614d8fd784eb..d155a59843df9091 100644 +--- a/sysdeps/unix/sysv/linux/hppa/ld.abilist ++++ b/sysdeps/unix/sysv/linux/hppa/ld.abilist +@@ -1,9 +1,5 @@ + GLIBC_2.2 __libc_stack_end D 0x4 + GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x14 +-GLIBC_2.2 calloc F +-GLIBC_2.2 free F +-GLIBC_2.2 malloc F +-GLIBC_2.2 realloc F + GLIBC_2.3 __tls_get_addr F + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/hppa/localplt.data b/sysdeps/unix/sysv/linux/hppa/localplt.data +index 867413f0c54d3d71..09893d4dcfd3a1f3 100644 +--- a/sysdeps/unix/sysv/linux/hppa/localplt.data ++++ b/sysdeps/unix/sysv/linux/hppa/localplt.data +@@ -10,12 +10,6 @@ libc.so: __sigsetjmp + libc.so: _IO_funlockfile + libc.so: __errno_location + libm.so: matherr +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist +index edb7307228110c33..0478e220712a55e6 100644 +--- a/sysdeps/unix/sysv/linux/i386/ld.abilist ++++ b/sysdeps/unix/sysv/linux/i386/ld.abilist +@@ -1,8 +1,4 @@ + GLIBC_2.0 _r_debug D 0x14 +-GLIBC_2.0 calloc F +-GLIBC_2.0 free F +-GLIBC_2.0 malloc F +-GLIBC_2.0 realloc F + GLIBC_2.1 __libc_stack_end D 0x4 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 ___tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/i386/localplt.data b/sysdeps/unix/sysv/linux/i386/localplt.data +index f6f20a5d15bc79e4..5334875b4b4a4dee 100644 +--- a/sysdeps/unix/sysv/linux/i386/localplt.data ++++ b/sysdeps/unix/sysv/linux/i386/localplt.data +@@ -7,12 +7,6 @@ libc.so: malloc + REL R_386_GLOB_DAT + libc.so: memalign + REL R_386_GLOB_DAT + libc.so: realloc + REL R_386_GLOB_DAT + libm.so: matherr + REL R_386_GLOB_DAT +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc + REL R_386_GLOB_DAT +-ld.so: calloc + REL R_386_GLOB_DAT +-ld.so: realloc + REL R_386_GLOB_DAT +-ld.so: free + REL R_386_GLOB_DAT + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + REL R_386_GLOB_DAT + ld.so: _dl_catch_error + REL R_386_GLOB_DAT +diff --git a/sysdeps/unix/sysv/linux/ia64/ld.abilist b/sysdeps/unix/sysv/linux/ia64/ld.abilist +index 82042472c3089a29..33f91199bfa516fb 100644 +--- a/sysdeps/unix/sysv/linux/ia64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/ia64/ld.abilist +@@ -1,8 +1,4 @@ + GLIBC_2.2 __libc_stack_end D 0x8 + GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x28 +-GLIBC_2.2 calloc F +-GLIBC_2.2 free F +-GLIBC_2.2 malloc F +-GLIBC_2.2 realloc F + GLIBC_2.3 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/ia64/localplt.data b/sysdeps/unix/sysv/linux/ia64/localplt.data +index 3820e2a4e682af2e..1c566a503e2eba00 100644 +--- a/sysdeps/unix/sysv/linux/ia64/localplt.data ++++ b/sysdeps/unix/sysv/linux/ia64/localplt.data +@@ -6,12 +6,6 @@ libc.so: realloc + libm.so: matherr + libm.so: matherrf + libm.so: matherrl +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist +index a301c6ebc49db1d7..cc8825c3bc68ad4a 100644 +--- a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist ++++ b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist +@@ -3,7 +3,3 @@ GLIBC_2.4 __stack_chk_guard D 0x4 + GLIBC_2.4 __tls_get_addr F + GLIBC_2.4 _dl_mcount F + GLIBC_2.4 _r_debug D 0x14 +-GLIBC_2.4 calloc F +-GLIBC_2.4 free F +-GLIBC_2.4 malloc F +-GLIBC_2.4 realloc F +diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data b/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data +index 4a07bf387e2da296..3c5efb7204281e2a 100644 +--- a/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data ++++ b/sysdeps/unix/sysv/linux/m68k/coldfire/localplt.data +@@ -5,12 +5,6 @@ libc.so: malloc + libc.so: memalign + libc.so: realloc + libm.so: matherr +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist +index c9ec45cf1cf6c1c5..3ba474c27f62fb10 100644 +--- a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist ++++ b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist +@@ -1,8 +1,4 @@ + GLIBC_2.0 _r_debug D 0x14 +-GLIBC_2.0 calloc F +-GLIBC_2.0 free F +-GLIBC_2.0 malloc F +-GLIBC_2.0 realloc F + GLIBC_2.1 __libc_stack_end D 0x4 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data b/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data +index c70d6ea3011c4511..843f4e25f213d632 100644 +--- a/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data ++++ b/sysdeps/unix/sysv/linux/m68k/m680x0/localplt.data +@@ -6,12 +6,6 @@ libc.so: malloc + libc.so: memalign + libc.so: realloc + libm.so: matherr +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/microblaze/ld.abilist b/sysdeps/unix/sysv/linux/microblaze/ld.abilist +index aa0d71150af8c62c..a4933c3541119538 100644 +--- a/sysdeps/unix/sysv/linux/microblaze/ld.abilist ++++ b/sysdeps/unix/sysv/linux/microblaze/ld.abilist +@@ -3,7 +3,3 @@ GLIBC_2.18 __stack_chk_guard D 0x4 + GLIBC_2.18 __tls_get_addr F + GLIBC_2.18 _dl_mcount F + GLIBC_2.18 _r_debug D 0x14 +-GLIBC_2.18 calloc F +-GLIBC_2.18 free F +-GLIBC_2.18 malloc F +-GLIBC_2.18 realloc F +diff --git a/sysdeps/unix/sysv/linux/microblaze/localplt.data b/sysdeps/unix/sysv/linux/microblaze/localplt.data +index 8ca23897dfa5b01c..0e98d5251ee14475 100644 +--- a/sysdeps/unix/sysv/linux/microblaze/localplt.data ++++ b/sysdeps/unix/sysv/linux/microblaze/localplt.data +@@ -7,12 +7,6 @@ libc.so: realloc + libm.so: matherr + # The dynamic loader needs __tls_get_addr for TLS. + ld.so: __tls_get_addr ? +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist +index 55d48868e8b686dc..be09641a48962434 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist +@@ -1,8 +1,4 @@ + GLIBC_2.0 _r_debug D 0x14 +-GLIBC_2.0 calloc F +-GLIBC_2.0 free F +-GLIBC_2.0 malloc F +-GLIBC_2.0 realloc F + GLIBC_2.2 __libc_stack_end D 0x4 + GLIBC_2.2 _dl_mcount F + GLIBC_2.3 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist +index 55d48868e8b686dc..be09641a48962434 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist +@@ -1,8 +1,4 @@ + GLIBC_2.0 _r_debug D 0x14 +-GLIBC_2.0 calloc F +-GLIBC_2.0 free F +-GLIBC_2.0 malloc F +-GLIBC_2.0 realloc F + GLIBC_2.2 __libc_stack_end D 0x4 + GLIBC_2.2 _dl_mcount F + GLIBC_2.3 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist +index 44b345b7cf31e854..1ea36e13f294a249 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist +@@ -1,8 +1,4 @@ + GLIBC_2.0 _r_debug D 0x28 +-GLIBC_2.0 calloc F +-GLIBC_2.0 free F +-GLIBC_2.0 malloc F +-GLIBC_2.0 realloc F + GLIBC_2.2 __libc_stack_end D 0x8 + GLIBC_2.2 _dl_mcount F + GLIBC_2.3 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/nios2/ld.abilist b/sysdeps/unix/sysv/linux/nios2/ld.abilist +index 110f1039fa39fb1c..52178802dd82b59a 100644 +--- a/sysdeps/unix/sysv/linux/nios2/ld.abilist ++++ b/sysdeps/unix/sysv/linux/nios2/ld.abilist +@@ -3,7 +3,3 @@ GLIBC_2.21 __stack_chk_guard D 0x4 + GLIBC_2.21 __tls_get_addr F + GLIBC_2.21 _dl_mcount F + GLIBC_2.21 _r_debug D 0x14 +-GLIBC_2.21 calloc F +-GLIBC_2.21 free F +-GLIBC_2.21 malloc F +-GLIBC_2.21 realloc F +diff --git a/sysdeps/unix/sysv/linux/nios2/localplt.data b/sysdeps/unix/sysv/linux/nios2/localplt.data +index 4430a5891e847aed..39009a62d6385849 100644 +--- a/sysdeps/unix/sysv/linux/nios2/localplt.data ++++ b/sysdeps/unix/sysv/linux/nios2/localplt.data +@@ -27,12 +27,6 @@ libc.so: __nedf2 + libc.so: __eqdf2 + libc.so: __extendsfdf2 + libm.so: matherr +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data +index e822e0a4809e5088..a02dd5cc246329a0 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/localplt.data +@@ -5,12 +5,6 @@ libc.so: malloc + libc.so: memalign + libc.so: realloc + libm.so: matherr +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist +index e8b0ea3a9bd98b92..4bbfba7a61c7a5ef 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist +@@ -1,8 +1,4 @@ + GLIBC_2.0 _r_debug D 0x14 +-GLIBC_2.0 calloc F +-GLIBC_2.0 free F +-GLIBC_2.0 malloc F +-GLIBC_2.0 realloc F + GLIBC_2.1 __libc_stack_end D 0x4 + GLIBC_2.1 _dl_mcount F + GLIBC_2.22 __tls_get_addr_opt F +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data +index fead931d4e5c4bc4..a4cd7cfb04249ae3 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/localplt.data +@@ -35,12 +35,6 @@ libc.so: realloc + libm.so: copysignl ? + libm.so: fabsl + libm.so: matherr +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld-le.abilist +index 37c8f6684b54341b..b1f313c7cd33defc 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld-le.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld-le.abilist +@@ -2,9 +2,5 @@ GLIBC_2.17 __libc_stack_end D 0x8 + GLIBC_2.17 __tls_get_addr F + GLIBC_2.17 _dl_mcount F + GLIBC_2.17 _r_debug D 0x28 +-GLIBC_2.17 calloc F +-GLIBC_2.17 free F +-GLIBC_2.17 malloc F +-GLIBC_2.17 realloc F + GLIBC_2.22 __tls_get_addr_opt F + GLIBC_2.23 __parse_hwcap_and_convert_at_platform F +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld.abilist +index edfc9ca56f2e4fee..283fb4510bea40ba 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ld.abilist +@@ -4,7 +4,3 @@ GLIBC_2.3 __libc_stack_end D 0x8 + GLIBC_2.3 __tls_get_addr F + GLIBC_2.3 _dl_mcount F + GLIBC_2.3 _r_debug D 0x28 +-GLIBC_2.3 calloc F +-GLIBC_2.3 free F +-GLIBC_2.3 malloc F +-GLIBC_2.3 realloc F +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data b/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data +index c1209336d2d339d4..bb498fbe3ae28d03 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/localplt.data +@@ -4,12 +4,6 @@ libc.so: malloc + libc.so: memalign + libc.so: realloc + libm.so: matherr +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/riscv/localplt.data b/sysdeps/unix/sysv/linux/riscv/localplt.data +index 14c02cb2d6c016d3..0ed8650b65a0ecbf 100644 +--- a/sysdeps/unix/sysv/linux/riscv/localplt.data ++++ b/sysdeps/unix/sysv/linux/riscv/localplt.data +@@ -6,12 +6,6 @@ libc.so: free + libc.so: malloc + libc.so: memalign + libc.so: realloc +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist +index b411871d0631e1a3..845f356c3c3fad54 100644 +--- a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist +@@ -3,7 +3,3 @@ GLIBC_2.27 __stack_chk_guard D 0x8 + GLIBC_2.27 __tls_get_addr F + GLIBC_2.27 _dl_mcount F + GLIBC_2.27 _r_debug D 0x28 +-GLIBC_2.27 calloc F +-GLIBC_2.27 free F +-GLIBC_2.27 malloc F +-GLIBC_2.27 realloc F +diff --git a/sysdeps/unix/sysv/linux/s390/localplt.data b/sysdeps/unix/sysv/linux/s390/localplt.data +index e822e0a4809e5088..a02dd5cc246329a0 100644 +--- a/sysdeps/unix/sysv/linux/s390/localplt.data ++++ b/sysdeps/unix/sysv/linux/s390/localplt.data +@@ -5,12 +5,6 @@ libc.so: malloc + libc.so: memalign + libc.so: realloc + libm.so: matherr +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist +index 0576c9575ea6118e..b56f005bebd3baf1 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist +@@ -1,8 +1,4 @@ + GLIBC_2.0 _r_debug D 0x14 +-GLIBC_2.0 calloc F +-GLIBC_2.0 free F +-GLIBC_2.0 malloc F +-GLIBC_2.0 realloc F + GLIBC_2.1 __libc_stack_end D 0x4 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 __tls_get_offset F +diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist +index 1fbb890d1dc495e5..6f788a086d68aaa5 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist +@@ -1,8 +1,4 @@ + GLIBC_2.2 __libc_stack_end D 0x8 + GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x28 +-GLIBC_2.2 calloc F +-GLIBC_2.2 free F +-GLIBC_2.2 malloc F +-GLIBC_2.2 realloc F + GLIBC_2.3 __tls_get_offset F +diff --git a/sysdeps/unix/sysv/linux/sh/ld.abilist b/sysdeps/unix/sysv/linux/sh/ld.abilist +index 0387614d8fd784eb..d155a59843df9091 100644 +--- a/sysdeps/unix/sysv/linux/sh/ld.abilist ++++ b/sysdeps/unix/sysv/linux/sh/ld.abilist +@@ -1,9 +1,5 @@ + GLIBC_2.2 __libc_stack_end D 0x4 + GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x14 +-GLIBC_2.2 calloc F +-GLIBC_2.2 free F +-GLIBC_2.2 malloc F +-GLIBC_2.2 realloc F + GLIBC_2.3 __tls_get_addr F + GLIBC_2.4 __stack_chk_guard D 0x4 +diff --git a/sysdeps/unix/sysv/linux/sh/localplt.data b/sysdeps/unix/sysv/linux/sh/localplt.data +index babb19d71785515d..3225177c50956972 100644 +--- a/sysdeps/unix/sysv/linux/sh/localplt.data ++++ b/sysdeps/unix/sysv/linux/sh/localplt.data +@@ -12,12 +12,6 @@ libc.so: __errno_location + libm.so: matherr + # Generated by the compiler because there is no trap insn pattern. + libc.so: abort ? +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist +index fd0b33f86d3f9c5c..0c6610e3c2f00cf3 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist +@@ -1,8 +1,4 @@ + GLIBC_2.0 _r_debug D 0x14 +-GLIBC_2.0 calloc F +-GLIBC_2.0 free F +-GLIBC_2.0 malloc F +-GLIBC_2.0 realloc F + GLIBC_2.1 __libc_stack_end D 0x4 + GLIBC_2.1 _dl_mcount F + GLIBC_2.3 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data b/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data +index 1668f4017e0f28f0..be40910c4de9859a 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data ++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/localplt.data +@@ -17,12 +17,6 @@ libc.so: malloc + libc.so: memalign + libc.so: realloc + libm.so: matherr +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist +index 82042472c3089a29..33f91199bfa516fb 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist +@@ -1,8 +1,4 @@ + GLIBC_2.2 __libc_stack_end D 0x8 + GLIBC_2.2 _dl_mcount F + GLIBC_2.2 _r_debug D 0x28 +-GLIBC_2.2 calloc F +-GLIBC_2.2 free F +-GLIBC_2.2 malloc F +-GLIBC_2.2 realloc F + GLIBC_2.3 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data b/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data +index b881b9096d9fa38f..809062d46c1b4837 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data ++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/localplt.data +@@ -18,12 +18,6 @@ libc.so: malloc + libc.so: memalign + libc.so: realloc + libm.so: matherr +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc +-ld.so: calloc +-ld.so: realloc +-ld.so: free + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + ld.so: _dl_catch_error +diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist +index 0dc943061197d374..d3cdf7611eb9cab3 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist +@@ -1,8 +1,4 @@ + GLIBC_2.2.5 __libc_stack_end D 0x8 + GLIBC_2.2.5 _dl_mcount F + GLIBC_2.2.5 _r_debug D 0x28 +-GLIBC_2.2.5 calloc F +-GLIBC_2.2.5 free F +-GLIBC_2.2.5 malloc F +-GLIBC_2.2.5 realloc F + GLIBC_2.3 __tls_get_addr F +diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist +index 80f3161586414674..c70bccf78245a552 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist ++++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist +@@ -2,7 +2,3 @@ GLIBC_2.16 __libc_stack_end D 0x4 + GLIBC_2.16 __tls_get_addr F + GLIBC_2.16 _dl_mcount F + GLIBC_2.16 _r_debug D 0x14 +-GLIBC_2.16 calloc F +-GLIBC_2.16 free F +-GLIBC_2.16 malloc F +-GLIBC_2.16 realloc F +diff --git a/sysdeps/x86_64/localplt.data b/sysdeps/x86_64/localplt.data +index c27a02b66acd2ab4..8f41e928708d9a42 100644 +--- a/sysdeps/x86_64/localplt.data ++++ b/sysdeps/x86_64/localplt.data +@@ -9,12 +9,6 @@ libc.so: malloc + RELA R_X86_64_GLOB_DAT + libc.so: memalign + RELA R_X86_64_GLOB_DAT + libc.so: realloc + RELA R_X86_64_GLOB_DAT + libm.so: matherr + RELA R_X86_64_GLOB_DAT +-# The main malloc is interposed into the dynamic linker, for +-# allocations after the initial link (when dlopen is used). +-ld.so: malloc + RELA R_X86_64_GLOB_DAT +-ld.so: calloc + RELA R_X86_64_GLOB_DAT +-ld.so: realloc + RELA R_X86_64_GLOB_DAT +-ld.so: free + RELA R_X86_64_GLOB_DAT + # The TLS-enabled version of these functions is interposed from libc.so. + ld.so: _dl_signal_error + RELA R_X86_64_GLOB_DAT + ld.so: _dl_catch_error + RELA R_X86_64_GLOB_DAT diff --git a/glibc-rh1817513-42.patch b/glibc-rh1817513-42.patch new file mode 100755 index 0000000..473724f --- /dev/null +++ b/glibc-rh1817513-42.patch @@ -0,0 +1,46 @@ +commit 758599bc9dcc5764e862bd9e1613c5d1e6efc5d3 +Author: Florian Weimer +Date: Wed Feb 26 15:58:23 2020 +0100 + + elf: Apply attribute_relro to pointers in elf/dl-minimal.c + + The present code leaves the function pointers unprotected, but moves + some of the static functions into .data.rel.ro instead. This causes + the linker to produce an allocatable, executable, writable section + and eventually an RWX load segment. Not only do we really do not + want that, it also breaks valgrind because valgrind does not load + debuginfo from the mmap interceptor if all it sees are RX and RWX + mappings. + + Fixes commit 3a0ecccb599a6b1ad4b149dc569c0080e92d057b ("ld.so: Do not + export free/calloc/malloc/realloc functions [BZ #25486]"). + +diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c +index 95ea7b024044864f..4335f1bd24289b01 100644 +--- a/elf/dl-minimal.c ++++ b/elf/dl-minimal.c +@@ -39,16 +39,16 @@ + implementation below. Before the final relocation, + __rtld_malloc_init_real is called to replace the pointers with the + real implementation. */ +-__typeof (calloc) *__rtld_calloc; +-__typeof (free) *__rtld_free; +-__typeof (malloc) *__rtld_malloc; +-__typeof (realloc) *__rtld_realloc; ++__typeof (calloc) *__rtld_calloc attribute_relro; ++__typeof (free) *__rtld_free attribute_relro; ++__typeof (malloc) *__rtld_malloc attribute_relro; ++__typeof (realloc) *__rtld_realloc attribute_relro; + + /* Defined below. */ +-static __typeof (calloc) rtld_calloc attribute_relro; +-static __typeof (free) rtld_free attribute_relro; +-static __typeof (malloc) rtld_malloc attribute_relro; +-static __typeof (realloc) rtld_realloc attribute_relro; ++static __typeof (calloc) rtld_calloc; ++static __typeof (free) rtld_free; ++static __typeof (malloc) rtld_malloc; ++static __typeof (realloc) rtld_realloc; + + void + __rtld_malloc_init_stubs (void) diff --git a/glibc-rh1817513-43.patch b/glibc-rh1817513-43.patch new file mode 100755 index 0000000..212bdc1 --- /dev/null +++ b/glibc-rh1817513-43.patch @@ -0,0 +1,356 @@ +commit dfe9aa91564c1bf2a23b5589a5db42f9da5d29b5 +Author: Adhemerval Zanella +Date: Tue Nov 19 17:17:05 2019 -0300 + + support: Add support_process_state_wait + + It allows parent process to wait for child state using a polling + strategy over procfs on Linux. The polling is used over ptrace to + avoid the need to handle signals on the target pid and to handle some + system specific limitation (such as YAMA). + + The polling has some limitations, such as resource consumption due + the procfs read in a loop and the lack of synchronization after the + state is obtained. + + The interface idea is to simplify some sleep synchronization waitid + tests and is to reduce timeouts by replacing arbitrary waits. + +diff --git a/support/Makefile b/support/Makefile +index 79d03bd6bfe02540..117cfdd4f22fc405 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -58,6 +58,7 @@ libsupport-routines = \ + support_format_hostent \ + support_format_netent \ + support_isolate_in_subprocess \ ++ support_process_state \ + support_ptrace \ + support_openpty \ + support_paths \ +@@ -90,6 +91,7 @@ libsupport-routines = \ + xfopen \ + xfork \ + xftruncate \ ++ xgetline \ + xgetsockname \ + xlisten \ + xlseek \ +@@ -217,6 +219,7 @@ tests = \ + tst-support_capture_subprocess \ + tst-support_descriptors \ + tst-support_format_dns_packet \ ++ tst-support-process_state \ + tst-support_quote_blob \ + tst-support_quote_string \ + tst-support_record_failure \ +diff --git a/support/process_state.h b/support/process_state.h +new file mode 100644 +index 0000000000000000..6c19afdbb7462277 +--- /dev/null ++++ b/support/process_state.h +@@ -0,0 +1,43 @@ ++/* Wait for process state. ++ Copyright (C) 2020 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 ++ . */ ++ ++#ifndef SUPPORT_PROCESS_STATE_H ++#define SUPPORT_PROCESS_STATE_H ++ ++#include ++ ++enum support_process_state ++{ ++ support_process_state_running = 0x01, /* R (running). */ ++ support_process_state_sleeping = 0x02, /* S (sleeping). */ ++ support_process_state_disk_sleep = 0x04, /* D (disk sleep). */ ++ support_process_state_stopped = 0x08, /* T (stopped). */ ++ support_process_state_tracing_stop = 0x10, /* t (tracing stop). */ ++ support_process_state_dead = 0x20, /* X (dead). */ ++ support_process_state_zombie = 0x40, /* Z (zombie). */ ++ support_process_state_parked = 0x80, /* P (parked). */ ++}; ++ ++/* Wait for process PID to reach state STATE. It can be a combination of ++ multiple possible states ('process_state_running | process_state_sleeping') ++ where the function return when any of these state are observed. ++ For an invalid state not represented by SUPPORT_PROCESS_STATE, it fallbacks ++ to a 2 second sleep. */ ++void support_process_state_wait (pid_t pid, enum support_process_state state); ++ ++#endif +diff --git a/support/support_process_state.c b/support/support_process_state.c +new file mode 100644 +index 0000000000000000..76dc798728ece0d9 +--- /dev/null ++++ b/support/support_process_state.c +@@ -0,0 +1,92 @@ ++/* Wait for process state. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++void ++support_process_state_wait (pid_t pid, enum support_process_state state) ++{ ++#ifdef __linux__ ++ /* For Linux it does a polling check on /proc//status checking on ++ third field. */ ++ ++ /* It mimics the kernel states from fs/proc/array.c */ ++ static const struct process_states ++ { ++ enum support_process_state s; ++ char v; ++ } process_states[] = { ++ { support_process_state_running, 'R' }, ++ { support_process_state_sleeping, 'S' }, ++ { support_process_state_disk_sleep, 'D' }, ++ { support_process_state_stopped, 'T' }, ++ { support_process_state_tracing_stop, 't' }, ++ { support_process_state_dead, 'X' }, ++ { support_process_state_zombie, 'Z' }, ++ { support_process_state_parked, 'P' }, ++ }; ++ ++ char spath[sizeof ("/proc/" + 3) * sizeof (pid_t) + sizeof ("/status") + 1]; ++ snprintf (spath, sizeof (spath), "/proc/%i/status", pid); ++ ++ FILE *fstatus = xfopen (spath, "r"); ++ char *line = NULL; ++ size_t linesiz = 0; ++ ++ for (;;) ++ { ++ char cur_state = -1; ++ while (xgetline (&line, &linesiz, fstatus) != -1) ++ if (strncmp (line, "State:", strlen ("State:")) == 0) ++ { ++ TEST_COMPARE (sscanf (line, "%*s %c", &cur_state), 1); ++ break; ++ } ++ /* Fallback to nanosleep for invalid state. */ ++ if (cur_state == -1) ++ break; ++ ++ for (size_t i = 0; i < array_length (process_states); ++i) ++ if (state & process_states[i].s && cur_state == process_states[i].v) ++ { ++ free (line); ++ xfclose (fstatus); ++ return; ++ } ++ ++ rewind (fstatus); ++ fflush (fstatus); ++ ++ if (nanosleep (&(struct timespec) { 0, 10000000 }, NULL) != 0) ++ FAIL_EXIT1 ("nanosleep: %m"); ++ } ++ ++ free (line); ++ xfclose (fstatus); ++ /* Fallback to nanosleep if an invalid state is found. */ ++#endif ++ nanosleep (&(struct timespec) { 2, 0 }, NULL); ++} +diff --git a/support/tst-support-process_state.c b/support/tst-support-process_state.c +new file mode 100644 +index 0000000000000000..3fc103ab9205ddb0 +--- /dev/null ++++ b/support/tst-support-process_state.c +@@ -0,0 +1,105 @@ ++/* Wait for process state tests. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef WEXITED ++# define WEXITED 0 ++#endif ++ ++static void ++sigusr1_handler (int signo) ++{ ++} ++ ++static void ++test_child (void) ++{ ++ xsignal (SIGUSR1, sigusr1_handler); ++ ++ raise (SIGSTOP); ++ ++ TEST_COMPARE (pause (), -1); ++ TEST_COMPARE (errno, EINTR); ++ ++ while (1) ++ asm (""); ++} ++ ++static int ++do_test (void) ++{ ++ pid_t pid = xfork (); ++ if (pid == 0) ++ { ++ test_child (); ++ _exit (127); ++ } ++ ++ /* Adding process_state_tracing_stop ('t') allows the test to work under ++ trace programs such as ptrace. */ ++ enum support_process_state stop_state = support_process_state_stopped ++ | support_process_state_tracing_stop; ++ ++ if (test_verbose) ++ printf ("info: waiting pid %d, state_stopped/state_tracing_stop\n", ++ (int) pid); ++ support_process_state_wait (pid, stop_state); ++ ++ if (kill (pid, SIGCONT) != 0) ++ FAIL_RET ("kill (%d, SIGCONT): %m\n", pid); ++ ++ if (test_verbose) ++ printf ("info: waiting pid %d, state_sleeping\n", (int) pid); ++ support_process_state_wait (pid, support_process_state_sleeping); ++ ++ if (kill (pid, SIGUSR1) != 0) ++ FAIL_RET ("kill (%d, SIGUSR1): %m\n", pid); ++ ++ if (test_verbose) ++ printf ("info: waiting pid %d, state_running\n", (int) pid); ++ support_process_state_wait (pid, support_process_state_running); ++ ++ if (kill (pid, SIGKILL) != 0) ++ FAIL_RET ("kill (%d, SIGKILL): %m\n", pid); ++ ++ if (test_verbose) ++ printf ("info: waiting pid %d, state_zombie\n", (int) pid); ++ support_process_state_wait (pid, support_process_state_zombie); ++ ++ siginfo_t info; ++ int r = waitid (P_PID, pid, &info, WEXITED); ++ TEST_COMPARE (r, 0); ++ TEST_COMPARE (info.si_signo, SIGCHLD); ++ TEST_COMPARE (info.si_code, CLD_KILLED); ++ TEST_COMPARE (info.si_status, SIGKILL); ++ TEST_COMPARE (info.si_pid, pid); ++ ++ return 0; ++} ++ ++#include +diff --git a/support/xgetline.c b/support/xgetline.c +new file mode 100644 +index 0000000000000000..180bc2db95a9c5d4 +--- /dev/null ++++ b/support/xgetline.c +@@ -0,0 +1,33 @@ ++/* fopen with error checking. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++ssize_t ++xgetline (char **lineptr, size_t *n, FILE *stream) ++{ ++ int old_errno = errno; ++ errno = 0; ++ size_t ret = getline (lineptr, n, stream); ++ if (!feof (stream) && ferror (stream)) ++ FAIL_EXIT1 ("getline failed: %m"); ++ errno = old_errno; ++ return ret; ++} +diff --git a/support/xstdio.h b/support/xstdio.h +index e7d0274474706380..9446b1f27b0f881e 100644 +--- a/support/xstdio.h ++++ b/support/xstdio.h +@@ -27,6 +27,8 @@ __BEGIN_DECLS + FILE *xfopen (const char *path, const char *mode); + void xfclose (FILE *); + ++ssize_t xgetline (char **lineptr, size_t *n, FILE *stream); ++ + __END_DECLS + + #endif /* SUPPORT_XSTDIO_H */ diff --git a/glibc-rh1817513-44.patch b/glibc-rh1817513-44.patch new file mode 100755 index 0000000..1b591b4 --- /dev/null +++ b/glibc-rh1817513-44.patch @@ -0,0 +1,24 @@ +commit 083d644d420f49c992667f4c7a54848ad3dee54d +Author: Michael Hudson-Doyle +Date: Wed Mar 11 13:05:25 2020 +1300 + + test-container: print errno when execvp fails + + I'm debugging a situation where lots of tests using test-container fail + and it's possible knowing errno would help understand why. + + Reviewed-by: DJ Delorie + +diff --git a/support/test-container.c b/support/test-container.c +index 9488ec7b4a824380..9eff8baeef0e9d8a 100644 +--- a/support/test-container.c ++++ b/support/test-container.c +@@ -1145,7 +1145,7 @@ main (int argc, char **argv) + execvp (new_child_exec, new_child_proc); + + /* Or don't run the child? */ +- FAIL_EXIT1 ("Unable to exec %s\n", new_child_exec); ++ FAIL_EXIT1 ("Unable to exec %s: %s\n", new_child_exec, strerror (errno)); + + /* Because gcc won't know error () never returns... */ + exit (EXIT_UNSUPPORTED); diff --git a/glibc-rh1817513-45.patch b/glibc-rh1817513-45.patch new file mode 100755 index 0000000..b578717 --- /dev/null +++ b/glibc-rh1817513-45.patch @@ -0,0 +1,106 @@ +commit b7176cc2aff4a8883e4834ddf65f8a6fdb1f160e +Author: DJ Delorie +Date: Wed Feb 19 12:31:38 2020 -0500 + + ldconfig: trace origin paths with -v + + With this patch, -v turns on a "from" trace for each directory + searched, that tells you WHY that directory is being searched - + is it a builtin, from the command line, or from some config file? + +diff --git a/elf/ldconfig.c b/elf/ldconfig.c +index ed7d9ab0412d93fd..5e6516688a1c192a 100644 +--- a/elf/ldconfig.c ++++ b/elf/ldconfig.c +@@ -79,6 +79,8 @@ struct dir_entry + int flag; + ino64_t ino; + dev_t dev; ++ const char *from_file; ++ int from_line; + struct dir_entry *next; + }; + +@@ -344,7 +346,12 @@ add_single_dir (struct dir_entry *entry, int verbose) + if (ptr->ino == entry->ino && ptr->dev == entry->dev) + { + if (opt_verbose && verbose) +- error (0, 0, _("Path `%s' given more than once"), entry->path); ++ { ++ error (0, 0, _("Path `%s' given more than once"), entry->path); ++ fprintf (stderr, _("(from %s:%d and %s:%d)\n"), ++ entry->from_file, entry->from_line, ++ ptr->from_file, ptr->from_line); ++ } + /* Use the newer information. */ + ptr->flag = entry->flag; + free (entry->path); +@@ -363,12 +370,15 @@ add_single_dir (struct dir_entry *entry, int verbose) + + /* Add one directory to the list of directories to process. */ + static void +-add_dir (const char *line) ++add_dir_1 (const char *line, const char *from_file, int from_line) + { + unsigned int i; + struct dir_entry *entry = xmalloc (sizeof (struct dir_entry)); + entry->next = NULL; + ++ entry->from_file = strdup (from_file); ++ entry->from_line = from_line; ++ + /* Search for an '=' sign. */ + entry->path = xstrdup (line); + char *equal_sign = strchr (entry->path, '='); +@@ -428,6 +438,11 @@ add_dir (const char *line) + free (path); + } + ++static void ++add_dir (const char *line) ++{ ++ add_dir_1 (line, "", 0); ++} + + static int + chroot_stat (const char *real_path, const char *path, struct stat64 *st) +@@ -672,9 +687,10 @@ search_dir (const struct dir_entry *entry) + if (opt_verbose) + { + if (hwcap != 0) +- printf ("%s: (hwcap: %#.16" PRIx64 ")\n", entry->path, hwcap); ++ printf ("%s: (hwcap: %#.16" PRIx64 ")", entry->path, hwcap); + else +- printf ("%s:\n", entry->path); ++ printf ("%s:", entry->path); ++ printf (_(" (from %s:%d)\n"), entry->from_file, entry->from_line); + } + + char *dir_name; +@@ -815,6 +831,8 @@ search_dir (const struct dir_entry *entry) + struct dir_entry *new_entry; + + new_entry = xmalloc (sizeof (struct dir_entry)); ++ new_entry->from_file = entry->from_file; ++ new_entry->from_line = entry->from_line; + new_entry->path = xstrdup (file_name); + new_entry->flag = entry->flag; + new_entry->next = NULL; +@@ -1174,7 +1192,7 @@ Warning: ignoring configuration file that cannot be opened: %s"), + } + } + else +- add_dir (cp); ++ add_dir_1 (cp, filename, lineno); + } + while (!feof_unlocked (file)); + +@@ -1282,7 +1300,7 @@ main (int argc, char **argv) + _("relative path `%s' used to build cache"), + argv[i]); + else +- add_dir (argv[i]); ++ add_dir_1 (argv[i], "", 0); + } + + /* The last entry in hwcap_extra is reserved for the "tls" pseudo-hwcap which diff --git a/glibc-rh1817513-46.patch b/glibc-rh1817513-46.patch new file mode 100755 index 0000000..7947d9f --- /dev/null +++ b/glibc-rh1817513-46.patch @@ -0,0 +1,83 @@ +commit cea56af185eae45b1f0963351e3d4daa1cbde521 +Author: Florian Weimer +Date: Thu Apr 2 17:09:36 2020 +0200 + + support: Change xgetline to return 0 on EOF + + The advantage is that the buffer will always contain the number + of characters as returned from the function, which allows one to use + a sequence like + + /* No more audit module output. */ + line_length = xgetline (&buffer, &buffer_length, fp); + TEST_COMPARE_BLOB ("", 0, buffer, line_length); + + to check for an expected EOF, while also reporting any unexpected + extra data encountered. + + Reviewed-by: Carlos O'Donell + +diff --git a/support/support_process_state.c b/support/support_process_state.c +index 76dc798728ece0d9..e303c78fc874b2f9 100644 +--- a/support/support_process_state.c ++++ b/support/support_process_state.c +@@ -59,7 +59,7 @@ support_process_state_wait (pid_t pid, enum support_process_state state) + for (;;) + { + char cur_state = -1; +- while (xgetline (&line, &linesiz, fstatus) != -1) ++ while (xgetline (&line, &linesiz, fstatus) > 0) + if (strncmp (line, "State:", strlen ("State:")) == 0) + { + TEST_COMPARE (sscanf (line, "%*s %c", &cur_state), 1); +diff --git a/support/xgetline.c b/support/xgetline.c +index 180bc2db95a9c5d4..d91c09ac108b4c75 100644 +--- a/support/xgetline.c ++++ b/support/xgetline.c +@@ -18,16 +18,22 @@ + + #include + #include +-#include + +-ssize_t ++size_t + xgetline (char **lineptr, size_t *n, FILE *stream) + { +- int old_errno = errno; +- errno = 0; +- size_t ret = getline (lineptr, n, stream); +- if (!feof (stream) && ferror (stream)) +- FAIL_EXIT1 ("getline failed: %m"); +- errno = old_errno; ++ TEST_VERIFY (!ferror (stream)); ++ ssize_t ret = getline (lineptr, n, stream); ++ if (ferror (stream)) ++ { ++ TEST_VERIFY (ret < 0); ++ FAIL_EXIT1 ("getline: %m"); ++ } ++ if (feof (stream)) ++ { ++ TEST_VERIFY (ret <= 0); ++ return 0; ++ } ++ TEST_VERIFY (ret > 0); + return ret; + } +diff --git a/support/xstdio.h b/support/xstdio.h +index 9446b1f27b0f881e..36071cf78822ec8d 100644 +--- a/support/xstdio.h ++++ b/support/xstdio.h +@@ -27,7 +27,10 @@ __BEGIN_DECLS + FILE *xfopen (const char *path, const char *mode); + void xfclose (FILE *); + +-ssize_t xgetline (char **lineptr, size_t *n, FILE *stream); ++/* Read a line from FP, using getline. *BUFFER must be NULL, or a ++ heap-allocated pointer of *LENGTH bytes. Return the number of ++ bytes in the line if a line was read, or 0 on EOF. */ ++size_t xgetline (char **lineptr, size_t *n, FILE *stream); + + __END_DECLS + diff --git a/glibc-rh1817513-47.patch b/glibc-rh1817513-47.patch new file mode 100755 index 0000000..ef5036c --- /dev/null +++ b/glibc-rh1817513-47.patch @@ -0,0 +1,373 @@ +commit 4c6e0415ef206a595c62d5d37e3b9a821782c533 +Author: Florian Weimer +Date: Fri Apr 3 13:17:48 2020 +0200 + + elf: Simplify handling of lists of audit strings + + All list elements are colon-separated strings, and there is a hard + upper limit for the number of audit modules, so it is possible to + pre-allocate a fixed-size array of strings to which the LD_AUDIT + environment variable and --audit arguments are added. + + Also eliminate the global variables for the audit list because + the list is only needed briefly during startup. + + There is a slight behavior change: All duplicate LD_AUDIT environment + variables are now processed, not just the last one as before. However, + such environment vectors are invalid anyway. + + Reviewed-by: Carlos O'Donell + +diff --git a/elf/rtld.c b/elf/rtld.c +index f755dc30331f799f..c39cb8f2cd4bb1cc 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + #include + +@@ -107,8 +108,53 @@ static void print_missing_version (int errcode, const char *objname, + /* Print the various times we collected. */ + static void print_statistics (const hp_timing_t *total_timep); + +-/* Add audit objects. */ +-static void process_dl_audit (char *str); ++/* Length limits for names and paths, to protect the dynamic linker, ++ particularly when __libc_enable_secure is active. */ ++#ifdef NAME_MAX ++# define SECURE_NAME_LIMIT NAME_MAX ++#else ++# define SECURE_NAME_LIMIT 255 ++#endif ++#ifdef PATH_MAX ++# define SECURE_PATH_LIMIT PATH_MAX ++#else ++# define SECURE_PATH_LIMIT 1024 ++#endif ++ ++/* Strings containing colon-separated lists of audit modules. */ ++struct audit_list ++{ ++ /* Array of strings containing colon-separated path lists. Each ++ audit module needs its own namespace, so pre-allocate the largest ++ possible list. */ ++ const char *audit_strings[DL_NNS]; ++ ++ /* Number of entries added to audit_strings. */ ++ size_t length; ++ ++ /* Index into the audit_strings array (for the iteration phase). */ ++ size_t current_index; ++ ++ /* Tail of audit_strings[current_index] which still needs ++ processing. */ ++ const char *current_tail; ++ ++ /* Scratch buffer for returning a name which is part of the strings ++ in audit_strings. */ ++ char fname[SECURE_NAME_LIMIT]; ++}; ++ ++/* Creates an empty audit list. */ ++static void audit_list_init (struct audit_list *); ++ ++/* Add a string to the end of the audit list, for later parsing. Must ++ not be called after audit_list_next. */ ++static void audit_list_add_string (struct audit_list *, const char *); ++ ++/* Extract the next audit module from the audit list. Only modules ++ for which dso_name_valid_for_suid is true are returned. Must be ++ called after all the audit_list_add_string calls. */ ++static const char *audit_list_next (struct audit_list *); + + /* This is a list of all the modes the dynamic loader can be in. */ + enum mode { normal, list, verify, trace }; +@@ -116,7 +162,7 @@ enum mode { normal, list, verify, trace }; + /* Process all environments variables the dynamic linker must recognize. + Since all of them start with `LD_' we are a bit smarter while finding + all the entries. */ +-static void process_envvars (enum mode *modep); ++static void process_envvars (enum mode *modep, struct audit_list *); + + #ifdef DL_ARGV_NOT_RELRO + int _dl_argc attribute_hidden; +@@ -144,19 +190,6 @@ uintptr_t __pointer_chk_guard_local + strong_alias (__pointer_chk_guard_local, __pointer_chk_guard) + #endif + +-/* Length limits for names and paths, to protect the dynamic linker, +- particularly when __libc_enable_secure is active. */ +-#ifdef NAME_MAX +-# define SECURE_NAME_LIMIT NAME_MAX +-#else +-# define SECURE_NAME_LIMIT 255 +-#endif +-#ifdef PATH_MAX +-# define SECURE_PATH_LIMIT PATH_MAX +-#else +-# define SECURE_PATH_LIMIT 1024 +-#endif +- + /* Check that AT_SECURE=0, or that the passed name does not contain + directories and is not overly long. Reject empty names + unconditionally. */ +@@ -174,89 +207,75 @@ dso_name_valid_for_suid (const char *p) + return *p != '\0'; + } + +-/* LD_AUDIT variable contents. Must be processed before the +- audit_list below. */ +-const char *audit_list_string; +- +-/* Cyclic list of auditing DSOs. audit_list->next is the first +- element. */ +-static struct audit_list ++static void ++audit_list_init (struct audit_list *list) + { +- const char *name; +- struct audit_list *next; +-} *audit_list; ++ list->length = 0; ++ list->current_index = 0; ++ list->current_tail = NULL; ++} + +-/* Iterator for audit_list_string followed by audit_list. */ +-struct audit_list_iter ++static void ++audit_list_add_string (struct audit_list *list, const char *string) + { +- /* Tail of audit_list_string still needing processing, or NULL. */ +- const char *audit_list_tail; ++ /* Empty strings do not load anything. */ ++ if (*string == '\0') ++ return; + +- /* The list element returned in the previous iteration. NULL before +- the first element. */ +- struct audit_list *previous; ++ if (list->length == array_length (list->audit_strings)) ++ _dl_fatal_printf ("Fatal glibc error: Too many audit modules requested\n"); + +- /* Scratch buffer for returning a name which is part of +- audit_list_string. */ +- char fname[SECURE_NAME_LIMIT]; +-}; ++ list->audit_strings[list->length++] = string; + +-/* Initialize an audit list iterator. */ +-static void +-audit_list_iter_init (struct audit_list_iter *iter) +-{ +- iter->audit_list_tail = audit_list_string; +- iter->previous = NULL; ++ /* Initialize processing of the first string for ++ audit_list_next. */ ++ if (list->length == 1) ++ list->current_tail = string; + } + +-/* Iterate through both audit_list_string and audit_list. */ + static const char * +-audit_list_iter_next (struct audit_list_iter *iter) ++audit_list_next (struct audit_list *list) + { +- if (iter->audit_list_tail != NULL) ++ if (list->current_tail == NULL) ++ return NULL; ++ ++ while (true) + { +- /* First iterate over audit_list_string. */ +- while (*iter->audit_list_tail != '\0') ++ /* Advance to the next string in audit_strings if the current ++ string has been exhausted. */ ++ while (*list->current_tail == '\0') + { +- /* Split audit list at colon. */ +- size_t len = strcspn (iter->audit_list_tail, ":"); +- if (len > 0 && len < sizeof (iter->fname)) ++ ++list->current_index; ++ if (list->current_index == list->length) + { +- memcpy (iter->fname, iter->audit_list_tail, len); +- iter->fname[len] = '\0'; ++ list->current_tail = NULL; ++ return NULL; + } +- else +- /* Do not return this name to the caller. */ +- iter->fname[0] = '\0'; +- +- /* Skip over the substring and the following delimiter. */ +- iter->audit_list_tail += len; +- if (*iter->audit_list_tail == ':') +- ++iter->audit_list_tail; +- +- /* If the name is valid, return it. */ +- if (dso_name_valid_for_suid (iter->fname)) +- return iter->fname; +- /* Otherwise, wrap around and try the next name. */ ++ list->current_tail = list->audit_strings[list->current_index]; + } +- /* Fall through to the procesing of audit_list. */ +- } + +- if (iter->previous == NULL) +- { +- if (audit_list == NULL) +- /* No pre-parsed audit list. */ +- return NULL; +- /* Start of audit list. The first list element is at +- audit_list->next (cyclic list). */ +- iter->previous = audit_list->next; +- return iter->previous->name; ++ /* Split the in-string audit list at the next colon colon. */ ++ size_t len = strcspn (list->current_tail, ":"); ++ if (len > 0 && len < sizeof (list->fname)) ++ { ++ memcpy (list->fname, list->current_tail, len); ++ list->fname[len] = '\0'; ++ } ++ else ++ /* Mark the name as unusable for dso_name_valid_for_suid. */ ++ list->fname[0] = '\0'; ++ ++ /* Skip over the substring and the following delimiter. */ ++ list->current_tail += len; ++ if (*list->current_tail == ':') ++ ++list->current_tail; ++ ++ /* If the name is valid, return it. */ ++ if (dso_name_valid_for_suid (list->fname)) ++ return list->fname; ++ ++ /* Otherwise wrap around to find the next list element. . */ + } +- if (iter->previous == audit_list) +- /* Cyclic list wrap-around. */ +- return NULL; +- iter->previous = iter->previous->next; +- return iter->previous->name; + } + + /* Set nonzero during loading and initialization of executable and +@@ -1060,15 +1079,13 @@ notify_audit_modules_of_loaded_object (struct link_map *map) + + /* Load all audit modules. */ + static void +-load_audit_modules (struct link_map *main_map) ++load_audit_modules (struct link_map *main_map, struct audit_list *audit_list) + { + struct audit_ifaces *last_audit = NULL; +- struct audit_list_iter al_iter; +- audit_list_iter_init (&al_iter); + + while (true) + { +- const char *name = audit_list_iter_next (&al_iter); ++ const char *name = audit_list_next (audit_list); + if (name == NULL) + break; + load_audit_module (name, &last_audit); +@@ -1100,6 +1117,9 @@ dl_main (const ElfW(Phdr) *phdr, + bool rtld_is_main = false; + void *tcbp = NULL; + ++ struct audit_list audit_list; ++ audit_list_init (&audit_list); ++ + GL(dl_init_static_tls) = &_dl_nothread_init_static_tls; + + #if defined SHARED && defined _LIBC_REENTRANT \ +@@ -1113,7 +1133,7 @@ dl_main (const ElfW(Phdr) *phdr, + GL(dl_make_stack_executable_hook) = &_dl_make_stack_executable; + + /* Process the environment variable which control the behaviour. */ +- process_envvars (&mode); ++ process_envvars (&mode, &audit_list); + + /* Set up a flag which tells we are just starting. */ + _dl_starting_up = 1; +@@ -1185,7 +1205,7 @@ dl_main (const ElfW(Phdr) *phdr, + } + else if (! strcmp (_dl_argv[1], "--audit") && _dl_argc > 2) + { +- process_dl_audit (_dl_argv[2]); ++ audit_list_add_string (&audit_list, _dl_argv[2]); + + _dl_skip_args += 2; + _dl_argc -= 2; +@@ -1612,8 +1632,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + + /* If we have auditing DSOs to load, do it now. */ + bool need_security_init = true; +- if (__glibc_unlikely (audit_list != NULL) +- || __glibc_unlikely (audit_list_string != NULL)) ++ if (audit_list.length > 0) + { + /* Since we start using the auditing DSOs right away we need to + initialize the data structures now. */ +@@ -1626,7 +1645,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + security_init (); + need_security_init = false; + +- load_audit_modules (main_map); ++ load_audit_modules (main_map, &audit_list); + } + + /* Keep track of the currently loaded modules to count how many +@@ -2500,30 +2519,6 @@ a filename can be specified using the LD_DEBUG_OUTPUT environment variable.\n"); + } + } + +-static void +-process_dl_audit (char *str) +-{ +- /* The parameter is a colon separated list of DSO names. */ +- char *p; +- +- while ((p = (strsep) (&str, ":")) != NULL) +- if (dso_name_valid_for_suid (p)) +- { +- /* This is using the local malloc, not the system malloc. The +- memory can never be freed. */ +- struct audit_list *newp = malloc (sizeof (*newp)); +- newp->name = p; +- +- if (audit_list == NULL) +- audit_list = newp->next = newp; +- else +- { +- newp->next = audit_list->next; +- audit_list = audit_list->next = newp; +- } +- } +-} +- + /* Process all environments variables the dynamic linker must recognize. + Since all of them start with `LD_' we are a bit smarter while finding + all the entries. */ +@@ -2531,7 +2526,7 @@ extern char **_environ attribute_hidden; + + + static void +-process_envvars (enum mode *modep) ++process_envvars (enum mode *modep, struct audit_list *audit_list) + { + char **runp = _environ; + char *envline; +@@ -2571,7 +2566,7 @@ process_envvars (enum mode *modep) + break; + } + if (memcmp (envline, "AUDIT", 5) == 0) +- audit_list_string = &envline[6]; ++ audit_list_add_string (audit_list, &envline[6]); + break; + + case 7: diff --git a/glibc-rh1817513-48.patch b/glibc-rh1817513-48.patch new file mode 100755 index 0000000..455373d --- /dev/null +++ b/glibc-rh1817513-48.patch @@ -0,0 +1,379 @@ +commit 8f7a75d700af809eeb4363895078fabfb3a9d7c3 +Author: Florian Weimer +Date: Mon Feb 17 16:49:40 2020 +0100 + + elf: Implement DT_AUDIT, DT_DEPAUDIT support [BZ #24943] + + binutils ld has supported --audit, --depaudit for a long time, + only support in glibc has been missing. + + Reviewed-by: Carlos O'Donell + +Conflicts: + elf/Makefile + (Test backport differences.) + +diff --git a/elf/Makefile b/elf/Makefile +index 5b0aeccb0a53c182..a6601ba84c8f4017 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -195,7 +195,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-sonamemove-link tst-sonamemove-dlopen \ + tst-auditmany tst-initfinilazyfail \ + tst-dlopenfail tst-dlopenfail-2 \ +- tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen ++ tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \ ++ tst-audit14 tst-audit15 tst-audit16 + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -310,7 +311,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-initlazyfailmod tst-finilazyfailmod \ + tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \ + tst-dlopenfailmod3 \ +- tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee ++ tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee \ ++ tst-auditlogmod-1 tst-auditlogmod-2 tst-auditlogmod-3 + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +@@ -1453,6 +1455,22 @@ $(objpfx)tst-auditmany.out: $(objpfx)tst-auditmanymod1.so \ + tst-auditmany-ENV = \ + LD_AUDIT=tst-auditmanymod1.so:tst-auditmanymod2.so:tst-auditmanymod3.so:tst-auditmanymod4.so:tst-auditmanymod5.so:tst-auditmanymod6.so:tst-auditmanymod7.so:tst-auditmanymod8.so:tst-auditmanymod9.so + ++LDFLAGS-tst-audit14 = -Wl,--audit=tst-auditlogmod-1.so ++$(objpfx)tst-auditlogmod-1.so: $(libsupport) ++$(objpfx)tst-audit14.out: $(objpfx)tst-auditlogmod-1.so ++LDFLAGS-tst-audit15 = \ ++ -Wl,--audit=tst-auditlogmod-1.so,--depaudit=tst-auditlogmod-2.so ++$(objpfx)tst-auditlogmod-2.so: $(libsupport) ++$(objpfx)tst-audit15.out: \ ++ $(objpfx)tst-auditlogmod-1.so $(objpfx)tst-auditlogmod-2.so ++LDFLAGS-tst-audit16 = \ ++ -Wl,--audit=tst-auditlogmod-1.so:tst-auditlogmod-2.so \ ++ -Wl,--depaudit=tst-auditlogmod-3.so ++$(objpfx)tst-auditlogmod-3.so: $(libsupport) ++$(objpfx)tst-audit16.out: \ ++ $(objpfx)tst-auditlogmod-1.so $(objpfx)tst-auditlogmod-2.so \ ++ $(objpfx)tst-auditlogmod-3.so ++ + # tst-sonamemove links against an older implementation of the library. + LDFLAGS-tst-sonamemove-linkmod1.so = \ + -Wl,--version-script=tst-sonamemove-linkmod1.map \ +diff --git a/elf/rtld.c b/elf/rtld.c +index c39cb8f2cd4bb1cc..d44facf5343b3301 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -151,9 +151,17 @@ static void audit_list_init (struct audit_list *); + not be called after audit_list_next. */ + static void audit_list_add_string (struct audit_list *, const char *); + ++/* Add the audit strings from the link map, found in the dynamic ++ segment at TG (either DT_AUDIT and DT_DEPAUDIT). Must be called ++ before audit_list_next. */ ++static void audit_list_add_dynamic_tag (struct audit_list *, ++ struct link_map *, ++ unsigned int tag); ++ + /* Extract the next audit module from the audit list. Only modules + for which dso_name_valid_for_suid is true are returned. Must be +- called after all the audit_list_add_string calls. */ ++ called after all the audit_list_add_string, ++ audit_list_add_dynamic_tags calls. */ + static const char *audit_list_next (struct audit_list *); + + /* This is a list of all the modes the dynamic loader can be in. */ +@@ -233,6 +241,16 @@ audit_list_add_string (struct audit_list *list, const char *string) + list->current_tail = string; + } + ++static void ++audit_list_add_dynamic_tag (struct audit_list *list, struct link_map *main_map, ++ unsigned int tag) ++{ ++ ElfW(Dyn) *info = main_map->l_info[ADDRIDX (tag)]; ++ const char *strtab = (const char *) D_PTR (main_map, l_info[DT_STRTAB]); ++ if (info != NULL) ++ audit_list_add_string (list, strtab + info->d_un.d_val); ++} ++ + static const char * + audit_list_next (struct audit_list *list) + { +@@ -1630,6 +1648,9 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + /* Assign a module ID. Do this before loading any audit modules. */ + GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid (); + ++ audit_list_add_dynamic_tag (&audit_list, main_map, DT_AUDIT); ++ audit_list_add_dynamic_tag (&audit_list, main_map, DT_DEPAUDIT); ++ + /* If we have auditing DSOs to load, do it now. */ + bool need_security_init = true; + if (audit_list.length > 0) +diff --git a/elf/tst-audit14.c b/elf/tst-audit14.c +new file mode 100644 +index 0000000000000000..27ff8db9480a98cc +--- /dev/null ++++ b/elf/tst-audit14.c +@@ -0,0 +1,46 @@ ++/* Main program with DT_AUDIT. One audit module. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* Verify what the audit module has written. This test assumes that ++ standard output has been redirected to a regular file. */ ++ FILE *fp = xfopen ("/dev/stdout", "r"); ++ ++ char *buffer = NULL; ++ size_t buffer_length = 0; ++ size_t line_length = xgetline (&buffer, &buffer_length, fp); ++ const char *message = "info: tst-auditlogmod-1.so loaded\n"; ++ TEST_COMPARE_BLOB (message, strlen (message), buffer, line_length); ++ ++ /* No more audit module output. */ ++ line_length = xgetline (&buffer, &buffer_length, fp); ++ TEST_COMPARE_BLOB ("", 0, buffer, line_length); ++ ++ free (buffer); ++ xfclose (fp); ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-audit15.c b/elf/tst-audit15.c +new file mode 100644 +index 0000000000000000..cbd1589ec40653d1 +--- /dev/null ++++ b/elf/tst-audit15.c +@@ -0,0 +1,50 @@ ++/* Main program with DT_AUDIT and DT_DEPAUDIT. Two audit modules. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* Verify what the audit modules have written. This test assumes ++ that standard output has been redirected to a regular file. */ ++ FILE *fp = xfopen ("/dev/stdout", "r"); ++ ++ char *buffer = NULL; ++ size_t buffer_length = 0; ++ size_t line_length = xgetline (&buffer, &buffer_length, fp); ++ const char *message = "info: tst-auditlogmod-1.so loaded\n"; ++ TEST_COMPARE_BLOB (message, strlen (message), buffer, line_length); ++ ++ line_length = xgetline (&buffer, &buffer_length, fp); ++ message = "info: tst-auditlogmod-2.so loaded\n"; ++ TEST_COMPARE_BLOB (message, strlen (message), buffer, line_length); ++ ++ /* No more audit module output. */ ++ line_length = xgetline (&buffer, &buffer_length, fp); ++ TEST_COMPARE_BLOB ("", 0, buffer, line_length); ++ ++ free (buffer); ++ xfclose (fp); ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-audit16.c b/elf/tst-audit16.c +new file mode 100644 +index 0000000000000000..dd6ce189ea6fffa3 +--- /dev/null ++++ b/elf/tst-audit16.c +@@ -0,0 +1,54 @@ ++/* Main program with DT_AUDIT and DT_DEPAUDIT. Three audit modules. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* Verify what the audit modules have written. This test assumes ++ that standard output has been redirected to a regular file. */ ++ FILE *fp = xfopen ("/dev/stdout", "r"); ++ ++ char *buffer = NULL; ++ size_t buffer_length = 0; ++ size_t line_length = xgetline (&buffer, &buffer_length, fp); ++ const char *message = "info: tst-auditlogmod-1.so loaded\n"; ++ TEST_COMPARE_BLOB (message, strlen (message), buffer, line_length); ++ ++ line_length = xgetline (&buffer, &buffer_length, fp); ++ message = "info: tst-auditlogmod-2.so loaded\n"; ++ TEST_COMPARE_BLOB (message, strlen (message), buffer, line_length); ++ ++ line_length = xgetline (&buffer, &buffer_length, fp); ++ message = "info: tst-auditlogmod-3.so loaded\n"; ++ TEST_COMPARE_BLOB (message, strlen (message), buffer, line_length); ++ ++ /* No more audit module output. */ ++ line_length = xgetline (&buffer, &buffer_length, fp); ++ TEST_COMPARE_BLOB ("", 0, buffer, line_length); ++ ++ free (buffer); ++ xfclose (fp); ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-auditlogmod-1.c b/elf/tst-auditlogmod-1.c +new file mode 100644 +index 0000000000000000..db9dac4c01a58dcd +--- /dev/null ++++ b/elf/tst-auditlogmod-1.c +@@ -0,0 +1,27 @@ ++/* Audit module which logs that it was loaded. Variant 1. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++ ++unsigned int ++la_version (unsigned int v) ++{ ++ write_message ("info: tst-auditlogmod-1.so loaded\n"); ++ return LAV_CURRENT; ++} +diff --git a/elf/tst-auditlogmod-2.c b/elf/tst-auditlogmod-2.c +new file mode 100644 +index 0000000000000000..871c22641c47fed0 +--- /dev/null ++++ b/elf/tst-auditlogmod-2.c +@@ -0,0 +1,27 @@ ++/* Audit module which logs that it was loaded. Variant 2. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++ ++unsigned int ++la_version (unsigned int v) ++{ ++ write_message ("info: tst-auditlogmod-2.so loaded\n"); ++ return LAV_CURRENT; ++} +diff --git a/elf/tst-auditlogmod-3.c b/elf/tst-auditlogmod-3.c +new file mode 100644 +index 0000000000000000..da2ee19d4ab9e861 +--- /dev/null ++++ b/elf/tst-auditlogmod-3.c +@@ -0,0 +1,27 @@ ++/* Audit module which logs that it was loaded. Variant 3. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++ ++unsigned int ++la_version (unsigned int v) ++{ ++ write_message ("info: tst-auditlogmod-3.so loaded\n"); ++ return LAV_CURRENT; ++} diff --git a/glibc-rh1817513-49.patch b/glibc-rh1817513-49.patch new file mode 100755 index 0000000..23a310a --- /dev/null +++ b/glibc-rh1817513-49.patch @@ -0,0 +1,163 @@ +commit 50a2d83c08a94a10f88a1fedeb7a6e3667a6b732 +Author: Florian Weimer +Date: Fri Apr 24 22:13:03 2020 +0200 + + elf: Introduce + + MIPS needs to ignore certain existing symbols during symbol lookup. + The old scheme uses the ELF_MACHINE_SYM_NO_MATCH macro, with an + inline function, within its own header, with a sysdeps override for + MIPS. This allows re-use of the function from another file (without + having to include or providing the default definition + for ELF_MACHINE_SYM_NO_MATCH). + + Reviewed-by: Carlos O'Donell + +diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c +index e4c479de9a1fd6ec..47acd134600b44b5 100644 +--- a/elf/dl-lookup.c ++++ b/elf/dl-lookup.c +@@ -28,18 +28,12 @@ + #include + #include + #include ++#include + + #include + +-/* Return nonzero if check_match should consider SYM to fail to match a +- symbol reference for some machine-specific reason. */ +-#ifndef ELF_MACHINE_SYM_NO_MATCH +-# define ELF_MACHINE_SYM_NO_MATCH(sym) 0 +-#endif +- + #define VERSTAG(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (tag)) + +- + struct sym_val + { + const ElfW(Sym) *s; +@@ -78,7 +72,7 @@ check_match (const char *const undef_name, + if (__glibc_unlikely ((sym->st_value == 0 /* No value. */ + && sym->st_shndx != SHN_ABS + && stt != STT_TLS) +- || ELF_MACHINE_SYM_NO_MATCH (sym) ++ || elf_machine_sym_no_match (sym) + || (type_class & (sym->st_shndx == SHN_UNDEF)))) + return NULL; + +diff --git a/sysdeps/generic/elf_machine_sym_no_match.h b/sysdeps/generic/elf_machine_sym_no_match.h +new file mode 100644 +index 0000000000000000..27155de4c0358460 +--- /dev/null ++++ b/sysdeps/generic/elf_machine_sym_no_match.h +@@ -0,0 +1,34 @@ ++/* Function to ignore certain symbol matches for machine-specific reasons. ++ Copyright (C) 2020 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 ++ . */ ++ ++#ifndef _ELF_MACHINE_SYM_NO_MATCH_H ++#define _ELF_MACHINE_SYM_NO_MATCH_H ++ ++#include ++#include ++ ++/* This can be customized to ignore certain symbols during lookup in ++ case there are machine-specific rules to disregard some ++ symbols. */ ++static inline bool ++elf_machine_sym_no_match (const ElfW(Sym) *sym) ++{ ++ return false; ++} ++ ++#endif /* _ELF_MACHINE_SYM_NO_MATCH_H */ +diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h +index 91fc640388a735c7..b41e10647d81843b 100644 +--- a/sysdeps/mips/dl-machine.h ++++ b/sysdeps/mips/dl-machine.h +@@ -467,21 +467,6 @@ elf_machine_plt_value (struct link_map *map, const ElfW(Rel) *reloc, + return value; + } + +-/* The semantics of zero/non-zero values of undefined symbols differs +- depending on whether the non-PIC ABI is in use. Under the non-PIC +- ABI, a non-zero value indicates that there is an address reference +- to the symbol and thus it must always be resolved (except when +- resolving a jump slot relocation) to the PLT entry whose address is +- provided as the symbol's value; a zero value indicates that this +- canonical-address behaviour is not required. Yet under the classic +- MIPS psABI, a zero value indicates that there is an address +- reference to the function and the dynamic linker must resolve the +- symbol immediately upon loading. To avoid conflict, symbols for +- which the dynamic linker must assume the non-PIC ABI semantics are +- marked with the STO_MIPS_PLT flag. */ +-#define ELF_MACHINE_SYM_NO_MATCH(sym) \ +- ((sym)->st_shndx == SHN_UNDEF && !((sym)->st_other & STO_MIPS_PLT)) +- + #endif /* !dl_machine_h */ + + #ifdef RESOLVE_MAP +diff --git a/sysdeps/mips/elf_machine_sym_no_match.h b/sysdeps/mips/elf_machine_sym_no_match.h +new file mode 100644 +index 0000000000000000..9d09e5fa2db1ff6c +--- /dev/null ++++ b/sysdeps/mips/elf_machine_sym_no_match.h +@@ -0,0 +1,43 @@ ++/* MIPS-specific handling of undefined symbols. ++ Copyright (C) 2008-2020 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 ++ . */ ++ ++#ifndef _ELF_MACHINE_SYM_NO_MATCH_H ++#define _ELF_MACHINE_SYM_NO_MATCH_H ++ ++#include ++#include ++ ++/* The semantics of zero/non-zero values of undefined symbols differs ++ depending on whether the non-PIC ABI is in use. Under the non-PIC ++ ABI, a non-zero value indicates that there is an address reference ++ to the symbol and thus it must always be resolved (except when ++ resolving a jump slot relocation) to the PLT entry whose address is ++ provided as the symbol's value; a zero value indicates that this ++ canonical-address behaviour is not required. Yet under the classic ++ MIPS psABI, a zero value indicates that there is an address ++ reference to the function and the dynamic linker must resolve the ++ symbol immediately upon loading. To avoid conflict, symbols for ++ which the dynamic linker must assume the non-PIC ABI semantics are ++ marked with the STO_MIPS_PLT flag. */ ++static inline bool ++elf_machine_sym_no_match (const ElfW(Sym) *sym) ++{ ++ return sym->st_shndx == SHN_UNDEF && !(sym->st_other & STO_MIPS_PLT); ++} ++ ++#endif /* _ELF_MACHINE_SYM_NO_MATCH_H */ diff --git a/glibc-rh1817513-5.patch b/glibc-rh1817513-5.patch new file mode 100755 index 0000000..dba4a6e --- /dev/null +++ b/glibc-rh1817513-5.patch @@ -0,0 +1,82 @@ +commit fb4c32aef64500c65c7fc95ca06d7e17d467be45 +Author: H.J. Lu +Date: Mon Aug 6 06:25:28 2018 -0700 + + x86: Move STATE_SAVE_OFFSET/STATE_SAVE_MASK to sysdep.h + + Move STATE_SAVE_OFFSET and STATE_SAVE_MASK to sysdep.h to make + sysdeps/x86/cpu-features.h a C header file. + + * sysdeps/x86/cpu-features.h (STATE_SAVE_OFFSET): Removed. + (STATE_SAVE_MASK): Likewise. + Don't check __ASSEMBLER__ to include . + * sysdeps/x86/sysdep.h (STATE_SAVE_OFFSET): New. + (STATE_SAVE_MASK): Likewise. + * sysdeps/x86_64/dl-trampoline.S: Include + instead of . + +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index 4c6d08c709eea204..d342664c64ab7aa1 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -92,18 +92,6 @@ + /* The current maximum size of the feature integer bit array. */ + #define FEATURE_INDEX_MAX 1 + +-/* Offset for fxsave/xsave area used by _dl_runtime_resolve. Also need +- space to preserve RCX, RDX, RSI, RDI, R8, R9 and RAX. It must be +- aligned to 16 bytes for fxsave and 64 bytes for xsave. */ +-#define STATE_SAVE_OFFSET (8 * 7 + 8) +- +-/* Save SSE, AVX, AVX512, mask and bound registers. */ +-#define STATE_SAVE_MASK \ +- ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7)) +- +-#ifdef __ASSEMBLER__ +-# include +-#else /* __ASSEMBLER__ */ + enum + { + COMMON_CPUID_INDEX_1 = 0, +@@ -267,8 +255,6 @@ extern const struct cpu_features *__get_cpu_features (void) + # define index_arch_XSAVEC_Usable FEATURE_INDEX_1 + # define index_arch_Prefer_FSRM FEATURE_INDEX_1 + +-#endif /* !__ASSEMBLER__ */ +- + #ifdef __x86_64__ + # define HAS_CPUID 1 + #elif defined __i586__ || defined __pentium__ +diff --git a/sysdeps/x86/sysdep.h b/sysdeps/x86/sysdep.h +index 8776ad8374e056d3..f41f4ebd425cfbaf 100644 +--- a/sysdeps/x86/sysdep.h ++++ b/sysdeps/x86/sysdep.h +@@ -48,6 +48,15 @@ enum cf_protection_level + # define SHSTK_ENABLED 0 + #endif + ++/* Offset for fxsave/xsave area used by _dl_runtime_resolve. Also need ++ space to preserve RCX, RDX, RSI, RDI, R8, R9 and RAX. It must be ++ aligned to 16 bytes for fxsave and 64 bytes for xsave. */ ++#define STATE_SAVE_OFFSET (8 * 7 + 8) ++ ++/* Save SSE, AVX, AVX512, mask and bound registers. */ ++#define STATE_SAVE_MASK \ ++ ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7)) ++ + #ifdef __ASSEMBLER__ + + /* Syntactic details of assembler. */ +diff --git a/sysdeps/x86_64/dl-trampoline.S b/sysdeps/x86_64/dl-trampoline.S +index ef1425cbb909529a..fd918510fe155733 100644 +--- a/sysdeps/x86_64/dl-trampoline.S ++++ b/sysdeps/x86_64/dl-trampoline.S +@@ -18,7 +18,7 @@ + + #include + #include +-#include ++#include + #include + + #ifndef DL_STACK_ALIGNMENT diff --git a/glibc-rh1817513-50.patch b/glibc-rh1817513-50.patch new file mode 100755 index 0000000..a3092bd --- /dev/null +++ b/glibc-rh1817513-50.patch @@ -0,0 +1,538 @@ +commit ec935dea6332cb22f9881cd1162bad156173f4b0 +Author: Florian Weimer +Date: Fri Apr 24 22:31:15 2020 +0200 + + elf: Implement __libc_early_init + + This function is defined in libc.so, and the dynamic loader calls + right after relocation has been finished, before any ELF constructors + or the preinit function is invoked. It is also used in the static + build for initializing parts of the static libc. + + To locate __libc_early_init, a direct symbol lookup function is used, + _dl_lookup_direct. It does not search the entire symbol scope and + consults merely a single link map. This function could also be used + to implement lookups in the vDSO (as an optimization). + + A per-namespace variable (libc_map) is added for locating libc.so, + to avoid repeated traversals of the search scope. It is similar to + GL(dl_initfirst). An alternative would have been to thread a context + argument from _dl_open down to _dl_map_object_from_fd (where libc.so + is identified). This could have avoided the global variable, but + the change would be larger as a result. It would not have been + possible to use this to replace GL(dl_initfirst) because that global + variable is used to pass the function pointer past the stack switch + from dl_main to the main program. Replacing that requires adding + a new argument to _dl_init, which in turn needs changes to the + architecture-specific libc.so startup code written in assembler. + + __libc_early_init should not be used to replace _dl_var_init (as + it exists today on some architectures). Instead, _dl_lookup_direct + should be used to look up a new variable symbol in libc.so, and + that should then be initialized from the dynamic loader, immediately + after the object has been loaded in _dl_map_object_from_fd (before + relocation is run). This way, more IFUNC resolvers which depend on + these variables will work. + + Reviewed-by: Carlos O'Donell + +diff --git a/csu/init-first.c b/csu/init-first.c +index 289373f9d8bd98f4..544229151ef79c67 100644 +--- a/csu/init-first.c ++++ b/csu/init-first.c +@@ -16,7 +16,6 @@ + License along with the GNU C Library; if not, see + . */ + +-#include + #include + #include + #include +@@ -80,9 +79,6 @@ _init (int argc, char **argv, char **envp) + + __init_misc (argc, argv, envp); + +- /* Initialize ctype data. */ +- __ctype_init (); +- + #if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS + __libc_global_ctors (); + #endif +diff --git a/csu/libc-start.c b/csu/libc-start.c +index dfbf195328239a17..d9c3248219d8f84f 100644 +--- a/csu/libc-start.c ++++ b/csu/libc-start.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + #include + +@@ -238,6 +239,10 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), + __cxa_atexit ((void (*) (void *)) rtld_fini, NULL, NULL); + + #ifndef SHARED ++ /* Perform early initialization. In the shared case, this function ++ is called from the dynamic loader as early as possible. */ ++ __libc_early_init (); ++ + /* Call the initializer of the libc. This is only needed here if we + are compiling for the static library in which case we haven't + run the constructors in `_dl_start_user'. */ +diff --git a/elf/Makefile b/elf/Makefile +index a6601ba84c8f4017..cbced7605ebe2443 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -25,7 +25,7 @@ headers = elf.h bits/elfclass.h link.h bits/link.h + routines = $(all-dl-routines) dl-support dl-iteratephdr \ + dl-addr dl-addr-obj enbl-secure dl-profstub \ + dl-origin dl-libc dl-sym dl-sysdep dl-error \ +- dl-reloc-static-pie ++ dl-reloc-static-pie libc_early_init + + # The core dynamic linking functions are in libc for the static and + # profiled libraries. +@@ -33,7 +33,8 @@ dl-routines = $(addprefix dl-,load lookup object reloc deps hwcaps \ + runtime init fini debug misc \ + version profile tls origin scope \ + execstack open close trampoline \ +- exception sort-maps) ++ exception sort-maps lookup-direct \ ++ call-libc-early-init) + ifeq (yes,$(use-ldconfig)) + dl-routines += dl-cache + endif +diff --git a/elf/Versions b/elf/Versions +index 705489fc51f4ac5f..3be879c4adfa74c7 100644 +--- a/elf/Versions ++++ b/elf/Versions +@@ -26,6 +26,7 @@ libc { + _dl_open_hook; _dl_open_hook2; + _dl_sym; _dl_vsym; + __libc_dlclose; __libc_dlopen_mode; __libc_dlsym; __libc_dlvsym; ++ __libc_early_init; + + # Internal error handling support. Interposes the functions in ld.so. + _dl_signal_exception; _dl_catch_exception; +diff --git a/elf/dl-call-libc-early-init.c b/elf/dl-call-libc-early-init.c +new file mode 100644 +index 0000000000000000..41e9ad9aad8b5b46 +--- /dev/null ++++ b/elf/dl-call-libc-early-init.c +@@ -0,0 +1,41 @@ ++/* Invoke the early initialization function in libc.so. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++void ++_dl_call_libc_early_init (struct link_map *libc_map) ++{ ++ /* There is nothing to do if we did not actually load libc.so. */ ++ if (libc_map == NULL) ++ return; ++ ++ const ElfW(Sym) *sym ++ = _dl_lookup_direct (libc_map, "__libc_early_init", ++ 0x069682ac, /* dl_new_hash output. */ ++ "GLIBC_PRIVATE", ++ 0x0963cf85); /* _dl_elf_hash output. */ ++ assert (sym != NULL); ++ __typeof (__libc_early_init) *early_init ++ = DL_SYMBOL_ADDRESS (libc_map, sym); ++ early_init (); ++} +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 8f8869ff524ab9f2..64da5323d0e368c1 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + /* Type for the buffer we put the ELF header and hopefully the program + header. This buffer does not really have to be too large. In most +@@ -1390,6 +1391,14 @@ cannot enable executable stack as shared object requires"); + add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB]) + + l->l_info[DT_SONAME]->d_un.d_val)); + ++ /* If we have newly loaded libc.so, update the namespace ++ description. */ ++ if (GL(dl_ns)[nsid].libc_map == NULL ++ && l->l_info[DT_SONAME] != NULL ++ && strcmp (((const char *) D_PTR (l, l_info[DT_STRTAB]) ++ + l->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) == 0) ++ GL(dl_ns)[nsid].libc_map = l; ++ + /* _dl_close can only eventually undo the module ID assignment (via + remove_slotinfo) if this function returns a pointer to a link + map. Therefore, delay this step until all possibilities for +diff --git a/elf/dl-lookup-direct.c b/elf/dl-lookup-direct.c +new file mode 100644 +index 0000000000000000..5637ae89de8a9d61 +--- /dev/null ++++ b/elf/dl-lookup-direct.c +@@ -0,0 +1,116 @@ ++/* Look up a symbol in a single specified object. ++ Copyright (C) 1995-2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++/* This function corresponds to do_lookup_x in elf/dl-lookup.c. The ++ variant here is simplified because it requires symbol ++ versioning. */ ++static const ElfW(Sym) * ++check_match (const struct link_map *const map, const char *const undef_name, ++ const char *version, uint32_t version_hash, ++ const Elf_Symndx symidx) ++{ ++ const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]); ++ const ElfW(Sym) *sym = &symtab[symidx]; ++ ++ unsigned int stt = ELFW(ST_TYPE) (sym->st_info); ++ if (__glibc_unlikely ((sym->st_value == 0 /* No value. */ ++ && sym->st_shndx != SHN_ABS ++ && stt != STT_TLS) ++ || elf_machine_sym_no_match (sym))) ++ return NULL; ++ ++ /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC, ++ STT_COMMON, STT_TLS, and STT_GNU_IFUNC since these are no ++ code/data definitions. */ ++#define ALLOWED_STT \ ++ ((1 << STT_NOTYPE) | (1 << STT_OBJECT) | (1 << STT_FUNC) \ ++ | (1 << STT_COMMON) | (1 << STT_TLS) | (1 << STT_GNU_IFUNC)) ++ if (__glibc_unlikely (((1 << stt) & ALLOWED_STT) == 0)) ++ return NULL; ++ ++ const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); ++ ++ if (strcmp (strtab + sym->st_name, undef_name) != 0) ++ /* Not the symbol we are looking for. */ ++ return NULL; ++ ++ ElfW(Half) ndx = map->l_versyms[symidx] & 0x7fff; ++ if (map->l_versions[ndx].hash != version_hash ++ || strcmp (map->l_versions[ndx].name, version) != 0) ++ /* It's not the version we want. */ ++ return NULL; ++ ++ return sym; ++} ++ ++ ++/* This function corresponds to do_lookup_x in elf/dl-lookup.c. The ++ variant here is simplified because it does not search object ++ dependencies. It is optimized for a successful lookup. */ ++const ElfW(Sym) * ++_dl_lookup_direct (struct link_map *map, ++ const char *undef_name, uint32_t new_hash, ++ const char *version, uint32_t version_hash) ++{ ++ const ElfW(Addr) *bitmask = map->l_gnu_bitmask; ++ if (__glibc_likely (bitmask != NULL)) ++ { ++ Elf32_Word bucket = map->l_gnu_buckets[new_hash % map->l_nbuckets]; ++ if (bucket != 0) ++ { ++ const Elf32_Word *hasharr = &map->l_gnu_chain_zero[bucket]; ++ ++ do ++ if (((*hasharr ^ new_hash) >> 1) == 0) ++ { ++ Elf_Symndx symidx = ELF_MACHINE_HASH_SYMIDX (map, hasharr); ++ const ElfW(Sym) *sym = check_match (map, undef_name, ++ version, version_hash, ++ symidx); ++ if (sym != NULL) ++ return sym; ++ } ++ while ((*hasharr++ & 1u) == 0); ++ } ++ } ++ else ++ { ++ /* Fallback code for lack of GNU_HASH support. */ ++ uint32_t old_hash = _dl_elf_hash (undef_name); ++ ++ /* Use the old SysV-style hash table. Search the appropriate ++ hash bucket in this object's symbol table for a definition ++ for the same symbol name. */ ++ for (Elf_Symndx symidx = map->l_buckets[old_hash % map->l_nbuckets]; ++ symidx != STN_UNDEF; ++ symidx = map->l_chain[symidx]) ++ { ++ const ElfW(Sym) *sym = check_match (map, undef_name, ++ version, version_hash, symidx); ++ if (sym != NULL) ++ return sym; ++ } ++ } ++ ++ return NULL; ++} +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 7113c4a04f0fddbc..1a77ec833cad6c55 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -57,6 +58,13 @@ struct dl_open_args + (non-negative). */ + unsigned int original_global_scope_pending_adds; + ++ /* Set to true by dl_open_worker if libc.so was already loaded into ++ the namespace at the time dl_open_worker was called. This is ++ used to determine whether libc.so early initialization has ++ already been done before, and whether to roll back the cached ++ libc_map value in the namespace in case of a dlopen failure. */ ++ bool libc_already_loaded; ++ + /* Original parameters to the program and the current environment. */ + int argc; + char **argv; +@@ -500,6 +508,11 @@ dl_open_worker (void *a) + args->nsid = call_map->l_ns; + } + ++ /* The namespace ID is now known. Keep track of whether libc.so was ++ already loaded, to determine whether it is necessary to call the ++ early initialization routine (or clear libc_map on error). */ ++ args->libc_already_loaded = GL(dl_ns)[args->nsid].libc_map != NULL; ++ + /* Retain the old value, so that it can be restored. */ + args->original_global_scope_pending_adds + = GL (dl_ns)[args->nsid]._ns_global_scope_pending_adds; +@@ -734,6 +747,11 @@ dl_open_worker (void *a) + if (relocation_in_progress) + LIBC_PROBE (reloc_complete, 3, args->nsid, r, new); + ++ /* If libc.so was not there before, attempt to call its early ++ initialization routine. */ ++ if (!args->libc_already_loaded) ++ _dl_call_libc_early_init (GL(dl_ns)[args->nsid].libc_map); ++ + #ifndef SHARED + DL_STATIC_INIT (new); + #endif +@@ -828,6 +846,8 @@ no more namespaces available for dlmopen()")); + args.caller_dlopen = caller_dlopen; + args.map = NULL; + args.nsid = nsid; ++ /* args.libc_already_loaded is always assigned by dl_open_worker ++ (before any explicit/non-local returns). */ + args.argc = argc; + args.argv = argv; + args.env = env; +@@ -856,6 +876,11 @@ no more namespaces available for dlmopen()")); + /* See if an error occurred during loading. */ + if (__glibc_unlikely (exception.errstring != NULL)) + { ++ /* Avoid keeping around a dangling reference to the libc.so link ++ map in case it has been cached in libc_map. */ ++ if (!args.libc_already_loaded) ++ GL(dl_ns)[nsid].libc_map = NULL; ++ + /* Remove the object from memory. It may be in an inconsistent + state if relocation failed, for example. */ + if (args.map) +diff --git a/elf/libc-early-init.h b/elf/libc-early-init.h +new file mode 100644 +index 0000000000000000..5185fa8895c0e11a +--- /dev/null ++++ b/elf/libc-early-init.h +@@ -0,0 +1,35 @@ ++/* Early initialization of libc.so. ++ Copyright (C) 2020 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 ++ . */ ++ ++#ifndef _LIBC_EARLY_INIT_H ++#define _LIBC_EARLY_INIT_H ++ ++struct link_map; ++ ++/* If LIBC_MAP is not NULL, look up the __libc_early_init symbol in it ++ and call this function. */ ++void _dl_call_libc_early_init (struct link_map *libc_map) attribute_hidden; ++ ++/* In the shared case, this function is defined in libc.so and invoked ++ from ld.so (or on the fist static dlopen) after complete relocation ++ of a new loaded libc.so, but before user-defined ELF constructors ++ run. In the static case, this function is called directly from the ++ startup code. */ ++void __libc_early_init (void); ++ ++#endif /* _LIBC_EARLY_INIT_H */ +diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c +new file mode 100644 +index 0000000000000000..7f4ca332b805a22c +--- /dev/null ++++ b/elf/libc_early_init.c +@@ -0,0 +1,27 @@ ++/* Early initialization of libc.so, libc.so side. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++ ++void ++__libc_early_init (void) ++{ ++ /* Initialize ctype data. */ ++ __ctype_init (); ++} +diff --git a/elf/rtld.c b/elf/rtld.c +index d44facf5343b3301..a40d5f17db0dac8b 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -44,6 +44,7 @@ + #include + #include + #include ++#include + + #include + +@@ -2365,6 +2366,9 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + rtld_timer_accum (&relocate_time, start); + } + ++ /* Relocation is complete. Perform early libc initialization. */ ++ _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map); ++ + /* Do any necessary cleanups for the startup OS interface code. + We do these now so that no calls are made after rtld re-relocation + which might be resolved to different functions than we expect. +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index a8fb0d211426e4b1..ccec08929e4ad4e7 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -336,6 +336,10 @@ struct rtld_global + recursive dlopen calls from ELF constructors. */ + unsigned int _ns_global_scope_pending_adds; + ++ /* Once libc.so has been loaded into the namespace, this points to ++ its link map. */ ++ struct link_map *libc_map; ++ + /* Search table for unique objects. */ + struct unique_sym_table + { +@@ -943,6 +947,19 @@ extern lookup_t _dl_lookup_symbol_x (const char *undef, + attribute_hidden; + + ++/* Restricted version of _dl_lookup_symbol_x. Searches MAP (and only ++ MAP) for the symbol UNDEF_NAME, with GNU hash NEW_HASH (computed ++ with dl_new_hash), symbol version VERSION, and symbol version hash ++ VERSION_HASH (computed with _dl_elf_hash). Returns a pointer to ++ the symbol table entry in MAP on success, or NULL on failure. MAP ++ must have symbol versioning information, or otherwise the result is ++ undefined. */ ++const ElfW(Sym) *_dl_lookup_direct (struct link_map *map, ++ const char *undef_name, ++ uint32_t new_hash, ++ const char *version, ++ uint32_t version_hash) attribute_hidden; ++ + /* Add the new link_map NEW to the end of the namespace list. */ + extern void _dl_add_to_namespace_list (struct link_map *new, Lmid_t nsid) + attribute_hidden; +diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c +index f8ad2ceb8e324f92..1636a40ee5d78858 100644 +--- a/sysdeps/mach/hurd/i386/init-first.c ++++ b/sysdeps/mach/hurd/i386/init-first.c +@@ -17,7 +17,6 @@ + . */ + + #include +-#include + #include + #include + #include +@@ -84,9 +83,6 @@ posixland_init (int argc, char **argv, char **envp) + #endif + __init_misc (argc, argv, envp); + +- /* Initialize ctype data. */ +- __ctype_init (); +- + #if defined SHARED && !defined NO_CTORS_DTORS_SECTIONS + __libc_global_ctors (); + #endif diff --git a/glibc-rh1817513-51.patch b/glibc-rh1817513-51.patch new file mode 100755 index 0000000..2b56755 --- /dev/null +++ b/glibc-rh1817513-51.patch @@ -0,0 +1,688 @@ +commit 92954ffa5a5662fbfde14febd7e5dcc358c85470 +Author: Carlos O'Donell +Date: Wed Jan 8 13:24:42 2020 -0500 + + localedef: Add verbose messages for failure paths. + + During testing of localedef running in a minimal container + there were several error cases which were hard to diagnose + since they appeared as strerror (errno) values printed by the + higher level functions. This change adds three new verbose + messages for potential failure paths. The new messages give + the user the opportunity to use -v and display additional + information about why localedef might be failing. I found + these messages useful myself while writing a localedef + container test for --no-hard-links. + + Since the changes cleanup the code that handle codeset + normalization we add tst-localedef-path-norm which contains + many sub-tests to verify the correct expected normalization of + codeset strings both when installing to default paths (the + only time normalization is enabled) and installing to absolute + paths. During the refactoring I created at least one + buffer-overflow which valgrind caught, but these tests did not + catch because the exec in the container had a very clean heap + with zero-initialized memory. However, between valgrind and + the tests the results are clean. + + The new tst-localedef-path-norm passes without regression on + x86_64. + + Change-Id: I28b9f680711ff00252a2cb15625b774cc58ecb9d + +diff --git a/include/programs/xasprintf.h b/include/programs/xasprintf.h +new file mode 100644 +index 0000000000000000..53193ba3837f7418 +--- /dev/null ++++ b/include/programs/xasprintf.h +@@ -0,0 +1,24 @@ ++/* asprintf with out of memory checking ++ Copyright (C) 2019 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published ++ by the Free Software Foundation; version 2 of the License, or ++ (at your option) any later version. ++ ++ This program 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 General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, see . */ ++ ++#ifndef _XASPRINTF_H ++#define _XASPRINTF_H 1 ++ ++extern char *xasprintf (const char *format, ...) ++ __attribute__ ((__format__ (__printf__, 1, 2), __warn_unused_result__)); ++ ++#endif /* xasprintf.h */ +diff --git a/locale/Makefile b/locale/Makefile +index 23a71321b6646c49..4278350cdc7be28d 100644 +--- a/locale/Makefile ++++ b/locale/Makefile +@@ -28,6 +28,7 @@ routines = setlocale findlocale loadlocale loadarchive \ + localeconv nl_langinfo nl_langinfo_l mb_cur_max \ + newlocale duplocale freelocale uselocale + tests = tst-C-locale tst-locname tst-duplocale ++tests-container = tst-localedef-path-norm + categories = ctype messages monetary numeric time paper name \ + address telephone measurement identification collate + aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name \ +@@ -54,7 +55,7 @@ localedef-modules := localedef $(categories:%=ld-%) \ + localedef-aux := md5 + locale-modules := locale locale-spec + lib-modules := charmap-dir simple-hash xmalloc xstrdup \ +- record-status ++ record-status xasprintf + + + GPERF = gperf +diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c +index d718d2e9f47382bc..9a57d2cb435b25ed 100644 +--- a/locale/programs/localedef.c ++++ b/locale/programs/localedef.c +@@ -174,14 +174,14 @@ static struct argp argp = + + /* Prototypes for local functions. */ + static void error_print (void); +-static const char *construct_output_path (char *path); +-static const char *normalize_codeset (const char *codeset, size_t name_len); ++static char *construct_output_path (char *path); ++static char *normalize_codeset (const char *codeset, size_t name_len); + + + int + main (int argc, char *argv[]) + { +- const char *output_path; ++ char *output_path; + int cannot_write_why; + struct charmap_t *charmap; + struct localedef_t global; +@@ -226,7 +226,8 @@ main (int argc, char *argv[]) + } + + /* The parameter describes the output path of the constructed files. +- If the described files cannot be written return a NULL pointer. */ ++ If the described files cannot be written return a NULL pointer. ++ We don't free output_path because we will exit. */ + output_path = construct_output_path (argv[remaining]); + if (output_path == NULL && ! no_archive) + error (4, errno, _("cannot create directory for output files")); +@@ -424,20 +425,16 @@ more_help (int key, const char *text, void *input) + { + case ARGP_KEY_HELP_EXTRA: + /* We print some extra information. */ +- if (asprintf (&tp, gettext ("\ ++ tp = xasprintf (gettext ("\ + For bug reporting instructions, please see:\n\ +-%s.\n"), REPORT_BUGS_TO) < 0) +- return NULL; +- if (asprintf (&cp, gettext ("\ ++%s.\n"), REPORT_BUGS_TO); ++ cp = xasprintf (gettext ("\ + System's directory for character maps : %s\n\ + repertoire maps: %s\n\ + locale path : %s\n\ + %s"), +- CHARMAP_PATH, REPERTOIREMAP_PATH, LOCALE_PATH, tp) < 0) +- { +- free (tp); +- return NULL; +- } ++ CHARMAP_PATH, REPERTOIREMAP_PATH, LOCALE_PATH, tp); ++ free (tp); + return cp; + default: + break; +@@ -467,15 +464,13 @@ error_print (void) + } + + +-/* The parameter to localedef describes the output path. If it does +- contain a '/' character it is a relative path. Otherwise it names the +- locale this definition is for. */ +-static const char * ++/* The parameter to localedef describes the output path. If it does contain a ++ '/' character it is a relative path. Otherwise it names the locale this ++ definition is for. The returned path must be freed by the caller. */ ++static char * + construct_output_path (char *path) + { +- const char *normal = NULL; + char *result; +- char *endp; + + if (strchr (path, '/') == NULL) + { +@@ -483,50 +478,44 @@ construct_output_path (char *path) + contains a reference to the codeset. This should be + normalized. */ + char *startp; ++ char *endp = NULL; ++ char *normal = NULL; + + startp = path; +- /* We must be prepared for finding a CEN name or a location of +- the introducing `.' where it is not possible anymore. */ ++ /* Either we have a '@' which starts a CEN name or '.' which starts the ++ codeset specification. The CEN name starts with '@' and may also have ++ a codeset specification, but we do not normalize the string after '@'. ++ If we only find the codeset specification then we normalize only the codeset ++ specification (but not anything after a subsequent '@'). */ + while (*startp != '\0' && *startp != '@' && *startp != '.') + ++startp; + if (*startp == '.') + { + /* We found a codeset specification. Now find the end. */ + endp = ++startp; ++ ++ /* Stop at the first '@', and don't normalize anything past that. */ + while (*endp != '\0' && *endp != '@') + ++endp; + + if (endp > startp) + normal = normalize_codeset (startp, endp - startp); + } +- else +- /* This is to keep gcc quiet. */ +- endp = NULL; + +- /* We put an additional '\0' at the end of the string because at +- the end of the function we need another byte for the trailing +- '/'. */ +- ssize_t n; + if (normal == NULL) +- n = asprintf (&result, "%s%s/%s%c", output_prefix ?: "", +- COMPLOCALEDIR, path, '\0'); ++ result = xasprintf ("%s%s/%s/", output_prefix ?: "", ++ COMPLOCALEDIR, path); + else +- n = asprintf (&result, "%s%s/%.*s%s%s%c", +- output_prefix ?: "", COMPLOCALEDIR, +- (int) (startp - path), path, normal, endp, '\0'); +- +- if (n < 0) +- return NULL; +- +- endp = result + n - 1; ++ result = xasprintf ("%s%s/%.*s%s%s/", ++ output_prefix ?: "", COMPLOCALEDIR, ++ (int) (startp - path), path, normal, endp ?: ""); ++ /* Free the allocated normalized codeset name. */ ++ free (normal); + } + else + { +- /* This is a user path. Please note the additional byte in the +- memory allocation. */ +- size_t len = strlen (path) + 1; +- result = xmalloc (len + 1); +- endp = mempcpy (result, path, len) - 1; ++ /* This is a user path. */ ++ result = xasprintf ("%s/", path); + + /* If the user specified an output path we cannot add the output + to the archive. */ +@@ -536,25 +525,41 @@ construct_output_path (char *path) + errno = 0; + + if (no_archive && euidaccess (result, W_OK) == -1) +- /* Perhaps the directory does not exist now. Try to create it. */ +- if (errno == ENOENT) +- { +- errno = 0; +- if (mkdir (result, 0777) < 0) +- return NULL; +- } +- +- *endp++ = '/'; +- *endp = '\0'; ++ { ++ /* Perhaps the directory does not exist now. Try to create it. */ ++ if (errno == ENOENT) ++ { ++ errno = 0; ++ if (mkdir (result, 0777) < 0) ++ { ++ record_verbose (stderr, ++ _("cannot create output path \'%s\': %s"), ++ result, strerror (errno)); ++ free (result); ++ return NULL; ++ } ++ } ++ else ++ record_verbose (stderr, ++ _("no write permission to output path \'%s\': %s"), ++ result, strerror (errno)); ++ } + + return result; + } + + +-/* Normalize codeset name. There is no standard for the codeset +- names. Normalization allows the user to use any of the common +- names. */ +-static const char * ++/* Normalize codeset name. There is no standard for the codeset names. ++ Normalization allows the user to use any of the common names e.g. UTF-8, ++ utf-8, utf8, UTF8 etc. ++ ++ We normalize using the following rules: ++ - Remove all non-alpha-numeric characters ++ - Lowercase all characters. ++ - If there are only digits assume it's an ISO standard and prefix with 'iso' ++ ++ We return the normalized string which needs to be freed by free. */ ++static char * + normalize_codeset (const char *codeset, size_t name_len) + { + int len = 0; +@@ -563,6 +568,7 @@ normalize_codeset (const char *codeset, size_t name_len) + char *wp; + size_t cnt; + ++ /* Compute the length of only the alpha-numeric characters. */ + for (cnt = 0; cnt < name_len; ++cnt) + if (isalnum (codeset[cnt])) + { +@@ -572,25 +578,24 @@ normalize_codeset (const char *codeset, size_t name_len) + only_digit = 0; + } + +- retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1); ++ /* If there were only digits we assume it's an ISO standard and we will ++ prefix with 'iso' so include space for that. We fill in the required ++ space from codeset up to the converted length. */ ++ wp = retval = xasprintf ("%s%.*s", only_digit ? "iso" : "", len, codeset); + +- if (retval != NULL) +- { +- if (only_digit) +- wp = stpcpy (retval, "iso"); +- else +- wp = retval; +- +- for (cnt = 0; cnt < name_len; ++cnt) +- if (isalpha (codeset[cnt])) +- *wp++ = tolower (codeset[cnt]); +- else if (isdigit (codeset[cnt])) +- *wp++ = codeset[cnt]; ++ /* Skip "iso". */ ++ if (only_digit) ++ wp += 3; + +- *wp = '\0'; +- } ++ /* Lowercase all characters. */ ++ for (cnt = 0; cnt < name_len; ++cnt) ++ if (isalpha (codeset[cnt])) ++ *wp++ = tolower (codeset[cnt]); ++ else if (isdigit (codeset[cnt])) ++ *wp++ = codeset[cnt]; + +- return (const char *) retval; ++ /* Return allocated and converted name for caller to free. */ ++ return retval; + } + + +diff --git a/locale/programs/localedef.h b/locale/programs/localedef.h +index 0083faceabbf3dd9..c528dbb97854dbd1 100644 +--- a/locale/programs/localedef.h ++++ b/locale/programs/localedef.h +@@ -122,6 +122,7 @@ extern const char *alias_file; + + /* Prototypes for a few program-wide used functions. */ + #include ++#include + + + /* Mark given locale as to be read. */ +diff --git a/locale/programs/xasprintf.c b/locale/programs/xasprintf.c +new file mode 100644 +index 0000000000000000..efc91a9c34074736 +--- /dev/null ++++ b/locale/programs/xasprintf.c +@@ -0,0 +1,34 @@ ++/* asprintf with out of memory checking ++ Copyright (C) 2019 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published ++ by the Free Software Foundation; version 2 of the License, or ++ (at your option) any later version. ++ ++ This program 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 General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, see . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++char * ++xasprintf (const char *format, ...) ++{ ++ va_list ap; ++ va_start (ap, format); ++ char *result; ++ if (vasprintf (&result, format, ap) < 0) ++ error (EXIT_FAILURE, 0, _("memory exhausted")); ++ va_end (ap); ++ return result; ++} +diff --git a/locale/tst-localedef-path-norm.c b/locale/tst-localedef-path-norm.c +new file mode 100644 +index 0000000000000000..2ef1d26f07084c68 +--- /dev/null ++++ b/locale/tst-localedef-path-norm.c +@@ -0,0 +1,242 @@ ++/* Test for localedef path name handling and normalization. ++ 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 ++ . */ ++ ++/* The test runs localedef with various named paths to test for expected ++ behaviours dealing with codeset name normalization. That is to say that use ++ of UTF-8, and it's variations, are normalized to utf8. Likewise that values ++ after the @ are not normalized and left as-is. The test needs to run ++ localedef with known input values and then check that the generated path ++ matches the expected value after normalization. */ ++ ++/* Note: In some cases adding -v (verbose) to localedef changes the exit ++ status to a non-zero value because some warnings are only enabled in verbose ++ mode. This should probably be changed so warnings are either present or not ++ present, regardless of verbosity. POSIX requires that any warnings cause the ++ exit status to be non-zero. */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++/* Full path to localedef. */ ++char *prog; ++ ++/* Execute localedef in a subprocess. */ ++static void ++execv_wrapper (void *args) ++{ ++ char **argv = args; ++ ++ execv (prog, argv); ++ FAIL_EXIT1 ("execv: %m"); ++} ++ ++struct test_closure ++{ ++ /* Arguments for running localedef. */ ++ const char *const argv[16]; ++ /* Expected directory name for compiled locale. */ ++ const char *exp; ++ /* Expected path to compiled locale. */ ++ const char *complocaledir; ++}; ++ ++/* Run localedef with DATA.ARGV arguments (NULL terminated), and expect path to ++ the compiled locale is "DATA.COMPLOCALEDIR/DATA.EXP". */ ++static void ++run_test (struct test_closure data) ++{ ++ const char * const *args = data.argv; ++ const char *exp = data.exp; ++ const char *complocaledir = data.complocaledir; ++ struct stat64 fs; ++ ++ /* Expected output path. */ ++ const char *path = xasprintf ("%s/%s", complocaledir, exp); ++ ++ /* Run test. */ ++ struct support_capture_subprocess result; ++ result = support_capture_subprocess (execv_wrapper, (void *)args); ++ support_capture_subprocess_check (&result, "execv", 0, sc_allow_none); ++ support_capture_subprocess_free (&result); ++ ++ /* Verify path is present and is a directory. */ ++ xstat (path, &fs); ++ TEST_VERIFY_EXIT (S_ISDIR (fs.st_mode)); ++ printf ("info: Directory '%s' exists.\n", path); ++} ++ ++static int ++do_test (void) ++{ ++ /* We are running as root inside the container. */ ++ prog = xasprintf ("%s/localedef", support_bindir_prefix); ++ ++ /* Create the needed directories: ++ - We need the default compiled locale dir for default output. ++ - We need an arbitrary absolute path for localedef output. ++ ++ Note: Writing to a non-default absolute path disables any kind ++ of path normalization since we expect the user wants the path ++ exactly as they specified it. */ ++ xmkdirp (support_complocaledir_prefix, 0777); ++ xmkdirp ("/output", 0777); ++ ++ /* It takes ~10 seconds to serially execute 9 localedef test. We ++ could run the compilations in parallel if we want to reduce test ++ time. We don't want to split this out into distinct tests because ++ it would require multiple chroots. Batching the same localedef ++ tests saves disk space during testing. */ ++ ++ /* Test 1: Expected normalization. ++ Run localedef and expect output in /usr/lib/locale/en_US1.utf8, ++ with normalization changing UTF-8 to utf8. */ ++ run_test ((struct test_closure) ++ { ++ .argv = { prog, ++ "--no-archive", ++ "-i", "en_US", ++ "-f", "UTF-8", ++ "en_US1.UTF-8", NULL }, ++ .exp = "en_US1.utf8", ++ .complocaledir = support_complocaledir_prefix ++ }); ++ ++ /* Test 2: No normalization past '@'. ++ Run localedef and expect output in /usr/lib/locale/en_US2.utf8@tEsT, ++ with normalization changing UTF-8@tEsT to utf8@tEsT (everything after ++ @ is untouched). */ ++ run_test ((struct test_closure) ++ { ++ .argv = { prog, ++ "--no-archive", ++ "-i", "en_US", ++ "-f", "UTF-8", ++ "en_US2.UTF-8@tEsT", NULL }, ++ .exp = "en_US2.utf8@tEsT", ++ .complocaledir = support_complocaledir_prefix ++ }); ++ ++ /* Test 3: No normalization past '@' despite period. ++ Run localedef and expect output in /usr/lib/locale/en_US3@tEsT.UTF-8, ++ with normalization changing nothing (everything after @ is untouched) ++ despite there being a period near the end. */ ++ run_test ((struct test_closure) ++ { ++ .argv = { prog, ++ "--no-archive", ++ "-i", "en_US", ++ "-f", "UTF-8", ++ "en_US3@tEsT.UTF-8", NULL }, ++ .exp = "en_US3@tEsT.UTF-8", ++ .complocaledir = support_complocaledir_prefix ++ }); ++ ++ /* Test 4: Normalize numeric codeset by adding 'iso' prefix. ++ Run localedef and expect output in /usr/lib/locale/en_US4.88591, ++ with normalization changing 88591 to iso88591. */ ++ run_test ((struct test_closure) ++ { ++ .argv = { prog, ++ "--no-archive", ++ "-i", "en_US", ++ "-f", "UTF-8", ++ "en_US4.88591", NULL }, ++ .exp = "en_US4.iso88591", ++ .complocaledir = support_complocaledir_prefix ++ }); ++ ++ /* Test 5: Don't add 'iso' prefix if first char is alpha. ++ Run localedef and expect output in /usr/lib/locale/en_US5.a88591, ++ with normalization changing nothing. */ ++ run_test ((struct test_closure) ++ { ++ .argv = { prog, ++ "--no-archive", ++ "-i", "en_US", ++ "-f", "UTF-8", ++ "en_US5.a88591", NULL }, ++ .exp = "en_US5.a88591", ++ .complocaledir = support_complocaledir_prefix ++ }); ++ ++ /* Test 6: Don't add 'iso' prefix if last char is alpha. ++ Run localedef and expect output in /usr/lib/locale/en_US6.88591a, ++ with normalization changing nothing. */ ++ run_test ((struct test_closure) ++ { ++ .argv = { prog, ++ "--no-archive", ++ "-i", "en_US", ++ "-f", "UTF-8", ++ "en_US6.88591a", NULL }, ++ .exp = "en_US6.88591a", ++ .complocaledir = support_complocaledir_prefix ++ }); ++ ++ /* Test 7: Don't normalize anything with an absolute path. ++ Run localedef and expect output in /output/en_US7.UTF-8, ++ with normalization changing nothing. */ ++ run_test ((struct test_closure) ++ { ++ .argv = { prog, ++ "--no-archive", ++ "-i", "en_US", ++ "-f", "UTF-8", ++ "/output/en_US7.UTF-8", NULL }, ++ .exp = "en_US7.UTF-8", ++ .complocaledir = "/output" ++ }); ++ ++ /* Test 8: Don't normalize anything with an absolute path. ++ Run localedef and expect output in /output/en_US8.UTF-8@tEsT, ++ with normalization changing nothing. */ ++ run_test ((struct test_closure) ++ { ++ .argv = { prog, ++ "--no-archive", ++ "-i", "en_US", ++ "-f", "UTF-8", ++ "/output/en_US8.UTF-8@tEsT", NULL }, ++ .exp = "en_US8.UTF-8@tEsT", ++ .complocaledir = "/output" ++ }); ++ ++ /* Test 9: Don't normalize anything with an absolute path. ++ Run localedef and expect output in /output/en_US9@tEsT.UTF-8, ++ with normalization changing nothing. */ ++ run_test ((struct test_closure) ++ { ++ .argv = { prog, ++ "--no-archive", ++ "-i", "en_US", ++ "-f", "UTF-8", ++ "/output/en_US9@tEsT.UTF-8", NULL }, ++ .exp = "en_US9@tEsT.UTF-8", ++ .complocaledir = "/output" ++ }); ++ ++ return 0; ++} ++ ++#include +diff --git a/locale/tst-localedef-path-norm.root/postclean.req b/locale/tst-localedef-path-norm.root/postclean.req +new file mode 100644 +index 0000000000000000..e69de29bb2d1d643 +diff --git a/locale/tst-localedef-path-norm.root/tst-localedef-path-norm.script b/locale/tst-localedef-path-norm.root/tst-localedef-path-norm.script +new file mode 100644 +index 0000000000000000..b0f016256a47f762 +--- /dev/null ++++ b/locale/tst-localedef-path-norm.root/tst-localedef-path-norm.script +@@ -0,0 +1,2 @@ ++# Must run localedef as root to write into default paths. ++su +diff --git a/support/Makefile b/support/Makefile +index 117cfdd4f22fc405..5808a42dce87151f 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -182,7 +182,8 @@ CFLAGS-support_paths.c = \ + -DLIBDIR_PATH=\"$(libdir)\" \ + -DBINDIR_PATH=\"$(bindir)\" \ + -DSBINDIR_PATH=\"$(sbindir)\" \ +- -DROOTSBINDIR_PATH=\"$(rootsbindir)\" ++ -DROOTSBINDIR_PATH=\"$(rootsbindir)\" \ ++ -DCOMPLOCALEDIR_PATH=\"$(complocaledir)\" + + ifeq (,$(CXX)) + LINKS_DSO_PROGRAM = links-dso-program-c +diff --git a/support/support.h b/support/support.h +index 121cc9e9b7c98ca6..3af87f85fe1b762d 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -112,6 +112,8 @@ extern const char support_bindir_prefix[]; + extern const char support_sbindir_prefix[]; + /* Corresponds to the install's sbin/ directory (without prefix). */ + extern const char support_install_rootsbindir[]; ++/* Corresponds to the install's compiled locale directory. */ ++extern const char support_complocaledir_prefix[]; + + extern ssize_t support_copy_file_range (int, off64_t *, int, off64_t *, + size_t, unsigned int); +diff --git a/support/support_paths.c b/support/support_paths.c +index eb2390227433aa70..6b15fae0f0173b1e 100644 +--- a/support/support_paths.c ++++ b/support/support_paths.c +@@ -78,3 +78,10 @@ const char support_install_rootsbindir[] = ROOTSBINDIR_PATH; + #else + # error please -DROOTSBINDIR_PATH=something in the Makefile + #endif ++ ++#ifdef COMPLOCALEDIR_PATH ++/* Corresponds to the install's compiled locale directory. */ ++const char support_complocaledir_prefix[] = COMPLOCALEDIR_PATH; ++#else ++# error please -DCOMPLOCALEDIR_PATH=something in the Makefile ++#endif diff --git a/glibc-rh1817513-52.patch b/glibc-rh1817513-52.patch new file mode 100755 index 0000000..61dbcf9 --- /dev/null +++ b/glibc-rh1817513-52.patch @@ -0,0 +1,141 @@ +commit 03e187a41d91069543cfcf33469a05912e555447 +Author: Florian Weimer +Date: Wed Apr 29 15:44:03 2020 +0200 + + elf: Add initial flag argument to __libc_early_init + + The rseq initialization should happen only for the libc in the base + namespace (in the dynamic case) or the statically linked libc. The + __libc_multiple_libcs flag does not quite cover this case at present, + so this commit introduces a flag argument to __libc_early_init, + indicating whether the libc being libc is the primary one (of the main + program). + + Reviewed-by: Carlos O'Donell + +diff --git a/csu/libc-start.c b/csu/libc-start.c +index d9c3248219d8f84f..fd0f8640eaeae34c 100644 +--- a/csu/libc-start.c ++++ b/csu/libc-start.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + #include + +@@ -241,7 +242,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), + #ifndef SHARED + /* Perform early initialization. In the shared case, this function + is called from the dynamic loader as early as possible. */ +- __libc_early_init (); ++ __libc_early_init (true); + + /* Call the initializer of the libc. This is only needed here if we + are compiling for the static library in which case we haven't +diff --git a/elf/dl-call-libc-early-init.c b/elf/dl-call-libc-early-init.c +index 41e9ad9aad8b5b46..9a84680a1ceafba2 100644 +--- a/elf/dl-call-libc-early-init.c ++++ b/elf/dl-call-libc-early-init.c +@@ -23,7 +23,7 @@ + #include + + void +-_dl_call_libc_early_init (struct link_map *libc_map) ++_dl_call_libc_early_init (struct link_map *libc_map, _Bool initial) + { + /* There is nothing to do if we did not actually load libc.so. */ + if (libc_map == NULL) +@@ -37,5 +37,5 @@ _dl_call_libc_early_init (struct link_map *libc_map) + assert (sym != NULL); + __typeof (__libc_early_init) *early_init + = DL_SYMBOL_ADDRESS (libc_map, sym); +- early_init (); ++ early_init (initial); + } +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 1a77ec833cad6c55..3d49a84596e99bf6 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -748,9 +748,22 @@ dl_open_worker (void *a) + LIBC_PROBE (reloc_complete, 3, args->nsid, r, new); + + /* If libc.so was not there before, attempt to call its early +- initialization routine. */ ++ initialization routine. Indicate to the initialization routine ++ whether the libc being initialized is the one in the base ++ namespace. */ + if (!args->libc_already_loaded) +- _dl_call_libc_early_init (GL(dl_ns)[args->nsid].libc_map); ++ { ++ struct link_map *libc_map = GL(dl_ns)[args->nsid].libc_map; ++#ifdef SHARED ++ bool initial = libc_map->l_ns == LM_ID_BASE; ++#else ++ /* In the static case, there is only one namespace, but it ++ contains a secondary libc (the primary libc is statically ++ linked). */ ++ bool initial = false; ++#endif ++ _dl_call_libc_early_init (libc_map, initial); ++ } + + #ifndef SHARED + DL_STATIC_INIT (new); +diff --git a/elf/libc-early-init.h b/elf/libc-early-init.h +index 5185fa8895c0e11a..8f7836dceaeecd5a 100644 +--- a/elf/libc-early-init.h ++++ b/elf/libc-early-init.h +@@ -22,14 +22,17 @@ + struct link_map; + + /* If LIBC_MAP is not NULL, look up the __libc_early_init symbol in it +- and call this function. */ +-void _dl_call_libc_early_init (struct link_map *libc_map) attribute_hidden; ++ and call this function, with INITIAL as the argument. */ ++void _dl_call_libc_early_init (struct link_map *libc_map, _Bool initial) ++ attribute_hidden; + + /* In the shared case, this function is defined in libc.so and invoked + from ld.so (or on the fist static dlopen) after complete relocation + of a new loaded libc.so, but before user-defined ELF constructors + run. In the static case, this function is called directly from the +- startup code. */ +-void __libc_early_init (void); ++ startup code. If INITIAL is true, the libc being initialized is ++ the libc for the main program. INITIAL is false for libcs loaded ++ for audit modules, dlmopen, and static dlopen. */ ++void __libc_early_init (_Bool initial); + + #endif /* _LIBC_EARLY_INIT_H */ +diff --git a/elf/libc_early_init.c b/elf/libc_early_init.c +index 7f4ca332b805a22c..e6c64fb526600fae 100644 +--- a/elf/libc_early_init.c ++++ b/elf/libc_early_init.c +@@ -20,7 +20,7 @@ + #include + + void +-__libc_early_init (void) ++__libc_early_init (_Bool initial) + { + /* Initialize ctype data. */ + __ctype_init (); +diff --git a/elf/rtld.c b/elf/rtld.c +index a40d5f17db0dac8b..772aff5160359b7b 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2366,8 +2366,10 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + rtld_timer_accum (&relocate_time, start); + } + +- /* Relocation is complete. Perform early libc initialization. */ +- _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map); ++ /* Relocation is complete. Perform early libc initialization. This ++ is the initial libc, even if audit modules have been loaded with ++ other libcs. */ ++ _dl_call_libc_early_init (GL(dl_ns)[LM_ID_BASE].libc_map, true); + + /* Do any necessary cleanups for the startup OS interface code. + We do these now so that no calls are made after rtld re-relocation diff --git a/glibc-rh1817513-53.patch b/glibc-rh1817513-53.patch new file mode 100755 index 0000000..fdd8a41 --- /dev/null +++ b/glibc-rh1817513-53.patch @@ -0,0 +1,86 @@ +commit 32ac0b988466785d6e3cc1dffc364bb26fc63193 +Author: mayshao +Date: Fri Apr 24 12:55:38 2020 +0800 + + x86: Add CPU Vendor ID detection support for Zhaoxin processors + + To recognize Zhaoxin CPU Vendor ID, add a new architecture type + arch_kind_zhaoxin for Vendor Zhaoxin detection. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index ade37a9bb3de86cc..c432d646ce6806a6 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -464,6 +464,60 @@ init_cpu_features (struct cpu_features *cpu_features) + } + } + } ++ /* This spells out "CentaurHauls" or " Shanghai ". */ ++ else if ((ebx == 0x746e6543 && ecx == 0x736c7561 && edx == 0x48727561) ++ || (ebx == 0x68532020 && ecx == 0x20206961 && edx == 0x68676e61)) ++ { ++ unsigned int extended_model, stepping; ++ ++ kind = arch_kind_zhaoxin; ++ ++ get_common_indices (cpu_features, &family, &model, &extended_model, ++ &stepping); ++ ++ get_extended_indices (cpu_features); ++ ++ model += extended_model; ++ if (family == 0x6) ++ { ++ if (model == 0xf || model == 0x19) ++ { ++ cpu_features->feature[index_arch_AVX_Usable] ++ &= (~bit_arch_AVX_Usable ++ & ~bit_arch_AVX2_Usable); ++ ++ cpu_features->feature[index_arch_Slow_SSE4_2] ++ |= (bit_arch_Slow_SSE4_2); ++ ++ cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load] ++ &= ~bit_arch_AVX_Fast_Unaligned_Load; ++ } ++ } ++ else if (family == 0x7) ++ { ++ if (model == 0x1b) ++ { ++ cpu_features->feature[index_arch_AVX_Usable] ++ &= (~bit_arch_AVX_Usable ++ & ~bit_arch_AVX2_Usable); ++ ++ cpu_features->feature[index_arch_Slow_SSE4_2] ++ |= bit_arch_Slow_SSE4_2; ++ ++ cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load] ++ &= ~bit_arch_AVX_Fast_Unaligned_Load; ++ } ++ else if (model == 0x3b) ++ { ++ cpu_features->feature[index_arch_AVX_Usable] ++ &= (~bit_arch_AVX_Usable ++ & ~bit_arch_AVX2_Usable); ++ ++ cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load] ++ &= ~bit_arch_AVX_Fast_Unaligned_Load; ++ } ++ } ++ } + else + { + kind = arch_kind_other; +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index 4917182e99a8ee90..388172a1c07bf979 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -53,6 +53,7 @@ enum cpu_features_kind + arch_kind_unknown = 0, + arch_kind_intel, + arch_kind_amd, ++ arch_kind_zhaoxin, + arch_kind_other + }; + diff --git a/glibc-rh1817513-54.patch b/glibc-rh1817513-54.patch new file mode 100755 index 0000000..44a747e --- /dev/null +++ b/glibc-rh1817513-54.patch @@ -0,0 +1,534 @@ +commit a98dc92dd1e278df4c501deb07985018bc2b06de +Author: mayshao-oc +Date: Sun Apr 26 13:48:27 2020 +0800 + + x86: Add cache information support for Zhaoxin processors + + To obtain Zhaoxin CPU cache information, add a new function + handle_zhaoxin(). + + Add a new function get_common_cache_info() that extracts the code + in init_cacheinfo() to get the value of the variable shared, threads. + + Add Zhaoxin branch in init_cacheinfo() for initializing variables, + such as __x86_shared_cache_size. + +diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c +index f1125f30223f5ca3..aa7cb705d546bcd0 100644 +--- a/sysdeps/x86/cacheinfo.c ++++ b/sysdeps/x86/cacheinfo.c +@@ -436,6 +436,57 @@ handle_amd (int name) + } + + ++static long int __attribute__ ((noinline)) ++handle_zhaoxin (int name) ++{ ++ unsigned int eax; ++ unsigned int ebx; ++ unsigned int ecx; ++ unsigned int edx; ++ ++ int folded_rel_name = (M(name) / 3) * 3; ++ ++ unsigned int round = 0; ++ while (1) ++ { ++ __cpuid_count (4, round, eax, ebx, ecx, edx); ++ ++ enum { null = 0, data = 1, inst = 2, uni = 3 } type = eax & 0x1f; ++ if (type == null) ++ break; ++ ++ unsigned int level = (eax >> 5) & 0x7; ++ ++ if ((level == 1 && type == data ++ && folded_rel_name == M(_SC_LEVEL1_DCACHE_SIZE)) ++ || (level == 1 && type == inst ++ && folded_rel_name == M(_SC_LEVEL1_ICACHE_SIZE)) ++ || (level == 2 && folded_rel_name == M(_SC_LEVEL2_CACHE_SIZE)) ++ || (level == 3 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE))) ++ { ++ unsigned int offset = M(name) - folded_rel_name; ++ ++ if (offset == 0) ++ /* Cache size. */ ++ return (((ebx >> 22) + 1) ++ * (((ebx >> 12) & 0x3ff) + 1) ++ * ((ebx & 0xfff) + 1) ++ * (ecx + 1)); ++ if (offset == 1) ++ return (ebx >> 22) + 1; ++ ++ assert (offset == 2); ++ return (ebx & 0xfff) + 1; ++ } ++ ++ ++round; ++ } ++ ++ /* Nothing found. */ ++ return 0; ++} ++ ++ + /* Get the value of the system variable NAME. */ + long int + attribute_hidden +@@ -449,6 +500,9 @@ __cache_sysconf (int name) + if (cpu_features->basic.kind == arch_kind_amd) + return handle_amd (name); + ++ if (cpu_features->basic.kind == arch_kind_zhaoxin) ++ return handle_zhaoxin (name); ++ + // XXX Fill in more vendors. + + /* CPU not known, we have no information. */ +@@ -482,6 +536,224 @@ int __x86_prefetchw attribute_hidden; + #endif + + ++static void ++get_common_cache_info (long int *shared_ptr, unsigned int *threads_ptr, ++ long int core) ++{ ++ unsigned int eax; ++ unsigned int ebx; ++ unsigned int ecx; ++ unsigned int edx; ++ ++ /* Number of logical processors sharing L2 cache. */ ++ int threads_l2; ++ ++ /* Number of logical processors sharing L3 cache. */ ++ int threads_l3; ++ ++ const struct cpu_features *cpu_features = __get_cpu_features (); ++ int max_cpuid = cpu_features->basic.max_cpuid; ++ unsigned int family = cpu_features->basic.family; ++ unsigned int model = cpu_features->basic.model; ++ long int shared = *shared_ptr; ++ unsigned int threads = *threads_ptr; ++ bool inclusive_cache = true; ++ bool support_count_mask = true; ++ ++ /* Try L3 first. */ ++ unsigned int level = 3; ++ ++ if (cpu_features->basic.kind == arch_kind_zhaoxin && family == 6) ++ support_count_mask = false; ++ ++ if (shared <= 0) ++ { ++ /* Try L2 otherwise. */ ++ level = 2; ++ shared = core; ++ threads_l2 = 0; ++ threads_l3 = -1; ++ } ++ else ++ { ++ threads_l2 = 0; ++ threads_l3 = 0; ++ } ++ ++ /* A value of 0 for the HTT bit indicates there is only a single ++ logical processor. */ ++ if (HAS_CPU_FEATURE (HTT)) ++ { ++ /* Figure out the number of logical threads that share the ++ highest cache level. */ ++ if (max_cpuid >= 4) ++ { ++ int i = 0; ++ ++ /* Query until cache level 2 and 3 are enumerated. */ ++ int check = 0x1 | (threads_l3 == 0) << 1; ++ do ++ { ++ __cpuid_count (4, i++, eax, ebx, ecx, edx); ++ ++ /* There seems to be a bug in at least some Pentium Ds ++ which sometimes fail to iterate all cache parameters. ++ Do not loop indefinitely here, stop in this case and ++ assume there is no such information. */ ++ if (cpu_features->basic.kind == arch_kind_intel ++ && (eax & 0x1f) == 0 ) ++ goto intel_bug_no_cache_info; ++ ++ switch ((eax >> 5) & 0x7) ++ { ++ default: ++ break; ++ case 2: ++ if ((check & 0x1)) ++ { ++ /* Get maximum number of logical processors ++ sharing L2 cache. */ ++ threads_l2 = (eax >> 14) & 0x3ff; ++ check &= ~0x1; ++ } ++ break; ++ case 3: ++ if ((check & (0x1 << 1))) ++ { ++ /* Get maximum number of logical processors ++ sharing L3 cache. */ ++ threads_l3 = (eax >> 14) & 0x3ff; ++ ++ /* Check if L2 and L3 caches are inclusive. */ ++ inclusive_cache = (edx & 0x2) != 0; ++ check &= ~(0x1 << 1); ++ } ++ break; ++ } ++ } ++ while (check); ++ ++ /* If max_cpuid >= 11, THREADS_L2/THREADS_L3 are the maximum ++ numbers of addressable IDs for logical processors sharing ++ the cache, instead of the maximum number of threads ++ sharing the cache. */ ++ if (max_cpuid >= 11 && support_count_mask) ++ { ++ /* Find the number of logical processors shipped in ++ one core and apply count mask. */ ++ i = 0; ++ ++ /* Count SMT only if there is L3 cache. Always count ++ core if there is no L3 cache. */ ++ int count = ((threads_l2 > 0 && level == 3) ++ | ((threads_l3 > 0 ++ || (threads_l2 > 0 && level == 2)) << 1)); ++ ++ while (count) ++ { ++ __cpuid_count (11, i++, eax, ebx, ecx, edx); ++ ++ int shipped = ebx & 0xff; ++ int type = ecx & 0xff00; ++ if (shipped == 0 || type == 0) ++ break; ++ else if (type == 0x100) ++ { ++ /* Count SMT. */ ++ if ((count & 0x1)) ++ { ++ int count_mask; ++ ++ /* Compute count mask. */ ++ asm ("bsr %1, %0" ++ : "=r" (count_mask) : "g" (threads_l2)); ++ count_mask = ~(-1 << (count_mask + 1)); ++ threads_l2 = (shipped - 1) & count_mask; ++ count &= ~0x1; ++ } ++ } ++ else if (type == 0x200) ++ { ++ /* Count core. */ ++ if ((count & (0x1 << 1))) ++ { ++ int count_mask; ++ int threads_core ++ = (level == 2 ? threads_l2 : threads_l3); ++ ++ /* Compute count mask. */ ++ asm ("bsr %1, %0" ++ : "=r" (count_mask) : "g" (threads_core)); ++ count_mask = ~(-1 << (count_mask + 1)); ++ threads_core = (shipped - 1) & count_mask; ++ if (level == 2) ++ threads_l2 = threads_core; ++ else ++ threads_l3 = threads_core; ++ count &= ~(0x1 << 1); ++ } ++ } ++ } ++ } ++ if (threads_l2 > 0) ++ threads_l2 += 1; ++ if (threads_l3 > 0) ++ threads_l3 += 1; ++ if (level == 2) ++ { ++ if (threads_l2) ++ { ++ threads = threads_l2; ++ if (cpu_features->basic.kind == arch_kind_intel ++ && threads > 2 ++ && family == 6) ++ switch (model) ++ { ++ case 0x37: ++ case 0x4a: ++ case 0x4d: ++ case 0x5a: ++ case 0x5d: ++ /* Silvermont has L2 cache shared by 2 cores. */ ++ threads = 2; ++ break; ++ default: ++ break; ++ } ++ } ++ } ++ else if (threads_l3) ++ threads = threads_l3; ++ } ++ else ++ { ++intel_bug_no_cache_info: ++ /* Assume that all logical threads share the highest cache ++ level. */ ++ threads ++ = ((cpu_features->cpuid[COMMON_CPUID_INDEX_1].ebx ++ >> 16) & 0xff); ++ } ++ ++ /* Cap usage of highest cache level to the number of supported ++ threads. */ ++ if (shared > 0 && threads > 0) ++ shared /= threads; ++ } ++ ++ /* Account for non-inclusive L2 and L3 caches. */ ++ if (!inclusive_cache) ++ { ++ if (threads_l2 > 0) ++ core /= threads_l2; ++ shared += core; ++ } ++ ++ *shared_ptr = shared; ++ *threads_ptr = threads; ++} ++ ++ + static void + __attribute__((constructor)) + init_cacheinfo (void) +@@ -494,211 +766,25 @@ init_cacheinfo (void) + int max_cpuid_ex; + long int data = -1; + long int shared = -1; +- unsigned int level; ++ long int core; + unsigned int threads = 0; + const struct cpu_features *cpu_features = __get_cpu_features (); +- int max_cpuid = cpu_features->basic.max_cpuid; + + if (cpu_features->basic.kind == arch_kind_intel) + { + data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, cpu_features); +- +- long int core = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features); +- bool inclusive_cache = true; +- +- /* Try L3 first. */ +- level = 3; ++ core = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features); + shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, cpu_features); + +- /* Number of logical processors sharing L2 cache. */ +- int threads_l2; +- +- /* Number of logical processors sharing L3 cache. */ +- int threads_l3; +- +- if (shared <= 0) +- { +- /* Try L2 otherwise. */ +- level = 2; +- shared = core; +- threads_l2 = 0; +- threads_l3 = -1; +- } +- else +- { +- threads_l2 = 0; +- threads_l3 = 0; +- } +- +- /* A value of 0 for the HTT bit indicates there is only a single +- logical processor. */ +- if (HAS_CPU_FEATURE (HTT)) +- { +- /* Figure out the number of logical threads that share the +- highest cache level. */ +- if (max_cpuid >= 4) +- { +- unsigned int family = cpu_features->basic.family; +- unsigned int model = cpu_features->basic.model; +- +- int i = 0; +- +- /* Query until cache level 2 and 3 are enumerated. */ +- int check = 0x1 | (threads_l3 == 0) << 1; +- do +- { +- __cpuid_count (4, i++, eax, ebx, ecx, edx); +- +- /* There seems to be a bug in at least some Pentium Ds +- which sometimes fail to iterate all cache parameters. +- Do not loop indefinitely here, stop in this case and +- assume there is no such information. */ +- if ((eax & 0x1f) == 0) +- goto intel_bug_no_cache_info; +- +- switch ((eax >> 5) & 0x7) +- { +- default: +- break; +- case 2: +- if ((check & 0x1)) +- { +- /* Get maximum number of logical processors +- sharing L2 cache. */ +- threads_l2 = (eax >> 14) & 0x3ff; +- check &= ~0x1; +- } +- break; +- case 3: +- if ((check & (0x1 << 1))) +- { +- /* Get maximum number of logical processors +- sharing L3 cache. */ +- threads_l3 = (eax >> 14) & 0x3ff; +- +- /* Check if L2 and L3 caches are inclusive. */ +- inclusive_cache = (edx & 0x2) != 0; +- check &= ~(0x1 << 1); +- } +- break; +- } +- } +- while (check); +- +- /* If max_cpuid >= 11, THREADS_L2/THREADS_L3 are the maximum +- numbers of addressable IDs for logical processors sharing +- the cache, instead of the maximum number of threads +- sharing the cache. */ +- if (max_cpuid >= 11) +- { +- /* Find the number of logical processors shipped in +- one core and apply count mask. */ +- i = 0; +- +- /* Count SMT only if there is L3 cache. Always count +- core if there is no L3 cache. */ +- int count = ((threads_l2 > 0 && level == 3) +- | ((threads_l3 > 0 +- || (threads_l2 > 0 && level == 2)) << 1)); +- +- while (count) +- { +- __cpuid_count (11, i++, eax, ebx, ecx, edx); +- +- int shipped = ebx & 0xff; +- int type = ecx & 0xff00; +- if (shipped == 0 || type == 0) +- break; +- else if (type == 0x100) +- { +- /* Count SMT. */ +- if ((count & 0x1)) +- { +- int count_mask; +- +- /* Compute count mask. */ +- asm ("bsr %1, %0" +- : "=r" (count_mask) : "g" (threads_l2)); +- count_mask = ~(-1 << (count_mask + 1)); +- threads_l2 = (shipped - 1) & count_mask; +- count &= ~0x1; +- } +- } +- else if (type == 0x200) +- { +- /* Count core. */ +- if ((count & (0x1 << 1))) +- { +- int count_mask; +- int threads_core +- = (level == 2 ? threads_l2 : threads_l3); +- +- /* Compute count mask. */ +- asm ("bsr %1, %0" +- : "=r" (count_mask) : "g" (threads_core)); +- count_mask = ~(-1 << (count_mask + 1)); +- threads_core = (shipped - 1) & count_mask; +- if (level == 2) +- threads_l2 = threads_core; +- else +- threads_l3 = threads_core; +- count &= ~(0x1 << 1); +- } +- } +- } +- } +- if (threads_l2 > 0) +- threads_l2 += 1; +- if (threads_l3 > 0) +- threads_l3 += 1; +- if (level == 2) +- { +- if (threads_l2) +- { +- threads = threads_l2; +- if (threads > 2 && family == 6) +- switch (model) +- { +- case 0x37: +- case 0x4a: +- case 0x4d: +- case 0x5a: +- case 0x5d: +- /* Silvermont has L2 cache shared by 2 cores. */ +- threads = 2; +- break; +- default: +- break; +- } +- } +- } +- else if (threads_l3) +- threads = threads_l3; +- } +- else +- { +-intel_bug_no_cache_info: +- /* Assume that all logical threads share the highest cache +- level. */ +- +- threads +- = ((cpu_features->cpuid[COMMON_CPUID_INDEX_1].ebx +- >> 16) & 0xff); +- } +- +- /* Cap usage of highest cache level to the number of supported +- threads. */ +- if (shared > 0 && threads > 0) +- shared /= threads; +- } ++ get_common_cache_info (&shared, &threads, core); ++ } ++ else if (cpu_features->basic.kind == arch_kind_zhaoxin) ++ { ++ data = handle_zhaoxin (_SC_LEVEL1_DCACHE_SIZE); ++ core = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE); ++ shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE); + +- /* Account for non-inclusive L2 and L3 caches. */ +- if (!inclusive_cache) +- { +- if (threads_l2 > 0) +- core /= threads_l2; +- shared += core; +- } ++ get_common_cache_info (&shared, &threads, core); + } + else if (cpu_features->basic.kind == arch_kind_amd) + { diff --git a/glibc-rh1817513-55.patch b/glibc-rh1817513-55.patch new file mode 100755 index 0000000..b649118 --- /dev/null +++ b/glibc-rh1817513-55.patch @@ -0,0 +1,136 @@ +commit 033362cfd7e0e1dccd6c9a2642710d6e3a7e7007 +Author: Carlos O'Donell +Date: Thu Jan 23 09:45:00 2020 -0500 + + test-container: Support $(complocaledir) and mkdirp. + + Expand the support infrastructure: + - Create $(complocaledir) in the testroot.pristine to support localedef. + - Add the variable $complocaledir to script support. + - Add the script command 'mkdirp'. + + All localedef tests which run with default paths need to have the + $(complocaledir) created in testroot.pristine. The localedef binary + will not by itself create the default path, but it will write into + the path. By adding this we can simplify the localedef tests. + + The variable $complocaledir is the value of the configured + $(complocaledir) which is the location of the compiled locales that + will be searched by the runtime by default. + + The command mkdirp will be available in script setup and will + be equivalent to running `mkdir -p`. + + The variable and command can be used to write more complex tests. + + Reviewed-by: DJ Delorie + +diff --git a/Makefile b/Makefile +index ae44b9cdd29fb0e3..3748d6f7cfb6223b 100644 +--- a/Makefile ++++ b/Makefile +@@ -371,6 +371,9 @@ $(objpfx)testroot.pristine/install.stamp : + # We need a working /bin/sh for some of the tests. + test -d $(objpfx)testroot.pristine/bin || \ + mkdir $(objpfx)testroot.pristine/bin ++ # We need the compiled locale dir for localedef tests. ++ test -d $(objpfx)testroot.pristine/$(complocaledir) || \ ++ mkdir -p $(objpfx)testroot.pristine/$(complocaledir) + cp $(objpfx)support/shell-container $(objpfx)testroot.pristine/bin/sh + cp $(objpfx)support/echo-container $(objpfx)testroot.pristine/bin/echo + cp $(objpfx)support/true-container $(objpfx)testroot.pristine/bin/true +diff --git a/support/test-container.c b/support/test-container.c +index 9eff8baeef0e9d8a..9fcc91e478038232 100644 +--- a/support/test-container.c ++++ b/support/test-container.c +@@ -72,6 +72,10 @@ int verbose = 0; + + * mkdir $buildroot/testroot.pristine/ + * install into it ++ * default glibc install ++ * create /bin for /bin/sh ++ * create $(complocaledir) so localedef tests work with default paths. ++ * install /bin/sh, /bin/echo, and /bin/true. + * rsync to $buildroot/testroot.root/ + + "Per-test" actions: +@@ -97,9 +101,23 @@ int verbose = 0; + rm FILE + cwd PATH + exec FILE +- FILE must start with $B/, $S/, $I/, $L/, or / +- (expands to build dir, source dir, install dir, library dir +- (in container), or container's root) ++ mkdirp MODE DIR ++ ++ variables: ++ $B/ build dir, equivalent to $(common-objpfx) ++ $S/ source dir, equivalent to $(srcdir) ++ $I/ install dir, equivalent to $(prefix) ++ $L/ library dir (in container), equivalent to $(libdir) ++ $complocaledir/ compiled locale dir, equivalent to $(complocaledir) ++ / container's root ++ ++ If FILE begins with any of these variables then they will be ++ substituted for the described value. ++ ++ The goal is to expose as many of the runtime's configured paths ++ via variables so they can be used to setup the container environment ++ before execution reaches the test. ++ + details: + - '#': A comment. + - 'su': Enables running test as root in the container. +@@ -108,6 +126,8 @@ int verbose = 0; + - 'rm': A minimal remove files command. + - 'cwd': set test working directory + - 'exec': change test binary location (may end in /) ++ - 'mkdirp': A minimal "mkdir -p FILE" command. ++ + * mytest.root/postclean.req causes fresh rsync (with delete) after + test if present + +@@ -859,6 +879,7 @@ main (int argc, char **argv) + int nt = tokenize (the_line, the_words, 3); + int i; + ++ /* Expand variables. */ + for (i = 1; i < nt; ++i) + { + if (memcmp (the_words[i], "$B/", 3) == 0) +@@ -875,6 +896,10 @@ main (int argc, char **argv) + the_words[i] = concat (new_root_path, + support_libdir_prefix, + the_words[i] + 2, NULL); ++ else if (memcmp (the_words[i], "$complocaledir/", 15) == 0) ++ the_words[i] = concat (new_root_path, ++ support_complocaledir_prefix, ++ the_words[i] + 14, NULL); + /* "exec" and "cwd" use inside-root paths. */ + else if (strcmp (the_words[0], "exec") != 0 + && strcmp (the_words[0], "cwd") != 0 +@@ -892,6 +917,9 @@ main (int argc, char **argv) + the_words[2] = concat (the_words[2], the_words[1], NULL); + } + ++ /* Run the following commands in the_words[0] with NT number of ++ arguments (including the command). */ ++ + if (nt == 2 && strcmp (the_words[0], "so") == 0) + { + the_words[2] = concat (new_root_path, support_libdir_prefix, +@@ -961,6 +989,14 @@ main (int argc, char **argv) + { + be_su = 1; + } ++ else if (nt == 3 && strcmp (the_words[0], "mkdirp") == 0) ++ { ++ long int m; ++ errno = 0; ++ m = strtol (the_words[1], NULL, 0); ++ TEST_COMPARE (errno, 0); ++ xmkdirp (the_words[2], m); ++ } + else if (nt > 0 && the_words[0][0] != '#') + { + fprintf (stderr, "\033[31minvalid [%s]\033[0m\n", the_words[0]); diff --git a/glibc-rh1817513-56.patch b/glibc-rh1817513-56.patch new file mode 100755 index 0000000..1cfb701 --- /dev/null +++ b/glibc-rh1817513-56.patch @@ -0,0 +1,45 @@ +commit 183083c35972611e7786c7ee0c96d7da571631ed +Author: Carlos O'Donell +Date: Wed Apr 29 16:31:29 2020 -0400 + + support: Set errno before testing it. + + In test-conainer we should set errno to 0 before calling strtol, + and check after with TEST_COMPARE. + + In tst-support_capture_subprocess we should set errno to 0 before + checking it after the call to strtol. + + Tested on x86_64. + + Reviewed-by: DJ Delorie + +diff --git a/support/test-container.c b/support/test-container.c +index 9fcc91e478038232..d7ed073812305f71 100644 +--- a/support/test-container.c ++++ b/support/test-container.c +@@ -940,7 +940,9 @@ main (int argc, char **argv) + else if (nt == 3 && strcmp (the_words[0], "chmod") == 0) + { + long int m; ++ errno = 0; + m = strtol (the_words[1], NULL, 0); ++ TEST_COMPARE (errno, 0); + if (chmod (the_words[2], m) < 0) + FAIL_EXIT1 ("chmod %s: %s\n", + the_words[2], strerror (errno)); +diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c +index 99570879eedd65b1..fe6649dda6032de2 100644 +--- a/support/tst-support_capture_subprocess.c ++++ b/support/tst-support_capture_subprocess.c +@@ -133,7 +133,9 @@ static int + parse_int (const char *str) + { + char *endptr; +- long int ret = strtol (str, &endptr, 10); ++ long int ret; ++ errno = 0; ++ ret = strtol (str, &endptr, 10); + TEST_COMPARE (errno, 0); + TEST_VERIFY (ret >= 0 && ret <= INT_MAX); + return ret; diff --git a/glibc-rh1817513-57.patch b/glibc-rh1817513-57.patch new file mode 100755 index 0000000..93ac1e4 --- /dev/null +++ b/glibc-rh1817513-57.patch @@ -0,0 +1,30 @@ +commit cad64f778aced84efdaa04ae64f8737b86f063ab +Author: Josh Triplett +Date: Tue May 19 14:41:48 2020 +0200 + + ldconfig: Default to the new format for ld.so.cache + + glibc has supported this format for close to 20 years. + +diff --git a/elf/ldconfig.c b/elf/ldconfig.c +index 5e6516688a1c192a..f31e10817dd5d665 100644 +--- a/elf/ldconfig.c ++++ b/elf/ldconfig.c +@@ -97,7 +97,7 @@ int opt_verbose; + + /* Format to support. */ + /* 0: only libc5/glibc2; 1: both; 2: only glibc 2.2. */ +-int opt_format = 1; ++int opt_format = 2; + + /* Build cache. */ + static int opt_build_cache = 1; +@@ -150,7 +150,7 @@ static const struct argp_option options[] = + { NULL, 'f', N_("CONF"), 0, N_("Use CONF as configuration file"), 0}, + { NULL, 'n', NULL, 0, N_("Only process directories specified on the command line. Don't build cache."), 0}, + { NULL, 'l', NULL, 0, N_("Manually link individual libraries."), 0}, +- { "format", 'c', N_("FORMAT"), 0, N_("Format to use: new, old or compat (default)"), 0}, ++ { "format", 'c', N_("FORMAT"), 0, N_("Format to use: new (default), old, or compat"), 0}, + { "ignore-aux-cache", 'i', NULL, 0, N_("Ignore auxiliary cache file"), 0}, + { NULL, 0, NULL, 0, NULL, 0 } + }; diff --git a/glibc-rh1817513-58.patch b/glibc-rh1817513-58.patch new file mode 100755 index 0000000..9133d56 --- /dev/null +++ b/glibc-rh1817513-58.patch @@ -0,0 +1,59 @@ +commit 76d5b2f002a1243ddba06bd646249553353f4322 +Author: H.J. Lu +Date: Thu May 21 13:36:54 2020 -0700 + + x86: Update Intel Atom processor family optimization + + Enable Intel Silvermont optimization for Intel Goldmont Plus. Detect more + Intel Airmont processors. Optimize Intel Tremont like Intel Silvermont + with rep string instructions. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index c432d646ce6806a6..2a801e1856cfe1b3 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -347,18 +347,23 @@ init_cpu_features (struct cpu_features *cpu_features) + case 0x57: + /* Knights Landing. Enable Silvermont optimizations. */ + ++ case 0x7a: ++ /* Unaligned load versions are faster than SSSE3 ++ on Goldmont Plus. */ ++ + case 0x5c: + case 0x5f: + /* Unaligned load versions are faster than SSSE3 + on Goldmont. */ + + case 0x4c: ++ case 0x5a: ++ case 0x75: + /* Airmont is a die shrink of Silvermont. */ + + case 0x37: + case 0x4a: + case 0x4d: +- case 0x5a: + case 0x5d: + /* Unaligned load versions are faster than SSSE3 + on Silvermont. */ +@@ -369,6 +374,19 @@ init_cpu_features (struct cpu_features *cpu_features) + | bit_arch_Slow_SSE4_2); + break; + ++ case 0x86: ++ case 0x96: ++ case 0x9c: ++ /* Enable rep string instructions, unaligned load, unaligned ++ copy, pminub and avoid SSE 4.2 on Tremont. */ ++ cpu_features->feature[index_arch_Fast_Rep_String] ++ |= (bit_arch_Fast_Rep_String ++ | bit_arch_Fast_Unaligned_Load ++ | bit_arch_Fast_Unaligned_Copy ++ | bit_arch_Prefer_PMINUB_for_stringop ++ | bit_arch_Slow_SSE4_2); ++ break; ++ + default: + /* Unknown family 0x06 processors. Assuming this is one + of Core i3/i5/i7 processors if AVX is available. */ diff --git a/glibc-rh1817513-59.patch b/glibc-rh1817513-59.patch new file mode 100755 index 0000000..0fbaab7 --- /dev/null +++ b/glibc-rh1817513-59.patch @@ -0,0 +1,148 @@ +commit dcbc6b83eff5b9238170bdfed834ba934150895f +Author: Florian Weimer +Date: Thu May 28 10:20:56 2020 +0200 + + elf: Do not read hwcaps from the vDSO in ld.so + + This was only ever used for the "nosegneg" flag. This approach for + passing hardware capability information creates a subtle dependency + between the kernel and userspace, and ld.so.cache contents. It seems + inappropriate for toady, where people expect to be able to run + system images which very different kernel versions. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c +index ecf00b457760e517..ae2e4ca7fe91d407 100644 +--- a/elf/dl-hwcaps.c ++++ b/elf/dl-hwcaps.c +@@ -26,12 +26,6 @@ + #include + #include + +-#ifdef _DL_FIRST_PLATFORM +-# define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT) +-#else +-# define _DL_FIRST_EXTRA _DL_HWCAP_COUNT +-#endif +- + /* Return an array of useful/necessary hardware capability names. */ + const struct r_strlenpair * + _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, +@@ -52,116 +46,12 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, + if ((masked & (1ULL << n)) != 0) + ++cnt; + +-#ifdef NEED_DL_SYSINFO_DSO +- /* The system-supplied DSO can contain a note of type 2, vendor "GNU". +- This gives us a list of names to treat as fake hwcap bits. */ +- +- const char *dsocaps = NULL; +- size_t dsocapslen = 0; +- if (GLRO(dl_sysinfo_map) != NULL) +- { +- const ElfW(Phdr) *const phdr = GLRO(dl_sysinfo_map)->l_phdr; +- const ElfW(Word) phnum = GLRO(dl_sysinfo_map)->l_phnum; +- for (uint_fast16_t i = 0; i < phnum; ++i) +- if (phdr[i].p_type == PT_NOTE) +- { +- const ElfW(Addr) start = (phdr[i].p_vaddr +- + GLRO(dl_sysinfo_map)->l_addr); +- /* NB: Some PT_NOTE segment may have alignment value of 0 +- or 1. gABI specifies that PT_NOTE segments should be +- aligned to 4 bytes in 32-bit objects and to 8 bytes in +- 64-bit objects. As a Linux extension, we also support +- 4 byte alignment in 64-bit objects. If p_align is less +- than 4, we treate alignment as 4 bytes since some note +- segments have 0 or 1 byte alignment. */ +- ElfW(Addr) align = phdr[i].p_align; +- if (align < 4) +- align = 4; +- else if (align != 4 && align != 8) +- continue; +- /* The standard ELF note layout is exactly as the anonymous struct. +- The next element is a variable length vendor name of length +- VENDORLEN (with a real length rounded to ElfW(Word)), followed +- by the data of length DATALEN (with a real length rounded to +- ElfW(Word)). */ +- const struct +- { +- ElfW(Word) vendorlen; +- ElfW(Word) datalen; +- ElfW(Word) type; +- } *note = (const void *) start; +- while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz) +- { +- /* The layout of the type 2, vendor "GNU" note is as follows: +- .long +- .long (as mask >> _DL_FIRST_EXTRA). +- .byte +- .asciz . */ +- if (note->type == NT_GNU_HWCAP +- && note->vendorlen == sizeof "GNU" +- && !memcmp ((note + 1), "GNU", sizeof "GNU") +- && note->datalen > 2 * sizeof (ElfW(Word)) + 2) +- { +- const ElfW(Word) *p +- = ((const void *) note +- + ELF_NOTE_DESC_OFFSET (sizeof "GNU", align)); +- cnt += *p++; +- ++p; /* Skip mask word. */ +- dsocaps = (const char *) p; /* Pseudo-string "name" */ +- dsocapslen = note->datalen - sizeof *p * 2; +- break; +- } +- note = ((const void *) note +- + ELF_NOTE_NEXT_OFFSET (note->vendorlen, +- note->datalen, align)); +- } +- if (dsocaps != NULL) +- break; +- } +- } +-#endif +- + /* For TLS enabled builds always add 'tls'. */ + ++cnt; + + /* Create temporary data structure to generate result table. */ + struct r_strlenpair temp[cnt]; + m = 0; +-#ifdef NEED_DL_SYSINFO_DSO +- if (dsocaps != NULL) +- { +- /* dsocaps points to the .asciz string, and -1 points to the mask +- .long just before the string. */ +- const ElfW(Word) mask = ((const ElfW(Word) *) dsocaps)[-1]; +- GLRO(dl_hwcap) |= (uint64_t) mask << _DL_FIRST_EXTRA; +- /* Note that we add the dsocaps to the set already chosen by the +- LD_HWCAP_MASK environment variable (or default HWCAP_IMPORTANT). +- So there is no way to request ignoring an OS-supplied dsocap +- string and bit like you can ignore an OS-supplied HWCAP bit. */ +- hwcap_mask |= (uint64_t) mask << _DL_FIRST_EXTRA; +-#if HAVE_TUNABLES +- TUNABLE_SET (glibc, cpu, hwcap_mask, uint64_t, hwcap_mask); +-#else +- GLRO(dl_hwcap_mask) = hwcap_mask; +-#endif +- size_t len; +- for (const char *p = dsocaps; p < dsocaps + dsocapslen; p += len + 1) +- { +- uint_fast8_t bit = *p++; +- len = strlen (p); +- +- /* Skip entries that are not enabled in the mask word. */ +- if (__glibc_likely (mask & ((ElfW(Word)) 1 << bit))) +- { +- temp[m].str = p; +- temp[m].len = len; +- ++m; +- } +- else +- --cnt; +- } +- } +-#endif + for (n = 0; masked != 0; ++n) + if ((masked & (1ULL << n)) != 0) + { diff --git a/glibc-rh1817513-6.patch b/glibc-rh1817513-6.patch new file mode 100755 index 0000000..4f8e256 --- /dev/null +++ b/glibc-rh1817513-6.patch @@ -0,0 +1,53 @@ +commit d330f31af68f96dde82840d1e9343b479a8c179e +Author: Carlos O'Donell +Date: Thu Aug 30 11:01:33 2018 -0400 + + Fix test failure with -DNDEBUG. + + The elf/tst-dlopen-aout.c test uses asserts to verify properties of the + test execution. Instead of using assert it should use xpthread_create + and xpthread_join to catch errors starting the threads and fail the + test. This shows up in Fedora 28 when building for i686-pc-linux-gnu + and using gcc 8.1.1. + + Tested on i686, and fixes a check failure with -DNDEBUG. + + Signed-off-by: Carlos O'Donell + +diff --git a/elf/tst-dlopen-aout.c b/elf/tst-dlopen-aout.c +index 9038e2096add8798..b0264515cfe62276 100644 +--- a/elf/tst-dlopen-aout.c ++++ b/elf/tst-dlopen-aout.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + __thread int x; + +@@ -45,7 +46,6 @@ do_test (int argc, char *argv[]) + { + pthread_t thr; + void *p; +- int rc; + + p = dlopen (argv[0], RTLD_LAZY); + if (p != NULL) +@@ -53,11 +53,11 @@ do_test (int argc, char *argv[]) + fprintf (stderr, "dlopen unexpectedly succeeded\n"); + return 1; + } +- rc = pthread_create (&thr, NULL, fn, NULL); +- assert (rc == 0); +- +- rc = pthread_join (thr, NULL); +- assert (rc == 0); ++ /* We create threads to force TLS allocation, which triggers ++ the original bug i.e. running out of surplus slotinfo entries ++ for TLS. */ ++ thr = xpthread_create (NULL, fn, NULL); ++ xpthread_join (thr); + } + + return 0; diff --git a/glibc-rh1817513-60.patch b/glibc-rh1817513-60.patch new file mode 100755 index 0000000..f6b4907 --- /dev/null +++ b/glibc-rh1817513-60.patch @@ -0,0 +1,151 @@ +commit 31563b68410ff8e9490c5aafca31ec71b38f87a5 +Author: Florian Weimer +Date: Thu May 28 10:21:17 2020 +0200 + + elf: Remove extra hwcap mechanism from ldconfig + + Historically, this mechanism was used to process "nosegneg" + subdirectories, and it is still used to include the "tls" + subdirectories. With nosegneg support gone from ld.so, this is part + no longer useful. + + The entire mechanism is not well-designed because it causes the + meaning of hwcap bits in ld.so.cache to depend on the kernel version + that was used to generate the cache, which makes it difficult to use + this mechanism for anything else in the future. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/ldconfig.c b/elf/ldconfig.c +index f31e10817dd5d665..7c8fd29387463a8a 100644 +--- a/elf/ldconfig.c ++++ b/elf/ldconfig.c +@@ -44,11 +44,15 @@ + + #include + +-#ifdef _DL_FIRST_PLATFORM +-# define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT) +-#else +-# define _DL_FIRST_EXTRA _DL_HWCAP_COUNT +-#endif ++/* This subpath in search path entries is always supported and ++ included in the cache for backwards compatibility. */ ++#define TLS_SUBPATH "tls" ++ ++/* The MSB of the hwcap field is set for objects in TLS_SUBPATH ++ directories. There is always TLS support in glibc, so the dynamic ++ loader does not check the bit directly. But more hwcap bits make a ++ an object more preferred, so the bit still has meaning. */ ++#define TLS_HWCAP_BIT 63 + + #ifndef LD_SO_CONF + # define LD_SO_CONF SYSCONFDIR "/ld.so.conf" +@@ -127,9 +131,6 @@ static const char *config_file; + /* Mask to use for important hardware capabilities. */ + static unsigned long int hwcap_mask = HWCAP_IMPORTANT; + +-/* Configuration-defined capabilities defined in kernel vDSOs. */ +-static const char *hwcap_extra[64 - _DL_FIRST_EXTRA]; +- + /* Name and version of program. */ + static void print_version (FILE *stream, struct argp_state *state); + void (*argp_program_version_hook) (FILE *, struct argp_state *) +@@ -186,12 +187,9 @@ is_hwcap_platform (const char *name) + if (hwcap_idx != -1) + return 1; + +- /* Is this one of the extra pseudo-hwcaps that we map beyond +- _DL_FIRST_EXTRA like "tls", or "nosegneg?" */ +- for (hwcap_idx = _DL_FIRST_EXTRA; hwcap_idx < 64; ++hwcap_idx) +- if (hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA] != NULL +- && !strcmp (name, hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA])) +- return 1; ++ /* Backwards-compatibility for the "tls" subdirectory. */ ++ if (strcmp (name, TLS_SUBPATH) == 0) ++ return 1; + + return 0; + } +@@ -226,11 +224,9 @@ path_hwcap (const char *path) + h = _dl_string_platform (ptr + 1); + if (h == (uint64_t) -1) + { +- for (h = _DL_FIRST_EXTRA; h < 64; ++h) +- if (hwcap_extra[h - _DL_FIRST_EXTRA] != NULL +- && !strcmp (ptr + 1, hwcap_extra[h - _DL_FIRST_EXTRA])) +- break; +- if (h == 64) ++ if (strcmp (ptr + 1, TLS_SUBPATH) == 0) ++ h = TLS_HWCAP_BIT; ++ else + break; + } + } +@@ -1145,52 +1141,7 @@ Warning: ignoring configuration file that cannot be opened: %s"), + parse_conf_include (filename, lineno, do_chroot, dir); + } + else if (!strncasecmp (cp, "hwcap", 5) && isblank (cp[5])) +- { +- cp += 6; +- char *p, *name = NULL; +- unsigned long int n = strtoul (cp, &cp, 0); +- if (cp != NULL && isblank (*cp)) +- while ((p = strsep (&cp, " \t")) != NULL) +- if (p[0] != '\0') +- { +- if (name == NULL) +- name = p; +- else +- { +- name = NULL; +- break; +- } +- } +- if (name == NULL) +- { +- error (EXIT_FAILURE, 0, _("%s:%u: bad syntax in hwcap line"), +- filename, lineno); +- break; +- } +- if (n >= (64 - _DL_FIRST_EXTRA)) +- error (EXIT_FAILURE, 0, +- _("%s:%u: hwcap index %lu above maximum %u"), +- filename, lineno, n, 64 - _DL_FIRST_EXTRA - 1); +- if (hwcap_extra[n] == NULL) +- { +- for (unsigned long int h = 0; h < (64 - _DL_FIRST_EXTRA); ++h) +- if (hwcap_extra[h] != NULL && !strcmp (name, hwcap_extra[h])) +- error (EXIT_FAILURE, 0, +- _("%s:%u: hwcap index %lu already defined as %s"), +- filename, lineno, h, name); +- hwcap_extra[n] = xstrdup (name); +- } +- else +- { +- if (strcmp (name, hwcap_extra[n])) +- error (EXIT_FAILURE, 0, +- _("%s:%u: hwcap index %lu already defined as %s"), +- filename, lineno, n, hwcap_extra[n]); +- if (opt_verbose) +- error (0, 0, _("%s:%u: duplicate hwcap %lu %s"), +- filename, lineno, n, name); +- } +- } ++ error (0, 0, _("%s:%u: hwcap directive ignored"), filename, lineno); + else + add_dir_1 (cp, filename, lineno); + } +@@ -1303,12 +1254,6 @@ main (int argc, char **argv) + add_dir_1 (argv[i], "", 0); + } + +- /* The last entry in hwcap_extra is reserved for the "tls" pseudo-hwcap which +- indicates support for TLS. This pseudo-hwcap is only used by old versions +- under which TLS support was optional. The entry is no longer needed, but +- must remain for compatibility. */ +- hwcap_extra[63 - _DL_FIRST_EXTRA] = "tls"; +- + set_hwcap (); + + if (opt_chroot) diff --git a/glibc-rh1817513-61.patch b/glibc-rh1817513-61.patch new file mode 100755 index 0000000..87cf249 --- /dev/null +++ b/glibc-rh1817513-61.patch @@ -0,0 +1,21 @@ +commit 9e2dc874e62b0950891b319c000b009ea12ac8c2 +Author: Girish Joshi +Date: Fri May 29 10:11:24 2020 -0300 + + build: Use FAIL_EXIT1 () on failure to exec child [BZ #23990] + + Reviewed-by: Adhemerval Zanella + +diff --git a/support/test-container.c b/support/test-container.c +index d7ed073812305f71..9975c8cb7bc9a955 100644 +--- a/support/test-container.c ++++ b/support/test-container.c +@@ -392,7 +392,7 @@ recursive_remove (char *path) + /* "rm" would have already printed a suitable error message. */ + if (! WIFEXITED (status) + || WEXITSTATUS (status) != 0) +- exit (1); ++ FAIL_EXIT1 ("exec child returned status: %d", status); + + break; + } diff --git a/glibc-rh1817513-62.patch b/glibc-rh1817513-62.patch new file mode 100755 index 0000000..77f123a --- /dev/null +++ b/glibc-rh1817513-62.patch @@ -0,0 +1,67 @@ +commit 533dd2acf7eefa969fb770fa782b20519bd4bc0f +Author: H.J. Lu +Date: Tue Jun 9 12:15:01 2020 -0700 + + Add "%d" support to _dl_debug_vdprintf + + "%d" will be used to print out signed value. + +diff --git a/elf/dl-misc.c b/elf/dl-misc.c +index 2eb81eeb0231368d..3f28de3ee9d68368 100644 +--- a/elf/dl-misc.c ++++ b/elf/dl-misc.c +@@ -167,6 +167,7 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg) + switch (*fmt) + { + /* Integer formatting. */ ++ case 'd': + case 'u': + case 'x': + { +@@ -179,11 +180,34 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg) + #else + unsigned long int num = va_arg (arg, unsigned int); + #endif ++ bool negative = false; ++ if (*fmt == 'd') ++ { ++#if LONG_MAX != INT_MAX ++ if (long_mod) ++ { ++ if ((long int) num < 0) ++ negative = true; ++ } ++ else ++ { ++ if ((int) num < 0) ++ { ++ num = (unsigned int) num; ++ negative = true; ++ } ++ } ++#else ++ if ((int) num < 0) ++ negative = true; ++#endif ++ } ++ + /* We use alloca() to allocate the buffer with the most + pessimistic guess for the size. Using alloca() allows + having more than one integer formatting in a call. */ +- char *buf = (char *) alloca (3 * sizeof (unsigned long int)); +- char *endp = &buf[3 * sizeof (unsigned long int)]; ++ char *buf = (char *) alloca (1 + 3 * sizeof (unsigned long int)); ++ char *endp = &buf[1 + 3 * sizeof (unsigned long int)]; + char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0); + + /* Pad to the width the user specified. */ +@@ -191,6 +215,9 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg) + while (endp - cp < width) + *--cp = fill; + ++ if (negative) ++ *--cp = '-'; ++ + iov[niov].iov_base = cp; + iov[niov].iov_len = endp - cp; + ++niov; diff --git a/glibc-rh1817513-63.patch b/glibc-rh1817513-63.patch new file mode 100755 index 0000000..7e42638 --- /dev/null +++ b/glibc-rh1817513-63.patch @@ -0,0 +1,62 @@ +commit e221c512c74ec42fd47b71de2981a475b38110a4 +Author: Florian Weimer +Date: Mon Jun 15 09:50:14 2020 +0200 + + ld.so: Check for new cache format first and enhance corruption check + + Now that ldconfig defaults to the new format (only), check for it + first. Also apply the corruption check added in commit 2954daf00bb4d + ("Add more checks for valid ld.so.cache file (bug 18093)") to the + new-format-only case. + + Suggested-by: Josh Triplett + +diff --git a/elf/dl-cache.c b/elf/dl-cache.c +index 6dd99a35b9f97cfb..ef37ca18fa9fb6e0 100644 +--- a/elf/dl-cache.c ++++ b/elf/dl-cache.c +@@ -199,15 +199,25 @@ _dl_load_cache_lookup (const char *name) + PROT_READ); + + /* We can handle three different cache file formats here: ++ - only the new format + - the old libc5/glibc2.0/2.1 format + - the old format with the new format in it +- - only the new format + The following checks if the cache contains any of these formats. */ +- if (file != MAP_FAILED && cachesize > sizeof *cache +- && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0 ++ if (file != MAP_FAILED && cachesize > sizeof *cache_new ++ && memcmp (file, CACHEMAGIC_VERSION_NEW, ++ sizeof CACHEMAGIC_VERSION_NEW - 1) == 0 + /* Check for corruption, avoiding overflow. */ +- && ((cachesize - sizeof *cache) / sizeof (struct file_entry) +- >= ((struct cache_file *) file)->nlibs)) ++ && ((cachesize - sizeof *cache_new) / sizeof (struct file_entry_new) ++ >= ((struct cache_file_new *) file)->nlibs)) ++ { ++ cache_new = file; ++ cache = file; ++ } ++ else if (file != MAP_FAILED && cachesize > sizeof *cache ++ && memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0 ++ /* Check for corruption, avoiding overflow. */ ++ && ((cachesize - sizeof *cache) / sizeof (struct file_entry) ++ >= ((struct cache_file *) file)->nlibs)) + { + size_t offset; + /* Looks ok. */ +@@ -223,13 +233,6 @@ _dl_load_cache_lookup (const char *name) + sizeof CACHEMAGIC_VERSION_NEW - 1) != 0) + cache_new = (void *) -1; + } +- else if (file != MAP_FAILED && cachesize > sizeof *cache_new +- && memcmp (file, CACHEMAGIC_VERSION_NEW, +- sizeof CACHEMAGIC_VERSION_NEW - 1) == 0) +- { +- cache_new = file; +- cache = file; +- } + else + { + if (file != MAP_FAILED) diff --git a/glibc-rh1817513-64.patch b/glibc-rh1817513-64.patch new file mode 100755 index 0000000..13fbc6c --- /dev/null +++ b/glibc-rh1817513-64.patch @@ -0,0 +1,21 @@ +commit b7c9bb183b799b10c09ec32e98d1843546ea4324 +Author: H.J. Lu +Date: Wed Jun 17 05:32:37 2020 -0700 + + x86: Correct bit_cpu_CLFLUSHOPT [BZ #26128] + + bit_cpu_CLFLUSHOPT should be (1u << 23), not (1u << 22). + +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index 388172a1c07bf979..7abfa046c4b8f6ac 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -465,7 +465,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_ADX (1u << 19) + #define bit_cpu_SMAP (1u << 20) + #define bit_cpu_AVX512_IFMA (1u << 21) +-#define bit_cpu_CLFLUSHOPT (1u << 22) ++#define bit_cpu_CLFLUSHOPT (1u << 23) + #define bit_cpu_CLWB (1u << 24) + #define bit_cpu_TRACE (1u << 25) + #define bit_cpu_AVX512PF (1u << 26) diff --git a/glibc-rh1817513-65.patch b/glibc-rh1817513-65.patch new file mode 100755 index 0000000..14f1c78 --- /dev/null +++ b/glibc-rh1817513-65.patch @@ -0,0 +1,68 @@ +commit 27f8864bd41f0f1b61e8e947d9a030b1a0d23df9 +Author: H.J. Lu +Date: Thu Jun 18 05:34:15 2020 -0700 + + x86: Update F16C detection [BZ #26133] + + Since F16C requires AVX, set F16C usable only when AVX is usable. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 2a801e1856cfe1b3..37619c93f8dbcc5d 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -146,6 +146,10 @@ get_common_indices (struct cpu_features *cpu_features, + if (CPU_FEATURES_CPU_P (cpu_features, XOP)) + cpu_features->feature[index_arch_XOP_Usable] + |= bit_arch_XOP_Usable; ++ /* Determine if F16C is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, F16C)) ++ cpu_features->feature[index_arch_F16C_Usable] ++ |= bit_arch_F16C_Usable; + } + + /* Check if OPMASK state, upper 256-bit of ZMM0-ZMM15 and +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index 7abfa046c4b8f6ac..f18f7520fcb7714a 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -142,6 +142,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_arch_VPCLMULQDQ_Usable (1u << 20) + #define bit_arch_XOP_Usable (1u << 21) + #define bit_arch_XSAVEC_Usable (1u << 22) ++#define bit_arch_F16C_Usable (1u << 23) + + #define index_arch_AVX_Usable FEATURE_INDEX_1 + #define index_arch_AVX2_Usable FEATURE_INDEX_1 +@@ -166,6 +167,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_arch_VPCLMULQDQ_Usable FEATURE_INDEX_1 + #define index_arch_XOP_Usable FEATURE_INDEX_1 + #define index_arch_XSAVEC_Usable FEATURE_INDEX_1 ++#define index_arch_F16C_Usable FEATURE_INDEX_1 + + /* Unused. Compiler will optimize them out. */ + #define bit_arch_SSE3_Usable (1u << 0) +@@ -179,7 +181,6 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_arch_AES_Usable (1u << 0) + #define bit_arch_XSAVE_Usable (1u << 0) + #define bit_arch_OSXSAVE_Usable (1u << 0) +-#define bit_arch_F16C_Usable (1u << 0) + #define bit_arch_RDRAND_Usable (1u << 0) + #define bit_arch_FPU_Usable (1u << 0) + #define bit_arch_TSC_Usable (1u << 0) +@@ -236,7 +237,6 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_arch_AES_Usable FEATURE_INDEX_1 + #define index_arch_XSAVE_Usable FEATURE_INDEX_1 + #define index_arch_OSXSAVE_Usable FEATURE_INDEX_1 +-#define index_arch_F16C_Usable FEATURE_INDEX_1 + #define index_arch_RDRAND_Usable FEATURE_INDEX_1 + #define index_arch_FPU_Usable FEATURE_INDEX_1 + #define index_arch_TSC_Usable FEATURE_INDEX_1 +@@ -296,7 +296,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define need_arch_feature_XSAVE 0 + #define need_arch_feature_OSXSAVE 0 + #define need_arch_feature_AVX 1 +-#define need_arch_feature_F16C 0 ++#define need_arch_feature_F16C 1 + #define need_arch_feature_RDRAND 0 + + /* EDX. */ diff --git a/glibc-rh1817513-66.patch b/glibc-rh1817513-66.patch new file mode 100755 index 0000000..04b83b4 --- /dev/null +++ b/glibc-rh1817513-66.patch @@ -0,0 +1,1123 @@ +commit ecbbadbf107ea1155ae5b71a8b7bd48f38c76731 +Author: H.J. Lu +Date: Wed Jun 17 06:34:46 2020 -0700 + + x86: Update CPU feature detection [BZ #26149] + + 1. Divide architecture features into the usable features and the preferred + features. The usable features are for correctness and can be exported in + a stable ABI. The preferred features are for performance and only for + glibc internal use. + 2. Change struct cpu_features to + + struct cpu_features + { + struct cpu_features_basic basic; + unsigned int *usable_p; + struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX]; + unsigned int usable[USABLE_FEATURE_INDEX_MAX]; + unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX]; + ... + }; + + and initialize usable_p to pointer to the usable arary so that + + struct cpu_features + { + struct cpu_features_basic basic; + unsigned int *usable_p; + struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX]; + }; + + can be exported via a stable ABI. The cpuid and usable arrays can be + expanded with backward binary compatibility for both .o and .so files. + 3. Add COMMON_CPUID_INDEX_7_ECX_1 for AVX512_BF16. + 4. Detect ENQCMD, PKS, AVX512_VP2INTERSECT, MD_CLEAR, SERIALIZE, HYBRID, + TSXLDTRK, L1D_FLUSH, CORE_CAPABILITIES and AVX512_BF16. + 5. Rename CAPABILITIES to ARCH_CAPABILITIES. + 6. Check if AVX512_VP2INTERSECT, AVX512_BF16 and PKU are usable. + 7. Update CPU feature detection test. + +diff --git a/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h b/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h +index ac694c032e7baf87..32f93bb3773a318b 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h ++++ b/sysdeps/unix/sysv/linux/x86_64/64/dl-librecon.h +@@ -33,7 +33,7 @@ + case 21: \ + if (!__libc_enable_secure \ + && memcmp (envline, "PREFER_MAP_32BIT_EXEC", 21) == 0) \ +- GLRO(dl_x86_cpu_features).feature[index_arch_Prefer_MAP_32BIT_EXEC] \ ++ GLRO(dl_x86_cpu_features).preferred[index_arch_Prefer_MAP_32BIT_EXEC] \ + |= bit_arch_Prefer_MAP_32BIT_EXEC; \ + break; + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 37619c93f8dbcc5d..7b2a5bc3ed27ec39 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -90,11 +90,18 @@ get_common_indices (struct cpu_features *cpu_features, + } + + if (cpu_features->basic.max_cpuid >= 7) +- __cpuid_count (7, 0, +- cpu_features->cpuid[COMMON_CPUID_INDEX_7].eax, +- cpu_features->cpuid[COMMON_CPUID_INDEX_7].ebx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_7].ecx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_7].edx); ++ { ++ __cpuid_count (7, 0, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_7].eax, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_7].ebx, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_7].ecx, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_7].edx); ++ __cpuid_count (7, 1, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_7_ECX_1].eax, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_7_ECX_1].ebx, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_7_ECX_1].ecx, ++ cpu_features->cpuid[COMMON_CPUID_INDEX_7_ECX_1].edx); ++ } + + if (cpu_features->basic.max_cpuid >= 0xd) + __cpuid_count (0xd, 1, +@@ -116,39 +123,39 @@ get_common_indices (struct cpu_features *cpu_features, + /* Determine if AVX is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX)) + { +- cpu_features->feature[index_arch_AVX_Usable] ++ cpu_features->usable[index_arch_AVX_Usable] + |= bit_arch_AVX_Usable; + /* The following features depend on AVX being usable. */ + /* Determine if AVX2 is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX2)) + { +- cpu_features->feature[index_arch_AVX2_Usable] ++ cpu_features->usable[index_arch_AVX2_Usable] + |= bit_arch_AVX2_Usable; + + /* Unaligned load with 256-bit AVX registers are faster on + Intel/AMD processors with AVX2. */ +- cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load] ++ cpu_features->preferred[index_arch_AVX_Fast_Unaligned_Load] + |= bit_arch_AVX_Fast_Unaligned_Load; + } + /* Determine if FMA is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, FMA)) +- cpu_features->feature[index_arch_FMA_Usable] ++ cpu_features->usable[index_arch_FMA_Usable] + |= bit_arch_FMA_Usable; + /* Determine if VAES is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, VAES)) +- cpu_features->feature[index_arch_VAES_Usable] ++ cpu_features->usable[index_arch_VAES_Usable] + |= bit_arch_VAES_Usable; + /* Determine if VPCLMULQDQ is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, VPCLMULQDQ)) +- cpu_features->feature[index_arch_VPCLMULQDQ_Usable] ++ cpu_features->usable[index_arch_VPCLMULQDQ_Usable] + |= bit_arch_VPCLMULQDQ_Usable; + /* Determine if XOP is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, XOP)) +- cpu_features->feature[index_arch_XOP_Usable] ++ cpu_features->usable[index_arch_XOP_Usable] + |= bit_arch_XOP_Usable; + /* Determine if F16C is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, F16C)) +- cpu_features->feature[index_arch_F16C_Usable] ++ cpu_features->usable[index_arch_F16C_Usable] + |= bit_arch_F16C_Usable; + } + +@@ -161,64 +168,73 @@ get_common_indices (struct cpu_features *cpu_features, + /* Determine if AVX512F is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512F)) + { +- cpu_features->feature[index_arch_AVX512F_Usable] ++ cpu_features->usable[index_arch_AVX512F_Usable] + |= bit_arch_AVX512F_Usable; + /* Determine if AVX512CD is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512CD)) +- cpu_features->feature[index_arch_AVX512CD_Usable] ++ cpu_features->usable[index_arch_AVX512CD_Usable] + |= bit_arch_AVX512CD_Usable; + /* Determine if AVX512ER is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512ER)) +- cpu_features->feature[index_arch_AVX512ER_Usable] ++ cpu_features->usable[index_arch_AVX512ER_Usable] + |= bit_arch_AVX512ER_Usable; + /* Determine if AVX512PF is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512PF)) +- cpu_features->feature[index_arch_AVX512PF_Usable] ++ cpu_features->usable[index_arch_AVX512PF_Usable] + |= bit_arch_AVX512PF_Usable; + /* Determine if AVX512VL is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512VL)) +- cpu_features->feature[index_arch_AVX512VL_Usable] ++ cpu_features->usable[index_arch_AVX512VL_Usable] + |= bit_arch_AVX512VL_Usable; + /* Determine if AVX512DQ is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512DQ)) +- cpu_features->feature[index_arch_AVX512DQ_Usable] ++ cpu_features->usable[index_arch_AVX512DQ_Usable] + |= bit_arch_AVX512DQ_Usable; + /* Determine if AVX512BW is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512BW)) +- cpu_features->feature[index_arch_AVX512BW_Usable] ++ cpu_features->usable[index_arch_AVX512BW_Usable] + |= bit_arch_AVX512BW_Usable; + /* Determine if AVX512_4FMAPS is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512_4FMAPS)) +- cpu_features->feature[index_arch_AVX512_4FMAPS_Usable] ++ cpu_features->usable[index_arch_AVX512_4FMAPS_Usable] + |= bit_arch_AVX512_4FMAPS_Usable; + /* Determine if AVX512_4VNNIW is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512_4VNNIW)) +- cpu_features->feature[index_arch_AVX512_4VNNIW_Usable] ++ cpu_features->usable[index_arch_AVX512_4VNNIW_Usable] + |= bit_arch_AVX512_4VNNIW_Usable; + /* Determine if AVX512_BITALG is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512_BITALG)) +- cpu_features->feature[index_arch_AVX512_BITALG_Usable] ++ cpu_features->usable[index_arch_AVX512_BITALG_Usable] + |= bit_arch_AVX512_BITALG_Usable; + /* Determine if AVX512_IFMA is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512_IFMA)) +- cpu_features->feature[index_arch_AVX512_IFMA_Usable] ++ cpu_features->usable[index_arch_AVX512_IFMA_Usable] + |= bit_arch_AVX512_IFMA_Usable; + /* Determine if AVX512_VBMI is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VBMI)) +- cpu_features->feature[index_arch_AVX512_VBMI_Usable] ++ cpu_features->usable[index_arch_AVX512_VBMI_Usable] + |= bit_arch_AVX512_VBMI_Usable; + /* Determine if AVX512_VBMI2 is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VBMI2)) +- cpu_features->feature[index_arch_AVX512_VBMI2_Usable] ++ cpu_features->usable[index_arch_AVX512_VBMI2_Usable] + |= bit_arch_AVX512_VBMI2_Usable; + /* Determine if is AVX512_VNNI usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VNNI)) +- cpu_features->feature[index_arch_AVX512_VNNI_Usable] ++ cpu_features->usable[index_arch_AVX512_VNNI_Usable] + |= bit_arch_AVX512_VNNI_Usable; + /* Determine if AVX512_VPOPCNTDQ is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VPOPCNTDQ)) +- cpu_features->feature[index_arch_AVX512_VPOPCNTDQ_Usable] ++ cpu_features->usable[index_arch_AVX512_VPOPCNTDQ_Usable] + |= bit_arch_AVX512_VPOPCNTDQ_Usable; ++ /* Determine if AVX512_VP2INTERSECT is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, ++ AVX512_VP2INTERSECT)) ++ cpu_features->usable[index_arch_AVX512_VP2INTERSECT_Usable] ++ |= bit_arch_AVX512_VP2INTERSECT_Usable; ++ /* Determine if AVX512_BF16 is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AVX512_BF16)) ++ cpu_features->usable[index_arch_AVX512_BF16_Usable] ++ |= bit_arch_AVX512_BF16_Usable; + } + } + } +@@ -284,13 +300,18 @@ get_common_indices (struct cpu_features *cpu_features, + { + cpu_features->xsave_state_size + = ALIGN_UP (size + STATE_SAVE_OFFSET, 64); +- cpu_features->feature[index_arch_XSAVEC_Usable] ++ cpu_features->usable[index_arch_XSAVEC_Usable] + |= bit_arch_XSAVEC_Usable; + } + } + } + } + } ++ ++ /* Determine if PKU is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, OSPKE)) ++ cpu_features->usable[index_arch_PKU_Usable] ++ |= bit_arch_PKU_Usable; + } + + _Static_assert (((index_arch_Fast_Unaligned_Load +@@ -314,6 +335,8 @@ init_cpu_features (struct cpu_features *cpu_features) + unsigned int stepping = 0; + enum cpu_features_kind kind; + ++ cpu_features->usable_p = cpu_features->usable; ++ + #if !HAS_CPUID + if (__get_cpuid_max (0, 0) == 0) + { +@@ -344,7 +367,7 @@ init_cpu_features (struct cpu_features *cpu_features) + case 0x1c: + case 0x26: + /* BSF is slow on Atom. */ +- cpu_features->feature[index_arch_Slow_BSF] ++ cpu_features->preferred[index_arch_Slow_BSF] + |= bit_arch_Slow_BSF; + break; + +@@ -371,7 +394,7 @@ init_cpu_features (struct cpu_features *cpu_features) + case 0x5d: + /* Unaligned load versions are faster than SSSE3 + on Silvermont. */ +- cpu_features->feature[index_arch_Fast_Unaligned_Load] ++ cpu_features->preferred[index_arch_Fast_Unaligned_Load] + |= (bit_arch_Fast_Unaligned_Load + | bit_arch_Fast_Unaligned_Copy + | bit_arch_Prefer_PMINUB_for_stringop +@@ -383,7 +406,7 @@ init_cpu_features (struct cpu_features *cpu_features) + case 0x9c: + /* Enable rep string instructions, unaligned load, unaligned + copy, pminub and avoid SSE 4.2 on Tremont. */ +- cpu_features->feature[index_arch_Fast_Rep_String] ++ cpu_features->preferred[index_arch_Fast_Rep_String] + |= (bit_arch_Fast_Rep_String + | bit_arch_Fast_Unaligned_Load + | bit_arch_Fast_Unaligned_Copy +@@ -407,7 +430,7 @@ init_cpu_features (struct cpu_features *cpu_features) + case 0x2f: + /* Rep string instructions, unaligned load, unaligned copy, + and pminub are fast on Intel Core i3, i5 and i7. */ +- cpu_features->feature[index_arch_Fast_Rep_String] ++ cpu_features->preferred[index_arch_Fast_Rep_String] + |= (bit_arch_Fast_Rep_String + | bit_arch_Fast_Unaligned_Load + | bit_arch_Fast_Unaligned_Copy +@@ -442,10 +465,10 @@ init_cpu_features (struct cpu_features *cpu_features) + if AVX512ER is available. Don't use AVX512 to avoid lower CPU + frequency if AVX512ER isn't available. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512ER)) +- cpu_features->feature[index_arch_Prefer_No_VZEROUPPER] ++ cpu_features->preferred[index_arch_Prefer_No_VZEROUPPER] + |= bit_arch_Prefer_No_VZEROUPPER; + else +- cpu_features->feature[index_arch_Prefer_No_AVX512] ++ cpu_features->preferred[index_arch_Prefer_No_AVX512] + |= bit_arch_Prefer_No_AVX512; + } + /* This spells out "AuthenticAMD". */ +@@ -467,7 +490,7 @@ init_cpu_features (struct cpu_features *cpu_features) + /* Since the FMA4 bit is in COMMON_CPUID_INDEX_80000001 and + FMA4 requires AVX, determine if FMA4 is usable here. */ + if (CPU_FEATURES_CPU_P (cpu_features, FMA4)) +- cpu_features->feature[index_arch_FMA4_Usable] ++ cpu_features->usable[index_arch_FMA4_Usable] + |= bit_arch_FMA4_Usable; + } + +@@ -476,13 +499,13 @@ init_cpu_features (struct cpu_features *cpu_features) + /* "Excavator" */ + if (model >= 0x60 && model <= 0x7f) + { +- cpu_features->feature[index_arch_Fast_Unaligned_Load] ++ cpu_features->preferred[index_arch_Fast_Unaligned_Load] + |= (bit_arch_Fast_Unaligned_Load + | bit_arch_Fast_Copy_Backward); + + /* Unaligned AVX loads are slower.*/ +- cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load] +- &= ~bit_arch_AVX_Fast_Unaligned_Load; ++ cpu_features->preferred[index_arch_AVX_Fast_Unaligned_Load] ++ &= ~bit_arch_AVX_Fast_Unaligned_Load; + } + } + } +@@ -504,41 +527,38 @@ init_cpu_features (struct cpu_features *cpu_features) + { + if (model == 0xf || model == 0x19) + { +- cpu_features->feature[index_arch_AVX_Usable] +- &= (~bit_arch_AVX_Usable +- & ~bit_arch_AVX2_Usable); ++ cpu_features->usable[index_arch_AVX_Usable] ++ &= ~(bit_arch_AVX_Usable | bit_arch_AVX2_Usable); + +- cpu_features->feature[index_arch_Slow_SSE4_2] +- |= (bit_arch_Slow_SSE4_2); ++ cpu_features->preferred[index_arch_Slow_SSE4_2] ++ |= bit_arch_Slow_SSE4_2; + +- cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load] +- &= ~bit_arch_AVX_Fast_Unaligned_Load; ++ cpu_features->preferred[index_arch_AVX_Fast_Unaligned_Load] ++ &= ~bit_arch_AVX_Fast_Unaligned_Load; + } + } + else if (family == 0x7) + { +- if (model == 0x1b) +- { +- cpu_features->feature[index_arch_AVX_Usable] +- &= (~bit_arch_AVX_Usable +- & ~bit_arch_AVX2_Usable); ++ if (model == 0x1b) ++ { ++ cpu_features->usable[index_arch_AVX_Usable] ++ &= ~(bit_arch_AVX_Usable | bit_arch_AVX2_Usable); + +- cpu_features->feature[index_arch_Slow_SSE4_2] +- |= bit_arch_Slow_SSE4_2; ++ cpu_features->preferred[index_arch_Slow_SSE4_2] ++ |= bit_arch_Slow_SSE4_2; ++ ++ cpu_features->preferred[index_arch_AVX_Fast_Unaligned_Load] ++ &= ~bit_arch_AVX_Fast_Unaligned_Load; ++ } ++ else if (model == 0x3b) ++ { ++ cpu_features->usable[index_arch_AVX_Usable] ++ &= ~(bit_arch_AVX_Usable | bit_arch_AVX2_Usable); + +- cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load] +- &= ~bit_arch_AVX_Fast_Unaligned_Load; +- } +- else if (model == 0x3b) +- { +- cpu_features->feature[index_arch_AVX_Usable] +- &= (~bit_arch_AVX_Usable +- & ~bit_arch_AVX2_Usable); +- +- cpu_features->feature[index_arch_AVX_Fast_Unaligned_Load] +- &= ~bit_arch_AVX_Fast_Unaligned_Load; +- } +- } ++ cpu_features->preferred[index_arch_AVX_Fast_Unaligned_Load] ++ &= ~bit_arch_AVX_Fast_Unaligned_Load; ++ } ++ } + } + else + { +@@ -548,11 +568,11 @@ init_cpu_features (struct cpu_features *cpu_features) + + /* Support i586 if CX8 is available. */ + if (CPU_FEATURES_CPU_P (cpu_features, CX8)) +- cpu_features->feature[index_arch_I586] |= bit_arch_I586; ++ cpu_features->preferred[index_arch_I586] |= bit_arch_I586; + + /* Support i686 if CMOV is available. */ + if (CPU_FEATURES_CPU_P (cpu_features, CMOV)) +- cpu_features->feature[index_arch_I686] |= bit_arch_I686; ++ cpu_features->preferred[index_arch_I686] |= bit_arch_I686; + + #if !HAS_CPUID + no_cpuid: +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index f18f7520fcb7714a..41c3855e94d16b49 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -20,12 +20,20 @@ + + enum + { +- /* The integer bit array index for the first set of internal feature ++ /* The integer bit array index for the first set of usable feature + bits. */ +- FEATURE_INDEX_1 = 0, +- FEATURE_INDEX_2, ++ USABLE_FEATURE_INDEX_1 = 0, + /* The current maximum size of the feature integer bit array. */ +- FEATURE_INDEX_MAX ++ USABLE_FEATURE_INDEX_MAX ++}; ++ ++enum ++{ ++ /* The integer bit array index for the first set of preferred feature ++ bits. */ ++ PREFERRED_FEATURE_INDEX_1 = 0, ++ /* The current maximum size of the feature integer bit array. */ ++ PREFERRED_FEATURE_INDEX_MAX + }; + + enum +@@ -36,6 +44,7 @@ enum + COMMON_CPUID_INDEX_D_ECX_1, + COMMON_CPUID_INDEX_80000007, + COMMON_CPUID_INDEX_80000008, ++ COMMON_CPUID_INDEX_7_ECX_1, + /* Keep the following line at the end. */ + COMMON_CPUID_INDEX_MAX + }; +@@ -68,9 +77,11 @@ struct cpu_features_basic + + struct cpu_features + { +- struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX]; +- unsigned int feature[FEATURE_INDEX_MAX]; + struct cpu_features_basic basic; ++ unsigned int *usable_p; ++ struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX]; ++ unsigned int usable[USABLE_FEATURE_INDEX_MAX]; ++ unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX]; + /* The state size for XSAVEC or XSAVE. The type must be unsigned long + int so that we use + +@@ -102,7 +113,7 @@ extern const struct cpu_features *__get_cpu_features (void) + # define CPU_FEATURES_CPU_P(ptr, name) \ + ((ptr->cpuid[index_cpu_##name].reg_##name & (bit_cpu_##name)) != 0) + # define CPU_FEATURES_ARCH_P(ptr, name) \ +- ((ptr->feature[index_arch_##name] & (bit_arch_##name)) != 0) ++ ((ptr->feature_##name[index_arch_##name] & (bit_arch_##name)) != 0) + + /* HAS_CPU_FEATURE evaluates to true if CPU supports the feature. */ + #define HAS_CPU_FEATURE(name) \ +@@ -112,13 +123,12 @@ extern const struct cpu_features *__get_cpu_features (void) + # define HAS_ARCH_FEATURE(name) \ + CPU_FEATURES_ARCH_P (__get_cpu_features (), name) + /* CPU_FEATURE_USABLE evaluates to true if the feature is usable. */ +-#define CPU_FEATURE_USABLE(name) \ +- ((need_arch_feature_##name && HAS_ARCH_FEATURE (name##_Usable)) \ +- || (!need_arch_feature_##name && HAS_CPU_FEATURE(name))) ++#define CPU_FEATURE_USABLE(name) \ ++ HAS_ARCH_FEATURE (name##_Usable) + + /* Architecture features. */ + +-/* FEATURE_INDEX_1. */ ++/* USABLE_FEATURE_INDEX_1. */ + #define bit_arch_AVX_Usable (1u << 0) + #define bit_arch_AVX2_Usable (1u << 1) + #define bit_arch_AVX512F_Usable (1u << 2) +@@ -143,237 +153,65 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_arch_XOP_Usable (1u << 21) + #define bit_arch_XSAVEC_Usable (1u << 22) + #define bit_arch_F16C_Usable (1u << 23) +- +-#define index_arch_AVX_Usable FEATURE_INDEX_1 +-#define index_arch_AVX2_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512F_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512CD_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512ER_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512PF_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512VL_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512BW_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512DQ_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512_4FMAPS_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512_4VNNIW_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512_BITALG_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512_IFMA_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512_VBMI_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512_VBMI2_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512_VNNI_Usable FEATURE_INDEX_1 +-#define index_arch_AVX512_VPOPCNTDQ_Usable FEATURE_INDEX_1 +-#define index_arch_FMA_Usable FEATURE_INDEX_1 +-#define index_arch_FMA4_Usable FEATURE_INDEX_1 +-#define index_arch_VAES_Usable FEATURE_INDEX_1 +-#define index_arch_VPCLMULQDQ_Usable FEATURE_INDEX_1 +-#define index_arch_XOP_Usable FEATURE_INDEX_1 +-#define index_arch_XSAVEC_Usable FEATURE_INDEX_1 +-#define index_arch_F16C_Usable FEATURE_INDEX_1 +- +-/* Unused. Compiler will optimize them out. */ +-#define bit_arch_SSE3_Usable (1u << 0) +-#define bit_arch_PCLMULQDQ_Usable (1u << 0) +-#define bit_arch_SSSE3_Usable (1u << 0) +-#define bit_arch_CMPXCHG16B_Usable (1u << 0) +-#define bit_arch_SSE4_1_Usable (1u << 0) +-#define bit_arch_SSE4_2_Usable (1u << 0) +-#define bit_arch_MOVBE_Usable (1u << 0) +-#define bit_arch_POPCNT_Usable (1u << 0) +-#define bit_arch_AES_Usable (1u << 0) +-#define bit_arch_XSAVE_Usable (1u << 0) +-#define bit_arch_OSXSAVE_Usable (1u << 0) +-#define bit_arch_RDRAND_Usable (1u << 0) +-#define bit_arch_FPU_Usable (1u << 0) +-#define bit_arch_TSC_Usable (1u << 0) +-#define bit_arch_MSR_Usable (1u << 0) +-#define bit_arch_CX8_Usable (1u << 0) +-#define bit_arch_SEP_Usable (1u << 0) +-#define bit_arch_CMOV_Usable (1u << 0) +-#define bit_arch_CLFSH_Usable (1u << 0) +-#define bit_arch_MMX_Usable (1u << 0) +-#define bit_arch_FXSR_Usable (1u << 0) +-#define bit_arch_SSE_Usable (1u << 0) +-#define bit_arch_SSE2_Usable (1u << 0) +-#define bit_arch_FSGSBASE_Usable (1u << 0) +-#define bit_arch_BMI1_Usable (1u << 0) +-#define bit_arch_HLE_Usable (1u << 0) +-#define bit_arch_BMI2_Usable (1u << 0) +-#define bit_arch_ERMS_Usable (1u << 0) +-#define bit_arch_RTM_Usable (1u << 0) +-#define bit_arch_RDSEED_Usable (1u << 0) +-#define bit_arch_ADX_Usable (1u << 0) +-#define bit_arch_CLFLUSHOPT_Usable (1u << 0) +-#define bit_arch_CLWB_Usable (1u << 0) +-#define bit_arch_SHA_Usable (1u << 0) +-#define bit_arch_PREFETCHWT1_Usable (1u << 0) +-#define bit_arch_GFNI_Usable (1u << 0) +-#define bit_arch_RDPID_Usable (1u << 0) +-#define bit_arch_CLDEMOTE_Usable (1u << 0) +-#define bit_arch_MOVDIRI_Usable (1u << 0) +-#define bit_arch_MOVDIR64B_Usable (1u << 0) +-#define bit_arch_FSRM_Usable (1u << 0) +-#define bit_arch_LAHF64_SAHF64_Usable (1u << 0) +-#define bit_arch_SVM_Usable (1u << 0) +-#define bit_arch_LZCNT_Usable (1u << 0) +-#define bit_arch_SSE4A_Usable (1u << 0) +-#define bit_arch_PREFETCHW_Usable (1u << 0) +-#define bit_arch_TBM_Usable (1u << 0) +-#define bit_arch_SYSCALL_SYSRET_Usable (1u << 0) +-#define bit_arch_RDTSCP_Usable (1u << 0) +-#define bit_arch_XSAVEOPT_Usable (1u << 0) +-#define bit_arch_XGETBV_ECX_1_Usable (1u << 0) +-#define bit_arch_XSAVES_Usable (1u << 0) +-#define bit_arch_INVARIANT_TSC_Usable (1u << 0) +-#define bit_arch_WBNOINVD_Usable (1u << 0) +- +-/* Unused. Compiler will optimize them out. */ +-#define index_arch_SSE3_Usable FEATURE_INDEX_1 +-#define index_arch_PCLMULQDQ_Usable FEATURE_INDEX_1 +-#define index_arch_SSSE3_Usable FEATURE_INDEX_1 +-#define index_arch_CMPXCHG16B_Usable FEATURE_INDEX_1 +-#define index_arch_SSE4_1_Usable FEATURE_INDEX_1 +-#define index_arch_SSE4_2_Usable FEATURE_INDEX_1 +-#define index_arch_MOVBE_Usable FEATURE_INDEX_1 +-#define index_arch_POPCNT_Usable FEATURE_INDEX_1 +-#define index_arch_AES_Usable FEATURE_INDEX_1 +-#define index_arch_XSAVE_Usable FEATURE_INDEX_1 +-#define index_arch_OSXSAVE_Usable FEATURE_INDEX_1 +-#define index_arch_RDRAND_Usable FEATURE_INDEX_1 +-#define index_arch_FPU_Usable FEATURE_INDEX_1 +-#define index_arch_TSC_Usable FEATURE_INDEX_1 +-#define index_arch_MSR_Usable FEATURE_INDEX_1 +-#define index_arch_CX8_Usable FEATURE_INDEX_1 +-#define index_arch_SEP_Usable FEATURE_INDEX_1 +-#define index_arch_CMOV_Usable FEATURE_INDEX_1 +-#define index_arch_CLFSH_Usable FEATURE_INDEX_1 +-#define index_arch_MMX_Usable FEATURE_INDEX_1 +-#define index_arch_FXSR_Usable FEATURE_INDEX_1 +-#define index_arch_SSE_Usable FEATURE_INDEX_1 +-#define index_arch_SSE2_Usable FEATURE_INDEX_1 +-#define index_arch_FSGSBASE_Usable FEATURE_INDEX_1 +-#define index_arch_BMI1_Usable FEATURE_INDEX_1 +-#define index_arch_HLE_Usable FEATURE_INDEX_1 +-#define index_arch_BMI2_Usable FEATURE_INDEX_1 +-#define index_arch_ERMS_Usable FEATURE_INDEX_1 +-#define index_arch_RTM_Usable FEATURE_INDEX_1 +-#define index_arch_RDSEED_Usable FEATURE_INDEX_1 +-#define index_arch_ADX_Usable FEATURE_INDEX_1 +-#define index_arch_CLFLUSHOPT_Usable FEATURE_INDEX_1 +-#define index_arch_CLWB_Usable FEATURE_INDEX_1 +-#define index_arch_SHA_Usable FEATURE_INDEX_1 +-#define index_arch_PREFETCHWT1_Usable FEATURE_INDEX_1 +-#define index_arch_GFNI_Usable FEATURE_INDEX_1 +-#define index_arch_RDPID_Usable FEATURE_INDEX_1 +-#define index_arch_CLDEMOTE_Usable FEATURE_INDEX_1 +-#define index_arch_MOVDIRI_Usable FEATURE_INDEX_1 +-#define index_arch_MOVDIR64B_Usable FEATURE_INDEX_1 +-#define index_arch_FSRM_Usable FEATURE_INDEX_1 +-#define index_arch_LAHF64_SAHF64_Usable FEATURE_INDEX_1 +-#define index_arch_LZCNT_Usable FEATURE_INDEX_1 +-#define index_arch_SSE4A_Usable FEATURE_INDEX_1 +-#define index_arch_PREFETCHW_Usable FEATURE_INDEX_1 +-#define index_arch_TBM_Usable FEATURE_INDEX_1 +-#define index_arch_SYSCALL_SYSRET_Usable FEATURE_INDEX_1 +-#define index_arch_RDTSCP_Usable FEATURE_INDEX_1 +-#define index_arch_XSAVEOPT_Usable FEATURE_INDEX_1 +-#define index_arch_XGETBV_ECX_1_Usable FEATURE_INDEX_1 +-#define index_arch_XSAVES_Usable FEATURE_INDEX_1 +-#define index_arch_INVARIANT_TSC_Usable FEATURE_INDEX_1 +-#define index_arch_WBNOINVD_Usable FEATURE_INDEX_1 +- +-/* COMMON_CPUID_INDEX_1. */ +- +-/* ECX. */ +-#define need_arch_feature_SSE3 0 +-#define need_arch_feature_PCLMULQDQ 0 +-#define need_arch_feature_SSSE3 0 +-#define need_arch_feature_FMA 1 +-#define need_arch_feature_CMPXCHG16B 0 +-#define need_arch_feature_SSE4_1 0 +-#define need_arch_feature_SSE4_2 0 +-#define need_arch_feature_MOVBE 0 +-#define need_arch_feature_POPCNT 0 +-#define need_arch_feature_AES 0 +-#define need_arch_feature_XSAVE 0 +-#define need_arch_feature_OSXSAVE 0 +-#define need_arch_feature_AVX 1 +-#define need_arch_feature_F16C 1 +-#define need_arch_feature_RDRAND 0 +- +-/* EDX. */ +-#define need_arch_feature_FPU 0 +-#define need_arch_feature_TSC 0 +-#define need_arch_feature_MSR 0 +-#define need_arch_feature_CX8 0 +-#define need_arch_feature_SEP 0 +-#define need_arch_feature_CMOV 0 +-#define need_arch_feature_CLFSH 0 +-#define need_arch_feature_MMX 0 +-#define need_arch_feature_FXSR 0 +-#define need_arch_feature_SSE 0 +-#define need_arch_feature_SSE2 0 +- +-/* COMMON_CPUID_INDEX_7. */ +- +-/* EBX. */ +-#define need_arch_feature_FSGSBASE 0 +-#define need_arch_feature_BMI1 0 +-#define need_arch_feature_HLE 0 +-#define need_arch_feature_AVX2 1 +-#define need_arch_feature_BMI2 0 +-#define need_arch_feature_ERMS 0 +-#define need_arch_feature_RTM 0 +-#define need_arch_feature_AVX512F 1 +-#define need_arch_feature_AVX512DQ 1 +-#define need_arch_feature_RDSEED 0 +-#define need_arch_feature_ADX 0 +-#define need_arch_feature_AVX512_IFMA 1 +-#define need_arch_feature_CLFLUSHOPT 0 +-#define need_arch_feature_CLWB 0 +-#define need_arch_feature_AVX512PF 1 +-#define need_arch_feature_AVX512ER 1 +-#define need_arch_feature_AVX512CD 1 +-#define need_arch_feature_SHA 0 +-#define need_arch_feature_AVX512BW 1 +-#define need_arch_feature_AVX512VL 1 +- +-/* ECX. */ +-#define need_arch_feature_PREFETCHWT1 0 +-#define need_arch_feature_AVX512_VBMI 1 +-#define need_arch_feature_AVX512_VBMI2 1 +-#define need_arch_feature_GFNI 0 +-#define need_arch_feature_VAES 1 +-#define need_arch_feature_VPCLMULQDQ 1 +-#define need_arch_feature_AVX512_VNNI 1 +-#define need_arch_feature_AVX512_BITALG 1 +-#define need_arch_feature_AVX512_VPOPCNTDQ 1 +-#define need_arch_feature_RDPID 0 +-#define need_arch_feature_CLDEMOTE 0 +-#define need_arch_feature_MOVDIRI 0 +-#define need_arch_feature_MOVDIR64B 0 +- +-/* EDX. */ +-#define need_arch_feature_AVX512_4VNNIW 1 +-#define need_arch_feature_AVX512_4FMAPS 1 +-#define need_arch_feature_FSRM 0 +- +-/* COMMON_CPUID_INDEX_80000001. */ +- +-/* ECX. */ +-#define need_arch_feature_LAHF64_SAHF64 0 +-#define need_arch_feature_LZCNT 0 +-#define need_arch_feature_SSE4A 0 +-#define need_arch_feature_PREFETCHW 0 +-#define need_arch_feature_XOP 1 +-#define need_arch_feature_FMA4 1 +-#define need_arch_feature_TBM 0 +-#define need_arch_feature_SYSCALL_SYSRET 0 +-#define need_arch_feature_RDTSCP 0 +-#define need_arch_feature_XSAVEOPT 0 +-#define need_arch_feature_XSAVEC 1 +-#define need_arch_feature_XGETBV_ECX_1 0 +-#define need_arch_feature_XSAVES 0 +-#define need_arch_feature_INVARIANT_TSC 0 +-#define need_arch_feature_WBNOINVD 0 ++#define bit_arch_AVX512_VP2INTERSECT_Usable (1u << 24) ++#define bit_arch_AVX512_BF16_Usable (1u << 25) ++#define bit_arch_PKU_Usable (1u << 26) ++ ++#define index_arch_AVX_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX2_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512F_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512CD_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512ER_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512PF_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512VL_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512BW_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512DQ_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512_4FMAPS_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512_4VNNIW_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512_BITALG_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512_IFMA_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512_VBMI_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512_VBMI2_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512_VNNI_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512_VPOPCNTDQ_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_FMA_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_FMA4_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_VAES_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_VPCLMULQDQ_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_XOP_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_XSAVEC_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_F16C_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512_VP2INTERSECT_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AVX512_BF16_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_PKU_Usable USABLE_FEATURE_INDEX_1 ++ ++#define feature_AVX_Usable usable ++#define feature_AVX2_Usable usable ++#define feature_AVX512F_Usable usable ++#define feature_AVX512CD_Usable usable ++#define feature_AVX512ER_Usable usable ++#define feature_AVX512PF_Usable usable ++#define feature_AVX512VL_Usable usable ++#define feature_AVX512BW_Usable usable ++#define feature_AVX512DQ_Usable usable ++#define feature_AVX512_4FMAPS_Usable usable ++#define feature_AVX512_4VNNIW_Usable usable ++#define feature_AVX512_BITALG_Usable usable ++#define feature_AVX512_IFMA_Usable usable ++#define feature_AVX512_VBMI_Usable usable ++#define feature_AVX512_VBMI2_Usable usable ++#define feature_AVX512_VNNI_Usable usable ++#define feature_AVX512_VPOPCNTDQ_Usable usable ++#define feature_FMA_Usable usable ++#define feature_FMA4_Usable usable ++#define feature_VAES_Usable usable ++#define feature_VPCLMULQDQ_Usable usable ++#define feature_XOP_Usable usable ++#define feature_XSAVEC_Usable usable ++#define feature_F16C_Usable usable ++#define feature_AVX512_VP2INTERSECT_Usable usable ++#define feature_AVX512_BF16_Usable usable ++#define feature_PKU_Usable usable + + /* CPU features. */ + +@@ -494,17 +332,26 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_CLDEMOTE (1u << 25) + #define bit_cpu_MOVDIRI (1u << 27) + #define bit_cpu_MOVDIR64B (1u << 28) ++#define bit_cpu_ENQCMD (1u << 29) + #define bit_cpu_SGX_LC (1u << 30) ++#define bit_cpu_PKS (1u << 31) + + /* EDX. */ + #define bit_cpu_AVX512_4VNNIW (1u << 2) + #define bit_cpu_AVX512_4FMAPS (1u << 3) + #define bit_cpu_FSRM (1u << 4) ++#define bit_cpu_AVX512_VP2INTERSECT (1u << 8) ++#define bit_cpu_MD_CLEAR (1u << 10) ++#define bit_cpu_SERIALIZE (1u << 14) ++#define bit_cpu_HYBRID (1u << 15) ++#define bit_cpu_TSXLDTRK (1u << 16) + #define bit_cpu_PCONFIG (1u << 18) + #define bit_cpu_IBT (1u << 20) + #define bit_cpu_IBRS_IBPB (1u << 26) + #define bit_cpu_STIBP (1u << 27) +-#define bit_cpu_CAPABILITIES (1u << 29) ++#define bit_cpu_L1D_FLUSH (1u << 28) ++#define bit_cpu_ARCH_CAPABILITIES (1u << 29) ++#define bit_cpu_CORE_CAPABILITIES (1u << 30) + #define bit_cpu_SSBD (1u << 31) + + /* COMMON_CPUID_INDEX_80000001. */ +@@ -545,6 +392,11 @@ extern const struct cpu_features *__get_cpu_features (void) + /* EBX. */ + #define bit_cpu_WBNOINVD (1u << 9) + ++/* COMMON_CPUID_INDEX_7_ECX_1. */ ++ ++/* EAX. */ ++#define bit_cpu_AVX512_BF16 (1u << 5) ++ + /* COMMON_CPUID_INDEX_1. */ + + /* ECX. */ +@@ -662,17 +514,26 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_CLDEMOTE COMMON_CPUID_INDEX_7 + #define index_cpu_MOVDIRI COMMON_CPUID_INDEX_7 + #define index_cpu_MOVDIR64B COMMON_CPUID_INDEX_7 ++#define index_cpu_ENQCMD COMMON_CPUID_INDEX_7 + #define index_cpu_SGX_LC COMMON_CPUID_INDEX_7 ++#define index_cpu_PKS COMMON_CPUID_INDEX_7 + + /* EDX. */ + #define index_cpu_AVX512_4VNNIW COMMON_CPUID_INDEX_7 + #define index_cpu_AVX512_4FMAPS COMMON_CPUID_INDEX_7 + #define index_cpu_FSRM COMMON_CPUID_INDEX_7 ++#define index_cpu_AVX512_VP2INTERSECT COMMON_CPUID_INDEX_7 ++#define index_cpu_MD_CLEAR COMMON_CPUID_INDEX_7 ++#define index_cpu_SERIALIZE COMMON_CPUID_INDEX_7 ++#define index_cpu_HYBRID COMMON_CPUID_INDEX_7 ++#define index_cpu_TSXLDTRK COMMON_CPUID_INDEX_7 + #define index_cpu_PCONFIG COMMON_CPUID_INDEX_7 + #define index_cpu_IBT COMMON_CPUID_INDEX_7 + #define index_cpu_IBRS_IBPB COMMON_CPUID_INDEX_7 + #define index_cpu_STIBP COMMON_CPUID_INDEX_7 +-#define index_cpu_CAPABILITIES COMMON_CPUID_INDEX_7 ++#define index_cpu_L1D_FLUSH COMMON_CPUID_INDEX_7 ++#define index_cpu_ARCH_CAPABILITIES COMMON_CPUID_INDEX_7 ++#define index_cpu_CORE_CAPABILITIES COMMON_CPUID_INDEX_7 + #define index_cpu_SSBD COMMON_CPUID_INDEX_7 + + /* COMMON_CPUID_INDEX_80000001. */ +@@ -713,6 +574,11 @@ extern const struct cpu_features *__get_cpu_features (void) + /* EBX. */ + #define index_cpu_WBNOINVD COMMON_CPUID_INDEX_80000008 + ++/* COMMON_CPUID_INDEX_7_ECX_1. */ ++ ++/* EAX. */ ++#define index_cpu_AVX512_BF16 COMMON_CPUID_INDEX_7_ECX_1 ++ + /* COMMON_CPUID_INDEX_1. */ + + /* ECX. */ +@@ -830,17 +696,26 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_CLDEMOTE ecx + #define reg_MOVDIRI ecx + #define reg_MOVDIR64B ecx ++#define reg_ENQCMD ecx + #define reg_SGX_LC ecx ++#define reg_PKS ecx + + /* EDX. */ + #define reg_AVX512_4VNNIW edx + #define reg_AVX512_4FMAPS edx + #define reg_FSRM edx ++#define reg_AVX512_VP2INTERSECT edx ++#define reg_MD_CLEAR edx ++#define reg_SERIALIZE edx ++#define reg_HYBRID edx ++#define reg_TSXLDTRK edx + #define reg_PCONFIG edx + #define reg_IBT edx + #define reg_IBRS_IBPB edx + #define reg_STIBP edx +-#define reg_CAPABILITIES edx ++#define reg_L1D_FLUSH edx ++#define reg_ARCH_CAPABILITIES edx ++#define reg_CORE_CAPABILITIES edx + #define reg_SSBD edx + + /* COMMON_CPUID_INDEX_80000001. */ +@@ -881,6 +756,11 @@ extern const struct cpu_features *__get_cpu_features (void) + /* EBX. */ + #define reg_WBNOINVD ebx + ++/* COMMON_CPUID_INDEX_7_ECX_1. */ ++ ++/* EAX. */ ++#define reg_AVX512_BF16 eax ++ + /* FEATURE_INDEX_2. */ + #define bit_arch_I586 (1u << 0) + #define bit_arch_I686 (1u << 1) +@@ -899,22 +779,39 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_arch_Prefer_No_AVX512 (1u << 14) + #define bit_arch_MathVec_Prefer_No_AVX512 (1u << 15) + +-#define index_arch_Fast_Rep_String FEATURE_INDEX_2 +-#define index_arch_Fast_Copy_Backward FEATURE_INDEX_2 +-#define index_arch_Slow_BSF FEATURE_INDEX_2 +-#define index_arch_Fast_Unaligned_Load FEATURE_INDEX_2 +-#define index_arch_Prefer_PMINUB_for_stringop FEATURE_INDEX_2 +-#define index_arch_Fast_Unaligned_Copy FEATURE_INDEX_2 +-#define index_arch_I586 FEATURE_INDEX_2 +-#define index_arch_I686 FEATURE_INDEX_2 +-#define index_arch_Slow_SSE4_2 FEATURE_INDEX_2 +-#define index_arch_AVX_Fast_Unaligned_Load FEATURE_INDEX_2 +-#define index_arch_Prefer_MAP_32BIT_EXEC FEATURE_INDEX_2 +-#define index_arch_Prefer_No_VZEROUPPER FEATURE_INDEX_2 +-#define index_arch_Prefer_ERMS FEATURE_INDEX_2 +-#define index_arch_Prefer_No_AVX512 FEATURE_INDEX_2 +-#define index_arch_MathVec_Prefer_No_AVX512 FEATURE_INDEX_2 +-#define index_arch_Prefer_FSRM FEATURE_INDEX_2 ++#define index_arch_Fast_Rep_String PREFERRED_FEATURE_INDEX_1 ++#define index_arch_Fast_Copy_Backward PREFERRED_FEATURE_INDEX_1 ++#define index_arch_Slow_BSF PREFERRED_FEATURE_INDEX_1 ++#define index_arch_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1 ++#define index_arch_Prefer_PMINUB_for_stringop PREFERRED_FEATURE_INDEX_1 ++#define index_arch_Fast_Unaligned_Copy PREFERRED_FEATURE_INDEX_1 ++#define index_arch_I586 PREFERRED_FEATURE_INDEX_1 ++#define index_arch_I686 PREFERRED_FEATURE_INDEX_1 ++#define index_arch_Slow_SSE4_2 PREFERRED_FEATURE_INDEX_1 ++#define index_arch_AVX_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1 ++#define index_arch_Prefer_MAP_32BIT_EXEC PREFERRED_FEATURE_INDEX_1 ++#define index_arch_Prefer_No_VZEROUPPER PREFERRED_FEATURE_INDEX_1 ++#define index_arch_Prefer_ERMS PREFERRED_FEATURE_INDEX_1 ++#define index_arch_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1 ++#define index_arch_MathVec_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1 ++#define index_arch_Prefer_FSRM PREFERRED_FEATURE_INDEX_1 ++ ++#define feature_Fast_Rep_String preferred ++#define feature_Fast_Copy_Backward preferred ++#define feature_Slow_BSF preferred ++#define feature_Fast_Unaligned_Load preferred ++#define feature_Prefer_PMINUB_for_stringop preferred ++#define feature_Fast_Unaligned_Copy preferred ++#define feature_I586 preferred ++#define feature_I686 preferred ++#define feature_Slow_SSE4_2 preferred ++#define feature_AVX_Fast_Unaligned_Load preferred ++#define feature_Prefer_MAP_32BIT_EXEC preferred ++#define feature_Prefer_No_VZEROUPPER preferred ++#define feature_Prefer_ERMS preferred ++#define feature_Prefer_No_AVX512 preferred ++#define feature_MathVec_Prefer_No_AVX512 preferred ++#define feature_Prefer_FSRM preferred + + /* XCR0 Feature flags. */ + #define bit_XMM_state (1u << 1) +diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c +index 2e5d37753713e975..012ae48933055eaa 100644 +--- a/sysdeps/x86/cpu-tunables.c ++++ b/sysdeps/x86/cpu-tunables.c +@@ -54,7 +54,7 @@ extern __typeof (memcmp) DEFAULT_MEMCMP; + _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \ + if (!DEFAULT_MEMCMP (f, #name, len)) \ + { \ +- cpu_features->feature[index_arch_##name] \ ++ cpu_features->feature_##name[index_arch_##name] \ + &= ~bit_arch_##name; \ + break; \ + } +@@ -66,10 +66,10 @@ extern __typeof (memcmp) DEFAULT_MEMCMP; + if (!DEFAULT_MEMCMP (f, #name, len)) \ + { \ + if (disable) \ +- cpu_features->feature[index_arch_##name] \ ++ cpu_features->feature_##name[index_arch_##name] \ + &= ~bit_arch_##name; \ + else \ +- cpu_features->feature[index_arch_##name] \ ++ cpu_features->feature_##name[index_arch_##name] \ + |= bit_arch_##name; \ + break; \ + } +@@ -82,10 +82,10 @@ extern __typeof (memcmp) DEFAULT_MEMCMP; + if (!DEFAULT_MEMCMP (f, #name, len)) \ + { \ + if (disable) \ +- cpu_features->feature[index_arch_##name] \ ++ cpu_features->feature_##name[index_arch_##name] \ + &= ~bit_arch_##name; \ + else if (CPU_FEATURES_ARCH_P (cpu_features, need)) \ +- cpu_features->feature[index_arch_##name] \ ++ cpu_features->feature_##name[index_arch_##name] \ + |= bit_arch_##name; \ + break; \ + } +@@ -98,10 +98,10 @@ extern __typeof (memcmp) DEFAULT_MEMCMP; + if (!DEFAULT_MEMCMP (f, #name, len)) \ + { \ + if (disable) \ +- cpu_features->feature[index_arch_##name] \ ++ cpu_features->feature_##name[index_arch_##name] \ + &= ~bit_arch_##name; \ + else if (CPU_FEATURES_CPU_P (cpu_features, need)) \ +- cpu_features->feature[index_arch_##name] \ ++ cpu_features->feature_##name[index_arch_##name] \ + |= bit_arch_##name; \ + break; \ + } +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index 64a7fd6157242bdd..08688ace2a0ae35e 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -172,15 +172,24 @@ do_test (void) + CHECK_CPU_FEATURE (CLDEMOTE); + CHECK_CPU_FEATURE (MOVDIRI); + CHECK_CPU_FEATURE (MOVDIR64B); ++ CHECK_CPU_FEATURE (ENQCMD); + CHECK_CPU_FEATURE (SGX_LC); ++ CHECK_CPU_FEATURE (PKS); + CHECK_CPU_FEATURE (AVX512_4VNNIW); + CHECK_CPU_FEATURE (AVX512_4FMAPS); + CHECK_CPU_FEATURE (FSRM); ++ CHECK_CPU_FEATURE (AVX512_VP2INTERSECT); ++ CHECK_CPU_FEATURE (MD_CLEAR); ++ CHECK_CPU_FEATURE (SERIALIZE); ++ CHECK_CPU_FEATURE (HYBRID); ++ CHECK_CPU_FEATURE (TSXLDTRK); + CHECK_CPU_FEATURE (PCONFIG); + CHECK_CPU_FEATURE (IBT); + CHECK_CPU_FEATURE (IBRS_IBPB); + CHECK_CPU_FEATURE (STIBP); +- CHECK_CPU_FEATURE (CAPABILITIES); ++ CHECK_CPU_FEATURE (L1D_FLUSH); ++ CHECK_CPU_FEATURE (ARCH_CAPABILITIES); ++ CHECK_CPU_FEATURE (CORE_CAPABILITIES); + CHECK_CPU_FEATURE (SSBD); + CHECK_CPU_FEATURE (LAHF64_SAHF64); + CHECK_CPU_FEATURE (SVM); +@@ -202,84 +211,36 @@ do_test (void) + CHECK_CPU_FEATURE (XSAVES); + CHECK_CPU_FEATURE (INVARIANT_TSC); + CHECK_CPU_FEATURE (WBNOINVD); ++ CHECK_CPU_FEATURE (AVX512_BF16); + + printf ("Usable CPU features:\n"); +- CHECK_CPU_FEATURE_USABLE (SSE3); +- CHECK_CPU_FEATURE_USABLE (PCLMULQDQ); +- CHECK_CPU_FEATURE_USABLE (SSSE3); + CHECK_CPU_FEATURE_USABLE (FMA); +- CHECK_CPU_FEATURE_USABLE (CMPXCHG16B); +- CHECK_CPU_FEATURE_USABLE (SSE4_1); +- CHECK_CPU_FEATURE_USABLE (SSE4_2); +- CHECK_CPU_FEATURE_USABLE (MOVBE); +- CHECK_CPU_FEATURE_USABLE (POPCNT); +- CHECK_CPU_FEATURE_USABLE (AES); +- CHECK_CPU_FEATURE_USABLE (XSAVE); +- CHECK_CPU_FEATURE_USABLE (OSXSAVE); + CHECK_CPU_FEATURE_USABLE (AVX); + CHECK_CPU_FEATURE_USABLE (F16C); +- CHECK_CPU_FEATURE_USABLE (RDRAND); +- CHECK_CPU_FEATURE_USABLE (FPU); +- CHECK_CPU_FEATURE_USABLE (TSC); +- CHECK_CPU_FEATURE_USABLE (MSR); +- CHECK_CPU_FEATURE_USABLE (CX8); +- CHECK_CPU_FEATURE_USABLE (SEP); +- CHECK_CPU_FEATURE_USABLE (CMOV); +- CHECK_CPU_FEATURE_USABLE (CLFSH); +- CHECK_CPU_FEATURE_USABLE (MMX); +- CHECK_CPU_FEATURE_USABLE (FXSR); +- CHECK_CPU_FEATURE_USABLE (SSE); +- CHECK_CPU_FEATURE_USABLE (SSE2); +- CHECK_CPU_FEATURE_USABLE (FSGSBASE); +- CHECK_CPU_FEATURE_USABLE (BMI1); +- CHECK_CPU_FEATURE_USABLE (HLE); + CHECK_CPU_FEATURE_USABLE (AVX2); +- CHECK_CPU_FEATURE_USABLE (BMI2); +- CHECK_CPU_FEATURE_USABLE (ERMS); + CHECK_CPU_FEATURE_USABLE (AVX512F); + CHECK_CPU_FEATURE_USABLE (AVX512DQ); +- CHECK_CPU_FEATURE_USABLE (RDSEED); +- CHECK_CPU_FEATURE_USABLE (ADX); + CHECK_CPU_FEATURE_USABLE (AVX512_IFMA); +- CHECK_CPU_FEATURE_USABLE (CLFLUSHOPT); +- CHECK_CPU_FEATURE_USABLE (CLWB); + CHECK_CPU_FEATURE_USABLE (AVX512PF); + CHECK_CPU_FEATURE_USABLE (AVX512ER); + CHECK_CPU_FEATURE_USABLE (AVX512CD); +- CHECK_CPU_FEATURE_USABLE (SHA); + CHECK_CPU_FEATURE_USABLE (AVX512BW); + CHECK_CPU_FEATURE_USABLE (AVX512VL); +- CHECK_CPU_FEATURE_USABLE (PREFETCHWT1); + CHECK_CPU_FEATURE_USABLE (AVX512_VBMI); ++ CHECK_CPU_FEATURE_USABLE (PKU); + CHECK_CPU_FEATURE_USABLE (AVX512_VBMI2); +- CHECK_CPU_FEATURE_USABLE (GFNI); + CHECK_CPU_FEATURE_USABLE (VAES); + CHECK_CPU_FEATURE_USABLE (VPCLMULQDQ); + CHECK_CPU_FEATURE_USABLE (AVX512_VNNI); + CHECK_CPU_FEATURE_USABLE (AVX512_BITALG); + CHECK_CPU_FEATURE_USABLE (AVX512_VPOPCNTDQ); +- CHECK_CPU_FEATURE_USABLE (RDPID); +- CHECK_CPU_FEATURE_USABLE (CLDEMOTE); +- CHECK_CPU_FEATURE_USABLE (MOVDIRI); +- CHECK_CPU_FEATURE_USABLE (MOVDIR64B); + CHECK_CPU_FEATURE_USABLE (AVX512_4VNNIW); + CHECK_CPU_FEATURE_USABLE (AVX512_4FMAPS); +- CHECK_CPU_FEATURE_USABLE (FSRM); +- CHECK_CPU_FEATURE_USABLE (LAHF64_SAHF64); +- CHECK_CPU_FEATURE_USABLE (LZCNT); +- CHECK_CPU_FEATURE_USABLE (SSE4A); +- CHECK_CPU_FEATURE_USABLE (PREFETCHW); ++ CHECK_CPU_FEATURE_USABLE (AVX512_VP2INTERSECT); + CHECK_CPU_FEATURE_USABLE (XOP); + CHECK_CPU_FEATURE_USABLE (FMA4); +- CHECK_CPU_FEATURE_USABLE (TBM); +- CHECK_CPU_FEATURE_USABLE (SYSCALL_SYSRET); +- CHECK_CPU_FEATURE_USABLE (RDTSCP); +- CHECK_CPU_FEATURE_USABLE (XSAVEOPT); + CHECK_CPU_FEATURE_USABLE (XSAVEC); +- CHECK_CPU_FEATURE_USABLE (XGETBV_ECX_1); +- CHECK_CPU_FEATURE_USABLE (XSAVES); +- CHECK_CPU_FEATURE_USABLE (INVARIANT_TSC); +- CHECK_CPU_FEATURE_USABLE (WBNOINVD); ++ CHECK_CPU_FEATURE_USABLE (AVX512_BF16); + + return 0; + } diff --git a/glibc-rh1817513-67.patch b/glibc-rh1817513-67.patch new file mode 100755 index 0000000..9e331ec --- /dev/null +++ b/glibc-rh1817513-67.patch @@ -0,0 +1,19 @@ +commit 6f3331f26d2ee5d210ba768389828c391750f7a0 +Author: Florian Weimer +Date: Wed Jun 24 11:02:33 2020 +0200 + + elf: Include in because bool is used + +diff --git a/elf/dl-tunables.h b/elf/dl-tunables.h +index 928b30dde9fa0489..7f181f3316cd9fc1 100644 +--- a/elf/dl-tunables.h ++++ b/elf/dl-tunables.h +@@ -21,6 +21,8 @@ + #ifndef _TUNABLES_H_ + #define _TUNABLES_H_ + ++#include ++ + #if !HAVE_TUNABLES + static inline void + __always_inline diff --git a/glibc-rh1817513-68.patch b/glibc-rh1817513-68.patch new file mode 100755 index 0000000..5ba0d6a --- /dev/null +++ b/glibc-rh1817513-68.patch @@ -0,0 +1,22 @@ +commit 2034c70e64b31e48140c8e31c5ae839af5ccb6eb +Author: Florian Weimer +Date: Thu Jun 25 16:51:03 2020 +0200 + + elf: Include (for size_t), in + + Reviewed-by: Carlos O'Donell + +diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h +index 59e20dc3ef790125..6774212110d23eae 100644 +--- a/sysdeps/generic/ldconfig.h ++++ b/sysdeps/generic/ldconfig.h +@@ -19,7 +19,9 @@ + #ifndef _LDCONFIG_H + #define _LDCONFIG_H + ++#include + #include ++#include + + #define FLAG_ANY -1 + #define FLAG_TYPE_MASK 0x00ff diff --git a/glibc-rh1817513-69.patch b/glibc-rh1817513-69.patch new file mode 100755 index 0000000..9d668b3 --- /dev/null +++ b/glibc-rh1817513-69.patch @@ -0,0 +1,144 @@ +commit 4fdd4d41a17dda26c854ed935658154a17d4b906 +Author: H.J. Lu +Date: Thu Jun 25 15:12:57 2020 -0700 + + x86: Detect Intel Advanced Matrix Extensions + + Intel Advanced Matrix Extensions (Intel AMX) is a new programming + paradigm consisting of two components: a set of 2-dimensional registers + (tiles) representing sub-arrays from a larger 2-dimensional memory image, + and accelerators able to operate on tiles. Intel AMX is an extensible + architecture. New accelerators can be added and the existing accelerator + may be enhanced to provide higher performance. The initial features are + AMX-BF16, AMX-TILE and AMX-INT8, which are usable only if the operating + system supports both XTILECFG state and XTILEDATA state. + + Add AMX-BF16, AMX-TILE and AMX-INT8 support to HAS_CPU_FEATURE and + CPU_FEATURE_USABLE. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 7b2a5bc3ed27ec39..21565474839efffc 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -239,6 +239,24 @@ get_common_indices (struct cpu_features *cpu_features, + } + } + ++ /* Are XTILECFG and XTILEDATA states usable? */ ++ if ((xcrlow & (bit_XTILECFG_state | bit_XTILEDATA_state)) ++ == (bit_XTILECFG_state | bit_XTILEDATA_state)) ++ { ++ /* Determine if AMX_BF16 is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AMX_BF16)) ++ cpu_features->usable[index_arch_AMX_BF16_Usable] ++ |= bit_arch_AMX_BF16_Usable; ++ /* Determine if AMX_TILE is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AMX_TILE)) ++ cpu_features->usable[index_arch_AMX_TILE_Usable] ++ |= bit_arch_AMX_TILE_Usable; ++ /* Determine if AMX_INT8 is usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AMX_INT8)) ++ cpu_features->usable[index_arch_AMX_INT8_Usable] ++ |= bit_arch_AMX_INT8_Usable; ++ } ++ + /* For _dl_runtime_resolve, set xsave_state_size to xsave area + size + integer register save size and align it to 64 bytes. */ + if (cpu_features->basic.max_cpuid >= 0xd) +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index 41c3855e94d16b49..7c46242aad69d427 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -156,6 +156,9 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_arch_AVX512_VP2INTERSECT_Usable (1u << 24) + #define bit_arch_AVX512_BF16_Usable (1u << 25) + #define bit_arch_PKU_Usable (1u << 26) ++#define bit_arch_AMX_BF16_Usable (1u << 27) ++#define bit_arch_AMX_TILE_Usable (1u << 28) ++#define bit_arch_AMX_INT8_Usable (1u << 29) + + #define index_arch_AVX_Usable USABLE_FEATURE_INDEX_1 + #define index_arch_AVX2_Usable USABLE_FEATURE_INDEX_1 +@@ -184,6 +187,9 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_arch_AVX512_VP2INTERSECT_Usable USABLE_FEATURE_INDEX_1 + #define index_arch_AVX512_BF16_Usable USABLE_FEATURE_INDEX_1 + #define index_arch_PKU_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AMX_BF16_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AMX_TILE_Usable USABLE_FEATURE_INDEX_1 ++#define index_arch_AMX_INT8_Usable USABLE_FEATURE_INDEX_1 + + #define feature_AVX_Usable usable + #define feature_AVX2_Usable usable +@@ -212,6 +218,9 @@ extern const struct cpu_features *__get_cpu_features (void) + #define feature_AVX512_VP2INTERSECT_Usable usable + #define feature_AVX512_BF16_Usable usable + #define feature_PKU_Usable usable ++#define feature_AMX_BF16_Usable usable ++#define feature_AMX_TILE_Usable usable ++#define feature_AMX_INT8_Usable usable + + /* CPU features. */ + +@@ -347,6 +356,9 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_TSXLDTRK (1u << 16) + #define bit_cpu_PCONFIG (1u << 18) + #define bit_cpu_IBT (1u << 20) ++#define bit_cpu_AMX_BF16 (1u << 22) ++#define bit_cpu_AMX_TILE (1u << 24) ++#define bit_cpu_AMX_INT8 (1u << 25) + #define bit_cpu_IBRS_IBPB (1u << 26) + #define bit_cpu_STIBP (1u << 27) + #define bit_cpu_L1D_FLUSH (1u << 28) +@@ -529,6 +541,9 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_TSXLDTRK COMMON_CPUID_INDEX_7 + #define index_cpu_PCONFIG COMMON_CPUID_INDEX_7 + #define index_cpu_IBT COMMON_CPUID_INDEX_7 ++#define index_cpu_AMX_BF16 COMMON_CPUID_INDEX_7 ++#define index_cpu_AMX_TILE COMMON_CPUID_INDEX_7 ++#define index_cpu_AMX_INT8 COMMON_CPUID_INDEX_7 + #define index_cpu_IBRS_IBPB COMMON_CPUID_INDEX_7 + #define index_cpu_STIBP COMMON_CPUID_INDEX_7 + #define index_cpu_L1D_FLUSH COMMON_CPUID_INDEX_7 +@@ -711,6 +726,9 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_TSXLDTRK edx + #define reg_PCONFIG edx + #define reg_IBT edx ++#define reg_AMX_BF16 edx ++#define reg_AMX_TILE edx ++#define reg_AMX_INT8 edx + #define reg_IBRS_IBPB edx + #define reg_STIBP edx + #define reg_L1D_FLUSH edx +@@ -819,6 +837,8 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_Opmask_state (1u << 5) + #define bit_ZMM0_15_state (1u << 6) + #define bit_ZMM16_31_state (1u << 7) ++#define bit_XTILECFG_state (1u << 17) ++#define bit_XTILEDATA_state (1u << 18) + + # if defined (_LIBC) && !IS_IN (nonlib) + /* Unused for x86. */ +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index 08688ace2a0ae35e..c4d91be3a48de886 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -185,6 +185,9 @@ do_test (void) + CHECK_CPU_FEATURE (TSXLDTRK); + CHECK_CPU_FEATURE (PCONFIG); + CHECK_CPU_FEATURE (IBT); ++ CHECK_CPU_FEATURE (AMX_BF16); ++ CHECK_CPU_FEATURE (AMX_TILE); ++ CHECK_CPU_FEATURE (AMX_INT8); + CHECK_CPU_FEATURE (IBRS_IBPB); + CHECK_CPU_FEATURE (STIBP); + CHECK_CPU_FEATURE (L1D_FLUSH); +@@ -237,6 +240,9 @@ do_test (void) + CHECK_CPU_FEATURE_USABLE (AVX512_4VNNIW); + CHECK_CPU_FEATURE_USABLE (AVX512_4FMAPS); + CHECK_CPU_FEATURE_USABLE (AVX512_VP2INTERSECT); ++ CHECK_CPU_FEATURE_USABLE (AMX_BF16); ++ CHECK_CPU_FEATURE_USABLE (AMX_TILE); ++ CHECK_CPU_FEATURE_USABLE (AMX_INT8); + CHECK_CPU_FEATURE_USABLE (XOP); + CHECK_CPU_FEATURE_USABLE (FMA4); + CHECK_CPU_FEATURE_USABLE (XSAVEC); diff --git a/glibc-rh1817513-7.patch b/glibc-rh1817513-7.patch new file mode 100755 index 0000000..57228a8 --- /dev/null +++ b/glibc-rh1817513-7.patch @@ -0,0 +1,54 @@ +commit 221e4babca17b363df2c56e839572e9f7ab7d127 +Author: Joseph Myers +Date: Wed Sep 12 20:31:24 2018 +0000 + + Include most of elf/ modules-names in modules-names-tests. + + I'm testing a patch to let the compiler expand calls to floor in libm + as built-in function calls as much as possible, instead of calling + __floor, so that no architecture-specific __floor inlines are needed, + and then to arrange for non-inlined calls to end up calling __floor, + as done with sqrt and __ieee754_sqrt. + + This shows up elf/tst-relsort1mod2.c calling floor, which must not be + converted to a call to __floor. Now, while an IS_IN (libm) + conditional could be added to the existing conditionals on such + redirections in include/math.h, the _ISOMAC conditional ought to + suffice (code in other glibc libraries shouldn't be calling floor or + sqrt anyway, as they aren't provided in libc and the other libraries + don't link with libm). But while tests are mostly now built with + _ISOMAC defined, test modules in modules-names aren't unless also + listed in modules-names-tests. + + As far as I can see, all the modules in modules-names in elf/ are in + fact parts of tests and so listing them in modules-names-tests is + appropriate, so they get built with something closer to the headers + used for user code, except in a few cases that actually rely on + something from internal headers. This patch duly sets + modules-names-tests there accordingly (filtering out those tests that + fail to build without internal headers). + + Tested for x86_64, and with build-many-glibcs.py. + + * elf/Makefile (modules-names-tests): New variable. + +Conflicts: + elf/Makefile + (Different backport order for tests.) + +diff --git a/elf/Makefile b/elf/Makefile +index b4b618ce62a9e6df..89dff92adfc417f5 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -306,6 +306,11 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-dlopenfailmod3 \ + tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee + ++# 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%,\ ++ $(modules-names)) ++ + ifeq (yes,$(have-mtls-dialect-gnu2)) + tests += tst-gnu2-tls1 + modules-names += tst-gnu2-tls1mod diff --git a/glibc-rh1817513-70.patch b/glibc-rh1817513-70.patch new file mode 100755 index 0000000..8960178 --- /dev/null +++ b/glibc-rh1817513-70.patch @@ -0,0 +1,21 @@ +commit f8b4630ef673486c2c77bd291a08ef132981e149 +Author: H.J. Lu +Date: Mon Jul 6 06:38:05 2020 -0700 + + x86: Correct bit_cpu_CLFSH [BZ #26208] + + bit_cpu_CLFSH should be (1u << 19), not (1u << 20). + +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index 7c46242aad69d427..535b3cb2d25b245b 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -277,7 +277,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_PAT (1u << 16) + #define bit_cpu_PSE_36 (1u << 17) + #define bit_cpu_PSN (1u << 18) +-#define bit_cpu_CLFSH (1u << 20) ++#define bit_cpu_CLFSH (1u << 19) + #define bit_cpu_DS (1u << 21) + #define bit_cpu_ACPI (1u << 22) + #define bit_cpu_MMX (1u << 23) diff --git a/glibc-rh1817513-71.patch b/glibc-rh1817513-71.patch new file mode 100755 index 0000000..1a5fcdd --- /dev/null +++ b/glibc-rh1817513-71.patch @@ -0,0 +1,51 @@ +commit 28c13ae5bbc81aa2ae67890ce53e65257d4703a4 +Author: H.J. Lu +Date: Mon Jul 6 06:57:08 2020 -0700 + + x86: Detect Extended Feature Disable (XFD) + + An extension called extended feature disable (XFD) is an extension added + for Intel AMX to the XSAVE feature set that allows an operating system + to enable a feature while preventing specific user threads from using + the feature. + +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index 535b3cb2d25b245b..e7ea9e8ece3e8211 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -393,6 +393,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_XSAVEC (1u << 1) + #define bit_cpu_XGETBV_ECX_1 (1u << 2) + #define bit_cpu_XSAVES (1u << 3) ++#define bit_cpu_XFD (1u << 4) + + /* COMMON_CPUID_INDEX_80000007. */ + +@@ -578,6 +579,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_XSAVEC COMMON_CPUID_INDEX_D_ECX_1 + #define index_cpu_XGETBV_ECX_1 COMMON_CPUID_INDEX_D_ECX_1 + #define index_cpu_XSAVES COMMON_CPUID_INDEX_D_ECX_1 ++#define index_cpu_XFD COMMON_CPUID_INDEX_D_ECX_1 + + /* COMMON_CPUID_INDEX_80000007. */ + +@@ -763,6 +765,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_XSAVEC eax + #define reg_XGETBV_ECX_1 eax + #define reg_XSAVES eax ++#define reg_XFD eax + + /* COMMON_CPUID_INDEX_80000007. */ + +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index c4d91be3a48de886..c56f309ba0736c0d 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -212,6 +212,7 @@ do_test (void) + CHECK_CPU_FEATURE (XSAVEC); + CHECK_CPU_FEATURE (XGETBV_ECX_1); + CHECK_CPU_FEATURE (XSAVES); ++ CHECK_CPU_FEATURE (XFD); + CHECK_CPU_FEATURE (INVARIANT_TSC); + CHECK_CPU_FEATURE (WBNOINVD); + CHECK_CPU_FEATURE (AVX512_BF16); diff --git a/glibc-rh1817513-72.patch b/glibc-rh1817513-72.patch new file mode 100755 index 0000000..fde1130 --- /dev/null +++ b/glibc-rh1817513-72.patch @@ -0,0 +1,235 @@ +commit 3f4b61a0b8de67ef9f20737919c713ddfc4bd620 +Author: H.J. Lu +Date: Mon Jul 6 11:48:09 2020 -0700 + + x86: Add thresholds for "rep movsb/stosb" to tunables + + Add x86_rep_movsb_threshold and x86_rep_stosb_threshold to tunables + to update thresholds for "rep movsb" and "rep stosb" at run-time. + + Note that the user specified threshold for "rep movsb" smaller than + the minimum threshold will be ignored. + + Reviewed-by: Carlos O'Donell + +Conflicts: + sysdeps/x86/cacheinfo.c + (Previous backport of the shared cache computation fix.) + +diff --git a/manual/tunables.texi b/manual/tunables.texi +index ef10d2872cfc244e..55d5dfb14db4dfb8 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -373,6 +373,22 @@ like memmove and memcpy. + This tunable is specific to i386 and x86-64. + @end deftp + ++@deftp Tunable glibc.cpu.x86_rep_movsb_threshold ++The @code{glibc.cpu.x86_rep_movsb_threshold} tunable allows the user to ++set threshold in bytes to start using "rep movsb". The value must be ++greater than zero, and currently defaults to 2048 bytes. ++ ++This tunable is specific to i386 and x86-64. ++@end deftp ++ ++@deftp Tunable glibc.cpu.x86_rep_stosb_threshold ++The @code{glibc.cpu.x86_rep_stosb_threshold} tunable allows the user to ++set threshold in bytes to start using "rep stosb". The value must be ++greater than zero, and currently defaults to 2048 bytes. ++ ++This tunable is specific to i386 and x86-64. ++@end deftp ++ + @deftp Tunable glibc.cpu.x86_ibt + The @code{glibc.cpu.x86_ibt} tunable allows the user to control how + indirect branch tracking (IBT) should be enabled. Accepted values are +diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c +index aa7cb705d546bcd0..c741a69fb19a1e95 100644 +--- a/sysdeps/x86/cacheinfo.c ++++ b/sysdeps/x86/cacheinfo.c +@@ -530,6 +530,12 @@ long int __x86_raw_shared_cache_size attribute_hidden = 1024 * 1024; + /* Threshold to use non temporal store. */ + long int __x86_shared_non_temporal_threshold attribute_hidden; + ++/* Threshold to use Enhanced REP MOVSB. */ ++long int __x86_rep_movsb_threshold attribute_hidden = 2048; ++ ++/* Threshold to use Enhanced REP STOSB. */ ++long int __x86_rep_stosb_threshold attribute_hidden = 2048; ++ + #ifndef DISABLE_PREFETCHW + /* PREFETCHW support flag for use in memory and string routines. */ + int __x86_prefetchw attribute_hidden; +@@ -892,6 +898,36 @@ init_cacheinfo (void) + = (cpu_features->non_temporal_threshold != 0 + ? cpu_features->non_temporal_threshold + : __x86_shared_cache_size * 3 / 4); ++ ++ /* NB: The REP MOVSB threshold must be greater than VEC_SIZE * 8. */ ++ unsigned int minimum_rep_movsb_threshold; ++ /* NB: The default REP MOVSB threshold is 2048 * (VEC_SIZE / 16). */ ++ unsigned int rep_movsb_threshold; ++ if (CPU_FEATURES_ARCH_P (cpu_features, AVX512F_Usable) ++ && !CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_AVX512)) ++ { ++ rep_movsb_threshold = 2048 * (64 / 16); ++ minimum_rep_movsb_threshold = 64 * 8; ++ } ++ else if (CPU_FEATURES_ARCH_P (cpu_features, ++ AVX_Fast_Unaligned_Load)) ++ { ++ rep_movsb_threshold = 2048 * (32 / 16); ++ minimum_rep_movsb_threshold = 32 * 8; ++ } ++ else ++ { ++ rep_movsb_threshold = 2048 * (16 / 16); ++ minimum_rep_movsb_threshold = 16 * 8; ++ } ++ if (cpu_features->rep_movsb_threshold > minimum_rep_movsb_threshold) ++ __x86_rep_movsb_threshold = cpu_features->rep_movsb_threshold; ++ else ++ __x86_rep_movsb_threshold = rep_movsb_threshold; ++ ++# if HAVE_TUNABLES ++ __x86_rep_stosb_threshold = cpu_features->rep_stosb_threshold; ++# endif + } + + #endif +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 21565474839efffc..ad470f79ef7769fc 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -605,6 +605,10 @@ no_cpuid: + TUNABLE_GET (hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps)); + cpu_features->non_temporal_threshold + = TUNABLE_GET (x86_non_temporal_threshold, long int, NULL); ++ cpu_features->rep_movsb_threshold ++ = TUNABLE_GET (x86_rep_movsb_threshold, long int, NULL); ++ cpu_features->rep_stosb_threshold ++ = TUNABLE_GET (x86_rep_stosb_threshold, long int, NULL); + cpu_features->data_cache_size + = TUNABLE_GET (x86_data_cache_size, long int, NULL); + cpu_features->shared_cache_size +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index e7ea9e8ece3e8211..0f19c64352c4d7f1 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -102,6 +102,10 @@ struct cpu_features + unsigned long int shared_cache_size; + /* Threshold to use non temporal store. */ + unsigned long int non_temporal_threshold; ++ /* Threshold to use "rep movsb". */ ++ unsigned long int rep_movsb_threshold; ++ /* Threshold to use "rep stosb". */ ++ unsigned long int rep_stosb_threshold; + }; + + /* Used from outside of glibc to get access to the CPU features +diff --git a/sysdeps/x86/dl-tunables.list b/sysdeps/x86/dl-tunables.list +index 2a457d0eec9c3122..e066313a1d1dd009 100644 +--- a/sysdeps/x86/dl-tunables.list ++++ b/sysdeps/x86/dl-tunables.list +@@ -30,6 +30,30 @@ glibc { + x86_non_temporal_threshold { + type: SIZE_T + } ++ x86_rep_movsb_threshold { ++ type: SIZE_T ++ # Since there is overhead to set up REP MOVSB operation, REP MOVSB ++ # isn't faster on short data. The memcpy micro benchmark in glibc ++ # shows that 2KB is the approximate value above which REP MOVSB ++ # becomes faster than SSE2 optimization on processors with Enhanced ++ # REP MOVSB. Since larger register size can move more data with a ++ # single load and store, the threshold is higher with larger register ++ # size. Note: Since the REP MOVSB threshold must be greater than 8 ++ # times of vector size, the minium value must be updated at run-time. ++ minval: 1 ++ default: 2048 ++ } ++ x86_rep_stosb_threshold { ++ type: SIZE_T ++ # Since there is overhead to set up REP STOSB operation, REP STOSB ++ # isn't faster on short data. The memset micro benchmark in glibc ++ # shows that 2KB is the approximate value above which REP STOSB ++ # becomes faster on processors with Enhanced REP STOSB. Since the ++ # stored value is fixed, larger register size has minimal impact ++ # on threshold. ++ minval: 1 ++ default: 2048 ++ } + x86_data_cache_size { + type: SIZE_T + } +diff --git a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S +index e2ede45e9f68791b..c952576cfdf6e3e6 100644 +--- a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S ++++ b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S +@@ -56,17 +56,6 @@ + # endif + #endif + +-/* Threshold to use Enhanced REP MOVSB. Since there is overhead to set +- up REP MOVSB operation, REP MOVSB isn't faster on short data. The +- memcpy micro benchmark in glibc shows that 2KB is the approximate +- value above which REP MOVSB becomes faster than SSE2 optimization +- on processors with Enhanced REP MOVSB. Since larger register size +- can move more data with a single load and store, the threshold is +- higher with larger register size. */ +-#ifndef REP_MOVSB_THRESHOLD +-# define REP_MOVSB_THRESHOLD (2048 * (VEC_SIZE / 16)) +-#endif +- + #ifndef PREFETCH + # define PREFETCH(addr) prefetcht0 addr + #endif +@@ -245,9 +234,6 @@ L(movsb): + leaq (%rsi,%rdx), %r9 + cmpq %r9, %rdi + /* Avoid slow backward REP MOVSB. */ +-# if REP_MOVSB_THRESHOLD <= (VEC_SIZE * 8) +-# error Unsupported REP_MOVSB_THRESHOLD and VEC_SIZE! +-# endif + jb L(more_8x_vec_backward) + 1: + movq %rdx, %rcx +@@ -323,7 +309,7 @@ L(between_2_3): + + #if defined USE_MULTIARCH && IS_IN (libc) + L(movsb_more_2x_vec): +- cmpq $REP_MOVSB_THRESHOLD, %rdx ++ cmp __x86_rep_movsb_threshold(%rip), %RDX_LP + ja L(movsb) + #endif + L(more_2x_vec): +diff --git a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S +index dc9cb88b37a5477a..270a1d49b34be9f5 100644 +--- a/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S ++++ b/sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S +@@ -58,16 +58,6 @@ + # endif + #endif + +-/* Threshold to use Enhanced REP STOSB. Since there is overhead to set +- up REP STOSB operation, REP STOSB isn't faster on short data. The +- memset micro benchmark in glibc shows that 2KB is the approximate +- value above which REP STOSB becomes faster on processors with +- Enhanced REP STOSB. Since the stored value is fixed, larger register +- size has minimal impact on threshold. */ +-#ifndef REP_STOSB_THRESHOLD +-# define REP_STOSB_THRESHOLD 2048 +-#endif +- + #ifndef SECTION + # error SECTION is not defined! + #endif +@@ -173,7 +163,7 @@ ENTRY (MEMSET_SYMBOL (__memset, unaligned_erms)) + ret + + L(stosb_more_2x_vec): +- cmpq $REP_STOSB_THRESHOLD, %rdx ++ cmp __x86_rep_stosb_threshold(%rip), %RDX_LP + ja L(stosb) + #endif + L(more_2x_vec): diff --git a/glibc-rh1817513-73.patch b/glibc-rh1817513-73.patch new file mode 100755 index 0000000..adb3c93 --- /dev/null +++ b/glibc-rh1817513-73.patch @@ -0,0 +1,289 @@ +commit 0c7b002fac12dcb2f53ba83ee56bb3b5d2439447 +Author: Szabolcs Nagy +Date: Tue Jun 9 09:57:28 2020 +0100 + + rtld: Add rtld.nns tunable for the number of supported namespaces + + TLS_STATIC_SURPLUS is 1664 bytes currently which is not enough to + support DL_NNS (== 16) number of dynamic link namespaces, if we + assume 192 bytes of TLS are reserved for libc use and 144 bytes + are reserved for other system libraries that use IE TLS. + + A new tunable is introduced to control the number of supported + namespaces and to adjust the surplus static TLS size as follows: + + surplus_tls = 192 * (rtld.nns-1) + 144 * rtld.nns + 512 + + The default is rtld.nns == 4 and then the surplus TLS size is the + same as before, so the behaviour is unchanged by default. If an + application creates more namespaces than the rtld.nns setting + allows, then it is not guaranteed to work, but the limit is not + checked. So existing usage will continue to work, but in the + future if an application creates more than 4 dynamic link + namespaces then the tunable will need to be set. + + In this patch DL_NNS is a fixed value and provides a maximum to + the rtld.nns setting. + + Static linking used fixed 2048 bytes surplus TLS, this is changed + so the same contract is used as for dynamic linking. With static + linking DL_NNS == 1 so rtld.nns tunable is forced to 1, so by + default the surplus TLS is reduced to 144 + 512 = 656 bytes. This + change is not expected to cause problems. + + Tested on aarch64-linux-gnu and x86_64-linux-gnu. + + Reviewed-by: Carlos O'Donell + +Conflicts: + elf/dl-tls.c + (Different per-namespace TLS reservation defaults before + this backport.) + +diff --git a/csu/libc-tls.c b/csu/libc-tls.c +index 28a79441cde379f7..08ed2b988b58ac6c 100644 +--- a/csu/libc-tls.c ++++ b/csu/libc-tls.c +@@ -52,13 +52,16 @@ bool _dl_tls_dtv_gaps; + struct dtv_slotinfo_list *_dl_tls_dtv_slotinfo_list; + /* Number of modules in the static TLS block. */ + size_t _dl_tls_static_nelem; +-/* Size of the static TLS block. Giving this initialized value +- preallocates some surplus bytes in the static TLS area. */ +-size_t _dl_tls_static_size = 2048; ++/* Size of the static TLS block. */ ++size_t _dl_tls_static_size; + /* Size actually allocated in the static TLS block. */ + size_t _dl_tls_static_used; + /* Alignment requirement of the static TLS block. */ + size_t _dl_tls_static_align; ++/* Size of surplus space in the static TLS area for dynamically ++ loaded modules with IE-model TLS or for TLSDESC optimization. ++ See comments in elf/dl-tls.c where it is initialized. */ ++size_t _dl_tls_static_surplus; + + /* Generation counter for the dtv. */ + size_t _dl_tls_generation; +@@ -87,10 +90,8 @@ init_slotinfo (void) + static void + init_static_tls (size_t memsz, size_t align) + { +- /* That is the size of the TLS memory for this object. The initialized +- value of _dl_tls_static_size is provided by dl-open.c to request some +- surplus that permits dynamic loading of modules with IE-model TLS. */ +- GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size), ++ /* That is the size of the TLS memory for this object. */ ++ GL(dl_tls_static_size) = roundup (memsz + GLRO(dl_tls_static_surplus), + TLS_TCB_ALIGN); + #if TLS_TCB_AT_TP + GL(dl_tls_static_size) += TLS_TCB_SIZE; +@@ -131,25 +132,24 @@ __libc_setup_tls (void) + break; + } + ++ /* Calculate the size of the static TLS surplus. */ ++ _dl_tls_static_surplus_init (); ++ + /* We have to set up the TCB block which also (possibly) contains + 'errno'. Therefore we avoid 'malloc' which might touch 'errno'. + Instead we use 'sbrk' which would only uses 'errno' if it fails. + In this case we are right away out of memory and the user gets +- what she/he deserves. +- +- The initialized value of _dl_tls_static_size is provided by dl-open.c +- to request some surplus that permits dynamic loading of modules with +- IE-model TLS. */ ++ what she/he deserves. */ + #if TLS_TCB_AT_TP + /* Align the TCB offset to the maximum alignment, as + _dl_allocate_tls_storage (in elf/dl-tls.c) does using __libc_memalign + and dl_tls_static_align. */ +- tcb_offset = roundup (memsz + GL(dl_tls_static_size), max_align); ++ tcb_offset = roundup (memsz + GLRO(dl_tls_static_surplus), max_align); + tlsblock = __sbrk (tcb_offset + TLS_INIT_TCB_SIZE + max_align); + #elif TLS_DTV_AT_TP + tcb_offset = roundup (TLS_INIT_TCB_SIZE, align ?: 1); + tlsblock = __sbrk (tcb_offset + memsz + max_align +- + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size)); ++ + TLS_PRE_TCB_SIZE + GLRO(dl_tls_static_surplus)); + tlsblock += TLS_PRE_TCB_SIZE; + #else + /* In case a model with a different layout for the TCB and DTV +diff --git a/elf/dl-tls.c b/elf/dl-tls.c +index a2def280b7096960..ef57a21391bb36fa 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -29,10 +29,54 @@ + #include + #include + +-/* Amount of excess space to allocate in the static TLS area +- to allow dynamic loading of modules defining IE-model TLS data. */ +-#define TLS_STATIC_SURPLUS 64 + DL_NNS * 100 ++#define TUNABLE_NAMESPACE rtld ++#include ++ ++/* Surplus static TLS, GLRO(dl_tls_static_surplus), is used for ++ ++ - IE TLS in libc.so for all dlmopen namespaces except in the initial ++ one where libc.so is not loaded dynamically but at startup time, ++ - IE TLS in other libraries which may be dynamically loaded even in the ++ initial namespace, ++ - and optionally for optimizing dynamic TLS access. ++ ++ The maximum number of namespaces is DL_NNS, but to support that many ++ namespaces correctly the static TLS allocation should be significantly ++ increased, which may cause problems with small thread stacks due to the ++ way static TLS is accounted (bug 11787). ++ ++ So there is a rtld.nns tunable limit on the number of supported namespaces ++ that affects the size of the static TLS and by default it's small enough ++ not to cause problems with existing applications. The limit is not ++ enforced or checked: it is the user's responsibility to increase rtld.nns ++ if more dlmopen namespaces are used. */ ++ ++/* Size of initial-exec TLS in libc.so. */ ++#define LIBC_IE_TLS 192 ++/* Size of initial-exec TLS in libraries other than libc.so. ++ This should be large enough to cover runtime libraries of the ++ compiler such as libgomp and libraries in libc other than libc.so. */ ++#define OTHER_IE_TLS 144 ++/* Size of additional surplus TLS, placeholder for TLS optimizations. */ ++#define OPT_SURPLUS_TLS 512 + ++void ++_dl_tls_static_surplus_init (void) ++{ ++ size_t nns; ++ ++#if HAVE_TUNABLES ++ nns = TUNABLE_GET (nns, size_t, NULL); ++#else ++ /* Default values of the tunables. */ ++ nns = 4; ++#endif ++ if (nns > DL_NNS) ++ nns = DL_NNS; ++ GLRO(dl_tls_static_surplus) = ((nns - 1) * LIBC_IE_TLS ++ + nns * OTHER_IE_TLS ++ + OPT_SURPLUS_TLS); ++} + + /* Out-of-memory handler. */ + static void +@@ -218,7 +262,8 @@ _dl_determine_tlsoffset (void) + } + + GL(dl_tls_static_used) = offset; +- GL(dl_tls_static_size) = (roundup (offset + TLS_STATIC_SURPLUS, max_align) ++ GL(dl_tls_static_size) = (roundup (offset + GLRO(dl_tls_static_surplus), ++ max_align) + + TLS_TCB_SIZE); + #elif TLS_DTV_AT_TP + /* The TLS blocks start right after the TCB. */ +@@ -262,7 +307,7 @@ _dl_determine_tlsoffset (void) + } + + GL(dl_tls_static_used) = offset; +- GL(dl_tls_static_size) = roundup (offset + TLS_STATIC_SURPLUS, ++ GL(dl_tls_static_size) = roundup (offset + GLRO(dl_tls_static_surplus), + TLS_TCB_ALIGN); + #else + # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list +index b7cc79f8bfe0a7c6..7337fb85062c91a7 100644 +--- a/elf/dl-tunables.list ++++ b/elf/dl-tunables.list +@@ -126,4 +126,13 @@ glibc { + default: 3 + } + } ++ ++ rtld { ++ nns { ++ type: SIZE_T ++ minval: 1 ++ maxval: 16 ++ default: 4 ++ } ++ } + } +diff --git a/elf/rtld.c b/elf/rtld.c +index 772aff5160359b7b..a440741f4c1b3c91 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -776,6 +776,9 @@ init_tls (void) + } + assert (i == GL(dl_tls_max_dtv_idx)); + ++ /* Calculate the size of the static TLS surplus. */ ++ _dl_tls_static_surplus_init (); ++ + /* Compute the TLS offsets for the various blocks. */ + _dl_determine_tlsoffset (); + +diff --git a/manual/tunables.texi b/manual/tunables.texi +index 55d5dfb14db4dfb8..e092b8e81a18d739 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -31,6 +31,7 @@ their own namespace. + @menu + * Tunable names:: The structure of a tunable name + * Memory Allocation Tunables:: Tunables in the memory allocation subsystem ++* Dynamic Linking Tunables:: Tunables in the dynamic linking subsystem + * Elision Tunables:: Tunables in elision subsystem + * Hardware Capability Tunables:: Tunables that modify the hardware + capabilities seen by @theglibc{} +@@ -225,6 +226,26 @@ pointer, so add 4 on 32-bit systems or 8 on 64-bit systems to the size + passed to @code{malloc} for the largest bin size to enable. + @end deftp + ++@node Dynamic Linking Tunables ++@section Dynamic Linking Tunables ++@cindex dynamic linking tunables ++@cindex rtld tunables ++ ++@deftp {Tunable namespace} glibc.rtld ++Dynamic linker behavior can be modified by setting the ++following tunables in the @code{rtld} namespace: ++@end deftp ++ ++@deftp Tunable glibc.rtld.nns ++Sets the number of supported dynamic link namespaces (see @code{dlmopen}). ++Currently this limit can be set between 1 and 16 inclusive, the default is 4. ++Each link namespace consumes some memory in all thread, and thus raising the ++limit will increase the amount of memory each thread uses. Raising the limit ++is useful when your application uses more than 4 dynamic linker audit modules ++e.g. @env{LD_AUDIT}, or will use more than 4 dynamic link namespaces as created ++by @code{dlmopen} with an lmid argument of @code{LM_ID_NEWLM}. ++@end deftp ++ + @node Elision Tunables + @section Elision Tunables + @cindex elision tunables +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index ccec08929e4ad4e7..e54105848c3cb7d1 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -582,6 +582,11 @@ struct rtld_global_ro + binaries, don't honor for PIEs). */ + EXTERN ElfW(Addr) _dl_use_load_bias; + ++ /* Size of surplus space in the static TLS area for dynamically ++ loaded modules with IE-model TLS or for TLSDESC optimization. ++ See comments in elf/dl-tls.c where it is initialized. */ ++ EXTERN size_t _dl_tls_static_surplus; ++ + /* Name of the shared object to be profiled (if any). */ + EXTERN const char *_dl_profile; + /* Filename of the output file. */ +@@ -1099,6 +1104,9 @@ extern size_t _dl_count_modids (void) attribute_hidden; + /* Calculate offset of the TLS blocks in the static TLS block. */ + extern void _dl_determine_tlsoffset (void) attribute_hidden; + ++/* Calculate the size of the static TLS surplus. */ ++void _dl_tls_static_surplus_init (void) attribute_hidden; ++ + #ifndef SHARED + /* Set up the TCB for statically linked applications. This is called + early during startup because we always use TLS (for errno and the diff --git a/glibc-rh1817513-74.patch b/glibc-rh1817513-74.patch new file mode 100755 index 0000000..8281192 --- /dev/null +++ b/glibc-rh1817513-74.patch @@ -0,0 +1,205 @@ +commit 17796419b5fd694348cceb65c3f77601faae082c +Author: Szabolcs Nagy +Date: Tue Jul 7 10:49:11 2020 +0100 + + rtld: Account static TLS surplus for audit modules + + The new static TLS surplus size computation is + + surplus_tls = 192 * (nns-1) + 144 * nns + 512 + + where nns is controlled via the rtld.nns tunable. This commit + accounts audit modules too so nns = rtld.nns + audit modules. + + rtld.nns should only include the namespaces required by the + application, namespaces for audit modules are accounted on top + of that so audit modules don't use up the static TLS that is + reserved for the application. This allows loading many audit + modules without tuning rtld.nns or using up static TLS, and it + fixes + + FAIL: elf/tst-auditmany + + Note that DL_NNS is currently a hard upper limit for nns, and + if rtld.nns + audit modules go over the limit that's a fatal + error. By default rtld.nns is 4 which allows 12 audit modules. + + Counting the audit modules is based on existing audit string + parsing code, we cannot use GLRO(dl_naudit) before the modules + are actually loaded. + +Conflicts: + elf/rtld.c + (Caused by glibc-fedora-__libc_multiple_libcs.patch.) + +diff --git a/csu/libc-tls.c b/csu/libc-tls.c +index 08ed2b988b58ac6c..6f2a47dc86222407 100644 +--- a/csu/libc-tls.c ++++ b/csu/libc-tls.c +@@ -132,8 +132,8 @@ __libc_setup_tls (void) + break; + } + +- /* Calculate the size of the static TLS surplus. */ +- _dl_tls_static_surplus_init (); ++ /* Calculate the size of the static TLS surplus, with 0 auditors. */ ++ _dl_tls_static_surplus_init (0); + + /* We have to set up the TCB block which also (possibly) contains + 'errno'. Therefore we avoid 'malloc' which might touch 'errno'. +diff --git a/elf/dl-tls.c b/elf/dl-tls.c +index ef57a21391bb36fa..cfda76f6de96df57 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -49,7 +49,10 @@ + that affects the size of the static TLS and by default it's small enough + not to cause problems with existing applications. The limit is not + enforced or checked: it is the user's responsibility to increase rtld.nns +- if more dlmopen namespaces are used. */ ++ if more dlmopen namespaces are used. ++ ++ Audit modules use their own namespaces, they are not included in rtld.nns, ++ but come on top when computing the number of namespaces. */ + + /* Size of initial-exec TLS in libc.so. */ + #define LIBC_IE_TLS 192 +@@ -60,8 +63,11 @@ + /* Size of additional surplus TLS, placeholder for TLS optimizations. */ + #define OPT_SURPLUS_TLS 512 + ++/* Calculate the size of the static TLS surplus, when the given ++ number of audit modules are loaded. Must be called after the ++ number of audit modules is known and before static TLS allocation. */ + void +-_dl_tls_static_surplus_init (void) ++_dl_tls_static_surplus_init (size_t naudit) + { + size_t nns; + +@@ -73,6 +79,11 @@ _dl_tls_static_surplus_init (void) + #endif + if (nns > DL_NNS) + nns = DL_NNS; ++ if (DL_NNS - nns < naudit) ++ _dl_fatal_printf ("Failed loading %lu audit modules, %lu are supported.\n", ++ (unsigned long) naudit, (unsigned long) (DL_NNS - nns)); ++ nns += naudit; ++ + GLRO(dl_tls_static_surplus) = ((nns - 1) * LIBC_IE_TLS + + nns * OTHER_IE_TLS + + OPT_SURPLUS_TLS); +diff --git a/elf/rtld.c b/elf/rtld.c +index a440741f4c1b3c91..67441ac6f252350e 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -297,6 +297,23 @@ audit_list_next (struct audit_list *list) + } + } + ++/* Count audit modules before they are loaded so GLRO(dl_naudit) ++ is not yet usable. */ ++static size_t ++audit_list_count (struct audit_list *list) ++{ ++ /* Restore the audit_list iterator state at the end. */ ++ const char *saved_tail = list->current_tail; ++ size_t naudit = 0; ++ ++ assert (list->current_index == 0); ++ while (audit_list_next (list) != NULL) ++ naudit++; ++ list->current_tail = saved_tail; ++ list->current_index = 0; ++ return naudit; ++} ++ + /* Set nonzero during loading and initialization of executable and + libraries, cleared before the executable's entry point runs. This + must not be initialized to nonzero, because the unused dynamic +@@ -734,7 +751,7 @@ match_version (const char *string, struct link_map *map) + static bool tls_init_tp_called; + + static void * +-init_tls (void) ++init_tls (size_t naudit) + { + /* Number of elements in the static TLS block. */ + GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx); +@@ -777,7 +794,7 @@ init_tls (void) + assert (i == GL(dl_tls_max_dtv_idx)); + + /* Calculate the size of the static TLS surplus. */ +- _dl_tls_static_surplus_init (); ++ _dl_tls_static_surplus_init (naudit); + + /* Compute the TLS offsets for the various blocks. */ + _dl_determine_tlsoffset (); +@@ -1659,9 +1676,11 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + bool need_security_init = true; + if (audit_list.length > 0) + { ++ size_t naudit = audit_list_count (&audit_list); ++ + /* Since we start using the auditing DSOs right away we need to + initialize the data structures now. */ +- tcbp = init_tls (); ++ tcbp = init_tls (naudit); + + /* Initialize security features. We need to do it this early + since otherwise the constructors of the audit libraries will +@@ -1671,6 +1690,10 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + need_security_init = false; + + load_audit_modules (main_map, &audit_list); ++ ++ /* The count based on audit strings may overestimate the number ++ of audit modules that got loaded, but not underestimate. */ ++ assert (GLRO(dl_naudit) <= naudit); + } + + /* Keep track of the currently loaded modules to count how many +@@ -1914,7 +1937,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + multiple threads (from a non-TLS-using libpthread). */ + bool was_tls_init_tp_called = tls_init_tp_called; + if (tcbp == NULL) +- tcbp = init_tls (); ++ tcbp = init_tls (0); + + if (__glibc_likely (need_security_init)) + /* Initialize security features. But only if we have not done it +diff --git a/manual/tunables.texi b/manual/tunables.texi +index e092b8e81a18d739..e6a3e9a2cf5c959c 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -241,9 +241,12 @@ Sets the number of supported dynamic link namespaces (see @code{dlmopen}). + Currently this limit can be set between 1 and 16 inclusive, the default is 4. + Each link namespace consumes some memory in all thread, and thus raising the + limit will increase the amount of memory each thread uses. Raising the limit +-is useful when your application uses more than 4 dynamic linker audit modules +-e.g. @env{LD_AUDIT}, or will use more than 4 dynamic link namespaces as created +-by @code{dlmopen} with an lmid argument of @code{LM_ID_NEWLM}. ++is useful when your application uses more than 4 dynamic link namespaces as ++created by @code{dlmopen} with an lmid argument of @code{LM_ID_NEWLM}. ++Dynamic linker audit modules are loaded in their own dynamic link namespaces, ++but they are not accounted for in @code{glibc.rtld.nns}. They implicitly ++increase the per-thread memory usage as necessary, so this tunable does ++not need to be changed to allow many audit modules e.g. via @env{LD_AUDIT}. + @end deftp + + @node Elision Tunables +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index e54105848c3cb7d1..293f3ab5a496afdf 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1104,8 +1104,9 @@ extern size_t _dl_count_modids (void) attribute_hidden; + /* Calculate offset of the TLS blocks in the static TLS block. */ + extern void _dl_determine_tlsoffset (void) attribute_hidden; + +-/* Calculate the size of the static TLS surplus. */ +-void _dl_tls_static_surplus_init (void) attribute_hidden; ++/* Calculate the size of the static TLS surplus, when the given ++ number of audit modules are loaded. */ ++void _dl_tls_static_surplus_init (size_t naudit) attribute_hidden; + + #ifndef SHARED + /* Set up the TCB for statically linked applications. This is called diff --git a/glibc-rh1817513-75.patch b/glibc-rh1817513-75.patch new file mode 100755 index 0000000..1c9577d --- /dev/null +++ b/glibc-rh1817513-75.patch @@ -0,0 +1,115 @@ +commit 9016b6f3893789ddfbd978aa572b46b3d3ce762f +Author: H.J. Lu +Date: Sat Jul 11 09:04:34 2020 -0700 + + x86: Remove the unused __x86_prefetchw + + Since + + commit c867597bff2562180a18da4b8dba89d24e8b65c4 + Author: H.J. Lu + Date: Wed Jun 8 13:57:50 2016 -0700 + + X86-64: Remove previous default/SSE2/AVX2 memcpy/memmove + + removed the only usage of __x86_prefetchw, we can remove the unused + __x86_prefetchw. + +Conflicts: + sysdeps/x86/cacheinfo.c + (Different backport order downstream, related to cache + comptuation. Also had to remove the now-unused eax variable.) + +diff --git a/sysdeps/i386/Makefile b/sysdeps/i386/Makefile +index c0a4fe15d47bff1c..41b345c6c6274c01 100644 +--- a/sysdeps/i386/Makefile ++++ b/sysdeps/i386/Makefile +@@ -13,10 +13,6 @@ ifeq ($(subdir),math) + CFLAGS-e_gamma_r.c += -DMATH_SET_BOTH_ROUNDING_MODES + endif + +-ifeq ($(subdir),string) +-sysdep_routines += cacheinfo +-endif +- + ifeq ($(subdir),gmon) + sysdep_routines += i386-mcount + endif +diff --git a/sysdeps/i386/cacheinfo.c b/sysdeps/i386/cacheinfo.c +deleted file mode 100644 +index f15fe0779afebb8f..0000000000000000 +--- a/sysdeps/i386/cacheinfo.c ++++ /dev/null +@@ -1,3 +0,0 @@ +-#define DISABLE_PREFETCHW +- +-#include +diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile +index a936134a577e42a5..962bbcb07eba1259 100644 +--- a/sysdeps/x86/Makefile ++++ b/sysdeps/x86/Makefile +@@ -14,6 +14,10 @@ gen-as-const-headers += jmp_buf-ssp.sym + sysdep_routines += __longjmp_cancel + endif + ++ifeq ($(subdir),string) ++sysdep_routines += cacheinfo ++endif ++ + ifneq ($(enable-cet),no) + ifeq ($(subdir),elf) + sysdep-dl-routines += dl-cet +diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c +index c741a69fb19a1e95..f4edbc0103beb435 100644 +--- a/sysdeps/x86/cacheinfo.c ++++ b/sysdeps/x86/cacheinfo.c +@@ -536,11 +536,6 @@ long int __x86_rep_movsb_threshold attribute_hidden = 2048; + /* Threshold to use Enhanced REP STOSB. */ + long int __x86_rep_stosb_threshold attribute_hidden = 2048; + +-#ifndef DISABLE_PREFETCHW +-/* PREFETCHW support flag for use in memory and string routines. */ +-int __x86_prefetchw attribute_hidden; +-#endif +- + + static void + get_common_cache_info (long int *shared_ptr, unsigned int *threads_ptr, +@@ -765,7 +760,6 @@ __attribute__((constructor)) + init_cacheinfo (void) + { + /* Find out what brand of processor. */ +- unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; +@@ -846,16 +840,6 @@ init_cacheinfo (void) + shared += core; + } + } +- +-#ifndef DISABLE_PREFETCHW +- if (max_cpuid_ex >= 0x80000001) +- { +- __cpuid (0x80000001, eax, ebx, ecx, edx); +- /* PREFETCHW || 3DNow! */ +- if ((ecx & 0x100) || (edx & 0x80000000)) +- __x86_prefetchw = -1; +- } +-#endif + } + + if (cpu_features->data_cache_size != 0) +diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile +index d51cf03ac92ebcc2..e3bb45d78811d70f 100644 +--- a/sysdeps/x86_64/Makefile ++++ b/sysdeps/x86_64/Makefile +@@ -18,7 +18,7 @@ tests += tst-mallocalign1 + endif + + ifeq ($(subdir),string) +-sysdep_routines += cacheinfo strcasecmp_l-nonascii strncase_l-nonascii ++sysdep_routines += strcasecmp_l-nonascii strncase_l-nonascii + gen-as-const-headers += locale-defines.sym + endif + diff --git a/glibc-rh1817513-76.patch b/glibc-rh1817513-76.patch new file mode 100755 index 0000000..c241cbf --- /dev/null +++ b/glibc-rh1817513-76.patch @@ -0,0 +1,34 @@ +commit 43530ba1dc4fccd438fefa26f50977ff6bf284c7 +Author: H.J. Lu +Date: Sat Jul 11 10:03:05 2020 -0700 + + x86: Remove __ASSEMBLER__ check in init-arch.h + + Since + + commit 430388d5dc0e1861b869096f4f5d946d7d74232a + Author: H.J. Lu + Date: Fri Aug 3 08:04:49 2018 -0700 + + x86: Don't include in assembly codes + + removed all usages of from assembly codes, we can remove + __ASSEMBLER__ check in init-arch.h. + +diff --git a/sysdeps/x86/init-arch.h b/sysdeps/x86/init-arch.h +index bc860fcd69a605b3..63a7f8562010e5e2 100644 +--- a/sysdeps/x86/init-arch.h ++++ b/sysdeps/x86/init-arch.h +@@ -15,11 +15,7 @@ + License along with the GNU C Library; if not, see + . */ + +-#ifdef __ASSEMBLER__ +-# include +-#else +-# include +-#endif ++#include + #include + #include + diff --git a/glibc-rh1817513-77.patch b/glibc-rh1817513-77.patch new file mode 100755 index 0000000..10ed7a3 --- /dev/null +++ b/glibc-rh1817513-77.patch @@ -0,0 +1,3679 @@ +commit 107e6a3c2212ba7a3a4ec7cae8d82d73f7c95d0b +Author: H.J. Lu +Date: Mon Jun 29 16:36:08 2020 -0700 + + x86: Support usable check for all CPU features + + Support usable check for all CPU features with the following changes: + + 1. Change struct cpu_features to + + struct cpuid_features + { + struct cpuid_registers cpuid; + struct cpuid_registers usable; + }; + + struct cpu_features + { + struct cpu_features_basic basic; + struct cpuid_features features[COMMON_CPUID_INDEX_MAX]; + unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX]; + ... + }; + + so that there is a usable bit for each cpuid bit. + 2. After the cpuid bits have been initialized, copy the known bits to the + usable bits. EAX/EBX from INDEX_1 and EAX from INDEX_7 aren't used for + CPU feature detection. + 3. Clear the usable bits which require OS support. + 4. If the feature is supported by OS, copy its cpuid bit to its usable + bit. + 5. Replace HAS_CPU_FEATURE and CPU_FEATURES_CPU_P with CPU_FEATURE_USABLE + and CPU_FEATURE_USABLE_P to check if a feature is usable. + 6. Add DEPR_FPU_CS_DS for INDEX_7_EBX_13. + 7. Unset MPX feature since it has been deprecated. + + The results are + + 1. If the feature is known and doesn't requre OS support, its usable bit + is copied from the cpuid bit. + 2. Otherwise, its usable bit is copied from the cpuid bit only if the + feature is known to supported by OS. + 3. CPU_FEATURE_USABLE/CPU_FEATURE_USABLE_P are used to check if the + feature can be used. + 4. HAS_CPU_FEATURE/CPU_FEATURE_CPU_P are used to check if CPU supports + the feature. + +diff --git a/sysdeps/i386/fpu/fclrexcpt.c b/sysdeps/i386/fpu/fclrexcpt.c +index 8463b102e7b79f07..9eff917e88235c64 100644 +--- a/sysdeps/i386/fpu/fclrexcpt.c ++++ b/sysdeps/i386/fpu/fclrexcpt.c +@@ -41,7 +41,7 @@ __feclearexcept (int excepts) + __asm__ ("fldenv %0" : : "m" (*&temp)); + + /* If the CPU supports SSE, we clear the MXCSR as well. */ +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + { + unsigned int xnew_exc; + +diff --git a/sysdeps/i386/fpu/fedisblxcpt.c b/sysdeps/i386/fpu/fedisblxcpt.c +index e2738e6d6c8304fe..3b5436018d08a269 100644 +--- a/sysdeps/i386/fpu/fedisblxcpt.c ++++ b/sysdeps/i386/fpu/fedisblxcpt.c +@@ -38,7 +38,7 @@ fedisableexcept (int excepts) + __asm__ ("fldcw %0" : : "m" (*&new_exc)); + + /* If the CPU supports SSE we set the MXCSR as well. */ +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + { + unsigned int xnew_exc; + +diff --git a/sysdeps/i386/fpu/feenablxcpt.c b/sysdeps/i386/fpu/feenablxcpt.c +index a4d986266636835b..88f46f6078e12e2c 100644 +--- a/sysdeps/i386/fpu/feenablxcpt.c ++++ b/sysdeps/i386/fpu/feenablxcpt.c +@@ -38,7 +38,7 @@ feenableexcept (int excepts) + __asm__ ("fldcw %0" : : "m" (*&new_exc)); + + /* If the CPU supports SSE we set the MXCSR as well. */ +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + { + unsigned int xnew_exc; + +diff --git a/sysdeps/i386/fpu/fegetenv.c b/sysdeps/i386/fpu/fegetenv.c +index 2a1a8507bac9bfa5..2a800fb6d6e856f3 100644 +--- a/sysdeps/i386/fpu/fegetenv.c ++++ b/sysdeps/i386/fpu/fegetenv.c +@@ -31,7 +31,7 @@ __fegetenv (fenv_t *envp) + would block all exceptions. */ + __asm__ ("fldenv %0" : : "m" (*envp)); + +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + __asm__ ("stmxcsr %0" : "=m" (envp->__eip)); + + /* Success. */ +diff --git a/sysdeps/i386/fpu/fegetmode.c b/sysdeps/i386/fpu/fegetmode.c +index 86de9f5548f4b0b4..b01ca64fc9187b10 100644 +--- a/sysdeps/i386/fpu/fegetmode.c ++++ b/sysdeps/i386/fpu/fegetmode.c +@@ -26,7 +26,7 @@ int + fegetmode (femode_t *modep) + { + _FPU_GETCW (modep->__control_word); +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + __asm__ ("stmxcsr %0" : "=m" (modep->__mxcsr)); + return 0; + } +diff --git a/sysdeps/i386/fpu/feholdexcpt.c b/sysdeps/i386/fpu/feholdexcpt.c +index 270554df31928cda..e2f3f97b9494f900 100644 +--- a/sysdeps/i386/fpu/feholdexcpt.c ++++ b/sysdeps/i386/fpu/feholdexcpt.c +@@ -30,7 +30,7 @@ __feholdexcept (fenv_t *envp) + __asm__ volatile ("fnstenv %0; fnclex" : "=m" (*envp)); + + /* If the CPU supports SSE we set the MXCSR as well. */ +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + { + unsigned int xwork; + +diff --git a/sysdeps/i386/fpu/fesetenv.c b/sysdeps/i386/fpu/fesetenv.c +index 6df6849da4007a45..5c8bf1f71a474aa9 100644 +--- a/sysdeps/i386/fpu/fesetenv.c ++++ b/sysdeps/i386/fpu/fesetenv.c +@@ -79,7 +79,7 @@ __fesetenv (const fenv_t *envp) + + __asm__ ("fldenv %0" : : "m" (temp)); + +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + { + unsigned int mxcsr; + __asm__ ("stmxcsr %0" : "=m" (mxcsr)); +diff --git a/sysdeps/i386/fpu/fesetmode.c b/sysdeps/i386/fpu/fesetmode.c +index 9aad6ea99f810786..35881b6adf5b0aed 100644 +--- a/sysdeps/i386/fpu/fesetmode.c ++++ b/sysdeps/i386/fpu/fesetmode.c +@@ -35,7 +35,7 @@ fesetmode (const femode_t *modep) + else + cw = modep->__control_word; + _FPU_SETCW (cw); +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + { + unsigned int mxcsr; + __asm__ ("stmxcsr %0" : "=m" (mxcsr)); +diff --git a/sysdeps/i386/fpu/fesetround.c b/sysdeps/i386/fpu/fesetround.c +index d260046c65d0aba0..5d38b6b8624bdaef 100644 +--- a/sysdeps/i386/fpu/fesetround.c ++++ b/sysdeps/i386/fpu/fesetround.c +@@ -37,7 +37,7 @@ __fesetround (int round) + __asm__ ("fldcw %0" : : "m" (*&cw)); + + /* If the CPU supports SSE we set the MXCSR as well. */ +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + { + unsigned int xcw; + +diff --git a/sysdeps/i386/fpu/feupdateenv.c b/sysdeps/i386/fpu/feupdateenv.c +index db3ff96dfa8336ec..1246b21e30740922 100644 +--- a/sysdeps/i386/fpu/feupdateenv.c ++++ b/sysdeps/i386/fpu/feupdateenv.c +@@ -32,7 +32,7 @@ __feupdateenv (const fenv_t *envp) + __asm__ ("fnstsw %0" : "=m" (*&temp)); + + /* If the CPU supports SSE we test the MXCSR as well. */ +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + __asm__ ("stmxcsr %0" : "=m" (*&xtemp)); + + temp = (temp | xtemp) & FE_ALL_EXCEPT; +diff --git a/sysdeps/i386/fpu/fgetexcptflg.c b/sysdeps/i386/fpu/fgetexcptflg.c +index 39d1f7df3aa24b25..acb2ae15ea681c13 100644 +--- a/sysdeps/i386/fpu/fgetexcptflg.c ++++ b/sysdeps/i386/fpu/fgetexcptflg.c +@@ -34,7 +34,7 @@ __fegetexceptflag (fexcept_t *flagp, int excepts) + *flagp = temp & excepts & FE_ALL_EXCEPT; + + /* If the CPU supports SSE, we clear the MXCSR as well. */ +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + { + unsigned int sse_exc; + +diff --git a/sysdeps/i386/fpu/fsetexcptflg.c b/sysdeps/i386/fpu/fsetexcptflg.c +index 21e70251cfbf8a73..caa15c0cf105a9bc 100644 +--- a/sysdeps/i386/fpu/fsetexcptflg.c ++++ b/sysdeps/i386/fpu/fsetexcptflg.c +@@ -41,7 +41,7 @@ __fesetexceptflag (const fexcept_t *flagp, int excepts) + __asm__ ("fldenv %0" : : "m" (*&temp)); + + /* If the CPU supports SSE, we set the MXCSR as well. */ +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + { + unsigned int xnew_exc; + +diff --git a/sysdeps/i386/fpu/ftestexcept.c b/sysdeps/i386/fpu/ftestexcept.c +index c1b5e90356bae9da..06d6134e0d85eeef 100644 +--- a/sysdeps/i386/fpu/ftestexcept.c ++++ b/sysdeps/i386/fpu/ftestexcept.c +@@ -32,7 +32,7 @@ fetestexcept (int excepts) + __asm__ ("fnstsw %0" : "=a" (temp)); + + /* If the CPU supports SSE we test the MXCSR as well. */ +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + __asm__ ("stmxcsr %0" : "=m" (*&xtemp)); + + return (temp | xtemp) & excepts & FE_ALL_EXCEPT; +diff --git a/sysdeps/i386/i686/fpu/multiarch/s_cosf.c b/sysdeps/i386/i686/fpu/multiarch/s_cosf.c +index a4556a478d16974a..c31592f238d67916 100644 +--- a/sysdeps/i386/i686/fpu/multiarch/s_cosf.c ++++ b/sysdeps/i386/i686/fpu/multiarch/s_cosf.c +@@ -23,7 +23,7 @@ extern float __cosf_sse2 (float); + extern float __cosf_ia32 (float); + float __cosf (float); + +-libm_ifunc (__cosf, HAS_CPU_FEATURE (SSE2) ? __cosf_sse2 : __cosf_ia32); ++libm_ifunc (__cosf, CPU_FEATURE_USABLE (SSE2) ? __cosf_sse2 : __cosf_ia32); + libm_alias_float (__cos, cos); + + #define COSF __cosf_ia32 +diff --git a/sysdeps/i386/i686/fpu/multiarch/s_sincosf.c b/sysdeps/i386/i686/fpu/multiarch/s_sincosf.c +index 5f21f5c0eda20fd1..116c541dba54dd16 100644 +--- a/sysdeps/i386/i686/fpu/multiarch/s_sincosf.c ++++ b/sysdeps/i386/i686/fpu/multiarch/s_sincosf.c +@@ -24,7 +24,7 @@ extern void __sincosf_ia32 (float, float *, float *); + void __sincosf (float, float *, float *); + + libm_ifunc (__sincosf, +- HAS_CPU_FEATURE (SSE2) ? __sincosf_sse2 : __sincosf_ia32); ++ CPU_FEATURE_USABLE (SSE2) ? __sincosf_sse2 : __sincosf_ia32); + libm_alias_float (__sincos, sincos); + + #define SINCOSF __sincosf_ia32 +diff --git a/sysdeps/i386/i686/fpu/multiarch/s_sinf.c b/sysdeps/i386/i686/fpu/multiarch/s_sinf.c +index 80a7ffaa1e36b492..63abd34c21a1c83f 100644 +--- a/sysdeps/i386/i686/fpu/multiarch/s_sinf.c ++++ b/sysdeps/i386/i686/fpu/multiarch/s_sinf.c +@@ -23,7 +23,7 @@ extern float __sinf_sse2 (float); + extern float __sinf_ia32 (float); + float __sinf (float); + +-libm_ifunc (__sinf, HAS_CPU_FEATURE (SSE2) ? __sinf_sse2 : __sinf_ia32); ++libm_ifunc (__sinf, CPU_FEATURE_USABLE (SSE2) ? __sinf_sse2 : __sinf_ia32); + libm_alias_float (__sin, sin); + #define SINF __sinf_ia32 + #include +diff --git a/sysdeps/i386/i686/multiarch/ifunc-impl-list.c b/sysdeps/i386/i686/multiarch/ifunc-impl-list.c +index a926b04acdfbb889..06e7231d94e21c02 100644 +--- a/sysdeps/i386/i686/multiarch/ifunc-impl-list.c ++++ b/sysdeps/i386/i686/multiarch/ifunc-impl-list.c +@@ -38,35 +38,35 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/i386/i686/multiarch/bcopy.S. */ + IFUNC_IMPL (i, name, bcopy, +- IFUNC_IMPL_ADD (array, i, bcopy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, bcopy, CPU_FEATURE_USABLE (SSSE3), + __bcopy_ssse3_rep) +- IFUNC_IMPL_ADD (array, i, bcopy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, bcopy, CPU_FEATURE_USABLE (SSSE3), + __bcopy_ssse3) +- IFUNC_IMPL_ADD (array, i, bcopy, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, bcopy, CPU_FEATURE_USABLE (SSE2), + __bcopy_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, bcopy, 1, __bcopy_ia32)) + + /* Support sysdeps/i386/i686/multiarch/bzero.S. */ + IFUNC_IMPL (i, name, bzero, +- IFUNC_IMPL_ADD (array, i, bzero, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, bzero, CPU_FEATURE_USABLE (SSE2), + __bzero_sse2_rep) +- IFUNC_IMPL_ADD (array, i, bzero, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, bzero, CPU_FEATURE_USABLE (SSE2), + __bzero_sse2) + IFUNC_IMPL_ADD (array, i, bzero, 1, __bzero_ia32)) + + /* Support sysdeps/i386/i686/multiarch/memchr.S. */ + IFUNC_IMPL (i, name, memchr, +- IFUNC_IMPL_ADD (array, i, memchr, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, memchr, CPU_FEATURE_USABLE (SSE2), + __memchr_sse2_bsf) +- IFUNC_IMPL_ADD (array, i, memchr, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, memchr, CPU_FEATURE_USABLE (SSE2), + __memchr_sse2) + IFUNC_IMPL_ADD (array, i, memchr, 1, __memchr_ia32)) + + /* Support sysdeps/i386/i686/multiarch/memcmp.S. */ + IFUNC_IMPL (i, name, memcmp, +- IFUNC_IMPL_ADD (array, i, memcmp, HAS_CPU_FEATURE (SSE4_2), ++ IFUNC_IMPL_ADD (array, i, memcmp, CPU_FEATURE_USABLE (SSE4_2), + __memcmp_sse4_2) +- IFUNC_IMPL_ADD (array, i, memcmp, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, memcmp, CPU_FEATURE_USABLE (SSSE3), + __memcmp_ssse3) + IFUNC_IMPL_ADD (array, i, memcmp, 1, __memcmp_ia32)) + +@@ -74,13 +74,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/i386/i686/multiarch/memmove_chk.S. */ + IFUNC_IMPL (i, name, __memmove_chk, + IFUNC_IMPL_ADD (array, i, __memmove_chk, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __memmove_chk_ssse3_rep) + IFUNC_IMPL_ADD (array, i, __memmove_chk, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __memmove_chk_ssse3) + IFUNC_IMPL_ADD (array, i, __memmove_chk, +- HAS_CPU_FEATURE (SSE2), ++ CPU_FEATURE_USABLE (SSE2), + __memmove_chk_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, __memmove_chk, 1, + __memmove_chk_ia32)) +@@ -88,19 +88,19 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/i386/i686/multiarch/memmove.S. */ + IFUNC_IMPL (i, name, memmove, +- IFUNC_IMPL_ADD (array, i, memmove, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, memmove, CPU_FEATURE_USABLE (SSSE3), + __memmove_ssse3_rep) +- IFUNC_IMPL_ADD (array, i, memmove, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, memmove, CPU_FEATURE_USABLE (SSSE3), + __memmove_ssse3) +- IFUNC_IMPL_ADD (array, i, memmove, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, memmove, CPU_FEATURE_USABLE (SSE2), + __memmove_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_ia32)) + + /* Support sysdeps/i386/i686/multiarch/memrchr.S. */ + IFUNC_IMPL (i, name, memrchr, +- IFUNC_IMPL_ADD (array, i, memrchr, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, memrchr, CPU_FEATURE_USABLE (SSE2), + __memrchr_sse2_bsf) +- IFUNC_IMPL_ADD (array, i, memrchr, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, memrchr, CPU_FEATURE_USABLE (SSE2), + __memrchr_sse2) + IFUNC_IMPL_ADD (array, i, memrchr, 1, __memrchr_ia32)) + +@@ -108,10 +108,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/i386/i686/multiarch/memset_chk.S. */ + IFUNC_IMPL (i, name, __memset_chk, + IFUNC_IMPL_ADD (array, i, __memset_chk, +- HAS_CPU_FEATURE (SSE2), ++ CPU_FEATURE_USABLE (SSE2), + __memset_chk_sse2_rep) + IFUNC_IMPL_ADD (array, i, __memset_chk, +- HAS_CPU_FEATURE (SSE2), ++ CPU_FEATURE_USABLE (SSE2), + __memset_chk_sse2) + IFUNC_IMPL_ADD (array, i, __memset_chk, 1, + __memset_chk_ia32)) +@@ -119,102 +119,102 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/i386/i686/multiarch/memset.S. */ + IFUNC_IMPL (i, name, memset, +- IFUNC_IMPL_ADD (array, i, memset, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, memset, CPU_FEATURE_USABLE (SSE2), + __memset_sse2_rep) +- IFUNC_IMPL_ADD (array, i, memset, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, memset, CPU_FEATURE_USABLE (SSE2), + __memset_sse2) + IFUNC_IMPL_ADD (array, i, memset, 1, __memset_ia32)) + + /* Support sysdeps/i386/i686/multiarch/rawmemchr.S. */ + IFUNC_IMPL (i, name, rawmemchr, +- IFUNC_IMPL_ADD (array, i, rawmemchr, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, rawmemchr, CPU_FEATURE_USABLE (SSE2), + __rawmemchr_sse2_bsf) +- IFUNC_IMPL_ADD (array, i, rawmemchr, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, rawmemchr, CPU_FEATURE_USABLE (SSE2), + __rawmemchr_sse2) + IFUNC_IMPL_ADD (array, i, rawmemchr, 1, __rawmemchr_ia32)) + + /* Support sysdeps/i386/i686/multiarch/stpncpy.S. */ + IFUNC_IMPL (i, name, stpncpy, +- IFUNC_IMPL_ADD (array, i, stpncpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, stpncpy, CPU_FEATURE_USABLE (SSSE3), + __stpncpy_ssse3) +- IFUNC_IMPL_ADD (array, i, stpncpy, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, stpncpy, CPU_FEATURE_USABLE (SSE2), + __stpncpy_sse2) + IFUNC_IMPL_ADD (array, i, stpncpy, 1, __stpncpy_ia32)) + + /* Support sysdeps/i386/i686/multiarch/stpcpy.S. */ + IFUNC_IMPL (i, name, stpcpy, +- IFUNC_IMPL_ADD (array, i, stpcpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, stpcpy, CPU_FEATURE_USABLE (SSSE3), + __stpcpy_ssse3) +- IFUNC_IMPL_ADD (array, i, stpcpy, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, stpcpy, CPU_FEATURE_USABLE (SSE2), + __stpcpy_sse2) + IFUNC_IMPL_ADD (array, i, stpcpy, 1, __stpcpy_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strcasecmp.S. */ + IFUNC_IMPL (i, name, strcasecmp, + IFUNC_IMPL_ADD (array, i, strcasecmp, +- HAS_CPU_FEATURE (SSE4_2), ++ CPU_FEATURE_USABLE (SSE4_2), + __strcasecmp_sse4_2) + IFUNC_IMPL_ADD (array, i, strcasecmp, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __strcasecmp_ssse3) + IFUNC_IMPL_ADD (array, i, strcasecmp, 1, __strcasecmp_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strcasecmp_l.S. */ + IFUNC_IMPL (i, name, strcasecmp_l, + IFUNC_IMPL_ADD (array, i, strcasecmp_l, +- HAS_CPU_FEATURE (SSE4_2), ++ CPU_FEATURE_USABLE (SSE4_2), + __strcasecmp_l_sse4_2) + IFUNC_IMPL_ADD (array, i, strcasecmp_l, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __strcasecmp_l_ssse3) + IFUNC_IMPL_ADD (array, i, strcasecmp_l, 1, + __strcasecmp_l_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strcat.S. */ + IFUNC_IMPL (i, name, strcat, +- IFUNC_IMPL_ADD (array, i, strcat, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, strcat, CPU_FEATURE_USABLE (SSSE3), + __strcat_ssse3) +- IFUNC_IMPL_ADD (array, i, strcat, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, strcat, CPU_FEATURE_USABLE (SSE2), + __strcat_sse2) + IFUNC_IMPL_ADD (array, i, strcat, 1, __strcat_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strchr.S. */ + IFUNC_IMPL (i, name, strchr, +- IFUNC_IMPL_ADD (array, i, strchr, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, strchr, CPU_FEATURE_USABLE (SSE2), + __strchr_sse2_bsf) +- IFUNC_IMPL_ADD (array, i, strchr, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, strchr, CPU_FEATURE_USABLE (SSE2), + __strchr_sse2) + IFUNC_IMPL_ADD (array, i, strchr, 1, __strchr_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strcmp.S. */ + IFUNC_IMPL (i, name, strcmp, +- IFUNC_IMPL_ADD (array, i, strcmp, HAS_CPU_FEATURE (SSE4_2), ++ IFUNC_IMPL_ADD (array, i, strcmp, CPU_FEATURE_USABLE (SSE4_2), + __strcmp_sse4_2) +- IFUNC_IMPL_ADD (array, i, strcmp, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, strcmp, CPU_FEATURE_USABLE (SSSE3), + __strcmp_ssse3) + IFUNC_IMPL_ADD (array, i, strcmp, 1, __strcmp_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strcpy.S. */ + IFUNC_IMPL (i, name, strcpy, +- IFUNC_IMPL_ADD (array, i, strcpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, strcpy, CPU_FEATURE_USABLE (SSSE3), + __strcpy_ssse3) +- IFUNC_IMPL_ADD (array, i, strcpy, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, strcpy, CPU_FEATURE_USABLE (SSE2), + __strcpy_sse2) + IFUNC_IMPL_ADD (array, i, strcpy, 1, __strcpy_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strcspn.S. */ + IFUNC_IMPL (i, name, strcspn, +- IFUNC_IMPL_ADD (array, i, strcspn, HAS_CPU_FEATURE (SSE4_2), ++ IFUNC_IMPL_ADD (array, i, strcspn, CPU_FEATURE_USABLE (SSE4_2), + __strcspn_sse42) + IFUNC_IMPL_ADD (array, i, strcspn, 1, __strcspn_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strncase.S. */ + IFUNC_IMPL (i, name, strncasecmp, + IFUNC_IMPL_ADD (array, i, strncasecmp, +- HAS_CPU_FEATURE (SSE4_2), ++ CPU_FEATURE_USABLE (SSE4_2), + __strncasecmp_sse4_2) + IFUNC_IMPL_ADD (array, i, strncasecmp, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __strncasecmp_ssse3) + IFUNC_IMPL_ADD (array, i, strncasecmp, 1, + __strncasecmp_ia32)) +@@ -222,91 +222,91 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/i386/i686/multiarch/strncase_l.S. */ + IFUNC_IMPL (i, name, strncasecmp_l, + IFUNC_IMPL_ADD (array, i, strncasecmp_l, +- HAS_CPU_FEATURE (SSE4_2), ++ CPU_FEATURE_USABLE (SSE4_2), + __strncasecmp_l_sse4_2) + IFUNC_IMPL_ADD (array, i, strncasecmp_l, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __strncasecmp_l_ssse3) + IFUNC_IMPL_ADD (array, i, strncasecmp_l, 1, + __strncasecmp_l_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strncat.S. */ + IFUNC_IMPL (i, name, strncat, +- IFUNC_IMPL_ADD (array, i, strncat, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, strncat, CPU_FEATURE_USABLE (SSSE3), + __strncat_ssse3) +- IFUNC_IMPL_ADD (array, i, strncat, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, strncat, CPU_FEATURE_USABLE (SSE2), + __strncat_sse2) + IFUNC_IMPL_ADD (array, i, strncat, 1, __strncat_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strncpy.S. */ + IFUNC_IMPL (i, name, strncpy, +- IFUNC_IMPL_ADD (array, i, strncpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, strncpy, CPU_FEATURE_USABLE (SSSE3), + __strncpy_ssse3) +- IFUNC_IMPL_ADD (array, i, strncpy, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, strncpy, CPU_FEATURE_USABLE (SSE2), + __strncpy_sse2) + IFUNC_IMPL_ADD (array, i, strncpy, 1, __strncpy_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strnlen.S. */ + IFUNC_IMPL (i, name, strnlen, +- IFUNC_IMPL_ADD (array, i, strnlen, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, strnlen, CPU_FEATURE_USABLE (SSE2), + __strnlen_sse2) + IFUNC_IMPL_ADD (array, i, strnlen, 1, __strnlen_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strpbrk.S. */ + IFUNC_IMPL (i, name, strpbrk, +- IFUNC_IMPL_ADD (array, i, strpbrk, HAS_CPU_FEATURE (SSE4_2), ++ IFUNC_IMPL_ADD (array, i, strpbrk, CPU_FEATURE_USABLE (SSE4_2), + __strpbrk_sse42) + IFUNC_IMPL_ADD (array, i, strpbrk, 1, __strpbrk_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strrchr.S. */ + IFUNC_IMPL (i, name, strrchr, +- IFUNC_IMPL_ADD (array, i, strrchr, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, strrchr, CPU_FEATURE_USABLE (SSE2), + __strrchr_sse2_bsf) +- IFUNC_IMPL_ADD (array, i, strrchr, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, strrchr, CPU_FEATURE_USABLE (SSE2), + __strrchr_sse2) + IFUNC_IMPL_ADD (array, i, strrchr, 1, __strrchr_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strspn.S. */ + IFUNC_IMPL (i, name, strspn, +- IFUNC_IMPL_ADD (array, i, strspn, HAS_CPU_FEATURE (SSE4_2), ++ IFUNC_IMPL_ADD (array, i, strspn, CPU_FEATURE_USABLE (SSE4_2), + __strspn_sse42) + IFUNC_IMPL_ADD (array, i, strspn, 1, __strspn_ia32)) + + /* Support sysdeps/i386/i686/multiarch/wcschr.S. */ + IFUNC_IMPL (i, name, wcschr, +- IFUNC_IMPL_ADD (array, i, wcschr, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, wcschr, CPU_FEATURE_USABLE (SSE2), + __wcschr_sse2) + IFUNC_IMPL_ADD (array, i, wcschr, 1, __wcschr_ia32)) + + /* Support sysdeps/i386/i686/multiarch/wcscmp.S. */ + IFUNC_IMPL (i, name, wcscmp, +- IFUNC_IMPL_ADD (array, i, wcscmp, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, wcscmp, CPU_FEATURE_USABLE (SSE2), + __wcscmp_sse2) + IFUNC_IMPL_ADD (array, i, wcscmp, 1, __wcscmp_ia32)) + + /* Support sysdeps/i386/i686/multiarch/wcscpy.S. */ + IFUNC_IMPL (i, name, wcscpy, +- IFUNC_IMPL_ADD (array, i, wcscpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, wcscpy, CPU_FEATURE_USABLE (SSSE3), + __wcscpy_ssse3) + IFUNC_IMPL_ADD (array, i, wcscpy, 1, __wcscpy_ia32)) + + /* Support sysdeps/i386/i686/multiarch/wcslen.S. */ + IFUNC_IMPL (i, name, wcslen, +- IFUNC_IMPL_ADD (array, i, wcslen, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, wcslen, CPU_FEATURE_USABLE (SSE2), + __wcslen_sse2) + IFUNC_IMPL_ADD (array, i, wcslen, 1, __wcslen_ia32)) + + /* Support sysdeps/i386/i686/multiarch/wcsrchr.S. */ + IFUNC_IMPL (i, name, wcsrchr, +- IFUNC_IMPL_ADD (array, i, wcsrchr, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, wcsrchr, CPU_FEATURE_USABLE (SSE2), + __wcsrchr_sse2) + IFUNC_IMPL_ADD (array, i, wcsrchr, 1, __wcsrchr_ia32)) + + /* Support sysdeps/i386/i686/multiarch/wmemcmp.S. */ + IFUNC_IMPL (i, name, wmemcmp, +- IFUNC_IMPL_ADD (array, i, wmemcmp, HAS_CPU_FEATURE (SSE4_2), ++ IFUNC_IMPL_ADD (array, i, wmemcmp, CPU_FEATURE_USABLE (SSE4_2), + __wmemcmp_sse4_2) +- IFUNC_IMPL_ADD (array, i, wmemcmp, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, wmemcmp, CPU_FEATURE_USABLE (SSSE3), + __wmemcmp_ssse3) + IFUNC_IMPL_ADD (array, i, wmemcmp, 1, __wmemcmp_ia32)) + +@@ -314,64 +314,64 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/i386/i686/multiarch/memcpy_chk.S. */ + IFUNC_IMPL (i, name, __memcpy_chk, + IFUNC_IMPL_ADD (array, i, __memcpy_chk, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __memcpy_chk_ssse3_rep) + IFUNC_IMPL_ADD (array, i, __memcpy_chk, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __memcpy_chk_ssse3) + IFUNC_IMPL_ADD (array, i, __memcpy_chk, +- HAS_CPU_FEATURE (SSE2), ++ CPU_FEATURE_USABLE (SSE2), + __memcpy_chk_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, __memcpy_chk, 1, + __memcpy_chk_ia32)) + + /* Support sysdeps/i386/i686/multiarch/memcpy.S. */ + IFUNC_IMPL (i, name, memcpy, +- IFUNC_IMPL_ADD (array, i, memcpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, memcpy, CPU_FEATURE_USABLE (SSSE3), + __memcpy_ssse3_rep) +- IFUNC_IMPL_ADD (array, i, memcpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, memcpy, CPU_FEATURE_USABLE (SSSE3), + __memcpy_ssse3) +- IFUNC_IMPL_ADD (array, i, memcpy, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, memcpy, CPU_FEATURE_USABLE (SSE2), + __memcpy_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_ia32)) + + /* Support sysdeps/i386/i686/multiarch/mempcpy_chk.S. */ + IFUNC_IMPL (i, name, __mempcpy_chk, + IFUNC_IMPL_ADD (array, i, __mempcpy_chk, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __mempcpy_chk_ssse3_rep) + IFUNC_IMPL_ADD (array, i, __mempcpy_chk, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __mempcpy_chk_ssse3) + IFUNC_IMPL_ADD (array, i, __mempcpy_chk, +- HAS_CPU_FEATURE (SSE2), ++ CPU_FEATURE_USABLE (SSE2), + __mempcpy_chk_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, __mempcpy_chk, 1, + __mempcpy_chk_ia32)) + + /* Support sysdeps/i386/i686/multiarch/mempcpy.S. */ + IFUNC_IMPL (i, name, mempcpy, +- IFUNC_IMPL_ADD (array, i, mempcpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, mempcpy, CPU_FEATURE_USABLE (SSSE3), + __mempcpy_ssse3_rep) +- IFUNC_IMPL_ADD (array, i, mempcpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, mempcpy, CPU_FEATURE_USABLE (SSSE3), + __mempcpy_ssse3) +- IFUNC_IMPL_ADD (array, i, mempcpy, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, mempcpy, CPU_FEATURE_USABLE (SSE2), + __mempcpy_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, mempcpy, 1, __mempcpy_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strlen.S. */ + IFUNC_IMPL (i, name, strlen, +- IFUNC_IMPL_ADD (array, i, strlen, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, strlen, CPU_FEATURE_USABLE (SSE2), + __strlen_sse2_bsf) +- IFUNC_IMPL_ADD (array, i, strlen, HAS_CPU_FEATURE (SSE2), ++ IFUNC_IMPL_ADD (array, i, strlen, CPU_FEATURE_USABLE (SSE2), + __strlen_sse2) + IFUNC_IMPL_ADD (array, i, strlen, 1, __strlen_ia32)) + + /* Support sysdeps/i386/i686/multiarch/strncmp.S. */ + IFUNC_IMPL (i, name, strncmp, +- IFUNC_IMPL_ADD (array, i, strncmp, HAS_CPU_FEATURE (SSE4_2), ++ IFUNC_IMPL_ADD (array, i, strncmp, CPU_FEATURE_USABLE (SSE4_2), + __strncmp_sse4_2) +- IFUNC_IMPL_ADD (array, i, strncmp, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, strncmp, CPU_FEATURE_USABLE (SSSE3), + __strncmp_ssse3) + IFUNC_IMPL_ADD (array, i, strncmp, 1, __strncmp_ia32)) + #endif +diff --git a/sysdeps/i386/i686/multiarch/ifunc-memmove.h b/sysdeps/i386/i686/multiarch/ifunc-memmove.h +index f0e97561784a82d5..cd4333f84b114552 100644 +--- a/sysdeps/i386/i686/multiarch/ifunc-memmove.h ++++ b/sysdeps/i386/i686/multiarch/ifunc-memmove.h +@@ -33,7 +33,7 @@ IFUNC_SELECTOR (void) + if (CPU_FEATURES_ARCH_P (cpu_features, Fast_Unaligned_Load)) + return OPTIMIZE (sse2_unaligned); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSSE3)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSSE3)) + { + if (CPU_FEATURES_ARCH_P (cpu_features, Fast_Rep_String)) + return OPTIMIZE (ssse3_rep); +diff --git a/sysdeps/i386/i686/multiarch/ifunc-memset.h b/sysdeps/i386/i686/multiarch/ifunc-memset.h +index e96609439aef30d1..6cf96ebcd480dba4 100644 +--- a/sysdeps/i386/i686/multiarch/ifunc-memset.h ++++ b/sysdeps/i386/i686/multiarch/ifunc-memset.h +@@ -28,7 +28,7 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSE2)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE2)) + { + if (CPU_FEATURES_ARCH_P (cpu_features, Fast_Rep_String)) + return OPTIMIZE (sse2_rep); +diff --git a/sysdeps/i386/i686/multiarch/ifunc-sse2-bsf.h b/sysdeps/i386/i686/multiarch/ifunc-sse2-bsf.h +index f5e7f1b846c28454..de30f004db53f227 100644 +--- a/sysdeps/i386/i686/multiarch/ifunc-sse2-bsf.h ++++ b/sysdeps/i386/i686/multiarch/ifunc-sse2-bsf.h +@@ -28,7 +28,7 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSE2)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE2)) + { + if (CPU_FEATURES_ARCH_P (cpu_features, Slow_BSF)) + return OPTIMIZE (sse2); +diff --git a/sysdeps/i386/i686/multiarch/ifunc-sse2-ssse3.h b/sysdeps/i386/i686/multiarch/ifunc-sse2-ssse3.h +index a33fe44f504bd178..299d73e3144698d7 100644 +--- a/sysdeps/i386/i686/multiarch/ifunc-sse2-ssse3.h ++++ b/sysdeps/i386/i686/multiarch/ifunc-sse2-ssse3.h +@@ -29,11 +29,11 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSE2) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE2) + && CPU_FEATURES_ARCH_P (cpu_features, Fast_Rep_String)) + return OPTIMIZE (sse2); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSSE3)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSSE3)) + return OPTIMIZE (ssse3); + + return OPTIMIZE (ia32); +diff --git a/sysdeps/i386/i686/multiarch/ifunc-sse2.h b/sysdeps/i386/i686/multiarch/ifunc-sse2.h +index 706c0329c9a76573..e1ba025299037bfb 100644 +--- a/sysdeps/i386/i686/multiarch/ifunc-sse2.h ++++ b/sysdeps/i386/i686/multiarch/ifunc-sse2.h +@@ -27,7 +27,7 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSE2)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE2)) + return OPTIMIZE (sse2); + + return OPTIMIZE (ia32); +diff --git a/sysdeps/i386/i686/multiarch/ifunc-sse4_2.h b/sysdeps/i386/i686/multiarch/ifunc-sse4_2.h +index de7fa2f185ad9a59..641cec2ced510524 100644 +--- a/sysdeps/i386/i686/multiarch/ifunc-sse4_2.h ++++ b/sysdeps/i386/i686/multiarch/ifunc-sse4_2.h +@@ -27,7 +27,7 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSE4_2)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_2)) + return OPTIMIZE (sse42); + + return OPTIMIZE (ia32); +diff --git a/sysdeps/i386/i686/multiarch/ifunc-ssse3-sse4_2.h b/sysdeps/i386/i686/multiarch/ifunc-ssse3-sse4_2.h +index bd772a9298ab7d6b..6b2b461e47e94b66 100644 +--- a/sysdeps/i386/i686/multiarch/ifunc-ssse3-sse4_2.h ++++ b/sysdeps/i386/i686/multiarch/ifunc-ssse3-sse4_2.h +@@ -29,10 +29,10 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSE4_2)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_2)) + return OPTIMIZE (sse4_2); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSSE3)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSSE3)) + return OPTIMIZE (ssse3); + + return OPTIMIZE (ia32); +diff --git a/sysdeps/i386/i686/multiarch/s_fma.c b/sysdeps/i386/i686/multiarch/s_fma.c +index 7f39f5fdc972fcc7..0cf6e41b03043911 100644 +--- a/sysdeps/i386/i686/multiarch/s_fma.c ++++ b/sysdeps/i386/i686/multiarch/s_fma.c +@@ -27,7 +27,7 @@ extern double __fma_ia32 (double x, double y, double z) attribute_hidden; + extern double __fma_fma (double x, double y, double z) attribute_hidden; + + libm_ifunc (__fma, +- HAS_ARCH_FEATURE (FMA_Usable) ? __fma_fma : __fma_ia32); ++ CPU_FEATURE_USABLE (FMA) ? __fma_fma : __fma_ia32); + libm_alias_double (__fma, fma) + + #define __fma __fma_ia32 +diff --git a/sysdeps/i386/i686/multiarch/s_fmaf.c b/sysdeps/i386/i686/multiarch/s_fmaf.c +index 1ebb6e975ee86f54..638cd5b10ba57592 100644 +--- a/sysdeps/i386/i686/multiarch/s_fmaf.c ++++ b/sysdeps/i386/i686/multiarch/s_fmaf.c +@@ -27,7 +27,7 @@ extern float __fmaf_ia32 (float x, float y, float z) attribute_hidden; + extern float __fmaf_fma (float x, float y, float z) attribute_hidden; + + libm_ifunc (__fmaf, +- HAS_ARCH_FEATURE (FMA_Usable) ? __fmaf_fma : __fmaf_ia32); ++ CPU_FEATURE_USABLE (FMA) ? __fmaf_fma : __fmaf_ia32); + libm_alias_float (__fma, fma) + + #define __fmaf __fmaf_ia32 +diff --git a/sysdeps/i386/i686/multiarch/wcscpy.c b/sysdeps/i386/i686/multiarch/wcscpy.c +index be89ab81b066d463..ea149b0d3af357f2 100644 +--- a/sysdeps/i386/i686/multiarch/wcscpy.c ++++ b/sysdeps/i386/i686/multiarch/wcscpy.c +@@ -34,7 +34,7 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSSE3)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSSE3)) + return OPTIMIZE (ssse3); + + return OPTIMIZE (ia32); +diff --git a/sysdeps/i386/setfpucw.c b/sysdeps/i386/setfpucw.c +index 931302bcd03d221b..3fa2651d46a70ab6 100644 +--- a/sysdeps/i386/setfpucw.c ++++ b/sysdeps/i386/setfpucw.c +@@ -39,7 +39,7 @@ __setfpucw (fpu_control_t set) + __asm__ ("fldcw %0" : : "m" (*&cw)); + + /* If the CPU supports SSE, we set the MXCSR as well. */ +- if (HAS_CPU_FEATURE (SSE)) ++ if (CPU_FEATURE_USABLE (SSE)) + { + unsigned int xnew_exc; + +diff --git a/sysdeps/unix/sysv/linux/x86/elision-conf.c b/sysdeps/unix/sysv/linux/x86/elision-conf.c +index 22af294426596add..bdfc514a238f92a8 100644 +--- a/sysdeps/unix/sysv/linux/x86/elision-conf.c ++++ b/sysdeps/unix/sysv/linux/x86/elision-conf.c +@@ -64,7 +64,7 @@ do_set_elision_enable (int32_t elision_enable) + if __libc_enable_secure isn't enabled since elision_enable will be set + according to the default, which is disabled. */ + if (elision_enable == 1) +- __pthread_force_elision = HAS_CPU_FEATURE (RTM) ? 1 : 0; ++ __pthread_force_elision = CPU_FEATURE_USABLE (RTM) ? 1 : 0; + } + + /* The pthread->elision_enable tunable is 0 or 1 indicating that elision +diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c +index f4edbc0103beb435..fdfe2684759d968c 100644 +--- a/sysdeps/x86/cacheinfo.c ++++ b/sysdeps/x86/cacheinfo.c +@@ -583,7 +583,7 @@ get_common_cache_info (long int *shared_ptr, unsigned int *threads_ptr, + + /* A value of 0 for the HTT bit indicates there is only a single + logical processor. */ +- if (HAS_CPU_FEATURE (HTT)) ++ if (CPU_FEATURE_USABLE (HTT)) + { + /* Figure out the number of logical threads that share the + highest cache level. */ +@@ -732,7 +732,7 @@ intel_bug_no_cache_info: + /* Assume that all logical threads share the highest cache + level. */ + threads +- = ((cpu_features->cpuid[COMMON_CPUID_INDEX_1].ebx ++ = ((cpu_features->features[COMMON_CPUID_INDEX_1].cpuid.ebx + >> 16) & 0xff); + } + +@@ -887,14 +887,14 @@ init_cacheinfo (void) + unsigned int minimum_rep_movsb_threshold; + /* NB: The default REP MOVSB threshold is 2048 * (VEC_SIZE / 16). */ + unsigned int rep_movsb_threshold; +- if (CPU_FEATURES_ARCH_P (cpu_features, AVX512F_Usable) +- && !CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_AVX512)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX512F) ++ && !CPU_FEATURE_PREFERRED_P (cpu_features, Prefer_No_AVX512)) + { + rep_movsb_threshold = 2048 * (64 / 16); + minimum_rep_movsb_threshold = 64 * 8; + } +- else if (CPU_FEATURES_ARCH_P (cpu_features, +- AVX_Fast_Unaligned_Load)) ++ else if (CPU_FEATURE_PREFERRED_P (cpu_features, ++ AVX_Fast_Unaligned_Load)) + { + rep_movsb_threshold = 2048 * (32 / 16); + minimum_rep_movsb_threshold = 32 * 8; +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index ad470f79ef7769fc..f13a1df4555c7000 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -42,73 +42,109 @@ extern void TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *) + #endif + + static void +-get_extended_indices (struct cpu_features *cpu_features) ++update_usable (struct cpu_features *cpu_features) + { +- unsigned int eax, ebx, ecx, edx; +- __cpuid (0x80000000, eax, ebx, ecx, edx); +- if (eax >= 0x80000001) +- __cpuid (0x80000001, +- cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].eax, +- cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].ebx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].ecx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_80000001].edx); +- if (eax >= 0x80000007) +- __cpuid (0x80000007, +- cpu_features->cpuid[COMMON_CPUID_INDEX_80000007].eax, +- cpu_features->cpuid[COMMON_CPUID_INDEX_80000007].ebx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_80000007].ecx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_80000007].edx); +- if (eax >= 0x80000008) +- __cpuid (0x80000008, +- cpu_features->cpuid[COMMON_CPUID_INDEX_80000008].eax, +- cpu_features->cpuid[COMMON_CPUID_INDEX_80000008].ebx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_80000008].ecx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_80000008].edx); +-} +- +-static void +-get_common_indices (struct cpu_features *cpu_features, +- unsigned int *family, unsigned int *model, +- unsigned int *extended_model, unsigned int *stepping) +-{ +- if (family) +- { +- unsigned int eax; +- __cpuid (1, eax, cpu_features->cpuid[COMMON_CPUID_INDEX_1].ebx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_1].ecx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_1].edx); +- cpu_features->cpuid[COMMON_CPUID_INDEX_1].eax = eax; +- *family = (eax >> 8) & 0x0f; +- *model = (eax >> 4) & 0x0f; +- *extended_model = (eax >> 12) & 0xf0; +- *stepping = eax & 0x0f; +- if (*family == 0x0f) +- { +- *family += (eax >> 20) & 0xff; +- *model += *extended_model; +- } +- } +- +- if (cpu_features->basic.max_cpuid >= 7) +- { +- __cpuid_count (7, 0, +- cpu_features->cpuid[COMMON_CPUID_INDEX_7].eax, +- cpu_features->cpuid[COMMON_CPUID_INDEX_7].ebx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_7].ecx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_7].edx); +- __cpuid_count (7, 1, +- cpu_features->cpuid[COMMON_CPUID_INDEX_7_ECX_1].eax, +- cpu_features->cpuid[COMMON_CPUID_INDEX_7_ECX_1].ebx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_7_ECX_1].ecx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_7_ECX_1].edx); +- } +- +- if (cpu_features->basic.max_cpuid >= 0xd) +- __cpuid_count (0xd, 1, +- cpu_features->cpuid[COMMON_CPUID_INDEX_D_ECX_1].eax, +- cpu_features->cpuid[COMMON_CPUID_INDEX_D_ECX_1].ebx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_D_ECX_1].ecx, +- cpu_features->cpuid[COMMON_CPUID_INDEX_D_ECX_1].edx); ++ /* Before COMMON_CPUID_INDEX_80000001, copy the cpuid array elements to ++ the usable array. */ ++ unsigned int i; ++ for (i = 0; i < COMMON_CPUID_INDEX_80000001; i++) ++ cpu_features->features[i].usable = cpu_features->features[i].cpuid; ++ ++ /* Before COMMON_CPUID_INDEX_80000001, clear the unknown usable bits ++ and the always zero bits. */ ++ CPU_FEATURE_UNSET (cpu_features, INDEX_1_ECX_16); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_1_ECX_31); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_1_EDX_10); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_1_EDX_20); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_1_EDX_30); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EBX_6); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EBX_22); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_ECX_13); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_ECX_15); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_ECX_16); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_ECX_23); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_ECX_24); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_ECX_26); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_0); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_1); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_5); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_6); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_7); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_9); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_11); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_12); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_13); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_17); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_19); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_21); ++ CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_23); ++ ++ /* EAX/EBX from COMMON_CPUID_INDEX_1 and EAX from COMMON_CPUID_INDEX_7 ++ aren't used for CPU feature detection. */ ++ cpu_features->features[COMMON_CPUID_INDEX_1].usable.eax = 0; ++ cpu_features->features[COMMON_CPUID_INDEX_1].usable.ebx = 0; ++ cpu_features->features[COMMON_CPUID_INDEX_7].usable.eax = 0; ++ ++ /* Starting from COMMON_CPUID_INDEX_80000001, copy the cpuid bits to ++ usable bits. */ ++ CPU_FEATURE_SET_USABLE (cpu_features, LAHF64_SAHF64); ++ CPU_FEATURE_SET_USABLE (cpu_features, SVM); ++ CPU_FEATURE_SET_USABLE (cpu_features, LZCNT); ++ CPU_FEATURE_SET_USABLE (cpu_features, SSE4A); ++ CPU_FEATURE_SET_USABLE (cpu_features, PREFETCHW); ++ CPU_FEATURE_SET_USABLE (cpu_features, XOP); ++ CPU_FEATURE_SET_USABLE (cpu_features, LWP); ++ CPU_FEATURE_SET_USABLE (cpu_features, FMA4); ++ CPU_FEATURE_SET_USABLE (cpu_features, TBM); ++ CPU_FEATURE_SET_USABLE (cpu_features, SYSCALL_SYSRET); ++ CPU_FEATURE_SET_USABLE (cpu_features, NX); ++ CPU_FEATURE_SET_USABLE (cpu_features, PAGE1GB); ++ CPU_FEATURE_SET_USABLE (cpu_features, RDTSCP); ++ CPU_FEATURE_SET_USABLE (cpu_features, LM); ++ CPU_FEATURE_SET_USABLE (cpu_features, XSAVEOPT); ++ CPU_FEATURE_SET_USABLE (cpu_features, XSAVEC); ++ CPU_FEATURE_SET_USABLE (cpu_features, XGETBV_ECX_1); ++ CPU_FEATURE_SET_USABLE (cpu_features, XSAVES); ++ CPU_FEATURE_SET_USABLE (cpu_features, XFD); ++ CPU_FEATURE_SET_USABLE (cpu_features, INVARIANT_TSC); ++ CPU_FEATURE_SET_USABLE (cpu_features, WBNOINVD); ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512_BF16); ++ ++ /* MPX has been deprecated. */ ++ CPU_FEATURE_UNSET (cpu_features, MPX); ++ ++ /* Clear the usable bits which require OS support. */ ++ CPU_FEATURE_UNSET (cpu_features, FMA); ++ CPU_FEATURE_UNSET (cpu_features, AVX); ++ CPU_FEATURE_UNSET (cpu_features, F16C); ++ CPU_FEATURE_UNSET (cpu_features, AVX2); ++ CPU_FEATURE_UNSET (cpu_features, AVX512F); ++ CPU_FEATURE_UNSET (cpu_features, AVX512DQ); ++ CPU_FEATURE_UNSET (cpu_features, AVX512_IFMA); ++ CPU_FEATURE_UNSET (cpu_features, AVX512PF); ++ CPU_FEATURE_UNSET (cpu_features, AVX512ER); ++ CPU_FEATURE_UNSET (cpu_features, AVX512CD); ++ CPU_FEATURE_UNSET (cpu_features, AVX512BW); ++ CPU_FEATURE_UNSET (cpu_features, AVX512VL); ++ CPU_FEATURE_UNSET (cpu_features, AVX512_VBMI); ++ CPU_FEATURE_UNSET (cpu_features, PKU); ++ CPU_FEATURE_UNSET (cpu_features, AVX512_VBMI2); ++ CPU_FEATURE_UNSET (cpu_features, VAES); ++ CPU_FEATURE_UNSET (cpu_features, VPCLMULQDQ); ++ CPU_FEATURE_UNSET (cpu_features, AVX512_VNNI); ++ CPU_FEATURE_UNSET (cpu_features, AVX512_BITALG); ++ CPU_FEATURE_UNSET (cpu_features, AVX512_VPOPCNTDQ); ++ CPU_FEATURE_UNSET (cpu_features, AVX512_4VNNIW); ++ CPU_FEATURE_UNSET (cpu_features, AVX512_4FMAPS); ++ CPU_FEATURE_UNSET (cpu_features, AVX512_VP2INTERSECT); ++ CPU_FEATURE_UNSET (cpu_features, AMX_BF16); ++ CPU_FEATURE_UNSET (cpu_features, AMX_TILE); ++ CPU_FEATURE_UNSET (cpu_features, AMX_INT8); ++ CPU_FEATURE_UNSET (cpu_features, XOP); ++ CPU_FEATURE_UNSET (cpu_features, FMA4); ++ CPU_FEATURE_UNSET (cpu_features, XSAVEC); ++ CPU_FEATURE_UNSET (cpu_features, XFD); ++ CPU_FEATURE_UNSET (cpu_features, AVX512_BF16); + + /* Can we call xgetbv? */ + if (CPU_FEATURES_CPU_P (cpu_features, OSXSAVE)) +@@ -123,40 +159,28 @@ get_common_indices (struct cpu_features *cpu_features, + /* Determine if AVX is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX)) + { +- cpu_features->usable[index_arch_AVX_Usable] +- |= bit_arch_AVX_Usable; ++ CPU_FEATURE_SET (cpu_features, AVX); + /* The following features depend on AVX being usable. */ + /* Determine if AVX2 is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX2)) +- { +- cpu_features->usable[index_arch_AVX2_Usable] +- |= bit_arch_AVX2_Usable; +- +- /* Unaligned load with 256-bit AVX registers are faster on +- Intel/AMD processors with AVX2. */ +- cpu_features->preferred[index_arch_AVX_Fast_Unaligned_Load] +- |= bit_arch_AVX_Fast_Unaligned_Load; +- } ++ { ++ CPU_FEATURE_SET (cpu_features, AVX2); ++ ++ /* Unaligned load with 256-bit AVX registers are faster ++ on Intel/AMD processors with AVX2. */ ++ cpu_features->preferred[index_arch_AVX_Fast_Unaligned_Load] ++ |= bit_arch_AVX_Fast_Unaligned_Load; ++ } + /* Determine if FMA is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, FMA)) +- cpu_features->usable[index_arch_FMA_Usable] +- |= bit_arch_FMA_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, FMA); + /* Determine if VAES is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, VAES)) +- cpu_features->usable[index_arch_VAES_Usable] +- |= bit_arch_VAES_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, VAES); + /* Determine if VPCLMULQDQ is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, VPCLMULQDQ)) +- cpu_features->usable[index_arch_VPCLMULQDQ_Usable] +- |= bit_arch_VPCLMULQDQ_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, VPCLMULQDQ); + /* Determine if XOP is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, XOP)) +- cpu_features->usable[index_arch_XOP_Usable] +- |= bit_arch_XOP_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, XOP); + /* Determine if F16C is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, F16C)) +- cpu_features->usable[index_arch_F16C_Usable] +- |= bit_arch_F16C_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, F16C); + } + + /* Check if OPMASK state, upper 256-bit of ZMM0-ZMM15 and +@@ -168,73 +192,41 @@ get_common_indices (struct cpu_features *cpu_features, + /* Determine if AVX512F is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, AVX512F)) + { +- cpu_features->usable[index_arch_AVX512F_Usable] +- |= bit_arch_AVX512F_Usable; ++ CPU_FEATURE_SET (cpu_features, AVX512F); + /* Determine if AVX512CD is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512CD)) +- cpu_features->usable[index_arch_AVX512CD_Usable] +- |= bit_arch_AVX512CD_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512CD); + /* Determine if AVX512ER is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512ER)) +- cpu_features->usable[index_arch_AVX512ER_Usable] +- |= bit_arch_AVX512ER_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512ER); + /* Determine if AVX512PF is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512PF)) +- cpu_features->usable[index_arch_AVX512PF_Usable] +- |= bit_arch_AVX512PF_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512PF); + /* Determine if AVX512VL is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512VL)) +- cpu_features->usable[index_arch_AVX512VL_Usable] +- |= bit_arch_AVX512VL_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512VL); + /* Determine if AVX512DQ is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512DQ)) +- cpu_features->usable[index_arch_AVX512DQ_Usable] +- |= bit_arch_AVX512DQ_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512DQ); + /* Determine if AVX512BW is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512BW)) +- cpu_features->usable[index_arch_AVX512BW_Usable] +- |= bit_arch_AVX512BW_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512BW); + /* Determine if AVX512_4FMAPS is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512_4FMAPS)) +- cpu_features->usable[index_arch_AVX512_4FMAPS_Usable] +- |= bit_arch_AVX512_4FMAPS_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512_4FMAPS); + /* Determine if AVX512_4VNNIW is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512_4VNNIW)) +- cpu_features->usable[index_arch_AVX512_4VNNIW_Usable] +- |= bit_arch_AVX512_4VNNIW_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512_4VNNIW); + /* Determine if AVX512_BITALG is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512_BITALG)) +- cpu_features->usable[index_arch_AVX512_BITALG_Usable] +- |= bit_arch_AVX512_BITALG_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512_BITALG); + /* Determine if AVX512_IFMA is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512_IFMA)) +- cpu_features->usable[index_arch_AVX512_IFMA_Usable] +- |= bit_arch_AVX512_IFMA_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512_IFMA); + /* Determine if AVX512_VBMI is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VBMI)) +- cpu_features->usable[index_arch_AVX512_VBMI_Usable] +- |= bit_arch_AVX512_VBMI_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512_VBMI); + /* Determine if AVX512_VBMI2 is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VBMI2)) +- cpu_features->usable[index_arch_AVX512_VBMI2_Usable] +- |= bit_arch_AVX512_VBMI2_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512_VBMI2); + /* Determine if is AVX512_VNNI usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VNNI)) +- cpu_features->usable[index_arch_AVX512_VNNI_Usable] +- |= bit_arch_AVX512_VNNI_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512_VNNI); + /* Determine if AVX512_VPOPCNTDQ is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512_VPOPCNTDQ)) +- cpu_features->usable[index_arch_AVX512_VPOPCNTDQ_Usable] +- |= bit_arch_AVX512_VPOPCNTDQ_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, ++ AVX512_VPOPCNTDQ); + /* Determine if AVX512_VP2INTERSECT is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, +- AVX512_VP2INTERSECT)) +- cpu_features->usable[index_arch_AVX512_VP2INTERSECT_Usable] +- |= bit_arch_AVX512_VP2INTERSECT_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, ++ AVX512_VP2INTERSECT); + /* Determine if AVX512_BF16 is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512_BF16)) +- cpu_features->usable[index_arch_AVX512_BF16_Usable] +- |= bit_arch_AVX512_BF16_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AVX512_BF16); + } + } + } +@@ -244,19 +236,17 @@ get_common_indices (struct cpu_features *cpu_features, + == (bit_XTILECFG_state | bit_XTILEDATA_state)) + { + /* Determine if AMX_BF16 is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AMX_BF16)) +- cpu_features->usable[index_arch_AMX_BF16_Usable] +- |= bit_arch_AMX_BF16_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AMX_BF16); + /* Determine if AMX_TILE is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AMX_TILE)) +- cpu_features->usable[index_arch_AMX_TILE_Usable] +- |= bit_arch_AMX_TILE_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AMX_TILE); + /* Determine if AMX_INT8 is usable. */ +- if (CPU_FEATURES_CPU_P (cpu_features, AMX_INT8)) +- cpu_features->usable[index_arch_AMX_INT8_Usable] +- |= bit_arch_AMX_INT8_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, AMX_INT8); + } + ++ ++ /* XFD is usable only when OSXSAVE is enabled. */ ++ CPU_FEATURE_SET_USABLE (cpu_features, XFD); ++ + /* For _dl_runtime_resolve, set xsave_state_size to xsave area + size + integer register save size and align it to 64 bytes. */ + if (cpu_features->basic.max_cpuid >= 0xd) +@@ -318,8 +308,7 @@ get_common_indices (struct cpu_features *cpu_features, + { + cpu_features->xsave_state_size + = ALIGN_UP (size + STATE_SAVE_OFFSET, 64); +- cpu_features->usable[index_arch_XSAVEC_Usable] +- |= bit_arch_XSAVEC_Usable; ++ CPU_FEATURE_SET (cpu_features, XSAVEC); + } + } + } +@@ -328,8 +317,79 @@ get_common_indices (struct cpu_features *cpu_features, + + /* Determine if PKU is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, OSPKE)) +- cpu_features->usable[index_arch_PKU_Usable] +- |= bit_arch_PKU_Usable; ++ CPU_FEATURE_SET (cpu_features, PKU); ++} ++ ++static void ++get_extended_indices (struct cpu_features *cpu_features) ++{ ++ unsigned int eax, ebx, ecx, edx; ++ __cpuid (0x80000000, eax, ebx, ecx, edx); ++ if (eax >= 0x80000001) ++ __cpuid (0x80000001, ++ cpu_features->features[COMMON_CPUID_INDEX_80000001].cpuid.eax, ++ cpu_features->features[COMMON_CPUID_INDEX_80000001].cpuid.ebx, ++ cpu_features->features[COMMON_CPUID_INDEX_80000001].cpuid.ecx, ++ cpu_features->features[COMMON_CPUID_INDEX_80000001].cpuid.edx); ++ if (eax >= 0x80000007) ++ __cpuid (0x80000007, ++ cpu_features->features[COMMON_CPUID_INDEX_80000007].cpuid.eax, ++ cpu_features->features[COMMON_CPUID_INDEX_80000007].cpuid.ebx, ++ cpu_features->features[COMMON_CPUID_INDEX_80000007].cpuid.ecx, ++ cpu_features->features[COMMON_CPUID_INDEX_80000007].cpuid.edx); ++ if (eax >= 0x80000008) ++ __cpuid (0x80000008, ++ cpu_features->features[COMMON_CPUID_INDEX_80000008].cpuid.eax, ++ cpu_features->features[COMMON_CPUID_INDEX_80000008].cpuid.ebx, ++ cpu_features->features[COMMON_CPUID_INDEX_80000008].cpuid.ecx, ++ cpu_features->features[COMMON_CPUID_INDEX_80000008].cpuid.edx); ++} ++ ++static void ++get_common_indices (struct cpu_features *cpu_features, ++ unsigned int *family, unsigned int *model, ++ unsigned int *extended_model, unsigned int *stepping) ++{ ++ if (family) ++ { ++ unsigned int eax; ++ __cpuid (1, eax, ++ cpu_features->features[COMMON_CPUID_INDEX_1].cpuid.ebx, ++ cpu_features->features[COMMON_CPUID_INDEX_1].cpuid.ecx, ++ cpu_features->features[COMMON_CPUID_INDEX_1].cpuid.edx); ++ cpu_features->features[COMMON_CPUID_INDEX_1].cpuid.eax = eax; ++ *family = (eax >> 8) & 0x0f; ++ *model = (eax >> 4) & 0x0f; ++ *extended_model = (eax >> 12) & 0xf0; ++ *stepping = eax & 0x0f; ++ if (*family == 0x0f) ++ { ++ *family += (eax >> 20) & 0xff; ++ *model += *extended_model; ++ } ++ } ++ ++ if (cpu_features->basic.max_cpuid >= 7) ++ { ++ __cpuid_count (7, 0, ++ cpu_features->features[COMMON_CPUID_INDEX_7].cpuid.eax, ++ cpu_features->features[COMMON_CPUID_INDEX_7].cpuid.ebx, ++ cpu_features->features[COMMON_CPUID_INDEX_7].cpuid.ecx, ++ cpu_features->features[COMMON_CPUID_INDEX_7].cpuid.edx); ++ __cpuid_count (7, 1, ++ cpu_features->features[COMMON_CPUID_INDEX_7_ECX_1].cpuid.eax, ++ cpu_features->features[COMMON_CPUID_INDEX_7_ECX_1].cpuid.ebx, ++ cpu_features->features[COMMON_CPUID_INDEX_7_ECX_1].cpuid.ecx, ++ cpu_features->features[COMMON_CPUID_INDEX_7_ECX_1].cpuid.edx); ++ } ++ ++ if (cpu_features->basic.max_cpuid >= 0xd) ++ __cpuid_count (0xd, 1, ++ cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.eax, ++ cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.ebx, ++ cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.ecx, ++ cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.edx); ++ + } + + _Static_assert (((index_arch_Fast_Unaligned_Load +@@ -353,8 +413,6 @@ init_cpu_features (struct cpu_features *cpu_features) + unsigned int stepping = 0; + enum cpu_features_kind kind; + +- cpu_features->usable_p = cpu_features->usable; +- + #if !HAS_CPUID + if (__get_cpuid_max (0, 0) == 0) + { +@@ -377,6 +435,8 @@ init_cpu_features (struct cpu_features *cpu_features) + + get_extended_indices (cpu_features); + ++ update_usable (cpu_features); ++ + if (family == 0x06) + { + model += extended_model; +@@ -473,7 +533,7 @@ init_cpu_features (struct cpu_features *cpu_features) + with stepping >= 4) to avoid TSX on kernels that weren't + updated with the latest microcode package (which disables + broken feature by default). */ +- cpu_features->cpuid[index_cpu_RTM].reg_RTM &= ~bit_cpu_RTM; ++ CPU_FEATURE_UNSET (cpu_features, RTM); + break; + } + } +@@ -501,15 +561,15 @@ init_cpu_features (struct cpu_features *cpu_features) + + get_extended_indices (cpu_features); + +- ecx = cpu_features->cpuid[COMMON_CPUID_INDEX_1].ecx; ++ update_usable (cpu_features); + +- if (HAS_ARCH_FEATURE (AVX_Usable)) ++ ecx = cpu_features->features[COMMON_CPUID_INDEX_1].cpuid.ecx; ++ ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX)) + { + /* Since the FMA4 bit is in COMMON_CPUID_INDEX_80000001 and + FMA4 requires AVX, determine if FMA4 is usable here. */ +- if (CPU_FEATURES_CPU_P (cpu_features, FMA4)) +- cpu_features->usable[index_arch_FMA4_Usable] +- |= bit_arch_FMA4_Usable; ++ CPU_FEATURE_SET_USABLE (cpu_features, FMA4); + } + + if (family == 0x15) +@@ -540,13 +600,15 @@ init_cpu_features (struct cpu_features *cpu_features) + + get_extended_indices (cpu_features); + ++ update_usable (cpu_features); ++ + model += extended_model; + if (family == 0x6) + { + if (model == 0xf || model == 0x19) + { +- cpu_features->usable[index_arch_AVX_Usable] +- &= ~(bit_arch_AVX_Usable | bit_arch_AVX2_Usable); ++ CPU_FEATURE_UNSET (cpu_features, AVX); ++ CPU_FEATURE_UNSET (cpu_features, AVX2); + + cpu_features->preferred[index_arch_Slow_SSE4_2] + |= bit_arch_Slow_SSE4_2; +@@ -559,8 +621,8 @@ init_cpu_features (struct cpu_features *cpu_features) + { + if (model == 0x1b) + { +- cpu_features->usable[index_arch_AVX_Usable] +- &= ~(bit_arch_AVX_Usable | bit_arch_AVX2_Usable); ++ CPU_FEATURE_UNSET (cpu_features, AVX); ++ CPU_FEATURE_UNSET (cpu_features, AVX2); + + cpu_features->preferred[index_arch_Slow_SSE4_2] + |= bit_arch_Slow_SSE4_2; +@@ -570,8 +632,8 @@ init_cpu_features (struct cpu_features *cpu_features) + } + else if (model == 0x3b) + { +- cpu_features->usable[index_arch_AVX_Usable] +- &= ~(bit_arch_AVX_Usable | bit_arch_AVX2_Usable); ++ CPU_FEATURE_UNSET (cpu_features, AVX); ++ CPU_FEATURE_UNSET (cpu_features, AVX2); + + cpu_features->preferred[index_arch_AVX_Fast_Unaligned_Load] + &= ~bit_arch_AVX_Fast_Unaligned_Load; +@@ -582,6 +644,7 @@ init_cpu_features (struct cpu_features *cpu_features) + { + kind = arch_kind_other; + get_common_indices (cpu_features, NULL, NULL, NULL, NULL); ++ update_usable (cpu_features); + } + + /* Support i586 if CX8 is available. */ +@@ -628,31 +691,30 @@ no_cpuid: + { + const char *platform = NULL; + +- if (CPU_FEATURES_ARCH_P (cpu_features, AVX512F_Usable) +- && CPU_FEATURES_CPU_P (cpu_features, AVX512CD)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX512CD)) + { +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512ER)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX512ER)) + { +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512PF)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX512PF)) + platform = "xeon_phi"; + } + else + { +- if (CPU_FEATURES_CPU_P (cpu_features, AVX512BW) +- && CPU_FEATURES_CPU_P (cpu_features, AVX512DQ) +- && CPU_FEATURES_CPU_P (cpu_features, AVX512VL)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX512BW) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX512DQ) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX512VL)) + GLRO(dl_hwcap) |= HWCAP_X86_AVX512_1; + } + } + + if (platform == NULL +- && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable) +- && CPU_FEATURES_ARCH_P (cpu_features, FMA_Usable) +- && CPU_FEATURES_CPU_P (cpu_features, BMI1) +- && CPU_FEATURES_CPU_P (cpu_features, BMI2) +- && CPU_FEATURES_CPU_P (cpu_features, LZCNT) +- && CPU_FEATURES_CPU_P (cpu_features, MOVBE) +- && CPU_FEATURES_CPU_P (cpu_features, POPCNT)) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2) ++ && CPU_FEATURE_USABLE_P (cpu_features, FMA) ++ && CPU_FEATURE_USABLE_P (cpu_features, BMI1) ++ && CPU_FEATURE_USABLE_P (cpu_features, BMI2) ++ && CPU_FEATURE_USABLE_P (cpu_features, LZCNT) ++ && CPU_FEATURE_USABLE_P (cpu_features, MOVBE) ++ && CPU_FEATURE_USABLE_P (cpu_features, POPCNT)) + platform = "haswell"; + + if (platform != NULL) +@@ -660,7 +722,7 @@ no_cpuid: + } + #else + GLRO(dl_hwcap) = 0; +- if (CPU_FEATURES_CPU_P (cpu_features, SSE2)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE2)) + GLRO(dl_hwcap) |= HWCAP_X86_SSE2; + + if (CPU_FEATURES_ARCH_P (cpu_features, I686)) +@@ -695,9 +757,9 @@ no_cpuid: + GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK + */ + unsigned int cet_feature = 0; +- if (!HAS_CPU_FEATURE (IBT)) ++ if (!CPU_FEATURE_USABLE (IBT)) + cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT; +- if (!HAS_CPU_FEATURE (SHSTK)) ++ if (!CPU_FEATURE_USABLE (SHSTK)) + cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK; + + if (cet_feature) +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index 0f19c64352c4d7f1..21708c028a12dbb2 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -18,15 +18,6 @@ + #ifndef cpu_features_h + #define cpu_features_h + +-enum +-{ +- /* The integer bit array index for the first set of usable feature +- bits. */ +- USABLE_FEATURE_INDEX_1 = 0, +- /* The current maximum size of the feature integer bit array. */ +- USABLE_FEATURE_INDEX_MAX +-}; +- + enum + { + /* The integer bit array index for the first set of preferred feature +@@ -57,6 +48,12 @@ struct cpuid_registers + unsigned int edx; + }; + ++struct cpuid_features ++{ ++ struct cpuid_registers cpuid; ++ struct cpuid_registers usable; ++}; ++ + enum cpu_features_kind + { + arch_kind_unknown = 0, +@@ -78,9 +75,7 @@ struct cpu_features_basic + struct cpu_features + { + struct cpu_features_basic basic; +- unsigned int *usable_p; +- struct cpuid_registers cpuid[COMMON_CPUID_INDEX_MAX]; +- unsigned int usable[USABLE_FEATURE_INDEX_MAX]; ++ struct cpuid_features features[COMMON_CPUID_INDEX_MAX]; + unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX]; + /* The state size for XSAVEC or XSAVE. The type must be unsigned long + int so that we use +@@ -91,7 +86,7 @@ struct cpu_features + unsigned long int xsave_state_size; + /* The full state size for XSAVE when XSAVEC is disabled by + +- GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable ++ GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC + */ + unsigned int xsave_state_full_size; + /* Data cache size for use in memory and string routines, typically +@@ -114,117 +109,40 @@ extern const struct cpu_features *__get_cpu_features (void) + __attribute__ ((const)); + + /* Only used directly in cpu-features.c. */ +-# define CPU_FEATURES_CPU_P(ptr, name) \ +- ((ptr->cpuid[index_cpu_##name].reg_##name & (bit_cpu_##name)) != 0) +-# define CPU_FEATURES_ARCH_P(ptr, name) \ +- ((ptr->feature_##name[index_arch_##name] & (bit_arch_##name)) != 0) ++#define CPU_FEATURE_CHECK_P(ptr, name, check) \ ++ ((ptr->features[index_cpu_##name].check.reg_##name \ ++ & bit_cpu_##name) != 0) ++#define CPU_FEATURE_SET(ptr, name) \ ++ ptr->features[index_cpu_##name].usable.reg_##name |= bit_cpu_##name; ++#define CPU_FEATURE_UNSET(ptr, name) \ ++ ptr->features[index_cpu_##name].usable.reg_##name &= ~bit_cpu_##name; ++#define CPU_FEATURE_SET_USABLE(ptr, name) \ ++ ptr->features[index_cpu_##name].usable.reg_##name \ ++ |= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name; ++#define CPU_FEATURE_PREFERRED_P(ptr, name) \ ++ ((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0) ++#define CPU_FEATURE_CPU_P(ptr, name) \ ++ CPU_FEATURE_CHECK_P (ptr, name, cpuid) ++#define CPU_FEATURE_USABLE_P(ptr, name) \ ++ CPU_FEATURE_CHECK_P (ptr, name, usable) + + /* HAS_CPU_FEATURE evaluates to true if CPU supports the feature. */ + #define HAS_CPU_FEATURE(name) \ +- CPU_FEATURES_CPU_P (__get_cpu_features (), name) +-/* HAS_ARCH_FEATURE evaluates to true if we may use the feature at +- runtime. */ +-# define HAS_ARCH_FEATURE(name) \ +- CPU_FEATURES_ARCH_P (__get_cpu_features (), name) ++ CPU_FEATURE_CPU_P (__get_cpu_features (), name) + /* CPU_FEATURE_USABLE evaluates to true if the feature is usable. */ + #define CPU_FEATURE_USABLE(name) \ +- HAS_ARCH_FEATURE (name##_Usable) +- +-/* Architecture features. */ +- +-/* USABLE_FEATURE_INDEX_1. */ +-#define bit_arch_AVX_Usable (1u << 0) +-#define bit_arch_AVX2_Usable (1u << 1) +-#define bit_arch_AVX512F_Usable (1u << 2) +-#define bit_arch_AVX512CD_Usable (1u << 3) +-#define bit_arch_AVX512ER_Usable (1u << 4) +-#define bit_arch_AVX512PF_Usable (1u << 5) +-#define bit_arch_AVX512VL_Usable (1u << 6) +-#define bit_arch_AVX512DQ_Usable (1u << 7) +-#define bit_arch_AVX512BW_Usable (1u << 8) +-#define bit_arch_AVX512_4FMAPS_Usable (1u << 9) +-#define bit_arch_AVX512_4VNNIW_Usable (1u << 10) +-#define bit_arch_AVX512_BITALG_Usable (1u << 11) +-#define bit_arch_AVX512_IFMA_Usable (1u << 12) +-#define bit_arch_AVX512_VBMI_Usable (1u << 13) +-#define bit_arch_AVX512_VBMI2_Usable (1u << 14) +-#define bit_arch_AVX512_VNNI_Usable (1u << 15) +-#define bit_arch_AVX512_VPOPCNTDQ_Usable (1u << 16) +-#define bit_arch_FMA_Usable (1u << 17) +-#define bit_arch_FMA4_Usable (1u << 18) +-#define bit_arch_VAES_Usable (1u << 19) +-#define bit_arch_VPCLMULQDQ_Usable (1u << 20) +-#define bit_arch_XOP_Usable (1u << 21) +-#define bit_arch_XSAVEC_Usable (1u << 22) +-#define bit_arch_F16C_Usable (1u << 23) +-#define bit_arch_AVX512_VP2INTERSECT_Usable (1u << 24) +-#define bit_arch_AVX512_BF16_Usable (1u << 25) +-#define bit_arch_PKU_Usable (1u << 26) +-#define bit_arch_AMX_BF16_Usable (1u << 27) +-#define bit_arch_AMX_TILE_Usable (1u << 28) +-#define bit_arch_AMX_INT8_Usable (1u << 29) +- +-#define index_arch_AVX_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX2_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512F_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512CD_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512ER_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512PF_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512VL_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512BW_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512DQ_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512_4FMAPS_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512_4VNNIW_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512_BITALG_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512_IFMA_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512_VBMI_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512_VBMI2_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512_VNNI_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512_VPOPCNTDQ_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_FMA_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_FMA4_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_VAES_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_VPCLMULQDQ_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_XOP_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_XSAVEC_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_F16C_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512_VP2INTERSECT_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AVX512_BF16_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_PKU_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AMX_BF16_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AMX_TILE_Usable USABLE_FEATURE_INDEX_1 +-#define index_arch_AMX_INT8_Usable USABLE_FEATURE_INDEX_1 +- +-#define feature_AVX_Usable usable +-#define feature_AVX2_Usable usable +-#define feature_AVX512F_Usable usable +-#define feature_AVX512CD_Usable usable +-#define feature_AVX512ER_Usable usable +-#define feature_AVX512PF_Usable usable +-#define feature_AVX512VL_Usable usable +-#define feature_AVX512BW_Usable usable +-#define feature_AVX512DQ_Usable usable +-#define feature_AVX512_4FMAPS_Usable usable +-#define feature_AVX512_4VNNIW_Usable usable +-#define feature_AVX512_BITALG_Usable usable +-#define feature_AVX512_IFMA_Usable usable +-#define feature_AVX512_VBMI_Usable usable +-#define feature_AVX512_VBMI2_Usable usable +-#define feature_AVX512_VNNI_Usable usable +-#define feature_AVX512_VPOPCNTDQ_Usable usable +-#define feature_FMA_Usable usable +-#define feature_FMA4_Usable usable +-#define feature_VAES_Usable usable +-#define feature_VPCLMULQDQ_Usable usable +-#define feature_XOP_Usable usable +-#define feature_XSAVEC_Usable usable +-#define feature_F16C_Usable usable +-#define feature_AVX512_VP2INTERSECT_Usable usable +-#define feature_AVX512_BF16_Usable usable +-#define feature_PKU_Usable usable +-#define feature_AMX_BF16_Usable usable +-#define feature_AMX_TILE_Usable usable +-#define feature_AMX_INT8_Usable usable ++ CPU_FEATURE_USABLE_P (__get_cpu_features (), name) ++/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at ++ runtime. */ ++#define CPU_FEATURE_PREFERRED(name) \ ++ CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name) ++ ++#define CPU_FEATURES_CPU_P(ptr, name) \ ++ CPU_FEATURE_CPU_P (ptr, name) ++#define CPU_FEATURES_ARCH_P(ptr, name) \ ++ CPU_FEATURE_PREFERRED_P (ptr, name) ++#define HAS_ARCH_FEATURE(name) \ ++ CPU_FEATURE_PREFERRED (name) + + /* CPU features. */ + +@@ -247,6 +165,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_CMPXCHG16B (1u << 13) + #define bit_cpu_XTPRUPDCTRL (1u << 14) + #define bit_cpu_PDCM (1u << 15) ++#define bit_cpu_INDEX_1_ECX_16 (1u << 16) + #define bit_cpu_PCID (1u << 17) + #define bit_cpu_DCA (1u << 18) + #define bit_cpu_SSE4_1 (1u << 19) +@@ -261,6 +180,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_AVX (1u << 28) + #define bit_cpu_F16C (1u << 29) + #define bit_cpu_RDRAND (1u << 30) ++#define bit_cpu_INDEX_1_ECX_31 (1u << 31) + + /* EDX. */ + #define bit_cpu_FPU (1u << 0) +@@ -273,6 +193,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_MCE (1u << 7) + #define bit_cpu_CX8 (1u << 8) + #define bit_cpu_APIC (1u << 9) ++#define bit_cpu_INDEX_1_EDX_10 (1u << 10) + #define bit_cpu_SEP (1u << 11) + #define bit_cpu_MTRR (1u << 12) + #define bit_cpu_PGE (1u << 13) +@@ -282,6 +203,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_PSE_36 (1u << 17) + #define bit_cpu_PSN (1u << 18) + #define bit_cpu_CLFSH (1u << 19) ++#define bit_cpu_INDEX_1_EDX_20 (1u << 20) + #define bit_cpu_DS (1u << 21) + #define bit_cpu_ACPI (1u << 22) + #define bit_cpu_MMX (1u << 23) +@@ -291,6 +213,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_SS (1u << 27) + #define bit_cpu_HTT (1u << 28) + #define bit_cpu_TM (1u << 29) ++#define bit_cpu_INDEX_1_EDX_30 (1u << 30) + #define bit_cpu_PBE (1u << 31) + + /* COMMON_CPUID_INDEX_7. */ +@@ -302,12 +225,14 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_BMI1 (1u << 3) + #define bit_cpu_HLE (1u << 4) + #define bit_cpu_AVX2 (1u << 5) ++#define bit_cpu_INDEX_7_EBX_6 (1u << 6) + #define bit_cpu_SMEP (1u << 7) + #define bit_cpu_BMI2 (1u << 8) + #define bit_cpu_ERMS (1u << 9) + #define bit_cpu_INVPCID (1u << 10) + #define bit_cpu_RTM (1u << 11) + #define bit_cpu_PQM (1u << 12) ++#define bit_cpu_DEPR_FPU_CS_DS (1u << 13) + #define bit_cpu_MPX (1u << 14) + #define bit_cpu_PQE (1u << 15) + #define bit_cpu_AVX512F (1u << 16) +@@ -316,6 +241,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_ADX (1u << 19) + #define bit_cpu_SMAP (1u << 20) + #define bit_cpu_AVX512_IFMA (1u << 21) ++#define bit_cpu_INDEX_7_EBX_22 (1u << 22) + #define bit_cpu_CLFLUSHOPT (1u << 23) + #define bit_cpu_CLWB (1u << 24) + #define bit_cpu_TRACE (1u << 25) +@@ -340,9 +266,17 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_VPCLMULQDQ (1u << 10) + #define bit_cpu_AVX512_VNNI (1u << 11) + #define bit_cpu_AVX512_BITALG (1u << 12) ++#define bit_cpu_INDEX_7_ECX_13 (1u << 13) + #define bit_cpu_AVX512_VPOPCNTDQ (1u << 14) ++#define bit_cpu_INDEX_7_ECX_15 (1u << 15) ++#define bit_cpu_INDEX_7_ECX_16 (1u << 16) ++/* Note: Bits 17-21: The value of MAWAU used by the BNDLDX and BNDSTX ++ instructions in 64-bit mode. */ + #define bit_cpu_RDPID (1u << 22) ++#define bit_cpu_INDEX_7_ECX_23 (1u << 23) ++#define bit_cpu_INDEX_7_ECX_24 (1u << 24) + #define bit_cpu_CLDEMOTE (1u << 25) ++#define bit_cpu_INDEX_7_ECX_26 (1u << 26) + #define bit_cpu_MOVDIRI (1u << 27) + #define bit_cpu_MOVDIR64B (1u << 28) + #define bit_cpu_ENQCMD (1u << 29) +@@ -350,17 +284,30 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_PKS (1u << 31) + + /* EDX. */ ++#define bit_cpu_INDEX_7_EDX_0 (1u << 0) ++#define bit_cpu_INDEX_7_EDX_1 (1u << 1) + #define bit_cpu_AVX512_4VNNIW (1u << 2) + #define bit_cpu_AVX512_4FMAPS (1u << 3) + #define bit_cpu_FSRM (1u << 4) ++#define bit_cpu_INDEX_7_EDX_5 (1u << 5) ++#define bit_cpu_INDEX_7_EDX_6 (1u << 6) ++#define bit_cpu_INDEX_7_EDX_7 (1u << 7) + #define bit_cpu_AVX512_VP2INTERSECT (1u << 8) ++#define bit_cpu_INDEX_7_EDX_9 (1u << 9) + #define bit_cpu_MD_CLEAR (1u << 10) ++#define bit_cpu_INDEX_7_EDX_11 (1u << 11) ++#define bit_cpu_INDEX_7_EDX_12 (1u << 12) ++#define bit_cpu_INDEX_7_EDX_13 (1u << 13) + #define bit_cpu_SERIALIZE (1u << 14) + #define bit_cpu_HYBRID (1u << 15) + #define bit_cpu_TSXLDTRK (1u << 16) ++#define bit_cpu_INDEX_7_EDX_17 (1u << 17) + #define bit_cpu_PCONFIG (1u << 18) ++#define bit_cpu_INDEX_7_EDX_19 (1u << 19) + #define bit_cpu_IBT (1u << 20) ++#define bit_cpu_INDEX_7_EDX_21 (1u << 21) + #define bit_cpu_AMX_BF16 (1u << 22) ++#define bit_cpu_INDEX_7_EDX_23 (1u << 23) + #define bit_cpu_AMX_TILE (1u << 24) + #define bit_cpu_AMX_INT8 (1u << 25) + #define bit_cpu_IBRS_IBPB (1u << 26) +@@ -433,6 +380,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_CMPXCHG16B COMMON_CPUID_INDEX_1 + #define index_cpu_XTPRUPDCTRL COMMON_CPUID_INDEX_1 + #define index_cpu_PDCM COMMON_CPUID_INDEX_1 ++#define index_cpu_INDEX_1_ECX_16 COMMON_CPUID_INDEX_1 + #define index_cpu_PCID COMMON_CPUID_INDEX_1 + #define index_cpu_DCA COMMON_CPUID_INDEX_1 + #define index_cpu_SSE4_1 COMMON_CPUID_INDEX_1 +@@ -447,6 +395,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_AVX COMMON_CPUID_INDEX_1 + #define index_cpu_F16C COMMON_CPUID_INDEX_1 + #define index_cpu_RDRAND COMMON_CPUID_INDEX_1 ++#define index_cpu_INDEX_1_ECX_31 COMMON_CPUID_INDEX_1 + + /* ECX. */ + #define index_cpu_FPU COMMON_CPUID_INDEX_1 +@@ -459,6 +408,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_MCE COMMON_CPUID_INDEX_1 + #define index_cpu_CX8 COMMON_CPUID_INDEX_1 + #define index_cpu_APIC COMMON_CPUID_INDEX_1 ++#define index_cpu_INDEX_1_EDX_10 COMMON_CPUID_INDEX_1 + #define index_cpu_SEP COMMON_CPUID_INDEX_1 + #define index_cpu_MTRR COMMON_CPUID_INDEX_1 + #define index_cpu_PGE COMMON_CPUID_INDEX_1 +@@ -468,6 +418,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_PSE_36 COMMON_CPUID_INDEX_1 + #define index_cpu_PSN COMMON_CPUID_INDEX_1 + #define index_cpu_CLFSH COMMON_CPUID_INDEX_1 ++#define index_cpu_INDEX_1_EDX_20 COMMON_CPUID_INDEX_1 + #define index_cpu_DS COMMON_CPUID_INDEX_1 + #define index_cpu_ACPI COMMON_CPUID_INDEX_1 + #define index_cpu_MMX COMMON_CPUID_INDEX_1 +@@ -477,6 +428,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_SS COMMON_CPUID_INDEX_1 + #define index_cpu_HTT COMMON_CPUID_INDEX_1 + #define index_cpu_TM COMMON_CPUID_INDEX_1 ++#define index_cpu_INDEX_1_EDX_30 COMMON_CPUID_INDEX_1 + #define index_cpu_PBE COMMON_CPUID_INDEX_1 + + /* COMMON_CPUID_INDEX_7. */ +@@ -488,12 +440,14 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_BMI1 COMMON_CPUID_INDEX_7 + #define index_cpu_HLE COMMON_CPUID_INDEX_7 + #define index_cpu_AVX2 COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EBX_6 COMMON_CPUID_INDEX_7 + #define index_cpu_SMEP COMMON_CPUID_INDEX_7 + #define index_cpu_BMI2 COMMON_CPUID_INDEX_7 + #define index_cpu_ERMS COMMON_CPUID_INDEX_7 + #define index_cpu_INVPCID COMMON_CPUID_INDEX_7 + #define index_cpu_RTM COMMON_CPUID_INDEX_7 + #define index_cpu_PQM COMMON_CPUID_INDEX_7 ++#define index_cpu_DEPR_FPU_CS_DS COMMON_CPUID_INDEX_7 + #define index_cpu_MPX COMMON_CPUID_INDEX_7 + #define index_cpu_PQE COMMON_CPUID_INDEX_7 + #define index_cpu_AVX512F COMMON_CPUID_INDEX_7 +@@ -502,6 +456,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_ADX COMMON_CPUID_INDEX_7 + #define index_cpu_SMAP COMMON_CPUID_INDEX_7 + #define index_cpu_AVX512_IFMA COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EBX_22 COMMON_CPUID_INDEX_7 + #define index_cpu_CLFLUSHOPT COMMON_CPUID_INDEX_7 + #define index_cpu_CLWB COMMON_CPUID_INDEX_7 + #define index_cpu_TRACE COMMON_CPUID_INDEX_7 +@@ -526,9 +481,15 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_VPCLMULQDQ COMMON_CPUID_INDEX_7 + #define index_cpu_AVX512_VNNI COMMON_CPUID_INDEX_7 + #define index_cpu_AVX512_BITALG COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_ECX_13 COMMON_CPUID_INDEX_7 + #define index_cpu_AVX512_VPOPCNTDQ COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_ECX_15 COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_ECX_16 COMMON_CPUID_INDEX_7 + #define index_cpu_RDPID COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_ECX_23 COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_ECX_24 COMMON_CPUID_INDEX_7 + #define index_cpu_CLDEMOTE COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_ECX_26 COMMON_CPUID_INDEX_7 + #define index_cpu_MOVDIRI COMMON_CPUID_INDEX_7 + #define index_cpu_MOVDIR64B COMMON_CPUID_INDEX_7 + #define index_cpu_ENQCMD COMMON_CPUID_INDEX_7 +@@ -536,17 +497,30 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_PKS COMMON_CPUID_INDEX_7 + + /* EDX. */ ++#define index_cpu_INDEX_7_EDX_0 COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EDX_1 COMMON_CPUID_INDEX_7 + #define index_cpu_AVX512_4VNNIW COMMON_CPUID_INDEX_7 + #define index_cpu_AVX512_4FMAPS COMMON_CPUID_INDEX_7 + #define index_cpu_FSRM COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EDX_5 COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EDX_6 COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EDX_7 COMMON_CPUID_INDEX_7 + #define index_cpu_AVX512_VP2INTERSECT COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EDX_9 COMMON_CPUID_INDEX_7 + #define index_cpu_MD_CLEAR COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EDX_11 COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EDX_12 COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EDX_13 COMMON_CPUID_INDEX_7 + #define index_cpu_SERIALIZE COMMON_CPUID_INDEX_7 + #define index_cpu_HYBRID COMMON_CPUID_INDEX_7 + #define index_cpu_TSXLDTRK COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EDX_17 COMMON_CPUID_INDEX_7 + #define index_cpu_PCONFIG COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EDX_19 COMMON_CPUID_INDEX_7 + #define index_cpu_IBT COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EDX_21 COMMON_CPUID_INDEX_7 + #define index_cpu_AMX_BF16 COMMON_CPUID_INDEX_7 ++#define index_cpu_INDEX_7_EDX_23 COMMON_CPUID_INDEX_7 + #define index_cpu_AMX_TILE COMMON_CPUID_INDEX_7 + #define index_cpu_AMX_INT8 COMMON_CPUID_INDEX_7 + #define index_cpu_IBRS_IBPB COMMON_CPUID_INDEX_7 +@@ -619,6 +593,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_CMPXCHG16B ecx + #define reg_XTPRUPDCTRL ecx + #define reg_PDCM ecx ++#define reg_INDEX_1_ECX_16 ecx + #define reg_PCID ecx + #define reg_DCA ecx + #define reg_SSE4_1 ecx +@@ -633,6 +608,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_AVX ecx + #define reg_F16C ecx + #define reg_RDRAND ecx ++#define reg_INDEX_1_ECX_31 ecx + + /* EDX. */ + #define reg_FPU edx +@@ -645,6 +621,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_MCE edx + #define reg_CX8 edx + #define reg_APIC edx ++#define reg_INDEX_1_EDX_10 edx + #define reg_SEP edx + #define reg_MTRR edx + #define reg_PGE edx +@@ -654,6 +631,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_PSE_36 edx + #define reg_PSN edx + #define reg_CLFSH edx ++#define reg_INDEX_1_EDX_20 edx + #define reg_DS edx + #define reg_ACPI edx + #define reg_MMX edx +@@ -663,6 +641,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_SS edx + #define reg_HTT edx + #define reg_TM edx ++#define reg_INDEX_1_EDX_30 edx + #define reg_PBE edx + + /* COMMON_CPUID_INDEX_7. */ +@@ -675,11 +654,13 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_HLE ebx + #define reg_BMI2 ebx + #define reg_AVX2 ebx ++#define reg_INDEX_7_EBX_6 ebx + #define reg_SMEP ebx + #define reg_ERMS ebx + #define reg_INVPCID ebx + #define reg_RTM ebx + #define reg_PQM ebx ++#define reg_DEPR_FPU_CS_DS ebx + #define reg_MPX ebx + #define reg_PQE ebx + #define reg_AVX512F ebx +@@ -688,6 +669,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_ADX ebx + #define reg_SMAP ebx + #define reg_AVX512_IFMA ebx ++#define reg_INDEX_7_EBX_22 ebx + #define reg_CLFLUSHOPT ebx + #define reg_CLWB ebx + #define reg_TRACE ebx +@@ -712,9 +694,15 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_VPCLMULQDQ ecx + #define reg_AVX512_VNNI ecx + #define reg_AVX512_BITALG ecx ++#define reg_INDEX_7_ECX_13 ecx + #define reg_AVX512_VPOPCNTDQ ecx ++#define reg_INDEX_7_ECX_15 ecx ++#define reg_INDEX_7_ECX_16 ecx + #define reg_RDPID ecx ++#define reg_INDEX_7_ECX_23 ecx ++#define reg_INDEX_7_ECX_24 ecx + #define reg_CLDEMOTE ecx ++#define reg_INDEX_7_ECX_26 ecx + #define reg_MOVDIRI ecx + #define reg_MOVDIR64B ecx + #define reg_ENQCMD ecx +@@ -722,17 +710,30 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_PKS ecx + + /* EDX. */ ++#define reg_INDEX_7_EDX_0 edx ++#define reg_INDEX_7_EDX_1 edx + #define reg_AVX512_4VNNIW edx + #define reg_AVX512_4FMAPS edx + #define reg_FSRM edx ++#define reg_INDEX_7_EDX_5 edx ++#define reg_INDEX_7_EDX_6 edx ++#define reg_INDEX_7_EDX_7 edx + #define reg_AVX512_VP2INTERSECT edx ++#define reg_INDEX_7_EDX_9 edx + #define reg_MD_CLEAR edx ++#define reg_INDEX_7_EDX_11 edx ++#define reg_INDEX_7_EDX_12 edx ++#define reg_INDEX_7_EDX_13 edx + #define reg_SERIALIZE edx + #define reg_HYBRID edx + #define reg_TSXLDTRK edx ++#define reg_INDEX_7_EDX_17 edx + #define reg_PCONFIG edx ++#define reg_INDEX_7_EDX_19 edx + #define reg_IBT edx ++#define reg_INDEX_7_EDX_21 edx + #define reg_AMX_BF16 edx ++#define reg_INDEX_7_EDX_23 edx + #define reg_AMX_TILE edx + #define reg_AMX_INT8 edx + #define reg_IBRS_IBPB edx +@@ -821,23 +822,6 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_arch_MathVec_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1 + #define index_arch_Prefer_FSRM PREFERRED_FEATURE_INDEX_1 + +-#define feature_Fast_Rep_String preferred +-#define feature_Fast_Copy_Backward preferred +-#define feature_Slow_BSF preferred +-#define feature_Fast_Unaligned_Load preferred +-#define feature_Prefer_PMINUB_for_stringop preferred +-#define feature_Fast_Unaligned_Copy preferred +-#define feature_I586 preferred +-#define feature_I686 preferred +-#define feature_Slow_SSE4_2 preferred +-#define feature_AVX_Fast_Unaligned_Load preferred +-#define feature_Prefer_MAP_32BIT_EXEC preferred +-#define feature_Prefer_No_VZEROUPPER preferred +-#define feature_Prefer_ERMS preferred +-#define feature_Prefer_No_AVX512 preferred +-#define feature_MathVec_Prefer_No_AVX512 preferred +-#define feature_Prefer_FSRM preferred +- + /* XCR0 Feature flags. */ + #define bit_XMM_state (1u << 1) + #define bit_YMM_state (1u << 2) +@@ -851,8 +835,6 @@ extern const struct cpu_features *__get_cpu_features (void) + /* Unused for x86. */ + # define INIT_ARCH() + # define __get_cpu_features() (&GLRO(dl_x86_cpu_features)) +-# define x86_get_cpuid_registers(i) \ +- (&(GLRO(dl_x86_cpu_features).cpuid[i])) + # endif + + #ifdef __x86_64__ +diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c +index 012ae48933055eaa..0728023007a0f423 100644 +--- a/sysdeps/x86/cpu-tunables.c ++++ b/sysdeps/x86/cpu-tunables.c +@@ -43,66 +43,45 @@ extern __typeof (memcmp) DEFAULT_MEMCMP; + _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \ + if (!DEFAULT_MEMCMP (f, #name, len)) \ + { \ +- cpu_features->cpuid[index_cpu_##name].reg_##name \ +- &= ~bit_cpu_##name; \ ++ CPU_FEATURE_UNSET (cpu_features, name) \ + break; \ + } + +-/* Disable an ARCH feature NAME. We don't enable an ARCH feature which +- isn't available. */ +-# define CHECK_GLIBC_IFUNC_ARCH_OFF(f, cpu_features, name, len) \ ++/* Disable a preferred feature NAME. We don't enable a preferred feature ++ which isn't available. */ ++# define CHECK_GLIBC_IFUNC_PREFERRED_OFF(f, cpu_features, name, len) \ + _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \ + if (!DEFAULT_MEMCMP (f, #name, len)) \ + { \ +- cpu_features->feature_##name[index_arch_##name] \ ++ cpu_features->preferred[index_arch_##name] \ + &= ~bit_arch_##name; \ + break; \ + } + +-/* Enable/disable an ARCH feature NAME. */ +-# define CHECK_GLIBC_IFUNC_ARCH_BOTH(f, cpu_features, name, disable, \ +- len) \ ++/* Enable/disable a preferred feature NAME. */ ++# define CHECK_GLIBC_IFUNC_PREFERRED_BOTH(f, cpu_features, name, \ ++ disable, len) \ + _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \ + if (!DEFAULT_MEMCMP (f, #name, len)) \ + { \ + if (disable) \ +- cpu_features->feature_##name[index_arch_##name] \ +- &= ~bit_arch_##name; \ ++ cpu_features->preferred[index_arch_##name] &= ~bit_arch_##name; \ + else \ +- cpu_features->feature_##name[index_arch_##name] \ +- |= bit_arch_##name; \ ++ cpu_features->preferred[index_arch_##name] |= bit_arch_##name; \ + break; \ + } + +-/* Enable/disable an ARCH feature NAME. Enable an ARCH feature only +- if the ARCH feature NEED is also enabled. */ +-# define CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH(f, cpu_features, name, \ ++/* Enable/disable a preferred feature NAME. Enable a preferred feature ++ only if the feature NEED is usable. */ ++# define CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH(f, cpu_features, name, \ + need, disable, len) \ + _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \ + if (!DEFAULT_MEMCMP (f, #name, len)) \ + { \ + if (disable) \ +- cpu_features->feature_##name[index_arch_##name] \ +- &= ~bit_arch_##name; \ +- else if (CPU_FEATURES_ARCH_P (cpu_features, need)) \ +- cpu_features->feature_##name[index_arch_##name] \ +- |= bit_arch_##name; \ +- break; \ +- } +- +-/* Enable/disable an ARCH feature NAME. Enable an ARCH feature only +- if the CPU feature NEED is also enabled. */ +-# define CHECK_GLIBC_IFUNC_ARCH_NEED_CPU_BOTH(f, cpu_features, name, \ +- need, disable, len) \ +- _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \ +- if (!DEFAULT_MEMCMP (f, #name, len)) \ +- { \ +- if (disable) \ +- cpu_features->feature_##name[index_arch_##name] \ +- &= ~bit_arch_##name; \ +- else if (CPU_FEATURES_CPU_P (cpu_features, need)) \ +- cpu_features->feature_##name[index_arch_##name] \ +- |= bit_arch_##name; \ ++ cpu_features->preferred[index_arch_##name] &= ~bit_arch_##name; \ ++ else if (CPU_FEATURE_USABLE_P (cpu_features, need)) \ ++ cpu_features->preferred[index_arch_##name] |= bit_arch_##name; \ + break; \ + } + +@@ -178,8 +157,8 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp) + CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, ERMS, 4); + CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, FMA4, 4); + CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SSE2, 4); +- CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, I586, 4); +- CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, I686, 4); ++ CHECK_GLIBC_IFUNC_PREFERRED_OFF (n, cpu_features, I586, 4); ++ CHECK_GLIBC_IFUNC_PREFERRED_OFF (n, cpu_features, I686, 4); + } + break; + case 5: +@@ -197,6 +176,13 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp) + CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, POPCNT, 6); + CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SSE4_1, 6); + CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, SSE4_2, 6); ++ if (!DEFAULT_MEMCMP (n, "XSAVEC", 6)) ++ { ++ /* Update xsave_state_size to XSAVE state size. */ ++ cpu_features->xsave_state_size ++ = cpu_features->xsave_state_full_size; ++ CPU_FEATURE_UNSET (cpu_features, XSAVEC); ++ } + } + break; + case 7: +@@ -216,115 +202,85 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp) + CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, AVX512PF, 8); + CHECK_GLIBC_IFUNC_CPU_OFF (n, cpu_features, AVX512VL, 8); + } +- CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features, Slow_BSF, +- disable, 8); +- break; +- case 10: +- if (disable) +- { +- CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, AVX_Usable, +- 10); +- CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, FMA_Usable, +- 10); +- } ++ CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features, Slow_BSF, ++ disable, 8); + break; + case 11: +- if (disable) + { +- CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, AVX2_Usable, +- 11); +- CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, FMA4_Usable, +- 11); +- } +- CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features, Prefer_ERMS, +- disable, 11); +- CHECK_GLIBC_IFUNC_ARCH_NEED_CPU_BOTH (n, cpu_features, +- Slow_SSE4_2, SSE4_2, ++ CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features, ++ Prefer_ERMS, + disable, 11); +- CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features, Prefer_FSRM, +- disable, 11); +- break; +- case 13: +- if (disable) +- { +- /* Update xsave_state_size to XSAVE state size. */ +- cpu_features->xsave_state_size +- = cpu_features->xsave_state_full_size; +- CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, +- XSAVEC_Usable, 13); +- } +- break; +- case 14: +- if (disable) +- { +- CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, +- AVX512F_Usable, 14); ++ CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features, ++ Prefer_FSRM, ++ disable, 11); ++ CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH (n, cpu_features, ++ Slow_SSE4_2, ++ SSE4_2, ++ disable, 11); + } + break; + case 15: +- if (disable) + { +- CHECK_GLIBC_IFUNC_ARCH_OFF (n, cpu_features, +- AVX512DQ_Usable, 15); ++ CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features, ++ Fast_Rep_String, ++ disable, 15); + } +- CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features, Fast_Rep_String, +- disable, 15); + break; + case 16: + { +- CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH +- (n, cpu_features, Prefer_No_AVX512, AVX512F_Usable, ++ CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH ++ (n, cpu_features, Prefer_No_AVX512, AVX512F, + disable, 16); + } + break; + case 18: + { +- CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features, +- Fast_Copy_Backward, disable, +- 18); ++ CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features, ++ Fast_Copy_Backward, ++ disable, 18); + } + break; + case 19: + { +- CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features, +- Fast_Unaligned_Load, disable, +- 19); +- CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features, +- Fast_Unaligned_Copy, disable, +- 19); ++ CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features, ++ Fast_Unaligned_Load, ++ disable, 19); ++ CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features, ++ Fast_Unaligned_Copy, ++ disable, 19); + } + break; + case 20: + { +- CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH +- (n, cpu_features, Prefer_No_VZEROUPPER, AVX_Usable, +- disable, 20); ++ CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH ++ (n, cpu_features, Prefer_No_VZEROUPPER, AVX, disable, ++ 20); + } + break; + case 21: + { +- CHECK_GLIBC_IFUNC_ARCH_BOTH (n, cpu_features, +- Prefer_MAP_32BIT_EXEC, disable, +- 21); ++ CHECK_GLIBC_IFUNC_PREFERRED_BOTH (n, cpu_features, ++ Prefer_MAP_32BIT_EXEC, ++ disable, 21); + } + break; + case 23: + { +- CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH +- (n, cpu_features, AVX_Fast_Unaligned_Load, AVX_Usable, ++ CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH ++ (n, cpu_features, AVX_Fast_Unaligned_Load, AVX, + disable, 23); + } + break; + case 24: + { +- CHECK_GLIBC_IFUNC_ARCH_NEED_ARCH_BOTH +- (n, cpu_features, MathVec_Prefer_No_AVX512, +- AVX512F_Usable, disable, 24); ++ CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH ++ (n, cpu_features, MathVec_Prefer_No_AVX512, AVX512F, ++ disable, 24); + } + break; + case 26: + { +- CHECK_GLIBC_IFUNC_ARCH_NEED_CPU_BOTH ++ CHECK_GLIBC_IFUNC_PREFERRED_NEED_BOTH + (n, cpu_features, Prefer_PMINUB_for_stringop, SSE2, + disable, 26); + } +diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c +index d481bddc27e5d7cc..11ff0618fae7230f 100644 +--- a/sysdeps/x86/dl-cet.c ++++ b/sysdeps/x86/dl-cet.c +@@ -74,10 +74,10 @@ dl_cet_check (struct link_map *m, const char *program) + + GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK + */ +- enable_ibt &= (HAS_CPU_FEATURE (IBT) ++ enable_ibt &= (CPU_FEATURE_USABLE (IBT) + && (enable_ibt_type == cet_always_on + || (m->l_cet & lc_ibt) != 0)); +- enable_shstk &= (HAS_CPU_FEATURE (SHSTK) ++ enable_shstk &= (CPU_FEATURE_USABLE (SHSTK) + && (enable_shstk_type == cet_always_on + || (m->l_cet & lc_shstk) != 0)); + } +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index c56f309ba0736c0d..85ec9d5a091e2c88 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -137,6 +137,7 @@ do_test (void) + CHECK_CPU_FEATURE (INVPCID); + CHECK_CPU_FEATURE (RTM); + CHECK_CPU_FEATURE (PQM); ++ CHECK_CPU_FEATURE (DEPR_FPU_CS_DS); + CHECK_CPU_FEATURE (MPX); + CHECK_CPU_FEATURE (PQE); + CHECK_CPU_FEATURE (AVX512F); +@@ -218,35 +219,156 @@ do_test (void) + CHECK_CPU_FEATURE (AVX512_BF16); + + printf ("Usable CPU features:\n"); ++ CHECK_CPU_FEATURE_USABLE (SSE3); ++ CHECK_CPU_FEATURE_USABLE (PCLMULQDQ); ++ CHECK_CPU_FEATURE_USABLE (DTES64); ++ CHECK_CPU_FEATURE_USABLE (MONITOR); ++ CHECK_CPU_FEATURE_USABLE (DS_CPL); ++ CHECK_CPU_FEATURE_USABLE (VMX); ++ CHECK_CPU_FEATURE_USABLE (SMX); ++ CHECK_CPU_FEATURE_USABLE (EST); ++ CHECK_CPU_FEATURE_USABLE (TM2); ++ CHECK_CPU_FEATURE_USABLE (SSSE3); ++ CHECK_CPU_FEATURE_USABLE (CNXT_ID); ++ CHECK_CPU_FEATURE_USABLE (SDBG); + CHECK_CPU_FEATURE_USABLE (FMA); ++ CHECK_CPU_FEATURE_USABLE (CMPXCHG16B); ++ CHECK_CPU_FEATURE_USABLE (XTPRUPDCTRL); ++ CHECK_CPU_FEATURE_USABLE (PDCM); ++ CHECK_CPU_FEATURE_USABLE (PCID); ++ CHECK_CPU_FEATURE_USABLE (DCA); ++ CHECK_CPU_FEATURE_USABLE (SSE4_1); ++ CHECK_CPU_FEATURE_USABLE (SSE4_2); ++ CHECK_CPU_FEATURE_USABLE (X2APIC); ++ CHECK_CPU_FEATURE_USABLE (MOVBE); ++ CHECK_CPU_FEATURE_USABLE (POPCNT); ++ CHECK_CPU_FEATURE_USABLE (TSC_DEADLINE); ++ CHECK_CPU_FEATURE_USABLE (AES); ++ CHECK_CPU_FEATURE_USABLE (XSAVE); ++ CHECK_CPU_FEATURE_USABLE (OSXSAVE); + CHECK_CPU_FEATURE_USABLE (AVX); + CHECK_CPU_FEATURE_USABLE (F16C); ++ CHECK_CPU_FEATURE_USABLE (RDRAND); ++ CHECK_CPU_FEATURE_USABLE (FPU); ++ CHECK_CPU_FEATURE_USABLE (VME); ++ CHECK_CPU_FEATURE_USABLE (DE); ++ CHECK_CPU_FEATURE_USABLE (PSE); ++ CHECK_CPU_FEATURE_USABLE (TSC); ++ CHECK_CPU_FEATURE_USABLE (MSR); ++ CHECK_CPU_FEATURE_USABLE (PAE); ++ CHECK_CPU_FEATURE_USABLE (MCE); ++ CHECK_CPU_FEATURE_USABLE (CX8); ++ CHECK_CPU_FEATURE_USABLE (APIC); ++ CHECK_CPU_FEATURE_USABLE (SEP); ++ CHECK_CPU_FEATURE_USABLE (MTRR); ++ CHECK_CPU_FEATURE_USABLE (PGE); ++ CHECK_CPU_FEATURE_USABLE (MCA); ++ CHECK_CPU_FEATURE_USABLE (CMOV); ++ CHECK_CPU_FEATURE_USABLE (PAT); ++ CHECK_CPU_FEATURE_USABLE (PSE_36); ++ CHECK_CPU_FEATURE_USABLE (PSN); ++ CHECK_CPU_FEATURE_USABLE (CLFSH); ++ CHECK_CPU_FEATURE_USABLE (DS); ++ CHECK_CPU_FEATURE_USABLE (ACPI); ++ CHECK_CPU_FEATURE_USABLE (MMX); ++ CHECK_CPU_FEATURE_USABLE (FXSR); ++ CHECK_CPU_FEATURE_USABLE (SSE); ++ CHECK_CPU_FEATURE_USABLE (SSE2); ++ CHECK_CPU_FEATURE_USABLE (SS); ++ CHECK_CPU_FEATURE_USABLE (HTT); ++ CHECK_CPU_FEATURE_USABLE (TM); ++ CHECK_CPU_FEATURE_USABLE (PBE); ++ CHECK_CPU_FEATURE_USABLE (FSGSBASE); ++ CHECK_CPU_FEATURE_USABLE (TSC_ADJUST); ++ CHECK_CPU_FEATURE_USABLE (SGX); ++ CHECK_CPU_FEATURE_USABLE (BMI1); ++ CHECK_CPU_FEATURE_USABLE (HLE); + CHECK_CPU_FEATURE_USABLE (AVX2); ++ CHECK_CPU_FEATURE_USABLE (SMEP); ++ CHECK_CPU_FEATURE_USABLE (BMI2); ++ CHECK_CPU_FEATURE_USABLE (ERMS); ++ CHECK_CPU_FEATURE_USABLE (INVPCID); ++ CHECK_CPU_FEATURE_USABLE (RTM); ++ CHECK_CPU_FEATURE_USABLE (PQM); ++ CHECK_CPU_FEATURE_USABLE (DEPR_FPU_CS_DS); ++ CHECK_CPU_FEATURE_USABLE (MPX); ++ CHECK_CPU_FEATURE_USABLE (PQE); + CHECK_CPU_FEATURE_USABLE (AVX512F); + CHECK_CPU_FEATURE_USABLE (AVX512DQ); ++ CHECK_CPU_FEATURE_USABLE (RDSEED); ++ CHECK_CPU_FEATURE_USABLE (ADX); ++ CHECK_CPU_FEATURE_USABLE (SMAP); + CHECK_CPU_FEATURE_USABLE (AVX512_IFMA); ++ CHECK_CPU_FEATURE_USABLE (CLFLUSHOPT); ++ CHECK_CPU_FEATURE_USABLE (CLWB); ++ CHECK_CPU_FEATURE_USABLE (TRACE); + CHECK_CPU_FEATURE_USABLE (AVX512PF); + CHECK_CPU_FEATURE_USABLE (AVX512ER); + CHECK_CPU_FEATURE_USABLE (AVX512CD); ++ CHECK_CPU_FEATURE_USABLE (SHA); + CHECK_CPU_FEATURE_USABLE (AVX512BW); + CHECK_CPU_FEATURE_USABLE (AVX512VL); ++ CHECK_CPU_FEATURE_USABLE (PREFETCHWT1); + CHECK_CPU_FEATURE_USABLE (AVX512_VBMI); ++ CHECK_CPU_FEATURE_USABLE (UMIP); + CHECK_CPU_FEATURE_USABLE (PKU); ++ CHECK_CPU_FEATURE_USABLE (OSPKE); ++ CHECK_CPU_FEATURE_USABLE (WAITPKG); + CHECK_CPU_FEATURE_USABLE (AVX512_VBMI2); ++ CHECK_CPU_FEATURE_USABLE (SHSTK); ++ CHECK_CPU_FEATURE_USABLE (GFNI); + CHECK_CPU_FEATURE_USABLE (VAES); + CHECK_CPU_FEATURE_USABLE (VPCLMULQDQ); + CHECK_CPU_FEATURE_USABLE (AVX512_VNNI); + CHECK_CPU_FEATURE_USABLE (AVX512_BITALG); + CHECK_CPU_FEATURE_USABLE (AVX512_VPOPCNTDQ); ++ CHECK_CPU_FEATURE_USABLE (RDPID); ++ CHECK_CPU_FEATURE_USABLE (CLDEMOTE); ++ CHECK_CPU_FEATURE_USABLE (MOVDIRI); ++ CHECK_CPU_FEATURE_USABLE (MOVDIR64B); ++ CHECK_CPU_FEATURE_USABLE (ENQCMD); ++ CHECK_CPU_FEATURE_USABLE (SGX_LC); ++ CHECK_CPU_FEATURE_USABLE (PKS); + CHECK_CPU_FEATURE_USABLE (AVX512_4VNNIW); + CHECK_CPU_FEATURE_USABLE (AVX512_4FMAPS); ++ CHECK_CPU_FEATURE_USABLE (FSRM); + CHECK_CPU_FEATURE_USABLE (AVX512_VP2INTERSECT); ++ CHECK_CPU_FEATURE_USABLE (MD_CLEAR); ++ CHECK_CPU_FEATURE_USABLE (SERIALIZE); ++ CHECK_CPU_FEATURE_USABLE (HYBRID); ++ CHECK_CPU_FEATURE_USABLE (TSXLDTRK); ++ CHECK_CPU_FEATURE_USABLE (PCONFIG); ++ CHECK_CPU_FEATURE_USABLE (IBT); + CHECK_CPU_FEATURE_USABLE (AMX_BF16); + CHECK_CPU_FEATURE_USABLE (AMX_TILE); + CHECK_CPU_FEATURE_USABLE (AMX_INT8); ++ CHECK_CPU_FEATURE_USABLE (IBRS_IBPB); ++ CHECK_CPU_FEATURE_USABLE (STIBP); ++ CHECK_CPU_FEATURE_USABLE (L1D_FLUSH); ++ CHECK_CPU_FEATURE_USABLE (ARCH_CAPABILITIES); ++ CHECK_CPU_FEATURE_USABLE (CORE_CAPABILITIES); ++ CHECK_CPU_FEATURE_USABLE (SSBD); ++ CHECK_CPU_FEATURE_USABLE (LAHF64_SAHF64); ++ CHECK_CPU_FEATURE_USABLE (SVM); ++ CHECK_CPU_FEATURE_USABLE (LZCNT); ++ CHECK_CPU_FEATURE_USABLE (SSE4A); ++ CHECK_CPU_FEATURE_USABLE (PREFETCHW); + CHECK_CPU_FEATURE_USABLE (XOP); ++ CHECK_CPU_FEATURE_USABLE (LWP); + CHECK_CPU_FEATURE_USABLE (FMA4); ++ CHECK_CPU_FEATURE_USABLE (TBM); ++ CHECK_CPU_FEATURE_USABLE (SYSCALL_SYSRET); ++ CHECK_CPU_FEATURE_USABLE (NX); ++ CHECK_CPU_FEATURE_USABLE (PAGE1GB); ++ CHECK_CPU_FEATURE_USABLE (RDTSCP); ++ CHECK_CPU_FEATURE_USABLE (LM); ++ CHECK_CPU_FEATURE_USABLE (XSAVEOPT); + CHECK_CPU_FEATURE_USABLE (XSAVEC); ++ CHECK_CPU_FEATURE_USABLE (XGETBV_ECX_1); ++ CHECK_CPU_FEATURE_USABLE (XSAVES); ++ CHECK_CPU_FEATURE_USABLE (XFD); ++ CHECK_CPU_FEATURE_USABLE (INVARIANT_TSC); ++ CHECK_CPU_FEATURE_USABLE (WBNOINVD); + CHECK_CPU_FEATURE_USABLE (AVX512_BF16); + + return 0; +diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile +index e3bb45d78811d70f..42b97c5cc73892cc 100644 +--- a/sysdeps/x86_64/Makefile ++++ b/sysdeps/x86_64/Makefile +@@ -57,7 +57,7 @@ modules-names += x86_64/tst-x86_64mod-1 + LDFLAGS-tst-x86_64mod-1.so = -Wl,-soname,tst-x86_64mod-1.so + ifneq (no,$(have-tunables)) + # Test the state size for XSAVE when XSAVEC is disabled. +-tst-x86_64-1-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC_Usable ++tst-x86_64-1-ENV = GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC + endif + + $(objpfx)tst-x86_64-1: $(objpfx)x86_64/tst-x86_64mod-1.so +@@ -71,10 +71,10 @@ CFLAGS-tst-platformmod-2.c = -mno-avx + LDFLAGS-tst-platformmod-2.so = -Wl,-soname,tst-platformmod-2.so + $(objpfx)tst-platform-1: $(objpfx)tst-platformmod-1.so + $(objpfx)tst-platform-1.out: $(objpfx)x86_64/tst-platformmod-2.so +-# Turn off AVX512F_Usable and AVX2_Usable so that GLRO(dl_platform) is ++# Turn off AVX512F and AVX2 so that GLRO(dl_platform) is + # always set to x86_64. + tst-platform-1-ENV = LD_PRELOAD=$(objpfx)\$$PLATFORM/tst-platformmod-2.so \ +- GLIBC_TUNABLES=glibc.cpu.hwcaps=-AVX512F_Usable,-AVX2_Usable ++ GLIBC_TUNABLES=glibc.cpu.hwcaps=-AVX512F,-AVX2 + endif + + tests += tst-audit3 tst-audit4 tst-audit5 tst-audit6 tst-audit7 \ +diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h +index 23afb3c05dbe17d6..d58298d787ef352c 100644 +--- a/sysdeps/x86_64/dl-machine.h ++++ b/sysdeps/x86_64/dl-machine.h +@@ -99,9 +99,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + end in this function. */ + if (__glibc_unlikely (profile)) + { +- if (HAS_ARCH_FEATURE (AVX512F_Usable)) ++ if (CPU_FEATURE_USABLE (AVX512F)) + *(ElfW(Addr) *) (got + 2) = (ElfW(Addr)) &_dl_runtime_profile_avx512; +- else if (HAS_ARCH_FEATURE (AVX_Usable)) ++ else if (CPU_FEATURE_USABLE (AVX)) + *(ElfW(Addr) *) (got + 2) = (ElfW(Addr)) &_dl_runtime_profile_avx; + else + *(ElfW(Addr) *) (got + 2) = (ElfW(Addr)) &_dl_runtime_profile_sse; +@@ -119,7 +119,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + the resolved address. */ + if (GLRO(dl_x86_cpu_features).xsave_state_size != 0) + *(ElfW(Addr) *) (got + 2) +- = (HAS_ARCH_FEATURE (XSAVEC_Usable) ++ = (CPU_FEATURE_USABLE (XSAVEC) + ? (ElfW(Addr)) &_dl_runtime_resolve_xsavec + : (ElfW(Addr)) &_dl_runtime_resolve_xsave); + else +diff --git a/sysdeps/x86_64/fpu/math-tests-arch.h b/sysdeps/x86_64/fpu/math-tests-arch.h +index a5df133292ce39b0..61955d70863321fd 100644 +--- a/sysdeps/x86_64/fpu/math-tests-arch.h ++++ b/sysdeps/x86_64/fpu/math-tests-arch.h +@@ -24,7 +24,7 @@ + # define CHECK_ARCH_EXT \ + do \ + { \ +- if (!HAS_ARCH_FEATURE (AVX_Usable)) return; \ ++ if (!CPU_FEATURE_USABLE (AVX)) return; \ + } \ + while (0) + +@@ -34,7 +34,7 @@ + # define CHECK_ARCH_EXT \ + do \ + { \ +- if (!HAS_ARCH_FEATURE (AVX2_Usable)) return; \ ++ if (!CPU_FEATURE_USABLE (AVX2)) return; \ + } \ + while (0) + +@@ -44,7 +44,7 @@ + # define CHECK_ARCH_EXT \ + do \ + { \ +- if (!HAS_ARCH_FEATURE (AVX512F_Usable)) return; \ ++ if (!CPU_FEATURE_USABLE (AVX512F)) return; \ + } \ + while (0) + +diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-avx-fma4.h b/sysdeps/x86_64/fpu/multiarch/ifunc-avx-fma4.h +index a5f9375afc683663..399ed90362f476b7 100644 +--- a/sysdeps/x86_64/fpu/multiarch/ifunc-avx-fma4.h ++++ b/sysdeps/x86_64/fpu/multiarch/ifunc-avx-fma4.h +@@ -29,14 +29,14 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_ARCH_P (cpu_features, FMA_Usable) +- && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, FMA) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2)) + return OPTIMIZE (fma); + +- if (CPU_FEATURES_ARCH_P (cpu_features, FMA4_Usable)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, FMA4)) + return OPTIMIZE (fma4); + +- if (CPU_FEATURES_ARCH_P (cpu_features, AVX_Usable)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX)) + return OPTIMIZE (avx); + + return OPTIMIZE (sse2); +diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-fma.h b/sysdeps/x86_64/fpu/multiarch/ifunc-fma.h +index 63a8cd221fb34e28..c6717d65dfd160e7 100644 +--- a/sysdeps/x86_64/fpu/multiarch/ifunc-fma.h ++++ b/sysdeps/x86_64/fpu/multiarch/ifunc-fma.h +@@ -26,8 +26,8 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_ARCH_P (cpu_features, FMA_Usable) +- && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, FMA) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2)) + return OPTIMIZE (fma); + + return OPTIMIZE (sse2); +diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h b/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h +index a2526a2ee0e55e18..76c677198dac5cb0 100644 +--- a/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h ++++ b/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h +@@ -28,11 +28,11 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_ARCH_P (cpu_features, FMA_Usable) +- && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, FMA) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2)) + return OPTIMIZE (fma); + +- if (CPU_FEATURES_ARCH_P (cpu_features, FMA4_Usable)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, FMA)) + return OPTIMIZE (fma4); + + return OPTIMIZE (sse2); +diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-mathvec-avx2.h b/sysdeps/x86_64/fpu/multiarch/ifunc-mathvec-avx2.h +index bd2d32e4186c11e3..d84d82a3a22f0e86 100644 +--- a/sysdeps/x86_64/fpu/multiarch/ifunc-mathvec-avx2.h ++++ b/sysdeps/x86_64/fpu/multiarch/ifunc-mathvec-avx2.h +@@ -31,8 +31,8 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_ARCH_P (cpu_features, FMA_Usable) +- && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, FMA) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2)) + return OPTIMIZE (avx2); + + return OPTIMIZE (sse_wrapper); +diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-mathvec-avx512.h b/sysdeps/x86_64/fpu/multiarch/ifunc-mathvec-avx512.h +index 174e462cfbcfa0a5..a2d9972e5a02b87c 100644 +--- a/sysdeps/x86_64/fpu/multiarch/ifunc-mathvec-avx512.h ++++ b/sysdeps/x86_64/fpu/multiarch/ifunc-mathvec-avx512.h +@@ -34,10 +34,10 @@ IFUNC_SELECTOR (void) + + if (!CPU_FEATURES_ARCH_P (cpu_features, MathVec_Prefer_No_AVX512)) + { +- if (CPU_FEATURES_ARCH_P (cpu_features, AVX512DQ_Usable)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX512DQ)) + return OPTIMIZE (skx); + +- if (CPU_FEATURES_ARCH_P (cpu_features, AVX512F_Usable)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX512F)) + return OPTIMIZE (knl); + } + +diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-mathvec-sse4_1.h b/sysdeps/x86_64/fpu/multiarch/ifunc-mathvec-sse4_1.h +index c1e70ebfc1b424e6..64d03f6cb1caa9b7 100644 +--- a/sysdeps/x86_64/fpu/multiarch/ifunc-mathvec-sse4_1.h ++++ b/sysdeps/x86_64/fpu/multiarch/ifunc-mathvec-sse4_1.h +@@ -31,7 +31,7 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSE4_1)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_1)) + return OPTIMIZE (sse4); + + return OPTIMIZE (sse2); +diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1.h b/sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1.h +index a8710ba80226f13f..81bca1c9ecde9fb7 100644 +--- a/sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1.h ++++ b/sysdeps/x86_64/fpu/multiarch/ifunc-sse4_1.h +@@ -26,7 +26,7 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSE4_1)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_1)) + return OPTIMIZE (sse41); + + return OPTIMIZE (c); +diff --git a/sysdeps/x86_64/fpu/multiarch/s_fma.c b/sysdeps/x86_64/fpu/multiarch/s_fma.c +index 875c76d3727e6d3c..9ea8d368d08220a9 100644 +--- a/sysdeps/x86_64/fpu/multiarch/s_fma.c ++++ b/sysdeps/x86_64/fpu/multiarch/s_fma.c +@@ -41,8 +41,8 @@ __fma_fma4 (double x, double y, double z) + } + + +-libm_ifunc (__fma, HAS_ARCH_FEATURE (FMA_Usable) +- ? __fma_fma3 : (HAS_ARCH_FEATURE (FMA4_Usable) ++libm_ifunc (__fma, CPU_FEATURE_USABLE (FMA) ++ ? __fma_fma3 : (CPU_FEATURE_USABLE (FMA4) + ? __fma_fma4 : __fma_sse2)); + libm_alias_double (__fma, fma) + +diff --git a/sysdeps/x86_64/fpu/multiarch/s_fmaf.c b/sysdeps/x86_64/fpu/multiarch/s_fmaf.c +index 5f4c2ec0be15c2dc..33e64ef8d1a03269 100644 +--- a/sysdeps/x86_64/fpu/multiarch/s_fmaf.c ++++ b/sysdeps/x86_64/fpu/multiarch/s_fmaf.c +@@ -40,8 +40,8 @@ __fmaf_fma4 (float x, float y, float z) + } + + +-libm_ifunc (__fmaf, HAS_ARCH_FEATURE (FMA_Usable) +- ? __fmaf_fma3 : (HAS_ARCH_FEATURE (FMA4_Usable) ++libm_ifunc (__fmaf, CPU_FEATURE_USABLE (FMA) ++ ? __fmaf_fma3 : (CPU_FEATURE_USABLE (FMA4) + ? __fmaf_fma4 : __fmaf_sse2)); + libm_alias_float (__fma, fma) + +diff --git a/sysdeps/x86_64/multiarch/ifunc-avx2.h b/sysdeps/x86_64/multiarch/ifunc-avx2.h +index 9cab837642b7af21..5c88640a2d901ec6 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-avx2.h ++++ b/sysdeps/x86_64/multiarch/ifunc-avx2.h +@@ -28,7 +28,7 @@ IFUNC_SELECTOR (void) + const struct cpu_features* cpu_features = __get_cpu_features (); + + if (!CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_VZEROUPPER) +- && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2) + && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) + return OPTIMIZE (avx2); + +diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +index 8b55bb6954000cc2..fe13505ca1ac7ef0 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c +@@ -41,19 +41,19 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/memchr.c. */ + IFUNC_IMPL (i, name, memchr, + IFUNC_IMPL_ADD (array, i, memchr, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __memchr_avx2) + IFUNC_IMPL_ADD (array, i, memchr, 1, __memchr_sse2)) + + /* Support sysdeps/x86_64/multiarch/memcmp.c. */ + IFUNC_IMPL (i, name, memcmp, + IFUNC_IMPL_ADD (array, i, memcmp, +- (HAS_ARCH_FEATURE (AVX2_Usable) +- && HAS_CPU_FEATURE (MOVBE)), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (MOVBE)), + __memcmp_avx2_movbe) +- IFUNC_IMPL_ADD (array, i, memcmp, HAS_CPU_FEATURE (SSE4_1), ++ IFUNC_IMPL_ADD (array, i, memcmp, CPU_FEATURE_USABLE (SSE4_1), + __memcmp_sse4_1) +- IFUNC_IMPL_ADD (array, i, memcmp, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, memcmp, CPU_FEATURE_USABLE (SSSE3), + __memcmp_ssse3) + IFUNC_IMPL_ADD (array, i, memcmp, 1, __memcmp_sse2)) + +@@ -61,25 +61,25 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/memmove_chk.c. */ + IFUNC_IMPL (i, name, __memmove_chk, + IFUNC_IMPL_ADD (array, i, __memmove_chk, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memmove_chk_avx512_no_vzeroupper) + IFUNC_IMPL_ADD (array, i, __memmove_chk, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memmove_chk_avx512_unaligned) + IFUNC_IMPL_ADD (array, i, __memmove_chk, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memmove_chk_avx512_unaligned_erms) + IFUNC_IMPL_ADD (array, i, __memmove_chk, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __memmove_chk_avx_unaligned) + IFUNC_IMPL_ADD (array, i, __memmove_chk, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __memmove_chk_avx_unaligned_erms) + IFUNC_IMPL_ADD (array, i, __memmove_chk, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __memmove_chk_ssse3_back) + IFUNC_IMPL_ADD (array, i, __memmove_chk, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __memmove_chk_ssse3) + IFUNC_IMPL_ADD (array, i, __memmove_chk, 1, + __memmove_chk_sse2_unaligned) +@@ -92,23 +92,23 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/memmove.c. */ + IFUNC_IMPL (i, name, memmove, + IFUNC_IMPL_ADD (array, i, memmove, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __memmove_avx_unaligned) + IFUNC_IMPL_ADD (array, i, memmove, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __memmove_avx_unaligned_erms) + IFUNC_IMPL_ADD (array, i, memmove, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memmove_avx512_no_vzeroupper) + IFUNC_IMPL_ADD (array, i, memmove, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memmove_avx512_unaligned) + IFUNC_IMPL_ADD (array, i, memmove, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memmove_avx512_unaligned_erms) +- IFUNC_IMPL_ADD (array, i, memmove, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, memmove, CPU_FEATURE_USABLE (SSSE3), + __memmove_ssse3_back) +- IFUNC_IMPL_ADD (array, i, memmove, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, memmove, CPU_FEATURE_USABLE (SSSE3), + __memmove_ssse3) + IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_erms) + IFUNC_IMPL_ADD (array, i, memmove, 1, +@@ -119,7 +119,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/memrchr.c. */ + IFUNC_IMPL (i, name, memrchr, + IFUNC_IMPL_ADD (array, i, memrchr, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __memrchr_avx2) + IFUNC_IMPL_ADD (array, i, memrchr, 1, __memrchr_sse2)) + +@@ -133,19 +133,19 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_IMPL_ADD (array, i, __memset_chk, 1, + __memset_chk_sse2_unaligned_erms) + IFUNC_IMPL_ADD (array, i, __memset_chk, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __memset_chk_avx2_unaligned) + IFUNC_IMPL_ADD (array, i, __memset_chk, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __memset_chk_avx2_unaligned_erms) + IFUNC_IMPL_ADD (array, i, __memset_chk, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memset_chk_avx512_unaligned_erms) + IFUNC_IMPL_ADD (array, i, __memset_chk, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memset_chk_avx512_unaligned) + IFUNC_IMPL_ADD (array, i, __memset_chk, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memset_chk_avx512_no_vzeroupper) + ) + #endif +@@ -158,48 +158,48 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + __memset_sse2_unaligned_erms) + IFUNC_IMPL_ADD (array, i, memset, 1, __memset_erms) + IFUNC_IMPL_ADD (array, i, memset, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __memset_avx2_unaligned) + IFUNC_IMPL_ADD (array, i, memset, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __memset_avx2_unaligned_erms) + IFUNC_IMPL_ADD (array, i, memset, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memset_avx512_unaligned_erms) + IFUNC_IMPL_ADD (array, i, memset, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memset_avx512_unaligned) + IFUNC_IMPL_ADD (array, i, memset, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memset_avx512_no_vzeroupper) + ) + + /* Support sysdeps/x86_64/multiarch/rawmemchr.c. */ + IFUNC_IMPL (i, name, rawmemchr, + IFUNC_IMPL_ADD (array, i, rawmemchr, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __rawmemchr_avx2) + IFUNC_IMPL_ADD (array, i, rawmemchr, 1, __rawmemchr_sse2)) + + /* Support sysdeps/x86_64/multiarch/strlen.c. */ + IFUNC_IMPL (i, name, strlen, + IFUNC_IMPL_ADD (array, i, strlen, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __strlen_avx2) + IFUNC_IMPL_ADD (array, i, strlen, 1, __strlen_sse2)) + + /* Support sysdeps/x86_64/multiarch/strnlen.c. */ + IFUNC_IMPL (i, name, strnlen, + IFUNC_IMPL_ADD (array, i, strnlen, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __strnlen_avx2) + IFUNC_IMPL_ADD (array, i, strnlen, 1, __strnlen_sse2)) + + /* Support sysdeps/x86_64/multiarch/stpncpy.c. */ + IFUNC_IMPL (i, name, stpncpy, +- IFUNC_IMPL_ADD (array, i, stpncpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, stpncpy, CPU_FEATURE_USABLE (SSSE3), + __stpncpy_ssse3) +- IFUNC_IMPL_ADD (array, i, stpncpy, HAS_ARCH_FEATURE (AVX2_Usable), ++ IFUNC_IMPL_ADD (array, i, stpncpy, CPU_FEATURE_USABLE (AVX2), + __stpncpy_avx2) + IFUNC_IMPL_ADD (array, i, stpncpy, 1, + __stpncpy_sse2_unaligned) +@@ -207,9 +207,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/x86_64/multiarch/stpcpy.c. */ + IFUNC_IMPL (i, name, stpcpy, +- IFUNC_IMPL_ADD (array, i, stpcpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, stpcpy, CPU_FEATURE_USABLE (SSSE3), + __stpcpy_ssse3) +- IFUNC_IMPL_ADD (array, i, stpcpy, HAS_ARCH_FEATURE (AVX2_Usable), ++ IFUNC_IMPL_ADD (array, i, stpcpy, CPU_FEATURE_USABLE (AVX2), + __stpcpy_avx2) + IFUNC_IMPL_ADD (array, i, stpcpy, 1, __stpcpy_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, stpcpy, 1, __stpcpy_sse2)) +@@ -217,35 +217,35 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/strcasecmp_l.c. */ + IFUNC_IMPL (i, name, strcasecmp, + IFUNC_IMPL_ADD (array, i, strcasecmp, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __strcasecmp_avx) + IFUNC_IMPL_ADD (array, i, strcasecmp, +- HAS_CPU_FEATURE (SSE4_2), ++ CPU_FEATURE_USABLE (SSE4_2), + __strcasecmp_sse42) + IFUNC_IMPL_ADD (array, i, strcasecmp, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __strcasecmp_ssse3) + IFUNC_IMPL_ADD (array, i, strcasecmp, 1, __strcasecmp_sse2)) + + /* Support sysdeps/x86_64/multiarch/strcasecmp_l.c. */ + IFUNC_IMPL (i, name, strcasecmp_l, + IFUNC_IMPL_ADD (array, i, strcasecmp_l, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __strcasecmp_l_avx) + IFUNC_IMPL_ADD (array, i, strcasecmp_l, +- HAS_CPU_FEATURE (SSE4_2), ++ CPU_FEATURE_USABLE (SSE4_2), + __strcasecmp_l_sse42) + IFUNC_IMPL_ADD (array, i, strcasecmp_l, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __strcasecmp_l_ssse3) + IFUNC_IMPL_ADD (array, i, strcasecmp_l, 1, + __strcasecmp_l_sse2)) + + /* Support sysdeps/x86_64/multiarch/strcat.c. */ + IFUNC_IMPL (i, name, strcat, +- IFUNC_IMPL_ADD (array, i, strcat, HAS_ARCH_FEATURE (AVX2_Usable), ++ IFUNC_IMPL_ADD (array, i, strcat, CPU_FEATURE_USABLE (AVX2), + __strcat_avx2) +- IFUNC_IMPL_ADD (array, i, strcat, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, strcat, CPU_FEATURE_USABLE (SSSE3), + __strcat_ssse3) + IFUNC_IMPL_ADD (array, i, strcat, 1, __strcat_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, strcat, 1, __strcat_sse2)) +@@ -253,7 +253,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/strchr.c. */ + IFUNC_IMPL (i, name, strchr, + IFUNC_IMPL_ADD (array, i, strchr, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __strchr_avx2) + IFUNC_IMPL_ADD (array, i, strchr, 1, __strchr_sse2_no_bsf) + IFUNC_IMPL_ADD (array, i, strchr, 1, __strchr_sse2)) +@@ -261,54 +261,54 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/strchrnul.c. */ + IFUNC_IMPL (i, name, strchrnul, + IFUNC_IMPL_ADD (array, i, strchrnul, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __strchrnul_avx2) + IFUNC_IMPL_ADD (array, i, strchrnul, 1, __strchrnul_sse2)) + + /* Support sysdeps/x86_64/multiarch/strrchr.c. */ + IFUNC_IMPL (i, name, strrchr, + IFUNC_IMPL_ADD (array, i, strrchr, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __strrchr_avx2) + IFUNC_IMPL_ADD (array, i, strrchr, 1, __strrchr_sse2)) + + /* Support sysdeps/x86_64/multiarch/strcmp.c. */ + IFUNC_IMPL (i, name, strcmp, + IFUNC_IMPL_ADD (array, i, strcmp, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __strcmp_avx2) +- IFUNC_IMPL_ADD (array, i, strcmp, HAS_CPU_FEATURE (SSE4_2), ++ IFUNC_IMPL_ADD (array, i, strcmp, CPU_FEATURE_USABLE (SSE4_2), + __strcmp_sse42) +- IFUNC_IMPL_ADD (array, i, strcmp, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, strcmp, CPU_FEATURE_USABLE (SSSE3), + __strcmp_ssse3) + IFUNC_IMPL_ADD (array, i, strcmp, 1, __strcmp_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, strcmp, 1, __strcmp_sse2)) + + /* Support sysdeps/x86_64/multiarch/strcpy.c. */ + IFUNC_IMPL (i, name, strcpy, +- IFUNC_IMPL_ADD (array, i, strcpy, HAS_ARCH_FEATURE (AVX2_Usable), ++ IFUNC_IMPL_ADD (array, i, strcpy, CPU_FEATURE_USABLE (AVX2), + __strcpy_avx2) +- IFUNC_IMPL_ADD (array, i, strcpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, strcpy, CPU_FEATURE_USABLE (SSSE3), + __strcpy_ssse3) + IFUNC_IMPL_ADD (array, i, strcpy, 1, __strcpy_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, strcpy, 1, __strcpy_sse2)) + + /* Support sysdeps/x86_64/multiarch/strcspn.c. */ + IFUNC_IMPL (i, name, strcspn, +- IFUNC_IMPL_ADD (array, i, strcspn, HAS_CPU_FEATURE (SSE4_2), ++ IFUNC_IMPL_ADD (array, i, strcspn, CPU_FEATURE_USABLE (SSE4_2), + __strcspn_sse42) + IFUNC_IMPL_ADD (array, i, strcspn, 1, __strcspn_sse2)) + + /* Support sysdeps/x86_64/multiarch/strncase_l.c. */ + IFUNC_IMPL (i, name, strncasecmp, + IFUNC_IMPL_ADD (array, i, strncasecmp, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __strncasecmp_avx) + IFUNC_IMPL_ADD (array, i, strncasecmp, +- HAS_CPU_FEATURE (SSE4_2), ++ CPU_FEATURE_USABLE (SSE4_2), + __strncasecmp_sse42) + IFUNC_IMPL_ADD (array, i, strncasecmp, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __strncasecmp_ssse3) + IFUNC_IMPL_ADD (array, i, strncasecmp, 1, + __strncasecmp_sse2)) +@@ -316,22 +316,22 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/strncase_l.c. */ + IFUNC_IMPL (i, name, strncasecmp_l, + IFUNC_IMPL_ADD (array, i, strncasecmp_l, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __strncasecmp_l_avx) + IFUNC_IMPL_ADD (array, i, strncasecmp_l, +- HAS_CPU_FEATURE (SSE4_2), ++ CPU_FEATURE_USABLE (SSE4_2), + __strncasecmp_l_sse42) + IFUNC_IMPL_ADD (array, i, strncasecmp_l, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __strncasecmp_l_ssse3) + IFUNC_IMPL_ADD (array, i, strncasecmp_l, 1, + __strncasecmp_l_sse2)) + + /* Support sysdeps/x86_64/multiarch/strncat.c. */ + IFUNC_IMPL (i, name, strncat, +- IFUNC_IMPL_ADD (array, i, strncat, HAS_ARCH_FEATURE (AVX2_Usable), ++ IFUNC_IMPL_ADD (array, i, strncat, CPU_FEATURE_USABLE (AVX2), + __strncat_avx2) +- IFUNC_IMPL_ADD (array, i, strncat, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, strncat, CPU_FEATURE_USABLE (SSSE3), + __strncat_ssse3) + IFUNC_IMPL_ADD (array, i, strncat, 1, + __strncat_sse2_unaligned) +@@ -339,9 +339,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/x86_64/multiarch/strncpy.c. */ + IFUNC_IMPL (i, name, strncpy, +- IFUNC_IMPL_ADD (array, i, strncpy, HAS_ARCH_FEATURE (AVX2_Usable), ++ IFUNC_IMPL_ADD (array, i, strncpy, CPU_FEATURE_USABLE (AVX2), + __strncpy_avx2) +- IFUNC_IMPL_ADD (array, i, strncpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, strncpy, CPU_FEATURE_USABLE (SSSE3), + __strncpy_ssse3) + IFUNC_IMPL_ADD (array, i, strncpy, 1, + __strncpy_sse2_unaligned) +@@ -349,14 +349,14 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/x86_64/multiarch/strpbrk.c. */ + IFUNC_IMPL (i, name, strpbrk, +- IFUNC_IMPL_ADD (array, i, strpbrk, HAS_CPU_FEATURE (SSE4_2), ++ IFUNC_IMPL_ADD (array, i, strpbrk, CPU_FEATURE_USABLE (SSE4_2), + __strpbrk_sse42) + IFUNC_IMPL_ADD (array, i, strpbrk, 1, __strpbrk_sse2)) + + + /* Support sysdeps/x86_64/multiarch/strspn.c. */ + IFUNC_IMPL (i, name, strspn, +- IFUNC_IMPL_ADD (array, i, strspn, HAS_CPU_FEATURE (SSE4_2), ++ IFUNC_IMPL_ADD (array, i, strspn, CPU_FEATURE_USABLE (SSE4_2), + __strspn_sse42) + IFUNC_IMPL_ADD (array, i, strspn, 1, __strspn_sse2)) + +@@ -368,70 +368,70 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/wcschr.c. */ + IFUNC_IMPL (i, name, wcschr, + IFUNC_IMPL_ADD (array, i, wcschr, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __wcschr_avx2) + IFUNC_IMPL_ADD (array, i, wcschr, 1, __wcschr_sse2)) + + /* Support sysdeps/x86_64/multiarch/wcsrchr.c. */ + IFUNC_IMPL (i, name, wcsrchr, + IFUNC_IMPL_ADD (array, i, wcsrchr, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __wcsrchr_avx2) + IFUNC_IMPL_ADD (array, i, wcsrchr, 1, __wcsrchr_sse2)) + + /* Support sysdeps/x86_64/multiarch/wcscmp.c. */ + IFUNC_IMPL (i, name, wcscmp, + IFUNC_IMPL_ADD (array, i, wcscmp, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __wcscmp_avx2) + IFUNC_IMPL_ADD (array, i, wcscmp, 1, __wcscmp_sse2)) + + /* Support sysdeps/x86_64/multiarch/wcsncmp.c. */ + IFUNC_IMPL (i, name, wcsncmp, + IFUNC_IMPL_ADD (array, i, wcsncmp, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __wcsncmp_avx2) + IFUNC_IMPL_ADD (array, i, wcsncmp, 1, __wcsncmp_sse2)) + + /* Support sysdeps/x86_64/multiarch/wcscpy.c. */ + IFUNC_IMPL (i, name, wcscpy, +- IFUNC_IMPL_ADD (array, i, wcscpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, wcscpy, CPU_FEATURE_USABLE (SSSE3), + __wcscpy_ssse3) + IFUNC_IMPL_ADD (array, i, wcscpy, 1, __wcscpy_sse2)) + + /* Support sysdeps/x86_64/multiarch/wcslen.c. */ + IFUNC_IMPL (i, name, wcslen, + IFUNC_IMPL_ADD (array, i, wcslen, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __wcslen_avx2) + IFUNC_IMPL_ADD (array, i, wcslen, 1, __wcslen_sse2)) + + /* Support sysdeps/x86_64/multiarch/wcsnlen.c. */ + IFUNC_IMPL (i, name, wcsnlen, + IFUNC_IMPL_ADD (array, i, wcsnlen, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __wcsnlen_avx2) + IFUNC_IMPL_ADD (array, i, wcsnlen, +- HAS_CPU_FEATURE (SSE4_1), ++ CPU_FEATURE_USABLE (SSE4_1), + __wcsnlen_sse4_1) + IFUNC_IMPL_ADD (array, i, wcsnlen, 1, __wcsnlen_sse2)) + + /* Support sysdeps/x86_64/multiarch/wmemchr.c. */ + IFUNC_IMPL (i, name, wmemchr, + IFUNC_IMPL_ADD (array, i, wmemchr, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __wmemchr_avx2) + IFUNC_IMPL_ADD (array, i, wmemchr, 1, __wmemchr_sse2)) + + /* Support sysdeps/x86_64/multiarch/wmemcmp.c. */ + IFUNC_IMPL (i, name, wmemcmp, + IFUNC_IMPL_ADD (array, i, wmemcmp, +- (HAS_ARCH_FEATURE (AVX2_Usable) +- && HAS_CPU_FEATURE (MOVBE)), ++ (CPU_FEATURE_USABLE (AVX2) ++ && CPU_FEATURE_USABLE (MOVBE)), + __wmemcmp_avx2_movbe) +- IFUNC_IMPL_ADD (array, i, wmemcmp, HAS_CPU_FEATURE (SSE4_1), ++ IFUNC_IMPL_ADD (array, i, wmemcmp, CPU_FEATURE_USABLE (SSE4_1), + __wmemcmp_sse4_1) +- IFUNC_IMPL_ADD (array, i, wmemcmp, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, wmemcmp, CPU_FEATURE_USABLE (SSSE3), + __wmemcmp_ssse3) + IFUNC_IMPL_ADD (array, i, wmemcmp, 1, __wmemcmp_sse2)) + +@@ -440,35 +440,35 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_IMPL_ADD (array, i, wmemset, 1, + __wmemset_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, wmemset, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __wmemset_avx2_unaligned) + IFUNC_IMPL_ADD (array, i, wmemset, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __wmemset_avx512_unaligned)) + + #ifdef SHARED + /* Support sysdeps/x86_64/multiarch/memcpy_chk.c. */ + IFUNC_IMPL (i, name, __memcpy_chk, + IFUNC_IMPL_ADD (array, i, __memcpy_chk, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memcpy_chk_avx512_no_vzeroupper) + IFUNC_IMPL_ADD (array, i, __memcpy_chk, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memcpy_chk_avx512_unaligned) + IFUNC_IMPL_ADD (array, i, __memcpy_chk, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memcpy_chk_avx512_unaligned_erms) + IFUNC_IMPL_ADD (array, i, __memcpy_chk, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __memcpy_chk_avx_unaligned) + IFUNC_IMPL_ADD (array, i, __memcpy_chk, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __memcpy_chk_avx_unaligned_erms) + IFUNC_IMPL_ADD (array, i, __memcpy_chk, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __memcpy_chk_ssse3_back) + IFUNC_IMPL_ADD (array, i, __memcpy_chk, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __memcpy_chk_ssse3) + IFUNC_IMPL_ADD (array, i, __memcpy_chk, 1, + __memcpy_chk_sse2_unaligned) +@@ -481,23 +481,23 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/memcpy.c. */ + IFUNC_IMPL (i, name, memcpy, + IFUNC_IMPL_ADD (array, i, memcpy, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __memcpy_avx_unaligned) + IFUNC_IMPL_ADD (array, i, memcpy, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __memcpy_avx_unaligned_erms) +- IFUNC_IMPL_ADD (array, i, memcpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, memcpy, CPU_FEATURE_USABLE (SSSE3), + __memcpy_ssse3_back) +- IFUNC_IMPL_ADD (array, i, memcpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, memcpy, CPU_FEATURE_USABLE (SSSE3), + __memcpy_ssse3) + IFUNC_IMPL_ADD (array, i, memcpy, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memcpy_avx512_no_vzeroupper) + IFUNC_IMPL_ADD (array, i, memcpy, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memcpy_avx512_unaligned) + IFUNC_IMPL_ADD (array, i, memcpy, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __memcpy_avx512_unaligned_erms) + IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, memcpy, 1, +@@ -508,25 +508,25 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/mempcpy_chk.c. */ + IFUNC_IMPL (i, name, __mempcpy_chk, + IFUNC_IMPL_ADD (array, i, __mempcpy_chk, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __mempcpy_chk_avx512_no_vzeroupper) + IFUNC_IMPL_ADD (array, i, __mempcpy_chk, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __mempcpy_chk_avx512_unaligned) + IFUNC_IMPL_ADD (array, i, __mempcpy_chk, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __mempcpy_chk_avx512_unaligned_erms) + IFUNC_IMPL_ADD (array, i, __mempcpy_chk, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __mempcpy_chk_avx_unaligned) + IFUNC_IMPL_ADD (array, i, __mempcpy_chk, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __mempcpy_chk_avx_unaligned_erms) + IFUNC_IMPL_ADD (array, i, __mempcpy_chk, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __mempcpy_chk_ssse3_back) + IFUNC_IMPL_ADD (array, i, __mempcpy_chk, +- HAS_CPU_FEATURE (SSSE3), ++ CPU_FEATURE_USABLE (SSSE3), + __mempcpy_chk_ssse3) + IFUNC_IMPL_ADD (array, i, __mempcpy_chk, 1, + __mempcpy_chk_sse2_unaligned) +@@ -539,23 +539,23 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/mempcpy.c. */ + IFUNC_IMPL (i, name, mempcpy, + IFUNC_IMPL_ADD (array, i, mempcpy, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __mempcpy_avx512_no_vzeroupper) + IFUNC_IMPL_ADD (array, i, mempcpy, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __mempcpy_avx512_unaligned) + IFUNC_IMPL_ADD (array, i, mempcpy, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __mempcpy_avx512_unaligned_erms) + IFUNC_IMPL_ADD (array, i, mempcpy, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __mempcpy_avx_unaligned) + IFUNC_IMPL_ADD (array, i, mempcpy, +- HAS_ARCH_FEATURE (AVX_Usable), ++ CPU_FEATURE_USABLE (AVX), + __mempcpy_avx_unaligned_erms) +- IFUNC_IMPL_ADD (array, i, mempcpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, mempcpy, CPU_FEATURE_USABLE (SSSE3), + __mempcpy_ssse3_back) +- IFUNC_IMPL_ADD (array, i, mempcpy, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, mempcpy, CPU_FEATURE_USABLE (SSSE3), + __mempcpy_ssse3) + IFUNC_IMPL_ADD (array, i, mempcpy, 1, + __mempcpy_sse2_unaligned) +@@ -566,11 +566,11 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/x86_64/multiarch/strncmp.c. */ + IFUNC_IMPL (i, name, strncmp, + IFUNC_IMPL_ADD (array, i, strncmp, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __strncmp_avx2) +- IFUNC_IMPL_ADD (array, i, strncmp, HAS_CPU_FEATURE (SSE4_2), ++ IFUNC_IMPL_ADD (array, i, strncmp, CPU_FEATURE_USABLE (SSE4_2), + __strncmp_sse42) +- IFUNC_IMPL_ADD (array, i, strncmp, HAS_CPU_FEATURE (SSSE3), ++ IFUNC_IMPL_ADD (array, i, strncmp, CPU_FEATURE_USABLE (SSSE3), + __strncmp_ssse3) + IFUNC_IMPL_ADD (array, i, strncmp, 1, __strncmp_sse2)) + +@@ -580,10 +580,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_IMPL_ADD (array, i, __wmemset_chk, 1, + __wmemset_chk_sse2_unaligned) + IFUNC_IMPL_ADD (array, i, __wmemset_chk, +- HAS_ARCH_FEATURE (AVX2_Usable), ++ CPU_FEATURE_USABLE (AVX2), + __wmemset_chk_avx2_unaligned) + IFUNC_IMPL_ADD (array, i, __wmemset_chk, +- HAS_ARCH_FEATURE (AVX512F_Usable), ++ CPU_FEATURE_USABLE (AVX512F), + __wmemset_chk_avx512_unaligned)) + #endif + +diff --git a/sysdeps/x86_64/multiarch/ifunc-memcmp.h b/sysdeps/x86_64/multiarch/ifunc-memcmp.h +index bf5ab8eb7ffd0002..6c1f3153579d19c4 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-memcmp.h ++++ b/sysdeps/x86_64/multiarch/ifunc-memcmp.h +@@ -30,15 +30,15 @@ IFUNC_SELECTOR (void) + const struct cpu_features* cpu_features = __get_cpu_features (); + + if (!CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_VZEROUPPER) +- && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable) +- && CPU_FEATURES_CPU_P (cpu_features, MOVBE) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2) ++ && CPU_FEATURE_USABLE_P (cpu_features, MOVBE) + && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) + return OPTIMIZE (avx2_movbe); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSE4_1)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_1)) + return OPTIMIZE (sse4_1); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSSE3)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSSE3)) + return OPTIMIZE (ssse3); + + return OPTIMIZE (sse2); +diff --git a/sysdeps/x86_64/multiarch/ifunc-memmove.h b/sysdeps/x86_64/multiarch/ifunc-memmove.h +index 5b1eb1c92c2f199b..5e5f02994531ec14 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-memmove.h ++++ b/sysdeps/x86_64/multiarch/ifunc-memmove.h +@@ -45,13 +45,13 @@ IFUNC_SELECTOR (void) + || CPU_FEATURES_ARCH_P (cpu_features, Prefer_FSRM)) + return OPTIMIZE (erms); + +- if (CPU_FEATURES_ARCH_P (cpu_features, AVX512F_Usable) ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX512F) + && !CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_AVX512)) + { + if (CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_VZEROUPPER)) + return OPTIMIZE (avx512_no_vzeroupper); + +- if (CPU_FEATURES_CPU_P (cpu_features, ERMS)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, ERMS)) + return OPTIMIZE (avx512_unaligned_erms); + + return OPTIMIZE (avx512_unaligned); +@@ -59,16 +59,16 @@ IFUNC_SELECTOR (void) + + if (CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) + { +- if (CPU_FEATURES_CPU_P (cpu_features, ERMS)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, ERMS)) + return OPTIMIZE (avx_unaligned_erms); + + return OPTIMIZE (avx_unaligned); + } + +- if (!CPU_FEATURES_CPU_P (cpu_features, SSSE3) ++ if (!CPU_FEATURE_USABLE_P (cpu_features, SSSE3) + || CPU_FEATURES_ARCH_P (cpu_features, Fast_Unaligned_Copy)) + { +- if (CPU_FEATURES_CPU_P (cpu_features, ERMS)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, ERMS)) + return OPTIMIZE (sse2_unaligned_erms); + + return OPTIMIZE (sse2_unaligned); +diff --git a/sysdeps/x86_64/multiarch/ifunc-memset.h b/sysdeps/x86_64/multiarch/ifunc-memset.h +index 19b5ae676c2d5d53..708bd72e2c3d3963 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-memset.h ++++ b/sysdeps/x86_64/multiarch/ifunc-memset.h +@@ -42,27 +42,27 @@ IFUNC_SELECTOR (void) + if (CPU_FEATURES_ARCH_P (cpu_features, Prefer_ERMS)) + return OPTIMIZE (erms); + +- if (CPU_FEATURES_ARCH_P (cpu_features, AVX512F_Usable) ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX512F) + && !CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_AVX512)) + { + if (CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_VZEROUPPER)) + return OPTIMIZE (avx512_no_vzeroupper); + +- if (CPU_FEATURES_CPU_P (cpu_features, ERMS)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, ERMS)) + return OPTIMIZE (avx512_unaligned_erms); + + return OPTIMIZE (avx512_unaligned); + } + +- if (CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX2)) + { +- if (CPU_FEATURES_CPU_P (cpu_features, ERMS)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, ERMS)) + return OPTIMIZE (avx2_unaligned_erms); + else + return OPTIMIZE (avx2_unaligned); + } + +- if (CPU_FEATURES_CPU_P (cpu_features, ERMS)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, ERMS)) + return OPTIMIZE (sse2_unaligned_erms); + + return OPTIMIZE (sse2_unaligned); +diff --git a/sysdeps/x86_64/multiarch/ifunc-sse4_2.h b/sysdeps/x86_64/multiarch/ifunc-sse4_2.h +index f2b791cccf12c425..73383f4b583b29c8 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-sse4_2.h ++++ b/sysdeps/x86_64/multiarch/ifunc-sse4_2.h +@@ -27,7 +27,7 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSE4_2)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_2)) + return OPTIMIZE (sse42); + + return OPTIMIZE (sse2); +diff --git a/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h b/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h +index 1ca170b663a4e65c..6a4bb07849a11f51 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h ++++ b/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h +@@ -29,14 +29,14 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_ARCH_P (cpu_features, AVX_Usable)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX)) + return OPTIMIZE (avx); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSE4_2) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_2) + && !CPU_FEATURES_ARCH_P (cpu_features, Slow_SSE4_2)) + return OPTIMIZE (sse42); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSSE3)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSSE3)) + return OPTIMIZE (ssse3); + + return OPTIMIZE (sse2); +diff --git a/sysdeps/x86_64/multiarch/ifunc-strcpy.h b/sysdeps/x86_64/multiarch/ifunc-strcpy.h +index 4f2286fefccda069..100dca5cde0ecac5 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-strcpy.h ++++ b/sysdeps/x86_64/multiarch/ifunc-strcpy.h +@@ -32,14 +32,14 @@ IFUNC_SELECTOR (void) + const struct cpu_features* cpu_features = __get_cpu_features (); + + if (!CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_VZEROUPPER) +- && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2) + && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) + return OPTIMIZE (avx2); + + if (CPU_FEATURES_ARCH_P (cpu_features, Fast_Unaligned_Load)) + return OPTIMIZE (sse2_unaligned); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSSE3)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSSE3)) + return OPTIMIZE (ssse3); + + return OPTIMIZE (sse2); +diff --git a/sysdeps/x86_64/multiarch/ifunc-wmemset.h b/sysdeps/x86_64/multiarch/ifunc-wmemset.h +index 2f1085f5fc483c70..eb2422104751b235 100644 +--- a/sysdeps/x86_64/multiarch/ifunc-wmemset.h ++++ b/sysdeps/x86_64/multiarch/ifunc-wmemset.h +@@ -28,10 +28,10 @@ IFUNC_SELECTOR (void) + const struct cpu_features* cpu_features = __get_cpu_features (); + + if (!CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_VZEROUPPER) +- && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2) + && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) + { +- if (CPU_FEATURES_ARCH_P (cpu_features, AVX512F_Usable) ++ if (CPU_FEATURE_USABLE_P (cpu_features, AVX512F) + && !CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_AVX512)) + return OPTIMIZE (avx512_unaligned); + else +diff --git a/sysdeps/x86_64/multiarch/sched_cpucount.c b/sysdeps/x86_64/multiarch/sched_cpucount.c +index 7949119dcdb5a94b..b38ff37c6511ca1b 100644 +--- a/sysdeps/x86_64/multiarch/sched_cpucount.c ++++ b/sysdeps/x86_64/multiarch/sched_cpucount.c +@@ -33,4 +33,4 @@ + #undef __sched_cpucount + + libc_ifunc (__sched_cpucount, +- HAS_CPU_FEATURE (POPCNT) ? popcount_cpucount : generic_cpucount); ++ CPU_FEATURE_USABLE (POPCNT) ? popcount_cpucount : generic_cpucount); +diff --git a/sysdeps/x86_64/multiarch/strchr.c b/sysdeps/x86_64/multiarch/strchr.c +index 76d64fb378e9bbac..329547132c3a301b 100644 +--- a/sysdeps/x86_64/multiarch/strchr.c ++++ b/sysdeps/x86_64/multiarch/strchr.c +@@ -36,7 +36,7 @@ IFUNC_SELECTOR (void) + const struct cpu_features* cpu_features = __get_cpu_features (); + + if (!CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_VZEROUPPER) +- && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2) + && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) + return OPTIMIZE (avx2); + +diff --git a/sysdeps/x86_64/multiarch/strcmp.c b/sysdeps/x86_64/multiarch/strcmp.c +index b903e418df151ec1..3f433fbccf9e7121 100644 +--- a/sysdeps/x86_64/multiarch/strcmp.c ++++ b/sysdeps/x86_64/multiarch/strcmp.c +@@ -37,14 +37,14 @@ IFUNC_SELECTOR (void) + const struct cpu_features* cpu_features = __get_cpu_features (); + + if (!CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_VZEROUPPER) +- && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2) + && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) + return OPTIMIZE (avx2); + + if (CPU_FEATURES_ARCH_P (cpu_features, Fast_Unaligned_Load)) + return OPTIMIZE (sse2_unaligned); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSSE3)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSSE3)) + return OPTIMIZE (ssse3); + + return OPTIMIZE (sse2); +diff --git a/sysdeps/x86_64/multiarch/strncmp.c b/sysdeps/x86_64/multiarch/strncmp.c +index 02b6d0b6f5717e2a..686d654f3da84379 100644 +--- a/sysdeps/x86_64/multiarch/strncmp.c ++++ b/sysdeps/x86_64/multiarch/strncmp.c +@@ -37,15 +37,15 @@ IFUNC_SELECTOR (void) + const struct cpu_features* cpu_features = __get_cpu_features (); + + if (!CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_VZEROUPPER) +- && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2) + && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) + return OPTIMIZE (avx2); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSE4_2) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_2) + && !CPU_FEATURES_ARCH_P (cpu_features, Slow_SSE4_2)) + return OPTIMIZE (sse42); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSSE3)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSSE3)) + return OPTIMIZE (ssse3); + + return OPTIMIZE (sse2); +diff --git a/sysdeps/x86_64/multiarch/test-multiarch.c b/sysdeps/x86_64/multiarch/test-multiarch.c +index 417147c3d5f325a5..cc2ea56a6753402d 100644 +--- a/sysdeps/x86_64/multiarch/test-multiarch.c ++++ b/sysdeps/x86_64/multiarch/test-multiarch.c +@@ -75,18 +75,18 @@ do_test (int argc, char **argv) + int fails; + + get_cpuinfo (); +- fails = check_proc ("avx", HAS_ARCH_FEATURE (AVX_Usable), +- "HAS_ARCH_FEATURE (AVX_Usable)"); +- fails += check_proc ("fma4", HAS_ARCH_FEATURE (FMA4_Usable), +- "HAS_ARCH_FEATURE (FMA4_Usable)"); +- fails += check_proc ("sse4_2", HAS_CPU_FEATURE (SSE4_2), +- "HAS_CPU_FEATURE (SSE4_2)"); +- fails += check_proc ("sse4_1", HAS_CPU_FEATURE (SSE4_1) +- , "HAS_CPU_FEATURE (SSE4_1)"); +- fails += check_proc ("ssse3", HAS_CPU_FEATURE (SSSE3), +- "HAS_CPU_FEATURE (SSSE3)"); +- fails += check_proc ("popcnt", HAS_CPU_FEATURE (POPCNT), +- "HAS_CPU_FEATURE (POPCNT)"); ++ fails = check_proc ("avx", CPU_FEATURE_USABLE (AVX), ++ "CPU_FEATURE_USABLE (AVX)"); ++ fails += check_proc ("fma4", CPU_FEATURE_USABLE (FMA4), ++ "CPU_FEATURE_USABLE (FMA4)"); ++ fails += check_proc ("sse4_2", CPU_FEATURE_USABLE (SSE4_2), ++ "CPU_FEATURE_USABLE (SSE4_2)"); ++ fails += check_proc ("sse4_1", CPU_FEATURE_USABLE (SSE4_1) ++ , "CPU_FEATURE_USABLE (SSE4_1)"); ++ fails += check_proc ("ssse3", CPU_FEATURE_USABLE (SSSE3), ++ "CPU_FEATURE_USABLE (SSSE3)"); ++ fails += check_proc ("popcnt", CPU_FEATURE_USABLE (POPCNT), ++ "CPU_FEATURE_USABLE (POPCNT)"); + + printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails); + +diff --git a/sysdeps/x86_64/multiarch/wcscpy.c b/sysdeps/x86_64/multiarch/wcscpy.c +index f23b1fd853a4dcb4..8fffb5c3163ab3e4 100644 +--- a/sysdeps/x86_64/multiarch/wcscpy.c ++++ b/sysdeps/x86_64/multiarch/wcscpy.c +@@ -34,7 +34,7 @@ IFUNC_SELECTOR (void) + { + const struct cpu_features* cpu_features = __get_cpu_features (); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSSE3)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSSE3)) + return OPTIMIZE (ssse3); + + return OPTIMIZE (sse2); +diff --git a/sysdeps/x86_64/multiarch/wcsnlen.c b/sysdeps/x86_64/multiarch/wcsnlen.c +index bd376057e3e26ed6..b3144c938df70b1e 100644 +--- a/sysdeps/x86_64/multiarch/wcsnlen.c ++++ b/sysdeps/x86_64/multiarch/wcsnlen.c +@@ -36,11 +36,11 @@ IFUNC_SELECTOR (void) + const struct cpu_features* cpu_features = __get_cpu_features (); + + if (!CPU_FEATURES_ARCH_P (cpu_features, Prefer_No_VZEROUPPER) +- && CPU_FEATURES_ARCH_P (cpu_features, AVX2_Usable) ++ && CPU_FEATURE_USABLE_P (cpu_features, AVX2) + && CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load)) + return OPTIMIZE (avx2); + +- if (CPU_FEATURES_CPU_P (cpu_features, SSE4_1)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, SSE4_1)) + return OPTIMIZE (sse4_1); + + return OPTIMIZE (sse2); diff --git a/glibc-rh1817513-78.patch b/glibc-rh1817513-78.patch new file mode 100755 index 0000000..2395513 --- /dev/null +++ b/glibc-rh1817513-78.patch @@ -0,0 +1,75 @@ +commit 94b63e66206a9ad38872a9136a623ce73cf7c858 +Author: Florian Weimer +Date: Thu Feb 7 09:02:00 2019 +0100 + + support: Implement xdlmopen + + Put xdlmopen into its own file, to avoid disturbing static linking + tests (where dlmopen pulls in additional code). + +diff --git a/support/Makefile b/support/Makefile +index 5808a42dce87151f..895b83a426369b0c 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -86,6 +86,7 @@ libsupport-routines = \ + xconnect \ + xcopy_file_range \ + xdlfcn \ ++ xdlmopen \ + xdup2 \ + xfclose \ + xfopen \ +diff --git a/support/xdlfcn.h b/support/xdlfcn.h +index ab1cbb3cb9bb1cc7..a53fb61b133af5c3 100644 +--- a/support/xdlfcn.h ++++ b/support/xdlfcn.h +@@ -25,11 +25,11 @@ __BEGIN_DECLS + + /* Each of these terminates process on failure with relevant error message. */ + void *xdlopen (const char *filename, int flags); ++void *xdlmopen (Lmid_t lmid, const char *filename, int flags); + void *xdlsym (void *handle, const char *symbol); + void *xdlvsym (void *handle, const char *symbol, const char *version); + void xdlclose (void *handle); + +- + __END_DECLS + + #endif /* SUPPORT_DLOPEN_H */ +diff --git a/support/xdlmopen.c b/support/xdlmopen.c +new file mode 100644 +index 0000000000000000..9a39ba8801eb1617 +--- /dev/null ++++ b/support/xdlmopen.c +@@ -0,0 +1,31 @@ ++/* dlmopen with error checking. ++ Copyright (C) 2017-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 ++ . */ ++ ++#include ++#include ++ ++void * ++xdlmopen (Lmid_t lmid, const char *filename, int flags) ++{ ++ void *dso = dlmopen (lmid, filename, flags); ++ ++ if (dso == NULL) ++ FAIL_EXIT1 ("error: dlmopen: %s\n", dlerror ()); ++ ++ return dso; ++} diff --git a/glibc-rh1817513-79.patch b/glibc-rh1817513-79.patch new file mode 100755 index 0000000..5b1cb3a --- /dev/null +++ b/glibc-rh1817513-79.patch @@ -0,0 +1,642 @@ +commit ffb17e7ba3a5ba9632cee97330b325072fbe41dd +Author: Szabolcs Nagy +Date: Wed Jun 10 13:40:40 2020 +0100 + + rtld: Avoid using up static TLS surplus for optimizations [BZ #25051] + + On some targets static TLS surplus area can be used opportunistically + for dynamically loaded modules such that the TLS access then becomes + faster (TLSDESC and powerpc TLS optimization). However we don't want + all surplus TLS to be used for this optimization because dynamically + loaded modules with initial-exec model TLS can only use surplus TLS. + + The new contract for surplus static TLS use is: + + - libc.so can have up to 192 bytes of IE TLS, + - other system libraries together can have up to 144 bytes of IE TLS. + - Some "optional" static TLS is available for opportunistic use. + + The optional TLS is now tunable: rtld.optional_static_tls, so users + can directly affect the allocated static TLS size. (Note that module + unloading with dlclose does not reclaim static TLS. After the optional + TLS runs out, TLS access is no longer optimized to use static TLS.) + + The default setting of rtld.optional_static_tls is 512 so the surplus + TLS is 3*192 + 4*144 + 512 = 1664 by default, the same as before. + + Fixes BZ #25051. + + Tested on aarch64-linux-gnu and x86_64-linux-gnu. + + Reviewed-by: Carlos O'Donell + +Conflicts: + elf/Makefile + (Missing __libc_single_threaded downstream.) + +diff --git a/csu/libc-tls.c b/csu/libc-tls.c +index 6f2a47dc86222407..76aa1b98ea059a43 100644 +--- a/csu/libc-tls.c ++++ b/csu/libc-tls.c +@@ -62,6 +62,9 @@ size_t _dl_tls_static_align; + loaded modules with IE-model TLS or for TLSDESC optimization. + See comments in elf/dl-tls.c where it is initialized. */ + size_t _dl_tls_static_surplus; ++/* Remaining amount of static TLS that may be used for optimizing ++ dynamic TLS access (e.g. with TLSDESC). */ ++size_t _dl_tls_static_optional; + + /* Generation counter for the dtv. */ + size_t _dl_tls_generation; +diff --git a/elf/Makefile b/elf/Makefile +index cbced7605ebe2443..8b96bfefd852b79f 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -197,7 +197,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-auditmany tst-initfinilazyfail \ + tst-dlopenfail tst-dlopenfail-2 \ + tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \ +- tst-audit14 tst-audit15 tst-audit16 ++ tst-audit14 tst-audit15 tst-audit16 \ ++ tst-tls-ie tst-tls-ie-dlmopen + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -313,7 +314,10 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \ + tst-dlopenfailmod3 \ + tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee \ +- tst-auditlogmod-1 tst-auditlogmod-2 tst-auditlogmod-3 ++ tst-auditlogmod-1 tst-auditlogmod-2 tst-auditlogmod-3 \ ++ tst-tls-ie-mod0 tst-tls-ie-mod1 tst-tls-ie-mod2 \ ++ tst-tls-ie-mod3 tst-tls-ie-mod4 tst-tls-ie-mod5 \ ++ tst-tls-ie-mod6 + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +@@ -1690,3 +1694,23 @@ $(objpfx)tst-auxobj: $(objpfx)tst-filterobj-aux.so + $(objpfx)tst-auxobj-dlopen: $(libdl) + $(objpfx)tst-auxobj.out: $(objpfx)tst-filterobj-filtee.so + $(objpfx)tst-auxobj-dlopen.out: $(objpfx)tst-filterobj-filtee.so ++ ++$(objpfx)tst-tls-ie: $(libdl) $(shared-thread-library) ++$(objpfx)tst-tls-ie.out: \ ++ $(objpfx)tst-tls-ie-mod0.so \ ++ $(objpfx)tst-tls-ie-mod1.so \ ++ $(objpfx)tst-tls-ie-mod2.so \ ++ $(objpfx)tst-tls-ie-mod3.so \ ++ $(objpfx)tst-tls-ie-mod4.so \ ++ $(objpfx)tst-tls-ie-mod5.so \ ++ $(objpfx)tst-tls-ie-mod6.so ++ ++$(objpfx)tst-tls-ie-dlmopen: $(libdl) $(shared-thread-library) ++$(objpfx)tst-tls-ie-dlmopen.out: \ ++ $(objpfx)tst-tls-ie-mod0.so \ ++ $(objpfx)tst-tls-ie-mod1.so \ ++ $(objpfx)tst-tls-ie-mod2.so \ ++ $(objpfx)tst-tls-ie-mod3.so \ ++ $(objpfx)tst-tls-ie-mod4.so \ ++ $(objpfx)tst-tls-ie-mod5.so \ ++ $(objpfx)tst-tls-ie-mod6.so +diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c +index afeace4d3e49180c..c6139b89d4ecddc8 100644 +--- a/elf/dl-reloc.c ++++ b/elf/dl-reloc.c +@@ -39,13 +39,16 @@ + /* We are trying to perform a static TLS relocation in MAP, but it was + dynamically loaded. This can only work if there is enough surplus in + the static TLS area already allocated for each running thread. If this +- object's TLS segment is too big to fit, we fail. If it fits, +- we set MAP->l_tls_offset and return. +- This function intentionally does not return any value but signals error +- directly, as static TLS should be rare and code handling it should +- not be inlined as much as possible. */ ++ object's TLS segment is too big to fit, we fail with -1. If it fits, ++ we set MAP->l_tls_offset and return 0. ++ A portion of the surplus static TLS can be optionally used to optimize ++ dynamic TLS access (with TLSDESC or powerpc TLS optimizations). ++ If OPTIONAL is true then TLS is allocated for such optimization and ++ the caller must have a fallback in case the optional portion of surplus ++ TLS runs out. If OPTIONAL is false then the entire surplus TLS area is ++ considered and the allocation only fails if that runs out. */ + int +-_dl_try_allocate_static_tls (struct link_map *map) ++_dl_try_allocate_static_tls (struct link_map *map, bool optional) + { + /* If we've already used the variable with dynamic access, or if the + alignment requirements are too high, fail. */ +@@ -68,8 +71,14 @@ _dl_try_allocate_static_tls (struct link_map *map) + + size_t n = (freebytes - blsize) / map->l_tls_align; + +- size_t offset = GL(dl_tls_static_used) + (freebytes - n * map->l_tls_align +- - map->l_tls_firstbyte_offset); ++ /* Account optional static TLS surplus usage. */ ++ size_t use = freebytes - n * map->l_tls_align - map->l_tls_firstbyte_offset; ++ if (optional && use > GL(dl_tls_static_optional)) ++ goto fail; ++ else if (optional) ++ GL(dl_tls_static_optional) -= use; ++ ++ size_t offset = GL(dl_tls_static_used) + use; + + map->l_tls_offset = GL(dl_tls_static_used) = offset; + #elif TLS_DTV_AT_TP +@@ -83,6 +92,13 @@ _dl_try_allocate_static_tls (struct link_map *map) + if (used > GL(dl_tls_static_size)) + goto fail; + ++ /* Account optional static TLS surplus usage. */ ++ size_t use = used - GL(dl_tls_static_used); ++ if (optional && use > GL(dl_tls_static_optional)) ++ goto fail; ++ else if (optional) ++ GL(dl_tls_static_optional) -= use; ++ + map->l_tls_offset = offset; + map->l_tls_firstbyte_offset = GL(dl_tls_static_used); + GL(dl_tls_static_used) = used; +@@ -110,12 +126,15 @@ _dl_try_allocate_static_tls (struct link_map *map) + return 0; + } + ++/* This function intentionally does not return any value but signals error ++ directly, as static TLS should be rare and code handling it should ++ not be inlined as much as possible. */ + void + __attribute_noinline__ + _dl_allocate_static_tls (struct link_map *map) + { + if (map->l_tls_offset == FORCED_DYNAMIC_TLS_OFFSET +- || _dl_try_allocate_static_tls (map)) ++ || _dl_try_allocate_static_tls (map, false)) + { + _dl_signal_error (0, map->l_name, NULL, N_("\ + cannot allocate memory in static TLS block")); +diff --git a/elf/dl-tls.c b/elf/dl-tls.c +index cfda76f6de96df57..4f8c35b7d37bfc18 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -60,8 +60,6 @@ + This should be large enough to cover runtime libraries of the + compiler such as libgomp and libraries in libc other than libc.so. */ + #define OTHER_IE_TLS 144 +-/* Size of additional surplus TLS, placeholder for TLS optimizations. */ +-#define OPT_SURPLUS_TLS 512 + + /* Calculate the size of the static TLS surplus, when the given + number of audit modules are loaded. Must be called after the +@@ -69,13 +67,15 @@ + void + _dl_tls_static_surplus_init (size_t naudit) + { +- size_t nns; ++ size_t nns, opt_tls; + + #if HAVE_TUNABLES + nns = TUNABLE_GET (nns, size_t, NULL); ++ opt_tls = TUNABLE_GET (optional_static_tls, size_t, NULL); + #else + /* Default values of the tunables. */ + nns = 4; ++ opt_tls = 512; + #endif + if (nns > DL_NNS) + nns = DL_NNS; +@@ -84,9 +84,10 @@ _dl_tls_static_surplus_init (size_t naudit) + (unsigned long) naudit, (unsigned long) (DL_NNS - nns)); + nns += naudit; + ++ GL(dl_tls_static_optional) = opt_tls; + GLRO(dl_tls_static_surplus) = ((nns - 1) * LIBC_IE_TLS + + nns * OTHER_IE_TLS +- + OPT_SURPLUS_TLS); ++ + opt_tls); + } + + /* Out-of-memory handler. */ +diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list +index 7337fb85062c91a7..6408a8e5ae92d2c6 100644 +--- a/elf/dl-tunables.list ++++ b/elf/dl-tunables.list +@@ -134,5 +134,10 @@ glibc { + maxval: 16 + default: 4 + } ++ optional_static_tls { ++ type: SIZE_T ++ minval: 0 ++ default: 512 ++ } + } + } +diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h +index 9e9d5a3b28bc06c5..2fc3c91b7defe84e 100644 +--- a/elf/dynamic-link.h ++++ b/elf/dynamic-link.h +@@ -40,9 +40,10 @@ + (__builtin_expect ((sym_map)->l_tls_offset \ + != FORCED_DYNAMIC_TLS_OFFSET, 1) \ + && (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET, 1) \ +- || _dl_try_allocate_static_tls (sym_map) == 0)) ++ || _dl_try_allocate_static_tls (sym_map, true) == 0)) + +-int _dl_try_allocate_static_tls (struct link_map *map) attribute_hidden; ++int _dl_try_allocate_static_tls (struct link_map *map, bool optional) ++ attribute_hidden; + + #include + +diff --git a/elf/tst-tls-ie-dlmopen.c b/elf/tst-tls-ie-dlmopen.c +new file mode 100644 +index 0000000000000000..c7b5c688e362c861 +--- /dev/null ++++ b/elf/tst-tls-ie-dlmopen.c +@@ -0,0 +1,112 @@ ++/* Test dlopen of modules with initial-exec TLS after dlmopen. ++ Copyright (C) 2016-2020 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 ++ . */ ++ ++/* This test tries to check that surplus static TLS is not used up for ++ dynamic TLS optimizations and 4*144 = 576 bytes of static TLS is ++ still available for dlopening modules with initial-exec TLS after 3 ++ new dlmopen namespaces are created. It depends on rtld.nns=4 and ++ rtld.optional_static_tls=512 tunable settings. */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int do_test (void); ++#include ++#include ++#include ++#include ++ ++/* Have some big TLS in the main exe: should not use surplus TLS. */ ++__thread char maintls[1000]; ++ ++static pthread_barrier_t barrier; ++ ++/* Forces multi-threaded behaviour. */ ++static void * ++blocked_thread_func (void *closure) ++{ ++ xpthread_barrier_wait (&barrier); ++ /* TLS load and access tests run here in the main thread. */ ++ xpthread_barrier_wait (&barrier); ++ return NULL; ++} ++ ++static void * ++load_and_access (Lmid_t lmid, const char *mod, const char *func) ++{ ++ /* Load module with TLS. */ ++ void *p = xdlmopen (lmid, mod, RTLD_NOW); ++ /* Access the TLS variable to ensure it is allocated. */ ++ void (*f) (void) = (void (*) (void))xdlsym (p, func); ++ f (); ++ return p; ++} ++ ++static int ++do_test (void) ++{ ++ void *mods[5]; ++ ++ { ++ int ret = pthread_barrier_init (&barrier, NULL, 2); ++ if (ret != 0) ++ { ++ errno = ret; ++ printf ("error: pthread_barrier_init: %m\n"); ++ exit (1); ++ } ++ } ++ ++ pthread_t blocked_thread = xpthread_create (NULL, blocked_thread_func, NULL); ++ xpthread_barrier_wait (&barrier); ++ ++ printf ("maintls[%zu]:\t %p .. %p\n", ++ sizeof maintls, maintls, maintls + sizeof maintls); ++ memset (maintls, 1, sizeof maintls); ++ ++ /* Load modules with dynamic TLS (use surplus static TLS for libc ++ in new namespaces and may be for TLS optimizations too). */ ++ mods[0] = load_and_access (LM_ID_BASE, "tst-tls-ie-mod0.so", "access0"); ++ mods[1] = load_and_access (LM_ID_NEWLM, "tst-tls-ie-mod1.so", "access1"); ++ mods[2] = load_and_access (LM_ID_NEWLM, "tst-tls-ie-mod2.so", "access2"); ++ mods[3] = load_and_access (LM_ID_NEWLM, "tst-tls-ie-mod3.so", "access3"); ++ /* Load modules with initial-exec TLS (can only use surplus static TLS). */ ++ mods[4] = load_and_access (LM_ID_BASE, "tst-tls-ie-mod6.so", "access6"); ++ ++ /* Here 576 bytes + 3 * libc use of surplus static TLS is in use so less ++ than 1024 bytes are available (exact number depends on TLS optimizations ++ and the libc TLS use). */ ++ printf ("The next dlmopen should fail...\n"); ++ void *p = dlmopen (LM_ID_BASE, "tst-tls-ie-mod4.so", RTLD_NOW); ++ if (p != NULL) ++ FAIL_EXIT1 ("error: expected dlmopen to fail because there is " ++ "not enough surplus static TLS.\n"); ++ printf ("...OK failed with: %s.\n", dlerror ()); ++ ++ xpthread_barrier_wait (&barrier); ++ xpthread_join (blocked_thread); ++ ++ /* Close the modules. */ ++ for (int i = 0; i < 5; ++i) ++ xdlclose (mods[i]); ++ ++ return 0; ++} +diff --git a/elf/tst-tls-ie-mod.h b/elf/tst-tls-ie-mod.h +new file mode 100644 +index 0000000000000000..46b362a9b783d214 +--- /dev/null ++++ b/elf/tst-tls-ie-mod.h +@@ -0,0 +1,40 @@ ++/* Module with specified TLS size and model. ++ Copyright (C) 2020 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 ++ . */ ++ ++/* This file is parameterized by macros N, SIZE and MODEL. */ ++ ++#include ++#include ++ ++#define CONCATX(x, y) x ## y ++#define CONCAT(x, y) CONCATX (x, y) ++#define STRX(x) #x ++#define STR(x) STRX (x) ++ ++#define VAR CONCAT (var, N) ++ ++__attribute__ ((aligned (8), tls_model (MODEL))) ++__thread char VAR[SIZE]; ++ ++void ++CONCAT (access, N) (void) ++{ ++ printf (STR (VAR) "[%d]:\t %p .. %p " MODEL "\n", SIZE, VAR, VAR + SIZE); ++ fflush (stdout); ++ memset (VAR, 1, SIZE); ++} +diff --git a/elf/tst-tls-ie-mod0.c b/elf/tst-tls-ie-mod0.c +new file mode 100644 +index 0000000000000000..2450686e400e1141 +--- /dev/null ++++ b/elf/tst-tls-ie-mod0.c +@@ -0,0 +1,4 @@ ++#define N 0 ++#define SIZE 480 ++#define MODEL "global-dynamic" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie-mod1.c b/elf/tst-tls-ie-mod1.c +new file mode 100644 +index 0000000000000000..849ff91e53b0a518 +--- /dev/null ++++ b/elf/tst-tls-ie-mod1.c +@@ -0,0 +1,4 @@ ++#define N 1 ++#define SIZE 120 ++#define MODEL "global-dynamic" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie-mod2.c b/elf/tst-tls-ie-mod2.c +new file mode 100644 +index 0000000000000000..23915ab67bab0ada +--- /dev/null ++++ b/elf/tst-tls-ie-mod2.c +@@ -0,0 +1,4 @@ ++#define N 2 ++#define SIZE 24 ++#define MODEL "global-dynamic" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie-mod3.c b/elf/tst-tls-ie-mod3.c +new file mode 100644 +index 0000000000000000..5395f844a5999ea9 +--- /dev/null ++++ b/elf/tst-tls-ie-mod3.c +@@ -0,0 +1,4 @@ ++#define N 3 ++#define SIZE 16 ++#define MODEL "global-dynamic" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie-mod4.c b/elf/tst-tls-ie-mod4.c +new file mode 100644 +index 0000000000000000..93ac2eacae292d86 +--- /dev/null ++++ b/elf/tst-tls-ie-mod4.c +@@ -0,0 +1,4 @@ ++#define N 4 ++#define SIZE 1024 ++#define MODEL "initial-exec" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie-mod5.c b/elf/tst-tls-ie-mod5.c +new file mode 100644 +index 0000000000000000..84b3fd285b5b5a3e +--- /dev/null ++++ b/elf/tst-tls-ie-mod5.c +@@ -0,0 +1,4 @@ ++#define N 5 ++#define SIZE 128 ++#define MODEL "initial-exec" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie-mod6.c b/elf/tst-tls-ie-mod6.c +new file mode 100644 +index 0000000000000000..c736bf0684f3b08f +--- /dev/null ++++ b/elf/tst-tls-ie-mod6.c +@@ -0,0 +1,4 @@ ++#define N 6 ++#define SIZE 576 ++#define MODEL "initial-exec" ++#include "tst-tls-ie-mod.h" +diff --git a/elf/tst-tls-ie.c b/elf/tst-tls-ie.c +new file mode 100644 +index 0000000000000000..2dc0894480417389 +--- /dev/null ++++ b/elf/tst-tls-ie.c +@@ -0,0 +1,111 @@ ++/* Test dlopen of modules with initial-exec TLS. ++ Copyright (C) 2016-2020 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 ++ . */ ++ ++/* This test tries to check that surplus static TLS is not used up for ++ dynamic TLS optimizations and 3*192 + 4*144 = 1152 bytes of static ++ TLS is available for dlopening modules with initial-exec TLS. It ++ depends on rtld.nns=4 and rtld.optional_static_tls=512 tunable setting. */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++static int do_test (void); ++#include ++#include ++#include ++#include ++ ++/* Have some big TLS in the main exe: should not use surplus TLS. */ ++__thread char maintls[1000]; ++ ++static pthread_barrier_t barrier; ++ ++/* Forces multi-threaded behaviour. */ ++static void * ++blocked_thread_func (void *closure) ++{ ++ xpthread_barrier_wait (&barrier); ++ /* TLS load and access tests run here in the main thread. */ ++ xpthread_barrier_wait (&barrier); ++ return NULL; ++} ++ ++static void * ++load_and_access (const char *mod, const char *func) ++{ ++ /* Load module with TLS. */ ++ void *p = xdlopen (mod, RTLD_NOW); ++ /* Access the TLS variable to ensure it is allocated. */ ++ void (*f) (void) = (void (*) (void))xdlsym (p, func); ++ f (); ++ return p; ++} ++ ++static int ++do_test (void) ++{ ++ void *mods[6]; ++ ++ { ++ int ret = pthread_barrier_init (&barrier, NULL, 2); ++ if (ret != 0) ++ { ++ errno = ret; ++ printf ("error: pthread_barrier_init: %m\n"); ++ exit (1); ++ } ++ } ++ ++ pthread_t blocked_thread = xpthread_create (NULL, blocked_thread_func, NULL); ++ xpthread_barrier_wait (&barrier); ++ ++ printf ("maintls[%zu]:\t %p .. %p\n", ++ sizeof maintls, maintls, maintls + sizeof maintls); ++ memset (maintls, 1, sizeof maintls); ++ ++ /* Load modules with dynamic TLS (may use surplus static TLS ++ opportunistically). */ ++ mods[0] = load_and_access ("tst-tls-ie-mod0.so", "access0"); ++ mods[1] = load_and_access ("tst-tls-ie-mod1.so", "access1"); ++ mods[2] = load_and_access ("tst-tls-ie-mod2.so", "access2"); ++ mods[3] = load_and_access ("tst-tls-ie-mod3.so", "access3"); ++ /* Load modules with initial-exec TLS (can only use surplus static TLS). */ ++ mods[4] = load_and_access ("tst-tls-ie-mod4.so", "access4"); ++ mods[5] = load_and_access ("tst-tls-ie-mod5.so", "access5"); ++ ++ /* Here 1152 bytes of surplus static TLS is in use and at most 512 bytes ++ are available (depending on TLS optimizations). */ ++ printf ("The next dlopen should fail...\n"); ++ void *p = dlopen ("tst-tls-ie-mod6.so", RTLD_NOW); ++ if (p != NULL) ++ FAIL_EXIT1 ("error: expected dlopen to fail because there is " ++ "not enough surplus static TLS.\n"); ++ printf ("...OK failed with: %s.\n", dlerror ()); ++ ++ xpthread_barrier_wait (&barrier); ++ xpthread_join (blocked_thread); ++ ++ /* Close the modules. */ ++ for (int i = 0; i < 6; ++i) ++ xdlclose (mods[i]); ++ ++ return 0; ++} +diff --git a/manual/tunables.texi b/manual/tunables.texi +index e6a3e9a2cf5c959c..bd737b5d57080462 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -249,6 +249,23 @@ increase the per-thread memory usage as necessary, so this tunable does + not need to be changed to allow many audit modules e.g. via @env{LD_AUDIT}. + @end deftp + ++@deftp Tunable glibc.rtld.optional_static_tls ++Sets the amount of surplus static TLS in bytes to allocate at program ++startup. Every thread created allocates this amount of specified surplus ++static TLS. This is a minimum value and additional space may be allocated ++for internal purposes including alignment. Optional static TLS is used for ++optimizing dynamic TLS access for platforms that support such optimizations ++e.g. TLS descriptors or optimized TLS access for POWER (@code{DT_PPC64_OPT} ++and @code{DT_PPC_OPT}). In order to make the best use of such optimizations ++the value should be as many bytes as would be required to hold all TLS ++variables in all dynamic loaded shared libraries. The value cannot be known ++by the dynamic loader because it doesn't know the expected set of shared ++libraries which will be loaded. The existing static TLS space cannot be ++changed once allocated at process startup. The default allocation of ++optional static TLS is 512 bytes and is allocated in every thread. ++@end deftp ++ ++ + @node Elision Tunables + @section Elision Tunables + @cindex elision tunables +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 293f3ab5a496afdf..37f1915b0c75a020 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -441,6 +441,9 @@ struct rtld_global + EXTERN size_t _dl_tls_static_used; + /* Alignment requirement of the static TLS block. */ + EXTERN size_t _dl_tls_static_align; ++ /* Remaining amount of static TLS that may be used for optimizing ++ dynamic TLS access (e.g. with TLSDESC). */ ++ EXTERN size_t _dl_tls_static_optional; + + /* Number of additional entries in the slotinfo array of each slotinfo + list element. A large number makes it almost certain take we never diff --git a/glibc-rh1817513-8.patch b/glibc-rh1817513-8.patch new file mode 100755 index 0000000..5f82d23 --- /dev/null +++ b/glibc-rh1817513-8.patch @@ -0,0 +1,74 @@ +commit d90c9b1a121295a5e31810b899ab637f68898857 +Author: Joseph Myers +Date: Thu Sep 20 12:43:41 2018 +0000 + + Invert sense of list of i686-class processors in sysdeps/x86/cpu-features.h. + + I noticed that sysdeps/x86/cpu-features.h had conditionals on whether + to define HAS_CPUID, HAS_I586 and HAS_I686 with a long list of + preprocessor macros for i686-and-later processors which however was + out of date. This patch avoids the problem of the list getting out of + date by instead having conditionals on all the (few, old) pre-i686 + processors for which GCC has preprocessor macros, rather than the + (many, expanding list) i686-and-later processors. It seems HAS_I586 + and HAS_I686 are unused so the only effect of these macros being + missing is that 32-bit glibc built for one of these processors would + end up doing runtime detection of CPUID availability. + + i386 builds are prevented by a configure test so there is no need to + allow for them here. __geode__ (no long nops?) and __k6__ (no CMOV, + at least according to GCC) are conservatively handled as i586, not + i686, here (as noted above, this is a theoretical distinction at + present in that only HAS_CPUID appears to be used). + + Tested for x86. + + * sysdeps/x86/cpu-features.h [__geode__ || __k6__]: Handle like + [__i586__ || __pentium__]. + [__i486__]: Handle explicitly. + (HAS_CPUID): Define to 1 if above macros are undefined. + (HAS_I586): Likewise. + (HAS_I686): Likewise. + +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index d342664c64ab7aa1..fb22d7b9d6226a92 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -257,30 +257,19 @@ extern const struct cpu_features *__get_cpu_features (void) + + #ifdef __x86_64__ + # define HAS_CPUID 1 +-#elif defined __i586__ || defined __pentium__ ++#elif (defined __i586__ || defined __pentium__ \ ++ || defined __geode__ || defined __k6__) + # define HAS_CPUID 1 + # define HAS_I586 1 + # define HAS_I686 HAS_ARCH_FEATURE (I686) +-#elif (defined __i686__ || defined __pentiumpro__ \ +- || defined __pentium4__ || defined __nocona__ \ +- || defined __atom__ || defined __core2__ \ +- || defined __corei7__ || defined __corei7_avx__ \ +- || defined __core_avx2__ || defined __nehalem__ \ +- || defined __sandybridge__ || defined __haswell__ \ +- || defined __knl__ || defined __bonnell__ \ +- || defined __silvermont__ \ +- || defined __k6__ || defined __k8__ \ +- || defined __athlon__ || defined __amdfam10__ \ +- || defined __bdver1__ || defined __bdver2__ \ +- || defined __bdver3__ || defined __bdver4__ \ +- || defined __btver1__ || defined __btver2__) +-# define HAS_CPUID 1 +-# define HAS_I586 1 +-# define HAS_I686 1 +-#else ++#elif defined __i486__ + # define HAS_CPUID 0 + # define HAS_I586 HAS_ARCH_FEATURE (I586) + # define HAS_I686 HAS_ARCH_FEATURE (I686) ++#else ++# define HAS_CPUID 1 ++# define HAS_I586 1 ++# define HAS_I686 1 + #endif + + #endif /* cpu_features_h */ diff --git a/glibc-rh1817513-80.patch b/glibc-rh1817513-80.patch new file mode 100755 index 0000000..1f83e15 --- /dev/null +++ b/glibc-rh1817513-80.patch @@ -0,0 +1,151 @@ +commit 07ed32f920f0bcb1ddb400e4ed606104756dee32 +Author: Florian Weimer +Date: Mon Jul 20 13:30:45 2020 +0200 + + elf: Change TLS static surplus default back to 1664 + + Make the computation in elf/dl-tls.c more transparent, and add + an explicit test for the historic value. + + Reviewed-by: Carlos O'Donell + +Conflicts: + elf/Makefile + (Missing test backports.) + elf/dl-tls.c + (Missing backport of rseq and its revert.) + +diff --git a/elf/Makefile b/elf/Makefile +index 8b96bfefd852b79f..82b5b4a07495c805 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -204,7 +204,7 @@ tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ + tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \ + tst-ptrguard1 tst-stackguard1 tst-libc_dlvsym \ +- tst-create_format1 ++ tst-create_format1 tst-tls-surplus + tests-container += tst-pldd + ifeq ($(build-hardcoded-path-in-tests),yes) + tests += tst-dlopen-aout +@@ -1714,3 +1714,5 @@ $(objpfx)tst-tls-ie-dlmopen.out: \ + $(objpfx)tst-tls-ie-mod4.so \ + $(objpfx)tst-tls-ie-mod5.so \ + $(objpfx)tst-tls-ie-mod6.so ++ ++$(objpfx)tst-tls-surplus: $(libdl) +diff --git a/elf/dl-tls.c b/elf/dl-tls.c +index 4f8c35b7d37bfc18..cccf74b33481b866 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -54,13 +54,37 @@ + Audit modules use their own namespaces, they are not included in rtld.nns, + but come on top when computing the number of namespaces. */ + +-/* Size of initial-exec TLS in libc.so. */ +-#define LIBC_IE_TLS 192 ++/* Size of initial-exec TLS in libc.so. This should be the maximum of ++ observed PT_GNU_TLS sizes across all architectures. Some ++ architectures have lower values due to differences in type sizes ++ and link editor capabilities. */ ++#define LIBC_IE_TLS 144 ++ + /* Size of initial-exec TLS in libraries other than libc.so. + This should be large enough to cover runtime libraries of the + compiler such as libgomp and libraries in libc other than libc.so. */ + #define OTHER_IE_TLS 144 + ++/* Default number of namespaces. */ ++#define DEFAULT_NNS 4 ++ ++/* Default for dl_tls_static_optional. */ ++#define OPTIONAL_TLS 512 ++ ++/* Compute the static TLS surplus based on the namespace count and the ++ TLS space that can be used for optimizations. */ ++static inline int ++tls_static_surplus (int nns, int opt_tls) ++{ ++ return (nns - 1) * LIBC_IE_TLS + nns * OTHER_IE_TLS + opt_tls; ++} ++ ++/* This value is chosen so that with default values for the tunables, ++ the computation of dl_tls_static_surplus in ++ _dl_tls_static_surplus_init yields the historic value 1664, for ++ backwards compatibility. */ ++#define LEGACY_TLS (1664 - tls_static_surplus (DEFAULT_NNS, OPTIONAL_TLS)) ++ + /* Calculate the size of the static TLS surplus, when the given + number of audit modules are loaded. Must be called after the + number of audit modules is known and before static TLS allocation. */ +@@ -74,8 +98,8 @@ _dl_tls_static_surplus_init (size_t naudit) + opt_tls = TUNABLE_GET (optional_static_tls, size_t, NULL); + #else + /* Default values of the tunables. */ +- nns = 4; +- opt_tls = 512; ++ nns = DEFAULT_NNS; ++ opt_tls = OPTIONAL_TLS; + #endif + if (nns > DL_NNS) + nns = DL_NNS; +@@ -85,9 +109,8 @@ _dl_tls_static_surplus_init (size_t naudit) + nns += naudit; + + GL(dl_tls_static_optional) = opt_tls; +- GLRO(dl_tls_static_surplus) = ((nns - 1) * LIBC_IE_TLS +- + nns * OTHER_IE_TLS +- + opt_tls); ++ assert (LEGACY_TLS >= 0); ++ GLRO(dl_tls_static_surplus) = tls_static_surplus (nns, opt_tls) + LEGACY_TLS; + } + + /* Out-of-memory handler. */ +diff --git a/elf/tst-tls-surplus.c b/elf/tst-tls-surplus.c +new file mode 100644 +index 0000000000000000..b0dea0b5ee178ddd +--- /dev/null ++++ b/elf/tst-tls-surplus.c +@@ -0,0 +1,42 @@ ++/* Test size of the static TLS surplus reservation for backwards compatibility. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++static int do_test (void); ++#include ++ ++/* This hack results in a definition of struct rtld_global_ro. Do ++ this after all the other header inclusions, to minimize the ++ impact. */ ++#define SHARED ++#include ++ ++static ++int do_test (void) ++{ ++ /* Avoid introducing a copy relocation due to the hidden alias in ++ ld.so. */ ++ struct rtld_global_ro *glro = xdlsym (NULL, "_rtld_global_ro"); ++ printf ("info: _dl_tls_static_surplus: %zu\n", glro->_dl_tls_static_surplus); ++ /* Hisoric value: 16 * 100 + 64. */ ++ TEST_VERIFY (glro->_dl_tls_static_surplus >= 1664); ++ return 0; ++} diff --git a/glibc-rh1817513-81.patch b/glibc-rh1817513-81.patch new file mode 100755 index 0000000..1a035bc --- /dev/null +++ b/glibc-rh1817513-81.patch @@ -0,0 +1,137 @@ +commit ac3bda9a251f1512650f7b2c10d711c740ee0b78 +Author: H.J. Lu +Date: Wed Aug 5 08:20:52 2020 -0700 + + x86: Rename Intel CPU feature names + + Intel64 and IA-32 Architectures Software Developer’s Manual has changed + the following CPU feature names: + + 1. The CPU feature of Enhanced Intel SpeedStep Technology is renamed + from EST to EIST. + 2. The CPU feature which supports Platform Quality of Service Monitoring + (PQM) capability is changed to Intel Resource Director Technology + (Intel RDT) Monitoring capability, i.e. PQM is renamed to RDT_M. + 3. The CPU feature which supports Platform Quality of Service + Enforcement (PQE) capability is changed to Intel Resource Director + Technology (Intel RDT) Allocation capability, i.e. PQE is renamed to + RDT_A. + +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/cpu-features.h +index 21708c028a12dbb2..3b401d441b8d370a 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/cpu-features.h +@@ -156,7 +156,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_DS_CPL (1u << 4) + #define bit_cpu_VMX (1u << 5) + #define bit_cpu_SMX (1u << 6) +-#define bit_cpu_EST (1u << 7) ++#define bit_cpu_EIST (1u << 7) + #define bit_cpu_TM2 (1u << 8) + #define bit_cpu_SSSE3 (1u << 9) + #define bit_cpu_CNXT_ID (1u << 10) +@@ -231,10 +231,10 @@ extern const struct cpu_features *__get_cpu_features (void) + #define bit_cpu_ERMS (1u << 9) + #define bit_cpu_INVPCID (1u << 10) + #define bit_cpu_RTM (1u << 11) +-#define bit_cpu_PQM (1u << 12) ++#define bit_cpu_RDT_M (1u << 12) + #define bit_cpu_DEPR_FPU_CS_DS (1u << 13) + #define bit_cpu_MPX (1u << 14) +-#define bit_cpu_PQE (1u << 15) ++#define bit_cpu_RDT_A (1u << 15) + #define bit_cpu_AVX512F (1u << 16) + #define bit_cpu_AVX512DQ (1u << 17) + #define bit_cpu_RDSEED (1u << 18) +@@ -371,7 +371,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_DS_CPL COMMON_CPUID_INDEX_1 + #define index_cpu_VMX COMMON_CPUID_INDEX_1 + #define index_cpu_SMX COMMON_CPUID_INDEX_1 +-#define index_cpu_EST COMMON_CPUID_INDEX_1 ++#define index_cpu_EIST COMMON_CPUID_INDEX_1 + #define index_cpu_TM2 COMMON_CPUID_INDEX_1 + #define index_cpu_SSSE3 COMMON_CPUID_INDEX_1 + #define index_cpu_CNXT_ID COMMON_CPUID_INDEX_1 +@@ -446,10 +446,10 @@ extern const struct cpu_features *__get_cpu_features (void) + #define index_cpu_ERMS COMMON_CPUID_INDEX_7 + #define index_cpu_INVPCID COMMON_CPUID_INDEX_7 + #define index_cpu_RTM COMMON_CPUID_INDEX_7 +-#define index_cpu_PQM COMMON_CPUID_INDEX_7 ++#define index_cpu_RDT_M COMMON_CPUID_INDEX_7 + #define index_cpu_DEPR_FPU_CS_DS COMMON_CPUID_INDEX_7 + #define index_cpu_MPX COMMON_CPUID_INDEX_7 +-#define index_cpu_PQE COMMON_CPUID_INDEX_7 ++#define index_cpu_RDT_A COMMON_CPUID_INDEX_7 + #define index_cpu_AVX512F COMMON_CPUID_INDEX_7 + #define index_cpu_AVX512DQ COMMON_CPUID_INDEX_7 + #define index_cpu_RDSEED COMMON_CPUID_INDEX_7 +@@ -584,7 +584,7 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_DS_CPL ecx + #define reg_VMX ecx + #define reg_SMX ecx +-#define reg_EST ecx ++#define reg_EIST ecx + #define reg_TM2 ecx + #define reg_SSSE3 ecx + #define reg_CNXT_ID ecx +@@ -659,10 +659,10 @@ extern const struct cpu_features *__get_cpu_features (void) + #define reg_ERMS ebx + #define reg_INVPCID ebx + #define reg_RTM ebx +-#define reg_PQM ebx ++#define reg_RDT_M ebx + #define reg_DEPR_FPU_CS_DS ebx + #define reg_MPX ebx +-#define reg_PQE ebx ++#define reg_RDT_A ebx + #define reg_AVX512F ebx + #define reg_AVX512DQ ebx + #define reg_RDSEED ebx +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index 85ec9d5a091e2c88..582b125a2dad3f21 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -73,7 +73,7 @@ do_test (void) + CHECK_CPU_FEATURE (DS_CPL); + CHECK_CPU_FEATURE (VMX); + CHECK_CPU_FEATURE (SMX); +- CHECK_CPU_FEATURE (EST); ++ CHECK_CPU_FEATURE (EIST); + CHECK_CPU_FEATURE (TM2); + CHECK_CPU_FEATURE (SSSE3); + CHECK_CPU_FEATURE (CNXT_ID); +@@ -136,10 +136,10 @@ do_test (void) + CHECK_CPU_FEATURE (ERMS); + CHECK_CPU_FEATURE (INVPCID); + CHECK_CPU_FEATURE (RTM); +- CHECK_CPU_FEATURE (PQM); ++ CHECK_CPU_FEATURE (RDT_M); + CHECK_CPU_FEATURE (DEPR_FPU_CS_DS); + CHECK_CPU_FEATURE (MPX); +- CHECK_CPU_FEATURE (PQE); ++ CHECK_CPU_FEATURE (RDT_A); + CHECK_CPU_FEATURE (AVX512F); + CHECK_CPU_FEATURE (AVX512DQ); + CHECK_CPU_FEATURE (RDSEED); +@@ -226,7 +226,7 @@ do_test (void) + CHECK_CPU_FEATURE_USABLE (DS_CPL); + CHECK_CPU_FEATURE_USABLE (VMX); + CHECK_CPU_FEATURE_USABLE (SMX); +- CHECK_CPU_FEATURE_USABLE (EST); ++ CHECK_CPU_FEATURE_USABLE (EIST); + CHECK_CPU_FEATURE_USABLE (TM2); + CHECK_CPU_FEATURE_USABLE (SSSE3); + CHECK_CPU_FEATURE_USABLE (CNXT_ID); +@@ -289,10 +289,10 @@ do_test (void) + CHECK_CPU_FEATURE_USABLE (ERMS); + CHECK_CPU_FEATURE_USABLE (INVPCID); + CHECK_CPU_FEATURE_USABLE (RTM); +- CHECK_CPU_FEATURE_USABLE (PQM); ++ CHECK_CPU_FEATURE_USABLE (RDT_M); + CHECK_CPU_FEATURE_USABLE (DEPR_FPU_CS_DS); + CHECK_CPU_FEATURE_USABLE (MPX); +- CHECK_CPU_FEATURE_USABLE (PQE); ++ CHECK_CPU_FEATURE_USABLE (RDT_A); + CHECK_CPU_FEATURE_USABLE (AVX512F); + CHECK_CPU_FEATURE_USABLE (AVX512DQ); + CHECK_CPU_FEATURE_USABLE (RDSEED); diff --git a/glibc-rh1817513-82.patch b/glibc-rh1817513-82.patch new file mode 100755 index 0000000..6a04b8c --- /dev/null +++ b/glibc-rh1817513-82.patch @@ -0,0 +1,178 @@ +commit 04bba1e5d84b6fd8d3a3b006bc240cd5d241ee30 +Author: H.J. Lu +Date: Wed Aug 5 13:51:56 2020 -0700 + + x86: Set CPU usable feature bits conservatively [BZ #26552] + + Set CPU usable feature bits only for CPU features which are usable in + user space and whose usability can be detected from user space, excluding + features like FSGSBASE whose enable bit can only be checked in the kernel. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index f13a1df4555c7000..6954728c47d0126b 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -44,107 +44,55 @@ extern void TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *) + static void + update_usable (struct cpu_features *cpu_features) + { +- /* Before COMMON_CPUID_INDEX_80000001, copy the cpuid array elements to +- the usable array. */ +- unsigned int i; +- for (i = 0; i < COMMON_CPUID_INDEX_80000001; i++) +- cpu_features->features[i].usable = cpu_features->features[i].cpuid; +- +- /* Before COMMON_CPUID_INDEX_80000001, clear the unknown usable bits +- and the always zero bits. */ +- CPU_FEATURE_UNSET (cpu_features, INDEX_1_ECX_16); +- CPU_FEATURE_UNSET (cpu_features, INDEX_1_ECX_31); +- CPU_FEATURE_UNSET (cpu_features, INDEX_1_EDX_10); +- CPU_FEATURE_UNSET (cpu_features, INDEX_1_EDX_20); +- CPU_FEATURE_UNSET (cpu_features, INDEX_1_EDX_30); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EBX_6); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EBX_22); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_ECX_13); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_ECX_15); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_ECX_16); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_ECX_23); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_ECX_24); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_ECX_26); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_0); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_1); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_5); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_6); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_7); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_9); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_11); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_12); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_13); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_17); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_19); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_21); +- CPU_FEATURE_UNSET (cpu_features, INDEX_7_EDX_23); +- +- /* EAX/EBX from COMMON_CPUID_INDEX_1 and EAX from COMMON_CPUID_INDEX_7 +- aren't used for CPU feature detection. */ +- cpu_features->features[COMMON_CPUID_INDEX_1].usable.eax = 0; +- cpu_features->features[COMMON_CPUID_INDEX_1].usable.ebx = 0; +- cpu_features->features[COMMON_CPUID_INDEX_7].usable.eax = 0; +- +- /* Starting from COMMON_CPUID_INDEX_80000001, copy the cpuid bits to +- usable bits. */ ++ /* Copy the cpuid bits to usable bits for CPU featuress whose usability ++ in user space can be detected without additonal OS support. */ ++ CPU_FEATURE_SET_USABLE (cpu_features, SSE3); ++ CPU_FEATURE_SET_USABLE (cpu_features, PCLMULQDQ); ++ CPU_FEATURE_SET_USABLE (cpu_features, SSSE3); ++ CPU_FEATURE_SET_USABLE (cpu_features, CMPXCHG16B); ++ CPU_FEATURE_SET_USABLE (cpu_features, SSE4_1); ++ CPU_FEATURE_SET_USABLE (cpu_features, SSE4_2); ++ CPU_FEATURE_SET_USABLE (cpu_features, MOVBE); ++ CPU_FEATURE_SET_USABLE (cpu_features, POPCNT); ++ CPU_FEATURE_SET_USABLE (cpu_features, AES); ++ CPU_FEATURE_SET_USABLE (cpu_features, OSXSAVE); ++ CPU_FEATURE_SET_USABLE (cpu_features, TSC); ++ CPU_FEATURE_SET_USABLE (cpu_features, CX8); ++ CPU_FEATURE_SET_USABLE (cpu_features, CMOV); ++ CPU_FEATURE_SET_USABLE (cpu_features, CLFSH); ++ CPU_FEATURE_SET_USABLE (cpu_features, MMX); ++ CPU_FEATURE_SET_USABLE (cpu_features, FXSR); ++ CPU_FEATURE_SET_USABLE (cpu_features, SSE); ++ CPU_FEATURE_SET_USABLE (cpu_features, SSE2); ++ CPU_FEATURE_SET_USABLE (cpu_features, HTT); ++ CPU_FEATURE_SET_USABLE (cpu_features, BMI1); ++ CPU_FEATURE_SET_USABLE (cpu_features, HLE); ++ CPU_FEATURE_SET_USABLE (cpu_features, BMI2); ++ CPU_FEATURE_SET_USABLE (cpu_features, ERMS); ++ CPU_FEATURE_SET_USABLE (cpu_features, RTM); ++ CPU_FEATURE_SET_USABLE (cpu_features, RDSEED); ++ CPU_FEATURE_SET_USABLE (cpu_features, ADX); ++ CPU_FEATURE_SET_USABLE (cpu_features, CLFLUSHOPT); ++ CPU_FEATURE_SET_USABLE (cpu_features, CLWB); ++ CPU_FEATURE_SET_USABLE (cpu_features, SHA); ++ CPU_FEATURE_SET_USABLE (cpu_features, PREFETCHWT1); ++ CPU_FEATURE_SET_USABLE (cpu_features, OSPKE); ++ CPU_FEATURE_SET_USABLE (cpu_features, WAITPKG); ++ CPU_FEATURE_SET_USABLE (cpu_features, GFNI); ++ CPU_FEATURE_SET_USABLE (cpu_features, RDPID); ++ CPU_FEATURE_SET_USABLE (cpu_features, CLDEMOTE); ++ CPU_FEATURE_SET_USABLE (cpu_features, MOVDIRI); ++ CPU_FEATURE_SET_USABLE (cpu_features, MOVDIR64B); ++ CPU_FEATURE_SET_USABLE (cpu_features, FSRM); ++ CPU_FEATURE_SET_USABLE (cpu_features, SERIALIZE); ++ CPU_FEATURE_SET_USABLE (cpu_features, TSXLDTRK); + CPU_FEATURE_SET_USABLE (cpu_features, LAHF64_SAHF64); +- CPU_FEATURE_SET_USABLE (cpu_features, SVM); + CPU_FEATURE_SET_USABLE (cpu_features, LZCNT); + CPU_FEATURE_SET_USABLE (cpu_features, SSE4A); + CPU_FEATURE_SET_USABLE (cpu_features, PREFETCHW); +- CPU_FEATURE_SET_USABLE (cpu_features, XOP); +- CPU_FEATURE_SET_USABLE (cpu_features, LWP); +- CPU_FEATURE_SET_USABLE (cpu_features, FMA4); + CPU_FEATURE_SET_USABLE (cpu_features, TBM); +- CPU_FEATURE_SET_USABLE (cpu_features, SYSCALL_SYSRET); +- CPU_FEATURE_SET_USABLE (cpu_features, NX); +- CPU_FEATURE_SET_USABLE (cpu_features, PAGE1GB); + CPU_FEATURE_SET_USABLE (cpu_features, RDTSCP); +- CPU_FEATURE_SET_USABLE (cpu_features, LM); +- CPU_FEATURE_SET_USABLE (cpu_features, XSAVEOPT); +- CPU_FEATURE_SET_USABLE (cpu_features, XSAVEC); +- CPU_FEATURE_SET_USABLE (cpu_features, XGETBV_ECX_1); +- CPU_FEATURE_SET_USABLE (cpu_features, XSAVES); +- CPU_FEATURE_SET_USABLE (cpu_features, XFD); +- CPU_FEATURE_SET_USABLE (cpu_features, INVARIANT_TSC); + CPU_FEATURE_SET_USABLE (cpu_features, WBNOINVD); +- CPU_FEATURE_SET_USABLE (cpu_features, AVX512_BF16); +- +- /* MPX has been deprecated. */ +- CPU_FEATURE_UNSET (cpu_features, MPX); +- +- /* Clear the usable bits which require OS support. */ +- CPU_FEATURE_UNSET (cpu_features, FMA); +- CPU_FEATURE_UNSET (cpu_features, AVX); +- CPU_FEATURE_UNSET (cpu_features, F16C); +- CPU_FEATURE_UNSET (cpu_features, AVX2); +- CPU_FEATURE_UNSET (cpu_features, AVX512F); +- CPU_FEATURE_UNSET (cpu_features, AVX512DQ); +- CPU_FEATURE_UNSET (cpu_features, AVX512_IFMA); +- CPU_FEATURE_UNSET (cpu_features, AVX512PF); +- CPU_FEATURE_UNSET (cpu_features, AVX512ER); +- CPU_FEATURE_UNSET (cpu_features, AVX512CD); +- CPU_FEATURE_UNSET (cpu_features, AVX512BW); +- CPU_FEATURE_UNSET (cpu_features, AVX512VL); +- CPU_FEATURE_UNSET (cpu_features, AVX512_VBMI); +- CPU_FEATURE_UNSET (cpu_features, PKU); +- CPU_FEATURE_UNSET (cpu_features, AVX512_VBMI2); +- CPU_FEATURE_UNSET (cpu_features, VAES); +- CPU_FEATURE_UNSET (cpu_features, VPCLMULQDQ); +- CPU_FEATURE_UNSET (cpu_features, AVX512_VNNI); +- CPU_FEATURE_UNSET (cpu_features, AVX512_BITALG); +- CPU_FEATURE_UNSET (cpu_features, AVX512_VPOPCNTDQ); +- CPU_FEATURE_UNSET (cpu_features, AVX512_4VNNIW); +- CPU_FEATURE_UNSET (cpu_features, AVX512_4FMAPS); +- CPU_FEATURE_UNSET (cpu_features, AVX512_VP2INTERSECT); +- CPU_FEATURE_UNSET (cpu_features, AMX_BF16); +- CPU_FEATURE_UNSET (cpu_features, AMX_TILE); +- CPU_FEATURE_UNSET (cpu_features, AMX_INT8); +- CPU_FEATURE_UNSET (cpu_features, XOP); +- CPU_FEATURE_UNSET (cpu_features, FMA4); +- CPU_FEATURE_UNSET (cpu_features, XSAVEC); +- CPU_FEATURE_UNSET (cpu_features, XFD); +- CPU_FEATURE_UNSET (cpu_features, AVX512_BF16); + + /* Can we call xgetbv? */ + if (CPU_FEATURES_CPU_P (cpu_features, OSXSAVE)) +@@ -243,8 +191,11 @@ update_usable (struct cpu_features *cpu_features) + CPU_FEATURE_SET_USABLE (cpu_features, AMX_INT8); + } + +- +- /* XFD is usable only when OSXSAVE is enabled. */ ++ /* These features are usable only when OSXSAVE is enabled. */ ++ CPU_FEATURE_SET (cpu_features, XSAVE); ++ CPU_FEATURE_SET_USABLE (cpu_features, XSAVEOPT); ++ CPU_FEATURE_SET_USABLE (cpu_features, XSAVEC); ++ CPU_FEATURE_SET_USABLE (cpu_features, XGETBV_ECX_1); + CPU_FEATURE_SET_USABLE (cpu_features, XFD); + + /* For _dl_runtime_resolve, set xsave_state_size to xsave area diff --git a/glibc-rh1817513-83.patch b/glibc-rh1817513-83.patch new file mode 100755 index 0000000..f3b8f3a --- /dev/null +++ b/glibc-rh1817513-83.patch @@ -0,0 +1,1664 @@ +commit 9620398097de3981c1adf5233e2b3478d36bc1b3 +Author: H.J. Lu +Date: Mon Jun 29 18:30:54 2020 -0700 + + x86: Install [BZ #26124] + + Install so that programmers can do + + #if __has_include() + #include + #endif + ... + + if (CPU_FEATURE_USABLE (SSE2)) + ... + if (CPU_FEATURE_USABLE (AVX2)) + ... + + exports only: + + enum + { + COMMON_CPUID_INDEX_1 = 0, + COMMON_CPUID_INDEX_7, + COMMON_CPUID_INDEX_80000001, + COMMON_CPUID_INDEX_D_ECX_1, + COMMON_CPUID_INDEX_80000007, + COMMON_CPUID_INDEX_80000008, + COMMON_CPUID_INDEX_7_ECX_1, + /* Keep the following line at the end. */ + COMMON_CPUID_INDEX_MAX + }; + + struct cpuid_features + { + struct cpuid_registers cpuid; + struct cpuid_registers usable; + }; + + struct cpu_features + { + struct cpu_features_basic basic; + struct cpuid_features features[COMMON_CPUID_INDEX_MAX]; + }; + + /* Get a pointer to the CPU features structure. */ + extern const struct cpu_features *__x86_get_cpu_features + (unsigned int max) __attribute__ ((const)); + + Since all feature checks are done through macros, programs compiled with + a newer are compatible with the older glibc binaries + as long as the layout of struct cpu_features is identical. The features + array can be expanded with backward binary compatibility for both .o and + .so files. When COMMON_CPUID_INDEX_MAX is increased to support new + processor features, __x86_get_cpu_features in the older glibc binaries + returns NULL and HAS_CPU_FEATURE/CPU_FEATURE_USABLE return false on the + new processor feature. No new symbol version is neeeded. + + Both CPU_FEATURE_USABLE and HAS_CPU_FEATURE are provided. HAS_CPU_FEATURE + can be used to identify processor features. + + Note: Although GCC has __builtin_cpu_supports, it only supports a subset + of and it is equivalent to CPU_FEATURE_USABLE. It + doesn't support HAS_CPU_FEATURE. + +Conflicts: + sysdeps/x86/sys/platform/x86.h + sysdeps/x86/tst-get-cpu-features.c + sysdeps/x86_64/multiarch/test-multiarch.c + (Copyright year, URL differences.) + +Downstream changes: Do not install , +and use a GLIBC_PRIVATE symbol for __x86_get_cpu_features. + +diff --git a/manual/platform.texi b/manual/platform.texi +index 504addc956086820..2c145acdc3564cbb 100644 +--- a/manual/platform.texi ++++ b/manual/platform.texi +@@ -7,6 +7,7 @@ + @menu + * PowerPC:: Facilities Specific to the PowerPC Architecture + * RISC-V:: Facilities Specific to the RISC-V Architecture ++* X86:: Facilities Specific to the X86 Architecture + @end menu + + @node PowerPC +@@ -134,3 +135,519 @@ all threads in the current process. Setting the + ordering on only the current thread is necessary. All other flag bits are + reserved. + @end deftypefun ++ ++@node X86 ++@appendixsec X86-specific Facilities ++ ++Facilities specific to X86 that are not specific to a particular ++operating system are declared in @file{sys/platform/x86.h}. ++ ++@deftypefun {const struct cpu_features *} __x86_get_cpu_features (unsigned int @var{max}) ++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} ++Return a pointer to x86 CPU feature structure used by query macros for x86 ++CPU features. If @var{max} exceeds @code{COMMON_CPUID_INDEX_MAX} which ++is the limit of the CPUID leaves supported by @Theglibc{}, the function ++returns @code{NULL}, indicating that the queried processor feature is ++unsupported by @Theglibc{} run-time. ++@end deftypefun ++ ++@deftypefn Macro int HAS_CPU_FEATURE (@var{name}) ++This macro returns a nonzero value (true) if the processor has the feature ++@var{name}. ++@end deftypefn ++ ++@deftypefn Macro int CPU_FEATURE_USABLE (@var{name}) ++This macro returns a nonzero value (true) if the processor has the feature ++@var{name} and the feature is supported by the operating system. ++@end deftypefn ++ ++The supported processor features are: ++ ++@itemize @bullet ++ ++@item ++@code{ACPI} -- Thermal Monitor and Software Controlled Clock Facilities. ++ ++@item ++@code{ADX} -- ADX instruction extensions. ++ ++@item ++@code{APIC} -- APIC On-Chip. ++ ++@item ++@code{AES} -- The AES instruction extensions. ++ ++@item ++@code{AMX_BF16} -- Tile computational operations on bfloat16 numbers. ++ ++@item ++@code{AMX_INT8} -- Tile computational operations on 8-bit numbers. ++ ++@item ++@code{AMX_TILE} -- Tile architecture. ++ ++@item ++@code{ARCH_CAPABILITIES} -- IA32_ARCH_CAPABILITIES MSR. ++ ++@item ++@code{AVX} -- The AVX instruction extensions. ++ ++@item ++@code{AVX2} -- The AVX2 instruction extensions. ++ ++@item ++@code{AVX512_4FMAPS} -- The AVX512_4FMAPS instruction extensions. ++ ++@item ++@code{AVX512_4VNNIW} -- The AVX512_4VNNIW instruction extensions. ++ ++@item ++@code{AVX512_BF16} -- The AVX512_BF16 instruction extensions. ++ ++@item ++@code{AVX512_BITALG} -- The AVX512_BITALG instruction extensions. ++ ++@item ++@code{AVX512_IFMA} -- The AVX512_IFMA instruction extensions. ++ ++@item ++@code{AVX512_VBMI} -- The AVX512_VBMI instruction extensions. ++ ++@item ++@code{AVX512_VBMI2} -- The AVX512_VBMI2 instruction extensions. ++ ++@item ++@code{AVX512_VNNI} -- The AVX512_VNNI instruction extensions. ++ ++@item ++@code{AVX512_VP2INTERSECT} -- The AVX512_VP2INTERSECT instruction ++extensions. ++ ++@item ++@code{AVX512_VPOPCNTDQ} -- The AVX512_VPOPCNTDQ instruction extensions. ++ ++@item ++@code{AVX512BW} -- The AVX512BW instruction extensions. ++ ++@item ++@code{AVX512CD} -- The AVX512CD instruction extensions. ++ ++@item ++@code{AVX512ER} -- The AVX512ER instruction extensions. ++ ++@item ++@code{AVX512DQ} -- The AVX512DQ instruction extensions. ++ ++@item ++@code{AVX512F} -- The AVX512F instruction extensions. ++ ++@item ++@code{AVX512PF} -- The AVX512PF instruction extensions. ++ ++@item ++@code{AVX512VL} -- The AVX512VL instruction extensions. ++ ++@item ++@code{BMI1} -- BMI1 instructions. ++ ++@item ++@code{BMI2} -- BMI2 instructions. ++ ++@item ++@code{CLDEMOTE} -- CLDEMOTE instruction. ++ ++@item ++@code{CLFLUSHOPT} -- CLFLUSHOPT instruction. ++ ++@item ++@code{CLFSH} -- CLFLUSH instruction. ++ ++@item ++@code{CLWB} -- CLWB instruction. ++ ++@item ++@code{CMOV} -- Conditional Move instructions. ++ ++@item ++@code{CMPXCHG16B} -- CMPXCHG16B instruction. ++ ++@item ++@code{CNXT_ID} -- L1 Context ID. ++ ++@item ++@code{CORE_CAPABILITIES} -- IA32_CORE_CAPABILITIES MSR. ++ ++@item ++@code{CX8} -- CMPXCHG8B instruction. ++ ++@item ++@code{DCA} -- Data prefetch from a memory mapped device. ++ ++@item ++@code{DE} -- Debugging Extensions. ++ ++@item ++@code{DEPR_FPU_CS_DS} -- Deprecates FPU CS and FPU DS values. ++ ++@item ++@code{DS} -- Debug Store. ++ ++@item ++@code{DS_CPL} -- CPL Qualified Debug Store. ++ ++@item ++@code{DTES64} -- 64-bit DS Area. ++ ++@item ++@code{EIST} -- Enhanced Intel SpeedStep technology. ++ ++@item ++@code{ENQCMD} -- Enqueue Stores instructions. ++ ++@item ++@code{ERMS} -- Enhanced REP MOVSB/STOSB. ++ ++@item ++@code{F16C} -- 16-bit floating-point conversion instructions. ++ ++@item ++@code{FMA} -- FMA extensions using YMM state. ++ ++@item ++@code{FMA4} -- FMA4 instruction extensions. ++ ++@item ++@code{FPU} -- X87 Floating Point Unit On-Chip. ++ ++@item ++@code{FSGSBASE} -- RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE instructions. ++ ++@item ++@code{FSRM} -- Fast Short REP MOV. ++ ++@item ++@code{FXSR} -- FXSAVE and FXRSTOR instructions. ++ ++@item ++@code{GFNI} -- GFNI instruction extensions. ++ ++@item ++@code{HLE} -- HLE instruction extensions. ++ ++@item ++@code{HTT} -- Max APIC IDs reserved field is Valid. ++ ++@item ++@code{HYBRID} -- Hybrid processor. ++ ++@item ++@code{IBRS_IBPB} -- Indirect branch restricted speculation (IBRS) and ++the indirect branch predictor barrier (IBPB). ++ ++@item ++@code{IBT} -- Intel Indirect Branch Tracking instruction extensions. ++ ++@item ++@code{INVARIANT_TSC} -- Invariant TSC. ++ ++@item ++@code{INVPCID} -- INVPCID instruction. ++ ++@item ++@code{L1D_FLUSH} -- IA32_FLUSH_CMD MSR. ++ ++@item ++@code{LAHF64_SAHF64} -- LAHF/SAHF available in 64-bit mode. ++ ++@item ++@code{LM} -- Long mode. ++ ++@item ++@code{LWP} -- Lightweight profiling. ++ ++@item ++@code{LZCNT} -- LZCNT instruction. ++ ++@item ++@code{MCA} -- Machine Check Architecture. ++ ++@item ++@code{MCE} -- Machine Check Exception. ++ ++@item ++@code{MD_CLEAR} -- MD_CLEAR. ++ ++@item ++@code{MMX} -- Intel MMX Technology. ++ ++@item ++@code{MONITOR} -- MONITOR/MWAIT instructions. ++ ++@item ++@code{MOVBE} -- MOVBE instruction. ++ ++@item ++@code{MOVDIRI} -- MOVDIRI instruction. ++ ++@item ++@code{MOVDIR64B} -- MOVDIR64B instruction. ++ ++@item ++@code{MPX} -- Intel Memory Protection Extensions. ++ ++@item ++@code{MSR} -- Model Specific Registers RDMSR and WRMSR instructions. ++ ++@item ++@code{MTRR} -- Memory Type Range Registers. ++ ++@item ++@code{NX} -- No-execute page protection. ++ ++@item ++@code{OSPKE} -- OS has set CR4.PKE to enable protection keys. ++ ++@item ++@code{OSXSAVE} -- The OS has set CR4.OSXSAVE[bit 18] to enable ++XSETBV/XGETBV instructions to access XCR0 and to support processor ++extended state management using XSAVE/XRSTOR. ++ ++@item ++@code{PAE} -- Physical Address Extension. ++ ++@item ++@code{PAGE1GB} -- 1-GByte page. ++ ++@item ++@code{PAT} -- Page Attribute Table. ++ ++@item ++@code{PBE} -- Pending Break Enable. ++ ++@item ++@code{PCID} -- Process-context identifiers. ++ ++@item ++@code{PCLMULQDQ} -- PCLMULQDQ instruction. ++ ++@item ++@code{PCONFIG} -- PCONFIG instruction. ++ ++@item ++@code{PDCM} -- Perfmon and Debug Capability. ++ ++@item ++@code{PGE} -- Page Global Bit. ++ ++@item ++@code{PKS} -- Protection keys for supervisor-mode pages. ++ ++@item ++@code{PKU} -- Protection keys for user-mode pages. ++ ++@item ++@code{POPCNT} -- POPCNT instruction. ++ ++@item ++@code{PREFETCHW} -- PREFETCHW instruction. ++ ++@item ++@code{PREFETCHWT1} -- PREFETCHWT1 instruction. ++ ++@item ++@code{PSE} -- Page Size Extension. ++ ++@item ++@code{PSE_36} -- 36-Bit Page Size Extension. ++ ++@item ++@code{PSN} -- Processor Serial Number. ++ ++@item ++@code{RDPID} -- RDPID instruction. ++ ++@item ++@code{RDRAND} -- RDRAND instruction. ++ ++@item ++@code{RDSEED} -- RDSEED instruction. ++ ++@item ++@code{RDT_A} -- Intel Resource Director Technology (Intel RDT) Allocation ++capability. ++ ++@item ++@code{RDT_M} -- Intel Resource Director Technology (Intel RDT) Monitoring ++capability. ++ ++@item ++@code{RDTSCP} -- RDTSCP instruction. ++ ++@item ++@code{RTM} -- RTM instruction extensions. ++ ++@item ++@code{SDBG} -- IA32_DEBUG_INTERFACE MSR for silicon debug. ++ ++@item ++@code{SEP} -- SYSENTER and SYSEXIT instructions. ++ ++@item ++@code{SERIALIZE} -- SERIALIZE instruction. ++ ++@item ++@code{SGX} -- Intel Software Guard Extensions. ++ ++@item ++@code{SGX_LC} -- SGX Launch Configuration. ++ ++@item ++@code{SHA} -- SHA instruction extensions. ++ ++@item ++@code{SHSTK} -- Intel Shadow Stack instruction extensions. ++ ++@item ++@code{SMAP} -- Supervisor-Mode Access Prevention. ++ ++@item ++@code{SMEP} -- Supervisor-Mode Execution Prevention. ++ ++@item ++@code{SMX} -- Safer Mode Extensions. ++ ++@item ++@code{SS} -- Self Snoop. ++ ++@item ++@code{SSBD} -- Speculative Store Bypass Disable (SSBD). ++ ++@item ++@code{SSE} -- Streaming SIMD Extensions. ++ ++@item ++@code{SSE2} -- Streaming SIMD Extensions 2. ++ ++@item ++@code{SSE3} -- Streaming SIMD Extensions 3. ++ ++@item ++@code{SSE4_1} -- Streaming SIMD Extensions 4.1. ++ ++@item ++@code{SSE4_2} -- Streaming SIMD Extensions 4.2. ++ ++@item ++@code{SSE4A} -- SSE4A instruction extensions. ++ ++@item ++@code{SSSE3} -- Supplemental Streaming SIMD Extensions 3. ++ ++@item ++@code{STIBP} -- Single thread indirect branch predictors (STIBP). ++ ++@item ++@code{SVM} -- Secure Virtual Machine. ++ ++@item ++@code{SYSCALL_SYSRET} -- SYSCALL/SYSRET instructions. ++ ++@item ++@code{TBM} -- Trailing bit manipulation instructions. ++ ++@item ++@code{TM} -- Thermal Monitor. ++ ++@item ++@code{TM2} -- Thermal Monitor 2. ++ ++@item ++@code{TRACE} -- Intel Processor Trace. ++ ++@item ++@code{TSC} -- Time Stamp Counter. RDTSC instruction. ++ ++@item ++@code{TSC_ADJUST} -- IA32_TSC_ADJUST MSR. ++ ++@item ++@code{TSC_DEADLINE} -- Local APIC timer supports one-shot operation ++using a TSC deadline value. ++ ++@item ++@code{TSXLDTRK} -- TSXLDTRK instructions. ++ ++@item ++@code{UMIP} -- User-mode instruction prevention. ++ ++@item ++@code{VAES} -- VAES instruction extensions. ++ ++@item ++@code{VME} -- Virtual 8086 Mode Enhancements. ++ ++@item ++@code{VMX} -- Virtual Machine Extensions. ++ ++@item ++@code{VPCLMULQDQ} -- VPCLMULQDQ instruction. ++ ++@item ++@code{WAITPKG} -- WAITPKG instruction extensions. ++ ++@item ++@code{WBNOINVD} -- WBINVD/WBNOINVD instructions. ++ ++@item ++@code{X2APIC} -- x2APIC. ++ ++@item ++@code{XFD} -- Extended Feature Disable (XFD). ++ ++@item ++@code{XGETBV_ECX_1} -- XGETBV with ECX = 1. ++ ++@item ++@code{XOP} -- XOP instruction extensions. ++ ++@item ++@code{XSAVE} -- The XSAVE/XRSTOR processor extended states feature, the ++XSETBV/XGETBV instructions, and XCR0. ++ ++@item ++@code{XSAVEC} -- XSAVEC instruction. ++ ++@item ++@code{XSAVEOPT} -- XSAVEOPT instruction. ++ ++@item ++@code{XSAVES} -- XSAVES/XRSTORS instructions. ++ ++@item ++@code{XTPRUPDCTRL} -- xTPR Update Control. ++ ++@end itemize ++ ++You could query if a processor supports @code{AVX} with: ++ ++@smallexample ++#include ++ ++int ++support_avx (void) ++@{ ++ return HAS_CPU_FEATURE (AVX); ++@} ++@end smallexample ++ ++and if @code{AVX} is usable with: ++ ++@smallexample ++#include ++ ++int ++usable_avx (void) ++@{ ++ return CPU_FEATURE_USABLE (AVX); ++@} ++@end smallexample +diff --git a/sysdeps/i386/i686/multiarch/Makefile b/sysdeps/i386/i686/multiarch/Makefile +index bf75a9947fe013a3..c4897922d710d37e 100644 +--- a/sysdeps/i386/i686/multiarch/Makefile ++++ b/sysdeps/i386/i686/multiarch/Makefile +@@ -1,7 +1,3 @@ +-ifeq ($(subdir),csu) +-tests += test-multiarch +-endif +- + ifeq ($(subdir),string) + gen-as-const-headers += locale-defines.sym + sysdep_routines += bzero-sse2 memset-sse2 memcpy-ssse3 mempcpy-ssse3 \ +diff --git a/sysdeps/i386/i686/multiarch/test-multiarch.c b/sysdeps/i386/i686/multiarch/test-multiarch.c +deleted file mode 100644 +index 593cfec2735fb5b0..0000000000000000 +--- a/sysdeps/i386/i686/multiarch/test-multiarch.c ++++ /dev/null +@@ -1 +0,0 @@ +-#include +diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile +index 962bbcb07eba1259..59e928e9d08d3229 100644 +--- a/sysdeps/x86/Makefile ++++ b/sysdeps/x86/Makefile +@@ -5,7 +5,8 @@ endif + ifeq ($(subdir),elf) + sysdep-dl-routines += dl-get-cpu-features + +-tests += tst-get-cpu-features tst-get-cpu-features-static ++tests += tst-get-cpu-features tst-get-cpu-features-static \ ++ tst-cpu-features-cpuinfo tst-cpu-features-supports + tests-static += tst-get-cpu-features-static + endif + +diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions +index e02923708e160881..df70e602192053c0 100644 +--- a/sysdeps/x86/Versions ++++ b/sysdeps/x86/Versions +@@ -1,5 +1,5 @@ + ld { + GLIBC_PRIVATE { +- __get_cpu_features; ++ __x86_get_cpu_features; + } + } +diff --git a/sysdeps/x86/dl-get-cpu-features.c b/sysdeps/x86/dl-get-cpu-features.c +index 49593f19c64ad0bb..2aba0d167129b336 100644 +--- a/sysdeps/x86/dl-get-cpu-features.c ++++ b/sysdeps/x86/dl-get-cpu-features.c +@@ -18,10 +18,12 @@ + + #include + +-#undef __get_cpu_features ++#undef __x86_get_cpu_features + + const struct cpu_features * +-__get_cpu_features (void) ++__x86_get_cpu_features (unsigned int max) + { ++ if (max > COMMON_CPUID_INDEX_MAX) ++ return NULL; + return &GLRO(dl_x86_cpu_features); + } +diff --git a/sysdeps/x86/include/cpu-features.h b/sysdeps/x86/include/cpu-features.h +new file mode 100644 +index 0000000000000000..dcf29b6fe8578078 +--- /dev/null ++++ b/sysdeps/x86/include/cpu-features.h +@@ -0,0 +1,183 @@ ++/* Data structure for x86 CPU features. ++ Copyright (C) 2020 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 ++ . */ ++ ++#ifndef _PRIVATE_CPU_FEATURES_H ++#define _PRIVATE_CPU_FEATURES_H 1 ++ ++#ifdef _CPU_FEATURES_H ++# error this should be impossible ++#endif ++ ++#ifndef _ISOMAC ++/* Get most of the contents from the public header, but we define a ++ different `struct cpu_features' type for private use. */ ++# define cpu_features cpu_features_public ++# define __x86_get_cpu_features __x86_get_cpu_features_public ++#endif ++ ++#include ++ ++#ifndef _ISOMAC ++ ++# undef cpu_features ++# undef __x86_get_cpu_features ++# define __get_cpu_features() __x86_get_cpu_features (0) ++ ++enum ++{ ++ /* The integer bit array index for the first set of preferred feature ++ bits. */ ++ PREFERRED_FEATURE_INDEX_1 = 0, ++ /* The current maximum size of the feature integer bit array. */ ++ PREFERRED_FEATURE_INDEX_MAX ++}; ++ ++/* Only used directly in cpu-features.c. */ ++# define CPU_FEATURE_SET(ptr, name) \ ++ ptr->features[index_cpu_##name].usable.reg_##name |= bit_cpu_##name; ++# define CPU_FEATURE_UNSET(ptr, name) \ ++ ptr->features[index_cpu_##name].usable.reg_##name &= ~bit_cpu_##name; ++# define CPU_FEATURE_SET_USABLE(ptr, name) \ ++ ptr->features[index_cpu_##name].usable.reg_##name \ ++ |= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name; ++# define CPU_FEATURE_PREFERRED_P(ptr, name) \ ++ ((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0) ++# define CPU_FEATURE_CPU_P(ptr, name) \ ++ CPU_FEATURE_CHECK_P (ptr, name, cpuid) ++ ++/* HAS_CPU_FEATURE evaluates to true if CPU supports the feature. */ ++# undef HAS_CPU_FEATURE ++# define HAS_CPU_FEATURE(name) \ ++ CPU_FEATURE_CPU_P (__x86_get_cpu_features (0), name) ++/* CPU_FEATURE_USABLE evaluates to true if the feature is usable. */ ++# undef CPU_FEATURE_USABLE ++# define CPU_FEATURE_USABLE(name) \ ++ CPU_FEATURE_USABLE_P (__x86_get_cpu_features (0), name) ++/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at ++ runtime. */ ++# define CPU_FEATURE_PREFERRED(name) \ ++ CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name) ++ ++# define CPU_FEATURES_CPU_P(ptr, name) \ ++ CPU_FEATURE_CPU_P (ptr, name) ++# define CPU_FEATURES_ARCH_P(ptr, name) \ ++ CPU_FEATURE_PREFERRED_P (ptr, name) ++# define HAS_ARCH_FEATURE(name) \ ++ CPU_FEATURE_PREFERRED (name) ++ ++/* PREFERRED_FEATURE_INDEX_1. */ ++# define bit_arch_I586 (1u << 0) ++# define bit_arch_I686 (1u << 1) ++# define bit_arch_Fast_Rep_String (1u << 2) ++# define bit_arch_Fast_Copy_Backward (1u << 3) ++# define bit_arch_Fast_Unaligned_Load (1u << 4) ++# define bit_arch_Fast_Unaligned_Copy (1u << 5) ++# define bit_arch_Slow_BSF (1u << 6) ++# define bit_arch_Slow_SSE4_2 (1u << 7) ++# define bit_arch_AVX_Fast_Unaligned_Load (1u << 8) ++# define bit_arch_Prefer_MAP_32BIT_EXEC (1u << 9) ++# define bit_arch_Prefer_PMINUB_for_stringop (1u << 10) ++# define bit_arch_Prefer_No_VZEROUPPER (1u << 11) ++# define bit_arch_Prefer_ERMS (1u << 12) ++# define bit_arch_Prefer_FSRM (1u << 13) ++# define bit_arch_Prefer_No_AVX512 (1u << 14) ++# define bit_arch_MathVec_Prefer_No_AVX512 (1u << 15) ++ ++# define index_arch_Fast_Rep_String PREFERRED_FEATURE_INDEX_1 ++# define index_arch_Fast_Copy_Backward PREFERRED_FEATURE_INDEX_1 ++# define index_arch_Slow_BSF PREFERRED_FEATURE_INDEX_1 ++# define index_arch_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1 ++# define index_arch_Prefer_PMINUB_for_stringop PREFERRED_FEATURE_INDEX_1 ++# define index_arch_Fast_Unaligned_Copy PREFERRED_FEATURE_INDEX_1 ++# define index_arch_I586 PREFERRED_FEATURE_INDEX_1 ++# define index_arch_I686 PREFERRED_FEATURE_INDEX_1 ++# define index_arch_Slow_SSE4_2 PREFERRED_FEATURE_INDEX_1 ++# define index_arch_AVX_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1 ++# define index_arch_Prefer_MAP_32BIT_EXEC PREFERRED_FEATURE_INDEX_1 ++# define index_arch_Prefer_No_VZEROUPPER PREFERRED_FEATURE_INDEX_1 ++# define index_arch_Prefer_ERMS PREFERRED_FEATURE_INDEX_1 ++# define index_arch_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1 ++# define index_arch_MathVec_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1 ++# define index_arch_Prefer_FSRM PREFERRED_FEATURE_INDEX_1 ++ ++/* XCR0 Feature flags. */ ++# define bit_XMM_state (1u << 1) ++# define bit_YMM_state (1u << 2) ++# define bit_Opmask_state (1u << 5) ++# define bit_ZMM0_15_state (1u << 6) ++# define bit_ZMM16_31_state (1u << 7) ++# define bit_XTILECFG_state (1u << 17) ++# define bit_XTILEDATA_state (1u << 18) ++ ++struct cpu_features ++{ ++ struct cpu_features_basic basic; ++ struct cpuid_features features[COMMON_CPUID_INDEX_MAX]; ++ unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX]; ++ /* The state size for XSAVEC or XSAVE. The type must be unsigned long ++ int so that we use ++ ++ sub xsave_state_size_offset(%rip) %RSP_LP ++ ++ in _dl_runtime_resolve. */ ++ unsigned long int xsave_state_size; ++ /* The full state size for XSAVE when XSAVEC is disabled by ++ ++ GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC ++ */ ++ unsigned int xsave_state_full_size; ++ /* Data cache size for use in memory and string routines, typically ++ L1 size. */ ++ unsigned long int data_cache_size; ++ /* Shared cache size for use in memory and string routines, typically ++ L2 or L3 size. */ ++ unsigned long int shared_cache_size; ++ /* Threshold to use non temporal store. */ ++ unsigned long int non_temporal_threshold; ++ /* Threshold to use "rep movsb". */ ++ unsigned long int rep_movsb_threshold; ++ /* Threshold to use "rep stosb". */ ++ unsigned long int rep_stosb_threshold; ++}; ++ ++# if defined (_LIBC) && !IS_IN (nonlib) ++/* Unused for x86. */ ++# define INIT_ARCH() ++# define __x86_get_cpu_features(max) (&GLRO(dl_x86_cpu_features)) ++# endif ++ ++# ifdef __x86_64__ ++# define HAS_CPUID 1 ++# elif (defined __i586__ || defined __pentium__ \ ++ || defined __geode__ || defined __k6__) ++# define HAS_CPUID 1 ++# define HAS_I586 1 ++# define HAS_I686 HAS_ARCH_FEATURE (I686) ++# elif defined __i486__ ++# define HAS_CPUID 0 ++# define HAS_I586 HAS_ARCH_FEATURE (I586) ++# define HAS_I686 HAS_ARCH_FEATURE (I686) ++# else ++# define HAS_CPUID 1 ++# define HAS_I586 1 ++# define HAS_I686 1 ++# endif ++ ++#endif /* !_ISOMAC */ ++ ++#endif /* include/cpu-features.h */ +diff --git a/sysdeps/x86/cpu-features.h b/sysdeps/x86/sys/platform/x86.h +similarity index 81% +rename from sysdeps/x86/cpu-features.h +rename to sysdeps/x86/sys/platform/x86.h +index 3b401d441b8d370a..ebc5f6fc16cb8104 100644 +--- a/sysdeps/x86/cpu-features.h ++++ b/sysdeps/x86/sys/platform/x86.h +@@ -1,5 +1,6 @@ +-/* This file is part of the GNU C Library. +- Copyright (C) 2008-2018 Free Software Foundation, Inc. ++/* Data structure for x86 CPU features. ++ This file is part of the GNU C Library. ++ Copyright (C) 2008-2020 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public +@@ -15,17 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + +-#ifndef cpu_features_h +-#define cpu_features_h +- +-enum +-{ +- /* The integer bit array index for the first set of preferred feature +- bits. */ +- PREFERRED_FEATURE_INDEX_1 = 0, +- /* The current maximum size of the feature integer bit array. */ +- PREFERRED_FEATURE_INDEX_MAX +-}; ++#ifndef _SYS_PLATFORM_X86_H ++#define _SYS_PLATFORM_X86_H + + enum + { +@@ -76,73 +68,32 @@ struct cpu_features + { + struct cpu_features_basic basic; + struct cpuid_features features[COMMON_CPUID_INDEX_MAX]; +- unsigned int preferred[PREFERRED_FEATURE_INDEX_MAX]; +- /* The state size for XSAVEC or XSAVE. The type must be unsigned long +- int so that we use +- +- sub xsave_state_size_offset(%rip) %RSP_LP +- +- in _dl_runtime_resolve. */ +- unsigned long int xsave_state_size; +- /* The full state size for XSAVE when XSAVEC is disabled by +- +- GLIBC_TUNABLES=glibc.cpu.hwcaps=-XSAVEC +- */ +- unsigned int xsave_state_full_size; +- /* Data cache size for use in memory and string routines, typically +- L1 size. */ +- unsigned long int data_cache_size; +- /* Shared cache size for use in memory and string routines, typically +- L2 or L3 size. */ +- unsigned long int shared_cache_size; +- /* Threshold to use non temporal store. */ +- unsigned long int non_temporal_threshold; +- /* Threshold to use "rep movsb". */ +- unsigned long int rep_movsb_threshold; +- /* Threshold to use "rep stosb". */ +- unsigned long int rep_stosb_threshold; + }; + +-/* Used from outside of glibc to get access to the CPU features +- structure. */ +-extern const struct cpu_features *__get_cpu_features (void) ++/* Get a pointer to the CPU features structure. */ ++extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + __attribute__ ((const)); + +-/* Only used directly in cpu-features.c. */ + #define CPU_FEATURE_CHECK_P(ptr, name, check) \ + ((ptr->features[index_cpu_##name].check.reg_##name \ + & bit_cpu_##name) != 0) +-#define CPU_FEATURE_SET(ptr, name) \ +- ptr->features[index_cpu_##name].usable.reg_##name |= bit_cpu_##name; +-#define CPU_FEATURE_UNSET(ptr, name) \ +- ptr->features[index_cpu_##name].usable.reg_##name &= ~bit_cpu_##name; +-#define CPU_FEATURE_SET_USABLE(ptr, name) \ +- ptr->features[index_cpu_##name].usable.reg_##name \ +- |= ptr->features[index_cpu_##name].cpuid.reg_##name & bit_cpu_##name; +-#define CPU_FEATURE_PREFERRED_P(ptr, name) \ +- ((ptr->preferred[index_arch_##name] & bit_arch_##name) != 0) + #define CPU_FEATURE_CPU_P(ptr, name) \ + CPU_FEATURE_CHECK_P (ptr, name, cpuid) + #define CPU_FEATURE_USABLE_P(ptr, name) \ + CPU_FEATURE_CHECK_P (ptr, name, usable) + + /* HAS_CPU_FEATURE evaluates to true if CPU supports the feature. */ +-#define HAS_CPU_FEATURE(name) \ +- CPU_FEATURE_CPU_P (__get_cpu_features (), name) ++#define HAS_CPU_FEATURE(name) \ ++ (__extension__ \ ++ ({ const struct cpu_features *__ptr = \ ++ __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX); \ ++ __ptr && CPU_FEATURE_CPU_P (__ptr, name); })) + /* CPU_FEATURE_USABLE evaluates to true if the feature is usable. */ +-#define CPU_FEATURE_USABLE(name) \ +- CPU_FEATURE_USABLE_P (__get_cpu_features (), name) +-/* CPU_FEATURE_PREFER evaluates to true if we prefer the feature at +- runtime. */ +-#define CPU_FEATURE_PREFERRED(name) \ +- CPU_FEATURE_PREFERRED_P(__get_cpu_features (), name) +- +-#define CPU_FEATURES_CPU_P(ptr, name) \ +- CPU_FEATURE_CPU_P (ptr, name) +-#define CPU_FEATURES_ARCH_P(ptr, name) \ +- CPU_FEATURE_PREFERRED_P (ptr, name) +-#define HAS_ARCH_FEATURE(name) \ +- CPU_FEATURE_PREFERRED (name) ++#define CPU_FEATURE_USABLE(name) \ ++ (__extension__ \ ++ ({ const struct cpu_features *__ptr = \ ++ __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX); \ ++ __ptr && CPU_FEATURE_USABLE_P (__ptr, name); })) + + /* CPU features. */ + +@@ -787,71 +738,4 @@ extern const struct cpu_features *__get_cpu_features (void) + /* EAX. */ + #define reg_AVX512_BF16 eax + +-/* FEATURE_INDEX_2. */ +-#define bit_arch_I586 (1u << 0) +-#define bit_arch_I686 (1u << 1) +-#define bit_arch_Fast_Rep_String (1u << 2) +-#define bit_arch_Fast_Copy_Backward (1u << 3) +-#define bit_arch_Fast_Unaligned_Load (1u << 4) +-#define bit_arch_Fast_Unaligned_Copy (1u << 5) +-#define bit_arch_Slow_BSF (1u << 6) +-#define bit_arch_Slow_SSE4_2 (1u << 7) +-#define bit_arch_AVX_Fast_Unaligned_Load (1u << 8) +-#define bit_arch_Prefer_MAP_32BIT_EXEC (1u << 9) +-#define bit_arch_Prefer_PMINUB_for_stringop (1u << 10) +-#define bit_arch_Prefer_No_VZEROUPPER (1u << 11) +-#define bit_arch_Prefer_ERMS (1u << 12) +-#define bit_arch_Prefer_FSRM (1u << 13) +-#define bit_arch_Prefer_No_AVX512 (1u << 14) +-#define bit_arch_MathVec_Prefer_No_AVX512 (1u << 15) +- +-#define index_arch_Fast_Rep_String PREFERRED_FEATURE_INDEX_1 +-#define index_arch_Fast_Copy_Backward PREFERRED_FEATURE_INDEX_1 +-#define index_arch_Slow_BSF PREFERRED_FEATURE_INDEX_1 +-#define index_arch_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1 +-#define index_arch_Prefer_PMINUB_for_stringop PREFERRED_FEATURE_INDEX_1 +-#define index_arch_Fast_Unaligned_Copy PREFERRED_FEATURE_INDEX_1 +-#define index_arch_I586 PREFERRED_FEATURE_INDEX_1 +-#define index_arch_I686 PREFERRED_FEATURE_INDEX_1 +-#define index_arch_Slow_SSE4_2 PREFERRED_FEATURE_INDEX_1 +-#define index_arch_AVX_Fast_Unaligned_Load PREFERRED_FEATURE_INDEX_1 +-#define index_arch_Prefer_MAP_32BIT_EXEC PREFERRED_FEATURE_INDEX_1 +-#define index_arch_Prefer_No_VZEROUPPER PREFERRED_FEATURE_INDEX_1 +-#define index_arch_Prefer_ERMS PREFERRED_FEATURE_INDEX_1 +-#define index_arch_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1 +-#define index_arch_MathVec_Prefer_No_AVX512 PREFERRED_FEATURE_INDEX_1 +-#define index_arch_Prefer_FSRM PREFERRED_FEATURE_INDEX_1 +- +-/* XCR0 Feature flags. */ +-#define bit_XMM_state (1u << 1) +-#define bit_YMM_state (1u << 2) +-#define bit_Opmask_state (1u << 5) +-#define bit_ZMM0_15_state (1u << 6) +-#define bit_ZMM16_31_state (1u << 7) +-#define bit_XTILECFG_state (1u << 17) +-#define bit_XTILEDATA_state (1u << 18) +- +-# if defined (_LIBC) && !IS_IN (nonlib) +-/* Unused for x86. */ +-# define INIT_ARCH() +-# define __get_cpu_features() (&GLRO(dl_x86_cpu_features)) +-# endif +- +-#ifdef __x86_64__ +-# define HAS_CPUID 1 +-#elif (defined __i586__ || defined __pentium__ \ +- || defined __geode__ || defined __k6__) +-# define HAS_CPUID 1 +-# define HAS_I586 1 +-# define HAS_I686 HAS_ARCH_FEATURE (I686) +-#elif defined __i486__ +-# define HAS_CPUID 0 +-# define HAS_I586 HAS_ARCH_FEATURE (I586) +-# define HAS_I686 HAS_ARCH_FEATURE (I686) +-#else +-# define HAS_CPUID 1 +-# define HAS_I586 1 +-# define HAS_I686 1 +-#endif +- +-#endif /* cpu_features_h */ ++#endif /* _SYS_PLATFORM_X86_H */ +diff --git a/sysdeps/x86/tst-cpu-features-cpuinfo.c b/sysdeps/x86/tst-cpu-features-cpuinfo.c +new file mode 100644 +index 0000000000000000..96277284d15a0690 +--- /dev/null ++++ b/sysdeps/x86/tst-cpu-features-cpuinfo.c +@@ -0,0 +1,250 @@ ++/* Test CPU feature data against /proc/cpuinfo. ++ This file is part of the GNU C Library. ++ Copyright (C) 2012-2020 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++static char *cpu_flags; ++ ++/* Search for flags in /proc/cpuinfo and store line ++ in cpu_flags. */ ++void ++get_cpuinfo (void) ++{ ++ FILE *f; ++ char *line = NULL; ++ size_t len = 0; ++ ssize_t read; ++ ++ f = fopen ("/proc/cpuinfo", "r"); ++ if (f == NULL) ++ { ++ printf ("cannot open /proc/cpuinfo\n"); ++ exit (1); ++ } ++ ++ while ((read = getline (&line, &len, f)) != -1) ++ { ++ if (strncmp (line, "flags", 5) == 0) ++ { ++ cpu_flags = strdup (line); ++ break; ++ } ++ } ++ fclose (f); ++ free (line); ++} ++ ++int ++check_proc (const char *proc_name, int flag, int usable, const char *name) ++{ ++ int found = 0; ++ ++ printf ("Checking %s:\n", name); ++ if (!usable) ++ { ++ printf (" %s: insufficient usable info, skipped\n", name); ++ return 0; ++ } ++ printf (" %s: %d\n", name, flag); ++ if (strstr (cpu_flags, proc_name) != NULL) ++ found = 1; ++ printf (" cpuinfo (%s): %d\n", proc_name, found); ++ ++ if (found != flag) ++ printf (" *** failure ***\n"); ++ ++ return (found != flag); ++} ++ ++#define CHECK_PROC(str, name) \ ++ check_proc (#str, HAS_CPU_FEATURE (name), CPU_FEATURE_USABLE (name), \ ++ "HAS_CPU_FEATURE (" #name ")"); ++ ++static int ++do_test (int argc, char **argv) ++{ ++ int fails = 0; ++ ++ get_cpuinfo (); ++ fails += CHECK_PROC (acpi, ACPI); ++ fails += CHECK_PROC (adx, ADX); ++ fails += CHECK_PROC (apic, APIC); ++ fails += CHECK_PROC (aes, AES); ++ fails += CHECK_PROC (amx_bf16, AMX_BF16); ++ fails += CHECK_PROC (amx_int8, AMX_INT8); ++ fails += CHECK_PROC (amx_tile, AMX_TILE); ++ fails += CHECK_PROC (arch_capabilities, ARCH_CAPABILITIES); ++ fails += CHECK_PROC (avx, AVX); ++ fails += CHECK_PROC (avx2, AVX2); ++ fails += CHECK_PROC (avx512_4fmaps, AVX512_4FMAPS); ++ fails += CHECK_PROC (avx512_4vnniw, AVX512_4VNNIW); ++ fails += CHECK_PROC (avx512_bf16, AVX512_BF16); ++ fails += CHECK_PROC (avx512_bitalg, AVX512_BITALG); ++ fails += CHECK_PROC (avx512ifma, AVX512_IFMA); ++ fails += CHECK_PROC (avx512_vbmi, AVX512_VBMI); ++ fails += CHECK_PROC (avx512_vbmi2, AVX512_VBMI2); ++ fails += CHECK_PROC (avx512_vnni, AVX512_VNNI); ++ fails += CHECK_PROC (avx512_vp2intersect, AVX512_VP2INTERSECT); ++ fails += CHECK_PROC (avx512_vpopcntdq, AVX512_VPOPCNTDQ); ++ fails += CHECK_PROC (avx512bw, AVX512BW); ++ fails += CHECK_PROC (avx512cd, AVX512CD); ++ fails += CHECK_PROC (avx512er, AVX512ER); ++ fails += CHECK_PROC (avx512dq, AVX512DQ); ++ fails += CHECK_PROC (avx512f, AVX512F); ++ fails += CHECK_PROC (avx512pf, AVX512PF); ++ fails += CHECK_PROC (avx512vl, AVX512VL); ++ fails += CHECK_PROC (bmi1, BMI1); ++ fails += CHECK_PROC (bmi2, BMI2); ++ fails += CHECK_PROC (cldemote, CLDEMOTE); ++ fails += CHECK_PROC (clflushopt, CLFLUSHOPT); ++ fails += CHECK_PROC (clflush, CLFSH); ++ fails += CHECK_PROC (clwb, CLWB); ++ fails += CHECK_PROC (cmov, CMOV); ++ fails += CHECK_PROC (cx16, CMPXCHG16B); ++ fails += CHECK_PROC (cnxt_id, CNXT_ID); ++ fails += CHECK_PROC (core_capabilities, CORE_CAPABILITIES); ++ fails += CHECK_PROC (cx8, CX8); ++ fails += CHECK_PROC (dca, DCA); ++ fails += CHECK_PROC (de, DE); ++ fails += CHECK_PROC (zero_fcs_fds, DEPR_FPU_CS_DS); ++ fails += CHECK_PROC (ds, DS); ++ fails += CHECK_PROC (ds_cpl, DS_CPL); ++ fails += CHECK_PROC (dtes64, DTES64); ++ fails += CHECK_PROC (est, EIST); ++ fails += CHECK_PROC (enqcmd, ENQCMD); ++ fails += CHECK_PROC (erms, ERMS); ++ fails += CHECK_PROC (f16c, F16C); ++ fails += CHECK_PROC (fma, FMA); ++ fails += CHECK_PROC (fma4, FMA4); ++ fails += CHECK_PROC (fpu, FPU); ++ fails += CHECK_PROC (fsgsbase, FSGSBASE); ++ fails += CHECK_PROC (fsrm, FSRM); ++ fails += CHECK_PROC (fxsr, FXSR); ++ fails += CHECK_PROC (gfni, GFNI); ++ fails += CHECK_PROC (hle, HLE); ++ fails += CHECK_PROC (ht, HTT); ++ fails += CHECK_PROC (hybrid, HYBRID); ++ fails += CHECK_PROC (ibrs, IBRS_IBPB); ++ fails += CHECK_PROC (ibt, IBT); ++ fails += CHECK_PROC (invariant_tsc, INVARIANT_TSC); ++ fails += CHECK_PROC (invpcid, INVPCID); ++ fails += CHECK_PROC (flush_l1d, L1D_FLUSH); ++ fails += CHECK_PROC (lahf_lm, LAHF64_SAHF64); ++ fails += CHECK_PROC (lm, LM); ++ fails += CHECK_PROC (lwp, LWP); ++ fails += CHECK_PROC (abm, LZCNT); ++ fails += CHECK_PROC (mca, MCA); ++ fails += CHECK_PROC (mce, MCE); ++ fails += CHECK_PROC (md_clear, MD_CLEAR); ++ fails += CHECK_PROC (mmx, MMX); ++ fails += CHECK_PROC (monitor, MONITOR); ++ fails += CHECK_PROC (movbe, MOVBE); ++ fails += CHECK_PROC (movdiri, MOVDIRI); ++ fails += CHECK_PROC (movdir64b, MOVDIR64B); ++ fails += CHECK_PROC (mpx, MPX); ++ fails += CHECK_PROC (msr, MSR); ++ fails += CHECK_PROC (mtrr, MTRR); ++ fails += CHECK_PROC (nx, NX); ++ fails += CHECK_PROC (ospke, OSPKE); ++#if 0 ++ /* NB: /proc/cpuinfo doesn't report this feature. */ ++ fails += CHECK_PROC (osxsave, OSXSAVE); ++#endif ++ fails += CHECK_PROC (pae, PAE); ++ fails += CHECK_PROC (pdpe1gb, PAGE1GB); ++ fails += CHECK_PROC (pat, PAT); ++ fails += CHECK_PROC (pbe, PBE); ++ fails += CHECK_PROC (pcid, PCID); ++ fails += CHECK_PROC (pclmulqdq, PCLMULQDQ); ++ fails += CHECK_PROC (pconfig, PCONFIG); ++ fails += CHECK_PROC (pdcm, PDCM); ++ fails += CHECK_PROC (pge, PGE); ++ fails += CHECK_PROC (pks, PKS); ++ fails += CHECK_PROC (pku, PKU); ++ fails += CHECK_PROC (popcnt, POPCNT); ++ fails += CHECK_PROC (3dnowprefetch, PREFETCHW); ++ fails += CHECK_PROC (prefetchwt1, PREFETCHWT1); ++ fails += CHECK_PROC (pse, PSE); ++ fails += CHECK_PROC (pse36, PSE_36); ++ fails += CHECK_PROC (psn, PSN); ++ fails += CHECK_PROC (rdpid, RDPID); ++ fails += CHECK_PROC (rdrand, RDRAND); ++ fails += CHECK_PROC (rdseed, RDSEED); ++ fails += CHECK_PROC (rdt_a, RDT_A); ++ fails += CHECK_PROC (cqm, RDT_M); ++ fails += CHECK_PROC (rdtscp, RDTSCP); ++ fails += CHECK_PROC (rtm, RTM); ++ fails += CHECK_PROC (sdbg, SDBG); ++ fails += CHECK_PROC (sep, SEP); ++ fails += CHECK_PROC (serialize, SERIALIZE); ++ fails += CHECK_PROC (sgx, SGX); ++ fails += CHECK_PROC (sgx_lc, SGX_LC); ++ fails += CHECK_PROC (sha_ni, SHA); ++ fails += CHECK_PROC (shstk, SHSTK); ++ fails += CHECK_PROC (smap, SMAP); ++ fails += CHECK_PROC (smep, SMEP); ++ fails += CHECK_PROC (smx, SMX); ++ fails += CHECK_PROC (ss, SS); ++ fails += CHECK_PROC (ssbd, SSBD); ++ fails += CHECK_PROC (sse, SSE); ++ fails += CHECK_PROC (sse2, SSE2); ++ fails += CHECK_PROC (sse3, SSE3); ++ fails += CHECK_PROC (sse4_1, SSE4_1); ++ fails += CHECK_PROC (sse4_2, SSE4_2); ++ fails += CHECK_PROC (sse4a, SSE4A); ++ fails += CHECK_PROC (ssse3, SSSE3); ++ fails += CHECK_PROC (stibp, STIBP); ++ fails += CHECK_PROC (svm, SVM); ++#ifdef __x86_64__ ++ /* NB: SYSCALL_SYSRET is 64-bit only. */ ++ fails += CHECK_PROC (syscall, SYSCALL_SYSRET); ++#endif ++ fails += CHECK_PROC (tbm, TBM); ++ fails += CHECK_PROC (tm, TM); ++ fails += CHECK_PROC (tm2, TM2); ++ fails += CHECK_PROC (intel_pt, TRACE); ++ fails += CHECK_PROC (tsc, TSC); ++ fails += CHECK_PROC (tsc_adjust, TSC_ADJUST); ++ fails += CHECK_PROC (tsc_deadline, TSC_DEADLINE); ++ fails += CHECK_PROC (tsxldtrk, TSXLDTRK); ++ fails += CHECK_PROC (umip, UMIP); ++ fails += CHECK_PROC (vaes, VAES); ++ fails += CHECK_PROC (vme, VME); ++ fails += CHECK_PROC (vmx, VMX); ++ fails += CHECK_PROC (vpclmulqdq, VPCLMULQDQ); ++ fails += CHECK_PROC (waitpkg, WAITPKG); ++ fails += CHECK_PROC (wbnoinvd, WBNOINVD); ++ fails += CHECK_PROC (x2apic, X2APIC); ++ fails += CHECK_PROC (xfd, XFD); ++ fails += CHECK_PROC (xgetbv1, XGETBV_ECX_1); ++ fails += CHECK_PROC (xop, XOP); ++ fails += CHECK_PROC (xsave, XSAVE); ++ fails += CHECK_PROC (xsavec, XSAVEC); ++ fails += CHECK_PROC (xsaveopt, XSAVEOPT); ++ fails += CHECK_PROC (xsaves, XSAVES); ++ fails += CHECK_PROC (xtpr, XTPRUPDCTRL); ++ ++ printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails); ++ ++ return (fails != 0); ++} ++ ++#include "../../../test-skeleton.c" +diff --git a/sysdeps/x86/tst-cpu-features-supports.c b/sysdeps/x86/tst-cpu-features-supports.c +new file mode 100644 +index 0000000000000000..bf881b531f4bc2ed +--- /dev/null ++++ b/sysdeps/x86/tst-cpu-features-supports.c +@@ -0,0 +1,192 @@ ++/* Test CPU feature data against __builtin_cpu_supports. ++ This file is part of the GNU C Library. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++int ++check_supports (int supports, int usable, const char *supports_name, ++ const char *name) ++{ ++ printf ("Checking %s:\n", name); ++ printf (" %s: %d\n", name, usable); ++ printf (" __builtin_cpu_supports (%s): %d\n", ++ supports_name, supports); ++ ++ if ((supports != 0) != (usable != 0)) ++ { ++ printf (" *** failure ***\n"); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++#define CHECK_SUPPORTS(str, name) \ ++ check_supports (__builtin_cpu_supports (#str), \ ++ CPU_FEATURE_USABLE (name), \ ++ #str, "HAS_CPU_FEATURE (" #name ")"); ++ ++static int ++do_test (int argc, char **argv) ++{ ++ int fails = 0; ++ ++#if __GNUC_PREREQ (11, 0) ++ fails += CHECK_SUPPORTS (adx, ADX); ++#endif ++#if __GNUC_PREREQ (6, 0) ++ fails += CHECK_SUPPORTS (aes, AES); ++#endif ++#if __GNUC_PREREQ (11, 1) ++ fails += CHECK_SUPPORTS (amx_bf16, AMX_BF16); ++ fails += CHECK_SUPPORTS (amx_int8, AMX_INT8); ++ fails += CHECK_SUPPORTS (amx_tile, AMX_TILE); ++#endif ++ fails += CHECK_SUPPORTS (avx, AVX); ++ fails += CHECK_SUPPORTS (avx2, AVX2); ++#if __GNUC_PREREQ (7, 0) ++ fails += CHECK_SUPPORTS (avx5124fmaps, AVX512_4FMAPS); ++ fails += CHECK_SUPPORTS (avx5124vnniw, AVX512_4VNNIW); ++#endif ++#if __GNUC_PREREQ (10, 0) ++ fails += CHECK_SUPPORTS (avx512bf16, AVX512_BF16); ++#endif ++#if __GNUC_PREREQ (8, 0) ++ fails += CHECK_SUPPORTS (avx512bitalg, AVX512_BITALG); ++#endif ++#if __GNUC_PREREQ (6, 0) ++ fails += CHECK_SUPPORTS (avx512ifma, AVX512_IFMA); ++ fails += CHECK_SUPPORTS (avx512vbmi, AVX512_VBMI); ++#endif ++#if __GNUC_PREREQ (8, 0) ++ fails += CHECK_SUPPORTS (avx512vbmi2, AVX512_VBMI2); ++ fails += CHECK_SUPPORTS (avx512vnni, AVX512_VNNI); ++#endif ++#if __GNUC_PREREQ (10, 0) ++ fails += CHECK_SUPPORTS (avx512vp2intersect, AVX512_VP2INTERSECT); ++#endif ++#if __GNUC_PREREQ (7, 0) ++ fails += CHECK_SUPPORTS (avx512vpopcntdq, AVX512_VPOPCNTDQ); ++#endif ++#if __GNUC_PREREQ (6, 0) ++ fails += CHECK_SUPPORTS (avx512bw, AVX512BW); ++ fails += CHECK_SUPPORTS (avx512cd, AVX512CD); ++ fails += CHECK_SUPPORTS (avx512er, AVX512ER); ++ fails += CHECK_SUPPORTS (avx512dq, AVX512DQ); ++#endif ++#if __GNUC_PREREQ (5, 0) ++ fails += CHECK_SUPPORTS (avx512f, AVX512F); ++#endif ++#if __GNUC_PREREQ (6, 0) ++ fails += CHECK_SUPPORTS (avx512pf, AVX512PF); ++ fails += CHECK_SUPPORTS (avx512vl, AVX512VL); ++#endif ++#if __GNUC_PREREQ (5, 0) ++ fails += CHECK_SUPPORTS (bmi, BMI1); ++ fails += CHECK_SUPPORTS (bmi2, BMI2); ++#endif ++#if __GNUC_PREREQ (11, 0) ++ fails += CHECK_SUPPORTS (cldemote, CLDEMOTE); ++ fails += CHECK_SUPPORTS (clflushopt, CLFLUSHOPT); ++ fails += CHECK_SUPPORTS (clwb, CLWB); ++#endif ++ fails += CHECK_SUPPORTS (cmov, CMOV); ++#if __GNUC_PREREQ (11, 0) ++ fails += CHECK_SUPPORTS (cmpxchg16b, CMPXCHG16B); ++ fails += CHECK_SUPPORTS (cmpxchg8b, CX8); ++ fails += CHECK_SUPPORTS (enqcmd, ENQCMD); ++ fails += CHECK_SUPPORTS (f16c, F16C); ++#endif ++#if __GNUC_PREREQ (4, 9) ++ fails += CHECK_SUPPORTS (fma, FMA); ++ fails += CHECK_SUPPORTS (fma4, FMA4); ++#endif ++#if __GNUC_PREREQ (11, 0) ++ fails += CHECK_SUPPORTS (fsgsbase, FSGSBASE); ++ fails += CHECK_SUPPORTS (fxsave, FXSR); ++#endif ++#if __GNUC_PREREQ (8, 0) ++ fails += CHECK_SUPPORTS (gfni, GFNI); ++#endif ++#if __GNUC_PREREQ (11, 0) ++ fails += CHECK_SUPPORTS (hle, HLE); ++ fails += CHECK_SUPPORTS (ibt, IBT); ++ fails += CHECK_SUPPORTS (lahf_lm, LAHF64_SAHF64); ++ fails += CHECK_SUPPORTS (lm, LM); ++ fails += CHECK_SUPPORTS (lwp, LWP); ++ fails += CHECK_SUPPORTS (lzcnt, LZCNT); ++#endif ++ fails += CHECK_SUPPORTS (mmx, MMX); ++#if __GNUC_PREREQ (11, 0) ++ fails += CHECK_SUPPORTS (movbe, MOVBE); ++ fails += CHECK_SUPPORTS (movdiri, MOVDIRI); ++ fails += CHECK_SUPPORTS (movdir64b, MOVDIR64B); ++ fails += CHECK_SUPPORTS (osxsave, OSXSAVE); ++ fails += CHECK_SUPPORTS (pconfig, PCONFIG); ++ fails += CHECK_SUPPORTS (pku, PKU); ++#endif ++ fails += CHECK_SUPPORTS (popcnt, POPCNT); ++#if __GNUC_PREREQ (11, 0) ++ fails += CHECK_SUPPORTS (prefetchwt1, PREFETCHWT1); ++ fails += CHECK_SUPPORTS (rdpid, RDPID); ++ fails += CHECK_SUPPORTS (rdrnd, RDRAND); ++ fails += CHECK_SUPPORTS (rdseed, RDSEED); ++ fails += CHECK_SUPPORTS (rtm, RTM); ++ fails += CHECK_SUPPORTS (serialize, SERIALIZE); ++ fails += CHECK_SUPPORTS (sha, SHA); ++ fails += CHECK_SUPPORTS (shstk, SHSTK); ++#endif ++ fails += CHECK_SUPPORTS (sse, SSE); ++ fails += CHECK_SUPPORTS (sse2, SSE2); ++ fails += CHECK_SUPPORTS (sse3, SSE3); ++ fails += CHECK_SUPPORTS (sse4.1, SSE4_1); ++ fails += CHECK_SUPPORTS (sse4.2, SSE4_2); ++#if __GNUC_PREREQ (4, 9) ++ fails += CHECK_SUPPORTS (sse4a, SSE4A); ++#endif ++ fails += CHECK_SUPPORTS (ssse3, SSSE3); ++#if __GNUC_PREREQ (11, 0) ++ fails += CHECK_SUPPORTS (tbm, TBM); ++ fails += CHECK_SUPPORTS (tsxldtrk, TSXLDTRK); ++ fails += CHECK_SUPPORTS (vaes, VAES); ++#endif ++#if __GNUC_PREREQ (8, 0) ++ fails += CHECK_SUPPORTS (vpclmulqdq, VPCLMULQDQ); ++#endif ++#if __GNUC_PREREQ (11, 0) ++ fails += CHECK_SUPPORTS (waitpkg, WAITPKG); ++ fails += CHECK_SUPPORTS (wbnoinvd, WBNOINVD); ++#endif ++#if __GNUC_PREREQ (4, 9) ++ fails += CHECK_SUPPORTS (xop, XOP); ++#endif ++#if __GNUC_PREREQ (11, 0) ++ fails += CHECK_SUPPORTS (xsave, XSAVE); ++ fails += CHECK_SUPPORTS (xsavec, XSAVEC); ++ fails += CHECK_SUPPORTS (xsaveopt, XSAVEOPT); ++ fails += CHECK_SUPPORTS (xsaves, XSAVES); ++#endif ++ ++ printf ("%d differences between __builtin_cpu_supports and glibc code.\n", ++ fails); ++ ++ return (fails != 0); ++} ++ ++#include "../../../test-skeleton.c" +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index 582b125a2dad3f21..95e0d33f6c7eeace 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -1,5 +1,5 @@ +-/* Test case for x86 __get_cpu_features interface +- Copyright (C) 2015-2018 Free Software Foundation, Inc. ++/* Test case for __x86_get_cpu_features interface ++ Copyright (C) 2015-2020 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 +@@ -18,7 +18,7 @@ + + #include + #include +-#include ++#include + #include + + #define CHECK_CPU_FEATURE(name) \ +@@ -44,7 +44,7 @@ static const char * const cpu_kinds[] = + static int + do_test (void) + { +- const struct cpu_features *cpu_features = __get_cpu_features (); ++ const struct cpu_features *cpu_features = __x86_get_cpu_features (0); + + switch (cpu_features->basic.kind) + { +diff --git a/sysdeps/x86_64/fpu/math-tests-arch.h b/sysdeps/x86_64/fpu/math-tests-arch.h +index 61955d70863321fd..c908eac6b4fff16d 100644 +--- a/sysdeps/x86_64/fpu/math-tests-arch.h ++++ b/sysdeps/x86_64/fpu/math-tests-arch.h +@@ -16,7 +16,7 @@ + License along with the GNU C Library; if not, see + . */ + +-#include ++#include + + #if defined REQUIRE_AVX + +diff --git a/sysdeps/x86_64/multiarch/Makefile b/sysdeps/x86_64/multiarch/Makefile +index 395e432c092ca17c..9477538af46787a5 100644 +--- a/sysdeps/x86_64/multiarch/Makefile ++++ b/sysdeps/x86_64/multiarch/Makefile +@@ -1,7 +1,3 @@ +-ifeq ($(subdir),csu) +-tests += test-multiarch +-endif +- + ifeq ($(subdir),string) + + sysdep_routines += strncat-c stpncpy-c strncpy-c \ +diff --git a/sysdeps/x86_64/multiarch/test-multiarch.c b/sysdeps/x86_64/multiarch/test-multiarch.c +deleted file mode 100644 +index cc2ea56a6753402d..0000000000000000 +--- a/sysdeps/x86_64/multiarch/test-multiarch.c ++++ /dev/null +@@ -1,96 +0,0 @@ +-/* Test CPU feature data. +- This file is part of the GNU C Library. +- Copyright (C) 2012-2018 Free Software Foundation, Inc. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +-#include +- +-static char *cpu_flags; +- +-/* Search for flags in /proc/cpuinfo and store line +- in cpu_flags. */ +-void +-get_cpuinfo (void) +-{ +- FILE *f; +- char *line = NULL; +- size_t len = 0; +- ssize_t read; +- +- f = fopen ("/proc/cpuinfo", "r"); +- if (f == NULL) +- { +- printf ("cannot open /proc/cpuinfo\n"); +- exit (1); +- } +- +- while ((read = getline (&line, &len, f)) != -1) +- { +- if (strncmp (line, "flags", 5) == 0) +- { +- cpu_flags = strdup (line); +- break; +- } +- } +- fclose (f); +- free (line); +-} +- +-int +-check_proc (const char *proc_name, int flag, const char *name) +-{ +- int found = 0; +- +- printf ("Checking %s:\n", name); +- printf (" init-arch %d\n", flag); +- if (strstr (cpu_flags, proc_name) != NULL) +- found = 1; +- printf (" cpuinfo (%s) %d\n", proc_name, found); +- +- if (found != flag) +- printf (" *** failure ***\n"); +- +- return (found != flag); +-} +- +-static int +-do_test (int argc, char **argv) +-{ +- int fails; +- +- get_cpuinfo (); +- fails = check_proc ("avx", CPU_FEATURE_USABLE (AVX), +- "CPU_FEATURE_USABLE (AVX)"); +- fails += check_proc ("fma4", CPU_FEATURE_USABLE (FMA4), +- "CPU_FEATURE_USABLE (FMA4)"); +- fails += check_proc ("sse4_2", CPU_FEATURE_USABLE (SSE4_2), +- "CPU_FEATURE_USABLE (SSE4_2)"); +- fails += check_proc ("sse4_1", CPU_FEATURE_USABLE (SSE4_1) +- , "CPU_FEATURE_USABLE (SSE4_1)"); +- fails += check_proc ("ssse3", CPU_FEATURE_USABLE (SSSE3), +- "CPU_FEATURE_USABLE (SSSE3)"); +- fails += check_proc ("popcnt", CPU_FEATURE_USABLE (POPCNT), +- "CPU_FEATURE_USABLE (POPCNT)"); +- +- printf ("%d differences between /proc/cpuinfo and glibc code.\n", fails); +- +- return (fails != 0); +-} +- +-#include "../../../test-skeleton.c" diff --git a/glibc-rh1817513-84.patch b/glibc-rh1817513-84.patch new file mode 100755 index 0000000..e7124ef --- /dev/null +++ b/glibc-rh1817513-84.patch @@ -0,0 +1,207 @@ +commit f2c679d4b2c73a95f437c705f960a4af1fa23498 +Author: H.J. Lu +Date: Tue Sep 15 05:49:27 2020 -0700 + + : Add Intel Key Locker support + + Add Intel Key Locker: + + https://software.intel.com/content/www/us/en/develop/download/intel-key-locker-specification.html + + support to . Intel Key Locker has + + 1. KL: AES Key Locker instructions. + 2. WIDE_KL: AES wide Key Locker instructions. + 3. AESKLE: AES Key Locker instructions are enabled by OS. + + Applications should use + + if (CPU_FEATURE_USABLE (KL)) + + and + + if (CPU_FEATURE_USABLE (WIDE_KL)) + + to check if AES Key Locker instructions and AES wide Key Locker + instructions are usable. + +diff --git a/manual/platform.texi b/manual/platform.texi +index 2c145acdc3564cbb..95b0ed0642c9f8a9 100644 +--- a/manual/platform.texi ++++ b/manual/platform.texi +@@ -177,6 +177,9 @@ The supported processor features are: + @item + @code{AES} -- The AES instruction extensions. + ++@item ++@code{AESKLE} -- AES Key Locker instructions are enabled by OS. ++ + @item + @code{AMX_BF16} -- Tile computational operations on bfloat16 numbers. + +@@ -353,6 +356,9 @@ the indirect branch predictor barrier (IBPB). + @item + @code{INVPCID} -- INVPCID instruction. + ++@item ++@code{KL} -- AES Key Locker instructions. ++ + @item + @code{L1D_FLUSH} -- IA32_FLUSH_CMD MSR. + +@@ -598,6 +604,9 @@ using a TSC deadline value. + @item + @code{WBNOINVD} -- WBINVD/WBNOINVD instructions. + ++@item ++@code{WIDE_KL} -- AES wide Key Locker instructions. ++ + @item + @code{X2APIC} -- x2APIC. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 6954728c47d0126b..77a596a15404b575 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -269,6 +269,14 @@ update_usable (struct cpu_features *cpu_features) + /* Determine if PKU is usable. */ + if (CPU_FEATURES_CPU_P (cpu_features, OSPKE)) + CPU_FEATURE_SET (cpu_features, PKU); ++ ++ /* Determine if Key Locker instructions are usable. */ ++ if (CPU_FEATURES_CPU_P (cpu_features, AESKLE)) ++ { ++ CPU_FEATURE_SET (cpu_features, AESKLE); ++ CPU_FEATURE_SET_USABLE (cpu_features, KL); ++ CPU_FEATURE_SET_USABLE (cpu_features, WIDE_KL); ++ } + } + + static void +@@ -341,6 +349,12 @@ get_common_indices (struct cpu_features *cpu_features, + cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.ecx, + cpu_features->features[COMMON_CPUID_INDEX_D_ECX_1].cpuid.edx); + ++ if (cpu_features->basic.max_cpuid >= 0x19) ++ __cpuid_count (0x19, 0, ++ cpu_features->features[COMMON_CPUID_INDEX_19].cpuid.eax, ++ cpu_features->features[COMMON_CPUID_INDEX_19].cpuid.ebx, ++ cpu_features->features[COMMON_CPUID_INDEX_19].cpuid.ecx, ++ cpu_features->features[COMMON_CPUID_INDEX_19].cpuid.edx); + } + + _Static_assert (((index_arch_Fast_Unaligned_Load +diff --git a/sysdeps/x86/sys/platform/x86.h b/sysdeps/x86/sys/platform/x86.h +index ebc5f6fc16cb8104..bcc81ab5f8ac8265 100644 +--- a/sysdeps/x86/sys/platform/x86.h ++++ b/sysdeps/x86/sys/platform/x86.h +@@ -28,6 +28,7 @@ enum + COMMON_CPUID_INDEX_80000007, + COMMON_CPUID_INDEX_80000008, + COMMON_CPUID_INDEX_7_ECX_1, ++ COMMON_CPUID_INDEX_19, + /* Keep the following line at the end. */ + COMMON_CPUID_INDEX_MAX + }; +@@ -224,7 +225,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + /* Note: Bits 17-21: The value of MAWAU used by the BNDLDX and BNDSTX + instructions in 64-bit mode. */ + #define bit_cpu_RDPID (1u << 22) +-#define bit_cpu_INDEX_7_ECX_23 (1u << 23) ++#define bit_cpu_KL (1u << 23) + #define bit_cpu_INDEX_7_ECX_24 (1u << 24) + #define bit_cpu_CLDEMOTE (1u << 25) + #define bit_cpu_INDEX_7_ECX_26 (1u << 26) +@@ -312,6 +313,12 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + /* EAX. */ + #define bit_cpu_AVX512_BF16 (1u << 5) + ++/* COMMON_CPUID_INDEX_19. */ ++ ++/* EBX. */ ++#define bit_cpu_AESKLE (1u << 0) ++#define bit_cpu_WIDE_KL (1u << 2) ++ + /* COMMON_CPUID_INDEX_1. */ + + /* ECX. */ +@@ -437,7 +444,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + #define index_cpu_INDEX_7_ECX_15 COMMON_CPUID_INDEX_7 + #define index_cpu_INDEX_7_ECX_16 COMMON_CPUID_INDEX_7 + #define index_cpu_RDPID COMMON_CPUID_INDEX_7 +-#define index_cpu_INDEX_7_ECX_23 COMMON_CPUID_INDEX_7 ++#define index_cpu_KL COMMON_CPUID_INDEX_7 + #define index_cpu_INDEX_7_ECX_24 COMMON_CPUID_INDEX_7 + #define index_cpu_CLDEMOTE COMMON_CPUID_INDEX_7 + #define index_cpu_INDEX_7_ECX_26 COMMON_CPUID_INDEX_7 +@@ -525,6 +532,12 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + /* EAX. */ + #define index_cpu_AVX512_BF16 COMMON_CPUID_INDEX_7_ECX_1 + ++/* COMMON_CPUID_INDEX_19. */ ++ ++/* EBX. */ ++#define index_cpu_AESKLE COMMON_CPUID_INDEX_19 ++#define index_cpu_WIDE_KL COMMON_CPUID_INDEX_19 ++ + /* COMMON_CPUID_INDEX_1. */ + + /* ECX. */ +@@ -650,7 +663,7 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + #define reg_INDEX_7_ECX_15 ecx + #define reg_INDEX_7_ECX_16 ecx + #define reg_RDPID ecx +-#define reg_INDEX_7_ECX_23 ecx ++#define reg_KL ecx + #define reg_INDEX_7_ECX_24 ecx + #define reg_CLDEMOTE ecx + #define reg_INDEX_7_ECX_26 ecx +@@ -738,4 +751,10 @@ extern const struct cpu_features *__x86_get_cpu_features (unsigned int) + /* EAX. */ + #define reg_AVX512_BF16 eax + ++/* COMMON_CPUID_INDEX_19. */ ++ ++/* EBX. */ ++#define reg_AESKLE ebx ++#define reg_WIDE_KL ebx ++ + #endif /* _SYS_PLATFORM_X86_H */ +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index 95e0d33f6c7eeace..c01d701b52090983 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -170,6 +170,7 @@ do_test (void) + CHECK_CPU_FEATURE (AVX512_BITALG); + CHECK_CPU_FEATURE (AVX512_VPOPCNTDQ); + CHECK_CPU_FEATURE (RDPID); ++ CHECK_CPU_FEATURE (KL); + CHECK_CPU_FEATURE (CLDEMOTE); + CHECK_CPU_FEATURE (MOVDIRI); + CHECK_CPU_FEATURE (MOVDIR64B); +@@ -217,6 +218,8 @@ do_test (void) + CHECK_CPU_FEATURE (INVARIANT_TSC); + CHECK_CPU_FEATURE (WBNOINVD); + CHECK_CPU_FEATURE (AVX512_BF16); ++ CHECK_CPU_FEATURE (AESKLE); ++ CHECK_CPU_FEATURE (WIDE_KL); + + printf ("Usable CPU features:\n"); + CHECK_CPU_FEATURE_USABLE (SSE3); +@@ -323,6 +326,7 @@ do_test (void) + CHECK_CPU_FEATURE_USABLE (AVX512_BITALG); + CHECK_CPU_FEATURE_USABLE (AVX512_VPOPCNTDQ); + CHECK_CPU_FEATURE_USABLE (RDPID); ++ CHECK_CPU_FEATURE_USABLE (KL); + CHECK_CPU_FEATURE_USABLE (CLDEMOTE); + CHECK_CPU_FEATURE_USABLE (MOVDIRI); + CHECK_CPU_FEATURE_USABLE (MOVDIR64B); +@@ -370,6 +374,8 @@ do_test (void) + CHECK_CPU_FEATURE_USABLE (INVARIANT_TSC); + CHECK_CPU_FEATURE_USABLE (WBNOINVD); + CHECK_CPU_FEATURE_USABLE (AVX512_BF16); ++ CHECK_CPU_FEATURE_USABLE (AESKLE); ++ CHECK_CPU_FEATURE_USABLE (WIDE_KL); + + return 0; + } diff --git a/glibc-rh1817513-85.patch b/glibc-rh1817513-85.patch new file mode 100755 index 0000000..10a18fa --- /dev/null +++ b/glibc-rh1817513-85.patch @@ -0,0 +1,73 @@ +commit 94cd37ebb293321115a36a422b091fdb72d2fb08 +Author: H.J. Lu +Date: Wed Sep 16 05:27:32 2020 -0700 + + x86: Use HAS_CPU_FEATURE with IBT and SHSTK [BZ #26625] + + commit 04bba1e5d84b6fd8d3a3b006bc240cd5d241ee30 + Author: H.J. Lu + Date: Wed Aug 5 13:51:56 2020 -0700 + + x86: Set CPU usable feature bits conservatively [BZ #26552] + + Set CPU usable feature bits only for CPU features which are usable in + user space and whose usability can be detected from user space, excluding + features like FSGSBASE whose enable bit can only be checked in the kernel. + + no longer turns on the usable bits of IBT and SHSTK since we don't know + if IBT and SHSTK are usable until much later. Use HAS_CPU_FEATURE to + check if the processor supports IBT and SHSTK. + +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 77a596a15404b575..7f2ff00f2b4b45f2 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -722,9 +722,9 @@ no_cpuid: + GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK + */ + unsigned int cet_feature = 0; +- if (!CPU_FEATURE_USABLE (IBT)) ++ if (!HAS_CPU_FEATURE (IBT)) + cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT; +- if (!CPU_FEATURE_USABLE (SHSTK)) ++ if (!HAS_CPU_FEATURE (SHSTK)) + cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK; + + if (cet_feature) +diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c +index 11ff0618fae7230f..d481bddc27e5d7cc 100644 +--- a/sysdeps/x86/dl-cet.c ++++ b/sysdeps/x86/dl-cet.c +@@ -74,10 +74,10 @@ dl_cet_check (struct link_map *m, const char *program) + + GLIBC_TUNABLES=glibc.cpu.hwcaps=-IBT,-SHSTK + */ +- enable_ibt &= (CPU_FEATURE_USABLE (IBT) ++ enable_ibt &= (HAS_CPU_FEATURE (IBT) + && (enable_ibt_type == cet_always_on + || (m->l_cet & lc_ibt) != 0)); +- enable_shstk &= (CPU_FEATURE_USABLE (SHSTK) ++ enable_shstk &= (HAS_CPU_FEATURE (SHSTK) + && (enable_shstk_type == cet_always_on + || (m->l_cet & lc_shstk) != 0)); + } +diff --git a/sysdeps/x86/tst-get-cpu-features.c b/sysdeps/x86/tst-get-cpu-features.c +index c01d701b52090983..3ec94e0c9a191f36 100644 +--- a/sysdeps/x86/tst-get-cpu-features.c ++++ b/sysdeps/x86/tst-get-cpu-features.c +@@ -318,7 +318,6 @@ do_test (void) + CHECK_CPU_FEATURE_USABLE (OSPKE); + CHECK_CPU_FEATURE_USABLE (WAITPKG); + CHECK_CPU_FEATURE_USABLE (AVX512_VBMI2); +- CHECK_CPU_FEATURE_USABLE (SHSTK); + CHECK_CPU_FEATURE_USABLE (GFNI); + CHECK_CPU_FEATURE_USABLE (VAES); + CHECK_CPU_FEATURE_USABLE (VPCLMULQDQ); +@@ -342,7 +341,6 @@ do_test (void) + CHECK_CPU_FEATURE_USABLE (HYBRID); + CHECK_CPU_FEATURE_USABLE (TSXLDTRK); + CHECK_CPU_FEATURE_USABLE (PCONFIG); +- CHECK_CPU_FEATURE_USABLE (IBT); + CHECK_CPU_FEATURE_USABLE (AMX_BF16); + CHECK_CPU_FEATURE_USABLE (AMX_TILE); + CHECK_CPU_FEATURE_USABLE (AMX_INT8); diff --git a/glibc-rh1817513-86.patch b/glibc-rh1817513-86.patch new file mode 100755 index 0000000..05a09e7 --- /dev/null +++ b/glibc-rh1817513-86.patch @@ -0,0 +1,173 @@ +commit c6702789344043fa998923c8f32ed0bdb2edfa9c +Author: Vincent Mihalkovic +Date: Tue Sep 29 12:34:39 2020 +0200 + + ld.so: add an --argv0 option [BZ #16124] + +Conflicts: + elf/Makefile + (Missing test backports.) + +diff --git a/elf/Makefile b/elf/Makefile +index 82b5b4a07495c805..837a070c267527e1 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -198,7 +198,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-dlopenfail tst-dlopenfail-2 \ + tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \ + tst-audit14 tst-audit15 tst-audit16 \ +- tst-tls-ie tst-tls-ie-dlmopen ++ tst-tls-ie tst-tls-ie-dlmopen \ ++ argv0test + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -395,7 +396,7 @@ endif + ifeq (yes,$(build-shared)) + ifeq ($(run-built-tests),yes) + tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \ +- $(objpfx)tst-rtld-preload.out ++ $(objpfx)tst-rtld-preload.out $(objpfx)argv0test.out + endif + tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \ + $(objpfx)check-wx-segment.out \ +@@ -1716,3 +1717,10 @@ $(objpfx)tst-tls-ie-dlmopen.out: \ + $(objpfx)tst-tls-ie-mod6.so + + $(objpfx)tst-tls-surplus: $(libdl) ++ ++$(objpfx)argv0test.out: tst-rtld-argv0.sh $(objpfx)ld.so \ ++ $(objpfx)argv0test ++ $(SHELL) $< $(objpfx)ld.so $(objpfx)argv0test \ ++ '$(test-wrapper-env)' '$(run_program_env)' \ ++ '$(rpath-link)' 'test-argv0' > $@; \ ++ $(evaluate-test) +diff --git a/elf/argv0test.c b/elf/argv0test.c +new file mode 100644 +index 0000000000000000..c22ba5ea70ed7dbf +--- /dev/null ++++ b/elf/argv0test.c +@@ -0,0 +1,31 @@ ++/* Test for --argv0 option ld.so. ++ ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++ ++static int ++do_test (int argc, char **argv) ++{ ++ TEST_COMPARE_STRING (argv[0], "test-argv0"); ++ return 0; ++} ++ ++#define TEST_FUNCTION_ARGV do_test ++#include +diff --git a/elf/rtld.c b/elf/rtld.c +index 67441ac6f252350e..4107a215abd554f4 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1196,6 +1196,8 @@ dl_main (const ElfW(Phdr) *phdr, + installing it. */ + rtld_is_main = true; + ++ char *argv0 = NULL; ++ + /* Note the place where the dynamic linker actually came from. */ + GL(dl_rtld_map).l_name = rtld_progname; + +@@ -1253,6 +1255,14 @@ dl_main (const ElfW(Phdr) *phdr, + else if (! strcmp (_dl_argv[1], "--preload") && _dl_argc > 2) + { + preloadarg = _dl_argv[2]; ++ _dl_skip_args += 2; ++ _dl_argc -= 2; ++ _dl_argv += 2; ++ } ++ else if (! strcmp (_dl_argv[1], "--argv0") && _dl_argc > 2) ++ { ++ argv0 = _dl_argv[2]; ++ + _dl_skip_args += 2; + _dl_argc -= 2; + _dl_argv += 2; +@@ -1286,7 +1296,8 @@ of this helper program; chances are you did not intend to run this program.\n\ + --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\ + in LIST\n\ + --audit LIST use objects named in LIST as auditors\n\ +- --preload LIST preload objects named in LIST\n"); ++ --preload LIST preload objects named in LIST\n\ ++ --argv0 STRING set argv[0] to STRING before running\n"); + + ++_dl_skip_args; + --_dl_argc; +@@ -1378,6 +1389,10 @@ of this helper program; chances are you did not intend to run this program.\n\ + break; + } + #endif ++ ++ /* Set the argv[0] string now that we've processed the executable. */ ++ if (argv0 != NULL) ++ _dl_argv[0] = argv0; + } + else + { +diff --git a/elf/tst-rtld-argv0.sh b/elf/tst-rtld-argv0.sh +new file mode 100755 +index 0000000000000000..14d97fb375fc652b +--- /dev/null ++++ b/elf/tst-rtld-argv0.sh +@@ -0,0 +1,37 @@ ++#!/bin/sh ++# Test for --argv0 option ld.so. ++# Copyright (C) 2020 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 ++# . ++ ++set -e ++ ++rtld=$1 ++test_program=$2 ++test_wrapper_env=$3 ++run_program_env=$4 ++library_path=$5 ++argv0=$6 ++ ++echo "# [${test_wrapper_env}] [${run_program_env}] [$rtld] [--library-path]" \ ++ "[$library_path] [--argv0] [$argv0] [$test_program]" ++${test_wrapper_env} \ ++${run_program_env} \ ++$rtld --library-path "$library_path" \ ++ --argv0 "$argv0" $test_program 2>&1 && rc=0 || rc=$? ++echo "# exit status $rc" ++ ++exit $rc diff --git a/glibc-rh1817513-87.patch b/glibc-rh1817513-87.patch new file mode 100755 index 0000000..b3c202c --- /dev/null +++ b/glibc-rh1817513-87.patch @@ -0,0 +1,97 @@ +commit 56f8d442942ee51824b4683be83f776a811a3f2a +Author: Florian Weimer +Date: Wed Oct 7 16:40:23 2020 +0200 + + elf: Do not search HWCAP subdirectories in statically linked binaries + + This functionality does not seem to be useful since static dlopen + is mostly used for iconv/character set conversion and NSS support. + gconv modules are loaded with full paths anyway, so that the + HWCAP subdirectory logic does not apply. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/Makefile b/elf/Makefile +index 837a070c267527e1..ef655630d50b07aa 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -29,7 +29,7 @@ routines = $(all-dl-routines) dl-support dl-iteratephdr \ + + # The core dynamic linking functions are in libc for the static and + # profiled libraries. +-dl-routines = $(addprefix dl-,load lookup object reloc deps hwcaps \ ++dl-routines = $(addprefix dl-,load lookup object reloc deps \ + runtime init fini debug misc \ + version profile tls origin scope \ + execstack open close trampoline \ +@@ -59,7 +59,7 @@ elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ + # ld.so uses those routines, plus some special stuff for being the program + # interpreter and operating independent of libc. + rtld-routines = rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal \ +- dl-error-minimal dl-conflict ++ dl-error-minimal dl-conflict dl-hwcaps + all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines) + + CFLAGS-dl-runtime.c += -fexceptions -fasynchronous-unwind-tables +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 64da5323d0e368c1..2b4dd9a0f3e27b70 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -101,9 +101,13 @@ int __stack_prot attribute_hidden attribute_relro + static struct r_search_path_struct env_path_list attribute_relro; + + /* List of the hardware capabilities we might end up using. */ ++#ifdef SHARED + static const struct r_strlenpair *capstr attribute_relro; + static size_t ncapstr attribute_relro; + static size_t max_capstrlen attribute_relro; ++#else ++enum { ncapstr = 1, max_capstrlen = 0 }; ++#endif + + + /* Get the generated information about the trusted directories. Use +@@ -691,9 +695,11 @@ _dl_init_paths (const char *llp) + /* Fill in the information about the application's RPATH and the + directories addressed by the LD_LIBRARY_PATH environment variable. */ + ++#ifdef SHARED + /* Get the capabilities. */ + capstr = _dl_important_hwcaps (GLRO(dl_platform), GLRO(dl_platformlen), + &ncapstr, &max_capstrlen); ++#endif + + /* First set up the rest of the default search directory entries. */ + aelem = rtld_search_dirs.dirs = (struct r_search_path_elem **) +@@ -1459,11 +1465,15 @@ print_search_path (struct r_search_path_elem **list, + for (cnt = 0; cnt < ncapstr; ++cnt) + if ((*list)->status[cnt] != nonexisting) + { ++#ifdef SHARED + char *cp = __mempcpy (endp, capstr[cnt].str, capstr[cnt].len); + if (cp == buf || (cp == buf + 1 && buf[0] == '/')) + cp[0] = '\0'; + else + cp[-1] = '\0'; ++#else ++ *endp = '\0'; ++#endif + + _dl_debug_printf_c (first ? "%s" : ":%s", buf); + first = 0; +@@ -1836,11 +1846,15 @@ open_path (const char *name, size_t namelen, int mode, + if (this_dir->status[cnt] == nonexisting) + continue; + ++#ifdef SHARED + buflen = + ((char *) __mempcpy (__mempcpy (edp, capstr[cnt].str, + capstr[cnt].len), + name, namelen) + - buf); ++#else ++ buflen = (char *) __mempcpy (edp, name, namelen) - buf; ++#endif + + /* Print name we try if this is wanted. */ + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_LIBS)) diff --git a/glibc-rh1817513-88.patch b/glibc-rh1817513-88.patch new file mode 100755 index 0000000..6100353 --- /dev/null +++ b/glibc-rh1817513-88.patch @@ -0,0 +1,144 @@ +commit b31d4355ae817aa3caf9414f842cc07465bca028 +Author: Florian Weimer +Date: Wed Oct 7 16:39:50 2020 +0200 + + elf: Implement _dl_write + + The generic version is parallel to _dl_writev. It cannot use + _dl_writev directly because the errno value needs to be obtained + under a lock. + + Reviewed-by: Adhemerval Zanella + +Backport adjusted for different INTERNAL_SYSCALL_CALL definition +downstream. + +diff --git a/elf/Makefile b/elf/Makefile +index ef655630d50b07aa..e2078f6bc325b7e0 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -34,7 +34,7 @@ dl-routines = $(addprefix dl-,load lookup object reloc deps \ + version profile tls origin scope \ + execstack open close trampoline \ + exception sort-maps lookup-direct \ +- call-libc-early-init) ++ call-libc-early-init write) + ifeq (yes,$(use-ldconfig)) + dl-routines += dl-cache + endif +diff --git a/elf/dl-write.c b/elf/dl-write.c +new file mode 100644 +index 0000000000000000..7350aff0035d4fbc +--- /dev/null ++++ b/elf/dl-write.c +@@ -0,0 +1,56 @@ ++/* Implementation of the _dl_write function. Generic version. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++ssize_t ++_dl_write (int fd, const void *buffer, size_t length) ++{ ++ struct iovec iov = { .iov_base = (void *) buffer, .iov_len = length }; ++ ssize_t ret; ++ ++#if RTLD_PRIVATE_ERRNO ++ /* We have to take this lock just to be sure we don't clobber the private ++ errno when it's being used by another thread that cares about it. ++ Yet we must be sure not to try calling the lock functions before ++ the thread library is fully initialized. */ ++ if (__glibc_unlikely (_dl_starting_up)) ++ { ++ ret = __writev (fd, &iov, 1); ++ if (ret < 0) ++ ret = -errno; ++ } ++ else ++ { ++ __rtld_lock_lock_recursive (GL(dl_load_lock)); ++ __writev (fd, &iov, 1); ++ if (ret < 0) ++ ret = -errno; ++ __rtld_lock_unlock_recursive (GL(dl_load_lock)); ++ } ++#else ++ ret = __writev (fd, &iov, 1); ++ if (ret < 0) ++ ret = -errno; ++#endif ++ ++ return ret; ++} +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 37f1915b0c75a020..4aa28b0229e0b339 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -754,6 +754,12 @@ _dl_dprintf (int fd, const char *fmt, ...) + } + #endif + ++/* Write LENGTH bytes at BUFFER to FD, like write. Returns the number ++ of bytes written on success, or a negative error constant on ++ failure. */ ++ssize_t _dl_write (int fd, const void *buffer, size_t length) ++ attribute_hidden; ++ + /* Write a message on the specified descriptor standard output. The + parameters are interpreted as for a `printf' call. */ + #define _dl_printf(fmt, args...) \ +diff --git a/sysdeps/unix/sysv/linux/dl-write.c b/sysdeps/unix/sysv/linux/dl-write.c +new file mode 100644 +index 0000000000000000..2c670a8059077076 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/dl-write.c +@@ -0,0 +1,31 @@ ++/* Implementation of the _dl_write function. Linux version. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++ssize_t ++_dl_write (int fd, const void *buffer, size_t length) ++{ ++ INTERNAL_SYSCALL_DECL (err); ++ long int r = INTERNAL_SYSCALL_CALL (write, err, fd, buffer, length); ++ if (INTERNAL_SYSCALL_ERROR_P (r, err)) ++ r = - INTERNAL_SYSCALL_ERRNO (r, err); ++ return r; ++} diff --git a/glibc-rh1817513-89.patch b/glibc-rh1817513-89.patch new file mode 100755 index 0000000..64a511e --- /dev/null +++ b/glibc-rh1817513-89.patch @@ -0,0 +1,46 @@ +commit 72d36ffd7db55ae599f4c77feb0eae25a0f3714e +Author: Florian Weimer +Date: Thu Oct 8 10:57:09 2020 +0200 + + elf: Implement __rtld_malloc_is_complete + + In some cases, it is difficult to determine the kind of malloc + based on the execution context, so a function to determine that + is helpful. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c +index 4335f1bd24289b01..cf7df8a8d5eabe9d 100644 +--- a/elf/dl-minimal.c ++++ b/elf/dl-minimal.c +@@ -59,6 +59,14 @@ __rtld_malloc_init_stubs (void) + __rtld_realloc = &rtld_realloc; + } + ++bool ++__rtld_malloc_is_complete (void) ++{ ++ /* The caller assumes that there is an active malloc. */ ++ assert (__rtld_malloc != NULL); ++ return __rtld_malloc != &rtld_malloc; ++} ++ + /* Lookup NAME at VERSION in the scope of MATCH. */ + static void * + lookup_malloc_symbol (struct link_map *main_map, const char *name, +diff --git a/include/rtld-malloc.h b/include/rtld-malloc.h +index b026a3270cd24819..9266ec532f3f3376 100644 +--- a/include/rtld-malloc.h ++++ b/include/rtld-malloc.h +@@ -66,6 +66,10 @@ realloc (void *ptr, size_t size) + implementation. */ + void __rtld_malloc_init_stubs (void) attribute_hidden; + ++/* Return false if the active malloc is the ld.so minimal malloc, true ++ if it is the full implementation from libc.so. */ ++_Bool __rtld_malloc_is_complete (void) attribute_hidden; ++ + /* Called shortly before the final self-relocation (when RELRO + variables are still writable) to activate the real malloc + implementation. MAIN_MAP is the link map of the executable. */ diff --git a/glibc-rh1817513-9.patch b/glibc-rh1817513-9.patch new file mode 100755 index 0000000..06b352b --- /dev/null +++ b/glibc-rh1817513-9.patch @@ -0,0 +1,247 @@ +commit 72771e53753647111d31c5c4bf43d8901e6baf7e +Author: H.J. Lu +Date: Wed Oct 17 15:16:38 2018 -0700 + + x86: Use _rdtsc intrinsic for HP_TIMING_NOW + + Since _rdtsc intrinsic is supported in GCC 4.9, we can use it for + HP_TIMING_NOW. This patch + + 1. Create x86 hp-timing.h to replace i686 and x86_64 hp-timing.h. + 2. Move MINIMUM_ISA from init-arch.h to isa.h so that x86 hp-timing.h + can check minimum x86 ISA to decide if _rdtsc can be used. + + NB: Checking if __i686__ isn't sufficient since __i686__ may not be + defined when building for i686 class processors. + + * sysdeps/i386/init-arch.h: Removed. + * sysdeps/i386/i586/init-arch.h: Likewise. + * sysdeps/i386/i686/init-arch.h: Likewise. + * sysdeps/i386/i686/hp-timing.h: Likewise. + * sysdeps/x86_64/hp-timing.h: Likewise. + * sysdeps/i386/isa.h: New file. + * sysdeps/i386/i586/isa.h: Likewise. + * sysdeps/i386/i686/isa.h: Likewise. + * sysdeps/x86_64/isa.h: Likewise. + * sysdeps/x86/hp-timing.h: New file. + * sysdeps/x86/init-arch.h: Include . + +diff --git a/sysdeps/i386/i586/init-arch.h b/sysdeps/i386/i586/isa.h +similarity index 85% +rename from sysdeps/i386/i586/init-arch.h +rename to sysdeps/i386/i586/isa.h +index 72fb46c61e4c5f34..79481ce68033e58c 100644 +--- a/sysdeps/i386/i586/init-arch.h ++++ b/sysdeps/i386/i586/isa.h +@@ -1,4 +1,5 @@ +-/* Copyright (C) 2015-2018 Free Software Foundation, Inc. ++/* x86 ISA info. i586 version. ++ Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -15,5 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + ++#ifndef _ISA_H ++#define _ISA_H ++ + #define MINIMUM_ISA 586 +-#include ++ ++#endif +diff --git a/sysdeps/i386/i686/init-arch.h b/sysdeps/i386/i686/isa.h +similarity index 85% +rename from sysdeps/i386/i686/init-arch.h +rename to sysdeps/i386/i686/isa.h +index ab99392b586b1e2d..584e26bd4f928021 100644 +--- a/sysdeps/i386/i686/init-arch.h ++++ b/sysdeps/i386/i686/isa.h +@@ -1,4 +1,5 @@ +-/* Copyright (C) 2015-2018 Free Software Foundation, Inc. ++/* x86 ISA info. i686 version. ++ Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -15,5 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + ++#ifndef _ISA_H ++#define _ISA_H ++ + #define MINIMUM_ISA 686 +-#include ++ ++#endif +diff --git a/sysdeps/i386/init-arch.h b/sysdeps/i386/isa.h +similarity index 85% +rename from sysdeps/i386/init-arch.h +rename to sysdeps/i386/isa.h +index 043089ceb99db33f..e0a1e9c84fd37efb 100644 +--- a/sysdeps/i386/init-arch.h ++++ b/sysdeps/i386/isa.h +@@ -1,4 +1,5 @@ +-/* Copyright (C) 2015-2018 Free Software Foundation, Inc. ++/* x86 ISA info. i486 version. ++ Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -15,5 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + ++#ifndef _ISA_H ++#define _ISA_H ++ + #define MINIMUM_ISA 486 +-#include ++ ++#endif +diff --git a/sysdeps/i386/i686/hp-timing.h b/sysdeps/x86/hp-timing.h +similarity index 69% +rename from sysdeps/i386/i686/hp-timing.h +rename to sysdeps/x86/hp-timing.h +index 59af526fdba0b6f5..1c20e9d8289cc15b 100644 +--- a/sysdeps/i386/i686/hp-timing.h ++++ b/sysdeps/x86/hp-timing.h +@@ -1,7 +1,6 @@ +-/* High precision, low overhead timing functions. i686 version. +- Copyright (C) 1998-2018 Free Software Foundation, Inc. ++/* High precision, low overhead timing functions. x86 version. ++ Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. +- Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public +@@ -20,12 +19,17 @@ + #ifndef _HP_TIMING_H + #define _HP_TIMING_H 1 + ++#include ++ ++#if MINIMUM_ISA == 686 || MINIMUM_ISA == 8664 ++# include ++ + /* We always assume having the timestamp register. */ +-#define HP_TIMING_AVAIL (1) +-#define HP_SMALL_TIMING_AVAIL (1) ++# define HP_TIMING_AVAIL (1) ++# define HP_SMALL_TIMING_AVAIL (1) + + /* We indeed have inlined functions. */ +-#define HP_TIMING_INLINE (1) ++# define HP_TIMING_INLINE (1) + + /* We use 64bit values for the times. */ + typedef unsigned long long int hp_timing_t; +@@ -35,8 +39,14 @@ typedef unsigned long long int hp_timing_t; + running in this moment. This could be changed by using a barrier like + 'cpuid' right before the `rdtsc' instruciton. But we are not interested + in accurate clock cycles here so we don't do this. */ +-#define HP_TIMING_NOW(Var) __asm__ __volatile__ ("rdtsc" : "=A" (Var)) ++# define HP_TIMING_NOW(Var) ((Var) = _rdtsc ()) + +-#include ++# include ++#else ++/* NB: Undefine _HP_TIMING_H so that will ++ be included. */ ++# undef _HP_TIMING_H ++# include ++#endif + +-#endif /* hp-timing.h */ ++#endif /* hp-timing.h */ +diff --git a/sysdeps/x86/init-arch.h b/sysdeps/x86/init-arch.h +index a81ca8a4eb292e72..bc860fcd69a605b3 100644 +--- a/sysdeps/x86/init-arch.h ++++ b/sysdeps/x86/init-arch.h +@@ -21,6 +21,7 @@ + # include + #endif + #include ++#include + + #ifndef __x86_64__ + /* Due to the reordering and the other nifty extensions in i686, it is +diff --git a/sysdeps/x86_64/hp-timing.h b/sysdeps/x86_64/hp-timing.h +deleted file mode 100644 +index ec543bef03b6c2d1..0000000000000000 +--- a/sysdeps/x86_64/hp-timing.h ++++ /dev/null +@@ -1,40 +0,0 @@ +-/* High precision, low overhead timing functions. x86-64 version. +- Copyright (C) 2002-2018 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 +- . */ +- +-#ifndef _HP_TIMING_H +-#define _HP_TIMING_H 1 +- +-/* We always assume having the timestamp register. */ +-#define HP_TIMING_AVAIL (1) +-#define HP_SMALL_TIMING_AVAIL (1) +- +-/* We indeed have inlined functions. */ +-#define HP_TIMING_INLINE (1) +- +-/* We use 64bit values for the times. */ +-typedef unsigned long long int hp_timing_t; +- +-/* The "=A" constraint used in 32-bit mode does not work in 64-bit mode. */ +-#define HP_TIMING_NOW(Var) \ +- ({ unsigned int _hi, _lo; \ +- asm volatile ("rdtsc" : "=a" (_lo), "=d" (_hi)); \ +- (Var) = ((unsigned long long int) _hi << 32) | _lo; }) +- +-#include +- +-#endif /* hp-timing.h */ +diff --git a/sysdeps/x86_64/isa.h b/sysdeps/x86_64/isa.h +new file mode 100644 +index 0000000000000000..452bce75eb03a474 +--- /dev/null ++++ b/sysdeps/x86_64/isa.h +@@ -0,0 +1,24 @@ ++/* x86 ISA info. x86-64 version. ++ Copyright (C) 2018 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 ++ . */ ++ ++#ifndef _ISA_H ++#define _ISA_H ++ ++#define MINIMUM_ISA 8664 ++ ++#endif diff --git a/glibc-rh1817513-90.patch b/glibc-rh1817513-90.patch new file mode 100755 index 0000000..344808e --- /dev/null +++ b/glibc-rh1817513-90.patch @@ -0,0 +1,568 @@ +commit 2bf9e641fd50ec34b04b70829679abf64fc0ed78 +Author: Florian Weimer +Date: Thu Oct 8 10:57:09 2020 +0200 + + elf: Extract command-line/environment variables state from rtld.c + + Introduce struct dl_main_state and move it to . Rename + enum mode to enum rtld_mode and add the rtld_mode_ prefix to the enum + constants. + + This avoids the need for putting state that is only needed during + startup into the ld.so data segment. + +Conflicts: + elf/rtld.c + (Caused by glibc-fedora-__libc_multiple_libcs.patch.) + +diff --git a/elf/dl-main.h b/elf/dl-main.h +new file mode 100644 +index 0000000000000000..bcc9bcf2e8fee6e7 +--- /dev/null ++++ b/elf/dl-main.h +@@ -0,0 +1,98 @@ ++/* Information collection during ld.so startup. ++ Copyright (C) 1995-2020 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 ++ . */ ++ ++#ifndef _DL_MAIN ++#define _DL_MAIN ++ ++#include ++ ++/* Length limits for names and paths, to protect the dynamic linker, ++ particularly when __libc_enable_secure is active. */ ++#ifdef NAME_MAX ++# define SECURE_NAME_LIMIT NAME_MAX ++#else ++# define SECURE_NAME_LIMIT 255 ++#endif ++#ifdef PATH_MAX ++# define SECURE_PATH_LIMIT PATH_MAX ++#else ++# define SECURE_PATH_LIMIT 1024 ++#endif ++ ++/* Strings containing colon-separated lists of audit modules. */ ++struct audit_list ++{ ++ /* Array of strings containing colon-separated path lists. Each ++ audit module needs its own namespace, so pre-allocate the largest ++ possible list. */ ++ const char *audit_strings[DL_NNS]; ++ ++ /* Number of entries added to audit_strings. */ ++ size_t length; ++ ++ /* Index into the audit_strings array (for the iteration phase). */ ++ size_t current_index; ++ ++ /* Tail of audit_strings[current_index] which still needs ++ processing. */ ++ const char *current_tail; ++ ++ /* Scratch buffer for returning a name which is part of the strings ++ in audit_strings. */ ++ char fname[SECURE_NAME_LIMIT]; ++}; ++ ++/* This is a list of all the modes the dynamic loader can be in. */ ++enum rtld_mode ++ { ++ rtld_mode_normal, rtld_mode_list, rtld_mode_verify, rtld_mode_trace, ++ }; ++ ++/* Aggregated state information extracted from environment variables ++ and the ld.so command line. */ ++struct dl_main_state ++{ ++ struct audit_list audit_list; ++ ++ /* The library search path. */ ++ const char *library_path; ++ ++ /* The list preloaded objects from LD_PRELOAD. */ ++ const char *preloadlist; ++ ++ /* The preload list passed as a command argument. */ ++ const char *preloadarg; ++ ++ enum rtld_mode mode; ++ ++ /* True if any of the debugging options is enabled. */ ++ bool any_debug; ++ ++ /* True if information about versions has to be printed. */ ++ bool version_info; ++}; ++ ++/* Helper function to invoke _dl_init_paths with the right arguments ++ from *STATE. */ ++static inline void ++call_init_paths (const struct dl_main_state *state) ++{ ++ _dl_init_paths (state->library_path); ++} ++ ++#endif /* _DL_MAIN */ +diff --git a/elf/rtld.c b/elf/rtld.c +index 4107a215abd554f4..fbfa441bf3b050ff 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + + #include + +@@ -109,42 +110,6 @@ static void print_missing_version (int errcode, const char *objname, + /* Print the various times we collected. */ + static void print_statistics (const hp_timing_t *total_timep); + +-/* Length limits for names and paths, to protect the dynamic linker, +- particularly when __libc_enable_secure is active. */ +-#ifdef NAME_MAX +-# define SECURE_NAME_LIMIT NAME_MAX +-#else +-# define SECURE_NAME_LIMIT 255 +-#endif +-#ifdef PATH_MAX +-# define SECURE_PATH_LIMIT PATH_MAX +-#else +-# define SECURE_PATH_LIMIT 1024 +-#endif +- +-/* Strings containing colon-separated lists of audit modules. */ +-struct audit_list +-{ +- /* Array of strings containing colon-separated path lists. Each +- audit module needs its own namespace, so pre-allocate the largest +- possible list. */ +- const char *audit_strings[DL_NNS]; +- +- /* Number of entries added to audit_strings. */ +- size_t length; +- +- /* Index into the audit_strings array (for the iteration phase). */ +- size_t current_index; +- +- /* Tail of audit_strings[current_index] which still needs +- processing. */ +- const char *current_tail; +- +- /* Scratch buffer for returning a name which is part of the strings +- in audit_strings. */ +- char fname[SECURE_NAME_LIMIT]; +-}; +- + /* Creates an empty audit list. */ + static void audit_list_init (struct audit_list *); + +@@ -165,13 +130,13 @@ static void audit_list_add_dynamic_tag (struct audit_list *, + audit_list_add_dynamic_tags calls. */ + static const char *audit_list_next (struct audit_list *); + +-/* This is a list of all the modes the dynamic loader can be in. */ +-enum mode { normal, list, verify, trace }; ++/* Initialize *STATE with the defaults. */ ++static void dl_main_state_init (struct dl_main_state *state); + + /* Process all environments variables the dynamic linker must recognize. + Since all of them start with `LD_' we are a bit smarter while finding + all the entries. */ +-static void process_envvars (enum mode *modep, struct audit_list *); ++static void process_envvars (struct dl_main_state *state); + + #ifdef DL_ARGV_NOT_RELRO + int _dl_argc attribute_hidden; +@@ -314,6 +279,18 @@ audit_list_count (struct audit_list *list) + return naudit; + } + ++static void ++dl_main_state_init (struct dl_main_state *state) ++{ ++ audit_list_init (&state->audit_list); ++ state->library_path = NULL; ++ state->preloadlist = NULL; ++ state->preloadarg = NULL; ++ state->mode = rtld_mode_normal; ++ state->any_debug = false; ++ state->version_info = false; ++} ++ + /* Set nonzero during loading and initialization of executable and + libraries, cleared before the executable's entry point runs. This + must not be initialized to nonzero, because the unused dynamic +@@ -896,15 +873,6 @@ security_init (void) + + #include "setup-vdso.h" + +-/* The library search path. */ +-static const char *library_path attribute_relro; +-/* The list preloaded objects. */ +-static const char *preloadlist attribute_relro; +-/* Nonzero if information about versions has to be printed. */ +-static int version_info attribute_relro; +-/* The preload list passed as a command argument. */ +-static const char *preloadarg attribute_relro; +- + /* The LD_PRELOAD environment variable gives list of libraries + separated by white space or colons that are loaded before the + executable's dependencies and prepended to the global scope list. +@@ -1146,7 +1114,6 @@ dl_main (const ElfW(Phdr) *phdr, + ElfW(auxv_t) *auxv) + { + const ElfW(Phdr) *ph; +- enum mode mode; + struct link_map *main_map; + size_t file_size; + char *file; +@@ -1156,8 +1123,8 @@ dl_main (const ElfW(Phdr) *phdr, + bool rtld_is_main = false; + void *tcbp = NULL; + +- struct audit_list audit_list; +- audit_list_init (&audit_list); ++ struct dl_main_state state; ++ dl_main_state_init (&state); + + GL(dl_init_static_tls) = &_dl_nothread_init_static_tls; + +@@ -1172,7 +1139,7 @@ dl_main (const ElfW(Phdr) *phdr, + GL(dl_make_stack_executable_hook) = &_dl_make_stack_executable; + + /* Process the environment variable which control the behaviour. */ +- process_envvars (&mode, &audit_list); ++ process_envvars (&state); + + /* Set up a flag which tells we are just starting. */ + _dl_starting_up = 1; +@@ -1204,7 +1171,7 @@ dl_main (const ElfW(Phdr) *phdr, + while (_dl_argc > 1) + if (! strcmp (_dl_argv[1], "--list")) + { +- mode = list; ++ state.mode = rtld_mode_list; + GLRO(dl_lazy) = -1; /* This means do no dependency analysis. */ + + ++_dl_skip_args; +@@ -1213,7 +1180,7 @@ dl_main (const ElfW(Phdr) *phdr, + } + else if (! strcmp (_dl_argv[1], "--verify")) + { +- mode = verify; ++ state.mode = rtld_mode_verify; + + ++_dl_skip_args; + --_dl_argc; +@@ -1229,7 +1196,7 @@ dl_main (const ElfW(Phdr) *phdr, + else if (! strcmp (_dl_argv[1], "--library-path") + && _dl_argc > 2) + { +- library_path = _dl_argv[2]; ++ state.library_path = _dl_argv[2]; + + _dl_skip_args += 2; + _dl_argc -= 2; +@@ -1246,7 +1213,7 @@ dl_main (const ElfW(Phdr) *phdr, + } + else if (! strcmp (_dl_argv[1], "--audit") && _dl_argc > 2) + { +- audit_list_add_string (&audit_list, _dl_argv[2]); ++ audit_list_add_string (&state.audit_list, _dl_argv[2]); + + _dl_skip_args += 2; + _dl_argc -= 2; +@@ -1254,7 +1221,7 @@ dl_main (const ElfW(Phdr) *phdr, + } + else if (! strcmp (_dl_argv[1], "--preload") && _dl_argc > 2) + { +- preloadarg = _dl_argv[2]; ++ state.preloadarg = _dl_argv[2]; + _dl_skip_args += 2; + _dl_argc -= 2; + _dl_argv += 2; +@@ -1322,7 +1289,7 @@ of this helper program; chances are you did not intend to run this program.\n\ + break; + } + +- if (__builtin_expect (mode, normal) == verify) ++ if (__glibc_unlikely (state.mode == rtld_mode_verify)) + { + const char *objname; + const char *err_str = NULL; +@@ -1351,7 +1318,7 @@ of this helper program; chances are you did not intend to run this program.\n\ + /* Now the map for the main executable is available. */ + main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; + +- if (__builtin_expect (mode, normal) == normal ++ if (__glibc_likely (state.mode == rtld_mode_normal) + && GL(dl_rtld_map).l_info[DT_SONAME] != NULL + && main_map->l_info[DT_SONAME] != NULL + && strcmp ((const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB]) +@@ -1592,7 +1559,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + _dl_setup_hash (main_map); + } + +- if (__builtin_expect (mode, normal) == verify) ++ if (__glibc_unlikely (state.mode == rtld_mode_verify)) + { + /* We were called just to verify that this is a dynamic + executable using us as the program interpreter. Exit with an +@@ -1619,7 +1586,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + + /* Initialize the data structures for the search paths for shared + objects. */ +- _dl_init_paths (library_path); ++ call_init_paths (&state); + + /* Initialize _r_debug. */ + struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr, +@@ -1684,14 +1651,14 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + /* Assign a module ID. Do this before loading any audit modules. */ + GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid (); + +- audit_list_add_dynamic_tag (&audit_list, main_map, DT_AUDIT); +- audit_list_add_dynamic_tag (&audit_list, main_map, DT_DEPAUDIT); ++ audit_list_add_dynamic_tag (&state.audit_list, main_map, DT_AUDIT); ++ audit_list_add_dynamic_tag (&state.audit_list, main_map, DT_DEPAUDIT); + + /* If we have auditing DSOs to load, do it now. */ + bool need_security_init = true; +- if (audit_list.length > 0) ++ if (state.audit_list.length > 0) + { +- size_t naudit = audit_list_count (&audit_list); ++ size_t naudit = audit_list_count (&state.audit_list); + + /* Since we start using the auditing DSOs right away we need to + initialize the data structures now. */ +@@ -1704,7 +1671,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + security_init (); + need_security_init = false; + +- load_audit_modules (main_map, &audit_list); ++ load_audit_modules (main_map, &state.audit_list); + + /* The count based on audit strings may overestimate the number + of audit modules that got loaded, but not underestimate. */ +@@ -1759,19 +1726,21 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + struct link_map **preloads = NULL; + unsigned int npreloads = 0; + +- if (__glibc_unlikely (preloadlist != NULL)) ++ if (__glibc_unlikely (state.preloadlist != NULL)) + { + RTLD_TIMING_VAR (start); + rtld_timer_start (&start); +- npreloads += handle_preload_list (preloadlist, main_map, "LD_PRELOAD"); ++ npreloads += handle_preload_list (state.preloadlist, main_map, ++ "LD_PRELOAD"); + rtld_timer_accum (&load_time, start); + } + +- if (__glibc_unlikely (preloadarg != NULL)) ++ if (__glibc_unlikely (state.preloadarg != NULL)) + { + RTLD_TIMING_VAR (start); + rtld_timer_start (&start); +- npreloads += handle_preload_list (preloadarg, main_map, "--preload"); ++ npreloads += handle_preload_list (state.preloadarg, main_map, ++ "--preload"); + rtld_timer_accum (&load_time, start); + } + +@@ -1878,7 +1847,8 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + { + RTLD_TIMING_VAR (start); + rtld_timer_start (&start); +- _dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0); ++ _dl_map_object_deps (main_map, preloads, npreloads, ++ state.mode == rtld_mode_trace, 0); + rtld_timer_accum (&load_time, start); + } + +@@ -1905,7 +1875,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + rtld_multiple_ref = true; + + GL(dl_rtld_map).l_prev = main_map->l_searchlist.r_list[i - 1]; +- if (__builtin_expect (mode, normal) == normal) ++ if (__glibc_likely (state.mode == rtld_mode_normal)) + { + GL(dl_rtld_map).l_next = (i + 1 < main_map->l_searchlist.r_nlist + ? main_map->l_searchlist.r_list[i + 1] +@@ -1938,8 +1908,8 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + versions we need. */ + { + struct version_check_args args; +- args.doexit = mode == normal; +- args.dotrace = mode == trace; ++ args.doexit = state.mode == rtld_mode_normal; ++ args.dotrace = state.mode == rtld_mode_trace; + _dl_receive_error (print_missing_version, version_check_doit, &args); + } + +@@ -1959,7 +1929,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + earlier. */ + security_init (); + +- if (__builtin_expect (mode, normal) != normal) ++ if (__glibc_unlikely (state.mode != rtld_mode_normal)) + { + /* We were run just to list the shared libraries. It is + important that we do this before real relocation, because the +@@ -2061,7 +2031,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + (size_t) l->l_map_start); + } + +- if (__builtin_expect (mode, trace) != trace) ++ if (__glibc_unlikely (state.mode != rtld_mode_trace)) + for (i = 1; i < (unsigned int) _dl_argc; ++i) + { + const ElfW(Sym) *ref = NULL; +@@ -2115,7 +2085,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + } + } + #define VERNEEDTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED)) +- if (version_info) ++ if (state.version_info) + { + /* Print more information. This means here, print information + about the versions needed. */ +@@ -2477,13 +2447,10 @@ print_missing_version (int errcode __attribute__ ((unused)), + objname, errstring); + } + +-/* Nonzero if any of the debugging options is enabled. */ +-static int any_debug attribute_relro; +- + /* Process the string given as the parameter which explains which debugging + options are enabled. */ + static void +-process_dl_debug (const char *dl_debug) ++process_dl_debug (struct dl_main_state *state, const char *dl_debug) + { + /* When adding new entries make sure that the maximal length of a name + is correctly handled in the LD_DEBUG_HELP code below. */ +@@ -2540,7 +2507,7 @@ process_dl_debug (const char *dl_debug) + && memcmp (dl_debug, debopts[cnt].name, len) == 0) + { + GLRO(dl_debug_mask) |= debopts[cnt].mask; +- any_debug = 1; ++ state->any_debug = true; + break; + } + +@@ -2594,11 +2561,10 @@ extern char **_environ attribute_hidden; + + + static void +-process_envvars (enum mode *modep, struct audit_list *audit_list) ++process_envvars (struct dl_main_state *state) + { + char **runp = _environ; + char *envline; +- enum mode mode = normal; + char *debug_output = NULL; + + /* This is the default place for profiling data file. */ +@@ -2630,25 +2596,25 @@ process_envvars (enum mode *modep, struct audit_list *audit_list) + /* Debugging of the dynamic linker? */ + if (memcmp (envline, "DEBUG", 5) == 0) + { +- process_dl_debug (&envline[6]); ++ process_dl_debug (state, &envline[6]); + break; + } + if (memcmp (envline, "AUDIT", 5) == 0) +- audit_list_add_string (audit_list, &envline[6]); ++ audit_list_add_string (&state->audit_list, &envline[6]); + break; + + case 7: + /* Print information about versions. */ + if (memcmp (envline, "VERBOSE", 7) == 0) + { +- version_info = envline[8] != '\0'; ++ state->version_info = envline[8] != '\0'; + break; + } + + /* List of objects to be preloaded. */ + if (memcmp (envline, "PRELOAD", 7) == 0) + { +- preloadlist = &envline[8]; ++ state->preloadlist = &envline[8]; + break; + } + +@@ -2697,7 +2663,7 @@ process_envvars (enum mode *modep, struct audit_list *audit_list) + if (!__libc_enable_secure + && memcmp (envline, "LIBRARY_PATH", 12) == 0) + { +- library_path = &envline[13]; ++ state->library_path = &envline[13]; + break; + } + +@@ -2739,7 +2705,7 @@ process_envvars (enum mode *modep, struct audit_list *audit_list) + /* The mode of the dynamic linker can be set. */ + if (memcmp (envline, "TRACE_PRELINKING", 16) == 0) + { +- mode = trace; ++ state->mode = rtld_mode_trace; + GLRO(dl_verbose) = 1; + GLRO(dl_debug_mask) |= DL_DEBUG_PRELINK; + GLRO(dl_trace_prelink) = &envline[17]; +@@ -2749,7 +2715,7 @@ process_envvars (enum mode *modep, struct audit_list *audit_list) + case 20: + /* The mode of the dynamic linker can be set. */ + if (memcmp (envline, "TRACE_LOADED_OBJECTS", 20) == 0) +- mode = trace; ++ state->mode = rtld_mode_trace; + break; + + /* We might have some extra environment variable to handle. This +@@ -2762,9 +2728,6 @@ process_envvars (enum mode *modep, struct audit_list *audit_list) + } + } + +- /* The caller wants this information. */ +- *modep = mode; +- + /* Extra security for SUID binaries. Remove all dangerous environment + variables. */ + if (__builtin_expect (__libc_enable_secure, 0)) +@@ -2793,13 +2756,13 @@ process_envvars (enum mode *modep, struct audit_list *audit_list) + GLRO(dl_debug_mask) = 0; + } + +- if (mode != normal) ++ if (state->mode != rtld_mode_normal) + _exit (5); + } + /* If we have to run the dynamic linker in debugging mode and the + LD_DEBUG_OUTPUT environment variable is given, we write the debug + messages to this file. */ +- else if (any_debug && debug_output != NULL) ++ else if (state->any_debug && debug_output != NULL) + { + const int flags = O_WRONLY | O_APPEND | O_CREAT | O_NOFOLLOW; + size_t name_len = strlen (debug_output); diff --git a/glibc-rh1817513-91.patch b/glibc-rh1817513-91.patch new file mode 100755 index 0000000..00dbfed --- /dev/null +++ b/glibc-rh1817513-91.patch @@ -0,0 +1,161 @@ +commit 9590a71adcf134c77f2d0f5711b0d6ab1b4193e6 +Author: Florian Weimer +Date: Thu Oct 8 10:57:10 2020 +0200 + + elf: Move ld.so error/help output to _dl_usage + + Also add a comment to elf/Makefile, explaining why we cannot use + config.status for autoconf template processing. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/Makefile b/elf/Makefile +index e2078f6bc325b7e0..e5666e5bf7817c3c 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -59,7 +59,7 @@ elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ + # ld.so uses those routines, plus some special stuff for being the program + # interpreter and operating independent of libc. + rtld-routines = rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal \ +- dl-error-minimal dl-conflict dl-hwcaps ++ dl-error-minimal dl-conflict dl-hwcaps dl-usage + all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines) + + CFLAGS-dl-runtime.c += -fexceptions -fasynchronous-unwind-tables +@@ -598,6 +598,12 @@ ldso_install: $(inst_rtlddir)/$(rtld-installed-name) + endif + + ++# Workarounds for ${exec_prefix} expansion in configure variables. ++# config.status cannot be used directly for processing ldd.bash.in or ++# expanding variables such as sysconfdir because the expansion ++# contains the literal string ${exec_prefix}, which is not valid in C ++# headers or installed shell scripts. ++ + ldd-rewrite = -e 's%@RTLD@%$(rtlddir)/$(rtld-installed-name)%g' \ + -e 's%@VERSION@%$(version)%g' \ + -e 's|@PKGVERSION@|$(PKGVERSION)|g' \ +@@ -635,6 +641,7 @@ libof-ldconfig = ldconfig + CFLAGS-dl-cache.c += $(SYSCONF-FLAGS) + CFLAGS-cache.c += $(SYSCONF-FLAGS) + CFLAGS-rtld.c += $(SYSCONF-FLAGS) ++CFLAGS-dl-usage.c += $(SYSCONF-FLAGS) + + cpp-srcs-left := $(all-rtld-routines:=.os) + lib := rtld +diff --git a/elf/dl-main.h b/elf/dl-main.h +index bcc9bcf2e8fee6e7..b01f433f9c8d9e1a 100644 +--- a/elf/dl-main.h ++++ b/elf/dl-main.h +@@ -19,7 +19,9 @@ + #ifndef _DL_MAIN + #define _DL_MAIN + ++#include + #include ++#include + + /* Length limits for names and paths, to protect the dynamic linker, + particularly when __libc_enable_secure is active. */ +@@ -95,4 +97,7 @@ call_init_paths (const struct dl_main_state *state) + _dl_init_paths (state->library_path); + } + ++/* Print ld.so usage information and exit. */ ++_Noreturn void _dl_usage (void) attribute_hidden; ++ + #endif /* _DL_MAIN */ +diff --git a/elf/dl-usage.c b/elf/dl-usage.c +new file mode 100644 +index 0000000000000000..f3d89d22b71d7d12 +--- /dev/null ++++ b/elf/dl-usage.c +@@ -0,0 +1,51 @@ ++/* Print usage information and help for ld.so. ++ Copyright (C) 1995-2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++void ++_dl_usage (void) ++{ ++ _dl_fatal_printf ("\ ++Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\ ++You have invoked `ld.so', the helper program for shared library executables.\n\ ++This program usually lives in the file `/lib/ld.so', and special directives\n\ ++in executable files using ELF shared libraries tell the system's program\n\ ++loader to load the helper program from this file. This helper program loads\n\ ++the shared libraries needed by the program executable, prepares the program\n\ ++to run, and runs it. You may invoke this helper program directly from the\n\ ++command line to load and run an ELF executable file; this is like executing\n\ ++that file itself, but always uses this helper program from the file you\n\ ++specified, instead of the helper program file specified in the executable\n\ ++file you run. This is mostly of use for maintainers to test new versions\n\ ++of this helper program; chances are you did not intend to run this program.\n\ ++\n\ ++ --list list all dependencies and how they are resolved\n\ ++ --verify verify that given object really is a dynamically linked\n\ ++ object we can handle\n\ ++ --inhibit-cache Do not use " LD_SO_CACHE "\n\ ++ --library-path PATH use given PATH instead of content of the environment\n\ ++ variable LD_LIBRARY_PATH\n\ ++ --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\ ++ in LIST\n\ ++ --audit LIST use objects named in LIST as auditors\n\ ++ --preload LIST preload objects named in LIST\n\ ++ --argv0 STRING set argv[0] to STRING before running\n"); ++} +diff --git a/elf/rtld.c b/elf/rtld.c +index fbfa441bf3b050ff..a12a56b550bbc837 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1240,31 +1240,7 @@ dl_main (const ElfW(Phdr) *phdr, + /* If we have no further argument the program was called incorrectly. + Grant the user some education. */ + if (_dl_argc < 2) +- _dl_fatal_printf ("\ +-Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\ +-You have invoked `ld.so', the helper program for shared library executables.\n\ +-This program usually lives in the file `/lib/ld.so', and special directives\n\ +-in executable files using ELF shared libraries tell the system's program\n\ +-loader to load the helper program from this file. This helper program loads\n\ +-the shared libraries needed by the program executable, prepares the program\n\ +-to run, and runs it. You may invoke this helper program directly from the\n\ +-command line to load and run an ELF executable file; this is like executing\n\ +-that file itself, but always uses this helper program from the file you\n\ +-specified, instead of the helper program file specified in the executable\n\ +-file you run. This is mostly of use for maintainers to test new versions\n\ +-of this helper program; chances are you did not intend to run this program.\n\ +-\n\ +- --list list all dependencies and how they are resolved\n\ +- --verify verify that given object really is a dynamically linked\n\ +- object we can handle\n\ +- --inhibit-cache Do not use " LD_SO_CACHE "\n\ +- --library-path PATH use given PATH instead of content of the environment\n\ +- variable LD_LIBRARY_PATH\n\ +- --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names\n\ +- in LIST\n\ +- --audit LIST use objects named in LIST as auditors\n\ +- --preload LIST preload objects named in LIST\n\ +- --argv0 STRING set argv[0] to STRING before running\n"); ++ _dl_usage (); + + ++_dl_skip_args; + --_dl_argc; diff --git a/glibc-rh1817513-92.patch b/glibc-rh1817513-92.patch new file mode 100755 index 0000000..45c4c95 --- /dev/null +++ b/glibc-rh1817513-92.patch @@ -0,0 +1,113 @@ +commit 27316f4a23efdc90bdfe4569a6c4b7e27941606e +Author: Florian Weimer +Date: Thu Oct 8 10:57:10 2020 +0200 + + elf: Record whether paths come from LD_LIBRARY_PATH or --library-path + + This allows more precise LD_DEBUG diagnostics. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 2b4dd9a0f3e27b70..1403a2e9c04e9a16 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -682,7 +682,7 @@ cache_rpath (struct link_map *l, + + + void +-_dl_init_paths (const char *llp) ++_dl_init_paths (const char *llp, const char *source) + { + size_t idx; + const char *strp; +@@ -820,7 +820,7 @@ _dl_init_paths (const char *llp) + } + + (void) fillin_rpath (llp_tmp, env_path_list.dirs, ":;", +- "LD_LIBRARY_PATH", NULL, l); ++ source, NULL, l); + + if (env_path_list.dirs[0] == NULL) + { +diff --git a/elf/dl-main.h b/elf/dl-main.h +index b01f433f9c8d9e1a..79c9c40056504f80 100644 +--- a/elf/dl-main.h ++++ b/elf/dl-main.h +@@ -74,6 +74,9 @@ struct dl_main_state + /* The library search path. */ + const char *library_path; + ++ /* Where library_path comes from. LD_LIBRARY_PATH or --library-path. */ ++ const char *library_path_source; ++ + /* The list preloaded objects from LD_PRELOAD. */ + const char *preloadlist; + +@@ -94,7 +97,7 @@ struct dl_main_state + static inline void + call_init_paths (const struct dl_main_state *state) + { +- _dl_init_paths (state->library_path); ++ _dl_init_paths (state->library_path, state->library_path_source); + } + + /* Print ld.so usage information and exit. */ +diff --git a/elf/dl-support.c b/elf/dl-support.c +index ef5455b91c17ca30..fb9672367f8d6abd 100644 +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -315,7 +315,7 @@ _dl_non_dynamic_init (void) + + /* Initialize the data structures for the search paths for shared + objects. */ +- _dl_init_paths (getenv ("LD_LIBRARY_PATH")); ++ _dl_init_paths (getenv ("LD_LIBRARY_PATH"), "LD_LIBRARY_PATH"); + + /* Remember the last search directory added at startup. */ + _dl_init_all_dirs = GL(dl_all_dirs); +diff --git a/elf/rtld.c b/elf/rtld.c +index a12a56b550bbc837..8e91cee41b62b894 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -284,6 +284,7 @@ dl_main_state_init (struct dl_main_state *state) + { + audit_list_init (&state->audit_list); + state->library_path = NULL; ++ state->library_path_source = NULL; + state->preloadlist = NULL; + state->preloadarg = NULL; + state->mode = rtld_mode_normal; +@@ -1197,6 +1198,7 @@ dl_main (const ElfW(Phdr) *phdr, + && _dl_argc > 2) + { + state.library_path = _dl_argv[2]; ++ state.library_path_source = "--library-path"; + + _dl_skip_args += 2; + _dl_argc -= 2; +@@ -2640,6 +2642,7 @@ process_envvars (struct dl_main_state *state) + && memcmp (envline, "LIBRARY_PATH", 12) == 0) + { + state->library_path = &envline[13]; ++ state->library_path_source = "LD_LIBRARY_PATH"; + break; + } + +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 4aa28b0229e0b339..aa006afafaf46dee 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1044,8 +1044,10 @@ rtld_hidden_proto (_dl_debug_state) + extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) + attribute_hidden; + +-/* Initialize the basic data structure for the search paths. */ +-extern void _dl_init_paths (const char *library_path) attribute_hidden; ++/* Initialize the basic data structure for the search paths. SOURCE ++ is either "LD_LIBRARY_PATH" or "--library-path". */ ++extern void _dl_init_paths (const char *library_path, const char *source) ++ attribute_hidden; + + /* Gather the information needed to install the profiling tables and start + the timers. */ diff --git a/glibc-rh1817513-93.patch b/glibc-rh1817513-93.patch new file mode 100755 index 0000000..e755b67 --- /dev/null +++ b/glibc-rh1817513-93.patch @@ -0,0 +1,202 @@ +commit e0f1a58f3d1f4f55591b524e9dcff23cc98a509e +Author: Florian Weimer +Date: Thu Oct 8 10:57:10 2020 +0200 + + elf: Implement ld.so --help + + --help processing is deferred to the point where the executable has + been loaded, so that it is possible to eventually include information + from the main executable in the help output. + + As suggested in the GNU command-line interface guidelines, the help + message is printed to standard output, and the exit status is + successful. + + Handle usage errors closer to the GNU command-line interface + guidelines. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-main.h b/elf/dl-main.h +index 79c9c40056504f80..ac7249a580214860 100644 +--- a/elf/dl-main.h ++++ b/elf/dl-main.h +@@ -63,6 +63,7 @@ struct audit_list + enum rtld_mode + { + rtld_mode_normal, rtld_mode_list, rtld_mode_verify, rtld_mode_trace, ++ rtld_mode_help, + }; + + /* Aggregated state information extracted from environment variables +@@ -101,6 +102,11 @@ call_init_paths (const struct dl_main_state *state) + } + + /* Print ld.so usage information and exit. */ +-_Noreturn void _dl_usage (void) attribute_hidden; ++_Noreturn void _dl_usage (const char *argv0, const char *wrong_option) ++ attribute_hidden; ++ ++/* Print ld.so --help output and exit. */ ++_Noreturn void _dl_help (const char *argv0, struct dl_main_state *state) ++ attribute_hidden; + + #endif /* _DL_MAIN */ +diff --git a/elf/dl-usage.c b/elf/dl-usage.c +index f3d89d22b71d7d12..c1820dca2fa117ee 100644 +--- a/elf/dl-usage.c ++++ b/elf/dl-usage.c +@@ -19,12 +19,24 @@ + #include + #include + #include ++#include + + void +-_dl_usage (void) ++_dl_usage (const char *argv0, const char *wrong_option) + { +- _dl_fatal_printf ("\ +-Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\ ++ if (wrong_option != NULL) ++ _dl_error_printf ("%s: unrecognized option '%s'\n", argv0, wrong_option); ++ else ++ _dl_error_printf ("%s: missing program name\n", argv0); ++ _dl_error_printf ("Try '%s --help' for more information.\n", argv0); ++ _exit (EXIT_FAILURE); ++} ++ ++void ++_dl_help (const char *argv0, struct dl_main_state *state) ++{ ++ _dl_printf ("\ ++Usage: %s [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\ + You have invoked `ld.so', the helper program for shared library executables.\n\ + This program usually lives in the file `/lib/ld.so', and special directives\n\ + in executable files using ELF shared libraries tell the system's program\n\ +@@ -47,5 +59,9 @@ of this helper program; chances are you did not intend to run this program.\n\ + in LIST\n\ + --audit LIST use objects named in LIST as auditors\n\ + --preload LIST preload objects named in LIST\n\ +- --argv0 STRING set argv[0] to STRING before running\n"); ++ --argv0 STRING set argv[0] to STRING before running\n\ ++ --help display this help and exit\n\ ++", ++ argv0); ++ _exit (EXIT_SUCCESS); + } +diff --git a/elf/rtld.c b/elf/rtld.c +index 8e91cee41b62b894..b92641cb1c2d99a6 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1145,6 +1145,7 @@ dl_main (const ElfW(Phdr) *phdr, + /* Set up a flag which tells we are just starting. */ + _dl_starting_up = 1; + ++ const char *ld_so_name = _dl_argv[0]; + if (*user_entry == (ElfW(Addr)) ENTRY_POINT) + { + /* Ho ho. We are not the program interpreter! We are the program +@@ -1172,8 +1173,12 @@ dl_main (const ElfW(Phdr) *phdr, + while (_dl_argc > 1) + if (! strcmp (_dl_argv[1], "--list")) + { +- state.mode = rtld_mode_list; +- GLRO(dl_lazy) = -1; /* This means do no dependency analysis. */ ++ if (state.mode != rtld_mode_help) ++ { ++ state.mode = rtld_mode_list; ++ /* This means do no dependency analysis. */ ++ GLRO(dl_lazy) = -1; ++ } + + ++_dl_skip_args; + --_dl_argc; +@@ -1181,7 +1186,8 @@ dl_main (const ElfW(Phdr) *phdr, + } + else if (! strcmp (_dl_argv[1], "--verify")) + { +- state.mode = rtld_mode_verify; ++ if (state.mode != rtld_mode_help) ++ state.mode = rtld_mode_verify; + + ++_dl_skip_args; + --_dl_argc; +@@ -1236,13 +1242,34 @@ dl_main (const ElfW(Phdr) *phdr, + _dl_argc -= 2; + _dl_argv += 2; + } ++ else if (strcmp (_dl_argv[1], "--help") == 0) ++ { ++ state.mode = rtld_mode_help; ++ --_dl_argc; ++ ++_dl_argv; ++ } ++ else if (_dl_argv[1][0] == '-' && _dl_argv[1][1] == '-') ++ { ++ if (_dl_argv[1][1] == '\0') ++ /* End of option list. */ ++ break; ++ else ++ /* Unrecognized option. */ ++ _dl_usage (ld_so_name, _dl_argv[1]); ++ } + else + break; + + /* If we have no further argument the program was called incorrectly. + Grant the user some education. */ + if (_dl_argc < 2) +- _dl_usage (); ++ { ++ if (state.mode == rtld_mode_help) ++ /* --help without an executable is not an error. */ ++ _dl_help (ld_so_name, &state); ++ else ++ _dl_usage (ld_so_name, NULL); ++ } + + ++_dl_skip_args; + --_dl_argc; +@@ -1267,7 +1294,8 @@ dl_main (const ElfW(Phdr) *phdr, + break; + } + +- if (__glibc_unlikely (state.mode == rtld_mode_verify)) ++ if (__glibc_unlikely (state.mode == rtld_mode_verify ++ || state.mode == rtld_mode_help)) + { + const char *objname; + const char *err_str = NULL; +@@ -1280,9 +1308,16 @@ dl_main (const ElfW(Phdr) *phdr, + (void) _dl_catch_error (&objname, &err_str, &malloced, map_doit, + &args); + if (__glibc_unlikely (err_str != NULL)) +- /* We don't free the returned string, the programs stops +- anyway. */ +- _exit (EXIT_FAILURE); ++ { ++ /* We don't free the returned string, the programs stops ++ anyway. */ ++ if (state.mode == rtld_mode_help) ++ /* Mask the failure to load the main object. The help ++ message contains less information in this case. */ ++ _dl_help (ld_so_name, &state); ++ else ++ _exit (EXIT_FAILURE); ++ } + } + else + { +@@ -1632,6 +1667,11 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + audit_list_add_dynamic_tag (&state.audit_list, main_map, DT_AUDIT); + audit_list_add_dynamic_tag (&state.audit_list, main_map, DT_DEPAUDIT); + ++ /* At this point, all data has been obtained that is included in the ++ --help output. */ ++ if (__glibc_unlikely (state.mode == rtld_mode_help)) ++ _dl_help (ld_so_name, &state); ++ + /* If we have auditing DSOs to load, do it now. */ + bool need_security_init = true; + if (state.audit_list.length > 0) diff --git a/glibc-rh1817513-94.patch b/glibc-rh1817513-94.patch new file mode 100755 index 0000000..8d1b874 --- /dev/null +++ b/glibc-rh1817513-94.patch @@ -0,0 +1,79 @@ +commit 542923d949e8b2480e48bd85fea13cf5d00d30b7 +Author: Florian Weimer +Date: Thu Oct 8 15:33:00 2020 +0200 + + elf: Implement ld.so --version + + This prints out version information for the dynamic loader and + exits immediately, without further command line processing + (which seems to match what some GNU tools do). + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-main.h b/elf/dl-main.h +index ac7249a580214860..b51256d3b48230b0 100644 +--- a/elf/dl-main.h ++++ b/elf/dl-main.h +@@ -105,6 +105,9 @@ call_init_paths (const struct dl_main_state *state) + _Noreturn void _dl_usage (const char *argv0, const char *wrong_option) + attribute_hidden; + ++/* Print ld.so version information and exit. */ ++_Noreturn void _dl_version (void) attribute_hidden; ++ + /* Print ld.so --help output and exit. */ + _Noreturn void _dl_help (const char *argv0, struct dl_main_state *state) + attribute_hidden; +diff --git a/elf/dl-usage.c b/elf/dl-usage.c +index c1820dca2fa117ee..f3c5ac76d37f9c03 100644 +--- a/elf/dl-usage.c ++++ b/elf/dl-usage.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include "version.h" + + void + _dl_usage (const char *argv0, const char *wrong_option) +@@ -32,6 +33,19 @@ _dl_usage (const char *argv0, const char *wrong_option) + _exit (EXIT_FAILURE); + } + ++void ++_dl_version (void) ++{ ++ _dl_printf ("\ ++ld.so " PKGVERSION RELEASE " release version " VERSION ".\n\ ++Copyright (C) 2020 Free Software Foundation, Inc.\n\ ++This is free software; see the source for copying conditions.\n\ ++There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\ ++PARTICULAR PURPOSE.\n\ ++"); ++ _exit (EXIT_SUCCESS); ++} ++ + void + _dl_help (const char *argv0, struct dl_main_state *state) + { +@@ -61,6 +75,7 @@ of this helper program; chances are you did not intend to run this program.\n\ + --preload LIST preload objects named in LIST\n\ + --argv0 STRING set argv[0] to STRING before running\n\ + --help display this help and exit\n\ ++ --version output version information and exit\n\ + ", + argv0); + _exit (EXIT_SUCCESS); +diff --git a/elf/rtld.c b/elf/rtld.c +index b92641cb1c2d99a6..da1eef108508b95f 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1248,6 +1248,8 @@ dl_main (const ElfW(Phdr) *phdr, + --_dl_argc; + ++_dl_argv; + } ++ else if (strcmp (_dl_argv[1], "--version") == 0) ++ _dl_version (); + else if (_dl_argv[1][0] == '-' && _dl_argv[1][1] == '-') + { + if (_dl_argv[1][1] == '\0') diff --git a/glibc-rh1817513-95.patch b/glibc-rh1817513-95.patch new file mode 100755 index 0000000..12e1075 --- /dev/null +++ b/glibc-rh1817513-95.patch @@ -0,0 +1,43 @@ +commit ca52c56abf50b89a95dc2a4a5504c0d7d3862961 +Author: Florian Weimer +Date: Thu Oct 8 15:33:00 2020 +0200 + + elf: Use the term "program interpreter" in the ld.so help message + + This is the term that the ELF standard itself uses. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-usage.c b/elf/dl-usage.c +index f3c5ac76d37f9c03..8c24c13770500df9 100644 +--- a/elf/dl-usage.c ++++ b/elf/dl-usage.c +@@ -51,17 +51,17 @@ _dl_help (const char *argv0, struct dl_main_state *state) + { + _dl_printf ("\ + Usage: %s [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]\n\ +-You have invoked `ld.so', the helper program for shared library executables.\n\ +-This program usually lives in the file `/lib/ld.so', and special directives\n\ +-in executable files using ELF shared libraries tell the system's program\n\ +-loader to load the helper program from this file. This helper program loads\n\ +-the shared libraries needed by the program executable, prepares the program\n\ +-to run, and runs it. You may invoke this helper program directly from the\n\ +-command line to load and run an ELF executable file; this is like executing\n\ +-that file itself, but always uses this helper program from the file you\n\ +-specified, instead of the helper program file specified in the executable\n\ +-file you run. This is mostly of use for maintainers to test new versions\n\ +-of this helper program; chances are you did not intend to run this program.\n\ ++You have invoked 'ld.so', the program interpreter for dynamically-linked\n\ ++ELF programs. Usually, the program interpreter is invoked automatically\n\ ++when a dynamically-linked executable is started.\n\ ++\n\ ++You may invoke the program interpreter program directly from the command\n\ ++line to load and run an ELF executable file; this is like executing that\n\ ++file itself, but always uses the program interpreter you invoked,\n\ ++instead of the program interpreter specified in the executable file you\n\ ++run. Invoking the program interpreter directly provides access to\n\ ++additional diagnostics, and changing the dynamic linker behavior without\n\ ++setting environment variables (which would be inherited by subprocesses).\n\ + \n\ + --list list all dependencies and how they are resolved\n\ + --verify verify that given object really is a dynamically linked\n\ diff --git a/glibc-rh1817513-96.patch b/glibc-rh1817513-96.patch new file mode 100755 index 0000000..94a0c03 --- /dev/null +++ b/glibc-rh1817513-96.patch @@ -0,0 +1,39 @@ +commit db03874df9843ab98c4faeb658f04d17e6db83a6 +Author: Florian Weimer +Date: Thu Oct 8 15:33:00 2020 +0200 + + elf: Print the full name of the dynamic loader in the ld.so help message + + This requires defining a macro for the full path, matching the + -Wl,--dynamic-link= arguments used for linking glibc programs, + and ldd script. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/Makefile b/elf/Makefile +index e5666e5bf7817c3c..bc96b8fd65e376cc 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -641,7 +641,8 @@ libof-ldconfig = ldconfig + CFLAGS-dl-cache.c += $(SYSCONF-FLAGS) + CFLAGS-cache.c += $(SYSCONF-FLAGS) + CFLAGS-rtld.c += $(SYSCONF-FLAGS) +-CFLAGS-dl-usage.c += $(SYSCONF-FLAGS) ++CFLAGS-dl-usage.c += $(SYSCONF-FLAGS) \ ++ -D'RTLD="$(rtlddir)/$(rtld-installed-name)"' + + cpp-srcs-left := $(all-rtld-routines:=.os) + lib := rtld +diff --git a/elf/dl-usage.c b/elf/dl-usage.c +index 8c24c13770500df9..1003a435bfc2b39e 100644 +--- a/elf/dl-usage.c ++++ b/elf/dl-usage.c +@@ -76,6 +76,8 @@ setting environment variables (which would be inherited by subprocesses).\n\ + --argv0 STRING set argv[0] to STRING before running\n\ + --help display this help and exit\n\ + --version output version information and exit\n\ ++\n\ ++This program interpreter self-identifies as: " RTLD "\n\ + ", + argv0); + _exit (EXIT_SUCCESS); diff --git a/glibc-rh1817513-97.patch b/glibc-rh1817513-97.patch new file mode 100755 index 0000000..754d50a --- /dev/null +++ b/glibc-rh1817513-97.patch @@ -0,0 +1,174 @@ +commit 50b1b7a3905cbcdfbcc7eab335aa81478d711d1a +Author: Florian Weimer +Date: Thu Oct 8 15:33:00 2020 +0200 + + elf: Make __rtld_env_path_list and __rtld_search_dirs global variables + + They have been renamed from env_path_list and rtld_search_dirs to + avoid linknamespace issues. + + This change will allow future use these variables in diagnostics. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 1403a2e9c04e9a16..2eb4f35b2467f7d8 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -98,7 +98,7 @@ int __stack_prot attribute_hidden attribute_relro + + + /* This is the decomposed LD_LIBRARY_PATH search path. */ +-static struct r_search_path_struct env_path_list attribute_relro; ++struct r_search_path_struct __rtld_env_path_list attribute_relro; + + /* List of the hardware capabilities we might end up using. */ + #ifdef SHARED +@@ -442,7 +442,7 @@ add_name_to_object (struct link_map *l, const char *name) + } + + /* Standard search directories. */ +-static struct r_search_path_struct rtld_search_dirs attribute_relro; ++struct r_search_path_struct __rtld_search_dirs attribute_relro; + + static size_t max_dirnamelen; + +@@ -702,9 +702,9 @@ _dl_init_paths (const char *llp, const char *source) + #endif + + /* First set up the rest of the default search directory entries. */ +- aelem = rtld_search_dirs.dirs = (struct r_search_path_elem **) ++ aelem = __rtld_search_dirs.dirs = (struct r_search_path_elem **) + malloc ((nsystem_dirs_len + 1) * sizeof (struct r_search_path_elem *)); +- if (rtld_search_dirs.dirs == NULL) ++ if (__rtld_search_dirs.dirs == NULL) + { + errstring = N_("cannot create search path array"); + signal_error: +@@ -715,16 +715,17 @@ _dl_init_paths (const char *llp, const char *source) + + ncapstr * sizeof (enum r_dir_status)) + / sizeof (struct r_search_path_elem)); + +- rtld_search_dirs.dirs[0] = malloc (nsystem_dirs_len * round_size +- * sizeof (*rtld_search_dirs.dirs[0])); +- if (rtld_search_dirs.dirs[0] == NULL) ++ __rtld_search_dirs.dirs[0] ++ = malloc (nsystem_dirs_len * round_size ++ * sizeof (*__rtld_search_dirs.dirs[0])); ++ if (__rtld_search_dirs.dirs[0] == NULL) + { + errstring = N_("cannot create cache for search path"); + goto signal_error; + } + +- rtld_search_dirs.malloced = 0; +- pelem = GL(dl_all_dirs) = rtld_search_dirs.dirs[0]; ++ __rtld_search_dirs.malloced = 0; ++ pelem = GL(dl_all_dirs) = __rtld_search_dirs.dirs[0]; + strp = system_dirs; + idx = 0; + +@@ -811,27 +812,27 @@ _dl_init_paths (const char *llp, const char *source) + if (*cp == ':' || *cp == ';') + ++nllp; + +- env_path_list.dirs = (struct r_search_path_elem **) ++ __rtld_env_path_list.dirs = (struct r_search_path_elem **) + malloc ((nllp + 1) * sizeof (struct r_search_path_elem *)); +- if (env_path_list.dirs == NULL) ++ if (__rtld_env_path_list.dirs == NULL) + { + errstring = N_("cannot create cache for search path"); + goto signal_error; + } + +- (void) fillin_rpath (llp_tmp, env_path_list.dirs, ":;", ++ (void) fillin_rpath (llp_tmp, __rtld_env_path_list.dirs, ":;", + source, NULL, l); + +- if (env_path_list.dirs[0] == NULL) ++ if (__rtld_env_path_list.dirs[0] == NULL) + { +- free (env_path_list.dirs); +- env_path_list.dirs = (void *) -1; ++ free (__rtld_env_path_list.dirs); ++ __rtld_env_path_list.dirs = (void *) -1; + } + +- env_path_list.malloced = 0; ++ __rtld_env_path_list.malloced = 0; + } + else +- env_path_list.dirs = (void *) -1; ++ __rtld_env_path_list.dirs = (void *) -1; + } + + +@@ -1946,9 +1947,9 @@ open_path (const char *name, size_t namelen, int mode, + if (sps->malloced) + free (sps->dirs); + +- /* rtld_search_dirs and env_path_list are attribute_relro, therefore +- avoid writing into it. */ +- if (sps != &rtld_search_dirs && sps != &env_path_list) ++ /* __rtld_search_dirs and __rtld_env_path_list are ++ attribute_relro, therefore avoid writing to them. */ ++ if (sps != &__rtld_search_dirs && sps != &__rtld_env_path_list) + sps->dirs = (void *) -1; + } + +@@ -2096,8 +2097,8 @@ _dl_map_object (struct link_map *loader, const char *name, + } + + /* Try the LD_LIBRARY_PATH environment variable. */ +- if (fd == -1 && env_path_list.dirs != (void *) -1) +- fd = open_path (name, namelen, mode, &env_path_list, ++ if (fd == -1 && __rtld_env_path_list.dirs != (void *) -1) ++ fd = open_path (name, namelen, mode, &__rtld_env_path_list, + &realname, &fb, + loader ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded, + LA_SER_LIBPATH, &found_other_class); +@@ -2186,8 +2187,8 @@ _dl_map_object (struct link_map *loader, const char *name, + if (fd == -1 + && ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL + || __glibc_likely (!(l->l_flags_1 & DF_1_NODEFLIB))) +- && rtld_search_dirs.dirs != (void *) -1) +- fd = open_path (name, namelen, mode, &rtld_search_dirs, ++ && __rtld_search_dirs.dirs != (void *) -1) ++ fd = open_path (name, namelen, mode, &__rtld_search_dirs, + &realname, &fb, l, LA_SER_DEFAULT, &found_other_class); + + /* Add another newline when we are tracing the library loading. */ +@@ -2355,7 +2356,7 @@ _dl_rtld_di_serinfo (struct link_map *loader, Dl_serinfo *si, bool counting) + } + + /* Try the LD_LIBRARY_PATH environment variable. */ +- add_path (&p, &env_path_list, XXX_ENV); ++ add_path (&p, &__rtld_env_path_list, XXX_ENV); + + /* Look at the RUNPATH information for this binary. */ + if (cache_rpath (loader, &loader->l_runpath_dirs, DT_RUNPATH, "RUNPATH")) +@@ -2367,7 +2368,7 @@ _dl_rtld_di_serinfo (struct link_map *loader, Dl_serinfo *si, bool counting) + + /* Finally, try the default path. */ + if (!(loader->l_flags_1 & DF_1_NODEFLIB)) +- add_path (&p, &rtld_search_dirs, XXX_default); ++ add_path (&p, &__rtld_search_dirs, XXX_default); + + if (counting) + /* Count the struct size before the string area, which we didn't +diff --git a/include/link.h b/include/link.h +index e90fa79a0b332087..cdd011f59445e490 100644 +--- a/include/link.h ++++ b/include/link.h +@@ -79,6 +79,10 @@ struct r_search_path_struct + int malloced; + }; + ++/* Search path information computed by _dl_init_paths. */ ++extern struct r_search_path_struct __rtld_search_dirs attribute_hidden; ++extern struct r_search_path_struct __rtld_env_path_list attribute_hidden; ++ + /* Structure describing a loaded shared object. The `l_next' and `l_prev' + members form a chain of all the shared objects loaded at startup. + diff --git a/glibc-rh1817513-98.patch b/glibc-rh1817513-98.patch new file mode 100755 index 0000000..d861cbc --- /dev/null +++ b/glibc-rh1817513-98.patch @@ -0,0 +1,81 @@ +commit 10b39a5124aea509dfeef2f39a0835adb0fb2296 +Author: Florian Weimer +Date: Fri Oct 9 10:13:14 2020 +0200 + + elf: Add library search path information to ld.so --help + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-usage.c b/elf/dl-usage.c +index 1003a435bfc2b39e..8d39bc9d5442bc59 100644 +--- a/elf/dl-usage.c ++++ b/elf/dl-usage.c +@@ -46,6 +46,61 @@ PARTICULAR PURPOSE.\n\ + _exit (EXIT_SUCCESS); + } + ++/* Print part of the library search path (from a single source). */ ++static void ++print_search_path_for_help_1 (struct r_search_path_elem **list) ++{ ++ if (list == NULL || list == (void *) -1) ++ /* Path is missing or marked as inactive. */ ++ return; ++ ++ for (; *list != NULL; ++list) ++ { ++ _dl_write (STDOUT_FILENO, " ", 2); ++ const char *name = (*list)->dirname; ++ size_t namelen = (*list)->dirnamelen; ++ if (namelen == 0) ++ { ++ /* The empty string denotes the current directory. */ ++ name = "."; ++ namelen = 1; ++ } ++ else if (namelen > 1) ++ /* Remove the trailing slash. */ ++ --namelen; ++ _dl_write (STDOUT_FILENO, name, namelen); ++ _dl_printf (" (%s)\n", (*list)->what); ++ } ++} ++ ++/* Prints the library search path. See _dl_init_paths in dl-load.c ++ how this information is populated. */ ++static void ++print_search_path_for_help (struct dl_main_state *state) ++{ ++ if (__rtld_search_dirs.dirs == NULL) ++ /* The run-time search paths have not yet been initialized. */ ++ _dl_init_paths (state->library_path, state->library_path_source); ++ ++ _dl_printf ("\nShared library search path:\n"); ++ ++ /* The print order should reflect the processing in ++ _dl_map_object. */ ++ ++ struct link_map *map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; ++ if (map != NULL) ++ print_search_path_for_help_1 (map->l_rpath_dirs.dirs); ++ ++ print_search_path_for_help_1 (__rtld_env_path_list.dirs); ++ ++ if (map != NULL) ++ print_search_path_for_help_1 (map->l_runpath_dirs.dirs); ++ ++ _dl_printf (" (libraries located via %s)\n", LD_SO_CACHE); ++ ++ print_search_path_for_help_1 (__rtld_search_dirs.dirs); ++} ++ + void + _dl_help (const char *argv0, struct dl_main_state *state) + { +@@ -80,5 +135,6 @@ setting environment variables (which would be inherited by subprocesses).\n\ + This program interpreter self-identifies as: " RTLD "\n\ + ", + argv0); ++ print_search_path_for_help (state); + _exit (EXIT_SUCCESS); + } diff --git a/glibc-rh1817513-99.patch b/glibc-rh1817513-99.patch new file mode 100755 index 0000000..b55d80e --- /dev/null +++ b/glibc-rh1817513-99.patch @@ -0,0 +1,94 @@ +commit 647103ea3a2aae2e6791b3bebe9e33eedc168102 +Author: Florian Weimer +Date: Fri Oct 9 10:13:14 2020 +0200 + + elf: Enhance ld.so --help to print HWCAP subdirectories + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-usage.c b/elf/dl-usage.c +index 8d39bc9d5442bc59..c07f43835bd771cf 100644 +--- a/elf/dl-usage.c ++++ b/elf/dl-usage.c +@@ -22,6 +22,8 @@ + #include + #include "version.h" + ++#include ++ + void + _dl_usage (const char *argv0, const char *wrong_option) + { +@@ -101,6 +103,65 @@ print_search_path_for_help (struct dl_main_state *state) + print_search_path_for_help_1 (__rtld_search_dirs.dirs); + } + ++/* Helper function for printing flags associated with a HWCAP name. */ ++static void ++print_hwcap_1 (bool *first, bool active, const char *label) ++{ ++ if (active) ++ { ++ if (*first) ++ { ++ _dl_printf (" ("); ++ *first = false; ++ } ++ else ++ _dl_printf (", "); ++ _dl_printf ("%s", label); ++ } ++} ++ ++/* Called after a series of print_hwcap_1 calls to emit the line ++ terminator. */ ++static void ++print_hwcap_1_finish (bool *first) ++{ ++ if (*first) ++ _dl_printf ("\n"); ++ else ++ _dl_printf (")\n"); ++} ++ ++/* Write a list of hwcap subdirectories to standard output. See ++ _dl_important_hwcaps in dl-hwcaps.c. */ ++static void ++print_legacy_hwcap_directories (void) ++{ ++ _dl_printf ("\n\ ++Legacy HWCAP subdirectories under library search path directories:\n"); ++ ++ const char *platform = GLRO (dl_platform); ++ if (platform != NULL) ++ _dl_printf (" %s (AT_PLATFORM; supported, searched)\n", platform); ++ ++ _dl_printf (" tls (supported, searched)\n"); ++ ++ uint64_t hwcap_mask = GET_HWCAP_MASK(); ++ uint64_t searched = GLRO (dl_hwcap) & hwcap_mask; ++ for (int n = 63; n >= 0; --n) ++ { ++ uint64_t bit = 1ULL << n; ++ if (HWCAP_IMPORTANT & bit) ++ { ++ _dl_printf (" %s", _dl_hwcap_string (n)); ++ bool first = true; ++ print_hwcap_1 (&first, GLRO (dl_hwcap) & bit, "supported"); ++ print_hwcap_1 (&first, !(hwcap_mask & bit), "masked"); ++ print_hwcap_1 (&first, searched & bit, "searched"); ++ print_hwcap_1_finish (&first); ++ } ++ } ++} ++ + void + _dl_help (const char *argv0, struct dl_main_state *state) + { +@@ -136,5 +197,6 @@ This program interpreter self-identifies as: " RTLD "\n\ + ", + argv0); + print_search_path_for_help (state); ++ print_legacy_hwcap_directories (); + _exit (EXIT_SUCCESS); + } diff --git a/glibc-rh1821531-1.patch b/glibc-rh1821531-1.patch new file mode 100755 index 0000000..c09ace9 --- /dev/null +++ b/glibc-rh1821531-1.patch @@ -0,0 +1,136 @@ +commit 284f42bc778e487dfd5dff5c01959f93b9e0c4f5 +Author: Wilco Dijkstra +Date: Fri Aug 3 17:24:12 2018 +0100 + + Simplify and speedup strstr/strcasestr first match + + Looking at the benchtests, both strstr and strcasestr spend a lot of time + in a slow initialization loop handling one character per iteration. + This can be simplified and use the much faster strlen/strnlen/strchr/memcmp. + Read ahead a few cachelines to reduce the number of strnlen calls, which + improves performance by ~3-4%. This patch improves the time taken for the + full strstr benchtest by >40%. + + * string/strcasestr.c (STRCASESTR): Simplify and speedup first match. + * string/strstr.c (AVAILABLE): Likewise. + +diff --git a/string/strcasestr.c b/string/strcasestr.c +index 421764bd1b0ff22e..8aa76037dcc052f3 100644 +--- a/string/strcasestr.c ++++ b/string/strcasestr.c +@@ -59,31 +59,22 @@ + case-insensitive comparison. This function gives unspecified + results in multibyte locales. */ + char * +-STRCASESTR (const char *haystack_start, const char *needle_start) ++STRCASESTR (const char *haystack, const char *needle) + { +- const char *haystack = haystack_start; +- const char *needle = needle_start; + size_t needle_len; /* Length of NEEDLE. */ + size_t haystack_len; /* Known minimum length of HAYSTACK. */ +- bool ok = true; /* True if NEEDLE is prefix of HAYSTACK. */ +- +- /* Determine length of NEEDLE, and in the process, make sure +- HAYSTACK is at least as long (no point processing all of a long +- NEEDLE if HAYSTACK is too short). */ +- while (*haystack && *needle) +- { +- ok &= (TOLOWER ((unsigned char) *haystack) +- == TOLOWER ((unsigned char) *needle)); +- haystack++; +- needle++; +- } +- if (*needle) ++ ++ /* Handle empty NEEDLE special case. */ ++ if (needle[0] == '\0') ++ return (char *) haystack; ++ ++ /* Ensure HAYSTACK length is at least as long as NEEDLE length. ++ Since a match may occur early on in a huge HAYSTACK, use strnlen ++ and read ahead a few cachelines for improved performance. */ ++ needle_len = strlen (needle); ++ haystack_len = __strnlen (haystack, needle_len + 256); ++ if (haystack_len < needle_len) + return NULL; +- if (ok) +- return (char *) haystack_start; +- needle_len = needle - needle_start; +- haystack = haystack_start + 1; +- haystack_len = needle_len - 1; + + /* Perform the search. Abstract memory is considered to be an array + of 'unsigned char' values, not an array of 'char' values. See +@@ -91,10 +82,10 @@ STRCASESTR (const char *haystack_start, const char *needle_start) + if (needle_len < LONG_NEEDLE_THRESHOLD) + return two_way_short_needle ((const unsigned char *) haystack, + haystack_len, +- (const unsigned char *) needle_start, ++ (const unsigned char *) needle, + needle_len); + return two_way_long_needle ((const unsigned char *) haystack, haystack_len, +- (const unsigned char *) needle_start, ++ (const unsigned char *) needle, + needle_len); + } + +diff --git a/string/strstr.c b/string/strstr.c +index 79ebcc75329d0b17..f74d7189ed1319f6 100644 +--- a/string/strstr.c ++++ b/string/strstr.c +@@ -51,33 +51,32 @@ + if NEEDLE is empty, otherwise NULL if NEEDLE is not found in + HAYSTACK. */ + char * +-STRSTR (const char *haystack_start, const char *needle_start) ++STRSTR (const char *haystack, const char *needle) + { +- const char *haystack = haystack_start; +- const char *needle = needle_start; + size_t needle_len; /* Length of NEEDLE. */ + size_t haystack_len; /* Known minimum length of HAYSTACK. */ +- bool ok = true; /* True if NEEDLE is prefix of HAYSTACK. */ +- +- /* Determine length of NEEDLE, and in the process, make sure +- HAYSTACK is at least as long (no point processing all of a long +- NEEDLE if HAYSTACK is too short). */ +- while (*haystack && *needle) +- ok &= *haystack++ == *needle++; +- if (*needle) ++ ++ /* Handle empty NEEDLE special case. */ ++ if (needle[0] == '\0') ++ return (char *) haystack; ++ ++ /* Skip until we find the first matching char from NEEDLE. */ ++ haystack = strchr (haystack, needle[0]); ++ if (haystack == NULL || needle[1] == '\0') ++ return (char *) haystack; ++ ++ /* Ensure HAYSTACK length is at least as long as NEEDLE length. ++ Since a match may occur early on in a huge HAYSTACK, use strnlen ++ and read ahead a few cachelines for improved performance. */ ++ needle_len = strlen (needle); ++ haystack_len = __strnlen (haystack, needle_len + 256); ++ if (haystack_len < needle_len) + return NULL; +- if (ok) +- return (char *) haystack_start; +- +- /* Reduce the size of haystack using strchr, since it has a smaller +- linear coefficient than the Two-Way algorithm. */ +- needle_len = needle - needle_start; +- haystack = strchr (haystack_start + 1, *needle_start); +- if (!haystack || __builtin_expect (needle_len == 1, 0)) ++ ++ /* Check whether we have a match. This improves performance since we avoid ++ the initialization overhead of the two-way algorithm. */ ++ if (memcmp (haystack, needle, needle_len) == 0) + return (char *) haystack; +- needle -= needle_len; +- haystack_len = (haystack > haystack_start + needle_len ? 1 +- : needle_len + haystack_start - haystack); + + /* Perform the search. Abstract memory is considered to be an array + of 'unsigned char' values, not an array of 'char' values. See diff --git a/glibc-rh1821531-2.patch b/glibc-rh1821531-2.patch new file mode 100755 index 0000000..f97e4a5 --- /dev/null +++ b/glibc-rh1821531-2.patch @@ -0,0 +1,260 @@ +commit 5e0a7ecb6629461b28adc1a5aabcc0ede122f201 +Author: Wilco Dijkstra +Date: Wed Jun 12 11:38:52 2019 +0100 + + Improve performance of strstr + + This patch significantly improves performance of strstr using a novel + modified Horspool algorithm. Needles up to size 256 use a bad-character + table indexed by hashed pairs of characters to quickly skip past mismatches. + Long needles use a self-adapting filtering step to avoid comparing the whole + needle repeatedly. + + By limiting the needle length to 256, the shift table only requires 8 bits + per entry, lowering preprocessing overhead and minimizing cache effects. + This limit also implies worst-case performance is linear. + + Small needles up to size 3 use a dedicated linear search. Very long needles + use the Two-Way algorithm. + + The performance gain using the improved bench-strstr on Cortex-A72 is 5.8 + times basic_strstr and 3.7 times twoway_strstr. + + Tested against GLIBC testsuite, randomized tests and the GNULIB strstr test + (https://git.savannah.gnu.org/cgit/gnulib.git/tree/tests/test-strstr.c). + + Reviewed-by: Szabolcs Nagy + + * string/str-two-way.h (two_way_short_needle): Add inline to avoid + warning. + (two_way_long_needle): Block inlining. + * string/strstr.c (strstr2): Add new function. + (strstr3): Likewise. + (STRSTR): Completely rewrite strstr to improve performance. + +diff --git a/string/str-two-way.h b/string/str-two-way.h +index 523d946c59412e1f..358959bef0fd6f74 100644 +--- a/string/str-two-way.h ++++ b/string/str-two-way.h +@@ -221,7 +221,7 @@ critical_factorization (const unsigned char *needle, size_t needle_len, + most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. + If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * + HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */ +-static RETURN_TYPE ++static inline RETURN_TYPE + two_way_short_needle (const unsigned char *haystack, size_t haystack_len, + const unsigned char *needle, size_t needle_len) + { +@@ -382,8 +382,11 @@ two_way_short_needle (const unsigned char *haystack, size_t haystack_len, + and sublinear performance O(HAYSTACK_LEN / NEEDLE_LEN) is possible. + If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * + HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and +- sublinear performance is not possible. */ +-static RETURN_TYPE ++ sublinear performance is not possible. ++ ++ Since this function is large and complex, block inlining to avoid ++ slowing down the common case of small needles. */ ++__attribute__((noinline)) static RETURN_TYPE + two_way_long_needle (const unsigned char *haystack, size_t haystack_len, + const unsigned char *needle, size_t needle_len) + { +diff --git a/string/strstr.c b/string/strstr.c +index f74d7189ed1319f6..7ffb18ab4285b060 100644 +--- a/string/strstr.c ++++ b/string/strstr.c +@@ -16,29 +16,17 @@ + License along with the GNU C Library; if not, see + . */ + +-/* This particular implementation was written by Eric Blake, 2008. */ +- + #ifndef _LIBC + # include + #endif + +-/* Specification of strstr. */ + #include + +-#include +- +-#ifndef _LIBC +-# define __builtin_expect(expr, val) (expr) +-#endif +- + #define RETURN_TYPE char * + #define AVAILABLE(h, h_l, j, n_l) \ + (((j) + (n_l) <= (h_l)) \ + || ((h_l) += __strnlen ((void*)((h) + (h_l)), (n_l) + 512), \ + (j) + (n_l) <= (h_l))) +-#define CHECK_EOL (1) +-#define RET0_IF_0(a) if (!a) goto ret0 +-#define FASTSEARCH(S,C,N) (void*) strchr ((void*)(S), (C)) + #include "str-two-way.h" + + #undef strstr +@@ -47,47 +35,128 @@ + #define STRSTR strstr + #endif + +-/* Return the first occurrence of NEEDLE in HAYSTACK. Return HAYSTACK +- if NEEDLE is empty, otherwise NULL if NEEDLE is not found in +- HAYSTACK. */ +-char * +-STRSTR (const char *haystack, const char *needle) ++static inline char * ++strstr2 (const unsigned char *hs, const unsigned char *ne) + { +- size_t needle_len; /* Length of NEEDLE. */ +- size_t haystack_len; /* Known minimum length of HAYSTACK. */ +- +- /* Handle empty NEEDLE special case. */ +- if (needle[0] == '\0') +- return (char *) haystack; ++ uint32_t h1 = (ne[0] << 16) | ne[1]; ++ uint32_t h2 = 0; ++ for (int c = hs[0]; h1 != h2 && c != 0; c = *++hs) ++ h2 = (h2 << 16) | c; ++ return h1 == h2 ? (char *)hs - 2 : NULL; ++} + +- /* Skip until we find the first matching char from NEEDLE. */ +- haystack = strchr (haystack, needle[0]); +- if (haystack == NULL || needle[1] == '\0') +- return (char *) haystack; ++static inline char * ++strstr3 (const unsigned char *hs, const unsigned char *ne) ++{ ++ uint32_t h1 = ((uint32_t)ne[0] << 24) | (ne[1] << 16) | (ne[2] << 8); ++ uint32_t h2 = 0; ++ for (int c = hs[0]; h1 != h2 && c != 0; c = *++hs) ++ h2 = (h2 | c) << 8; ++ return h1 == h2 ? (char *)hs - 3 : NULL; ++} + +- /* Ensure HAYSTACK length is at least as long as NEEDLE length. +- Since a match may occur early on in a huge HAYSTACK, use strnlen ++/* Hash character pairs so a small shift table can be used. All bits of ++ p[0] are included, but not all bits from p[-1]. So if two equal hashes ++ match on p[-1], p[0] matches too. Hash collisions are harmless and result ++ in smaller shifts. */ ++#define hash2(p) (((size_t)(p)[0] - ((size_t)(p)[-1] << 3)) % sizeof (shift)) ++ ++/* Fast strstr algorithm with guaranteed linear-time performance. ++ Small needles up to size 3 use a dedicated linear search. Longer needles ++ up to size 256 use a novel modified Horspool algorithm. It hashes pairs ++ of characters to quickly skip past mismatches. The main search loop only ++ exits if the last 2 characters match, avoiding unnecessary calls to memcmp ++ and allowing for a larger skip if there is no match. A self-adapting ++ filtering check is used to quickly detect mismatches in long needles. ++ By limiting the needle length to 256, the shift table can be reduced to 8 ++ bits per entry, lowering preprocessing overhead and minimizing cache effects. ++ The limit also implies worst-case performance is linear. ++ Needles larger than 256 characters use the linear-time Two-Way algorithm. */ ++char * ++STRSTR (const char *haystack, const char *needle) ++{ ++ const unsigned char *hs = (const unsigned char *) haystack; ++ const unsigned char *ne = (const unsigned char *) needle; ++ ++ /* Handle short needle special cases first. */ ++ if (ne[0] == '\0') ++ return (char *)hs; ++ hs = (const unsigned char *)strchr ((const char*)hs, ne[0]); ++ if (hs == NULL || ne[1] == '\0') ++ return (char*)hs; ++ if (ne[2] == '\0') ++ return strstr2 (hs, ne); ++ if (ne[3] == '\0') ++ return strstr3 (hs, ne); ++ ++ /* Ensure haystack length is at least as long as needle length. ++ Since a match may occur early on in a huge haystack, use strnlen + and read ahead a few cachelines for improved performance. */ +- needle_len = strlen (needle); +- haystack_len = __strnlen (haystack, needle_len + 256); +- if (haystack_len < needle_len) ++ size_t ne_len = strlen ((const char*)ne); ++ size_t hs_len = __strnlen ((const char*)hs, ne_len | 512); ++ if (hs_len < ne_len) + return NULL; + +- /* Check whether we have a match. This improves performance since we avoid +- the initialization overhead of the two-way algorithm. */ +- if (memcmp (haystack, needle, needle_len) == 0) +- return (char *) haystack; +- +- /* Perform the search. Abstract memory is considered to be an array +- of 'unsigned char' values, not an array of 'char' values. See +- ISO C 99 section 6.2.6.1. */ +- if (needle_len < LONG_NEEDLE_THRESHOLD) +- return two_way_short_needle ((const unsigned char *) haystack, +- haystack_len, +- (const unsigned char *) needle, needle_len); +- return two_way_long_needle ((const unsigned char *) haystack, haystack_len, +- (const unsigned char *) needle, needle_len); ++ /* Check whether we have a match. This improves performance since we ++ avoid initialization overheads. */ ++ if (memcmp (hs, ne, ne_len) == 0) ++ return (char *) hs; ++ ++ /* Use Two-Way algorithm for very long needles. */ ++ if (__glibc_unlikely (ne_len > 256)) ++ return two_way_long_needle (hs, hs_len, ne, ne_len); ++ ++ const unsigned char *end = hs + hs_len - ne_len; ++ uint8_t shift[256]; ++ size_t tmp, shift1; ++ size_t m1 = ne_len - 1; ++ size_t offset = 0; ++ ++ /* Initialize bad character shift hash table. */ ++ memset (shift, 0, sizeof (shift)); ++ for (int i = 1; i < m1; i++) ++ shift[hash2 (ne + i)] = i; ++ /* Shift1 is the amount we can skip after matching the hash of the ++ needle end but not the full needle. */ ++ shift1 = m1 - shift[hash2 (ne + m1)]; ++ shift[hash2 (ne + m1)] = m1; ++ ++ while (1) ++ { ++ if (__glibc_unlikely (hs > end)) ++ { ++ end += __strnlen ((const char*)end + m1 + 1, 2048); ++ if (hs > end) ++ return NULL; ++ } ++ ++ /* Skip past character pairs not in the needle. */ ++ do ++ { ++ hs += m1; ++ tmp = shift[hash2 (hs)]; ++ } ++ while (tmp == 0 && hs <= end); ++ ++ /* If the match is not at the end of the needle, shift to the end ++ and continue until we match the hash of the needle end. */ ++ hs -= tmp; ++ if (tmp < m1) ++ continue; ++ ++ /* Hash of the last 2 characters matches. If the needle is long, ++ try to quickly filter out mismatches. */ ++ if (m1 < 15 || memcmp (hs + offset, ne + offset, 8) == 0) ++ { ++ if (memcmp (hs, ne, m1) == 0) ++ return (void *) hs; ++ ++ /* Adjust filter offset when it doesn't find the mismatch. */ ++ offset = (offset >= 8 ? offset : m1) - 8; ++ } ++ ++ /* Skip based on matching the hash of the needle end. */ ++ hs += shift1; ++ } + } + libc_hidden_builtin_def (strstr) +- +-#undef LONG_NEEDLE_THRESHOLD diff --git a/glibc-rh1836867.patch b/glibc-rh1836867.patch new file mode 100755 index 0000000..d546a44 --- /dev/null +++ b/glibc-rh1836867.patch @@ -0,0 +1,194 @@ +commit 790b8dda4455865cb8c3a47801f4304c1a43baf6 +Author: Florian Weimer +Date: Tue May 19 14:09:38 2020 +0200 + + nss_compat: internal_end*ent may clobber errno, hiding ERANGE [BZ #25976] + + During cleanup, before returning from get*_r functions, the end*ent + calls must not change errno. Otherwise, an ERANGE error from the + underlying implementation can be hidden, causing unexpected lookup + failures. This commit introduces an internal_end*ent_noerror + function which saves and restore errno, and marks the original + internal_end*ent function as warn_unused_result, so that it is used + only in contexts were errors from it can be handled explicitly. + + Reviewed-by: DJ Delorie + +diff --git a/nss/nss_compat/compat-grp.c b/nss/nss_compat/compat-grp.c +index 012929eae7048702..fca9f4860f72e3d2 100644 +--- a/nss/nss_compat/compat-grp.c ++++ b/nss/nss_compat/compat-grp.c +@@ -142,7 +142,7 @@ _nss_compat_setgrent (int stayopen) + } + + +-static enum nss_status ++static enum nss_status __attribute_warn_unused_result__ + internal_endgrent (ent_t *ent) + { + if (ent->stream != NULL) +@@ -163,6 +163,15 @@ internal_endgrent (ent_t *ent) + return NSS_STATUS_SUCCESS; + } + ++/* Like internal_endgrent, but preserve errno in all cases. */ ++static void ++internal_endgrent_noerror (ent_t *ent) ++{ ++ int saved_errno = errno; ++ enum nss_status unused __attribute__ ((unused)) = internal_endgrent (ent); ++ __set_errno (saved_errno); ++} ++ + enum nss_status + _nss_compat_endgrent (void) + { +@@ -483,7 +492,7 @@ _nss_compat_getgrnam_r (const char *name, struct group *grp, + if (result == NSS_STATUS_SUCCESS) + result = internal_getgrnam_r (name, grp, &ent, buffer, buflen, errnop); + +- internal_endgrent (&ent); ++ internal_endgrent_noerror (&ent); + + return result; + } +@@ -612,7 +621,7 @@ _nss_compat_getgrgid_r (gid_t gid, struct group *grp, + if (result == NSS_STATUS_SUCCESS) + result = internal_getgrgid_r (gid, grp, &ent, buffer, buflen, errnop); + +- internal_endgrent (&ent); ++ internal_endgrent_noerror (&ent); + + return result; + } +diff --git a/nss/nss_compat/compat-initgroups.c b/nss/nss_compat/compat-initgroups.c +index 5beaa6b88b7e1764..d7a89ea8e7718ab0 100644 +--- a/nss/nss_compat/compat-initgroups.c ++++ b/nss/nss_compat/compat-initgroups.c +@@ -133,7 +133,7 @@ internal_setgrent (ent_t *ent) + } + + +-static enum nss_status ++static enum nss_status __attribute_warn_unused_result__ + internal_endgrent (ent_t *ent) + { + if (ent->stream != NULL) +@@ -157,6 +157,15 @@ internal_endgrent (ent_t *ent) + return NSS_STATUS_SUCCESS; + } + ++/* Like internal_endgrent, but preserve errno in all cases. */ ++static void ++internal_endgrent_noerror (ent_t *ent) ++{ ++ int saved_errno = errno; ++ enum nss_status unused __attribute__ ((unused)) = internal_endgrent (ent); ++ __set_errno (saved_errno); ++} ++ + /* Add new group record. */ + static void + add_group (long int *start, long int *size, gid_t **groupsp, long int limit, +@@ -501,7 +510,7 @@ _nss_compat_initgroups_dyn (const char *user, gid_t group, long int *start, + done: + scratch_buffer_free (&tmpbuf); + +- internal_endgrent (&intern); ++ internal_endgrent_noerror (&intern); + + return status; + } +diff --git a/nss/nss_compat/compat-pwd.c b/nss/nss_compat/compat-pwd.c +index a903452cdf96de74..8832fb7518d8bbff 100644 +--- a/nss/nss_compat/compat-pwd.c ++++ b/nss/nss_compat/compat-pwd.c +@@ -259,7 +259,7 @@ _nss_compat_setpwent (int stayopen) + } + + +-static enum nss_status ++static enum nss_status __attribute_warn_unused_result__ + internal_endpwent (ent_t *ent) + { + if (ent->stream != NULL) +@@ -287,6 +287,15 @@ internal_endpwent (ent_t *ent) + return NSS_STATUS_SUCCESS; + } + ++/* Like internal_endpwent, but preserve errno in all cases. */ ++static void ++internal_endpwent_noerror (ent_t *ent) ++{ ++ int saved_errno = errno; ++ enum nss_status unused __attribute__ ((unused)) = internal_endpwent (ent); ++ __set_errno (saved_errno); ++} ++ + enum nss_status + _nss_compat_endpwent (void) + { +@@ -822,7 +831,7 @@ _nss_compat_getpwnam_r (const char *name, struct passwd *pwd, + if (result == NSS_STATUS_SUCCESS) + result = internal_getpwnam_r (name, pwd, &ent, buffer, buflen, errnop); + +- internal_endpwent (&ent); ++ internal_endpwent_noerror (&ent); + + return result; + } +@@ -1061,7 +1070,7 @@ _nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd, + if (result == NSS_STATUS_SUCCESS) + result = internal_getpwuid_r (uid, pwd, &ent, buffer, buflen, errnop); + +- internal_endpwent (&ent); ++ internal_endpwent_noerror (&ent); + + return result; + } +diff --git a/nss/nss_compat/compat-spwd.c b/nss/nss_compat/compat-spwd.c +index eb96ca09172d5743..684a06007ab84ac9 100644 +--- a/nss/nss_compat/compat-spwd.c ++++ b/nss/nss_compat/compat-spwd.c +@@ -215,7 +215,7 @@ _nss_compat_setspent (int stayopen) + } + + +-static enum nss_status ++static enum nss_status __attribute_warn_unused_result__ + internal_endspent (ent_t *ent) + { + if (ent->stream != NULL) +@@ -244,6 +244,15 @@ internal_endspent (ent_t *ent) + return NSS_STATUS_SUCCESS; + } + ++/* Like internal_endspent, but preserve errno in all cases. */ ++static void ++internal_endspent_noerror (ent_t *ent) ++{ ++ int saved_errno = errno; ++ enum nss_status unused __attribute__ ((unused)) = internal_endspent (ent); ++ __set_errno (saved_errno); ++} ++ + enum nss_status + _nss_compat_endspent (void) + { +@@ -261,7 +270,6 @@ _nss_compat_endspent (void) + return result; + } + +- + static enum nss_status + getspent_next_nss_netgr (const char *name, struct spwd *result, ent_t *ent, + char *group, char *buffer, size_t buflen, +@@ -786,7 +794,7 @@ _nss_compat_getspnam_r (const char *name, struct spwd *pwd, + if (result == NSS_STATUS_SUCCESS) + result = internal_getspnam_r (name, pwd, &ent, buffer, buflen, errnop); + +- internal_endspent (&ent); ++ internal_endspent_noerror (&ent); + + return result; + } diff --git a/glibc-rh1845098-1.patch b/glibc-rh1845098-1.patch new file mode 100755 index 0000000..463697d --- /dev/null +++ b/glibc-rh1845098-1.patch @@ -0,0 +1,36 @@ +commit ae725e3f9cb4e1eb825ebe1d55241c98c2ea32f1 +Author: Tulio Magno Quites Machado Filho +Date: Mon Jun 15 11:15:57 2020 -0300 + + powerpc: Add new hwcap values + + Linux commit ID ee988c11acf6f9464b7b44e9a091bf6afb3b3a49 reserved 2 new + bits in AT_HWCAP2: + - PPC_FEATURE2_ARCH_3_1 indicates the availability of the POWER ISA + 3.1; + - PPC_FEATURE2_MMA indicates the availability of the Matrix-Multiply + Assist facility. + +diff --git a/sysdeps/powerpc/bits/hwcap.h b/sysdeps/powerpc/bits/hwcap.h +index b35f5eddc1d309bb..f2853a11df16f63c 100644 +--- a/sysdeps/powerpc/bits/hwcap.h ++++ b/sysdeps/powerpc/bits/hwcap.h +@@ -74,3 +74,5 @@ + #define PPC_FEATURE2_SCV 0x00100000 /* scv syscall. */ + #define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000 /* TM without suspended + state. */ ++#define PPC_FEATURE2_ARCH_3_1 0x00040000 /* ISA 3.1. */ ++#define PPC_FEATURE2_MMA 0x00020000 /* Matrix-Multiply Assist. */ +diff --git a/sysdeps/powerpc/dl-procinfo.c b/sysdeps/powerpc/dl-procinfo.c +index 35cac2e249916507..4555d4548554e788 100644 +--- a/sysdeps/powerpc/dl-procinfo.c ++++ b/sysdeps/powerpc/dl-procinfo.c +@@ -77,7 +77,7 @@ PROCINFO_CLASS const char _dl_powerpc_cap_flags[64][15] + "", "", "", "", + "", "", "", "", + "", "", "", "", +- "", "", "", "htm-no-suspend", ++ "", "mma", "arch_3_1", "htm-no-suspend", + "scv", "darn", "ieee128", "arch_3_00", + "htm-nosc", "vcrypto", "tar", "isel", + "ebb", "dscr", "htm", "arch_2_07", diff --git a/glibc-rh1845098-2.patch b/glibc-rh1845098-2.patch new file mode 100755 index 0000000..d947c3b --- /dev/null +++ b/glibc-rh1845098-2.patch @@ -0,0 +1,52 @@ +This patch is based on the following commit, with the new Implies +files for POWER10, and the preconfigure changes removed. + +commit d2ba3677da7a785556fcd708404d8e049b1c063b +Author: Tulio Magno Quites Machado Filho +Date: Wed Jun 24 18:04:41 2020 -0300 + + powerpc: Add support for POWER10 + + 1. Add the directories to hold POWER10 files. + + 2. Add support to select POWER10 libraries based on AT_PLATFORM. + + 3. Let submachine=power10 be set automatically. + + +diff --git a/sysdeps/powerpc/dl-procinfo.h b/sysdeps/powerpc/dl-procinfo.h +index 3803379ab2303658..3558d6a83ca2a988 100644 +--- a/sysdeps/powerpc/dl-procinfo.h ++++ b/sysdeps/powerpc/dl-procinfo.h +@@ -37,7 +37,7 @@ + #define HWCAP_IMPORTANT (PPC_FEATURE_HAS_ALTIVEC \ + + PPC_FEATURE_HAS_DFP) + +-#define _DL_PLATFORMS_COUNT 15 ++#define _DL_PLATFORMS_COUNT 16 + + #define _DL_FIRST_PLATFORM 32 + /* Mask to filter out platforms. */ +@@ -60,6 +60,7 @@ + #define PPC_PLATFORM_PPC476 12 + #define PPC_PLATFORM_POWER8 13 + #define PPC_PLATFORM_POWER9 14 ++#define PPC_PLATFORM_POWER10 15 + + static inline const char * + __attribute__ ((unused)) +@@ -91,6 +92,14 @@ _dl_string_platform (const char *str) + str += 5; + switch (*str) + { ++ case '1': ++ if (str[1] == '0') ++ { ++ ret = _DL_FIRST_PLATFORM + PPC_PLATFORM_POWER10; ++ } ++ else ++ return -1; ++ break; + case '4': + ret = _DL_FIRST_PLATFORM + PPC_PLATFORM_POWER4; + break; diff --git a/glibc-rh1845098-3.patch b/glibc-rh1845098-3.patch new file mode 100755 index 0000000..feefa6f --- /dev/null +++ b/glibc-rh1845098-3.patch @@ -0,0 +1,26 @@ +commit f6add169c89bbdd139a2eb845686127ead5799cd +Author: Tulio Magno Quites Machado Filho +Date: Tue Jul 21 18:01:39 2020 -0300 + + powerpc: Fix POWER10 selection + + Add a line that was missing from a previous commit. + Without increasing str, the null-byte is not validated, and + _dl_string_platform returns -1. + + Fixes: d2ba3677da7a ("powerpc: Add support for POWER10") + + Reviewed-by: Carlos O'Donell + +diff --git a/sysdeps/powerpc/dl-procinfo.h b/sysdeps/powerpc/dl-procinfo.h +index 3558d6a83ca2a988..3593e9661b06dcff 100644 +--- a/sysdeps/powerpc/dl-procinfo.h ++++ b/sysdeps/powerpc/dl-procinfo.h +@@ -96,6 +96,7 @@ _dl_string_platform (const char *str) + if (str[1] == '0') + { + ret = _DL_FIRST_PLATFORM + PPC_PLATFORM_POWER10; ++ str++; + } + else + return -1; diff --git a/glibc-rh1855790-1.patch b/glibc-rh1855790-1.patch new file mode 100755 index 0000000..91eaf37 --- /dev/null +++ b/glibc-rh1855790-1.patch @@ -0,0 +1,120 @@ +commit 15eab1e3e89129ab3ed03f5bdc3415b26e9caeb9 +Author: H.J. Lu +Date: Sat Feb 1 05:44:55 2020 -0800 + + i386: Don't unnecessarily save and restore EAX, ECX and EDX [BZ# 25262] + + On i386, since EAX, ECX and EDX are caller-saved, there are no need + to save and restore EAX, ECX and EDX in getcontext, setcontext and + swapcontext. They just need to clear EAX on success. The extra + scratch registers are needed to enable CET. + + Tested on i386. + + Reviewed-by: Adhemerval Zanella +--- + +diff --git a/sysdeps/unix/sysv/linux/i386/getcontext.S b/sysdeps/unix/sysv/linux/i386/getcontext.S +index 26ca08a..6637596 100644 +--- a/sysdeps/unix/sysv/linux/i386/getcontext.S ++++ b/sysdeps/unix/sysv/linux/i386/getcontext.S +@@ -26,13 +26,7 @@ ENTRY(__getcontext) + /* Load address of the context data structure. */ + movl 4(%esp), %eax + +- /* Return value of getcontext. EAX is the only register whose +- value is not preserved. */ +- movl $0, oEAX(%eax) +- +- /* Save the 32-bit register values and the return address. */ +- movl %ecx, oECX(%eax) +- movl %edx, oEDX(%eax) ++ /* Save the preserved register values and the return address. */ + movl %edi, oEDI(%eax) + movl %esi, oESI(%eax) + movl %ebp, oEBP(%eax) +diff --git a/sysdeps/unix/sysv/linux/i386/setcontext.S b/sysdeps/unix/sysv/linux/i386/setcontext.S +index a604fca..7565d7d 100644 +--- a/sysdeps/unix/sysv/linux/i386/setcontext.S ++++ b/sysdeps/unix/sysv/linux/i386/setcontext.S +@@ -65,22 +65,19 @@ ENTRY(__setcontext) + cfi_offset (esi, oESI) + cfi_offset (ebp, oEBP) + cfi_offset (ebx, oEBX) +- cfi_offset (edx, oEDX) +- cfi_offset (ecx, oECX) + movl oESP(%eax), %esp + + /* Push the return address on the new stack so we can return there. */ + pushl %ecx + +- /* Load the values of all the 32-bit registers (except ESP). +- Since we are loading from EAX, it must be last. */ ++ /* Load the values of all the preserved registers (except ESP). */ + movl oEDI(%eax), %edi + movl oESI(%eax), %esi + movl oEBP(%eax), %ebp + movl oEBX(%eax), %ebx +- movl oEDX(%eax), %edx +- movl oECX(%eax), %ecx +- movl oEAX(%eax), %eax ++ ++ /* All done, return 0 for success. */ ++ xorl %eax, %eax + + /* End FDE here, we fall into another context. */ + cfi_endproc +diff --git a/sysdeps/unix/sysv/linux/i386/swapcontext.S b/sysdeps/unix/sysv/linux/i386/swapcontext.S +index 431f22c..ce27d51 100644 +--- a/sysdeps/unix/sysv/linux/i386/swapcontext.S ++++ b/sysdeps/unix/sysv/linux/i386/swapcontext.S +@@ -26,13 +26,7 @@ ENTRY(__swapcontext) + /* Load address of the context data structure we save in. */ + movl 4(%esp), %eax + +- /* Return value of swapcontext. EAX is the only register whose +- value is not preserved. */ +- movl $0, oEAX(%eax) +- +- /* Save the 32-bit register values and the return address. */ +- movl %ecx, oECX(%eax) +- movl %edx, oEDX(%eax) ++ /* Save the preserved register values and the return address. */ + movl %edi, oEDI(%eax) + movl %esi, oESI(%eax) + movl %ebp, oEBP(%eax) +@@ -91,15 +85,14 @@ ENTRY(__swapcontext) + /* Push the return address on the new stack so we can return there. */ + pushl %ecx + +- /* Load the values of all the 32-bit registers (except ESP). +- Since we are loading from EAX, it must be last. */ ++ /* Load the values of all the preserved registers (except ESP). */ + movl oEDI(%eax), %edi + movl oESI(%eax), %esi + movl oEBP(%eax), %ebp + movl oEBX(%eax), %ebx +- movl oEDX(%eax), %edx +- movl oECX(%eax), %ecx +- movl oEAX(%eax), %eax ++ ++ /* All done, return 0 for success. */ ++ xorl %eax, %eax + + /* The following 'ret' will pop the address of the code and jump + to it. */ +diff --git a/sysdeps/unix/sysv/linux/i386/ucontext_i.sym b/sysdeps/unix/sysv/linux/i386/ucontext_i.sym +index b11a550..1dfe03d 100644 +--- a/sysdeps/unix/sysv/linux/i386/ucontext_i.sym ++++ b/sysdeps/unix/sysv/linux/i386/ucontext_i.sym +@@ -21,9 +21,6 @@ oESI mreg (ESI) + oEBP mreg (EBP) + oESP mreg (ESP) + oEBX mreg (EBX) +-oEDX mreg (EDX) +-oECX mreg (ECX) +-oEAX mreg (EAX) + oEIP mreg (EIP) + oFPREGS mcontext (fpregs) + oSIGMASK ucontext (uc_sigmask) + diff --git a/glibc-rh1855790-10.patch b/glibc-rh1855790-10.patch new file mode 100755 index 0000000..fb4a056 --- /dev/null +++ b/glibc-rh1855790-10.patch @@ -0,0 +1,380 @@ +commit 9e38f455a6c602be86b7b5a8d6523cbdcd7ec051 +Author: H.J. Lu +Date: Mon Apr 27 15:44:07 2020 -0700 + + x86: Add --enable-cet=permissive + + When CET is enabled, it is an error to dlopen a non CET enabled shared + library in CET enabled application. It may be desirable to make CET + permissive, that is disable CET when dlopening a non CET enabled shared + library. With the new --enable-cet=permissive configure option, CET is + disabled when dlopening a non CET enabled shared library. + + Add DEFAULT_DL_X86_CET_CONTROL to config.h.in: + + /* The default value of x86 CET control. */ + #define DEFAULT_DL_X86_CET_CONTROL cet_elf_property + + which enables CET features based on ELF property note. + + --enable-cet=permissive it to + + /* The default value of x86 CET control. */ + #define DEFAULT_DL_X86_CET_CONTROL cet_permissive + + which enables CET features permissively. + + Update tst-cet-legacy-5a, tst-cet-legacy-5b, tst-cet-legacy-6a and + tst-cet-legacy-6b to check --enable-cet and --enable-cet=permissive. +--- + +diff --git a/INSTALL b/INSTALL +index d56e102..0655650 100644 +--- a/INSTALL ++++ b/INSTALL +@@ -116,20 +116,24 @@ if 'CFLAGS' is specified it must enable optimization. For example: + executables (PIE) by default. + + '--enable-cet' ++'--enable-cet=permissive' + Enable Intel Control-flow Enforcement Technology (CET) support. +- When the GNU C Library is built with '--enable-cet', the resulting +- library is protected with indirect branch tracking (IBT) and shadow +- stack (SHSTK). When CET is enabled, the GNU C Library is +- compatible with all existing executables and shared libraries. +- This feature is currently supported on i386, x86_64 and x32 with +- GCC 8 and binutils 2.29 or later. Note that when CET is enabled, +- the GNU C Library requires CPUs capable of multi-byte NOPs, like +- x86-64 processors as well as Intel Pentium Pro or newer. ++ When the GNU C Library is built with '--enable-cet' or ++ '--enable-cet=permissive', the resulting library is protected with ++ indirect branch tracking (IBT) and shadow stack (SHSTK). When CET ++ is enabled, the GNU C Library is compatible with all existing ++ executables and shared libraries. This feature is currently ++ supported on i386, x86_64 and x32 with GCC 8 and binutils 2.29 or ++ later. Note that when CET is enabled, the GNU C Library requires ++ CPUs capable of multi-byte NOPs, like x86-64 processors as well as ++ Intel Pentium Pro or newer. With '--enable-cet', it is an error to ++ dlopen a non CET enabled shared library in CET enabled application. ++ With '--enable-cet=permissive', CET is disabled when dlopening a ++ non CET enabled shared library in CET enabled application. + + NOTE: '--enable-cet' has been tested for i686, x86_64 and x32 on +- non-CET processors. '--enable-cet' has been tested for x86_64 and +- x32 on CET SDVs, but Intel CET support hasn't been validated for +- i686. ++ non-CET processors. '--enable-cet' has been tested for i686, ++ x86_64 and x32 on CET processors. + + '--disable-profile' + Don't build libraries with profiling information. You may want to +diff --git a/config.h.in b/config.h.in +index f63f6c8..8520b0f 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -259,4 +259,7 @@ + in i386 6 argument syscall issue). */ + #define CAN_USE_REGISTER_ASM_EBP 0 + ++/* The default value of x86 CET control. */ ++#define DEFAULT_DL_X86_CET_CONTROL cet_elf_property ++ + #endif +diff --git a/manual/install.texi b/manual/install.texi +index 351d67c..7e9f2be 100644 +--- a/manual/install.texi ++++ b/manual/install.texi +@@ -147,20 +147,24 @@ PIE. This option also implies that glibc programs and tests are created + as dynamic position independent executables (PIE) by default. + + @item --enable-cet ++@itemx --enable-cet=permissive + Enable Intel Control-flow Enforcement Technology (CET) support. When +-@theglibc{} is built with @option{--enable-cet}, the resulting library ++@theglibc{} is built with @option{--enable-cet} or ++@option{--enable-cet=permissive}, the resulting library + is protected with indirect branch tracking (IBT) and shadow stack + (SHSTK)@. When CET is enabled, @theglibc{} is compatible with all + existing executables and shared libraries. This feature is currently + supported on i386, x86_64 and x32 with GCC 8 and binutils 2.29 or later. + Note that when CET is enabled, @theglibc{} requires CPUs capable of + multi-byte NOPs, like x86-64 processors as well as Intel Pentium Pro or +-newer. ++newer. With @option{--enable-cet}, it is an error to dlopen a non CET ++enabled shared library in CET enabled application. With ++@option{--enable-cet=permissive}, CET is disabled when dlopening a ++non CET enabled shared library in CET enabled application. + + NOTE: @option{--enable-cet} has been tested for i686, x86_64 and x32 + on non-CET processors. @option{--enable-cet} has been tested for +-x86_64 and x32 on CET SDVs, but Intel CET support hasn't been validated +-for i686. ++i686, x86_64 and x32 on CET processors. + + @item --disable-profile + Don't build libraries with profiling information. You may want to use +diff --git a/sysdeps/unix/sysv/linux/x86/Makefile b/sysdeps/unix/sysv/linux/x86/Makefile +index 7dc4e61..8ac2fd4 100644 +--- a/sysdeps/unix/sysv/linux/x86/Makefile ++++ b/sysdeps/unix/sysv/linux/x86/Makefile +@@ -24,7 +24,7 @@ ifeq ($(subdir),setjmp) + tests += tst-saved_mask-1 + endif + +-ifeq ($(enable-cet),yes) ++ifneq ($(enable-cet),no) + ifeq ($(subdir),elf) + tests += tst-cet-property-1 tst-cet-property-2 + +diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile +index d9bdf0b..d5f821e 100644 +--- a/sysdeps/x86/Makefile ++++ b/sysdeps/x86/Makefile +@@ -14,7 +14,7 @@ gen-as-const-headers += jmp_buf-ssp.sym + sysdep_routines += __longjmp_cancel + endif + +-ifeq ($(enable-cet),yes) ++ifneq ($(enable-cet),no) + ifeq ($(subdir),elf) + sysdep-dl-routines += dl-cet + +@@ -41,13 +41,21 @@ CFLAGS-tst-cet-legacy-4.c += -fcf-protection=branch + CFLAGS-tst-cet-legacy-4a.c += -fcf-protection + CFLAGS-tst-cet-legacy-4b.c += -fcf-protection + CFLAGS-tst-cet-legacy-mod-4.c += -fcf-protection=none +-CFLAGS-tst-cet-legacy-5a.c += -fcf-protection +-CFLAGS-tst-cet-legacy-5b.c += -fcf-protection ++CFLAGS-tst-cet-legacy-5a.c += -fcf-protection -mshstk ++ifeq ($(enable-cet),permissive) ++CPPFLAGS-tst-cet-legacy-5a.c += -DCET_IS_PERMISSIVE=1 ++endif ++CFLAGS-tst-cet-legacy-5b.c += -fcf-protection -mshstk ++CPPFLAGS-tst-cet-legacy-5b.c += -DCET_DISABLED_BY_ENV=1 + CFLAGS-tst-cet-legacy-mod-5a.c += -fcf-protection=branch + CFLAGS-tst-cet-legacy-mod-5b.c += -fcf-protection + CFLAGS-tst-cet-legacy-mod-5c.c += -fcf-protection +-CFLAGS-tst-cet-legacy-6a.c += -fcf-protection +-CFLAGS-tst-cet-legacy-6b.c += -fcf-protection ++CFLAGS-tst-cet-legacy-6a.c += -fcf-protection -mshstk ++ifeq ($(enable-cet),permissive) ++CPPFLAGS-tst-cet-legacy-6a.c += -DCET_IS_PERMISSIVE=1 ++endif ++CFLAGS-tst-cet-legacy-6b.c += -fcf-protection -mshstk ++CPPFLAGS-tst-cet-legacy-6b.c += -DCET_DISABLED_BY_ENV=1 + CFLAGS-tst-cet-legacy-mod-6a.c += -fcf-protection=branch + CFLAGS-tst-cet-legacy-mod-6b.c += -fcf-protection + CFLAGS-tst-cet-legacy-mod-6c.c += -fcf-protection +diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure +index b1ff281..81cc4e8 100644 +--- a/sysdeps/x86/configure ++++ b/sysdeps/x86/configure +@@ -1,7 +1,7 @@ + # This file is generated from configure.ac by Autoconf. DO NOT EDIT! + # Local configure fragment for sysdeps/x86. + +-if test x"$enable_cet" = xyes; then ++if test $enable_cet != no; then + # Check if CET can be enabled. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether CET can be enabled" >&5 + $as_echo_n "checking whether CET can be enabled... " >&6; } +@@ -27,17 +27,11 @@ EOF + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_x86_cet_available" >&5 + $as_echo "$libc_cv_x86_cet_available" >&6; } +- if test $libc_cv_x86_cet_available = yes; then +- enable_cet=yes +- else +- if test x"$enable_cet" = xdefault; then +- enable_cet=no +- else +- as_fn_error $? "$CC doesn't support CET" "$LINENO" 5 +- fi ++ if test $libc_cv_x86_cet_available != yes; then ++ as_fn_error $? "$CC doesn't support CET" "$LINENO" 5 + fi + fi +-if test $enable_cet = yes; then ++if test $enable_cet != no; then + # Check if assembler supports CET. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $AS supports CET" >&5 + $as_echo_n "checking whether $AS supports CET... " >&6; } +@@ -65,5 +59,12 @@ $as_echo "$libc_cv_x86_cet_as" >&6; } + as_fn_error $? "$AS doesn't support CET" "$LINENO" 5 + fi + fi ++if test $enable_cet = yes; then ++ $as_echo "#define DEFAULT_DL_X86_CET_CONTROL cet_elf_property" >>confdefs.h ++ ++elif test $enable_cet = permissive; then ++ $as_echo "#define DEFAULT_DL_X86_CET_CONTROL cet_permissive" >>confdefs.h ++ ++fi + config_vars="$config_vars + enable-cet = $enable_cet" +diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac +index a909b07..8f3e119 100644 +--- a/sysdeps/x86/configure.ac ++++ b/sysdeps/x86/configure.ac +@@ -1,7 +1,7 @@ + GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. + # Local configure fragment for sysdeps/x86. + +-if test x"$enable_cet" = xyes; then ++if test $enable_cet != no; then + # Check if CET can be enabled. + AC_CACHE_CHECK(whether CET can be enabled, + libc_cv_x86_cet_available, [dnl +@@ -16,17 +16,11 @@ EOF + libc_cv_x86_cet_available=no + fi + rm -rf conftest*]) +- if test $libc_cv_x86_cet_available = yes; then +- enable_cet=yes +- else +- if test x"$enable_cet" = xdefault; then +- enable_cet=no +- else +- AC_MSG_ERROR([$CC doesn't support CET]) +- fi ++ if test $libc_cv_x86_cet_available != yes; then ++ AC_MSG_ERROR([$CC doesn't support CET]) + fi + fi +-if test $enable_cet = yes; then ++if test $enable_cet != no; then + # Check if assembler supports CET. + AC_CACHE_CHECK(whether $AS supports CET, + libc_cv_x86_cet_as, [dnl +@@ -43,4 +37,9 @@ EOF + AC_MSG_ERROR([$AS doesn't support CET]) + fi + fi ++if test $enable_cet = yes; then ++ AC_DEFINE(DEFAULT_DL_X86_CET_CONTROL, cet_elf_property) ++elif test $enable_cet = permissive; then ++ AC_DEFINE(DEFAULT_DL_X86_CET_CONTROL, cet_permissive) ++fi + LIBC_CONFIG_VAR([enable-cet], [$enable_cet]) +diff --git a/sysdeps/x86/dl-procruntime.c b/sysdeps/x86/dl-procruntime.c +index 26b2b39..72b16fa 100644 +--- a/sysdeps/x86/dl-procruntime.c ++++ b/sysdeps/x86/dl-procruntime.c +@@ -65,8 +65,8 @@ PROCINFO_CLASS struct dl_x86_feature_control _dl_x86_feature_control + # endif + # ifndef PROCINFO_DECL + = { +- .ibt = cet_elf_property, +- .shstk = cet_elf_property ++ .ibt = DEFAULT_DL_X86_CET_CONTROL, ++ .shstk = DEFAULT_DL_X86_CET_CONTROL, + } + # endif + # if !defined SHARED || defined PROCINFO_DECL +diff --git a/sysdeps/x86/tst-cet-legacy-5.c b/sysdeps/x86/tst-cet-legacy-5.c +index 0a34d37..c578979 100644 +--- a/sysdeps/x86/tst-cet-legacy-5.c ++++ b/sysdeps/x86/tst-cet-legacy-5.c +@@ -22,6 +22,14 @@ + #include + #include + #include ++#include ++#include ++ ++#if defined CET_IS_PERMISSIVE || defined CET_DISABLED_BY_ENV ++# define CET_MAYBE_DISABLED 1 ++#else ++# define CET_MAYBE_DISABLED 0 ++#endif + + static void + do_test_1 (const char *modname, bool fail) +@@ -32,24 +40,25 @@ do_test_1 (const char *modname, bool fail) + h = dlopen (modname, RTLD_LAZY); + if (h == NULL) + { ++ const char *err = dlerror (); + if (fail) + { +- const char *err = dlerror (); + if (strstr (err, "rebuild shared object with SHSTK support enabled") + == NULL) +- { +- printf ("incorrect dlopen '%s' error: %s\n", modname, +- err); +- exit (1); +- } ++ FAIL_EXIT1 ("incorrect dlopen '%s' error: %s\n", modname, err); + + return; + } + +- printf ("cannot open '%s': %s\n", modname, dlerror ()); +- exit (1); ++ FAIL_EXIT1 ("cannot open '%s': %s\n", modname, err); + } + ++ /* NB: dlopen should never fail on non-CET platforms. If SHSTK is ++ disabled, assuming IBT is also disabled. */ ++ bool cet_enabled = _get_ssp () != 0 && !CET_MAYBE_DISABLED; ++ if (fail && cet_enabled) ++ FAIL_EXIT1 ("dlopen should have failed\n"); ++ + fp = dlsym (h, "test"); + if (fp == NULL) + { +diff --git a/sysdeps/x86/tst-cet-legacy-6.c b/sysdeps/x86/tst-cet-legacy-6.c +index bd45218..78e72ba 100644 +--- a/sysdeps/x86/tst-cet-legacy-6.c ++++ b/sysdeps/x86/tst-cet-legacy-6.c +@@ -22,6 +22,14 @@ + #include + #include + #include ++#include ++#include ++ ++#if defined CET_IS_PERMISSIVE || defined CET_DISABLED_BY_ENV ++# define CET_MAYBE_DISABLED 1 ++#else ++# define CET_MAYBE_DISABLED 0 ++#endif + + static void + do_test_1 (const char *modname, bool fail) +@@ -32,24 +40,25 @@ do_test_1 (const char *modname, bool fail) + h = dlopen (modname, RTLD_LAZY); + if (h == NULL) + { ++ const char *err = dlerror (); + if (fail) + { +- const char *err = dlerror (); + if (strstr (err, "rebuild shared object with SHSTK support enabled") + == NULL) +- { +- printf ("incorrect dlopen '%s' error: %s\n", modname, +- err); +- exit (1); +- } ++ FAIL_EXIT1 ("incorrect dlopen '%s' error: %s\n", modname, err); + + return; + } + +- printf ("cannot open '%s': %s\n", modname, dlerror ()); +- exit (1); ++ FAIL_EXIT1 ("cannot open '%s': %s\n", modname, err); + } + ++ /* NB: dlopen should never fail on non-CET platforms. If SHSTK is ++ disabled, assuming IBT is also disabled. */ ++ bool cet_enabled = _get_ssp () != 0 && !CET_MAYBE_DISABLED; ++ if (fail && cet_enabled) ++ FAIL_EXIT1 ("dlopen should have failed\n"); ++ + fp = dlsym (h, "test"); + if (fp == NULL) + { + diff --git a/glibc-rh1855790-11.patch b/glibc-rh1855790-11.patch new file mode 100755 index 0000000..8f6d3c4 --- /dev/null +++ b/glibc-rh1855790-11.patch @@ -0,0 +1,293 @@ +commit c02695d776406faaf63418e4e80c4a7023af0b4f +Author: H.J. Lu +Date: Wed Sep 16 16:00:14 2020 -0700 + + x86/CET: Update vfork to prevent child return + + Child of vfork should either call _exit or one of the exec family of + functions. But normally there is nothing to prevent child of vfork from + return of the vfork-calling function. Simpilfy x86 vfork when shadow + stack is in use to introduce mismatched shadow stack in child of vfork + to trigger SIGSEGV when the child returns from the function in which + vfork was called. +--- + +diff --git a/sysdeps/unix/sysv/linux/i386/vfork.S b/sysdeps/unix/sysv/linux/i386/vfork.S +index ceb41db0bd..91277a639f 100644 +--- a/sysdeps/unix/sysv/linux/i386/vfork.S ++++ b/sysdeps/unix/sysv/linux/i386/vfork.S +@@ -21,39 +21,6 @@ + #include + #include + +-#if SHSTK_ENABLED +-/* The shadow stack prevents us from pushing the saved return PC onto +- the stack and returning normally. Instead we pop the shadow stack +- and return directly. This is the safest way to return and ensures +- any stack manipulations done by the vfork'd child doesn't cause the +- parent to terminate when CET is enabled. */ +-# undef SYSCALL_ERROR_HANDLER +-# ifdef PIC +-# define SYSCALL_ERROR_HANDLER \ +-0: \ +- calll .L1; \ +-.L1: \ +- popl %edx; \ +-.L2: \ +- addl $_GLOBAL_OFFSET_TABLE_ + (.L2 - .L1), %edx; \ +- movl __libc_errno@gotntpoff(%edx), %edx; \ +- negl %eax; \ +- movl %eax, %gs:(%edx); \ +- orl $-1, %eax; \ +- jmp 1b; +-# else +-# define SYSCALL_ERROR_HANDLER \ +-0: \ +- movl __libc_errno@indntpoff, %edx; \ +- negl %eax; \ +- movl %eax, %gs:(%edx); \ +- orl $-1, %eax; \ +- jmp 1b; +-# endif +-# undef SYSCALL_ERROR_LABEL +-# define SYSCALL_ERROR_LABEL 0f +-#endif +- + /* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, +@@ -70,20 +37,17 @@ ENTRY (__vfork) + movl $SYS_ify (vfork), %eax + int $0x80 + +-#if !SHSTK_ENABLED + /* Jump to the return PC. Don't jump directly since this + disturbs the branch target cache. Instead push the return + address back on the stack. */ + pushl %ecx + cfi_adjust_cfa_offset (4) +-#endif + + cmpl $-4095, %eax + /* Branch forward if it failed. */ + jae SYSCALL_ERROR_LABEL + + #if SHSTK_ENABLED +-1: + /* Check if shadow stack is in use. */ + xorl %edx, %edx + rdsspd %edx +@@ -91,18 +55,19 @@ ENTRY (__vfork) + /* Normal return if shadow stack isn't in use. */ + je L(no_shstk) + +- /* Pop return address from shadow stack and jump back to caller +- directly. */ +- movl $1, %edx +- incsspd %edx ++ testl %eax, %eax ++ /* In parent, normal return. */ ++ jnz L(no_shstk) ++ ++ /* NB: In child, jump back to caller via indirect branch without ++ popping shadow stack which is shared with parent. Keep shadow ++ stack mismatched so that child returns in the vfork-calling ++ function will trigger SIGSEGV. */ ++ popl %ecx ++ cfi_adjust_cfa_offset (-4) + jmp *%ecx + + L(no_shstk): +- /* Jump to the return PC. Don't jump directly since this +- disturbs the branch target cache. Instead push the return +- address back on the stack. */ +- pushl %ecx +- cfi_adjust_cfa_offset (4) + #endif + + ret +diff --git a/sysdeps/unix/sysv/linux/x86/Makefile b/sysdeps/unix/sysv/linux/x86/Makefile +index 50fd018fa3..6bfd6bec49 100644 +--- a/sysdeps/unix/sysv/linux/x86/Makefile ++++ b/sysdeps/unix/sysv/linux/x86/Makefile +@@ -40,6 +40,11 @@ $(objpfx)tst-cet-property-2.out: $(objpfx)tst-cet-property-2 \ + $(evaluate-test) + endif + ++ifeq ($(subdir),posix) ++tests += tst-cet-vfork-1 ++CFLAGS-tst-cet-vfork-1.c += -mshstk ++endif ++ + ifeq ($(subdir),stdlib) + tests += tst-cet-setcontext-1 + CFLAGS-tst-cet-setcontext-1.c += -mshstk +diff --git a/sysdeps/unix/sysv/linux/x86/tst-cet-vfork-1.c b/sysdeps/unix/sysv/linux/x86/tst-cet-vfork-1.c +new file mode 100644 +index 0000000000..5b9fc8c170 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/x86/tst-cet-vfork-1.c +@@ -0,0 +1,88 @@ ++/* Verify that child of the vfork-calling function can't return when ++ shadow stack is in use. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++__attribute__ ((noclone, noinline)) ++static void ++do_test_1 (void) ++{ ++ pid_t p1; ++ int fd[2]; ++ ++ if (pipe (fd) == -1) ++ { ++ puts ("pipe failed"); ++ _exit (EXIT_FAILURE); ++ } ++ ++ if ((p1 = vfork ()) == 0) ++ { ++ pid_t p = getpid (); ++ TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))); ++ /* Child return should trigger SIGSEGV. */ ++ return; ++ } ++ else if (p1 == -1) ++ { ++ puts ("vfork failed"); ++ _exit (EXIT_FAILURE); ++ } ++ ++ pid_t p2 = 0; ++ if (TEMP_FAILURE_RETRY (read (fd[0], &p2, sizeof (pid_t))) ++ != sizeof (pid_t)) ++ puts ("pipd read failed"); ++ else ++ { ++ int r; ++ if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1) ++ puts ("waitpid failed"); ++ else if (r != 0) ++ puts ("pip write in child failed"); ++ } ++ ++ /* Parent exits immediately so that parent returns without triggering ++ SIGSEGV when shadow stack isn't in use. */ ++ _exit (EXIT_FAILURE); ++} ++ ++static int ++do_test (void) ++{ ++ /* NB: This test should trigger SIGSEGV with shadow stack enabled. */ ++ if (_get_ssp () == 0) ++ return EXIT_UNSUPPORTED; ++ do_test_1 (); ++ /* Child exits immediately so that child returns without triggering ++ SIGSEGV when shadow stack isn't in use. */ ++ _exit (EXIT_FAILURE); ++} ++ ++#define EXPECTED_SIGNAL (_get_ssp () == 0 ? 0 : SIGSEGV) ++#include +diff --git a/sysdeps/unix/sysv/linux/x86_64/vfork.S b/sysdeps/unix/sysv/linux/x86_64/vfork.S +index 776d2fc610..613ff7e846 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/vfork.S ++++ b/sysdeps/unix/sysv/linux/x86_64/vfork.S +@@ -20,22 +20,6 @@ + #include + #include + +-#if SHSTK_ENABLED +-/* The shadow stack prevents us from pushing the saved return PC onto +- the stack and returning normally. Instead we pop the shadow stack +- and return directly. This is the safest way to return and ensures +- any stack manipulations done by the vfork'd child doesn't cause the +- parent to terminate when CET is enabled. */ +-# undef SYSCALL_ERROR_HANDLER +-# define SYSCALL_ERROR_HANDLER \ +-0: \ +- SYSCALL_SET_ERRNO; \ +- or $-1, %RAX_LP; \ +- jmp 1b; +-# undef SYSCALL_ERROR_LABEL +-# define SYSCALL_ERROR_LABEL 0f +-#endif +- + /* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, +@@ -53,17 +37,14 @@ ENTRY (__vfork) + movl $SYS_ify (vfork), %eax + syscall + +-#if !SHSTK_ENABLED + /* Push back the return PC. */ + pushq %rdi + cfi_adjust_cfa_offset(8) +-#endif + + cmpl $-4095, %eax + jae SYSCALL_ERROR_LABEL /* Branch forward if it failed. */ + + #if SHSTK_ENABLED +-1: + /* Check if shadow stack is in use. */ + xorl %esi, %esi + rdsspq %rsi +@@ -71,16 +52,19 @@ ENTRY (__vfork) + /* Normal return if shadow stack isn't in use. */ + je L(no_shstk) + +- /* Pop return address from shadow stack and jump back to caller +- directly. */ +- movl $1, %esi +- incsspq %rsi ++ testl %eax, %eax ++ /* In parent, normal return. */ ++ jnz L(no_shstk) ++ ++ /* NB: In child, jump back to caller via indirect branch without ++ popping shadow stack which is shared with parent. Keep shadow ++ stack mismatched so that child returns in the vfork-calling ++ function will trigger SIGSEGV. */ ++ popq %rdi ++ cfi_adjust_cfa_offset(-8) + jmp *%rdi + + L(no_shstk): +- /* Push back the return PC. */ +- pushq %rdi +- cfi_adjust_cfa_offset(8) + #endif + + /* Normal return. */ +-- +2.26.2 + diff --git a/glibc-rh1855790-2.patch b/glibc-rh1855790-2.patch new file mode 100755 index 0000000..4d0aed9 --- /dev/null +++ b/glibc-rh1855790-2.patch @@ -0,0 +1,24 @@ +commit 4031d7484ab3f6327184b5973d91f46978ebe8cf +Author: H.J. Lu +Date: Sat Feb 1 05:44:55 2020 -0800 + + i386/sub_n.S: Add a missing _CET_ENDBR to indirect jump target + + Add a missing _CET_ENDBR to indirect jump targe in sysdeps/i386/sub_n.S. + + Reviewed-by: Adhemerval Zanella +--- + +diff --git a/sysdeps/i386/sub_n.S b/sysdeps/i386/sub_n.S +index ada0cf5..949958a 100644 +--- a/sysdeps/i386/sub_n.S ++++ b/sysdeps/i386/sub_n.S +@@ -91,6 +91,7 @@ L(oop): movl (%esi),%eax + movl 8(%esi),%eax + sbbl 8(%edx),%eax + movl %eax,8(%edi) ++ _CET_ENDBR + movl 12(%esi),%eax + sbbl 12(%edx),%eax + movl %eax,12(%edi) + diff --git a/glibc-rh1855790-3.patch b/glibc-rh1855790-3.patch new file mode 100755 index 0000000..490d67c --- /dev/null +++ b/glibc-rh1855790-3.patch @@ -0,0 +1,33 @@ +commit 825b58f3fb04781e559858510fe83a8c4bf28425 +Author: H.J. Lu +Date: Sat Feb 1 05:44:55 2020 -0800 + + i386-mcount.S: Add _CET_ENDBR to _mcount and __fentry__ + + Since _mcount and __fentry__ don't use ENTRY, we need to add _CET_ENDBR + by hand. + + Reviewed-by: Adhemerval Zanella +--- + +diff --git a/sysdeps/i386/i386-mcount.S b/sysdeps/i386/i386-mcount.S +index 3db2fcd..8c8eeb8 100644 +--- a/sysdeps/i386/i386-mcount.S ++++ b/sysdeps/i386/i386-mcount.S +@@ -30,6 +30,7 @@ + .type C_SYMBOL_NAME(_mcount), @function + .align ALIGNARG(4) + C_LABEL(_mcount) ++ _CET_ENDBR + /* Save the caller-clobbered registers. */ + pushl %eax + pushl %ecx +@@ -58,6 +59,7 @@ weak_alias (_mcount, mcount) + .type C_SYMBOL_NAME(__fentry__), @function + .align ALIGNARG(4) + C_LABEL(__fentry__) ++ _CET_ENDBR + /* Save the caller-clobbered registers. */ + pushl %eax + pushl %ecx + diff --git a/glibc-rh1855790-4.patch b/glibc-rh1855790-4.patch new file mode 100755 index 0000000..cfaea33 --- /dev/null +++ b/glibc-rh1855790-4.patch @@ -0,0 +1,92 @@ +commit 0455f251f494d30db4b52f11b5b0b7f285f775ef +Author: H.J. Lu +Date: Sat Feb 1 05:44:55 2020 -0800 + + i386: Use ENTRY/END in assembly codes + + Use ENTRY and END in assembly codes so that ENDBR32 will be added at + function entries when CET is enabled. + + Reviewed-by: Adhemerval Zanella +--- + +diff --git a/sysdeps/i386/nptl/pthread_spin_lock.S b/sysdeps/i386/nptl/pthread_spin_lock.S +index 1980fec..8aa081b 100644 +--- a/sysdeps/i386/nptl/pthread_spin_lock.S ++++ b/sysdeps/i386/nptl/pthread_spin_lock.S +@@ -15,12 +15,10 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + +- .globl pthread_spin_lock +- .type pthread_spin_lock,@function +- .align 16 +-pthread_spin_lock: ++ENTRY (pthread_spin_lock) + mov 4(%esp), %eax + 1: LOCK + decl 0(%eax) +@@ -34,4 +32,4 @@ pthread_spin_lock: + cmpl $0, 0(%eax) + jg 1b + jmp 2b +- .size pthread_spin_lock,.-pthread_spin_lock ++END (pthread_spin_lock) +diff --git a/sysdeps/i386/nptl/pthread_spin_unlock.S b/sysdeps/i386/nptl/pthread_spin_unlock.S +index 2e71086..2995001 100644 +--- a/sysdeps/i386/nptl/pthread_spin_unlock.S ++++ b/sysdeps/i386/nptl/pthread_spin_unlock.S +@@ -16,15 +16,14 @@ + License along with the GNU C Library; if not, see + . */ + +- .globl pthread_spin_unlock +- .type pthread_spin_unlock,@function +- .align 16 +-pthread_spin_unlock: ++#include ++ ++ENTRY (pthread_spin_unlock) + movl 4(%esp), %eax + movl $1, (%eax) + xorl %eax, %eax + ret +- .size pthread_spin_unlock,.-pthread_spin_unlock ++END (pthread_spin_unlock) + + /* The implementation of pthread_spin_init is identical. */ + .globl pthread_spin_init +diff --git a/sysdeps/i386/pthread_spin_trylock.S b/sysdeps/i386/pthread_spin_trylock.S +index 686dd8c..42cbdb7 100644 +--- a/sysdeps/i386/pthread_spin_trylock.S ++++ b/sysdeps/i386/pthread_spin_trylock.S +@@ -16,6 +16,7 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + + +@@ -25,10 +26,7 @@ + # define LOCK lock + #endif + +- .globl pthread_spin_trylock +- .type pthread_spin_trylock,@function +- .align 16 +-pthread_spin_trylock: ++ENTRY (pthread_spin_trylock) + movl 4(%esp), %edx + movl $1, %eax + xorl %ecx, %ecx +@@ -43,4 +41,4 @@ pthread_spin_trylock: + 0: + #endif + ret +- .size pthread_spin_trylock,.-pthread_spin_trylock ++END (pthread_spin_trylock) + diff --git a/glibc-rh1855790-5.patch b/glibc-rh1855790-5.patch new file mode 100755 index 0000000..908ff46 --- /dev/null +++ b/glibc-rh1855790-5.patch @@ -0,0 +1,63 @@ +commit bbfc0f0f8e30680437d1c5b90563018bcd403881 +Author: H.J. Lu +Date: Sat Feb 1 05:44:56 2020 -0800 + + i386: Remove _exit.S + + The generic implementation is suffice since __NR_exit_group is always + support and i386 does define ABORT_INSTRUCTION. + + Reviewed-by: Adhemerval Zanella +--- + +diff --git a/sysdeps/unix/sysv/linux/i386/_exit.S b/sysdeps/unix/sysv/linux/i386/_exit.S +deleted file mode 100644 +index a10eede..0000000 +--- a/sysdeps/unix/sysv/linux/i386/_exit.S ++++ /dev/null +@@ -1,44 +0,0 @@ +-/* Copyright (C) 2002-2018 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 +- . */ +- +-#include +- +- .text +- .type _exit,@function +- .global _exit +-_exit: +- movl 4(%esp), %ebx +- +- /* Try the new syscall first. */ +-#ifdef __NR_exit_group +- movl $__NR_exit_group, %eax +- ENTER_KERNEL +-#endif +- +- /* Not available. Now the old one. */ +- movl $__NR_exit, %eax +- /* Don't bother using ENTER_KERNEL here. If the exit_group +- syscall is not available AT_SYSINFO isn't either. */ +- int $0x80 +- +- /* This must not fail. Be sure we don't return. */ +- hlt +- .size _exit,.-_exit +- +-libc_hidden_def (_exit) +-rtld_hidden_def (_exit) +-weak_alias (_exit, _Exit) + diff --git a/glibc-rh1855790-6.patch b/glibc-rh1855790-6.patch new file mode 100755 index 0000000..0ecf744 --- /dev/null +++ b/glibc-rh1855790-6.patch @@ -0,0 +1,572 @@ +commit 5d844e1b72513cf59b5e7c14295644efdcc66e44 +Author: H.J. Lu +Date: Fri Feb 14 14:45:34 2020 -0800 + + i386: Enable CET support in ucontext functions + + 1. getcontext and swapcontext are updated to save the caller's shadow + stack pointer and return address. + 2. setcontext and swapcontext are updated to restore shadow stack and + jump to new context directly. + 3. makecontext is updated to allocate a new shadow stack and set the + caller's return address to the helper code, L(exitcode). + 4. Since we no longer save and restore EAX, ECX and EDX in getcontext, + setcontext and swapcontext, we can use them as scratch register slots + to enable CET in ucontext functions. + + Since makecontext allocates a new shadow stack when making a new + context and kernel allocates a new shadow stack for clone/fork/vfork + syscalls, we track the current shadow stack base. In setcontext and + swapcontext, if the target shadow stack base is the same as the current + shadow stack base, we unwind the shadow stack. Otherwise it is a stack + switch and we look for a restore token. + + We enable shadow stack at run-time only if program and all used shared + objects, including dlopened ones, are shadow stack enabled, which means + that they must be compiled with GCC 8 or above and glibc 2.28 or above. + We need to save and restore shadow stack only if shadow stack is enabled. + When caller of getcontext, setcontext, swapcontext and makecontext is + compiled with smaller ucontext_t, shadow stack won't be enabled at + run-time. We check if shadow stack is enabled before accessing the + extended field in ucontext_t. + + Tested on i386 CET/non-CET machines. + + Reviewed-by: Carlos O'Donell +--- + +diff --git a/sysdeps/unix/sysv/linux/i386/getcontext.S b/sysdeps/unix/sysv/linux/i386/getcontext.S +index 6637596..4ed9d03 100644 +--- a/sysdeps/unix/sysv/linux/i386/getcontext.S ++++ b/sysdeps/unix/sysv/linux/i386/getcontext.S +@@ -18,6 +18,7 @@ + . */ + + #include ++#include + + #include "ucontext_i.h" + +@@ -42,6 +43,61 @@ ENTRY(__getcontext) + movw %fs, %dx + movl %edx, oFS(%eax) + ++#if SHSTK_ENABLED ++ /* Check if shadow stack is enabled. */ ++ testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET ++ jz L(no_shstk) ++ ++ /* Save EAX in EDX. */ ++ movl %eax, %edx ++ ++ xorl %eax, %eax ++ cmpl %gs:SSP_BASE_OFFSET, %eax ++ jnz L(shadow_stack_bound_recorded) ++ ++ /* Save EBX in the first scratch register slot. */ ++ movl %ebx, oSCRATCH1(%edx) ++ ++ /* Get the base address and size of the default shadow stack ++ which must be the current shadow stack since nothing has ++ been recorded yet. */ ++ sub $24, %esp ++ mov %esp, %ecx ++ movl $ARCH_CET_STATUS, %ebx ++ movl $__NR_arch_prctl, %eax ++ ENTER_KERNEL ++ testl %eax, %eax ++ jz L(continue_no_err) ++ ++ /* This should never happen. */ ++ hlt ++ ++L(continue_no_err): ++ /* Restore EBX from the first scratch register slot. */ ++ movl oSCRATCH1(%edx), %ebx ++ ++ /* Record the base of the current shadow stack. */ ++ movl 8(%esp), %eax ++ movl %eax, %gs:SSP_BASE_OFFSET ++ add $24, %esp ++ ++L(shadow_stack_bound_recorded): ++ /* Load address of the context data structure. */ ++ movl 4(%esp), %eax ++ ++ /* Get the current shadow stack pointer. */ ++ rdsspd %edx ++ /* NB: Save the caller's shadow stack so that we can jump back ++ to the caller directly. */ ++ addl $4, %edx ++ movl %edx, oSSP(%eax) ++ ++ /* Save the current shadow stack base in ucontext. */ ++ movl %gs:SSP_BASE_OFFSET, %edx ++ movl %edx, (oSSP + 4)(%eax) ++ ++L(no_shstk): ++#endif + /* We have separate floating-point register content memory on the + stack. We use the __fpregs_mem block in the context. Set the + links up correctly. */ +diff --git a/sysdeps/unix/sysv/linux/i386/makecontext.S b/sysdeps/unix/sysv/linux/i386/makecontext.S +index e3ca3dc..2d82ddc 100644 +--- a/sysdeps/unix/sysv/linux/i386/makecontext.S ++++ b/sysdeps/unix/sysv/linux/i386/makecontext.S +@@ -18,6 +18,7 @@ + . */ + + #include ++#include + + #include "ucontext_i.h" + +@@ -68,6 +69,127 @@ ENTRY(__makecontext) + jnz 1b + 2: + ++#if SHSTK_ENABLED ++ /* Check if Shadow Stack is enabled. */ ++ testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET ++ jz L(skip_ssp) ++ ++ /* Reload the pointer to ucontext. */ ++ movl 4(%esp), %eax ++ ++ /* Shadow stack is enabled. We need to allocate a new shadow ++ stack. */ ++ subl oSS_SP(%eax), %edx ++ shrl $STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT, %edx ++ ++ /* Align shadow stack size to 8 bytes. */ ++ addl $7, %edx ++ andl $-8, %edx ++ ++ /* Store shadow stack size in __ssp[2]. */ ++ movl %edx, (oSSP + 8)(%eax) ++ ++ /* Save ESI in the second scratch register slot. */ ++ movl %esi, oSCRATCH2(%eax) ++ /* Save EDI in the third scratch register slot. */ ++ movl %edi, oSCRATCH3(%eax) ++ ++ /* Save the pointer to ucontext. */ ++ movl %eax, %edi ++ ++ /* Get the original shadow stack pointer. */ ++ rdsspd %esi ++ ++ /* Align the saved original shadow stack pointer to the next ++ 8 byte aligned boundary. */ ++ andl $-8, %esi ++ ++ /* Load the top of the new stack into EDX. */ ++ movl oESP(%eax), %edx ++ ++ /* We need to terminate the FDE here because the unwinder looks ++ at ra-1 for unwind information. */ ++ cfi_endproc ++ ++ /* Swap the original stack pointer with the top of the new ++ stack. */ ++ xchgl %esp, %edx ++ ++ /* Add 4 bytes since CALL will push the 4-byte return address ++ onto stack. */ ++ addl $4, %esp ++ ++ /* Allocate the new shadow stack. Save EBX in the first scratch ++ register slot. */ ++ movl %ebx, oSCRATCH1(%eax) ++ ++ /* CET syscall takes 64-bit sizes. */ ++ subl $16, %esp ++ movl (oSSP + 8)(%eax), %ecx ++ movl %ecx, (%esp) ++ movl $0, 4(%esp) ++ movl %ecx, 8(%esp) ++ movl $0, 12(%esp) ++ movl %esp, %ecx ++ ++ movl $ARCH_CET_ALLOC_SHSTK, %ebx ++ movl $__NR_arch_prctl, %eax ++ ENTER_KERNEL ++ testl %eax, %eax ++ jne L(hlt) /* This should never happen. */ ++ ++ /* Copy the base address of the new shadow stack to __ssp[1]. */ ++ movl (%esp), %eax ++ movl %eax, (oSSP + 4)(%edi) ++ ++ addl $16, %esp ++ ++ /* Restore EBX from the first scratch register slot. */ ++ movl oSCRATCH1(%edi), %ebx ++ ++ /* Get the size of the new shadow stack. */ ++ movl (oSSP + 8)(%edi), %ecx ++ ++ /* Use the restore stoken to restore the new shadow stack. */ ++ rstorssp -8(%eax, %ecx) ++ ++ /* Save the restore token at the next 8 byte aligned boundary ++ on the original shadow stack. */ ++ saveprevssp ++ ++ /* Push the address of "jmp exitcode" onto the new stack as ++ well as the new shadow stack. */ ++ call 1f ++ jmp L(exitcode) ++1: ++ ++ /* Get the new shadow stack pointer. */ ++ rdsspd %eax ++ ++ /* Use the restore stoken to restore the original shadow stack. */ ++ rstorssp -8(%esi) ++ ++ /* Save the restore token on the new shadow stack. */ ++ saveprevssp ++ ++ /* Store the new shadow stack pointer in __ssp[0]. */ ++ movl %eax, oSSP(%edi) ++ ++ /* Restore the original stack. */ ++ mov %edx, %esp ++ ++ cfi_startproc ++ ++ /* Restore ESI from the second scratch register slot. */ ++ movl oSCRATCH2(%edi), %esi ++ /* Restore EDI from the third scratch register slot. */ ++ movl oSCRATCH3(%edi), %edi ++ ++ ret ++ ++L(skip_ssp): ++#endif ++ + /* If the function we call returns we must continue with the + context which is given in the uc_link element. To do this + set the return address for the function the user provides +@@ -123,6 +245,7 @@ L(call_exit): + call HIDDEN_JUMPTARGET(exit) + /* The 'exit' call should never return. In case it does cause + the process to terminate. */ ++L(hlt): + hlt + cfi_startproc + END(__makecontext) +diff --git a/sysdeps/unix/sysv/linux/i386/setcontext.S b/sysdeps/unix/sysv/linux/i386/setcontext.S +index 7565d7d..7b58918 100644 +--- a/sysdeps/unix/sysv/linux/i386/setcontext.S ++++ b/sysdeps/unix/sysv/linux/i386/setcontext.S +@@ -18,6 +18,7 @@ + . */ + + #include ++#include + + #include "ucontext_i.h" + +@@ -56,9 +57,6 @@ ENTRY(__setcontext) + movl oFS(%eax), %ecx + movw %cx, %fs + +- /* Fetch the address to return to. */ +- movl oEIP(%eax), %ecx +- + /* Load the new stack pointer. */ + cfi_def_cfa (eax, 0) + cfi_offset (edi, oEDI) +@@ -67,6 +65,103 @@ ENTRY(__setcontext) + cfi_offset (ebx, oEBX) + movl oESP(%eax), %esp + ++#if SHSTK_ENABLED ++ /* Check if Shadow Stack is enabled. */ ++ testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET ++ jz L(no_shstk) ++ ++ /* If the base of the target shadow stack is the same as the ++ base of the current shadow stack, we unwind the shadow ++ stack. Otherwise it is a stack switch and we look for a ++ restore token. */ ++ movl oSSP(%eax), %esi ++ movl %esi, %edi ++ ++ /* Get the base of the target shadow stack. */ ++ movl (oSSP + 4)(%eax), %ecx ++ cmpl %gs:SSP_BASE_OFFSET, %ecx ++ je L(unwind_shadow_stack) ++ ++ /* Align the saved original shadow stack pointer to the next ++ 8 byte aligned boundary. */ ++ andl $-8, %esi ++ ++L(find_restore_token_loop): ++ /* Look for a restore token. */ ++ movl -8(%esi), %ebx ++ andl $-8, %ebx ++ cmpl %esi, %ebx ++ je L(restore_shadow_stack) ++ ++ /* Try the next slot. */ ++ subl $8, %esi ++ jmp L(find_restore_token_loop) ++ ++L(restore_shadow_stack): ++ /* Pop return address from the shadow stack since setcontext ++ will not return. */ ++ movl $1, %ebx ++ incsspd %ebx ++ ++ /* Use the restore stoken to restore the target shadow stack. */ ++ rstorssp -8(%esi) ++ ++ /* Save the restore token on the old shadow stack. NB: This ++ restore token may be checked by setcontext or swapcontext ++ later. */ ++ saveprevssp ++ ++ /* Record the new shadow stack base that was switched to. */ ++ movl (oSSP + 4)(%eax), %ebx ++ movl %ebx, %gs:SSP_BASE_OFFSET ++ ++L(unwind_shadow_stack): ++ rdsspd %ebx ++ subl %edi, %ebx ++ je L(skip_unwind_shadow_stack) ++ negl %ebx ++ shrl $2, %ebx ++ movl $255, %esi ++L(loop): ++ cmpl %esi, %ebx ++ cmovb %ebx, %esi ++ incsspd %esi ++ subl %esi, %ebx ++ ja L(loop) ++ ++L(skip_unwind_shadow_stack): ++ ++ /* Load the values of all the preserved registers (except ESP). */ ++ movl oEDI(%eax), %edi ++ movl oESI(%eax), %esi ++ movl oEBP(%eax), %ebp ++ movl oEBX(%eax), %ebx ++ ++ /* Get the return address set with getcontext. */ ++ movl oEIP(%eax), %ecx ++ ++ /* Check if return address is valid for the case when setcontext ++ is invoked from L(exitcode) with linked context. */ ++ rdsspd %eax ++ cmpl (%eax), %ecx ++ /* Clear EAX to indicate success. NB: Don't use xorl to keep ++ EFLAGS for jne. */ ++ movl $0, %eax ++ jne L(jmp) ++ /* Return to the new context if return address valid. */ ++ pushl %ecx ++ ret ++ ++L(jmp): ++ /* Jump to the new context directly. */ ++ jmp *%ecx ++ ++L(no_shstk): ++#endif ++ ++ /* Fetch the address to return to. */ ++ movl oEIP(%eax), %ecx ++ + /* Push the return address on the new stack so we can return there. */ + pushl %ecx + +diff --git a/sysdeps/unix/sysv/linux/i386/swapcontext.S b/sysdeps/unix/sysv/linux/i386/swapcontext.S +index ce27d51..d1b648c 100644 +--- a/sysdeps/unix/sysv/linux/i386/swapcontext.S ++++ b/sysdeps/unix/sysv/linux/i386/swapcontext.S +@@ -18,6 +18,7 @@ + . */ + + #include ++#include + + #include "ucontext_i.h" + +@@ -76,6 +77,144 @@ ENTRY(__swapcontext) + movl oFS(%eax), %edx + movw %dx, %fs + ++#if SHSTK_ENABLED ++ /* Check if Shadow Stack is enabled. */ ++ testl $X86_FEATURE_1_SHSTK, %gs:FEATURE_1_OFFSET ++ jz L(no_shstk) ++ ++ xorl %eax, %eax ++ cmpl %gs:SSP_BASE_OFFSET, %eax ++ jnz L(shadow_stack_bound_recorded) ++ ++ /* Get the base address and size of the default shadow stack ++ which must be the current shadow stack since nothing has ++ been recorded yet. */ ++ sub $24, %esp ++ mov %esp, %ecx ++ movl $ARCH_CET_STATUS, %ebx ++ movl $__NR_arch_prctl, %eax ++ ENTER_KERNEL ++ testl %eax, %eax ++ jz L(continue_no_err) ++ ++ /* This should never happen. */ ++ hlt ++ ++L(continue_no_err): ++ /* Record the base of the current shadow stack. */ ++ movl 8(%esp), %eax ++ movl %eax, %gs:SSP_BASE_OFFSET ++ add $24, %esp ++ ++L(shadow_stack_bound_recorded): ++ /* Load address of the context data structure we save in. */ ++ movl 4(%esp), %eax ++ ++ /* Load address of the context data structure we swap in */ ++ movl 8(%esp), %edx ++ ++ /* If we unwind the stack, we can't undo stack unwinding. Just ++ save the target shadow stack pointer as the current shadow ++ stack pointer. */ ++ movl oSSP(%edx), %ecx ++ movl %ecx, oSSP(%eax) ++ ++ /* Save the current shadow stack base in ucontext. */ ++ movl %gs:SSP_BASE_OFFSET, %ecx ++ movl %ecx, (oSSP + 4)(%eax) ++ ++ /* If the base of the target shadow stack is the same as the ++ base of the current shadow stack, we unwind the shadow ++ stack. Otherwise it is a stack switch and we look for a ++ restore token. */ ++ movl oSSP(%edx), %esi ++ movl %esi, %edi ++ ++ /* Get the base of the target shadow stack. */ ++ movl (oSSP + 4)(%edx), %ecx ++ cmpl %gs:SSP_BASE_OFFSET, %ecx ++ je L(unwind_shadow_stack) ++ ++ /* Align the saved original shadow stack pointer to the next ++ 8 byte aligned boundary. */ ++ andl $-8, %esi ++ ++L(find_restore_token_loop): ++ /* Look for a restore token. */ ++ movl -8(%esi), %ebx ++ andl $-8, %ebx ++ cmpl %esi, %ebx ++ je L(restore_shadow_stack) ++ ++ /* Try the next slot. */ ++ subl $8, %esi ++ jmp L(find_restore_token_loop) ++ ++L(restore_shadow_stack): ++ /* The target shadow stack will be restored. Save the current ++ shadow stack pointer. */ ++ rdsspd %ecx ++ movl %ecx, oSSP(%eax) ++ ++ /* Use the restore stoken to restore the target shadow stack. */ ++ rstorssp -8(%esi) ++ ++ /* Save the restore token on the old shadow stack. NB: This ++ restore token may be checked by setcontext or swapcontext ++ later. */ ++ saveprevssp ++ ++ /* Record the new shadow stack base that was switched to. */ ++ movl (oSSP + 4)(%edx), %ebx ++ movl %ebx, %gs:SSP_BASE_OFFSET ++ ++L(unwind_shadow_stack): ++ rdsspd %ebx ++ subl %edi, %ebx ++ je L(skip_unwind_shadow_stack) ++ negl %ebx ++ shrl $2, %ebx ++ movl $255, %esi ++L(loop): ++ cmpl %esi, %ebx ++ cmovb %ebx, %esi ++ incsspd %esi ++ subl %esi, %ebx ++ ja L(loop) ++ ++L(skip_unwind_shadow_stack): ++ ++ /* Load the new stack pointer. */ ++ movl oESP(%edx), %esp ++ ++ /* Load the values of all the preserved registers (except ESP). */ ++ movl oEDI(%edx), %edi ++ movl oESI(%edx), %esi ++ movl oEBP(%edx), %ebp ++ movl oEBX(%edx), %ebx ++ ++ /* Get the return address set with getcontext. */ ++ movl oEIP(%edx), %ecx ++ ++ /* Check if return address is valid for the case when setcontext ++ is invoked from L(exitcode) with linked context. */ ++ rdsspd %eax ++ cmpl (%eax), %ecx ++ /* Clear EAX to indicate success. NB: Don't use xorl to keep ++ EFLAGS for jne. */ ++ movl $0, %eax ++ jne L(jmp) ++ /* Return to the new context if return address valid. */ ++ pushl %ecx ++ ret ++ ++L(jmp): ++ /* Jump to the new context directly. */ ++ jmp *%ecx ++ ++L(no_shstk): ++#endif ++ + /* Fetch the address to return to. */ + movl oEIP(%eax), %ecx + +diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h +index 3255cc7..9344ac7 100644 +--- a/sysdeps/unix/sysv/linux/i386/sysdep.h ++++ b/sysdeps/unix/sysv/linux/i386/sysdep.h +@@ -656,4 +656,9 @@ struct libc_do_syscall_args + # endif + #endif + ++/* Each shadow stack slot takes 4 bytes. Assuming that each stack ++ frame takes 128 bytes, this is used to compute shadow stack size ++ from stack size. */ ++#define STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT 5 ++ + #endif /* linux/i386/sysdep.h */ +diff --git a/sysdeps/unix/sysv/linux/i386/ucontext_i.sym b/sysdeps/unix/sysv/linux/i386/ucontext_i.sym +index 1dfe03d..1d8608e 100644 +--- a/sysdeps/unix/sysv/linux/i386/ucontext_i.sym ++++ b/sysdeps/unix/sysv/linux/i386/ucontext_i.sym +@@ -22,6 +22,10 @@ oEBP mreg (EBP) + oESP mreg (ESP) + oEBX mreg (EBX) + oEIP mreg (EIP) ++oSCRATCH1 mreg (EAX) ++oSCRATCH2 mreg (ECX) ++oSCRATCH3 mreg (EDX) + oFPREGS mcontext (fpregs) + oSIGMASK ucontext (uc_sigmask) + oFPREGSMEM ucontext (__fpregs_mem) ++oSSP ucontext (__ssp) + diff --git a/glibc-rh1855790-7.patch b/glibc-rh1855790-7.patch new file mode 100755 index 0000000..990df57 --- /dev/null +++ b/glibc-rh1855790-7.patch @@ -0,0 +1,574 @@ +commit 1fabdb99084df004f7f4cdc7068d1be209a258be +Author: H.J. Lu +Date: Wed Mar 18 04:35:54 2020 -0700 + + x86: Remove ARCH_CET_LEGACY_BITMAP [BZ #25397] + + Since legacy bitmap doesn't cover jitted code generated by legacy JIT + engine, it isn't very useful. This patch removes ARCH_CET_LEGACY_BITMAP + and treats indirect branch tracking similar to shadow stack by removing + legacy bitmap support. + + Tested on CET Linux/x86-64 and non-CET Linux/x86-64. + + Reviewed-by: Carlos O'Donell +--- + +diff --git a/sysdeps/unix/sysv/linux/x86/dl-cet.h b/sysdeps/unix/sysv/linux/x86/dl-cet.h +index 3fbcfeb..47c52e6 100644 +--- a/sysdeps/unix/sysv/linux/x86/dl-cet.h ++++ b/sysdeps/unix/sysv/linux/x86/dl-cet.h +@@ -19,27 +19,6 @@ + #include + + static inline int __attribute__ ((always_inline)) +-dl_cet_allocate_legacy_bitmap (unsigned long *legacy_bitmap) +-{ +- /* Allocate legacy bitmap. */ +- INTERNAL_SYSCALL_DECL (err); +-#ifdef __LP64__ +- return (int) INTERNAL_SYSCALL (arch_prctl, err, 2, +- ARCH_CET_LEGACY_BITMAP, legacy_bitmap); +-#else +- unsigned long long legacy_bitmap_u64[2]; +- int res = INTERNAL_SYSCALL (arch_prctl, err, 2, +- ARCH_CET_LEGACY_BITMAP, legacy_bitmap_u64); +- if (res == 0) +- { +- legacy_bitmap[0] = legacy_bitmap_u64[0]; +- legacy_bitmap[1] = legacy_bitmap_u64[1]; +- } +- return res; +-#endif +-} +- +-static inline int __attribute__ ((always_inline)) + dl_cet_disable_cet (unsigned int cet_feature) + { + INTERNAL_SYSCALL_DECL (err); +diff --git a/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h b/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h +index f67f329..45ad0b0 100644 +--- a/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h ++++ b/sysdeps/unix/sysv/linux/x86/include/asm/prctl.h +@@ -24,9 +24,4 @@ + OUT: allocated shadow stack address: *addr. + */ + # define ARCH_CET_ALLOC_SHSTK 0x3004 +-/* Return legacy region bitmap info in unsigned long long *addr: +- address: addr[0]. +- size: addr[1]. +- */ +-# define ARCH_CET_LEGACY_BITMAP 0x3005 + #endif /* ARCH_CET_STATUS */ +diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile +index 43ad4a7..d9bdf0b 100644 +--- a/sysdeps/x86/Makefile ++++ b/sysdeps/x86/Makefile +@@ -20,7 +20,8 @@ sysdep-dl-routines += dl-cet + + tests += tst-cet-legacy-1 tst-cet-legacy-2 tst-cet-legacy-2a \ + tst-cet-legacy-3 tst-cet-legacy-4 \ +- tst-cet-legacy-5a tst-cet-legacy-6a ++ tst-cet-legacy-5a tst-cet-legacy-6a tst-cet-legacy-7 \ ++ tst-cet-legacy-8 + ifneq (no,$(have-tunables)) + tests += tst-cet-legacy-4a tst-cet-legacy-4b tst-cet-legacy-4c \ + tst-cet-legacy-5b tst-cet-legacy-6b +@@ -42,14 +43,16 @@ CFLAGS-tst-cet-legacy-4b.c += -fcf-protection + CFLAGS-tst-cet-legacy-mod-4.c += -fcf-protection=none + CFLAGS-tst-cet-legacy-5a.c += -fcf-protection + CFLAGS-tst-cet-legacy-5b.c += -fcf-protection +-CFLAGS-tst-cet-legacy-mod-5a.c += -fcf-protection=none ++CFLAGS-tst-cet-legacy-mod-5a.c += -fcf-protection=branch + CFLAGS-tst-cet-legacy-mod-5b.c += -fcf-protection + CFLAGS-tst-cet-legacy-mod-5c.c += -fcf-protection + CFLAGS-tst-cet-legacy-6a.c += -fcf-protection + CFLAGS-tst-cet-legacy-6b.c += -fcf-protection +-CFLAGS-tst-cet-legacy-mod-6a.c += -fcf-protection=none ++CFLAGS-tst-cet-legacy-mod-6a.c += -fcf-protection=branch + CFLAGS-tst-cet-legacy-mod-6b.c += -fcf-protection + CFLAGS-tst-cet-legacy-mod-6c.c += -fcf-protection ++CFLAGS-tst-cet-legacy-7.c += -fcf-protection=none ++CFLAGS-tst-cet-legacy-8.c += -mshstk + + $(objpfx)tst-cet-legacy-1: $(objpfx)tst-cet-legacy-mod-1.so \ + $(objpfx)tst-cet-legacy-mod-2.so +diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c +index b82ba14..627d937 100644 +--- a/sysdeps/x86/dl-cet.c ++++ b/sysdeps/x86/dl-cet.c +@@ -33,63 +33,6 @@ + # error GNU_PROPERTY_X86_FEATURE_1_SHSTK != X86_FEATURE_1_SHSTK + #endif + +-static int +-dl_cet_mark_legacy_region (struct link_map *l) +-{ +- /* Mark PT_LOAD segments with PF_X in legacy code page bitmap. */ +- size_t i, phnum = l->l_phnum; +- const ElfW(Phdr) *phdr = l->l_phdr; +-#ifdef __x86_64__ +- typedef unsigned long long word_t; +-#else +- typedef unsigned long word_t; +-#endif +- unsigned int bits_to_set; +- word_t mask_to_set; +-#define BITS_PER_WORD (sizeof (word_t) * 8) +-#define BITMAP_FIRST_WORD_MASK(start) \ +- (~((word_t) 0) << ((start) & (BITS_PER_WORD - 1))) +-#define BITMAP_LAST_WORD_MASK(nbits) \ +- (~((word_t) 0) >> (-(nbits) & (BITS_PER_WORD - 1))) +- +- word_t *bitmap = (word_t *) GL(dl_x86_legacy_bitmap)[0]; +- word_t bitmap_size = GL(dl_x86_legacy_bitmap)[1]; +- word_t *p; +- size_t page_size = GLRO(dl_pagesize); +- +- for (i = 0; i < phnum; i++) +- if (phdr[i].p_type == PT_LOAD && (phdr[i].p_flags & PF_X)) +- { +- /* One bit in legacy bitmap represents a page. */ +- ElfW(Addr) start = (phdr[i].p_vaddr + l->l_addr) / page_size; +- ElfW(Addr) len = (phdr[i].p_memsz + page_size - 1) / page_size; +- ElfW(Addr) end = start + len; +- +- if ((end / 8) > bitmap_size) +- return -EINVAL; +- +- p = bitmap + (start / BITS_PER_WORD); +- bits_to_set = BITS_PER_WORD - (start % BITS_PER_WORD); +- mask_to_set = BITMAP_FIRST_WORD_MASK (start); +- +- while (len >= bits_to_set) +- { +- *p |= mask_to_set; +- len -= bits_to_set; +- bits_to_set = BITS_PER_WORD; +- mask_to_set = ~((word_t) 0); +- p++; +- } +- if (len) +- { +- mask_to_set &= BITMAP_LAST_WORD_MASK (end); +- *p |= mask_to_set; +- } +- } +- +- return 0; +-} +- + /* Check if object M is compatible with CET. */ + + static void +@@ -117,6 +60,8 @@ dl_cet_check (struct link_map *m, const char *program) + if (ibt_enabled || shstk_enabled) + { + struct link_map *l = NULL; ++ unsigned int ibt_legacy = 0, shstk_legacy = 0; ++ bool found_ibt_legacy = false, found_shstk_legacy = false; + + /* Check if IBT and SHSTK are enabled in object. */ + bool enable_ibt = (ibt_enabled +@@ -142,10 +87,7 @@ dl_cet_check (struct link_map *m, const char *program) + support IBT nor SHSTK. */ + if (enable_ibt || enable_shstk) + { +- int res; + unsigned int i; +- unsigned int first_legacy, last_legacy; +- bool need_legacy_bitmap = false; + + i = m->l_searchlist.r_nlist; + while (i-- > 0) +@@ -167,91 +109,25 @@ dl_cet_check (struct link_map *m, const char *program) + continue; + #endif + +- if (enable_ibt +- && enable_ibt_type != CET_ALWAYS_ON +- && !(l->l_cet & lc_ibt)) ++ /* IBT is enabled only if it is enabled in executable as ++ well as all shared objects. */ ++ enable_ibt &= (enable_ibt_type == CET_ALWAYS_ON ++ || (l->l_cet & lc_ibt) != 0); ++ if (!found_ibt_legacy && enable_ibt != ibt_enabled) + { +- /* Remember the first and last legacy objects. */ +- if (!need_legacy_bitmap) +- last_legacy = i; +- first_legacy = i; +- need_legacy_bitmap = true; ++ found_ibt_legacy = true; ++ ibt_legacy = i; + } + + /* SHSTK is enabled only if it is enabled in executable as + well as all shared objects. */ + enable_shstk &= (enable_shstk_type == CET_ALWAYS_ON + || (l->l_cet & lc_shstk) != 0); +- } +- +- if (need_legacy_bitmap) +- { +- if (GL(dl_x86_legacy_bitmap)[0]) +- { +- /* Change legacy bitmap to writable. */ +- if (__mprotect ((void *) GL(dl_x86_legacy_bitmap)[0], +- GL(dl_x86_legacy_bitmap)[1], +- PROT_READ | PROT_WRITE) < 0) +- { +-mprotect_failure: +- if (program) +- _dl_fatal_printf ("%s: mprotect legacy bitmap failed\n", +- l->l_name); +- else +- _dl_signal_error (EINVAL, l->l_name, "dlopen", +- N_("mprotect legacy bitmap failed")); +- } +- } +- else ++ if (enable_shstk != shstk_enabled) + { +- /* Allocate legacy bitmap. */ +- int res = dl_cet_allocate_legacy_bitmap +- (GL(dl_x86_legacy_bitmap)); +- if (res != 0) +- { +- if (program) +- _dl_fatal_printf ("%s: legacy bitmap isn't available\n", +- l->l_name); +- else +- _dl_signal_error (EINVAL, l->l_name, "dlopen", +- N_("legacy bitmap isn't available")); +- } ++ found_shstk_legacy = true; ++ shstk_legacy = i; + } +- +- /* Put legacy shared objects in legacy bitmap. */ +- for (i = first_legacy; i <= last_legacy; i++) +- { +- l = m->l_initfini[i]; +- +- if (l->l_init_called || (l->l_cet & lc_ibt)) +- continue; +- +-#ifdef SHARED +- if (l == &GL(dl_rtld_map) +- || l->l_real == &GL(dl_rtld_map) +- || (program && l == m)) +- continue; +-#endif +- +- /* If IBT is enabled in executable and IBT isn't enabled +- in this shard object, mark PT_LOAD segments with PF_X +- in legacy code page bitmap. */ +- res = dl_cet_mark_legacy_region (l); +- if (res != 0) +- { +- if (program) +- _dl_fatal_printf ("%s: failed to mark legacy code region\n", +- l->l_name); +- else +- _dl_signal_error (-res, l->l_name, "dlopen", +- N_("failed to mark legacy code region")); +- } +- } +- +- /* Change legacy bitmap to read-only. */ +- if (__mprotect ((void *) GL(dl_x86_legacy_bitmap)[0], +- GL(dl_x86_legacy_bitmap)[1], PROT_READ) < 0) +- goto mprotect_failure; + } + } + +@@ -259,23 +135,40 @@ mprotect_failure: + + if (enable_ibt != ibt_enabled || enable_shstk != shstk_enabled) + { +- if (!program +- && enable_shstk_type != CET_PERMISSIVE) ++ if (!program) + { +- /* When SHSTK is enabled, we can't dlopening a shared +- object without SHSTK. */ +- if (enable_shstk != shstk_enabled) +- _dl_signal_error (EINVAL, l->l_name, "dlopen", +- N_("shadow stack isn't enabled")); +- return; ++ if (enable_ibt_type != CET_PERMISSIVE) ++ { ++ /* When IBT is enabled, we cannot dlopen a shared ++ object without IBT. */ ++ if (found_ibt_legacy) ++ _dl_signal_error (0, ++ m->l_initfini[ibt_legacy]->l_name, ++ "dlopen", ++ N_("rebuild shared object with IBT support enabled")); ++ } ++ ++ if (enable_shstk_type != CET_PERMISSIVE) ++ { ++ /* When SHSTK is enabled, we cannot dlopen a shared ++ object without SHSTK. */ ++ if (found_shstk_legacy) ++ _dl_signal_error (0, ++ m->l_initfini[shstk_legacy]->l_name, ++ "dlopen", ++ N_("rebuild shared object with SHSTK support enabled")); ++ } ++ ++ if (enable_ibt_type != CET_PERMISSIVE ++ && enable_shstk_type != CET_PERMISSIVE) ++ return; + } + + /* Disable IBT and/or SHSTK if they are enabled by kernel, but + disabled in executable or shared objects. */ + unsigned int cet_feature = 0; + +- /* Disable IBT only during program startup. */ +- if (program && !enable_ibt) ++ if (!enable_ibt) + cet_feature |= GNU_PROPERTY_X86_FEATURE_1_IBT; + if (!enable_shstk) + cet_feature |= GNU_PROPERTY_X86_FEATURE_1_SHSTK; +@@ -286,8 +179,14 @@ mprotect_failure: + if (program) + _dl_fatal_printf ("%s: can't disable CET\n", program); + else +- _dl_signal_error (-res, l->l_name, "dlopen", +- N_("can't disable CET")); ++ { ++ if (found_ibt_legacy) ++ l = m->l_initfini[ibt_legacy]; ++ else ++ l = m->l_initfini[shstk_legacy]; ++ _dl_signal_error (-res, l->l_name, "dlopen", ++ N_("can't disable CET")); ++ } + } + + /* Clear the disabled bits in dl_x86_feature_1. */ +@@ -297,17 +196,21 @@ mprotect_failure: + } + + #ifdef SHARED +- if (program +- && (!shstk_enabled +- || enable_shstk_type != CET_PERMISSIVE) +- && (ibt_enabled || shstk_enabled)) ++ if (program && (ibt_enabled || shstk_enabled)) + { +- /* Lock CET if IBT or SHSTK is enabled in executable. Don't +- lock CET if SHSTK is enabled permissively. */ +- int res = dl_cet_lock_cet (); +- if (res != 0) +- _dl_fatal_printf ("%s: can't lock CET\n", program); ++ if ((!ibt_enabled ++ || enable_ibt_type != CET_PERMISSIVE) ++ && (!shstk_enabled ++ || enable_shstk_type != CET_PERMISSIVE)) ++ { ++ /* Lock CET if IBT or SHSTK is enabled in executable unless ++ IBT or SHSTK is enabled permissively. */ ++ int res = dl_cet_lock_cet (); ++ if (res != 0) ++ _dl_fatal_printf ("%s: can't lock CET\n", program); ++ } + ++ /* Set feature_1 if IBT or SHSTK is enabled in executable. */ + cet_feature_changed = true; + } + #endif +diff --git a/sysdeps/x86/dl-procruntime.c b/sysdeps/x86/dl-procruntime.c +index eddbde6..920bfe8 100644 +--- a/sysdeps/x86/dl-procruntime.c ++++ b/sysdeps/x86/dl-procruntime.c +@@ -54,15 +54,4 @@ PROCINFO_CLASS unsigned int _dl_x86_feature_1[2] + # else + , + # endif +- +-# if !defined PROCINFO_DECL && defined SHARED +- ._dl_x86_legacy_bitmap +-# else +-PROCINFO_CLASS unsigned long _dl_x86_legacy_bitmap[2] +-# endif +-# if !defined SHARED || defined PROCINFO_DECL +-; +-# else +-, +-# endif + #endif +diff --git a/sysdeps/x86/tst-cet-legacy-4.c b/sysdeps/x86/tst-cet-legacy-4.c +index 3ead63d..f0ba326 100644 +--- a/sysdeps/x86/tst-cet-legacy-4.c ++++ b/sysdeps/x86/tst-cet-legacy-4.c +@@ -20,6 +20,9 @@ + #include + #include + #include ++#include ++ ++#include + + static int + do_test (void) +@@ -31,22 +34,18 @@ do_test (void) + h = dlopen (modname, RTLD_LAZY); + if (h == NULL) + { +- printf ("cannot open '%s': %s\n", modname, dlerror ()); +- exit (1); ++ const char *err = dlerror (); ++ if (!strstr (err, "rebuild shared object with IBT support enabled")) ++ FAIL_EXIT1 ("incorrect dlopen '%s' error: %s\n", modname, err); ++ return 0; + } + + fp = dlsym (h, "test"); + if (fp == NULL) +- { +- printf ("cannot get symbol 'test': %s\n", dlerror ()); +- exit (1); +- } ++ FAIL_EXIT1 ("cannot get symbol 'test': %s\n", dlerror ()); + + if (fp () != 0) +- { +- puts ("test () != 0"); +- exit (1); +- } ++ FAIL_EXIT1 ("test () != 0"); + + dlclose (h); + +diff --git a/sysdeps/x86/tst-cet-legacy-5.c b/sysdeps/x86/tst-cet-legacy-5.c +index fbf640f..e1ca09d 100644 +--- a/sysdeps/x86/tst-cet-legacy-5.c ++++ b/sysdeps/x86/tst-cet-legacy-5.c +@@ -35,7 +35,8 @@ do_test_1 (const char *modname, bool fail) + if (fail) + { + const char *err = dlerror (); +- if (strstr (err, "shadow stack isn't enabled") == NULL) ++ if (strstr (err, "rebuild shared object with SHSTK support enabled") ++ == NULL) + { + printf ("incorrect dlopen '%s' error: %s\n", modname, + dlerror ()); +diff --git a/sysdeps/x86/tst-cet-legacy-6.c b/sysdeps/x86/tst-cet-legacy-6.c +index 9151225..184a35b 100644 +--- a/sysdeps/x86/tst-cet-legacy-6.c ++++ b/sysdeps/x86/tst-cet-legacy-6.c +@@ -35,7 +35,8 @@ do_test_1 (const char *modname, bool fail) + if (fail) + { + const char *err = dlerror (); +- if (strstr (err, "shadow stack isn't enabled") == NULL) ++ if (strstr (err, "rebuild shared object with SHSTK support enabled") ++ == NULL) + { + printf ("incorrect dlopen '%s' error: %s\n", modname, + dlerror ()); +diff --git a/sysdeps/x86/tst-cet-legacy-7.c b/sysdeps/x86/tst-cet-legacy-7.c +new file mode 100644 +index 0000000..58bcb29 +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-7.c +@@ -0,0 +1,38 @@ ++/* Check compatibility of legacy executable with a JIT engine. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++/* Check that mmapped legacy code works with -fcf-protection=none. */ ++ ++static int ++do_test (void) ++{ ++ void (*funcp) (void); ++ funcp = xmmap (NULL, 0x1000, PROT_EXEC | PROT_READ | PROT_WRITE, ++ MAP_ANONYMOUS | MAP_PRIVATE, -1); ++ printf ("mmap = %p\n", funcp); ++ /* Write RET instruction. */ ++ *(char *) funcp = 0xc3; ++ funcp (); ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/x86/tst-cet-legacy-8.c b/sysdeps/x86/tst-cet-legacy-8.c +new file mode 100644 +index 0000000..11e8115 +--- /dev/null ++++ b/sysdeps/x86/tst-cet-legacy-8.c +@@ -0,0 +1,48 @@ ++/* Check incompatibility with legacy JIT engine. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Check that mmapped legacy code trigges segfault with -fcf-protection. */ ++ ++static int ++do_test (void) ++{ ++ /* NB: This test should trigger SIGSEGV on CET platforms. If SHSTK ++ is disabled, assuming IBT is also disabled. */ ++ if (_get_ssp () == 0) ++ return EXIT_UNSUPPORTED; ++ ++ void (*funcp) (void); ++ funcp = xmmap (NULL, 0x1000, PROT_EXEC | PROT_READ | PROT_WRITE, ++ MAP_ANONYMOUS | MAP_PRIVATE, -1); ++ printf ("mmap = %p\n", funcp); ++ /* Write RET instruction. */ ++ *(char *) funcp = 0xc3; ++ funcp (); ++ return EXIT_FAILURE; ++} ++ ++#define EXPECTED_SIGNAL (_get_ssp () == 0 ? 0 : SIGSEGV) ++#include + diff --git a/glibc-rh1855790-8.patch b/glibc-rh1855790-8.patch new file mode 100755 index 0000000..47c212d --- /dev/null +++ b/glibc-rh1855790-8.patch @@ -0,0 +1,420 @@ +commit 674ea88294bfb8d89878a0ebbbcec38a85e118a5 +Author: H.J. Lu +Date: Tue Apr 28 10:05:25 2020 -0700 + + x86: Move CET control to _dl_x86_feature_control [BZ #25887] + + 1. Include to get architecture specific initializer in + rtld_global. + 2. Change _dl_x86_feature_1[2] to _dl_x86_feature_1. + 3. Add _dl_x86_feature_control after _dl_x86_feature_1, which is a + struct of 2 bitfields for IBT and SHSTK control + + This fixes [BZ #25887]. +--- + +diff --git a/elf/rtld.c b/elf/rtld.c +index e107bd1..7f030f7 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -230,6 +230,8 @@ rtld_hidden_def (_dl_starting_up) + (except those which cannot be added for some reason). */ + struct rtld_global _rtld_global = + { ++ /* Get architecture specific initializer. */ ++#include + /* Generally the default presumption without further information is an + * executable stack but this is not true for all platforms. */ + ._dl_stack_flags = DEFAULT_STACK_PERMS, +diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h +index f6cfb90..8c959e3 100644 +--- a/sysdeps/i386/dl-machine.h ++++ b/sysdeps/i386/dl-machine.h +@@ -71,7 +71,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) + extern void _dl_runtime_profile_shstk (Elf32_Word) attribute_hidden; + /* Check if SHSTK is enabled by kernel. */ + bool shstk_enabled +- = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0; ++ = (GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0; + + if (l->l_info[DT_JMPREL] && lazy) + { +diff --git a/sysdeps/unix/sysv/linux/x86/cpu-features.c b/sysdeps/unix/sysv/linux/x86/cpu-features.c +index 8566a26..9f40624 100644 +--- a/sysdeps/unix/sysv/linux/x86/cpu-features.c ++++ b/sysdeps/unix/sysv/linux/x86/cpu-features.c +@@ -36,7 +36,7 @@ static inline void + x86_setup_tls (void) + { + __libc_setup_tls (); +- THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1)[0]); ++ THREAD_SETMEM (THREAD_SELF, header.feature_1, GL(dl_x86_feature_1)); + } + + # define ARCH_SETUP_TLS() x86_setup_tls () +diff --git a/sysdeps/x86/cet-control.h b/sysdeps/x86/cet-control.h +new file mode 100644 +index 0000000..7b29f95 +--- /dev/null ++++ b/sysdeps/x86/cet-control.h +@@ -0,0 +1,41 @@ ++/* x86 CET tuning. ++ This file is part of the GNU C Library. ++ Copyright (C) 2018 Free Software Foundation, Inc. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _CET_CONTROL_H ++#define _CET_CONTROL_H ++ ++/* For each CET feature, IBT and SHSTK, valid control values. */ ++enum dl_x86_cet_control ++{ ++ /* Enable CET features based on ELF property note. */ ++ cet_elf_property = 0, ++ /* Always enable CET features. */ ++ cet_always_on, ++ /* Always disable CET features. */ ++ cet_always_off, ++ /* Enable CET features permissively. */ ++ cet_permissive ++}; ++ ++struct dl_x86_feature_control ++{ ++ enum dl_x86_cet_control ibt : 2; ++ enum dl_x86_cet_control shstk : 2; ++}; ++ ++#endif /* cet-control.h */ +diff --git a/sysdeps/x86/cet-tunables.h b/sysdeps/x86/cet-tunables.h +deleted file mode 100644 +index ca02305..0000000 +--- a/sysdeps/x86/cet-tunables.h ++++ /dev/null +@@ -1,29 +0,0 @@ +-/* x86 CET tuning. +- This file is part of the GNU C Library. +- Copyright (C) 2018 Free Software Foundation, Inc. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-/* Valid control values: +- 0: Enable CET features based on ELF property note. +- 1: Always disable CET features. +- 2: Always enable CET features. +- 3: Enable CET features permissively. +- */ +-#define CET_ELF_PROPERTY 0 +-#define CET_ALWAYS_OFF 1 +-#define CET_ALWAYS_ON 2 +-#define CET_PERMISSIVE 3 +-#define CET_MAX CET_PERMISSIVE +diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c +index 4695ac8..ac74f40 100644 +--- a/sysdeps/x86/cpu-features.c ++++ b/sysdeps/x86/cpu-features.c +@@ -39,7 +39,6 @@ extern void TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *) + + #if CET_ENABLED + # include +-# include + #endif + + static void +@@ -490,7 +489,7 @@ no_cpuid: + + if (cet_status) + { +- GL(dl_x86_feature_1)[0] = cet_status; ++ GL(dl_x86_feature_1) = cet_status; + + # ifndef SHARED + /* Check if IBT and SHSTK are enabled by kernel. */ +@@ -514,14 +513,13 @@ no_cpuid: + + /* Clear the disabled bits in dl_x86_feature_1. */ + if (res == 0) +- GL(dl_x86_feature_1)[0] &= ~cet_feature; ++ GL(dl_x86_feature_1) &= ~cet_feature; + } + + /* Lock CET if IBT or SHSTK is enabled in executable. Don't +- lock CET if SHSTK is enabled permissively. */ +- if (((GL(dl_x86_feature_1)[1] >> CET_MAX) +- & ((1 << CET_MAX) - 1)) +- != CET_PERMISSIVE) ++ lock CET if IBT or SHSTK is enabled permissively. */ ++ if (GL(dl_x86_feature_control).ibt != cet_permissive ++ && GL(dl_x86_feature_control).shstk != cet_permissive) + dl_cet_lock_cet (); + } + # endif +diff --git a/sysdeps/x86/cpu-tunables.c b/sysdeps/x86/cpu-tunables.c +index 69155a8..fad6726 100644 +--- a/sysdeps/x86/cpu-tunables.c ++++ b/sysdeps/x86/cpu-tunables.c +@@ -336,28 +336,18 @@ TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp) + } + + # if CET_ENABLED +-# include + + attribute_hidden + void + TUNABLE_CALLBACK (set_x86_ibt) (tunable_val_t *valp) + { + if (DEFAULT_MEMCMP (valp->strval, "on", sizeof ("on")) == 0) +- { +- GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1); +- GL(dl_x86_feature_1)[1] |= CET_ALWAYS_ON; +- } ++ GL(dl_x86_feature_control).ibt = cet_always_on; + else if (DEFAULT_MEMCMP (valp->strval, "off", sizeof ("off")) == 0) +- { +- GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1); +- GL(dl_x86_feature_1)[1] |= CET_ALWAYS_OFF; +- } ++ GL(dl_x86_feature_control).ibt = cet_always_off; + else if (DEFAULT_MEMCMP (valp->strval, "permissive", + sizeof ("permissive")) == 0) +- { +- GL(dl_x86_feature_1)[1] &= ~((1 << CET_MAX) - 1); +- GL(dl_x86_feature_1)[1] |= CET_PERMISSIVE; +- } ++ GL(dl_x86_feature_control).ibt = cet_permissive; + } + + attribute_hidden +@@ -365,21 +355,12 @@ void + TUNABLE_CALLBACK (set_x86_shstk) (tunable_val_t *valp) + { + if (DEFAULT_MEMCMP (valp->strval, "on", sizeof ("on")) == 0) +- { +- GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX); +- GL(dl_x86_feature_1)[1] |= (CET_ALWAYS_ON << CET_MAX); +- } ++ GL(dl_x86_feature_control).shstk = cet_always_on; + else if (DEFAULT_MEMCMP (valp->strval, "off", sizeof ("off")) == 0) +- { +- GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX); +- GL(dl_x86_feature_1)[1] |= (CET_ALWAYS_OFF << CET_MAX); +- } ++ GL(dl_x86_feature_control).shstk = cet_always_off; + else if (DEFAULT_MEMCMP (valp->strval, "permissive", + sizeof ("permissive")) == 0) +- { +- GL(dl_x86_feature_1)[1] &= ~(((1 << CET_MAX) - 1) << CET_MAX); +- GL(dl_x86_feature_1)[1] |= (CET_PERMISSIVE << CET_MAX); +- } ++ GL(dl_x86_feature_control).shstk = cet_permissive; + } + # endif + #endif +diff --git a/sysdeps/x86/dl-cet.c b/sysdeps/x86/dl-cet.c +index 627d937..ebc0d57 100644 +--- a/sysdeps/x86/dl-cet.c ++++ b/sysdeps/x86/dl-cet.c +@@ -20,7 +20,6 @@ + #include + #include + #include +-#include + + /* GNU_PROPERTY_X86_FEATURE_1_IBT and GNU_PROPERTY_X86_FEATURE_1_SHSTK + are defined in , which are only available for C sources. +@@ -39,23 +38,23 @@ static void + dl_cet_check (struct link_map *m, const char *program) + { + /* Check how IBT should be enabled. */ +- unsigned int enable_ibt_type +- = GL(dl_x86_feature_1)[1] & ((1 << CET_MAX) - 1); ++ enum dl_x86_cet_control enable_ibt_type ++ = GL(dl_x86_feature_control).ibt; + /* Check how SHSTK should be enabled. */ +- unsigned int enable_shstk_type +- = ((GL(dl_x86_feature_1)[1] >> CET_MAX) & ((1 << CET_MAX) - 1)); ++ enum dl_x86_cet_control enable_shstk_type ++ = GL(dl_x86_feature_control).shstk; + + /* No legacy object check if both IBT and SHSTK are always on. */ +- if (enable_ibt_type == CET_ALWAYS_ON +- && enable_shstk_type == CET_ALWAYS_ON) ++ if (enable_ibt_type == cet_always_on ++ && enable_shstk_type == cet_always_on) + return; + + /* Check if IBT is enabled by kernel. */ + bool ibt_enabled +- = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0; ++ = (GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_IBT) != 0; + /* Check if SHSTK is enabled by kernel. */ + bool shstk_enabled +- = (GL(dl_x86_feature_1)[0] & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0; ++ = (GL(dl_x86_feature_1) & GNU_PROPERTY_X86_FEATURE_1_SHSTK) != 0; + + if (ibt_enabled || shstk_enabled) + { +@@ -65,9 +64,9 @@ dl_cet_check (struct link_map *m, const char *program) + + /* Check if IBT and SHSTK are enabled in object. */ + bool enable_ibt = (ibt_enabled +- && enable_ibt_type != CET_ALWAYS_OFF); ++ && enable_ibt_type != cet_always_off); + bool enable_shstk = (shstk_enabled +- && enable_shstk_type != CET_ALWAYS_OFF); ++ && enable_shstk_type != cet_always_off); + if (program) + { + /* Enable IBT and SHSTK only if they are enabled in executable. +@@ -76,10 +75,10 @@ dl_cet_check (struct link_map *m, const char *program) + GLIBC_TUNABLES=glibc.tune.hwcaps=-IBT,-SHSTK + */ + enable_ibt &= (HAS_CPU_FEATURE (IBT) +- && (enable_ibt_type == CET_ALWAYS_ON ++ && (enable_ibt_type == cet_always_on + || (m->l_cet & lc_ibt) != 0)); + enable_shstk &= (HAS_CPU_FEATURE (SHSTK) +- && (enable_shstk_type == CET_ALWAYS_ON ++ && (enable_shstk_type == cet_always_on + || (m->l_cet & lc_shstk) != 0)); + } + +@@ -111,7 +110,7 @@ dl_cet_check (struct link_map *m, const char *program) + + /* IBT is enabled only if it is enabled in executable as + well as all shared objects. */ +- enable_ibt &= (enable_ibt_type == CET_ALWAYS_ON ++ enable_ibt &= (enable_ibt_type == cet_always_on + || (l->l_cet & lc_ibt) != 0); + if (!found_ibt_legacy && enable_ibt != ibt_enabled) + { +@@ -121,7 +120,7 @@ dl_cet_check (struct link_map *m, const char *program) + + /* SHSTK is enabled only if it is enabled in executable as + well as all shared objects. */ +- enable_shstk &= (enable_shstk_type == CET_ALWAYS_ON ++ enable_shstk &= (enable_shstk_type == cet_always_on + || (l->l_cet & lc_shstk) != 0); + if (enable_shstk != shstk_enabled) + { +@@ -137,7 +136,7 @@ dl_cet_check (struct link_map *m, const char *program) + { + if (!program) + { +- if (enable_ibt_type != CET_PERMISSIVE) ++ if (enable_ibt_type != cet_permissive) + { + /* When IBT is enabled, we cannot dlopen a shared + object without IBT. */ +@@ -148,7 +147,7 @@ dl_cet_check (struct link_map *m, const char *program) + N_("rebuild shared object with IBT support enabled")); + } + +- if (enable_shstk_type != CET_PERMISSIVE) ++ if (enable_shstk_type != cet_permissive) + { + /* When SHSTK is enabled, we cannot dlopen a shared + object without SHSTK. */ +@@ -159,8 +158,8 @@ dl_cet_check (struct link_map *m, const char *program) + N_("rebuild shared object with SHSTK support enabled")); + } + +- if (enable_ibt_type != CET_PERMISSIVE +- && enable_shstk_type != CET_PERMISSIVE) ++ if (enable_ibt_type != cet_permissive ++ && enable_shstk_type != cet_permissive) + return; + } + +@@ -190,7 +189,7 @@ dl_cet_check (struct link_map *m, const char *program) + } + + /* Clear the disabled bits in dl_x86_feature_1. */ +- GL(dl_x86_feature_1)[0] &= ~cet_feature; ++ GL(dl_x86_feature_1) &= ~cet_feature; + + cet_feature_changed = true; + } +@@ -199,9 +198,9 @@ dl_cet_check (struct link_map *m, const char *program) + if (program && (ibt_enabled || shstk_enabled)) + { + if ((!ibt_enabled +- || enable_ibt_type != CET_PERMISSIVE) ++ || enable_ibt_type != cet_permissive) + && (!shstk_enabled +- || enable_shstk_type != CET_PERMISSIVE)) ++ || enable_shstk_type != cet_permissive)) + { + /* Lock CET if IBT or SHSTK is enabled in executable unless + IBT or SHSTK is enabled permissively. */ +diff --git a/sysdeps/x86/dl-procruntime.c b/sysdeps/x86/dl-procruntime.c +index 920bfe8..26b2b39 100644 +--- a/sysdeps/x86/dl-procruntime.c ++++ b/sysdeps/x86/dl-procruntime.c +@@ -47,7 +47,27 @@ + # if !defined PROCINFO_DECL && defined SHARED + ._dl_x86_feature_1 + # else +-PROCINFO_CLASS unsigned int _dl_x86_feature_1[2] ++PROCINFO_CLASS unsigned int _dl_x86_feature_1 ++# endif ++# ifndef PROCINFO_DECL ++= 0 ++# endif ++# if !defined SHARED || defined PROCINFO_DECL ++; ++# else ++, ++# endif ++ ++# if !defined PROCINFO_DECL && defined SHARED ++ ._dl_x86_feature_control ++# else ++PROCINFO_CLASS struct dl_x86_feature_control _dl_x86_feature_control ++# endif ++# ifndef PROCINFO_DECL ++= { ++ .ibt = cet_elf_property, ++ .shstk = cet_elf_property ++ } + # endif + # if !defined SHARED || defined PROCINFO_DECL + ; +diff --git a/sysdeps/x86/ldsodefs.h b/sysdeps/x86/ldsodefs.h +index 0616215..54f6864 100644 +--- a/sysdeps/x86/ldsodefs.h ++++ b/sysdeps/x86/ldsodefs.h +@@ -61,6 +61,7 @@ struct La_x32_retval; + struct La_x86_64_retval *, \ + const char *) + ++#include + #include_next + + #endif + diff --git a/glibc-rh1855790-9.patch b/glibc-rh1855790-9.patch new file mode 100755 index 0000000..a4e0e49 --- /dev/null +++ b/glibc-rh1855790-9.patch @@ -0,0 +1,42 @@ +commit 635d6fae03257129b4672591b700a495cb6cb6c7 +Author: H.J. Lu +Date: Sat Feb 1 05:43:34 2020 -0800 + + x86: Don't make 2 calls to dlerror () in a row + + We shouldn't make 2 calls to dlerror () in a row since the first call + will clear the error. We should just use the return value from the + first call. + + Tested on Linux/x86-64. + + Reviewed-by: Florian Weimer +--- + +diff --git a/sysdeps/x86/tst-cet-legacy-5.c b/sysdeps/x86/tst-cet-legacy-5.c +index e1ca09d..0a34d37 100644 +--- a/sysdeps/x86/tst-cet-legacy-5.c ++++ b/sysdeps/x86/tst-cet-legacy-5.c +@@ -39,7 +39,7 @@ do_test_1 (const char *modname, bool fail) + == NULL) + { + printf ("incorrect dlopen '%s' error: %s\n", modname, +- dlerror ()); ++ err); + exit (1); + } + +diff --git a/sysdeps/x86/tst-cet-legacy-6.c b/sysdeps/x86/tst-cet-legacy-6.c +index 184a35b..bd45218 100644 +--- a/sysdeps/x86/tst-cet-legacy-6.c ++++ b/sysdeps/x86/tst-cet-legacy-6.c +@@ -39,7 +39,7 @@ do_test_1 (const char *modname, bool fail) + == NULL) + { + printf ("incorrect dlopen '%s' error: %s\n", modname, +- dlerror ()); ++ err); + exit (1); + } + + diff --git a/glibc-rh1856398.patch b/glibc-rh1856398.patch new file mode 100755 index 0000000..8eebe0b --- /dev/null +++ b/glibc-rh1856398.patch @@ -0,0 +1,25 @@ +commit 16536e98e36e08bc1ce1edbd8dd50c7c3bb7a936 +Author: Florian Weimer +Date: Tue May 12 11:30:30 2020 +0200 + + aarch64: Accept PLT calls to __getauxval within libc.so + + When using outline atomics (-moutline-atomics, the default for ARMv8-A + starting with GCC 10), libgcc contains an ELF constructor which calls + __getauxval. This code is built outside of glibc, so none of its + internal PLT avoidance schemes can be applied to it. This change + suppresses the elf/check-localplt failure. + +diff -rup a/sysdeps/unix/sysv/linux/aarch64/localplt.data b/sysdeps/unix/sysv/linux/aarch64/localplt.data +--- a/sysdeps/unix/sysv/linux/aarch64/localplt.data 2018-08-01 01:10:47.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/aarch64/localplt.data 2020-10-27 15:55:53.457002541 -0400 +@@ -7,6 +7,9 @@ libc.so: malloc + libc.so: memalign + libc.so: realloc + libm.so: matherr ++# If outline atomics are used, libgcc (built outside of glibc) may ++# call __getauxval using the PLT. ++libc.so: __getauxval ? + # The dynamic loader needs __tls_get_addr for TLS. + ld.so: __tls_get_addr + # The main malloc is interposed into the dynamic linker, for diff --git a/glibc-rh1868106-1.patch b/glibc-rh1868106-1.patch new file mode 100755 index 0000000..1469c9b --- /dev/null +++ b/glibc-rh1868106-1.patch @@ -0,0 +1,62 @@ +Partial backport of: + +commit 333221862ecbebde60dd16e7ca17d26444e62f50 +Author: Florian Weimer +Date: Mon Apr 8 11:19:38 2019 +0200 + + resolv: Remove RES_INSECURE1, RES_INSECURE2 + + Always perform the associated security checks. + +The constants and their debug output handling are preserve in this +backport. + +diff --git a/resolv/res_send.c b/resolv/res_send.c +index 705ecb7189d215c2..c9b02cca130bc20d 100644 +--- a/resolv/res_send.c ++++ b/resolv/res_send.c +@@ -1324,31 +1324,25 @@ send_dg(res_state statp, + */ + goto wait; + } +- if (!(statp->options & RES_INSECURE1) && +- !res_ourserver_p(statp, &from)) { +- /* +- * response from wrong server? ignore it. +- * XXX - potential security hazard could +- * be detected here. +- */ +- goto wait; +- } +- if (!(statp->options & RES_INSECURE2) +- && (recvresp1 || !res_queriesmatch(buf, buf + buflen, ++ ++ /* Paranoia check. Due to the connected UDP socket, ++ the kernel has already filtered invalid addresses ++ for us. */ ++ if (!res_ourserver_p(statp, &from)) ++ goto wait; ++ ++ /* Check for the correct header layout and a matching ++ question. */ ++ if ((recvresp1 || !res_queriesmatch(buf, buf + buflen, + *thisansp, + *thisansp + + *thisanssizp)) + && (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2, + *thisansp, + *thisansp +- + *thisanssizp))) { +- /* +- * response contains wrong query? ignore it. +- * XXX - potential security hazard could +- * be detected here. +- */ +- goto wait; +- } ++ + *thisanssizp))) ++ goto wait; ++ + if (anhp->rcode == SERVFAIL || + anhp->rcode == NOTIMP || + anhp->rcode == REFUSED) { diff --git a/glibc-rh1868106-2.patch b/glibc-rh1868106-2.patch new file mode 100755 index 0000000..a1e5bc9 --- /dev/null +++ b/glibc-rh1868106-2.patch @@ -0,0 +1,51 @@ +Backport the support/ changes from this commit, to avoid future +conflicts: + +commit 446997ff1433d33452b81dfa9e626b8dccf101a4 +Author: Florian Weimer +Date: Wed Oct 30 17:26:58 2019 +0100 + + resolv: Implement trust-ad option for /etc/resolv.conf [BZ #20358] + + This introduces a concept of trusted name servers, for which the + AD bit is passed through to applications. For untrusted name + servers (the default), the AD bit in responses are cleared, to + provide a safe default. + + This approach is very similar to the one suggested by Pavel Šimerda + in . + + The DNS test framework in support/ is enhanced with support for + setting the AD bit in responses. + + Tested on x86_64-linux-gnu. + + Change-Id: Ibfe0f7c73ea221c35979842c5c3b6ed486495ccc + +diff --git a/support/resolv_test.c b/support/resolv_test.c +index 3f2a09f36f445878..28af227cb5ed901c 100644 +--- a/support/resolv_test.c ++++ b/support/resolv_test.c +@@ -182,6 +182,8 @@ resolv_response_init (struct resolv_response_builder *b, + if (flags.tc) + b->buffer[2] |= 0x02; + b->buffer[3] = 0x80 | flags.rcode; /* Always set RA. */ ++ if (flags.ad) ++ b->buffer[3] |= 0x20; + + /* Fill in the initial section count values. */ + b->buffer[4] = flags.qdcount >> 8; +diff --git a/support/resolv_test.h b/support/resolv_test.h +index 4c2e6c1b417f5fcd..be736aead40cd0cc 100644 +--- a/support/resolv_test.h ++++ b/support/resolv_test.h +@@ -134,6 +134,9 @@ struct resolv_response_flags + /* If true, the TC (truncation) flag will be set. */ + bool tc; + ++ /* If true, the AD (authenticated data) flag will be set. */ ++ bool ad; ++ + /* Initial section count values. Can be used to artificially + increase the counts, for malformed packet testing.*/ + unsigned short qdcount; diff --git a/glibc-rh1868106-3.patch b/glibc-rh1868106-3.patch new file mode 100755 index 0000000..dc3c8ea --- /dev/null +++ b/glibc-rh1868106-3.patch @@ -0,0 +1,293 @@ +commit 873e239a4c3d8ec235c27439c1bdc5bbf8aa1818 +Author: Florian Weimer +Date: Wed Oct 14 10:54:39 2020 +0200 + + support: Provide a way to reorder responses within the DNS test server + +diff --git a/support/Makefile b/support/Makefile +index 3c940aa6a7bdfc99..37d5dcc92a5c6dee 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -35,6 +35,8 @@ libsupport-routines = \ + ignore_stderr \ + next_to_fault \ + oom_error \ ++ resolv_response_context_duplicate \ ++ resolv_response_context_free \ + resolv_test \ + set_fortify_handler \ + support-xfstat \ +diff --git a/support/resolv_response_context_duplicate.c b/support/resolv_response_context_duplicate.c +new file mode 100644 +index 0000000000000000..f9c5c3462ad053ec +--- /dev/null ++++ b/support/resolv_response_context_duplicate.c +@@ -0,0 +1,37 @@ ++/* Duplicate a response context used in DNS resolver tests. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++struct resolv_response_context * ++resolv_response_context_duplicate (const struct resolv_response_context *ctx) ++{ ++ struct resolv_response_context *result = xmalloc (sizeof (*result)); ++ memcpy (result, ctx, sizeof (*result)); ++ if (result->client_address != NULL) ++ { ++ result->client_address = xmalloc (result->client_address_length); ++ memcpy (result->client_address, ctx->client_address, ++ result->client_address_length); ++ } ++ result->query_buffer = xmalloc (result->query_length); ++ memcpy (result->query_buffer, ctx->query_buffer, result->query_length); ++ return result; ++} +diff --git a/support/resolv_response_context_free.c b/support/resolv_response_context_free.c +new file mode 100644 +index 0000000000000000..b88c05ffd4acfdd4 +--- /dev/null ++++ b/support/resolv_response_context_free.c +@@ -0,0 +1,28 @@ ++/* Free a response context used in DNS resolver tests. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++ ++void ++resolv_response_context_free (struct resolv_response_context *ctx) ++{ ++ free (ctx->query_buffer); ++ free (ctx->client_address); ++ free (ctx); ++} +diff --git a/support/resolv_test.c b/support/resolv_test.c +index 28af227cb5ed901c..8cca4e6cf723de28 100644 +--- a/support/resolv_test.c ++++ b/support/resolv_test.c +@@ -434,9 +434,9 @@ resolv_response_buffer (const struct resolv_response_builder *b) + return result; + } + +-static struct resolv_response_builder * +-response_builder_allocate +- (const unsigned char *query_buffer, size_t query_length) ++struct resolv_response_builder * ++resolv_response_builder_allocate (const unsigned char *query_buffer, ++ size_t query_length) + { + struct resolv_response_builder *b = xmalloc (sizeof (*b)); + memset (b, 0, offsetof (struct resolv_response_builder, buffer)); +@@ -445,8 +445,8 @@ response_builder_allocate + return b; + } + +-static void +-response_builder_free (struct resolv_response_builder *b) ++void ++resolv_response_builder_free (struct resolv_response_builder *b) + { + tdestroy (b->compression_offsets, free); + free (b); +@@ -661,13 +661,17 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index) + + struct resolv_response_context ctx = + { ++ .test = obj, ++ .client_address = &peer, ++ .client_address_length = peerlen, + .query_buffer = query, + .query_length = length, + .server_index = server_index, + .tcp = false, + .edns = qinfo.edns, + }; +- struct resolv_response_builder *b = response_builder_allocate (query, length); ++ struct resolv_response_builder *b ++ = resolv_response_builder_allocate (query, length); + obj->config.response_callback + (&ctx, b, qinfo.qname, qinfo.qclass, qinfo.qtype); + +@@ -684,7 +688,7 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index) + if (b->offset >= 12) + printf ("info: UDP server %d: sending response:" + " %zu bytes, RCODE %d (for %s/%u/%u)\n", +- server_index, b->offset, b->buffer[3] & 0x0f, ++ ctx.server_index, b->offset, b->buffer[3] & 0x0f, + qinfo.qname, qinfo.qclass, qinfo.qtype); + else + printf ("info: UDP server %d: sending response: %zu bytes" +@@ -694,23 +698,31 @@ server_thread_udp_process_one (struct resolv_test *obj, int server_index) + if (b->truncate_bytes > 0) + printf ("info: truncated by %u bytes\n", b->truncate_bytes); + } +- size_t to_send = b->offset; +- if (to_send < b->truncate_bytes) +- to_send = 0; +- else +- to_send -= b->truncate_bytes; +- +- /* Ignore most errors here because the other end may have closed +- the socket. */ +- if (sendto (obj->servers[server_index].socket_udp, +- b->buffer, to_send, 0, +- (struct sockaddr *) &peer, peerlen) < 0) +- TEST_VERIFY_EXIT (errno != EBADF); ++ resolv_response_send_udp (&ctx, b); + } +- response_builder_free (b); ++ resolv_response_builder_free (b); + return true; + } + ++void ++resolv_response_send_udp (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b) ++{ ++ TEST_VERIFY_EXIT (!ctx->tcp); ++ size_t to_send = b->offset; ++ if (to_send < b->truncate_bytes) ++ to_send = 0; ++ else ++ to_send -= b->truncate_bytes; ++ ++ /* Ignore most errors here because the other end may have closed ++ the socket. */ ++ if (sendto (ctx->test->servers[ctx->server_index].socket_udp, ++ b->buffer, to_send, 0, ++ ctx->client_address, ctx->client_address_length) < 0) ++ TEST_VERIFY_EXIT (errno != EBADF); ++} ++ + /* UDP thread_callback function. Variant for one thread per + server. */ + static void +@@ -897,14 +909,15 @@ server_thread_tcp_client (void *arg) + + struct resolv_response_context ctx = + { ++ .test = closure->obj, + .query_buffer = query_buffer, + .query_length = query_length, + .server_index = closure->server_index, + .tcp = true, + .edns = qinfo.edns, + }; +- struct resolv_response_builder *b = response_builder_allocate +- (query_buffer, query_length); ++ struct resolv_response_builder *b ++ = resolv_response_builder_allocate (query_buffer, query_length); + closure->obj->config.response_callback + (&ctx, b, qinfo.qname, qinfo.qclass, qinfo.qtype); + +@@ -936,7 +949,7 @@ server_thread_tcp_client (void *arg) + writev_fully (closure->client_socket, buffers, 2); + } + bool close_flag = b->close; +- response_builder_free (b); ++ resolv_response_builder_free (b); + free (query_buffer); + if (close_flag) + break; +diff --git a/support/resolv_test.h b/support/resolv_test.h +index be736aead40cd0cc..ff5571dace92c936 100644 +--- a/support/resolv_test.h ++++ b/support/resolv_test.h +@@ -35,25 +35,36 @@ struct resolv_edns_info + uint16_t payload_size; + }; + ++/* This opaque struct collects information about the resolver testing ++ currently in progress. */ ++struct resolv_test; ++ + /* This struct provides context information when the response callback + specified in struct resolv_redirect_config is invoked. */ + struct resolv_response_context + { +- const unsigned char *query_buffer; ++ struct resolv_test *test; ++ void *client_address; ++ size_t client_address_length; ++ unsigned char *query_buffer; + size_t query_length; + int server_index; + bool tcp; + struct resolv_edns_info edns; + }; + ++/* Produces a deep copy of the context. */ ++struct resolv_response_context * ++ resolv_response_context_duplicate (const struct resolv_response_context *); ++ ++/* Frees the copy. For the context passed to the response function, ++ this happens implicitly. */ ++void resolv_response_context_free (struct resolv_response_context *); ++ + /* This opaque struct is used to construct responses from within the + response callback function. */ + struct resolv_response_builder; + +-/* This opaque struct collects information about the resolver testing +- currently in progress. */ +-struct resolv_test; +- + enum + { + /* Maximum number of test servers supported by the framework. */ +@@ -188,6 +199,22 @@ void resolv_response_close (struct resolv_response_builder *); + /* The size of the response packet built so far. */ + size_t resolv_response_length (const struct resolv_response_builder *); + ++/* Allocates a response builder tied to a specific query packet, ++ starting at QUERY_BUFFER, containing QUERY_LENGTH bytes. */ ++struct resolv_response_builder * ++ resolv_response_builder_allocate (const unsigned char *query_buffer, ++ size_t query_length); ++ ++/* Deallocates a response buffer. */ ++void resolv_response_builder_free (struct resolv_response_builder *); ++ ++/* Sends a UDP response using a specific context. This can be used to ++ reorder or duplicate responses, along with ++ resolv_response_context_duplicate and ++ response_builder_allocate. */ ++void resolv_response_send_udp (const struct resolv_response_context *, ++ struct resolv_response_builder *); ++ + __END_DECLS + + #endif /* SUPPORT_RESOLV_TEST_H */ diff --git a/glibc-rh1868106-4.patch b/glibc-rh1868106-4.patch new file mode 100755 index 0000000..7559a15 --- /dev/null +++ b/glibc-rh1868106-4.patch @@ -0,0 +1,36 @@ +commit 08443b19965f48862b02c2fd7b33a39d66daf2ff +Author: Florian Weimer +Date: Wed Oct 14 10:54:39 2020 +0200 + + support: Provide a way to clear the RA bit in DNS server responses + +diff --git a/support/resolv_test.c b/support/resolv_test.c +index 8cca4e6cf723de28..9323f1d55b0be8f1 100644 +--- a/support/resolv_test.c ++++ b/support/resolv_test.c +@@ -181,7 +181,9 @@ resolv_response_init (struct resolv_response_builder *b, + b->buffer[2] |= b->query_buffer[2] & 0x01; /* Copy the RD bit. */ + if (flags.tc) + b->buffer[2] |= 0x02; +- b->buffer[3] = 0x80 | flags.rcode; /* Always set RA. */ ++ b->buffer[3] = flags.rcode; ++ if (!flags.clear_ra) ++ b->buffer[3] |= 0x80; + if (flags.ad) + b->buffer[3] |= 0x20; + +diff --git a/support/resolv_test.h b/support/resolv_test.h +index ff5571dace92c936..825abb9ff2897a43 100644 +--- a/support/resolv_test.h ++++ b/support/resolv_test.h +@@ -148,6 +148,10 @@ struct resolv_response_flags + /* If true, the AD (authenticated data) flag will be set. */ + bool ad; + ++ /* If true, do not set the RA (recursion available) flag in the ++ response. */ ++ bool clear_ra; ++ + /* Initial section count values. Can be used to artificially + increase the counts, for malformed packet testing.*/ + unsigned short qdcount; diff --git a/glibc-rh1868106-5.patch b/glibc-rh1868106-5.patch new file mode 100755 index 0000000..d5848b6 --- /dev/null +++ b/glibc-rh1868106-5.patch @@ -0,0 +1,442 @@ +commit f1f00c072138af90ae6da180f260111f09afe7a3 +Author: Florian Weimer +Date: Wed Oct 14 10:54:39 2020 +0200 + + resolv: Handle transaction ID collisions in parallel queries (bug 26600) + + If the transaction IDs are equal, the old check attributed both + responses to the first query, not recognizing the second response. + This fixes bug 26600. + +diff --git a/resolv/Makefile b/resolv/Makefile +index 72a0f196506ac489..cee5225f8933f245 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -62,6 +62,11 @@ tests += \ + tst-resolv-search \ + tst-resolv-trailing \ + ++# This test calls __res_context_send directly, which is not exported ++# from libresolv. ++tests-internal += tst-resolv-txnid-collision ++tests-static += tst-resolv-txnid-collision ++ + # These tests need libdl. + ifeq (yes,$(build-shared)) + tests += \ +@@ -202,6 +207,8 @@ $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-trailing: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-threads: \ + $(libdl) $(objpfx)libresolv.so $(shared-thread-library) ++$(objpfx)tst-resolv-txnid-collision: $(objpfx)libresolv.a \ ++ $(static-thread-library) + $(objpfx)tst-resolv-canonname: \ + $(libdl) $(objpfx)libresolv.so $(shared-thread-library) + +diff --git a/resolv/res_send.c b/resolv/res_send.c +index c9b02cca130bc20d..ac19627634281c2f 100644 +--- a/resolv/res_send.c ++++ b/resolv/res_send.c +@@ -1315,15 +1315,6 @@ send_dg(res_state statp, + *terrno = EMSGSIZE; + return close_and_return_error (statp, resplen2); + } +- if ((recvresp1 || hp->id != anhp->id) +- && (recvresp2 || hp2->id != anhp->id)) { +- /* +- * response from old query, ignore it. +- * XXX - potential security hazard could +- * be detected here. +- */ +- goto wait; +- } + + /* Paranoia check. Due to the connected UDP socket, + the kernel has already filtered invalid addresses +@@ -1333,15 +1324,24 @@ send_dg(res_state statp, + + /* Check for the correct header layout and a matching + question. */ +- if ((recvresp1 || !res_queriesmatch(buf, buf + buflen, +- *thisansp, +- *thisansp +- + *thisanssizp)) +- && (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2, +- *thisansp, +- *thisansp +- + *thisanssizp))) +- goto wait; ++ int matching_query = 0; /* Default to no matching query. */ ++ if (!recvresp1 ++ && anhp->id == hp->id ++ && res_queriesmatch (buf, buf + buflen, ++ *thisansp, *thisansp + *thisanssizp)) ++ matching_query = 1; ++ if (!recvresp2 ++ && anhp->id == hp2->id ++ && res_queriesmatch (buf2, buf2 + buflen2, ++ *thisansp, *thisansp + *thisanssizp)) ++ matching_query = 2; ++ if (matching_query == 0) ++ /* Spurious UDP packet. Drop it and continue ++ waiting. */ ++ { ++ need_recompute = 1; ++ goto wait; ++ } + + if (anhp->rcode == SERVFAIL || + anhp->rcode == NOTIMP || +@@ -1356,7 +1356,7 @@ send_dg(res_state statp, + /* No data from the first reply. */ + resplen = 0; + /* We are waiting for a possible second reply. */ +- if (hp->id == anhp->id) ++ if (matching_query == 1) + recvresp1 = 1; + else + recvresp2 = 1; +@@ -1387,7 +1387,7 @@ send_dg(res_state statp, + return (1); + } + /* Mark which reply we received. */ +- if (recvresp1 == 0 && hp->id == anhp->id) ++ if (matching_query == 1) + recvresp1 = 1; + else + recvresp2 = 1; +diff --git a/resolv/tst-resolv-txnid-collision.c b/resolv/tst-resolv-txnid-collision.c +new file mode 100644 +index 0000000000000000..611d37362f3e5e89 +--- /dev/null ++++ b/resolv/tst-resolv-txnid-collision.c +@@ -0,0 +1,329 @@ ++/* Test parallel queries with transaction ID collisions. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Result of parsing a DNS question name. ++ ++ A question name has the form reorder-N-M-rcode-C.example.net, where ++ N and M are either 0 and 1, corresponding to the reorder member, ++ and C is a number that will be stored in the rcode field. ++ ++ Also see parse_qname below. */ ++struct parsed_qname ++{ ++ /* The DNS response code requested from the first server. The ++ second server always responds with RCODE zero. */ ++ int rcode; ++ ++ /* Indicates whether to perform reordering in the responses from the ++ respective server. */ ++ bool reorder[2]; ++}; ++ ++/* Fills *PARSED based on QNAME. */ ++static void ++parse_qname (struct parsed_qname *parsed, const char *qname) ++{ ++ int reorder0; ++ int reorder1; ++ int rcode; ++ char *suffix; ++ if (sscanf (qname, "reorder-%d-%d.rcode-%d.%ms", ++ &reorder0, &reorder1, &rcode, &suffix) == 4) ++ { ++ if (reorder0 != 0) ++ TEST_COMPARE (reorder0, 1); ++ if (reorder1 != 0) ++ TEST_COMPARE (reorder1, 1); ++ TEST_VERIFY (rcode >= 0 && rcode <= 15); ++ TEST_COMPARE_STRING (suffix, "example.net"); ++ free (suffix); ++ ++ parsed->rcode = rcode; ++ parsed->reorder[0] = reorder0; ++ parsed->reorder[1] = reorder1; ++ } ++ else ++ FAIL_EXIT1 ("unexpected query: %s", qname); ++} ++ ++/* Used to construct a response. The first server responds with an ++ error, the second server succeeds. */ ++static void ++build_response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ struct parsed_qname parsed; ++ parse_qname (&parsed, qname); ++ ++ switch (ctx->server_index) ++ { ++ case 0: ++ { ++ struct resolv_response_flags flags = { 0 }; ++ if (parsed.rcode == 0) ++ /* Simulate a delegation in case a NODATA (RCODE zero) ++ response is requested. */ ++ flags.clear_ra = true; ++ else ++ flags.rcode = parsed.rcode; ++ ++ resolv_response_init (b, flags); ++ resolv_response_add_question (b, qname, qclass, qtype); ++ } ++ break; ++ ++ case 1: ++ { ++ struct resolv_response_flags flags = { 0, }; ++ resolv_response_init (b, flags); ++ resolv_response_add_question (b, qname, qclass, qtype); ++ ++ resolv_response_section (b, ns_s_an); ++ resolv_response_open_record (b, qname, qclass, qtype, 0); ++ if (qtype == T_A) ++ { ++ char ipv4[4] = { 192, 0, 2, 1 }; ++ resolv_response_add_data (b, &ipv4, sizeof (ipv4)); ++ } ++ else ++ { ++ char ipv6[16] ++ = { 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; ++ resolv_response_add_data (b, &ipv6, sizeof (ipv6)); ++ } ++ resolv_response_close_record (b); ++ } ++ break; ++ } ++} ++ ++/* Used to reorder responses. */ ++struct resolv_response_context *previous_query; ++ ++/* Used to keep track of the queries received. */ ++static int previous_server_index = -1; ++static uint16_t previous_qtype; ++ ++/* For each server, buffer the first query and then send both answers ++ to the second query, reordered if requested. */ ++static void ++response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ TEST_VERIFY (qtype == T_A || qtype == T_AAAA); ++ if (ctx->server_index != 0) ++ TEST_COMPARE (ctx->server_index, 1); ++ ++ struct parsed_qname parsed; ++ parse_qname (&parsed, qname); ++ ++ if (previous_query == NULL) ++ { ++ /* No buffered query. Record this query and do not send a ++ response. */ ++ TEST_COMPARE (previous_qtype, 0); ++ previous_query = resolv_response_context_duplicate (ctx); ++ previous_qtype = qtype; ++ resolv_response_drop (b); ++ previous_server_index = ctx->server_index; ++ ++ if (test_verbose) ++ printf ("info: buffering first query for: %s\n", qname); ++ } ++ else ++ { ++ TEST_VERIFY (previous_query != 0); ++ TEST_COMPARE (ctx->server_index, previous_server_index); ++ TEST_VERIFY (previous_qtype != qtype); /* Not a duplicate. */ ++ ++ /* If reordering, send a response for this query explicitly, and ++ then skip the implicit send. */ ++ if (parsed.reorder[ctx->server_index]) ++ { ++ if (test_verbose) ++ printf ("info: sending reordered second response for: %s\n", ++ qname); ++ build_response (ctx, b, qname, qclass, qtype); ++ resolv_response_send_udp (ctx, b); ++ resolv_response_drop (b); ++ } ++ ++ /* Build a response for the previous query and send it, thus ++ reordering the two responses. */ ++ { ++ if (test_verbose) ++ printf ("info: sending first response for: %s\n", qname); ++ struct resolv_response_builder *btmp ++ = resolv_response_builder_allocate (previous_query->query_buffer, ++ previous_query->query_length); ++ build_response (ctx, btmp, qname, qclass, previous_qtype); ++ resolv_response_send_udp (ctx, btmp); ++ resolv_response_builder_free (btmp); ++ } ++ ++ /* If not reordering, send the reply as usual. */ ++ if (!parsed.reorder[ctx->server_index]) ++ { ++ if (test_verbose) ++ printf ("info: sending non-reordered second response for: %s\n", ++ qname); ++ build_response (ctx, b, qname, qclass, qtype); ++ } ++ ++ /* Unbuffer the response and prepare for the next query. */ ++ resolv_response_context_free (previous_query); ++ previous_query = NULL; ++ previous_qtype = 0; ++ previous_server_index = -1; ++ } ++} ++ ++/* Runs a query for QNAME and checks for the expected reply. See ++ struct parsed_qname for the expected format for QNAME. */ ++static void ++test_qname (const char *qname, int rcode) ++{ ++ struct resolv_context *ctx = __resolv_context_get (); ++ TEST_VERIFY_EXIT (ctx != NULL); ++ ++ unsigned char q1[512]; ++ int q1len = res_mkquery (QUERY, qname, C_IN, T_A, NULL, 0, NULL, ++ q1, sizeof (q1)); ++ TEST_VERIFY_EXIT (q1len > 12); ++ ++ unsigned char q2[512]; ++ int q2len = res_mkquery (QUERY, qname, C_IN, T_AAAA, NULL, 0, NULL, ++ q2, sizeof (q2)); ++ TEST_VERIFY_EXIT (q2len > 12); ++ ++ /* Produce a transaction ID collision. */ ++ memcpy (q2, q1, 2); ++ ++ unsigned char ans1[512]; ++ unsigned char *ans1p = ans1; ++ unsigned char *ans2p = NULL; ++ int nans2p = 0; ++ int resplen2 = 0; ++ int ans2p_malloced = 0; ++ ++ /* Perform a parallel A/AAAA query. */ ++ int resplen1 = __res_context_send (ctx, q1, q1len, q2, q2len, ++ ans1, sizeof (ans1), &ans1p, ++ &ans2p, &nans2p, ++ &resplen2, &ans2p_malloced); ++ ++ TEST_VERIFY (resplen1 > 12); ++ TEST_VERIFY (resplen2 > 12); ++ if (resplen1 <= 12 || resplen2 <= 12) ++ return; ++ ++ if (rcode == 1 || rcode == 3) ++ { ++ /* Format Error and Name Error responses does not trigger ++ switching to the next server. */ ++ TEST_COMPARE (ans1p[3] & 0x0f, rcode); ++ TEST_COMPARE (ans2p[3] & 0x0f, rcode); ++ return; ++ } ++ ++ /* The response should be successful. */ ++ TEST_COMPARE (ans1p[3] & 0x0f, 0); ++ TEST_COMPARE (ans2p[3] & 0x0f, 0); ++ ++ /* Due to bug 19691, the answer may not be in the slot matching the ++ query. Assume that the AAAA response is the longer one. */ ++ unsigned char *a_answer; ++ int a_answer_length; ++ unsigned char *aaaa_answer; ++ int aaaa_answer_length; ++ if (resplen2 > resplen1) ++ { ++ a_answer = ans1p; ++ a_answer_length = resplen1; ++ aaaa_answer = ans2p; ++ aaaa_answer_length = resplen2; ++ } ++ else ++ { ++ a_answer = ans2p; ++ a_answer_length = resplen2; ++ aaaa_answer = ans1p; ++ aaaa_answer_length = resplen1; ++ } ++ ++ { ++ char *expected = xasprintf ("name: %s\n" ++ "address: 192.0.2.1\n", ++ qname); ++ check_dns_packet (qname, a_answer, a_answer_length, expected); ++ free (expected); ++ } ++ { ++ char *expected = xasprintf ("name: %s\n" ++ "address: 2001:db8::1\n", ++ qname); ++ check_dns_packet (qname, aaaa_answer, aaaa_answer_length, expected); ++ free (expected); ++ } ++ ++ if (ans2p_malloced) ++ free (ans2p); ++ ++ __resolv_context_put (ctx); ++} ++ ++static int ++do_test (void) ++{ ++ struct resolv_test *aux = resolv_test_start ++ ((struct resolv_redirect_config) ++ { ++ .response_callback = response, ++ }); ++ ++ for (int rcode = 0; rcode <= 5; ++rcode) ++ for (int do_reorder_0 = 0; do_reorder_0 < 2; ++do_reorder_0) ++ for (int do_reorder_1 = 0; do_reorder_1 < 2; ++do_reorder_1) ++ { ++ char *qname = xasprintf ("reorder-%d-%d.rcode-%d.example.net", ++ do_reorder_0, do_reorder_1, rcode); ++ test_qname (qname, rcode); ++ free (qname); ++ } ++ ++ resolv_test_end (aux); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1868106-6.patch b/glibc-rh1868106-6.patch new file mode 100755 index 0000000..c85bafe --- /dev/null +++ b/glibc-rh1868106-6.patch @@ -0,0 +1,31 @@ +commit b8b53b338f6da91e86d115a39da860cefac736ad +Author: Florian Weimer +Date: Thu Oct 15 12:33:13 2020 +0200 + + resolv: Serialize processing in resolv/tst-resolv-txnid-collision + + When switching name servers, response processing by two server + threads clobbers the global test state. (There is still some + risk that this test is negatively impact by packet drops and + packet reordering, but this applies to many of the resolver tests + and is difficult to avoid.) + + Fixes commit f1f00c072138af90ae6da180f260111f09afe7a3 ("resolv: + Handle transaction ID collisions in parallel queries (bug 26600)"). + +diff --git a/resolv/tst-resolv-txnid-collision.c b/resolv/tst-resolv-txnid-collision.c +index 611d37362f3e5e89..189b76f1268f4e4d 100644 +--- a/resolv/tst-resolv-txnid-collision.c ++++ b/resolv/tst-resolv-txnid-collision.c +@@ -309,6 +309,11 @@ do_test (void) + ((struct resolv_redirect_config) + { + .response_callback = response, ++ ++ /* The response callback use global state (the previous_* ++ variables), and query processing must therefore be ++ serialized. */ ++ .single_thread_udp = true, + }); + + for (int rcode = 0; rcode <= 5; ++rcode) diff --git a/glibc-rh1871386-1.patch b/glibc-rh1871386-1.patch new file mode 100755 index 0000000..5cd3074 --- /dev/null +++ b/glibc-rh1871386-1.patch @@ -0,0 +1,20 @@ +commit 0798b8ecc8da8667362496c1217d18635106c609 +Author: Vineet Gupta +Date: Wed Apr 8 19:56:12 2020 -0700 + + ARC: Update syscall-names.list for ARC specific syscalls + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 314a653938..21a62a06f4 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -41,6 +41,9 @@ adjtimex + afs_syscall + alarm + alloc_hugepages ++arc_gettls ++arc_settls ++arc_usr_cmpxchg + arch_prctl + arm_fadvise64_64 + arm_sync_file_range diff --git a/glibc-rh1871386-2.patch b/glibc-rh1871386-2.patch new file mode 100755 index 0000000..d89c08d --- /dev/null +++ b/glibc-rh1871386-2.patch @@ -0,0 +1,26 @@ +commit b67339d0bbc07911859ca8c488e1923441cd3c33 +Author: Joseph Myers +Date: Mon Jun 15 22:58:22 2020 +0000 + + Update syscall-names.list for Linux 5.7. + + Linux 5.7 has no new syscalls. Update the version number in + syscall-names.list to reflect that it is still current for 5.7. + + Tested with build-many-glibcs.py. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 21a62a06f4..15dec5b98f 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.6. +-kernel 5.6 ++# The list of system calls is current as of Linux 5.7. ++kernel 5.7 + + FAST_atomic_update + FAST_cmpxchg diff --git a/glibc-rh1871386-3.patch b/glibc-rh1871386-3.patch new file mode 100755 index 0000000..09bd048 --- /dev/null +++ b/glibc-rh1871386-3.patch @@ -0,0 +1,37 @@ +commit 1cfb4715288845ebc55ad664421b48b32de9599c +Author: Joseph Myers +Date: Fri Aug 7 14:38:43 2020 +0000 + + Update syscall lists for Linux 5.8. + + Linux 5.8 has one new syscall, faccessat2. Update syscall-names.list + and regenerate the arch-syscall.h headers with build-many-glibcs.py + update-syscalls. + + Tested with build-many-glibcs.py. + +Modified to only update syscall-names.list for RHEL 8.5.0. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 15dec5b98f..a462318ecf 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.7. +-kernel 5.7 ++# The list of system calls is current as of Linux 5.8. ++kernel 5.8 + + FAST_atomic_update + FAST_cmpxchg +@@ -105,6 +105,7 @@ execveat + exit + exit_group + faccessat ++faccessat2 + fadvise64 + fadvise64_64 + fallocate diff --git a/glibc-rh1871386-4.patch b/glibc-rh1871386-4.patch new file mode 100755 index 0000000..72bb49d --- /dev/null +++ b/glibc-rh1871386-4.patch @@ -0,0 +1,37 @@ +commit dac8713629c8736a60aebec2f01657e46baa4c73 +Author: Joseph Myers +Date: Fri Oct 23 16:31:11 2020 +0000 + + Update syscall lists for Linux 5.9. + + Linux 5.9 has one new syscall, close_range. Update syscall-names.list + and regenerate the arch-syscall.h headers with build-many-glibcs.py + update-syscalls. + + Tested with build-many-glibcs.py. + +Modified to only update syscall-names.list for RHEL 8.5.0. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index a462318ecf..2d42aaf803 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.8. +-kernel 5.8 ++# The list of system calls is current as of Linux 5.9. ++kernel 5.9 + + FAST_atomic_update + FAST_cmpxchg +@@ -79,6 +79,7 @@ clone + clone2 + clone3 + close ++close_range + cmpxchg_badaddr + connect + copy_file_range diff --git a/glibc-rh1871386-5.patch b/glibc-rh1871386-5.patch new file mode 100755 index 0000000..a2e2b7d --- /dev/null +++ b/glibc-rh1871386-5.patch @@ -0,0 +1,37 @@ +commit bcf47eb0fba4c6278aadd6a377d6b7b3f673e17c +Author: Joseph Myers +Date: Wed Dec 16 02:08:52 2020 +0000 + + Update syscall lists for Linux 5.10. + + Linux 5.10 has one new syscall, process_madvise. Update + syscall-names.list and regenerate the arch-syscall.h headers with + build-many-glibcs.py update-syscalls. + + Tested with build-many-glibcs.py. + +Modified to only update syscall-names.list for RHEL 8.5.0. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 2d42aaf803..4bd42be2b9 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.9. +-kernel 5.9 ++# The list of system calls is current as of Linux 5.10. ++kernel 5.10 + + FAST_atomic_update + FAST_cmpxchg +@@ -433,6 +433,7 @@ pread64 + preadv + preadv2 + prlimit64 ++process_madvise + process_vm_readv + process_vm_writev + prof diff --git a/glibc-rh1871386-6.patch b/glibc-rh1871386-6.patch new file mode 100755 index 0000000..36a47e8 --- /dev/null +++ b/glibc-rh1871386-6.patch @@ -0,0 +1,42 @@ +commit 2b778ceb4010c28d70de9b8eab20e8d88eed586b +Author: Paul Eggert +Date: Sat Jan 2 11:32:25 2021 -0800 + + Update copyright dates with scripts/update-copyrights + + I used these shell commands: + + ../glibc/scripts/update-copyrights $PWD/../gnulib/build-aux/update-copyright + (cd ../glibc && git commit -am"[this commit message]") + + and then ignored the output, which consisted lines saying "FOO: warning: + copyright statement not found" for each of 6694 files FOO. + I then removed trailing white space from benchtests/bench-pthread-locks.c + and iconvdata/tst-iconv-big5-hkscs-to-2ucs4.c, to work around this + diagnostic from Savannah: + remote: *** pre-commit check failed ... + remote: *** error: lines with trailing whitespace found + remote: error: hook declined to update refs/heads/master + +Modified to only update copyright for syscall-names.list for RHEL 8.5.0. Also +update licenses link to use https. + +diff -Nrup a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +--- a/sysdeps/unix/sysv/linux/syscall-names.list 2021-03-16 14:12:27.828571456 -0400 ++++ b/sysdeps/unix/sysv/linux/syscall-names.list 2021-03-16 14:13:23.950145631 -0400 +@@ -1,5 +1,5 @@ + # List of all known Linux system calls. +-# Copyright (C) 2017-2018 Free Software Foundation, Inc. ++# Copyright (C) 2017-2021 Free Software Foundation, Inc. + # This file is part of the GNU C Library. + # + # The GNU C Library is free software; you can redistribute it and/or +@@ -14,7 +14,7 @@ + # + # You should have received a copy of the GNU Lesser General Public + # License along with the GNU C Library; if not, see +-# . ++# . + + # This file contains the list of system call names. It has to remain in + # alphabetical order. Lines which start with # are treated as comments. diff --git a/glibc-rh1871386-7.patch b/glibc-rh1871386-7.patch new file mode 100755 index 0000000..79774e7 --- /dev/null +++ b/glibc-rh1871386-7.patch @@ -0,0 +1,37 @@ +commit 83908b3a1ea51e3aa7ff422275940e56dbba989f +Author: Joseph Myers +Date: Fri Feb 19 21:16:27 2021 +0000 + + Update syscall lists for Linux 5.11. + + Linux 5.11 has one new syscall, epoll_pwait2. Update + syscall-names.list and regenerate the arch-syscall.h headers with + build-many-glibcs.py update-syscalls. + + Tested with build-many-glibcs.py. + +Modified to only update syscall-names.list for RHEL 8.5.0. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 4df7eeab96..f6cb34089d 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.10. +-kernel 5.10 ++# The list of system calls is current as of Linux 5.11. ++kernel 5.11 + + FAST_atomic_update + FAST_cmpxchg +@@ -95,6 +95,7 @@ epoll_create1 + epoll_ctl + epoll_ctl_old + epoll_pwait ++epoll_pwait2 + epoll_wait + epoll_wait_old + eventfd diff --git a/glibc-rh1871387-1.patch b/glibc-rh1871387-1.patch new file mode 100755 index 0000000..f37c484 --- /dev/null +++ b/glibc-rh1871387-1.patch @@ -0,0 +1,254 @@ +commit 7793ad7a2c00434398aa8bb3f5932e2fdf43536a +Author: Rajalakshmi Srinivasaraghavan +Date: Thu Aug 16 12:12:02 2018 +0530 + + powerpc: Rearrange little endian specific files + + This patch moves little endian specific POWER9 optimization files to + sysdeps/powerpc/powerpc64/le and creates POWER9 ifunc functions + only for little endian. + +diff --git a/sysdeps/powerpc/powerpc64/power9/strcmp.S b/sysdeps/powerpc/powerpc64/le/power9/strcmp.S +similarity index 93% +rename from sysdeps/powerpc/powerpc64/power9/strcmp.S +rename to sysdeps/powerpc/powerpc64/le/power9/strcmp.S +index 98243a9d51e1577f..bf057f598ef2aa55 100644 +--- a/sysdeps/powerpc/powerpc64/power9/strcmp.S ++++ b/sysdeps/powerpc/powerpc64/le/power9/strcmp.S +@@ -15,7 +15,6 @@ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ +-#ifdef __LITTLE_ENDIAN__ + #include + + #ifndef STRCMP +@@ -30,16 +29,16 @@ + as in POWER8 patch and uses vectorised loops after that. */ + + /* TODO: Change this to actual instructions when minimum binutils is upgraded +- to 2.27. Macros are defined below for these newer instructions in order ++ to 2.27. Macros are defined below for these newer instructions in order + to maintain compatibility. */ +-# define VCTZLSBB(r,v) .long (0x10010602 | ((r)<<(32-11)) | ((v)<<(32-21))) ++#define VCTZLSBB(r,v) .long (0x10010602 | ((r)<<(32-11)) | ((v)<<(32-21))) + +-# define VEXTUBRX(t,a,b) .long (0x1000070d \ ++#define VEXTUBRX(t,a,b) .long (0x1000070d \ + | ((t)<<(32-11)) \ + | ((a)<<(32-16)) \ + | ((b)<<(32-21)) ) + +-# define VCMPNEZB(t,a,b) .long (0x10000507 \ ++#define VCMPNEZB(t,a,b) .long (0x10000507 \ + | ((t)<<(32-11)) \ + | ((a)<<(32-16)) \ + | ((b)<<(32-21)) ) +@@ -48,7 +47,7 @@ + reg1: Vector to hold next 16 bytes. + reg2: Address to read from. + reg3: Permute control vector. */ +-# define GET16BYTES(reg1, reg2, reg3) \ ++#define GET16BYTES(reg1, reg2, reg3) \ + lvx reg1, 0, reg2; \ + vperm v8, v2, reg1, reg3; \ + vcmpequb. v8, v0, v8; \ +@@ -263,6 +262,3 @@ L(pagecross_nullfound): + b L(pagecross_retdiff) + END (STRCMP) + libc_hidden_builtin_def (strcmp) +-#else +-#include +-#endif +diff --git a/sysdeps/powerpc/powerpc64/power9/strncmp.S b/sysdeps/powerpc/powerpc64/le/power9/strncmp.S +similarity index 95% +rename from sysdeps/powerpc/powerpc64/power9/strncmp.S +rename to sysdeps/powerpc/powerpc64/le/power9/strncmp.S +index 40be98ff45c9f485..93a79343c6be1099 100644 +--- a/sysdeps/powerpc/powerpc64/power9/strncmp.S ++++ b/sysdeps/powerpc/powerpc64/le/power9/strncmp.S +@@ -15,7 +15,6 @@ + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ +-#ifdef __LITTLE_ENDIAN__ + #include + + /* Implements the function +@@ -31,16 +30,16 @@ + #endif + + /* TODO: Change this to actual instructions when minimum binutils is upgraded +- to 2.27. Macros are defined below for these newer instructions in order ++ to 2.27. Macros are defined below for these newer instructions in order + to maintain compatibility. */ +-# define VCTZLSBB(r,v) .long (0x10010602 | ((r)<<(32-11)) | ((v)<<(32-21))) ++#define VCTZLSBB(r,v) .long (0x10010602 | ((r)<<(32-11)) | ((v)<<(32-21))) + +-# define VEXTUBRX(t,a,b) .long (0x1000070d \ ++#define VEXTUBRX(t,a,b) .long (0x1000070d \ + | ((t)<<(32-11)) \ + | ((a)<<(32-16)) \ + | ((b)<<(32-21)) ) + +-# define VCMPNEZB(t,a,b) .long (0x10000507 \ ++#define VCMPNEZB(t,a,b) .long (0x10000507 \ + | ((t)<<(32-11)) \ + | ((a)<<(32-16)) \ + | ((b)<<(32-21)) ) +@@ -49,7 +48,7 @@ + reg1: Vector to hold next 16 bytes. + reg2: Address to read from. + reg3: Permute control vector. */ +-# define GET16BYTES(reg1, reg2, reg3) \ ++#define GET16BYTES(reg1, reg2, reg3) \ + lvx reg1, 0, reg2; \ + vperm v8, v2, reg1, reg3; \ + vcmpequb. v8, v0, v8; \ +@@ -374,6 +373,3 @@ L(byte_ne_3): + b L(byte_ne_1) + END(STRNCMP) + libc_hidden_builtin_def(strncmp) +-#else +-#include +-#endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index 4df6b45c4c1c495a..963ea84dbfa98c74 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -12,7 +12,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + strnlen-power8 strnlen-power7 strnlen-ppc64 \ + strcasecmp-power7 strcasecmp_l-power7 \ + strncase-power7 strncase_l-power7 \ +- strncmp-power9 strncmp-power8 strncmp-power7 \ ++ strncmp-power8 strncmp-power7 \ + strncmp-power4 strncmp-ppc64 \ + strchr-power8 strchr-power7 strchr-ppc64 \ + strchrnul-power8 strchrnul-power7 strchrnul-ppc64 \ +@@ -22,7 +22,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + strncat-power8 strncat-power7 strncat-ppc64 \ + strncpy-power7 strncpy-ppc64 \ + stpncpy-power8 stpncpy-power7 stpncpy-ppc64 \ +- strcmp-power9 strcmp-power8 strcmp-power7 strcmp-ppc64 \ ++ strcmp-power8 strcmp-power7 strcmp-ppc64 \ + strcat-power8 strcat-power7 strcat-ppc64 \ + memmove-power7 memmove-ppc64 wordcopy-ppc64 bcopy-ppc64 \ + strncpy-power8 strstr-power7 strstr-ppc64 \ +@@ -31,6 +31,9 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + strcasecmp-ppc64 strcasecmp-power8 strncase-ppc64 \ + strncase-power8 + ++ifneq (,$(filter %le,$(config-machine))) ++sysdep_routines += strcmp-power9 strncmp-power9 ++endif + CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops + CFLAGS-strncase_l-power7.c += -mcpu=power7 -funroll-loops + endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 38a21e478e2527f5..1d374f2ae48165bd 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -112,8 +112,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/powerpc/powerpc64/multiarch/strncmp.c. */ + IFUNC_IMPL (i, name, strncmp, ++#ifdef __LITTLE_ENDIAN__ + IFUNC_IMPL_ADD (array, i, strncmp, hwcap2 & PPC_FEATURE2_ARCH_3_00, + __strncmp_power9) ++#endif + IFUNC_IMPL_ADD (array, i, strncmp, hwcap2 & PPC_FEATURE2_ARCH_2_07, + __strncmp_power8) + IFUNC_IMPL_ADD (array, i, strncmp, hwcap & PPC_FEATURE_HAS_VSX, +@@ -337,9 +339,11 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/powerpc/powerpc64/multiarch/strcmp.c. */ + IFUNC_IMPL (i, name, strcmp, ++#ifdef __LITTLE_ENDIAN__ + IFUNC_IMPL_ADD (array, i, strcmp, + hwcap2 & PPC_FEATURE2_ARCH_3_00, + __strcmp_power9) ++#endif + IFUNC_IMPL_ADD (array, i, strcmp, + hwcap2 & PPC_FEATURE2_ARCH_2_07, + __strcmp_power8) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcmp-power9.S b/sysdeps/powerpc/powerpc64/multiarch/strcmp-power9.S +index 8b569d38be783316..545e6cee91e61311 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/strcmp-power9.S ++++ b/sysdeps/powerpc/powerpc64/multiarch/strcmp-power9.S +@@ -16,11 +16,11 @@ + License along with the GNU C Library; if not, see + . */ + +-#if IS_IN (libc) ++#if defined __LITTLE_ENDIAN__ && IS_IN (libc) + #define STRCMP __strcmp_power9 + + #undef libc_hidden_builtin_def + #define libc_hidden_builtin_def(name) + +-#include ++#include + #endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcmp.c b/sysdeps/powerpc/powerpc64/multiarch/strcmp.c +index b669053166771cae..2422c8d72cfdec83 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/strcmp.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/strcmp.c +@@ -27,13 +27,17 @@ + extern __typeof (strcmp) __strcmp_ppc attribute_hidden; + extern __typeof (strcmp) __strcmp_power7 attribute_hidden; + extern __typeof (strcmp) __strcmp_power8 attribute_hidden; ++# ifdef __LITTLE_ENDIAN__ + extern __typeof (strcmp) __strcmp_power9 attribute_hidden; ++# endif + + # undef strcmp + + libc_ifunc_redirected (__redirect_strcmp, strcmp, ++# ifdef __LITTLE_ENDIAN__ + (hwcap2 & PPC_FEATURE2_ARCH_3_00) + ? __strcmp_power9 : ++# endif + (hwcap2 & PPC_FEATURE2_ARCH_2_07) + ? __strcmp_power8 + : (hwcap & PPC_FEATURE_HAS_VSX) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power9.S b/sysdeps/powerpc/powerpc64/multiarch/strncmp-power9.S +index 3356f7252771a043..c6f0128379c497b4 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp-power9.S ++++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp-power9.S +@@ -15,11 +15,11 @@ + License along with the GNU C Library; if not, see + . */ + +-#if IS_IN (libc) ++#if defined __LITTLE_ENDIAN__ && IS_IN (libc) + #define STRNCMP __strncmp_power9 + + #undef libc_hidden_builtin_def + #define libc_hidden_builtin_def(name) + +-#include ++#include + #endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c +index c4a40d1ec7245a3b..9c887ee18186f070 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/strncmp.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/strncmp.c +@@ -29,14 +29,18 @@ extern __typeof (strncmp) __strncmp_ppc attribute_hidden; + extern __typeof (strncmp) __strncmp_power4 attribute_hidden; + extern __typeof (strncmp) __strncmp_power7 attribute_hidden; + extern __typeof (strncmp) __strncmp_power8 attribute_hidden; ++# ifdef __LITTLE_ENDIAN__ + extern __typeof (strncmp) __strncmp_power9 attribute_hidden; ++# endif + # undef strncmp + + /* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle + ifunc symbol properly. */ + libc_ifunc_redirected (__redirect_strncmp, strncmp, ++# ifdef __LITTLE_ENDIAN_ + (hwcap2 & PPC_FEATURE2_ARCH_3_00) + ? __strncmp_power9 : ++# endif + (hwcap2 & PPC_FEATURE2_ARCH_2_07) + ? __strncmp_power8 + : (hwcap & PPC_FEATURE_HAS_VSX) diff --git a/glibc-rh1871387-2.patch b/glibc-rh1871387-2.patch new file mode 100755 index 0000000..7f0cc39 --- /dev/null +++ b/glibc-rh1871387-2.patch @@ -0,0 +1,245 @@ +commit 39037048502d52ab6422c18f2d178d6228d2c7b9 +Author: Anton Blanchard via Libc-alpha +Date: Thu May 14 09:00:26 2020 +1000 + + powerpc: Optimized strcpy for POWER9 + + This version uses VSX store vector with length instructions and is + significantly faster on small strings and relatively unaligned large + strings, compared to the POWER8 version. A few examples: + + __strcpy_power9 __strcpy_power8 + Length 16, alignments in bytes 0/ 0: 2.52454 4.62695 + Length 412, alignments in bytes 4/ 0: 11.6 22.9185 + +diff --git a/sysdeps/powerpc/powerpc64/le/power9/strcpy.S b/sysdeps/powerpc/powerpc64/le/power9/strcpy.S +new file mode 100644 +index 0000000000000000..5749228054667b2d +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power9/strcpy.S +@@ -0,0 +1,144 @@ ++/* Optimized strcpy implementation for PowerPC64/POWER9. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++ ++#ifndef STRCPY ++# define STRCPY strcpy ++#endif ++ ++/* Implements the function ++ ++ char * [r3] strcpy (char *dest [r3], const char *src [r4]) ++ ++ The implementation can load bytes past a null terminator, but only ++ up to the next 16B boundary, so it never crosses a page. */ ++ ++.machine power9 ++ENTRY_TOCLESS (STRCPY, 4) ++ CALL_MCOUNT 2 ++ ++ /* NULL string optimisation */ ++ lbz r0,0(r4) ++ stb r0,0(r3) ++ cmpwi r0,0 ++ beqlr ++ ++ addi r4,r4,1 ++ addi r11,r3,1 ++ ++ vspltisb v18,0 /* Zeroes in v18 */ ++ ++ neg r5,r4 ++ rldicl r9,r5,0,60 /* How many bytes to get source 16B aligned? */ ++ ++ /* Get source 16B aligned */ ++ lvx v0,0,r4 ++ lvsr v1,0,r4 ++ vperm v0,v18,v0,v1 ++ ++ vcmpequb v6,v0,v18 /* 0xff if byte is NULL, 0x00 otherwise */ ++ vctzlsbb r8,v6 /* Number of trailing zeroes */ ++ addi r8,r8,1 /* Add null terminator */ ++ ++ /* r8 = bytes including null ++ r9 = bytes to get source 16B aligned ++ if r8 > r9 ++ no null, copy r9 bytes ++ else ++ there is a null, copy r8 bytes and return. */ ++ cmpd r8,r9 ++ bgt L(no_null) ++ ++ sldi r10,r8,56 /* stxvl wants size in top 8 bits */ ++ stxvl 32+v0,r11,r10 /* Partial store */ ++ ++ blr ++ ++L(no_null): ++ sldi r10,r9,56 /* stxvl wants size in top 8 bits */ ++ stxvl 32+v0,r11,r10 /* Partial store */ ++ ++ add r4,r4,r9 ++ add r11,r11,r9 ++ ++L(loop): ++ lxv 32+v0,0(r4) ++ vcmpequb. v6,v0,v18 /* Any zero bytes? */ ++ bne cr6,L(tail1) ++ ++ lxv 32+v1,16(r4) ++ vcmpequb. v6,v1,v18 /* Any zero bytes? */ ++ bne cr6,L(tail2) ++ ++ lxv 32+v2,32(r4) ++ vcmpequb. v6,v2,v18 /* Any zero bytes? */ ++ bne cr6,L(tail3) ++ ++ lxv 32+v3,48(r4) ++ vcmpequb. v6,v3,v18 /* Any zero bytes? */ ++ bne cr6,L(tail4) ++ ++ stxv 32+v0,0(r11) ++ stxv 32+v1,16(r11) ++ stxv 32+v2,32(r11) ++ stxv 32+v3,48(r11) ++ ++ addi r4,r4,64 ++ addi r11,r11,64 ++ ++ b L(loop) ++ ++L(tail1): ++ vctzlsbb r8,v6 ++ addi r8,r8,1 ++ sldi r9,r8,56 /* stxvl wants size in top 8 bits */ ++ stxvl 32+v0,r11,r9 ++ blr ++ ++L(tail2): ++ stxv 32+v0,0(r11) ++ vctzlsbb r8,v6 /* Number of trailing zeroes */ ++ addi r8,r8,1 /* Add null terminator */ ++ sldi r10,r8,56 /* stxvl wants size in top 8 bits */ ++ addi r11,r11,16 ++ stxvl 32+v1,r11,r10 /* Partial store */ ++ blr ++ ++L(tail3): ++ stxv 32+v0,0(r11) ++ stxv 32+v1,16(r11) ++ vctzlsbb r8,v6 /* Number of trailing zeroes */ ++ addi r8,r8,1 /* Add null terminator */ ++ sldi r10,r8,56 /* stxvl wants size in top 8 bits */ ++ addi r11,r11,32 ++ stxvl 32+v2,r11,r10 /* Partial store */ ++ blr ++ ++L(tail4): ++ stxv 32+v0,0(r11) ++ stxv 32+v1,16(r11) ++ stxv 32+v2,32(r11) ++ vctzlsbb r8,v6 /* Number of trailing zeroes */ ++ addi r8,r8,1 /* Add null terminator */ ++ sldi r10,r8,56 /* stxvl wants size in top 8 bits */ ++ addi r11,r11,48 ++ stxvl 32+v3,r11,r10 /* Partial store */ ++ blr ++END (STRCPY) ++libc_hidden_builtin_def (strcpy) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index 963ea84dbfa98c74..17057bcbd694a710 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -32,7 +32,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + strncase-power8 + + ifneq (,$(filter %le,$(config-machine))) +-sysdep_routines += strcmp-power9 strncmp-power9 ++sysdep_routines += strcmp-power9 strncmp-power9 strcpy-power9 + endif + CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops + CFLAGS-strncase_l-power7.c += -mcpu=power7 -funroll-loops +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 1d374f2ae48165bd..2857fa8f36599afd 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -85,6 +85,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/powerpc/powerpc64/multiarch/strcpy.c. */ + IFUNC_IMPL (i, name, strcpy, ++#ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, strcpy, hwcap2 & PPC_FEATURE2_ARCH_3_00, ++ __strcpy_power9) ++#endif + IFUNC_IMPL_ADD (array, i, strcpy, hwcap2 & PPC_FEATURE2_ARCH_2_07, + __strcpy_power8) + IFUNC_IMPL_ADD (array, i, strcpy, hwcap & PPC_FEATURE_HAS_VSX, +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcpy-power9.S b/sysdeps/powerpc/powerpc64/multiarch/strcpy-power9.S +new file mode 100644 +index 0000000000000000..d22aa0a8d690cad7 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/strcpy-power9.S +@@ -0,0 +1,26 @@ ++/* Optimized strcpy implementation for POWER9/PPC64. ++ Copyright (C) 2016-2020 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 ++ . */ ++ ++#if defined __LITTLE_ENDIAN__ && IS_IN (libc) ++#define STRCPY __strcpy_power9 ++ ++#undef libc_hidden_builtin_def ++#define libc_hidden_builtin_def(name) ++ ++#include ++#endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strcpy.c b/sysdeps/powerpc/powerpc64/multiarch/strcpy.c +index b18a92a62a526d9c..88826392be4bdf48 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/strcpy.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/strcpy.c +@@ -25,9 +25,16 @@ + extern __typeof (strcpy) __strcpy_ppc attribute_hidden; + extern __typeof (strcpy) __strcpy_power7 attribute_hidden; + extern __typeof (strcpy) __strcpy_power8 attribute_hidden; ++# ifdef __LITTLE_ENDIAN__ ++extern __typeof (strcpy) __strcpy_power9 attribute_hidden; ++# endif + #undef strcpy + + libc_ifunc_redirected (__redirect_strcpy, strcpy, ++# ifdef __LITTLE_ENDIAN__ ++ (hwcap2 & PPC_FEATURE2_ARCH_3_00) ++ ? __strcpy_power9 : ++# endif + (hwcap2 & PPC_FEATURE2_ARCH_2_07) + ? __strcpy_power8 + : (hwcap & PPC_FEATURE_HAS_VSX) diff --git a/glibc-rh1871387-3.patch b/glibc-rh1871387-3.patch new file mode 100755 index 0000000..5ccacc9 --- /dev/null +++ b/glibc-rh1871387-3.patch @@ -0,0 +1,270 @@ +commit aa70d0563256b8ea053203177f756bca33b5cf37 +Author: Anton Blanchard via Libc-alpha +Date: Thu May 14 09:08:35 2020 +1000 + + powerpc: Optimized stpcpy for POWER9 + + Add stpcpy support to the POWER9 strcpy. This is up to 40% faster on + small strings and up to 90% faster on long relatively unaligned strings, + compared to the POWER8 version. A few examples: + + __stpcpy_power9 __stpcpy_power8 + Length 20, alignments in bytes 4/ 4: 2.58246 4.8788 + Length 1024, alignments in bytes 1/ 6: 24.8186 47.8528 + +diff --git a/sysdeps/powerpc/powerpc64/le/power9/stpcpy.S b/sysdeps/powerpc/powerpc64/le/power9/stpcpy.S +new file mode 100644 +index 0000000000000000..44425cb1e80ea198 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power9/stpcpy.S +@@ -0,0 +1,24 @@ ++/* Optimized stpcpy implementation for PowerPC64/POWER9. ++ Copyright (C) 2015-2020 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 ++ . */ ++ ++#define USE_AS_STPCPY ++#include ++ ++weak_alias (__stpcpy, stpcpy) ++libc_hidden_def (__stpcpy) ++libc_hidden_builtin_def (stpcpy) +diff --git a/sysdeps/powerpc/powerpc64/le/power9/strcpy.S b/sysdeps/powerpc/powerpc64/le/power9/strcpy.S +index 5749228054667b2d..ce8f50329177fd06 100644 +--- a/sysdeps/powerpc/powerpc64/le/power9/strcpy.S ++++ b/sysdeps/powerpc/powerpc64/le/power9/strcpy.S +@@ -18,19 +18,35 @@ + + #include + +-#ifndef STRCPY +-# define STRCPY strcpy +-#endif ++#ifdef USE_AS_STPCPY ++# ifndef STPCPY ++# define FUNC_NAME __stpcpy ++# else ++# define FUNC_NAME STPCPY ++# endif ++#else ++# ifndef STRCPY ++# define FUNC_NAME strcpy ++# else ++# define FUNC_NAME STRCPY ++# endif ++#endif /* !USE_AS_STPCPY */ + + /* Implements the function + + char * [r3] strcpy (char *dest [r3], const char *src [r4]) + ++ or ++ ++ char * [r3] stpcpy (char *dest [r3], const char *src [r4]) ++ ++ if USE_AS_STPCPY is defined. ++ + The implementation can load bytes past a null terminator, but only + up to the next 16B boundary, so it never crosses a page. */ + + .machine power9 +-ENTRY_TOCLESS (STRCPY, 4) ++ENTRY_TOCLESS (FUNC_NAME, 4) + CALL_MCOUNT 2 + + /* NULL string optimisation */ +@@ -53,8 +69,8 @@ ENTRY_TOCLESS (STRCPY, 4) + vperm v0,v18,v0,v1 + + vcmpequb v6,v0,v18 /* 0xff if byte is NULL, 0x00 otherwise */ +- vctzlsbb r8,v6 /* Number of trailing zeroes */ +- addi r8,r8,1 /* Add null terminator */ ++ vctzlsbb r7,v6 /* Number of trailing zeroes */ ++ addi r8,r7,1 /* Add null terminator */ + + /* r8 = bytes including null + r9 = bytes to get source 16B aligned +@@ -68,6 +84,11 @@ ENTRY_TOCLESS (STRCPY, 4) + sldi r10,r8,56 /* stxvl wants size in top 8 bits */ + stxvl 32+v0,r11,r10 /* Partial store */ + ++#ifdef USE_AS_STPCPY ++ /* stpcpy returns the dest address plus the size not counting the ++ final '\0'. */ ++ add r3,r11,r7 ++#endif + blr + + L(no_null): +@@ -106,28 +127,43 @@ L(loop): + + L(tail1): + vctzlsbb r8,v6 +- addi r8,r8,1 +- sldi r9,r8,56 /* stxvl wants size in top 8 bits */ ++ addi r9,r8,1 ++ sldi r9,r9,56 /* stxvl wants size in top 8 bits */ + stxvl 32+v0,r11,r9 ++#ifdef USE_AS_STPCPY ++ /* stpcpy returns the dest address plus the size not counting the ++ final '\0'. */ ++ add r3,r11,r8 ++#endif + blr + + L(tail2): + stxv 32+v0,0(r11) + vctzlsbb r8,v6 /* Number of trailing zeroes */ +- addi r8,r8,1 /* Add null terminator */ +- sldi r10,r8,56 /* stxvl wants size in top 8 bits */ ++ addi r9,r8,1 /* Add null terminator */ ++ sldi r10,r9,56 /* stxvl wants size in top 8 bits */ + addi r11,r11,16 + stxvl 32+v1,r11,r10 /* Partial store */ ++#ifdef USE_AS_STPCPY ++ /* stpcpy returns the dest address plus the size not counting the ++ final '\0'. */ ++ add r3,r11,r8 ++#endif + blr + + L(tail3): + stxv 32+v0,0(r11) + stxv 32+v1,16(r11) + vctzlsbb r8,v6 /* Number of trailing zeroes */ +- addi r8,r8,1 /* Add null terminator */ +- sldi r10,r8,56 /* stxvl wants size in top 8 bits */ ++ addi r9,r8,1 /* Add null terminator */ ++ sldi r10,r9,56 /* stxvl wants size in top 8 bits */ + addi r11,r11,32 + stxvl 32+v2,r11,r10 /* Partial store */ ++#ifdef USE_AS_STPCPY ++ /* stpcpy returns the dest address plus the size not counting the ++ final '\0'. */ ++ add r3,r11,r8 ++#endif + blr + + L(tail4): +@@ -135,10 +171,17 @@ L(tail4): + stxv 32+v1,16(r11) + stxv 32+v2,32(r11) + vctzlsbb r8,v6 /* Number of trailing zeroes */ +- addi r8,r8,1 /* Add null terminator */ +- sldi r10,r8,56 /* stxvl wants size in top 8 bits */ ++ addi r9,r8,1 /* Add null terminator */ ++ sldi r10,r9,56 /* stxvl wants size in top 8 bits */ + addi r11,r11,48 + stxvl 32+v3,r11,r10 /* Partial store */ ++#ifdef USE_AS_STPCPY ++ /* stpcpy returns the dest address plus the size not counting the ++ final '\0'. */ ++ add r3,r11,r8 ++#endif + blr +-END (STRCPY) ++END (FUNC_NAME) ++#ifndef USE_AS_STPCPY + libc_hidden_builtin_def (strcpy) ++#endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index 17057bcbd694a710..cada6b19bf3c8fab 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -32,7 +32,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + strncase-power8 + + ifneq (,$(filter %le,$(config-machine))) +-sysdep_routines += strcmp-power9 strncmp-power9 strcpy-power9 ++sysdep_routines += strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 + endif + CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops + CFLAGS-strncase_l-power7.c += -mcpu=power7 -funroll-loops +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 2857fa8f36599afd..b0abc6b61dc15f19 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -98,6 +98,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/powerpc/powerpc64/multiarch/stpcpy.c. */ + IFUNC_IMPL (i, name, stpcpy, ++#ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, strncmp, hwcap2 & PPC_FEATURE2_ARCH_3_00, ++ __stpcpy_power9) ++#endif + IFUNC_IMPL_ADD (array, i, stpcpy, hwcap2 & PPC_FEATURE2_ARCH_2_07, + __stpcpy_power8) + IFUNC_IMPL_ADD (array, i, stpcpy, hwcap & PPC_FEATURE_HAS_VSX, +diff --git a/sysdeps/powerpc/powerpc64/multiarch/stpcpy-power9.S b/sysdeps/powerpc/powerpc64/multiarch/stpcpy-power9.S +new file mode 100644 +index 0000000000000000..a728d49fd2575e00 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/stpcpy-power9.S +@@ -0,0 +1,24 @@ ++/* Optimized stpcpy implementation for POWER9/PPC64. ++ Copyright (C) 2015-2020 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 ++ . */ ++ ++#define STPCPY __stpcpy_power9 ++ ++#undef libc_hidden_builtin_def ++#define libc_hidden_builtin_def(name) ++ ++#include +diff --git a/sysdeps/powerpc/powerpc64/multiarch/stpcpy.c b/sysdeps/powerpc/powerpc64/multiarch/stpcpy.c +index 34c889644133d757..8ce58572e0f27c7f 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/stpcpy.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/stpcpy.c +@@ -26,13 +26,20 @@ + extern __typeof (__stpcpy) __stpcpy_ppc attribute_hidden; + extern __typeof (__stpcpy) __stpcpy_power7 attribute_hidden; + extern __typeof (__stpcpy) __stpcpy_power8 attribute_hidden; ++# ifdef __LITTLE_ENDIAN__ ++extern __typeof (__stpcpy) __stpcpy_power9 attribute_hidden; ++# endif + + libc_ifunc_hidden (__stpcpy, __stpcpy, +- (hwcap2 & PPC_FEATURE2_ARCH_2_07) +- ? __stpcpy_power8 +- : (hwcap & PPC_FEATURE_HAS_VSX) +- ? __stpcpy_power7 +- : __stpcpy_ppc); ++# ifdef __LITTLE_ENDIAN__ ++ (hwcap2 & PPC_FEATURE2_ARCH_3_00) ++ ? __stpcpy_power9 : ++# endif ++ (hwcap2 & PPC_FEATURE2_ARCH_2_07) ++ ? __stpcpy_power8 ++ : (hwcap & PPC_FEATURE_HAS_VSX) ++ ? __stpcpy_power7 ++ : __stpcpy_ppc); + + weak_alias (__stpcpy, stpcpy) + libc_hidden_def (__stpcpy) diff --git a/glibc-rh1871387-4.patch b/glibc-rh1871387-4.patch new file mode 100755 index 0000000..1161362 --- /dev/null +++ b/glibc-rh1871387-4.patch @@ -0,0 +1,213 @@ +commit 765de945efc5d5602999b2999fe8abdf04881370 +Author: Anton Blanchard +Date: Thu May 14 21:49:16 2020 +1000 + + powerpc: Optimized rawmemchr for POWER9 + + This version uses vector instructions and is up to 60% faster on medium + matches and up to 90% faster on long matches, compared to the POWER7 + version. A few examples: + + __rawmemchr_power9 __rawmemchr_power7 + Length 32, alignment 0: 2.27566 3.77765 + Length 64, alignment 2: 2.46231 3.51064 + Length 1024, alignment 0: 17.3059 32.6678 + +diff --git a/sysdeps/powerpc/powerpc64/le/power9/rawmemchr.S b/sysdeps/powerpc/powerpc64/le/power9/rawmemchr.S +new file mode 100644 +index 0000000000000000..9d0276c9315af5c8 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power9/rawmemchr.S +@@ -0,0 +1,107 @@ ++/* Optimized rawmemchr implementation for PowerPC64/POWER9. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++ ++#ifndef RAWMEMCHR ++# define RAWMEMCHR __rawmemchr ++#endif ++ ++/* Implements the function ++ ++ int [r3] rawmemchr (void *s [r3], int c [r4]) ++ ++ The implementation can load bytes past a matching byte, but only ++ up to the next 16B boundary, so it never crosses a page. */ ++ ++.machine power9 ++ENTRY_TOCLESS (RAWMEMCHR, 4) ++ CALL_MCOUNT 2 ++ ++ xori r5,r4,0xff ++ ++ mtvsrd v18+32,r4 /* matching char in v18 */ ++ mtvsrd v19+32,r5 /* non matching char in v19 */ ++ ++ vspltb v18,v18,7 /* replicate */ ++ vspltb v19,v19,7 /* replicate */ ++ ++ neg r5,r3 ++ rldicl r9,r5,0,60 /* How many bytes to get source 16B aligned? */ ++ ++ /* Align data and fill bytes not loaded with non matching char */ ++ lvx v0,0,r3 ++ lvsr v1,0,r3 ++ vperm v0,v19,v0,v1 ++ ++ vcmpequb. v6,v0,v18 /* 0xff if byte matches, 0x00 otherwise */ ++ beq cr6,L(aligned) ++ ++ vctzlsbb r0,v6 ++ add r3,r3,r0 ++ blr ++ ++L(aligned): ++ add r3,r3,r9 ++ ++L(loop): ++ lxv v0+32,0(r3) ++ vcmpequb. v6,v0,v18 /* 0xff if byte matches, 0x00 otherwise */ ++ bne cr6,L(tail1) ++ ++ lxv v0+32,16(r3) ++ vcmpequb. v6,v0,v18 /* 0xff if byte matches, 0x00 otherwise */ ++ bne cr6,L(tail2) ++ ++ lxv v0+32,32(r3) ++ vcmpequb. v6,v0,v18 /* 0xff if byte matches, 0x00 otherwise */ ++ bne cr6,L(tail3) ++ ++ lxv v0+32,48(r3) ++ vcmpequb. v6,v0,v18 /* 0xff if byte matches, 0x00 otherwise */ ++ bne cr6,L(tail4) ++ ++ addi r3,r3,64 ++ b L(loop) ++ ++L(tail1): ++ vctzlsbb r0,v6 ++ add r3,r3,r0 ++ blr ++ ++L(tail2): ++ vctzlsbb r0,v6 ++ add r3,r3,r0 ++ addi r3,r3,16 ++ blr ++ ++L(tail3): ++ vctzlsbb r0,v6 ++ add r3,r3,r0 ++ addi r3,r3,32 ++ blr ++ ++L(tail4): ++ vctzlsbb r0,v6 ++ add r3,r3,r0 ++ addi r3,r3,48 ++ blr ++ ++END (RAWMEMCHR) ++weak_alias (__rawmemchr,rawmemchr) ++libc_hidden_builtin_def (__rawmemchr) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index cada6b19bf3c8fab..1a8ef5fb73c3b0db 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -32,7 +32,8 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + strncase-power8 + + ifneq (,$(filter %le,$(config-machine))) +-sysdep_routines += strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 ++sysdep_routines += strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 \ ++ rawmemchr-power9 + endif + CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops + CFLAGS-strncase_l-power7.c += -mcpu=power7 -funroll-loops +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index b0abc6b61dc15f19..297935863e44c0e1 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -216,6 +216,11 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c. */ + IFUNC_IMPL (i, name, rawmemchr, ++#ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, rawmemchr, ++ hwcap2 & PPC_FEATURE2_ARCH_3_00, ++ __rawmemchr_power9) ++#endif + IFUNC_IMPL_ADD (array, i, rawmemchr, + hwcap & PPC_FEATURE_HAS_VSX, + __rawmemchr_power7) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/rawmemchr-power9.S b/sysdeps/powerpc/powerpc64/multiarch/rawmemchr-power9.S +new file mode 100644 +index 0000000000000000..bac0a9090e7a07f8 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/rawmemchr-power9.S +@@ -0,0 +1,21 @@ ++/* Optimized rawmemchr implementation for PowerPC64/POWER9. ++ Copyright (C) 2020 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 ++ . */ ++ ++#define RAWMEMCHR __rawmemchr_power9 ++ ++#include +diff --git a/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c b/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c +index 02bac49b53d52411..2a7ae5a1ed02e556 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c +@@ -24,13 +24,21 @@ + + extern __typeof (__rawmemchr) __rawmemchr_ppc attribute_hidden; + extern __typeof (__rawmemchr) __rawmemchr_power7 attribute_hidden; ++# ifdef __LITTLE_ENDIAN__ ++extern __typeof (__rawmemchr) __rawmemchr_power9 attribute_hidden; ++# endif ++ + # undef __rawmemchr + + /* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle + ifunc symbol properly. */ + libc_ifunc_redirected (__redirect___rawmemchr, __rawmemchr, +- (hwcap & PPC_FEATURE_HAS_VSX) +- ? __rawmemchr_power7 ++# ifdef __LITTLE_ENDIAN__ ++ (hwcap2 & PPC_FEATURE2_ARCH_3_00) ++ ? __rawmemchr_power9 : ++# endif ++ (hwcap & PPC_FEATURE_HAS_VSX) ++ ? __rawmemchr_power7 + : __rawmemchr_ppc); + + weak_alias (__rawmemchr, rawmemchr) diff --git a/glibc-rh1871387-5.patch b/glibc-rh1871387-5.patch new file mode 100755 index 0000000..8190aed --- /dev/null +++ b/glibc-rh1871387-5.patch @@ -0,0 +1,300 @@ +commit a23bd00f9d810c28d9e83ce1d7cf53968375937d +Author: Paul E. Murphy +Date: Mon May 18 11:16:06 2020 -0500 + + powerpc64le: add optimized strlen for P9 + + This started as a trivial change to Anton's rawmemchr. I got + carried away. This is a hybrid between P8's asympotically + faster 64B checks with extremely efficient small string checks + e.g <64B (and sometimes a little bit more depending on alignment). + + The second trick is to align to 64B by running a 48B checking loop + 16B at a time until we naturally align to 64B (i.e checking 48/96/144 + bytes/iteration based on the alignment after the first 5 comparisons). + This allieviates the need to check page boundaries. + + Finally, explicly use the P7 strlen with the runtime loader when building + P9. We need to be cautious about vector/vsx extensions here on P9 only + builds. + +diff --git a/sysdeps/powerpc/powerpc64/le/power9/rtld-strlen.S b/sysdeps/powerpc/powerpc64/le/power9/rtld-strlen.S +new file mode 100644 +index 0000000000000000..e9d83323acacfbca +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power9/rtld-strlen.S +@@ -0,0 +1 @@ ++#include +diff --git a/sysdeps/powerpc/powerpc64/le/power9/strlen.S b/sysdeps/powerpc/powerpc64/le/power9/strlen.S +new file mode 100644 +index 0000000000000000..66a9b79647eebbd8 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power9/strlen.S +@@ -0,0 +1,213 @@ ++/* Optimized strlen implementation for PowerPC64/POWER9. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++ ++#ifndef STRLEN ++# define STRLEN __strlen ++# define DEFINE_STRLEN_HIDDEN_DEF 1 ++#endif ++ ++/* Implements the function ++ ++ int [r3] strlen (const void *s [r3]) ++ ++ The implementation can load bytes past a matching byte, but only ++ up to the next 64B boundary, so it never crosses a page. */ ++ ++.machine power9 ++ENTRY_TOCLESS (STRLEN, 4) ++ CALL_MCOUNT 2 ++ ++ vspltisb v18,0 ++ vspltisb v19,-1 ++ ++ neg r5,r3 ++ rldicl r9,r5,0,60 /* How many bytes to get source 16B aligned? */ ++ ++ /* Align data and fill bytes not loaded with non matching char. */ ++ lvx v0,0,r3 ++ lvsr v1,0,r3 ++ vperm v0,v19,v0,v1 ++ ++ vcmpequb. v6,v0,v18 ++ beq cr6,L(aligned) ++ ++ vctzlsbb r3,v6 ++ blr ++ ++ /* Test 64B 16B at a time. The 64B vector loop is optimized for ++ longer strings. Likewise, we check a multiple of 64B to avoid ++ breaking the alignment calculation below. */ ++L(aligned): ++ add r4,r3,r9 ++ rldicl. r5,r4,60,62 /* Determine the number of 48B loops needed for ++ alignment to 64B. And test for zero. */ ++ ++ lxv v0+32,0(r4) ++ vcmpequb. v6,v0,v18 ++ bne cr6,L(tail1) ++ ++ lxv v0+32,16(r4) ++ vcmpequb. v6,v0,v18 ++ bne cr6,L(tail2) ++ ++ lxv v0+32,32(r4) ++ vcmpequb. v6,v0,v18 ++ bne cr6,L(tail3) ++ ++ lxv v0+32,48(r4) ++ vcmpequb. v6,v0,v18 ++ bne cr6,L(tail4) ++ addi r4,r4,64 ++ ++ /* Speculatively generate a fake 16B aligned address to generate the ++ vector byte constant 0,1,..,15 using lvsl during reduction. */ ++ li r0,0 ++ ++ /* Skip the alignment if already 64B aligned. */ ++ beq L(loop_64b) ++ mtctr r5 ++ ++ /* Test 48B per iteration until 64B aligned. */ ++ .p2align 5 ++L(loop): ++ lxv v0+32,0(r4) ++ vcmpequb. v6,v0,v18 ++ bne cr6,L(tail1) ++ ++ lxv v0+32,16(r4) ++ vcmpequb. v6,v0,v18 ++ bne cr6,L(tail2) ++ ++ lxv v0+32,32(r4) ++ vcmpequb. v6,v0,v18 ++ bne cr6,L(tail3) ++ ++ addi r4,r4,48 ++ bdnz L(loop) ++ ++ .p2align 5 ++L(loop_64b): ++ lxv v1+32,0(r4) /* Load 4 quadwords. */ ++ lxv v2+32,16(r4) ++ lxv v3+32,32(r4) ++ lxv v4+32,48(r4) ++ vminub v5,v1,v2 /* Compare and merge into one VR for speed. */ ++ vminub v6,v3,v4 ++ vminub v7,v5,v6 ++ vcmpequb. v7,v7,v18 /* Check for NULLs. */ ++ addi r4,r4,64 /* Adjust address for the next iteration. */ ++ bne cr6,L(vmx_zero) ++ ++ lxv v1+32,0(r4) /* Load 4 quadwords. */ ++ lxv v2+32,16(r4) ++ lxv v3+32,32(r4) ++ lxv v4+32,48(r4) ++ vminub v5,v1,v2 /* Compare and merge into one VR for speed. */ ++ vminub v6,v3,v4 ++ vminub v7,v5,v6 ++ vcmpequb. v7,v7,v18 /* Check for NULLs. */ ++ addi r4,r4,64 /* Adjust address for the next iteration. */ ++ bne cr6,L(vmx_zero) ++ ++ lxv v1+32,0(r4) /* Load 4 quadwords. */ ++ lxv v2+32,16(r4) ++ lxv v3+32,32(r4) ++ lxv v4+32,48(r4) ++ vminub v5,v1,v2 /* Compare and merge into one VR for speed. */ ++ vminub v6,v3,v4 ++ vminub v7,v5,v6 ++ vcmpequb. v7,v7,v18 /* Check for NULLs. */ ++ addi r4,r4,64 /* Adjust address for the next iteration. */ ++ beq cr6,L(loop_64b) ++ ++L(vmx_zero): ++ /* OK, we found a null byte. Let's look for it in the current 64-byte ++ block and mark it in its corresponding VR. */ ++ vcmpequb v1,v1,v18 ++ vcmpequb v2,v2,v18 ++ vcmpequb v3,v3,v18 ++ vcmpequb v4,v4,v18 ++ ++ /* We will now 'compress' the result into a single doubleword, so it ++ can be moved to a GPR for the final calculation. First, we ++ generate an appropriate mask for vbpermq, so we can permute bits into ++ the first halfword. */ ++ vspltisb v10,3 ++ lvsl v11,0,r0 ++ vslb v10,v11,v10 ++ ++ /* Permute the first bit of each byte into bits 48-63. */ ++ vbpermq v1,v1,v10 ++ vbpermq v2,v2,v10 ++ vbpermq v3,v3,v10 ++ vbpermq v4,v4,v10 ++ ++ /* Shift each component into its correct position for merging. */ ++ vsldoi v2,v2,v2,2 ++ vsldoi v3,v3,v3,4 ++ vsldoi v4,v4,v4,6 ++ ++ /* Merge the results and move to a GPR. */ ++ vor v1,v2,v1 ++ vor v2,v3,v4 ++ vor v4,v1,v2 ++ mfvrd r10,v4 ++ ++ /* Adjust address to the begninning of the current 64-byte block. */ ++ addi r4,r4,-64 ++ ++ cnttzd r0,r10 /* Count trailing zeros before the match. */ ++ subf r5,r3,r4 ++ add r3,r5,r0 /* Compute final length. */ ++ blr ++ ++L(tail1): ++ vctzlsbb r0,v6 ++ add r4,r4,r0 ++ subf r3,r3,r4 ++ blr ++ ++L(tail2): ++ vctzlsbb r0,v6 ++ add r4,r4,r0 ++ addi r4,r4,16 ++ subf r3,r3,r4 ++ blr ++ ++L(tail3): ++ vctzlsbb r0,v6 ++ add r4,r4,r0 ++ addi r4,r4,32 ++ subf r3,r3,r4 ++ blr ++ ++L(tail4): ++ vctzlsbb r0,v6 ++ add r4,r4,r0 ++ addi r4,r4,48 ++ subf r3,r3,r4 ++ blr ++ ++END (STRLEN) ++ ++#ifdef DEFINE_STRLEN_HIDDEN_DEF ++weak_alias (__strlen, strlen) ++libc_hidden_builtin_def (strlen) ++#endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index 1a8ef5fb73c3b0db..6d5661d08257b7a0 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -33,7 +33,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + + ifneq (,$(filter %le,$(config-machine))) + sysdep_routines += strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 \ +- rawmemchr-power9 ++ rawmemchr-power9 strlen-power9 + endif + CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops + CFLAGS-strncase_l-power7.c += -mcpu=power7 -funroll-loops +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 297935863e44c0e1..daa30d3907395680 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -111,6 +111,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/powerpc/powerpc64/multiarch/strlen.c. */ + IFUNC_IMPL (i, name, strlen, ++#ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, strcpy, hwcap2 & PPC_FEATURE2_ARCH_3_00, ++ __strlen_power9) ++#endif + IFUNC_IMPL_ADD (array, i, strlen, hwcap2 & PPC_FEATURE2_ARCH_2_07, + __strlen_power8) + IFUNC_IMPL_ADD (array, i, strlen, hwcap & PPC_FEATURE_HAS_VSX, +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strlen-power9.S b/sysdeps/powerpc/powerpc64/multiarch/strlen-power9.S +new file mode 100644 +index 0000000000000000..68c8d54b5f5876a2 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/strlen-power9.S +@@ -0,0 +1,2 @@ ++#define STRLEN __strlen_power9 ++#include +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strlen.c b/sysdeps/powerpc/powerpc64/multiarch/strlen.c +index 74810dab9929d505..b7f0fbb13fb97783 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/strlen.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/strlen.c +@@ -30,8 +30,13 @@ extern __typeof (__redirect_strlen) __libc_strlen; + extern __typeof (__redirect_strlen) __strlen_ppc attribute_hidden; + extern __typeof (__redirect_strlen) __strlen_power7 attribute_hidden; + extern __typeof (__redirect_strlen) __strlen_power8 attribute_hidden; ++extern __typeof (__redirect_strlen) __strlen_power9 attribute_hidden; + + libc_ifunc (__libc_strlen, ++# ifdef __LITTLE_ENDIAN__ ++ (hwcap2 & PPC_FEATURE2_ARCH_3_00) ++ ? __strlen_power9 : ++# endif + (hwcap2 & PPC_FEATURE2_ARCH_2_07) + ? __strlen_power8 : + (hwcap & PPC_FEATURE_HAS_VSX) diff --git a/glibc-rh1871387-6.patch b/glibc-rh1871387-6.patch new file mode 100755 index 0000000..e05901b --- /dev/null +++ b/glibc-rh1871387-6.patch @@ -0,0 +1,31 @@ +commit 07f3ecdba69c5190180112c25757040c69041bb9 +Author: Raphael Moreira Zinsly +Date: Thu Sep 17 11:16:36 2020 -0300 + + powerpc: fix ifunc implementation list for POWER9 strlen and stpcpy + + __strlen_power9 and __stpcpy_power9 were added to their ifunc lists + using the wrong function names. + +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index daa30d3907395680..e622ab4d47548146 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -99,7 +99,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/powerpc/powerpc64/multiarch/stpcpy.c. */ + IFUNC_IMPL (i, name, stpcpy, + #ifdef __LITTLE_ENDIAN__ +- IFUNC_IMPL_ADD (array, i, strncmp, hwcap2 & PPC_FEATURE2_ARCH_3_00, ++ IFUNC_IMPL_ADD (array, i, stpcpy, hwcap2 & PPC_FEATURE2_ARCH_3_00, + __stpcpy_power9) + #endif + IFUNC_IMPL_ADD (array, i, stpcpy, hwcap2 & PPC_FEATURE2_ARCH_2_07, +@@ -112,7 +112,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/powerpc/powerpc64/multiarch/strlen.c. */ + IFUNC_IMPL (i, name, strlen, + #ifdef __LITTLE_ENDIAN__ +- IFUNC_IMPL_ADD (array, i, strcpy, hwcap2 & PPC_FEATURE2_ARCH_3_00, ++ IFUNC_IMPL_ADD (array, i, strlen, hwcap2 & PPC_FEATURE2_ARCH_3_00, + __strlen_power9) + #endif + IFUNC_IMPL_ADD (array, i, strlen, hwcap2 & PPC_FEATURE2_ARCH_2_07, diff --git a/glibc-rh1871394-1.patch b/glibc-rh1871394-1.patch new file mode 100755 index 0000000..bc36d64 --- /dev/null +++ b/glibc-rh1871394-1.patch @@ -0,0 +1,47 @@ +commit 75870237ff3bb363447b03f4b0af100227570910 +Author: Sunil K Pandey +Date: Fri Jun 12 08:57:16 2020 -0700 + + Fix avx2 strncmp offset compare condition check [BZ #25933] + + strcmp-avx2.S: In avx2 strncmp function, strings are compared in + chunks of 4 vector size(i.e. 32x4=128 byte for avx2). After first 4 + vector size comparison, code must check whether it already passed + the given offset. This patch implement avx2 offset check condition + for strncmp function, if both string compare same for first 4 vector + size. + +diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S +index 5f88a68262..d42b04b54f 100644 +--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S ++++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S +@@ -591,7 +591,14 @@ L(loop_cross_page_2_vec): + movl $(PAGE_SIZE / (VEC_SIZE * 4) - 1), %esi + + testq %rdi, %rdi ++# ifdef USE_AS_STRNCMP ++ /* At this point, if %rdi value is 0, it already tested ++ VEC_SIZE*4+%r10 byte starting from %rax. This label ++ checks whether strncmp maximum offset reached or not. */ ++ je L(string_nbyte_offset_check) ++# else + je L(back_to_loop) ++# endif + tzcntq %rdi, %rcx + addq %r10, %rcx + /* Adjust for number of bytes skipped. */ +@@ -627,6 +634,14 @@ L(loop_cross_page_2_vec): + VZEROUPPER + ret + ++# ifdef USE_AS_STRNCMP ++L(string_nbyte_offset_check): ++ leaq (VEC_SIZE * 4)(%r10), %r10 ++ cmpq %r10, %r11 ++ jbe L(zero) ++ jmp L(back_to_loop) ++# endif ++ + .p2align 4 + L(cross_page_loop): + /* Check one byte/dword at a time. */ diff --git a/glibc-rh1871394-2.patch b/glibc-rh1871394-2.patch new file mode 100755 index 0000000..11ae1e3 --- /dev/null +++ b/glibc-rh1871394-2.patch @@ -0,0 +1,69 @@ +commit f7e3f92b7c45663be808279a43b5221c16001229 +Author: H.J. Lu +Date: Thu May 7 07:29:46 2020 -0700 + + strncmp: Add a testcase for page boundary [BZ #25933] + + Add a strncmp testcase to cover cases where one of strings ends on the + page boundary with the maximum string length less than the number bytes + of each AVX2 loop iteration and different offsets from page boundary. + + The updated string/test-strncmp fails on Intel Core i7-8559U without + + ommit 1c6432316bc434a72108d7b0c7cfbfdde64c3124 + Author: Sunil K Pandey + Date: Fri Jun 12 08:57:16 2020 -0700 + + Fix avx2 strncmp offset compare condition check [BZ #25933] + +diff --git a/string/test-strncmp.c b/string/test-strncmp.c +index d961ac4493..962679b384 100644 +--- a/string/test-strncmp.c ++++ b/string/test-strncmp.c +@@ -403,6 +403,38 @@ check2 (void) + free (s2); + } + ++static void ++check3 (void) ++{ ++ /* To trigger bug 25933, we need a size that is equal to the vector ++ length times 4. In the case of AVX2 for Intel, we need 32 * 4. We ++ make this test generic and run it for all architectures as additional ++ boundary testing for such related algorithms. */ ++ size_t size = 32 * 4; ++ CHAR *s1 = (CHAR *) (buf1 + (BUF1PAGES - 1) * page_size); ++ CHAR *s2 = (CHAR *) (buf2 + (BUF1PAGES - 1) * page_size); ++ int exp_result; ++ ++ memset (s1, 'a', page_size); ++ memset (s2, 'a', page_size); ++ s1[(page_size / CHARBYTES) - 1] = (CHAR) 0; ++ ++ /* Iterate over a size that is just below where we expect the bug to ++ trigger up to the size we expect will trigger the bug e.g. [99-128]. ++ Likewise iterate the start of two strings between 30 and 31 bytes ++ away from the boundary to simulate alignment changes. */ ++ for (size_t s = 99; s <= size; s++) ++ for (size_t s1a = 30; s1a < 32; s1a++) ++ for (size_t s2a = 30; s2a < 32; s2a++) ++ { ++ CHAR *s1p = s1 + (page_size / CHARBYTES - s) - s1a; ++ CHAR *s2p = s2 + (page_size / CHARBYTES - s) - s2a; ++ exp_result = SIMPLE_STRNCMP (s1p, s2p, s); ++ FOR_EACH_IMPL (impl, 0) ++ check_result (impl, s1p, s2p, s, exp_result); ++ } ++} ++ + int + test_main (void) + { +@@ -412,6 +444,7 @@ test_main (void) + + check1 (); + check2 (); ++ check3 (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) diff --git a/glibc-rh1871394-3.patch b/glibc-rh1871394-3.patch new file mode 100755 index 0000000..fd47aff --- /dev/null +++ b/glibc-rh1871394-3.patch @@ -0,0 +1,60 @@ +commit 659c0411880328ed341ca26b43d069ec5269a8b5 +Author: H.J. Lu +Date: Thu Jun 11 09:03:56 2020 -0700 + + strcmp: Add a testcase for page boundary + + Add a strcmp testcase to cover cases where both strings end on the page + boundary. + +diff --git a/string/test-strcmp.c b/string/test-strcmp.c +index 8d4784de80..6a840fc04b 100644 +--- a/string/test-strcmp.c ++++ b/string/test-strcmp.c +@@ -359,6 +359,38 @@ check (void) + } + } + ++static void ++check2 (void) ++{ ++ /* To trigger bug 25933, we need a size that is equal to the vector ++ length times 4. In the case of AVX2 for Intel, we need 32 * 4. We ++ make this test generic and run it for all architectures as additional ++ boundary testing for such related algorithms. */ ++ size_t size = 32 * 4; ++ CHAR *s1 = (CHAR *) (buf1 + (BUF1PAGES - 1) * page_size); ++ CHAR *s2 = (CHAR *) (buf2 + (BUF1PAGES - 1) * page_size); ++ int exp_result; ++ ++ memset (s1, 'a', page_size); ++ memset (s2, 'a', page_size); ++ s1[(page_size / CHARBYTES) - 1] = (CHAR) 0; ++ s2[(page_size / CHARBYTES) - 1] = (CHAR) 0; ++ ++ /* Iterate over a size that is just below where we expect the bug to ++ trigger up to the size we expect will trigger the bug e.g. [99-128]. ++ Likewise iterate the start of two strings between 30 and 31 bytes ++ away from the boundary to simulate alignment changes. */ ++ for (size_t s = 99; s <= size; s++) ++ for (size_t s1a = 30; s1a < 32; s1a++) ++ for (size_t s2a = 30; s2a < 32; s2a++) ++ { ++ CHAR *s1p = s1 + (page_size / CHARBYTES - s) - s1a; ++ CHAR *s2p = s2 + (page_size / CHARBYTES - s) - s2a; ++ exp_result = SIMPLE_STRCMP (s1p, s2p); ++ FOR_EACH_IMPL (impl, 0) ++ check_result (impl, s1p, s2p, exp_result); ++ } ++} + + int + test_main (void) +@@ -367,6 +399,7 @@ test_main (void) + + test_init (); + check(); ++ check2 (); + + printf ("%23s", ""); + FOR_EACH_IMPL (impl, 0) diff --git a/glibc-rh1871395-1.patch b/glibc-rh1871395-1.patch new file mode 100755 index 0000000..8f87702 --- /dev/null +++ b/glibc-rh1871395-1.patch @@ -0,0 +1,55 @@ +commit 0792c8ae1aebf538de45ff9a0e2e401a60525de2 +Author: Stefan Liebler +Date: Fri Jun 26 09:45:11 2020 +0200 + + S390: Optimize __memcpy_z196. + + This patch introduces an extra loop without pfd instructions + as it turned out that the pfd instructions are usefull + for copies >=64KB but are counterproductive for smaller copies. + +diff --git a/sysdeps/s390/memcpy-z900.S b/sysdeps/s390/memcpy-z900.S +index f2e9aaeb2d..dc2f491ec3 100644 +--- a/sysdeps/s390/memcpy-z900.S ++++ b/sysdeps/s390/memcpy-z900.S +@@ -184,25 +184,34 @@ ENTRY(MEMCPY_Z196) + je .L_Z196_4 + .L_Z196_start2: + aghi %r4,-1 +- srlg %r5,%r4,8 +- ltgr %r5,%r5 ++ risbg %r5,%r4,8,128+63,56 # r0 = r5 / 256 + jne .L_Z196_5 + .L_Z196_3: + exrl %r4,.L_Z196_14 + .L_Z196_4: + br %r14 + .L_Z196_5: +- cgfi %r5,262144 # Switch to mvcle for copies >64MB +- jh __memcpy_mvcle ++ cgfi %r5,255 # Switch to loop with pfd for copies >=64kB ++ jh .L_Z196_6 + .L_Z196_2: +- pfd 1,768(%r3) +- pfd 2,768(%r1) + mvc 0(256,%r1),0(%r3) + aghi %r5,-1 + la %r1,256(%r1) + la %r3,256(%r3) + jne .L_Z196_2 + j .L_Z196_3 ++.L_Z196_6: ++ cgfi %r5,262144 # Switch to mvcle for copies >64MB ++ jh __memcpy_mvcle ++.L_Z196_7: ++ pfd 1,1024(%r3) ++ pfd 2,1024(%r1) ++ mvc 0(256,%r1),0(%r3) ++ aghi %r5,-1 ++ la %r1,256(%r1) ++ la %r3,256(%r3) ++ jne .L_Z196_7 ++ j .L_Z196_3 + .L_Z196_14: + mvc 0(1,%r1),0(%r3) + END(MEMCPY_Z196) diff --git a/glibc-rh1871395-2.patch b/glibc-rh1871395-2.patch new file mode 100755 index 0000000..d215b5f --- /dev/null +++ b/glibc-rh1871395-2.patch @@ -0,0 +1,54 @@ +commit 1d21fb1061cbeb50414a8f371abb36548d90f150 +Author: Stefan Liebler +Date: Fri Jun 26 09:45:11 2020 +0200 + + S390: Optimize __memset_z196. + + It turned out that an 256b-mvc instruction which depends on the + result of a previous 256b-mvc instruction is counterproductive. + Therefore this patch adjusts the 256b-loop by storing the + first byte with stc and setting the remaining 255b with mvc. + Now the 255b-mvc instruction depends on the stc instruction. + +diff --git a/sysdeps/s390/memset-z900.S b/sysdeps/s390/memset-z900.S +index ca3eac0522..1e0c334156 100644 +--- a/sysdeps/s390/memset-z900.S ++++ b/sysdeps/s390/memset-z900.S +@@ -157,28 +157,27 @@ ENTRY(MEMSET_Z196) + # if !defined __s390x__ + llgfr %r4,%r4 + # endif /* !defined __s390x__ */ +- ltgr %r4,%r4 +- je .L_Z196_4 ++ clgfi %r4,1 ++ jl .L_Z196_4 # n == 0 + stc %r3,0(%r2) ++ je .L_Z196_4 # n == 1 ++ aghi %r4,-2 + lgr %r1,%r2 +- cghi %r4,1 +- je .L_Z196_4 +- aghi %r4,-2 +- srlg %r5,%r4,8 +- ltgr %r5,%r5 +- jne .L_Z196_1 ++ risbg %r5,%r4,8,128+63,56 # r5 = n / 256 ++ jne .L_Z196_1 # Jump away if r5 != 0 + .L_Z196_3: + exrl %r4,.L_Z196_17 + .L_Z196_4: + br %r14 + .L_Z196_1: + cgfi %r5,1048576 +- jh __memset_mvcle # Switch to mvcle for >256MB ++ jh __memset_mvcle # Switch to mvcle for >256MB + .L_Z196_2: + pfd 2,1024(%r1) +- mvc 1(256,%r1),0(%r1) ++ mvc 1(255,%r1),0(%r1) + aghi %r5,-1 + la %r1,256(%r1) ++ stc %r3,0(%r1) + jne .L_Z196_2 + j .L_Z196_3 + .L_Z196_17: diff --git a/glibc-rh1871397-1.patch b/glibc-rh1871397-1.patch new file mode 100755 index 0000000..bf1e46a --- /dev/null +++ b/glibc-rh1871397-1.patch @@ -0,0 +1,233 @@ +From 299210c1fa67e2dfb564475986fce11cd33db9ad Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 16:12:46 +0200 +Subject: [PATCH 01/11] nss_files: Consolidate file opening in + __nss_files_fopen + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + include/nss_files.h | 28 ++++++++++++++++++++++++ + nss/Makefile | 2 +- + nss/Versions | 1 + + nss/nss_files/files-XXX.c | 3 ++- + nss/nss_files/files-alias.c | 5 +++-- + nss/nss_files/files-initgroups.c | 6 ++--- + nss/nss_files/files-netgrp.c | 5 ++--- + nss/nss_files_fopen.c | 47 ++++++++++++++++++++++++++++++++++++++++ + 8 files changed, 86 insertions(+), 11 deletions(-) + create mode 100644 include/nss_files.h + create mode 100644 nss/nss_files_fopen.c + +diff -rupN a/include/nss_files.h b/include/nss_files.h +--- a/include/nss_files.h 1969-12-31 19:00:00.000000000 -0500 ++++ b/include/nss_files.h 2020-09-11 21:28:42.027034988 -0400 +@@ -0,0 +1,28 @@ ++/* Internal routines for nss_files. ++ Copyright (C) 2020 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 ++ . */ ++ ++#ifndef _NSS_FILES_H ++#define _NSS_FILES_H ++ ++#include ++ ++/* Open PATH for reading, as a data source for nss_files. */ ++FILE *__nss_files_fopen (const char *path); ++libc_hidden_proto (__nss_files_fopen) ++ ++#endif /* _NSS_FILES_H */ +diff -rupN a/nss/Makefile b/nss/Makefile +--- a/nss/Makefile 2020-09-11 21:24:05.569544894 -0400 ++++ b/nss/Makefile 2020-09-11 21:28:42.035035292 -0400 +@@ -28,7 +28,7 @@ headers := nss.h + routines = nsswitch getnssent getnssent_r digits_dots \ + valid_field valid_list_field rewrite_field \ + $(addsuffix -lookup,$(databases)) \ +- compat-lookup nss_hash ++ compat-lookup nss_hash nss_files_fopen + + # These are the databases that go through nss dispatch. + # Caution: if you add a database here, you must add its real name +diff -rupN a/nss/Versions b/nss/Versions +--- a/nss/Versions 2020-09-11 21:24:04.852517683 -0400 ++++ b/nss/Versions 2020-09-11 21:28:42.041035519 -0400 +@@ -21,6 +21,7 @@ libc { + __nss_passwd_lookup2; __nss_group_lookup2; __nss_hosts_lookup2; + __nss_services_lookup2; __nss_next2; __nss_lookup; + __nss_hash; __nss_database_lookup2; ++ __nss_files_fopen; + } + } + +diff -rupN a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c +--- a/nss/nss_files/files-XXX.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/nss_files/files-XXX.c 2020-09-11 21:28:42.049035823 -0400 +@@ -22,6 +22,7 @@ + #include + #include + #include "nsswitch.h" ++#include + + #include + +@@ -74,7 +75,7 @@ internal_setent (FILE **stream) + + if (*stream == NULL) + { +- *stream = fopen (DATAFILE, "rce"); ++ *stream = __nss_files_fopen (DATAFILE); + + if (*stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; +diff -rupN a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c +--- a/nss/nss_files/files-alias.c 2020-09-11 21:24:02.004409596 -0400 ++++ b/nss/nss_files/files-alias.c 2020-09-11 21:28:42.055036051 -0400 +@@ -29,6 +29,7 @@ + #include + + #include "nsswitch.h" ++#include + + /* Locks the static variables in this file. */ + __libc_lock_define_initialized (static, lock) +@@ -47,7 +48,7 @@ internal_setent (FILE **stream) + + if (*stream == NULL) + { +- *stream = fopen ("/etc/aliases", "rce"); ++ *stream = __nss_files_fopen ("/etc/aliases"); + + if (*stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; +@@ -213,7 +214,7 @@ get_next_alias (FILE *stream, const char + + first_unused = cp; + +- listfile = fopen (&cp[9], "rce"); ++ listfile = __nss_files_fopen (&cp[9]); + /* If the file does not exist we simply ignore + the statement. */ + if (listfile != NULL +diff -rupN a/nss/nss_files/files-initgroups.c b/nss/nss_files/files-initgroups.c +--- a/nss/nss_files/files-initgroups.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/nss_files/files-initgroups.c 2020-09-11 22:08:25.130740010 -0400 +@@ -25,22 +25,20 @@ + #include + #include + #include ++#include + + enum nss_status + _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start, + long int *size, gid_t **groupsp, long int limit, + int *errnop) + { +- FILE *stream = fopen ("/etc/group", "rce"); ++ FILE *stream = __nss_files_fopen ("/etc/group"); + if (stream == NULL) + { + *errnop = errno; + return *errnop == ENOMEM ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + } + +- /* No other thread using this stream. */ +- __fsetlocking (stream, FSETLOCKING_BYCALLER); +- + char *line = NULL; + size_t linelen = 0; + enum nss_status status = NSS_STATUS_SUCCESS; +diff -rupN a/nss/nss_files/files-netgrp.c b/nss/nss_files/files-netgrp.c +--- a/nss/nss_files/files-netgrp.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/nss/nss_files/files-netgrp.c 2020-09-11 21:28:42.068036544 -0400 +@@ -26,6 +26,7 @@ + #include + #include "nsswitch.h" + #include "netgroup.h" ++#include + + #define DATAFILE "/etc/netgroup" + +@@ -62,7 +63,7 @@ _nss_files_setnetgrent (const char *grou + return NSS_STATUS_UNAVAIL; + + /* Find the netgroups file and open it. */ +- fp = fopen (DATAFILE, "rce"); ++ fp = __nss_files_fopen (DATAFILE); + if (fp == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + else +@@ -76,8 +77,6 @@ _nss_files_setnetgrent (const char *grou + status = NSS_STATUS_NOTFOUND; + result->cursor = result->data; + +- __fsetlocking (fp, FSETLOCKING_BYCALLER); +- + while (!feof_unlocked (fp)) + { + ssize_t curlen = getline (&line, &line_len, fp); +diff -rupN a/nss/nss_files_fopen.c b/nss/nss_files_fopen.c +--- a/nss/nss_files_fopen.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/nss/nss_files_fopen.c 2020-09-11 21:28:42.074036771 -0400 +@@ -0,0 +1,47 @@ ++/* Open an nss_files database file. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++ ++#include ++#include ++ ++FILE * ++__nss_files_fopen (const char *path) ++{ ++ FILE *fp = fopen (path, "rce"); ++ if (fp == NULL) ++ return NULL; ++ ++ /* The stream is not shared across threads. */ ++ __fsetlocking (fp, FSETLOCKING_BYCALLER); ++ ++ /* This tells libio that the file is seekable, and that fp->_offset ++ is correct, ensuring that __ftello64 is efficient (bug 26257). */ ++ if (__fseeko64 (fp, 0, SEEK_SET) < 0) ++ { ++ /* nss_files requires seekable files, to deal with repeated ++ reads of the same line after reporting ERANGE. */ ++ fclose (fp); ++ __set_errno (ESPIPE); ++ return NULL; ++ } ++ ++ return fp; ++} ++libc_hidden_def (__nss_files_fopen) diff --git a/glibc-rh1871397-10.patch b/glibc-rh1871397-10.patch new file mode 100755 index 0000000..106a868 --- /dev/null +++ b/glibc-rh1871397-10.patch @@ -0,0 +1,82 @@ +From 00bc6830e3fe3f10495917afe0835ddd19133c6a Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 17:34:43 +0200 +Subject: [PATCH 10/11] shadow: Implement fgetspent_r using __nss_fgetent_r + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + gshadow/tst-fgetsgent_r.c | 1 + + shadow/fgetspent_r.c | 43 ++++++------------------------------------- + 2 files changed, 7 insertions(+), 37 deletions(-) + +diff -rup a/gshadow/tst-fgetsgent_r.c b/gshadow/tst-fgetsgent_r.c +--- a/gshadow/tst-fgetsgent_r.c 2020-09-14 18:00:57.174146151 -0400 ++++ b/gshadow/tst-fgetsgent_r.c 2020-09-14 19:12:57.867548005 -0400 +@@ -168,6 +168,7 @@ run_test (const char *path, size_t buffe + free (result_storage); + } + ++ xfclose (fp); + return resized; + } + +diff -rup a/shadow/fgetspent_r.c b/shadow/fgetspent_r.c +--- a/shadow/fgetspent_r.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/shadow/fgetspent_r.c 2020-09-14 19:17:15.623285970 -0400 +@@ -20,9 +20,6 @@ + #include + #include + +-#define flockfile(s) _IO_flockfile (s) +-#define funlockfile(s) _IO_funlockfile (s) +- + /* Define a line parsing function using the common code + used in the nss_files module. */ + +@@ -39,39 +36,11 @@ int + __fgetspent_r (FILE *stream, struct spwd *resbuf, char *buffer, size_t buflen, + struct spwd **result) + { +- char *p; +- +- flockfile (stream); +- do +- { +- buffer[buflen - 1] = '\xff'; +- p = fgets_unlocked (buffer, buflen, stream); +- if (p == NULL && feof_unlocked (stream)) +- { +- funlockfile (stream); +- *result = NULL; +- __set_errno (ENOENT); +- return errno; +- } +- if (p == NULL || buffer[buflen - 1] != '\xff') +- { +- funlockfile (stream); +- *result = NULL; +- __set_errno (ERANGE); +- return errno; +- } +- +- /* Skip leading blanks. */ +- while (isspace (*p)) +- ++p; +- } 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, NULL, 0, &errno)); +- +- funlockfile (stream); +- +- *result = resbuf; +- return 0; ++ int ret = __nss_fgetent_r (stream, resbuf, buffer, buflen, parse_line); ++ if (ret == 0) ++ *result = resbuf; ++ else ++ *result = NULL; ++ return ret; + } + weak_alias (__fgetspent_r, fgetspent_r) diff --git a/glibc-rh1871397-11.patch b/glibc-rh1871397-11.patch new file mode 100755 index 0000000..e045949 --- /dev/null +++ b/glibc-rh1871397-11.patch @@ -0,0 +1,492 @@ +From ec2f1fddf29053957d061dfe310f106388472a4f Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Wed, 15 Jul 2020 12:37:01 +0200 +Subject: [PATCH 11/11] libio: Remove __libc_readline_unlocked + +__nss_readline supersedes it. This reverts part of commit +3f5e3f5d066dcffb80af48ae2cf35a01a85a8f10 ("libio: Implement +internal function __libc_readline_unlocked"). The internal +aliases __fseeko64 and __ftello64 are preserved because +they are needed by __nss_readline as well. + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + include/stdio.h | 13 --- + libio/Makefile | 4 +- + libio/Versions | 1 - + libio/readline.c | 170 ------------------------------------ + libio/tst-readline.c | 237 --------------------------------------------------- + 5 files changed, 2 insertions(+), 423 deletions(-) + delete mode 100644 libio/readline.c + delete mode 100644 libio/tst-readline.c + +diff -rupN a/include/stdio.h b/include/stdio.h +--- a/include/stdio.h 2020-09-14 17:48:49.359699532 -0400 ++++ b/include/stdio.h 2020-09-14 19:20:51.204429471 -0400 +@@ -135,19 +135,6 @@ extern int __fxprintf (FILE *__fp, const + extern int __fxprintf_nocancel (FILE *__fp, const char *__fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))) attribute_hidden; + +-/* Read the next line from FP into BUFFER, of LENGTH bytes. LINE will +- include the line terminator and a NUL terminator. On success, +- return the length of the line, including the line terminator, but +- excluding the NUL termintor. On EOF, return zero and write a NUL +- terminator. On error, return -1 and set errno. If the total byte +- count (line and both terminators) exceeds LENGTH, return -1 and set +- errno to ERANGE (but do not mark the stream as failed). +- +- The behavior is undefined if FP is not seekable, or if the stream +- is already in an error state. */ +-ssize_t __libc_readline_unlocked (FILE *fp, char *buffer, size_t length); +-libc_hidden_proto (__libc_readline_unlocked); +- + extern const char *const _sys_errlist_internal[] attribute_hidden; + extern int _sys_nerr_internal attribute_hidden; + +diff -rupN a/libio/Makefile b/libio/Makefile +--- a/libio/Makefile 2020-09-14 17:48:45.722562485 -0400 ++++ b/libio/Makefile 2020-09-14 19:20:51.211429735 -0400 +@@ -49,7 +49,7 @@ routines := \ + __fbufsize __freading __fwriting __freadable __fwritable __flbf \ + __fpurge __fpending __fsetlocking \ + \ +- libc_fatal fmemopen oldfmemopen vtables readline ++ libc_fatal fmemopen oldfmemopen vtables + + tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ + tst_wprintf2 tst-widetext test-fmemopen tst-ext tst-ext2 \ +@@ -67,7 +67,7 @@ tests = tst_swprintf tst_wprintf tst_sws + tst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof \ + tst-wfile-sync + +-tests-internal = tst-vtables tst-vtables-interposed tst-readline ++tests-internal = tst-vtables tst-vtables-interposed + + ifeq (yes,$(build-shared)) + # Add test-fopenloc only if shared library is enabled since it depends on +diff -rupN a/libio/Versions b/libio/Versions +--- a/libio/Versions 2018-08-01 01:10:47.000000000 -0400 ++++ b/libio/Versions 2020-09-14 19:20:51.217429962 -0400 +@@ -161,6 +161,5 @@ libc { + + __fseeko64; + __ftello64; +- __libc_readline_unlocked; + } + } +diff -rupN a/libio/readline.c b/libio/readline.c +--- a/libio/readline.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/libio/readline.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,170 +0,0 @@ +-/* fgets with ERANGE error reporting and size_t buffer length. +- Copyright (C) 2018 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 +- . */ +- +-#include +-#include +-#include +-#include +- +-#include "libioP.h" +- +-/* Return -1 and set errno to EINVAL if it is ERANGE. */ +-static ssize_t +-fail_no_erange (void) +-{ +- if (errno == ERANGE) +- __set_errno (EINVAL); +- return -1; +-} +- +-/* Slow path for reading the line. Called with no data in the stream +- read buffer. Write data to [BUFFER, BUFFER_END). */ +-static ssize_t +-readline_slow (FILE *fp, char *buffer, char *buffer_end) +-{ +- char *start = buffer; +- +- while (buffer < buffer_end) +- { +- if (__underflow (fp) == EOF) +- { +- if (_IO_ferror_unlocked (fp)) +- /* If the EOF was caused by a read error, report it. */ +- return fail_no_erange (); +- *buffer = '\0'; +- /* Do not include the null terminator. */ +- return buffer - start; +- } +- +- /* __underflow has filled the buffer. */ +- char *readptr = fp->_IO_read_ptr; +- ssize_t readlen = fp->_IO_read_end - readptr; +- /* Make sure that __underflow really has acquired some data. */ +- assert (readlen > 0); +- char *pnl = memchr (readptr, '\n', readlen); +- if (pnl != NULL) +- { +- /* We found the terminator. */ +- size_t line_length = pnl - readptr; +- if (line_length + 2 > buffer_end - buffer) +- /* Not enough room in the caller-supplied buffer. */ +- break; +- memcpy (buffer, readptr, line_length + 1); +- buffer[line_length + 1] = '\0'; +- fp->_IO_read_ptr = pnl + 1; +- /* Do not include the null terminator. */ +- return buffer - start + line_length + 1; +- } +- +- if (readlen >= buffer_end - buffer) +- /* Not enough room in the caller-supplied buffer. */ +- break; +- +- /* Save and consume the stream buffer. */ +- memcpy (buffer, readptr, readlen); +- fp->_IO_read_ptr = fp->_IO_read_end; +- buffer += readlen; +- } +- +- /* The line does not fit into the buffer. */ +- __set_errno (ERANGE); +- return -1; +-} +- +-ssize_t +-__libc_readline_unlocked (FILE *fp, char *buffer, size_t buffer_length) +-{ +- char *buffer_end = buffer + buffer_length; +- +- /* Orient the stream. */ +- if (__builtin_expect (fp->_mode, -1) == 0) +- _IO_fwide (fp, -1); +- +- /* Fast path: The line terminator is found in the buffer. */ +- char *readptr = fp->_IO_read_ptr; +- ssize_t readlen = fp->_IO_read_end - readptr; +- off64_t start_offset; /* File offset before reading anything. */ +- if (readlen > 0) +- { +- char *pnl = memchr (readptr, '\n', readlen); +- if (pnl != NULL) +- { +- size_t line_length = pnl - readptr; +- /* Account for line and null terminators. */ +- if (line_length + 2 > buffer_length) +- { +- __set_errno (ERANGE); +- return -1; +- } +- memcpy (buffer, readptr, line_length + 1); +- buffer[line_length + 1] = '\0'; +- /* Consume the entire line. */ +- fp->_IO_read_ptr = pnl + 1; +- return line_length + 1; +- } +- +- /* If the buffer does not have enough space for what is pending +- in the stream (plus a NUL terminator), the buffer is too +- small. */ +- if (readlen + 1 > buffer_length) +- { +- __set_errno (ERANGE); +- return -1; +- } +- +- /* End of line not found. We need all the buffered data. Fall +- through to the slow path. */ +- memcpy (buffer, readptr, readlen); +- buffer += readlen; +- /* The original length is invalid after this point. Use +- buffer_end instead. */ +-#pragma GCC poison buffer_length +- /* Read the old offset before updating the read pointer. */ +- start_offset = __ftello64 (fp); +- fp->_IO_read_ptr = fp->_IO_read_end; +- } +- else +- { +- readlen = 0; +- start_offset = __ftello64 (fp); +- } +- +- /* Slow path: Read more data from the underlying file. We need to +- restore the file pointer if the buffer is too small. First, +- check if the __ftello64 call above failed. */ +- if (start_offset < 0) +- return fail_no_erange (); +- +- ssize_t result = readline_slow (fp, buffer, buffer_end); +- if (result < 0) +- { +- if (errno == ERANGE) +- { +- /* Restore the file pointer so that the caller may read the +- same line again. */ +- if (__fseeko64 (fp, start_offset, SEEK_SET) < 0) +- return fail_no_erange (); +- __set_errno (ERANGE); +- } +- /* Do not restore the file position on other errors; it is +- likely that the __fseeko64 call would fail, too. */ +- return -1; +- } +- return readlen + result; +-} +-libc_hidden_def (__libc_readline_unlocked) +diff -rupN a/libio/tst-readline.c b/libio/tst-readline.c +--- a/libio/tst-readline.c 2020-09-14 17:48:41.969421067 -0400 ++++ b/libio/tst-readline.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,237 +0,0 @@ +-/* Test the __libc_readline_unlocked function. +- Copyright (C) 2018 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 +- . */ +- +-/* Exercise __libc_readline_unlocked with various combinations of line +- lengths, stdio buffer sizes, and line read buffer sizes. */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-enum +- { +- maximum_line_length = 7, +- number_of_lines = 3, +- }; +- +-/* -1: Do not set buffer size. 0: unbuffered. Otherwise, use this as +- the size of the buffer. */ +-static int buffer_size; +- +-/* These size of the buffer used for reading. Must be at least 2. */ +-static int read_size; +- +-/* If a read files with ERANGE, increase the buffer size by this +- amount. Must be positive. */ +-static int read_size_increment; +- +-/* If non-zero, do not reset the read size after an ERANGE error. */ +-static int read_size_preserve; +- +-/* If non-zero, no '\n' at the end of the file. */ +-static int no_newline_at_eof; +- +-/* Length of the line, or -1 if the line is not present. */ +-static int line_lengths[number_of_lines]; +- +-/* The name of the test file. */ +-static char *test_file_path; +- +-/* The contents of the test file. */ +-static char expected_contents[(maximum_line_length + 2) * number_of_lines + 1]; +-static size_t expected_length; +- +-/* Returns a random byte which is not zero or the line terminator. */ +-static char +-random_char (void) +-{ +- static unsigned int rand_state = 1; +- while (true) +- { +- char result = rand_r (&rand_state) >> 16; +- if (result != 0 && result != '\n') +- return result; +- } +-} +- +-/* Create the test file. */ +-static void +-prepare (int argc, char **argv) +-{ +- int fd = create_temp_file ("tst-readline-", &test_file_path); +- TEST_VERIFY_EXIT (fd >= 0); +- xclose (fd); +-} +- +-/* Prepare the test file. Return false if the test parameters are +- incongruent and the test should be skipped. */ +-static bool +-write_test_file (void) +-{ +- expected_length = 0; +- char *p = expected_contents; +- for (int lineno = 0; lineno < number_of_lines; ++lineno) +- for (int i = 0; i < line_lengths[lineno]; ++i) +- *p++ = random_char (); +- expected_length = p - &expected_contents[0]; +- if (no_newline_at_eof) +- { +- if (expected_length == 0) +- return false; +- --expected_length; +- --p; +- } +- if (test_verbose > 0) +- { +- printf ("info: writing test file of %zu bytes:\n", expected_length); +- for (int i = 0; i < number_of_lines; ++i) +- printf (" line %d: %d\n", i, line_lengths[i]); +- if (no_newline_at_eof) +- puts (" (no newline at EOF)"); +- } +- TEST_VERIFY_EXIT (expected_length < sizeof (expected_contents)); +- *p++ = '\0'; +- support_write_file_string (test_file_path, expected_contents); +- return true; +-} +- +-/* Run a single test (a combination of a test file and read +- parameters). */ +-static void +-run_test (void) +-{ +- TEST_VERIFY_EXIT (read_size_increment > 0); +- if (test_verbose > 0) +- { +- printf ("info: running test: buffer_size=%d read_size=%d\n" +- " read_size_increment=%d read_size_preserve=%d\n", +- buffer_size, read_size, read_size_increment, read_size_preserve); +- } +- +- struct xmemstream result; +- xopen_memstream (&result); +- +- FILE *fp = xfopen (test_file_path, "rce"); +- char *fp_buffer = NULL; +- if (buffer_size == 0) +- TEST_VERIFY_EXIT (setvbuf (fp, NULL, _IONBF, 0) == 0); +- if (buffer_size > 0) +- { +- fp_buffer = xmalloc (buffer_size); +- TEST_VERIFY_EXIT (setvbuf (fp, fp_buffer, _IOFBF, buffer_size) == 0); +- } +- +- char *line_buffer = xmalloc (read_size); +- size_t line_buffer_size = read_size; +- +- while (true) +- { +- ssize_t ret = __libc_readline_unlocked +- (fp, line_buffer, line_buffer_size); +- if (ret < 0) +- { +- TEST_VERIFY (ret == -1); +- if (errno != ERANGE) +- FAIL_EXIT1 ("__libc_readline_unlocked: %m"); +- line_buffer_size += read_size_increment; +- free (line_buffer); +- line_buffer = xmalloc (line_buffer_size); +- /* Try reading this line again. */ +- } +- else if (ret == 0) +- break; +- else +- { +- /* A line has been read. Save it. */ +- TEST_VERIFY (ret == strlen (line_buffer)); +- const char *pnl = strchr (line_buffer, '\n'); +- /* If there is a \n, it must be at the end. */ +- TEST_VERIFY (pnl == NULL || pnl == line_buffer + ret - 1); +- fputs (line_buffer, result.out); +- +- /* Restore the original read size if required. */ +- if (line_buffer_size > read_size && !read_size_preserve) +- { +- line_buffer_size = read_size; +- free (line_buffer); +- line_buffer = xmalloc (line_buffer_size); +- } +- } +- } +- +- xfclose (fp); +- free (fp_buffer); +- free (line_buffer); +- +- xfclose_memstream (&result); +- TEST_VERIFY (result.length == expected_length); +- TEST_VERIFY (strcmp (result.buffer, expected_contents) == 0); +- if (test_verbose > 0) +- { +- printf ("info: expected (%zu): [[%s]]\n", +- expected_length, expected_contents); +- printf ("info: actual (%zu): [[%s]]\n", result.length, result.buffer); +- } +- free (result.buffer); +-} +- +-/* Test one test file with multiple read parameters. */ +-static void +-test_one_file (void) +-{ +- for (buffer_size = -1; buffer_size <= maximum_line_length + 1; ++buffer_size) +- for (read_size = 2; read_size <= maximum_line_length + 2; ++read_size) +- for (read_size_increment = 1; read_size_increment <= 4; +- ++read_size_increment) +- for (read_size_preserve = 0; read_size_preserve < 2; +- ++read_size_preserve) +- run_test (); +-} +- +- +-static int +-do_test (void) +-{ +- /* Set up the test file contents. */ +- for (line_lengths[0] = -1; line_lengths[0] <= maximum_line_length; +- ++line_lengths[0]) +- for (line_lengths[1] = -1; line_lengths[1] <= maximum_line_length; +- ++line_lengths[1]) +- for (line_lengths[2] = -1; line_lengths[2] <= maximum_line_length; +- ++line_lengths[2]) +- for (no_newline_at_eof = 0; no_newline_at_eof < 2; ++no_newline_at_eof) +- { +- if (!write_test_file ()) +- continue; +- test_one_file (); +- } +- free (test_file_path); +- return 0; +-} +- +-#define TIMEOUT 100 +-#define PREPARE prepare +-#include diff --git a/glibc-rh1871397-2.patch b/glibc-rh1871397-2.patch new file mode 100755 index 0000000..1b95b01 --- /dev/null +++ b/glibc-rh1871397-2.patch @@ -0,0 +1,123 @@ +From 23ed36735af09c258e542266aaed92cdd8571c6c Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 16:21:28 +0200 +Subject: [PATCH 02/11] nss_compat: Do not use mmap to read database files (bug + 26258) + +This avoids crashes in case the files are truncated for some reason. +For typically file sizes, it is also going to be slightly faster. +Using __nss_files_fopen instead mirrors what nss_files does. + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + nss/nss_compat/compat-grp.c | 6 ++---- + nss/nss_compat/compat-initgroups.c | 6 ++---- + nss/nss_compat/compat-pwd.c | 6 ++---- + nss/nss_compat/compat-spwd.c | 6 ++---- + 4 files changed, 8 insertions(+), 16 deletions(-) + +diff -rup a/nss/nss_compat/compat-grp.c b/nss/nss_compat/compat-grp.c +--- a/nss/nss_compat/compat-grp.c 2020-09-14 15:49:18.248178627 -0400 ++++ b/nss/nss_compat/compat-grp.c 2020-09-14 17:18:22.514977541 -0400 +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + static service_user *ni; + static enum nss_status (*nss_setgrent) (int stayopen); +@@ -106,13 +107,10 @@ internal_setgrent (ent_t *ent, int stayo + + if (ent->stream == NULL) + { +- ent->stream = fopen ("/etc/group", "rme"); ++ ent->stream = __nss_files_fopen ("/etc/group"); + + if (ent->stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; +- else +- /* We take care of locking ourself. */ +- __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); + } + else + rewind (ent->stream); +diff -rup a/nss/nss_compat/compat-initgroups.c b/nss/nss_compat/compat-initgroups.c +--- a/nss/nss_compat/compat-initgroups.c 2020-09-14 15:49:18.255178892 -0400 ++++ b/nss/nss_compat/compat-initgroups.c 2020-09-14 17:18:22.519977728 -0400 +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + + static service_user *ni; + /* Type of the lookup function. */ +@@ -121,13 +122,10 @@ internal_setgrent (ent_t *ent) + else + ent->blacklist.current = 0; + +- ent->stream = fopen ("/etc/group", "rme"); ++ ent->stream = __nss_files_fopen ("/etc/group"); + + if (ent->stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; +- else +- /* We take care of locking ourself. */ +- __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); + + return status; + } +diff -rup a/nss/nss_compat/compat-pwd.c b/nss/nss_compat/compat-pwd.c +--- a/nss/nss_compat/compat-pwd.c 2020-09-14 15:49:18.260179081 -0400 ++++ b/nss/nss_compat/compat-pwd.c 2020-09-14 17:18:22.523977879 -0400 +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include "netgroup.h" + #include "nisdomain.h" +@@ -221,13 +222,10 @@ internal_setpwent (ent_t *ent, int stayo + + if (ent->stream == NULL) + { +- ent->stream = fopen ("/etc/passwd", "rme"); ++ ent->stream = __nss_files_fopen ("/etc/passwd"); + + if (ent->stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; +- else +- /* We take care of locking ourself. */ +- __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); + } + else + rewind (ent->stream); +diff -rup a/nss/nss_compat/compat-spwd.c b/nss/nss_compat/compat-spwd.c +--- a/nss/nss_compat/compat-spwd.c 2020-09-14 15:49:18.264179232 -0400 ++++ b/nss/nss_compat/compat-spwd.c 2020-09-14 17:18:22.527978029 -0400 +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include "netgroup.h" + #include "nisdomain.h" +@@ -177,13 +178,10 @@ internal_setspent (ent_t *ent, int stayo + + if (ent->stream == NULL) + { +- ent->stream = fopen ("/etc/shadow", "rme"); ++ ent->stream = __nss_files_fopen ("/etc/shadow"); + + if (ent->stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; +- else +- /* We take care of locking ourself. */ +- __fsetlocking (ent->stream, FSETLOCKING_BYCALLER); + } + else + rewind (ent->stream); diff --git a/glibc-rh1871397-3.patch b/glibc-rh1871397-3.patch new file mode 100755 index 0000000..474ab8b --- /dev/null +++ b/glibc-rh1871397-3.patch @@ -0,0 +1,227 @@ +From e9b2340998ab22402a8e968ba674c380a625b9dc Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 16:40:44 +0200 +Subject: [PATCH 03/11] nss_files: Consolidate line parse declarations in + + +These functions should eventually have the same type, so it makes +sense to declare them together. + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + include/grp.h | 6 ------ + include/gshadow.h | 6 ------ + include/netdb.h | 13 ------------ + include/netinet/ether.h | 6 ------ + include/nss_files.h | 51 +++++++++++++++++++++++++++++++++++++++++++++ + include/pwd.h | 6 ------ + include/rpc/netdb.h | 6 ------ + include/shadow.h | 6 ------ + nss/nss_files/files-parse.c | 1 + + 9 files changed, 52 insertions(+), 49 deletions(-) + +diff --git a/include/grp.h b/include/grp.h +index 58f7b4d..2cd2475 100644 +--- a/include/grp.h ++++ b/include/grp.h +@@ -30,12 +30,6 @@ extern int __old_getgrnam_r (const char *__name, struct group *__resultbuf, + char *__buffer, size_t __buflen, + struct group **__result); + +-struct parser_data; +-extern int _nss_files_parse_grent (char *line, struct group *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-libc_hidden_proto (_nss_files_parse_grent) +- + #define DECLARE_NSS_PROTOTYPES(service) \ + extern enum nss_status _nss_ ## service ## _setgrent (int); \ + extern enum nss_status _nss_ ## service ## _endgrent (void); \ +diff --git a/include/gshadow.h b/include/gshadow.h +index aa6a5a6..1cefcfc 100644 +--- a/include/gshadow.h ++++ b/include/gshadow.h +@@ -10,11 +10,5 @@ extern int __sgetsgent_r (const char *string, struct sgrp *resbuf, + char *buffer, size_t buflen, struct sgrp **result) + attribute_hidden; + +-struct parser_data; +-extern int _nss_files_parse_sgent (char *line, struct sgrp *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-libc_hidden_proto (_nss_files_parse_sgent) +- + # endif /* !_ISOMAC */ + #endif +diff --git a/include/netdb.h b/include/netdb.h +index 6b43135..49d63c1 100644 +--- a/include/netdb.h ++++ b/include/netdb.h +@@ -202,23 +202,10 @@ libc_hidden_proto (ruserpass) + + #include + +-struct parser_data; +-extern int _nss_files_parse_protoent (char *line, struct protoent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_servent (char *line, struct servent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_netent (char *line, struct netent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); + extern enum nss_status _nss_netgroup_parseline (char **cursor, + struct __netgrent *result, + char *buffer, size_t buflen, + int *errnop); +-libnss_files_hidden_proto (_nss_files_parse_protoent) +-libnss_files_hidden_proto (_nss_files_parse_servent) +-libnss_files_hidden_proto (_nss_files_parse_netent) + libnss_files_hidden_proto (_nss_netgroup_parseline) + + #define DECLARE_NSS_PROTOTYPES(service) \ +diff --git a/include/netinet/ether.h b/include/netinet/ether.h +index 8fd05f8..1763a7e 100644 +--- a/include/netinet/ether.h ++++ b/include/netinet/ether.h +@@ -15,12 +15,6 @@ struct etherent + struct ether_addr e_addr; + }; + +-struct parser_data; +-extern int _nss_files_parse_etherent (char *line, struct etherent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-libnss_files_hidden_proto (_nss_files_parse_etherent) +- + #define DECLARE_NSS_PROTOTYPES(service) \ + extern enum nss_status _nss_ ## service ## _setetherent (int __stayopen); \ + extern enum nss_status _nss_ ## service ## _endetherent (void); \ +diff --git a/include/nss_files.h b/include/nss_files.h +index 17144b7..54b354a 100644 +--- a/include/nss_files.h ++++ b/include/nss_files.h +@@ -25,4 +25,55 @@ + FILE *__nss_files_fopen (const char *path); + libc_hidden_proto (__nss_files_fopen) + ++struct parser_data; ++struct etherent; ++struct group; ++struct netent; ++struct passwd; ++struct protoent; ++struct rpcent; ++struct servent; ++struct sgrp; ++struct spwd; ++ ++/* Instances of the parse_line function from ++ nss/nss_files/files-parse.c. */ ++extern int _nss_files_parse_etherent (char *line, struct etherent *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_grent (char *line, struct group *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_netent (char *line, struct netent *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_protoent (char *line, struct protoent *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_pwent (char *line, struct passwd *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_rpcent (char *line, struct rpcent *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_servent (char *line, struct servent *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_sgent (char *line, struct sgrp *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern int _nss_files_parse_spent (char *line, struct spwd *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++ ++libnss_files_hidden_proto (_nss_files_parse_etherent) ++libc_hidden_proto (_nss_files_parse_grent) ++libnss_files_hidden_proto (_nss_files_parse_netent) ++libnss_files_hidden_proto (_nss_files_parse_protoent) ++libc_hidden_proto (_nss_files_parse_pwent) ++libnss_files_hidden_proto (_nss_files_parse_rpcent) ++libnss_files_hidden_proto (_nss_files_parse_servent) ++libc_hidden_proto (_nss_files_parse_sgent) ++libc_hidden_proto (_nss_files_parse_spent) ++ + #endif /* _NSS_FILES_H */ +diff --git a/include/pwd.h b/include/pwd.h +index fd23fe9..f8975d4 100644 +--- a/include/pwd.h ++++ b/include/pwd.h +@@ -26,12 +26,6 @@ extern int __fgetpwent_r (FILE * __stream, struct passwd *__resultbuf, + + #include + +-struct parser_data; +-extern int _nss_files_parse_pwent (char *line, struct passwd *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-libc_hidden_proto (_nss_files_parse_pwent) +- + #define DECLARE_NSS_PROTOTYPES(service) \ + extern enum nss_status _nss_ ## service ## _setpwent (int); \ + extern enum nss_status _nss_ ## service ## _endpwent (void); \ +diff --git a/include/rpc/netdb.h b/include/rpc/netdb.h +index 5ddd776..c1a936e 100644 +--- a/include/rpc/netdb.h ++++ b/include/rpc/netdb.h +@@ -24,12 +24,6 @@ extern int __getrpcent_r (struct rpcent *__result_buf, char *__buffer, + extern int __old_getrpcent_r (struct rpcent *__result_buf, char *__buffer, + size_t __buflen, struct rpcent **__result); + +-struct parser_data; +-extern int _nss_files_parse_rpcent (char *line, struct rpcent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-libnss_files_hidden_proto (_nss_files_parse_rpcent) +- + #define DECLARE_NSS_PROTOTYPES(service) \ + extern enum nss_status _nss_ ## service ## _setrpcent (int); \ + extern enum nss_status _nss_ ## service ## _endrpcent (void); \ +diff --git a/include/shadow.h b/include/shadow.h +index 5168d8d..fb16819 100644 +--- a/include/shadow.h ++++ b/include/shadow.h +@@ -25,12 +25,6 @@ extern int __fgetspent_r (FILE *__stream, struct spwd *__result_buf, + extern int __lckpwdf (void); + extern int __ulckpwdf (void); + +-struct parser_data; +-extern int _nss_files_parse_spent (char *line, struct spwd *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-libc_hidden_proto (_nss_files_parse_spent) +- + #define DECLARE_NSS_PROTOTYPES(service) \ + extern enum nss_status _nss_ ## service ## _setspent (int); \ + extern enum nss_status _nss_ ## service ## _endspent (void); \ +diff --git a/nss/nss_files/files-parse.c b/nss/nss_files/files-parse.c +index a563d81..3820287 100644 +--- a/nss/nss_files/files-parse.c ++++ b/nss/nss_files/files-parse.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + /* These symbols are defined by the including source file: + +-- +1.8.3.1 + diff --git a/glibc-rh1871397-4.patch b/glibc-rh1871397-4.patch new file mode 100755 index 0000000..aed1bd8 --- /dev/null +++ b/glibc-rh1871397-4.patch @@ -0,0 +1,111 @@ +From 9980bf0b307368959cb29f3ca3f7446ad92347f1 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 16:55:45 +0200 +Subject: [PATCH 04/11] nss_files: Use generic result pointer in parse_line + +As a result, all parse_line functions have the same prototype, except +for that producing struct hostent. This change is ABI-compatible, so +it does not alter the internal GLIBC_PRIVATE ABI (otherwise we should +probably have renamed the exported functions). + +A future change will use this to implement a generict fget*ent_r +function. + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + include/nss_files.h | 48 ++++++++++++--------------------------------- + nss/nss_files/files-parse.c | 5 +++-- + 2 files changed, 15 insertions(+), 38 deletions(-) + +diff --git a/include/nss_files.h b/include/nss_files.h +index 54b354a..d0f2681 100644 +--- a/include/nss_files.h ++++ b/include/nss_files.h +@@ -26,45 +26,21 @@ FILE *__nss_files_fopen (const char *path); + libc_hidden_proto (__nss_files_fopen) + + struct parser_data; +-struct etherent; +-struct group; +-struct netent; +-struct passwd; +-struct protoent; +-struct rpcent; +-struct servent; +-struct sgrp; +-struct spwd; + + /* Instances of the parse_line function from + nss/nss_files/files-parse.c. */ +-extern int _nss_files_parse_etherent (char *line, struct etherent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_grent (char *line, struct group *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_netent (char *line, struct netent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_protoent (char *line, struct protoent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_pwent (char *line, struct passwd *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_rpcent (char *line, struct rpcent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_servent (char *line, struct servent *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_sgent (char *line, struct sgrp *result, +- struct parser_data *data, +- size_t datalen, int *errnop); +-extern int _nss_files_parse_spent (char *line, struct spwd *result, +- struct parser_data *data, +- size_t datalen, int *errnop); ++typedef int nss_files_parse_line (char *line, void *result, ++ struct parser_data *data, ++ size_t datalen, int *errnop); ++extern nss_files_parse_line _nss_files_parse_etherent; ++extern nss_files_parse_line _nss_files_parse_grent; ++extern nss_files_parse_line _nss_files_parse_netent; ++extern nss_files_parse_line _nss_files_parse_protoent; ++extern nss_files_parse_line _nss_files_parse_pwent; ++extern nss_files_parse_line _nss_files_parse_rpcent; ++extern nss_files_parse_line _nss_files_parse_servent; ++extern nss_files_parse_line _nss_files_parse_sgent; ++extern nss_files_parse_line _nss_files_parse_spent; + + libnss_files_hidden_proto (_nss_files_parse_etherent) + libc_hidden_proto (_nss_files_parse_grent) +diff --git a/nss/nss_files/files-parse.c b/nss/nss_files/files-parse.c +index 3820287..c6cd43b 100644 +--- a/nss/nss_files/files-parse.c ++++ b/nss/nss_files/files-parse.c +@@ -87,7 +87,7 @@ struct parser_data + #ifdef EXTERN_PARSER + + /* The parser is defined in a different module. */ +-extern int parse_line (char *line, struct STRUCTURE *result, ++extern int parse_line (char *line, void *result, + struct parser_data *data, size_t datalen, int *errnop + EXTRA_ARGS_DECL); + +@@ -99,10 +99,11 @@ extern int parse_line (char *line, struct STRUCTURE *result, + + # define LINE_PARSER(EOLSET, BODY) \ + parser_stclass int \ +-parse_line (char *line, struct STRUCTURE *result, \ ++parse_line (char *line, void *generic_result, \ + struct parser_data *data, size_t datalen, int *errnop \ + EXTRA_ARGS_DECL) \ + { \ ++ struct STRUCTURE *result = generic_result; \ + ENTDATA_DECL (data) \ + BUFFER_PREPARE \ + char *p = strpbrk (line, EOLSET "\n"); \ +-- +1.8.3.1 + diff --git a/glibc-rh1871397-5.patch b/glibc-rh1871397-5.patch new file mode 100755 index 0000000..857cd83 --- /dev/null +++ b/glibc-rh1871397-5.patch @@ -0,0 +1,28 @@ +From d4b4586315974d2471486d41891aa9463a5838ad Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 17:00:46 +0200 +Subject: [PATCH 05/11] libio: Add fseterr_unlocked for internal use + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + include/stdio.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff -rup a/include/stdio.h b/include/stdio.h +--- a/include/stdio.h 2020-09-14 17:39:06.191727167 -0400 ++++ b/include/stdio.h 2020-09-14 17:43:44.780222972 -0400 +@@ -9,6 +9,13 @@ + + /* Now define the internal interfaces. */ + ++/* Set the error indicator on FP. */ ++static inline void ++fseterr_unlocked (FILE *fp) ++{ ++ fp->_flags |= _IO_ERR_SEEN; ++} ++ + extern int __fcloseall (void) attribute_hidden; + extern int __snprintf (char *__restrict __s, size_t __maxlen, + const char *__restrict __format, ...) diff --git a/glibc-rh1871397-6.patch b/glibc-rh1871397-6.patch new file mode 100755 index 0000000..997f84a --- /dev/null +++ b/glibc-rh1871397-6.patch @@ -0,0 +1,406 @@ +commit bdee910e88006ae33dc83ac3d2c0708adb6627d0 +Author: Florian Weimer +Date: Wed Jul 15 13:41:31 2020 +0200 + + nss: Add __nss_fgetent_r + + And helper functions __nss_readline, __nss_readline_seek, + __nss_parse_line_result. + + This consolidates common code for handling overlong lines and + parse files. Use the new functionality in internal_getent + in nss/nss_files/files-XXX.c. + + Tested-by: Carlos O'Donell + Reviewed-by: Carlos O'Donell + +diff -rupN a/include/nss_files.h b/include/nss_files.h +--- a/include/nss_files.h 2020-09-14 17:48:49.353699306 -0400 ++++ b/include/nss_files.h 2020-09-14 17:55:21.856488740 -0400 +@@ -25,6 +25,28 @@ + FILE *__nss_files_fopen (const char *path); + libc_hidden_proto (__nss_files_fopen) + ++/* Read a line from FP, storing it BUF. Strip leading blanks and skip ++ comments. Sets errno and returns error code on failure. Special ++ failure: ERANGE means the buffer is too small. The function writes ++ the original offset to *POFFSET (which can be negative in the case ++ of non-seekable input). */ ++int __nss_readline (FILE *fp, char *buf, size_t len, off64_t *poffset); ++libc_hidden_proto (__nss_readline) ++ ++/* Seek FP to OFFSET. Sets errno and returns error code on failure. ++ On success, sets errno to ERANGE and returns ERANGE (to indicate ++ re-reading of the same input line to the caller). If OFFSET is ++ negative, fail with ESPIPE without seeking. Intended to be used ++ after parsing data read by __nss_readline failed with ERANGE. */ ++int __nss_readline_seek (FILE *fp, off64_t offset) attribute_hidden; ++ ++/* Handles the result of a parse_line call (as defined by ++ nss/nss_files/files-parse.c). Adjusts the file offset of FP as ++ necessary. Returns 0 on success, and updates errno on failure (and ++ returns that error code). */ ++int __nss_parse_line_result (FILE *fp, off64_t offset, int parse_line_result); ++libc_hidden_proto (__nss_parse_line_result) ++ + struct parser_data; + + /* Instances of the parse_line function from +@@ -52,4 +74,11 @@ libnss_files_hidden_proto (_nss_files_pa + libc_hidden_proto (_nss_files_parse_sgent) + libc_hidden_proto (_nss_files_parse_spent) + ++/* Generic implementation of fget*ent_r. Reads lines from FP until ++ EOF or a successful parse into *RESULT using PARSER. Returns 0 on ++ success, ENOENT on EOF, ERANGE on too-small buffer. */ ++int __nss_fgetent_r (FILE *fp, void *result, ++ char *buffer, size_t buffer_length, ++ nss_files_parse_line parser) attribute_hidden; ++ + #endif /* _NSS_FILES_H */ +diff -rupN a/nss/Makefile b/nss/Makefile +--- a/nss/Makefile 2020-09-14 17:48:49.293697045 -0400 ++++ b/nss/Makefile 2020-09-14 17:55:21.860488891 -0400 +@@ -28,7 +28,9 @@ headers := nss.h + routines = nsswitch getnssent getnssent_r digits_dots \ + valid_field valid_list_field rewrite_field \ + $(addsuffix -lookup,$(databases)) \ +- compat-lookup nss_hash nss_files_fopen ++ compat-lookup nss_hash nss_files_fopen \ ++ nss_readline nss_parse_line_result \ ++ nss_fgetent_r + + # These are the databases that go through nss dispatch. + # Caution: if you add a database here, you must add its real name +diff -rupN a/nss/Versions b/nss/Versions +--- a/nss/Versions 2020-09-14 17:48:49.294697083 -0400 ++++ b/nss/Versions 2020-09-14 17:55:21.867489155 -0400 +@@ -21,7 +21,7 @@ libc { + __nss_passwd_lookup2; __nss_group_lookup2; __nss_hosts_lookup2; + __nss_services_lookup2; __nss_next2; __nss_lookup; + __nss_hash; __nss_database_lookup2; +- __nss_files_fopen; ++ __nss_files_fopen; __nss_readline; __nss_parse_line_result; + } + } + +diff -rupN a/nss/nss_fgetent_r.c b/nss/nss_fgetent_r.c +--- a/nss/nss_fgetent_r.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/nss/nss_fgetent_r.c 2020-09-14 17:55:21.870489268 -0400 +@@ -0,0 +1,55 @@ ++/* Generic implementation of fget*ent_r. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++ ++int ++__nss_fgetent_r (FILE *fp, void *result, char *buffer, size_t buffer_length, ++ nss_files_parse_line parser) ++{ ++ int ret; ++ ++ _IO_flockfile (fp); ++ ++ while (true) ++ { ++ off64_t original_offset; ++ ret = __nss_readline (fp, buffer, buffer_length, &original_offset); ++ if (ret == 0) ++ { ++ /* Parse the line into *RESULT. */ ++ ret = parser (buffer, result, ++ (struct parser_data *) buffer, buffer_length, &errno); ++ ++ /* Translate the result code from the parser into an errno ++ value. Also seeks back to the start of the line if ++ necessary. */ ++ ret = __nss_parse_line_result (fp, original_offset, ret); ++ ++ if (ret == EINVAL) ++ /* Skip over malformed lines. */ ++ continue; ++ } ++ break; ++ } ++ ++ _IO_funlockfile (fp); ++ ++ return ret; ++} +diff -rupN a/nss/nss_files/files-XXX.c b/nss/nss_files/files-XXX.c +--- a/nss/nss_files/files-XXX.c 2020-09-14 17:48:49.296697158 -0400 ++++ b/nss/nss_files/files-XXX.c 2020-09-14 17:55:21.878489569 -0400 +@@ -135,10 +135,9 @@ internal_getent (FILE *stream, struct ST + char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO + EXTRA_ARGS_DECL) + { +- char *p; + struct parser_data *data = (void *) buffer; + size_t linebuflen = buffer + buflen - data->linebuffer; +- int parse_result; ++ int saved_errno = errno; /* Do not clobber errno on success. */ + + if (buflen < sizeof *data + 2) + { +@@ -149,66 +148,42 @@ internal_getent (FILE *stream, struct ST + + while (true) + { +- ssize_t r = __libc_readline_unlocked +- (stream, data->linebuffer, linebuflen); +- if (r < 0) +- { +- *errnop = errno; +- H_ERRNO_SET (NETDB_INTERNAL); +- if (*errnop == ERANGE) +- /* Request larger buffer. */ +- return NSS_STATUS_TRYAGAIN; +- else +- /* Other read failure. */ +- return NSS_STATUS_UNAVAIL; +- } +- else if (r == 0) ++ off64_t original_offset; ++ int ret = __nss_readline (stream, data->linebuffer, linebuflen, ++ &original_offset); ++ if (ret == ENOENT) + { + /* End of file. */ + H_ERRNO_SET (HOST_NOT_FOUND); ++ __set_errno (saved_errno); + return NSS_STATUS_NOTFOUND; + } +- +- /* Everything OK. Now skip leading blanks. */ +- p = data->linebuffer; +- while (isspace (*p)) +- ++p; +- +- /* Ignore empty and comment lines. */ +- if (*p == '\0' || *p == '#') +- continue; +- +- /* Parse the line. */ +- *errnop = EINVAL; +- parse_result = parse_line (p, result, data, buflen, errnop EXTRA_ARGS); +- +- if (parse_result == -1) ++ else if (ret == 0) + { +- if (*errnop == ERANGE) ++ ret = __nss_parse_line_result (stream, original_offset, ++ parse_line (data->linebuffer, ++ result, data, buflen, ++ errnop EXTRA_ARGS)); ++ if (ret == 0) + { +- /* Return to the original file position at the beginning +- of the line, so that the next call can read it again +- if necessary. */ +- if (__fseeko64 (stream, -r, SEEK_CUR) != 0) +- { +- if (errno == ERANGE) +- *errnop = EINVAL; +- else +- *errnop = errno; +- H_ERRNO_SET (NETDB_INTERNAL); +- return NSS_STATUS_UNAVAIL; +- } ++ /* Line has been parsed successfully. */ ++ __set_errno (saved_errno); ++ return NSS_STATUS_SUCCESS; + } +- H_ERRNO_SET (NETDB_INTERNAL); +- return NSS_STATUS_TRYAGAIN; ++ else if (ret == EINVAL) ++ /* If it is invalid, loop to get the next line of the file ++ to parse. */ ++ continue; + } + +- /* Return the data if parsed successfully. */ +- if (parse_result != 0) +- return NSS_STATUS_SUCCESS; +- +- /* If it is invalid, loop to get the next line of the file to +- parse. */ ++ *errnop = ret; ++ H_ERRNO_SET (NETDB_INTERNAL); ++ if (ret == ERANGE) ++ /* Request larger buffer. */ ++ return NSS_STATUS_TRYAGAIN; ++ else ++ /* Other read failure. */ ++ return NSS_STATUS_UNAVAIL; + } + } + +diff -rupN a/nss/nss_parse_line_result.c b/nss/nss_parse_line_result.c +--- a/nss/nss_parse_line_result.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/nss/nss_parse_line_result.c 2020-09-14 17:55:21.880489645 -0400 +@@ -0,0 +1,46 @@ ++/* Implementation of __nss_parse_line_result. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++ ++#include ++#include ++ ++int ++__nss_parse_line_result (FILE *fp, off64_t offset, int parse_line_result) ++{ ++ assert (parse_line_result >= -1 && parse_line_result <= 1); ++ ++ switch (__builtin_expect (parse_line_result, 1)) ++ { ++ case 1: ++ /* Sucess. */ ++ return 0; ++ case 0: ++ /* Parse error. */ ++ __set_errno (EINVAL); ++ return EINVAL; ++ case -1: ++ /* Out of buffer space. */ ++ return __nss_readline_seek (fp, offset); ++ ++ default: ++ __builtin_unreachable (); ++ } ++} ++libc_hidden_def (__nss_parse_line_result) +diff -rupN a/nss/nss_readline.c b/nss/nss_readline.c +--- a/nss/nss_readline.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/nss/nss_readline.c 2020-09-14 17:55:21.883489758 -0400 +@@ -0,0 +1,99 @@ ++/* Read a line from an nss_files database file. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++ ++#include ++#include ++#include ++ ++int ++__nss_readline (FILE *fp, char *buf, size_t len, off64_t *poffset) ++{ ++ /* We need space for at least one character, the line terminator, ++ and the NUL byte. */ ++ if (len < 3) ++ { ++ *poffset = -1; ++ __set_errno (ERANGE); ++ return ERANGE; ++ } ++ ++ while (true) ++ { ++ /* Keep original offset for retries. */ ++ *poffset = __ftello64 (fp); ++ ++ buf[len - 1] = '\xff'; /* Marker to recognize truncation. */ ++ if (fgets_unlocked (buf, len, fp) == NULL) ++ { ++ if (feof_unlocked (fp)) ++ { ++ __set_errno (ENOENT); ++ return ENOENT; ++ } ++ else ++ { ++ /* Any other error. Do not return ERANGE in this case ++ because the caller would retry. */ ++ if (errno == ERANGE) ++ __set_errno (EINVAL); ++ return errno; ++ } ++ } ++ else if (buf[len - 1] != '\xff') ++ /* The buffer is too small. Arrange for re-reading the same ++ line on the next call. */ ++ return __nss_readline_seek (fp, *poffset); ++ ++ /* fgets_unlocked succeeded. */ ++ ++ /* Remove leading whitespace. */ ++ char *p = buf; ++ while (isspace (*p)) ++ ++p; ++ if (*p == '\0' || *p == '#') ++ /* Skip empty lines and comments. */ ++ continue; ++ if (p != buf) ++ memmove (buf, p, strlen (p)); ++ ++ /* Return line to the caller. */ ++ return 0; ++ } ++} ++libc_hidden_def (__nss_readline) ++ ++int ++__nss_readline_seek (FILE *fp, off64_t offset) ++{ ++ if (offset < 0 /* __ftello64 failed. */ ++ || __fseeko64 (fp, offset, SEEK_SET) < 0) ++ { ++ /* Without seeking support, it is not possible to ++ re-read the same line, so this is a hard failure. */ ++ fseterr_unlocked (fp); ++ __set_errno (ESPIPE); ++ return ESPIPE; ++ } ++ else ++ { ++ __set_errno (ERANGE); ++ return ERANGE; ++ } ++} diff --git a/glibc-rh1871397-7.patch b/glibc-rh1871397-7.patch new file mode 100755 index 0000000..3465d9d --- /dev/null +++ b/glibc-rh1871397-7.patch @@ -0,0 +1,85 @@ +From 4f62a21d0ed19ff29bba704167179b862140d011 Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 17:28:28 +0200 +Subject: [PATCH 07/11] grp: Implement fgetgrent_r using __nss_fgetent_r + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + grp/fgetgrent_r.c | 54 ++++++------------------------------------------------ + 1 file changed, 6 insertions(+), 48 deletions(-) + +diff --git a/grp/fgetgrent_r.c b/grp/fgetgrent_r.c +index 03daf4f..b598584 100644 +--- a/grp/fgetgrent_r.c ++++ b/grp/fgetgrent_r.c +@@ -20,10 +20,6 @@ + #include + #include + +-#include +-#define flockfile(s) _IO_flockfile (s) +-#define funlockfile(s) _IO_funlockfile (s) +- + /* Define a line parsing function using the common code + used in the nss_files module. */ + +@@ -59,49 +55,11 @@ int + __fgetgrent_r (FILE *stream, struct group *resbuf, char *buffer, size_t buflen, + struct group **result) + { +- char *p; +- int parse_result; +- +- flockfile (stream); +- do +- { +- buffer[buflen - 1] = '\xff'; +- p = fgets_unlocked (buffer, buflen, stream); +- if (__builtin_expect (p == NULL, 0) && feof_unlocked (stream)) +- { +- funlockfile (stream); +- *result = NULL; +- __set_errno (ENOENT); +- return errno; +- } +- if (__builtin_expect (p == NULL, 0) || buffer[buflen - 1] != '\xff') +- { +- funlockfile (stream); +- *result = NULL; +- __set_errno (ERANGE); +- return errno; +- } +- +- /* Skip leading blanks. */ +- while (isspace (*p)) +- ++p; +- } 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_result = parse_line (p, resbuf, +- (void *) buffer, buflen, +- &errno))); +- +- funlockfile (stream); +- +- if (__builtin_expect (parse_result, 0) == -1) +- { +- /* The parser ran out of space. */ +- *result = NULL; +- return errno; +- } +- +- *result = resbuf; +- return 0; ++ int ret = __nss_fgetent_r (stream, resbuf, buffer, buflen, parse_line); ++ if (ret == 0) ++ *result = resbuf; ++ else ++ *result = NULL; ++ return ret; + } + weak_alias (__fgetgrent_r, fgetgrent_r) +-- +1.8.3.1 + diff --git a/glibc-rh1871397-8.patch b/glibc-rh1871397-8.patch new file mode 100755 index 0000000..58bd476 --- /dev/null +++ b/glibc-rh1871397-8.patch @@ -0,0 +1,272 @@ +From 2add4235ef674988948155f9a8f60a8c7b09bcff Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 17:31:20 +0200 +Subject: [PATCH 08/11] gshadow: Implement fgetsgent_r using __nss_fgetent_r + (bug 20338) + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + gshadow/Makefile | 2 +- + gshadow/fgetsgent_r.c | 41 ++-------- + gshadow/tst-fgetsgent_r.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 198 insertions(+), 36 deletions(-) + create mode 100644 gshadow/tst-fgetsgent_r.c + +diff -rupN a/gshadow/Makefile b/gshadow/Makefile +--- a/gshadow/Makefile 2018-08-01 01:10:47.000000000 -0400 ++++ b/gshadow/Makefile 2020-09-14 18:00:57.167145887 -0400 +@@ -26,7 +26,7 @@ headers = gshadow.h + routines = getsgent getsgnam sgetsgent fgetsgent putsgent \ + getsgent_r getsgnam_r sgetsgent_r fgetsgent_r + +-tests = tst-gshadow tst-putsgent ++tests = tst-gshadow tst-putsgent tst-fgetsgent_r + + CFLAGS-getsgent_r.c += -fexceptions + CFLAGS-getsgent.c += -fexceptions +diff -rupN a/gshadow/fgetsgent_r.c b/gshadow/fgetsgent_r.c +--- a/gshadow/fgetsgent_r.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/gshadow/fgetsgent_r.c 2020-09-14 18:45:59.189353065 -0400 +@@ -36,40 +36,11 @@ int + __fgetsgent_r (FILE *stream, struct sgrp *resbuf, char *buffer, size_t buflen, + struct sgrp **result) + { +- char *p; +- +- _IO_flockfile (stream); +- do +- { +- buffer[buflen - 1] = '\xff'; +- p = fgets_unlocked (buffer, buflen, stream); +- if (p == NULL && feof_unlocked (stream)) +- { +- _IO_funlockfile (stream); +- *result = NULL; +- __set_errno (ENOENT); +- return errno; +- } +- if (p == NULL || buffer[buflen - 1] != '\xff') +- { +- _IO_funlockfile (stream); +- *result = NULL; +- __set_errno (ERANGE); +- return errno; +- } +- +- /* Skip leading blanks. */ +- while (isspace (*p)) +- ++p; +- } 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)); +- +- _IO_funlockfile (stream); +- +- *result = resbuf; +- return 0; ++ int ret = __nss_fgetent_r (stream, resbuf, buffer, buflen, parse_line); ++ if (ret == 0) ++ *result = resbuf; ++ else ++ *result = NULL; ++ return ret; + } + weak_alias (__fgetsgent_r, fgetsgent_r) +diff -rupN a/gshadow/tst-fgetsgent_r.c b/gshadow/tst-fgetsgent_r.c +--- a/gshadow/tst-fgetsgent_r.c 1969-12-31 19:00:00.000000000 -0500 ++++ b/gshadow/tst-fgetsgent_r.c 2020-09-14 18:00:57.174146151 -0400 +@@ -0,0 +1,191 @@ ++/* Test for fgetsgent_r and buffer sizes. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Turn a parsed struct back into a line string. The returned string ++ should be freed. */ ++static char * ++format_ent (const struct sgrp *e) ++{ ++ struct xmemstream stream; ++ xopen_memstream (&stream); ++ TEST_COMPARE (putsgent (e, stream.out), 0); ++ xfclose_memstream (&stream); ++ return stream.buffer; ++} ++ ++/* An entry in the input file along with the expected output. */ ++struct input ++{ ++ const char *line; /* Line in the file. */ ++ const char *expected; /* Expected output. NULL if skipped. */ ++}; ++ ++const struct input inputs[] = ++ { ++ /* Regular entries. */ ++ { "g1:x1::\n", "g1:x1::\n" }, ++ { "g2:x2:a1:\n", "g2:x2:a1:\n" }, ++ { "g3:x3:a2:u1\n", "g3:x3:a2:u1\n" }, ++ { "g4:x4:a3,a4:u2,u3,u4\n", "g4:x4:a3,a4:u2,u3,u4\n" }, ++ ++ /* Comments and empty lines. */ ++ { "\n", NULL }, ++ { " \n", NULL }, ++ { "\t\n", NULL }, ++ { "#g:x::\n", NULL }, ++ { " #g:x::\n", NULL }, ++ { "\t#g:x::\n", NULL }, ++ { " \t#g:x::\n", NULL }, ++ ++ /* Marker for synchronization. */ ++ { "g5:x5::\n", "g5:x5::\n" }, ++ ++ /* Leading whitespace. */ ++ { " g6:x6::\n", "g6:x6::\n" }, ++ { "\tg7:x7::\n", "g7:x7::\n" }, ++ ++ /* This is expected to trigger buffer exhaustion during parsing ++ (bug 20338). */ ++ { ++ "g8:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:u5,u6,u7,u8,u9:\n", ++ "g8:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:u5,u6,u7,u8,u9:\n", ++ }, ++ { ++ "g9:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::a5,a6,a7,a8,a9,a10\n", ++ "g9:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx::a5,a6,a7,a8,a9,a10\n", ++ }, ++ }; ++ ++/* Writes the test data to a temporary file and returns its name. The ++ returned pointer should be freed. */ ++static char * ++create_test_file (void) ++{ ++ char *path; ++ int fd = create_temp_file ("tst-fgetsgent_r-", &path); ++ FILE *fp = fdopen (fd, "w"); ++ TEST_VERIFY_EXIT (fp != NULL); ++ ++ for (size_t i = 0; i < array_length (inputs); ++i) ++ fputs (inputs[i].line, fp); ++ ++ xfclose (fp); ++ return path; ++} ++ ++/* Read the test file with the indicated start buffer size. Return ++ true if the buffer size had to be increased during reading. */ ++static bool ++run_test (const char *path, size_t buffer_size) ++{ ++ bool resized = false; ++ FILE *fp = xfopen (path, "r"); ++ ++ /* This avoids repeated lseek system calls (bug 26257). */ ++ TEST_COMPARE (fseeko64 (fp, 0, SEEK_SET), 0); ++ ++ size_t i = 0; ++ while (true) ++ { ++ /* Skip over unused expected entries. */ ++ while (i < array_length (inputs) && inputs[i].expected == NULL) ++ ++i; ++ ++ /* Store the data on the heap, to help valgrind to detect ++ invalid accesses. */ ++ struct sgrp *result_storage = xmalloc (sizeof (*result_storage)); ++ char *buffer = xmalloc (buffer_size); ++ struct sgrp **result_pointer_storage ++ = xmalloc (sizeof (*result_pointer_storage)); ++ ++ int ret = fgetsgent_r (fp, result_storage, buffer, buffer_size, ++ result_pointer_storage); ++ if (ret == 0) ++ { ++ TEST_VERIFY (*result_pointer_storage != NULL); ++ TEST_VERIFY (i < array_length (inputs)); ++ if (*result_pointer_storage != NULL ++ && i < array_length (inputs)) ++ { ++ char * actual = format_ent (*result_pointer_storage); ++ TEST_COMPARE_STRING (inputs[i].expected, actual); ++ free (actual); ++ ++i; ++ } ++ else ++ break; ++ } ++ else ++ { ++ TEST_VERIFY (*result_pointer_storage == NULL); ++ TEST_COMPARE (ret, errno); ++ ++ if (ret == ENOENT) ++ { ++ TEST_COMPARE (i, array_length (inputs)); ++ free (result_pointer_storage); ++ free (buffer); ++ free (result_storage); ++ break; ++ } ++ else if (ret == ERANGE) ++ { ++ resized = true; ++ ++buffer_size; ++ } ++ else ++ FAIL_EXIT1 ("read failure: %m"); ++ } ++ ++ free (result_pointer_storage); ++ free (buffer); ++ free (result_storage); ++ } ++ ++ return resized; ++} ++ ++static int ++do_test (void) ++{ ++ char *path = create_test_file (); ++ ++ for (size_t buffer_size = 3; ; ++buffer_size) ++ { ++ bool resized = run_test (path, buffer_size); ++ if (!resized) ++ break; ++ } ++ ++ free (path); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1871397-9.patch b/glibc-rh1871397-9.patch new file mode 100755 index 0000000..4e0396e --- /dev/null +++ b/glibc-rh1871397-9.patch @@ -0,0 +1,70 @@ +From ee1c062be09da006e82ab34c1c9b5c82dd2af92c Mon Sep 17 00:00:00 2001 +From: Florian Weimer +Date: Thu, 16 Jul 2020 17:34:19 +0200 +Subject: [PATCH 09/11] pwd: Implement fgetpwent_r using __nss_fgetent_r + +Tested-by: Carlos O'Donell +Reviewed-by: Carlos O'Donell +--- + pwd/fgetpwent_r.c | 43 ++++++------------------------------------- + 1 file changed, 6 insertions(+), 37 deletions(-) + +diff -rup a/pwd/fgetpwent_r.c b/pwd/fgetpwent_r.c +--- a/pwd/fgetpwent_r.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/pwd/fgetpwent_r.c 2020-09-14 19:03:41.277514743 -0400 +@@ -20,9 +20,6 @@ + #include + #include + +-#define flockfile(s) _IO_flockfile (s) +-#define funlockfile(s) _IO_funlockfile (s) +- + /* Define a line parsing function using the common code + used in the nss_files module. */ + +@@ -72,39 +69,11 @@ int + __fgetpwent_r (FILE *stream, struct passwd *resbuf, char *buffer, + size_t buflen, struct passwd **result) + { +- char *p; +- +- flockfile (stream); +- do +- { +- buffer[buflen - 1] = '\xff'; +- p = fgets_unlocked (buffer, buflen, stream); +- if (p == NULL && feof_unlocked (stream)) +- { +- funlockfile (stream); +- *result = NULL; +- __set_errno (ENOENT); +- return errno; +- } +- if (p == NULL || buffer[buflen - 1] != '\xff') +- { +- funlockfile (stream); +- *result = NULL; +- __set_errno (ERANGE); +- return errno; +- } +- +- /* Skip leading blanks. */ +- while (isspace (*p)) +- ++p; +- } 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 (p, resbuf, (void *) buffer, buflen, &errno)); +- +- funlockfile (stream); +- +- *result = resbuf; +- return 0; ++ int ret = __nss_fgetent_r (stream, resbuf, buffer, buflen, parse_line); ++ if (ret == 0) ++ *result = resbuf; ++ else ++ *result = NULL; ++ return ret; + } + weak_alias (__fgetpwent_r, fgetpwent_r) diff --git a/glibc-rh1880670-2.patch b/glibc-rh1880670-2.patch new file mode 100755 index 0000000..c976be6 --- /dev/null +++ b/glibc-rh1880670-2.patch @@ -0,0 +1,64 @@ +commit 8813b2682e4094e43b0cf1634e99619f1b8b2c62 +Author: Sajan Karumanchi +Date: Wed Oct 28 13:05:33 2020 +0530 + + x86: Optimizing memcpy for AMD Zen architecture. + + Modifying the shareable cache '__x86_shared_cache_size', which is a + factor in computing the non-temporal threshold parameter + '__x86_shared_non_temporal_threshold' to optimize memcpy for AMD Zen + architectures. + In the existing implementation, the shareable cache is computed as 'L3 + per thread, L2 per core'. Recomputing this shareable cache as 'L3 per + CCX(Core-Complex)' has brought in performance gains. + As per the large bench variant results, this patch also addresses the + regression problem on AMD Zen architectures. + + Backport of commit 59803e81f96b479c17f583b31eac44b57591a1bf upstream, + with the fix from cb3a749a22a55645dc6a52659eea765300623f98 ("x86: + Restore processing of cache size tunables in init_cacheinfo") applied. + + Reviewed-by: Premachandra Mallappa + Co-Authored-by: Florian Weimer + +Backport is off the release/2.32/master branch upstream, to minimize +conflicts. Adjusted for missing "basic" member in struct cpu_features. + +diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c +index 42b468d0c4885bad..57c36d030a76c8b2 100644 +--- a/sysdeps/x86/cacheinfo.c ++++ b/sysdeps/x86/cacheinfo.c +@@ -722,7 +722,7 @@ intel_bug_no_cache_info: + threads = 1 << ((ecx >> 12) & 0x0f); + } + +- if (threads == 0) ++ if (threads == 0 || cpu_features->family >= 0x17) + { + /* If APIC ID width is not available, use logical + processor count. */ +@@ -737,8 +737,22 @@ intel_bug_no_cache_info: + if (threads > 0) + shared /= threads; + +- /* Account for exclusive L2 and L3 caches. */ +- shared += core; ++ /* Get shared cache per ccx for Zen architectures. */ ++ if (cpu_features->family >= 0x17) ++ { ++ unsigned int eax; ++ ++ /* Get number of threads share the L3 cache in CCX. */ ++ __cpuid_count (0x8000001D, 0x3, eax, ebx, ecx, edx); ++ ++ unsigned int threads_per_ccx = ((eax >> 14) & 0xfff) + 1; ++ shared *= threads_per_ccx; ++ } ++ else ++ { ++ /* Account for exclusive L2 and L3 caches. */ ++ shared += core; ++ } + } + + #ifndef DISABLE_PREFETCHW diff --git a/glibc-rh1880670.patch b/glibc-rh1880670.patch new file mode 100755 index 0000000..d76a028 --- /dev/null +++ b/glibc-rh1880670.patch @@ -0,0 +1,97 @@ +commit d3c57027470b78dba79c6d931e4e409b1fecfc80 +Author: Patrick McGehearty +Date: Mon Sep 28 20:11:28 2020 +0000 + + Reversing calculation of __x86_shared_non_temporal_threshold + + The __x86_shared_non_temporal_threshold determines when memcpy on x86 + uses non_temporal stores to avoid pushing other data out of the last + level cache. + + This patch proposes to revert the calculation change made by H.J. Lu's + patch of June 2, 2017. + + H.J. Lu's patch selected a threshold suitable for a single thread + getting maximum performance. It was tuned using the single threaded + large memcpy micro benchmark on an 8 core processor. The last change + changes the threshold from using 3/4 of one thread's share of the + cache to using 3/4 of the entire cache of a multi-threaded system + before switching to non-temporal stores. Multi-threaded systems with + more than a few threads are server-class and typically have many + active threads. If one thread consumes 3/4 of the available cache for + all threads, it will cause other active threads to have data removed + from the cache. Two examples show the range of the effect. John + McCalpin's widely parallel Stream benchmark, which runs in parallel + and fetches data sequentially, saw a 20% slowdown with this patch on + an internal system test of 128 threads. This regression was discovered + when comparing OL8 performance to OL7. An example that compares + normal stores to non-temporal stores may be found at + https://vgatherps.github.io/2018-09-02-nontemporal/. A simple test + shows performance loss of 400 to 500% due to a failure to use + nontemporal stores. These performance losses are most likely to occur + when the system load is heaviest and good performance is critical. + + The tunable x86_non_temporal_threshold can be used to override the + default for the knowledgable user who really wants maximum cache + allocation to a single thread in a multi-threaded system. + The manual entry for the tunable has been expanded to provide + more information about its purpose. + + modified: sysdeps/x86/cacheinfo.c + modified: manual/tunables.texi + +Conflicts: + manual/tunables.texi + (Downstream uses the glibc.tune namespace, upstream uses + glibc.cpu.) + sysdeps/x86/cacheinfo.c + (Downstream does not have rep_movsb_threshold, + x86_rep_stosb_threshold tunables.) + +diff --git a/manual/tunables.texi b/manual/tunables.texi +index 3dc6f9a44592c030..3e1e519dff153b09 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -364,7 +364,11 @@ set shared cache size in bytes for use in memory and string routines. + + @deftp Tunable glibc.tune.x86_non_temporal_threshold + The @code{glibc.tune.x86_non_temporal_threshold} tunable allows the user +-to set threshold in bytes for non temporal store. ++to set threshold in bytes for non temporal store. Non temporal stores ++give a hint to the hardware to move data directly to memory without ++displacing other data from the cache. This tunable is used by some ++platforms to determine when to use non temporal stores in operations ++like memmove and memcpy. + + This tunable is specific to i386 and x86-64. + @end deftp +diff --git a/sysdeps/x86/cacheinfo.c b/sysdeps/x86/cacheinfo.c +index b9444ddd52051e05..42b468d0c4885bad 100644 +--- a/sysdeps/x86/cacheinfo.c ++++ b/sysdeps/x86/cacheinfo.c +@@ -778,14 +778,20 @@ intel_bug_no_cache_info: + __x86_shared_cache_size = shared; + } + +- /* The large memcpy micro benchmark in glibc shows that 6 times of +- shared cache size is the approximate value above which non-temporal +- store becomes faster on a 8-core processor. This is the 3/4 of the +- total shared cache size. */ ++ /* The default setting for the non_temporal threshold is 3/4 of one ++ thread's share of the chip's cache. For most Intel and AMD processors ++ with an initial release date between 2017 and 2020, a thread's typical ++ share of the cache is from 500 KBytes to 2 MBytes. Using the 3/4 ++ threshold leaves 125 KBytes to 500 KBytes of the thread's data ++ in cache after a maximum temporal copy, which will maintain ++ in cache a reasonable portion of the thread's stack and other ++ active data. If the threshold is set higher than one thread's ++ share of the cache, it has a substantial risk of negatively ++ impacting the performance of other threads running on the chip. */ + __x86_shared_non_temporal_threshold + = (cpu_features->non_temporal_threshold != 0 + ? cpu_features->non_temporal_threshold +- : __x86_shared_cache_size * threads * 3 / 4); ++ : __x86_shared_cache_size * 3 / 4); + } + + #endif diff --git a/glibc-rh1882466-1.patch b/glibc-rh1882466-1.patch new file mode 100755 index 0000000..7a22ce0 --- /dev/null +++ b/glibc-rh1882466-1.patch @@ -0,0 +1,51 @@ +commit cb81264fd9973cd95bbc71495185b98979d28918 +Author: Florian Weimer +Date: Fri Dec 11 17:24:08 2020 +0100 + + support: Add support_slibdir_prefix variable + + Reviewed-by: Carlos O'Donell + +diff --git a/support/Makefile b/support/Makefile +index 35b21b19a248ba7f..dcf3c4baa2a31070 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -184,6 +184,7 @@ CFLAGS-support_paths.c = \ + -DLIBDIR_PATH=\"$(libdir)\" \ + -DBINDIR_PATH=\"$(bindir)\" \ + -DSBINDIR_PATH=\"$(sbindir)\" \ ++ -DSLIBDIR_PATH=\"$(slibdir)\" \ + -DROOTSBINDIR_PATH=\"$(rootsbindir)\" \ + -DCOMPLOCALEDIR_PATH=\"$(complocaledir)\" + +diff --git a/support/support.h b/support/support.h +index 6f7f804847f67600..f50f8cc1496d657d 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -110,6 +110,8 @@ extern const char support_libdir_prefix[]; + extern const char support_bindir_prefix[]; + /* Corresponds to the install's sbin/ directory. */ + extern const char support_sbindir_prefix[]; ++/* Corresponds to the install's system /lib or /lib64 directory. */ ++extern const char support_slibdir_prefix[]; + /* Corresponds to the install's sbin/ directory (without prefix). */ + extern const char support_install_rootsbindir[]; + /* Corresponds to the install's compiled locale directory. */ +diff --git a/support/support_paths.c b/support/support_paths.c +index 6b15fae0f0173b1e..be61c8acee3ec1a5 100644 +--- a/support/support_paths.c ++++ b/support/support_paths.c +@@ -72,6 +72,13 @@ const char support_sbindir_prefix[] = SBINDIR_PATH; + # error please -DSBINDIR_PATH=something in the Makefile + #endif + ++#ifdef SLIBDIR_PATH ++/* Corresponds to the system /lib or /lib64 directory. */ ++const char support_slibdir_prefix[] = SLIBDIR_PATH; ++#else ++# error please -DSLIBDIR_PATH=something in the Makefile ++#endif ++ + #ifdef ROOTSBINDIR_PATH + /* Corresponds to the install's sbin/ directory. */ + const char support_install_rootsbindir[] = ROOTSBINDIR_PATH; diff --git a/glibc-rh1882466-2.patch b/glibc-rh1882466-2.patch new file mode 100755 index 0000000..1ee6651 --- /dev/null +++ b/glibc-rh1882466-2.patch @@ -0,0 +1,98 @@ +commit 9ffa50b26b0cb5d3043adf6d3d0b1ea735acc147 +Author: Florian Weimer +Date: Fri Dec 11 17:30:03 2020 +0100 + + elf: Include libc.so.6 as main program in dependency sort (bug 20972) + + _dl_map_object_deps always sorts the initially loaded object first + during dependency sorting. This means it is relocated last in + dl_open_worker. This results in crashes in IFUNC resolvers without + lazy bindings if libraries are preloaded that refer to IFUNCs in + libc.so.6: the resolvers are called when libc.so.6 has not been + relocated yet, so references to _rtld_global_ro etc. crash. + + The fix is to check against the libc.so.6 link map recorded by the + __libc_early_init framework, and let it participate in the dependency + sort. + + This fixes bug 20972. + + Reviewed-by: Carlos O'Donell + +Conflicts: + elf/Makefile + (Usual test backport differences.) + +diff --git a/elf/Makefile b/elf/Makefile +index 67029930dd2cb461..fc9c685b9d23bb6c 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -215,7 +215,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 tst-tls-surplus tst-dl-hwcaps_split +-tests-container += tst-pldd ++tests-container += tst-pldd tst-preload-pthread-libc + ifeq ($(build-hardcoded-path-in-tests),yes) + tests += tst-dlopen-aout + tst-dlopen-aout-no-pie = yes +diff --git a/elf/dl-deps.c b/elf/dl-deps.c +index 50f053a1586efdc3..007069f670eced95 100644 +--- a/elf/dl-deps.c ++++ b/elf/dl-deps.c +@@ -610,7 +610,12 @@ Filters not supported with LD_TRACE_PRELINKING")); + memcpy (l_initfini, map->l_searchlist.r_list, + nlist * sizeof (struct link_map *)); + +- _dl_sort_maps (&l_initfini[1], nlist - 1, NULL, false); ++ /* If libc.so.6 is the main map, it participates in the sort, so ++ that the relocation order is correct regarding libc.so.6. */ ++ if (l_initfini[0] == GL (dl_ns)[l_initfini[0]->l_ns].libc_map) ++ _dl_sort_maps (l_initfini, nlist, NULL, false); ++ else ++ _dl_sort_maps (&l_initfini[1], nlist - 1, NULL, false); + + /* Terminate the list of dependencies. */ + l_initfini[nlist] = NULL; +diff --git a/elf/tst-preload-pthread-libc.c b/elf/tst-preload-pthread-libc.c +new file mode 100644 +index 0000000000000000..48cb512a93f3da19 +--- /dev/null ++++ b/elf/tst-preload-pthread-libc.c +@@ -0,0 +1,36 @@ ++/* Test relocation ordering if the main executable is libc.so.6 (bug 20972). ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++int ++main (void) ++{ ++ char *libc = xasprintf ("%s/%s", support_slibdir_prefix, LIBC_SO); ++ char *argv[] = { libc, NULL }; ++ char *envp[] = { (char *) "LD_PRELOAD=" LIBPTHREAD_SO, ++ /* Relocation ordering matters most without lazy binding. */ ++ (char *) "LD_BIND_NOW=1", ++ NULL }; ++ execve (libc, argv, envp); ++ printf ("execve of %s failed: %m\n", libc); ++ return 1; ++} diff --git a/glibc-rh1882466-3.patch b/glibc-rh1882466-3.patch new file mode 100755 index 0000000..d254df7 --- /dev/null +++ b/glibc-rh1882466-3.patch @@ -0,0 +1,45 @@ +commit 4d0985543f479a6f421d4d8a9e0d1dc71c9c2c53 +Author: Florian Weimer +Date: Tue Dec 15 20:56:04 2020 +0100 + + elf: Record libc.so link map when it is the main program (bug 20972) + + Otherwise, it will not participate in the dependency sorting. + + Fixes commit 9ffa50b26b0cb5d3043adf6d3d0b1ea735acc147 + ("elf: Include libc.so.6 as main program in dependency sort + (bug 20972)"). + +Conflicts: + elf/rtld.c + (Missing backported header include.) + +diff --git a/elf/rtld.c b/elf/rtld.c +index fde5a6a4a485207e..992f825ba00762a7 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + + #include + +@@ -1588,6 +1589,16 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + { + /* Extract the contents of the dynamic section for easy access. */ + elf_get_dynamic_info (main_map, NULL); ++ ++ /* If the main map is libc.so, update the base namespace to ++ refer to this map. If libc.so is loaded later, this happens ++ in _dl_map_object_from_fd. */ ++ if (main_map->l_info[DT_SONAME] != NULL ++ && (strcmp (((const char *) D_PTR (main_map, l_info[DT_STRTAB]) ++ + main_map->l_info[DT_SONAME]->d_un.d_val), LIBC_SO) ++ == 0)) ++ GL(dl_ns)[LM_ID_BASE].libc_map = main_map; ++ + /* Set up our cache of pointers into the hash table. */ + _dl_setup_hash (main_map); + } diff --git a/glibc-rh1893662-1.patch b/glibc-rh1893662-1.patch new file mode 100755 index 0000000..f225f64 --- /dev/null +++ b/glibc-rh1893662-1.patch @@ -0,0 +1,47 @@ +commit 558251bd8785760ad40fcbfeaaee5d27fa5b0fe4 +Author: Szabolcs Nagy +Date: Thu Oct 22 17:55:01 2020 +0100 + + aarch64: Fix DT_AARCH64_VARIANT_PCS handling [BZ #26798] + + The variant PCS support was ineffective because in the common case + linkmap->l_mach.plt == 0 but then the symbol table flags were ignored + and normal lazy binding was used instead of resolving the relocs early. + (This was a misunderstanding about how GOT[1] is setup by the linker.) + + In practice this mainly affects SVE calls when the vector length is + more than 128 bits, then the top bits of the argument registers get + clobbered during lazy binding. + + Fixes bug 26798. + +diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h +index b39eae4acf4086ee..3fd3c8a265d012b1 100644 +--- a/sysdeps/aarch64/dl-machine.h ++++ b/sysdeps/aarch64/dl-machine.h +@@ -391,13 +391,6 @@ elf_machine_lazy_rel (struct link_map *map, + /* Check for unexpected PLT reloc type. */ + if (__builtin_expect (r_type == AARCH64_R(JUMP_SLOT), 1)) + { +- if (map->l_mach.plt == 0) +- { +- /* Prelinking. */ +- *reloc_addr += l_addr; +- return; +- } +- + if (__glibc_unlikely (map->l_info[DT_AARCH64 (VARIANT_PCS)] != NULL)) + { + /* Check the symbol table for variant PCS symbols. */ +@@ -421,7 +414,10 @@ elf_machine_lazy_rel (struct link_map *map, + } + } + +- *reloc_addr = map->l_mach.plt; ++ if (map->l_mach.plt == 0) ++ *reloc_addr += l_addr; ++ else ++ *reloc_addr = map->l_mach.plt; + } + else if (__builtin_expect (r_type == AARCH64_R(TLSDESC), 1)) + { diff --git a/glibc-rh1893662-2.patch b/glibc-rh1893662-2.patch new file mode 100755 index 0000000..e421ade --- /dev/null +++ b/glibc-rh1893662-2.patch @@ -0,0 +1,349 @@ +commit e156dabc766d6f6f99ce9402999eae380a3ec1f2 +Author: Szabolcs Nagy +Date: Mon Oct 26 15:48:01 2020 +0000 + + aarch64: Add variant PCS lazy binding test [BZ #26798] + + This test fails without bug 26798 fixed because some integer registers + likely get clobbered by lazy binding and variant PCS only allows x16 + and x17 to be clobbered at call time. + + The test requires binutils 2.32.1 or newer for handling variant PCS + symbols. SVE registers are not covered by this test, to avoid the + complexity of handling multiple compile- and runtime feature support + cases. + +(Trivial textual conflicts due to lack of PAC and BTI support) + +# Conflicts: +# sysdeps/aarch64/Makefile +# sysdeps/aarch64/configure +# sysdeps/aarch64/configure.ac + +diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile +index 94baaf52dda4b801..3ec78fefc6dd5797 100644 +--- a/sysdeps/aarch64/Makefile ++++ b/sysdeps/aarch64/Makefile +@@ -3,6 +3,13 @@ long-double-fcts = yes + ifeq ($(subdir),elf) + sysdep-dl-routines += tlsdesc dl-tlsdesc + gen-as-const-headers += dl-link.sym ++ ++ifeq (yes,$(aarch64-variant-pcs)) ++tests += tst-vpcs ++modules-names += tst-vpcs-mod ++LDFLAGS-tst-vpcs-mod.so = -Wl,-z,lazy ++$(objpfx)tst-vpcs: $(objpfx)tst-vpcs-mod.so ++endif + endif + + ifeq ($(subdir),csu) +diff --git a/sysdeps/aarch64/configure b/sysdeps/aarch64/configure +index 5bd355a6917df365..f78a79338aba1e34 100644 +--- a/sysdeps/aarch64/configure ++++ b/sysdeps/aarch64/configure +@@ -172,3 +172,43 @@ else + config_vars="$config_vars + default-abi = lp64" + fi ++ ++# Check if binutils supports variant PCS symbols. ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for variant PCS support" >&5 ++$as_echo_n "checking for variant PCS support... " >&6; } ++if ${libc_cv_aarch64_variant_pcs+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat > conftest.S <&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } \ ++ && { ac_try='$READELF -dW conftest.so | grep -q AARCH64_VARIANT_PCS' ++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 ++ test $ac_status = 0; }; } ++ then ++ libc_cv_aarch64_variant_pcs=yes ++ fi ++ rm -rf conftest.* ++fi ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_aarch64_variant_pcs" >&5 ++$as_echo "$libc_cv_aarch64_variant_pcs" >&6; } ++config_vars="$config_vars ++aarch64-variant-pcs = $libc_cv_aarch64_variant_pcs" +diff --git a/sysdeps/aarch64/configure.ac b/sysdeps/aarch64/configure.ac +index 7851dd4dac345b2a..7f13bfb93b60bfd7 100644 +--- a/sysdeps/aarch64/configure.ac ++++ b/sysdeps/aarch64/configure.ac +@@ -20,3 +20,25 @@ if test $libc_cv_aarch64_be = yes; then + else + LIBC_CONFIG_VAR([default-abi], [lp64]) + fi ++ ++# Check if binutils supports variant PCS symbols. ++AC_CACHE_CHECK([for variant PCS support], [libc_cv_aarch64_variant_pcs], [dnl ++ cat > conftest.S <. */ ++ ++ .variant_pcs vpcs_call ++ .global vpcs_call ++ .type vpcs_call, %function ++vpcs_call: ++ .cfi_startproc ++ hint 34 /* bti c. */ ++ ++ /* Save register state to *x0. */ ++ stp x0, x1, [x0] ++ stp x2, x3, [x0, 16] ++ stp x4, x5, [x0, 32] ++ stp x6, x7, [x0, 48] ++ stp x8, x9, [x0, 64] ++ stp x10, x11, [x0, 80] ++ stp x12, x13, [x0, 96] ++ stp x14, x15, [x0, 112] ++ stp x16, x17, [x0, 128] ++ stp x18, x19, [x0, 144] ++ stp x20, x21, [x0, 160] ++ stp x22, x23, [x0, 176] ++ stp x24, x25, [x0, 192] ++ stp x26, x27, [x0, 208] ++ stp x28, x29, [x0, 224] ++ mov x1, sp ++ stp x30, x1, [x0, 240] ++ stp q0, q1, [x0, 256] ++ stp q2, q3, [x0, 288] ++ stp q4, q5, [x0, 320] ++ stp q6, q7, [x0, 352] ++ stp q8, q9, [x0, 384] ++ stp q10, q11, [x0, 416] ++ stp q12, q13, [x0, 448] ++ stp q14, q15, [x0, 480] ++ stp q16, q17, [x0, 512] ++ stp q18, q19, [x0, 544] ++ stp q20, q21, [x0, 576] ++ stp q22, q23, [x0, 608] ++ stp q24, q25, [x0, 640] ++ stp q26, q27, [x0, 672] ++ stp q28, q29, [x0, 704] ++ stp q30, q31, [x0, 736] ++ ret ++ .cfi_endproc ++ .size vpcs_call, .-vpcs_call ++ ++ .global vpcs_call_regs ++ .type vpcs_call_regs, %function ++vpcs_call_regs: ++ .cfi_startproc ++ hint 34 /* bti c. */ ++ ++ stp x29, x30, [sp, -160]! ++ mov x29, sp ++ ++ /* Save callee-saved registers. */ ++ stp x19, x20, [sp, 16] ++ stp x21, x22, [sp, 32] ++ stp x23, x24, [sp, 48] ++ stp x25, x26, [sp, 64] ++ stp x27, x28, [sp, 80] ++ stp d8, d9, [sp, 96] ++ stp d10, d11, [sp, 112] ++ stp d12, d13, [sp, 128] ++ stp d14, d15, [sp, 144] ++ ++ /* Initialize most registers from *x1, and save x0, x1, x29, x30, ++ and sp (== x29), so *x1 contains the register state. */ ++ stp x0, x1, [x1] ++ str x29, [x1, 232] ++ ldp x2, x3, [x1, 16] ++ ldp x4, x5, [x1, 32] ++ ldp x6, x7, [x1, 48] ++ ldp x8, x9, [x1, 64] ++ ldp x10, x11, [x1, 80] ++ ldp x12, x13, [x1, 96] ++ ldp x14, x15, [x1, 112] ++ ldp x16, x17, [x1, 128] ++ ldp x18, x19, [x1, 144] ++ ldp x20, x21, [x1, 160] ++ ldp x22, x23, [x1, 176] ++ ldp x24, x25, [x1, 192] ++ ldp x26, x27, [x1, 208] ++ ldr x28, [x1, 224] ++ /* Skip x29, x30, sp. */ ++ ldp q0, q1, [x1, 256] ++ ldp q2, q3, [x1, 288] ++ ldp q4, q5, [x1, 320] ++ ldp q6, q7, [x1, 352] ++ ldp q8, q9, [x1, 384] ++ ldp q10, q11, [x1, 416] ++ ldp q12, q13, [x1, 448] ++ ldp q14, q15, [x1, 480] ++ ldp q16, q17, [x1, 512] ++ ldp q18, q19, [x1, 544] ++ ldp q20, q21, [x1, 576] ++ ldp q22, q23, [x1, 608] ++ ldp q24, q25, [x1, 640] ++ ldp q26, q27, [x1, 672] ++ ldp q28, q29, [x1, 704] ++ ldp q30, q31, [x1, 736] ++ ++ /* Emulate a BL using B, but save x30 before the branch. */ ++ adr x30, .L_return_addr ++ stp x30, x29, [x1, 240] ++ b vpcs_call ++.L_return_addr: ++ ++ /* Restore callee-saved registers. */ ++ ldp x19, x20, [sp, 16] ++ ldp x21, x22, [sp, 32] ++ ldp x23, x24, [sp, 48] ++ ldp x25, x26, [sp, 64] ++ ldp x27, x28, [sp, 80] ++ ldp d8, d9, [sp, 96] ++ ldp d10, d11, [sp, 112] ++ ldp d12, d13, [sp, 128] ++ ldp d14, d15, [sp, 144] ++ ++ ldp x29, x30, [sp], 160 ++ ret ++ .cfi_endproc ++ .size vpcs_call_regs, .-vpcs_call_regs +diff --git a/sysdeps/aarch64/tst-vpcs.c b/sysdeps/aarch64/tst-vpcs.c +new file mode 100644 +index 0000000000000000..92a701eb7cdea8ac +--- /dev/null ++++ b/sysdeps/aarch64/tst-vpcs.c +@@ -0,0 +1,78 @@ ++/* Test that variant PCS calls don't clobber registers with lazy binding. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++struct regs ++{ ++ uint64_t x[32]; ++ union { ++ long double q[32]; ++ uint64_t u[64]; ++ } v; ++}; ++ ++/* Gives the registers in the caller and callee around a variant PCS call. ++ Most registers are initialized from BEFORE in the caller so they can ++ have values that likely show clobbers. Register state extensions such ++ as SVE is not covered here, only the base registers. */ ++void vpcs_call_regs (struct regs *after, struct regs *before); ++ ++static int ++do_test (void) ++{ ++ struct regs before, after; ++ int err = 0; ++ ++ unsigned char *p = (unsigned char *)&before; ++ for (int i = 0; i < sizeof before; i++) ++ p[i] = i & 0xff; ++ ++ vpcs_call_regs (&after, &before); ++ ++ for (int i = 0; i < 32; i++) ++ if (before.x[i] != after.x[i]) ++ { ++ if (i == 16 || i == 17) ++ /* Variant PCS allows clobbering x16 and x17. */ ++ continue; ++ err++; ++ printf ("x%d: before: 0x%016llx after: 0x%016llx\n", ++ i, ++ (unsigned long long)before.x[i], ++ (unsigned long long)after.x[i]); ++ } ++ for (int i = 0; i < 64; i++) ++ if (before.v.u[i] != after.v.u[i]) ++ { ++ err++; ++ printf ("v%d: before: 0x%016llx %016llx after: 0x%016llx %016llx\n", ++ i/2, ++ (unsigned long long)before.v.u[2*(i/2)+1], ++ (unsigned long long)before.v.u[2*(i/2)], ++ (unsigned long long)after.v.u[2*(i/2)+1], ++ (unsigned long long)after.v.u[2*(i/2)]); ++ } ++ if (err) ++ FAIL_EXIT1 ("The variant PCS call clobbered %d registers.\n", err); ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1912544.patch b/glibc-rh1912544.patch new file mode 100755 index 0000000..c64e731 --- /dev/null +++ b/glibc-rh1912544.patch @@ -0,0 +1,126 @@ +commit ee7a3144c9922808181009b7b3e50e852fb4999b +Author: Andreas Schwab +Date: Mon Dec 21 08:56:43 2020 +0530 + + Fix buffer overrun in EUC-KR conversion module (bz #24973) + + The byte 0xfe as input to the EUC-KR conversion denotes a user-defined + area and is not allowed. The from_euc_kr function used to skip two bytes + when told to skip over the unknown designation, potentially running over + the buffer end. + +# Conflicts: +# iconvdata/Makefile + +diff --git a/iconvdata/Makefile b/iconvdata/Makefile +index 06e161d9b8f67118..a47a4c07cd2e3d1b 100644 +--- a/iconvdata/Makefile ++++ b/iconvdata/Makefile +@@ -73,7 +73,7 @@ modules.so := $(addsuffix .so, $(modules)) + ifeq (yes,$(build-shared)) + tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ + tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \ +- bug-iconv10 bug-iconv11 bug-iconv12 ++ bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 + ifeq ($(have-thread-library),yes) + tests += bug-iconv3 + endif +diff --git a/iconvdata/bug-iconv13.c b/iconvdata/bug-iconv13.c +new file mode 100644 +index 0000000000000000..87aaff398e0f6167 +--- /dev/null ++++ b/iconvdata/bug-iconv13.c +@@ -0,0 +1,53 @@ ++/* bug 24973: Test EUC-KR module ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ iconv_t cd = iconv_open ("UTF-8//IGNORE", "EUC-KR"); ++ TEST_VERIFY_EXIT (cd != (iconv_t) -1); ++ ++ /* 0xfe (->0x7e : row 94) and 0xc9 (->0x49 : row 41) are user-defined ++ areas, which are not allowed and should be skipped over due to ++ //IGNORE. The trailing 0xfe also is an incomplete sequence, which ++ should be checked first. */ ++ char input[4] = { '\xc9', '\xa1', '\0', '\xfe' }; ++ char *inptr = input; ++ size_t insize = sizeof (input); ++ char output[4]; ++ char *outptr = output; ++ size_t outsize = sizeof (output); ++ ++ /* This used to crash due to buffer overrun. */ ++ TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == (size_t) -1); ++ TEST_VERIFY (errno == EINVAL); ++ /* The conversion should produce one character, the converted null ++ character. */ ++ TEST_VERIFY (sizeof (output) - outsize == 1); ++ ++ TEST_VERIFY_EXIT (iconv_close (cd) != -1); ++ ++ return 0; ++} ++ ++#include +diff --git a/iconvdata/euc-kr.c b/iconvdata/euc-kr.c +index 73e02817a07e873d..dc7eaa6596f5d4d4 100644 +--- a/iconvdata/euc-kr.c ++++ b/iconvdata/euc-kr.c +@@ -80,11 +80,7 @@ euckr_from_ucs4 (uint32_t ch, unsigned char *cp) + \ + if (ch <= 0x9f) \ + ++inptr; \ +- /* 0xfe(->0x7e : row 94) and 0xc9(->0x59 : row 41) are \ +- user-defined areas. */ \ +- else if (__builtin_expect (ch == 0xa0, 0) \ +- || __builtin_expect (ch > 0xfe, 0) \ +- || __builtin_expect (ch == 0xc9, 0)) \ ++ else if (__glibc_unlikely (ch == 0xa0)) \ + { \ + /* This is illegal. */ \ + STANDARD_FROM_LOOP_ERR_HANDLER (1); \ +diff --git a/iconvdata/ksc5601.h b/iconvdata/ksc5601.h +index 5588d3a14b667b42..fa2d30677c41f46a 100644 +--- a/iconvdata/ksc5601.h ++++ b/iconvdata/ksc5601.h +@@ -50,15 +50,15 @@ ksc5601_to_ucs4 (const unsigned char **s, size_t avail, unsigned char offset) + unsigned char ch2; + int idx; + ++ if (avail < 2) ++ return 0; ++ + /* row 94(0x7e) and row 41(0x49) are user-defined area in KS C 5601 */ + + if (ch < offset || (ch - offset) <= 0x20 || (ch - offset) >= 0x7e + || (ch - offset) == 0x49) + return __UNKNOWN_10646_CHAR; + +- if (avail < 2) +- return 0; +- + ch2 = (*s)[1]; + if (ch2 < offset || (ch2 - offset) <= 0x20 || (ch2 - offset) >= 0x7f) + return __UNKNOWN_10646_CHAR; diff --git a/glibc-rh1912670-1.patch b/glibc-rh1912670-1.patch new file mode 100755 index 0000000..92bd13d --- /dev/null +++ b/glibc-rh1912670-1.patch @@ -0,0 +1,266 @@ +Conflicts in sysdeps/unix/sysv/linux/semctl.c were due to 64-bit time_t +and RHEL8 has a simpler implementation. + +Conflicts in sysdeps/unix/sysv/linux/Makefile were due to the usual test +case conflicts. + +commit 574500a108be1d2a6a0dc97a075c9e0a98371aba +Author: Dmitry V. Levin +Date: Tue Sep 29 14:10:20 2020 -0300 + + sysvipc: Fix SEM_STAT_ANY kernel argument pass [BZ #26637] + + Handle SEM_STAT_ANY the same way as SEM_STAT so that the buffer argument + of SEM_STAT_ANY is properly passed to the kernel and back. + + The regression testcase checks for Linux specifix SysV ipc message + control extension. For IPC_INFO/SEM_INFO it tries to match the values + against the tunable /proc values and for SEM_STAT/SEM_STAT_ANY it + check if the create message queue is within the global list returned + by the kernel. + + Checked on x86_64-linux-gnu and on i686-linux-gnu (Linux v5.4 and on + Linux v4.15). + + Co-authored-by: Adhemerval Zanella + +# Conflicts: +# sysdeps/unix/sysv/linux/Makefile +# sysdeps/unix/sysv/linux/semctl.c + +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index fb4ccd63ddec7eca..c6907796152eb09d 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -45,7 +45,8 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \ + tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \ + tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \ + test-errno-linux tst-memfd_create tst-mlock2 tst-pkey \ +- tst-rlimit-infinity tst-ofdlocks ++ tst-rlimit-infinity tst-ofdlocks \ ++ tst-sysvsem-linux + tests-internal += tst-ofdlocks-compat + + +diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c +index e2925447eba2ee94..bdf31ca7747fe5a4 100644 +--- a/sysdeps/unix/sysv/linux/semctl.c ++++ b/sysdeps/unix/sysv/linux/semctl.c +@@ -51,6 +51,7 @@ __new_semctl (int semid, int semnum, int cmd, ...) + case IPC_STAT: /* arg.buf */ + case IPC_SET: + case SEM_STAT: ++ case SEM_STAT_ANY: + case IPC_INFO: /* arg.__buf */ + case SEM_INFO: + va_start (ap, cmd); +@@ -90,6 +91,7 @@ __old_semctl (int semid, int semnum, int cmd, ...) + case IPC_STAT: /* arg.buf */ + case IPC_SET: + case SEM_STAT: ++ case SEM_STAT_ANY: + case IPC_INFO: /* arg.__buf */ + case SEM_INFO: + va_start (ap, cmd); +diff --git a/sysdeps/unix/sysv/linux/tst-sysvsem-linux.c b/sysdeps/unix/sysv/linux/tst-sysvsem-linux.c +new file mode 100644 +index 0000000000000000..45f19e2d37ed194a +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-sysvsem-linux.c +@@ -0,0 +1,184 @@ ++/* Basic tests for Linux SYSV semaphore extensions. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++/* These are for the temporary file we generate. */ ++static char *name; ++static int semid; ++ ++static void ++remove_sem (void) ++{ ++ /* Enforce message queue removal in case of early test failure. ++ Ignore error since the sem may already have being removed. */ ++ semctl (semid, 0, IPC_RMID, 0); ++} ++ ++static void ++do_prepare (int argc, char *argv[]) ++{ ++ TEST_VERIFY_EXIT (create_temp_file ("tst-sysvsem.", &name) != -1); ++} ++ ++#define PREPARE do_prepare ++ ++#define SEM_MODE 0644 ++ ++union semun ++{ ++ int val; ++ struct semid_ds *buf; ++ unsigned short *array; ++ struct seminfo *__buf; ++}; ++ ++struct test_seminfo ++{ ++ int semmsl; ++ int semmns; ++ int semopm; ++ int semmni; ++}; ++ ++/* It tries to obtain some system-wide SysV semaphore information from /proc ++ to check against IPC_INFO/SEM_INFO. The /proc only returns the tunables ++ value of SEMMSL, SEMMNS, SEMOPM, and SEMMNI. ++ ++ The kernel also returns constant value for SEMVMX, SEMMNU, SEMMAP, SEMUME, ++ and also SEMUSZ and SEMAEM (for IPC_INFO). The issue to check them is they ++ might change over kernel releases. */ ++ ++static void ++read_sem_stat (struct test_seminfo *tseminfo) ++{ ++ FILE *f = fopen ("/proc/sys/kernel/sem", "r"); ++ if (f == NULL) ++ FAIL_UNSUPPORTED ("/proc is not mounted or /proc/sys/kernel/sem is not " ++ "available"); ++ ++ int r = fscanf (f, "%d %d %d %d", ++ &tseminfo->semmsl, &tseminfo->semmns, &tseminfo->semopm, ++ &tseminfo->semmni); ++ TEST_VERIFY_EXIT (r == 4); ++ ++ fclose (f); ++} ++ ++ ++/* Check if the semaphore with IDX (index into the kernel's internal array) ++ matches the one with KEY. The CMD is either SEM_STAT or SEM_STAT_ANY. */ ++ ++static bool ++check_seminfo (int idx, key_t key, int cmd) ++{ ++ struct semid_ds seminfo; ++ int sid = semctl (idx, 0, cmd, (union semun) { .buf = &seminfo }); ++ /* Ignore unused array slot returned by the kernel or information from ++ unknown semaphores. */ ++ if ((sid == -1 && errno == EINVAL) || sid != semid) ++ return false; ++ ++ if (sid == -1) ++ FAIL_EXIT1 ("semctl with SEM_STAT failed (errno=%d)", errno); ++ ++ TEST_COMPARE (seminfo.sem_perm.__key, key); ++ TEST_COMPARE (seminfo.sem_perm.mode, SEM_MODE); ++ TEST_COMPARE (seminfo.sem_nsems, 1); ++ ++ return true; ++} ++ ++static int ++do_test (void) ++{ ++ atexit (remove_sem); ++ ++ key_t key = ftok (name, 'G'); ++ if (key == -1) ++ FAIL_EXIT1 ("ftok failed: %m"); ++ ++ semid = semget (key, 1, IPC_CREAT | IPC_EXCL | SEM_MODE); ++ if (semid == -1) ++ FAIL_EXIT1 ("semget failed: %m"); ++ ++ struct test_seminfo tipcinfo; ++ read_sem_stat (&tipcinfo); ++ ++ int semidx; ++ ++ { ++ struct seminfo ipcinfo; ++ semidx = semctl (semid, 0, IPC_INFO, (union semun) { .__buf = &ipcinfo }); ++ if (semidx == -1) ++ FAIL_EXIT1 ("semctl with IPC_INFO failed: %m"); ++ ++ TEST_COMPARE (ipcinfo.semmsl, tipcinfo.semmsl); ++ TEST_COMPARE (ipcinfo.semmns, tipcinfo.semmns); ++ TEST_COMPARE (ipcinfo.semopm, tipcinfo.semopm); ++ TEST_COMPARE (ipcinfo.semmni, tipcinfo.semmni); ++ } ++ ++ /* Same as before but with SEM_INFO. */ ++ { ++ struct seminfo ipcinfo; ++ semidx = semctl (semid, 0, SEM_INFO, (union semun) { .__buf = &ipcinfo }); ++ if (semidx == -1) ++ FAIL_EXIT1 ("semctl with IPC_INFO failed: %m"); ++ ++ TEST_COMPARE (ipcinfo.semmsl, tipcinfo.semmsl); ++ TEST_COMPARE (ipcinfo.semmns, tipcinfo.semmns); ++ TEST_COMPARE (ipcinfo.semopm, tipcinfo.semopm); ++ TEST_COMPARE (ipcinfo.semmni, tipcinfo.semmni); ++ } ++ ++ /* We check if the created semaphore shows in the system-wide status. */ ++ bool found = false; ++ for (int i = 0; i <= semidx; i++) ++ { ++ /* We can't tell apart if SEM_STAT_ANY is not supported (kernel older ++ than 4.17) or if the index used is invalid. So it just check if ++ value returned from a valid call matches the created semaphore. */ ++ check_seminfo (i, key, SEM_STAT_ANY); ++ ++ if (check_seminfo (i, key, SEM_STAT)) ++ { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) ++ FAIL_EXIT1 ("semctl with SEM_STAT/SEM_STAT_ANY could not find the " ++ "created semaphore"); ++ ++ if (semctl (semid, 0, IPC_RMID, 0) == -1) ++ FAIL_EXIT1 ("semctl failed: %m"); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysvipc/test-sysvsem.c b/sysvipc/test-sysvsem.c +index a8e9bff000949ff8..d197772917a7579d 100644 +--- a/sysvipc/test-sysvsem.c ++++ b/sysvipc/test-sysvsem.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include diff --git a/glibc-rh1912670-2.patch b/glibc-rh1912670-2.patch new file mode 100755 index 0000000..7f730f0 --- /dev/null +++ b/glibc-rh1912670-2.patch @@ -0,0 +1,151 @@ +Rewrite of the following commit but adjusted pre-64-bit time_t +conversion. We want to follow the same upstream behaviour and return +EINVAL for unknown commands rather than to attempt the command with an +argument of {0} which has likely never been tested upstream. + +commit a16d2abd496bd974a88207d5599265aae5ae4880 +Author: Adhemerval Zanella +Date: Tue Sep 29 14:29:48 2020 -0300 + + sysvipc: Return EINVAL for invalid semctl commands + + It avoids regressions on possible future commands that might require + additional libc support. The downside is new commands added by newer + kernels will need further glibc support. + + Checked on x86_64-linux-gnu and i686-linux-gnu (Linux v4.15 and v5.4). + +diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c +index bdf31ca7747fe5a4..03c56c69a5412c82 100644 +--- a/sysdeps/unix/sysv/linux/semctl.c ++++ b/sysdeps/unix/sysv/linux/semctl.c +@@ -58,6 +58,15 @@ __new_semctl (int semid, int semnum, int cmd, ...) + arg = va_arg (ap, union semun); + va_end (ap); + break; ++ case IPC_RMID: /* arg ignored. */ ++ case GETNCNT: ++ case GETPID: ++ case GETVAL: ++ case GETZCNT: ++ break; ++ default: ++ __set_errno (EINVAL); ++ return -1; + } + + #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS +diff --git a/sysvipc/test-sysvipc.h b/sysvipc/test-sysvipc.h +new file mode 100644 +index 0000000000000000..d7ed496511c10afb +--- /dev/null ++++ b/sysvipc/test-sysvipc.h +@@ -0,0 +1,85 @@ ++/* Basic definition for Sysv IPC test functions. ++ Copyright (C) 2020 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 ++ . */ ++ ++#ifndef _TEST_SYSV_H ++#define _TEST_SYSV_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* Return the first invalid command SysV IPC command from common shared ++ between message queue, shared memory, and semaphore. */ ++static inline int ++first_common_invalid_cmd (void) ++{ ++ const int common_cmds[] = { ++ IPC_RMID, ++ IPC_SET, ++ IPC_STAT, ++ IPC_INFO, ++ }; ++ ++ int invalid = 0; ++ for (int i = 0; i < array_length (common_cmds); i++) ++ { ++ if (invalid == common_cmds[i]) ++ { ++ invalid++; ++ i = 0; ++ } ++ } ++ ++ return invalid; ++} ++ ++/* Return the first invalid command SysV IPC command for semaphore. */ ++static inline int ++first_sem_invalid_cmd (void) ++{ ++ const int sem_cmds[] = { ++ GETPID, ++ GETVAL, ++ GETALL, ++ GETNCNT, ++ GETZCNT, ++ SETVAL, ++ SETALL, ++ SEM_STAT, ++ SEM_INFO, ++#ifdef SEM_STAT_ANY ++ SEM_STAT_ANY, ++#endif ++ }; ++ ++ int invalid = first_common_invalid_cmd (); ++ for (int i = 0; i < array_length (sem_cmds); i++) ++ { ++ if (invalid == sem_cmds[i]) ++ { ++ invalid++; ++ i = 0; ++ } ++ } ++ ++ return invalid; ++} ++ ++#endif /* _TEST_SYSV_H */ +diff --git a/sysvipc/test-sysvsem.c b/sysvipc/test-sysvsem.c +index d197772917a7579d..43a1460ec2b9308f 100644 +--- a/sysvipc/test-sysvsem.c ++++ b/sysvipc/test-sysvsem.c +@@ -25,6 +25,8 @@ + #include + #include + ++#include ++ + #include + #include + #include +@@ -80,6 +82,9 @@ do_test (void) + FAIL_EXIT1 ("semget failed (errno=%d)", errno); + } + ++ TEST_COMPARE (semctl (semid, 0, first_sem_invalid_cmd (), NULL), -1); ++ TEST_COMPARE (errno, EINVAL); ++ + /* Get semaphore kernel information and do some sanity checks. */ + struct semid_ds seminfo; + if (semctl (semid, 0, IPC_STAT, (union semun) { .buf = &seminfo }) == -1) diff --git a/glibc-rh1912670-3.patch b/glibc-rh1912670-3.patch new file mode 100755 index 0000000..046f63b --- /dev/null +++ b/glibc-rh1912670-3.patch @@ -0,0 +1,224 @@ +Backport only the test case: + * sysdeps/unix/sysv/linux/tst-sysvmsg-linux.c + +This improves coverage for IPC_INFO and MSG_INFO. + +We don't need the actual fix in the bug because we don't have the 64-bit +time_t handling backported. + +commit 20a00dbefca5695cccaa44846a482db8ccdd85ab +Author: Adhemerval Zanella +Date: Tue Sep 29 14:39:56 2020 -0300 + + sysvipc: Fix IPC_INFO and MSG_INFO handling [BZ #26639] + + Both commands are Linux extensions where the third argument is a + 'struct msginfo' instead of 'struct msqid_ds' and its information + does not contain any time related fields (so there is no need to + extra conversion for __IPC_TIME64. + + The regression testcase checks for Linux specifix SysV ipc message + control extension. For IPC_INFO/MSG_INFO it tries to match the values + against the tunable /proc values and for MSG_STAT/MSG_STAT_ANY it + check if the create message queue is within the global list returned + by the kernel. + + Checked on x86_64-linux-gnu and on i686-linux-gnu (Linux v5.4 and on + Linux v4.15). + +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index 7d04e3313c56c15d..688cf9fa9dea23a6 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -46,7 +46,7 @@ tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \ + tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \ + test-errno-linux tst-memfd_create tst-mlock2 tst-pkey \ + tst-rlimit-infinity tst-ofdlocks \ +- tst-sysvsem-linux ++ tst-sysvsem-linux tst-sysvmsg-linux + tests-internal += tst-ofdlocks-compat + + +diff --git a/sysdeps/unix/sysv/linux/tst-sysvmsg-linux.c b/sysdeps/unix/sysv/linux/tst-sysvmsg-linux.c +new file mode 100644 +index 0000000000000000..1857fab8c1fdf041 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-sysvmsg-linux.c +@@ -0,0 +1,177 @@ ++/* Basic tests for Linux SYSV message queue extensions. ++ Copyright (C) 2020-2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define MSGQ_MODE 0644 ++ ++/* These are for the temporary file we generate. */ ++static char *name; ++static int msqid; ++ ++static void ++remove_msq (void) ++{ ++ /* Enforce message queue removal in case of early test failure. ++ Ignore error since the msg may already have being removed. */ ++ msgctl (msqid, IPC_RMID, NULL); ++} ++ ++static void ++do_prepare (int argc, char *argv[]) ++{ ++ TEST_VERIFY_EXIT (create_temp_file ("tst-sysvmsg.", &name) != -1); ++} ++ ++#define PREPARE do_prepare ++ ++struct test_msginfo ++{ ++ int msgmax; ++ int msgmnb; ++ int msgmni; ++}; ++ ++/* It tries to obtain some system-wide SysV messsage queue information from ++ /proc to check against IPC_INFO/MSG_INFO. The /proc only returns the ++ tunables value of MSGMAX, MSGMNB, and MSGMNI. ++ ++ The kernel also returns constant value for MSGSSZ, MSGSEG and also MSGMAP, ++ MSGPOOL, and MSGTQL (for IPC_INFO). The issue to check them is they might ++ change over kernel releases. */ ++ ++static int ++read_proc_file (const char *file) ++{ ++ FILE *f = fopen (file, "r"); ++ if (f == NULL) ++ FAIL_UNSUPPORTED ("/proc is not mounted or %s is not available", file); ++ ++ int v; ++ int r = fscanf (f, "%d", & v); ++ TEST_VERIFY_EXIT (r == 1); ++ ++ fclose (f); ++ return v; ++} ++ ++ ++/* Check if the message queue with IDX (index into the kernel's internal ++ array) matches the one with KEY. The CMD is either MSG_STAT or ++ MSG_STAT_ANY. */ ++ ++static bool ++check_msginfo (int idx, key_t key, int cmd) ++{ ++ struct msqid_ds msginfo; ++ int mid = msgctl (idx, cmd, &msginfo); ++ /* Ignore unused array slot returned by the kernel or information from ++ unknown message queue. */ ++ if ((mid == -1 && errno == EINVAL) || mid != msqid) ++ return false; ++ ++ if (mid == -1) ++ FAIL_EXIT1 ("msgctl with %s failed: %m", ++ cmd == MSG_STAT ? "MSG_STAT" : "MSG_STAT_ANY"); ++ ++ TEST_COMPARE (msginfo.msg_perm.__key, key); ++ TEST_COMPARE (msginfo.msg_perm.mode, MSGQ_MODE); ++ TEST_COMPARE (msginfo.msg_qnum, 0); ++ ++ return true; ++} ++ ++static int ++do_test (void) ++{ ++ atexit (remove_msq); ++ ++ key_t key = ftok (name, 'G'); ++ if (key == -1) ++ FAIL_EXIT1 ("ftok failed: %m"); ++ ++ msqid = msgget (key, MSGQ_MODE | IPC_CREAT); ++ if (msqid == -1) ++ FAIL_EXIT1 ("msgget failed: %m"); ++ ++ struct test_msginfo tipcinfo; ++ tipcinfo.msgmax = read_proc_file ("/proc/sys/kernel/msgmax"); ++ tipcinfo.msgmnb = read_proc_file ("/proc/sys/kernel/msgmnb"); ++ tipcinfo.msgmni = read_proc_file ("/proc/sys/kernel/msgmni"); ++ ++ int msqidx; ++ ++ { ++ struct msginfo ipcinfo; ++ msqidx = msgctl (msqid, IPC_INFO, (struct msqid_ds *) &ipcinfo); ++ if (msqidx == -1) ++ FAIL_EXIT1 ("msgctl with IPC_INFO failed: %m"); ++ ++ TEST_COMPARE (ipcinfo.msgmax, tipcinfo.msgmax); ++ TEST_COMPARE (ipcinfo.msgmnb, tipcinfo.msgmnb); ++ TEST_COMPARE (ipcinfo.msgmni, tipcinfo.msgmni); ++ } ++ ++ /* Same as before but with MSG_INFO. */ ++ { ++ struct msginfo ipcinfo; ++ msqidx = msgctl (msqid, MSG_INFO, (struct msqid_ds *) &ipcinfo); ++ if (msqidx == -1) ++ FAIL_EXIT1 ("msgctl with IPC_INFO failed: %m"); ++ ++ TEST_COMPARE (ipcinfo.msgmax, tipcinfo.msgmax); ++ TEST_COMPARE (ipcinfo.msgmnb, tipcinfo.msgmnb); ++ TEST_COMPARE (ipcinfo.msgmni, tipcinfo.msgmni); ++ } ++ ++ /* We check if the created message queue shows in global list. */ ++ bool found = false; ++ for (int i = 0; i <= msqidx; i++) ++ { ++ /* We can't tell apart if MSG_STAT_ANY is not supported (kernel older ++ than 4.17) or if the index used is invalid. So it just check if the ++ value returned from a valid call matches the created message ++ queue. */ ++ check_msginfo (i, key, MSG_STAT_ANY); ++ ++ if (check_msginfo (i, key, MSG_STAT)) ++ { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) ++ FAIL_EXIT1 ("msgctl with MSG_STAT/MSG_STAT_ANY could not find the " ++ "created message queue"); ++ ++ if (msgctl (msqid, IPC_RMID, NULL) == -1) ++ FAIL_EXIT1 ("msgctl failed"); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh1912670-4.patch b/glibc-rh1912670-4.patch new file mode 100755 index 0000000..2b0c33f --- /dev/null +++ b/glibc-rh1912670-4.patch @@ -0,0 +1,98 @@ +This is a rewrite of the commit for the pre-64-bit time_t version of +the msgctl handling. Similar to semctl we want the RHEL8 handling of +the unknown commands to be the same as upstream. + +commit be9b0b9a012780a403a266c90878efffb9a5f3ca +Author: Adhemerval Zanella +Date: Tue Sep 29 14:45:09 2020 -0300 + + sysvipc: Return EINVAL for invalid msgctl commands + + It avoids regressions on possible future commands that might require + additional libc support. The downside is new commands added by newer + kernels will need further glibc support. + + Checked on x86_64-linux-gnu and i686-linux-gnu (Linux v4.15 and v5.4). + +diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c +index 7280cba31a8815a2..6a2c79d188b875b9 100644 +--- a/sysdeps/unix/sysv/linux/msgctl.c ++++ b/sysdeps/unix/sysv/linux/msgctl.c +@@ -29,6 +29,20 @@ + int + __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) + { ++ switch (cmd) ++ { ++ case IPC_RMID: ++ case IPC_SET: ++ case IPC_STAT: ++ case MSG_STAT: ++ case MSG_STAT_ANY: ++ case IPC_INFO: ++ case MSG_INFO: ++ break; ++ default: ++ __set_errno (EINVAL); ++ return -1; ++ } + #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS + return INLINE_SYSCALL_CALL (msgctl, msqid, cmd | __IPC_64, buf); + #else +diff --git a/sysvipc/test-sysvipc.h b/sysvipc/test-sysvipc.h +index ed0057b7871e505c..133fb71c6113a2b5 100644 +--- a/sysvipc/test-sysvipc.h ++++ b/sysvipc/test-sysvipc.h +@@ -134,4 +134,29 @@ first_shm_invalid_cmd (void) + return invalid; + } + ++/* Return the first invalid command SysV IPC command for message queue. */ ++static inline int ++first_msg_invalid_cmd (void) ++{ ++ const int msg_cmds[] = { ++ MSG_STAT, ++ MSG_INFO, ++#ifdef MSG_STAT_ANY ++ MSG_STAT_ANY, ++#endif ++ }; ++ ++ int invalid = first_common_invalid_cmd (); ++ for (int i = 0; i < array_length (msg_cmds); i++) ++ { ++ if (invalid == msg_cmds[i]) ++ { ++ invalid++; ++ i = 0; ++ } ++ } ++ ++ return invalid; ++} ++ + #endif /* _TEST_SYSV_H */ +diff --git a/sysvipc/test-sysvmsg.c b/sysvipc/test-sysvmsg.c +index 1e0471807cd26da1..74a907ad39ee114e 100644 +--- a/sysvipc/test-sysvmsg.c ++++ b/sysvipc/test-sysvmsg.c +@@ -24,6 +24,8 @@ + #include + #include + ++#include ++ + #include + #include + #include +@@ -86,6 +88,9 @@ do_test (void) + FAIL_EXIT1 ("msgget failed (errno=%d)", errno); + } + ++ TEST_COMPARE (msgctl (msqid, first_msg_invalid_cmd (), NULL), -1); ++ TEST_COMPARE (errno, EINVAL); ++ + /* Get message queue kernel information and do some sanity checks. */ + struct msqid_ds msginfo; + if (msgctl (msqid, IPC_STAT, &msginfo) == -1) diff --git a/glibc-rh1912670-5.patch b/glibc-rh1912670-5.patch new file mode 100755 index 0000000..2ffdbca --- /dev/null +++ b/glibc-rh1912670-5.patch @@ -0,0 +1,128 @@ +Rewrite of the following commit to support returning EINVAL for unknown +commands and therefore match upstream behaviour. + +commit 9ebaabeaac1a96b0d91f52902ce1dbf4f5a562dd +Author: Adhemerval Zanella +Date: Tue Sep 29 14:55:02 2020 -0300 + + sysvipc: Return EINVAL for invalid shmctl commands + + It avoids regressions on possible future commands that might require + additional libc support. The downside is new commands added by newer + kernels will need further glibc support. + + Checked on x86_64-linux-gnu and i686-linux-gnu (Linux v4.15 and v5.4). + +diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c +index 25c5152944a6fcf3..00768bc47614f9aa 100644 +--- a/sysdeps/unix/sysv/linux/shmctl.c ++++ b/sysdeps/unix/sysv/linux/shmctl.c +@@ -33,6 +33,22 @@ + int + __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) + { ++ switch (cmd) ++ { ++ case IPC_RMID: ++ case SHM_LOCK: ++ case SHM_UNLOCK: ++ case IPC_SET: ++ case IPC_STAT: ++ case SHM_STAT: ++ case SHM_STAT_ANY: ++ case IPC_INFO: ++ case SHM_INFO: ++ break; ++ default: ++ __set_errno (EINVAL); ++ break; ++ } + #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS + return INLINE_SYSCALL_CALL (shmctl, shmid, cmd | __IPC_64, buf); + #else +diff --git a/sysvipc/test-sysvipc.h b/sysvipc/test-sysvipc.h +index 21ef6c656581519e..d1c8349b45b5ce49 100644 +--- a/sysvipc/test-sysvipc.h ++++ b/sysvipc/test-sysvipc.h +@@ -25,7 +25,7 @@ + #include + #include + +-/* Return the first invalid command SysV IPC command from common shared ++/* Return the first invalid SysV IPC command from common shared + between message queue, shared memory, and semaphore. */ + static inline int + first_common_invalid_cmd (void) +@@ -50,7 +50,7 @@ first_common_invalid_cmd (void) + return invalid; + } + +-/* Return the first invalid command SysV IPC command for semaphore. */ ++/* Return the first invalid SysV IPC command for semaphore. */ + static inline int + first_sem_invalid_cmd (void) + { +@@ -82,7 +82,7 @@ first_sem_invalid_cmd (void) + return invalid; + } + +-/* Return the first invalid command SysV IPC command for message queue. */ ++/* Return the first invalid SysV IPC command for message queue. */ + static inline int + first_msg_invalid_cmd (void) + { +@@ -107,4 +107,31 @@ first_msg_invalid_cmd (void) + return invalid; + } + ++/* Return the first invalid SysV IPC command for shared memory. */ ++static inline int ++first_shm_invalid_cmd (void) ++{ ++ const int shm_cmds[] = { ++ SHM_STAT, ++ SHM_INFO, ++#ifdef SHM_STAT_ANY ++ SHM_STAT_ANY, ++#endif ++ SHM_LOCK, ++ SHM_UNLOCK ++ }; ++ ++ int invalid = first_common_invalid_cmd (); ++ for (int i = 0; i < array_length (shm_cmds); i++) ++ { ++ if (invalid == shm_cmds[i]) ++ { ++ invalid++; ++ i = 0; ++ } ++ } ++ ++ return invalid; ++} ++ + #endif /* _TEST_SYSV_H */ +diff --git a/sysvipc/test-sysvshm.c b/sysvipc/test-sysvshm.c +index a7c2e0bd4065dbcd..0fdfddf8550413e4 100644 +--- a/sysvipc/test-sysvshm.c ++++ b/sysvipc/test-sysvshm.c +@@ -25,6 +25,8 @@ + #include + #include + ++#include ++ + #include + #include + #include +@@ -81,6 +83,9 @@ do_test (void) + FAIL_EXIT1 ("shmget failed (errno=%d)", errno); + } + ++ TEST_COMPARE (shmctl (shmid, first_shm_invalid_cmd (), NULL), -1); ++ TEST_COMPARE (errno, EINVAL); ++ + /* Get shared memory kernel information and do some sanity checks. */ + struct shmid_ds shminfo; + if (shmctl (shmid, IPC_STAT, &shminfo) == -1) diff --git a/glibc-rh1918115.patch b/glibc-rh1918115.patch new file mode 100755 index 0000000..1556ff4 --- /dev/null +++ b/glibc-rh1918115.patch @@ -0,0 +1,23 @@ +commit 23af890b3f04e80da783ba64e6b6d94822e01d54 +Author: Ondřej Hošek +Date: Wed Aug 26 04:26:50 2020 +0200 + + x86-64: Fix FMA4 detection in ifunc [BZ #26534] + + A typo in commit 107e6a3c2212ba7a3a4ec7cae8d82d73f7c95d0b causes the + FMA4 code path to be taken on systems that support FMA, even if they do + not support FMA4. Fix this to detect FMA4. + +diff --git a/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h b/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h +index 76c677198dac5cb0..6cb70ce25209ee15 100644 +--- a/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h ++++ b/sysdeps/x86_64/fpu/multiarch/ifunc-fma4.h +@@ -32,7 +32,7 @@ IFUNC_SELECTOR (void) + && CPU_FEATURE_USABLE_P (cpu_features, AVX2)) + return OPTIMIZE (fma); + +- if (CPU_FEATURE_USABLE_P (cpu_features, FMA)) ++ if (CPU_FEATURE_USABLE_P (cpu_features, FMA4)) + return OPTIMIZE (fma4); + + return OPTIMIZE (sse2); diff --git a/glibc-rh1918719-1.patch b/glibc-rh1918719-1.patch new file mode 100755 index 0000000..622ced9 --- /dev/null +++ b/glibc-rh1918719-1.patch @@ -0,0 +1,453 @@ +From b9d83bf3eb57e1cf8ef785f1a58e13ddf162b6f3 Mon Sep 17 00:00:00 2001 +From: Raphael M Zinsly +Date: Thu, 12 Nov 2020 13:12:24 -0300 +Subject: powerpc: Add optimized strncpy for POWER9 + +Similar to the strcpy P9 optimization, this version uses VSX to improve +performance. + +Reviewed-by: Matheus Castanho +Reviewed-by: Tulio Magno Quites Machado Filho + +diff --git a/sysdeps/powerpc/powerpc64/le/power9/strncpy.S b/sysdeps/powerpc/powerpc64/le/power9/strncpy.S +new file mode 100644 +index 0000000000..cbfc37bda3 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power9/strncpy.S +@@ -0,0 +1,344 @@ ++/* Optimized strncpy implementation for POWER9 LE. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++ ++# ifndef STRNCPY ++# define FUNC_NAME strncpy ++# else ++# define FUNC_NAME STRNCPY ++# endif ++ ++#ifndef MEMSET ++/* For builds without IFUNC support, local calls should be made to internal ++ GLIBC symbol (created by libc_hidden_builtin_def). */ ++# ifdef SHARED ++# define MEMSET_is_local ++# define MEMSET __GI_memset ++# else ++# define MEMSET memset ++# endif ++#endif ++ ++#define FRAMESIZE (FRAME_MIN_SIZE+8) ++ ++/* Implements the function ++ ++ char * [r3] strncpy (char *dest [r3], const char *src [r4], size_t n [r5]) ++ ++ The implementation can load bytes past a null terminator, but only ++ up to the next 16-byte aligned address, so it never crosses a page. */ ++ ++.machine power9 ++#ifdef MEMSET_is_local ++ENTRY_TOCLESS (FUNC_NAME, 4) ++#else ++ENTRY (FUNC_NAME, 4) ++#endif ++ CALL_MCOUNT 2 ++ ++ /* NULL string optimizations */ ++ cmpdi r5, 0 ++ beqlr ++ ++ lbz r0,0(r4) ++ stb r0,0(r3) ++ addi r11,r3,1 ++ addi r5,r5,-1 ++ vspltisb v18,0 /* Zeroes in v18 */ ++ cmpdi r0,0 ++ beq L(zero_padding) ++ ++ /* Empty/1-byte string optimization */ ++ cmpdi r5,0 ++ beqlr ++ ++ addi r4,r4,1 ++ neg r7,r4 ++ rldicl r9,r7,0,60 /* How many bytes to get source 16B aligned? */ ++ ++ /* Get source 16B aligned */ ++ lvx v0,0,r4 ++ lvsr v1,0,r4 ++ vperm v0,v18,v0,v1 ++ ++ vcmpequb v6,v0,v18 /* 0xff if byte is NULL, 0x00 otherwise */ ++ vctzlsbb r7,v6 /* Number of trailing zeroes */ ++ addi r8,r7,1 /* Add null terminator */ ++ ++ /* r8 = bytes including null ++ r9 = bytes to get source 16B aligned ++ if r8 > r9 ++ no null, copy r9 bytes ++ else ++ there is a null, copy r8 bytes and return. */ ++ cmpld r8,r9 ++ bgt L(no_null) ++ ++ cmpld cr6,r8,r5 /* r8 <= n? */ ++ ble cr6,L(null) ++ ++ sldi r10,r5,56 /* stxvl wants size in top 8 bits */ ++ stxvl 32+v0,r11,r10 /* Partial store */ ++ ++ blr ++ ++L(null): ++ sldi r10,r8,56 /* stxvl wants size in top 8 bits */ ++ stxvl 32+v0,r11,r10 /* Partial store */ ++ ++ add r11,r11,r8 ++ sub r5,r5,r8 ++ b L(zero_padding) ++ ++L(no_null): ++ cmpld r9,r5 /* Check if length was reached. */ ++ bge L(n_tail1) ++ ++ sldi r10,r9,56 /* stxvl wants size in top 8 bits */ ++ stxvl 32+v0,r11,r10 /* Partial store */ ++ ++ add r4,r4,r9 ++ add r11,r11,r9 ++ sub r5,r5,r9 ++ ++L(loop): ++ cmpldi cr6,r5,64 /* Check if length was reached. */ ++ ble cr6,L(final_loop) ++ ++ lxv 32+v0,0(r4) ++ vcmpequb. v6,v0,v18 /* Any zero bytes? */ ++ bne cr6,L(prep_tail1) ++ ++ lxv 32+v1,16(r4) ++ vcmpequb. v6,v1,v18 /* Any zero bytes? */ ++ bne cr6,L(prep_tail2) ++ ++ lxv 32+v2,32(r4) ++ vcmpequb. v6,v2,v18 /* Any zero bytes? */ ++ bne cr6,L(prep_tail3) ++ ++ lxv 32+v3,48(r4) ++ vcmpequb. v6,v3,v18 /* Any zero bytes? */ ++ bne cr6,L(prep_tail4) ++ ++ stxv 32+v0,0(r11) ++ stxv 32+v1,16(r11) ++ stxv 32+v2,32(r11) ++ stxv 32+v3,48(r11) ++ ++ addi r4,r4,64 ++ addi r11,r11,64 ++ addi r5,r5,-64 ++ ++ b L(loop) ++ ++L(final_loop): ++ cmpldi cr5,r5,16 ++ lxv 32+v0,0(r4) ++ vcmpequb. v6,v0,v18 /* Any zero bytes? */ ++ ble cr5,L(prep_n_tail1) ++ bne cr6,L(count_tail1) ++ addi r5,r5,-16 ++ ++ cmpldi cr5,r5,16 ++ lxv 32+v1,16(r4) ++ vcmpequb. v6,v1,v18 /* Any zero bytes? */ ++ ble cr5,L(prep_n_tail2) ++ bne cr6,L(count_tail2) ++ addi r5,r5,-16 ++ ++ cmpldi cr5,r5,16 ++ lxv 32+v2,32(r4) ++ vcmpequb. v6,v2,v18 /* Any zero bytes? */ ++ ble cr5,L(prep_n_tail3) ++ bne cr6,L(count_tail3) ++ addi r5,r5,-16 ++ ++ lxv 32+v3,48(r4) ++ vcmpequb. v6,v3,v18 /* Any zero bytes? */ ++ beq cr6,L(n_tail4) ++ ++ vctzlsbb r8,v6 /* Number of trailing zeroes */ ++ cmpld r8,r5 /* r8 < n? */ ++ blt L(tail4) ++ ++L(n_tail4): ++ stxv 32+v0,0(r11) ++ stxv 32+v1,16(r11) ++ stxv 32+v2,32(r11) ++ sldi r10,r5,56 /* stxvl wants size in top 8 bits */ ++ addi r11,r11,48 /* Offset */ ++ stxvl 32+v3,r11,r10 /* Partial store */ ++ blr ++ ++L(prep_n_tail1): ++ beq cr6,L(n_tail1) /* Any zero bytes? */ ++ vctzlsbb r8,v6 /* Number of trailing zeroes */ ++ cmpld r8,r5 /* r8 < n? */ ++ blt L(tail1) ++ ++L(n_tail1): ++ sldi r10,r5,56 /* stxvl wants size in top 8 bits */ ++ stxvl 32+v0,r11,r10 /* Partial store */ ++ blr ++ ++L(prep_n_tail2): ++ beq cr6,L(n_tail2) /* Any zero bytes? */ ++ vctzlsbb r8,v6 /* Number of trailing zeroes */ ++ cmpld r8,r5 /* r8 < n? */ ++ blt L(tail2) ++ ++L(n_tail2): ++ stxv 32+v0,0(r11) ++ sldi r10,r5,56 /* stxvl wants size in top 8 bits */ ++ addi r11,r11,16 /* offset */ ++ stxvl 32+v1,r11,r10 /* Partial store */ ++ blr ++ ++L(prep_n_tail3): ++ beq cr6,L(n_tail3) /* Any zero bytes? */ ++ vctzlsbb r8,v6 /* Number of trailing zeroes */ ++ cmpld r8,r5 /* r8 < n? */ ++ blt L(tail3) ++ ++L(n_tail3): ++ stxv 32+v0,0(r11) ++ stxv 32+v1,16(r11) ++ sldi r10,r5,56 /* stxvl wants size in top 8 bits */ ++ addi r11,r11,32 /* Offset */ ++ stxvl 32+v2,r11,r10 /* Partial store */ ++ blr ++ ++L(prep_tail1): ++L(count_tail1): ++ vctzlsbb r8,v6 /* Number of trailing zeroes */ ++L(tail1): ++ addi r9,r8,1 /* Add null terminator */ ++ sldi r10,r9,56 /* stxvl wants size in top 8 bits */ ++ stxvl 32+v0,r11,r10 /* Partial store */ ++ add r11,r11,r9 ++ sub r5,r5,r9 ++ b L(zero_padding) ++ ++L(prep_tail2): ++ addi r5,r5,-16 ++L(count_tail2): ++ vctzlsbb r8,v6 /* Number of trailing zeroes */ ++L(tail2): ++ addi r9,r8,1 /* Add null terminator */ ++ stxv 32+v0,0(r11) ++ sldi r10,r9,56 /* stxvl wants size in top 8 bits */ ++ addi r11,r11,16 /* offset */ ++ stxvl 32+v1,r11,r10 /* Partial store */ ++ add r11,r11,r9 ++ sub r5,r5,r9 ++ b L(zero_padding) ++ ++L(prep_tail3): ++ addi r5,r5,-32 ++L(count_tail3): ++ vctzlsbb r8,v6 /* Number of trailing zeroes */ ++L(tail3): ++ addi r9,r8,1 /* Add null terminator */ ++ stxv 32+v0,0(r11) ++ stxv 32+v1,16(r11) ++ sldi r10,r9,56 /* stxvl wants size in top 8 bits */ ++ addi r11,r11,32 /* offset */ ++ stxvl 32+v2,r11,r10 /* Partial store */ ++ add r11,r11,r9 ++ sub r5,r5,r9 ++ b L(zero_padding) ++ ++L(prep_tail4): ++ addi r5,r5,-48 ++ vctzlsbb r8,v6 /* Number of trailing zeroes */ ++L(tail4): ++ addi r9,r8,1 /* Add null terminator */ ++ stxv 32+v0,0(r11) ++ stxv 32+v1,16(r11) ++ stxv 32+v2,32(r11) ++ sldi r10,r9,56 /* stxvl wants size in top 8 bits */ ++ addi r11,r11,48 /* offset */ ++ stxvl 32+v3,r11,r10 /* Partial store */ ++ add r11,r11,r9 ++ sub r5,r5,r9 ++ ++/* This code pads the remainder of dest with NULL bytes. For large numbers ++ memset gives a better performance, 255 was chosen through experimentation. ++ */ ++L(zero_padding): ++ cmpldi r5,255 ++ bge L(zero_padding_memset) ++ ++L(zero_padding_loop): ++ cmpldi cr6,r5,16 /* Check if length was reached. */ ++ ble cr6,L(zero_padding_end) ++ ++ stxv v18,0(r11) ++ addi r11,r11,16 ++ addi r5,r5,-16 ++ ++ b L(zero_padding_loop) ++ ++L(zero_padding_end): ++ sldi r10,r5,56 /* stxvl wants size in top 8 bits */ ++ stxvl v18,r11,r10 /* Partial store */ ++ blr ++ ++ .align 4 ++L(zero_padding_memset): ++ std r30,-8(r1) /* Save r30 on the stack. */ ++ cfi_offset(r30, -8) ++ mr r30,r3 /* Save the return value of strncpy. */ ++ /* Prepare the call to memset. */ ++ mr r3,r11 /* Pointer to the area to be zero-filled. */ ++ li r4,0 /* Byte to be written (zero). */ ++ ++ /* We delayed the creation of the stack frame, as well as the saving of ++ the link register, because only at this point, we are sure that ++ doing so is actually needed. */ ++ ++ /* Save the link register. */ ++ mflr r0 ++ std r0,16(r1) ++ ++ /* Create the stack frame. */ ++ stdu r1,-FRAMESIZE(r1) ++ cfi_adjust_cfa_offset(FRAMESIZE) ++ cfi_offset(lr, 16) ++ ++ bl MEMSET ++#ifndef MEMSET_is_local ++ nop ++#endif ++ ++ ld r0,FRAMESIZE+16(r1) ++ ++ mr r3,r30 /* Restore the return value of strncpy, i.e.: ++ dest. */ ++ ld r30,FRAMESIZE-8(r1) /* Restore r30. */ ++ /* Restore the stack frame. */ ++ addi r1,r1,FRAMESIZE ++ cfi_adjust_cfa_offset(-FRAMESIZE) ++ /* Restore the link register. */ ++ mtlr r0 ++ cfi_restore(lr) ++ blr ++ ++END (FUNC_NAME) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index 19acb6c64a..cd2b47b403 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -33,7 +33,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + + ifneq (,$(filter %le,$(config-machine))) + sysdep_routines += strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 \ +- rawmemchr-power9 strlen-power9 ++ rawmemchr-power9 strlen-power9 strncpy-power9 + endif + CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops + CFLAGS-strncase_l-power7.c += -mcpu=power7 -funroll-loops +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index dd54e7d6bb..135326c97a 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -301,6 +301,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/powerpc/powerpc64/multiarch/strncpy.c. */ + IFUNC_IMPL (i, name, strncpy, ++#ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, strncpy, ++ (hwcap2 & PPC_FEATURE2_ARCH_3_00) ++ && (hwcap & PPC_FEATURE_HAS_VSX), ++ __strncpy_power9) ++#endif + IFUNC_IMPL_ADD (array, i, strncpy, + hwcap2 & PPC_FEATURE2_ARCH_2_07, + __strncpy_power8) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncpy-power9.S b/sysdeps/powerpc/powerpc64/multiarch/strncpy-power9.S +new file mode 100644 +index 0000000000..2b57c190f5 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/strncpy-power9.S +@@ -0,0 +1,32 @@ ++/* Optimized strncpy implementation for POWER9 LE. ++ Copyright (C) 2020 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 ++ . */ ++ ++#if defined __LITTLE_ENDIAN__ && IS_IN (libc) ++# define STRNCPY __strncpy_power9 ++ ++# undef libc_hidden_builtin_def ++# define libc_hidden_builtin_def(name) ++ ++/* memset is used to pad the end of the string. */ ++# define MEMSET __memset_power8 ++# ifdef SHARED ++# define MEMSET_is_local ++# endif ++ ++# include ++#endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strncpy.c b/sysdeps/powerpc/powerpc64/multiarch/strncpy.c +index 7bacf28aca..af8b6cdd9c 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/strncpy.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/strncpy.c +@@ -28,11 +28,19 @@ + extern __typeof (strncpy) __strncpy_ppc attribute_hidden; + extern __typeof (strncpy) __strncpy_power7 attribute_hidden; + extern __typeof (strncpy) __strncpy_power8 attribute_hidden; ++# ifdef __LITTLE_ENDIAN__ ++extern __typeof (strncpy) __strncpy_power9 attribute_hidden; ++# endif + # undef strncpy + + /* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle + ifunc symbol properly. */ + libc_ifunc_redirected (__redirect_strncpy, strncpy, ++# ifdef __LITTLE_ENDIAN__ ++ (hwcap2 & PPC_FEATURE2_ARCH_3_00) && ++ (hwcap & PPC_FEATURE_HAS_VSX) ++ ? __strncpy_power9 : ++# endif + (hwcap2 & PPC_FEATURE2_ARCH_2_07) + ? __strncpy_power8 + : (hwcap & PPC_FEATURE_HAS_VSX) diff --git a/glibc-rh1918719-2.patch b/glibc-rh1918719-2.patch new file mode 100755 index 0000000..0a50fd5 --- /dev/null +++ b/glibc-rh1918719-2.patch @@ -0,0 +1,307 @@ +From 7beee7b39adeda657f45989b0635033dae25a1fd Mon Sep 17 00:00:00 2001 +From: Raphael M Zinsly +Date: Thu, 12 Nov 2020 13:12:24 -0300 +Subject: powerpc: Add optimized stpncpy for POWER9 + +Add stpncpy support into the POWER9 strncpy. + +Reviewed-by: Matheus Castanho +Reviewed-by: Tulio Magno Quites Machado Filho + +diff --git a/sysdeps/powerpc/powerpc64/le/power9/stpncpy.S b/sysdeps/powerpc/powerpc64/le/power9/stpncpy.S +new file mode 100644 +index 0000000000..81d9673d8b +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power9/stpncpy.S +@@ -0,0 +1,24 @@ ++/* Optimized stpncpy implementation for POWER9 LE. ++ Copyright (C) 2020 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 ++ . */ ++ ++#define USE_AS_STPNCPY ++#include ++ ++weak_alias (__stpncpy, stpncpy) ++libc_hidden_def (__stpncpy) ++libc_hidden_builtin_def (stpncpy) +diff --git a/sysdeps/powerpc/powerpc64/le/power9/strncpy.S b/sysdeps/powerpc/powerpc64/le/power9/strncpy.S +index cbfc37bda3..b4ba428662 100644 +--- a/sysdeps/powerpc/powerpc64/le/power9/strncpy.S ++++ b/sysdeps/powerpc/powerpc64/le/power9/strncpy.S +@@ -18,11 +18,19 @@ + + #include + ++#ifdef USE_AS_STPNCPY ++# ifndef STPNCPY ++# define FUNC_NAME __stpncpy ++# else ++# define FUNC_NAME STPNCPY ++# endif ++#else + # ifndef STRNCPY + # define FUNC_NAME strncpy + # else + # define FUNC_NAME STRNCPY + # endif ++#endif /* !USE_AS_STPNCPY */ + + #ifndef MEMSET + /* For builds without IFUNC support, local calls should be made to internal +@@ -41,6 +49,12 @@ + + char * [r3] strncpy (char *dest [r3], const char *src [r4], size_t n [r5]) + ++ or ++ ++ char * [r3] stpncpy (char *dest [r3], const char *src [r4], size_t n [r5]) ++ ++ if USE_AS_STPNCPY is defined. ++ + The implementation can load bytes past a null terminator, but only + up to the next 16-byte aligned address, so it never crosses a page. */ + +@@ -66,7 +80,15 @@ ENTRY (FUNC_NAME, 4) + + /* Empty/1-byte string optimization */ + cmpdi r5,0 ++#ifdef USE_AS_STPNCPY ++ bgt L(cont) ++ /* Compute pointer to last byte copied into dest. */ ++ addi r3,r3,1 ++ blr ++L(cont): ++#else + beqlr ++#endif + + addi r4,r4,1 + neg r7,r4 +@@ -96,12 +118,20 @@ ENTRY (FUNC_NAME, 4) + sldi r10,r5,56 /* stxvl wants size in top 8 bits */ + stxvl 32+v0,r11,r10 /* Partial store */ + ++#ifdef USE_AS_STPNCPY ++ /* Compute pointer to last byte copied into dest. */ ++ add r3,r11,r5 ++#endif + blr + + L(null): + sldi r10,r8,56 /* stxvl wants size in top 8 bits */ + stxvl 32+v0,r11,r10 /* Partial store */ + ++#ifdef USE_AS_STPNCPY ++ /* Compute pointer to last byte copied into dest. */ ++ add r3,r11,r7 ++#endif + add r11,r11,r8 + sub r5,r5,r8 + b L(zero_padding) +@@ -185,6 +215,10 @@ L(n_tail4): + sldi r10,r5,56 /* stxvl wants size in top 8 bits */ + addi r11,r11,48 /* Offset */ + stxvl 32+v3,r11,r10 /* Partial store */ ++#ifdef USE_AS_STPNCPY ++ /* Compute pointer to last byte copied into dest. */ ++ add r3,r11,r5 ++#endif + blr + + L(prep_n_tail1): +@@ -196,6 +230,10 @@ L(prep_n_tail1): + L(n_tail1): + sldi r10,r5,56 /* stxvl wants size in top 8 bits */ + stxvl 32+v0,r11,r10 /* Partial store */ ++#ifdef USE_AS_STPNCPY ++ /* Compute pointer to last byte copied into dest. */ ++ add r3,r11,r5 ++#endif + blr + + L(prep_n_tail2): +@@ -209,6 +247,10 @@ L(n_tail2): + sldi r10,r5,56 /* stxvl wants size in top 8 bits */ + addi r11,r11,16 /* offset */ + stxvl 32+v1,r11,r10 /* Partial store */ ++#ifdef USE_AS_STPNCPY ++ /* Compute pointer to last byte copied into dest. */ ++ add r3,r11,r5 ++#endif + blr + + L(prep_n_tail3): +@@ -223,6 +265,10 @@ L(n_tail3): + sldi r10,r5,56 /* stxvl wants size in top 8 bits */ + addi r11,r11,32 /* Offset */ + stxvl 32+v2,r11,r10 /* Partial store */ ++#ifdef USE_AS_STPNCPY ++ /* Compute pointer to last byte copied into dest. */ ++ add r3,r11,r5 ++#endif + blr + + L(prep_tail1): +@@ -232,6 +278,10 @@ L(tail1): + addi r9,r8,1 /* Add null terminator */ + sldi r10,r9,56 /* stxvl wants size in top 8 bits */ + stxvl 32+v0,r11,r10 /* Partial store */ ++#ifdef USE_AS_STPNCPY ++ /* Compute pointer to last byte copied into dest. */ ++ add r3,r11,r8 ++#endif + add r11,r11,r9 + sub r5,r5,r9 + b L(zero_padding) +@@ -246,6 +296,10 @@ L(tail2): + sldi r10,r9,56 /* stxvl wants size in top 8 bits */ + addi r11,r11,16 /* offset */ + stxvl 32+v1,r11,r10 /* Partial store */ ++#ifdef USE_AS_STPNCPY ++ /* Compute pointer to last byte copied into dest. */ ++ add r3,r11,r8 ++#endif + add r11,r11,r9 + sub r5,r5,r9 + b L(zero_padding) +@@ -261,6 +315,10 @@ L(tail3): + sldi r10,r9,56 /* stxvl wants size in top 8 bits */ + addi r11,r11,32 /* offset */ + stxvl 32+v2,r11,r10 /* Partial store */ ++#ifdef USE_AS_STPNCPY ++ /* Compute pointer to last byte copied into dest. */ ++ add r3,r11,r8 ++#endif + add r11,r11,r9 + sub r5,r5,r9 + b L(zero_padding) +@@ -276,6 +334,10 @@ L(tail4): + sldi r10,r9,56 /* stxvl wants size in top 8 bits */ + addi r11,r11,48 /* offset */ + stxvl 32+v3,r11,r10 /* Partial store */ ++#ifdef USE_AS_STPNCPY ++ /* Compute pointer to last byte copied into dest. */ ++ add r3,r11,r8 ++#endif + add r11,r11,r9 + sub r5,r5,r9 + +@@ -331,7 +393,8 @@ L(zero_padding_memset): + ld r0,FRAMESIZE+16(r1) + + mr r3,r30 /* Restore the return value of strncpy, i.e.: +- dest. */ ++ dest. For stpncpy, the return value is the ++ same as return value of memset. */ + ld r30,FRAMESIZE-8(r1) /* Restore r30. */ + /* Restore the stack frame. */ + addi r1,r1,FRAMESIZE +@@ -342,3 +405,6 @@ L(zero_padding_memset): + blr + + END (FUNC_NAME) ++#ifndef USE_AS_STPNCPY ++libc_hidden_builtin_def (strncpy) ++#endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index cd2b47b403..f46bf50732 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -33,7 +33,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + + ifneq (,$(filter %le,$(config-machine))) + sysdep_routines += strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 \ +- rawmemchr-power9 strlen-power9 strncpy-power9 ++ rawmemchr-power9 strlen-power9 strncpy-power9 stpncpy-power9 + endif + CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops + CFLAGS-strncase_l-power7.c += -mcpu=power7 -funroll-loops +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 135326c97a..8e19ebbf09 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -318,6 +318,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/powerpc/powerpc64/multiarch/stpncpy.c. */ + IFUNC_IMPL (i, name, stpncpy, ++#ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, stpncpy, ++ (hwcap2 & PPC_FEATURE2_ARCH_3_00) ++ && (hwcap & PPC_FEATURE_HAS_VSX), ++ __stpncpy_power9) ++#endif + IFUNC_IMPL_ADD (array, i, stpncpy, + hwcap2 & PPC_FEATURE2_ARCH_2_07, + __stpncpy_power8) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/stpncpy-power9.S b/sysdeps/powerpc/powerpc64/multiarch/stpncpy-power9.S +new file mode 100644 +index 0000000000..1188bd0894 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/stpncpy-power9.S +@@ -0,0 +1,29 @@ ++/* Optimized stpncpy implementation for POWER9 LE. ++ Copyright (C) 2020 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 ++ . */ ++ ++#define STPNCPY __stpncpy_power9 ++ ++#undef libc_hidden_builtin_def ++#define libc_hidden_builtin_def(name) ++ ++#define MEMSET __memset_power8 ++#ifdef SHARED ++# define MEMSET_is_local ++#endif ++ ++#include +diff --git a/sysdeps/powerpc/powerpc64/multiarch/stpncpy.c b/sysdeps/powerpc/powerpc64/multiarch/stpncpy.c +index 17df886431..3758f29ad1 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/stpncpy.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/stpncpy.c +@@ -26,10 +26,18 @@ + extern __typeof (__stpncpy) __stpncpy_ppc attribute_hidden; + extern __typeof (__stpncpy) __stpncpy_power7 attribute_hidden; + extern __typeof (__stpncpy) __stpncpy_power8 attribute_hidden; ++# ifdef __LITTLE_ENDIAN__ ++extern __typeof (__stpncpy) __stpncpy_power9 attribute_hidden; ++# endif + # undef stpncpy + # undef __stpncpy + + libc_ifunc_redirected (__redirect___stpncpy, __stpncpy, ++# ifdef __LITTLE_ENDIAN__ ++ (hwcap2 & PPC_FEATURE2_ARCH_3_00) && ++ (hwcap & PPC_FEATURE_HAS_VSX) ++ ? __stpncpy_power9 : ++# endif + (hwcap2 & PPC_FEATURE2_ARCH_2_07) + ? __stpncpy_power8 + : (hwcap & PPC_FEATURE_HAS_VSX) diff --git a/glibc-rh1918719-3.patch b/glibc-rh1918719-3.patch new file mode 100755 index 0000000..3c061fe --- /dev/null +++ b/glibc-rh1918719-3.patch @@ -0,0 +1,30 @@ +From 3322ecbfe29a16e74c4f584d661b0b8018bb4031 Mon Sep 17 00:00:00 2001 +From: Raphael Moreira Zinsly +Date: Mon, 14 Sep 2020 11:59:24 -0300 +Subject: [PATCH] powerpc: Protect dl_powerpc_cpu_features on INIT_ARCH() [BZ + #26615] + +dl_powerpc_cpu_features also needs to be protected by __GLRO to check +for the _rtld_global_ro realocation before accessing it. + +Reviewed-by: Tulio Magno Quites Machado Filho +--- + sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h b/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h +index 17ddfcf528..c8fa07fadc 100644 +--- a/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h ++++ b/sysdeps/powerpc/powerpc32/power4/multiarch/init-arch.h +@@ -38,7 +38,7 @@ + unsigned long int hwcap = __GLRO(dl_hwcap); \ + unsigned long int __attribute__((unused)) hwcap2 = __GLRO(dl_hwcap2); \ + bool __attribute__((unused)) use_cached_memopt = \ +- GLRO(dl_powerpc_cpu_features).use_cached_memopt; \ ++ __GLRO(dl_powerpc_cpu_features.use_cached_memopt); \ + if (hwcap & PPC_FEATURE_ARCH_2_06) \ + hwcap |= PPC_FEATURE_ARCH_2_05 | \ + PPC_FEATURE_POWER5_PLUS | \ +-- +2.27.0 + diff --git a/glibc-rh1924919.patch b/glibc-rh1924919.patch new file mode 100755 index 0000000..72c211a --- /dev/null +++ b/glibc-rh1924919.patch @@ -0,0 +1,287 @@ +commit 7d88c6142c6efc160c0ee5e4f85cde382c072888 +Author: Florian Weimer +Date: Wed Jan 27 13:36:12 2021 +0100 + + gconv: Fix assertion failure in ISO-2022-JP-3 module (bug 27256) + + The conversion loop to the internal encoding does not follow + the interface contract that __GCONV_FULL_OUTPUT is only returned + after the internal wchar_t buffer has been filled completely. This + is enforced by the first of the two asserts in iconv/skeleton.c: + + /* We must run out of output buffer space in this + rerun. */ + assert (outbuf == outerr); + assert (nstatus == __GCONV_FULL_OUTPUT); + + This commit solves this issue by queuing a second wide character + which cannot be written immediately in the state variable, like + other converters already do (e.g., BIG5-HKSCS or TSCII). + + Reported-by: Tavis Ormandy + +Conflicts: + iconvdata/Makefile + (Usual differences in backported tests.) + +diff --git a/iconvdata/Makefile b/iconvdata/Makefile +index a47a4c07cd2e3d1b..32656ad31d9b434b 100644 +--- a/iconvdata/Makefile ++++ b/iconvdata/Makefile +@@ -73,7 +73,7 @@ modules.so := $(addsuffix .so, $(modules)) + ifeq (yes,$(build-shared)) + tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \ + tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \ +- bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 ++ bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 bug-iconv14 + ifeq ($(have-thread-library),yes) + tests += bug-iconv3 + endif +@@ -316,6 +316,8 @@ $(objpfx)bug-iconv10.out: $(objpfx)gconv-modules \ + $(addprefix $(objpfx),$(modules.so)) + $(objpfx)bug-iconv12.out: $(objpfx)gconv-modules \ + $(addprefix $(objpfx),$(modules.so)) ++$(objpfx)bug-iconv14.out: $(objpfx)gconv-modules \ ++ $(addprefix $(objpfx),$(modules.so)) + + $(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \ + $(addprefix $(objpfx),$(modules.so)) \ +diff --git a/iconvdata/bug-iconv14.c b/iconvdata/bug-iconv14.c +new file mode 100644 +index 0000000000000000..902f140fa949cbac +--- /dev/null ++++ b/iconvdata/bug-iconv14.c +@@ -0,0 +1,127 @@ ++/* Assertion in ISO-2022-JP-3 due to two-character sequence (bug 27256). ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++/* Use an escape sequence to return to the initial state. */ ++static void ++with_escape_sequence (void) ++{ ++ iconv_t c = iconv_open ("UTF-8", "ISO-2022-JP-3"); ++ TEST_VERIFY_EXIT (c != (iconv_t) -1); ++ ++ char in[] = "\e$(O+D\e(B"; ++ char *inbuf = in; ++ size_t inleft = strlen (in); ++ char out[3]; /* Space for one output character. */ ++ char *outbuf; ++ size_t outleft; ++ ++ outbuf = out; ++ outleft = sizeof (out); ++ TEST_COMPARE (iconv (c, &inbuf, &inleft, &outbuf, &outleft), (size_t) -1); ++ TEST_COMPARE (errno, E2BIG); ++ TEST_COMPARE (inleft, 3); ++ TEST_COMPARE (inbuf - in, strlen (in) - 3); ++ TEST_COMPARE (outleft, sizeof (out) - 2); ++ TEST_COMPARE (outbuf - out, 2); ++ TEST_COMPARE (out[0] & 0xff, 0xc3); ++ TEST_COMPARE (out[1] & 0xff, 0xa6); ++ ++ /* Return to the initial shift state, producing the pending ++ character. */ ++ outbuf = out; ++ outleft = sizeof (out); ++ TEST_COMPARE (iconv (c, &inbuf, &inleft, &outbuf, &outleft), 0); ++ TEST_COMPARE (inleft, 0); ++ TEST_COMPARE (inbuf - in, strlen (in)); ++ TEST_COMPARE (outleft, sizeof (out) - 2); ++ TEST_COMPARE (outbuf - out, 2); ++ TEST_COMPARE (out[0] & 0xff, 0xcc); ++ TEST_COMPARE (out[1] & 0xff, 0x80); ++ ++ /* Nothing should be flushed the second time. */ ++ outbuf = out; ++ outleft = sizeof (out); ++ TEST_COMPARE (iconv (c, NULL, 0, &outbuf, &outleft), 0); ++ TEST_COMPARE (outleft, sizeof (out)); ++ TEST_COMPARE (outbuf - out, 0); ++ TEST_COMPARE (out[0] & 0xff, 0xcc); ++ TEST_COMPARE (out[1] & 0xff, 0x80); ++ ++ TEST_COMPARE (iconv_close (c), 0); ++} ++ ++/* Use an explicit flush to return to the initial state. */ ++static void ++with_flush (void) ++{ ++ iconv_t c = iconv_open ("UTF-8", "ISO-2022-JP-3"); ++ TEST_VERIFY_EXIT (c != (iconv_t) -1); ++ ++ char in[] = "\e$(O+D"; ++ char *inbuf = in; ++ size_t inleft = strlen (in); ++ char out[3]; /* Space for one output character. */ ++ char *outbuf; ++ size_t outleft; ++ ++ outbuf = out; ++ outleft = sizeof (out); ++ TEST_COMPARE (iconv (c, &inbuf, &inleft, &outbuf, &outleft), (size_t) -1); ++ TEST_COMPARE (errno, E2BIG); ++ TEST_COMPARE (inleft, 0); ++ TEST_COMPARE (inbuf - in, strlen (in)); ++ TEST_COMPARE (outleft, sizeof (out) - 2); ++ TEST_COMPARE (outbuf - out, 2); ++ TEST_COMPARE (out[0] & 0xff, 0xc3); ++ TEST_COMPARE (out[1] & 0xff, 0xa6); ++ ++ /* Flush the pending character. */ ++ outbuf = out; ++ outleft = sizeof (out); ++ TEST_COMPARE (iconv (c, NULL, 0, &outbuf, &outleft), 0); ++ TEST_COMPARE (outleft, sizeof (out) - 2); ++ TEST_COMPARE (outbuf - out, 2); ++ TEST_COMPARE (out[0] & 0xff, 0xcc); ++ TEST_COMPARE (out[1] & 0xff, 0x80); ++ ++ /* Nothing should be flushed the second time. */ ++ outbuf = out; ++ outleft = sizeof (out); ++ TEST_COMPARE (iconv (c, NULL, 0, &outbuf, &outleft), 0); ++ TEST_COMPARE (outleft, sizeof (out)); ++ TEST_COMPARE (outbuf - out, 0); ++ TEST_COMPARE (out[0] & 0xff, 0xcc); ++ TEST_COMPARE (out[1] & 0xff, 0x80); ++ ++ TEST_COMPARE (iconv_close (c), 0); ++} ++ ++static int ++do_test (void) ++{ ++ with_escape_sequence (); ++ with_flush (); ++ return 0; ++} ++ ++#include +diff --git a/iconvdata/iso-2022-jp-3.c b/iconvdata/iso-2022-jp-3.c +index de259580c3f378bb..047fab8e8dfbde7e 100644 +--- a/iconvdata/iso-2022-jp-3.c ++++ b/iconvdata/iso-2022-jp-3.c +@@ -67,23 +67,34 @@ enum + CURRENT_SEL_MASK = 7 << 3 + }; + +-/* During UCS-4 to ISO-2022-JP-3 conversion, the COUNT element of the state +- also contains the last two bytes to be output, shifted by 6 bits, and a +- one-bit indicator whether they must be preceded by the shift sequence, +- in bit 22. */ ++/* During UCS-4 to ISO-2022-JP-3 conversion, the COUNT element of the ++ state also contains the last two bytes to be output, shifted by 6 ++ bits, and a one-bit indicator whether they must be preceded by the ++ shift sequence, in bit 22. During ISO-2022-JP-3 to UCS-4 ++ conversion, COUNT may also contain a non-zero pending wide ++ character, shifted by six bits. This happens for certain inputs in ++ JISX0213_1_2004_set and JISX0213_2_set if the second wide character ++ in a combining sequence cannot be written because the buffer is ++ full. */ + + /* Since this is a stateful encoding we have to provide code which resets + the output state to the initial state. This has to be done during the + flushing. */ + #define EMIT_SHIFT_TO_INIT \ +- if ((data->__statep->__count & ~7) != ASCII_set) \ ++ if (data->__statep->__count != ASCII_set) \ + { \ + if (FROM_DIRECTION) \ + { \ +- /* It's easy, we don't have to emit anything, we just reset the \ +- state for the input. */ \ +- data->__statep->__count &= 7; \ +- data->__statep->__count |= ASCII_set; \ ++ if (__glibc_likely (outbuf + 4 <= outend)) \ ++ { \ ++ /* Write out the last character. */ \ ++ *((uint32_t *) outbuf) = data->__statep->__count >> 6; \ ++ outbuf += sizeof (uint32_t); \ ++ data->__statep->__count = ASCII_set; \ ++ } \ ++ else \ ++ /* We don't have enough room in the output buffer. */ \ ++ status = __GCONV_FULL_OUTPUT; \ + } \ + else \ + { \ +@@ -151,7 +162,21 @@ enum + #define LOOPFCT FROM_LOOP + #define BODY \ + { \ +- uint32_t ch = *inptr; \ ++ uint32_t ch; \ ++ \ ++ /* Output any pending character. */ \ ++ ch = set >> 6; \ ++ if (__glibc_unlikely (ch != 0)) \ ++ { \ ++ put32 (outptr, ch); \ ++ outptr += 4; \ ++ /* Remove the pending character, but preserve state bits. */ \ ++ set &= (1 << 6) - 1; \ ++ continue; \ ++ } \ ++ \ ++ /* Otherwise read the next input byte. */ \ ++ ch = *inptr; \ + \ + /* Recognize escape sequences. */ \ + if (__glibc_unlikely (ch == ESC)) \ +@@ -297,21 +322,25 @@ enum + uint32_t u1 = __jisx0213_to_ucs_combining[ch - 1][0]; \ + uint32_t u2 = __jisx0213_to_ucs_combining[ch - 1][1]; \ + \ ++ inptr += 2; \ ++ \ ++ put32 (outptr, u1); \ ++ outptr += 4; \ ++ \ + /* See whether we have room for two characters. */ \ +- if (outptr + 8 <= outend) \ ++ if (outptr + 4 <= outend) \ + { \ +- inptr += 2; \ +- put32 (outptr, u1); \ +- outptr += 4; \ + put32 (outptr, u2); \ + outptr += 4; \ + continue; \ + } \ +- else \ +- { \ +- result = __GCONV_FULL_OUTPUT; \ +- break; \ +- } \ ++ \ ++ /* Otherwise store only the first character now, and \ ++ put the second one into the queue. */ \ ++ set |= u2 << 6; \ ++ /* Tell the caller why we terminate the loop. */ \ ++ result = __GCONV_FULL_OUTPUT; \ ++ break; \ + } \ + \ + inptr += 2; \ diff --git a/glibc-rh1927877.patch b/glibc-rh1927877.patch new file mode 100755 index 0000000..d842710 --- /dev/null +++ b/glibc-rh1927877.patch @@ -0,0 +1,39 @@ +commit dca565886b5e8bd7966e15f0ca42ee5cff686673 +Author: DJ Delorie +Date: Thu Feb 25 16:08:21 2021 -0500 + + nscd: Fix double free in netgroupcache [BZ #27462] + + In commit 745664bd798ec8fd50438605948eea594179fba1 a use-after-free + was fixed, but this led to an occasional double-free. This patch + tracks the "live" allocation better. + + Tested manually by a third party. + + Related: RHBZ 1927877 + + Reviewed-by: Siddhesh Poyarekar + Reviewed-by: Carlos O'Donell + +diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c +index f521df824102bbca..5ee4413ef9384ec9 100644 +--- a/nscd/netgroupcache.c ++++ b/nscd/netgroupcache.c +@@ -248,7 +248,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + : NULL); + ndomain = (ndomain ? newbuf + ndomaindiff + : NULL); +- buffer = newbuf; ++ *tofreep = buffer = newbuf; + } + + nhost = memcpy (buffer + bufused, +@@ -319,7 +319,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req, + else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE) + { + buflen *= 2; +- buffer = xrealloc (buffer, buflen); ++ *tofreep = buffer = xrealloc (buffer, buflen); + } + else if (status == NSS_STATUS_RETURN + || status == NSS_STATUS_NOTFOUND diff --git a/glibc-rh1930302-1.patch b/glibc-rh1930302-1.patch new file mode 100755 index 0000000..0c0d614 --- /dev/null +++ b/glibc-rh1930302-1.patch @@ -0,0 +1,25 @@ +commit dc91a19e6f71e1523f4ac179191a29b2131d74bb +Author: Joseph Myers +Date: Mon Jun 3 11:16:02 2019 +0000 + + Add INADDR_ALLSNOOPERS_GROUP from Linux 5.1 to netinet/in.h. + + This patch adds INADDR_ALLSNOOPERS_GROUP from Linux 5.1 to + netinet/in.h. + + Tested for x86_64. + + * inet/netinet/in.h (INADDR_ALLSNOOPERS_GROUP): New macro. + +diff --git a/inet/netinet/in.h b/inet/netinet/in.h +index 03a31b634c8bfbed..c2d12a04aab6c022 100644 +--- a/inet/netinet/in.h ++++ b/inet/netinet/in.h +@@ -204,6 +204,7 @@ enum + #define INADDR_UNSPEC_GROUP ((in_addr_t) 0xe0000000) /* 224.0.0.0 */ + #define INADDR_ALLHOSTS_GROUP ((in_addr_t) 0xe0000001) /* 224.0.0.1 */ + #define INADDR_ALLRTRS_GROUP ((in_addr_t) 0xe0000002) /* 224.0.0.2 */ ++#define INADDR_ALLSNOOPERS_GROUP ((in_addr_t) 0xe000006a) /* 224.0.0.106 */ + #define INADDR_MAX_LOCAL_GROUP ((in_addr_t) 0xe00000ff) /* 224.0.0.255 */ + + #if !__USE_KERNEL_IPV6_DEFS diff --git a/glibc-rh1930302-2.patch b/glibc-rh1930302-2.patch new file mode 100755 index 0000000..a0b75ad --- /dev/null +++ b/glibc-rh1930302-2.patch @@ -0,0 +1,28 @@ +commit f9ac84f92f151e07586c55e14ed628d493a5929d +Author: Joseph Myers +Date: Fri Apr 3 18:08:28 2020 +0000 + + Add IPPROTO_ETHERNET and IPPROTO_MPTCP from Linux 5.6 to netinet/in.h. + + This patch adds the IPPROTO_ETHERNET and IPPROTO_MPTCP constants from + Linux 5.6 to glibc's netinet/in.h. + + Tested for x86_64. + +diff --git a/inet/netinet/in.h b/inet/netinet/in.h +index c2d12a04aab6c022..5880e909ff3e06fb 100644 +--- a/inet/netinet/in.h ++++ b/inet/netinet/in.h +@@ -87,8 +87,12 @@ enum + #define IPPROTO_UDPLITE IPPROTO_UDPLITE + IPPROTO_MPLS = 137, /* MPLS in IP. */ + #define IPPROTO_MPLS IPPROTO_MPLS ++ IPPROTO_ETHERNET = 143, /* Ethernet-within-IPv6 Encapsulation. */ ++#define IPPROTO_ETHERNET IPPROTO_ETHERNET + IPPROTO_RAW = 255, /* Raw IP packets. */ + #define IPPROTO_RAW IPPROTO_RAW ++ IPPROTO_MPTCP = 262, /* Multipath TCP connection. */ ++#define IPPROTO_MPTCP IPPROTO_MPTCP + IPPROTO_MAX + }; + diff --git a/glibc-rh1932770.patch b/glibc-rh1932770.patch new file mode 100755 index 0000000..4960631 --- /dev/null +++ b/glibc-rh1932770.patch @@ -0,0 +1,177 @@ +This is a custom downstream RHEL 8 patch which rebuilds three +GLIBC_PRIVATE interfaces locally for use by libnss_files.so.2 +and libnss_compat.so.2. + +The shared objects needs the following 3 functions: +__nss_readline +__nss_parse_line_result +__nss_files_fopen (only requirement for libnss_compat.so.2) + +They are implemented in: +nss/nss_parse_line_result.c +nss/nss_readline.c +nss/nss_files_fopen.c + +We create wrappers for those functions, recompile, and link directly +into the shared objects: +nss/nss_parse_line_result_int.c +nss/nss_readline_int.c +nss/nss_files_fopen_int.c + +After building the new shared objects there are no longer any undefined +global function references to __nss_readline@GLIBC_PRIVATE, +__nss_parse_line_result@GLIBC_PRIVATE or +__nss_files_fopen@GLIBC_PRIVATE. + +Instead we see local function definitions in the shared object e.g. +Symbol table '.symtab' contains 628 entries: +... + 486: 0000000000008ce0 92 FUNC LOCAL DEFAULT 15 __nss_parse_line_result +... + 494: 0000000000008b70 72 FUNC LOCAL DEFAULT 15 __nss_readline_seek +... + 497: 0000000000008bc0 279 FUNC LOCAL DEFAULT 15 __nss_readline +... + 510: 0000000000008ce0 82 FUNC LOCAL DEFAULT 15 __nss_files_fopen + +The remaining GLIBC_PRIVATE references in the shared objects are all +pre-existing and do not impact upgrade scenarios. + +For reference the existing and present GLIBC_PRIVATE interfaces are: +__libc_alloc_buffer_alloc_array@@GLIBC_PRIVATE +__libc_alloc_buffer_copy_string@@GLIBC_PRIVATE +__libc_alloc_buffer_create_failure@@GLIBC_PRIVATE +__libc_dynarray_emplace_enlarge@@GLIBC_PRIVATE +__libc_scratch_buffer_grow@@GLIBC_PRIVATE +__resp@@GLIBC_PRIVATE +_nss_files_parse_grent@@GLIBC_PRIVATE +_nss_files_parse_pwent@@GLIBC_PRIVATE +_nss_files_parse_sgent@@GLIBC_PRIVATE +_nss_files_parse_spent@@GLIBC_PRIVATE +errno@@GLIBC_PRIVATE +__nss_database_lookup2@GLIBC_PRIVATE +__nss_lookup_function@GLIBC_PRIVATE + +Each was checked for existence in libc.so.6. + +A small reproducer was used in testing this patch, included here: +cat >> tst-rhbz1927040.c < +#include +#include +#include +#include +#include + +int +main (void) +{ + struct passwd *res; + + /* Only lookup via files. */ + printf ("INFO: Upgrade glibc, then press ENTER to see if libnss_files.so.2 loads."); + getchar (); + + /* Try to get one entry. */ + printf ("INFO: Looking up first password entry.\n"); + setpwent (); + errno = 0; + res = getpwent (); + if (res == NULL && errno != 0) + { + printf ("FAIL: Could not get entry (%s).\n", strerror(errno)); + exit (1); + } + printf ("INFO: First entry passwd.pw_name = \"%s\"\n", res->pw_name); + printf ("PASS: Call to getpwent succeeded.\n"); + endpwent (); + exit (0); +} +EOF + +Testing RHEL upgrade +from: glibc-2.28-127.el8_3.2 +to: glibc-2.28-148.el8 + +./tst-rhbz1927040 +INFO: Upgrade glibc, then press ENTER to see if libnss_files.so.2 loads. +INFO: Looking up first password entry. +INFO: Result was NULL. +PASS: Call to getpwent succeeded. + +With LD_DEBUG=all you can observe: + 22697: /lib64/libnss_files.so.2: error: symbol lookup error: undefined symbol: __nss_files_fopen, version GLIBC_PRIVATE (fatal) + +Which is the indication that the upgrade caused the transient IdM lookup failure. + +Running again succeeds: +INFO: Upgrade glibc, then press ENTER to see if libnss_files.so.2 loads. +INFO: Looking up first password entry. +INFO: First entry passwd.pw_name = "root" +PASS: Call to getpwent succeeded. + +diff --git a/nss/Makefile b/nss/Makefile +index 7359da38feb65618..d5c28a6b5ed3661c 100644 +--- a/nss/Makefile ++++ b/nss/Makefile +@@ -92,9 +92,19 @@ extra-libs-others = $(extra-libs) + subdir-dirs = $(services:%=nss_%) + vpath %.c $(subdir-dirs) ../locale/programs ../intl + +- ++# In RHEL we add nss_readline, nss_parse_line_result, and ++# nss_files_fopen to the libnss_files-routines in order to avoid the ++# case where a long running process (having never used NSS) attemps to ++# load an NSS module for the first time and that NSS module needs a ++# newer GLIBC_PRIVATE interface. In effect we must make the NSS modules ++# self-sufficient and not rely on a GLIBC_PRIVATE interface. ++# See: https://bugzilla.redhat.com/show_bug.cgi?id=1927040 ++# Note: We must recompile the objects to get the correct global symbol ++# references, which is why we have the *_int.c wrappers. + libnss_files-routines := $(addprefix files-,$(databases)) \ +- files-initgroups files-init ++ files-initgroups files-init \ ++ nss_readline_int nss_parse_line_result_int \ ++ nss_files_fopen_int + + libnss_db-dbs := $(addprefix db-,\ + $(filter-out hosts network key alias,\ +@@ -104,8 +114,10 @@ libnss_db-routines := $(libnss_db-dbs) db-open db-init hash-string + generated += $(filter-out db-alias.c db-netgrp.c, \ + $(addsuffix .c,$(libnss_db-dbs))) + ++# See note above regarding nss_files_fopen. + libnss_compat-routines := $(addprefix compat-,grp pwd spwd initgroups) \ +- nisdomain ++ nisdomain \ ++ nss_files_fopen_int + + install-others += $(inst_vardbdir)/Makefile + +diff --git a/nss/nss_files_fopen_int.c b/nss/nss_files_fopen_int.c +new file mode 100644 +index 0000000000000000..fa518084fd609b52 +--- /dev/null ++++ b/nss/nss_files_fopen_int.c +@@ -0,0 +1,3 @@ ++/* Include a local internal copy of __nss_files_fopen to make the NSS ++ module self-contained. */ ++#include +diff --git a/nss/nss_parse_line_result_int.c b/nss/nss_parse_line_result_int.c +new file mode 100644 +index 0000000000000000..bc0ee7a251743c9a +--- /dev/null ++++ b/nss/nss_parse_line_result_int.c +@@ -0,0 +1,3 @@ ++/* Include a local internal copy of __nss_parse_line_result to make the ++ NSS module self-contained. */ ++#include +diff --git a/nss/nss_readline_int.c b/nss/nss_readline_int.c +new file mode 100644 +index 0000000000000000..0e7bd259733673c9 +--- /dev/null ++++ b/nss/nss_readline_int.c +@@ -0,0 +1,3 @@ ++/* Include a local internal copy of __nss_readline and ++ __nss_readline_seek to make the NSS module self-contained. */ ++#include diff --git a/glibc-rh1934155-1.patch b/glibc-rh1934155-1.patch new file mode 100755 index 0000000..e5d5af6 --- /dev/null +++ b/glibc-rh1934155-1.patch @@ -0,0 +1,20 @@ +support: Pass environ to child process + +Pass environ to posix_spawn so that the child process can inherit +environment of the test. + +(cherry picked from commit e958490f8c74e660bd93c128b3bea746e268f3f6) + +diff --git a/support/support_subprocess.c b/support/support_subprocess.c +index 12c79ff6b0859877..4573350d775ac4c8 100644 +--- a/support/support_subprocess.c ++++ b/support/support_subprocess.c +@@ -84,7 +84,7 @@ support_subprogram (const char *file, char *const argv[]) + 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); ++ result.pid = xposix_spawn (file, &fa, NULL, argv, environ); + + xclose (result.stdout_pipe[1]); + xclose (result.stderr_pipe[1]); diff --git a/glibc-rh1934155-2.patch b/glibc-rh1934155-2.patch new file mode 100755 index 0000000..ca842ee --- /dev/null +++ b/glibc-rh1934155-2.patch @@ -0,0 +1,51 @@ +support: Typo and formatting fixes + +- Add a newline to the end of error messages in transfer(). +- Fixed the name of support_subprocess_init(). + +(cherry picked from commit 95c68080a3ded882789b1629f872c3ad531efda0) + +diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c +index c13b3e59ece0842e..c475e2004da3183e 100644 +--- a/support/support_capture_subprocess.c ++++ b/support/support_capture_subprocess.c +@@ -36,7 +36,7 @@ transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream) + if (ret < 0) + { + support_record_failure (); +- printf ("error: reading from subprocess %s: %m", what); ++ printf ("error: reading from subprocess %s: %m\n", what); + pfd->events = 0; + pfd->revents = 0; + } +diff --git a/support/support_subprocess.c b/support/support_subprocess.c +index 4573350d775ac4c8..af01827cac81d80c 100644 +--- a/support/support_subprocess.c ++++ b/support/support_subprocess.c +@@ -27,7 +27,7 @@ + #include + + static struct support_subprocess +-support_suprocess_init (void) ++support_subprocess_init (void) + { + struct support_subprocess result; + +@@ -48,7 +48,7 @@ support_suprocess_init (void) + struct support_subprocess + support_subprocess (void (*callback) (void *), void *closure) + { +- struct support_subprocess result = support_suprocess_init (); ++ struct support_subprocess result = support_subprocess_init (); + + result.pid = xfork (); + if (result.pid == 0) +@@ -71,7 +71,7 @@ support_subprocess (void (*callback) (void *), void *closure) + struct support_subprocess + support_subprogram (const char *file, char *const argv[]) + { +- struct support_subprocess result = support_suprocess_init (); ++ struct support_subprocess result = support_subprocess_init (); + + posix_spawn_file_actions_t fa; + /* posix_spawn_file_actions_init does not fail. */ diff --git a/glibc-rh1934155-3.patch b/glibc-rh1934155-3.patch new file mode 100755 index 0000000..97ca5dd --- /dev/null +++ b/glibc-rh1934155-3.patch @@ -0,0 +1,447 @@ +support: Add capability to fork an sgid child + +Add a new function support_capture_subprogram_self_sgid that spawns an +sgid child of the running program with its own image and returns the +exit code of the child process. This functionality is used by at +least three tests in the testsuite at the moment, so it makes sense to +consolidate. + +There is also a new function support_subprogram_wait which should +provide simple system() like functionality that does not set up file +actions. This is useful in cases where only the return code of the +spawned subprocess is interesting. + +This patch also ports tst-secure-getenv to this new function. A +subsequent patch will port other tests. This also brings an important +change to tst-secure-getenv behaviour. Now instead of succeeding, the +test fails as UNSUPPORTED if it is unable to spawn a setgid child, +which is how it should have been in the first place. +Reviewed-by: Carlos O'Donell + +(cherry picked from commit 716a3bdc41b2b4b864dc64475015ba51e35e1273) + +diff --git a/stdlib/tst-secure-getenv.c b/stdlib/tst-secure-getenv.c +index a682b7493e41f200..156c92fea216729f 100644 +--- a/stdlib/tst-secure-getenv.c ++++ b/stdlib/tst-secure-getenv.c +@@ -30,156 +30,12 @@ + #include + #include + ++#include + #include ++#include + #include + + static char MAGIC_ARGUMENT[] = "run-actual-test"; +-#define MAGIC_STATUS 19 +- +-/* Return a GID which is not our current GID, but is present in the +- supplementary group list. */ +-static gid_t +-choose_gid (void) +-{ +- const int count = 64; +- gid_t groups[count]; +- int ret = getgroups (count, groups); +- if (ret < 0) +- { +- printf ("getgroups: %m\n"); +- exit (1); +- } +- gid_t current = getgid (); +- for (int i = 0; i < ret; ++i) +- { +- if (groups[i] != current) +- return groups[i]; +- } +- return 0; +-} +- +- +-/* Copies the executable into a restricted directory, so that we can +- safely make it SGID with the TARGET group ID. Then runs the +- executable. */ +-static int +-run_executable_sgid (gid_t target) +-{ +- char *dirname = xasprintf ("%s/secure-getenv.%jd", +- test_dir, (intmax_t) getpid ()); +- char *execname = xasprintf ("%s/bin", dirname); +- int infd = -1; +- int outfd = -1; +- int ret = -1; +- if (mkdir (dirname, 0700) < 0) +- { +- printf ("mkdir: %m\n"); +- goto err; +- } +- infd = open ("/proc/self/exe", O_RDONLY); +- if (infd < 0) +- { +- printf ("open (/proc/self/exe): %m\n"); +- goto err; +- } +- outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700); +- if (outfd < 0) +- { +- printf ("open (%s): %m\n", execname); +- goto err; +- } +- char buf[4096]; +- for (;;) +- { +- ssize_t rdcount = read (infd, buf, sizeof (buf)); +- if (rdcount < 0) +- { +- printf ("read: %m\n"); +- goto err; +- } +- if (rdcount == 0) +- break; +- char *p = buf; +- char *end = buf + rdcount; +- while (p != end) +- { +- ssize_t wrcount = write (outfd, buf, end - p); +- if (wrcount == 0) +- errno = ENOSPC; +- if (wrcount <= 0) +- { +- printf ("write: %m\n"); +- goto err; +- } +- p += wrcount; +- } +- } +- if (fchown (outfd, getuid (), target) < 0) +- { +- printf ("fchown (%s): %m\n", execname); +- goto err; +- } +- if (fchmod (outfd, 02750) < 0) +- { +- printf ("fchmod (%s): %m\n", execname); +- goto err; +- } +- if (close (outfd) < 0) +- { +- printf ("close (outfd): %m\n"); +- goto err; +- } +- if (close (infd) < 0) +- { +- printf ("close (infd): %m\n"); +- goto err; +- } +- +- int kid = fork (); +- if (kid < 0) +- { +- printf ("fork: %m\n"); +- goto err; +- } +- if (kid == 0) +- { +- /* Child process. */ +- char *args[] = { execname, MAGIC_ARGUMENT, NULL }; +- execve (execname, args, environ); +- printf ("execve (%s): %m\n", execname); +- _exit (1); +- } +- int status; +- if (waitpid (kid, &status, 0) < 0) +- { +- printf ("waitpid: %m\n"); +- goto err; +- } +- if (!WIFEXITED (status) || WEXITSTATUS (status) != MAGIC_STATUS) +- { +- printf ("Unexpected exit status %d from child process\n", +- status); +- goto err; +- } +- ret = 0; +- +-err: +- if (outfd >= 0) +- close (outfd); +- if (infd >= 0) +- close (infd); +- if (execname) +- { +- unlink (execname); +- free (execname); +- } +- if (dirname) +- { +- rmdir (dirname); +- free (dirname); +- } +- return ret; +-} + + static int + do_test (void) +@@ -201,15 +57,15 @@ do_test (void) + exit (1); + } + +- gid_t target = choose_gid (); +- if (target == 0) +- { +- fprintf (stderr, +- "Could not find a suitable GID for user %jd, skipping test\n", +- (intmax_t) getuid ()); +- exit (0); +- } +- return run_executable_sgid (target); ++ int status = support_capture_subprogram_self_sgid (MAGIC_ARGUMENT); ++ ++ if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) ++ return EXIT_UNSUPPORTED; ++ ++ if (!WIFEXITED (status)) ++ FAIL_EXIT1 ("Unexpected exit status %d from child process\n", status); ++ ++ return 0; + } + + static void +@@ -218,23 +74,15 @@ alternative_main (int argc, char **argv) + if (argc == 2 && strcmp (argv[1], MAGIC_ARGUMENT) == 0) + { + if (getgid () == getegid ()) +- { +- /* This can happen if the file system is mounted nosuid. */ +- fprintf (stderr, "SGID failed: GID and EGID match (%jd)\n", +- (intmax_t) getgid ()); +- exit (MAGIC_STATUS); +- } ++ /* This can happen if the file system is mounted nosuid. */ ++ FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n", ++ (intmax_t) getgid ()); + if (getenv ("PATH") == NULL) +- { +- printf ("PATH variable not present\n"); +- exit (3); +- } ++ FAIL_EXIT (3, "PATH variable not present\n"); + if (secure_getenv ("PATH") != NULL) +- { +- printf ("PATH variable not filtered out\n"); +- exit (4); +- } +- exit (MAGIC_STATUS); ++ FAIL_EXIT (4, "PATH variable not filtered out\n"); ++ ++ exit (EXIT_SUCCESS); + } + } + +diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h +index 2d2384e73df0d2d0..72fb30504684a84e 100644 +--- a/support/capture_subprocess.h ++++ b/support/capture_subprocess.h +@@ -41,6 +41,12 @@ struct support_capture_subprocess support_capture_subprocess + struct support_capture_subprocess support_capture_subprogram + (const char *file, char *const argv[]); + ++/* Copy the running program into a setgid binary and run it with CHILD_ID ++ argument. If execution is successful, return the exit status of the child ++ program, otherwise return a non-zero failure exit code. */ ++int support_capture_subprogram_self_sgid ++ (char *child_id); ++ + /* 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 +index c031878d94c70c71..a19335ee5dbfcf98 100644 +--- a/support/subprocess.h ++++ b/support/subprocess.h +@@ -38,6 +38,11 @@ struct support_subprocess support_subprocess + struct support_subprocess support_subprogram + (const char *file, char *const argv[]); + ++/* Invoke program FILE with ARGV arguments by using posix_spawn and wait for it ++ to complete. Return program exit status. */ ++int support_subprogram_wait ++ (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); +diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c +index c475e2004da3183e..eec5371d5602aa29 100644 +--- a/support/support_capture_subprocess.c ++++ b/support/support_capture_subprocess.c +@@ -20,11 +20,14 @@ + #include + + #include ++#include + #include + #include + #include + #include + #include ++#include ++#include + + static void + transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream) +@@ -101,6 +104,129 @@ support_capture_subprogram (const char *file, char *const argv[]) + return result; + } + ++/* Copies the executable into a restricted directory, so that we can ++ safely make it SGID with the TARGET group ID. Then runs the ++ executable. */ ++static int ++copy_and_spawn_sgid (char *child_id, gid_t gid) ++{ ++ char *dirname = xasprintf ("%s/tst-tunables-setuid.%jd", ++ test_dir, (intmax_t) getpid ()); ++ char *execname = xasprintf ("%s/bin", dirname); ++ int infd = -1; ++ int outfd = -1; ++ int ret = 1, status = 1; ++ ++ TEST_VERIFY (mkdir (dirname, 0700) == 0); ++ if (support_record_failure_is_failed ()) ++ goto err; ++ ++ infd = open ("/proc/self/exe", O_RDONLY); ++ if (infd < 0) ++ FAIL_UNSUPPORTED ("unsupported: Cannot read binary from procfs\n"); ++ ++ outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700); ++ TEST_VERIFY (outfd >= 0); ++ if (support_record_failure_is_failed ()) ++ goto err; ++ ++ char buf[4096]; ++ for (;;) ++ { ++ ssize_t rdcount = read (infd, buf, sizeof (buf)); ++ TEST_VERIFY (rdcount >= 0); ++ if (support_record_failure_is_failed ()) ++ goto err; ++ if (rdcount == 0) ++ break; ++ char *p = buf; ++ char *end = buf + rdcount; ++ while (p != end) ++ { ++ ssize_t wrcount = write (outfd, buf, end - p); ++ if (wrcount == 0) ++ errno = ENOSPC; ++ TEST_VERIFY (wrcount > 0); ++ if (support_record_failure_is_failed ()) ++ goto err; ++ p += wrcount; ++ } ++ } ++ TEST_VERIFY (fchown (outfd, getuid (), gid) == 0); ++ if (support_record_failure_is_failed ()) ++ goto err; ++ TEST_VERIFY (fchmod (outfd, 02750) == 0); ++ if (support_record_failure_is_failed ()) ++ goto err; ++ TEST_VERIFY (close (outfd) == 0); ++ if (support_record_failure_is_failed ()) ++ goto err; ++ TEST_VERIFY (close (infd) == 0); ++ if (support_record_failure_is_failed ()) ++ goto err; ++ ++ /* We have the binary, now spawn the subprocess. Avoid using ++ support_subprogram because we only want the program exit status, not the ++ contents. */ ++ ret = 0; ++ ++ char * const args[] = {execname, child_id, NULL}; ++ ++ status = support_subprogram_wait (args[0], args); ++ ++err: ++ if (outfd >= 0) ++ close (outfd); ++ if (infd >= 0) ++ close (infd); ++ if (execname != NULL) ++ { ++ unlink (execname); ++ free (execname); ++ } ++ if (dirname != NULL) ++ { ++ rmdir (dirname); ++ free (dirname); ++ } ++ ++ if (ret != 0) ++ FAIL_EXIT1("Failed to make sgid executable for test\n"); ++ ++ return status; ++} ++ ++int ++support_capture_subprogram_self_sgid (char *child_id) ++{ ++ gid_t target = 0; ++ const int count = 64; ++ gid_t groups[count]; ++ ++ /* Get a GID which is not our current GID, but is present in the ++ supplementary group list. */ ++ int ret = getgroups (count, groups); ++ if (ret < 0) ++ FAIL_UNSUPPORTED("Could not get group list for user %jd\n", ++ (intmax_t) getuid ()); ++ ++ gid_t current = getgid (); ++ for (int i = 0; i < ret; ++i) ++ { ++ if (groups[i] != current) ++ { ++ target = groups[i]; ++ break; ++ } ++ } ++ ++ if (target == 0) ++ FAIL_UNSUPPORTED("Could not find a suitable GID for user %jd\n", ++ (intmax_t) getuid ()); ++ ++ return copy_and_spawn_sgid (child_id, target); ++} ++ + void + support_capture_subprocess_free (struct support_capture_subprocess *p) + { +diff --git a/support/support_subprocess.c b/support/support_subprocess.c +index af01827cac81d80c..f7ee28af2531eda8 100644 +--- a/support/support_subprocess.c ++++ b/support/support_subprocess.c +@@ -92,6 +92,19 @@ support_subprogram (const char *file, char *const argv[]) + return result; + } + ++int ++support_subprogram_wait (const char *file, char *const argv[]) ++{ ++ posix_spawn_file_actions_t fa; ++ ++ posix_spawn_file_actions_init (&fa); ++ struct support_subprocess res = support_subprocess_init (); ++ ++ res.pid = xposix_spawn (file, &fa, NULL, argv, environ); ++ ++ return support_process_wait (&res); ++} ++ + int + support_process_wait (struct support_subprocess *proc) + { diff --git a/glibc-rh1934155-4.patch b/glibc-rh1934155-4.patch new file mode 100755 index 0000000..ebdebcf --- /dev/null +++ b/glibc-rh1934155-4.patch @@ -0,0 +1,240 @@ +tst-env-setuid: Use support_capture_subprogram_self_sgid + +Use the support_capture_subprogram_self_sgid to spawn an sgid child. +Reviewed-by: Carlos O'Donell + +(cherry picked from commit ca335281068a1ed549a75ee64f90a8310755956f) + +diff --git a/elf/tst-env-setuid.c b/elf/tst-env-setuid.c +index 183a6dd133cfa16e..eda87f9dda293e79 100644 +--- a/elf/tst-env-setuid.c ++++ b/elf/tst-env-setuid.c +@@ -29,173 +29,12 @@ + #include + #include + ++#include + #include + #include ++#include + + static char SETGID_CHILD[] = "setgid-child"; +-#define CHILD_STATUS 42 +- +-/* Return a GID which is not our current GID, but is present in the +- supplementary group list. */ +-static gid_t +-choose_gid (void) +-{ +- const int count = 64; +- gid_t groups[count]; +- int ret = getgroups (count, groups); +- if (ret < 0) +- { +- printf ("getgroups: %m\n"); +- exit (1); +- } +- gid_t current = getgid (); +- for (int i = 0; i < ret; ++i) +- { +- if (groups[i] != current) +- return groups[i]; +- } +- return 0; +-} +- +-/* Spawn and execute a program and verify that it returns the CHILD_STATUS. */ +-static pid_t +-do_execve (char **args) +-{ +- pid_t kid = vfork (); +- +- if (kid < 0) +- { +- printf ("vfork: %m\n"); +- return -1; +- } +- +- if (kid == 0) +- { +- /* Child process. */ +- execve (args[0], args, environ); +- _exit (-errno); +- } +- +- if (kid < 0) +- return 1; +- +- int status; +- +- if (waitpid (kid, &status, 0) < 0) +- { +- printf ("waitpid: %m\n"); +- return 1; +- } +- +- if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) +- return EXIT_UNSUPPORTED; +- +- if (!WIFEXITED (status) || WEXITSTATUS (status) != CHILD_STATUS) +- { +- printf ("Unexpected exit status %d from child process\n", +- WEXITSTATUS (status)); +- return 1; +- } +- return 0; +-} +- +-/* Copies the executable into a restricted directory, so that we can +- safely make it SGID with the TARGET group ID. Then runs the +- executable. */ +-static int +-run_executable_sgid (gid_t target) +-{ +- char *dirname = xasprintf ("%s/tst-tunables-setuid.%jd", +- test_dir, (intmax_t) getpid ()); +- char *execname = xasprintf ("%s/bin", dirname); +- int infd = -1; +- int outfd = -1; +- int ret = 0; +- if (mkdir (dirname, 0700) < 0) +- { +- printf ("mkdir: %m\n"); +- goto err; +- } +- infd = open ("/proc/self/exe", O_RDONLY); +- if (infd < 0) +- { +- printf ("open (/proc/self/exe): %m\n"); +- goto err; +- } +- outfd = open (execname, O_WRONLY | O_CREAT | O_EXCL, 0700); +- if (outfd < 0) +- { +- printf ("open (%s): %m\n", execname); +- goto err; +- } +- char buf[4096]; +- for (;;) +- { +- ssize_t rdcount = read (infd, buf, sizeof (buf)); +- if (rdcount < 0) +- { +- printf ("read: %m\n"); +- goto err; +- } +- if (rdcount == 0) +- break; +- char *p = buf; +- char *end = buf + rdcount; +- while (p != end) +- { +- ssize_t wrcount = write (outfd, buf, end - p); +- if (wrcount == 0) +- errno = ENOSPC; +- if (wrcount <= 0) +- { +- printf ("write: %m\n"); +- goto err; +- } +- p += wrcount; +- } +- } +- if (fchown (outfd, getuid (), target) < 0) +- { +- printf ("fchown (%s): %m\n", execname); +- goto err; +- } +- if (fchmod (outfd, 02750) < 0) +- { +- printf ("fchmod (%s): %m\n", execname); +- goto err; +- } +- if (close (outfd) < 0) +- { +- printf ("close (outfd): %m\n"); +- goto err; +- } +- if (close (infd) < 0) +- { +- printf ("close (infd): %m\n"); +- goto err; +- } +- +- char *args[] = {execname, SETGID_CHILD, NULL}; +- +- ret = do_execve (args); +- +-err: +- if (outfd >= 0) +- close (outfd); +- if (infd >= 0) +- close (infd); +- if (execname) +- { +- unlink (execname); +- free (execname); +- } +- if (dirname) +- { +- rmdir (dirname); +- free (dirname); +- } +- return ret; +-} + + #ifndef test_child + static int +@@ -256,40 +95,32 @@ do_test (int argc, char **argv) + if (argc == 2 && strcmp (argv[1], SETGID_CHILD) == 0) + { + if (getgid () == getegid ()) +- { +- /* This can happen if the file system is mounted nosuid. */ +- fprintf (stderr, "SGID failed: GID and EGID match (%jd)\n", +- (intmax_t) getgid ()); +- exit (EXIT_UNSUPPORTED); +- } ++ /* This can happen if the file system is mounted nosuid. */ ++ FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n", ++ (intmax_t) getgid ()); + + int ret = test_child (); + + if (ret != 0) + exit (1); + +- exit (CHILD_STATUS); ++ exit (EXIT_SUCCESS); + } + else + { + if (test_parent () != 0) + exit (1); + +- /* Try running a setgid program. */ +- gid_t target = choose_gid (); +- if (target == 0) +- { +- fprintf (stderr, +- "Could not find a suitable GID for user %jd, skipping test\n", +- (intmax_t) getuid ()); +- exit (0); +- } ++ int status = support_capture_subprogram_self_sgid (SETGID_CHILD); + +- return run_executable_sgid (target); +- } ++ if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) ++ return EXIT_UNSUPPORTED; ++ ++ if (!WIFEXITED (status)) ++ FAIL_EXIT1 ("Unexpected exit status %d from child process\n", status); + +- /* Something went wrong and our argv was corrupted. */ +- _exit (1); ++ return 0; ++ } + } + + #define TEST_FUNCTION_ARGV do_test diff --git a/glibc-rh1934155-5.patch b/glibc-rh1934155-5.patch new file mode 100755 index 0000000..1f5dea1 --- /dev/null +++ b/glibc-rh1934155-5.patch @@ -0,0 +1,613 @@ +Enhance setuid-tunables test + +Instead of passing GLIBC_TUNABLES via the environment, pass the +environment variable from parent to child. This allows us to test +multiple variables to ensure better coverage. + +The test list currently only includes the case that's already being +tested. More tests will be added later. +Reviewed-by: Carlos O'Donell + +(cherry picked from commit 061fe3f8add46a89b7453e87eabb9c4695005ced) + +Also add intprops.h from 2.29 from commit 8e6fd2bdb21efe2cc1ae7571ff8fb2599db6a05a + +diff --git a/elf/Makefile b/elf/Makefile +index fc9c685b9d23bb6c..2093cefa7e73349e 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -1597,8 +1597,6 @@ $(objpfx)tst-nodelete-dlclose.out: $(objpfx)tst-nodelete-dlclose-dso.so \ + + tst-env-setuid-ENV = MALLOC_CHECK_=2 MALLOC_MMAP_THRESHOLD_=4096 \ + LD_HWCAP_MASK=0x1 +-tst-env-setuid-tunables-ENV = \ +- GLIBC_TUNABLES=glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096 + + $(objpfx)tst-debug1: $(libdl) + $(objpfx)tst-debug1.out: $(objpfx)tst-debug1mod1.so +diff --git a/elf/tst-env-setuid-tunables.c b/elf/tst-env-setuid-tunables.c +index d7c4f0d5742cd526..a48281b175af6920 100644 +--- a/elf/tst-env-setuid-tunables.c ++++ b/elf/tst-env-setuid-tunables.c +@@ -25,35 +25,50 @@ + #include "config.h" + #undef _LIBC + +-#define test_parent test_parent_tunables +-#define test_child test_child_tunables +- +-static int test_child_tunables (void); +-static int test_parent_tunables (void); +- +-#include "tst-env-setuid.c" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++const char *teststrings[] = ++{ ++ "glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096", ++}; + +-#define CHILD_VALSTRING_VALUE "glibc.malloc.mmap_threshold=4096" +-#define PARENT_VALSTRING_VALUE \ +- "glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096" ++const char *resultstrings[] = ++{ ++ "glibc.malloc.mmap_threshold=4096", ++}; + + static int +-test_child_tunables (void) ++test_child (int off) + { + const char *val = getenv ("GLIBC_TUNABLES"); + + #if HAVE_TUNABLES +- if (val != NULL && strcmp (val, CHILD_VALSTRING_VALUE) == 0) ++ if (val != NULL && strcmp (val, resultstrings[off]) == 0) + return 0; + + if (val != NULL) +- printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val); ++ printf ("[%d] Unexpected GLIBC_TUNABLES VALUE %s\n", off, val); + + return 1; + #else + if (val != NULL) + { +- printf ("GLIBC_TUNABLES not cleared\n"); ++ printf ("[%d] GLIBC_TUNABLES not cleared\n", off); + return 1; + } + return 0; +@@ -61,15 +76,48 @@ test_child_tunables (void) + } + + static int +-test_parent_tunables (void) ++do_test (int argc, char **argv) + { +- const char *val = getenv ("GLIBC_TUNABLES"); ++ /* Setgid child process. */ ++ if (argc == 2) ++ { ++ if (getgid () == getegid ()) ++ /* This can happen if the file system is mounted nosuid. */ ++ FAIL_UNSUPPORTED ("SGID failed: GID and EGID match (%jd)\n", ++ (intmax_t) getgid ()); + +- if (val != NULL && strcmp (val, PARENT_VALSTRING_VALUE) == 0) +- return 0; ++ int ret = test_child (atoi (argv[1])); + +- if (val != NULL) +- printf ("Unexpected GLIBC_TUNABLES VALUE %s\n", val); ++ if (ret != 0) ++ exit (1); + +- return 1; ++ exit (EXIT_SUCCESS); ++ } ++ else ++ { ++ int ret = 0; ++ ++ /* Spawn tests. */ ++ for (int i = 0; i < array_length (teststrings); i++) ++ { ++ char buf[INT_BUFSIZE_BOUND (int)]; ++ ++ printf ("Spawned test for %s (%d)\n", teststrings[i], i); ++ snprintf (buf, sizeof (buf), "%d\n", i); ++ if (setenv ("GLIBC_TUNABLES", teststrings[i], 1) != 0) ++ exit (1); ++ ++ int status = support_capture_subprogram_self_sgid (buf); ++ ++ /* Bail out early if unsupported. */ ++ if (WEXITSTATUS (status) == EXIT_UNSUPPORTED) ++ return EXIT_UNSUPPORTED; ++ ++ ret |= status; ++ } ++ return ret; ++ } + } ++ ++#define TEST_FUNCTION_ARGV do_test ++#include +diff --git a/include/intprops.h b/include/intprops.h +new file mode 100644 +index 0000000000000000..9702aec4c6e3c80a +--- /dev/null ++++ b/include/intprops.h +@@ -0,0 +1,455 @@ ++/* intprops.h -- properties of integer types ++ ++ Copyright (C) 2001-2018 Free Software Foundation, Inc. ++ ++ This program 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. ++ ++ This program 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 this program. If not, see . */ ++ ++/* Written by Paul Eggert. */ ++ ++#ifndef _GL_INTPROPS_H ++#define _GL_INTPROPS_H ++ ++#include ++ ++/* Return a value with the common real type of E and V and the value of V. ++ Do not evaluate E. */ ++#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v)) ++ ++/* Act like _GL_INT_CONVERT (E, -V) but work around a bug in IRIX 6.5 cc; see ++ . */ ++#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v)) ++ ++/* The extra casts in the following macros work around compiler bugs, ++ e.g., in Cray C 5.0.3.0. */ ++ ++/* True if the arithmetic type T is an integer type. bool counts as ++ an integer. */ ++#define TYPE_IS_INTEGER(t) ((t) 1.5 == 1) ++ ++/* True if the real type T is signed. */ ++#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) ++ ++/* Return 1 if the real expression E, after promotion, has a ++ signed or floating type. Do not evaluate E. */ ++#define EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0) ++ ++ ++/* Minimum and maximum values for integer types and expressions. */ ++ ++/* The width in bits of the integer type or expression T. ++ Do not evaluate T. ++ Padding bits are not supported; this is checked at compile-time below. */ ++#define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT) ++ ++/* The maximum and minimum values for the integer type T. */ ++#define TYPE_MINIMUM(t) ((t) ~ TYPE_MAXIMUM (t)) ++#define TYPE_MAXIMUM(t) \ ++ ((t) (! TYPE_SIGNED (t) \ ++ ? (t) -1 \ ++ : ((((t) 1 << (TYPE_WIDTH (t) - 2)) - 1) * 2 + 1))) ++ ++/* The maximum and minimum values for the type of the expression E, ++ after integer promotion. E is not evaluated. */ ++#define _GL_INT_MINIMUM(e) \ ++ (EXPR_SIGNED (e) \ ++ ? ~ _GL_SIGNED_INT_MAXIMUM (e) \ ++ : _GL_INT_CONVERT (e, 0)) ++#define _GL_INT_MAXIMUM(e) \ ++ (EXPR_SIGNED (e) \ ++ ? _GL_SIGNED_INT_MAXIMUM (e) \ ++ : _GL_INT_NEGATE_CONVERT (e, 1)) ++#define _GL_SIGNED_INT_MAXIMUM(e) \ ++ (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH ((e) + 0) - 2)) - 1) * 2 + 1) ++ ++/* Work around OpenVMS incompatibility with C99. */ ++#if !defined LLONG_MAX && defined __INT64_MAX ++# define LLONG_MAX __INT64_MAX ++# define LLONG_MIN __INT64_MIN ++#endif ++ ++/* This include file assumes that signed types are two's complement without ++ padding bits; the above macros have undefined behavior otherwise. ++ If this is a problem for you, please let us know how to fix it for your host. ++ This assumption is tested by the intprops-tests module. */ ++ ++/* Does the __typeof__ keyword work? This could be done by ++ 'configure', but for now it's easier to do it by hand. */ ++#if (2 <= __GNUC__ \ ++ || (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \ ++ || (0x5110 <= __SUNPRO_C && !__STDC__)) ++# define _GL_HAVE___TYPEOF__ 1 ++#else ++# define _GL_HAVE___TYPEOF__ 0 ++#endif ++ ++/* Return 1 if the integer type or expression T might be signed. Return 0 ++ if it is definitely unsigned. This macro does not evaluate its argument, ++ and expands to an integer constant expression. */ ++#if _GL_HAVE___TYPEOF__ ++# define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t)) ++#else ++# define _GL_SIGNED_TYPE_OR_EXPR(t) 1 ++#endif ++ ++/* Bound on length of the string representing an unsigned integer ++ value representable in B bits. log10 (2.0) < 146/485. The ++ smallest value of B where this bound is not tight is 2621. */ ++#define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485) ++ ++/* Bound on length of the string representing an integer type or expression T. ++ Subtract 1 for the sign bit if T is signed, and then add 1 more for ++ a minus sign if needed. ++ ++ Because _GL_SIGNED_TYPE_OR_EXPR sometimes returns 0 when its argument is ++ signed, this macro may overestimate the true bound by one byte when ++ applied to unsigned types of size 2, 4, 16, ... bytes. */ ++#define INT_STRLEN_BOUND(t) \ ++ (INT_BITS_STRLEN_BOUND (TYPE_WIDTH (t) - _GL_SIGNED_TYPE_OR_EXPR (t)) \ ++ + _GL_SIGNED_TYPE_OR_EXPR (t)) ++ ++/* Bound on buffer size needed to represent an integer type or expression T, ++ including the terminating null. */ ++#define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) ++ ++ ++/* Range overflow checks. ++ ++ The INT__RANGE_OVERFLOW macros return 1 if the corresponding C ++ operators might not yield numerically correct answers due to ++ arithmetic overflow. They do not rely on undefined or ++ implementation-defined behavior. Their implementations are simple ++ and straightforward, but they are a bit harder to use than the ++ INT__OVERFLOW macros described below. ++ ++ Example usage: ++ ++ long int i = ...; ++ long int j = ...; ++ if (INT_MULTIPLY_RANGE_OVERFLOW (i, j, LONG_MIN, LONG_MAX)) ++ printf ("multiply would overflow"); ++ else ++ printf ("product is %ld", i * j); ++ ++ Restrictions on *_RANGE_OVERFLOW macros: ++ ++ These macros do not check for all possible numerical problems or ++ undefined or unspecified behavior: they do not check for division ++ by zero, for bad shift counts, or for shifting negative numbers. ++ ++ These macros may evaluate their arguments zero or multiple times, ++ so the arguments should not have side effects. The arithmetic ++ arguments (including the MIN and MAX arguments) must be of the same ++ integer type after the usual arithmetic conversions, and the type ++ must have minimum value MIN and maximum MAX. Unsigned types should ++ use a zero MIN of the proper type. ++ ++ These macros are tuned for constant MIN and MAX. For commutative ++ operations such as A + B, they are also tuned for constant B. */ ++ ++/* Return 1 if A + B would overflow in [MIN,MAX] arithmetic. ++ See above for restrictions. */ ++#define INT_ADD_RANGE_OVERFLOW(a, b, min, max) \ ++ ((b) < 0 \ ++ ? (a) < (min) - (b) \ ++ : (max) - (b) < (a)) ++ ++/* Return 1 if A - B would overflow in [MIN,MAX] arithmetic. ++ See above for restrictions. */ ++#define INT_SUBTRACT_RANGE_OVERFLOW(a, b, min, max) \ ++ ((b) < 0 \ ++ ? (max) + (b) < (a) \ ++ : (a) < (min) + (b)) ++ ++/* Return 1 if - A would overflow in [MIN,MAX] arithmetic. ++ See above for restrictions. */ ++#define INT_NEGATE_RANGE_OVERFLOW(a, min, max) \ ++ ((min) < 0 \ ++ ? (a) < - (max) \ ++ : 0 < (a)) ++ ++/* Return 1 if A * B would overflow in [MIN,MAX] arithmetic. ++ See above for restrictions. Avoid && and || as they tickle ++ bugs in Sun C 5.11 2010/08/13 and other compilers; see ++ . */ ++#define INT_MULTIPLY_RANGE_OVERFLOW(a, b, min, max) \ ++ ((b) < 0 \ ++ ? ((a) < 0 \ ++ ? (a) < (max) / (b) \ ++ : (b) == -1 \ ++ ? 0 \ ++ : (min) / (b) < (a)) \ ++ : (b) == 0 \ ++ ? 0 \ ++ : ((a) < 0 \ ++ ? (a) < (min) / (b) \ ++ : (max) / (b) < (a))) ++ ++/* Return 1 if A / B would overflow in [MIN,MAX] arithmetic. ++ See above for restrictions. Do not check for division by zero. */ ++#define INT_DIVIDE_RANGE_OVERFLOW(a, b, min, max) \ ++ ((min) < 0 && (b) == -1 && (a) < - (max)) ++ ++/* Return 1 if A % B would overflow in [MIN,MAX] arithmetic. ++ See above for restrictions. Do not check for division by zero. ++ Mathematically, % should never overflow, but on x86-like hosts ++ INT_MIN % -1 traps, and the C standard permits this, so treat this ++ as an overflow too. */ ++#define INT_REMAINDER_RANGE_OVERFLOW(a, b, min, max) \ ++ INT_DIVIDE_RANGE_OVERFLOW (a, b, min, max) ++ ++/* Return 1 if A << B would overflow in [MIN,MAX] arithmetic. ++ See above for restrictions. Here, MIN and MAX are for A only, and B need ++ not be of the same type as the other arguments. The C standard says that ++ behavior is undefined for shifts unless 0 <= B < wordwidth, and that when ++ A is negative then A << B has undefined behavior and A >> B has ++ implementation-defined behavior, but do not check these other ++ restrictions. */ ++#define INT_LEFT_SHIFT_RANGE_OVERFLOW(a, b, min, max) \ ++ ((a) < 0 \ ++ ? (a) < (min) >> (b) \ ++ : (max) >> (b) < (a)) ++ ++/* True if __builtin_add_overflow (A, B, P) works when P is non-null. */ ++#if 5 <= __GNUC__ && !defined __ICC ++# define _GL_HAS_BUILTIN_OVERFLOW 1 ++#else ++# define _GL_HAS_BUILTIN_OVERFLOW 0 ++#endif ++ ++/* True if __builtin_add_overflow_p (A, B, C) works. */ ++#define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__) ++ ++/* The _GL*_OVERFLOW macros have the same restrictions as the ++ *_RANGE_OVERFLOW macros, except that they do not assume that operands ++ (e.g., A and B) have the same type as MIN and MAX. Instead, they assume ++ that the result (e.g., A + B) has that type. */ ++#if _GL_HAS_BUILTIN_OVERFLOW_P ++# define _GL_ADD_OVERFLOW(a, b, min, max) \ ++ __builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0) ++# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ ++ __builtin_sub_overflow_p (a, b, (__typeof__ ((a) - (b))) 0) ++# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ ++ __builtin_mul_overflow_p (a, b, (__typeof__ ((a) * (b))) 0) ++#else ++# define _GL_ADD_OVERFLOW(a, b, min, max) \ ++ ((min) < 0 ? INT_ADD_RANGE_OVERFLOW (a, b, min, max) \ ++ : (a) < 0 ? (b) <= (a) + (b) \ ++ : (b) < 0 ? (a) <= (a) + (b) \ ++ : (a) + (b) < (b)) ++# define _GL_SUBTRACT_OVERFLOW(a, b, min, max) \ ++ ((min) < 0 ? INT_SUBTRACT_RANGE_OVERFLOW (a, b, min, max) \ ++ : (a) < 0 ? 1 \ ++ : (b) < 0 ? (a) - (b) <= (a) \ ++ : (a) < (b)) ++# define _GL_MULTIPLY_OVERFLOW(a, b, min, max) \ ++ (((min) == 0 && (((a) < 0 && 0 < (b)) || ((b) < 0 && 0 < (a)))) \ ++ || INT_MULTIPLY_RANGE_OVERFLOW (a, b, min, max)) ++#endif ++#define _GL_DIVIDE_OVERFLOW(a, b, min, max) \ ++ ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ ++ : (a) < 0 ? (b) <= (a) + (b) - 1 \ ++ : (b) < 0 && (a) + (b) <= (a)) ++#define _GL_REMAINDER_OVERFLOW(a, b, min, max) \ ++ ((min) < 0 ? (b) == _GL_INT_NEGATE_CONVERT (min, 1) && (a) < - (max) \ ++ : (a) < 0 ? (a) % (b) != ((max) - (b) + 1) % (b) \ ++ : (b) < 0 && ! _GL_UNSIGNED_NEG_MULTIPLE (a, b, max)) ++ ++/* Return a nonzero value if A is a mathematical multiple of B, where ++ A is unsigned, B is negative, and MAX is the maximum value of A's ++ type. A's type must be the same as (A % B)'s type. Normally (A % ++ -B == 0) suffices, but things get tricky if -B would overflow. */ ++#define _GL_UNSIGNED_NEG_MULTIPLE(a, b, max) \ ++ (((b) < -_GL_SIGNED_INT_MAXIMUM (b) \ ++ ? (_GL_SIGNED_INT_MAXIMUM (b) == (max) \ ++ ? (a) \ ++ : (a) % (_GL_INT_CONVERT (a, _GL_SIGNED_INT_MAXIMUM (b)) + 1)) \ ++ : (a) % - (b)) \ ++ == 0) ++ ++/* Check for integer overflow, and report low order bits of answer. ++ ++ The INT__OVERFLOW macros return 1 if the corresponding C operators ++ might not yield numerically correct answers due to arithmetic overflow. ++ The INT__WRAPV macros also store the low-order bits of the answer. ++ These macros work correctly on all known practical hosts, and do not rely ++ on undefined behavior due to signed arithmetic overflow. ++ ++ Example usage, assuming A and B are long int: ++ ++ if (INT_MULTIPLY_OVERFLOW (a, b)) ++ printf ("result would overflow\n"); ++ else ++ printf ("result is %ld (no overflow)\n", a * b); ++ ++ Example usage with WRAPV flavor: ++ ++ long int result; ++ bool overflow = INT_MULTIPLY_WRAPV (a, b, &result); ++ printf ("result is %ld (%s)\n", result, ++ overflow ? "after overflow" : "no overflow"); ++ ++ Restrictions on these macros: ++ ++ These macros do not check for all possible numerical problems or ++ undefined or unspecified behavior: they do not check for division ++ by zero, for bad shift counts, or for shifting negative numbers. ++ ++ These macros may evaluate their arguments zero or multiple times, so the ++ arguments should not have side effects. ++ ++ The WRAPV macros are not constant expressions. They support only ++ +, binary -, and *. The result type must be signed. ++ ++ These macros are tuned for their last argument being a constant. ++ ++ Return 1 if the integer expressions A * B, A - B, -A, A * B, A / B, ++ A % B, and A << B would overflow, respectively. */ ++ ++#define INT_ADD_OVERFLOW(a, b) \ ++ _GL_BINARY_OP_OVERFLOW (a, b, _GL_ADD_OVERFLOW) ++#define INT_SUBTRACT_OVERFLOW(a, b) \ ++ _GL_BINARY_OP_OVERFLOW (a, b, _GL_SUBTRACT_OVERFLOW) ++#if _GL_HAS_BUILTIN_OVERFLOW_P ++# define INT_NEGATE_OVERFLOW(a) INT_SUBTRACT_OVERFLOW (0, a) ++#else ++# define INT_NEGATE_OVERFLOW(a) \ ++ INT_NEGATE_RANGE_OVERFLOW (a, _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) ++#endif ++#define INT_MULTIPLY_OVERFLOW(a, b) \ ++ _GL_BINARY_OP_OVERFLOW (a, b, _GL_MULTIPLY_OVERFLOW) ++#define INT_DIVIDE_OVERFLOW(a, b) \ ++ _GL_BINARY_OP_OVERFLOW (a, b, _GL_DIVIDE_OVERFLOW) ++#define INT_REMAINDER_OVERFLOW(a, b) \ ++ _GL_BINARY_OP_OVERFLOW (a, b, _GL_REMAINDER_OVERFLOW) ++#define INT_LEFT_SHIFT_OVERFLOW(a, b) \ ++ INT_LEFT_SHIFT_RANGE_OVERFLOW (a, b, \ ++ _GL_INT_MINIMUM (a), _GL_INT_MAXIMUM (a)) ++ ++/* Return 1 if the expression A B would overflow, ++ where OP_RESULT_OVERFLOW (A, B, MIN, MAX) does the actual test, ++ assuming MIN and MAX are the minimum and maximum for the result type. ++ Arguments should be free of side effects. */ ++#define _GL_BINARY_OP_OVERFLOW(a, b, op_result_overflow) \ ++ op_result_overflow (a, b, \ ++ _GL_INT_MINIMUM (_GL_INT_CONVERT (a, b)), \ ++ _GL_INT_MAXIMUM (_GL_INT_CONVERT (a, b))) ++ ++/* Store the low-order bits of A + B, A - B, A * B, respectively, into *R. ++ Return 1 if the result overflows. See above for restrictions. */ ++#define INT_ADD_WRAPV(a, b, r) \ ++ _GL_INT_OP_WRAPV (a, b, r, +, __builtin_add_overflow, INT_ADD_OVERFLOW) ++#define INT_SUBTRACT_WRAPV(a, b, r) \ ++ _GL_INT_OP_WRAPV (a, b, r, -, __builtin_sub_overflow, INT_SUBTRACT_OVERFLOW) ++#define INT_MULTIPLY_WRAPV(a, b, r) \ ++ _GL_INT_OP_WRAPV (a, b, r, *, __builtin_mul_overflow, INT_MULTIPLY_OVERFLOW) ++ ++/* Nonzero if this compiler has GCC bug 68193 or Clang bug 25390. See: ++ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68193 ++ https://llvm.org/bugs/show_bug.cgi?id=25390 ++ For now, assume all versions of GCC-like compilers generate bogus ++ warnings for _Generic. This matters only for older compilers that ++ lack __builtin_add_overflow. */ ++#if __GNUC__ ++# define _GL__GENERIC_BOGUS 1 ++#else ++# define _GL__GENERIC_BOGUS 0 ++#endif ++ ++/* Store the low-order bits of A B into *R, where OP specifies ++ the operation. BUILTIN is the builtin operation, and OVERFLOW the ++ overflow predicate. Return 1 if the result overflows. See above ++ for restrictions. */ ++#if _GL_HAS_BUILTIN_OVERFLOW ++# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) builtin (a, b, r) ++#elif 201112 <= __STDC_VERSION__ && !_GL__GENERIC_BOGUS ++# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \ ++ (_Generic \ ++ (*(r), \ ++ signed char: \ ++ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ ++ signed char, SCHAR_MIN, SCHAR_MAX), \ ++ short int: \ ++ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ ++ short int, SHRT_MIN, SHRT_MAX), \ ++ int: \ ++ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ ++ int, INT_MIN, INT_MAX), \ ++ long int: \ ++ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ ++ long int, LONG_MIN, LONG_MAX), \ ++ long long int: \ ++ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ ++ long long int, LLONG_MIN, LLONG_MAX))) ++#else ++# define _GL_INT_OP_WRAPV(a, b, r, op, builtin, overflow) \ ++ (sizeof *(r) == sizeof (signed char) \ ++ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ ++ signed char, SCHAR_MIN, SCHAR_MAX) \ ++ : sizeof *(r) == sizeof (short int) \ ++ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ ++ short int, SHRT_MIN, SHRT_MAX) \ ++ : sizeof *(r) == sizeof (int) \ ++ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \ ++ int, INT_MIN, INT_MAX) \ ++ : _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow)) ++# ifdef LLONG_MAX ++# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \ ++ (sizeof *(r) == sizeof (long int) \ ++ ? _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ ++ long int, LONG_MIN, LONG_MAX) \ ++ : _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long long int, \ ++ long long int, LLONG_MIN, LLONG_MAX)) ++# else ++# define _GL_INT_OP_WRAPV_LONGISH(a, b, r, op, overflow) \ ++ _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned long int, \ ++ long int, LONG_MIN, LONG_MAX) ++# endif ++#endif ++ ++/* Store the low-order bits of A B into *R, where the operation ++ is given by OP. Use the unsigned type UT for calculation to avoid ++ overflow problems. *R's type is T, with extrema TMIN and TMAX. ++ T must be a signed integer type. Return 1 if the result overflows. */ ++#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \ ++ (sizeof ((a) op (b)) < sizeof (t) \ ++ ? _GL_INT_OP_CALC1 ((t) (a), (t) (b), r, op, overflow, ut, t, tmin, tmax) \ ++ : _GL_INT_OP_CALC1 (a, b, r, op, overflow, ut, t, tmin, tmax)) ++#define _GL_INT_OP_CALC1(a, b, r, op, overflow, ut, t, tmin, tmax) \ ++ ((overflow (a, b) \ ++ || (EXPR_SIGNED ((a) op (b)) && ((a) op (b)) < (tmin)) \ ++ || (tmax) < ((a) op (b))) \ ++ ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \ ++ : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0)) ++ ++/* Return the low-order bits of A B, where the operation is given ++ by OP. Use the unsigned type UT for calculation to avoid undefined ++ behavior on signed integer overflow, and convert the result to type T. ++ UT is at least as wide as T and is no narrower than unsigned int, ++ T is two's complement, and there is no padding or trap representations. ++ Assume that converting UT to T yields the low-order bits, as is ++ done in all known two's-complement C compilers. E.g., see: ++ https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html ++ ++ According to the C standard, converting UT to T yields an ++ implementation-defined result or signal for values outside T's ++ range. However, code that works around this theoretical problem ++ runs afoul of a compiler bug in Oracle Studio 12.3 x86. See: ++ https://lists.gnu.org/r/bug-gnulib/2017-04/msg00049.html ++ As the compiler bug is real, don't try to work around the ++ theoretical problem. */ ++ ++#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \ ++ ((t) ((ut) (a) op (ut) (b))) ++ ++#endif /* _GL_INTPROPS_H */ diff --git a/glibc-rh1934155-6.patch b/glibc-rh1934155-6.patch new file mode 100755 index 0000000..83e0ff4 --- /dev/null +++ b/glibc-rh1934155-6.patch @@ -0,0 +1,160 @@ +Fix SXID_ERASE behavior in setuid programs (BZ #27471) + +When parse_tunables tries to erase a tunable marked as SXID_ERASE for +setuid programs, it ends up setting the envvar string iterator +incorrectly, because of which it may parse the next tunable +incorrectly. Given that currently the implementation allows malformed +and unrecognized tunables pass through, it may even allow SXID_ERASE +tunables to go through. + +This change revamps the SXID_ERASE implementation so that: + +- Only valid tunables are written back to the tunestr string, because + of which children of SXID programs will only inherit a clean list of + identified tunables that are not SXID_ERASE. + +- Unrecognized tunables get scrubbed off from the environment and + subsequently from the child environment. + +- This has the side-effect that a tunable that is not identified by + the setxid binary, will not be passed on to a non-setxid child even + if the child could have identified that tunable. This may break + applications that expect this behaviour but expecting such tunables + to cross the SXID boundary is wrong. +Reviewed-by: Carlos O'Donell + +(cherry picked from commit 2ed18c5b534d9e92fc006202a5af0df6b72e7aca) + +diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c +index 4c9d36e3980758b9..bbc3679e3564a766 100644 +--- a/elf/dl-tunables.c ++++ b/elf/dl-tunables.c +@@ -178,6 +178,7 @@ parse_tunables (char *tunestr, char *valstring) + return; + + char *p = tunestr; ++ size_t off = 0; + + while (true) + { +@@ -191,7 +192,11 @@ parse_tunables (char *tunestr, char *valstring) + /* If we reach the end of the string before getting a valid name-value + pair, bail out. */ + if (p[len] == '\0') +- return; ++ { ++ if (__libc_enable_secure) ++ tunestr[off] = '\0'; ++ return; ++ } + + /* We did not find a valid name-value pair before encountering the + colon. */ +@@ -217,35 +222,28 @@ parse_tunables (char *tunestr, char *valstring) + + if (tunable_is_name (cur->name, name)) + { +- /* If we are in a secure context (AT_SECURE) then ignore the tunable +- unless it is explicitly marked as secure. Tunable values take +- precendence over their envvar aliases. */ ++ /* If we are in a secure context (AT_SECURE) then ignore the ++ tunable unless it is explicitly marked as secure. Tunable ++ values take precedence over their envvar aliases. We write ++ the tunables that are not SXID_ERASE back to TUNESTR, thus ++ dropping all SXID_ERASE tunables and any invalid or ++ unrecognized tunables. */ + if (__libc_enable_secure) + { +- if (cur->security_level == TUNABLE_SECLEVEL_SXID_ERASE) ++ if (cur->security_level != TUNABLE_SECLEVEL_SXID_ERASE) + { +- if (p[len] == '\0') +- { +- /* Last tunable in the valstring. Null-terminate and +- return. */ +- *name = '\0'; +- return; +- } +- else +- { +- /* Remove the current tunable from the string. We do +- this by overwriting the string starting from NAME +- (which is where the current tunable begins) with +- the remainder of the string. We then have P point +- to NAME so that we continue in the correct +- position in the valstring. */ +- char *q = &p[len + 1]; +- p = name; +- while (*q != '\0') +- *name++ = *q++; +- name[0] = '\0'; +- len = 0; +- } ++ if (off > 0) ++ tunestr[off++] = ':'; ++ ++ const char *n = cur->name; ++ ++ while (*n != '\0') ++ tunestr[off++] = *n++; ++ ++ tunestr[off++] = '='; ++ ++ for (size_t j = 0; j < len; j++) ++ tunestr[off++] = value[j]; + } + + if (cur->security_level != TUNABLE_SECLEVEL_NONE) +@@ -258,9 +256,7 @@ parse_tunables (char *tunestr, char *valstring) + } + } + +- if (p[len] == '\0') +- return; +- else ++ if (p[len] != '\0') + p += len + 1; + } + } +diff --git a/elf/tst-env-setuid-tunables.c b/elf/tst-env-setuid-tunables.c +index a48281b175af6920..0b9b075c40598c6f 100644 +--- a/elf/tst-env-setuid-tunables.c ++++ b/elf/tst-env-setuid-tunables.c +@@ -45,11 +45,37 @@ + const char *teststrings[] = + { + "glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096", ++ "glibc.malloc.check=2:glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096", ++ "glibc.malloc.check=2:glibc.malloc.mmap_threshold=4096:glibc.malloc.check=2", ++ "glibc.malloc.perturb=0x800", ++ "glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096", ++ "glibc.malloc.perturb=0x800:not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096", ++ "glibc.not_valid.check=2:glibc.malloc.mmap_threshold=4096", ++ "not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096", ++ "glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096:glibc.malloc.check=2", ++ "glibc.malloc.check=4:glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096", ++ ":glibc.malloc.garbage=2:glibc.malloc.check=1", ++ "glibc.malloc.check=1:glibc.malloc.check=2", ++ "not_valid.malloc.check=2", ++ "glibc.not_valid.check=2", + }; + + const char *resultstrings[] = + { + "glibc.malloc.mmap_threshold=4096", ++ "glibc.malloc.mmap_threshold=4096", ++ "glibc.malloc.mmap_threshold=4096", ++ "glibc.malloc.perturb=0x800", ++ "glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096", ++ "glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096", ++ "glibc.malloc.mmap_threshold=4096", ++ "glibc.malloc.mmap_threshold=4096", ++ "", ++ "", ++ "", ++ "", ++ "", ++ "", + }; + + static int diff --git a/glibc-rh1936864.patch b/glibc-rh1936864.patch new file mode 100755 index 0000000..688a60c --- /dev/null +++ b/glibc-rh1936864.patch @@ -0,0 +1,28 @@ +commit 583dd860d5b833037175247230a328f0050dbfe9 +Author: Paul Eggert +Date: Mon Jan 21 11:08:13 2019 -0800 + + 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. + +diff --git a/posix/regexec.c b/posix/regexec.c +index 73644c2341336e66..06b8487c3e3eab0e 100644 +--- a/posix/regexec.c ++++ b/posix/regexec.c +@@ -1289,8 +1289,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/glibc-rh1956357-1.patch b/glibc-rh1956357-1.patch new file mode 100755 index 0000000..2c4fca1 --- /dev/null +++ b/glibc-rh1956357-1.patch @@ -0,0 +1,100 @@ +commit 56c81132ccc6f468fa4fc29c536db060e18e9d87 +Author: Raphael Moreira Zinsly +Date: Tue Feb 23 14:14:37 2021 -0300 + + powerpc: Add optimized ilogb* for POWER9 + + The instructions xsxexpdp and xsxexpqp introduced on POWER9 extract + the exponent from a double-precision and quad-precision floating-point + respectively, thus they can be used to improve ilogb, ilogbf and ilogbf128. + +diff --git a/sysdeps/powerpc/fpu/math_private.h b/sysdeps/powerpc/fpu/math_private.h +index e642d6c8237578ea..5bbc468829062a48 100644 +--- a/sysdeps/powerpc/fpu/math_private.h ++++ b/sysdeps/powerpc/fpu/math_private.h +@@ -26,7 +26,28 @@ + + #include_next + +-#if defined _ARCH_PWR9 && __HAVE_DISTINCT_FLOAT128 ++#ifdef _ARCH_PWR9 ++ ++#if __GNUC_PREREQ (8, 0) ++# define _GL_HAS_BUILTIN_ILOGB 1 ++#elif defined __has_builtin ++# define _GL_HAS_BUILTIN_ILOGB __has_builtin (__builtin_vsx_scalar_extract_exp) ++#else ++# define _GL_HAS_BUILTIN_ILOGB 0 ++#endif ++ ++#define __builtin_test_dc_ilogbf __builtin_test_dc_ilogb ++#define __builtin_ilogbf __builtin_ilogb ++ ++#define __builtin_test_dc_ilogb(x, y) \ ++ __builtin_vsx_scalar_test_data_class_dp(x, y) ++#define __builtin_ilogb(x) __builtin_vsx_scalar_extract_exp(x) - 0x3ff ++ ++#define __builtin_test_dc_ilogbf128(x, y) \ ++ __builtin_vsx_scalar_test_data_class_qp(x, y) ++#define __builtin_ilogbf128(x) __builtin_vsx_scalar_extract_expq(x) - 0x3fff ++ ++#if __HAVE_DISTINCT_FLOAT128 + extern __always_inline _Float128 + __ieee754_sqrtf128 (_Float128 __x) + { +@@ -35,6 +56,9 @@ __ieee754_sqrtf128 (_Float128 __x) + return __z; + } + #endif ++#else /* !_ARCH_PWR9 */ ++#define _GL_HAS_BUILTIN_ILOGB 0 ++#endif + + #if defined _ARCH_PWR5X + +diff --git a/sysdeps/powerpc/powerpc64/le/fpu/w_ilogb_template.c b/sysdeps/powerpc/powerpc64/le/fpu/w_ilogb_template.c +new file mode 100644 +index 0000000000000000..b5c1c0aa9db86f3d +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/fpu/w_ilogb_template.c +@@ -0,0 +1,30 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#if _GL_HAS_BUILTIN_ILOGB ++int ++M_DECL_FUNC (__ilogb) (FLOAT x) ++{ ++ int r; ++ /* Check for exceptional cases. */ ++ if (! M_SUF(__builtin_test_dc_ilogb) (x, 0x7f)) ++ r = M_SUF (__builtin_ilogb) (x); ++ else ++ /* Fallback to the generic ilogb if x is NaN, Inf or subnormal. */ ++ r = M_SUF (__ieee754_ilogb) (x); ++ if (__builtin_expect (r == FP_ILOGB0, 0) ++ || __builtin_expect (r == FP_ILOGBNAN, 0) ++ || __builtin_expect (r == INT_MAX, 0)) ++ { ++ __set_errno (EDOM); ++ __feraiseexcept (FE_INVALID); ++ } ++ return r; ++} ++declare_mgen_alias (__ilogb, ilogb) ++#else ++#include ++#endif +diff --git a/sysdeps/powerpc/powerpc64/le/fpu/w_ilogbl.c b/sysdeps/powerpc/powerpc64/le/fpu/w_ilogbl.c +new file mode 100644 +index 0000000000000000..205f154f0089a269 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/fpu/w_ilogbl.c +@@ -0,0 +1,4 @@ ++/* Skip the optimization for long double as ibm128 does not provide an ++ optimized builtin. */ ++#include ++#include diff --git a/glibc-rh1956357-2.patch b/glibc-rh1956357-2.patch new file mode 100755 index 0000000..c1da766 --- /dev/null +++ b/glibc-rh1956357-2.patch @@ -0,0 +1,64 @@ +commit a7d88506c260e7a0e4268803e76fc19e38ed041f +Author: Raphael Moreira Zinsly +Date: Thu Feb 25 09:58:52 2021 -0300 + + powerpc: Add optimized llogb* for POWER9 + + The POWER9 builtins used to improve the ilogb* functions can be + used in the llogb* functions as well. + +diff --git a/sysdeps/powerpc/powerpc64/le/fpu/w_llogb_template.c b/sysdeps/powerpc/powerpc64/le/fpu/w_llogb_template.c +new file mode 100644 +index 0000000000000000..d00b71d2a34e28da +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/fpu/w_llogb_template.c +@@ -0,0 +1,39 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#if _GL_HAS_BUILTIN_ILOGB ++long int ++M_DECL_FUNC (__llogb) (FLOAT x) ++{ ++ int r; ++ /* Check for exceptional cases. */ ++ if (! M_SUF(__builtin_test_dc_ilogb) (x, 0x7f)) ++ r = M_SUF (__builtin_ilogb) (x); ++ else ++ /* Fallback to the generic ilogb if x is NaN, Inf or subnormal. */ ++ r = M_SUF (__ieee754_ilogb) (x); ++ long int lr = r; ++ if (__glibc_unlikely (r == FP_ILOGB0) ++ || __glibc_unlikely (r == FP_ILOGBNAN) ++ || __glibc_unlikely (r == INT_MAX)) ++ { ++#if LONG_MAX != INT_MAX ++ if (r == FP_ILOGB0) ++ lr = FP_LLOGB0; ++ else if (r == FP_ILOGBNAN) ++ lr = FP_LLOGBNAN; ++ else ++ lr = LONG_MAX; ++#endif ++ __set_errno (EDOM); ++ __feraiseexcept (FE_INVALID); ++ } ++ return lr; ++} ++declare_mgen_alias (__llogb, llogb) ++#else ++#include ++#endif +diff --git a/sysdeps/powerpc/powerpc64/le/fpu/w_llogbl.c b/sysdeps/powerpc/powerpc64/le/fpu/w_llogbl.c +new file mode 100644 +index 0000000000000000..69477a37ae82c476 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/fpu/w_llogbl.c +@@ -0,0 +1,4 @@ ++/* Skip the optimization for long double as ibm128 does not provide an ++ optimized builtin. */ ++#include ++#include diff --git a/glibc-rh1956357-3.patch b/glibc-rh1956357-3.patch new file mode 100755 index 0000000..6596582 --- /dev/null +++ b/glibc-rh1956357-3.patch @@ -0,0 +1,334 @@ +commit 10624a97e8e47004985740cbb04060a84cfada76 +Author: Matheus Castanho +Date: Tue Sep 29 15:40:08 2020 -0300 + + powerpc: Add optimized strlen for POWER10 + + Improvements compared to POWER9 version: + + 1. Take into account first 16B comparison for aligned strings + + The previous version compares the first 16B and increments r4 by the number + of bytes until the address is 16B-aligned, then starts doing aligned loads at + that address. For aligned strings, this causes the first 16B to be compared + twice, because the increment is 0. Here we calculate the next 16B-aligned + address differently, which avoids that issue. + + 2. Use simple comparisons for the first ~192 bytes + + The main loop is good for big strings, but comparing 16B each time is better + for smaller strings. So after aligning the address to 16 Bytes, we check + more 176B in 16B chunks. There may be some overlaps with the main loop for + unaligned strings, but we avoid using the more aggressive strategy too soon, + and also allow the loop to start at a 64B-aligned address. This greatly + benefits smaller strings and avoids overlapping checks if the string is + already aligned at a 64B boundary. + + 3. Reduce dependencies between load blocks caused by address calculation on loop + + Doing a precise time tracing on the code showed many loads in the loop were + stalled waiting for updates to r4 from previous code blocks. This + implementation avoids that as much as possible by using 2 registers (r4 and + r5) to hold addresses to be used by different parts of the code. + + Also, the previous code aligned the address to 16B, then to 64B by doing a + few 48B loops (if needed) until the address was aligned. The main loop could + not start until that 48B loop had finished and r4 was updated with the + current address. Here we calculate the address used by the loop very early, + so it can start sooner. + + The main loop now uses 2 pointers 128B apart to make pointer updates less + frequent, and also unrolls 1 iteration to guarantee there is enough time + between iterations to update the pointers, reducing stalled cycles. + + 4. Use new P10 instructions + + lxvp is used to load 32B with a single instruction, reducing contention in + the load queue. + + vextractbm allows simplifying the tail code for the loop, replacing + vbpermq and avoiding having to generate a permute control vector. + + Reviewed-by: Paul E Murphy + Reviewed-by: Raphael M Zinsly + Reviewed-by: Lucas A. M. Magalhaes + +diff --git a/sysdeps/powerpc/powerpc64/le/power10/strlen.S b/sysdeps/powerpc/powerpc64/le/power10/strlen.S +new file mode 100644 +index 0000000000000000..ca7e9eb3d84c9b00 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power10/strlen.S +@@ -0,0 +1,221 @@ ++/* Optimized strlen implementation for POWER10 LE. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++#ifndef STRLEN ++# define STRLEN __strlen ++# define DEFINE_STRLEN_HIDDEN_DEF 1 ++#endif ++ ++/* TODO: Replace macros by the actual instructions when minimum binutils becomes ++ >= 2.35. This is used to keep compatibility with older versions. */ ++#define VEXTRACTBM(rt,vrb) \ ++ .long(((4)<<(32-6)) \ ++ | ((rt)<<(32-11)) \ ++ | ((8)<<(32-16)) \ ++ | ((vrb)<<(32-21)) \ ++ | 1602) ++ ++#define LXVP(xtp,dq,ra) \ ++ .long(((6)<<(32-6)) \ ++ | ((((xtp)-32)>>1)<<(32-10)) \ ++ | ((1)<<(32-11)) \ ++ | ((ra)<<(32-16)) \ ++ | dq) ++ ++#define CHECK16(vreg,offset,addr,label) \ ++ lxv vreg+32,offset(addr); \ ++ vcmpequb. vreg,vreg,v18; \ ++ bne cr6,L(label); ++ ++/* Load 4 quadwords, merge into one VR for speed and check for NULLs. r6 has # ++ of bytes already checked. */ ++#define CHECK64(offset,addr,label) \ ++ li r6,offset; \ ++ LXVP(v4+32,offset,addr); \ ++ LXVP(v6+32,offset+32,addr); \ ++ vminub v14,v4,v5; \ ++ vminub v15,v6,v7; \ ++ vminub v16,v14,v15; \ ++ vcmpequb. v0,v16,v18; \ ++ bne cr6,L(label) ++ ++#define TAIL(vreg,increment) \ ++ vctzlsbb r4,vreg; \ ++ subf r3,r3,r5; \ ++ addi r4,r4,increment; \ ++ add r3,r3,r4; \ ++ blr ++ ++/* Implements the function ++ ++ int [r3] strlen (const void *s [r3]) ++ ++ The implementation can load bytes past a matching byte, but only ++ up to the next 64B boundary, so it never crosses a page. */ ++ ++.machine power9 ++ ++ENTRY_TOCLESS (STRLEN, 4) ++ CALL_MCOUNT 1 ++ ++ vspltisb v18,0 ++ vspltisb v19,-1 ++ ++ /* Next 16B-aligned address. Prepare address for L(aligned). */ ++ addi r5,r3,16 ++ clrrdi r5,r5,4 ++ ++ /* Align data and fill bytes not loaded with non matching char. */ ++ lvx v0,0,r3 ++ lvsr v1,0,r3 ++ vperm v0,v19,v0,v1 ++ ++ vcmpequb. v6,v0,v18 ++ beq cr6,L(aligned) ++ ++ vctzlsbb r3,v6 ++ blr ++ ++ /* Test next 176B, 16B at a time. The main loop is optimized for longer ++ strings, so checking the first bytes in 16B chunks benefits a lot ++ small strings. */ ++ .p2align 5 ++L(aligned): ++ /* Prepare address for the loop. */ ++ addi r4,r3,192 ++ clrrdi r4,r4,6 ++ ++ CHECK16(v0,0,r5,tail1) ++ CHECK16(v1,16,r5,tail2) ++ CHECK16(v2,32,r5,tail3) ++ CHECK16(v3,48,r5,tail4) ++ CHECK16(v4,64,r5,tail5) ++ CHECK16(v5,80,r5,tail6) ++ CHECK16(v6,96,r5,tail7) ++ CHECK16(v7,112,r5,tail8) ++ CHECK16(v8,128,r5,tail9) ++ CHECK16(v9,144,r5,tail10) ++ CHECK16(v10,160,r5,tail11) ++ ++ addi r5,r4,128 ++ ++ /* Switch to a more aggressive approach checking 64B each time. Use 2 ++ pointers 128B apart and unroll the loop once to make the pointer ++ updates and usages separated enough to avoid stalls waiting for ++ address calculation. */ ++ .p2align 5 ++L(loop): ++ CHECK64(0,r4,pre_tail_64b) ++ CHECK64(64,r4,pre_tail_64b) ++ addi r4,r4,256 ++ ++ CHECK64(0,r5,tail_64b) ++ CHECK64(64,r5,tail_64b) ++ addi r5,r5,256 ++ ++ b L(loop) ++ ++ .p2align 5 ++L(pre_tail_64b): ++ mr r5,r4 ++L(tail_64b): ++ /* OK, we found a null byte. Let's look for it in the current 64-byte ++ block and mark it in its corresponding VR. lxvp vx,0(ry) puts the ++ low 16B bytes into vx+1, and the high into vx, so the order here is ++ v5, v4, v7, v6. */ ++ vcmpequb v1,v5,v18 ++ vcmpequb v2,v4,v18 ++ vcmpequb v3,v7,v18 ++ vcmpequb v4,v6,v18 ++ ++ /* Take into account the other 64B blocks we had already checked. */ ++ add r5,r5,r6 ++ ++ /* Extract first bit of each byte. */ ++ VEXTRACTBM(r7,v1) ++ VEXTRACTBM(r8,v2) ++ VEXTRACTBM(r9,v3) ++ VEXTRACTBM(r10,v4) ++ ++ /* Shift each value into their corresponding position. */ ++ sldi r8,r8,16 ++ sldi r9,r9,32 ++ sldi r10,r10,48 ++ ++ /* Merge the results. */ ++ or r7,r7,r8 ++ or r8,r9,r10 ++ or r10,r8,r7 ++ ++ cnttzd r0,r10 /* Count trailing zeros before the match. */ ++ subf r5,r3,r5 ++ add r3,r5,r0 /* Compute final length. */ ++ blr ++ ++ .p2align 5 ++L(tail1): ++ TAIL(v0,0) ++ ++ .p2align 5 ++L(tail2): ++ TAIL(v1,16) ++ ++ .p2align 5 ++L(tail3): ++ TAIL(v2,32) ++ ++ .p2align 5 ++L(tail4): ++ TAIL(v3,48) ++ ++ .p2align 5 ++L(tail5): ++ TAIL(v4,64) ++ ++ .p2align 5 ++L(tail6): ++ TAIL(v5,80) ++ ++ .p2align 5 ++L(tail7): ++ TAIL(v6,96) ++ ++ .p2align 5 ++L(tail8): ++ TAIL(v7,112) ++ ++ .p2align 5 ++L(tail9): ++ TAIL(v8,128) ++ ++ .p2align 5 ++L(tail10): ++ TAIL(v9,144) ++ ++ .p2align 5 ++L(tail11): ++ TAIL(v10,160) ++ ++END (STRLEN) ++ ++#ifdef DEFINE_STRLEN_HIDDEN_DEF ++weak_alias (__strlen, strlen) ++libc_hidden_builtin_def (strlen) ++#endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index a9e13e05e90601cd..61652b65dd223018 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -33,7 +33,8 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + + ifneq (,$(filter %le,$(config-machine))) + sysdep_routines += strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 \ +- rawmemchr-power9 strlen-power9 strncpy-power9 stpncpy-power9 ++ rawmemchr-power9 strlen-power9 strncpy-power9 stpncpy-power9 \ ++ strlen-power10 + endif + CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops + CFLAGS-strncase_l-power7.c += -mcpu=power7 -funroll-loops +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index b30bc53930fc0e36..46d5956adda72b86 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -112,6 +112,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/powerpc/powerpc64/multiarch/strlen.c. */ + IFUNC_IMPL (i, name, strlen, + #ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, strlen, hwcap2 & PPC_FEATURE2_ARCH_3_1, ++ __strlen_power10) + IFUNC_IMPL_ADD (array, i, strlen, hwcap2 & PPC_FEATURE2_ARCH_3_00, + __strlen_power9) + #endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strlen-power10.S b/sysdeps/powerpc/powerpc64/multiarch/strlen-power10.S +new file mode 100644 +index 0000000000000000..6a774fad58c77179 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/strlen-power10.S +@@ -0,0 +1,2 @@ ++#define STRLEN __strlen_power10 ++#include +diff --git a/sysdeps/powerpc/powerpc64/multiarch/strlen.c b/sysdeps/powerpc/powerpc64/multiarch/strlen.c +index b7f0fbb13fb97783..11bdb96de2d2aa66 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/strlen.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/strlen.c +@@ -31,9 +31,12 @@ extern __typeof (__redirect_strlen) __strlen_ppc attribute_hidden; + extern __typeof (__redirect_strlen) __strlen_power7 attribute_hidden; + extern __typeof (__redirect_strlen) __strlen_power8 attribute_hidden; + extern __typeof (__redirect_strlen) __strlen_power9 attribute_hidden; ++extern __typeof (__redirect_strlen) __strlen_power10 attribute_hidden; + + libc_ifunc (__libc_strlen, + # ifdef __LITTLE_ENDIAN__ ++ (hwcap2 & PPC_FEATURE2_ARCH_3_1) ++ ? __strlen_power10 : + (hwcap2 & PPC_FEATURE2_ARCH_3_00) + ? __strlen_power9 : + # endif diff --git a/glibc-rh1956357-4.patch b/glibc-rh1956357-4.patch new file mode 100755 index 0000000..ad6aa06 --- /dev/null +++ b/glibc-rh1956357-4.patch @@ -0,0 +1,527 @@ +commit dd59655e9371af86043b97e38953f43bd9496699 +Author: Lucas A. M. Magalhaes +Date: Fri Apr 30 18:12:08 2021 -0300 + + powerpc64le: Optimized memmove for POWER10 + + This patch was initially based on the __memmove_power7 with some ideas + from strncpy implementation for Power 9. + + Improvements from __memmove_power7: + + 1. Use lxvl/stxvl for alignment code. + + The code for Power 7 uses branches when the input is not naturally + aligned to the width of a vector. The new implementation uses + lxvl/stxvl instead which reduces pressure on GPRs. It also allows + the removal of branch instructions, implicitly removing branch stalls + and mispredictions. + + 2. Use of lxv/stxv and lxvl/stxvl pair is safe to use on Cache Inhibited + memory. + + On Power 10 vector load and stores are safe to use on CI memory for + addresses unaligned to 16B. This code takes advantage of this to + do unaligned loads. + + The unaligned loads don't have a significant performance impact by + themselves. However doing so decreases register pressure on GPRs + and interdependence stalls on load/store pairs. This also improved + readability as there are now less code paths for different alignments. + Finally this reduces the overall code size. + + 3. Improved performance. + + This version runs on average about 30% better than memmove_power7 + for lengths larger than 8KB. For input lengths shorter than 8KB + the improvement is smaller, it has on average about 17% better + performance. + + This version has a degradation of about 50% for input lengths + in the 0 to 31 bytes range when dest is unaligned. + + Reviewed-by: Tulio Magno Quites Machado Filho + +diff --git a/sysdeps/powerpc/powerpc64/le/power10/memmove.S b/sysdeps/powerpc/powerpc64/le/power10/memmove.S +new file mode 100644 +index 0000000000000000..7dfd57edeb37e8e4 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power10/memmove.S +@@ -0,0 +1,320 @@ ++/* Optimized memmove implementation for POWER10. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++ ++/* void* [r3] memmove (void *dest [r3], const void *src [r4], size_t len [r5]) ++ ++ This optimization checks if 'src' and 'dst' overlap. If they do not ++ or 'src' is ahead of 'dest' then it copies forward. ++ Otherwise, an optimized backward copy is used. */ ++ ++#ifndef MEMMOVE ++# define MEMMOVE memmove ++#endif ++ .machine power9 ++ENTRY_TOCLESS (MEMMOVE, 5) ++ CALL_MCOUNT 3 ++ ++L(_memmove): ++ .p2align 5 ++ /* Check if there is overlap, if so it will branch to backward copy. */ ++ subf r9,r4,r3 ++ cmpld cr7,r9,r5 ++ blt cr7,L(memmove_bwd) ++ ++ /* Fast path for length shorter than 16 bytes. */ ++ sldi r7,r5,56 ++ lxvl 32+v2,r4,r7 ++ stxvl 32+v2,r3,r7 ++ subic. r8,r5,16 ++ blelr ++ ++ /* For shorter lengths aligning the dest address to 16 bytes either ++ decreases performance or is irrelevant. I'm making use of this ++ comparison to skip the alignment in. */ ++ cmpldi cr6,r5,256 ++ bge cr6,L(ge_256) ++ /* Account for the first 16-byte copy. */ ++ addi r4,r4,16 ++ addi r11,r3,16 /* use r11 to keep dest address on r3. */ ++ subi r5,r5,16 ++ b L(loop_head) ++ ++ .p2align 5 ++L(ge_256): ++ /* Account for the first copy <= 16 bytes. This is necessary for ++ memmove because at this point the src address can be in front of the ++ dest address. */ ++ clrldi r9,r5,56 ++ li r8,16 ++ cmpldi r9,16 ++ iselgt r9,r8,r9 ++ add r4,r4,r9 ++ add r11,r3,r9 /* use r11 to keep dest address on r3. */ ++ sub r5,r5,r9 ++ ++ /* Align dest to 16 bytes. */ ++ neg r7,r3 ++ clrldi. r9,r7,60 ++ beq L(loop_head) ++ ++ .p2align 5 ++ sldi r6,r9,56 ++ lxvl 32+v0,r4,r6 ++ stxvl 32+v0,r11,r6 ++ sub r5,r5,r9 ++ add r4,r4,r9 ++ add r11,r11,r9 ++ ++L(loop_head): ++ cmpldi r5,63 ++ ble L(final_64) ++ ++ srdi. r7,r5,7 ++ beq L(loop_tail) ++ ++ mtctr r7 ++ ++/* Main loop that copies 128 bytes each iteration. */ ++ .p2align 5 ++L(loop): ++ addi r9,r4,64 ++ addi r10,r11,64 ++ ++ lxv 32+v0,0(r4) ++ lxv 32+v1,16(r4) ++ lxv 32+v2,32(r4) ++ lxv 32+v3,48(r4) ++ ++ stxv 32+v0,0(r11) ++ stxv 32+v1,16(r11) ++ stxv 32+v2,32(r11) ++ stxv 32+v3,48(r11) ++ ++ addi r4,r4,128 ++ addi r11,r11,128 ++ ++ lxv 32+v4,0(r9) ++ lxv 32+v5,16(r9) ++ lxv 32+v6,32(r9) ++ lxv 32+v7,48(r9) ++ ++ stxv 32+v4,0(r10) ++ stxv 32+v5,16(r10) ++ stxv 32+v6,32(r10) ++ stxv 32+v7,48(r10) ++ ++ bdnz L(loop) ++ clrldi. r5,r5,57 ++ beqlr ++ ++/* Copy 64 bytes. */ ++ .p2align 5 ++L(loop_tail): ++ cmpldi cr5,r5,63 ++ ble cr5,L(final_64) ++ ++ lxv 32+v0,0(r4) ++ lxv 32+v1,16(r4) ++ lxv 32+v2,32(r4) ++ lxv 32+v3,48(r4) ++ ++ stxv 32+v0,0(r11) ++ stxv 32+v1,16(r11) ++ stxv 32+v2,32(r11) ++ stxv 32+v3,48(r11) ++ ++ addi r4,r4,64 ++ addi r11,r11,64 ++ subi r5,r5,64 ++ ++/* Copies the last 1-63 bytes. */ ++ .p2align 5 ++L(final_64): ++ /* r8 holds the number of bytes that will be copied with lxv/stxv. */ ++ clrrdi. r8,r5,4 ++ beq L(tail1) ++ ++ cmpldi cr5,r5,32 ++ lxv 32+v0,0(r4) ++ blt cr5,L(tail2) ++ ++ cmpldi cr6,r5,48 ++ lxv 32+v1,16(r4) ++ blt cr6,L(tail3) ++ ++ .p2align 5 ++ lxv 32+v2,32(r4) ++ stxv 32+v2,32(r11) ++L(tail3): ++ stxv 32+v1,16(r11) ++L(tail2): ++ stxv 32+v0,0(r11) ++ sub r5,r5,r8 ++ add r4,r4,r8 ++ add r11,r11,r8 ++ .p2align 5 ++L(tail1): ++ sldi r6,r5,56 ++ lxvl v4,r4,r6 ++ stxvl v4,r11,r6 ++ blr ++ ++/* If dest and src overlap, we should copy backwards. */ ++L(memmove_bwd): ++ add r11,r3,r5 ++ add r4,r4,r5 ++ ++ /* Optimization for length smaller than 16 bytes. */ ++ cmpldi cr5,r5,15 ++ ble cr5,L(tail1_bwd) ++ ++ /* For shorter lengths the alignment either slows down or is irrelevant. ++ The forward copy uses a already need 256 comparison for that. Here ++ it's using 128 as it will reduce code and improve readability. */ ++ cmpldi cr7,r5,128 ++ blt cr7,L(bwd_loop_tail) ++ ++ /* Align dest address to 16 bytes. */ ++ .p2align 5 ++ clrldi. r9,r11,60 ++ beq L(bwd_loop_head) ++ sub r4,r4,r9 ++ sub r11,r11,r9 ++ lxv 32+v0,0(r4) ++ sldi r6,r9,56 ++ stxvl 32+v0,r11,r6 ++ sub r5,r5,r9 ++ ++L(bwd_loop_head): ++ srdi. r7,r5,7 ++ beq L(bwd_loop_tail) ++ ++ mtctr r7 ++ ++/* Main loop that copies 128 bytes every iteration. */ ++ .p2align 5 ++L(bwd_loop): ++ addi r9,r4,-64 ++ addi r10,r11,-64 ++ ++ lxv 32+v0,-16(r4) ++ lxv 32+v1,-32(r4) ++ lxv 32+v2,-48(r4) ++ lxv 32+v3,-64(r4) ++ ++ stxv 32+v0,-16(r11) ++ stxv 32+v1,-32(r11) ++ stxv 32+v2,-48(r11) ++ stxv 32+v3,-64(r11) ++ ++ addi r4,r4,-128 ++ addi r11,r11,-128 ++ ++ lxv 32+v0,-16(r9) ++ lxv 32+v1,-32(r9) ++ lxv 32+v2,-48(r9) ++ lxv 32+v3,-64(r9) ++ ++ stxv 32+v0,-16(r10) ++ stxv 32+v1,-32(r10) ++ stxv 32+v2,-48(r10) ++ stxv 32+v3,-64(r10) ++ ++ bdnz L(bwd_loop) ++ clrldi. r5,r5,57 ++ beqlr ++ ++/* Copy 64 bytes. */ ++ .p2align 5 ++L(bwd_loop_tail): ++ cmpldi cr5,r5,63 ++ ble cr5,L(bwd_final_64) ++ ++ addi r4,r4,-64 ++ addi r11,r11,-64 ++ ++ lxv 32+v0,0(r4) ++ lxv 32+v1,16(r4) ++ lxv 32+v2,32(r4) ++ lxv 32+v3,48(r4) ++ ++ stxv 32+v0,0(r11) ++ stxv 32+v1,16(r11) ++ stxv 32+v2,32(r11) ++ stxv 32+v3,48(r11) ++ ++ subi r5,r5,64 ++ ++/* Copies the last 1-63 bytes. */ ++ .p2align 5 ++L(bwd_final_64): ++ /* r8 holds the number of bytes that will be copied with lxv/stxv. */ ++ clrrdi. r8,r5,4 ++ beq L(tail1_bwd) ++ ++ cmpldi cr5,r5,32 ++ lxv 32+v2,-16(r4) ++ blt cr5,L(tail2_bwd) ++ ++ cmpldi cr6,r5,48 ++ lxv 32+v1,-32(r4) ++ blt cr6,L(tail3_bwd) ++ ++ .p2align 5 ++ lxv 32+v0,-48(r4) ++ stxv 32+v0,-48(r11) ++L(tail3_bwd): ++ stxv 32+v1,-32(r11) ++L(tail2_bwd): ++ stxv 32+v2,-16(r11) ++ sub r4,r4,r5 ++ sub r11,r11,r5 ++ sub r5,r5,r8 ++ sldi r6,r5,56 ++ lxvl v4,r4,r6 ++ stxvl v4,r11,r6 ++ blr ++ ++/* Copy last 16 bytes. */ ++ .p2align 5 ++L(tail1_bwd): ++ sub r4,r4,r5 ++ sub r11,r11,r5 ++ sldi r6,r5,56 ++ lxvl v4,r4,r6 ++ stxvl v4,r11,r6 ++ blr ++ ++END_GEN_TB (MEMMOVE,TB_TOCLESS) ++libc_hidden_builtin_def (memmove) ++ ++/* void bcopy(const void *src [r3], void *dest [r4], size_t n [r5]) ++ Implemented in this file to avoid linker create a stub function call ++ in the branch to '_memmove'. */ ++ENTRY_TOCLESS (__bcopy) ++ mr r6,r3 ++ mr r3,r4 ++ mr r4,r6 ++ b L(_memmove) ++END (__bcopy) ++#ifndef __bcopy ++weak_alias (__bcopy, bcopy) ++#endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index 61652b65dd223018..66f8c6ace9824d4a 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -32,7 +32,8 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + strncase-power8 + + ifneq (,$(filter %le,$(config-machine))) +-sysdep_routines += strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 \ ++sysdep_routines += memmove-power10 \ ++ strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 \ + rawmemchr-power9 strlen-power9 strncpy-power9 stpncpy-power9 \ + strlen-power10 + endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/bcopy.c b/sysdeps/powerpc/powerpc64/multiarch/bcopy.c +index 1c4a229b1fc5654a..705fef33d4e57557 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/bcopy.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/bcopy.c +@@ -22,8 +22,17 @@ + extern __typeof (bcopy) __bcopy_ppc attribute_hidden; + /* __bcopy_power7 symbol is implemented at memmove-power7.S */ + extern __typeof (bcopy) __bcopy_power7 attribute_hidden; ++#ifdef __LITTLE_ENDIAN__ ++extern __typeof (bcopy) __bcopy_power10 attribute_hidden; ++#endif + + libc_ifunc (bcopy, ++#ifdef __LITTLE_ENDIAN__ ++ hwcap2 & (PPC_FEATURE2_ARCH_3_1 | ++ PPC_FEATURE2_HAS_ISEL) ++ && (hwcap & PPC_FEATURE_HAS_VSX) ++ ? __bcopy_power10 : ++#endif + (hwcap & PPC_FEATURE_HAS_VSX) + ? __bcopy_power7 + : __bcopy_ppc); +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 46d5956adda72b86..4ce04bc51574cca1 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -67,6 +67,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/powerpc/powerpc64/multiarch/memmove.c. */ + IFUNC_IMPL (i, name, memmove, ++#ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, memmove, ++ hwcap2 & (PPC_FEATURE2_ARCH_3_1 | ++ PPC_FEATURE2_HAS_ISEL) ++ && (hwcap & PPC_FEATURE_HAS_VSX), ++ __memmove_power10) ++#endif + IFUNC_IMPL_ADD (array, i, memmove, hwcap & PPC_FEATURE_HAS_VSX, + __memmove_power7) + IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_ppc)) +@@ -186,6 +193,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/powerpc/powerpc64/multiarch/bcopy.c. */ + IFUNC_IMPL (i, name, bcopy, ++#ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, bcopy, ++ hwcap2 & (PPC_FEATURE2_ARCH_3_1 | ++ PPC_FEATURE2_HAS_ISEL) ++ && (hwcap & PPC_FEATURE_HAS_VSX), ++ __bcopy_power10) ++#endif + IFUNC_IMPL_ADD (array, i, bcopy, hwcap & PPC_FEATURE_HAS_VSX, + __bcopy_power7) + IFUNC_IMPL_ADD (array, i, bcopy, 1, __bcopy_ppc)) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/memmove-power10.S b/sysdeps/powerpc/powerpc64/multiarch/memmove-power10.S +new file mode 100644 +index 0000000000000000..171b32921a0a4d47 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/memmove-power10.S +@@ -0,0 +1,27 @@ ++/* Optimized memmove implementation for POWER10. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define MEMMOVE __memmove_power10 ++ ++#undef libc_hidden_builtin_def ++#define libc_hidden_builtin_def(name) ++ ++#undef __bcopy ++#define __bcopy __bcopy_power10 ++ ++#include +diff --git a/sysdeps/powerpc/powerpc64/multiarch/memmove-power7.S b/sysdeps/powerpc/powerpc64/multiarch/memmove-power7.S +index 0b251d0f5f087874..fb5261ecda64d061 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/memmove-power7.S ++++ b/sysdeps/powerpc/powerpc64/multiarch/memmove-power7.S +@@ -21,7 +21,7 @@ + #undef libc_hidden_builtin_def + #define libc_hidden_builtin_def(name) + +-#undef bcopy +-#define bcopy __bcopy_power7 ++#undef __bcopy ++#define __bcopy __bcopy_power7 + + #include +diff --git a/sysdeps/powerpc/powerpc64/multiarch/memmove.c b/sysdeps/powerpc/powerpc64/multiarch/memmove.c +index 39987155cc7d3624..2fd7b6d309e4bedd 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/memmove.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/memmove.c +@@ -28,14 +28,22 @@ + # include "init-arch.h" + + extern __typeof (__redirect_memmove) __libc_memmove; +- + extern __typeof (__redirect_memmove) __memmove_ppc attribute_hidden; + extern __typeof (__redirect_memmove) __memmove_power7 attribute_hidden; ++#ifdef __LITTLE_ENDIAN__ ++extern __typeof (__redirect_memmove) __memmove_power10 attribute_hidden; ++#endif + + libc_ifunc (__libc_memmove, +- (hwcap & PPC_FEATURE_HAS_VSX) +- ? __memmove_power7 +- : __memmove_ppc); ++#ifdef __LITTLE_ENDIAN__ ++ hwcap2 & (PPC_FEATURE2_ARCH_3_1 | ++ PPC_FEATURE2_HAS_ISEL) ++ && (hwcap & PPC_FEATURE_HAS_VSX) ++ ? __memmove_power10 : ++#endif ++ (hwcap & PPC_FEATURE_HAS_VSX) ++ ? __memmove_power7 ++ : __memmove_ppc); + + #undef memmove + strong_alias (__libc_memmove, memmove); +diff --git a/sysdeps/powerpc/powerpc64/power7/memmove.S b/sysdeps/powerpc/powerpc64/power7/memmove.S +index b7f3dc28d1a8eac3..9e4cabb07ef9b732 100644 +--- a/sysdeps/powerpc/powerpc64/power7/memmove.S ++++ b/sysdeps/powerpc/powerpc64/power7/memmove.S +@@ -832,4 +832,6 @@ ENTRY_TOCLESS (__bcopy) + mr r4,r6 + b L(_memmove) + END (__bcopy) ++#ifndef __bcopy + weak_alias (__bcopy, bcopy) ++#endif diff --git a/glibc-rh1956357-5.patch b/glibc-rh1956357-5.patch new file mode 100755 index 0000000..11f1597 --- /dev/null +++ b/glibc-rh1956357-5.patch @@ -0,0 +1,308 @@ +commit e941e0ae80626b7661c1db8953a673cafd3b8b19 +Author: Tulio Magno Quites Machado Filho +Date: Fri Apr 30 18:12:08 2021 -0300 + + powerpc64le: Optimize memcpy for POWER10 + + This implementation is based on __memcpy_power8_cached and integrates + suggestions from Anton Blanchard. + It benefits from loads and stores with length for short lengths and for + tail code, simplifying the code. + + All unaligned memory accesses use instructions that do not generate + alignment interrupts on POWER10, making it safe to use on + caching-inhibited memory. + + The main loop has also been modified in order to increase instruction + throughput by reducing the dependency on updates from previous iterations. + + On average, this implementation provides around 30% improvement when + compared to __memcpy_power7 and 10% improvement in comparison to + __memcpy_power8_cached. + +diff --git a/sysdeps/powerpc/powerpc64/le/power10/memcpy.S b/sysdeps/powerpc/powerpc64/le/power10/memcpy.S +new file mode 100644 +index 0000000000000000..ad1414db4a3a8b9f +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power10/memcpy.S +@@ -0,0 +1,198 @@ ++/* Optimized memcpy implementation for POWER10. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++ ++#ifndef MEMCPY ++# define MEMCPY memcpy ++#endif ++ ++/* __ptr_t [r3] memcpy (__ptr_t dst [r3], __ptr_t src [r4], size_t len [r5]); ++ Returns 'dst'. */ ++ ++ .machine power9 ++ENTRY_TOCLESS (MEMCPY, 5) ++ CALL_MCOUNT 3 ++ ++ /* Copy up to 16 bytes. */ ++ sldi r6,r5,56 /* Prepare [l|st]xvl counter. */ ++ lxvl v10,r4,r6 ++ stxvl v10,r3,r6 ++ subic. r6,r5,16 /* Return if len <= 16. */ ++ blelr ++ ++ /* If len >= 256, assume nothing got copied before and copy ++ again. This might cause issues with overlapped memory, but memcpy ++ is not expected to treat overlapped memory. */ ++ cmpdi r5,256 ++ bge L(copy_ge_256) ++ /* 16 < len < 256 and the first 16 bytes have already been copied. */ ++ addi r10,r3,16 /* Keep r3 intact as return value. */ ++ addi r4,r4,16 ++ subi r5,r5,16 ++ b L(copy_lt_256) /* Avoid the main loop if len < 256. */ ++ ++ .p2align 5 ++L(copy_ge_256): ++ mr r10,r3 /* Keep r3 intact as return value. */ ++ /* Align dst to 16 bytes. */ ++ andi. r9,r10,0xf ++ beq L(dst_is_align_16) ++ lxv v10,0(r4) ++ subfic r12,r9,16 ++ subf r5,r12,r5 ++ add r4,r4,r12 ++ stxv v10,0(r3) ++ add r10,r3,r12 ++ ++L(dst_is_align_16): ++ srdi r9,r5,7 /* Divide by 128. */ ++ mtctr r9 ++ addi r6,r4,64 ++ addi r7,r10,64 ++ ++ ++ /* Main loop, copy 128 bytes per iteration. ++ Use r6=src+64 and r7=dest+64 in order to reduce the dependency on ++ r4 and r10. */ ++ .p2align 5 ++L(copy_128): ++ ++ lxv v10, 0(r4) ++ lxv v11, 16(r4) ++ lxv v12, 32(r4) ++ lxv v13, 48(r4) ++ ++ addi r4,r4,128 ++ ++ stxv v10, 0(r10) ++ stxv v11, 16(r10) ++ stxv v12, 32(r10) ++ stxv v13, 48(r10) ++ ++ addi r10,r10,128 ++ ++ lxv v10, 0(r6) ++ lxv v11, 16(r6) ++ lxv v12, 32(r6) ++ lxv v13, 48(r6) ++ ++ addi r6,r6,128 ++ ++ stxv v10, 0(r7) ++ stxv v11, 16(r7) ++ stxv v12, 32(r7) ++ stxv v13, 48(r7) ++ ++ addi r7,r7,128 ++ ++ bdnz L(copy_128) ++ ++ clrldi. r5,r5,64-7 /* Have we copied everything? */ ++ beqlr ++ ++ .p2align 5 ++L(copy_lt_256): ++ cmpdi r5,16 ++ ble L(copy_le_16) ++ srdi. r9,r5,5 /* Divide by 32. */ ++ beq L(copy_lt_32) ++ mtctr r9 ++ /* Use r6=src+32, r7=dest+32, r8=src+64, r9=dest+64 in order to reduce ++ the dependency on r4 and r10. */ ++ addi r6,r4,32 ++ addi r7,r10,32 ++ addi r8,r4,64 ++ addi r9,r10,64 ++ ++ .p2align 5 ++ /* Copy 32 bytes at a time, unaligned. ++ The loop is unrolled 3 times in order to reduce the dependency on ++ r4 and r10, copying up-to 96 bytes per iteration. */ ++L(copy_32): ++ lxv v10, 0(r4) ++ lxv v11, 16(r4) ++ stxv v10, 0(r10) ++ stxv v11, 16(r10) ++ bdz L(end_copy_32a) ++ addi r4,r4,96 ++ addi r10,r10,96 ++ ++ lxv v10, 0(r6) ++ lxv v11, 16(r6) ++ addi r6,r6,96 ++ stxv v10, 0(r7) ++ stxv v11, 16(r7) ++ bdz L(end_copy_32b) ++ addi r7,r7,96 ++ ++ lxv v12, 0(r8) ++ lxv v13, 16(r8) ++ addi r8,r8,96 ++ stxv v12, 0(r9) ++ stxv v13, 16(r9) ++ addi r9,r9,96 ++ bdnz L(copy_32) ++ ++ clrldi. r5,r5,64-5 /* Have we copied everything? */ ++ beqlr ++ cmpdi r5,16 ++ ble L(copy_le_16) ++ b L(copy_lt_32) ++ ++ .p2align 5 ++L(end_copy_32a): ++ clrldi. r5,r5,64-5 /* Have we copied everything? */ ++ beqlr ++ /* 32 bytes have been copied since the last update of r4 and r10. */ ++ addi r4,r4,32 ++ addi r10,r10,32 ++ cmpdi r5,16 ++ ble L(copy_le_16) ++ b L(copy_lt_32) ++ ++ .p2align 5 ++L(end_copy_32b): ++ clrldi. r5,r5,64-5 /* Have we copied everything? */ ++ beqlr ++ /* The last iteration of the loop copied 64 bytes. Update r4 and r10 ++ accordingly. */ ++ addi r4,r4,-32 ++ addi r10,r10,-32 ++ cmpdi r5,16 ++ ble L(copy_le_16) ++ ++ .p2align 5 ++L(copy_lt_32): ++ lxv v10, 0(r4) ++ stxv v10, 0(r10) ++ addi r4,r4,16 ++ addi r10,r10,16 ++ subi r5,r5,16 ++ ++ .p2align 5 ++L(copy_le_16): ++ sldi r6,r5,56 ++ lxvl v10,r4,r6 ++ stxvl v10,r10,r6 ++ blr ++ ++ ++END_GEN_TB (MEMCPY,TB_TOCLESS) ++libc_hidden_builtin_def (memcpy) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index 66f8c6ace9824d4a..2e3c8f2e8a81cda4 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -32,7 +32,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + strncase-power8 + + ifneq (,$(filter %le,$(config-machine))) +-sysdep_routines += memmove-power10 \ ++sysdep_routines += memcpy-power10 memmove-power10 \ + strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 \ + rawmemchr-power9 strlen-power9 strncpy-power9 stpncpy-power9 \ + strlen-power10 +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 4ce04bc51574cca1..9d5a14e480c02171 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -51,6 +51,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + #ifdef SHARED + /* Support sysdeps/powerpc/powerpc64/multiarch/memcpy.c. */ + IFUNC_IMPL (i, name, memcpy, ++#ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, memcpy, ++ hwcap2 & PPC_FEATURE2_ARCH_3_1 ++ && hwcap & PPC_FEATURE_HAS_VSX, ++ __memcpy_power10) ++#endif + IFUNC_IMPL_ADD (array, i, memcpy, hwcap2 & PPC_FEATURE2_ARCH_2_07, + __memcpy_power8_cached) + IFUNC_IMPL_ADD (array, i, memcpy, hwcap & PPC_FEATURE_HAS_VSX, +diff --git a/sysdeps/powerpc/powerpc64/multiarch/memcpy-power10.S b/sysdeps/powerpc/powerpc64/multiarch/memcpy-power10.S +new file mode 100644 +index 0000000000000000..70e0fc3ed610cdc3 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/memcpy-power10.S +@@ -0,0 +1,26 @@ ++/* Optimized memcpy implementation for POWER10. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#if defined __LITTLE_ENDIAN__ && IS_IN (libc) ++#define MEMCPY __memcpy_power10 ++ ++#undef libc_hidden_builtin_def ++#define libc_hidden_builtin_def(name) ++ ++#include ++#endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/memcpy.c b/sysdeps/powerpc/powerpc64/multiarch/memcpy.c +index 44dea594f3770673..be0e47f32dde2ccf 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/memcpy.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/memcpy.c +@@ -36,8 +36,15 @@ extern __typeof (__redirect_memcpy) __memcpy_power6 attribute_hidden; + extern __typeof (__redirect_memcpy) __memcpy_a2 attribute_hidden; + extern __typeof (__redirect_memcpy) __memcpy_power7 attribute_hidden; + extern __typeof (__redirect_memcpy) __memcpy_power8_cached attribute_hidden; ++# if defined __LITTLE_ENDIAN__ ++extern __typeof (__redirect_memcpy) __memcpy_power10 attribute_hidden; ++# endif + + libc_ifunc (__libc_memcpy, ++# if defined __LITTLE_ENDIAN__ ++ (hwcap2 & PPC_FEATURE2_ARCH_3_1 && hwcap & PPC_FEATURE_HAS_VSX) ++ ? __memcpy_power10 : ++# endif + ((hwcap2 & PPC_FEATURE2_ARCH_2_07) && use_cached_memopt) + ? __memcpy_power8_cached : + (hwcap & PPC_FEATURE_HAS_VSX) diff --git a/glibc-rh1956357-6.patch b/glibc-rh1956357-6.patch new file mode 100755 index 0000000..cc92e31 --- /dev/null +++ b/glibc-rh1956357-6.patch @@ -0,0 +1,420 @@ +commit 23fdf8178cce3c2ec320dd5eca8b544245bcaef0 +Author: Raoni Fassina Firmino +Date: Fri Apr 30 18:12:08 2021 -0300 + + powerpc64le: Optimize memset for POWER10 + + This implementation is based on __memset_power8 and integrates a lot + of suggestions from Anton Blanchard. + + The biggest difference is that it makes extensive use of stxvl to + alignment and tail code to avoid branches and small stores. It has + three main execution paths: + + a) "Short lengths" for lengths up to 64 bytes, avoiding as many + branches as possible. + + b) "General case" for larger lengths, it has an alignment section + using stxvl to avoid branches, a 128 bytes loop and then a tail + code, again using stxvl with few branches. + + c) "Zeroing cache blocks" for lengths from 256 bytes upwards and set + value being zero. It is mostly the __memset_power8 code but the + alignment phase was simplified because, at this point, address is + already 16-bytes aligned and also changed to use vector stores. + The tail code was also simplified to reuse the general case tail. + + All unaligned stores use stxvl instructions that do not generate + alignment interrupts on POWER10, making it safe to use on + caching-inhibited memory. + + On average, this implementation provides something around 30% + improvement when compared to __memset_power8. + + Reviewed-by: Matheus Castanho + Reviewed-by: Tulio Magno Quites Machado Filho + +diff --git a/sysdeps/powerpc/powerpc64/le/power10/memset.S b/sysdeps/powerpc/powerpc64/le/power10/memset.S +new file mode 100644 +index 0000000000000000..6b8e2cfdaf25fd30 +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power10/memset.S +@@ -0,0 +1,256 @@ ++/* Optimized memset implementation for POWER10 LE. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++/* void * [r3] memset (void *s [r3], int c [r4], size_t n [r5])); ++ Returns 's'. */ ++ ++#ifndef MEMSET ++# define MEMSET memset ++#endif ++ ++ .machine power9 ++ENTRY_TOCLESS (MEMSET, 5) ++ CALL_MCOUNT 3 ++ ++L(_memset): ++ /* Assume memset of zero length is uncommon, and just let it go ++ through the small path below. */ ++ cmpldi r5,64 ++ ++ /* Replicate byte to quad word. */ ++ mtvsrd v0+32,r4 ++ vspltb v0,v0,7 ++ ++ li r7,16 ++ sldi r8,r7,56 ++ ++ bgt L(large) ++ ++ /* For short lengths we want to avoid as many branches as possible. ++ We use store VSX vector with length instructions to do this. ++ It takes advantage of the fact that if the length passed to stxvl ++ is zero nothing is done, effectively a no-op. */ ++ sldi r5,r5,56 ++ ++ addi r10,r3,16 ++ ++ sub. r11,r5,r8 ++ isellt r11,0,r11 /* Saturate the subtraction to zero. */ ++ ++ stxvl v0+32,r3,r5 ++ stxvl v0+32,r10,r11 ++ ++ addi r9,r3,32 ++ addi r10,r3,48 ++ ++ sub. r11,r11,r8 ++ isellt r11,0,r11 ++ ++ sub. r5,r11,r8 ++ isellt r5,0,r5 ++ ++ stxvl v0+32,r9,r11 ++ stxvl v0+32,r10,r5 ++ ++ blr ++ ++ .balign 16 ++L(large): ++ mr r6,r3 /* Don't modify r3 since we need to return it. */ ++ ++ /* Get dest 16B aligned. */ ++ neg r0,r3 ++ clrldi. r7,r0,(64-4) ++ beq L(aligned) ++ rldic r9,r0,56,4 /* (~X & 0xf)<<56 "clrlsldi r9,r0,64-4,56". */ ++ ++ stxvl v0+32,r6,r9 /* Store up to 15B until aligned address. */ ++ ++ add r6,r6,r7 ++ sub r5,r5,r7 ++ ++ /* Go to tail if there is less than 64B left after alignment. */ ++ cmpldi r5,64 ++ blt L(tail_64) ++ ++ .balign 16 ++L(aligned): ++ /* Go to tail if there is less than 128B left after alignment. */ ++ srdi. r0,r5,7 ++ beq L(tail_128) ++ ++ /* If c == 0 && n >= 256 use dcbz to zero out full cache blocks. */ ++ cmpldi cr5,r5,255 ++ cmpldi cr6,r4,0 ++ crand 27,26,21 ++ bt 27,L(dcbz) ++ ++ mtctr r0 ++ ++ .balign 32 ++L(loop): ++ stxv v0+32,0(r6) ++ stxv v0+32,16(r6) ++ stxv v0+32,32(r6) ++ stxv v0+32,48(r6) ++ stxv v0+32,64(r6) ++ stxv v0+32,80(r6) ++ stxv v0+32,96(r6) ++ stxv v0+32,112(r6) ++ addi r6,r6,128 ++ bdnz L(loop) ++ ++ .balign 16 ++L(tail): ++ /* 127B or less left, finish the tail or return. */ ++ andi. r5,r5,127 ++ beqlr ++ ++ cmpldi r5,64 ++ blt L(tail_64) ++ ++ .balign 16 ++L(tail_128): ++ /* Stores a minimum of 64B and up to 128B and return. */ ++ stxv v0+32,0(r6) ++ stxv v0+32,16(r6) ++ stxv v0+32,32(r6) ++ stxv v0+32,48(r6) ++ addi r6,r6,64 ++ andi. r5,r5,63 ++ beqlr ++ ++ .balign 16 ++L(tail_64): ++ /* Stores up to 64B and return. */ ++ sldi r5,r5,56 ++ ++ addi r10,r6,16 ++ ++ sub. r11,r5,r8 ++ isellt r11,0,r11 ++ ++ stxvl v0+32,r6,r5 ++ stxvl v0+32,r10,r11 ++ ++ sub. r11,r11,r8 ++ blelr ++ ++ addi r9,r6,32 ++ addi r10,r6,48 ++ ++ isellt r11,0,r11 ++ ++ sub. r5,r11,r8 ++ isellt r5,0,r5 ++ ++ stxvl v0+32,r9,r11 ++ stxvl v0+32,r10,r5 ++ ++ blr ++ ++ .balign 16 ++L(dcbz): ++ /* Special case when value is 0 and we have a long length to deal ++ with. Use dcbz to zero out a full cacheline of 128 bytes at a time. ++ Before using dcbz though, we need to get the destination 128-byte ++ aligned. */ ++ neg r0,r6 ++ clrldi. r0,r0,(64-7) ++ beq L(dcbz_aligned) ++ ++ sub r5,r5,r0 ++ mtocrf 0x2,r0 /* copying bits 57..59 to cr6. The ones for sizes 64, ++ 32 and 16 which need to be checked. */ ++ ++ /* Write 16-128 bytes until DST is aligned to 128 bytes. */ ++64: bf 25,32f ++ stxv v0+32,0(r6) ++ stxv v0+32,16(r6) ++ stxv v0+32,32(r6) ++ stxv v0+32,48(r6) ++ addi r6,r6,64 ++ ++32: bf 26,16f ++ stxv v0+32,0(r6) ++ stxv v0+32,16(r6) ++ addi r6,r6,32 ++ ++16: bf 27,L(dcbz_aligned) ++ stxv v0+32,0(r6) ++ addi r6,r6,16 ++ ++ .balign 16 ++L(dcbz_aligned): ++ /* Setup dcbz unroll offsets and count numbers. */ ++ srdi. r0,r5,9 ++ li r9,128 ++ beq L(bcdz_tail) ++ li r10,256 ++ li r11,384 ++ mtctr r0 ++ ++ .balign 16 ++L(dcbz_loop): ++ /* Sets 512 bytes to zero in each iteration, the loop unrolling shows ++ a throughput boost for large sizes (2048 bytes or higher). */ ++ dcbz 0,r6 ++ dcbz r9,r6 ++ dcbz r10,r6 ++ dcbz r11,r6 ++ addi r6,r6,512 ++ bdnz L(dcbz_loop) ++ ++ andi. r5,r5,511 ++ beqlr ++ ++ .balign 16 ++L(bcdz_tail): ++ /* We have 1-511 bytes remaining. */ ++ srdi. r0,r5,7 ++ beq L(tail) ++ ++ mtocrf 0x1,r0 ++ ++256: bf 30,128f ++ dcbz 0,r6 ++ dcbz r9,r6 ++ addi r6,r6,256 ++ ++128: bf 31,L(tail) ++ dcbz 0,r6 ++ addi r6,r6,128 ++ ++ b L(tail) ++ ++END_GEN_TB (MEMSET,TB_TOCLESS) ++libc_hidden_builtin_def (memset) ++ ++/* Copied from bzero.S to prevent the linker from inserting a stub ++ between bzero and memset. */ ++ENTRY_TOCLESS (__bzero) ++ CALL_MCOUNT 2 ++ mr r5,r4 ++ li r4,0 ++ b L(_memset) ++END (__bzero) ++#ifndef __bzero ++weak_alias (__bzero, bzero) ++#endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index 2e3c8f2e8a81cda4..1d517698429e1230 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -32,7 +32,7 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + strncase-power8 + + ifneq (,$(filter %le,$(config-machine))) +-sysdep_routines += memcpy-power10 memmove-power10 \ ++sysdep_routines += memcpy-power10 memmove-power10 memset-power10 \ + strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 \ + rawmemchr-power9 strlen-power9 strncpy-power9 stpncpy-power9 \ + strlen-power10 +diff --git a/sysdeps/powerpc/powerpc64/multiarch/bzero.c b/sysdeps/powerpc/powerpc64/multiarch/bzero.c +index f8cb05bea8a3505b..4ce98e324d12a31e 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/bzero.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/bzero.c +@@ -27,8 +27,16 @@ extern __typeof (bzero) __bzero_power4 attribute_hidden; + extern __typeof (bzero) __bzero_power6 attribute_hidden; + extern __typeof (bzero) __bzero_power7 attribute_hidden; + extern __typeof (bzero) __bzero_power8 attribute_hidden; ++# ifdef __LITTLE_ENDIAN__ ++extern __typeof (bzero) __bzero_power10 attribute_hidden; ++# endif + + libc_ifunc (__bzero, ++# ifdef __LITTLE_ENDIAN__ ++ (hwcap2 & (PPC_FEATURE2_ARCH_3_1 | PPC_FEATURE2_HAS_ISEL) ++ && hwcap & PPC_FEATURE_HAS_VSX) ++ ? __bzero_power10 : ++# endif + (hwcap2 & PPC_FEATURE2_ARCH_2_07) + ? __bzero_power8 : + (hwcap & PPC_FEATURE_HAS_VSX) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 9d5a14e480c02171..11532f77d4d03b2a 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -86,6 +86,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/powerpc/powerpc64/multiarch/memset.c. */ + IFUNC_IMPL (i, name, memset, ++#ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, memset, ++ hwcap2 & (PPC_FEATURE2_ARCH_3_1 | ++ PPC_FEATURE2_HAS_ISEL) ++ && hwcap & PPC_FEATURE_HAS_VSX, ++ __memset_power10) ++#endif + IFUNC_IMPL_ADD (array, i, memset, hwcap2 & PPC_FEATURE2_ARCH_2_07, + __memset_power8) + IFUNC_IMPL_ADD (array, i, memset, hwcap & PPC_FEATURE_HAS_VSX, +@@ -187,6 +194,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + + /* Support sysdeps/powerpc/powerpc64/multiarch/bzero.c. */ + IFUNC_IMPL (i, name, bzero, ++#ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, bzero, ++ hwcap2 & (PPC_FEATURE2_ARCH_3_1 | ++ PPC_FEATURE2_HAS_ISEL) ++ && hwcap & PPC_FEATURE_HAS_VSX, ++ __bzero_power10) ++#endif + IFUNC_IMPL_ADD (array, i, bzero, hwcap2 & PPC_FEATURE2_ARCH_2_07, + __bzero_power8) + IFUNC_IMPL_ADD (array, i, bzero, hwcap & PPC_FEATURE_HAS_VSX, +diff --git a/sysdeps/powerpc/powerpc64/multiarch/memset-power10.S b/sysdeps/powerpc/powerpc64/multiarch/memset-power10.S +new file mode 100644 +index 0000000000000000..548e99789735296c +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/memset-power10.S +@@ -0,0 +1,27 @@ ++/* Optimized memset implementation for POWER10 LE. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define MEMSET __memset_power10 ++ ++#undef libc_hidden_builtin_def ++#define libc_hidden_builtin_def(name) ++ ++#undef __bzero ++#define __bzero __bzero_power10 ++ ++#include +diff --git a/sysdeps/powerpc/powerpc64/multiarch/memset.c b/sysdeps/powerpc/powerpc64/multiarch/memset.c +index 1a7c46fecf78ab1f..4c97622c7d7eb8aa 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/memset.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/memset.c +@@ -33,10 +33,18 @@ extern __typeof (__redirect_memset) __memset_power4 attribute_hidden; + extern __typeof (__redirect_memset) __memset_power6 attribute_hidden; + extern __typeof (__redirect_memset) __memset_power7 attribute_hidden; + extern __typeof (__redirect_memset) __memset_power8 attribute_hidden; ++# ifdef __LITTLE_ENDIAN__ ++extern __typeof (__redirect_memset) __memset_power10 attribute_hidden; ++# endif + + /* Avoid DWARF definition DIE on ifunc symbol so that GDB can handle + ifunc symbol properly. */ + libc_ifunc (__libc_memset, ++# ifdef __LITTLE_ENDIAN__ ++ (hwcap2 & (PPC_FEATURE2_ARCH_3_1 | PPC_FEATURE2_HAS_ISEL) ++ && hwcap & PPC_FEATURE_HAS_VSX) ++ ? __memset_power10 : ++# endif + (hwcap2 & PPC_FEATURE2_ARCH_2_07) + ? __memset_power8 : + (hwcap & PPC_FEATURE_HAS_VSX) diff --git a/glibc-rh1956357-7.patch b/glibc-rh1956357-7.patch new file mode 100755 index 0000000..dca81f2 --- /dev/null +++ b/glibc-rh1956357-7.patch @@ -0,0 +1,131 @@ +commit 17a73a6d8b4c46f3e87fc53c7c25fa7cec01d707 +Author: Raoni Fassina Firmino +Date: Mon May 3 16:59:35 2021 -0300 + + powerpc64le: Fix ifunc selection for memset, memmove, bzero and bcopy + + The hwcap2 check for the aforementioned functions should check for + both PPC_FEATURE2_ARCH_3_1 and PPC_FEATURE2_HAS_ISEL but was + mistakenly checking for any one of them, enabling isa 3.1 version of + the functions in incompatible processors, like POWER8. + + Reviewed-by: Tulio Magno Quites Machado Filho + +diff --git a/sysdeps/powerpc/powerpc64/multiarch/bcopy.c b/sysdeps/powerpc/powerpc64/multiarch/bcopy.c +index 705fef33d4e57557..3c6528e5dbccfdbd 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/bcopy.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/bcopy.c +@@ -28,10 +28,10 @@ extern __typeof (bcopy) __bcopy_power10 attribute_hidden; + + libc_ifunc (bcopy, + #ifdef __LITTLE_ENDIAN__ +- hwcap2 & (PPC_FEATURE2_ARCH_3_1 | +- PPC_FEATURE2_HAS_ISEL) +- && (hwcap & PPC_FEATURE_HAS_VSX) +- ? __bcopy_power10 : ++ (hwcap2 & PPC_FEATURE2_ARCH_3_1 ++ && hwcap2 & PPC_FEATURE2_HAS_ISEL ++ && hwcap & PPC_FEATURE_HAS_VSX) ++ ? __bcopy_power10 : + #endif + (hwcap & PPC_FEATURE_HAS_VSX) + ? __bcopy_power7 +diff --git a/sysdeps/powerpc/powerpc64/multiarch/bzero.c b/sysdeps/powerpc/powerpc64/multiarch/bzero.c +index 4ce98e324d12a31e..b08b381b4a3999f1 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/bzero.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/bzero.c +@@ -33,7 +33,8 @@ extern __typeof (bzero) __bzero_power10 attribute_hidden; + + libc_ifunc (__bzero, + # ifdef __LITTLE_ENDIAN__ +- (hwcap2 & (PPC_FEATURE2_ARCH_3_1 | PPC_FEATURE2_HAS_ISEL) ++ (hwcap2 & PPC_FEATURE2_ARCH_3_1 ++ && hwcap2 & PPC_FEATURE2_HAS_ISEL + && hwcap & PPC_FEATURE_HAS_VSX) + ? __bzero_power10 : + # endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 11532f77d4d03b2a..6e36659d1903448a 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -75,9 +75,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_IMPL (i, name, memmove, + #ifdef __LITTLE_ENDIAN__ + IFUNC_IMPL_ADD (array, i, memmove, +- hwcap2 & (PPC_FEATURE2_ARCH_3_1 | +- PPC_FEATURE2_HAS_ISEL) +- && (hwcap & PPC_FEATURE_HAS_VSX), ++ hwcap2 & PPC_FEATURE2_ARCH_3_1 ++ && hwcap2 & PPC_FEATURE2_HAS_ISEL ++ && hwcap & PPC_FEATURE_HAS_VSX, + __memmove_power10) + #endif + IFUNC_IMPL_ADD (array, i, memmove, hwcap & PPC_FEATURE_HAS_VSX, +@@ -88,8 +88,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_IMPL (i, name, memset, + #ifdef __LITTLE_ENDIAN__ + IFUNC_IMPL_ADD (array, i, memset, +- hwcap2 & (PPC_FEATURE2_ARCH_3_1 | +- PPC_FEATURE2_HAS_ISEL) ++ hwcap2 & PPC_FEATURE2_ARCH_3_1 ++ && hwcap2 & PPC_FEATURE2_HAS_ISEL + && hwcap & PPC_FEATURE_HAS_VSX, + __memset_power10) + #endif +@@ -196,8 +196,8 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_IMPL (i, name, bzero, + #ifdef __LITTLE_ENDIAN__ + IFUNC_IMPL_ADD (array, i, bzero, +- hwcap2 & (PPC_FEATURE2_ARCH_3_1 | +- PPC_FEATURE2_HAS_ISEL) ++ hwcap2 & PPC_FEATURE2_ARCH_3_1 ++ && hwcap2 & PPC_FEATURE2_HAS_ISEL + && hwcap & PPC_FEATURE_HAS_VSX, + __bzero_power10) + #endif +@@ -215,9 +215,9 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + IFUNC_IMPL (i, name, bcopy, + #ifdef __LITTLE_ENDIAN__ + IFUNC_IMPL_ADD (array, i, bcopy, +- hwcap2 & (PPC_FEATURE2_ARCH_3_1 | +- PPC_FEATURE2_HAS_ISEL) +- && (hwcap & PPC_FEATURE_HAS_VSX), ++ hwcap2 & PPC_FEATURE2_ARCH_3_1 ++ && hwcap2 & PPC_FEATURE2_HAS_ISEL ++ && hwcap & PPC_FEATURE_HAS_VSX, + __bcopy_power10) + #endif + IFUNC_IMPL_ADD (array, i, bcopy, hwcap & PPC_FEATURE_HAS_VSX, +diff --git a/sysdeps/powerpc/powerpc64/multiarch/memmove.c b/sysdeps/powerpc/powerpc64/multiarch/memmove.c +index 2fd7b6d309e4bedd..27895faad0cab40e 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/memmove.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/memmove.c +@@ -36,10 +36,10 @@ extern __typeof (__redirect_memmove) __memmove_power10 attribute_hidden; + + libc_ifunc (__libc_memmove, + #ifdef __LITTLE_ENDIAN__ +- hwcap2 & (PPC_FEATURE2_ARCH_3_1 | +- PPC_FEATURE2_HAS_ISEL) +- && (hwcap & PPC_FEATURE_HAS_VSX) +- ? __memmove_power10 : ++ (hwcap2 & PPC_FEATURE2_ARCH_3_1 ++ && hwcap2 & PPC_FEATURE2_HAS_ISEL ++ && hwcap & PPC_FEATURE_HAS_VSX) ++ ? __memmove_power10 : + #endif + (hwcap & PPC_FEATURE_HAS_VSX) + ? __memmove_power7 +diff --git a/sysdeps/powerpc/powerpc64/multiarch/memset.c b/sysdeps/powerpc/powerpc64/multiarch/memset.c +index 4c97622c7d7eb8aa..685623ae870a0725 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/memset.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/memset.c +@@ -41,7 +41,8 @@ extern __typeof (__redirect_memset) __memset_power10 attribute_hidden; + ifunc symbol properly. */ + libc_ifunc (__libc_memset, + # ifdef __LITTLE_ENDIAN__ +- (hwcap2 & (PPC_FEATURE2_ARCH_3_1 | PPC_FEATURE2_HAS_ISEL) ++ (hwcap2 & PPC_FEATURE2_ARCH_3_1 ++ && hwcap2 & PPC_FEATURE2_HAS_ISEL + && hwcap & PPC_FEATURE_HAS_VSX) + ? __memset_power10 : + # endif diff --git a/glibc-rh1956357-8.patch b/glibc-rh1956357-8.patch new file mode 100755 index 0000000..beee664 --- /dev/null +++ b/glibc-rh1956357-8.patch @@ -0,0 +1,387 @@ +commit 1a594aa986ffe28657a03baa5c53c0a0e7dc2ecd +Author: Matheus Castanho +Date: Tue May 11 17:53:07 2021 -0300 + + powerpc: Add optimized rawmemchr for POWER10 + + Reuse code for optimized strlen to implement a faster version of rawmemchr. + This takes advantage of the same benefits provided by the strlen implementation, + but needs some extra steps. __strlen_power10 code should be unchanged after this + change. + + rawmemchr returns a pointer to the char found, while strlen returns only the + length, so we have to take that into account when preparing the return value. + + To quickly check 64B, the loop on __strlen_power10 merges the whole block into + 16B by using unsigned minimum vector operations (vminub) and checks if there are + any \0 on the resulting vector. The same code is used by rawmemchr if the char c + is 0. However, this approach does not work when c != 0. We first need to + subtract each byte by c, so that the value we are looking for is converted to a + 0, then taking the minimum and checking for nulls works again. + + The new code branches after it has compared ~256 bytes and chooses which of the + two strategies above will be used in the main loop, based on the char c. This + extra branch adds some overhead (~5%) for length ~256, but is quickly amortized + by the faster loop for larger sizes. + + Compared to __rawmemchr_power9, this version is ~20% faster for length < 256. + Because of the optimized main loop, the improvement becomes ~35% for c != 0 + and ~50% for c = 0 for strings longer than 256. + + Reviewed-by: Lucas A. M. Magalhaes + Reviewed-by: Raphael M Zinsly + +diff --git a/sysdeps/powerpc/powerpc64/le/power10/rawmemchr.S b/sysdeps/powerpc/powerpc64/le/power10/rawmemchr.S +new file mode 100644 +index 0000000000000000..5351c2634f6086bf +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/le/power10/rawmemchr.S +@@ -0,0 +1,22 @@ ++/* Optimized rawmemchr implementation for POWER10 LE. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++#define USE_AS_RAWMEMCHR 1 ++#include +diff --git a/sysdeps/powerpc/powerpc64/le/power10/strlen.S b/sysdeps/powerpc/powerpc64/le/power10/strlen.S +index ca7e9eb3d84c9b00..dda5282f1b9a07cf 100644 +--- a/sysdeps/powerpc/powerpc64/le/power10/strlen.S ++++ b/sysdeps/powerpc/powerpc64/le/power10/strlen.S +@@ -18,10 +18,50 @@ + + #include + +-#ifndef STRLEN +-# define STRLEN __strlen +-# define DEFINE_STRLEN_HIDDEN_DEF 1 +-#endif ++/* To reuse the code for rawmemchr, we have some extra steps compared to the ++ strlen implementation: ++ - Sum the initial value of r3 with the position at which the char was ++ found, to guarantee we return a pointer and not the length. ++ - In the main loop, subtract each byte by the char we are looking for, ++ so we can keep using vminub to quickly check 64B at once. */ ++#ifdef USE_AS_RAWMEMCHR ++# ifndef RAWMEMCHR ++# define FUNCNAME __rawmemchr ++# else ++# define FUNCNAME RAWMEMCHR ++# endif ++# define MCOUNT_NARGS 2 ++# define VREG_ZERO v20 ++# define OFF_START_LOOP 256 ++# define RAWMEMCHR_SUBTRACT_VECTORS \ ++ vsububm v4,v4,v18; \ ++ vsububm v5,v5,v18; \ ++ vsububm v6,v6,v18; \ ++ vsububm v7,v7,v18; ++# define TAIL(vreg,increment) \ ++ vctzlsbb r4,vreg; \ ++ addi r4,r4,increment; \ ++ add r3,r5,r4; \ ++ blr ++ ++#else /* strlen */ ++ ++# ifndef STRLEN ++# define FUNCNAME __strlen ++# define DEFINE_STRLEN_HIDDEN_DEF 1 ++# else ++# define FUNCNAME STRLEN ++# endif ++# define MCOUNT_NARGS 1 ++# define VREG_ZERO v18 ++# define OFF_START_LOOP 192 ++# define TAIL(vreg,increment) \ ++ vctzlsbb r4,vreg; \ ++ subf r3,r3,r5; \ ++ addi r4,r4,increment; \ ++ add r3,r3,r4; \ ++ blr ++#endif /* USE_AS_RAWMEMCHR */ + + /* TODO: Replace macros by the actual instructions when minimum binutils becomes + >= 2.35. This is used to keep compatibility with older versions. */ +@@ -50,33 +90,41 @@ + li r6,offset; \ + LXVP(v4+32,offset,addr); \ + LXVP(v6+32,offset+32,addr); \ ++ RAWMEMCHR_SUBTRACT_VECTORS; \ + vminub v14,v4,v5; \ + vminub v15,v6,v7; \ + vminub v16,v14,v15; \ +- vcmpequb. v0,v16,v18; \ ++ vcmpequb. v0,v16,VREG_ZERO; \ + bne cr6,L(label) + +-#define TAIL(vreg,increment) \ +- vctzlsbb r4,vreg; \ +- subf r3,r3,r5; \ +- addi r4,r4,increment; \ +- add r3,r3,r4; \ +- blr +- + /* Implements the function + + int [r3] strlen (const void *s [r3]) + ++ but when USE_AS_RAWMEMCHR is set, implements the function ++ ++ void* [r3] rawmemchr (const void *s [r3], int c [r4]) ++ + The implementation can load bytes past a matching byte, but only + up to the next 64B boundary, so it never crosses a page. */ + + .machine power9 + +-ENTRY_TOCLESS (STRLEN, 4) +- CALL_MCOUNT 1 ++ENTRY_TOCLESS (FUNCNAME, 4) ++ CALL_MCOUNT MCOUNT_NARGS + +- vspltisb v18,0 ++#ifdef USE_AS_RAWMEMCHR ++ xori r5,r4,0xff ++ ++ mtvsrd v18+32,r4 /* matching char in v18 */ ++ mtvsrd v19+32,r5 /* non matching char in v19 */ ++ ++ vspltb v18,v18,7 /* replicate */ ++ vspltb v19,v19,7 /* replicate */ ++#else + vspltisb v19,-1 ++#endif ++ vspltisb VREG_ZERO,0 + + /* Next 16B-aligned address. Prepare address for L(aligned). */ + addi r5,r3,16 +@@ -90,16 +138,25 @@ ENTRY_TOCLESS (STRLEN, 4) + vcmpequb. v6,v0,v18 + beq cr6,L(aligned) + ++#ifdef USE_AS_RAWMEMCHR ++ vctzlsbb r6,v6 ++ add r3,r3,r6 ++#else + vctzlsbb r3,v6 ++#endif + blr + +- /* Test next 176B, 16B at a time. The main loop is optimized for longer +- strings, so checking the first bytes in 16B chunks benefits a lot +- small strings. */ ++ /* Test up to OFF_START_LOOP-16 bytes in 16B chunks. The main loop is ++ optimized for longer strings, so checking the first bytes in 16B ++ chunks benefits a lot small strings. */ + .p2align 5 + L(aligned): ++#ifdef USE_AS_RAWMEMCHR ++ cmpdi cr5,r4,0 /* Check if c == 0. This will be useful to ++ choose how we will perform the main loop. */ ++#endif + /* Prepare address for the loop. */ +- addi r4,r3,192 ++ addi r4,r3,OFF_START_LOOP + clrrdi r4,r4,6 + + CHECK16(v0,0,r5,tail1) +@@ -113,15 +170,43 @@ L(aligned): + CHECK16(v8,128,r5,tail9) + CHECK16(v9,144,r5,tail10) + CHECK16(v10,160,r5,tail11) ++#ifdef USE_AS_RAWMEMCHR ++ CHECK16(v0,176,r5,tail12) ++ CHECK16(v1,192,r5,tail13) ++ CHECK16(v2,208,r5,tail14) ++ CHECK16(v3,224,r5,tail15) ++#endif + + addi r5,r4,128 + ++#ifdef USE_AS_RAWMEMCHR ++ /* If c == 0, use the same loop as strlen, without the vsububm. */ ++ beq cr5,L(loop) ++ ++ /* This is very similar to the block after L(loop), the difference is ++ that here RAWMEMCHR_SUBTRACT_VECTORS is not empty, and we subtract ++ each byte loaded by the char we are looking for, this way we can keep ++ using vminub to merge the results and checking for nulls. */ ++ .p2align 5 ++L(rawmemchr_loop): ++ CHECK64(0,r4,pre_tail_64b) ++ CHECK64(64,r4,pre_tail_64b) ++ addi r4,r4,256 ++ ++ CHECK64(0,r5,tail_64b) ++ CHECK64(64,r5,tail_64b) ++ addi r5,r5,256 ++ ++ b L(rawmemchr_loop) ++#endif + /* Switch to a more aggressive approach checking 64B each time. Use 2 + pointers 128B apart and unroll the loop once to make the pointer + updates and usages separated enough to avoid stalls waiting for + address calculation. */ + .p2align 5 + L(loop): ++#undef RAWMEMCHR_SUBTRACT_VECTORS ++#define RAWMEMCHR_SUBTRACT_VECTORS /* nothing */ + CHECK64(0,r4,pre_tail_64b) + CHECK64(64,r4,pre_tail_64b) + addi r4,r4,256 +@@ -140,10 +225,10 @@ L(tail_64b): + block and mark it in its corresponding VR. lxvp vx,0(ry) puts the + low 16B bytes into vx+1, and the high into vx, so the order here is + v5, v4, v7, v6. */ +- vcmpequb v1,v5,v18 +- vcmpequb v2,v4,v18 +- vcmpequb v3,v7,v18 +- vcmpequb v4,v6,v18 ++ vcmpequb v1,v5,VREG_ZERO ++ vcmpequb v2,v4,VREG_ZERO ++ vcmpequb v3,v7,VREG_ZERO ++ vcmpequb v4,v6,VREG_ZERO + + /* Take into account the other 64B blocks we had already checked. */ + add r5,r5,r6 +@@ -165,7 +250,9 @@ L(tail_64b): + or r10,r8,r7 + + cnttzd r0,r10 /* Count trailing zeros before the match. */ ++#ifndef USE_AS_RAWMEMCHR + subf r5,r3,r5 ++#endif + add r3,r5,r0 /* Compute final length. */ + blr + +@@ -213,9 +300,32 @@ L(tail10): + L(tail11): + TAIL(v10,160) + +-END (STRLEN) ++#ifdef USE_AS_RAWMEMCHR ++ .p2align 5 ++L(tail12): ++ TAIL(v0,176) ++ ++ .p2align 5 ++L(tail13): ++ TAIL(v1,192) ++ ++ .p2align 5 ++L(tail14): ++ TAIL(v2,208) ++ ++ .p2align 5 ++L(tail15): ++ TAIL(v3,224) ++#endif ++ ++END (FUNCNAME) + +-#ifdef DEFINE_STRLEN_HIDDEN_DEF ++#ifdef USE_AS_RAWMEMCHR ++weak_alias (__rawmemchr,rawmemchr) ++libc_hidden_builtin_def (__rawmemchr) ++#else ++# ifdef DEFINE_STRLEN_HIDDEN_DEF + weak_alias (__strlen, strlen) + libc_hidden_builtin_def (strlen) ++# endif + #endif +diff --git a/sysdeps/powerpc/powerpc64/multiarch/Makefile b/sysdeps/powerpc/powerpc64/multiarch/Makefile +index 1d517698429e1230..ac2446aca62cc4ab 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/Makefile ++++ b/sysdeps/powerpc/powerpc64/multiarch/Makefile +@@ -33,9 +33,9 @@ sysdep_routines += memcpy-power8-cached memcpy-power7 memcpy-a2 memcpy-power6 \ + + ifneq (,$(filter %le,$(config-machine))) + sysdep_routines += memcpy-power10 memmove-power10 memset-power10 \ ++ rawmemchr-power9 rawmemchr-power10 \ + strcmp-power9 strncmp-power9 strcpy-power9 stpcpy-power9 \ +- rawmemchr-power9 strlen-power9 strncpy-power9 stpncpy-power9 \ +- strlen-power10 ++ strlen-power9 strncpy-power9 stpncpy-power9 strlen-power10 + endif + CFLAGS-strncase-power7.c += -mcpu=power7 -funroll-loops + CFLAGS-strncase_l-power7.c += -mcpu=power7 -funroll-loops +diff --git a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +index 6e36659d1903448a..127af84b32a8196f 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/ifunc-impl-list.c +@@ -257,6 +257,10 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, + /* Support sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c. */ + IFUNC_IMPL (i, name, rawmemchr, + #ifdef __LITTLE_ENDIAN__ ++ IFUNC_IMPL_ADD (array, i, rawmemchr, ++ (hwcap2 & PPC_FEATURE2_ARCH_3_1) ++ && (hwcap & PPC_FEATURE_HAS_VSX), ++ __rawmemchr_power10) + IFUNC_IMPL_ADD (array, i, rawmemchr, + hwcap2 & PPC_FEATURE2_ARCH_3_00, + __rawmemchr_power9) +diff --git a/sysdeps/powerpc/powerpc64/multiarch/rawmemchr-power10.S b/sysdeps/powerpc/powerpc64/multiarch/rawmemchr-power10.S +new file mode 100644 +index 0000000000000000..bf1ed7e1941f922d +--- /dev/null ++++ b/sysdeps/powerpc/powerpc64/multiarch/rawmemchr-power10.S +@@ -0,0 +1,21 @@ ++/* Optimized rawmemchr implementation for PowerPC64/POWER10. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define RAWMEMCHR __rawmemchr_power10 ++ ++#include +diff --git a/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c b/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c +index 2a7ae5a1ed02e556..369d6359e8987052 100644 +--- a/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c ++++ b/sysdeps/powerpc/powerpc64/multiarch/rawmemchr.c +@@ -26,6 +26,7 @@ extern __typeof (__rawmemchr) __rawmemchr_ppc attribute_hidden; + extern __typeof (__rawmemchr) __rawmemchr_power7 attribute_hidden; + # ifdef __LITTLE_ENDIAN__ + extern __typeof (__rawmemchr) __rawmemchr_power9 attribute_hidden; ++extern __typeof (__rawmemchr) __rawmemchr_power10 attribute_hidden; + # endif + + # undef __rawmemchr +@@ -34,6 +35,9 @@ extern __typeof (__rawmemchr) __rawmemchr_power9 attribute_hidden; + ifunc symbol properly. */ + libc_ifunc_redirected (__redirect___rawmemchr, __rawmemchr, + # ifdef __LITTLE_ENDIAN__ ++ (hwcap2 & PPC_FEATURE2_ARCH_3_1) ++ && (hwcap & PPC_FEATURE_HAS_VSX) ++ ? __rawmemchr_power10 : + (hwcap2 & PPC_FEATURE2_ARCH_3_00) + ? __rawmemchr_power9 : + # endif diff --git a/glibc-rh1966472-1.patch b/glibc-rh1966472-1.patch new file mode 100755 index 0000000..ecccfeb --- /dev/null +++ b/glibc-rh1966472-1.patch @@ -0,0 +1,159 @@ +nptl: Add __pthread_attr_copy for copying pthread_attr_t objects + +Also add the private type union pthread_attr_transparent, to reduce +the amount of casting that is required. + +Reviewed-by: Carlos O'Donell +Tested-by: Carlos O'Donell +(cherry picked from commit 331c6e8a184167dd21a9f0b3fc165aeefea6eeca) + +Difference from upstream: +Unlike upstream, __pthread_attr_copy is in libpthread.so. + +# Conflicts: +# nptl/Makefile +# nptl/Versions + +diff --git a/nptl/Makefile b/nptl/Makefile +index d6b37b6efd3b7d78..b14de3ffb330c10b 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -54,7 +54,8 @@ libpthread-routines = nptl-init nptlfreeres vars events version pt-interp \ + pthread_getconcurrency pthread_setconcurrency \ + pthread_getschedparam pthread_setschedparam \ + pthread_setschedprio \ +- pthread_attr_init pthread_attr_destroy \ ++ pthread_attr_init pthread_attr_copy \ ++ pthread_attr_destroy \ + pthread_attr_getdetachstate pthread_attr_setdetachstate \ + pthread_attr_getguardsize pthread_attr_setguardsize \ + pthread_attr_getschedparam pthread_attr_setschedparam \ +diff --git a/nptl/Versions b/nptl/Versions +index 6007fd03e7ed117c..e38272aa187fbe78 100644 +--- a/nptl/Versions ++++ b/nptl/Versions +@@ -283,5 +283,6 @@ libpthread { + __pthread_barrier_init; __pthread_barrier_wait; + __shm_directory; + __libpthread_freeres; ++ __pthread_attr_copy; + } + } +diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h +index 00be8f92793e8710..a2d48b2015cd385c 100644 +--- a/nptl/pthreadP.h ++++ b/nptl/pthreadP.h +@@ -464,6 +464,9 @@ extern int __pthread_attr_getstack (const pthread_attr_t *__restrict __attr, + size_t *__restrict __stacksize); + extern int __pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize); ++extern int __pthread_attr_setaffinity_np (pthread_attr_t *attr, ++ size_t cpusetsize, ++ const cpu_set_t *cpuset); + extern int __pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, + const pthread_rwlockattr_t *__restrict + __attr); +@@ -605,6 +608,11 @@ extern void __wait_lookup_done (void) attribute_hidden; + # define PTHREAD_STATIC_FN_REQUIRE(name) __asm (".globl " #name); + #endif + ++/* Make a deep copy of the attribute *SOURCE in *TARGET. *TARGET is ++ not assumed to have been initialized. Returns 0 on success, or a ++ positive error code otherwise. */ ++int __pthread_attr_copy (pthread_attr_t *target, const pthread_attr_t *source); ++ + /* Returns 0 if POL is a valid scheduling policy. */ + static inline int + check_sched_policy_attr (int pol) +diff --git a/nptl/pthread_attr_copy.c b/nptl/pthread_attr_copy.c +new file mode 100644 +index 0000000000000000..67f272acf297100c +--- /dev/null ++++ b/nptl/pthread_attr_copy.c +@@ -0,0 +1,56 @@ ++/* Deep copy of a pthread_attr_t object. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++int ++__pthread_attr_copy (pthread_attr_t *target, const pthread_attr_t *source) ++{ ++ /* Avoid overwriting *TARGET until all allocations have ++ succeeded. */ ++ union pthread_attr_transparent temp; ++ temp.external = *source; ++ ++ /* Force new allocation. This function has full ownership of temp. */ ++ temp.internal.cpuset = NULL; ++ temp.internal.cpusetsize = 0; ++ ++ int ret = 0; ++ ++ struct pthread_attr *isource = (struct pthread_attr *) source; ++ ++ /* Propagate affinity mask information. */ ++ if (isource->cpusetsize > 0) ++ ret = __pthread_attr_setaffinity_np (&temp.external, ++ isource->cpusetsize, ++ isource->cpuset); ++ ++ if (ret != 0) ++ { ++ /* Deallocate because we have ownership. */ ++ __pthread_attr_destroy (&temp.external); ++ return ret; ++ } ++ ++ /* Transfer ownership. *target is not assumed to have been ++ initialized. */ ++ *target = temp.external; ++ return 0; ++} +diff --git a/nptl/pthread_attr_setaffinity.c b/nptl/pthread_attr_setaffinity.c +index 545b72c91e290216..914ebf6f9cbfd5ff 100644 +--- a/nptl/pthread_attr_setaffinity.c ++++ b/nptl/pthread_attr_setaffinity.c +@@ -55,6 +55,7 @@ __pthread_attr_setaffinity_new (pthread_attr_t *attr, size_t cpusetsize, + + return 0; + } ++strong_alias (__pthread_attr_setaffinity_new, __pthread_attr_setaffinity_np) + versioned_symbol (libpthread, __pthread_attr_setaffinity_new, + pthread_attr_setaffinity_np, GLIBC_2_3_4); + +diff --git a/sysdeps/nptl/internaltypes.h b/sysdeps/nptl/internaltypes.h +index b78ad99a888b4e3b..d3dce1278de989e2 100644 +--- a/sysdeps/nptl/internaltypes.h ++++ b/sysdeps/nptl/internaltypes.h +@@ -49,6 +49,13 @@ struct pthread_attr + #define ATTR_FLAG_SCHED_SET 0x0020 + #define ATTR_FLAG_POLICY_SET 0x0040 + ++/* Used to allocate a pthread_attr_t object which is also accessed ++ internally. */ ++union pthread_attr_transparent ++{ ++ pthread_attr_t external; ++ struct pthread_attr internal; ++}; + + /* Mutex attribute data structure. */ + struct pthread_mutexattr diff --git a/glibc-rh1966472-2.patch b/glibc-rh1966472-2.patch new file mode 100755 index 0000000..014f62a --- /dev/null +++ b/glibc-rh1966472-2.patch @@ -0,0 +1,50 @@ +Use __pthread_attr_copy in mq_notify (bug 27896) + +Make a deep copy of the pthread attribute object to remove a potential +use-after-free issue. + +(cherry picked from commit 42d359350510506b87101cf77202fefcbfc790cb) + +# Conflicts: +# NEWS + +diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c +index 3563e82cd4f4b552..c4091169306ffde8 100644 +--- a/sysdeps/unix/sysv/linux/mq_notify.c ++++ b/sysdeps/unix/sysv/linux/mq_notify.c +@@ -135,8 +135,11 @@ helper_thread (void *arg) + (void) __pthread_barrier_wait (¬ify_barrier); + } + else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) +- /* The only state we keep is the copy of the thread attributes. */ +- free (data.attr); ++ { ++ /* The only state we keep is the copy of the thread attributes. */ ++ pthread_attr_destroy (data.attr); ++ free (data.attr); ++ } + } + return NULL; + } +@@ -257,8 +260,7 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification) + if (data.attr == NULL) + return -1; + +- memcpy (data.attr, notification->sigev_notify_attributes, +- sizeof (pthread_attr_t)); ++ __pthread_attr_copy (data.attr, notification->sigev_notify_attributes); + } + + /* Construct the new request. */ +@@ -272,7 +274,10 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification) + + /* If it failed, free the allocated memory. */ + if (__glibc_unlikely (retval != 0)) +- free (data.attr); ++ { ++ pthread_attr_destroy (data.attr); ++ free (data.attr); ++ } + + return retval; + } diff --git a/glibc-rh1966472-3.patch b/glibc-rh1966472-3.patch new file mode 100755 index 0000000..23d704f --- /dev/null +++ b/glibc-rh1966472-3.patch @@ -0,0 +1,44 @@ +Fix use of __pthread_attr_copy in mq_notify (bug 27896) + +__pthread_attr_copy can fail and does not initialize the attribute +structure in that case. + +If __pthread_attr_copy is never called and there is no allocated +attribute, pthread_attr_destroy should not be called, otherwise +there is a null pointer dereference in rt/tst-mqueue6. + +Fixes commit 42d359350510506b87101cf77202fefcbfc790cb +("Use __pthread_attr_copy in mq_notify (bug 27896)"). + +Reviewed-by: Siddhesh Poyarekar +(cherry picked from commit 217b6dc298156bdb0d6aea9ea93e7e394a5ff091) + +diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c +index c4091169306ffde8..45449571d14c379f 100644 +--- a/sysdeps/unix/sysv/linux/mq_notify.c ++++ b/sysdeps/unix/sysv/linux/mq_notify.c +@@ -260,7 +260,14 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification) + if (data.attr == NULL) + return -1; + +- __pthread_attr_copy (data.attr, notification->sigev_notify_attributes); ++ int ret = __pthread_attr_copy (data.attr, ++ notification->sigev_notify_attributes); ++ if (ret != 0) ++ { ++ free (data.attr); ++ __set_errno (ret); ++ return -1; ++ } + } + + /* Construct the new request. */ +@@ -273,7 +280,7 @@ mq_notify (mqd_t mqdes, const struct sigevent *notification) + int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se); + + /* If it failed, free the allocated memory. */ +- if (__glibc_unlikely (retval != 0)) ++ if (retval != 0 && data.attr != NULL) + { + pthread_attr_destroy (data.attr); + free (data.attr); diff --git a/glibc-rh1966472-4.patch b/glibc-rh1966472-4.patch new file mode 100755 index 0000000..47a01ff --- /dev/null +++ b/glibc-rh1966472-4.patch @@ -0,0 +1,34 @@ +commit b805aebd42364fe696e417808a700fdb9800c9e8 +Author: Nikita Popov +Date: Mon Aug 9 20:17:34 2021 +0530 + + librt: fix NULL pointer dereference (bug 28213) + + Helper thread frees copied attribute on NOTIFY_REMOVED message + received from the OS kernel. Unfortunately, it fails to check whether + copied attribute actually exists (data.attr != NULL). This worked + earlier because free() checks passed pointer before actually + attempting to release corresponding memory. But + __pthread_attr_destroy assumes pointer is not NULL. + + So passing NULL pointer to __pthread_attr_destroy will result in + segmentation fault. This scenario is possible if + notification->sigev_notify_attributes == NULL (which means default + thread attributes should be used). + + Signed-off-by: Nikita Popov + Reviewed-by: Siddhesh Poyarekar + +diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c +index 45449571d14c379f..581959d621135fb0 100644 +--- a/sysdeps/unix/sysv/linux/mq_notify.c ++++ b/sysdeps/unix/sysv/linux/mq_notify.c +@@ -134,7 +134,7 @@ helper_thread (void *arg) + to wait until it is done with it. */ + (void) __pthread_barrier_wait (¬ify_barrier); + } +- else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) ++ else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED && data.attr != NULL) + { + /* The only state we keep is the copy of the thread attributes. */ + pthread_attr_destroy (data.attr); diff --git a/glibc-rh1979127.patch b/glibc-rh1979127.patch new file mode 100755 index 0000000..4a21d5a --- /dev/null +++ b/glibc-rh1979127.patch @@ -0,0 +1,33 @@ +commit 5adda61f62b77384718b4c0d8336ade8f2b4b35c +Author: Andreas Schwab +Date: Fri Jun 25 15:02:47 2021 +0200 + + wordexp: handle overflow in positional parameter number (bug 28011) + + Use strtoul instead of atoi so that overflow can be detected. + +diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c +index cc29840355e047cc..30c1dd65efcc0b49 100644 +--- a/posix/wordexp-test.c ++++ b/posix/wordexp-test.c +@@ -200,6 +200,7 @@ struct test_case_struct + { 0, NULL, "$var", 0, 0, { NULL, }, IFS }, + { 0, NULL, "\"\\n\"", 0, 1, { "\\n", }, IFS }, + { 0, NULL, "", 0, 0, { NULL, }, IFS }, ++ { 0, NULL, "${1234567890123456789012}", 0, 0, { NULL, }, IFS }, + + /* Flags not already covered (testit() has special handling for these) */ + { 0, NULL, "one two", WRDE_DOOFFS, 2, { "one", "two", }, IFS }, +diff --git a/posix/wordexp.c b/posix/wordexp.c +index 048a8068544c81fa..4061969c720f1f34 100644 +--- a/posix/wordexp.c ++++ b/posix/wordexp.c +@@ -1420,7 +1420,7 @@ envsubst: + /* Is it a numeric parameter? */ + else if (isdigit (env[0])) + { +- int n = atoi (env); ++ unsigned long n = strtoul (env, NULL, 10); + + if (n >= __libc_argc) + /* Substitute NULL. */ diff --git a/glibc-rh2032280-1.patch b/glibc-rh2032280-1.patch new file mode 100755 index 0000000..6308350 --- /dev/null +++ b/glibc-rh2032280-1.patch @@ -0,0 +1,64 @@ +commit a7e9dbb7742954814643a8562dcad09abb0b0e5d +Author: Alexandra Hájková +Date: Sat Dec 26 18:45:13 2020 +0100 + + Add xchdir to libsupport. + +diff --git a/support/Makefile b/support/Makefile +index dcf3c4baa2a31070..fb95a69ed9158e78 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -82,6 +82,7 @@ libsupport-routines = \ + xasprintf \ + xbind \ + xcalloc \ ++ xchdir \ + xchroot \ + xclose \ + xconnect \ +diff --git a/support/xchdir.c b/support/xchdir.c +new file mode 100644 +index 0000000000000000..beb4feff72832065 +--- /dev/null ++++ b/support/xchdir.c +@@ -0,0 +1,28 @@ ++/* chdir with error checking. ++ Copyright (C) 2020 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 ++ . */ ++ ++#include ++#include ++#include ++ ++void ++xchdir (const char *path) ++{ ++ if (chdir (path) != 0) ++ FAIL_EXIT1 ("chdir (\"%s\"): %m", path); ++} +diff --git a/support/xunistd.h b/support/xunistd.h +index f99f362cb4763c5b..74fd2771d12c36fe 100644 +--- a/support/xunistd.h ++++ b/support/xunistd.h +@@ -44,6 +44,7 @@ long xsysconf (int name); + long long xlseek (int fd, long long offset, int whence); + void xftruncate (int fd, long long length); + void xsymlink (const char *target, const char *linkpath); ++void xchdir (const char *path); + + /* Equivalent of "mkdir -p". */ + void xmkdirp (const char *, mode_t); diff --git a/glibc-rh2032280-2.patch b/glibc-rh2032280-2.patch new file mode 100755 index 0000000..56edb3d --- /dev/null +++ b/glibc-rh2032280-2.patch @@ -0,0 +1,72 @@ +commit 60854f40ea2d420867ed2f0f052ee7fca661dbff +Author: Adhemerval Zanella +Date: Thu Oct 15 15:14:22 2020 -0300 + + support: Add create_temp_file_in_dir + + It allows created a temporary file in a specified directory. + +diff --git a/support/support.h b/support/support.h +index f50f8cc1496d657d..96833bd4e992e6d3 100644 +--- a/support/support.h ++++ b/support/support.h +@@ -23,6 +23,7 @@ + #ifndef SUPPORT_H + #define SUPPORT_H + ++#include + #include + #include + /* For mode_t. */ +diff --git a/support/temp_file.c b/support/temp_file.c +index 0bbc7f997264f758..5a2728c94a9c32ae 100644 +--- a/support/temp_file.c ++++ b/support/temp_file.c +@@ -60,14 +60,12 @@ add_temp_file (const char *name) + } + + int +-create_temp_file (const char *base, char **filename) ++create_temp_file_in_dir (const char *base, const char *dir, char **filename) + { + char *fname; + int fd; + +- fname = (char *) xmalloc (strlen (test_dir) + 1 + strlen (base) +- + sizeof ("XXXXXX")); +- strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX"); ++ fname = xasprintf ("%s/%sXXXXXX", dir, base); + + fd = mkstemp (fname); + if (fd == -1) +@@ -86,6 +84,12 @@ create_temp_file (const char *base, char **filename) + return fd; + } + ++int ++create_temp_file (const char *base, char **filename) ++{ ++ return create_temp_file_in_dir (base, test_dir, filename); ++} ++ + char * + support_create_temp_directory (const char *base) + { +diff --git a/support/temp_file.h b/support/temp_file.h +index c7795cc577ca22a9..d64563f41f1f50cd 100644 +--- a/support/temp_file.h ++++ b/support/temp_file.h +@@ -32,6 +32,13 @@ void add_temp_file (const char *name); + *FILENAME. */ + int create_temp_file (const char *base, char **filename); + ++/* Create a temporary file in directory DIR. Return the opened file ++ descriptor on success, or -1 on failure. Write the file name to ++ *FILENAME if FILENAME is not NULL. In this case, the caller is ++ expected to free *FILENAME. */ ++int create_temp_file_in_dir (const char *base, const char *dir, ++ char **filename); ++ + /* Create a temporary directory and schedule it for deletion. BASE is + used as a prefix for the unique directory name, which the function + returns. The caller should free this string. */ diff --git a/glibc-rh2032280-3.patch b/glibc-rh2032280-3.patch new file mode 100755 index 0000000..7cb306d --- /dev/null +++ b/glibc-rh2032280-3.patch @@ -0,0 +1,278 @@ +commit fb7bff12e81c677a6622f724edd4d4987dd9d971 +Author: Siddhesh Poyarekar +Date: Tue Jan 18 13:29:36 2022 +0530 + + support: Add helpers to create paths longer than PATH_MAX + + Add new helpers support_create_and_chdir_toolong_temp_directory and + support_chdir_toolong_temp_directory to create and descend into + directory trees longer than PATH_MAX. + + Reviewed-by: Adhemerval Zanella + Signed-off-by: Siddhesh Poyarekar + +# Conflicts: +# support/temp_file.c + +diff --git a/support/temp_file.c b/support/temp_file.c +index 5a2728c94a9c32ae..661c86bad5c0121f 100644 +--- a/support/temp_file.c ++++ b/support/temp_file.c +@@ -1,5 +1,6 @@ + /* Temporary file handling for tests. +- Copyright (C) 1998-2018 Free Software Foundation, Inc. ++ Copyright (C) 1998-2022 Free Software Foundation, Inc. ++ Copyright The GNU Tools Authors. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -20,15 +21,17 @@ + some 32-bit platforms. */ + #define _FILE_OFFSET_BITS 64 + ++#include + #include + #include + #include + ++#include + #include + #include + #include + #include +-#include ++#include + + /* List of temporary files. */ + static struct temp_name_list +@@ -36,14 +39,20 @@ static struct temp_name_list + struct temp_name_list *next; + char *name; + pid_t owner; ++ bool toolong; + } *temp_name_list; + + /* Location of the temporary files. Set by the test skeleton via + support_set_test_dir. The string is not be freed. */ + static const char *test_dir = _PATH_TMP; + +-void +-add_temp_file (const char *name) ++/* Name of subdirectories in a too long temporary directory tree. */ ++static char toolong_subdir[NAME_MAX + 1]; ++static bool toolong_initialized; ++static size_t toolong_path_max; ++ ++static void ++add_temp_file_internal (const char *name, bool toolong) + { + struct temp_name_list *newp + = (struct temp_name_list *) xcalloc (sizeof (*newp), 1); +@@ -53,12 +62,19 @@ add_temp_file (const char *name) + newp->name = newname; + newp->next = temp_name_list; + newp->owner = getpid (); ++ newp->toolong = toolong; + temp_name_list = newp; + } + else + free (newp); + } + ++void ++add_temp_file (const char *name) ++{ ++ add_temp_file_internal (name, false); ++} ++ + int + create_temp_file_in_dir (const char *base, const char *dir, char **filename) + { +@@ -90,8 +106,8 @@ create_temp_file (const char *base, char **filename) + return create_temp_file_in_dir (base, test_dir, filename); + } + +-char * +-support_create_temp_directory (const char *base) ++static char * ++create_temp_directory_internal (const char *base, bool toolong) + { + char *path = xasprintf ("%s/%sXXXXXX", test_dir, base); + if (mkdtemp (path) == NULL) +@@ -99,16 +115,132 @@ support_create_temp_directory (const char *base) + printf ("error: mkdtemp (\"%s\"): %m", path); + exit (1); + } +- add_temp_file (path); ++ add_temp_file_internal (path, toolong); + return path; + } + +-/* Helper functions called by the test skeleton follow. */ ++char * ++support_create_temp_directory (const char *base) ++{ ++ return create_temp_directory_internal (base, false); ++} ++ ++static void ++ensure_toolong_initialized (void) ++{ ++ if (!toolong_initialized) ++ FAIL_EXIT1 ("uninitialized toolong directory tree\n"); ++} ++ ++static void ++initialize_toolong (const char *base) ++{ ++ long name_max = pathconf (base, _PC_NAME_MAX); ++ name_max = (name_max < 0 ? 64 ++ : (name_max < sizeof (toolong_subdir) ? name_max ++ : sizeof (toolong_subdir) - 1)); ++ ++ long path_max = pathconf (base, _PC_PATH_MAX); ++ path_max = (path_max < 0 ? 1024 ++ : path_max <= PTRDIFF_MAX ? path_max : PTRDIFF_MAX); ++ ++ /* Sanity check to ensure that the test does not create temporary directories ++ in different filesystems because this API doesn't support it. */ ++ if (toolong_initialized) ++ { ++ if (name_max != strlen (toolong_subdir)) ++ FAIL_UNSUPPORTED ("name_max: Temporary directories in different" ++ " filesystems not supported yet\n"); ++ if (path_max != toolong_path_max) ++ FAIL_UNSUPPORTED ("path_max: Temporary directories in different" ++ " filesystems not supported yet\n"); ++ return; ++ } ++ ++ toolong_path_max = path_max; ++ ++ size_t len = name_max; ++ memset (toolong_subdir, 'X', len); ++ toolong_initialized = true; ++} ++ ++char * ++support_create_and_chdir_toolong_temp_directory (const char *basename) ++{ ++ char *base = create_temp_directory_internal (basename, true); ++ xchdir (base); ++ ++ initialize_toolong (base); ++ ++ size_t sz = strlen (toolong_subdir); ++ ++ /* Create directories and descend into them so that the final path is larger ++ than PATH_MAX. */ ++ for (size_t i = 0; i <= toolong_path_max / sz; i++) ++ { ++ int ret = mkdir (toolong_subdir, S_IRWXU); ++ if (ret != 0 && errno == ENAMETOOLONG) ++ FAIL_UNSUPPORTED ("Filesystem does not support creating too long " ++ "directory trees\n"); ++ else if (ret != 0) ++ FAIL_EXIT1 ("Failed to create directory tree: %m\n"); ++ xchdir (toolong_subdir); ++ } ++ return base; ++} + + void +-support_set_test_dir (const char *path) ++support_chdir_toolong_temp_directory (const char *base) + { +- test_dir = path; ++ ensure_toolong_initialized (); ++ ++ xchdir (base); ++ ++ size_t sz = strlen (toolong_subdir); ++ for (size_t i = 0; i <= toolong_path_max / sz; i++) ++ xchdir (toolong_subdir); ++} ++ ++/* Helper functions called by the test skeleton follow. */ ++ ++static void ++remove_toolong_subdirs (const char *base) ++{ ++ ensure_toolong_initialized (); ++ ++ if (chdir (base) != 0) ++ { ++ printf ("warning: toolong cleanup base failed: chdir (\"%s\"): %m\n", ++ base); ++ return; ++ } ++ ++ /* Descend. */ ++ int levels = 0; ++ size_t sz = strlen (toolong_subdir); ++ for (levels = 0; levels <= toolong_path_max / sz; levels++) ++ if (chdir (toolong_subdir) != 0) ++ { ++ printf ("warning: toolong cleanup failed: chdir (\"%s\"): %m\n", ++ toolong_subdir); ++ break; ++ } ++ ++ /* Ascend and remove. */ ++ while (--levels >= 0) ++ { ++ if (chdir ("..") != 0) ++ { ++ printf ("warning: toolong cleanup failed: chdir (\"..\"): %m\n"); ++ return; ++ } ++ if (remove (toolong_subdir) != 0) ++ { ++ printf ("warning: could not remove subdirectory: %s: %m\n", ++ toolong_subdir); ++ return; ++ } ++ } + } + + void +@@ -123,6 +255,9 @@ support_delete_temp_files (void) + around, to prevent PID reuse.) */ + if (temp_name_list->owner == pid) + { ++ if (temp_name_list->toolong) ++ remove_toolong_subdirs (temp_name_list->name); ++ + if (remove (temp_name_list->name) != 0) + printf ("warning: could not remove temporary file: %s: %m\n", + temp_name_list->name); +@@ -147,3 +282,9 @@ support_print_temp_files (FILE *f) + fprintf (f, ")\n"); + } + } ++ ++void ++support_set_test_dir (const char *path) ++{ ++ test_dir = path; ++} +diff --git a/support/temp_file.h b/support/temp_file.h +index d64563f41f1f50cd..055e31dcfb843ba6 100644 +--- a/support/temp_file.h ++++ b/support/temp_file.h +@@ -44,6 +44,15 @@ int create_temp_file_in_dir (const char *base, const char *dir, + returns. The caller should free this string. */ + char *support_create_temp_directory (const char *base); + ++/* Create a temporary directory tree that is longer than PATH_MAX and schedule ++ it for deletion. BASENAME is used as a prefix for the unique directory ++ name, which the function returns. The caller should free this string. */ ++char *support_create_and_chdir_toolong_temp_directory (const char *basename); ++ ++/* Change into the innermost directory of the directory tree BASE, which was ++ created using support_create_and_chdir_toolong_temp_directory. */ ++void support_chdir_toolong_temp_directory (const char *base); ++ + __END_DECLS + + #endif /* SUPPORT_TEMP_FILE_H */ diff --git a/glibc-rh2032280-4.patch b/glibc-rh2032280-4.patch new file mode 100755 index 0000000..65ba651 --- /dev/null +++ b/glibc-rh2032280-4.patch @@ -0,0 +1,331 @@ +commit 23e0e8f5f1fb5ed150253d986ecccdc90c2dcd5e +Author: Siddhesh Poyarekar +Date: Fri Jan 21 23:32:56 2022 +0530 + + getcwd: Set errno to ERANGE for size == 1 (CVE-2021-3999) + + No valid path returned by getcwd would fit into 1 byte, so reject the + size early and return NULL with errno set to ERANGE. This change is + prompted by CVE-2021-3999, which describes a single byte buffer + underflow and overflow when all of the following conditions are met: + + - The buffer size (i.e. the second argument of getcwd) is 1 byte + - The current working directory is too long + - '/' is also mounted on the current working directory + + Sequence of events: + + - In sysdeps/unix/sysv/linux/getcwd.c, the syscall returns ENAMETOOLONG + because the linux kernel checks for name length before it checks + buffer size + + - The code falls back to the generic getcwd in sysdeps/posix + + - In the generic func, the buf[0] is set to '\0' on line 250 + + - this while loop on line 262 is bypassed: + + while (!(thisdev == rootdev && thisino == rootino)) + + since the rootfs (/) is bind mounted onto the directory and the flow + goes on to line 449, where it puts a '/' in the byte before the + buffer. + + - Finally on line 458, it moves 2 bytes (the underflowed byte and the + '\0') to the buf[0] and buf[1], resulting in a 1 byte buffer overflow. + + - buf is returned on line 469 and errno is not set. + + This resolves BZ #28769. + + Reviewed-by: Andreas Schwab + Reviewed-by: Adhemerval Zanella + Signed-off-by: Qualys Security Advisory + Signed-off-by: Siddhesh Poyarekar + +# Conflicts: +# sysdeps/posix/getcwd.c +# sysdeps/unix/sysv/linux/Makefile + +diff --git a/sysdeps/posix/getcwd.c b/sysdeps/posix/getcwd.c +index b53433a2dc77fafa..fcd7aaea79c6477b 100644 +--- a/sysdeps/posix/getcwd.c ++++ b/sysdeps/posix/getcwd.c +@@ -238,6 +238,13 @@ __getcwd (char *buf, size_t size) + bool fd_needs_closing = false; + int fd = AT_FDCWD; + ++ /* A size of 1 byte is never useful. */ ++ if (size == 1) ++ { ++ __set_errno (ERANGE); ++ return NULL; ++ } ++ + char *path; + #ifndef NO_ALLOCATION + size_t allocated = size; +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile +index 688cf9fa9dea23a6..bb055f9d6b841ff5 100644 +--- a/sysdeps/unix/sysv/linux/Makefile ++++ b/sysdeps/unix/sysv/linux/Makefile +@@ -180,7 +180,11 @@ sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \ + + sysdep_headers += bits/fcntl-linux.h + +-tests += tst-fallocate tst-fallocate64 ++tests += \ ++ tst-fallocate \ ++ tst-fallocate64 \ ++ tst-getcwd-smallbuff \ ++# tests + endif + + ifeq ($(subdir),elf) +diff --git a/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c +new file mode 100644 +index 0000000000000000..d460d6e7662dc5e4 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c +@@ -0,0 +1,241 @@ ++/* Verify that getcwd returns ERANGE for size 1 byte and does not underflow ++ buffer when the CWD is too long and is also a mount target of /. See bug ++ #28769 or CVE-2021-3999 for more context. ++ Copyright The GNU Toolchain Authors. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static char *base; ++#define BASENAME "tst-getcwd-smallbuff" ++#define MOUNT_NAME "mpoint" ++static int sockfd[2]; ++ ++static void ++do_cleanup (void) ++{ ++ support_chdir_toolong_temp_directory (base); ++ TEST_VERIFY_EXIT (rmdir (MOUNT_NAME) == 0); ++ free (base); ++} ++ ++static void ++send_fd (const int sock, const int fd) ++{ ++ struct msghdr msg = {0}; ++ union ++ { ++ struct cmsghdr hdr; ++ char buf[CMSG_SPACE (sizeof (int))]; ++ } cmsgbuf = {0}; ++ struct cmsghdr *cmsg; ++ struct iovec vec; ++ char ch = 'A'; ++ ssize_t n; ++ ++ msg.msg_control = &cmsgbuf.buf; ++ msg.msg_controllen = sizeof (cmsgbuf.buf); ++ ++ cmsg = CMSG_FIRSTHDR (&msg); ++ cmsg->cmsg_len = CMSG_LEN (sizeof (int)); ++ cmsg->cmsg_level = SOL_SOCKET; ++ cmsg->cmsg_type = SCM_RIGHTS; ++ memcpy (CMSG_DATA (cmsg), &fd, sizeof (fd)); ++ ++ vec.iov_base = &ch; ++ vec.iov_len = 1; ++ msg.msg_iov = &vec; ++ msg.msg_iovlen = 1; ++ ++ while ((n = sendmsg (sock, &msg, 0)) == -1 && errno == EINTR); ++ ++ TEST_VERIFY_EXIT (n == 1); ++} ++ ++static int ++recv_fd (const int sock) ++{ ++ struct msghdr msg = {0}; ++ union ++ { ++ struct cmsghdr hdr; ++ char buf[CMSG_SPACE(sizeof(int))]; ++ } cmsgbuf = {0}; ++ struct cmsghdr *cmsg; ++ struct iovec vec; ++ ssize_t n; ++ char ch = '\0'; ++ int fd = -1; ++ ++ vec.iov_base = &ch; ++ vec.iov_len = 1; ++ msg.msg_iov = &vec; ++ msg.msg_iovlen = 1; ++ ++ msg.msg_control = &cmsgbuf.buf; ++ msg.msg_controllen = sizeof (cmsgbuf.buf); ++ ++ while ((n = recvmsg (sock, &msg, 0)) == -1 && errno == EINTR); ++ if (n != 1 || ch != 'A') ++ return -1; ++ ++ cmsg = CMSG_FIRSTHDR (&msg); ++ if (cmsg == NULL) ++ return -1; ++ if (cmsg->cmsg_type != SCM_RIGHTS) ++ return -1; ++ memcpy (&fd, CMSG_DATA (cmsg), sizeof (fd)); ++ if (fd < 0) ++ return -1; ++ return fd; ++} ++ ++static int ++child_func (void * const arg) ++{ ++ xclose (sockfd[0]); ++ const int sock = sockfd[1]; ++ char ch; ++ ++ TEST_VERIFY_EXIT (read (sock, &ch, 1) == 1); ++ TEST_VERIFY_EXIT (ch == '1'); ++ ++ if (mount ("/", MOUNT_NAME, NULL, MS_BIND | MS_REC, NULL)) ++ FAIL_EXIT1 ("mount failed: %m\n"); ++ const int fd = xopen ("mpoint", ++ O_RDONLY | O_PATH | O_DIRECTORY | O_NOFOLLOW, 0); ++ ++ send_fd (sock, fd); ++ xclose (fd); ++ ++ TEST_VERIFY_EXIT (read (sock, &ch, 1) == 1); ++ TEST_VERIFY_EXIT (ch == 'a'); ++ ++ xclose (sock); ++ return 0; ++} ++ ++static void ++update_map (char * const mapping, const char * const map_file) ++{ ++ const size_t map_len = strlen (mapping); ++ ++ const int fd = xopen (map_file, O_WRONLY, 0); ++ xwrite (fd, mapping, map_len); ++ xclose (fd); ++} ++ ++static void ++proc_setgroups_write (const long child_pid, const char * const str) ++{ ++ const size_t str_len = strlen(str); ++ ++ char setgroups_path[sizeof ("/proc//setgroups") + INT_STRLEN_BOUND (long)]; ++ ++ snprintf (setgroups_path, sizeof (setgroups_path), ++ "/proc/%ld/setgroups", child_pid); ++ ++ const int fd = open (setgroups_path, O_WRONLY); ++ ++ if (fd < 0) ++ { ++ TEST_VERIFY_EXIT (errno == ENOENT); ++ FAIL_UNSUPPORTED ("/proc/%ld/setgroups not found\n", child_pid); ++ } ++ ++ xwrite (fd, str, str_len); ++ xclose(fd); ++} ++ ++static char child_stack[1024 * 1024]; ++ ++int ++do_test (void) ++{ ++ base = support_create_and_chdir_toolong_temp_directory (BASENAME); ++ ++ xmkdir (MOUNT_NAME, S_IRWXU); ++ atexit (do_cleanup); ++ ++ TEST_VERIFY_EXIT (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfd) == 0); ++ pid_t child_pid = xclone (child_func, NULL, child_stack, ++ sizeof (child_stack), ++ CLONE_NEWUSER | CLONE_NEWNS | SIGCHLD); ++ ++ xclose (sockfd[1]); ++ const int sock = sockfd[0]; ++ ++ char map_path[sizeof ("/proc//uid_map") + INT_STRLEN_BOUND (long)]; ++ char map_buf[sizeof ("0 1") + INT_STRLEN_BOUND (long)]; ++ ++ snprintf (map_path, sizeof (map_path), "/proc/%ld/uid_map", ++ (long) child_pid); ++ snprintf (map_buf, sizeof (map_buf), "0 %ld 1", (long) getuid()); ++ update_map (map_buf, map_path); ++ ++ proc_setgroups_write ((long) child_pid, "deny"); ++ snprintf (map_path, sizeof (map_path), "/proc/%ld/gid_map", ++ (long) child_pid); ++ snprintf (map_buf, sizeof (map_buf), "0 %ld 1", (long) getgid()); ++ update_map (map_buf, map_path); ++ ++ TEST_VERIFY_EXIT (send (sock, "1", 1, MSG_NOSIGNAL) == 1); ++ const int fd = recv_fd (sock); ++ TEST_VERIFY_EXIT (fd >= 0); ++ TEST_VERIFY_EXIT (fchdir (fd) == 0); ++ ++ static char buf[2 * 10 + 1]; ++ memset (buf, 'A', sizeof (buf)); ++ ++ /* Finally, call getcwd and check if it resulted in a buffer underflow. */ ++ char * cwd = getcwd (buf + sizeof (buf) / 2, 1); ++ TEST_VERIFY (cwd == NULL); ++ TEST_VERIFY (errno == ERANGE); ++ ++ for (int i = 0; i < sizeof (buf); i++) ++ if (buf[i] != 'A') ++ { ++ printf ("buf[%d] = %02x\n", i, (unsigned int) buf[i]); ++ support_record_failure (); ++ } ++ ++ TEST_VERIFY_EXIT (send (sock, "a", 1, MSG_NOSIGNAL) == 1); ++ xclose (sock); ++ TEST_VERIFY_EXIT (xwaitpid (child_pid, NULL, 0) == child_pid); ++ ++ return 0; ++} ++ ++#define CLEANUP_HANDLER do_cleanup ++#include diff --git a/glibc-rh2032280-5.patch b/glibc-rh2032280-5.patch new file mode 100755 index 0000000..f761b9d --- /dev/null +++ b/glibc-rh2032280-5.patch @@ -0,0 +1,121 @@ +commit de8995a2a04163617c1a233b4b81356ef9f9741f +Author: Adhemerval Zanella +Date: Wed Mar 10 12:26:30 2021 -0300 + + support: Add xclone + + It is a wrapper for Linux clone syscall, to simplify the call to the + use only the most common arguments and remove architecture specific + handling (such as ia64 different name and signature). + +# Conflicts: +# support/Makefile + +diff --git a/support/Makefile b/support/Makefile +index fb95a69ed9158e78..d2b95539403e416c 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -84,6 +84,7 @@ libsupport-routines = \ + xcalloc \ + xchdir \ + xchroot \ ++ xclone \ + xclose \ + xconnect \ + xcopy_file_range \ +diff --git a/support/xclone.c b/support/xclone.c +new file mode 100644 +index 0000000000000000..924d2b875402a819 +--- /dev/null ++++ b/support/xclone.c +@@ -0,0 +1,50 @@ ++/* Auxiliary functions to issue the clone syscall. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifdef __linux__ ++# include ++# include /* For _STACK_GROWS_{UP,DOWN}. */ ++# include ++ ++pid_t ++xclone (int (*fn) (void *arg), void *arg, void *stack, size_t stack_size, ++ int flags) ++{ ++ pid_t r = -1; ++ ++# ifdef __ia64__ ++ extern int __clone2 (int (*fn) (void *arg), void *stack, size_t stack_size, ++ int flags, void *arg, ...); ++ r = __clone2 (f, stack, stack_size, flags, arg, /* ptid */ NULL, ++ /* tls */ NULL, /* ctid */ ctid); ++# else ++# if _STACK_GROWS_DOWN ++ r = clone (fn, stack + stack_size, flags, arg, /* ptid */ NULL, ++ /* tls */ NULL, /* ctid */ NULL); ++# elif _STACK_GROWS_UP ++ r = clone (fn, stack, flags, arg, /* ptid */ NULL, /* tls */ NULL, ++ &ctid); ++# endif ++# endif ++ ++ if (r < 0) ++ FAIL_EXIT1 ("clone: %m"); ++ ++ return r; ++} ++#endif +diff --git a/support/xsched.h b/support/xsched.h +new file mode 100644 +index 0000000000000000..eefd731940187b39 +--- /dev/null ++++ b/support/xsched.h +@@ -0,0 +1,34 @@ ++/* Wrapper for sched.h functions. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef SUPPORT_XSCHED_H ++#define SUPPORT_XSCHED_H ++ ++__BEGIN_DECLS ++ ++#include ++#include ++ ++#ifdef __linux__ ++pid_t xclone (int (*fn) (void *arg), void *arg, void *stack, ++ size_t stack_size, int flags); ++#endif ++ ++__END_DECLS ++ ++#endif diff --git a/glibc-rh2032280-6.patch b/glibc-rh2032280-6.patch new file mode 100755 index 0000000..a8bc55b --- /dev/null +++ b/glibc-rh2032280-6.patch @@ -0,0 +1,46 @@ +commit 5b8e7980c5dabd9aaefeba4f0208baa8cf7653ee +Author: Florian Weimer +Date: Mon Jan 24 18:14:24 2022 +0100 + + Linux: Detect user namespace support in io/tst-getcwd-smallbuff + + Otherwise the test fails with certain container runtimes. + + Reviewed-by: Siddhesh Poyarekar + +diff --git a/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c +index d460d6e7662dc5e4..55362f6060a2b3be 100644 +--- a/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c ++++ b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c +@@ -34,6 +34,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -188,6 +189,23 @@ do_test (void) + xmkdir (MOUNT_NAME, S_IRWXU); + atexit (do_cleanup); + ++ /* Check whether user namespaces are supported. */ ++ { ++ pid_t pid = xfork (); ++ if (pid == 0) ++ { ++ if (unshare (CLONE_NEWUSER | CLONE_NEWNS) != 0) ++ _exit (EXIT_UNSUPPORTED); ++ else ++ _exit (0); ++ } ++ int status; ++ xwaitpid (pid, &status, 0); ++ TEST_VERIFY_EXIT (WIFEXITED (status)); ++ if (WEXITSTATUS (status) != 0) ++ return WEXITSTATUS (status); ++ } ++ + TEST_VERIFY_EXIT (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfd) == 0); + pid_t child_pid = xclone (child_func, NULL, child_stack, + sizeof (child_stack), diff --git a/glibc-rh2032280-7.patch b/glibc-rh2032280-7.patch new file mode 100755 index 0000000..60ea205 --- /dev/null +++ b/glibc-rh2032280-7.patch @@ -0,0 +1,24 @@ +commit 3842ba494963b1d76ad5f68b8d1e5c2279160e31 +Author: Szabolcs Nagy +Date: Tue Jun 1 09:23:40 2021 +0100 + + aarch64: align stack in clone [BZ #27939] + + The AArch64 PCS requires 16 byte aligned stack. Previously if the + caller passed an unaligned stack to clone then the child crashed. + + Fixes bug 27939. + +diff --git a/sysdeps/unix/sysv/linux/aarch64/clone.S b/sysdeps/unix/sysv/linux/aarch64/clone.S +index e0653048259dd9a3..4a1a999447ee5cf1 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/clone.S ++++ b/sysdeps/unix/sysv/linux/aarch64/clone.S +@@ -48,6 +48,8 @@ ENTRY(__clone) + /* Sanity check args. */ + mov x0, #-EINVAL + cbz x10, .Lsyscall_error ++ /* Align sp. */ ++ and x1, x1, -16 + cbz x1, .Lsyscall_error + + /* Do the system call. */ diff --git a/glibc-rh2045062-1.patch b/glibc-rh2045062-1.patch new file mode 100755 index 0000000..2885e3f --- /dev/null +++ b/glibc-rh2045062-1.patch @@ -0,0 +1,164 @@ +commit e368b12f6c16b6888dda99ba641e999b9c9643c8 +Author: Florian Weimer +Date: Mon Jan 17 10:21:34 2022 +0100 + + socket: Add the __sockaddr_un_set function + + Reviewed-by: Siddhesh Poyarekar + +# Conflicts: +# socket/Makefile + +diff --git a/include/sys/un.h b/include/sys/un.h +index bdbee999806930f4..152afd9fc7426d8b 100644 +--- a/include/sys/un.h ++++ b/include/sys/un.h +@@ -1 +1,13 @@ + #include ++ ++#ifndef _ISOMAC ++ ++/* Set ADDR->sun_family to AF_UNIX and ADDR->sun_path to PATHNAME. ++ Return 0 on success or -1 on failure (due to overlong PATHNAME). ++ The caller should always use sizeof (struct sockaddr_un) as the ++ socket address length, disregaring the length of PATHNAME. ++ Only concrete (non-abstract) pathnames are supported. */ ++int __sockaddr_un_set (struct sockaddr_un *addr, const char *pathname) ++ attribute_hidden; ++ ++#endif /* _ISOMAC */ +diff --git a/socket/Makefile b/socket/Makefile +index b41eb071507a6271..8975a65c2aabbfbc 100644 +--- a/socket/Makefile ++++ b/socket/Makefile +@@ -29,10 +29,14 @@ headers := sys/socket.h sys/un.h bits/sockaddr.h bits/socket.h \ + routines := accept bind connect getpeername getsockname getsockopt \ + listen recv recvfrom recvmsg send sendmsg sendto \ + setsockopt shutdown socket socketpair isfdtype opensock \ +- sockatmark accept4 recvmmsg sendmmsg ++ sockatmark accept4 recvmmsg sendmmsg sockaddr_un_set + + tests := tst-accept4 + ++tests-internal := \ ++ tst-sockaddr_un_set \ ++ # tests-internal ++ + aux := sa_len + + include ../Rules +diff --git a/socket/sockaddr_un_set.c b/socket/sockaddr_un_set.c +new file mode 100644 +index 0000000000000000..0bd40dc34e3d7efc +--- /dev/null ++++ b/socket/sockaddr_un_set.c +@@ -0,0 +1,41 @@ ++/* Set the sun_path member of struct sockaddr_un. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++int ++__sockaddr_un_set (struct sockaddr_un *addr, const char *pathname) ++{ ++ size_t name_length = strlen (pathname); ++ ++ /* The kernel supports names of exactly sizeof (addr->sun_path) ++ bytes, without a null terminator, but userspace does not; see the ++ SUN_LEN macro. */ ++ if (name_length >= sizeof (addr->sun_path)) ++ { ++ __set_errno (EINVAL); /* Error code used by the kernel. */ ++ return -1; ++ } ++ ++ addr->sun_family = AF_UNIX; ++ memcpy (addr->sun_path, pathname, name_length + 1); ++ return 0; ++} +diff --git a/socket/tst-sockaddr_un_set.c b/socket/tst-sockaddr_un_set.c +new file mode 100644 +index 0000000000000000..29c2a81afda81b5e +--- /dev/null ++++ b/socket/tst-sockaddr_un_set.c +@@ -0,0 +1,62 @@ ++/* Test the __sockaddr_un_set function. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++/* Re-compile the function because the version in libc is not ++ exported. */ ++#include "sockaddr_un_set.c" ++ ++#include ++ ++static int ++do_test (void) ++{ ++ struct sockaddr_un sun; ++ ++ memset (&sun, 0xcc, sizeof (sun)); ++ __sockaddr_un_set (&sun, ""); ++ TEST_COMPARE (sun.sun_family, AF_UNIX); ++ TEST_COMPARE (__sockaddr_un_set (&sun, ""), 0); ++ ++ memset (&sun, 0xcc, sizeof (sun)); ++ TEST_COMPARE (__sockaddr_un_set (&sun, "/example"), 0); ++ TEST_COMPARE_STRING (sun.sun_path, "/example"); ++ ++ { ++ char pathname[108]; /* Length of sun_path (ABI constant). */ ++ memset (pathname, 'x', sizeof (pathname)); ++ pathname[sizeof (pathname) - 1] = '\0'; ++ memset (&sun, 0xcc, sizeof (sun)); ++ TEST_COMPARE (__sockaddr_un_set (&sun, pathname), 0); ++ TEST_COMPARE (sun.sun_family, AF_UNIX); ++ TEST_COMPARE_STRING (sun.sun_path, pathname); ++ } ++ ++ { ++ char pathname[109]; ++ memset (pathname, 'x', sizeof (pathname)); ++ pathname[sizeof (pathname) - 1] = '\0'; ++ memset (&sun, 0xcc, sizeof (sun)); ++ errno = 0; ++ TEST_COMPARE (__sockaddr_un_set (&sun, pathname), -1); ++ TEST_COMPARE (errno, EINVAL); ++ } ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh2045062-2.patch b/glibc-rh2045062-2.patch new file mode 100755 index 0000000..9e74607 --- /dev/null +++ b/glibc-rh2045062-2.patch @@ -0,0 +1,32 @@ +commit 226b46770c82899b555986583294b049c6ec9b40 +Author: Florian Weimer +Date: Mon Jan 17 10:21:34 2022 +0100 + + CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix" (bug 22542) + + Processing an overlong pathname in the sunrpc clnt_create function + results in a stack-based buffer overflow. + + Reviewed-by: Siddhesh Poyarekar + +diff --git a/sunrpc/clnt_gen.c b/sunrpc/clnt_gen.c +index 13ced8994e49d4ee..b44357cd88e60599 100644 +--- a/sunrpc/clnt_gen.c ++++ b/sunrpc/clnt_gen.c +@@ -57,9 +57,13 @@ clnt_create (const char *hostname, u_long prog, u_long vers, + + if (strcmp (proto, "unix") == 0) + { +- memset ((char *)&sun, 0, sizeof (sun)); +- sun.sun_family = AF_UNIX; +- strcpy (sun.sun_path, hostname); ++ if (__sockaddr_un_set (&sun, hostname) < 0) ++ { ++ struct rpc_createerr *ce = &get_rpc_createerr (); ++ ce->cf_stat = RPC_SYSTEMERROR; ++ ce->cf_error.re_errno = errno; ++ return NULL; ++ } + sock = RPC_ANYSOCK; + client = clntunix_create (&sun, prog, vers, &sock, 0, 0); + if (client == NULL) diff --git a/glibc-rh2045062-3.patch b/glibc-rh2045062-3.patch new file mode 100755 index 0000000..cd1e55d --- /dev/null +++ b/glibc-rh2045062-3.patch @@ -0,0 +1,80 @@ +commit ef972a4c50014a16132b5c75571cfb6b30bef136 +Author: Martin Sebor +Date: Mon Jan 17 10:21:34 2022 +0100 + + sunrpc: Test case for clnt_create "unix" buffer overflow (bug 22542) + + Reviewed-by: Siddhesh Poyarekar + +# Conflicts: +# sunrpc/Makefile + +diff --git a/sunrpc/Makefile b/sunrpc/Makefile +index 85b0b3356aaf81a3..2f8f0597c99e117f 100644 +--- a/sunrpc/Makefile ++++ b/sunrpc/Makefile +@@ -95,7 +95,8 @@ others += rpcgen + endif + + tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error tst-udp-timeout \ +- tst-udp-nonblocking ++ tst-udp-nonblocking tst-bug22542 ++ + xtests := tst-getmyaddr + + ifeq ($(have-thread-library),yes) +@@ -246,3 +247,4 @@ $(objpfx)tst-udp-timeout: $(common-objpfx)linkobj/libc.so + $(objpfx)tst-udp-nonblocking: $(common-objpfx)linkobj/libc.so + $(objpfx)tst-udp-garbage: \ + $(common-objpfx)linkobj/libc.so $(shared-thread-library) ++$(objpfx)tst-bug22542: $(common-objpfx)linkobj/libc.so +diff --git a/sunrpc/tst-bug22542.c b/sunrpc/tst-bug22542.c +new file mode 100644 +index 0000000000000000..d6cd79787bdef21d +--- /dev/null ++++ b/sunrpc/tst-bug22542.c +@@ -0,0 +1,44 @@ ++/* Test to verify that overlong hostname is rejected by clnt_create ++ and doesn't cause a buffer overflow (bug 22542). ++ ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* Create an arbitrary hostname that's longer than fits in sun_path. */ ++ char name [sizeof ((struct sockaddr_un*)0)->sun_path * 2]; ++ memset (name, 'x', sizeof name - 1); ++ name [sizeof name - 1] = '\0'; ++ ++ errno = 0; ++ CLIENT *clnt = clnt_create (name, 0, 0, "unix"); ++ ++ TEST_VERIFY (clnt == NULL); ++ TEST_COMPARE (errno, EINVAL); ++ return 0; ++} ++ ++#include diff --git a/glibc-rh2045062-4.patch b/glibc-rh2045062-4.patch new file mode 100755 index 0000000..489c315 --- /dev/null +++ b/glibc-rh2045062-4.patch @@ -0,0 +1,101 @@ +commit f545ad4928fa1f27a3075265182b38a4f939a5f7 +Author: Florian Weimer +Date: Mon Jan 17 10:21:34 2022 +0100 + + CVE-2022-23218: Buffer overflow in sunrpc svcunix_create (bug 28768) + + The sunrpc function svcunix_create suffers from a stack-based buffer + overflow with overlong pathname arguments. + + Reviewed-by: Siddhesh Poyarekar + +diff --git a/sunrpc/Makefile b/sunrpc/Makefile +index 2f8f0597c99e117f..5f7087aee494cc2e 100644 +--- a/sunrpc/Makefile ++++ b/sunrpc/Makefile +@@ -95,7 +95,7 @@ others += rpcgen + endif + + tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error tst-udp-timeout \ +- tst-udp-nonblocking tst-bug22542 ++ tst-udp-nonblocking tst-bug22542 tst-bug28768 + + xtests := tst-getmyaddr + +diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c +index c2c076aa87f0a2ad..8fac2b35da1d38a5 100644 +--- a/sunrpc/svc_unix.c ++++ b/sunrpc/svc_unix.c +@@ -154,7 +154,10 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) + SVCXPRT *xprt; + struct unix_rendezvous *r; + struct sockaddr_un addr; +- socklen_t len = sizeof (struct sockaddr_in); ++ socklen_t len = sizeof (addr); ++ ++ if (__sockaddr_un_set (&addr, path) < 0) ++ return NULL; + + if (sock == RPC_ANYSOCK) + { +@@ -165,12 +168,6 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) + } + madesock = TRUE; + } +- memset (&addr, '\0', sizeof (addr)); +- addr.sun_family = AF_UNIX; +- len = strlen (path) + 1; +- memcpy (addr.sun_path, path, len); +- len += sizeof (addr.sun_family); +- + __bind (sock, (struct sockaddr *) &addr, len); + + if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0 +diff --git a/sunrpc/tst-bug28768.c b/sunrpc/tst-bug28768.c +new file mode 100644 +index 0000000000000000..35a4b7b0b3d34350 +--- /dev/null ++++ b/sunrpc/tst-bug28768.c +@@ -0,0 +1,42 @@ ++/* Test to verify that long path is rejected by svcunix_create (bug 28768). ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* svcunix_create does not have a default version in linkobj/libc.so. */ ++compat_symbol_reference (libc, svcunix_create, svcunix_create, GLIBC_2_1); ++ ++static int ++do_test (void) ++{ ++ char pathname[109]; ++ memset (pathname, 'x', sizeof (pathname)); ++ pathname[sizeof (pathname) - 1] = '\0'; ++ ++ errno = 0; ++ TEST_VERIFY (svcunix_create (RPC_ANYSOCK, 4096, 4096, pathname) == NULL); ++ TEST_COMPARE (errno, EINVAL); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-rh2045062-5.patch b/glibc-rh2045062-5.patch new file mode 100755 index 0000000..3d7b71e --- /dev/null +++ b/glibc-rh2045062-5.patch @@ -0,0 +1,54 @@ +commit 36f6e408845c8c539128f3fb9cb132bf1845a2c8 +Author: Florian Weimer +Date: Tue Mar 9 21:07:24 2021 +0100 + + : Support compat_symbol_reference for _ISOMAC + + This is helpful for testing compat symbols in cases where _ISOMAC + is activated implicitly due to -DMODULE_NAME=testsuite and cannot + be disabled easily. + +diff --git a/include/libc-symbols.h b/include/libc-symbols.h +index 41436050d060b89f..44e12b63d40cc572 100644 +--- a/include/libc-symbols.h ++++ b/include/libc-symbols.h +@@ -59,6 +59,19 @@ + # define IN_MODULE (-1) + #endif + ++/* Use symbol_version_reference to specify the version a symbol ++ reference should link to. Use symbol_version or ++ default_symbol_version for the definition of a versioned symbol. ++ The difference is that the latter is a no-op in non-shared ++ builds. */ ++#ifdef __ASSEMBLER__ ++# define symbol_version_reference(real, name, version) \ ++ .symver real, name##@##version ++#else /* !__ASSEMBLER__ */ ++# define symbol_version_reference(real, name, version) \ ++ __asm__ (".symver " #real "," #name "@" #version) ++#endif ++ + #ifndef _ISOMAC + + /* This is defined for the compilation of all C library code. features.h +@@ -388,19 +401,6 @@ for linking") + past the last element in SET. */ + #define symbol_set_end_p(set, ptr) ((ptr) >= (void *const *) &__stop_##set) + +-/* Use symbol_version_reference to specify the version a symbol +- reference should link to. Use symbol_version or +- default_symbol_version for the definition of a versioned symbol. +- The difference is that the latter is a no-op in non-shared +- builds. */ +-#ifdef __ASSEMBLER__ +-# define symbol_version_reference(real, name, version) \ +- .symver real, name##@##version +-#else /* !__ASSEMBLER__ */ +-# define symbol_version_reference(real, name, version) \ +- __asm__ (".symver " #real "," #name "@" #version) +-#endif +- + #ifdef SHARED + # define symbol_version(real, name, version) \ + symbol_version_reference(real, name, version) diff --git a/glibc-rh697421.patch b/glibc-rh697421.patch new file mode 100755 index 0000000..e909aa1 --- /dev/null +++ b/glibc-rh697421.patch @@ -0,0 +1,21 @@ +Short description: Add UCS-2 aliases. +Author(s): Fedora glibc team +Origin: PATCH +Bug-RHEL: #697421 +Upstream status: https://sourceware.org/ml/libc-alpha/2012-12/msg00103.html + +This is a Fedora-specific change to include new aliases for UCS-2 +data for gconv used by a certain class of users. This should be +revisited at some point to determine if those users are just using +UTF-8 at this point. + +diff -rup a/iconvdata/gconv-modules b/iconvdata/gconv-modules +--- a/iconvdata/gconv-modules 2010-05-04 05:27:23.000000000 -0600 ++++ b/iconvdata/gconv-modules 2012-01-26 10:58:24.181895489 -0700 +@@ -1954,3 +1954,6 @@ alias HPGREEK8// HP-GREEK8// + alias OSF10010004// HP-GREEK8// + module HP-GREEK8// INTERNAL HP-GREEK8 1 + module INTERNAL HP-GREEK8// HP-GREEK8 1 ++ ++alias ISO-10646-UCS-2// UNICODE// ++alias ISO-10646-UCS-2// ISO-10646/UTF8/ diff --git a/glibc-rh741105.patch b/glibc-rh741105.patch new file mode 100755 index 0000000..f7d06ca --- /dev/null +++ b/glibc-rh741105.patch @@ -0,0 +1,84 @@ +Short description: Work ld.so --verify crash on debuginfo files. +Author(s): Fedora glibc team +Origin: PATCH +Bug-RHEL: #741105, #767146 +Upstream status: not-needed + +This change is designed to work around running ld.so on a debuginfo +file. This is the wrong fix for this problem and should be dropped. +The correct solution is to mark debuginfo files as new types of +ELF files. + +Index: glibc-2.22-386-g95e8397/elf/dl-load.c +=================================================================== +--- glibc-2.22-386-g95e8397.orig/elf/dl-load.c ++++ glibc-2.22-386-g95e8397/elf/dl-load.c +@@ -881,7 +881,8 @@ _dl_map_object_from_fd (const char *name + + /* Get file information. */ + struct r_file_id id; +- if (__glibc_unlikely (!_dl_get_file_id (fd, &id))) ++ struct stat64 st; ++ if (__glibc_unlikely (!_dl_get_file_id (fd, &id, &st))) + { + errstring = N_("cannot stat shared object"); + call_lose_errno: +@@ -1076,6 +1077,16 @@ _dl_map_object_from_fd (const char *name + = N_("ELF load command address/offset not properly aligned"); + goto call_lose; + } ++ if (__glibc_unlikely (ph->p_offset + ph->p_filesz > st.st_size)) ++ { ++ /* If the segment requires zeroing of part of its last ++ page, we'll crash when accessing the unmapped page. ++ There's still a possibility of a race, if the shared ++ object is truncated between the fxstat above and the ++ memset below. */ ++ errstring = N_("ELF load command past end of file"); ++ goto call_lose; ++ } + + struct loadcmd *c = &loadcmds[nloadcmds++]; + c->mapstart = ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize)); +Index: glibc-2.22-386-g95e8397/sysdeps/generic/dl-fileid.h +=================================================================== +--- glibc-2.22-386-g95e8397.orig/sysdeps/generic/dl-fileid.h ++++ glibc-2.22-386-g95e8397/sysdeps/generic/dl-fileid.h +@@ -29,7 +29,8 @@ struct r_file_id + On error, returns false, with errno set. */ + static inline bool + _dl_get_file_id (int fd __attribute__ ((unused)), +- struct r_file_id *id __attribute__ ((unused))) ++ struct r_file_id *id __attribute__ ((unused)), ++ struct stat64_t *st __attribute__((unused))) + { + return true; + } +Index: glibc-2.22-386-g95e8397/sysdeps/posix/dl-fileid.h +=================================================================== +--- glibc-2.22-386-g95e8397.orig/sysdeps/posix/dl-fileid.h ++++ glibc-2.22-386-g95e8397/sysdeps/posix/dl-fileid.h +@@ -27,18 +27,16 @@ struct r_file_id + ino64_t ino; + }; + +-/* Sample FD to fill in *ID. Returns true on success. ++/* Sample FD to fill in *ID and *ST. Returns true on success. + On error, returns false, with errno set. */ + static inline bool +-_dl_get_file_id (int fd, struct r_file_id *id) ++_dl_get_file_id (int fd, struct r_file_id *id, struct stat64 *st) + { +- struct stat64 st; +- +- if (__glibc_unlikely (__fxstat64 (_STAT_VER, fd, &st) < 0)) ++ if (__glibc_unlikely (__fxstat64 (_STAT_VER, fd, st) < 0)) + return false; + +- id->dev = st.st_dev; +- id->ino = st.st_ino; ++ id->dev = st->st_dev; ++ id->ino = st->st_ino; + return true; + } + diff --git a/glibc-rh819430.patch b/glibc-rh819430.patch new file mode 100755 index 0000000..8b766f1 --- /dev/null +++ b/glibc-rh819430.patch @@ -0,0 +1,91 @@ +Short description: fnmatch() fails with MBCS. +Author(s): Fedora glibc team +Origin: PATCH +Bug-RHEL: #819430, #826149, #826151 +Bug-Upstream: #14185 +Upstream status: not-submitted + +fnmatch() fails when '*' wildcard is applied on the file name +containing multi-byte character(s) + +This needs to be reviewed thoroughly and go upstream with a +new test case. + +diff -Nrup a/posix/fnmatch.c b/posix/fnmatch.c +--- a/posix/fnmatch.c 2012-01-01 07:16:32.000000000 -0500 ++++ b/posix/fnmatch.c 2012-05-23 14:14:29.099461189 -0400 +@@ -333,6 +333,7 @@ fnmatch (pattern, string, flags) + # if HANDLE_MULTIBYTE + if (__builtin_expect (MB_CUR_MAX, 1) != 1) + { ++ const char *orig_pattern = pattern; + mbstate_t ps; + size_t n; + const char *p; +@@ -356,10 +357,8 @@ fnmatch (pattern, string, flags) + alloca_used); + n = mbsrtowcs (wpattern, &p, n + 1, &ps); + if (__glibc_unlikely (n == (size_t) -1)) +- /* Something wrong. +- XXX Do we have to set `errno' to something which mbsrtows hasn't +- already done? */ +- return -1; ++ /* Something wrong: Fall back to single byte matching. */ ++ goto try_singlebyte; + if (p) + { + memset (&ps, '\0', sizeof (ps)); +@@ -371,10 +370,8 @@ fnmatch (pattern, string, flags) + prepare_wpattern: + n = mbsrtowcs (NULL, &pattern, 0, &ps); + if (__glibc_unlikely (n == (size_t) -1)) +- /* Something wrong. +- XXX Do we have to set `errno' to something which mbsrtows hasn't +- already done? */ +- return -1; ++ /*Something wrong: Fall back to single byte matching. */ ++ goto try_singlebyte; + if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t))) + { + __set_errno (ENOMEM); +@@ -401,14 +398,8 @@ fnmatch (pattern, string, flags) + alloca_used); + n = mbsrtowcs (wstring, &p, n + 1, &ps); + if (__glibc_unlikely (n == (size_t) -1)) +- { +- /* Something wrong. +- XXX Do we have to set `errno' to something which +- mbsrtows hasn't already done? */ +- free_return: +- free (wpattern_malloc); +- return -1; +- } ++ /* Something wrong: Fall back to single byte matching. */ ++ goto free_and_try_singlebyte; + if (p) + { + memset (&ps, '\0', sizeof (ps)); +@@ -420,10 +411,8 @@ fnmatch (pattern, string, flags) + prepare_wstring: + n = mbsrtowcs (NULL, &string, 0, &ps); + if (__glibc_unlikely (n == (size_t) -1)) +- /* Something wrong. +- XXX Do we have to set `errno' to something which mbsrtows hasn't +- already done? */ +- goto free_return; ++ /* Something wrong: Fall back to singlebyte matching. */ ++ goto free_and_try_singlebyte; + if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t))) + { + free (wpattern_malloc); +@@ -450,6 +439,10 @@ fnmatch (pattern, string, flags) + free (wpattern_malloc); + + return res; ++ free_and_try_singlebyte: ++ free(wpattern_malloc); ++ try_singlebyte: ++ pattern = orig_pattern; + } + # endif /* mbstate_t and mbsrtowcs or _LIBC. */ + diff --git a/glibc-fix-newlocale-error-return.patch b/glibc-rh827510.patch old mode 100644 new mode 100755 similarity index 100% rename from glibc-fix-newlocale-error-return.patch rename to glibc-rh827510.patch diff --git a/glibc-with-nonshared-cflags.patch b/glibc-with-nonshared-cflags.patch new file mode 100755 index 0000000..af7f65b --- /dev/null +++ b/glibc-with-nonshared-cflags.patch @@ -0,0 +1,139 @@ +Author: Florian Weimer +Date: Wed Jul 4 11:34:36 2018 +0200 + + Add --with-nonshared-cflags option to configure + +Submitted upstream: + + https://sourceware.org/ml/libc-alpha/2018-07/msg00071.html + +diff --git a/INSTALL b/INSTALL +index 0a22aa7d01e6e87b..0f80d9d615db6d42 100644 +--- a/INSTALL ++++ b/INSTALL +@@ -90,6 +90,15 @@ if 'CFLAGS' is specified it must enable optimization. For example: + library will still be usable, but functionality may be lost--for + example, you can't build a shared libc with old binutils. + ++'--with-nonshared-cflags=CFLAGS' ++ Use additional compiler flags CFLAGS to build the parts of the ++ library which are always statically linked into applications and ++ libraries even with shared linking (that is, the object files ++ contained in 'lib*_nonshared.a' libraries). The build process will ++ automatically use the appropriate flags, but this option can be ++ used to set additional flags required for building applications and ++ libraries, to match local policy. ++ + '--disable-shared' + Don't build shared libraries even if it is possible. Not all + systems support shared libraries; you need ELF support and +diff --git a/Makeconfig b/Makeconfig +index 608ffe648c80c724..b0b27f0113ac18b8 100644 +--- a/Makeconfig ++++ b/Makeconfig +@@ -1038,7 +1038,7 @@ object-suffixes-for-libc += .oS + # Must build the routines as PIC, though, because they can end up in (users') + # shared objects. We don't want to use CFLAGS-os because users may, for + # example, make that processor-specific. +-CFLAGS-.oS = $(CFLAGS-.o) $(PIC-ccflag) ++CFLAGS-.oS = $(CFLAGS-.o) $(PIC-ccflag) $(extra-nonshared-cflags) + CPPFLAGS-.oS = $(CPPFLAGS-.o) -DPIC -DLIBC_NONSHARED=1 + libtype.oS = lib%_nonshared.a + endif +diff --git a/config.make.in b/config.make.in +index d9891b2cd8ec3fbf..a6fe48d31f4d2725 100644 +--- a/config.make.in ++++ b/config.make.in +@@ -110,6 +110,7 @@ BUILD_CC = @BUILD_CC@ + CFLAGS = @CFLAGS@ + CPPFLAGS-config = @CPPFLAGS@ + CPPUNDEFS = @CPPUNDEFS@ ++extra-nonshared-cflags = @extra_nonshared_cflags@ + ASFLAGS-config = @ASFLAGS_config@ + AR = @AR@ + NM = @NM@ +diff --git a/configure b/configure +index ef1830221522b7a5..fec0efff8216addd 100755 +--- a/configure ++++ b/configure +@@ -684,6 +684,7 @@ force_install + bindnow + hardcoded_path_in_tests + enable_timezone_tools ++extra_nonshared_cflags + use_default_link + sysheaders + ac_ct_CXX +@@ -762,6 +763,7 @@ with_binutils + with_selinux + with_headers + with_default_link ++with_nonshared_cflags + enable_sanity_checks + enable_shared + enable_profile +@@ -1479,6 +1481,8 @@ Optional Packages: + --with-headers=PATH location of system headers to use (for example + /usr/src/linux/include) [default=compiler default] + --with-default-link do not use explicit linker scripts ++ --with-nonshared-cflags=FLAGS ++ build nonshared libraries with additional FLAGS + --with-cpu=CPU select code for CPU variant + + Some influential environment variables: +@@ -3336,6 +3340,16 @@ else + fi + + ++ ++# Check whether --with-nonshared-cflags was given. ++if test "${with_nonshared_cflags+set}" = set; then : ++ withval=$with_nonshared_cflags; extra_nonshared_cflags=$withval ++else ++ extra_nonshared_cflags= ++fi ++ ++ ++ + # Check whether --enable-sanity-checks was given. + if test "${enable_sanity_checks+set}" = set; then : + enableval=$enable_sanity_checks; enable_sanity=$enableval +diff --git a/configure.ac b/configure.ac +index dc517017f588626a..154185d70de38928 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -154,6 +154,14 @@ AC_ARG_WITH([default-link], + [use_default_link=$withval], + [use_default_link=default]) + ++dnl Additional build flags injection. ++AC_ARG_WITH([nonshared-cflags], ++ AC_HELP_STRING([--with-nonshared-cflags=FLAGS], ++ [build nonshared libraries with additional FLAGS]), ++ [extra_nonshared_cflags=$withval], ++ [extra_nonshared_cflags=]) ++AC_SUBST(extra_nonshared_cflags) ++ + AC_ARG_ENABLE([sanity-checks], + AC_HELP_STRING([--disable-sanity-checks], + [really do not use threads (should not be used except in special situations) @<:@default=yes@:>@]), +diff --git a/manual/install.texi b/manual/install.texi +index 422da1447eb4dc68..eaf0cd09e7501b96 100644 +--- a/manual/install.texi ++++ b/manual/install.texi +@@ -117,6 +117,15 @@ problem and suppress these constructs, so that the library will still be + usable, but functionality may be lost---for example, you can't build a + shared libc with old binutils. + ++@item --with-nonshared-cflags=@var{cflags} ++Use additional compiler flags @var{cflags} to build the parts of the ++library which are always statically linked into applications and ++libraries even with shared linking (that is, the object files contained ++in @file{lib*_nonshared.a} libraries). The build process will ++automatically use the appropriate flags, but this option can be used to ++set additional flags required for building applications and libraries, ++to match local policy. ++ + @c disable static doesn't work currently + @c @item --disable-static + @c Don't build static libraries. Static libraries aren't that useful these diff --git a/glibc.spec b/glibc.spec old mode 100644 new mode 100755 index 2e5adb0..3bc5fb3 --- a/glibc.spec +++ b/glibc.spec @@ -1,229 +1,972 @@ -%define anolis_release 3 - +%define glibcsrcdir glibc-2.28 +%define glibcversion 2.28 +%define glibcrelease 164%{?dist}.3 +# Pre-release tarballs are pulled in from git using a command that is +# effectively: +# +# git archive HEAD --format=tar --prefix=$(git describe --match 'glibc-*')/ \ +# > $(git describe --match 'glibc-*').tar +# gzip -9 $(git describe --match 'glibc-*').tar +# +# glibc_release_url is only defined when we have a release tarball. +%{lua: if string.match(rpm.expand("%glibcsrcdir"), "^glibc%-[0-9.]+$") then + rpm.define("glibc_release_url https://ftp.gnu.org/gnu/glibc/") end} +############################################################################## +# We support the following options: +# --with/--without, +# * testsuite - Running the testsuite. +# * benchtests - Running and building benchmark subpackage. +# * bootstrap - Bootstrapping the package. +# * werror - Build with -Werror +# * docs - Build with documentation and the required dependencies. +# * valgrind - Run smoke tests with valgrind to verify dynamic loader. +# +# You must always run the testsuite for production builds. +# Default: Always run the testsuite. %bcond_without testsuite +# Default: Always build the benchtests. %bcond_without benchtests +# Default: Not bootstrapping. %bcond_with bootstrap +# Default: Enable using -Werror %bcond_without werror +# Default: Always build documentation. %bcond_without docs -%ifarch x86_64 aarch64 +# Default: Always run valgrind tests if there is architecture support. +%ifarch %{valgrind_arches} %bcond_without valgrind %else %bcond_with valgrind %endif - -%global __filter_GLIBC_PRIVATE 1 -%global __provides_exclude ^libc_malloc_debug\\.so.*$ -%global locale_rx eo syr *_* +# Restrict %%{valgrind_arches} further in case there are problems with +# the smoke test. +%if %{with valgrind} +%ifarch ppc64 ppc64p7 +# The valgrind smoke test does not work on ppc64, ppc64p7 (bug 1273103). +%undefine with_valgrind +%endif +%endif %if %{with bootstrap} +# Disable benchtests, -Werror, docs, and valgrind if we're bootstrapping %undefine with_benchtests %undefine with_werror %undefine with_docs %undefine with_valgrind %endif +############################################################################## +# Auxiliary arches are those arches that can be built in addition +# to the core supported arches. You either install an auxarch or +# you install the base arch, not both. You would do this in order +# to provide a more optimized version of the package for your arch. +%define auxarches athlon alphaev6 -%undefine _auto_set_build_flags -%undefine _unique_build_ids -%undefine __brp_ldconfig -%define _no_recompute_build_ids 1 -%define enablekernel 3.2 -%define target %{_target_cpu}-anolis-linux -%define glibc_make_flags_as ASFLAGS="-g -Wa,--generate-missing-build-notes=yes" -%define glibc_make_flags %{glibc_make_flags_as} +# Only some architectures have static PIE support. +%define pie_arches %{ix86} x86_64 -%define glibc_post_funcs() \ -function post_exec (program, ...) \ - local pid = posix.fork () \ - if pid == 0 then \ - posix.exec (program, ...) \ - assert (nil) \ - elseif pid > 0 then \ - posix.wait (pid) \ - end \ -end \ -\ -function update_gconv_modules_cache () \ - local iconv_dir = "%{_libdir}/gconv" \ - local iconv_cache = iconv_dir .. "/gconv-modules.cache" \ - local iconv_modules = iconv_dir .. "/gconv-modules" \ - if (posix.utime (iconv_modules) == 0) then \ - if (posix.utime (iconv_cache) == 0) then \ - post_exec ("%{_prefix}/sbin/iconvconfig", \ - "-o", iconv_cache, \ - "--nostdlib", \ - iconv_dir) \ - else \ - io.stdout:write ("Error: Missing " .. iconv_cache .. " file.\n") \ - end \ - end \ -end \ -%{nil} +# Build the POWER9 runtime on POWER, but only for downstream. +%ifarch ppc64le +%define buildpower9 0%{?rhel} > 0 +%else +%define buildpower9 0 +%endif +# RHEL 8 does not have a working %%dnl macro. +%define comment() %{nil} + +############################################################################## +# Any architecture/kernel combination that supports running 32-bit and 64-bit +# code in userspace is considered a biarch arch. +%define biarcharches %{ix86} x86_64 %{power64} s390 s390x +############################################################################## +# If the debug information is split into two packages, the core debuginfo +# pacakge and the common debuginfo package then the arch should be listed +# here. If the arch is not listed here then a single core debuginfo package +# will be created for the architecture. +%define debuginfocommonarches %{biarcharches} alpha alphaev6 +############################################################################## +# %%package glibc - The GNU C Library (glibc) core package. +############################################################################## Summary: The GNU libc libraries Name: glibc -Version: 2.38 -Release: %{anolis_release}%{?dist} +Version: %{glibcversion} +Release: %{glibcrelease} + +# In general, GPLv2+ is used by programs, LGPLv2+ is used for +# libraries. +# +# LGPLv2+ with exceptions is used for things that are linked directly +# into dynamically linked programs and shared libraries (e.g. crt +# files, lib*_nonshared.a). Historically, this exception also applies +# to parts of libio. +# +# GPLv2+ with exceptions is used for parts of the Arm unwinder. +# +# GFDL is used for the documentation. +# +# Some other licenses are used in various places (BSD, Inner-Net, +# ISC, Public Domain). +# +# HSRL and FSFAP are only used in test cases, which currently do not +# ship in binary RPMs, so they are not listed here. MIT is used for +# scripts/install-sh, which does not ship, either. +# +# GPLv3+ is used by manual/texinfo.tex, which we do not use. +# +# LGPLv3+ is used by some Hurd code, which we do not build. +# +# LGPLv2 is used in one place (time/timespec_get.c, by mistake), but +# it is not actually compiled, so it does not matter for libraries. License: LGPLv2+ and LGPLv2+ with exceptions and GPLv2+ and GPLv2+ with exceptions and BSD and Inner-Net and ISC and Public Domain and GFDL URL: http://www.gnu.org/software/glibc/ -Source0: https://ftp.gnu.org/gnu/glibc/%{name}-%{version}.tar.xz -Source1: bench.mk -Source2: glibc-bench-compare -Source10: wrap-find-debuginfo.sh -Source20: langpacklist +Source0: %{?glibc_release_url}%{glibcsrcdir}.tar.xz +Source1: build-locale-archive.c +Source4: nscd.conf +Source8: power6emul.c +Source9: bench.mk +Source10: glibc-bench-compare +# A copy of localedata/SUPPORTED in the Source0 tarball. The +# SUPPORTED file is used below to generate the list of locale +# packages, using a Lua snippet. +Source11: SUPPORTED -%{lua: -local wrapper = rpm.expand("%{SOURCE10}") -local sysroot = rpm.expand("%{buildroot}") -local original = rpm.expand("%{macrobody:__debug_install_post}") --- Strip leading newline. It confuses the macro redefinition. --- Avoid embedded newlines that confuse the macro definition. -original = original:match("^%s*(.-)%s*$"):gsub("\\\n", "") -rpm.define("__debug_install_post bash " .. wrapper - .. " " .. sysroot .. " " .. original) -} +# Include in the source RPM for reference. +Source12: ChangeLog.old +############################################################################## +# Patches: +# - See each individual patch file for origin and upstream status. +# - For new patches follow template.patch format. +############################################################################## +Patch2: glibc-fedora-nscd.patch +Patch3: glibc-rh697421.patch +Patch4: glibc-fedora-linux-tcsetattr.patch +Patch5: glibc-rh741105.patch +Patch6: glibc-fedora-localedef.patch +Patch7: glibc-fedora-nis-rh188246.patch +Patch8: glibc-fedora-manual-dircategory.patch +Patch9: glibc-rh827510.patch +Patch10: glibc-fedora-locarchive.patch +Patch11: glibc-fedora-streams-rh436349.patch +Patch12: glibc-rh819430.patch +Patch13: glibc-fedora-localedata-rh61908.patch +Patch14: glibc-fedora-__libc_multiple_libcs.patch +Patch15: glibc-rh1070416.patch +Patch16: glibc-nscd-sysconfig.patch +Patch17: glibc-cs-path.patch +Patch18: glibc-c-utf8-locale.patch +Patch23: glibc-python3.patch +Patch24: glibc-with-nonshared-cflags.patch +Patch25: glibc-asflags.patch +Patch27: glibc-rh1614253.patch +Patch28: glibc-rh1577365.patch +Patch29: glibc-rh1615781.patch +Patch30: glibc-rh1615784.patch +Patch31: glibc-rh1615790.patch +Patch32: glibc-rh1622675.patch +Patch33: glibc-rh1622678-1.patch +Patch34: glibc-rh1622678-2.patch +Patch35: glibc-rh1631293-1.patch +Patch36: glibc-rh1631293-2.patch +Patch37: glibc-rh1623536.patch +Patch38: glibc-rh1631722.patch +Patch39: glibc-rh1631730.patch +Patch40: glibc-rh1623536-2.patch +Patch41: glibc-rh1614979.patch +Patch42: glibc-rh1645593.patch +Patch43: glibc-rh1645596.patch +Patch44: glibc-rh1645604.patch +Patch45: glibc-rh1646379.patch +Patch46: glibc-rh1645601.patch +Patch52: glibc-rh1638523-1.patch +Patch47: glibc-rh1638523-2.patch +Patch48: glibc-rh1638523-3.patch +Patch49: glibc-rh1638523-4.patch +Patch50: glibc-rh1638523-5.patch +Patch51: glibc-rh1638523-6.patch +Patch53: glibc-rh1641982.patch +Patch54: glibc-rh1645597.patch +Patch55: glibc-rh1650560-1.patch +Patch56: glibc-rh1650560-2.patch +Patch57: glibc-rh1650563.patch +Patch58: glibc-rh1650566.patch +Patch59: glibc-rh1650571.patch +Patch60: glibc-rh1638520.patch +Patch61: glibc-rh1651274.patch +Patch62: glibc-rh1654010-1.patch +Patch63: glibc-rh1635779.patch +Patch64: glibc-rh1654010-2.patch +Patch65: glibc-rh1654010-3.patch +Patch66: glibc-rh1654010-4.patch +Patch67: glibc-rh1654010-5.patch +Patch68: glibc-rh1654010-6.patch +Patch69: glibc-rh1642094-1.patch +Patch70: glibc-rh1642094-2.patch +Patch71: glibc-rh1642094-3.patch +Patch72: glibc-rh1654872-1.patch +Patch73: glibc-rh1654872-2.patch +Patch74: glibc-rh1651283-1.patch +Patch75: glibc-rh1662843-1.patch +Patch76: glibc-rh1662843-2.patch +Patch77: glibc-rh1623537.patch +Patch78: glibc-rh1577438.patch +Patch79: glibc-rh1664408.patch +Patch80: glibc-rh1651742.patch +Patch81: glibc-rh1672773.patch +Patch82: glibc-rh1651283-2.patch +Patch83: glibc-rh1651283-3.patch +Patch84: glibc-rh1651283-4.patch +Patch85: glibc-rh1651283-5.patch +Patch86: glibc-rh1651283-6.patch +Patch87: glibc-rh1651283-7.patch +Patch88: glibc-rh1659293-1.patch +Patch89: glibc-rh1659293-2.patch +Patch90: glibc-rh1639343-1.patch +Patch91: glibc-rh1639343-2.patch +Patch92: glibc-rh1639343-3.patch +Patch93: glibc-rh1639343-4.patch +Patch94: glibc-rh1639343-5.patch +Patch95: glibc-rh1639343-6.patch +Patch96: glibc-rh1663035.patch +Patch97: glibc-rh1658901.patch +Patch98: glibc-rh1659512-1.patch +Patch99: glibc-rh1659512-2.patch +Patch100: glibc-rh1659438-1.patch +Patch101: glibc-rh1659438-2.patch +Patch102: glibc-rh1659438-3.patch +Patch103: glibc-rh1659438-4.patch +Patch104: glibc-rh1659438-5.patch +Patch105: glibc-rh1659438-6.patch +Patch106: glibc-rh1659438-7.patch +Patch107: glibc-rh1659438-8.patch +Patch108: glibc-rh1659438-9.patch +Patch109: glibc-rh1659438-10.patch +Patch110: glibc-rh1659438-11.patch +Patch111: glibc-rh1659438-12.patch +Patch112: glibc-rh1659438-13.patch +Patch113: glibc-rh1659438-14.patch +Patch114: glibc-rh1659438-15.patch +Patch115: glibc-rh1659438-16.patch +Patch116: glibc-rh1659438-17.patch +Patch117: glibc-rh1659438-18.patch +Patch118: glibc-rh1659438-19.patch +Patch119: glibc-rh1659438-20.patch +Patch120: glibc-rh1659438-21.patch +Patch121: glibc-rh1659438-22.patch +Patch122: glibc-rh1659438-23.patch +Patch123: glibc-rh1659438-24.patch +Patch124: glibc-rh1659438-25.patch +Patch125: glibc-rh1659438-26.patch +Patch126: glibc-rh1659438-27.patch +Patch127: glibc-rh1659438-28.patch +Patch128: glibc-rh1659438-29.patch +Patch129: glibc-rh1659438-30.patch +Patch130: glibc-rh1659438-31.patch +Patch131: glibc-rh1659438-32.patch +Patch132: glibc-rh1659438-33.patch +Patch133: glibc-rh1659438-34.patch +Patch134: glibc-rh1659438-35.patch +Patch135: glibc-rh1659438-36.patch +Patch136: glibc-rh1659438-37.patch +Patch137: glibc-rh1659438-38.patch +Patch138: glibc-rh1659438-39.patch +Patch139: glibc-rh1659438-40.patch +Patch140: glibc-rh1659438-41.patch +Patch141: glibc-rh1659438-42.patch +Patch142: glibc-rh1659438-43.patch +Patch143: glibc-rh1659438-44.patch +Patch144: glibc-rh1659438-45.patch +Patch145: glibc-rh1659438-46.patch +Patch146: glibc-rh1659438-47.patch +Patch147: glibc-rh1659438-48.patch +Patch148: glibc-rh1659438-49.patch +Patch149: glibc-rh1659438-50.patch +Patch150: glibc-rh1659438-51.patch +Patch151: glibc-rh1659438-52.patch +Patch152: glibc-rh1659438-53.patch +Patch153: glibc-rh1659438-54.patch +Patch154: glibc-rh1659438-55.patch +Patch155: glibc-rh1659438-56.patch +Patch156: glibc-rh1659438-57.patch +Patch157: glibc-rh1659438-58.patch +Patch158: glibc-rh1659438-59.patch +Patch159: glibc-rh1659438-60.patch +Patch160: glibc-rh1659438-61.patch +Patch161: glibc-rh1659438-62.patch +Patch162: glibc-rh1702539-1.patch +Patch163: glibc-rh1702539-2.patch +Patch164: glibc-rh1701605-1.patch +Patch165: glibc-rh1701605-2.patch +Patch166: glibc-rh1691528-1.patch +Patch167: glibc-rh1691528-2.patch +Patch168: glibc-rh1706777.patch +Patch169: glibc-rh1710478.patch +Patch170: glibc-rh1670043-1.patch +Patch171: glibc-rh1670043-2.patch +Patch172: glibc-rh1710894.patch +Patch173: glibc-rh1699194-1.patch +Patch174: glibc-rh1699194-2.patch +Patch175: glibc-rh1699194-3.patch +Patch176: glibc-rh1699194-4.patch +Patch177: glibc-rh1727241-1.patch +Patch178: glibc-rh1727241-2.patch +Patch179: glibc-rh1727241-3.patch +Patch180: glibc-rh1717438.patch +Patch181: glibc-rh1727152.patch +Patch182: glibc-rh1724975.patch +Patch183: glibc-rh1722215.patch +Patch184: glibc-rh1764234-1.patch +Patch185: glibc-rh1764234-2.patch +Patch186: glibc-rh1764234-3.patch +Patch187: glibc-rh1764234-4.patch +Patch188: glibc-rh1764234-5.patch +Patch189: glibc-rh1764234-6.patch +Patch190: glibc-rh1764234-7.patch +Patch191: glibc-rh1764234-8.patch +Patch192: glibc-rh1747505-1.patch +Patch193: glibc-rh1747505-2.patch +Patch194: glibc-rh1747505-3.patch +Patch195: glibc-rh1747505-4.patch +Patch196: glibc-rh1747453.patch +Patch197: glibc-rh1764241.patch +Patch198: glibc-rh1746933-1.patch +Patch199: glibc-rh1746933-2.patch +Patch200: glibc-rh1746933-3.patch +Patch201: glibc-rh1735747-1.patch +Patch202: glibc-rh1735747-2.patch +Patch203: glibc-rh1764226-1.patch +Patch204: glibc-rh1764226-2.patch +Patch205: glibc-rh1764226-3.patch +Patch206: glibc-rh1764218-1.patch +Patch207: glibc-rh1764218-2.patch +Patch208: glibc-rh1764218-3.patch +Patch209: glibc-rh1682954.patch +Patch210: glibc-rh1746928.patch +Patch211: glibc-rh1747502.patch +Patch212: glibc-rh1747502-1.patch +Patch213: glibc-rh1747502-2.patch +Patch214: glibc-rh1747502-3.patch +Patch215: glibc-rh1747502-4.patch +Patch216: glibc-rh1747502-5.patch +Patch217: glibc-rh1747502-6.patch +Patch218: glibc-rh1747502-7.patch +Patch219: glibc-rh1747502-8.patch +Patch220: glibc-rh1747502-9.patch +Patch221: glibc-rh1726638-1.patch +Patch222: glibc-rh1726638-2.patch +Patch223: glibc-rh1726638-3.patch +Patch224: glibc-rh1764238-1.patch +Patch225: glibc-rh1764238-2.patch +Patch226: glibc-rh1764242.patch +Patch227: glibc-rh1769304.patch +Patch228: glibc-rh1749439-1.patch +Patch229: glibc-rh1749439-2.patch +Patch230: glibc-rh1749439-3.patch +Patch231: glibc-rh1749439-4.patch +Patch232: glibc-rh1749439-5.patch +Patch233: glibc-rh1749439-6.patch +Patch234: glibc-rh1749439-7.patch +Patch235: glibc-rh1749439-8.patch +Patch236: glibc-rh1749439-9.patch +Patch237: glibc-rh1749439-10.patch +Patch238: glibc-rh1749439-11.patch +Patch239: glibc-rh1749439-12.patch +Patch240: glibc-rh1749439-13.patch +Patch241: glibc-rh1764231-1.patch +Patch242: glibc-rh1764231-2.patch +Patch243: glibc-rh1764235.patch +Patch244: glibc-rh1361965.patch +Patch245: glibc-rh1764223.patch +Patch246: glibc-rh1764214.patch +Patch247: glibc-rh1774021.patch +Patch248: glibc-rh1775294.patch +Patch249: glibc-rh1777241.patch +Patch250: glibc-rh1410154-1.patch +Patch251: glibc-rh1410154-2.patch +Patch252: glibc-rh1410154-3.patch +Patch253: glibc-rh1410154-4.patch +Patch254: glibc-rh1410154-5.patch +Patch255: glibc-rh1410154-6.patch +Patch256: glibc-rh1410154-7.patch +Patch257: glibc-rh1410154-8.patch +Patch258: glibc-rh1410154-9.patch +Patch259: glibc-rh1410154-10.patch +Patch260: glibc-rh1410154-11.patch +Patch261: glibc-rh1410154-12.patch +Patch262: glibc-rh1410154-13.patch +Patch263: glibc-rh1410154-14.patch +Patch264: glibc-rh1410154-15.patch +Patch265: glibc-rh1410154-16.patch +Patch266: glibc-rh1810142-1.patch +Patch267: glibc-rh1810142-2.patch +Patch268: glibc-rh1810142-3.patch +Patch269: glibc-rh1810142-4.patch +Patch270: glibc-rh1810142-5.patch +Patch271: glibc-rh1810142-6.patch +Patch272: glibc-rh1743445-1.patch +Patch273: glibc-rh1743445-2.patch +Patch274: glibc-rh1780204-01.patch +Patch275: glibc-rh1780204-02.patch +Patch276: glibc-rh1780204-03.patch +Patch277: glibc-rh1780204-04.patch +Patch278: glibc-rh1780204-05.patch +Patch279: glibc-rh1780204-06.patch +Patch280: glibc-rh1780204-07.patch +Patch281: glibc-rh1780204-08.patch +Patch282: glibc-rh1780204-09.patch +Patch283: glibc-rh1780204-10.patch +Patch284: glibc-rh1780204-11.patch +Patch285: glibc-rh1780204-12.patch +Patch286: glibc-rh1780204-13.patch +Patch287: glibc-rh1780204-14.patch +Patch288: glibc-rh1780204-15.patch +Patch289: glibc-rh1780204-16.patch +Patch290: glibc-rh1780204-17.patch +Patch291: glibc-rh1780204-18.patch +Patch292: glibc-rh1780204-19.patch +Patch293: glibc-rh1780204-20.patch +Patch294: glibc-rh1780204-21.patch +Patch295: glibc-rh1780204-22.patch +Patch296: glibc-rh1780204-23.patch +Patch297: glibc-rh1780204-24.patch +Patch298: glibc-rh1780204-25.patch +Patch299: glibc-rh1780204-26.patch +Patch300: glibc-rh1780204-27.patch +Patch301: glibc-rh1780204-28.patch +Patch302: glibc-rh1784519.patch +Patch303: glibc-rh1775819.patch +Patch304: glibc-rh1774114.patch +Patch305: glibc-rh1812756-1.patch +Patch306: glibc-rh1812756-2.patch +Patch307: glibc-rh1812756-3.patch +Patch308: glibc-rh1757354.patch +Patch309: glibc-rh1784520.patch +Patch310: glibc-rh1784525.patch +Patch311: glibc-rh1810146.patch +Patch312: glibc-rh1810223-1.patch +Patch313: glibc-rh1810223-2.patch +Patch314: glibc-rh1811796-1.patch +Patch315: glibc-rh1811796-2.patch +Patch316: glibc-rh1813398.patch +Patch317: glibc-rh1813399.patch +Patch318: glibc-rh1810224-1.patch +Patch319: glibc-rh1810224-2.patch +Patch320: glibc-rh1810224-3.patch +Patch321: glibc-rh1810224-4.patch +Patch322: glibc-rh1783303-1.patch +Patch323: glibc-rh1783303-2.patch +Patch324: glibc-rh1783303-3.patch +Patch325: glibc-rh1783303-4.patch +Patch326: glibc-rh1783303-5.patch +Patch327: glibc-rh1783303-6.patch +Patch328: glibc-rh1783303-7.patch +Patch329: glibc-rh1783303-8.patch +Patch330: glibc-rh1783303-9.patch +Patch331: glibc-rh1783303-10.patch +Patch332: glibc-rh1783303-11.patch +Patch333: glibc-rh1783303-12.patch +Patch334: glibc-rh1783303-13.patch +Patch335: glibc-rh1783303-14.patch +Patch336: glibc-rh1783303-15.patch +Patch337: glibc-rh1783303-16.patch +Patch338: glibc-rh1783303-17.patch +Patch339: glibc-rh1783303-18.patch +Patch340: glibc-rh1642150-1.patch +Patch341: glibc-rh1642150-2.patch +Patch342: glibc-rh1642150-3.patch +Patch343: glibc-rh1774115.patch +Patch344: glibc-rh1780204-29.patch +Patch345: glibc-rh1748197-1.patch +Patch346: glibc-rh1748197-2.patch +Patch347: glibc-rh1748197-3.patch +Patch348: glibc-rh1748197-4.patch +Patch349: glibc-rh1748197-5.patch +Patch350: glibc-rh1748197-6.patch +Patch351: glibc-rh1748197-7.patch +Patch352: glibc-rh1642150-4.patch +Patch353: glibc-rh1836867.patch +Patch354: glibc-rh1821531-1.patch +Patch355: glibc-rh1821531-2.patch +Patch356: glibc-rh1845098-1.patch +Patch357: glibc-rh1845098-2.patch +Patch358: glibc-rh1845098-3.patch +Patch359: glibc-rh1871387-1.patch +Patch360: glibc-rh1871387-2.patch +Patch361: glibc-rh1871387-3.patch +Patch362: glibc-rh1871387-4.patch +Patch363: glibc-rh1871387-5.patch +Patch364: glibc-rh1871387-6.patch +Patch365: glibc-rh1871394-1.patch +Patch366: glibc-rh1871394-2.patch +Patch367: glibc-rh1871394-3.patch +Patch368: glibc-rh1871395-1.patch +Patch369: glibc-rh1871395-2.patch +Patch370: glibc-rh1871397-1.patch +Patch371: glibc-rh1871397-2.patch +Patch372: glibc-rh1871397-3.patch +Patch373: glibc-rh1871397-4.patch +Patch374: glibc-rh1871397-5.patch +Patch375: glibc-rh1871397-6.patch +Patch376: glibc-rh1871397-7.patch +Patch377: glibc-rh1871397-8.patch +Patch378: glibc-rh1871397-9.patch +Patch379: glibc-rh1871397-10.patch +Patch380: glibc-rh1871397-11.patch +Patch381: glibc-rh1880670.patch +Patch382: glibc-rh1868106-1.patch +Patch383: glibc-rh1868106-2.patch +Patch384: glibc-rh1868106-3.patch +Patch385: glibc-rh1868106-4.patch +Patch386: glibc-rh1868106-5.patch +Patch387: glibc-rh1868106-6.patch +Patch388: glibc-rh1856398.patch +Patch389: glibc-rh1880670-2.patch +Patch390: glibc-rh1704868-1.patch +Patch391: glibc-rh1704868-2.patch +Patch392: glibc-rh1704868-3.patch +Patch393: glibc-rh1704868-4.patch +Patch394: glibc-rh1704868-5.patch +Patch395: glibc-rh1893662-1.patch +Patch396: glibc-rh1893662-2.patch +Patch397: glibc-rh1855790-1.patch +Patch398: glibc-rh1855790-2.patch +Patch399: glibc-rh1855790-3.patch +Patch400: glibc-rh1855790-4.patch +Patch401: glibc-rh1855790-5.patch +Patch402: glibc-rh1855790-6.patch +Patch403: glibc-rh1855790-7.patch +Patch404: glibc-rh1855790-8.patch +Patch405: glibc-rh1855790-9.patch +Patch406: glibc-rh1855790-10.patch +Patch407: glibc-rh1855790-11.patch +Patch408: glibc-rh1817513-1.patch +Patch409: glibc-rh1817513-2.patch +Patch410: glibc-rh1817513-3.patch +Patch411: glibc-rh1817513-4.patch +Patch412: glibc-rh1817513-5.patch +Patch413: glibc-rh1817513-6.patch +Patch414: glibc-rh1817513-7.patch +Patch415: glibc-rh1817513-8.patch +Patch416: glibc-rh1817513-9.patch +Patch417: glibc-rh1817513-10.patch +Patch418: glibc-rh1817513-11.patch +Patch419: glibc-rh1817513-12.patch +Patch420: glibc-rh1817513-13.patch +Patch421: glibc-rh1817513-14.patch +Patch422: glibc-rh1817513-15.patch +Patch423: glibc-rh1817513-16.patch +Patch424: glibc-rh1817513-17.patch +Patch425: glibc-rh1817513-18.patch +Patch426: glibc-rh1817513-19.patch +Patch427: glibc-rh1817513-20.patch +Patch428: glibc-rh1817513-21.patch +Patch429: glibc-rh1817513-22.patch +Patch430: glibc-rh1817513-23.patch +Patch431: glibc-rh1817513-24.patch +Patch432: glibc-rh1817513-25.patch +Patch433: glibc-rh1817513-26.patch +Patch434: glibc-rh1817513-27.patch +Patch435: glibc-rh1817513-28.patch +Patch436: glibc-rh1817513-29.patch +Patch437: glibc-rh1817513-30.patch +Patch438: glibc-rh1817513-31.patch +Patch439: glibc-rh1817513-32.patch +Patch440: glibc-rh1817513-33.patch +Patch441: glibc-rh1817513-34.patch +Patch442: glibc-rh1817513-35.patch +Patch443: glibc-rh1817513-36.patch +Patch444: glibc-rh1817513-37.patch +Patch445: glibc-rh1817513-38.patch +Patch446: glibc-rh1817513-39.patch +Patch447: glibc-rh1817513-40.patch +Patch448: glibc-rh1817513-41.patch +Patch449: glibc-rh1817513-42.patch +Patch450: glibc-rh1817513-43.patch +Patch451: glibc-rh1817513-44.patch +Patch452: glibc-rh1817513-45.patch +Patch453: glibc-rh1817513-46.patch +Patch454: glibc-rh1817513-47.patch +Patch455: glibc-rh1817513-48.patch +Patch456: glibc-rh1817513-49.patch +Patch457: glibc-rh1817513-50.patch +Patch458: glibc-rh1817513-51.patch +Patch459: glibc-rh1817513-52.patch +Patch460: glibc-rh1817513-53.patch +Patch461: glibc-rh1817513-54.patch +Patch462: glibc-rh1817513-55.patch +Patch463: glibc-rh1817513-56.patch +Patch464: glibc-rh1817513-57.patch +Patch465: glibc-rh1817513-58.patch +Patch466: glibc-rh1817513-59.patch +Patch467: glibc-rh1817513-60.patch +Patch468: glibc-rh1817513-61.patch +Patch469: glibc-rh1817513-62.patch +Patch470: glibc-rh1817513-63.patch +Patch471: glibc-rh1817513-64.patch +Patch472: glibc-rh1817513-65.patch +Patch473: glibc-rh1817513-66.patch +Patch474: glibc-rh1817513-67.patch +Patch475: glibc-rh1817513-68.patch +Patch476: glibc-rh1817513-69.patch +Patch477: glibc-rh1817513-70.patch +Patch478: glibc-rh1817513-71.patch +Patch479: glibc-rh1817513-72.patch +Patch480: glibc-rh1817513-73.patch +Patch481: glibc-rh1817513-74.patch +Patch482: glibc-rh1817513-75.patch +Patch483: glibc-rh1817513-76.patch +Patch484: glibc-rh1817513-77.patch +Patch485: glibc-rh1817513-78.patch +Patch486: glibc-rh1817513-79.patch +Patch487: glibc-rh1817513-80.patch +Patch488: glibc-rh1817513-81.patch +Patch489: glibc-rh1817513-82.patch +Patch490: glibc-rh1817513-83.patch +Patch491: glibc-rh1817513-84.patch +Patch492: glibc-rh1817513-85.patch +Patch493: glibc-rh1817513-86.patch +Patch494: glibc-rh1817513-87.patch +Patch495: glibc-rh1817513-88.patch +Patch496: glibc-rh1817513-89.patch +Patch497: glibc-rh1817513-90.patch +Patch498: glibc-rh1817513-91.patch +Patch499: glibc-rh1817513-92.patch +Patch500: glibc-rh1817513-93.patch +Patch501: glibc-rh1817513-94.patch +Patch502: glibc-rh1817513-95.patch +Patch503: glibc-rh1817513-96.patch +Patch504: glibc-rh1817513-97.patch +Patch505: glibc-rh1817513-98.patch +Patch506: glibc-rh1817513-99.patch +Patch507: glibc-rh1817513-100.patch +Patch508: glibc-rh1817513-101.patch +Patch509: glibc-rh1817513-102.patch +Patch510: glibc-rh1817513-103.patch +Patch511: glibc-rh1817513-104.patch +Patch512: glibc-rh1817513-105.patch +Patch513: glibc-rh1817513-106.patch +Patch514: glibc-rh1817513-107.patch +Patch515: glibc-rh1817513-108.patch +Patch516: glibc-rh1817513-109.patch +Patch517: glibc-rh1817513-110.patch +Patch518: glibc-rh1817513-111.patch +Patch519: glibc-rh1817513-112.patch +Patch520: glibc-rh1817513-113.patch +Patch521: glibc-rh1817513-114.patch +Patch522: glibc-rh1817513-115.patch +Patch523: glibc-rh1817513-116.patch +Patch524: glibc-rh1817513-117.patch +Patch525: glibc-rh1817513-118.patch +Patch526: glibc-rh1817513-119.patch +Patch527: glibc-rh1817513-120.patch +Patch528: glibc-rh1817513-121.patch +Patch529: glibc-rh1817513-122.patch +Patch530: glibc-rh1817513-123.patch +Patch531: glibc-rh1817513-124.patch +Patch532: glibc-rh1817513-125.patch +Patch533: glibc-rh1817513-126.patch +Patch534: glibc-rh1817513-127.patch +Patch535: glibc-rh1817513-128.patch +Patch536: glibc-rh1817513-129.patch +Patch537: glibc-rh1817513-130.patch +Patch538: glibc-rh1817513-131.patch +Patch539: glibc-rh1817513-132.patch +Patch540: glibc-rh1882466-1.patch +Patch541: glibc-rh1882466-2.patch +Patch542: glibc-rh1882466-3.patch +Patch543: glibc-rh1817513-133.patch +Patch544: glibc-rh1912544.patch +Patch545: glibc-rh1918115.patch +Patch546: glibc-rh1924919.patch +Patch547: glibc-rh1932770.patch +Patch548: glibc-rh1936864.patch +Patch549: glibc-rh1871386-1.patch +Patch550: glibc-rh1871386-2.patch +Patch551: glibc-rh1871386-3.patch +Patch552: glibc-rh1871386-4.patch +Patch553: glibc-rh1871386-5.patch +Patch554: glibc-rh1871386-6.patch +Patch555: glibc-rh1871386-7.patch +Patch556: glibc-rh1912670-1.patch +Patch557: glibc-rh1912670-2.patch +Patch558: glibc-rh1912670-3.patch +Patch559: glibc-rh1912670-4.patch +Patch560: glibc-rh1912670-5.patch +Patch561: glibc-rh1930302-1.patch +Patch562: glibc-rh1930302-2.patch +Patch563: glibc-rh1927877.patch +Patch564: glibc-rh1918719-1.patch +Patch565: glibc-rh1918719-2.patch +Patch566: glibc-rh1918719-3.patch +Patch567: glibc-rh1934155-1.patch +Patch568: glibc-rh1934155-2.patch +Patch569: glibc-rh1934155-3.patch +Patch570: glibc-rh1934155-4.patch +Patch571: glibc-rh1934155-5.patch +Patch572: glibc-rh1934155-6.patch +Patch573: glibc-rh1956357-1.patch +Patch574: glibc-rh1956357-2.patch +Patch575: glibc-rh1956357-3.patch +Patch576: glibc-rh1956357-4.patch +Patch577: glibc-rh1956357-5.patch +Patch578: glibc-rh1956357-6.patch +Patch579: glibc-rh1956357-7.patch +Patch580: glibc-rh1956357-8.patch +Patch581: glibc-rh1979127.patch +Patch582: glibc-rh1966472-1.patch +Patch583: glibc-rh1966472-2.patch +Patch584: glibc-rh1966472-3.patch +Patch585: glibc-rh1966472-4.patch +Patch586: glibc-rh2032280-1.patch +Patch587: glibc-rh2032280-2.patch +Patch588: glibc-rh2032280-3.patch +Patch589: glibc-rh2032280-4.patch +Patch590: glibc-rh2032280-5.patch +Patch591: glibc-rh2032280-6.patch +Patch592: glibc-rh2032280-7.patch +Patch593: glibc-rh2045062-1.patch +Patch594: glibc-rh2045062-2.patch +Patch595: glibc-rh2045062-3.patch +Patch596: glibc-rh2045062-4.patch +Patch597: glibc-rh2045062-5.patch -Patch1: glibc-no-archive-for-localedef.patch -Patch2: glibc-place-info-into-Libraries-category.patch -Patch3: glibc-nscd-add-syslog-target-dependency.patch -Patch4: glibc-fix-newlocale-error-return.patch -Patch5: glibc-cs-path.patch -Patch6: glibc-python3.patch -Patch7: glibc-deprecated-selinux-makedb.patch -# https://sourceware.org/bugzilla/show_bug.cgi?id=30243 -Patch8: glibc-gb18030-2022-bug30243.patch +############################################################################## +# Continued list of core "glibc" package information: +############################################################################## +Obsoletes: glibc-profile < 2.4 +Provides: ldconfig -Patch0183: 0083-CVE-2023-4527.patch -Patch0184: 0084-CVE-2023-4806.patch -Patch0185: 0085-CVE-2023-5156.patch -Patch0186: 1086-CVE-2023-4911.patch -Patch0187: 0087-CVE-2023-6246.patch -Patch0188: 0088-CVE-2023-6779.patch -Patch0189: 0089-CVE-2023-6780.patch -Patch0190: 0090-CVE-2024-2961.patch +# The dynamic linker supports DT_GNU_HASH +Provides: rtld(GNU_HASH) +Requires: glibc-common = %{version}-%{release} -# Part 3000 ~ 4999 -Patch3000: LoongArch-Redefine-macro-LEAF-ENTRY.patch -Patch3001: LoongArch-Add-minuimum-binutils-required-version.patch -Patch3002: Loongarch-Add-ifunc-support-and-add-different-versio.patch -Patch3003: elf-Add-new-LoongArch-reloc-types-101-to-108-into-el.patch -Patch3004: LoongArch-elf-Add-new-LoongArch-reloc-types-109-into.patch -Patch3005: Loongarch-Add-ifunc-support-for-strchr-aligned-lsx-l.patch -Patch3006: Loongarch-Add-ifunc-support-for-memcpy-aligned-unali.patch -Patch3007: LoongArch-Add-ifunc-support-for-strnlen-aligned-lsx-.patch -Patch3008: LoongArch-Add-ifunc-support-for-strcmp-aligned-lsx.patch -Patch3009: LoongArch-Add-ifunc-support-for-strncmp-aligned-lsx.patch -Patch3010: LoongArch-Remove-support-code-for-old-linker-in-star.patch -Patch3011: LoongArch-Micro-optimize-LD_PCREL.patch -Patch3012: LoongArch-Add-ifunc-support-for-rawmemchr-aligned-ls.patch -Patch3013: LoongArch-Add-ifunc-support-for-memchr-aligned-lsx-l.patch -Patch3014: LoongArch-Add-ifunc-support-for-memrchr-lsx-lasx.patch -Patch3015: LoongArch-Add-ifunc-support-for-memset-aligned-unali.patch -Patch3016: LoongArch-Add-ifunc-support-for-memcmp-aligned-lsx-l.patch -Patch3017: LoongArch-Change-loongarch-to-LoongArch-in-comments.patch -Patch3018: LoongArch-Add-lasx-lsx-support-for-_dl_runtime_profi.patch -Patch3019: LoongArch-Replace-deprecated-v0-with-a0-to-eliminate.patch -Patch3020: LoongArch-Add-ifunc-support-for-strcpy-stpcpy-aligne.patch -Patch3021: LoongArch-Add-ifunc-support-for-strrchr-aligned-lsx-.patch -Patch3022: LoongArch-Change-to-put-magic-number-to-.rodata-sect.patch -Patch3023: LoongArch-Add-glibc.cpu.hwcap-support.patch -Patch3024: Revert-LoongArch-Add-glibc.cpu.hwcap-support.patch -Patch3025: LoongArch-Unify-Register-Names.patch -Patch3026: LoongArch-Update-hwcap.h-to-sync-with-LoongArch-kern.patch -Patch3027: linux-Sync-Linux-6.6-elf.h.patch -Patch3028: Decrease-value-of-arch_minimum_kernel-with-LoongArch.patch +# Various components (regex, glob) have been imported from gnulib. +Provides: bundled(gnulib) -BuildRequires: audit-libs-devel >= 1.1.3 libcap-devel systemtap-sdt-devel -BuildRequires: procps-ng util-linux gawk sed >= 3.95 gettext -BuildRequires: python3 python3-devel -BuildRequires: gcc >= 7.2.1 -BuildRequires: make >= 4.0 bison >= 2.7 binutils >= 2.30 -%if %{with valgrind} -BuildRequires: valgrind -%endif -%if %{without bootstrap} -BuildRequires: gd-devel libpng-devel zlib-devel libselinux-devel >= 1.33.4 -%if %{with testsuite} -BuildRequires: gcc-c++ libstdc++-static glibc-static libidn2 perl-interpreter -%endif -%endif - -Provides: ldconfig rtld(GNU_HASH) bundled(gnulib) - -Requires: glibc-common = %{EVR} -Requires: basesystem libgcc -Requires: glibc-langpack = %{EVR} -Requires: (glibc-gconv-extra = %{EVR} if system-rpm-config) Requires(pre): basesystem -Suggests: glibc-minimal-langpack = %{EVR} -Recommends: glibc-gconv-extra = %{EVR} +%ifarch %{ix86} +# Automatically install the 32-bit variant if the 64-bit variant has +# been installed. This covers the case when glibc.i686 is installed +# after nss_db.x86_64. (See below for the other ordering.) +Recommends: (nss_db(x86-32) if nss_db(x86-64)) +%endif -Obsoletes: glibc-profile < 2.4 -Obsoletes: nscd < 2.35 +# This is for building auxiliary programs like memusage, nscd +# For initial glibc bootstraps it can be commented out +%if %{without bootstrap} +BuildRequires: gd-devel libpng-devel zlib-devel +%endif +%if %{with docs} +# Removing texinfo will cause check-safety.sh test to fail because it seems to +# trigger documentation generation based on dependencies. We need to fix this +# upstream in some way that doesn't depend on generating docs to validate the +# texinfo. I expect it's simply the wrong dependency for that target. +BuildRequires: texinfo >= 5.0 +%endif +%if %{without bootstrap} +BuildRequires: libselinux-devel >= 1.33.4-3 +%endif +BuildRequires: audit-libs-devel >= 1.1.3, sed >= 3.95, libcap-devel, gettext +# We need procps-ng (/bin/ps), util-linux (/bin/kill), and gawk (/bin/awk), +# but it is more flexible to require the actual programs and let rpm infer +# the packages. However, until bug 1259054 is widely fixed we avoid the +# following: +# BuildRequires: /bin/ps, /bin/kill, /bin/awk +# And use instead (which should be reverted some time in the future): +BuildRequires: procps-ng, util-linux, gawk +BuildRequires: systemtap-sdt-devel +%if %{with valgrind} +# Require valgrind for smoke testing the dynamic loader to make sure we +# have not broken valgrind. +BuildRequires: valgrind +%endif + +# We use systemd rpm macros for nscd +BuildRequires: systemd + +# We use python for the microbenchmarks and locale data regeneration +# from unicode sources (carried out manually). We choose python3 +# explicitly because it supports both use cases. On some +# distributions, python3 does not actually install /usr/bin/python3, +# so we also depend on python3-devel. +BuildRequires: python3 python3-devel + +# This is the first GCC version with -moutline-atomics (#1856398) +BuildRequires: gcc >= 8.3.1-5.2 +%define enablekernel 3.2 Conflicts: kernel < %{enablekernel} +%define target %{_target_cpu}-redhat-linux +%ifarch %{arm} +%define target %{_target_cpu}-redhat-linuxeabi +%endif +%ifarch %{power64} +%ifarch ppc64le +%define target ppc64le-redhat-linux +%else +%define target ppc64-redhat-linux +%endif +%endif + +# GNU make 4.0 introduced the -O option. +BuildRequires: make >= 4.0 + +# The intl subsystem generates a parser using bison. +BuildRequires: bison >= 2.7 + +# binutils 2.30-51 is needed for z13 support on s390x. +BuildRequires: binutils >= 2.30-51 + +# Earlier releases have broken support for IRELATIVE relocations Conflicts: prelink < 0.4.2 +%if 0%{?_enable_debug_packages} +BuildRequires: elfutils >= 0.72 +BuildRequires: rpm >= 4.2-0.56 +%endif + +%if %{without bootstrap} +%if %{with testsuite} +# The testsuite builds static C++ binaries that require a C++ compiler, +# static C++ runtime from libstdc++-static, and lastly static glibc. +BuildRequires: gcc-c++ +BuildRequires: libstdc++-static +# A configure check tests for the ability to create static C++ binaries +# before glibc is built and therefore we need a glibc-static for that +# check to pass even if we aren't going to use any of those objects to +# build the tests. +BuildRequires: glibc-static + +# libidn2 (but not libidn2-devel) is needed for testing AI_IDN/NI_IDN. +BuildRequires: libidn2 +%endif +%endif + +# Filter out all GLIBC_PRIVATE symbols since they are internal to +# the package and should not be examined by any other tool. +%global __filter_GLIBC_PRIVATE 1 + +# For language packs we have glibc require a virtual dependency +# "glibc-langpack" wich gives us at least one installed langpack. +# If no langpack providing 'glibc-langpack' was installed you'd +# get all of them, and that would make the transition from a +# system without langpacks smoother (you'd get all the locales +# installed). You would then trim that list, and the trimmed list +# is preserved. One problem is you can't have "no" locales installed, +# in that case we offer a "glibc-minimal-langpack" sub-pakcage for +# this purpose. +Requires: glibc-langpack = %{version}-%{release} +Suggests: glibc-all-langpacks = %{version}-%{release} + %description The glibc package contains standard libraries which are used by -multiple programs on the system. -In order to save disk space and memory, as well as to make upgrading easier, -common system code is kept in one place and shared between programs. -This particular package contains the most important sets of shared libraries: -the standard C library and the standard math library. -Without these two libraries, a Linux system will not function. +multiple programs on the system. In order to save disk space and +memory, as well as to make upgrading easier, common system code is +kept in one place and shared between programs. This particular package +contains the most important sets of shared libraries: the standard C +library and the standard math library. Without these two libraries, a +Linux system will not function. + +###################################################################### +# libnsl subpackage +###################################################################### -%ifnarch loongarch64 %package -n libnsl Summary: Legacy support library for NIS -Requires: %{name} = %{EVR} +Requires: %{name}%{_isa} = %{version}-%{release} %description -n libnsl -This package provides the legacy version of libnsl library, -for accessing NIS services. This library is provided for -backwards compatibility only, applications should use -libnsl2 instead to gain IPv6 support. -%endif +This package provides the legacy version of libnsl library, for +accessing NIS services. +This library is provided for backwards compatibility only; +applications should use libnsl2 instead to gain IPv6 support. + +############################################################################## +# glibc "devel" sub-package +############################################################################## %package devel Summary: Object files for development using standard C libraries. -BuildRequires: kernel-headers >= 3.2 -Requires: %{name} = %{EVR} -Requires: libxcrypt-devel >= 4.0.0 kernel-headers >= 3.2 -Provides: glibc-headers = %{EVR} -Provides: glibc-headers(%{_target_cpu}) -Obsoletes: glibc-headers < %{EVR} +Requires(pre): /sbin/install-info +Requires(pre): %{name}-headers +Requires: %{name}-headers = %{version}-%{release} +Requires: %{name} = %{version}-%{release} +Requires: libgcc%{_isa} +Requires: libxcrypt-devel%{_isa} >= 4.0.0 %description devel The glibc-devel package contains the object files necessary for developing programs which use the standard C libraries (which are -used by nearly all programs). -If you are developing programs which will use the standard C libraries, -your system needs to have these standard object files -available in order to create the executables. +used by nearly all programs). If you are developing programs which +will use the standard C libraries, your system needs to have these +standard object files available in order to create the +executables. +Install glibc-devel if you are going to develop programs which will +use the standard C libraries. + +############################################################################## +# glibc "static" sub-package +############################################################################## %package static Summary: C library static libraries for -static linking. -Requires: %{name}-devel = %{EVR} -Requires: libxcrypt-static >= 4.0.0 +Requires: %{name}-devel = %{version}-%{release} +Requires: libxcrypt-static%{?_isa} >= 4.0.0 %description static The glibc-static package contains the C library static libraries -for -static linking. -You don't need these unless you link statically, which is highly discouraged. +for -static linking. You don't need these, unless you link statically, +which is highly discouraged. +############################################################################## +# glibc "headers" sub-package +# - The headers package includes all common headers that are shared amongst +# the multilib builds. It was created to reduce the download size, and +# thus avoid downloading one header package per multilib. The package is +# identical both in content and file list, any difference is an error. +# Files like gnu/stubs.h which have gnu/stubs-32.h (i686) and gnu/stubs-64.h +# are included in glibc-headers, but the -32 and -64 files are in their +# respective i686 and x86_64 devel packages. +############################################################################## +%package headers +Summary: Header files for development using standard C libraries. +Provides: %{name}-headers(%{_target_cpu}) +Requires(pre): kernel-headers +Requires: kernel-headers >= 2.2.1, %{name} = %{version}-%{release} +BuildRequires: kernel-headers >= 3.2 + +%description headers +The glibc-headers package contains the header files necessary +for developing programs which use the standard C libraries (which are +used by nearly all programs). If you are developing programs which +will use the standard C libraries, your system needs to have these +standard header files available in order to create the +executables. + +Install glibc-headers if you are going to develop programs which will +use the standard C libraries. + +############################################################################## +# glibc "common" sub-package +############################################################################## %package common Summary: Common binaries and locale data for glibc -Requires: %{name} = %{EVR} +Requires: %{name} = %{version}-%{release} Requires: tzdata >= 2003a %description common The glibc-common package includes common binaries for the GNU libc libraries, as well as national language (locale) support. +###################################################################### +# File triggers to do ldconfig calls automatically (see rhbz#1380878) +###################################################################### + +# File triggers for when libraries are added or removed in standard +# paths. %transfiletriggerin common -P 2000000 -- /lib /usr/lib /lib64 /usr/lib64 /sbin/ldconfig %end @@ -232,100 +975,200 @@ libraries, as well as national language (locale) support. /sbin/ldconfig %end +# We need to run ldconfig manually because __brp_ldconfig assumes that +# glibc itself is always installed in $RPM_BUILD_ROOT, but with sysroots +# we may be installed into a subdirectory of that path. Therefore we +# unset __brp_ldconfig and run ldconfig by hand with the sysroots path +# passed to -r. +%undefine __brp_ldconfig + +###################################################################### + %package locale-source Summary: The sources for the locales -Requires: %{name} = %{EVR} -Requires: %{name}-common = %{EVR} +Requires: %{name} = %{version}-%{release} +Requires: %{name}-common = %{version}-%{release} %description locale-source The sources for all locales provided in the language packs. If you are building custom locales you will most likely use these sources as the basis for your new locale. -%package all-langpacks -Summary: All language packs for glibc. -Provides: glibc-langpack = %{EVR} -Requires: %{name} = %{EVR} -Requires: %{name}-common = %{EVR} %{lua: --- List the langpacks provided by all-langpacks -lang_provides = {} -for line in io.lines(rpm.expand("%{SOURCE20}")) do - print(rpm.expand([[ -Provides: %{name}-langpack-]]..line..[[ = %{EVR} -Obsoletes: %{name}-langpack-]]..line..[[ <= %{EVR} +-- Array of languages (ISO-639 codes). +local languages = {} +-- Dictionary from language codes (as in the languages array) to arrays +-- of regions. +local supplements = {} +do + -- Parse the SUPPORTED file. Eliminate duplicates. + local lang_region_seen = {} + for line in io.lines(rpm.expand("%{SOURCE11}")) do + -- Match lines which contain a language (eo) or language/region + -- (en_US) strings. + local lang_region = string.match(line, "^([a-z][^/@.]+)") + if lang_region ~= nil then + if lang_region_seen[lang_region] == nil then + lang_region_seen[lang_region] = true + + -- Split language/region pair. + local lang, region = string.match(lang_region, "^(.+)_(.+)") + if lang == nil then + -- Region is missing, use only the language. + lang = lang_region + end + local suppl = supplements[lang] + if suppl == nil then + suppl = {} + supplements[lang] = suppl + -- New language not seen before. + languages[#languages + 1] = lang + end + if region ~= nil then + -- New region because of the check against + -- lang_region_seen above. + suppl[#suppl + 1] = region + end + end + end + end + -- Sort for determinism. + table.sort(languages) + for _, supples in pairs(supplements) do + table.sort(supplements) + end +end + +-- Compute the Supplements: list for a language, based on the regions. +local function compute_supplements(lang) + result = "langpacks-" .. lang + regions = supplements[lang] + if regions ~= nil then + for i = 1, #regions do + result = result .. " or langpacks-" .. lang .. "_" .. regions[i] + end + end + return result +end + +-- Emit the definition of a language pack package. +local function lang_package(lang) + local suppl = compute_supplements(lang) + print(rpm.expand([[ + +%package langpack-]]..lang..[[ + +Summary: Locale data for ]]..lang..[[ + +Provides: glibc-langpack = %{version}-%{release} +Requires: %{name} = %{version}-%{release} +Requires: %{name}-common = %{version}-%{release} +Supplements: (glibc and (]]..suppl..[[)) +%description langpack-]]..lang..[[ + +The glibc-langpack-]]..lang..[[ package includes the basic information required +to support the ]]..lang..[[ language in your applications. +%ifnarch %{auxarches} +%files -f langpack-]]..lang..[[.filelist langpack-]]..lang..[[ + +%endif ]])) end + +for i = 1, #languages do + lang_package(languages[i]) +end } +# The glibc-all-langpacks provides the virtual glibc-langpack, +# and thus satisfies glibc's requirement for installed locales. +# Users can add one more other langauge packs and then eventually +# uninstall all-langpacks to save space. +%package all-langpacks +Summary: All language packs for %{name}. +Requires: %{name} = %{version}-%{release} +Requires: %{name}-common = %{version}-%{release} +Provides: %{name}-langpack = %{version}-%{release} %description all-langpacks -This package includes all the basic infomation required -to support all language. Exclude en and zh langpack. - -%package langpack-en -Summary: Locale data for English -Provides: glibc-langpack = %{EVR} -Requires: %{name} = %{EVR} -Requires: %{name}-common = %{EVR} - -%description langpack-en -The glibc-langpack-en package includes the basic information -required to support the English language in your applications. - -%package langpack-zh -Summary: Locale data for Chinese -Provides: glibc-langpack = %{EVR} -Requires: %{name} = %{EVR} -Requires: %{name}-common = %{EVR} -Obsoletes: %{name}-langpack-cmn < %{EVR} -Provides: %{name}-langpack-cmn = %{EVR} - -%description langpack-zh -The glibc-langpack-zh package includes the basic information required -to support the Chinese language in your applications. +# No %files, this is an empty pacakge. The C/POSIX and +# C.UTF-8 files are already installed by glibc. We create +# minimal-langpack because the virtual provide of +# glibc-langpack needs at least one package installed +# to satisfy it. Given that no-locales installed is a valid +# use case we support it here with this package. %package minimal-langpack -Summary: Minimal language packs for glibc. -Provides: glibc-langpack = %{EVR} -Requires: %{name} = %{EVR} -Requires: %{name}-common = %{EVR} +Summary: Minimal language packs for %{name}. +Provides: glibc-langpack = %{version}-%{release} +Requires: %{name} = %{version}-%{release} +Requires: %{name}-common = %{version}-%{release} %description minimal-langpack This is a Meta package that is used to install minimal language packs. This package ensures you can use C, POSIX, or C.UTF-8 locales, but -nothing else. -It is designed for assembling a minimal system. +nothing else. It is designed for assembling a minimal system. +%ifnarch %{auxarches} +%files minimal-langpack +%endif -%package gconv-extra -Summary: All iconv converter modules for glibc. -Requires: %{name} = %{EVR} -Requires: %{name}-common = %{EVR} +############################################################################## +# glibc "nscd" sub-package +############################################################################## +%package -n nscd +Summary: A Name Service Caching Daemon (nscd). +Requires: %{name} = %{version}-%{release} +%if %{without bootstrap} +Requires: libselinux >= 1.17.10-1 +%endif +Requires: audit-libs >= 1.1.3 +Requires(pre): /usr/sbin/useradd, coreutils +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd, /usr/sbin/userdel -%description gconv-extra -This package contains all iconv converter modules built in glibc. +%description -n nscd +The nscd daemon caches name service lookups and can improve +performance with LDAP, and may help with DNS as well. +############################################################################## +# Subpackages for NSS modules except nss_files, nss_compat, nss_dns +############################################################################## + +# This should remain it's own subpackage or "Provides: nss_db" to allow easy +# migration from old systems that previously had the old nss_db package +# installed. Note that this doesn't make the migration that smooth, the +# databases still need rebuilding because the formats were different. +# The nss_db package was deprecated in F16 and onwards: +# https://lists.fedoraproject.org/pipermail/devel/2011-July/153665.html +# The different database format does cause some issues for users: +# https://lists.fedoraproject.org/pipermail/devel/2011-December/160497.html %package -n nss_db Summary: Name Service Switch (NSS) module using hash-indexed files -Requires: %{name} = %{EVR} +Requires: %{name}%{_isa} = %{version}-%{release} +%ifarch x86_64 +# Automatically install the 32-bit variant if the 64-bit variant has +# been installed. This covers the case when glibc.i686 is installed +# before nss_db.x86_64. (See above for the other ordering.) +Recommends: (nss_db(x86-32) if glibc(x86-32)) +%endif %description -n nss_db -The nss_db Name Service Switch module uses hash-indexed files -in /var/db to speed up user, group, service, host name, -and other NSS-based lookups. +The nss_db Name Service Switch module uses hash-indexed files in /var/db +to speed up user, group, service, host name, and other NSS-based lookups. %package -n nss_hesiod Summary: Name Service Switch (NSS) module using Hesiod -Requires: %{name} = %{EVR} +Requires: %{name}%{_isa} = %{version}-%{release} %description -n nss_hesiod The nss_hesiod Name Service Switch module uses the Domain Name System -(DNS) as a source for user, group, and service information, -following the Hesiod convention of Project Athena. +(DNS) as a source for user, group, and service information, following +the Hesiod convention of Project Athena. %package nss-devel Summary: Development files for directly linking NSS service modules -Requires: %{name} = %{EVR} -Requires: nss_db = %{EVR} -Requires: nss_hesiod = %{EVR} +Requires: %{name}%{_isa} = %{version}-%{release} +Requires: nss_db%{_isa} = %{version}-%{release} +Requires: nss_hesiod%{_isa} = %{version}-%{release} %description nss-devel The glibc-nss-devel package contains the object files necessary to @@ -335,9 +1178,12 @@ modules supplied by glibc. This is a rare and special use case; regular development has to use the glibc-devel package instead. +############################################################################## +# glibc "utils" sub-package +############################################################################## %package utils Summary: Development utilities from GNU C library -Requires: %{name} = %{EVR} +Requires: %{name} = %{version}-%{release} %description utils The glibc-utils package contains memusage, a memory usage profiler, @@ -346,54 +1192,125 @@ which can be helpful during program debugging. If unsure if you need this, don't install this package. +############################################################################## +# glibc core "debuginfo" sub-package +############################################################################## +%if 0%{?_enable_debug_packages} +%define debug_package %{nil} +%define __debug_install_post %{nil} +%global __debug_package 1 +# Disable thew new features that glibc packages don't use. +%undefine _debugsource_packages +%undefine _debuginfo_subpackages +%undefine _unique_debug_names +%undefine _unique_debug_srcs + +%package debuginfo +Summary: Debug information for package %{name} +AutoReqProv: no +%ifarch %{debuginfocommonarches} +Requires: glibc-debuginfo-common = %{version}-%{release} +%else +%ifarch %{ix86} %{sparc} +Obsoletes: glibc-debuginfo-common +%endif +%endif + +%description debuginfo +This package provides debug information for package %{name}. +Debug information is useful when developing applications that use this +package or when debugging this package. + +This package also contains static standard C libraries with +debugging information. You need this only if you want to step into +C library routines during debugging programs statically linked against +one or more of the standard C libraries. +To use this debugging information, you need to link binaries +with -static -L%{_prefix}/lib/debug%{_libdir} compiler options. + +############################################################################## +# glibc common "debuginfo-common" sub-package +############################################################################## +%ifarch %{debuginfocommonarches} + +%package debuginfo-common +Summary: Debug information for package %{name} +AutoReqProv: no + +%description debuginfo-common +This package provides debug information for package %{name}. +Debug information is useful when developing applications that use this +package or when debugging this package. + +%comment Matches: %ifarch %{debuginfocommonarches} +%endif + +%comment Matches: %if 0%{?_enable_debug_packages} +%endif + %if %{with benchtests} %package benchtests -Summary: Benchmarking binaries and scripts for glibc - +Summary: Benchmarking binaries and scripts for %{name} %description benchtests This package provides built benchmark binaries and scripts to run microbenchmark tests on the system. %endif +############################################################################## +# compat-libpthread-nonshared +# See: https://sourceware.org/bugzilla/show_bug.cgi?id=23500 +############################################################################## %package -n compat-libpthread-nonshared Summary: Compatibility support for linking against libpthread_nonshared.a. %description -n compat-libpthread-nonshared This package provides compatibility support for applications that expect -libpthread_nonshared.a to exist. -The support provided is in the form of an empty libpthread_nonshared.a -that allows dynamic links to succeed. +libpthread_nonshared.a to exist. The support provided is in the form of +an empty libpthread_nonshared.a that allows dynamic links to succeed. Such applications should be adjusted to avoid linking against -libpthread_nonshared.a which is no longer used. -The static library libpthread_nonshared.a is an internal implementation -detail of the C runtime and should not be expected to exist. - -%if %{with docs} -%package doc -Summary: Documentation for GNU libc -BuildArch: noarch -BuildRequires: texinfo >= 5.0 -Requires: %{name} = %{EVR} - -%description doc -The glibc-doc package contains The GNU C Library Reference Manual -in info format. Additional package documentation is also provided. -%endif +libpthread_nonshared.a which is no longer used. The static library +libpthread_nonshared.a is an internal implementation detail of the C +runtime and should not be expected to exist. +############################################################################## +# Prepare for the build. +############################################################################## %prep -%autosetup -p1 +%autosetup -n %{glibcsrcdir} -p1 +############################################################################## +# %%prep - Additional prep required... +############################################################################## +# Make benchmark scripts executable chmod +x benchtests/scripts/*.py scripts/pylint + +# Remove all files generated from patching. find . -type f -size 0 -o -name "*.orig" -exec rm -f {} \; + +# Ensure timestamps on configure files are current to prevent +# regenerating them. touch `find . -name configure` + +# Ensure *-kw.h files are current to prevent regenerating them. touch locale/programs/*-kw.h -# Ignore kernel version check errors. -%ifarch loongarch64 -sed -i "s@5.19.0@4.15.0@g" sysdeps/unix/sysv/linux/loongarch/configure{,.ac} -%endif +# Verify that our copy of localedata/SUPPORTED matches the glibc +# version. +# +# The separate file copy is used by the Lua parser above. +# Patches or new upstream versions may change the list of locales, +# which changes the set of langpacks we need to build. Verify the +# differences then update the copy of SUPPORTED. This approach has +# two purposes: (a) avoid spurious changes to the set of langpacks, +# and (b) the Lua snippet can use a fully patched-up version +# of the localedata/SUPPORTED file. +diff -u %{SOURCE11} localedata/SUPPORTED +############################################################################## +# Build glibc... +############################################################################## %build +# Log system information uname -a LD_SHOW_AUXV=1 /bin/true cat /proc/cpuinfo @@ -401,193 +1318,459 @@ cat /proc/sysinfo 2>/dev/null || true cat /proc/meminfo df +# We build using the native system compilers. GCC=gcc GXX=g++ +# Part of rpm_inherit_flags. Is overridden below. rpm_append_flag () { BuildFlags="$BuildFlags $*" } +# Propagates the listed flags to rpm_append_flag if supplied by +# redhat-rpm-config. BuildFlags="-O2 -g" rpm_inherit_flags () { - local reference=" $* " - local flag - for flag in $RPM_OPT_FLAGS $RPM_LD_FLAGS ; do - if echo "$reference" | grep -q -F " $flag " ; then - rpm_append_flag "$flag" - fi - done + local reference=" $* " + local flag + for flag in $RPM_OPT_FLAGS $RPM_LD_FLAGS ; do + if echo "$reference" | grep -q -F " $flag " ; then + rpm_append_flag "$flag" + fi + done } +# Propgate select compiler flags from redhat-rpm-config. These flags +# are target-dependent, so we use only those which are specified in +# redhat-rpm-config. We keep the -m32/-m32/-m64 flags to support +# multilib builds. +# +# Note: For building alternative run-times, care is required to avoid +# overriding the architecture flags which go into CC/CXX. The flags +# below are passed in CFLAGS. + rpm_inherit_flags \ - "-Wp,-D_GLIBCXX_ASSERTIONS" \ - "-fasynchronous-unwind-tables" \ - "-fstack-clash-protection" \ - "-funwind-tables" \ - "-m31" \ - "-m32" \ - "-m64" \ - "-march=armv8-a+lse" \ - "-march=armv8.1-a" \ - "-march=armv9-a" \ - "-march=haswell" \ - "-march=i686" \ - "-march=x86-64" \ - "-march=x86-64-v2" \ - "-march=x86-64-v3" \ - "-march=x86-64-v4" \ - "-march=z13" \ - "-march=z14" \ - "-march=z15" \ - "-march=zEC12" \ - "-mbranch-protection=standard" \ - "-mcpu=power10" \ - "-mcpu=power8" \ - "-mcpu=power9" \ - "-mfpmath=sse" \ - "-msse2" \ - "-mstackrealign" \ - "-mtune=generic" \ - "-mtune=power10" \ - "-mtune=power8" \ - "-mtune=power9" \ - "-mtune=z13" \ - "-mtune=z14" \ - "-mtune=z15" \ - "-mtune=zEC12" \ - "-specs=/usr/lib/rpm/anolis/anolis-annobin-cc1" \ + "-Wp,-D_GLIBCXX_ASSERTIONS" \ + "-fasynchronous-unwind-tables" \ + "-fstack-clash-protection" \ + "-funwind-tables" \ + "-m31" \ + "-m32" \ + "-m64" \ + "-march=i686" \ + "-march=x86-64" \ + "-march=z13" \ + "-march=z14" \ + "-march=zEC12" \ + "-mfpmath=sse" \ + "-msse2" \ + "-mstackrealign" \ + "-mtune=generic" \ + "-mtune=z13" \ + "-mtune=z14" \ + "-mtune=zEC12" \ + "-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1" \ -%if 0%{?_annotated_build} > 0 -BuildFlagsNonshared="-fplugin=annobin -fplugin-arg-annobin-disable -Wa,--generate-missing-build-notes=yes" +# Propagate additional build flags to BuildFlagsNonshared. This is +# very special because some of these files are part of the startup +# code. We essentially hope that these flags have little effect +# there, and only specify the, for consistency, so that annobin +# records the expected compiler flags. +BuildFlagsNonshared= +rpm_append_flag () { + BuildFlagsNonshared="$BuildFlagsNonshared $*" +} +rpm_inherit_flags \ + "-Wp,-D_FORTIFY_SOURCE=2" \ + +# Special flag to enable annobin annotations for statically linked +# assembler code. Needs to be passed to make; not preserved by +# configure. +%define glibc_make_flags_as ASFLAGS="-g -Wa,--generate-missing-build-notes=yes" +%define glibc_make_flags %{glibc_make_flags_as} + +%ifarch aarch64 +# BZ 1856398 - Build AArch64 with out-of-line support for LSE atomics +GCC="$GCC -moutline-atomics" +GXX="$GXX -moutline-atomics" %endif +############################################################################## +# %%build - Generic options. +############################################################################## +EnableKernel="--enable-kernel=%{enablekernel}" +# Save the used compiler and options into the file "Gcc" for use later +# by %%install. echo "$GCC" > Gcc + +############################################################################## +# build() +# Build glibc in `build-%{target}$1', passing the rest of the arguments +# as CFLAGS to the build (not the same as configure CFLAGS). Several +# global values are used to determine build flags, kernel version, +# system tap support, etc. +############################################################################## build() { - local builddir=build-%{target}${1:+-$1} - ${1+shift} - rm -rf $builddir - mkdir $builddir - pushd $builddir - ../configure CC="$GCC" CXX="$GXX" CFLAGS="$BuildFlags $*" \ - --prefix=%{_prefix} \ - --build=%{target} \ - --with-headers=%{_prefix}/include \ - --enable-kernel=%{enablekernel} \ - --with-nonshared-cflags="$BuildFlagsNonshared" \ - --enable-bind-now \ - --enable-stack-protector=strong \ - --enable-tunables \ - --enable-systemtap \ - ${core_with_options} \ -%ifarch x86_64 - --enable-cet \ + local builddir=build-%{target}${1:+-$1} + ${1+shift} + rm -rf $builddir + mkdir $builddir + pushd $builddir + ../configure CC="$GCC" CXX="$GXX" CFLAGS="$BuildFlags $*" \ + --prefix=%{_prefix} \ + --with-headers=%{_prefix}/include $EnableKernel \ + --with-nonshared-cflags="$BuildFlagsNonshared" \ + --enable-bind-now \ + --build=%{target} \ + --enable-stack-protector=strong \ +%ifarch %{pie_arches} + --enable-static-pie \ +%endif + --enable-tunables \ + --enable-systemtap \ + ${core_with_options} \ +%ifarch x86_64 %{ix86} + --enable-cet \ +%endif +%ifarch %{ix86} + --disable-multi-arch \ %endif %if %{without werror} - --disable-werror \ + --disable-werror \ %endif + --disable-profile \ %if %{with bootstrap} - --without-selinux \ + --without-selinux \ %endif -%ifarch aarch64 - --enable-memory-tagging \ -%endif - --disable-profile \ - --disable-crypt \ - --disable-build-nscd \ - --disable-nscd || - { cat config.log; false; } + --disable-crypt || + { cat config.log; false; } - %make_build -r %{glibc_make_flags} - popd + make %{?_smp_mflags} -O -r %{glibc_make_flags} + popd } +# Default set of compiler options. build +%if %{buildpower9} +( + GCC="$GCC -mcpu=power9 -mtune=power9" + GXX="$GXX -mcpu=power9 -mtune=power9" + core_with_options="--with-cpu=power9" + build power9 +) +%endif + +############################################################################## +# Install glibc... +############################################################################## %install + +# The built glibc is installed into a subdirectory of $RPM_BUILD_ROOT. +# For a system glibc that subdirectory is "/" (the root of the filesystem). +# This is called a sysroot (system root) and can be changed if we have a +# distribution that supports multiple installed glibc versions. +%define glibc_sysroot $RPM_BUILD_ROOT + +# Remove existing file lists. +find . -type f -name '*.filelist' -exec rm -rf {} \; + +# Ensure the permissions of errlist.c do not change. When the file is +# regenerated the Makefile sets the permissions to 444. We set it to 644 +# to match what comes out of git. The tarball of the git archive won't have +# correct permissions because git doesn't track all of the permissions +# accurately (see git-cache-meta if you need that). We also set it to 644 to +# match pre-existing rpms. We do this *after* the build because the build +# might regenerate the file and set the permissions to 444. +chmod 644 sysdeps/gnu/errlist.c + +# Reload compiler and build options that were used during %%build. GCC=`cat Gcc` %ifarch riscv64 -for d in %{buildroot}%{_libdir} %{buildroot}/%{_lib}; do - mkdir -p $d - (cd $d && ln -sf . lp64d) +# RISC-V ABI wants to install everything in /lib64/lp64d or /usr/lib64/lp64d. +# Make these be symlinks to /lib64 or /usr/lib64 respectively. See: +# https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/thread/DRHT5YTPK4WWVGL3GIN5BF2IKX2ODHZ3/ +for d in %{glibc_sysroot}%{_libdir} %{glibc_sysroot}/%{_lib}; do + mkdir -p $d + (cd $d && ln -sf . lp64d) done %endif +# Build and install: +make -j1 install_root=%{glibc_sysroot} install -C build-%{target} + +# If we are not building an auxiliary arch then install all of the supported +# locales. +%ifnarch %{auxarches} pushd build-%{target} -%make_build install_root=%{buildroot} install -%make_build install_root=%{buildroot} install-locales -C ../localedata objdir=`pwd` +# Do not use a parallel make here because the hardlink optimization in +# localedef is not fully reproducible when running concurrently. +make install_root=%{glibc_sysroot} \ + install-locales -C ../localedata objdir=`pwd` popd - -hardlink %{buildroot}/usr/lib/locale - -rm -f %{buildroot}/%{_libdir}/libNoVersion* -rm -f %{buildroot}/%{_lib}/libNoVersion* -rm -f %{buildroot}/%{_lib}/libnss1-* -rm -f %{buildroot}/%{_lib}/libnss-*.so.1 -rm -f %{buildroot}/{usr/,}sbin/sln - -mkdir -p %{buildroot}/var/cache/ldconfig -truncate -s 0 %{buildroot}/var/cache/ldconfig/aux-cache -%{buildroot}/sbin/ldconfig -N -r %{buildroot} - -%if %{with docs} -if [ -d %{buildroot}%{_prefix}/info -a "%{_infodir}" != "%{_prefix}/info" ]; then - mkdir -p %{buildroot}%{_infodir} - mv -f %{buildroot}%{_prefix}/info/* %{buildroot}%{_infodir} - rm -rf %{buildroot}%{_prefix}/info -fi -gzip -9nvf %{buildroot}%{_infodir}/libc* -mkdir -p %{buildroot}%{_docdir}/glibc -cp elf/rtld-debugger-interface.txt %{buildroot}%{_docdir}/glibc -%else -rm -f %{buildroot}%{_infodir}/dir -rm -f %{buildroot}%{_infodir}/libc.info* %endif +# install_different: +# Install all core libraries into DESTDIR/SUBDIR. Either the file is +# installed as a copy or a symlink to the default install (if it is the +# same). The path SUBDIR_UP is the prefix used to go from +# DESTDIR/SUBDIR to the default installed libraries e.g. +# ln -s SUBDIR_UP/foo.so DESTDIR/SUBDIR/foo.so. +# When you call this function it is expected that you are in the root +# of the build directory, and that the default build directory is: +# "../build-%{target}" (relatively). +# The primary use of this function is to install alternate runtimes +# into the build directory and avoid duplicating this code for each +# runtime. +install_different() +{ + local lib libbase libbaseso dlib + local destdir="$1" + local subdir="$2" + local subdir_up="$3" + local libdestdir="$destdir/$subdir" + # All three arguments must be non-zero paths. + if ! [ "$destdir" \ + -a "$subdir" \ + -a "$subdir_up" ]; then + echo "One of the arguments to install_different was emtpy." + exit 1 + fi + # Create the destination directory and the multilib directory. + mkdir -p "$destdir" + mkdir -p "$libdestdir" + # Walk all of the libraries we installed... + for lib in libc math/libm nptl/libpthread rt/librt nptl_db/libthread_db + do + libbase=${lib#*/} + # Take care that `libbaseso' has a * that needs expanding so + # take care with quoting. + libbaseso=$(basename %{glibc_sysroot}/%{_lib}/${libbase}-*.so) + # Only install if different from default build library. + if cmp -s ${lib}.so ../build-%{target}/${lib}.so; then + ln -sf "$subdir_up"/$libbaseso $libdestdir/$libbaseso + else + cp -a ${lib}.so $libdestdir/$libbaseso + fi + dlib=$libdestdir/$(basename %{glibc_sysroot}/%{_lib}/${libbase}.so.*) + ln -sf $libbaseso $dlib + done +} + +%if %{buildpower9} +pushd build-%{target}-power9 +install_different "$RPM_BUILD_ROOT/%{_lib}/glibc-hwcaps" power9 "../.." +popd +%endif + +############################################################################## +# Remove the files we don't want to distribute +############################################################################## + +# Remove the libNoVersion files. +# XXX: This looks like a bug in glibc that accidentally installed these +# wrong files. We probably don't need this today. +rm -f %{glibc_sysroot}/%{_libdir}/libNoVersion* +rm -f %{glibc_sysroot}/%{_lib}/libNoVersion* + +# Remove the old nss modules. +rm -f %{glibc_sysroot}/%{_lib}/libnss1-* +rm -f %{glibc_sysroot}/%{_lib}/libnss-*.so.1 + +# This statically linked binary is no longer necessary in a world where +# the default Fedora install uses an initramfs, and further we have rpm-ostree +# which captures the whole userspace FS tree. +# Further, see https://github.com/projectatomic/rpm-ostree/pull/1173#issuecomment-355014583 +rm -f %{glibc_sysroot}/{usr/,}sbin/sln + +###################################################################### +# Run ldconfig to create all the symbolic links we need +###################################################################### + +# Note: This has to happen before creating /etc/ld.so.conf. + +mkdir -p %{glibc_sysroot}/var/cache/ldconfig +truncate -s 0 %{glibc_sysroot}/var/cache/ldconfig/aux-cache + +# ldconfig is statically linked, so we can use the new version. +%{glibc_sysroot}/sbin/ldconfig -N -r %{glibc_sysroot} + +############################################################################## +# Install info files +############################################################################## + +%if %{with docs} +# Move the info files if glibc installed them into the wrong location. +if [ -d %{glibc_sysroot}%{_prefix}/info -a "%{_infodir}" != "%{_prefix}/info" ]; then + mkdir -p %{glibc_sysroot}%{_infodir} + mv -f %{glibc_sysroot}%{_prefix}/info/* %{glibc_sysroot}%{_infodir} + rm -rf %{glibc_sysroot}%{_prefix}/info +fi + +# Compress all of the info files. +gzip -9nvf %{glibc_sysroot}%{_infodir}/libc* + +%else +rm -f %{glibc_sysroot}%{_infodir}/dir +rm -f %{glibc_sysroot}%{_infodir}/libc.info* +%endif + +############################################################################## +# Create locale sub-package file lists +############################################################################## + +%ifnarch %{auxarches} olddir=`pwd` -pushd %{buildroot}%{_prefix}/lib/locale +pushd %{glibc_sysroot}%{_prefix}/lib/locale rm -f locale-archive -$olddir/build-%{target}/elf/ld.so \ - --library-path $olddir/build-%{target}/ \ +# Intentionally we do not pass --alias-file=, aliases will be added +# by build-locale-archive. +$olddir/build-%{target}/testrun.sh \ $olddir/build-%{target}/locale/localedef \ - --alias-file=$olddir/intl/locale.alias \ - --prefix %{buildroot} --add-to-archive \ - %locale_rx -ln locale-archive locale-archive.real + --prefix %{glibc_sysroot} --add-to-archive \ + eo *_* +# Setup the locale-archive template for use by glibc-all-langpacks. We +# copy the archive in place to keep the size of the file. Even though we +# mark the file with "ghost" the size is used by rpm to compute the +# required free space (see rhbz#1725131). We do this because there is a +# point in the install when build-locale-archive has copied 100% of the +# template into the new locale archive and so this consumes twice the +# amount of diskspace. Note that this doesn't account for copying +# existing compiled locales into the archive, this may consume even more +# disk space and we can't fix that issue. In upstream we have moved away +# from this process, removing build-locale-archive and installing a +# default locale-archive without modification, and leaving compiled +# locales as they are (without inclusion into the archive). +cp locale-archive{,.tmpl} +# Create the file lists for the language specific sub-packages: +for i in eo *_* +do + lang=${i%%_*} + if [ ! -e langpack-${lang}.filelist ]; then + echo "%dir %{_prefix}/lib/locale" >> langpack-${lang}.filelist + fi + echo "%dir %{_prefix}/lib/locale/$i" >> langpack-${lang}.filelist + echo "%{_prefix}/lib/locale/$i/*" >> langpack-${lang}.filelist +done +popd +pushd %{glibc_sysroot}%{_prefix}/share/locale +for i in */LC_MESSAGES/libc.mo +do + locale=${i%%%%/*} + lang=${locale%%%%_*} + echo "%lang($lang) %{_prefix}/share/locale/${i}" \ + >> %{glibc_sysroot}%{_prefix}/lib/locale/langpack-${lang}.filelist +done +popd +mv %{glibc_sysroot}%{_prefix}/lib/locale/*.filelist . +%endif + +############################################################################## +# Install configuration files for services +############################################################################## + +install -p -m 644 nss/nsswitch.conf %{glibc_sysroot}/etc/nsswitch.conf + +%ifnarch %{auxarches} +# This is for ncsd - in glibc 2.2 +install -m 644 nscd/nscd.conf %{glibc_sysroot}/etc +mkdir -p %{glibc_sysroot}%{_tmpfilesdir} +install -m 644 %{SOURCE4} %{buildroot}%{_tmpfilesdir} +mkdir -p %{glibc_sysroot}/lib/systemd/system +install -m 644 nscd/nscd.service nscd/nscd.socket %{glibc_sysroot}/lib/systemd/system +%endif + +# Include ld.so.conf +echo 'include ld.so.conf.d/*.conf' > %{glibc_sysroot}/etc/ld.so.conf +truncate -s 0 %{glibc_sysroot}/etc/ld.so.cache +chmod 644 %{glibc_sysroot}/etc/ld.so.conf +mkdir -p %{glibc_sysroot}/etc/ld.so.conf.d +%ifnarch %{auxarches} +mkdir -p %{glibc_sysroot}/etc/sysconfig +truncate -s 0 %{glibc_sysroot}/etc/sysconfig/nscd +truncate -s 0 %{glibc_sysroot}/etc/gai.conf +%endif + +# Include %{_libdir}/gconv/gconv-modules.cache +truncate -s 0 %{glibc_sysroot}%{_libdir}/gconv/gconv-modules.cache +chmod 644 %{glibc_sysroot}%{_libdir}/gconv/gconv-modules.cache + +############################################################################## +# Install debug copies of unstripped static libraries +# - This step must be last in order to capture any additional static +# archives we might have added. +############################################################################## + +# If we are building a debug package then copy all of the static archives +# into the debug directory to keep them as unstripped copies. +%if 0%{?_enable_debug_packages} +mkdir -p %{glibc_sysroot}%{_prefix}/lib/debug%{_libdir} +cp -a %{glibc_sysroot}%{_libdir}/*.a \ + %{glibc_sysroot}%{_prefix}/lib/debug%{_libdir}/ +rm -f %{glibc_sysroot}%{_prefix}/lib/debug%{_libdir}/*_p.a +%endif + +# Remove any zoneinfo files; they are maintained by tzdata. +rm -rf %{glibc_sysroot}%{_prefix}/share/zoneinfo + +# Make sure %config files have the same timestamp across multilib packages. +# +# XXX: Ideally ld.so.conf should have the timestamp of the spec file, but there +# doesn't seem to be any macro to give us that. So we do the next best thing, +# which is to at least keep the timestamp consistent. The choice of using +# SOURCE0 is arbitrary. +touch -r %{SOURCE0} %{glibc_sysroot}/etc/ld.so.conf +touch -r sunrpc/etc.rpc %{glibc_sysroot}/etc/rpc + +pushd build-%{target} +$GCC -Os -g -static -o build-locale-archive %{SOURCE1} \ + ../build-%{target}/locale/locarchive.o \ + ../build-%{target}/locale/md5.o \ + ../build-%{target}/locale/record-status.o \ + -I. -DDATADIR=\"%{_datadir}\" -DPREFIX=\"%{_prefix}\" \ + -L../build-%{target} \ + -B../build-%{target}/csu/ -lc -lc_nonshared +install -m 700 build-locale-archive %{glibc_sysroot}%{_prefix}/sbin/build-locale-archive popd -echo 'include ld.so.conf.d/*.conf' > %{buildroot}/etc/ld.so.conf -truncate -s 0 %{buildroot}/etc/ld.so.cache -chmod 644 %{buildroot}/etc/ld.so.conf -mkdir -p %{buildroot}/etc/ld.so.conf.d -truncate -s 0 %{buildroot}/etc/gai.conf +# Lastly copy some additional documentation for the packages. +rm -rf documentation +mkdir documentation +cp timezone/README documentation/README.timezone +cp posix/gai.conf documentation/ -truncate -s 0 %{buildroot}%{_libdir}/gconv/gconv-modules.cache -chmod 644 %{buildroot}%{_libdir}/gconv/gconv-modules.cache - -rm -rf %{buildroot}%{_prefix}/share/zoneinfo - -touch -r %{SOURCE0} %{buildroot}/etc/ld.so.conf -touch -r inet/etc.rpc %{buildroot}/etc/rpc +%ifarch s390x +# Compatibility symlink +mkdir -p %{glibc_sysroot}/lib +ln -sf /%{_lib}/ld64.so.1 %{glibc_sysroot}/lib/ld64.so.1 +%endif %if %{with benchtests} +# Build benchmark binaries. Ignore the output of the benchmark runs. pushd build-%{target} make BENCH_DURATION=1 bench-build popd -mkdir -p %{buildroot}%{_prefix}/libexec/glibc-benchtests -cp $(find build-%{target}/benchtests -type f -executable) %{buildroot}%{_prefix}/libexec/glibc-benchtests/ -for b in %{SOURCE1} %{SOURCE2}; do - cp $b %{buildroot}%{_prefix}/libexec/glibc-benchtests/ -done -cp benchtests/scripts/benchout.schema.json %{buildroot}%{_prefix}/libexec/glibc-benchtests/ -cp benchtests/scripts/compare_bench.py %{buildroot}%{_prefix}/libexec/glibc-benchtests/ -cp benchtests/scripts/import_bench.py %{buildroot}%{_prefix}/libexec/glibc-benchtests/ -cp benchtests/scripts/validate_benchout.py %{buildroot}%{_prefix}/libexec/glibc-benchtests/ -%endif +# Copy over benchmark binaries. +mkdir -p %{glibc_sysroot}%{_prefix}/libexec/glibc-benchtests +cp $(find build-%{target}/benchtests -type f -executable) %{glibc_sysroot}%{_prefix}/libexec/glibc-benchtests/ +# ... and the makefile. +for b in %{SOURCE9} %{SOURCE10}; do + cp $b %{glibc_sysroot}%{_prefix}/libexec/glibc-benchtests/ +done +# .. and finally, the comparison scripts. +cp benchtests/scripts/benchout.schema.json %{glibc_sysroot}%{_prefix}/libexec/glibc-benchtests/ +cp benchtests/scripts/compare_bench.py %{glibc_sysroot}%{_prefix}/libexec/glibc-benchtests/ +cp benchtests/scripts/import_bench.py %{glibc_sysroot}%{_prefix}/libexec/glibc-benchtests/ +cp benchtests/scripts/validate_benchout.py %{glibc_sysroot}%{_prefix}/libexec/glibc-benchtests/ + +%if 0%{?_enable_debug_packages} +# The #line directives gperf generates do not give the proper +# file name relative to the build directory. pushd locale ln -s programs/*.gperf . popd @@ -596,32 +1779,503 @@ ln -s ../locale/programs/charmap-kw.gperf . popd %if %{with docs} -rm -f %{buildroot}%{_infodir}/dir +# Remove the `dir' info-heirarchy file which will be maintained +# by the system as it adds info files to the install. +rm -f %{glibc_sysroot}%{_infodir}/dir %endif -mkdir -p %{buildroot}%{_libdir} -mv -f %{buildroot}/%{_lib}/lib{pcprofile,memusage}.so %{buildroot}%{_libdir} +%ifnarch %{auxarches} +mkdir -p %{glibc_sysroot}/var/{db,run}/nscd +touch %{glibc_sysroot}/var/{db,run}/nscd/{passwd,group,hosts,services} +touch %{glibc_sysroot}/var/run/nscd/{socket,nscd.pid} +%endif -rm %{buildroot}%{_libdir}/libc_malloc_debug.so -strip -g %{buildroot}%{_libdir}/*.o +# Move libpcprofile.so and libmemusage.so into the proper library directory. +# They can be moved without any real consequences because users would not use +# them directly. +mkdir -p %{glibc_sysroot}%{_libdir} +mv -f %{glibc_sysroot}/%{_lib}/lib{pcprofile,memusage}.so \ + %{glibc_sysroot}%{_libdir} -for i in %{buildroot}%{_prefix}/bin/{xtrace,memusage}; do +# Strip all of the installed object files. +strip -g %{glibc_sysroot}%{_libdir}/*.o + +############################################################################### +# Rebuild libpthread.a using --whole-archive to ensure all of libpthread +# is included in a static link. This prevents any problems when linking +# statically, using parts of libpthread, and other necessary parts not +# being included. Upstream has decided that this is the wrong approach to +# this problem and that the full set of dependencies should be resolved +# such that static linking works and produces the most minimally sized +# static application possible. +############################################################################### +pushd %{glibc_sysroot}%{_prefix}/%{_lib}/ +$GCC -r -nostdlib -o libpthread.o -Wl,--whole-archive ./libpthread.a +rm libpthread.a +ar rcs libpthread.a libpthread.o +rm libpthread.o +popd + +# The xtrace and memusage scripts have hard-coded paths that need to be +# translated to a correct set of paths using the $LIB token which is +# dynamically translated by ld.so as the default lib directory. +for i in %{glibc_sysroot}%{_prefix}/bin/{xtrace,memusage}; do %if %{with bootstrap} test -w $i || continue %endif - sed -e 's#=/%{_lib}\/libpcprofile.so#=%{_libdir}/libpcprofile.so#' \ - -e 's#=/%{_lib}/libmemusage.so#=%{_libdir}/libmemusage.so#' \ - -e 's#='\''/\\\$LIB/libpcprofile.so#='\''%{_prefix}/\\$LIB/libpcprofile.so#' \ - -e 's#='\''/\\\$LIB/libmemusage.so#='\''%{_prefix}/\\$LIB/libmemusage.so#' \ + sed -e 's~=/%{_lib}/libpcprofile.so~=%{_libdir}/libpcprofile.so~' \ + -e 's~=/%{_lib}/libmemusage.so~=%{_libdir}/libmemusage.so~' \ + -e 's~='\''/\\\$LIB/libpcprofile.so~='\''%{_prefix}/\\$LIB/libpcprofile.so~' \ + -e 's~='\''/\\\$LIB/libmemusage.so~='\''%{_prefix}/\\$LIB/libmemusage.so~' \ -i $i done -ar cr %{buildroot}%{_prefix}/%{_lib}/libpthread_nonshared.a +############################################################################## +# Build an empty libpthread_nonshared.a for compatiliby with applications +# that have old linker scripts that reference this file. We ship this only +# in compat-libpthread-nonshared sub-package. +############################################################################## +ar cr %{glibc_sysroot}%{_prefix}/%{_lib}/libpthread_nonshared.a +############################################################################## +# Beyond this point in the install process we no longer modify the set of +# installed files, with one exception, for auxarches we cleanup the file list +# at the end and remove files which we don't intend to ship. We need the file +# list to effect a proper cleanup, and so it happens last. +############################################################################## + +############################################################################## +# Build the file lists used for describing the package and subpackages. +############################################################################## +# There are several main file lists (and many more for +# the langpack sub-packages (langpack-${lang}.filelist)): +# * master.filelist +# - Master file list from which all other lists are built. +# * glibc.filelist +# - Files for the glibc packages. +# * common.filelist +# - Flies for the common subpackage. +# * utils.filelist +# - Files for the utils subpackage. +# * nscd.filelist +# - Files for the nscd subpackage. +# * devel.filelist +# - Files for the devel subpackage. +# * headers.filelist +# - Files for the headers subpackage. +# * static.filelist +# - Files for the static subpackage. +# * libnsl.filelist +# - Files for the libnsl subpackage +# * nss_db.filelist +# * nss_hesiod.filelist +# - File lists for nss_* NSS module subpackages. +# * nss-devel.filelist +# - File list with the .so symbolic links for NSS packages. +# * compat-libpthread-nonshared.filelist. +# - File list for compat-libpthread-nonshared subpackage. +# * debuginfo.filelist +# - Files for the glibc debuginfo package. +# * debuginfocommon.filelist +# - Files for the glibc common debuginfo package. +# + +# Create the main file lists. This way we can append to any one of them later +# wihtout having to create it. Note these are removed at the start of the +# install phase. +touch master.filelist +touch glibc.filelist +touch common.filelist +touch utils.filelist +touch nscd.filelist +touch devel.filelist +touch headers.filelist +touch static.filelist +touch libnsl.filelist +touch nss_db.filelist +touch nss_hesiod.filelist +touch nss-devel.filelist +touch compat-libpthread-nonshared.filelist +touch debuginfo.filelist +touch debuginfocommon.filelist + +############################################################################### +# Master file list, excluding a few things. +############################################################################### +{ + # List all files or links that we have created during install. + # Files with 'etc' are configuration files, likewise 'gconv-modules' + # and 'gconv-modules.cache' are caches, and we exclude them. + find %{glibc_sysroot} \( -type f -o -type l \) \ + \( \ + -name etc -printf "%%%%config " -o \ + -name gconv-modules \ + -printf "%%%%verify(not md5 size mtime) %%%%config(noreplace) " -o \ + -name gconv-modules.cache \ + -printf "%%%%verify(not md5 size mtime) " \ + , \ + ! -path "*/lib/debug/*" -printf "/%%P\n" \) + # List all directories with a %%dir prefix. We omit the info directory and + # all directories in (and including) /usr/share/locale. + find %{glibc_sysroot} -type d \ + \( -path '*%{_prefix}/share/locale' -prune -o \ + \( -path '*%{_prefix}/share/*' \ +%if %{with docs} + ! -path '*%{_infodir}' -o \ +%endif + -path "*%{_prefix}/include/*" \ + \) -printf "%%%%dir /%%P\n" \) +} | { + # Also remove the *.mo entries. We will add them to the + # language specific sub-packages. + # libnss_ files go into subpackages related to NSS modules. + # and .*/share/i18n/charmaps/.*), they go into the sub-package + # "locale-source": + sed -e '\,.*/share/locale/\([^/_]\+\).*/LC_MESSAGES/.*\.mo,d' \ + -e '\,.*/share/i18n/locales/.*,d' \ + -e '\,.*/share/i18n/charmaps/.*,d' \ + -e '\,.*/etc/\(localtime\|nsswitch.conf\|ld\.so\.conf\|ld\.so\.cache\|default\|rpc\|gai\.conf\),d' \ + -e '\,.*/%{_libdir}/lib\(pcprofile\|memusage\)\.so,d' \ + -e '\,.*/bin/\(memusage\|mtrace\|xtrace\|pcprofiledump\),d' +} | sort > master.filelist + +# The master file list is now used by each subpackage to list their own +# files. We go through each package and subpackage now and create their lists. +# Each subpackage picks the files from the master list that they need. +# The order of the subpackage list generation does not matter. + +# Make the master file list read-only after this point to avoid accidental +# modification. +chmod 0444 master.filelist + +############################################################################### +# glibc +############################################################################### + +# Add all files with the following exceptions: +# - The info files '%{_infodir}/dir' +# - The partial (lib*_p.a) static libraries, include files. +# - The static files, objects, unversioned DSOs, and nscd. +# - The bin, locale, some sbin, and share. +# - We want iconvconfig in the main package and we do this by using +# a double negation of -v and [^i] so it removes all files in +# sbin *but* iconvconfig. +# - All the libnss files (we add back the ones we want later). +# - All bench test binaries. +# - The aux-cache, since it's handled specially in the files section. +# - The build-locale-archive binary since it's in the common package. +cat master.filelist \ + | grep -v \ + -e '%{_infodir}' \ + -e '%{_libdir}/lib.*_p.a' \ + -e '%{_prefix}/include' \ + -e '%{_libdir}/lib.*\.a' \ + -e '%{_libdir}/.*\.o' \ + -e '%{_libdir}/lib.*\.so' \ + -e 'nscd' \ + -e '%{_prefix}/bin' \ + -e '%{_prefix}/lib/locale' \ + -e '%{_prefix}/sbin/[^i]' \ + -e '%{_prefix}/share' \ + -e '/var/db/Makefile' \ + -e '/libnss_.*\.so[0-9.]*$' \ + -e '/libnsl' \ + -e 'glibc-benchtests' \ + -e 'aux-cache' \ + -e 'build-locale-archive' \ + > glibc.filelist + +# Add specific files: +# - The nss_files, nss_compat, and nss_db files. +# - The libmemusage.so and libpcprofile.so used by utils. +for module in compat files dns; do + cat master.filelist \ + | grep -E \ + -e "/libnss_$module(\.so\.[0-9.]+|-[0-9.]+\.so)$" \ + >> glibc.filelist +done +grep -e "libmemusage.so" -e "libpcprofile.so" master.filelist >> glibc.filelist + +############################################################################### +# glibc-devel +############################################################################### + +%if %{with docs} +# Put the info files into the devel file list, but exclude the generated dir. +grep '%{_infodir}' master.filelist | grep -v '%{_infodir}/dir' > devel.filelist +%endif + +# Put some static files into the devel package. +grep '%{_libdir}/lib.*\.a' master.filelist \ + | grep '/lib\(\(c\|pthread\|nldbl\|mvec\)_nonshared\|g\|ieee\|mcheck\)\.a$' \ + >> devel.filelist + +# Put all of the object files and *.so (not the versioned ones) into the +# devel package. +grep '%{_libdir}/.*\.o' < master.filelist >> devel.filelist +grep '%{_libdir}/lib.*\.so' < master.filelist >> devel.filelist +# The exceptions are: +# - libmemusage.so and libpcprofile.so in glibc used by utils. +# - libnss_*.so which are in nss-devel. +sed -i -e '\,libmemusage.so,d' \ + -e '\,libpcprofile.so,d' \ + -e '\,/libnss_[a-z]*\.so$,d' \ + devel.filelist + +############################################################################### +# glibc-headers +############################################################################### + +# The glibc-headers package includes only common files which are identical +# across all multilib packages. We must keep gnu/stubs.h and gnu/lib-names.h +# in the glibc-headers package, but the -32, -64, -64-v1, and -64-v2 versions +# go into the development packages. +grep '%{_prefix}/include/gnu/stubs-.*\.h$' < master.filelist >> devel.filelist || : +grep '%{_prefix}/include/gnu/lib-names-.*\.h$' < master.filelist >> devel.filelist || : +# Put the include files into headers file list. +grep '%{_prefix}/include' < master.filelist \ + | egrep -v '%{_prefix}/include/gnu/stubs-.*\.h$' \ + | egrep -v '%{_prefix}/include/gnu/lib-names-.*\.h$' \ + > headers.filelist + +############################################################################### +# glibc-static +############################################################################### + +# Put the rest of the static files into the static package. +grep '%{_libdir}/lib.*\.a' < master.filelist \ + | grep -v '/lib\(\(c\|pthread\|nldbl\|mvec\)_nonshared\|g\|ieee\|mcheck\)\.a$' \ + > static.filelist + +############################################################################### +# glibc-common +############################################################################### + +# All of the bin and certain sbin files go into the common package except +# iconvconfig which needs to go in glibc. Likewise nscd is excluded because +# it goes in nscd. The iconvconfig binary is kept in the main glibc package +# because we use it in the post-install scriptlet to rebuild the +# gconv-modules.cache. +grep '%{_prefix}/bin' master.filelist >> common.filelist +grep '%{_prefix}/sbin' master.filelist \ + | grep -v '%{_prefix}/sbin/iconvconfig' \ + | grep -v 'nscd' >> common.filelist +# All of the files under share go into the common package since they should be +# multilib-independent. +# Exceptions: +# - The actual share directory, not owned by us. +# - The info files which go in devel, and the info directory. +grep '%{_prefix}/share' master.filelist \ + | grep -v \ + -e '%{_prefix}/share/info/libc.info.*' \ + -e '%%dir %{prefix}/share/info' \ + -e '%%dir %{prefix}/share' \ + >> common.filelist + +# Add the binary to build locales to the common subpackage. +echo '%{_prefix}/sbin/build-locale-archive' >> common.filelist + +############################################################################### +# nscd +############################################################################### + +# The nscd binary must go into the nscd subpackage. +echo '%{_prefix}/sbin/nscd' > nscd.filelist + +############################################################################### +# glibc-utils +############################################################################### + +# Add the utils scripts and programs to the utils subpackage. +cat > utils.filelist < nss_$module.filelist +done + +############################################################################### +# nss-devel +############################################################################### + +# Symlinks go into the nss-devel package (instead of the main devel +# package). +grep '/libnss_[a-z]*\.so$' master.filelist > nss-devel.filelist + +############################################################################### +# libnsl +############################################################################### + +# Prepare the libnsl-related file lists. +grep '/libnsl-[0-9.]*.so$' master.filelist > libnsl.filelist +test $(wc -l < libnsl.filelist) -eq 1 + +############################################################################### +# glibc-benchtests +############################################################################### + +# List of benchmarks. +find build-%{target}/benchtests -type f -executable | while read b; do + echo "%{_prefix}/libexec/glibc-benchtests/$(basename $b)" +done >> benchtests.filelist +# ... and the makefile. +for b in %{SOURCE9} %{SOURCE10}; do + echo "%{_prefix}/libexec/glibc-benchtests/$(basename $b)" >> benchtests.filelist +done +# ... and finally, the comparison scripts. +echo "%{_prefix}/libexec/glibc-benchtests/benchout.schema.json" >> benchtests.filelist +echo "%{_prefix}/libexec/glibc-benchtests/compare_bench.py*" >> benchtests.filelist +echo "%{_prefix}/libexec/glibc-benchtests/import_bench.py*" >> benchtests.filelist +echo "%{_prefix}/libexec/glibc-benchtests/validate_benchout.py*" >> benchtests.filelist +%endif + +############################################################################### +# compat-libpthread-nonshared +############################################################################### +echo "%{_libdir}/libpthread_nonshared.a" >> compat-libpthread-nonshared.filelist + +############################################################################### +# glibc-debuginfocommon, and glibc-debuginfo +############################################################################### + +find_debuginfo_args='--strict-build-id -g -i' +%ifarch %{debuginfocommonarches} +find_debuginfo_args="$find_debuginfo_args \ + -l common.filelist \ + -l utils.filelist \ + -l nscd.filelist \ + -p '.*/(sbin|libexec)/.*' \ + -o debuginfocommon.filelist \ + -l nss_db.filelist -l nss_hesiod.filelist \ + -l libnsl.filelist -l glibc.filelist \ +%if %{with benchtests} + -l benchtests.filelist +%endif + " +%endif + +/usr/lib/rpm/find-debuginfo.sh $find_debuginfo_args -o debuginfo.filelist + +# List all of the *.a archives in the debug directory. +list_debug_archives() +{ + local dir=%{_prefix}/lib/debug%{_libdir} + find %{glibc_sysroot}$dir -name "*.a" -printf "$dir/%%P\n" +} + +%ifarch %{debuginfocommonarches} + +# Remove the source files from the common package debuginfo. +sed -i '\#^%{glibc_sysroot}%{_prefix}/src/debug/#d' debuginfocommon.filelist + +# Create a list of all of the source files we copied to the debug directory. +find %{glibc_sysroot}%{_prefix}/src/debug \ + \( -type d -printf '%%%%dir ' \) , \ + -printf '%{_prefix}/src/debug/%%P\n' > debuginfocommon.sources + +%ifarch %{biarcharches} + +# Add the source files to the core debuginfo package. +cat debuginfocommon.sources >> debuginfo.filelist + +%else + +%ifarch %{ix86} +%define basearch i686 +%endif +%ifarch sparc sparcv9 +%define basearch sparc +%endif + +# The auxarches get only these few source files. +auxarches_debugsources=\ +'/(generic|linux|%{basearch}|nptl(_db)?)/|/%{glibcsrcdir}/build|/dl-osinfo\.h' + +# Place the source files into the core debuginfo pakcage. +egrep "$auxarches_debugsources" debuginfocommon.sources >> debuginfo.filelist + +# Remove the source files from the common debuginfo package. +egrep -v "$auxarches_debugsources" \ + debuginfocommon.sources >> debuginfocommon.filelist + +%comment Matches: %ifarch %{biarcharches} +%endif + +# Add the list of *.a archives in the debug directory to +# the common debuginfo package. +list_debug_archives >> debuginfocommon.filelist + +%comment Matches: %ifarch %{debuginfocommonarches} +%endif + +# Remove some common directories from the common package debuginfo so that we +# don't end up owning them. +exclude_common_dirs() +{ + exclude_dirs="%{_prefix}/src/debug" + exclude_dirs="$exclude_dirs $(echo %{_prefix}/lib/debug{,/%{_lib},/bin,/sbin})" + exclude_dirs="$exclude_dirs $(echo %{_prefix}/lib/debug%{_prefix}{,/%{_lib},/libexec,/bin,/sbin})" + + for d in $(echo $exclude_dirs | sed 's/ /\n/g'); do + sed -i "\|^%%dir $d/\?$|d" $1 + done +} + +%ifarch %{debuginfocommonarches} +exclude_common_dirs debuginfocommon.filelist +%endif +exclude_common_dirs debuginfo.filelist + +%comment Matches: %if 0%{?_enable_debug_packages} +%endif + +############################################################################## +# Delete files that we do not intended to ship with the auxarch. +# This is the only place where we touch the installed files after generating +# the file lists. +############################################################################## +%ifarch %{auxarches} +echo Cutting down the list of unpackaged files +sed -e '/%%dir/d;/%%config/d;/%%verify/d;s/%%lang([^)]*) //;s#^/*##' \ + common.filelist devel.filelist static.filelist headers.filelist \ + utils.filelist nscd.filelist \ +%ifarch %{debuginfocommonarches} + debuginfocommon.filelist \ +%endif + | (cd %{glibc_sysroot}; xargs --no-run-if-empty rm -f 2> /dev/null || :) +%comment Matches: %ifarch %{auxarches} +%endif + +############################################################################## +# Run the glibc testsuite +############################################################################## %check %if %{with testsuite} + +# Run the glibc tests. If any tests fail to build we exit %check with +# an error, otherwise we print the test failure list and the failed +# test output and continue. Write to standard error to avoid +# synchronization issues with make and shell tracing output if +# standard output and standard error are different pipes. run_tests () { - %make_build check |& tee rpmbuild.check.log >&2 + # This hides a test suite build failure, which should be fatal. We + # check "Summary of test results:" below to verify that all tests + # were built and run. + make %{?_smp_mflags} -O check |& tee rpmbuild.check.log >&2 test -n tests.sum if ! grep -q '^Summary of test results:$' rpmbuild.check.log ; then echo "FAIL: test suite build of target: $(basename "$(pwd)")" >& 2 @@ -636,53 +2290,71 @@ run_tests () { while read failed_code failed_test ; do for suffix in out test-result ; do if test -e "$failed_test.$suffix"; then - echo >&2 + echo >&2 echo "=====$failed_code $failed_test.$suffix=====" >&2 cat -- "$failed_test.$suffix" >&2 - echo >&2 + echo >&2 fi done done &2 cat misc/tst-syscall-list.out >&2 set -x } +# Increase timeouts export TIMEOUTFACTOR=16 parent=$$ echo ====================TESTING========================= +# Default libraries. pushd build-%{target} run_tests popd +%if %{buildpower9} +echo ====================TESTING -mcpu=power9============= +pushd build-%{target}-power9 +run_tests +popd +%endif + + + echo ====================TESTING END===================== PLTCMD='/^Relocation section .*\(\.rela\?\.plt\|\.rela\.IA_64\.pltoff\)/,/^$/p' echo ====================PLT RELOCS LD.SO================ -readelf -Wr %{buildroot}/%{_lib}/ld-*.so | sed -n -e "$PLTCMD" +readelf -Wr %{glibc_sysroot}/%{_lib}/ld-*.so | sed -n -e "$PLTCMD" echo ====================PLT RELOCS LIBC.SO============== -readelf -Wr %{buildroot}/%{_lib}/libc-*.so | sed -n -e "$PLTCMD" +readelf -Wr %{glibc_sysroot}/%{_lib}/libc-*.so | sed -n -e "$PLTCMD" echo ====================PLT RELOCS END================== -ldso_path="$(find %{buildroot}/ -regextype posix-extended \ - -regex '.*/ld(-.*|64|)\.so\.[0-9]+$' -type f | LC_ALL=C sort | head -n1)" -run_ldso="$ldso_path --library-path %{buildroot}/%{_lib}" +# Finally, check if valgrind runs with the new glibc. +# We want to fail building if valgrind is not able to run with this glibc so +# that we can then coordinate with valgrind to get it fixed before we update +# glibc. +pushd build-%{target} -LD_SHOW_AUXV=1 $run_ldso /bin/true +# Show the auxiliary vector as seen by the new library +# (even if we do not perform the valgrind test). +LD_SHOW_AUXV=1 elf/ld.so --library-path .:elf:nptl:dlfcn /bin/true -%if 0%{?_enable_debug_packages} %if %{with valgrind} -$run_ldso /usr/bin/valgrind --error-exitcode=1 $run_ldso /usr/bin/true -$run_ldso /usr/bin/valgrind --error-exitcode=1 $run_ldso /usr/bin/true --help >/dev/null -%endif +elf/ld.so --library-path .:elf:nptl:dlfcn \ + /usr/bin/valgrind --error-exitcode=1 \ + elf/ld.so --library-path .:elf:nptl:dlfcn /usr/bin/true %endif +popd +%comment Matches: %if %{run_glibc_tests} %endif %pre -p +-- Check that the running kernel is new enough required = '%{enablekernel}' rel = posix.uname("%r") if rpm.vercmp(rel, required) < 0 then @@ -690,77 +2362,94 @@ if rpm.vercmp(rel, required) < 0 then end %post -p -%glibc_post_funcs --- (1) Remove multilib libraries from previous installs. -install_libs = { "anl", "BrokenLocale", "c", "dl", "m", "mvec", - "nss_compat", "nss_db", "nss_dns", "nss_files", - "nss_hesiod", "pthread", "resolv", "rt", "SegFault", - "thread_db", "util" } - -remove_regexps = {} -for i = 1, #install_libs do - remove_regexps[#remove_regexps + 1] = ("lib" .. install_libs[i] - .. "%%-[2-9]%%.[0-9]+%%.so$") - remove_regexps[#remove_regexps + 1] = ("lib" .. install_libs[i] - .. "%%.so%%.[0-9]+$") +-- We use lua's posix.exec because there may be no shell that we can +-- run during glibc upgrade. +function post_exec (program, ...) + local pid = posix.fork () + if pid == 0 then + assert (posix.exec (program, ...)) + elseif pid > 0 then + posix.wait (pid) + end end +-- (1) Remove multilib libraries from previous installs. +-- In order to support in-place upgrades, we must immediately remove +-- obsolete platform directories after installing a new glibc +-- version. RPM only deletes files removed by updates near the end +-- of the transaction. If we did not remove the obsolete platform +-- directories here, they may be preferred by the dynamic linker +-- during the execution of subsequent RPM scriptlets, likely +-- resulting in process startup failures. + +-- Full set of libraries glibc may install. +install_libs = { "anl", "BrokenLocale", "c", "dl", "m", "mvec", + "nss_compat", "nss_db", "nss_dns", "nss_files", + "nss_hesiod", "pthread", "resolv", "rt", "SegFault", + "thread_db", "util" } + +-- We are going to remove these libraries. Generally speaking we remove +-- all core libraries in the multilib directory. +-- We employ a tight match where X.Y is in [2.0,9.9*], so we would +-- match "libc-2.0.so" and so on up to "libc-9.9*". +remove_regexps = {} +for i = 1, #install_libs do + remove_regexps[i] = ("lib" .. install_libs[i] + .. "%%-[2-9]%%.[0-9]+%%.so$") +end + +-- Two exceptions: remove_regexps[#install_libs + 1] = "libthread_db%%-1%%.0%%.so" remove_regexps[#install_libs + 2] = "libSegFault%%.so" +-- We are going to search these directories. local remove_dirs = { "%{_libdir}/i686", - "%{_libdir}/i686/nosegneg", - "%{_libdir}/power6", - "%{_libdir}/power7", - "%{_libdir}/power8", - "%{_libdir}/power9", - } - -repeat - local iter = posix.files("%{_libdir}/glibc-hwcaps") - if iter ~= nil then - for entry in iter do - if entry ~= "." and entry ~= ".." then - local path = "%{_libdir}/glibc-hwcaps/" .. entry - if posix.access(path .. "/.", "x") then - remove_dirs[#remove_dirs + 1] = path - end - end - end - end -until true + "%{_libdir}/i686/nosegneg", + "%{_libdir}/power6", + "%{_libdir}/power7", + "%{_libdir}/power8", + "%{_libdir}/power9"} +-- Walk all the directories with files we need to remove... for _, rdir in ipairs (remove_dirs) do if posix.access (rdir) then -- If the directory exists we look at all the files... local remove_files = posix.files (rdir) for rfile in remove_files do for _, rregexp in ipairs (remove_regexps) do - -- Does it match the regexp? - local dso = string.match (rfile, rregexp) + -- Does it match the regexp? + local dso = string.match (rfile, rregexp) if (dso ~= nil) then - -- Removing file... - os.remove (rdir .. '/' .. rfile) - end + -- Removing file... + os.remove (rdir .. '/' .. rfile) + end end end end end -- (2) Update /etc/ld.so.conf +-- Next we update /etc/ld.so.conf to ensure that it starts with +-- a literal "include ld.so.conf.d/*.conf". local ldsoconf = "/etc/ld.so.conf" local ldsoconf_tmp = "/etc/glibc_post_upgrade.ld.so.conf" if posix.access (ldsoconf) then + + -- We must have a "include ld.so.conf.d/*.conf" line. local have_include = false for line in io.lines (ldsoconf) do + -- This must match, and we don't ignore whitespace. if string.match (line, "^include ld.so.conf.d/%%*%%.conf$") ~= nil then have_include = true end end if not have_include then + -- Insert "include ld.so.conf.d/*.conf" line at the start of the + -- file. We only support one of these post upgrades running at + -- a time (temporary file name is fixed). local tmp_fd = io.open (ldsoconf_tmp, "w") if tmp_fd ~= nil then tmp_fd:write ("include ld.so.conf.d/*.conf\n") @@ -779,161 +2468,121 @@ if posix.access (ldsoconf) then end -- (3) Rebuild ld.so.cache early. +-- If the format of the cache changes then we need to rebuild +-- the cache early to avoid any problems running binaries with +-- the new glibc. +-- Note: We use _prefix because Fedora's UsrMove says so. post_exec ("%{_prefix}/sbin/ldconfig") -- (4) Update gconv modules cache. +-- If the /usr/lib/gconv/gconv-modules.cache exists, then update it +-- with the latest set of modules that were just installed. +-- We assume that the cache is in _libdir/gconv and called +-- "gconv-modules.cache". -update_gconv_modules_cache() +local iconv_dir = "%{_libdir}/gconv" +local iconv_cache = iconv_dir .. "/gconv-modules.cache" +if (posix.utime (iconv_cache) == 0) then + post_exec ("%{_prefix}/sbin/iconvconfig", + "-o", iconv_cache, + "--nostdlib", + iconv_dir) +else + io.stdout:write ("Error: Missing " .. iconv_cache .. " file.\n") +end --- (5) On upgrades, restart systemd if installed. - -if tonumber(arg[2]) >= 2 - and posix.access("%{_prefix}/bin/systemctl", "x") -then - local pid = posix.fork() +%posttrans all-langpacks -e -p +-- If at the end of the transaction we are still installed +-- (have a template of non-zero size), then we rebuild the +-- locale cache (locale-archive) from the pre-populated +-- locale cache (locale-archive.tmpl) i.e. template. +if posix.stat("%{_prefix}/lib/locale/locale-archive.tmpl", "size") > 0 then + pid = posix.fork() if pid == 0 then - posix.redirect2null(2) - assert(posix.exec("%{_prefix}/bin/systemctl", "daemon-reexec")) + posix.exec("%{_prefix}/sbin/build-locale-archive", "--install-langs", "%%{_install_langs}") elseif pid > 0 then posix.wait(pid) end end -%posttrans all-langpacks -e -p -local archive_path = "%{_prefix}/lib/locale/locale-archive" -local real_path = "%{_prefix}/lib/locale/locale-archive.real" -local stat_archive = posix.stat(archive_path) -local stat_real = posix.stat(real_path) -if stat_archive ~= nil and stat_real ~= nil - and (stat_archive.ino ~= stat_real.ino - or stat_archive.dev ~= stat_real.dev) then - posix.unlink(archive_path) - stat_archive = nil -end -if stat_archive == nil then - posix.link(real_path, archive_path) -end -local save_path = archive_path .. ".rpmsave" -if posix.access(save_path) then - posix.unlink(save_path) +%postun all-langpacks -p +-- In the postun we remove the locale cache if unstalling. +-- (build-locale-archive will delete the archive during an upgrade.) +if arg[2] == 0 then + os.remove("%{_prefix}/lib/locale/locale-archive") end -%post gconv-extra -p -%glibc_post_funcs -update_gconv_modules_cache () - -%postun gconv-extra -p -%glibc_post_funcs -update_gconv_modules_cache () - -%files -%ifarch x86_64 -/lib64/ld-linux-x86-64.so.2 +%if %{with docs} +%post devel +/sbin/install-info %{_infodir}/libc.info.gz %{_infodir}/dir > /dev/null 2>&1 || : %endif -%ifarch aarch64 -/lib/ld-linux-aarch64.so.1 +%pre headers +# this used to be a link and it is causing nightmares now +if [ -L %{_prefix}/include/scsi ] ; then + rm -f %{_prefix}/include/scsi +fi + +%if %{with docs} +%preun devel +if [ "$1" = 0 ]; then + /sbin/install-info --delete %{_infodir}/libc.info.gz %{_infodir}/dir > /dev/null 2>&1 || : +fi %endif -%ifarch loongarch64 -/lib64/ld-linux-loongarch-lp64d.so.1 -%endif +%pre -n nscd +getent group nscd >/dev/null || /usr/sbin/groupadd -g 28 -r nscd +getent passwd nscd >/dev/null || + /usr/sbin/useradd -M -o -r -d / -s /sbin/nologin \ + -c "NSCD Daemon" -u 28 -g nscd nscd -/lib64/libBrokenLocale.so.1 -%ifnarch loongarch64 -/lib64/libmvec.so.1 -/lib64/libanl.so.1 -/lib64/libutil.so.1 +%post -n nscd +%systemd_post nscd.service + +%preun -n nscd +%systemd_preun nscd.service + +%postun -n nscd +if test $1 = 0; then + /usr/sbin/userdel nscd > /dev/null 2>&1 || : +fi +%systemd_postun_with_restart nscd.service + +%files -f glibc.filelist +%dir %{_prefix}/%{_lib}/audit +%if %{buildpower9} +%dir /%{_lib}/glibc-hwcaps/power9 %endif -/lib64/libc.so.6 -/lib64/libc_malloc_debug.so.0 -/lib64/libdl.so.2 -/lib64/libm.so.6 -/lib64/libpthread.so.0 -/lib64/libresolv.so.2 -/lib64/librt.so.1 -/lib64/libthread_db.so.1 -/lib64/libnss_compat.so.2 -/lib64/libnss_files.so.2 -/lib64/libnss_dns.so.2 -/usr/lib64/libmemusage.so -/usr/lib64/libpcprofile.so -/usr/lib64/gconv/ANSI_X3.110.so -/usr/lib64/gconv/CP1252.so -/usr/lib64/gconv/ISO8859-1.so -/usr/lib64/gconv/ISO8859-15.so -/usr/lib64/gconv/UNICODE.so -/usr/lib64/gconv/UTF-16.so -/usr/lib64/gconv/UTF-32.so -/usr/lib64/gconv/UTF-7.so -/usr/lib64/audit/sotruss-lib.so -/sbin/ldconfig -/usr/sbin/iconvconfig -%dir %{_prefix}/libexec/getconf -%{_prefix}/libexec/getconf/POSIX_V6_LP64_OFF64 -%{_prefix}/libexec/getconf/POSIX_V7_LP64_OFF64 -%{_prefix}/libexec/getconf/XBS5_LP64_OFF64 +%ifarch s390x +/lib/ld64.so.1 +%endif +%verify(not md5 size mtime) %config(noreplace) /etc/nsswitch.conf %verify(not md5 size mtime) %config(noreplace) /etc/ld.so.conf %verify(not md5 size mtime) %config(noreplace) /etc/rpc %dir /etc/ld.so.conf.d -%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/ld.so.cache -%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/gai.conf +%dir %{_prefix}/libexec/getconf %dir %{_libdir}/gconv -%dir %{_libdir}/gconv/gconv-modules.d -%verify(not md5 size mtime) %config(noreplace) /usr/lib64/gconv/gconv-modules -%verify(not md5 size mtime) /usr/lib64/gconv/gconv-modules.cache -%dir %{_prefix}/%{_lib}/audit %dir %attr(0700,root,root) /var/cache/ldconfig %attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/cache/ldconfig/aux-cache +%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/ld.so.cache +%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/gai.conf +%doc README NEWS INSTALL elf/rtld-debugger-interface.txt +# If rpm doesn't support %license, then use %doc instead. +%{!?_licensedir:%global license %%doc} %license COPYING COPYING.LIB LICENSES - -%files common -%{_bindir}/gencat -%{_bindir}/getconf -%{_bindir}/getent -%{_bindir}/iconv -%{_bindir}/ld.so -%{_bindir}/ldd -%{_bindir}/locale -%{_bindir}/localedef -%{_bindir}/pldd -%{_bindir}/sotruss -%{_bindir}/sprof -%{_bindir}/tzselect -%{_bindir}/zdump -%{_sbindir}/zic -%dir /usr/share/i18n -%dir /usr/share/i18n/charmaps -%dir /usr/share/i18n/locales -/usr/share/locale/locale.alias +%ifnarch %{auxarches} +%files -f common.filelist common %dir %{_prefix}/lib/locale %dir %{_prefix}/lib/locale/C.utf8 %{_prefix}/lib/locale/C.utf8/* +%doc documentation/README.timezone +%doc documentation/gai.conf %files all-langpacks -%{_prefix}/lib/locale -%{_prefix}/lib/locale/locale-archive -%{_prefix}/lib/locale/locale-archive.real -%{_prefix}/share/locale/*/LC_MESSAGES/libc.mo -%exclude %{_prefix}/lib/locale/C.utf8 -%exclude %{_prefix}/lib/locale/zh* -%exclude %{_prefix}/lib/locale/en* -%exclude %{_prefix}/share/locale/zh* -%exclude %{_prefix}/share/locale/en* - -%files minimal-langpack - -%files langpack-en -%dir %{_prefix}/lib/locale -%{_prefix}/lib/locale/en* -%{_prefix}/share/locale/en_*/LC_MESSAGES/libc.mo - -%files langpack-zh -%dir %{_prefix}/lib/locale -%{_prefix}/lib/locale/zh* -%{_prefix}/share/locale/zh_*/LC_MESSAGES/libc.mo +%attr(0644,root,root) %verify(not md5 size mtime) %{_prefix}/lib/locale/locale-archive.tmpl +%attr(0644,root,root) %verify(not md5 size mtime mode) %ghost %{_prefix}/lib/locale/locale-archive %files locale-source %dir %{_prefix}/share/i18n/locales @@ -941,210 +2590,1287 @@ update_gconv_modules_cache () %dir %{_prefix}/share/i18n/charmaps %{_prefix}/share/i18n/charmaps/* -%files devel -%ifnarch loongarch64 -/usr/lib64/libanl.a -%endif -/usr/lib64/libc_nonshared.a -/usr/lib64/libdl.a -/usr/lib64/libg.a -/usr/lib64/libmcheck.a -/usr/lib64/libpthread.a -/usr/lib64/librt.a -/usr/lib64/libutil.a -/usr/lib64/Mcrt1.o -/usr/lib64/Scrt1.o -/usr/lib64/crt1.o -/usr/lib64/crti.o -/usr/lib64/crtn.o -/usr/lib64/gcrt1.o -/usr/lib64/grcrt1.o -/usr/lib64/rcrt1.o -/usr/lib64/libBrokenLocale.so -%ifnarch loongarch64 -/usr/lib64/libmvec.so -/usr/lib64/libanl.so -%endif -/usr/lib64/libc.so -/usr/lib64/libm.so -/usr/lib64/libresolv.so -/usr/lib64/libthread_db.so -/usr/include/*.h -%dir /usr/include/arpa -/usr/include/arpa/*.h -%dir /usr/include/bits -/usr/include/bits/*.h -/usr/include/bits/stab.def -%dir /usr/include/bits/types -/usr/include/bits/types/*.h -%dir /usr/include/finclude -/usr/include/finclude/math-vector-fortran.h -%dir /usr/include/gnu -/usr/include/gnu/*.h -%dir /usr/include/net -/usr/include/net/*.h -%dir /usr/include/netash -/usr/include/netash/ash.h -%dir /usr/include/netatalk -/usr/include/netatalk/at.h -%dir /usr/include/netax25 -/usr/include/netax25/ax25.h -%dir /usr/include/neteconet -/usr/include/neteconet/ec.h -%dir /usr/include/netinet -/usr/include/netinet/*.h -%dir /usr/include/netipx -/usr/include/netipx/ipx.h -%dir /usr/include/netiucv -/usr/include/netiucv/iucv.h -%dir /usr/include/netpacket -/usr/include/netpacket/packet.h -%dir /usr/include/netrom -/usr/include/netrom/netrom.h -%dir /usr/include/netrose -/usr/include/netrose/rose.h -%dir /usr/include/nfs -/usr/include/nfs/nfs.h -%dir /usr/include/protocols -/usr/include/protocols/routed.h -/usr/include/protocols/rwhod.h -/usr/include/protocols/talkd.h -/usr/include/protocols/timed.h -%dir /usr/include/rpc -/usr/include/rpc/netdb.h -%dir /usr/include/scsi -/usr/include/scsi/scsi.h -/usr/include/scsi/scsi_ioctl.h -/usr/include/scsi/sg.h -%dir /usr/include/sys -/usr/include/sys/*.h +%files -f devel.filelist devel -%ifarch x86_64 -%dir /usr/include/sys/platform -/usr/include/sys/platform/*.h -%dir /usr/include/bits/platform -/usr/include/bits/platform/*.h +%files -f static.filelist static + +%files -f headers.filelist headers + +%files -f utils.filelist utils + +%files -f nscd.filelist -n nscd +%config(noreplace) /etc/nscd.conf +%dir %attr(0755,root,root) /var/run/nscd +%dir %attr(0755,root,root) /var/db/nscd +/lib/systemd/system/nscd.service +/lib/systemd/system/nscd.socket +%{_tmpfilesdir}/nscd.conf +%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/nscd.pid +%attr(0666,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/socket +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/passwd +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/group +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/hosts +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/services +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/passwd +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/group +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/hosts +%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/services +%ghost %config(missingok,noreplace) /etc/sysconfig/nscd %endif -%if %{with docs} -%files doc -/usr/share/info/libc.info-* -/usr/share/info/libc.info.* -%dir /usr/share/doc -%dir /usr/share/doc/glibc -/usr/share/doc/glibc/rtld-debugger-interface.txt -%endif - -%files static -%{_libdir}/libBrokenLocale.a -%{_libdir}/libc.a -%{_libdir}/libm.a -%{_libdir}/libresolv.a -%ifnarch loongarch64 -%{_libdir}/libm-%{version}.a -%{_libdir}/libmvec.a -%endif - -%files utils -%if %{without bootstrap} -%{_bindir}/memusage -%{_bindir}/memusagestat -%endif -%{_bindir}/mtrace -%{_bindir}/pcprofiledump -%{_bindir}/xtrace - -%files gconv-extra -%verify(not md5 size mtime) %config(noreplace) /usr/lib64/gconv/gconv-modules.d/gconv-modules-extra.conf -/usr/lib64/gconv/*.so -%exclude /usr/lib64/gconv/{ANSI_X3.110,CP1252,ISO8859-1,ISO8859-15,UNICODE,UTF-16,UTF-32,UTF-7}.so - -%files -n nss_db +%files -f nss_db.filelist -n nss_db /var/db/Makefile -/lib64/libnss_db.so.2 -%{_bindir}/makedb - -%files -n nss_hesiod -/lib64/libnss_hesiod.so.2 +%files -f nss_hesiod.filelist -n nss_hesiod %doc hesiod/README.hesiod +%files -f nss-devel.filelist nss-devel -%files nss-devel -%{_libdir}/libnss_compat.so -%{_libdir}/libnss_db.so -%{_libdir}/libnss_hesiod.so +%files -f libnsl.filelist -n libnsl +/%{_lib}/libnsl.so.1 -%ifnarch loongarch64 -%files -n libnsl -/lib64/libnsl.so.1 +%if 0%{?_enable_debug_packages} +%files debuginfo -f debuginfo.filelist +%ifarch %{debuginfocommonarches} +%ifnarch %{auxarches} +%files debuginfo-common -f debuginfocommon.filelist +%endif +%endif %endif %if %{with benchtests} -%files benchtests -/usr/libexec/glibc-benchtests/* +%files benchtests -f benchtests.filelist %endif -%files -n compat-libpthread-nonshared -%{_libdir}/libpthread_nonshared.a +%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared %changelog -* Thu May 09 2024 Zhenyu Wang - 2.38-3 -- fix CVE-2024-2961 +* Thu Jan 27 2022 Siddhesh Poyarekar - 2.28-164.3 +- CVE-2021-3999: getcwd: align stack on clone in aarch64 and fix a memory leak + (#2032280) -* Sat Mar 16 2024 Peng Fan - 2.38-2 -- LoongArch: sync patch from glibc upstream -- Reduced kernel version requirements +* Wed Jan 26 2022 Siddhesh Poyarekar - 2.28-164.2 +- CVE-2022-23218, CVE-2022-23219: Fix buffer overflows in sunrpc clnt_create + for "unix" and svcunix_create (#2045062). -* Tue Mar 05 2024 mgb01105731 - 2.38-1 -- update to 2.38 +* Mon Jan 24 2022 Siddhesh Poyarekar - 2.28-164.1 +- CVE-2021-3999: getcwd: Set errno to ERANGE for size == 1 (#2032280) -* Thu Feb 01 2024 Funda Wang - 2.36-13 -- fix CVE-2023-6246, CVE-2023-6779, and CVE-2023-6780. +* Mon Aug 9 2021 Siddhesh Poyarekar - 2.28-164 +- librt: fix NULL pointer dereference (#1966472). -* Tue Oct 24 2023 Peng Fan - 2.36-12 -- LoongArch: Not provided libanl, libnsl and libutil by LoongArch. +* Mon Aug 9 2021 Siddhesh Poyarekar - 2.28-163 +- CVE-2021-33574: Deep copy pthread attribute in mq_notify (#1966472) -* Wed Oct 11 2023 Peng Fan - 2.36-11 -- LoongArch: Ignore kernel version checks. -- Temporarily not pack libanl.so and libutil.so in LoongArch. +* Thu Jul 8 2021 Siddhesh Poyarekar - 2.28-162 +- CVE-2021-35942: wordexp: handle overflow in positional parameter number + (#1979127) -* Wed Oct 04 2023 Funda Wang - 2.36-10 -- fix CVE-2023-4527, CVE-2023-4806, CVE-2023-5156, CVE-2023-4911 +* Fri Jun 18 2021 Carlos O'Donell - 2.28-161 +- Improve POWER10 performance with POWER9 fallbacks (#1956357) -* Tue Aug 15 2023 Funda Wang - 2.36-9 -- Add patch for gb18030-2022 from upstream bug#30243 -- Correctly move langpack-cmn into langpack-zh +* Mon May 31 2021 Arjun Shankar - 2.28-160 +- Backport POWER10 optimized rawmemchr for ppc64le (#1956357) -* Tue Aug 8 2023 Peng Fan - 2.36-8 -- LoongArch: backport from upstream. -- upstream commit: eaa5b1cce87d34c945955360b1e519c6994308a1 +* Thu May 27 2021 Arjun Shankar - 2.28-159 +- Backport additional ifunc optimizations for ppc64le (#1956357) -* Fri Apr 14 2023 Chunmei Xu - 2.36-7 -- optimise spec file +* Thu Apr 22 2021 Florian Weimer - 2.28-158 +- Rebuild with new binutils (#1946518) -* Tue Mar 28 2023 mgb01105731 - 2.36-6 -- Del Specific Fields +* Wed Apr 14 2021 Siddhesh Poyarekar - 2.28-157 +- Consistently SXID_ERASE tunables in sxid binaries (#1934155) -* Wed Feb 22 2023 Chunmei Xu - 2.36-5 -- recover to provide glibc-minimal-langpack +* Wed Mar 31 2021 DJ Delorie - 2.28-156 +- Backport ifunc optimizations for glibc for ppc64le (#1918719) -* Wed Feb 22 2023 Chunmei Xu - 2.36-4 -- remove glibc-minimal-langpack -- add glibc-langpack-en/zh as suggests for glibc +* Wed Mar 24 2021 Arjun Shankar - 2.28-155 +- CVE-2021-27645: nscd: Fix double free in netgroupcache (#1927877) -* Thu Jan 5 2023 Chunmei Xu - 2.36-3 -- sync patches from 2.36 release branch, upstream commit 4f4d7a13edfd2fdc57c9d76e1fd6d017fb47550c -- move glibc-langpack-xxx subpackage to glibc-all-langpacks except glibc-langpack-en/zh +* Thu Mar 18 2021 Carlos O'Donell - 2.28-154 +- Add IPPROTO_ETHERNET, IPPROTO_MPTCP, and INADDR_ALLSNOOPERS_GROUP defines + (#1930302) -* Thu Sep 1 2022 Chunmei Xu - 2.36-2 -- sync patches from 2.36 release branch -- upstream commit: b3736d1a3c60a3ec9959bf3b38794958546bf6a2 +* Thu Mar 18 2021 Carlos O'Donell - 2.28-153 +- Support SEM_STAT_ANY via semctl. Return EINVAL for unknown commands to semctl, + msgctl, and shmctl. (#1912670) -* Thu Aug 04 2022 Chunmei Xu - 2.36-1 -- rebase to 2.36 +* Tue Mar 16 2021 Patsy Griffin - 2.28-152 +- Update syscall-names.list to 5.7, 5.8, 5.9, 5.10 and 5.11. (#1871386) -* Mon Jul 11 2022 Weisson - 2.35-2 -- Add support for riscv64 -- RISC-V ABI wants to install everything in /lib64/lp64d or /usr/lib64/lp64d. Make these be symlinks to /lib64 or /usr/lib64 respectively. +* Mon Mar 15 2021 Siddhesh Poyarekar - 2.28-151 +- CVE-2019-9169: Fix buffer overread in regexec.c (#1936864). -* Tue Feb 22 2022 Chunmei Xu - 2.35-1 -- upstream 2.35 release tarball and add patches from release/2.35/master +* Mon Mar 15 2021 Siddhesh Poyarekar - 2.28-150 +- Rebuild glibc to update security markup metadata (#1935128) + +* Mon Mar 15 2021 Siddhesh Poyarekar - 2.28-149 +- Fix NSS files and compat service upgrade defect (#1932770). + +* Fri Feb 5 2021 Florian Weimer - 2.28-148 +- CVE-2021-3326: iconv assertion failure in ISO-2022-JP-3 decoding (#1924919) + +* Wed Jan 20 2021 Florian Weimer - 2.28-147 +- x86-64: Fix FMA4 math routine selection after bug 1817513 (#1918115) + +* Mon Jan 18 2021 Siddhesh Poyarekar - 2.28-146 +- CVE-2019-25013:Fix buffer overrun in EUC-KR conversion module (#1912544) + +* Mon Jan 4 2021 Florian Weimer - 2.28-145 +- Update glibc-hwcaps fix from upstream (#1817513) + +* Tue Dec 15 2020 Florian Weimer - 2.28-144 +- Support running libc.so.6 as a main program in more cases (#1882466) + +* Thu Dec 10 2020 Florian Weimer - 2.28-142 +- Add glibc-hwcaps support (#1817513) +- Implement DT_AUDIT support (#1871385) + +* Mon Nov 30 2020 Carlos O'Donell - 2.28-141 +- Update Intel CET support (#1855790) + +* Tue Nov 10 2020 Carlos O'Donell - 2.28-140 +- Fix calling lazily-bound SVE-using functions on AArch64 (#1893662) + +* Tue Nov 10 2020 Arjun Shankar - 2.28-139 +- CVE-2016-10228, CVE-2020-27618: Fix infinite loops in iconv (#1704868, + #1894669) + +* Fri Nov 6 2020 Florian Weimer - 2.28-138 +- Avoid comments after %%endif in the RPM spec file (#1894340) + +* Fri Oct 30 2020 Florian Weimer - 2.28-137 +- x86: Further memcpy optimizations for AMD Zen (#1880670) + +* Tue Oct 27 2020 DJ Delorie - 2.28-136 +- Allow __getauxval in testsuite check (#1856398) + +* Wed Oct 21 2020 DJ Delorie - 2.28-135 +- Use -moutline-atomics for aarch64 (#1856398) + +* Tue Oct 20 2020 Florian Weimer - 2.28-134 +- resolv: Handle DNS transaction ID collisions (#1868106) + +* Tue Oct 20 2020 Florian Weimer - 2.28-133 +- x86: Update auto-tuning of memcpy non-temporal threshold (#1880670) + +* Mon Oct 5 2020 DJ Delorie - 2.28-132 +- Fix fgetsgent_r data corruption bug (#1871397) + +* Fri Oct 02 2020 Patsy Griffin - 2.28-131 +- Improve IBM zSeries (s390x) Performance (#1871395) + +* Fri Oct 02 2020 Patsy Griffin - 2.28-130 +- Fix avx2 strncmp offset compare condition check (#1871394) +- Add strncmp and strcmp testcases for page boundary + +* Fri Sep 18 2020 Arjun Shankar - 2.28-129 +- Improve IBM POWER9 architecture performance (#1871387) + +* Thu Sep 17 2020 Arjun Shankar - 2.28-128 +- Enable glibc for POWER10 (#1845098) + +* Tue Jun 09 2020 Carlos O'Donell - 2.28-127 +- Improve performance of library strstr() function (#1821531) + +* Wed May 27 2020 Florian Weimer - 2.28-126 +- Do not clobber errno in nss_compat (#1836867) + +* Thu May 14 2020 Carlos O'Donell - 2.28-125 +- Support building rpm under newer versions of Coverity Scan (#1835999) + +* Mon May 11 2020 Florian Weimer - 2.28-124 +- Enhance memory protection key support on ppc64le (#1642150) + +* Thu Apr 23 2020 Florian Weimer - 2.28-123 +- Reduce IFUNC resolver usage in libpthread and librt (#1748197) + +* Thu Apr 9 2020 DJ Delorie - 2.28-122 +- Math library optimizations for IBM Z (#1780204) +- Additional patch for s_nearbyint.c + +* Wed Apr 8 2020 Florian Weimer - 2.28-121 +- elf: Assign TLS modid later during dlopen (#1774115) + +* Wed Apr 8 2020 Florian Weimer - 2.28-120 +- x86-64: Automatically install nss_db.i686 for 32-bit environments (#1807824) + +* Tue Apr 7 2020 Florian Weimer - 2.28-119 +- ppc64le: Enable protection key support (#1642150) + +* Tue Apr 7 2020 Florian Weimer - 2.28-118 +- ppc64le: floating-point status and exception optimizations (#1783303) + +* Fri Apr 3 2020 Patsy Griffin - 2.28-117 +- Update to Linux 5.6 syscall-names.list. (#1810224) + +* Fri Apr 3 2020 Patsy Griffin - 2.28-116 +- CVE-2020-1751: Fix an array overflow in backtrace on PowerPC. (#1813399) + +* Fri Apr 3 2020 Patsy Griffin - 2.28-115 +- CVE:2020-1752: Fix a use after free in glob when expanding ~user. (#1813398) + +* Fri Apr 3 2020 Patsy Griffin - 2.28-114 +- CVE-2020-10029: Prevent stack corruption from crafted input in cosl, sinl, + sincosl, and tanl function. (#1811796) + +* Thu Apr 2 2020 Carlos O'Donell - 2.28-113 +- Improve elf/ and nptl/ testsuites (#1810223) + +* Thu Apr 2 2020 Carlos O'Donell - 2.28-112 +- Fix resource leak in getaddrinfo (#1810146) + +* Thu Apr 2 2020 Carlos O'Donell - 2.28-111 +- Protect locale archive against corruption (#1784525) + +* Thu Apr 2 2020 Carlos O'Donell - 2.28-110 +- Properly handle signed vs. unsigned values in mallopt (#1784520) + +* Thu Apr 2 2020 Carlos O'Donell - 2.28-109 +- Update and harmonize locale names with CLDR (#1757354) + +* Thu Apr 2 2020 Carlos O'Donell - 2.28-108 +- Fix filter and auxiliary filter implementation (#1812756) + +* Thu Apr 2 2020 Carlos O'Donell - 2.28-107 +- Handle .dynstr located in separate segment (#1774114) + +* Fri Mar 27 2020 Patsy Griffin - 2.28-106 +- Disable vtable validation for pre-2.1 interposed handles (#1775819) + +* Fri Mar 27 2020 Patsy Griffin - 2.28-105 +- Define __CORRECT_ISO_CPP_STRING_H_PROTO for Clang. (#1784519) + +* Wed Mar 25 2020 DJ Delorie - 2.28-104 +- Math library optimizations for IBM Z (#1780204) + +* Wed Mar 25 2020 DJ Delorie - 2.28-103 +- Filter "ignore" autofs mount entries in getmntent (#1743445) + +* Wed Mar 25 2020 DJ Delorie - 2.28-102 +- Fix /etc/resolv.conf reloading defects (#1810142) + +* Thu Jan 16 2020 Florian Weimer - 2.28-101 +- ld.so: Reset GL (dl_initfirst) pointer on dlopen failure (#1410154) + +* Fri Dec 13 2019 Florian Weimer - 2.28-100 +- Roll back dynamic linker state on dlopen failure (#1410154) + +* Wed Nov 27 2019 Florian Weimer - 2.28-99 +- s390x: Fix z15 strstr for patterns crossing pages (#1777241) + +* Wed Nov 27 2019 Florian Weimer - 2.28-98 +- Rebuild with new rpm (#1654901) + +* Fri Nov 22 2019 Florian Weimer - 2.28-97 +- Avoid invalid __has_include in (#1775294) + +* Fri Nov 22 2019 Florian Weimer - 2.28-96 +- x86-64: Ignore LD_PREFER_MAP_32BIT_EXEC in SUID binaries (#1774021) + +* Thu Nov 14 2019 DJ Delorie - 2.28-95 +- Fix alignment of TLS variables for tls variant TLS_TCB_AT_TP (#1764214) + +* Thu Nov 14 2019 DJ Delorie - 2.28-94 +- Refuse to dlopen PIE objects (#1764223) + +* Thu Nov 14 2019 Carlos O'Donell - 2.28-93 +- Fix C.UTF-8 locale source ellipsis expressions (#1361965) + +* Thu Nov 14 2019 Carlos O'Donell - 2.28-92 +- Fix hangs during malloc tracing (#1764235) + +* Thu Nov 14 2019 Carlos O'Donell - 2.28-91 +- Support moving versioned symbols between sonames (#1764231) + +* Wed Nov 13 2019 Florian Weimer - 2.28-90 +- Avoid creating stale utmp entries for repeated pututxline (#1749439) + +* Wed Nov 6 2019 Florian Weimer - 2.28-89 +- Backport more precise tokenizer for installed headers test (#1769304) + +* Wed Nov 6 2019 Florian Weimer - 2.28-88 +- math: Enable some math builtins for clang in LLVM Toolset (#1764242) + +* Wed Nov 6 2019 Florian Weimer - 2.28-87 +- Support Fortran vectorized math functions with GCC Toolset 9 (#1764238) + +* Wed Nov 6 2019 Florian Weimer - 2.28-86 +- aarch64: Support STO_AARCH64_VARIANT_PCS, DT_AARCH64_VARIANT_PCS (#1726638) + +* Mon Nov 4 2019 DJ Delorie - 2.28-85 +- Add more test-in-container support (#1747502) + +* Fri Nov 1 2019 DJ Delorie - 2.28-84 +- Fix calling getpwent after endpwent (#1747502) + +* Fri Nov 1 2019 DJ Delorie - 2.28-83 +- nptl: Avoid fork handler lock for async-signal-safe fork (#1746928) + +* Thu Oct 31 2019 DJ Delorie - 2.28-82 +- Call _dl_open_check after relocation (#1682954) + +* Thu Oct 31 2019 Arjun Shankar - 2.28-81 +- Add malloc fastbin tunable (#1764218) + +* Thu Oct 31 2019 Arjun Shankar - 2.28-80 +- Fix race condition in tst-clone3 and add a new ldconfig test, + tst-ldconfig-bad-aux-cache (#1764226) + +* Thu Oct 31 2019 Arjun Shankar - 2.28-79 +- Remove unwanted whitespace from size lines and account for top chunk in + malloc_info output (#1735747) + +* Wed Oct 30 2019 Arjun Shankar - 2.28-78 +- Enhance malloc tcache (#1746933) + +* Tue Oct 29 2019 Patsy Griffin - 2.28-77 +- Don't define initgroups in nsswitch.conf (#1747505) + +* Mon Oct 28 2019 Patsy Griffin - 2.28-76 +- libio: Remove codecvt vtable. (#1764241) + +* Mon Oct 28 2019 Patsy Griffin - 2.28-75 +- Implement --preload option for the dynamic linker.(#1747453) + +* Mon Oct 28 2019 Patsy Griffin - 2.28-74 +- Make nsswitch.conf more distribution friendly. + Improve nscd.conf comments. (#1747505) + +* Fri Oct 25 2019 Patsy Griffin - 2.28-73 +- Update system call names list to Linux 5.3 (#1764234) + +* Mon Jul 22 2019 Carlos O'Donell - 2.28-72 +- Skip wide buffer handling for legacy stdio handles (#1722215) + +* Mon Jul 22 2019 Carlos O'Donell - 2.28-71 +- Remove copy_file_range emulation (#1724975) + +* Mon Jul 22 2019 Carlos O'Donell - 2.28-70 +- Avoid nscd assertion failure during persistent db check (#1727152) + +* Mon Jul 22 2019 Carlos O'Donell - 2.28-69 +- Fix invalid free under valgrind with libdl (#1717438) + +* Thu Jul 18 2019 Carlos O'Donell - 2.28-68 +- Account for size of locale-archive in rpm package (#1725131) + +* Thu Jul 18 2019 Carlos O'Donell - 2.28-67 +- Reject IP addresses with trailing characters in getaddrinfo (#1727241) + +* Fri Jun 14 2019 Florian Weimer - 2.28-66 +- Avoid header conflict between and (#1699194) + +* Wed Jun 12 2019 Florian Weimer - 2.28-65 +- glibc-all-langpacks: Do not delete locale archive during update (#1717347) +- Do not mark /usr/lib/locale/locale-archive as a configuration file + because it is always automatically overwritten by build-locale-archive. + +* Mon Jun 10 2019 DJ Delorie - 2.28-64 +- Avoid ABI exposure of the NSS service_user type (#1710894) + +* Thu Jun 6 2019 Patsy Griffin Franklin - 2.28-63 +- Enable full ICMP errors for UDP DNS sockets. (#1670043) + +* Mon Jun 3 2019 Carlos O'Donell - 2.28-62 +- Convert post-install binary to rpm lua scriptlet (#1639346) + +* Mon Jun 3 2019 Florian Weimer - 2.28-61 +- Fix crash during wide stream buffer flush (#1710478) + +* Fri May 31 2019 Carlos O'Donell - 2.28-60 +- Add PF_XDP, AF_XDP and SOL_XDP from Linux 4.18 (#1706777) + +* Wed May 22 2019 DJ Delorie - 2.28-59 +- Add .gdb_index to debug information (#1612448) + +* Wed May 22 2019 DJ Delorie - 2.28-57 +- locale: Add LOCPATH diagnostics to the locale program (#1701605) + +* Fri May 17 2019 Patsy Griffin Franklin - 2.28-56 +- Fix hang in pldd. (#1702539) + +* Mon May 13 2019 Florian Weimer - 2.28-55 +- s390x string function improvements (#1659438) + +* Thu May 2 2019 Patsy Griffin Franklin - 2.28-54 +- Fix test suite failures due to race conditions in posix/tst-spawn + spawned processes. (#1659512) + +* Wed May 1 2019 DJ Delorie - 2.28-53 +- Add missing CFI data to __mpn_* functions on ppc64le (#1658901) + +* Fri Apr 26 2019 Arjun Shankar - 2.28-52 +- intl: Do not return NULL on asprintf failure in gettext (#1663035) + +* Fri Apr 26 2019 Florian Weimer - 2.28-51 +- Increase BIND_NOW coverage (#1639343) + +* Tue Apr 23 2019 Carlos O'Donell - 2.28-50 +- Fix pthread_rwlock_trywrlock and pthread_rwlock_tryrdlock stalls (#1659293) + +* Tue Apr 23 2019 Arjun Shankar - 2.28-49 +- malloc: Improve bad chunk detection (#1651283) + +* Mon Apr 22 2019 Patsy Griffin Franklin - 2.28-48 +- Add compiler barriers around modifications of the robust mutex list + for pthread_mutex_trylock. (#1672773) + +* Tue Apr 16 2019 DJ Delorie - 2.28-47 +- powerpc: Only enable HTM if kernel supports PPC_FEATURE2_HTM_NOSC (#1651742) + +* Fri Apr 12 2019 Florian Weimer - 2.28-46 +- Only build libm with -fno-math-errno (#1664408) + +* Tue Apr 2 2019 Florian Weimer - 2.28-45 +- ja_JP: Add new Japanese Era name (#1577438) + +* Wed Mar 6 2019 Florian Weimer - 2.28-44 +- math: Add XFAILs for some IBM 128-bit long double fma tests (#1623537) + +* Fri Mar 1 2019 Florian Weimer - 2.28-43 +- malloc: realloc ncopies integer overflow (#1662843) + +* Fri Dec 14 2018 Florian Weimer - 2.28-42 +- Fix rdlock stall with PREFER_WRITER_NONRECURSIVE_NP (#1654872) + +* Fri Dec 14 2018 Florian Weimer - 2.28-41 +- malloc: Implement double-free check for the thread cache (#1642094) + +* Thu Dec 13 2018 Florian Weimer - 2.28-40 +- Add upstream test case for CVE-2018-19591 (#1654010) + +* Thu Dec 13 2018 Florian Weimer - 2.28-39 +- Add GCC dependency for new inline string functions on ppc64le (#1652932) + +* Sat Dec 01 2018 Carlos O'Donell - 2.28-38 +- Add requires on explicit glibc version for glibc-nss-devel (#1649890) + +* Fri Nov 30 2018 Carlos O'Donell - 2.28-37 +- Fix data race in dynamic loader when using LD_AUDIT (#1635779) + +* Wed Nov 28 2018 Florian Weimer - 2.28-36 +- CVE-2018-19591: File descriptor leak in if_nametoindex (#1654010) + +* Mon Nov 26 2018 Florian Weimer - 2.28-35 +- Do not use parallel make for building locales (#1652229) + +* Tue Nov 20 2018 Florian Weimer - 2.28-34 +- support: Print timestamps in timeout handler (#1651274) + +* Tue Nov 20 2018 Florian Weimer - 2.28-33 +- Increase test timeout for libio/tst-readline (#1638520) + +* Tue Nov 20 2018 Florian Weimer - 2.28-32 +- Fix tzfile low-memory assertion failure (#1650571) + +* Tue Nov 20 2018 Florian Weimer - 2.28-31 +- Add newlines in __libc_fatal calls (#1650566) + +* Tue Nov 20 2018 Florian Weimer - 2.28-30 +- nscd: Fix use-after-free in addgetnetgrentX (#1650563) + +* Tue Nov 20 2018 Florian Weimer - 2.28-29 +- Update syscall names to Linux 4.19 (#1650560) + +* Tue Nov 13 2018 Florian Weimer - 2.28-28 +- kl_GL: Fix spelling of Sunday, should be "sapaat" (#1645597) + +* Tue Nov 13 2018 Florian Weimer - 2.28-27 +- Fix x86 CPU flags analysis for string function selection (#1641982) + +* Fri Nov 9 2018 Florian Weimer - 2.28-26 +- Reduce RAM requirements for stdlib/test-bz22786 (#1638523) + +* Fri Nov 9 2018 Florian Weimer - 2.28-25 +- x86: Improve enablement for 32-bit code using CET (#1645601) + +* Fri Nov 9 2018 Florian Weimer - 2.28-24 +- Fix crash in getaddrinfo_a when thread creation fails (#1646379) + +* Fri Nov 9 2018 Florian Weimer - 2.28-23 +- Fix race in pthread_mutex_lock related to PTHREAD_MUTEX_ELISION_NP (#1645604) + +* Fri Nov 9 2018 Florian Weimer - 2.28-22 +- Fix misreported errno on preadv2/pwritev2 (#1645596) + +* Fri Nov 9 2018 Florian Weimer - 2.28-21 +- Fix posix/tst-spawn4-compat test case (#1645593) + +* Fri Nov 9 2018 Florian Weimer - 2.28-20 +- Disable CET for binaries created by older link editors (#1614979) + +* Fri Nov 2 2018 Mike FABIAN - 2.28-19 +- Include Esperanto (eo) in glibc-all-langpacks (#1644303) + +* Thu Sep 27 2018 Florian Weimer - 2.28-18 +- stdlib/tst-setcontext9 test suite failure on ppc64le (#1623536) + +* Wed Sep 26 2018 Florian Weimer - 2.28-17 +- Add missing ENDBR32 in start.S (#1631730) + +* Wed Sep 26 2018 Florian Weimer - 2.28-16 +- Fix bug in generic strstr with large needles (#1631722) + +* Wed Sep 26 2018 Florian Weimer - 2.28-15 +- stdlib/tst-setcontext9 test suite failure (#1623536) + +* Wed Sep 26 2018 Florian Weimer - 2.28-14 +- gethostid: Missing NULL check for gethostbyname_r (#1631293) + +* Wed Sep 5 2018 Carlos O'Donell - 2.28-13 +- Provide compatibility support for linking against libpthread_nonshared.a + (#1614439) + +* Wed Sep 5 2018 Florian Weimer - 2.28-12 +- Add python3-devel build dependency (#1625592) + +* Wed Aug 29 2018 Florian Weimer - 2.28-11 +- Drop glibc-ldflags.patch and valgrind bug workaround (#1623456) + +* Wed Aug 29 2018 Florian Weimer - 2.28-10 +- regex: Fix memory overread when pattern contains NUL byte (#1622678) + +* Wed Aug 29 2018 Florian Weimer - 2.28-9 +- nptl: Fix waiters-after-spinning case in pthread_cond_broadcast (#1622675) + +* Tue Aug 14 2018 Florian Weimer - 2.28-8 +- nss_files aliases database file stream leak (#1615790) + +* Tue Aug 14 2018 Florian Weimer - 2.28-7 +- Fix static analysis warning in nscd user name allocation (#1615784) + +* Tue Aug 14 2018 Florian Weimer - 2.28-6 +- error, error_at_line: Add missing va_end calls (#1615781) + +* Mon Aug 13 2018 Carlos O'Donell - 2.28-5 +- Remove abort() warning in manual (#1577365) + +* Fri Aug 10 2018 Florian Weimer - 2.28-4 +- Fix regression in readdir64@GLIBC_2.1 compat symbol (#1614253) + +* Thu Aug 2 2018 Florian Weimer - 2.28-3 +- Log /proc/sysinfo if available (on s390x) + +* Thu Aug 2 2018 Florian Weimer - 2.28-2 +- Honor %%{valgrind_arches} + +* Wed Aug 01 2018 Florian Weimer - 2.27.9000-43 +- Update to glibc 2.28 release tarball: +- Translation updates +- x86/CET: Fix property note parser (swbz#23467) +- x86: Add tst-get-cpu-features-static to $(tests) (swbz#23458) + +* Mon Jul 30 2018 Florian Weimer - 2.27.9000-42 +- Auto-sync with upstream branch master, + commit af86087f02a5522d8801a11d8381e04f95e33162: +- x86/CET: Don't parse beyond the note end +- Fix Linux fcntl OFD locks tests on unsupported kernels +- x86: Populate COMMON_CPUID_INDEX_80000001 for Intel CPUs (swbz#23459) +- x86: Correct index_cpu_LZCNT (swbz#23456) +- Fix string/tst-xbzero-opt if build with gcc head + +* Thu Jul 26 2018 Florian Weimer - 2.27.9000-41 +- Build with --enable-cet on x86_64, i686 +- Auto-sync with upstream branch master, + commit cfba5dbb10cc3abde632b46c60c10b2843917035: +- Keep expected behaviour for [a-z] and [A-z] (#1607286) +- Additional ucontext tests +- Intel CET enhancements +- ISO C11 threads support +- Fix out-of-bounds access in IBM-1390 converter (swbz#23448) +- New locale Yakut (Sakha) for Russia (sah_RU) (swbz#22241) +- os_RU: Add alternative month names (swbz#23140) +- powerpc64: Always restore TOC on longjmp (swbz#21895) +- dsb_DE locale: Fix syntax error and add tests (swbz#23208) +- Improve performance of the generic strstr implementation +- regcomp: Fix off-by-one bug in build_equiv_class (swbz#23396) +- Fix out of bounds access in findidxwc (swbz#23442) + +* Fri Jul 13 2018 Carlos O'Donell - 2.27.9000-40 +- Fix file list for glibc RPM packaging (#1601011). + +* Wed Jul 11 2018 Florian Weimer - 2.27.9000-39 +- Add POWER9 multilib (downstream only) + +* Wed Jul 11 2018 Florian Weimer - 2.27.9000-38 +- Auto-sync with upstream branch master, + commit 93304f5f7a32f73b551266c5a181db51d97a71e4: +- Install header +- Put the correct Unicode version number 11.0.0 into the generated files + +* Wed Jul 11 2018 Florian Weimer - 2.27.9000-37 +- Work around valgrind issue on i686 (#1600034) + +* Tue Jul 10 2018 Florian Weimer - 2.27.9000-36 +- Auto-sync with upstream branch master, + commit fd70af45528d59a00eb3190ef6706cb299488fcd: +- Add the statx function +- regexec: Fix off-by-one bug in weight comparison (#1582229) +- nss_files: Fix re-reading of long lines (swbz#18991) +- aarch64: add HWCAP_ATOMICS to HWCAP_IMPORTANT +- aarch64: Remove HWCAP_CPUID from HWCAP_IMPORTANT +- conform/conformtest.pl: Escape literal braces in regular expressions +- x86: Use AVX_Fast_Unaligned_Load from Zen onwards. + +* Fri Jul 6 2018 Florian Weimer - 2.27.9000-35 +- Remove ppc64 multilibs + +* Fri Jul 06 2018 Florian Weimer - 2.27.9000-34 +- Auto-sync with upstream branch master, + commit 3a885c1f51b18852869a91cf59a1b39da1595c7a. + +* Thu Jul 5 2018 Florian Weimer - 2.27.9000-33 +- Enable build flags inheritance for nonshared flags + +* Wed Jul 4 2018 Florian Weimer - 2.27.9000-32 +- Add annobin annotations to assembler code (#1548438) + +* Wed Jul 4 2018 Florian Weimer - 2.27.9000-31 +- Enable -D_FORTIFY_SOURCE=2 for nonshared code + +* Mon Jul 02 2018 Florian Weimer - 2.27.9000-30 +- Auto-sync with upstream branch master, + commit b7b88cea4151d85eafd7ababc2e4b7ae1daeedf5: +- New locale: dsb_DE (Lower Sorbian) + +* Fri Jun 29 2018 Florian Weimer - 2.27.9000-29 +- Drop glibc-deprecate_libcrypt.patch. Variant applied upstream. (#1566464) +- Drop glibc-linux-timespec-header-compat.patch. Upstreamed. +- Auto-sync with upstream branch master, + commit e69d994a63afc2d367f286a2a7df28cbf710f0fe. + +* Thu Jun 28 2018 Florian Weimer - 2.27.9000-28 +- Drop glibc-rh1315108.patch. extend_alloca was removed upstream. (#1315108) +- Auto-sync with upstream branch master, + commit c49e18222e4c40f21586dabced8a49732d946917. + +* Thu Jun 21 2018 Florian Weimer - 2.27.9000-27 +- Compatibility fix for and + +* Thu Jun 21 2018 Florian Weimer - 2.27.9000-26 +- Auto-sync with upstream branch master, + commit f496b28e61d0342f579bf794c71b80e9c7d0b1b5. + +* Mon Jun 18 2018 Florian Weimer - 2.27.9000-25 +- Auto-sync with upstream branch master, + commit f2857da7cdb65bfad75ee30981f5b2fde5bbb1dc. + +* Mon Jun 18 2018 Florian Weimer - 2.27.9000-24 +- Auto-sync with upstream branch master, + commit 14beef7575099f6373f9a45b4656f1e3675f7372: +- iconv: Make IBM273 equivalent to ISO-8859-1 (#1592270) + +* Mon Jun 18 2018 Florian Weimer - 2.27.9000-23 +- Inherit the -msse2 build flag as well (#1592212) + +* Fri Jun 01 2018 Florian Weimer - 2.27.9000-22 +- Modernise nsswitch.conf defaults (#1581809) +- Adjust build flags inheritence from redhat-rpm-config +- Auto-sync with upstream branch master, + commit 104502102c6fa322515ba0bb3c95c05c3185da7a. + +* Fri May 25 2018 Florian Weimer - 2.27.9000-21 +- Auto-sync with upstream branch master, + commit c1dc1e1b34873db79dfbfa8f2f0a2abbe28c0514. + +* Wed May 23 2018 Florian Weimer - 2.27.9000-20 +- Auto-sync with upstream branch master, + commit 7f9f1ecb710eac4d65bb02785ddf288cac098323: +- CVE-2018-11237: Buffer overflow in __mempcpy_avx512_no_vzeroupper (#1581275) +- Drop glibc-rh1452750-allocate_once.patch, + glibc-rh1452750-libidn2.patch. Applied upstream. + +* Wed May 23 2018 Florian Weimer - 2.27.9000-19 +- Auto-sync with upstream branch master, + commit 8f145c77123a565b816f918969e0e35ee5b89153. + +* Thu May 17 2018 Florian Weimer - 2.27.9000-18 +- Do not run telinit u on upgrades (#1579225) +- Auto-sync with upstream branch master, + commit 632a6cbe44cdd41dba7242887992cdca7b42922a. + +* Fri May 11 2018 Florian Weimer - 2.27.9000-17 +- Avoid exporting some Sun RPC symbols with default versions (#1577210) +- Inherit the -mstackrealign flag if it is set +- Inherit compiler flags in the original order +- Auto-sync with upstream branch master, + commit 89aacb513eb77549a29df2638913a0f8178cf3f5: +- CVE-2018-11236: realpath: Fix path length overflow (#1581270, swbz#22786) + +* Fri May 11 2018 Florian Weimer - 2.27.9000-16 +- Use /usr/bin/python3 for benchmarks scripts (#1577223) + +* Thu Apr 19 2018 Florian Weimer - 2.27.9000-15 +- Auto-sync with upstream branch master, + commit 0085be1415a38b40a5a1a12e49368498f1687380. + +* Mon Apr 09 2018 Florian Weimer - 2.27.9000-14 +- Auto-sync with upstream branch master, + commit 583a27d525ae189bdfaa6784021b92a9a1dae12e. + +* Thu Mar 29 2018 Florian Weimer - 2.27.9000-13 +- Auto-sync with upstream branch master, + commit d39c0a459ef32a41daac4840859bf304d931adab: +- CVE-2017-18269: memory corruption in i386 memmove (#1580934) + +* Mon Mar 19 2018 Florian Weimer - 2.27.9000-12 +- Auto-sync with upstream branch master, + commit fbce6f7260c3847f14dfa38f60c9111978fb33a5. + +* Fri Mar 16 2018 Florian Weimer - 2.27.9000-11 +- Auto-sync with upstream branch master, + commit 700593fdd7aef1e36cfa8bad969faab76a6facda. + +* Wed Mar 14 2018 Florian Weimer - 2.27.9000-10 +- Auto-sync with upstream branch master, + commit 7108f1f944792ac68332967015d5e6418c5ccc88. + +* Mon Mar 12 2018 Florian Weimer - 2.27.9000-9 +- Auto-sync with upstream branch master, + commit da6d4404ecfd7eacba8c096b0761a5758a59da4b. + +* Tue Mar 6 2018 Florian Weimer - 2.27.9000-8 +- Enable annobin annotations (#1548438) + +* Thu Mar 01 2018 Florian Weimer - 2.27.9000-7 +- Auto-sync with upstream branch master, + commit 1a2f44a848663036c8a14671fe0faa3fed0b2a25: +- Remove spurios reference to libpthread_nonshared.a + +* Thu Mar 01 2018 Florian Weimer - 2.27.9000-6 +- Switch back to upstream master branch +- Drop glibc-rh1013801.patch, applied upstream. +- Drop glibc-fedora-nptl-linklibc.patch, no longer needed. +- Auto-sync with upstream branch master, + commit bd60ce86520b781ca24b99b2555e2ad389bbfeaa. + +* Wed Feb 28 2018 Florian Weimer - 2.27-5 +- Inherit as many flags as possible from redhat-rpm-config (#1550914) + +* Mon Feb 19 2018 Richard W.M. Jones - 2.27-4 +- riscv64: Add symlink from /usr/lib64/lp64d -> /usr/lib64 for ABI compat. +- riscv64: Disable valgrind smoke test on this architecture. + +* Wed Feb 14 2018 Florian Weimer - 2.27-3 +- Spec file cleanups: + - Remove %%defattr(-,root,root) + - Use shell to run ldconfig %%transfiletrigger + - Move %%transfiletrigger* to the glibc-common subpackage + - Trim changelog + - Include ChangeLog.old in the source RPM + +* Wed Feb 7 2018 Florian Weimer - 2.27-2.1 +- Linux: use reserved name __key in pkey_get (#1542643) +- Auto-sync with upstream branch release/2.27/master, + commit 56170e064e2b21ce204f0817733e92f1730541ea. + +* Wed Feb 07 2018 Fedora Release Engineering +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Mon Feb 05 2018 Carlos O'Donell - 2.27-1 +- Update to released glibc 2.27. +- Auto-sync with upstream branch master, + commit 23158b08a0908f381459f273a984c6fd328363cb. + +* Tue Jan 30 2018 Richard W.M. Jones - 2.26.9000-52 +- Disable -fstack-clash-protection on riscv64: + not supported even by GCC 7.3.1 on this architecture. + +* Mon Jan 29 2018 Florian Weimer - 2.26.9000-51 +- Explicitly run ldconfig in the buildroot +- Do not run ldconfig from scriptlets +- Put triggers into the glibc-common package, do not pass arguments to ldconfig + +* Mon Jan 29 2018 Florian Weimer - 2.26.9000-50 +- Auto-sync with upstream branch master, + commit cdd14619a713ab41e26ba700add4880604324dbb: +- libnsl: Turn remaining symbols into compat symbols (swbz#22701) +- be_BY, be_BY@latin, lt_LT, el_CY, el_GR, ru_RU, ru_UA, uk_UA: + Add alternative month names (swbz#10871) +- x86: Revert Intel CET changes to __jmp_buf_tag (swbz#22743) +- aarch64: Revert the change of the __reserved member of mcontext_t + +* Mon Jan 29 2018 Igor Gnatenko - 2.26.9000-49 +- Add file triggers to do ldconfig calls automatically + +* Mon Jan 22 2018 Florian Weimer - 2.26.9000-48 +- Auto-sync with upstream branch master, + commit 21c0696cdef617517de6e25711958c40455c554f: +- locale: Implement alternative month names (swbz#10871) +- locale: Change month names for pl_PL (swbz#10871) + +* Mon Jan 22 2018 Florian Weimer - 2.26.9000-47 +- Unconditionally build without libcrypt + +* Fri Jan 19 2018 Björn Esser - 2.26.9000-46 +- Remove deprecated libcrypt, gets replaced by libxcrypt +- Add applicable Requires on libxcrypt + +* Fri Jan 19 2018 Florian Weimer - 2.26.9000-45 +- Drop static PIE support on aarch64. It leads to crashes at run time. +- Remove glibc-rpcgen subpackage. See rpcsvc-proto. (#1531540) + +* Fri Jan 19 2018 Florian Weimer - 2.26.9000-44 +- Correct the list of static PIE architectures (#1247050) +- glibc_post_upgrade: Remove process restart logic +- glibc_post_upgrade: Integrate into the build process +- glibc_post_upgrade: Do not clean up tls subdirectories +- glibc_post_upgrade: Drop ia64 support +- Remove architecture-specific symbolic link for iconvconfig +- Auto-sync with upstream branch master, + commit 4612268a0ad8e3409d8ce2314dd2dd8ee0af5269: +- powerpc: Fix syscalls during early process initialization (swbz#22685) + +* Fri Jan 19 2018 Florian Weimer - 2.26.9000-43 +- Enable static PIE support on i386, x86_64 (#1247050) +- Remove add-on support (already gone upstream) +- Rework test suite status reporting +- Auto-sync with upstream branch master, + commit 64f63cb4583ecc1ba16c7253aacc192b6d088511: +- malloc: Fix integer overflows in memalign and malloc functions (swbz#22343) +- x86-64: Properly align La_x86_64_retval to VEC_SIZE (swbz#22715) +- aarch64: Update bits/hwcap.h for Linux 4.15 +- Add NT_ARM_SVE to elf.h + +* Wed Jan 17 2018 Florian Weimer - 2.26.9000-42 +- CVE-2017-14062, CVE-2016-6261, CVE-2016-6263: + Use libidn2 for IDNA support (#1452750) + +* Mon Jan 15 2018 Florian Weimer - 2.26.9000-41 +- CVE-2018-1000001: Make getcwd fail if it cannot obtain an absolute path + (#1533837) +- elf: Synchronize DF_1_* flags with binutils (#1439328) +- Auto-sync with upstream branch master, + commit 860b0240a5645edd6490161de3f8d1d1f2786025: +- aarch64: fix static pie enabled libc when main is in a shared library +- malloc: Ensure that the consolidated fast chunk has a sane size + +* Fri Jan 12 2018 Florian Weimer - 2.26.9000-40 +- libnsl: Do not install libnsl.so, libnsl.a (#1531540) +- Use unversioned Supplements: for langpacks (#1490725) +- Auto-sync with upstream branch master, + commit 9a08a366a7e7ddffe62113a9ffe5e50605ea0924: +- hu_HU locale: Avoid double space (swbz#22657) +- math: Make default libc_feholdsetround_noex_ctx use __feholdexcept + (swbz#22702) + +* Thu Jan 11 2018 Florian Weimer - 2.26.9000-39 +- nptl: Open libgcc.so with RTLD_NOW during pthread_cancel (#1527887) +- Introduce libnsl subpackage and remove NIS headers (#1531540) +- Use versioned Obsoletes: for libcrypt-nss. +- Auto-sync with upstream branch master, + commit 08c6e95234c60a5c2f37532d1111acf084f39345: +- nptl: Add tst-minstack-cancel, tst-minstack-exit (swbz#22636) +- math: ldbl-128ibm log1pl (-qNaN) spurious "invalid" exception (swbz#22693) + +* Wed Jan 10 2018 Florian Weimer - 2.26.9000-38 +- nptl: Fix stack guard size accounting (#1527887) +- Remove invalid Obsoletes: on glibc-header provides +- Require python3 instead of python during builds +- Auto-sync with upstream branch master, + commit 09085ede12fb9650f286bdcd805609ae69f80618: +- math: ldbl-128ibm lrintl/lroundl missing "invalid" exceptions (swbz#22690) +- x86-64: Add sincosf with vector FMA + +* Mon Jan 8 2018 Florian Weimer - 2.26.9000-37 +- Add glibc-rpcgen subpackage, until the replacement is packaged (#1531540) + +* Mon Jan 08 2018 Florian Weimer - 2.26.9000-36 +- Auto-sync with upstream branch master, + commit 579396ee082565ab5f42ff166a264891223b7b82: +- nptl: Add test for callee-saved register restore in pthread_exit +- getrlimit64: fix for 32-bit configurations with default version >= 2.2 +- elf: Add linux-4.15 VDSO hash for RISC-V +- elf: Add RISC-V dynamic relocations to elf.h +- powerpc: Fix error message during relocation overflow +- prlimit: Replace old_rlimit RLIM64_INFINITY with RLIM_INFINITY (swbz#22678) + +* Fri Jan 05 2018 Florian Weimer - 2.26.9000-35 +- Remove sln (#1531546) +- Remove Sun RPC interfaces (#1531540) +- Rebuild with newer GCC to fix pthread_exit stack unwinding issue (#1529549) +- Auto-sync with upstream branch master, + commit f1a844ac6389ea4e111afc019323ca982b5b027d: +- CVE-2017-16997: elf: Check for empty tokens before DST expansion (#1526866) +- i386: In makecontext, align the stack before calling exit (swbz#22667) +- x86, armhfp: sync sys/ptrace.h with Linux 4.15 (swbz#22433) +- elf: check for rpath emptiness before making a copy of it +- elf: remove redundant is_path argument +- elf: remove redundant code from is_dst +- elf: remove redundant code from _dl_dst_substitute +- scandir: fix wrong assumption about errno (swbz#17804) +- Deprecate external use of libio.h and _G_config.h + +* Fri Dec 22 2017 Florian Weimer - 2.26.9000-34 +- Auto-sync with upstream branch master, + commit bad7a0c81f501fbbcc79af9eaa4b8254441c4a1f: +- copy_file_range: New function to copy file data +- nptl: Consolidate pthread_{timed,try}join{_np} +- nptl: Implement pthread_self in libc.so (swbz#22635) +- math: Provide a C++ version of iseqsig (swbz#22377) +- elf: remove redundant __libc_enable_secure check from fillin_rpath +- math: Avoid signed shift overflow in pow (swbz#21309) +- x86: Add feature_1 to tcbhead_t (swbz#22563) +- x86: Update cancel_jmp_buf to match __jmp_buf_tag (swbz#22563) +- ld.so: Examine GLRO to detect inactive loader (swbz#20204) +- nscd: Fix nscd readlink argument aliasing (swbz#22446) +- elf: do not substitute dst in $LD_LIBRARY_PATH twice (swbz#22627) +- ldconfig: set LC_COLLATE to C (swbz#22505) +- math: New generic sincosf +- powerpc: st{r,p}cpy optimization for aligned strings +- CVE-2017-1000409: Count in expanded path in _dl_init_path (#1524867) +- CVE-2017-1000408: Compute correct array size in _dl_init_paths (#1524867) +- x86-64: Remove sysdeps/x86_64/fpu/s_cosf.S +- aarch64: Improve strcmp unaligned performance + +* Wed Dec 13 2017 Florian Weimer - 2.26.9000-33 +- Remove power6 platform directory (#1522675) + +* Wed Dec 13 2017 Florian Weimer - 2.26.9000-32 +- Obsolete the libcrypt-nss subpackage (#1525396) +- armhfp: Disable -fstack-clash-protection due to GCC bug (#1522678) +- ppc64: Disable power6 multilib due to GCC bug (#1522675) +- Auto-sync with upstream branch master, + commit 243b63337c2c02f30ec3a988ecc44bc0f6ffa0ad: +- libio: Free backup area when it not required (swbz#22415) +- math: Fix nextafter and nexttoward declaration (swbz#22593) +- math: New generic cosf +- powerpc: POWER8 memcpy optimization for cached memory +- x86-64: Add sinf with FMA +- x86-64: Remove sysdeps/x86_64/fpu/s_sinf.S +- math: Fix ctanh (0 + i NaN), ctanh (0 + i Inf) (swbz#22568) +- lt_LT locale: Base collation on copy "iso14651_t1" (swbz#22524) +- math: Add _Float32 function aliases +- math: Make cacosh (0 + iNaN) return NaN + i pi/2 (swbz#22561) +- hsb_DE locale: Base collation on copy "iso14651_t1" (swbz#22515) + +* Wed Dec 06 2017 Florian Weimer - 2.26.9000-31 +- Add elision tunables. Drop related configure flag. (#1383986) +- Auto-sync with upstream branch master, + commit 37ac8e635a29810318f6d79902102e2e96b2b5bf: +- Linux: Implement interfaces for memory protection keys +- math: Add _Float64, _Float32x function aliases +- math: Use sign as double for reduced case in sinf +- math: fix sinf(NAN) +- math: s_sinf.c: Replace floor with simple casts +- et_EE locale: Base collation on iso14651_t1 (swbz#22517) +- tr_TR locale: Base collation on iso14651_t1 (swbz#22527) +- hr_HR locale: Avoid single code points for digraphs in LC_TIME (swbz#10580) +- S390: Fix backtrace in vdso functions + +* Mon Dec 04 2017 Florian Weimer - 2.26.9000-30 +- Add build dependency on bison +- Auto-sync with upstream branch master, + commit 7863a7118112fe502e8020a0db0fa74fef281f29: +- math: New generic sinf (swbz#5997) +- is_IS locale: Base collation on iso14651_t1 (swbz#22519) +- intl: Improve reproducibility by using bison (swbz#22432) +- sr_RS, bs_BA locales: make collation rules the same as for hr_HR (wbz#22534) +- hr_HR locale: various updates (swbz#10580) +- x86: Make a space in jmpbuf for shadow stack pointer +- CVE-2017-17426: malloc: Fix integer overflow in tcache (swbz#22375) +- locale: make forward accent sorting the default in collating (swbz#17750) + +* Wed Nov 29 2017 Florian Weimer - 2.26.9000-29 +- Enable -fstack-clash-protection (#1512531) +- Auto-sync with upstream branch master, + commit a55430cb0e261834ce7a4e118dd9e0f2b7fb14bc: +- elf: Properly compute offsets of note descriptor and next note (swbz#22370) +- cs_CZ locale: Base collation on iso14651_t1 (swbz#22336) +- Implement the mlock2 function +- Add _Float64x function aliases +- elf: Consolidate link map sorting +- pl_PL locale: Base collation on iso14651_t1 (swbz#22469) +- nss: Export nscd hash function as __nss_hash (swbz#22459) + +* Thu Nov 23 2017 Florian Weimer - 2.26.9000-28 +- Auto-sync with upstream branch master, + commit cccb6d4e87053ed63c74aee063fa84eb63ebf7b8: +- sigwait can fail with EINTR (#1516394) +- Add memfd_create function +- resolv: Fix p_secstodate overflow handling (swbz#22463) +- resolv: Obsolete p_secstodate +- Avoid use of strlen in getlogin_r (swbz#22447) +- lv_LV locale: fix collation (swbz#15537) +- S390: Add cfi information for start routines in order to stop unwinding +- aarch64: Optimized memset for falkor + +* Sun Nov 19 2017 Florian Weimer - 2.26.9000-27 +- Auto-sync with upstream branch master, + commit f6e965ee94b37289f64ecd3253021541f7c214c3: +- powerpc: AT_HWCAP2 bit PPC_FEATURE2_HTM_NO_SUSPEND +- aarch64: Add HWCAP_DCPOP bit +- ttyname, ttyname_r: Don't bail prematurely (swbz#22145) +- signal: Optimize sigrelse implementation +- inet: Check length of ifname in if_nametoindex (swbz#22442) +- malloc: Account for all heaps in an arena in malloc_info (swbz#22439) +- malloc: Add missing arena lock in malloc_info (swbz#22408) +- malloc: Use __builtin_tgmath in tgmath.h with GCC 8 (swbz#21660) +- locale: Replaced unicode sequences in the ASCII printable range +- resolv: More precise checks in res_hnok, res_dnok (swbz#22409, swbz#22412) +- resolv: ns_name_pton should report trailing \ as error (swbz#22413) +- locale: mfe_MU, miq_NI, an_ES, kab_DZ, om_ET: Escape / in d_fmt (swbz#22403) + +* Tue Nov 07 2017 Florian Weimer - 2.26.9000-26 +- Auto-sync with upstream branch master, + commit 6b86036452b9ac47b4ee7789a50f2f37df7ecc4f: +- CVE-2017-15804: glob: Fix buffer overflow during GLOB_TILDE unescaping +- powerpc: Use latest string function optimization for internal function calls +- math: No _Float128 support for ppc64le -mlong-double-64 (swbz#22402) +- tpi_PG locale: Fix wrong d_fmt +- aarch64: Disable lazy symbol binding of TLSDESC +- tpi_PG locale: fix syntax error (swbz#22382) +- i586: Use conditional branches in strcpy.S (swbz#22353) +- ffsl, ffsll: Declare under __USE_MISC, not just __USE_GNU +- csb_PL locale: Fix abmon/mon for March (swbz#19485) +- locale: Various yesstr/nostr/yesexpr/noexpr fixes (swbz#15260, swbz#15261) +- localedef: Add --no-warnings/--warnings option +- powerpc: Replace lxvd2x/stxvd2x with lvx/stvx in P7's memcpy/memmove +- locale: Use ASCII as much as possible in LC_MESSAGES +- Add new locale yuw_PG (swbz#20952) +- malloc: Add single-threaded path to malloc/realloc/calloc/memalloc +- i386: Replace assembly versions of e_powf with generic e_powf.c +- i386: Replace assembly versions of e_log2f with generic e_log2f.c +- x86-64: Add powf with FMA +- x86-64: Add logf with FMA +- i386: Replace assembly versions of e_logf with generic e_logf.c +- i386: Replace assembly versions of e_exp2f with generic e_exp2f.c +- x86-64: Add exp2f with FMA +- i386: Replace assembly versions of e_expf with generic e_expf.c + +* Sat Oct 21 2017 Florian Weimer - 2.26.9000-25 +- Auto-sync with upstream branch master, + commit 797ba44ba27521261f94cc521f1c2ca74f650147: +- math: Add bits/floatn.h defines for more _FloatN / _FloatNx types +- posix: Fix improper assert in Linux posix_spawn (swbz#22273) +- x86-64: Use fxsave/xsave/xsavec in _dl_runtime_resolve (swbz#21265) +- CVE-2017-15670: glob: Fix one-byte overflow (#1504807) +- malloc: Add single-threaded path to _int_free +- locale: Add new locale kab_DZ (swbz#18812) +- locale: Add new locale shn_MM (swbz#13605) + +* Fri Oct 20 2017 Florian Weimer - 2.26.9000-24 +- Use make -O to serialize make output +- Auto-sync with upstream branch master, + commit 63b4baa44e8d22501c433c4093aa3310f91b6aa2: +- sysconf: Fix missing definition of UIO_MAXIOV on Linux (#1504165) +- Install correct bits/long-double.h for MIPS64 (swbz#22322) +- malloc: Fix deadlock in _int_free consistency check +- x86-64: Don't set GLRO(dl_platform) to NULL (swbz#22299) +- math: Add _Float128 function aliases +- locale: Add new locale mjw_IN (swbz#13994) +- aarch64: Rewrite elf_machine_load_address using _DYNAMIC symbol +- powerpc: fix check-before-set in SET_RESTORE_ROUND +- locale: Use U+202F as thousands separators in pl_PL locale (swbz#16777) +- math: Use __f128 to define FLT128_* constants in include/float.h for old GCC +- malloc: Improve malloc initialization sequence (swbz#22159) +- malloc: Use relaxed atomics for malloc have_fastchunks +- locale: New locale ca_ES@valencia (swbz#2522) +- math: Let signbit use the builtin in C++ mode with gcc < 6.x (swbz#22296) +- locale: Place monetary symbol in el_GR, el_CY after the amount (swbz#22019) + +* Tue Oct 17 2017 Florian Weimer - 2.26.9000-23 +- Switch to .9000 version numbers during development + +* Tue Oct 17 2017 Florian Weimer - 2.26.90-22 +- Auto-sync with upstream branch master, + commit c38a4bfd596db2be2b9c1f96715bdc833eab760a: +- malloc: Use compat_symbol_reference in libmcheck (swbz#22050) + +* Mon Oct 16 2017 Florian Weimer - 2.26.90-21 +- Auto-sync with upstream branch master, + commit 596f70134a8f11967c65c1d55a94a3a2718c731d: +- Silence -O3 -Wall warning in malloc/hooks.c with GCC 7 (swbz#22052) +- locale: No warning for non-symbolic character (swbz#22295) +- locale: Allow "" int_curr_Symbol (swbz#22294) +- locale: Fix localedef exit code (swbz#22292) +- nptl: Preserve error in setxid thread broadcast in coredumps (swbz#22153) +- powerpc: Avoid putting floating point values in memory (swbz#22189) +- powerpc: Fix the carry bit on mpn_[add|sub]_n on POWER7 (swbz#22142) +- Support profiling PIE (swbz#22284) + +* Wed Oct 11 2017 Florian Weimer - 2.26.90-20 +- Auto-sync with upstream branch master, + commit d8425e116cdd954fea0c04c0f406179b5daebbb3: +- nss_files performance issue in multi mode (swbz#22078) +- Ensure C99 and C11 interfaces are available for C++ (swbz#21326) + +* Mon Oct 09 2017 Florian Weimer - 2.26.90-19 +- Move /var/db/Makefile to nss_db (#1498900) +- Auto-sync with upstream branch master, + commit 645ac9aaf89e3311949828546df6334322f48933: +- openpty: use TIOCGPTPEER to open slave side fd + +* Fri Oct 06 2017 Carlos O'Donell - 2.26.90-18 +- Auto-sync with upstream master, + commit 1e26d35193efbb29239c710a4c46a64708643320. +- malloc: Fix tcache leak after thread destruction (swbz#22111) +- powerpc: Fix IFUNC for memrchr. +- aarch64: Optimized implementation of memmove for Qualcomm Falkor +- Always do locking when iterating over list of streams (swbz#15142) +- abort: Do not flush stdio streams (swbz#15436) + +* Wed Oct 04 2017 Florian Weimer - 2.26.90-17 +- Move nss_compat to the main glibc package (#1400538) +- Auto-sync with upstream master, + commit 11c4f5010c58029e73e656d5df4f8f42c9b8e877: +- crypt: Use NSPR header files in addition to NSS header files (#1489339) +- math: Fix yn(n,0) without SVID wrapper (swbz#22244) +- math: Fix log2(0) and log(10) in downward rounding (swbz#22243) +- math: Add C++ versions of iscanonical for ldbl-96, ldbl-128ibm (swbz#22235) +- powerpc: Optimize memrchr for power8 +- Hide various internal functions (swbz#18822) + +* Sat Sep 30 2017 Florian Weimer - 2.26.90-16 +- Auto-sync with upstream master, + commit 1e2bffd05c36a9be30d7092d6593a9e9aa009ada: +- Add IBM858 charset (#1416405) +- Update kernel version in syscall-names.list to 4.13 +- Add Linux 4.13 constants to bits/fcntl-linux.h +- Add fcntl sealing interfaces from Linux 3.17 to bits/fcntl-linux.h +- math: New generic powf, log2f, logf +- Fix nearbyint arithmetic moved before feholdexcept (swbz#22225) +- Mark __dso_handle as hidden (swbz#18822) +- Skip PT_DYNAMIC segment with p_filesz == 0 (swbz#22101) +- glob now matches dangling symbolic links (swbz#866, swbz#22183) +- nscd: Release read lock after resetting timeout (swbz#22161) +- Avoid __MATH_TG in C++ mode with -Os for fpclassify (swbz#22146) +- Fix dlclose/exit race (swbz#22180) +- x86: Add SSE4.1 trunc, truncf (swbz#20142) +- Fix atexit/exit race (swbz#14333) +- Use execveat syscall in fexecve (swbz#22134) +- Enable unwind info in libc-start.c and backtrace.c +- powerpc: Avoid misaligned stores in memset +- powerpc: build some IFUNC math functions for libc and libm (swbz#21745) +- Removed redundant data (LC_TIME and LC_MESSAGES) for niu_NZ (swbz#22023) +- Fix LC_TELEPHONE for az_AZ (swbz#22112) +- x86: Add MathVec_Prefer_No_AVX512 to cpu-features (swbz#21967) +- x86: Add x86_64 to x86-64 HWCAP (swbz#22093) +- Finish change from “Bengali” to “Bangla” (swbz#14925) +- posix: fix glob bugs with long login names (swbz#1062) +- posix: Fix getpwnam_r usage (swbz#1062) +- posix: accept inode 0 is a valid inode number (swbz#19971) +- Remove redundant LC_TIME data in om_KE (swbz#22100) +- Remove remaining _HAVE_STRING_ARCH_* definitions (swbz#18858) +- resolv: Fix memory leak with OOM during resolv.conf parsing (swbz#22095) +- Add miq_NI locale for Miskito (swbz#20498) +- Fix bits/math-finite.h exp10 condition (swbz#22082) + +* Mon Sep 04 2017 Florian Weimer - 2.26.90-15 +- Auto-sync with upstream master, + commit b38042f51430974642616a60afbbf96fd0b98659: +- Implement tmpfile with O_TMPFILE (swbz#21530) +- Obsolete pow10 functions +- math.h: Warn about an already-defined log macro + +* Fri Sep 01 2017 Florian Weimer - 2.26.90-14 +- Build glibc with -O2 (following the upstream default). +- Auto-sync with upstream master, + commit f4a6be2582b8dfe8adfa68da3dd8decf566b3983: +- malloc: Abort on heap corruption, without a backtrace (swbz#21754) +- getaddrinfo: Return EAI_NODATA for gethostbyname2_r with NO_DATA (swbz#21922) +- getaddrinfo: Fix error handling in gethosts (swbz#21915) (swbz#21922) +- Place $(elf-objpfx)sofini.os last (swbz#22051) +- Various locale fixes (swbz#15332, swbz#22044) + +* Wed Aug 30 2017 Florian Weimer - 2.26.90-13 +- Drop glibc-rh952799.patch, applied upstream (#952799, swbz#22025) +- Auto-sync with upstream master, + commit 5f9409b787c5758fc277f8d1baf7478b752b775d: +- Various locale fixes (swbz#22022, swbz#22038, swbz#21951, swbz#13805, + swbz#21971, swbz#21959) +- MIPS/o32: Fix internal_syscall5/6/7 (swbz#21956) +- AArch64: Fix procfs.h not to expose stdint.h types +- iconv_open: Fix heap corruption on gconv_init failure (swbz#22026) +- iconv: Mangle __btowc_fct even without __init_fct (swbz#22025) +- Fix bits/math-finite.h _MSUF_ expansion namespace (swbz#22028) +- Provide a C++ version of iszero that does not use __MATH_TG (swbz#21930) + +* Mon Aug 28 2017 Florian Weimer - 2.26.90-12 +- Auto-sync with upstream master, + commit 2dba5ce7b8115d6a2789bf279892263621088e74. + +* Fri Aug 25 2017 Florian Weimer - 2.26.90-11 +- Auto-sync with upstream master, + commit 3d7b66f66cb223e899a7ebc0f4c20f13e711c9e0: +- string/stratcliff.c: Replace int with size_t (swbz#21982) +- Fix tgmath.h handling of complex integers (swbz#21684) + +* Thu Aug 24 2017 Florian Weimer - 2.26.90-10 +- Use an architecture-independent system call list (#1484729) +- Drop glibc-fedora-include-bits-ldbl.patch (#1482105) + +* Tue Aug 22 2017 Florian Weimer - 2.26.90-9 +- Auto-sync with upstream master, + commit 80f91666fed71fa3dd5eb5618739147cc731bc89. + +* Mon Aug 21 2017 Florian Weimer - 2.26.90-8 +- Auto-sync with upstream master, + commit a8410a5fc9305c316633a5a3033f3927b759be35: +- Obsolete matherr, _LIB_VERSION, libieee.a. + +* Mon Aug 21 2017 Florian Weimer - 2.26.90-7 +- Auto-sync with upstream master, + commit 4504783c0f65b7074204c6126c6255ed89d6594e. + +* Mon Aug 21 2017 Florian Weimer - 2.26.90-6 +- Auto-sync with upstream master, + commit b5889d25e9bf944a89fdd7bcabf3b6c6f6bb6f7c: +- assert: Support types without operator== (int) (#1483005) + +* Mon Aug 21 2017 Florian Weimer - 2.26.90-5 +- Auto-sync with upstream master, + commit 2585d7b839559e665d5723734862fbe62264b25d: +- Do not use generic selection in C++ mode +- Do not use __builtin_types_compatible_p in C++ mode (#1481205) +- x86-64: Check FMA_Usable in ifunc-mathvec-avx2.h (swbz#21966) +- Various locale fixes (swbz#21750, swbz#21960, swbz#21959, swbz#19852) +- Fix sigval namespace (swbz#21944) +- x86-64: Optimize e_expf with FMA (swbz#21912) +- Adjust glibc-rh827510.patch. + +* Wed Aug 16 2017 Tomasz Kłoczko - 2.26-4 +- Remove 'Buildroot' tag, 'Group' tag, and '%%clean' section, and don't + remove the buildroot in '%%install', all per Fedora Packaging Guidelines + (#1476839) + +* Wed Aug 16 2017 Florian Weimer - 2.26.90-3 +- Auto-sync with upstream master, + commit 403143e1df85dadd374f304bd891be0cd7573e3b: +- x86-64: Align L(SP_RANGE)/L(SP_INF_0) to 8 bytes (swbz#21955) +- powerpc: Add values from Linux 4.8 to +- S390: Add new s390 platform z14. +- Various locale fixes (swbz#14925, swbz#20008, swbz#20482, swbz#12349 + swbz#19982, swbz#20756, swbz#20756, swbz#21836, swbz#17563, swbz#16905, + swbz#21920, swbz#21854) +- NSS: Replace exported NSS lookup functions with stubs (swbz#21962) +- i386: Do not set internal_function +- assert: Suppress pedantic warning caused by statement expression (swbz#21242) +- powerpc: Restrict xssqrtqp operands to Vector Registers (swbz#21941) +- sys/ptrace.h: remove obsolete PTRACE_SEIZE_DEVEL constant (swbz#21928) +- Remove __qaddr_t, __long_double_t +- Fix uc_* namespace (swbz#21457) +- nss: Call __resolv_context_put before early return in get*_r (swbz#21932) +- aarch64: Optimized memcpy for Qualcomm Falkor processor +- manual: Document getcontext uc_stack value on Linux (swbz#759) +- i386: Add (swbz#21913) +- Don't use IFUNC resolver for longjmp or system in libpthread (swbz#21041) +- Fix XPG4.2 bits/sigaction.h namespace (swbz#21899) +- x86-64: Add FMA multiarch functions to libm +- i386: Support static PIE in start.S +- Compile tst-prelink.c without PIE (swbz#21815) +- x86-64: Use _dl_runtime_resolve_opt only with AVX512F (swbz#21871) +- x86: Remove __memset_zero_constant_len_parameter (swbz#21790) + +* Wed Aug 16 2017 Florian Weimer - 2.26-2 +- Disable multi-arch (IFUNC string functions) on i686 (#1471427) +- Remove nosegneg 32-bit Xen PV support libraries (#1482027) +- Adjust spec file to RPM changes + +* Thu Aug 03 2017 Carlos O'Donell - 2.26-1 +- Update to released glibc 2.26. +- Auto-sync with upstream master, + commit 2aad4b04ad7b17a2e6b0e66d2cb4bc559376617b. +- getaddrinfo: Release resolver context on error in gethosts (swbz#21885) diff --git a/langpacklist b/langpacklist deleted file mode 100644 index 367ac6f..0000000 --- a/langpacklist +++ /dev/null @@ -1,197 +0,0 @@ -aa -af -agr -ak -am -an -anp -ar -as -ast -ayc -az -be -bem -ber -bg -bhb -bho -bi -bn -bo -br -brx -bs -byn -ca -ce -chr -ckb -crh -cs -csb -cv -cy -da -de -doi -dsb -dv -dz -el -eo -es -et -eu -fa -ff -fi -fil -fo -fr -fur -fy -ga -gd -gez -gl -gu -gv -ha -hak -he -hi -hif -hne -hr -hsb -ht -hu -hy -ia -id -ig -ik -is -it -iu -ja -ka -kab -kk -kl -km -kn -ko -kok -ks -ku -kw -ky -lb -lg -li -lij -ln -lo -lt -lv -lzh -mag -mai -mfe -mg -mhr -mi -miq -mjw -mk -ml -mn -mni -mnw -mr -ms -mt -my -nan -nb -nds -ne -nhn -niu -nl -nn -nr -nso -oc -om -or -os -pa -pap -pl -ps -pt -quz -raj -rif -ro -ru -rw -sa -sah -sat -sc -sd -se -sgs -shn -shs -si -sid -sk -sl -sm -so -sq -sr -ss -st -sv -sw -syr -szl -ta -tcy -te -tg -th -the -ti -tig -tk -tl -tn -to -tpi -tr -ts -tt -ug -uk -unm -ur -uz -ve -vi -wa -wae -wal -wo -xh -yi -yo -yue -yuw -zu diff --git a/linux-Sync-Linux-6.6-elf.h.patch b/linux-Sync-Linux-6.6-elf.h.patch deleted file mode 100644 index ac3c74a..0000000 --- a/linux-Sync-Linux-6.6-elf.h.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 6b3d687470b8f91bc6eb87e924fe97d4592b3aa5 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Tue, 31 Oct 2023 13:32:38 -0300 -Subject: [PATCH 29/29] linux: Sync Linux 6.6 elf.h - -It adds NT_X86_SHSTK (2fab02b25ae7cf5), NT_RISCV_CSR/NT_RISCV_VECTOR -(9300f00439743c4), and NT_LOONGARCH_HW_BREAK/NT_LOONGARCH_HW_WATCH -(1a69f7a161a78ae). - -Signed-off-by: Peng Fan -Signed-off-by: ticat_fp ---- - elf/elf.h | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/elf/elf.h b/elf/elf.h -index 9c51073f..51633079 100644 ---- a/elf/elf.h -+++ b/elf/elf.h -@@ -794,6 +794,7 @@ typedef struct - #define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ - #define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ - #define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */ -+#define NT_X86_SHSTK 0x204 /* x86 SHSTK state */ - #define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */ - #define NT_S390_TIMER 0x301 /* s390 timer register */ - #define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */ -@@ -832,6 +833,8 @@ typedef struct - #define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers. */ - #define NT_MIPS_FP_MODE 0x801 /* MIPS floating-point mode. */ - #define NT_MIPS_MSA 0x802 /* MIPS SIMD registers. */ -+#define NT_RISCV_CSR 0x900 /* RISC-V Control and Status Registers */ -+#define NT_RISCV_VECTOR 0x901 /* RISC-V vector registers */ - #define NT_LOONGARCH_CPUCFG 0xa00 /* LoongArch CPU config registers. */ - #define NT_LOONGARCH_CSR 0xa01 /* LoongArch control and - status registers. */ -@@ -841,6 +844,8 @@ typedef struct - SIMD Extension registers. */ - #define NT_LOONGARCH_LBT 0xa04 /* LoongArch Loongson Binary - Translation registers. */ -+#define NT_LOONGARCH_HW_BREAK 0xa05 /* LoongArch hardware breakpoint registers */ -+#define NT_LOONGARCH_HW_WATCH 0xa06 /* LoongArch hardware watchpoint registers */ - - /* Legal values for the note segment descriptor types for object files. */ - --- -2.33.0 - diff --git a/nscd.conf b/nscd.conf new file mode 100755 index 0000000..8a24a78 --- /dev/null +++ b/nscd.conf @@ -0,0 +1 @@ +d /run/nscd 0755 root root diff --git a/parse-SUPPORTED.py b/parse-SUPPORTED.py deleted file mode 100644 index cf512de..0000000 --- a/parse-SUPPORTED.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/python3 -# -# This script turns localedata/SUPPORTED (whose path is passed as the -# first argument) into a normalized list of LANGUAGE "_" REGION pairs. -# (If there is no REGION defined, only LANGUAGE is used.) The list -# is written to standard output, with one element per line. - -import sys - -supported, = sys.argv[1:] - -# Pairs seen so far. Used to suppress duplicates. -seen = set() -with open(supported) as inp: - for line in inp: - if line.startswith("#") or line == "SUPPORTED-LOCALES=\\\n": - # Comment or prefix. - continue - if not line.endswith(" \\\n"): - raise IOError("line without continuation: " + repr(line)) - try: - slash = line.index("/") - except ValueError: - raise IOError("line without slash: " + repr(line)) - spec = line[:slash] - for separator in ".@": - try: - # Strip charset, variant specifiers. - spec = spec[:spec.index(separator)] - except ValueError: - pass - seen.add(spec) - -# The C locale does not correspond to a language. -seen.remove("C") - -# The glibc source file is not sorted. -for spec in sorted(seen): - print(spec) -print() # The Lua generator produces a trailing newline. diff --git a/power6emul.c b/power6emul.c new file mode 100755 index 0000000..1b0187b --- /dev/null +++ b/power6emul.c @@ -0,0 +1,273 @@ +/* Emulate power6 mf[tf]gpr and fri[zpmn] instructions. + Copyright (C) 2006 Red Hat, Inc. + Contributed by Jakub Jelinek , 2006. + + This 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. + + It 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +extern double frip (double), friz (double), frin (double), frim (double); +asm (".globl frip, friz, frin, frim\n.hidden frip, friz, frin, frim\n\t" +#ifdef __powerpc64__ + ".section \".toc\",\"aw\"\n" +"8:" ".tc FD_43300000_0[TC],0x4330000000000000\n" +"9:" ".tc FD_3fe00000_0[TC],0x3fe0000000000000\n\t" + ".previous\n\t" +#else + ".rodata\n\t" + ".align 2\n" +"8:" ".long 0x59800000\n" +"9:" ".long 0x3f000000\n\t" + ".previous\n\t" +#endif + "# frip == ceil\n" +"frip:" "mffs 11\n\t" +#ifdef __powerpc64__ + "lfd 13,8b@toc(2)\n\t" +#else + "mflr 11\n\t" + "bcl 20,31,1f\n" +"1:" "mflr 9\n\t" + "addis 9,9,8b-1b@ha\n\t" + "lfs 13,8b-1b@l(9)\n\t" + "mtlr 11\n\t" +#endif + "fabs 0,1\n\t" + "fsub 12,13,13\n\t" + "fcmpu 7,0,13\n\t" + "fcmpu 6,1,12\n\t" + "bnllr- 7\n\t" + "mtfsfi 7,2\n\t" + "ble- 6,2f\n\t" + "fadd 1,1,13\n\t" + "fsub 1,1,13\n\t" + "fabs 1,1\n\t" + "mtfsf 0x01,11\n\t" + "blr\n" +"2:" "bge- 6,3f\n\t" + "fsub 1,1,13\n\t" + "fadd 1,1,13\n\t" + "fnabs 1,1\n" +"3:" "mtfsf 0x01,11\n\t" + "blr\n\t" + "# friz == trunc\n" +"friz:" "mffs 11\n\t" +#ifdef __powerpc64__ + "lfd 13,8b@toc(2)\n\t" +#else + "mflr 11\n\t" + "bcl 20,31,1f\n" +"1:" "mflr 9\n\t" + "addis 9,9,8b-1b@ha\n\t" + "lfs 13,8b-1b@l(9)\n\t" + "mtlr 11\n\t" +#endif + "fabs 0,1\n\t" + "fsub 12,13,13\n\t" + "fcmpu 7,0,13\n\t" + "fcmpu 6,1,12\n\t" + "bnllr- 7\n\t" + "mtfsfi 7,1\n\t" + "ble- 6,2f\n\t" + "fadd 1,1,13\n\t" + "fsub 1,1,13\n\t" + "fabs 1,1\n\t" + "mtfsf 0x01,11\n\t" + "blr\n" +"2:" "bge- 6,3f\n\t" + "fsub 1,1,13\n\t" + "fadd 1,1,13\n\t" + "fnabs 1,1\n" +"3:" "mtfsf 0x01,11\n\t" + "blr\n\t" + "# frin == round\n" +"frin:" "mffs 11\n\t" +#ifdef __powerpc64__ + "lfd 13,8b@toc(2)\n\t" +#else + "mflr 11\n\t" + "bcl 20,31,1f\n" +"1:" "mflr 9\n\t" + "addis 9,9,8b-1b@ha\n\t" + "addi 9,9,8b-1b@l\n\t" + "mtlr 11\n\t" + "lfs 13,0(9)\n\t" +#endif + "fabs 0,1\n\t" + "fsub 12,13,13\n\t" + "fcmpu 7,0,13\n\t" + "fcmpu 6,1,12\n\t" + "bnllr- 7\n\t" + "mtfsfi 7,1\n\t" +#ifdef __powerpc64__ + "lfd 10,9b@toc(2)\n\t" +#else + "lfs 10,9b-8b(9)\n\t" +#endif + "ble- 6,2f\n\t" + "fadd 1,1,10\n\t" + "fadd 1,1,13\n\t" + "fsub 1,1,13\n\t" + "fabs 1,1\n\t" + "mtfsf 0x01,11\n\t" + "blr\n" +"2:" "fsub 9,1,10\n\t" + "bge- 6,3f\n\t" + "fsub 1,9,13\n\t" + "fadd 1,1,13\n\t" + "fnabs 1,1\n" +"3:" "mtfsf 0x01,11\n\t" + "blr\n\t" + "# frim == floor\n" +"frim:" "mffs 11\n\t" +#ifdef __powerpc64__ + "lfd 13,8b@toc(2)\n\t" +#else + "mflr 11\n\t" + "bcl 20,31,1f\n" +"1:" "mflr 9\n\t" + "addis 9,9,8b-1b@ha\n\t" + "lfs 13,8b-1b@l(9)\n\t" + "mtlr 11\n\t" +#endif + "fabs 0,1\n\t" + "fsub 12,13,13\n\t" + "fcmpu 7,0,13\n\t" + "fcmpu 6,1,12\n\t" + "bnllr- 7\n\t" + "mtfsfi 7,3\n\t" + "ble- 6,2f\n\t" + "fadd 1,1,13\n\t" + "fsub 1,1,13\n\t" + "fabs 1,1\n\t" + "mtfsf 0x01,11\n\t" + "blr\n" +"2:" "bge- 6,3f\n\t" + "fsub 1,1,13\n\t" + "fadd 1,1,13\n\t" + "fnabs 1,1\n" +"3:" "mtfsf 0x01,11\n\t" + "blr\n"); + +#ifdef __powerpc64__ +#define m1 0x5555555555555555L +#define m2 0x3333333333333333L +#define m3 0x0f0f0f0f0f0f0f0fL +#else +#define m1 0x55555555 +#define m2 0x33333333 +#define m3 0x0f0f0f0f +#endif + +static inline unsigned long +popcntb (unsigned long n) +{ + n -= (n >> 1) & m1; + n = (n & m2) + ((n >> 2) & m2); + n = (n + (n >> 4)) & m3; + return n; +} + +static void +catch_sigill (int signal, struct sigcontext *ctx) +{ + unsigned int insn = *(unsigned int *) (ctx->regs->nip); +#ifdef __powerpc64__ + if ((insn & 0xfc1f07ff) == 0x7c0005be) /* mftgpr */ + { + unsigned long *regs = (unsigned long *) ctx->regs; + unsigned fpr = (insn >> 11) & 0x1f; + unsigned gpr = (insn >> 21) & 0x1f; + regs[gpr] = regs[fpr + 0x30]; + ctx->regs->nip += 4; + return; + } + if ((insn & 0xfc1f07ff) == 0x7c0004be) /*mffgpr */ + { + unsigned long *regs = (unsigned long *) ctx->regs; + unsigned fpr = (insn >> 21) & 0x1f; + unsigned gpr = (insn >> 11) & 0x1f; + regs[fpr + 0x30] = regs[gpr]; + ctx->regs->nip += 4; + return; + } +#endif + if ((insn & 0xfc1f073f) == 0xfc000310) /* fri[pznm] */ + { +#ifdef __powerpc64__ + double *regs = (double *) (((char *) ctx->regs) + 0x30 * 8); + unsigned int *fpscr = (unsigned int *) (((char *) ctx->regs) + 0x50 * 8 + 4); +#else + double *regs = (double *) (((char *) ctx->regs) + 0x30 * 4); + unsigned int *fpscr = (unsigned int *) (((char *) ctx->regs) + 0x30 * 4 + 0x20 * 8 + 4); +#endif + unsigned dest = (insn >> 21) & 0x1f; + unsigned src = (insn >> 11) & 0x1f; + switch (insn & 0xc0) + { + case 0: + regs[dest] = frin (regs[src]); + break; + case 0x40: + regs[dest] = friz (regs[src]); + break; + case 0x80: + regs[dest] = frip (regs[src]); + break; + case 0xc0: + regs[dest] = frim (regs[src]); + break; + } + /* Update raised exceptions. */ + union { unsigned int i[2]; double d; } u; + asm volatile ("mffs %0" : "=f" (u.d)); + u.i[1] &= 0xfffe0000; /* Is this correct? */ + *fpscr |= u.i[1]; + ctx->regs->nip += 4; + return; + } + if ((insn & 0xfc00ffff) == 0x7c0000f4) /* popcntb */ + { + unsigned long *regs = (unsigned long *) ctx->regs; + unsigned dest = (insn >> 16) & 0x1f; + unsigned src = (insn >> 21) & 0x1f; + unsigned long res = 0; + int i; + + regs[dest] = popcntb (regs[src]); + ctx->regs->nip += 4; + return; + } + + struct sigaction sa; + sa.sa_handler = SIG_DFL; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (signal, &sa, NULL); + raise (signal); +} + +static void +__attribute__ ((constructor)) +install_handler (void) +{ + struct sigaction sa; + sa.sa_handler = (void *) catch_sigill; + sigemptyset (&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sigaction (SIGILL, &sa, NULL); +} diff --git a/wrap-find-debuginfo.sh b/wrap-find-debuginfo.sh deleted file mode 100644 index 6a558df..0000000 --- a/wrap-find-debuginfo.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/bin/bash -# Wrapper script for find-debuginfo.sh -# -# Usage: -# wrap-find-debuginfo.sh SYSROOT-PATH SCRIPT-PATH SCRIPT-ARGS... -# -# The wrapper saves the original version of ld.so found in SYSROOT-PATH, -# invokes SCRIPT-PATH with SCRIPT-ARGS, and then restores the -# LDSO-PATH file, followed by note merging and DWZ compression. -# As a result, ld.so has (mostly) unchanged debuginfo even -# after debuginfo extraction. -# -# For libc.so.6, a set of strategic symbols is preserved in .symtab -# that are frequently used in valgrind suppressions and elsewhere. - -set -ex - -ldso_tmp="$(mktemp)" -libc_tmp="$(mktemp)" - -# Prefer a separately installed debugedit over the RPM-integrated one. -if command -v debugedit >/dev/null ; then - debugedit=debugedit -else - debugedit=/usr/lib/rpm/debugedit -fi - -cleanup () { - rm -f "$ldso_tmp" "$libc_tmp" -} -trap cleanup 0 - -sysroot_path="$1" -shift -script_path="$1" -shift - -# See ldso_path setting in glibc.spec. -ldso_path= -for ldso_candidate in `find "$sysroot_path" -regextype posix-extended \ - -regex '.*/ld(-.*|64|)\.so\.[0-9]+$' -type f` ; do - if test -z "$ldso_path" ; then - ldso_path="$ldso_candidate" - else - echo "error: multiple ld.so candidates: $ldso_path, $ldso_candidate" - exit 1 - fi -done - -# libc.so.6 always uses this name, so it is simpler to locate. -libc_path= -for libc_candidate in `find "$sysroot_path" -name libc.so.6`; do - if test -z "$libc_path" ; then - libc_path="$libc_candidate" - else - echo "error: multiple libc.so.6 candidates: $libc_path, $libc_candidate" - exit 1 - fi -done - - -# Preserve the original files. -cp "$ldso_path" "$ldso_tmp" -cp "$libc_path" "$libc_tmp" - -# Run the debuginfo extraction. -"$script_path" "$@" - -# Restore the original files. -cp "$ldso_tmp" "$ldso_path" -cp "$libc_tmp" "$libc_path" - -# Reduce the size of notes. Primarily for annobin. -objcopy --merge-notes "$ldso_path" -objcopy --merge-notes "$libc_path" - -# libc.so.6: Reduce to valuable symbols. Eliminate file symbols, -# annobin symbols, and symbols used by the glibc build to implement -# hidden aliases (__EI_*). We would also like to remove __GI_* -# symbols, but even listing them explicitly (as in -K __GI_strlen) -# still causes strip to remove them, so there is no filtering of -# __GI_* here. (Debuginfo is gone after this, so no need to optimize -# it.) -strip -w \ - -K '*' \ - -K '!*.c' \ - -K '!*.os' \ - -K '!.annobin_*' \ - -K '!__EI_*' \ - -K '!__PRETTY_FUNCTION__*' \ - "$libc_path" - -# ld.so: Rewrite the source file paths to match the extracted -# locations. First compute the arguments for invoking debugedit. -# See find-debuginfo.sh. -debug_dest_name="/usr/src/debug" -last_arg= -while true ; do - arg="$1" - shift || break - case "$arg" in - (--unique-debug-src-base) - debug_dest_name="/usr/src/debug/$1" - shift - ;; - (-*) - ;; - (*) - last_arg="$arg" - ;; - esac -done -debug_base_name=${last_arg:-$RPM_BUILD_ROOT} -$debugedit -b "$debug_base_name" -d "$debug_dest_name" -n $ldso_path - -# Apply single-file DWARF optimization. -dwz $ldso_path