Compare commits
No commits in common. "a23.1" and "a8.4-temp-2.28-164.el8_5.3" have entirely different histories.
a23.1
...
a8.4-temp-
642 changed files with 129161 additions and 15978 deletions
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
6058
ChangeLog.old
Executable file
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
@ -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
|
||||
|
11
README.md
11
README.md
|
@ -1,11 +0,0 @@
|
|||
Anolis OS
|
||||
=======================================
|
||||
# 代码仓库说明
|
||||
## 分支说明
|
||||
>进行代码开发工作时,请注意选择当前版本对应的分支
|
||||
* aX分支为对应大版本的主分支,如a8分支对应当前最新版本
|
||||
* aX.Y分支为对应小版本的维护分支,如a8.2分支对应8.2版本
|
||||
## 开发流程
|
||||
1. 首先fork目标分支到自己的namespace
|
||||
2. 在自己的fork分支上做出修改
|
||||
3. 向对应的仓库中提交merge request,源分支为fork分支
|
|
@ -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
494
SUPPORTED
Executable 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
0
bench.mk
Normal file → Executable file
862
build-locale-archive.c
Executable file
862
build-locale-archive.c
Executable 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);
|
||||
}
|
|
@ -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
25
glibc-asflags.patch
Executable 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
286
glibc-c-utf8-locale.patch
Executable 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
43
glibc-cs-path.patch
Normal file → Executable 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"
|
||||
|
|
|
@ -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>
|
91
glibc-fedora-__libc_multiple_libcs.patch
Executable file
91
glibc-fedora-__libc_multiple_libcs.patch
Executable 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)
|
||||
{
|
61
glibc-fedora-linux-tcsetattr.patch
Executable file
61
glibc-fedora-linux-tcsetattr.patch
Executable 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)
|
49
glibc-fedora-localedata-rh61908.patch
Executable file
49
glibc-fedora-localedata-rh61908.patch
Executable 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 \
|
6
glibc-no-archive-for-localedef.patch → glibc-fedora-localedef.patch
Normal file → Executable file
6
glibc-no-archive-for-localedef.patch → glibc-fedora-localedef.patch
Normal file → Executable 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
46
glibc-fedora-locarchive.patch
Executable 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)
|
||||
{
|
0
glibc-place-info-into-Libraries-category.patch → glibc-fedora-manual-dircategory.patch
Normal file → Executable file
0
glibc-place-info-into-Libraries-category.patch → glibc-fedora-manual-dircategory.patch
Normal file → Executable file
31
glibc-fedora-nis-rh188246.patch
Executable file
31
glibc-fedora-nis-rh188246.patch
Executable 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
20
glibc-fedora-nscd.patch
Executable 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
|
38
glibc-fedora-streams-rh436349.patch
Executable file
38
glibc-fedora-streams-rh436349.patch
Executable 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
|
|
@ -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
21
glibc-nscd-sysconfig.patch
Executable 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
19
glibc-python3.patch
Normal file → Executable 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.
|
||||
#
|
||||
|
|
0
glibc-nscd-add-syslog-target-dependency.patch → glibc-rh1070416.patch
Normal file → Executable file
0
glibc-nscd-add-syslog-target-dependency.patch → glibc-rh1070416.patch
Normal file → Executable file
49
glibc-rh1361965.patch
Executable file
49
glibc-rh1361965.patch
Executable 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
185
glibc-rh1410154-1.patch
Executable 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
42
glibc-rh1410154-10.patch
Executable 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
27
glibc-rh1410154-11.patch
Executable 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
1229
glibc-rh1410154-12.patch
Executable file
File diff suppressed because it is too large
Load diff
328
glibc-rh1410154-13.patch
Executable file
328
glibc-rh1410154-13.patch
Executable 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
134
glibc-rh1410154-14.patch
Executable 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
27
glibc-rh1410154-15.patch
Executable 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
143
glibc-rh1410154-16.patch
Executable 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
33
glibc-rh1410154-2.patch
Executable 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
54
glibc-rh1410154-3.patch
Executable 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
42
glibc-rh1410154-4.patch
Executable 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
343
glibc-rh1410154-5.patch
Executable 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
308
glibc-rh1410154-6.patch
Executable 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
490
glibc-rh1410154-7.patch
Executable 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
619
glibc-rh1410154-8.patch
Executable 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
104
glibc-rh1410154-9.patch
Executable 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
22
glibc-rh1577365.patch
Executable 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
24
glibc-rh1577438.patch
Executable 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
254
glibc-rh1614253.patch
Executable 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
154
glibc-rh1614979.patch
Executable 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
28
glibc-rh1615781.patch
Executable 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
35
glibc-rh1615784.patch
Executable 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
306
glibc-rh1615790.patch
Executable 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
27
glibc-rh1622675.patch
Executable 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
41
glibc-rh1622678-1.patch
Executable 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
226
glibc-rh1622678-2.patch
Executable 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 (®, 0, sizeof (reg));
|
||||
+ const char *msg = re_compile_pattern
|
||||
+ (ntf_start, length, ®);
|
||||
+ if (msg != NULL)
|
||||
+ {
|
||||
+ if (test_verbose > 0)
|
||||
+ {
|
||||
+ char *quoted = support_quote_blob
|
||||
+ (buffer, length);
|
||||
+ printf ("info: compilation failed for pattern"
|
||||
+ " \"%s\", syntax 0x%lx: %s\n",
|
||||
+ quoted, re_syntax_options, msg);
|
||||
+ free (quoted);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ regfree (®);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ support_next_to_fault_free (&ntf);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
34
glibc-rh1623536-2.patch
Executable file
34
glibc-rh1623536-2.patch
Executable 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
100
glibc-rh1623536.patch
Executable 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
61
glibc-rh1623537.patch
Executable 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
29
glibc-rh1631293-1.patch
Executable 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
146
glibc-rh1631293-2.patch
Executable 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
108
glibc-rh1631722.patch
Executable 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
82
glibc-rh1631730.patch
Executable 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
483
glibc-rh1635779.patch
Executable 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
35
glibc-rh1638520.patch
Executable 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
2823
glibc-rh1638523-1.patch
Executable file
File diff suppressed because it is too large
Load diff
80
glibc-rh1638523-2.patch
Executable file
80
glibc-rh1638523-2.patch
Executable 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
55
glibc-rh1638523-3.patch
Executable 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
65
glibc-rh1638523-4.patch
Executable 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
51
glibc-rh1638523-5.patch
Executable 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
Loading…
Add table
Add a link
Reference in a new issue