Compare commits

...

No commits in common. "glibc-2.28-236.0.1.an8.12" and "a23.1" have entirely different histories.

921 changed files with 15372 additions and 213071 deletions

View file

@ -1,36 +1,40 @@
commit bd77dd7e73e3530203be1c52c8a29d08270cb25d
Author: Florian Weimer <fweimer@redhat.com>
Date: Wed Sep 13 14:10:56 2023 +0200
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
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.
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.
Fixes commit f282cdbe7f436c75864e5640a4 ("resolv: Implement no-aaaa
stub resolver option") and bug 30842.
Conflicts:
resolv/nss_dns/dns-host.c
(missing dns_packet_buffer cleanup downstream)
(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 ab8ad49b5318ad41..4f4eaf060443c128 100644
index f8a92c6cff..28cedf49ee 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -58,6 +58,7 @@ tests += \
tst-resolv-edns \
@@ -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 \
@@ -202,6 +203,7 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \
$(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \
@@ -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)
@ -38,21 +42,21 @@ index ab8ad49b5318ad41..4f4eaf060443c128 100644
$(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 ff0a0b6f7f1f4703..f678c7d7caa3a026 100644
index 9fa81f23c8..227734da5c 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -392,7 +392,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
else
@@ -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,
- host_buffer.buf->buf, 2048, NULL,
+ host_buffer.buf->buf, 2048, &host_buffer.ptr,
NULL, NULL, NULL, NULL);
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 (host_buffer.buf, n,
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 0000000000000000..9f5aebd99f2d74a2
index 0000000000..9f5aebd99f
--- /dev/null
+++ b/resolv/tst-resolv-noaaaa-vc.c
@@ -0,0 +1,129 @@
@ -185,3 +189,6 @@ index 0000000000000000..9f5aebd99f2d74a2
+}
+
+#include <support/test-driver.c>
--
2.39.3

View file

@ -1,4 +1,8 @@
Avoid UAF in getcanonname (CVE-2023-4806)
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
@ -17,60 +21,39 @@ 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. This is a minimal
RHEL-8-specific fix. Test case differences from upstream:
resolves BZ #30843, which is assigned CVE-2023-4806.
- The test module needs to explicitly link against libnss_files on
RHEL-8; upstream libnss_files is built into libc.so.
- Test module code was adapted to not use the upstream NSS module
convenience macros.
This change is adapted from the following commit from upstream:
commit 973fe93a5675c42798b2161c6f29c01b0e243994
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date: Fri Sep 15 13:51:12 2023 -0400
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>
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 cfb255c6e7a3a4de..5829a2539306ddb5 100644
index a978e3927a..f0af87e6f1 100644
--- a/nss/Makefile
+++ b/nss/Makefile
@@ -66,7 +66,8 @@ xtests = bug-erange
tests-container = \
tst-nss-db-endpwent \
tst-nss-db-endgrent \
- tst-nss-gai-actions
+ tst-nss-gai-actions \
+ tst-nss-gai-hv2-canonname
@@ -81,6 +81,7 @@ tests-container := \
tst-nss-test3 \
tst-reload1 \
tst-reload2 \
+ tst-nss-gai-hv2-canonname \
# tests-container
# Tests which need libdl
ifeq (yes,$(build-shared))
@@ -132,7 +133,8 @@ routines += $(libnss_files-routines)
static-only-routines += $(libnss_files-routines)
@@ -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
@ -79,7 +62,7 @@ index cfb255c6e7a3a4de..5829a2539306ddb5 100644
include ../Rules
@@ -169,12 +171,17 @@ rtld-tests-LDFLAGS += -Wl,--dynamic-list=nss_test.ver
@@ -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
@ -91,34 +74,38 @@ index cfb255c6e7a3a4de..5829a2539306ddb5 100644
$(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) \
+ $(objpfx)/libnss_files.so
+ $(objpfx)nss_test_gai_hv2_canonname.os $(link-libc-deps)
+ $(build-module)
$(objpfx)nss_test2.os : nss_test1.c
ifdef libnss_test1.so-version
$(objpfx)/libnss_test1.so$(libnss_test1.so-version): $(objpfx)/libnss_test1.so
@@ -187,10 +194,14 @@ endif
# 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)) : \
$(objpfx)/libnss_test1.so$(libnss_test1.so-version) \
$(objpfx)/libnss_test2.so$(libnss_test2.so-version) \
$(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 0000000000000000..4195d7d24fdd5f6d
index 0000000000..4439c83c9f
--- /dev/null
+++ b/nss/nss_test_gai_hv2_canonname.c
@@ -0,0 +1,64 @@
@@ -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.
@ -137,7 +124,6 @@ index 0000000000000000..4195d7d24fdd5f6d
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <netdb.h>
+#include <nss.h>
+#include <stdlib.h>
+#include <string.h>
@ -145,20 +131,13 @@ index 0000000000000000..4195d7d24fdd5f6d
+
+/* 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 *, int, struct hostent
+ *, char *, size_t, int *, int *);
+
+enum nss_status
+_nss_test_gai_hv2_canonname_getcanonname_r (const char *, char *, size_t, char
+ **, 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,
@ -185,7 +164,7 @@ index 0000000000000000..4195d7d24fdd5f6d
+}
diff --git a/nss/tst-nss-gai-hv2-canonname.c b/nss/tst-nss-gai-hv2-canonname.c
new file mode 100644
index 0000000000000000..d5f10c07d6a90773
index 0000000000..d5f10c07d6
--- /dev/null
+++ b/nss/tst-nss-gai-hv2-canonname.c
@@ -0,0 +1,63 @@
@ -254,61 +233,86 @@ index 0000000000000000..d5f10c07d6a90773
+#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 0000000000000000..14f2a9cb0867dff9
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 0000000000000000..e69de29bb2d1d643
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 0000000000000000..31848b4a28524af6
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 4fa963644af8b7d5..46046504a6858f2e 100644
index 5cda9bb072..7a43a3bf4c 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -233,7 +233,6 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
@@ -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;
*result = array;
@@ -287,6 +286,18 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
} \
*pat = addrmem; \
\
+ /* Store h_name so that it survives accidental deallocation when \
+ gethosts is called again and tmpbuf gets reallocated. */ \
+ if (h_name == NULL && th.h_name != NULL) \
+ { \
+ h_name = __strdup (th.h_name); \
+ if (h_name == NULL) \
+ { \
+ __resolv_context_put (res_ctx); \
+ result = -EAI_SYSTEM; \
+ goto free_and_return; \
+ } \
+ } \
if (localcanon != NULL && canon == NULL) \
{ \
canonbuf = __strdup (localcanon); \
@@ -323,15 +334,15 @@ typedef enum nss_status (*nss_getcanonname_r)
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 (service_user *nip, struct gaih_addrtuple *at, const char *name)
+getcanonname (service_user *nip, const char *hname, const char *name)
-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");
nss_getcanonname_r *cfct = __nss_lookup_function (nip, "getcanonname_r");
char *s = (char *) name;
if (cfct != NULL)
{
@ -320,28 +324,15 @@ index 4fa963644af8b7d5..46046504a6858f2e 100644
/* If the canonical name cannot be determined, use the passed
string. */
s = (char *) name;
@@ -349,6 +360,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
struct gaih_addrtuple *at = NULL;
bool got_ipv6 = false;
const char *canon = NULL;
+ char *h_name = NULL;
const char *orig_name = name;
/* Reserve stack memory for the scratch buffer in the getaddrinfo
@@ -919,7 +931,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
if ((req->ai_flags & AI_CANONNAME) != 0
&& canon == NULL)
{
- canonbuf = getcanonname (nip, at, name);
+ canonbuf = getcanonname (nip, h_name, name);
if (canonbuf == NULL)
{
__resolv_context_enable_inet6
@@ -1169,6 +1181,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
free ((char *) name);
free (addrmem);
free (canonbuf);
+ free (h_name);
return result;
}
@@ -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

98
0085-CVE-2023-5156.patch Normal file
View file

@ -0,0 +1,98 @@
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

181
0087-CVE-2023-6246.patch Normal file
View file

@ -0,0 +1,181 @@
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

106
0088-CVE-2023-6779.patch Normal file
View file

@ -0,0 +1,106 @@
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

41
0089-CVE-2023-6780.patch Normal file
View file

@ -0,0 +1,41 @@
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

213
0090-CVE-2024-2961.patch Normal file
View file

@ -0,0 +1,213 @@
From f9dc609e06b1136bb0408be9605ce7973a767ada Mon Sep 17 00:00:00 2001
From: Charles Fol <folcharles@gmail.com>
Date: Thu, 28 Mar 2024 12:25:38 -0300
Subject: [PATCH] iconv: ISO-2022-CN-EXT: fix out-of-bound writes when writing
escape sequence (CVE-2024-2961)
ISO-2022-CN-EXT uses escape sequences to indicate character set changes
(as specified by RFC 1922). While the SOdesignation has the expected
bounds checks, neither SS2designation nor SS3designation have its;
allowing a write overflow of 1, 2, or 3 bytes with fixed values:
'$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'.
Checked on aarch64-linux-gnu.
Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
---
iconvdata/Makefile | 5 +-
iconvdata/iso-2022-cn-ext.c | 12 +++
iconvdata/tst-iconv-iso-2022-cn-ext.c | 128 ++++++++++++++++++++++++++
3 files changed, 144 insertions(+), 1 deletion(-)
create mode 100644 iconvdata/tst-iconv-iso-2022-cn-ext.c
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
index ea019ce5c0..7196a8744b 100644
--- a/iconvdata/Makefile
+++ b/iconvdata/Makefile
@@ -75,7 +75,8 @@ ifeq (yes,$(build-shared))
tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \
- bug-iconv13 bug-iconv14 bug-iconv15
+ bug-iconv13 bug-iconv14 bug-iconv15 \
+ tst-iconv-iso-2022-cn-ext
ifeq ($(have-thread-library),yes)
tests += bug-iconv3
endif
@@ -330,6 +331,8 @@ $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \
$(addprefix $(objpfx),$(modules.so))
$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
$(addprefix $(objpfx),$(modules.so))
+$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \
+ $(addprefix $(objpfx),$(modules.so))
$(objpfx)iconv-test.out: run-iconv-test.sh \
$(addprefix $(objpfx), $(gconv-modules)) \
diff --git a/iconvdata/iso-2022-cn-ext.c b/iconvdata/iso-2022-cn-ext.c
index b34c8a36f4..cce29b1969 100644
--- a/iconvdata/iso-2022-cn-ext.c
+++ b/iconvdata/iso-2022-cn-ext.c
@@ -574,6 +574,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
{ \
const char *escseq; \
\
+ if (outptr + 4 > outend) \
+ { \
+ result = __GCONV_FULL_OUTPUT; \
+ break; \
+ } \
+ \
assert (used == CNS11643_2_set); /* XXX */ \
escseq = "*H"; \
*outptr++ = ESC; \
@@ -587,6 +593,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
{ \
const char *escseq; \
\
+ if (outptr + 4 > outend) \
+ { \
+ result = __GCONV_FULL_OUTPUT; \
+ break; \
+ } \
+ \
assert ((used >> 5) >= 3 && (used >> 5) <= 7); \
escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2; \
*outptr++ = ESC; \
diff --git a/iconvdata/tst-iconv-iso-2022-cn-ext.c b/iconvdata/tst-iconv-iso-2022-cn-ext.c
new file mode 100644
index 0000000000..96a8765fd5
--- /dev/null
+++ b/iconvdata/tst-iconv-iso-2022-cn-ext.c
@@ -0,0 +1,128 @@
+/* Verify ISO-2022-CN-EXT does not write out of the bounds.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <errno.h>
+#include <iconv.h>
+#include <sys/mman.h>
+
+#include <support/xunistd.h>
+#include <support/check.h>
+#include <support/support.h>
+
+/* The test sets up a two memory page buffer with the second page marked
+ PROT_NONE to trigger a fault if the conversion writes beyond the exact
+ expected amount. Then we carry out various conversions and precisely
+ place the start of the output buffer in order to trigger a SIGSEGV if the
+ process writes anywhere between 1 and page sized bytes more (only one
+ PROT_NONE page is setup as a canary) than expected. These tests exercise
+ all three of the cases in ISO-2022-CN-EXT where the converter must switch
+ character sets and may run out of buffer space while doing the
+ operation. */
+
+static int
+do_test (void)
+{
+ iconv_t cd = iconv_open ("ISO-2022-CN-EXT", "UTF-8");
+ TEST_VERIFY_EXIT (cd != (iconv_t) -1);
+
+ char *ntf;
+ size_t ntfsize;
+ char *outbufbase;
+ {
+ int pgz = getpagesize ();
+ TEST_VERIFY_EXIT (pgz > 0);
+ ntfsize = 2 * pgz;
+
+ ntf = xmmap (NULL, ntfsize, PROT_READ | PROT_WRITE, MAP_PRIVATE
+ | MAP_ANONYMOUS, -1);
+ xmprotect (ntf + pgz, pgz, PROT_NONE);
+
+ outbufbase = ntf + pgz;
+ }
+
+ /* Check if SOdesignation escape sequence does not trigger an OOB write. */
+ {
+ char inbuf[] = "\xe4\xba\xa4\xe6\x8d\xa2";
+
+ for (int i = 0; i < 9; i++)
+ {
+ char *inp = inbuf;
+ size_t inleft = sizeof (inbuf) - 1;
+
+ char *outp = outbufbase - i;
+ size_t outleft = i;
+
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+ == (size_t) -1);
+ TEST_COMPARE (errno, E2BIG);
+
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+ }
+ }
+
+ /* Same as before for SS2designation. */
+ {
+ char inbuf[] = "ã´½ \xe3\xb4\xbd";
+
+ for (int i = 0; i < 14; i++)
+ {
+ char *inp = inbuf;
+ size_t inleft = sizeof (inbuf) - 1;
+
+ char *outp = outbufbase - i;
+ size_t outleft = i;
+
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+ == (size_t) -1);
+ TEST_COMPARE (errno, E2BIG);
+
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+ }
+ }
+
+ /* Same as before for SS3designation. */
+ {
+ char inbuf[] = "劄 \xe5\x8a\x84";
+
+ for (int i = 0; i < 14; i++)
+ {
+ char *inp = inbuf;
+ size_t inleft = sizeof (inbuf) - 1;
+
+ char *outp = outbufbase - i;
+ size_t outleft = i;
+
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+ == (size_t) -1);
+ TEST_COMPARE (errno, E2BIG);
+
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+ }
+ }
+
+ TEST_VERIFY_EXIT (iconv_close (cd) != -1);
+
+ xmunmap (ntf, ntfsize);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
--
2.39.3

View file

@ -1,38 +1,18 @@
This patch was developed under embargo and cannot reference an upstream
commit. To find the associated commit please review the upstream git
log for CVE-2023-4911 to identify the relevant commits.
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
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date: Tue Sep 19 18:39:32 2023 -0400
tunables: Terminate if end of input is reached (CVE-2023-4911)
The string parsing routine may end up writing beyond bounds of tunestr
if the input tunable string is malformed, of the form name=name=val.
This gets processed twice, first as name=name=val and next as name=val,
resulting in tunestr being name=name=val:name=val, thus overflowing
tunestr.
Terminate the parsing loop at the first instance itself so that tunestr
does not overflow.
This also fixes up tst-env-setuid-tunables to actually handle failures
correct and add new tests to validate the fix for this CVE.
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Conflicts:
NEWS
(Dropped)
elf/tst-env-setuid-tunables.c
(Trivial conflict at HAVE_TUNABLES)
---
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 3c84809d44381241..2c878e08ea197b29 100644
index 62b7332d..0edfade8 100644
--- a/elf/dl-tunables.c
+++ b/elf/dl-tunables.c
@@ -193,11 +193,7 @@ parse_tunables (char *tunestr, char *valstring)
@@ -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')
@ -45,7 +25,7 @@ index 3c84809d44381241..2c878e08ea197b29 100644
/* We did not find a valid name-value pair before encountering the
colon. */
@@ -257,9 +253,16 @@ parse_tunables (char *tunestr, char *valstring)
@@ -244,9 +240,15 @@ parse_tunables (char *tunestr, char *valstring)
}
}
@ -54,7 +34,6 @@ index 3c84809d44381241..2c878e08ea197b29 100644
+ /* We reached the end while processing the tunable string. */
+ if (p[len] == '\0')
+ break;
+
+ p += len + 1;
}
+
@ -62,13 +41,13 @@ index 3c84809d44381241..2c878e08ea197b29 100644
+ if (__libc_enable_secure)
+ tunestr[off] = '\0';
}
#endif
/* 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 0b9b075c40598c6f..8b0861c4ad853040 100644
index 7dfb0e07..2364d162 100644
--- a/elf/tst-env-setuid-tunables.c
+++ b/elf/tst-env-setuid-tunables.c
@@ -52,6 +52,8 @@ const char *teststrings[] =
@@ -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",
@ -77,7 +56,7 @@ index 0b9b075c40598c6f..8b0861c4ad853040 100644
"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",
@@ -70,6 +72,8 @@ const char *resultstrings[] =
@@ -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",
@ -86,10 +65,10 @@ index 0b9b075c40598c6f..8b0861c4ad853040 100644
"",
"",
"",
@@ -84,11 +88,18 @@ test_child (int off)
@@ -81,11 +85,17 @@ test_child (int off)
{
const char *val = getenv ("GLIBC_TUNABLES");
#if HAVE_TUNABLES
+ printf (" [%d] GLIBC_TUNABLES is %s\n", off, val);
+ fflush (stdout);
if (val != NULL && strcmp (val, resultstrings[off]) == 0)
@ -98,27 +77,26 @@ index 0b9b075c40598c6f..8b0861c4ad853040 100644
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]);
+ off, val, resultstrings[off]);
+ else
+ printf (" [%d] GLIBC_TUNABLES environment variable absent\n", off);
+
+ fflush (stdout);
return 1;
#else
@@ -117,21 +128,26 @@ do_test (int argc, char **argv)
}
@@ -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. */
+ through. */
+ exit (42);
}
else
{
- int ret = 0;
-
/* Spawn tests. */
for (int i = 0; i < array_length (teststrings); i++)
{
@ -130,28 +108,32 @@ index 0b9b075c40598c6f..8b0861c4ad853040 100644
+ 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;
+ }
+ continue;
+ }
+
int status = support_capture_subprogram_self_sgid (buf);
@@ -139,9 +155,14 @@ do_test (int argc, char **argv)
/* 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 ();
+ }
+ {
+ printf (" [%d] child failed with status %d\n", i,
+ WEXITSTATUS (status));
+ support_record_failure ();
+ }
}
- return ret;
+ return 0;
}
}
--
2.41.0

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,40 @@
From 2c8dfc45a8009e5110a9d2148b62d802e989fde7 Mon Sep 17 00:00:00 2001
From: ticat_fp <fanpeng@loongson.cn>
Date: Thu, 29 Feb 2024 15:58:31 +0800
Subject: [PATCH] Decrease value of arch_minimum_kernel with LoongArch
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/unix/sysv/linux/loongarch/configure | 2 +-
sysdeps/unix/sysv/linux/loongarch/configure.ac | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/sysdeps/unix/sysv/linux/loongarch/configure b/sysdeps/unix/sysv/linux/loongarch/configure
index 0d1159e9..851b2285 100644
--- a/sysdeps/unix/sysv/linux/loongarch/configure
+++ b/sysdeps/unix/sysv/linux/loongarch/configure
@@ -1,7 +1,7 @@
# This file is generated from configure.ac by Autoconf. DO NOT EDIT!
# Local configure fragment for sysdeps/unix/sysv/linux/loongarch.
-arch_minimum_kernel=5.19.0
+arch_minimum_kernel=4.19.0
libc_cv_loongarch_int_abi=no
diff --git a/sysdeps/unix/sysv/linux/loongarch/configure.ac b/sysdeps/unix/sysv/linux/loongarch/configure.ac
index 04e9150a..00815c2f 100644
--- a/sysdeps/unix/sysv/linux/loongarch/configure.ac
+++ b/sysdeps/unix/sysv/linux/loongarch/configure.ac
@@ -2,7 +2,7 @@ sinclude(./aclocal.m4)dnl Autoconf lossage
GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
# Local configure fragment for sysdeps/unix/sysv/linux/loongarch.
-arch_minimum_kernel=5.19.0
+arch_minimum_kernel=4.19.0
libc_cv_loongarch_int_abi=no
AC_EGREP_CPP(4 8 8, [__SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_POINTER__
--
2.33.0

View file

@ -1,34 +0,0 @@
From c5de7c407853b807e8d0c764e6325bb1311f39cd Mon Sep 17 00:00:00 2001
From: Xing Li <lixing@loongson.cn>
Date: Tue, 4 Jul 2023 15:10:03 +0800
Subject: [PATCH 2/2] Fix tst-cancel21.c to suit kernel struct sigcontext
change. * nptl/tst-cancel21.c
---
nptl/tst-cancel21.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/nptl/tst-cancel21.c b/nptl/tst-cancel21.c
index b10fdbc1..a3653f21 100644
--- a/nptl/tst-cancel21.c
+++ b/nptl/tst-cancel21.c
@@ -217,14 +217,14 @@ static int
do_test (void)
{
stack_t ss;
- ss.ss_sp = malloc (2 * SIGSTKSZ);
+ ss.ss_sp = malloc (4 * SIGSTKSZ);
if (ss.ss_sp == NULL)
{
puts ("failed to allocate alternate stack");
return 1;
}
ss.ss_flags = 0;
- ss.ss_size = 2 * SIGSTKSZ;
+ ss.ss_size = 4 * SIGSTKSZ;
if (sigaltstack (&ss, NULL) < 0)
{
printf ("sigaltstack failed %m\n");
--
2.27.0

View file

@ -0,0 +1,499 @@
From 8923e4e9c79e672fd6b3b89aba598a60d5c01211 Mon Sep 17 00:00:00 2001
From: caiyinyu <caiyinyu@loongson.cn>
Date: Fri, 15 Sep 2023 17:35:19 +0800
Subject: [PATCH 25/29] LoongArch: Add glibc.cpu.hwcap support.
Key Points:
1. On lasx & lsx platforms, We must use _dl_runtime_{profile, resolve}_{lsx, lasx}
to save vector registers.
2. Via "tunables", users can choose str/mem_{lasx,lsx,unaligned} functions with
`export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,...`.
Note: glibc.cpu.hwcaps doesn't affect _dl_runtime_{profile, resolve}_{lsx, lasx}
selection.
Usage Notes:
1. Only valid inputs: LASX, LSX, UAL. Case-sensitive, comma-separated, no spaces.
2. Example: `export GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL` turns on LASX & UAL.
Unmentioned features turn off. With default ifunc: lasx > lsx > unaligned >
aligned > generic, effect is: lasx > unaligned > aligned > generic; lsx off.
3. Incorrect GLIBC_TUNABLES settings will show error messages.
For example: On lsx platforms, you cannot enable lasx features. If you do
that, you will get error messages.
4. Valid input examples:
- GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX: lasx > aligned > generic.
- GLIBC_TUNABLES=glibc.cpu.hwcaps=LSX,UAL: lsx > unaligned > aligned > generic.
- GLIBC_TUNABLES=glibc.cpu.hwcaps=LASX,UAL,LASX,UAL,LSX,LASX,UAL: Repetitions
allowed but not recommended. Results in: lasx > lsx > unaligned > aligned >
generic.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/Makefile | 4 +
sysdeps/loongarch/Versions | 5 ++
sysdeps/loongarch/cpu-tunables.c | 89 +++++++++++++++++++
sysdeps/loongarch/dl-get-cpu-features.c | 25 ++++++
sysdeps/loongarch/dl-machine.h | 27 +++++-
sysdeps/loongarch/dl-tunables.list | 25 ++++++
.../unix/sysv/linux/loongarch/cpu-features.c | 29 ++++++
.../unix/sysv/linux/loongarch/cpu-features.h | 18 +++-
.../unix/sysv/linux/loongarch/dl-procinfo.c | 60 +++++++++++++
sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c | 21 +++++
.../unix/sysv/linux/loongarch/libc-start.c | 34 +++++++
11 files changed, 329 insertions(+), 8 deletions(-)
create mode 100644 sysdeps/loongarch/Versions
create mode 100644 sysdeps/loongarch/cpu-tunables.c
create mode 100644 sysdeps/loongarch/dl-get-cpu-features.c
create mode 100644 sysdeps/loongarch/dl-tunables.list
create mode 100644 sysdeps/unix/sysv/linux/loongarch/cpu-features.c
create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
create mode 100644 sysdeps/unix/sysv/linux/loongarch/libc-start.c
diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile
index 43d2f583..30a1f4a8 100644
--- a/sysdeps/loongarch/Makefile
+++ b/sysdeps/loongarch/Makefile
@@ -6,6 +6,10 @@ ifeq ($(subdir),elf)
gen-as-const-headers += dl-link.sym
endif
+ifeq ($(subdir),elf)
+ sysdep-dl-routines += dl-get-cpu-features
+endif
+
# LoongArch's assembler also needs to know about PIC as it changes the
# definition of some assembler macros.
ASFLAGS-.os += $(pic-ccflag)
diff --git a/sysdeps/loongarch/Versions b/sysdeps/loongarch/Versions
new file mode 100644
index 00000000..33ae2cc0
--- /dev/null
+++ b/sysdeps/loongarch/Versions
@@ -0,0 +1,5 @@
+ld {
+ GLIBC_PRIVATE {
+ _dl_larch_get_cpu_features;
+ }
+}
diff --git a/sysdeps/loongarch/cpu-tunables.c b/sysdeps/loongarch/cpu-tunables.c
new file mode 100644
index 00000000..8e9fab93
--- /dev/null
+++ b/sysdeps/loongarch/cpu-tunables.c
@@ -0,0 +1,89 @@
+/* LoongArch CPU feature tuning.
+ This file is part of the GNU C Library.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+# include <stdbool.h>
+# include <stdint.h>
+# include <unistd.h> /* Get STDOUT_FILENO for _dl_printf. */
+# include <elf/dl-tunables.h>
+# include <string.h>
+# include <cpu-features.h>
+# include <ldsodefs.h>
+# include <sys/auxv.h>
+
+# define HWCAP_LOONGARCH_IFUNC \
+ (HWCAP_LOONGARCH_UAL | HWCAP_LOONGARCH_LSX | HWCAP_LOONGARCH_LASX)
+
+# define CHECK_GLIBC_IFUNC_CPU_OFF(f, name, len) \
+ _Static_assert (sizeof (#name) - 1 == len, #name " != " #len); \
+ if (!memcmp (f, #name, len) && \
+ (GLRO (dl_hwcap) & HWCAP_LOONGARCH_##name)) \
+ { \
+ hwcap |= (HWCAP_LOONGARCH_##name | (~HWCAP_LOONGARCH_IFUNC)); \
+ break; \
+ } \
+
+attribute_hidden
+void
+TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *valp)
+{
+ const char *p = valp->strval;
+ size_t len;
+ unsigned long hwcap = 0;
+ const char *c;
+
+ do {
+ for (c = p; *c != ','; c++)
+ if (*c == '\0')
+ break;
+
+ len = c - p;
+
+ switch(len)
+ {
+ default:
+ _dl_fatal_printf (
+ "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
+ );
+ break;
+ case 3:
+ {
+ CHECK_GLIBC_IFUNC_CPU_OFF (p, LSX, 3);
+ CHECK_GLIBC_IFUNC_CPU_OFF (p, UAL, 3);
+ _dl_fatal_printf (
+ "Some features are invalid or not supported on this machine!!\n"
+ "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
+ );
+ }
+ break;
+ case 4:
+ {
+ CHECK_GLIBC_IFUNC_CPU_OFF (p, LASX, 4);
+ _dl_fatal_printf (
+ "Some features are invalid or not supported on this machine!!\n"
+ "The valid values of glibc.cpu.hwcaps is UAL, LASX, LSX!!\n"
+ );
+ }
+ break;
+ }
+
+ p += len + 1;
+ }
+ while (*c != '\0');
+
+ GLRO (dl_larch_cpu_features).hwcap &= hwcap;
+}
diff --git a/sysdeps/loongarch/dl-get-cpu-features.c b/sysdeps/loongarch/dl-get-cpu-features.c
new file mode 100644
index 00000000..7cd9bc15
--- /dev/null
+++ b/sysdeps/loongarch/dl-get-cpu-features.c
@@ -0,0 +1,25 @@
+/* Define _dl_larch_get_cpu_features.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+
+#include <ldsodefs.h>
+
+const struct cpu_features *
+_dl_larch_get_cpu_features (void)
+{
+ return &GLRO(dl_larch_cpu_features);
+}
diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
index 57913cef..b395a928 100644
--- a/sysdeps/loongarch/dl-machine.h
+++ b/sysdeps/loongarch/dl-machine.h
@@ -29,6 +29,8 @@
#include <dl-static-tls.h>
#include <dl-machine-rel.h>
+#include <cpu-features.c>
+
#ifndef _RTLD_PROLOGUE
# define _RTLD_PROLOGUE(entry) \
".globl\t" __STRING (entry) "\n\t" \
@@ -53,6 +55,23 @@
#define ELF_MACHINE_NO_REL 1
#define ELF_MACHINE_NO_RELA 0
+#define DL_PLATFORM_INIT dl_platform_init ()
+
+static inline void __attribute__ ((unused))
+dl_platform_init (void)
+{
+ if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
+ /* Avoid an empty string which would disturb us. */
+ GLRO(dl_platform) = NULL;
+
+#ifdef SHARED
+ /* init_cpu_features has been called early from __libc_start_main in
+ static executable. */
+ init_cpu_features (&GLRO(dl_larch_cpu_features));
+#endif
+}
+
+
/* Return nonzero iff ELF header is compatible with the running host. */
static inline int
elf_machine_matches_host (const ElfW (Ehdr) *ehdr)
@@ -290,9 +309,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
if (profile != 0)
{
#if !defined __loongarch_soft_float
- if (SUPPORT_LASX)
+ if (RTLD_SUPPORT_LASX)
gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lasx;
- else if (SUPPORT_LSX)
+ else if (RTLD_SUPPORT_LSX)
gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lsx;
else
#endif
@@ -310,9 +329,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
indicated by the offset on the stack, and then jump to
the resolved address. */
#if !defined __loongarch_soft_float
- if (SUPPORT_LASX)
+ if (RTLD_SUPPORT_LASX)
gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lasx;
- else if (SUPPORT_LSX)
+ else if (RTLD_SUPPORT_LSX)
gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lsx;
else
#endif
diff --git a/sysdeps/loongarch/dl-tunables.list b/sysdeps/loongarch/dl-tunables.list
new file mode 100644
index 00000000..66b34275
--- /dev/null
+++ b/sysdeps/loongarch/dl-tunables.list
@@ -0,0 +1,25 @@
+# LoongArch specific tunables.
+# Copyright (C) 2023 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+glibc {
+ cpu {
+ hwcaps {
+ type: STRING
+ }
+ }
+}
diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.c b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
new file mode 100644
index 00000000..1290c4ce
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.c
@@ -0,0 +1,29 @@
+/* Initialize CPU feature data. LoongArch64 version.
+ This file is part of the GNU C Library.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <cpu-features.h>
+#include <elf/dl-hwcaps.h>
+#include <elf/dl-tunables.h>
+extern void TUNABLE_CALLBACK (set_hwcaps) (tunable_val_t *) attribute_hidden;
+
+static inline void
+init_cpu_features (struct cpu_features *cpu_features)
+{
+ GLRO (dl_larch_cpu_features).hwcap = GLRO (dl_hwcap);
+ TUNABLE_GET (glibc, cpu, hwcaps, tunable_val_t *, TUNABLE_CALLBACK (set_hwcaps));
+}
diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
index d1a280a5..450963ce 100644
--- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
+++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
@@ -19,13 +19,23 @@
#ifndef _CPU_FEATURES_LOONGARCH64_H
#define _CPU_FEATURES_LOONGARCH64_H
+#include <stdint.h>
#include <sys/auxv.h>
-#define SUPPORT_UAL (GLRO (dl_hwcap) & HWCAP_LOONGARCH_UAL)
-#define SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
-#define SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
+struct cpu_features
+ {
+ uint64_t hwcap;
+ };
+/* Get a pointer to the CPU features structure. */
+extern const struct cpu_features *_dl_larch_get_cpu_features (void)
+ __attribute__ ((pure));
+
+#define SUPPORT_UAL (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_UAL)
+#define SUPPORT_LSX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LSX)
+#define SUPPORT_LASX (GLRO (dl_larch_cpu_features).hwcap & HWCAP_LOONGARCH_LASX)
+#define RTLD_SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
+#define RTLD_SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
#define INIT_ARCH()
#endif /* _CPU_FEATURES_LOONGARCH64_H */
-
diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
new file mode 100644
index 00000000..6217fda9
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/dl-procinfo.c
@@ -0,0 +1,60 @@
+/* Data for LoongArch64 version of processor capability information.
+ Linux version.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* If anything should be added here check whether the size of each string
+ is still ok with the given array size.
+
+ All the #ifdefs in the definitions are quite irritating but
+ necessary if we want to avoid duplicating the information. There
+ are three different modes:
+
+ - PROCINFO_DECL is defined. This means we are only interested in
+ declarations.
+
+ - PROCINFO_DECL is not defined:
+
+ + if SHARED is defined the file is included in an array
+ initializer. The .element = { ... } syntax is needed.
+
+ + if SHARED is not defined a normal array initialization is
+ needed.
+ */
+
+#ifndef PROCINFO_CLASS
+# define PROCINFO_CLASS
+#endif
+
+#if !IS_IN (ldconfig)
+# if !defined PROCINFO_DECL && defined SHARED
+ ._dl_larch_cpu_features
+# else
+PROCINFO_CLASS struct cpu_features _dl_larch_cpu_features
+# endif
+# ifndef PROCINFO_DECL
+= { }
+# endif
+# if !defined SHARED || defined PROCINFO_DECL
+;
+# else
+,
+# endif
+#endif
+
+#undef PROCINFO_DECL
+#undef PROCINFO_CLASS
diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
new file mode 100644
index 00000000..455fd71a
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/dl-sysdep.c
@@ -0,0 +1,21 @@
+/* Operating system support for run-time dynamic linker. LoongArch version.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include <sysdeps/loongarch/cpu-tunables.c>
+#include <sysdeps/unix/sysv/linux/dl-sysdep.c>
diff --git a/sysdeps/unix/sysv/linux/loongarch/libc-start.c b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
new file mode 100644
index 00000000..f1346ece
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/loongarch/libc-start.c
@@ -0,0 +1,34 @@
+/* Override csu/libc-start.c on LoongArch64.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef SHARED
+
+/* Mark symbols hidden in static PIE for early self relocation to work. */
+# if BUILD_PIE_DEFAULT
+# pragma GCC visibility push(hidden)
+# endif
+
+# include <ldsodefs.h>
+# include <cpu-features.c>
+
+extern struct cpu_features _dl_larch_cpu_features;
+
+# define ARCH_INIT_CPU_FEATURES() init_cpu_features (&_dl_larch_cpu_features)
+
+#endif
+#include <csu/libc-start.c>
--
2.33.0

View file

@ -0,0 +1,485 @@
From 3ee56bbc56faa7b85a6513340db4a4fdd6ce709d Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Mon, 28 Aug 2023 10:08:36 +0800
Subject: [PATCH 15/29] LoongArch: Add ifunc support for memchr{aligned, lsx,
lasx}
According to glibc memchr microbenchmark, this implementation could reduce
the runtime as following:
Name Percent of runtime reduced
memchr-lasx 37%-83%
memchr-lsx 30%-66%
memchr-aligned 0%-15%
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/lp64/multiarch/Makefile | 3 +
.../lp64/multiarch/ifunc-impl-list.c | 7 ++
.../loongarch/lp64/multiarch/ifunc-memchr.h | 40 ++++++
.../loongarch/lp64/multiarch/memchr-aligned.S | 95 ++++++++++++++
.../loongarch/lp64/multiarch/memchr-lasx.S | 117 ++++++++++++++++++
sysdeps/loongarch/lp64/multiarch/memchr-lsx.S | 102 +++++++++++++++
sysdeps/loongarch/lp64/multiarch/memchr.c | 37 ++++++
7 files changed, 401 insertions(+)
create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-memchr.h
create mode 100644 sysdeps/loongarch/lp64/multiarch/memchr-aligned.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/memchr-lasx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/memchr-lsx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/memchr.c
diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile
index 64416b02..2f4802cf 100644
--- a/sysdeps/loongarch/lp64/multiarch/Makefile
+++ b/sysdeps/loongarch/lp64/multiarch/Makefile
@@ -24,5 +24,8 @@ sysdep_routines += \
rawmemchr-aligned \
rawmemchr-lsx \
rawmemchr-lasx \
+ memchr-aligned \
+ memchr-lsx \
+ memchr-lasx \
# sysdep_routines
endif
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
index 3db9af14..a567b9cf 100644
--- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
@@ -102,5 +102,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
IFUNC_IMPL_ADD (array, i, rawmemchr, 1, __rawmemchr_aligned)
)
+ IFUNC_IMPL (i, name, memchr,
+#if !defined __loongarch_soft_float
+ IFUNC_IMPL_ADD (array, i, memchr, SUPPORT_LASX, __memchr_lasx)
+ IFUNC_IMPL_ADD (array, i, memchr, SUPPORT_LSX, __memchr_lsx)
+#endif
+ IFUNC_IMPL_ADD (array, i, memchr, 1, __memchr_aligned)
+ )
return i;
}
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-memchr.h b/sysdeps/loongarch/lp64/multiarch/ifunc-memchr.h
new file mode 100644
index 00000000..9060ccd5
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-memchr.h
@@ -0,0 +1,40 @@
+/* Common definition for memchr ifunc selections.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#if !defined __loongarch_soft_float
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden;
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden;
+#endif
+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+#if !defined __loongarch_soft_float
+ if (SUPPORT_LASX)
+ return OPTIMIZE (lasx);
+ else if (SUPPORT_LSX)
+ return OPTIMIZE (lsx);
+ else
+#endif
+ return OPTIMIZE (aligned);
+}
diff --git a/sysdeps/loongarch/lp64/multiarch/memchr-aligned.S b/sysdeps/loongarch/lp64/multiarch/memchr-aligned.S
new file mode 100644
index 00000000..81d0d004
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memchr-aligned.S
@@ -0,0 +1,95 @@
+/* Optimized memchr implementation using basic LoongArch instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc)
+# define MEMCHR_NAME __memchr_aligned
+#else
+# define MEMCHR_NAME memchr
+#endif
+
+LEAF(MEMCHR_NAME, 6)
+ beqz a2, L(out)
+ andi t1, a0, 0x7
+ add.d a5, a0, a2
+ bstrins.d a0, zero, 2, 0
+
+ ld.d t0, a0, 0
+ bstrins.d a1, a1, 15, 8
+ lu12i.w a3, 0x01010
+ slli.d t2, t1, 03
+
+ bstrins.d a1, a1, 31, 16
+ ori a3, a3, 0x101
+ li.d t7, -1
+ li.d t8, 8
+
+ bstrins.d a1, a1, 63, 32
+ bstrins.d a3, a3, 63, 32
+ sll.d t2, t7, t2
+ xor t0, t0, a1
+
+
+ addi.d a6, a5, -1
+ slli.d a4, a3, 7
+ sub.d t1, t8, t1
+ orn t0, t0, t2
+
+ sub.d t2, t0, a3
+ andn t3, a4, t0
+ bstrins.d a6, zero, 2, 0
+ and t0, t2, t3
+
+ bgeu t1, a2, L(end)
+L(loop):
+ bnez t0, L(found)
+ ld.d t1, a0, 8
+ xor t0, t1, a1
+
+ addi.d a0, a0, 8
+ sub.d t2, t0, a3
+ andn t3, a4, t0
+ and t0, t2, t3
+
+
+ bne a0, a6, L(loop)
+L(end):
+ sub.d t1, a5, a6
+ ctz.d t0, t0
+ srli.d t0, t0, 3
+
+ sltu t1, t0, t1
+ add.d a0, a0, t0
+ maskeqz a0, a0, t1
+ jr ra
+
+L(found):
+ ctz.d t0, t0
+ srli.d t0, t0, 3
+ add.d a0, a0, t0
+ jr ra
+
+L(out):
+ move a0, zero
+ jr ra
+END(MEMCHR_NAME)
+
+libc_hidden_builtin_def (MEMCHR_NAME)
diff --git a/sysdeps/loongarch/lp64/multiarch/memchr-lasx.S b/sysdeps/loongarch/lp64/multiarch/memchr-lasx.S
new file mode 100644
index 00000000..a26cdf48
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memchr-lasx.S
@@ -0,0 +1,117 @@
+/* Optimized memchr implementation using LoongArch LASX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define MEMCHR __memchr_lasx
+
+LEAF(MEMCHR, 6)
+ beqz a2, L(ret0)
+ add.d a3, a0, a2
+ andi t0, a0, 0x3f
+ bstrins.d a0, zero, 5, 0
+
+ xvld xr0, a0, 0
+ xvld xr1, a0, 32
+ li.d t1, -1
+ li.d t2, 64
+
+ xvreplgr2vr.b xr2, a1
+ sll.d t3, t1, t0
+ sub.d t2, t2, t0
+ xvseq.b xr0, xr0, xr2
+
+ xvseq.b xr1, xr1, xr2
+ xvmsknz.b xr0, xr0
+ xvmsknz.b xr1, xr1
+ xvpickve.w xr3, xr0, 4
+
+
+ xvpickve.w xr4, xr1, 4
+ vilvl.h vr0, vr3, vr0
+ vilvl.h vr1, vr4, vr1
+ vilvl.w vr0, vr1, vr0
+
+ movfr2gr.d t0, fa0
+ and t0, t0, t3
+ bgeu t2, a2, L(end)
+ bnez t0, L(found)
+
+ addi.d a4, a3, -1
+ bstrins.d a4, zero, 5, 0
+L(loop):
+ xvld xr0, a0, 64
+ xvld xr1, a0, 96
+
+ addi.d a0, a0, 64
+ xvseq.b xr0, xr0, xr2
+ xvseq.b xr1, xr1, xr2
+ beq a0, a4, L(out)
+
+
+ xvmax.bu xr3, xr0, xr1
+ xvseteqz.v fcc0, xr3
+ bcnez fcc0, L(loop)
+ xvmsknz.b xr0, xr0
+
+ xvmsknz.b xr1, xr1
+ xvpickve.w xr3, xr0, 4
+ xvpickve.w xr4, xr1, 4
+ vilvl.h vr0, vr3, vr0
+
+ vilvl.h vr1, vr4, vr1
+ vilvl.w vr0, vr1, vr0
+ movfr2gr.d t0, fa0
+L(found):
+ ctz.d t1, t0
+
+ add.d a0, a0, t1
+ jr ra
+L(ret0):
+ move a0, zero
+ jr ra
+
+
+L(out):
+ xvmsknz.b xr0, xr0
+ xvmsknz.b xr1, xr1
+ xvpickve.w xr3, xr0, 4
+ xvpickve.w xr4, xr1, 4
+
+ vilvl.h vr0, vr3, vr0
+ vilvl.h vr1, vr4, vr1
+ vilvl.w vr0, vr1, vr0
+ movfr2gr.d t0, fa0
+
+L(end):
+ sub.d t2, zero, a3
+ srl.d t1, t1, t2
+ and t0, t0, t1
+ ctz.d t1, t0
+
+ add.d a0, a0, t1
+ maskeqz a0, a0, t0
+ jr ra
+END(MEMCHR)
+
+libc_hidden_builtin_def (MEMCHR)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/memchr-lsx.S b/sysdeps/loongarch/lp64/multiarch/memchr-lsx.S
new file mode 100644
index 00000000..a73ecd25
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memchr-lsx.S
@@ -0,0 +1,102 @@
+/* Optimized memchr implementation using LoongArch LSX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define MEMCHR __memchr_lsx
+
+LEAF(MEMCHR, 6)
+ beqz a2, L(ret0)
+ add.d a3, a0, a2
+ andi t0, a0, 0x1f
+ bstrins.d a0, zero, 4, 0
+
+ vld vr0, a0, 0
+ vld vr1, a0, 16
+ li.d t1, -1
+ li.d t2, 32
+
+ vreplgr2vr.b vr2, a1
+ sll.d t3, t1, t0
+ sub.d t2, t2, t0
+ vseq.b vr0, vr0, vr2
+
+ vseq.b vr1, vr1, vr2
+ vmsknz.b vr0, vr0
+ vmsknz.b vr1, vr1
+ vilvl.h vr0, vr1, vr0
+
+
+ movfr2gr.s t0, fa0
+ and t0, t0, t3
+ bgeu t2, a2, L(end)
+ bnez t0, L(found)
+
+ addi.d a4, a3, -1
+ bstrins.d a4, zero, 4, 0
+L(loop):
+ vld vr0, a0, 32
+ vld vr1, a0, 48
+
+ addi.d a0, a0, 32
+ vseq.b vr0, vr0, vr2
+ vseq.b vr1, vr1, vr2
+ beq a0, a4, L(out)
+
+ vmax.bu vr3, vr0, vr1
+ vseteqz.v fcc0, vr3
+ bcnez fcc0, L(loop)
+ vmsknz.b vr0, vr0
+
+
+ vmsknz.b vr1, vr1
+ vilvl.h vr0, vr1, vr0
+ movfr2gr.s t0, fa0
+L(found):
+ ctz.w t0, t0
+
+ add.d a0, a0, t0
+ jr ra
+L(ret0):
+ move a0, zero
+ jr ra
+
+L(out):
+ vmsknz.b vr0, vr0
+ vmsknz.b vr1, vr1
+ vilvl.h vr0, vr1, vr0
+ movfr2gr.s t0, fa0
+
+L(end):
+ sub.d t2, zero, a3
+ srl.w t1, t1, t2
+ and t0, t0, t1
+ ctz.w t1, t0
+
+
+ add.d a0, a0, t1
+ maskeqz a0, a0, t0
+ jr ra
+END(MEMCHR)
+
+libc_hidden_builtin_def (MEMCHR)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/memchr.c b/sysdeps/loongarch/lp64/multiarch/memchr.c
new file mode 100644
index 00000000..059479c0
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memchr.c
@@ -0,0 +1,37 @@
+/* Multiple versions of memchr.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define memchr __redirect_memchr
+# include <string.h>
+# undef memchr
+
+# define SYMBOL_NAME memchr
+# include "ifunc-memchr.h"
+
+libc_ifunc_redirected (__redirect_memchr, memchr,
+ IFUNC_SELECTOR ());
+
+# ifdef SHARED
+__hidden_ver1 (memchr, __GI_memchr, __redirect_memchr)
+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (memchr);
+# endif
+
+#endif
--
2.33.0

View file

@ -0,0 +1,946 @@
From 60f4bbd1eec528ba8df044ae6b3091f6337a7fcc Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Mon, 28 Aug 2023 10:08:39 +0800
Subject: [PATCH 18/29] LoongArch: Add ifunc support for memcmp{aligned, lsx,
lasx}
According to glibc memcmp microbenchmark test results(Add generic
memcmp), this implementation have performance improvement
except the length is less than 3, details as below:
Name Percent of time reduced
memcmp-lasx 16%-74%
memcmp-lsx 20%-50%
memcmp-aligned 5%-20%
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/lp64/multiarch/Makefile | 3 +
.../lp64/multiarch/ifunc-impl-list.c | 7 +
.../loongarch/lp64/multiarch/ifunc-memcmp.h | 40 +++
.../loongarch/lp64/multiarch/memcmp-aligned.S | 292 ++++++++++++++++++
.../loongarch/lp64/multiarch/memcmp-lasx.S | 207 +++++++++++++
sysdeps/loongarch/lp64/multiarch/memcmp-lsx.S | 269 ++++++++++++++++
sysdeps/loongarch/lp64/multiarch/memcmp.c | 43 +++
7 files changed, 861 insertions(+)
create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-memcmp.h
create mode 100644 sysdeps/loongarch/lp64/multiarch/memcmp-aligned.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/memcmp-lasx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/memcmp-lsx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/memcmp.c
diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile
index 216886c5..360a6718 100644
--- a/sysdeps/loongarch/lp64/multiarch/Makefile
+++ b/sysdeps/loongarch/lp64/multiarch/Makefile
@@ -34,5 +34,8 @@ sysdep_routines += \
memset-unaligned \
memset-lsx \
memset-lasx \
+ memcmp-aligned \
+ memcmp-lsx \
+ memcmp-lasx \
# sysdep_routines
endif
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
index 37f60dde..e397d58c 100644
--- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
@@ -127,5 +127,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
IFUNC_IMPL_ADD (array, i, memset, 1, __memset_aligned)
)
+ IFUNC_IMPL (i, name, memcmp,
+#if !defined __loongarch_soft_float
+ IFUNC_IMPL_ADD (array, i, memcmp, SUPPORT_LASX, __memcmp_lasx)
+ IFUNC_IMPL_ADD (array, i, memcmp, SUPPORT_LSX, __memcmp_lsx)
+#endif
+ IFUNC_IMPL_ADD (array, i, memcmp, 1, __memcmp_aligned)
+ )
return i;
}
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-memcmp.h b/sysdeps/loongarch/lp64/multiarch/ifunc-memcmp.h
new file mode 100644
index 00000000..04adc2e5
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-memcmp.h
@@ -0,0 +1,40 @@
+/* Common definition for memcmp ifunc selections.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#if !defined __loongarch_soft_float
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden;
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden;
+#endif
+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+#if !defined __loongarch_soft_float
+ if (SUPPORT_LASX)
+ return OPTIMIZE (lasx);
+ else if (SUPPORT_LSX)
+ return OPTIMIZE (lsx);
+ else
+#endif
+ return OPTIMIZE (aligned);
+}
diff --git a/sysdeps/loongarch/lp64/multiarch/memcmp-aligned.S b/sysdeps/loongarch/lp64/multiarch/memcmp-aligned.S
new file mode 100644
index 00000000..14a7caa9
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memcmp-aligned.S
@@ -0,0 +1,292 @@
+/* Optimized memcmp implementation using basic LoongArch instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc)
+# define MEMCMP_NAME __memcmp_aligned
+#else
+# define MEMCMP_NAME memcmp
+#endif
+
+LEAF(MEMCMP_NAME, 6)
+ beqz a2, L(ret)
+ andi a4, a1, 0x7
+ andi a3, a0, 0x7
+ sltu a5, a4, a3
+
+ xor t0, a0, a1
+ li.w t8, 8
+ maskeqz t0, t0, a5
+ li.w t7, -1
+
+ xor a0, a0, t0
+ xor a1, a1, t0
+ andi a3, a0, 0x7
+ andi a4, a1, 0x7
+
+ xor a0, a0, a3
+ xor a1, a1, a4
+ ld.d t2, a0, 0
+ ld.d t1, a1, 0
+
+ slli.d t3, a3, 3
+ slli.d t4, a4, 3
+ sub.d a6, t3, t4
+ srl.d t1, t1, t4
+
+ srl.d t0, t2, t3
+ srl.d t5, t7, t4
+ sub.d t6, t0, t1
+ and t6, t6, t5
+
+ sub.d t5, t8, a4
+ bnez t6, L(first_out)
+ bgeu t5, a2, L(ret)
+ sub.d a2, a2, t5
+
+ bnez a6, L(unaligned)
+ blt a2, t8, L(al_less_8bytes)
+ andi t1, a2, 31
+ beq t1, a2, L(al_less_32bytes)
+
+ sub.d t2, a2, t1
+ add.d a4, a0, t2
+ move a2, t1
+
+L(al_loop):
+ ld.d t0, a0, 8
+
+ ld.d t1, a1, 8
+ ld.d t2, a0, 16
+ ld.d t3, a1, 16
+ ld.d t4, a0, 24
+
+ ld.d t5, a1, 24
+ ld.d t6, a0, 32
+ ld.d t7, a1, 32
+ addi.d a0, a0, 32
+
+ addi.d a1, a1, 32
+ bne t0, t1, L(out1)
+ bne t2, t3, L(out2)
+ bne t4, t5, L(out3)
+
+ bne t6, t7, L(out4)
+ bne a0, a4, L(al_loop)
+
+L(al_less_32bytes):
+ srai.d a4, a2, 4
+ beqz a4, L(al_less_16bytes)
+
+ ld.d t0, a0, 8
+ ld.d t1, a1, 8
+ ld.d t2, a0, 16
+ ld.d t3, a1, 16
+
+ addi.d a0, a0, 16
+ addi.d a1, a1, 16
+ addi.d a2, a2, -16
+ bne t0, t1, L(out1)
+
+ bne t2, t3, L(out2)
+
+L(al_less_16bytes):
+ srai.d a4, a2, 3
+ beqz a4, L(al_less_8bytes)
+ ld.d t0, a0, 8
+
+ ld.d t1, a1, 8
+ addi.d a0, a0, 8
+ addi.d a1, a1, 8
+ addi.d a2, a2, -8
+
+ bne t0, t1, L(out1)
+
+L(al_less_8bytes):
+ beqz a2, L(ret)
+ ld.d t0, a0, 8
+ ld.d t1, a1, 8
+
+ li.d t7, -1
+ slli.d t2, a2, 3
+ sll.d t2, t7, t2
+ sub.d t3, t0, t1
+
+ andn t6, t3, t2
+ bnez t6, L(count_diff)
+
+L(ret):
+ move a0, zero
+ jr ra
+
+L(out4):
+ move t0, t6
+ move t1, t7
+ sub.d t6, t6, t7
+ b L(count_diff)
+
+L(out3):
+ move t0, t4
+ move t1, t5
+ sub.d t6, t4, t5
+ b L(count_diff)
+
+L(out2):
+ move t0, t2
+ move t1, t3
+L(out1):
+ sub.d t6, t0, t1
+ b L(count_diff)
+
+L(first_out):
+ slli.d t4, a2, 3
+ slt t3, a2, t5
+ sll.d t4, t7, t4
+ maskeqz t4, t4, t3
+
+ andn t6, t6, t4
+
+L(count_diff):
+ ctz.d t2, t6
+ bstrins.d t2, zero, 2, 0
+ srl.d t0, t0, t2
+
+ srl.d t1, t1, t2
+ andi t0, t0, 0xff
+ andi t1, t1, 0xff
+ sub.d t2, t0, t1
+
+ sub.d t3, t1, t0
+ masknez t2, t2, a5
+ maskeqz t3, t3, a5
+ or a0, t2, t3
+
+ jr ra
+
+L(unaligned):
+ sub.d a7, zero, a6
+ srl.d t0, t2, a6
+ blt a2, t8, L(un_less_8bytes)
+
+ andi t1, a2, 31
+ beq t1, a2, L(un_less_32bytes)
+ sub.d t2, a2, t1
+ add.d a4, a0, t2
+
+ move a2, t1
+
+L(un_loop):
+ ld.d t2, a0, 8
+ ld.d t1, a1, 8
+ ld.d t4, a0, 16
+
+ ld.d t3, a1, 16
+ ld.d t6, a0, 24
+ ld.d t5, a1, 24
+ ld.d t8, a0, 32
+
+ ld.d t7, a1, 32
+ addi.d a0, a0, 32
+ addi.d a1, a1, 32
+ sll.d a3, t2, a7
+
+ or t0, a3, t0
+ bne t0, t1, L(out1)
+ srl.d t0, t2, a6
+ sll.d a3, t4, a7
+
+ or t2, a3, t0
+ bne t2, t3, L(out2)
+ srl.d t0, t4, a6
+ sll.d a3, t6, a7
+
+ or t4, a3, t0
+ bne t4, t5, L(out3)
+ srl.d t0, t6, a6
+ sll.d a3, t8, a7
+
+ or t6, t0, a3
+ bne t6, t7, L(out4)
+ srl.d t0, t8, a6
+ bne a0, a4, L(un_loop)
+
+L(un_less_32bytes):
+ srai.d a4, a2, 4
+ beqz a4, L(un_less_16bytes)
+ ld.d t2, a0, 8
+ ld.d t1, a1, 8
+
+ ld.d t4, a0, 16
+ ld.d t3, a1, 16
+ addi.d a0, a0, 16
+ addi.d a1, a1, 16
+
+ addi.d a2, a2, -16
+ sll.d a3, t2, a7
+ or t0, a3, t0
+ bne t0, t1, L(out1)
+
+ srl.d t0, t2, a6
+ sll.d a3, t4, a7
+ or t2, a3, t0
+ bne t2, t3, L(out2)
+
+ srl.d t0, t4, a6
+
+L(un_less_16bytes):
+ srai.d a4, a2, 3
+ beqz a4, L(un_less_8bytes)
+ ld.d t2, a0, 8
+
+ ld.d t1, a1, 8
+ addi.d a0, a0, 8
+ addi.d a1, a1, 8
+ addi.d a2, a2, -8
+
+ sll.d a3, t2, a7
+ or t0, a3, t0
+ bne t0, t1, L(out1)
+ srl.d t0, t2, a6
+
+L(un_less_8bytes):
+ beqz a2, L(ret)
+ andi a7, a7, 63
+ slli.d a4, a2, 3
+ bgeu a7, a4, L(last_cmp)
+
+ ld.d t2, a0, 8
+ sll.d a3, t2, a7
+ or t0, a3, t0
+
+L(last_cmp):
+ ld.d t1, a1, 8
+
+ li.d t7, -1
+ sll.d t2, t7, a4
+ sub.d t3, t0, t1
+ andn t6, t3, t2
+
+ bnez t6, L(count_diff)
+ move a0, zero
+ jr ra
+END(MEMCMP_NAME)
+
+libc_hidden_builtin_def (MEMCMP_NAME)
diff --git a/sysdeps/loongarch/lp64/multiarch/memcmp-lasx.S b/sysdeps/loongarch/lp64/multiarch/memcmp-lasx.S
new file mode 100644
index 00000000..3151a179
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memcmp-lasx.S
@@ -0,0 +1,207 @@
+/* Optimized memcmp implementation using LoongArch LASX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define MEMCMP __memcmp_lasx
+
+LEAF(MEMCMP, 6)
+ li.d t2, 32
+ add.d a3, a0, a2
+ add.d a4, a1, a2
+ bgeu t2, a2, L(less32)
+
+ li.d t1, 160
+ bgeu a2, t1, L(make_aligned)
+L(loop32):
+ xvld xr0, a0, 0
+ xvld xr1, a1, 0
+
+ addi.d a0, a0, 32
+ addi.d a1, a1, 32
+ addi.d a2, a2, -32
+ xvseq.b xr2, xr0, xr1
+
+ xvsetanyeqz.b fcc0, xr2
+ bcnez fcc0, L(end)
+L(last_bytes):
+ bltu t2, a2, L(loop32)
+ xvld xr0, a3, -32
+
+
+ xvld xr1, a4, -32
+ xvseq.b xr2, xr0, xr1
+L(end):
+ xvmsknz.b xr2, xr2
+ xvpermi.q xr4, xr0, 1
+
+ xvpickve.w xr3, xr2, 4
+ xvpermi.q xr5, xr1, 1
+ vilvl.h vr2, vr3, vr2
+ movfr2gr.s t0, fa2
+
+ cto.w t0, t0
+ vreplgr2vr.b vr2, t0
+ vshuf.b vr0, vr4, vr0, vr2
+ vshuf.b vr1, vr5, vr1, vr2
+
+ vpickve2gr.bu t0, vr0, 0
+ vpickve2gr.bu t1, vr1, 0
+ sub.d a0, t0, t1
+ jr ra
+
+
+L(less32):
+ srli.d t0, a2, 4
+ beqz t0, L(less16)
+ vld vr0, a0, 0
+ vld vr1, a1, 0
+
+ vld vr2, a3, -16
+ vld vr3, a4, -16
+L(short_ret):
+ vseq.b vr4, vr0, vr1
+ vseq.b vr5, vr2, vr3
+
+ vmsknz.b vr4, vr4
+ vmsknz.b vr5, vr5
+ vilvl.h vr4, vr5, vr4
+ movfr2gr.s t0, fa4
+
+ cto.w t0, t0
+ vreplgr2vr.b vr4, t0
+ vshuf.b vr0, vr2, vr0, vr4
+ vshuf.b vr1, vr3, vr1, vr4
+
+
+ vpickve2gr.bu t0, vr0, 0
+ vpickve2gr.bu t1, vr1, 0
+ sub.d a0, t0, t1
+ jr ra
+
+L(less16):
+ srli.d t0, a2, 3
+ beqz t0, L(less8)
+ vldrepl.d vr0, a0, 0
+ vldrepl.d vr1, a1, 0
+
+ vldrepl.d vr2, a3, -8
+ vldrepl.d vr3, a4, -8
+ b L(short_ret)
+ nop
+
+L(less8):
+ srli.d t0, a2, 2
+ beqz t0, L(less4)
+ vldrepl.w vr0, a0, 0
+ vldrepl.w vr1, a1, 0
+
+
+ vldrepl.w vr2, a3, -4
+ vldrepl.w vr3, a4, -4
+ b L(short_ret)
+ nop
+
+L(less4):
+ srli.d t0, a2, 1
+ beqz t0, L(less2)
+ vldrepl.h vr0, a0, 0
+ vldrepl.h vr1, a1, 0
+
+ vldrepl.h vr2, a3, -2
+ vldrepl.h vr3, a4, -2
+ b L(short_ret)
+ nop
+
+L(less2):
+ beqz a2, L(ret0)
+ ld.bu t0, a0, 0
+ ld.bu t1, a1, 0
+ sub.d a0, t0, t1
+
+ jr ra
+L(ret0):
+ move a0, zero
+ jr ra
+
+L(make_aligned):
+ xvld xr0, a0, 0
+
+ xvld xr1, a1, 0
+ xvseq.b xr2, xr0, xr1
+ xvsetanyeqz.b fcc0, xr2
+ bcnez fcc0, L(end)
+
+ andi t0, a0, 0x1f
+ sub.d t0, t2, t0
+ sub.d t1, a2, t0
+ add.d a0, a0, t0
+
+ add.d a1, a1, t0
+ andi a2, t1, 0x3f
+ sub.d t0, t1, a2
+ add.d a5, a0, t0
+
+
+L(loop_align):
+ xvld xr0, a0, 0
+ xvld xr1, a1, 0
+ xvld xr2, a0, 32
+ xvld xr3, a1, 32
+
+ xvseq.b xr0, xr0, xr1
+ xvseq.b xr1, xr2, xr3
+ xvmin.bu xr2, xr1, xr0
+ xvsetanyeqz.b fcc0, xr2
+
+ bcnez fcc0, L(pair_end)
+ addi.d a0, a0, 64
+ addi.d a1, a1, 64
+ bne a0, a5, L(loop_align)
+
+ bnez a2, L(last_bytes)
+ move a0, zero
+ jr ra
+ nop
+
+
+L(pair_end):
+ xvmsknz.b xr0, xr0
+ xvmsknz.b xr1, xr1
+ xvpickve.w xr2, xr0, 4
+ xvpickve.w xr3, xr1, 4
+
+ vilvl.h vr0, vr2, vr0
+ vilvl.h vr1, vr3, vr1
+ vilvl.w vr0, vr1, vr0
+ movfr2gr.d t0, fa0
+
+ cto.d t0, t0
+ ldx.bu t1, a0, t0
+ ldx.bu t2, a1, t0
+ sub.d a0, t1, t2
+
+ jr ra
+END(MEMCMP)
+
+libc_hidden_builtin_def (MEMCMP)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/memcmp-lsx.S b/sysdeps/loongarch/lp64/multiarch/memcmp-lsx.S
new file mode 100644
index 00000000..38a50a4c
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memcmp-lsx.S
@@ -0,0 +1,269 @@
+/* Optimized memcmp implementation using LoongArch LSX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+#define MEMCMP __memcmp_lsx
+
+LEAF(MEMCMP, 6)
+ beqz a2, L(out)
+ pcalau12i t0, %pc_hi20(L(INDEX))
+ andi a3, a0, 0xf
+ vld vr5, t0, %pc_lo12(L(INDEX))
+
+ andi a4, a1, 0xf
+ bne a3, a4, L(unaligned)
+ bstrins.d a0, zero, 3, 0
+ xor a1, a1, a4
+
+ vld vr0, a0, 0
+ vld vr1, a1, 0
+ li.d t0, 16
+ vreplgr2vr.b vr3, a3
+
+ sub.d t1, t0, a3
+ vadd.b vr3, vr3, vr5
+ vshuf.b vr0, vr3, vr0, vr3
+ vshuf.b vr1, vr3, vr1, vr3
+
+
+ vseq.b vr4, vr0, vr1
+ bgeu t1, a2, L(al_end)
+ vsetanyeqz.b fcc0, vr4
+ bcnez fcc0, L(al_found)
+
+ sub.d t1, a2, t1
+ andi a2, t1, 31
+ beq a2, t1, L(al_less_32bytes)
+ sub.d t2, t1, a2
+
+ add.d a4, a0, t2
+L(al_loop):
+ vld vr0, a0, 16
+ vld vr1, a1, 16
+ vld vr2, a0, 32
+
+ vld vr3, a1, 32
+ addi.d a0, a0, 32
+ addi.d a1, a1, 32
+ vseq.b vr4, vr0, vr1
+
+
+ vseq.b vr6, vr2, vr3
+ vand.v vr6, vr4, vr6
+ vsetanyeqz.b fcc0, vr6
+ bcnez fcc0, L(al_pair_end)
+
+ bne a0, a4, L(al_loop)
+L(al_less_32bytes):
+ bgeu t0, a2, L(al_less_16bytes)
+ vld vr0, a0, 16
+ vld vr1, a1, 16
+
+ vld vr2, a0, 32
+ vld vr3, a1, 32
+ addi.d a2, a2, -16
+ vreplgr2vr.b vr6, a2
+
+ vslt.b vr5, vr5, vr6
+ vseq.b vr4, vr0, vr1
+ vseq.b vr6, vr2, vr3
+ vorn.v vr6, vr6, vr5
+
+
+L(al_pair_end):
+ vsetanyeqz.b fcc0, vr4
+ bcnez fcc0, L(al_found)
+ vnori.b vr4, vr6, 0
+ vfrstpi.b vr4, vr4, 0
+
+ vshuf.b vr0, vr2, vr2, vr4
+ vshuf.b vr1, vr3, vr3, vr4
+ vpickve2gr.bu t0, vr0, 0
+ vpickve2gr.bu t1, vr1, 0
+
+ sub.d a0, t0, t1
+ jr ra
+ nop
+ nop
+
+L(al_less_16bytes):
+ beqz a2, L(out)
+ vld vr0, a0, 16
+ vld vr1, a1, 16
+ vseq.b vr4, vr0, vr1
+
+
+L(al_end):
+ vreplgr2vr.b vr6, a2
+ vslt.b vr5, vr5, vr6
+ vorn.v vr4, vr4, vr5
+ nop
+
+L(al_found):
+ vnori.b vr4, vr4, 0
+ vfrstpi.b vr4, vr4, 0
+ vshuf.b vr0, vr0, vr0, vr4
+ vshuf.b vr1, vr1, vr1, vr4
+
+ vpickve2gr.bu t0, vr0, 0
+ vpickve2gr.bu t1, vr1, 0
+ sub.d a0, t0, t1
+ jr ra
+
+L(out):
+ move a0, zero
+ jr ra
+ nop
+ nop
+
+
+L(unaligned):
+ xor t2, a0, a1
+ sltu a5, a3, a4
+ masknez t2, t2, a5
+ xor a0, a0, t2
+
+ xor a1, a1, t2
+ andi a3, a0, 0xf
+ andi a4, a1, 0xf
+ bstrins.d a0, zero, 3, 0
+
+ xor a1, a1, a4
+ vld vr4, a0, 0
+ vld vr1, a1, 0
+ li.d t0, 16
+
+ vreplgr2vr.b vr2, a4
+ sub.d a6, a4, a3
+ sub.d t1, t0, a4
+ sub.d t2, t0, a6
+
+
+ vadd.b vr2, vr2, vr5
+ vreplgr2vr.b vr6, t2
+ vadd.b vr6, vr6, vr5
+ vshuf.b vr0, vr4, vr4, vr6
+
+ vshuf.b vr1, vr2, vr1, vr2
+ vshuf.b vr0, vr2, vr0, vr2
+ vseq.b vr7, vr0, vr1
+ bgeu t1, a2, L(un_end)
+
+ vsetanyeqz.b fcc0, vr7
+ bcnez fcc0, L(un_found)
+ sub.d a2, a2, t1
+ andi t1, a2, 31
+
+ beq a2, t1, L(un_less_32bytes)
+ sub.d t2, a2, t1
+ move a2, t1
+ add.d a4, a1, t2
+
+
+L(un_loop):
+ vld vr2, a0, 16
+ vld vr1, a1, 16
+ vld vr3, a1, 32
+ addi.d a1, a1, 32
+
+ addi.d a0, a0, 32
+ vshuf.b vr0, vr2, vr4, vr6
+ vld vr4, a0, 0
+ vseq.b vr7, vr0, vr1
+
+ vshuf.b vr2, vr4, vr2, vr6
+ vseq.b vr8, vr2, vr3
+ vand.v vr8, vr7, vr8
+ vsetanyeqz.b fcc0, vr8
+
+ bcnez fcc0, L(un_pair_end)
+ bne a1, a4, L(un_loop)
+
+L(un_less_32bytes):
+ bltu a2, t0, L(un_less_16bytes)
+ vld vr2, a0, 16
+ vld vr1, a1, 16
+ addi.d a0, a0, 16
+
+ addi.d a1, a1, 16
+ addi.d a2, a2, -16
+ vshuf.b vr0, vr2, vr4, vr6
+ vor.v vr4, vr2, vr2
+
+ vseq.b vr7, vr0, vr1
+ vsetanyeqz.b fcc0, vr7
+ bcnez fcc0, L(un_found)
+L(un_less_16bytes):
+ beqz a2, L(out)
+ vld vr1, a1, 16
+ bgeu a6, a2, 1f
+
+ vld vr2, a0, 16
+1:
+ vshuf.b vr0, vr2, vr4, vr6
+ vseq.b vr7, vr0, vr1
+L(un_end):
+ vreplgr2vr.b vr3, a2
+
+
+ vslt.b vr3, vr5, vr3
+ vorn.v vr7, vr7, vr3
+
+L(un_found):
+ vnori.b vr7, vr7, 0
+ vfrstpi.b vr7, vr7, 0
+
+ vshuf.b vr0, vr0, vr0, vr7
+ vshuf.b vr1, vr1, vr1, vr7
+L(calc_result):
+ vpickve2gr.bu t0, vr0, 0
+ vpickve2gr.bu t1, vr1, 0
+
+ sub.d t2, t0, t1
+ sub.d t3, t1, t0
+ masknez t0, t3, a5
+ maskeqz t1, t2, a5
+
+ or a0, t0, t1
+ jr ra
+L(un_pair_end):
+ vsetanyeqz.b fcc0, vr7
+ bcnez fcc0, L(un_found)
+
+
+ vnori.b vr7, vr8, 0
+ vfrstpi.b vr7, vr7, 0
+ vshuf.b vr0, vr2, vr2, vr7
+ vshuf.b vr1, vr3, vr3, vr7
+
+ b L(calc_result)
+END(MEMCMP)
+
+ .section .rodata.cst16,"M",@progbits,16
+ .align 4
+L(INDEX):
+ .dword 0x0706050403020100
+ .dword 0x0f0e0d0c0b0a0908
+
+libc_hidden_builtin_def (MEMCMP)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/memcmp.c b/sysdeps/loongarch/lp64/multiarch/memcmp.c
new file mode 100644
index 00000000..32eccac2
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memcmp.c
@@ -0,0 +1,43 @@
+/* Multiple versions of memcmp.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define memcmp __redirect_memcmp
+# include <string.h>
+# undef memcmp
+
+# define SYMBOL_NAME memcmp
+# include "ifunc-memcmp.h"
+
+libc_ifunc_redirected (__redirect_memcmp, memcmp,
+ IFUNC_SELECTOR ());
+# undef bcmp
+weak_alias (memcmp, bcmp)
+
+# undef __memcmpeq
+strong_alias (memcmp, __memcmpeq)
+libc_hidden_def (__memcmpeq)
+
+# ifdef SHARED
+__hidden_ver1 (memcmp, __GI_memcmp, __redirect_memcmp)
+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (memcmp);
+# endif
+
+#endif
--
2.33.0

View file

@ -0,0 +1,417 @@
From c4c272fb8067364530a2a78df92c37403acc963f Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Mon, 28 Aug 2023 10:08:37 +0800
Subject: [PATCH 16/29] LoongArch: Add ifunc support for memrchr{lsx, lasx}
According to glibc memrchr microbenchmark, this implementation could reduce
the runtime as following:
Name Percent of rutime reduced
memrchr-lasx 20%-83%
memrchr-lsx 20%-64%
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/lp64/multiarch/Makefile | 3 +
.../lp64/multiarch/ifunc-impl-list.c | 8 ++
.../loongarch/lp64/multiarch/ifunc-memrchr.h | 40 ++++++
.../lp64/multiarch/memrchr-generic.c | 23 ++++
.../loongarch/lp64/multiarch/memrchr-lasx.S | 123 ++++++++++++++++++
.../loongarch/lp64/multiarch/memrchr-lsx.S | 105 +++++++++++++++
sysdeps/loongarch/lp64/multiarch/memrchr.c | 33 +++++
7 files changed, 335 insertions(+)
create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-memrchr.h
create mode 100644 sysdeps/loongarch/lp64/multiarch/memrchr-generic.c
create mode 100644 sysdeps/loongarch/lp64/multiarch/memrchr-lasx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/memrchr-lsx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/memrchr.c
diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile
index 2f4802cf..7b87bc90 100644
--- a/sysdeps/loongarch/lp64/multiarch/Makefile
+++ b/sysdeps/loongarch/lp64/multiarch/Makefile
@@ -27,5 +27,8 @@ sysdep_routines += \
memchr-aligned \
memchr-lsx \
memchr-lasx \
+ memrchr-generic \
+ memrchr-lsx \
+ memrchr-lasx \
# sysdep_routines
endif
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
index a567b9cf..8bd5489e 100644
--- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
@@ -109,5 +109,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
#endif
IFUNC_IMPL_ADD (array, i, memchr, 1, __memchr_aligned)
)
+
+ IFUNC_IMPL (i, name, memrchr,
+#if !defined __loongarch_soft_float
+ IFUNC_IMPL_ADD (array, i, memrchr, SUPPORT_LASX, __memrchr_lasx)
+ IFUNC_IMPL_ADD (array, i, memrchr, SUPPORT_LSX, __memrchr_lsx)
+#endif
+ IFUNC_IMPL_ADD (array, i, memrchr, 1, __memrchr_generic)
+ )
return i;
}
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-memrchr.h b/sysdeps/loongarch/lp64/multiarch/ifunc-memrchr.h
new file mode 100644
index 00000000..8215f9ad
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-memrchr.h
@@ -0,0 +1,40 @@
+/* Common definition for memrchr implementation.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#if !defined __loongarch_soft_float
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden;
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden;
+#endif
+extern __typeof (REDIRECT_NAME) OPTIMIZE (generic) attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+#if !defined __loongarch_soft_float
+ if (SUPPORT_LASX)
+ return OPTIMIZE (lasx);
+ else if (SUPPORT_LSX)
+ return OPTIMIZE (lsx);
+ else
+#endif
+ return OPTIMIZE (generic);
+}
diff --git a/sysdeps/loongarch/lp64/multiarch/memrchr-generic.c b/sysdeps/loongarch/lp64/multiarch/memrchr-generic.c
new file mode 100644
index 00000000..ced61ebc
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memrchr-generic.c
@@ -0,0 +1,23 @@
+/* Generic implementation of memrchr.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#if IS_IN (libc)
+# define MEMRCHR __memrchr_generic
+#endif
+
+#include <string/memrchr.c>
diff --git a/sysdeps/loongarch/lp64/multiarch/memrchr-lasx.S b/sysdeps/loongarch/lp64/multiarch/memrchr-lasx.S
new file mode 100644
index 00000000..5f3e0d06
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memrchr-lasx.S
@@ -0,0 +1,123 @@
+/* Optimized memrchr implementation using LoongArch LASX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+#ifndef MEMRCHR
+# define MEMRCHR __memrchr_lasx
+#endif
+
+LEAF(MEMRCHR, 6)
+ beqz a2, L(ret0)
+ addi.d a2, a2, -1
+ add.d a3, a0, a2
+ andi t1, a3, 0x3f
+
+ bstrins.d a3, zero, 5, 0
+ addi.d t1, t1, 1
+ xvld xr0, a3, 0
+ xvld xr1, a3, 32
+
+ sub.d t2, zero, t1
+ li.d t3, -1
+ xvreplgr2vr.b xr2, a1
+ andi t4, a0, 0x3f
+
+ srl.d t2, t3, t2
+ xvseq.b xr0, xr0, xr2
+ xvseq.b xr1, xr1, xr2
+ xvmsknz.b xr0, xr0
+
+
+ xvmsknz.b xr1, xr1
+ xvpickve.w xr3, xr0, 4
+ xvpickve.w xr4, xr1, 4
+ vilvl.h vr0, vr3, vr0
+
+ vilvl.h vr1, vr4, vr1
+ vilvl.w vr0, vr1, vr0
+ movfr2gr.d t0, fa0
+ and t0, t0, t2
+
+ bltu a2, t1, L(end)
+ bnez t0, L(found)
+ bstrins.d a0, zero, 5, 0
+L(loop):
+ xvld xr0, a3, -64
+
+ xvld xr1, a3, -32
+ addi.d a3, a3, -64
+ xvseq.b xr0, xr0, xr2
+ xvseq.b xr1, xr1, xr2
+
+
+ beq a0, a3, L(out)
+ xvmax.bu xr3, xr0, xr1
+ xvseteqz.v fcc0, xr3
+ bcnez fcc0, L(loop)
+
+ xvmsknz.b xr0, xr0
+ xvmsknz.b xr1, xr1
+ xvpickve.w xr3, xr0, 4
+ xvpickve.w xr4, xr1, 4
+
+ vilvl.h vr0, vr3, vr0
+ vilvl.h vr1, vr4, vr1
+ vilvl.w vr0, vr1, vr0
+ movfr2gr.d t0, fa0
+
+L(found):
+ addi.d a0, a3, 63
+ clz.d t1, t0
+ sub.d a0, a0, t1
+ jr ra
+
+
+L(out):
+ xvmsknz.b xr0, xr0
+ xvmsknz.b xr1, xr1
+ xvpickve.w xr3, xr0, 4
+ xvpickve.w xr4, xr1, 4
+
+ vilvl.h vr0, vr3, vr0
+ vilvl.h vr1, vr4, vr1
+ vilvl.w vr0, vr1, vr0
+ movfr2gr.d t0, fa0
+
+L(end):
+ sll.d t2, t3, t4
+ and t0, t0, t2
+ addi.d a0, a3, 63
+ clz.d t1, t0
+
+ sub.d a0, a0, t1
+ maskeqz a0, a0, t0
+ jr ra
+L(ret0):
+ move a0, zero
+
+
+ jr ra
+END(MEMRCHR)
+
+libc_hidden_builtin_def (MEMRCHR)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/memrchr-lsx.S b/sysdeps/loongarch/lp64/multiarch/memrchr-lsx.S
new file mode 100644
index 00000000..39a7c8b0
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memrchr-lsx.S
@@ -0,0 +1,105 @@
+/* Optimized memrchr implementation using LoongArch LSX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define MEMRCHR __memrchr_lsx
+
+LEAF(MEMRCHR, 6)
+ beqz a2, L(ret0)
+ addi.d a2, a2, -1
+ add.d a3, a0, a2
+ andi t1, a3, 0x1f
+
+ bstrins.d a3, zero, 4, 0
+ addi.d t1, t1, 1
+ vld vr0, a3, 0
+ vld vr1, a3, 16
+
+ sub.d t2, zero, t1
+ li.d t3, -1
+ vreplgr2vr.b vr2, a1
+ andi t4, a0, 0x1f
+
+ srl.d t2, t3, t2
+ vseq.b vr0, vr0, vr2
+ vseq.b vr1, vr1, vr2
+ vmsknz.b vr0, vr0
+
+
+ vmsknz.b vr1, vr1
+ vilvl.h vr0, vr1, vr0
+ movfr2gr.s t0, fa0
+ and t0, t0, t2
+
+ bltu a2, t1, L(end)
+ bnez t0, L(found)
+ bstrins.d a0, zero, 4, 0
+L(loop):
+ vld vr0, a3, -32
+
+ vld vr1, a3, -16
+ addi.d a3, a3, -32
+ vseq.b vr0, vr0, vr2
+ vseq.b vr1, vr1, vr2
+
+ beq a0, a3, L(out)
+ vmax.bu vr3, vr0, vr1
+ vseteqz.v fcc0, vr3
+ bcnez fcc0, L(loop)
+
+
+ vmsknz.b vr0, vr0
+ vmsknz.b vr1, vr1
+ vilvl.h vr0, vr1, vr0
+ movfr2gr.s t0, fa0
+
+L(found):
+ addi.d a0, a3, 31
+ clz.w t1, t0
+ sub.d a0, a0, t1
+ jr ra
+
+L(out):
+ vmsknz.b vr0, vr0
+ vmsknz.b vr1, vr1
+ vilvl.h vr0, vr1, vr0
+ movfr2gr.s t0, fa0
+
+L(end):
+ sll.d t2, t3, t4
+ and t0, t0, t2
+ addi.d a0, a3, 31
+ clz.w t1, t0
+
+
+ sub.d a0, a0, t1
+ maskeqz a0, a0, t0
+ jr ra
+L(ret0):
+ move a0, zero
+
+ jr ra
+END(MEMRCHR)
+
+libc_hidden_builtin_def (MEMRCHR)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/memrchr.c b/sysdeps/loongarch/lp64/multiarch/memrchr.c
new file mode 100644
index 00000000..8baba9ab
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memrchr.c
@@ -0,0 +1,33 @@
+/* Multiple versions of memrchr.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define memrchr __redirect_memrchr
+# include <string.h>
+# undef memrchr
+
+# define SYMBOL_NAME memrchr
+# include "ifunc-memrchr.h"
+
+libc_ifunc_redirected (__redirect_memrchr, __memrchr, IFUNC_SELECTOR ());
+libc_hidden_def (__memrchr)
+weak_alias (__memrchr, memrchr)
+
+#endif
--
2.33.0

View file

@ -0,0 +1,784 @@
From 14032f7bbe18443af8492f5d0365f72b76701673 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Mon, 28 Aug 2023 10:08:38 +0800
Subject: [PATCH 17/29] LoongArch: Add ifunc support for memset{aligned,
unaligned, lsx, lasx}
According to glibc memset microbenchmark test results, for LSX and LASX
versions, A few cases with length less than 8 experience performace
degradation, overall, the LASX version could reduce the runtime about
15% - 75%, LSX version could reduce the runtime about 15%-50%.
The unaligned version uses unaligned memmory access to set data which
length is less than 64 and make address aligned with 8. For this part,
the performace is better than aligned version. Comparing with the generic
version, the performance is close when the length is larger than 128. When
the length is 8-128, the unaligned version could reduce the runtime about
30%-70%, the aligned version could reduce the runtime about 20%-50%.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/lp64/multiarch/Makefile | 4 +
.../lp64/multiarch/dl-symbol-redir-ifunc.h | 24 +++
.../lp64/multiarch/ifunc-impl-list.c | 10 +
.../loongarch/lp64/multiarch/memset-aligned.S | 174 ++++++++++++++++++
.../loongarch/lp64/multiarch/memset-lasx.S | 142 ++++++++++++++
sysdeps/loongarch/lp64/multiarch/memset-lsx.S | 135 ++++++++++++++
.../lp64/multiarch/memset-unaligned.S | 162 ++++++++++++++++
sysdeps/loongarch/lp64/multiarch/memset.c | 37 ++++
8 files changed, 688 insertions(+)
create mode 100644 sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h
create mode 100644 sysdeps/loongarch/lp64/multiarch/memset-aligned.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/memset-lasx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/memset-lsx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/memset-unaligned.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/memset.c
diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile
index 7b87bc90..216886c5 100644
--- a/sysdeps/loongarch/lp64/multiarch/Makefile
+++ b/sysdeps/loongarch/lp64/multiarch/Makefile
@@ -30,5 +30,9 @@ sysdep_routines += \
memrchr-generic \
memrchr-lsx \
memrchr-lasx \
+ memset-aligned \
+ memset-unaligned \
+ memset-lsx \
+ memset-lasx \
# sysdep_routines
endif
diff --git a/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h b/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h
new file mode 100644
index 00000000..e2723873
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/dl-symbol-redir-ifunc.h
@@ -0,0 +1,24 @@
+/* Symbol rediretion for loader/static initialization code.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _DL_IFUNC_GENERIC_H
+#define _DL_IFUNC_GENERIC_H
+
+asm ("memset = __memset_aligned");
+
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
index 8bd5489e..37f60dde 100644
--- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
@@ -117,5 +117,15 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
#endif
IFUNC_IMPL_ADD (array, i, memrchr, 1, __memrchr_generic)
)
+
+ IFUNC_IMPL (i, name, memset,
+#if !defined __loongarch_soft_float
+ IFUNC_IMPL_ADD (array, i, memset, SUPPORT_LASX, __memset_lasx)
+ IFUNC_IMPL_ADD (array, i, memset, SUPPORT_LSX, __memset_lsx)
+#endif
+ IFUNC_IMPL_ADD (array, i, memset, SUPPORT_UAL, __memset_unaligned)
+ IFUNC_IMPL_ADD (array, i, memset, 1, __memset_aligned)
+ )
+
return i;
}
diff --git a/sysdeps/loongarch/lp64/multiarch/memset-aligned.S b/sysdeps/loongarch/lp64/multiarch/memset-aligned.S
new file mode 100644
index 00000000..1fce95b7
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memset-aligned.S
@@ -0,0 +1,174 @@
+/* Optimized memset aligned implementation using basic LoongArch instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc)
+# define MEMSET_NAME __memset_aligned
+#else
+# define MEMSET_NAME memset
+#endif
+
+LEAF(MEMSET_NAME, 6)
+ move t0, a0
+ andi a3, a0, 0x7
+ li.w t6, 16
+ beqz a3, L(align)
+ bltu a2, t6, L(short_data)
+
+L(make_align):
+ li.w t8, 8
+ sub.d t2, t8, a3
+ pcaddi t1, 11
+ slli.d t3, t2, 2
+ sub.d t1, t1, t3
+ jr t1
+
+L(al7):
+ st.b a1, t0, 6
+L(al6):
+ st.b a1, t0, 5
+L(al5):
+ st.b a1, t0, 4
+L(al4):
+ st.b a1, t0, 3
+L(al3):
+ st.b a1, t0, 2
+L(al2):
+ st.b a1, t0, 1
+L(al1):
+ st.b a1, t0, 0
+L(al0):
+ add.d t0, t0, t2
+ sub.d a2, a2, t2
+
+L(align):
+ bstrins.d a1, a1, 15, 8
+ bstrins.d a1, a1, 31, 16
+ bstrins.d a1, a1, 63, 32
+ bltu a2, t6, L(less_16bytes)
+
+ andi a4, a2, 0x3f
+ beq a4, a2, L(less_64bytes)
+
+ sub.d t1, a2, a4
+ move a2, a4
+ add.d a5, t0, t1
+
+L(loop_64bytes):
+ addi.d t0, t0, 64
+ st.d a1, t0, -64
+ st.d a1, t0, -56
+ st.d a1, t0, -48
+ st.d a1, t0, -40
+
+ st.d a1, t0, -32
+ st.d a1, t0, -24
+ st.d a1, t0, -16
+ st.d a1, t0, -8
+ bne t0, a5, L(loop_64bytes)
+
+L(less_64bytes):
+ srai.d a4, a2, 5
+ beqz a4, L(less_32bytes)
+ addi.d a2, a2, -32
+ st.d a1, t0, 0
+
+ st.d a1, t0, 8
+ st.d a1, t0, 16
+ st.d a1, t0, 24
+ addi.d t0, t0, 32
+
+L(less_32bytes):
+ bltu a2, t6, L(less_16bytes)
+ addi.d a2, a2, -16
+ st.d a1, t0, 0
+ st.d a1, t0, 8
+ addi.d t0, t0, 16
+
+L(less_16bytes):
+ srai.d a4, a2, 3
+ beqz a4, L(less_8bytes)
+ addi.d a2, a2, -8
+ st.d a1, t0, 0
+ addi.d t0, t0, 8
+
+L(less_8bytes):
+ beqz a2, L(less_1byte)
+ srai.d a4, a2, 2
+ beqz a4, L(less_4bytes)
+ addi.d a2, a2, -4
+ st.w a1, t0, 0
+ addi.d t0, t0, 4
+
+L(less_4bytes):
+ srai.d a3, a2, 1
+ beqz a3, L(less_2bytes)
+ addi.d a2, a2, -2
+ st.h a1, t0, 0
+ addi.d t0, t0, 2
+
+L(less_2bytes):
+ beqz a2, L(less_1byte)
+ st.b a1, t0, 0
+L(less_1byte):
+ jr ra
+
+L(short_data):
+ pcaddi t1, 19
+ slli.d t3, a2, 2
+ sub.d t1, t1, t3
+ jr t1
+L(short_15):
+ st.b a1, a0, 14
+L(short_14):
+ st.b a1, a0, 13
+L(short_13):
+ st.b a1, a0, 12
+L(short_12):
+ st.b a1, a0, 11
+L(short_11):
+ st.b a1, a0, 10
+L(short_10):
+ st.b a1, a0, 9
+L(short_9):
+ st.b a1, a0, 8
+L(short_8):
+ st.b a1, a0, 7
+L(short_7):
+ st.b a1, a0, 6
+L(short_6):
+ st.b a1, a0, 5
+L(short_5):
+ st.b a1, a0, 4
+L(short_4):
+ st.b a1, a0, 3
+L(short_3):
+ st.b a1, a0, 2
+L(short_2):
+ st.b a1, a0, 1
+L(short_1):
+ st.b a1, a0, 0
+L(short_0):
+ jr ra
+END(MEMSET_NAME)
+
+libc_hidden_builtin_def (MEMSET_NAME)
diff --git a/sysdeps/loongarch/lp64/multiarch/memset-lasx.S b/sysdeps/loongarch/lp64/multiarch/memset-lasx.S
new file mode 100644
index 00000000..041abbac
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memset-lasx.S
@@ -0,0 +1,142 @@
+/* Optimized memset implementation using LoongArch LASX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define MEMSET __memset_lasx
+
+LEAF(MEMSET, 6)
+ li.d t1, 32
+ move a3, a0
+ xvreplgr2vr.b xr0, a1
+ add.d a4, a0, a2
+
+ bgeu t1, a2, L(less_32bytes)
+ li.d t3, 128
+ li.d t2, 64
+ blt t3, a2, L(long_bytes)
+
+L(less_128bytes):
+ bgeu t2, a2, L(less_64bytes)
+ xvst xr0, a3, 0
+ xvst xr0, a3, 32
+ xvst xr0, a4, -32
+
+ xvst xr0, a4, -64
+ jr ra
+L(less_64bytes):
+ xvst xr0, a3, 0
+ xvst xr0, a4, -32
+
+
+ jr ra
+L(less_32bytes):
+ srli.d t0, a2, 4
+ beqz t0, L(less_16bytes)
+ vst vr0, a3, 0
+
+ vst vr0, a4, -16
+ jr ra
+L(less_16bytes):
+ srli.d t0, a2, 3
+ beqz t0, L(less_8bytes)
+
+ vstelm.d vr0, a3, 0, 0
+ vstelm.d vr0, a4, -8, 0
+ jr ra
+L(less_8bytes):
+ srli.d t0, a2, 2
+
+ beqz t0, L(less_4bytes)
+ vstelm.w vr0, a3, 0, 0
+ vstelm.w vr0, a4, -4, 0
+ jr ra
+
+
+L(less_4bytes):
+ srli.d t0, a2, 1
+ beqz t0, L(less_2bytes)
+ vstelm.h vr0, a3, 0, 0
+ vstelm.h vr0, a4, -2, 0
+
+ jr ra
+L(less_2bytes):
+ beqz a2, L(less_1bytes)
+ st.b a1, a3, 0
+L(less_1bytes):
+ jr ra
+
+L(long_bytes):
+ xvst xr0, a3, 0
+ bstrins.d a3, zero, 4, 0
+ addi.d a3, a3, 32
+ sub.d a2, a4, a3
+
+ andi t0, a2, 0xff
+ beq t0, a2, L(long_end)
+ move a2, t0
+ sub.d t0, a4, t0
+
+
+L(loop_256):
+ xvst xr0, a3, 0
+ xvst xr0, a3, 32
+ xvst xr0, a3, 64
+ xvst xr0, a3, 96
+
+ xvst xr0, a3, 128
+ xvst xr0, a3, 160
+ xvst xr0, a3, 192
+ xvst xr0, a3, 224
+
+ addi.d a3, a3, 256
+ bne a3, t0, L(loop_256)
+L(long_end):
+ bltu a2, t3, L(end_less_128)
+ addi.d a2, a2, -128
+
+ xvst xr0, a3, 0
+ xvst xr0, a3, 32
+ xvst xr0, a3, 64
+ xvst xr0, a3, 96
+
+
+ addi.d a3, a3, 128
+L(end_less_128):
+ bltu a2, t2, L(end_less_64)
+ addi.d a2, a2, -64
+ xvst xr0, a3, 0
+
+ xvst xr0, a3, 32
+ addi.d a3, a3, 64
+L(end_less_64):
+ bltu a2, t1, L(end_less_32)
+ xvst xr0, a3, 0
+
+L(end_less_32):
+ xvst xr0, a4, -32
+ jr ra
+END(MEMSET)
+
+libc_hidden_builtin_def (MEMSET)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/memset-lsx.S b/sysdeps/loongarch/lp64/multiarch/memset-lsx.S
new file mode 100644
index 00000000..3d3982aa
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memset-lsx.S
@@ -0,0 +1,135 @@
+/* Optimized memset implementation using LoongArch LSX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define MEMSET __memset_lsx
+
+LEAF(MEMSET, 6)
+ li.d t1, 16
+ move a3, a0
+ vreplgr2vr.b vr0, a1
+ add.d a4, a0, a2
+
+ bgeu t1, a2, L(less_16bytes)
+ li.d t3, 64
+ li.d t2, 32
+ bgeu a2, t3, L(long_bytes)
+
+L(less_64bytes):
+ bgeu t2, a2, L(less_32bytes)
+ vst vr0, a3, 0
+ vst vr0, a3, 16
+ vst vr0, a4, -32
+
+ vst vr0, a4, -16
+ jr ra
+L(less_32bytes):
+ vst vr0, a3, 0
+ vst vr0, a4, -16
+
+
+ jr ra
+L(less_16bytes):
+ srli.d t0, a2, 3
+ beqz t0, L(less_8bytes)
+ vstelm.d vr0, a3, 0, 0
+
+ vstelm.d vr0, a4, -8, 0
+ jr ra
+L(less_8bytes):
+ srli.d t0, a2, 2
+ beqz t0, L(less_4bytes)
+
+ vstelm.w vr0, a3, 0, 0
+ vstelm.w vr0, a4, -4, 0
+ jr ra
+L(less_4bytes):
+ srli.d t0, a2, 1
+
+ beqz t0, L(less_2bytes)
+ vstelm.h vr0, a3, 0, 0
+ vstelm.h vr0, a4, -2, 0
+ jr ra
+
+
+L(less_2bytes):
+ beqz a2, L(less_1bytes)
+ vstelm.b vr0, a3, 0, 0
+L(less_1bytes):
+ jr ra
+L(long_bytes):
+ vst vr0, a3, 0
+
+ bstrins.d a3, zero, 3, 0
+ addi.d a3, a3, 16
+ sub.d a2, a4, a3
+ andi t0, a2, 0x7f
+
+ beq t0, a2, L(long_end)
+ move a2, t0
+ sub.d t0, a4, t0
+
+L(loop_128):
+ vst vr0, a3, 0
+
+ vst vr0, a3, 16
+ vst vr0, a3, 32
+ vst vr0, a3, 48
+ vst vr0, a3, 64
+
+
+ vst vr0, a3, 80
+ vst vr0, a3, 96
+ vst vr0, a3, 112
+ addi.d a3, a3, 128
+
+ bne a3, t0, L(loop_128)
+L(long_end):
+ bltu a2, t3, L(end_less_64)
+ addi.d a2, a2, -64
+ vst vr0, a3, 0
+
+ vst vr0, a3, 16
+ vst vr0, a3, 32
+ vst vr0, a3, 48
+ addi.d a3, a3, 64
+
+L(end_less_64):
+ bltu a2, t2, L(end_less_32)
+ addi.d a2, a2, -32
+ vst vr0, a3, 0
+ vst vr0, a3, 16
+
+ addi.d a3, a3, 32
+L(end_less_32):
+ bltu a2, t1, L(end_less_16)
+ vst vr0, a3, 0
+
+L(end_less_16):
+ vst vr0, a4, -16
+ jr ra
+END(MEMSET)
+
+libc_hidden_builtin_def (MEMSET)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/memset-unaligned.S b/sysdeps/loongarch/lp64/multiarch/memset-unaligned.S
new file mode 100644
index 00000000..f7d32039
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memset-unaligned.S
@@ -0,0 +1,162 @@
+/* Optimized memset unaligned implementation using basic LoongArch instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc)
+
+# define MEMSET_NAME __memset_unaligned
+
+#define ST_128(n) \
+ st.d a1, a0, n; \
+ st.d a1, a0, n+8 ; \
+ st.d a1, a0, n+16 ; \
+ st.d a1, a0, n+24 ; \
+ st.d a1, a0, n+32 ; \
+ st.d a1, a0, n+40 ; \
+ st.d a1, a0, n+48 ; \
+ st.d a1, a0, n+56 ; \
+ st.d a1, a0, n+64 ; \
+ st.d a1, a0, n+72 ; \
+ st.d a1, a0, n+80 ; \
+ st.d a1, a0, n+88 ; \
+ st.d a1, a0, n+96 ; \
+ st.d a1, a0, n+104; \
+ st.d a1, a0, n+112; \
+ st.d a1, a0, n+120;
+
+LEAF(MEMSET_NAME, 6)
+ bstrins.d a1, a1, 15, 8
+ add.d t7, a0, a2
+ bstrins.d a1, a1, 31, 16
+ move t0, a0
+
+ bstrins.d a1, a1, 63, 32
+ srai.d t8, a2, 4
+ beqz t8, L(less_16bytes)
+ srai.d t8, a2, 6
+
+ bnez t8, L(more_64bytes)
+ srai.d t8, a2, 5
+ beqz t8, L(less_32bytes)
+
+ st.d a1, a0, 0
+ st.d a1, a0, 8
+ st.d a1, a0, 16
+ st.d a1, a0, 24
+
+ st.d a1, t7, -32
+ st.d a1, t7, -24
+ st.d a1, t7, -16
+ st.d a1, t7, -8
+
+ jr ra
+
+L(less_32bytes):
+ st.d a1, a0, 0
+ st.d a1, a0, 8
+ st.d a1, t7, -16
+ st.d a1, t7, -8
+
+ jr ra
+
+L(less_16bytes):
+ srai.d t8, a2, 3
+ beqz t8, L(less_8bytes)
+ st.d a1, a0, 0
+ st.d a1, t7, -8
+
+ jr ra
+
+L(less_8bytes):
+ srai.d t8, a2, 2
+ beqz t8, L(less_4bytes)
+ st.w a1, a0, 0
+ st.w a1, t7, -4
+
+ jr ra
+
+L(less_4bytes):
+ srai.d t8, a2, 1
+ beqz t8, L(less_2bytes)
+ st.h a1, a0, 0
+ st.h a1, t7, -2
+
+ jr ra
+
+L(less_2bytes):
+ beqz a2, L(less_1bytes)
+ st.b a1, a0, 0
+
+ jr ra
+
+L(less_1bytes):
+ jr ra
+
+L(more_64bytes):
+ srli.d a0, a0, 3
+ slli.d a0, a0, 3
+ addi.d a0, a0, 0x8
+ st.d a1, t0, 0
+
+ sub.d t2, t0, a0
+ add.d a2, t2, a2
+ addi.d a2, a2, -0x80
+ blt a2, zero, L(end_unalign_proc)
+
+L(loop_less):
+ ST_128(0)
+ addi.d a0, a0, 0x80
+ addi.d a2, a2, -0x80
+ bge a2, zero, L(loop_less)
+
+L(end_unalign_proc):
+ addi.d a2, a2, 0x80
+ pcaddi t1, 20
+ andi t5, a2, 0x78
+ srli.d t5, t5, 1
+
+ sub.d t1, t1, t5
+ jr t1
+
+ st.d a1, a0, 112
+ st.d a1, a0, 104
+ st.d a1, a0, 96
+ st.d a1, a0, 88
+ st.d a1, a0, 80
+ st.d a1, a0, 72
+ st.d a1, a0, 64
+ st.d a1, a0, 56
+ st.d a1, a0, 48
+ st.d a1, a0, 40
+ st.d a1, a0, 32
+ st.d a1, a0, 24
+ st.d a1, a0, 16
+ st.d a1, a0, 8
+ st.d a1, a0, 0
+ st.d a1, t7, -8
+
+ move a0, t0
+ jr ra
+END(MEMSET_NAME)
+
+libc_hidden_builtin_def (MEMSET_NAME)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/memset.c b/sysdeps/loongarch/lp64/multiarch/memset.c
new file mode 100644
index 00000000..3ff60d8a
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/memset.c
@@ -0,0 +1,37 @@
+/* Multiple versions of memset.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define memset __redirect_memset
+# include <string.h>
+# undef memset
+
+# define SYMBOL_NAME memset
+# include "ifunc-lasx.h"
+
+libc_ifunc_redirected (__redirect_memset, memset,
+ IFUNC_SELECTOR ());
+
+# ifdef SHARED
+__hidden_ver1 (memset, __GI_memset, __redirect_memset)
+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (memset);
+# endif
+
+#endif
--
2.33.0

View file

@ -0,0 +1,448 @@
From b412bcb2cf4914a664bcd24924d670a2e37394b3 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Mon, 28 Aug 2023 10:08:35 +0800
Subject: [PATCH 14/29] LoongArch: Add ifunc support for rawmemchr{aligned,
lsx, lasx}
According to glibc rawmemchr microbenchmark, A few cases tested with
char '\0' experience performance degradation due to the lasx and lsx
versions don't handle the '\0' separately. Overall, rawmemchr-lasx
implementation could reduce the runtime about 40%-80%, rawmemchr-lsx
implementation could reduce the runtime about 40%-66%, rawmemchr-aligned
implementation could reduce the runtime about 20%-40%.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/lp64/multiarch/Makefile | 3 +
.../lp64/multiarch/ifunc-impl-list.c | 8 ++
.../lp64/multiarch/ifunc-rawmemchr.h | 40 ++++++
.../lp64/multiarch/rawmemchr-aligned.S | 124 ++++++++++++++++++
.../loongarch/lp64/multiarch/rawmemchr-lasx.S | 82 ++++++++++++
.../loongarch/lp64/multiarch/rawmemchr-lsx.S | 71 ++++++++++
sysdeps/loongarch/lp64/multiarch/rawmemchr.c | 37 ++++++
7 files changed, 365 insertions(+)
create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-rawmemchr.h
create mode 100644 sysdeps/loongarch/lp64/multiarch/rawmemchr-aligned.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/rawmemchr-lasx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/rawmemchr-lsx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/rawmemchr.c
diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile
index 5d7ae7ae..64416b02 100644
--- a/sysdeps/loongarch/lp64/multiarch/Makefile
+++ b/sysdeps/loongarch/lp64/multiarch/Makefile
@@ -21,5 +21,8 @@ sysdep_routines += \
memmove-unaligned \
memmove-lsx \
memmove-lasx \
+ rawmemchr-aligned \
+ rawmemchr-lsx \
+ rawmemchr-lasx \
# sysdep_routines
endif
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
index c8ba87bd..3db9af14 100644
--- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
@@ -94,5 +94,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_aligned)
)
+ IFUNC_IMPL (i, name, rawmemchr,
+#if !defined __loongarch_soft_float
+ IFUNC_IMPL_ADD (array, i, rawmemchr, SUPPORT_LASX, __rawmemchr_lasx)
+ IFUNC_IMPL_ADD (array, i, rawmemchr, SUPPORT_LSX, __rawmemchr_lsx)
+#endif
+ IFUNC_IMPL_ADD (array, i, rawmemchr, 1, __rawmemchr_aligned)
+ )
+
return i;
}
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-rawmemchr.h b/sysdeps/loongarch/lp64/multiarch/ifunc-rawmemchr.h
new file mode 100644
index 00000000..a7bb4cf9
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-rawmemchr.h
@@ -0,0 +1,40 @@
+/* Common definition for rawmemchr ifunc selections.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#if !defined __loongarch_soft_float
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden;
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden;
+#endif
+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+#if !defined __loongarch_soft_float
+ if (SUPPORT_LASX)
+ return OPTIMIZE (lasx);
+ else if (SUPPORT_LSX)
+ return OPTIMIZE (lsx);
+ else
+#endif
+ return OPTIMIZE (aligned);
+}
diff --git a/sysdeps/loongarch/lp64/multiarch/rawmemchr-aligned.S b/sysdeps/loongarch/lp64/multiarch/rawmemchr-aligned.S
new file mode 100644
index 00000000..9c7155ae
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/rawmemchr-aligned.S
@@ -0,0 +1,124 @@
+/* Optimized rawmemchr implementation using basic LoongArch instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc)
+# define RAWMEMCHR_NAME __rawmemchr_aligned
+#else
+# define RAWMEMCHR_NAME __rawmemchr
+#endif
+
+LEAF(RAWMEMCHR_NAME, 6)
+ andi t1, a0, 0x7
+ bstrins.d a0, zero, 2, 0
+ lu12i.w a2, 0x01010
+ bstrins.d a1, a1, 15, 8
+
+ ld.d t0, a0, 0
+ slli.d t1, t1, 3
+ ori a2, a2, 0x101
+ bstrins.d a1, a1, 31, 16
+
+ li.w t8, -1
+ bstrins.d a1, a1, 63, 32
+ bstrins.d a2, a2, 63, 32
+ sll.d t2, t8, t1
+
+ sll.d t3, a1, t1
+ orn t0, t0, t2
+ slli.d a3, a2, 7
+ beqz a1, L(find_zero)
+
+ xor t0, t0, t3
+ sub.d t1, t0, a2
+ andn t2, a3, t0
+ and t3, t1, t2
+
+ bnez t3, L(count_pos)
+ addi.d a0, a0, 8
+
+L(loop):
+ ld.d t0, a0, 0
+ xor t0, t0, a1
+
+ sub.d t1, t0, a2
+ andn t2, a3, t0
+ and t3, t1, t2
+ bnez t3, L(count_pos)
+
+ ld.d t0, a0, 8
+ addi.d a0, a0, 16
+ xor t0, t0, a1
+ sub.d t1, t0, a2
+
+ andn t2, a3, t0
+ and t3, t1, t2
+ beqz t3, L(loop)
+ addi.d a0, a0, -8
+L(count_pos):
+ ctz.d t0, t3
+ srli.d t0, t0, 3
+ add.d a0, a0, t0
+ jr ra
+
+L(loop_7bit):
+ ld.d t0, a0, 0
+L(find_zero):
+ sub.d t1, t0, a2
+ and t2, t1, a3
+ bnez t2, L(more_check)
+
+ ld.d t0, a0, 8
+ addi.d a0, a0, 16
+ sub.d t1, t0, a2
+ and t2, t1, a3
+
+ beqz t2, L(loop_7bit)
+ addi.d a0, a0, -8
+
+L(more_check):
+ andn t2, a3, t0
+ and t3, t1, t2
+ bnez t3, L(count_pos)
+ addi.d a0, a0, 8
+
+L(loop_8bit):
+ ld.d t0, a0, 0
+
+ sub.d t1, t0, a2
+ andn t2, a3, t0
+ and t3, t1, t2
+ bnez t3, L(count_pos)
+
+ ld.d t0, a0, 8
+ addi.d a0, a0, 16
+ sub.d t1, t0, a2
+
+ andn t2, a3, t0
+ and t3, t1, t2
+ beqz t3, L(loop_8bit)
+
+ addi.d a0, a0, -8
+ b L(count_pos)
+
+END(RAWMEMCHR_NAME)
+
+libc_hidden_builtin_def (__rawmemchr)
diff --git a/sysdeps/loongarch/lp64/multiarch/rawmemchr-lasx.S b/sysdeps/loongarch/lp64/multiarch/rawmemchr-lasx.S
new file mode 100644
index 00000000..be2eb59d
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/rawmemchr-lasx.S
@@ -0,0 +1,82 @@
+/* Optimized rawmemchr implementation using LoongArch LASX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/asm.h>
+#include <sys/regdef.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define RAWMEMCHR __rawmemchr_lasx
+
+LEAF(RAWMEMCHR, 6)
+ move a2, a0
+ bstrins.d a0, zero, 5, 0
+ xvld xr0, a0, 0
+ xvld xr1, a0, 32
+
+ xvreplgr2vr.b xr2, a1
+ xvseq.b xr0, xr0, xr2
+ xvseq.b xr1, xr1, xr2
+ xvmsknz.b xr0, xr0
+
+ xvmsknz.b xr1, xr1
+ xvpickve.w xr3, xr0, 4
+ xvpickve.w xr4, xr1, 4
+ vilvl.h vr0, vr3, vr0
+
+ vilvl.h vr1, vr4, vr1
+ vilvl.w vr0, vr1, vr0
+ movfr2gr.d t0, fa0
+ sra.d t0, t0, a2
+
+
+ beqz t0, L(loop)
+ ctz.d t0, t0
+ add.d a0, a2, t0
+ jr ra
+
+L(loop):
+ xvld xr0, a0, 64
+ xvld xr1, a0, 96
+ addi.d a0, a0, 64
+ xvseq.b xr0, xr0, xr2
+
+ xvseq.b xr1, xr1, xr2
+ xvmax.bu xr3, xr0, xr1
+ xvseteqz.v fcc0, xr3
+ bcnez fcc0, L(loop)
+
+ xvmsknz.b xr0, xr0
+ xvmsknz.b xr1, xr1
+ xvpickve.w xr3, xr0, 4
+ xvpickve.w xr4, xr1, 4
+
+
+ vilvl.h vr0, vr3, vr0
+ vilvl.h vr1, vr4, vr1
+ vilvl.w vr0, vr1, vr0
+ movfr2gr.d t0, fa0
+
+ ctz.d t0, t0
+ add.d a0, a0, t0
+ jr ra
+END(RAWMEMCHR)
+
+libc_hidden_builtin_def (RAWMEMCHR)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/rawmemchr-lsx.S b/sysdeps/loongarch/lp64/multiarch/rawmemchr-lsx.S
new file mode 100644
index 00000000..2f6fe024
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/rawmemchr-lsx.S
@@ -0,0 +1,71 @@
+/* Optimized rawmemchr implementation using LoongArch LSX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define RAWMEMCHR __rawmemchr_lsx
+
+LEAF(RAWMEMCHR, 6)
+ move a2, a0
+ bstrins.d a0, zero, 4, 0
+ vld vr0, a0, 0
+ vld vr1, a0, 16
+
+ vreplgr2vr.b vr2, a1
+ vseq.b vr0, vr0, vr2
+ vseq.b vr1, vr1, vr2
+ vmsknz.b vr0, vr0
+
+ vmsknz.b vr1, vr1
+ vilvl.h vr0, vr1, vr0
+ movfr2gr.s t0, fa0
+ sra.w t0, t0, a2
+
+ beqz t0, L(loop)
+ ctz.w t0, t0
+ add.d a0, a2, t0
+ jr ra
+
+
+L(loop):
+ vld vr0, a0, 32
+ vld vr1, a0, 48
+ addi.d a0, a0, 32
+ vseq.b vr0, vr0, vr2
+
+ vseq.b vr1, vr1, vr2
+ vmax.bu vr3, vr0, vr1
+ vseteqz.v fcc0, vr3
+ bcnez fcc0, L(loop)
+
+ vmsknz.b vr0, vr0
+ vmsknz.b vr1, vr1
+ vilvl.h vr0, vr1, vr0
+ movfr2gr.s t0, fa0
+
+ ctz.w t0, t0
+ add.d a0, a0, t0
+ jr ra
+END(RAWMEMCHR)
+
+libc_hidden_builtin_def (RAWMEMCHR)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/rawmemchr.c b/sysdeps/loongarch/lp64/multiarch/rawmemchr.c
new file mode 100644
index 00000000..89c7ffff
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/rawmemchr.c
@@ -0,0 +1,37 @@
+/* Multiple versions of rawmemchr.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#if IS_IN (libc)
+# define rawmemchr __redirect_rawmemchr
+# define __rawmemchr __redirect___rawmemchr
+# include <string.h>
+# undef rawmemchr
+# undef __rawmemchr
+
+# define SYMBOL_NAME rawmemchr
+# include "ifunc-rawmemchr.h"
+
+libc_ifunc_redirected (__redirect_rawmemchr, __rawmemchr,
+ IFUNC_SELECTOR ());
+weak_alias (__rawmemchr, rawmemchr)
+# ifdef SHARED
+__hidden_ver1 (__rawmemchr, __GI___rawmemchr, __redirect___rawmemchr)
+ __attribute__((visibility ("hidden")));
+# endif
+#endif
--
2.33.0

View file

@ -0,0 +1,499 @@
From e258cfcf92f5e31e902fa045b41652f00fcf2521 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Thu, 24 Aug 2023 16:50:18 +0800
Subject: [PATCH 09/29] LoongArch: Add ifunc support for strcmp{aligned, lsx}
Based on the glibc microbenchmark, strcmp-aligned implementation could
reduce the runtime 0%-10% for aligned comparison, 10%-20% for unaligned
comparison, strcmp-lsx implemenation could reduce the runtime 0%-50%.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/lp64/multiarch/Makefile | 2 +
.../lp64/multiarch/ifunc-impl-list.c | 7 +
.../loongarch/lp64/multiarch/ifunc-strcmp.h | 38 ++++
.../loongarch/lp64/multiarch/strcmp-aligned.S | 179 ++++++++++++++++++
sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S | 165 ++++++++++++++++
sysdeps/loongarch/lp64/multiarch/strcmp.c | 35 ++++
6 files changed, 426 insertions(+)
create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-strcmp.h
create mode 100644 sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/strcmp.c
diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile
index c4dd3143..d5a500de 100644
--- a/sysdeps/loongarch/lp64/multiarch/Makefile
+++ b/sysdeps/loongarch/lp64/multiarch/Makefile
@@ -12,6 +12,8 @@ sysdep_routines += \
strchrnul-aligned \
strchrnul-lsx \
strchrnul-lasx \
+ strcmp-aligned \
+ strcmp-lsx \
memcpy-aligned \
memcpy-unaligned \
memmove-unaligned \
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
index 7cec0b77..9183b7da 100644
--- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
@@ -62,6 +62,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
IFUNC_IMPL_ADD (array, i, strchrnul, 1, __strchrnul_aligned)
)
+ IFUNC_IMPL (i, name, strcmp,
+#if !defined __loongarch_soft_float
+ IFUNC_IMPL_ADD (array, i, strcmp, SUPPORT_LSX, __strcmp_lsx)
+#endif
+ IFUNC_IMPL_ADD (array, i, strcmp, 1, __strcmp_aligned)
+ )
+
IFUNC_IMPL (i, name, memcpy,
#if !defined __loongarch_soft_float
IFUNC_IMPL_ADD (array, i, memcpy, SUPPORT_LASX, __memcpy_lasx)
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-strcmp.h b/sysdeps/loongarch/lp64/multiarch/ifunc-strcmp.h
new file mode 100644
index 00000000..ca26352b
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-strcmp.h
@@ -0,0 +1,38 @@
+/* Common definition for strcmp ifunc selection.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#if !defined __loongarch_soft_float
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden;
+#endif
+
+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+#if !defined __loongarch_soft_float
+ if (SUPPORT_LSX)
+ return OPTIMIZE (lsx);
+ else
+#endif
+ return OPTIMIZE (aligned);
+}
diff --git a/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S b/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S
new file mode 100644
index 00000000..f5f4f336
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S
@@ -0,0 +1,179 @@
+/* Optimized strcmp implementation using basic Loongarch instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc)
+# define STRCMP_NAME __strcmp_aligned
+#else
+# define STRCMP_NAME strcmp
+#endif
+
+LEAF(STRCMP_NAME, 6)
+ lu12i.w a4, 0x01010
+ andi a2, a0, 0x7
+ ori a4, a4, 0x101
+ andi a3, a1, 0x7
+
+ bstrins.d a4, a4, 63, 32
+ li.d t7, -1
+ li.d t8, 8
+ slli.d a5, a4, 7
+
+ bne a2, a3, L(unaligned)
+ bstrins.d a0, zero, 2, 0
+ bstrins.d a1, zero, 2, 0
+ ld.d t0, a0, 0
+
+ ld.d t1, a1, 0
+ slli.d t3, a2, 3
+ sll.d t2, t7, t3
+ orn t0, t0, t2
+
+
+ orn t1, t1, t2
+ sub.d t2, t0, a4
+ andn t3, a5, t0
+ and t2, t2, t3
+
+ bne t0, t1, L(al_end)
+L(al_loop):
+ bnez t2, L(ret0)
+ ldx.d t0, a0, t8
+ ldx.d t1, a1, t8
+
+ addi.d t8, t8, 8
+ sub.d t2, t0, a4
+ andn t3, a5, t0
+ and t2, t2, t3
+
+ beq t0, t1, L(al_loop)
+L(al_end):
+ xor t3, t0, t1
+ or t2, t2, t3
+ ctz.d t3, t2
+
+
+ bstrins.d t3, zero, 2, 0
+ srl.d t0, t0, t3
+ srl.d t1, t1, t3
+ andi t0, t0, 0xff
+
+ andi t1, t1, 0xff
+ sub.d a0, t0, t1
+ jr ra
+ nop
+
+L(ret0):
+ move a0, zero
+ jr ra
+ nop
+ nop
+
+L(unaligned):
+ slt a6, a3, a2
+ xor t0, a0, a1
+ maskeqz t0, t0, a6
+ xor a0, a0, t0
+
+
+ xor a1, a1, t0
+ andi a2, a0, 0x7
+ andi a3, a1, 0x7
+ bstrins.d a0, zero, 2, 0
+
+ bstrins.d a1, zero, 2, 0
+ ld.d t4, a0, 0
+ ld.d t1, a1, 0
+ slli.d a2, a2, 3
+
+ slli.d a3, a3, 3
+ srl.d t0, t4, a2
+ srl.d t1, t1, a3
+ srl.d t5, t7, a3
+
+ orn t0, t0, t5
+ orn t1, t1, t5
+ bne t0, t1, L(not_equal)
+ sll.d t5, t7, a2
+
+
+ sub.d a3, a2, a3
+ orn t4, t4, t5
+ sub.d a2, zero, a3
+ sub.d t2, t4, a4
+
+ andn t3, a5, t4
+ and t2, t2, t3
+ bnez t2, L(find_zero)
+L(un_loop):
+ srl.d t5, t4, a3
+
+ ldx.d t4, a0, t8
+ ldx.d t1, a1, t8
+ addi.d t8, t8, 8
+ sll.d t0, t4, a2
+
+ or t0, t0, t5
+ bne t0, t1, L(not_equal)
+ sub.d t2, t4, a4
+ andn t3, a5, t4
+
+
+ and t2, t2, t3
+ beqz t2, L(un_loop)
+L(find_zero):
+ sub.d t2, t0, a4
+ andn t3, a5, t0
+
+ and t2, t2, t3
+ bnez t2, L(ret0)
+ ldx.d t1, a1, t8
+ srl.d t0, t4, a3
+
+L(not_equal):
+ sub.d t2, t0, a4
+ andn t3, a5, t0
+ and t2, t2, t3
+ xor t3, t0, t1
+
+ or t2, t2, t3
+L(un_end):
+ ctz.d t3, t2
+ bstrins.d t3, zero, 2, 0
+ srl.d t0, t0, t3
+
+
+ srl.d t1, t1, t3
+ andi t0, t0, 0xff
+ andi t1, t1, 0xff
+ sub.d t2, t0, t1
+
+
+ sub.d t3, t1, t0
+ masknez t0, t2, a6
+ maskeqz t1, t3, a6
+ or a0, t0, t1
+
+ jr ra
+END(STRCMP_NAME)
+
+libc_hidden_builtin_def (STRCMP_NAME)
diff --git a/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S b/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S
new file mode 100644
index 00000000..2e177a38
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S
@@ -0,0 +1,165 @@
+/* Optimized strcmp implementation using Loongarch LSX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define STRCMP __strcmp_lsx
+
+LEAF(STRCMP, 6)
+ pcalau12i t0, %pc_hi20(L(INDEX))
+ andi a2, a0, 0xf
+ vld vr2, t0, %pc_lo12(L(INDEX))
+ andi a3, a1, 0xf
+
+ bne a2, a3, L(unaligned)
+ bstrins.d a0, zero, 3, 0
+ bstrins.d a1, zero, 3, 0
+ vld vr0, a0, 0
+
+ vld vr1, a1, 0
+ vreplgr2vr.b vr3, a2
+ vslt.b vr2, vr2, vr3
+ vseq.b vr3, vr0, vr1
+
+ vmin.bu vr3, vr0, vr3
+ vor.v vr3, vr3, vr2
+ vsetanyeqz.b fcc0, vr3
+ bcnez fcc0, L(al_out)
+
+
+L(al_loop):
+ vld vr0, a0, 16
+ vld vr1, a1, 16
+ addi.d a0, a0, 16
+ addi.d a1, a1, 16
+
+ vseq.b vr3, vr0, vr1
+ vmin.bu vr3, vr0, vr3
+ vsetanyeqz.b fcc0, vr3
+ bceqz fcc0, L(al_loop)
+
+L(al_out):
+ vseqi.b vr3, vr3, 0
+ vfrstpi.b vr3, vr3, 0
+ vshuf.b vr0, vr0, vr0, vr3
+ vshuf.b vr1, vr1, vr1, vr3
+
+ vpickve2gr.bu t0, vr0, 0
+ vpickve2gr.bu t1, vr1, 0
+ sub.d a0, t0, t1
+ jr ra
+
+
+L(unaligned):
+ slt a4, a3, a2
+ xor t0, a0, a1
+ maskeqz t0, t0, a4
+ xor a0, a0, t0
+
+ xor a1, a1, t0
+ andi a2, a0, 0xf
+ andi a3, a1, 0xf
+ bstrins.d a0, zero, 3, 0
+
+ bstrins.d a1, zero, 3, 0
+ vld vr3, a0, 0
+ vld vr1, a1, 0
+ vreplgr2vr.b vr4, a2
+
+ vreplgr2vr.b vr5, a3
+ vslt.b vr7, vr2, vr5
+ vsub.b vr5, vr5, vr4
+ vaddi.bu vr6, vr2, 16
+
+
+ vsub.b vr6, vr6, vr5
+ vshuf.b vr0, vr3, vr3, vr6
+ vor.v vr0, vr0, vr7
+ vor.v vr1, vr1, vr7
+
+ vseq.b vr5, vr0, vr1
+ vsetanyeqz.b fcc0, vr5
+ bcnez fcc0, L(not_equal)
+ vslt.b vr4, vr2, vr4
+
+ vor.v vr0, vr3, vr4
+ vsetanyeqz.b fcc0, vr0
+ bcnez fcc0, L(find_zero)
+ nop
+
+L(un_loop):
+ vld vr3, a0, 16
+ vld vr1, a1, 16
+ addi.d a0, a0, 16
+ addi.d a1, a1, 16
+
+
+ vshuf.b vr0, vr3, vr0, vr6
+ vseq.b vr5, vr0, vr1
+ vsetanyeqz.b fcc0, vr5
+ bcnez fcc0, L(not_equal)
+
+ vsetanyeqz.b fcc0, vr3
+ vor.v vr0, vr3, vr3
+ bceqz fcc0, L(un_loop)
+L(find_zero):
+ vmin.bu vr5, vr1, vr5
+
+ vsetanyeqz.b fcc0, vr5
+ bcnez fcc0, L(ret0)
+ vld vr1, a1, 16
+ vshuf.b vr0, vr3, vr3, vr6
+
+ vseq.b vr5, vr0, vr1
+L(not_equal):
+ vmin.bu vr5, vr0, vr5
+L(un_end):
+ vseqi.b vr5, vr5, 0
+ vfrstpi.b vr5, vr5, 0
+
+
+ vshuf.b vr0, vr0, vr0, vr5
+ vshuf.b vr1, vr1, vr1, vr5
+ vpickve2gr.bu t0, vr0, 0
+ vpickve2gr.bu t1, vr1, 0
+
+ sub.d t3, t0, t1
+ sub.d t4, t1, t0
+ masknez t0, t3, a4
+ maskeqz t1, t4, a4
+
+ or a0, t0, t1
+ jr ra
+L(ret0):
+ move a0, zero
+ jr ra
+END(STRCMP)
+
+ .section .rodata.cst16,"M",@progbits,16
+ .align 4
+L(INDEX):
+ .dword 0x0706050403020100
+ .dword 0x0f0e0d0c0b0a0908
+
+libc_hidden_builtin_def (STRCMP)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/strcmp.c b/sysdeps/loongarch/lp64/multiarch/strcmp.c
new file mode 100644
index 00000000..6f249c0b
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strcmp.c
@@ -0,0 +1,35 @@
+/* Multiple versions of strcmp.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define strcmp __redirect_strcmp
+# include <string.h>
+# undef strcmp
+
+# define SYMBOL_NAME strcmp
+# include "ifunc-strcmp.h"
+
+libc_ifunc_redirected (__redirect_strcmp, strcmp, IFUNC_SELECTOR ());
+
+# ifdef SHARED
+__hidden_ver1 (strcmp, __GI_strcmp, __redirect_strcmp)
+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strcmp);
+# endif
+#endif
--
2.33.0

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,583 @@
From 6f03da2d7ef218c0f78375cf706dada59c3fee63 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Thu, 24 Aug 2023 16:50:19 +0800
Subject: [PATCH 10/29] LoongArch: Add ifunc support for strncmp{aligned, lsx}
Based on the glibc microbenchmark, only a few short inputs with this
strncmp-aligned and strncmp-lsx implementation experience performance
degradation, overall, strncmp-aligned could reduce the runtime 0%-10%
for aligned comparision, 10%-25% for unaligend comparision, strncmp-lsx
could reduce the runtime about 0%-60%.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/lp64/multiarch/Makefile | 2 +
.../lp64/multiarch/ifunc-impl-list.c | 7 +
.../loongarch/lp64/multiarch/ifunc-strncmp.h | 38 +++
.../lp64/multiarch/strncmp-aligned.S | 218 ++++++++++++++++++
.../loongarch/lp64/multiarch/strncmp-lsx.S | 208 +++++++++++++++++
sysdeps/loongarch/lp64/multiarch/strncmp.c | 35 +++
6 files changed, 508 insertions(+)
create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-strncmp.h
create mode 100644 sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/strncmp.c
diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile
index d5a500de..5d7ae7ae 100644
--- a/sysdeps/loongarch/lp64/multiarch/Makefile
+++ b/sysdeps/loongarch/lp64/multiarch/Makefile
@@ -14,6 +14,8 @@ sysdep_routines += \
strchrnul-lasx \
strcmp-aligned \
strcmp-lsx \
+ strncmp-aligned \
+ strncmp-lsx \
memcpy-aligned \
memcpy-unaligned \
memmove-unaligned \
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
index 9183b7da..c8ba87bd 100644
--- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
@@ -69,6 +69,13 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
IFUNC_IMPL_ADD (array, i, strcmp, 1, __strcmp_aligned)
)
+ IFUNC_IMPL (i, name, strncmp,
+#if !defined __loongarch_soft_float
+ IFUNC_IMPL_ADD (array, i, strncmp, SUPPORT_LSX, __strncmp_lsx)
+#endif
+ IFUNC_IMPL_ADD (array, i, strncmp, 1, __strncmp_aligned)
+ )
+
IFUNC_IMPL (i, name, memcpy,
#if !defined __loongarch_soft_float
IFUNC_IMPL_ADD (array, i, memcpy, SUPPORT_LASX, __memcpy_lasx)
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-strncmp.h b/sysdeps/loongarch/lp64/multiarch/ifunc-strncmp.h
new file mode 100644
index 00000000..1a7dc36b
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-strncmp.h
@@ -0,0 +1,38 @@
+/* Common definition for strncmp ifunc selection.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#if !defined __loongarch_soft_float
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden;
+#endif
+
+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+#if !defined __loongarch_soft_float
+ if (SUPPORT_LSX)
+ return OPTIMIZE (lsx);
+ else
+#endif
+ return OPTIMIZE (aligned);
+}
diff --git a/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S b/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S
new file mode 100644
index 00000000..e2687fa7
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S
@@ -0,0 +1,218 @@
+/* Optimized strncmp implementation using basic Loongarch instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc)
+# define STRNCMP __strncmp_aligned
+#else
+# define STRNCMP strncmp
+#endif
+
+LEAF(STRNCMP, 6)
+ beqz a2, L(ret0)
+ lu12i.w a5, 0x01010
+ andi a3, a0, 0x7
+ ori a5, a5, 0x101
+
+ andi a4, a1, 0x7
+ bstrins.d a5, a5, 63, 32
+ li.d t7, -1
+ li.d t8, 8
+
+ addi.d a2, a2, -1
+ slli.d a6, a5, 7
+ bne a3, a4, L(unaligned)
+ bstrins.d a0, zero, 2, 0
+
+ bstrins.d a1, zero, 2, 0
+ ld.d t0, a0, 0
+ ld.d t1, a1, 0
+ slli.d t2, a3, 3
+
+
+ sub.d t5, t8, a3
+ srl.d t3, t7, t2
+ srl.d t0, t0, t2
+ srl.d t1, t1, t2
+
+ orn t0, t0, t3
+ orn t1, t1, t3
+ sub.d t2, t0, a5
+ andn t3, a6, t0
+
+ and t2, t2, t3
+ bne t0, t1, L(al_end)
+ sltu t4, a2, t5
+ sub.d a2, a2, t5
+
+L(al_loop):
+ or t4, t2, t4
+ bnez t4, L(ret0)
+ ldx.d t0, a0, t8
+ ldx.d t1, a1, t8
+
+
+ addi.d t8, t8, 8
+ sltui t4, a2, 8
+ addi.d a2, a2, -8
+ sub.d t2, t0, a5
+
+ andn t3, a6, t0
+ and t2, t2, t3
+ beq t0, t1, L(al_loop)
+ addi.d a2, a2, 8
+
+L(al_end):
+ xor t3, t0, t1
+ or t2, t2, t3
+ ctz.d t2, t2
+ srli.d t4, t2, 3
+
+ bstrins.d t2, zero, 2, 0
+ srl.d t0, t0, t2
+ srl.d t1, t1, t2
+ andi t0, t0, 0xff
+
+
+ andi t1, t1, 0xff
+ sltu t2, a2, t4
+ sub.d a0, t0, t1
+ masknez a0, a0, t2
+
+ jr ra
+L(ret0):
+ move a0, zero
+ jr ra
+ nop
+
+L(unaligned):
+ slt a7, a4, a3
+ xor t0, a0, a1
+ maskeqz t0, t0, a7
+ xor a0, a0, t0
+
+ xor a1, a1, t0
+ andi a3, a0, 0x7
+ andi a4, a1, 0x7
+ bstrins.d a0, zero, 2, 0
+
+
+ bstrins.d a1, zero, 2, 0
+ ld.d t4, a0, 0
+ ld.d t1, a1, 0
+ slli.d t2, a3, 3
+
+ slli.d t3, a4, 3
+ srl.d t5, t7, t3
+ srl.d t0, t4, t2
+ srl.d t1, t1, t3
+
+ orn t0, t0, t5
+ orn t1, t1, t5
+ bne t0, t1, L(not_equal)
+ sub.d t6, t8, a4
+
+ sub.d a4, t2, t3
+ sll.d t2, t7, t2
+ sub.d t5, t8, a3
+ orn t4, t4, t2
+
+
+ sub.d t2, t4, a5
+ andn t3, a6, t4
+ sltu t7, a2, t5
+ and t2, t2, t3
+
+ sub.d a3, zero, a4
+ or t2, t2, t7
+ bnez t2, L(un_end)
+ sub.d t7, t5, t6
+
+ sub.d a2, a2, t5
+ sub.d t6, t8, t7
+L(un_loop):
+ srl.d t5, t4, a4
+ ldx.d t4, a0, t8
+
+ ldx.d t1, a1, t8
+ addi.d t8, t8, 8
+ sll.d t0, t4, a3
+ or t0, t0, t5
+
+
+ bne t0, t1, L(loop_not_equal)
+ sub.d t2, t4, a5
+ andn t3, a6, t4
+ sltui t5, a2, 8
+
+ and t2, t2, t3
+ addi.d a2, a2, -8
+ or t3, t2, t5
+ beqz t3, L(un_loop)
+
+ addi.d a2, a2, 8
+L(un_end):
+ sub.d t2, t0, a5
+ andn t3, a6, t0
+ sltu t5, a2, t6
+
+ and t2, t2, t3
+ or t2, t2, t5
+ bnez t2, L(ret0)
+ ldx.d t1, a1, t8
+
+
+ srl.d t0, t4, a4
+ sub.d a2, a2, t6
+L(not_equal):
+ sub.d t2, t0, a5
+ andn t3, a6, t0
+
+ xor t4, t0, t1
+ and t2, t2, t3
+ or t2, t2, t4
+ ctz.d t2, t2
+
+ bstrins.d t2, zero, 2, 0
+ srli.d t4, t2, 3
+ srl.d t0, t0, t2
+ srl.d t1, t1, t2
+
+ andi t0, t0, 0xff
+ andi t1, t1, 0xff
+ sub.d t2, t0, t1
+ sub.d t3, t1, t0
+
+
+ masknez t0, t2, a7
+ maskeqz t1, t3, a7
+ sltu t2, a2, t4
+ or a0, t0, t1
+
+ masknez a0, a0, t2
+ jr ra
+L(loop_not_equal):
+ add.d a2, a2, t7
+ b L(not_equal)
+END(STRNCMP)
+
+libc_hidden_builtin_def (STRNCMP)
diff --git a/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S b/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S
new file mode 100644
index 00000000..0b4eee2a
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S
@@ -0,0 +1,208 @@
+/* Optimized strncmp implementation using Loongarch LSX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define STRNCMP __strncmp_lsx
+
+LEAF(STRNCMP, 6)
+ beqz a2, L(ret0)
+ pcalau12i t0, %pc_hi20(L(INDEX))
+ andi a3, a0, 0xf
+ vld vr2, t0, %pc_lo12(L(INDEX))
+
+ andi a4, a1, 0xf
+ li.d t2, 16
+ bne a3, a4, L(unaligned)
+ xor t0, a0, a3
+
+ xor t1, a1, a4
+ vld vr0, t0, 0
+ vld vr1, t1, 0
+ vreplgr2vr.b vr3, a3
+
+
+ sub.d t2, t2, a3
+ vadd.b vr3, vr3, vr2
+ vshuf.b vr0, vr3, vr0, vr3
+ vshuf.b vr1, vr3, vr1, vr3
+
+ vseq.b vr3, vr0, vr1
+ vmin.bu vr3, vr0, vr3
+ bgeu t2, a2, L(al_early_end)
+ vsetanyeqz.b fcc0, vr3
+
+ bcnez fcc0, L(al_end)
+ add.d a3, a0, a2
+ addi.d a4, a3, -1
+ bstrins.d a4, zero, 3, 0
+
+ sub.d a2, a3, a4
+L(al_loop):
+ vld vr0, t0, 16
+ vld vr1, t1, 16
+ addi.d t0, t0, 16
+
+
+ addi.d t1, t1, 16
+ vseq.b vr3, vr0, vr1
+ vmin.bu vr3, vr0, vr3
+ beq t0, a4, L(al_early_end)
+
+ vsetanyeqz.b fcc0, vr3
+ bceqz fcc0, L(al_loop)
+L(al_end):
+ vseqi.b vr3, vr3, 0
+ vfrstpi.b vr3, vr3, 0
+
+ vshuf.b vr0, vr0, vr0, vr3
+ vshuf.b vr1, vr1, vr1, vr3
+ vpickve2gr.bu t0, vr0, 0
+ vpickve2gr.bu t1, vr1, 0
+
+ sub.d a0, t0, t1
+ jr ra
+L(al_early_end):
+ vreplgr2vr.b vr4, a2
+ vslt.b vr4, vr2, vr4
+
+
+ vorn.v vr3, vr3, vr4
+ b L(al_end)
+L(unaligned):
+ slt a5, a3, a4
+ xor t0, a0, a1
+
+ maskeqz t0, t0, a5
+ xor a0, a0, t0
+ xor a1, a1, t0
+ andi a3, a0, 0xf
+
+ andi a4, a1, 0xf
+ xor t0, a0, a3
+ xor t1, a1, a4
+ vld vr0, t0, 0
+
+ vld vr3, t1, 0
+ sub.d t2, t2, a3
+ vreplgr2vr.b vr4, a3
+ vreplgr2vr.b vr5, a4
+
+
+ vaddi.bu vr6, vr2, 16
+ vsub.b vr7, vr4, vr5
+ vsub.b vr6, vr6, vr7
+ vadd.b vr4, vr2, vr4
+
+ vshuf.b vr1, vr3, vr3, vr6
+ vshuf.b vr0, vr7, vr0, vr4
+ vshuf.b vr1, vr7, vr1, vr4
+ vseq.b vr4, vr0, vr1
+
+ vmin.bu vr4, vr0, vr4
+ bgeu t2, a2, L(un_early_end)
+ vsetanyeqz.b fcc0, vr4
+ bcnez fcc0, L(un_end)
+
+ add.d a6, a0, a2
+ vslt.b vr5, vr2, vr5
+ addi.d a7, a6, -1
+ vor.v vr3, vr3, vr5
+
+
+ bstrins.d a7, zero, 3, 0
+ sub.d a2, a6, a7
+L(un_loop):
+ vld vr0, t0, 16
+ addi.d t0, t0, 16
+
+ vsetanyeqz.b fcc0, vr3
+ bcnez fcc0, L(has_zero)
+ beq t0, a7, L(end_with_len)
+ vor.v vr1, vr3, vr3
+
+ vld vr3, t1, 16
+ addi.d t1, t1, 16
+ vshuf.b vr1, vr3, vr1, vr6
+ vseq.b vr4, vr0, vr1
+
+ vmin.bu vr4, vr0, vr4
+ vsetanyeqz.b fcc0, vr4
+ bceqz fcc0, L(un_loop)
+L(un_end):
+ vseqi.b vr4, vr4, 0
+
+
+ vfrstpi.b vr4, vr4, 0
+ vshuf.b vr0, vr0, vr0, vr4
+ vshuf.b vr1, vr1, vr1, vr4
+ vpickve2gr.bu t0, vr0, 0
+
+ vpickve2gr.bu t1, vr1, 0
+ sub.d t2, t0, t1
+ sub.d t3, t1, t0
+ masknez t0, t2, a5
+
+ maskeqz t1, t3, a5
+ or a0, t0, t1
+ jr ra
+L(has_zero):
+ vshuf.b vr1, vr3, vr3, vr6
+
+ vseq.b vr4, vr0, vr1
+ vmin.bu vr4, vr0, vr4
+ bne t0, a7, L(un_end)
+L(un_early_end):
+ vreplgr2vr.b vr5, a2
+
+ vslt.b vr5, vr2, vr5
+ vorn.v vr4, vr4, vr5
+ b L(un_end)
+L(end_with_len):
+ sub.d a6, a3, a4
+
+ bgeu a6, a2, 1f
+ vld vr4, t1, 16
+1:
+ vshuf.b vr1, vr4, vr3, vr6
+ vseq.b vr4, vr0, vr1
+
+ vmin.bu vr4, vr0, vr4
+ vreplgr2vr.b vr5, a2
+ vslt.b vr5, vr2, vr5
+ vorn.v vr4, vr4, vr5
+
+ b L(un_end)
+L(ret0):
+ move a0, zero
+ jr ra
+END(STRNCMP)
+
+ .section .rodata.cst16,"M",@progbits,16
+ .align 4
+L(INDEX):
+ .dword 0x0706050403020100
+ .dword 0x0f0e0d0c0b0a0908
+
+libc_hidden_builtin_def (STRNCMP)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/strncmp.c b/sysdeps/loongarch/lp64/multiarch/strncmp.c
new file mode 100644
index 00000000..af6d0bc4
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strncmp.c
@@ -0,0 +1,35 @@
+/* Multiple versions of strncmp.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define strncmp __redirect_strncmp
+# include <string.h>
+# undef strncmp
+
+# define SYMBOL_NAME strncmp
+# include "ifunc-strncmp.h"
+
+libc_ifunc_redirected (__redirect_strncmp, strncmp, IFUNC_SELECTOR ());
+
+# ifdef SHARED
+__hidden_ver1 (strncmp, __GI_strncmp, __redirect_strncmp)
+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strncmp);
+# endif
+#endif
--
2.33.0

View file

@ -0,0 +1,465 @@
From e494d32d3b76eee0d59cfab37789a356459b517a Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Thu, 24 Aug 2023 16:50:17 +0800
Subject: [PATCH 08/29] LoongArch: Add ifunc support for strnlen{aligned, lsx,
lasx}
Based on the glibc microbenchmark, strnlen-aligned implementation could
reduce the runtime more than 10%, strnlen-lsx implementation could reduce
the runtime about 50%-78%, strnlen-lasx implementation could reduce the
runtime about 50%-88%.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/lp64/multiarch/Makefile | 3 +
.../lp64/multiarch/ifunc-impl-list.c | 8 ++
.../loongarch/lp64/multiarch/ifunc-strnlen.h | 41 +++++++
.../lp64/multiarch/strnlen-aligned.S | 102 ++++++++++++++++++
.../loongarch/lp64/multiarch/strnlen-lasx.S | 100 +++++++++++++++++
.../loongarch/lp64/multiarch/strnlen-lsx.S | 89 +++++++++++++++
sysdeps/loongarch/lp64/multiarch/strnlen.c | 39 +++++++
7 files changed, 382 insertions(+)
create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-strnlen.h
create mode 100644 sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/strnlen.c
diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile
index afa51041..c4dd3143 100644
--- a/sysdeps/loongarch/lp64/multiarch/Makefile
+++ b/sysdeps/loongarch/lp64/multiarch/Makefile
@@ -3,6 +3,9 @@ sysdep_routines += \
strlen-aligned \
strlen-lsx \
strlen-lasx \
+ strnlen-aligned \
+ strnlen-lsx \
+ strnlen-lasx \
strchr-aligned \
strchr-lsx \
strchr-lasx \
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
index 25eb96b0..7cec0b77 100644
--- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
@@ -38,6 +38,14 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
IFUNC_IMPL_ADD (array, i, strlen, 1, __strlen_aligned)
)
+ IFUNC_IMPL (i, name, strnlen,
+#if !defined __loongarch_soft_float
+ IFUNC_IMPL_ADD (array, i, strnlen, SUPPORT_LASX, __strnlen_lasx)
+ IFUNC_IMPL_ADD (array, i, strnlen, SUPPORT_LSX, __strnlen_lsx)
+#endif
+ IFUNC_IMPL_ADD (array, i, strnlen, 1, __strnlen_aligned)
+ )
+
IFUNC_IMPL (i, name, strchr,
#if !defined __loongarch_soft_float
IFUNC_IMPL_ADD (array, i, strchr, SUPPORT_LASX, __strchr_lasx)
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-strnlen.h b/sysdeps/loongarch/lp64/multiarch/ifunc-strnlen.h
new file mode 100644
index 00000000..5cf89810
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-strnlen.h
@@ -0,0 +1,41 @@
+/* Common definition for strnlen ifunc selections.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#if !defined __loongarch_soft_float
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden;
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden;
+#endif
+
+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+#if !defined __loongarch_soft_float
+ if (SUPPORT_LASX)
+ return OPTIMIZE (lasx);
+ else if (SUPPORT_LSX)
+ return OPTIMIZE (lsx);
+ else
+#endif
+ return OPTIMIZE (aligned);
+}
diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S b/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S
new file mode 100644
index 00000000..b900430a
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S
@@ -0,0 +1,102 @@
+/* Optimized strnlen implementation using basic Loongarch instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc)
+# define STRNLEN __strnlen_aligned
+#else
+# define STRNLEN __strnlen
+#endif
+
+LEAF(STRNLEN, 6)
+ beqz a1, L(out)
+ lu12i.w a2, 0x01010
+ andi t1, a0, 0x7
+ move t4, a0
+
+ bstrins.d a0, zero, 2, 0
+ ori a2, a2, 0x101
+ li.w t0, -1
+ ld.d t2, a0, 0
+
+ slli.d t3, t1, 3
+ bstrins.d a2, a2, 63, 32
+ li.w t5, 8
+ slli.d a3, a2, 7
+
+ sub.w t1, t5, t1
+ sll.d t0, t0, t3
+ orn t2, t2, t0
+ sub.d t0, t2, a2
+
+
+ andn t3, a3, t2
+ and t0, t0, t3
+ bnez t0, L(count_pos)
+ sub.d t5, a1, t1
+
+ bgeu t1, a1, L(out)
+ addi.d a0, a0, 8
+L(loop):
+ ld.d t2, a0, 0
+ sub.d t0, t2, a2
+
+ andn t1, a3, t2
+ sltui t6, t5, 9
+ and t0, t0, t1
+ or t7, t0, t6
+
+ bnez t7, L(count_pos)
+ ld.d t2, a0, 8
+ addi.d a0, a0, 16
+ sub.d t0, t2, a2
+
+
+ andn t1, a3, t2
+ sltui t6, t5, 17
+ and t0, t0, t1
+ addi.d t5, t5, -16
+
+ or t7, t0, t6
+ beqz t7, L(loop)
+ addi.d a0, a0, -8
+L(count_pos):
+ ctz.d t1, t0
+
+ sub.d a0, a0, t4
+ srli.d t1, t1, 3
+ add.d a0, t1, a0
+ sltu t0, a0, a1
+
+ masknez t1, a1, t0
+ maskeqz a0, a0, t0
+ or a0, a0, t1
+ jr ra
+
+
+L(out):
+ move a0, a1
+ jr ra
+END(STRNLEN)
+
+weak_alias (STRNLEN, strnlen)
+libc_hidden_builtin_def (STRNLEN)
diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S b/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S
new file mode 100644
index 00000000..2c03d3d9
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S
@@ -0,0 +1,100 @@
+/* Optimized strnlen implementation using loongarch LASX instructions
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define STRNLEN __strnlen_lasx
+
+LEAF(STRNLEN, 6)
+ beqz a1, L(ret0)
+ andi t1, a0, 0x3f
+ li.d t3, 65
+ sub.d a2, a0, t1
+
+ xvld xr0, a2, 0
+ xvld xr1, a2, 32
+ sub.d t1, t3, t1
+ move a3, a0
+
+ sltu t1, a1, t1
+ xvmsknz.b xr0, xr0
+ xvmsknz.b xr1, xr1
+ xvpickve.w xr2, xr0, 4
+
+ xvpickve.w xr3, xr1, 4
+ vilvl.h vr0, vr2, vr0
+ vilvl.h vr1, vr3, vr1
+ vilvl.w vr0, vr1, vr0
+
+
+ movfr2gr.d t0, fa0
+ sra.d t0, t0, a0
+ orn t1, t1, t0
+ bnez t1, L(end)
+
+ add.d a4, a0, a1
+ move a0, a2
+ addi.d a4, a4, -1
+ bstrins.d a4, zero, 5, 0
+
+L(loop):
+ xvld xr0, a0, 64
+ xvld xr1, a0, 96
+ addi.d a0, a0, 64
+ beq a0, a4, L(out)
+
+ xvmin.bu xr2, xr0, xr1
+ xvsetanyeqz.b fcc0, xr2
+ bceqz fcc0, L(loop)
+L(out):
+ xvmsknz.b xr0, xr0
+
+
+ xvmsknz.b xr1, xr1
+ xvpickve.w xr2, xr0, 4
+ xvpickve.w xr3, xr1, 4
+ vilvl.h vr0, vr2, vr0
+
+ vilvl.h vr1, vr3, vr1
+ vilvl.w vr0, vr1, vr0
+ movfr2gr.d t0, fa0
+L(end):
+ sub.d a0, a0, a3
+
+ cto.d t0, t0
+ add.d a0, a0, t0
+ sltu t1, a0, a1
+ masknez t0, a1, t1
+
+ maskeqz t1, a0, t1
+ or a0, t0, t1
+ jr ra
+L(ret0):
+ move a0, zero
+
+
+ jr ra
+END(STRNLEN)
+
+libc_hidden_def (STRNLEN)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S b/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S
new file mode 100644
index 00000000..b769a895
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S
@@ -0,0 +1,89 @@
+/* Optimized strnlen implementation using loongarch LSX instructions
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define STRNLEN __strnlen_lsx
+
+LEAF(STRNLEN, 6)
+ beqz a1, L(ret0)
+ andi t1, a0, 0x1f
+ li.d t3, 33
+ sub.d a2, a0, t1
+
+ vld vr0, a2, 0
+ vld vr1, a2, 16
+ sub.d t1, t3, t1
+ move a3, a0
+
+ sltu t1, a1, t1
+ vmsknz.b vr0, vr0
+ vmsknz.b vr1, vr1
+ vilvl.h vr0, vr1, vr0
+
+ movfr2gr.s t0, fa0
+ sra.w t0, t0, a0
+ orn t1, t1, t0
+ bnez t1, L(end)
+
+
+ add.d a4, a0, a1
+ move a0, a2
+ addi.d a4, a4, -1
+ bstrins.d a4, zero, 4, 0
+
+L(loop):
+ vld vr0, a0, 32
+ vld vr1, a0, 48
+ addi.d a0, a0, 32
+ beq a0, a4, L(out)
+
+ vmin.bu vr2, vr0, vr1
+ vsetanyeqz.b fcc0, vr2
+ bceqz fcc0, L(loop)
+L(out):
+ vmsknz.b vr0, vr0
+
+ vmsknz.b vr1, vr1
+ vilvl.h vr0, vr1, vr0
+ movfr2gr.s t0, fa0
+L(end):
+ sub.d a0, a0, a3
+
+
+ cto.w t0, t0
+ add.d a0, a0, t0
+ sltu t1, a0, a1
+ masknez t0, a1, t1
+
+ maskeqz t1, a0, t1
+ or a0, t0, t1
+ jr ra
+L(ret0):
+ move a0, zero
+
+ jr ra
+END(STRNLEN)
+
+libc_hidden_builtin_def (STRNLEN)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen.c b/sysdeps/loongarch/lp64/multiarch/strnlen.c
new file mode 100644
index 00000000..38b7a25a
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strnlen.c
@@ -0,0 +1,39 @@
+/* Multiple versions of strnlen.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define strnlen __redirect_strnlen
+# define __strnlen __redirect___strnlen
+# include <string.h>
+# undef __strnlen
+# undef strnlen
+
+# define SYMBOL_NAME strnlen
+# include "ifunc-strnlen.h"
+
+libc_ifunc_redirected (__redirect_strnlen, __strnlen, IFUNC_SELECTOR ());
+weak_alias (__strnlen, strnlen);
+# ifdef SHARED
+__hidden_ver1 (__strnlen, __GI___strnlen, __redirect___strnlen)
+ __attribute__((visibility ("hidden"))) __attribute_copy__ (strnlen);
+__hidden_ver1 (strnlen, __GI_strnlen, __redirect_strnlen)
+ __attribute__((weak, visibility ("hidden"))) __attribute_copy__ (strnlen);
+# endif
+#endif
--
2.33.0

View file

@ -0,0 +1,670 @@
From d537d0ab45a55048c8da483e73be4448ddb45525 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Wed, 13 Sep 2023 15:35:00 +0800
Subject: [PATCH 23/29] LoongArch: Add ifunc support for strrchr{aligned, lsx,
lasx}
According to glibc strrchr microbenchmark test results, this implementation
could reduce the runtime time as following:
Name Percent of rutime reduced
strrchr-lasx 10%-50%
strrchr-lsx 0%-50%
strrchr-aligned 5%-50%
Generic strrchr is implemented by function strlen + memrchr, the lasx version
will compare with generic strrchr implemented by strlen-lasx + memrchr-lasx,
the lsx version will compare with generic strrchr implemented by strlen-lsx +
memrchr-lsx, the aligned version will compare with generic strrchr implemented
by strlen-aligned + memrchr-generic.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/lp64/multiarch/Makefile | 3 +
.../lp64/multiarch/ifunc-impl-list.c | 8 +
.../loongarch/lp64/multiarch/ifunc-strrchr.h | 41 ++++
.../lp64/multiarch/strrchr-aligned.S | 170 +++++++++++++++++
.../loongarch/lp64/multiarch/strrchr-lasx.S | 176 ++++++++++++++++++
.../loongarch/lp64/multiarch/strrchr-lsx.S | 144 ++++++++++++++
sysdeps/loongarch/lp64/multiarch/strrchr.c | 36 ++++
7 files changed, 578 insertions(+)
create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-strrchr.h
create mode 100644 sysdeps/loongarch/lp64/multiarch/strrchr-aligned.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/strrchr-lasx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/strrchr-lsx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/strrchr.c
diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile
index 39550bea..fe863e1b 100644
--- a/sysdeps/loongarch/lp64/multiarch/Makefile
+++ b/sysdeps/loongarch/lp64/multiarch/Makefile
@@ -9,6 +9,9 @@ sysdep_routines += \
strchr-aligned \
strchr-lsx \
strchr-lasx \
+ strrchr-aligned \
+ strrchr-lsx \
+ strrchr-lasx \
strchrnul-aligned \
strchrnul-lsx \
strchrnul-lasx \
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
index 39a14f1d..529e2369 100644
--- a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
@@ -94,6 +94,14 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
IFUNC_IMPL_ADD (array, i, stpcpy, 1, __stpcpy_aligned)
)
+ IFUNC_IMPL (i, name, strrchr,
+#if !defined __loongarch_soft_float
+ IFUNC_IMPL_ADD (array, i, strrchr, SUPPORT_LASX, __strrchr_lasx)
+ IFUNC_IMPL_ADD (array, i, strrchr, SUPPORT_LSX, __strrchr_lsx)
+#endif
+ IFUNC_IMPL_ADD (array, i, strrchr, 1, __strrchr_aligned)
+ )
+
IFUNC_IMPL (i, name, memcpy,
#if !defined __loongarch_soft_float
IFUNC_IMPL_ADD (array, i, memcpy, SUPPORT_LASX, __memcpy_lasx)
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-strrchr.h b/sysdeps/loongarch/lp64/multiarch/ifunc-strrchr.h
new file mode 100644
index 00000000..bbb34089
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-strrchr.h
@@ -0,0 +1,41 @@
+/* Common definition for strrchr ifunc selections.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#if !defined __loongarch_soft_float
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden;
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden;
+#endif
+
+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+#if !defined __loongarch_soft_float
+ if (SUPPORT_LASX)
+ return OPTIMIZE (lasx);
+ else if (SUPPORT_LSX)
+ return OPTIMIZE (lsx);
+ else
+#endif
+ return OPTIMIZE (aligned);
+}
diff --git a/sysdeps/loongarch/lp64/multiarch/strrchr-aligned.S b/sysdeps/loongarch/lp64/multiarch/strrchr-aligned.S
new file mode 100644
index 00000000..a73deb78
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strrchr-aligned.S
@@ -0,0 +1,170 @@
+/* Optimized strrchr implementation using basic LoongArch instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc)
+# define STRRCHR __strrchr_aligned
+#else
+# define STRRCHR strrchr
+#endif
+
+LEAF(STRRCHR, 6)
+ slli.d t0, a0, 3
+ bstrins.d a0, zero, 2, 0
+ lu12i.w a2, 0x01010
+ ld.d t2, a0, 0
+
+ andi a1, a1, 0xff
+ ori a2, a2, 0x101
+ li.d t3, -1
+ bstrins.d a2, a2, 63, 32
+
+ sll.d t5, t3, t0
+ slli.d a3, a2, 7
+ orn t4, t2, t5
+ mul.d a1, a1, a2
+
+ sub.d t0, t4, a2
+ andn t1, a3, t4
+ and t1, t0, t1
+ beqz t1, L(find_tail)
+
+
+ ctz.d t0, t1
+ orn t0, zero, t0
+ xor t2, t4, a1
+ srl.d t0, t3, t0
+
+ orn t2, t2, t0
+ orn t2, t2, t5
+ revb.d t2, t2
+ sub.d t1, t2, a2
+
+ andn t0, a3, t2
+ and t1, t0, t1
+ ctz.d t0, t1
+ srli.d t0, t0, 3
+
+ addi.d a0, a0, 7
+ sub.d a0, a0, t0
+ maskeqz a0, a0, t1
+ jr ra
+
+
+L(find_tail):
+ addi.d a4, a0, 8
+ addi.d a0, a0, 8
+L(loop_ascii):
+ ld.d t2, a0, 0
+ sub.d t1, t2, a2
+
+ and t0, t1, a3
+ bnez t0, L(more_check)
+ ld.d t2, a0, 8
+ sub.d t1, t2, a2
+
+ and t0, t1, a3
+ addi.d a0, a0, 16
+ beqz t0, L(loop_ascii)
+ addi.d a0, a0, -8
+
+L(more_check):
+ andn t0, a3, t2
+ and t1, t1, t0
+ bnez t1, L(tail)
+ addi.d a0, a0, 8
+
+
+L(loop_nonascii):
+ ld.d t2, a0, 0
+ sub.d t1, t2, a2
+ andn t0, a3, t2
+ and t1, t0, t1
+
+ bnez t1, L(tail)
+ ld.d t2, a0, 8
+ addi.d a0, a0, 16
+ sub.d t1, t2, a2
+
+ andn t0, a3, t2
+ and t1, t0, t1
+ beqz t1, L(loop_nonascii)
+ addi.d a0, a0, -8
+
+L(tail):
+ ctz.d t0, t1
+ orn t0, zero, t0
+ xor t2, t2, a1
+ srl.d t0, t3, t0
+
+
+ orn t2, t2, t0
+ revb.d t2, t2
+ sub.d t1, t2, a2
+ andn t0, a3, t2
+
+ and t1, t0, t1
+ bnez t1, L(count_pos)
+L(find_loop):
+ beq a0, a4, L(find_end)
+ ld.d t2, a0, -8
+
+ addi.d a0, a0, -8
+ xor t2, t2, a1
+ sub.d t1, t2, a2
+ andn t0, a3, t2
+
+ and t1, t0, t1
+ beqz t1, L(find_loop)
+ revb.d t2, t2
+ sub.d t1, t2, a2
+
+
+ andn t0, a3, t2
+ and t1, t0, t1
+L(count_pos):
+ ctz.d t0, t1
+ addi.d a0, a0, 7
+
+ srli.d t0, t0, 3
+ sub.d a0, a0, t0
+ jr ra
+ nop
+
+L(find_end):
+ xor t2, t4, a1
+ orn t2, t2, t5
+ revb.d t2, t2
+ sub.d t1, t2, a2
+
+
+ andn t0, a3, t2
+ and t1, t0, t1
+ ctz.d t0, t1
+ srli.d t0, t0, 3
+
+ addi.d a0, a4, -1
+ sub.d a0, a0, t0
+ maskeqz a0, a0, t1
+ jr ra
+END(STRRCHR)
+
+libc_hidden_builtin_def(STRRCHR)
diff --git a/sysdeps/loongarch/lp64/multiarch/strrchr-lasx.S b/sysdeps/loongarch/lp64/multiarch/strrchr-lasx.S
new file mode 100644
index 00000000..5a6e2297
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strrchr-lasx.S
@@ -0,0 +1,176 @@
+/* Optimized strrchr implementation using LoongArch LASX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+#define STRRCHR __strrchr_lasx
+
+LEAF(STRRCHR, 6)
+ move a2, a0
+ bstrins.d a0, zero, 5, 0
+ xvld xr0, a0, 0
+ xvld xr1, a0, 32
+
+ li.d t2, -1
+ xvreplgr2vr.b xr4, a1
+ xvmsknz.b xr2, xr0
+ xvmsknz.b xr3, xr1
+
+ xvpickve.w xr5, xr2, 4
+ xvpickve.w xr6, xr3, 4
+ vilvl.h vr2, vr5, vr2
+ vilvl.h vr3, vr6, vr3
+
+ vilvl.w vr2, vr3, vr2
+ movfr2gr.d t0, fa2
+ sra.d t0, t0, a2
+ beq t0, t2, L(find_tail)
+
+
+ xvseq.b xr2, xr0, xr4
+ xvseq.b xr3, xr1, xr4
+ xvmsknz.b xr2, xr2
+ xvmsknz.b xr3, xr3
+
+ xvpickve.w xr4, xr2, 4
+ xvpickve.w xr5, xr3, 4
+ vilvl.h vr2, vr4, vr2
+ vilvl.h vr3, vr5, vr3
+
+ vilvl.w vr1, vr3, vr2
+ slli.d t3, t2, 1
+ movfr2gr.d t1, fa1
+ cto.d t0, t0
+
+ srl.d t1, t1, a2
+ sll.d t3, t3, t0
+ addi.d a0, a2, 63
+ andn t1, t1, t3
+
+
+ clz.d t0, t1
+ sub.d a0, a0, t0
+ maskeqz a0, a0, t1
+ jr ra
+
+ .align 5
+L(find_tail):
+ addi.d a3, a0, 64
+L(loop):
+ xvld xr2, a0, 64
+ xvld xr3, a0, 96
+ addi.d a0, a0, 64
+
+ xvmin.bu xr5, xr2, xr3
+ xvsetanyeqz.b fcc0, xr5
+ bceqz fcc0, L(loop)
+ xvmsknz.b xr5, xr2
+
+
+ xvmsknz.b xr6, xr3
+ xvpickve.w xr7, xr5, 4
+ xvpickve.w xr8, xr6, 4
+ vilvl.h vr5, vr7, vr5
+
+ vilvl.h vr6, vr8, vr6
+ xvseq.b xr2, xr2, xr4
+ xvseq.b xr3, xr3, xr4
+ xvmsknz.b xr2, xr2
+
+ xvmsknz.b xr3, xr3
+ xvpickve.w xr7, xr2, 4
+ xvpickve.w xr8, xr3, 4
+ vilvl.h vr2, vr7, vr2
+
+ vilvl.h vr3, vr8, vr3
+ vilvl.w vr5, vr6, vr5
+ vilvl.w vr2, vr3, vr2
+ movfr2gr.d t0, fa5
+
+
+ movfr2gr.d t1, fa2
+ slli.d t3, t2, 1
+ cto.d t0, t0
+ sll.d t3, t3, t0
+
+ andn t1, t1, t3
+ beqz t1, L(find_loop)
+ clz.d t0, t1
+ addi.d a0, a0, 63
+
+ sub.d a0, a0, t0
+ jr ra
+L(find_loop):
+ beq a0, a3, L(find_end)
+ xvld xr2, a0, -64
+
+ xvld xr3, a0, -32
+ addi.d a0, a0, -64
+ xvseq.b xr2, xr2, xr4
+ xvseq.b xr3, xr3, xr4
+
+
+ xvmax.bu xr5, xr2, xr3
+ xvseteqz.v fcc0, xr5
+ bcnez fcc0, L(find_loop)
+ xvmsknz.b xr0, xr2
+
+ xvmsknz.b xr1, xr3
+ xvpickve.w xr2, xr0, 4
+ xvpickve.w xr3, xr1, 4
+ vilvl.h vr0, vr2, vr0
+
+ vilvl.h vr1, vr3, vr1
+ vilvl.w vr0, vr1, vr0
+ movfr2gr.d t0, fa0
+ addi.d a0, a0, 63
+
+ clz.d t0, t0
+ sub.d a0, a0, t0
+ jr ra
+ nop
+
+
+L(find_end):
+ xvseq.b xr2, xr0, xr4
+ xvseq.b xr3, xr1, xr4
+ xvmsknz.b xr2, xr2
+ xvmsknz.b xr3, xr3
+
+ xvpickve.w xr4, xr2, 4
+ xvpickve.w xr5, xr3, 4
+ vilvl.h vr2, vr4, vr2
+ vilvl.h vr3, vr5, vr3
+
+ vilvl.w vr1, vr3, vr2
+ movfr2gr.d t1, fa1
+ addi.d a0, a2, 63
+ srl.d t1, t1, a2
+
+ clz.d t0, t1
+ sub.d a0, a0, t0
+ maskeqz a0, a0, t1
+ jr ra
+END(STRRCHR)
+
+libc_hidden_builtin_def(STRRCHR)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/strrchr-lsx.S b/sysdeps/loongarch/lp64/multiarch/strrchr-lsx.S
new file mode 100644
index 00000000..8f2fd22e
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strrchr-lsx.S
@@ -0,0 +1,144 @@
+/* Optimized strrchr implementation using LoongArch LSX instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+#define STRRCHR __strrchr_lsx
+
+LEAF(STRRCHR, 6)
+ move a2, a0
+ bstrins.d a0, zero, 4, 0
+ vld vr0, a0, 0
+ vld vr1, a0, 16
+
+ li.d t2, -1
+ vreplgr2vr.b vr4, a1
+ vmsknz.b vr2, vr0
+ vmsknz.b vr3, vr1
+
+ vilvl.h vr2, vr3, vr2
+ movfr2gr.s t0, fa2
+ sra.w t0, t0, a2
+ beq t0, t2, L(find_tail)
+
+ vseq.b vr2, vr0, vr4
+ vseq.b vr3, vr1, vr4
+ vmsknz.b vr2, vr2
+ vmsknz.b vr3, vr3
+
+
+ vilvl.h vr1, vr3, vr2
+ slli.d t3, t2, 1
+ movfr2gr.s t1, fa1
+ cto.w t0, t0
+
+ srl.w t1, t1, a2
+ sll.d t3, t3, t0
+ addi.d a0, a2, 31
+ andn t1, t1, t3
+
+ clz.w t0, t1
+ sub.d a0, a0, t0
+ maskeqz a0, a0, t1
+ jr ra
+
+ .align 5
+L(find_tail):
+ addi.d a3, a0, 32
+L(loop):
+ vld vr2, a0, 32
+ vld vr3, a0, 48
+ addi.d a0, a0, 32
+
+ vmin.bu vr5, vr2, vr3
+ vsetanyeqz.b fcc0, vr5
+ bceqz fcc0, L(loop)
+ vmsknz.b vr5, vr2
+
+ vmsknz.b vr6, vr3
+ vilvl.h vr5, vr6, vr5
+ vseq.b vr2, vr2, vr4
+ vseq.b vr3, vr3, vr4
+
+ vmsknz.b vr2, vr2
+ vmsknz.b vr3, vr3
+ vilvl.h vr2, vr3, vr2
+ movfr2gr.s t0, fa5
+
+
+ movfr2gr.s t1, fa2
+ slli.d t3, t2, 1
+ cto.w t0, t0
+ sll.d t3, t3, t0
+
+ andn t1, t1, t3
+ beqz t1, L(find_loop)
+ clz.w t0, t1
+ addi.d a0, a0, 31
+
+ sub.d a0, a0, t0
+ jr ra
+L(find_loop):
+ beq a0, a3, L(find_end)
+ vld vr2, a0, -32
+
+ vld vr3, a0, -16
+ addi.d a0, a0, -32
+ vseq.b vr2, vr2, vr4
+ vseq.b vr3, vr3, vr4
+
+
+ vmax.bu vr5, vr2, vr3
+ vseteqz.v fcc0, vr5
+ bcnez fcc0, L(find_loop)
+ vmsknz.b vr0, vr2
+
+ vmsknz.b vr1, vr3
+ vilvl.h vr0, vr1, vr0
+ movfr2gr.s t0, fa0
+ addi.d a0, a0, 31
+
+ clz.w t0, t0
+ sub.d a0, a0, t0
+ jr ra
+ nop
+
+L(find_end):
+ vseq.b vr2, vr0, vr4
+ vseq.b vr3, vr1, vr4
+ vmsknz.b vr2, vr2
+ vmsknz.b vr3, vr3
+
+
+ vilvl.h vr1, vr3, vr2
+ movfr2gr.s t1, fa1
+ addi.d a0, a2, 31
+ srl.w t1, t1, a2
+
+ clz.w t0, t1
+ sub.d a0, a0, t0
+ maskeqz a0, a0, t1
+ jr ra
+END(STRRCHR)
+
+libc_hidden_builtin_def(STRRCHR)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/strrchr.c b/sysdeps/loongarch/lp64/multiarch/strrchr.c
new file mode 100644
index 00000000..d9c9f660
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strrchr.c
@@ -0,0 +1,36 @@
+/* Multiple versions of strrchr.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+#if IS_IN (libc)
+# define strrchr __redirect_strrchr
+# include <string.h>
+# undef strrchr
+
+# define SYMBOL_NAME strrchr
+# include "ifunc-strrchr.h"
+
+libc_ifunc_redirected (__redirect_strrchr, strrchr, IFUNC_SELECTOR ());
+weak_alias (strrchr, rindex)
+# ifdef SHARED
+__hidden_ver1 (strrchr, __GI_strrchr, __redirect_strrchr)
+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strrchr);
+# endif
+
+#endif
--
2.33.0

View file

@ -0,0 +1,626 @@
From b5979df8ad07823c79a934c1fa0a91ec0abffb61 Mon Sep 17 00:00:00 2001
From: caiyinyu <caiyinyu@loongson.cn>
Date: Fri, 8 Sep 2023 14:10:55 +0800
Subject: [PATCH 20/29] LoongArch: Add lasx/lsx support for
_dl_runtime_profile.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/bits/link.h | 24 ++-
sysdeps/loongarch/bits/link_lavcurrent.h | 25 +++
sysdeps/loongarch/dl-audit-check.h | 23 +++
sysdeps/loongarch/dl-link.sym | 8 +-
sysdeps/loongarch/dl-machine.h | 11 +-
sysdeps/loongarch/dl-trampoline.S | 177 +----------------
sysdeps/loongarch/dl-trampoline.h | 242 +++++++++++++++++++++++
7 files changed, 331 insertions(+), 179 deletions(-)
create mode 100644 sysdeps/loongarch/bits/link_lavcurrent.h
create mode 100644 sysdeps/loongarch/dl-audit-check.h
diff --git a/sysdeps/loongarch/bits/link.h b/sysdeps/loongarch/bits/link.h
index 7fa61312..00f6f25f 100644
--- a/sysdeps/loongarch/bits/link.h
+++ b/sysdeps/loongarch/bits/link.h
@@ -20,10 +20,26 @@
#error "Never include <bits/link.h> directly; use <link.h> instead."
#endif
+#ifndef __loongarch_soft_float
+typedef float La_loongarch_vr
+ __attribute__ ((__vector_size__ (16), __aligned__ (16)));
+typedef float La_loongarch_xr
+ __attribute__ ((__vector_size__ (32), __aligned__ (16)));
+
+typedef union
+{
+ double fpreg[4];
+ La_loongarch_vr vr[2];
+ La_loongarch_xr xr[1];
+} La_loongarch_vector __attribute__ ((__aligned__ (16)));
+#endif
+
typedef struct La_loongarch_regs
{
unsigned long int lr_reg[8]; /* a0 - a7 */
- double lr_fpreg[8]; /* fa0 - fa7 */
+#ifndef __loongarch_soft_float
+ La_loongarch_vector lr_vec[8]; /* fa0 - fa7 or vr0 - vr7 or xr0 - xr7*/
+#endif
unsigned long int lr_ra;
unsigned long int lr_sp;
} La_loongarch_regs;
@@ -33,8 +49,10 @@ typedef struct La_loongarch_retval
{
unsigned long int lrv_a0;
unsigned long int lrv_a1;
- double lrv_fa0;
- double lrv_fa1;
+#ifndef __loongarch_soft_float
+ La_loongarch_vector lrv_vec0;
+ La_loongarch_vector lrv_vec1;
+#endif
} La_loongarch_retval;
__BEGIN_DECLS
diff --git a/sysdeps/loongarch/bits/link_lavcurrent.h b/sysdeps/loongarch/bits/link_lavcurrent.h
new file mode 100644
index 00000000..15f1eb84
--- /dev/null
+++ b/sysdeps/loongarch/bits/link_lavcurrent.h
@@ -0,0 +1,25 @@
+/* Data structure for communication from the run-time dynamic linker for
+ loaded ELF shared objects. LAV_CURRENT definition.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link_lavcurrent.h> directly; use <link.h> instead."
+#endif
+
+/* Version numbers for la_version handshake interface. */
+#define LAV_CURRENT 3
diff --git a/sysdeps/loongarch/dl-audit-check.h b/sysdeps/loongarch/dl-audit-check.h
new file mode 100644
index 00000000..a139c939
--- /dev/null
+++ b/sysdeps/loongarch/dl-audit-check.h
@@ -0,0 +1,23 @@
+/* rtld-audit version check. LoongArch version.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+static inline bool
+_dl_audit_check_version (unsigned int lav)
+{
+ return lav == LAV_CURRENT;
+}
diff --git a/sysdeps/loongarch/dl-link.sym b/sysdeps/loongarch/dl-link.sym
index 868ab7c6..b534968e 100644
--- a/sysdeps/loongarch/dl-link.sym
+++ b/sysdeps/loongarch/dl-link.sym
@@ -6,9 +6,13 @@ DL_SIZEOF_RG sizeof(struct La_loongarch_regs)
DL_SIZEOF_RV sizeof(struct La_loongarch_retval)
DL_OFFSET_RG_A0 offsetof(struct La_loongarch_regs, lr_reg)
-DL_OFFSET_RG_FA0 offsetof(struct La_loongarch_regs, lr_fpreg)
+#ifndef __loongarch_soft_float
+DL_OFFSET_RG_VEC0 offsetof(struct La_loongarch_regs, lr_vec)
+#endif
DL_OFFSET_RG_RA offsetof(struct La_loongarch_regs, lr_ra)
DL_OFFSET_RG_SP offsetof(struct La_loongarch_regs, lr_sp)
DL_OFFSET_RV_A0 offsetof(struct La_loongarch_retval, lrv_a0)
-DL_OFFSET_RV_FA0 offsetof(struct La_loongarch_retval, lrv_a1)
+#ifndef __loongarch_soft_float
+DL_OFFSET_RV_VEC0 offsetof(struct La_loongarch_retval, lrv_vec0)
+#endif
diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
index 066bb233..8a2db9de 100644
--- a/sysdeps/loongarch/dl-machine.h
+++ b/sysdeps/loongarch/dl-machine.h
@@ -273,6 +273,8 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
#if !defined __loongarch_soft_float
extern void _dl_runtime_resolve_lasx (void) attribute_hidden;
extern void _dl_runtime_resolve_lsx (void) attribute_hidden;
+ extern void _dl_runtime_profile_lasx (void) attribute_hidden;
+ extern void _dl_runtime_profile_lsx (void) attribute_hidden;
#endif
extern void _dl_runtime_resolve (void) attribute_hidden;
extern void _dl_runtime_profile (void) attribute_hidden;
@@ -287,7 +289,14 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
end in this function. */
if (profile != 0)
{
- gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile;
+#if !defined __loongarch_soft_float
+ if (SUPPORT_LASX)
+ gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lasx;
+ else if (SUPPORT_LSX)
+ gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile_lsx;
+ else
+#endif
+ gotplt[0] = (ElfW(Addr)) &_dl_runtime_profile;
if (GLRO(dl_profile) != NULL
&& _dl_name_match_p (GLRO(dl_profile), l))
diff --git a/sysdeps/loongarch/dl-trampoline.S b/sysdeps/loongarch/dl-trampoline.S
index 8fd91469..bb449ecf 100644
--- a/sysdeps/loongarch/dl-trampoline.S
+++ b/sysdeps/loongarch/dl-trampoline.S
@@ -22,190 +22,21 @@
#if !defined __loongarch_soft_float
#define USE_LASX
#define _dl_runtime_resolve _dl_runtime_resolve_lasx
+#define _dl_runtime_profile _dl_runtime_profile_lasx
#include "dl-trampoline.h"
#undef FRAME_SIZE
#undef USE_LASX
#undef _dl_runtime_resolve
+#undef _dl_runtime_profile
#define USE_LSX
#define _dl_runtime_resolve _dl_runtime_resolve_lsx
+#define _dl_runtime_profile _dl_runtime_profile_lsx
#include "dl-trampoline.h"
#undef FRAME_SIZE
#undef USE_LSX
#undef _dl_runtime_resolve
+#undef _dl_runtime_profile
#endif
#include "dl-trampoline.h"
-
-#include "dl-link.h"
-
-ENTRY (_dl_runtime_profile)
- /* LoongArch we get called with:
- t0 linkr_map pointer
- t1 the scaled offset stored in t0, which can be used
- to calculate the offset of the current symbol in .rela.plt
- t2 %hi(%pcrel(.got.plt)) stored in t2, no use in this function
- t3 dl resolver entry point, no use in this function
-
- Stack frame layout:
- [sp, #96] La_loongarch_regs
- [sp, #48] La_loongarch_retval
- [sp, #40] frame size return from pltenter
- [sp, #32] dl_profile_call saved a1
- [sp, #24] dl_profile_call saved a0
- [sp, #16] T1
- [sp, #0] ra, fp <- fp
- */
-
-# define OFFSET_T1 16
-# define OFFSET_SAVED_CALL_A0 OFFSET_T1 + 8
-# define OFFSET_FS OFFSET_SAVED_CALL_A0 + 16
-# define OFFSET_RV OFFSET_FS + 8
-# define OFFSET_RG OFFSET_RV + DL_SIZEOF_RV
-
-# define SF_SIZE (-(-(OFFSET_RG + DL_SIZEOF_RG) & ALMASK))
-
- /* Save arguments to stack. */
- ADDI sp, sp, -SF_SIZE
- REG_S ra, sp, 0
- REG_S fp, sp, 8
-
- or fp, sp, zero
-
- REG_S a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG
- REG_S a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG
- REG_S a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG
- REG_S a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG
- REG_S a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG
- REG_S a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG
- REG_S a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG
- REG_S a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG
-
-#ifndef __loongarch_soft_float
- FREG_S fa0, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 0*SZFREG
- FREG_S fa1, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 1*SZFREG
- FREG_S fa2, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 2*SZFREG
- FREG_S fa3, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 3*SZFREG
- FREG_S fa4, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 4*SZFREG
- FREG_S fa5, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 5*SZFREG
- FREG_S fa6, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 6*SZFREG
- FREG_S fa7, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 7*SZFREG
-#endif
-
- /* Update .got.plt and obtain runtime address of callee. */
- SLLI a1, t1, 1
- or a0, t0, zero
- ADD a1, a1, t1
- or a2, ra, zero /* return addr */
- ADDI a3, fp, OFFSET_RG /* La_loongarch_regs pointer */
- ADDI a4, fp, OFFSET_FS /* frame size return from pltenter */
-
- REG_S a0, fp, OFFSET_SAVED_CALL_A0
- REG_S a1, fp, OFFSET_SAVED_CALL_A0 + SZREG
-
- la t2, _dl_profile_fixup
- jirl ra, t2, 0
-
- REG_L t3, fp, OFFSET_FS
- bge t3, zero, 1f
-
- /* Save the return. */
- or t4, v0, zero
-
- /* Restore arguments from stack. */
- REG_L a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG
- REG_L a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG
- REG_L a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG
- REG_L a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG
- REG_L a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG
- REG_L a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG
- REG_L a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG
- REG_L a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG
-
-#ifndef __loongarch_soft_float
- FREG_L fa0, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 0*SZFREG
- FREG_L fa1, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 1*SZFREG
- FREG_L fa2, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 2*SZFREG
- FREG_L fa3, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 3*SZFREG
- FREG_L fa4, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 4*SZFREG
- FREG_L fa5, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 5*SZFREG
- FREG_L fa6, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 6*SZFREG
- FREG_L fa7, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 7*SZFREG
-#endif
-
- REG_L ra, fp, 0
- REG_L fp, fp, SZREG
-
- ADDI sp, sp, SF_SIZE
- jirl zero, t4, 0
-
-1:
- /* The new frame size is in t3. */
- SUB sp, fp, t3
- BSTRINS sp, zero, 3, 0
-
- REG_S a0, fp, OFFSET_T1
-
- or a0, sp, zero
- ADDI a1, fp, SF_SIZE
- or a2, t3, zero
- la t5, memcpy
- jirl ra, t5, 0
-
- REG_L t6, fp, OFFSET_T1
-
- /* Call the function. */
- REG_L a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG
- REG_L a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG
- REG_L a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG
- REG_L a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG
- REG_L a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG
- REG_L a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG
- REG_L a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG
- REG_L a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG
-
-#ifndef __loongarch_soft_float
- FREG_L fa0, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 0*SZFREG
- FREG_L fa1, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 1*SZFREG
- FREG_L fa2, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 2*SZFREG
- FREG_L fa3, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 3*SZFREG
- FREG_L fa4, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 4*SZFREG
- FREG_L fa5, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 5*SZFREG
- FREG_L fa6, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 6*SZFREG
- FREG_L fa7, fp, OFFSET_RG + DL_OFFSET_RG_FA0 + 7*SZFREG
-#endif
- jirl ra, t6, 0
-
- REG_S a0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_A0
- REG_S a1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_A0 + SZREG
-
-#ifndef __loongarch_soft_float
- FREG_S fa0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_FA0
- FREG_S fa1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_FA0 + SZFREG
-#endif
-
- /* Setup call to pltexit. */
- REG_L a0, fp, OFFSET_SAVED_CALL_A0
- REG_L a1, fp, OFFSET_SAVED_CALL_A0 + SZREG
- ADDI a2, fp, OFFSET_RG
- ADDI a3, fp, OFFSET_RV
- la t7, _dl_audit_pltexit
- jirl ra, t7, 0
-
- REG_L a0, fp, OFFSET_RV + DL_OFFSET_RV_A0
- REG_L a1, fp, OFFSET_RV + DL_OFFSET_RV_A0 + SZREG
-
-#ifndef __loongarch_soft_float
- FREG_L fa0, fp, OFFSET_RV + DL_OFFSET_RV_FA0
- FREG_L fa1, fp, OFFSET_RV + DL_OFFSET_RV_FA0 + SZFREG
-#endif
-
- /* RA from within La_loongarch_reg. */
- REG_L ra, fp, OFFSET_RG + DL_OFFSET_RG_RA
- or sp, fp, zero
- ADDI sp, sp, SF_SIZE
- REG_S fp, fp, SZREG
-
- jirl zero, ra, 0
-
-END (_dl_runtime_profile)
diff --git a/sysdeps/loongarch/dl-trampoline.h b/sysdeps/loongarch/dl-trampoline.h
index 99fcacab..e298439d 100644
--- a/sysdeps/loongarch/dl-trampoline.h
+++ b/sysdeps/loongarch/dl-trampoline.h
@@ -125,3 +125,245 @@ ENTRY (_dl_runtime_resolve)
/* Invoke the callee. */
jirl zero, t1, 0
END (_dl_runtime_resolve)
+
+#include "dl-link.h"
+
+ENTRY (_dl_runtime_profile)
+ /* LoongArch we get called with:
+ t0 linkr_map pointer
+ t1 the scaled offset stored in t0, which can be used
+ to calculate the offset of the current symbol in .rela.plt
+ t2 %hi(%pcrel(.got.plt)) stored in t2, no use in this function
+ t3 dl resolver entry point, no use in this function
+
+ Stack frame layout:
+ [sp, #208] La_loongarch_regs
+ [sp, #128] La_loongarch_retval // align: 16
+ [sp, #112] frame size return from pltenter
+ [sp, #80 ] dl_profile_call saved vec1
+ [sp, #48 ] dl_profile_call saved vec0 // align: 16
+ [sp, #32 ] dl_profile_call saved a1
+ [sp, #24 ] dl_profile_call saved a0
+ [sp, #16 ] T1
+ [sp, #0 ] ra, fp <- fp
+ */
+
+# define OFFSET_T1 16
+# define OFFSET_SAVED_CALL_A0 OFFSET_T1 + 8
+# define OFFSET_FS OFFSET_SAVED_CALL_A0 + 16 + 8 + 64
+# define OFFSET_RV OFFSET_FS + 8 + 8
+# define OFFSET_RG OFFSET_RV + DL_SIZEOF_RV
+
+# define SF_SIZE (-(-(OFFSET_RG + DL_SIZEOF_RG) & ALMASK))
+
+ /* Save arguments to stack. */
+ ADDI sp, sp, -SF_SIZE
+ REG_S ra, sp, 0
+ REG_S fp, sp, 8
+
+ or fp, sp, zero
+
+ REG_S a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG
+ REG_S a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG
+ REG_S a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG
+ REG_S a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG
+ REG_S a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG
+ REG_S a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG
+ REG_S a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG
+ REG_S a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG
+
+#ifdef USE_LASX
+ xvst xr0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZXREG
+ xvst xr1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZXREG
+ xvst xr2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZXREG
+ xvst xr3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZXREG
+ xvst xr4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZXREG
+ xvst xr5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZXREG
+ xvst xr6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZXREG
+ xvst xr7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZXREG
+#elif defined USE_LSX
+ vst vr0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZVREG
+ vst vr1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZVREG
+ vst vr2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZVREG
+ vst vr3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZVREG
+ vst vr4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZVREG
+ vst vr5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZVREG
+ vst vr6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZVREG
+ vst vr7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZVREG
+#elif !defined __loongarch_soft_float
+ FREG_S fa0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZFREG
+ FREG_S fa1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZFREG
+ FREG_S fa2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZFREG
+ FREG_S fa3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZFREG
+ FREG_S fa4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZFREG
+ FREG_S fa5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZFREG
+ FREG_S fa6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZFREG
+ FREG_S fa7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZFREG
+#endif
+
+ /* Update .got.plt and obtain runtime address of callee. */
+ SLLI a1, t1, 1
+ or a0, t0, zero
+ ADD a1, a1, t1
+ or a2, ra, zero /* return addr */
+ ADDI a3, fp, OFFSET_RG /* La_loongarch_regs pointer */
+ ADDI a4, fp, OFFSET_FS /* frame size return from pltenter */
+
+ REG_S a0, fp, OFFSET_SAVED_CALL_A0
+ REG_S a1, fp, OFFSET_SAVED_CALL_A0 + SZREG
+
+ la t2, _dl_profile_fixup
+ jirl ra, t2, 0
+
+ REG_L t3, fp, OFFSET_FS
+ bge t3, zero, 1f
+
+ /* Save the return. */
+ or t4, v0, zero
+
+ /* Restore arguments from stack. */
+ REG_L a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG
+ REG_L a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG
+ REG_L a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG
+ REG_L a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG
+ REG_L a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG
+ REG_L a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG
+ REG_L a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG
+ REG_L a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG
+
+#ifdef USE_LASX
+ xvld xr0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZXREG
+ xvld xr1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZXREG
+ xvld xr2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZXREG
+ xvld xr3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZXREG
+ xvld xr4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZXREG
+ xvld xr5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZXREG
+ xvld xr6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZXREG
+ xvld xr7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZXREG
+#elif defined USE_LSX
+ vld vr0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZVREG
+ vld vr1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZVREG
+ vld vr2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZVREG
+ vld vr3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZVREG
+ vld vr4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZVREG
+ vld vr5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZVREG
+ vld vr6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZVREG
+ vld vr7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZVREG
+#elif !defined __loongarch_soft_float
+ FREG_L fa0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZFREG
+ FREG_L fa1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZFREG
+ FREG_L fa2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZFREG
+ FREG_L fa3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZFREG
+ FREG_L fa4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZFREG
+ FREG_L fa5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZFREG
+ FREG_L fa6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZFREG
+ FREG_L fa7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZFREG
+#endif
+
+ REG_L ra, fp, 0
+ REG_L fp, fp, SZREG
+
+ ADDI sp, sp, SF_SIZE
+ jirl zero, t4, 0
+
+1:
+ /* The new frame size is in t3. */
+ SUB sp, fp, t3
+ BSTRINS sp, zero, 3, 0
+
+ REG_S a0, fp, OFFSET_T1
+
+ or a0, sp, zero
+ ADDI a1, fp, SF_SIZE
+ or a2, t3, zero
+ la t5, memcpy
+ jirl ra, t5, 0
+
+ REG_L t6, fp, OFFSET_T1
+
+ /* Call the function. */
+ REG_L a0, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 0*SZREG
+ REG_L a1, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 1*SZREG
+ REG_L a2, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 2*SZREG
+ REG_L a3, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 3*SZREG
+ REG_L a4, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 4*SZREG
+ REG_L a5, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 5*SZREG
+ REG_L a6, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 6*SZREG
+ REG_L a7, fp, OFFSET_RG + DL_OFFSET_RG_A0 + 7*SZREG
+
+#ifdef USE_LASX
+ xvld xr0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZXREG
+ xvld xr1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZXREG
+ xvld xr2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZXREG
+ xvld xr3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZXREG
+ xvld xr4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZXREG
+ xvld xr5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZXREG
+ xvld xr6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZXREG
+ xvld xr7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZXREG
+#elif defined USE_LSX
+ vld vr0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZVREG
+ vld vr1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZVREG
+ vld vr2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZVREG
+ vld vr3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZVREG
+ vld vr4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZVREG
+ vld vr5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZVREG
+ vld vr6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZVREG
+ vld vr7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZVREG
+#elif !defined __loongarch_soft_float
+ FREG_L fa0, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 0*SZFREG
+ FREG_L fa1, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 1*SZFREG
+ FREG_L fa2, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 2*SZFREG
+ FREG_L fa3, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 3*SZFREG
+ FREG_L fa4, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 4*SZFREG
+ FREG_L fa5, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 5*SZFREG
+ FREG_L fa6, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 6*SZFREG
+ FREG_L fa7, fp, OFFSET_RG + DL_OFFSET_RG_VEC0 + 7*SZFREG
+#endif
+
+ jirl ra, t6, 0
+
+ REG_S a0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_A0
+ REG_S a1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_A0 + SZREG
+
+#ifdef USE_LASX
+ xvst xr0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0
+ xvst xr1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 + SZXREG
+#elif defined USE_LSX
+ vst vr0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0
+ vst vr1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 + SZVREG
+#elif !defined __loongarch_soft_float
+ FREG_S fa0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0
+ FREG_S fa1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 + SZFREG
+#endif
+
+ /* Setup call to pltexit. */
+ REG_L a0, fp, OFFSET_SAVED_CALL_A0
+ REG_L a1, fp, OFFSET_SAVED_CALL_A0 + SZREG
+ ADDI a2, fp, OFFSET_RG
+ ADDI a3, fp, OFFSET_RV
+ la t7, _dl_audit_pltexit
+ jirl ra, t7, 0
+
+ REG_L a0, fp, OFFSET_RV + DL_OFFSET_RV_A0
+ REG_L a1, fp, OFFSET_RV + DL_OFFSET_RV_A0 + SZREG
+
+#ifdef USE_LASX
+ xvld xr0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0
+ xvld xr1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 + SZXREG
+#elif defined USE_LSX
+ vld vr0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0
+ vld vr1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 + SZVREG
+#elif !defined __loongarch_soft_float
+ FREG_L fa0, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0
+ FREG_L fa1, fp, OFFSET_SAVED_CALL_A0 + DL_OFFSET_RV_VEC0 + SZFREG
+#endif
+
+ /* RA from within La_loongarch_reg. */
+ REG_L ra, fp, OFFSET_RG + DL_OFFSET_RG_RA
+ or sp, fp, zero
+ ADDI sp, sp, SF_SIZE
+ REG_S fp, fp, SZREG
+
+ jirl zero, ra, 0
+
+END (_dl_runtime_profile)
--
2.33.0

View file

@ -0,0 +1,102 @@
From 7353f21f6ed1754b67e455e2b80123787efa9e91 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Tue, 8 Aug 2023 14:15:43 +0800
Subject: [PATCH 02/29] LoongArch: Add minuimum binutils required version
LoongArch glibc can add some LASX/LSX vector instructions codes,
change the required minimum binutils version to 2.41 which could
support vector instructions. HAVE_LOONGARCH_VEC_ASM is removed
accordingly.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
config.h.in | 5 -----
sysdeps/loongarch/configure | 5 ++---
sysdeps/loongarch/configure.ac | 4 ++--
sysdeps/loongarch/dl-machine.h | 4 ++--
sysdeps/loongarch/dl-trampoline.S | 2 +-
5 files changed, 7 insertions(+), 13 deletions(-)
diff --git a/config.h.in b/config.h.in
index 0dedc124..44a34072 100644
--- a/config.h.in
+++ b/config.h.in
@@ -141,11 +141,6 @@
/* LOONGARCH floating-point ABI for ld.so. */
#undef LOONGARCH_ABI_FRLEN
-/* Assembler support LoongArch LASX/LSX vector instructions.
- This macro becomes obsolete when glibc increased the minimum
- required version of GNU 'binutils' to 2.41 or later. */
-#define HAVE_LOONGARCH_VEC_ASM 0
-
/* Linux specific: minimum supported kernel version. */
#undef __LINUX_KERNEL_VERSION
diff --git a/sysdeps/loongarch/configure b/sysdeps/loongarch/configure
index 5843c7cf..395ddc92 100644
--- a/sysdeps/loongarch/configure
+++ b/sysdeps/loongarch/configure
@@ -128,8 +128,7 @@ rm -f conftest*
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_loongarch_vec_asm" >&5
printf "%s\n" "$libc_cv_loongarch_vec_asm" >&6; }
-if test $libc_cv_loongarch_vec_asm = yes; then
- printf "%s\n" "#define HAVE_LOONGARCH_VEC_ASM 1" >>confdefs.h
-
+if test $libc_cv_loongarch_vec_asm = no; then
+ as_fn_error $? "binutils version is too old, use 2.41 or newer version" "$LINENO" 5
fi
diff --git a/sysdeps/loongarch/configure.ac b/sysdeps/loongarch/configure.ac
index ba89d834..989287c6 100644
--- a/sysdeps/loongarch/configure.ac
+++ b/sysdeps/loongarch/configure.ac
@@ -74,6 +74,6 @@ else
libc_cv_loongarch_vec_asm=no
fi
rm -f conftest*])
-if test $libc_cv_loongarch_vec_asm = yes; then
- AC_DEFINE(HAVE_LOONGARCH_VEC_ASM)
+if test $libc_cv_loongarch_vec_asm = no; then
+ AC_MSG_ERROR([binutils version is too old, use 2.41 or newer version])
fi
diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
index 51ce9af8..066bb233 100644
--- a/sysdeps/loongarch/dl-machine.h
+++ b/sysdeps/loongarch/dl-machine.h
@@ -270,7 +270,7 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
/* If using PLTs, fill in the first two entries of .got.plt. */
if (l->l_info[DT_JMPREL])
{
-#if HAVE_LOONGARCH_VEC_ASM && !defined __loongarch_soft_float
+#if !defined __loongarch_soft_float
extern void _dl_runtime_resolve_lasx (void) attribute_hidden;
extern void _dl_runtime_resolve_lsx (void) attribute_hidden;
#endif
@@ -300,7 +300,7 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
/* This function will get called to fix up the GOT entry
indicated by the offset on the stack, and then jump to
the resolved address. */
-#if HAVE_LOONGARCH_VEC_ASM && !defined __loongarch_soft_float
+#if !defined __loongarch_soft_float
if (SUPPORT_LASX)
gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve_lasx;
else if (SUPPORT_LSX)
diff --git a/sysdeps/loongarch/dl-trampoline.S b/sysdeps/loongarch/dl-trampoline.S
index f6ba5e44..8fd91469 100644
--- a/sysdeps/loongarch/dl-trampoline.S
+++ b/sysdeps/loongarch/dl-trampoline.S
@@ -19,7 +19,7 @@
#include <sysdep.h>
#include <sys/asm.h>
-#if HAVE_LOONGARCH_VEC_ASM && !defined __loongarch_soft_float
+#if !defined __loongarch_soft_float
#define USE_LASX
#define _dl_runtime_resolve _dl_runtime_resolve_lasx
#include "dl-trampoline.h"
--
2.33.0

View file

@ -0,0 +1,277 @@
From e5ccd79e81de7ad5821fde83875973e878d85d4b Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Mon, 28 Aug 2023 10:08:40 +0800
Subject: [PATCH 19/29] LoongArch: Change loongarch to LoongArch in comments
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S | 2 +-
sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S | 2 +-
sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S | 2 +-
sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S | 2 +-
sysdeps/loongarch/lp64/multiarch/memmove-aligned.S | 2 +-
sysdeps/loongarch/lp64/multiarch/memmove-lasx.S | 2 +-
sysdeps/loongarch/lp64/multiarch/memmove-lsx.S | 2 +-
sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strchr-aligned.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strchr-lasx.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strchr-lsx.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strlen-aligned.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strlen-lasx.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strlen-lsx.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S | 2 +-
sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S | 2 +-
24 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S b/sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S
index 299dd49c..7eb34395 100644
--- a/sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S
+++ b/sysdeps/loongarch/lp64/multiarch/memcpy-aligned.S
@@ -1,4 +1,4 @@
-/* Optimized memcpy_aligned implementation using basic Loongarch instructions.
+/* Optimized memcpy_aligned implementation using basic LoongArch instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S b/sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S
index 4aae5bf8..ae148df5 100644
--- a/sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S
+++ b/sysdeps/loongarch/lp64/multiarch/memcpy-lasx.S
@@ -1,4 +1,4 @@
-/* Optimized memcpy implementation using Loongarch LASX instructions.
+/* Optimized memcpy implementation using LoongArch LASX instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S b/sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S
index 6ebbe7a2..feb2bb0e 100644
--- a/sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S
+++ b/sysdeps/loongarch/lp64/multiarch/memcpy-lsx.S
@@ -1,4 +1,4 @@
-/* Optimized memcpy implementation using Loongarch LSX instructions.
+/* Optimized memcpy implementation using LoongArch LSX instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S b/sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S
index 8e60a22d..31019b13 100644
--- a/sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S
+++ b/sysdeps/loongarch/lp64/multiarch/memcpy-unaligned.S
@@ -1,4 +1,4 @@
-/* Optimized unaligned memcpy implementation using basic Loongarch instructions.
+/* Optimized unaligned memcpy implementation using basic LoongArch instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-aligned.S b/sysdeps/loongarch/lp64/multiarch/memmove-aligned.S
index 5354f383..a02114c0 100644
--- a/sysdeps/loongarch/lp64/multiarch/memmove-aligned.S
+++ b/sysdeps/loongarch/lp64/multiarch/memmove-aligned.S
@@ -1,4 +1,4 @@
-/* Optimized memmove_aligned implementation using basic Loongarch instructions.
+/* Optimized memmove_aligned implementation using basic LoongArch instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-lasx.S b/sysdeps/loongarch/lp64/multiarch/memmove-lasx.S
index ff68e7a2..95d8ee7b 100644
--- a/sysdeps/loongarch/lp64/multiarch/memmove-lasx.S
+++ b/sysdeps/loongarch/lp64/multiarch/memmove-lasx.S
@@ -1,4 +1,4 @@
-/* Optimized memmove implementation using Loongarch LASX instructions.
+/* Optimized memmove implementation using LoongArch LASX instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S b/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S
index 9e1502a7..8a936770 100644
--- a/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S
+++ b/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S
@@ -1,4 +1,4 @@
-/* Optimized memmove implementation using Loongarch LSX instructions.
+/* Optimized memmove implementation using LoongArch LSX instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S b/sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S
index 90a64b6b..3284ce25 100644
--- a/sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S
+++ b/sysdeps/loongarch/lp64/multiarch/memmove-unaligned.S
@@ -1,4 +1,4 @@
-/* Optimized memmove_unaligned implementation using basic Loongarch instructions.
+/* Optimized memmove_unaligned implementation using basic LoongArch instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strchr-aligned.S b/sysdeps/loongarch/lp64/multiarch/strchr-aligned.S
index 5fb01806..62020054 100644
--- a/sysdeps/loongarch/lp64/multiarch/strchr-aligned.S
+++ b/sysdeps/loongarch/lp64/multiarch/strchr-aligned.S
@@ -1,4 +1,4 @@
-/* Optimized strchr implementation using basic Loongarch instructions.
+/* Optimized strchr implementation using basic LoongArch instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strchr-lasx.S b/sysdeps/loongarch/lp64/multiarch/strchr-lasx.S
index 254402da..4d3cc588 100644
--- a/sysdeps/loongarch/lp64/multiarch/strchr-lasx.S
+++ b/sysdeps/loongarch/lp64/multiarch/strchr-lasx.S
@@ -1,4 +1,4 @@
-/* Optimized strchr implementation using loongarch LASX SIMD instructions.
+/* Optimized strchr implementation using LoongArch LASX instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strchr-lsx.S b/sysdeps/loongarch/lp64/multiarch/strchr-lsx.S
index dae98b0a..8b78c35c 100644
--- a/sysdeps/loongarch/lp64/multiarch/strchr-lsx.S
+++ b/sysdeps/loongarch/lp64/multiarch/strchr-lsx.S
@@ -1,4 +1,4 @@
-/* Optimized strlen implementation using loongarch LSX SIMD instructions.
+/* Optimized strlen implementation using LoongArch LSX instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S b/sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S
index 1c01a023..20856a06 100644
--- a/sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S
+++ b/sysdeps/loongarch/lp64/multiarch/strchrnul-aligned.S
@@ -1,4 +1,4 @@
-/* Optimized strchrnul implementation using basic Loongarch instructions.
+/* Optimized strchrnul implementation using basic LoongArch instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S b/sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S
index d45495e4..4753d4ce 100644
--- a/sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S
+++ b/sysdeps/loongarch/lp64/multiarch/strchrnul-lasx.S
@@ -1,4 +1,4 @@
-/* Optimized strchrnul implementation using loongarch LASX SIMD instructions.
+/* Optimized strchrnul implementation using LoongArch LASX instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S b/sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S
index 07d793ae..671e740c 100644
--- a/sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S
+++ b/sysdeps/loongarch/lp64/multiarch/strchrnul-lsx.S
@@ -1,4 +1,4 @@
-/* Optimized strchrnul implementation using loongarch LSX SIMD instructions.
+/* Optimized strchrnul implementation using LoongArch LSX instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S b/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S
index f5f4f336..ba1f9667 100644
--- a/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S
+++ b/sysdeps/loongarch/lp64/multiarch/strcmp-aligned.S
@@ -1,4 +1,4 @@
-/* Optimized strcmp implementation using basic Loongarch instructions.
+/* Optimized strcmp implementation using basic LoongArch instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S b/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S
index 2e177a38..091c8c9e 100644
--- a/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S
+++ b/sysdeps/loongarch/lp64/multiarch/strcmp-lsx.S
@@ -1,4 +1,4 @@
-/* Optimized strcmp implementation using Loongarch LSX instructions.
+/* Optimized strcmp implementation using LoongArch LSX instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S b/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S
index e9e1d2fc..ed0548e4 100644
--- a/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S
+++ b/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S
@@ -1,4 +1,4 @@
-/* Optimized strlen implementation using basic Loongarch instructions.
+/* Optimized strlen implementation using basic LoongArch instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S b/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S
index 258c47ce..91342f34 100644
--- a/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S
+++ b/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S
@@ -1,4 +1,4 @@
-/* Optimized strlen implementation using loongarch LASX SIMD instructions.
+/* Optimized strlen implementation using LoongArch LASX instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S b/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S
index b194355e..b09c12e0 100644
--- a/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S
+++ b/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S
@@ -1,4 +1,4 @@
-/* Optimized strlen implementation using Loongarch LSX SIMD instructions.
+/* Optimized strlen implementation using LoongArch LSX instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S b/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S
index e2687fa7..f63de872 100644
--- a/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S
+++ b/sysdeps/loongarch/lp64/multiarch/strncmp-aligned.S
@@ -1,4 +1,4 @@
-/* Optimized strncmp implementation using basic Loongarch instructions.
+/* Optimized strncmp implementation using basic LoongArch instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S b/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S
index 0b4eee2a..83cb801d 100644
--- a/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S
+++ b/sysdeps/loongarch/lp64/multiarch/strncmp-lsx.S
@@ -1,4 +1,4 @@
-/* Optimized strncmp implementation using Loongarch LSX instructions.
+/* Optimized strncmp implementation using LoongArch LSX instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S b/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S
index b900430a..a8296a1b 100644
--- a/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S
+++ b/sysdeps/loongarch/lp64/multiarch/strnlen-aligned.S
@@ -1,4 +1,4 @@
-/* Optimized strnlen implementation using basic Loongarch instructions.
+/* Optimized strnlen implementation using basic LoongArch instructions.
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S b/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S
index 2c03d3d9..aa6c812d 100644
--- a/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S
+++ b/sysdeps/loongarch/lp64/multiarch/strnlen-lasx.S
@@ -1,4 +1,4 @@
-/* Optimized strnlen implementation using loongarch LASX instructions
+/* Optimized strnlen implementation using LoongArch LASX instructions
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
diff --git a/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S b/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S
index b769a895..d0febe3e 100644
--- a/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S
+++ b/sysdeps/loongarch/lp64/multiarch/strnlen-lsx.S
@@ -1,4 +1,4 @@
-/* Optimized strnlen implementation using loongarch LSX instructions
+/* Optimized strnlen implementation using LoongArch LSX instructions
Copyright (C) 2023 Free Software Foundation, Inc.
This file is part of the GNU C Library.
--
2.33.0

View file

@ -0,0 +1,67 @@
From fb72c81f9894b23797f6e2e066532c0963f5155f Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Wed, 13 Sep 2023 15:35:01 +0800
Subject: [PATCH 24/29] LoongArch: Change to put magic number to .rodata
section
Change to put magic number to .rodata section in memmove-lsx, and use
pcalau12i and %pc_lo12 with vld to get the data.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
.../loongarch/lp64/multiarch/memmove-lsx.S | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S b/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S
index 8a936770..5eb819ef 100644
--- a/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S
+++ b/sysdeps/loongarch/lp64/multiarch/memmove-lsx.S
@@ -209,13 +209,10 @@ L(al_less_16):
nop
-L(magic_num):
- .dword 0x0706050403020100
- .dword 0x0f0e0d0c0b0a0908
L(unaligned):
- pcaddi t2, -4
+ pcalau12i t2, %pc_hi20(L(INDEX))
bstrins.d a1, zero, 3, 0
- vld vr8, t2, 0
+ vld vr8, t2, %pc_lo12(L(INDEX))
vld vr0, a1, 0
vld vr1, a1, 16
@@ -413,13 +410,10 @@ L(back_al_less_16):
vst vr1, a0, 0
jr ra
-L(magic_num_2):
- .dword 0x0706050403020100
- .dword 0x0f0e0d0c0b0a0908
L(back_unaligned):
- pcaddi t2, -4
+ pcalau12i t2, %pc_hi20(L(INDEX))
bstrins.d a4, zero, 3, 0
- vld vr8, t2, 0
+ vld vr8, t2, %pc_lo12(L(INDEX))
vld vr0, a4, 0
vld vr1, a4, -16
@@ -529,6 +523,12 @@ L(back_un_less_16):
jr ra
END(MEMMOVE_NAME)
+ .section .rodata.cst16,"M",@progbits,16
+ .align 4
+L(INDEX):
+ .dword 0x0706050403020100
+ .dword 0x0f0e0d0c0b0a0908
+
libc_hidden_builtin_def (MEMCPY_NAME)
libc_hidden_builtin_def (MEMMOVE_NAME)
#endif
--
2.33.0

View file

@ -0,0 +1,44 @@
From 7f703cf758c4f185dd62f2a4f463002bb514af16 Mon Sep 17 00:00:00 2001
From: Xi Ruoyao <xry111@xry111.site>
Date: Sun, 27 Aug 2023 00:36:51 +0800
Subject: [PATCH 13/29] LoongArch: Micro-optimize LD_PCREL
We are requiring Binutils >= 2.41, so explicit relocation syntax is
always supported by the assembler. Use it to reduce one instruction.
Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/unix/sysv/linux/loongarch/pointer_guard.h | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/sysdeps/unix/sysv/linux/loongarch/pointer_guard.h b/sysdeps/unix/sysv/linux/loongarch/pointer_guard.h
index b25e353b..d6c78687 100644
--- a/sysdeps/unix/sysv/linux/loongarch/pointer_guard.h
+++ b/sysdeps/unix/sysv/linux/loongarch/pointer_guard.h
@@ -19,17 +19,15 @@
#ifndef POINTER_GUARD_H
#define POINTER_GUARD_H
-/* Load a got-relative EXPR into G, using T.
- Note G and T are register names. */
+/* Load a got-relative EXPR into register G. */
#define LD_GLOBAL(G, EXPR) \
la.global G, EXPR; \
REG_L G, G, 0;
-/* Load a pc-relative EXPR into G, using T.
- Note G and T are register names. */
+/* Load a pc-relative EXPR into register G. */
#define LD_PCREL(G, EXPR) \
- la.pcrel G, EXPR; \
- REG_L G, G, 0;
+ pcalau12i G, %pc_hi20(EXPR); \
+ REG_L G, G, %pc_lo12(EXPR);
#if (IS_IN (rtld) \
|| (!defined SHARED && (IS_IN (libc) \
--
2.33.0

View file

@ -0,0 +1,65 @@
From 8dcd8c837df2e3cf81675522487697522f1542f8 Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Tue, 8 Aug 2023 14:15:42 +0800
Subject: [PATCH 01/29] LoongArch: Redefine macro LEAF/ENTRY.
The following usage of macro LEAF/ENTRY are all feasible:
1. LEAF(fcn) -- the align value of fcn is .align 3(default value)
2. LEAF(fcn, 6) -- the align value of fcn is .align 6
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/sys/asm.h | 36 ++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/sysdeps/loongarch/sys/asm.h b/sysdeps/loongarch/sys/asm.h
index d1a279b8..c5eb8afa 100644
--- a/sysdeps/loongarch/sys/asm.h
+++ b/sysdeps/loongarch/sys/asm.h
@@ -39,16 +39,32 @@
#define FREG_L fld.d
#define FREG_S fst.d
-/* Declare leaf routine. */
-#define LEAF(symbol) \
- .text; \
- .globl symbol; \
- .align 3; \
- cfi_startproc; \
- .type symbol, @function; \
- symbol:
-
-#define ENTRY(symbol) LEAF (symbol)
+/* Declare leaf routine.
+ The usage of macro LEAF/ENTRY is as follows:
+ 1. LEAF(fcn) -- the align value of fcn is .align 3 (default value)
+ 2. LEAF(fcn, 6) -- the align value of fcn is .align 6
+*/
+#define LEAF_IMPL(symbol, aln, ...) \
+ .text; \
+ .globl symbol; \
+ .align aln; \
+ .type symbol, @function; \
+symbol: \
+ cfi_startproc;
+
+
+#define LEAF(...) LEAF_IMPL(__VA_ARGS__, 3)
+#define ENTRY(...) LEAF(__VA_ARGS__)
+
+#define LEAF_NO_ALIGN(symbol) \
+ .text; \
+ .globl symbol; \
+ .type symbol, @function; \
+symbol: \
+ cfi_startproc;
+
+#define ENTRY_NO_ALIGN(symbol) LEAF_NO_ALIGN(symbol)
+
/* Mark end of function. */
#undef END
--
2.33.0

View file

@ -0,0 +1,56 @@
From f8d66a269cb6f1a7087afadf3375bdf0553abf53 Mon Sep 17 00:00:00 2001
From: Xi Ruoyao <xry111@xry111.site>
Date: Sun, 27 Aug 2023 00:36:50 +0800
Subject: [PATCH 12/29] LoongArch: Remove support code for old linker in
start.S
We are requiring Binutils >= 2.41, so la.pcrel always works here.
Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/start.S | 19 +++----------------
1 file changed, 3 insertions(+), 16 deletions(-)
diff --git a/sysdeps/loongarch/start.S b/sysdeps/loongarch/start.S
index e9d82033..bf6bfc9e 100644
--- a/sysdeps/loongarch/start.S
+++ b/sysdeps/loongarch/start.S
@@ -60,20 +60,7 @@ ENTRY (ENTRY_POINT)
cfi_undefined (1)
or a5, a0, zero /* rtld_fini */
-#if ENABLE_STATIC_PIE
-/* For static PIE, the GOT cannot be used in _start because the GOT entries are
- offsets instead of real addresses before __libc_start_main.
- __libc_start_main and/or main may be not local, so we rely on the linker to
- produce PLT entries for them. GNU ld >= 2.40 supports this. */
-# define LA la.pcrel
-#else
-/* Old GNU ld (< 2.40) cannot handle PC relative address against a non-local
- function correctly. We deem these old linkers failing to support static PIE
- and load the addresses from GOT. */
-# define LA la.got
-#endif
-
- LA a0, t0, main
+ la.pcrel a0, t0, main
REG_L a1, sp, 0
ADDI a2, sp, SZREG
@@ -84,9 +71,9 @@ ENTRY (ENTRY_POINT)
move a4, zero /* used to be fini */
or a6, sp, zero /* stack_end */
- LA ra, t0, __libc_start_main
+ la.pcrel ra, t0, __libc_start_main
jirl ra, ra, 0
- LA ra, t0, abort
+ la.pcrel ra, t0, abort
jirl ra, ra, 0
END (ENTRY_POINT)
--
2.33.0

View file

@ -0,0 +1,28 @@
From b4b4bb7c9220a0bbdf5aec0ac8c1de1d22329280 Mon Sep 17 00:00:00 2001
From: caiyinyu <caiyinyu@loongson.cn>
Date: Thu, 14 Sep 2023 19:48:24 +0800
Subject: [PATCH 21/29] LoongArch: Replace deprecated $v0 with $a0 to eliminate
'as' Warnings.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/dl-machine.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
index 8a2db9de..57913cef 100644
--- a/sysdeps/loongarch/dl-machine.h
+++ b/sysdeps/loongarch/dl-machine.h
@@ -90,7 +90,7 @@ static inline ElfW (Addr) elf_machine_dynamic (void)
or $a0, $sp, $zero \n\
bl _dl_start \n\
# Stash user entry point in s0. \n\
- or $s0, $v0, $zero \n\
+ or $s0, $a0, $zero \n\
# Load the original argument count. \n\
ld.d $a1, $sp, 0 \n\
# Call _dl_init (struct link_map *main_map, int argc, \
--
2.33.0

View file

@ -0,0 +1,81 @@
From 458ab6d5f39cca1cabd83abd2022f67491f6f5ed Mon Sep 17 00:00:00 2001
From: caiyinyu <caiyinyu@loongson.cn>
Date: Fri, 20 Oct 2023 09:20:02 +0800
Subject: [PATCH 27/29] LoongArch: Unify Register Names.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/__longjmp.S | 20 ++++++++++----------
sysdeps/loongarch/setjmp.S | 18 +++++++++---------
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/sysdeps/loongarch/__longjmp.S b/sysdeps/loongarch/__longjmp.S
index cbde1946..e87ce311 100644
--- a/sysdeps/loongarch/__longjmp.S
+++ b/sysdeps/loongarch/__longjmp.S
@@ -43,18 +43,18 @@ ENTRY (__longjmp)
REG_L s8, a0, 12*SZREG
#ifndef __loongarch_soft_float
- FREG_L $f24, a0, 13*SZREG + 0*SZFREG
- FREG_L $f25, a0, 13*SZREG + 1*SZFREG
- FREG_L $f26, a0, 13*SZREG + 2*SZFREG
- FREG_L $f27, a0, 13*SZREG + 3*SZFREG
- FREG_L $f28, a0, 13*SZREG + 4*SZFREG
- FREG_L $f29, a0, 13*SZREG + 5*SZFREG
- FREG_L $f30, a0, 13*SZREG + 6*SZFREG
- FREG_L $f31, a0, 13*SZREG + 7*SZFREG
+ FREG_L fs0, a0, 13*SZREG + 0*SZFREG
+ FREG_L fs1, a0, 13*SZREG + 1*SZFREG
+ FREG_L fs2, a0, 13*SZREG + 2*SZFREG
+ FREG_L fs3, a0, 13*SZREG + 3*SZFREG
+ FREG_L fs4, a0, 13*SZREG + 4*SZFREG
+ FREG_L fs5, a0, 13*SZREG + 5*SZFREG
+ FREG_L fs6, a0, 13*SZREG + 6*SZFREG
+ FREG_L fs7, a0, 13*SZREG + 7*SZFREG
#endif
- sltui a0,a1,1
+ sltui a0, a1, 1
ADD a0, a0, a1 # a0 = (a1 == 0) ? 1 : a1
- jirl zero,ra,0
+ jirl zero, ra, 0
END (__longjmp)
diff --git a/sysdeps/loongarch/setjmp.S b/sysdeps/loongarch/setjmp.S
index 6c7065cd..b6e4f727 100644
--- a/sysdeps/loongarch/setjmp.S
+++ b/sysdeps/loongarch/setjmp.S
@@ -52,19 +52,19 @@ ENTRY (__sigsetjmp)
REG_S s8, a0, 12*SZREG
#ifndef __loongarch_soft_float
- FREG_S $f24, a0, 13*SZREG + 0*SZFREG
- FREG_S $f25, a0, 13*SZREG + 1*SZFREG
- FREG_S $f26, a0, 13*SZREG + 2*SZFREG
- FREG_S $f27, a0, 13*SZREG + 3*SZFREG
- FREG_S $f28, a0, 13*SZREG + 4*SZFREG
- FREG_S $f29, a0, 13*SZREG + 5*SZFREG
- FREG_S $f30, a0, 13*SZREG + 6*SZFREG
- FREG_S $f31, a0, 13*SZREG + 7*SZFREG
+ FREG_S fs0, a0, 13*SZREG + 0*SZFREG
+ FREG_S fs1, a0, 13*SZREG + 1*SZFREG
+ FREG_S fs2, a0, 13*SZREG + 2*SZFREG
+ FREG_S fs3, a0, 13*SZREG + 3*SZFREG
+ FREG_S fs4, a0, 13*SZREG + 4*SZFREG
+ FREG_S fs5, a0, 13*SZREG + 5*SZFREG
+ FREG_S fs6, a0, 13*SZREG + 6*SZFREG
+ FREG_S fs7, a0, 13*SZREG + 7*SZFREG
#endif
#if !IS_IN (libc) && IS_IN(rtld)
li.w v0, 0
- jirl zero,ra,0
+ jirl zero, ra, 0
#else
b __sigjmp_save
#endif
--
2.33.0

View file

@ -0,0 +1,24 @@
From 4828d1aa0028e819a5fb336d962e8f7cbfedf8b4 Mon Sep 17 00:00:00 2001
From: caiyinyu <caiyinyu@loongson.cn>
Date: Mon, 23 Oct 2023 15:53:38 +0800
Subject: [PATCH 28/29] LoongArch: Update hwcap.h to sync with LoongArch
kernel.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/unix/sysv/linux/loongarch/bits/hwcap.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/hwcap.h b/sysdeps/unix/sysv/linux/loongarch/bits/hwcap.h
index 5104b69c..7acec23d 100644
--- a/sysdeps/unix/sysv/linux/loongarch/bits/hwcap.h
+++ b/sysdeps/unix/sysv/linux/loongarch/bits/hwcap.h
@@ -35,3 +35,4 @@
#define HWCAP_LOONGARCH_LBT_X86 (1 << 10)
#define HWCAP_LOONGARCH_LBT_ARM (1 << 11)
#define HWCAP_LOONGARCH_LBT_MIPS (1 << 12)
+#define HWCAP_LOONGARCH_PTW (1 << 13)
--
2.33.0

View file

@ -0,0 +1,30 @@
From 4938840b15ff9734fdcc63cc0744ce3f3bbb0b16 Mon Sep 17 00:00:00 2001
From: caiyinyu <caiyinyu@loongson.cn>
Date: Mon, 14 Aug 2023 15:34:08 +0800
Subject: [PATCH 05/29] LoongArch: elf: Add new LoongArch reloc types 109 into
elf.h
These reloc types are generated by GNU assembler >= 2.41 for relaxation
support.
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
elf/elf.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/elf/elf.h b/elf/elf.h
index d623bdeb..9c51073f 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -4213,6 +4213,7 @@ enum
#define R_LARCH_SUB6 106
#define R_LARCH_ADD_ULEB128 107
#define R_LARCH_SUB_ULEB128 108
+#define R_LARCH_64_PCREL 109
/* ARC specific declarations. */
--
2.33.0

View file

@ -0,0 +1,528 @@
From 43abd8772a143cd96688c081500397dd712e631b Mon Sep 17 00:00:00 2001
From: dengjianbo <dengjianbo@loongson.cn>
Date: Tue, 8 Aug 2023 14:15:44 +0800
Subject: [PATCH 03/29] Loongarch: Add ifunc support and add different versions
of strlen
strlen-lasx is implemeted by LASX simd instructions(256bit)
strlen-lsx is implemeted by LSX simd instructions(128bit)
strlen-align is implemented by LA basic instructions and never use unaligned memory acess
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
---
sysdeps/loongarch/lp64/multiarch/Makefile | 7 ++
.../lp64/multiarch/ifunc-impl-list.c | 41 +++++++
.../loongarch/lp64/multiarch/ifunc-strlen.h | 40 +++++++
.../loongarch/lp64/multiarch/strlen-aligned.S | 100 ++++++++++++++++++
.../loongarch/lp64/multiarch/strlen-lasx.S | 63 +++++++++++
sysdeps/loongarch/lp64/multiarch/strlen-lsx.S | 71 +++++++++++++
sysdeps/loongarch/lp64/multiarch/strlen.c | 37 +++++++
sysdeps/loongarch/sys/regdef.h | 57 ++++++++++
.../unix/sysv/linux/loongarch/cpu-features.h | 2 +
9 files changed, 418 insertions(+)
create mode 100644 sysdeps/loongarch/lp64/multiarch/Makefile
create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
create mode 100644 sysdeps/loongarch/lp64/multiarch/ifunc-strlen.h
create mode 100644 sysdeps/loongarch/lp64/multiarch/strlen-aligned.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/strlen-lasx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/strlen-lsx.S
create mode 100644 sysdeps/loongarch/lp64/multiarch/strlen.c
diff --git a/sysdeps/loongarch/lp64/multiarch/Makefile b/sysdeps/loongarch/lp64/multiarch/Makefile
new file mode 100644
index 00000000..76c506c9
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/Makefile
@@ -0,0 +1,7 @@
+ifeq ($(subdir),string)
+sysdep_routines += \
+ strlen-aligned \
+ strlen-lsx \
+ strlen-lasx \
+# sysdep_routines
+endif
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
new file mode 100644
index 00000000..1a2a576f
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-impl-list.c
@@ -0,0 +1,41 @@
+/* Enumerate available IFUNC implementations of a function LoongArch64 version.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <string.h>
+#include <wchar.h>
+#include <ldsodefs.h>
+#include <ifunc-impl-list.h>
+#include <stdio.h>
+
+size_t
+__libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
+ size_t max)
+{
+
+ size_t i = max;
+
+ IFUNC_IMPL (i, name, strlen,
+#if !defined __loongarch_soft_float
+ IFUNC_IMPL_ADD (array, i, strlen, SUPPORT_LASX, __strlen_lasx)
+ IFUNC_IMPL_ADD (array, i, strlen, SUPPORT_LSX, __strlen_lsx)
+#endif
+ IFUNC_IMPL_ADD (array, i, strlen, 1, __strlen_aligned)
+ )
+ return i;
+}
diff --git a/sysdeps/loongarch/lp64/multiarch/ifunc-strlen.h b/sysdeps/loongarch/lp64/multiarch/ifunc-strlen.h
new file mode 100644
index 00000000..6258bb76
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/ifunc-strlen.h
@@ -0,0 +1,40 @@
+/* Common definition for strlen ifunc selections.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+#include <ifunc-init.h>
+
+#if !defined __loongarch_soft_float
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lasx) attribute_hidden;
+extern __typeof (REDIRECT_NAME) OPTIMIZE (lsx) attribute_hidden;
+#endif
+extern __typeof (REDIRECT_NAME) OPTIMIZE (aligned) attribute_hidden;
+
+static inline void *
+IFUNC_SELECTOR (void)
+{
+#if !defined __loongarch_soft_float
+ if (SUPPORT_LASX)
+ return OPTIMIZE (lasx);
+ else if (SUPPORT_LSX)
+ return OPTIMIZE (lsx);
+ else
+#endif
+ return OPTIMIZE (aligned);
+}
diff --git a/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S b/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S
new file mode 100644
index 00000000..e9e1d2fc
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strlen-aligned.S
@@ -0,0 +1,100 @@
+/* Optimized strlen implementation using basic Loongarch instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc)
+# define STRLEN __strlen_aligned
+#else
+# define STRLEN strlen
+#endif
+
+LEAF(STRLEN, 6)
+ move a1, a0
+ bstrins.d a0, zero, 2, 0
+ lu12i.w a2, 0x01010
+ li.w t0, -1
+
+ ld.d t2, a0, 0
+ andi t1, a1, 0x7
+ ori a2, a2, 0x101
+ slli.d t1, t1, 3
+
+ bstrins.d a2, a2, 63, 32
+ sll.d t1, t0, t1
+ slli.d t3, a2, 7
+ nor a3, zero, t3
+
+ orn t2, t2, t1
+ sub.d t0, t2, a2
+ nor t1, t2, a3
+ and t0, t0, t1
+
+
+ bnez t0, L(count_pos)
+ addi.d a0, a0, 8
+L(loop_16_7bit):
+ ld.d t2, a0, 0
+ sub.d t1, t2, a2
+
+ and t0, t1, t3
+ bnez t0, L(more_check)
+ ld.d t2, a0, 8
+ sub.d t1, t2, a2
+
+ and t0, t1, t3
+ addi.d a0, a0, 16
+ beqz t0, L(loop_16_7bit)
+ addi.d a0, a0, -8
+
+L(more_check):
+ nor t0, t2, a3
+ and t0, t1, t0
+ bnez t0, L(count_pos)
+ addi.d a0, a0, 8
+
+
+L(loop_16_8bit):
+ ld.d t2, a0, 0
+ sub.d t1, t2, a2
+ nor t0, t2, a3
+ and t0, t0, t1
+
+ bnez t0, L(count_pos)
+ ld.d t2, a0, 8
+ addi.d a0, a0, 16
+ sub.d t1, t2, a2
+
+ nor t0, t2, a3
+ and t0, t0, t1
+ beqz t0, L(loop_16_8bit)
+ addi.d a0, a0, -8
+
+L(count_pos):
+ ctz.d t1, t0
+ sub.d a0, a0, a1
+ srli.d t1, t1, 3
+ add.d a0, a0, t1
+
+ jr ra
+END(STRLEN)
+
+libc_hidden_builtin_def (STRLEN)
diff --git a/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S b/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S
new file mode 100644
index 00000000..258c47ce
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strlen-lasx.S
@@ -0,0 +1,63 @@
+/* Optimized strlen implementation using loongarch LASX SIMD instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define STRLEN __strlen_lasx
+
+LEAF(STRLEN, 6)
+ move a1, a0
+ bstrins.d a0, zero, 4, 0
+ li.d t1, -1
+ xvld xr0, a0, 0
+
+ xvmsknz.b xr0, xr0
+ xvpickve.w xr1, xr0, 4
+ vilvl.h vr0, vr1, vr0
+ movfr2gr.s t0, fa0 # sign extend
+
+ sra.w t0, t0, a1
+ beq t0, t1, L(loop)
+ cto.w a0, t0
+ jr ra
+
+L(loop):
+ xvld xr0, a0, 32
+ addi.d a0, a0, 32
+ xvsetanyeqz.b fcc0, xr0
+ bceqz fcc0, L(loop)
+
+
+ xvmsknz.b xr0, xr0
+ sub.d a0, a0, a1
+ xvpickve.w xr1, xr0, 4
+ vilvl.h vr0, vr1, vr0
+
+ movfr2gr.s t0, fa0
+ cto.w t0, t0
+ add.d a0, a0, t0
+ jr ra
+END(STRLEN)
+
+libc_hidden_builtin_def (STRLEN)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S b/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S
new file mode 100644
index 00000000..b194355e
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strlen-lsx.S
@@ -0,0 +1,71 @@
+/* Optimized strlen implementation using Loongarch LSX SIMD instructions.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library. If not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <sys/regdef.h>
+#include <sys/asm.h>
+
+#if IS_IN (libc) && !defined __loongarch_soft_float
+
+# define STRLEN __strlen_lsx
+
+LEAF(STRLEN, 6)
+ move a1, a0
+ bstrins.d a0, zero, 4, 0
+ vld vr0, a0, 0
+ vld vr1, a0, 16
+
+ li.d t1, -1
+ vmsknz.b vr0, vr0
+ vmsknz.b vr1, vr1
+ vilvl.h vr0, vr1, vr0
+
+ movfr2gr.s t0, fa0
+ sra.w t0, t0, a1
+ beq t0, t1, L(loop)
+ cto.w a0, t0
+
+ jr ra
+ nop
+ nop
+ nop
+
+
+L(loop):
+ vld vr0, a0, 32
+ vld vr1, a0, 48
+ addi.d a0, a0, 32
+ vmin.bu vr2, vr0, vr1
+
+ vsetanyeqz.b fcc0, vr2
+ bceqz fcc0, L(loop)
+ vmsknz.b vr0, vr0
+ vmsknz.b vr1, vr1
+
+ vilvl.h vr0, vr1, vr0
+ sub.d a0, a0, a1
+ movfr2gr.s t0, fa0
+ cto.w t0, t0
+
+ add.d a0, a0, t0
+ jr ra
+END(STRLEN)
+
+libc_hidden_builtin_def (STRLEN)
+#endif
diff --git a/sysdeps/loongarch/lp64/multiarch/strlen.c b/sysdeps/loongarch/lp64/multiarch/strlen.c
new file mode 100644
index 00000000..381c2daa
--- /dev/null
+++ b/sysdeps/loongarch/lp64/multiarch/strlen.c
@@ -0,0 +1,37 @@
+/* Multiple versions of strlen.
+ All versions must be listed in ifunc-impl-list.c.
+ Copyright (C) 2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* Define multiple versions only for the definition in libc. */
+
+#if IS_IN (libc)
+# define strlen __redirect_strlen
+# include <string.h>
+# undef strlen
+
+# define SYMBOL_NAME strlen
+# include "ifunc-strlen.h"
+
+libc_ifunc_redirected (__redirect_strlen, strlen, IFUNC_SELECTOR ());
+
+# ifdef SHARED
+__hidden_ver1 (strlen, __GI_strlen, __redirect_strlen)
+ __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strlen);
+# endif
+
+#endif
diff --git a/sysdeps/loongarch/sys/regdef.h b/sysdeps/loongarch/sys/regdef.h
index 5100f36d..524d2e32 100644
--- a/sysdeps/loongarch/sys/regdef.h
+++ b/sysdeps/loongarch/sys/regdef.h
@@ -89,6 +89,14 @@
#define fs5 $f29
#define fs6 $f30
#define fs7 $f31
+#define fcc0 $fcc0
+#define fcc1 $fcc1
+#define fcc2 $fcc2
+#define fcc3 $fcc3
+#define fcc4 $fcc4
+#define fcc5 $fcc5
+#define fcc6 $fcc6
+#define fcc7 $fcc7
#define vr0 $vr0
#define vr1 $vr1
@@ -98,6 +106,30 @@
#define vr5 $vr5
#define vr6 $vr6
#define vr7 $vr7
+#define vr8 $vr8
+#define vr9 $vr9
+#define vr10 $vr10
+#define vr11 $vr11
+#define vr12 $vr12
+#define vr13 $vr13
+#define vr14 $vr14
+#define vr15 $vr15
+#define vr16 $vr16
+#define vr17 $vr17
+#define vr18 $vr18
+#define vr19 $vr19
+#define vr20 $vr20
+#define vr21 $vr21
+#define vr22 $vr22
+#define vr23 $vr23
+#define vr24 $vr24
+#define vr25 $vr25
+#define vr26 $vr26
+#define vr27 $vr27
+#define vr28 $vr28
+#define vr29 $vr29
+#define vr30 $vr30
+#define vr31 $vr31
#define xr0 $xr0
#define xr1 $xr1
@@ -107,5 +139,30 @@
#define xr5 $xr5
#define xr6 $xr6
#define xr7 $xr7
+#define xr7 $xr7
+#define xr8 $xr8
+#define xr9 $xr9
+#define xr10 $xr10
+#define xr11 $xr11
+#define xr12 $xr12
+#define xr13 $xr13
+#define xr14 $xr14
+#define xr15 $xr15
+#define xr16 $xr16
+#define xr17 $xr17
+#define xr18 $xr18
+#define xr19 $xr19
+#define xr20 $xr20
+#define xr21 $xr21
+#define xr22 $xr22
+#define xr23 $xr23
+#define xr24 $xr24
+#define xr25 $xr25
+#define xr26 $xr26
+#define xr27 $xr27
+#define xr28 $xr28
+#define xr29 $xr29
+#define xr30 $xr30
+#define xr31 $xr31
#endif /* _SYS_REGDEF_H */
diff --git a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
index e371e13b..d1a280a5 100644
--- a/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
+++ b/sysdeps/unix/sysv/linux/loongarch/cpu-features.h
@@ -25,5 +25,7 @@
#define SUPPORT_LSX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LSX)
#define SUPPORT_LASX (GLRO (dl_hwcap) & HWCAP_LOONGARCH_LASX)
+#define INIT_ARCH()
+
#endif /* _CPU_FEATURES_LOONGARCH64_H */
--
2.33.0

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,706 @@
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 Normal file
View file

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

View file

@ -0,0 +1,478 @@
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

496
SUPPORTED
View file

@ -1,496 +0,0 @@
# 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_US@ampm/UTF-8 \
en_US.UTF-8@ampm/UTF-8 \
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 \

View file

@ -1,862 +0,0 @@
#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 || d_type == DT_LNK)
#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
dist
View file

@ -1 +0,0 @@
an8_9

View file

@ -1 +0,0 @@
c81d2388896379997bc359d4f2084239 glibc-2.28.tar.xz

View file

@ -0,0 +1,39 @@
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

BIN
glibc-2.38.tar.xz Normal file

Binary file not shown.

View file

@ -1,28 +0,0 @@
From ed64d30125f855e25ac6f12d8863857dfd3e2cbe Mon Sep 17 00:00:00 2001
From: lijing22222 <lijing@hygon.cn>
Date: Fri, 1 Mar 2024 16:00:15 +0800
Subject: [PATCH] Add Hygon Support
---
sysdeps/x86/cpu-features.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
index 91042505..0ce37a9a 100644
--- a/sysdeps/x86/cpu-features.c
+++ b/sysdeps/x86/cpu-features.c
@@ -527,8 +527,9 @@ init_cpu_features (struct cpu_features *cpu_features)
cpu_features->preferred[index_arch_Prefer_No_AVX512]
|= bit_arch_Prefer_No_AVX512;
}
- /* This spells out "AuthenticAMD". */
- else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
+ /* This spells out "AuthenticAMD" or "HygonGenuine". */
+ else if ((ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)||(ebx == 0x6f677948 && ecx == 0x656e6975 && edx == 0x6e65476e))
+
{
unsigned int extended_model;
--
2.17.1

View file

@ -1,147 +0,0 @@
From 58f93dff514cc0bdf3c72eff590dcf5fe5bf9e00 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 19 Jul 2023 23:09:09 +0800
Subject: [PATCH 3/6] Add a testcase to check alignment of PT_LOAD segment [BZ
#28676]
Backport from master commit: fc2334a
Signed-off-by: Rongwei Wang <rongwei.wang@linux.alibaba.com>
---
elf/Makefile | 13 ++++++++++++-
elf/tst-align3.c | 38 ++++++++++++++++++++++++++++++++++++++
elf/tst-alignmod3.c | 32 ++++++++++++++++++++++++++++++++
3 files changed, 82 insertions(+), 1 deletion(-)
create mode 100644 elf/tst-align3.c
create mode 100644 elf/tst-alignmod3.c
diff --git a/elf/Makefile b/elf/Makefile
index 634c3113..442817ca 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -331,6 +331,7 @@ tests += \
tst-addr1 \
tst-align \
tst-align2 \
+ tst-align3 \
tst-audit-tlsdesc \
tst-audit-tlsdesc-dlopen \
tst-audit1 \
@@ -466,7 +467,9 @@ endif
test-srcs = \
tst-pathopt
# tests-srcs
-
+ifeq (yes,$(have-fpie))
+tests-pie += tst-align3
+endif
selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null)
ifneq ($(selinux-enabled),1)
@@ -647,6 +650,7 @@ modules-names = \
tst-absolute-zero-lib \
tst-alignmod \
tst-alignmod2 \
+ tst-alignmod3 \
tst-array2dep \
tst-array5dep \
tst-audit-tlsdesc-mod1 \
@@ -1669,6 +1673,13 @@ CFLAGS-tst-alignmod2.c += $(stack-align-test-flags)
$(objpfx)tst-align: $(libdl)
$(objpfx)tst-align.out: $(objpfx)tst-alignmod.so
$(objpfx)tst-align2: $(objpfx)tst-alignmod2.so
+$(objpfx)tst-align3: $(objpfx)tst-alignmod3.so
+ifeq (yes,$(have-fpie))
+CFLAGS-tst-align3.c += $(PIE-ccflag)
+endif
+LDFLAGS-tst-align3 += -Wl,-z,max-page-size=0x200000
+LDFLAGS-tst-alignmod3.so += -Wl,-z,max-page-size=0x200000
+$(objpfx)tst-alignmod3.so: $(libsupport)
$(objpfx)unload3: $(libdl)
$(objpfx)unload3.out: $(objpfx)unload3mod1.so $(objpfx)unload3mod2.so \
diff --git a/elf/tst-align3.c b/elf/tst-align3.c
new file mode 100644
index 00000000..ac86d623
--- /dev/null
+++ b/elf/tst-align3.c
@@ -0,0 +1,38 @@
+/* Check alignment of PT_LOAD segment in a shared library.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <tst-stack-align.h>
+
+/* This should cover all possible page sizes we currently support. */
+#define ALIGN 0x200000
+
+int bar __attribute__ ((aligned (ALIGN))) = 1;
+
+extern int do_load_test (void);
+
+static int
+do_test (void)
+{
+ printf ("bar: %p\n", &bar);
+ TEST_VERIFY (is_aligned (&bar, ALIGN) == 0);
+
+ return do_load_test ();
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-alignmod3.c b/elf/tst-alignmod3.c
new file mode 100644
index 00000000..0d33f237
--- /dev/null
+++ b/elf/tst-alignmod3.c
@@ -0,0 +1,32 @@
+/* Check alignment of PT_LOAD segment in a shared library.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <tst-stack-align.h>
+
+/* This should cover all possible page sizes we currently support. */
+#define ALIGN 0x200000
+
+int foo __attribute__ ((aligned (ALIGN))) = 1;
+
+void
+do_load_test (void)
+{
+ printf ("foo: %p\n", &foo);
+ TEST_VERIFY (is_aligned (&foo, ALIGN) == 0);
+}
--
2.27.0

View file

@ -1,325 +0,0 @@
From 6152628751bf13f74c9336263a9c22f29ccd8ffb Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 19 Jul 2023 23:01:53 +0800
Subject: [PATCH 1/6] Properly check stack alignment [BZ #27901]
1. Replace
if ((((uintptr_t) &_d) & (__alignof (double) - 1)) != 0)
which may be optimized out by compiler, with
int
__attribute__ ((weak, noclone, noinline))
is_aligned (void *p, int align)
{
return (((uintptr_t) p) & (align - 1)) != 0;
}
2. Add TEST_STACK_ALIGN_INIT to TEST_STACK_ALIGN.
3. Add a common TEST_STACK_ALIGN_INIT to check 16-byte stack alignment
for both i386 and x86-64.
4. Update powerpc to use TEST_STACK_ALIGN_INIT.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Signed-off-by: Rongwei Wang <rongwei.wang@linux.alibaba.com>
---
sysdeps/generic/tst-stack-align.h | 40 ++++++++++++++++---------
sysdeps/i386/i686/tst-stack-align.h | 44 ---------------------------
sysdeps/i386/tst-stack-align.h | 41 -------------------------
sysdeps/powerpc/tst-stack-align.h | 27 +++++------------
sysdeps/x86/tst-stack-align.h | 28 ++++++++++++++++++
sysdeps/x86_64/tst-stack-align.h | 46 -----------------------------
6 files changed, 61 insertions(+), 165 deletions(-)
delete mode 100644 sysdeps/i386/i686/tst-stack-align.h
delete mode 100644 sysdeps/i386/tst-stack-align.h
create mode 100644 sysdeps/x86/tst-stack-align.h
delete mode 100644 sysdeps/x86_64/tst-stack-align.h
diff --git a/sysdeps/generic/tst-stack-align.h b/sysdeps/generic/tst-stack-align.h
index e5cb3310..e6050901 100644
--- a/sysdeps/generic/tst-stack-align.h
+++ b/sysdeps/generic/tst-stack-align.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
+/* Check stack alignment. Generic version.
+ Copyright (C) 2003-2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -18,17 +19,28 @@
#include <stdio.h>
#include <stdint.h>
+int
+__attribute__ ((weak, noclone, noinline))
+is_aligned (void *p, int align)
+{
+ return (((uintptr_t) p) & (align - 1)) != 0;
+}
+
+#ifndef TEST_STACK_ALIGN_INIT
+# define TEST_STACK_ALIGN_INIT() 0
+#endif
+
#define TEST_STACK_ALIGN() \
- ({ \
- double _d = 12.0; \
- long double _ld = 15.0; \
- int _ret = 0; \
- printf ("double: %g %p %zu\n", _d, &_d, __alignof (double)); \
- if ((((uintptr_t) &_d) & (__alignof (double) - 1)) != 0) \
- _ret = 1; \
- \
- printf ("ldouble: %Lg %p %zu\n", _ld, &_ld, __alignof (long double)); \
- if ((((uintptr_t) &_ld) & (__alignof (long double) - 1)) != 0) \
- _ret = 1; \
- _ret; \
- })
+ ({ \
+ double _d = 12.0; \
+ long double _ld = 15.0; \
+ int _ret = TEST_STACK_ALIGN_INIT (); \
+ \
+ printf ("double: %g %p %zu\n", _d, &_d, __alignof (double)); \
+ _ret += is_aligned (&_d, __alignof (double)); \
+ \
+ printf ("ldouble: %Lg %p %zu\n", _ld, &_ld, \
+ __alignof (long double)); \
+ _ret += is_aligned (&_ld, __alignof (long double)); \
+ _ret; \
+ })
diff --git a/sysdeps/i386/i686/tst-stack-align.h b/sysdeps/i386/i686/tst-stack-align.h
deleted file mode 100644
index 975f26ef..00000000
--- a/sysdeps/i386/i686/tst-stack-align.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <stdio.h>
-#include <stdint.h>
-#ifndef __SSE__
-#include_next <tst-stack-align.h>
-#else
-#include <xmmintrin.h>
-
-#define TEST_STACK_ALIGN() \
- ({ \
- __m128 _m; \
- double _d = 12.0; \
- long double _ld = 15.0; \
- int _ret = 0; \
- printf ("__m128: %p %zu\n", &_m, __alignof (__m128)); \
- if ((((uintptr_t) &_m) & (__alignof (__m128) - 1)) != 0) \
- _ret = 1; \
- \
- printf ("double: %g %p %zu\n", _d, &_d, __alignof (double)); \
- if ((((uintptr_t) &_d) & (__alignof (double) - 1)) != 0) \
- _ret = 1; \
- \
- printf ("ldouble: %Lg %p %zu\n", _ld, &_ld, __alignof (long double)); \
- if ((((uintptr_t) &_ld) & (__alignof (long double) - 1)) != 0) \
- _ret = 1; \
- _ret; \
- })
-#endif
diff --git a/sysdeps/i386/tst-stack-align.h b/sysdeps/i386/tst-stack-align.h
deleted file mode 100644
index 394ff773..00000000
--- a/sysdeps/i386/tst-stack-align.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Copyright (C) 2004-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <stdio.h>
-#include <stdint.h>
-
-typedef struct { int i[4]; } int_al16 __attribute__((aligned (16)));
-
-#define TEST_STACK_ALIGN() \
- ({ \
- int_al16 _m; \
- double _d = 12.0; \
- long double _ld = 15.0; \
- int _ret = 0; \
- printf ("int_al16: %p %zu\n", &_m, __alignof (int_al16)); \
- if ((((uintptr_t) &_m) & (__alignof (int_al16) - 1)) != 0) \
- _ret = 1; \
- \
- printf ("double: %g %p %zu\n", _d, &_d, __alignof (double)); \
- if ((((uintptr_t) &_d) & (__alignof (double) - 1)) != 0) \
- _ret = 1; \
- \
- printf ("ldouble: %Lg %p %zu\n", _ld, &_ld, __alignof (long double)); \
- if ((((uintptr_t) &_ld) & (__alignof (long double) - 1)) != 0) \
- _ret = 1; \
- _ret; \
- })
diff --git a/sysdeps/powerpc/tst-stack-align.h b/sysdeps/powerpc/tst-stack-align.h
index 7fd7013b..d7400b28 100644
--- a/sysdeps/powerpc/tst-stack-align.h
+++ b/sysdeps/powerpc/tst-stack-align.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2005-2018 Free Software Foundation, Inc.
+/* Check stack alignment. PowerPC version.
+ Copyright (C) 2005-2021 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -15,10 +16,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
-#include <stdio.h>
-#include <stdint.h>
-
-#define TEST_STACK_ALIGN() \
+#define TEST_STACK_ALIGN_INIT() \
({ \
/* Altivec __vector int etc. needs 16byte aligned stack. \
Instead of using altivec.h here, use aligned attribute instead. */ \
@@ -27,20 +25,9 @@
int _i __attribute__((aligned (16))); \
int _j[3]; \
} _s = { ._i = 18, ._j[0] = 19, ._j[1] = 20, ._j[2] = 21 }; \
- double _d = 12.0; \
- long double _ld = 15.0; \
- int _ret = 0; \
printf ("__vector int: { %d, %d, %d, %d } %p %zu\n", _s._i, _s._j[0], \
_s._j[1], _s._j[2], &_s, __alignof (_s)); \
- if ((((uintptr_t) &_s) & (__alignof (_s) - 1)) != 0) \
- _ret = 1; \
- \
- printf ("double: %g %p %zu\n", _d, &_d, __alignof (double)); \
- if ((((uintptr_t) &_d) & (__alignof (double) - 1)) != 0) \
- _ret = 1; \
- \
- printf ("ldouble: %Lg %p %zu\n", _ld, &_ld, __alignof (long double)); \
- if ((((uintptr_t) &_ld) & (__alignof (long double) - 1)) != 0) \
- _ret = 1; \
- _ret; \
- })
+ is_aligned (&_s, __alignof (_s)); \
+ })
+
+#include_next <tst-stack-align.h>
diff --git a/sysdeps/x86/tst-stack-align.h b/sysdeps/x86/tst-stack-align.h
new file mode 100644
index 00000000..02ecc72d
--- /dev/null
+++ b/sysdeps/x86/tst-stack-align.h
@@ -0,0 +1,28 @@
+/* Check stack alignment. X86 version.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+typedef struct { int i[16]; } int_al16 __attribute__((aligned (16)));
+
+#define TEST_STACK_ALIGN_INIT() \
+ ({ \
+ int_al16 _m; \
+ printf ("int_al16: %p %zu\n", &_m, __alignof (int_al16)); \
+ is_aligned (&_m, __alignof (int_al16)); \
+ })
+
+#include_next <tst-stack-align.h>
diff --git a/sysdeps/x86_64/tst-stack-align.h b/sysdeps/x86_64/tst-stack-align.h
deleted file mode 100644
index b2ef77f6..00000000
--- a/sysdeps/x86_64/tst-stack-align.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <stdio.h>
-#include <stdint.h>
-
-#define TEST_STACK_ALIGN() \
- ({ \
- /* AMD64 ABI mandates 16byte aligned stack. \
- Unfortunately, current GCC doesn't support __int128 or __float128 \
- types, so use aligned attribute instead. */ \
- struct _S \
- { \
- int _i __attribute__((aligned (16))); \
- int _pad[3]; \
- } _s = { ._i = 18 }; \
- double _d = 12.0; \
- long double _ld = 15.0; \
- int _ret = 0; \
- printf ("__int128: %d %p %zu\n", _s._i, &_s, __alignof (_s)); \
- if ((((uintptr_t) &_s) & (__alignof (_s) - 1)) != 0) \
- _ret = 1; \
- \
- printf ("double: %g %p %zu\n", _d, &_d, __alignof (double)); \
- if ((((uintptr_t) &_d) & (__alignof (double) - 1)) != 0) \
- _ret = 1; \
- \
- printf ("ldouble: %Lg %p %zu\n", _ld, &_ld, __alignof (long double)); \
- if ((((uintptr_t) &_ld) & (__alignof (long double) - 1)) != 0) \
- _ret = 1; \
- _ret; \
- })
--
2.27.0

View file

@ -1,112 +0,0 @@
commit 849274d48fc59bfa6db3c713c8ced8026b20f3b7
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Nov 16 19:55:35 2023 +0100
elf: Fix force_first handling in dlclose (bug 30981)
The force_first parameter was ineffective because the dlclose'd
object was not necessarily the first in the maps array. Also
enable force_first handling unconditionally, regardless of namespace.
The initial object in a namespace should be destructed first, too.
The _dl_sort_maps_dfs function had early returns for relocation
dependency processing which broke force_first handling, too, and
this is fixed in this change as well.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 22225efb3226c3e1..16a39f5bf17b440f 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -182,6 +182,16 @@ _dl_close_worker (struct link_map *map, bool force)
}
assert (idx == nloaded);
+ /* Put the dlclose'd map first, so that its destructor runs first.
+ The map variable is NULL after a retry. */
+ if (map != NULL)
+ {
+ maps[map->l_idx] = maps[0];
+ maps[map->l_idx]->l_idx = map->l_idx;
+ maps[0] = map;
+ maps[0]->l_idx = 0;
+ }
+
/* Keep track of the lowest index link map we have covered already. */
int done_index = -1;
while (++done_index < nloaded)
@@ -255,9 +265,10 @@ _dl_close_worker (struct link_map *map, bool force)
}
}
- /* Sort the entries. We can skip looking for the binary itself which is
- at the front of the search list for the main namespace. */
- _dl_sort_maps (maps, nloaded, (nsid == LM_ID_BASE), true);
+ /* Sort the entries. Unless retrying, the maps[0] object (the
+ original argument to dlclose) needs to remain first, so that its
+ destructor runs first. */
+ _dl_sort_maps (maps, nloaded, /* force_first */ map != NULL, true);
/* Call all termination functions at once. */
bool unload_any = false;
@@ -768,7 +779,11 @@ _dl_close_worker (struct link_map *map, bool force)
/* Recheck if we need to retry, release the lock. */
out:
if (dl_close_state == rerun)
- goto retry;
+ {
+ /* The map may have been deallocated. */
+ map = NULL;
+ goto retry;
+ }
dl_close_state = not_pending;
}
diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
index aeb79b40b45054c0..c17ac325eca658ef 100644
--- a/elf/dl-sort-maps.c
+++ b/elf/dl-sort-maps.c
@@ -260,13 +260,12 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
The below memcpy is not needed in the do_reldeps case here,
since we wrote back to maps[] during DFS traversal. */
if (maps_head == maps)
- return;
+ break;
}
assert (maps_head == maps);
- return;
}
-
- memcpy (maps, rpo, sizeof (struct link_map *) * nmaps);
+ else
+ memcpy (maps, rpo, sizeof (struct link_map *) * nmaps);
/* Skipping the first object at maps[0] is not valid in general,
since traversing along object dependency-links may "find" that
diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def
index 4bf9052db16fb352..cf6453e9eb85ac65 100644
--- a/elf/dso-sort-tests-1.def
+++ b/elf/dso-sort-tests-1.def
@@ -56,14 +56,16 @@ output: b>a>{}<a<b
# relocation(dynamic) dependencies. While this is technically unspecified, the
# presumed reasonable practical behavior is for the destructor order to respect
# the static DT_NEEDED links (here this means the a->b->c->d order).
-# The older dynamic_sort=1 algorithm does not achieve this, while the DFS-based
-# dynamic_sort=2 algorithm does, although it is still arguable whether going
-# beyond spec to do this is the right thing to do.
+# The older dynamic_sort=1 algorithm originally did not achieve this,
+# but this was a bug in the way _dl_sort_maps was called from _dl_close_worker,
+# effectively disabling proper force_first handling.
+# The new dynamic_sort=2 algorithm shows the effect of the simpler force_first
+# handling: the a object is simply moved to the front.
# The below expected outputs are what the two algorithms currently produce
# respectively, for regression testing purposes.
tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};a->b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c
-output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];}
-output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<g<f<a<b<c<d<e];}
+output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<b<c<d<g<f<e];}
+output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<g<f<b<c<d<e];}
# Test that even in the presence of dependency loops involving dlopen'ed
# object, that object is initialized last (and not unloaded prematurely).

View file

@ -1,35 +0,0 @@
commit b893410be304ddcea0bd43f537a13e8b18d37cf2
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Nov 27 11:28:07 2023 +0100
elf: In _dl_relocate_object, skip processing if object is relocated
This is just a minor optimization. It also makes it more obvious that
_dl_relocate_object can be called multiple times.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 7a84b1fa8c3a7fdd..a80a54fb013adab5 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -165,6 +165,9 @@ void
_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
int reloc_mode, int consider_profiling)
{
+ if (l->l_relocated)
+ return;
+
struct textrels
{
caddr_t start;
@@ -202,9 +205,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
# define consider_symbind 0
#endif
- if (l->l_relocated)
- return;
-
/* If DT_BIND_NOW is set relocate all references in this object. We
do not do this if we are profiling, of course. */
// XXX Correct for auditing?

View file

@ -1,121 +0,0 @@
commit a74c2e1cbc8673dd7e97aae2f2705392e2ccc3f6
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Nov 27 11:28:10 2023 +0100
elf: Introduce the _dl_open_relocate_one_object function
It is extracted from dl_open_worker_begin.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/elf/dl-open.c b/elf/dl-open.c
index e82e53ff8b38fa11..1505fdb73088dcdb 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -466,6 +466,50 @@ activate_nodelete (struct link_map *new)
}
}
+/* Relocate the object L. *RELOCATION_IN_PROGRESS controls whether
+ the debugger is notified of the start of relocation processing. */
+static void
+_dl_open_relocate_one_object (struct dl_open_args *args, struct r_debug *r,
+ struct link_map *l, int reloc_mode,
+ bool *relocation_in_progress)
+{
+ if (l->l_real->l_relocated)
+ return;
+
+ if (!*relocation_in_progress)
+ {
+ /* Notify the debugger that relocations are about to happen. */
+ LIBC_PROBE (reloc_start, 2, args->nsid, r);
+ *relocation_in_progress = true;
+ }
+
+#ifdef SHARED
+ if (__glibc_unlikely (GLRO(dl_profile) != NULL))
+ {
+ /* If this here is the shared object which we want to profile
+ make sure the profile is started. We can find out whether
+ this is necessary or not by observing the `_dl_profile_map'
+ variable. If it was NULL but is not NULL afterwards we must
+ start the profiling. */
+ struct link_map *old_profile_map = GL(dl_profile_map);
+
+ _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1);
+
+ if (old_profile_map == NULL && GL(dl_profile_map) != NULL)
+ {
+ /* We must prepare the profiling. */
+ _dl_start_profile ();
+
+ /* Prevent unloading the object. */
+ GL(dl_profile_map)->l_nodelete_active = true;
+ }
+ }
+ else
+#endif
+ _dl_relocate_object (l, l->l_scope, reloc_mode, 0);
+}
+
+
/* struct dl_init_args and call_dl_init are used to call _dl_init with
exception handling disabled. */
struct dl_init_args
@@ -638,7 +682,7 @@ dl_open_worker_begin (void *a)
}
while (l != NULL);
- int relocation_in_progress = 0;
+ bool relocation_in_progress = false;
/* Perform relocation. This can trigger lazy binding in IFUNC
resolvers. For NODELETE mappings, these dependencies are not
@@ -649,44 +693,8 @@ dl_open_worker_begin (void *a)
are undefined anyway, so this is not a problem. */
for (unsigned int i = last; i-- > first; )
- {
- l = new->l_initfini[i];
-
- if (l->l_real->l_relocated)
- continue;
-
- if (! relocation_in_progress)
- {
- /* Notify the debugger that relocations are about to happen. */
- LIBC_PROBE (reloc_start, 2, args->nsid, r);
- relocation_in_progress = 1;
- }
-
-#ifdef SHARED
- if (__glibc_unlikely (GLRO(dl_profile) != NULL))
- {
- /* If this here is the shared object which we want to profile
- make sure the profile is started. We can find out whether
- this is necessary or not by observing the `_dl_profile_map'
- variable. If it was NULL but is not NULL afterwards we must
- start the profiling. */
- struct link_map *old_profile_map = GL(dl_profile_map);
-
- _dl_relocate_object (l, l->l_scope, reloc_mode | RTLD_LAZY, 1);
-
- if (old_profile_map == NULL && GL(dl_profile_map) != NULL)
- {
- /* We must prepare the profiling. */
- _dl_start_profile ();
-
- /* Prevent unloading the object. */
- GL(dl_profile_map)->l_nodelete_active = true;
- }
- }
- else
-#endif
- _dl_relocate_object (l, l->l_scope, reloc_mode, 0);
- }
+ _dl_open_relocate_one_object (args, r, new->l_initfini[i], reloc_mode,
+ &relocation_in_progress);
/* This only performs the memory allocations. The actual update of
the scopes happens below, after failure is impossible. */

View file

@ -1,223 +0,0 @@
commit 78ca44da0160a0b442f0ca1f253e3360f044b2ec
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Nov 27 11:28:13 2023 +0100
elf: Relocate libc.so early during startup and dlmopen (bug 31083)
This makes it more likely that objects without dependencies can
use IFUNC resolvers in libc.so.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Conflicts:
elf/Makefile
(differences in test backports)
elf/rtld.c
(removal of prelink support upstream)
diff --git a/elf/Makefile b/elf/Makefile
index 634c3113227d64a6..6f0f36cdfe3961e8 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -386,6 +386,8 @@ tests += \
tst-nodelete2 \
tst-nodelete-dlclose \
tst-nodelete-opened \
+ tst-nodeps1 \
+ tst-nodeps2 \
tst-noload \
tst-null-argv \
tst-relsort1 \
@@ -740,6 +742,8 @@ modules-names = \
tst-nodelete-dlclose-dso \
tst-nodelete-dlclose-plugin \
tst-nodelete-opened-lib \
+ tst-nodeps1-mod \
+ tst-nodeps2-mod \
tst-null-argv-lib \
tst-relsort1mod1 \
tst-relsort1mod2 \
@@ -886,8 +890,13 @@ modules-execstack-yes = tst-execstack-mod
extra-test-objs += $(addsuffix .os,$(strip $(modules-names)))
# filtmod1.so has a special rule
-modules-names-nobuild := filtmod1 \
- tst-audit24bmod1 tst-audit24bmod2
+modules-names-nobuild += \
+ filtmod1 \
+ tst-audit24bmod1 \
+ tst-audit24bmod2 \
+ tst-nodeps1-mod \
+ tst-nodeps2-mod \
+ # modules-names-nobuild
tests += $(tests-static)
@@ -2697,3 +2706,19 @@ $(objpfx)tst-dlmopen-twice: $(libdl)
$(objpfx)tst-dlmopen-twice.out: \
$(objpfx)tst-dlmopen-twice-mod1.so \
$(objpfx)tst-dlmopen-twice-mod2.so
+
+# The object tst-nodeps1-mod.so has no explicit dependencies on libc.so.
+$(objpfx)tst-nodeps1-mod.so: $(objpfx)tst-nodeps1-mod.os
+ $(LINK.o) -nostartfiles -nostdlib -shared -o $@ $^
+tst-nodeps1.so-no-z-defs = yes
+# Link libc.so before the test module with the IFUNC resolver reference.
+LDFLAGS-tst-nodeps1 = $(common-objpfx)libc.so $(objpfx)tst-nodeps1-mod.so
+$(objpfx)tst-nodeps1: $(objpfx)tst-nodeps1-mod.so
+# Reuse the tst-nodeps1 module. Link libc.so before the test module
+# with the IFUNC resolver reference.
+$(objpfx)tst-nodeps2-mod.so: $(common-objpfx)libc.so \
+ $(objpfx)tst-nodeps1-mod.so $(objpfx)tst-nodeps2-mod.os
+ $(LINK.o) -Wl,--no-as-needed -nostartfiles -nostdlib -shared -o $@ $^
+$(objpfx)tst-nodeps2: $(libdl)
+$(objpfx)tst-nodeps2.out: \
+ $(objpfx)tst-nodeps1-mod.so $(objpfx)tst-nodeps2-mod.so
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 1505fdb73088dcdb..6508b0ea545440b8 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -692,6 +692,17 @@ dl_open_worker_begin (void *a)
them. However, such relocation dependencies in IFUNC resolvers
are undefined anyway, so this is not a problem. */
+ /* Ensure that libc is relocated first. This helps with the
+ execution of IFUNC resolvers in libc, and matters only to newly
+ created dlmopen namespaces. Do not do this for static dlopen
+ because libc has relocations against ld.so, which may not have
+ been relocated at this point. */
+#ifdef SHARED
+ if (GL(dl_ns)[args->nsid].libc_map != NULL)
+ _dl_open_relocate_one_object (args, r, GL(dl_ns)[args->nsid].libc_map,
+ reloc_mode, &relocation_in_progress);
+#endif
+
for (unsigned int i = last; i-- > first; )
_dl_open_relocate_one_object (args, r, new->l_initfini[i], reloc_mode,
&relocation_in_progress);
diff --git a/elf/rtld.c b/elf/rtld.c
index cd2cc4024a3581c2..502d2a1c58505d88 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -2414,11 +2414,17 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
objects. We do not re-relocate the dynamic linker itself in this
loop because that could result in the GOT entries for functions we
call being changed, and that would break us. It is safe to relocate
- the dynamic linker out of order because it has no copy relocs (we
- know that because it is self-contained). */
+ the dynamic linker out of order because it has no copy relocations.
+ Likewise for libc, which is relocated early to ensure that IFUNC
+ resolvers in libc work. */
int consider_profiling = GLRO(dl_profile) != NULL;
+ if (GL(dl_ns)[LM_ID_BASE].libc_map != NULL)
+ _dl_relocate_object (GL(dl_ns)[LM_ID_BASE].libc_map,
+ GL(dl_ns)[LM_ID_BASE].libc_map->l_scope,
+ GLRO(dl_lazy) ? RTLD_LAZY : 0, consider_profiling);
+
/* If we are profiling we also must do lazy reloaction. */
GLRO(dl_lazy) |= consider_profiling;
diff --git a/elf/tst-nodeps1-mod.c b/elf/tst-nodeps1-mod.c
new file mode 100644
index 0000000000000000..45c8e3c631251a89
--- /dev/null
+++ b/elf/tst-nodeps1-mod.c
@@ -0,0 +1,25 @@
+/* Test module with no libc.so dependency and string function references.
+ 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 <string.h>
+
+/* Some references to libc symbols which are likely to have IFUNC
+ resolvers. If they do not, this module does not exercise bug 31083. */
+void *memcpy_pointer = memcpy;
+void *memmove_pointer = memmove;
+void *memset_pointer = memset;
diff --git a/elf/tst-nodeps1.c b/elf/tst-nodeps1.c
new file mode 100644
index 0000000000000000..1a8bde36cdb71446
--- /dev/null
+++ b/elf/tst-nodeps1.c
@@ -0,0 +1,23 @@
+/* Test initially loaded module with implicit libc.so dependency (bug 31083).
+ 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/>. */
+
+/* Testing happens before main. */
+int
+main (void)
+{
+}
diff --git a/elf/tst-nodeps2-mod.c b/elf/tst-nodeps2-mod.c
new file mode 100644
index 0000000000000000..4913feee9b56e0e1
--- /dev/null
+++ b/elf/tst-nodeps2-mod.c
@@ -0,0 +1 @@
+/* Empty test module which depends on tst-nodeps1-mod.so. */
diff --git a/elf/tst-nodeps2.c b/elf/tst-nodeps2.c
new file mode 100644
index 0000000000000000..0bdc8eeb8cba3a99
--- /dev/null
+++ b/elf/tst-nodeps2.c
@@ -0,0 +1,29 @@
+/* Test dlmopen with implicit libc.so dependency (bug 31083).
+ 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 <support/xdlfcn.h>
+
+static int
+do_test (void)
+{
+ void *handle = xdlmopen (LM_ID_NEWLM, "tst-nodeps2-mod.so", RTLD_NOW);
+ xdlclose (handle);
+ return 0;
+}
+
+#include <support/test-driver.c>

View file

@ -1,41 +0,0 @@
commit b3bee76c5f59498b9c189608f0a3132e2013fa1a
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Dec 8 09:51:34 2023 +0100
elf: Initialize GLRO(dl_lazy) before relocating libc in dynamic startup
GLRO(dl_lazy) is used to set the parameters for the early
_dl_relocate_object call, so the consider_profiling setting has to
be applied before the call.
Fixes commit 78ca44da0160a0b442f0ca1f253e3360f044b2ec ("elf: Relocate
libc.so early during startup and dlmopen (bug 31083)").
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Conflicts:
elf/rtld.c
(removal of prelink support upstream)
diff --git a/elf/rtld.c b/elf/rtld.c
index 502d2a1c58505d88..4f317a2a874e6af7 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -2420,14 +2420,14 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]);
int consider_profiling = GLRO(dl_profile) != NULL;
+ /* If we are profiling we also must do lazy reloaction. */
+ GLRO(dl_lazy) |= consider_profiling;
+
if (GL(dl_ns)[LM_ID_BASE].libc_map != NULL)
_dl_relocate_object (GL(dl_ns)[LM_ID_BASE].libc_map,
GL(dl_ns)[LM_ID_BASE].libc_map->l_scope,
GLRO(dl_lazy) ? RTLD_LAZY : 0, consider_profiling);
- /* If we are profiling we also must do lazy reloaction. */
- GLRO(dl_lazy) |= consider_profiling;
-
RTLD_TIMING_VAR (start);
rtld_timer_start (&start);
unsigned i = main_map->l_searchlist.r_nlist;

View file

@ -1,83 +0,0 @@
commit c00b984fcd53f679ca2dafcd1aee2c89836e6e73
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Aug 29 08:28:31 2023 +0200
nscd: Skip unusable entries in first pass in prune_cache (bug 30800)
Previously, if an entry was marked unusable for any reason, but had
not timed out yet, the assert would trigger.
One way to get into such state is if a data change is detected during
re-validation of an entry. This causes the entry to be marked as not
usable. If exits nscd soon after that, then the clock jumps
backwards, and nscd restarted, the cache re-validation run after
startup triggers the removed assert.
The change is more complicated than just the removal of the assert
because entries marked as not usable should be garbage-collected in
the second pass. To make this happen, it is necessary to update some
book-keeping data.
Reviewed-by: DJ Delorie <dj@redhat.com>
diff --git a/nscd/cache.c b/nscd/cache.c
index efe4214d953edb30..2fd3f78ebb567bbe 100644
--- a/nscd/cache.c
+++ b/nscd/cache.c
@@ -371,8 +371,11 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
serv2str[runp->type], str, dh->timeout);
}
- /* Check whether the entry timed out. */
- if (dh->timeout < now)
+ /* Check whether the entry timed out. Timed out entries
+ will be revalidated. For unusable records, it is still
+ necessary to record that the bucket needs to be scanned
+ again below. */
+ if (dh->timeout < now || !dh->usable)
{
/* This hash bucket could contain entries which need to
be looked at. */
@@ -384,7 +387,7 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
/* We only have to look at the data of the first entries
since the count information is kept in the data part
which is shared. */
- if (runp->first)
+ if (runp->first && dh->usable)
{
/* At this point there are two choices: we reload the
@@ -400,9 +403,6 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
{
/* Remove the value. */
dh->usable = false;
-
- /* We definitely have some garbage entries now. */
- any = true;
}
else
{
@@ -414,18 +414,15 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
time_t timeout = readdfcts[runp->type] (table, runp, dh);
next_timeout = MIN (next_timeout, timeout);
-
- /* If the entry has been replaced, we might need
- cleanup. */
- any |= !dh->usable;
}
}
+
+ /* If the entry has been replaced, we might need cleanup. */
+ any |= !dh->usable;
}
else
- {
- assert (dh->usable);
- next_timeout = MIN (next_timeout, dh->timeout);
- }
+ /* Entry has not timed out and is usable. */
+ next_timeout = MIN (next_timeout, dh->timeout);
run = runp->next;
}

View file

@ -1,237 +0,0 @@
commit d0f07f7df8d9758c838674b70144ac73bcbd1634
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue May 30 13:25:50 2023 +0200
elf: Make more functions available for binding during dlclose (bug 30425)
Previously, after destructors for a DSO have been invoked, ld.so refused
to bind against that DSO in all cases. Relax this restriction somewhat
if the referencing object is itself a DSO that is being unloaded. This
assumes that the symbol reference is not going to be stored anywhere.
The situation in the test case can arise fairly easily with C++ and
objects that are built with different optimization levels and therefore
define different functions with vague linkage.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Conflicts:
elf/Makefile
(usual test differences, link test with -ldl)
diff --git a/elf/Makefile b/elf/Makefile
index 6f0f36cdfe3961e8..ebf46a297d241d8f 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -362,6 +362,7 @@ tests += \
tst-big-note \
tst-debug1 \
tst-deep1 \
+ tst-dlclose-lazy \
tst-dlmodcount \
tst-dlmopen1 \
tst-dlmopen3 \
@@ -711,6 +712,8 @@ modules-names = \
tst-deep1mod2 \
tst-deep1mod3 \
tst-dlmopen1mod \
+ tst-dlclose-lazy-mod1 \
+ tst-dlclose-lazy-mod2 \
tst-dlmopen-dlerror-mod \
tst-dlmopen-gethostbyname-mod \
tst-dlmopen-twice-mod1 \
@@ -2707,6 +2710,12 @@ $(objpfx)tst-dlmopen-twice.out: \
$(objpfx)tst-dlmopen-twice-mod1.so \
$(objpfx)tst-dlmopen-twice-mod2.so
+LDFLAGS-tst-dlclose-lazy-mod1.so = -Wl,-z,lazy,--no-as-needed
+$(objpfx)tst-dlclose-lazy-mod1.so: $(objpfx)tst-dlclose-lazy-mod2.so
+$(objpfx)tst-dlclose-lazy: $(libdl)
+$(objpfx)tst-dlclose-lazy.out: \
+ $(objpfx)tst-dlclose-lazy-mod1.so $(objpfx)tst-dlclose-lazy-mod2.so
+
# The object tst-nodeps1-mod.so has no explicit dependencies on libc.so.
$(objpfx)tst-nodeps1-mod.so: $(objpfx)tst-nodeps1-mod.os
$(LINK.o) -nostartfiles -nostdlib -shared -o $@ $^
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 47acd134600b44b5..9e8f14b8483f5eba 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -380,8 +380,25 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable)
continue;
- /* Do not look into objects which are going to be removed. */
- if (map->l_removed)
+ /* Do not look into objects which are going to be removed,
+ except when the referencing object itself is being removed.
+
+ The second part covers the situation when an object lazily
+ binds to another object while running its destructor, but the
+ destructor of the other object has already run, so that
+ dlclose has set l_removed. It may not always be obvious how
+ to avoid such a scenario to programmers creating DSOs,
+ particularly if C++ vague linkage is involved and triggers
+ symbol interposition.
+
+ Accepting these to-be-removed objects makes the lazy and
+ BIND_NOW cases more similar. (With BIND_NOW, the symbol is
+ resolved early, before the destructor call, so the issue does
+ not arise.). Behavior matches the constructor scenario: the
+ implementation allows binding to symbols of objects whose
+ constructors have not run. In fact, not doing this would be
+ mostly incompatible with symbol interposition. */
+ if (map->l_removed && !(undef_map != NULL && undef_map->l_removed))
continue;
/* Print some debugging info if wanted. */
diff --git a/elf/tst-dlclose-lazy-mod1.c b/elf/tst-dlclose-lazy-mod1.c
new file mode 100644
index 0000000000000000..8439dc1925cc8b41
--- /dev/null
+++ b/elf/tst-dlclose-lazy-mod1.c
@@ -0,0 +1,36 @@
+/* Lazy binding during dlclose. Directly loaded module.
+ 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/>. */
+
+/* This function is called from exported_function below. It is only
+ defined in this module. The weak attribute mimics how G++
+ implements vague linkage for C++. */
+void __attribute__ ((weak))
+lazily_bound_exported_function (void)
+{
+}
+
+/* Called from tst-dlclose-lazy-mod2.so. */
+void
+exported_function (int call_it)
+{
+ if (call_it)
+ /* Previous to the fix this would crash when called during dlclose
+ since symbols from the DSO were no longer available for binding
+ (bug 30425) after the DSO started being closed by dlclose. */
+ lazily_bound_exported_function ();
+}
diff --git a/elf/tst-dlclose-lazy-mod2.c b/elf/tst-dlclose-lazy-mod2.c
new file mode 100644
index 0000000000000000..767f69ffdb23a685
--- /dev/null
+++ b/elf/tst-dlclose-lazy-mod2.c
@@ -0,0 +1,49 @@
+/* Lazy binding during dlclose. Indirectly loaded module.
+ 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 <stdio.h>
+#include <stdlib.h>
+
+void
+exported_function (int ignored)
+{
+ /* This function is interposed from tst-dlclose-lazy-mod1.so and
+ thus never called. */
+ abort ();
+}
+
+static void __attribute__ ((constructor))
+init (void)
+{
+ puts ("info: tst-dlclose-lazy-mod2.so constructor called");
+
+ /* Trigger lazy binding to the definition in
+ tst-dlclose-lazy-mod1.so, but not for
+ lazily_bound_exported_function in that module. */
+ exported_function (0);
+}
+
+static void __attribute__ ((destructor))
+fini (void)
+{
+ puts ("info: tst-dlclose-lazy-mod2.so destructor called");
+
+ /* Trigger the lazily_bound_exported_function call in
+ exported_function in tst-dlclose-lazy-mod1.so. */
+ exported_function (1);
+}
diff --git a/elf/tst-dlclose-lazy.c b/elf/tst-dlclose-lazy.c
new file mode 100644
index 0000000000000000..976a6bb6f64fa981
--- /dev/null
+++ b/elf/tst-dlclose-lazy.c
@@ -0,0 +1,47 @@
+/* Test lazy binding during dlclose (bug 30425).
+ 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/>. */
+
+/* This test re-creates a situation that can arise naturally for C++
+ applications due to the use of vague linkage and differences in the
+ set of compiler-emitted functions. A function in
+ tst-dlclose-lazy-mod1.so (exported_function) interposes a function
+ in tst-dlclose-lazy-mod2.so. This function is called from the
+ destructor in tst-dlclose-lazy-mod2.so, after the destructor for
+ tst-dlclose-lazy-mod1.so has already completed. Prior to the fix
+ for bug 30425, this would lead to a lazy binding failure in
+ tst-dlclose-lazy-mod1.so because dlclose had already marked the DSO
+ as unavailable for binding (by setting l_removed). */
+
+#include <dlfcn.h>
+#include <support/xdlfcn.h>
+#include <support/check.h>
+
+int
+main (void)
+{
+ /* Load tst-dlclose-lazy-mod1.so, indirectly loading
+ tst-dlclose-lazy-mod2.so. */
+ void *handle = xdlopen ("tst-dlclose-lazy-mod1.so", RTLD_GLOBAL | RTLD_LAZY);
+
+ /* Invoke the destructor of tst-dlclose-lazy-mod2.so, which calls
+ into tst-dlclose-lazy-mod1.so after its destructor has been
+ called. */
+ xdlclose (handle);
+
+ return 0;
+}

View file

@ -1,27 +0,0 @@
commit ecc7c3deb9f347649c2078fcc0f94d4cedf92d60
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Jan 2 14:36:17 2024 +0100
libio: Check remaining buffer size in _IO_wdo_write (bug 31183)
The multibyte character needs to fit into the remaining buffer space,
not the already-written buffer space. Without the fix, we were never
moving the write pointer from the start of the buffer, always using
the single-character fallback buffer.
Fixes commit 04b76b5aa8b2d1d19066e42dd1 ("Don't error out writing
a multibyte character to an unbuffered stream (bug 17522)").
diff --git a/libio/wfileops.c b/libio/wfileops.c
index d3deb34ba058ca39..6a6421f8880f9356 100644
--- a/libio/wfileops.c
+++ b/libio/wfileops.c
@@ -57,7 +57,7 @@ _IO_wdo_write (FILE *fp, const wchar_t *data, size_t to_do)
char mb_buf[MB_LEN_MAX];
char *write_base, *write_ptr, *buf_end;
- if (fp->_IO_write_ptr - fp->_IO_write_base < sizeof (mb_buf))
+ if (fp->_IO_buf_end - fp->_IO_write_ptr < sizeof (mb_buf))
{
/* Make sure we have room for at least one multibyte
character. */

View file

@ -1,22 +0,0 @@
Work around in the test case, the fact that RHEL-8 NSS modules
infrastructure incorrectly allows merging in the hosts database. This
is a RHEL-8 only fix.
diff --git a/nss/tst-nss-gai-actions.c b/nss/tst-nss-gai-actions.c
index efca6cd1837a172a..c35e752896eceb2a 100644
--- a/nss/tst-nss-gai-actions.c
+++ b/nss/tst-nss-gai-actions.c
@@ -87,6 +87,13 @@ do_one_test (int action, int family, bool canon)
case ACTION_MERGE:
if (ret == 0)
{
+ if (hints.ai_flags == 0 && hints.ai_family == AF_INET)
+ {
+ printf ("***** RHEL-8 limitation: "
+ "NSS modules infrastructure incorrectly allows MERGE\n");
+ return;
+ }
+
char *formatted = support_format_addrinfo (ai, ret);
printf ("merge unexpectedly succeeded:\n %s\n", formatted);

View file

@ -1,979 +0,0 @@
commit 228cdb00a045ae3b68a91b35c7548bab6029446e
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date: Thu Mar 17 11:44:34 2022 +0530
Simplify allocations and fix merge and continue actions [BZ #28931]
Allocations for address tuples is currently a bit confusing because of
the pointer chasing through PAT, making it hard to observe the sequence
in which allocations have been made. Narrow scope of the pointer
chasing through PAT so that it is only used where necessary.
This also tightens actions behaviour with the hosts database in
getaddrinfo to comply with the manual text. The "continue" action
discards previous results and the "merge" action results in an immedate
lookup failure. Consequently, chaining of allocations across modules is
no longer necessary, thus opening up cleanup opportunities.
A test has been added that checks some combinations to ensure that they
work correctly.
Resolves: BZ #28931
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: DJ Delorie <dj@redhat.com>
(cherry picked from commit 1c37b8022e8763fedbb3f79c02e05c6acfe5a215)
Conflicts:
nss/Makefile
(Missing test cases)
sysdeps/posix/getaddrinfo.c
(RES_USE_INET6 still present in RHEL-8 and NSS module traversal rewrite
not in RHEL-8)
diff --git a/nss/Makefile b/nss/Makefile
index e8a7d9c7b3cefcdf..cfb255c6e7a3a4de 100644
--- a/nss/Makefile
+++ b/nss/Makefile
@@ -65,7 +65,8 @@ xtests = bug-erange
tests-container = \
tst-nss-db-endpwent \
- tst-nss-db-endgrent
+ tst-nss-db-endgrent \
+ tst-nss-gai-actions
# Tests which need libdl
ifeq (yes,$(build-shared))
diff --git a/nss/tst-nss-gai-actions.c b/nss/tst-nss-gai-actions.c
new file mode 100644
index 0000000000000000..efca6cd1837a172a
--- /dev/null
+++ b/nss/tst-nss-gai-actions.c
@@ -0,0 +1,149 @@
+/* Test continue and merge NSS actions for getaddrinfo.
+ 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 <dlfcn.h>
+#include <gnu/lib-names.h>
+#include <nss.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <support/check.h>
+#include <support/format_nss.h>
+#include <support/support.h>
+#include <support/xstdio.h>
+#include <support/xunistd.h>
+
+enum
+{
+ ACTION_MERGE = 0,
+ ACTION_CONTINUE,
+};
+
+static const char *
+family_str (int family)
+{
+ switch (family)
+ {
+ case AF_UNSPEC:
+ return "AF_UNSPEC";
+ case AF_INET:
+ return "AF_INET";
+ default:
+ __builtin_unreachable ();
+ }
+}
+
+static const char *
+action_str (int action)
+{
+ switch (action)
+ {
+ case ACTION_MERGE:
+ return "merge";
+ case ACTION_CONTINUE:
+ return "continue";
+ default:
+ __builtin_unreachable ();
+ }
+}
+
+static void
+do_one_test (int action, int family, bool canon)
+{
+ struct addrinfo hints =
+ {
+ .ai_family = family,
+ };
+
+ struct addrinfo *ai;
+
+ if (canon)
+ hints.ai_flags = AI_CANONNAME;
+
+ printf ("***** Testing \"files [SUCCESS=%s] files\" for family %s, %s\n",
+ action_str (action), family_str (family),
+ canon ? "AI_CANONNAME" : "");
+
+ int ret = getaddrinfo ("example.org", "80", &hints, &ai);
+
+ switch (action)
+ {
+ case ACTION_MERGE:
+ if (ret == 0)
+ {
+ char *formatted = support_format_addrinfo (ai, ret);
+
+ printf ("merge unexpectedly succeeded:\n %s\n", formatted);
+ support_record_failure ();
+ free (formatted);
+ }
+ else
+ return;
+ case ACTION_CONTINUE:
+ {
+ char *formatted = support_format_addrinfo (ai, ret);
+
+ /* Verify that the result appears exactly once. */
+ const char *expected = "address: STREAM/TCP 192.0.0.1 80\n"
+ "address: DGRAM/UDP 192.0.0.1 80\n"
+ "address: RAW/IP 192.0.0.1 80\n";
+
+ const char *contains = strstr (formatted, expected);
+ const char *contains2 = NULL;
+
+ if (contains != NULL)
+ contains2 = strstr (contains + strlen (expected), expected);
+
+ if (contains == NULL || contains2 != NULL)
+ {
+ printf ("continue failed:\n%s\n", formatted);
+ support_record_failure ();
+ }
+
+ free (formatted);
+ break;
+ }
+ default:
+ __builtin_unreachable ();
+ }
+}
+
+static void
+do_one_test_set (int action)
+{
+ char buf[32];
+
+ snprintf (buf, sizeof (buf), "files [SUCCESS=%s] files",
+ action_str (action));
+ __nss_configure_lookup ("hosts", buf);
+
+ do_one_test (action, AF_UNSPEC, false);
+ do_one_test (action, AF_INET, false);
+ do_one_test (action, AF_INET, true);
+}
+
+static int
+do_test (void)
+{
+ do_one_test_set (ACTION_CONTINUE);
+ do_one_test_set (ACTION_MERGE);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/nss/tst-nss-gai-actions.root/etc/host.conf b/nss/tst-nss-gai-actions.root/etc/host.conf
new file mode 100644
index 0000000000000000..d1a59f73a90f2993
--- /dev/null
+++ b/nss/tst-nss-gai-actions.root/etc/host.conf
@@ -0,0 +1 @@
+multi on
diff --git a/nss/tst-nss-gai-actions.root/etc/hosts b/nss/tst-nss-gai-actions.root/etc/hosts
new file mode 100644
index 0000000000000000..50ce9774dc2c21d9
--- /dev/null
+++ b/nss/tst-nss-gai-actions.root/etc/hosts
@@ -0,0 +1,508 @@
+192.0.0.1 example.org
+192.0.0.2 example.org
+192.0.0.3 example.org
+192.0.0.4 example.org
+192.0.0.5 example.org
+192.0.0.6 example.org
+192.0.0.7 example.org
+192.0.0.8 example.org
+192.0.0.9 example.org
+192.0.0.10 example.org
+192.0.0.11 example.org
+192.0.0.12 example.org
+192.0.0.13 example.org
+192.0.0.14 example.org
+192.0.0.15 example.org
+192.0.0.16 example.org
+192.0.0.17 example.org
+192.0.0.18 example.org
+192.0.0.19 example.org
+192.0.0.20 example.org
+192.0.0.21 example.org
+192.0.0.22 example.org
+192.0.0.23 example.org
+192.0.0.24 example.org
+192.0.0.25 example.org
+192.0.0.26 example.org
+192.0.0.27 example.org
+192.0.0.28 example.org
+192.0.0.29 example.org
+192.0.0.30 example.org
+192.0.0.31 example.org
+192.0.0.32 example.org
+192.0.0.33 example.org
+192.0.0.34 example.org
+192.0.0.35 example.org
+192.0.0.36 example.org
+192.0.0.37 example.org
+192.0.0.38 example.org
+192.0.0.39 example.org
+192.0.0.40 example.org
+192.0.0.41 example.org
+192.0.0.42 example.org
+192.0.0.43 example.org
+192.0.0.44 example.org
+192.0.0.45 example.org
+192.0.0.46 example.org
+192.0.0.47 example.org
+192.0.0.48 example.org
+192.0.0.49 example.org
+192.0.0.50 example.org
+192.0.0.51 example.org
+192.0.0.52 example.org
+192.0.0.53 example.org
+192.0.0.54 example.org
+192.0.0.55 example.org
+192.0.0.56 example.org
+192.0.0.57 example.org
+192.0.0.58 example.org
+192.0.0.59 example.org
+192.0.0.60 example.org
+192.0.0.61 example.org
+192.0.0.62 example.org
+192.0.0.63 example.org
+192.0.0.64 example.org
+192.0.0.65 example.org
+192.0.0.66 example.org
+192.0.0.67 example.org
+192.0.0.68 example.org
+192.0.0.69 example.org
+192.0.0.70 example.org
+192.0.0.71 example.org
+192.0.0.72 example.org
+192.0.0.73 example.org
+192.0.0.74 example.org
+192.0.0.75 example.org
+192.0.0.76 example.org
+192.0.0.77 example.org
+192.0.0.78 example.org
+192.0.0.79 example.org
+192.0.0.80 example.org
+192.0.0.81 example.org
+192.0.0.82 example.org
+192.0.0.83 example.org
+192.0.0.84 example.org
+192.0.0.85 example.org
+192.0.0.86 example.org
+192.0.0.87 example.org
+192.0.0.88 example.org
+192.0.0.89 example.org
+192.0.0.90 example.org
+192.0.0.91 example.org
+192.0.0.92 example.org
+192.0.0.93 example.org
+192.0.0.94 example.org
+192.0.0.95 example.org
+192.0.0.96 example.org
+192.0.0.97 example.org
+192.0.0.98 example.org
+192.0.0.99 example.org
+192.0.0.100 example.org
+192.0.0.101 example.org
+192.0.0.102 example.org
+192.0.0.103 example.org
+192.0.0.104 example.org
+192.0.0.105 example.org
+192.0.0.106 example.org
+192.0.0.107 example.org
+192.0.0.108 example.org
+192.0.0.109 example.org
+192.0.0.110 example.org
+192.0.0.111 example.org
+192.0.0.112 example.org
+192.0.0.113 example.org
+192.0.0.114 example.org
+192.0.0.115 example.org
+192.0.0.116 example.org
+192.0.0.117 example.org
+192.0.0.118 example.org
+192.0.0.119 example.org
+192.0.0.120 example.org
+192.0.0.121 example.org
+192.0.0.122 example.org
+192.0.0.123 example.org
+192.0.0.124 example.org
+192.0.0.125 example.org
+192.0.0.126 example.org
+192.0.0.127 example.org
+192.0.0.128 example.org
+192.0.0.129 example.org
+192.0.0.130 example.org
+192.0.0.131 example.org
+192.0.0.132 example.org
+192.0.0.133 example.org
+192.0.0.134 example.org
+192.0.0.135 example.org
+192.0.0.136 example.org
+192.0.0.137 example.org
+192.0.0.138 example.org
+192.0.0.139 example.org
+192.0.0.140 example.org
+192.0.0.141 example.org
+192.0.0.142 example.org
+192.0.0.143 example.org
+192.0.0.144 example.org
+192.0.0.145 example.org
+192.0.0.146 example.org
+192.0.0.147 example.org
+192.0.0.148 example.org
+192.0.0.149 example.org
+192.0.0.150 example.org
+192.0.0.151 example.org
+192.0.0.152 example.org
+192.0.0.153 example.org
+192.0.0.154 example.org
+192.0.0.155 example.org
+192.0.0.156 example.org
+192.0.0.157 example.org
+192.0.0.158 example.org
+192.0.0.159 example.org
+192.0.0.160 example.org
+192.0.0.161 example.org
+192.0.0.162 example.org
+192.0.0.163 example.org
+192.0.0.164 example.org
+192.0.0.165 example.org
+192.0.0.166 example.org
+192.0.0.167 example.org
+192.0.0.168 example.org
+192.0.0.169 example.org
+192.0.0.170 example.org
+192.0.0.171 example.org
+192.0.0.172 example.org
+192.0.0.173 example.org
+192.0.0.174 example.org
+192.0.0.175 example.org
+192.0.0.176 example.org
+192.0.0.177 example.org
+192.0.0.178 example.org
+192.0.0.179 example.org
+192.0.0.180 example.org
+192.0.0.181 example.org
+192.0.0.182 example.org
+192.0.0.183 example.org
+192.0.0.184 example.org
+192.0.0.185 example.org
+192.0.0.186 example.org
+192.0.0.187 example.org
+192.0.0.188 example.org
+192.0.0.189 example.org
+192.0.0.190 example.org
+192.0.0.191 example.org
+192.0.0.192 example.org
+192.0.0.193 example.org
+192.0.0.194 example.org
+192.0.0.195 example.org
+192.0.0.196 example.org
+192.0.0.197 example.org
+192.0.0.198 example.org
+192.0.0.199 example.org
+192.0.0.200 example.org
+192.0.0.201 example.org
+192.0.0.202 example.org
+192.0.0.203 example.org
+192.0.0.204 example.org
+192.0.0.205 example.org
+192.0.0.206 example.org
+192.0.0.207 example.org
+192.0.0.208 example.org
+192.0.0.209 example.org
+192.0.0.210 example.org
+192.0.0.211 example.org
+192.0.0.212 example.org
+192.0.0.213 example.org
+192.0.0.214 example.org
+192.0.0.215 example.org
+192.0.0.216 example.org
+192.0.0.217 example.org
+192.0.0.218 example.org
+192.0.0.219 example.org
+192.0.0.220 example.org
+192.0.0.221 example.org
+192.0.0.222 example.org
+192.0.0.223 example.org
+192.0.0.224 example.org
+192.0.0.225 example.org
+192.0.0.226 example.org
+192.0.0.227 example.org
+192.0.0.228 example.org
+192.0.0.229 example.org
+192.0.0.230 example.org
+192.0.0.231 example.org
+192.0.0.232 example.org
+192.0.0.233 example.org
+192.0.0.234 example.org
+192.0.0.235 example.org
+192.0.0.236 example.org
+192.0.0.237 example.org
+192.0.0.238 example.org
+192.0.0.239 example.org
+192.0.0.240 example.org
+192.0.0.241 example.org
+192.0.0.242 example.org
+192.0.0.243 example.org
+192.0.0.244 example.org
+192.0.0.245 example.org
+192.0.0.246 example.org
+192.0.0.247 example.org
+192.0.0.248 example.org
+192.0.0.249 example.org
+192.0.0.250 example.org
+192.0.0.251 example.org
+192.0.0.252 example.org
+192.0.0.253 example.org
+192.0.0.254 example.org
+192.0.1.1 example.org
+192.0.1.2 example.org
+192.0.1.3 example.org
+192.0.1.4 example.org
+192.0.1.5 example.org
+192.0.1.6 example.org
+192.0.1.7 example.org
+192.0.1.8 example.org
+192.0.1.9 example.org
+192.0.1.10 example.org
+192.0.1.11 example.org
+192.0.1.12 example.org
+192.0.1.13 example.org
+192.0.1.14 example.org
+192.0.1.15 example.org
+192.0.1.16 example.org
+192.0.1.17 example.org
+192.0.1.18 example.org
+192.0.1.19 example.org
+192.0.1.20 example.org
+192.0.1.21 example.org
+192.0.1.22 example.org
+192.0.1.23 example.org
+192.0.1.24 example.org
+192.0.1.25 example.org
+192.0.1.26 example.org
+192.0.1.27 example.org
+192.0.1.28 example.org
+192.0.1.29 example.org
+192.0.1.30 example.org
+192.0.1.31 example.org
+192.0.1.32 example.org
+192.0.1.33 example.org
+192.0.1.34 example.org
+192.0.1.35 example.org
+192.0.1.36 example.org
+192.0.1.37 example.org
+192.0.1.38 example.org
+192.0.1.39 example.org
+192.0.1.40 example.org
+192.0.1.41 example.org
+192.0.1.42 example.org
+192.0.1.43 example.org
+192.0.1.44 example.org
+192.0.1.45 example.org
+192.0.1.46 example.org
+192.0.1.47 example.org
+192.0.1.48 example.org
+192.0.1.49 example.org
+192.0.1.50 example.org
+192.0.1.51 example.org
+192.0.1.52 example.org
+192.0.1.53 example.org
+192.0.1.54 example.org
+192.0.1.55 example.org
+192.0.1.56 example.org
+192.0.1.57 example.org
+192.0.1.58 example.org
+192.0.1.59 example.org
+192.0.1.60 example.org
+192.0.1.61 example.org
+192.0.1.62 example.org
+192.0.1.63 example.org
+192.0.1.64 example.org
+192.0.1.65 example.org
+192.0.1.66 example.org
+192.0.1.67 example.org
+192.0.1.68 example.org
+192.0.1.69 example.org
+192.0.1.70 example.org
+192.0.1.71 example.org
+192.0.1.72 example.org
+192.0.1.73 example.org
+192.0.1.74 example.org
+192.0.1.75 example.org
+192.0.1.76 example.org
+192.0.1.77 example.org
+192.0.1.78 example.org
+192.0.1.79 example.org
+192.0.1.80 example.org
+192.0.1.81 example.org
+192.0.1.82 example.org
+192.0.1.83 example.org
+192.0.1.84 example.org
+192.0.1.85 example.org
+192.0.1.86 example.org
+192.0.1.87 example.org
+192.0.1.88 example.org
+192.0.1.89 example.org
+192.0.1.90 example.org
+192.0.1.91 example.org
+192.0.1.92 example.org
+192.0.1.93 example.org
+192.0.1.94 example.org
+192.0.1.95 example.org
+192.0.1.96 example.org
+192.0.1.97 example.org
+192.0.1.98 example.org
+192.0.1.99 example.org
+192.0.1.100 example.org
+192.0.1.101 example.org
+192.0.1.102 example.org
+192.0.1.103 example.org
+192.0.1.104 example.org
+192.0.1.105 example.org
+192.0.1.106 example.org
+192.0.1.107 example.org
+192.0.1.108 example.org
+192.0.1.109 example.org
+192.0.1.110 example.org
+192.0.1.111 example.org
+192.0.1.112 example.org
+192.0.1.113 example.org
+192.0.1.114 example.org
+192.0.1.115 example.org
+192.0.1.116 example.org
+192.0.1.117 example.org
+192.0.1.118 example.org
+192.0.1.119 example.org
+192.0.1.120 example.org
+192.0.1.121 example.org
+192.0.1.122 example.org
+192.0.1.123 example.org
+192.0.1.124 example.org
+192.0.1.125 example.org
+192.0.1.126 example.org
+192.0.1.127 example.org
+192.0.1.128 example.org
+192.0.1.129 example.org
+192.0.1.130 example.org
+192.0.1.131 example.org
+192.0.1.132 example.org
+192.0.1.133 example.org
+192.0.1.134 example.org
+192.0.1.135 example.org
+192.0.1.136 example.org
+192.0.1.137 example.org
+192.0.1.138 example.org
+192.0.1.139 example.org
+192.0.1.140 example.org
+192.0.1.141 example.org
+192.0.1.142 example.org
+192.0.1.143 example.org
+192.0.1.144 example.org
+192.0.1.145 example.org
+192.0.1.146 example.org
+192.0.1.147 example.org
+192.0.1.148 example.org
+192.0.1.149 example.org
+192.0.1.150 example.org
+192.0.1.151 example.org
+192.0.1.152 example.org
+192.0.1.153 example.org
+192.0.1.154 example.org
+192.0.1.155 example.org
+192.0.1.156 example.org
+192.0.1.157 example.org
+192.0.1.158 example.org
+192.0.1.159 example.org
+192.0.1.160 example.org
+192.0.1.161 example.org
+192.0.1.162 example.org
+192.0.1.163 example.org
+192.0.1.164 example.org
+192.0.1.165 example.org
+192.0.1.166 example.org
+192.0.1.167 example.org
+192.0.1.168 example.org
+192.0.1.169 example.org
+192.0.1.170 example.org
+192.0.1.171 example.org
+192.0.1.172 example.org
+192.0.1.173 example.org
+192.0.1.174 example.org
+192.0.1.175 example.org
+192.0.1.176 example.org
+192.0.1.177 example.org
+192.0.1.178 example.org
+192.0.1.179 example.org
+192.0.1.180 example.org
+192.0.1.181 example.org
+192.0.1.182 example.org
+192.0.1.183 example.org
+192.0.1.184 example.org
+192.0.1.185 example.org
+192.0.1.186 example.org
+192.0.1.187 example.org
+192.0.1.188 example.org
+192.0.1.189 example.org
+192.0.1.190 example.org
+192.0.1.191 example.org
+192.0.1.192 example.org
+192.0.1.193 example.org
+192.0.1.194 example.org
+192.0.1.195 example.org
+192.0.1.196 example.org
+192.0.1.197 example.org
+192.0.1.198 example.org
+192.0.1.199 example.org
+192.0.1.200 example.org
+192.0.1.201 example.org
+192.0.1.202 example.org
+192.0.1.203 example.org
+192.0.1.204 example.org
+192.0.1.205 example.org
+192.0.1.206 example.org
+192.0.1.207 example.org
+192.0.1.208 example.org
+192.0.1.209 example.org
+192.0.1.210 example.org
+192.0.1.211 example.org
+192.0.1.212 example.org
+192.0.1.213 example.org
+192.0.1.214 example.org
+192.0.1.215 example.org
+192.0.1.216 example.org
+192.0.1.217 example.org
+192.0.1.218 example.org
+192.0.1.219 example.org
+192.0.1.220 example.org
+192.0.1.221 example.org
+192.0.1.222 example.org
+192.0.1.223 example.org
+192.0.1.224 example.org
+192.0.1.225 example.org
+192.0.1.226 example.org
+192.0.1.227 example.org
+192.0.1.228 example.org
+192.0.1.229 example.org
+192.0.1.230 example.org
+192.0.1.231 example.org
+192.0.1.232 example.org
+192.0.1.233 example.org
+192.0.1.234 example.org
+192.0.1.235 example.org
+192.0.1.236 example.org
+192.0.1.237 example.org
+192.0.1.238 example.org
+192.0.1.239 example.org
+192.0.1.240 example.org
+192.0.1.241 example.org
+192.0.1.242 example.org
+192.0.1.243 example.org
+192.0.1.244 example.org
+192.0.1.245 example.org
+192.0.1.246 example.org
+192.0.1.247 example.org
+192.0.1.248 example.org
+192.0.1.249 example.org
+192.0.1.250 example.org
+192.0.1.251 example.org
+192.0.1.252 example.org
+192.0.1.253 example.org
+192.0.1.254 example.org
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
index fae3dea81f19dba6..4fa963644af8b7d5 100644
--- a/sysdeps/posix/getaddrinfo.c
+++ b/sysdeps/posix/getaddrinfo.c
@@ -474,11 +474,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
if (name != NULL)
{
- at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
- at->family = AF_UNSPEC;
- at->scopeid = 0;
- at->next = NULL;
-
if (req->ai_flags & AI_IDN)
{
char *out;
@@ -489,13 +484,21 @@ gaih_inet (const char *name, const struct gaih_service *service,
malloc_name = true;
}
- if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0)
+ uint32_t addr[4];
+ if (__inet_aton_exact (name, (struct in_addr *) addr) != 0)
{
+ at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
+ at->scopeid = 0;
+ at->next = NULL;
+
if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
- at->family = AF_INET;
+ {
+ memcpy (at->addr, addr, sizeof (at->addr));
+ at->family = AF_INET;
+ }
else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
{
- at->addr[3] = at->addr[0];
+ at->addr[3] = addr[0];
at->addr[2] = htonl (0xffff);
at->addr[1] = 0;
at->addr[0] = 0;
@@ -509,49 +512,62 @@ gaih_inet (const char *name, const struct gaih_service *service,
if (req->ai_flags & AI_CANONNAME)
canon = name;
+
+ goto process_list;
}
- else if (at->family == AF_UNSPEC)
+
+ char *scope_delim = strchr (name, SCOPE_DELIMITER);
+ int e;
+
+ if (scope_delim == NULL)
+ e = inet_pton (AF_INET6, name, addr);
+ else
+ e = __inet_pton_length (AF_INET6, name, scope_delim - name, addr);
+
+ if (e > 0)
{
- char *scope_delim = strchr (name, SCOPE_DELIMITER);
- int e;
- if (scope_delim == NULL)
- e = inet_pton (AF_INET6, name, at->addr);
+ at = alloca_account (sizeof (struct gaih_addrtuple),
+ alloca_used);
+ at->scopeid = 0;
+ at->next = NULL;
+
+ if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
+ {
+ memcpy (at->addr, addr, sizeof (at->addr));
+ at->family = AF_INET6;
+ }
+ else if (req->ai_family == AF_INET
+ && IN6_IS_ADDR_V4MAPPED (addr))
+ {
+ at->addr[0] = addr[3];
+ at->addr[1] = addr[1];
+ at->addr[2] = addr[2];
+ at->addr[3] = addr[3];
+ at->family = AF_INET;
+ }
else
- e = __inet_pton_length (AF_INET6, name, scope_delim - name,
- at->addr);
- if (e > 0)
{
- if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
- at->family = AF_INET6;
- else if (req->ai_family == AF_INET
- && IN6_IS_ADDR_V4MAPPED (at->addr))
- {
- at->addr[0] = at->addr[3];
- at->family = AF_INET;
- }
- else
- {
- result = -EAI_ADDRFAMILY;
- goto free_and_return;
- }
-
- if (scope_delim != NULL
- && __inet6_scopeid_pton ((struct in6_addr *) at->addr,
- scope_delim + 1,
- &at->scopeid) != 0)
- {
- result = -EAI_NONAME;
- goto free_and_return;
- }
+ result = -EAI_ADDRFAMILY;
+ goto free_and_return;
+ }
- if (req->ai_flags & AI_CANONNAME)
- canon = name;
+ if (scope_delim != NULL
+ && __inet6_scopeid_pton ((struct in6_addr *) at->addr,
+ scope_delim + 1,
+ &at->scopeid) != 0)
+ {
+ result = -EAI_NONAME;
+ goto free_and_return;
}
+
+ if (req->ai_flags & AI_CANONNAME)
+ canon = name;
+
+ goto process_list;
}
- if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
+ if ((req->ai_flags & AI_NUMERICHOST) == 0)
{
- struct gaih_addrtuple **pat = &at;
int no_data = 0;
int no_inet6_data = 0;
service_user *nip;
@@ -560,6 +576,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
int no_more;
struct resolv_context *res_ctx = NULL;
bool res_enable_inet6 = false;
+ bool do_merge = false;
/* If we do not have to look for IPv6 addresses or the canonical
name, use the simple, old functions, which do not support
@@ -596,7 +613,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
result = -EAI_MEMORY;
goto free_and_return;
}
- *pat = addrmem;
+ at = addrmem;
}
else
{
@@ -649,6 +666,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
}
struct gaih_addrtuple *addrfree = addrmem;
+ struct gaih_addrtuple **pat = &at;
+
for (int i = 0; i < air->naddrs; ++i)
{
socklen_t size = (air->family[i] == AF_INET
@@ -712,12 +731,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
free (air);
- if (at->family == AF_UNSPEC)
- {
- result = -EAI_NONAME;
- goto free_and_return;
- }
-
goto process_list;
}
else if (err == 0)
@@ -756,6 +769,22 @@ gaih_inet (const char *name, const struct gaih_service *service,
while (!no_more)
{
+ /* Always start afresh; continue should discard previous results
+ and the hosts database does not support merge. */
+ at = NULL;
+ free (canonbuf);
+ free (addrmem);
+ canon = canonbuf = NULL;
+ addrmem = NULL;
+ got_ipv6 = false;
+
+ if (do_merge)
+ {
+ __set_h_errno (NETDB_INTERNAL);
+ __set_errno (EBUSY);
+ break;
+ }
+
no_data = 0;
nss_gethostbyname4_r fct4 = NULL;
@@ -768,12 +797,14 @@ gaih_inet (const char *name, const struct gaih_service *service,
{
while (1)
{
- status = DL_CALL_FCT (fct4, (name, pat,
+ status = DL_CALL_FCT (fct4, (name, &at,
tmpbuf->data, tmpbuf->length,
&errno, &h_errno,
NULL));
if (status == NSS_STATUS_SUCCESS)
break;
+ /* gethostbyname4_r may write into AT, so reset it. */
+ at = NULL;
if (status != NSS_STATUS_TRYAGAIN
|| errno != ERANGE || h_errno != NETDB_INTERNAL)
{
@@ -800,7 +831,9 @@ gaih_inet (const char *name, const struct gaih_service *service,
no_data = 1;
if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
- canon = (*pat)->name;
+ canon = at->name;
+
+ struct gaih_addrtuple **pat = &at;
while (*pat != NULL)
{
@@ -852,6 +885,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
if (fct != NULL)
{
+ struct gaih_addrtuple **pat = &at;
+
if (req->ai_family == AF_INET6
|| req->ai_family == AF_UNSPEC)
{
@@ -927,6 +962,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
break;
+ /* The hosts database does not support MERGE. */
+ if (nss_next_action (nip, status) == NSS_ACTION_MERGE)
+ do_merge = true;
+
if (nip->next == NULL)
no_more = -1;
else
@@ -960,7 +999,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
}
process_list:
- if (at->family == AF_UNSPEC)
+ if (at == NULL)
{
result = -EAI_NONAME;
goto free_and_return;

View file

@ -1,171 +0,0 @@
From 2e86602d21fcaa8353c529f2f6768125396da39f Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 19 Jul 2023 23:12:30 +0800
Subject: [PATCH 5/6] Support target specific ALIGN for variable alignment test
[BZ #28676]
Add <tst-file-align.h> to support target specific ALIGN for variable
alignment test:
1. Alpha: Use 0x10000.
2. MicroBlaze and Nios II: Use 0x8000.
3. All others: Use 0x200000.
Backport from master commit: 4435c29
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Signed-off-by: Rongwei Wang <rongwei.wang@linux.alibaba.com>
---
elf/tst-align3.c | 4 +---
elf/tst-alignmod3.c | 4 +---
sysdeps/alpha/tst-file-align.h | 20 ++++++++++++++++++++
sysdeps/generic/tst-file-align.h | 20 ++++++++++++++++++++
sysdeps/microblaze/tst-file-align.h | 20 ++++++++++++++++++++
sysdeps/nios2/tst-file-align.h | 20 ++++++++++++++++++++
6 files changed, 82 insertions(+), 6 deletions(-)
create mode 100644 sysdeps/alpha/tst-file-align.h
create mode 100644 sysdeps/generic/tst-file-align.h
create mode 100644 sysdeps/microblaze/tst-file-align.h
create mode 100644 sysdeps/nios2/tst-file-align.h
diff --git a/elf/tst-align3.c b/elf/tst-align3.c
index ac86d623..87a8ff81 100644
--- a/elf/tst-align3.c
+++ b/elf/tst-align3.c
@@ -17,11 +17,9 @@
<https://www.gnu.org/licenses/>. */
#include <support/check.h>
+#include <tst-file-align.h>
#include <tst-stack-align.h>
-/* This should cover all possible page sizes we currently support. */
-#define ALIGN 0x200000
-
int bar __attribute__ ((aligned (ALIGN))) = 1;
extern int do_load_test (void);
diff --git a/elf/tst-alignmod3.c b/elf/tst-alignmod3.c
index 0d33f237..9520c352 100644
--- a/elf/tst-alignmod3.c
+++ b/elf/tst-alignmod3.c
@@ -17,11 +17,9 @@
<https://www.gnu.org/licenses/>. */
#include <support/check.h>
+#include <tst-file-align.h>
#include <tst-stack-align.h>
-/* This should cover all possible page sizes we currently support. */
-#define ALIGN 0x200000
-
int foo __attribute__ ((aligned (ALIGN))) = 1;
void
diff --git a/sysdeps/alpha/tst-file-align.h b/sysdeps/alpha/tst-file-align.h
new file mode 100644
index 00000000..8fc3c940
--- /dev/null
+++ b/sysdeps/alpha/tst-file-align.h
@@ -0,0 +1,20 @@
+/* Check file alignment. Alpha version.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* This should cover all possible alignments we currently support. */
+#define ALIGN 0x10000
diff --git a/sysdeps/generic/tst-file-align.h b/sysdeps/generic/tst-file-align.h
new file mode 100644
index 00000000..6ee6783a
--- /dev/null
+++ b/sysdeps/generic/tst-file-align.h
@@ -0,0 +1,20 @@
+/* Check file alignment. Generic version.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* This should cover all possible page sizes we currently support. */
+#define ALIGN 0x200000
diff --git a/sysdeps/microblaze/tst-file-align.h b/sysdeps/microblaze/tst-file-align.h
new file mode 100644
index 00000000..43c58b29
--- /dev/null
+++ b/sysdeps/microblaze/tst-file-align.h
@@ -0,0 +1,20 @@
+/* Check file alignment. MicroBlaze version.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* This should cover all possible alignments we currently support. */
+#define ALIGN 0x8000
diff --git a/sysdeps/nios2/tst-file-align.h b/sysdeps/nios2/tst-file-align.h
new file mode 100644
index 00000000..589a2d5a
--- /dev/null
+++ b/sysdeps/nios2/tst-file-align.h
@@ -0,0 +1,20 @@
+/* Check file alignment. Nios II version.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* This should cover all possible alignments we currently support. */
+#define ALIGN 0x8000
--
2.27.0

File diff suppressed because it is too large Load diff

View file

@ -1,183 +0,0 @@
From b9f145df85145506f8e61bac38b792584a38d88f Mon Sep 17 00:00:00 2001
From: Krzysztof Koch <Krzysztof.Koch@arm.com>
Date: Tue, 5 Nov 2019 17:35:18 +0000
Subject: [PATCH 02/14] aarch64: Increase small and medium cases for
__memcpy_generic
Increase the upper bound on medium cases from 96 to 128 bytes.
Now, up to 128 bytes are copied unrolled.
Increase the upper bound on small cases from 16 to 32 bytes so that
copies of 17-32 bytes are not impacted by the larger medium case.
Benchmarking:
The attached figures show relative timing difference with respect
to 'memcpy_generic', which is the existing implementation.
'memcpy_med_128' denotes the the version of memcpy_generic with
only the medium case enlarged. The 'memcpy_med_128_small_32' numbers
are for the version of memcpy_generic submitted in this patch, which
has both medium and small cases enlarged. The figures were generated
using the script from:
https://www.sourceware.org/ml/libc-alpha/2019-10/msg00563.html
Depending on the platform, the performance improvement in the
bench-memcpy-random.c benchmark ranges from 6% to 20% between
the original and final version of memcpy.S
Tested against GLIBC testsuite and randomized tests.
---
sysdeps/aarch64/memcpy.S | 82 +++++++++++++++++++++++-----------------
1 file changed, 47 insertions(+), 35 deletions(-)
diff --git a/sysdeps/aarch64/memcpy.S b/sysdeps/aarch64/memcpy.S
index 6e4f4a74bd..10801aa0f4 100644
--- a/sysdeps/aarch64/memcpy.S
+++ b/sysdeps/aarch64/memcpy.S
@@ -41,17 +41,19 @@
#define C_h x11
#define D_l x12
#define D_h x13
-#define E_l src
-#define E_h count
-#define F_l srcend
-#define F_h dst
+#define E_l x14
+#define E_h x15
+#define F_l x16
+#define F_h x17
#define G_l count
#define G_h dst
+#define H_l src
+#define H_h srcend
#define tmp1 x14
-/* Copies are split into 3 main cases: small copies of up to 16 bytes,
- medium copies of 17..96 bytes which are fully unrolled. Large copies
- of more than 96 bytes align the destination and use an unrolled loop
+/* Copies are split into 3 main cases: small copies of up to 32 bytes,
+ medium copies of 33..128 bytes which are fully unrolled. Large copies
+ of more than 128 bytes align the destination and use an unrolled loop
processing 64 bytes per iteration.
In order to share code with memmove, small and medium copies read all
data before writing, allowing any kind of overlap. So small, medium
@@ -73,7 +75,7 @@ ENTRY_ALIGN (MEMMOVE, 6)
DELOUSE (2)
sub tmp1, dstin, src
- cmp count, 96
+ cmp count, 128
ccmp tmp1, count, 2, hi
b.lo L(move_long)
@@ -89,31 +91,39 @@ ENTRY (MEMCPY)
prfm PLDL1KEEP, [src]
add srcend, src, count
add dstend, dstin, count
- cmp count, 16
- b.ls L(copy16)
- cmp count, 96
+ cmp count, 32
+ b.ls L(copy32)
+ cmp count, 128
b.hi L(copy_long)
- /* Medium copies: 17..96 bytes. */
- sub tmp1, count, 1
+ /* Medium copies: 33..128 bytes. */
ldp A_l, A_h, [src]
- tbnz tmp1, 6, L(copy96)
- ldp D_l, D_h, [srcend, -16]
- tbz tmp1, 5, 1f
ldp B_l, B_h, [src, 16]
ldp C_l, C_h, [srcend, -32]
+ ldp D_l, D_h, [srcend, -16]
+ cmp count, 64
+ b.hi L(copy128)
+ stp A_l, A_h, [dstin]
stp B_l, B_h, [dstin, 16]
stp C_l, C_h, [dstend, -32]
-1:
- stp A_l, A_h, [dstin]
stp D_l, D_h, [dstend, -16]
ret
.p2align 4
- /* Small copies: 0..16 bytes. */
-L(copy16):
- cmp count, 8
+ /* Small copies: 0..32 bytes. */
+L(copy32):
+ /* 16-32 bytes. */
+ cmp count, 16
b.lo 1f
+ ldp A_l, A_h, [src]
+ ldp B_l, B_h, [srcend, -16]
+ stp A_l, A_h, [dstin]
+ stp B_l, B_h, [dstend, -16]
+ ret
+ .p2align 4
+1:
+ /* 8-15 bytes. */
+ tbz count, 3, 1f
ldr A_l, [src]
ldr A_h, [srcend, -8]
str A_l, [dstin]
@@ -121,6 +131,7 @@ L(copy16):
ret
.p2align 4
1:
+ /* 4-7 bytes. */
tbz count, 2, 1f
ldr A_lw, [src]
ldr A_hw, [srcend, -4]
@@ -142,24 +153,25 @@ L(copy16):
2: ret
.p2align 4
- /* Copy 64..96 bytes. Copy 64 bytes from the start and
- 32 bytes from the end. */
-L(copy96):
- ldp B_l, B_h, [src, 16]
- ldp C_l, C_h, [src, 32]
- ldp D_l, D_h, [src, 48]
- ldp E_l, E_h, [srcend, -32]
- ldp F_l, F_h, [srcend, -16]
+ /* Copy 65..128 bytes. Copy 64 bytes from the start and
+ 64 bytes from the end. */
+L(copy128):
+ ldp E_l, E_h, [src, 32]
+ ldp F_l, F_h, [src, 48]
+ ldp G_l, G_h, [srcend, -64]
+ ldp H_l, H_h, [srcend, -48]
stp A_l, A_h, [dstin]
stp B_l, B_h, [dstin, 16]
- stp C_l, C_h, [dstin, 32]
- stp D_l, D_h, [dstin, 48]
- stp E_l, E_h, [dstend, -32]
- stp F_l, F_h, [dstend, -16]
+ stp E_l, E_h, [dstin, 32]
+ stp F_l, F_h, [dstin, 48]
+ stp G_l, G_h, [dstend, -64]
+ stp H_l, H_h, [dstend, -48]
+ stp C_l, C_h, [dstend, -32]
+ stp D_l, D_h, [dstend, -16]
ret
/* Align DST to 16 byte alignment so that we don't cross cache line
- boundaries on both loads and stores. There are at least 96 bytes
+ boundaries on both loads and stores. There are at least 128 bytes
to copy, so copy 16 bytes unaligned and then align. The loop
copies 64 bytes per iteration and prefetches one iteration ahead. */
@@ -215,7 +227,7 @@ L(move_long):
add dstend, dstin, count
/* Align dstend to 16 byte alignment so that we don't cross cache line
- boundaries on both loads and stores. There are at least 96 bytes
+ boundaries on both loads and stores. There are at least 128 bytes
to copy, so copy 16 bytes unaligned and then align. The loop
copies 64 bytes per iteration and prefetches one iteration ahead. */
--
2.39.3

View file

@ -1,25 +0,0 @@
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)

View file

@ -1,286 +0,0 @@
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

View file

@ -1,15 +1,44 @@
Short description: Adjust CS_PATH return value.
Short description: Adjust CS_PATH and the test container layout.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: not-needed
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).
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).
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
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
@@ -1 +1 @@
-#define CS_PATH "/bin:/usr/bin"
+#define CS_PATH "/usr/bin"

View file

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

View file

@ -1,36 +0,0 @@
From bf126f79dff0370d1e52ef8193da7fd593c37833 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Wed, 19 Jul 2023 23:10:48 +0800
Subject: [PATCH 4/6] elf: Align argument of __munmap to page size [BZ #28676]
On Linux/x86-64, for elf/tst-align3, we now get
munmap(0x7f88f9401000, 1126424) = 0
instead of
munmap(0x7f1615200018, 544768) = -1 EINVAL (Invalid argument)
Backport from master commit: fd6062e
Reviewed-by: Florian Weimer <fweimer@redhat.com>
Signed-off-by: Rongwei Wang <rongwei.wang@linux.alibaba.com>
---
elf/dl-map-segments.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
index 61ba04cd..f1f7ad88 100644
--- a/elf/dl-map-segments.h
+++ b/elf/dl-map-segments.h
@@ -55,6 +55,7 @@ _dl_map_segment (const struct loadcmd *c, ElfW(Addr) mappref,
if (delta)
__munmap ((void *) map_start, delta);
ElfW(Addr) map_end = map_start_aligned + maplength;
+ map_end = ALIGN_UP (map_end, GLRO(dl_pagesize));
delta = map_start + maplen - map_end;
if (delta)
__munmap ((void *) map_end, delta);
--
2.27.0

View file

@ -1,40 +0,0 @@
From 8b39d3b4bf2fc49ab31f31cf30aa80104afa3432 Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed, 19 Jul 2023 23:14:33 +0800
Subject: [PATCH 6/6] elf: Fix tst-align3
The elf/tst-align3.c declares the function using a wrong prototype.
Checked on aarch64-linux-gnu.
Signed-off-by: Rongwei Wang <rongwei.wang@linux.alibaba.com>
---
elf/tst-align3.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/elf/tst-align3.c b/elf/tst-align3.c
index 87a8ff81..731dd59f 100644
--- a/elf/tst-align3.c
+++ b/elf/tst-align3.c
@@ -22,7 +22,7 @@
int bar __attribute__ ((aligned (ALIGN))) = 1;
-extern int do_load_test (void);
+extern void do_load_test (void);
static int
do_test (void)
@@ -30,7 +30,8 @@ do_test (void)
printf ("bar: %p\n", &bar);
TEST_VERIFY (is_aligned (&bar, ALIGN) == 0);
- return do_load_test ();
+ do_load_test ();
+ return 0;
}
#include <support/test-driver.c>
--
2.27.0

View file

@ -1,137 +0,0 @@
From fe5893121176136b0ae3a5f9198536feeb6f64f8 Mon Sep 17 00:00:00 2001
From: Rongwei Wang <rongwei.wang@linux.alibaba.com>
Date: Wed, 19 Jul 2023 23:05:39 +0800
Subject: [PATCH 2/6] elf: Properly align PT_LOAD segments [BZ #28676]
When PT_LOAD segment alignment > the page size, allocate enough space to
ensure that the segment can be properly aligned. This change helps code
segments use huge pages become simple and available.
This fixes [BZ #28676].
Backport from master commit: 718fdd8
Signed-off-by: Xu Yu <xuyu@linux.alibaba.com>
Signed-off-by: Rongwei Wang <rongwei.wang@linux.alibaba.com>
---
elf/dl-load.c | 2 ++
elf/dl-load.h | 3 ++-
elf/dl-map-segments.h | 50 +++++++++++++++++++++++++++++++++++++++----
3 files changed, 50 insertions(+), 5 deletions(-)
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 0b45e6e3..132e4233 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1,5 +1,6 @@
/* Map in a shared object's segments from the file.
Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ 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
@@ -1076,6 +1077,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
c->mapend = ALIGN_UP (ph->p_vaddr + ph->p_filesz, GLRO(dl_pagesize));
c->dataend = ph->p_vaddr + ph->p_filesz;
c->allocend = ph->p_vaddr + ph->p_memsz;
+ c->mapalign = ph->p_align;
c->mapoff = ALIGN_DOWN (ph->p_offset, GLRO(dl_pagesize));
/* Determine whether there is a gap between the last segment
diff --git a/elf/dl-load.h b/elf/dl-load.h
index 66ea2e92..d9f648ea 100644
--- a/elf/dl-load.h
+++ b/elf/dl-load.h
@@ -1,5 +1,6 @@
/* Map in a shared object's segments from the file.
Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ 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
@@ -74,7 +75,7 @@ ELF_PREFERRED_ADDRESS_DATA;
Its details have been expanded out and converted. */
struct loadcmd
{
- ElfW(Addr) mapstart, mapend, dataend, allocend;
+ ElfW(Addr) mapstart, mapend, dataend, allocend, mapalign;
ElfW(Off) mapoff;
int prot; /* PROT_* bits. */
};
diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
index 084076a2..61ba04cd 100644
--- a/elf/dl-map-segments.h
+++ b/elf/dl-map-segments.h
@@ -1,5 +1,6 @@
/* Map in a shared object's segments. Generic version.
Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ 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
@@ -18,6 +19,50 @@
#include <dl-load.h>
+/* Map a segment and align it properly. */
+
+static __always_inline ElfW(Addr)
+_dl_map_segment (const struct loadcmd *c, ElfW(Addr) mappref,
+ const size_t maplength, int fd)
+{
+ if (__glibc_likely (c->mapalign <= GLRO(dl_pagesize)))
+ return (ElfW(Addr)) __mmap ((void *) mappref, maplength, c->prot,
+ MAP_COPY|MAP_FILE, fd, c->mapoff);
+
+ /* If the segment alignment > the page size, allocate enough space to
+ ensure that the segment can be properly aligned. */
+ ElfW(Addr) maplen = (maplength >= c->mapalign
+ ? (maplength + c->mapalign)
+ : (2 * c->mapalign));
+ ElfW(Addr) map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplen,
+ PROT_NONE,
+ MAP_ANONYMOUS|MAP_PRIVATE,
+ -1, 0);
+ if (__glibc_unlikely ((void *) map_start == MAP_FAILED))
+ return map_start;
+
+ ElfW(Addr) map_start_aligned = ALIGN_UP (map_start, c->mapalign);
+ map_start_aligned = (ElfW(Addr)) __mmap ((void *) map_start_aligned,
+ maplength, c->prot,
+ MAP_COPY|MAP_FILE|MAP_FIXED,
+ fd, c->mapoff);
+ if (__glibc_unlikely ((void *) map_start_aligned == MAP_FAILED))
+ __munmap ((void *) map_start, maplen);
+ else
+ {
+ /* Unmap the unused regions. */
+ ElfW(Addr) delta = map_start_aligned - map_start;
+ if (delta)
+ __munmap ((void *) map_start, delta);
+ ElfW(Addr) map_end = map_start_aligned + maplength;
+ delta = map_start + maplen - map_end;
+ if (delta)
+ __munmap ((void *) map_end, delta);
+ }
+
+ return map_start_aligned;
+}
+
/* This implementation assumes (as does the corresponding implementation
of _dl_unmap_segments, in dl-unmap-segments.h) that shared objects
are always laid out with all segments contiguous (or with gaps
@@ -53,10 +98,7 @@ _dl_map_segments (struct link_map *l, int fd,
- MAP_BASE_ADDR (l));
/* Remember which part of the address space this object uses. */
- l->l_map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplength,
- c->prot,
- MAP_COPY|MAP_FILE,
- fd, c->mapoff);
+ l->l_map_start = _dl_map_segment (c, mappref, maplength, fd);
if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED))
return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
--
2.27.0

View file

@ -1,91 +0,0 @@
Short description: Cleanup use of _dl_starting_up.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Upstream status: https://sourceware.org/ml/libc-alpha/2014-02/msg00589.html
Upstream discussions:
https://sourceware.org/ml/libc-alpha/2014-02/msg00580.html
Based on the following commit:
~~~
From 16552c01a66633c9e412984d9d92616bd4e5303c Mon Sep 17 00:00:00 2001
From: Andreas Schwab <schwab@redhat.com>
Date: Fri, 11 Jun 2010 11:04:11 +0200
Subject: [PATCH] Properly set __libc_multiple_libcs
* elf/rtld.c (_dl_starting_up): Always define.
(dl_main): Always set _dl_starting_up.
* elf/dl-support.c (_dl_starting_up): Always define.
* elf/dl-init.c (_dl_init): Always clear _dl_starting_up.
---
ChangeLog | 7 +++++++
elf/dl-init.c | 4 ----
elf/dl-support.c | 2 --
elf/rtld.c | 4 ----
4 files changed, 7 insertions(+), 10 deletions(-)
~~~
This patch needs to go upstream to get cleaned up, but has always involed
analysis of the GNU/Hurd parts of the change and that stalled out, but
perhaps with build-many-glibcs we can now test these changes more easily.
Index: b/elf/dl-init.c
===================================================================
--- a/elf/dl-init.c
+++ b/elf/dl-init.c
@@ -119,8 +119,6 @@ _dl_init (struct link_map *main_map, int
while (i-- > 0)
call_init (main_map->l_initfini[i], argc, argv, env);
-#ifndef HAVE_INLINED_SYSCALLS
/* Finished starting up. */
_dl_starting_up = 0;
-#endif
}
Index: b/elf/dl-support.c
===================================================================
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -117,10 +117,8 @@ struct r_scope_elem _dl_initial_searchli
.r_nlist = 1,
};
-#ifndef HAVE_INLINED_SYSCALLS
/* Nonzero during startup. */
int _dl_starting_up = 1;
-#endif
/* Random data provided by the kernel. */
void *_dl_random;
Index: b/elf/rtld.c
===================================================================
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -214,7 +214,6 @@ audit_list_iter_next (struct audit_list_
return iter->previous->name;
}
-#ifndef HAVE_INLINED_SYSCALLS
/* Set nonzero during loading and initialization of executable and
libraries, cleared before the executable's entry point runs. This
must not be initialized to nonzero, because the unused dynamic
@@ -224,7 +223,6 @@ audit_list_iter_next (struct audit_list_
never be called. */
int _dl_starting_up = 0;
rtld_hidden_def (_dl_starting_up)
-#endif
/* This is the structure which defines all variables global to ld.so
(except those which cannot be added for some reason). */
@@ -898,10 +896,8 @@ dl_main (const ElfW(Phdr) *phdr,
/* Process the environment variable which control the behaviour. */
process_envvars (&mode);
-#ifndef HAVE_INLINED_SYSCALLS
/* Set up a flag which tells we are just starting. */
_dl_starting_up = 1;
-#endif
if (*user_entry == (ElfW(Addr)) ENTRY_POINT)
{

View file

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

View file

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

View file

@ -1,46 +0,0 @@
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)
{

View file

@ -1,31 +0,0 @@
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

View file

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

View file

@ -1,38 +0,0 @@
Short description: Do not define _XOPEN_STREAMS.
Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
Origin: PATCH
Bug-Fedora: #436349
Upstream status: not-submitted
This patch should go upstream. Not defining _XOPEN_STREAMS is the
same as setting it to -1 for POSIX conformance. The headers setting
needs to be reviewed indepedently.
This is part of commit glibc-2.3.3-1564-gd0b6ac6
* Fri Mar 14 2008 Jakub Jelinek <jakub@redhat.com> 2.7.90-11
- remove <stropts.h>, define _XOPEN_STREAMS -1 (#436349)
diff -Nrup a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
--- a/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-05 07:42:49.000000000 -0600
+++ b/sysdeps/unix/sysv/linux/bits/posix_opt.h 2012-06-07 12:15:21.817318674 -0600
@@ -188,4 +188,7 @@
/* Typed memory objects are not available. */
#define _POSIX_TYPED_MEMORY_OBJECTS -1
+/* Streams are not available. */
+#define _XOPEN_STREAMS -1
+
#endif /* bits/posix_opt.h */
diff -Nrup a/streams/Makefile b/streams/Makefile
--- a/streams/Makefile 2012-06-05 07:42:49.000000000 -0600
+++ b/streams/Makefile 2012-06-07 12:15:21.824318649 -0600
@@ -20,7 +20,7 @@
include ../Makeconfig
-headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
+#headers = stropts.h sys/stropts.h bits/stropts.h bits/xtitypes.h
routines = isastream getmsg getpmsg putmsg putpmsg fattach fdetach
include ../Rules

View file

@ -0,0 +1,797 @@
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>

View file

@ -8,14 +8,14 @@ behaviour which updates the locale archive. The Fedora install phase
in the spec file of the rpm will handle this manually.
diff --git a/localedata/Makefile b/localedata/Makefile
index a5f3c92d58954dfc..56719c7c714aa0f1 100644
index 0eea396ad86da956..54caabda33728207 100644
--- a/localedata/Makefile
+++ b/localedata/Makefile
@@ -218,6 +218,7 @@ $(INSTALL-SUPPORTED-LOCALES): install-locales-dir
@@ -413,6 +413,7 @@ define build-one-locale
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';

View file

@ -1,21 +0,0 @@
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

View file

@ -8,33 +8,24 @@ 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 ea25f778c09bba9d..b53beb3c6e32c3cf 100755
index a85ca3a38be1fdeb..9f1ea9d85f4b833a 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-2018 Free Software Foundation, Inc.
# Copyright (C) 2015-2023 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 602b3f954d4801a6..76bf1528a5418748 100644
index d8bdde7753885a4d..698c4ff81b13f697 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-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.
# Copyright (C) 2015-2023 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
#

File diff suppressed because one or more lines are too long

View file

@ -1,79 +0,0 @@
commit dbb75513f5cf9285c77c9e55777c5c35b653f890
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Sep 6 07:38:10 2022 +0200
elf: Rename _dl_sort_maps parameter from skip to force_first
The new implementation will not be able to skip an arbitrary number
of objects.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
index 99354dc08a010dd3..7a586749adc3fa7d 100644
--- a/elf/dl-sort-maps.c
+++ b/elf/dl-sort-maps.c
@@ -27,12 +27,12 @@
If FOR_FINI is true, this is called for finishing an object. */
static void
_dl_sort_maps_original (struct link_map **maps, unsigned int nmaps,
- unsigned int skip, bool for_fini)
+ bool force_first, bool for_fini)
{
/* Allows caller to do the common optimization of skipping the first map,
usually the main binary. */
- maps += skip;
- nmaps -= skip;
+ maps += force_first;
+ nmaps -= force_first;
/* A list of one element need not be sorted. */
if (nmaps <= 1)
@@ -182,7 +182,7 @@ dfs_traversal (struct link_map ***rpo, struct link_map *map,
static void
_dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
- unsigned int skip __attribute__ ((unused)), bool for_fini)
+ bool force_first __attribute__ ((unused)), bool for_fini)
{
for (int i = nmaps - 1; i >= 0; i--)
maps[i]->l_visited = 0;
@@ -286,7 +286,7 @@ _dl_sort_maps_init (void)
void
_dl_sort_maps (struct link_map **maps, unsigned int nmaps,
- unsigned int skip, bool for_fini)
+ bool force_first, bool for_fini)
{
/* It can be tempting to use a static function pointer to store and call
the current selected sorting algorithm routine, but experimentation
@@ -296,9 +296,9 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps,
input cases. A simple if-case with direct function calls appears to
be the fastest. */
if (__glibc_likely (GLRO(dl_dso_sort_algo) == dso_sort_algorithm_original))
- _dl_sort_maps_original (maps, nmaps, skip, for_fini);
+ _dl_sort_maps_original (maps, nmaps, force_first, for_fini);
else
- _dl_sort_maps_dfs (maps, nmaps, skip, for_fini);
+ _dl_sort_maps_dfs (maps, nmaps, force_first, for_fini);
}
#endif /* HAVE_TUNABLES. */
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 9f09a4a280396659..2c1b4c47c6a6c643 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1056,9 +1056,11 @@ extern void _dl_init (struct link_map *main_map, int argc, char **argv,
initializer functions have completed. */
extern void _dl_fini (void) attribute_hidden;
-/* Sort array MAPS according to dependencies of the contained objects. */
+/* Sort array MAPS according to dependencies of the contained objects.
+ If FORCE_FIRST, MAPS[0] keeps its place even if the dependencies
+ say otherwise. */
extern void _dl_sort_maps (struct link_map **maps, unsigned int nmaps,
- unsigned int skip, bool for_fini) attribute_hidden;
+ bool force_first, bool for_fini) attribute_hidden;
/* The dynamic linker calls this function before and having changing
any shared object mappings. The `r_state' member of `struct r_debug'

View file

@ -1,90 +0,0 @@
commit 1df71d32fe5f5905ffd5d100e5e9ca8ad6210891
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Sep 20 11:00:42 2022 +0200
elf: Implement force_first handling in _dl_sort_maps_dfs (bug 28937)
The implementation in _dl_close_worker requires that the first
element of l_initfini is always this very map (“We are always the
zeroth entry, and since we don't include ourselves in the
dependency analysis start at 1.”). Rather than fixing that
assumption, this commit adds an implementation of the force_first
argument to the new dependency sorting algorithm. This also means
that the directly dlopen'ed shared object is always initialized last,
which is the least surprising behavior in the presence of cycles.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
index 7a586749adc3fa7d..6f5c17b47b98fbc7 100644
--- a/elf/dl-sort-maps.c
+++ b/elf/dl-sort-maps.c
@@ -182,8 +182,9 @@ dfs_traversal (struct link_map ***rpo, struct link_map *map,
static void
_dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
- bool force_first __attribute__ ((unused)), bool for_fini)
+ bool force_first, bool for_fini)
{
+ struct link_map *first_map = maps[0];
for (int i = nmaps - 1; i >= 0; i--)
maps[i]->l_visited = 0;
@@ -208,14 +209,6 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
Adjusting the order so that maps[0] is last traversed naturally avoids
this problem.
- Further, the old "optimization" of skipping the main object at maps[0]
- from the call-site (i.e. _dl_sort_maps(maps+1,nmaps-1)) is in general
- no longer valid, since traversing along object dependency-links
- may "find" the main object even when it is not included in the initial
- order (e.g. a dlopen()'ed shared object can have circular dependencies
- linked back to itself). In such a case, traversing N-1 objects will
- create a N-object result, and raise problems.
-
To summarize, just passing in the full list, and iterating from back
to front makes things much more straightforward. */
@@ -274,6 +267,27 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
}
memcpy (maps, rpo, sizeof (struct link_map *) * nmaps);
+
+ /* Skipping the first object at maps[0] is not valid in general,
+ since traversing along object dependency-links may "find" that
+ first object even when it is not included in the initial order
+ (e.g., a dlopen'ed shared object can have circular dependencies
+ linked back to itself). In such a case, traversing N-1 objects
+ will create a N-object result, and raise problems. Instead,
+ force the object back into first place after sorting. This naive
+ approach may introduce further dependency ordering violations
+ compared to rotating the cycle until the first map is again in
+ the first position, but as there is a cycle, at least one
+ violation is already present. */
+ if (force_first && maps[0] != first_map)
+ {
+ int i;
+ for (i = 0; maps[i] != first_map; ++i)
+ ;
+ assert (i < nmaps);
+ memmove (&maps[1], maps, i * sizeof (maps[0]));
+ maps[0] = first_map;
+ }
}
void
diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def
index 5f7f18ef270bc12d..4bf9052db16fb352 100644
--- a/elf/dso-sort-tests-1.def
+++ b/elf/dso-sort-tests-1.def
@@ -64,3 +64,10 @@ output: b>a>{}<a<b
tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};a->b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c
output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];}
output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<g<f<a<b<c<d<e];}
+
+# Test that even in the presence of dependency loops involving dlopen'ed
+# object, that object is initialized last (and not unloaded prematurely).
+# Final destructor order is indeterminate due to the cycle.
+tst-bz28937: {+a;+b;-b;+c;%c};a->a1;a->a2;a2->a;b->b1;c->a1;c=>a1
+output(glibc.rtld.dynamic_sort=1): {+a[a2>a1>a>];+b[b1>b>];-b[<b<b1];+c[c>];%c(a1());}<a<a2<c<a1
+output(glibc.rtld.dynamic_sort=2): {+a[a2>a1>a>];+b[b1>b>];-b[<b<b1];+c[c>];%c(a1());}<a2<a<c<a1

View file

@ -1,35 +0,0 @@
Downstream-specific patch to link DSO sorting tests with -ldl
if needed. Upstream does not need this because <dlfcn.h> interfaces
are part of libc.
diff --git a/scripts/dso-ordering-test.py b/scripts/dso-ordering-test.py
index 43b5ec4d920ad6a3..ae85e0f4a6ae5b3e 100644
--- a/scripts/dso-ordering-test.py
+++ b/scripts/dso-ordering-test.py
@@ -657,6 +657,8 @@ def process_testcase(t):
% (test_name + "-" + dep + ".FAKE.so",
("$(objpfx)" + test_subdir + "/"
+ test_name + "-" + dep + ".so")))
+ makefile.write(
+ "LDLIBS-%s += -Wl,--as-needed -ldl -Wl,--no-as-needed\n" % dso)
rule = ("$(objpfx)" + test_subdir + "/"
+ test_name + "-" + dep + ".FAKE.os: "
"$(objpfx)" + test_srcdir
@@ -685,6 +687,8 @@ def process_testcase(t):
+ test_descr.soname_map[o] + ".so")
ldflags += (" -Wl,-soname=" + soname)
makefile.write("LDFLAGS-%s = %s\n" % (dso, ldflags))
+ makefile.write(
+ "LDLIBS-%s += -Wl,--as-needed -ldl -Wl,--no-as-needed\n" % dso)
if o in test_descr.callrefs:
makefile.write("%s-no-z-defs = yes\n" % (dso))
@@ -702,6 +706,8 @@ def process_testcase(t):
+ test_descr.soname_map['#'] + ".so")
ldflags += (" -Wl,-soname=" + soname)
makefile.write("LDFLAGS-%s = %s\n" % (test_name, ldflags))
+ makefile.write(
+ "LDLIBS-%s += -Wl,--as-needed -ldl -Wl,--no-as-needed\n" % test_name)
rule = ("$(objpfx)" + test_subdir + "/" + test_name + ".o: "
"$(objpfx)" + test_srcdir + test_name + ".c\n"
"\t$(compile.c) $(OUTPUT_OPTION)\n")

View file

@ -1,189 +0,0 @@
commit b4bbedb1e75737a80bcc3d53d6eef1fbe0b5f4d5
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Sat Nov 6 14:13:27 2021 -0700
dso-ordering-test.py: Put all sources in one directory [BZ #28550]
Put all sources for DSO sorting tests in the dso-sort-tests-src directory
and compile test relocatable objects with
$(objpfx)tst-dso-ordering1-dir/tst-dso-ordering1-a.os: $(objpfx)dso-sort-tests-src/tst-dso-ordering1-a.c
$(compile.c) $(OUTPUT_OPTION)
to avoid random $< values from $(before-compile) when compiling test
relocatable objects with
$(objpfx)%$o: $(objpfx)%.c $(before-compile); $$(compile-command.c)
compile-command.c = $(compile.c) $(OUTPUT_OPTION) $(compile-mkdep-flags)
compile.c = $(CC) $< -c $(CFLAGS) $(CPPFLAGS)
for 3 "make -j 28" parallel builds on a machine with 112 cores at the
same time.
This partially fixes BZ #28550.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/scripts/dso-ordering-test.py b/scripts/dso-ordering-test.py
index 944ee740527d60fd..bde0406be9da14fc 100644
--- a/scripts/dso-ordering-test.py
+++ b/scripts/dso-ordering-test.py
@@ -526,9 +526,13 @@ def process_testcase(t):
base_test_name = t.test_name
test_subdir = base_test_name + "-dir"
testpfx = objpfx + test_subdir + "/"
+ test_srcdir = "dso-sort-tests-src/"
+ testpfx_src = objpfx + test_srcdir
if not os.path.exists(testpfx):
os.mkdir(testpfx)
+ if not os.path.exists(testpfx_src):
+ os.mkdir(testpfx_src)
def find_objs_not_depended_on(t):
objs_not_depended_on = []
@@ -595,6 +599,11 @@ def process_testcase(t):
# Print out needed Makefile fragments for use in glibc/elf/Makefile.
module_names = ""
for o in test_descr.objs:
+ rule = ("$(objpfx)" + test_subdir + "/" + test_name
+ + "-" + o + ".os: $(objpfx)" + test_srcdir
+ + test_name + "-" + o + ".c\n"
+ "\t$(compile.c) $(OUTPUT_OPTION)\n")
+ makefile.write (rule)
module_names += " " + test_subdir + "/" + test_name + "-" + o
makefile.write("modules-names +=%s\n" % (module_names))
@@ -637,7 +646,7 @@ def process_testcase(t):
# object. This only needs to be done at most once for
# an object name.
if not dep in fake_created:
- f = open(testpfx + test_name + "-" + dep
+ f = open(testpfx_src + test_name + "-" + dep
+ ".FAKE.c", "w")
f.write(" \n")
f.close()
@@ -648,6 +657,12 @@ def process_testcase(t):
% (test_name + "-" + dep + ".FAKE.so",
("$(objpfx)" + test_subdir + "/"
+ test_name + "-" + dep + ".so")))
+ rule = ("$(objpfx)" + test_subdir + "/"
+ + test_name + "-" + dep + ".FAKE.os: "
+ "$(objpfx)" + test_srcdir
+ + test_name + "-" + dep + ".FAKE.c\n"
+ "\t$(compile.c) $(OUTPUT_OPTION)\n")
+ makefile.write (rule)
makefile.write \
("modules-names += %s\n"
% (test_subdir + "/"
@@ -687,6 +702,10 @@ def process_testcase(t):
+ test_descr.soname_map['#'] + ".so")
ldflags += (" -Wl,-soname=" + soname)
makefile.write("LDFLAGS-%s = %s\n" % (test_name, ldflags))
+ rule = ("$(objpfx)" + test_subdir + "/" + test_name + ".o: "
+ "$(objpfx)" + test_srcdir + test_name + ".c\n"
+ "\t$(compile.c) $(OUTPUT_OPTION)\n")
+ makefile.write (rule)
not_depended_objs = find_objs_not_depended_on(test_descr)
if not_depended_objs:
@@ -745,7 +764,7 @@ def process_testcase(t):
" something_failed=true\n"
"else\n"
" diff -wu ${common_objpfx}elf/%s/%s%s.output \\\n"
- " ${common_objpfx}elf/%s/%s%s.exp\n"
+ " ${common_objpfx}elf/%s%s%s.exp\n"
" if [ $? -ne 0 ]; then\n"
" echo '%sFAIL: %s%s expected output comparison'\n"
" something_failed=true\n"
@@ -753,14 +772,14 @@ def process_testcase(t):
"fi\n"
% (("X" if xfail else ""), test_name, tunable_descr,
test_subdir, test_name, tunable_sfx,
- test_subdir, base_test_name, exp_tunable_sfx,
+ test_srcdir, base_test_name, exp_tunable_sfx,
("X" if xfail else ""), test_name, tunable_descr))
# Generate C files according to dependency and calling relations from
# description string.
for obj in test_descr.objs:
src_name = test_name + "-" + obj + ".c"
- f = open(testpfx + src_name, "w")
+ f = open(testpfx_src + src_name, "w")
if obj in test_descr.callrefs:
called_objs = test_descr.callrefs[obj]
for callee in called_objs:
@@ -804,7 +823,7 @@ def process_testcase(t):
f.close()
# Open C file for writing main program
- f = open(testpfx + test_name + ".c", "w")
+ f = open(testpfx_src + test_name + ".c", "w")
# if there are some operations in main(), it means we need -ldl
f.write("#include <stdio.h>\n")
@@ -885,7 +904,7 @@ def process_testcase(t):
for obj in test_descr.objs:
src_name = test_name + "-" + obj + ".c"
obj_name = test_name + "-" + obj + ".os"
- run_cmd([build_gcc, "-c", "-fPIC", testpfx + src_name,
+ run_cmd([build_gcc, "-c", "-fPIC", testpfx_src + src_name,
"-o", testpfx + obj_name])
obj_processed = {}
@@ -903,10 +922,12 @@ def process_testcase(t):
deps.append(dep + ".FAKE")
if not dep in fake_created:
base_name = testpfx + test_name + "-" + dep
+ src_base_name = (testpfx_src + test_name
+ + "-" + dep)
cmd = [build_gcc, "-Wl,--no-as-needed",
("-Wl,-soname=" + base_name + ".so"),
"-shared", base_name + ".FAKE.c",
- "-o", base_name + ".FAKE.so"]
+ "-o", src_base_name + ".FAKE.so"]
run_cmd(cmd)
fake_created[dep] = True
dso_deps = map(lambda d: testpfx + test_name + "-" + d + ".so",
@@ -932,7 +953,7 @@ def process_testcase(t):
main_deps = map(lambda d: testpfx + test_name + "-" + d + ".so",
deps)
cmd = [build_gcc, "-Wl,--no-as-needed", "-o", testpfx + test_name,
- testpfx + test_name + ".c", "-L%s" % (os.getcwd()),
+ testpfx_src + test_name + ".c", "-L%s" % (os.getcwd()),
"-Wl,-rpath-link=%s" % (os.getcwd())]
if '#' in test_descr.soname_map:
soname = ("-Wl,-soname=" + testpfx + test_name + "-"
@@ -987,14 +1008,14 @@ def process_testcase(t):
sfx = ""
if r[0] != "":
sfx = "-" + r[0].replace("=","_")
- f = open(testpfx + t.test_name + sfx + ".exp", "w")
+ f = open(testpfx_src + t.test_name + sfx + ".exp", "w")
(output, xfail) = r[1]
f.write('%s' % output)
f.close()
# Create header part of top-level testcase shell script, to wrap execution
# and output comparison together.
- t.sh = open(testpfx + t.test_name + ".sh", "w")
+ t.sh = open(testpfx_src + t.test_name + ".sh", "w")
t.sh.write("#!/bin/sh\n")
t.sh.write("# Test driver for %s, generated by "
"dso-ordering-test.py\n" % (t.test_name))
@@ -1022,12 +1043,12 @@ def process_testcase(t):
sfx = ""
if r[0] != "":
sfx = "-" + r[0].replace("=","_")
- expected_output_files += " $(objpfx)%s/%s%s.exp" % (test_subdir,
+ expected_output_files += " $(objpfx)%s%s%s.exp" % (test_srcdir,
t.test_name, sfx)
makefile.write \
- ("$(objpfx)%s.out: $(objpfx)%s/%s.sh%s "
+ ("$(objpfx)%s.out: $(objpfx)%s%s.sh%s "
"$(common-objpfx)support/test-run-command\n"
- % (t.test_name, test_subdir, t.test_name,
+ % (t.test_name, test_srcdir, t.test_name,
expected_output_files))
makefile.write("\t$(SHELL) $< $(common-objpfx) '$(test-wrapper-env)' "
"'$(run-program-env)' > $@; $(evaluate-test)\n")

View file

@ -1,589 +0,0 @@
commit 15a0c5730d1d5aeb95f50c9ec7470640084feae8
Author: Chung-Lin Tang <cltang@codesourcery.com>
Date: Thu Oct 21 21:41:22 2021 +0800
elf: Fix slow DSO sorting behavior in dynamic loader (BZ #17645)
This second patch contains the actual implementation of a new sorting algorithm
for shared objects in the dynamic loader, which solves the slow behavior that
the current "old" algorithm falls into when the DSO set contains circular
dependencies.
The new algorithm implemented here is simply depth-first search (DFS) to obtain
the Reverse-Post Order (RPO) sequence, a topological sort. A new l_visited:1
bitfield is added to struct link_map to more elegantly facilitate such a search.
The DFS algorithm is applied to the input maps[nmap-1] backwards towards
maps[0]. This has the effect of a more "shallow" recursion depth in general
since the input is in BFS. Also, when combined with the natural order of
processing l_initfini[] at each node, this creates a resulting output sorting
closer to the intuitive "left-to-right" order in most cases.
Another notable implementation adjustment related to this _dl_sort_maps change
is the removing of two char arrays 'used' and 'done' in _dl_close_worker to
represent two per-map attributes. This has been changed to simply use two new
bit-fields l_map_used:1, l_map_done:1 added to struct link_map. This also allows
discarding the clunky 'used' array sorting that _dl_sort_maps had to sometimes
do along the way.
Tunable support for switching between different sorting algorithms at runtime is
also added. A new tunable 'glibc.rtld.dynamic_sort' with current valid values 1
(old algorithm) and 2 (new DFS algorithm) has been added. At time of commit
of this patch, the default setting is 1 (old algorithm).
Signed-off-by: Chung-Lin Tang <cltang@codesourcery.com>
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Conflicts:
elf/dl-tunables.list
(No mem.tagging tunable downstream.)
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 74ca9a85dd309780..22225efb3226c3e1 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -167,8 +167,6 @@ _dl_close_worker (struct link_map *map, bool force)
bool any_tls = false;
const unsigned int nloaded = ns->_ns_nloaded;
- char used[nloaded];
- char done[nloaded];
struct link_map *maps[nloaded];
/* Run over the list and assign indexes to the link maps and enter
@@ -176,24 +174,21 @@ _dl_close_worker (struct link_map *map, bool force)
int idx = 0;
for (struct link_map *l = ns->_ns_loaded; l != NULL; l = l->l_next)
{
+ l->l_map_used = 0;
+ l->l_map_done = 0;
l->l_idx = idx;
maps[idx] = l;
++idx;
-
}
assert (idx == nloaded);
- /* Prepare the bitmaps. */
- memset (used, '\0', sizeof (used));
- memset (done, '\0', sizeof (done));
-
/* Keep track of the lowest index link map we have covered already. */
int done_index = -1;
while (++done_index < nloaded)
{
struct link_map *l = maps[done_index];
- if (done[done_index])
+ if (l->l_map_done)
/* Already handled. */
continue;
@@ -204,12 +199,12 @@ _dl_close_worker (struct link_map *map, bool force)
/* 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
- && !used[done_index])
+ && !l->l_map_used)
continue;
/* We need this object and we handle it now. */
- done[done_index] = 1;
- used[done_index] = 1;
+ l->l_map_used = 1;
+ l->l_map_done = 1;
/* Signal the object is still needed. */
l->l_idx = IDX_STILL_USED;
@@ -225,9 +220,9 @@ _dl_close_worker (struct link_map *map, bool force)
{
assert ((*lp)->l_idx >= 0 && (*lp)->l_idx < nloaded);
- if (!used[(*lp)->l_idx])
+ if (!(*lp)->l_map_used)
{
- used[(*lp)->l_idx] = 1;
+ (*lp)->l_map_used = 1;
/* If we marked a new object as used, and we've
already processed it, then we need to go back
and process again from that point forward to
@@ -250,9 +245,9 @@ _dl_close_worker (struct link_map *map, bool force)
{
assert (jmap->l_idx >= 0 && jmap->l_idx < nloaded);
- if (!used[jmap->l_idx])
+ if (!jmap->l_map_used)
{
- used[jmap->l_idx] = 1;
+ jmap->l_map_used = 1;
if (jmap->l_idx - 1 < done_index)
done_index = jmap->l_idx - 1;
}
@@ -262,8 +257,7 @@ _dl_close_worker (struct link_map *map, bool force)
/* Sort the entries. We can skip looking for the binary itself which is
at the front of the search list for the main namespace. */
- _dl_sort_maps (maps + (nsid == LM_ID_BASE), nloaded - (nsid == LM_ID_BASE),
- used + (nsid == LM_ID_BASE), true);
+ _dl_sort_maps (maps, nloaded, (nsid == LM_ID_BASE), true);
/* Call all termination functions at once. */
bool unload_any = false;
@@ -277,7 +271,7 @@ _dl_close_worker (struct link_map *map, bool force)
/* All elements must be in the same namespace. */
assert (imap->l_ns == nsid);
- if (!used[i])
+ if (!imap->l_map_used)
{
assert (imap->l_type == lt_loaded && !imap->l_nodelete_active);
@@ -315,7 +309,7 @@ _dl_close_worker (struct link_map *map, bool force)
if (i < first_loaded)
first_loaded = i;
}
- /* Else used[i]. */
+ /* Else imap->l_map_used. */
else if (imap->l_type == lt_loaded)
{
struct r_scope_elem *new_list = NULL;
@@ -524,7 +518,7 @@ _dl_close_worker (struct link_map *map, bool force)
for (unsigned int i = first_loaded; i < nloaded; ++i)
{
struct link_map *imap = maps[i];
- if (!used[i])
+ if (!imap->l_map_used)
{
assert (imap->l_type == lt_loaded);
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 007069f670eced95..9365d54c8e03e5f4 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -612,10 +612,9 @@ Filters not supported with LD_TRACE_PRELINKING"));
/* If libc.so.6 is the main map, it participates in the sort, so
that the relocation order is correct regarding libc.so.6. */
- if (l_initfini[0] == GL (dl_ns)[l_initfini[0]->l_ns].libc_map)
- _dl_sort_maps (l_initfini, nlist, NULL, false);
- else
- _dl_sort_maps (&l_initfini[1], nlist - 1, NULL, false);
+ _dl_sort_maps (l_initfini, nlist,
+ (l_initfini[0] != GL (dl_ns)[l_initfini[0]->l_ns].libc_map),
+ false);
/* Terminate the list of dependencies. */
l_initfini[nlist] = NULL;
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index eea9d8aad736a99e..e14259a3c8806e0d 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -95,8 +95,7 @@ _dl_fini (void)
/* Now we have to do the sorting. We can skip looking for the
binary itself which is at the front of the search list for
the main namespace. */
- _dl_sort_maps (maps + (ns == LM_ID_BASE), nmaps - (ns == LM_ID_BASE),
- NULL, true);
+ _dl_sort_maps (maps, nmaps, (ns == LM_ID_BASE), true);
/* We do not rely on the linked list of loaded object anymore
from this point on. We have our own list here (maps). The
diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
index b2a01ede627be1e9..398a08f28c4d9ff1 100644
--- a/elf/dl-sort-maps.c
+++ b/elf/dl-sort-maps.c
@@ -16,16 +16,24 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <assert.h>
#include <ldsodefs.h>
+#include <elf/dl-tunables.h>
+/* Note: this is the older, "original" sorting algorithm, being used as
+ default up to 2.35.
-/* Sort array MAPS according to dependencies of the contained objects.
- Array USED, if non-NULL, is permutated along MAPS. If FOR_FINI this is
- called for finishing an object. */
-void
-_dl_sort_maps (struct link_map **maps, unsigned int nmaps, char *used,
- bool for_fini)
+ Sort array MAPS according to dependencies of the contained objects.
+ If FOR_FINI is true, this is called for finishing an object. */
+static void
+_dl_sort_maps_original (struct link_map **maps, unsigned int nmaps,
+ unsigned int skip, bool for_fini)
{
+ /* Allows caller to do the common optimization of skipping the first map,
+ usually the main binary. */
+ maps += skip;
+ nmaps -= skip;
+
/* A list of one element need not be sorted. */
if (nmaps <= 1)
return;
@@ -66,14 +74,6 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps, char *used,
(k - i) * sizeof (maps[0]));
maps[k] = thisp;
- if (used != NULL)
- {
- char here_used = used[i];
- memmove (&used[i], &used[i + 1],
- (k - i) * sizeof (used[0]));
- used[k] = here_used;
- }
-
if (seen[i + 1] > nmaps - i)
{
++i;
@@ -120,3 +120,183 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps, char *used,
next:;
}
}
+
+#if !HAVE_TUNABLES
+/* In this case, just default to the original algorithm. */
+strong_alias (_dl_sort_maps_original, _dl_sort_maps);
+#else
+
+/* We use a recursive function due to its better clarity and ease of
+ implementation, as well as faster execution speed. We already use
+ alloca() for list allocation during the breadth-first search of
+ dependencies in _dl_map_object_deps(), and this should be on the
+ same order of worst-case stack usage.
+
+ Note: the '*rpo' parameter is supposed to point to one past the
+ last element of the array where we save the sort results, and is
+ decremented before storing the current map at each level. */
+
+static void
+dfs_traversal (struct link_map ***rpo, struct link_map *map,
+ bool *do_reldeps)
+{
+ if (map->l_visited)
+ return;
+
+ map->l_visited = 1;
+
+ if (map->l_initfini)
+ {
+ for (int i = 0; map->l_initfini[i] != NULL; i++)
+ {
+ struct link_map *dep = map->l_initfini[i];
+ if (dep->l_visited == 0
+ && dep->l_main_map == 0)
+ dfs_traversal (rpo, dep, do_reldeps);
+ }
+ }
+
+ if (__glibc_unlikely (do_reldeps != NULL && map->l_reldeps != NULL))
+ {
+ /* Indicate that we encountered relocation dependencies during
+ traversal. */
+ *do_reldeps = true;
+
+ for (int m = map->l_reldeps->act - 1; m >= 0; m--)
+ {
+ struct link_map *dep = map->l_reldeps->list[m];
+ if (dep->l_visited == 0
+ && dep->l_main_map == 0)
+ dfs_traversal (rpo, dep, do_reldeps);
+ }
+ }
+
+ *rpo -= 1;
+ **rpo = map;
+}
+
+/* Topologically sort array MAPS according to dependencies of the contained
+ objects. */
+
+static void
+_dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
+ unsigned int skip __attribute__ ((unused)), bool for_fini)
+{
+ for (int i = nmaps - 1; i >= 0; i--)
+ maps[i]->l_visited = 0;
+
+ /* We apply DFS traversal for each of maps[i] until the whole total order
+ is found and we're at the start of the Reverse-Postorder (RPO) sequence,
+ which is a topological sort.
+
+ We go from maps[nmaps - 1] backwards towards maps[0] at this level.
+ Due to the breadth-first search (BFS) ordering we receive, going
+ backwards usually gives a more shallow depth-first recursion depth,
+ adding more stack usage safety. Also, combined with the natural
+ processing order of l_initfini[] at each node during DFS, this maintains
+ an ordering closer to the original link ordering in the sorting results
+ under most simpler cases.
+
+ Another reason we order the top level backwards, it that maps[0] is
+ usually exactly the main object of which we're in the midst of
+ _dl_map_object_deps() processing, and maps[0]->l_initfini[] is still
+ blank. If we start the traversal from maps[0], since having no
+ dependencies yet filled in, maps[0] will always be immediately
+ incorrectly placed at the last place in the order (first in reverse).
+ Adjusting the order so that maps[0] is last traversed naturally avoids
+ this problem.
+
+ Further, the old "optimization" of skipping the main object at maps[0]
+ from the call-site (i.e. _dl_sort_maps(maps+1,nmaps-1)) is in general
+ no longer valid, since traversing along object dependency-links
+ may "find" the main object even when it is not included in the initial
+ order (e.g. a dlopen()'ed shared object can have circular dependencies
+ linked back to itself). In such a case, traversing N-1 objects will
+ create a N-object result, and raise problems.
+
+ To summarize, just passing in the full list, and iterating from back
+ to front makes things much more straightforward. */
+
+ /* Array to hold RPO sorting results, before we copy back to maps[]. */
+ struct link_map *rpo[nmaps];
+
+ /* The 'head' position during each DFS iteration. Note that we start at
+ one past the last element due to first-decrement-then-store (see the
+ bottom of above dfs_traversal() routine). */
+ struct link_map **rpo_head = &rpo[nmaps];
+
+ bool do_reldeps = false;
+ bool *do_reldeps_ref = (for_fini ? &do_reldeps : NULL);
+
+ for (int i = nmaps - 1; i >= 0; i--)
+ {
+ dfs_traversal (&rpo_head, maps[i], do_reldeps_ref);
+
+ /* We can break early if all objects are already placed. */
+ if (rpo_head == rpo)
+ goto end;
+ }
+ assert (rpo_head == rpo);
+
+ end:
+ /* Here we may do a second pass of sorting, using only l_initfini[]
+ static dependency links. This is avoided if !FOR_FINI or if we didn't
+ find any reldeps in the first DFS traversal.
+
+ The reason we do this is: while it is unspecified how circular
+ dependencies should be handled, the presumed reasonable behavior is to
+ have destructors to respect static dependency links as much as possible,
+ overriding reldeps if needed. And the first sorting pass, which takes
+ l_initfini/l_reldeps links equally, may not preserve this priority.
+
+ Hence we do a 2nd sorting pass, taking only DT_NEEDED links into account
+ (see how the do_reldeps argument to dfs_traversal() is NULL below). */
+ if (do_reldeps)
+ {
+ for (int i = nmaps - 1; i >= 0; i--)
+ rpo[i]->l_visited = 0;
+
+ struct link_map **maps_head = &maps[nmaps];
+ for (int i = nmaps - 1; i >= 0; i--)
+ {
+ dfs_traversal (&maps_head, rpo[i], NULL);
+
+ /* We can break early if all objects are already placed.
+ The below memcpy is not needed in the do_reldeps case here,
+ since we wrote back to maps[] during DFS traversal. */
+ if (maps_head == maps)
+ return;
+ }
+ assert (maps_head == maps);
+ return;
+ }
+
+ memcpy (maps, rpo, sizeof (struct link_map *) * nmaps);
+}
+
+void
+_dl_sort_maps_init (void)
+{
+ int32_t algorithm = TUNABLE_GET (glibc, rtld, dynamic_sort, int32_t, NULL);
+ GLRO(dl_dso_sort_algo) = algorithm == 1 ? dso_sort_algorithm_original
+ : dso_sort_algorithm_dfs;
+}
+
+void
+_dl_sort_maps (struct link_map **maps, unsigned int nmaps,
+ unsigned int skip, bool for_fini)
+{
+ /* It can be tempting to use a static function pointer to store and call
+ the current selected sorting algorithm routine, but experimentation
+ shows that current processors still do not handle indirect branches
+ that efficiently, plus a static function pointer will involve
+ PTR_MANGLE/DEMANGLE, further impairing performance of small, common
+ input cases. A simple if-case with direct function calls appears to
+ be the fastest. */
+ if (__glibc_likely (GLRO(dl_dso_sort_algo) == dso_sort_algorithm_original))
+ _dl_sort_maps_original (maps, nmaps, skip, for_fini);
+ else
+ _dl_sort_maps_dfs (maps, nmaps, skip, for_fini);
+}
+
+#endif /* HAVE_TUNABLES. */
diff --git a/elf/dl-support.c b/elf/dl-support.c
index e9943e889ef447ad..ae03aec9764e29d3 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -155,6 +155,8 @@ size_t _dl_phnum;
uint64_t _dl_hwcap __attribute__ ((nocommon));
uint64_t _dl_hwcap2 __attribute__ ((nocommon));
+enum dso_sort_algorithm _dl_dso_sort_algo;
+
/* The value of the FPU control word the kernel will preset in hardware. */
fpu_control_t _dl_fpu_control = _FPU_DEFAULT;
diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
index 998c5d52bcab8193..4e8a986541fc4c09 100644
--- a/elf/dl-sysdep.c
+++ b/elf/dl-sysdep.c
@@ -223,6 +223,9 @@ _dl_sysdep_start (void **start_argptr,
__tunables_init (_environ);
+ /* Initialize DSO sorting algorithm after tunables. */
+ _dl_sort_maps_init ();
+
#ifdef DL_SYSDEP_INIT
DL_SYSDEP_INIT;
#endif
diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
index 6408a8e5ae92d2c6..54ef2a921310b229 100644
--- a/elf/dl-tunables.list
+++ b/elf/dl-tunables.list
@@ -140,4 +140,13 @@ glibc {
default: 512
}
}
+
+ rtld {
+ dynamic_sort {
+ type: INT_32
+ minval: 1
+ maxval: 2
+ default: 1
+ }
+ }
}
diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def
index 873ddf55d91155c6..5f7f18ef270bc12d 100644
--- a/elf/dso-sort-tests-1.def
+++ b/elf/dso-sort-tests-1.def
@@ -62,5 +62,5 @@ output: b>a>{}<a<b
# The below expected outputs are what the two algorithms currently produce
# respectively, for regression testing purposes.
tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};a->b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c
-xfail_output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];}
+output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];}
output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<g<f<a<b<c<d<e];}
diff --git a/elf/rtld.c b/elf/rtld.c
index b47e84ca2fb6f03c..cd2cc4024a3581c2 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1453,6 +1453,9 @@ dl_main (const ElfW(Phdr) *phdr,
main_map->l_name = (char *) "";
*user_entry = main_map->l_entry;
+ /* Set bit indicating this is the main program map. */
+ main_map->l_main_map = 1;
+
#ifdef HAVE_AUX_VECTOR
/* Adjust the on-stack auxiliary vector so that it looks like the
binary was executed directly. */
diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp
index 4f3f7ee4e30a2b42..118afc271057afd4 100644
--- a/elf/tst-rtld-list-tunables.exp
+++ b/elf/tst-rtld-list-tunables.exp
@@ -10,5 +10,6 @@ glibc.malloc.tcache_max: 0x0 (min: 0x0, max: 0x[f]+)
glibc.malloc.tcache_unsorted_limit: 0x0 (min: 0x0, max: 0x[f]+)
glibc.malloc.top_pad: 0x0 (min: 0x0, max: 0x[f]+)
glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0x[f]+)
+glibc.rtld.dynamic_sort: 1 (min: 1, max: 2)
glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10)
glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0x[f]+)
diff --git a/include/link.h b/include/link.h
index dd491989beb41353..041ff5f753a9ee11 100644
--- a/include/link.h
+++ b/include/link.h
@@ -181,6 +181,11 @@ struct link_map
unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */
unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */
unsigned int l_reserved:2; /* Reserved for internal use. */
+ unsigned int l_main_map:1; /* Nonzero for the map of the main program. */
+ unsigned int l_visited:1; /* Used internally for map dependency
+ graph traversal. */
+ unsigned int l_map_used:1; /* These two bits are used during traversal */
+ unsigned int l_map_done:1; /* of maps in _dl_close_worker. */
unsigned int l_phdr_allocated:1; /* Nonzero if the data structure pointed
to by `l_phdr' is allocated. */
unsigned int l_soname_added:1; /* Nonzero if the SONAME is for sure in
diff --git a/manual/tunables.texi b/manual/tunables.texi
index 43272cf885d1e3e6..c3f96cdc85208926 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -303,6 +303,17 @@ changed once allocated at process startup. The default allocation of
optional static TLS is 512 bytes and is allocated in every thread.
@end deftp
+@deftp Tunable glibc.rtld.dynamic_sort
+Sets the algorithm to use for DSO sorting, valid values are @samp{1} and
+@samp{2}. For value of @samp{1}, an older O(n^3) algorithm is used, which is
+long time tested, but may have performance issues when dependencies between
+shared objects contain cycles due to circular dependencies. When set to the
+value of @samp{2}, a different algorithm is used, which implements a
+topological sort through depth-first search, and does not exhibit the
+performance issues of @samp{1}.
+
+The default value of this tunable is @samp{1}.
+@end deftp
@node Elision Tunables
@section Elision Tunables
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 5e56550a4d556fa7..9f09a4a280396659 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -240,6 +240,13 @@ enum allowmask
};
+/* DSO sort algorithm to use (check dl-sort-maps.c). */
+enum dso_sort_algorithm
+ {
+ dso_sort_algorithm_original,
+ dso_sort_algorithm_dfs
+ };
+
struct audit_ifaces
{
void (*activity) (uintptr_t *, unsigned int);
@@ -633,6 +640,8 @@ struct rtld_global_ro
platforms. */
EXTERN uint64_t _dl_hwcap2;
+ EXTERN enum dso_sort_algorithm _dl_dso_sort_algo;
+
#ifdef SHARED
/* We add a function table to _rtld_global which is then used to
call the function instead of going through the PLT. The result
@@ -1049,7 +1058,7 @@ extern void _dl_fini (void) attribute_hidden;
/* Sort array MAPS according to dependencies of the contained objects. */
extern void _dl_sort_maps (struct link_map **maps, unsigned int nmaps,
- char *used, bool for_fini) attribute_hidden;
+ unsigned int skip, bool for_fini) attribute_hidden;
/* The dynamic linker calls this function before and having changing
any shared object mappings. The `r_state' member of `struct r_debug'
@@ -1167,6 +1176,9 @@ extern struct link_map * _dl_get_dl_main_map (void)
# endif
#endif
+/* Initialize the DSO sort algorithm to use. */
+extern void _dl_sort_maps_init (void) attribute_hidden;
+
/* Initialization of libpthread for statically linked applications.
If libpthread is not linked in, this is an empty function. */
void __pthread_initialize_minimal (void) weak_function;

View file

@ -1,25 +0,0 @@
commit d3bf2f5927d51258a51ac7fde04f4805f8ee294a
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed Nov 3 09:19:30 2021 -0300
elf: Do not run DSO sorting if tunables is not enabled
Since the argorithm selection requires tunables.
Checked on x86_64-linux-gnu with --enable-tunables=no.
diff --git a/elf/Makefile b/elf/Makefile
index e92f62f279566684..3b5e1f59e6696a2b 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -998,8 +998,10 @@ include $(objpfx)$(1).generated-makefile
endef
# Generate from each testcase description file
+ifeq (yes,$(have-tunables))
$(eval $(call include_dsosort_tests,dso-sort-tests-1.def))
$(eval $(call include_dsosort_tests,dso-sort-tests-2.def))
+endif
check-abi: $(objpfx)check-abi-ld.out
tests-special += $(objpfx)check-abi-ld.out

View file

@ -1,45 +0,0 @@
commit 1f67d8286b5da9266a138198ef1f15c27cbb0010
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Mon Nov 15 16:28:39 2021 -0800
elf: Use a temporary file to generate Makefile fragments [BZ #28550]
1. Use a temporary file to generate Makefile fragments for DSO sorting
tests and use -include on them.
2. Add Makefile fragments to postclean-generated so that a "make clean"
removes the autogenerated fragments and a subsequent "make" regenerates
them.
This partially fixes BZ #28550.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/Makefile b/elf/Makefile
index 3b5e1f59e6696a2b..22a8060f7d3bb1a1 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -986,6 +986,7 @@ tests-special += \
# tests-special
endif
+ifndef avoid-generated
# DSO sorting tests:
# The dso-ordering-test.py script generates testcase source files in $(objpfx),
# creating a $(objpfx)<testcase-name>-dir for each testcase, and creates a
@@ -993,9 +994,14 @@ endif
define include_dsosort_tests
$(objpfx)$(1).generated-makefile: $(1)
$(PYTHON) $(..)scripts/dso-ordering-test.py \
- --description-file $$< --objpfx $(objpfx) --output-makefile $$@
-include $(objpfx)$(1).generated-makefile
+ --description-file $$< --objpfx $(objpfx) --output-makefile $$@T
+ mv $$@T $$@
+-include $(objpfx)$(1).generated-makefile
endef
+endif
+
+postclean-generated += $(objpfx)/dso-sort-tests-2.generated-makefile \
+ $(objpfx)/dso-sort-tests-2.generated-makefile
# Generate from each testcase description file
ifeq (yes,$(have-tunables))

View file

@ -1,49 +0,0 @@
commit 0884724a95b60452ad483dbe086d237d02ba624d
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Dec 14 12:37:44 2021 +0100
elf: Use new dependency sorting algorithm by default
The default has to change eventually, and there are no known failures
that require a delay.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
index 54ef2a921310b229..f11ca5b3e8b09b43 100644
--- a/elf/dl-tunables.list
+++ b/elf/dl-tunables.list
@@ -146,7 +146,7 @@ glibc {
type: INT_32
minval: 1
maxval: 2
- default: 1
+ default: 2
}
}
}
diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp
index 118afc271057afd4..478ee8ab091685eb 100644
--- a/elf/tst-rtld-list-tunables.exp
+++ b/elf/tst-rtld-list-tunables.exp
@@ -10,6 +10,6 @@ glibc.malloc.tcache_max: 0x0 (min: 0x0, max: 0x[f]+)
glibc.malloc.tcache_unsorted_limit: 0x0 (min: 0x0, max: 0x[f]+)
glibc.malloc.top_pad: 0x0 (min: 0x0, max: 0x[f]+)
glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0x[f]+)
-glibc.rtld.dynamic_sort: 1 (min: 1, max: 2)
+glibc.rtld.dynamic_sort: 2 (min: 1, max: 2)
glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10)
glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0x[f]+)
diff --git a/manual/tunables.texi b/manual/tunables.texi
index c3f96cdc85208926..7b70e80391ee87f7 100644
--- a/manual/tunables.texi
+++ b/manual/tunables.texi
@@ -312,7 +312,7 @@ value of @samp{2}, a different algorithm is used, which implements a
topological sort through depth-first search, and does not exhibit the
performance issues of @samp{1}.
-The default value of this tunable is @samp{1}.
+The default value of this tunable is @samp{2}.
@end deftp
@node Elision Tunables

View file

@ -1,357 +0,0 @@
commit 3a0588ae48fb35384a6bd33f9b66403badfa1262
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Tue Feb 8 15:22:49 2022 -0300
elf: Fix DFS sorting algorithm for LD_TRACE_LOADED_OBJECTS with missing libraries (BZ #28868)
On _dl_map_object the underlying file is not opened in trace mode
(in other cases where the underlying file can't be opened,
_dl_map_object quits with an error). If there any missing libraries
being processed, they will not be considered on final nlist size
passed on _dl_sort_maps later in the function. And it is then used by
_dl_sort_maps_dfs on the stack allocated working maps:
222 /* Array to hold RPO sorting results, before we copy back to maps[]. */
223 struct link_map *rpo[nmaps];
224
225 /* The 'head' position during each DFS iteration. Note that we start at
226 one past the last element due to first-decrement-then-store (see the
227 bottom of above dfs_traversal() routine). */
228 struct link_map **rpo_head = &rpo[nmaps];
However while transversing the 'l_initfini' on dfs_traversal it will
still consider the l_faked maps and thus update rpo more times than the
allocated working 'rpo', overflowing the stack object.
As suggested in bugzilla, one option would be to avoid sorting the maps
for trace mode. However I think ignoring l_faked object does make
sense (there is one less constraint to call the sorting function), it
allows a slight less stack usage for trace, and it is slight simpler
solution.
The tests does trigger the stack overflow, however I tried to make
it more generic to check different scenarios or missing objects.
Checked on x86_64-linux-gnu.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Conflicts:
elf/Makefile
(differences in backported tests)
diff --git a/elf/Makefile b/elf/Makefile
index 22a8060f7d3bb1a1..634c3113227d64a6 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -584,6 +584,11 @@ modules-names = \
libmarkermod5-3 \
libmarkermod5-4 \
libmarkermod5-5 \
+ libtracemod1-1 \
+ libtracemod2-1 \
+ libtracemod3-1 \
+ libtracemod4-1 \
+ libtracemod5-1 \
ltglobmod1 \
ltglobmod2 \
neededobj1 \
@@ -983,6 +988,11 @@ tests-special += \
$(objpfx)tst-initorder2-cmp.out \
$(objpfx)tst-unused-dep-cmp.out \
$(objpfx)tst-unused-dep.out \
+ $(objpfx)tst-trace1.out \
+ $(objpfx)tst-trace2.out \
+ $(objpfx)tst-trace3.out \
+ $(objpfx)tst-trace4.out \
+ $(objpfx)tst-trace5.out \
# tests-special
endif
@@ -2619,6 +2629,51 @@ $(objpfx)tst-rtld-run-static.out: $(objpfx)/ldconfig
$(objpfx)tst-dlmopen-gethostbyname: $(libdl)
$(objpfx)tst-dlmopen-gethostbyname.out: $(objpfx)tst-dlmopen-gethostbyname-mod.so
+
+LDFLAGS-libtracemod1-1.so += -Wl,-soname,libtracemod1.so
+LDFLAGS-libtracemod2-1.so += -Wl,-soname,libtracemod2.so
+LDFLAGS-libtracemod3-1.so += -Wl,-soname,libtracemod3.so
+LDFLAGS-libtracemod4-1.so += -Wl,-soname,libtracemod4.so
+LDFLAGS-libtracemod5-1.so += -Wl,-soname,libtracemod5.so
+
+$(objpfx)libtracemod1-1.so: $(objpfx)libtracemod2-1.so \
+ $(objpfx)libtracemod3-1.so
+$(objpfx)libtracemod2-1.so: $(objpfx)libtracemod4-1.so \
+ $(objpfx)libtracemod5-1.so
+
+define libtracemod-x
+$(objpfx)libtracemod$(1)/libtracemod$(1).so: $(objpfx)libtracemod$(1)-1.so
+ $$(make-target-directory)
+ cp $$< $$@
+endef
+libtracemod-suffixes = 1 2 3 4 5
+$(foreach i,$(libtracemod-suffixes), $(eval $(call libtracemod-x,$(i))))
+
+define tst-trace-skeleton
+$(objpfx)tst-trace$(1).out: $(objpfx)libtracemod1/libtracemod1.so \
+ $(objpfx)libtracemod2/libtracemod2.so \
+ $(objpfx)libtracemod3/libtracemod3.so \
+ $(objpfx)libtracemod4/libtracemod4.so \
+ $(objpfx)libtracemod5/libtracemod5.so \
+ $(..)scripts/tst-ld-trace.py \
+ tst-trace$(1).exp
+ ${ $(PYTHON) $(..)scripts/tst-ld-trace.py \
+ "$(test-wrapper-env) $(elf-objpfx)$(rtld-installed-name) \
+ --library-path $(common-objpfx):$(strip $(2)) \
+ $(objpfx)libtracemod1/libtracemod1.so" tst-trace$(1).exp \
+ } > $$@; $$(evaluate-test)
+endef
+
+$(eval $(call tst-trace-skeleton,1,))
+$(eval $(call tst-trace-skeleton,2,\
+ $(objpfx)libtracemod2))
+$(eval $(call tst-trace-skeleton,3,\
+ $(objpfx)libtracemod2:$(objpfx)libtracemod3))
+$(eval $(call tst-trace-skeleton,4,\
+ $(objpfx)libtracemod2:$(objpfx)libtracemod3:$(objpfx)libtracemod4))
+$(eval $(call tst-trace-skeleton,5,\
+ $(objpfx)libtracemod2:$(objpfx)libtracemod3:$(objpfx)libtracemod4:$(objpfx)libtracemod5))
+
$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \
$(objpfx)tst-audit-tlsdesc-mod2.so \
$(shared-thread-library)
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 9365d54c8e03e5f4..9ff589c8562b2dd1 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -489,6 +489,8 @@ _dl_map_object_deps (struct link_map *map,
for (nlist = 0, runp = known; runp; runp = runp->next)
{
+ /* _dl_sort_maps ignores l_faked object, so it is safe to not consider
+ them for nlist. */
if (__builtin_expect (trace_mode, 0) && runp->map->l_faked)
/* This can happen when we trace the loading. */
--map->l_searchlist.r_nlist;
diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
index 398a08f28c4d9ff1..99354dc08a010dd3 100644
--- a/elf/dl-sort-maps.c
+++ b/elf/dl-sort-maps.c
@@ -140,7 +140,9 @@ static void
dfs_traversal (struct link_map ***rpo, struct link_map *map,
bool *do_reldeps)
{
- if (map->l_visited)
+ /* _dl_map_object_deps ignores l_faked objects when calculating the
+ number of maps before calling _dl_sort_maps, ignore them as well. */
+ if (map->l_visited || map->l_faked)
return;
map->l_visited = 1;
diff --git a/elf/libtracemod1-1.c b/elf/libtracemod1-1.c
new file mode 100644
index 0000000000000000..7c89c9a5a40b9668
--- /dev/null
+++ b/elf/libtracemod1-1.c
@@ -0,0 +1 @@
+/* Empty */
diff --git a/elf/libtracemod2-1.c b/elf/libtracemod2-1.c
new file mode 100644
index 0000000000000000..7c89c9a5a40b9668
--- /dev/null
+++ b/elf/libtracemod2-1.c
@@ -0,0 +1 @@
+/* Empty */
diff --git a/elf/libtracemod3-1.c b/elf/libtracemod3-1.c
new file mode 100644
index 0000000000000000..7c89c9a5a40b9668
--- /dev/null
+++ b/elf/libtracemod3-1.c
@@ -0,0 +1 @@
+/* Empty */
diff --git a/elf/libtracemod4-1.c b/elf/libtracemod4-1.c
new file mode 100644
index 0000000000000000..7c89c9a5a40b9668
--- /dev/null
+++ b/elf/libtracemod4-1.c
@@ -0,0 +1 @@
+/* Empty */
diff --git a/elf/libtracemod5-1.c b/elf/libtracemod5-1.c
new file mode 100644
index 0000000000000000..7c89c9a5a40b9668
--- /dev/null
+++ b/elf/libtracemod5-1.c
@@ -0,0 +1 @@
+/* Empty */
diff --git a/elf/tst-trace1.exp b/elf/tst-trace1.exp
new file mode 100644
index 0000000000000000..4a6f5211a68fe2c8
--- /dev/null
+++ b/elf/tst-trace1.exp
@@ -0,0 +1,4 @@
+ld 1
+libc 1
+libtracemod2.so 0
+libtracemod3.so 0
diff --git a/elf/tst-trace2.exp b/elf/tst-trace2.exp
new file mode 100644
index 0000000000000000..e13506e2eb9aeca2
--- /dev/null
+++ b/elf/tst-trace2.exp
@@ -0,0 +1,6 @@
+ld 1
+libc 1
+libtracemod2.so 1
+libtracemod3.so 0
+libtracemod4.so 0
+libtracemod5.so 0
diff --git a/elf/tst-trace3.exp b/elf/tst-trace3.exp
new file mode 100644
index 0000000000000000..e574549d12a53d72
--- /dev/null
+++ b/elf/tst-trace3.exp
@@ -0,0 +1,6 @@
+ld 1
+libc 1
+libtracemod2.so 1
+libtracemod3.so 1
+libtracemod4.so 0
+libtracemod5.so 0
diff --git a/elf/tst-trace4.exp b/elf/tst-trace4.exp
new file mode 100644
index 0000000000000000..31ca97b35bde0009
--- /dev/null
+++ b/elf/tst-trace4.exp
@@ -0,0 +1,6 @@
+ld 1
+libc 1
+libtracemod2.so 1
+libtracemod3.so 1
+libtracemod4.so 1
+libtracemod5.so 0
diff --git a/elf/tst-trace5.exp b/elf/tst-trace5.exp
new file mode 100644
index 0000000000000000..5d7d95372656396f
--- /dev/null
+++ b/elf/tst-trace5.exp
@@ -0,0 +1,6 @@
+ld 1
+libc 1
+libtracemod2.so 1
+libtracemod3.so 1
+libtracemod4.so 1
+libtracemod5.so 1
diff --git a/scripts/tst-ld-trace.py b/scripts/tst-ld-trace.py
new file mode 100755
index 0000000000000000..f5a402800377f44b
--- /dev/null
+++ b/scripts/tst-ld-trace.py
@@ -0,0 +1,108 @@
+#!/usr/bin/python3
+# Dump the output of LD_TRACE_LOADED_OBJECTS in architecture neutral format.
+# Copyright (C) 2022 Free Software Foundation, Inc.
+# 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/>.
+
+import argparse
+import os
+import subprocess
+import sys
+
+try:
+ subprocess.run
+except:
+ class _CompletedProcess:
+ def __init__(self, args, returncode, stdout=None, stderr=None):
+ self.args = args
+ self.returncode = returncode
+ self.stdout = stdout
+ self.stderr = stderr
+
+ def _run(*popenargs, input=None, timeout=None, check=False, **kwargs):
+ assert(timeout is None)
+ with subprocess.Popen(*popenargs, **kwargs) as process:
+ try:
+ stdout, stderr = process.communicate(input)
+ except:
+ process.kill()
+ process.wait()
+ raise
+ returncode = process.poll()
+ if check and returncode:
+ raise subprocess.CalledProcessError(returncode, popenargs)
+ return _CompletedProcess(popenargs, returncode, stdout, stderr)
+
+ subprocess.run = _run
+
+def is_vdso(lib):
+ return lib.startswith('linux-gate') or lib.startswith('linux-vdso')
+
+
+def parse_trace(cmd, fref):
+ new_env = os.environ.copy()
+ new_env['LD_TRACE_LOADED_OBJECTS'] = '1'
+ trace_out = subprocess.run(cmd, stdout=subprocess.PIPE, check=True,
+ universal_newlines=True, env=new_env).stdout
+ trace = []
+ for line in trace_out.splitlines():
+ line = line.strip()
+ if is_vdso(line):
+ continue
+ fields = line.split('=>' if '=>' in line else ' ')
+ lib = os.path.basename(fields[0].strip())
+ if lib.startswith('ld'):
+ lib = 'ld'
+ elif lib.startswith('libc'):
+ lib = 'libc'
+ found = 1 if fields[1].strip() != 'not found' else 0
+ trace += ['{} {}'.format(lib, found)]
+ trace = sorted(trace)
+
+ reference = sorted(line.replace('\n','') for line in fref.readlines())
+
+ ret = 0 if trace == reference else 1
+ if ret != 0:
+ for i in reference:
+ if i not in trace:
+ print("Only in {}: {}".format(fref.name, i))
+ for i in trace:
+ if i not in reference:
+ print("Only in trace: {}".format(i))
+
+ sys.exit(ret)
+
+
+def get_parser():
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('command',
+ help='comand to run')
+ parser.add_argument('reference',
+ help='reference file to compare')
+ return parser
+
+
+def main(argv):
+ parser = get_parser()
+ opts = parser.parse_args(argv)
+ with open(opts.reference, 'r') as fref:
+ # Remove the initial 'env' command.
+ parse_trace(opts.command.split()[1:], fref)
+
+
+if __name__ == '__main__':
+ main(sys.argv[1:])

View file

@ -1,36 +0,0 @@
commit a2211c76c3b994099fd58a06d6072d7495d699cd
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Mar 18 18:18:35 2022 +0100
scripts/dso-ordering-test.py: Fix C&P error in * callrefs processing
The elf/dso-sort-tests-src subdirectory is not changed by this commit,
so it seems that the cut-and-paste error was not material.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/scripts/dso-ordering-test.py b/scripts/dso-ordering-test.py
index bde0406be9da14fc..ee476c810c76f1b0 100644
--- a/scripts/dso-ordering-test.py
+++ b/scripts/dso-ordering-test.py
@@ -551,17 +551,17 @@ def process_testcase(t):
if obj in t.deps:
deps = t.deps[obj]
if '*' in deps:
- t.deps[obj].remove('*')
+ deps.remove('*')
t.add_deps([obj], non_dep_tgt_objs)
if obj in t.callrefs:
deps = t.callrefs[obj]
if '*' in deps:
- t.deps[obj].remove('*')
+ deps.remove('*')
t.add_callrefs([obj], non_dep_tgt_objs)
if "#" in t.deps:
deps = t.deps["#"]
if '*' in deps:
- t.deps["#"].remove('*')
+ deps.remove('*')
t.add_deps(["#"], non_dep_tgt_objs)
# If no main program was specified in dependency description, make a

View file

@ -1,37 +0,0 @@
commit 183d99737298bb3200f0610fdcd1c7549c8ed560
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Sep 6 07:38:10 2022 +0200
scripts/dso-ordering-test.py: Generate program run-time dependencies
The main program needs to depend on all shared objects, even objects
that have link-time dependencies among shared objects. Filtering
out shared objects that already have an link-time dependencies is not
necessary here; make will do this automatically.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
diff --git a/scripts/dso-ordering-test.py b/scripts/dso-ordering-test.py
index ee476c810c76f1b0..43b5ec4d920ad6a3 100644
--- a/scripts/dso-ordering-test.py
+++ b/scripts/dso-ordering-test.py
@@ -707,13 +707,12 @@ def process_testcase(t):
"\t$(compile.c) $(OUTPUT_OPTION)\n")
makefile.write (rule)
- not_depended_objs = find_objs_not_depended_on(test_descr)
- if not_depended_objs:
- depstr = ""
- for dep in not_depended_objs:
- depstr += (" $(objpfx)" + test_subdir + "/"
- + test_name + "-" + dep + ".so")
- makefile.write("$(objpfx)%s.out:%s\n" % (base_test_name, depstr))
+ # Ensure that all shared objects are built before running the
+ # test, whether there link-time dependencies or not.
+ depobjs = ["$(objpfx){}/{}-{}.so".format(test_subdir, test_name, dep)
+ for dep in test_descr.objs]
+ makefile.write("$(objpfx){}.out: {}\n".format(
+ base_test_name, " ".join(depobjs)))
# Add main executable to test-srcs
makefile.write("test-srcs += %s/%s\n" % (test_subdir, test_name))

View file

@ -1,49 +0,0 @@
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

View file

@ -1,185 +0,0 @@
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);

View file

@ -1,42 +0,0 @@
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);

View file

@ -1,27 +0,0 @@
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

File diff suppressed because it is too large Load diff

View file

@ -1,328 +0,0 @@
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>

View file

@ -1,134 +0,0 @@
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);

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