Compare commits

...

No commits in common. "a23.1" and "a8.4-temp-2.28-164.el8_5.3" have entirely different histories.

642 changed files with 129161 additions and 15978 deletions

View file

@ -1,194 +0,0 @@
From 4ea972b7edd7e36610e8cde18bf7a8149d7bac4f Mon Sep 17 00:00:00 2001
From: Florian Weimer <fweimer@redhat.com>
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+/* 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 <support/test-driver.c>
--
2.39.3

View file

@ -1,338 +0,0 @@
From a9728f798ec7f05454c95637ee6581afaa9b487d Mon Sep 17 00:00:00 2001
From: Siddhesh Poyarekar <siddhesh@sourceware.org>
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 <siddhesh@sourceware.org>
(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
+ <https://www.gnu.org/licenses/>. */
+
+#include <nss.h>
+#include <stdlib.h>
+#include <string.h>
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <nss.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#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 <support/test-driver.c>
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

View file

@ -1,98 +0,0 @@
From 856bac55f98dc840e7c27cfa82262b933385de90 Mon Sep 17 00:00:00 2001
From: Romain Geissler <romain.geissler@amadeus.com>
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 <siddhesh@sourceware.org>
(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 <netdb.h>
#include <stdlib.h>
#include <string.h>
+#include <mcheck.h>
#include <support/check.h>
#include <support/xstdio.h>
#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

View file

@ -1,181 +0,0 @@
From d1a83b6767f68b3cb5b4b4ea2617254acd040c82 Mon Sep 17 00:00:00 2001
From: Arjun Shankar <arjun@redhat.com>
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 <adhemerval.zanella@linaro.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
(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
+ <https://www.gnu.org/licenses/>. */
+
+#include <syslog.h>
+#include <string.h>
+
+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 <support/test-driver.c>
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

View file

@ -1,106 +0,0 @@
From 2bc9d7c002bdac38b5c2a3f11b78e309d7765b83 Mon Sep 17 00:00:00 2001
From: Arjun Shankar <arjun@redhat.com>
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 <carlos@redhat.com>
(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

View file

@ -1,41 +0,0 @@
From b9b7d6a27aa0632f334352fa400771115b3c69b7 Mon Sep 17 00:00:00 2001
From: Arjun Shankar <arjun@redhat.com>
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 <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
(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 <sys/uio.h>
#include <sys/un.h>
#include <syslog.h>
+#include <limits.h>
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

View file

@ -1,213 +0,0 @@
From f9dc609e06b1136bb0408be9605ce7973a767ada Mon Sep 17 00:00:00 2001
From: Charles Fol <folcharles@gmail.com>
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 <adhemerval.zanella@linaro.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
---
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <errno.h>
+#include <iconv.h>
+#include <sys/mman.h>
+
+#include <support/xunistd.h>
+#include <support/check.h>
+#include <support/support.h>
+
+/* 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 <support/test-driver.c>
--
2.39.3

View file

@ -1,139 +0,0 @@
From 27e06a423cf06845a0515ab767a109b31b34724a Mon Sep 17 00:00:00 2001
From: Chunmei Xu <xuchunmei@linux.alibaba.com>
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

6058
ChangeLog.old Executable file

File diff suppressed because it is too large Load diff

View file

@ -1,40 +0,0 @@
From 2c8dfc45a8009e5110a9d2148b62d802e989fde7 Mon Sep 17 00:00:00 2001
From: ticat_fp <fanpeng@loongson.cn>
Date: Thu, 29 Feb 2024 15:58:31 +0800
Subject: [PATCH] Decrease value of arch_minimum_kernel with LoongArch
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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

View file

@ -1,499 +0,0 @@
From 8923e4e9c79e672fd6b3b89aba598a60d5c01211 Mon Sep 17 00:00:00 2001
From: caiyinyu <caiyinyu@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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
+ <http://www.gnu.org/licenses/>. */
+
+# include <stdbool.h>
+# include <stdint.h>
+# include <unistd.h> /* Get STDOUT_FILENO for _dl_printf. */
+# include <elf/dl-tunables.h>
+# include <string.h>
+# include <cpu-features.h>
+# include <ldsodefs.h>
+# include <sys/auxv.h>
+
+# 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
+ <https://www.gnu.org/licenses/>. */
+
+
+#include <ldsodefs.h>
+
+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 <dl-static-tls.h>
#include <dl-machine-rel.h>
+#include <cpu-features.c>
+
#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
+# <http://www.gnu.org/licenses/>.
+
+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
+ <http://www.gnu.org/licenses/>. */
+
+#include <cpu-features.h>
+#include <elf/dl-hwcaps.h>
+#include <elf/dl-tunables.h>
+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 <stdint.h>
#include <sys/auxv.h>
-#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
+ <http://www.gnu.org/licenses/>. */
+
+/* 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <sysdeps/loongarch/cpu-tunables.c>
+#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
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
+ <http://www.gnu.org/licenses/>. */
+
+#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 <ldsodefs.h>
+# include <cpu-features.c>
+
+extern struct cpu_features _dl_larch_cpu_features;
+
+# define ARCH_INIT_CPU_FEATURES() init_cpu_features (&_dl_larch_cpu_features)
+
+#endif
+#include <csu/libc-start.c>
--
2.33.0

View file

@ -1,485 +0,0 @@
From 3ee56bbc56faa7b85a6513340db4a4fdd6ce709d Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define memchr __redirect_memchr
+# include <string.h>
+# 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

View file

@ -1,946 +0,0 @@
From 60f4bbd1eec528ba8df044ae6b3091f6337a7fcc Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define memcmp __redirect_memcmp
+# include <string.h>
+# 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

View file

@ -1,417 +0,0 @@
From c4c272fb8067364530a2a78df92c37403acc963f Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#if IS_IN (libc)
+# define MEMRCHR __memrchr_generic
+#endif
+
+#include <string/memrchr.c>
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define memrchr __redirect_memrchr
+# include <string.h>
+# 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

View file

@ -1,784 +0,0 @@
From 14032f7bbe18443af8492f5d0365f72b76701673 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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
+ <https://www.gnu.org/licenses/>. */
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define memset __redirect_memset
+# include <string.h>
+# 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

View file

@ -1,448 +0,0 @@
From b412bcb2cf4914a664bcd24924d670a2e37394b3 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+#include <sys/regdef.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#if IS_IN (libc)
+# define rawmemchr __redirect_rawmemchr
+# define __rawmemchr __redirect___rawmemchr
+# include <string.h>
+# 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

View file

@ -1,499 +0,0 @@
From e258cfcf92f5e31e902fa045b41652f00fcf2521 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <http://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define strcmp __redirect_strcmp
+# include <string.h>
+# 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

File diff suppressed because it is too large Load diff

View file

@ -1,583 +0,0 @@
From 6f03da2d7ef218c0f78375cf706dada59c3fee63 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <http://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define strncmp __redirect_strncmp
+# include <string.h>
+# 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

View file

@ -1,465 +0,0 @@
From e494d32d3b76eee0d59cfab37789a356459b517a Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define strnlen __redirect_strnlen
+# define __strnlen __redirect___strnlen
+# include <string.h>
+# 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

View file

@ -1,670 +0,0 @@
From d537d0ab45a55048c8da483e73be4448ddb45525 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define strrchr __redirect_strrchr
+# include <string.h>
+# 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

View file

@ -1,626 +0,0 @@
From b5979df8ad07823c79a934c1fa0a91ec0abffb61 Mon Sep 17 00:00:00 2001
From: caiyinyu <caiyinyu@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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 <bits/link.h> directly; use <link.h> 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
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link_lavcurrent.h> directly; use <link.h> 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
+ <https://www.gnu.org/licenses/>. */
+
+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

View file

@ -1,102 +0,0 @@
From 7353f21f6ed1754b67e455e2b80123787efa9e91 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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 <sysdep.h>
#include <sys/asm.h>
-#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

View file

@ -1,277 +0,0 @@
From e5ccd79e81de7ad5821fde83875973e878d85d4b Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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

View file

@ -1,67 +0,0 @@
From fb72c81f9894b23797f6e2e066532c0963f5155f Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
.../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

View file

@ -1,44 +0,0 @@
From 7f703cf758c4f185dd62f2a4f463002bb514af16 Mon Sep 17 00:00:00 2001
From: Xi Ruoyao <xry111@xry111.site>
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 <xry111@xry111.site>
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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

View file

@ -1,65 +0,0 @@
From 8dcd8c837df2e3cf81675522487697522f1542f8 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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

View file

@ -1,56 +0,0 @@
From f8d66a269cb6f1a7087afadf3375bdf0553abf53 Mon Sep 17 00:00:00 2001
From: Xi Ruoyao <xry111@xry111.site>
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 <xry111@xry111.site>
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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

View file

@ -1,28 +0,0 @@
From b4b4bb7c9220a0bbdf5aec0ac8c1de1d22329280 Mon Sep 17 00:00:00 2001
From: caiyinyu <caiyinyu@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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

View file

@ -1,81 +0,0 @@
From 458ab6d5f39cca1cabd83abd2022f67491f6f5ed Mon Sep 17 00:00:00 2001
From: caiyinyu <caiyinyu@loongson.cn>
Date: Fri, 20 Oct 2023 09:20:02 +0800
Subject: [PATCH 27/29] LoongArch: Unify Register Names.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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

View file

@ -1,24 +0,0 @@
From 4828d1aa0028e819a5fb336d962e8f7cbfedf8b4 Mon Sep 17 00:00:00 2001
From: caiyinyu <caiyinyu@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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

View file

@ -1,30 +0,0 @@
From 4938840b15ff9734fdcc63cc0744ce3f3bbb0b16 Mon Sep 17 00:00:00 2001
From: caiyinyu <caiyinyu@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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

View file

@ -1,528 +0,0 @@
From 43abd8772a143cd96688c081500397dd712e631b Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <string.h>
+#include <wchar.h>
+#include <ldsodefs.h>
+#include <ifunc-impl-list.h>
+#include <stdio.h>
+
+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
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+
+#if IS_IN (libc)
+# define strlen __redirect_strlen
+# include <string.h>
+# 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

File diff suppressed because it is too large Load diff

View file

@ -1,706 +0,0 @@
From aca7d7f0dde5f56344e8e58e5f6648c96bb1f1cc Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define strchr __redirect_strchr
+# include <string.h>
+# 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#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
+ <https://www.gnu.org/licenses/>. */
+
+#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
+ <http://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+
+#if IS_IN (libc)
+# define strchrnul __redirect_strchrnul
+# define __strchrnul __redirect___strchrnul
+# include <string.h>
+# 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

View file

@ -1,11 +0,0 @@
Anolis OS
=======================================
# 代码仓库说明
## 分支说明
>进行代码开发工作时,请注意选择当前版本对应的分支
* aX分支为对应大版本的主分支,如a8分支对应当前最新版本
* aX.Y分支为对应小版本的维护分支如a8.2分支对应8.2版本
## 开发流程
1. 首先fork目标分支到自己的namespace
2. 在自己的fork分支上做出修改
3. 向对应的仓库中提交merge request源分支为fork分支

View file

@ -1,478 +0,0 @@
From c0f3b0a8c71c26d5351e8ddabe3e8a323803e683 Mon Sep 17 00:00:00 2001
From: caiyinyu <caiyinyu@loongson.cn>
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 <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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
- <http://www.gnu.org/licenses/>. */
-
-# include <stdbool.h>
-# include <stdint.h>
-# include <unistd.h> /* Get STDOUT_FILENO for _dl_printf. */
-# include <elf/dl-tunables.h>
-# include <string.h>
-# include <cpu-features.h>
-# include <ldsodefs.h>
-# include <sys/auxv.h>
-
-# 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
- <https://www.gnu.org/licenses/>. */
-
-
-#include <ldsodefs.h>
-
-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 <dl-static-tls.h>
#include <dl-machine-rel.h>
-#include <cpu-features.c>
-
#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
-# <http://www.gnu.org/licenses/>.
-
-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
- <http://www.gnu.org/licenses/>. */
-
-#include <cpu-features.h>
-#include <elf/dl-hwcaps.h>
-#include <elf/dl-tunables.h>
-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 <stdint.h>
#include <sys/auxv.h>
-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
- <http://www.gnu.org/licenses/>. */
-
-/* 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
- <http://www.gnu.org/licenses/>. */
-
-#include <config.h>
-#include <sysdeps/loongarch/cpu-tunables.c>
-#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
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
- <http://www.gnu.org/licenses/>. */
-
-#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 <ldsodefs.h>
-# include <cpu-features.c>
-
-extern struct cpu_features _dl_larch_cpu_features;
-
-# define ARCH_INIT_CPU_FEATURES() init_cpu_features (&_dl_larch_cpu_features)
-
-#endif
-#include <csu/libc-start.c>
--
2.33.0

494
SUPPORTED Executable file
View file

@ -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 \

0
bench.mk Normal file → Executable file
View file

862
build-locale-archive.c Executable file
View file

@ -0,0 +1,862 @@
#define _GNU_SOURCE
#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#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);
}

View file

@ -1,39 +0,0 @@
From fc60db3cf29ba157d09ba4f4b92e3ab382b0339d Mon Sep 17 00:00:00 2001
From: Xi Ruoyao <xry111@xry111.site>
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 <xry111@xry111.site>
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
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

Binary file not shown.

25
glibc-asflags.patch Executable file
View file

@ -0,0 +1,25 @@
Author: Florian Weimer <fweimer@redhat.com>
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)

286
glibc-c-utf8-locale.patch Executable file
View file

@ -0,0 +1,286 @@
Short description: Add C.UTF-8 support.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-submitted
This patch needs to upstream as part of Carlos O'Donell
<carlos@redhat.com>'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 <mfabian@redhat.com>
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
+<U0000>
+..
+<UFFFF>
+<U10000>
+..
+<U1FFFF>
+<U20000>
+..
+<U2FFFF>
+<UE0000>
+..
+<UEFFFF>
+<UF0000>
+..
+<UFFFFF>
+<U100000>
+..
+<U10FFFF>
+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 "<U0055><U0053><U0044><U0020>"
+% Using "$" for currency_symbol. But maybe <U00A4> would be better?
+% U+00A4 is the "generic currency symbol"
+% (https://en.wikipedia.org/wiki/Currency_sign_%28typography%29)
+currency_symbol "<U0024>"
+mon_decimal_point "<U002E>"
+mon_thousands_sep ""
+mon_grouping -1
+positive_sign ""
+negative_sign "<U002D>"
+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 "<U002E>"
+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 "<U0053><U0075><U006E>";"<U004D><U006F><U006E>";/
+ "<U0054><U0075><U0065>";"<U0057><U0065><U0064>";/
+ "<U0054><U0068><U0075>";"<U0046><U0072><U0069>";/
+ "<U0053><U0061><U0074>"
+
+% Full weekday names (%A)
+day "<U0053><U0075><U006E><U0064><U0061><U0079>";/
+ "<U004D><U006F><U006E><U0064><U0061><U0079>";/
+ "<U0054><U0075><U0065><U0073><U0064><U0061><U0079>";/
+ "<U0057><U0065><U0064><U006E><U0065><U0073><U0064><U0061><U0079>";/
+ "<U0054><U0068><U0075><U0072><U0073><U0064><U0061><U0079>";/
+ "<U0046><U0072><U0069><U0064><U0061><U0079>";/
+ "<U0053><U0061><U0074><U0075><U0072><U0064><U0061><U0079>"
+
+% Abbreviated month names (%b)
+abmon "<U004A><U0061><U006E>";"<U0046><U0065><U0062>";/
+ "<U004D><U0061><U0072>";"<U0041><U0070><U0072>";/
+ "<U004D><U0061><U0079>";"<U004A><U0075><U006E>";/
+ "<U004A><U0075><U006C>";"<U0041><U0075><U0067>";/
+ "<U0053><U0065><U0070>";"<U004F><U0063><U0074>";/
+ "<U004E><U006F><U0076>";"<U0044><U0065><U0063>"
+
+% Full month names (%B)
+mon "<U004A><U0061><U006E><U0075><U0061><U0072><U0079>";/
+ "<U0046><U0065><U0062><U0072><U0075><U0061><U0072><U0079>";/
+ "<U004D><U0061><U0072><U0063><U0068>";/
+ "<U0041><U0070><U0072><U0069><U006C>";/
+ "<U004D><U0061><U0079>";/
+ "<U004A><U0075><U006E><U0065>";/
+ "<U004A><U0075><U006C><U0079>";/
+ "<U0041><U0075><U0067><U0075><U0073><U0074>";/
+ "<U0053><U0065><U0070><U0074><U0065><U006D><U0062><U0065><U0072>";/
+ "<U004F><U0063><U0074><U006F><U0062><U0065><U0072>";/
+ "<U004E><U006F><U0076><U0065><U006D><U0062><U0065><U0072>";/
+ "<U0044><U0065><U0063><U0065><U006D><U0062><U0065><U0072>"
+
+% 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 "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0059>"
+
+% Appropriate date representation (%x)
+% "%m/%d/%y"
+d_fmt "<U0025><U006D><U002F><U0025><U0064><U002F><U0025><U0079>"
+
+% Appropriate time representation (%X)
+% "%H:%M:%S"
+t_fmt "<U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053>"
+
+% Appropriate AM/PM time representation (%r)
+% "%I:%M:%S %p"
+t_fmt_ampm "<U0025><U0049><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0070>"
+
+% Equivalent of AM/PM (%p) "AM"/"PM"
+%
+am_pm "<U0041><U004D>";"<U0050><U004D>"
+
+% Appropriate date representation (date(1)) "%a %b %e %H:%M:%S %Z %Y"
+date_fmt "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065><U0020><U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025><U005A><U0020><U0025><U0059>"
+END LC_TIME
+
+LC_MESSAGES
+% This is the POSIX Locale definition for
+% the LC_NUMERIC category.
+%
+yesexpr "<U005E><U005B><U0079><U0059><U005D>"
+noexpr "<U005E><U005B><U006E><U004E><U005D>"
+yesstr "<U0059><U0065><U0073>"
+nostr "<U004E><U006F>"
+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 "<U0025><U0070><U0025><U0074><U0025><U0067><U0025><U0074>/
+<U0025><U006D><U0025><U0074><U0025><U0066>"
+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 "<U0025><U0061><U0025><U004E><U0025><U0066><U0025><U004E>/
+<U0025><U0064><U0025><U004E><U0025><U0062><U0025><U004E><U0025><U0073>/
+<U0020><U0025><U0068><U0020><U0025><U0065><U0020><U0025><U0072><U0025>/
+<U004E><U0025><U0043><U002D><U0025><U007A><U0020><U0025><U0054><U0025>/
+<U004E><U0025><U0063><U0025><U004E>"
+END LC_ADDRESS
+
+LC_TELEPHONE
+% This is the ISO/IEC 14652 "i18n" definition for
+% the LC_TELEPHONE category.
+% "+%c %a %l"
+tel_int_fmt "<U002B><U0025><U0063><U0020><U0025><U0061><U0020><U0025>/
+<U006C>"
+% (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

43
glibc-cs-path.patch Normal file → Executable file
View file

@ -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 <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-needed
In Fedora we should return only /usr/bin as CS_PATH because /bin is just
a symlink to /usr/bin after MoveToUsr transition (which glibc has not
really completed).
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"

View file

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

View file

@ -0,0 +1,91 @@
Short description: Cleanup use of _dl_starting_up.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
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 <schwab@redhat.com>
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)
{

View file

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

View file

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

View file

@ -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'; \

46
glibc-fedora-locarchive.patch Executable file
View file

@ -0,0 +1,46 @@
Short description: Allow access to internal locale archive functions.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
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 <jakub@redhat.com>
* 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)
{

31
glibc-fedora-nis-rh188246.patch Executable file
View file

@ -0,0 +1,31 @@
Short description: Fedora-specific enabling batch read in NSS.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
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 <jakub@redhat.com>
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 <jakub@redhat.com> 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

20
glibc-fedora-nscd.patch Executable file
View file

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

View file

@ -0,0 +1,38 @@
Short description: Do not define _XOPEN_STREAMS.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
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 <jakub@redhat.com> 2.7.90-11
- remove <stropts.h>, 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

View file

@ -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 (<Unnnn>..<Ummmm> 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
<UE78A> /xa6/xbe <Private Use>
<UE78B> /xa6/xbf <Private Use>
<UE78C> /xa6/xc0 <Private Use>
-% 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 <UFE10> to <UFE19>.
-% <UE78D> /xa6/xd9 <Private Use>
-% <UE78E> /xa6/xda <Private Use>
-% <UE78F> /xa6/xdb <Private Use>
-% <UE790> /xa6/xdc <Private Use>
-% <UE791> /xa6/xdd <Private Use>
-% <UE792> /xa6/xde <Private Use>
-% <UE793> /xa6/xdf <Private Use>
-% <UE794> /xa6/xec <Private Use>
-% <UE795> /xa6/xed <Private Use>
-% <UE796> /xa6/xf3 <Private Use>
+<UE78D> /x84/x31/x82/x36 <Private Use>
+<UE78E> /x84/x31/x82/x38 <Private Use>
+<UE78F> /x84/x31/x82/x37 <Private Use>
+<UE790> /x84/x31/x82/x39 <Private Use>
+<UE791> /x84/x31/x83/x30 <Private Use>
+<UE792> /x84/x31/x83/x31 <Private Use>
+<UE793> /x84/x31/x83/x32 <Private Use>
+<UE794> /x84/x31/x83/x33 <Private Use>
+<UE795> /x84/x31/x83/x34 <Private Use>
+<UE796> /x84/x31/x83/x35 <Private Use>
<UE797> /xa6/xf6 <Private Use>
<UE798> /xa6/xf7 <Private Use>
<UE799> /xa6/xf8 <Private Use>
@@ -57387,17 +57371,15 @@ CHARMAP
<UE813> /xd7/xfd <Private Use>
<UE814> /xd7/xfe <Private Use>
<UE815> /x83/x36/xc9/x34 <Private Use>
-% These 3 PUA mappings use equivalents <U20087>, <U20089> and <U200CC>.
-% <UE816> /xfe/x51 <Private Use>
-% <UE817> /xfe/x52 <Private Use>
-% <UE818> /xfe/x53 <Private Use>
+<UE816> /xfe/x51 <Private Use>
+<UE817> /xfe/x52 <Private Use>
+<UE818> /xfe/x53 <Private Use>
<UE819> /x83/x36/xc9/x35 <Private Use>
<UE81A> /x83/x36/xc9/x36 <Private Use>
<UE81B> /x83/x36/xc9/x37 <Private Use>
<UE81C> /x83/x36/xc9/x38 <Private Use>
<UE81D> /x83/x36/xc9/x39 <Private Use>
-% This 1 PUA mapping uses the equivalent <U9FB4>.
-% <UE81E> /xfe/x59 <Private Use>
+<UE81E> /x82/x35/x90/x37 <Private Use>
<UE81F> /x83/x36/xca/x30 <Private Use>
<UE820> /x83/x36/xca/x31 <Private Use>
<UE821> /x83/x36/xca/x32 <Private Use>
@@ -57405,22 +57387,19 @@ CHARMAP
<UE823> /x83/x36/xca/x34 <Private Use>
<UE824> /x83/x36/xca/x35 <Private Use>
<UE825> /x83/x36/xca/x36 <Private Use>
-% This 1 PUA mapping uses the equivalent <U9FB5>.
-% <UE826> /xfe/x61 <Private Use>
+<UE826> /x82/x35/x90/x38 <Private Use>
<UE827> /x83/x36/xca/x37 <Private Use>
<UE828> /x83/x36/xca/x38 <Private Use>
<UE829> /x83/x36/xca/x39 <Private Use>
<UE82A> /x83/x36/xcb/x30 <Private Use>
-% These 2 PUA mappings use the equivalents <U9FB6> and <U9FB7>.
-% <UE82B> /xfe/x66 <Private Use>
-% <UE82C> /xfe/x67 <Private Use>
+<UE82B> /x82/x35/x90/x39 <Private Use>
+<UE82C> /x82/x35/x91/x30 <Private Use>
<UE82D> /x83/x36/xcb/x31 <Private Use>
<UE82E> /x83/x36/xcb/x32 <Private Use>
<UE82F> /x83/x36/xcb/x33 <Private Use>
<UE830> /x83/x36/xcb/x34 <Private Use>
-% These 2 PUA mappings use the equivalents <U215D7> and <U9FB8>.
-% <UE831> /xfe/x6c <Private Use>
-% <UE832> /xfe/x6d <Private Use>
+<UE831> /xfe/x6c <Private Use>
+<UE832> /x82/x35/x91/x31 <Private Use>
<UE833> /x83/x36/xcb/x35 <Private Use>
<UE834> /x83/x36/xcb/x36 <Private Use>
<UE835> /x83/x36/xcb/x37 <Private Use>
@@ -57429,8 +57408,7 @@ CHARMAP
<UE838> /x83/x36/xcc/x30 <Private Use>
<UE839> /x83/x36/xcc/x31 <Private Use>
<UE83A> /x83/x36/xcc/x32 <Private Use>
-% This 1 PUA mapping uses the equivalent <U2298F>.
-% <UE83B> /xfe/x76 <Private Use>
+<UE83B> /xfe/x76 <Private Use>
<UE83C> /x83/x36/xcc/x33 <Private Use>
<UE83D> /x83/x36/xcc/x34 <Private Use>
<UE83E> /x83/x36/xcc/x35 <Private Use>
@@ -57438,8 +57416,7 @@ CHARMAP
<UE840> /x83/x36/xcc/x37 <Private Use>
<UE841> /x83/x36/xcc/x38 <Private Use>
<UE842> /x83/x36/xcc/x39 <Private Use>
-% This 1 PUA mapping uses the equivalent <U9FB9>.
-% <UE843> /xfe/x7e <Private Use>
+<UE843> /x82/x35/x91/x32 <Private Use>
<UE844> /x83/x36/xcd/x30 <Private Use>
<UE845> /x83/x36/xcd/x31 <Private Use>
<UE846> /x83/x36/xcd/x32 <Private Use>
@@ -57456,9 +57433,8 @@ CHARMAP
<UE851> /x83/x36/xce/x33 <Private Use>
<UE852> /x83/x36/xce/x34 <Private Use>
<UE853> /x83/x36/xce/x35 <Private Use>
-% These 2 PUA mappings use the equivalents <U9FBA> and <U241FE>.
-% <UE854> /xfe/x90 <Private Use>
-% <UE855> /xfe/x91 <Private Use>
+<UE854> /x82/x35/x91/x33 <Private Use>
+<UE855> /xfe/x91 <Private Use>
<UE856> /x83/x36/xce/x36 <Private Use>
<UE857> /x83/x36/xce/x37 <Private Use>
<UE858> /x83/x36/xce/x38 <Private Use>
@@ -57473,8 +57449,7 @@ CHARMAP
<UE861> /x83/x36/xcf/x37 <Private Use>
<UE862> /x83/x36/xcf/x38 <Private Use>
<UE863> /x83/x36/xcf/x39 <Private Use>
-% This 1 PUA mapping uses the equivalent <U9FBB>.
-% <UE864> /xfe/xa0 <Private Use>
+<UE864> /x82/x35/x91/x34 <Private Use>
<UE865> /x83/x36/xd0/x30 <Private Use>
<UE866> /x83/x36/xd0/x31 <Private Use>
<UE867> /x83/x36/xd0/x32 <Private Use>
@@ -70447,19 +70422,14 @@ CHARMAP
<U00020068>..<U00020071> /x95/x32/x8d/x30 <CJK>
<U00020072>..<U0002007B> /x95/x32/x8e/x30 <CJK>
<U0002007C>..<U00020085> /x95/x32/x8f/x30 <CJK>
-<U00020086> /x95/x32/x90/x30 <CJK>
-<U00020087> /xfe/x51 <CJK>
-<U00020088> /x95/x32/x90/x32 <CJK>
-<U00020089> /xfe/x52 <CJK>
-<U0002008A>..<U0002008F> /x95/x32/x90/x34 <CJK>
+<U00020086>..<U0002008F> /x95/x32/x90/x30 <CJK>
<U00020090>..<U00020099> /x95/x32/x91/x30 <CJK>
<U0002009A>..<U000200A3> /x95/x32/x92/x30 <CJK>
<U000200A4>..<U000200AD> /x95/x32/x93/x30 <CJK>
<U000200AE>..<U000200B7> /x95/x32/x94/x30 <CJK>
<U000200B8>..<U000200C1> /x95/x32/x95/x30 <CJK>
<U000200C2>..<U000200CB> /x95/x32/x96/x30 <CJK>
-<U000200CC> /xfe/x53 <CJK>
-<U000200CD>..<U000200D5> /x95/x32/x97/x31 <CJK>
+<U000200CC>..<U000200D5> /x95/x32/x97/x30 <CJK>
<U000200D6>..<U000200DF> /x95/x32/x98/x30 <CJK>
<U000200E0>..<U000200E9> /x95/x32/x99/x30 <CJK>
<U000200EA>..<U000200F3> /x95/x32/x9a/x30 <CJK>
@@ -70998,8 +70968,7 @@ CHARMAP
<U000215BC>..<U000215C5> /x95/x36/xb7/x30 <CJK>
<U000215C6>..<U000215CF> /x95/x36/xb8/x30 <CJK>
<U000215D0>..<U000215D6> /x95/x36/xb9/x30 <CJK>
-<U000215D7> /xfe/x6c <CJK>
-<U000215D8>..<U000215D9> /x95/x36/xb9/x38 <CJK>
+<U000215D7>..<U000215D9> /x95/x36/xb9/x37 <CJK>
<U000215DA>..<U000215E3> /x95/x36/xba/x30 <CJK>
<U000215E4>..<U000215ED> /x95/x36/xbb/x30 <CJK>
<U000215EE>..<U000215F7> /x95/x36/xbc/x30 <CJK>
@@ -71505,8 +71474,7 @@ CHARMAP
<U00022976>..<U0002297F> /x96/x30/xb8/x30 <CJK>
<U00022980>..<U00022989> /x96/x30/xb9/x30 <CJK>
<U0002298A>..<U0002298E> /x96/x30/xba/x30 <CJK>
-<U0002298F> /xfe/x76 <CJK>
-<U00022990>..<U00022993> /x96/x30/xba/x36 <CJK>
+<U0002298F>..<U00022993> /x96/x30/xba/x35 <CJK>
<U00022994>..<U0002299D> /x96/x30/xbb/x30 <CJK>
<U0002299E>..<U000229A7> /x96/x30/xbc/x30 <CJK>
<U000229A8>..<U000229B1> /x96/x30/xbd/x30 <CJK>
@@ -72132,8 +72100,7 @@ CHARMAP
<U000241E0>..<U000241E9> /x96/x35/xb3/x30 <CJK>
<U000241EA>..<U000241F3> /x96/x35/xb4/x30 <CJK>
<U000241F4>..<U000241FD> /x96/x35/xb5/x30 <CJK>
-<U000241FE> /xfe/x91 <CJK>
-<U000241FF>..<U00024207> /x96/x35/xb6/x31 <CJK>
+<U000241FE>..<U00024207> /x96/x35/xb6/x30 <CJK>
<U00024208>..<U00024211> /x96/x35/xb7/x30 <CJK>
<U00024212>..<U0002421B> /x96/x35/xb8/x30 <CJK>
<U0002421C>..<U00024225> /x96/x35/xb9/x30 <CJK>

21
glibc-nscd-sysconfig.patch Executable file
View file

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

19
glibc-python3.patch Normal file → Executable file
View file

@ -8,24 +8,33 @@ python3 during a transitional phase.
Author: Carlos O'Donell <carlos@redhat.com>
diff --git a/benchtests/scripts/compare_bench.py b/benchtests/scripts/compare_bench.py
index 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.
#

49
glibc-rh1361965.patch Executable file
View file

@ -0,0 +1,49 @@
Backport of this Fedora Rawhide commit but split out into a distinct
patch.
commit 72195d44855ab96875f117acb75c37f98dcb26a9
Author: Carlos O'Donell <carlos@redhat.com>
Date: Thu Jun 6 23:58:21 2019 -0400
locale: Fix C.UTF-8 ranges.
The ellipsis range support only allows <Uxxxx> or <Uxxxxxxxx> 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
<U0000>
..
<UFFFF>
-<U10000>
+<U00010000>
..
-<U1FFFF>
-<U20000>
+<U0001FFFF>
+<U00020000>
..
-<U2FFFF>
-<UE0000>
+<U0002FFFF>
+<U000E0000>
..
-<UEFFFF>
-<UF0000>
+<U000EFFFF>
+<U000F0000>
..
-<UFFFFF>
-<U100000>
+<U000FFFFF>
+<U00100000>
..
-<U10FFFF>
+<U0010FFFF>
UNDEFINED
order_end
END LC_COLLATE

185
glibc-rh1410154-1.patch Executable file
View file

@ -0,0 +1,185 @@
commit 96cd0558bcd69481ccc42e1b392f0c0b36fce2b0
Author: Florian Weimer <fweimer@redhat.com>
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 <stdio.h>
#include <support/capture_subprocess.h>
#include <support/check.h>
+#include <sys/wait.h>
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);

42
glibc-rh1410154-10.patch Executable file
View file

@ -0,0 +1,42 @@
commit e37c2cf299b61ce18f62852f6c5624c27829b610
Author: Florian Weimer <fweimer@redhat.com>
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);

27
glibc-rh1410154-11.patch Executable file
View file

@ -0,0 +1,27 @@
commit 61a7c9df71ee4e6f94b56c20f0d37c6e17d5f284
Author: Florian Weimer <fweimer@redhat.com>
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

1229
glibc-rh1410154-12.patch Executable file

File diff suppressed because it is too large Load diff

328
glibc-rh1410154-13.patch Executable file
View file

@ -0,0 +1,328 @@
commit f8ed116aa574435c6e28260f21963233682d3b57
Author: Florian Weimer <fweimer@redhat.com>
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 <adhemerval.zanella@linaro.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
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 <link_map.h>

134
glibc-rh1410154-14.patch Executable file
View file

@ -0,0 +1,134 @@
commit f7649d5780aa4682393b9daedd653e4d9c12784c
Author: Florian Weimer <fweimer@redhat.com>
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 <adhemerval.zanella@linaro.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
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 <atomic.h>
#include <libc-internal.h>
#include <array_length.h>
-#include <internal-signals.h>
#include <dl-dst.h>
#include <dl-prop.h>
@@ -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);

27
glibc-rh1410154-15.patch Executable file
View file

@ -0,0 +1,27 @@
commit 5177d85b0c050a2333a0c4165c938dd422013d05
Author: H.J. Lu <hjl.tools@gmail.com>
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 <fweimer@redhat.com>
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);
}
}

143
glibc-rh1410154-16.patch Executable file
View file

@ -0,0 +1,143 @@
commit a332bd1518af518c984fad73eba6f46dc5b2b2d4
Author: Florian Weimer <fweimer@redhat.com>
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 <siddhesh@sourceware.org>
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <gnu/lib-names.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+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 <support/test-driver.c>
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
+ <https://www.gnu.org/licenses/>. */

33
glibc-rh1410154-2.patch Executable file
View file

@ -0,0 +1,33 @@
commit ca136bb0a36d0a7056c926bfe5126873566efe40
Author: Florian Weimer <fweimer@redhat.com>
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 <carlos@redhat.com>
Reviewed-by: Gabriel F. T. Gomes <gabrielftg@linux.ibm.com>
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))

54
glibc-rh1410154-3.patch Executable file
View file

@ -0,0 +1,54 @@
commit 2a764c6ee848dfe92cb2921ed3b14085f15d9e79
Author: Florian Weimer <fweimer@redhat.com>
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)

42
glibc-rh1410154-4.patch Executable file
View file

@ -0,0 +1,42 @@
commit fcb04b9aed26a737159ef7be9c5a6ad0994437dc
Author: Florian Weimer <fweimer@redhat.com>
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. */

343
glibc-rh1410154-5.patch Executable file
View file

@ -0,0 +1,343 @@
commit 79e0cd7b3c997e211fad44a81fd839dc5b2546e8
Author: Florian Weimer <fweimer@redhat.com>
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
+ <https://www.gnu.org/licenses/>. */
+
+/* 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <string.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+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 <support/test-driver.c>
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
+ <https://www.gnu.org/licenses/>. */
+
+/* An undefined function. Calling it will cause a lazy binding
+ failure. */
+void undefined_function (void);
+
+static void __attribute__ ((constructor))
+init (void)
+{
+ undefined_function ();
+}

308
glibc-rh1410154-6.patch Executable file
View file

@ -0,0 +1,308 @@
commit 440b7f8653e4ed8f6e1425145208050b795e9a6c
Author: Florian Weimer <fweimer@redhat.com>
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
{

490
glibc-rh1410154-7.patch Executable file
View file

@ -0,0 +1,490 @@
commit a509eb117fac1d764b15eba64993f4bdb63d7f3c
Author: Florian Weimer <fweimer@redhat.com>
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 <stap-probe.h>
#include <atomic.h>
#include <libc-internal.h>
+#include <array_length.h>
#include <dl-dst.h>
#include <dl-prop.h>
@@ -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. */

619
glibc-rh1410154-8.patch Executable file
View file

@ -0,0 +1,619 @@
commit f63b73814f74032c0e5d0a83300e3d864ef905e5
Author: Florian Weimer <fweimer@redhat.com>
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
+ <https://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <gnu/lib-names.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+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 <support/test-driver.c>
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
+ <https://www.gnu.org/licenses/>. */
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
+ <https://www.gnu.org/licenses/>. */
+
+/* Note: Due to the missing second module, this object cannot be
+ loaded at run time. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+/* 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <stdio.h>
+
+/* 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 <link_map.h>
/* Collected information about own RPATH directories. */

104
glibc-rh1410154-9.patch Executable file
View file

@ -0,0 +1,104 @@
commit a2e8aa0d9ea648068d8be52dd7b15f1b6a008e23
Author: Florian Weimer <fweimer@redhat.com>
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 <atomic.h>
#include <libc-internal.h>
#include <array_length.h>
+#include <internal-signals.h>
#include <dl-dst.h>
#include <dl-prop.h>
@@ -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);

22
glibc-rh1577365.patch Executable file
View file

@ -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

24
glibc-rh1577438.patch Executable file
View file

@ -0,0 +1,24 @@
Patch by Hanataka Shinya <hanataka.shinya@gmail.com> from
<https://sourceware.org/bugzilla/show_bug.cgi?id=24405>. Confirmed by TAMUKI
Shoichi's patch in
<https://sourceware.org/ml/libc-alpha/2019-04/msg00005.html>.
The official announcement by the Japanese Prime Minister in
<https://www.kantei.go.jp/jp/tyoukanpress/201904/1_a.html> 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 "<U5348><U524D>";"<U5348><U5F8C>"
t_fmt_ampm "%p%I<U6642>%M<U5206>%S<U79D2>"
-era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/
+era "+:2:2020//01//01:+*:<U4EE4><U548C>:%EC%Ey<U5E74>";/
+ "+:1:2019//05//01:2019//12//31:<U4EE4><U548C>:%EC<U5143><U5E74>";/
+ "+:2:1990//01//01:2019//04//30:<U5E73><U6210>:%EC%Ey<U5E74>";/
"+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/
"+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/
"+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/

254
glibc-rh1614253.patch Executable file
View file

@ -0,0 +1,254 @@
commit 4b25485f03158959cff45379eecc1d73c7dcdd11
Author: Florian Weimer <fweimer@redhat.com>
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 <shlib-compat.h>
# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
-# include <olddirent.h>
+# include <olddirent.h>
+# include <unistd.h>
-/* 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <shlib-compat.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <support/check.h>
+
+/* Copied from <olddirent.h>. */
+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 <support/test-driver.c>

154
glibc-rh1614979.patch Executable file
View file

@ -0,0 +1,154 @@
commit d524fa6c35e675eedbd8fe6cdf4db0b49c658026
Author: H.J. Lu <hjl.tools@gmail.com>
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;

28
glibc-rh1615781.patch Executable file
View file

@ -0,0 +1,28 @@
commit d05b05d1570ba3ae354a2f5a3cfeefb373b09979
Author: Florian Weimer <fweimer@redhat.com>
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);

35
glibc-rh1615784.patch Executable file
View file

@ -0,0 +1,35 @@
commit bfcfa22589f2b4277a65e60c6b736b6bbfbd87d0
Author: Florian Weimer <fweimer@redhat.com>
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);

306
glibc-rh1615790.patch Executable file
View file

@ -0,0 +1,306 @@
commit 2f498f3d140ab5152bd784df2be7af7d9c5e63ed
Author: Florian Weimer <fweimer@redhat.com>
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
+ <http://www.gnu.org/licenses/>. */
+
+#include <aliases.h>
+#include <array_length.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <gnu/lib-names.h>
+#include <nss.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/test-driver.h>
+#include <support/xstdio.h>
+#include <support/xunistd.h>
+
+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 <support/test-driver.c>

27
glibc-rh1622675.patch Executable file
View file

@ -0,0 +1,27 @@
commit aa8a3e4cdef20c50cb20f008864fff05cbfbdf29
Author: Martin Kuchta <martin.kuchta@netapp.com>
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);

41
glibc-rh1622678-1.patch Executable file
View file

@ -0,0 +1,41 @@
commit 58559f14437d2aa71753a29fed435efa06aa4576
Author: Paul Eggert <eggert@cs.ucla.edu>
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 <bugs@feusi.co> 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)

226
glibc-rh1622678-2.patch Executable file
View file

@ -0,0 +1,226 @@
commit 0b79004569e5ce1669136b8c41564c3809730f15
Author: Florian Weimer <fweimer@redhat.com>
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
+ <http://www.gnu.org/licenses/>. */
+
+/* This test constructs various patterns in an attempt to trigger
+ over-reading the regular expression compiler, such as bug
+ 23578. */
+
+#include <array_length.h>
+#include <errno.h>
+#include <locale.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/next_to_fault.h>
+#include <support/support.h>
+#include <support/test-driver.h>
+#include <wchar.h>
+
+/* 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 (&reg, 0, sizeof (reg));
+ const char *msg = re_compile_pattern
+ (ntf_start, length, &reg);
+ 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 (&reg);
+ }
+ }
+ }
+ }
+ }
+
+ support_next_to_fault_free (&ntf);
+
+ return 0;
+}
+
+#include <support/test-driver.c>

34
glibc-rh1623536-2.patch Executable file
View file

@ -0,0 +1,34 @@
commit 3a67c72c1512f778304a5644dea2fcf5bdece274
Author: Andreas Schwab <schwab@suse.de>
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)
{

100
glibc-rh1623536.patch Executable file
View file

@ -0,0 +1,100 @@
commit a55e109709af55e6ed67d3f9536cac5d929c982e
Author: Carlos O'Donell <carlos@redhat.com>
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 <carlos@redhat.com>
(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)
{

61
glibc-rh1623537.patch Executable file
View file

@ -0,0 +1,61 @@
commit b297581acb66f80b513996c1580158b0fb12d469
Author: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
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 <tuliom@linux.ibm.com>
(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),
};

29
glibc-rh1631293-1.patch Executable file
View file

@ -0,0 +1,29 @@
commit e7d22db29cfdd2f1fb97a70a76fa53d151569945
Author: Mingli Yu <Mingli.Yu@windriver.com>
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;

146
glibc-rh1631293-2.patch Executable file
View file

@ -0,0 +1,146 @@
commit 307d04334d516bb180f484a2b283f97310bfee66
Author: Florian Weimer <fweimer@redhat.com>
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
+ <http://www.gnu.org/licenses/>. */
+
+#include <gnu/lib-names.h>
+#include <nss.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/namespace.h>
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/xdlfcn.h>
+#include <support/xstdio.h>
+#include <support/xunistd.h>
+#include <unistd.h>
+
+/* 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 <support/test-driver.c>

108
glibc-rh1631722.patch Executable file
View file

@ -0,0 +1,108 @@
commit 0ef2f4400c06927af34c515555f68840a70ba409
Author: Wilco Dijkstra <wdijkstr@arm.com>
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);

82
glibc-rh1631730.patch Executable file
View file

@ -0,0 +1,82 @@
commit 2339d6a55eb7a7e040ae888e906adc49eeb59eab
Author: H.J. Lu <hjl.tools@gmail.com>
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 <compare>, 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 <compare>) 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 <sysdep.h>
(_start): Use ENTRY/END to insert ENDBR32 at entry when CET is
enabled. Add cfi_undefined (eip).
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
(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 <sysdep.h>
+
+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. */

483
glibc-rh1635779.patch Executable file
View file

@ -0,0 +1,483 @@
commit e5d262effe3a87164308a3f37e61b32d0348692a
Author: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
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 <tuliom@linux.ibm.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
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
+ <http://www.gnu.org/licenses/>. */
+
+#include <elf.h>
+#include <link.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+/* 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
+ <http://www.gnu.org/licenses/>. */
+
+/* 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
+ <http://www.gnu.org/licenses/>. */
+
+/* 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 <support/xthread.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <sys/sysinfo.h>
+
+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
+ <http://www.gnu.org/licenses/>. */
+
+/* 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 ();

35
glibc-rh1638520.patch Executable file
View file

@ -0,0 +1,35 @@
commit ed643089cd3251038863d32e67ec47b94cd557f3
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
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 <carlos@redhat.com>
* 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 <support/test-driver.c>

2823
glibc-rh1638523-1.patch Executable file

File diff suppressed because it is too large Load diff

80
glibc-rh1638523-2.patch Executable file
View file

@ -0,0 +1,80 @@
commit 6c3a8a9d868a8deddf0d6dcc785b6d120de90523
Author: Paul Pluzhnikov <ppluzhnikov@kazbek.mtv.corp.google.com>
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 <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/temp_file.h>
#include <support/test-driver.h>
#include <libc-diag.h>
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;
}

55
glibc-rh1638523-3.patch Executable file
View file

@ -0,0 +1,55 @@
commit 3bad2358d67d371497079bba4f8eca9c0096f4e2
Author: Stefan Liebler <stli@linux.ibm.com>
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 <carlos@redhat.com>
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));

65
glibc-rh1638523-4.patch Executable file
View file

@ -0,0 +1,65 @@
commit f5e7e95921847bd83186bfe621fc2b48c4de5477
Author: Florian Weimer <fweimer@redhat.com>
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 <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <support/blob_repeat.h>
#include <support/check.h>
#include <support/support.h>
#include <support/temp_file.h>
@@ -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;
}

51
glibc-rh1638523-5.patch Executable file
View file

@ -0,0 +1,51 @@
commit 07da99aad93c9364acb7efdab47c27ba698f6313
Author: Florian Weimer <fweimer@redhat.com>
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <support/blob_repeat.h>
+#include <support/test-driver.h>
#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;
}

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