From af815d34f3be80b2e8cde1d61e15697f962cb241 Mon Sep 17 00:00:00 2001 From: anolis-bot Date: Thu, 10 Nov 2022 20:39:23 +0800 Subject: [PATCH] update to glibc-2.28-211.el8 Signed-off-by: anolis-bot --- SUPPORTED | 3 +- build-locale-archive.c | 2 +- dist | 1 + ...check-alignment-of-PT_LOAD-segment-2.patch | 148 - glibc-LoongArch-Port.patch | 16504 ---------------- ...perly-check-stack-alignment-BZ-27901.patch | 325 - ...cific-ALIGN-for-variable-alignment-4.patch | 171 - ...-of-__munmap-to-page-size-BZ-28676-3.patch | 36 - glibc-elf-Fix-tst-align3.patch | 40 - ...ly-align-PT_LOAD-segments-BZ-28676-1.patch | 137 - glibc-rh1888660.patch | 767 + ...c-rh2084564.patch => glibc-rh1961109.patch | 0 glibc-rh1982608.patch | 2216 +++ glibc-rh2033684-1.patch | 27 + glibc-rh2033684-10.patch | 90 + glibc-rh2033684-11.patch | 41 + glibc-rh2033684-12.patch | 295 + glibc-rh2033684-2.patch | 101 + glibc-rh2033684-3.patch | 43 + glibc-rh2033684-4.patch | 161 + glibc-rh2033684-5.patch | 963 + glibc-rh2033684-6.patch | 1037 + glibc-rh2033684-7.patch | 43 + glibc-rh2033684-8.patch | 357 + glibc-rh2033684-9.patch | 23 + glibc-rh2037416-1.patch | 136 + glibc-rh2037416-2.patch | 131 + glibc-rh2037416-3.patch | 80 + glibc-rh2037416-4.patch | 51 + glibc-rh2037416-5.patch | 96 + glibc-rh2037416-6.patch | 39 + glibc-rh2037416-7.patch | 32 + glibc-rh2037416-8.patch | 630 + glibc-rh2047981-1.patch | 98 + glibc-rh2047981-10.patch | 31 + glibc-rh2047981-11.patch | 45 + glibc-rh2047981-12.patch | 607 + glibc-rh2047981-13.patch | 65 + glibc-rh2047981-14.patch | 388 + glibc-rh2047981-15.patch | 160 + glibc-rh2047981-16.patch | 253 + glibc-rh2047981-17.patch | 156 + glibc-rh2047981-18.patch | 122 + glibc-rh2047981-19.patch | 333 + glibc-rh2047981-2.patch | 70 + glibc-rh2047981-20.patch | 113 + glibc-rh2047981-21.patch | 205 + glibc-rh2047981-22.patch | 795 + glibc-rh2047981-23.patch | 449 + glibc-rh2047981-24.patch | 296 + glibc-rh2047981-25.patch | 313 + glibc-rh2047981-26.patch | 170 + glibc-rh2047981-27.patch | 557 + glibc-rh2047981-28.patch | 77 + glibc-rh2047981-29.patch | 42 + glibc-rh2047981-3.patch | 245 + glibc-rh2047981-30.patch | 520 + glibc-rh2047981-31.patch | 440 + glibc-rh2047981-32.patch | 298 + glibc-rh2047981-33.patch | 1777 ++ glibc-rh2047981-34.patch | 1042 + glibc-rh2047981-35.patch | 21 + glibc-rh2047981-36.patch | 28 + glibc-rh2047981-37.patch | 112 + glibc-rh2047981-38.patch | 44 + glibc-rh2047981-39.patch | 42 + glibc-rh2047981-4.patch | 34 + glibc-rh2047981-40.patch | 170 + glibc-rh2047981-41.patch | 268 + glibc-rh2047981-42.patch | 296 + glibc-rh2047981-43.patch | 22 + glibc-rh2047981-44.patch | 98 + glibc-rh2047981-45.patch | 74 + glibc-rh2047981-46.patch | 227 + glibc-rh2047981-47.patch | 59 + glibc-rh2047981-5.patch | 224 + glibc-rh2047981-6.patch | 822 + glibc-rh2047981-7.patch | 134 + glibc-rh2047981-8.patch | 29 + glibc-rh2047981-9.patch | 126 + glibc-rh2054790.patch | 27 + glibc-rh2063042.patch | 358 + ...c-rh2061727.patch => glibc-rh2063712.patch | 0 glibc-rh2065588-1.patch | 253 + glibc-rh2065588-10.patch | 21 + glibc-rh2065588-11.patch | 39 + glibc-rh2065588-12.patch | 60 + glibc-rh2065588-13.patch | 66 + glibc-rh2065588-2.patch | 231 + glibc-rh2065588-3.patch | 527 + glibc-rh2065588-4.patch | 194 + glibc-rh2065588-5.patch | 64 + glibc-rh2065588-6.patch | 56 + glibc-rh2065588-7.patch | 73 + glibc-rh2065588-8.patch | 74 + glibc-rh2065588-9.patch | 21 + ...c-rh2073432.patch => glibc-rh2071745.patch | 0 glibc-rh2072329.patch | 86 + glibc-rh2077835.patch | 211 + glibc-rh2080349-1.patch | 37 + glibc-rh2080349-2.patch | 40 + glibc-rh2080349-3.patch | 45 + glibc-rh2080349-4.patch | 43 + glibc-rh2080349-5.patch | 37 + glibc-rh2080349-6.patch | 37 + glibc-rh2080349-7.patch | 28 + glibc-rh2080349-8.patch | 20 + glibc-rh2080349-9.patch | 10 + glibc-rh2086853.patch | 30 + ...2093457-1.patch => glibc-rh2089247-1.patch | 0 ...2093457-2.patch => glibc-rh2089247-2.patch | 0 ...2093457-3.patch => glibc-rh2089247-3.patch | 0 ...2093457-4.patch => glibc-rh2089247-4.patch | 0 ...2093457-5.patch => glibc-rh2089247-5.patch | 0 ...2093457-6.patch => glibc-rh2089247-6.patch | 0 ...c-rh2094540.patch => glibc-rh2091553.patch | 0 glibc-rh2096189-1.patch | 67 + glibc-rh2096189-2.patch | 957 + glibc-rh2096189-3.patch | 44 + glibc-rh2104907.patch | 14 + glibc-rh2119304-1.patch | 49 + glibc-rh2119304-2.patch | 202 + glibc-rh2119304-3.patch | 19 + glibc.spec | 235 +- 124 files changed, 24096 insertions(+), 17402 deletions(-) create mode 100644 dist delete mode 100644 glibc-Add-a-testcase-to-check-alignment-of-PT_LOAD-segment-2.patch delete mode 100644 glibc-LoongArch-Port.patch delete mode 100644 glibc-Properly-check-stack-alignment-BZ-27901.patch delete mode 100644 glibc-Support-target-specific-ALIGN-for-variable-alignment-4.patch delete mode 100644 glibc-elf-Align-argument-of-__munmap-to-page-size-BZ-28676-3.patch delete mode 100644 glibc-elf-Fix-tst-align3.patch delete mode 100644 glibc-elf-Properly-align-PT_LOAD-segments-BZ-28676-1.patch create mode 100644 glibc-rh1888660.patch rename glibc-rh2084564.patch => glibc-rh1961109.patch (100%) create mode 100644 glibc-rh1982608.patch create mode 100644 glibc-rh2033684-1.patch create mode 100644 glibc-rh2033684-10.patch create mode 100644 glibc-rh2033684-11.patch create mode 100644 glibc-rh2033684-12.patch create mode 100644 glibc-rh2033684-2.patch create mode 100644 glibc-rh2033684-3.patch create mode 100644 glibc-rh2033684-4.patch create mode 100644 glibc-rh2033684-5.patch create mode 100644 glibc-rh2033684-6.patch create mode 100644 glibc-rh2033684-7.patch create mode 100644 glibc-rh2033684-8.patch create mode 100644 glibc-rh2033684-9.patch create mode 100644 glibc-rh2037416-1.patch create mode 100644 glibc-rh2037416-2.patch create mode 100644 glibc-rh2037416-3.patch create mode 100644 glibc-rh2037416-4.patch create mode 100644 glibc-rh2037416-5.patch create mode 100644 glibc-rh2037416-6.patch create mode 100644 glibc-rh2037416-7.patch create mode 100644 glibc-rh2037416-8.patch create mode 100644 glibc-rh2047981-1.patch create mode 100644 glibc-rh2047981-10.patch create mode 100644 glibc-rh2047981-11.patch create mode 100644 glibc-rh2047981-12.patch create mode 100644 glibc-rh2047981-13.patch create mode 100644 glibc-rh2047981-14.patch create mode 100644 glibc-rh2047981-15.patch create mode 100644 glibc-rh2047981-16.patch create mode 100644 glibc-rh2047981-17.patch create mode 100644 glibc-rh2047981-18.patch create mode 100644 glibc-rh2047981-19.patch create mode 100644 glibc-rh2047981-2.patch create mode 100644 glibc-rh2047981-20.patch create mode 100644 glibc-rh2047981-21.patch create mode 100644 glibc-rh2047981-22.patch create mode 100644 glibc-rh2047981-23.patch create mode 100644 glibc-rh2047981-24.patch create mode 100644 glibc-rh2047981-25.patch create mode 100644 glibc-rh2047981-26.patch create mode 100644 glibc-rh2047981-27.patch create mode 100644 glibc-rh2047981-28.patch create mode 100644 glibc-rh2047981-29.patch create mode 100644 glibc-rh2047981-3.patch create mode 100644 glibc-rh2047981-30.patch create mode 100644 glibc-rh2047981-31.patch create mode 100644 glibc-rh2047981-32.patch create mode 100644 glibc-rh2047981-33.patch create mode 100644 glibc-rh2047981-34.patch create mode 100644 glibc-rh2047981-35.patch create mode 100644 glibc-rh2047981-36.patch create mode 100644 glibc-rh2047981-37.patch create mode 100644 glibc-rh2047981-38.patch create mode 100644 glibc-rh2047981-39.patch create mode 100644 glibc-rh2047981-4.patch create mode 100644 glibc-rh2047981-40.patch create mode 100644 glibc-rh2047981-41.patch create mode 100644 glibc-rh2047981-42.patch create mode 100644 glibc-rh2047981-43.patch create mode 100644 glibc-rh2047981-44.patch create mode 100644 glibc-rh2047981-45.patch create mode 100644 glibc-rh2047981-46.patch create mode 100644 glibc-rh2047981-47.patch create mode 100644 glibc-rh2047981-5.patch create mode 100644 glibc-rh2047981-6.patch create mode 100644 glibc-rh2047981-7.patch create mode 100644 glibc-rh2047981-8.patch create mode 100644 glibc-rh2047981-9.patch create mode 100644 glibc-rh2054790.patch create mode 100644 glibc-rh2063042.patch rename glibc-rh2061727.patch => glibc-rh2063712.patch (100%) create mode 100644 glibc-rh2065588-1.patch create mode 100644 glibc-rh2065588-10.patch create mode 100644 glibc-rh2065588-11.patch create mode 100644 glibc-rh2065588-12.patch create mode 100644 glibc-rh2065588-13.patch create mode 100644 glibc-rh2065588-2.patch create mode 100644 glibc-rh2065588-3.patch create mode 100644 glibc-rh2065588-4.patch create mode 100644 glibc-rh2065588-5.patch create mode 100644 glibc-rh2065588-6.patch create mode 100644 glibc-rh2065588-7.patch create mode 100644 glibc-rh2065588-8.patch create mode 100644 glibc-rh2065588-9.patch rename glibc-rh2073432.patch => glibc-rh2071745.patch (100%) create mode 100644 glibc-rh2072329.patch create mode 100644 glibc-rh2077835.patch create mode 100644 glibc-rh2080349-1.patch create mode 100644 glibc-rh2080349-2.patch create mode 100644 glibc-rh2080349-3.patch create mode 100644 glibc-rh2080349-4.patch create mode 100644 glibc-rh2080349-5.patch create mode 100644 glibc-rh2080349-6.patch create mode 100644 glibc-rh2080349-7.patch create mode 100644 glibc-rh2080349-8.patch create mode 100644 glibc-rh2080349-9.patch create mode 100644 glibc-rh2086853.patch rename glibc-rh2093457-1.patch => glibc-rh2089247-1.patch (100%) rename glibc-rh2093457-2.patch => glibc-rh2089247-2.patch (100%) rename glibc-rh2093457-3.patch => glibc-rh2089247-3.patch (100%) rename glibc-rh2093457-4.patch => glibc-rh2089247-4.patch (100%) rename glibc-rh2093457-5.patch => glibc-rh2089247-5.patch (100%) rename glibc-rh2093457-6.patch => glibc-rh2089247-6.patch (100%) rename glibc-rh2094540.patch => glibc-rh2091553.patch (100%) create mode 100644 glibc-rh2096189-1.patch create mode 100644 glibc-rh2096189-2.patch create mode 100644 glibc-rh2096189-3.patch create mode 100644 glibc-rh2104907.patch create mode 100644 glibc-rh2119304-1.patch create mode 100644 glibc-rh2119304-2.patch create mode 100644 glibc-rh2119304-3.patch diff --git a/SUPPORTED b/SUPPORTED index a4bf79c..fdf15fd 100644 --- a/SUPPORTED +++ b/SUPPORTED @@ -159,7 +159,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/UTF-8 \ +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 \ diff --git a/build-locale-archive.c b/build-locale-archive.c index 9183972..3cb3b47 100644 --- a/build-locale-archive.c +++ b/build-locale-archive.c @@ -448,7 +448,7 @@ fill_archive (struct locarhandle *tmpl_ah, char fullname[fnamelen + 2 * strlen (d->d_name) + 7]; #ifdef _DIRENT_HAVE_D_TYPE - if (d_type == DT_UNKNOWN) + if (d_type == DT_UNKNOWN || d_type == DT_LNK) #endif { strcpy (stpcpy (stpcpy (fullname, fname), "/"), diff --git a/dist b/dist new file mode 100644 index 0000000..9c0e36e --- /dev/null +++ b/dist @@ -0,0 +1 @@ +an8 diff --git a/glibc-Add-a-testcase-to-check-alignment-of-PT_LOAD-segment-2.patch b/glibc-Add-a-testcase-to-check-alignment-of-PT_LOAD-segment-2.patch deleted file mode 100644 index 8fbe86d..0000000 --- a/glibc-Add-a-testcase-to-check-alignment-of-PT_LOAD-segment-2.patch +++ /dev/null @@ -1,148 +0,0 @@ -From ab887596903b159107e0be6f8b25986a5597cfca Mon Sep 17 00:00:00 2001 -From: "H.J. Lu" -Date: Mon, 7 Feb 2022 10:44:17 -0500 -Subject: [PATCH 2/4] Add a testcase to check alignment of PT_LOAD segment [BZ - #28676] - -Backport from master commit: fc2334a - -Signed-off-by: Rongwei Wang ---- - elf/Makefile | 14 ++++++++++++-- - elf/tst-align3.c | 38 ++++++++++++++++++++++++++++++++++++++ - elf/tst-alignmod3.c | 32 ++++++++++++++++++++++++++++++++ - 3 files changed, 82 insertions(+), 2 deletions(-) - create mode 100644 elf/tst-align3.c - create mode 100644 elf/tst-alignmod3.c - -diff --git a/elf/Makefile b/elf/Makefile -index 2093cefa..0d3366e2 100644 ---- a/elf/Makefile -+++ b/elf/Makefile -@@ -187,7 +187,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ - tst-tls4 tst-tls5 \ - tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \ - tst-tls16 tst-tls17 tst-tls18 tst-tls19 tst-tls-dlinfo \ -- tst-align tst-align2 \ -+ tst-align tst-align2 tst-align3 \ - tst-dlmodcount tst-dlopenrpath tst-deep1 \ - tst-dlmopen1 tst-dlmopen3 \ - unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \ -@@ -221,6 +221,9 @@ tests += tst-dlopen-aout - tst-dlopen-aout-no-pie = yes - endif - test-srcs = tst-pathopt -+ifeq (yes,$(have-fpie)) -+tests-pie += tst-align3 -+endif - selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null) - ifneq ($(selinux-enabled),1) - tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog -@@ -268,7 +271,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ - circlemod3 circlemod3a \ - reldep8mod1 reldep8mod2 reldep8mod3 \ - reldep9mod1 reldep9mod2 reldep9mod3 \ -- tst-alignmod tst-alignmod2 \ -+ tst-alignmod tst-alignmod2 tst-alignmod3 \ - $(modules-execstack-$(have-z-execstack)) \ - tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \ - tst-dlmopen1mod tst-auditmod1 \ -@@ -1060,6 +1063,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 -+ . */ -+ -+#include -+#include -+ -+/* 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 -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 -+ . */ -+ -+#include -+#include -+ -+/* 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.18.4 - diff --git a/glibc-LoongArch-Port.patch b/glibc-LoongArch-Port.patch deleted file mode 100644 index ca00cdd..0000000 --- a/glibc-LoongArch-Port.patch +++ /dev/null @@ -1,16504 +0,0 @@ -From b8f82ee8df870058d80a7a51bea14465235f06d5 Mon Sep 17 00:00:00 2001 -From: wanghongliang -Date: Thu, 23 Jun 2022 10:29:34 +0800 -Subject: [PATCH] glibc LoongArch Port. - -add LoongArch architecture support. - -Signed-off-by: wanghongliang ---- - README | 1 + - elf/elf.h | 84 + - scripts/config.sub | 7 +- - sysdeps/loongarch/Implies | 5 + - sysdeps/loongarch/Makefile | 32 + - sysdeps/loongarch/__longjmp.S | 50 + - sysdeps/loongarch/abort-instr.h | 2 + - sysdeps/loongarch/at_quick_exit.c | 1 + - sysdeps/loongarch/atexit.c | 1 + - sysdeps/loongarch/bits/endian.h | 9 + - sysdeps/loongarch/bits/fenv.h | 93 + - sysdeps/loongarch/bits/link.h | 56 + - sysdeps/loongarch/bits/setjmp.h | 39 + - sysdeps/loongarch/bits/wordsize.h | 22 + - sysdeps/loongarch/bsd-_setjmp.c | 1 + - sysdeps/loongarch/bsd-setjmp.c | 1 + - sysdeps/loongarch/configure | 4 + - sysdeps/loongarch/configure.ac | 6 + - sysdeps/loongarch/dl-irel.h | 51 + - sysdeps/loongarch/dl-machine.h | 366 +++ - sysdeps/loongarch/dl-tls.h | 49 + - sysdeps/loongarch/dl-trampoline.S | 108 + - sysdeps/loongarch/e_sqrtl.c | 39 + - sysdeps/loongarch/elf-init.c | 1 + - sysdeps/loongarch/fpu/e_sqrt.c | 29 + - sysdeps/loongarch/fpu/e_sqrtf.c | 28 + - sysdeps/loongarch/fpu/fclrexcpt.c | 47 + - sysdeps/loongarch/fpu/fedisblxcpt.c | 40 + - sysdeps/loongarch/fpu/feenablxcpt.c | 40 + - sysdeps/loongarch/fpu/fegetenv.c | 33 + - sysdeps/loongarch/fpu/fegetexcept.c | 33 + - sysdeps/loongarch/fpu/fegetmode.c | 27 + - sysdeps/loongarch/fpu/fegetround.c | 35 + - sysdeps/loongarch/fpu/feholdexcpt.c | 41 + - sysdeps/loongarch/fpu/fenv_libc.h | 31 + - sysdeps/loongarch/fpu/fesetenv.c | 44 + - sysdeps/loongarch/fpu/fesetexcept.c | 32 + - sysdeps/loongarch/fpu/fesetmode.c | 38 + - sysdeps/loongarch/fpu/fesetround.c | 46 + - sysdeps/loongarch/fpu/feupdateenv.c | 45 + - sysdeps/loongarch/fpu/fgetexcptflg.c | 39 + - sysdeps/loongarch/fpu/fraiseexcpt.c | 84 + - sysdeps/loongarch/fpu/fsetexcptflg.c | 42 + - sysdeps/loongarch/fpu/ftestexcept.c | 33 + - sysdeps/loongarch/fpu_control.h | 111 + - sysdeps/loongarch/fstat.c | 1 + - sysdeps/loongarch/fstat64.c | 1 + - sysdeps/loongarch/fstatat.c | 1 + - sysdeps/loongarch/fstatat64.c | 1 + - sysdeps/loongarch/gccframe.h | 21 + - sysdeps/loongarch/hp-timing.h | 40 + - sysdeps/loongarch/jmpbuf-offsets.h | 23 + - sysdeps/loongarch/jmpbuf-unwind.h | 46 + - sysdeps/loongarch/ldsodefs.h | 47 + - sysdeps/loongarch/libc-start.h | 25 + - sysdeps/loongarch/libc-tls.c | 32 + - sysdeps/loongarch/linkmap.h | 4 + - sysdeps/loongarch/lp64/Implies-after | 1 + - sysdeps/loongarch/lp64/libm-test-ulps | 2206 +++++++++++++++++ - sysdeps/loongarch/lp64/libm-test-ulps-name | 1 + - sysdeps/loongarch/lp64/memcpy.S | 402 +++ - sysdeps/loongarch/lp64/memmove.S | 476 ++++ - sysdeps/loongarch/lp64/memset.S | 175 ++ - sysdeps/loongarch/lp64/s_cosf.S | 409 +++ - sysdeps/loongarch/lp64/s_sinf.S | 392 +++ - sysdeps/loongarch/lp64/strchr.S | 140 ++ - sysdeps/loongarch/lp64/strchrnul.S | 156 ++ - sysdeps/loongarch/lp64/strcmp.S | 197 ++ - sysdeps/loongarch/lp64/strcpy.S | 210 ++ - sysdeps/loongarch/lp64/strlen.S | 135 + - sysdeps/loongarch/lp64/strncmp.S | 269 ++ - sysdeps/loongarch/lp64/strnlen.S | 155 ++ - sysdeps/loongarch/lstat.c | 1 + - sysdeps/loongarch/lstat64.c | 1 + - sysdeps/loongarch/machine-gmon.h | 37 + - sysdeps/loongarch/math_private.h | 245 ++ - sysdeps/loongarch/memusage.h | 21 + - sysdeps/loongarch/mknod.c | 1 + - sysdeps/loongarch/mknodat.c | 1 + - sysdeps/loongarch/nptl/Makefile | 26 + - .../loongarch/nptl/bits/pthreadtypes-arch.h | 68 + - sysdeps/loongarch/nptl/bits/semaphore.h | 33 + - sysdeps/loongarch/nptl/libc-lowlevellock.c | 8 + - sysdeps/loongarch/nptl/nptl-sysdep.S | 2 + - sysdeps/loongarch/nptl/pthread-offsets.h | 23 + - sysdeps/loongarch/nptl/pthreaddef.h | 32 + - sysdeps/loongarch/nptl/tcb-offsets.sym | 6 + - sysdeps/loongarch/nptl/tls.h | 147 ++ - sysdeps/loongarch/preconfigure | 9 + - sysdeps/loongarch/pthread_atfork.c | 1 + - sysdeps/loongarch/setjmp.S | 62 + - sysdeps/loongarch/sfp-machine.h | 79 + - sysdeps/loongarch/sotruss-lib.c | 51 + - sysdeps/loongarch/stack_chk_fail_local.c | 1 + - sysdeps/loongarch/stackinfo.h | 33 + - sysdeps/loongarch/start.S | 51 + - sysdeps/loongarch/stat.c | 1 + - sysdeps/loongarch/stat64.c | 1 + - sysdeps/loongarch/sys/asm.h | 49 + - sysdeps/loongarch/sys/regdef.h | 83 + - sysdeps/loongarch/tininess.h | 1 + - sysdeps/loongarch/tls-macros.h | 46 + - sysdeps/loongarch/tst-audit.h | 23 + - sysdeps/loongarch/warning-nop.c | 1 + - sysdeps/unix/sysv/linux/loongarch/Implies | 1 + - sysdeps/unix/sysv/linux/loongarch/Makefile | 17 + - sysdeps/unix/sysv/linux/loongarch/Versions | 44 + - .../sysv/linux/loongarch/atomic-machine.h | 188 ++ - .../unix/sysv/linux/loongarch/bits/fcntl.h | 62 + - .../sysv/linux/loongarch/bits/local_lim.h | 99 + - sysdeps/unix/sysv/linux/loongarch/bits/mman.h | 41 + - sysdeps/unix/sysv/linux/loongarch/bits/shm.h | 112 + - .../sysv/linux/loongarch/bits/sigcontext.h | 47 + - .../unix/sysv/linux/loongarch/bits/signum.h | 58 + - sysdeps/unix/sysv/linux/loongarch/clone.S | 98 + - sysdeps/unix/sysv/linux/loongarch/configure | 199 ++ - .../unix/sysv/linux/loongarch/configure.ac | 27 + - sysdeps/unix/sysv/linux/loongarch/dl-static.c | 84 + - .../unix/sysv/linux/loongarch/getcontext.S | 72 + - sysdeps/unix/sysv/linux/loongarch/getpid.c | 54 + - .../unix/sysv/linux/loongarch/gettimeofday.c | 58 + - sysdeps/unix/sysv/linux/loongarch/getuid.c | 60 + - .../unix/sysv/linux/loongarch/init-first.c | 57 + - sysdeps/unix/sysv/linux/loongarch/ipc_priv.h | 21 + - .../sysv/linux/loongarch/kernel-features.h | 24 + - .../unix/sysv/linux/loongarch/ldd-rewrite.sed | 1 + - sysdeps/unix/sysv/linux/loongarch/ldsodefs.h | 32 + - sysdeps/unix/sysv/linux/loongarch/libc-vdso.h | 37 + - .../unix/sysv/linux/loongarch/localplt.data | 13 + - .../unix/sysv/linux/loongarch/lp64/Implies | 3 + - .../sysv/linux/loongarch/lp64/c++-types.data | 67 + - .../linux/loongarch/lp64/jmp_buf-macros.h | 41 + - .../unix/sysv/linux/loongarch/lp64/ld.abilist | 5 + - .../loongarch/lp64/libBrokenLocale.abilist | 1 + - .../sysv/linux/loongarch/lp64/libanl.abilist | 4 + - .../sysv/linux/loongarch/lp64/libc.abilist | 2101 ++++++++++++++++ - .../linux/loongarch/lp64/libcrypt.abilist | 7 + - .../sysv/linux/loongarch/lp64/libdl.abilist | 9 + - .../sysv/linux/loongarch/lp64/libm.abilist | 1021 ++++++++ - .../sysv/linux/loongarch/lp64/libnsl.abilist | 120 + - .../linux/loongarch/lp64/libpthread.abilist | 264 ++ - .../linux/loongarch/lp64/libresolv.abilist | 79 + - .../sysv/linux/loongarch/lp64/librt.abilist | 35 + - .../linux/loongarch/lp64/libthread_db.abilist | 40 + - .../sysv/linux/loongarch/lp64/libutil.abilist | 6 + - .../unix/sysv/linux/loongarch/makecontext.c | 78 + - .../sysv/linux/loongarch/profil-counter.h | 31 + - sysdeps/unix/sysv/linux/loongarch/pt-vfork.S | 1 + - .../unix/sysv/linux/loongarch/register-dump.h | 63 + - .../unix/sysv/linux/loongarch/setcontext.S | 111 + - .../unix/sysv/linux/loongarch/shlib-versions | 2 + - .../sysv/linux/loongarch/sigcontextinfo.h | 22 + - .../unix/sysv/linux/loongarch/swapcontext.S | 120 + - .../unix/sysv/linux/loongarch/sys/procfs.h | 122 + - .../unix/sysv/linux/loongarch/sys/ucontext.h | 81 + - sysdeps/unix/sysv/linux/loongarch/sys/user.h | 31 + - sysdeps/unix/sysv/linux/loongarch/syscall.c | 36 + - sysdeps/unix/sysv/linux/loongarch/sysdep.S | 52 + - sysdeps/unix/sysv/linux/loongarch/sysdep.h | 333 +++ - .../sysv/linux/loongarch/ucontext-macros.h | 44 + - .../unix/sysv/linux/loongarch/ucontext_i.sym | 33 + - sysdeps/unix/sysv/linux/loongarch/vfork.S | 49 + - 162 files changed, 15153 insertions(+), 1 deletion(-) - create mode 100644 sysdeps/loongarch/Implies - create mode 100644 sysdeps/loongarch/Makefile - create mode 100644 sysdeps/loongarch/__longjmp.S - create mode 100644 sysdeps/loongarch/abort-instr.h - create mode 100644 sysdeps/loongarch/at_quick_exit.c - create mode 100644 sysdeps/loongarch/atexit.c - create mode 100644 sysdeps/loongarch/bits/endian.h - create mode 100644 sysdeps/loongarch/bits/fenv.h - create mode 100644 sysdeps/loongarch/bits/link.h - create mode 100644 sysdeps/loongarch/bits/setjmp.h - create mode 100644 sysdeps/loongarch/bits/wordsize.h - create mode 100644 sysdeps/loongarch/bsd-_setjmp.c - create mode 100644 sysdeps/loongarch/bsd-setjmp.c - create mode 100755 sysdeps/loongarch/configure - create mode 100644 sysdeps/loongarch/configure.ac - create mode 100644 sysdeps/loongarch/dl-irel.h - create mode 100644 sysdeps/loongarch/dl-machine.h - create mode 100644 sysdeps/loongarch/dl-tls.h - create mode 100644 sysdeps/loongarch/dl-trampoline.S - create mode 100644 sysdeps/loongarch/e_sqrtl.c - create mode 100644 sysdeps/loongarch/elf-init.c - create mode 100644 sysdeps/loongarch/fpu/e_sqrt.c - create mode 100644 sysdeps/loongarch/fpu/e_sqrtf.c - create mode 100644 sysdeps/loongarch/fpu/fclrexcpt.c - create mode 100644 sysdeps/loongarch/fpu/fedisblxcpt.c - create mode 100644 sysdeps/loongarch/fpu/feenablxcpt.c - create mode 100644 sysdeps/loongarch/fpu/fegetenv.c - create mode 100644 sysdeps/loongarch/fpu/fegetexcept.c - create mode 100644 sysdeps/loongarch/fpu/fegetmode.c - create mode 100644 sysdeps/loongarch/fpu/fegetround.c - create mode 100644 sysdeps/loongarch/fpu/feholdexcpt.c - create mode 100644 sysdeps/loongarch/fpu/fenv_libc.h - create mode 100644 sysdeps/loongarch/fpu/fesetenv.c - create mode 100644 sysdeps/loongarch/fpu/fesetexcept.c - create mode 100644 sysdeps/loongarch/fpu/fesetmode.c - create mode 100644 sysdeps/loongarch/fpu/fesetround.c - create mode 100644 sysdeps/loongarch/fpu/feupdateenv.c - create mode 100644 sysdeps/loongarch/fpu/fgetexcptflg.c - create mode 100644 sysdeps/loongarch/fpu/fraiseexcpt.c - create mode 100644 sysdeps/loongarch/fpu/fsetexcptflg.c - create mode 100644 sysdeps/loongarch/fpu/ftestexcept.c - create mode 100644 sysdeps/loongarch/fpu_control.h - create mode 100644 sysdeps/loongarch/fstat.c - create mode 100644 sysdeps/loongarch/fstat64.c - create mode 100644 sysdeps/loongarch/fstatat.c - create mode 100644 sysdeps/loongarch/fstatat64.c - create mode 100644 sysdeps/loongarch/gccframe.h - create mode 100644 sysdeps/loongarch/hp-timing.h - create mode 100644 sysdeps/loongarch/jmpbuf-offsets.h - create mode 100644 sysdeps/loongarch/jmpbuf-unwind.h - create mode 100644 sysdeps/loongarch/ldsodefs.h - create mode 100644 sysdeps/loongarch/libc-start.h - create mode 100644 sysdeps/loongarch/libc-tls.c - create mode 100644 sysdeps/loongarch/linkmap.h - create mode 100644 sysdeps/loongarch/lp64/Implies-after - create mode 100644 sysdeps/loongarch/lp64/libm-test-ulps - create mode 100644 sysdeps/loongarch/lp64/libm-test-ulps-name - create mode 100644 sysdeps/loongarch/lp64/memcpy.S - create mode 100644 sysdeps/loongarch/lp64/memmove.S - create mode 100644 sysdeps/loongarch/lp64/memset.S - create mode 100644 sysdeps/loongarch/lp64/s_cosf.S - create mode 100644 sysdeps/loongarch/lp64/s_sinf.S - create mode 100644 sysdeps/loongarch/lp64/strchr.S - create mode 100644 sysdeps/loongarch/lp64/strchrnul.S - create mode 100644 sysdeps/loongarch/lp64/strcmp.S - create mode 100644 sysdeps/loongarch/lp64/strcpy.S - create mode 100644 sysdeps/loongarch/lp64/strlen.S - create mode 100644 sysdeps/loongarch/lp64/strncmp.S - create mode 100644 sysdeps/loongarch/lp64/strnlen.S - create mode 100644 sysdeps/loongarch/lstat.c - create mode 100644 sysdeps/loongarch/lstat64.c - create mode 100644 sysdeps/loongarch/machine-gmon.h - create mode 100644 sysdeps/loongarch/math_private.h - create mode 100644 sysdeps/loongarch/memusage.h - create mode 100644 sysdeps/loongarch/mknod.c - create mode 100644 sysdeps/loongarch/mknodat.c - create mode 100644 sysdeps/loongarch/nptl/Makefile - create mode 100644 sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h - create mode 100644 sysdeps/loongarch/nptl/bits/semaphore.h - create mode 100644 sysdeps/loongarch/nptl/libc-lowlevellock.c - create mode 100644 sysdeps/loongarch/nptl/nptl-sysdep.S - create mode 100644 sysdeps/loongarch/nptl/pthread-offsets.h - create mode 100644 sysdeps/loongarch/nptl/pthreaddef.h - create mode 100644 sysdeps/loongarch/nptl/tcb-offsets.sym - create mode 100644 sysdeps/loongarch/nptl/tls.h - create mode 100644 sysdeps/loongarch/preconfigure - create mode 100644 sysdeps/loongarch/pthread_atfork.c - create mode 100644 sysdeps/loongarch/setjmp.S - create mode 100644 sysdeps/loongarch/sfp-machine.h - create mode 100644 sysdeps/loongarch/sotruss-lib.c - create mode 100644 sysdeps/loongarch/stack_chk_fail_local.c - create mode 100644 sysdeps/loongarch/stackinfo.h - create mode 100644 sysdeps/loongarch/start.S - create mode 100644 sysdeps/loongarch/stat.c - create mode 100644 sysdeps/loongarch/stat64.c - create mode 100644 sysdeps/loongarch/sys/asm.h - create mode 100644 sysdeps/loongarch/sys/regdef.h - create mode 100644 sysdeps/loongarch/tininess.h - create mode 100644 sysdeps/loongarch/tls-macros.h - create mode 100644 sysdeps/loongarch/tst-audit.h - create mode 100644 sysdeps/loongarch/warning-nop.c - create mode 100644 sysdeps/unix/sysv/linux/loongarch/Implies - create mode 100644 sysdeps/unix/sysv/linux/loongarch/Makefile - create mode 100644 sysdeps/unix/sysv/linux/loongarch/Versions - create mode 100644 sysdeps/unix/sysv/linux/loongarch/atomic-machine.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/fcntl.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/local_lim.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/mman.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/shm.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/sigcontext.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/signum.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/clone.S - create mode 100644 sysdeps/unix/sysv/linux/loongarch/configure - create mode 100644 sysdeps/unix/sysv/linux/loongarch/configure.ac - create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-static.c - create mode 100644 sysdeps/unix/sysv/linux/loongarch/getcontext.S - create mode 100644 sysdeps/unix/sysv/linux/loongarch/getpid.c - create mode 100644 sysdeps/unix/sysv/linux/loongarch/gettimeofday.c - create mode 100644 sysdeps/unix/sysv/linux/loongarch/getuid.c - create mode 100644 sysdeps/unix/sysv/linux/loongarch/init-first.c - create mode 100644 sysdeps/unix/sysv/linux/loongarch/ipc_priv.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/kernel-features.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed - create mode 100644 sysdeps/unix/sysv/linux/loongarch/ldsodefs.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/libc-vdso.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/localplt.data - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/Implies - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/c++-types.data - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/jmp_buf-macros.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/ld.abilist - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libBrokenLocale.abilist - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libanl.abilist - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libcrypt.abilist - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libdl.abilist - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libm.abilist - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libnsl.abilist - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libpthread.abilist - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libresolv.abilist - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/librt.abilist - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libthread_db.abilist - create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libutil.abilist - create mode 100644 sysdeps/unix/sysv/linux/loongarch/makecontext.c - create mode 100644 sysdeps/unix/sysv/linux/loongarch/profil-counter.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/pt-vfork.S - create mode 100644 sysdeps/unix/sysv/linux/loongarch/register-dump.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/setcontext.S - create mode 100644 sysdeps/unix/sysv/linux/loongarch/shlib-versions - create mode 100644 sysdeps/unix/sysv/linux/loongarch/sigcontextinfo.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/swapcontext.S - create mode 100644 sysdeps/unix/sysv/linux/loongarch/sys/procfs.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/sys/ucontext.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/sys/user.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/syscall.c - create mode 100644 sysdeps/unix/sysv/linux/loongarch/sysdep.S - create mode 100644 sysdeps/unix/sysv/linux/loongarch/sysdep.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h - create mode 100644 sysdeps/unix/sysv/linux/loongarch/ucontext_i.sym - create mode 100644 sysdeps/unix/sysv/linux/loongarch/vfork.S - -diff --git a/README b/README -index 27a9fd47..1b5e147d 100644 ---- a/README -+++ b/README -@@ -41,6 +41,7 @@ The GNU C Library supports these configurations for using Linux kernels: - sh[34]-*-linux-gnu - sparc*-*-linux-gnu - sparc64*-*-linux-gnu -+ loongarch64-*-linux-gnu - - If you are interested in doing a port, please contact the glibc - maintainers; see http://www.gnu.org/software/libc/ for more -diff --git a/elf/elf.h b/elf/elf.h -index d6506ea1..0dc58b6d 100644 ---- a/elf/elf.h -+++ b/elf/elf.h -@@ -360,6 +360,7 @@ typedef struct - #define EM_RISCV 243 /* RISC-V */ - - #define EM_BPF 247 /* Linux BPF -- in-kernel virtual machine */ -+#define EM_LOONGARCH 258 /* Loongson Loongarch */ - - #define EM_NUM 248 - -@@ -3935,6 +3936,89 @@ enum - #define R_NDS32_TLS_TPOFF 102 - #define R_NDS32_TLS_DESC 119 - -+/* LoongISA ELF Flags */ -+#define EF_LARCH_ABI 0x0003 -+#define EF_LARCH_ABI_LP64 0x0003 -+#define EF_LARCH_ABI_LPX32 0x0002 -+#define EF_LARCH_ABI_LP32 0x0001 -+ -+/* Loongarch specific dynamic relocations. */ -+#define R_LARCH_NONE 0 -+#define R_LARCH_32 1 -+#define R_LARCH_64 2 -+#define R_LARCH_RELATIVE 3 -+#define R_LARCH_COPY 4 -+#define R_LARCH_JUMP_SLOT 5 -+#define R_LARCH_TLS_DTPMOD32 6 -+#define R_LARCH_TLS_DTPMOD64 7 -+#define R_LARCH_TLS_DTPREL32 8 -+#define R_LARCH_TLS_DTPREL64 9 -+#define R_LARCH_TLS_TPREL32 10 -+#define R_LARCH_TLS_TPREL64 11 -+#define R_LARCH_IRELATIVE 12 -+ -+/* Reserved for future relocs that the dynamic linker must understand. */ -+ -+/* used by the static linker for relocating .text */ -+#define R_LARCH_MARK_LA 20 -+#define R_LARCH_MARK_PCREL 21 -+ -+/* 这个重定位类型将symbol距离重定位位置的pc相对位置偏移量压栈。 -+ 它against symbol,因为如果是个常数,虽然在no-pic的情况下可以得到结果,但因为 -+ 重定位位置相对这个常数的偏移量一定很大,八成填不进去;而在pic的情况下, -+ 偏移量无法在静态连接时确定。因此我们约定这个重定位不可能against constant */ -+#define R_LARCH_SOP_PUSH_PCREL 22 -+ -+/* 这个重定位against a symbol or a constant。它将symbol的运行时绝对地址 -+ 或常数压栈,因此在pic的情况下会报错。另外我不太清楚常数和ABS段的关系。 */ -+#define R_LARCH_SOP_PUSH_ABSOLUTE 23 -+#define R_LARCH_SOP_PUSH_DUP 24 -+#define R_LARCH_SOP_PUSH_GPREL 25 -+#define R_LARCH_SOP_PUSH_TLS_TPREL 26 -+#define R_LARCH_SOP_PUSH_TLS_GOT 27 -+#define R_LARCH_SOP_PUSH_TLS_GD 28 -+#define R_LARCH_SOP_PUSH_PLT_PCREL 29 -+ -+#define R_LARCH_SOP_ASSERT 30 -+#define R_LARCH_SOP_NOT 31 -+#define R_LARCH_SOP_SUB 32 -+#define R_LARCH_SOP_SL 33 -+#define R_LARCH_SOP_SR 34 -+#define R_LARCH_SOP_ADD 35 -+#define R_LARCH_SOP_AND 36 -+#define R_LARCH_SOP_IF_ELSE 37 -+#define R_LARCH_SOP_POP_32_S_10_5 38 -+#define R_LARCH_SOP_POP_32_U_10_12 39 -+#define R_LARCH_SOP_POP_32_S_10_12 40 -+#define R_LARCH_SOP_POP_32_S_10_16 41 -+#define R_LARCH_SOP_POP_32_S_10_16_S2 42 -+#define R_LARCH_SOP_POP_32_S_5_20 43 -+#define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44 -+#define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45 -+#define R_LARCH_SOP_POP_32_U 46 -+ -+/* used by the static linker for relocating non .text */ -+/* 这几个重定位类型是为了照顾到 ".dword sym1 - sym2" 这种求差的写法。 -+ 这些重定位类型处理的是连接时地址,一般情况下它们是成对出现的。 -+ 在直接求负数".dword - sym1"的情况下,R_LARCH_SUBxx会单独出现。但注意, -+ 那个位置填进去的是连接时地址。 */ -+#define R_LARCH_ADD8 47 -+#define R_LARCH_ADD16 48 -+#define R_LARCH_ADD24 49 -+#define R_LARCH_ADD32 50 -+#define R_LARCH_ADD64 51 -+#define R_LARCH_SUB8 52 -+#define R_LARCH_SUB16 53 -+#define R_LARCH_SUB24 54 -+#define R_LARCH_SUB32 55 -+#define R_LARCH_SUB64 56 -+ -+ /* I don't know what it is. Existing in almost all other arch */ -+#define R_LARCH_GNU_VTINHERIT 57 -+#define R_LARCH_GNU_VTENTRY 58 -+ -+ -+ - __END_DECLS - - #endif /* elf.h */ -diff --git a/scripts/config.sub b/scripts/config.sub -index f2632cd8..34e9313f 100755 ---- a/scripts/config.sub -+++ b/scripts/config.sub -@@ -142,7 +142,7 @@ case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; -- -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -+ -dec* | -mips* | -loongarch* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -@@ -288,6 +288,7 @@ case $basic_machine in - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipsr5900 | mipsr5900el \ - | mipstx39 | mipstx39el \ -+ | loongarch | loongarch64 \ - | mn10200 | mn10300 \ - | moxie \ - | mt \ -@@ -415,6 +416,7 @@ case $basic_machine in - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipsr5900-* | mipsr5900el-* \ - | mipstx39-* | mipstx39el-* \ -+ | loongarch-* | loongarch64-* \ - | mmix-* \ - | mt-* \ - | msp430-* \ -@@ -1339,6 +1341,9 @@ case $basic_machine in - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; -+ loongarch) -+ basic_machine=loongarch-loongson -+ ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; -diff --git a/sysdeps/loongarch/Implies b/sysdeps/loongarch/Implies -new file mode 100644 -index 00000000..c88325b8 ---- /dev/null -+++ b/sysdeps/loongarch/Implies -@@ -0,0 +1,5 @@ -+init_array -+ -+ieee754/ldbl-128 -+ieee754/dbl-64 -+ieee754/flt-32 -diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile -new file mode 100644 -index 00000000..d5801b3c ---- /dev/null -+++ b/sysdeps/loongarch/Makefile -@@ -0,0 +1,32 @@ -+ifeq ($(subdir),misc) -+sysdep_headers += sys/asm.h -+endif -+ -+# LoongArch's assembler also needs to know about PIC as it changes the definition -+# of some assembler macros. -+ASFLAGS-.os += $(pic-ccflag) -+CFLAGS-elf-init.oS += -mcmodel=large -+CFLAGS-atexit.oS += -mcmodel=large -+CFLAGS-at_quick_exit.oS += -mcmodel=large -+CFLAGS-stat.oS += -mcmodel=large -+CFLAGS-fstat.oS += -mcmodel=large -+CFLAGS-lstat.oS += -mcmodel=large -+CFLAGS-stat64.oS += -mcmodel=large -+CFLAGS-fstat64.oS += -mcmodel=large -+CFLAGS-lstat64.oS += -mcmodel=large -+CFLAGS-fstatat.oS += -mcmodel=large -+CFLAGS-fstatat64.oS += -mcmodel=large -+CFLAGS-mknod.oS += -mcmodel=large -+CFLAGS-mknodat.oS += -mcmodel=large -+CFLAGS-pthread_atfork.oS += -mcmodel=large -+CFLAGS-warning-nop.oS += -mcmodel=large -+CFLAGS-stack_chk_fail_local.oS += -mcmodel=large -+ -+abi-variants := lp32 lp64 -+ -+ifeq (,$(filter $(default-abi),$(abi-variants))) -+$(error Unknown ABI $(default-abi), must be one of $(abi-variants)) -+endif -+ -+abi-lp64-condition := defined _ABILP64 -+abi-lp32-condition := defined _ABILP32 -diff --git a/sysdeps/loongarch/__longjmp.S b/sysdeps/loongarch/__longjmp.S -new file mode 100644 -index 00000000..68f67639 ---- /dev/null -+++ b/sysdeps/loongarch/__longjmp.S -@@ -0,0 +1,50 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+ -+ENTRY (__longjmp) -+ REG_L ra, a0, 0*SZREG -+ REG_L sp, a0, 1*SZREG -+ REG_L x, a0, 2*SZREG -+ REG_L fp, a0, 3*SZREG -+ REG_L s0, a0, 4*SZREG -+ REG_L s1, a0, 5*SZREG -+ REG_L s2, a0, 6*SZREG -+ REG_L s3, a0, 7*SZREG -+ REG_L s4, a0, 8*SZREG -+ REG_L s5, a0, 9*SZREG -+ REG_L s6, a0, 10*SZREG -+ REG_L s7, a0, 11*SZREG -+ REG_L s8, a0, 12*SZREG -+ -+ 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 -+ -+ sltui a0,a1,1 -+ add.d a0, a0, a1 # a0 = (a1 == 0) ? 1 : a1 -+ jirl zero,ra,0 -+ -+END (__longjmp) -diff --git a/sysdeps/loongarch/abort-instr.h b/sysdeps/loongarch/abort-instr.h -new file mode 100644 -index 00000000..46d3ad08 ---- /dev/null -+++ b/sysdeps/loongarch/abort-instr.h -@@ -0,0 +1,2 @@ -+/* An instruction which should crash any program is a breakpoint. */ -+#define ABORT_INSTRUCTION asm ("break 0") -diff --git a/sysdeps/loongarch/at_quick_exit.c b/sysdeps/loongarch/at_quick_exit.c -new file mode 100644 -index 00000000..8d4b44a7 ---- /dev/null -+++ b/sysdeps/loongarch/at_quick_exit.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/atexit.c b/sysdeps/loongarch/atexit.c -new file mode 100644 -index 00000000..fc055a48 ---- /dev/null -+++ b/sysdeps/loongarch/atexit.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/bits/endian.h b/sysdeps/loongarch/bits/endian.h -new file mode 100644 -index 00000000..dc9a3f2e ---- /dev/null -+++ b/sysdeps/loongarch/bits/endian.h -@@ -0,0 +1,9 @@ -+/* The MIPS architecture has selectable endianness. -+ It exists in both little and big endian flavours and we -+ want to be able to share the installed header files between -+ both, so we define __BYTE_ORDER based on GCC's predefines. */ -+ -+#ifndef _ENDIAN_H -+# error "Never use directly; include instead." -+#endif -+# define __BYTE_ORDER __LITTLE_ENDIAN -diff --git a/sysdeps/loongarch/bits/fenv.h b/sysdeps/loongarch/bits/fenv.h -new file mode 100644 -index 00000000..42767412 ---- /dev/null -+++ b/sysdeps/loongarch/bits/fenv.h -@@ -0,0 +1,93 @@ -+/* Copyright (C) 1998-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _FENV_H -+# error "Never use directly; include instead." -+#endif -+ -+ -+/* Define bits representing the exception. We use the bit positions -+ of the appropriate bits in the FPU control word. */ -+enum -+ { -+ FE_INEXACT = -+#define FE_INEXACT 0x010000 -+ FE_INEXACT, -+ FE_UNDERFLOW = -+#define FE_UNDERFLOW 0x020000 -+ FE_UNDERFLOW, -+ FE_OVERFLOW = -+#define FE_OVERFLOW 0x040000 -+ FE_OVERFLOW, -+ FE_DIVBYZERO = -+#define FE_DIVBYZERO 0x080000 -+ FE_DIVBYZERO, -+ FE_INVALID = -+#define FE_INVALID 0x100000 -+ FE_INVALID, -+ }; -+ -+#define FE_ALL_EXCEPT \ -+ (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) -+ -+/* The MIPS FPU supports all of the four defined rounding modes. We -+ use again the bit positions in the FPU control word as the values -+ for the appropriate macros. */ -+enum -+ { -+ FE_TONEAREST = -+#define FE_TONEAREST 0x000 -+ FE_TONEAREST, -+ FE_TOWARDZERO = -+#define FE_TOWARDZERO 0x100 -+ FE_TOWARDZERO, -+ FE_UPWARD = -+#define FE_UPWARD 0x200 -+ FE_UPWARD, -+ FE_DOWNWARD = -+#define FE_DOWNWARD 0x300 -+ FE_DOWNWARD -+ }; -+ -+ -+/* Type representing exception flags. */ -+typedef unsigned int fexcept_t; -+ -+ -+/* Type representing floating-point environment. This function corresponds -+ to the layout of the block written by the `fstenv'. */ -+typedef struct -+ { -+ unsigned int __fp_control_register; -+ } -+fenv_t; -+ -+/* If the default argument is used we use this value. */ -+#define FE_DFL_ENV ((const fenv_t *) -1) -+ -+#ifdef __USE_GNU -+/* Floating-point environment where none of the exception is masked. */ -+# define FE_NOMASK_ENV ((const fenv_t *) -257) -+#endif -+ -+#if __GLIBC_USE (IEC_60559_BFP_EXT) -+/* Type representing floating-point control modes. */ -+typedef unsigned int femode_t; -+ -+/* Default floating-point control modes. */ -+# define FE_DFL_MODE ((const femode_t *) -1L) -+#endif -diff --git a/sysdeps/loongarch/bits/link.h b/sysdeps/loongarch/bits/link.h -new file mode 100644 -index 00000000..554dfdc0 ---- /dev/null -+++ b/sysdeps/loongarch/bits/link.h -@@ -0,0 +1,56 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _LINK_H -+# error "Never include directly; use instead." -+#endif -+ -+typedef struct La_loongarch_regs -+{ -+ unsigned long int lr_reg[8]; /* a0 - a7 */ -+ double lr_fpreg[8]; /* fa0 - fa7 */ -+ unsigned long int lr_ra; -+ unsigned long int lr_sp; -+} La_loongarch_regs; -+ -+/* Return values for calls from PLT on LoongArch. */ -+typedef struct La_loongarch_retval -+{ -+ unsigned long int lrv_a0; -+ unsigned long int lrv_a1; -+ double lrv_fa0; -+ double lrv_fa1; -+} La_loongarch_retval; -+ -+__BEGIN_DECLS -+ -+extern ElfW(Addr) la_loongarch_gnu_pltenter (ElfW(Sym) *__sym, unsigned int __ndx, -+ uintptr_t *__refcook, -+ uintptr_t *__defcook, -+ La_loongarch_regs *__regs, -+ unsigned int *__flags, -+ const char *__symname, -+ long int *__framesizep); -+extern unsigned int la_loongarch_gnu_pltexit (ElfW(Sym) *__sym, unsigned int __ndx, -+ uintptr_t *__refcook, -+ uintptr_t *__defcook, -+ const La_loongarch_regs *__inregs, -+ La_loongarch_retval *__outregs, -+ const char *__symname); -+ -+__END_DECLS -diff --git a/sysdeps/loongarch/bits/setjmp.h b/sysdeps/loongarch/bits/setjmp.h -new file mode 100644 -index 00000000..cc9b6bfd ---- /dev/null -+++ b/sysdeps/loongarch/bits/setjmp.h -@@ -0,0 +1,39 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _LOONGARCH_BITS_SETJMP_H -+#define _LOONGARCH_BITS_SETJMP_H -+ -+typedef struct __jmp_buf_internal_tag -+ { -+ /* Program counter. */ -+ long int __pc; -+ /* Stack pointer. */ -+ long int __sp; -+ /* Reserved */ -+ long int __x; -+ /* Frame pointer. */ -+ long int __fp; -+ /* Callee-saved registers. */ -+ long int __regs[9]; -+ -+ /* Callee-saved floating point registers. */ -+ double __fpregs[8]; -+ } __jmp_buf[1]; -+ -+#endif /* _LOONGARCH_BITS_SETJMP_H */ -diff --git a/sysdeps/loongarch/bits/wordsize.h b/sysdeps/loongarch/bits/wordsize.h -new file mode 100644 -index 00000000..8dbaa00d ---- /dev/null -+++ b/sysdeps/loongarch/bits/wordsize.h -@@ -0,0 +1,22 @@ -+/* Copyright (C) 1999-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#define __loongarch_xlen 64 -+ -+#define __WORDSIZE __loongarch_xlen -+#define __WORDSIZE_TIME64_COMPAT32 0 -+ -diff --git a/sysdeps/loongarch/bsd-_setjmp.c b/sysdeps/loongarch/bsd-_setjmp.c -new file mode 100644 -index 00000000..0d413101 ---- /dev/null -+++ b/sysdeps/loongarch/bsd-_setjmp.c -@@ -0,0 +1 @@ -+/* _setjmp is implemented in setjmp.S */ -diff --git a/sysdeps/loongarch/bsd-setjmp.c b/sysdeps/loongarch/bsd-setjmp.c -new file mode 100644 -index 00000000..ee7c5e34 ---- /dev/null -+++ b/sysdeps/loongarch/bsd-setjmp.c -@@ -0,0 +1 @@ -+/* setjmp is implemented in setjmp.S */ -diff --git a/sysdeps/loongarch/configure b/sysdeps/loongarch/configure -new file mode 100755 -index 00000000..1e5abf81 ---- /dev/null -+++ b/sysdeps/loongarch/configure -@@ -0,0 +1,4 @@ -+# This file is generated from configure.ac by Autoconf. DO NOT EDIT! -+ # Local configure fragment for sysdeps/loongarch/elf. -+ -+#AC_DEFINE(PI_STATIC_AND_HIDDEN) -diff --git a/sysdeps/loongarch/configure.ac b/sysdeps/loongarch/configure.ac -new file mode 100644 -index 00000000..67b46ce0 ---- /dev/null -+++ b/sysdeps/loongarch/configure.ac -@@ -0,0 +1,6 @@ -+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. -+# Local configure fragment for sysdeps/loongarch/elf. -+ -+dnl It is always possible to access static and hidden symbols in an -+dnl position independent way. -+#AC_DEFINE(PI_STATIC_AND_HIDDEN) -diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h -new file mode 100644 -index 00000000..4216fec2 ---- /dev/null -+++ b/sysdeps/loongarch/dl-irel.h -@@ -0,0 +1,51 @@ -+/* Machine-dependent ELF indirect relocation inline functions. -+ x86-64 version. -+ Copyright (C) 2009-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#ifndef _DL_IREL_H -+#define _DL_IREL_H -+ -+#include -+#include -+ -+#define ELF_MACHINE_IRELA 1 -+ -+static inline ElfW(Addr) -+__attribute ((always_inline)) -+elf_ifunc_invoke (ElfW(Addr) addr) -+{ -+ return ((ElfW(Addr) (*) (void)) (addr)) (); -+} -+ -+static inline void -+__attribute ((always_inline)) -+elf_irela (const ElfW(Rela) *reloc) -+{ -+ ElfW(Addr) *const reloc_addr = (void *) reloc->r_offset; -+ const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info); -+ -+ if (__glibc_likely (r_type == R_LARCH_IRELATIVE)) -+ { -+ ElfW(Addr) value = elf_ifunc_invoke(reloc->r_addend); -+ *reloc_addr = value; -+ } -+ else -+ __libc_fatal ("Unexpected reloc type in static binary.\n"); -+} -+ -+#endif /* dl-irel.h */ -diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h -new file mode 100644 -index 00000000..2a5e3767 ---- /dev/null -+++ b/sysdeps/loongarch/dl-machine.h -@@ -0,0 +1,366 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef dl_machine_h -+#define dl_machine_h -+ -+#define ELF_MACHINE_NAME "LoongArch" -+ -+#include -+#include -+#include -+#include -+ -+#ifndef _RTLD_PROLOGUE -+# define _RTLD_PROLOGUE(entry) \ -+ ".globl\t" __STRING (entry) "\n\t" \ -+ ".type\t" __STRING (entry) ", @function\n\t" \ -+ CFI_STARTPROC "\n" \ -+ __STRING (entry) ":\n" -+#endif -+ -+#ifndef _RTLD_EPILOGUE -+# define _RTLD_EPILOGUE(entry) \ -+ CFI_ENDPROC "\n\t" \ -+ ".size\t" __STRING (entry) ", . - " __STRING (entry) "\n" -+#endif -+ -+#define ELF_MACHINE_JMP_SLOT R_LARCH_JUMP_SLOT -+#define ELF_MACHINE_IRELATIVE R_LARCH_IRELATIVE -+ -+#define elf_machine_type_class(type) \ -+ ((ELF_RTYPE_CLASS_PLT * ((type) == ELF_MACHINE_JMP_SLOT \ -+ || (__WORDSIZE == 32 && (type) == R_LARCH_TLS_DTPREL32) \ -+ || (__WORDSIZE == 32 && (type) == R_LARCH_TLS_DTPMOD32) \ -+ || (__WORDSIZE == 32 && (type) == R_LARCH_TLS_TPREL32) \ -+ || (__WORDSIZE == 64 && (type) == R_LARCH_TLS_DTPREL64) \ -+ || (__WORDSIZE == 64 && (type) == R_LARCH_TLS_DTPMOD64) \ -+ || (__WORDSIZE == 64 && (type) == R_LARCH_TLS_TPREL64))) \ -+ | (ELF_RTYPE_CLASS_COPY * ((type) == R_LARCH_COPY))) -+ -+#define ELF_MACHINE_NO_REL 1 -+#define ELF_MACHINE_NO_RELA 0 -+ -+/* Return nonzero iff ELF header is compatible with the running host. */ -+static inline int __attribute_used__ -+elf_machine_matches_host (const ElfW(Ehdr) *ehdr) -+{ -+ /* We can only run LoongArch binaries. */ -+ if (ehdr->e_machine != EM_LOONGARCH) -+ return 0; -+ -+#ifdef _ABILP64 -+ if ((ehdr->e_flags & EF_LARCH_ABI) != EF_LARCH_ABI_LP64) -+#elif defined _ABILPX32 -+ if ((ehdr->e_flags & EF_LARCH_ABI) != EF_LARCH_ABI_LPX32) -+#elif defined _ABILP32 -+ if ((ehdr->e_flags & EF_LARCH_ABI) != EF_LARCH_ABI_LP32) -+#else -+# error "Unknown ABI" -+#endif -+ return 0; -+ -+ return 1; -+} -+ -+/* Runtime address of .got */ -+#define _GLOBAL_OFFSET_TABLE_ ({ \ -+ ElfW(Addr) *r; \ -+ asm ("la.pcrel %0, _GLOBAL_OFFSET_TABLE_":"=r" (r)); \ -+ r; \ -+}) -+ -+/* Return the link-time address of _DYNAMIC. */ -+static inline ElfW(Addr) -+elf_machine_dynamic (void) -+{ -+ return _GLOBAL_OFFSET_TABLE_[0]; -+} -+ -+#define STRINGXP(X) __STRING (X) -+#define STRINGXV(X) STRINGV_ (X) -+#define STRINGV_(...) # __VA_ARGS__ -+ -+/* Return the run-time load address of the shared object. */ -+static inline ElfW(Addr) -+elf_machine_load_address (void) -+{ -+ ElfW(Addr) got_linktime_addr; -+ asm ( -+ "la.got %0, _GLOBAL_OFFSET_TABLE_" -+ /* Link-time address in GOT entry before runtime relocation */ -+ : "=r" (got_linktime_addr) -+ ); -+ return (ElfW(Addr))_GLOBAL_OFFSET_TABLE_ - got_linktime_addr; -+} -+ -+/* Initial entry point code for the dynamic linker. -+ The C function `_dl_start' is the real entry point; -+ its return value is the user program's entry point. */ -+ -+#define RTLD_START asm (\ -+ ".text\n\ -+ " _RTLD_PROLOGUE (ENTRY_POINT) "\ -+ .cfi_label .Ldummy\n\ -+ " CFI_UNDEFINED (1) "\n\ -+ or $a0, $sp, $zero\n\ -+ bl _dl_start\n\ -+ # Stash user entry point in s0.\n\ -+ or $s0, $v0, $zero\n\ -+ # See if we were run as a command with the executable file\n\ -+ # name as an extra leading argument.\n\ -+ la $a0, _dl_skip_args\n\ -+ ld.w $a0, $a0, 0\n\ -+ # Load the original argument count.\n\ -+ ld.d $a1, $sp, 0\n\ -+ # Subtract _dl_skip_args from it.\n\ -+ sub.d $a1, $a1, $a0\n\ -+ # Adjust the stack pointer to skip _dl_skip_args words.\n\ -+ slli.d $a0, $a0, 3\n\ -+ add.d $sp, $sp, $a0\n\ -+ # Save back the modified argument count.\n\ -+ st.d $a1, $sp, 0\n\ -+ # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env) \n\ -+ la $a0, _rtld_local\n\ -+ ld.d $a0, $a0, 0\n\ -+ addi.d $a2, $sp, 8\n\ -+ slli.d $a3, $a1, 3\n\ -+ add.d $a3, $a3, $a2\n\ -+ addi.d $a3, $a3, 8\n\ -+ # Adjust $sp for 16-aligned\n\ -+ srli.d $t0, $sp, 4\n\ -+ slli.d $t0, $t0, 4\n\ -+ ori $t1, $sp, 0\n\ -+ addi.d $sp, $t0, -32\n\ -+ st.d $t1, $sp, 24\n\ -+ # Call the function to run the initializers.\n\ -+ bl _dl_init\n\ -+ # Pass our finalizer function to _start.\n\ -+ ld.d $sp, $sp, 24\n\ -+ la $a0, _dl_fini\n\ -+ # Jump to the user entry point.\n\ -+ jirl $zero, $s0, 0\n\ -+ " _RTLD_EPILOGUE (ENTRY_POINT) "\ -+ .previous" \ -+); -+ -+/* Names of the architecture-specific auditing callback functions. */ -+#define ARCH_LA_PLTENTER loongarch_gnu_pltenter -+#define ARCH_LA_PLTEXIT loongarch_gnu_pltexit -+ -+/* Bias .got.plt entry by the offset requested by the PLT header. */ -+#define elf_machine_plt_value(map, reloc, value) (value) -+ -+static inline ElfW(Addr) -+elf_machine_fixup_plt (struct link_map *map, lookup_t t, -+ const ElfW(Sym) *refsym, const ElfW(Sym) *sym, -+ const ElfW(Rela) *reloc, -+ ElfW(Addr) *reloc_addr, ElfW(Addr) value) -+{ -+ return *reloc_addr = value; -+} -+ -+#endif /* !dl_machine_h */ -+ -+#ifdef RESOLVE_MAP -+ -+/* Perform a relocation described by R_INFO at the location pointed to -+ by RELOC_ADDR. SYM is the relocation symbol specified by R_INFO and -+ MAP is the object containing the reloc. */ -+ -+auto inline void -+__attribute__ ((always_inline)) -+elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, -+ const ElfW(Sym) *sym, const struct r_found_version *version, -+ void *const reloc_addr, int skip_ifunc) -+{ -+ ElfW(Addr) r_info = reloc->r_info; -+ const unsigned long int r_type = ELFW (R_TYPE) (r_info); -+ ElfW(Addr) *addr_field = (ElfW(Addr) *) reloc_addr; -+ const ElfW(Sym) *const __attribute__ ((unused)) refsym = sym; -+ struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); -+ ElfW(Addr) value = 0; -+ if (sym_map != NULL) -+ value = SYMBOL_ADDRESS (sym_map, sym, true) + reloc->r_addend; -+ -+ if (sym != NULL -+ && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0) -+ && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1) -+ && __builtin_expect (!skip_ifunc, 1)) -+ value = ((ElfW(Addr) (*) (int)) value) (GLRO(dl_hwcap)); -+ -+ switch (r_type) -+ { -+#ifndef RTLD_BOOTSTRAP -+ case __WORDSIZE == 64 ? R_LARCH_TLS_DTPMOD64 : R_LARCH_TLS_DTPMOD32: -+ if (sym_map) -+ *addr_field = sym_map->l_tls_modid; -+ break; -+ -+ case __WORDSIZE == 64 ? R_LARCH_TLS_DTPREL64 : R_LARCH_TLS_DTPREL32: -+ if (sym != NULL) -+ *addr_field = TLS_DTPREL_VALUE (sym) + reloc->r_addend; -+ break; -+ -+ case __WORDSIZE == 64 ? R_LARCH_TLS_TPREL64 : R_LARCH_TLS_TPREL32: -+ if (sym != NULL) -+ { -+ CHECK_STATIC_TLS (map, sym_map); -+ *addr_field = TLS_TPREL_VALUE (sym_map, sym) + reloc->r_addend; -+ } -+ break; -+ -+ case R_LARCH_COPY: -+ { -+ if (__glibc_unlikely (sym == NULL)) -+ /* This can happen in trace mode if an object could not be -+ found. */ -+ break; -+ -+ /* Handle TLS copy relocations. */ -+ if (__glibc_unlikely (ELFW (ST_TYPE) (sym->st_info) == STT_TLS)) -+ { -+ /* There's nothing to do if the symbol is in .tbss. */ -+ if (__glibc_likely (sym->st_value >= sym_map->l_tls_initimage_size)) -+ break; -+ value += (ElfW(Addr)) sym_map->l_tls_initimage - sym_map->l_addr; -+ } -+ -+ size_t size = sym->st_size; -+ if (__glibc_unlikely (sym->st_size != refsym->st_size)) -+ { -+ const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); -+ if (sym->st_size > refsym->st_size) -+ size = refsym->st_size; -+ if (sym->st_size > refsym->st_size || GLRO(dl_verbose)) -+ _dl_error_printf ("\ -+ %s: Symbol `%s' has different size in shared object, consider re-linking\n", -+ rtld_progname ?: "", -+ strtab + refsym->st_name); -+ } -+ -+ memcpy (reloc_addr, (void *)value, size); -+ break; -+ } -+#endif -+ -+#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC -+ case R_LARCH_RELATIVE: -+ { -+# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC -+ /* This is defined in rtld.c, but nowhere in the static libc.a; -+ make the reference weak so static programs can still link. -+ This declaration cannot be done when compiling rtld.c -+ (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the -+ common defn for _dl_rtld_map, which is incompatible with a -+ weak decl in the same file. */ -+# ifndef SHARED -+ weak_extern (GL(dl_rtld_map)); -+# endif -+ if (map != &GL(dl_rtld_map)) /* Already done in rtld itself. */ -+# endif -+ *addr_field = map->l_addr + reloc->r_addend; -+ break; -+ } -+#endif -+ -+ case R_LARCH_JUMP_SLOT: -+ case __WORDSIZE == 64 ? R_LARCH_64 : R_LARCH_32: -+ *addr_field = value; -+ break; -+ -+ case R_LARCH_IRELATIVE: -+ value = map->l_addr + reloc->r_addend; -+ value = ((ElfW(Addr) (*) (void)) value) (); -+ *addr_field = value; -+ break; -+ -+ case R_LARCH_NONE: -+ break; -+ -+ default: -+ _dl_reloc_bad_type (map, r_type, 0); -+ break; -+ } -+} -+ -+auto inline void -+__attribute__ ((always_inline)) -+elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc, -+ void *const reloc_addr) -+{ -+ *(ElfW(Addr) *) reloc_addr = l_addr + reloc->r_addend; -+} -+ -+auto inline void -+__attribute__ ((always_inline)) -+elf_machine_lazy_rel (struct link_map *map, ElfW(Addr) l_addr, -+ const ElfW(Rela) *reloc, int skip_ifunc) -+{ -+ ElfW(Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset); -+ const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info); -+ -+ /* Check for unexpected PLT reloc type. */ -+ if (__glibc_likely (r_type == R_LARCH_JUMP_SLOT)) -+ { -+ if (__glibc_unlikely (map->l_mach.plt == 0)) -+ { -+ if (l_addr) -+ *reloc_addr += l_addr; -+ } -+ else -+ *reloc_addr = map->l_mach.plt; -+ } -+ else if (__glibc_unlikely (r_type == R_LARCH_IRELATIVE)) -+ { -+ ElfW(Addr) *value = (void *) (l_addr + reloc->r_addend); -+ if (__glibc_likely (!skip_ifunc)) -+ value = (ElfW(Addr) *)((ElfW(Addr) (*) (void)) value) (); -+ *reloc_addr = (ElfW(Addr))value; -+ } -+ else -+ _dl_reloc_bad_type (map, r_type, 1); -+} -+ -+/* Set up the loaded object described by L so its stub function -+ will jump to the on-demand fixup code __dl_runtime_resolve. */ -+ -+auto inline int -+__attribute__ ((always_inline)) -+elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) -+{ -+#ifndef RTLD_BOOTSTRAP -+ /* If using PLTs, fill in the first two entries of .got.plt. */ -+ if (l->l_info[DT_JMPREL]) -+ { -+ extern void _dl_runtime_resolve (void) __attribute__ ((visibility ("hidden"))); -+ ElfW(Addr) *gotplt = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]); -+ /* If a library is prelinked but we have to relocate anyway, -+ we have to be able to undo the prelinking of .got.plt. -+ The prelinker saved the address of .plt for us here. */ -+ if (gotplt[1]) -+ l->l_mach.plt = gotplt[1] + l->l_addr; -+ gotplt[0] = (ElfW(Addr)) &_dl_runtime_resolve; -+ gotplt[1] = (ElfW(Addr)) l; -+ } -+#endif -+ -+ return lazy; -+} -+ -+#endif /* RESOLVE_MAP */ -diff --git a/sysdeps/loongarch/dl-tls.h b/sysdeps/loongarch/dl-tls.h -new file mode 100644 -index 00000000..70110c50 ---- /dev/null -+++ b/sysdeps/loongarch/dl-tls.h -@@ -0,0 +1,49 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+ -+/* Type used for the representation of TLS information in the GOT. */ -+typedef struct -+{ -+ unsigned long int ti_module; -+ unsigned long int ti_offset; -+} tls_index; -+ -+/* The thread pointer points to the first static TLS block. */ -+#define TLS_TP_OFFSET 0 -+ -+/* Dynamic thread vector pointers point 0x800 past the start of each -+ TLS block. */ -+//#define TLS_DTV_OFFSET 0x800 -+#define TLS_DTV_OFFSET 0 -+ -+/* Compute the value for a GOTTPREL reloc. */ -+#define TLS_TPREL_VALUE(sym_map, sym) \ -+ ((sym_map)->l_tls_offset + (sym)->st_value - TLS_TP_OFFSET) -+ -+/* Compute the value for a DTPREL reloc. */ -+#define TLS_DTPREL_VALUE(sym) \ -+ ((sym)->st_value - TLS_DTV_OFFSET) -+ -+extern void *__tls_get_addr (tls_index *ti); -+ -+#define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET) -+#define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET) -+ -+/* Value used for dtv entries for which the allocation is delayed. */ -+#define TLS_DTV_UNALLOCATED ((void *) -1l) -diff --git a/sysdeps/loongarch/dl-trampoline.S b/sysdeps/loongarch/dl-trampoline.S -new file mode 100644 -index 00000000..1f4689e0 ---- /dev/null -+++ b/sysdeps/loongarch/dl-trampoline.S -@@ -0,0 +1,108 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+ -+/* Assembler veneer called from the PLT header code for lazy loading. -+ The PLT header passes its own args in t0-t2. */ -+ -+#ifdef __loongarch_soft_float -+# define FRAME_SIZE (-((-10 * SZREG) & ALMASK)) -+#else -+# define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK)) -+#endif -+ -+ENTRY (_dl_runtime_resolve) -+ # Save arguments to stack. -+ -+#ifdef __loongarch64 -+ addi.d sp, sp, -FRAME_SIZE -+#elif defined __loongarch32 -+ addi.w sp, sp, -FRAME_SIZE -+#endif -+ -+ REG_S ra, sp, 9*SZREG -+ REG_S a0, sp, 1*SZREG -+ REG_S a1, sp, 2*SZREG -+ REG_S a2, sp, 3*SZREG -+ REG_S a3, sp, 4*SZREG -+ REG_S a4, sp, 5*SZREG -+ REG_S a5, sp, 6*SZREG -+ REG_S a6, sp, 7*SZREG -+ REG_S a7, sp, 8*SZREG -+ -+#ifndef __loongarch_soft_float -+ FREG_S fa0, sp, 10*SZREG + 0*SZFREG -+ FREG_S fa1, sp, 10*SZREG + 1*SZFREG -+ FREG_S fa2, sp, 10*SZREG + 2*SZFREG -+ FREG_S fa3, sp, 10*SZREG + 3*SZFREG -+ FREG_S fa4, sp, 10*SZREG + 4*SZFREG -+ FREG_S fa5, sp, 10*SZREG + 5*SZFREG -+ FREG_S fa6, sp, 10*SZREG + 6*SZFREG -+ FREG_S fa7, sp, 10*SZREG + 7*SZFREG -+#endif -+ -+ # Update .got.plt and obtain runtime address of callee. -+#ifdef __loongarch64 -+ slli.d a1, t1, 1 -+ or a0, t0, zero -+ add.d a1, a1, t1 -+ la a2, _dl_fixup -+ jirl ra, a2, 0 -+ or t1, v0, zero -+#elif defined __loongarch32 -+ slli.w a1, t1, 1 -+ or a0, t0, zero -+ add.w a1, a1, t1 -+ la a2, _dl_fixup -+ jirl ra, a2, 0 -+ or t1, v0, zero -+#endif -+ -+ # Restore arguments from stack. -+ REG_L ra, sp, 9*SZREG -+ REG_L a0, sp, 1*SZREG -+ REG_L a1, sp, 2*SZREG -+ REG_L a2, sp, 3*SZREG -+ REG_L a3, sp, 4*SZREG -+ REG_L a4, sp, 5*SZREG -+ REG_L a5, sp, 6*SZREG -+ REG_L a6, sp, 7*SZREG -+ REG_L a7, sp, 8*SZREG -+ -+#ifndef __loongarch_soft_float -+ FREG_L fa0, sp, 10*SZREG + 0*SZFREG -+ FREG_L fa1, sp, 10*SZREG + 1*SZFREG -+ FREG_L fa2, sp, 10*SZREG + 2*SZFREG -+ FREG_L fa3, sp, 10*SZREG + 3*SZFREG -+ FREG_L fa4, sp, 10*SZREG + 4*SZFREG -+ FREG_L fa5, sp, 10*SZREG + 5*SZFREG -+ FREG_L fa6, sp, 10*SZREG + 6*SZFREG -+ FREG_L fa7, sp, 10*SZREG + 7*SZFREG -+#endif -+ -+#ifdef __loongarch64 -+ addi.d sp, sp, FRAME_SIZE -+#elif defined __loongarch32 -+ addi.w sp, sp, FRAME_SIZE -+#endif -+ -+ # Invoke the callee. -+ jirl zero, t1, 0 -+END (_dl_runtime_resolve) -diff --git a/sysdeps/loongarch/e_sqrtl.c b/sysdeps/loongarch/e_sqrtl.c -new file mode 100644 -index 00000000..65ae7ad8 ---- /dev/null -+++ b/sysdeps/loongarch/e_sqrtl.c -@@ -0,0 +1,39 @@ -+/* long double square root in software floating-point emulation. -+ Copyright (C) 1997-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Richard Henderson (rth@cygnus.com) and -+ Jakub Jelinek (jj@ultra.linux.cz). -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+#include -+ -+long double -+__ieee754_sqrtl (const long double a) -+{ -+ FP_DECL_EX; -+ FP_DECL_Q(A); FP_DECL_Q(C); -+ long double c; -+ -+ FP_INIT_ROUNDMODE; -+ FP_UNPACK_Q(A, a); -+ FP_SQRT_Q(C, A); -+ FP_PACK_Q(c, C); -+ FP_HANDLE_EXCEPTIONS; -+ return c; -+} -+strong_alias (__ieee754_sqrtl, __sqrtl_finite) -diff --git a/sysdeps/loongarch/elf-init.c b/sysdeps/loongarch/elf-init.c -new file mode 100644 -index 00000000..5f261a9d ---- /dev/null -+++ b/sysdeps/loongarch/elf-init.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/fpu/e_sqrt.c b/sysdeps/loongarch/fpu/e_sqrt.c -new file mode 100644 -index 00000000..dac8696a ---- /dev/null -+++ b/sysdeps/loongarch/fpu/e_sqrt.c -@@ -0,0 +1,29 @@ -+/* Copyright (C) 2002-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Hartvig Ekner , 2002. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+ -+ -+double -+__ieee754_sqrt (double x) -+{ -+ double z; -+ __asm__ ("fsqrt.d %0,%1" : "=f" (z) : "f" (x)); -+ return z; -+} -+strong_alias (__ieee754_sqrt, __sqrt_finite) -+ -diff --git a/sysdeps/loongarch/fpu/e_sqrtf.c b/sysdeps/loongarch/fpu/e_sqrtf.c -new file mode 100644 -index 00000000..706c0494 ---- /dev/null -+++ b/sysdeps/loongarch/fpu/e_sqrtf.c -@@ -0,0 +1,28 @@ -+/* Copyright (C) 2002-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Hartvig Ekner , 2002. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+ -+ -+float -+__ieee754_sqrtf (float x) -+{ -+ float z; -+ __asm__ ("fsqrt.s %0,%1" : "=f" (z) : "f" (x)); -+ return z; -+} -+strong_alias (__ieee754_sqrtf, __sqrtf_finite) -diff --git a/sysdeps/loongarch/fpu/fclrexcpt.c b/sysdeps/loongarch/fpu/fclrexcpt.c -new file mode 100644 -index 00000000..51310d93 ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fclrexcpt.c -@@ -0,0 +1,47 @@ -+/* Clear given exceptions in current floating-point environment. -+ Copyright (C) 1998-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger , 1998. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+#include -+ -+int -+feclearexcept (int excepts) -+{ -+ int cw; -+ -+ /* Mask out unsupported bits/exceptions. */ -+ excepts &= FE_ALL_EXCEPT; -+ -+ /* Read the complete control word. */ -+ _FPU_GETCW (cw); -+ -+ /* Clear exception flag bits and cause bits. If the cause bit is not -+ cleared, the next CTC instruction (just below) will re-generate the -+ exception. */ -+ -+ cw &= ~(excepts | (excepts << CAUSE_SHIFT)); -+ -+ /* Put the new data in effect. */ -+ _FPU_SETCW (cw); -+ -+ /* Success. */ -+ return 0; -+} -+libm_hidden_def (feclearexcept) -diff --git a/sysdeps/loongarch/fpu/fedisblxcpt.c b/sysdeps/loongarch/fpu/fedisblxcpt.c -new file mode 100644 -index 00000000..004b0ecb ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fedisblxcpt.c -@@ -0,0 +1,40 @@ -+/* Disable floating-point exceptions. -+ Copyright (C) 2000-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger , 2000. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+#include -+ -+int -+fedisableexcept (int excepts) -+{ -+ unsigned int new_exc, old_exc; -+ -+ /* Get the current control word. */ -+ _FPU_GETCW (new_exc); -+ -+ old_exc = (new_exc & ENABLE_MASK) << ENABLE_SHIFT; -+ -+ excepts &= FE_ALL_EXCEPT; -+ -+ new_exc &= ~(excepts >> ENABLE_SHIFT); -+ _FPU_SETCW (new_exc); -+ -+ return old_exc; -+} -diff --git a/sysdeps/loongarch/fpu/feenablxcpt.c b/sysdeps/loongarch/fpu/feenablxcpt.c -new file mode 100644 -index 00000000..b8f56625 ---- /dev/null -+++ b/sysdeps/loongarch/fpu/feenablxcpt.c -@@ -0,0 +1,40 @@ -+/* Enable floating-point exceptions. -+ Copyright (C) 2000-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger , 2000. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+#include -+ -+int -+feenableexcept (int excepts) -+{ -+ unsigned int new_exc, old_exc; -+ -+ /* Get the current control word. */ -+ _FPU_GETCW (new_exc); -+ -+ old_exc = (new_exc & ENABLE_MASK) << ENABLE_SHIFT; -+ -+ excepts &= FE_ALL_EXCEPT; -+ -+ new_exc |= excepts >> ENABLE_SHIFT; -+ _FPU_SETCW (new_exc); -+ -+ return old_exc; -+} -diff --git a/sysdeps/loongarch/fpu/fegetenv.c b/sysdeps/loongarch/fpu/fegetenv.c -new file mode 100644 -index 00000000..8e8fa2c5 ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fegetenv.c -@@ -0,0 +1,33 @@ -+/* Store current floating-point environment. -+ Copyright (C) 1998-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger , 1998. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+ -+int -+__fegetenv (fenv_t *envp) -+{ -+ _FPU_GETCW (*envp); -+ -+ /* Success. */ -+ return 0; -+} -+libm_hidden_def (__fegetenv) -+weak_alias (__fegetenv, fegetenv) -+libm_hidden_weak (fegetenv) -diff --git a/sysdeps/loongarch/fpu/fegetexcept.c b/sysdeps/loongarch/fpu/fegetexcept.c -new file mode 100644 -index 00000000..2c0a1208 ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fegetexcept.c -@@ -0,0 +1,33 @@ -+/* Get enabled floating-point exceptions. -+ Copyright (C) 2000-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger , 2000. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+#include -+ -+int -+fegetexcept (void) -+{ -+ unsigned int exc; -+ -+ /* Get the current control word. */ -+ _FPU_GETCW (exc); -+ -+ return (exc & ENABLE_MASK) << ENABLE_SHIFT; -+} -diff --git a/sysdeps/loongarch/fpu/fegetmode.c b/sysdeps/loongarch/fpu/fegetmode.c -new file mode 100644 -index 00000000..e0a5180f ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fegetmode.c -@@ -0,0 +1,27 @@ -+/* Store current floating-point control modes. MIPS version. -+ Copyright (C) 2016-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+#include -+ -+int -+fegetmode (femode_t *modep) -+{ -+ _FPU_GETCW (*modep); -+ return 0; -+} -diff --git a/sysdeps/loongarch/fpu/fegetround.c b/sysdeps/loongarch/fpu/fegetround.c -new file mode 100644 -index 00000000..a7ac444a ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fegetround.c -@@ -0,0 +1,35 @@ -+/* Return current rounding direction. -+ Copyright (C) 1998-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger , 1998. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+ -+int -+__fegetround (void) -+{ -+ int cw; -+ -+ /* Get control word. */ -+ _FPU_GETCW (cw); -+ -+ return cw & _FPU_RC_MASK; -+} -+libm_hidden_def (__fegetround) -+weak_alias (__fegetround, fegetround) -+libm_hidden_weak (fegetround) -diff --git a/sysdeps/loongarch/fpu/feholdexcpt.c b/sysdeps/loongarch/fpu/feholdexcpt.c -new file mode 100644 -index 00000000..eb9d4764 ---- /dev/null -+++ b/sysdeps/loongarch/fpu/feholdexcpt.c -@@ -0,0 +1,41 @@ -+/* Store current floating-point environment and clear exceptions. -+ Copyright (C) 2000-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger , 2000. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+ -+int -+__feholdexcept (fenv_t *envp) -+{ -+ fpu_control_t cw; -+ -+ /* Save the current state. */ -+ _FPU_GETCW (cw); -+ envp->__fp_control_register = cw; -+ -+ /* Clear all exception enable bits and flags. */ -+ cw &= ~(_FPU_MASK_V|_FPU_MASK_Z|_FPU_MASK_O|_FPU_MASK_U|_FPU_MASK_I|FE_ALL_EXCEPT); -+ _FPU_SETCW (cw); -+ -+ return 0; -+} -+ -+libm_hidden_def (__feholdexcept) -+weak_alias (__feholdexcept, feholdexcept) -+libm_hidden_weak (feholdexcept) -diff --git a/sysdeps/loongarch/fpu/fenv_libc.h b/sysdeps/loongarch/fpu/fenv_libc.h -new file mode 100644 -index 00000000..f5dd1678 ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fenv_libc.h -@@ -0,0 +1,31 @@ -+/* Copyright (C) 2000-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger . -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _FENV_LIBC_H -+#define _FENV_LIBC_H 1 -+ -+/* Mask for enabling exceptions and for the CAUSE bits. */ -+#define ENABLE_MASK 0x0000001FU -+#define CAUSE_MASK 0x1F000000U -+ -+/* Shift for FE_* flags to get up to the ENABLE bits and the CAUSE bits. */ -+#define ENABLE_SHIFT 16 -+#define CAUSE_SHIFT 8 -+ -+ -+#endif /* _FENV_LIBC_H */ -diff --git a/sysdeps/loongarch/fpu/fesetenv.c b/sysdeps/loongarch/fpu/fesetenv.c -new file mode 100644 -index 00000000..8dee8782 ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fesetenv.c -@@ -0,0 +1,44 @@ -+/* Install given floating-point environment. -+ Copyright (C) 1998-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger , 1998. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+ -+int -+__fesetenv (const fenv_t *envp) -+{ -+ fpu_control_t cw; -+ -+ /* Read first current state to flush fpu pipeline. */ -+ _FPU_GETCW (cw); -+ -+ if (envp == FE_DFL_ENV) -+ _FPU_SETCW (_FPU_DEFAULT); -+ else if (envp == FE_NOMASK_ENV) -+ _FPU_SETCW (_FPU_IEEE); -+ else -+ _FPU_SETCW (envp->__fp_control_register); -+ -+ /* Success. */ -+ return 0; -+} -+ -+libm_hidden_def (__fesetenv) -+weak_alias (__fesetenv, fesetenv) -+libm_hidden_weak (fesetenv) -diff --git a/sysdeps/loongarch/fpu/fesetexcept.c b/sysdeps/loongarch/fpu/fesetexcept.c -new file mode 100644 -index 00000000..d14febca ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fesetexcept.c -@@ -0,0 +1,32 @@ -+/* Set given exception flags. MIPS version. -+ Copyright (C) 2016-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+#include -+ -+int -+fesetexcept (int excepts) -+{ -+ fpu_control_t temp; -+ -+ _FPU_GETCW (temp); -+ temp |= excepts & FE_ALL_EXCEPT; -+ _FPU_SETCW (temp); -+ -+ return 0; -+} -diff --git a/sysdeps/loongarch/fpu/fesetmode.c b/sysdeps/loongarch/fpu/fesetmode.c -new file mode 100644 -index 00000000..8cc5d0b1 ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fesetmode.c -@@ -0,0 +1,38 @@ -+/* Install given floating-point control modes. MIPS version. -+ Copyright (C) 2016-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+#include -+ -+#define FCSR_STATUS 0x1f1f0000 -+ -+int -+fesetmode (const femode_t *modep) -+{ -+ fpu_control_t cw; -+ -+ _FPU_GETCW (cw); -+ cw &= FCSR_STATUS; -+ if (modep == FE_DFL_MODE) -+ cw |= _FPU_DEFAULT; -+ else -+ cw |= *modep & ~FCSR_STATUS; -+ _FPU_SETCW (cw); -+ -+ return 0; -+} -diff --git a/sysdeps/loongarch/fpu/fesetround.c b/sysdeps/loongarch/fpu/fesetround.c -new file mode 100644 -index 00000000..31fdeab3 ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fesetround.c -@@ -0,0 +1,46 @@ -+/* Set current rounding direction. -+ Copyright (C) 1998-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger , 1998. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+ -+int -+__fesetround (int round) -+{ -+ fpu_control_t cw; -+ -+ if ((round & ~_FPU_RC_MASK) != 0) -+ /* ROUND is no valid rounding mode. */ -+ return 1; -+ -+ /* Get current state. */ -+ _FPU_GETCW (cw); -+ -+ /* Set rounding bits. */ -+ cw &= ~_FPU_RC_MASK; -+ cw |= round; -+ /* Set new state. */ -+ _FPU_SETCW (cw); -+ -+ return 0; -+} -+ -+libm_hidden_def (__fesetround) -+weak_alias (__fesetround, fesetround) -+libm_hidden_weak (fesetround) -diff --git a/sysdeps/loongarch/fpu/feupdateenv.c b/sysdeps/loongarch/fpu/feupdateenv.c -new file mode 100644 -index 00000000..669bfc3c ---- /dev/null -+++ b/sysdeps/loongarch/fpu/feupdateenv.c -@@ -0,0 +1,45 @@ -+/* Install given floating-point environment and raise exceptions. -+ Copyright (C) 1998-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger , 1998. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+ -+int -+__feupdateenv (const fenv_t *envp) -+{ -+ int temp; -+ -+ /* Save current exceptions. */ -+ _FPU_GETCW (temp); -+ temp &= FE_ALL_EXCEPT; -+ -+ /* Install new environment. */ -+ __fesetenv (envp); -+ -+ /* Raise the safed exception. Incidently for us the implementation -+ defined format of the values in objects of type fexcept_t is the -+ same as the ones specified using the FE_* constants. */ -+ __feraiseexcept (temp); -+ -+ /* Success. */ -+ return 0; -+} -+libm_hidden_def (__feupdateenv) -+weak_alias (__feupdateenv, feupdateenv) -+libm_hidden_weak (feupdateenv) -diff --git a/sysdeps/loongarch/fpu/fgetexcptflg.c b/sysdeps/loongarch/fpu/fgetexcptflg.c -new file mode 100644 -index 00000000..1e594e14 ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fgetexcptflg.c -@@ -0,0 +1,39 @@ -+/* Store current representation for exceptions. -+ Copyright (C) 1998-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger , 1998. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+ -+int -+fegetexceptflag (fexcept_t *flagp, int excepts) -+{ -+ fpu_control_t temp; -+ -+ /* Get the current exceptions. */ -+ _FPU_GETCW (temp); -+ -+ /* We only save the relevant bits here. In particular, care has to be -+ taken with the CAUSE bits, as an inadvertent restore later on could -+ generate unexpected exceptions. */ -+ -+ *flagp = temp & excepts & FE_ALL_EXCEPT; -+ -+ /* Success. */ -+ return 0; -+} -diff --git a/sysdeps/loongarch/fpu/fraiseexcpt.c b/sysdeps/loongarch/fpu/fraiseexcpt.c -new file mode 100644 -index 00000000..2eec053a ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fraiseexcpt.c -@@ -0,0 +1,84 @@ -+/* Raise given exceptions. -+ Copyright (C) 2000-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger , 2000. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+#include -+ -+int -+__feraiseexcept (int excepts) -+{ -+ -+ const float fp_zero = 0.0, fp_one = 1.0, fp_max = FLT_MAX, -+ fp_min = FLT_MIN, fp_1e32 = 1.0e32f, fp_two = 2.0, -+ fp_three = 3.0; -+ -+ /* Raise exceptions represented by EXPECTS. But we must raise only -+ one signal at a time. It is important that if the overflow/underflow -+ exception and the inexact exception are given at the same time, -+ the overflow/underflow exception follows the inexact exception.*/ -+ -+ /* First: invalid exception. */ -+ if (FE_INVALID & excepts) -+ __asm__ __volatile__ ( -+ "fdiv.s $f0,%0,%0\n\t" -+ : -+ : "f" (fp_zero) -+ :"$f0"); -+ -+ /* Next: division by zero. */ -+ if (FE_DIVBYZERO & excepts) -+ __asm__ __volatile__ ( -+ "fdiv.s $f0,%0,%1\n\t" -+ : -+ : "f" (fp_one), "f" (fp_zero) -+ :"$f0"); -+ -+ /* Next: overflow. */ -+ if (FE_OVERFLOW & excepts) -+ /* There's no way to raise overflow without also raising inexact. */ -+ __asm__ __volatile__ ( -+ "fadd.s $f0,%0,%1\n\t" -+ : -+ : "f" (fp_max), "f" (fp_1e32) -+ : "$f0"); -+ -+ /* Next: underflow. */ -+ if (FE_UNDERFLOW & excepts) -+ __asm__ __volatile__ ( -+ "fdiv.s $f0,%0,%1\n\t" -+ : -+ : "f" (fp_min), "f" (fp_three) -+ : "$f0"); -+ -+ /* Last: inexact. */ -+ if (FE_INEXACT & excepts) -+ __asm__ __volatile__ ( -+ "fdiv.s $f0, %0, %1\n\t" -+ : -+ : "f" (fp_two), "f" (fp_three) -+ : "$f0"); -+ -+ /* Success. */ -+ return 0; -+} -+ -+libm_hidden_def (__feraiseexcept) -+weak_alias (__feraiseexcept, feraiseexcept) -+libm_hidden_weak (feraiseexcept) -diff --git a/sysdeps/loongarch/fpu/fsetexcptflg.c b/sysdeps/loongarch/fpu/fsetexcptflg.c -new file mode 100644 -index 00000000..dc447a77 ---- /dev/null -+++ b/sysdeps/loongarch/fpu/fsetexcptflg.c -@@ -0,0 +1,42 @@ -+/* Set floating-point environment exception handling. -+ Copyright (C) 1998-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Hartvig Ekner , 2002. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+ -+int -+fesetexceptflag (const fexcept_t *flagp, int excepts) -+{ -+ fpu_control_t temp; -+ -+ /* Get the current exceptions. */ -+ _FPU_GETCW (temp); -+ -+ /* Make sure the flags we want restored are legal. */ -+ excepts &= FE_ALL_EXCEPT; -+ -+ /* Now clear the bits called for, and copy them in from flagp. Note that -+ we ignore all non-flag bits from *flagp, so they don't matter. */ -+ temp = (temp & ~excepts) | (*flagp & excepts); -+ -+ _FPU_SETCW (temp); -+ -+ /* Success. */ -+ return 0; -+} -diff --git a/sysdeps/loongarch/fpu/ftestexcept.c b/sysdeps/loongarch/fpu/ftestexcept.c -new file mode 100644 -index 00000000..fa645b26 ---- /dev/null -+++ b/sysdeps/loongarch/fpu/ftestexcept.c -@@ -0,0 +1,33 @@ -+/* Test exception in current environment. -+ Copyright (C) 1998-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Andreas Jaeger , 1998. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+ -+int -+fetestexcept (int excepts) -+{ -+ int cw; -+ -+ /* Get current control word. */ -+ _FPU_GETCW (cw); -+ -+ return cw & excepts & FE_ALL_EXCEPT; -+} -+libm_hidden_def (fetestexcept) -diff --git a/sysdeps/loongarch/fpu_control.h b/sysdeps/loongarch/fpu_control.h -new file mode 100644 -index 00000000..92474b25 ---- /dev/null -+++ b/sysdeps/loongarch/fpu_control.h -@@ -0,0 +1,111 @@ -+/* FPU control word bits. Mips version. -+ Copyright (C) 1996-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Olaf Flebbe and Ralf Baechle. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _FPU_CONTROL_H -+#define _FPU_CONTROL_H -+ -+/* MIPS FPU floating point control register bits. -+ * -+ * 31-25 -> floating point conditions code bits 7-1. These bits are only -+ * available in MIPS IV. -+ * 24 -> flush denormalized results to zero instead of -+ * causing unimplemented operation exception. This bit is only -+ * available for MIPS III and newer. -+ * 23 -> Condition bit -+ * 22-21 -> reserved for architecture implementers -+ * 20 -> reserved (read as 0, write with 0) -+ * 19 -> IEEE 754-2008 non-arithmetic ABS.fmt and NEG.fmt enable -+ * 18 -> IEEE 754-2008 recommended NaN encoding enable -+ * 17 -> cause bit for unimplemented operation -+ * 28 -> cause bit for invalid exception -+ * 27 -> cause bit for division by zero exception -+ * 26 -> cause bit for overflow exception -+ * 25 -> cause bit for underflow exception -+ * 24 -> cause bit for inexact exception -+ * 4 -> enable exception for invalid exception -+ * 3 -> enable exception for division by zero exception -+ * 2 -> enable exception for overflow exception -+ * 1 -> enable exception for underflow exception -+ * 0 -> enable exception for inexact exception -+ * 20 -> flag invalid exception -+ * 19 -> flag division by zero exception -+ * 18 -> flag overflow exception -+ * 17 -> flag underflow exception -+ * 16 -> flag inexact exception -+ * 9-8 -> rounding control -+ * -+ * -+ * Rounding Control: -+ * 00 - rounding to nearest (RN) -+ * 01 - rounding toward zero (RZ) -+ * 10 - rounding (up) toward plus infinity (RP) -+ * 11 - rounding (down)toward minus infinity (RM) -+ */ -+ -+#include -+ -+#ifdef __loongarch_soft_float -+ -+#define _FPU_RESERVED 0xffffffff -+#define _FPU_DEFAULT 0x00000000 -+typedef unsigned int fpu_control_t; -+#define _FPU_GETCW(cw) (cw) = 0 -+#define _FPU_SETCW(cw) (void) (cw) -+extern fpu_control_t __fpu_control; -+ -+#else /* __loongarch_soft_float */ -+ -+/* Masks for interrupts. */ -+#define _FPU_MASK_V 0x10 /* Invalid operation */ -+#define _FPU_MASK_Z 0x08 /* Division by zero */ -+#define _FPU_MASK_O 0x04 /* Overflow */ -+#define _FPU_MASK_U 0x02 /* Underflow */ -+#define _FPU_MASK_I 0x01 /* Inexact operation */ -+ -+/* Flush denormalized numbers to zero. */ -+#define _FPU_FLUSH_TZ 0x1000000 -+ -+/* Rounding control. */ -+#define _FPU_RC_NEAREST 0x000 /* RECOMMENDED */ -+#define _FPU_RC_ZERO 0x100 -+#define _FPU_RC_UP 0x200 -+#define _FPU_RC_DOWN 0x300 -+/* Mask for rounding control. */ -+#define _FPU_RC_MASK 0x300 -+ -+#define _FPU_RESERVED 0x0 -+ -+#define _FPU_DEFAULT 0x0 -+#define _FPU_IEEE 0x1F -+ -+/* Type of the control word. */ -+typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); -+ -+/* Macros for accessing the hardware control word. */ -+extern fpu_control_t __mips_fpu_getcw (void) __THROW; -+extern void __mips_fpu_setcw (fpu_control_t) __THROW; -+#define _FPU_GETCW(cw) __asm__ volatile ("movfcsr2gr %0,$r0" : "=r" (cw)) -+#define _FPU_SETCW(cw) __asm__ volatile ("movgr2fcsr $r0,%0" : : "r" (cw)) -+ -+/* Default control word set at startup. */ -+extern fpu_control_t __fpu_control; -+ -+#endif /* __loongarch_soft_float */ -+ -+#endif /* fpu_control.h */ -diff --git a/sysdeps/loongarch/fstat.c b/sysdeps/loongarch/fstat.c -new file mode 100644 -index 00000000..c4504eeb ---- /dev/null -+++ b/sysdeps/loongarch/fstat.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/fstat64.c b/sysdeps/loongarch/fstat64.c -new file mode 100644 -index 00000000..143ca2b0 ---- /dev/null -+++ b/sysdeps/loongarch/fstat64.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/fstatat.c b/sysdeps/loongarch/fstatat.c -new file mode 100644 -index 00000000..0b0a3342 ---- /dev/null -+++ b/sysdeps/loongarch/fstatat.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/fstatat64.c b/sysdeps/loongarch/fstatat64.c -new file mode 100644 -index 00000000..e82b9274 ---- /dev/null -+++ b/sysdeps/loongarch/fstatat64.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/gccframe.h b/sysdeps/loongarch/gccframe.h -new file mode 100644 -index 00000000..5c799c64 ---- /dev/null -+++ b/sysdeps/loongarch/gccframe.h -@@ -0,0 +1,21 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#define FIRST_PSEUDO_REGISTER 74 -+ -+#include -diff --git a/sysdeps/loongarch/hp-timing.h b/sysdeps/loongarch/hp-timing.h -new file mode 100644 -index 00000000..2d006540 ---- /dev/null -+++ b/sysdeps/loongarch/hp-timing.h -@@ -0,0 +1,40 @@ -+/* High precision, low overhead timing functions. x86-64 version. -+ Copyright (C) 2002-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#ifndef _HP_TIMING_H -+#define _HP_TIMING_H 1 -+ -+/* We always assume having the timestamp register. */ -+#define HP_TIMING_AVAIL (1) -+#define HP_SMALL_TIMING_AVAIL (1) -+ -+/* We indeed have inlined functions. */ -+#define HP_TIMING_INLINE (1) -+ -+/* We use 64bit values for the times. */ -+typedef unsigned long long int hp_timing_t; -+ -+/* Read the cp0 count, this maybe inaccurate. */ -+#define HP_TIMING_NOW(Var) \ -+ ({ unsigned long long int _count; \ -+ asm volatile ("rdtime.d\t%0,$r0" : "=r" (_count)); \ -+ (Var) = _count; }) -+ -+#include -+ -+#endif /* hp-timing.h */ -diff --git a/sysdeps/loongarch/jmpbuf-offsets.h b/sysdeps/loongarch/jmpbuf-offsets.h -new file mode 100644 -index 00000000..bc4c1523 ---- /dev/null -+++ b/sysdeps/loongarch/jmpbuf-offsets.h -@@ -0,0 +1,23 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public License as -+ published by the Free Software Foundation; either version 2.1 of the -+ License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+ -+/* Helper for generic ____longjmp_chk(). */ -+#define JB_FRAME_ADDRESS(buf) \ -+ ((void *) _jmpbuf_sp (buf)) -diff --git a/sysdeps/loongarch/jmpbuf-unwind.h b/sysdeps/loongarch/jmpbuf-unwind.h -new file mode 100644 -index 00000000..c866d910 ---- /dev/null -+++ b/sysdeps/loongarch/jmpbuf-unwind.h -@@ -0,0 +1,46 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+#include -+#include -+ -+/* Test if longjmp to JMPBUF would unwind the frame -+ containing a local variable at ADDRESS. */ -+#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \ -+ ((void *) (address) < (void *) demangle ((jmpbuf)[0].__sp)) -+ -+#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ -+ _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) -+ -+static inline uintptr_t __attribute__ ((unused)) -+_jmpbuf_sp (__jmp_buf regs) -+{ -+ uintptr_t sp = regs[0].__sp; -+#ifdef PTR_DEMANGLE -+ PTR_DEMANGLE (sp); -+#endif -+ return sp; -+} -+ -+#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ -+ ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj)) -+ -+/* We use the normal longjmp for unwinding. */ -+#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) -diff --git a/sysdeps/loongarch/ldsodefs.h b/sysdeps/loongarch/ldsodefs.h -new file mode 100644 -index 00000000..60b6db58 ---- /dev/null -+++ b/sysdeps/loongarch/ldsodefs.h -@@ -0,0 +1,47 @@ -+/* Run-time dynamic linker data structures for loaded ELF shared objects. -+ Copyright (C) 2011-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _LOONGARCH_LDSODEFS_H -+#define _LOONGARCH_LDSODEFS_H 1 -+ -+#include -+ -+struct La_loongarch_regs; -+struct La_loongarch_retval; -+ -+#define ARCH_PLTENTER_MEMBERS \ -+ ElfW(Addr) (*loongarch_gnu_pltenter) (ElfW(Sym) *, unsigned int, \ -+ uintptr_t *, uintptr_t *, \ -+ const struct La_loongarch_regs *, \ -+ unsigned int *, const char *name, \ -+ long int *framesizep); -+ -+#define ARCH_PLTEXIT_MEMBERS \ -+ unsigned int (*loongarch_gnu_pltexit) (ElfW(Sym) *, unsigned int, \ -+ uintptr_t *, uintptr_t *, \ -+ const struct La_loongarch_regs *, \ -+ struct La_loongarch_retval *, \ -+ const char *); -+ -+/* The LoongArch ABI specifies that the dynamic section has to be read-only. */ -+ -+#define DL_RO_DYN_SECTION 1 -+ -+#include_next -+ -+#endif -diff --git a/sysdeps/loongarch/libc-start.h b/sysdeps/loongarch/libc-start.h -new file mode 100644 -index 00000000..d35ed85f ---- /dev/null -+++ b/sysdeps/loongarch/libc-start.h -@@ -0,0 +1,25 @@ -+ /* X86 definitions for libc main startup. -+ Copyright (C) 2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#ifndef SHARED -+# define ARCH_SETUP_IREL() -+# define ARCH_APPLY_IREL() apply_irel () -+# ifndef ARCH_SETUP_TLS -+# define ARCH_SETUP_TLS() __libc_setup_tls () -+# endif -+#endif /* !SHARED */ -diff --git a/sysdeps/loongarch/libc-tls.c b/sysdeps/loongarch/libc-tls.c -new file mode 100644 -index 00000000..0b0590d1 ---- /dev/null -+++ b/sysdeps/loongarch/libc-tls.c -@@ -0,0 +1,32 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+ -+/* On LoongArch, linker optimizations are not required, so __tls_get_addr -+ can be called even in statically linked binaries. In this case module -+ must be always 1 and PT_TLS segment exist in the binary, otherwise it -+ would not link. */ -+ -+void * -+__tls_get_addr (tls_index *ti) -+{ -+ dtv_t *dtv = THREAD_DTV (); -+ return (char *) dtv[1].pointer.val + GET_ADDR_OFFSET; -+} -diff --git a/sysdeps/loongarch/linkmap.h b/sysdeps/loongarch/linkmap.h -new file mode 100644 -index 00000000..ac170bb3 ---- /dev/null -+++ b/sysdeps/loongarch/linkmap.h -@@ -0,0 +1,4 @@ -+struct link_map_machine -+ { -+ ElfW(Addr) plt; /* Address of .plt. */ -+ }; -diff --git a/sysdeps/loongarch/lp64/Implies-after b/sysdeps/loongarch/lp64/Implies-after -new file mode 100644 -index 00000000..a8cae95f ---- /dev/null -+++ b/sysdeps/loongarch/lp64/Implies-after -@@ -0,0 +1 @@ -+wordsize-64 -diff --git a/sysdeps/loongarch/lp64/libm-test-ulps b/sysdeps/loongarch/lp64/libm-test-ulps -new file mode 100644 -index 00000000..61be2df6 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/libm-test-ulps -@@ -0,0 +1,2206 @@ -+# Begin of automatic generation -+ -+# Maximal error of functions: -+Function: "acos": -+float: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "acos_downward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "acos_towardzero": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "acos_upward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "acosh": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "acosh_downward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "acosh_towardzero": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "acosh_upward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "asin": -+float: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "asin_downward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "asin_towardzero": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "asin_upward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "asinh": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "asinh_downward": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "asinh_towardzero": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "asinh_upward": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "atan": -+float: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "atan2": -+float: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "atan2_downward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "atan2_towardzero": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "atan2_upward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "atan_downward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "atan_towardzero": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "atan_upward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "atanh": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "atanh_downward": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "atanh_towardzero": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "atanh_upward": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "cabs": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "cabs_downward": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "cabs_towardzero": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "cabs_upward": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Real part of "cacos": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "cacos": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "cacos_downward": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "cacos_downward": -+double: 5 -+float: 3 -+idouble: 5 -+ifloat: 3 -+ildouble: 6 -+ldouble: 6 -+ -+Function: Real part of "cacos_towardzero": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "cacos_towardzero": -+double: 4 -+float: 2 -+idouble: 4 -+ifloat: 2 -+ildouble: 5 -+ldouble: 5 -+ -+Function: Real part of "cacos_upward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "cacos_upward": -+double: 5 -+float: 5 -+idouble: 5 -+ifloat: 5 -+ildouble: 7 -+ldouble: 7 -+ -+Function: Real part of "cacosh": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "cacosh": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "cacosh_downward": -+double: 4 -+float: 2 -+idouble: 4 -+ifloat: 2 -+ildouble: 5 -+ldouble: 5 -+ -+Function: Imaginary part of "cacosh_downward": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 4 -+ldouble: 4 -+ -+Function: Real part of "cacosh_towardzero": -+double: 4 -+float: 2 -+idouble: 4 -+ifloat: 2 -+ildouble: 5 -+ldouble: 5 -+ -+Function: Imaginary part of "cacosh_towardzero": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "cacosh_upward": -+double: 4 -+float: 3 -+idouble: 4 -+ifloat: 3 -+ildouble: 6 -+ldouble: 6 -+ -+Function: Imaginary part of "cacosh_upward": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "carg": -+float: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "carg_downward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "carg_towardzero": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "carg_upward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "casin": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "casin": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "casin_downward": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "casin_downward": -+double: 5 -+float: 3 -+idouble: 5 -+ifloat: 3 -+ildouble: 6 -+ldouble: 6 -+ -+Function: Real part of "casin_towardzero": -+double: 3 -+float: 1 -+idouble: 3 -+ifloat: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "casin_towardzero": -+double: 4 -+float: 2 -+idouble: 4 -+ifloat: 2 -+ildouble: 5 -+ldouble: 5 -+ -+Function: Real part of "casin_upward": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "casin_upward": -+double: 5 -+float: 5 -+idouble: 5 -+ifloat: 5 -+ildouble: 7 -+ldouble: 7 -+ -+Function: Real part of "casinh": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "casinh": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "casinh_downward": -+double: 5 -+float: 3 -+idouble: 5 -+ifloat: 3 -+ildouble: 6 -+ldouble: 6 -+ -+Function: Imaginary part of "casinh_downward": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "casinh_towardzero": -+double: 4 -+float: 2 -+idouble: 4 -+ifloat: 2 -+ildouble: 5 -+ldouble: 5 -+ -+Function: Imaginary part of "casinh_towardzero": -+double: 3 -+float: 1 -+idouble: 3 -+ifloat: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "casinh_upward": -+double: 5 -+float: 5 -+idouble: 5 -+ifloat: 5 -+ildouble: 7 -+ldouble: 7 -+ -+Function: Imaginary part of "casinh_upward": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "catan": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Imaginary part of "catan": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Real part of "catan_downward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "catan_downward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "catan_towardzero": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "catan_towardzero": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "catan_upward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "catan_upward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "catanh": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Imaginary part of "catanh": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Real part of "catanh_downward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "catanh_downward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "catanh_towardzero": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "catanh_towardzero": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "catanh_upward": -+double: 4 -+float: 4 -+idouble: 4 -+ifloat: 4 -+ildouble: 4 -+ldouble: 4 -+ -+Function: Imaginary part of "catanh_upward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "cbrt": -+double: 3 -+float: 1 -+idouble: 3 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "cbrt_downward": -+double: 4 -+float: 1 -+idouble: 4 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "cbrt_towardzero": -+double: 3 -+float: 1 -+idouble: 3 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "cbrt_upward": -+double: 5 -+float: 1 -+idouble: 5 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Real part of "ccos": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Imaginary part of "ccos": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Real part of "ccos_downward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "ccos_downward": -+double: 2 -+float: 3 -+idouble: 2 -+ifloat: 3 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "ccos_towardzero": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "ccos_towardzero": -+double: 2 -+float: 3 -+idouble: 2 -+ifloat: 3 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "ccos_upward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "ccos_upward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "ccosh": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Imaginary part of "ccosh": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Real part of "ccosh_downward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "ccosh_downward": -+double: 2 -+float: 3 -+idouble: 2 -+ifloat: 3 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "ccosh_towardzero": -+double: 1 -+float: 3 -+idouble: 1 -+ifloat: 3 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "ccosh_towardzero": -+double: 2 -+float: 3 -+idouble: 2 -+ifloat: 3 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "ccosh_upward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "ccosh_upward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "cexp": -+double: 2 -+float: 1 -+idouble: 2 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Imaginary part of "cexp": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Real part of "cexp_downward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "cexp_downward": -+double: 1 -+float: 3 -+idouble: 1 -+ifloat: 3 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "cexp_towardzero": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "cexp_towardzero": -+double: 1 -+float: 3 -+idouble: 1 -+ifloat: 3 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "cexp_upward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "cexp_upward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "clog": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "clog": -+float: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Real part of "clog10": -+double: 3 -+float: 4 -+idouble: 3 -+ifloat: 4 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "clog10": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "clog10_downward": -+double: 5 -+float: 5 -+idouble: 5 -+ifloat: 5 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "clog10_downward": -+double: 2 -+float: 4 -+idouble: 2 -+ifloat: 4 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "clog10_towardzero": -+double: 5 -+float: 5 -+idouble: 5 -+ifloat: 5 -+ildouble: 4 -+ldouble: 4 -+ -+Function: Imaginary part of "clog10_towardzero": -+double: 2 -+float: 4 -+idouble: 2 -+ifloat: 4 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "clog10_upward": -+double: 6 -+float: 5 -+idouble: 6 -+ifloat: 5 -+ildouble: 4 -+ldouble: 4 -+ -+Function: Imaginary part of "clog10_upward": -+double: 2 -+float: 4 -+idouble: 2 -+ifloat: 4 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "clog_downward": -+double: 4 -+float: 3 -+idouble: 4 -+ifloat: 3 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "clog_downward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "clog_towardzero": -+double: 4 -+float: 4 -+idouble: 4 -+ifloat: 4 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "clog_towardzero": -+double: 1 -+float: 3 -+idouble: 1 -+ifloat: 3 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "clog_upward": -+double: 4 -+float: 3 -+idouble: 4 -+ifloat: 3 -+ildouble: 4 -+ldouble: 4 -+ -+Function: Imaginary part of "clog_upward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "cos": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "cos_downward": -+double: 1 -+idouble: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "cos_towardzero": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "cos_upward": -+double: 1 -+idouble: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "cosh": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "cosh_downward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 2 -+ -+Function: "cosh_towardzero": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 2 -+ -+Function: "cosh_upward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 1 -+ldouble: 3 -+ -+Function: Real part of "cpow": -+double: 2 -+float: 5 -+idouble: 2 -+ifloat: 5 -+ildouble: 4 -+ldouble: 4 -+ -+Function: Imaginary part of "cpow": -+float: 2 -+ifloat: 2 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Real part of "cpow_downward": -+double: 4 -+float: 8 -+idouble: 4 -+ifloat: 8 -+ildouble: 6 -+ldouble: 6 -+ -+Function: Imaginary part of "cpow_downward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "cpow_towardzero": -+double: 4 -+float: 8 -+idouble: 4 -+ifloat: 8 -+ildouble: 6 -+ldouble: 6 -+ -+Function: Imaginary part of "cpow_towardzero": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "cpow_upward": -+double: 4 -+float: 1 -+idouble: 4 -+ifloat: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "cpow_upward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "csin": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Imaginary part of "csin": -+ildouble: 1 -+ldouble: 1 -+ -+Function: Real part of "csin_downward": -+double: 2 -+float: 3 -+idouble: 2 -+ifloat: 3 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "csin_downward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "csin_towardzero": -+double: 2 -+float: 3 -+idouble: 2 -+ifloat: 3 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "csin_towardzero": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "csin_upward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "csin_upward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "csinh": -+float: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Imaginary part of "csinh": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: Real part of "csinh_downward": -+double: 2 -+float: 1 -+idouble: 2 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "csinh_downward": -+double: 2 -+float: 3 -+idouble: 2 -+ifloat: 3 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "csinh_towardzero": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "csinh_towardzero": -+double: 2 -+float: 3 -+idouble: 2 -+ifloat: 3 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "csinh_upward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "csinh_upward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "csqrt": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Imaginary part of "csqrt": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: Real part of "csqrt_downward": -+double: 5 -+float: 4 -+idouble: 5 -+ifloat: 4 -+ildouble: 4 -+ldouble: 4 -+ -+Function: Imaginary part of "csqrt_downward": -+double: 4 -+float: 3 -+idouble: 4 -+ifloat: 3 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "csqrt_towardzero": -+double: 4 -+float: 3 -+idouble: 4 -+ifloat: 3 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "csqrt_towardzero": -+double: 4 -+float: 3 -+idouble: 4 -+ifloat: 3 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "csqrt_upward": -+double: 5 -+float: 4 -+idouble: 5 -+ifloat: 4 -+ildouble: 4 -+ldouble: 4 -+ -+Function: Imaginary part of "csqrt_upward": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "ctan": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "ctan": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "ctan_downward": -+double: 6 -+float: 5 -+idouble: 6 -+ifloat: 5 -+ildouble: 4 -+ldouble: 4 -+ -+Function: Imaginary part of "ctan_downward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 5 -+ldouble: 5 -+ -+Function: Real part of "ctan_towardzero": -+double: 5 -+float: 2 -+idouble: 5 -+ifloat: 2 -+ildouble: 4 -+ldouble: 4 -+ -+Function: Imaginary part of "ctan_towardzero": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 5 -+ldouble: 5 -+ -+Function: Real part of "ctan_upward": -+double: 2 -+float: 4 -+idouble: 2 -+ifloat: 4 -+ildouble: 5 -+ldouble: 5 -+ -+Function: Imaginary part of "ctan_upward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 5 -+ldouble: 5 -+ -+Function: Real part of "ctanh": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Imaginary part of "ctanh": -+double: 2 -+float: 1 -+idouble: 2 -+ifloat: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "ctanh_downward": -+double: 4 -+float: 2 -+idouble: 4 -+ifloat: 2 -+ildouble: 5 -+ldouble: 5 -+ -+Function: Imaginary part of "ctanh_downward": -+double: 6 -+float: 5 -+idouble: 6 -+ifloat: 5 -+ildouble: 4 -+ldouble: 4 -+ -+Function: Real part of "ctanh_towardzero": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 5 -+ldouble: 5 -+ -+Function: Imaginary part of "ctanh_towardzero": -+double: 5 -+float: 2 -+idouble: 5 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: Real part of "ctanh_upward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 5 -+ldouble: 5 -+ -+Function: Imaginary part of "ctanh_upward": -+double: 2 -+float: 3 -+idouble: 2 -+ifloat: 3 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "erf": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "erf_downward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "erf_towardzero": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "erf_upward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "erfc": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "erfc_downward": -+double: 3 -+float: 4 -+idouble: 3 -+ifloat: 4 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "erfc_towardzero": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "erfc_upward": -+double: 3 -+float: 4 -+idouble: 3 -+ifloat: 4 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "exp": -+ildouble: 1 -+ldouble: 1 -+ -+Function: "exp10": -+double: 2 -+idouble: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "exp10_downward": -+double: 2 -+float: 1 -+idouble: 2 -+ifloat: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "exp10_towardzero": -+double: 2 -+float: 1 -+idouble: 2 -+ifloat: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "exp10_upward": -+double: 2 -+float: 1 -+idouble: 2 -+ifloat: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "exp2": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "exp2_downward": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "exp2_towardzero": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "exp2_upward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "exp_downward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ -+Function: "exp_towardzero": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ -+Function: "exp_upward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ -+Function: "expm1": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "expm1_downward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "expm1_towardzero": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "expm1_upward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "gamma": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "gamma_downward": -+double: 4 -+float: 4 -+idouble: 4 -+ifloat: 4 -+ildouble: 8 -+ldouble: 8 -+ -+Function: "gamma_towardzero": -+double: 4 -+float: 3 -+idouble: 4 -+ifloat: 3 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "gamma_upward": -+double: 4 -+float: 5 -+idouble: 4 -+ifloat: 5 -+ildouble: 8 -+ldouble: 8 -+ -+Function: "hypot": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "hypot_downward": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "hypot_towardzero": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "hypot_upward": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "j0": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "j0_downward": -+double: 2 -+float: 4 -+idouble: 2 -+ifloat: 4 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "j0_towardzero": -+double: 2 -+float: 1 -+idouble: 2 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "j0_upward": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "j1": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "j1_downward": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "j1_towardzero": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "j1_upward": -+double: 3 -+float: 4 -+idouble: 3 -+ifloat: 4 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "jn": -+double: 4 -+float: 4 -+idouble: 4 -+ifloat: 4 -+ildouble: 7 -+ldouble: 7 -+ -+Function: "jn_downward": -+double: 4 -+float: 5 -+idouble: 4 -+ifloat: 5 -+ildouble: 8 -+ldouble: 8 -+ -+Function: "jn_towardzero": -+double: 4 -+float: 5 -+idouble: 4 -+ifloat: 5 -+ildouble: 8 -+ldouble: 8 -+ -+Function: "jn_upward": -+double: 5 -+float: 4 -+idouble: 5 -+ifloat: 4 -+ildouble: 7 -+ldouble: 7 -+ -+Function: "lgamma": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "lgamma_downward": -+double: 4 -+float: 4 -+idouble: 4 -+ifloat: 4 -+ildouble: 8 -+ldouble: 8 -+ -+Function: "lgamma_towardzero": -+double: 4 -+float: 3 -+idouble: 4 -+ifloat: 3 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "lgamma_upward": -+double: 4 -+float: 5 -+idouble: 4 -+ifloat: 5 -+ildouble: 8 -+ldouble: 8 -+ -+Function: "log": -+ildouble: 1 -+ldouble: 1 -+ -+Function: "log10": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "log10_downward": -+double: 2 -+float: 3 -+idouble: 2 -+ifloat: 3 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "log10_towardzero": -+double: 2 -+float: 1 -+idouble: 2 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "log10_upward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "log1p": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "log1p_downward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "log1p_towardzero": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "log1p_upward": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "log2": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "log2_downward": -+double: 3 -+idouble: 3 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "log2_towardzero": -+double: 2 -+idouble: 2 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "log2_upward": -+double: 3 -+idouble: 3 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "log_downward": -+ildouble: 1 -+ldouble: 1 -+ -+Function: "log_towardzero": -+ildouble: 2 -+ldouble: 2 -+ -+Function: "log_upward": -+double: 1 -+idouble: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "pow": -+double: 1 -+idouble: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "pow_downward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "pow_towardzero": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "pow_upward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "sin": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "sin_downward": -+double: 1 -+idouble: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "sin_towardzero": -+double: 1 -+idouble: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "sin_upward": -+double: 1 -+idouble: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "sincos": -+double: 1 -+idouble: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "sincos_downward": -+double: 1 -+idouble: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "sincos_towardzero": -+double: 1 -+idouble: 1 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "sincos_upward": -+double: 1 -+idouble: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "sinh": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "sinh_downward": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "sinh_towardzero": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "sinh_upward": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "tan": -+float: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "tan_downward": -+double: 1 -+float: 2 -+idouble: 1 -+ifloat: 2 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "tan_towardzero": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "tan_upward": -+double: 1 -+float: 1 -+idouble: 1 -+ifloat: 1 -+ildouble: 1 -+ldouble: 1 -+ -+Function: "tanh": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "tanh_downward": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "tanh_towardzero": -+double: 2 -+float: 2 -+idouble: 2 -+ifloat: 2 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "tanh_upward": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "tgamma": -+double: 5 -+float: 4 -+idouble: 5 -+ifloat: 4 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "tgamma_downward": -+double: 5 -+float: 5 -+idouble: 5 -+ifloat: 5 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "tgamma_towardzero": -+double: 5 -+float: 4 -+idouble: 5 -+ifloat: 4 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "tgamma_upward": -+double: 4 -+float: 4 -+idouble: 4 -+ifloat: 4 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "y0": -+double: 2 -+float: 1 -+idouble: 2 -+ifloat: 1 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "y0_downward": -+double: 3 -+float: 4 -+idouble: 3 -+ifloat: 4 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "y0_towardzero": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "y0_upward": -+double: 2 -+float: 5 -+idouble: 2 -+ifloat: 5 -+ildouble: 3 -+ldouble: 3 -+ -+Function: "y1": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "y1_downward": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 4 -+ldouble: 4 -+ -+Function: "y1_towardzero": -+double: 3 -+float: 2 -+idouble: 3 -+ifloat: 2 -+ildouble: 2 -+ldouble: 2 -+ -+Function: "y1_upward": -+double: 5 -+float: 2 -+idouble: 5 -+ifloat: 2 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "yn": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "yn_downward": -+double: 3 -+float: 4 -+idouble: 3 -+ifloat: 4 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "yn_towardzero": -+double: 3 -+float: 3 -+idouble: 3 -+ifloat: 3 -+ildouble: 5 -+ldouble: 5 -+ -+Function: "yn_upward": -+double: 4 -+float: 5 -+idouble: 4 -+ifloat: 5 -+ildouble: 5 -+ldouble: 5 -+ -+# end of automatic generation -diff --git a/sysdeps/loongarch/lp64/libm-test-ulps-name b/sysdeps/loongarch/lp64/libm-test-ulps-name -new file mode 100644 -index 00000000..ce02281e ---- /dev/null -+++ b/sysdeps/loongarch/lp64/libm-test-ulps-name -@@ -0,0 +1 @@ -+LoongArch 64-bit -diff --git a/sysdeps/loongarch/lp64/memcpy.S b/sysdeps/loongarch/lp64/memcpy.S -new file mode 100644 -index 00000000..2dc7a779 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/memcpy.S -@@ -0,0 +1,402 @@ -+#ifdef _LIBC -+#include -+#include -+#include -+#else -+#include -+#include -+#endif -+ -+/* Allow the routine to be named something else if desired. */ -+#ifndef MEMCPY_NAME -+#define MEMCPY_NAME memcpy -+#endif -+ -+#define LD_64(reg, n) \ -+ ld.d t0, reg, n; \ -+ ld.d t1, reg, n+8; \ -+ ld.d t2, reg, n+16; \ -+ ld.d t3, reg, n+24; \ -+ ld.d t4, reg, n+32; \ -+ ld.d t5, reg, n+40; \ -+ ld.d t6, reg, n+48; \ -+ ld.d t7, reg, n+56; -+ -+ -+#define ST_64(reg, n) \ -+ st.d t0, reg, n; \ -+ st.d t1, reg, n+8; \ -+ st.d t2, reg, n+16; \ -+ st.d t3, reg, n+24; \ -+ st.d t4, reg, n+32; \ -+ st.d t5, reg, n+40; \ -+ st.d t6, reg, n+48; \ -+ st.d t7, reg, n+56; -+ -+#define LDST_1024 \ -+ LD_64(a1, 0); \ -+ ST_64(a0, 0); \ -+ LD_64(a1, 64); \ -+ ST_64(a0, 64); \ -+ LD_64(a1, 128); \ -+ ST_64(a0, 128); \ -+ LD_64(a1, 192); \ -+ ST_64(a0, 192); \ -+ LD_64(a1, 256); \ -+ ST_64(a0, 256); \ -+ LD_64(a1, 320); \ -+ ST_64(a0, 320); \ -+ LD_64(a1, 384); \ -+ ST_64(a0, 384); \ -+ LD_64(a1, 448); \ -+ ST_64(a0, 448); \ -+ LD_64(a1, 512); \ -+ ST_64(a0, 512); \ -+ LD_64(a1, 576); \ -+ ST_64(a0, 576); \ -+ LD_64(a1, 640); \ -+ ST_64(a0, 640); \ -+ LD_64(a1, 704); \ -+ ST_64(a0, 704); \ -+ LD_64(a1, 768); \ -+ ST_64(a0, 768); \ -+ LD_64(a1, 832); \ -+ ST_64(a0, 832); \ -+ LD_64(a1, 896); \ -+ ST_64(a0, 896); \ -+ LD_64(a1, 960); \ -+ ST_64(a0, 960); -+ -+#ifdef ANDROID_CHANGES -+LEAF(MEMCPY_NAME, 0) -+#else -+LEAF(MEMCPY_NAME) -+#endif -+ -+//1st var: dest ptr: void *str1 $r4 -+//2nd var: src ptr: void *str2 $r5 -+//3rd var: size_t num -+//t0~t9 registers as temp -+ -+ add.d a4, a1, a2 -+ add.d a3, a0, a2 -+ move t8, a0 -+ move a5, a1 -+ srai.d a6, a2, 4 #num/16 -+ beqz a6, less_16bytes #num<16 -+ slti a6, a2, 137 -+ beqz a6, more_137bytes #num>137 -+ srai.d a6, a2, 6 -+ beqz a6, less_64bytes #num<64 -+ -+ srli.d a0, a0, 3 -+ slli.d a0, a0, 3 -+ addi.d a0, a0, 0x8 -+ sub.d a7, t8, a0 -+ ld.d t0, a1, 0 -+ sub.d a1, a1, a7 -+ st.d t0, t8, 0 -+ -+ add.d a7, a7, a2 -+ addi.d a7, a7, -0x20 -+loop_32: -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ ld.d t2, a1, 16 -+ ld.d t3, a1, 24 -+ st.d t0, a0, 0 -+ st.d t1, a0, 8 -+ st.d t2, a0, 16 -+ st.d t3, a0, 24 -+ -+ addi.d a0, a0, 0x20 -+ addi.d a1, a1, 0x20 -+ addi.d a7, a7, -0x20 -+ blt zero, a7, loop_32 -+ -+ ld.d t4, a4, -32 -+ ld.d t5, a4, -24 -+ ld.d t6, a4, -16 -+ ld.d t7, a4, -8 -+ st.d t4, a3, -32 -+ st.d t5, a3, -24 -+ st.d t6, a3, -16 -+ st.d t7, a3, -8 -+ -+ move v0, t8 -+ jr ra -+ -+less_64bytes: -+ srai.d a6, a2, 5 -+ beqz a6, less_32bytes -+ -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ ld.d t2, a1, 16 -+ ld.d t3, a1, 24 -+ ld.d t4, a4, -32 -+ ld.d t5, a4, -24 -+ ld.d t6, a4, -16 -+ ld.d t7, a4, -8 -+ st.d t0, a0, 0 -+ st.d t1, a0, 8 -+ st.d t2, a0, 16 -+ st.d t3, a0, 24 -+ st.d t4, a3, -32 -+ st.d t5, a3, -24 -+ st.d t6, a3, -16 -+ st.d t7, a3, -8 -+ -+ jr ra -+ -+less_32bytes: -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ ld.d t2, a4, -16 -+ ld.d t3, a4, -8 -+ st.d t0, a0, 0 -+ st.d t1, a0, 8 -+ st.d t2, a3, -16 -+ st.d t3, a3, -8 -+ -+ jr ra -+ -+less_16bytes: -+ srai.d a6, a2, 3 #num/8 -+ beqz a6, less_8bytes -+ -+ ld.d t0, a1, 0 -+ ld.d t1, a4, -8 -+ st.d t0, a0, 0 -+ st.d t1, a3, -8 -+ -+ jr ra -+ -+less_8bytes: -+ srai.d a6, a2, 2 -+ beqz a6, less_4bytes -+ -+ ld.w t0, a1, 0 -+ ld.w t1, a4, -4 -+ st.w t0, a0, 0 -+ st.w t1, a3, -4 -+ -+ jr ra -+ -+less_4bytes: -+ srai.d a6, a2, 1 -+ beqz a6, less_2bytes -+ -+ ld.h t0, a1, 0 -+ ld.h t1, a4, -2 -+ st.h t0, a0, 0 -+ st.h t1, a3, -2 -+ -+ jr ra -+ -+less_2bytes: -+ beqz a2, less_1bytes -+ -+ ld.b t0, a1, 0 -+ st.b t0, a0, 0 -+ -+ jr ra -+ -+less_1bytes: -+ jr ra -+ -+more_137bytes: -+ li.w a6, 64 -+ andi t1, a0, 7 -+ srli.d a0, a0, 3 -+ andi t2, a2, 7 -+ slli.d a0, a0, 3 -+ add.d t1, t1, t2 -+ beqz t1, all_align -+ beq a0, t8, start_over -+ addi.d a0, a0, 0x8 -+ sub.d a7, t8, a0 -+ sub.d a1, a1, a7 -+ add.d a2, a7, a2 -+ -+start_unalign_proc: -+ ld.d t0, a5, 0 -+ slli.d t0, t0, 8 -+ pcaddi t1, 18 -+ slli.d t2, a7, 3 -+ add.d t1, t1, t2 -+ jirl zero, t1, 0 -+ -+start_7_unalign: -+ srli.d t0, t0, 8 -+ st.b t0, a0, -7 -+start_6_unalign: -+ srli.d t0, t0, 8 -+ st.b t0, a0, -6 -+start_5_unalign: -+ srli.d t0, t0, 8 -+ st.b t0, a0, -5 -+start_4_unalign: -+ srli.d t0, t0, 8 -+ st.b t0, a0, -4 -+start_3_unalign: -+ srli.d t0, t0, 8 -+ st.b t0, a0, -3 -+start_2_unalign: -+ srli.d t0, t0, 8 -+ st.b t0, a0, -2 -+start_1_unalign: -+ srli.d t0, t0, 8 -+ st.b t0, a0, -1 -+start_over: -+ -+ addi.d a2, a2, -0x80 -+ blt a2, zero, end_unalign_proc -+ -+loop_less: -+ LD_64(a1, 0) -+ ST_64(a0, 0) -+ LD_64(a1, 64) -+ ST_64(a0, 64) -+ -+ addi.d a0, a0, 0x80 -+ addi.d a1, a1, 0x80 -+ addi.d a2, a2, -0x80 -+ bge a2, zero, loop_less -+ -+end_unalign_proc: -+ addi.d a2, a2, 0x80 -+ -+ pcaddi t1, 34 -+ andi t2, a2, 0x78 -+ sub.d t1, t1, t2 -+ jirl zero, t1, 0 -+ -+end_120_128_unalign: -+ ld.d t0, a1, 112 -+ st.d t0, a0, 112 -+end_112_120_unalign: -+ ld.d t0, a1, 104 -+ st.d t0, a0, 104 -+end_104_112_unalign: -+ ld.d t0, a1, 96 -+ st.d t0, a0, 96 -+end_96_104_unalign: -+ ld.d t0, a1, 88 -+ st.d t0, a0, 88 -+end_88_96_unalign: -+ ld.d t0, a1, 80 -+ st.d t0, a0, 80 -+end_80_88_unalign: -+ ld.d t0, a1, 72 -+ st.d t0, a0, 72 -+end_72_80_unalign: -+ ld.d t0, a1, 64 -+ st.d t0, a0, 64 -+end_64_72_unalign: -+ ld.d t0, a1, 56 -+ st.d t0, a0, 56 -+end_56_64_unalign: -+ ld.d t0, a1, 48 -+ st.d t0, a0, 48 -+end_48_56_unalign: -+ ld.d t0, a1, 40 -+ st.d t0, a0, 40 -+end_40_48_unalign: -+ ld.d t0, a1, 32 -+ st.d t0, a0, 32 -+end_32_40_unalign: -+ ld.d t0, a1, 24 -+ st.d t0, a0, 24 -+end_24_32_unalign: -+ ld.d t0, a1, 16 -+ st.d t0, a0, 16 -+end_16_24_unalign: -+ ld.d t0, a1, 8 -+ st.d t0, a0, 8 -+end_8_16_unalign: -+ ld.d t0, a1, 0 -+ st.d t0, a0, 0 -+end_0_8_unalign: -+ -+ mod.d t0, a3, a6 -+ srli.d t1, t0, 3 -+ slti t0, t0, 1 -+ add.d t0, t0, t1 -+ blt zero, t0, end_8_without_cross_cache_line -+ -+ andi a2, a2, 0x7 -+ pcaddi t1, 18 -+ slli.d a2, a2, 3 -+ sub.d t1, t1, a2 -+ jirl zero, t1, 0 -+ -+end_7_unalign: -+ ld.b t0, a4, -7 -+ st.b t0, a3, -7 -+end_6_unalign: -+ ld.b t0, a4, -6 -+ st.b t0, a3, -6 -+end_5_unalign: -+ ld.b t0, a4, -5 -+ st.b t0, a3, -5 -+end_4_unalign: -+ ld.b t0, a4, -4 -+ st.b t0, a3, -4 -+end_3_unalign: -+ ld.b t0, a4, -3 -+ st.b t0, a3, -3 -+end_2_unalign: -+ ld.b t0, a4, -2 -+ st.b t0, a3, -2 -+end_1_unalign: -+ ld.b t0, a4, -1 -+ st.b t0, a3, -1 -+end: -+ -+ move v0, t8 -+ jr ra -+ -+all_align: -+ addi.d a2, a2, -0x20 -+ -+align_loop_less: -+ ld.d t0, a1, 0 -+ ld.d t1, a1, 8 -+ ld.d t2, a1, 16 -+ ld.d t3, a1, 24 -+ st.d t0, a0, 0 -+ st.d t1, a0, 8 -+ st.d t2, a0, 16 -+ st.d t3, a0, 24 -+ -+ addi.d a0, a0, 0x20 -+ addi.d a1, a1, 0x20 -+ addi.d a2, a2, -0x20 -+ blt zero, a2, align_loop_less -+ -+ ld.d t4, a4, -32 -+ ld.d t5, a4, -24 -+ ld.d t6, a4, -16 -+ ld.d t7, a4, -8 -+ st.d t4, a3, -32 -+ st.d t5, a3, -24 -+ st.d t6, a3, -16 -+ st.d t7, a3, -8 -+ -+ move v0, t8 -+ jr ra -+ -+end_8_without_cross_cache_line: -+ ld.d t0, a4, -8 -+ st.d t0, a3, -8 -+ -+ move v0, t8 -+ jr ra -+ -+END(MEMCPY_NAME) -+#ifndef ANDROID_CHANGES -+#ifdef _LIBC -+libc_hidden_builtin_def (MEMCPY_NAME) -+#endif -+#endif -diff --git a/sysdeps/loongarch/lp64/memmove.S b/sysdeps/loongarch/lp64/memmove.S -new file mode 100644 -index 00000000..f87d036b ---- /dev/null -+++ b/sysdeps/loongarch/lp64/memmove.S -@@ -0,0 +1,476 @@ -+#ifdef _LIBC -+#include -+#include -+#include -+#else -+#include -+#include -+#endif -+ -+/* Allow the routine to be named something else if desired. */ -+#ifndef MEMMOVE_NAME -+#define MEMMOVE_NAME memmove -+#endif -+ -+#define LD_64(reg, n) \ -+ ld.d t0, reg, n; \ -+ ld.d t1, reg, n+8; \ -+ ld.d t2, reg, n+16; \ -+ ld.d t3, reg, n+24; \ -+ ld.d t4, reg, n+32; \ -+ ld.d t5, reg, n+40; \ -+ ld.d t6, reg, n+48; \ -+ ld.d t7, reg, n+56; -+ -+ -+#define ST_64(reg, n) \ -+ st.d t0, reg, n; \ -+ st.d t1, reg, n+8; \ -+ st.d t2, reg, n+16; \ -+ st.d t3, reg, n+24; \ -+ st.d t4, reg, n+32; \ -+ st.d t5, reg, n+40; \ -+ st.d t6, reg, n+48; \ -+ st.d t7, reg, n+56; -+ -+#define LDST_1024 \ -+ LD_64(a1, 0); \ -+ ST_64(a0, 0); \ -+ LD_64(a1, 64); \ -+ ST_64(a0, 64); \ -+ LD_64(a1, 128); \ -+ ST_64(a0, 128); \ -+ LD_64(a1, 192); \ -+ ST_64(a0, 192); \ -+ LD_64(a1, 256); \ -+ ST_64(a0, 256); \ -+ LD_64(a1, 320); \ -+ ST_64(a0, 320); \ -+ LD_64(a1, 384); \ -+ ST_64(a0, 384); \ -+ LD_64(a1, 448); \ -+ ST_64(a0, 448); \ -+ LD_64(a1, 512); \ -+ ST_64(a0, 512); \ -+ LD_64(a1, 576); \ -+ ST_64(a0, 576); \ -+ LD_64(a1, 640); \ -+ ST_64(a0, 640); \ -+ LD_64(a1, 704); \ -+ ST_64(a0, 704); \ -+ LD_64(a1, 768); \ -+ ST_64(a0, 768); \ -+ LD_64(a1, 832); \ -+ ST_64(a0, 832); \ -+ LD_64(a1, 896); \ -+ ST_64(a0, 896); \ -+ LD_64(a1, 960); \ -+ ST_64(a0, 960); -+ -+#define LDST_1024_BACK \ -+ LD_64(a4, -64); \ -+ ST_64(a3, -64); \ -+ LD_64(a4, -128); \ -+ ST_64(a3, -128); \ -+ LD_64(a4, -192); \ -+ ST_64(a3, -192); \ -+ LD_64(a4, -256); \ -+ ST_64(a3, -256); \ -+ LD_64(a4, -320); \ -+ ST_64(a3, -320); \ -+ LD_64(a4, -384); \ -+ ST_64(a3, -384); \ -+ LD_64(a4, -448); \ -+ ST_64(a3, -448); \ -+ LD_64(a4, -512); \ -+ ST_64(a3, -512); \ -+ LD_64(a4, -576); \ -+ ST_64(a3, -576); \ -+ LD_64(a4, -640); \ -+ ST_64(a3, -640); \ -+ LD_64(a4, -704); \ -+ ST_64(a3, -704); \ -+ LD_64(a4, -768); \ -+ ST_64(a3, -768); \ -+ LD_64(a4, -832); \ -+ ST_64(a3, -832); \ -+ LD_64(a4, -896); \ -+ ST_64(a3, -896); \ -+ LD_64(a4, -960); \ -+ ST_64(a3, -960); \ -+ LD_64(a4, -1024); \ -+ ST_64(a3, -1024); -+ -+#ifdef ANDROID_CHANGES -+LEAF(MEMMOVE_NAME, 0) -+#else -+LEAF(MEMMOVE_NAME) -+#endif -+ -+//1st var: dest ptr: void *str1 $r4 a0 -+//2nd var: src ptr: void *str2 $r5 a1 -+//3rd var: size_t num -+//t0~t9 registers as temp -+ -+ add.d a4, a1, a2 -+ add.d a3, a0, a2 -+ beq a1, a0, less_1bytes -+ move t8, a0 -+ srai.d a6, a2, 4 #num/16 -+ beqz a6, less_16bytes #num<16 -+ srai.d a6, a2, 6 #num/64 -+ bnez a6, more_64bytes #num>64 -+ srai.d a6, a2, 5 -+ beqz a6, less_32bytes #num<32 -+ -+ ld.d t0, a1, 0 #32 -+#include -+#include -+#else -+#include -+#include -+#endif -+ -+#ifdef LOONGSON_TEST -+#define MEMSET _memset -+#else -+#define MEMSET memset -+#endif -+ -+#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; \ -+ -+//1st var: void *str $4 a0 -+//2nd var: int val $5 a1 -+//3rd var: size_t num $6 a2 -+ -+LEAF(MEMSET) -+ -+memset: -+ .align 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 #num/16 -+ beqz t8, less_16bytes #num<16 -+ srai.d t8, a2, 6 #num/64 -+ bnez t8, more_64bytes #num>64 -+ srai.d t8, a2, 5 #num/32 -+ beqz t8, less_32bytes #num<32 -+ st.d a1, a0, 0 #32 -+#include -+#include -+ -+/* Short algorithm description: -+ * -+ * 1) if |x|==0: sin(x)=x, -+ * cos(x)=1. -+ * 2) if |x|<2^-27: sin(x)=x-x*DP_SMALL, raising underflow only when needed, -+ * cos(x)=1-|x|. -+ * 3) if |x|<2^-5 : sin(x)=x+x*x^2*DP_SIN2_0+x^5*DP_SIN2_1, -+ * cos(x)=1+1*x^2*DP_COS2_0+x^5*DP_COS2_1 -+ * 4) if |x|< Pi/4: sin(x)=x+x*x^2*(S0+x^2*(S1+x^2*(S2+x^2*(S3+x^2*S4)))), -+ * cos(x)=1+1*x^2*(C0+x^2*(C1+x^2*(C2+x^2*(C3+x^2*C4)))). -+ * 5) if |x| < 9*Pi/4: -+ * 5.1) Range reduction: -+ * k=trunc(|x|/(Pi/4)), j=(k+1)&0x0e, n=k+1, t=|x|-j*Pi/4. -+ * 5.2) Reconstruction: -+ * sign_sin = sign(x) * (-1.0)^(( n >>2)&1) -+ * sign_cos = (-1.0)^(((n+2)>>2)&1) -+ * poly_sin = ((((S4*t^2 + S3)*t^2 + S2)*t^2 + S1)*t^2 + S0)*t^2*t+t -+ * poly_cos = ((((C4*t^2 + C3)*t^2 + C2)*t^2 + C1)*t^2 + C0)*t^2*s+s -+ * if(n&2 != 0) { -+ * using cos(t) and sin(t) polynomials for |t|= 2^23, very large args: -+ * 7.1) Range reduction: -+ * k=trunc(|x|/(Pi/4)), j=(k+1)&0xfffffffe, n=k+1, t=|x|-j*Pi/4. -+ * 7.2) Reconstruction same as (5.2). -+ * 8) if x is Inf, return x-x, and set errno=EDOM. -+ * 9) if x is NaN, return x-x. -+ * -+ * Special cases: -+ * sin/cos(+-0) = +-0/1 not raising inexact/underflow, -+ * sin/cos(subnormal) raises inexact/underflow, -+ * sin/cos(min_normalized) raises inexact/underflow, -+ * sin/cos(normalized) raises inexact, -+ * sin/cos(Inf) = NaN, raises invalid, sets errno to EDOM, -+ * sin/cos(NaN) = NaN. -+ */ -+ -+#define COSF __cosf -+ -+#define LOADFD(rd, rs, label) \ -+ la.local rs, label;\ -+ fld.d rd, rs, 0 -+ -+#define LOADFS(rd, rs, label) \ -+ la.local rs, label;\ -+ fld.s rd, rs, 0 -+ -+#define FTOL(rd, rs, tmp) \ -+ ftintrz.l.d tmp, rs;\ -+ movfr2gr.d rd, tmp -+ -+#define FTOW(rd, rs, tmp) \ -+ ftintrz.w.d tmp, rs;\ -+ movfr2gr.s rd, tmp -+ -+#define WTOF(rd, rs, tmp) \ -+ movgr2fr.w tmp, rs;\ -+ ffint.d.w rd, tmp -+ -+#define LTOF(rd, rs, tmp) \ -+ movgr2fr.d tmp, rs;\ -+ ffint.d.l rd, tmp -+ -+LEAF(COSF) -+ .align 2 -+ .align 3 -+ /* fa0 is SP x; fa1 is DP x */ -+ movfr2gr.s t0, fa0 /* Bits of x */ -+ fcvt.d.s fa1, fa0 /* DP x */ -+ li.w t1, 0x7fffffff -+ and t0, t0, t1 /* |x| */ -+ li.w t1, 0x3f490fdb /* const Pi/4 */ -+ bltu t0, t1, L(arg_less_pio4) /* |x| < Pi/4 branch */ -+ li.w t1, 0x40e231d6 /* 9*Pi/4 */ -+ la.local t4, L(DP_) /*DP_ base addr*/ -+ bgeu t0, t1, L(greater_or_equal_9pio4) /* |x| >= 9*Pi/4 branch */ -+/* L(median_args): */ -+ /* Here if Pi/4<=|x|<9*Pi/4 */ -+ fabs.d fa0, fa1 /* DP |x| */ -+ fld.d fa1, t4, 56 /* 4/Pi */ -+ fmul.d fa1, fa1, fa0 /* DP |x|/(Pi/4) */ -+ FTOW( t0, fa1, fa1 ) /* k=trunc(|x|/(Pi/4)) */ -+ la.local t1, L(PIO2J) /* base addr of PIO2J table */ -+ addi.w t0, t0, 1 /* k+1 */ -+ bstrpick.d t2, t0, 3, 1 /* j=n/2 */ -+ alsl.d t1, t2, t1, 3 -+ fld.d fa1, t1, 0 /* j*Pi/2 */ -+ addi.w t0, t0, 2 /* n = k+3 */ -+ fsub.d fa0, fa0, fa1 /* t = |x| - j * Pi/2 */ -+/* Input: t0=n fa0=t*/ -+L(reduced): -+ /* Here if cos(x) calculated using cos(t) polynomial for |t|>2)&1) -+ * result = s * (1.0+t^2*(C0+t^2*(C1+t^2*(C2+t^2*(C3+t^2*C4))))) -+ -+ * Here if cos(x) calculated using sin(t) polynomial for |t|>2)&1) -+ * result = s * t * (1.0+t^2*(S0+t^2*(S1+t^2*(S2+t^2*(S3+t^2*S4))))) -+ */ -+ /* TODO: what is the best order ??? */ -+ /* load-to-use latency, hardware module usage, integer pipeline & float pipeline */ -+ /* cancel branch */ -+ slli.w t0, t0, 1 /* (n << 1) */ -+ andi t1, t0, 4 /* (n << 1) & 4 */ -+ alsl.d t2, t1, t4, 4 /* adjust to DP_C or DP_S */ -+ fld.d fa3, t2, 32 /* C4 */ -+ andi t0, t0, 8 /* =====> (n << 1) & 8 */ -+ fmul.d fa1, fa0, fa0 /* y=x^2 */ -+ fld.d fa4, t2, 16 /* C2 */ -+ fmul.d fa2, fa1, fa1 /* z=x^4 */ -+ fld.d fa5, t2, 24 /* C3 */ -+ la.local t3, L(DP_ONES) /* =====> DP_ONES */ -+ fld.d fa6, t2, 8 /* C1 */ -+ fmadd.d fa4, fa2, fa3, fa4 /* cx = C2+z*C4 */ -+ fld.d fa3, t2, 0 /* C0 */ -+ fmadd.d fa5, fa2, fa5, fa6 /* cy = C1+z*C3 */ -+ fld.d fa6, t3, 0 /* one */ -+ fmadd.d fa4, fa2, fa4, fa3 /* cx = C0+z*cx */ -+ add.d t0, t0, t3 /* =====> addr */ -+ fmadd.d fa4, fa1, fa5, fa4 /* cx = cx+y*cy */ -+ fld.d fa2, t0, 0 /* sign */ -+ fmadd.d fa4, fa4, fa1, fa6 /* 1.0+y*cx */ -+ fmul.d fa1, fa2, fa4 /* sign * cx */ -+ bnez t1, L_return -+ fmul.d fa1, fa1, fa0 /* t*s, where s = sign(x) * (-1.0)^((n>>2)&1) */ -+L_return: -+ fcvt.s.d fa0, fa1 /* SP result */ -+ jr ra -+ -+L(greater_or_equal_9pio4): -+ /* Here if |x|>=9*Pi/4 */ -+ li.w t1, 0x7f800000 /* x is Inf or NaN? */ -+ bgeu t0, t1, L(inf_or_nan) /* |x| >= Inf branch */ -+ /* Here if finite |x|>=9*Pi/4 */ -+ li.w t1, 0x4b000000 /* 2^23 */ -+ bgeu t0, t1, L(greater_or_equal_2p23) /* |x| >= 2^23 branch */ -+ /* Here if 9*Pi/4<=|x|<2^23 */ -+ fabs.d fa0, fa1 /* DP |x| */ -+ fld.d fa1, t4, 56 -+ fmul.d fa1, fa1, fa0 /* |x|/(Pi/4) */ -+ FTOW( t0, fa1, fa1 ) /* k=trunc(|x|/(Pi/4)) */ -+ addi.w t0, t0, 1 /* k+1 */ -+ srli.w t1, t0, 1 /* x=n/2 */ -+ WTOF( fa1, t1, fa1 ) /* DP x */ -+ fld.d fa2, t4, 104 /* -PIO2HI = high part of -Pi/2 */ -+ fld.d fa3, t4, 112 /* -PIO2LO = low part of -Pi/2 */ -+ fmadd.d fa0, fa2, fa1, fa0 /* |x| - x*PIO2HI */ -+ addi.w t0, t0, 2 /* n = k+3 */ -+ fmadd.d fa0, fa3, fa1, fa0 /* |x| - x*PIO2HI - x*PIO2LO */ -+ b L(reduced) -+ -+L(greater_or_equal_2p23): -+ /* Here if finite |x|>=2^23 */ -+ fabs.s fa5, fa0 /* SP |x| */ -+ /* bitpos = (ix>>23) - BIAS_32; */ -+ srli.w t0, t0, 23 /*TODO???srai.w eb = biased exponent of x */ -+ /* bitpos = eb - 0x7f + 59, where 0x7f is exponent bias */ -+ addi.w t0, t0, -124 /* t0 = bitpos */ -+ /* t3= j = bitpos/28 */ -+ /* x/28 = (x * ((0x100000000 / 28) + 1)) >> 32 */ -+ li.w t1, 0x924924a -+ mulh.wu t0, t1, t0 -+ fcvt.d.s fa5, fa5 /* Convert to double */ -+ /* TODO: what is the best order ??? */ -+ la.local t1, L(invpio4_table) /* t2 */ -+ alsl.d t1, t0, t1, 3 -+ fld.d fa0, t1, 0 /* invpio4_table[j] */ -+ fld.d fa1, t1, 8 /* invpio4_table[j+1] */ -+ fmul.d fa0, fa0, fa5 /* a = invpio4_table[j]*|x| */ -+ fld.d fa2, t1, 16 /* invpio4_table[j+2] */ -+ fmul.d fa1, fa1, fa5 /* b = invpio4_table[j+1]*|x| */ -+ fld.d fa3, t1, 24 /* invpio4_table[j+3] */ -+ fmul.d fa2, fa2, fa5 /* c = invpio4_table[j+2]*|x| */ -+ fmul.d fa3, fa3, fa5 /* d = invpio4_table[j+3]*|x| */ -+/*TODO: overflow check*/ -+ FTOL( t0, fa0, fa4 ) /*uint64_t l = a; TODO: change the order*/ -+ li.w t1, -8 /* 0xfffffffffffffff8 */ -+ and t0, t0, t1 /* l &= ~0x7; */ -+ LTOF( fa4, t0, fa4 ) /* DP l*/ -+ fsub.d fa0, fa0, fa4 /* a -= l; */ -+ fadd.d fa4, fa0, fa1 /* fa4 double e = a + b; */ -+/*TODO: overflow check*/ -+ FTOL( t0, fa4, fa4 ) /*uint64_t l = e;*/ -+ andi t2, t0, 1 /* l & 1 TODO: change the order*/ -+ LOADFD( fa5, t1, L(DP_ONES) ) /* fa5 = 1.0 */ -+ LTOF( fa4, t0, fa4 ) /* fa4 DP l*/ -+/* critical!!!! the order */ -+ fsub.d fa0, fa0, fa4 -+ fld.d fa4, t4, 120 /* PI_4 */ -+ beqz t2, L_even_integer -+/*L_odd_integer:*/ -+ fsub.d fa0, fa0, fa5 -+ fadd.d fa0, fa0, fa1 -+ fadd.d fa2, fa2, fa3 -+ fadd.d fa0, fa0, fa2 -+ addi.d t0, t0, 3 -+ fmul.d fa0, fa0, fa4 -+ b L(reduced) -+L_even_integer: -+ fadd.d fa0, fa0, fa1 -+ fadd.d fa2, fa2, fa3 -+ fadd.d fa0, fa0, fa2 -+ fcmp.sle.d $fcc0, fa0, fa5 -+ addi.d t0, t0, 3 -+ bcnez $fcc0, L_leq_one -+/*L_gt_one:*/ -+ fld.d fa2, t1, 16 /* 2.0 */ -+ addi.d t0, t0, 1 -+ fsub.d fa0, fa0, fa2 -+L_leq_one: -+ fmul.d fa0, fa0, fa4 -+ b L(reduced) -+ -+L(arg_less_pio4): -+ /* Here if |x| -+#include -+#include -+ -+/* Short algorithm description: -+ * -+ * 1) if |x|==0: sin(x)=x, -+ * cos(x)=1. -+ * 2) if |x|<2^-27: sin(x)=x-x*DP_SMALL, raising underflow only when needed, -+ * cos(x)=1-|x|. -+ * 3) if |x|<2^-5 : sin(x)=x+x*x^2*DP_SIN2_0+x^5*DP_SIN2_1, -+ * cos(x)=1+1*x^2*DP_COS2_0+x^5*DP_COS2_1 -+ * 4) if |x|< Pi/4: sin(x)=x+x*x^2*(S0+x^2*(S1+x^2*(S2+x^2*(S3+x^2*S4)))), -+ * cos(x)=1+1*x^2*(C0+x^2*(C1+x^2*(C2+x^2*(C3+x^2*C4)))). -+ * 5) if |x| < 9*Pi/4: -+ * 5.1) Range reduction: -+ * k=trunc(|x|/(Pi/4)), j=(k+1)&0x0e, n=k+1, t=|x|-j*Pi/4. -+ * 5.2) Reconstruction: -+ * sign_sin = sign(x) * (-1.0)^(( n >>2)&1) -+ * sign_cos = (-1.0)^(((n+2)>>2)&1) -+ * poly_sin = ((((S4*t^2 + S3)*t^2 + S2)*t^2 + S1)*t^2 + S0)*t^2*t+t -+ * poly_cos = ((((C4*t^2 + C3)*t^2 + C2)*t^2 + C1)*t^2 + C0)*t^2*s+s -+ * if(n&2 != 0) { -+ * using cos(t) and sin(t) polynomials for |t|= 2^23, very large args: -+ * 7.1) Range reduction: -+ * k=trunc(|x|/(Pi/4)), j=(k+1)&0xfffffffe, n=k+1, t=|x|-j*Pi/4. -+ * 7.2) Reconstruction same as (5.2). -+ * 8) if x is Inf, return x-x, and set errno=EDOM. -+ * 9) if x is NaN, return x-x. -+ * -+ * Special cases: -+ * sin/cos(+-0) = +-0/1 not raising inexact/underflow, -+ * sin/cos(subnormal) raises inexact/underflow, -+ * sin/cos(min_normalized) raises inexact/underflow, -+ * sin/cos(normalized) raises inexact, -+ * sin/cos(Inf) = NaN, raises invalid, sets errno to EDOM, -+ * sin/cos(NaN) = NaN. -+ */ -+ -+#define SINF __sinf -+ -+#define LOADFD(rd, rs, label) \ -+ la.local rs, label;\ -+ fld.d rd, rs, 0 -+ -+#define LOADFS(rd, rs, label) \ -+ la.local rs, label;\ -+ fld.s rd, rs, 0 -+ -+#define FTOL(rd, rs, tmp) \ -+ ftintrz.l.d tmp, rs;\ -+ movfr2gr.d rd, tmp -+ -+#define FTOW(rd, rs, tmp) \ -+ ftintrz.w.d tmp, rs;\ -+ movfr2gr.s rd, tmp -+ -+#define WTOF(rd, rs, tmp) \ -+ movgr2fr.w tmp, rs;\ -+ ffint.d.w rd, tmp -+ -+#define LTOF(rd, rs, tmp) \ -+ movgr2fr.d tmp, rs;\ -+ ffint.d.l rd, tmp -+ -+LEAF(SINF) -+ .align 2 -+ .align 3 -+ /* fa0 is SP x; fa1 is DP x */ -+ movfr2gr.s t2, fa0 /* Bits of x */ -+ fcvt.d.s fa1, fa0 /* DP x */ -+ li.w t1, 0x7fffffff -+ and t0, t2, t1 /* |x| */ -+ li.w t1, 0x3f490fdb /* const Pi/4 */ -+ bltu t0, t1, L(arg_less_pio4) /* |x| < Pi/4 branch */ -+ li.w t1, 0x40e231d6 /* 9*Pi/4 */ -+ la.local t4, L(DP_) /*DP_ base addr*/ -+ bstrpick.d t5, t2, 31, 31 /* sign of x */ -+ slli.w t5, t5, 3 -+ bgeu t0, t1, L(greater_or_equal_9pio4) /* |x| >= 9*Pi/4 branch */ -+/* L(median_args): */ -+ /* Here if Pi/4<=|x|<9*Pi/4 */ -+ fabs.d fa0, fa1 /* DP |x| */ -+ fld.d fa1, t4, 56 /* 4/Pi */ -+ fmul.d fa1, fa1, fa0 /* DP |x|/(Pi/4) */ -+ FTOW( t0, fa1, fa1 ) /* k=trunc(|x|/(Pi/4)) */ -+ la.local t1, L(PIO2J) /* base addr of PIO2J table */ -+ addi.w t0, t0, 1 /* k+1 */ -+ bstrpick.d t2, t0, 3, 1 /* j=n/2 */ -+ alsl.d t1, t2, t1, 3 -+ fld.d fa1, t1, 0 /* j*Pi/2 */ -+ fsub.d fa0, fa0, fa1 /* t = |x| - j * Pi/2 */ -+/* Input: t0=n fa0=t*/ -+/* Input: t0=n fa0=t, t5=sign(x) */ -+L(reduced): -+ /* Here if cos(x) calculated using cos(t) polynomial for |t|>2)&1) -+ * result = s * (1.0+t^2*(C0+t^2*(C1+t^2*(C2+t^2*(C3+t^2*C4))))) -+ -+ * Here if cos(x) calculated using sin(t) polynomial for |t|>2)&1) -+ * result = s * t * (1.0+t^2*(S0+t^2*(S1+t^2*(S2+t^2*(S3+t^2*S4))))) -+ */ -+ /* TODO: what is the best order ??? */ -+ /* load-to-use latency, hardware module usage, integer pipeline & float pipeline */ -+ /* cancel branch */ -+ slli.w t0, t0, 1 /* (n << 1) */ -+ andi t1, t0, 4 /* (n << 1) & 4 */ -+ alsl.d t2, t1, t4, 4 /* adjust to DP_C or DP_S */ -+ fld.d fa3, t2, 32 /* C4 */ -+ andi t0, t0, 8 /* =====> (n << 1) & 8 */ -+ fmul.d fa1, fa0, fa0 /* y=x^2 */ -+ xor t0, t0, t5 /* (-1.0)^((n>>2)&1) XOR sign(x) */ -+ fld.d fa4, t2, 16 /* C2 */ -+ fmul.d fa2, fa1, fa1 /* z=x^4 */ -+ fld.d fa5, t2, 24 /* C3 */ -+ la.local t3, L(DP_ONES) /* =====> DP_ONES */ -+ fld.d fa6, t2, 8 /* C1 */ -+ fmadd.d fa4, fa2, fa3, fa4 /* cx = C2+z*C4 */ -+ fld.d fa3, t2, 0 /* C0 */ -+ fmadd.d fa5, fa2, fa5, fa6 /* cy = C1+z*C3 */ -+ fld.d fa6, t3, 0 /* 1.0 */ -+ fmadd.d fa4, fa2, fa4, fa3 /* cx = C0+z*cx */ -+ add.d t0, t0, t3 /* =====> addr */ -+ fmadd.d fa4, fa1, fa5, fa4 /* cx = cx+y*cy */ -+ fld.d fa2, t0, 0 /* sign */ -+ fmadd.d fa4, fa4, fa1, fa6 /* 1.0+y*cx */ -+ fmul.d fa1, fa2, fa4 /* sign * cx */ -+ bnez t1, L_return -+ fmul.d fa1, fa1, fa0 /* t*s, where s = sign(x) * (-1.0)^((n>>2)&1) */ -+L_return: -+ fcvt.s.d fa0, fa1 /* SP result */ -+ jr ra -+ -+L(greater_or_equal_9pio4): -+ /* Here if |x|>=9*Pi/4 */ -+ li.w t1, 0x7f800000 /* x is Inf or NaN? */ -+ bgeu t0, t1, L(inf_or_nan) /* |x| >= Inf branch */ -+ /* Here if finite |x|>=9*Pi/4 */ -+ li.w t1, 0x4b000000 /* 2^23 */ -+ bgeu t0, t1, L(greater_or_equal_2p23) /* |x| >= 2^23 branch */ -+ /* Here if 9*Pi/4<=|x|<2^23 */ -+ fabs.d fa0, fa1 /* DP |x| */ -+ fld.d fa1, t4, 56 -+ fmul.d fa1, fa1, fa0 /* |x|/(Pi/4) */ -+ FTOW( t0, fa1, fa1 ) /* k=trunc(|x|/(Pi/4)) */ -+ addi.w t0, t0, 1 /* k+1 */ -+ srli.w t1, t0, 1 /* x=n/2 */ -+ WTOF( fa1, t1, fa1 ) /* DP x */ -+ fld.d fa2, t4, 104 /* -PIO2HI = high part of -Pi/2 */ -+ fld.d fa3, t4, 112 /* -PIO2LO = low part of -Pi/2 */ -+ fmadd.d fa0, fa2, fa1, fa0 /* |x| - x*PIO2HI */ -+ fmadd.d fa0, fa3, fa1, fa0 /* |x| - x*PIO2HI - x*PIO2LO */ -+ b L(reduced) -+ -+L(greater_or_equal_2p23): -+ /* Here if finite |x|>=2^23 */ -+ fabs.s fa5, fa0 /* SP |x| */ -+ /* bitpos = (ix>>23) - BIAS_32; */ -+ srli.w t0, t0, 23 /*TODO???srai.w eb = biased exponent of x */ -+ /* bitpos = eb - 0x7f + 59, where 0x7f is exponent bias */ -+ addi.w t0, t0, -124 /* t0 = bitpos */ -+ /* t3= j = bitpos/28 */ -+ /* x/28 = (x * ((0x100000000 / 28) + 1)) >> 32 */ -+ li.w t1, 0x924924a -+ mulh.wu t0, t1, t0 -+ fcvt.d.s fa5, fa5 /* Convert to double */ -+ /* TODO: what is the best order ??? */ -+ la.local t1, L(invpio4_table) /* t2 */ -+ alsl.d t1, t0, t1, 3 -+ fld.d fa0, t1, 0 /* invpio4_table[j] */ -+ fld.d fa1, t1, 8 /* invpio4_table[j+1] */ -+ fmul.d fa0, fa0, fa5 /* a = invpio4_table[j]*|x| */ -+ fld.d fa2, t1, 16 /* invpio4_table[j+2] */ -+ fmul.d fa1, fa1, fa5 /* b = invpio4_table[j+1]*|x| */ -+ fld.d fa3, t1, 24 /* invpio4_table[j+3] */ -+ fmul.d fa2, fa2, fa5 /* c = invpio4_table[j+2]*|x| */ -+ fmul.d fa3, fa3, fa5 /* d = invpio4_table[j+3]*|x| */ -+/*TODO: overflow check*/ -+ FTOL( t0, fa0, fa4 ) /*uint64_t l = a; TODO: change the order*/ -+ li.w t1, -8 /* 0xfffffffffffffff8 */ -+ and t0, t0, t1 /* l &= ~0x7; */ -+ LTOF( fa4, t0, fa4 ) /* DP l*/ -+ fsub.d fa0, fa0, fa4 /* a -= l; */ -+ fadd.d fa4, fa0, fa1 /* fa4 double e = a + b; */ -+/*TODO: overflow check*/ -+ FTOL( t0, fa4, fa4 ) /*uint64_t l = e;*/ -+ andi t2, t0, 1 /* l & 1 TODO: change the order*/ -+ LOADFD( fa5, t1, L(DP_ONES) ) /* fa5 = 1.0 */ -+ LTOF( fa4, t0, fa4 ) /* fa4 DP l*/ -+/* critical!!!! the order */ -+ fsub.d fa0, fa0, fa4 -+ fld.d fa4, t4, 120 /* PI_4 */ -+ beqz t2, L_even_integer -+/*L_odd_integer:*/ -+ fsub.d fa0, fa0, fa5 -+ fadd.d fa0, fa0, fa1 -+ fadd.d fa2, fa2, fa3 -+ fadd.d fa0, fa0, fa2 -+ addi.d t0, t0, 1 -+ fmul.d fa0, fa0, fa4 -+ b L(reduced) -+L_even_integer: -+ fadd.d fa0, fa0, fa1 -+ fadd.d fa2, fa2, fa3 -+ fadd.d fa0, fa0, fa2 -+ fcmp.sle.d $fcc0, fa0, fa5 -+ addi.d t0, t0, 1 -+ bcnez $fcc0, L_leq_one -+/*L_gt_one:*/ -+ fld.d fa2, t1, 16 /* 2.0 */ -+ addi.d t0, t0, 1 -+ fsub.d fa0, fa0, fa2 -+L_leq_one: -+ fmul.d fa0, fa0, fa4 -+ b L(reduced) -+ -+L(arg_less_pio4): -+ /* Here if |x| -+#include -+ -+ -+ -+ -+ -+#define L_ADDIU addi.d -+#define L_ADDU add.d -+#define L_SUBU sub.d -+ -+#define STRCHR strchr -+#define MOVN(rd,rs,rt) \ -+ maskeqz t6, rs, rt;\ -+ masknez rd, rd, rt;\ -+ or rd, rd, t6 -+ -+#define MOVN2(rd,rt) \ -+ masknez rd, rd, rt;\ -+ or rd, rd, rt -+ -+ -+/* char * strchr (const char *s1, int c); */ -+ -+LEAF(STRCHR) -+ .align 6 -+ -+ li.w t4, 0x7 -+ lu12i.w a2, 0x01010 -+ bstrins.d a1, a1, 15, 8 -+ andi t0, a0, 0x7 -+ -+ ori a2, a2, 0x101 -+ andn t4, a0, t4 -+ slli.w t1, t0, 3 -+ -+ ld.d t4, t4, 0 -+ -+ -+ nor t8, zero, zero -+ bstrins.d a1, a1, 31, 16 -+ srl.d t4, t4, t1 -+ -+ bstrins.d a1, a1, 63, 32 -+ bstrins.d a2, a2, 63, 32 -+ srl.d a7, t8, t1 -+ -+ li.w t1, 8 -+ nor t8, a7, zero -+ slli.d a3, a2, 7 -+ or t5, t8, t4 -+ and t3, a7, a1 -+ -+ sub.w t1, t1, t0 -+ nor a3, a3, zero -+ xor t2, t5, t3 -+ sub.d a7, t5, a2 -+ nor a6, t5, a3 -+ -+ sub.d a5, t2, a2 -+ nor a4, t2, a3 -+ -+ and a6, a7, a6 -+ and a5, a5, a4 -+ or a7, a6, a5 -+ bnez a7, L(_mc8_a) -+ -+ L_ADDU a0, a0, t1 -+L(_aloop): -+ ld.d t4, a0, 0 -+ -+ xor t2, t4, a1 -+ sub.d a7, t4, a2 -+ nor a6, t4, a3 -+ sub.d a5, t2, a2 -+ -+ nor a4, t2, a3 -+ and a6, a7, a6 -+ and a5, a5, a4 -+ or a7, a6, a5 -+ bnez a7, L(_mc8_a) -+ -+ ld.d t4, a0, 8 -+ L_ADDIU a0, a0, 16 -+ xor t2, t4, a1 -+ sub.d a7, t4, a2 -+ nor a6, t4, a3 -+ sub.d a5, t2, a2 -+ -+ nor a4, t2, a3 -+ and a6, a7, a6 -+ and a5, a5, a4 -+ or a7, a6, a5 -+ beqz a7, L(_aloop) -+ -+ L_ADDIU a0, a0, -8 -+L(_mc8_a): -+ -+ ctz.d t0, a5 -+ ctz.d t2, a6 -+ -+ srli.w t0, t0, 3 -+ srli.w t2, t2, 3 -+ sltu t1, t2, t0 -+ L_ADDU v0, a0, t0 -+ masknez v0, v0, t1 -+ jr ra -+END(STRCHR) -+ -+#ifndef ANDROID_CHANGES -+#ifdef _LIBC -+libc_hidden_builtin_def (strchr) -+weak_alias (strchr, index) -+#endif -+#endif -diff --git a/sysdeps/loongarch/lp64/strchrnul.S b/sysdeps/loongarch/lp64/strchrnul.S -new file mode 100644 -index 00000000..a57a5065 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/strchrnul.S -@@ -0,0 +1,156 @@ -+/* Copyright 2016 Loongson Technology Corporation Limited */ -+ -+/* Author: Songyuekun songyuekun@loongson.cn */ -+ -+/* -+ * ISA: MIPS64R2 -+ * ABI: N64 -+ */ -+ -+/* basic algorithm : -+ -+ +. use ld.d and mask for the first 8 bytes or less; -+ -+ +. build a1 with 8c with dins; -+ -+ +. use xor from a1 and v0 to check if is found; -+ -+ +. if (v0 - 0x0101010101010101) & (~(v0 | 0x7f7f7f7f7f7f7f7f)!= 0, v0 has -+ one byte is \0, else has no \0 -+ -+*/ -+ -+ -+ -+ -+#include -+#include -+ -+ -+ -+ -+ -+#define L_ADDIU addi.d -+#define L_ADDU add.d -+#define L_SUBU sub.d -+ -+#define STRCHRNUL __strchrnul -+ -+#define MOVN(rd,rs,rt) \ -+ maskeqz t6, rs, rt;\ -+ masknez rd, rd, rt;\ -+ or rd, rd, t6 -+ -+#define MOVZ(rd,rs,rt) \ -+ masknez t6, rs, rt;\ -+ maskeqz rd, rd, rt;\ -+ or rd, rd, t6 -+ -+ -+#define MOVN2(rd,rt) \ -+ masknez rd, rd, rt;\ -+ or rd, rd, rt -+ -+ -+/* char * strchrnul (const char *s1, int c); */ -+ -+LEAF(STRCHRNUL) -+ .align 6 -+ -+ li.w t4, 0x7 -+ lu12i.w a2, 0x01010 -+ bstrins.d a1, a1, 15, 8 -+ andi t0, a0, 0x7 -+ -+ ori a2, a2, 0x101 -+ andn t4, a0, t4 -+ slli.w t1, t0, 3 -+/* -+ ldr t4, 0(a0) -+*/ -+ ld.d t4, t4, 0 -+ -+ -+ nor t8, zero, zero -+ bstrins.d a1, a1, 31, 16 -+ srl.d t4, t4, t1 -+ -+ preld 0, a0, 32 -+ bstrins.d a1, a1, 63, 32 -+ bstrins.d a2, a2, 63, 32 -+ srl.d a7, t8, t1 -+ -+ nor t8, a7, zero -+ slli.d a3, a2, 7 -+ or t5, t8, t4 -+ and t3, a7, a1 -+ -+ nor a3, a3, zero -+ xor t2, t5, t3 -+ sub.d a7, t5, a2 -+ nor a6, t5, a3 -+ -+ li.w t1, 8 -+ sub.d a5, t2, a2 -+ nor a4, t2, a3 -+ -+ and a6, a7, a6 -+ and a5, a5, a4 -+ or a7, a6, a5 -+ bnez a7, L(_mc8_a) -+ -+ -+ sub.w t1, t1, t0 -+ L_ADDU a0, a0, t1 -+L(_aloop): -+ ld.d t4, a0, 0 -+ -+ xor t2, t4, a1 -+ sub.d a7, t4, a2 -+ nor a6, t4, a3 -+ sub.d a5, t2, a2 -+ -+ nor a4, t2, a3 -+ and a6, a7, a6 -+ and a5, a5, a4 -+ -+ or a7, a6, a5 -+ bnez a7, L(_mc8_a) -+ -+ ld.d t4, a0, 8 -+ L_ADDIU a0, a0, 16 -+ -+ xor t2, t4, a1 -+ sub.d a7, t4, a2 -+ nor a6, t4, a3 -+ sub.d a5, t2, a2 -+ -+ nor a4, t2, a3 -+ and a6, a7, a6 -+ and a5, a5, a4 -+ -+ or a7, a6, a5 -+ beqz a7, L(_aloop) -+ -+ L_ADDIU a0, a0, -8 -+L(_mc8_a): -+ -+ ctz.d t0, a5 -+ ctz.d t2, a6 -+ -+ srli.w t0, t0, 3 -+ srli.w t2, t2, 3 -+ slt t1, t0, t2 -+ -+ MOVZ(t0,t2,t1) -+ -+ L_ADDU v0, a0, t0 -+ jr ra -+END(STRCHRNUL) -+ -+#ifndef ANDROID_CHANGES -+#ifdef _LIBC -+weak_alias(__strchrnul, strchrnul) -+libc_hidden_builtin_def (__strchrnul) -+#endif -+#endif -diff --git a/sysdeps/loongarch/lp64/strcmp.S b/sysdeps/loongarch/lp64/strcmp.S -new file mode 100644 -index 00000000..11474bf2 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/strcmp.S -@@ -0,0 +1,197 @@ -+/* Copyright 2016 Loongson Technology Corporation Limited */ -+ -+/* Author: songyuekun songyuekun@loongson.cn */ -+ -+/* -+ * ISA: MIPS64R2 -+ * ABI: N64 -+ */ -+ -+/* basic algorithm : -+ -+ +. let t0, t1 point to a0, a1, if a0 has smaller low 3 bit of a0 and a1, -+ set a4 to 1 and let t0 point to the larger of lower 3bit of a0 and a1 -+ -+ +. if low 3 bit of a0 equal low 3 bit of a0, use a ldr one time and more ld other times; -+ -+ +. if not, load partial t2 and t3, check if t2 has \0; -+ -+ +. then use use ld for t0, ldr for t1, -+ -+ +. if partial 8 byte from t1 has \0, compare partial 8 byte from t1 with 8 -+ byte from t0 with a mask in a7 -+ -+ +. if not, ldl other part of t1, compare 8 byte from t1 with 8 byte from t0 -+ -+ +. if (v0 - 0x0101010101010101) & (~v0) & 0x8080808080808080 != 0, v0 has -+ one byte is \0, else has no \0 -+ -+ +. for partial 8 byte from ldr t3, 0(a0), preload t3 with 0xffffffffffffffff -+ -+ -+*/ -+#include -+#include -+ -+ -+#define STRCMP strcmp -+ -+#define REP8_01 0x0101010101010101 -+#define REP8_7f 0x7f7f7f7f7f7f7f7f -+#define REP8_80 0x8080808080808080 -+ -+/* Parameters and Results */ -+#define src1 a0 -+#define src2 a1 -+#define result v0 -+// Note: v0 = a0 in N64 ABI -+ -+ -+/* Internal variable */ -+#define data1 t0 -+#define data2 t1 -+#define has_nul t2 -+#define diff t3 -+#define syndrome t4 -+#define zeroones t5 -+#define sevenf t6 -+#define pos t7 -+#define exchange t8 -+#define tmp1 a4 -+#define tmp2 a5 -+#define tmp3 a6 -+#define src1_off a2 -+#define src2_off a3 -+#define tmp4 a7 -+ -+/* rd <- if rc then ra else rb -+ will destroy tmp3 -+*/ -+#define CONDITIONSEL(rd,rc,ra,rb)\ -+ masknez tmp3, rb, rc;\ -+ maskeqz rd, ra, rc;\ -+ or rd, rd, tmp3 -+ -+ -+ -+/* int strcmp (const char *s1, const char *s2); */ -+ -+LEAF(STRCMP) -+ .align 4 -+ -+ xor tmp1, src1, src2 -+ lu12i.w zeroones, 0x01010 -+ lu12i.w sevenf, 0x7f7f7 -+ andi src1_off, src1, 0x7 -+ ori zeroones, zeroones, 0x101 -+ ori sevenf, sevenf, 0xf7f -+ andi tmp1, tmp1, 0x7 -+ bstrins.d zeroones, zeroones, 63, 32 -+ bstrins.d sevenf, sevenf, 63, 32 -+ bnez tmp1, strcmp_misaligned8 -+ bnez src1_off, strcmp_mutual_align -+strcmp_loop_aligned: -+ ld.d data1, src1, 0 -+ addi.d src1, src1, 8 -+ ld.d data2, src2, 0 -+ addi.d src2, src2, 8 -+strcmp_start_realigned: -+ sub.d tmp1, data1, zeroones -+ or tmp2, data1, sevenf -+ xor diff, data1, data2 -+ andn has_nul, tmp1, tmp2 -+ or syndrome, diff, has_nul -+ beqz syndrome, strcmp_loop_aligned -+ -+strcmp_end: -+ ctz.d pos, syndrome -+ bstrins.d pos, zero, 2, 0 -+ srl.d data1, data1, pos -+ srl.d data2, data2, pos -+ andi data1, data1, 0xff -+ andi data2, data2, 0xff -+ sub.d result, data1, data2 -+ jr ra -+strcmp_mutual_align: -+ bstrins.d src1, zero, 2, 0 -+ bstrins.d src2, zero, 2, 0 -+ slli.d tmp1, src1_off, 0x3 -+ ld.d data1, src1, 0 -+ sub.d tmp1, zero, tmp1 -+ ld.d data2, src2, 0 -+ addi.d src1, src1, 8 -+ addi.d src2, src2, 8 -+ nor tmp2, zero, zero -+ srl.d tmp2, tmp2, tmp1 -+ or data1, data1, tmp2 -+ or data2, data2, tmp2 -+ b strcmp_start_realigned -+ -+strcmp_misaligned8: -+ -+/* check -+ if ((src1 != 0) && ((src2 == 0 ) || (src1 < src2))) -+ then exchange(src1,src2) -+ -+*/ -+ andi src2_off, src2, 0x7 -+ slt tmp2, src1_off, src2_off -+ CONDITIONSEL(tmp2,src2_off,tmp2,tmp1) -+ maskeqz exchange, tmp2, src1_off -+ xor tmp3, src1, src2 -+ maskeqz tmp3, tmp3, exchange -+ xor src1, src1, tmp3 -+ xor src2, src2, tmp3 -+ -+ andi src1_off, src1, 0x7 -+ beqz src1_off, strcmp_loop_misaligned -+strcmp_do_misaligned: -+ ld.bu data1, src1, 0 -+ ld.bu data2, src2, 0 -+ xor tmp3, data1, data2 -+ addi.d src1, src1, 1 -+ masknez tmp3, data1, tmp3 -+ addi.d src2, src2, 1 -+ beqz tmp3, strcmp_done -+ andi src1_off, src1, 0x7 -+ bnez src1_off, strcmp_do_misaligned -+ -+strcmp_loop_misaligned: -+ andi tmp1, src2, 0xff8 -+ xori tmp1, tmp1, 0xff8 -+ beqz tmp1, strcmp_do_misaligned -+ ld.d data1, src1, 0 -+ ld.d data2, src2, 0 -+ addi.d src1, src1, 8 -+ addi.d src2, src2, 8 -+ -+ sub.d tmp1, data1, zeroones -+ or tmp2, data1, sevenf -+ xor diff, data1, data2 -+ andn has_nul, tmp1, tmp2 -+ or syndrome, diff, has_nul -+ beqz syndrome, strcmp_loop_misaligned -+// b strcmp_end -+strcmp_misalign_end: -+ ctz.d pos, syndrome -+ bstrins.d pos, zero, 2, 0 -+ srl.d data1, data1, pos -+ srl.d data2, data2, pos -+ andi data1, data1, 0xff -+ andi data2, data2, 0xff -+ sub.d tmp1, data1, data2 -+ sub.d tmp2, data2, data1 -+ CONDITIONSEL(result,exchange,tmp2,tmp1) -+ jr ra -+ -+strcmp_done: -+ sub.d tmp1, data1, data2 -+ sub.d tmp2, data2, data1 -+ CONDITIONSEL(result,exchange,tmp2,tmp1) -+ jr ra -+END(STRCMP) -+#ifndef ANDROID_CHANGES -+#ifdef _LIBC -+libc_hidden_builtin_def (strcmp) -+#endif -+#endif -diff --git a/sysdeps/loongarch/lp64/strcpy.S b/sysdeps/loongarch/lp64/strcpy.S -new file mode 100644 -index 00000000..ce39e5a1 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/strcpy.S -@@ -0,0 +1,210 @@ -+/* Copyright 2016 Loongson Technology Corporation Limited */ -+ -+/* Author: Huang Pei huangpei@loongson.cn */ -+ -+/* -+ * ISA: MIPS64R2 -+ * ABI: N64 -+ */ -+ -+/* basic algorithm : -+ -+ +. if src aligned. just do the copy loop. if not, do the cross page check and copy one double word. -+ -+ Then move src to aligned. -+ -+ +. if (v0 - 0x0101010101010101) & (~v0) & 0x8080808080808080 != 0, v0 has -+ one byte is \0, else has no \0 -+ -+ -+*/ -+ -+ -+#include -+#include -+ -+ -+#define STRCPY strcpy -+ -+ -+#define REP8_01 0x0101010101010101 -+#define REP8_7f 0x7f7f7f7f7f7f7f7f -+#define REP8_80 0x8080808080808080 -+ -+/* Parameters and Results */ -+#define dest a0 -+#define src a1 -+#define result v0 -+// Note: v0 = a0 in N64 ABI -+ -+ -+/* Internal variable */ -+#define data t0 -+#define data1 t1 -+#define has_nul t2 -+#define diff t3 -+#define syndrome t4 -+#define zeroones t5 -+#define sevenf t6 -+#define pos t7 -+#define dest_backup t8 -+#define tmp1 a4 -+#define tmp2 a5 -+#define tmp3 a6 -+#define dest_off a2 -+#define src_off a3 -+#define tmp4 a7 -+ -+/* rd <- if rc then ra else rb -+ will destroy tmp3 -+*/ -+#define CONDITIONSEL(rd,rc,ra,rb)\ -+ masknez tmp3, rb, rc;\ -+ maskeqz rd, ra, rc;\ -+ or rd, rd, tmp3 -+ -+ -+ -+/* int strcpy (const char *s1, const char *s2); */ -+ -+LEAF(STRCPY) -+ .align 4 -+ -+ move dest_backup, dest -+ lu12i.w zeroones, 0x01010 -+ lu12i.w sevenf, 0x7f7f7 -+ ori zeroones, zeroones, 0x101 -+ ori sevenf, sevenf, 0xf7f -+ bstrins.d zeroones, zeroones, 63, 32 -+ bstrins.d sevenf, sevenf, 63, 32 -+ andi src_off, src, 0x7 -+ beqz src_off, strcpy_loop_aligned_1 -+ b strcpy_mutual_align -+strcpy_loop_aligned: -+ st.d data, dest, 0 -+ addi.d dest, dest, 8 -+strcpy_loop_aligned_1: -+ ld.d data, src, 0 -+ addi.d src, src, 8 -+strcpy_start_realigned: -+ sub.d tmp1, data, zeroones -+ or tmp2, data, sevenf -+ andn has_nul, tmp1, tmp2 -+ beqz has_nul, strcpy_loop_aligned -+ -+strcpy_end: -+ -+/* -+8 4 2 1 -+*/ -+ ctz.d pos, has_nul -+ srli.d pos, pos, 3 -+ addi.d pos, pos, 1 -+/* -+ Do 8/4/2/1 strcpy based on pos value. -+ pos value is the number of bytes to be copied -+ the bytes include the final \0 so the max length is 8 and the min length is 1 -+*/ -+ -+strcpy_end_8: -+ andi tmp1, pos, 0x8 -+ beqz tmp1, strcpy_end_4 -+ st.d data, dest, 0 -+ move dest, dest_backup -+ jr ra -+strcpy_end_4: -+ andi tmp1, pos, 0x4 -+ beqz tmp1, strcpy_end_2 -+ st.w data, dest, 0 -+ srli.d data, data, 32 -+ addi.d dest, dest, 4 -+strcpy_end_2: -+ andi tmp1, pos, 0x2 -+ beqz tmp1, strcpy_end_1 -+ st.h data, dest, 0 -+ srli.d data, data, 16 -+ addi.d dest, dest, 2 -+strcpy_end_1: -+ andi tmp1, pos, 0x1 -+ beqz tmp1, strcpy_end_ret -+ st.b data, dest, 0 -+strcpy_end_ret: -+ move result, dest_backup -+ jr ra -+ -+ -+strcpy_mutual_align: -+/* -+ Check if around src page bound. -+ if not go to page cross ok. -+ if it is, do further check. -+ use tmp2 to accelerate. -+*/ -+ -+ li.w tmp2, 0xff8 -+ andi tmp1, src, 0xff8 -+ beq tmp1, tmp2, strcpy_page_cross -+ -+strcpy_page_cross_ok: -+/* -+ Load a misaligned double word and check if has \0 -+ If no, do a misaligned double word paste. -+ If yes, calculate the number of avaliable bytes, -+ then jump to 4/2/1 end. -+*/ -+ ld.d data, src, 0 -+ sub.d tmp1, data, zeroones -+ or tmp2, data, sevenf -+ andn has_nul, tmp1, tmp2 -+ bnez has_nul, strcpy_end -+strcpy_mutual_align_finish: -+/* -+ Before jump back to align loop, make dest/src aligned. -+ This will cause a duplicated paste for several bytes between the first double word and the second double word, -+ but should not bring a problem. -+*/ -+ li.w tmp1, 8 -+ st.d data, dest, 0 -+ sub.d tmp1, tmp1, src_off -+ add.d src, src, tmp1 -+ add.d dest, dest, tmp1 -+ -+ b strcpy_loop_aligned_1 -+ -+strcpy_page_cross: -+/* -+ ld.d from aligned address(src & ~0x7). -+ check if high bytes have \0. -+ it not, go back to page cross ok, -+ since the string is supposed to cross the page bound in such situation. -+ if it is, do a srl for data to make it seems like a direct double word from src, -+ then go to 4/2/1 strcpy end. -+ -+ tmp4 is 0xffff...ffff mask -+ tmp2 demonstrate the bytes to be masked -+ tmp2 = src_off << 3 -+ data = data >> (src_off * 8) | -1 << (64 - src_off * 8) -+ and -+ -1 << (64 - src_off * 8) -> ~(-1 >> (src_off * 8)) -+ -+*/ -+ li.w tmp1, 0x7 -+ andn tmp3, src, tmp1 -+ ld.d data, tmp3, 0 -+ li.w tmp4, -1 -+ slli.d tmp2, src_off, 3 -+ srl.d tmp4, tmp4, tmp2 -+ srl.d data, data, tmp2 -+ nor tmp4, tmp4, zero -+ or data, data, tmp4 -+ sub.d tmp1, data, zeroones -+ or tmp2, data, sevenf -+ andn has_nul, tmp1, tmp2 -+ beqz has_nul, strcpy_page_cross_ok -+ b strcpy_end -+END(STRCPY) -+#ifndef ANDROID_CHANGES -+#ifdef _LIBC -+libc_hidden_builtin_def (strcpy) -+#endif -+#endif -diff --git a/sysdeps/loongarch/lp64/strlen.S b/sysdeps/loongarch/lp64/strlen.S -new file mode 100644 -index 00000000..a34d8b69 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/strlen.S -@@ -0,0 +1,135 @@ -+/* Copyright 2016 Loongson Technology Corporation Limited */ -+ -+/* Author: Songyuekun songyuekun@loongson.cn */ -+ -+/* -+ * ISA: MIPS64R2 -+ * ABI: N64 -+ */ -+/* -+algorithm: -+ -+ #. use ld/ldr to access word/partial word in the string -+ -+ #. use (x - 0x0101010101010101) & (~(x | 0x7f7f7f7f7f7f7f7f) != 0 to -+ judge if x has zero byte -+ -+ #. use dctz((x - 0x0101010101010101) & (~(x | 0x7f7f7f7f7f7f7f7f) >> 3 -+ to get the index of first rightmost zero byte in dword x; -+ -+ #. use dctz(x) = 64 - dclz(~x & (x-1)); -+ -+ #. use pointer to the last non zero byte minus pointer to the start -+ of the string to get the length of string -+ -+*/ -+ -+ -+#include -+#include -+ -+ -+ -+#define L_ADDIU addi.d -+#define L_ADDU add.d -+#define L_SUBU sub.d -+ -+#define STRLEN strlen -+#define L(x) x -+ -+ -+/* size_t strlen (const char *s1); */ -+ -+ .text; -+ .globl strlen; -+ .align 5; -+ cfi_startproc ; -+ .type strlen, @function; -+strlen: -+ -+ //LEAF(strlen) -+ #preld 0, a0, 0 -+ -+ nor t4, zero, zero -+ lu12i.w a2, 0x01010 -+ andi t5, a0, 0x7 -+ -+ li.w t7, 0x7 -+ slli.d t6, t5, 0x3 -+ andn t7, a0, t7 -+ ld.d a1, t7, 0 -+ sub.d t7, zero, t6 -+ sll.d t4, t4, t7 -+ maskeqz t4, t4, t6 -+ srl.d a1, a1, t6 -+ or a1, a1, t4 -+ -+ -+ ori a2, a2, 0x101 -+ nor t1, a1, zero -+ li.w a4, 8 -+ -+ #preld 0, a0, 32 -+ bstrins.d a2, a2, 63, 32 -+ sub.d a5, a4, t5 -+ move t5, a0 -+ -+ sub.d t0, a1, a2 -+ slli.d t4, a2, 7 -+ nor a3, zero, t4 -+ nor t1, a1, a3 -+ -+ and t0, t0, t1 -+ #preld 0, a0, 64 -+ bnez t0, strlen_count1 /* instead of use bnel with daddu a0, a0, a5 in branch slot */ -+ L_ADDU a0, a0, a5 -+strlen_loop: -+ ld.d a1, a0, 0 -+ sub.d t0, a1, a2 -+ and t1, t0, t4 -+ bnez t1, strlen_count_pre -+ ld.d a1, a0, 8 -+ sub.d t0, a1, a2 -+ and t1, t0, t4 -+ L_ADDIU a0, a0, 16 -+ beqz t1, strlen_loop -+strlen_count: -+ addi.d a0, a0, -8 -+strlen_count_pre: -+ nor t1, a1, a3 -+ and t0, t0, t1 -+ beqz t0, strlen_noascii_start -+strlen_count1: -+ ctz.d t1, t0 -+ L_SUBU v0, a0, t5 -+ srli.w t1, t1, 3 -+ L_ADDU v0, v0, t1 -+ jr ra -+strlen_noascii_start: -+ addi.d a0, a0, 8 -+strlen_loop_noascii: -+ ld.d a1, a0, 0 -+ sub.d t0, a1, a2 -+ nor t1, a1, a3 -+ and t0, t0, t1 -+ bnez t0, strlen_count1 -+ ld.d a1, a0, 8 -+ sub.d t0, a1, a2 -+ nor t1, a1, a3 -+ and t0, t0, t1 -+ L_ADDIU a0, a0, 16 -+ beqz t0, strlen_loop_noascii -+ addi.d a0, a0, -8 -+ ctz.d t1, t0 -+ L_SUBU v0, a0, t5 -+ srli.w t1, t1, 3 -+ L_ADDU v0, v0, t1 -+ jr ra -+END(STRLEN) -+ -+#ifndef ANDROID_CHANGES -+#ifdef _LIBC -+libc_hidden_builtin_def (strlen) -+#endif -+#endif -+ -diff --git a/sysdeps/loongarch/lp64/strncmp.S b/sysdeps/loongarch/lp64/strncmp.S -new file mode 100644 -index 00000000..29cc7b02 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/strncmp.S -@@ -0,0 +1,269 @@ -+/* Copyright 2016 Loongson Technology Corporation Limited */ -+ -+/* Author: songyuekun songyuekun@loongson.cn */ -+ -+/* -+ * ISA: MIPS64R2 -+ * ABI: N64 -+ */ -+ -+/* basic algorithm : -+ -+ +. let t0, t1 point to a0, a1, if a0 has smaller low 3 bit of a0 and a1, -+ set a4 to 1 and let t0 point to the larger of lower 3bit of a0 and a1 -+ -+ +. if low 3 bit of a0 equal low 3 bit of a0, use a ldr one time and more ld other times; -+ -+ +. if not, load partial t2 and t3, check if t2 has \0; -+ -+ +. then use use ld for t0, ldr for t1, -+ -+ +. if partial 8 byte from t1 has \0, compare partial 8 byte from t1 with 8 -+ byte from t0 with a mask in a7 -+ -+ +. if not, ldl other part of t1, compare 8 byte from t1 with 8 byte from t0 -+ -+ +. if (v0 - 0x0101010101010101) & (~v0) & 0x8080808080808080 != 0, v0 has -+ one byte is \0, else has no \0 -+ -+ +. for partial 8 byte from ldr t3, 0(a0), preload t3 with 0xffffffffffffffff -+ -+ -+*/ -+#include -+#include -+ -+ -+#define STRNCMP strncmp -+ -+#define REP8_01 0x0101010101010101 -+#define REP8_7f 0x7f7f7f7f7f7f7f7f -+#define REP8_80 0x8080808080808080 -+ -+/* Parameters and Results */ -+#define src1 a0 -+#define src2 a1 -+#define limit a2 -+#define result v0 -+// Note: v0 = a0 in N64 ABI -+ -+ -+/* Internal variable */ -+#define data1 t0 -+#define data2 t1 -+#define has_nul t2 -+#define diff t3 -+#define syndrome t4 -+#define zeroones t5 -+#define sevenf t6 -+#define pos t7 -+#define exchange t8 -+#define tmp1 a5 -+#define tmp2 a6 -+#define tmp3 a7 -+#define src1_off a3 -+#define limit_wd a4 -+ -+ -+/* int strncmp (const char *s1, const char *s2); */ -+ -+LEAF(STRNCMP) -+ .align 4 -+ beqz limit, strncmp_ret0 -+ -+ xor tmp1, src1, src2 -+ lu12i.w zeroones, 0x01010 -+ lu12i.w sevenf, 0x7f7f7 -+ andi src1_off, src1, 0x7 -+ ori zeroones, zeroones, 0x101 -+ andi tmp1, tmp1, 0x7 -+ ori sevenf, sevenf, 0xf7f -+ bstrins.d zeroones, zeroones, 63, 32 -+ bstrins.d sevenf, sevenf, 63, 32 -+ bnez tmp1, strncmp_misaligned8 -+ bnez src1_off, strncmp_mutual_align -+ /* */ -+ addi.d limit_wd, limit, -1 -+ srli.d limit_wd, limit_wd, 3 -+ -+strncmp_loop_aligned: -+ ld.d data1, src1, 0 -+ addi.d src1, src1, 8 -+ ld.d data2, src2, 0 -+ addi.d src2, src2, 8 -+strncmp_start_realigned: -+ addi.d limit_wd, limit_wd, -1 -+ sub.d tmp1, data1, zeroones -+ or tmp2, data1, sevenf -+ xor diff, data1, data2 -+ andn has_nul, tmp1, tmp2 -+ srli.d tmp1, limit_wd, 63 -+ or syndrome, diff, has_nul -+ or tmp2, syndrome, tmp1 -+ beqz tmp2, strncmp_loop_aligned -+ -+ /* if not reach limit */ -+ bge limit_wd, zero, strncmp_not_limit -+ /* if reach limit */ -+ andi limit, limit, 0x7 -+ li.w tmp1, 0x8 -+ sub.d limit, tmp1, limit -+ slli.d limit, limit, 0x3 -+ li.d tmp1, -1 -+ srl.d tmp1, tmp1, limit -+ and data1, data1, tmp1 -+ and data2, data2, tmp1 -+ orn syndrome, syndrome, tmp1 -+ -+ -+strncmp_not_limit: -+ ctz.d pos, syndrome -+ bstrins.d pos, zero, 2, 0 -+ srl.d data1, data1, pos -+ srl.d data2, data2, pos -+ andi data1, data1, 0xff -+ andi data2, data2, 0xff -+ sub.d result, data1, data2 -+ jr ra -+ -+ -+ -+strncmp_mutual_align: -+ bstrins.d src1, zero, 2, 0 -+ bstrins.d src2, zero, 2, 0 -+ slli.d tmp1, src1_off, 0x3 -+ ld.d data1, src1, 0 -+ ld.d data2, src2, 0 -+ addi.d src2, src2, 8 -+ addi.d src1, src1, 8 -+ -+ addi.d limit_wd, limit, -1 -+ andi tmp3, limit_wd, 0x7 -+ srli.d limit_wd, limit_wd, 3 -+ add.d limit, limit, src1_off -+ add.d tmp3, tmp3, src1_off -+ srli.d tmp3, tmp3, 3 -+ add.d limit_wd, limit_wd, tmp3 -+ -+ sub.d tmp1, zero, tmp1 -+ nor tmp2, zero, zero -+ srl.d tmp2, tmp2, tmp1 -+ or data1, data1, tmp2 -+ or data2, data2, tmp2 -+ b strncmp_start_realigned -+ -+strncmp_misaligned8: -+ -+ li.w tmp1, 0x10 -+ bge limit, tmp1, strncmp_try_words -+strncmp_byte_loop: -+ ld.bu data1, src1, 0 -+ ld.bu data2, src2, 0 -+ addi.d limit, limit, -1 -+ xor tmp1, data1, data2 -+ masknez tmp1, data1, tmp1 -+ maskeqz tmp1, limit, tmp1 -+ beqz tmp1, strncmp_done -+ -+ ld.bu data1, src1, 1 -+ ld.bu data2, src2, 1 -+ addi.d src1, src1, 2 -+ addi.d src2, src2, 2 -+ addi.d limit, limit, -1 -+ xor tmp1, data1, data2 -+ masknez tmp1, data1, tmp1 -+ maskeqz tmp1, limit, tmp1 -+ bnez tmp1, strncmp_byte_loop -+ -+ -+strncmp_done: -+ sub.d result, data1, data2 -+ jr ra -+ -+strncmp_try_words: -+ srli.d limit_wd, limit, 3 -+ beqz src1_off, strncmp_do_misaligned -+ -+ sub.d src1_off, zero, src1_off -+ andi src1_off, src1_off, 0x7 -+ sub.d limit, limit, src1_off -+ srli.d limit_wd, limit, 0x3 -+ -+ -+strncmp_page_end_loop: -+ ld.bu data1, src1, 0 -+ ld.bu data2, src2, 0 -+ addi.d src1, src1, 1 -+ addi.d src2, src2, 1 -+ xor tmp1, data1, data2 -+ masknez tmp1, data1, tmp1 -+ beqz tmp1, strncmp_done -+ andi tmp1, src1, 0x7 -+ bnez tmp1, strncmp_page_end_loop -+strncmp_do_misaligned: -+ li.w src1_off, 0x8 -+ addi.d limit_wd, limit_wd, -1 -+ blt limit_wd, zero, strncmp_done_loop -+ -+strncmp_loop_misaligned: -+ andi tmp2, src2, 0xff8 -+ xori tmp2, tmp2, 0xff8 -+ beqz tmp2, strncmp_page_end_loop -+ -+ ld.d data1, src1, 0 -+ ld.d data2, src2, 0 -+ addi.d src1, src1, 8 -+ addi.d src2, src2, 8 -+ sub.d tmp1, data1, zeroones -+ or tmp2, data1, sevenf -+ xor diff, data1, data2 -+ andn has_nul, tmp1, tmp2 -+ or syndrome, diff, has_nul -+ bnez syndrome, strncmp_not_limit -+ addi.d limit_wd, limit_wd, -1 -+ #blt zero, limit_wd, strncmp_loop_misaligned -+ bge limit_wd, zero, strncmp_loop_misaligned -+ -+strncmp_done_loop: -+ andi limit, limit, 0x7 -+ beqz limit, strncmp_not_limit -+ /* Read the last double word */ -+ /* check if the final part is about to exceed the page */ -+ andi tmp1, src2, 0x7 -+ andi tmp2, src2, 0xff8 -+ add.d tmp1, tmp1, limit -+ xori tmp2, tmp2, 0xff8 -+ andi tmp1, tmp1, 0x8 -+ masknez tmp1, tmp1, tmp2 -+ bnez tmp1, strncmp_byte_loop -+ addi.d src1, src1, -8 -+ addi.d src2, src2, -8 -+ ldx.d data1, src1, limit -+ ldx.d data2, src2, limit -+ sub.d tmp1, data1, zeroones -+ or tmp2, data1, sevenf -+ xor diff, data1, data2 -+ andn has_nul, tmp1, tmp2 -+ or syndrome, diff, has_nul -+ bnez syndrome, strncmp_not_limit -+ -+strncmp_ret0: -+ move result, zero -+ jr ra -+/* check -+ if ((src1 != 0) && ((src2 == 0 ) || (src1 < src2))) -+ then exchange(src1,src2) -+ -+*/ -+ -+ -+ -+ -+ -+ -+END(STRNCMP) -+#ifndef ANDROID_CHANGES -+#ifdef _LIBC -+libc_hidden_builtin_def (strncmp) -+#endif -+#endif -diff --git a/sysdeps/loongarch/lp64/strnlen.S b/sysdeps/loongarch/lp64/strnlen.S -new file mode 100644 -index 00000000..3a204686 ---- /dev/null -+++ b/sysdeps/loongarch/lp64/strnlen.S -@@ -0,0 +1,155 @@ -+/* Copyright 2016 Loongson Technology Corporation Limited */ -+ -+/* Author: Songyuekun songyuekun@loongson.cn */ -+ -+/* -+ * ISA: MIPS64R2 -+ * ABI: N64 -+ */ -+/* -+algorithm: -+ -+ #. use ld/ldr to access word/partial word in the string -+ -+ #. use (x - 0x0101010101010101) & (~(x | 0x7f7f7f7f7f7f7f7f) != 0 to -+ judge if x has zero byte -+ -+ #. use dctz((x - 0x0101010101010101) & (~(x | 0x7f7f7f7f7f7f7f7f) >> 3 -+ to get the index of first rightmost zero byte in dword x; -+ -+ #. use dctz(x) = 64 - dclz(~x & (x-1)); -+ -+ #. use pointer to the last non zero byte minus pointer to the start -+ of the string to get the length of string -+ -+*/ -+ -+#include -+#include -+ -+ -+ -+#define L_ADDIU addi.d -+#define L_ADDU add.d -+#define L_SUBU sub.d -+ -+#define STRNLEN __strnlen -+#define L(x) x -+/* rd <- if rc then ra else rb -+ will destroy t6 -+*/ -+ -+#define CONDITIONSEL(rd,ra,rb,rc)\ -+ masknez a5, rb, rc;\ -+ maskeqz rd, ra, rc;\ -+ or rd, rd, a5 -+ -+ -+/* Parameters and Results */ -+#define srcin a0 -+#define limit a1 -+#define len v0 -+ -+ -+/* Internal variable */ -+#define data1 t0 -+#define data2 t1 -+#define has_nul1 t2 -+#define has_nul2 t3 -+#define src t4 -+#define zeroones t5 -+#define sevenf t6 -+#define data2a t7 -+#define tmp6 t7 -+#define pos t8 -+#define tmp1 a2 -+#define tmp2 a3 -+#define tmp3 a4 -+#define tmp4 a5 -+#define tmp5 a6 -+#define limit_wd a7 -+ -+ -+ -+/* size_t strnlen (const char *s1,size_t maxlen); */ -+ -+LEAF(STRNLEN) -+ -+ .align 4 -+ beqz limit, L(_hit_limit) -+ lu12i.w zeroones, 0x01010 -+ lu12i.w sevenf, 0x7f7f7 -+ ori zeroones, zeroones, 0x101 -+ ori sevenf, sevenf, 0xf7f -+ bstrins.d zeroones, zeroones, 63, 32 -+ bstrins.d sevenf, sevenf, 63, 32 -+ andi tmp1, srcin, 15 -+ sub.d src, srcin, tmp1 -+ bnez tmp1, L(misaligned) -+ addi.d limit_wd, limit, -1 -+ srli.d limit_wd, limit_wd, 4 -+L(_loop): -+ ld.d data1, src, 0 -+ ld.d data2, src, 8 -+ addi.d src, src, 16 -+L(_realigned): -+ sub.d tmp1, data1, zeroones -+ or tmp2, data1, sevenf -+ sub.d tmp3, data2, zeroones -+ or tmp4, data2, sevenf -+ andn has_nul1, tmp1, tmp2 -+ andn has_nul2, tmp3, tmp4 -+ addi.d limit_wd, limit_wd, -1 -+ srli.d tmp1, limit_wd, 63 -+ or tmp2, has_nul1, has_nul2 -+ or tmp3, tmp1, tmp2 -+ beqz tmp3, L(_loop) -+ beqz tmp2, L(_hit_limit) -+ sub.d len, src, srcin -+ beqz has_nul1, L(_nul_in_data2) -+ move has_nul2, has_nul1 -+ addi.d len, len, -8 -+L(_nul_in_data2): -+ ctz.d pos, has_nul2 -+ srli.d pos, pos, 3 -+ addi.d len, len, -8 -+ add.d len, len, pos -+ sltu tmp1, len, limit -+ CONDITIONSEL(len,len,limit,tmp1) -+ jr ra -+ -+ -+L(misaligned): -+ addi.d limit_wd, limit, -1 -+ sub.d tmp4, zero, tmp1 -+ andi tmp3, limit_wd, 15 -+ srli.d limit_wd, limit_wd, 4 -+ li.d tmp5, -1 -+ ld.d data1, src, 0 -+ ld.d data2, src, 8 -+ addi.d src, src, 16 -+ slli.d tmp4, tmp4, 3 -+ add.d tmp3, tmp3, tmp1 -+ srl.d tmp2, tmp5, tmp4 -+ srli.d tmp3, tmp3, 4 -+ add.d limit_wd, limit_wd, tmp3 -+ or data1, data1, tmp2 -+ or data2a, data2, tmp2 -+ li.w tmp3, 9 -+ sltu tmp1, tmp1, tmp3 -+ CONDITIONSEL(data1,data1,tmp5,tmp1) -+ CONDITIONSEL(data2,data2,data2a,tmp1) -+ b L(_realigned) -+ -+ -+L(_hit_limit): -+ move len, limit -+ jr ra -+END(STRNLEN) -+#ifndef ANDROID_CHANGES -+#ifdef _LIBC -+weak_alias (__strnlen, strnlen) -+libc_hidden_def (strnlen) -+libc_hidden_def (__strnlen) -+#endif -+#endif -diff --git a/sysdeps/loongarch/lstat.c b/sysdeps/loongarch/lstat.c -new file mode 100644 -index 00000000..f47a56af ---- /dev/null -+++ b/sysdeps/loongarch/lstat.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/lstat64.c b/sysdeps/loongarch/lstat64.c -new file mode 100644 -index 00000000..d6811656 ---- /dev/null -+++ b/sysdeps/loongarch/lstat64.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/machine-gmon.h b/sysdeps/loongarch/machine-gmon.h -new file mode 100644 -index 00000000..0b49082d ---- /dev/null -+++ b/sysdeps/loongarch/machine-gmon.h -@@ -0,0 +1,37 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+/* Accept 'frompc' address as argument from the function that calls -+ _mcount for profiling. Use __builtin_return_address (0) -+ for the 'selfpc' address. */ -+ -+#include -+ -+static void mcount_internal (unsigned long int frompc, -+ unsigned long int selfpc); -+ -+#define _MCOUNT_DECL(frompc, selfpc) \ -+static inline void mcount_internal (unsigned long int frompc, \ -+unsigned long int selfpc) -+ -+#define MCOUNT \ -+void _mcount (void *frompc) \ -+{ \ -+ mcount_internal ((unsigned long int) frompc, \ -+ (unsigned long int) RETURN_ADDRESS (0)); \ -+} -diff --git a/sysdeps/loongarch/math_private.h b/sysdeps/loongarch/math_private.h -new file mode 100644 -index 00000000..140eef07 ---- /dev/null -+++ b/sysdeps/loongarch/math_private.h -@@ -0,0 +1,245 @@ -+/* Internal math stuff. LOONGARCH version. -+ Copyright (C) 2013-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#ifndef LOONGARCH_MATH_PRIVATE_H -+#define LOONGARCH_MATH_PRIVATE_H 1 -+ -+/* Inline functions to speed up the math library implementation. The -+ default versions of these routines are in generic/math_private.h -+ and call fesetround, feholdexcept, etc. These routines use inlined -+ code instead. */ -+ -+#ifdef __loongarch_hard_float -+ -+# include -+# include -+# include -+ -+# define _FPU_MASK_ALL (_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O \ -+ |_FPU_MASK_U | _FPU_MASK_I | FE_ALL_EXCEPT) -+ -+static __always_inline void -+libc_feholdexcept_loongarch (fenv_t *envp) -+{ -+ fpu_control_t cw; -+ -+ /* Save the current state. */ -+ _FPU_GETCW (cw); -+ envp->__fp_control_register = cw; -+ -+ /* Clear all exception enable bits and flags. */ -+ cw &= ~(_FPU_MASK_ALL); -+ _FPU_SETCW (cw); -+} -+# define libc_feholdexcept libc_feholdexcept_loongarch -+# define libc_feholdexceptf libc_feholdexcept_loongarch -+# define libc_feholdexceptl libc_feholdexcept_loongarch -+ -+static __always_inline void -+libc_fesetround_loongarch (int round) -+{ -+ fpu_control_t cw; -+ -+ /* Get current state. */ -+ _FPU_GETCW (cw); -+ -+ /* Set rounding bits. */ -+ cw &= ~_FPU_RC_MASK; -+ cw |= round; -+ -+ /* Set new state. */ -+ _FPU_SETCW (cw); -+} -+# define libc_fesetround libc_fesetround_loongarch -+# define libc_fesetroundf libc_fesetround_loongarch -+# define libc_fesetroundl libc_fesetround_loongarch -+ -+static __always_inline void -+libc_feholdexcept_setround_loongarch (fenv_t *envp, int round) -+{ -+ fpu_control_t cw; -+ -+ /* Save the current state. */ -+ _FPU_GETCW (cw); -+ envp->__fp_control_register = cw; -+ -+ /* Clear all exception enable bits and flags. */ -+ cw &= ~(_FPU_MASK_ALL); -+ -+ /* Set rounding bits. */ -+ cw &= ~_FPU_RC_MASK; -+ cw |= round; -+ -+ /* Set new state. */ -+ _FPU_SETCW (cw); -+} -+# define libc_feholdexcept_setround libc_feholdexcept_setround_loongarch -+# define libc_feholdexcept_setroundf libc_feholdexcept_setround_loongarch -+# define libc_feholdexcept_setroundl libc_feholdexcept_setround_loongarch -+ -+# define libc_feholdsetround libc_feholdexcept_setround_loongarch -+# define libc_feholdsetroundf libc_feholdexcept_setround_loongarch -+# define libc_feholdsetroundl libc_feholdexcept_setround_loongarch -+ -+static __always_inline void -+libc_fesetenv_loongarch (fenv_t *envp) -+{ -+ fpu_control_t cw __attribute__ ((unused)); -+ -+ /* Read current state to flush fpu pipeline. */ -+ _FPU_GETCW (cw); -+ -+ _FPU_SETCW (envp->__fp_control_register); -+} -+# define libc_fesetenv libc_fesetenv_loongarch -+# define libc_fesetenvf libc_fesetenv_loongarch -+# define libc_fesetenvl libc_fesetenv_loongarch -+ -+static __always_inline int -+libc_feupdateenv_test_loongarch (fenv_t *envp, int excepts) -+{ -+ /* int ret = fetestexcept (excepts); feupdateenv (envp); return ret; */ -+ int cw, temp; -+ -+ /* Get current control word. */ -+ _FPU_GETCW (cw); -+ -+ /* Set flag bits (which are accumulative), and *also* set the -+ cause bits. The setting of the cause bits is what actually causes -+ the hardware to generate the exception, if the corresponding enable -+ bit is set as well. */ -+ temp = cw & FE_ALL_EXCEPT; -+ temp |= envp->__fp_control_register | (temp << CAUSE_SHIFT); -+ -+ /* Set new state. */ -+ _FPU_SETCW (temp); -+ -+ return cw & excepts & FE_ALL_EXCEPT; -+} -+# define libc_feupdateenv_test libc_feupdateenv_test_loongarch -+# define libc_feupdateenv_testf libc_feupdateenv_test_loongarch -+# define libc_feupdateenv_testl libc_feupdateenv_test_loongarch -+ -+static __always_inline void -+libc_feupdateenv_loongarch (fenv_t *envp) -+{ -+ libc_feupdateenv_test_loongarch (envp, 0); -+} -+# define libc_feupdateenv libc_feupdateenv_loongarch -+# define libc_feupdateenvf libc_feupdateenv_loongarch -+# define libc_feupdateenvl libc_feupdateenv_loongarch -+ -+# define libc_feresetround libc_feupdateenv_loongarch -+# define libc_feresetroundf libc_feupdateenv_loongarch -+# define libc_feresetroundl libc_feupdateenv_loongarch -+ -+static __always_inline int -+libc_fetestexcept_loongarch (int excepts) -+{ -+ int cw; -+ -+ /* Get current control word. */ -+ _FPU_GETCW (cw); -+ -+ return cw & excepts & FE_ALL_EXCEPT; -+} -+# define libc_fetestexcept libc_fetestexcept_loongarch -+# define libc_fetestexceptf libc_fetestexcept_loongarch -+# define libc_fetestexceptl libc_fetestexcept_loongarch -+ -+/* Enable support for rounding mode context. */ -+# define HAVE_RM_CTX 1 -+ -+static __always_inline void -+libc_feholdexcept_setround_loongarch_ctx (struct rm_ctx *ctx, int round) -+{ -+ fpu_control_t old, new; -+ -+ /* Save the current state. */ -+ _FPU_GETCW (old); -+ ctx->env.__fp_control_register = old; -+ -+ /* Clear all exception enable bits and flags. */ -+ new = old & ~(_FPU_MASK_ALL); -+ -+ /* Set rounding bits. */ -+ new = (new & ~_FPU_RC_MASK) | round; -+ -+ if (__glibc_unlikely (new != old)) -+ { -+ _FPU_SETCW (new); -+ ctx->updated_status = true; -+ } -+ else -+ ctx->updated_status = false; -+} -+# define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_loongarch_ctx -+# define libc_feholdexcept_setroundf_ctx libc_feholdexcept_setround_loongarch_ctx -+# define libc_feholdexcept_setroundl_ctx libc_feholdexcept_setround_loongarch_ctx -+ -+static __always_inline void -+libc_fesetenv_loongarch_ctx (struct rm_ctx *ctx) -+{ -+ libc_fesetenv_loongarch (&ctx->env); -+} -+# define libc_fesetenv_ctx libc_fesetenv_loongarch_ctx -+# define libc_fesetenvf_ctx libc_fesetenv_loongarch_ctx -+# define libc_fesetenvl_ctx libc_fesetenv_loongarch_ctx -+ -+static __always_inline void -+libc_feupdateenv_loongarch_ctx (struct rm_ctx *ctx) -+{ -+ if (__glibc_unlikely (ctx->updated_status)) -+ libc_feupdateenv_test_loongarch (&ctx->env, 0); -+} -+# define libc_feupdateenv_ctx libc_feupdateenv_loongarch_ctx -+# define libc_feupdateenvf_ctx libc_feupdateenv_loongarch_ctx -+# define libc_feupdateenvl_ctx libc_feupdateenv_loongarch_ctx -+# define libc_feresetround_ctx libc_feupdateenv_loongarch_ctx -+# define libc_feresetroundf_ctx libc_feupdateenv_loongarch_ctx -+# define libc_feresetroundl_ctx libc_feupdateenv_loongarch_ctx -+ -+static __always_inline void -+libc_feholdsetround_loongarch_ctx (struct rm_ctx *ctx, int round) -+{ -+ fpu_control_t old, new; -+ -+ /* Save the current state. */ -+ _FPU_GETCW (old); -+ ctx->env.__fp_control_register = old; -+ -+ /* Set rounding bits. */ -+ new = (old & ~_FPU_RC_MASK) | round; -+ -+ if (__glibc_unlikely (new != old)) -+ { -+ _FPU_SETCW (new); -+ ctx->updated_status = true; -+ } -+ else -+ ctx->updated_status = false; -+} -+# define libc_feholdsetround_ctx libc_feholdsetround_loongarch_ctx -+# define libc_feholdsetroundf_ctx libc_feholdsetround_loongarch_ctx -+# define libc_feholdsetroundl_ctx libc_feholdsetround_loongarch_ctx -+ -+#endif -+ -+#include_next -+ -+#endif -diff --git a/sysdeps/loongarch/memusage.h b/sysdeps/loongarch/memusage.h -new file mode 100644 -index 00000000..bdf99f8a ---- /dev/null -+++ b/sysdeps/loongarch/memusage.h -@@ -0,0 +1,21 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#define GETSP() ({ register uintptr_t stack_ptr asm ("$sp"); stack_ptr; }) -+ -+#include -diff --git a/sysdeps/loongarch/mknod.c b/sysdeps/loongarch/mknod.c -new file mode 100644 -index 00000000..1ed3681f ---- /dev/null -+++ b/sysdeps/loongarch/mknod.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/mknodat.c b/sysdeps/loongarch/mknodat.c -new file mode 100644 -index 00000000..82bc6ee6 ---- /dev/null -+++ b/sysdeps/loongarch/mknodat.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/nptl/Makefile b/sysdeps/loongarch/nptl/Makefile -new file mode 100644 -index 00000000..a1d5768a ---- /dev/null -+++ b/sysdeps/loongarch/nptl/Makefile -@@ -0,0 +1,26 @@ -+# Makefile for sysdeps/loongarch/nptl. -+# Copyright (C) 2005-2018 Free Software Foundation, Inc. -+# This file is part of the GNU C Library. -+# -+# The GNU C Library is free software; you can redistribute it and/or -+# modify it under the terms of the GNU Lesser General Public -+# License as published by the Free Software Foundation; either -+# version 2.1 of the License, or (at your option) any later version. -+# -+# The GNU C Library is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+# Lesser General Public License for more details. -+# -+# You should have received a copy of the GNU Lesser General Public -+# License along with the GNU C Library; if not, see -+# . -+ -+ifeq ($(subdir),csu) -+gen-as-const-headers += tcb-offsets.sym -+endif -+ -+ifeq ($(subdir),nptl) -+libpthread-sysdep_routines += nptl-sysdep -+libpthread-shared-only-routines += nptl-sysdep -+endif -diff --git a/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h b/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h -new file mode 100644 -index 00000000..5a761355 ---- /dev/null -+++ b/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h -@@ -0,0 +1,68 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _BITS_PTHREADTYPES_ARCH_H -+#define _BITS_PTHREADTYPES_ARCH_H 1 -+ -+#include -+ -+#if __loongarch_xlen == 64 -+# define __SIZEOF_PTHREAD_ATTR_T 56 -+# define __SIZEOF_PTHREAD_MUTEX_T 40 -+# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 -+# define __SIZEOF_PTHREAD_COND_T 48 -+# define __SIZEOF_PTHREAD_CONDATTR_T 4 -+# define __SIZEOF_PTHREAD_RWLOCK_T 56 -+# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 -+# define __SIZEOF_PTHREAD_BARRIER_T 32 -+# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 -+#else -+# error "rv32i-based systems are not supported" -+#endif -+ -+#define __PTHREAD_COMPAT_PADDING_MID -+#define __PTHREAD_COMPAT_PADDING_END -+#define __PTHREAD_MUTEX_LOCK_ELISION 0 -+#define __PTHREAD_MUTEX_USE_UNION 0 -+#define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0 -+ -+#define __LOCK_ALIGNMENT -+#define __ONCE_ALIGNMENT -+ -+/* There is a lot of padding in this structure. While it's not strictly -+ necessary on LoongArch, we're going to leave it in to be on the safe side in -+ case it's needed in the future. Most other architectures have the padding, -+ so this gives us the same extensibility as everyone else has. */ -+struct __pthread_rwlock_arch_t -+{ -+ unsigned int __readers; -+ unsigned int __writers; -+ unsigned int __wrphase_futex; -+ unsigned int __writers_futex; -+ unsigned int __pad3; -+ unsigned int __pad4; -+ int __cur_writer; -+ int __shared; -+ unsigned long int __pad1; -+ unsigned long int __pad2; -+ unsigned int __flags; -+}; -+ -+#define __PTHREAD_RWLOCK_ELISION_EXTRA 0 -+ -+#endif /* bits/pthreadtypes.h */ -diff --git a/sysdeps/loongarch/nptl/bits/semaphore.h b/sysdeps/loongarch/nptl/bits/semaphore.h -new file mode 100644 -index 00000000..a9ddefb2 ---- /dev/null -+++ b/sysdeps/loongarch/nptl/bits/semaphore.h -@@ -0,0 +1,33 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _SEMAPHORE_H -+# error "Never use directly; include instead." -+#endif -+ -+#define __SIZEOF_SEM_T (4 * __SIZEOF_POINTER__) -+ -+/* Value returned if `sem_open' failed. */ -+#define SEM_FAILED ((sem_t *) 0) -+ -+ -+typedef union -+{ -+ char __size[__SIZEOF_SEM_T]; -+ long int __align; -+} sem_t; -diff --git a/sysdeps/loongarch/nptl/libc-lowlevellock.c b/sysdeps/loongarch/nptl/libc-lowlevellock.c -new file mode 100644 -index 00000000..9523fb46 ---- /dev/null -+++ b/sysdeps/loongarch/nptl/libc-lowlevellock.c -@@ -0,0 +1,8 @@ -+/* This kludge works around a libpthread static linking problem: -+ https://sourceware.org/bugzilla/show_bug.cgi?id=15648. */ -+ -+#ifndef SHARED -+# define __lll_lock_wait_private weak_function __lll_lock_wait_private -+#endif -+ -+#include -diff --git a/sysdeps/loongarch/nptl/nptl-sysdep.S b/sysdeps/loongarch/nptl/nptl-sysdep.S -new file mode 100644 -index 00000000..3f5c2a36 ---- /dev/null -+++ b/sysdeps/loongarch/nptl/nptl-sysdep.S -@@ -0,0 +1,2 @@ -+/* Pull in __syscall_error. */ -+#include -diff --git a/sysdeps/loongarch/nptl/pthread-offsets.h b/sysdeps/loongarch/nptl/pthread-offsets.h -new file mode 100644 -index 00000000..04130879 ---- /dev/null -+++ b/sysdeps/loongarch/nptl/pthread-offsets.h -@@ -0,0 +1,23 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#define __PTHREAD_MUTEX_NUSERS_OFFSET 12 -+#define __PTHREAD_MUTEX_KIND_OFFSET 16 -+#define __PTHREAD_MUTEX_SPINS_OFFSET 20 -+#define __PTHREAD_MUTEX_ELISION_OFFSET 22 -+#define __PTHREAD_MUTEX_LIST_OFFSET 24 -diff --git a/sysdeps/loongarch/nptl/pthreaddef.h b/sysdeps/loongarch/nptl/pthreaddef.h -new file mode 100644 -index 00000000..87c407bc ---- /dev/null -+++ b/sysdeps/loongarch/nptl/pthreaddef.h -@@ -0,0 +1,32 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+/* Default stack size. */ -+#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) -+ -+/* Required stack pointer alignment at beginning. */ -+#define STACK_ALIGN 16 -+ -+/* Minimal stack size after allocating thread descriptor and guard size. */ -+#define MINIMAL_REST_STACK 2048 -+ -+/* Alignment requirement for TCB. */ -+#define TCB_ALIGNMENT 16 -+ -+/* Location of current stack frame. */ -+#define CURRENT_STACK_FRAME __builtin_frame_address (0) -diff --git a/sysdeps/loongarch/nptl/tcb-offsets.sym b/sysdeps/loongarch/nptl/tcb-offsets.sym -new file mode 100644 -index 00000000..ab4981f2 ---- /dev/null -+++ b/sysdeps/loongarch/nptl/tcb-offsets.sym -@@ -0,0 +1,6 @@ -+#include -+#include -+ -+#define thread_offsetof(mem) (long)(offsetof (struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) -+ -+MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads) -diff --git a/sysdeps/loongarch/nptl/tls.h b/sysdeps/loongarch/nptl/tls.h -new file mode 100644 -index 00000000..8d2d4ca2 ---- /dev/null -+++ b/sysdeps/loongarch/nptl/tls.h -@@ -0,0 +1,147 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _LOONGARCH_TLS_H -+#define _LOONGARCH_TLS_H 1 -+ -+#include -+ -+#ifndef __ASSEMBLER__ -+# include -+# include -+# include -+# include -+ -+register void *__thread_self asm ("$tp"); /* FIXME */ -+# define READ_THREAD_POINTER() ({ __thread_self; }) -+ -+/* Get system call information. */ -+# include -+ -+/* The TP points to the start of the thread blocks. */ -+# define TLS_DTV_AT_TP 1 -+# define TLS_TCB_AT_TP 0 -+ -+/* Get the thread descriptor definition. */ -+# include -+ -+typedef struct -+{ -+ dtv_t *dtv; -+ void *private; -+} tcbhead_t; -+ -+/* This is the size of the initial TCB. Because our TCB is before the thread -+ pointer, we don't need this. */ -+# define TLS_INIT_TCB_SIZE 0 -+ -+/* Alignment requirements for the initial TCB. */ -+# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) -+ -+/* This is the size of the TCB. Because our TCB is before the thread -+ pointer, we don't need this. */ -+# define TLS_TCB_SIZE 0 -+ -+/* Alignment requirements for the TCB. */ -+# define TLS_TCB_ALIGN __alignof__ (struct pthread) -+ -+/* This is the size we need before TCB - actually, it includes the TCB. */ -+# define TLS_PRE_TCB_SIZE \ -+ (sizeof (struct pthread) \ -+ + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) -+ -+/* The thread pointer tp points to the end of the TCB. -+ The pthread_descr structure is immediately in front of the TCB. */ -+# define TLS_TCB_OFFSET 0 -+ -+/* Install the dtv pointer. The pointer passed is to the element with -+ index -1 which contain the length. */ -+# define INSTALL_DTV(tcbp, dtvp) \ -+ (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1) -+ -+/* Install new dtv for current thread. */ -+# define INSTALL_NEW_DTV(dtv) \ -+ (THREAD_DTV() = (dtv)) -+ -+/* Return dtv of given thread descriptor. */ -+# define GET_DTV(tcbp) \ -+ (((tcbhead_t *) (tcbp))[-1].dtv) -+ -+/* Code to initially initialize the thread pointer. */ -+# define TLS_INIT_TP(tcbp) \ -+ ({ __thread_self = (char*)tcbp + TLS_TCB_OFFSET; NULL; }) -+ -+/* Return the address of the dtv for the current thread. */ -+# define THREAD_DTV() \ -+ (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv) -+ -+/* Return the thread descriptor for the current thread. */ -+# define THREAD_SELF \ -+ ((struct pthread *) (READ_THREAD_POINTER () \ -+ - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) -+ -+/* Value passed to 'clone' for initialization of the thread register. */ -+# define TLS_DEFINE_INIT_TP(tp, pd) \ -+ void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE -+ -+/* Informs libthread_db that the thread pointer is register 2, which is used -+ * to know how to do THREAD_SELF. */ -+# define DB_THREAD_SELF \ -+ REGISTER (64, 64, 2 * 8, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) -+ -+/* Access to data in the thread descriptor is easy. */ -+# define THREAD_GETMEM(descr, member) \ -+ descr->member -+# define THREAD_GETMEM_NC(descr, member, idx) \ -+ descr->member[idx] -+# define THREAD_SETMEM(descr, member, value) \ -+ descr->member = (value) -+# define THREAD_SETMEM_NC(descr, member, idx, value) \ -+ descr->member[idx] = (value) -+ -+/* l_tls_offset == 0 is perfectly valid, so we have to use some different -+ value to mean unset l_tls_offset. */ -+# define NO_TLS_OFFSET -1 -+ -+/* Get and set the global scope generation counter in struct pthread. */ -+# define THREAD_GSCOPE_IN_TCB 1 -+# define THREAD_GSCOPE_FLAG_UNUSED 0 -+# define THREAD_GSCOPE_FLAG_USED 1 -+# define THREAD_GSCOPE_FLAG_WAIT 2 -+# define THREAD_GSCOPE_RESET_FLAG() \ -+ do \ -+ { int __res \ -+ = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ -+ THREAD_GSCOPE_FLAG_UNUSED); \ -+ if (__res == THREAD_GSCOPE_FLAG_WAIT) \ -+ lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ -+ } \ -+ while (0) -+# define THREAD_GSCOPE_SET_FLAG() \ -+ do \ -+ { \ -+ THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ -+ atomic_write_barrier (); \ -+ } \ -+ while (0) -+# define THREAD_GSCOPE_WAIT() \ -+ GL(dl_wait_lookup_done) () -+ -+#endif /* __ASSEMBLER__ */ -+ -+#endif /* tls.h */ -diff --git a/sysdeps/loongarch/preconfigure b/sysdeps/loongarch/preconfigure -new file mode 100644 -index 00000000..26ffe884 ---- /dev/null -+++ b/sysdeps/loongarch/preconfigure -@@ -0,0 +1,9 @@ -+case "$machine" in -+loongarch*) -+ base_machine=loongarch -+ machine=loongarch/lp64 -+ ;; -+esac -+ -+#TODO: this file is useless now. -+#Maybe we can make use of it to get arch info from GCC to set env -diff --git a/sysdeps/loongarch/pthread_atfork.c b/sysdeps/loongarch/pthread_atfork.c -new file mode 100644 -index 00000000..0f01d805 ---- /dev/null -+++ b/sysdeps/loongarch/pthread_atfork.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/setjmp.S b/sysdeps/loongarch/setjmp.S -new file mode 100644 -index 00000000..da09a93c ---- /dev/null -+++ b/sysdeps/loongarch/setjmp.S -@@ -0,0 +1,62 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+ -+ENTRY (_setjmp) -+ li.w a1,0 -+ b __sigsetjmp -+END (_setjmp) -+ENTRY (setjmp) -+ li.w a1,1 -+END (setjmp) -+ENTRY (__sigsetjmp) -+ REG_S ra, a0, 0*SZREG -+ REG_S sp, a0, 1*SZREG -+ REG_S x, a0, 2*SZREG -+ REG_S fp, a0, 3*SZREG -+ REG_S s0, a0, 4*SZREG -+ REG_S s1, a0, 5*SZREG -+ REG_S s2, a0, 6*SZREG -+ REG_S s3, a0, 7*SZREG -+ REG_S s4, a0, 8*SZREG -+ REG_S s5, a0, 9*SZREG -+ REG_S s6, a0, 10*SZREG -+ REG_S s7, a0, 11*SZREG -+ REG_S s8, a0, 12*SZREG -+ -+ 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 -+ -+#if !IS_IN (libc) && IS_IN(rtld) -+ li.w v0, 0 -+ jirl zero,ra,0 -+#else -+ b __sigjmp_save -+#endif -+END (__sigsetjmp) -+ -+hidden_def (__sigsetjmp) -+weak_alias (_setjmp, __GI__setjmp) -diff --git a/sysdeps/loongarch/sfp-machine.h b/sysdeps/loongarch/sfp-machine.h -new file mode 100644 -index 00000000..b5c79bc0 ---- /dev/null -+++ b/sysdeps/loongarch/sfp-machine.h -@@ -0,0 +1,79 @@ -+#include -+#include -+ -+#define _FP_W_TYPE_SIZE 64 -+#define _FP_W_TYPE unsigned long long -+#define _FP_WS_TYPE signed long long -+#define _FP_I_TYPE long long -+ -+#define _FP_MUL_MEAT_S(R,X,Y) \ -+ _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y) -+#define _FP_MUL_MEAT_D(R,X,Y) \ -+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) -+#define _FP_MUL_MEAT_Q(R,X,Y) \ -+ _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) -+ -+#define _FP_MUL_MEAT_DW_S(R,X,Y) \ -+ _FP_MUL_MEAT_DW_1_imm(_FP_WFRACBITS_S,R,X,Y) -+#define _FP_MUL_MEAT_DW_D(R,X,Y) \ -+ _FP_MUL_MEAT_DW_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) -+#define _FP_MUL_MEAT_DW_Q(R,X,Y) \ -+ _FP_MUL_MEAT_DW_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) -+ -+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm) -+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y) -+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y) -+ -+# define _FP_NANFRAC_S _FP_QNANBIT_S -+# define _FP_NANFRAC_D _FP_QNANBIT_D -+# define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0 -+ -+#define _FP_NANSIGN_S 0 -+#define _FP_NANSIGN_D 0 -+#define _FP_NANSIGN_Q 0 -+ -+#define _FP_KEEPNANFRACP 1 -+#define _FP_QNANNEGATEDP 0 -+ -+/* NaN payloads should be preserved for NAN2008. */ -+# define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ -+ do \ -+ { \ -+ R##_s = X##_s; \ -+ _FP_FRAC_COPY_##wc (R, X); \ -+ R##_c = FP_CLS_NAN; \ -+ } \ -+ while (0) -+ -+#define _FP_DECL_EX fpu_control_t _fcw -+ -+#define FP_ROUNDMODE (_fcw & 0x300) -+ -+#define FP_RND_NEAREST FE_TONEAREST -+#define FP_RND_ZERO FE_TOWARDZERO -+#define FP_RND_PINF FE_UPWARD -+#define FP_RND_MINF FE_DOWNWARD -+ -+#define FP_EX_INVALID FE_INVALID -+#define FP_EX_OVERFLOW FE_OVERFLOW -+#define FP_EX_UNDERFLOW FE_UNDERFLOW -+#define FP_EX_DIVZERO FE_DIVBYZERO -+#define FP_EX_INEXACT FE_INEXACT -+ -+#define _FP_TININESS_AFTER_ROUNDING 1 -+ -+#ifdef __loongarch_hard_float -+#define FP_INIT_ROUNDMODE \ -+do { \ -+ _FPU_GETCW (_fcw); \ -+} while (0) -+ -+#define FP_HANDLE_EXCEPTIONS \ -+do { \ -+ if (__builtin_expect (_fex, 0)) \ -+ _FPU_SETCW (_fcw | _fex | (_fex << 8)); \ -+} while (0) -+#define FP_TRAPPING_EXCEPTIONS ((_fcw << 16) & 0x1f0000) -+#else -+#define FP_INIT_ROUNDMODE _fcw = FP_RND_NEAREST -+#endif -diff --git a/sysdeps/loongarch/sotruss-lib.c b/sysdeps/loongarch/sotruss-lib.c -new file mode 100644 -index 00000000..124db440 ---- /dev/null -+++ b/sysdeps/loongarch/sotruss-lib.c -@@ -0,0 +1,51 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#define HAVE_ARCH_PLTENTER -+#define HAVE_ARCH_PLTEXIT -+ -+#include -+ -+ElfW(Addr) -+la_loongarch_gnu_pltenter (ElfW(Sym) *sym __attribute__ ((unused)), -+ unsigned int ndx __attribute__ ((unused)), -+ uintptr_t *refcook, uintptr_t *defcook, -+ La_loongarch_regs *regs, unsigned int *flags, -+ const char *symname, long int *framesizep) -+{ -+ print_enter (refcook, defcook, symname, -+ regs->lr_reg[0], regs->lr_reg[1], regs->lr_reg[2], -+ *flags); -+ -+ /* No need to copy anything, we will not need the parameters in any case. */ -+ *framesizep = 0; -+ -+ return sym->st_value; -+} -+ -+unsigned int -+la_loongarch_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, -+ uintptr_t *defcook, -+ const struct La_loongarch_regs *inregs, -+ struct La_loongarch_retval *outregs, -+ const char *symname) -+{ -+ print_exit (refcook, defcook, symname, outregs->lrv_a0); -+ -+ return 0; -+} -diff --git a/sysdeps/loongarch/stack_chk_fail_local.c b/sysdeps/loongarch/stack_chk_fail_local.c -new file mode 100644 -index 00000000..305871fb ---- /dev/null -+++ b/sysdeps/loongarch/stack_chk_fail_local.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/stackinfo.h b/sysdeps/loongarch/stackinfo.h -new file mode 100644 -index 00000000..5f5e6ad1 ---- /dev/null -+++ b/sysdeps/loongarch/stackinfo.h -@@ -0,0 +1,33 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+/* This file contains a bit of information about the stack allocation -+ of the processor. */ -+ -+#ifndef _STACKINFO_H -+#define _STACKINFO_H 1 -+ -+#include -+ -+/* On LoongArch the stack grows down. */ -+#define _STACK_GROWS_DOWN 1 -+ -+/* Default to a non-executable stack. */ -+#define DEFAULT_STACK_PERMS (PF_R | PF_W) -+ -+#endif /* stackinfo.h */ -diff --git a/sysdeps/loongarch/start.S b/sysdeps/loongarch/start.S -new file mode 100644 -index 00000000..cf0a14b5 ---- /dev/null -+++ b/sysdeps/loongarch/start.S -@@ -0,0 +1,51 @@ -+#define __ASSEMBLY__ 1 -+#include -+#include -+ -+/* The entry point's job is to call __libc_start_main. Per the ABI, -+ a0 contains the address of a function to be passed to atexit. -+ __libc_start_main wants this in a5. */ -+ -+/* -+int -+__libc_start_main (int (*main) (int, char **, char **), -+ int argc, -+ char **argv, -+ __typeof (main) init, -+ void (*fini) (void), -+ void (*rtld_fini) (void), -+ void *stack_end); -+*/ -+ -+ENTRY (ENTRY_POINT) -+ /* Terminate call stack by noting ra is undefined. Use a dummy -+ .cfi_label to force starting the FDE. */ -+ .cfi_label .Ldummy -+ cfi_undefined (1) -+ or a5, a0, zero /* rtld_fini */ -+ -+ /* 这个main必须要走GOT表拿到。因为main不一定是local的。 -+ 比如googletest就把main定义在动态库里了。 */ -+ la.got a0, t0, main -+#ifdef __loongarch64 -+ ld.d a1, sp, 0 -+ addi.d a2, sp, SZREG -+#elif defined __loongarch32 -+ ld.w a1, sp, 0 -+ addi.w a2, sp, SZREG -+#endif -+ /* Adjust $sp for 16-aligned */ -+ srli.d sp, sp, 4 -+ slli.d sp, sp, 4 -+ -+ la.got a3, t0, __libc_csu_init -+ la.got a4, t0, __libc_csu_fini -+ or a6, sp, zero /* stack_end. */ -+ -+ la.got ra, t0, __libc_start_main -+ jirl ra, ra, 0 -+ -+ la.got ra, t0, abort -+ jirl ra, ra, 0 -+END (ENTRY_POINT) -+ -diff --git a/sysdeps/loongarch/stat.c b/sysdeps/loongarch/stat.c -new file mode 100644 -index 00000000..36461b87 ---- /dev/null -+++ b/sysdeps/loongarch/stat.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/stat64.c b/sysdeps/loongarch/stat64.c -new file mode 100644 -index 00000000..0897282e ---- /dev/null -+++ b/sysdeps/loongarch/stat64.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/loongarch/sys/asm.h b/sysdeps/loongarch/sys/asm.h -new file mode 100644 -index 00000000..7f3769bd ---- /dev/null -+++ b/sysdeps/loongarch/sys/asm.h -@@ -0,0 +1,49 @@ -+#ifndef _SYS_ASM_H -+#define _SYS_ASM_H -+ -+#include -+#include -+ -+/* Macros to handle different pointer/register sizes for 32/64-bit code. */ -+#ifdef __loongarch64 -+# define PTRLOG 3 -+# define SZREG 8 -+# define SZFREG 8 -+# define REG_L ld.d -+# define REG_S st.d -+# define FREG_L fld.d -+# define FREG_S fst.d -+#elif defined __loongarch32 -+# define PTRLOG 2 -+# define SZREG 4 -+# define SZFREG 4 -+# define REG_L ld.w -+# define REG_S st.w -+# define FREG_L fld.w -+# define FREG_S fst.w -+#else -+# error __loongarch_xlen must equal 32 or 64 -+#endif -+ -+ -+/* Declare leaf routine. */ -+#define LEAF(symbol) \ -+ .text; \ -+ .globl symbol; \ -+ .align 3; \ -+ cfi_startproc ; \ -+ .type symbol, @function; \ -+symbol: -+ -+# define ENTRY(symbol) LEAF(symbol) -+ -+/* Mark end of function. */ -+#undef END -+#define END(function) \ -+ cfi_endproc ; \ -+ .size function,.-function; -+ -+/* Stack alignment. */ -+#define ALMASK ~15 -+ -+#endif /* sys/asm.h */ -diff --git a/sysdeps/loongarch/sys/regdef.h b/sysdeps/loongarch/sys/regdef.h -new file mode 100644 -index 00000000..769784b8 ---- /dev/null -+++ b/sysdeps/loongarch/sys/regdef.h -@@ -0,0 +1,83 @@ -+#ifndef _SYS_REGDEF_H -+#define _SYS_REGDEF_H -+ -+#if _LOONGARCH_SIM == _ABILP64 -+# define zero $r0 -+# define ra $r1 -+# define tp $r2 -+# define sp $r3 -+# define a0 $r4 -+# define a1 $r5 -+# define a2 $r6 -+# define a3 $r7 -+# define a4 $r8 -+# define a5 $r9 -+# define a6 $r10 -+# define a7 $r11 -+# define v0 $r4 -+# define v1 $r5 -+# define t0 $r12 -+# define t1 $r13 -+# define t2 $r14 -+# define t3 $r15 -+# define t4 $r16 -+# define t5 $r17 -+# define t6 $r18 -+# define t7 $r19 -+# define t8 $r20 -+# define x $r21 -+# define fp $r22 -+# define s0 $r23 -+# define s1 $r24 -+# define s2 $r25 -+# define s3 $r26 -+# define s4 $r27 -+# define s5 $r28 -+# define s6 $r29 -+# define s7 $r30 -+# define s8 $r31 -+ -+# define fa0 $f0 -+# define fa1 $f1 -+# define fa2 $f2 -+# define fa3 $f3 -+# define fa4 $f4 -+# define fa5 $f5 -+# define fa6 $f6 -+# define fa7 $f7 -+# define fv0 $f0 -+# define fv1 $f1 -+# define ft0 $f8 -+# define ft1 $f9 -+# define ft2 $f10 -+# define ft3 $f11 -+# define ft4 $f12 -+# define ft5 $f13 -+# define ft6 $f14 -+# define ft7 $f15 -+# define ft8 $f16 -+# define ft9 $f17 -+# define ft10 $f18 -+# define ft11 $f19 -+# define ft12 $f20 -+# define ft13 $f21 -+# define ft14 $f22 -+# define ft15 $f23 -+# define fs0 $f24 -+# define fs1 $f25 -+# define fs2 $f26 -+# define fs3 $f27 -+# define fs4 $f28 -+# define fs5 $f29 -+# define fs6 $f30 -+# define fs7 $f31 -+ -+#elif _LOONGARCH_SIM == _ABILPX32 -+# error ABILPX32 -+#elif _LOONGARCH_SIM == _ABILP32 -+# error ABILP32 -+#else -+# error noABI -+#endif -+ -+#endif /* _SYS_REGDEF_H */ -diff --git a/sysdeps/loongarch/tininess.h b/sysdeps/loongarch/tininess.h -new file mode 100644 -index 00000000..1db37790 ---- /dev/null -+++ b/sysdeps/loongarch/tininess.h -@@ -0,0 +1 @@ -+#define TININESS_AFTER_ROUNDING 1 -diff --git a/sysdeps/loongarch/tls-macros.h b/sysdeps/loongarch/tls-macros.h -new file mode 100644 -index 00000000..f0ad55ac ---- /dev/null -+++ b/sysdeps/loongarch/tls-macros.h -@@ -0,0 +1,46 @@ -+/* Macros to support TLS testing in times of missing compiler support. -+ Copyright (C) 2017-2018 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+ -+#include -+#include -+#include -+#include "dl-tls.h" -+ -+#define TLS_GD(x) \ -+ ({ void *__result; \ -+ asm ("la.tls.gd %0, " #x "\n\t" \ -+ : "=r" (__result)); \ -+ __tls_get_addr (__result); }) -+ -+#define TLS_LD(x) TLS_GD(x) -+ -+#define TLS_IE(x) \ -+ ({ void *__result; \ -+ asm ("la.tls.ie %0, " #x "\n\t" \ -+ "add.d %0, %0, $tp\n\t" \ -+ : "=r" (__result)); \ -+ __result; }) -+ -+#define TLS_LE(x) \ -+ ({ void *__result; \ -+ asm ("la.tls.le %0, " #x "\n\t" \ -+ "add.d %0, %0, $tp\n\t" \ -+ : "=r" (__result)); \ -+ __result; }) -diff --git a/sysdeps/loongarch/tst-audit.h b/sysdeps/loongarch/tst-audit.h -new file mode 100644 -index 00000000..d8d260eb ---- /dev/null -+++ b/sysdeps/loongarch/tst-audit.h -@@ -0,0 +1,23 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#define pltenter la_loongarch_gnu_pltenter -+#define pltexit la_loongarch_gnu_pltexit -+#define La_regs La_loongarch_regs -+#define La_retval La_loongarch_retval -+#define int_retval lrv_a0 -diff --git a/sysdeps/loongarch/warning-nop.c b/sysdeps/loongarch/warning-nop.c -new file mode 100644 -index 00000000..b76aae79 ---- /dev/null -+++ b/sysdeps/loongarch/warning-nop.c -@@ -0,0 +1 @@ -+#include -diff --git a/sysdeps/unix/sysv/linux/loongarch/Implies b/sysdeps/unix/sysv/linux/loongarch/Implies -new file mode 100644 -index 00000000..e52b1ac3 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/Implies -@@ -0,0 +1 @@ -+loongarch/nptl -diff --git a/sysdeps/unix/sysv/linux/loongarch/Makefile b/sysdeps/unix/sysv/linux/loongarch/Makefile -new file mode 100644 -index 00000000..6f049aa9 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/Makefile -@@ -0,0 +1,17 @@ -+ifeq ($(subdir),elf) -+sysdep_routines += dl-vdso -+ifeq ($(build-shared),yes) -+# This is needed for DSO loading from static binaries. -+sysdep-dl-routines += dl-static -+endif -+endif -+ -+#ifeq ($(subdir),misc) -+#sysdep_headers += sys/cachectl.h -+#sysdep_routines += flush-icache -+#endif -+ -+ifeq ($(subdir),stdlib) -+gen-as-const-headers += ucontext_i.sym -+endif -+ -diff --git a/sysdeps/unix/sysv/linux/loongarch/Versions b/sysdeps/unix/sysv/linux/loongarch/Versions -new file mode 100644 -index 00000000..453f276a ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/Versions -@@ -0,0 +1,44 @@ -+ld { -+ GLIBC_PRIVATE { -+ # used for loading by static libraries -+ _dl_var_init; -+ } -+} -+libc { -+ # The comment lines with "#errlist-compat" are magic; see errlist-compat.awk. -+ # When you get an error from errlist-compat.awk, you need to add a new -+ # version here. Don't do this blindly, since this means changing the ABI -+ # for all GNU/Linux configurations. -+ -+ GLIBC_2.0 { -+ #errlist-compat 123 -+ _sys_errlist; sys_errlist; _sys_nerr; sys_nerr; -+ -+ # Exception handling support functions from libgcc -+ __register_frame; __register_frame_table; __deregister_frame; -+ __frame_state_for; __register_frame_info_table; -+ -+ # Needed by gcc: -+ _flush_cache; -+ -+ # c* -+ cachectl; cacheflush; -+ -+ # s* -+ sysmips; -+ } -+ GLIBC_2.2 { -+ #errlist-compat 1134 -+ _sys_errlist; sys_errlist; _sys_nerr; sys_nerr; -+ -+ # _* -+ _test_and_set; -+ } -+ GLIBC_2.11 { -+ fallocate64; -+ } -+ GLIBC_PRIVATE { -+ # nptl/pthread_cond_timedwait.c uses INTERNAL_VSYSCALL(clock_gettime). -+ __vdso_clock_gettime; -+ } -+} -diff --git a/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h b/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h -new file mode 100644 -index 00000000..ac1948ea ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h -@@ -0,0 +1,188 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _LINUX_LOONGARCH_BITS_ATOMIC_H -+#define _LINUX_LOONGARCH_BITS_ATOMIC_H 1 -+ -+#include -+ -+typedef int32_t atomic32_t; -+typedef uint32_t uatomic32_t; -+ -+typedef int64_t atomic64_t; -+typedef uint64_t uatomic64_t; -+ -+typedef intptr_t atomicptr_t; -+typedef uintptr_t uatomicptr_t; -+typedef intmax_t atomic_max_t; -+typedef uintmax_t uatomic_max_t; -+ -+#define atomic_full_barrier() __sync_synchronize () -+ -+# define __HAVE_64B_ATOMICS (__loongarch_xlen >= 64) -+# define USE_ATOMIC_COMPILER_BUILTINS 1 -+# define ATOMIC_EXCHANGE_USES_CAS 0 -+ -+/* Compare and exchange. -+ For all "bool" routines, we return FALSE if exchange succesful. */ -+ -+# define __arch_compare_and_exchange_bool_8_int(mem, newval, oldval, model) \ -+ ({ \ -+ typeof (*mem) __oldval = (oldval); \ -+ !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ -+ model, __ATOMIC_RELAXED); \ -+ }) -+ -+# define __arch_compare_and_exchange_bool_16_int(mem, newval, oldval, model) \ -+ ({ \ -+ typeof (*mem) __oldval = (oldval); \ -+ !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ -+ model, __ATOMIC_RELAXED); \ -+ }) -+ -+# define __arch_compare_and_exchange_bool_32_int(mem, newval, oldval, model) \ -+ ({ \ -+ typeof (*mem) __oldval = (oldval); \ -+ !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ -+ model, __ATOMIC_RELAXED); \ -+ }) -+ -+# define __arch_compare_and_exchange_bool_64_int(mem, newval, oldval, model) \ -+ ({ \ -+ typeof (*mem) __oldval = (oldval); \ -+ !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ -+ model, __ATOMIC_RELAXED); \ -+ }) -+ -+# define __arch_compare_and_exchange_val_8_int(mem, newval, oldval, model) \ -+ ({ \ -+ typeof (*mem) __oldval = (oldval); \ -+ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ -+ model, __ATOMIC_RELAXED); \ -+ __oldval; \ -+ }) -+ -+# define __arch_compare_and_exchange_val_16_int(mem, newval, oldval, model) \ -+ ({ \ -+ typeof (*mem) __oldval = (oldval); \ -+ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ -+ model, __ATOMIC_RELAXED); \ -+ __oldval; \ -+ }) -+ -+# define __arch_compare_and_exchange_val_32_int(mem, newval, oldval, model) \ -+ ({ \ -+ typeof (*mem) __oldval = (oldval); \ -+ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ -+ model, __ATOMIC_RELAXED); \ -+ __oldval; \ -+ }) -+ -+# define __arch_compare_and_exchange_val_64_int(mem, newval, oldval, model) \ -+ ({ \ -+ typeof (*mem) __oldval = (oldval); \ -+ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, \ -+ model, __ATOMIC_RELAXED); \ -+ __oldval; \ -+ }) -+ -+/* Atomic compare and exchange. */ -+ -+# define atomic_compare_and_exchange_bool_acq(mem, new, old) \ -+ __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ -+ mem, new, old, __ATOMIC_ACQUIRE) -+ -+# define atomic_compare_and_exchange_val_acq(mem, new, old) \ -+ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ -+ mem, new, old, __ATOMIC_ACQUIRE) -+ -+# define atomic_compare_and_exchange_val_rel(mem, new, old) \ -+ __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ -+ mem, new, old, __ATOMIC_RELEASE) -+ -+/* Atomic exchange (without compare). */ -+ -+# define __arch_exchange_8_int(mem, newval, model) \ -+ __atomic_exchange_n (mem, newval, model) -+ -+# define __arch_exchange_16_int(mem, newval, model) \ -+ __atomic_exchange_n (mem, newval, model) -+ -+# define __arch_exchange_32_int(mem, newval, model) \ -+ __atomic_exchange_n (mem, newval, model) -+ -+# define __arch_exchange_64_int(mem, newval, model) \ -+ __atomic_exchange_n (mem, newval, model) -+ -+# define atomic_exchange_acq(mem, value) \ -+ __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_ACQUIRE) -+ -+# define atomic_exchange_rel(mem, value) \ -+ __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_RELEASE) -+ -+/* Atomically add value and return the previous (unincremented) value. */ -+ -+# define __arch_exchange_and_add_8_int(mem, value, model) \ -+ __atomic_fetch_add (mem, value, model) -+ -+# define __arch_exchange_and_add_16_int(mem, value, model) \ -+ __atomic_fetch_add (mem, value, model) -+ -+# define __arch_exchange_and_add_32_int(mem, value, model) \ -+ __atomic_fetch_add (mem, value, model) -+ -+# define __arch_exchange_and_add_64_int(mem, value, model) \ -+ __atomic_fetch_add (mem, value, model) -+ -+# define atomic_exchange_and_add_acq(mem, value) \ -+ __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \ -+ __ATOMIC_ACQUIRE) -+ -+# define atomic_exchange_and_add_rel(mem, value) \ -+ __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \ -+ __ATOMIC_RELEASE) -+ -+/* Miscellaneous. */ -+ -+# define asm_amo(which, mem, value) ({ \ -+ __atomic_check_size (mem); \ -+ typeof (*mem) __tmp; \ -+ if (sizeof (__tmp) == 4) \ -+ asm volatile (which ".w""\t%0, %z2, %1" \ -+ : "=&r" (__tmp), "+ZB" (* (mem)) \ -+ : "rJ" (value)); \ -+ else if (sizeof (__tmp) == 8) \ -+ asm volatile (which ".d""\t%0, %z2, %1" \ -+ : "=&r" (__tmp), "+ZB" (* (mem)) \ -+ : "rJ" (value)); \ -+ else \ -+ abort (); \ -+ __tmp; }) -+ -+# define atomic_max(mem, value) asm_amo ("ammax_db", mem, value) -+# define atomic_min(mem, value) asm_amo ("ammin_db", mem, value) -+ -+# define atomic_bit_test_set(mem, bit) \ -+ ({ typeof (*mem) __mask = (typeof (*mem))1 << (bit); \ -+ asm_amo("amor_db", mem, __mask) & __mask; }) -+ -+# define catomic_exchange_and_add(mem, value) \ -+ atomic_exchange_and_add (mem, value) -+# define catomic_max(mem, value) atomic_max (mem, value) -+ -+#endif /* bits/atomic.h */ -diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/fcntl.h b/sysdeps/unix/sysv/linux/loongarch/bits/fcntl.h -new file mode 100644 -index 00000000..5ee2e976 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/bits/fcntl.h -@@ -0,0 +1,62 @@ -+/* O_*, F_*, FD_* bit values for the generic Linux ABI. -+ Copyright (C) 2011-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Chris Metcalf , 2011. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _FCNTL_H -+# error "Never use directly; include instead." -+#endif -+ -+#include -+ -+/* In 64-bit ISA files are always with 64bit off_t and F_*LK64 are the same as -+ non-64-bit versions. It will need to be revised for 128-bit. */ -+#if __WORDSIZE == 64 -+# define __O_LARGEFILE 0 -+ -+# define F_GETLK64 5 /* Get record locking info. */ -+# define F_SETLK64 6 /* Set record locking info (non-blocking). */ -+# define F_SETLKW64 7 /* Set record locking info (blocking). */ -+#endif -+ -+struct flock -+ { -+ short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ -+ short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ -+#ifndef __USE_FILE_OFFSET64 -+ __off_t l_start; /* Offset where the lock begins. */ -+ __off_t l_len; /* Size of the locked area; zero means until EOF. */ -+#else -+ __off64_t l_start; /* Offset where the lock begins. */ -+ __off64_t l_len; /* Size of the locked area; zero means until EOF. */ -+#endif -+ __pid_t l_pid; /* Process holding the lock. */ -+ }; -+ -+#ifdef __USE_LARGEFILE64 -+struct flock64 -+ { -+ short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ -+ short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ -+ __off64_t l_start; /* Offset where the lock begins. */ -+ __off64_t l_len; /* Size of the locked area; zero means until EOF. */ -+ __pid_t l_pid; /* Process holding the lock. */ -+ }; -+#endif -+ -+/* Include generic Linux declarations. */ -+#include -diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/local_lim.h b/sysdeps/unix/sysv/linux/loongarch/bits/local_lim.h -new file mode 100644 -index 00000000..a8cd6df8 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/bits/local_lim.h -@@ -0,0 +1,99 @@ -+/* Minimum guaranteed maximum values for system limits. Linux version. -+ Copyright (C) 1993-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public License as -+ published by the Free Software Foundation; either version 2.1 of the -+ License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; see the file COPYING.LIB. If -+ not, see . */ -+ -+/* The kernel header pollutes the namespace with the NR_OPEN symbol -+ and defines LINK_MAX although filesystems have different maxima. A -+ similar thing is true for OPEN_MAX: the limit can be changed at -+ runtime and therefore the macro must not be defined. Remove this -+ after including the header if necessary. */ -+#ifndef NR_OPEN -+# define __undef_NR_OPEN -+#endif -+#ifndef LINK_MAX -+# define __undef_LINK_MAX -+#endif -+#ifndef OPEN_MAX -+# define __undef_OPEN_MAX -+#endif -+#ifndef ARG_MAX -+# define __undef_ARG_MAX -+#endif -+ -+/* The kernel sources contain a file with all the needed information. */ -+#include -+ -+/* Have to remove NR_OPEN? */ -+#ifdef __undef_NR_OPEN -+# undef NR_OPEN -+# undef __undef_NR_OPEN -+#endif -+/* Have to remove LINK_MAX? */ -+#ifdef __undef_LINK_MAX -+# undef LINK_MAX -+# undef __undef_LINK_MAX -+#endif -+/* Have to remove OPEN_MAX? */ -+#ifdef __undef_OPEN_MAX -+# undef OPEN_MAX -+# undef __undef_OPEN_MAX -+#endif -+/* Have to remove ARG_MAX? */ -+#ifdef __undef_ARG_MAX -+# undef ARG_MAX -+# undef __undef_ARG_MAX -+#endif -+ -+/* The number of data keys per process. */ -+#define _POSIX_THREAD_KEYS_MAX 128 -+/* This is the value this implementation supports. */ -+#define PTHREAD_KEYS_MAX 1024 -+ -+/* Controlling the iterations of destructors for thread-specific data. */ -+#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 -+/* Number of iterations this implementation does. */ -+#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS -+ -+/* The number of threads per process. */ -+#define _POSIX_THREAD_THREADS_MAX 64 -+/* We have no predefined limit on the number of threads. */ -+#undef PTHREAD_THREADS_MAX -+ -+/* Maximum amount by which a process can descrease its asynchronous I/O -+ priority level. */ -+#define AIO_PRIO_DELTA_MAX 20 -+ -+/* Minimum size for a thread. At least two pages with 64k pages. */ -+#define PTHREAD_STACK_MIN 131072 -+ -+/* Maximum number of timer expiration overruns. */ -+#define DELAYTIMER_MAX 2147483647 -+ -+/* Maximum tty name length. */ -+#define TTY_NAME_MAX 32 -+ -+/* Maximum login name length. This is arbitrary. */ -+#define LOGIN_NAME_MAX 256 -+ -+/* Maximum host name length. */ -+#define HOST_NAME_MAX 64 -+ -+/* Maximum message queue priority level. */ -+#define MQ_PRIO_MAX 32768 -+ -+/* Maximum value the semaphore can have. */ -+#define SEM_VALUE_MAX (2147483647) -diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/mman.h b/sysdeps/unix/sysv/linux/loongarch/bits/mman.h -new file mode 100644 -index 00000000..5a16f8ac ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/bits/mman.h -@@ -0,0 +1,41 @@ -+/* Definitions for POSIX memory map interface. Linux/MIPS version. -+ Copyright (C) 1997-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+ -+#ifndef _SYS_MMAN_H -+# error "Never use directly; include instead." -+#endif -+ -+#ifdef __USE_MISC -+# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ -+# define MAP_DENYWRITE 0x00800 /* ETXTBSY. */ -+# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ -+# define MAP_LOCKED 0x02000 /* Lock the mapping. */ -+# define MAP_NORESERVE 0x04000 /* Don't check for reservations. */ -+# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */ -+# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ -+# define MAP_STACK 0x20000 /* Allocation is for a stack. */ -+# define MAP_HUGETLB 0x40000 /* Create huge page mapping. */ -+# define MAP_SYNC 0x80000 /* Perform synchronous page -+ faults for the mapping. */ -+# define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED but do not unmap -+ underlying mapping. */ -+#endif -+ -+/* Include generic Linux declarations. */ -+#include -diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/shm.h b/sysdeps/unix/sysv/linux/loongarch/bits/shm.h -new file mode 100644 -index 00000000..9e23092d ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/bits/shm.h -@@ -0,0 +1,112 @@ -+/* Copyright (C) 2011-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ Contributed by Chris Metcalf , 2011. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _SYS_SHM_H -+# error "Never include directly; use instead." -+#endif -+ -+#include -+#include -+ -+/* Permission flag for shmget. */ -+#define SHM_R 0400 /* or S_IRUGO from */ -+#define SHM_W 0200 /* or S_IWUGO from */ -+ -+/* Flags for `shmat'. */ -+#define SHM_RDONLY 010000 /* attach read-only else read-write */ -+#define SHM_RND 020000 /* round attach address to SHMLBA */ -+#define SHM_REMAP 040000 /* take-over region on attach */ -+#define SHM_EXEC 0100000 /* execution access */ -+ -+/* Commands for `shmctl'. */ -+#define SHM_LOCK 11 /* lock segment (root only) */ -+#define SHM_UNLOCK 12 /* unlock segment (root only) */ -+ -+__BEGIN_DECLS -+ -+/* Segment low boundary address multiple. */ -+#define SHMLBA (__getpagesize () << 2) -+extern int __getpagesize (void) __THROW __attribute__ ((__const__)); -+ -+ -+/* Type to count number of attaches. */ -+typedef unsigned long int shmatt_t; -+ -+/* Data structure describing a shared memory segment. */ -+struct shmid_ds -+ { -+ struct ipc_perm shm_perm; /* operation permission struct */ -+ size_t shm_segsz; /* size of segment in bytes */ -+ __time_t shm_atime; /* time of last shmat() */ -+#if __WORDSIZE == 32 -+ unsigned long int __glibc_reserved1; -+#endif -+ __time_t shm_dtime; /* time of last shmdt() */ -+#if __WORDSIZE == 32 -+ unsigned long int __glibc_reserved2; -+#endif -+ __time_t shm_ctime; /* time of last change by shmctl() */ -+#if __WORDSIZE == 32 -+ unsigned long int __glibc_reserved3; -+#endif -+ __pid_t shm_cpid; /* pid of creator */ -+ __pid_t shm_lpid; /* pid of last shmop */ -+ shmatt_t shm_nattch; /* number of current attaches */ -+ unsigned long int __glibc_reserved4; -+ unsigned long int __glibc_reserved5; -+ }; -+ -+#ifdef __USE_MISC -+ -+/* ipcs ctl commands */ -+# define SHM_STAT 13 -+# define SHM_INFO 14 -+# define SHM_STAT_ANY 15 -+ -+/* shm_mode upper byte flags */ -+# define SHM_DEST 01000 /* segment will be destroyed on last detach */ -+# define SHM_LOCKED 02000 /* segment will not be swapped */ -+# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ -+# define SHM_NORESERVE 010000 /* don't check for reservations */ -+ -+struct shminfo -+ { -+ unsigned long int shmmax; -+ unsigned long int shmmin; -+ unsigned long int shmmni; -+ unsigned long int shmseg; -+ unsigned long int shmall; -+ unsigned long int __glibc_reserved1; -+ unsigned long int __glibc_reserved2; -+ unsigned long int __glibc_reserved3; -+ unsigned long int __glibc_reserved4; -+ }; -+ -+struct shm_info -+ { -+ int used_ids; -+ unsigned long int shm_tot; /* total allocated shm */ -+ unsigned long int shm_rss; /* total resident shm */ -+ unsigned long int shm_swp; /* total swapped shm */ -+ unsigned long int swap_attempts; -+ unsigned long int swap_successes; -+ }; -+ -+#endif /* __USE_MISC */ -+ -+__END_DECLS -diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/sigcontext.h b/sysdeps/unix/sysv/linux/loongarch/bits/sigcontext.h -new file mode 100644 -index 00000000..0f925b4c ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/bits/sigcontext.h -@@ -0,0 +1,47 @@ -+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -+/* -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file "COPYING" in the main directory of this archive -+ * for more details. -+ * -+ * Copyright (C) 1996, 1997, 1999 by Ralf Baechle -+ * Copyright (C) 1999 Silicon Graphics, Inc. -+ */ -+#ifndef _BITS_SIGCONTEXT_H -+#define _BITS_SIGCONTEXT_H -+ -+/* -+ * Keep this struct definition in sync with the sigcontext fragment -+ * in arch/mips/kernel/asm-offsets.c -+ * -+ * Warning: this structure illdefined with sc_badvaddr being just an unsigned -+ * int so it was changed to unsigned long in 2.6.0-test1. This may break -+ * binary compatibility - no prisoners. -+ * DSP ASE in 2.6.12-rc4. Turn sc_mdhi and sc_mdlo into an array of four -+ * entries, add sc_dsp and sc_reserved for padding. No prisoners. -+ */ -+ -+#define FPU_REG_WIDTH 256 -+#define FPU_ALIGN __attribute__((aligned(32))) -+ -+struct sigcontext { -+ unsigned long long sc_pc; -+ unsigned long long sc_regs[32]; -+ unsigned int sc_flags; -+ -+ unsigned int sc_fcsr; -+ unsigned int sc_vcsr; -+ unsigned long long sc_fcc; -+ -+ unsigned long long sc_scr[4]; -+ -+ union { -+ unsigned int val32[FPU_REG_WIDTH / 32]; -+ unsigned long long val64[FPU_REG_WIDTH / 64]; -+ } sc_fpregs[32] FPU_ALIGN; -+ unsigned char sc_reserved[4096] __attribute__((__aligned__(16))); -+ -+}; -+ -+ -+#endif /* _BITS_SIGCONTEXT_H */ -diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/signum.h b/sysdeps/unix/sysv/linux/loongarch/bits/signum.h -new file mode 100644 -index 00000000..3cad0b19 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/bits/signum.h -@@ -0,0 +1,58 @@ -+/* Signal number definitions. Linux version. -+ Copyright (C) 1995-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#ifndef _BITS_SIGNUM_H -+#define _BITS_SIGNUM_H 1 -+ -+#ifndef _SIGNAL_H -+#error "Never include directly; use instead." -+#endif -+ -+#include -+ -+/* Adjustments and additions to the signal number constants for -+ most Linux systems. */ -+ -+#define SIGSTKFLT 16 /* Stack fault (obsolete). */ -+#define SIGPWR 30 /* Power failure imminent. */ -+ -+#undef SIGBUS -+#define SIGBUS 7 -+#undef SIGUSR1 -+#define SIGUSR1 10 -+#undef SIGUSR2 -+#define SIGUSR2 12 -+#undef SIGCHLD -+#define SIGCHLD 17 -+#undef SIGCONT -+#define SIGCONT 18 -+#undef SIGSTOP -+#define SIGSTOP 19 -+#undef SIGTSTP -+#define SIGTSTP 20 -+#undef SIGURG -+#define SIGURG 23 -+#undef SIGPOLL -+#define SIGPOLL 29 -+#undef SIGSYS -+#define SIGSYS 31 -+ -+#undef __SIGRTMAX -+#define __SIGRTMAX 127 -+ -+#endif /* included. */ -diff --git a/sysdeps/unix/sysv/linux/loongarch/clone.S b/sysdeps/unix/sysv/linux/loongarch/clone.S -new file mode 100644 -index 00000000..f0fc566e ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/clone.S -@@ -0,0 +1,98 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+/* clone() is even more special than fork() as it mucks with stacks -+ and invokes a function in the right context after its all over. */ -+ -+#include -+#include -+#define _ERRNO_H 1 -+#include -+#include -+#include "tcb-offsets.h" -+ -+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, -+ void *parent_tidptr, void *tls, void *child_tidptr) */ -+ -+ENTRY (__clone) -+ -+ /* Align stack to 16 or 8 bytes per the ABI. */ -+#if _LOONGARCH_SIM == _ABILP64 -+ addi.d t0, zero, -16 -+#elif _LOONGARCH_SIM == _ABILP32 -+ addi.w t0, zero, -8 -+#endif -+ and a1, a1, t0 -+ -+ /* Sanity check arguments. */ -+ beqz a0, L (invalid) /* No NULL function pointers. */ -+ beqz a1, L (invalid) /* No NULL stack pointers. */ -+ -+ addi.d a1, a1, -16 /* Reserve argument save space. */ -+ st.d a0, a1, 0 /* Save function pointer. */ -+ st.d a3, a1, SZREG /* Save argument pointer. */ -+ -+ /* The syscall expects the args to be in different slots. */ -+ or a0, a2, zero -+ or a2, a4, zero -+ or a3, a6, zero -+ or a4, a5, zero -+ -+ /* Do the system call. */ -+ li.d a7,__NR_clone -+ syscall 0 -+ -+ blt a0, zero ,L (error) -+ beqz a0,L (thread_start) -+ -+ /* Successful return from the parent. */ -+ ret -+ -+L (invalid): -+ li.d a0, -EINVAL -+ /* Something bad happened -- no child created. */ -+L (error): -+ b __syscall_error -+ END (__clone) -+ -+/* Load up the arguments to the function. Put this block of code in -+ its own function so that we can terminate the stack trace with our -+ debug info. */ -+ -+ENTRY (__thread_start) -+L (thread_start): -+ /* Terminate call stack by noting ra is undefined. Use a dummy -+ .cfi_label to force starting the FDE. */ -+ .cfi_label .Ldummy -+ cfi_undefined (1) -+ -+ /* Restore the arg for user's function. */ -+ ld.d a1, sp, 0 /* Function pointer. */ -+ ld.d a0, sp, SZREG /* Argument pointer. */ -+ -+ /* Call the user's function. */ -+ jirl ra, a1, 0 -+ -+ /* Call exit with the function's return value. */ -+ li.d a7, __NR_exit -+ syscall 0 -+ -+ END (__thread_start) -+ -+libc_hidden_def (__clone) -+weak_alias (__clone, clone) -diff --git a/sysdeps/unix/sysv/linux/loongarch/configure b/sysdeps/unix/sysv/linux/loongarch/configure -new file mode 100644 -index 00000000..a402323a ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/configure -@@ -0,0 +1,199 @@ -+# This file is generated from configure.ac by Autoconf. DO NOT EDIT! -+ # Local configure fragment for sysdeps/unix/sysv/linux/loongarch. -+ -+arch_minimum_kernel=4.15.0 -+ -+libc_cv_loongarch_int_abi=no -+ -+ -+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 -+$as_echo_n "checking for grep that handles long lines and -e... " >&6; } -+if ${ac_cv_path_GREP+:} false; then : -+ $as_echo_n "(cached) " >&6 -+else -+ if test -z "$GREP"; then -+ ac_path_GREP_found=false -+ # Loop through the user's path and test for each of PROGNAME-LIST -+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -+do -+ IFS=$as_save_IFS -+ test -z "$as_dir" && as_dir=. -+ for ac_prog in grep ggrep; do -+ for ac_exec_ext in '' $ac_executable_extensions; do -+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" -+ as_fn_executable_p "$ac_path_GREP" || continue -+# Check for GNU ac_path_GREP and select it if it is found. -+ # Check for GNU $ac_path_GREP -+case `"$ac_path_GREP" --version 2>&1` in -+*GNU*) -+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; -+*) -+ ac_count=0 -+ $as_echo_n 0123456789 >"conftest.in" -+ while : -+ do -+ cat "conftest.in" "conftest.in" >"conftest.tmp" -+ mv "conftest.tmp" "conftest.in" -+ cp "conftest.in" "conftest.nl" -+ $as_echo 'GREP' >> "conftest.nl" -+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break -+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break -+ as_fn_arith $ac_count + 1 && ac_count=$as_val -+ if test $ac_count -gt ${ac_path_GREP_max-0}; then -+ # Best one so far, save it but keep looking for a better one -+ ac_cv_path_GREP="$ac_path_GREP" -+ ac_path_GREP_max=$ac_count -+ fi -+ # 10*(2^10) chars as input seems more than enough -+ test $ac_count -gt 10 && break -+ done -+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -+esac -+ -+ $ac_path_GREP_found && break 3 -+ done -+ done -+ done -+IFS=$as_save_IFS -+ if test -z "$ac_cv_path_GREP"; then -+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 -+ fi -+else -+ ac_cv_path_GREP=$GREP -+fi -+ -+fi -+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 -+$as_echo "$ac_cv_path_GREP" >&6; } -+ GREP="$ac_cv_path_GREP" -+ -+ -+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -+$as_echo_n "checking for egrep... " >&6; } -+if ${ac_cv_path_EGREP+:} false; then : -+ $as_echo_n "(cached) " >&6 -+else -+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 -+ then ac_cv_path_EGREP="$GREP -E" -+ else -+ if test -z "$EGREP"; then -+ ac_path_EGREP_found=false -+ # Loop through the user's path and test for each of PROGNAME-LIST -+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -+do -+ IFS=$as_save_IFS -+ test -z "$as_dir" && as_dir=. -+ for ac_prog in egrep; do -+ for ac_exec_ext in '' $ac_executable_extensions; do -+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" -+ as_fn_executable_p "$ac_path_EGREP" || continue -+# Check for GNU ac_path_EGREP and select it if it is found. -+ # Check for GNU $ac_path_EGREP -+case `"$ac_path_EGREP" --version 2>&1` in -+*GNU*) -+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -+*) -+ ac_count=0 -+ $as_echo_n 0123456789 >"conftest.in" -+ while : -+ do -+ cat "conftest.in" "conftest.in" >"conftest.tmp" -+ mv "conftest.tmp" "conftest.in" -+ cp "conftest.in" "conftest.nl" -+ $as_echo 'EGREP' >> "conftest.nl" -+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break -+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break -+ as_fn_arith $ac_count + 1 && ac_count=$as_val -+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then -+ # Best one so far, save it but keep looking for a better one -+ ac_cv_path_EGREP="$ac_path_EGREP" -+ ac_path_EGREP_max=$ac_count -+ fi -+ # 10*(2^10) chars as input seems more than enough -+ test $ac_count -gt 10 && break -+ done -+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -+esac -+ -+ $ac_path_EGREP_found && break 3 -+ done -+ done -+ done -+IFS=$as_save_IFS -+ if test -z "$ac_cv_path_EGREP"; then -+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 -+ fi -+else -+ ac_cv_path_EGREP=$EGREP -+fi -+ -+ fi -+fi -+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -+$as_echo "$ac_cv_path_EGREP" >&6; } -+ EGREP="$ac_cv_path_EGREP" -+ -+ -+cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+__SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_POINTER__ -+ -+_ACEOF -+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | -+ $EGREP "4 4 4" >/dev/null 2>&1; then : -+ libc_cv_loongarch_int_abi=lp32 -+fi -+rm -f conftest* -+ -+cat confdefs.h - <<_ACEOF >conftest.$ac_ext -+/* end confdefs.h. */ -+__SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_POINTER__ -+ -+_ACEOF -+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | -+ $EGREP "4 8 8" >/dev/null 2>&1; then : -+ libc_cv_loongarch_int_abi=lp64 -+fi -+rm -f conftest* -+ -+if test $libc_cv_loongarch_int_abi = no; then -+ as_fn_error $? "Unable to determine integer ABI" "$LINENO" 5 -+fi -+ -+config_vars="$config_vars -+default-abi = $libc_cv_loongarch_int_abi" -+ -+case $libc_cv_loongarch_int_abi in -+lp32) -+ test -n "$libc_cv_slibdir" || -+case "$prefix" in -+/usr | /usr/) -+ libc_cv_slibdir='/lib32' -+ libc_cv_rtlddir='/lib32' -+ if test "$libdir" = '${exec_prefix}/lib'; then -+ libdir='${exec_prefix}/lib32'; -+ # Locale data can be shared between 32-bit and 64-bit libraries. -+ libc_cv_complocaledir='${exec_prefix}/lib/locale' -+ fi -+ ;; -+esac -+ ;; -+lp64) -+ test -n "$libc_cv_slibdir" || -+case "$prefix" in -+/usr | /usr/) -+ libc_cv_slibdir='/lib64' -+ libc_cv_rtlddir='/lib64' -+ if test "$libdir" = '${exec_prefix}/lib'; then -+ libdir='${exec_prefix}/lib64'; -+ # Locale data can be shared between 32-bit and 64-bit libraries. -+ libc_cv_complocaledir='${exec_prefix}/lib/locale' -+ fi -+ ;; -+esac -+ ;; -+esac -+ -+ldd_rewrite_script=sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed -diff --git a/sysdeps/unix/sysv/linux/loongarch/configure.ac b/sysdeps/unix/sysv/linux/loongarch/configure.ac -new file mode 100644 -index 00000000..fef4f4d2 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/configure.ac -@@ -0,0 +1,27 @@ -+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=4.15.0 -+ -+libc_cv_loongarch_int_abi=no -+AC_EGREP_CPP(4 4 4, [__SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_POINTER__ -+ ], libc_cv_loongarch_int_abi=lp32) -+AC_EGREP_CPP(4 8 8, [__SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_POINTER__ -+ ], libc_cv_loongarch_int_abi=lp64) -+if test $libc_cv_loongarch_int_abi = no; then -+ AC_MSG_ERROR([Unable to determine integer ABI]) -+fi -+ -+LIBC_CONFIG_VAR([default-abi], [$libc_cv_loongarch_int_abi]) -+ -+case $libc_cv_loongarch_int_abi in -+lp32) -+ LIBC_SLIBDIR_RTLDDIR([lib32], [lib32]) -+ ;; -+lp64) -+ LIBC_SLIBDIR_RTLDDIR([lib64], [lib]) -+ ;; -+esac -+ -+ldd_rewrite_script=sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed -diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-static.c b/sysdeps/unix/sysv/linux/loongarch/dl-static.c -new file mode 100644 -index 00000000..12b030f0 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/dl-static.c -@@ -0,0 +1,84 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+ -+#ifdef SHARED -+ -+void -+_dl_var_init (void *array[]) -+{ -+ /* It has to match "variables" below. */ -+ enum -+ { -+ DL_PAGESIZE = 0 -+ }; -+ -+ GLRO(dl_pagesize) = *((size_t *) array[DL_PAGESIZE]); -+} -+ -+#else -+ -+static void *variables[] = -+{ -+ &GLRO(dl_pagesize) -+}; -+ -+static void -+_dl_unprotect_relro (struct link_map *l) -+{ -+ ElfW(Addr) start = ((l->l_addr + l->l_relro_addr) -+ & ~(GLRO(dl_pagesize) - 1)); -+ ElfW(Addr) end = ((l->l_addr + l->l_relro_addr + l->l_relro_size) -+ & ~(GLRO(dl_pagesize) - 1)); -+ -+ if (start != end) -+ __mprotect ((void *) start, end - start, PROT_READ | PROT_WRITE); -+} -+ -+void -+_dl_static_init (struct link_map *l) -+{ -+ struct link_map *rtld_map = l; -+ struct r_scope_elem **scope; -+ const ElfW(Sym) *ref = NULL; -+ lookup_t loadbase; -+ void (*f) (void *[]); -+ size_t i; -+ -+ loadbase = _dl_lookup_symbol_x ("_dl_var_init", l, &ref, l->l_local_scope, -+ NULL, 0, 1, NULL); -+ -+ for (scope = l->l_local_scope; *scope != NULL; scope++) -+ for (i = 0; i < (*scope)->r_nlist; i++) -+ if ((*scope)->r_list[i] == loadbase) -+ { -+ rtld_map = (*scope)->r_list[i]; -+ break; -+ } -+ -+ if (ref != NULL) -+ { -+ f = (void (*) (void *[])) DL_SYMBOL_ADDRESS (loadbase, ref); -+ _dl_unprotect_relro (rtld_map); -+ f (variables); -+ _dl_protect_relro (rtld_map); -+ } -+} -+ -+#endif -diff --git a/sysdeps/unix/sysv/linux/loongarch/getcontext.S b/sysdeps/unix/sysv/linux/loongarch/getcontext.S -new file mode 100644 -index 00000000..9c28d958 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/getcontext.S -@@ -0,0 +1,72 @@ -+/* Save current context. -+ Copyright (C) 2009-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include "ucontext-macros.h" -+ -+/* int getcontext (ucontext_t *ucp) */ -+ -+ .text -+LEAF (__getcontext) -+ SAVE_INT_REG (ra, 1, a0) -+ SAVE_INT_REG (sp, 3, a0) -+ SAVE_INT_REG (zero, 4, a0) /* return 0 by overwriting a0. */ -+ SAVE_INT_REG (x, 21, a0) -+ SAVE_INT_REG (fp, 22, a0) -+ SAVE_INT_REG (s0, 23, a0) -+ SAVE_INT_REG (s1, 24, a0) -+ SAVE_INT_REG (s2, 25, a0) -+ SAVE_INT_REG (s3, 26, a0) -+ SAVE_INT_REG (s4, 27, a0) -+ SAVE_INT_REG (s5, 28, a0) -+ SAVE_INT_REG (s6, 29, a0) -+ SAVE_INT_REG (s7, 30, a0) -+ SAVE_INT_REG (s8, 31, a0) -+ st.d ra, a0, MCONTEXT_PC -+ -+#ifndef __loongarch_soft_float -+ movfcsr2gr a1, $r0 -+ -+ SAVE_FP_REG (fs0, 24, a0) -+ SAVE_FP_REG (fs1, 25, a0) -+ SAVE_FP_REG (fs2, 26, a0) -+ SAVE_FP_REG (fs3, 27, a0) -+ SAVE_FP_REG (fs4, 28, a0) -+ SAVE_FP_REG (fs5, 29, a0) -+ SAVE_FP_REG (fs6, 30, a0) -+ SAVE_FP_REG (fs7, 31, a0) -+ -+ st.w a1, a0, MCONTEXT_FCSR -+#endif /* __loongarch_soft_float */ -+ -+/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */ -+ li.d a3, _NSIG8 -+ addi.d a2, a0, UCONTEXT_SIGMASK -+ ori a1, zero,0 -+ li.d a0, SIG_BLOCK -+ -+ li.d a7, SYS_ify (rt_sigprocmask) -+ syscall 0 -+ blt a0, zero, 99f -+ -+ jirl $r0, $r1, 0 -+ -+99: b __syscall_error -+ -+PSEUDO_END (__getcontext) -+ -+weak_alias (__getcontext, getcontext) -diff --git a/sysdeps/unix/sysv/linux/loongarch/getpid.c b/sysdeps/unix/sysv/linux/loongarch/getpid.c -new file mode 100644 -index 00000000..5b4edb2b ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/getpid.c -@@ -0,0 +1,54 @@ -+/* getpid - get the pid. Linux/Loongarch version. -+ Copyright (C) 2015-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+ -+#ifdef SHARED -+# include -+# include -+ -+static pid_t -+__getpid_syscall (void) -+{ -+ return INLINE_SYSCALL (getpid, 0); -+} -+ -+# ifndef __getpid_type -+# define __getpid_type __getpid -+# endif -+ -+# undef INIT_ARCH -+# define INIT_ARCH() PREPARE_VERSION_KNOWN (linux26, LINUX_2_6) -+libc_ifunc_hidden (__getpid_type, __getpid, (_dl_vdso_vsym ("__vdso_getpid", &linux26) ?: &__getpid_syscall)) -+libc_hidden_def (__getpid) -+ -+#else -+ -+# include -+# include -+ -+pid_t -+__getpid (void) -+{ -+ return INLINE_SYSCALL (getpid, 0); -+} -+libc_hidden_def (__getpid); -+ -+#endif -+weak_alias (__getpid, getpid) -+libc_hidden_weak (getpid) -diff --git a/sysdeps/unix/sysv/linux/loongarch/gettimeofday.c b/sysdeps/unix/sysv/linux/loongarch/gettimeofday.c -new file mode 100644 -index 00000000..902b1a5d ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/gettimeofday.c -@@ -0,0 +1,58 @@ -+/* gettimeofday - get the time. Linux/LoongArch version. -+ Copyright (C) 2015-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+ -+#ifdef SHARED -+ -+# include -+# include -+ -+static int -+__gettimeofday_syscall (struct timeval *tv, struct timezone *tz) -+{ -+ return INLINE_SYSCALL (gettimeofday, 2, tv, tz); -+} -+ -+# ifndef __gettimeofday_type -+# define __gettimeofday_type __gettimeofday -+# endif -+ -+# undef INIT_ARCH -+# define INIT_ARCH() PREPARE_VERSION_KNOWN (linux26, LINUX_2_6) -+/* If the vDSO is not available we fall back to syscall. */ -+libc_ifunc_hidden (__gettimeofday_type, __gettimeofday, -+ (_dl_vdso_vsym ("__vdso_gettimeofday", &linux26) -+ ?: &__gettimeofday_syscall)) -+libc_hidden_def (__gettimeofday) -+ -+#else -+ -+# include -+# include -+ -+int -+__gettimeofday (struct timeval *tv, struct timezone *tz) -+{ -+ return INLINE_SYSCALL (gettimeofday, 2, tv, tz); -+} -+libc_hidden_def (__gettimeofday) -+ -+#endif -+weak_alias (__gettimeofday, gettimeofday) -+libc_hidden_weak (gettimeofday) -diff --git a/sysdeps/unix/sysv/linux/loongarch/getuid.c b/sysdeps/unix/sysv/linux/loongarch/getuid.c -new file mode 100644 -index 00000000..4b3f95eb ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/getuid.c -@@ -0,0 +1,60 @@ -+/* getuid - get the uid. Linux/Loongarch version. -+ Copyright (C) 2015-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+ -+#ifdef SHARED -+ -+# include -+# include -+ -+libc_hidden_proto (getuid) -+ -+extern __uid_t __getuid (void); -+libc_hidden_proto (__getuid) -+ -+static uid_t -+__getuid_syscall(void) -+{ -+ return INLINE_SYSCALL (getuid, 0); -+} -+ -+# ifndef __getuid_type -+# define __getuid_type __getuid -+# endif -+ -+# undef INIT_ARCH -+# define INIT_ARCH() PREPARE_VERSION_KNOWN (linux26, LINUX_2_6) -+libc_ifunc_hidden (__getuid_type, __getuid, (_dl_vdso_vsym ("__vdso_getuid", &linux26) ?: &__getuid_syscall)) -+libc_hidden_def (__getuid) -+ -+#else -+ -+# include -+# include -+ -+uid_t -+__getuid(void) -+{ -+ return INLINE_SYSCALL (getuid, 0); -+} -+libc_hidden_def (__getuid) -+ -+#endif -+weak_alias (__getuid, getuid) -+libc_hidden_weak (getuid) -diff --git a/sysdeps/unix/sysv/linux/loongarch/init-first.c b/sysdeps/unix/sysv/linux/loongarch/init-first.c -new file mode 100644 -index 00000000..5185a831 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/init-first.c -@@ -0,0 +1,57 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public License as -+ published by the Free Software Foundation; either version 2.1 of the -+ License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#ifdef SHARED -+# include -+# include -+ -+long int (*VDSO_SYMBOL (getcpu)) (unsigned int *, unsigned int *, void *) -+ attribute_hidden; -+long int (*VDSO_SYMBOL (gettimeofday)) (struct timeval *, void *) -+ attribute_hidden; -+long int (*VDSO_SYMBOL (clock_gettime)) (clockid_t, struct timespec *) -+ attribute_hidden; -+long int (*VDSO_SYMBOL (clock_getres)) (clockid_t, struct timespec *) -+ attribute_hidden; -+ -+static inline void -+_libc_vdso_platform_setup (void) -+{ -+ PREPARE_VERSION_KNOWN (linux_version, LINUX_2_6); -+ -+ void *p = _dl_vdso_vsym ("__vdso_getcpu", &linux_version); -+ PTR_MANGLE (p); -+ VDSO_SYMBOL (getcpu) = p; -+ -+ p = _dl_vdso_vsym ("__vdso_gettimeofday", &linux_version); -+ PTR_MANGLE (p); -+ VDSO_SYMBOL (gettimeofday) = p; -+ -+ p = _dl_vdso_vsym ("__vdso_clock_gettime", &linux_version); -+ PTR_MANGLE (p); -+ VDSO_SYMBOL (clock_gettime) = p; -+ -+ p = _dl_vdso_vsym ("__vdso_clock_getres", &linux_version); -+ PTR_MANGLE (p); -+ VDSO_SYMBOL (clock_getres) = p; -+} -+ -+# define VDSO_SETUP _libc_vdso_platform_setup -+#endif -+ -+#include -diff --git a/sysdeps/unix/sysv/linux/loongarch/ipc_priv.h b/sysdeps/unix/sysv/linux/loongarch/ipc_priv.h -new file mode 100644 -index 00000000..51583429 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/ipc_priv.h -@@ -0,0 +1,21 @@ -+/* Old SysV permission definition for Linux. LoongArch version. -+ Copyright (C) 2020 Loongson Technology, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include /* For __key_t */ -+ -+#define __IPC_64 0x0 -diff --git a/sysdeps/unix/sysv/linux/loongarch/kernel-features.h b/sysdeps/unix/sysv/linux/loongarch/kernel-features.h -new file mode 100644 -index 00000000..c87c7967 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/kernel-features.h -@@ -0,0 +1,24 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ * -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include_next -+ -+/* No support for PI mutexes or robust futexes before 4.20. */ -+#if __LINUX_KERNEL_VERSION < 0x041400 -+# undef __ASSUME_SET_ROBUST_LIST -+#endif -diff --git a/sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed b/sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed -new file mode 100644 -index 00000000..131c5f14 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed -@@ -0,0 +1 @@ -+s_^\(RTLDLIST=\)\(.*lib/\)\(ld-linux\)-\(loongarch64\)-\(lp64\)\(d*\)\(\.so\.[0-9.]*\)_\1"\2\3-\4-\5\7 \2\3-\4-\5d\7"_ -diff --git a/sysdeps/unix/sysv/linux/loongarch/ldsodefs.h b/sysdeps/unix/sysv/linux/loongarch/ldsodefs.h -new file mode 100644 -index 00000000..c0fc7046 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/ldsodefs.h -@@ -0,0 +1,32 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _LDSODEFS_H -+ -+/* Get the real definitions. */ -+#include_next -+ -+/* Now define our stuff. */ -+ -+/* We need special support to initialize DSO loaded for statically linked -+ binaries. */ -+extern void _dl_static_init (struct link_map *map); -+#undef DL_STATIC_INIT -+#define DL_STATIC_INIT(map) _dl_static_init (map) -+ -+#endif /* ldsodefs.h */ -diff --git a/sysdeps/unix/sysv/linux/loongarch/libc-vdso.h b/sysdeps/unix/sysv/linux/loongarch/libc-vdso.h -new file mode 100644 -index 00000000..658c27a5 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/libc-vdso.h -@@ -0,0 +1,37 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _LIBC_VDSO_H -+#define _LIBC_VDSO_H -+ -+#ifdef SHARED -+ -+# include -+ -+extern long int (*VDSO_SYMBOL (getcpu)) (unsigned int *, unsigned int *, void *) -+ attribute_hidden; -+extern long int (*VDSO_SYMBOL (gettimeofday)) (struct timeval *, void *) -+ attribute_hidden; -+extern long int (*VDSO_SYMBOL (clock_gettime)) (clockid_t, struct timespec *) -+ attribute_hidden; -+extern long int (*VDSO_SYMBOL (clock_getres)) (clockid_t, struct timespec *) -+ attribute_hidden; -+ -+#endif -+ -+#endif /* _LIBC_VDSO_H */ -diff --git a/sysdeps/unix/sysv/linux/loongarch/localplt.data b/sysdeps/unix/sysv/linux/loongarch/localplt.data -new file mode 100644 -index 00000000..0ed8650b ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/localplt.data -@@ -0,0 +1,13 @@ -+# See scripts/check-localplt.awk for how this file is processed. -+# PLT use is required for the malloc family and for matherr because -+# users can define their own functions and have library internals call them. -+libc.so: calloc -+libc.so: free -+libc.so: malloc -+libc.so: memalign -+libc.so: realloc -+# The TLS-enabled version of these functions is interposed from libc.so. -+ld.so: _dl_signal_error -+ld.so: _dl_catch_error -+ld.so: _dl_signal_exception -+ld.so: _dl_catch_exception -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/Implies b/sysdeps/unix/sysv/linux/loongarch/lp64/Implies -new file mode 100644 -index 00000000..117c2b8e ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/Implies -@@ -0,0 +1,3 @@ -+unix/sysv/linux/loongarch -+unix/sysv/linux/generic -+unix/sysv/linux/wordsize-64 -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/c++-types.data b/sysdeps/unix/sysv/linux/loongarch/lp64/c++-types.data -new file mode 100644 -index 00000000..ac925ccb ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/c++-types.data -@@ -0,0 +1,67 @@ -+blkcnt64_t:l -+blkcnt_t:l -+blksize_t:i -+caddr_t:Pc -+clockid_t:i -+clock_t:l -+daddr_t:i -+dev_t:m -+fd_mask:l -+fsblkcnt64_t:m -+fsblkcnt_t:m -+fsfilcnt64_t:m -+fsfilcnt_t:m -+fsid_t:8__fsid_t -+gid_t:j -+id_t:j -+ino64_t:m -+ino_t:m -+int16_t:s -+int32_t:i -+int64_t:l -+int8_t:a -+intptr_t:l -+key_t:i -+loff_t:l -+mode_t:j -+nlink_t:j -+off64_t:l -+off_t:l -+pid_t:i -+pthread_attr_t:14pthread_attr_t -+pthread_barrier_t:17pthread_barrier_t -+pthread_barrierattr_t:21pthread_barrierattr_t -+pthread_cond_t:14pthread_cond_t -+pthread_condattr_t:18pthread_condattr_t -+pthread_key_t:j -+pthread_mutex_t:15pthread_mutex_t -+pthread_mutexattr_t:19pthread_mutexattr_t -+pthread_once_t:i -+pthread_rwlock_t:16pthread_rwlock_t -+pthread_rwlockattr_t:20pthread_rwlockattr_t -+pthread_spinlock_t:i -+pthread_t:m -+quad_t:l -+register_t:l -+rlim64_t:m -+rlim_t:m -+sigset_t:10__sigset_t -+size_t:m -+socklen_t:j -+ssize_t:l -+suseconds_t:l -+time_t:l -+u_char:h -+uid_t:j -+uint:j -+u_int:j -+u_int16_t:t -+u_int32_t:j -+u_int64_t:m -+u_int8_t:h -+ulong:m -+u_long:m -+u_quad_t:m -+useconds_t:j -+ushort:t -+u_short:t -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/jmp_buf-macros.h b/sysdeps/unix/sysv/linux/loongarch/lp64/jmp_buf-macros.h -new file mode 100644 -index 00000000..e1c96e67 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/jmp_buf-macros.h -@@ -0,0 +1,41 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+/* Produced by this program: -+ -+ #include -+ #include -+ #include -+ #include -+ -+ int main (int argc, char **argv) -+ { -+ printf ("#define JMP_BUF_SIZE %d\n", sizeof (jmp_buf)); -+ printf ("#define JMP_BUF_ALIGN %d\n", __alignof__ (jmp_buf)); -+ printf ("#define SIGJMP_BUF_SIZE %d\n", sizeof (sigjmp_buf)); -+ printf ("#define SIGJMP_BUF_ALIGN %d\n", __alignof__ (sigjmp_buf)); -+ printf ("#define MASK_WAS_SAVED_OFFSET %d\n", offsetof (struct __jmp_buf_tag, __mask_was_saved)); -+ printf ("#define SAVED_MASK_OFFSET %d\n", offsetof (struct __jmp_buf_tag, __saved_mask)); -+ } */ -+ -+# define JMP_BUF_SIZE 304 -+# define JMP_BUF_ALIGN 8 -+# define SIGJMP_BUF_SIZE 304 -+# define SIGJMP_BUF_ALIGN 8 -+# define MASK_WAS_SAVED_OFFSET 168 -+# define SAVED_MASK_OFFSET 176 -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/ld.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/ld.abilist -new file mode 100644 -index 00000000..845f356c ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/ld.abilist -@@ -0,0 +1,5 @@ -+GLIBC_2.27 __libc_stack_end D 0x8 -+GLIBC_2.27 __stack_chk_guard D 0x8 -+GLIBC_2.27 __tls_get_addr F -+GLIBC_2.27 _dl_mcount F -+GLIBC_2.27 _r_debug D 0x28 -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libBrokenLocale.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libBrokenLocale.abilist -new file mode 100644 -index 00000000..18968d3c ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libBrokenLocale.abilist -@@ -0,0 +1 @@ -+GLIBC_2.27 __ctype_get_mb_cur_max F -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libanl.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libanl.abilist -new file mode 100644 -index 00000000..711fc87c ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libanl.abilist -@@ -0,0 +1,4 @@ -+GLIBC_2.27 gai_cancel F -+GLIBC_2.27 gai_error F -+GLIBC_2.27 gai_suspend F -+GLIBC_2.27 getaddrinfo_a F -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist -new file mode 100644 -index 00000000..4d8733f2 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist -@@ -0,0 +1,2101 @@ -+GLIBC_2.27 _Exit F -+GLIBC_2.27 _IO_2_1_stderr_ D 0xe0 -+GLIBC_2.27 _IO_2_1_stdin_ D 0xe0 -+GLIBC_2.27 _IO_2_1_stdout_ D 0xe0 -+GLIBC_2.27 _IO_adjust_column F -+GLIBC_2.27 _IO_adjust_wcolumn F -+GLIBC_2.27 _IO_default_doallocate F -+GLIBC_2.27 _IO_default_finish F -+GLIBC_2.27 _IO_default_pbackfail F -+GLIBC_2.27 _IO_default_uflow F -+GLIBC_2.27 _IO_default_xsgetn F -+GLIBC_2.27 _IO_default_xsputn F -+GLIBC_2.27 _IO_do_write F -+GLIBC_2.27 _IO_doallocbuf F -+GLIBC_2.27 _IO_fclose F -+GLIBC_2.27 _IO_fdopen F -+GLIBC_2.27 _IO_feof F -+GLIBC_2.27 _IO_ferror F -+GLIBC_2.27 _IO_fflush F -+GLIBC_2.27 _IO_fgetpos F -+GLIBC_2.27 _IO_fgetpos64 F -+GLIBC_2.27 _IO_fgets F -+GLIBC_2.27 _IO_file_attach F -+GLIBC_2.27 _IO_file_close F -+GLIBC_2.27 _IO_file_close_it F -+GLIBC_2.27 _IO_file_doallocate F -+GLIBC_2.27 _IO_file_finish F -+GLIBC_2.27 _IO_file_fopen F -+GLIBC_2.27 _IO_file_init F -+GLIBC_2.27 _IO_file_jumps D 0xa8 -+GLIBC_2.27 _IO_file_open F -+GLIBC_2.27 _IO_file_overflow F -+GLIBC_2.27 _IO_file_read F -+GLIBC_2.27 _IO_file_seek F -+GLIBC_2.27 _IO_file_seekoff F -+GLIBC_2.27 _IO_file_setbuf F -+GLIBC_2.27 _IO_file_stat F -+GLIBC_2.27 _IO_file_sync F -+GLIBC_2.27 _IO_file_underflow F -+GLIBC_2.27 _IO_file_write F -+GLIBC_2.27 _IO_file_xsputn F -+GLIBC_2.27 _IO_flockfile F -+GLIBC_2.27 _IO_flush_all F -+GLIBC_2.27 _IO_flush_all_linebuffered F -+GLIBC_2.27 _IO_fopen F -+GLIBC_2.27 _IO_fprintf F -+GLIBC_2.27 _IO_fputs F -+GLIBC_2.27 _IO_fread F -+GLIBC_2.27 _IO_free_backup_area F -+GLIBC_2.27 _IO_free_wbackup_area F -+GLIBC_2.27 _IO_fsetpos F -+GLIBC_2.27 _IO_fsetpos64 F -+GLIBC_2.27 _IO_ftell F -+GLIBC_2.27 _IO_ftrylockfile F -+GLIBC_2.27 _IO_funlockfile F -+GLIBC_2.27 _IO_fwrite F -+GLIBC_2.27 _IO_getc F -+GLIBC_2.27 _IO_getline F -+GLIBC_2.27 _IO_getline_info F -+GLIBC_2.27 _IO_gets F -+GLIBC_2.27 _IO_init F -+GLIBC_2.27 _IO_init_marker F -+GLIBC_2.27 _IO_init_wmarker F -+GLIBC_2.27 _IO_iter_begin F -+GLIBC_2.27 _IO_iter_end F -+GLIBC_2.27 _IO_iter_file F -+GLIBC_2.27 _IO_iter_next F -+GLIBC_2.27 _IO_least_wmarker F -+GLIBC_2.27 _IO_link_in F -+GLIBC_2.27 _IO_list_all D 0x8 -+GLIBC_2.27 _IO_list_lock F -+GLIBC_2.27 _IO_list_resetlock F -+GLIBC_2.27 _IO_list_unlock F -+GLIBC_2.27 _IO_marker_delta F -+GLIBC_2.27 _IO_marker_difference F -+GLIBC_2.27 _IO_padn F -+GLIBC_2.27 _IO_peekc_locked F -+GLIBC_2.27 _IO_popen F -+GLIBC_2.27 _IO_printf F -+GLIBC_2.27 _IO_proc_close F -+GLIBC_2.27 _IO_proc_open F -+GLIBC_2.27 _IO_putc F -+GLIBC_2.27 _IO_puts F -+GLIBC_2.27 _IO_remove_marker F -+GLIBC_2.27 _IO_seekmark F -+GLIBC_2.27 _IO_seekoff F -+GLIBC_2.27 _IO_seekpos F -+GLIBC_2.27 _IO_seekwmark F -+GLIBC_2.27 _IO_setb F -+GLIBC_2.27 _IO_setbuffer F -+GLIBC_2.27 _IO_setvbuf F -+GLIBC_2.27 _IO_sgetn F -+GLIBC_2.27 _IO_sprintf F -+GLIBC_2.27 _IO_sputbackc F -+GLIBC_2.27 _IO_sputbackwc F -+GLIBC_2.27 _IO_sscanf F -+GLIBC_2.27 _IO_str_init_readonly F -+GLIBC_2.27 _IO_str_init_static F -+GLIBC_2.27 _IO_str_overflow F -+GLIBC_2.27 _IO_str_pbackfail F -+GLIBC_2.27 _IO_str_seekoff F -+GLIBC_2.27 _IO_str_underflow F -+GLIBC_2.27 _IO_sungetc F -+GLIBC_2.27 _IO_sungetwc F -+GLIBC_2.27 _IO_switch_to_get_mode F -+GLIBC_2.27 _IO_switch_to_main_wget_area F -+GLIBC_2.27 _IO_switch_to_wbackup_area F -+GLIBC_2.27 _IO_switch_to_wget_mode F -+GLIBC_2.27 _IO_un_link F -+GLIBC_2.27 _IO_ungetc F -+GLIBC_2.27 _IO_unsave_markers F -+GLIBC_2.27 _IO_unsave_wmarkers F -+GLIBC_2.27 _IO_vfprintf F -+GLIBC_2.27 _IO_vfscanf F -+GLIBC_2.27 _IO_vsprintf F -+GLIBC_2.27 _IO_wdefault_doallocate F -+GLIBC_2.27 _IO_wdefault_finish F -+GLIBC_2.27 _IO_wdefault_pbackfail F -+GLIBC_2.27 _IO_wdefault_uflow F -+GLIBC_2.27 _IO_wdefault_xsgetn F -+GLIBC_2.27 _IO_wdefault_xsputn F -+GLIBC_2.27 _IO_wdo_write F -+GLIBC_2.27 _IO_wdoallocbuf F -+GLIBC_2.27 _IO_wfile_jumps D 0xa8 -+GLIBC_2.27 _IO_wfile_overflow F -+GLIBC_2.27 _IO_wfile_seekoff F -+GLIBC_2.27 _IO_wfile_sync F -+GLIBC_2.27 _IO_wfile_underflow F -+GLIBC_2.27 _IO_wfile_xsputn F -+GLIBC_2.27 _IO_wmarker_delta F -+GLIBC_2.27 _IO_wsetb F -+GLIBC_2.27 ___brk_addr D 0x8 -+GLIBC_2.27 __adjtimex F -+GLIBC_2.27 __after_morecore_hook D 0x8 -+GLIBC_2.27 __argz_count F -+GLIBC_2.27 __argz_next F -+GLIBC_2.27 __argz_stringify F -+GLIBC_2.27 __asprintf F -+GLIBC_2.27 __asprintf_chk F -+GLIBC_2.27 __assert F -+GLIBC_2.27 __assert_fail F -+GLIBC_2.27 __assert_perror_fail F -+GLIBC_2.27 __backtrace F -+GLIBC_2.27 __backtrace_symbols F -+GLIBC_2.27 __backtrace_symbols_fd F -+GLIBC_2.27 __bsd_getpgrp F -+GLIBC_2.27 __bzero F -+GLIBC_2.27 __check_rhosts_file D 0x4 -+GLIBC_2.27 __chk_fail F -+GLIBC_2.27 __clone F -+GLIBC_2.27 __close F -+GLIBC_2.27 __cmsg_nxthdr F -+GLIBC_2.27 __confstr_chk F -+GLIBC_2.27 __connect F -+GLIBC_2.27 __ctype_b_loc F -+GLIBC_2.27 __ctype_get_mb_cur_max F -+GLIBC_2.27 __ctype_tolower_loc F -+GLIBC_2.27 __ctype_toupper_loc F -+GLIBC_2.27 __curbrk D 0x8 -+GLIBC_2.27 __cxa_at_quick_exit F -+GLIBC_2.27 __cxa_atexit F -+GLIBC_2.27 __cxa_finalize F -+GLIBC_2.27 __cxa_thread_atexit_impl F -+GLIBC_2.27 __cyg_profile_func_enter F -+GLIBC_2.27 __cyg_profile_func_exit F -+GLIBC_2.27 __daylight D 0x4 -+GLIBC_2.27 __dcgettext F -+GLIBC_2.27 __default_morecore F -+GLIBC_2.27 __dgettext F -+GLIBC_2.27 __dprintf_chk F -+GLIBC_2.27 __dup2 F -+GLIBC_2.27 __duplocale F -+GLIBC_2.27 __endmntent F -+GLIBC_2.27 __environ D 0x8 -+GLIBC_2.27 __errno_location F -+GLIBC_2.27 __explicit_bzero_chk F -+GLIBC_2.27 __fbufsize F -+GLIBC_2.27 __fcntl F -+GLIBC_2.27 __fdelt_chk F -+GLIBC_2.27 __fdelt_warn F -+GLIBC_2.27 __ffs F -+GLIBC_2.27 __fgets_chk F -+GLIBC_2.27 __fgets_unlocked_chk F -+GLIBC_2.27 __fgetws_chk F -+GLIBC_2.27 __fgetws_unlocked_chk F -+GLIBC_2.27 __finite F -+GLIBC_2.27 __finitef F -+GLIBC_2.27 __finitel F -+GLIBC_2.27 __flbf F -+GLIBC_2.27 __fork F -+GLIBC_2.27 __fpending F -+GLIBC_2.27 __fprintf_chk F -+GLIBC_2.27 __fpu_control D 0x4 -+GLIBC_2.27 __fpurge F -+GLIBC_2.27 __fread_chk F -+GLIBC_2.27 __fread_unlocked_chk F -+GLIBC_2.27 __freadable F -+GLIBC_2.27 __freading F -+GLIBC_2.27 __free_hook D 0x8 -+GLIBC_2.27 __freelocale F -+GLIBC_2.27 __fsetlocking F -+GLIBC_2.27 __fwprintf_chk F -+GLIBC_2.27 __fwritable F -+GLIBC_2.27 __fwriting F -+GLIBC_2.27 __fxstat F -+GLIBC_2.27 __fxstat64 F -+GLIBC_2.27 __fxstatat F -+GLIBC_2.27 __fxstatat64 F -+GLIBC_2.27 __getauxval F -+GLIBC_2.27 __getcwd_chk F -+GLIBC_2.27 __getdelim F -+GLIBC_2.27 __getdomainname_chk F -+GLIBC_2.27 __getgroups_chk F -+GLIBC_2.27 __gethostname_chk F -+GLIBC_2.27 __getlogin_r_chk F -+GLIBC_2.27 __getmntent_r F -+GLIBC_2.27 __getpagesize F -+GLIBC_2.27 __getpgid F -+GLIBC_2.27 __getpid F -+GLIBC_2.27 __gets_chk F -+GLIBC_2.27 __gettimeofday F -+GLIBC_2.27 __getwd_chk F -+GLIBC_2.27 __gmtime_r F -+GLIBC_2.27 __h_errno_location F -+GLIBC_2.27 __isalnum_l F -+GLIBC_2.27 __isalpha_l F -+GLIBC_2.27 __isascii_l F -+GLIBC_2.27 __isblank_l F -+GLIBC_2.27 __iscntrl_l F -+GLIBC_2.27 __isctype F -+GLIBC_2.27 __isdigit_l F -+GLIBC_2.27 __isgraph_l F -+GLIBC_2.27 __isinf F -+GLIBC_2.27 __isinff F -+GLIBC_2.27 __isinfl F -+GLIBC_2.27 __islower_l F -+GLIBC_2.27 __isnan F -+GLIBC_2.27 __isnanf F -+GLIBC_2.27 __isnanl F -+GLIBC_2.27 __isoc99_fscanf F -+GLIBC_2.27 __isoc99_fwscanf F -+GLIBC_2.27 __isoc99_scanf F -+GLIBC_2.27 __isoc99_sscanf F -+GLIBC_2.27 __isoc99_swscanf F -+GLIBC_2.27 __isoc99_vfscanf F -+GLIBC_2.27 __isoc99_vfwscanf F -+GLIBC_2.27 __isoc99_vscanf F -+GLIBC_2.27 __isoc99_vsscanf F -+GLIBC_2.27 __isoc99_vswscanf F -+GLIBC_2.27 __isoc99_vwscanf F -+GLIBC_2.27 __isoc99_wscanf F -+GLIBC_2.27 __isprint_l F -+GLIBC_2.27 __ispunct_l F -+GLIBC_2.27 __isspace_l F -+GLIBC_2.27 __isupper_l F -+GLIBC_2.27 __iswalnum_l F -+GLIBC_2.27 __iswalpha_l F -+GLIBC_2.27 __iswblank_l F -+GLIBC_2.27 __iswcntrl_l F -+GLIBC_2.27 __iswctype F -+GLIBC_2.27 __iswctype_l F -+GLIBC_2.27 __iswdigit_l F -+GLIBC_2.27 __iswgraph_l F -+GLIBC_2.27 __iswlower_l F -+GLIBC_2.27 __iswprint_l F -+GLIBC_2.27 __iswpunct_l F -+GLIBC_2.27 __iswspace_l F -+GLIBC_2.27 __iswupper_l F -+GLIBC_2.27 __iswxdigit_l F -+GLIBC_2.27 __isxdigit_l F -+GLIBC_2.27 __ivaliduser F -+GLIBC_2.27 __key_decryptsession_pk_LOCAL D 0x8 -+GLIBC_2.27 __key_encryptsession_pk_LOCAL D 0x8 -+GLIBC_2.27 __key_gendes_LOCAL D 0x8 -+GLIBC_2.27 __libc_allocate_rtsig F -+GLIBC_2.27 __libc_calloc F -+GLIBC_2.27 __libc_current_sigrtmax F -+GLIBC_2.27 __libc_current_sigrtmin F -+GLIBC_2.27 __libc_free F -+GLIBC_2.27 __libc_freeres F -+GLIBC_2.27 __libc_init_first F -+GLIBC_2.27 __libc_mallinfo F -+GLIBC_2.27 __libc_malloc F -+GLIBC_2.27 __libc_mallopt F -+GLIBC_2.27 __libc_memalign F -+GLIBC_2.27 __libc_pvalloc F -+GLIBC_2.27 __libc_realloc F -+GLIBC_2.27 __libc_sa_len F -+GLIBC_2.27 __libc_start_main F -+GLIBC_2.27 __libc_valloc F -+GLIBC_2.27 __longjmp_chk F -+GLIBC_2.27 __lseek F -+GLIBC_2.27 __lxstat F -+GLIBC_2.27 __lxstat64 F -+GLIBC_2.27 __malloc_hook D 0x8 -+GLIBC_2.27 __mbrlen F -+GLIBC_2.27 __mbrtowc F -+GLIBC_2.27 __mbsnrtowcs_chk F -+GLIBC_2.27 __mbsrtowcs_chk F -+GLIBC_2.27 __mbstowcs_chk F -+GLIBC_2.27 __memalign_hook D 0x8 -+GLIBC_2.27 __memcpy_chk F -+GLIBC_2.27 __memmove_chk F -+GLIBC_2.27 __mempcpy F -+GLIBC_2.27 __mempcpy_chk F -+GLIBC_2.27 __memset_chk F -+GLIBC_2.27 __monstartup F -+GLIBC_2.27 __morecore D 0x8 -+GLIBC_2.27 __nanosleep F -+GLIBC_2.27 __newlocale F -+GLIBC_2.27 __nl_langinfo_l F -+GLIBC_2.27 __nss_configure_lookup F -+GLIBC_2.27 __nss_database_lookup F -+GLIBC_2.27 __nss_hostname_digits_dots F -+GLIBC_2.27 __nss_next F -+GLIBC_2.27 __obstack_printf_chk F -+GLIBC_2.27 __obstack_vprintf_chk F -+GLIBC_2.27 __open F -+GLIBC_2.27 __open64 F -+GLIBC_2.27 __open64_2 F -+GLIBC_2.27 __open_2 F -+GLIBC_2.27 __openat64_2 F -+GLIBC_2.27 __openat_2 F -+GLIBC_2.27 __overflow F -+GLIBC_2.27 __pipe F -+GLIBC_2.27 __poll F -+GLIBC_2.27 __poll_chk F -+GLIBC_2.27 __posix_getopt F -+GLIBC_2.27 __ppoll_chk F -+GLIBC_2.27 __pread64 F -+GLIBC_2.27 __pread64_chk F -+GLIBC_2.27 __pread_chk F -+GLIBC_2.27 __printf_chk F -+GLIBC_2.27 __printf_fp F -+GLIBC_2.27 __profile_frequency F -+GLIBC_2.27 __progname D 0x8 -+GLIBC_2.27 __progname_full D 0x8 -+GLIBC_2.27 __ptsname_r_chk F -+GLIBC_2.27 __pwrite64 F -+GLIBC_2.27 __rawmemchr F -+GLIBC_2.27 __rcmd_errstr D 0x8 -+GLIBC_2.27 __read F -+GLIBC_2.27 __read_chk F -+GLIBC_2.27 __readlink_chk F -+GLIBC_2.27 __readlinkat_chk F -+GLIBC_2.27 __realloc_hook D 0x8 -+GLIBC_2.27 __realpath_chk F -+GLIBC_2.27 __recv_chk F -+GLIBC_2.27 __recvfrom_chk F -+GLIBC_2.27 __register_atfork F -+GLIBC_2.27 __res_init F -+GLIBC_2.27 __res_nclose F -+GLIBC_2.27 __res_ninit F -+GLIBC_2.27 __res_randomid F -+GLIBC_2.27 __res_state F -+GLIBC_2.27 __rpc_thread_createerr F -+GLIBC_2.27 __rpc_thread_svc_fdset F -+GLIBC_2.27 __rpc_thread_svc_max_pollfd F -+GLIBC_2.27 __rpc_thread_svc_pollfd F -+GLIBC_2.27 __sbrk F -+GLIBC_2.27 __sched_cpualloc F -+GLIBC_2.27 __sched_cpucount F -+GLIBC_2.27 __sched_cpufree F -+GLIBC_2.27 __sched_get_priority_max F -+GLIBC_2.27 __sched_get_priority_min F -+GLIBC_2.27 __sched_getparam F -+GLIBC_2.27 __sched_getscheduler F -+GLIBC_2.27 __sched_setscheduler F -+GLIBC_2.27 __sched_yield F -+GLIBC_2.27 __select F -+GLIBC_2.27 __send F -+GLIBC_2.27 __setmntent F -+GLIBC_2.27 __setpgid F -+GLIBC_2.27 __sigaction F -+GLIBC_2.27 __signbit F -+GLIBC_2.27 __signbitf F -+GLIBC_2.27 __signbitl F -+GLIBC_2.27 __sigpause F -+GLIBC_2.27 __sigsetjmp F -+GLIBC_2.27 __sigsuspend F -+GLIBC_2.27 __snprintf_chk F -+GLIBC_2.27 __sprintf_chk F -+GLIBC_2.27 __stack_chk_fail F -+GLIBC_2.27 __statfs F -+GLIBC_2.27 __stpcpy F -+GLIBC_2.27 __stpcpy_chk F -+GLIBC_2.27 __stpncpy F -+GLIBC_2.27 __stpncpy_chk F -+GLIBC_2.27 __strcasecmp F -+GLIBC_2.27 __strcasecmp_l F -+GLIBC_2.27 __strcasestr F -+GLIBC_2.27 __strcat_chk F -+GLIBC_2.27 __strcoll_l F -+GLIBC_2.27 __strcpy_chk F -+GLIBC_2.27 __strdup F -+GLIBC_2.27 __strerror_r F -+GLIBC_2.27 __strfmon_l F -+GLIBC_2.27 __strftime_l F -+GLIBC_2.27 __strncasecmp_l F -+GLIBC_2.27 __strncat_chk F -+GLIBC_2.27 __strncpy_chk F -+GLIBC_2.27 __strndup F -+GLIBC_2.27 __strsep_g F -+GLIBC_2.27 __strtod_internal F -+GLIBC_2.27 __strtod_l F -+GLIBC_2.27 __strtof_internal F -+GLIBC_2.27 __strtof_l F -+GLIBC_2.27 __strtok_r F -+GLIBC_2.27 __strtol_internal F -+GLIBC_2.27 __strtol_l F -+GLIBC_2.27 __strtold_internal F -+GLIBC_2.27 __strtold_l F -+GLIBC_2.27 __strtoll_internal F -+GLIBC_2.27 __strtoll_l F -+GLIBC_2.27 __strtoul_internal F -+GLIBC_2.27 __strtoul_l F -+GLIBC_2.27 __strtoull_internal F -+GLIBC_2.27 __strtoull_l F -+GLIBC_2.27 __strverscmp F -+GLIBC_2.27 __strxfrm_l F -+GLIBC_2.27 __swprintf_chk F -+GLIBC_2.27 __sysconf F -+GLIBC_2.27 __syslog_chk F -+GLIBC_2.27 __sysv_signal F -+GLIBC_2.27 __timezone D 0x8 -+GLIBC_2.27 __toascii_l F -+GLIBC_2.27 __tolower_l F -+GLIBC_2.27 __toupper_l F -+GLIBC_2.27 __towctrans F -+GLIBC_2.27 __towctrans_l F -+GLIBC_2.27 __towlower_l F -+GLIBC_2.27 __towupper_l F -+GLIBC_2.27 __ttyname_r_chk F -+GLIBC_2.27 __tzname D 0x10 -+GLIBC_2.27 __uflow F -+GLIBC_2.27 __underflow F -+GLIBC_2.27 __uselocale F -+GLIBC_2.27 __vasprintf_chk F -+GLIBC_2.27 __vdprintf_chk F -+GLIBC_2.27 __vfork F -+GLIBC_2.27 __vfprintf_chk F -+GLIBC_2.27 __vfscanf F -+GLIBC_2.27 __vfwprintf_chk F -+GLIBC_2.27 __vprintf_chk F -+GLIBC_2.27 __vsnprintf F -+GLIBC_2.27 __vsnprintf_chk F -+GLIBC_2.27 __vsprintf_chk F -+GLIBC_2.27 __vsscanf F -+GLIBC_2.27 __vswprintf_chk F -+GLIBC_2.27 __vsyslog_chk F -+GLIBC_2.27 __vwprintf_chk F -+GLIBC_2.27 __wait F -+GLIBC_2.27 __waitpid F -+GLIBC_2.27 __wcpcpy_chk F -+GLIBC_2.27 __wcpncpy_chk F -+GLIBC_2.27 __wcrtomb_chk F -+GLIBC_2.27 __wcscasecmp_l F -+GLIBC_2.27 __wcscat_chk F -+GLIBC_2.27 __wcscoll_l F -+GLIBC_2.27 __wcscpy_chk F -+GLIBC_2.27 __wcsftime_l F -+GLIBC_2.27 __wcsncasecmp_l F -+GLIBC_2.27 __wcsncat_chk F -+GLIBC_2.27 __wcsncpy_chk F -+GLIBC_2.27 __wcsnrtombs_chk F -+GLIBC_2.27 __wcsrtombs_chk F -+GLIBC_2.27 __wcstod_internal F -+GLIBC_2.27 __wcstod_l F -+GLIBC_2.27 __wcstof_internal F -+GLIBC_2.27 __wcstof_l F -+GLIBC_2.27 __wcstol_internal F -+GLIBC_2.27 __wcstol_l F -+GLIBC_2.27 __wcstold_internal F -+GLIBC_2.27 __wcstold_l F -+GLIBC_2.27 __wcstoll_internal F -+GLIBC_2.27 __wcstoll_l F -+GLIBC_2.27 __wcstombs_chk F -+GLIBC_2.27 __wcstoul_internal F -+GLIBC_2.27 __wcstoul_l F -+GLIBC_2.27 __wcstoull_internal F -+GLIBC_2.27 __wcstoull_l F -+GLIBC_2.27 __wcsxfrm_l F -+GLIBC_2.27 __wctomb_chk F -+GLIBC_2.27 __wctrans_l F -+GLIBC_2.27 __wctype_l F -+GLIBC_2.27 __wmemcpy_chk F -+GLIBC_2.27 __wmemmove_chk F -+GLIBC_2.27 __wmempcpy_chk F -+GLIBC_2.27 __wmemset_chk F -+GLIBC_2.27 __woverflow F -+GLIBC_2.27 __wprintf_chk F -+GLIBC_2.27 __write F -+GLIBC_2.27 __wuflow F -+GLIBC_2.27 __wunderflow F -+GLIBC_2.27 __xmknod F -+GLIBC_2.27 __xmknodat F -+GLIBC_2.27 __xpg_basename F -+GLIBC_2.27 __xpg_sigpause F -+GLIBC_2.27 __xpg_strerror_r F -+GLIBC_2.27 __xstat F -+GLIBC_2.27 __xstat64 F -+GLIBC_2.27 _authenticate F -+GLIBC_2.27 _dl_mcount_wrapper F -+GLIBC_2.27 _dl_mcount_wrapper_check F -+GLIBC_2.27 _environ D 0x8 -+GLIBC_2.27 _exit F -+GLIBC_2.27 _flushlbf F -+GLIBC_2.27 _libc_intl_domainname D 0x5 -+GLIBC_2.27 _longjmp F -+GLIBC_2.27 _mcleanup F -+GLIBC_2.27 _mcount F -+GLIBC_2.27 _nl_default_dirname D 0x12 -+GLIBC_2.27 _nl_domain_bindings D 0x8 -+GLIBC_2.27 _nl_msg_cat_cntr D 0x4 -+GLIBC_2.27 _null_auth D 0x18 -+GLIBC_2.27 _obstack_allocated_p F -+GLIBC_2.27 _obstack_begin F -+GLIBC_2.27 _obstack_begin_1 F -+GLIBC_2.27 _obstack_free F -+GLIBC_2.27 _obstack_memory_used F -+GLIBC_2.27 _obstack_newchunk F -+GLIBC_2.27 _res D 0x238 -+GLIBC_2.27 _res_hconf D 0x48 -+GLIBC_2.27 _rpc_dtablesize F -+GLIBC_2.27 _seterr_reply F -+GLIBC_2.27 _setjmp F -+GLIBC_2.27 _sys_errlist D 0x2370 -+GLIBC_2.27 _sys_nerr D 0x4 -+GLIBC_2.27 _sys_siglist D 0x400 -+GLIBC_2.27 _tolower F -+GLIBC_2.27 _toupper F -+GLIBC_2.27 a64l F -+GLIBC_2.27 abort F -+GLIBC_2.27 abs F -+GLIBC_2.27 accept F -+GLIBC_2.27 accept4 F -+GLIBC_2.27 access F -+GLIBC_2.27 acct F -+GLIBC_2.27 addmntent F -+GLIBC_2.27 addseverity F -+GLIBC_2.27 adjtime F -+GLIBC_2.27 adjtimex F -+GLIBC_2.27 alarm F -+GLIBC_2.27 aligned_alloc F -+GLIBC_2.27 alphasort F -+GLIBC_2.27 alphasort64 F -+GLIBC_2.27 argp_err_exit_status D 0x4 -+GLIBC_2.27 argp_error F -+GLIBC_2.27 argp_failure F -+GLIBC_2.27 argp_help F -+GLIBC_2.27 argp_parse F -+GLIBC_2.27 argp_program_bug_address D 0x8 -+GLIBC_2.27 argp_program_version D 0x8 -+GLIBC_2.27 argp_program_version_hook D 0x8 -+GLIBC_2.27 argp_state_help F -+GLIBC_2.27 argp_usage F -+GLIBC_2.27 argz_add F -+GLIBC_2.27 argz_add_sep F -+GLIBC_2.27 argz_append F -+GLIBC_2.27 argz_count F -+GLIBC_2.27 argz_create F -+GLIBC_2.27 argz_create_sep F -+GLIBC_2.27 argz_delete F -+GLIBC_2.27 argz_extract F -+GLIBC_2.27 argz_insert F -+GLIBC_2.27 argz_next F -+GLIBC_2.27 argz_replace F -+GLIBC_2.27 argz_stringify F -+GLIBC_2.27 asctime F -+GLIBC_2.27 asctime_r F -+GLIBC_2.27 asprintf F -+GLIBC_2.27 atof F -+GLIBC_2.27 atoi F -+GLIBC_2.27 atol F -+GLIBC_2.27 atoll F -+GLIBC_2.27 authdes_create F -+GLIBC_2.27 authdes_getucred F -+GLIBC_2.27 authdes_pk_create F -+GLIBC_2.27 authnone_create F -+GLIBC_2.27 authunix_create F -+GLIBC_2.27 authunix_create_default F -+GLIBC_2.27 backtrace F -+GLIBC_2.27 backtrace_symbols F -+GLIBC_2.27 backtrace_symbols_fd F -+GLIBC_2.27 basename F -+GLIBC_2.27 bcmp F -+GLIBC_2.27 bcopy F -+GLIBC_2.27 bind F -+GLIBC_2.27 bind_textdomain_codeset F -+GLIBC_2.27 bindresvport F -+GLIBC_2.27 bindtextdomain F -+GLIBC_2.27 brk F -+GLIBC_2.27 bsd_signal F -+GLIBC_2.27 bsearch F -+GLIBC_2.27 btowc F -+GLIBC_2.27 bzero F -+GLIBC_2.27 c16rtomb F -+GLIBC_2.27 c32rtomb F -+GLIBC_2.27 calloc F -+GLIBC_2.27 callrpc F -+GLIBC_2.27 canonicalize_file_name F -+GLIBC_2.27 capget F -+GLIBC_2.27 capset F -+GLIBC_2.27 catclose F -+GLIBC_2.27 catgets F -+GLIBC_2.27 catopen F -+GLIBC_2.27 cbc_crypt F -+GLIBC_2.27 cfgetispeed F -+GLIBC_2.27 cfgetospeed F -+GLIBC_2.27 cfmakeraw F -+GLIBC_2.27 cfsetispeed F -+GLIBC_2.27 cfsetospeed F -+GLIBC_2.27 cfsetspeed F -+GLIBC_2.27 chdir F -+GLIBC_2.27 chflags F -+GLIBC_2.27 chmod F -+GLIBC_2.27 chown F -+GLIBC_2.27 chroot F -+GLIBC_2.27 clearenv F -+GLIBC_2.27 clearerr F -+GLIBC_2.27 clearerr_unlocked F -+GLIBC_2.27 clnt_broadcast F -+GLIBC_2.27 clnt_create F -+GLIBC_2.27 clnt_pcreateerror F -+GLIBC_2.27 clnt_perrno F -+GLIBC_2.27 clnt_perror F -+GLIBC_2.27 clnt_spcreateerror F -+GLIBC_2.27 clnt_sperrno F -+GLIBC_2.27 clnt_sperror F -+GLIBC_2.27 clntraw_create F -+GLIBC_2.27 clnttcp_create F -+GLIBC_2.27 clntudp_bufcreate F -+GLIBC_2.27 clntudp_create F -+GLIBC_2.27 clntunix_create F -+GLIBC_2.27 clock F -+GLIBC_2.27 clock_adjtime F -+GLIBC_2.27 clock_getcpuclockid F -+GLIBC_2.27 clock_getres F -+GLIBC_2.27 clock_gettime F -+GLIBC_2.27 clock_nanosleep F -+GLIBC_2.27 clock_settime F -+GLIBC_2.27 clone F -+GLIBC_2.27 close F -+GLIBC_2.27 closedir F -+GLIBC_2.27 closelog F -+GLIBC_2.27 confstr F -+GLIBC_2.27 connect F -+GLIBC_2.27 copy_file_range F -+GLIBC_2.27 copysign F -+GLIBC_2.27 copysignf F -+GLIBC_2.27 copysignl F -+GLIBC_2.27 creat F -+GLIBC_2.27 creat64 F -+GLIBC_2.27 ctermid F -+GLIBC_2.27 ctime F -+GLIBC_2.27 ctime_r F -+GLIBC_2.27 cuserid F -+GLIBC_2.27 daemon F -+GLIBC_2.27 daylight D 0x4 -+GLIBC_2.27 dcgettext F -+GLIBC_2.27 dcngettext F -+GLIBC_2.27 delete_module F -+GLIBC_2.27 des_setparity F -+GLIBC_2.27 dgettext F -+GLIBC_2.27 difftime F -+GLIBC_2.27 dirfd F -+GLIBC_2.27 dirname F -+GLIBC_2.27 div F -+GLIBC_2.27 dl_iterate_phdr F -+GLIBC_2.27 dngettext F -+GLIBC_2.27 dprintf F -+GLIBC_2.27 drand48 F -+GLIBC_2.27 drand48_r F -+GLIBC_2.27 dup F -+GLIBC_2.27 dup2 F -+GLIBC_2.27 dup3 F -+GLIBC_2.27 duplocale F -+GLIBC_2.27 dysize F -+GLIBC_2.27 eaccess F -+GLIBC_2.27 ecb_crypt F -+GLIBC_2.27 ecvt F -+GLIBC_2.27 ecvt_r F -+GLIBC_2.27 endaliasent F -+GLIBC_2.27 endfsent F -+GLIBC_2.27 endgrent F -+GLIBC_2.27 endhostent F -+GLIBC_2.27 endmntent F -+GLIBC_2.27 endnetent F -+GLIBC_2.27 endnetgrent F -+GLIBC_2.27 endprotoent F -+GLIBC_2.27 endpwent F -+GLIBC_2.27 endrpcent F -+GLIBC_2.27 endservent F -+GLIBC_2.27 endsgent F -+GLIBC_2.27 endspent F -+GLIBC_2.27 endttyent F -+GLIBC_2.27 endusershell F -+GLIBC_2.27 endutent F -+GLIBC_2.27 endutxent F -+GLIBC_2.27 environ D 0x8 -+GLIBC_2.27 envz_add F -+GLIBC_2.27 envz_entry F -+GLIBC_2.27 envz_get F -+GLIBC_2.27 envz_merge F -+GLIBC_2.27 envz_remove F -+GLIBC_2.27 envz_strip F -+GLIBC_2.27 epoll_create F -+GLIBC_2.27 epoll_create1 F -+GLIBC_2.27 epoll_ctl F -+GLIBC_2.27 epoll_pwait F -+GLIBC_2.27 epoll_wait F -+GLIBC_2.27 erand48 F -+GLIBC_2.27 erand48_r F -+GLIBC_2.27 err F -+GLIBC_2.27 error F -+GLIBC_2.27 error_at_line F -+GLIBC_2.27 error_message_count D 0x4 -+GLIBC_2.27 error_one_per_line D 0x4 -+GLIBC_2.27 error_print_progname D 0x8 -+GLIBC_2.27 errx F -+GLIBC_2.27 ether_aton F -+GLIBC_2.27 ether_aton_r F -+GLIBC_2.27 ether_hostton F -+GLIBC_2.27 ether_line F -+GLIBC_2.27 ether_ntoa F -+GLIBC_2.27 ether_ntoa_r F -+GLIBC_2.27 ether_ntohost F -+GLIBC_2.27 euidaccess F -+GLIBC_2.27 eventfd F -+GLIBC_2.27 eventfd_read F -+GLIBC_2.27 eventfd_write F -+GLIBC_2.27 execl F -+GLIBC_2.27 execle F -+GLIBC_2.27 execlp F -+GLIBC_2.27 execv F -+GLIBC_2.27 execve F -+GLIBC_2.27 execvp F -+GLIBC_2.27 execvpe F -+GLIBC_2.27 exit F -+GLIBC_2.27 explicit_bzero F -+GLIBC_2.27 faccessat F -+GLIBC_2.27 fallocate F -+GLIBC_2.27 fallocate64 F -+GLIBC_2.27 fanotify_init F -+GLIBC_2.27 fanotify_mark F -+GLIBC_2.27 fattach F -+GLIBC_2.27 fchdir F -+GLIBC_2.27 fchflags F -+GLIBC_2.27 fchmod F -+GLIBC_2.27 fchmodat F -+GLIBC_2.27 fchown F -+GLIBC_2.27 fchownat F -+GLIBC_2.27 fclose F -+GLIBC_2.27 fcloseall F -+GLIBC_2.27 fcntl F -+GLIBC_2.27 fcvt F -+GLIBC_2.27 fcvt_r F -+GLIBC_2.27 fdatasync F -+GLIBC_2.27 fdetach F -+GLIBC_2.27 fdopen F -+GLIBC_2.27 fdopendir F -+GLIBC_2.27 feof F -+GLIBC_2.27 feof_unlocked F -+GLIBC_2.27 ferror F -+GLIBC_2.27 ferror_unlocked F -+GLIBC_2.27 fexecve F -+GLIBC_2.27 fflush F -+GLIBC_2.27 fflush_unlocked F -+GLIBC_2.27 ffs F -+GLIBC_2.27 ffsl F -+GLIBC_2.27 ffsll F -+GLIBC_2.27 fgetc F -+GLIBC_2.27 fgetc_unlocked F -+GLIBC_2.27 fgetgrent F -+GLIBC_2.27 fgetgrent_r F -+GLIBC_2.27 fgetpos F -+GLIBC_2.27 fgetpos64 F -+GLIBC_2.27 fgetpwent F -+GLIBC_2.27 fgetpwent_r F -+GLIBC_2.27 fgets F -+GLIBC_2.27 fgets_unlocked F -+GLIBC_2.27 fgetsgent F -+GLIBC_2.27 fgetsgent_r F -+GLIBC_2.27 fgetspent F -+GLIBC_2.27 fgetspent_r F -+GLIBC_2.27 fgetwc F -+GLIBC_2.27 fgetwc_unlocked F -+GLIBC_2.27 fgetws F -+GLIBC_2.27 fgetws_unlocked F -+GLIBC_2.27 fgetxattr F -+GLIBC_2.27 fileno F -+GLIBC_2.27 fileno_unlocked F -+GLIBC_2.27 finite F -+GLIBC_2.27 finitef F -+GLIBC_2.27 finitel F -+GLIBC_2.27 flistxattr F -+GLIBC_2.27 flock F -+GLIBC_2.27 flockfile F -+GLIBC_2.27 fmemopen F -+GLIBC_2.27 fmtmsg F -+GLIBC_2.27 fnmatch F -+GLIBC_2.27 fopen F -+GLIBC_2.27 fopen64 F -+GLIBC_2.27 fopencookie F -+GLIBC_2.27 fork F -+GLIBC_2.27 fpathconf F -+GLIBC_2.27 fprintf F -+GLIBC_2.27 fputc F -+GLIBC_2.27 fputc_unlocked F -+GLIBC_2.27 fputs F -+GLIBC_2.27 fputs_unlocked F -+GLIBC_2.27 fputwc F -+GLIBC_2.27 fputwc_unlocked F -+GLIBC_2.27 fputws F -+GLIBC_2.27 fputws_unlocked F -+GLIBC_2.27 fread F -+GLIBC_2.27 fread_unlocked F -+GLIBC_2.27 free F -+GLIBC_2.27 freeaddrinfo F -+GLIBC_2.27 freeifaddrs F -+GLIBC_2.27 freelocale F -+GLIBC_2.27 fremovexattr F -+GLIBC_2.27 freopen F -+GLIBC_2.27 freopen64 F -+GLIBC_2.27 frexp F -+GLIBC_2.27 frexpf F -+GLIBC_2.27 frexpl F -+GLIBC_2.27 fscanf F -+GLIBC_2.27 fseek F -+GLIBC_2.27 fseeko F -+GLIBC_2.27 fseeko64 F -+GLIBC_2.27 fsetpos F -+GLIBC_2.27 fsetpos64 F -+GLIBC_2.27 fsetxattr F -+GLIBC_2.27 fstatfs F -+GLIBC_2.27 fstatfs64 F -+GLIBC_2.27 fstatvfs F -+GLIBC_2.27 fstatvfs64 F -+GLIBC_2.27 fsync F -+GLIBC_2.27 ftell F -+GLIBC_2.27 ftello F -+GLIBC_2.27 ftello64 F -+GLIBC_2.27 ftime F -+GLIBC_2.27 ftok F -+GLIBC_2.27 ftruncate F -+GLIBC_2.27 ftruncate64 F -+GLIBC_2.27 ftrylockfile F -+GLIBC_2.27 fts64_children F -+GLIBC_2.27 fts64_close F -+GLIBC_2.27 fts64_open F -+GLIBC_2.27 fts64_read F -+GLIBC_2.27 fts64_set F -+GLIBC_2.27 fts_children F -+GLIBC_2.27 fts_close F -+GLIBC_2.27 fts_open F -+GLIBC_2.27 fts_read F -+GLIBC_2.27 fts_set F -+GLIBC_2.27 ftw F -+GLIBC_2.27 ftw64 F -+GLIBC_2.27 funlockfile F -+GLIBC_2.27 futimens F -+GLIBC_2.27 futimes F -+GLIBC_2.27 futimesat F -+GLIBC_2.27 fwide F -+GLIBC_2.27 fwprintf F -+GLIBC_2.27 fwrite F -+GLIBC_2.27 fwrite_unlocked F -+GLIBC_2.27 fwscanf F -+GLIBC_2.27 gai_strerror F -+GLIBC_2.27 gcvt F -+GLIBC_2.27 get_avphys_pages F -+GLIBC_2.27 get_current_dir_name F -+GLIBC_2.27 get_myaddress F -+GLIBC_2.27 get_nprocs F -+GLIBC_2.27 get_nprocs_conf F -+GLIBC_2.27 get_phys_pages F -+GLIBC_2.27 getaddrinfo F -+GLIBC_2.27 getaliasbyname F -+GLIBC_2.27 getaliasbyname_r F -+GLIBC_2.27 getaliasent F -+GLIBC_2.27 getaliasent_r F -+GLIBC_2.27 getauxval F -+GLIBC_2.27 getc F -+GLIBC_2.27 getc_unlocked F -+GLIBC_2.27 getchar F -+GLIBC_2.27 getchar_unlocked F -+GLIBC_2.27 getcontext F -+GLIBC_2.27 getcwd F -+GLIBC_2.27 getdate F -+GLIBC_2.27 getdate_err D 0x4 -+GLIBC_2.27 getdate_r F -+GLIBC_2.27 getdelim F -+GLIBC_2.27 getdirentries F -+GLIBC_2.27 getdirentries64 F -+GLIBC_2.27 getdomainname F -+GLIBC_2.27 getdtablesize F -+GLIBC_2.27 getegid F -+GLIBC_2.27 getentropy F -+GLIBC_2.27 getenv F -+GLIBC_2.27 geteuid F -+GLIBC_2.27 getfsent F -+GLIBC_2.27 getfsfile F -+GLIBC_2.27 getfsspec F -+GLIBC_2.27 getgid F -+GLIBC_2.27 getgrent F -+GLIBC_2.27 getgrent_r F -+GLIBC_2.27 getgrgid F -+GLIBC_2.27 getgrgid_r F -+GLIBC_2.27 getgrnam F -+GLIBC_2.27 getgrnam_r F -+GLIBC_2.27 getgrouplist F -+GLIBC_2.27 getgroups F -+GLIBC_2.27 gethostbyaddr F -+GLIBC_2.27 gethostbyaddr_r F -+GLIBC_2.27 gethostbyname F -+GLIBC_2.27 gethostbyname2 F -+GLIBC_2.27 gethostbyname2_r F -+GLIBC_2.27 gethostbyname_r F -+GLIBC_2.27 gethostent F -+GLIBC_2.27 gethostent_r F -+GLIBC_2.27 gethostid F -+GLIBC_2.27 gethostname F -+GLIBC_2.27 getifaddrs F -+GLIBC_2.27 getipv4sourcefilter F -+GLIBC_2.27 getitimer F -+GLIBC_2.27 getline F -+GLIBC_2.27 getloadavg F -+GLIBC_2.27 getlogin F -+GLIBC_2.27 getlogin_r F -+GLIBC_2.27 getmntent F -+GLIBC_2.27 getmntent_r F -+GLIBC_2.27 getmsg F -+GLIBC_2.27 getnameinfo F -+GLIBC_2.27 getnetbyaddr F -+GLIBC_2.27 getnetbyaddr_r F -+GLIBC_2.27 getnetbyname F -+GLIBC_2.27 getnetbyname_r F -+GLIBC_2.27 getnetent F -+GLIBC_2.27 getnetent_r F -+GLIBC_2.27 getnetgrent F -+GLIBC_2.27 getnetgrent_r F -+GLIBC_2.27 getnetname F -+GLIBC_2.27 getopt F -+GLIBC_2.27 getopt_long F -+GLIBC_2.27 getopt_long_only F -+GLIBC_2.27 getpagesize F -+GLIBC_2.27 getpass F -+GLIBC_2.27 getpeername F -+GLIBC_2.27 getpgid F -+GLIBC_2.27 getpgrp F -+GLIBC_2.27 getpid F -+GLIBC_2.27 getpmsg F -+GLIBC_2.27 getppid F -+GLIBC_2.27 getpriority F -+GLIBC_2.27 getprotobyname F -+GLIBC_2.27 getprotobyname_r F -+GLIBC_2.27 getprotobynumber F -+GLIBC_2.27 getprotobynumber_r F -+GLIBC_2.27 getprotoent F -+GLIBC_2.27 getprotoent_r F -+GLIBC_2.27 getpt F -+GLIBC_2.27 getpublickey F -+GLIBC_2.27 getpw F -+GLIBC_2.27 getpwent F -+GLIBC_2.27 getpwent_r F -+GLIBC_2.27 getpwnam F -+GLIBC_2.27 getpwnam_r F -+GLIBC_2.27 getpwuid F -+GLIBC_2.27 getpwuid_r F -+GLIBC_2.27 getrandom F -+GLIBC_2.27 getresgid F -+GLIBC_2.27 getresuid F -+GLIBC_2.27 getrlimit F -+GLIBC_2.27 getrlimit64 F -+GLIBC_2.27 getrpcbyname F -+GLIBC_2.27 getrpcbyname_r F -+GLIBC_2.27 getrpcbynumber F -+GLIBC_2.27 getrpcbynumber_r F -+GLIBC_2.27 getrpcent F -+GLIBC_2.27 getrpcent_r F -+GLIBC_2.27 getrpcport F -+GLIBC_2.27 getrusage F -+GLIBC_2.27 gets F -+GLIBC_2.27 getsecretkey F -+GLIBC_2.27 getservbyname F -+GLIBC_2.27 getservbyname_r F -+GLIBC_2.27 getservbyport F -+GLIBC_2.27 getservbyport_r F -+GLIBC_2.27 getservent F -+GLIBC_2.27 getservent_r F -+GLIBC_2.27 getsgent F -+GLIBC_2.27 getsgent_r F -+GLIBC_2.27 getsgnam F -+GLIBC_2.27 getsgnam_r F -+GLIBC_2.27 getsid F -+GLIBC_2.27 getsockname F -+GLIBC_2.27 getsockopt F -+GLIBC_2.27 getsourcefilter F -+GLIBC_2.27 getspent F -+GLIBC_2.27 getspent_r F -+GLIBC_2.27 getspnam F -+GLIBC_2.27 getspnam_r F -+GLIBC_2.27 getsubopt F -+GLIBC_2.27 gettext F -+GLIBC_2.27 gettimeofday F -+GLIBC_2.27 getttyent F -+GLIBC_2.27 getttynam F -+GLIBC_2.27 getuid F -+GLIBC_2.27 getusershell F -+GLIBC_2.27 getutent F -+GLIBC_2.27 getutent_r F -+GLIBC_2.27 getutid F -+GLIBC_2.27 getutid_r F -+GLIBC_2.27 getutline F -+GLIBC_2.27 getutline_r F -+GLIBC_2.27 getutmp F -+GLIBC_2.27 getutmpx F -+GLIBC_2.27 getutxent F -+GLIBC_2.27 getutxid F -+GLIBC_2.27 getutxline F -+GLIBC_2.27 getw F -+GLIBC_2.27 getwc F -+GLIBC_2.27 getwc_unlocked F -+GLIBC_2.27 getwchar F -+GLIBC_2.27 getwchar_unlocked F -+GLIBC_2.27 getwd F -+GLIBC_2.27 getxattr F -+GLIBC_2.27 glob F -+GLIBC_2.27 glob64 F -+GLIBC_2.27 glob_pattern_p F -+GLIBC_2.27 globfree F -+GLIBC_2.27 globfree64 F -+GLIBC_2.27 gmtime F -+GLIBC_2.27 gmtime_r F -+GLIBC_2.27 gnu_dev_major F -+GLIBC_2.27 gnu_dev_makedev F -+GLIBC_2.27 gnu_dev_minor F -+GLIBC_2.27 gnu_get_libc_release F -+GLIBC_2.27 gnu_get_libc_version F -+GLIBC_2.27 grantpt F -+GLIBC_2.27 group_member F -+GLIBC_2.27 gsignal F -+GLIBC_2.27 gtty F -+GLIBC_2.27 h_errlist D 0x28 -+GLIBC_2.27 h_nerr D 0x4 -+GLIBC_2.27 hasmntopt F -+GLIBC_2.27 hcreate F -+GLIBC_2.27 hcreate_r F -+GLIBC_2.27 hdestroy F -+GLIBC_2.27 hdestroy_r F -+GLIBC_2.27 herror F -+GLIBC_2.27 host2netname F -+GLIBC_2.27 hsearch F -+GLIBC_2.27 hsearch_r F -+GLIBC_2.27 hstrerror F -+GLIBC_2.27 htonl F -+GLIBC_2.27 htons F -+GLIBC_2.27 iconv F -+GLIBC_2.27 iconv_close F -+GLIBC_2.27 iconv_open F -+GLIBC_2.27 if_freenameindex F -+GLIBC_2.27 if_indextoname F -+GLIBC_2.27 if_nameindex F -+GLIBC_2.27 if_nametoindex F -+GLIBC_2.27 imaxabs F -+GLIBC_2.27 imaxdiv F -+GLIBC_2.27 in6addr_any D 0x10 -+GLIBC_2.27 in6addr_loopback D 0x10 -+GLIBC_2.27 index F -+GLIBC_2.27 inet6_opt_append F -+GLIBC_2.27 inet6_opt_find F -+GLIBC_2.27 inet6_opt_finish F -+GLIBC_2.27 inet6_opt_get_val F -+GLIBC_2.27 inet6_opt_init F -+GLIBC_2.27 inet6_opt_next F -+GLIBC_2.27 inet6_opt_set_val F -+GLIBC_2.27 inet6_option_alloc F -+GLIBC_2.27 inet6_option_append F -+GLIBC_2.27 inet6_option_find F -+GLIBC_2.27 inet6_option_init F -+GLIBC_2.27 inet6_option_next F -+GLIBC_2.27 inet6_option_space F -+GLIBC_2.27 inet6_rth_add F -+GLIBC_2.27 inet6_rth_getaddr F -+GLIBC_2.27 inet6_rth_init F -+GLIBC_2.27 inet6_rth_reverse F -+GLIBC_2.27 inet6_rth_segments F -+GLIBC_2.27 inet6_rth_space F -+GLIBC_2.27 inet_addr F -+GLIBC_2.27 inet_aton F -+GLIBC_2.27 inet_lnaof F -+GLIBC_2.27 inet_makeaddr F -+GLIBC_2.27 inet_netof F -+GLIBC_2.27 inet_network F -+GLIBC_2.27 inet_nsap_addr F -+GLIBC_2.27 inet_nsap_ntoa F -+GLIBC_2.27 inet_ntoa F -+GLIBC_2.27 inet_ntop F -+GLIBC_2.27 inet_pton F -+GLIBC_2.27 init_module F -+GLIBC_2.27 initgroups F -+GLIBC_2.27 initstate F -+GLIBC_2.27 initstate_r F -+GLIBC_2.27 innetgr F -+GLIBC_2.27 inotify_add_watch F -+GLIBC_2.27 inotify_init F -+GLIBC_2.27 inotify_init1 F -+GLIBC_2.27 inotify_rm_watch F -+GLIBC_2.27 insque F -+GLIBC_2.27 ioctl F -+GLIBC_2.27 iruserok F -+GLIBC_2.27 iruserok_af F -+GLIBC_2.27 isalnum F -+GLIBC_2.27 isalnum_l F -+GLIBC_2.27 isalpha F -+GLIBC_2.27 isalpha_l F -+GLIBC_2.27 isascii F -+GLIBC_2.27 isastream F -+GLIBC_2.27 isatty F -+GLIBC_2.27 isblank F -+GLIBC_2.27 isblank_l F -+GLIBC_2.27 iscntrl F -+GLIBC_2.27 iscntrl_l F -+GLIBC_2.27 isctype F -+GLIBC_2.27 isdigit F -+GLIBC_2.27 isdigit_l F -+GLIBC_2.27 isfdtype F -+GLIBC_2.27 isgraph F -+GLIBC_2.27 isgraph_l F -+GLIBC_2.27 isinf F -+GLIBC_2.27 isinff F -+GLIBC_2.27 isinfl F -+GLIBC_2.27 islower F -+GLIBC_2.27 islower_l F -+GLIBC_2.27 isnan F -+GLIBC_2.27 isnanf F -+GLIBC_2.27 isnanl F -+GLIBC_2.27 isprint F -+GLIBC_2.27 isprint_l F -+GLIBC_2.27 ispunct F -+GLIBC_2.27 ispunct_l F -+GLIBC_2.27 isspace F -+GLIBC_2.27 isspace_l F -+GLIBC_2.27 isupper F -+GLIBC_2.27 isupper_l F -+GLIBC_2.27 iswalnum F -+GLIBC_2.27 iswalnum_l F -+GLIBC_2.27 iswalpha F -+GLIBC_2.27 iswalpha_l F -+GLIBC_2.27 iswblank F -+GLIBC_2.27 iswblank_l F -+GLIBC_2.27 iswcntrl F -+GLIBC_2.27 iswcntrl_l F -+GLIBC_2.27 iswctype F -+GLIBC_2.27 iswctype_l F -+GLIBC_2.27 iswdigit F -+GLIBC_2.27 iswdigit_l F -+GLIBC_2.27 iswgraph F -+GLIBC_2.27 iswgraph_l F -+GLIBC_2.27 iswlower F -+GLIBC_2.27 iswlower_l F -+GLIBC_2.27 iswprint F -+GLIBC_2.27 iswprint_l F -+GLIBC_2.27 iswpunct F -+GLIBC_2.27 iswpunct_l F -+GLIBC_2.27 iswspace F -+GLIBC_2.27 iswspace_l F -+GLIBC_2.27 iswupper F -+GLIBC_2.27 iswupper_l F -+GLIBC_2.27 iswxdigit F -+GLIBC_2.27 iswxdigit_l F -+GLIBC_2.27 isxdigit F -+GLIBC_2.27 isxdigit_l F -+GLIBC_2.27 jrand48 F -+GLIBC_2.27 jrand48_r F -+GLIBC_2.27 key_decryptsession F -+GLIBC_2.27 key_decryptsession_pk F -+GLIBC_2.27 key_encryptsession F -+GLIBC_2.27 key_encryptsession_pk F -+GLIBC_2.27 key_gendes F -+GLIBC_2.27 key_get_conv F -+GLIBC_2.27 key_secretkey_is_set F -+GLIBC_2.27 key_setnet F -+GLIBC_2.27 key_setsecret F -+GLIBC_2.27 kill F -+GLIBC_2.27 killpg F -+GLIBC_2.27 klogctl F -+GLIBC_2.27 l64a F -+GLIBC_2.27 labs F -+GLIBC_2.27 lchmod F -+GLIBC_2.27 lchown F -+GLIBC_2.27 lckpwdf F -+GLIBC_2.27 lcong48 F -+GLIBC_2.27 lcong48_r F -+GLIBC_2.27 ldexp F -+GLIBC_2.27 ldexpf F -+GLIBC_2.27 ldexpl F -+GLIBC_2.27 ldiv F -+GLIBC_2.27 lfind F -+GLIBC_2.27 lgetxattr F -+GLIBC_2.27 link F -+GLIBC_2.27 linkat F -+GLIBC_2.27 listen F -+GLIBC_2.27 listxattr F -+GLIBC_2.27 llabs F -+GLIBC_2.27 lldiv F -+GLIBC_2.27 llistxattr F -+GLIBC_2.27 llseek F -+GLIBC_2.27 localeconv F -+GLIBC_2.27 localtime F -+GLIBC_2.27 localtime_r F -+GLIBC_2.27 lockf F -+GLIBC_2.27 lockf64 F -+GLIBC_2.27 longjmp F -+GLIBC_2.27 lrand48 F -+GLIBC_2.27 lrand48_r F -+GLIBC_2.27 lremovexattr F -+GLIBC_2.27 lsearch F -+GLIBC_2.27 lseek F -+GLIBC_2.27 lseek64 F -+GLIBC_2.27 lsetxattr F -+GLIBC_2.27 lutimes F -+GLIBC_2.27 madvise F -+GLIBC_2.27 makecontext F -+GLIBC_2.27 mallinfo F -+GLIBC_2.27 malloc F -+GLIBC_2.27 malloc_info F -+GLIBC_2.27 malloc_stats F -+GLIBC_2.27 malloc_trim F -+GLIBC_2.27 malloc_usable_size F -+GLIBC_2.27 mallopt F -+GLIBC_2.27 mallwatch D 0x8 -+GLIBC_2.27 mblen F -+GLIBC_2.27 mbrlen F -+GLIBC_2.27 mbrtoc16 F -+GLIBC_2.27 mbrtoc32 F -+GLIBC_2.27 mbrtowc F -+GLIBC_2.27 mbsinit F -+GLIBC_2.27 mbsnrtowcs F -+GLIBC_2.27 mbsrtowcs F -+GLIBC_2.27 mbstowcs F -+GLIBC_2.27 mbtowc F -+GLIBC_2.27 mcheck F -+GLIBC_2.27 mcheck_check_all F -+GLIBC_2.27 mcheck_pedantic F -+GLIBC_2.27 memalign F -+GLIBC_2.27 memccpy F -+GLIBC_2.27 memchr F -+GLIBC_2.27 memcmp F -+GLIBC_2.27 memcpy F -+GLIBC_2.27 memfd_create F -+GLIBC_2.27 memfrob F -+GLIBC_2.27 memmem F -+GLIBC_2.27 memmove F -+GLIBC_2.27 mempcpy F -+GLIBC_2.27 memrchr F -+GLIBC_2.27 memset F -+GLIBC_2.27 mincore F -+GLIBC_2.27 mkdir F -+GLIBC_2.27 mkdirat F -+GLIBC_2.27 mkdtemp F -+GLIBC_2.27 mkfifo F -+GLIBC_2.27 mkfifoat F -+GLIBC_2.27 mkostemp F -+GLIBC_2.27 mkostemp64 F -+GLIBC_2.27 mkostemps F -+GLIBC_2.27 mkostemps64 F -+GLIBC_2.27 mkstemp F -+GLIBC_2.27 mkstemp64 F -+GLIBC_2.27 mkstemps F -+GLIBC_2.27 mkstemps64 F -+GLIBC_2.27 mktemp F -+GLIBC_2.27 mktime F -+GLIBC_2.27 mlock F -+GLIBC_2.27 mlock2 F -+GLIBC_2.27 mlockall F -+GLIBC_2.27 mmap F -+GLIBC_2.27 mmap64 F -+GLIBC_2.27 modf F -+GLIBC_2.27 modff F -+GLIBC_2.27 modfl F -+GLIBC_2.27 moncontrol F -+GLIBC_2.27 monstartup F -+GLIBC_2.27 mount F -+GLIBC_2.27 mprobe F -+GLIBC_2.27 mprotect F -+GLIBC_2.27 mrand48 F -+GLIBC_2.27 mrand48_r F -+GLIBC_2.27 mremap F -+GLIBC_2.27 msgctl F -+GLIBC_2.27 msgget F -+GLIBC_2.27 msgrcv F -+GLIBC_2.27 msgsnd F -+GLIBC_2.27 msync F -+GLIBC_2.27 mtrace F -+GLIBC_2.27 munlock F -+GLIBC_2.27 munlockall F -+GLIBC_2.27 munmap F -+GLIBC_2.27 muntrace F -+GLIBC_2.27 name_to_handle_at F -+GLIBC_2.27 nanosleep F -+GLIBC_2.27 netname2host F -+GLIBC_2.27 netname2user F -+GLIBC_2.27 newlocale F -+GLIBC_2.27 nfsservctl F -+GLIBC_2.27 nftw F -+GLIBC_2.27 nftw64 F -+GLIBC_2.27 ngettext F -+GLIBC_2.27 nice F -+GLIBC_2.27 nl_langinfo F -+GLIBC_2.27 nl_langinfo_l F -+GLIBC_2.27 nrand48 F -+GLIBC_2.27 nrand48_r F -+GLIBC_2.27 ntohl F -+GLIBC_2.27 ntohs F -+GLIBC_2.27 ntp_adjtime F -+GLIBC_2.27 ntp_gettime F -+GLIBC_2.27 ntp_gettimex F -+GLIBC_2.27 obstack_alloc_failed_handler D 0x8 -+GLIBC_2.27 obstack_exit_failure D 0x4 -+GLIBC_2.27 obstack_free F -+GLIBC_2.27 obstack_printf F -+GLIBC_2.27 obstack_vprintf F -+GLIBC_2.27 on_exit F -+GLIBC_2.27 open F -+GLIBC_2.27 open64 F -+GLIBC_2.27 open_by_handle_at F -+GLIBC_2.27 open_memstream F -+GLIBC_2.27 open_wmemstream F -+GLIBC_2.27 openat F -+GLIBC_2.27 openat64 F -+GLIBC_2.27 opendir F -+GLIBC_2.27 openlog F -+GLIBC_2.27 optarg D 0x8 -+GLIBC_2.27 opterr D 0x4 -+GLIBC_2.27 optind D 0x4 -+GLIBC_2.27 optopt D 0x4 -+GLIBC_2.27 parse_printf_format F -+GLIBC_2.27 passwd2des F -+GLIBC_2.27 pathconf F -+GLIBC_2.27 pause F -+GLIBC_2.27 pclose F -+GLIBC_2.27 perror F -+GLIBC_2.27 personality F -+GLIBC_2.27 pipe F -+GLIBC_2.27 pipe2 F -+GLIBC_2.27 pivot_root F -+GLIBC_2.27 pkey_alloc F -+GLIBC_2.27 pkey_free F -+GLIBC_2.27 pkey_get F -+GLIBC_2.27 pkey_mprotect F -+GLIBC_2.27 pkey_set F -+GLIBC_2.27 pmap_getmaps F -+GLIBC_2.27 pmap_getport F -+GLIBC_2.27 pmap_rmtcall F -+GLIBC_2.27 pmap_set F -+GLIBC_2.27 pmap_unset F -+GLIBC_2.27 poll F -+GLIBC_2.27 popen F -+GLIBC_2.27 posix_fadvise F -+GLIBC_2.27 posix_fadvise64 F -+GLIBC_2.27 posix_fallocate F -+GLIBC_2.27 posix_fallocate64 F -+GLIBC_2.27 posix_madvise F -+GLIBC_2.27 posix_memalign F -+GLIBC_2.27 posix_openpt F -+GLIBC_2.27 posix_spawn F -+GLIBC_2.27 posix_spawn_file_actions_addclose F -+GLIBC_2.27 posix_spawn_file_actions_adddup2 F -+GLIBC_2.27 posix_spawn_file_actions_addopen F -+GLIBC_2.27 posix_spawn_file_actions_destroy F -+GLIBC_2.27 posix_spawn_file_actions_init F -+GLIBC_2.27 posix_spawnattr_destroy F -+GLIBC_2.27 posix_spawnattr_getflags F -+GLIBC_2.27 posix_spawnattr_getpgroup F -+GLIBC_2.27 posix_spawnattr_getschedparam F -+GLIBC_2.27 posix_spawnattr_getschedpolicy F -+GLIBC_2.27 posix_spawnattr_getsigdefault F -+GLIBC_2.27 posix_spawnattr_getsigmask F -+GLIBC_2.27 posix_spawnattr_init F -+GLIBC_2.27 posix_spawnattr_setflags F -+GLIBC_2.27 posix_spawnattr_setpgroup F -+GLIBC_2.27 posix_spawnattr_setschedparam F -+GLIBC_2.27 posix_spawnattr_setschedpolicy F -+GLIBC_2.27 posix_spawnattr_setsigdefault F -+GLIBC_2.27 posix_spawnattr_setsigmask F -+GLIBC_2.27 posix_spawnp F -+GLIBC_2.27 ppoll F -+GLIBC_2.27 prctl F -+GLIBC_2.27 pread F -+GLIBC_2.27 pread64 F -+GLIBC_2.27 preadv F -+GLIBC_2.27 preadv2 F -+GLIBC_2.27 preadv64 F -+GLIBC_2.27 preadv64v2 F -+GLIBC_2.27 printf F -+GLIBC_2.27 printf_size F -+GLIBC_2.27 printf_size_info F -+GLIBC_2.27 prlimit F -+GLIBC_2.27 prlimit64 F -+GLIBC_2.27 process_vm_readv F -+GLIBC_2.27 process_vm_writev F -+GLIBC_2.27 profil F -+GLIBC_2.27 program_invocation_name D 0x8 -+GLIBC_2.27 program_invocation_short_name D 0x8 -+GLIBC_2.27 pselect F -+GLIBC_2.27 psiginfo F -+GLIBC_2.27 psignal F -+GLIBC_2.27 pthread_attr_destroy F -+GLIBC_2.27 pthread_attr_getdetachstate F -+GLIBC_2.27 pthread_attr_getinheritsched F -+GLIBC_2.27 pthread_attr_getschedparam F -+GLIBC_2.27 pthread_attr_getschedpolicy F -+GLIBC_2.27 pthread_attr_getscope F -+GLIBC_2.27 pthread_attr_init F -+GLIBC_2.27 pthread_attr_setdetachstate F -+GLIBC_2.27 pthread_attr_setinheritsched F -+GLIBC_2.27 pthread_attr_setschedparam F -+GLIBC_2.27 pthread_attr_setschedpolicy F -+GLIBC_2.27 pthread_attr_setscope F -+GLIBC_2.27 pthread_cond_broadcast F -+GLIBC_2.27 pthread_cond_destroy F -+GLIBC_2.27 pthread_cond_init F -+GLIBC_2.27 pthread_cond_signal F -+GLIBC_2.27 pthread_cond_timedwait F -+GLIBC_2.27 pthread_cond_wait F -+GLIBC_2.27 pthread_condattr_destroy F -+GLIBC_2.27 pthread_condattr_init F -+GLIBC_2.27 pthread_equal F -+GLIBC_2.27 pthread_exit F -+GLIBC_2.27 pthread_getschedparam F -+GLIBC_2.27 pthread_mutex_destroy F -+GLIBC_2.27 pthread_mutex_init F -+GLIBC_2.27 pthread_mutex_lock F -+GLIBC_2.27 pthread_mutex_unlock F -+GLIBC_2.27 pthread_self F -+GLIBC_2.27 pthread_setcancelstate F -+GLIBC_2.27 pthread_setcanceltype F -+GLIBC_2.27 pthread_setschedparam F -+GLIBC_2.27 ptrace F -+GLIBC_2.27 ptsname F -+GLIBC_2.27 ptsname_r F -+GLIBC_2.27 putc F -+GLIBC_2.27 putc_unlocked F -+GLIBC_2.27 putchar F -+GLIBC_2.27 putchar_unlocked F -+GLIBC_2.27 putenv F -+GLIBC_2.27 putgrent F -+GLIBC_2.27 putmsg F -+GLIBC_2.27 putpmsg F -+GLIBC_2.27 putpwent F -+GLIBC_2.27 puts F -+GLIBC_2.27 putsgent F -+GLIBC_2.27 putspent F -+GLIBC_2.27 pututline F -+GLIBC_2.27 pututxline F -+GLIBC_2.27 putw F -+GLIBC_2.27 putwc F -+GLIBC_2.27 putwc_unlocked F -+GLIBC_2.27 putwchar F -+GLIBC_2.27 putwchar_unlocked F -+GLIBC_2.27 pvalloc F -+GLIBC_2.27 pwrite F -+GLIBC_2.27 pwrite64 F -+GLIBC_2.27 pwritev F -+GLIBC_2.27 pwritev2 F -+GLIBC_2.27 pwritev64 F -+GLIBC_2.27 pwritev64v2 F -+GLIBC_2.27 qecvt F -+GLIBC_2.27 qecvt_r F -+GLIBC_2.27 qfcvt F -+GLIBC_2.27 qfcvt_r F -+GLIBC_2.27 qgcvt F -+GLIBC_2.27 qsort F -+GLIBC_2.27 qsort_r F -+GLIBC_2.27 quick_exit F -+GLIBC_2.27 quotactl F -+GLIBC_2.27 raise F -+GLIBC_2.27 rand F -+GLIBC_2.27 rand_r F -+GLIBC_2.27 random F -+GLIBC_2.27 random_r F -+GLIBC_2.27 rawmemchr F -+GLIBC_2.27 rcmd F -+GLIBC_2.27 rcmd_af F -+GLIBC_2.27 re_comp F -+GLIBC_2.27 re_compile_fastmap F -+GLIBC_2.27 re_compile_pattern F -+GLIBC_2.27 re_exec F -+GLIBC_2.27 re_match F -+GLIBC_2.27 re_match_2 F -+GLIBC_2.27 re_search F -+GLIBC_2.27 re_search_2 F -+GLIBC_2.27 re_set_registers F -+GLIBC_2.27 re_set_syntax F -+GLIBC_2.27 re_syntax_options D 0x8 -+GLIBC_2.27 read F -+GLIBC_2.27 readahead F -+GLIBC_2.27 readdir F -+GLIBC_2.27 readdir64 F -+GLIBC_2.27 readdir64_r F -+GLIBC_2.27 readdir_r F -+GLIBC_2.27 readlink F -+GLIBC_2.27 readlinkat F -+GLIBC_2.27 readv F -+GLIBC_2.27 realloc F -+GLIBC_2.27 reallocarray F -+GLIBC_2.27 realpath F -+GLIBC_2.27 reboot F -+GLIBC_2.27 recv F -+GLIBC_2.27 recvfrom F -+GLIBC_2.27 recvmmsg F -+GLIBC_2.27 recvmsg F -+GLIBC_2.27 regcomp F -+GLIBC_2.27 regerror F -+GLIBC_2.27 regexec F -+GLIBC_2.27 regfree F -+GLIBC_2.27 register_printf_function F -+GLIBC_2.27 register_printf_modifier F -+GLIBC_2.27 register_printf_specifier F -+GLIBC_2.27 register_printf_type F -+GLIBC_2.27 registerrpc F -+GLIBC_2.27 remap_file_pages F -+GLIBC_2.27 remove F -+GLIBC_2.27 removexattr F -+GLIBC_2.27 remque F -+GLIBC_2.27 rename F -+GLIBC_2.27 renameat F -+GLIBC_2.27 revoke F -+GLIBC_2.27 rewind F -+GLIBC_2.27 rewinddir F -+GLIBC_2.27 rexec F -+GLIBC_2.27 rexec_af F -+GLIBC_2.27 rexecoptions D 0x4 -+GLIBC_2.27 rindex F -+GLIBC_2.27 rmdir F -+GLIBC_2.27 rpc_createerr D 0x20 -+GLIBC_2.27 rpmatch F -+GLIBC_2.27 rresvport F -+GLIBC_2.27 rresvport_af F -+GLIBC_2.27 rtime F -+GLIBC_2.27 ruserok F -+GLIBC_2.27 ruserok_af F -+GLIBC_2.27 ruserpass F -+GLIBC_2.27 sbrk F -+GLIBC_2.27 scalbn F -+GLIBC_2.27 scalbnf F -+GLIBC_2.27 scalbnl F -+GLIBC_2.27 scandir F -+GLIBC_2.27 scandir64 F -+GLIBC_2.27 scandirat F -+GLIBC_2.27 scandirat64 F -+GLIBC_2.27 scanf F -+GLIBC_2.27 sched_get_priority_max F -+GLIBC_2.27 sched_get_priority_min F -+GLIBC_2.27 sched_getaffinity F -+GLIBC_2.27 sched_getcpu F -+GLIBC_2.27 sched_getparam F -+GLIBC_2.27 sched_getscheduler F -+GLIBC_2.27 sched_rr_get_interval F -+GLIBC_2.27 sched_setaffinity F -+GLIBC_2.27 sched_setparam F -+GLIBC_2.27 sched_setscheduler F -+GLIBC_2.27 sched_yield F -+GLIBC_2.27 secure_getenv F -+GLIBC_2.27 seed48 F -+GLIBC_2.27 seed48_r F -+GLIBC_2.27 seekdir F -+GLIBC_2.27 select F -+GLIBC_2.27 semctl F -+GLIBC_2.27 semget F -+GLIBC_2.27 semop F -+GLIBC_2.27 semtimedop F -+GLIBC_2.27 send F -+GLIBC_2.27 sendfile F -+GLIBC_2.27 sendfile64 F -+GLIBC_2.27 sendmmsg F -+GLIBC_2.27 sendmsg F -+GLIBC_2.27 sendto F -+GLIBC_2.27 setaliasent F -+GLIBC_2.27 setbuf F -+GLIBC_2.27 setbuffer F -+GLIBC_2.27 setcontext F -+GLIBC_2.27 setdomainname F -+GLIBC_2.27 setegid F -+GLIBC_2.27 setenv F -+GLIBC_2.27 seteuid F -+GLIBC_2.27 setfsent F -+GLIBC_2.27 setfsgid F -+GLIBC_2.27 setfsuid F -+GLIBC_2.27 setgid F -+GLIBC_2.27 setgrent F -+GLIBC_2.27 setgroups F -+GLIBC_2.27 sethostent F -+GLIBC_2.27 sethostid F -+GLIBC_2.27 sethostname F -+GLIBC_2.27 setipv4sourcefilter F -+GLIBC_2.27 setitimer F -+GLIBC_2.27 setjmp F -+GLIBC_2.27 setlinebuf F -+GLIBC_2.27 setlocale F -+GLIBC_2.27 setlogin F -+GLIBC_2.27 setlogmask F -+GLIBC_2.27 setmntent F -+GLIBC_2.27 setnetent F -+GLIBC_2.27 setnetgrent F -+GLIBC_2.27 setns F -+GLIBC_2.27 setpgid F -+GLIBC_2.27 setpgrp F -+GLIBC_2.27 setpriority F -+GLIBC_2.27 setprotoent F -+GLIBC_2.27 setpwent F -+GLIBC_2.27 setregid F -+GLIBC_2.27 setresgid F -+GLIBC_2.27 setresuid F -+GLIBC_2.27 setreuid F -+GLIBC_2.27 setrlimit F -+GLIBC_2.27 setrlimit64 F -+GLIBC_2.27 setrpcent F -+GLIBC_2.27 setservent F -+GLIBC_2.27 setsgent F -+GLIBC_2.27 setsid F -+GLIBC_2.27 setsockopt F -+GLIBC_2.27 setsourcefilter F -+GLIBC_2.27 setspent F -+GLIBC_2.27 setstate F -+GLIBC_2.27 setstate_r F -+GLIBC_2.27 settimeofday F -+GLIBC_2.27 setttyent F -+GLIBC_2.27 setuid F -+GLIBC_2.27 setusershell F -+GLIBC_2.27 setutent F -+GLIBC_2.27 setutxent F -+GLIBC_2.27 setvbuf F -+GLIBC_2.27 setxattr F -+GLIBC_2.27 sgetsgent F -+GLIBC_2.27 sgetsgent_r F -+GLIBC_2.27 sgetspent F -+GLIBC_2.27 sgetspent_r F -+GLIBC_2.27 shmat F -+GLIBC_2.27 shmctl F -+GLIBC_2.27 shmdt F -+GLIBC_2.27 shmget F -+GLIBC_2.27 shutdown F -+GLIBC_2.27 sigaction F -+GLIBC_2.27 sigaddset F -+GLIBC_2.27 sigaltstack F -+GLIBC_2.27 sigandset F -+GLIBC_2.27 sigblock F -+GLIBC_2.27 sigdelset F -+GLIBC_2.27 sigemptyset F -+GLIBC_2.27 sigfillset F -+GLIBC_2.27 siggetmask F -+GLIBC_2.27 sighold F -+GLIBC_2.27 sigignore F -+GLIBC_2.27 siginterrupt F -+GLIBC_2.27 sigisemptyset F -+GLIBC_2.27 sigismember F -+GLIBC_2.27 siglongjmp F -+GLIBC_2.27 signal F -+GLIBC_2.27 signalfd F -+GLIBC_2.27 sigorset F -+GLIBC_2.27 sigpause F -+GLIBC_2.27 sigpending F -+GLIBC_2.27 sigprocmask F -+GLIBC_2.27 sigqueue F -+GLIBC_2.27 sigrelse F -+GLIBC_2.27 sigreturn F -+GLIBC_2.27 sigset F -+GLIBC_2.27 sigsetmask F -+GLIBC_2.27 sigstack F -+GLIBC_2.27 sigsuspend F -+GLIBC_2.27 sigtimedwait F -+GLIBC_2.27 sigwait F -+GLIBC_2.27 sigwaitinfo F -+GLIBC_2.27 sleep F -+GLIBC_2.27 snprintf F -+GLIBC_2.27 sockatmark F -+GLIBC_2.27 socket F -+GLIBC_2.27 socketpair F -+GLIBC_2.27 splice F -+GLIBC_2.27 sprintf F -+GLIBC_2.27 sprofil F -+GLIBC_2.27 srand F -+GLIBC_2.27 srand48 F -+GLIBC_2.27 srand48_r F -+GLIBC_2.27 srandom F -+GLIBC_2.27 srandom_r F -+GLIBC_2.27 sscanf F -+GLIBC_2.27 ssignal F -+GLIBC_2.27 sstk F -+GLIBC_2.27 statfs F -+GLIBC_2.27 statfs64 F -+GLIBC_2.27 statvfs F -+GLIBC_2.27 statvfs64 F -+GLIBC_2.27 stderr D 0x8 -+GLIBC_2.27 stdin D 0x8 -+GLIBC_2.27 stdout D 0x8 -+GLIBC_2.27 stime F -+GLIBC_2.27 stpcpy F -+GLIBC_2.27 stpncpy F -+GLIBC_2.27 strcasecmp F -+GLIBC_2.27 strcasecmp_l F -+GLIBC_2.27 strcasestr F -+GLIBC_2.27 strcat F -+GLIBC_2.27 strchr F -+GLIBC_2.27 strchrnul F -+GLIBC_2.27 strcmp F -+GLIBC_2.27 strcoll F -+GLIBC_2.27 strcoll_l F -+GLIBC_2.27 strcpy F -+GLIBC_2.27 strcspn F -+GLIBC_2.27 strdup F -+GLIBC_2.27 strerror F -+GLIBC_2.27 strerror_l F -+GLIBC_2.27 strerror_r F -+GLIBC_2.27 strfmon F -+GLIBC_2.27 strfmon_l F -+GLIBC_2.27 strfromd F -+GLIBC_2.27 strfromf F -+GLIBC_2.27 strfromf128 F -+GLIBC_2.27 strfromf32 F -+GLIBC_2.27 strfromf32x F -+GLIBC_2.27 strfromf64 F -+GLIBC_2.27 strfromf64x F -+GLIBC_2.27 strfroml F -+GLIBC_2.27 strfry F -+GLIBC_2.27 strftime F -+GLIBC_2.27 strftime_l F -+GLIBC_2.27 strlen F -+GLIBC_2.27 strncasecmp F -+GLIBC_2.27 strncasecmp_l F -+GLIBC_2.27 strncat F -+GLIBC_2.27 strncmp F -+GLIBC_2.27 strncpy F -+GLIBC_2.27 strndup F -+GLIBC_2.27 strnlen F -+GLIBC_2.27 strpbrk F -+GLIBC_2.27 strptime F -+GLIBC_2.27 strptime_l F -+GLIBC_2.27 strrchr F -+GLIBC_2.27 strsep F -+GLIBC_2.27 strsignal F -+GLIBC_2.27 strspn F -+GLIBC_2.27 strstr F -+GLIBC_2.27 strtod F -+GLIBC_2.27 strtod_l F -+GLIBC_2.27 strtof F -+GLIBC_2.27 strtof128 F -+GLIBC_2.27 strtof128_l F -+GLIBC_2.27 strtof32 F -+GLIBC_2.27 strtof32_l F -+GLIBC_2.27 strtof32x F -+GLIBC_2.27 strtof32x_l F -+GLIBC_2.27 strtof64 F -+GLIBC_2.27 strtof64_l F -+GLIBC_2.27 strtof64x F -+GLIBC_2.27 strtof64x_l F -+GLIBC_2.27 strtof_l F -+GLIBC_2.27 strtoimax F -+GLIBC_2.27 strtok F -+GLIBC_2.27 strtok_r F -+GLIBC_2.27 strtol F -+GLIBC_2.27 strtol_l F -+GLIBC_2.27 strtold F -+GLIBC_2.27 strtold_l F -+GLIBC_2.27 strtoll F -+GLIBC_2.27 strtoll_l F -+GLIBC_2.27 strtoq F -+GLIBC_2.27 strtoul F -+GLIBC_2.27 strtoul_l F -+GLIBC_2.27 strtoull F -+GLIBC_2.27 strtoull_l F -+GLIBC_2.27 strtoumax F -+GLIBC_2.27 strtouq F -+GLIBC_2.27 strverscmp F -+GLIBC_2.27 strxfrm F -+GLIBC_2.27 strxfrm_l F -+GLIBC_2.27 stty F -+GLIBC_2.27 svc_exit F -+GLIBC_2.27 svc_fdset D 0x80 -+GLIBC_2.27 svc_getreq F -+GLIBC_2.27 svc_getreq_common F -+GLIBC_2.27 svc_getreq_poll F -+GLIBC_2.27 svc_getreqset F -+GLIBC_2.27 svc_max_pollfd D 0x4 -+GLIBC_2.27 svc_pollfd D 0x8 -+GLIBC_2.27 svc_register F -+GLIBC_2.27 svc_run F -+GLIBC_2.27 svc_sendreply F -+GLIBC_2.27 svc_unregister F -+GLIBC_2.27 svcauthdes_stats D 0x18 -+GLIBC_2.27 svcerr_auth F -+GLIBC_2.27 svcerr_decode F -+GLIBC_2.27 svcerr_noproc F -+GLIBC_2.27 svcerr_noprog F -+GLIBC_2.27 svcerr_progvers F -+GLIBC_2.27 svcerr_systemerr F -+GLIBC_2.27 svcerr_weakauth F -+GLIBC_2.27 svcfd_create F -+GLIBC_2.27 svcraw_create F -+GLIBC_2.27 svctcp_create F -+GLIBC_2.27 svcudp_bufcreate F -+GLIBC_2.27 svcudp_create F -+GLIBC_2.27 svcudp_enablecache F -+GLIBC_2.27 svcunix_create F -+GLIBC_2.27 svcunixfd_create F -+GLIBC_2.27 swab F -+GLIBC_2.27 swapcontext F -+GLIBC_2.27 swapoff F -+GLIBC_2.27 swapon F -+GLIBC_2.27 swprintf F -+GLIBC_2.27 swscanf F -+GLIBC_2.27 symlink F -+GLIBC_2.27 symlinkat F -+GLIBC_2.27 sync F -+GLIBC_2.27 sync_file_range F -+GLIBC_2.27 syncfs F -+GLIBC_2.27 sys_errlist D 0x2370 -+GLIBC_2.27 sys_nerr D 0x4 -+GLIBC_2.27 sys_sigabbrev D 0x400 -+GLIBC_2.27 sys_siglist D 0x400 -+GLIBC_2.27 syscall F -+GLIBC_2.27 sysconf F -+GLIBC_2.27 sysctl F -+GLIBC_2.27 sysinfo F -+GLIBC_2.27 syslog F -+GLIBC_2.27 system F -+GLIBC_2.27 sysv_signal F -+GLIBC_2.27 tcdrain F -+GLIBC_2.27 tcflow F -+GLIBC_2.27 tcflush F -+GLIBC_2.27 tcgetattr F -+GLIBC_2.27 tcgetpgrp F -+GLIBC_2.27 tcgetsid F -+GLIBC_2.27 tcsendbreak F -+GLIBC_2.27 tcsetattr F -+GLIBC_2.27 tcsetpgrp F -+GLIBC_2.27 tdelete F -+GLIBC_2.27 tdestroy F -+GLIBC_2.27 tee F -+GLIBC_2.27 telldir F -+GLIBC_2.27 tempnam F -+GLIBC_2.27 textdomain F -+GLIBC_2.27 tfind F -+GLIBC_2.27 time F -+GLIBC_2.27 timegm F -+GLIBC_2.27 timelocal F -+GLIBC_2.27 timerfd_create F -+GLIBC_2.27 timerfd_gettime F -+GLIBC_2.27 timerfd_settime F -+GLIBC_2.27 times F -+GLIBC_2.27 timespec_get F -+GLIBC_2.27 timezone D 0x8 -+GLIBC_2.27 tmpfile F -+GLIBC_2.27 tmpfile64 F -+GLIBC_2.27 tmpnam F -+GLIBC_2.27 tmpnam_r F -+GLIBC_2.27 toascii F -+GLIBC_2.27 tolower F -+GLIBC_2.27 tolower_l F -+GLIBC_2.27 toupper F -+GLIBC_2.27 toupper_l F -+GLIBC_2.27 towctrans F -+GLIBC_2.27 towctrans_l F -+GLIBC_2.27 towlower F -+GLIBC_2.27 towlower_l F -+GLIBC_2.27 towupper F -+GLIBC_2.27 towupper_l F -+GLIBC_2.27 tr_break F -+GLIBC_2.27 truncate F -+GLIBC_2.27 truncate64 F -+GLIBC_2.27 tsearch F -+GLIBC_2.27 ttyname F -+GLIBC_2.27 ttyname_r F -+GLIBC_2.27 ttyslot F -+GLIBC_2.27 twalk F -+GLIBC_2.27 tzname D 0x10 -+GLIBC_2.27 tzset F -+GLIBC_2.27 ualarm F -+GLIBC_2.27 ulckpwdf F -+GLIBC_2.27 ulimit F -+GLIBC_2.27 umask F -+GLIBC_2.27 umount F -+GLIBC_2.27 umount2 F -+GLIBC_2.27 uname F -+GLIBC_2.27 ungetc F -+GLIBC_2.27 ungetwc F -+GLIBC_2.27 unlink F -+GLIBC_2.27 unlinkat F -+GLIBC_2.27 unlockpt F -+GLIBC_2.27 unsetenv F -+GLIBC_2.27 unshare F -+GLIBC_2.27 updwtmp F -+GLIBC_2.27 updwtmpx F -+GLIBC_2.27 uselocale F -+GLIBC_2.27 user2netname F -+GLIBC_2.27 usleep F -+GLIBC_2.27 ustat F -+GLIBC_2.27 utime F -+GLIBC_2.27 utimensat F -+GLIBC_2.27 utimes F -+GLIBC_2.27 utmpname F -+GLIBC_2.27 utmpxname F -+GLIBC_2.27 valloc F -+GLIBC_2.27 vasprintf F -+GLIBC_2.27 vdprintf F -+GLIBC_2.27 verr F -+GLIBC_2.27 verrx F -+GLIBC_2.27 versionsort F -+GLIBC_2.27 versionsort64 F -+GLIBC_2.27 vfork F -+GLIBC_2.27 vfprintf F -+GLIBC_2.27 vfscanf F -+GLIBC_2.27 vfwprintf F -+GLIBC_2.27 vfwscanf F -+GLIBC_2.27 vhangup F -+GLIBC_2.27 vlimit F -+GLIBC_2.27 vmsplice F -+GLIBC_2.27 vprintf F -+GLIBC_2.27 vscanf F -+GLIBC_2.27 vsnprintf F -+GLIBC_2.27 vsprintf F -+GLIBC_2.27 vsscanf F -+GLIBC_2.27 vswprintf F -+GLIBC_2.27 vswscanf F -+GLIBC_2.27 vsyslog F -+GLIBC_2.27 vtimes F -+GLIBC_2.27 vwarn F -+GLIBC_2.27 vwarnx F -+GLIBC_2.27 vwprintf F -+GLIBC_2.27 vwscanf F -+GLIBC_2.27 wait F -+GLIBC_2.27 wait3 F -+GLIBC_2.27 wait4 F -+GLIBC_2.27 waitid F -+GLIBC_2.27 waitpid F -+GLIBC_2.27 warn F -+GLIBC_2.27 warnx F -+GLIBC_2.27 wcpcpy F -+GLIBC_2.27 wcpncpy F -+GLIBC_2.27 wcrtomb F -+GLIBC_2.27 wcscasecmp F -+GLIBC_2.27 wcscasecmp_l F -+GLIBC_2.27 wcscat F -+GLIBC_2.27 wcschr F -+GLIBC_2.27 wcschrnul F -+GLIBC_2.27 wcscmp F -+GLIBC_2.27 wcscoll F -+GLIBC_2.27 wcscoll_l F -+GLIBC_2.27 wcscpy F -+GLIBC_2.27 wcscspn F -+GLIBC_2.27 wcsdup F -+GLIBC_2.27 wcsftime F -+GLIBC_2.27 wcsftime_l F -+GLIBC_2.27 wcslen F -+GLIBC_2.27 wcsncasecmp F -+GLIBC_2.27 wcsncasecmp_l F -+GLIBC_2.27 wcsncat F -+GLIBC_2.27 wcsncmp F -+GLIBC_2.27 wcsncpy F -+GLIBC_2.27 wcsnlen F -+GLIBC_2.27 wcsnrtombs F -+GLIBC_2.27 wcspbrk F -+GLIBC_2.27 wcsrchr F -+GLIBC_2.27 wcsrtombs F -+GLIBC_2.27 wcsspn F -+GLIBC_2.27 wcsstr F -+GLIBC_2.27 wcstod F -+GLIBC_2.27 wcstod_l F -+GLIBC_2.27 wcstof F -+GLIBC_2.27 wcstof128 F -+GLIBC_2.27 wcstof128_l F -+GLIBC_2.27 wcstof32 F -+GLIBC_2.27 wcstof32_l F -+GLIBC_2.27 wcstof32x F -+GLIBC_2.27 wcstof32x_l F -+GLIBC_2.27 wcstof64 F -+GLIBC_2.27 wcstof64_l F -+GLIBC_2.27 wcstof64x F -+GLIBC_2.27 wcstof64x_l F -+GLIBC_2.27 wcstof_l F -+GLIBC_2.27 wcstoimax F -+GLIBC_2.27 wcstok F -+GLIBC_2.27 wcstol F -+GLIBC_2.27 wcstol_l F -+GLIBC_2.27 wcstold F -+GLIBC_2.27 wcstold_l F -+GLIBC_2.27 wcstoll F -+GLIBC_2.27 wcstoll_l F -+GLIBC_2.27 wcstombs F -+GLIBC_2.27 wcstoq F -+GLIBC_2.27 wcstoul F -+GLIBC_2.27 wcstoul_l F -+GLIBC_2.27 wcstoull F -+GLIBC_2.27 wcstoull_l F -+GLIBC_2.27 wcstoumax F -+GLIBC_2.27 wcstouq F -+GLIBC_2.27 wcswcs F -+GLIBC_2.27 wcswidth F -+GLIBC_2.27 wcsxfrm F -+GLIBC_2.27 wcsxfrm_l F -+GLIBC_2.27 wctob F -+GLIBC_2.27 wctomb F -+GLIBC_2.27 wctrans F -+GLIBC_2.27 wctrans_l F -+GLIBC_2.27 wctype F -+GLIBC_2.27 wctype_l F -+GLIBC_2.27 wcwidth F -+GLIBC_2.27 wmemchr F -+GLIBC_2.27 wmemcmp F -+GLIBC_2.27 wmemcpy F -+GLIBC_2.27 wmemmove F -+GLIBC_2.27 wmempcpy F -+GLIBC_2.27 wmemset F -+GLIBC_2.27 wordexp F -+GLIBC_2.27 wordfree F -+GLIBC_2.27 wprintf F -+GLIBC_2.27 write F -+GLIBC_2.27 writev F -+GLIBC_2.27 wscanf F -+GLIBC_2.27 xdecrypt F -+GLIBC_2.27 xdr_accepted_reply F -+GLIBC_2.27 xdr_array F -+GLIBC_2.27 xdr_authdes_cred F -+GLIBC_2.27 xdr_authdes_verf F -+GLIBC_2.27 xdr_authunix_parms F -+GLIBC_2.27 xdr_bool F -+GLIBC_2.27 xdr_bytes F -+GLIBC_2.27 xdr_callhdr F -+GLIBC_2.27 xdr_callmsg F -+GLIBC_2.27 xdr_char F -+GLIBC_2.27 xdr_cryptkeyarg F -+GLIBC_2.27 xdr_cryptkeyarg2 F -+GLIBC_2.27 xdr_cryptkeyres F -+GLIBC_2.27 xdr_des_block F -+GLIBC_2.27 xdr_double F -+GLIBC_2.27 xdr_enum F -+GLIBC_2.27 xdr_float F -+GLIBC_2.27 xdr_free F -+GLIBC_2.27 xdr_getcredres F -+GLIBC_2.27 xdr_hyper F -+GLIBC_2.27 xdr_int F -+GLIBC_2.27 xdr_int16_t F -+GLIBC_2.27 xdr_int32_t F -+GLIBC_2.27 xdr_int64_t F -+GLIBC_2.27 xdr_int8_t F -+GLIBC_2.27 xdr_key_netstarg F -+GLIBC_2.27 xdr_key_netstres F -+GLIBC_2.27 xdr_keybuf F -+GLIBC_2.27 xdr_keystatus F -+GLIBC_2.27 xdr_long F -+GLIBC_2.27 xdr_longlong_t F -+GLIBC_2.27 xdr_netnamestr F -+GLIBC_2.27 xdr_netobj F -+GLIBC_2.27 xdr_opaque F -+GLIBC_2.27 xdr_opaque_auth F -+GLIBC_2.27 xdr_pmap F -+GLIBC_2.27 xdr_pmaplist F -+GLIBC_2.27 xdr_pointer F -+GLIBC_2.27 xdr_quad_t F -+GLIBC_2.27 xdr_reference F -+GLIBC_2.27 xdr_rejected_reply F -+GLIBC_2.27 xdr_replymsg F -+GLIBC_2.27 xdr_rmtcall_args F -+GLIBC_2.27 xdr_rmtcallres F -+GLIBC_2.27 xdr_short F -+GLIBC_2.27 xdr_sizeof F -+GLIBC_2.27 xdr_string F -+GLIBC_2.27 xdr_u_char F -+GLIBC_2.27 xdr_u_hyper F -+GLIBC_2.27 xdr_u_int F -+GLIBC_2.27 xdr_u_long F -+GLIBC_2.27 xdr_u_longlong_t F -+GLIBC_2.27 xdr_u_quad_t F -+GLIBC_2.27 xdr_u_short F -+GLIBC_2.27 xdr_uint16_t F -+GLIBC_2.27 xdr_uint32_t F -+GLIBC_2.27 xdr_uint64_t F -+GLIBC_2.27 xdr_uint8_t F -+GLIBC_2.27 xdr_union F -+GLIBC_2.27 xdr_unixcred F -+GLIBC_2.27 xdr_vector F -+GLIBC_2.27 xdr_void F -+GLIBC_2.27 xdr_wrapstring F -+GLIBC_2.27 xdrmem_create F -+GLIBC_2.27 xdrrec_create F -+GLIBC_2.27 xdrrec_endofrecord F -+GLIBC_2.27 xdrrec_eof F -+GLIBC_2.27 xdrrec_skiprecord F -+GLIBC_2.27 xdrstdio_create F -+GLIBC_2.27 xencrypt F -+GLIBC_2.27 xprt_register F -+GLIBC_2.27 xprt_unregister F -+GLIBC_2.28 fcntl64 F -+GLIBC_2.28 renameat2 F -+GLIBC_2.28 statx F -+GLIBC_2.28 thrd_current F -+GLIBC_2.28 thrd_equal F -+GLIBC_2.28 thrd_sleep F -+GLIBC_2.28 thrd_yield F -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libcrypt.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libcrypt.abilist -new file mode 100644 -index 00000000..9484dca7 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libcrypt.abilist -@@ -0,0 +1,7 @@ -+GLIBC_2.27 crypt F -+GLIBC_2.27 crypt_r F -+GLIBC_2.27 encrypt F -+GLIBC_2.27 encrypt_r F -+GLIBC_2.27 fcrypt F -+GLIBC_2.27 setkey F -+GLIBC_2.27 setkey_r F -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libdl.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libdl.abilist -new file mode 100644 -index 00000000..16adcae5 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libdl.abilist -@@ -0,0 +1,9 @@ -+GLIBC_2.27 dladdr F -+GLIBC_2.27 dladdr1 F -+GLIBC_2.27 dlclose F -+GLIBC_2.27 dlerror F -+GLIBC_2.27 dlinfo F -+GLIBC_2.27 dlmopen F -+GLIBC_2.27 dlopen F -+GLIBC_2.27 dlsym F -+GLIBC_2.27 dlvsym F -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libm.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libm.abilist -new file mode 100644 -index 00000000..361fce20 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libm.abilist -@@ -0,0 +1,1021 @@ -+GLIBC_2.27 __acos_finite F -+GLIBC_2.27 __acosf_finite F -+GLIBC_2.27 __acosh_finite F -+GLIBC_2.27 __acoshf_finite F -+GLIBC_2.27 __acoshl_finite F -+GLIBC_2.27 __acosl_finite F -+GLIBC_2.27 __asin_finite F -+GLIBC_2.27 __asinf_finite F -+GLIBC_2.27 __asinl_finite F -+GLIBC_2.27 __atan2_finite F -+GLIBC_2.27 __atan2f_finite F -+GLIBC_2.27 __atan2l_finite F -+GLIBC_2.27 __atanh_finite F -+GLIBC_2.27 __atanhf_finite F -+GLIBC_2.27 __atanhl_finite F -+GLIBC_2.27 __clog10 F -+GLIBC_2.27 __clog10f F -+GLIBC_2.27 __clog10l F -+GLIBC_2.27 __cosh_finite F -+GLIBC_2.27 __coshf_finite F -+GLIBC_2.27 __coshl_finite F -+GLIBC_2.27 __exp10_finite F -+GLIBC_2.27 __exp10f_finite F -+GLIBC_2.27 __exp10l_finite F -+GLIBC_2.27 __exp2_finite F -+GLIBC_2.27 __exp2f_finite F -+GLIBC_2.27 __exp2l_finite F -+GLIBC_2.27 __exp_finite F -+GLIBC_2.27 __expf_finite F -+GLIBC_2.27 __expl_finite F -+GLIBC_2.27 __finite F -+GLIBC_2.27 __finitef F -+GLIBC_2.27 __finitel F -+GLIBC_2.27 __fmod_finite F -+GLIBC_2.27 __fmodf_finite F -+GLIBC_2.27 __fmodl_finite F -+GLIBC_2.27 __fpclassify F -+GLIBC_2.27 __fpclassifyf F -+GLIBC_2.27 __fpclassifyl F -+GLIBC_2.27 __gamma_r_finite F -+GLIBC_2.27 __gammaf_r_finite F -+GLIBC_2.27 __gammal_r_finite F -+GLIBC_2.27 __hypot_finite F -+GLIBC_2.27 __hypotf_finite F -+GLIBC_2.27 __hypotl_finite F -+GLIBC_2.27 __iseqsig F -+GLIBC_2.27 __iseqsigf F -+GLIBC_2.27 __iseqsigl F -+GLIBC_2.27 __issignaling F -+GLIBC_2.27 __issignalingf F -+GLIBC_2.27 __issignalingl F -+GLIBC_2.27 __j0_finite F -+GLIBC_2.27 __j0f_finite F -+GLIBC_2.27 __j0l_finite F -+GLIBC_2.27 __j1_finite F -+GLIBC_2.27 __j1f_finite F -+GLIBC_2.27 __j1l_finite F -+GLIBC_2.27 __jn_finite F -+GLIBC_2.27 __jnf_finite F -+GLIBC_2.27 __jnl_finite F -+GLIBC_2.27 __lgamma_r_finite F -+GLIBC_2.27 __lgammaf_r_finite F -+GLIBC_2.27 __lgammal_r_finite F -+GLIBC_2.27 __log10_finite F -+GLIBC_2.27 __log10f_finite F -+GLIBC_2.27 __log10l_finite F -+GLIBC_2.27 __log2_finite F -+GLIBC_2.27 __log2f_finite F -+GLIBC_2.27 __log2l_finite F -+GLIBC_2.27 __log_finite F -+GLIBC_2.27 __logf_finite F -+GLIBC_2.27 __logl_finite F -+GLIBC_2.27 __pow_finite F -+GLIBC_2.27 __powf_finite F -+GLIBC_2.27 __powl_finite F -+GLIBC_2.27 __remainder_finite F -+GLIBC_2.27 __remainderf_finite F -+GLIBC_2.27 __remainderl_finite F -+GLIBC_2.27 __scalb_finite F -+GLIBC_2.27 __scalbf_finite F -+GLIBC_2.27 __scalbl_finite F -+GLIBC_2.27 __signbit F -+GLIBC_2.27 __signbitf F -+GLIBC_2.27 __signbitl F -+GLIBC_2.27 __signgam D 0x4 -+GLIBC_2.27 __sinh_finite F -+GLIBC_2.27 __sinhf_finite F -+GLIBC_2.27 __sinhl_finite F -+GLIBC_2.27 __sqrt_finite F -+GLIBC_2.27 __sqrtf_finite F -+GLIBC_2.27 __sqrtl_finite F -+GLIBC_2.27 __y0_finite F -+GLIBC_2.27 __y0f_finite F -+GLIBC_2.27 __y0l_finite F -+GLIBC_2.27 __y1_finite F -+GLIBC_2.27 __y1f_finite F -+GLIBC_2.27 __y1l_finite F -+GLIBC_2.27 __yn_finite F -+GLIBC_2.27 __ynf_finite F -+GLIBC_2.27 __ynl_finite F -+GLIBC_2.27 acos F -+GLIBC_2.27 acosf F -+GLIBC_2.27 acosf128 F -+GLIBC_2.27 acosf32 F -+GLIBC_2.27 acosf32x F -+GLIBC_2.27 acosf64 F -+GLIBC_2.27 acosf64x F -+GLIBC_2.27 acosh F -+GLIBC_2.27 acoshf F -+GLIBC_2.27 acoshf128 F -+GLIBC_2.27 acoshf32 F -+GLIBC_2.27 acoshf32x F -+GLIBC_2.27 acoshf64 F -+GLIBC_2.27 acoshf64x F -+GLIBC_2.27 acoshl F -+GLIBC_2.27 acosl F -+GLIBC_2.27 asin F -+GLIBC_2.27 asinf F -+GLIBC_2.27 asinf128 F -+GLIBC_2.27 asinf32 F -+GLIBC_2.27 asinf32x F -+GLIBC_2.27 asinf64 F -+GLIBC_2.27 asinf64x F -+GLIBC_2.27 asinh F -+GLIBC_2.27 asinhf F -+GLIBC_2.27 asinhf128 F -+GLIBC_2.27 asinhf32 F -+GLIBC_2.27 asinhf32x F -+GLIBC_2.27 asinhf64 F -+GLIBC_2.27 asinhf64x F -+GLIBC_2.27 asinhl F -+GLIBC_2.27 asinl F -+GLIBC_2.27 atan F -+GLIBC_2.27 atan2 F -+GLIBC_2.27 atan2f F -+GLIBC_2.27 atan2f128 F -+GLIBC_2.27 atan2f32 F -+GLIBC_2.27 atan2f32x F -+GLIBC_2.27 atan2f64 F -+GLIBC_2.27 atan2f64x F -+GLIBC_2.27 atan2l F -+GLIBC_2.27 atanf F -+GLIBC_2.27 atanf128 F -+GLIBC_2.27 atanf32 F -+GLIBC_2.27 atanf32x F -+GLIBC_2.27 atanf64 F -+GLIBC_2.27 atanf64x F -+GLIBC_2.27 atanh F -+GLIBC_2.27 atanhf F -+GLIBC_2.27 atanhf128 F -+GLIBC_2.27 atanhf32 F -+GLIBC_2.27 atanhf32x F -+GLIBC_2.27 atanhf64 F -+GLIBC_2.27 atanhf64x F -+GLIBC_2.27 atanhl F -+GLIBC_2.27 atanl F -+GLIBC_2.27 cabs F -+GLIBC_2.27 cabsf F -+GLIBC_2.27 cabsf128 F -+GLIBC_2.27 cabsf32 F -+GLIBC_2.27 cabsf32x F -+GLIBC_2.27 cabsf64 F -+GLIBC_2.27 cabsf64x F -+GLIBC_2.27 cabsl F -+GLIBC_2.27 cacos F -+GLIBC_2.27 cacosf F -+GLIBC_2.27 cacosf128 F -+GLIBC_2.27 cacosf32 F -+GLIBC_2.27 cacosf32x F -+GLIBC_2.27 cacosf64 F -+GLIBC_2.27 cacosf64x F -+GLIBC_2.27 cacosh F -+GLIBC_2.27 cacoshf F -+GLIBC_2.27 cacoshf128 F -+GLIBC_2.27 cacoshf32 F -+GLIBC_2.27 cacoshf32x F -+GLIBC_2.27 cacoshf64 F -+GLIBC_2.27 cacoshf64x F -+GLIBC_2.27 cacoshl F -+GLIBC_2.27 cacosl F -+GLIBC_2.27 canonicalize F -+GLIBC_2.27 canonicalizef F -+GLIBC_2.27 canonicalizef128 F -+GLIBC_2.27 canonicalizef32 F -+GLIBC_2.27 canonicalizef32x F -+GLIBC_2.27 canonicalizef64 F -+GLIBC_2.27 canonicalizef64x F -+GLIBC_2.27 canonicalizel F -+GLIBC_2.27 carg F -+GLIBC_2.27 cargf F -+GLIBC_2.27 cargf128 F -+GLIBC_2.27 cargf32 F -+GLIBC_2.27 cargf32x F -+GLIBC_2.27 cargf64 F -+GLIBC_2.27 cargf64x F -+GLIBC_2.27 cargl F -+GLIBC_2.27 casin F -+GLIBC_2.27 casinf F -+GLIBC_2.27 casinf128 F -+GLIBC_2.27 casinf32 F -+GLIBC_2.27 casinf32x F -+GLIBC_2.27 casinf64 F -+GLIBC_2.27 casinf64x F -+GLIBC_2.27 casinh F -+GLIBC_2.27 casinhf F -+GLIBC_2.27 casinhf128 F -+GLIBC_2.27 casinhf32 F -+GLIBC_2.27 casinhf32x F -+GLIBC_2.27 casinhf64 F -+GLIBC_2.27 casinhf64x F -+GLIBC_2.27 casinhl F -+GLIBC_2.27 casinl F -+GLIBC_2.27 catan F -+GLIBC_2.27 catanf F -+GLIBC_2.27 catanf128 F -+GLIBC_2.27 catanf32 F -+GLIBC_2.27 catanf32x F -+GLIBC_2.27 catanf64 F -+GLIBC_2.27 catanf64x F -+GLIBC_2.27 catanh F -+GLIBC_2.27 catanhf F -+GLIBC_2.27 catanhf128 F -+GLIBC_2.27 catanhf32 F -+GLIBC_2.27 catanhf32x F -+GLIBC_2.27 catanhf64 F -+GLIBC_2.27 catanhf64x F -+GLIBC_2.27 catanhl F -+GLIBC_2.27 catanl F -+GLIBC_2.27 cbrt F -+GLIBC_2.27 cbrtf F -+GLIBC_2.27 cbrtf128 F -+GLIBC_2.27 cbrtf32 F -+GLIBC_2.27 cbrtf32x F -+GLIBC_2.27 cbrtf64 F -+GLIBC_2.27 cbrtf64x F -+GLIBC_2.27 cbrtl F -+GLIBC_2.27 ccos F -+GLIBC_2.27 ccosf F -+GLIBC_2.27 ccosf128 F -+GLIBC_2.27 ccosf32 F -+GLIBC_2.27 ccosf32x F -+GLIBC_2.27 ccosf64 F -+GLIBC_2.27 ccosf64x F -+GLIBC_2.27 ccosh F -+GLIBC_2.27 ccoshf F -+GLIBC_2.27 ccoshf128 F -+GLIBC_2.27 ccoshf32 F -+GLIBC_2.27 ccoshf32x F -+GLIBC_2.27 ccoshf64 F -+GLIBC_2.27 ccoshf64x F -+GLIBC_2.27 ccoshl F -+GLIBC_2.27 ccosl F -+GLIBC_2.27 ceil F -+GLIBC_2.27 ceilf F -+GLIBC_2.27 ceilf128 F -+GLIBC_2.27 ceilf32 F -+GLIBC_2.27 ceilf32x F -+GLIBC_2.27 ceilf64 F -+GLIBC_2.27 ceilf64x F -+GLIBC_2.27 ceill F -+GLIBC_2.27 cexp F -+GLIBC_2.27 cexpf F -+GLIBC_2.27 cexpf128 F -+GLIBC_2.27 cexpf32 F -+GLIBC_2.27 cexpf32x F -+GLIBC_2.27 cexpf64 F -+GLIBC_2.27 cexpf64x F -+GLIBC_2.27 cexpl F -+GLIBC_2.27 cimag F -+GLIBC_2.27 cimagf F -+GLIBC_2.27 cimagf128 F -+GLIBC_2.27 cimagf32 F -+GLIBC_2.27 cimagf32x F -+GLIBC_2.27 cimagf64 F -+GLIBC_2.27 cimagf64x F -+GLIBC_2.27 cimagl F -+GLIBC_2.27 clog F -+GLIBC_2.27 clog10 F -+GLIBC_2.27 clog10f F -+GLIBC_2.27 clog10f128 F -+GLIBC_2.27 clog10f32 F -+GLIBC_2.27 clog10f32x F -+GLIBC_2.27 clog10f64 F -+GLIBC_2.27 clog10f64x F -+GLIBC_2.27 clog10l F -+GLIBC_2.27 clogf F -+GLIBC_2.27 clogf128 F -+GLIBC_2.27 clogf32 F -+GLIBC_2.27 clogf32x F -+GLIBC_2.27 clogf64 F -+GLIBC_2.27 clogf64x F -+GLIBC_2.27 clogl F -+GLIBC_2.27 conj F -+GLIBC_2.27 conjf F -+GLIBC_2.27 conjf128 F -+GLIBC_2.27 conjf32 F -+GLIBC_2.27 conjf32x F -+GLIBC_2.27 conjf64 F -+GLIBC_2.27 conjf64x F -+GLIBC_2.27 conjl F -+GLIBC_2.27 copysign F -+GLIBC_2.27 copysignf F -+GLIBC_2.27 copysignf128 F -+GLIBC_2.27 copysignf32 F -+GLIBC_2.27 copysignf32x F -+GLIBC_2.27 copysignf64 F -+GLIBC_2.27 copysignf64x F -+GLIBC_2.27 copysignl F -+GLIBC_2.27 cos F -+GLIBC_2.27 cosf F -+GLIBC_2.27 cosf128 F -+GLIBC_2.27 cosf32 F -+GLIBC_2.27 cosf32x F -+GLIBC_2.27 cosf64 F -+GLIBC_2.27 cosf64x F -+GLIBC_2.27 cosh F -+GLIBC_2.27 coshf F -+GLIBC_2.27 coshf128 F -+GLIBC_2.27 coshf32 F -+GLIBC_2.27 coshf32x F -+GLIBC_2.27 coshf64 F -+GLIBC_2.27 coshf64x F -+GLIBC_2.27 coshl F -+GLIBC_2.27 cosl F -+GLIBC_2.27 cpow F -+GLIBC_2.27 cpowf F -+GLIBC_2.27 cpowf128 F -+GLIBC_2.27 cpowf32 F -+GLIBC_2.27 cpowf32x F -+GLIBC_2.27 cpowf64 F -+GLIBC_2.27 cpowf64x F -+GLIBC_2.27 cpowl F -+GLIBC_2.27 cproj F -+GLIBC_2.27 cprojf F -+GLIBC_2.27 cprojf128 F -+GLIBC_2.27 cprojf32 F -+GLIBC_2.27 cprojf32x F -+GLIBC_2.27 cprojf64 F -+GLIBC_2.27 cprojf64x F -+GLIBC_2.27 cprojl F -+GLIBC_2.27 creal F -+GLIBC_2.27 crealf F -+GLIBC_2.27 crealf128 F -+GLIBC_2.27 crealf32 F -+GLIBC_2.27 crealf32x F -+GLIBC_2.27 crealf64 F -+GLIBC_2.27 crealf64x F -+GLIBC_2.27 creall F -+GLIBC_2.27 csin F -+GLIBC_2.27 csinf F -+GLIBC_2.27 csinf128 F -+GLIBC_2.27 csinf32 F -+GLIBC_2.27 csinf32x F -+GLIBC_2.27 csinf64 F -+GLIBC_2.27 csinf64x F -+GLIBC_2.27 csinh F -+GLIBC_2.27 csinhf F -+GLIBC_2.27 csinhf128 F -+GLIBC_2.27 csinhf32 F -+GLIBC_2.27 csinhf32x F -+GLIBC_2.27 csinhf64 F -+GLIBC_2.27 csinhf64x F -+GLIBC_2.27 csinhl F -+GLIBC_2.27 csinl F -+GLIBC_2.27 csqrt F -+GLIBC_2.27 csqrtf F -+GLIBC_2.27 csqrtf128 F -+GLIBC_2.27 csqrtf32 F -+GLIBC_2.27 csqrtf32x F -+GLIBC_2.27 csqrtf64 F -+GLIBC_2.27 csqrtf64x F -+GLIBC_2.27 csqrtl F -+GLIBC_2.27 ctan F -+GLIBC_2.27 ctanf F -+GLIBC_2.27 ctanf128 F -+GLIBC_2.27 ctanf32 F -+GLIBC_2.27 ctanf32x F -+GLIBC_2.27 ctanf64 F -+GLIBC_2.27 ctanf64x F -+GLIBC_2.27 ctanh F -+GLIBC_2.27 ctanhf F -+GLIBC_2.27 ctanhf128 F -+GLIBC_2.27 ctanhf32 F -+GLIBC_2.27 ctanhf32x F -+GLIBC_2.27 ctanhf64 F -+GLIBC_2.27 ctanhf64x F -+GLIBC_2.27 ctanhl F -+GLIBC_2.27 ctanl F -+GLIBC_2.27 drem F -+GLIBC_2.27 dremf F -+GLIBC_2.27 dreml F -+GLIBC_2.27 erf F -+GLIBC_2.27 erfc F -+GLIBC_2.27 erfcf F -+GLIBC_2.27 erfcf128 F -+GLIBC_2.27 erfcf32 F -+GLIBC_2.27 erfcf32x F -+GLIBC_2.27 erfcf64 F -+GLIBC_2.27 erfcf64x F -+GLIBC_2.27 erfcl F -+GLIBC_2.27 erff F -+GLIBC_2.27 erff128 F -+GLIBC_2.27 erff32 F -+GLIBC_2.27 erff32x F -+GLIBC_2.27 erff64 F -+GLIBC_2.27 erff64x F -+GLIBC_2.27 erfl F -+GLIBC_2.27 exp F -+GLIBC_2.27 exp10 F -+GLIBC_2.27 exp10f F -+GLIBC_2.27 exp10f128 F -+GLIBC_2.27 exp10f32 F -+GLIBC_2.27 exp10f32x F -+GLIBC_2.27 exp10f64 F -+GLIBC_2.27 exp10f64x F -+GLIBC_2.27 exp10l F -+GLIBC_2.27 exp2 F -+GLIBC_2.27 exp2f F -+GLIBC_2.27 exp2f128 F -+GLIBC_2.27 exp2f32 F -+GLIBC_2.27 exp2f32x F -+GLIBC_2.27 exp2f64 F -+GLIBC_2.27 exp2f64x F -+GLIBC_2.27 exp2l F -+GLIBC_2.27 expf F -+GLIBC_2.27 expf128 F -+GLIBC_2.27 expf32 F -+GLIBC_2.27 expf32x F -+GLIBC_2.27 expf64 F -+GLIBC_2.27 expf64x F -+GLIBC_2.27 expl F -+GLIBC_2.27 expm1 F -+GLIBC_2.27 expm1f F -+GLIBC_2.27 expm1f128 F -+GLIBC_2.27 expm1f32 F -+GLIBC_2.27 expm1f32x F -+GLIBC_2.27 expm1f64 F -+GLIBC_2.27 expm1f64x F -+GLIBC_2.27 expm1l F -+GLIBC_2.27 fabs F -+GLIBC_2.27 fabsf F -+GLIBC_2.27 fabsf128 F -+GLIBC_2.27 fabsf32 F -+GLIBC_2.27 fabsf32x F -+GLIBC_2.27 fabsf64 F -+GLIBC_2.27 fabsf64x F -+GLIBC_2.27 fabsl F -+GLIBC_2.27 fdim F -+GLIBC_2.27 fdimf F -+GLIBC_2.27 fdimf128 F -+GLIBC_2.27 fdimf32 F -+GLIBC_2.27 fdimf32x F -+GLIBC_2.27 fdimf64 F -+GLIBC_2.27 fdimf64x F -+GLIBC_2.27 fdiml F -+GLIBC_2.27 feclearexcept F -+GLIBC_2.27 fedisableexcept F -+GLIBC_2.27 feenableexcept F -+GLIBC_2.27 fegetenv F -+GLIBC_2.27 fegetexcept F -+GLIBC_2.27 fegetexceptflag F -+GLIBC_2.27 fegetmode F -+GLIBC_2.27 fegetround F -+GLIBC_2.27 feholdexcept F -+GLIBC_2.27 feraiseexcept F -+GLIBC_2.27 fesetenv F -+GLIBC_2.27 fesetexcept F -+GLIBC_2.27 fesetexceptflag F -+GLIBC_2.27 fesetmode F -+GLIBC_2.27 fesetround F -+GLIBC_2.27 fetestexcept F -+GLIBC_2.27 fetestexceptflag F -+GLIBC_2.27 feupdateenv F -+GLIBC_2.27 finite F -+GLIBC_2.27 finitef F -+GLIBC_2.27 finitel F -+GLIBC_2.27 floor F -+GLIBC_2.27 floorf F -+GLIBC_2.27 floorf128 F -+GLIBC_2.27 floorf32 F -+GLIBC_2.27 floorf32x F -+GLIBC_2.27 floorf64 F -+GLIBC_2.27 floorf64x F -+GLIBC_2.27 floorl F -+GLIBC_2.27 fma F -+GLIBC_2.27 fmaf F -+GLIBC_2.27 fmaf128 F -+GLIBC_2.27 fmaf32 F -+GLIBC_2.27 fmaf32x F -+GLIBC_2.27 fmaf64 F -+GLIBC_2.27 fmaf64x F -+GLIBC_2.27 fmal F -+GLIBC_2.27 fmax F -+GLIBC_2.27 fmaxf F -+GLIBC_2.27 fmaxf128 F -+GLIBC_2.27 fmaxf32 F -+GLIBC_2.27 fmaxf32x F -+GLIBC_2.27 fmaxf64 F -+GLIBC_2.27 fmaxf64x F -+GLIBC_2.27 fmaxl F -+GLIBC_2.27 fmaxmag F -+GLIBC_2.27 fmaxmagf F -+GLIBC_2.27 fmaxmagf128 F -+GLIBC_2.27 fmaxmagf32 F -+GLIBC_2.27 fmaxmagf32x F -+GLIBC_2.27 fmaxmagf64 F -+GLIBC_2.27 fmaxmagf64x F -+GLIBC_2.27 fmaxmagl F -+GLIBC_2.27 fmin F -+GLIBC_2.27 fminf F -+GLIBC_2.27 fminf128 F -+GLIBC_2.27 fminf32 F -+GLIBC_2.27 fminf32x F -+GLIBC_2.27 fminf64 F -+GLIBC_2.27 fminf64x F -+GLIBC_2.27 fminl F -+GLIBC_2.27 fminmag F -+GLIBC_2.27 fminmagf F -+GLIBC_2.27 fminmagf128 F -+GLIBC_2.27 fminmagf32 F -+GLIBC_2.27 fminmagf32x F -+GLIBC_2.27 fminmagf64 F -+GLIBC_2.27 fminmagf64x F -+GLIBC_2.27 fminmagl F -+GLIBC_2.27 fmod F -+GLIBC_2.27 fmodf F -+GLIBC_2.27 fmodf128 F -+GLIBC_2.27 fmodf32 F -+GLIBC_2.27 fmodf32x F -+GLIBC_2.27 fmodf64 F -+GLIBC_2.27 fmodf64x F -+GLIBC_2.27 fmodl F -+GLIBC_2.27 frexp F -+GLIBC_2.27 frexpf F -+GLIBC_2.27 frexpf128 F -+GLIBC_2.27 frexpf32 F -+GLIBC_2.27 frexpf32x F -+GLIBC_2.27 frexpf64 F -+GLIBC_2.27 frexpf64x F -+GLIBC_2.27 frexpl F -+GLIBC_2.27 fromfp F -+GLIBC_2.27 fromfpf F -+GLIBC_2.27 fromfpf128 F -+GLIBC_2.27 fromfpf32 F -+GLIBC_2.27 fromfpf32x F -+GLIBC_2.27 fromfpf64 F -+GLIBC_2.27 fromfpf64x F -+GLIBC_2.27 fromfpl F -+GLIBC_2.27 fromfpx F -+GLIBC_2.27 fromfpxf F -+GLIBC_2.27 fromfpxf128 F -+GLIBC_2.27 fromfpxf32 F -+GLIBC_2.27 fromfpxf32x F -+GLIBC_2.27 fromfpxf64 F -+GLIBC_2.27 fromfpxf64x F -+GLIBC_2.27 fromfpxl F -+GLIBC_2.27 gamma F -+GLIBC_2.27 gammaf F -+GLIBC_2.27 gammal F -+GLIBC_2.27 getpayload F -+GLIBC_2.27 getpayloadf F -+GLIBC_2.27 getpayloadf128 F -+GLIBC_2.27 getpayloadf32 F -+GLIBC_2.27 getpayloadf32x F -+GLIBC_2.27 getpayloadf64 F -+GLIBC_2.27 getpayloadf64x F -+GLIBC_2.27 getpayloadl F -+GLIBC_2.27 hypot F -+GLIBC_2.27 hypotf F -+GLIBC_2.27 hypotf128 F -+GLIBC_2.27 hypotf32 F -+GLIBC_2.27 hypotf32x F -+GLIBC_2.27 hypotf64 F -+GLIBC_2.27 hypotf64x F -+GLIBC_2.27 hypotl F -+GLIBC_2.27 ilogb F -+GLIBC_2.27 ilogbf F -+GLIBC_2.27 ilogbf128 F -+GLIBC_2.27 ilogbf32 F -+GLIBC_2.27 ilogbf32x F -+GLIBC_2.27 ilogbf64 F -+GLIBC_2.27 ilogbf64x F -+GLIBC_2.27 ilogbl F -+GLIBC_2.27 j0 F -+GLIBC_2.27 j0f F -+GLIBC_2.27 j0f128 F -+GLIBC_2.27 j0f32 F -+GLIBC_2.27 j0f32x F -+GLIBC_2.27 j0f64 F -+GLIBC_2.27 j0f64x F -+GLIBC_2.27 j0l F -+GLIBC_2.27 j1 F -+GLIBC_2.27 j1f F -+GLIBC_2.27 j1f128 F -+GLIBC_2.27 j1f32 F -+GLIBC_2.27 j1f32x F -+GLIBC_2.27 j1f64 F -+GLIBC_2.27 j1f64x F -+GLIBC_2.27 j1l F -+GLIBC_2.27 jn F -+GLIBC_2.27 jnf F -+GLIBC_2.27 jnf128 F -+GLIBC_2.27 jnf32 F -+GLIBC_2.27 jnf32x F -+GLIBC_2.27 jnf64 F -+GLIBC_2.27 jnf64x F -+GLIBC_2.27 jnl F -+GLIBC_2.27 ldexp F -+GLIBC_2.27 ldexpf F -+GLIBC_2.27 ldexpf128 F -+GLIBC_2.27 ldexpf32 F -+GLIBC_2.27 ldexpf32x F -+GLIBC_2.27 ldexpf64 F -+GLIBC_2.27 ldexpf64x F -+GLIBC_2.27 ldexpl F -+GLIBC_2.27 lgamma F -+GLIBC_2.27 lgamma_r F -+GLIBC_2.27 lgammaf F -+GLIBC_2.27 lgammaf128 F -+GLIBC_2.27 lgammaf128_r F -+GLIBC_2.27 lgammaf32 F -+GLIBC_2.27 lgammaf32_r F -+GLIBC_2.27 lgammaf32x F -+GLIBC_2.27 lgammaf32x_r F -+GLIBC_2.27 lgammaf64 F -+GLIBC_2.27 lgammaf64_r F -+GLIBC_2.27 lgammaf64x F -+GLIBC_2.27 lgammaf64x_r F -+GLIBC_2.27 lgammaf_r F -+GLIBC_2.27 lgammal F -+GLIBC_2.27 lgammal_r F -+GLIBC_2.27 llogb F -+GLIBC_2.27 llogbf F -+GLIBC_2.27 llogbf128 F -+GLIBC_2.27 llogbf32 F -+GLIBC_2.27 llogbf32x F -+GLIBC_2.27 llogbf64 F -+GLIBC_2.27 llogbf64x F -+GLIBC_2.27 llogbl F -+GLIBC_2.27 llrint F -+GLIBC_2.27 llrintf F -+GLIBC_2.27 llrintf128 F -+GLIBC_2.27 llrintf32 F -+GLIBC_2.27 llrintf32x F -+GLIBC_2.27 llrintf64 F -+GLIBC_2.27 llrintf64x F -+GLIBC_2.27 llrintl F -+GLIBC_2.27 llround F -+GLIBC_2.27 llroundf F -+GLIBC_2.27 llroundf128 F -+GLIBC_2.27 llroundf32 F -+GLIBC_2.27 llroundf32x F -+GLIBC_2.27 llroundf64 F -+GLIBC_2.27 llroundf64x F -+GLIBC_2.27 llroundl F -+GLIBC_2.27 log F -+GLIBC_2.27 log10 F -+GLIBC_2.27 log10f F -+GLIBC_2.27 log10f128 F -+GLIBC_2.27 log10f32 F -+GLIBC_2.27 log10f32x F -+GLIBC_2.27 log10f64 F -+GLIBC_2.27 log10f64x F -+GLIBC_2.27 log10l F -+GLIBC_2.27 log1p F -+GLIBC_2.27 log1pf F -+GLIBC_2.27 log1pf128 F -+GLIBC_2.27 log1pf32 F -+GLIBC_2.27 log1pf32x F -+GLIBC_2.27 log1pf64 F -+GLIBC_2.27 log1pf64x F -+GLIBC_2.27 log1pl F -+GLIBC_2.27 log2 F -+GLIBC_2.27 log2f F -+GLIBC_2.27 log2f128 F -+GLIBC_2.27 log2f32 F -+GLIBC_2.27 log2f32x F -+GLIBC_2.27 log2f64 F -+GLIBC_2.27 log2f64x F -+GLIBC_2.27 log2l F -+GLIBC_2.27 logb F -+GLIBC_2.27 logbf F -+GLIBC_2.27 logbf128 F -+GLIBC_2.27 logbf32 F -+GLIBC_2.27 logbf32x F -+GLIBC_2.27 logbf64 F -+GLIBC_2.27 logbf64x F -+GLIBC_2.27 logbl F -+GLIBC_2.27 logf F -+GLIBC_2.27 logf128 F -+GLIBC_2.27 logf32 F -+GLIBC_2.27 logf32x F -+GLIBC_2.27 logf64 F -+GLIBC_2.27 logf64x F -+GLIBC_2.27 logl F -+GLIBC_2.27 lrint F -+GLIBC_2.27 lrintf F -+GLIBC_2.27 lrintf128 F -+GLIBC_2.27 lrintf32 F -+GLIBC_2.27 lrintf32x F -+GLIBC_2.27 lrintf64 F -+GLIBC_2.27 lrintf64x F -+GLIBC_2.27 lrintl F -+GLIBC_2.27 lround F -+GLIBC_2.27 lroundf F -+GLIBC_2.27 lroundf128 F -+GLIBC_2.27 lroundf32 F -+GLIBC_2.27 lroundf32x F -+GLIBC_2.27 lroundf64 F -+GLIBC_2.27 lroundf64x F -+GLIBC_2.27 lroundl F -+GLIBC_2.27 modf F -+GLIBC_2.27 modff F -+GLIBC_2.27 modff128 F -+GLIBC_2.27 modff32 F -+GLIBC_2.27 modff32x F -+GLIBC_2.27 modff64 F -+GLIBC_2.27 modff64x F -+GLIBC_2.27 modfl F -+GLIBC_2.27 nan F -+GLIBC_2.27 nanf F -+GLIBC_2.27 nanf128 F -+GLIBC_2.27 nanf32 F -+GLIBC_2.27 nanf32x F -+GLIBC_2.27 nanf64 F -+GLIBC_2.27 nanf64x F -+GLIBC_2.27 nanl F -+GLIBC_2.27 nearbyint F -+GLIBC_2.27 nearbyintf F -+GLIBC_2.27 nearbyintf128 F -+GLIBC_2.27 nearbyintf32 F -+GLIBC_2.27 nearbyintf32x F -+GLIBC_2.27 nearbyintf64 F -+GLIBC_2.27 nearbyintf64x F -+GLIBC_2.27 nearbyintl F -+GLIBC_2.27 nextafter F -+GLIBC_2.27 nextafterf F -+GLIBC_2.27 nextafterf128 F -+GLIBC_2.27 nextafterf32 F -+GLIBC_2.27 nextafterf32x F -+GLIBC_2.27 nextafterf64 F -+GLIBC_2.27 nextafterf64x F -+GLIBC_2.27 nextafterl F -+GLIBC_2.27 nextdown F -+GLIBC_2.27 nextdownf F -+GLIBC_2.27 nextdownf128 F -+GLIBC_2.27 nextdownf32 F -+GLIBC_2.27 nextdownf32x F -+GLIBC_2.27 nextdownf64 F -+GLIBC_2.27 nextdownf64x F -+GLIBC_2.27 nextdownl F -+GLIBC_2.27 nexttoward F -+GLIBC_2.27 nexttowardf F -+GLIBC_2.27 nexttowardl F -+GLIBC_2.27 nextup F -+GLIBC_2.27 nextupf F -+GLIBC_2.27 nextupf128 F -+GLIBC_2.27 nextupf32 F -+GLIBC_2.27 nextupf32x F -+GLIBC_2.27 nextupf64 F -+GLIBC_2.27 nextupf64x F -+GLIBC_2.27 nextupl F -+GLIBC_2.27 pow F -+GLIBC_2.27 powf F -+GLIBC_2.27 powf128 F -+GLIBC_2.27 powf32 F -+GLIBC_2.27 powf32x F -+GLIBC_2.27 powf64 F -+GLIBC_2.27 powf64x F -+GLIBC_2.27 powl F -+GLIBC_2.27 remainder F -+GLIBC_2.27 remainderf F -+GLIBC_2.27 remainderf128 F -+GLIBC_2.27 remainderf32 F -+GLIBC_2.27 remainderf32x F -+GLIBC_2.27 remainderf64 F -+GLIBC_2.27 remainderf64x F -+GLIBC_2.27 remainderl F -+GLIBC_2.27 remquo F -+GLIBC_2.27 remquof F -+GLIBC_2.27 remquof128 F -+GLIBC_2.27 remquof32 F -+GLIBC_2.27 remquof32x F -+GLIBC_2.27 remquof64 F -+GLIBC_2.27 remquof64x F -+GLIBC_2.27 remquol F -+GLIBC_2.27 rint F -+GLIBC_2.27 rintf F -+GLIBC_2.27 rintf128 F -+GLIBC_2.27 rintf32 F -+GLIBC_2.27 rintf32x F -+GLIBC_2.27 rintf64 F -+GLIBC_2.27 rintf64x F -+GLIBC_2.27 rintl F -+GLIBC_2.27 round F -+GLIBC_2.27 roundeven F -+GLIBC_2.27 roundevenf F -+GLIBC_2.27 roundevenf128 F -+GLIBC_2.27 roundevenf32 F -+GLIBC_2.27 roundevenf32x F -+GLIBC_2.27 roundevenf64 F -+GLIBC_2.27 roundevenf64x F -+GLIBC_2.27 roundevenl F -+GLIBC_2.27 roundf F -+GLIBC_2.27 roundf128 F -+GLIBC_2.27 roundf32 F -+GLIBC_2.27 roundf32x F -+GLIBC_2.27 roundf64 F -+GLIBC_2.27 roundf64x F -+GLIBC_2.27 roundl F -+GLIBC_2.27 scalb F -+GLIBC_2.27 scalbf F -+GLIBC_2.27 scalbl F -+GLIBC_2.27 scalbln F -+GLIBC_2.27 scalblnf F -+GLIBC_2.27 scalblnf128 F -+GLIBC_2.27 scalblnf32 F -+GLIBC_2.27 scalblnf32x F -+GLIBC_2.27 scalblnf64 F -+GLIBC_2.27 scalblnf64x F -+GLIBC_2.27 scalblnl F -+GLIBC_2.27 scalbn F -+GLIBC_2.27 scalbnf F -+GLIBC_2.27 scalbnf128 F -+GLIBC_2.27 scalbnf32 F -+GLIBC_2.27 scalbnf32x F -+GLIBC_2.27 scalbnf64 F -+GLIBC_2.27 scalbnf64x F -+GLIBC_2.27 scalbnl F -+GLIBC_2.27 setpayload F -+GLIBC_2.27 setpayloadf F -+GLIBC_2.27 setpayloadf128 F -+GLIBC_2.27 setpayloadf32 F -+GLIBC_2.27 setpayloadf32x F -+GLIBC_2.27 setpayloadf64 F -+GLIBC_2.27 setpayloadf64x F -+GLIBC_2.27 setpayloadl F -+GLIBC_2.27 setpayloadsig F -+GLIBC_2.27 setpayloadsigf F -+GLIBC_2.27 setpayloadsigf128 F -+GLIBC_2.27 setpayloadsigf32 F -+GLIBC_2.27 setpayloadsigf32x F -+GLIBC_2.27 setpayloadsigf64 F -+GLIBC_2.27 setpayloadsigf64x F -+GLIBC_2.27 setpayloadsigl F -+GLIBC_2.27 signgam D 0x4 -+GLIBC_2.27 significand F -+GLIBC_2.27 significandf F -+GLIBC_2.27 significandl F -+GLIBC_2.27 sin F -+GLIBC_2.27 sincos F -+GLIBC_2.27 sincosf F -+GLIBC_2.27 sincosf128 F -+GLIBC_2.27 sincosf32 F -+GLIBC_2.27 sincosf32x F -+GLIBC_2.27 sincosf64 F -+GLIBC_2.27 sincosf64x F -+GLIBC_2.27 sincosl F -+GLIBC_2.27 sinf F -+GLIBC_2.27 sinf128 F -+GLIBC_2.27 sinf32 F -+GLIBC_2.27 sinf32x F -+GLIBC_2.27 sinf64 F -+GLIBC_2.27 sinf64x F -+GLIBC_2.27 sinh F -+GLIBC_2.27 sinhf F -+GLIBC_2.27 sinhf128 F -+GLIBC_2.27 sinhf32 F -+GLIBC_2.27 sinhf32x F -+GLIBC_2.27 sinhf64 F -+GLIBC_2.27 sinhf64x F -+GLIBC_2.27 sinhl F -+GLIBC_2.27 sinl F -+GLIBC_2.27 sqrt F -+GLIBC_2.27 sqrtf F -+GLIBC_2.27 sqrtf128 F -+GLIBC_2.27 sqrtf32 F -+GLIBC_2.27 sqrtf32x F -+GLIBC_2.27 sqrtf64 F -+GLIBC_2.27 sqrtf64x F -+GLIBC_2.27 sqrtl F -+GLIBC_2.27 tan F -+GLIBC_2.27 tanf F -+GLIBC_2.27 tanf128 F -+GLIBC_2.27 tanf32 F -+GLIBC_2.27 tanf32x F -+GLIBC_2.27 tanf64 F -+GLIBC_2.27 tanf64x F -+GLIBC_2.27 tanh F -+GLIBC_2.27 tanhf F -+GLIBC_2.27 tanhf128 F -+GLIBC_2.27 tanhf32 F -+GLIBC_2.27 tanhf32x F -+GLIBC_2.27 tanhf64 F -+GLIBC_2.27 tanhf64x F -+GLIBC_2.27 tanhl F -+GLIBC_2.27 tanl F -+GLIBC_2.27 tgamma F -+GLIBC_2.27 tgammaf F -+GLIBC_2.27 tgammaf128 F -+GLIBC_2.27 tgammaf32 F -+GLIBC_2.27 tgammaf32x F -+GLIBC_2.27 tgammaf64 F -+GLIBC_2.27 tgammaf64x F -+GLIBC_2.27 tgammal F -+GLIBC_2.27 totalorder F -+GLIBC_2.27 totalorderf F -+GLIBC_2.27 totalorderf128 F -+GLIBC_2.27 totalorderf32 F -+GLIBC_2.27 totalorderf32x F -+GLIBC_2.27 totalorderf64 F -+GLIBC_2.27 totalorderf64x F -+GLIBC_2.27 totalorderl F -+GLIBC_2.27 totalordermag F -+GLIBC_2.27 totalordermagf F -+GLIBC_2.27 totalordermagf128 F -+GLIBC_2.27 totalordermagf32 F -+GLIBC_2.27 totalordermagf32x F -+GLIBC_2.27 totalordermagf64 F -+GLIBC_2.27 totalordermagf64x F -+GLIBC_2.27 totalordermagl F -+GLIBC_2.27 trunc F -+GLIBC_2.27 truncf F -+GLIBC_2.27 truncf128 F -+GLIBC_2.27 truncf32 F -+GLIBC_2.27 truncf32x F -+GLIBC_2.27 truncf64 F -+GLIBC_2.27 truncf64x F -+GLIBC_2.27 truncl F -+GLIBC_2.27 ufromfp F -+GLIBC_2.27 ufromfpf F -+GLIBC_2.27 ufromfpf128 F -+GLIBC_2.27 ufromfpf32 F -+GLIBC_2.27 ufromfpf32x F -+GLIBC_2.27 ufromfpf64 F -+GLIBC_2.27 ufromfpf64x F -+GLIBC_2.27 ufromfpl F -+GLIBC_2.27 ufromfpx F -+GLIBC_2.27 ufromfpxf F -+GLIBC_2.27 ufromfpxf128 F -+GLIBC_2.27 ufromfpxf32 F -+GLIBC_2.27 ufromfpxf32x F -+GLIBC_2.27 ufromfpxf64 F -+GLIBC_2.27 ufromfpxf64x F -+GLIBC_2.27 ufromfpxl F -+GLIBC_2.27 y0 F -+GLIBC_2.27 y0f F -+GLIBC_2.27 y0f128 F -+GLIBC_2.27 y0f32 F -+GLIBC_2.27 y0f32x F -+GLIBC_2.27 y0f64 F -+GLIBC_2.27 y0f64x F -+GLIBC_2.27 y0l F -+GLIBC_2.27 y1 F -+GLIBC_2.27 y1f F -+GLIBC_2.27 y1f128 F -+GLIBC_2.27 y1f32 F -+GLIBC_2.27 y1f32x F -+GLIBC_2.27 y1f64 F -+GLIBC_2.27 y1f64x F -+GLIBC_2.27 y1l F -+GLIBC_2.27 yn F -+GLIBC_2.27 ynf F -+GLIBC_2.27 ynf128 F -+GLIBC_2.27 ynf32 F -+GLIBC_2.27 ynf32x F -+GLIBC_2.27 ynf64 F -+GLIBC_2.27 ynf64x F -+GLIBC_2.27 ynl F -+GLIBC_2.28 daddl F -+GLIBC_2.28 ddivl F -+GLIBC_2.28 dmull F -+GLIBC_2.28 dsubl F -+GLIBC_2.28 f32addf128 F -+GLIBC_2.28 f32addf32x F -+GLIBC_2.28 f32addf64 F -+GLIBC_2.28 f32addf64x F -+GLIBC_2.28 f32divf128 F -+GLIBC_2.28 f32divf32x F -+GLIBC_2.28 f32divf64 F -+GLIBC_2.28 f32divf64x F -+GLIBC_2.28 f32mulf128 F -+GLIBC_2.28 f32mulf32x F -+GLIBC_2.28 f32mulf64 F -+GLIBC_2.28 f32mulf64x F -+GLIBC_2.28 f32subf128 F -+GLIBC_2.28 f32subf32x F -+GLIBC_2.28 f32subf64 F -+GLIBC_2.28 f32subf64x F -+GLIBC_2.28 f32xaddf128 F -+GLIBC_2.28 f32xaddf64 F -+GLIBC_2.28 f32xaddf64x F -+GLIBC_2.28 f32xdivf128 F -+GLIBC_2.28 f32xdivf64 F -+GLIBC_2.28 f32xdivf64x F -+GLIBC_2.28 f32xmulf128 F -+GLIBC_2.28 f32xmulf64 F -+GLIBC_2.28 f32xmulf64x F -+GLIBC_2.28 f32xsubf128 F -+GLIBC_2.28 f32xsubf64 F -+GLIBC_2.28 f32xsubf64x F -+GLIBC_2.28 f64addf128 F -+GLIBC_2.28 f64addf64x F -+GLIBC_2.28 f64divf128 F -+GLIBC_2.28 f64divf64x F -+GLIBC_2.28 f64mulf128 F -+GLIBC_2.28 f64mulf64x F -+GLIBC_2.28 f64subf128 F -+GLIBC_2.28 f64subf64x F -+GLIBC_2.28 f64xaddf128 F -+GLIBC_2.28 f64xdivf128 F -+GLIBC_2.28 f64xmulf128 F -+GLIBC_2.28 f64xsubf128 F -+GLIBC_2.28 fadd F -+GLIBC_2.28 faddl F -+GLIBC_2.28 fdiv F -+GLIBC_2.28 fdivl F -+GLIBC_2.28 fmul F -+GLIBC_2.28 fmull F -+GLIBC_2.28 fsub F -+GLIBC_2.28 fsubl F -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libnsl.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libnsl.abilist -new file mode 100644 -index 00000000..0767472d ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libnsl.abilist -@@ -0,0 +1,120 @@ -+GLIBC_2.27 __free_fdresult F -+GLIBC_2.27 __nis_default_access F -+GLIBC_2.27 __nis_default_group F -+GLIBC_2.27 __nis_default_owner F -+GLIBC_2.27 __nis_default_ttl F -+GLIBC_2.27 __nis_finddirectory F -+GLIBC_2.27 __nisbind_connect F -+GLIBC_2.27 __nisbind_create F -+GLIBC_2.27 __nisbind_destroy F -+GLIBC_2.27 __nisbind_next F -+GLIBC_2.27 __yp_check F -+GLIBC_2.27 nis_add F -+GLIBC_2.27 nis_add_entry F -+GLIBC_2.27 nis_addmember F -+GLIBC_2.27 nis_checkpoint F -+GLIBC_2.27 nis_clone_directory F -+GLIBC_2.27 nis_clone_object F -+GLIBC_2.27 nis_clone_result F -+GLIBC_2.27 nis_creategroup F -+GLIBC_2.27 nis_destroy_object F -+GLIBC_2.27 nis_destroygroup F -+GLIBC_2.27 nis_dir_cmp F -+GLIBC_2.27 nis_domain_of F -+GLIBC_2.27 nis_domain_of_r F -+GLIBC_2.27 nis_first_entry F -+GLIBC_2.27 nis_free_directory F -+GLIBC_2.27 nis_free_object F -+GLIBC_2.27 nis_free_request F -+GLIBC_2.27 nis_freenames F -+GLIBC_2.27 nis_freeresult F -+GLIBC_2.27 nis_freeservlist F -+GLIBC_2.27 nis_freetags F -+GLIBC_2.27 nis_getnames F -+GLIBC_2.27 nis_getservlist F -+GLIBC_2.27 nis_ismember F -+GLIBC_2.27 nis_leaf_of F -+GLIBC_2.27 nis_leaf_of_r F -+GLIBC_2.27 nis_lerror F -+GLIBC_2.27 nis_list F -+GLIBC_2.27 nis_local_directory F -+GLIBC_2.27 nis_local_group F -+GLIBC_2.27 nis_local_host F -+GLIBC_2.27 nis_local_principal F -+GLIBC_2.27 nis_lookup F -+GLIBC_2.27 nis_mkdir F -+GLIBC_2.27 nis_modify F -+GLIBC_2.27 nis_modify_entry F -+GLIBC_2.27 nis_name_of F -+GLIBC_2.27 nis_name_of_r F -+GLIBC_2.27 nis_next_entry F -+GLIBC_2.27 nis_perror F -+GLIBC_2.27 nis_ping F -+GLIBC_2.27 nis_print_directory F -+GLIBC_2.27 nis_print_entry F -+GLIBC_2.27 nis_print_group F -+GLIBC_2.27 nis_print_group_entry F -+GLIBC_2.27 nis_print_link F -+GLIBC_2.27 nis_print_object F -+GLIBC_2.27 nis_print_result F -+GLIBC_2.27 nis_print_rights F -+GLIBC_2.27 nis_print_table F -+GLIBC_2.27 nis_read_obj F -+GLIBC_2.27 nis_remove F -+GLIBC_2.27 nis_remove_entry F -+GLIBC_2.27 nis_removemember F -+GLIBC_2.27 nis_rmdir F -+GLIBC_2.27 nis_servstate F -+GLIBC_2.27 nis_sperrno F -+GLIBC_2.27 nis_sperror F -+GLIBC_2.27 nis_sperror_r F -+GLIBC_2.27 nis_stats F -+GLIBC_2.27 nis_verifygroup F -+GLIBC_2.27 nis_write_obj F -+GLIBC_2.27 readColdStartFile F -+GLIBC_2.27 writeColdStartFile F -+GLIBC_2.27 xdr_cback_data F -+GLIBC_2.27 xdr_domainname F -+GLIBC_2.27 xdr_keydat F -+GLIBC_2.27 xdr_mapname F -+GLIBC_2.27 xdr_obj_p F -+GLIBC_2.27 xdr_peername F -+GLIBC_2.27 xdr_valdat F -+GLIBC_2.27 xdr_yp_buf F -+GLIBC_2.27 xdr_ypall F -+GLIBC_2.27 xdr_ypbind_binding F -+GLIBC_2.27 xdr_ypbind_resp F -+GLIBC_2.27 xdr_ypbind_resptype F -+GLIBC_2.27 xdr_ypbind_setdom F -+GLIBC_2.27 xdr_ypdelete_args F -+GLIBC_2.27 xdr_ypmap_parms F -+GLIBC_2.27 xdr_ypmaplist F -+GLIBC_2.27 xdr_yppush_status F -+GLIBC_2.27 xdr_yppushresp_xfr F -+GLIBC_2.27 xdr_ypreq_key F -+GLIBC_2.27 xdr_ypreq_nokey F -+GLIBC_2.27 xdr_ypreq_xfr F -+GLIBC_2.27 xdr_ypresp_all F -+GLIBC_2.27 xdr_ypresp_key_val F -+GLIBC_2.27 xdr_ypresp_maplist F -+GLIBC_2.27 xdr_ypresp_master F -+GLIBC_2.27 xdr_ypresp_order F -+GLIBC_2.27 xdr_ypresp_val F -+GLIBC_2.27 xdr_ypresp_xfr F -+GLIBC_2.27 xdr_ypstat F -+GLIBC_2.27 xdr_ypupdate_args F -+GLIBC_2.27 xdr_ypxfrstat F -+GLIBC_2.27 yp_all F -+GLIBC_2.27 yp_bind F -+GLIBC_2.27 yp_first F -+GLIBC_2.27 yp_get_default_domain F -+GLIBC_2.27 yp_maplist F -+GLIBC_2.27 yp_master F -+GLIBC_2.27 yp_match F -+GLIBC_2.27 yp_next F -+GLIBC_2.27 yp_order F -+GLIBC_2.27 yp_unbind F -+GLIBC_2.27 yp_update F -+GLIBC_2.27 ypbinderr_string F -+GLIBC_2.27 yperr_string F -+GLIBC_2.27 ypprot_err F -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libpthread.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libpthread.abilist -new file mode 100644 -index 00000000..f60b22ef ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libpthread.abilist -@@ -0,0 +1,264 @@ -+GLIBC_2.0 _IO_flockfile F -+GLIBC_2.0 _IO_ftrylockfile F -+GLIBC_2.0 _IO_funlockfile F -+GLIBC_2.0 __close F -+GLIBC_2.0 __connect F -+GLIBC_2.0 __errno_location F -+GLIBC_2.0 __fcntl F -+GLIBC_2.0 __fork F -+GLIBC_2.0 __h_errno_location F -+GLIBC_2.0 __lseek F -+GLIBC_2.0 __open F -+GLIBC_2.0 __pthread_getspecific F -+GLIBC_2.0 __pthread_key_create F -+GLIBC_2.0 __pthread_mutex_destroy F -+GLIBC_2.0 __pthread_mutex_init F -+GLIBC_2.0 __pthread_mutex_lock F -+GLIBC_2.0 __pthread_mutex_trylock F -+GLIBC_2.0 __pthread_mutex_unlock F -+GLIBC_2.0 __pthread_mutexattr_destroy F -+GLIBC_2.0 __pthread_mutexattr_init F -+GLIBC_2.0 __pthread_mutexattr_settype F -+GLIBC_2.0 __pthread_once F -+GLIBC_2.0 __pthread_setspecific F -+GLIBC_2.0 __read F -+GLIBC_2.0 __send F -+GLIBC_2.0 __sigaction F -+GLIBC_2.0 __wait F -+GLIBC_2.0 __write F -+GLIBC_2.0 _pthread_cleanup_pop F -+GLIBC_2.0 _pthread_cleanup_pop_restore F -+GLIBC_2.0 _pthread_cleanup_push F -+GLIBC_2.0 _pthread_cleanup_push_defer F -+GLIBC_2.0 accept F -+GLIBC_2.0 close F -+GLIBC_2.0 connect F -+GLIBC_2.0 fcntl F -+GLIBC_2.0 flockfile F -+GLIBC_2.0 fork F -+GLIBC_2.0 fsync F -+GLIBC_2.0 ftrylockfile F -+GLIBC_2.0 funlockfile F -+GLIBC_2.0 longjmp F -+GLIBC_2.0 lseek F -+GLIBC_2.0 msync F -+GLIBC_2.0 nanosleep F -+GLIBC_2.0 open F -+GLIBC_2.0 pause F -+GLIBC_2.0 pthread_atfork F -+GLIBC_2.0 pthread_attr_destroy F -+GLIBC_2.0 pthread_attr_getdetachstate F -+GLIBC_2.0 pthread_attr_getinheritsched F -+GLIBC_2.0 pthread_attr_getschedparam F -+GLIBC_2.0 pthread_attr_getschedpolicy F -+GLIBC_2.0 pthread_attr_getscope F -+GLIBC_2.0 pthread_attr_init F -+GLIBC_2.0 pthread_attr_setdetachstate F -+GLIBC_2.0 pthread_attr_setinheritsched F -+GLIBC_2.0 pthread_attr_setschedparam F -+GLIBC_2.0 pthread_attr_setschedpolicy F -+GLIBC_2.0 pthread_attr_setscope F -+GLIBC_2.0 pthread_cancel F -+GLIBC_2.0 pthread_cond_broadcast F -+GLIBC_2.0 pthread_cond_destroy F -+GLIBC_2.0 pthread_cond_init F -+GLIBC_2.0 pthread_cond_signal F -+GLIBC_2.0 pthread_cond_timedwait F -+GLIBC_2.0 pthread_cond_wait F -+GLIBC_2.0 pthread_condattr_destroy F -+GLIBC_2.0 pthread_condattr_init F -+GLIBC_2.0 pthread_create F -+GLIBC_2.0 pthread_detach F -+GLIBC_2.0 pthread_equal F -+GLIBC_2.0 pthread_exit F -+GLIBC_2.0 pthread_getschedparam F -+GLIBC_2.0 pthread_getspecific F -+GLIBC_2.0 pthread_join F -+GLIBC_2.0 pthread_key_create F -+GLIBC_2.0 pthread_key_delete F -+GLIBC_2.0 pthread_kill F -+GLIBC_2.0 pthread_kill_other_threads_np F -+GLIBC_2.0 pthread_mutex_destroy F -+GLIBC_2.0 pthread_mutex_init F -+GLIBC_2.0 pthread_mutex_lock F -+GLIBC_2.0 pthread_mutex_trylock F -+GLIBC_2.0 pthread_mutex_unlock F -+GLIBC_2.0 pthread_mutexattr_destroy F -+GLIBC_2.0 pthread_mutexattr_getkind_np F -+GLIBC_2.0 pthread_mutexattr_init F -+GLIBC_2.0 pthread_mutexattr_setkind_np F -+GLIBC_2.0 pthread_once F -+GLIBC_2.0 pthread_self F -+GLIBC_2.0 pthread_setcancelstate F -+GLIBC_2.0 pthread_setcanceltype F -+GLIBC_2.0 pthread_setschedparam F -+GLIBC_2.0 pthread_setspecific F -+GLIBC_2.0 pthread_sigmask F -+GLIBC_2.0 pthread_testcancel F -+GLIBC_2.0 raise F -+GLIBC_2.0 read F -+GLIBC_2.0 recv F -+GLIBC_2.0 recvfrom F -+GLIBC_2.0 recvmsg F -+GLIBC_2.0 sem_destroy F -+GLIBC_2.0 sem_getvalue F -+GLIBC_2.0 sem_init F -+GLIBC_2.0 sem_post F -+GLIBC_2.0 sem_trywait F -+GLIBC_2.0 sem_wait F -+GLIBC_2.0 send F -+GLIBC_2.0 sendmsg F -+GLIBC_2.0 sendto F -+GLIBC_2.0 sigaction F -+GLIBC_2.0 siglongjmp F -+GLIBC_2.0 sigwait F -+GLIBC_2.0 system F -+GLIBC_2.0 tcdrain F -+GLIBC_2.0 wait F -+GLIBC_2.0 waitpid F -+GLIBC_2.0 write F -+GLIBC_2.11 pthread_sigqueue F -+GLIBC_2.12 pthread_getname_np F -+GLIBC_2.12 pthread_mutex_consistent F -+GLIBC_2.12 pthread_mutexattr_getrobust F -+GLIBC_2.12 pthread_mutexattr_setrobust F -+GLIBC_2.12 pthread_setname_np F -+GLIBC_2.18 pthread_getattr_default_np F -+GLIBC_2.18 pthread_setattr_default_np F -+GLIBC_2.2 __libc_allocate_rtsig F -+GLIBC_2.2 __libc_current_sigrtmax F -+GLIBC_2.2 __libc_current_sigrtmin F -+GLIBC_2.2 __open64 F -+GLIBC_2.2 __pread64 F -+GLIBC_2.2 __pthread_rwlock_destroy F -+GLIBC_2.2 __pthread_rwlock_init F -+GLIBC_2.2 __pthread_rwlock_rdlock F -+GLIBC_2.2 __pthread_rwlock_tryrdlock F -+GLIBC_2.2 __pthread_rwlock_trywrlock F -+GLIBC_2.2 __pthread_rwlock_unlock F -+GLIBC_2.2 __pthread_rwlock_wrlock F -+GLIBC_2.2 __pwrite64 F -+GLIBC_2.2 __res_state F -+GLIBC_2.2 lseek64 F -+GLIBC_2.2 open64 F -+GLIBC_2.2 pread F -+GLIBC_2.2 pread64 F -+GLIBC_2.2 pthread_attr_getguardsize F -+GLIBC_2.2 pthread_attr_getstack F -+GLIBC_2.2 pthread_attr_getstackaddr F -+GLIBC_2.2 pthread_attr_getstacksize F -+GLIBC_2.2 pthread_attr_init F -+GLIBC_2.2 pthread_attr_setguardsize F -+GLIBC_2.2 pthread_attr_setstack F -+GLIBC_2.2 pthread_attr_setstackaddr F -+GLIBC_2.2 pthread_attr_setstacksize F -+GLIBC_2.2 pthread_barrier_destroy F -+GLIBC_2.2 pthread_barrier_init F -+GLIBC_2.2 pthread_barrier_wait F -+GLIBC_2.2 pthread_barrierattr_destroy F -+GLIBC_2.2 pthread_barrierattr_init F -+GLIBC_2.2 pthread_barrierattr_setpshared F -+GLIBC_2.2 pthread_condattr_getpshared F -+GLIBC_2.2 pthread_condattr_setpshared F -+GLIBC_2.2 pthread_create F -+GLIBC_2.2 pthread_getconcurrency F -+GLIBC_2.2 pthread_getcpuclockid F -+GLIBC_2.2 pthread_mutex_timedlock F -+GLIBC_2.2 pthread_mutexattr_getpshared F -+GLIBC_2.2 pthread_mutexattr_gettype F -+GLIBC_2.2 pthread_mutexattr_setpshared F -+GLIBC_2.2 pthread_mutexattr_settype F -+GLIBC_2.2 pthread_rwlock_destroy F -+GLIBC_2.2 pthread_rwlock_init F -+GLIBC_2.2 pthread_rwlock_rdlock F -+GLIBC_2.2 pthread_rwlock_timedrdlock F -+GLIBC_2.2 pthread_rwlock_timedwrlock F -+GLIBC_2.2 pthread_rwlock_tryrdlock F -+GLIBC_2.2 pthread_rwlock_trywrlock F -+GLIBC_2.2 pthread_rwlock_unlock F -+GLIBC_2.2 pthread_rwlock_wrlock F -+GLIBC_2.2 pthread_rwlockattr_destroy F -+GLIBC_2.2 pthread_rwlockattr_getkind_np F -+GLIBC_2.2 pthread_rwlockattr_getpshared F -+GLIBC_2.2 pthread_rwlockattr_init F -+GLIBC_2.2 pthread_rwlockattr_setkind_np F -+GLIBC_2.2 pthread_rwlockattr_setpshared F -+GLIBC_2.2 pthread_setconcurrency F -+GLIBC_2.2 pthread_spin_destroy F -+GLIBC_2.2 pthread_spin_init F -+GLIBC_2.2 pthread_spin_lock F -+GLIBC_2.2 pthread_spin_trylock F -+GLIBC_2.2 pthread_spin_unlock F -+GLIBC_2.2 pthread_yield F -+GLIBC_2.2 pwrite F -+GLIBC_2.2 pwrite64 F -+GLIBC_2.2 sem_close F -+GLIBC_2.2 sem_destroy F -+GLIBC_2.2 sem_getvalue F -+GLIBC_2.2 sem_init F -+GLIBC_2.2 sem_open F -+GLIBC_2.2 sem_post F -+GLIBC_2.2 sem_timedwait F -+GLIBC_2.2 sem_trywait F -+GLIBC_2.2 sem_unlink F -+GLIBC_2.2 sem_wait F -+GLIBC_2.2.3 pthread_getattr_np F -+GLIBC_2.2.6 __nanosleep F -+GLIBC_2.28 call_once F -+GLIBC_2.28 cnd_broadcast F -+GLIBC_2.28 cnd_destroy F -+GLIBC_2.28 cnd_init F -+GLIBC_2.28 cnd_signal F -+GLIBC_2.28 cnd_timedwait F -+GLIBC_2.28 cnd_wait F -+GLIBC_2.28 mtx_destroy F -+GLIBC_2.28 mtx_init F -+GLIBC_2.28 mtx_lock F -+GLIBC_2.28 mtx_timedlock F -+GLIBC_2.28 mtx_trylock F -+GLIBC_2.28 mtx_unlock F -+GLIBC_2.28 thrd_create F -+GLIBC_2.28 thrd_detach F -+GLIBC_2.28 thrd_exit F -+GLIBC_2.28 thrd_join F -+GLIBC_2.28 tss_create F -+GLIBC_2.28 tss_delete F -+GLIBC_2.28 tss_get F -+GLIBC_2.28 tss_set F -+GLIBC_2.3.2 pthread_cond_broadcast F -+GLIBC_2.3.2 pthread_cond_destroy F -+GLIBC_2.3.2 pthread_cond_init F -+GLIBC_2.3.2 pthread_cond_signal F -+GLIBC_2.3.2 pthread_cond_timedwait F -+GLIBC_2.3.2 pthread_cond_wait F -+GLIBC_2.3.3 __pthread_cleanup_routine F -+GLIBC_2.3.3 __pthread_register_cancel F -+GLIBC_2.3.3 __pthread_register_cancel_defer F -+GLIBC_2.3.3 __pthread_unregister_cancel F -+GLIBC_2.3.3 __pthread_unregister_cancel_restore F -+GLIBC_2.3.3 __pthread_unwind_next F -+GLIBC_2.3.3 pthread_attr_getaffinity_np F -+GLIBC_2.3.3 pthread_attr_setaffinity_np F -+GLIBC_2.3.3 pthread_attr_setstack F -+GLIBC_2.3.3 pthread_attr_setstacksize F -+GLIBC_2.3.3 pthread_barrierattr_getpshared F -+GLIBC_2.3.3 pthread_condattr_getclock F -+GLIBC_2.3.3 pthread_condattr_setclock F -+GLIBC_2.3.3 pthread_getaffinity_np F -+GLIBC_2.3.3 pthread_setaffinity_np F -+GLIBC_2.3.3 pthread_timedjoin_np F -+GLIBC_2.3.3 pthread_tryjoin_np F -+GLIBC_2.3.4 pthread_attr_getaffinity_np F -+GLIBC_2.3.4 pthread_attr_setaffinity_np F -+GLIBC_2.3.4 pthread_getaffinity_np F -+GLIBC_2.3.4 pthread_setaffinity_np F -+GLIBC_2.3.4 pthread_setschedprio F -+GLIBC_2.4 pthread_mutex_consistent_np F -+GLIBC_2.4 pthread_mutex_getprioceiling F -+GLIBC_2.4 pthread_mutex_setprioceiling F -+GLIBC_2.4 pthread_mutexattr_getprioceiling F -+GLIBC_2.4 pthread_mutexattr_getprotocol F -+GLIBC_2.4 pthread_mutexattr_getrobust_np F -+GLIBC_2.4 pthread_mutexattr_setprioceiling F -+GLIBC_2.4 pthread_mutexattr_setprotocol F -+GLIBC_2.4 pthread_mutexattr_setrobust_np F -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libresolv.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libresolv.abilist -new file mode 100644 -index 00000000..eb9c1cb7 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libresolv.abilist -@@ -0,0 +1,79 @@ -+GLIBC_2.27 __b64_ntop F -+GLIBC_2.27 __b64_pton F -+GLIBC_2.27 __dn_comp F -+GLIBC_2.27 __dn_count_labels F -+GLIBC_2.27 __dn_expand F -+GLIBC_2.27 __dn_skipname F -+GLIBC_2.27 __fp_nquery F -+GLIBC_2.27 __fp_query F -+GLIBC_2.27 __fp_resstat F -+GLIBC_2.27 __hostalias F -+GLIBC_2.27 __loc_aton F -+GLIBC_2.27 __loc_ntoa F -+GLIBC_2.27 __p_cdname F -+GLIBC_2.27 __p_cdnname F -+GLIBC_2.27 __p_class F -+GLIBC_2.27 __p_class_syms D 0xa8 -+GLIBC_2.27 __p_fqname F -+GLIBC_2.27 __p_fqnname F -+GLIBC_2.27 __p_option F -+GLIBC_2.27 __p_query F -+GLIBC_2.27 __p_rcode F -+GLIBC_2.27 __p_time F -+GLIBC_2.27 __p_type F -+GLIBC_2.27 __p_type_syms D 0x450 -+GLIBC_2.27 __putlong F -+GLIBC_2.27 __putshort F -+GLIBC_2.27 __res_close F -+GLIBC_2.27 __res_dnok F -+GLIBC_2.27 __res_hnok F -+GLIBC_2.27 __res_hostalias F -+GLIBC_2.27 __res_isourserver F -+GLIBC_2.27 __res_mailok F -+GLIBC_2.27 __res_mkquery F -+GLIBC_2.27 __res_nameinquery F -+GLIBC_2.27 __res_nmkquery F -+GLIBC_2.27 __res_nquery F -+GLIBC_2.27 __res_nquerydomain F -+GLIBC_2.27 __res_nsearch F -+GLIBC_2.27 __res_nsend F -+GLIBC_2.27 __res_ownok F -+GLIBC_2.27 __res_queriesmatch F -+GLIBC_2.27 __res_query F -+GLIBC_2.27 __res_querydomain F -+GLIBC_2.27 __res_search F -+GLIBC_2.27 __res_send F -+GLIBC_2.27 __sym_ntop F -+GLIBC_2.27 __sym_ntos F -+GLIBC_2.27 __sym_ston F -+GLIBC_2.27 _getlong F -+GLIBC_2.27 _getshort F -+GLIBC_2.27 inet_net_ntop F -+GLIBC_2.27 inet_net_pton F -+GLIBC_2.27 inet_neta F -+GLIBC_2.27 ns_datetosecs F -+GLIBC_2.27 ns_format_ttl F -+GLIBC_2.27 ns_get16 F -+GLIBC_2.27 ns_get32 F -+GLIBC_2.27 ns_initparse F -+GLIBC_2.27 ns_makecanon F -+GLIBC_2.27 ns_msg_getflag F -+GLIBC_2.27 ns_name_compress F -+GLIBC_2.27 ns_name_ntol F -+GLIBC_2.27 ns_name_ntop F -+GLIBC_2.27 ns_name_pack F -+GLIBC_2.27 ns_name_pton F -+GLIBC_2.27 ns_name_rollback F -+GLIBC_2.27 ns_name_skip F -+GLIBC_2.27 ns_name_uncompress F -+GLIBC_2.27 ns_name_unpack F -+GLIBC_2.27 ns_parse_ttl F -+GLIBC_2.27 ns_parserr F -+GLIBC_2.27 ns_put16 F -+GLIBC_2.27 ns_put32 F -+GLIBC_2.27 ns_samedomain F -+GLIBC_2.27 ns_samename F -+GLIBC_2.27 ns_skiprr F -+GLIBC_2.27 ns_sprintrr F -+GLIBC_2.27 ns_sprintrrf F -+GLIBC_2.27 ns_subdomain F -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/librt.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/librt.abilist -new file mode 100644 -index 00000000..bfd262ec ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/librt.abilist -@@ -0,0 +1,35 @@ -+GLIBC_2.27 __mq_open_2 F -+GLIBC_2.27 aio_cancel F -+GLIBC_2.27 aio_cancel64 F -+GLIBC_2.27 aio_error F -+GLIBC_2.27 aio_error64 F -+GLIBC_2.27 aio_fsync F -+GLIBC_2.27 aio_fsync64 F -+GLIBC_2.27 aio_init F -+GLIBC_2.27 aio_read F -+GLIBC_2.27 aio_read64 F -+GLIBC_2.27 aio_return F -+GLIBC_2.27 aio_return64 F -+GLIBC_2.27 aio_suspend F -+GLIBC_2.27 aio_suspend64 F -+GLIBC_2.27 aio_write F -+GLIBC_2.27 aio_write64 F -+GLIBC_2.27 lio_listio F -+GLIBC_2.27 lio_listio64 F -+GLIBC_2.27 mq_close F -+GLIBC_2.27 mq_getattr F -+GLIBC_2.27 mq_notify F -+GLIBC_2.27 mq_open F -+GLIBC_2.27 mq_receive F -+GLIBC_2.27 mq_send F -+GLIBC_2.27 mq_setattr F -+GLIBC_2.27 mq_timedreceive F -+GLIBC_2.27 mq_timedsend F -+GLIBC_2.27 mq_unlink F -+GLIBC_2.27 shm_open F -+GLIBC_2.27 shm_unlink F -+GLIBC_2.27 timer_create F -+GLIBC_2.27 timer_delete F -+GLIBC_2.27 timer_getoverrun F -+GLIBC_2.27 timer_gettime F -+GLIBC_2.27 timer_settime F -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libthread_db.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libthread_db.abilist -new file mode 100644 -index 00000000..4122e563 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libthread_db.abilist -@@ -0,0 +1,40 @@ -+GLIBC_2.27 td_init F -+GLIBC_2.27 td_log F -+GLIBC_2.27 td_symbol_list F -+GLIBC_2.27 td_ta_clear_event F -+GLIBC_2.27 td_ta_delete F -+GLIBC_2.27 td_ta_enable_stats F -+GLIBC_2.27 td_ta_event_addr F -+GLIBC_2.27 td_ta_event_getmsg F -+GLIBC_2.27 td_ta_get_nthreads F -+GLIBC_2.27 td_ta_get_ph F -+GLIBC_2.27 td_ta_get_stats F -+GLIBC_2.27 td_ta_map_id2thr F -+GLIBC_2.27 td_ta_map_lwp2thr F -+GLIBC_2.27 td_ta_new F -+GLIBC_2.27 td_ta_reset_stats F -+GLIBC_2.27 td_ta_set_event F -+GLIBC_2.27 td_ta_setconcurrency F -+GLIBC_2.27 td_ta_thr_iter F -+GLIBC_2.27 td_ta_tsd_iter F -+GLIBC_2.27 td_thr_clear_event F -+GLIBC_2.27 td_thr_dbresume F -+GLIBC_2.27 td_thr_dbsuspend F -+GLIBC_2.27 td_thr_event_enable F -+GLIBC_2.27 td_thr_event_getmsg F -+GLIBC_2.27 td_thr_get_info F -+GLIBC_2.27 td_thr_getfpregs F -+GLIBC_2.27 td_thr_getgregs F -+GLIBC_2.27 td_thr_getxregs F -+GLIBC_2.27 td_thr_getxregsize F -+GLIBC_2.27 td_thr_set_event F -+GLIBC_2.27 td_thr_setfpregs F -+GLIBC_2.27 td_thr_setgregs F -+GLIBC_2.27 td_thr_setprio F -+GLIBC_2.27 td_thr_setsigpending F -+GLIBC_2.27 td_thr_setxregs F -+GLIBC_2.27 td_thr_sigsetmask F -+GLIBC_2.27 td_thr_tls_get_addr F -+GLIBC_2.27 td_thr_tlsbase F -+GLIBC_2.27 td_thr_tsd F -+GLIBC_2.27 td_thr_validate F -diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libutil.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libutil.abilist -new file mode 100644 -index 00000000..cbfec8d4 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libutil.abilist -@@ -0,0 +1,6 @@ -+GLIBC_2.27 forkpty F -+GLIBC_2.27 login F -+GLIBC_2.27 login_tty F -+GLIBC_2.27 logout F -+GLIBC_2.27 logwtmp F -+GLIBC_2.27 openpty F -diff --git a/sysdeps/unix/sysv/linux/loongarch/makecontext.c b/sysdeps/unix/sysv/linux/loongarch/makecontext.c -new file mode 100644 -index 00000000..55d509ab ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/makecontext.c -@@ -0,0 +1,78 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+void -+__makecontext (ucontext_t *ucp, void (*func) (void), int argc, -+ long int a0, long int a1, long int a2, long int a3, long int a4, -+ ...) -+{ -+ extern void __start_context (void) attribute_hidden; -+ long int i, sp; -+ -+ _Static_assert (LARCH_REG_NARGS == 8, "__makecontext assumes 8 argument registers"); -+ -+ /* Set up the stack. */ -+ sp = ((long int) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size) & ALMASK; -+ -+ /* Set up the register context. -+ ra = s0 = 0, terminating the stack for backtracing purposes. -+ s1 = the function we must call. -+ s2 = the subsequent context to run. */ -+ ucp->uc_mcontext.__gregs[LARCH_REG_RA] = 0; -+ ucp->uc_mcontext.__gregs[LARCH_REG_S0] = 0; -+ ucp->uc_mcontext.__gregs[LARCH_REG_S1] = (long int) func; -+ ucp->uc_mcontext.__gregs[LARCH_REG_S2] = (long int) ucp->uc_link; -+ ucp->uc_mcontext.__gregs[LARCH_REG_SP] = sp; -+ ucp->uc_mcontext.__pc = (long int) &__start_context; -+ -+ /* Put args in a0-a7, then put any remaining args on the stack. */ -+ ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 0] = a0; -+ ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 1] = a1; -+ ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 2] = a2; -+ ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 3] = a3; -+ ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 4] = a4; -+ -+ if (__glibc_unlikely (argc > 5)) -+ { -+ va_list vl; -+ va_start (vl, a4); -+ -+ long reg_args = argc < LARCH_REG_NARGS ? argc : LARCH_REG_NARGS; -+ for (i = 5; i < reg_args; i++) -+ ucp->uc_mcontext.__gregs[LARCH_REG_A0 + i] = va_arg (vl, long); -+ -+ long int stack_args = argc - reg_args; -+ if (stack_args > 0) -+ { -+ sp = (sp - stack_args * sizeof (long int)) & ALMASK; -+ ucp->uc_mcontext.__gregs[LARCH_REG_SP] = sp; -+ for (i = 0; i < stack_args; i++) -+ ((long int *) sp)[i] = va_arg (vl, long int); -+ } -+ -+ va_end (vl); -+ } -+} -+ -+weak_alias (__makecontext, makecontext) -diff --git a/sysdeps/unix/sysv/linux/loongarch/profil-counter.h b/sysdeps/unix/sysv/linux/loongarch/profil-counter.h -new file mode 100644 -index 00000000..6a3cc201 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/profil-counter.h -@@ -0,0 +1,31 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+#include -+ -+static void -+__profil_counter (int signo, const SIGCONTEXT scp) -+{ -+ profil_count ((void *) GET_PC (scp)); -+ -+ /* This is a hack to prevent the compiler from implementing the -+ above function call as a sibcall. The sibcall would overwrite -+ the signal context. */ -+ asm volatile (""); -+} -diff --git a/sysdeps/unix/sysv/linux/loongarch/pt-vfork.S b/sysdeps/unix/sysv/linux/loongarch/pt-vfork.S -new file mode 100644 -index 00000000..1cc89317 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/pt-vfork.S -@@ -0,0 +1 @@ -+/* Not needed. */ -diff --git a/sysdeps/unix/sysv/linux/loongarch/register-dump.h b/sysdeps/unix/sysv/linux/loongarch/register-dump.h -new file mode 100644 -index 00000000..5e45d5c7 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/register-dump.h -@@ -0,0 +1,63 @@ -+/* Dump registers. -+ Copyright (C) 2000-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+#include -+#include <_itoa.h> -+ -+static void -+hexvalue (unsigned long int value, char *buf, size_t len) -+{ -+ char *cp = _itoa_word (value, buf + len, 16, 0); -+ while (cp > buf) -+ *--cp = '0'; -+} -+ -+#define REGDUMP_NREGS 32 -+#define REGDUMP_PER_LINE (80 / (__WORDSIZE / 4 + 4)) -+ -+static void -+register_dump (int fd, ucontext_t *ctx) -+{ -+ int i; -+ char regvalue[__WORDSIZE / 4 + 1]; -+ char str[82 * ((REGDUMP_NREGS + REGDUMP_PER_LINE - 1) / REGDUMP_PER_LINE)]; -+ -+ static const char names[REGDUMP_NREGS][4] = { -+ "pc", "ra", "tp", "sp", "a0", "a1", "a2", "a3", -+ "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", -+ "t4", "t5", "t6", "t7", "t8", "x" , "fp", "s0", -+ "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8" -+ }; -+ -+ str[0] = 0; -+ for (i = 0; i < REGDUMP_NREGS; i++) -+ { -+ strcat (str, names[i]); -+ strcat (str, " "); -+ hexvalue (ctx->uc_mcontext.__gregs[i], regvalue, __WORDSIZE / 4); -+ strcat (str, regvalue); -+ -+ if ((i + 1) % REGDUMP_PER_LINE == 0) -+ strcat (str, "\n"); -+ } -+ -+ write (fd, str, strlen (str)); -+} -+ -+#define REGISTER_DUMP register_dump (fd, ctx) -diff --git a/sysdeps/unix/sysv/linux/loongarch/setcontext.S b/sysdeps/unix/sysv/linux/loongarch/setcontext.S -new file mode 100644 -index 00000000..c96ec43c ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/setcontext.S -@@ -0,0 +1,111 @@ -+/* Set current context. -+ Copyright (C) 2009-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+#include "sys/regdef.h" -+#include "ucontext-macros.h" -+ -+/* int __setcontext (const ucontext_t *ucp) -+ -+ Restores the machine context in UCP and thereby resumes execution -+ in that context. -+ -+ This implementation is intended to be used for *synchronous* context -+ switches only. Therefore, it does not have to restore anything -+ other than the PRESERVED state. */ -+ -+ .text -+LEAF (__setcontext) -+ -+ addi.d sp, sp, -16 -+ st.d a0, sp, 0 /* Save ucp to stack. */ -+/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8) */ -+ li.d a3, _NSIG8 -+ li.d a2, 0 -+ addi.d a1, a0, UCONTEXT_SIGMASK -+ li.d a0, SIG_SETMASK -+ -+ li.d a7, SYS_ify (rt_sigprocmask) -+ syscall 0 -+ -+ blt a0, $r0, 99f -+ -+ ld.d t0, sp, 0 /* Load ucp to t0. */ -+ cfi_def_cfa (12, 0) -+ -+#ifndef __loongarch_soft_float -+ ld.w t1, t0, MCONTEXT_FCSR -+ -+ RESTORE_FP_REG (fs0, 24, t0) -+ RESTORE_FP_REG (fs1, 25, t0) -+ RESTORE_FP_REG (fs2, 26, t0) -+ RESTORE_FP_REG (fs3, 27, t0) -+ RESTORE_FP_REG (fs4, 28, t0) -+ RESTORE_FP_REG (fs5, 29, t0) -+ RESTORE_FP_REG (fs6, 30, t0) -+ RESTORE_FP_REG (fs7, 31, t0) -+ -+ movgr2fcsr $r0, t1 -+#endif /* __loongarch_soft_float */ -+ -+ /* Note the contents of argument registers will be random -+ unless makecontext() has been called. */ -+ RESTORE_INT_REG (ra, 1, t0) -+ RESTORE_INT_REG (sp, 3, t0) -+ RESTORE_INT_REG (a0, 4, t0) -+ RESTORE_INT_REG (a1, 5, t0) -+ RESTORE_INT_REG (a2, 6, t0) -+ RESTORE_INT_REG (a3, 7, t0) -+ RESTORE_INT_REG (a4, 8, t0) -+ RESTORE_INT_REG (a5, 9, t0) -+ RESTORE_INT_REG (a6, 10, t0) -+ RESTORE_INT_REG (a7, 11, t0) -+ RESTORE_INT_REG (x, 21, t0) -+ RESTORE_INT_REG (fp, 22, t0) -+ RESTORE_INT_REG (s0, 23, t0) -+ RESTORE_INT_REG (s1, 24, t0) -+ RESTORE_INT_REG (s2, 25, t0) -+ RESTORE_INT_REG (s3, 26, t0) -+ RESTORE_INT_REG (s4, 27, t0) -+ RESTORE_INT_REG (s5, 28, t0) -+ RESTORE_INT_REG (s6, 29, t0) -+ RESTORE_INT_REG (s7, 30, t0) -+ RESTORE_INT_REG (s8, 31, t0) -+ ld.d t1, t0, MCONTEXT_PC -+ jirl $r0,t1,0 -+ -+99: -+ addi.d sp, sp, 16 -+ b __syscall_error -+ -+PSEUDO_END (__setcontext) -+weak_alias (__setcontext, setcontext) -+ -+LEAF (__start_context) -+ -+ /* Terminate call stack by noting ra == 0. Happily, s0 == 0 here. */ -+ cfi_register (1, 23) -+ -+ /* Call the function passed to makecontext. */ -+ jirl $r1,s1,0 -+ -+ /* Invoke subsequent context if present, else exit(0). */ -+ ori a0, s2, 0 -+ beqz s2, 1f -+ bl __setcontext -+1: b exit -+ -+PSEUDO_END (__start_context) -diff --git a/sysdeps/unix/sysv/linux/loongarch/shlib-versions b/sysdeps/unix/sysv/linux/loongarch/shlib-versions -new file mode 100644 -index 00000000..2a67fe71 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/shlib-versions -@@ -0,0 +1,2 @@ -+DEFAULT GLIBC_2.27 -+libpthread=0 GLIBC_2.0 GLIBC_2.2 -diff --git a/sysdeps/unix/sysv/linux/loongarch/sigcontextinfo.h b/sysdeps/unix/sysv/linux/loongarch/sigcontextinfo.h -new file mode 100644 -index 00000000..2a864795 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/sigcontextinfo.h -@@ -0,0 +1,22 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+ -+#define SIGCONTEXT siginfo_t *_si, ucontext_t * -+#define GET_PC(ctx) ((void *) ctx->uc_mcontext.__pc) -diff --git a/sysdeps/unix/sysv/linux/loongarch/swapcontext.S b/sysdeps/unix/sysv/linux/loongarch/swapcontext.S -new file mode 100644 -index 00000000..d839dd87 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/swapcontext.S -@@ -0,0 +1,120 @@ -+/* Save and set current context. -+ Copyright (C) 2009-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include "ucontext-macros.h" -+ -+/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */ -+ -+LEAF (__swapcontext) -+ ori a2, sp, 0 /* Save sp to a2. */ -+ addi.d sp, sp, -16 -+ st.d a1, sp, 0 -+ ori t0, a1, 0 -+ -+ SAVE_INT_REG (ra, 1, a0) -+ SAVE_INT_REG (a2, 3, a0) /* Store sp .*/ -+ SAVE_INT_REG (zero, 4, a0) /* return 0 by overwriting a0. */ -+ SAVE_INT_REG (x, 21, a0) -+ SAVE_INT_REG (fp, 22, a0) -+ SAVE_INT_REG (s0, 23, a0) -+ SAVE_INT_REG (s1, 24, a0) -+ SAVE_INT_REG (s2, 25, a0) -+ SAVE_INT_REG (s3, 26, a0) -+ SAVE_INT_REG (s4, 27, a0) -+ SAVE_INT_REG (s5, 28, a0) -+ SAVE_INT_REG (s6, 29, a0) -+ SAVE_INT_REG (s7, 30, a0) -+ SAVE_INT_REG (s8, 31, a0) -+ st.d ra, a0, MCONTEXT_PC -+#ifndef __loongarch_soft_float -+ movfcsr2gr a1, $r0 -+ -+ SAVE_FP_REG (fs0, 24, a0) -+ SAVE_FP_REG (fs1, 25, a0) -+ SAVE_FP_REG (fs2, 26, a0) -+ SAVE_FP_REG (fs3, 27, a0) -+ SAVE_FP_REG (fs4, 28, a0) -+ SAVE_FP_REG (fs5, 29, a0) -+ SAVE_FP_REG (fs6, 30, a0) -+ SAVE_FP_REG (fs7, 31, a0) -+ -+ st.w a1, a0, MCONTEXT_FCSR -+#endif /* __loongarch_soft_float */ -+ -+/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask, _NSIG8) */ -+ li.d a3, _NSIG8 -+ addi.d a2, a0, UCONTEXT_SIGMASK -+ addi.d a1, t0, UCONTEXT_SIGMASK -+ li.d a0, SIG_SETMASK -+ -+ li.d a7, SYS_ify (rt_sigprocmask) -+ syscall 0 -+ -+ blt a0, zero, 99f -+ -+#ifndef __loongarch_soft_float -+ ld.d t0, sp, 0 /* Load a1 to t0. */ -+ ld.w t1, t0, MCONTEXT_FCSR -+ -+ RESTORE_FP_REG (fs0, 24, t0) -+ RESTORE_FP_REG (fs1, 25, t0) -+ RESTORE_FP_REG (fs2, 26, t0) -+ RESTORE_FP_REG (fs3, 27, t0) -+ RESTORE_FP_REG (fs4, 28, t0) -+ RESTORE_FP_REG (fs5, 29, t0) -+ RESTORE_FP_REG (fs6, 30, t0) -+ RESTORE_FP_REG (fs7, 31, t0) -+ -+ movgr2fcsr $r0, t1 -+#endif /* __loongarch_soft_float */ -+ -+ /* Note the contents of argument registers will be random -+ unless makecontext() has been called. */ -+ RESTORE_INT_REG (ra, 1, t0) -+ RESTORE_INT_REG (sp, 3, t0) -+ RESTORE_INT_REG (a0, 4, t0) -+ RESTORE_INT_REG (a1, 5, t0) -+ RESTORE_INT_REG (a2, 6, t0) -+ RESTORE_INT_REG (a3, 7, t0) -+ RESTORE_INT_REG (a4, 8, t0) -+ RESTORE_INT_REG (a5, 9, t0) -+ RESTORE_INT_REG (a6, 10, t0) -+ RESTORE_INT_REG (a7, 11, t0) -+ RESTORE_INT_REG (x, 21, t0) -+ RESTORE_INT_REG (fp, 22, t0) -+ RESTORE_INT_REG (s0, 23, t0) -+ RESTORE_INT_REG (s1, 24, t0) -+ RESTORE_INT_REG (s2, 25, t0) -+ RESTORE_INT_REG (s3, 26, t0) -+ RESTORE_INT_REG (s4, 27, t0) -+ RESTORE_INT_REG (s5, 28, t0) -+ RESTORE_INT_REG (s6, 29, t0) -+ RESTORE_INT_REG (s7, 30, t0) -+ RESTORE_INT_REG (s8, 31, t0) -+ ld.d t1, t0, MCONTEXT_PC -+ -+ jirl $r0, t1, 0 -+ -+ -+99: -+ addi.d sp, sp, 16 -+ b __syscall_error -+ -+PSEUDO_END (__swapcontext) -+ -+weak_alias (__swapcontext, swapcontext) -diff --git a/sysdeps/unix/sysv/linux/loongarch/sys/procfs.h b/sysdeps/unix/sysv/linux/loongarch/sys/procfs.h -new file mode 100644 -index 00000000..9ae06b40 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/sys/procfs.h -@@ -0,0 +1,122 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _SYS_PROCFS_H -+#define _SYS_PROCFS_H 1 -+ -+/* This is somehow modelled after the file of the same name on SysVr4 -+ systems. It provides a definition of the core file format for ELF -+ used on Linux. */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+__BEGIN_DECLS -+ -+/* Type for a general-purpose register. */ -+typedef uint64_t elf_greg_t; -+ -+/* And the whole bunch of them. We could have used `struct -+ pt_regs' directly in the typedef, but tradition says that -+ the register set is an array, which does have some peculiar -+ semantics, so leave it that way. */ -+#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) -+typedef elf_greg_t elf_gregset_t[ELF_NGREG]; -+ -+#define ELF_NFPREG 34 /* 32 FPRs + 8-byte byte-vec for fcc + 4-byte FCR */ -+typedef union { double d; float f; } elf_fpreg_t; -+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; -+ -+typedef union { double d[2]; float f[4]; } __attribute__((__aligned__ (16))) elf_lsxregset_t[32]; -+typedef union { double d[4]; float f[8]; } __attribute__((__aligned__ (32))) elf_lasxregset_t[32]; -+ -+struct elf_siginfo -+ { -+ int si_signo; /* Signal number. */ -+ int si_code; /* Extra code. */ -+ int si_errno; /* Errno. */ -+ }; -+ -+/* Definitions to generate Intel SVR4-like core files. These mostly -+ have the same names as the SVR4 types with "elf_" tacked on the -+ front to prevent clashes with linux definitions, and the typedef -+ forms have been avoided. This is mostly like the SVR4 structure, -+ but more Linuxy, with things that Linux does not support and which -+ gdb doesn't really use excluded. Fields present but not used are -+ marked with "XXX". */ -+struct elf_prstatus -+ { -+ struct elf_siginfo pr_info; /* Info associated with signal. */ -+ short int pr_cursig; /* Current signal. */ -+ unsigned long int pr_sigpend; /* Set of pending signals. */ -+ unsigned long int pr_sighold; /* Set of held signals. */ -+ __pid_t pr_pid; -+ __pid_t pr_ppid; -+ __pid_t pr_pgrp; -+ __pid_t pr_sid; -+ struct timeval pr_utime; /* User time. */ -+ struct timeval pr_stime; /* System time. */ -+ struct timeval pr_cutime; /* Cumulative user time. */ -+ struct timeval pr_cstime; /* Cumulative system time. */ -+ elf_gregset_t pr_reg; /* GP registers. */ -+ int pr_fpvalid; /* True if math copro being used. */ -+ }; -+ -+ -+#define ELF_PRARGSZ (80) /* Number of chars for args */ -+ -+struct elf_prpsinfo -+ { -+ char pr_state; /* Numeric process state. */ -+ char pr_sname; /* Char for pr_state. */ -+ char pr_zomb; /* Zombie. */ -+ char pr_nice; /* Nice val. */ -+ unsigned long int pr_flag; /* Flags. */ -+ unsigned int pr_uid; -+ unsigned int pr_gid; -+ int pr_pid, pr_ppid, pr_pgrp, pr_sid; -+ /* Lots missing */ -+ char pr_fname[16]; /* Filename of executable. */ -+ char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ -+ }; -+ -+/* The rest of this file provides the types for emulation of the -+ Solaris interfaces that should be implemented by -+ users of libthread_db. */ -+ -+/* Addresses. */ -+typedef void *psaddr_t; -+ -+/* Register sets. Linux has different names. */ -+typedef elf_gregset_t prgregset_t; -+typedef elf_fpregset_t prfpregset_t; -+ -+/* We don't have any differences between processes and threads, -+ therefore habe only ine PID type. */ -+typedef __pid_t lwpid_t; -+ -+/* Process status and info. In the end we do provide typedefs for them. */ -+typedef struct elf_prstatus prstatus_t; -+typedef struct elf_prpsinfo prpsinfo_t; -+ -+__END_DECLS -+ -+#endif /* sys/procfs.h */ -diff --git a/sysdeps/unix/sysv/linux/loongarch/sys/ucontext.h b/sysdeps/unix/sysv/linux/loongarch/sys/ucontext.h -new file mode 100644 -index 00000000..e52a46c9 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/sys/ucontext.h -@@ -0,0 +1,81 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+/* Don't rely on this, the interface is currently messed up and may need to -+ be broken to be fixed. */ -+#ifndef _SYS_UCONTEXT_H -+#define _SYS_UCONTEXT_H 1 -+ -+#include -+ -+#include -+#include -+ -+typedef unsigned long int __loongarch_mc_gp_state[32]; -+ -+#ifdef __USE_MISC -+# define LARCH_NGREG 32 -+ -+# define LARCH_REG_RA 1 -+# define LARCH_REG_SP 3 -+# define LARCH_REG_S0 23 -+# define LARCH_REG_S1 24 -+# define LARCH_REG_A0 4 -+# define LARCH_REG_S2 25 -+# define LARCH_REG_NARGS 8 -+ -+typedef unsigned long int greg_t; -+ -+/* Container for all general registers. */ -+typedef __loongarch_mc_gp_state gregset_t; -+ -+/* Container for floating-point state. */ -+typedef union __loongarch_mc_fp_state fpregset_t; -+#endif -+ -+ -+ -+union __loongarch_mc_fp_state { -+ unsigned int __val32[256 / 32]; -+ unsigned long long __val64[256 / 64]; -+}; -+ -+typedef struct mcontext_t { -+ unsigned long long __pc; -+ unsigned long long __gregs[32]; -+ unsigned int __flags; -+ -+ unsigned int __fcsr; -+ unsigned int __vcsr; -+ unsigned long long __fcc; -+ union __loongarch_mc_fp_state __fpregs[32] __attribute__((__aligned__ (32))); -+ -+ unsigned int __reserved; -+} mcontext_t; -+ -+/* Userlevel context. */ -+typedef struct ucontext_t -+ { -+ unsigned long int __uc_flags; -+ struct ucontext_t *uc_link; -+ stack_t uc_stack; -+ mcontext_t uc_mcontext; -+ sigset_t uc_sigmask; -+ } ucontext_t; -+ -+#endif /* sys/ucontext.h */ -diff --git a/sysdeps/unix/sysv/linux/loongarch/sys/user.h b/sysdeps/unix/sysv/linux/loongarch/sys/user.h -new file mode 100644 -index 00000000..f9108350 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/sys/user.h -@@ -0,0 +1,31 @@ -+/* Copyright (C) 2001-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#ifndef _SYS_USER_H -+#define _SYS_USER_H 1 -+ -+#include -+ -+struct user_regs_struct -+{ -+ uint64_t gpr[32]; -+ uint64_t pc; -+ uint64_t badvaddr; -+ uint64_t reserved[11]; -+}; -+ -+#endif /* _SYS_USER_H */ -diff --git a/sysdeps/unix/sysv/linux/loongarch/syscall.c b/sysdeps/unix/sysv/linux/loongarch/syscall.c -new file mode 100644 -index 00000000..b06a528e ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/syscall.c -@@ -0,0 +1,36 @@ -+/* Copyright (C) 2020-2021 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+ -+long int -+syscall (long int syscall_number, long int arg1, long int arg2, long int arg3, -+ long int arg4, long int arg5, long int arg6, long int arg7) -+{ -+ long int ret; -+ INTERNAL_SYSCALL_DECL (err); -+ -+ ret = INTERNAL_SYSCALL_NCS (syscall_number, err, 7, arg1, arg2, arg3, arg4, -+ arg5, arg6, arg7); -+ -+ if (INTERNAL_SYSCALL_ERROR_P (ret, err)) -+ return __syscall_error (ret); -+ -+ return ret; -+} -+ -diff --git a/sysdeps/unix/sysv/linux/loongarch/sysdep.S b/sysdeps/unix/sysv/linux/loongarch/sysdep.S -new file mode 100644 -index 00000000..a8094283 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/sysdep.S -@@ -0,0 +1,52 @@ -+/* syscall error handlers -+ Copyright (C) 2011-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#include -+ -+#if IS_IN (libc) -+# define errno __libc_errno -+#endif -+ -+ENTRY (__syscall_error) -+ /* Fall through to __syscall_set_errno. */ -+END (__syscall_error) -+ -+/* Non-standard calling convention: argument in a0, return address in t0, -+ and clobber only t1. */ -+ENTRY (__syscall_set_errno) -+ /* We got here because a0 < 0, but only codes in the range [-4095, -1] -+ represent errors. Otherwise, just return the result normally. */ -+ -+ li.d t1, -4096 -+ bgeu t1, a0, L (out) -+ sub.w a0, zero, a0 -+ -+#if RTLD_PRIVATE_ERRNO -+ la t1, rtld_errno -+#elif defined(__PIC__) -+ la.tls.ie t1, errno -+ add.d t1, tp, t1 -+#else -+ la.tls.le t1, errno -+ add.d t1, tp, t1 -+#endif -+ st.w a0, t1, 0 -+ li.d a0, -1 -+L (out): -+ ret -+END (__syscall_set_errno) -diff --git a/sysdeps/unix/sysv/linux/loongarch/sysdep.h b/sysdeps/unix/sysv/linux/loongarch/sysdep.h -new file mode 100644 -index 00000000..f50946d4 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/sysdep.h -@@ -0,0 +1,333 @@ -+#ifndef _LINUX_LOONGARCH_SYSDEP_H -+#define _LINUX_LOONGARCH_SYSDEP_H 1 -+ -+#include -+#include -+ -+#ifdef __ASSEMBLER__ -+ -+# include -+# define ret jirl zero, ra, 0 -+# define L(label) .L ## label -+ -+/* Performs a system call, handling errors by setting errno. Linux indicates -+ errors by setting a0 to a value between -1 and -4095. */ -+# undef PSEUDO -+# define PSEUDO(name, syscall_name, args) \ -+ ENTRY (name); \ -+ li.d a7, SYS_ify (syscall_name); \ -+ syscall 0; \ -+ li.d a7, -4096; \ -+ bltu a7, a0, .Lsyscall_error ## name; -+ -+# undef PSEUDO_END -+# define PSEUDO_END(sym) \ -+ SYSCALL_ERROR_HANDLER (sym); \ -+ ret; \ -+ END (sym); -+ -+# if !IS_IN (libc) -+# if RTLD_PRIVATE_ERRNO -+ -+# define SYSCALL_ERROR_HANDLER(name) \ -+.Lsyscall_error ## name: \ -+ la t0, rtld_errno; \ -+ sub.w a0, zero, a0; \ -+ st.w a0, t0, 0; \ -+ li.d a0, -1; -+ -+# else -+ -+# define SYSCALL_ERROR_HANDLER(name) \ -+.Lsyscall_error ## name: \ -+ la.tls.ie t0, errno; \ -+ add.d t0, tp, t0; \ -+ sub.w a0, zero, a0; \ -+ st.w a0, t0, 0; \ -+ li.d a0, -1; -+ -+# endif -+# else -+ -+# define SYSCALL_ERROR_HANDLER(name) \ -+.Lsyscall_error ## name: \ -+ b __syscall_error; -+ -+# endif -+ -+/* Performs a system call, not setting errno. */ -+# undef PSEUDO_NEORRNO -+# define PSEUDO_NOERRNO(name, syscall_name, args) \ -+ ENTRY (name); \ -+ li.d a7, SYS_ify (syscall_name); \ -+ syscall 0; -+ -+# undef PSEUDO_END_NOERRNO -+# define PSEUDO_END_NOERRNO(name) \ -+ END (name); -+ -+# undef ret_NOERRNO -+# define ret_NOERRNO ret -+ -+/* Perfroms a system call, returning the error code. */ -+# undef PSEUDO_ERRVAL -+# define PSEUDO_ERRVAL(name, syscall_name, args) \ -+ PSEUDO_NOERRNO (name, syscall_name, args); \ -+ slli.d a0, a0, 32; \ -+ srai.d a0, a0, 32; /* sign_ext */ \ -+ sub.d a0, zero, a0; -+ -+# undef PSEUDO_END_ERRVAL -+# define PSEUDO_END_ERRVAL(name) \ -+ END (name); -+ -+# undef ret_ERRVAL -+# define ret_ERRVAL ret -+ -+#endif /* __ASSEMBLER__ */ -+ -+/* In order to get __set_errno() definition in INLINE_SYSCALL. */ -+#ifndef __ASSEMBLER__ -+# include -+#endif -+ -+#include -+ -+#undef SYS_ify -+#define SYS_ify(syscall_name) __NR_##syscall_name -+ -+#ifndef __ASSEMBLER__ -+ -+/* List of system calls which are supported as vsyscalls. */ -+# define HAVE_CLOCK_GETRES_VSYSCALL 1 -+# define HAVE_CLOCK_GETTIME_VSYSCALL 1 -+# define HAVE_GETTIMEOFDAY_VSYSCALL 1 -+# define HAVE_GETCPU_VSYSCALL 1 -+ -+/* Define a macro which expands into the inline wrapper code for a system -+ call. */ -+# undef INLINE_SYSCALL -+# define INLINE_SYSCALL(name, nr, args...) \ -+ ({ INTERNAL_SYSCALL_DECL (err); \ -+ long int __sys_result = INTERNAL_SYSCALL (name, err, nr, args); \ -+ if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (__sys_result, ))) \ -+ { \ -+ __set_errno (INTERNAL_SYSCALL_ERRNO (__sys_result, )); \ -+ __sys_result = (unsigned long) -1; \ -+ } \ -+ __sys_result; }) -+ -+ -+# define INTERNAL_SYSCALL_DECL(err) do { } while (0) -+ -+# define INTERNAL_SYSCALL_ERROR_P(val, err) \ -+ ((unsigned long int) (val) > -4096UL) -+ -+# define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) -+ -+# define INTERNAL_SYSCALL(name, err, nr, args...) \ -+ internal_syscall##nr (SYS_ify (name), err, args) -+ -+# define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ -+ internal_syscall##nr (number, err, args) -+ -+# define internal_syscall0(number, err, dummy...) \ -+({ \ -+ long int _sys_result; \ -+ \ -+ { \ -+ register long int __a7 asm ("$a7") = number; \ -+ register long int __a0 asm ("$a0"); \ -+ __asm__ volatile ( \ -+ "syscall 0\n\t" \ -+ : "=r" (__a0) \ -+ : "r" (__a7) \ -+ : __SYSCALL_CLOBBERS); \ -+ _sys_result = __a0; \ -+ } \ -+ _sys_result; \ -+}) -+ -+# define internal_syscall1(number, err, arg0) \ -+({ \ -+ long int _sys_result; \ -+ \ -+ { \ -+ long int _arg0 = (long int) (arg0); \ -+ register long int __a7 asm ("$a7") = number; \ -+ register long int __a0 asm ("$a0") = _arg0; \ -+ __asm__ volatile ( \ -+ "syscall 0\n\t" \ -+ : "+r" (__a0) \ -+ : "r" (__a7) \ -+ : __SYSCALL_CLOBBERS); \ -+ _sys_result = __a0; \ -+ } \ -+ _sys_result; \ -+}) -+ -+# define internal_syscall2(number, err, arg0, arg1) \ -+({ \ -+ long int _sys_result; \ -+ \ -+ { \ -+ long int _arg0 = (long int) (arg0); \ -+ long int _arg1 = (long int) (arg1); \ -+ register long int __a7 asm ("$a7") = number; \ -+ register long int __a0 asm ("$a0") = _arg0; \ -+ register long int __a1 asm ("$a1") = _arg1; \ -+ __asm__ volatile ( \ -+ "syscall 0\n\t" \ -+ : "+r" (__a0) \ -+ : "r" (__a7), "r" (__a1) \ -+ : __SYSCALL_CLOBBERS); \ -+ _sys_result = __a0; \ -+ } \ -+ _sys_result; \ -+}) -+ -+# define internal_syscall3(number, err, arg0, arg1, arg2) \ -+({ \ -+ long int _sys_result; \ -+ \ -+ { \ -+ long int _arg0 = (long int) (arg0); \ -+ long int _arg1 = (long int) (arg1); \ -+ long int _arg2 = (long int) (arg2); \ -+ register long int __a7 asm ("$a7") = number; \ -+ register long int __a0 asm ("$a0") = _arg0; \ -+ register long int __a1 asm ("$a1") = _arg1; \ -+ register long int __a2 asm ("$a2") = _arg2; \ -+ __asm__ volatile ( \ -+ "syscall 0\n\t" \ -+ : "+r" (__a0) \ -+ : "r" (__a7), "r" (__a1), "r" (__a2) \ -+ : __SYSCALL_CLOBBERS); \ -+ _sys_result = __a0; \ -+ } \ -+ _sys_result; \ -+}) -+ -+# define internal_syscall4(number, err, arg0, arg1, arg2, arg3) \ -+({ \ -+ long int _sys_result; \ -+ \ -+ { \ -+ long int _arg0 = (long int) (arg0); \ -+ long int _arg1 = (long int) (arg1); \ -+ long int _arg2 = (long int) (arg2); \ -+ long int _arg3 = (long int) (arg3); \ -+ register long int __a7 asm ("$a7") = number; \ -+ register long int __a0 asm ("$a0") = _arg0; \ -+ register long int __a1 asm ("$a1") = _arg1; \ -+ register long int __a2 asm ("$a2") = _arg2; \ -+ register long int __a3 asm ("$a3") = _arg3; \ -+ __asm__ volatile ( \ -+ "syscall 0\n\t" \ -+ : "+r" (__a0) \ -+ : "r" (__a7), "r" (__a1), "r" (__a2), "r" (__a3) \ -+ : __SYSCALL_CLOBBERS); \ -+ _sys_result = __a0; \ -+ } \ -+ _sys_result; \ -+}) -+ -+# define internal_syscall5(number, err, arg0, arg1, arg2, arg3, arg4) \ -+({ \ -+ long int _sys_result; \ -+ \ -+ { \ -+ long int _arg0 = (long int) (arg0); \ -+ long int _arg1 = (long int) (arg1); \ -+ long int _arg2 = (long int) (arg2); \ -+ long int _arg3 = (long int) (arg3); \ -+ long int _arg4 = (long int) (arg4); \ -+ register long int __a7 asm ("$a7") = number; \ -+ register long int __a0 asm ("$a0") = _arg0; \ -+ register long int __a1 asm ("$a1") = _arg1; \ -+ register long int __a2 asm ("$a2") = _arg2; \ -+ register long int __a3 asm ("$a3") = _arg3; \ -+ register long int __a4 asm ("$a4") = _arg4; \ -+ __asm__ volatile ( \ -+ "syscall 0\n\t" \ -+ : "+r" (__a0) \ -+ : "r" (__a7), "r"(__a1), "r"(__a2), "r"(__a3), "r" (__a4) \ -+ : __SYSCALL_CLOBBERS); \ -+ _sys_result = __a0; \ -+ } \ -+ _sys_result; \ -+}) -+ -+# define internal_syscall6(number, err, arg0, arg1, arg2, arg3, arg4, arg5) \ -+({ \ -+ long int _sys_result; \ -+ \ -+ { \ -+ long int _arg0 = (long int) (arg0); \ -+ long int _arg1 = (long int) (arg1); \ -+ long int _arg2 = (long int) (arg2); \ -+ long int _arg3 = (long int) (arg3); \ -+ long int _arg4 = (long int) (arg4); \ -+ long int _arg5 = (long int) (arg5); \ -+ register long int __a7 asm ("$a7") = number; \ -+ register long int __a0 asm ("$a0") = _arg0; \ -+ register long int __a1 asm ("$a1") = _arg1; \ -+ register long int __a2 asm ("$a2") = _arg2; \ -+ register long int __a3 asm ("$a3") = _arg3; \ -+ register long int __a4 asm ("$a4") = _arg4; \ -+ register long int __a5 asm ("$a5") = _arg5; \ -+ __asm__ volatile ( \ -+ "syscall 0\n\t" \ -+ : "+r" (__a0) \ -+ : "r" (__a7), "r" (__a1), "r" (__a2), "r" (__a3), \ -+ "r" (__a4), "r" (__a5) \ -+ : __SYSCALL_CLOBBERS); \ -+ _sys_result = __a0; \ -+ } \ -+ _sys_result; \ -+}) -+ -+# define internal_syscall7(number, err, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \ -+({ \ -+ long int _sys_result; \ -+ \ -+ { \ -+ long int _arg0 = (long int) (arg0); \ -+ long int _arg1 = (long int) (arg1); \ -+ long int _arg2 = (long int) (arg2); \ -+ long int _arg3 = (long int) (arg3); \ -+ long int _arg4 = (long int) (arg4); \ -+ long int _arg5 = (long int) (arg5); \ -+ long int _arg6 = (long int) (arg6); \ -+ register long int __a7 asm ("$a7") = number; \ -+ register long int __a0 asm ("$a0") = _arg0; \ -+ register long int __a1 asm ("$a1") = _arg1; \ -+ register long int __a2 asm ("$a2") = _arg2; \ -+ register long int __a3 asm ("$a3") = _arg3; \ -+ register long int __a4 asm ("$a4") = _arg4; \ -+ register long int __a5 asm ("$a5") = _arg5; \ -+ register long int __a6 asm ("$a6") = _arg6; \ -+ __asm__ volatile ( \ -+ "syscall 0\n\t" \ -+ : "+r" (__a0) \ -+ : "r" (__a7), "r" (__a1), "r" (__a2), "r" (__a3), \ -+ "r" (__a4), "r" (__a5), "r" (__a6) \ -+ : __SYSCALL_CLOBBERS); \ -+ _sys_result = __a0; \ -+ } \ -+ _sys_result; \ -+}) -+ -+# define __SYSCALL_CLOBBERS \ -+ "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8",\ -+ "memory" -+ -+extern long int __syscall_error (long int neg_errno); -+ -+#endif /* ! __ASSEMBLER__ */ -+ -+/* Pointer mangling is not supported. */ -+#define PTR_MANGLE(var) (void) (var) -+#define PTR_DEMANGLE(var) (void) (var) -+ -+#endif /* linux/loongarch/sysdep.h */ -diff --git a/sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h b/sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h -new file mode 100644 -index 00000000..abd22247 ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h -@@ -0,0 +1,44 @@ -+/* Macros for ucontext routines. -+ Copyright (C) 2017-2018 Free Software Foundation, Inc. -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public -+ License as published by the Free Software Foundation; either -+ version 2.1 of the License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library. If not, see -+ . */ -+ -+#ifndef _LINUX_LOONGARCH_UCONTEXT_MACROS_H -+#define _LINUX_LOONGARCH_UCONTEXT_MACROS_H -+ -+#include -+#include -+ -+#include "ucontext_i.h" -+ -+#define SAVE_FP_REG(name, num, base) \ -+ FREG_S name, base, ((num) * SZFREG + MCONTEXT_FPREGS) -+ -+#define RESTORE_FP_REG(name, num, base) \ -+ FREG_L name, base, ((num) * SZFREG + MCONTEXT_FPREGS) -+ -+#define SAVE_INT_REG(name, num, base) \ -+ REG_S name, base, ((num) * SZREG + MCONTEXT_GREGS) -+ -+#define RESTORE_INT_REG(name, num, base) \ -+ REG_L name, base, ((num) * SZREG + MCONTEXT_GREGS) -+ -+#define SAVE_REG(name, offset, base) \ -+ REG_S name, base, (offset) -+ -+#define RESTORE_REG(name, offset, base) \ -+ REG_L name, base, (offset) -+#endif /* _LINUX_LOONGARCH_UCONTEXT_MACROS_H */ -diff --git a/sysdeps/unix/sysv/linux/loongarch/ucontext_i.sym b/sysdeps/unix/sysv/linux/loongarch/ucontext_i.sym -new file mode 100644 -index 00000000..d7f612fe ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/ucontext_i.sym -@@ -0,0 +1,33 @@ -+#include -+#include -+#include -+#include -+ -+-- Constants used by the rt_sigprocmask call. -+ -+SIG_BLOCK -+SIG_SETMASK -+ -+_NSIG8 (_NSIG / 8) -+ -+-- Offsets of the fields in the ucontext_t structure. -+#define ucontext(member) offsetof (ucontext_t, member) -+#define stack(member) ucontext (uc_stack.member) -+#define mcontext(member) ucontext (uc_mcontext.member) -+ -+UCONTEXT_FLAGS ucontext (__uc_flags) -+UCONTEXT_LINK ucontext (uc_link) -+UCONTEXT_STACK ucontext (uc_stack) -+UCONTEXT_MCONTEXT ucontext (uc_mcontext) -+UCONTEXT_SIGMASK ucontext (uc_sigmask) -+ -+STACK_SP stack (ss_sp) -+STACK_SIZE stack (ss_size) -+STACK_FLAGS stack (ss_flags) -+ -+MCONTEXT_PC mcontext (__pc) -+MCONTEXT_FCSR mcontext (__fcsr) -+MCONTEXT_GREGS mcontext (__gregs) -+MCONTEXT_FPREGS mcontext (__fpregs) -+ -+UCONTEXT_SIZE sizeof (ucontext_t) -diff --git a/sysdeps/unix/sysv/linux/loongarch/vfork.S b/sysdeps/unix/sysv/linux/loongarch/vfork.S -new file mode 100644 -index 00000000..83cf141f ---- /dev/null -+++ b/sysdeps/unix/sysv/linux/loongarch/vfork.S -@@ -0,0 +1,49 @@ -+/* Copyright (C) 1999-2018 Free Software Foundation, Inc. -+ -+ This file is part of the GNU C Library. -+ -+ The GNU C Library is free software; you can redistribute it and/or -+ modify it under the terms of the GNU Lesser General Public License as -+ published by the Free Software Foundation; either version 2.1 of the -+ License, or (at your option) any later version. -+ -+ The GNU C Library is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ Lesser General Public License for more details. -+ -+ You should have received a copy of the GNU Lesser General Public -+ License along with the GNU C Library; if not, see -+ . */ -+ -+#include -+#define _ERRNO_H 1 -+#include -+ -+/* Clone the calling process, but without copying the whole address space. -+ The calling process is suspended until the new process exits or is -+ replaced by a call to `execve'. Return -1 for errors, 0 to the new process, -+ and the process ID of the new process to the old process. */ -+ -+ENTRY (__vfork) -+ -+ -+ li.d a0, 0x4111 /* CLONE_VM | CLONE_VFORK | SIGCHLD */ -+ add.d a1, zero, sp -+ -+ /* Do the system call. */ -+ li.d a7, __NR_clone -+ syscall 0 -+ -+ blt a0, zero ,L (error) -+ -+ ret -+ -+L (error): -+ b __syscall_error -+ END (__vfork) -+ -+libc_hidden_def (__vfork) -+ -+weak_alias (__vfork, vfork) -+strong_alias (__vfork, __libc_vfork) --- -2.20.1 - diff --git a/glibc-Properly-check-stack-alignment-BZ-27901.patch b/glibc-Properly-check-stack-alignment-BZ-27901.patch deleted file mode 100644 index 58b6c5f..0000000 --- a/glibc-Properly-check-stack-alignment-BZ-27901.patch +++ /dev/null @@ -1,325 +0,0 @@ -From 7ae4fdd1783cdfd30bfefdd7c3c3c9430f234406 Mon Sep 17 00:00:00 2001 -From: "H.J. Lu" -Date: Tue, 15 Feb 2022 14:15:50 -0500 -Subject: [PATCH] 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 -Signed-off-by: Rongwei Wang ---- - 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 - #include - -+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 -- . */ -- --#include --#include --#ifndef __SSE__ --#include_next --#else --#include -- --#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 -- . */ -- --#include --#include -- --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 - . */ - --#include --#include -- --#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 -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 -+ . */ -+ -+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 -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 -- . */ -- --#include --#include -- --#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.18.4 - diff --git a/glibc-Support-target-specific-ALIGN-for-variable-alignment-4.patch b/glibc-Support-target-specific-ALIGN-for-variable-alignment-4.patch deleted file mode 100644 index 5ac2055..0000000 --- a/glibc-Support-target-specific-ALIGN-for-variable-alignment-4.patch +++ /dev/null @@ -1,171 +0,0 @@ -From 9302aaad29363eb1dba30d5b9b588a165395672a Mon Sep 17 00:00:00 2001 -From: "H.J. Lu" -Date: Mon, 7 Feb 2022 10:46:19 -0500 -Subject: [PATCH 4/4] Support target specific ALIGN for variable alignment test - [BZ #28676] - -Add 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 -Signed-off-by: Rongwei Wang ---- - 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 @@ - . */ - - #include -+#include - #include - --/* 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 @@ - . */ - - #include -+#include - #include - --/* 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 -+ . */ -+ -+/* 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 -+ . */ -+ -+/* 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 -+ . */ -+ -+/* 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 -+ . */ -+ -+/* This should cover all possible alignments we currently support. */ -+#define ALIGN 0x8000 --- -2.18.4 - diff --git a/glibc-elf-Align-argument-of-__munmap-to-page-size-BZ-28676-3.patch b/glibc-elf-Align-argument-of-__munmap-to-page-size-BZ-28676-3.patch deleted file mode 100644 index c065572..0000000 --- a/glibc-elf-Align-argument-of-__munmap-to-page-size-BZ-28676-3.patch +++ /dev/null @@ -1,36 +0,0 @@ -From a36e3f474b748bec447de3bdd8483b52b09e5804 Mon Sep 17 00:00:00 2001 -From: "H.J. Lu" -Date: Thu, 13 Jan 2022 03:48:36 +0800 -Subject: [PATCH 3/4] 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 -Signed-off-by: Rongwei Wang ---- - 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.18.4 - diff --git a/glibc-elf-Fix-tst-align3.patch b/glibc-elf-Fix-tst-align3.patch deleted file mode 100644 index c170b2c..0000000 --- a/glibc-elf-Fix-tst-align3.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 716c4027b04db785034b0f67ac552cfaff360463 Mon Sep 17 00:00:00 2001 -From: Adhemerval Zanella -Date: Tue, 18 Jan 2022 14:36:45 -0300 -Subject: [PATCH] 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 ---- - 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 4913c26..6853b6e 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 --- -1.8.3.1 - diff --git a/glibc-elf-Properly-align-PT_LOAD-segments-BZ-28676-1.patch b/glibc-elf-Properly-align-PT_LOAD-segments-BZ-28676-1.patch deleted file mode 100644 index af6b6a6..0000000 --- a/glibc-elf-Properly-align-PT_LOAD-segments-BZ-28676-1.patch +++ /dev/null @@ -1,137 +0,0 @@ -From c61fc02c61a88204a5af47f61c1b7cfb19b61e32 Mon Sep 17 00:00:00 2001 -From: Rongwei Wang -Date: Mon, 7 Feb 2022 10:42:01 -0500 -Subject: [PATCH 1/4] 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 -Signed-off-by: Rongwei Wang ---- - 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 fee08d78..6785a499 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 -@@ -1107,6 +1108,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 - -+/* 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.18.4 - diff --git a/glibc-rh1888660.patch b/glibc-rh1888660.patch new file mode 100644 index 0000000..ec80b81 --- /dev/null +++ b/glibc-rh1888660.patch @@ -0,0 +1,767 @@ +This patch is a RHEL-8.7 backport of the following upstream commit: + +commit 52a103e237329b9f88a28513fe7506ffc3bd8ced +Author: Arjun Shankar +Date: Tue May 24 17:57:36 2022 +0200 + + Fix deadlock when pthread_atfork handler calls pthread_atfork or dlclose + + In multi-threaded programs, registering via pthread_atfork, + de-registering implicitly via dlclose, or running pthread_atfork + handlers during fork was protected by an internal lock. This meant + that a pthread_atfork handler attempting to register another handler or + dlclose a dynamically loaded library would lead to a deadlock. + + This commit fixes the deadlock in the following way: + + During the execution of handlers at fork time, the atfork lock is + released prior to the execution of each handler and taken again upon its + return. Any handler registrations or de-registrations that occurred + during the execution of the handler are accounted for before proceeding + with further handler execution. + + If a handler that hasn't been executed yet gets de-registered by another + handler during fork, it will not be executed. If a handler gets + registered by another handler during fork, it will not be executed + during that particular fork. + + The possibility that handlers may now be registered or deregistered + during handler execution means that identifying the next handler to be + run after a given handler may register/de-register others requires some + bookkeeping. The fork_handler struct has an additional field, 'id', + which is assigned sequentially during registration. Thus, handlers are + executed in ascending order of 'id' during 'prepare', and descending + order of 'id' during parent/child handler execution after the fork. + + Two tests are included: + + * tst-atfork3: Adhemerval Zanella + This test exercises calling dlclose from prepare, parent, and child + handlers. + + * tst-atfork4: This test exercises calling pthread_atfork and dlclose + from the prepare handler. + + [BZ #24595, BZ #27054] + + Co-authored-by: Adhemerval Zanella + Reviewed-by: Adhemerval Zanella + +diff --git a/nptl/Makefile b/nptl/Makefile +index 70a3be23ecfcd9c9..76c914e23e8873f2 100644 +--- a/nptl/Makefile ++++ b/nptl/Makefile +@@ -382,8 +382,17 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \ + tst-cancelx16 tst-cancelx17 tst-cancelx18 tst-cancelx20 tst-cancelx21 \ + tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 + ifeq ($(build-shared),yes) +-tests += tst-atfork2 tst-tls4 tst-_res1 tst-fini1 tst-compat-forwarder \ +- tst-audit-threads ++tests += \ ++ tst-atfork2 \ ++ tst-tls4 \ ++ tst-_res1 \ ++ tst-fini1 \ ++ tst-compat-forwarder \ ++ tst-audit-threads \ ++ tst-atfork3 \ ++ tst-atfork4 \ ++# tests ++ + tests-internal += tst-tls3 tst-tls3-malloc tst-tls5 tst-stackguard1 + tests-nolibpthread += tst-fini1 + ifeq ($(have-z-execstack),yes) +@@ -391,18 +400,39 @@ tests += tst-execstack + endif + endif + +-modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \ +- tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \ +- tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \ +- tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \ +- tst-join7mod tst-compat-forwarder-mod tst-audit-threads-mod1 \ +- tst-audit-threads-mod2 ++modules-names = \ ++ tst-atfork2mod \ ++ tst-tls3mod \ ++ tst-tls4moda \ ++ tst-tls4modb \ ++ tst-tls5mod \ ++ tst-tls5moda \ ++ tst-tls5modb \ ++ tst-tls5modc \ ++ tst-tls5modd \ ++ tst-tls5mode \ ++ tst-tls5modf \ ++ tst-stack4mod \ ++ tst-_res1mod1 \ ++ tst-_res1mod2 \ ++ tst-execstack-mod \ ++ tst-fini1mod \ ++ tst-join7mod \ ++ tst-compat-forwarder-mod \ ++ tst-audit-threads-mod1 \ ++ tst-audit-threads-mod2 \ ++ tst-atfork3mod \ ++ tst-atfork4mod \ ++# module-names ++ + extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) \ + tst-cleanup4aux.o tst-cleanupx4aux.o + test-extras += tst-cleanup4aux tst-cleanupx4aux + test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) + + tst-atfork2mod.so-no-z-defs = yes ++tst-atfork3mod.so-no-z-defs = yes ++tst-atfork4mod.so-no-z-defs = yes + tst-tls3mod.so-no-z-defs = yes + tst-tls5mod.so-no-z-defs = yes + tst-tls5moda.so-no-z-defs = yes +@@ -541,6 +571,14 @@ LDFLAGS-tst-atfork2 = -rdynamic + tst-atfork2-ENV = MALLOC_TRACE=$(objpfx)tst-atfork2.mtrace + $(objpfx)tst-atfork2mod.so: $(shared-thread-library) + ++$(objpfx)tst-atfork3: $(libdl) $(shared-thread-library) ++LDFLAGS-tst-atfork3 = -rdynamic ++$(objpfx)tst-atfork3mod.so: $(shared-thread-library) ++ ++$(objpfx)tst-atfork4: $(libdl) $(shared-thread-library) ++LDFLAGS-tst-atfork4 = -rdynamic ++$(objpfx)tst-atfork4mod.so: $(shared-thread-library) ++ + tst-stack3-ENV = MALLOC_TRACE=$(objpfx)tst-stack3.mtrace + $(objpfx)tst-stack3-mem.out: $(objpfx)tst-stack3.out + $(common-objpfx)malloc/mtrace $(objpfx)tst-stack3.mtrace > $@; \ +@@ -640,6 +678,8 @@ $(objpfx)../libc.so: $(common-objpfx)libc.so ; + $(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a + + $(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so ++$(objpfx)tst-atfork3.out: $(objpfx)tst-atfork3mod.so ++$(objpfx)tst-atfork4.out: $(objpfx)tst-atfork4mod.so + else + $(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a + endif +diff --git a/nptl/register-atfork.c b/nptl/register-atfork.c +index 9edb7d4bbb49fbed..4c1e20ae8cab005f 100644 +--- a/nptl/register-atfork.c ++++ b/nptl/register-atfork.c +@@ -21,6 +21,8 @@ + #include + #include + #include ++#include ++#include + + #define DYNARRAY_ELEMENT struct fork_handler + #define DYNARRAY_STRUCT fork_handler_list +@@ -29,7 +31,7 @@ + #include + + static struct fork_handler_list fork_handlers; +-static bool fork_handler_init = false; ++static uint64_t fork_handler_counter; + + static int atfork_lock = LLL_LOCK_INITIALIZER; + +@@ -39,11 +41,8 @@ __register_atfork (void (*prepare) (void), void (*parent) (void), + { + lll_lock (atfork_lock, LLL_PRIVATE); + +- if (!fork_handler_init) +- { +- fork_handler_list_init (&fork_handlers); +- fork_handler_init = true; +- } ++ if (fork_handler_counter == 0) ++ fork_handler_list_init (&fork_handlers); + + struct fork_handler *newp = fork_handler_list_emplace (&fork_handlers); + if (newp != NULL) +@@ -52,6 +51,13 @@ __register_atfork (void (*prepare) (void), void (*parent) (void), + newp->parent_handler = parent; + newp->child_handler = child; + newp->dso_handle = dso_handle; ++ ++ /* IDs assigned to handlers start at 1 and increment with handler ++ registration. Un-registering a handlers discards the corresponding ++ ID. It is not reused in future registrations. */ ++ if (INT_ADD_OVERFLOW (fork_handler_counter, 1)) ++ __libc_fatal ("fork handler counter overflow"); ++ newp->id = ++fork_handler_counter; + } + + /* Release the lock. */ +@@ -106,37 +112,111 @@ __unregister_atfork (void *dso_handle) + lll_unlock (atfork_lock, LLL_PRIVATE); + } + +-void +-__run_fork_handlers (enum __run_fork_handler_type who, _Bool do_locking) ++uint64_t ++__run_prefork_handlers (_Bool do_locking) + { +- struct fork_handler *runp; ++ uint64_t lastrun; + +- if (who == atfork_run_prepare) ++ if (do_locking) ++ lll_lock (atfork_lock, LLL_PRIVATE); ++ ++ /* We run prepare handlers from last to first. After fork, only ++ handlers up to the last handler found here (pre-fork) will be run. ++ Handlers registered during __run_prefork_handlers or ++ __run_postfork_handlers will be positioned after this last handler, and ++ since their prepare handlers won't be run now, their parent/child ++ handlers should also be ignored. */ ++ lastrun = fork_handler_counter; ++ ++ size_t sl = fork_handler_list_size (&fork_handlers); ++ for (size_t i = sl; i > 0;) + { +- if (do_locking) +- lll_lock (atfork_lock, LLL_PRIVATE); +- size_t sl = fork_handler_list_size (&fork_handlers); +- for (size_t i = sl; i > 0; i--) +- { +- runp = fork_handler_list_at (&fork_handlers, i - 1); +- if (runp->prepare_handler != NULL) +- runp->prepare_handler (); +- } ++ struct fork_handler *runp ++ = fork_handler_list_at (&fork_handlers, i - 1); ++ ++ uint64_t id = runp->id; ++ ++ if (runp->prepare_handler != NULL) ++ { ++ if (do_locking) ++ lll_unlock (atfork_lock, LLL_PRIVATE); ++ ++ runp->prepare_handler (); ++ ++ if (do_locking) ++ lll_lock (atfork_lock, LLL_PRIVATE); ++ } ++ ++ /* We unlocked, ran the handler, and locked again. In the ++ meanwhile, one or more deregistrations could have occurred leading ++ to the current (just run) handler being moved up the list or even ++ removed from the list itself. Since handler IDs are guaranteed to ++ to be in increasing order, the next handler has to have: */ ++ ++ /* A. An earlier position than the current one has. */ ++ i--; ++ ++ /* B. A lower ID than the current one does. The code below skips ++ any newly added handlers with higher IDs. */ ++ while (i > 0 ++ && fork_handler_list_at (&fork_handlers, i - 1)->id >= id) ++ i--; + } +- else ++ ++ return lastrun; ++} ++ ++void ++__run_postfork_handlers (enum __run_fork_handler_type who, _Bool do_locking, ++ uint64_t lastrun) ++{ ++ size_t sl = fork_handler_list_size (&fork_handlers); ++ for (size_t i = 0; i < sl;) + { +- size_t sl = fork_handler_list_size (&fork_handlers); +- for (size_t i = 0; i < sl; i++) +- { +- runp = fork_handler_list_at (&fork_handlers, i); +- if (who == atfork_run_child && runp->child_handler) +- runp->child_handler (); +- else if (who == atfork_run_parent && runp->parent_handler) +- runp->parent_handler (); +- } ++ struct fork_handler *runp = fork_handler_list_at (&fork_handlers, i); ++ uint64_t id = runp->id; ++ ++ /* prepare handlers were not run for handlers with ID > LASTRUN. ++ Thus, parent/child handlers will also not be run. */ ++ if (id > lastrun) ++ break; ++ + if (do_locking) +- lll_unlock (atfork_lock, LLL_PRIVATE); ++ lll_unlock (atfork_lock, LLL_PRIVATE); ++ ++ if (who == atfork_run_child && runp->child_handler) ++ runp->child_handler (); ++ else if (who == atfork_run_parent && runp->parent_handler) ++ runp->parent_handler (); ++ ++ if (do_locking) ++ lll_lock (atfork_lock, LLL_PRIVATE); ++ ++ /* We unlocked, ran the handler, and locked again. In the meanwhile, ++ one or more [de]registrations could have occurred. Due to this, ++ the list size must be updated. */ ++ sl = fork_handler_list_size (&fork_handlers); ++ ++ /* The just-run handler could also have moved up the list. */ ++ ++ if (sl > i && fork_handler_list_at (&fork_handlers, i)->id == id) ++ /* The position of the recently run handler hasn't changed. The ++ next handler to be run is an easy increment away. */ ++ i++; ++ else ++ { ++ /* The next handler to be run is the first handler in the list ++ to have an ID higher than the current one. */ ++ for (i = 0; i < sl; i++) ++ { ++ if (fork_handler_list_at (&fork_handlers, i)->id > id) ++ break; ++ } ++ } + } ++ ++ if (do_locking) ++ lll_unlock (atfork_lock, LLL_PRIVATE); + } + + +diff --git a/nptl/tst-atfork3.c b/nptl/tst-atfork3.c +new file mode 100644 +index 0000000000000000..bb2250e432ab79ad +--- /dev/null ++++ b/nptl/tst-atfork3.c +@@ -0,0 +1,118 @@ ++/* Check if pthread_atfork handler can call dlclose (BZ#24595). ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++/* Check if pthread_atfork handlers do not deadlock when calling a function ++ that might alter the internal fork handle list, such as dlclose. ++ ++ The test registers a callback set with pthread_atfork(), dlopen() a shared ++ library (nptl/tst-atfork3mod.c), calls an exported symbol from the library ++ (which in turn also registers atfork handlers), and calls fork to trigger ++ the callbacks. */ ++ ++static void *handler; ++static bool run_dlclose_prepare; ++static bool run_dlclose_parent; ++static bool run_dlclose_child; ++ ++static void ++prepare (void) ++{ ++ if (run_dlclose_prepare) ++ xdlclose (handler); ++} ++ ++static void ++parent (void) ++{ ++ if (run_dlclose_parent) ++ xdlclose (handler); ++} ++ ++static void ++child (void) ++{ ++ if (run_dlclose_child) ++ xdlclose (handler); ++} ++ ++static void ++proc_func (void *closure) ++{ ++} ++ ++static void ++do_test_generic (bool dlclose_prepare, bool dlclose_parent, bool dlclose_child) ++{ ++ run_dlclose_prepare = dlclose_prepare; ++ run_dlclose_parent = dlclose_parent; ++ run_dlclose_child = dlclose_child; ++ ++ handler = xdlopen ("tst-atfork3mod.so", RTLD_NOW); ++ ++ int (*atfork3mod_func)(void); ++ atfork3mod_func = xdlsym (handler, "atfork3mod_func"); ++ ++ atfork3mod_func (); ++ ++ struct support_capture_subprocess proc ++ = support_capture_subprocess (proc_func, NULL); ++ support_capture_subprocess_check (&proc, "tst-atfork3", 0, sc_allow_none); ++ ++ handler = atfork3mod_func = NULL; ++ ++ support_capture_subprocess_free (&proc); ++} ++ ++static void * ++thread_func (void *closure) ++{ ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ { ++ /* Make the process acts as multithread. */ ++ pthread_attr_t attr; ++ xpthread_attr_init (&attr); ++ xpthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); ++ xpthread_create (&attr, thread_func, NULL); ++ } ++ ++ TEST_COMPARE (pthread_atfork (prepare, parent, child), 0); ++ ++ do_test_generic (true /* prepare */, false /* parent */, false /* child */); ++ do_test_generic (false /* prepare */, true /* parent */, false /* child */); ++ do_test_generic (false /* prepare */, false /* parent */, true /* child */); ++ ++ return 0; ++} ++ ++#include +diff --git a/nptl/tst-atfork3mod.c b/nptl/tst-atfork3mod.c +new file mode 100644 +index 0000000000000000..6d0658cb9efdecbc +--- /dev/null ++++ b/nptl/tst-atfork3mod.c +@@ -0,0 +1,44 @@ ++/* Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++#include ++ ++static void ++mod_prepare (void) ++{ ++} ++ ++static void ++mod_parent (void) ++{ ++} ++ ++static void ++mod_child (void) ++{ ++} ++ ++int atfork3mod_func (void) ++{ ++ TEST_COMPARE (pthread_atfork (mod_prepare, mod_parent, mod_child), 0); ++ ++ return 0; ++} +diff --git a/nptl/tst-atfork4.c b/nptl/tst-atfork4.c +new file mode 100644 +index 0000000000000000..52dc87e73b846ab9 +--- /dev/null ++++ b/nptl/tst-atfork4.c +@@ -0,0 +1,128 @@ ++/* pthread_atfork supports handlers that call pthread_atfork or dlclose. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static void * ++thread_func (void *x) ++{ ++ return NULL; ++} ++ ++static unsigned int second_atfork_handler_runcount = 0; ++ ++static void ++second_atfork_handler (void) ++{ ++ second_atfork_handler_runcount++; ++} ++ ++static void *h = NULL; ++ ++static unsigned int atfork_handler_runcount = 0; ++ ++static void ++prepare (void) ++{ ++ /* These atfork handlers are registered while atfork handlers are being ++ executed and thus will not be executed during the corresponding ++ fork. */ ++ TEST_VERIFY_EXIT (pthread_atfork (second_atfork_handler, ++ second_atfork_handler, ++ second_atfork_handler) == 0); ++ ++ /* This will de-register the atfork handlers registered by the dlopen'd ++ library and so they will not be executed. */ ++ if (h != NULL) ++ { ++ xdlclose (h); ++ h = NULL; ++ } ++ ++ atfork_handler_runcount++; ++} ++ ++static void ++after (void) ++{ ++ atfork_handler_runcount++; ++} ++ ++static int ++do_test (void) ++{ ++ /* Make sure __libc_single_threaded is 0. */ ++ pthread_attr_t attr; ++ xpthread_attr_init (&attr); ++ xpthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); ++ xpthread_create (&attr, thread_func, NULL); ++ ++ void (*reg_atfork_handlers) (void); ++ ++ h = xdlopen ("tst-atfork4mod.so", RTLD_LAZY); ++ ++ reg_atfork_handlers = xdlsym (h, "reg_atfork_handlers"); ++ ++ reg_atfork_handlers (); ++ ++ /* We register our atfork handlers *after* loading the module so that our ++ prepare handler is called first at fork, where we then dlclose the ++ module before its prepare handler has a chance to be called. */ ++ TEST_VERIFY_EXIT (pthread_atfork (prepare, after, after) == 0); ++ ++ pid_t pid = xfork (); ++ ++ /* Both the parent and the child processes should observe this. */ ++ TEST_VERIFY_EXIT (atfork_handler_runcount == 2); ++ TEST_VERIFY_EXIT (second_atfork_handler_runcount == 0); ++ ++ if (pid > 0) ++ { ++ int childstat; ++ ++ xwaitpid (-1, &childstat, 0); ++ TEST_VERIFY_EXIT (WIFEXITED (childstat) ++ && WEXITSTATUS (childstat) == 0); ++ ++ /* This time, the second set of atfork handlers should also be called ++ since the handlers are already in place before fork is called. */ ++ ++ pid = xfork (); ++ ++ TEST_VERIFY_EXIT (atfork_handler_runcount == 4); ++ TEST_VERIFY_EXIT (second_atfork_handler_runcount == 2); ++ ++ if (pid > 0) ++ { ++ xwaitpid (-1, &childstat, 0); ++ TEST_VERIFY_EXIT (WIFEXITED (childstat) ++ && WEXITSTATUS (childstat) == 0); ++ } ++ } ++ ++ return 0; ++} ++ ++#include +diff --git a/nptl/tst-atfork4mod.c b/nptl/tst-atfork4mod.c +new file mode 100644 +index 0000000000000000..e111efeb185916e0 +--- /dev/null ++++ b/nptl/tst-atfork4mod.c +@@ -0,0 +1,48 @@ ++/* pthread_atfork supports handlers that call pthread_atfork or dlclose. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++/* This dynamically loaded library simply registers its atfork handlers when ++ asked to. The atfork handlers should never be executed because the ++ library is unloaded before fork is called by the test program. */ ++ ++static void ++prepare (void) ++{ ++ abort (); ++} ++ ++static void ++parent (void) ++{ ++ abort (); ++} ++ ++static void ++child (void) ++{ ++ abort (); ++} ++ ++void ++reg_atfork_handlers (void) ++{ ++ pthread_atfork (prepare, parent, child); ++} +diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c +index b4d20fa652f4ba3b..1324b813136764fc 100644 +--- a/sysdeps/nptl/fork.c ++++ b/sysdeps/nptl/fork.c +@@ -54,8 +54,9 @@ __libc_fork (void) + signal handlers. POSIX requires that fork is async-signal-safe, + but our current fork implementation is not. */ + bool multiple_threads = THREAD_GETMEM (THREAD_SELF, header.multiple_threads); ++ uint64_t lastrun; + +- __run_fork_handlers (atfork_run_prepare, multiple_threads); ++ lastrun = __run_prefork_handlers (multiple_threads); + + /* If we are not running multiple threads, we do not have to + preserve lock state. If fork runs from a signal handler, only +@@ -129,7 +130,7 @@ __libc_fork (void) + __rtld_lock_initialize (GL(dl_load_tls_lock)); + + /* Run the handlers registered for the child. */ +- __run_fork_handlers (atfork_run_child, multiple_threads); ++ __run_postfork_handlers (atfork_run_child, multiple_threads, lastrun); + } + else + { +@@ -144,7 +145,7 @@ __libc_fork (void) + } + + /* Run the handlers registered for the parent. */ +- __run_fork_handlers (atfork_run_parent, multiple_threads); ++ __run_postfork_handlers (atfork_run_parent, multiple_threads, lastrun); + } + + return pid; +diff --git a/sysdeps/nptl/fork.h b/sysdeps/nptl/fork.h +index bef2b7a8a6af8635..222c4f618970a455 100644 +--- a/sysdeps/nptl/fork.h ++++ b/sysdeps/nptl/fork.h +@@ -31,6 +31,7 @@ struct fork_handler + void (*parent_handler) (void); + void (*child_handler) (void); + void *dso_handle; ++ uint64_t id; + }; + + /* Function to call to unregister fork handlers. */ +@@ -44,19 +45,18 @@ enum __run_fork_handler_type + atfork_run_parent + }; + +-/* Run the atfork handlers and lock/unlock the internal lock depending +- of the WHO argument: ++/* Run the atfork prepare handlers in the reverse order of registration and ++ return the ID of the last registered handler. If DO_LOCKING is true, the ++ internal lock is held locked upon return. */ ++extern uint64_t __run_prefork_handlers (_Bool do_locking) attribute_hidden; + +- - atfork_run_prepare: run all the PREPARE_HANDLER in reverse order of +- insertion and locks the internal lock. +- - atfork_run_child: run all the CHILD_HANDLER and unlocks the internal +- lock. +- - atfork_run_parent: run all the PARENT_HANDLER and unlocks the internal +- lock. +- +- Perform locking only if DO_LOCKING. */ +-extern void __run_fork_handlers (enum __run_fork_handler_type who, +- _Bool do_locking) attribute_hidden; ++/* Given a handler type (parent or child), run all the atfork handlers in ++ the order of registration up to and including the handler with id equal ++ to LASTRUN. If DO_LOCKING is true, the internal lock is unlocked prior ++ to return. */ ++extern void __run_postfork_handlers (enum __run_fork_handler_type who, ++ _Bool do_locking, ++ uint64_t lastrun) attribute_hidden; + + /* C library side function to register new fork handlers. */ + extern int __register_atfork (void (*__prepare) (void), diff --git a/glibc-rh2084564.patch b/glibc-rh1961109.patch similarity index 100% rename from glibc-rh2084564.patch rename to glibc-rh1961109.patch diff --git a/glibc-rh1982608.patch b/glibc-rh1982608.patch new file mode 100644 index 0000000..6f67ed6 --- /dev/null +++ b/glibc-rh1982608.patch @@ -0,0 +1,2216 @@ +This is a rebase of posix/glob.c from upstream (gnulib->glibc->rhel). + +Relevent upstream commits: + +7c477b57a31487eda516db02b9e04f22d1a6e6af posix/glob.c: update from gnulib + (This is the master commit to which we're syncing) + +gnulib commit 98f034a0c2ba8917c96f363de1a8d66244e411da + (This is the gnulib commit to which glibc upstream sync'd) + +Additional glibc upstream commits of note: +84f7ce84474c1648ce96884f1c91ca7b97ca3fc2 posix: Add glob64 with 64-bit time_t support + (just posix/glob.c and sysdeps/gnu/glob64-lstat-compat.c) +9a7ab0769b295cbf5232140401742a8f34bda3de hurd: Fix glob lstat compatibility +4883360415f1ed772ba44decc501d59deb17bdf0 posix: Sync glob code with gnulib +04986243d1af37ac0177ed2f9db0a066ebd2b212 Remove internal usage of extensible stat functions +ddc650e9b3dc916eab417ce9f79e67337b05035c Fix use-after-free in glob when expanding ~user (bug 25414) + + +diff -rup a/posix/glob-lstat-compat.c b/posix/glob-lstat-compat.c +--- a/posix/glob-lstat-compat.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/posix/glob-lstat-compat.c 2022-05-02 22:49:06.504676711 -0400 +@@ -28,7 +28,8 @@ + # define GLOB_ATTRIBUTE attribute_compat_text_section + + /* Avoid calling gl_lstat with GLOB_ALTDIRFUNC. */ +-# define GLOB_NO_LSTAT ++# define GLOB_LSTAT gl_stat ++# define GLOB_LSTAT64 __stat64 + + # include + +diff -rup a/posix/glob.c b/posix/glob.c +--- a/posix/glob.c 2022-05-03 14:37:52.959042051 -0400 ++++ b/posix/glob.c 2022-05-02 22:49:18.655134696 -0400 +@@ -1,4 +1,4 @@ +-/* Copyright (C) 1991-2018 Free Software Foundation, Inc. ++/* Copyright (C) 1991-2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or +@@ -13,11 +13,22 @@ + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see +- . */ ++ . */ ++ ++#ifndef _LIBC ++ ++/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc ++ optimizes away the pattern == NULL test below. */ ++# define _GL_ARG_NONNULL(params) ++ ++# include ++ ++#endif + + #include + + #include ++#include + #include + #include + #include +@@ -26,7 +37,7 @@ + #include + #include + +-#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ ++#if defined _WIN32 && ! defined __CYGWIN__ + # define WINDOWS32 + #endif + +@@ -46,30 +57,38 @@ + # define sysconf(id) __sysconf (id) + # define closedir(dir) __closedir (dir) + # define opendir(name) __opendir (name) ++# undef dirfd ++# define dirfd(str) __dirfd (str) + # define readdir(str) __readdir64 (str) + # define getpwnam_r(name, bufp, buf, len, res) \ + __getpwnam_r (name, bufp, buf, len, res) +-# ifndef __lstat64 +-# define __lstat64(fname, buf) __lxstat64 (_STAT_VER, fname, buf) ++# define FLEXIBLE_ARRAY_MEMBER ++# ifndef struct_stat ++# define struct_stat struct stat + # endif +-# ifndef __stat64 +-# define __stat64(fname, buf) __xstat64 (_STAT_VER, fname, buf) ++# ifndef struct_stat64 ++# define struct_stat64 struct stat64 ++# endif ++# ifndef GLOB_LSTAT ++# define GLOB_LSTAT gl_lstat ++# endif ++# ifndef GLOB_FSTATAT64 ++# define GLOB_FSTATAT64 __fstatat64 + # endif +-# define struct_stat64 struct stat64 +-# define FLEXIBLE_ARRAY_MEMBER + # include + #else /* !_LIBC */ + # define __glob glob + # define __getlogin_r(buf, len) getlogin_r (buf, len) +-# define __lstat64(fname, buf) lstat (fname, buf) +-# define __stat64(fname, buf) stat (fname, buf) + # define __fxstatat64(_, d, f, st, flag) fstatat (d, f, st, flag) +-# define struct_stat64 struct stat + # ifndef __MVS__ + # define __alloca alloca + # endif + # define __readdir readdir + # define COMPILE_GLOB64 ++# define struct_stat struct stat ++# define struct_stat64 struct stat ++# define GLOB_LSTAT gl_lstat ++# define GLOB_FSTATAT64 fstatat + #endif /* _LIBC */ + + #include +@@ -80,7 +99,9 @@ + + static const char *next_brace_sub (const char *begin, int flags) __THROWNL; + +-typedef uint_fast8_t dirent_type; ++/* The type of ((struct dirent *) 0)->d_type is 'unsigned char' on most ++ platforms, but 'unsigned int' in the mingw from mingw.org. */ ++typedef uint_fast32_t dirent_type; + + #if !defined _LIBC && !defined HAVE_STRUCT_DIRENT_D_TYPE + /* Any distinct values will do here. +@@ -119,9 +140,9 @@ readdir_result_type (struct readdir_resu + /* Construct an initializer for a struct readdir_result object from a + struct dirent *. No copy of the name is made. */ + #define READDIR_RESULT_INITIALIZER(source) \ +- { \ +- source->d_name, \ +- D_TYPE_TO_RESULT (source) \ ++ { \ ++ source->d_name, \ ++ D_TYPE_TO_RESULT (source) \ + } + + /* Call gl_readdir on STREAM. This macro can be overridden to reduce +@@ -186,22 +207,15 @@ glob_lstat (glob_t *pglob, int flags, co + { + /* Use on glob-lstat-compat.c to provide a compat symbol which does not + use lstat / gl_lstat. */ +-#ifdef GLOB_NO_LSTAT +-# define GL_LSTAT gl_stat +-# define LSTAT64 __stat64 +-#else +-# define GL_LSTAT gl_lstat +-# define LSTAT64 __lstat64 +-#endif +- + union + { +- struct stat st; ++ struct_stat st; + struct_stat64 st64; + } ust; + return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC) +- ? pglob->GL_LSTAT (fullname, &ust.st) +- : LSTAT64 (fullname, &ust.st64)); ++ ? pglob->GLOB_LSTAT (fullname, &ust.st) ++ : GLOB_FSTATAT64 (AT_FDCWD, fullname, &ust.st64, ++ AT_SYMLINK_NOFOLLOW)); + } + + /* Set *R = A + B. Return true if the answer is mathematically +@@ -211,7 +225,7 @@ glob_lstat (glob_t *pglob, int flags, co + static bool + size_add_wrapv (size_t a, size_t b, size_t *r) + { +-#if 5 <= __GNUC__ && !defined __ICC ++#if 7 <= __GNUC__ && !defined __ICC + return __builtin_add_overflow (a, b, r); + #else + *r = a + b; +@@ -228,8 +242,8 @@ glob_use_alloca (size_t alloca_used, siz + } + + static int glob_in_dir (const char *pattern, const char *directory, +- int flags, int (*errfunc) (const char *, int), +- glob_t *pglob, size_t alloca_used); ++ int flags, int (*errfunc) (const char *, int), ++ glob_t *pglob, size_t alloca_used); + static int prefix_array (const char *prefix, char **array, size_t n) __THROWNL; + static int collated_compare (const void *, const void *) __THROWNL; + +@@ -239,11 +253,12 @@ static int collated_compare (const void + static bool + is_dir (char const *filename, int flags, glob_t const *pglob) + { +- struct stat st; ++ struct_stat st; + struct_stat64 st64; + return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC) + ? pglob->gl_stat (filename, &st) == 0 && S_ISDIR (st.st_mode) +- : __stat64 (filename, &st64) == 0 && S_ISDIR (st64.st_mode)); ++ : (GLOB_FSTATAT64 (AT_FDCWD, filename, &st64, 0) == 0 ++ && S_ISDIR (st64.st_mode))); + } + + /* Find the end of the sub-pattern in a brace expression. */ +@@ -254,17 +269,17 @@ next_brace_sub (const char *cp, int flag + while (*cp != '\0') + if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\') + { +- if (*++cp == '\0') +- break; +- ++cp; ++ if (*++cp == '\0') ++ break; ++ ++cp; + } + else + { +- if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0)) +- break; ++ if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0)) ++ break; + +- if (*cp++ == '{') +- depth++; ++ if (*cp++ == '{') ++ depth++; + } + + return *cp != '\0' ? cp : NULL; +@@ -285,7 +300,7 @@ next_brace_sub (const char *cp, int flag + int + GLOB_ATTRIBUTE + __glob (const char *pattern, int flags, int (*errfunc) (const char *, int), +- glob_t *pglob) ++ glob_t *pglob) + { + const char *filename; + char *dirname = NULL; +@@ -319,22 +334,22 @@ __glob (const char *pattern, int flags, + { + pglob->gl_pathc = 0; + if (!(flags & GLOB_DOOFFS)) +- pglob->gl_pathv = NULL; ++ pglob->gl_pathv = NULL; + else +- { +- size_t i; ++ { ++ size_t i; + +- if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *)) +- return GLOB_NOSPACE; ++ if (pglob->gl_offs >= ~((size_t) 0) / sizeof (char *)) ++ return GLOB_NOSPACE; + +- pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1) +- * sizeof (char *)); +- if (pglob->gl_pathv == NULL) +- return GLOB_NOSPACE; +- +- for (i = 0; i <= pglob->gl_offs; ++i) +- pglob->gl_pathv[i] = NULL; +- } ++ pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1) ++ * sizeof (char *)); ++ if (pglob->gl_pathv == NULL) ++ return GLOB_NOSPACE; ++ ++ for (i = 0; i <= pglob->gl_offs; ++i) ++ pglob->gl_pathv[i] = NULL; ++ } + } + + if (flags & GLOB_BRACE) +@@ -342,129 +357,129 @@ __glob (const char *pattern, int flags, + const char *begin; + + if (flags & GLOB_NOESCAPE) +- begin = strchr (pattern, '{'); ++ begin = strchr (pattern, '{'); + else +- { +- begin = pattern; +- while (1) +- { +- if (*begin == '\0') +- { +- begin = NULL; +- break; +- } +- +- if (*begin == '\\' && begin[1] != '\0') +- ++begin; +- else if (*begin == '{') +- break; +- +- ++begin; +- } +- } ++ { ++ begin = pattern; ++ while (1) ++ { ++ if (*begin == '\0') ++ { ++ begin = NULL; ++ break; ++ } ++ ++ if (*begin == '\\' && begin[1] != '\0') ++ ++begin; ++ else if (*begin == '{') ++ break; ++ ++ ++begin; ++ } ++ } + + if (begin != NULL) +- { +- /* Allocate working buffer large enough for our work. Note that +- we have at least an opening and closing brace. */ +- size_t firstc; +- char *alt_start; +- const char *p; +- const char *next; +- const char *rest; +- size_t rest_len; +- char *onealt; +- size_t pattern_len = strlen (pattern) - 1; +- int alloca_onealt = glob_use_alloca (alloca_used, pattern_len); +- if (alloca_onealt) +- onealt = alloca_account (pattern_len, alloca_used); +- else +- { +- onealt = malloc (pattern_len); +- if (onealt == NULL) +- return GLOB_NOSPACE; +- } +- +- /* We know the prefix for all sub-patterns. */ +- alt_start = mempcpy (onealt, pattern, begin - pattern); +- +- /* Find the first sub-pattern and at the same time find the +- rest after the closing brace. */ +- next = next_brace_sub (begin + 1, flags); +- if (next == NULL) +- { +- /* It is an invalid expression. */ +- illegal_brace: +- if (__glibc_unlikely (!alloca_onealt)) +- free (onealt); +- flags &= ~GLOB_BRACE; +- goto no_brace; +- } +- +- /* Now find the end of the whole brace expression. */ +- rest = next; +- while (*rest != '}') +- { +- rest = next_brace_sub (rest + 1, flags); +- if (rest == NULL) +- /* It is an illegal expression. */ +- goto illegal_brace; +- } +- /* Please note that we now can be sure the brace expression +- is well-formed. */ +- rest_len = strlen (++rest) + 1; +- +- /* We have a brace expression. BEGIN points to the opening {, +- NEXT points past the terminator of the first element, and END +- points past the final }. We will accumulate result names from +- recursive runs for each brace alternative in the buffer using +- GLOB_APPEND. */ +- firstc = pglob->gl_pathc; +- +- p = begin + 1; +- while (1) +- { +- int result; +- +- /* Construct the new glob expression. */ +- mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len); +- +- result = __glob (onealt, +- ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC)) +- | GLOB_APPEND), +- errfunc, pglob); +- +- /* If we got an error, return it. */ +- if (result && result != GLOB_NOMATCH) +- { +- if (__glibc_unlikely (!alloca_onealt)) +- free (onealt); +- if (!(flags & GLOB_APPEND)) +- { +- globfree (pglob); +- pglob->gl_pathc = 0; +- } +- return result; +- } +- +- if (*next == '}') +- /* We saw the last entry. */ +- break; +- +- p = next + 1; +- next = next_brace_sub (p, flags); +- assert (next != NULL); +- } +- +- if (__glibc_unlikely (!alloca_onealt)) +- free (onealt); +- +- if (pglob->gl_pathc != firstc) +- /* We found some entries. */ +- return 0; +- else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) +- return GLOB_NOMATCH; +- } ++ { ++ /* Allocate working buffer large enough for our work. Note that ++ we have at least an opening and closing brace. */ ++ size_t firstc; ++ char *alt_start; ++ const char *p; ++ const char *next; ++ const char *rest; ++ size_t rest_len; ++ char *onealt; ++ size_t pattern_len = strlen (pattern) - 1; ++ int alloca_onealt = glob_use_alloca (alloca_used, pattern_len); ++ if (alloca_onealt) ++ onealt = alloca_account (pattern_len, alloca_used); ++ else ++ { ++ onealt = malloc (pattern_len); ++ if (onealt == NULL) ++ return GLOB_NOSPACE; ++ } ++ ++ /* We know the prefix for all sub-patterns. */ ++ alt_start = mempcpy (onealt, pattern, begin - pattern); ++ ++ /* Find the first sub-pattern and at the same time find the ++ rest after the closing brace. */ ++ next = next_brace_sub (begin + 1, flags); ++ if (next == NULL) ++ { ++ /* It is an invalid expression. */ ++ illegal_brace: ++ if (__glibc_unlikely (!alloca_onealt)) ++ free (onealt); ++ flags &= ~GLOB_BRACE; ++ goto no_brace; ++ } ++ ++ /* Now find the end of the whole brace expression. */ ++ rest = next; ++ while (*rest != '}') ++ { ++ rest = next_brace_sub (rest + 1, flags); ++ if (rest == NULL) ++ /* It is an illegal expression. */ ++ goto illegal_brace; ++ } ++ /* Please note that we now can be sure the brace expression ++ is well-formed. */ ++ rest_len = strlen (++rest) + 1; ++ ++ /* We have a brace expression. BEGIN points to the opening {, ++ NEXT points past the terminator of the first element, and END ++ points past the final }. We will accumulate result names from ++ recursive runs for each brace alternative in the buffer using ++ GLOB_APPEND. */ ++ firstc = pglob->gl_pathc; ++ ++ p = begin + 1; ++ while (1) ++ { ++ int result; ++ ++ /* Construct the new glob expression. */ ++ mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len); ++ ++ result = __glob (onealt, ++ ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC)) ++ | GLOB_APPEND), ++ errfunc, pglob); ++ ++ /* If we got an error, return it. */ ++ if (result && result != GLOB_NOMATCH) ++ { ++ if (__glibc_unlikely (!alloca_onealt)) ++ free (onealt); ++ if (!(flags & GLOB_APPEND)) ++ { ++ globfree (pglob); ++ pglob->gl_pathc = 0; ++ } ++ return result; ++ } ++ ++ if (*next == '}') ++ /* We saw the last entry. */ ++ break; ++ ++ p = next + 1; ++ next = next_brace_sub (p, flags); ++ assert (next != NULL); ++ } ++ ++ if (__glibc_unlikely (!alloca_onealt)) ++ free (onealt); ++ ++ if (pglob->gl_pathc != firstc) ++ /* We found some entries. */ ++ return 0; ++ else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) ++ return GLOB_NOMATCH; ++ } + } + + no_brace: +@@ -486,33 +501,33 @@ __glob (const char *pattern, int flags, + if (filename == NULL) + { + /* This can mean two things: a simple name or "~name". The latter +- case is nothing but a notation for a directory. */ ++ case is nothing but a notation for a directory. */ + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') +- { +- dirname = (char *) pattern; +- dirlen = strlen (pattern); +- +- /* Set FILENAME to NULL as a special flag. This is ugly but +- other solutions would require much more code. We test for +- this special case below. */ +- filename = NULL; +- } ++ { ++ dirname = (char *) pattern; ++ dirlen = strlen (pattern); ++ ++ /* Set FILENAME to NULL as a special flag. This is ugly but ++ other solutions would require much more code. We test for ++ this special case below. */ ++ filename = NULL; ++ } + else +- { +- if (__glibc_unlikely (pattern[0] == '\0')) +- { +- dirs.gl_pathv = NULL; +- goto no_matches; +- } +- +- filename = pattern; +- dirname = (char *) "."; +- dirlen = 0; +- } ++ { ++ if (__glibc_unlikely (pattern[0] == '\0')) ++ { ++ dirs.gl_pathv = NULL; ++ goto no_matches; ++ } ++ ++ filename = pattern; ++ dirname = (char *) "."; ++ dirlen = 0; ++ } + } + else if (filename == pattern +- || (filename == pattern + 1 && pattern[0] == '\\' +- && (flags & GLOB_NOESCAPE) == 0)) ++ || (filename == pattern + 1 && pattern[0] == '\\' ++ && (flags & GLOB_NOESCAPE) == 0)) + { + /* "/pattern" or "\\/pattern". */ + dirname = (char *) "/"; +@@ -525,32 +540,32 @@ __glob (const char *pattern, int flags, + dirlen = filename - pattern; + #if defined __MSDOS__ || defined WINDOWS32 + if (*filename == ':' +- || (filename > pattern + 1 && filename[-1] == ':')) +- { +- char *drive_spec; +- +- ++dirlen; +- drive_spec = __alloca (dirlen + 1); +- *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0'; +- /* For now, disallow wildcards in the drive spec, to +- prevent infinite recursion in glob. */ +- if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE))) +- return GLOB_NOMATCH; +- /* If this is "d:pattern", we need to copy ':' to DIRNAME +- as well. If it's "d:/pattern", don't remove the slash +- from "d:/", since "d:" and "d:/" are not the same.*/ +- } ++ || (filename > pattern + 1 && filename[-1] == ':')) ++ { ++ char *drive_spec; ++ ++ ++dirlen; ++ drive_spec = __alloca (dirlen + 1); ++ *((char *) mempcpy (drive_spec, pattern, dirlen)) = '\0'; ++ /* For now, disallow wildcards in the drive spec, to ++ prevent infinite recursion in glob. */ ++ if (__glob_pattern_p (drive_spec, !(flags & GLOB_NOESCAPE))) ++ return GLOB_NOMATCH; ++ /* If this is "d:pattern", we need to copy ':' to DIRNAME ++ as well. If it's "d:/pattern", don't remove the slash ++ from "d:/", since "d:" and "d:/" are not the same.*/ ++ } + #endif + + if (glob_use_alloca (alloca_used, dirlen + 1)) +- newp = alloca_account (dirlen + 1, alloca_used); ++ newp = alloca_account (dirlen + 1, alloca_used); + else +- { +- newp = malloc (dirlen + 1); +- if (newp == NULL) +- return GLOB_NOSPACE; +- malloc_dirname = 1; +- } ++ { ++ newp = malloc (dirlen + 1); ++ if (newp == NULL) ++ return GLOB_NOSPACE; ++ malloc_dirname = 1; ++ } + *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; + dirname = newp; + ++filename; +@@ -566,363 +581,383 @@ __glob (const char *pattern, int flags, + + if (filename[0] == '\0' && dirlen > 1 && !drive_root) + /* "pattern/". Expand "pattern", appending slashes. */ +- { +- int orig_flags = flags; +- if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\') +- { +- /* "pattern\\/". Remove the final backslash if it hasn't +- been quoted. */ +- char *p = (char *) &dirname[dirlen - 1]; +- +- while (p > dirname && p[-1] == '\\') --p; +- if ((&dirname[dirlen] - p) & 1) +- { +- *(char *) &dirname[--dirlen] = '\0'; +- flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); +- } +- } +- int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob); +- if (val == 0) +- pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) +- | (flags & GLOB_MARK)); +- else if (val == GLOB_NOMATCH && flags != orig_flags) +- { +- /* Make sure globfree (&dirs); is a nop. */ +- dirs.gl_pathv = NULL; +- flags = orig_flags; +- oldcount = pglob->gl_pathc + pglob->gl_offs; +- goto no_matches; +- } +- retval = val; +- goto out; +- } ++ { ++ int orig_flags = flags; ++ if (!(flags & GLOB_NOESCAPE) && dirname[dirlen - 1] == '\\') ++ { ++ /* "pattern\\/". Remove the final backslash if it hasn't ++ been quoted. */ ++ char *p = (char *) &dirname[dirlen - 1]; ++ ++ while (p > dirname && p[-1] == '\\') --p; ++ if ((&dirname[dirlen] - p) & 1) ++ { ++ *(char *) &dirname[--dirlen] = '\0'; ++ flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); ++ } ++ } ++ int val = __glob (dirname, flags | GLOB_MARK, errfunc, pglob); ++ if (val == 0) ++ pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) ++ | (flags & GLOB_MARK)); ++ else if (val == GLOB_NOMATCH && flags != orig_flags) ++ { ++ /* Make sure globfree (&dirs); is a nop. */ ++ dirs.gl_pathv = NULL; ++ flags = orig_flags; ++ oldcount = pglob->gl_pathc + pglob->gl_offs; ++ goto no_matches; ++ } ++ retval = val; ++ goto out; ++ } + } + + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') + { + if (dirname[1] == '\0' || dirname[1] == '/' +- || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\' +- && (dirname[2] == '\0' || dirname[2] == '/'))) +- { +- /* Look up home directory. */ +- char *home_dir = getenv ("HOME"); +- int malloc_home_dir = 0; +- if (home_dir == NULL || home_dir[0] == '\0') +- { ++ || (!(flags & GLOB_NOESCAPE) && dirname[1] == '\\' ++ && (dirname[2] == '\0' || dirname[2] == '/'))) ++ { ++ /* Look up home directory. */ ++ char *home_dir = getenv ("HOME"); ++ int malloc_home_dir = 0; ++ if (home_dir == NULL || home_dir[0] == '\0') ++ { + #ifdef WINDOWS32 +- /* Windows NT defines HOMEDRIVE and HOMEPATH. But give +- preference to HOME, because the user can change HOME. */ +- const char *home_drive = getenv ("HOMEDRIVE"); +- const char *home_path = getenv ("HOMEPATH"); +- +- if (home_drive != NULL && home_path != NULL) +- { +- size_t home_drive_len = strlen (home_drive); +- size_t home_path_len = strlen (home_path); +- char *mem = alloca (home_drive_len + home_path_len + 1); +- +- memcpy (mem, home_drive, home_drive_len); +- memcpy (mem + home_drive_len, home_path, home_path_len + 1); +- home_dir = mem; +- } +- else +- home_dir = "c:/users/default"; /* poor default */ ++ /* Windows NT defines HOMEDRIVE and HOMEPATH. But give ++ preference to HOME, because the user can change HOME. */ ++ const char *home_drive = getenv ("HOMEDRIVE"); ++ const char *home_path = getenv ("HOMEPATH"); ++ ++ if (home_drive != NULL && home_path != NULL) ++ { ++ size_t home_drive_len = strlen (home_drive); ++ size_t home_path_len = strlen (home_path); ++ char *mem = alloca (home_drive_len + home_path_len + 1); ++ ++ memcpy (mem, home_drive, home_drive_len); ++ memcpy (mem + home_drive_len, home_path, home_path_len + 1); ++ home_dir = mem; ++ } ++ else ++ home_dir = "c:/users/default"; /* poor default */ + #else +- int err; +- struct passwd *p; +- struct passwd pwbuf; +- struct scratch_buffer s; +- scratch_buffer_init (&s); +- while (true) +- { +- p = NULL; +- err = __getlogin_r (s.data, s.length); +- if (err == 0) +- { ++ int err; ++ struct passwd *p; ++ struct passwd pwbuf; ++ struct scratch_buffer s; ++ scratch_buffer_init (&s); ++ while (true) ++ { ++ p = NULL; ++ err = __getlogin_r (s.data, s.length); ++ if (err == 0) ++ { + # if defined HAVE_GETPWNAM_R || defined _LIBC +- size_t ssize = strlen (s.data) + 1; +- char *sdata = s.data; +- err = getpwnam_r (sdata, &pwbuf, sdata + ssize, +- s.length - ssize, &p); ++ size_t ssize = strlen (s.data) + 1; ++ char *sdata = s.data; ++ err = getpwnam_r (sdata, &pwbuf, sdata + ssize, ++ s.length - ssize, &p); + # else +- p = getpwnam (s.data); +- if (p == NULL) +- err = errno; ++ p = getpwnam (s.data); ++ if (p == NULL) ++ err = errno; + # endif +- } +- if (err != ERANGE) +- break; +- if (!scratch_buffer_grow (&s)) +- { +- retval = GLOB_NOSPACE; +- goto out; +- } +- } +- if (err == 0) +- { +- home_dir = strdup (p->pw_dir); +- malloc_home_dir = 1; +- } +- scratch_buffer_free (&s); +- if (err == 0 && home_dir == NULL) +- { +- retval = GLOB_NOSPACE; +- goto out; +- } ++ } ++ if (err != ERANGE) ++ break; ++ if (!scratch_buffer_grow (&s)) ++ { ++ retval = GLOB_NOSPACE; ++ goto out; ++ } ++ } ++ if (err == 0) ++ { ++ home_dir = strdup (p->pw_dir); ++ malloc_home_dir = 1; ++ } ++ scratch_buffer_free (&s); ++ if (err == 0 && home_dir == NULL) ++ { ++ retval = GLOB_NOSPACE; ++ goto out; ++ } + #endif /* WINDOWS32 */ +- } +- if (home_dir == NULL || home_dir[0] == '\0') +- { +- if (__glibc_unlikely (malloc_home_dir)) +- free (home_dir); +- if (flags & GLOB_TILDE_CHECK) +- { +- retval = GLOB_NOMATCH; +- goto out; +- } +- else +- { +- home_dir = (char *) "~"; /* No luck. */ +- malloc_home_dir = 0; +- } +- } +- /* Now construct the full directory. */ +- if (dirname[1] == '\0') +- { +- if (__glibc_unlikely (malloc_dirname)) +- free (dirname); +- +- dirname = home_dir; +- dirlen = strlen (dirname); +- malloc_dirname = malloc_home_dir; +- } +- else +- { +- char *newp; +- size_t home_len = strlen (home_dir); +- int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen); +- if (use_alloca) +- newp = alloca_account (home_len + dirlen, alloca_used); +- else +- { +- newp = malloc (home_len + dirlen); +- if (newp == NULL) +- { +- if (__glibc_unlikely (malloc_home_dir)) +- free (home_dir); +- retval = GLOB_NOSPACE; +- goto out; +- } +- } +- +- mempcpy (mempcpy (newp, home_dir, home_len), +- &dirname[1], dirlen); +- +- if (__glibc_unlikely (malloc_dirname)) +- free (dirname); +- +- dirname = newp; +- dirlen += home_len - 1; +- malloc_dirname = !use_alloca; +- +- if (__glibc_unlikely (malloc_home_dir)) +- free (home_dir); +- } +- dirname_modified = 1; +- } ++ } ++ if (home_dir == NULL || home_dir[0] == '\0') ++ { ++ if (__glibc_unlikely (malloc_home_dir)) ++ free (home_dir); ++ if (flags & GLOB_TILDE_CHECK) ++ { ++ retval = GLOB_NOMATCH; ++ goto out; ++ } ++ else ++ { ++ home_dir = (char *) "~"; /* No luck. */ ++ malloc_home_dir = 0; ++ } ++ } ++ /* Now construct the full directory. */ ++ if (dirname[1] == '\0') ++ { ++ if (__glibc_unlikely (malloc_dirname)) ++ free (dirname); ++ ++ dirname = home_dir; ++ dirlen = strlen (dirname); ++ malloc_dirname = malloc_home_dir; ++ } ++ else ++ { ++ char *newp; ++ size_t home_len = strlen (home_dir); ++ int use_alloca = glob_use_alloca (alloca_used, home_len + dirlen); ++ if (use_alloca) ++ newp = alloca_account (home_len + dirlen, alloca_used); ++ else ++ { ++ newp = malloc (home_len + dirlen); ++ if (newp == NULL) ++ { ++ if (__glibc_unlikely (malloc_home_dir)) ++ free (home_dir); ++ retval = GLOB_NOSPACE; ++ goto out; ++ } ++ } ++ ++ mempcpy (mempcpy (newp, home_dir, home_len), ++ &dirname[1], dirlen); ++ ++ if (__glibc_unlikely (malloc_dirname)) ++ free (dirname); ++ ++ dirname = newp; ++ dirlen += home_len - 1; ++ malloc_dirname = !use_alloca; ++ ++ if (__glibc_unlikely (malloc_home_dir)) ++ free (home_dir); ++ } ++ dirname_modified = 1; ++ } + else +- { ++ { + #ifndef WINDOWS32 +- char *end_name = strchr (dirname, '/'); +- char *user_name; +- int malloc_user_name = 0; +- char *unescape = NULL; +- +- if (!(flags & GLOB_NOESCAPE)) +- { +- if (end_name == NULL) +- { +- unescape = strchr (dirname, '\\'); +- if (unescape) +- end_name = strchr (unescape, '\0'); +- } +- else +- unescape = memchr (dirname, '\\', end_name - dirname); +- } +- if (end_name == NULL) +- user_name = dirname + 1; +- else +- { +- char *newp; +- if (glob_use_alloca (alloca_used, end_name - dirname)) +- newp = alloca_account (end_name - dirname, alloca_used); +- else +- { +- newp = malloc (end_name - dirname); +- if (newp == NULL) +- { +- retval = GLOB_NOSPACE; +- goto out; +- } +- malloc_user_name = 1; +- } +- if (unescape != NULL) +- { +- char *p = mempcpy (newp, dirname + 1, +- unescape - dirname - 1); +- char *q = unescape; +- while (q != end_name) +- { +- if (*q == '\\') +- { +- if (q + 1 == end_name) +- { +- /* "~fo\\o\\" unescape to user_name "foo\\", +- but "~fo\\o\\/" unescape to user_name +- "foo". */ +- if (filename == NULL) +- *p++ = '\\'; +- break; +- } +- ++q; +- } +- *p++ = *q++; +- } +- *p = '\0'; +- } +- else +- *((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1)) +- = '\0'; +- user_name = newp; +- } +- +- /* Look up specific user's home directory. */ +- { +- struct passwd *p; +- struct scratch_buffer pwtmpbuf; +- scratch_buffer_init (&pwtmpbuf); ++ /* Recognize ~user as a shorthand for the specified user's home ++ directory. */ ++ char *end_name = strchr (dirname, '/'); ++ char *user_name; ++ int malloc_user_name = 0; ++ char *unescape = NULL; ++ ++ if (!(flags & GLOB_NOESCAPE)) ++ { ++ if (end_name == NULL) ++ { ++ unescape = strchr (dirname, '\\'); ++ if (unescape) ++ end_name = strchr (unescape, '\0'); ++ } ++ else ++ unescape = memchr (dirname, '\\', end_name - dirname); ++ } ++ if (end_name == NULL) ++ user_name = dirname + 1; ++ else ++ { ++ char *newp; ++ if (glob_use_alloca (alloca_used, end_name - dirname)) ++ newp = alloca_account (end_name - dirname, alloca_used); ++ else ++ { ++ newp = malloc (end_name - dirname); ++ if (newp == NULL) ++ { ++ retval = GLOB_NOSPACE; ++ goto out; ++ } ++ malloc_user_name = 1; ++ } ++ if (unescape != NULL) ++ { ++ char *p = mempcpy (newp, dirname + 1, ++ unescape - dirname - 1); ++ char *q = unescape; ++ while (q != end_name) ++ { ++ if (*q == '\\') ++ { ++ if (q + 1 == end_name) ++ { ++ /* "~fo\\o\\" unescape to user_name "foo\\", ++ but "~fo\\o\\/" unescape to user_name ++ "foo". */ ++ if (filename == NULL) ++ *p++ = '\\'; ++ break; ++ } ++ ++q; ++ } ++ *p++ = *q++; ++ } ++ *p = '\0'; ++ } ++ else ++ *((char *) mempcpy (newp, dirname + 1, end_name - dirname - 1)) ++ = '\0'; ++ user_name = newp; ++ } ++ ++ /* Look up specific user's home directory. */ ++ { ++ struct passwd *p; ++ struct scratch_buffer pwtmpbuf; ++ scratch_buffer_init (&pwtmpbuf); + + # if defined HAVE_GETPWNAM_R || defined _LIBC +- struct passwd pwbuf; ++ struct passwd pwbuf; + +- while (getpwnam_r (user_name, &pwbuf, +- pwtmpbuf.data, pwtmpbuf.length, &p) +- == ERANGE) +- { +- if (!scratch_buffer_grow (&pwtmpbuf)) +- { +- retval = GLOB_NOSPACE; +- goto out; +- } +- } ++ while (getpwnam_r (user_name, &pwbuf, ++ pwtmpbuf.data, pwtmpbuf.length, &p) ++ == ERANGE) ++ { ++ if (!scratch_buffer_grow (&pwtmpbuf)) ++ { ++ retval = GLOB_NOSPACE; ++ goto out; ++ } ++ } + # else +- p = getpwnam (user_name); ++ p = getpwnam (user_name); + # endif + +- if (__glibc_unlikely (malloc_user_name)) +- free (user_name); ++ if (__glibc_unlikely (malloc_user_name)) ++ free (user_name); + +- /* If we found a home directory use this. */ +- if (p != NULL) +- { +- size_t home_len = strlen (p->pw_dir); +- size_t rest_len = end_name == NULL ? 0 : strlen (end_name); +- char *d, *newp; +- bool use_alloca = glob_use_alloca (alloca_used, +- home_len + rest_len + 1); +- +- if (use_alloca) +- newp = alloca_account (home_len + rest_len + 1, alloca_used); +- else +- { +- newp = malloc (home_len + rest_len + 1); +- if (newp == NULL) +- { +- scratch_buffer_free (&pwtmpbuf); +- retval = GLOB_NOSPACE; +- goto out; +- } +- } +- d = mempcpy (newp, p->pw_dir, home_len); +- if (end_name != NULL) +- d = mempcpy (d, end_name, rest_len); +- *d = '\0'; +- +- if (__glibc_unlikely (malloc_dirname)) +- free (dirname); +- dirname = newp; +- malloc_dirname = !use_alloca; +- +- dirlen = home_len + rest_len; +- dirname_modified = 1; +- } +- else +- { +- if (flags & GLOB_TILDE_CHECK) +- { +- /* We have to regard it as an error if we cannot find the +- home directory. */ +- retval = GLOB_NOMATCH; +- goto out; +- } +- } +- scratch_buffer_free (&pwtmpbuf); +- } +-#endif /* !WINDOWS32 */ +- } ++ /* If we found a home directory use this. */ ++ if (p != NULL) ++ { ++ size_t home_len = strlen (p->pw_dir); ++ size_t rest_len = end_name == NULL ? 0 : strlen (end_name); ++ /* dirname contains end_name; we can't free it now. */ ++ char *prev_dirname = ++ (__glibc_unlikely (malloc_dirname) ? dirname : NULL); ++ char *d; ++ ++ malloc_dirname = 0; ++ ++ if (glob_use_alloca (alloca_used, home_len + rest_len + 1)) ++ dirname = alloca_account (home_len + rest_len + 1, ++ alloca_used); ++ else ++ { ++ dirname = malloc (home_len + rest_len + 1); ++ if (dirname == NULL) ++ { ++ free (prev_dirname); ++ scratch_buffer_free (&pwtmpbuf); ++ retval = GLOB_NOSPACE; ++ goto out; ++ } ++ malloc_dirname = 1; ++ } ++ d = mempcpy (dirname, p->pw_dir, home_len); ++ if (end_name != NULL) ++ d = mempcpy (d, end_name, rest_len); ++ *d = '\0'; ++ ++ free (prev_dirname); ++ ++ dirlen = home_len + rest_len; ++ dirname_modified = 1; ++ } ++ else ++ { ++ if (flags & GLOB_TILDE_CHECK) ++ { ++ /* We have to regard it as an error if we cannot find the ++ home directory. */ ++ retval = GLOB_NOMATCH; ++ goto out; ++ } ++ } ++ scratch_buffer_free (&pwtmpbuf); ++ } ++#else /* WINDOWS32 */ ++ /* On native Windows, access to a user's home directory ++ (via GetUserProfileDirectory) or to a user's environment ++ variables (via ExpandEnvironmentStringsForUser) requires ++ the credentials of the user. Therefore we cannot support ++ the ~user syntax on this platform. ++ Handling ~user specially (and treat it like plain ~) if ++ user is getenv ("USERNAME") would not be a good idea, ++ since it would make people think that ~user is supported ++ in general. */ ++ if (flags & GLOB_TILDE_CHECK) ++ { ++ retval = GLOB_NOMATCH; ++ goto out; ++ } ++#endif /* WINDOWS32 */ ++ } + } + + /* Now test whether we looked for "~" or "~NAME". In this case we + can give the answer now. */ + if (filename == NULL) + { +- size_t newcount = pglob->gl_pathc + pglob->gl_offs; +- char **new_gl_pathv; ++ size_t newcount = pglob->gl_pathc + pglob->gl_offs; ++ char **new_gl_pathv; ++ ++ if (newcount > SIZE_MAX / sizeof (char *) - 2) ++ { ++ nospace: ++ free (pglob->gl_pathv); ++ pglob->gl_pathv = NULL; ++ pglob->gl_pathc = 0; ++ retval = GLOB_NOSPACE; ++ goto out; ++ } + +- if (newcount > SIZE_MAX / sizeof (char *) - 2) +- { +- nospace: +- free (pglob->gl_pathv); +- pglob->gl_pathv = NULL; +- pglob->gl_pathc = 0; +- retval = GLOB_NOSPACE; +- goto out; +- } +- +- new_gl_pathv = realloc (pglob->gl_pathv, +- (newcount + 2) * sizeof (char *)); +- if (new_gl_pathv == NULL) +- goto nospace; +- pglob->gl_pathv = new_gl_pathv; +- +- if (flags & GLOB_MARK && is_dir (dirname, flags, pglob)) +- { +- char *p; +- pglob->gl_pathv[newcount] = malloc (dirlen + 2); +- if (pglob->gl_pathv[newcount] == NULL) +- goto nospace; +- p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen); +- p[0] = '/'; +- p[1] = '\0'; +- if (__glibc_unlikely (malloc_dirname)) +- free (dirname); +- } +- else +- { +- if (__glibc_unlikely (malloc_dirname)) +- pglob->gl_pathv[newcount] = dirname; +- else +- { +- pglob->gl_pathv[newcount] = strdup (dirname); +- if (pglob->gl_pathv[newcount] == NULL) +- goto nospace; +- } +- } +- pglob->gl_pathv[++newcount] = NULL; +- ++pglob->gl_pathc; +- pglob->gl_flags = flags; ++ new_gl_pathv = realloc (pglob->gl_pathv, ++ (newcount + 2) * sizeof (char *)); ++ if (new_gl_pathv == NULL) ++ goto nospace; ++ pglob->gl_pathv = new_gl_pathv; ++ ++ if (flags & GLOB_MARK && is_dir (dirname, flags, pglob)) ++ { ++ char *p; ++ pglob->gl_pathv[newcount] = malloc (dirlen + 2); ++ if (pglob->gl_pathv[newcount] == NULL) ++ goto nospace; ++ p = mempcpy (pglob->gl_pathv[newcount], dirname, dirlen); ++ p[0] = '/'; ++ p[1] = '\0'; ++ if (__glibc_unlikely (malloc_dirname)) ++ free (dirname); ++ } ++ else ++ { ++ if (__glibc_unlikely (malloc_dirname)) ++ pglob->gl_pathv[newcount] = dirname; ++ else ++ { ++ pglob->gl_pathv[newcount] = strdup (dirname); ++ if (pglob->gl_pathv[newcount] == NULL) ++ goto nospace; ++ } ++ } ++ pglob->gl_pathv[++newcount] = NULL; ++ ++pglob->gl_pathc; ++ pglob->gl_flags = flags; + +- return 0; ++ return 0; + } + + meta = __glob_pattern_type (dirname, !(flags & GLOB_NOESCAPE)); +@@ -934,135 +969,135 @@ __glob (const char *pattern, int flags, + if (meta & (GLOBPAT_SPECIAL | GLOBPAT_BRACKET)) + { + /* The directory name contains metacharacters, so we +- have to glob for the directory, and then glob for +- the pattern in each directory found. */ ++ have to glob for the directory, and then glob for ++ the pattern in each directory found. */ + size_t i; + + if (!(flags & GLOB_NOESCAPE) && dirlen > 0 && dirname[dirlen - 1] == '\\') +- { +- /* "foo\\/bar". Remove the final backslash from dirname +- if it has not been quoted. */ +- char *p = (char *) &dirname[dirlen - 1]; +- +- while (p > dirname && p[-1] == '\\') --p; +- if ((&dirname[dirlen] - p) & 1) +- *(char *) &dirname[--dirlen] = '\0'; +- } ++ { ++ /* "foo\\/bar". Remove the final backslash from dirname ++ if it has not been quoted. */ ++ char *p = (char *) &dirname[dirlen - 1]; ++ ++ while (p > dirname && p[-1] == '\\') --p; ++ if ((&dirname[dirlen] - p) & 1) ++ *(char *) &dirname[--dirlen] = '\0'; ++ } + + if (__glibc_unlikely ((flags & GLOB_ALTDIRFUNC) != 0)) +- { +- /* Use the alternative access functions also in the recursive +- call. */ +- dirs.gl_opendir = pglob->gl_opendir; +- dirs.gl_readdir = pglob->gl_readdir; +- dirs.gl_closedir = pglob->gl_closedir; +- dirs.gl_stat = pglob->gl_stat; +- dirs.gl_lstat = pglob->gl_lstat; +- } ++ { ++ /* Use the alternative access functions also in the recursive ++ call. */ ++ dirs.gl_opendir = pglob->gl_opendir; ++ dirs.gl_readdir = pglob->gl_readdir; ++ dirs.gl_closedir = pglob->gl_closedir; ++ dirs.gl_stat = pglob->gl_stat; ++ dirs.gl_lstat = pglob->gl_lstat; ++ } + + status = __glob (dirname, +- ((flags & (GLOB_ERR | GLOB_NOESCAPE | GLOB_ALTDIRFUNC)) +- | GLOB_NOSORT | GLOB_ONLYDIR), +- errfunc, &dirs); ++ ((flags & (GLOB_ERR | GLOB_NOESCAPE | GLOB_ALTDIRFUNC)) ++ | GLOB_NOSORT | GLOB_ONLYDIR), ++ errfunc, &dirs); + if (status != 0) +- { +- if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH) +- { +- retval = status; +- goto out; +- } +- goto no_matches; +- } ++ { ++ if ((flags & GLOB_NOCHECK) == 0 || status != GLOB_NOMATCH) ++ { ++ retval = status; ++ goto out; ++ } ++ goto no_matches; ++ } + + /* We have successfully globbed the preceding directory name. +- For each name we found, call glob_in_dir on it and FILENAME, +- appending the results to PGLOB. */ ++ For each name we found, call glob_in_dir on it and FILENAME, ++ appending the results to PGLOB. */ + for (i = 0; i < dirs.gl_pathc; ++i) +- { +- size_t old_pathc; ++ { ++ size_t old_pathc; + +- old_pathc = pglob->gl_pathc; +- status = glob_in_dir (filename, dirs.gl_pathv[i], +- ((flags | GLOB_APPEND) +- & ~(GLOB_NOCHECK | GLOB_NOMAGIC)), +- errfunc, pglob, alloca_used); +- if (status == GLOB_NOMATCH) +- /* No matches in this directory. Try the next. */ +- continue; +- +- if (status != 0) +- { +- globfree (&dirs); +- globfree (pglob); +- pglob->gl_pathc = 0; +- retval = status; +- goto out; +- } +- +- /* Stick the directory on the front of each name. */ +- if (prefix_array (dirs.gl_pathv[i], +- &pglob->gl_pathv[old_pathc + pglob->gl_offs], +- pglob->gl_pathc - old_pathc)) +- { +- globfree (&dirs); +- globfree (pglob); +- pglob->gl_pathc = 0; +- retval = GLOB_NOSPACE; +- goto out; +- } +- } ++ old_pathc = pglob->gl_pathc; ++ status = glob_in_dir (filename, dirs.gl_pathv[i], ++ ((flags | GLOB_APPEND) ++ & ~(GLOB_NOCHECK | GLOB_NOMAGIC)), ++ errfunc, pglob, alloca_used); ++ if (status == GLOB_NOMATCH) ++ /* No matches in this directory. Try the next. */ ++ continue; ++ ++ if (status != 0) ++ { ++ globfree (&dirs); ++ globfree (pglob); ++ pglob->gl_pathc = 0; ++ retval = status; ++ goto out; ++ } ++ ++ /* Stick the directory on the front of each name. */ ++ if (prefix_array (dirs.gl_pathv[i], ++ &pglob->gl_pathv[old_pathc + pglob->gl_offs], ++ pglob->gl_pathc - old_pathc)) ++ { ++ globfree (&dirs); ++ globfree (pglob); ++ pglob->gl_pathc = 0; ++ retval = GLOB_NOSPACE; ++ goto out; ++ } ++ } + + flags |= GLOB_MAGCHAR; + + /* We have ignored the GLOB_NOCHECK flag in the 'glob_in_dir' calls. +- But if we have not found any matching entry and the GLOB_NOCHECK +- flag was set we must return the input pattern itself. */ ++ But if we have not found any matching entry and the GLOB_NOCHECK ++ flag was set we must return the input pattern itself. */ + if (pglob->gl_pathc + pglob->gl_offs == oldcount) +- { +- no_matches: +- /* No matches. */ +- if (flags & GLOB_NOCHECK) +- { +- size_t newcount = pglob->gl_pathc + pglob->gl_offs; +- char **new_gl_pathv; +- +- if (newcount > SIZE_MAX / sizeof (char *) - 2) +- { +- nospace2: +- globfree (&dirs); +- retval = GLOB_NOSPACE; +- goto out; +- } +- +- new_gl_pathv = realloc (pglob->gl_pathv, +- (newcount + 2) * sizeof (char *)); +- if (new_gl_pathv == NULL) +- goto nospace2; +- pglob->gl_pathv = new_gl_pathv; +- +- pglob->gl_pathv[newcount] = strdup (pattern); +- if (pglob->gl_pathv[newcount] == NULL) +- { +- globfree (&dirs); +- globfree (pglob); +- pglob->gl_pathc = 0; +- retval = GLOB_NOSPACE; +- goto out; +- } +- +- ++pglob->gl_pathc; +- ++newcount; +- +- pglob->gl_pathv[newcount] = NULL; +- pglob->gl_flags = flags; +- } +- else +- { +- globfree (&dirs); +- retval = GLOB_NOMATCH; +- goto out; +- } +- } ++ { ++ no_matches: ++ /* No matches. */ ++ if (flags & GLOB_NOCHECK) ++ { ++ size_t newcount = pglob->gl_pathc + pglob->gl_offs; ++ char **new_gl_pathv; ++ ++ if (newcount > SIZE_MAX / sizeof (char *) - 2) ++ { ++ nospace2: ++ globfree (&dirs); ++ retval = GLOB_NOSPACE; ++ goto out; ++ } ++ ++ new_gl_pathv = realloc (pglob->gl_pathv, ++ (newcount + 2) * sizeof (char *)); ++ if (new_gl_pathv == NULL) ++ goto nospace2; ++ pglob->gl_pathv = new_gl_pathv; ++ ++ pglob->gl_pathv[newcount] = strdup (pattern); ++ if (pglob->gl_pathv[newcount] == NULL) ++ { ++ globfree (&dirs); ++ globfree (pglob); ++ pglob->gl_pathc = 0; ++ retval = GLOB_NOSPACE; ++ goto out; ++ } ++ ++ ++pglob->gl_pathc; ++ ++newcount; ++ ++ pglob->gl_pathv[newcount] = NULL; ++ pglob->gl_flags = flags; ++ } ++ else ++ { ++ globfree (&dirs); ++ retval = GLOB_NOMATCH; ++ goto out; ++ } ++ } + + globfree (&dirs); + } +@@ -1072,57 +1107,57 @@ __glob (const char *pattern, int flags, + int orig_flags = flags; + + if (meta & GLOBPAT_BACKSLASH) +- { +- char *p = strchr (dirname, '\\'), *q; +- /* We need to unescape the dirname string. It is certainly +- allocated by alloca, as otherwise filename would be NULL +- or dirname wouldn't contain backslashes. */ +- q = p; +- do +- { +- if (*p == '\\') +- { +- *q = *++p; +- --dirlen; +- } +- else +- *q = *p; +- ++q; +- } +- while (*p++ != '\0'); +- dirname_modified = 1; +- } ++ { ++ char *p = strchr (dirname, '\\'), *q; ++ /* We need to unescape the dirname string. It is certainly ++ allocated by alloca, as otherwise filename would be NULL ++ or dirname wouldn't contain backslashes. */ ++ q = p; ++ do ++ { ++ if (*p == '\\') ++ { ++ *q = *++p; ++ --dirlen; ++ } ++ else ++ *q = *p; ++ ++q; ++ } ++ while (*p++ != '\0'); ++ dirname_modified = 1; ++ } + if (dirname_modified) +- flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); ++ flags &= ~(GLOB_NOCHECK | GLOB_NOMAGIC); + status = glob_in_dir (filename, dirname, flags, errfunc, pglob, +- alloca_used); ++ alloca_used); + if (status != 0) +- { +- if (status == GLOB_NOMATCH && flags != orig_flags +- && pglob->gl_pathc + pglob->gl_offs == oldcount) +- { +- /* Make sure globfree (&dirs); is a nop. */ +- dirs.gl_pathv = NULL; +- flags = orig_flags; +- goto no_matches; +- } +- retval = status; +- goto out; +- } ++ { ++ if (status == GLOB_NOMATCH && flags != orig_flags ++ && pglob->gl_pathc + pglob->gl_offs == oldcount) ++ { ++ /* Make sure globfree (&dirs); is a nop. */ ++ dirs.gl_pathv = NULL; ++ flags = orig_flags; ++ goto no_matches; ++ } ++ retval = status; ++ goto out; ++ } + + if (dirlen > 0) +- { +- /* Stick the directory on the front of each name. */ +- if (prefix_array (dirname, +- &pglob->gl_pathv[old_pathc + pglob->gl_offs], +- pglob->gl_pathc - old_pathc)) +- { +- globfree (pglob); +- pglob->gl_pathc = 0; +- retval = GLOB_NOSPACE; +- goto out; +- } +- } ++ { ++ /* Stick the directory on the front of each name. */ ++ if (prefix_array (dirname, ++ &pglob->gl_pathv[old_pathc + pglob->gl_offs], ++ pglob->gl_pathc - old_pathc)) ++ { ++ globfree (pglob); ++ pglob->gl_pathc = 0; ++ retval = GLOB_NOSPACE; ++ goto out; ++ } ++ } + } + + if (flags & GLOB_MARK) +@@ -1131,28 +1166,28 @@ __glob (const char *pattern, int flags, + size_t i; + + for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i) +- if (is_dir (pglob->gl_pathv[i], flags, pglob)) +- { +- size_t len = strlen (pglob->gl_pathv[i]) + 2; +- char *new = realloc (pglob->gl_pathv[i], len); +- if (new == NULL) +- { +- globfree (pglob); +- pglob->gl_pathc = 0; +- retval = GLOB_NOSPACE; +- goto out; +- } +- strcpy (&new[len - 2], "/"); +- pglob->gl_pathv[i] = new; +- } ++ if (is_dir (pglob->gl_pathv[i], flags, pglob)) ++ { ++ size_t len = strlen (pglob->gl_pathv[i]) + 2; ++ char *new = realloc (pglob->gl_pathv[i], len); ++ if (new == NULL) ++ { ++ globfree (pglob); ++ pglob->gl_pathc = 0; ++ retval = GLOB_NOSPACE; ++ goto out; ++ } ++ strcpy (&new[len - 2], "/"); ++ pglob->gl_pathv[i] = new; ++ } + } + + if (!(flags & GLOB_NOSORT)) + { + /* Sort the vector. */ + qsort (&pglob->gl_pathv[oldcount], +- pglob->gl_pathc + pglob->gl_offs - oldcount, +- sizeof (char *), collated_compare); ++ pglob->gl_pathc + pglob->gl_offs - oldcount, ++ sizeof (char *), collated_compare); + } + + out: +@@ -1204,14 +1239,14 @@ prefix_array (const char *dirname, char + if (dirlen > 1) + { + if (dirname[dirlen - 1] == '/' && dirname[dirlen - 2] == ':') +- /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */ +- --dirlen; ++ /* DIRNAME is "d:/". Don't prepend the slash from DIRNAME. */ ++ --dirlen; + else if (dirname[dirlen - 1] == ':') +- { +- /* DIRNAME is "d:". Use ':' instead of '/'. */ +- --dirlen; +- dirsep_char = ':'; +- } ++ { ++ /* DIRNAME is "d:". Use ':' instead of '/'. */ ++ --dirlen; ++ dirsep_char = ':'; ++ } + } + #endif + +@@ -1220,16 +1255,16 @@ prefix_array (const char *dirname, char + size_t eltlen = strlen (array[i]) + 1; + char *new = malloc (dirlen + 1 + eltlen); + if (new == NULL) +- { +- while (i > 0) +- free (array[--i]); +- return 1; +- } ++ { ++ while (i > 0) ++ free (array[--i]); ++ return 1; ++ } + + { +- char *endp = mempcpy (new, dirname, dirlen); +- *endp++ = dirsep_char; +- mempcpy (endp, array[i], eltlen); ++ char *endp = mempcpy (new, dirname, dirlen); ++ *endp++ = dirsep_char; ++ mempcpy (endp, array[i], eltlen); + } + free (array[i]); + array[i] = new; +@@ -1244,11 +1279,13 @@ prefix_array (const char *dirname, char + The GLOB_APPEND flag is assumed to be set (always appends). */ + static int + glob_in_dir (const char *pattern, const char *directory, int flags, +- int (*errfunc) (const char *, int), +- glob_t *pglob, size_t alloca_used) ++ int (*errfunc) (const char *, int), ++ glob_t *pglob, size_t alloca_used) + { + size_t dirlen = strlen (directory); + void *stream = NULL; ++ struct scratch_buffer s; ++ scratch_buffer_init (&s); + # define GLOBNAMES_MEMBERS(nnames) \ + struct globnames *next; size_t count; char *name[nnames]; + struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) }; +@@ -1273,8 +1310,8 @@ glob_in_dir (const char *pattern, const + if (meta == GLOBPAT_NONE && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) + { + /* We need not do any tests. The PATTERN contains no meta +- characters and we must not return an error therefore the +- result will always contain exactly one name. */ ++ characters and we must not return an error therefore the ++ result will always contain exactly one name. */ + flags |= GLOB_NOCHECK; + } + else if (meta == GLOBPAT_NONE) +@@ -1288,102 +1325,127 @@ glob_in_dir (const char *pattern, const + if (alloca_fullname) + fullname = alloca_account (fullsize, alloca_used); + else +- { +- fullname = malloc (fullsize); +- if (fullname == NULL) +- return GLOB_NOSPACE; +- } ++ { ++ fullname = malloc (fullsize); ++ if (fullname == NULL) ++ return GLOB_NOSPACE; ++ } + + mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), +- "/", 1), +- pattern, patlen + 1); ++ "/", 1), ++ pattern, patlen + 1); + if (glob_lstat (pglob, flags, fullname) == 0 +- || errno == EOVERFLOW) +- /* We found this file to be existing. Now tell the rest +- of the function to copy this name into the result. */ +- flags |= GLOB_NOCHECK; ++ || errno == EOVERFLOW) ++ /* We found this file to be existing. Now tell the rest ++ of the function to copy this name into the result. */ ++ flags |= GLOB_NOCHECK; + + if (__glibc_unlikely (!alloca_fullname)) +- free (fullname); ++ free (fullname); + } + else + { + stream = (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0) +- ? (*pglob->gl_opendir) (directory) +- : opendir (directory)); ++ ? (*pglob->gl_opendir) (directory) ++ : opendir (directory)); + if (stream == NULL) +- { +- if (errno != ENOTDIR +- && ((errfunc != NULL && (*errfunc) (directory, errno)) +- || (flags & GLOB_ERR))) +- return GLOB_ABORTED; +- } ++ { ++ if (errno != ENOTDIR ++ && ((errfunc != NULL && (*errfunc) (directory, errno)) ++ || (flags & GLOB_ERR))) ++ return GLOB_ABORTED; ++ } + else +- { +- int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) +- | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)); +- flags |= GLOB_MAGCHAR; +- +- while (1) +- { +- struct readdir_result d; +- { +- if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)) +- d = convert_dirent (GL_READDIR (pglob, stream)); +- else +- { ++ { ++ int dfd = dirfd (stream); ++ int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) ++ | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)); ++ flags |= GLOB_MAGCHAR; ++ ++ while (1) ++ { ++ struct readdir_result d; ++ { ++ if (__builtin_expect (flags & GLOB_ALTDIRFUNC, 0)) ++ d = convert_dirent (GL_READDIR (pglob, stream)); ++ else ++ { + #ifdef COMPILE_GLOB64 +- d = convert_dirent (__readdir (stream)); ++ d = convert_dirent (__readdir (stream)); + #else +- d = convert_dirent64 (__readdir64 (stream)); ++ d = convert_dirent64 (__readdir64 (stream)); + #endif +- } +- } +- if (d.name == NULL) +- break; +- +- /* If we shall match only directories use the information +- provided by the dirent call if possible. */ +- if (flags & GLOB_ONLYDIR) +- switch (readdir_result_type (d)) +- { +- case DT_DIR: case DT_LNK: case DT_UNKNOWN: break; +- default: continue; +- } +- +- if (fnmatch (pattern, d.name, fnm_flags) == 0) +- { +- if (cur == names->count) +- { +- struct globnames *newnames; +- size_t count = names->count * 2; +- size_t nameoff = offsetof (struct globnames, name); +- size_t size = FLEXSIZEOF (struct globnames, name, +- count * sizeof (char *)); +- if ((SIZE_MAX - nameoff) / 2 / sizeof (char *) +- < names->count) +- goto memory_error; +- if (glob_use_alloca (alloca_used, size)) +- newnames = names_alloca +- = alloca_account (size, alloca_used); +- else if ((newnames = malloc (size)) +- == NULL) +- goto memory_error; +- newnames->count = count; +- newnames->next = names; +- names = newnames; +- cur = 0; +- } +- names->name[cur] = strdup (d.name); +- if (names->name[cur] == NULL) +- goto memory_error; +- ++cur; +- ++nfound; +- if (SIZE_MAX - pglob->gl_offs <= nfound) +- goto memory_error; +- } +- } +- } ++ } ++ } ++ if (d.name == NULL) ++ break; ++ ++ /* If we shall match only directories use the information ++ provided by the dirent call if possible. */ ++ if (flags & GLOB_ONLYDIR) ++ switch (readdir_result_type (d)) ++ { ++ default: continue; ++ case DT_DIR: break; ++ case DT_LNK: case DT_UNKNOWN: ++ /* The filesystem was too lazy to give us a hint, ++ so we have to do it the hard way. */ ++ if (__glibc_unlikely (dfd < 0 || flags & GLOB_ALTDIRFUNC)) ++ { ++ size_t namelen = strlen (d.name); ++ size_t need = dirlen + 1 + namelen + 1; ++ if (s.length < need ++ && !scratch_buffer_set_array_size (&s, need, 1)) ++ goto memory_error; ++ char *p = mempcpy (s.data, directory, dirlen); ++ *p = '/'; ++ p += p[-1] != '/'; ++ memcpy (p, d.name, namelen + 1); ++ if (! is_dir (s.data, flags, pglob)) ++ continue; ++ } ++ else ++ { ++ struct_stat64 st64; ++ if (! (GLOB_FSTATAT64 (dfd, d.name, &st64, 0) == 0 ++ && S_ISDIR (st64.st_mode))) ++ continue; ++ } ++ } ++ ++ if (fnmatch (pattern, d.name, fnm_flags) == 0) ++ { ++ if (cur == names->count) ++ { ++ struct globnames *newnames; ++ size_t count = names->count * 2; ++ size_t nameoff = offsetof (struct globnames, name); ++ size_t size = FLEXSIZEOF (struct globnames, name, ++ count * sizeof (char *)); ++ if ((SIZE_MAX - nameoff) / 2 / sizeof (char *) ++ < names->count) ++ goto memory_error; ++ if (glob_use_alloca (alloca_used, size)) ++ newnames = names_alloca ++ = alloca_account (size, alloca_used); ++ else if ((newnames = malloc (size)) ++ == NULL) ++ goto memory_error; ++ newnames->count = count; ++ newnames->next = names; ++ names = newnames; ++ cur = 0; ++ } ++ names->name[cur] = strdup (d.name); ++ if (names->name[cur] == NULL) ++ goto memory_error; ++ ++cur; ++ ++nfound; ++ if (SIZE_MAX - pglob->gl_offs <= nfound) ++ goto memory_error; ++ } ++ } ++ } + } + + if (nfound == 0 && (flags & GLOB_NOCHECK)) +@@ -1392,7 +1454,7 @@ glob_in_dir (const char *pattern, const + nfound = 1; + names->name[cur] = malloc (len + 1); + if (names->name[cur] == NULL) +- goto memory_error; ++ goto memory_error; + *((char *) mempcpy (names->name[cur++], pattern, len)) = '\0'; + } + +@@ -1403,82 +1465,83 @@ glob_in_dir (const char *pattern, const + result = 0; + + if (SIZE_MAX / sizeof (char *) - pglob->gl_pathc +- < pglob->gl_offs + nfound + 1) +- goto memory_error; ++ < pglob->gl_offs + nfound + 1) ++ goto memory_error; + + new_gl_pathv +- = realloc (pglob->gl_pathv, +- (pglob->gl_pathc + pglob->gl_offs + nfound + 1) +- * sizeof (char *)); ++ = realloc (pglob->gl_pathv, ++ (pglob->gl_pathc + pglob->gl_offs + nfound + 1) ++ * sizeof (char *)); + + if (new_gl_pathv == NULL) +- { +- memory_error: +- while (1) +- { +- struct globnames *old = names; +- for (size_t i = 0; i < cur; ++i) +- free (names->name[i]); +- names = names->next; +- /* NB: we will not leak memory here if we exit without +- freeing the current block assigned to OLD. At least +- the very first block is always allocated on the stack +- and this is the block assigned to OLD here. */ +- if (names == NULL) +- { +- assert (old == init_names); +- break; +- } +- cur = names->count; +- if (old == names_alloca) +- names_alloca = names; +- else +- free (old); +- } +- result = GLOB_NOSPACE; +- } ++ { ++ memory_error: ++ while (1) ++ { ++ struct globnames *old = names; ++ for (size_t i = 0; i < cur; ++i) ++ free (names->name[i]); ++ names = names->next; ++ /* NB: we will not leak memory here if we exit without ++ freeing the current block assigned to OLD. At least ++ the very first block is always allocated on the stack ++ and this is the block assigned to OLD here. */ ++ if (names == NULL) ++ { ++ assert (old == init_names); ++ break; ++ } ++ cur = names->count; ++ if (old == names_alloca) ++ names_alloca = names; ++ else ++ free (old); ++ } ++ result = GLOB_NOSPACE; ++ } + else +- { +- while (1) +- { +- struct globnames *old = names; +- for (size_t i = 0; i < cur; ++i) +- new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++] +- = names->name[i]; +- names = names->next; +- /* NB: we will not leak memory here if we exit without +- freeing the current block assigned to OLD. At least +- the very first block is always allocated on the stack +- and this is the block assigned to OLD here. */ +- if (names == NULL) +- { +- assert (old == init_names); +- break; +- } +- cur = names->count; +- if (old == names_alloca) +- names_alloca = names; +- else +- free (old); +- } ++ { ++ while (1) ++ { ++ struct globnames *old = names; ++ for (size_t i = 0; i < cur; ++i) ++ new_gl_pathv[pglob->gl_offs + pglob->gl_pathc++] ++ = names->name[i]; ++ names = names->next; ++ /* NB: we will not leak memory here if we exit without ++ freeing the current block assigned to OLD. At least ++ the very first block is always allocated on the stack ++ and this is the block assigned to OLD here. */ ++ if (names == NULL) ++ { ++ assert (old == init_names); ++ break; ++ } ++ cur = names->count; ++ if (old == names_alloca) ++ names_alloca = names; ++ else ++ free (old); ++ } + +- pglob->gl_pathv = new_gl_pathv; ++ pglob->gl_pathv = new_gl_pathv; + +- pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; ++ pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; + +- pglob->gl_flags = flags; +- } ++ pglob->gl_flags = flags; ++ } + } + + if (stream != NULL) + { + save = errno; + if (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)) +- (*pglob->gl_closedir) (stream); ++ (*pglob->gl_closedir) (stream); + else +- closedir (stream); ++ closedir (stream); + __set_errno (save); + } + ++ scratch_buffer_free (&s); + return result; + } +diff -rup a/sysdeps/gnu/glob-lstat-compat.c b/sysdeps/gnu/glob-lstat-compat.c +--- a/sysdeps/gnu/glob-lstat-compat.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/sysdeps/gnu/glob-lstat-compat.c 2022-05-02 17:51:04.167557574 -0400 +@@ -29,7 +29,8 @@ + #define GLOB_ATTRIBUTE attribute_compat_text_section + + /* Avoid calling gl_lstat with GLOB_ALTDIRFUNC. */ +-#define GLOB_NO_LSTAT ++#define GLOB_LSTAT gl_stat ++#define GLOB_LSTAT64 __stat64 + + #include + +diff -rup a/sysdeps/unix/sysv/linux/glob-lstat-compat.c b/sysdeps/unix/sysv/linux/glob-lstat-compat.c +--- a/sysdeps/unix/sysv/linux/glob-lstat-compat.c 2018-08-01 01:10:47.000000000 -0400 ++++ b/sysdeps/unix/sysv/linux/glob-lstat-compat.c 2022-05-02 23:05:45.197297341 -0400 +@@ -30,7 +30,12 @@ + #define GLOB_ATTRIBUTE attribute_compat_text_section + + /* Avoid calling gl_lstat with GLOB_ALTDIRFUNC. */ +-#define GLOB_NO_LSTAT ++# define COMPILE_GLOB64 1 ++# define struct_stat struct stat ++# define struct_stat64 struct stat64 ++# define GLOB_LSTAT gl_stat ++# define GLOB_STAT64 __stat64 ++# define GLOB_LSTAT64 __stat64 + + #include + diff --git a/glibc-rh2033684-1.patch b/glibc-rh2033684-1.patch new file mode 100644 index 0000000..8734628 --- /dev/null +++ b/glibc-rh2033684-1.patch @@ -0,0 +1,27 @@ +commit 2a08b6e8331a611dc29325bfa6e29fecc9a3a46e +Author: Siddhesh Poyarekar +Date: Thu Dec 10 16:47:02 2020 +0530 + + Warn on unsupported fortification levels + + Make the _FORTIFY_SOURCE macro soup in features.h warn about + unsupported fortification levels. For example, it will warn about + _FORTIFY_SOURCE=3 and over with an indication of which level has been + selected. + + Co-authored-by: Paul Eggert + +diff --git a/include/features.h b/include/features.h +index 5bed0a499605a3a2..ea7673ee115bcf0a 100644 +--- a/include/features.h ++++ b/include/features.h +@@ -382,6 +382,9 @@ + # elif !__GNUC_PREREQ (4, 1) + # warning _FORTIFY_SOURCE requires GCC 4.1 or later + # elif _FORTIFY_SOURCE > 1 ++# if _FORTIFY_SOURCE > 2 ++# warning _FORTIFY_SOURCE > 2 is treated like 2 on this platform ++# endif + # define __USE_FORTIFY_LEVEL 2 + # else + # define __USE_FORTIFY_LEVEL 1 diff --git a/glibc-rh2033684-10.patch b/glibc-rh2033684-10.patch new file mode 100644 index 0000000..94b4519 --- /dev/null +++ b/glibc-rh2033684-10.patch @@ -0,0 +1,90 @@ +commit 2bbd07c715275eb6c616988925738a0517180d57 +Author: Siddhesh Poyarekar +Date: Fri Dec 17 18:35:44 2021 +0530 + + fortify: Fix spurious warning with realpath + + The length and object size arguments were swapped around for realpath. + Also add a smoke test so that any changes in this area get caught in + future. + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: Adhemerval Zanella + +diff --git a/debug/Makefile b/debug/Makefile +index 81361438fc3d2aa9..b43f42ee3851f360 100644 +--- a/debug/Makefile ++++ b/debug/Makefile +@@ -108,6 +108,7 @@ CFLAGS-tst-longjmp_chk2.c += -fexceptions -fasynchronous-unwind-tables + CPPFLAGS-tst-longjmp_chk2.c += -D_FORTIFY_SOURCE=1 + CFLAGS-tst-longjmp_chk3.c += -fexceptions -fasynchronous-unwind-tables + CPPFLAGS-tst-longjmp_chk3.c += -D_FORTIFY_SOURCE=1 ++CPPFLAGS-tst-realpath-chk.c += -D_FORTIFY_SOURCE=2 + + # We know these tests have problems with format strings, this is what + # we are testing. Disable that warning. They are also testing +@@ -155,7 +156,7 @@ tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \ + tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \ + tst-chk4 tst-chk5 tst-chk6 tst-chk7 tst-chk8 tst-lfschk4 tst-lfschk5 \ + tst-lfschk6 tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 \ +- tst-backtrace4 tst-backtrace5 tst-backtrace6 ++ tst-backtrace4 tst-backtrace5 tst-backtrace6 tst-realpath-chk + + ifeq ($(have-ssp),yes) + tests += tst-ssp-1 +diff --git a/debug/tst-realpath-chk.c b/debug/tst-realpath-chk.c +new file mode 100644 +index 0000000000000000..a8fcb327c43fb34d +--- /dev/null ++++ b/debug/tst-realpath-chk.c +@@ -0,0 +1,37 @@ ++/* Smoke test to verify that realpath does not cause spurious warnings. ++ Copyright The GNU Toolchain Authors. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++#include ++#include ++ ++static int ++do_test (void) ++{ ++#ifdef PATH_MAX ++ char buf[PATH_MAX + 1]; ++ char *res = realpath (".", buf); ++ TEST_VERIFY (res == buf); ++#endif ++ ++ return 0; ++} ++ ++#include +diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h +index 7ea364a276497720..81ec9bdb32215e3b 100644 +--- a/stdlib/bits/stdlib.h ++++ b/stdlib/bits/stdlib.h +@@ -42,7 +42,7 @@ __NTH (realpath (const char *__restrict __name, char *__restrict __resolved)) + return __realpath_alias (__name, __resolved); + + #if defined _LIBC_LIMITS_H_ && defined PATH_MAX +- if (__glibc_unsafe_len (sz, sizeof (char), PATH_MAX)) ++ if (__glibc_unsafe_len (PATH_MAX, sizeof (char), sz)) + return __realpath_chk_warn (__name, __resolved, sz); + #endif + return __realpath_chk (__name, __resolved, sz); diff --git a/glibc-rh2033684-11.patch b/glibc-rh2033684-11.patch new file mode 100644 index 0000000..41ce66c --- /dev/null +++ b/glibc-rh2033684-11.patch @@ -0,0 +1,41 @@ +commit 86bf0feb0e3ec8e37872f72499d6ae33406561d7 +Author: Siddhesh Poyarekar +Date: Wed Jan 12 18:46:28 2022 +0530 + + Enable _FORTIFY_SOURCE=3 for gcc 12 and above + + gcc 12 now has support for the __builtin_dynamic_object_size builtin. + Adapt the macro checks to enable _FORTIFY_SOURCE=3 on gcc 12 and above. + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: Adhemerval Zanella + +diff --git a/include/features.h b/include/features.h +index fe9fe16d034fad1b..2e9ca6ec2f4a0380 100644 +--- a/include/features.h ++++ b/include/features.h +@@ -381,7 +381,9 @@ + # warning _FORTIFY_SOURCE requires compiling with optimization (-O) + # elif !__GNUC_PREREQ (4, 1) + # warning _FORTIFY_SOURCE requires GCC 4.1 or later +-# elif _FORTIFY_SOURCE > 2 && __glibc_clang_prereq (9, 0) ++# elif _FORTIFY_SOURCE > 2 && (__glibc_clang_prereq (9, 0) \ ++ || __GNUC_PREREQ (12, 0)) ++ + # if _FORTIFY_SOURCE > 3 + # warning _FORTIFY_SOURCE > 3 is treated like 3 on this platform + # endif +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index 147339957c4ad490..a17ae0ed87e6163f 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -124,7 +124,8 @@ + #define __bos0(ptr) __builtin_object_size (ptr, 0) + + /* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available. */ +-#if __USE_FORTIFY_LEVEL == 3 && __glibc_clang_prereq (9, 0) ++#if __USE_FORTIFY_LEVEL == 3 && (__glibc_clang_prereq (9, 0) \ ++ || __GNUC_PREREQ (12, 0)) + # define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0) + # define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1) + #else diff --git a/glibc-rh2033684-12.patch b/glibc-rh2033684-12.patch new file mode 100644 index 0000000..9c9c98f --- /dev/null +++ b/glibc-rh2033684-12.patch @@ -0,0 +1,295 @@ +commit db27f1251b008280a29d540b4f8ab2a38a0d80af +Author: Siddhesh Poyarekar +Date: Wed Jan 12 23:34:23 2022 +0530 + + debug: Autogenerate _FORTIFY_SOURCE tests + + Rename debug/tst-chk1.c to debug/tst-fortify.c and add make hackery to + autogenerate tests with different macros enabled to build and run the + same test with different configurations as well as different + fortification levels. + + The change also ends up expanding the -lfs tests to include + _FORTIFY_SOURCE=3. + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: Adhemerval Zanella + +# Conflicts: +# debug/Makefile + +diff --git a/Makerules b/Makerules +index 5d6434c74bf9bfe5..05a549eb0f259113 100644 +--- a/Makerules ++++ b/Makerules +@@ -444,6 +444,12 @@ $(objpfx)%$o: $(objpfx)%.c $(before-compile); $$(compile-command.c) + endef + object-suffixes-left := $(all-object-suffixes) + include $(o-iterator) ++ ++define o-iterator-doit ++$(objpfx)%$o: $(objpfx)%.cc $(before-compile); $$(compile-command.cc) ++endef ++object-suffixes-left := $(all-object-suffixes) ++include $(o-iterator) + endif + + # Generate version maps, but wait until sysdep-subdirs is known +diff --git a/debug/Makefile b/debug/Makefile +index b43f42ee3851f360..c92fd23dda1a7279 100644 +--- a/debug/Makefile ++++ b/debug/Makefile +@@ -1,4 +1,5 @@ +-# Copyright (C) 1998-2018 Free Software Foundation, Inc. ++# Copyright (C) 1998-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 +@@ -110,32 +111,60 @@ CFLAGS-tst-longjmp_chk3.c += -fexceptions -fasynchronous-unwind-tables + CPPFLAGS-tst-longjmp_chk3.c += -D_FORTIFY_SOURCE=1 + CPPFLAGS-tst-realpath-chk.c += -D_FORTIFY_SOURCE=2 + ++# _FORTIFY_SOURCE tests. ++# Auto-generate tests for _FORTIFY_SOURCE for different levels, compilers and ++# preprocessor conditions based on tst-fortify.c. ++# ++# To add a new test condition, define a cflags-$(cond) make variable to set ++# CFLAGS for the file. ++ ++tests-all-chk = tst-fortify ++tests-c-chk = ++tests-cc-chk = ++ ++CFLAGS-tst-fortify.c += -Wno-format -Wno-deprecated-declarations -Wno-error ++ ++# No additional flags for the default tests. ++define cflags-default ++endef ++ ++define cflags-lfs ++CFLAGS-tst-fortify-$(1)-lfs-$(2).$(1) += -D_FILE_OFFSET_BITS=64 ++endef ++ + # We know these tests have problems with format strings, this is what + # we are testing. Disable that warning. They are also testing + # deprecated functions (notably gets) so disable that warning as well. + # And they also generate warnings from warning attributes, which + # cannot be disabled via pragmas, so require -Wno-error to be used. +-CFLAGS-tst-chk1.c += -Wno-format -Wno-deprecated-declarations -Wno-error +-CFLAGS-tst-chk2.c += -Wno-format -Wno-deprecated-declarations -Wno-error +-CFLAGS-tst-chk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error +-CFLAGS-tst-chk4.cc += -Wno-format -Wno-deprecated-declarations -Wno-error +-CFLAGS-tst-chk5.cc += -Wno-format -Wno-deprecated-declarations -Wno-error +-CFLAGS-tst-chk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error +-CFLAGS-tst-chk7.c += -Wno-format -Wno-deprecated-declarations -Wno-error +-CFLAGS-tst-chk8.cc += -Wno-format -Wno-deprecated-declarations -Wno-error +-CFLAGS-tst-lfschk1.c += -Wno-format -Wno-deprecated-declarations -Wno-error +-CFLAGS-tst-lfschk2.c += -Wno-format -Wno-deprecated-declarations -Wno-error +-CFLAGS-tst-lfschk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error +-CFLAGS-tst-lfschk4.cc += -Wno-format -Wno-deprecated-declarations -Wno-error +-CFLAGS-tst-lfschk5.cc += -Wno-format -Wno-deprecated-declarations -Wno-error +-CFLAGS-tst-lfschk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error +-LDLIBS-tst-chk4 = -lstdc++ +-LDLIBS-tst-chk5 = -lstdc++ +-LDLIBS-tst-chk6 = -lstdc++ +-LDLIBS-tst-chk8 = -lstdc++ +-LDLIBS-tst-lfschk4 = -lstdc++ +-LDLIBS-tst-lfschk5 = -lstdc++ +-LDLIBS-tst-lfschk6 = -lstdc++ ++define gen-chk-test ++tests-$(1)-chk += tst-fortify-$(1)-$(2)-$(3) ++CFLAGS-tst-fortify-$(1)-$(2)-$(3).$(1) += -D_FORTIFY_SOURCE=$(3) -Wno-format \ ++ -Wno-deprecated-declarations \ ++ -Wno-error ++$(eval $(call cflags-$(2),$(1),$(3))) ++$(objpfx)tst-fortify-$(1)-$(2)-$(3).$(1): tst-fortify.c Makefile ++ ( echo "/* Autogenerated from Makefile. */"; \ ++ echo ""; \ ++ echo "#include \"tst-fortify.c\"" ) > $$@.tmp ++ mv $$@.tmp $$@ ++endef ++ ++chk-extensions = c cc ++chk-types = default lfs ++chk-levels = 1 2 3 ++ ++$(foreach e,$(chk-extensions), \ ++ $(foreach t,$(chk-types), \ ++ $(foreach l,$(chk-levels), \ ++ $(eval $(call gen-chk-test,$(e),$(t),$(l)))))) ++ ++tests-all-chk += $(tests-c-chk) $(tests-cc-chk) ++ ++define link-cc ++LDLIBS-$(1) = -lstdc++ ++endef ++$(foreach t,$(tests-cc-chk), $(eval $(call link-cc,$(t)))) + + # backtrace_symbols only works if we link with -rdynamic. backtrace + # requires unwind tables on most architectures. +@@ -152,19 +181,25 @@ LDFLAGS-tst-backtrace6 = -rdynamic + + CFLAGS-tst-ssp-1.c += -fstack-protector-all + +-tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \ +- tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \ +- tst-chk4 tst-chk5 tst-chk6 tst-chk7 tst-chk8 tst-lfschk4 tst-lfschk5 \ +- tst-lfschk6 tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 \ +- tst-backtrace4 tst-backtrace5 tst-backtrace6 tst-realpath-chk ++tests = backtrace-tst \ ++ tst-longjmp_chk \ ++ test-strcpy_chk \ ++ test-stpcpy_chk \ ++ tst-longjmp_chk2 \ ++ tst-backtrace2 \ ++ tst-backtrace3 \ ++ tst-backtrace4 \ ++ tst-backtrace5 \ ++ tst-backtrace6 \ ++ tst-realpath-chk \ ++ $(tests-all-chk) + + ifeq ($(have-ssp),yes) + tests += tst-ssp-1 + endif + + ifeq (,$(CXX)) +-tests-unsupported = tst-chk4 tst-chk5 tst-chk6 tst-chk8 \ +- tst-lfschk4 tst-lfschk5 tst-lfschk6 ++tests-unsupported = $(tests-cc-chk) + endif + + extra-libs = libSegFault libpcprofile +@@ -191,20 +226,10 @@ ifeq ($(run-built-tests),yes) + LOCALES := de_DE.UTF-8 + include ../gen-locales.mk + +-$(objpfx)tst-chk1.out: $(gen-locales) +-$(objpfx)tst-chk2.out: $(gen-locales) +-$(objpfx)tst-chk3.out: $(gen-locales) +-$(objpfx)tst-chk4.out: $(gen-locales) +-$(objpfx)tst-chk5.out: $(gen-locales) +-$(objpfx)tst-chk6.out: $(gen-locales) +-$(objpfx)tst-chk7.out: $(gen-locales) +-$(objpfx)tst-chk8.out: $(gen-locales) +-$(objpfx)tst-lfschk1.out: $(gen-locales) +-$(objpfx)tst-lfschk2.out: $(gen-locales) +-$(objpfx)tst-lfschk3.out: $(gen-locales) +-$(objpfx)tst-lfschk4.out: $(gen-locales) +-$(objpfx)tst-lfschk5.out: $(gen-locales) +-$(objpfx)tst-lfschk6.out: $(gen-locales) ++define chk-gen-locales ++$(objpfx)$(1).out: $(gen-locales) ++endef ++$(foreach t, $(tests-all-chk), $(eval $(call chk-gen-locales,$(t)))) + endif + + sLIBdir := $(shell echo $(slibdir) | sed 's,lib\(\|64\)$$,\\\\$$LIB,') +diff --git a/debug/tst-chk2.c b/debug/tst-chk2.c +deleted file mode 100644 +index be37ce2d22f0760a..0000000000000000 +--- a/debug/tst-chk2.c ++++ /dev/null +@@ -1,2 +0,0 @@ +-#define _FORTIFY_SOURCE 1 +-#include "tst-chk1.c" +diff --git a/debug/tst-chk3.c b/debug/tst-chk3.c +deleted file mode 100644 +index 38b8e4fb360ba722..0000000000000000 +--- a/debug/tst-chk3.c ++++ /dev/null +@@ -1,2 +0,0 @@ +-#define _FORTIFY_SOURCE 2 +-#include "tst-chk1.c" +diff --git a/debug/tst-chk4.cc b/debug/tst-chk4.cc +deleted file mode 100644 +index c82e6aac86038791..0000000000000000 +--- a/debug/tst-chk4.cc ++++ /dev/null +@@ -1 +0,0 @@ +-#include "tst-chk1.c" +diff --git a/debug/tst-chk5.cc b/debug/tst-chk5.cc +deleted file mode 100644 +index be37ce2d22f0760a..0000000000000000 +--- a/debug/tst-chk5.cc ++++ /dev/null +@@ -1,2 +0,0 @@ +-#define _FORTIFY_SOURCE 1 +-#include "tst-chk1.c" +diff --git a/debug/tst-chk6.cc b/debug/tst-chk6.cc +deleted file mode 100644 +index 38b8e4fb360ba722..0000000000000000 +--- a/debug/tst-chk6.cc ++++ /dev/null +@@ -1,2 +0,0 @@ +-#define _FORTIFY_SOURCE 2 +-#include "tst-chk1.c" +diff --git a/debug/tst-chk7.c b/debug/tst-chk7.c +deleted file mode 100644 +index 2a7b32381268135c..0000000000000000 +--- a/debug/tst-chk7.c ++++ /dev/null +@@ -1,2 +0,0 @@ +-#define _FORTIFY_SOURCE 3 +-#include "tst-chk1.c" +diff --git a/debug/tst-chk8.cc b/debug/tst-chk8.cc +deleted file mode 100644 +index 2a7b32381268135c..0000000000000000 +--- a/debug/tst-chk8.cc ++++ /dev/null +@@ -1,2 +0,0 @@ +-#define _FORTIFY_SOURCE 3 +-#include "tst-chk1.c" +diff --git a/debug/tst-chk1.c b/debug/tst-fortify.c +similarity index 100% +rename from debug/tst-chk1.c +rename to debug/tst-fortify.c +diff --git a/debug/tst-lfschk1.c b/debug/tst-lfschk1.c +deleted file mode 100644 +index f3e6d47d5e4484c3..0000000000000000 +--- a/debug/tst-lfschk1.c ++++ /dev/null +@@ -1,2 +0,0 @@ +-#define _FILE_OFFSET_BITS 64 +-#include "tst-chk1.c" +diff --git a/debug/tst-lfschk2.c b/debug/tst-lfschk2.c +deleted file mode 100644 +index 95d4db1d32d2eeb3..0000000000000000 +--- a/debug/tst-lfschk2.c ++++ /dev/null +@@ -1,2 +0,0 @@ +-#define _FILE_OFFSET_BITS 64 +-#include "tst-chk2.c" +diff --git a/debug/tst-lfschk3.c b/debug/tst-lfschk3.c +deleted file mode 100644 +index 50a1ae1258f1553d..0000000000000000 +--- a/debug/tst-lfschk3.c ++++ /dev/null +@@ -1,2 +0,0 @@ +-#define _FILE_OFFSET_BITS 64 +-#include "tst-chk3.c" +diff --git a/debug/tst-lfschk4.cc b/debug/tst-lfschk4.cc +deleted file mode 100644 +index f3e6d47d5e4484c3..0000000000000000 +--- a/debug/tst-lfschk4.cc ++++ /dev/null +@@ -1,2 +0,0 @@ +-#define _FILE_OFFSET_BITS 64 +-#include "tst-chk1.c" +diff --git a/debug/tst-lfschk5.cc b/debug/tst-lfschk5.cc +deleted file mode 100644 +index 95d4db1d32d2eeb3..0000000000000000 +--- a/debug/tst-lfschk5.cc ++++ /dev/null +@@ -1,2 +0,0 @@ +-#define _FILE_OFFSET_BITS 64 +-#include "tst-chk2.c" +diff --git a/debug/tst-lfschk6.cc b/debug/tst-lfschk6.cc +deleted file mode 100644 +index 50a1ae1258f1553d..0000000000000000 +--- a/debug/tst-lfschk6.cc ++++ /dev/null +@@ -1,2 +0,0 @@ +-#define _FILE_OFFSET_BITS 64 +-#include "tst-chk3.c" diff --git a/glibc-rh2033684-2.patch b/glibc-rh2033684-2.patch new file mode 100644 index 0000000..4651008 --- /dev/null +++ b/glibc-rh2033684-2.patch @@ -0,0 +1,101 @@ +commit c43c5796121bc5bcc0867f02e5536874aa8196c1 +Author: Siddhesh Poyarekar +Date: Wed Dec 30 11:54:00 2020 +0530 + + Introduce _FORTIFY_SOURCE=3 + + Introduce a new _FORTIFY_SOURCE level of 3 to enable additional + fortifications that may have a noticeable performance impact, allowing + more fortification coverage at the cost of some performance. + + With llvm 9.0 or later, this will replace the use of + __builtin_object_size with __builtin_dynamic_object_size. + + __builtin_dynamic_object_size + ----------------------------- + + __builtin_dynamic_object_size is an LLVM builtin that is similar to + __builtin_object_size. In addition to what __builtin_object_size + does, i.e. replace the builtin call with a constant object size, + __builtin_dynamic_object_size will replace the call site with an + expression that evaluates to the object size, thus expanding its + applicability. In practice, __builtin_dynamic_object_size evaluates + these expressions through malloc/calloc calls that it can associate + with the object being evaluated. + + A simple motivating example is below; -D_FORTIFY_SOURCE=2 would miss + this and emit memcpy, but -D_FORTIFY_SOURCE=3 with the help of + __builtin_dynamic_object_size is able to emit __memcpy_chk with the + allocation size expression passed into the function: + + void *copy_obj (const void *src, size_t alloc, size_t copysize) + { + void *obj = malloc (alloc); + memcpy (obj, src, copysize); + return obj; + } + + Limitations + ----------- + + If the object was allocated elsewhere that the compiler cannot see, or + if it was allocated in the function with a function that the compiler + does not recognize as an allocator then __builtin_dynamic_object_size + also returns -1. + + Further, the expression used to compute object size may be non-trivial + and may potentially incur a noticeable performance impact. These + fortifications are hence enabled at a new _FORTIFY_SOURCE level to + allow developers to make a choice on the tradeoff according to their + environment. + +diff --git a/include/features.h b/include/features.h +index ea7673ee115bcf0a..fe9fe16d034fad1b 100644 +--- a/include/features.h ++++ b/include/features.h +@@ -381,6 +381,11 @@ + # warning _FORTIFY_SOURCE requires compiling with optimization (-O) + # elif !__GNUC_PREREQ (4, 1) + # warning _FORTIFY_SOURCE requires GCC 4.1 or later ++# elif _FORTIFY_SOURCE > 2 && __glibc_clang_prereq (9, 0) ++# if _FORTIFY_SOURCE > 3 ++# warning _FORTIFY_SOURCE > 3 is treated like 3 on this platform ++# endif ++# define __USE_FORTIFY_LEVEL 3 + # elif _FORTIFY_SOURCE > 1 + # if _FORTIFY_SOURCE > 2 + # warning _FORTIFY_SOURCE > 2 is treated like 2 on this platform +diff --git a/manual/creature.texi b/manual/creature.texi +index 8876b2ab779c988f..64f361f27a7d6cdf 100644 +--- a/manual/creature.texi ++++ b/manual/creature.texi +@@ -247,7 +247,8 @@ included. + @standards{GNU, (none)} + If this macro is defined to @math{1}, security hardening is added to + various library functions. If defined to @math{2}, even stricter +-checks are applied. ++checks are applied. If defined to @math{3}, @theglibc{} may also use ++checks that may have an additional performance overhead. + @end defvr + + @defvr Macro _REENTRANT +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index 3f6fe3cc8563b493..1e39307b0ebcf38f 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -123,6 +123,15 @@ + #define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1) + #define __bos0(ptr) __builtin_object_size (ptr, 0) + ++/* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available. */ ++#if __USE_FORTIFY_LEVEL == 3 && __glibc_clang_prereq (9, 0) ++# define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0) ++# define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1) ++#else ++# define __glibc_objsize0(__o) __bos0 (__o) ++# define __glibc_objsize(__o) __bos (__o) ++#endif ++ + #if __GNUC_PREREQ (4,3) + # define __warndecl(name, msg) \ + extern void name (void) __attribute__((__warning__ (msg))) diff --git a/glibc-rh2033684-3.patch b/glibc-rh2033684-3.patch new file mode 100644 index 0000000..b8d0093 --- /dev/null +++ b/glibc-rh2033684-3.patch @@ -0,0 +1,43 @@ +commit 7163ace3318d666d40771f5c8e7c4a148827070f +Author: Siddhesh Poyarekar +Date: Thu Nov 12 12:09:56 2020 +0530 + + Use __builtin___stpncpy_chk when available + + The builtin has been available in gcc since 4.7.0 and in clang since + 2.6. This fixes stpncpy fortification with clang since it does a + better job of plugging in __stpncpy_chk in the right place than the + header hackery. + + This has been tested by building and running all tests with gcc 10.2.1 + and also with clang tip as of a few days ago (just the tests in debug/ + since running all tests don't work with clang at the moment) to make + sure that both compilers pass the stpncpy tests. + +diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h +index a07ab0dbc8c8dd5b..4ed6755a6c1ca247 100644 +--- a/string/bits/string_fortified.h ++++ b/string/bits/string_fortified.h +@@ -106,7 +106,13 @@ __NTH (strncpy (char *__restrict __dest, const char *__restrict __src, + return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest)); + } + +-/* XXX We have no corresponding builtin yet. */ ++#if __GNUC_PREREQ (4, 7) || __glibc_clang_prereq (2, 6) ++__fortify_function char * ++__NTH (stpncpy (char *__dest, const char *__src, size_t __n)) ++{ ++ return __builtin___stpncpy_chk (__dest, __src, __n, __bos (__dest)); ++} ++#else + extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n, + size_t __destlen) __THROW; + extern char *__REDIRECT_NTH (__stpncpy_alias, (char *__dest, const char *__src, +@@ -120,6 +126,7 @@ __NTH (stpncpy (char *__dest, const char *__src, size_t __n)) + return __stpncpy_chk (__dest, __src, __n, __bos (__dest)); + return __stpncpy_alias (__dest, __src, __n); + } ++#endif + + + __fortify_function char * diff --git a/glibc-rh2033684-4.patch b/glibc-rh2033684-4.patch new file mode 100644 index 0000000..ebd0c33 --- /dev/null +++ b/glibc-rh2033684-4.patch @@ -0,0 +1,161 @@ +commit 2a3224c53653214cbba2ec23424702193c80ea3b +Author: Siddhesh Poyarekar +Date: Wed Dec 30 11:09:58 2020 +0530 + + string: Enable __FORTIFY_LEVEL=3 + + This change enhances fortified string functions to use + __builtin_dynamic_object_size under _FORTIFY_SOURCE=3 whenever the + compiler supports it. + +# Conflicts: +# string/bits/string_fortified.h + +Conflict resolved to retain __GNUC_PREREQ (5,0) macro check in RHEL-8 +glibc. + +diff --git a/include/string.h b/include/string.h +index 4d622f1c0305e78e..bbc97082661caf42 100644 +--- a/include/string.h ++++ b/include/string.h +@@ -119,10 +119,11 @@ libc_hidden_proto (__ffs) + void __explicit_bzero_chk_internal (void *, size_t, size_t) + __THROW __nonnull ((1)) attribute_hidden; + # define explicit_bzero(buf, len) \ +- __explicit_bzero_chk_internal (buf, len, __bos0 (buf)) ++ __explicit_bzero_chk_internal (buf, len, __glibc_objsize0 (buf)) + #elif !IS_IN (nonlib) + void __explicit_bzero_chk (void *, size_t, size_t) __THROW __nonnull ((1)); +-# define explicit_bzero(buf, len) __explicit_bzero_chk (buf, len, __bos0 (buf)) ++# define explicit_bzero(buf, len) __explicit_bzero_chk (buf, len, \ ++ __glibc_objsize0 (buf)) + #endif + + libc_hidden_builtin_proto (memchr) +diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h +index 4ed6755a6c1ca247..27ec273ec41cd81c 100644 +--- a/string/bits/string_fortified.h ++++ b/string/bits/string_fortified.h +@@ -31,13 +31,15 @@ __fortify_function void * + __NTH (memcpy (void *__restrict __dest, const void *__restrict __src, + size_t __len)) + { +- return __builtin___memcpy_chk (__dest, __src, __len, __bos0 (__dest)); ++ return __builtin___memcpy_chk (__dest, __src, __len, ++ __glibc_objsize0 (__dest)); + } + + __fortify_function void * + __NTH (memmove (void *__dest, const void *__src, size_t __len)) + { +- return __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest)); ++ return __builtin___memmove_chk (__dest, __src, __len, ++ __glibc_objsize0 (__dest)); + } + + #ifdef __USE_GNU +@@ -45,7 +47,8 @@ __fortify_function void * + __NTH (mempcpy (void *__restrict __dest, const void *__restrict __src, + size_t __len)) + { +- return __builtin___mempcpy_chk (__dest, __src, __len, __bos0 (__dest)); ++ return __builtin___mempcpy_chk (__dest, __src, __len, ++ __glibc_objsize0 (__dest)); + } + #endif + +@@ -68,7 +71,8 @@ __NTH (memset (void *__dest, int __ch, size_t __len)) + return __dest; + } + #endif +- return __builtin___memset_chk (__dest, __ch, __len, __bos0 (__dest)); ++ return __builtin___memset_chk (__dest, __ch, __len, ++ __glibc_objsize0 (__dest)); + } + + #ifdef __USE_MISC +@@ -80,21 +84,21 @@ void __explicit_bzero_chk (void *__dest, size_t __len, size_t __destlen) + __fortify_function void + __NTH (explicit_bzero (void *__dest, size_t __len)) + { +- __explicit_bzero_chk (__dest, __len, __bos0 (__dest)); ++ __explicit_bzero_chk (__dest, __len, __glibc_objsize0 (__dest)); + } + #endif + + __fortify_function char * + __NTH (strcpy (char *__restrict __dest, const char *__restrict __src)) + { +- return __builtin___strcpy_chk (__dest, __src, __bos (__dest)); ++ return __builtin___strcpy_chk (__dest, __src, __glibc_objsize (__dest)); + } + + #ifdef __USE_GNU + __fortify_function char * + __NTH (stpcpy (char *__restrict __dest, const char *__restrict __src)) + { +- return __builtin___stpcpy_chk (__dest, __src, __bos (__dest)); ++ return __builtin___stpcpy_chk (__dest, __src, __glibc_objsize (__dest)); + } + #endif + +@@ -103,14 +107,16 @@ __fortify_function char * + __NTH (strncpy (char *__restrict __dest, const char *__restrict __src, + size_t __len)) + { +- return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest)); ++ return __builtin___strncpy_chk (__dest, __src, __len, ++ __glibc_objsize (__dest)); + } + + #if __GNUC_PREREQ (4, 7) || __glibc_clang_prereq (2, 6) + __fortify_function char * + __NTH (stpncpy (char *__dest, const char *__src, size_t __n)) + { +- return __builtin___stpncpy_chk (__dest, __src, __n, __bos (__dest)); ++ return __builtin___stpncpy_chk (__dest, __src, __n, ++ __glibc_objsize (__dest)); + } + #else + extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n, +@@ -132,7 +138,7 @@ __NTH (stpncpy (char *__dest, const char *__src, size_t __n)) + __fortify_function char * + __NTH (strcat (char *__restrict __dest, const char *__restrict __src)) + { +- return __builtin___strcat_chk (__dest, __src, __bos (__dest)); ++ return __builtin___strcat_chk (__dest, __src, __glibc_objsize (__dest)); + } + + +@@ -140,7 +146,8 @@ __fortify_function char * + __NTH (strncat (char *__restrict __dest, const char *__restrict __src, + size_t __len)) + { +- return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest)); ++ return __builtin___strncat_chk (__dest, __src, __len, ++ __glibc_objsize (__dest)); + } + + #endif /* bits/string_fortified.h */ +diff --git a/string/bits/strings_fortified.h b/string/bits/strings_fortified.h +index d9b2804525cfa994..871515bd2cba1f8a 100644 +--- a/string/bits/strings_fortified.h ++++ b/string/bits/strings_fortified.h +@@ -22,13 +22,15 @@ + __fortify_function void + __NTH (bcopy (const void *__src, void *__dest, size_t __len)) + { +- (void) __builtin___memmove_chk (__dest, __src, __len, __bos0 (__dest)); ++ (void) __builtin___memmove_chk (__dest, __src, __len, ++ __glibc_objsize0 (__dest)); + } + + __fortify_function void + __NTH (bzero (void *__dest, size_t __len)) + { +- (void) __builtin___memset_chk (__dest, '\0', __len, __bos0 (__dest)); ++ (void) __builtin___memset_chk (__dest, '\0', __len, ++ __glibc_objsize0 (__dest)); + } + + #endif diff --git a/glibc-rh2033684-5.patch b/glibc-rh2033684-5.patch new file mode 100644 index 0000000..8c1f7f3 --- /dev/null +++ b/glibc-rh2033684-5.patch @@ -0,0 +1,963 @@ +commit f9de8bfe1a731c309b91d175b4f6f4aeb786effa +Author: Siddhesh Poyarekar +Date: Tue Dec 15 23:50:09 2020 +0530 + + nonstring: Enable __FORTIFY_LEVEL=3 + + Use __builtin_dynamic_object_size in the remaining functions that + don't have compiler builtins as is the case for string functions. + +diff --git a/io/bits/poll2.h b/io/bits/poll2.h +index 7e8406b87d6319f8..f47fd9ad0945234f 100644 +--- a/io/bits/poll2.h ++++ b/io/bits/poll2.h +@@ -35,12 +35,13 @@ extern int __REDIRECT (__poll_chk_warn, (struct pollfd *__fds, nfds_t __nfds, + __fortify_function int + poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) + { +- if (__bos (__fds) != (__SIZE_TYPE__) -1) ++ if (__glibc_objsize (__fds) != (__SIZE_TYPE__) -1) + { + if (! __builtin_constant_p (__nfds)) +- return __poll_chk (__fds, __nfds, __timeout, __bos (__fds)); +- else if (__bos (__fds) / sizeof (*__fds) < __nfds) +- return __poll_chk_warn (__fds, __nfds, __timeout, __bos (__fds)); ++ return __poll_chk (__fds, __nfds, __timeout, __glibc_objsize (__fds)); ++ else if (__glibc_objsize (__fds) / sizeof (*__fds) < __nfds) ++ return __poll_chk_warn (__fds, __nfds, __timeout, ++ __glibc_objsize (__fds)); + } + + return __poll_alias (__fds, __nfds, __timeout); +@@ -65,13 +66,14 @@ __fortify_function int + ppoll (struct pollfd *__fds, nfds_t __nfds, const struct timespec *__timeout, + const __sigset_t *__ss) + { +- if (__bos (__fds) != (__SIZE_TYPE__) -1) ++ if (__glibc_objsize (__fds) != (__SIZE_TYPE__) -1) + { + if (! __builtin_constant_p (__nfds)) +- return __ppoll_chk (__fds, __nfds, __timeout, __ss, __bos (__fds)); +- else if (__bos (__fds) / sizeof (*__fds) < __nfds) ++ return __ppoll_chk (__fds, __nfds, __timeout, __ss, ++ __glibc_objsize (__fds)); ++ else if (__glibc_objsize (__fds) / sizeof (*__fds) < __nfds) + return __ppoll_chk_warn (__fds, __nfds, __timeout, __ss, +- __bos (__fds)); ++ __glibc_objsize (__fds)); + } + + return __ppoll_alias (__fds, __nfds, __timeout, __ss); +diff --git a/libio/bits/stdio.h b/libio/bits/stdio.h +index 4ab919031f77a960..1372d4bf70c43d53 100644 +--- a/libio/bits/stdio.h ++++ b/libio/bits/stdio.h +@@ -31,7 +31,7 @@ + + + #ifdef __USE_EXTERN_INLINES +-/* For -D_FORTIFY_SOURCE{,=2} bits/stdio2.h will define a different ++/* For -D_FORTIFY_SOURCE{,=2,=3} bits/stdio2.h will define a different + inline. */ + # if !(__USE_FORTIFY_LEVEL > 0 && defined __fortify_function) + /* Write formatted output to stdout from argument list ARG. */ +diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h +index 11651506a67daea0..2cd69f44cfadfc9f 100644 +--- a/libio/bits/stdio2.h ++++ b/libio/bits/stdio2.h +@@ -34,12 +34,13 @@ __fortify_function int + __NTH (sprintf (char *__restrict __s, const char *__restrict __fmt, ...)) + { + return __builtin___sprintf_chk (__s, __USE_FORTIFY_LEVEL - 1, +- __bos (__s), __fmt, __va_arg_pack ()); ++ __glibc_objsize (__s), __fmt, ++ __va_arg_pack ()); + } + #elif !defined __cplusplus + # define sprintf(str, ...) \ +- __builtin___sprintf_chk (str, __USE_FORTIFY_LEVEL - 1, __bos (str), \ +- __VA_ARGS__) ++ __builtin___sprintf_chk (str, __USE_FORTIFY_LEVEL - 1, \ ++ __glibc_objsize (str), __VA_ARGS__) + #endif + + __fortify_function int +@@ -47,7 +48,7 @@ __NTH (vsprintf (char *__restrict __s, const char *__restrict __fmt, + __gnuc_va_list __ap)) + { + return __builtin___vsprintf_chk (__s, __USE_FORTIFY_LEVEL - 1, +- __bos (__s), __fmt, __ap); ++ __glibc_objsize (__s), __fmt, __ap); + } + + #if defined __USE_ISOC99 || defined __USE_UNIX98 +@@ -65,12 +66,13 @@ __NTH (snprintf (char *__restrict __s, size_t __n, + const char *__restrict __fmt, ...)) + { + return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, +- __bos (__s), __fmt, __va_arg_pack ()); ++ __glibc_objsize (__s), __fmt, ++ __va_arg_pack ()); + } + # elif !defined __cplusplus + # define snprintf(str, len, ...) \ +- __builtin___snprintf_chk (str, len, __USE_FORTIFY_LEVEL - 1, __bos (str), \ +- __VA_ARGS__) ++ __builtin___snprintf_chk (str, len, __USE_FORTIFY_LEVEL - 1, \ ++ __glibc_objsize (str), __VA_ARGS__) + # endif + + __fortify_function int +@@ -78,7 +80,7 @@ __NTH (vsnprintf (char *__restrict __s, size_t __n, + const char *__restrict __fmt, __gnuc_va_list __ap)) + { + return __builtin___vsnprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, +- __bos (__s), __fmt, __ap); ++ __glibc_objsize (__s), __fmt, __ap); + } + + #endif +@@ -234,8 +236,8 @@ extern char *__REDIRECT (__gets_warn, (char *__str), gets) + __fortify_function __wur char * + gets (char *__str) + { +- if (__bos (__str) != (size_t) -1) +- return __gets_chk (__str, __bos (__str)); ++ if (__glibc_objsize (__str) != (size_t) -1) ++ return __gets_chk (__str, __glibc_objsize (__str)); + return __gets_warn (__str); + } + #endif +@@ -254,13 +256,13 @@ extern char *__REDIRECT (__fgets_chk_warn, + __fortify_function __wur char * + fgets (char *__restrict __s, int __n, FILE *__restrict __stream) + { +- if (__bos (__s) != (size_t) -1) ++ if (__glibc_objsize (__s) != (size_t) -1) + { + if (!__builtin_constant_p (__n) || __n <= 0) +- return __fgets_chk (__s, __bos (__s), __n, __stream); ++ return __fgets_chk (__s, __glibc_objsize (__s), __n, __stream); + +- if ((size_t) __n > __bos (__s)) +- return __fgets_chk_warn (__s, __bos (__s), __n, __stream); ++ if ((size_t) __n > __glibc_objsize (__s)) ++ return __fgets_chk_warn (__s, __glibc_objsize (__s), __n, __stream); + } + return __fgets_alias (__s, __n, __stream); + } +@@ -284,15 +286,17 @@ __fortify_function __wur size_t + fread (void *__restrict __ptr, size_t __size, size_t __n, + FILE *__restrict __stream) + { +- if (__bos0 (__ptr) != (size_t) -1) ++ if (__glibc_objsize0 (__ptr) != (size_t) -1) + { + if (!__builtin_constant_p (__size) + || !__builtin_constant_p (__n) + || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2))) +- return __fread_chk (__ptr, __bos0 (__ptr), __size, __n, __stream); ++ return __fread_chk (__ptr, __glibc_objsize0 (__ptr), __size, __n, ++ __stream); + +- if (__size * __n > __bos0 (__ptr)) +- return __fread_chk_warn (__ptr, __bos0 (__ptr), __size, __n, __stream); ++ if (__size * __n > __glibc_objsize0 (__ptr)) ++ return __fread_chk_warn (__ptr, __glibc_objsize0 (__ptr), __size, __n, ++ __stream); + } + return __fread_alias (__ptr, __size, __n, __stream); + } +@@ -312,13 +316,15 @@ extern char *__REDIRECT (__fgets_unlocked_chk_warn, + __fortify_function __wur char * + fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream) + { +- if (__bos (__s) != (size_t) -1) ++ if (__glibc_objsize (__s) != (size_t) -1) + { + if (!__builtin_constant_p (__n) || __n <= 0) +- return __fgets_unlocked_chk (__s, __bos (__s), __n, __stream); ++ return __fgets_unlocked_chk (__s, __glibc_objsize (__s), __n, ++ __stream); + +- if ((size_t) __n > __bos (__s)) +- return __fgets_unlocked_chk_warn (__s, __bos (__s), __n, __stream); ++ if ((size_t) __n > __glibc_objsize (__s)) ++ return __fgets_unlocked_chk_warn (__s, __glibc_objsize (__s), __n, ++ __stream); + } + return __fgets_unlocked_alias (__s, __n, __stream); + } +@@ -345,17 +351,17 @@ __fortify_function __wur size_t + fread_unlocked (void *__restrict __ptr, size_t __size, size_t __n, + FILE *__restrict __stream) + { +- if (__bos0 (__ptr) != (size_t) -1) ++ if (__glibc_objsize0 (__ptr) != (size_t) -1) + { + if (!__builtin_constant_p (__size) + || !__builtin_constant_p (__n) + || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2))) +- return __fread_unlocked_chk (__ptr, __bos0 (__ptr), __size, __n, +- __stream); ++ return __fread_unlocked_chk (__ptr, __glibc_objsize0 (__ptr), __size, ++ __n, __stream); + +- if (__size * __n > __bos0 (__ptr)) +- return __fread_unlocked_chk_warn (__ptr, __bos0 (__ptr), __size, __n, +- __stream); ++ if (__size * __n > __glibc_objsize0 (__ptr)) ++ return __fread_unlocked_chk_warn (__ptr, __glibc_objsize0 (__ptr), ++ __size, __n, __stream); + } + + # ifdef __USE_EXTERN_INLINES +diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h +index 9a749dccf8de65cd..a0c4dcfe9c61a7b8 100644 +--- a/posix/bits/unistd.h ++++ b/posix/bits/unistd.h +@@ -33,13 +33,14 @@ extern ssize_t __REDIRECT (__read_chk_warn, + __fortify_function __wur ssize_t + read (int __fd, void *__buf, size_t __nbytes) + { +- if (__bos0 (__buf) != (size_t) -1) ++ if (__glibc_objsize0 (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__nbytes)) +- return __read_chk (__fd, __buf, __nbytes, __bos0 (__buf)); ++ return __read_chk (__fd, __buf, __nbytes, __glibc_objsize0 (__buf)); + +- if (__nbytes > __bos0 (__buf)) +- return __read_chk_warn (__fd, __buf, __nbytes, __bos0 (__buf)); ++ if (__nbytes > __glibc_objsize0 (__buf)) ++ return __read_chk_warn (__fd, __buf, __nbytes, ++ __glibc_objsize0 (__buf)); + } + return __read_alias (__fd, __buf, __nbytes); + } +@@ -71,14 +72,15 @@ extern ssize_t __REDIRECT (__pread64_chk_warn, + __fortify_function __wur ssize_t + pread (int __fd, void *__buf, size_t __nbytes, __off_t __offset) + { +- if (__bos0 (__buf) != (size_t) -1) ++ if (__glibc_objsize0 (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__nbytes)) +- return __pread_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf)); ++ return __pread_chk (__fd, __buf, __nbytes, __offset, ++ __glibc_objsize0 (__buf)); + +- if ( __nbytes > __bos0 (__buf)) ++ if ( __nbytes > __glibc_objsize0 (__buf)) + return __pread_chk_warn (__fd, __buf, __nbytes, __offset, +- __bos0 (__buf)); ++ __glibc_objsize0 (__buf)); + } + return __pread_alias (__fd, __buf, __nbytes, __offset); + } +@@ -86,14 +88,15 @@ pread (int __fd, void *__buf, size_t __nbytes, __off_t __offset) + __fortify_function __wur ssize_t + pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset) + { +- if (__bos0 (__buf) != (size_t) -1) ++ if (__glibc_objsize0 (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__nbytes)) +- return __pread64_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf)); ++ return __pread64_chk (__fd, __buf, __nbytes, __offset, ++ __glibc_objsize0 (__buf)); + +- if ( __nbytes > __bos0 (__buf)) ++ if ( __nbytes > __glibc_objsize0 (__buf)) + return __pread64_chk_warn (__fd, __buf, __nbytes, __offset, +- __bos0 (__buf)); ++ __glibc_objsize0 (__buf)); + } + + return __pread64_alias (__fd, __buf, __nbytes, __offset); +@@ -104,14 +107,15 @@ pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset) + __fortify_function __wur ssize_t + pread64 (int __fd, void *__buf, size_t __nbytes, __off64_t __offset) + { +- if (__bos0 (__buf) != (size_t) -1) ++ if (__glibc_objsize0 (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__nbytes)) +- return __pread64_chk (__fd, __buf, __nbytes, __offset, __bos0 (__buf)); ++ return __pread64_chk (__fd, __buf, __nbytes, __offset, ++ __glibc_objsize0 (__buf)); + +- if ( __nbytes > __bos0 (__buf)) ++ if ( __nbytes > __glibc_objsize0 (__buf)) + return __pread64_chk_warn (__fd, __buf, __nbytes, __offset, +- __bos0 (__buf)); ++ __glibc_objsize0 (__buf)); + } + + return __pread64_alias (__fd, __buf, __nbytes, __offset); +@@ -139,13 +143,14 @@ __fortify_function __nonnull ((1, 2)) __wur ssize_t + __NTH (readlink (const char *__restrict __path, char *__restrict __buf, + size_t __len)) + { +- if (__bos (__buf) != (size_t) -1) ++ if (__glibc_objsize (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) +- return __readlink_chk (__path, __buf, __len, __bos (__buf)); ++ return __readlink_chk (__path, __buf, __len, __glibc_objsize (__buf)); + +- if ( __len > __bos (__buf)) +- return __readlink_chk_warn (__path, __buf, __len, __bos (__buf)); ++ if ( __len > __glibc_objsize (__buf)) ++ return __readlink_chk_warn (__path, __buf, __len, ++ __glibc_objsize (__buf)); + } + return __readlink_alias (__path, __buf, __len); + } +@@ -173,14 +178,15 @@ __fortify_function __nonnull ((2, 3)) __wur ssize_t + __NTH (readlinkat (int __fd, const char *__restrict __path, + char *__restrict __buf, size_t __len)) + { +- if (__bos (__buf) != (size_t) -1) ++ if (__glibc_objsize (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) +- return __readlinkat_chk (__fd, __path, __buf, __len, __bos (__buf)); ++ return __readlinkat_chk (__fd, __path, __buf, __len, ++ __glibc_objsize (__buf)); + +- if (__len > __bos (__buf)) ++ if (__len > __glibc_objsize (__buf)) + return __readlinkat_chk_warn (__fd, __path, __buf, __len, +- __bos (__buf)); ++ __glibc_objsize (__buf)); + } + return __readlinkat_alias (__fd, __path, __buf, __len); + } +@@ -199,13 +205,13 @@ extern char *__REDIRECT_NTH (__getcwd_chk_warn, + __fortify_function __wur char * + __NTH (getcwd (char *__buf, size_t __size)) + { +- if (__bos (__buf) != (size_t) -1) ++ if (__glibc_objsize (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__size)) +- return __getcwd_chk (__buf, __size, __bos (__buf)); ++ return __getcwd_chk (__buf, __size, __glibc_objsize (__buf)); + +- if (__size > __bos (__buf)) +- return __getcwd_chk_warn (__buf, __size, __bos (__buf)); ++ if (__size > __glibc_objsize (__buf)) ++ return __getcwd_chk_warn (__buf, __size, __glibc_objsize (__buf)); + } + return __getcwd_alias (__buf, __size); + } +@@ -220,8 +226,8 @@ extern char *__REDIRECT_NTH (__getwd_warn, (char *__buf), getwd) + __fortify_function __nonnull ((1)) __attribute_deprecated__ __wur char * + __NTH (getwd (char *__buf)) + { +- if (__bos (__buf) != (size_t) -1) +- return __getwd_chk (__buf, __bos (__buf)); ++ if (__glibc_objsize (__buf) != (size_t) -1) ++ return __getwd_chk (__buf, __glibc_objsize (__buf)); + return __getwd_warn (__buf); + } + #endif +@@ -239,13 +245,14 @@ extern size_t __REDIRECT_NTH (__confstr_chk_warn, + __fortify_function size_t + __NTH (confstr (int __name, char *__buf, size_t __len)) + { +- if (__bos (__buf) != (size_t) -1) ++ if (__glibc_objsize (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) +- return __confstr_chk (__name, __buf, __len, __bos (__buf)); ++ return __confstr_chk (__name, __buf, __len, __glibc_objsize (__buf)); + +- if (__bos (__buf) < __len) +- return __confstr_chk_warn (__name, __buf, __len, __bos (__buf)); ++ if (__glibc_objsize (__buf) < __len) ++ return __confstr_chk_warn (__name, __buf, __len, ++ __glibc_objsize (__buf)); + } + return __confstr_alias (__name, __buf, __len); + } +@@ -264,13 +271,13 @@ extern int __REDIRECT_NTH (__getgroups_chk_warn, + __fortify_function int + __NTH (getgroups (int __size, __gid_t __list[])) + { +- if (__bos (__list) != (size_t) -1) ++ if (__glibc_objsize (__list) != (size_t) -1) + { + if (!__builtin_constant_p (__size) || __size < 0) +- return __getgroups_chk (__size, __list, __bos (__list)); ++ return __getgroups_chk (__size, __list, __glibc_objsize (__list)); + +- if (__size * sizeof (__gid_t) > __bos (__list)) +- return __getgroups_chk_warn (__size, __list, __bos (__list)); ++ if (__size * sizeof (__gid_t) > __glibc_objsize (__list)) ++ return __getgroups_chk_warn (__size, __list, __glibc_objsize (__list)); + } + return __getgroups_alias (__size, __list); + } +@@ -290,13 +297,15 @@ extern int __REDIRECT_NTH (__ttyname_r_chk_warn, + __fortify_function int + __NTH (ttyname_r (int __fd, char *__buf, size_t __buflen)) + { +- if (__bos (__buf) != (size_t) -1) ++ if (__glibc_objsize (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__buflen)) +- return __ttyname_r_chk (__fd, __buf, __buflen, __bos (__buf)); ++ return __ttyname_r_chk (__fd, __buf, __buflen, ++ __glibc_objsize (__buf)); + +- if (__buflen > __bos (__buf)) +- return __ttyname_r_chk_warn (__fd, __buf, __buflen, __bos (__buf)); ++ if (__buflen > __glibc_objsize (__buf)) ++ return __ttyname_r_chk_warn (__fd, __buf, __buflen, ++ __glibc_objsize (__buf)); + } + return __ttyname_r_alias (__fd, __buf, __buflen); + } +@@ -316,13 +325,14 @@ extern int __REDIRECT (__getlogin_r_chk_warn, + __fortify_function int + getlogin_r (char *__buf, size_t __buflen) + { +- if (__bos (__buf) != (size_t) -1) ++ if (__glibc_objsize (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__buflen)) +- return __getlogin_r_chk (__buf, __buflen, __bos (__buf)); ++ return __getlogin_r_chk (__buf, __buflen, __glibc_objsize (__buf)); + +- if (__buflen > __bos (__buf)) +- return __getlogin_r_chk_warn (__buf, __buflen, __bos (__buf)); ++ if (__buflen > __glibc_objsize (__buf)) ++ return __getlogin_r_chk_warn (__buf, __buflen, ++ __glibc_objsize (__buf)); + } + return __getlogin_r_alias (__buf, __buflen); + } +@@ -343,13 +353,14 @@ extern int __REDIRECT_NTH (__gethostname_chk_warn, + __fortify_function int + __NTH (gethostname (char *__buf, size_t __buflen)) + { +- if (__bos (__buf) != (size_t) -1) ++ if (__glibc_objsize (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__buflen)) +- return __gethostname_chk (__buf, __buflen, __bos (__buf)); ++ return __gethostname_chk (__buf, __buflen, __glibc_objsize (__buf)); + +- if (__buflen > __bos (__buf)) +- return __gethostname_chk_warn (__buf, __buflen, __bos (__buf)); ++ if (__buflen > __glibc_objsize (__buf)) ++ return __gethostname_chk_warn (__buf, __buflen, ++ __glibc_objsize (__buf)); + } + return __gethostname_alias (__buf, __buflen); + } +@@ -372,13 +383,14 @@ extern int __REDIRECT_NTH (__getdomainname_chk_warn, + __fortify_function int + __NTH (getdomainname (char *__buf, size_t __buflen)) + { +- if (__bos (__buf) != (size_t) -1) ++ if (__glibc_objsize (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__buflen)) +- return __getdomainname_chk (__buf, __buflen, __bos (__buf)); ++ return __getdomainname_chk (__buf, __buflen, __glibc_objsize (__buf)); + +- if (__buflen > __bos (__buf)) +- return __getdomainname_chk_warn (__buf, __buflen, __bos (__buf)); ++ if (__buflen > __glibc_objsize (__buf)) ++ return __getdomainname_chk_warn (__buf, __buflen, ++ __glibc_objsize (__buf)); + } + return __getdomainname_alias (__buf, __buflen); + } +diff --git a/socket/bits/socket2.h b/socket/bits/socket2.h +index a129e697352fd7cb..729e5a4cc1f4cb92 100644 +--- a/socket/bits/socket2.h ++++ b/socket/bits/socket2.h +@@ -33,13 +33,15 @@ extern ssize_t __REDIRECT (__recv_chk_warn, + __fortify_function ssize_t + recv (int __fd, void *__buf, size_t __n, int __flags) + { +- if (__bos0 (__buf) != (size_t) -1) ++ if (__glibc_objsize0 (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__n)) +- return __recv_chk (__fd, __buf, __n, __bos0 (__buf), __flags); ++ return __recv_chk (__fd, __buf, __n, __glibc_objsize0 (__buf), ++ __flags); + +- if (__n > __bos0 (__buf)) +- return __recv_chk_warn (__fd, __buf, __n, __bos0 (__buf), __flags); ++ if (__n > __glibc_objsize0 (__buf)) ++ return __recv_chk_warn (__fd, __buf, __n, __glibc_objsize0 (__buf), ++ __flags); + } + return __recv_alias (__fd, __buf, __n, __flags); + } +@@ -64,14 +66,14 @@ __fortify_function ssize_t + recvfrom (int __fd, void *__restrict __buf, size_t __n, int __flags, + __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len) + { +- if (__bos0 (__buf) != (size_t) -1) ++ if (__glibc_objsize0 (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__n)) +- return __recvfrom_chk (__fd, __buf, __n, __bos0 (__buf), __flags, +- __addr, __addr_len); +- if (__n > __bos0 (__buf)) +- return __recvfrom_chk_warn (__fd, __buf, __n, __bos0 (__buf), __flags, +- __addr, __addr_len); ++ return __recvfrom_chk (__fd, __buf, __n, __glibc_objsize0 (__buf), ++ __flags, __addr, __addr_len); ++ if (__n > __glibc_objsize0 (__buf)) ++ return __recvfrom_chk_warn (__fd, __buf, __n, __glibc_objsize0 (__buf), ++ __flags, __addr, __addr_len); + } + return __recvfrom_alias (__fd, __buf, __n, __flags, __addr, __addr_len); + } +diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h +index 53c379b99ae9d5fe..5e4114ded33f2033 100644 +--- a/stdlib/bits/stdlib.h ++++ b/stdlib/bits/stdlib.h +@@ -36,13 +36,14 @@ extern char *__REDIRECT_NTH (__realpath_chk_warn, + __fortify_function __wur char * + __NTH (realpath (const char *__restrict __name, char *__restrict __resolved)) + { +- if (__bos (__resolved) != (size_t) -1) ++ if (__glibc_objsize (__resolved) != (size_t) -1) + { + #if defined _LIBC_LIMITS_H_ && defined PATH_MAX +- if (__bos (__resolved) < PATH_MAX) +- return __realpath_chk_warn (__name, __resolved, __bos (__resolved)); ++ if (__glibc_objsize (__resolved) < PATH_MAX) ++ return __realpath_chk_warn (__name, __resolved, ++ __glibc_objsize (__resolved)); + #endif +- return __realpath_chk (__name, __resolved, __bos (__resolved)); ++ return __realpath_chk (__name, __resolved, __glibc_objsize (__resolved)); + } + + return __realpath_alias (__name, __resolved); +@@ -63,12 +64,14 @@ extern int __REDIRECT_NTH (__ptsname_r_chk_warn, + __fortify_function int + __NTH (ptsname_r (int __fd, char *__buf, size_t __buflen)) + { +- if (__bos (__buf) != (size_t) -1) ++ if (__glibc_objsize (__buf) != (size_t) -1) + { + if (!__builtin_constant_p (__buflen)) +- return __ptsname_r_chk (__fd, __buf, __buflen, __bos (__buf)); +- if (__buflen > __bos (__buf)) +- return __ptsname_r_chk_warn (__fd, __buf, __buflen, __bos (__buf)); ++ return __ptsname_r_chk (__fd, __buf, __buflen, ++ __glibc_objsize (__buf)); ++ if (__buflen > __glibc_objsize (__buf)) ++ return __ptsname_r_chk_warn (__fd, __buf, __buflen, ++ __glibc_objsize (__buf)); + } + return __ptsname_r_alias (__fd, __buf, __buflen); + } +@@ -89,8 +92,9 @@ __NTH (wctomb (char *__s, wchar_t __wchar)) + #if defined MB_LEN_MAX && MB_LEN_MAX != __STDLIB_MB_LEN_MAX + # error "Assumed value of MB_LEN_MAX wrong" + #endif +- if (__bos (__s) != (size_t) -1 && __STDLIB_MB_LEN_MAX > __bos (__s)) +- return __wctomb_chk (__s, __wchar, __bos (__s)); ++ if (__glibc_objsize (__s) != (size_t) -1 ++ && __STDLIB_MB_LEN_MAX > __glibc_objsize (__s)) ++ return __wctomb_chk (__s, __wchar, __glibc_objsize (__s)); + return __wctomb_alias (__s, __wchar); + } + +@@ -113,15 +117,16 @@ __fortify_function size_t + __NTH (mbstowcs (wchar_t *__restrict __dst, const char *__restrict __src, + size_t __len)) + { +- if (__bos (__dst) != (size_t) -1) ++ if (__glibc_objsize (__dst) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) + return __mbstowcs_chk (__dst, __src, __len, +- __bos (__dst) / sizeof (wchar_t)); ++ __glibc_objsize (__dst) / sizeof (wchar_t)); + +- if (__len > __bos (__dst) / sizeof (wchar_t)) ++ if (__len > __glibc_objsize (__dst) / sizeof (wchar_t)) + return __mbstowcs_chk_warn (__dst, __src, __len, +- __bos (__dst) / sizeof (wchar_t)); ++ (__glibc_objsize (__dst) ++ / sizeof (wchar_t))); + } + return __mbstowcs_alias (__dst, __src, __len); + } +@@ -144,12 +149,13 @@ __fortify_function size_t + __NTH (wcstombs (char *__restrict __dst, const wchar_t *__restrict __src, + size_t __len)) + { +- if (__bos (__dst) != (size_t) -1) ++ if (__glibc_objsize (__dst) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) +- return __wcstombs_chk (__dst, __src, __len, __bos (__dst)); +- if (__len > __bos (__dst)) +- return __wcstombs_chk_warn (__dst, __src, __len, __bos (__dst)); ++ return __wcstombs_chk (__dst, __src, __len, __glibc_objsize (__dst)); ++ if (__len > __glibc_objsize (__dst)) ++ return __wcstombs_chk_warn (__dst, __src, __len, ++ __glibc_objsize (__dst)); + } + return __wcstombs_alias (__dst, __src, __len); + } +diff --git a/wcsmbs/bits/wchar2.h b/wcsmbs/bits/wchar2.h +index d62b86de3e288d53..838ba877ee4b4afe 100644 +--- a/wcsmbs/bits/wchar2.h ++++ b/wcsmbs/bits/wchar2.h +@@ -39,15 +39,15 @@ __fortify_function wchar_t * + __NTH (wmemcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2, + size_t __n)) + { +- if (__bos0 (__s1) != (size_t) -1) ++ if (__glibc_objsize0 (__s1) != (size_t) -1) + { + if (!__builtin_constant_p (__n)) + return __wmemcpy_chk (__s1, __s2, __n, +- __bos0 (__s1) / sizeof (wchar_t)); ++ __glibc_objsize0 (__s1) / sizeof (wchar_t)); + +- if (__n > __bos0 (__s1) / sizeof (wchar_t)) ++ if (__n > __glibc_objsize0 (__s1) / sizeof (wchar_t)) + return __wmemcpy_chk_warn (__s1, __s2, __n, +- __bos0 (__s1) / sizeof (wchar_t)); ++ __glibc_objsize0 (__s1) / sizeof (wchar_t)); + } + return __wmemcpy_alias (__s1, __s2, __n); + } +@@ -67,15 +67,16 @@ extern wchar_t *__REDIRECT_NTH (__wmemmove_chk_warn, + __fortify_function wchar_t * + __NTH (wmemmove (wchar_t *__s1, const wchar_t *__s2, size_t __n)) + { +- if (__bos0 (__s1) != (size_t) -1) ++ if (__glibc_objsize0 (__s1) != (size_t) -1) + { + if (!__builtin_constant_p (__n)) + return __wmemmove_chk (__s1, __s2, __n, +- __bos0 (__s1) / sizeof (wchar_t)); ++ __glibc_objsize0 (__s1) / sizeof (wchar_t)); + +- if (__n > __bos0 (__s1) / sizeof (wchar_t)) ++ if (__n > __glibc_objsize0 (__s1) / sizeof (wchar_t)) + return __wmemmove_chk_warn (__s1, __s2, __n, +- __bos0 (__s1) / sizeof (wchar_t)); ++ (__glibc_objsize0 (__s1) ++ / sizeof (wchar_t))); + } + return __wmemmove_alias (__s1, __s2, __n); + } +@@ -100,15 +101,16 @@ __fortify_function wchar_t * + __NTH (wmempcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2, + size_t __n)) + { +- if (__bos0 (__s1) != (size_t) -1) ++ if (__glibc_objsize0 (__s1) != (size_t) -1) + { + if (!__builtin_constant_p (__n)) + return __wmempcpy_chk (__s1, __s2, __n, +- __bos0 (__s1) / sizeof (wchar_t)); ++ __glibc_objsize0 (__s1) / sizeof (wchar_t)); + +- if (__n > __bos0 (__s1) / sizeof (wchar_t)) ++ if (__n > __glibc_objsize0 (__s1) / sizeof (wchar_t)) + return __wmempcpy_chk_warn (__s1, __s2, __n, +- __bos0 (__s1) / sizeof (wchar_t)); ++ (__glibc_objsize0 (__s1) ++ / sizeof (wchar_t))); + } + return __wmempcpy_alias (__s1, __s2, __n); + } +@@ -128,14 +130,15 @@ extern wchar_t *__REDIRECT_NTH (__wmemset_chk_warn, + __fortify_function wchar_t * + __NTH (wmemset (wchar_t *__s, wchar_t __c, size_t __n)) + { +- if (__bos0 (__s) != (size_t) -1) ++ if (__glibc_objsize0 (__s) != (size_t) -1) + { + if (!__builtin_constant_p (__n)) +- return __wmemset_chk (__s, __c, __n, __bos0 (__s) / sizeof (wchar_t)); ++ return __wmemset_chk (__s, __c, __n, ++ __glibc_objsize0 (__s) / sizeof (wchar_t)); + +- if (__n > __bos0 (__s) / sizeof (wchar_t)) ++ if (__n > __glibc_objsize0 (__s) / sizeof (wchar_t)) + return __wmemset_chk_warn (__s, __c, __n, +- __bos0 (__s) / sizeof (wchar_t)); ++ __glibc_objsize0 (__s) / sizeof (wchar_t)); + } + return __wmemset_alias (__s, __c, __n); + } +@@ -151,8 +154,9 @@ extern wchar_t *__REDIRECT_NTH (__wcscpy_alias, + __fortify_function wchar_t * + __NTH (wcscpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src)) + { +- if (__bos (__dest) != (size_t) -1) +- return __wcscpy_chk (__dest, __src, __bos (__dest) / sizeof (wchar_t)); ++ if (__glibc_objsize (__dest) != (size_t) -1) ++ return __wcscpy_chk (__dest, __src, ++ __glibc_objsize (__dest) / sizeof (wchar_t)); + return __wcscpy_alias (__dest, __src); + } + +@@ -167,8 +171,9 @@ extern wchar_t *__REDIRECT_NTH (__wcpcpy_alias, + __fortify_function wchar_t * + __NTH (wcpcpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src)) + { +- if (__bos (__dest) != (size_t) -1) +- return __wcpcpy_chk (__dest, __src, __bos (__dest) / sizeof (wchar_t)); ++ if (__glibc_objsize (__dest) != (size_t) -1) ++ return __wcpcpy_chk (__dest, __src, ++ __glibc_objsize (__dest) / sizeof (wchar_t)); + return __wcpcpy_alias (__dest, __src); + } + +@@ -191,14 +196,15 @@ __fortify_function wchar_t * + __NTH (wcsncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src, + size_t __n)) + { +- if (__bos (__dest) != (size_t) -1) ++ if (__glibc_objsize (__dest) != (size_t) -1) + { + if (!__builtin_constant_p (__n)) + return __wcsncpy_chk (__dest, __src, __n, +- __bos (__dest) / sizeof (wchar_t)); +- if (__n > __bos (__dest) / sizeof (wchar_t)) ++ __glibc_objsize (__dest) / sizeof (wchar_t)); ++ if (__n > __glibc_objsize (__dest) / sizeof (wchar_t)) + return __wcsncpy_chk_warn (__dest, __src, __n, +- __bos (__dest) / sizeof (wchar_t)); ++ (__glibc_objsize (__dest) ++ / sizeof (wchar_t))); + } + return __wcsncpy_alias (__dest, __src, __n); + } +@@ -222,14 +228,15 @@ __fortify_function wchar_t * + __NTH (wcpncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src, + size_t __n)) + { +- if (__bos (__dest) != (size_t) -1) ++ if (__glibc_objsize (__dest) != (size_t) -1) + { + if (!__builtin_constant_p (__n)) + return __wcpncpy_chk (__dest, __src, __n, +- __bos (__dest) / sizeof (wchar_t)); +- if (__n > __bos (__dest) / sizeof (wchar_t)) ++ __glibc_objsize (__dest) / sizeof (wchar_t)); ++ if (__n > __glibc_objsize (__dest) / sizeof (wchar_t)) + return __wcpncpy_chk_warn (__dest, __src, __n, +- __bos (__dest) / sizeof (wchar_t)); ++ (__glibc_objsize (__dest) ++ / sizeof (wchar_t))); + } + return __wcpncpy_alias (__dest, __src, __n); + } +@@ -245,8 +252,9 @@ extern wchar_t *__REDIRECT_NTH (__wcscat_alias, + __fortify_function wchar_t * + __NTH (wcscat (wchar_t *__restrict __dest, const wchar_t *__restrict __src)) + { +- if (__bos (__dest) != (size_t) -1) +- return __wcscat_chk (__dest, __src, __bos (__dest) / sizeof (wchar_t)); ++ if (__glibc_objsize (__dest) != (size_t) -1) ++ return __wcscat_chk (__dest, __src, ++ __glibc_objsize (__dest) / sizeof (wchar_t)); + return __wcscat_alias (__dest, __src); + } + +@@ -263,9 +271,9 @@ __fortify_function wchar_t * + __NTH (wcsncat (wchar_t *__restrict __dest, const wchar_t *__restrict __src, + size_t __n)) + { +- if (__bos (__dest) != (size_t) -1) ++ if (__glibc_objsize (__dest) != (size_t) -1) + return __wcsncat_chk (__dest, __src, __n, +- __bos (__dest) / sizeof (wchar_t)); ++ __glibc_objsize (__dest) / sizeof (wchar_t)); + return __wcsncat_alias (__dest, __src, __n); + } + +@@ -285,18 +293,18 @@ __fortify_function int + __NTH (swprintf (wchar_t *__restrict __s, size_t __n, + const wchar_t *__restrict __fmt, ...)) + { +- if (__bos (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1) ++ if (__glibc_objsize (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1) + return __swprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, +- __bos (__s) / sizeof (wchar_t), ++ __glibc_objsize (__s) / sizeof (wchar_t), + __fmt, __va_arg_pack ()); + return __swprintf_alias (__s, __n, __fmt, __va_arg_pack ()); + } + #elif !defined __cplusplus + /* XXX We might want to have support in gcc for swprintf. */ + # define swprintf(s, n, ...) \ +- (__bos (s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1 \ ++ (__glibc_objsize (s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1 \ + ? __swprintf_chk (s, n, __USE_FORTIFY_LEVEL - 1, \ +- __bos (s) / sizeof (wchar_t), __VA_ARGS__) \ ++ __glibc_objsize (s) / sizeof (wchar_t), __VA_ARGS__) \ + : swprintf (s, n, __VA_ARGS__)) + #endif + +@@ -315,9 +323,10 @@ __fortify_function int + __NTH (vswprintf (wchar_t *__restrict __s, size_t __n, + const wchar_t *__restrict __fmt, __gnuc_va_list __ap)) + { +- if (__bos (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1) ++ if (__glibc_objsize (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1) + return __vswprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, +- __bos (__s) / sizeof (wchar_t), __fmt, __ap); ++ __glibc_objsize (__s) / sizeof (wchar_t), __fmt, ++ __ap); + return __vswprintf_alias (__s, __n, __fmt, __ap); + } + +@@ -383,14 +392,15 @@ extern wchar_t *__REDIRECT (__fgetws_chk_warn, + __fortify_function __wur wchar_t * + fgetws (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream) + { +- if (__bos (__s) != (size_t) -1) ++ if (__glibc_objsize (__s) != (size_t) -1) + { + if (!__builtin_constant_p (__n) || __n <= 0) +- return __fgetws_chk (__s, __bos (__s) / sizeof (wchar_t), ++ return __fgetws_chk (__s, __glibc_objsize (__s) / sizeof (wchar_t), + __n, __stream); + +- if ((size_t) __n > __bos (__s) / sizeof (wchar_t)) +- return __fgetws_chk_warn (__s, __bos (__s) / sizeof (wchar_t), ++ if ((size_t) __n > __glibc_objsize (__s) / sizeof (wchar_t)) ++ return __fgetws_chk_warn (__s, ++ __glibc_objsize (__s) / sizeof (wchar_t), + __n, __stream); + } + return __fgetws_alias (__s, __n, __stream); +@@ -414,14 +424,17 @@ extern wchar_t *__REDIRECT (__fgetws_unlocked_chk_warn, + __fortify_function __wur wchar_t * + fgetws_unlocked (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream) + { +- if (__bos (__s) != (size_t) -1) ++ if (__glibc_objsize (__s) != (size_t) -1) + { + if (!__builtin_constant_p (__n) || __n <= 0) +- return __fgetws_unlocked_chk (__s, __bos (__s) / sizeof (wchar_t), ++ return __fgetws_unlocked_chk (__s, ++ __glibc_objsize (__s) / sizeof (wchar_t), + __n, __stream); + +- if ((size_t) __n > __bos (__s) / sizeof (wchar_t)) +- return __fgetws_unlocked_chk_warn (__s, __bos (__s) / sizeof (wchar_t), ++ if ((size_t) __n > __glibc_objsize (__s) / sizeof (wchar_t)) ++ return __fgetws_unlocked_chk_warn (__s, ++ (__glibc_objsize (__s) ++ / sizeof (wchar_t)), + __n, __stream); + } + return __fgetws_unlocked_alias (__s, __n, __stream); +@@ -447,8 +460,9 @@ __NTH (wcrtomb (char *__restrict __s, wchar_t __wchar, + #if defined MB_LEN_MAX && MB_LEN_MAX != __WCHAR_MB_LEN_MAX + # error "Assumed value of MB_LEN_MAX wrong" + #endif +- if (__bos (__s) != (size_t) -1 && __WCHAR_MB_LEN_MAX > __bos (__s)) +- return __wcrtomb_chk (__s, __wchar, __ps, __bos (__s)); ++ if (__glibc_objsize (__s) != (size_t) -1 ++ && __WCHAR_MB_LEN_MAX > __glibc_objsize (__s)) ++ return __wcrtomb_chk (__s, __wchar, __ps, __glibc_objsize (__s)); + return __wcrtomb_alias (__s, __wchar, __ps); + } + +@@ -474,15 +488,16 @@ __fortify_function size_t + __NTH (mbsrtowcs (wchar_t *__restrict __dst, const char **__restrict __src, + size_t __len, mbstate_t *__restrict __ps)) + { +- if (__bos (__dst) != (size_t) -1) ++ if (__glibc_objsize (__dst) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) + return __mbsrtowcs_chk (__dst, __src, __len, __ps, +- __bos (__dst) / sizeof (wchar_t)); ++ __glibc_objsize (__dst) / sizeof (wchar_t)); + +- if (__len > __bos (__dst) / sizeof (wchar_t)) ++ if (__len > __glibc_objsize (__dst) / sizeof (wchar_t)) + return __mbsrtowcs_chk_warn (__dst, __src, __len, __ps, +- __bos (__dst) / sizeof (wchar_t)); ++ (__glibc_objsize (__dst) ++ / sizeof (wchar_t))); + } + return __mbsrtowcs_alias (__dst, __src, __len, __ps); + } +@@ -508,13 +523,15 @@ __fortify_function size_t + __NTH (wcsrtombs (char *__restrict __dst, const wchar_t **__restrict __src, + size_t __len, mbstate_t *__restrict __ps)) + { +- if (__bos (__dst) != (size_t) -1) ++ if (__glibc_objsize (__dst) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) +- return __wcsrtombs_chk (__dst, __src, __len, __ps, __bos (__dst)); ++ return __wcsrtombs_chk (__dst, __src, __len, __ps, ++ __glibc_objsize (__dst)); + +- if (__len > __bos (__dst)) +- return __wcsrtombs_chk_warn (__dst, __src, __len, __ps, __bos (__dst)); ++ if (__len > __glibc_objsize (__dst)) ++ return __wcsrtombs_chk_warn (__dst, __src, __len, __ps, ++ __glibc_objsize (__dst)); + } + return __wcsrtombs_alias (__dst, __src, __len, __ps); + } +@@ -542,15 +559,16 @@ __fortify_function size_t + __NTH (mbsnrtowcs (wchar_t *__restrict __dst, const char **__restrict __src, + size_t __nmc, size_t __len, mbstate_t *__restrict __ps)) + { +- if (__bos (__dst) != (size_t) -1) ++ if (__glibc_objsize (__dst) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) + return __mbsnrtowcs_chk (__dst, __src, __nmc, __len, __ps, +- __bos (__dst) / sizeof (wchar_t)); ++ __glibc_objsize (__dst) / sizeof (wchar_t)); + +- if (__len > __bos (__dst) / sizeof (wchar_t)) ++ if (__len > __glibc_objsize (__dst) / sizeof (wchar_t)) + return __mbsnrtowcs_chk_warn (__dst, __src, __nmc, __len, __ps, +- __bos (__dst) / sizeof (wchar_t)); ++ (__glibc_objsize (__dst) ++ / sizeof (wchar_t))); + } + return __mbsnrtowcs_alias (__dst, __src, __nmc, __len, __ps); + } +@@ -578,15 +596,15 @@ __fortify_function size_t + __NTH (wcsnrtombs (char *__restrict __dst, const wchar_t **__restrict __src, + size_t __nwc, size_t __len, mbstate_t *__restrict __ps)) + { +- if (__bos (__dst) != (size_t) -1) ++ if (__glibc_objsize (__dst) != (size_t) -1) + { + if (!__builtin_constant_p (__len)) + return __wcsnrtombs_chk (__dst, __src, __nwc, __len, __ps, +- __bos (__dst)); ++ __glibc_objsize (__dst)); + +- if (__len > __bos (__dst)) ++ if (__len > __glibc_objsize (__dst)) + return __wcsnrtombs_chk_warn (__dst, __src, __nwc, __len, __ps, +- __bos (__dst)); ++ __glibc_objsize (__dst)); + } + return __wcsnrtombs_alias (__dst, __src, __nwc, __len, __ps); + } diff --git a/glibc-rh2033684-6.patch b/glibc-rh2033684-6.patch new file mode 100644 index 0000000..b183d70 --- /dev/null +++ b/glibc-rh2033684-6.patch @@ -0,0 +1,1037 @@ +commit a643f60c53876be0d57b4b7373770e6cb356fd13 +Author: Siddhesh Poyarekar +Date: Wed Oct 20 18:12:41 2021 +0530 + + Make sure that the fortified function conditionals are constant + + In _FORTIFY_SOURCE=3, the size expression may be non-constant, + resulting in branches in the inline functions remaining intact and + causing a tiny overhead. Clang (and in future, gcc) make sure that + the -1 case is always safe, i.e. any comparison of the generated + expression with (size_t)-1 is always false so that bit is taken care + of. The rest is avoidable since we want the _chk variant whenever we + have a size expression and it's not -1. + + Rework the conditionals in a uniform way to clearly indicate two + conditions at compile time: + + - Either the size is unknown (-1) or we know at compile time that the + operation length is less than the object size. We can call the + original function in this case. It could be that either the length, + object size or both are non-constant, but the compiler, through + range analysis, is able to fold the *comparison* to a constant. + + - The size and length are known and the compiler can see at compile + time that operation length > object size. This is valid grounds for + a warning at compile time, followed by emitting the _chk variant. + + For everything else, emit the _chk variant. + + This simplifies most of the fortified function implementations and at + the same time, ensures that only one call from _chk or the regular + function is emitted. + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: Adhemerval Zanella + +diff --git a/io/bits/poll2.h b/io/bits/poll2.h +index f47fd9ad0945234f..6f4dae77e5e2d0d3 100644 +--- a/io/bits/poll2.h ++++ b/io/bits/poll2.h +@@ -35,16 +35,9 @@ extern int __REDIRECT (__poll_chk_warn, (struct pollfd *__fds, nfds_t __nfds, + __fortify_function int + poll (struct pollfd *__fds, nfds_t __nfds, int __timeout) + { +- if (__glibc_objsize (__fds) != (__SIZE_TYPE__) -1) +- { +- if (! __builtin_constant_p (__nfds)) +- return __poll_chk (__fds, __nfds, __timeout, __glibc_objsize (__fds)); +- else if (__glibc_objsize (__fds) / sizeof (*__fds) < __nfds) +- return __poll_chk_warn (__fds, __nfds, __timeout, +- __glibc_objsize (__fds)); +- } +- +- return __poll_alias (__fds, __nfds, __timeout); ++ return __glibc_fortify (poll, __nfds, sizeof (*__fds), ++ __glibc_objsize (__fds), ++ __fds, __nfds, __timeout); + } + + +@@ -66,17 +59,9 @@ __fortify_function int + ppoll (struct pollfd *__fds, nfds_t __nfds, const struct timespec *__timeout, + const __sigset_t *__ss) + { +- if (__glibc_objsize (__fds) != (__SIZE_TYPE__) -1) +- { +- if (! __builtin_constant_p (__nfds)) +- return __ppoll_chk (__fds, __nfds, __timeout, __ss, +- __glibc_objsize (__fds)); +- else if (__glibc_objsize (__fds) / sizeof (*__fds) < __nfds) +- return __ppoll_chk_warn (__fds, __nfds, __timeout, __ss, +- __glibc_objsize (__fds)); +- } +- +- return __ppoll_alias (__fds, __nfds, __timeout, __ss); ++ return __glibc_fortify (ppoll, __nfds, sizeof (*__fds), ++ __glibc_objsize (__fds), ++ __fds, __nfds, __timeout, __ss); + } + #endif + +diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h +index 2cd69f44cfadfc9f..4630fe0256b1a562 100644 +--- a/libio/bits/stdio2.h ++++ b/libio/bits/stdio2.h +@@ -256,15 +256,12 @@ extern char *__REDIRECT (__fgets_chk_warn, + __fortify_function __wur char * + fgets (char *__restrict __s, int __n, FILE *__restrict __stream) + { +- if (__glibc_objsize (__s) != (size_t) -1) +- { +- if (!__builtin_constant_p (__n) || __n <= 0) +- return __fgets_chk (__s, __glibc_objsize (__s), __n, __stream); +- +- if ((size_t) __n > __glibc_objsize (__s)) +- return __fgets_chk_warn (__s, __glibc_objsize (__s), __n, __stream); +- } +- return __fgets_alias (__s, __n, __stream); ++ size_t sz = __glibc_objsize (__s); ++ if (__glibc_safe_or_unknown_len (__n, sizeof (char), sz)) ++ return __fgets_alias (__s, __n, __stream); ++ if (__glibc_unsafe_len (__n, sizeof (char), sz)) ++ return __fgets_chk_warn (__s, sz, __n, __stream); ++ return __fgets_chk (__s, sz, __n, __stream); + } + + extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen, +@@ -286,19 +283,12 @@ __fortify_function __wur size_t + fread (void *__restrict __ptr, size_t __size, size_t __n, + FILE *__restrict __stream) + { +- if (__glibc_objsize0 (__ptr) != (size_t) -1) +- { +- if (!__builtin_constant_p (__size) +- || !__builtin_constant_p (__n) +- || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2))) +- return __fread_chk (__ptr, __glibc_objsize0 (__ptr), __size, __n, +- __stream); +- +- if (__size * __n > __glibc_objsize0 (__ptr)) +- return __fread_chk_warn (__ptr, __glibc_objsize0 (__ptr), __size, __n, +- __stream); +- } +- return __fread_alias (__ptr, __size, __n, __stream); ++ size_t sz = __glibc_objsize0 (__ptr); ++ if (__glibc_safe_or_unknown_len (__n, __size, sz)) ++ return __fread_alias (__ptr, __size, __n, __stream); ++ if (__glibc_unsafe_len (__n, __size, sz)) ++ return __fread_chk_warn (__ptr, sz, __size, __n, __stream); ++ return __fread_chk (__ptr, sz, __size, __n, __stream); + } + + #ifdef __USE_GNU +@@ -316,17 +306,12 @@ extern char *__REDIRECT (__fgets_unlocked_chk_warn, + __fortify_function __wur char * + fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream) + { +- if (__glibc_objsize (__s) != (size_t) -1) +- { +- if (!__builtin_constant_p (__n) || __n <= 0) +- return __fgets_unlocked_chk (__s, __glibc_objsize (__s), __n, +- __stream); +- +- if ((size_t) __n > __glibc_objsize (__s)) +- return __fgets_unlocked_chk_warn (__s, __glibc_objsize (__s), __n, +- __stream); +- } +- return __fgets_unlocked_alias (__s, __n, __stream); ++ size_t sz = __glibc_objsize (__s); ++ if (__glibc_safe_or_unknown_len (__n, sizeof (char), sz)) ++ return __fgets_unlocked_alias (__s, __n, __stream); ++ if (__glibc_unsafe_len (__n, sizeof (char), sz)) ++ return __fgets_unlocked_chk_warn (__s, sz, __n, __stream); ++ return __fgets_unlocked_chk (__s, sz, __n, __stream); + } + #endif + +@@ -351,41 +336,36 @@ __fortify_function __wur size_t + fread_unlocked (void *__restrict __ptr, size_t __size, size_t __n, + FILE *__restrict __stream) + { +- if (__glibc_objsize0 (__ptr) != (size_t) -1) ++ size_t sz = __glibc_objsize0 (__ptr); ++ if (__glibc_safe_or_unknown_len (__n, __size, sz)) + { +- if (!__builtin_constant_p (__size) +- || !__builtin_constant_p (__n) +- || (__size | __n) >= (((size_t) 1) << (8 * sizeof (size_t) / 2))) +- return __fread_unlocked_chk (__ptr, __glibc_objsize0 (__ptr), __size, +- __n, __stream); +- +- if (__size * __n > __glibc_objsize0 (__ptr)) +- return __fread_unlocked_chk_warn (__ptr, __glibc_objsize0 (__ptr), +- __size, __n, __stream); +- } +- + # ifdef __USE_EXTERN_INLINES +- if (__builtin_constant_p (__size) +- && __builtin_constant_p (__n) +- && (__size | __n) < (((size_t) 1) << (8 * sizeof (size_t) / 2)) +- && __size * __n <= 8) +- { +- size_t __cnt = __size * __n; +- char *__cptr = (char *) __ptr; +- if (__cnt == 0) +- return 0; +- +- for (; __cnt > 0; --__cnt) ++ if (__builtin_constant_p (__size) ++ && __builtin_constant_p (__n) ++ && (__size | __n) < (((size_t) 1) << (8 * sizeof (size_t) / 2)) ++ && __size * __n <= 8) + { +- int __c = getc_unlocked (__stream); +- if (__c == EOF) +- break; +- *__cptr++ = __c; ++ size_t __cnt = __size * __n; ++ char *__cptr = (char *) __ptr; ++ if (__cnt == 0) ++ return 0; ++ ++ for (; __cnt > 0; --__cnt) ++ { ++ int __c = getc_unlocked (__stream); ++ if (__c == EOF) ++ break; ++ *__cptr++ = __c; ++ } ++ return (__cptr - (char *) __ptr) / __size; + } +- return (__cptr - (char *) __ptr) / __size; +- } + # endif +- return __fread_unlocked_alias (__ptr, __size, __n, __stream); ++ return __fread_unlocked_alias (__ptr, __size, __n, __stream); ++ } ++ if (__glibc_unsafe_len (__n, __size, sz)) ++ return __fread_unlocked_chk_warn (__ptr, sz, __size, __n, __stream); ++ return __fread_unlocked_chk (__ptr, sz, __size, __n, __stream); ++ + } + #endif + +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index 1e39307b0ebcf38f..17b84a2e6c69d961 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -132,6 +132,53 @@ + # define __glibc_objsize(__o) __bos (__o) + #endif + ++/* Compile time conditions to choose between the regular, _chk and _chk_warn ++ variants. These conditions should get evaluated to constant and optimized ++ away. */ ++ ++#define __glibc_safe_len_cond(__l, __s, __osz) ((__l) <= (__osz) / (__s)) ++#define __glibc_unsigned_or_positive(__l) \ ++ ((__typeof (__l)) 0 < (__typeof (__l)) -1 \ ++ || (__builtin_constant_p (__l) && (__l) > 0)) ++ ++/* Length is known to be safe at compile time if the __L * __S <= __OBJSZ ++ condition can be folded to a constant and if it is true. The -1 check is ++ redundant because since it implies that __glibc_safe_len_cond is true. */ ++#define __glibc_safe_or_unknown_len(__l, __s, __osz) \ ++ (__glibc_unsigned_or_positive (__l) \ ++ && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ ++ __s, __osz)) \ ++ && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz)) ++ ++/* Conversely, we know at compile time that the length is safe if the ++ __L * __S <= __OBJSZ condition can be folded to a constant and if it is ++ false. */ ++#define __glibc_unsafe_len(__l, __s, __osz) \ ++ (__glibc_unsigned_or_positive (__l) \ ++ && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ ++ __s, __osz)) \ ++ && !__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz)) ++ ++/* Fortify function f. __f_alias, __f_chk and __f_chk_warn must be ++ declared. */ ++ ++#define __glibc_fortify(f, __l, __s, __osz, ...) \ ++ (__glibc_safe_or_unknown_len (__l, __s, __osz) \ ++ ? __ ## f ## _alias (__VA_ARGS__) \ ++ : (__glibc_unsafe_len (__l, __s, __osz) \ ++ ? __ ## f ## _chk_warn (__VA_ARGS__, __osz) \ ++ : __ ## f ## _chk (__VA_ARGS__, __osz))) \ ++ ++/* Fortify function f, where object size argument passed to f is the number of ++ elements and not total size. */ ++ ++#define __glibc_fortify_n(f, __l, __s, __osz, ...) \ ++ (__glibc_safe_or_unknown_len (__l, __s, __osz) \ ++ ? __ ## f ## _alias (__VA_ARGS__) \ ++ : (__glibc_unsafe_len (__l, __s, __osz) \ ++ ? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s)) \ ++ : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s)))) \ ++ + #if __GNUC_PREREQ (4,3) + # define __warndecl(name, msg) \ + extern void name (void) __attribute__((__warning__ (msg))) +diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h +index a0c4dcfe9c61a7b8..a456d1723547db70 100644 +--- a/posix/bits/unistd.h ++++ b/posix/bits/unistd.h +@@ -33,16 +33,9 @@ extern ssize_t __REDIRECT (__read_chk_warn, + __fortify_function __wur ssize_t + read (int __fd, void *__buf, size_t __nbytes) + { +- if (__glibc_objsize0 (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__nbytes)) +- return __read_chk (__fd, __buf, __nbytes, __glibc_objsize0 (__buf)); +- +- if (__nbytes > __glibc_objsize0 (__buf)) +- return __read_chk_warn (__fd, __buf, __nbytes, +- __glibc_objsize0 (__buf)); +- } +- return __read_alias (__fd, __buf, __nbytes); ++ return __glibc_fortify (read, __nbytes, sizeof (char), ++ __glibc_objsize0 (__buf), ++ __fd, __buf, __nbytes); + } + + #ifdef __USE_UNIX98 +@@ -72,34 +65,17 @@ extern ssize_t __REDIRECT (__pread64_chk_warn, + __fortify_function __wur ssize_t + pread (int __fd, void *__buf, size_t __nbytes, __off_t __offset) + { +- if (__glibc_objsize0 (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__nbytes)) +- return __pread_chk (__fd, __buf, __nbytes, __offset, +- __glibc_objsize0 (__buf)); +- +- if ( __nbytes > __glibc_objsize0 (__buf)) +- return __pread_chk_warn (__fd, __buf, __nbytes, __offset, +- __glibc_objsize0 (__buf)); +- } +- return __pread_alias (__fd, __buf, __nbytes, __offset); ++ return __glibc_fortify (pread, __nbytes, sizeof (char), ++ __glibc_objsize0 (__buf), ++ __fd, __buf, __nbytes, __offset); + } + # else + __fortify_function __wur ssize_t + pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset) + { +- if (__glibc_objsize0 (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__nbytes)) +- return __pread64_chk (__fd, __buf, __nbytes, __offset, +- __glibc_objsize0 (__buf)); +- +- if ( __nbytes > __glibc_objsize0 (__buf)) +- return __pread64_chk_warn (__fd, __buf, __nbytes, __offset, +- __glibc_objsize0 (__buf)); +- } +- +- return __pread64_alias (__fd, __buf, __nbytes, __offset); ++ return __glibc_fortify (pread64, __nbytes, sizeof (char), ++ __glibc_objsize0 (__buf), ++ __fd, __buf, __nbytes, __offset); + } + # endif + +@@ -107,18 +83,9 @@ pread (int __fd, void *__buf, size_t __nbytes, __off64_t __offset) + __fortify_function __wur ssize_t + pread64 (int __fd, void *__buf, size_t __nbytes, __off64_t __offset) + { +- if (__glibc_objsize0 (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__nbytes)) +- return __pread64_chk (__fd, __buf, __nbytes, __offset, +- __glibc_objsize0 (__buf)); +- +- if ( __nbytes > __glibc_objsize0 (__buf)) +- return __pread64_chk_warn (__fd, __buf, __nbytes, __offset, +- __glibc_objsize0 (__buf)); +- } +- +- return __pread64_alias (__fd, __buf, __nbytes, __offset); ++ return __glibc_fortify (pread64, __nbytes, sizeof (char), ++ __glibc_objsize0 (__buf), ++ __fd, __buf, __nbytes, __offset); + } + # endif + #endif +@@ -143,16 +110,9 @@ __fortify_function __nonnull ((1, 2)) __wur ssize_t + __NTH (readlink (const char *__restrict __path, char *__restrict __buf, + size_t __len)) + { +- if (__glibc_objsize (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__len)) +- return __readlink_chk (__path, __buf, __len, __glibc_objsize (__buf)); +- +- if ( __len > __glibc_objsize (__buf)) +- return __readlink_chk_warn (__path, __buf, __len, +- __glibc_objsize (__buf)); +- } +- return __readlink_alias (__path, __buf, __len); ++ return __glibc_fortify (readlink, __len, sizeof (char), ++ __glibc_objsize (__buf), ++ __path, __buf, __len); + } + #endif + +@@ -178,17 +138,9 @@ __fortify_function __nonnull ((2, 3)) __wur ssize_t + __NTH (readlinkat (int __fd, const char *__restrict __path, + char *__restrict __buf, size_t __len)) + { +- if (__glibc_objsize (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__len)) +- return __readlinkat_chk (__fd, __path, __buf, __len, +- __glibc_objsize (__buf)); +- +- if (__len > __glibc_objsize (__buf)) +- return __readlinkat_chk_warn (__fd, __path, __buf, __len, +- __glibc_objsize (__buf)); +- } +- return __readlinkat_alias (__fd, __path, __buf, __len); ++ return __glibc_fortify (readlinkat, __len, sizeof (char), ++ __glibc_objsize (__buf), ++ __fd, __path, __buf, __len); + } + #endif + +@@ -205,15 +157,9 @@ extern char *__REDIRECT_NTH (__getcwd_chk_warn, + __fortify_function __wur char * + __NTH (getcwd (char *__buf, size_t __size)) + { +- if (__glibc_objsize (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__size)) +- return __getcwd_chk (__buf, __size, __glibc_objsize (__buf)); +- +- if (__size > __glibc_objsize (__buf)) +- return __getcwd_chk_warn (__buf, __size, __glibc_objsize (__buf)); +- } +- return __getcwd_alias (__buf, __size); ++ return __glibc_fortify (getcwd, __size, sizeof (char), ++ __glibc_objsize (__buf), ++ __buf, __size); + } + + #if defined __USE_MISC || defined __USE_XOPEN_EXTENDED +@@ -245,16 +191,9 @@ extern size_t __REDIRECT_NTH (__confstr_chk_warn, + __fortify_function size_t + __NTH (confstr (int __name, char *__buf, size_t __len)) + { +- if (__glibc_objsize (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__len)) +- return __confstr_chk (__name, __buf, __len, __glibc_objsize (__buf)); +- +- if (__glibc_objsize (__buf) < __len) +- return __confstr_chk_warn (__name, __buf, __len, +- __glibc_objsize (__buf)); +- } +- return __confstr_alias (__name, __buf, __len); ++ return __glibc_fortify (confstr, __len, sizeof (char), ++ __glibc_objsize (__buf), ++ __name, __buf, __len); + } + + +@@ -271,15 +210,9 @@ extern int __REDIRECT_NTH (__getgroups_chk_warn, + __fortify_function int + __NTH (getgroups (int __size, __gid_t __list[])) + { +- if (__glibc_objsize (__list) != (size_t) -1) +- { +- if (!__builtin_constant_p (__size) || __size < 0) +- return __getgroups_chk (__size, __list, __glibc_objsize (__list)); +- +- if (__size * sizeof (__gid_t) > __glibc_objsize (__list)) +- return __getgroups_chk_warn (__size, __list, __glibc_objsize (__list)); +- } +- return __getgroups_alias (__size, __list); ++ return __glibc_fortify (getgroups, __size, sizeof (__gid_t), ++ __glibc_objsize (__list), ++ __size, __list); + } + + +@@ -297,17 +230,9 @@ extern int __REDIRECT_NTH (__ttyname_r_chk_warn, + __fortify_function int + __NTH (ttyname_r (int __fd, char *__buf, size_t __buflen)) + { +- if (__glibc_objsize (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__buflen)) +- return __ttyname_r_chk (__fd, __buf, __buflen, +- __glibc_objsize (__buf)); +- +- if (__buflen > __glibc_objsize (__buf)) +- return __ttyname_r_chk_warn (__fd, __buf, __buflen, +- __glibc_objsize (__buf)); +- } +- return __ttyname_r_alias (__fd, __buf, __buflen); ++ return __glibc_fortify (ttyname_r, __buflen, sizeof (char), ++ __glibc_objsize (__buf), ++ __fd, __buf, __buflen); + } + + +@@ -325,16 +250,9 @@ extern int __REDIRECT (__getlogin_r_chk_warn, + __fortify_function int + getlogin_r (char *__buf, size_t __buflen) + { +- if (__glibc_objsize (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__buflen)) +- return __getlogin_r_chk (__buf, __buflen, __glibc_objsize (__buf)); +- +- if (__buflen > __glibc_objsize (__buf)) +- return __getlogin_r_chk_warn (__buf, __buflen, +- __glibc_objsize (__buf)); +- } +- return __getlogin_r_alias (__buf, __buflen); ++ return __glibc_fortify (getlogin_r, __buflen, sizeof (char), ++ __glibc_objsize (__buf), ++ __buf, __buflen); + } + #endif + +@@ -353,16 +271,9 @@ extern int __REDIRECT_NTH (__gethostname_chk_warn, + __fortify_function int + __NTH (gethostname (char *__buf, size_t __buflen)) + { +- if (__glibc_objsize (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__buflen)) +- return __gethostname_chk (__buf, __buflen, __glibc_objsize (__buf)); +- +- if (__buflen > __glibc_objsize (__buf)) +- return __gethostname_chk_warn (__buf, __buflen, +- __glibc_objsize (__buf)); +- } +- return __gethostname_alias (__buf, __buflen); ++ return __glibc_fortify (gethostname, __buflen, sizeof (char), ++ __glibc_objsize (__buf), ++ __buf, __buflen); + } + #endif + +@@ -383,15 +294,8 @@ extern int __REDIRECT_NTH (__getdomainname_chk_warn, + __fortify_function int + __NTH (getdomainname (char *__buf, size_t __buflen)) + { +- if (__glibc_objsize (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__buflen)) +- return __getdomainname_chk (__buf, __buflen, __glibc_objsize (__buf)); +- +- if (__buflen > __glibc_objsize (__buf)) +- return __getdomainname_chk_warn (__buf, __buflen, +- __glibc_objsize (__buf)); +- } +- return __getdomainname_alias (__buf, __buflen); ++ return __glibc_fortify (getdomainname, __buflen, sizeof (char), ++ __glibc_objsize (__buf), ++ __buf, __buflen); + } + #endif +diff --git a/socket/bits/socket2.h b/socket/bits/socket2.h +index 729e5a4cc1f4cb92..68fe5435b3b29c2a 100644 +--- a/socket/bits/socket2.h ++++ b/socket/bits/socket2.h +@@ -33,17 +33,12 @@ extern ssize_t __REDIRECT (__recv_chk_warn, + __fortify_function ssize_t + recv (int __fd, void *__buf, size_t __n, int __flags) + { +- if (__glibc_objsize0 (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__n)) +- return __recv_chk (__fd, __buf, __n, __glibc_objsize0 (__buf), +- __flags); +- +- if (__n > __glibc_objsize0 (__buf)) +- return __recv_chk_warn (__fd, __buf, __n, __glibc_objsize0 (__buf), +- __flags); +- } +- return __recv_alias (__fd, __buf, __n, __flags); ++ size_t sz = __glibc_objsize0 (__buf); ++ if (__glibc_safe_or_unknown_len (__n, sizeof (char), sz)) ++ return __recv_alias (__fd, __buf, __n, __flags); ++ if (__glibc_unsafe_len (__n, sizeof (char), sz)) ++ return __recv_chk_warn (__fd, __buf, __n, sz, __flags); ++ return __recv_chk (__fd, __buf, __n, sz, __flags); + } + + extern ssize_t __recvfrom_chk (int __fd, void *__restrict __buf, size_t __n, +@@ -66,14 +61,11 @@ __fortify_function ssize_t + recvfrom (int __fd, void *__restrict __buf, size_t __n, int __flags, + __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len) + { +- if (__glibc_objsize0 (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__n)) +- return __recvfrom_chk (__fd, __buf, __n, __glibc_objsize0 (__buf), +- __flags, __addr, __addr_len); +- if (__n > __glibc_objsize0 (__buf)) +- return __recvfrom_chk_warn (__fd, __buf, __n, __glibc_objsize0 (__buf), +- __flags, __addr, __addr_len); +- } +- return __recvfrom_alias (__fd, __buf, __n, __flags, __addr, __addr_len); ++ size_t sz = __glibc_objsize0 (__buf); ++ if (__glibc_safe_or_unknown_len (__n, sizeof (char), sz)) ++ return __recvfrom_alias (__fd, __buf, __n, __flags, __addr, __addr_len); ++ if (__glibc_unsafe_len (__n, sizeof (char), sz)) ++ return __recvfrom_chk_warn (__fd, __buf, __n, sz, __flags, __addr, ++ __addr_len); ++ return __recvfrom_chk (__fd, __buf, __n, sz, __flags, __addr, __addr_len); + } +diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h +index 5e4114ded33f2033..7ea364a276497720 100644 +--- a/stdlib/bits/stdlib.h ++++ b/stdlib/bits/stdlib.h +@@ -36,17 +36,16 @@ extern char *__REDIRECT_NTH (__realpath_chk_warn, + __fortify_function __wur char * + __NTH (realpath (const char *__restrict __name, char *__restrict __resolved)) + { +- if (__glibc_objsize (__resolved) != (size_t) -1) +- { ++ size_t sz = __glibc_objsize (__resolved); ++ ++ if (sz == (size_t) -1) ++ return __realpath_alias (__name, __resolved); ++ + #if defined _LIBC_LIMITS_H_ && defined PATH_MAX +- if (__glibc_objsize (__resolved) < PATH_MAX) +- return __realpath_chk_warn (__name, __resolved, +- __glibc_objsize (__resolved)); ++ if (__glibc_unsafe_len (sz, sizeof (char), PATH_MAX)) ++ return __realpath_chk_warn (__name, __resolved, sz); + #endif +- return __realpath_chk (__name, __resolved, __glibc_objsize (__resolved)); +- } +- +- return __realpath_alias (__name, __resolved); ++ return __realpath_chk (__name, __resolved, sz); + } + + +@@ -64,16 +63,9 @@ extern int __REDIRECT_NTH (__ptsname_r_chk_warn, + __fortify_function int + __NTH (ptsname_r (int __fd, char *__buf, size_t __buflen)) + { +- if (__glibc_objsize (__buf) != (size_t) -1) +- { +- if (!__builtin_constant_p (__buflen)) +- return __ptsname_r_chk (__fd, __buf, __buflen, +- __glibc_objsize (__buf)); +- if (__buflen > __glibc_objsize (__buf)) +- return __ptsname_r_chk_warn (__fd, __buf, __buflen, +- __glibc_objsize (__buf)); +- } +- return __ptsname_r_alias (__fd, __buf, __buflen); ++ return __glibc_fortify (ptsname_r, __buflen, sizeof (char), ++ __glibc_objsize (__buf), ++ __fd, __buf, __buflen); + } + + +@@ -117,18 +109,9 @@ __fortify_function size_t + __NTH (mbstowcs (wchar_t *__restrict __dst, const char *__restrict __src, + size_t __len)) + { +- if (__glibc_objsize (__dst) != (size_t) -1) +- { +- if (!__builtin_constant_p (__len)) +- return __mbstowcs_chk (__dst, __src, __len, +- __glibc_objsize (__dst) / sizeof (wchar_t)); +- +- if (__len > __glibc_objsize (__dst) / sizeof (wchar_t)) +- return __mbstowcs_chk_warn (__dst, __src, __len, +- (__glibc_objsize (__dst) +- / sizeof (wchar_t))); +- } +- return __mbstowcs_alias (__dst, __src, __len); ++ return __glibc_fortify_n (mbstowcs, __len, sizeof (wchar_t), ++ __glibc_objsize (__dst), ++ __dst, __src, __len); + } + + +@@ -149,13 +132,7 @@ __fortify_function size_t + __NTH (wcstombs (char *__restrict __dst, const wchar_t *__restrict __src, + size_t __len)) + { +- if (__glibc_objsize (__dst) != (size_t) -1) +- { +- if (!__builtin_constant_p (__len)) +- return __wcstombs_chk (__dst, __src, __len, __glibc_objsize (__dst)); +- if (__len > __glibc_objsize (__dst)) +- return __wcstombs_chk_warn (__dst, __src, __len, +- __glibc_objsize (__dst)); +- } +- return __wcstombs_alias (__dst, __src, __len); ++ return __glibc_fortify (wcstombs, __len, sizeof (char), ++ __glibc_objsize (__dst), ++ __dst, __src, __len); + } +diff --git a/wcsmbs/bits/wchar2.h b/wcsmbs/bits/wchar2.h +index 838ba877ee4b4afe..f82bba481981e4fb 100644 +--- a/wcsmbs/bits/wchar2.h ++++ b/wcsmbs/bits/wchar2.h +@@ -39,17 +39,9 @@ __fortify_function wchar_t * + __NTH (wmemcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2, + size_t __n)) + { +- if (__glibc_objsize0 (__s1) != (size_t) -1) +- { +- if (!__builtin_constant_p (__n)) +- return __wmemcpy_chk (__s1, __s2, __n, +- __glibc_objsize0 (__s1) / sizeof (wchar_t)); +- +- if (__n > __glibc_objsize0 (__s1) / sizeof (wchar_t)) +- return __wmemcpy_chk_warn (__s1, __s2, __n, +- __glibc_objsize0 (__s1) / sizeof (wchar_t)); +- } +- return __wmemcpy_alias (__s1, __s2, __n); ++ return __glibc_fortify_n (wmemcpy, __n, sizeof (wchar_t), ++ __glibc_objsize0 (__s1), ++ __s1, __s2, __n); + } + + +@@ -67,18 +59,9 @@ extern wchar_t *__REDIRECT_NTH (__wmemmove_chk_warn, + __fortify_function wchar_t * + __NTH (wmemmove (wchar_t *__s1, const wchar_t *__s2, size_t __n)) + { +- if (__glibc_objsize0 (__s1) != (size_t) -1) +- { +- if (!__builtin_constant_p (__n)) +- return __wmemmove_chk (__s1, __s2, __n, +- __glibc_objsize0 (__s1) / sizeof (wchar_t)); +- +- if (__n > __glibc_objsize0 (__s1) / sizeof (wchar_t)) +- return __wmemmove_chk_warn (__s1, __s2, __n, +- (__glibc_objsize0 (__s1) +- / sizeof (wchar_t))); +- } +- return __wmemmove_alias (__s1, __s2, __n); ++ return __glibc_fortify_n (wmemmove, __n, sizeof (wchar_t), ++ __glibc_objsize0 (__s1), ++ __s1, __s2, __n); + } + + +@@ -101,18 +84,9 @@ __fortify_function wchar_t * + __NTH (wmempcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2, + size_t __n)) + { +- if (__glibc_objsize0 (__s1) != (size_t) -1) +- { +- if (!__builtin_constant_p (__n)) +- return __wmempcpy_chk (__s1, __s2, __n, +- __glibc_objsize0 (__s1) / sizeof (wchar_t)); +- +- if (__n > __glibc_objsize0 (__s1) / sizeof (wchar_t)) +- return __wmempcpy_chk_warn (__s1, __s2, __n, +- (__glibc_objsize0 (__s1) +- / sizeof (wchar_t))); +- } +- return __wmempcpy_alias (__s1, __s2, __n); ++ return __glibc_fortify_n (wmempcpy, __n, sizeof (wchar_t), ++ __glibc_objsize0 (__s1), ++ __s1, __s2, __n); + } + #endif + +@@ -130,17 +104,9 @@ extern wchar_t *__REDIRECT_NTH (__wmemset_chk_warn, + __fortify_function wchar_t * + __NTH (wmemset (wchar_t *__s, wchar_t __c, size_t __n)) + { +- if (__glibc_objsize0 (__s) != (size_t) -1) +- { +- if (!__builtin_constant_p (__n)) +- return __wmemset_chk (__s, __c, __n, +- __glibc_objsize0 (__s) / sizeof (wchar_t)); +- +- if (__n > __glibc_objsize0 (__s) / sizeof (wchar_t)) +- return __wmemset_chk_warn (__s, __c, __n, +- __glibc_objsize0 (__s) / sizeof (wchar_t)); +- } +- return __wmemset_alias (__s, __c, __n); ++ return __glibc_fortify_n (wmemset, __n, sizeof (wchar_t), ++ __glibc_objsize0 (__s), ++ __s, __c, __n); + } + + +@@ -154,9 +120,9 @@ extern wchar_t *__REDIRECT_NTH (__wcscpy_alias, + __fortify_function wchar_t * + __NTH (wcscpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src)) + { +- if (__glibc_objsize (__dest) != (size_t) -1) +- return __wcscpy_chk (__dest, __src, +- __glibc_objsize (__dest) / sizeof (wchar_t)); ++ size_t sz = __glibc_objsize (__dest); ++ if (sz != (size_t) -1) ++ return __wcscpy_chk (__dest, __src, sz / sizeof (wchar_t)); + return __wcscpy_alias (__dest, __src); + } + +@@ -171,9 +137,9 @@ extern wchar_t *__REDIRECT_NTH (__wcpcpy_alias, + __fortify_function wchar_t * + __NTH (wcpcpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src)) + { +- if (__glibc_objsize (__dest) != (size_t) -1) +- return __wcpcpy_chk (__dest, __src, +- __glibc_objsize (__dest) / sizeof (wchar_t)); ++ size_t sz = __glibc_objsize (__dest); ++ if (sz != (size_t) -1) ++ return __wcpcpy_chk (__dest, __src, sz / sizeof (wchar_t)); + return __wcpcpy_alias (__dest, __src); + } + +@@ -196,17 +162,9 @@ __fortify_function wchar_t * + __NTH (wcsncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src, + size_t __n)) + { +- if (__glibc_objsize (__dest) != (size_t) -1) +- { +- if (!__builtin_constant_p (__n)) +- return __wcsncpy_chk (__dest, __src, __n, +- __glibc_objsize (__dest) / sizeof (wchar_t)); +- if (__n > __glibc_objsize (__dest) / sizeof (wchar_t)) +- return __wcsncpy_chk_warn (__dest, __src, __n, +- (__glibc_objsize (__dest) +- / sizeof (wchar_t))); +- } +- return __wcsncpy_alias (__dest, __src, __n); ++ return __glibc_fortify_n (wcsncpy, __n, sizeof (wchar_t), ++ __glibc_objsize (__dest), ++ __dest, __src, __n); + } + + +@@ -228,17 +186,9 @@ __fortify_function wchar_t * + __NTH (wcpncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src, + size_t __n)) + { +- if (__glibc_objsize (__dest) != (size_t) -1) +- { +- if (!__builtin_constant_p (__n)) +- return __wcpncpy_chk (__dest, __src, __n, +- __glibc_objsize (__dest) / sizeof (wchar_t)); +- if (__n > __glibc_objsize (__dest) / sizeof (wchar_t)) +- return __wcpncpy_chk_warn (__dest, __src, __n, +- (__glibc_objsize (__dest) +- / sizeof (wchar_t))); +- } +- return __wcpncpy_alias (__dest, __src, __n); ++ return __glibc_fortify_n (wcpncpy, __n, sizeof (wchar_t), ++ __glibc_objsize (__dest), ++ __dest, __src, __n); + } + + +@@ -252,9 +202,9 @@ extern wchar_t *__REDIRECT_NTH (__wcscat_alias, + __fortify_function wchar_t * + __NTH (wcscat (wchar_t *__restrict __dest, const wchar_t *__restrict __src)) + { +- if (__glibc_objsize (__dest) != (size_t) -1) +- return __wcscat_chk (__dest, __src, +- __glibc_objsize (__dest) / sizeof (wchar_t)); ++ size_t sz = __glibc_objsize (__dest); ++ if (sz != (size_t) -1) ++ return __wcscat_chk (__dest, __src, sz / sizeof (wchar_t)); + return __wcscat_alias (__dest, __src); + } + +@@ -271,9 +221,9 @@ __fortify_function wchar_t * + __NTH (wcsncat (wchar_t *__restrict __dest, const wchar_t *__restrict __src, + size_t __n)) + { +- if (__glibc_objsize (__dest) != (size_t) -1) +- return __wcsncat_chk (__dest, __src, __n, +- __glibc_objsize (__dest) / sizeof (wchar_t)); ++ size_t sz = __glibc_objsize (__dest); ++ if (sz != (size_t) -1) ++ return __wcsncat_chk (__dest, __src, __n, sz / sizeof (wchar_t)); + return __wcsncat_alias (__dest, __src, __n); + } + +@@ -293,10 +243,10 @@ __fortify_function int + __NTH (swprintf (wchar_t *__restrict __s, size_t __n, + const wchar_t *__restrict __fmt, ...)) + { +- if (__glibc_objsize (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1) ++ size_t sz = __glibc_objsize (__s); ++ if (sz != (size_t) -1 || __USE_FORTIFY_LEVEL > 1) + return __swprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, +- __glibc_objsize (__s) / sizeof (wchar_t), +- __fmt, __va_arg_pack ()); ++ sz / sizeof (wchar_t), __fmt, __va_arg_pack ()); + return __swprintf_alias (__s, __n, __fmt, __va_arg_pack ()); + } + #elif !defined __cplusplus +@@ -323,10 +273,10 @@ __fortify_function int + __NTH (vswprintf (wchar_t *__restrict __s, size_t __n, + const wchar_t *__restrict __fmt, __gnuc_va_list __ap)) + { +- if (__glibc_objsize (__s) != (size_t) -1 || __USE_FORTIFY_LEVEL > 1) ++ size_t sz = __glibc_objsize (__s); ++ if (sz != (size_t) -1 || __USE_FORTIFY_LEVEL > 1) + return __vswprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, +- __glibc_objsize (__s) / sizeof (wchar_t), __fmt, +- __ap); ++ sz / sizeof (wchar_t), __fmt, __ap); + return __vswprintf_alias (__s, __n, __fmt, __ap); + } + +@@ -392,18 +342,12 @@ extern wchar_t *__REDIRECT (__fgetws_chk_warn, + __fortify_function __wur wchar_t * + fgetws (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream) + { +- if (__glibc_objsize (__s) != (size_t) -1) +- { +- if (!__builtin_constant_p (__n) || __n <= 0) +- return __fgetws_chk (__s, __glibc_objsize (__s) / sizeof (wchar_t), +- __n, __stream); +- +- if ((size_t) __n > __glibc_objsize (__s) / sizeof (wchar_t)) +- return __fgetws_chk_warn (__s, +- __glibc_objsize (__s) / sizeof (wchar_t), +- __n, __stream); +- } +- return __fgetws_alias (__s, __n, __stream); ++ size_t sz = __glibc_objsize (__s); ++ if (__glibc_safe_or_unknown_len (__n, sizeof (wchar_t), sz)) ++ return __fgetws_alias (__s, __n, __stream); ++ if (__glibc_unsafe_len (__n, sizeof (wchar_t), sz)) ++ return __fgetws_chk_warn (__s, sz / sizeof (wchar_t), __n, __stream); ++ return __fgetws_chk (__s, sz / sizeof (wchar_t), __n, __stream); + } + + #ifdef __USE_GNU +@@ -424,20 +368,13 @@ extern wchar_t *__REDIRECT (__fgetws_unlocked_chk_warn, + __fortify_function __wur wchar_t * + fgetws_unlocked (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream) + { +- if (__glibc_objsize (__s) != (size_t) -1) +- { +- if (!__builtin_constant_p (__n) || __n <= 0) +- return __fgetws_unlocked_chk (__s, +- __glibc_objsize (__s) / sizeof (wchar_t), +- __n, __stream); +- +- if ((size_t) __n > __glibc_objsize (__s) / sizeof (wchar_t)) +- return __fgetws_unlocked_chk_warn (__s, +- (__glibc_objsize (__s) +- / sizeof (wchar_t)), +- __n, __stream); +- } +- return __fgetws_unlocked_alias (__s, __n, __stream); ++ size_t sz = __glibc_objsize (__s); ++ if (__glibc_safe_or_unknown_len (__n, sizeof (wchar_t), sz)) ++ return __fgetws_unlocked_alias (__s, __n, __stream); ++ if (__glibc_unsafe_len (__n, sizeof (wchar_t), sz)) ++ return __fgetws_unlocked_chk_warn (__s, sz / sizeof (wchar_t), __n, ++ __stream); ++ return __fgetws_unlocked_chk (__s, sz / sizeof (wchar_t), __n, __stream); + } + #endif + +@@ -488,18 +425,9 @@ __fortify_function size_t + __NTH (mbsrtowcs (wchar_t *__restrict __dst, const char **__restrict __src, + size_t __len, mbstate_t *__restrict __ps)) + { +- if (__glibc_objsize (__dst) != (size_t) -1) +- { +- if (!__builtin_constant_p (__len)) +- return __mbsrtowcs_chk (__dst, __src, __len, __ps, +- __glibc_objsize (__dst) / sizeof (wchar_t)); +- +- if (__len > __glibc_objsize (__dst) / sizeof (wchar_t)) +- return __mbsrtowcs_chk_warn (__dst, __src, __len, __ps, +- (__glibc_objsize (__dst) +- / sizeof (wchar_t))); +- } +- return __mbsrtowcs_alias (__dst, __src, __len, __ps); ++ return __glibc_fortify_n (mbsrtowcs, __len, sizeof (wchar_t), ++ __glibc_objsize (__dst), ++ __dst, __src, __len, __ps); + } + + +@@ -523,17 +451,9 @@ __fortify_function size_t + __NTH (wcsrtombs (char *__restrict __dst, const wchar_t **__restrict __src, + size_t __len, mbstate_t *__restrict __ps)) + { +- if (__glibc_objsize (__dst) != (size_t) -1) +- { +- if (!__builtin_constant_p (__len)) +- return __wcsrtombs_chk (__dst, __src, __len, __ps, +- __glibc_objsize (__dst)); +- +- if (__len > __glibc_objsize (__dst)) +- return __wcsrtombs_chk_warn (__dst, __src, __len, __ps, +- __glibc_objsize (__dst)); +- } +- return __wcsrtombs_alias (__dst, __src, __len, __ps); ++ return __glibc_fortify (wcsrtombs, __len, sizeof (char), ++ __glibc_objsize (__dst), ++ __dst, __src, __len, __ps); + } + + +@@ -559,18 +479,9 @@ __fortify_function size_t + __NTH (mbsnrtowcs (wchar_t *__restrict __dst, const char **__restrict __src, + size_t __nmc, size_t __len, mbstate_t *__restrict __ps)) + { +- if (__glibc_objsize (__dst) != (size_t) -1) +- { +- if (!__builtin_constant_p (__len)) +- return __mbsnrtowcs_chk (__dst, __src, __nmc, __len, __ps, +- __glibc_objsize (__dst) / sizeof (wchar_t)); +- +- if (__len > __glibc_objsize (__dst) / sizeof (wchar_t)) +- return __mbsnrtowcs_chk_warn (__dst, __src, __nmc, __len, __ps, +- (__glibc_objsize (__dst) +- / sizeof (wchar_t))); +- } +- return __mbsnrtowcs_alias (__dst, __src, __nmc, __len, __ps); ++ return __glibc_fortify_n (mbsnrtowcs, __len, sizeof (wchar_t), ++ __glibc_objsize (__dst), ++ __dst, __src, __nmc, __len, __ps); + } + + +@@ -596,16 +507,8 @@ __fortify_function size_t + __NTH (wcsnrtombs (char *__restrict __dst, const wchar_t **__restrict __src, + size_t __nwc, size_t __len, mbstate_t *__restrict __ps)) + { +- if (__glibc_objsize (__dst) != (size_t) -1) +- { +- if (!__builtin_constant_p (__len)) +- return __wcsnrtombs_chk (__dst, __src, __nwc, __len, __ps, +- __glibc_objsize (__dst)); +- +- if (__len > __glibc_objsize (__dst)) +- return __wcsnrtombs_chk_warn (__dst, __src, __nwc, __len, __ps, +- __glibc_objsize (__dst)); +- } +- return __wcsnrtombs_alias (__dst, __src, __nwc, __len, __ps); ++ return __glibc_fortify (wcsnrtombs, __len, sizeof (char), ++ __glibc_objsize (__dst), ++ __dst, __src, __nwc, __len, __ps); + } + #endif diff --git a/glibc-rh2033684-7.patch b/glibc-rh2033684-7.patch new file mode 100644 index 0000000..7cb18a6 --- /dev/null +++ b/glibc-rh2033684-7.patch @@ -0,0 +1,43 @@ +commit fadf75c370494da6a02274ebe79e45b2f22ebbd0 +Author: Florian Weimer +Date: Mon Feb 10 14:37:10 2020 +0100 + + debug: Add missing locale dependencies of fortify tests + + The missing dependencies result in failures like this if make check + is invoked with sufficient parallelism for the debug subdirectory: + + FAIL: debug/tst-chk2 + FAIL: debug/tst-chk3 + FAIL: debug/tst-chk4 + FAIL: debug/tst-chk5 + FAIL: debug/tst-chk6 + FAIL: debug/tst-lfschk1 + FAIL: debug/tst-lfschk2 + FAIL: debug/tst-lfschk3 + FAIL: debug/tst-lfschk4 + FAIL: debug/tst-lfschk5 + FAIL: debug/tst-lfschk6 + +diff --git a/debug/Makefile b/debug/Makefile +index 506cebc3c4ca19ff..5e45c9b41077f2fd 100644 +--- a/debug/Makefile ++++ b/debug/Makefile +@@ -188,6 +188,17 @@ LOCALES := de_DE.UTF-8 + include ../gen-locales.mk + + $(objpfx)tst-chk1.out: $(gen-locales) ++$(objpfx)tst-chk2.out: $(gen-locales) ++$(objpfx)tst-chk3.out: $(gen-locales) ++$(objpfx)tst-chk4.out: $(gen-locales) ++$(objpfx)tst-chk5.out: $(gen-locales) ++$(objpfx)tst-chk6.out: $(gen-locales) ++$(objpfx)tst-lfschk1.out: $(gen-locales) ++$(objpfx)tst-lfschk2.out: $(gen-locales) ++$(objpfx)tst-lfschk3.out: $(gen-locales) ++$(objpfx)tst-lfschk4.out: $(gen-locales) ++$(objpfx)tst-lfschk5.out: $(gen-locales) ++$(objpfx)tst-lfschk6.out: $(gen-locales) + endif + + sLIBdir := $(shell echo $(slibdir) | sed 's,lib\(\|64\)$$,\\\\$$LIB,') diff --git a/glibc-rh2033684-8.patch b/glibc-rh2033684-8.patch new file mode 100644 index 0000000..5b90b20 --- /dev/null +++ b/glibc-rh2033684-8.patch @@ -0,0 +1,357 @@ +commit ad6f2a010c2ce759936de4747f6e0d53991912f8 +Author: Siddhesh Poyarekar +Date: Wed Oct 20 18:13:05 2021 +0530 + + debug: Add tests for _FORTIFY_SOURCE=3 + + Add some testing coverage for _FORTIFY_SOURCE=3. + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: Adhemerval Zanella + +diff --git a/debug/Makefile b/debug/Makefile +index 5e45c9b41077f2fd..81361438fc3d2aa9 100644 +--- a/debug/Makefile ++++ b/debug/Makefile +@@ -120,6 +120,8 @@ CFLAGS-tst-chk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error + CFLAGS-tst-chk4.cc += -Wno-format -Wno-deprecated-declarations -Wno-error + CFLAGS-tst-chk5.cc += -Wno-format -Wno-deprecated-declarations -Wno-error + CFLAGS-tst-chk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error ++CFLAGS-tst-chk7.c += -Wno-format -Wno-deprecated-declarations -Wno-error ++CFLAGS-tst-chk8.cc += -Wno-format -Wno-deprecated-declarations -Wno-error + CFLAGS-tst-lfschk1.c += -Wno-format -Wno-deprecated-declarations -Wno-error + CFLAGS-tst-lfschk2.c += -Wno-format -Wno-deprecated-declarations -Wno-error + CFLAGS-tst-lfschk3.c += -Wno-format -Wno-deprecated-declarations -Wno-error +@@ -129,6 +131,7 @@ CFLAGS-tst-lfschk6.cc += -Wno-format -Wno-deprecated-declarations -Wno-error + LDLIBS-tst-chk4 = -lstdc++ + LDLIBS-tst-chk5 = -lstdc++ + LDLIBS-tst-chk6 = -lstdc++ ++LDLIBS-tst-chk8 = -lstdc++ + LDLIBS-tst-lfschk4 = -lstdc++ + LDLIBS-tst-lfschk5 = -lstdc++ + LDLIBS-tst-lfschk6 = -lstdc++ +@@ -150,16 +153,16 @@ CFLAGS-tst-ssp-1.c += -fstack-protector-all + + tests = backtrace-tst tst-longjmp_chk tst-chk1 tst-chk2 tst-chk3 \ + tst-lfschk1 tst-lfschk2 tst-lfschk3 test-strcpy_chk test-stpcpy_chk \ +- tst-chk4 tst-chk5 tst-chk6 tst-lfschk4 tst-lfschk5 tst-lfschk6 \ +- tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 tst-backtrace4 \ +- tst-backtrace5 tst-backtrace6 ++ tst-chk4 tst-chk5 tst-chk6 tst-chk7 tst-chk8 tst-lfschk4 tst-lfschk5 \ ++ tst-lfschk6 tst-longjmp_chk2 tst-backtrace2 tst-backtrace3 \ ++ tst-backtrace4 tst-backtrace5 tst-backtrace6 + + ifeq ($(have-ssp),yes) + tests += tst-ssp-1 + endif + + ifeq (,$(CXX)) +-tests-unsupported = tst-chk4 tst-chk5 tst-chk6 \ ++tests-unsupported = tst-chk4 tst-chk5 tst-chk6 tst-chk8 \ + tst-lfschk4 tst-lfschk5 tst-lfschk6 + endif + +@@ -193,6 +196,8 @@ $(objpfx)tst-chk3.out: $(gen-locales) + $(objpfx)tst-chk4.out: $(gen-locales) + $(objpfx)tst-chk5.out: $(gen-locales) + $(objpfx)tst-chk6.out: $(gen-locales) ++$(objpfx)tst-chk7.out: $(gen-locales) ++$(objpfx)tst-chk8.out: $(gen-locales) + $(objpfx)tst-lfschk1.out: $(gen-locales) + $(objpfx)tst-lfschk2.out: $(gen-locales) + $(objpfx)tst-lfschk3.out: $(gen-locales) +diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c +index ca2b524b2fa6404c..5e76081255316a93 100644 +--- a/debug/tst-chk1.c ++++ b/debug/tst-chk1.c +@@ -83,8 +83,14 @@ handler (int sig) + _exit (127); + } + ++#if __USE_FORTIFY_LEVEL == 3 ++volatile size_t buf_size = 10; ++#else + char buf[10]; + wchar_t wbuf[10]; ++#define buf_size sizeof (buf) ++#endif ++ + volatile size_t l0; + volatile char *p; + volatile wchar_t *wp; +@@ -123,6 +129,10 @@ int num2 = 987654; + static int + do_test (void) + { ++#if __USE_FORTIFY_LEVEL == 3 ++ char *buf = (char *) malloc (buf_size); ++ wchar_t *wbuf = (wchar_t *) malloc (buf_size * sizeof (wchar_t)); ++#endif + set_fortify_handler (handler); + + struct A { char buf1[9]; char buf2[1]; } a; +@@ -947,93 +957,93 @@ do_test (void) + + rewind (stdin); + +- if (fgets (buf, sizeof (buf), stdin) != buf ++ if (fgets (buf, buf_size, stdin) != buf + || memcmp (buf, "abcdefgh\n", 10)) + FAIL (); +- if (fgets (buf, sizeof (buf), stdin) != buf || memcmp (buf, "ABCDEFGHI", 10)) ++ if (fgets (buf, buf_size, stdin) != buf || memcmp (buf, "ABCDEFGHI", 10)) + FAIL (); + + rewind (stdin); + +- if (fgets (buf, l0 + sizeof (buf), stdin) != buf ++ if (fgets (buf, l0 + buf_size, stdin) != buf + || memcmp (buf, "abcdefgh\n", 10)) + FAIL (); + + #if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START +- if (fgets (buf, sizeof (buf) + 1, stdin) != buf) ++ if (fgets (buf, buf_size + 1, stdin) != buf) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START +- if (fgets (buf, l0 + sizeof (buf) + 1, stdin) != buf) ++ if (fgets (buf, l0 + buf_size + 1, stdin) != buf) + FAIL (); + CHK_FAIL_END + #endif + + rewind (stdin); + +- if (fgets_unlocked (buf, sizeof (buf), stdin) != buf ++ if (fgets_unlocked (buf, buf_size, stdin) != buf + || memcmp (buf, "abcdefgh\n", 10)) + FAIL (); +- if (fgets_unlocked (buf, sizeof (buf), stdin) != buf ++ if (fgets_unlocked (buf, buf_size, stdin) != buf + || memcmp (buf, "ABCDEFGHI", 10)) + FAIL (); + + rewind (stdin); + +- if (fgets_unlocked (buf, l0 + sizeof (buf), stdin) != buf ++ if (fgets_unlocked (buf, l0 + buf_size, stdin) != buf + || memcmp (buf, "abcdefgh\n", 10)) + FAIL (); + + #if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START +- if (fgets_unlocked (buf, sizeof (buf) + 1, stdin) != buf) ++ if (fgets_unlocked (buf, buf_size + 1, stdin) != buf) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START +- if (fgets_unlocked (buf, l0 + sizeof (buf) + 1, stdin) != buf) ++ if (fgets_unlocked (buf, l0 + buf_size + 1, stdin) != buf) + FAIL (); + CHK_FAIL_END + #endif + + rewind (stdin); + +- if (fread (buf, 1, sizeof (buf), stdin) != sizeof (buf) ++ if (fread (buf, 1, buf_size, stdin) != buf_size + || memcmp (buf, "abcdefgh\nA", 10)) + FAIL (); +- if (fread (buf, sizeof (buf), 1, stdin) != 1 ++ if (fread (buf, buf_size, 1, stdin) != 1 + || memcmp (buf, "BCDEFGHI\na", 10)) + FAIL (); + + rewind (stdin); + +- if (fread (buf, l0 + 1, sizeof (buf), stdin) != sizeof (buf) ++ if (fread (buf, l0 + 1, buf_size, stdin) != buf_size + || memcmp (buf, "abcdefgh\nA", 10)) + FAIL (); +- if (fread (buf, sizeof (buf), l0 + 1, stdin) != 1 ++ if (fread (buf, buf_size, l0 + 1, stdin) != 1 + || memcmp (buf, "BCDEFGHI\na", 10)) + FAIL (); + + #if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START +- if (fread (buf, 1, sizeof (buf) + 1, stdin) != sizeof (buf) + 1) ++ if (fread (buf, 1, buf_size + 1, stdin) != buf_size + 1) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START +- if (fread (buf, sizeof (buf) + 1, l0 + 1, stdin) != 1) ++ if (fread (buf, buf_size + 1, l0 + 1, stdin) != 1) + FAIL (); + CHK_FAIL_END + #endif + + rewind (stdin); + +- if (fread_unlocked (buf, 1, sizeof (buf), stdin) != sizeof (buf) ++ if (fread_unlocked (buf, 1, buf_size, stdin) != buf_size + || memcmp (buf, "abcdefgh\nA", 10)) + FAIL (); +- if (fread_unlocked (buf, sizeof (buf), 1, stdin) != 1 ++ if (fread_unlocked (buf, buf_size, 1, stdin) != 1 + || memcmp (buf, "BCDEFGHI\na", 10)) + FAIL (); + +@@ -1048,100 +1058,100 @@ do_test (void) + + rewind (stdin); + +- if (fread_unlocked (buf, l0 + 1, sizeof (buf), stdin) != sizeof (buf) ++ if (fread_unlocked (buf, l0 + 1, buf_size, stdin) != buf_size + || memcmp (buf, "abcdefgh\nA", 10)) + FAIL (); +- if (fread_unlocked (buf, sizeof (buf), l0 + 1, stdin) != 1 ++ if (fread_unlocked (buf, buf_size, l0 + 1, stdin) != 1 + || memcmp (buf, "BCDEFGHI\na", 10)) + FAIL (); + + #if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START +- if (fread_unlocked (buf, 1, sizeof (buf) + 1, stdin) != sizeof (buf) + 1) ++ if (fread_unlocked (buf, 1, buf_size + 1, stdin) != buf_size + 1) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START +- if (fread_unlocked (buf, sizeof (buf) + 1, l0 + 1, stdin) != 1) ++ if (fread_unlocked (buf, buf_size + 1, l0 + 1, stdin) != 1) + FAIL (); + CHK_FAIL_END + #endif + + lseek (fileno (stdin), 0, SEEK_SET); + +- if (read (fileno (stdin), buf, sizeof (buf) - 1) != sizeof (buf) - 1 ++ if (read (fileno (stdin), buf, buf_size - 1) != buf_size - 1 + || memcmp (buf, "abcdefgh\n", 9)) + FAIL (); +- if (read (fileno (stdin), buf, sizeof (buf) - 1) != sizeof (buf) - 1 ++ if (read (fileno (stdin), buf, buf_size - 1) != buf_size - 1 + || memcmp (buf, "ABCDEFGHI", 9)) + FAIL (); + + lseek (fileno (stdin), 0, SEEK_SET); + +- if (read (fileno (stdin), buf, l0 + sizeof (buf) - 1) != sizeof (buf) - 1 ++ if (read (fileno (stdin), buf, l0 + buf_size - 1) != buf_size - 1 + || memcmp (buf, "abcdefgh\n", 9)) + FAIL (); + + #if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START +- if (read (fileno (stdin), buf, sizeof (buf) + 1) != sizeof (buf) + 1) ++ if (read (fileno (stdin), buf, buf_size + 1) != buf_size + 1) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START +- if (read (fileno (stdin), buf, l0 + sizeof (buf) + 1) != sizeof (buf) + 1) ++ if (read (fileno (stdin), buf, l0 + buf_size + 1) != buf_size + 1) + FAIL (); + CHK_FAIL_END + #endif + +- if (pread (fileno (stdin), buf, sizeof (buf) - 1, sizeof (buf) - 2) +- != sizeof (buf) - 1 ++ if (pread (fileno (stdin), buf, buf_size - 1, buf_size - 2) ++ != buf_size - 1 + || memcmp (buf, "\nABCDEFGH", 9)) + FAIL (); +- if (pread (fileno (stdin), buf, sizeof (buf) - 1, 0) != sizeof (buf) - 1 ++ if (pread (fileno (stdin), buf, buf_size - 1, 0) != buf_size - 1 + || memcmp (buf, "abcdefgh\n", 9)) + FAIL (); +- if (pread (fileno (stdin), buf, l0 + sizeof (buf) - 1, sizeof (buf) - 3) +- != sizeof (buf) - 1 ++ if (pread (fileno (stdin), buf, l0 + buf_size - 1, buf_size - 3) ++ != buf_size - 1 + || memcmp (buf, "h\nABCDEFG", 9)) + FAIL (); + + #if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START +- if (pread (fileno (stdin), buf, sizeof (buf) + 1, 2 * sizeof (buf)) +- != sizeof (buf) + 1) ++ if (pread (fileno (stdin), buf, buf_size + 1, 2 * buf_size) ++ != buf_size + 1) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START +- if (pread (fileno (stdin), buf, l0 + sizeof (buf) + 1, 2 * sizeof (buf)) +- != sizeof (buf) + 1) ++ if (pread (fileno (stdin), buf, l0 + buf_size + 1, 2 * buf_size) ++ != buf_size + 1) + FAIL (); + CHK_FAIL_END + #endif + +- if (pread64 (fileno (stdin), buf, sizeof (buf) - 1, sizeof (buf) - 2) +- != sizeof (buf) - 1 ++ if (pread64 (fileno (stdin), buf, buf_size - 1, buf_size - 2) ++ != buf_size - 1 + || memcmp (buf, "\nABCDEFGH", 9)) + FAIL (); +- if (pread64 (fileno (stdin), buf, sizeof (buf) - 1, 0) != sizeof (buf) - 1 ++ if (pread64 (fileno (stdin), buf, buf_size - 1, 0) != buf_size - 1 + || memcmp (buf, "abcdefgh\n", 9)) + FAIL (); +- if (pread64 (fileno (stdin), buf, l0 + sizeof (buf) - 1, sizeof (buf) - 3) +- != sizeof (buf) - 1 ++ if (pread64 (fileno (stdin), buf, l0 + buf_size - 1, buf_size - 3) ++ != buf_size - 1 + || memcmp (buf, "h\nABCDEFG", 9)) + FAIL (); + + #if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START +- if (pread64 (fileno (stdin), buf, sizeof (buf) + 1, 2 * sizeof (buf)) +- != sizeof (buf) + 1) ++ if (pread64 (fileno (stdin), buf, buf_size + 1, 2 * buf_size) ++ != buf_size + 1) + FAIL (); + CHK_FAIL_END + + CHK_FAIL_START +- if (pread64 (fileno (stdin), buf, l0 + sizeof (buf) + 1, 2 * sizeof (buf)) +- != sizeof (buf) + 1) ++ if (pread64 (fileno (stdin), buf, l0 + buf_size + 1, 2 * buf_size) ++ != buf_size + 1) + FAIL (); + CHK_FAIL_END + #endif +@@ -1179,7 +1189,7 @@ do_test (void) + CHK_FAIL2_END + + CHK_FAIL2_START +- snprintf (buf, sizeof (buf), "%3$d\n", 1, 2, 3, 4); ++ snprintf (buf, buf_size, "%3$d\n", 1, 2, 3, 4); + CHK_FAIL2_END + + int sp[2]; +diff --git a/debug/tst-chk7.c b/debug/tst-chk7.c +new file mode 100644 +index 0000000000000000..2a7b32381268135c +--- /dev/null ++++ b/debug/tst-chk7.c +@@ -0,0 +1,2 @@ ++#define _FORTIFY_SOURCE 3 ++#include "tst-chk1.c" +diff --git a/debug/tst-chk8.cc b/debug/tst-chk8.cc +new file mode 100644 +index 0000000000000000..2a7b32381268135c +--- /dev/null ++++ b/debug/tst-chk8.cc +@@ -0,0 +1,2 @@ ++#define _FORTIFY_SOURCE 3 ++#include "tst-chk1.c" diff --git a/glibc-rh2033684-9.patch b/glibc-rh2033684-9.patch new file mode 100644 index 0000000..467ece4 --- /dev/null +++ b/glibc-rh2033684-9.patch @@ -0,0 +1,23 @@ +commit ae23fa3e5fe24daf94fc7f8e5268bb8ceeda7477 +Author: Siddhesh Poyarekar +Date: Thu Dec 16 07:19:14 2021 +0530 + + __glibc_unsafe_len: Fix comment + + We know that the length is *unsafe*. + + Signed-off-by: Siddhesh Poyarekar + +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index 17b84a2e6c69d961..147339957c4ad490 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -150,7 +150,7 @@ + __s, __osz)) \ + && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz)) + +-/* Conversely, we know at compile time that the length is safe if the ++/* Conversely, we know at compile time that the length is unsafe if the + __L * __S <= __OBJSZ condition can be folded to a constant and if it is + false. */ + #define __glibc_unsafe_len(__l, __s, __osz) \ diff --git a/glibc-rh2037416-1.patch b/glibc-rh2037416-1.patch new file mode 100644 index 0000000..3fddefe --- /dev/null +++ b/glibc-rh2037416-1.patch @@ -0,0 +1,136 @@ +From 07b427296b8d59f439144029d9a948f6c1ce0a31 Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra +Date: Tue, 10 Aug 2021 13:30:27 +0100 +Subject: [PATCH] [1/5] AArch64: Improve A64FX memset for small sizes + +Improve performance of small memsets by reducing instruction counts and +improving code alignment. Bench-memset shows 35-45% performance gain for +small sizes. + +Reviewed-by: Naohiro Tamura +--- + sysdeps/aarch64/multiarch/memset_a64fx.S | 96 +++++++++--------------- + 1 file changed, 36 insertions(+), 60 deletions(-) + +diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S +index ce54e5418b..cf3d402ef6 100644 +--- a/sysdeps/aarch64/multiarch/memset_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S +@@ -51,78 +51,54 @@ + .endm + + .macro st1b_unroll first=0, last=7 +- st1b z0.b, p0, [dst, #\first, mul vl] ++ st1b z0.b, p0, [dst, \first, mul vl] + .if \last-\first + st1b_unroll "(\first+1)", \last + .endif + .endm + +- .macro shortcut_for_small_size exit +- // if rest <= vector_length * 2 +- whilelo p0.b, xzr, count +- whilelo p1.b, vector_length, count +- b.last 1f +- st1b z0.b, p0, [dstin, #0, mul vl] +- st1b z0.b, p1, [dstin, #1, mul vl] +- ret +-1: // if rest > vector_length * 8 +- cmp count, vector_length, lsl 3 // vector_length * 8 +- b.hi \exit +- // if rest <= vector_length * 4 +- lsl tmp1, vector_length, 1 // vector_length * 2 +- whilelo p2.b, tmp1, count +- incb tmp1 +- whilelo p3.b, tmp1, count +- b.last 1f +- st1b z0.b, p0, [dstin, #0, mul vl] +- st1b z0.b, p1, [dstin, #1, mul vl] +- st1b z0.b, p2, [dstin, #2, mul vl] +- st1b z0.b, p3, [dstin, #3, mul vl] +- ret +-1: // if rest <= vector_length * 8 +- lsl tmp1, vector_length, 2 // vector_length * 4 +- whilelo p4.b, tmp1, count +- incb tmp1 +- whilelo p5.b, tmp1, count +- b.last 1f +- st1b z0.b, p0, [dstin, #0, mul vl] +- st1b z0.b, p1, [dstin, #1, mul vl] +- st1b z0.b, p2, [dstin, #2, mul vl] +- st1b z0.b, p3, [dstin, #3, mul vl] +- st1b z0.b, p4, [dstin, #4, mul vl] +- st1b z0.b, p5, [dstin, #5, mul vl] +- ret +-1: lsl tmp1, vector_length, 2 // vector_length * 4 +- incb tmp1 // vector_length * 5 +- incb tmp1 // vector_length * 6 +- whilelo p6.b, tmp1, count +- incb tmp1 +- whilelo p7.b, tmp1, count +- st1b z0.b, p0, [dstin, #0, mul vl] +- st1b z0.b, p1, [dstin, #1, mul vl] +- st1b z0.b, p2, [dstin, #2, mul vl] +- st1b z0.b, p3, [dstin, #3, mul vl] +- st1b z0.b, p4, [dstin, #4, mul vl] +- st1b z0.b, p5, [dstin, #5, mul vl] +- st1b z0.b, p6, [dstin, #6, mul vl] +- st1b z0.b, p7, [dstin, #7, mul vl] +- ret +- .endm + +-ENTRY (MEMSET) ++#undef BTI_C ++#define BTI_C + ++ENTRY (MEMSET) + PTR_ARG (0) + SIZE_ARG (2) + +- cbnz count, 1f +- ret +-1: dup z0.b, valw + cntb vector_length +- // shortcut for less than vector_length * 8 +- // gives a free ptrue to p0.b for n >= vector_length +- shortcut_for_small_size L(vl_agnostic) +- // end of shortcut ++ dup z0.b, valw ++ whilelo p0.b, vector_length, count ++ b.last 1f ++ whilelo p1.b, xzr, count ++ st1b z0.b, p1, [dstin, 0, mul vl] ++ st1b z0.b, p0, [dstin, 1, mul vl] ++ ret ++ ++ // count >= vector_length * 2 ++1: cmp count, vector_length, lsl 2 ++ add dstend, dstin, count ++ b.hi 1f ++ st1b z0.b, p0, [dstin, 0, mul vl] ++ st1b z0.b, p0, [dstin, 1, mul vl] ++ st1b z0.b, p0, [dstend, -2, mul vl] ++ st1b z0.b, p0, [dstend, -1, mul vl] ++ ret ++ ++ // count > vector_length * 4 ++1: lsl tmp1, vector_length, 3 ++ cmp count, tmp1 ++ b.hi L(vl_agnostic) ++ st1b z0.b, p0, [dstin, 0, mul vl] ++ st1b z0.b, p0, [dstin, 1, mul vl] ++ st1b z0.b, p0, [dstin, 2, mul vl] ++ st1b z0.b, p0, [dstin, 3, mul vl] ++ st1b z0.b, p0, [dstend, -4, mul vl] ++ st1b z0.b, p0, [dstend, -3, mul vl] ++ st1b z0.b, p0, [dstend, -2, mul vl] ++ st1b z0.b, p0, [dstend, -1, mul vl] ++ ret + ++ .p2align 4 + L(vl_agnostic): // VL Agnostic + mov rest, count + mov dst, dstin +-- +2.31.1 + diff --git a/glibc-rh2037416-2.patch b/glibc-rh2037416-2.patch new file mode 100644 index 0000000..e991e91 --- /dev/null +++ b/glibc-rh2037416-2.patch @@ -0,0 +1,131 @@ +From 9bc2ed8f46d80859a5596789cc9e8cc2de84b0e7 Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra +Date: Tue, 10 Aug 2021 13:39:37 +0100 +Subject: [PATCH] [2/5] AArch64: Improve A64FX memset for large sizes + +Improve performance of large memsets. Simplify alignment code. For zero memset +use DC ZVA, which almost doubles performance. For non-zero memsets use the +unroll8 loop which is about 10% faster. + +Reviewed-by: Naohiro Tamura +--- + sysdeps/aarch64/multiarch/memset_a64fx.S | 85 +++++++----------------- + 1 file changed, 25 insertions(+), 60 deletions(-) + +diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S +index cf3d402ef6..75cf43ae79 100644 +--- a/sysdeps/aarch64/multiarch/memset_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S +@@ -27,14 +27,11 @@ + */ + + #define L1_SIZE (64*1024) // L1 64KB +-#define L2_SIZE (8*1024*1024) // L2 8MB - 1MB ++#define L2_SIZE (8*1024*1024) // L2 8MB + #define CACHE_LINE_SIZE 256 + #define PF_DIST_L1 (CACHE_LINE_SIZE * 16) // Prefetch distance L1 +-#define ZF_DIST (CACHE_LINE_SIZE * 21) // Zerofill distance +-#define rest x8 ++#define rest x2 + #define vector_length x9 +-#define vl_remainder x10 // vector_length remainder +-#define cl_remainder x11 // CACHE_LINE_SIZE remainder + + #if HAVE_AARCH64_SVE_ASM + # if IS_IN (libc) +@@ -42,14 +39,6 @@ + + .arch armv8.2-a+sve + +- .macro dc_zva times +- dc zva, tmp1 +- add tmp1, tmp1, CACHE_LINE_SIZE +- .if \times-1 +- dc_zva "(\times-1)" +- .endif +- .endm +- + .macro st1b_unroll first=0, last=7 + st1b z0.b, p0, [dst, \first, mul vl] + .if \last-\first +@@ -188,54 +177,30 @@ L(L1_prefetch): // if rest >= L1_SIZE + cbnz rest, L(unroll32) + ret + +-L(L2): +- // align dst address at vector_length byte boundary +- sub tmp1, vector_length, 1 +- ands tmp2, dst, tmp1 +- // if vl_remainder == 0 +- b.eq 1f +- sub vl_remainder, vector_length, tmp2 +- // process remainder until the first vector_length boundary +- whilelt p2.b, xzr, vl_remainder +- st1b z0.b, p2, [dst] +- add dst, dst, vl_remainder +- sub rest, rest, vl_remainder +- // align dstin address at CACHE_LINE_SIZE byte boundary +-1: mov tmp1, CACHE_LINE_SIZE +- ands tmp2, dst, CACHE_LINE_SIZE - 1 +- // if cl_remainder == 0 +- b.eq L(L2_dc_zva) +- sub cl_remainder, tmp1, tmp2 +- // process remainder until the first CACHE_LINE_SIZE boundary +- mov tmp1, xzr // index +-2: whilelt p2.b, tmp1, cl_remainder +- st1b z0.b, p2, [dst, tmp1] +- incb tmp1 +- cmp tmp1, cl_remainder +- b.lo 2b +- add dst, dst, cl_remainder +- sub rest, rest, cl_remainder +- +-L(L2_dc_zva): +- // zero fill +- mov tmp1, dst +- dc_zva (ZF_DIST / CACHE_LINE_SIZE) - 1 +- mov zva_len, ZF_DIST +- add tmp1, zva_len, CACHE_LINE_SIZE * 2 +- // unroll ++ // count >= L2_SIZE + .p2align 3 +-1: st1b_unroll 0, 3 +- add tmp2, dst, zva_len +- dc zva, tmp2 +- st1b_unroll 4, 7 +- add tmp2, tmp2, CACHE_LINE_SIZE +- dc zva, tmp2 +- add dst, dst, CACHE_LINE_SIZE * 2 +- sub rest, rest, CACHE_LINE_SIZE * 2 +- cmp rest, tmp1 // ZF_DIST + CACHE_LINE_SIZE * 2 +- b.ge 1b +- cbnz rest, L(unroll8) +- ret ++L(L2): ++ tst valw, 255 ++ b.ne L(unroll8) ++ // align dst to CACHE_LINE_SIZE byte boundary ++ and tmp2, dst, CACHE_LINE_SIZE - 1 ++ st1b z0.b, p0, [dst, 0, mul vl] ++ st1b z0.b, p0, [dst, 1, mul vl] ++ st1b z0.b, p0, [dst, 2, mul vl] ++ st1b z0.b, p0, [dst, 3, mul vl] ++ sub dst, dst, tmp2 ++ add count, count, tmp2 ++ ++ // clear cachelines using DC ZVA ++ sub count, count, CACHE_LINE_SIZE * 2 ++ .p2align 4 ++1: add dst, dst, CACHE_LINE_SIZE ++ dc zva, dst ++ subs count, count, CACHE_LINE_SIZE ++ b.hi 1b ++ add count, count, CACHE_LINE_SIZE ++ add dst, dst, CACHE_LINE_SIZE ++ b L(last) + + END (MEMSET) + libc_hidden_builtin_def (MEMSET) +-- +2.31.1 + diff --git a/glibc-rh2037416-3.patch b/glibc-rh2037416-3.patch new file mode 100644 index 0000000..3ac7aa2 --- /dev/null +++ b/glibc-rh2037416-3.patch @@ -0,0 +1,80 @@ +From 186092c6ba8825598ffdbf15dbf0823c771f560d Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra +Date: Tue, 10 Aug 2021 13:42:07 +0100 +Subject: [PATCH] [3/5] AArch64: Improve A64FX memset for remaining bytes + +Simplify handling of remaining bytes. Avoid lots of taken branches and complex +whilelo computations, instead unconditionally write vectors from the end. + +Reviewed-by: Naohiro Tamura +--- + sysdeps/aarch64/multiarch/memset_a64fx.S | 46 +++++++----------------- + 1 file changed, 13 insertions(+), 33 deletions(-) + +diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S +index 75cf43ae79..337c86be6f 100644 +--- a/sysdeps/aarch64/multiarch/memset_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S +@@ -130,38 +130,19 @@ L(unroll8): + b 1b + + L(last): +- whilelo p0.b, xzr, rest +- whilelo p1.b, vector_length, rest +- b.last 1f +- st1b z0.b, p0, [dst, #0, mul vl] +- st1b z0.b, p1, [dst, #1, mul vl] +- ret +-1: lsl tmp1, vector_length, 1 // vector_length * 2 +- whilelo p2.b, tmp1, rest +- incb tmp1 +- whilelo p3.b, tmp1, rest +- b.last 1f +- st1b z0.b, p0, [dst, #0, mul vl] +- st1b z0.b, p1, [dst, #1, mul vl] +- st1b z0.b, p2, [dst, #2, mul vl] +- st1b z0.b, p3, [dst, #3, mul vl] +- ret +-1: lsl tmp1, vector_length, 2 // vector_length * 4 +- whilelo p4.b, tmp1, rest +- incb tmp1 +- whilelo p5.b, tmp1, rest +- incb tmp1 +- whilelo p6.b, tmp1, rest +- incb tmp1 +- whilelo p7.b, tmp1, rest +- st1b z0.b, p0, [dst, #0, mul vl] +- st1b z0.b, p1, [dst, #1, mul vl] +- st1b z0.b, p2, [dst, #2, mul vl] +- st1b z0.b, p3, [dst, #3, mul vl] +- st1b z0.b, p4, [dst, #4, mul vl] +- st1b z0.b, p5, [dst, #5, mul vl] +- st1b z0.b, p6, [dst, #6, mul vl] +- st1b z0.b, p7, [dst, #7, mul vl] ++ cmp count, vector_length, lsl 1 ++ b.ls 2f ++ add tmp2, vector_length, vector_length, lsl 2 ++ cmp count, tmp2 ++ b.ls 5f ++ st1b z0.b, p0, [dstend, -8, mul vl] ++ st1b z0.b, p0, [dstend, -7, mul vl] ++ st1b z0.b, p0, [dstend, -6, mul vl] ++5: st1b z0.b, p0, [dstend, -5, mul vl] ++ st1b z0.b, p0, [dstend, -4, mul vl] ++ st1b z0.b, p0, [dstend, -3, mul vl] ++2: st1b z0.b, p0, [dstend, -2, mul vl] ++ st1b z0.b, p0, [dstend, -1, mul vl] + ret + + L(L1_prefetch): // if rest >= L1_SIZE +@@ -199,7 +180,6 @@ L(L2): + subs count, count, CACHE_LINE_SIZE + b.hi 1b + add count, count, CACHE_LINE_SIZE +- add dst, dst, CACHE_LINE_SIZE + b L(last) + + END (MEMSET) +-- +2.31.1 + diff --git a/glibc-rh2037416-4.patch b/glibc-rh2037416-4.patch new file mode 100644 index 0000000..e057eeb --- /dev/null +++ b/glibc-rh2037416-4.patch @@ -0,0 +1,51 @@ +From e69d9981f858a38e19304e6ff5ebdf89f2cb0ba0 Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra +Date: Tue, 10 Aug 2021 13:44:27 +0100 +Subject: [PATCH] [4/5] AArch64: Improve A64FX memset by removing unroll32 + +Remove unroll32 code since it doesn't improve performance. + +Reviewed-by: Naohiro Tamura +--- + sysdeps/aarch64/multiarch/memset_a64fx.S | 18 +----------------- + 1 file changed, 1 insertion(+), 17 deletions(-) + +diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S +index 337c86be6f..ef0315658a 100644 +--- a/sysdeps/aarch64/multiarch/memset_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S +@@ -102,22 +102,6 @@ L(vl_agnostic): // VL Agnostic + ccmp vector_length, tmp1, 0, cs + b.eq L(L1_prefetch) + +-L(unroll32): +- lsl tmp1, vector_length, 3 // vector_length * 8 +- lsl tmp2, vector_length, 5 // vector_length * 32 +- .p2align 3 +-1: cmp rest, tmp2 +- b.cc L(unroll8) +- st1b_unroll +- add dst, dst, tmp1 +- st1b_unroll +- add dst, dst, tmp1 +- st1b_unroll +- add dst, dst, tmp1 +- st1b_unroll +- add dst, dst, tmp1 +- sub rest, rest, tmp2 +- b 1b + + L(unroll8): + lsl tmp1, vector_length, 3 +@@ -155,7 +139,7 @@ L(L1_prefetch): // if rest >= L1_SIZE + sub rest, rest, CACHE_LINE_SIZE * 2 + cmp rest, L1_SIZE + b.ge 1b +- cbnz rest, L(unroll32) ++ cbnz rest, L(unroll8) + ret + + // count >= L2_SIZE +-- +2.31.1 + diff --git a/glibc-rh2037416-5.patch b/glibc-rh2037416-5.patch new file mode 100644 index 0000000..c92c2cf --- /dev/null +++ b/glibc-rh2037416-5.patch @@ -0,0 +1,96 @@ +From a5db6a5cae6a92d1675c013e5c8d972768721576 Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra +Date: Tue, 10 Aug 2021 13:46:20 +0100 +Subject: [PATCH] [5/5] AArch64: Improve A64FX memset medium loops + +Simplify the code for memsets smaller than L1. Improve the unroll8 and +L1_prefetch loops. + +Reviewed-by: Naohiro Tamura +--- + sysdeps/aarch64/multiarch/memset_a64fx.S | 45 ++++++++++-------------- + 1 file changed, 19 insertions(+), 26 deletions(-) + +diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S +index ef0315658a..7bf759b6a7 100644 +--- a/sysdeps/aarch64/multiarch/memset_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S +@@ -30,7 +30,6 @@ + #define L2_SIZE (8*1024*1024) // L2 8MB + #define CACHE_LINE_SIZE 256 + #define PF_DIST_L1 (CACHE_LINE_SIZE * 16) // Prefetch distance L1 +-#define rest x2 + #define vector_length x9 + + #if HAVE_AARCH64_SVE_ASM +@@ -89,29 +88,19 @@ ENTRY (MEMSET) + + .p2align 4 + L(vl_agnostic): // VL Agnostic +- mov rest, count + mov dst, dstin +- add dstend, dstin, count +- // if rest >= L2_SIZE && vector_length == 64 then L(L2) +- mov tmp1, 64 +- cmp rest, L2_SIZE +- ccmp vector_length, tmp1, 0, cs +- b.eq L(L2) +- // if rest >= L1_SIZE && vector_length == 64 then L(L1_prefetch) +- cmp rest, L1_SIZE +- ccmp vector_length, tmp1, 0, cs +- b.eq L(L1_prefetch) +- ++ cmp count, L1_SIZE ++ b.hi L(L1_prefetch) + ++ // count >= 8 * vector_length + L(unroll8): +- lsl tmp1, vector_length, 3 +- .p2align 3 +-1: cmp rest, tmp1 +- b.cc L(last) +- st1b_unroll ++ sub count, count, tmp1 ++ .p2align 4 ++1: st1b_unroll 0, 7 + add dst, dst, tmp1 +- sub rest, rest, tmp1 +- b 1b ++ subs count, count, tmp1 ++ b.hi 1b ++ add count, count, tmp1 + + L(last): + cmp count, vector_length, lsl 1 +@@ -129,18 +118,22 @@ L(last): + st1b z0.b, p0, [dstend, -1, mul vl] + ret + +-L(L1_prefetch): // if rest >= L1_SIZE ++ // count >= L1_SIZE + .p2align 3 ++L(L1_prefetch): ++ cmp count, L2_SIZE ++ b.hs L(L2) ++ cmp vector_length, 64 ++ b.ne L(unroll8) + 1: st1b_unroll 0, 3 + prfm pstl1keep, [dst, PF_DIST_L1] + st1b_unroll 4, 7 + prfm pstl1keep, [dst, PF_DIST_L1 + CACHE_LINE_SIZE] + add dst, dst, CACHE_LINE_SIZE * 2 +- sub rest, rest, CACHE_LINE_SIZE * 2 +- cmp rest, L1_SIZE +- b.ge 1b +- cbnz rest, L(unroll8) +- ret ++ sub count, count, CACHE_LINE_SIZE * 2 ++ cmp count, PF_DIST_L1 ++ b.hs 1b ++ b L(unroll8) + + // count >= L2_SIZE + .p2align 3 +-- +2.31.1 + diff --git a/glibc-rh2037416-6.patch b/glibc-rh2037416-6.patch new file mode 100644 index 0000000..b2522ad --- /dev/null +++ b/glibc-rh2037416-6.patch @@ -0,0 +1,39 @@ +From 1d9f99ce1b3788d1897cb53a76d57e973111b8fe Mon Sep 17 00:00:00 2001 +From: Naohiro Tamura +Date: Fri, 27 Aug 2021 05:03:04 +0000 +Subject: [PATCH] AArch64: Update A64FX memset not to degrade at 16KB + +This patch updates unroll8 code so as not to degrade at the peak +performance 16KB for both FX1000 and FX700. + +Inserted 2 instructions at the beginning of the unroll8 loop, +cmp and branch, are a workaround that is found heuristically. + +Reviewed-by: Wilco Dijkstra +--- + sysdeps/aarch64/multiarch/memset_a64fx.S | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S +index 7bf759b6a7..f7dfdaace7 100644 +--- a/sysdeps/aarch64/multiarch/memset_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S +@@ -96,7 +96,14 @@ L(vl_agnostic): // VL Agnostic + L(unroll8): + sub count, count, tmp1 + .p2align 4 +-1: st1b_unroll 0, 7 ++ // The 2 instructions at the beginning of the following loop, ++ // cmp and branch, are a workaround so as not to degrade at ++ // the peak performance 16KB. ++ // It is found heuristically and the branch condition, b.ne, ++ // is chosen intentionally never to jump. ++1: cmp xzr, xzr ++ b.ne 1b ++ st1b_unroll 0, 7 + add dst, dst, tmp1 + subs count, count, tmp1 + b.hi 1b +-- +2.31.1 + diff --git a/glibc-rh2037416-7.patch b/glibc-rh2037416-7.patch new file mode 100644 index 0000000..e57fef7 --- /dev/null +++ b/glibc-rh2037416-7.patch @@ -0,0 +1,32 @@ +From 381b29616abb82babc8163bdf516c6da87544b35 Mon Sep 17 00:00:00 2001 +From: Naohiro Tamura +Date: Fri, 24 Sep 2021 07:49:59 +0000 +Subject: [PATCH] aarch64: Disable A64FX memcpy/memmove BTI unconditionally + +This patch disables A64FX memcpy/memmove BTI instruction insertion +unconditionally such as A64FX memset patch [1] for performance. + +[1] commit 07b427296b8d59f439144029d9a948f6c1ce0a31 + +Reviewed-by: Szabolcs Nagy +--- + sysdeps/aarch64/multiarch/memcpy_a64fx.S | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sysdeps/aarch64/multiarch/memcpy_a64fx.S b/sysdeps/aarch64/multiarch/memcpy_a64fx.S +index 65528405bb..ae7464e09f 100644 +--- a/sysdeps/aarch64/multiarch/memcpy_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memcpy_a64fx.S +@@ -19,6 +19,9 @@ + + #include + ++#undef BTI_C ++#define BTI_C ++ + /* Assumptions: + * + * ARMv8.2-a, AArch64, unaligned accesses, sve +-- +2.31.1 + diff --git a/glibc-rh2037416-8.patch b/glibc-rh2037416-8.patch new file mode 100644 index 0000000..6a68332 --- /dev/null +++ b/glibc-rh2037416-8.patch @@ -0,0 +1,630 @@ +From b31bd11454fade731e5158b1aea40b133ae19926 Mon Sep 17 00:00:00 2001 +From: Wilco Dijkstra +Date: Thu, 2 Dec 2021 18:33:26 +0000 +Subject: [PATCH] AArch64: Improve A64FX memcpy + +v2 is a complete rewrite of the A64FX memcpy. Performance is improved +by streamlining the code, aligning all large copies and using a single +unrolled loop for all sizes. The code size for memcpy and memmove goes +down from 1796 bytes to 868 bytes. Performance is better in all cases: +bench-memcpy-random is 2.3% faster overall, bench-memcpy-large is ~33% +faster for large sizes, bench-memcpy-walk is 25% faster for small sizes +and 20% for the largest sizes. The geomean of all tests in bench-memcpy +is 5.1% faster, and total time is reduced by 4%. + +Reviewed-by: Szabolcs Nagy +--- + sysdeps/aarch64/multiarch/memcpy_a64fx.S | 546 ++++++++++------------- + 1 file changed, 225 insertions(+), 321 deletions(-) + +diff --git a/sysdeps/aarch64/multiarch/memcpy_a64fx.S b/sysdeps/aarch64/multiarch/memcpy_a64fx.S +index ae7464e09f..0b306925e6 100644 +--- a/sysdeps/aarch64/multiarch/memcpy_a64fx.S ++++ b/sysdeps/aarch64/multiarch/memcpy_a64fx.S +@@ -28,20 +28,15 @@ + * + */ + +-#define L2_SIZE (8*1024*1024)/2 // L2 8MB/2 +-#define CACHE_LINE_SIZE 256 +-#define ZF_DIST (CACHE_LINE_SIZE * 21) // Zerofill distance +-#define dest x0 +-#define src x1 +-#define n x2 // size +-#define tmp1 x3 +-#define tmp2 x4 +-#define tmp3 x5 +-#define rest x6 +-#define dest_ptr x7 +-#define src_ptr x8 +-#define vector_length x9 +-#define cl_remainder x10 // CACHE_LINE_SIZE remainder ++#define dstin x0 ++#define src x1 ++#define n x2 ++#define dst x3 ++#define dstend x4 ++#define srcend x5 ++#define tmp x6 ++#define vlen x7 ++#define vlen8 x8 + + #if HAVE_AARCH64_SVE_ASM + # if IS_IN (libc) +@@ -50,45 +45,37 @@ + + .arch armv8.2-a+sve + +- .macro dc_zva times +- dc zva, tmp1 +- add tmp1, tmp1, CACHE_LINE_SIZE +- .if \times-1 +- dc_zva "(\times-1)" +- .endif +- .endm +- + .macro ld1b_unroll8 +- ld1b z0.b, p0/z, [src_ptr, #0, mul vl] +- ld1b z1.b, p0/z, [src_ptr, #1, mul vl] +- ld1b z2.b, p0/z, [src_ptr, #2, mul vl] +- ld1b z3.b, p0/z, [src_ptr, #3, mul vl] +- ld1b z4.b, p0/z, [src_ptr, #4, mul vl] +- ld1b z5.b, p0/z, [src_ptr, #5, mul vl] +- ld1b z6.b, p0/z, [src_ptr, #6, mul vl] +- ld1b z7.b, p0/z, [src_ptr, #7, mul vl] ++ ld1b z0.b, p0/z, [src, 0, mul vl] ++ ld1b z1.b, p0/z, [src, 1, mul vl] ++ ld1b z2.b, p0/z, [src, 2, mul vl] ++ ld1b z3.b, p0/z, [src, 3, mul vl] ++ ld1b z4.b, p0/z, [src, 4, mul vl] ++ ld1b z5.b, p0/z, [src, 5, mul vl] ++ ld1b z6.b, p0/z, [src, 6, mul vl] ++ ld1b z7.b, p0/z, [src, 7, mul vl] + .endm + + .macro stld1b_unroll4a +- st1b z0.b, p0, [dest_ptr, #0, mul vl] +- st1b z1.b, p0, [dest_ptr, #1, mul vl] +- ld1b z0.b, p0/z, [src_ptr, #0, mul vl] +- ld1b z1.b, p0/z, [src_ptr, #1, mul vl] +- st1b z2.b, p0, [dest_ptr, #2, mul vl] +- st1b z3.b, p0, [dest_ptr, #3, mul vl] +- ld1b z2.b, p0/z, [src_ptr, #2, mul vl] +- ld1b z3.b, p0/z, [src_ptr, #3, mul vl] ++ st1b z0.b, p0, [dst, 0, mul vl] ++ st1b z1.b, p0, [dst, 1, mul vl] ++ ld1b z0.b, p0/z, [src, 0, mul vl] ++ ld1b z1.b, p0/z, [src, 1, mul vl] ++ st1b z2.b, p0, [dst, 2, mul vl] ++ st1b z3.b, p0, [dst, 3, mul vl] ++ ld1b z2.b, p0/z, [src, 2, mul vl] ++ ld1b z3.b, p0/z, [src, 3, mul vl] + .endm + + .macro stld1b_unroll4b +- st1b z4.b, p0, [dest_ptr, #4, mul vl] +- st1b z5.b, p0, [dest_ptr, #5, mul vl] +- ld1b z4.b, p0/z, [src_ptr, #4, mul vl] +- ld1b z5.b, p0/z, [src_ptr, #5, mul vl] +- st1b z6.b, p0, [dest_ptr, #6, mul vl] +- st1b z7.b, p0, [dest_ptr, #7, mul vl] +- ld1b z6.b, p0/z, [src_ptr, #6, mul vl] +- ld1b z7.b, p0/z, [src_ptr, #7, mul vl] ++ st1b z4.b, p0, [dst, 4, mul vl] ++ st1b z5.b, p0, [dst, 5, mul vl] ++ ld1b z4.b, p0/z, [src, 4, mul vl] ++ ld1b z5.b, p0/z, [src, 5, mul vl] ++ st1b z6.b, p0, [dst, 6, mul vl] ++ st1b z7.b, p0, [dst, 7, mul vl] ++ ld1b z6.b, p0/z, [src, 6, mul vl] ++ ld1b z7.b, p0/z, [src, 7, mul vl] + .endm + + .macro stld1b_unroll8 +@@ -97,87 +84,18 @@ + .endm + + .macro st1b_unroll8 +- st1b z0.b, p0, [dest_ptr, #0, mul vl] +- st1b z1.b, p0, [dest_ptr, #1, mul vl] +- st1b z2.b, p0, [dest_ptr, #2, mul vl] +- st1b z3.b, p0, [dest_ptr, #3, mul vl] +- st1b z4.b, p0, [dest_ptr, #4, mul vl] +- st1b z5.b, p0, [dest_ptr, #5, mul vl] +- st1b z6.b, p0, [dest_ptr, #6, mul vl] +- st1b z7.b, p0, [dest_ptr, #7, mul vl] ++ st1b z0.b, p0, [dst, 0, mul vl] ++ st1b z1.b, p0, [dst, 1, mul vl] ++ st1b z2.b, p0, [dst, 2, mul vl] ++ st1b z3.b, p0, [dst, 3, mul vl] ++ st1b z4.b, p0, [dst, 4, mul vl] ++ st1b z5.b, p0, [dst, 5, mul vl] ++ st1b z6.b, p0, [dst, 6, mul vl] ++ st1b z7.b, p0, [dst, 7, mul vl] + .endm + +- .macro shortcut_for_small_size exit +- // if rest <= vector_length * 2 +- whilelo p0.b, xzr, n +- whilelo p1.b, vector_length, n +- b.last 1f +- ld1b z0.b, p0/z, [src, #0, mul vl] +- ld1b z1.b, p1/z, [src, #1, mul vl] +- st1b z0.b, p0, [dest, #0, mul vl] +- st1b z1.b, p1, [dest, #1, mul vl] +- ret +-1: // if rest > vector_length * 8 +- cmp n, vector_length, lsl 3 // vector_length * 8 +- b.hi \exit +- // if rest <= vector_length * 4 +- lsl tmp1, vector_length, 1 // vector_length * 2 +- whilelo p2.b, tmp1, n +- incb tmp1 +- whilelo p3.b, tmp1, n +- b.last 1f +- ld1b z0.b, p0/z, [src, #0, mul vl] +- ld1b z1.b, p1/z, [src, #1, mul vl] +- ld1b z2.b, p2/z, [src, #2, mul vl] +- ld1b z3.b, p3/z, [src, #3, mul vl] +- st1b z0.b, p0, [dest, #0, mul vl] +- st1b z1.b, p1, [dest, #1, mul vl] +- st1b z2.b, p2, [dest, #2, mul vl] +- st1b z3.b, p3, [dest, #3, mul vl] +- ret +-1: // if rest <= vector_length * 8 +- lsl tmp1, vector_length, 2 // vector_length * 4 +- whilelo p4.b, tmp1, n +- incb tmp1 +- whilelo p5.b, tmp1, n +- b.last 1f +- ld1b z0.b, p0/z, [src, #0, mul vl] +- ld1b z1.b, p1/z, [src, #1, mul vl] +- ld1b z2.b, p2/z, [src, #2, mul vl] +- ld1b z3.b, p3/z, [src, #3, mul vl] +- ld1b z4.b, p4/z, [src, #4, mul vl] +- ld1b z5.b, p5/z, [src, #5, mul vl] +- st1b z0.b, p0, [dest, #0, mul vl] +- st1b z1.b, p1, [dest, #1, mul vl] +- st1b z2.b, p2, [dest, #2, mul vl] +- st1b z3.b, p3, [dest, #3, mul vl] +- st1b z4.b, p4, [dest, #4, mul vl] +- st1b z5.b, p5, [dest, #5, mul vl] +- ret +-1: lsl tmp1, vector_length, 2 // vector_length * 4 +- incb tmp1 // vector_length * 5 +- incb tmp1 // vector_length * 6 +- whilelo p6.b, tmp1, n +- incb tmp1 +- whilelo p7.b, tmp1, n +- ld1b z0.b, p0/z, [src, #0, mul vl] +- ld1b z1.b, p1/z, [src, #1, mul vl] +- ld1b z2.b, p2/z, [src, #2, mul vl] +- ld1b z3.b, p3/z, [src, #3, mul vl] +- ld1b z4.b, p4/z, [src, #4, mul vl] +- ld1b z5.b, p5/z, [src, #5, mul vl] +- ld1b z6.b, p6/z, [src, #6, mul vl] +- ld1b z7.b, p7/z, [src, #7, mul vl] +- st1b z0.b, p0, [dest, #0, mul vl] +- st1b z1.b, p1, [dest, #1, mul vl] +- st1b z2.b, p2, [dest, #2, mul vl] +- st1b z3.b, p3, [dest, #3, mul vl] +- st1b z4.b, p4, [dest, #4, mul vl] +- st1b z5.b, p5, [dest, #5, mul vl] +- st1b z6.b, p6, [dest, #6, mul vl] +- st1b z7.b, p7, [dest, #7, mul vl] +- ret +- .endm ++#undef BTI_C ++#define BTI_C + + ENTRY (MEMCPY) + +@@ -185,223 +103,209 @@ ENTRY (MEMCPY) + PTR_ARG (1) + SIZE_ARG (2) + +-L(memcpy): +- cntb vector_length +- // shortcut for less than vector_length * 8 +- // gives a free ptrue to p0.b for n >= vector_length +- shortcut_for_small_size L(vl_agnostic) +- // end of shortcut +- +-L(vl_agnostic): // VL Agnostic +- mov rest, n +- mov dest_ptr, dest +- mov src_ptr, src +- // if rest >= L2_SIZE && vector_length == 64 then L(L2) +- mov tmp1, 64 +- cmp rest, L2_SIZE +- ccmp vector_length, tmp1, 0, cs +- b.eq L(L2) +- +-L(unroll8): // unrolling and software pipeline +- lsl tmp1, vector_length, 3 // vector_length * 8 +- .p2align 3 +- cmp rest, tmp1 +- b.cc L(last) ++ cntb vlen ++ cmp n, vlen, lsl 1 ++ b.hi L(copy_small) ++ whilelo p1.b, vlen, n ++ whilelo p0.b, xzr, n ++ ld1b z0.b, p0/z, [src, 0, mul vl] ++ ld1b z1.b, p1/z, [src, 1, mul vl] ++ st1b z0.b, p0, [dstin, 0, mul vl] ++ st1b z1.b, p1, [dstin, 1, mul vl] ++ ret ++ ++ .p2align 4 ++ ++L(copy_small): ++ cmp n, vlen, lsl 3 ++ b.hi L(copy_large) ++ add dstend, dstin, n ++ add srcend, src, n ++ cmp n, vlen, lsl 2 ++ b.hi 1f ++ ++ /* Copy 2-4 vectors. */ ++ ptrue p0.b ++ ld1b z0.b, p0/z, [src, 0, mul vl] ++ ld1b z1.b, p0/z, [src, 1, mul vl] ++ ld1b z2.b, p0/z, [srcend, -2, mul vl] ++ ld1b z3.b, p0/z, [srcend, -1, mul vl] ++ st1b z0.b, p0, [dstin, 0, mul vl] ++ st1b z1.b, p0, [dstin, 1, mul vl] ++ st1b z2.b, p0, [dstend, -2, mul vl] ++ st1b z3.b, p0, [dstend, -1, mul vl] ++ ret ++ ++ .p2align 4 ++ /* Copy 4-8 vectors. */ ++1: ptrue p0.b ++ ld1b z0.b, p0/z, [src, 0, mul vl] ++ ld1b z1.b, p0/z, [src, 1, mul vl] ++ ld1b z2.b, p0/z, [src, 2, mul vl] ++ ld1b z3.b, p0/z, [src, 3, mul vl] ++ ld1b z4.b, p0/z, [srcend, -4, mul vl] ++ ld1b z5.b, p0/z, [srcend, -3, mul vl] ++ ld1b z6.b, p0/z, [srcend, -2, mul vl] ++ ld1b z7.b, p0/z, [srcend, -1, mul vl] ++ st1b z0.b, p0, [dstin, 0, mul vl] ++ st1b z1.b, p0, [dstin, 1, mul vl] ++ st1b z2.b, p0, [dstin, 2, mul vl] ++ st1b z3.b, p0, [dstin, 3, mul vl] ++ st1b z4.b, p0, [dstend, -4, mul vl] ++ st1b z5.b, p0, [dstend, -3, mul vl] ++ st1b z6.b, p0, [dstend, -2, mul vl] ++ st1b z7.b, p0, [dstend, -1, mul vl] ++ ret ++ ++ .p2align 4 ++ /* At least 8 vectors - always align to vector length for ++ higher and consistent write performance. */ ++L(copy_large): ++ sub tmp, vlen, 1 ++ and tmp, dstin, tmp ++ sub tmp, vlen, tmp ++ whilelo p1.b, xzr, tmp ++ ld1b z1.b, p1/z, [src] ++ st1b z1.b, p1, [dstin] ++ add dst, dstin, tmp ++ add src, src, tmp ++ sub n, n, tmp ++ ptrue p0.b ++ ++ lsl vlen8, vlen, 3 ++ subs n, n, vlen8 ++ b.ls 3f + ld1b_unroll8 +- add src_ptr, src_ptr, tmp1 +- sub rest, rest, tmp1 +- cmp rest, tmp1 +- b.cc 2f +- .p2align 3 ++ add src, src, vlen8 ++ subs n, n, vlen8 ++ b.ls 2f ++ ++ .p2align 4 ++ /* 8x unrolled and software pipelined loop. */ + 1: stld1b_unroll8 +- add dest_ptr, dest_ptr, tmp1 +- add src_ptr, src_ptr, tmp1 +- sub rest, rest, tmp1 +- cmp rest, tmp1 +- b.ge 1b ++ add dst, dst, vlen8 ++ add src, src, vlen8 ++ subs n, n, vlen8 ++ b.hi 1b + 2: st1b_unroll8 +- add dest_ptr, dest_ptr, tmp1 +- +- .p2align 3 +-L(last): +- whilelo p0.b, xzr, rest +- whilelo p1.b, vector_length, rest +- b.last 1f +- ld1b z0.b, p0/z, [src_ptr, #0, mul vl] +- ld1b z1.b, p1/z, [src_ptr, #1, mul vl] +- st1b z0.b, p0, [dest_ptr, #0, mul vl] +- st1b z1.b, p1, [dest_ptr, #1, mul vl] +- ret +-1: lsl tmp1, vector_length, 1 // vector_length * 2 +- whilelo p2.b, tmp1, rest +- incb tmp1 +- whilelo p3.b, tmp1, rest +- b.last 1f +- ld1b z0.b, p0/z, [src_ptr, #0, mul vl] +- ld1b z1.b, p1/z, [src_ptr, #1, mul vl] +- ld1b z2.b, p2/z, [src_ptr, #2, mul vl] +- ld1b z3.b, p3/z, [src_ptr, #3, mul vl] +- st1b z0.b, p0, [dest_ptr, #0, mul vl] +- st1b z1.b, p1, [dest_ptr, #1, mul vl] +- st1b z2.b, p2, [dest_ptr, #2, mul vl] +- st1b z3.b, p3, [dest_ptr, #3, mul vl] ++ add dst, dst, vlen8 ++3: add n, n, vlen8 ++ ++ /* Move last 0-8 vectors. */ ++L(last_bytes): ++ cmp n, vlen, lsl 1 ++ b.hi 1f ++ whilelo p0.b, xzr, n ++ whilelo p1.b, vlen, n ++ ld1b z0.b, p0/z, [src, 0, mul vl] ++ ld1b z1.b, p1/z, [src, 1, mul vl] ++ st1b z0.b, p0, [dst, 0, mul vl] ++ st1b z1.b, p1, [dst, 1, mul vl] + ret +-1: lsl tmp1, vector_length, 2 // vector_length * 4 +- whilelo p4.b, tmp1, rest +- incb tmp1 +- whilelo p5.b, tmp1, rest +- incb tmp1 +- whilelo p6.b, tmp1, rest +- incb tmp1 +- whilelo p7.b, tmp1, rest +- ld1b z0.b, p0/z, [src_ptr, #0, mul vl] +- ld1b z1.b, p1/z, [src_ptr, #1, mul vl] +- ld1b z2.b, p2/z, [src_ptr, #2, mul vl] +- ld1b z3.b, p3/z, [src_ptr, #3, mul vl] +- ld1b z4.b, p4/z, [src_ptr, #4, mul vl] +- ld1b z5.b, p5/z, [src_ptr, #5, mul vl] +- ld1b z6.b, p6/z, [src_ptr, #6, mul vl] +- ld1b z7.b, p7/z, [src_ptr, #7, mul vl] +- st1b z0.b, p0, [dest_ptr, #0, mul vl] +- st1b z1.b, p1, [dest_ptr, #1, mul vl] +- st1b z2.b, p2, [dest_ptr, #2, mul vl] +- st1b z3.b, p3, [dest_ptr, #3, mul vl] +- st1b z4.b, p4, [dest_ptr, #4, mul vl] +- st1b z5.b, p5, [dest_ptr, #5, mul vl] +- st1b z6.b, p6, [dest_ptr, #6, mul vl] +- st1b z7.b, p7, [dest_ptr, #7, mul vl] ++ ++ .p2align 4 ++ ++1: add srcend, src, n ++ add dstend, dst, n ++ ld1b z0.b, p0/z, [src, 0, mul vl] ++ ld1b z1.b, p0/z, [src, 1, mul vl] ++ ld1b z2.b, p0/z, [srcend, -2, mul vl] ++ ld1b z3.b, p0/z, [srcend, -1, mul vl] ++ cmp n, vlen, lsl 2 ++ b.hi 1f ++ ++ st1b z0.b, p0, [dst, 0, mul vl] ++ st1b z1.b, p0, [dst, 1, mul vl] ++ st1b z2.b, p0, [dstend, -2, mul vl] ++ st1b z3.b, p0, [dstend, -1, mul vl] + ret + +-L(L2): +- // align dest address at CACHE_LINE_SIZE byte boundary +- mov tmp1, CACHE_LINE_SIZE +- ands tmp2, dest_ptr, CACHE_LINE_SIZE - 1 +- // if cl_remainder == 0 +- b.eq L(L2_dc_zva) +- sub cl_remainder, tmp1, tmp2 +- // process remainder until the first CACHE_LINE_SIZE boundary +- whilelo p1.b, xzr, cl_remainder // keep p0.b all true +- whilelo p2.b, vector_length, cl_remainder +- b.last 1f +- ld1b z1.b, p1/z, [src_ptr, #0, mul vl] +- ld1b z2.b, p2/z, [src_ptr, #1, mul vl] +- st1b z1.b, p1, [dest_ptr, #0, mul vl] +- st1b z2.b, p2, [dest_ptr, #1, mul vl] +- b 2f +-1: lsl tmp1, vector_length, 1 // vector_length * 2 +- whilelo p3.b, tmp1, cl_remainder +- incb tmp1 +- whilelo p4.b, tmp1, cl_remainder +- ld1b z1.b, p1/z, [src_ptr, #0, mul vl] +- ld1b z2.b, p2/z, [src_ptr, #1, mul vl] +- ld1b z3.b, p3/z, [src_ptr, #2, mul vl] +- ld1b z4.b, p4/z, [src_ptr, #3, mul vl] +- st1b z1.b, p1, [dest_ptr, #0, mul vl] +- st1b z2.b, p2, [dest_ptr, #1, mul vl] +- st1b z3.b, p3, [dest_ptr, #2, mul vl] +- st1b z4.b, p4, [dest_ptr, #3, mul vl] +-2: add dest_ptr, dest_ptr, cl_remainder +- add src_ptr, src_ptr, cl_remainder +- sub rest, rest, cl_remainder +- +-L(L2_dc_zva): +- // zero fill +- and tmp1, dest, 0xffffffffffffff +- and tmp2, src, 0xffffffffffffff +- subs tmp1, tmp1, tmp2 // diff +- b.ge 1f +- neg tmp1, tmp1 +-1: mov tmp3, ZF_DIST + CACHE_LINE_SIZE * 2 +- cmp tmp1, tmp3 +- b.lo L(unroll8) +- mov tmp1, dest_ptr +- dc_zva (ZF_DIST / CACHE_LINE_SIZE) - 1 +- // unroll +- ld1b_unroll8 // this line has to be after "b.lo L(unroll8)" +- add src_ptr, src_ptr, CACHE_LINE_SIZE * 2 +- sub rest, rest, CACHE_LINE_SIZE * 2 +- mov tmp1, ZF_DIST +- .p2align 3 +-1: stld1b_unroll4a +- add tmp2, dest_ptr, tmp1 // dest_ptr + ZF_DIST +- dc zva, tmp2 +- stld1b_unroll4b +- add tmp2, tmp2, CACHE_LINE_SIZE +- dc zva, tmp2 +- add dest_ptr, dest_ptr, CACHE_LINE_SIZE * 2 +- add src_ptr, src_ptr, CACHE_LINE_SIZE * 2 +- sub rest, rest, CACHE_LINE_SIZE * 2 +- cmp rest, tmp3 // ZF_DIST + CACHE_LINE_SIZE * 2 +- b.ge 1b +- st1b_unroll8 +- add dest_ptr, dest_ptr, CACHE_LINE_SIZE * 2 +- b L(unroll8) ++1: ld1b z4.b, p0/z, [src, 2, mul vl] ++ ld1b z5.b, p0/z, [src, 3, mul vl] ++ ld1b z6.b, p0/z, [srcend, -4, mul vl] ++ ld1b z7.b, p0/z, [srcend, -3, mul vl] ++ st1b z0.b, p0, [dst, 0, mul vl] ++ st1b z1.b, p0, [dst, 1, mul vl] ++ st1b z4.b, p0, [dst, 2, mul vl] ++ st1b z5.b, p0, [dst, 3, mul vl] ++ st1b z6.b, p0, [dstend, -4, mul vl] ++ st1b z7.b, p0, [dstend, -3, mul vl] ++ st1b z2.b, p0, [dstend, -2, mul vl] ++ st1b z3.b, p0, [dstend, -1, mul vl] ++ ret + + END (MEMCPY) + libc_hidden_builtin_def (MEMCPY) + + +-ENTRY (MEMMOVE) ++ENTRY_ALIGN (MEMMOVE, 4) + + PTR_ARG (0) + PTR_ARG (1) + SIZE_ARG (2) + +- // remove tag address +- // dest has to be immutable because it is the return value +- // src has to be immutable because it is used in L(bwd_last) +- and tmp2, dest, 0xffffffffffffff // save dest_notag into tmp2 +- and tmp3, src, 0xffffffffffffff // save src_notag intp tmp3 +- cmp n, 0 +- ccmp tmp2, tmp3, 4, ne +- b.ne 1f ++ /* Fast case for up to 2 vectors. */ ++ cntb vlen ++ cmp n, vlen, lsl 1 ++ b.hi 1f ++ whilelo p0.b, xzr, n ++ whilelo p1.b, vlen, n ++ ld1b z0.b, p0/z, [src, 0, mul vl] ++ ld1b z1.b, p1/z, [src, 1, mul vl] ++ st1b z0.b, p0, [dstin, 0, mul vl] ++ st1b z1.b, p1, [dstin, 1, mul vl] ++L(full_overlap): + ret +-1: cntb vector_length +- // shortcut for less than vector_length * 8 +- // gives a free ptrue to p0.b for n >= vector_length +- // tmp2 and tmp3 should not be used in this macro to keep +- // notag addresses +- shortcut_for_small_size L(dispatch) +- // end of shortcut +- +-L(dispatch): +- // tmp2 = dest_notag, tmp3 = src_notag +- // diff = dest_notag - src_notag +- sub tmp1, tmp2, tmp3 +- // if diff <= 0 || diff >= n then memcpy +- cmp tmp1, 0 +- ccmp tmp1, n, 2, gt +- b.cs L(vl_agnostic) +- +-L(bwd_start): +- mov rest, n +- add dest_ptr, dest, n // dest_end +- add src_ptr, src, n // src_end +- +-L(bwd_unroll8): // unrolling and software pipeline +- lsl tmp1, vector_length, 3 // vector_length * 8 +- .p2align 3 +- cmp rest, tmp1 +- b.cc L(bwd_last) +- sub src_ptr, src_ptr, tmp1 ++ ++ .p2align 4 ++ /* Check for overlapping moves. Return if there is a full overlap. ++ Small moves up to 8 vectors use the overlap-safe copy_small code. ++ Non-overlapping or overlapping moves with dst < src use memcpy. ++ Overlapping moves with dst > src use a backward copy loop. */ ++1: sub tmp, dstin, src ++ ands tmp, tmp, 0xffffffffffffff /* Clear special tag bits. */ ++ b.eq L(full_overlap) ++ cmp n, vlen, lsl 3 ++ b.ls L(copy_small) ++ cmp tmp, n ++ b.hs L(copy_large) ++ ++ /* Align to vector length. */ ++ add dst, dstin, n ++ sub tmp, vlen, 1 ++ ands tmp, dst, tmp ++ csel tmp, tmp, vlen, ne ++ whilelo p1.b, xzr, tmp ++ sub n, n, tmp ++ ld1b z1.b, p1/z, [src, n] ++ st1b z1.b, p1, [dstin, n] ++ add src, src, n ++ add dst, dstin, n ++ ++ ptrue p0.b ++ lsl vlen8, vlen, 3 ++ subs n, n, vlen8 ++ b.ls 3f ++ sub src, src, vlen8 + ld1b_unroll8 +- sub rest, rest, tmp1 +- cmp rest, tmp1 +- b.cc 2f +- .p2align 3 +-1: sub src_ptr, src_ptr, tmp1 +- sub dest_ptr, dest_ptr, tmp1 ++ subs n, n, vlen8 ++ b.ls 2f ++ ++ .p2align 4 ++ /* 8x unrolled and software pipelined backward copy loop. */ ++1: sub src, src, vlen8 ++ sub dst, dst, vlen8 + stld1b_unroll8 +- sub rest, rest, tmp1 +- cmp rest, tmp1 +- b.ge 1b +-2: sub dest_ptr, dest_ptr, tmp1 ++ subs n, n, vlen8 ++ b.hi 1b ++2: sub dst, dst, vlen8 + st1b_unroll8 ++3: add n, n, vlen8 + +-L(bwd_last): +- mov dest_ptr, dest +- mov src_ptr, src +- b L(last) ++ /* Adjust src/dst for last 0-8 vectors. */ ++ sub src, src, n ++ mov dst, dstin ++ b L(last_bytes) + + END (MEMMOVE) + libc_hidden_builtin_def (MEMMOVE) +-- +2.31.1 + diff --git a/glibc-rh2047981-1.patch b/glibc-rh2047981-1.patch new file mode 100644 index 0000000..e1a085d --- /dev/null +++ b/glibc-rh2047981-1.patch @@ -0,0 +1,98 @@ +commit eb77a1fccc7e60cea32245c11288c7f1d92545fa +Author: Florian Weimer +Date: Wed Oct 16 18:19:51 2019 +0200 + + dlfcn: Remove remnants of caller sensitivity from dlinfo + + dlinfo operates on a specific handle, which means that there is no + caller sensivity involved. + +diff --git a/dlfcn/dlinfo.c b/dlfcn/dlinfo.c +index 964572cc670ceba4..23ef3f57ca41afdf 100644 +--- a/dlfcn/dlinfo.c ++++ b/dlfcn/dlinfo.c +@@ -26,7 +26,7 @@ + int + dlinfo (void *handle, int request, void *arg) + { +- return __dlinfo (handle, request, arg, RETURN_ADDRESS (0)); ++ return __dlinfo (handle, request, arg); + } + + #else +@@ -35,7 +35,6 @@ dlinfo (void *handle, int request, void *arg) + + struct dlinfo_args + { +- ElfW(Addr) caller; + void *handle; + int request; + void *arg; +@@ -47,24 +46,6 @@ dlinfo_doit (void *argsblock) + struct dlinfo_args *const args = argsblock; + struct link_map *l = args->handle; + +-# if 0 +- if (args->handle == RTLD_SELF) +- { +- Lmid_t nsid; +- +- /* Find the highest-addressed object that CALLER is not below. */ +- for (nsid = 0; nsid < DL_NNS; ++nsid) +- for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next) +- if (caller >= l->l_map_start && caller < l->l_map_end +- && (l->l_contiguous || _dl_addr_inside_object (l, caller))) +- break; +- +- if (l == NULL) +- _dl_signal_error (0, NULL, NULL, N_("\ +-RTLD_SELF used in code not dynamically loaded")); +- } +-# endif +- + switch (args->request) + { + case RTLD_DI_CONFIGADDR: +@@ -108,16 +89,14 @@ RTLD_SELF used in code not dynamically loaded")); + } + + int +-__dlinfo (void *handle, int request, void *arg DL_CALLER_DECL) ++__dlinfo (void *handle, int request, void *arg) + { + # ifdef SHARED + if (!rtld_active ()) +- return _dlfcn_hook->dlinfo (handle, request, arg, +- DL_CALLER); ++ return _dlfcn_hook->dlinfo (handle, request, arg); + # endif + +- struct dlinfo_args args = { (ElfW(Addr)) DL_CALLER, +- handle, request, arg }; ++ struct dlinfo_args args = { handle, request, arg }; + return _dlerror_run (&dlinfo_doit, &args) ? -1 : 0; + } + # ifdef SHARED +diff --git a/include/dlfcn.h b/include/dlfcn.h +index 0dc57dbe2217cfe7..93dd369ab12a5745 100644 +--- a/include/dlfcn.h ++++ b/include/dlfcn.h +@@ -117,7 +117,7 @@ struct dlfcn_hook + int (*dladdr) (const void *address, Dl_info *info); + int (*dladdr1) (const void *address, Dl_info *info, + void **extra_info, int flags); +- int (*dlinfo) (void *handle, int request, void *arg, void *dl_caller); ++ int (*dlinfo) (void *handle, int request, void *arg); + void *(*dlmopen) (Lmid_t nsid, const char *file, int mode, void *dl_caller); + void *pad[4]; + }; +@@ -143,8 +143,7 @@ extern int __dladdr (const void *address, Dl_info *info) + extern int __dladdr1 (const void *address, Dl_info *info, + void **extra_info, int flags) + attribute_hidden; +-extern int __dlinfo (void *handle, int request, void *arg DL_CALLER_DECL) +- attribute_hidden; ++extern int __dlinfo (void *handle, int request, void *arg) attribute_hidden; + + #ifndef SHARED + struct link_map; diff --git a/glibc-rh2047981-10.patch b/glibc-rh2047981-10.patch new file mode 100644 index 0000000..00b7a71 --- /dev/null +++ b/glibc-rh2047981-10.patch @@ -0,0 +1,31 @@ +commit 88361b408b9dbd313f15413cc2e6be0f1cafb01a +Author: H.J. Lu +Date: Tue Aug 17 19:36:04 2021 -0700 + + elf: Copy l_addr/l_ld when adding ld.so to a new namespace + + When add ld.so to a new namespace, we don't actually load ld.so. We + create a new link map and refers the real one for almost everything. + Copy l_addr and l_ld from the real ld.so link map to avoid GDB warning: + + warning: .dynamic section for ".../elf/ld-linux-x86-64.so.2" is not at the expected address (wrong library or version mismatch?) + + when handling shared library loaded by dlmopen. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-load.c b/elf/dl-load.c +index cdb5d4b5b67f1ca1..303e6594f9af9b7e 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -932,6 +932,10 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + /* Refer to the real descriptor. */ + l->l_real = &GL(dl_rtld_map); + ++ /* Copy l_addr and l_ld to avoid a GDB warning with dlmopen(). */ ++ l->l_addr = l->l_real->l_addr; ++ l->l_ld = l->l_real->l_ld; ++ + /* No need to bump the refcount of the real object, ld.so will + never be unloaded. */ + __close_nocancel (fd); diff --git a/glibc-rh2047981-11.patch b/glibc-rh2047981-11.patch new file mode 100644 index 0000000..a0cde6c --- /dev/null +++ b/glibc-rh2047981-11.patch @@ -0,0 +1,45 @@ +commit 1e1ecea62e899acb58c3fdf3b320a0833ddd0dff +Author: H.J. Lu +Date: Thu Sep 30 10:29:17 2021 -0700 + + elf: Replace nsid with args.nsid [BZ #27609] + + commit ec935dea6332cb22f9881cd1162bad156173f4b0 + Author: Florian Weimer + Date: Fri Apr 24 22:31:15 2020 +0200 + + elf: Implement __libc_early_init + + has + + @@ -856,6 +876,11 @@ no more namespaces available for dlmopen()")); + /* See if an error occurred during loading. */ + if (__glibc_unlikely (exception.errstring != NULL)) + { + + /* Avoid keeping around a dangling reference to the libc.so link + + map in case it has been cached in libc_map. */ + + if (!args.libc_already_loaded) + + GL(dl_ns)[nsid].libc_map = NULL; + + + + do_dlopen calls _dl_open with nsid == __LM_ID_CALLER (-2), which calls + dl_open_worker with args.nsid = nsid. dl_open_worker updates args.nsid + if it is __LM_ID_CALLER. After dl_open_worker returns, it is wrong to + use nsid. + + Replace nsid with args.nsid after dl_open_worker returns. This fixes + BZ #27609. + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 661a2172d1789b26..b5a4da04907d8d29 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -916,7 +916,7 @@ no more namespaces available for dlmopen()")); + /* Avoid keeping around a dangling reference to the libc.so link + map in case it has been cached in libc_map. */ + if (!args.libc_already_loaded) +- GL(dl_ns)[nsid].libc_map = NULL; ++ GL(dl_ns)[args.nsid].libc_map = NULL; + + /* Remove the object from memory. It may be in an inconsistent + state if relocation failed, for example. */ diff --git a/glibc-rh2047981-12.patch b/glibc-rh2047981-12.patch new file mode 100644 index 0000000..8588aaa --- /dev/null +++ b/glibc-rh2047981-12.patch @@ -0,0 +1,607 @@ +This is a partial backport of this commit with only the 'scope' +refactoring required to have access to the outer scope value +to use with RESOLVE_MAP to implement la_symbind for BIND_NOW. + +We do not backport this entire patch because the nested function +changes have significant impact on code generation and would +require furhter backports to support and maintain. + +commit 490e6c62aa31a8aa5c4a059f6e646ede121edf0a +Author: Fangrui Song +Date: Thu Oct 7 11:55:02 2021 -0700 + + elf: Avoid nested functions in the loader [BZ #27220] + + dynamic-link.h is included more than once in some elf/ files (rtld.c, + dl-conflict.c, dl-reloc.c, dl-reloc-static-pie.c) and uses GCC nested + functions. This harms readability and the nested functions usage + is the biggest obstacle prevents Clang build (Clang doesn't support GCC + nested functions). + + The key idea for unnesting is to add extra parameters (struct link_map + *and struct r_scope_elm *[]) to RESOLVE_MAP, + ELF_MACHINE_BEFORE_RTLD_RELOC, ELF_DYNAMIC_RELOCATE, elf_machine_rel[a], + elf_machine_lazy_rel, and elf_machine_runtime_setup. (This is inspired + by Stan Shebs' ppc64/x86-64 implementation in the + google/grte/v5-2.27/master which uses mixed extra parameters and static + variables.) + + Future simplification: + * If mips elf_machine_runtime_setup no longer needs RESOLVE_GOTSYM, + elf_machine_runtime_setup can drop the `scope` parameter. + * If TLSDESC no longer need to be in elf_machine_lazy_rel, + elf_machine_lazy_rel can drop the `scope` parameter. + + Tested on aarch64, i386, x86-64, powerpc64le, powerpc64, powerpc32, + sparc64, sparcv9, s390x, s390, hppa, ia64, armhf, alpha, and mips64. + In addition, tested build-many-glibcs.py with {arc,csky,microblaze,nios2}-linux-gnu + and riscv64-linux-gnu-rv64imafdc-lp64d. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-conflict.c b/elf/dl-conflict.c +index 70f14b04cd383048..31d87ac846427752 100644 +--- a/elf/dl-conflict.c ++++ b/elf/dl-conflict.c +@@ -40,7 +40,7 @@ _dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict, + data. */ + + /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */ +-#define RESOLVE_MAP(ref, version, flags) (*ref = NULL, NULL) ++#define RESOLVE_MAP(map, scope, ref, version, flags) (*ref = NULL, NULL) + #define RESOLVE(ref, version, flags) (*ref = NULL, 0) + #define RESOLVE_CONFLICT_FIND_MAP(map, r_offset) \ + do { \ +@@ -67,8 +67,8 @@ _dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict, + GL(dl_num_cache_relocations) += conflictend - conflict; + + for (; conflict < conflictend; ++conflict) +- elf_machine_rela (l, conflict, NULL, NULL, (void *) conflict->r_offset, +- 0); ++ elf_machine_rela (l, NULL, conflict, NULL, NULL, ++ (void *) conflict->r_offset, 0); + } + #endif + } +diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c +index ab1ce0eacced9d2b..1efbf515c3c1c16d 100644 +--- a/elf/dl-reloc-static-pie.c ++++ b/elf/dl-reloc-static-pie.c +@@ -30,7 +30,7 @@ _dl_relocate_static_pie (void) + + # define STATIC_PIE_BOOTSTRAP + # define BOOTSTRAP_MAP (main_map) +-# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP ++# define RESOLVE_MAP(map, scope, sym, version, flags) BOOTSTRAP_MAP + # include "dynamic-link.h" + + /* Figure out the run-time load address of static PIE. */ +@@ -46,7 +46,7 @@ _dl_relocate_static_pie (void) + + /* Relocate ourselves so we can do normal function calls and + data access using the global offset table. */ +- ELF_DYNAMIC_RELOCATE (main_map, 0, 0, 0); ++ ELF_DYNAMIC_RELOCATE (main_map, NULL, 0, 0, 0); + main_map->l_relocated = 1; + + /* Initialize _r_debug. */ +diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c +index c6139b89d4ecddc8..19de5de067a5ef07 100644 +--- a/elf/dl-reloc.c ++++ b/elf/dl-reloc.c +@@ -250,7 +250,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); + + /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */ +-#define RESOLVE_MAP(ref, version, r_type) \ ++#define RESOLVE_MAP(l, scope, ref, version, r_type) \ + ((ELFW(ST_BIND) ((*ref)->st_info) != STB_LOCAL \ + && __glibc_likely (!dl_symbol_visibility_binds_local_p (*ref))) \ + ? ((__builtin_expect ((*ref) == l->l_lookup_cache.sym, 0) \ +@@ -275,7 +275,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + + #include "dynamic-link.h" + +- ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc); ++ ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc); + + #ifndef PROF + if (__glibc_unlikely (consider_profiling) +diff --git a/elf/do-rel.h b/elf/do-rel.h +index 19cb5d236ee30698..0b04d1a0bf28b9f4 100644 +--- a/elf/do-rel.h ++++ b/elf/do-rel.h +@@ -38,7 +38,7 @@ + than fully resolved now. */ + + auto inline void __attribute__ ((always_inline)) +-elf_dynamic_do_Rel (struct link_map *map, ++elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[], + ElfW(Addr) reladdr, ElfW(Addr) relsize, + __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative, + int lazy, int skip_ifunc) +@@ -68,13 +68,13 @@ elf_dynamic_do_Rel (struct link_map *map, + } + else + # endif +- elf_machine_lazy_rel (map, l_addr, r, skip_ifunc); ++ elf_machine_lazy_rel (map, scope, l_addr, r, skip_ifunc); + + # ifdef ELF_MACHINE_IRELATIVE + if (r2 != NULL) + for (; r2 <= end2; ++r2) + if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE) +- elf_machine_lazy_rel (map, l_addr, r2, skip_ifunc); ++ elf_machine_lazy_rel (map, scope, l_addr, r2, skip_ifunc); + # endif + } + else +@@ -134,7 +134,7 @@ elf_dynamic_do_Rel (struct link_map *map, + #endif + + ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff; +- elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], ++ elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)], + &map->l_versions[ndx], + (void *) (l_addr + r->r_offset), skip_ifunc); + } +@@ -146,7 +146,7 @@ elf_dynamic_do_Rel (struct link_map *map, + { + ElfW(Half) ndx + = version[ELFW(R_SYM) (r2->r_info)] & 0x7fff; +- elf_machine_rel (map, r2, ++ elf_machine_rel (map, scope, r2, + &symtab[ELFW(R_SYM) (r2->r_info)], + &map->l_versions[ndx], + (void *) (l_addr + r2->r_offset), +@@ -167,14 +167,14 @@ elf_dynamic_do_Rel (struct link_map *map, + } + else + # endif +- elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, ++ elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, + (void *) (l_addr + r->r_offset), skip_ifunc); + + # ifdef ELF_MACHINE_IRELATIVE + if (r2 != NULL) + for (; r2 <= end2; ++r2) + if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE) +- elf_machine_rel (map, r2, &symtab[ELFW(R_SYM) (r2->r_info)], ++ elf_machine_rel (map, scope, r2, &symtab[ELFW(R_SYM) (r2->r_info)], + NULL, (void *) (l_addr + r2->r_offset), + skip_ifunc); + # endif +diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h +index 2fc3c91b7defe84e..357a2e3c6825e0fc 100644 +--- a/elf/dynamic-link.h ++++ b/elf/dynamic-link.h +@@ -60,8 +60,9 @@ int _dl_try_allocate_static_tls (struct link_map *map, bool optional) + unaligned cases. */ + # if ! ELF_MACHINE_NO_REL + auto inline void __attribute__((always_inline)) +-elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc, +- const ElfW(Sym) *sym, const struct r_found_version *version, ++elf_machine_rel (struct link_map *map, struct r_scope_elem *scope[], ++ const ElfW(Rel) *reloc, const ElfW(Sym) *sym, ++ const struct r_found_version *version, + void *const reloc_addr, int skip_ifunc); + auto inline void __attribute__((always_inline)) + elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc, +@@ -69,8 +70,9 @@ elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc, + # endif + # if ! ELF_MACHINE_NO_RELA + auto inline void __attribute__((always_inline)) +-elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, +- const ElfW(Sym) *sym, const struct r_found_version *version, ++elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[], ++ const ElfW(Rela) *reloc, const ElfW(Sym) *sym, ++ const struct r_found_version *version, + void *const reloc_addr, int skip_ifunc); + auto inline void __attribute__((always_inline)) + elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc, +@@ -78,12 +80,12 @@ elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc, + # endif + # if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL + auto inline void __attribute__((always_inline)) +-elf_machine_lazy_rel (struct link_map *map, ++elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[], + ElfW(Addr) l_addr, const ElfW(Rel) *reloc, + int skip_ifunc); + # else + auto inline void __attribute__((always_inline)) +-elf_machine_lazy_rel (struct link_map *map, ++elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[], + ElfW(Addr) l_addr, const ElfW(Rela) *reloc, + int skip_ifunc); + # endif +@@ -114,7 +116,7 @@ elf_machine_lazy_rel (struct link_map *map, + consumes precisely the very end of the DT_REL*, or DT_JMPREL and DT_REL* + are completely separate and there is a gap between them. */ + +-# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \ ++# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, scope, do_lazy, skip_ifunc, test_rel) \ + do { \ + struct { ElfW(Addr) start, size; \ + __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; } \ +@@ -152,13 +154,13 @@ elf_machine_lazy_rel (struct link_map *map, + } \ + \ + if (ELF_DURING_STARTUP) \ +- elf_dynamic_do_##reloc ((map), ranges[0].start, ranges[0].size, \ ++ elf_dynamic_do_##reloc ((map), scope, ranges[0].start, ranges[0].size, \ + ranges[0].nrelative, 0, skip_ifunc); \ + else \ + { \ + int ranges_index; \ + for (ranges_index = 0; ranges_index < 2; ++ranges_index) \ +- elf_dynamic_do_##reloc ((map), \ ++ elf_dynamic_do_##reloc ((map), scope, \ + ranges[ranges_index].start, \ + ranges[ranges_index].size, \ + ranges[ranges_index].nrelative, \ +@@ -175,29 +177,29 @@ elf_machine_lazy_rel (struct link_map *map, + + # if ! ELF_MACHINE_NO_REL + # include "do-rel.h" +-# define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) \ +- _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, lazy, skip_ifunc, _ELF_CHECK_REL) ++# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) \ ++ _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, scope, lazy, skip_ifunc, _ELF_CHECK_REL) + # else +-# define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) /* Nothing to do. */ ++# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) /* Nothing to do. */ + # endif + + # if ! ELF_MACHINE_NO_RELA + # define DO_RELA + # include "do-rel.h" +-# define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) \ +- _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, lazy, skip_ifunc, _ELF_CHECK_REL) ++# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) \ ++ _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, scope, lazy, skip_ifunc, _ELF_CHECK_REL) + # else +-# define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) /* Nothing to do. */ ++# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) /* Nothing to do. */ + # endif + + /* This can't just be an inline function because GCC is too dumb + to inline functions containing inlines themselves. */ +-# define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile, skip_ifunc) \ ++# define ELF_DYNAMIC_RELOCATE(map, scope, lazy, consider_profile, skip_ifunc) \ + do { \ +- int edr_lazy = elf_machine_runtime_setup ((map), (lazy), \ ++ int edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy), \ + (consider_profile)); \ +- ELF_DYNAMIC_DO_REL ((map), edr_lazy, skip_ifunc); \ +- ELF_DYNAMIC_DO_RELA ((map), edr_lazy, skip_ifunc); \ ++ ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, skip_ifunc); \ ++ ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, skip_ifunc); \ + } while (0) + + #endif +diff --git a/elf/rtld.c b/elf/rtld.c +index e107af4014d43777..f3836b8a78faaf27 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -514,7 +514,7 @@ _dl_start (void *arg) + is trivial: always the map of ld.so itself. */ + #define RTLD_BOOTSTRAP + #define BOOTSTRAP_MAP (&bootstrap_map) +-#define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP ++#define RESOLVE_MAP(map, scope, sym, version, flags) BOOTSTRAP_MAP + #include "dynamic-link.h" + + #ifdef DONT_USE_BOOTSTRAP_MAP +@@ -560,7 +560,7 @@ _dl_start (void *arg) + /* Relocate ourselves so we can do normal function calls and + data access using the global offset table. */ + +- ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0, 0); ++ ELF_DYNAMIC_RELOCATE (&bootstrap_map, NULL, 0, 0, 0); + } + bootstrap_map.l_relocated = 1; + +diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h +index 3fd3c8a265d012b1..5eab544afe2717f7 100644 +--- a/sysdeps/aarch64/dl-machine.h ++++ b/sysdeps/aarch64/dl-machine.h +@@ -65,7 +65,8 @@ elf_machine_load_address (void) + entries will jump to the on-demand fixup code in dl-runtime.c. */ + + static inline int __attribute__ ((unused)) +-elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) ++elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], ++ int lazy, int profile) + { + if (l->l_info[DT_JMPREL] && lazy) + { +@@ -242,8 +243,9 @@ elf_machine_plt_value (struct link_map *map, + + auto inline void + __attribute__ ((always_inline)) +-elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, +- const ElfW(Sym) *sym, const struct r_found_version *version, ++elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[], ++ const ElfW(Rela) *reloc, const ElfW(Sym) *sym, ++ const struct r_found_version *version, + void *const reloc_addr_arg, int skip_ifunc) + { + ElfW(Addr) *const reloc_addr = reloc_addr_arg; +@@ -256,7 +258,8 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, + else + { + const ElfW(Sym) *const refsym = sym; +- struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); ++ struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version, ++ r_type); + ElfW(Addr) value = SYMBOL_ADDRESS (sym_map, sym, true); + + if (sym != NULL +@@ -381,7 +384,7 @@ elf_machine_rela_relative (ElfW(Addr) l_addr, + + inline void + __attribute__ ((always_inline)) +-elf_machine_lazy_rel (struct link_map *map, ++elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[], + ElfW(Addr) l_addr, + const ElfW(Rela) *reloc, + int skip_ifunc) +@@ -408,7 +411,7 @@ elf_machine_lazy_rel (struct link_map *map, + (const void *)D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); + version = &map->l_versions[vernum[symndx] & 0x7fff]; + } +- elf_machine_rela (map, reloc, sym, version, reloc_addr, ++ elf_machine_rela (map, scope, reloc, sym, version, reloc_addr, + skip_ifunc); + return; + } +@@ -435,7 +438,7 @@ elf_machine_lazy_rel (struct link_map *map, + + /* Always initialize TLS descriptors completely, because lazy + initialization requires synchronization at every TLS access. */ +- elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc); ++ elf_machine_rela (map, scope, reloc, sym, version, reloc_addr, skip_ifunc); + } + else if (__glibc_unlikely (r_type == AARCH64_R(IRELATIVE))) + { +diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h +index 3a30671591284d79..5ba95b9e4af49942 100644 +--- a/sysdeps/i386/dl-machine.h ++++ b/sysdeps/i386/dl-machine.h +@@ -61,7 +61,8 @@ elf_machine_load_address (void) + entries will jump to the on-demand fixup code in dl-runtime.c. */ + + static inline int __attribute__ ((unused, always_inline)) +-elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) ++elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], ++ int lazy, int profile) + { + Elf32_Addr *got; + extern void _dl_runtime_resolve (Elf32_Word) attribute_hidden; +@@ -293,8 +294,9 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc, + + auto inline void + __attribute ((always_inline)) +-elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, +- const Elf32_Sym *sym, const struct r_found_version *version, ++elf_machine_rel (struct link_map *map, struct r_scope_elem *scope[], ++ const Elf32_Rel *reloc, const Elf32_Sym *sym, ++ const struct r_found_version *version, + void *const reloc_addr_arg, int skip_ifunc) + { + Elf32_Addr *const reloc_addr = reloc_addr_arg; +@@ -327,7 +329,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, + # ifndef RTLD_BOOTSTRAP + const Elf32_Sym *const refsym = sym; + # endif +- struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); ++ struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version, ++ r_type); + Elf32_Addr value = SYMBOL_ADDRESS (sym_map, sym, true); + + if (sym != NULL +@@ -493,8 +496,9 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, + # ifndef RTLD_BOOTSTRAP + auto inline void + __attribute__ ((always_inline)) +-elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, +- const Elf32_Sym *sym, const struct r_found_version *version, ++elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[], ++ const Elf32_Rela *reloc, const Elf32_Sym *sym, ++ const struct r_found_version *version, + void *const reloc_addr_arg, int skip_ifunc) + { + Elf32_Addr *const reloc_addr = reloc_addr_arg; +@@ -507,7 +511,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, + # ifndef RESOLVE_CONFLICT_FIND_MAP + const Elf32_Sym *const refsym = sym; + # endif +- struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); ++ struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version, ++ r_type); + Elf32_Addr value = SYMBOL_ADDRESS (sym_map, sym, true); + + if (sym != NULL +@@ -661,7 +666,7 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc, + + auto inline void + __attribute__ ((always_inline)) +-elf_machine_lazy_rel (struct link_map *map, ++elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[], + Elf32_Addr l_addr, const Elf32_Rel *reloc, + int skip_ifunc) + { +@@ -696,13 +701,13 @@ elf_machine_lazy_rel (struct link_map *map, + const ElfW(Half) *const version = + (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]); + ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff; +- elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], ++ elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)], + &map->l_versions[ndx], + (void *) (l_addr + r->r_offset), skip_ifunc); + } + # ifndef RTLD_BOOTSTRAP + else +- elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, ++ elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, + (void *) (l_addr + r->r_offset), skip_ifunc); + # endif + } +@@ -721,7 +726,7 @@ elf_machine_lazy_rel (struct link_map *map, + + auto inline void + __attribute__ ((always_inline)) +-elf_machine_lazy_rela (struct link_map *map, ++elf_machine_lazy_rela (struct link_map *map, struct r_scope_elem *scope[], + Elf32_Addr l_addr, const Elf32_Rela *reloc, + int skip_ifunc) + { +@@ -745,7 +750,8 @@ elf_machine_lazy_rela (struct link_map *map, + + /* Always initialize TLS descriptors completely at load time, in + case static TLS is allocated for it that requires locking. */ +- elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc); ++ elf_machine_rela (map, scope, reloc, sym, version, reloc_addr, ++ skip_ifunc); + } + else if (__glibc_unlikely (r_type == R_386_IRELATIVE)) + { +diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h +index 99a83d0c82ea0a9c..35996bb9173da231 100644 +--- a/sysdeps/powerpc/powerpc64/dl-machine.h ++++ b/sysdeps/powerpc/powerpc64/dl-machine.h +@@ -345,7 +345,8 @@ dl_platform_init (void) + /* Set up the loaded object described by MAP so its unrelocated PLT + entries will jump to the on-demand fixup code in dl-runtime.c. */ + static inline int __attribute__ ((always_inline)) +-elf_machine_runtime_setup (struct link_map *map, int lazy, int profile) ++elf_machine_runtime_setup (struct link_map *map, struct r_scope_elem *scope[], ++ int lazy, int profile) + { + if (map->l_info[DT_JMPREL]) + { +@@ -679,7 +680,7 @@ resolve_ifunc (Elf64_Addr value, + /* Perform the relocation specified by RELOC and SYM (which is fully + resolved). MAP is the object containing the reloc. */ + auto inline void __attribute__ ((always_inline)) +-elf_machine_rela (struct link_map *map, ++elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[], + const Elf64_Rela *reloc, + const Elf64_Sym *sym, + const struct r_found_version *version, +@@ -707,7 +708,7 @@ elf_machine_rela (struct link_map *map, + + /* We need SYM_MAP even in the absence of TLS, for elf_machine_fixup_plt + and STT_GNU_IFUNC. */ +- struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); ++ struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version, r_type); + Elf64_Addr value = SYMBOL_ADDRESS (sym_map, sym, true) + reloc->r_addend; + + if (sym != NULL +@@ -1036,7 +1037,7 @@ elf_machine_rela (struct link_map *map, + } + + auto inline void __attribute__ ((always_inline)) +-elf_machine_lazy_rel (struct link_map *map, ++elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[], + Elf64_Addr l_addr, const Elf64_Rela *reloc, + int skip_ifunc) + { +diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h +index f22db7860b4da3ec..36327c40a1972dd7 100644 +--- a/sysdeps/s390/s390-64/dl-machine.h ++++ b/sysdeps/s390/s390-64/dl-machine.h +@@ -75,7 +75,8 @@ elf_machine_load_address (void) + entries will jump to the on-demand fixup code in dl-runtime.c. */ + + static inline int __attribute__ ((unused)) +-elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) ++elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], ++ int lazy, int profile) + { + extern void _dl_runtime_resolve (Elf64_Word); + extern void _dl_runtime_profile (Elf64_Word); +@@ -270,8 +271,9 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc, + + auto inline void + __attribute__ ((always_inline)) +-elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, +- const Elf64_Sym *sym, const struct r_found_version *version, ++elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[], ++ const Elf64_Rela *reloc, const Elf64_Sym *sym, ++ const struct r_found_version *version, + void *const reloc_addr_arg, int skip_ifunc) + { + Elf64_Addr *const reloc_addr = reloc_addr_arg; +@@ -304,7 +306,8 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, + /* Only needed for R_390_COPY below. */ + const Elf64_Sym *const refsym = sym; + #endif +- struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); ++ struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version, ++ r_type); + Elf64_Addr value = SYMBOL_ADDRESS (sym_map, sym, true); + + if (sym != NULL +@@ -449,7 +452,7 @@ elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc, + + auto inline void + __attribute__ ((always_inline)) +-elf_machine_lazy_rel (struct link_map *map, ++elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[], + Elf64_Addr l_addr, const Elf64_Rela *reloc, + int skip_ifunc) + { +diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h +index b94d3b39ec1dca64..5262aa69c06aa8db 100644 +--- a/sysdeps/x86_64/dl-machine.h ++++ b/sysdeps/x86_64/dl-machine.h +@@ -62,7 +62,8 @@ elf_machine_load_address (void) + entries will jump to the on-demand fixup code in dl-runtime.c. */ + + static inline int __attribute__ ((unused, always_inline)) +-elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) ++elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], ++ int lazy, int profile) + { + Elf64_Addr *got; + extern void _dl_runtime_resolve_fxsave (ElfW(Word)) attribute_hidden; +@@ -260,8 +261,9 @@ elf_machine_plt_value (struct link_map *map, const ElfW(Rela) *reloc, + + auto inline void + __attribute__ ((always_inline)) +-elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, +- const ElfW(Sym) *sym, const struct r_found_version *version, ++elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[], ++ const ElfW(Rela) *reloc, const ElfW(Sym) *sym, ++ const struct r_found_version *version, + void *const reloc_addr_arg, int skip_ifunc) + { + ElfW(Addr) *const reloc_addr = reloc_addr_arg; +@@ -300,7 +302,7 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, + # ifndef RTLD_BOOTSTRAP + const ElfW(Sym) *const refsym = sym; + # endif +- struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); ++ struct link_map *sym_map = RESOLVE_MAP (map, scope, &sym, version, r_type); + ElfW(Addr) value = SYMBOL_ADDRESS (sym_map, sym, true); + + if (sym != NULL +@@ -539,7 +541,7 @@ elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc, + + auto inline void + __attribute ((always_inline)) +-elf_machine_lazy_rel (struct link_map *map, ++elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[], + ElfW(Addr) l_addr, const ElfW(Rela) *reloc, + int skip_ifunc) + { +@@ -573,7 +575,7 @@ elf_machine_lazy_rel (struct link_map *map, + + /* Always initialize TLS descriptors completely at load time, in + case static TLS is allocated for it that requires locking. */ +- elf_machine_rela (map, reloc, sym, version, reloc_addr, skip_ifunc); ++ elf_machine_rela (map, scope, reloc, sym, version, reloc_addr, skip_ifunc); + } + else if (__glibc_unlikely (r_type == R_X86_64_IRELATIVE)) + { diff --git a/glibc-rh2047981-13.patch b/glibc-rh2047981-13.patch new file mode 100644 index 0000000..d67e40f --- /dev/null +++ b/glibc-rh2047981-13.patch @@ -0,0 +1,65 @@ +commit 54816ae98d57930b7c945f17485714a5574bfe47 +Author: Adhemerval Zanella +Date: Thu Jul 29 11:13:57 2021 -0300 + + elf: Move LAV_CURRENT to link_lavcurrent.h + + No functional change. + +diff --git a/bits/link_lavcurrent.h b/bits/link_lavcurrent.h +new file mode 100644 +index 0000000000000000..44fbea1e8060997f +--- /dev/null ++++ b/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) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _LINK_H ++# error "Never include directly; use instead." ++#endif ++ ++/* Version numbers for la_version handshake interface. */ ++#define LAV_CURRENT 1 +diff --git a/elf/Makefile b/elf/Makefile +index 6262a4a65cfd2148..b9751e8bd87c4f71 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -21,7 +21,7 @@ subdir := elf + + include ../Makeconfig + +-headers = elf.h bits/elfclass.h link.h bits/link.h ++headers = elf.h bits/elfclass.h link.h bits/link.h bits/link_lavcurrent.h + routines = $(all-dl-routines) dl-support dl-iteratephdr \ + dl-addr dl-addr-obj enbl-secure dl-profstub \ + dl-origin dl-libc dl-sym dl-sysdep dl-error \ +diff --git a/elf/link.h b/elf/link.h +index c67a50dd8ee9187e..cbda60b4135997f6 100644 +--- a/elf/link.h ++++ b/elf/link.h +@@ -96,7 +96,7 @@ struct link_map + #ifdef __USE_GNU + + /* Version numbers for la_version handshake interface. */ +-#define LAV_CURRENT 1 ++#include + + /* Activity types signaled through la_activity. */ + enum diff --git a/glibc-rh2047981-14.patch b/glibc-rh2047981-14.patch new file mode 100644 index 0000000..1d1295c --- /dev/null +++ b/glibc-rh2047981-14.patch @@ -0,0 +1,388 @@ +Added $(objpfx)tst-audit18: $(libdl) in elf/Makefile since +we still have $(libdl) in RHEL8. + +commit ed3ce71f5c64c5f07cbde0ef03554ea8950d8f2c +Author: Adhemerval Zanella +Date: Thu Nov 11 09:28:21 2021 -0300 + + elf: Move la_activity (LA_ACT_ADD) after _dl_add_to_namespace_list() (BZ #28062) + + It ensures that the the namespace is guaranteed to not be empty. + + Checked on x86_64-linux-gnu. + + Reviewed-by: Florian Weimer + +Conflicts: + elf/Makefile + elf/dl-load.c + Conflict with missing MAP_ANON removal. + +diff --git a/elf/Makefile b/elf/Makefile +index b9751e8bd87c4f71..2312184692433313 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -219,6 +219,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-dlmopen-dlerror \ + tst-dlmopen-gethostbyname \ + tst-audit17 \ ++ tst-audit18 \ + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -354,6 +355,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + libmarkermod5-5 tst-tls20mod-bad tst-tls21mod \ + tst-dlmopen-dlerror-mod \ + tst-dlmopen-gethostbyname-mod \ ++ tst-auditmod18 \ ++ tst-audit18mod \ + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +@@ -1539,6 +1542,11 @@ $(objpfx)tst-auditmod17.so: $(objpfx)tst-auditmod17.os + CFLAGS-.os += $(call elide-stack-protector,.os,tst-auditmod17) + tst-audit17-ENV = LD_AUDIT=$(objpfx)tst-auditmod17.so + ++$(objpfx)tst-audit18: $(libdl) ++$(objpfx)tst-audit18.out: $(objpfx)tst-auditmod18.so \ ++ $(objpfx)tst-audit18mod.so ++tst-audit18-ARGS = -- $(host-test-program-cmd) ++ + # tst-sonamemove links against an older implementation of the library. + LDFLAGS-tst-sonamemove-linkmod1.so = \ + -Wl,--version-script=tst-sonamemove-linkmod1.map \ +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 303e6594f9af9b7e..de5aef5777045da5 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -978,42 +978,6 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd, + } + #endif + +- /* Signal that we are going to add new objects. */ +- if (r->r_state == RT_CONSISTENT) +- { +-#ifdef SHARED +- /* Auditing checkpoint: we are going to add new objects. */ +- if ((mode & __RTLD_AUDIT) == 0 +- && __glibc_unlikely (GLRO(dl_naudit) > 0)) +- { +- struct link_map *head = GL(dl_ns)[nsid]._ns_loaded; +- /* Do not call the functions for any auditing object. */ +- if (head->l_auditing == 0) +- { +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->activity != NULL) +- afct->activity (&link_map_audit_state (head, cnt)->cookie, +- LA_ACT_ADD); +- +- afct = afct->next; +- } +- } +- } +-#endif +- +- /* Notify the debugger we have added some objects. We need to +- call _dl_debug_initialize in a static program in case dynamic +- linking has not been used before. */ +- r->r_state = RT_ADD; +- _dl_debug_state (); +- LIBC_PROBE (map_start, 2, nsid, r); +- make_consistent = true; +- } +- else +- assert (r->r_state == RT_ADD); +- + /* Enter the new object in the list of loaded objects. */ + l = _dl_new_object (realname, name, l_type, loader, mode, nsid); + if (__glibc_unlikely (l == NULL)) +@@ -1432,6 +1396,44 @@ cannot enable executable stack as shared object requires"); + /* Now that the object is fully initialized add it to the object list. */ + _dl_add_to_namespace_list (l, nsid); + ++ /* Signal that we are going to add new objects. */ ++ if (r->r_state == RT_CONSISTENT) ++ { ++#ifdef SHARED ++ /* Auditing checkpoint: we are going to add new objects. Since this ++ is called after _dl_add_to_namespace_list the namespace is guaranteed ++ to not be empty. */ ++ if ((mode & __RTLD_AUDIT) == 0 ++ && __glibc_unlikely (GLRO(dl_naudit) > 0)) ++ { ++ struct link_map *head = GL(dl_ns)[nsid]._ns_loaded; ++ /* Do not call the functions for any auditing object. */ ++ if (head->l_auditing == 0) ++ { ++ struct audit_ifaces *afct = GLRO(dl_audit); ++ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ { ++ if (afct->activity != NULL) ++ afct->activity (&link_map_audit_state (head, cnt)->cookie, ++ LA_ACT_ADD); ++ ++ afct = afct->next; ++ } ++ } ++ } ++#endif ++ ++ /* Notify the debugger we have added some objects. We need to ++ call _dl_debug_initialize in a static program in case dynamic ++ linking has not been used before. */ ++ r->r_state = RT_ADD; ++ _dl_debug_state (); ++ LIBC_PROBE (map_start, 2, nsid, r); ++ make_consistent = true; ++ } ++ else ++ assert (r->r_state == RT_ADD); ++ + #ifdef SHARED + /* Auditing checkpoint: we have a new object. */ + if (__glibc_unlikely (GLRO(dl_naudit) > 0) +diff --git a/elf/tst-audit18.c b/elf/tst-audit18.c +new file mode 100644 +index 0000000000000000..ef784908f60d50aa +--- /dev/null ++++ b/elf/tst-audit18.c +@@ -0,0 +1,129 @@ ++/* Check DT_AUDIT with dlmopen. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int restart; ++#define CMDLINE_OPTIONS \ ++ { "restart", no_argument, &restart, 1 }, ++ ++static int ++handle_restart (void) ++{ ++ { ++ void *h = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW); ++ ++ pid_t (*s) (void) = xdlsym (h, "getpid"); ++ TEST_COMPARE (s (), getpid ()); ++ ++ xdlclose (h); ++ } ++ ++ { ++ void *h = xdlmopen (LM_ID_NEWLM, "tst-audit18mod.so", RTLD_NOW); ++ ++ int (*foo) (void) = xdlsym (h, "foo"); ++ TEST_COMPARE (foo (), 10); ++ ++ xdlclose (h); ++ } ++ ++ return 0; ++} ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ /* We must have either: ++ - One our fource parameters left if called initially: ++ + path to ld.so optional ++ + "--library-path" optional ++ + the library path optional ++ + the application name */ ++ ++ if (restart) ++ return handle_restart (); ++ ++ char *spargv[9]; ++ int i = 0; ++ for (; i < argc - 1; i++) ++ spargv[i] = argv[i + 1]; ++ spargv[i++] = (char *) "--direct"; ++ spargv[i++] = (char *) "--restart"; ++ spargv[i] = NULL; ++ ++ setenv ("LD_AUDIT", "tst-auditmod18.so", 0); ++ struct support_capture_subprocess result ++ = support_capture_subprogram (spargv[0], spargv); ++ support_capture_subprocess_check (&result, "tst-audit18", 0, sc_allow_stderr); ++ ++ struct ++ { ++ const char *name; ++ bool found; ++ } audit_iface[] = ++ { ++ { "la_version", false }, ++ { "la_objsearch", false }, ++ { "la_activity", false }, ++ { "la_objopen", false }, ++ { "la_objclose", false }, ++ { "la_preinit", false }, ++#if __WORDSIZE == 32 ++ { "la_symbind32", false }, ++#elif __WORDSIZE == 64 ++ { "la_symbind64", false }, ++#endif ++ }; ++ ++ /* Some hooks are called more than once but the test only check if any ++ is called at least once. */ ++ FILE *out = fmemopen (result.err.buffer, result.err.length, "r"); ++ TEST_VERIFY (out != NULL); ++ char *buffer = NULL; ++ size_t buffer_length = 0; ++ while (xgetline (&buffer, &buffer_length, out)) ++ { ++ for (int i = 0; i < array_length (audit_iface); i++) ++ if (strncmp (buffer, audit_iface[i].name, ++ strlen (audit_iface[i].name)) == 0) ++ audit_iface[i].found = true; ++ } ++ free (buffer); ++ xfclose (out); ++ ++ for (int i = 0; i < array_length (audit_iface); i++) ++ TEST_COMPARE (audit_iface[i].found, true); ++ ++ support_capture_subprocess_free (&result); ++ ++ return 0; ++} ++ ++#define TEST_FUNCTION_ARGV do_test ++#include +diff --git a/elf/tst-audit18mod.c b/elf/tst-audit18mod.c +new file mode 100644 +index 0000000000000000..096a9167c9f8353f +--- /dev/null ++++ b/elf/tst-audit18mod.c +@@ -0,0 +1,23 @@ ++/* Check DT_AUDIT with dlmopen. ++ 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 ++ . */ ++ ++int ++foo (void) ++{ ++ return 10; ++} +diff --git a/elf/tst-auditmod18.c b/elf/tst-auditmod18.c +new file mode 100644 +index 0000000000000000..182992e9fdb1620c +--- /dev/null ++++ b/elf/tst-auditmod18.c +@@ -0,0 +1,73 @@ ++/* Check DT_AUDIT with dlmopen. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++unsigned int ++la_version (unsigned int version) ++{ ++ fprintf (stderr, "%s\n", __func__); ++ return LAV_CURRENT; ++} ++ ++char * ++la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) ++{ ++ fprintf (stderr, "%s\n", __func__); ++ return (char *) name; ++} ++ ++void ++la_activity (uintptr_t *cookie, unsigned int flag) ++{ ++ fprintf (stderr, "%s\n", __func__); ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ fprintf (stderr, "%s\n", __func__); ++ return LA_FLG_BINDTO | LA_FLG_BINDFROM; ++} ++ ++unsigned int ++la_objclose (uintptr_t *cookie) ++{ ++ fprintf (stderr, "%s\n", __func__); ++ return 0; ++} ++ ++void ++la_preinit (uintptr_t *cookie) ++{ ++ fprintf (stderr, "%s\n", __func__); ++} ++ ++uintptr_t ++#if __ELF_NATIVE_CLASS == 32 ++la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook, ++ uintptr_t *defcook, unsigned int *flags, const char *symname) ++#else ++la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, ++ uintptr_t *defcook, unsigned int *flags, const char *symname) ++#endif ++{ ++ fprintf (stderr, "%s\n", __func__); ++ return sym->st_value; ++} diff --git a/glibc-rh2047981-15.patch b/glibc-rh2047981-15.patch new file mode 100644 index 0000000..7da5392 --- /dev/null +++ b/glibc-rh2047981-15.patch @@ -0,0 +1,160 @@ +commit aee6e90f93e285016b6cd9c8bd00402c19ba271b +Author: Adhemerval Zanella +Date: Mon Jul 19 15:47:51 2021 -0300 + + elf: Add _dl_audit_objopen + + It consolidates the code required to call la_objopen audit callback. + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Florian Weimer + +Conflicts: + elf/Makefile + +diff --git a/elf/Makefile b/elf/Makefile +index 2312184692433313..08a32a712a34f2cc 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -64,7 +64,8 @@ elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ + # interpreter and operating independent of libc. + rtld-routines = rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal \ + dl-error-minimal dl-conflict dl-hwcaps dl-hwcaps_split dl-hwcaps-subdirs \ +- dl-usage dl-diagnostics dl-diagnostics-kernel dl-diagnostics-cpu ++ dl-usage dl-diagnostics dl-diagnostics-kernel dl-diagnostics-cpu \ ++ dl-audit + all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines) + + CFLAGS-dl-runtime.c += -fexceptions -fasynchronous-unwind-tables +diff --git a/elf/dl-audit.c b/elf/dl-audit.c +new file mode 100644 +index 0000000000000000..4066dfe85146b9d4 +--- /dev/null ++++ b/elf/dl-audit.c +@@ -0,0 +1,39 @@ ++/* Audit common functions. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++void ++_dl_audit_objopen (struct link_map *l, Lmid_t nsid) ++{ ++ if (__glibc_likely (GLRO(dl_naudit) == 0)) ++ return; ++ ++ struct audit_ifaces *afct = GLRO(dl_audit); ++ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ { ++ if (afct->objopen != NULL) ++ { ++ struct auditstate *state = link_map_audit_state (l, cnt); ++ state->bindflags = afct->objopen (l, nsid, &state->cookie); ++ l->l_audit_any_plt |= state->bindflags != 0; ++ } ++ ++ afct = afct->next; ++ } ++} +diff --git a/elf/dl-load.c b/elf/dl-load.c +index de5aef5777045da5..c11b1d1781e9b40b 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -1436,22 +1436,8 @@ cannot enable executable stack as shared object requires"); + + #ifdef SHARED + /* Auditing checkpoint: we have a new object. */ +- if (__glibc_unlikely (GLRO(dl_naudit) > 0) +- && !GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing) +- { +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->objopen != NULL) +- { +- struct auditstate *state = link_map_audit_state (l, cnt); +- state->bindflags = afct->objopen (l, nsid, &state->cookie); +- l->l_audit_any_plt |= state->bindflags != 0; +- } +- +- afct = afct->next; +- } +- } ++ if (!GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing) ++ _dl_audit_objopen (l, nsid); + #endif + + return l; +diff --git a/elf/rtld.c b/elf/rtld.c +index f3836b8a78faaf27..1982e42390760e0a 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1075,25 +1075,6 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d); + dlmargs.map->l_auditing = 1; + } + +-/* Notify the the audit modules that the object MAP has already been +- loaded. */ +-static void +-notify_audit_modules_of_loaded_object (struct link_map *map) +-{ +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->objopen != NULL) +- { +- struct auditstate *state = link_map_audit_state (map, cnt); +- state->bindflags = afct->objopen (map, LM_ID_BASE, &state->cookie); +- map->l_audit_any_plt |= state->bindflags != 0; +- } +- +- afct = afct->next; +- } +-} +- + /* Load all audit modules. */ + static void + load_audit_modules (struct link_map *main_map, struct audit_list *audit_list) +@@ -1112,8 +1093,8 @@ load_audit_modules (struct link_map *main_map, struct audit_list *audit_list) + program and the dynamic linker itself). */ + if (GLRO(dl_naudit) > 0) + { +- notify_audit_modules_of_loaded_object (main_map); +- notify_audit_modules_of_loaded_object (&GL(dl_rtld_map)); ++ _dl_audit_objopen (main_map, LM_ID_BASE); ++ _dl_audit_objopen (&GL(dl_rtld_map), LM_ID_BASE); + } + } + +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 2dd6f0c3c4aaaef5..410f070e28b74bdf 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1268,6 +1268,11 @@ link_map_audit_state (struct link_map *l, size_t index) + { + return &l->l_audit[index]; + } ++ ++/* Call the la_objopen from the audit modules for the link_map L on the ++ namespace identification NSID. */ ++void _dl_audit_objopen (struct link_map *l, Lmid_t nsid) ++ attribute_hidden; + #endif /* SHARED */ + + __END_DECLS diff --git a/glibc-rh2047981-16.patch b/glibc-rh2047981-16.patch new file mode 100644 index 0000000..eec1516 --- /dev/null +++ b/glibc-rh2047981-16.patch @@ -0,0 +1,253 @@ +commit 3dac3959a5cb585b065cef2cb8a8d909c907e202 +Author: Adhemerval Zanella +Date: Tue Jul 20 11:03:34 2021 -0300 + + elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid + + It consolidates the code required to call la_activity audit + callback. + + Also for a new Lmid_t the namespace link_map list are empty, so it + requires to check if before using it. This can happen for when audit + module is used along with dlmopen. + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Florian Weimer + +diff --git a/elf/dl-audit.c b/elf/dl-audit.c +index 4066dfe85146b9d4..74b87f4b39be75e1 100644 +--- a/elf/dl-audit.c ++++ b/elf/dl-audit.c +@@ -18,6 +18,32 @@ + + #include + ++void ++_dl_audit_activity_map (struct link_map *l, int action) ++{ ++ struct audit_ifaces *afct = GLRO(dl_audit); ++ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ { ++ if (afct->activity != NULL) ++ afct->activity (&link_map_audit_state (l, cnt)->cookie, action); ++ afct = afct->next; ++ } ++} ++ ++void ++_dl_audit_activity_nsid (Lmid_t nsid, int action) ++{ ++ /* If head is NULL, the namespace has become empty, and the audit interface ++ does not give us a way to signal LA_ACT_CONSISTENT for it because the ++ first loaded module is used to identify the namespace. */ ++ struct link_map *head = GL(dl_ns)[nsid]._ns_loaded; ++ if (__glibc_likely (GLRO(dl_naudit) == 0) ++ || head == NULL || head->l_auditing) ++ return; ++ ++ _dl_audit_activity_map (head, action); ++} ++ + void + _dl_audit_objopen (struct link_map *l, Lmid_t nsid) + { +diff --git a/elf/dl-close.c b/elf/dl-close.c +index 698bda929c0eab6c..1ba594b600c4c87a 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -478,25 +478,7 @@ _dl_close_worker (struct link_map *map, bool force) + + #ifdef SHARED + /* Auditing checkpoint: we will start deleting objects. */ +- if (__glibc_unlikely (do_audit)) +- { +- struct link_map *head = ns->_ns_loaded; +- struct audit_ifaces *afct = GLRO(dl_audit); +- /* Do not call the functions for any auditing object. */ +- if (head->l_auditing == 0) +- { +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->activity != NULL) +- { +- struct auditstate *state = link_map_audit_state (head, cnt); +- afct->activity (&state->cookie, LA_ACT_DELETE); +- } +- +- afct = afct->next; +- } +- } +- } ++ _dl_audit_activity_nsid (nsid, LA_ACT_DELETE); + #endif + + /* Notify the debugger we are about to remove some loaded objects. */ +@@ -791,32 +773,9 @@ _dl_close_worker (struct link_map *map, bool force) + __rtld_lock_unlock_recursive (GL(dl_load_tls_lock)); + + #ifdef SHARED +- /* Auditing checkpoint: we have deleted all objects. */ +- if (__glibc_unlikely (do_audit)) +- { +- struct link_map *head = ns->_ns_loaded; +- /* If head is NULL, the namespace has become empty, and the +- audit interface does not give us a way to signal +- LA_ACT_CONSISTENT for it because the first loaded module is +- used to identify the namespace. +- +- Furthermore, do not notify auditors of the cleanup of a +- failed audit module loading attempt. */ +- if (head != NULL && head->l_auditing == 0) +- { +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->activity != NULL) +- { +- struct auditstate *state = link_map_audit_state (head, cnt); +- afct->activity (&state->cookie, LA_ACT_CONSISTENT); +- } +- +- afct = afct->next; +- } +- } +- } ++ /* Auditing checkpoint: we have deleted all objects. Also, do not notify ++ auditors of the cleanup of a failed audit module loading attempt. */ ++ _dl_audit_activity_nsid (nsid, LA_ACT_CONSISTENT); + #endif + + if (__builtin_expect (ns->_ns_loaded == NULL, 0) +diff --git a/elf/dl-load.c b/elf/dl-load.c +index c11b1d1781e9b40b..8a18c761bb753e37 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -1403,24 +1403,8 @@ cannot enable executable stack as shared object requires"); + /* Auditing checkpoint: we are going to add new objects. Since this + is called after _dl_add_to_namespace_list the namespace is guaranteed + to not be empty. */ +- if ((mode & __RTLD_AUDIT) == 0 +- && __glibc_unlikely (GLRO(dl_naudit) > 0)) +- { +- struct link_map *head = GL(dl_ns)[nsid]._ns_loaded; +- /* Do not call the functions for any auditing object. */ +- if (head->l_auditing == 0) +- { +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->activity != NULL) +- afct->activity (&link_map_audit_state (head, cnt)->cookie, +- LA_ACT_ADD); +- +- afct = afct->next; +- } +- } +- } ++ if ((mode & __RTLD_AUDIT) == 0) ++ _dl_audit_activity_nsid (nsid, LA_ACT_ADD); + #endif + + /* Notify the debugger we have added some objects. We need to +diff --git a/elf/dl-open.c b/elf/dl-open.c +index b5a4da04907d8d29..660a56b2fb2639cd 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -598,25 +598,7 @@ dl_open_worker_begin (void *a) + + #ifdef SHARED + /* Auditing checkpoint: we have added all objects. */ +- if (__glibc_unlikely (GLRO(dl_naudit) > 0)) +- { +- struct link_map *head = GL(dl_ns)[new->l_ns]._ns_loaded; +- /* Do not call the functions for any auditing object. */ +- if (head->l_auditing == 0) +- { +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->activity != NULL) +- { +- struct auditstate *state = link_map_audit_state (head, cnt); +- afct->activity (&state->cookie, LA_ACT_CONSISTENT); +- } +- +- afct = afct->next; +- } +- } +- } ++ _dl_audit_activity_nsid (new->l_ns, LA_ACT_CONSISTENT); + #endif + + /* Notify the debugger all new objects are now ready to go. */ +diff --git a/elf/rtld.c b/elf/rtld.c +index 1982e42390760e0a..767acd122262b824 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1799,18 +1799,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + + /* Auditing checkpoint: we are ready to signal that the initial map + is being constructed. */ +- if (__glibc_unlikely (GLRO(dl_naudit) > 0)) +- { +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->activity != NULL) +- afct->activity (&link_map_audit_state (main_map, cnt)->cookie, +- LA_ACT_ADD); +- +- afct = afct->next; +- } +- } ++ _dl_audit_activity_map (main_map, LA_ACT_ADD); + + /* We have two ways to specify objects to preload: via environment + variable and via the file /etc/ld.so.preload. The latter can also +@@ -2484,23 +2473,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + + #ifdef SHARED + /* Auditing checkpoint: we have added all objects. */ +- if (__glibc_unlikely (GLRO(dl_naudit) > 0)) +- { +- struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded; +- /* Do not call the functions for any auditing object. */ +- if (head->l_auditing == 0) +- { +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->activity != NULL) +- afct->activity (&link_map_audit_state (head, cnt)->cookie, +- LA_ACT_CONSISTENT); +- +- afct = afct->next; +- } +- } +- } ++ _dl_audit_activity_nsid (LM_ID_BASE, LA_ACT_CONSISTENT); + #endif + + /* Notify the debugger all new objects are now ready to go. We must re-get +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 410f070e28b74bdf..05737342d6287233 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1269,6 +1269,16 @@ link_map_audit_state (struct link_map *l, size_t index) + return &l->l_audit[index]; + } + ++/* Call the la_activity from the audit modules from the link map L and issues ++ the ACTION argument. */ ++void _dl_audit_activity_map (struct link_map *l, int action) ++ attribute_hidden; ++ ++/* Call the la_activity from the audit modules from the link map from the ++ namespace NSID and issues the ACTION argument. */ ++void _dl_audit_activity_nsid (Lmid_t nsid, int action) ++ attribute_hidden; ++ + /* Call the la_objopen from the audit modules for the link_map L on the + namespace identification NSID. */ + void _dl_audit_objopen (struct link_map *l, Lmid_t nsid) diff --git a/glibc-rh2047981-17.patch b/glibc-rh2047981-17.patch new file mode 100644 index 0000000..4a22e82 --- /dev/null +++ b/glibc-rh2047981-17.patch @@ -0,0 +1,156 @@ +commit c91008d3490e4e3ce29520068405f081f0d368ca +Author: Adhemerval Zanella +Date: Tue Jul 20 13:47:36 2021 -0300 + + elf: Add _dl_audit_objsearch + + It consolidates the code required to call la_objsearch audit + callback. + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Florian Weimer + +diff --git a/elf/dl-audit.c b/elf/dl-audit.c +index 74b87f4b39be75e1..5682427220569d90 100644 +--- a/elf/dl-audit.c ++++ b/elf/dl-audit.c +@@ -44,6 +44,28 @@ _dl_audit_activity_nsid (Lmid_t nsid, int action) + _dl_audit_activity_map (head, action); + } + ++const char * ++_dl_audit_objsearch (const char *name, struct link_map *l, unsigned int code) ++{ ++ if (l == NULL || l->l_auditing || code == 0) ++ return name; ++ ++ struct audit_ifaces *afct = GLRO(dl_audit); ++ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ { ++ if (afct->objsearch != NULL) ++ { ++ struct auditstate *state = link_map_audit_state (l, cnt); ++ name = afct->objsearch (name, &state->cookie, code); ++ if (name == NULL) ++ return NULL; ++ } ++ afct = afct->next; ++ } ++ ++ return name; ++} ++ + void + _dl_audit_objopen (struct link_map *l, Lmid_t nsid) + { +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 8a18c761bb753e37..1613217a236c7fc3 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -1517,32 +1517,20 @@ open_verify (const char *name, int fd, + + #ifdef SHARED + /* Give the auditing libraries a chance. */ +- if (__glibc_unlikely (GLRO(dl_naudit) > 0) && whatcode != 0 +- && loader->l_auditing == 0) ++ if (__glibc_unlikely (GLRO(dl_naudit) > 0)) + { + const char *original_name = name; +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->objsearch != NULL) +- { +- struct auditstate *state = link_map_audit_state (loader, cnt); +- name = afct->objsearch (name, &state->cookie, whatcode); +- if (name == NULL) +- /* Ignore the path. */ +- return -1; +- } +- +- afct = afct->next; +- } ++ name = _dl_audit_objsearch (name, loader, whatcode); ++ if (name == NULL) ++ return -1; + + if (fd != -1 && name != original_name && strcmp (name, original_name)) +- { +- /* An audit library changed what we're supposed to open, +- so FD no longer matches it. */ +- __close_nocancel (fd); +- fd = -1; +- } ++ { ++ /* An audit library changed what we're supposed to open, ++ so FD no longer matches it. */ ++ __close_nocancel (fd); ++ fd = -1; ++ } + } + #endif + +@@ -1992,36 +1980,17 @@ _dl_map_object (struct link_map *loader, const char *name, + #ifdef SHARED + /* Give the auditing libraries a chance to change the name before we + try anything. */ +- if (__glibc_unlikely (GLRO(dl_naudit) > 0) +- && (loader == NULL || loader->l_auditing == 0)) ++ if (__glibc_unlikely (GLRO(dl_naudit) > 0)) + { +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ const char *before = name; ++ name = _dl_audit_objsearch (name, loader, LA_SER_ORIG); ++ if (name == NULL) + { +- if (afct->objsearch != NULL) +- { +- const char *before = name; +- struct auditstate *state = link_map_audit_state (loader, cnt); +- name = afct->objsearch (name, &state->cookie, LA_SER_ORIG); +- if (name == NULL) +- { +- /* Do not try anything further. */ +- fd = -1; +- goto no_file; +- } +- if (before != name && strcmp (before, name) != 0) +- { +- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) +- _dl_debug_printf ("audit changed filename %s -> %s\n", +- before, name); +- +- if (origname == NULL) +- origname = before; +- } +- } +- +- afct = afct->next; ++ fd = -1; ++ goto no_file; + } ++ if (before != name && strcmp (before, name) != 0) ++ origname = before; + } + #endif + +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 05737342d6287233..da83e717e8cd8e0b 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1269,6 +1269,13 @@ link_map_audit_state (struct link_map *l, size_t index) + return &l->l_audit[index]; + } + ++/* Call the la_objsearch from the audit modules from the link map L. If ++ ORIGNAME is non NULL, it is updated with the revious name prior calling ++ la_objsearch. */ ++const char *_dl_audit_objsearch (const char *name, struct link_map *l, ++ unsigned int code) ++ attribute_hidden; ++ + /* Call the la_activity from the audit modules from the link map L and issues + the ACTION argument. */ + void _dl_audit_activity_map (struct link_map *l, int action) diff --git a/glibc-rh2047981-18.patch b/glibc-rh2047981-18.patch new file mode 100644 index 0000000..b866295 --- /dev/null +++ b/glibc-rh2047981-18.patch @@ -0,0 +1,122 @@ +commit 311c9ee54ea963ff69bd3a2e6981c37e893b4c3e +Author: Adhemerval Zanella +Date: Tue Jul 20 14:04:51 2021 -0300 + + elf: Add _dl_audit_objclose + + It consolidates the code required to call la_objclose audit + callback. + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Florian Weimer + +diff --git a/elf/dl-audit.c b/elf/dl-audit.c +index 5682427220569d90..cb1c3de93cba447b 100644 +--- a/elf/dl-audit.c ++++ b/elf/dl-audit.c +@@ -85,3 +85,24 @@ _dl_audit_objopen (struct link_map *l, Lmid_t nsid) + afct = afct->next; + } + } ++ ++void ++_dl_audit_objclose (struct link_map *l) ++{ ++ if (__glibc_likely (GLRO(dl_naudit) == 0) ++ || GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing) ++ return; ++ ++ struct audit_ifaces *afct = GLRO(dl_audit); ++ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ { ++ if (afct->objclose != NULL) ++ { ++ struct auditstate *state= link_map_audit_state (l, cnt); ++ /* Return value is ignored. */ ++ afct->objclose (&state->cookie); ++ } ++ ++ afct = afct->next; ++ } ++} +diff --git a/elf/dl-close.c b/elf/dl-close.c +index 1ba594b600c4c87a..74ca9a85dd309780 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -266,9 +266,6 @@ _dl_close_worker (struct link_map *map, bool force) + used + (nsid == LM_ID_BASE), true); + + /* Call all termination functions at once. */ +-#ifdef SHARED +- bool do_audit = GLRO(dl_naudit) > 0 && !ns->_ns_loaded->l_auditing; +-#endif + bool unload_any = false; + bool scope_mem_left = false; + unsigned int unload_global = 0; +@@ -302,22 +299,7 @@ _dl_close_worker (struct link_map *map, bool force) + + #ifdef SHARED + /* Auditing checkpoint: we remove an object. */ +- if (__glibc_unlikely (do_audit)) +- { +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->objclose != NULL) +- { +- struct auditstate *state +- = link_map_audit_state (imap, cnt); +- /* Return value is ignored. */ +- (void) afct->objclose (&state->cookie); +- } +- +- afct = afct->next; +- } +- } ++ _dl_audit_objclose (imap); + #endif + + /* This object must not be used anymore. */ +diff --git a/elf/dl-fini.c b/elf/dl-fini.c +index 915ceb104e1c81d6..e102d93647cb8c47 100644 +--- a/elf/dl-fini.c ++++ b/elf/dl-fini.c +@@ -146,21 +146,7 @@ _dl_fini (void) + + #ifdef SHARED + /* Auditing checkpoint: another object closed. */ +- if (!do_audit && __builtin_expect (GLRO(dl_naudit) > 0, 0)) +- { +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->objclose != NULL) +- { +- struct auditstate *state +- = link_map_audit_state (l, cnt); +- /* Return value is ignored. */ +- (void) afct->objclose (&state->cookie); +- } +- afct = afct->next; +- } +- } ++ _dl_audit_objclose (l); + #endif + } + +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index da83e717e8cd8e0b..3db25c5be1acf871 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1290,6 +1290,10 @@ void _dl_audit_activity_nsid (Lmid_t nsid, int action) + namespace identification NSID. */ + void _dl_audit_objopen (struct link_map *l, Lmid_t nsid) + attribute_hidden; ++ ++/* Call the la_objclose from the audit modules for the link_map L. */ ++void _dl_audit_objclose (struct link_map *l) ++ attribute_hidden; + #endif /* SHARED */ + + __END_DECLS diff --git a/glibc-rh2047981-19.patch b/glibc-rh2047981-19.patch new file mode 100644 index 0000000..2c55405 --- /dev/null +++ b/glibc-rh2047981-19.patch @@ -0,0 +1,333 @@ +commit cda4f265c65fb6c4ce38ca1cf0a7e527c5e77cd5 +Author: Adhemerval Zanella +Date: Tue Jul 20 15:58:35 2021 -0300 + + elf: Add _dl_audit_symbind_alt and _dl_audit_symbind + + It consolidates the code required to call la_symbind{32,64} audit + callback. + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Florian Weimer + +diff --git a/elf/Versions b/elf/Versions +index be88c48e6d45a937..c5d4342cf1f5124c 100644 +--- a/elf/Versions ++++ b/elf/Versions +@@ -59,6 +59,7 @@ ld { + _dl_argv; _dl_find_dso_for_object; _dl_get_tls_static_info; + _dl_deallocate_tls; _dl_make_stack_executable; + _dl_rtld_di_serinfo; _dl_starting_up; _dl_fatal_printf; ++ _dl_audit_symbind_alt; + _rtld_global; _rtld_global_ro; + + # Only here for gdb while a better method is developed. +diff --git a/elf/dl-audit.c b/elf/dl-audit.c +index cb1c3de93cba447b..a21530f30bc5524b 100644 +--- a/elf/dl-audit.c ++++ b/elf/dl-audit.c +@@ -16,6 +16,7 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + + void +@@ -106,3 +107,124 @@ _dl_audit_objclose (struct link_map *l) + afct = afct->next; + } + } ++ ++void ++_dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, void **value, ++ lookup_t result) ++{ ++ if ((l->l_audit_any_plt | result->l_audit_any_plt) == 0) ++ return; ++ ++ const char *strtab = (const char *) D_PTR (result, l_info[DT_STRTAB]); ++ /* Compute index of the symbol entry in the symbol table of the DSO with ++ the definition. */ ++ unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result, l_info[DT_SYMTAB])); ++ ++ unsigned int altvalue = 0; ++ /* Synthesize a symbol record where the st_value field is the result. */ ++ ElfW(Sym) sym = *ref; ++ sym.st_value = (ElfW(Addr)) *value; ++ ++ struct audit_ifaces *afct = GLRO(dl_audit); ++ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ { ++ struct auditstate *match_audit = link_map_audit_state (l, cnt); ++ struct auditstate *result_audit = link_map_audit_state (result, cnt); ++ if (afct->symbind != NULL ++ && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0 ++ || ((result_audit->bindflags & LA_FLG_BINDTO) ++ != 0))) ++ { ++ unsigned int flags = altvalue | LA_SYMB_DLSYM; ++ uintptr_t new_value = afct->symbind (&sym, ndx, ++ &match_audit->cookie, ++ &result_audit->cookie, ++ &flags, strtab + ref->st_name); ++ if (new_value != (uintptr_t) sym.st_value) ++ { ++ altvalue = LA_SYMB_ALTVALUE; ++ sym.st_value = new_value; ++ } ++ ++ afct = afct->next; ++ } ++ ++ *value = (void *) sym.st_value; ++ } ++} ++rtld_hidden_def (_dl_audit_symbind_alt) ++ ++void ++_dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, ++ const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value, ++ lookup_t result) ++{ ++ reloc_result->bound = result; ++ /* Compute index of the symbol entry in the symbol table of the DSO with the ++ definition. */ ++ reloc_result->boundndx = (defsym - (ElfW(Sym) *) D_PTR (result, ++ l_info[DT_SYMTAB])); ++ ++ if ((l->l_audit_any_plt | result->l_audit_any_plt) == 0) ++ { ++ /* Set all bits since this symbol binding is not interesting. */ ++ reloc_result->enterexit = (1u << DL_NNS) - 1; ++ return; ++ } ++ ++ /* Synthesize a symbol record where the st_value field is the result. */ ++ ElfW(Sym) sym = *defsym; ++ sym.st_value = DL_FIXUP_VALUE_ADDR (*value); ++ ++ /* Keep track whether there is any interest in tracing the call in the lower ++ two bits. */ ++ assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8); ++ assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3); ++ reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT; ++ ++ const char *strtab2 = (const void *) D_PTR (result, l_info[DT_STRTAB]); ++ ++ unsigned int flags = 0; ++ struct audit_ifaces *afct = GLRO(dl_audit); ++ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ { ++ /* XXX Check whether both DSOs must request action or only one */ ++ struct auditstate *l_state = link_map_audit_state (l, cnt); ++ struct auditstate *result_state = link_map_audit_state (result, cnt); ++ if ((l_state->bindflags & LA_FLG_BINDFROM) != 0 ++ && (result_state->bindflags & LA_FLG_BINDTO) != 0) ++ { ++ if (afct->symbind != NULL) ++ { ++ uintptr_t new_value = afct->symbind (&sym, ++ reloc_result->boundndx, ++ &l_state->cookie, ++ &result_state->cookie, ++ &flags, ++ strtab2 + defsym->st_name); ++ if (new_value != (uintptr_t) sym.st_value) ++ { ++ flags |= LA_SYMB_ALTVALUE; ++ sym.st_value = new_value; ++ } ++ } ++ ++ /* Remember the results for every audit library and store a summary ++ in the first two bits. */ ++ reloc_result->enterexit &= flags & (LA_SYMB_NOPLTENTER ++ | LA_SYMB_NOPLTEXIT); ++ reloc_result->enterexit |= ((flags & (LA_SYMB_NOPLTENTER ++ | LA_SYMB_NOPLTEXIT)) ++ << ((cnt + 1) * 2)); ++ } ++ else ++ /* If the bind flags say this auditor is not interested, set the bits ++ manually. */ ++ reloc_result->enterexit |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) ++ << ((cnt + 1) * 2)); ++ afct = afct->next; ++ } ++ ++ reloc_result->flags = flags; ++ *value = DL_FIXUP_ADDR_VALUE (sym.st_value); ++} +diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c +index 4ccd7c30678fafad..d4840a7c17441126 100644 +--- a/elf/dl-runtime.c ++++ b/elf/dl-runtime.c +@@ -296,84 +296,7 @@ _dl_profile_fixup ( + auditing libraries the possibility to change the value and + tell us whether further auditing is wanted. */ + if (defsym != NULL && GLRO(dl_naudit) > 0) +- { +- reloc_result->bound = result; +- /* Compute index of the symbol entry in the symbol table of +- the DSO with the definition. */ +- reloc_result->boundndx = (defsym +- - (ElfW(Sym) *) D_PTR (result, +- l_info[DT_SYMTAB])); +- +- /* Determine whether any of the two participating DSOs is +- interested in auditing. */ +- if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0) +- { +- unsigned int flags = 0; +- struct audit_ifaces *afct = GLRO(dl_audit); +- /* Synthesize a symbol record where the st_value field is +- the result. */ +- ElfW(Sym) sym = *defsym; +- sym.st_value = DL_FIXUP_VALUE_ADDR (value); +- +- /* Keep track whether there is any interest in tracing +- the call in the lower two bits. */ +- assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8); +- assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3); +- reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT; +- +- const char *strtab2 = (const void *) D_PTR (result, +- l_info[DT_STRTAB]); +- +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- /* XXX Check whether both DSOs must request action or +- only one */ +- struct auditstate *l_state = link_map_audit_state (l, cnt); +- struct auditstate *result_state +- = link_map_audit_state (result, cnt); +- if ((l_state->bindflags & LA_FLG_BINDFROM) != 0 +- && (result_state->bindflags & LA_FLG_BINDTO) != 0) +- { +- if (afct->symbind != NULL) +- { +- uintptr_t new_value +- = afct->symbind (&sym, reloc_result->boundndx, +- &l_state->cookie, +- &result_state->cookie, +- &flags, +- strtab2 + defsym->st_name); +- if (new_value != (uintptr_t) sym.st_value) +- { +- flags |= LA_SYMB_ALTVALUE; +- sym.st_value = new_value; +- } +- } +- +- /* Remember the results for every audit library and +- store a summary in the first two bits. */ +- reloc_result->enterexit +- &= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT); +- reloc_result->enterexit +- |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) +- << ((cnt + 1) * 2)); +- } +- else +- /* If the bind flags say this auditor is not interested, +- set the bits manually. */ +- reloc_result->enterexit +- |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) +- << ((cnt + 1) * 2)); +- +- afct = afct->next; +- } +- +- reloc_result->flags = flags; +- value = DL_FIXUP_ADDR_VALUE (sym.st_value); +- } +- else +- /* Set all bits since this symbol binding is not interesting. */ +- reloc_result->enterexit = (1u << DL_NNS) - 1; +- } ++ _dl_audit_symbind (l, reloc_result, defsym, &value, result); + #endif + + /* Store the result for later runs. */ +diff --git a/elf/dl-sym-post.h b/elf/dl-sym-post.h +index 4c4f574633497789..f33934c92047f293 100644 +--- a/elf/dl-sym-post.h ++++ b/elf/dl-sym-post.h +@@ -52,54 +52,9 @@ _dl_sym_post (lookup_t result, const ElfW(Sym) *ref, void *value, + tell us whether further auditing is wanted. */ + if (__glibc_unlikely (GLRO(dl_naudit) > 0)) + { +- const char *strtab = (const char *) D_PTR (result, +- l_info[DT_STRTAB]); +- /* Compute index of the symbol entry in the symbol table of +- the DSO with the definition. */ +- unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result, +- l_info[DT_SYMTAB])); +- + if (match == NULL) + match = _dl_sym_find_caller_link_map (caller); +- +- if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0) +- { +- unsigned int altvalue = 0; +- struct audit_ifaces *afct = GLRO(dl_audit); +- /* Synthesize a symbol record where the st_value field is +- the result. */ +- ElfW(Sym) sym = *ref; +- sym.st_value = (ElfW(Addr)) value; +- +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- struct auditstate *match_audit +- = link_map_audit_state (match, cnt); +- struct auditstate *result_audit +- = link_map_audit_state (result, cnt); +- if (afct->symbind != NULL +- && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0 +- || ((result_audit->bindflags & LA_FLG_BINDTO) +- != 0))) +- { +- unsigned int flags = altvalue | LA_SYMB_DLSYM; +- uintptr_t new_value +- = afct->symbind (&sym, ndx, +- &match_audit->cookie, +- &result_audit->cookie, +- &flags, strtab + ref->st_name); +- if (new_value != (uintptr_t) sym.st_value) +- { +- altvalue = LA_SYMB_ALTVALUE; +- sym.st_value = new_value; +- } +- } +- +- afct = afct->next; +- } +- +- value = (void *) sym.st_value; +- } ++ _dl_audit_symbind_alt (match, ref, &value, result); + } + #endif + return value; +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 3db25c5be1acf871..fa55c3bde10de52e 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1294,6 +1294,16 @@ void _dl_audit_objopen (struct link_map *l, Lmid_t nsid) + /* Call the la_objclose from the audit modules for the link_map L. */ + void _dl_audit_objclose (struct link_map *l) + attribute_hidden; ++ ++/* Call the la_symbind{32,64} from the audit modules for the link_map L. */ ++void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, ++ const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value, ++ lookup_t result) ++ attribute_hidden; ++/* Same as _dl_audit_symbind, but also sets LA_SYMB_DLSYM flag. */ ++void _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, ++ void **value, lookup_t result); ++rtld_hidden_proto (_dl_audit_symbind_alt) + #endif /* SHARED */ + + __END_DECLS diff --git a/glibc-rh2047981-2.patch b/glibc-rh2047981-2.patch new file mode 100644 index 0000000..02bc403 --- /dev/null +++ b/glibc-rh2047981-2.patch @@ -0,0 +1,70 @@ +commit acdcca72940e060270e4e54d9c0457398110f409 +Author: John David Anglin +Date: Mon Mar 30 21:58:06 2020 +0000 + + Add new file missed in previous hppa commit. + +diff --git a/sysdeps/hppa/dl-runtime.c b/sysdeps/hppa/dl-runtime.c +new file mode 100644 +index 0000000000000000..885a3f1837cbc56d +--- /dev/null ++++ b/sysdeps/hppa/dl-runtime.c +@@ -0,0 +1,58 @@ ++/* On-demand PLT fixup for shared objects. HPPA version. ++ Copyright (C) 2019 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++/* Clear PA_GP_RELOC bit in relocation offset. */ ++#define reloc_offset (reloc_arg & ~PA_GP_RELOC) ++#define reloc_index (reloc_arg & ~PA_GP_RELOC) / sizeof (PLTREL) ++ ++#include ++ ++/* The caller has encountered a partially relocated function descriptor. ++ The gp of the descriptor has been updated, but not the ip. We find ++ the function descriptor again and compute the relocation offset and ++ return that to the caller. The caller will continue on to call ++ _dl_fixup with the relocation offset. */ ++ ++ElfW(Word) ++attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE ++_dl_fix_reloc_arg (struct fdesc *fptr, struct link_map *l) ++{ ++ Elf32_Addr l_addr, iplt, jmprel, end_jmprel, r_type; ++ const Elf32_Rela *reloc; ++ ++ l_addr = l->l_addr; ++ jmprel = D_PTR(l, l_info[DT_JMPREL]); ++ end_jmprel = jmprel + l->l_info[DT_PLTRELSZ]->d_un.d_val; ++ ++ /* Look for the entry... */ ++ for (iplt = jmprel; iplt < end_jmprel; iplt += sizeof (Elf32_Rela)) ++ { ++ reloc = (const Elf32_Rela *) iplt; ++ r_type = ELF32_R_TYPE (reloc->r_info); ++ ++ if (__builtin_expect (r_type == R_PARISC_IPLT, 1) ++ && fptr == (struct fdesc *) (reloc->r_offset + l_addr)) ++ /* Found entry. Return the reloc offset. */ ++ return iplt - jmprel; ++ } ++ ++ /* Crash if we weren't passed a valid function pointer. */ ++ ABORT_INSTRUCTION; ++ return 0; ++} diff --git a/glibc-rh2047981-20.patch b/glibc-rh2047981-20.patch new file mode 100644 index 0000000..bce1f3d --- /dev/null +++ b/glibc-rh2047981-20.patch @@ -0,0 +1,113 @@ +commit 0b98a8748759e88b58927882a8714109abe0a2d6 +Author: Adhemerval Zanella +Date: Thu Jul 22 17:10:57 2021 -0300 + + elf: Add _dl_audit_preinit + + It consolidates the code required to call la_preinit audit + callback. + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Florian Weimer + +Conflicts: + csu/libc-start.c + Rework to existing init call code. + +diff --git a/csu/libc-start.c b/csu/libc-start.c +index fd0f8640eaeae34c..ae703cfa620163fd 100644 +--- a/csu/libc-start.c ++++ b/csu/libc-start.c +@@ -265,32 +265,20 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), + #ifdef SHARED + if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0)) + GLRO(dl_debug_printf) ("\ninitialize program: %s\n\n", argv[0]); +-#endif ++ + if (init) + (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM); + +-#ifdef SHARED + /* Auditing checkpoint: we have a new object. */ +- if (__glibc_unlikely (GLRO(dl_naudit) > 0)) +- { +- struct audit_ifaces *afct = GLRO(dl_audit); +- struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded; +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->preinit != NULL) +- afct->preinit (&link_map_audit_state (head, cnt)->cookie); +- +- afct = afct->next; +- } +- } +-#endif ++ _dl_audit_preinit (GL(dl_ns)[LM_ID_BASE]._ns_loaded); + +-#ifdef SHARED + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS)) + GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]); +-#endif + +-#ifndef SHARED ++#else /* !SHARED */ ++ if (init) ++ (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM); ++ + _dl_debug_initialize (0, LM_ID_BASE); + #endif + #ifdef HAVE_CLEANUP_JMP_BUF +diff --git a/elf/Versions b/elf/Versions +index c5d4342cf1f5124c..35ac181bdb099af8 100644 +--- a/elf/Versions ++++ b/elf/Versions +@@ -59,7 +59,7 @@ ld { + _dl_argv; _dl_find_dso_for_object; _dl_get_tls_static_info; + _dl_deallocate_tls; _dl_make_stack_executable; + _dl_rtld_di_serinfo; _dl_starting_up; _dl_fatal_printf; +- _dl_audit_symbind_alt; ++ _dl_audit_symbind_alt; _dl_audit_preinit; + _rtld_global; _rtld_global_ro; + + # Only here for gdb while a better method is developed. +diff --git a/elf/dl-audit.c b/elf/dl-audit.c +index a21530f30bc5524b..0b6fac8e48877c93 100644 +--- a/elf/dl-audit.c ++++ b/elf/dl-audit.c +@@ -108,6 +108,21 @@ _dl_audit_objclose (struct link_map *l) + } + } + ++void ++_dl_audit_preinit (struct link_map *l) ++{ ++ if (__glibc_likely (GLRO(dl_naudit) == 0)) ++ return; ++ ++ struct audit_ifaces *afct = GLRO(dl_audit); ++ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ { ++ if (afct->preinit != NULL) ++ afct->preinit (&link_map_audit_state (l, cnt)->cookie); ++ afct = afct->next; ++ } ++} ++ + void + _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, void **value, + lookup_t result) +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index fa55c3bde10de52e..03676b474c3d37a3 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1295,6 +1295,9 @@ void _dl_audit_objopen (struct link_map *l, Lmid_t nsid) + void _dl_audit_objclose (struct link_map *l) + attribute_hidden; + ++/* Call the la_preinit from the audit modules for the link_map L. */ ++void _dl_audit_preinit (struct link_map *l); ++ + /* Call the la_symbind{32,64} from the audit modules for the link_map L. */ + void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, + const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value, diff --git a/glibc-rh2047981-21.patch b/glibc-rh2047981-21.patch new file mode 100644 index 0000000..ea5003f --- /dev/null +++ b/glibc-rh2047981-21.patch @@ -0,0 +1,205 @@ +commit eff687e8462b0eaf65992a6031b54a4b1cd16796 +Author: Adhemerval Zanella +Date: Thu Jul 22 17:45:33 2021 -0300 + + elf: Add _dl_audit_pltenter + + It consolidates the code required to call la_pltenter audit + callback. + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Florian Weimer + +diff --git a/elf/dl-audit.c b/elf/dl-audit.c +index 0b6fac8e48877c93..15250c67e8ac1658 100644 +--- a/elf/dl-audit.c ++++ b/elf/dl-audit.c +@@ -17,7 +17,9 @@ + . */ + + #include ++#include + #include ++#include + + void + _dl_audit_activity_map (struct link_map *l, int action) +@@ -243,3 +245,78 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, + reloc_result->flags = flags; + *value = DL_FIXUP_ADDR_VALUE (sym.st_value); + } ++ ++void ++_dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result, ++ DL_FIXUP_VALUE_TYPE *value, void *regs, long int *framesize) ++{ ++ /* Don't do anything if no auditor wants to intercept this call. */ ++ if (GLRO(dl_naudit) == 0 ++ || (reloc_result->enterexit & LA_SYMB_NOPLTENTER)) ++ return; ++ ++ /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been ++ initialized earlier in this function or in another thread. */ ++ assert (DL_FIXUP_VALUE_CODE_ADDR (*value) != 0); ++ ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, ++ l_info[DT_SYMTAB]) ++ + reloc_result->boundndx); ++ ++ /* Set up the sym parameter. */ ++ ElfW(Sym) sym = *defsym; ++ sym.st_value = DL_FIXUP_VALUE_ADDR (*value); ++ ++ /* Get the symbol name. */ ++ const char *strtab = (const void *) D_PTR (reloc_result->bound, ++ l_info[DT_STRTAB]); ++ const char *symname = strtab + sym.st_name; ++ ++ /* Keep track of overwritten addresses. */ ++ unsigned int flags = reloc_result->flags; ++ ++ struct audit_ifaces *afct = GLRO(dl_audit); ++ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ { ++ if (afct->ARCH_LA_PLTENTER != NULL ++ && (reloc_result->enterexit ++ & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0) ++ { ++ long int new_framesize = -1; ++ struct auditstate *l_state = link_map_audit_state (l, cnt); ++ struct auditstate *bound_state ++ = link_map_audit_state (reloc_result->bound, cnt); ++ uintptr_t new_value ++ = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx, ++ &l_state->cookie, &bound_state->cookie, ++ regs, &flags, symname, &new_framesize); ++ if (new_value != (uintptr_t) sym.st_value) ++ { ++ flags |= LA_SYMB_ALTVALUE; ++ sym.st_value = new_value; ++ } ++ ++ /* Remember the results for every audit library and store a summary ++ in the first two bits. */ ++ reloc_result->enterexit |= ((flags & (LA_SYMB_NOPLTENTER ++ | LA_SYMB_NOPLTEXIT)) ++ << (2 * (cnt + 1))); ++ ++ if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT ++ << (2 * (cnt + 1)))) ++ == 0 && new_framesize != -1 && *framesize != -2) ++ { ++ /* If this is the first call providing information, use it. */ ++ if (*framesize == -1) ++ *framesize = new_framesize; ++ /* If two pltenter calls provide conflicting information, use ++ the larger value. */ ++ else if (new_framesize != *framesize) ++ *framesize = MAX (new_framesize, *framesize); ++ } ++ } ++ ++ afct = afct->next; ++ } ++ ++ *value = DL_FIXUP_ADDR_VALUE (sym.st_value); ++} +diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c +index d4840a7c17441126..b46f7d7376e65361 100644 +--- a/elf/dl-runtime.c ++++ b/elf/dl-runtime.c +@@ -319,78 +319,7 @@ _dl_profile_fixup ( + #ifdef SHARED + /* Auditing checkpoint: report the PLT entering and allow the + auditors to change the value. */ +- if (GLRO(dl_naudit) > 0 +- /* Don't do anything if no auditor wants to intercept this call. */ +- && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0) +- { +- /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been +- initialized earlier in this function or in another thread. */ +- assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0); +- ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, +- l_info[DT_SYMTAB]) +- + reloc_result->boundndx); +- +- /* Set up the sym parameter. */ +- ElfW(Sym) sym = *defsym; +- sym.st_value = DL_FIXUP_VALUE_ADDR (value); +- +- /* Get the symbol name. */ +- const char *strtab = (const void *) D_PTR (reloc_result->bound, +- l_info[DT_STRTAB]); +- const char *symname = strtab + sym.st_name; +- +- /* Keep track of overwritten addresses. */ +- unsigned int flags = reloc_result->flags; +- +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->ARCH_LA_PLTENTER != NULL +- && (reloc_result->enterexit +- & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0) +- { +- long int new_framesize = -1; +- struct auditstate *l_state = link_map_audit_state (l, cnt); +- struct auditstate *bound_state +- = link_map_audit_state (reloc_result->bound, cnt); +- uintptr_t new_value +- = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx, +- &l_state->cookie, +- &bound_state->cookie, +- regs, &flags, symname, +- &new_framesize); +- if (new_value != (uintptr_t) sym.st_value) +- { +- flags |= LA_SYMB_ALTVALUE; +- sym.st_value = new_value; +- } +- +- /* Remember the results for every audit library and +- store a summary in the first two bits. */ +- reloc_result->enterexit +- |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) +- << (2 * (cnt + 1))); +- +- if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT +- << (2 * (cnt + 1)))) +- == 0 && new_framesize != -1 && framesize != -2) +- { +- /* If this is the first call providing information, +- use it. */ +- if (framesize == -1) +- framesize = new_framesize; +- /* If two pltenter calls provide conflicting information, +- use the larger value. */ +- else if (new_framesize != framesize) +- framesize = MAX (new_framesize, framesize); +- } +- } +- +- afct = afct->next; +- } +- +- value = DL_FIXUP_ADDR_VALUE (sym.st_value); +- } ++ _dl_audit_pltenter (l, reloc_result, &value, regs, &framesize); + #endif + + /* Store the frame size information. */ +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 03676b474c3d37a3..47a9dee5b1c0ca63 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1307,6 +1307,10 @@ void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, + void _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, + void **value, lookup_t result); + rtld_hidden_proto (_dl_audit_symbind_alt) ++void _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result, ++ DL_FIXUP_VALUE_TYPE *value, void *regs, ++ long int *framesize) ++ attribute_hidden; + #endif /* SHARED */ + + __END_DECLS diff --git a/glibc-rh2047981-22.patch b/glibc-rh2047981-22.patch new file mode 100644 index 0000000..17c35d5 --- /dev/null +++ b/glibc-rh2047981-22.patch @@ -0,0 +1,795 @@ +commit 8c0664e2b861fd3789602cc0b0b1922b0e20cb3a +Author: Adhemerval Zanella +Date: Thu Jul 22 18:02:42 2021 -0300 + + elf: Add _dl_audit_pltexit + + It consolidates the code required to call la_pltexit audit + callback. + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Florian Weimer + +Conflicts: + nptl/tst-atfork4mod.c + sysdeps/powerpc/fpu/s_fmaf.S + sysdeps/powerpc/powerpc32/power4/multiarch/wcscpy-ppc32.c + sysdeps/powerpc/powerpc64/power5+/fpu/s_floor.S + Without d6d89608ac8cf2b37c75debad1fff653f6939f90 we + don't have dl-machine-rel.h so git picks a match for + all four files above, instead we modify dl-machine.h + for the targets: + sysdeps/i386/dl-machine.h + sysdeps/arm/dl-machine.h + sysdeps/mips/dl-machine.h + The fourth is the generic file and without it we + add the PLTREL macro to each target: + sysdeps/aarch64/dl-machine.h + sysdeps/powerpc/powerpc32/dl-machine.h + sysdeps/powerpc/powerpc64/dl-machine.h + sysdeps/s390/s390-32/dl-machine.h + sysdeps/s390/s390-64/dl-machine.h + sysdeps/x86_64/dl-machine.h + sysdeps/s390/s390-32/dl-trampoline.h + sysdeps/s390/s390-64/dl-trampoline.h + +diff --git a/elf/dl-audit.c b/elf/dl-audit.c +index 15250c67e8ac1658..152712b12fed6de2 100644 +--- a/elf/dl-audit.c ++++ b/elf/dl-audit.c +@@ -20,6 +20,8 @@ + #include + #include + #include ++#include ++#include + + void + _dl_audit_activity_map (struct link_map *l, int action) +@@ -320,3 +322,48 @@ _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result, + + *value = DL_FIXUP_ADDR_VALUE (sym.st_value); + } ++ ++void ++DL_ARCH_FIXUP_ATTRIBUTE ++_dl_audit_pltexit (struct link_map *l, ElfW(Word) reloc_arg, ++ const void *inregs, void *outregs) ++{ ++ const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]); ++ ++ /* This is the address in the array where we store the result of previous ++ relocations. */ ++ // XXX Maybe the bound information must be stored on the stack since ++ // XXX with bind_not a new value could have been stored in the meantime. ++ struct reloc_result *reloc_result = ++ &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))]; ++ ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, ++ l_info[DT_SYMTAB]) ++ + reloc_result->boundndx); ++ ++ /* Set up the sym parameter. */ ++ ElfW(Sym) sym = *defsym; ++ sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr); ++ ++ /* Get the symbol name. */ ++ const char *strtab = (const void *) D_PTR (reloc_result->bound, ++ l_info[DT_STRTAB]); ++ const char *symname = strtab + sym.st_name; ++ ++ struct audit_ifaces *afct = GLRO(dl_audit); ++ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ { ++ if (afct->ARCH_LA_PLTEXIT != NULL ++ && (reloc_result->enterexit ++ & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0) ++ { ++ struct auditstate *l_state = link_map_audit_state (l, cnt); ++ struct auditstate *bound_state ++ = link_map_audit_state (reloc_result->bound, cnt); ++ afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx, ++ &l_state->cookie, &bound_state->cookie, ++ inregs, outregs, symname); ++ } ++ ++ afct = afct->next; ++ } ++} +diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c +index b46f7d7376e65361..ec0b2164825fa538 100644 +--- a/elf/dl-runtime.c ++++ b/elf/dl-runtime.c +@@ -16,8 +16,6 @@ + License along with the GNU C Library; if not, see + . */ + +-#define IN_DL_RUNTIME 1 /* This can be tested in dl-machine.h. */ +- + #include + #include + #include +@@ -30,19 +28,6 @@ + #include + + +-#if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \ +- || ELF_MACHINE_NO_REL +-# define PLTREL ElfW(Rela) +-#else +-# define PLTREL ElfW(Rel) +-#endif +- +-/* The fixup functions might have need special attributes. If none +- are provided define the macro as empty. */ +-#ifndef ARCH_FIXUP_ATTRIBUTE +-# define ARCH_FIXUP_ATTRIBUTE +-#endif +- + /* This function is called through a special trampoline from the PLT the + first time each PLT entry is called. We must perform the relocation + specified in the PLT of the given shared object, and return the resolved +@@ -51,7 +36,7 @@ + function. */ + + DL_FIXUP_VALUE_TYPE +-attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE ++attribute_hidden __attribute ((noinline)) DL_ARCH_FIXUP_ATTRIBUTE + _dl_fixup ( + # ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS + ELF_MACHINE_RUNTIME_FIXUP_ARGS, +@@ -147,7 +132,8 @@ _dl_fixup ( + + #ifndef PROF + DL_FIXUP_VALUE_TYPE +-__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE ++__attribute ((noinline)) ++DL_ARCH_FIXUP_ATTRIBUTE + _dl_profile_fixup ( + #ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS + ELF_MACHINE_RUNTIME_FIXUP_ARGS, +@@ -331,52 +317,3 @@ _dl_profile_fixup ( + } + + #endif /* PROF */ +- +- +-#include +-void +-ARCH_FIXUP_ATTRIBUTE +-_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg, +- const void *inregs, void *outregs) +-{ +-#ifdef SHARED +- const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]); +- +- /* This is the address in the array where we store the result of previous +- relocations. */ +- // XXX Maybe the bound information must be stored on the stack since +- // XXX with bind_not a new value could have been stored in the meantime. +- struct reloc_result *reloc_result = +- &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))]; +- ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, +- l_info[DT_SYMTAB]) +- + reloc_result->boundndx); +- +- /* Set up the sym parameter. */ +- ElfW(Sym) sym = *defsym; +- sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr); +- +- /* Get the symbol name. */ +- const char *strtab = (const void *) D_PTR (reloc_result->bound, +- l_info[DT_STRTAB]); +- const char *symname = strtab + sym.st_name; +- +- struct audit_ifaces *afct = GLRO(dl_audit); +- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) +- { +- if (afct->ARCH_LA_PLTEXIT != NULL +- && (reloc_result->enterexit +- & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0) +- { +- struct auditstate *l_state = link_map_audit_state (l, cnt); +- struct auditstate *bound_state +- = link_map_audit_state (reloc_result->bound, cnt); +- afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx, +- &l_state->cookie, &bound_state->cookie, +- inregs, outregs, symname); +- } +- +- afct = afct->next; +- } +-#endif +-} +diff --git a/elf/dl-support.c b/elf/dl-support.c +index 3e5531138eaa18f8..e9943e889ef447ad 100644 +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -399,3 +399,11 @@ _dl_get_dl_main_map (void) + return &_dl_main_map; + } + #endif ++ ++/* This is used by _dl_runtime_profile, not used on static code. */ ++void ++DL_ARCH_FIXUP_ATTRIBUTE ++_dl_audit_pltexit (struct link_map *l, ElfW(Word) reloc_arg, ++ const void *inregs, void *outregs) ++{ ++} +diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h +index 5eab544afe2717f7..c13d896a57811c7d 100644 +--- a/sysdeps/aarch64/dl-machine.h ++++ b/sysdeps/aarch64/dl-machine.h +@@ -196,6 +196,7 @@ _dl_start_user: \n\ + /* AArch64 uses RELA not REL */ + #define ELF_MACHINE_NO_REL 1 + #define ELF_MACHINE_NO_RELA 0 ++#define PLTREL ElfW(Rela) + + #define DL_PLATFORM_INIT dl_platform_init () + +diff --git a/sysdeps/aarch64/dl-trampoline.S b/sysdeps/aarch64/dl-trampoline.S +index a86d0722d4a0415b..18740398e63fdf97 100644 +--- a/sysdeps/aarch64/dl-trampoline.S ++++ b/sysdeps/aarch64/dl-trampoline.S +@@ -277,7 +277,7 @@ _dl_runtime_profile: + ldp x0, x1, [x29, #OFFSET_SAVED_CALL_X0] + add x2, x29, #OFFSET_RG + add x3, x29, #OFFSET_RV +- bl _dl_call_pltexit ++ bl _dl_audit_pltexit + + ldp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0] + ldp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0] +diff --git a/sysdeps/alpha/dl-trampoline.S b/sysdeps/alpha/dl-trampoline.S +index b326b37acedb5eaa..3acf5dec8d9585da 100644 +--- a/sysdeps/alpha/dl-trampoline.S ++++ b/sysdeps/alpha/dl-trampoline.S +@@ -187,7 +187,7 @@ _dl_runtime_profile_new: + jsr $26, ($27), 0 + ldgp $29, 0($26) + +- /* Set up for call to _dl_call_pltexit. */ ++ /* Set up for call to _dl_audit_pltexit. */ + ldq $16, 16*8($15) + ldq $17, 17*8($15) + stq $0, 16*8($15) +@@ -196,7 +196,7 @@ _dl_runtime_profile_new: + lda $19, 16*8($15) + stt $f0, 18*8($15) + stt $f1, 19*8($15) +- bsr $26, _dl_call_pltexit !samegp ++ bsr $26, _dl_audit_pltexit !samegp + + mov $15, $30 + cfi_def_cfa_register (30) +@@ -518,7 +518,7 @@ _dl_runtime_profile_old: + jsr $26, ($27), 0 + ldgp $29, 0($26) + +- /* Set up for call to _dl_call_pltexit. */ ++ /* Set up for call to _dl_audit_pltexit. */ + ldq $16, 48*8($15) + ldq $17, 49*8($15) + stq $0, 46*8($15) +@@ -527,7 +527,7 @@ _dl_runtime_profile_old: + lda $19, 46*8($15) + stt $f0, 48*8($15) + stt $f1, 49*8($15) +- bsr $26, _dl_call_pltexit !samegp ++ bsr $26, _dl_audit_pltexit !samegp + + mov $15, $30 + cfi_def_cfa_register (30) +diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h +index 1a4fd3f17b6df7da..9b5d0567df984c5d 100644 +--- a/sysdeps/arm/dl-machine.h ++++ b/sysdeps/arm/dl-machine.h +@@ -260,6 +260,8 @@ _dl_start_user:\n\ + Prelinked libraries may use Elf32_Rela though. */ + #define ELF_MACHINE_PLT_REL 1 + ++#define PLTREL ElfW(Rel) ++ + /* We define an initialization functions. This is called very early in + _dl_sysdep_start. */ + #define DL_PLATFORM_INIT dl_platform_init () +diff --git a/sysdeps/arm/dl-trampoline.S b/sysdeps/arm/dl-trampoline.S +index c731b012869a9cbc..ced1b1cb1017d677 100644 +--- a/sysdeps/arm/dl-trampoline.S ++++ b/sysdeps/arm/dl-trampoline.S +@@ -194,7 +194,7 @@ _dl_runtime_profile: + ldmia ip, {r0,r1} + add r2, r7, #72 + add r3, r7, #0 +- bl _dl_call_pltexit ++ bl _dl_audit_pltexit + + @ Return to caller. + ldmia r7, {r0-r3} +diff --git a/sysdeps/generic/dl-fixup-attribute.h b/sysdeps/generic/dl-fixup-attribute.h +new file mode 100644 +index 0000000000000000..aa92169b709b3fea +--- /dev/null ++++ b/sysdeps/generic/dl-fixup-attribute.h +@@ -0,0 +1,24 @@ ++/* ABI specifics for lazy resolution functions. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _DL_FIXUP_ATTRIBUTE_H ++#define _DL_FIXUP_ATTRIBUTE_H ++ ++#define DL_ARCH_FIXUP_ATTRIBUTE ++ ++#endif +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 47a9dee5b1c0ca63..29b77b35175c1116 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1311,6 +1312,11 @@ void _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result, + DL_FIXUP_VALUE_TYPE *value, void *regs, + long int *framesize) + attribute_hidden; ++void DL_ARCH_FIXUP_ATTRIBUTE _dl_audit_pltexit (struct link_map *l, ++ ElfW(Word) reloc_arg, ++ const void *inregs, ++ void *outregs) ++ attribute_hidden; + #endif /* SHARED */ + + __END_DECLS +diff --git a/sysdeps/hppa/dl-runtime.c b/sysdeps/hppa/dl-runtime.c +index 2d061b150f0602c1..4c323131f937094b 100644 +--- a/sysdeps/hppa/dl-runtime.c ++++ b/sysdeps/hppa/dl-runtime.c +@@ -26,7 +26,7 @@ + _dl_fixup with the relocation offset. */ + + ElfW(Word) +-attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE ++attribute_hidden __attribute ((noinline)) DL_ARCH_FIXUP_ATTRIBUTE + _dl_fix_reloc_arg (struct fdesc *fptr, struct link_map *l) + { + Elf32_Addr l_addr, iplt, jmprel, end_jmprel, r_type; +diff --git a/sysdeps/hppa/dl-trampoline.S b/sysdeps/hppa/dl-trampoline.S +index 7ee4331cc2e7deff..3c83c8542f4fc63f 100644 +--- a/sysdeps/hppa/dl-trampoline.S ++++ b/sysdeps/hppa/dl-trampoline.S +@@ -275,7 +275,7 @@ L(cont): + ldw -4(%sp),%r1 + copy %r1, %sp + +- /* Arguments to _dl_call_pltexit */ ++ /* Arguments to _dl_audit_pltexit */ + ldw -116(%sp), %r26 /* (1) got[1] == struct link_map */ + ldw -120(%sp), %r25 /* (2) reloc offsets */ + ldo -56(%sp), %r24 /* (3) *La_hppa_regs */ +@@ -287,8 +287,8 @@ L(cont): + ldo -128(%sp), %r1 + fstd %fr4,0(%r1) + +- /* Call _dl_call_pltexit */ +- bl _dl_call_pltexit,%rp ++ /* Call _dl_audit_pltexit */ ++ bl _dl_audit_pltexit,%rp + nop + + /* Restore *La_hppa_retval */ +diff --git a/sysdeps/i386/dl-fixup-attribute.h b/sysdeps/i386/dl-fixup-attribute.h +new file mode 100644 +index 0000000000000000..c10e9936f4db7254 +--- /dev/null ++++ b/sysdeps/i386/dl-fixup-attribute.h +@@ -0,0 +1,30 @@ ++/* ABI specifics for lazy resolution functions. i386 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 ++ . */ ++ ++#ifndef _DL_FIXUP_ATTRIBUTE_H ++#define _DL_FIXUP_ATTRIBUTE_H ++ ++/* We cannot use this scheme for profiling because the _mcount call destroys ++ the passed register information. */ ++#ifndef PROF ++# define DL_ARCH_FIXUP_ATTRIBUTE __attribute__ ((regparm (3), stdcall, unused)) ++#else ++# define DL_ARCH_FIXUP_ATTRIBUTE ++#endif ++ ++#endif +diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h +index 5ba95b9e4af49942..30c3464fc4ac19d8 100644 +--- a/sysdeps/i386/dl-machine.h ++++ b/sysdeps/i386/dl-machine.h +@@ -119,29 +119,6 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[], + return lazy; + } + +-#ifdef IN_DL_RUNTIME +- +-# ifndef PROF +-/* We add a declaration of this function here so that in dl-runtime.c +- the ELF_MACHINE_RUNTIME_TRAMPOLINE macro really can pass the parameters +- in registers. +- +- We cannot use this scheme for profiling because the _mcount call +- destroys the passed register information. */ +-#define ARCH_FIXUP_ATTRIBUTE __attribute__ ((regparm (3), stdcall, unused)) +- +-extern ElfW(Addr) _dl_fixup (struct link_map *l, +- ElfW(Word) reloc_offset) +- ARCH_FIXUP_ATTRIBUTE; +-extern ElfW(Addr) _dl_profile_fixup (struct link_map *l, +- ElfW(Word) reloc_offset, +- ElfW(Addr) retaddr, void *regs, +- long int *framesizep) +- ARCH_FIXUP_ATTRIBUTE; +-# endif +- +-#endif +- + /* Mask identifying addresses reserved for the user program, + where the dynamic linker should not map anything. */ + #define ELF_MACHINE_USER_ADDRESS_MASK 0xf8000000UL +@@ -240,6 +217,8 @@ _dl_start_user:\n\ + Prelinked libraries may use Elf32_Rela though. */ + #define ELF_MACHINE_PLT_REL 1 + ++#define PLTREL ElfW(Rel) ++ + /* We define an initialization functions. This is called very early in + _dl_sysdep_start. */ + #define DL_PLATFORM_INIT dl_platform_init () +diff --git a/sysdeps/i386/dl-trampoline.S b/sysdeps/i386/dl-trampoline.S +index 6dc03192168ae2f3..a738b291a79bf8c2 100644 +--- a/sysdeps/i386/dl-trampoline.S ++++ b/sysdeps/i386/dl-trampoline.S +@@ -265,7 +265,7 @@ _dl_runtime_profile: + movl (LRV_SIZE + 4 + LR_SIZE)(%esp), %eax + # PLT1 + movl (LRV_SIZE + 4 + LR_SIZE + 4)(%esp), %edx +- call _dl_call_pltexit ++ call _dl_audit_pltexit + movl LRV_EAX_OFFSET(%esp), %eax + movl LRV_EDX_OFFSET(%esp), %edx + fldt LRV_ST1_OFFSET(%esp) +diff --git a/sysdeps/ia64/dl-trampoline.S b/sysdeps/ia64/dl-trampoline.S +index fc24c425bfe6907b..caeca3afcd7db6b6 100644 +--- a/sysdeps/ia64/dl-trampoline.S ++++ b/sysdeps/ia64/dl-trampoline.S +@@ -133,7 +133,7 @@ END(_dl_runtime_resolve) + + + /* The fourth argument to _dl_profile_fixup and the third one to +- _dl_call_pltexit are a pointer to La_ia64_regs: ++ _dl_audit_pltexit are a pointer to La_ia64_regs: + + 8byte r8 + 8byte r9 +@@ -159,7 +159,7 @@ END(_dl_runtime_resolve) + 8byte sp + + The fifth argument to _dl_profile_fixup is a pointer to long int. +- The fourth argument to _dl_call_pltexit is a pointer to ++ The fourth argument to _dl_audit_pltexit is a pointer to + La_ia64_retval: + + 8byte r8 +@@ -261,7 +261,7 @@ ENTRY(_dl_runtime_profile) + } + { .mii + mov r18 = ar.unat /* save it in La_ia64_regs */ +- mov loc7 = out3 /* save it for _dl_call_pltexit */ ++ mov loc7 = out3 /* save it for _dl_audit_pltexit */ + mov loc5 = r11 /* preserve language specific register */ + } + { .mmi +@@ -272,7 +272,7 @@ ENTRY(_dl_runtime_profile) + } + { .mii + mov ar.unat = r17 /* restore it for function call */ +- mov loc8 = r16 /* save it for _dl_call_pltexit */ ++ mov loc8 = r16 /* save it for _dl_audit_pltexit */ + nop.i 0x0 + } + { .mmi +@@ -291,7 +291,7 @@ ENTRY(_dl_runtime_profile) + { .mmi + stf.spill [r2] = f14, 32 + stf.spill [r3] = f15, 24 +- mov loc9 = out1 /* save it for _dl_call_pltexit */ ++ mov loc9 = out1 /* save it for _dl_audit_pltexit */ + ;; + } + { .mmb +@@ -426,7 +426,7 @@ ENTRY(_dl_runtime_profile) + br.call.sptk.many b0 = b6 + } + { .mii +- /* Prepare stack for _dl_call_pltexit. Loc10 has the original ++ /* Prepare stack for _dl_audit_pltexit. Loc10 has the original + stack pointer. */ + adds r12 = -PLTEXIT_FRAME_SIZE, loc10 + adds r2 = -(PLTEXIT_FRAME_SIZE - 16), loc10 +@@ -461,14 +461,14 @@ ENTRY(_dl_runtime_profile) + { .mmi + stf.spill [r2] = f12, 32 + stf.spill [r3] = f13, 32 +- /* We need to restore gp for _dl_call_pltexit. */ ++ /* We need to restore gp for _dl_audit_pltexit. */ + mov gp = loc11 + ;; + } + { .mmb + stf.spill [r2] = f14 + stf.spill [r3] = f15 +- br.call.sptk.many b0 = _dl_call_pltexit ++ br.call.sptk.many b0 = _dl_audit_pltexit + } + { .mmi + /* Load all the non-floating and floating return values. Skip +diff --git a/sysdeps/m68k/dl-trampoline.S b/sysdeps/m68k/dl-trampoline.S +index 7e1eace26b4a519d..27282ca8a6b1dada 100644 +--- a/sysdeps/m68k/dl-trampoline.S ++++ b/sysdeps/m68k/dl-trampoline.S +@@ -202,7 +202,7 @@ _dl_runtime_profile: + cfi_adjust_cfa_offset (4) + move.l (32+FPSPACE)(%sp), -(%sp) + cfi_adjust_cfa_offset (4) +- jbsr _dl_call_pltexit ++ jbsr _dl_audit_pltexit + lea 16(%sp), %sp + cfi_adjust_cfa_offset (-16) + move.l (%sp)+, %d0 +diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h +index b41e10647d81843b..d4bd8b62f4b036a3 100644 +--- a/sysdeps/mips/dl-machine.h ++++ b/sysdeps/mips/dl-machine.h +@@ -63,6 +63,7 @@ + #define ELF_MACHINE_PLT_REL 1 + #define ELF_MACHINE_NO_REL 0 + #define ELF_MACHINE_NO_RELA 0 ++#define PLTREL ElfW(Rel) + + /* Translate a processor specific dynamic tag to the index + in l_info array. */ +diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h +index 31c7f3f95a2ce1b2..84322595793dc8bb 100644 +--- a/sysdeps/powerpc/powerpc32/dl-machine.h ++++ b/sysdeps/powerpc/powerpc32/dl-machine.h +@@ -150,6 +150,7 @@ __elf_preferred_address(struct link_map *loader, size_t maplength, + /* The PowerPC never uses REL relocations. */ + #define ELF_MACHINE_NO_REL 1 + #define ELF_MACHINE_NO_RELA 0 ++#define PLTREL ElfW(Rela) + + /* We define an initialization function to initialize HWCAP/HWCAP2 and + platform data so it can be copied into the TCB later. This is called +diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h +index 35996bb9173da231..3af1f708378f9a3c 100644 +--- a/sysdeps/powerpc/powerpc64/dl-machine.h ++++ b/sysdeps/powerpc/powerpc64/dl-machine.h +@@ -297,6 +297,7 @@ BODY_PREFIX "_dl_start_user:\n" \ + /* The PowerPC never uses REL relocations. */ + #define ELF_MACHINE_NO_REL 1 + #define ELF_MACHINE_NO_RELA 0 ++#define PLTREL ElfW(Rela) + + /* We define an initialization function to initialize HWCAP/HWCAP2 and + platform data so it can be copied into the TCB later. This is called +diff --git a/sysdeps/powerpc/powerpc64/dl-trampoline.S b/sysdeps/powerpc/powerpc64/dl-trampoline.S +index aa141dc44b980d9b..23290d32360507fd 100644 +--- a/sysdeps/powerpc/powerpc64/dl-trampoline.S ++++ b/sysdeps/powerpc/powerpc64/dl-trampoline.S +@@ -197,7 +197,7 @@ END(_dl_runtime_resolve) + #ifndef PROF + ENTRY (_dl_profile_resolve, 4) + /* Spill r30, r31 to preserve the link_map* and reloc_addr, in case we +- need to call _dl_call_pltexit. */ ++ need to call _dl_audit_pltexit. */ + std r31,-8(r1) + std r30,-16(r1) + /* We need to save the registers used to pass parameters, ie. r3 thru +@@ -452,7 +452,7 @@ L(restoreFXR2): + L(callpltexit): + addi r5,r1,INT_PARMS + addi r6,r1,INT_RTN +- bl JUMPTARGET(_dl_call_pltexit) ++ bl JUMPTARGET(_dl_audit_pltexit) + #ifndef SHARED + nop + #endif +diff --git a/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h +index ded41adff80346b6..2f3bb085ae2b6794 100644 +--- a/sysdeps/s390/s390-32/dl-machine.h ++++ b/sysdeps/s390/s390-32/dl-machine.h +@@ -279,6 +279,7 @@ _dl_start_user:\n\ + /* The S390 never uses Elf32_Rel relocations. */ + #define ELF_MACHINE_NO_REL 1 + #define ELF_MACHINE_NO_RELA 0 ++#define PLTREL ElfW(Rela) + + /* We define an initialization functions. This is called very early in + _dl_sysdep_start. */ +diff --git a/sysdeps/s390/s390-32/dl-trampoline.h b/sysdeps/s390/s390-32/dl-trampoline.h +index d36c002743bf2f0c..c447a41f067c462b 100644 +--- a/sysdeps/s390/s390-32/dl-trampoline.h ++++ b/sysdeps/s390/s390-32/dl-trampoline.h +@@ -207,7 +207,7 @@ _dl_runtime_profile: + basr %r1,0 + 5: l %r14,7f-5b(%r1) + la %r5,40(%r12) # pointer to struct La_s390_32_retval +- bas %r14,0(%r14,%r1) # call _dl_call_pltexit ++ bas %r14,0(%r14,%r1) # call _dl_audit_pltexit + + lr %r15,%r12 # remove stack frame + cfi_def_cfa_register (15) +@@ -224,7 +224,7 @@ _dl_runtime_profile: + br %r14 + + 6: .long _dl_profile_fixup - 0b +-7: .long _dl_call_pltexit - 5b ++7: .long _dl_audit_pltexit - 5b + cfi_endproc + .size _dl_runtime_profile, .-_dl_runtime_profile + #endif +diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h +index 36327c40a1972dd7..033e7c9916e751f4 100644 +--- a/sysdeps/s390/s390-64/dl-machine.h ++++ b/sysdeps/s390/s390-64/dl-machine.h +@@ -228,6 +228,7 @@ _dl_start_user:\n\ + /* The 64 bit S/390 never uses Elf64_Rel relocations. */ + #define ELF_MACHINE_NO_REL 1 + #define ELF_MACHINE_NO_RELA 0 ++#define PLTREL ElfW(Rela) + + /* We define an initialization functions. This is called very early in + _dl_sysdep_start. */ +diff --git a/sysdeps/s390/s390-64/dl-trampoline.h b/sysdeps/s390/s390-64/dl-trampoline.h +index d313fd521db0b859..18534d629ebc00e2 100644 +--- a/sysdeps/s390/s390-64/dl-trampoline.h ++++ b/sysdeps/s390/s390-64/dl-trampoline.h +@@ -203,7 +203,7 @@ _dl_runtime_profile: + lmg %r2,%r4,48(%r12) # r2, r3: load arguments saved by PLT + # r4: pointer to struct La_s390_64_regs + la %r5,72(%r12) # pointer to struct La_s390_64_retval +- brasl %r14,_dl_call_pltexit ++ brasl %r14,_dl_audit_pltexit + + lgr %r15,%r12 # remove stack frame + cfi_def_cfa_register (15) +diff --git a/sysdeps/sh/dl-trampoline.S b/sysdeps/sh/dl-trampoline.S +index 0c8f84d26d3015ca..73f865f2af4e2d48 100644 +--- a/sysdeps/sh/dl-trampoline.S ++++ b/sysdeps/sh/dl-trampoline.S +@@ -423,8 +423,8 @@ _dl_runtime_profile: + .align 2 + #ifdef SHARED + 7: .long _GLOBAL_OFFSET_TABLE_ +-8: .long _dl_call_pltexit@GOTOFF ++8: .long _dl_audit_pltexit@GOTOFF + #else +-8: .long _dl_call_pltexit ++8: .long _dl_audit_pltexit + #endif + .size _dl_runtime_profile, .-_dl_runtime_profile +diff --git a/sysdeps/sparc/sparc32/dl-trampoline.S b/sysdeps/sparc/sparc32/dl-trampoline.S +index 098ffcfacc55d0b6..18ef2f0d3655b3de 100644 +--- a/sysdeps/sparc/sparc32/dl-trampoline.S ++++ b/sysdeps/sparc/sparc32/dl-trampoline.S +@@ -127,7 +127,7 @@ _dl_profile_invoke: + mov %l5, %o0 + mov %l6, %o1 + add %sp, (11 * 8), %o2 +- call _dl_call_pltexit ++ call _dl_audit_pltexit + add %sp, ( 9 * 8), %o3 + + ldd [%sp + ( 9 * 8)], %i0 +diff --git a/sysdeps/sparc/sparc64/dl-trampoline.S b/sysdeps/sparc/sparc64/dl-trampoline.S +index 4948b88b9640691d..9c18ceb131c9a25b 100644 +--- a/sysdeps/sparc/sparc64/dl-trampoline.S ++++ b/sysdeps/sparc/sparc64/dl-trampoline.S +@@ -196,7 +196,7 @@ _dl_profile_invoke: + mov %l5, %o0 + mov %l6, %o1 + add %sp, STACK_BIAS + (24 * 8), %o2 +- call _dl_call_pltexit ++ call _dl_audit_pltexit + add %sp, STACK_BIAS + (16 * 8), %o3 + + ldx [%sp + STACK_BIAS + (16 * 8)], %i0 +diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h +index 5262aa69c06aa8db..d30317980882ac51 100644 +--- a/sysdeps/x86_64/dl-machine.h ++++ b/sysdeps/x86_64/dl-machine.h +@@ -210,6 +210,7 @@ _dl_start_user:\n\ + /* The x86-64 never uses Elf64_Rel/Elf32_Rel relocations. */ + #define ELF_MACHINE_NO_REL 1 + #define ELF_MACHINE_NO_RELA 0 ++#define PLTREL ElfW(Rela) + + /* We define an initialization function. This is called very early in + _dl_sysdep_start. */ +diff --git a/sysdeps/x86_64/dl-runtime.h b/sysdeps/x86_64/dl-runtime.h +index 3fa61d7a4697cf3f..379f8bd4dea8ef97 100644 +--- a/sysdeps/x86_64/dl-runtime.h ++++ b/sysdeps/x86_64/dl-runtime.h +@@ -18,7 +18,7 @@ + 02111-1307 USA. */ + + /* The ABI calls for the PLT stubs to pass the index of the relocation +- and not its offset. In _dl_profile_fixup and _dl_call_pltexit we ++ and not its offset. In _dl_profile_fixup and _dl_audit_pltexit we + also use the index. Therefore it is wasteful to compute the offset + in the trampoline just to reverse the operation immediately + afterwards. */ +diff --git a/sysdeps/x86_64/dl-trampoline.h b/sysdeps/x86_64/dl-trampoline.h +index a28b1e73a4b187ba..256dfbb64df9f03d 100644 +--- a/sysdeps/x86_64/dl-trampoline.h ++++ b/sysdeps/x86_64/dl-trampoline.h +@@ -388,7 +388,7 @@ _dl_runtime_profile: + jns 3f + + /* There's nothing in the frame size, so there +- will be no call to the _dl_call_pltexit. */ ++ will be no call to the _dl_audit_pltexit. */ + + /* Get back registers content. */ + movq LR_RCX_OFFSET(%rsp), %rcx +@@ -436,7 +436,7 @@ _dl_runtime_profile: + mov 24(%rbx), %RSP_LP # Drop the copied stack content + + /* Now we have to prepare the La_x86_64_retval structure for the +- _dl_call_pltexit. The La_x86_64_regs is being pointed by rsp now, ++ _dl_audit_pltexit. The La_x86_64_regs is being pointed by rsp now, + so we just need to allocate the sizeof(La_x86_64_retval) space on + the stack, since the alignment has already been taken care of. */ + # ifdef RESTORE_AVX +@@ -491,7 +491,7 @@ _dl_runtime_profile: + movq 24(%rbx), %rdx # La_x86_64_regs argument to %rdx. + movq 40(%rbx), %rsi # Copy args pushed by PLT in register. + movq 32(%rbx), %rdi # %rdi: link_map, %rsi: reloc_index +- call _dl_call_pltexit ++ call _dl_audit_pltexit + + /* Restore return registers. */ + movq LRV_RAX_OFFSET(%rsp), %rax diff --git a/glibc-rh2047981-23.patch b/glibc-rh2047981-23.patch new file mode 100644 index 0000000..b2e83f8 --- /dev/null +++ b/glibc-rh2047981-23.patch @@ -0,0 +1,449 @@ +Added $(objpfx)tst-audit19a: $(libdl) to elf/Makefile since +we still need $(libdl) in RHEL8. + +commit 063f9ba220f434c7f30dd65c4cff17c0c458a7cf +Author: Adhemerval Zanella +Date: Wed Jun 30 10:24:09 2021 -0300 + + elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533) + + The rtld-audit interfaces introduces a slowdown due to enabling + profiling instrumentation (as if LD_AUDIT implied LD_PROFILE). + However, instrumenting is only necessary if one of audit libraries + provides PLT callbacks (la_pltenter or la_pltexit symbols). Otherwise, + the slowdown can be avoided. + + The following patch adjusts the logic that enables profiling to iterate + over all audit modules and check if any of those provides a PLT hook. + To keep la_symbind to work even without PLT callbacks, _dl_fixup now + calls the audit callback if the modules implements it. + + Co-authored-by: Alexander Monakov + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Florian Weimer + +Conflicts: + elf/Makefile + +diff --git a/elf/Makefile b/elf/Makefile +index 08a32a712a34f2cc..0cc03ffe2984ee50 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -221,12 +221,14 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-dlmopen-gethostbyname \ + tst-audit17 \ + tst-audit18 \ ++ tst-audit19b \ + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ + tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \ + tst-ptrguard1 tst-stackguard1 tst-libc_dlvsym \ +- tst-create_format1 tst-tls-surplus tst-dl-hwcaps_split ++ tst-create_format1 tst-tls-surplus tst-dl-hwcaps_split \ ++ tst-audit19a + tests-container += tst-pldd tst-preload-pthread-libc + ifeq ($(build-hardcoded-path-in-tests),yes) + tests += tst-dlopen-aout +@@ -358,6 +360,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-dlmopen-gethostbyname-mod \ + tst-auditmod18 \ + tst-audit18mod \ ++ tst-auditmod19a \ ++ tst-auditmod19b \ ++ tst-audit19bmod \ + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +@@ -1548,6 +1553,14 @@ $(objpfx)tst-audit18.out: $(objpfx)tst-auditmod18.so \ + $(objpfx)tst-audit18mod.so + tst-audit18-ARGS = -- $(host-test-program-cmd) + ++$(objpfx)tst-audit19a: $(libdl) ++$(objpfx)tst-audit19a.out: $(objpfx)tst-auditmod19a.so ++tst-audit19a-ENV = LD_AUDIT=$(objpfx)tst-auditmod19a.so ++ ++$(objpfx)tst-audit19b.out: $(objpfx)tst-auditmod19b.so ++$(objpfx)tst-audit19b: $(objpfx)tst-audit19bmod.so ++tst-audit19b-ARGS = -- $(host-test-program-cmd) ++ + # tst-sonamemove links against an older implementation of the library. + LDFLAGS-tst-sonamemove-linkmod1.so = \ + -Wl,--version-script=tst-sonamemove-linkmod1.map \ +diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c +index 19de5de067a5ef07..7a84b1fa8c3a7fdd 100644 +--- a/elf/dl-reloc.c ++++ b/elf/dl-reloc.c +@@ -178,12 +178,28 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + int skip_ifunc = reloc_mode & __RTLD_NOIFUNC; + + #ifdef SHARED ++ bool consider_symbind = false; + /* If we are auditing, install the same handlers we need for profiling. */ + if ((reloc_mode & __RTLD_AUDIT) == 0) +- consider_profiling |= GLRO(dl_audit) != NULL; ++ { ++ struct audit_ifaces *afct = GLRO(dl_audit); ++ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) ++ { ++ /* Profiling is needed only if PLT hooks are provided. */ ++ if (afct->ARCH_LA_PLTENTER != NULL ++ || afct->ARCH_LA_PLTEXIT != NULL) ++ consider_profiling = 1; ++ if (afct->symbind != NULL) ++ consider_symbind = true; ++ ++ afct = afct->next; ++ } ++ } + #elif defined PROF + /* Never use dynamic linker profiling for gprof profiling code. */ + # define consider_profiling 0 ++#else ++# define consider_symbind 0 + #endif + + if (l->l_relocated) +@@ -278,7 +294,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[], + ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc); + + #ifndef PROF +- if (__glibc_unlikely (consider_profiling) ++ if ((consider_profiling || consider_symbind) + && l->l_info[DT_PLTRELSZ] != NULL) + { + /* Allocate the array which will contain the already found +diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c +index ec0b2164825fa538..71ec65264ff780fb 100644 +--- a/elf/dl-runtime.c ++++ b/elf/dl-runtime.c +@@ -123,6 +123,37 @@ _dl_fixup ( + && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)) + value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value)); + ++#ifdef SHARED ++ /* Auditing checkpoint: we have a new binding. Provide the auditing ++ libraries the possibility to change the value and tell us whether further ++ auditing is wanted. ++ The l_reloc_result is only allocated if there is an audit module which ++ provides a la_symbind. */ ++ if (l->l_reloc_result != NULL) ++ { ++ /* This is the address in the array where we store the result of previous ++ relocations. */ ++ struct reloc_result *reloc_result ++ = &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))]; ++ unsigned int init = atomic_load_acquire (&reloc_result->init); ++ if (init == 0) ++ { ++ _dl_audit_symbind (l, reloc_result, sym, &value, result); ++ ++ /* Store the result for later runs. */ ++ if (__glibc_likely (! GLRO(dl_bind_not))) ++ { ++ reloc_result->addr = value; ++ /* Guarantee all previous writes complete before init is ++ updated. See CONCURRENCY NOTES below. */ ++ atomic_store_release (&reloc_result->init, 1); ++ } ++ } ++ else ++ value = reloc_result->addr; ++ } ++#endif ++ + /* Finally, fix up the plt itself. */ + if (__glibc_unlikely (GLRO(dl_bind_not))) + return value; +diff --git a/elf/rtld.c b/elf/rtld.c +index 767acd122262b824..2994578ba3a5f911 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1027,13 +1027,7 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d); + "la_objsearch\0" + "la_objopen\0" + "la_preinit\0" +-#if __ELF_NATIVE_CLASS == 32 +- "la_symbind32\0" +-#elif __ELF_NATIVE_CLASS == 64 +- "la_symbind64\0" +-#else +-# error "__ELF_NATIVE_CLASS must be defined" +-#endif ++ LA_SYMBIND "\0" + #define STRING(s) __STRING (s) + "la_" STRING (ARCH_LA_PLTENTER) "\0" + "la_" STRING (ARCH_LA_PLTEXIT) "\0" +diff --git a/elf/tst-audit19a.c b/elf/tst-audit19a.c +new file mode 100644 +index 0000000000000000..035cde9351c2711b +--- /dev/null ++++ b/elf/tst-audit19a.c +@@ -0,0 +1,38 @@ ++/* Check if DT_AUDIT a module without la_plt{enter,exit} symbols does not incur ++ in profiling (BZ#15533). ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ void *h = xdlopen ("tst-auditmod19a.so", RTLD_NOW); ++ ++ struct link_map *lmap; ++ TEST_VERIFY_EXIT (dlinfo (h, RTLD_DI_LINKMAP, &lmap) == 0); ++ ++ /* The internal array is only allocated if profiling is enabled. */ ++ TEST_VERIFY (lmap->l_reloc_result == NULL); ++ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-audit19b.c b/elf/tst-audit19b.c +new file mode 100644 +index 0000000000000000..da015734f24e0d79 +--- /dev/null ++++ b/elf/tst-audit19b.c +@@ -0,0 +1,94 @@ ++/* Check if DT_AUDIT a module with la_plt{enter,exit} call la_symbind ++ for lazy resolution. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int restart; ++#define CMDLINE_OPTIONS \ ++ { "restart", no_argument, &restart, 1 }, ++ ++int tst_audit18bmod1_func (void); ++ ++static int ++handle_restart (void) ++{ ++ TEST_COMPARE (tst_audit18bmod1_func (), 10); ++ return 0; ++} ++ ++static inline bool ++startswith (const char *str, const char *pre) ++{ ++ size_t lenpre = strlen (pre); ++ size_t lenstr = strlen (str); ++ return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0; ++} ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ /* We must have either: ++ - One our fource parameters left if called initially: ++ + path to ld.so optional ++ + "--library-path" optional ++ + the library path optional ++ + the application name */ ++ ++ if (restart) ++ return handle_restart (); ++ ++ char *spargv[9]; ++ int i = 0; ++ for (; i < argc - 1; i++) ++ spargv[i] = argv[i + 1]; ++ spargv[i++] = (char *) "--direct"; ++ spargv[i++] = (char *) "--restart"; ++ spargv[i] = NULL; ++ ++ setenv ("LD_AUDIT", "tst-auditmod18b.so", 0); ++ struct support_capture_subprocess result ++ = support_capture_subprogram (spargv[0], spargv); ++ support_capture_subprocess_check (&result, "tst-audit18b", 0, sc_allow_stderr); ++ ++ bool find_symbind = false; ++ ++ FILE *out = fmemopen (result.err.buffer, result.err.length, "r"); ++ TEST_VERIFY (out != NULL); ++ char *buffer = NULL; ++ size_t buffer_length = 0; ++ while (xgetline (&buffer, &buffer_length, out)) ++ if (startswith (buffer, "la_symbind: tst_audit18bmod1_func") == 0) ++ find_symbind = true; ++ ++ TEST_COMPARE (find_symbind, true); ++ ++ free (buffer); ++ xfclose (out); ++ ++ return 0; ++} ++ ++#define TEST_FUNCTION_ARGV do_test ++#include +diff --git a/elf/tst-audit19bmod.c b/elf/tst-audit19bmod.c +new file mode 100644 +index 0000000000000000..9ffdcd8f3ffbc38e +--- /dev/null ++++ b/elf/tst-audit19bmod.c +@@ -0,0 +1,23 @@ ++/* Extra module for tst-audit18b. ++ 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 ++ . */ ++ ++int ++tst_audit18bmod1_func (void) ++{ ++ return 10; ++} +diff --git a/elf/tst-auditmod19a.c b/elf/tst-auditmod19a.c +new file mode 100644 +index 0000000000000000..f58204099457743d +--- /dev/null ++++ b/elf/tst-auditmod19a.c +@@ -0,0 +1,25 @@ ++/* Audit module for tst-audit18a. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++unsigned int ++la_version (unsigned int version) ++{ ++ return LAV_CURRENT; ++} +diff --git a/elf/tst-auditmod19b.c b/elf/tst-auditmod19b.c +new file mode 100644 +index 0000000000000000..e2248b2a75946746 +--- /dev/null ++++ b/elf/tst-auditmod19b.c +@@ -0,0 +1,46 @@ ++/* Audit module for tst-audit18b. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++unsigned int ++la_version (unsigned int version) ++{ ++ return LAV_CURRENT; ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ return LA_FLG_BINDTO | LA_FLG_BINDFROM; ++} ++ ++uintptr_t ++#if __ELF_NATIVE_CLASS == 32 ++la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook, ++ uintptr_t *defcook, unsigned int *flags, const char *symname) ++#else ++la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, ++ uintptr_t *defcook, unsigned int *flags, const char *symname) ++#endif ++{ ++ fprintf (stderr, "la_symbind: %s\n", symname); ++ return sym->st_value; ++} +diff --git a/include/link.h b/include/link.h +index cdd011f59445e490..dd491989beb41353 100644 +--- a/include/link.h ++++ b/include/link.h +@@ -353,8 +353,10 @@ struct link_map + + #if __ELF_NATIVE_CLASS == 32 + # define symbind symbind32 ++# define LA_SYMBIND "la_symbind32" + #elif __ELF_NATIVE_CLASS == 64 + # define symbind symbind64 ++# define LA_SYMBIND "la_symbind64" + #else + # error "__ELF_NATIVE_CLASS must be defined" + #endif diff --git a/glibc-rh2047981-24.patch b/glibc-rh2047981-24.patch new file mode 100644 index 0000000..c6fc26a --- /dev/null +++ b/glibc-rh2047981-24.patch @@ -0,0 +1,296 @@ +Added $(libdl) to $(objpfx)tst-audit-tlsdesc-dlopen in elf/Makefile +since we still need $(libdl) in RHEL8. + +commit d1b38173c9255b1a4ae00018ad9b35404a7c74d0 +Author: Adhemerval Zanella +Date: Wed Jun 30 15:51:31 2021 -0300 + + elf: Add audit tests for modules with TLSDESC + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Florian Weimer + +diff --git a/elf/Makefile b/elf/Makefile +index 0cc03ffe2984ee50..d8d9734df0fea9a8 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -375,6 +375,22 @@ modules-names += tst-gnu2-tls1mod + $(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so + tst-gnu2-tls1mod.so-no-z-defs = yes + CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2 ++ ++tests += tst-audit-tlsdesc tst-audit-tlsdesc-dlopen ++modules-names += tst-audit-tlsdesc-mod1 tst-audit-tlsdesc-mod2 tst-auditmod-tlsdesc ++$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \ ++ $(objpfx)tst-audit-tlsdesc-mod2.so \ ++ $(shared-thread-library) ++CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=gnu2 ++CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=gnu2 ++$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library) $(libdl) ++$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \ ++ $(objpfx)tst-audit-tlsdesc-mod2.so ++$(objpfx)tst-audit-tlsdesc-mod1.so: $(objpfx)tst-audit-tlsdesc-mod2.so ++$(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so ++tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so ++$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so ++tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so + endif + ifeq (yes,$(have-protected-data)) + modules-names += tst-protected1moda tst-protected1modb +diff --git a/elf/tst-audit-tlsdesc-dlopen.c b/elf/tst-audit-tlsdesc-dlopen.c +new file mode 100644 +index 0000000000000000..9c16bb087aca1b77 +--- /dev/null ++++ b/elf/tst-audit-tlsdesc-dlopen.c +@@ -0,0 +1,67 @@ ++/* DT_AUDIT with modules with TLSDESC. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++static void * ++thr_func (void *mod) ++{ ++ int* (*get_global1)(void) = xdlsym (mod, "get_global1"); ++ int* (*get_global2)(void) = xdlsym (mod, "get_global2"); ++ void (*set_global2)(int) = xdlsym (mod, "set_global2"); ++ int* (*get_local1)(void) = xdlsym (mod, "get_local1"); ++ int* (*get_local2)(void) = xdlsym (mod, "get_local2"); ++ ++ int *global1 = get_global1 (); ++ TEST_COMPARE (*global1, 0); ++ ++*global1; ++ ++ int *global2 = get_global2 (); ++ TEST_COMPARE (*global2, 0); ++ ++*global2; ++ TEST_COMPARE (*global2, 1); ++ ++ set_global2 (10); ++ TEST_COMPARE (*global2, 10); ++ ++ int *local1 = get_local1 (); ++ TEST_COMPARE (*local1, 0); ++ ++*local1; ++ ++ int *local2 = get_local2 (); ++ TEST_COMPARE (*local2, 0); ++ ++*local2; ++ ++ return 0; ++} ++ ++static int ++do_test (void) ++{ ++ void *mod = xdlopen ("tst-audit-tlsdesc-mod1.so", RTLD_LAZY); ++ ++ pthread_t thr = xpthread_create (NULL, thr_func, mod); ++ void *r = xpthread_join (thr); ++ TEST_VERIFY (r == NULL); ++ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-audit-tlsdesc-mod1.c b/elf/tst-audit-tlsdesc-mod1.c +new file mode 100644 +index 0000000000000000..61c7dd99a2fb5e28 +--- /dev/null ++++ b/elf/tst-audit-tlsdesc-mod1.c +@@ -0,0 +1,41 @@ ++/* DT_AUDIT with modules with TLSDESC. ++ 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 ++ . */ ++ ++__thread int global1; ++ ++int * ++get_global1 (void) ++{ ++ return &global1; ++} ++ ++static __thread int local1; ++ ++void * ++get_local1 (void) ++{ ++ return &local1; ++} ++ ++extern __thread int global2; ++ ++void ++set_global2 (int v) ++{ ++ global2 = v; ++} +diff --git a/elf/tst-audit-tlsdesc-mod2.c b/elf/tst-audit-tlsdesc-mod2.c +new file mode 100644 +index 0000000000000000..28aef635f688ee03 +--- /dev/null ++++ b/elf/tst-audit-tlsdesc-mod2.c +@@ -0,0 +1,33 @@ ++/* DT_AUDIT with modules with TLSDESC. ++ 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 ++ . */ ++ ++__thread int global2; ++ ++int * ++get_global2 (void) ++{ ++ return &global2; ++} ++ ++static __thread int local2; ++ ++void * ++get_local2 (void) ++{ ++ return &local2; ++} +diff --git a/elf/tst-audit-tlsdesc.c b/elf/tst-audit-tlsdesc.c +new file mode 100644 +index 0000000000000000..3c8be81c95528f47 +--- /dev/null ++++ b/elf/tst-audit-tlsdesc.c +@@ -0,0 +1,60 @@ ++/* DT_AUDIT with modules with TLSDESC. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++extern __thread int global1; ++extern __thread int global2; ++void *get_local1 (void); ++void set_global2 (int v); ++void *get_local2 (void); ++ ++static void * ++thr_func (void *clousure) ++{ ++ TEST_COMPARE (global1, 0); ++ ++global1; ++ TEST_COMPARE (global2, 0); ++ ++global2; ++ TEST_COMPARE (global2, 1); ++ ++ set_global2 (10); ++ TEST_COMPARE (global2, 10); ++ ++ int *local1 = get_local1 (); ++ TEST_COMPARE (*local1, 0); ++ ++*local1; ++ ++ int *local2 = get_local2 (); ++ TEST_COMPARE (*local2, 0); ++ ++*local2; ++ ++ return 0; ++} ++ ++static int ++do_test (void) ++{ ++ pthread_t thr = xpthread_create (NULL, thr_func, NULL); ++ void *r = xpthread_join (thr); ++ TEST_VERIFY (r == NULL); ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-auditmod-tlsdesc.c b/elf/tst-auditmod-tlsdesc.c +new file mode 100644 +index 0000000000000000..e4b835d1f1fb6f73 +--- /dev/null ++++ b/elf/tst-auditmod-tlsdesc.c +@@ -0,0 +1,25 @@ ++/* DT_AUDIT with modules with TLSDESC. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++unsigned int ++la_version (unsigned int version) ++{ ++ return LAV_CURRENT; ++} diff --git a/glibc-rh2047981-25.patch b/glibc-rh2047981-25.patch new file mode 100644 index 0000000..14cbb8d --- /dev/null +++ b/glibc-rh2047981-25.patch @@ -0,0 +1,313 @@ +commit f0e23d34a7bdf6b90fba954ee741419171ac41b2 +Author: Adhemerval Zanella +Date: Mon Jul 19 18:42:26 2021 -0300 + + elf: Issue audit la_objopen for vDSO + + The vDSO is is listed in the link_map chain, but is never the subject of + an la_objopen call. A new internal flag __RTLD_VDSO is added that + acts as __RTLD_OPENEXEC to allocate the required 'struct auditstate' + extra space for the 'struct link_map'. + + The return value from the callback is currently ignored, since there + is no PLT call involved by glibc when using the vDSO, neither the vDSO + are exported directly. + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Florian Weimer + +Conflicts: + elf/Makefile + +diff --git a/elf/Makefile b/elf/Makefile +index d8d9734df0fea9a8..f047c1cce0c55da0 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -222,6 +222,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-audit17 \ + tst-audit18 \ + tst-audit19b \ ++ tst-audit22 \ + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -363,6 +364,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-auditmod19a \ + tst-auditmod19b \ + tst-audit19bmod \ ++ tst-auditmod22 \ + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +@@ -1577,6 +1579,9 @@ $(objpfx)tst-audit19b.out: $(objpfx)tst-auditmod19b.so + $(objpfx)tst-audit19b: $(objpfx)tst-audit19bmod.so + tst-audit19b-ARGS = -- $(host-test-program-cmd) + ++$(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so ++tst-audit22-ARGS = -- $(host-test-program-cmd) ++ + # tst-sonamemove links against an older implementation of the library. + LDFLAGS-tst-sonamemove-linkmod1.so = \ + -Wl,--version-script=tst-sonamemove-linkmod1.map \ +diff --git a/elf/dl-object.c b/elf/dl-object.c +index 05a7750c65305771..3be309ecf1b5d4e2 100644 +--- a/elf/dl-object.c ++++ b/elf/dl-object.c +@@ -59,16 +59,19 @@ _dl_new_object (char *realname, const char *libname, int type, + { + #ifdef SHARED + unsigned int naudit; +- if (__glibc_unlikely ((mode & __RTLD_OPENEXEC) != 0)) ++ if (__glibc_unlikely ((mode & (__RTLD_OPENEXEC | __RTLD_VDSO)) != 0)) + { +- assert (type == lt_executable); +- assert (nsid == LM_ID_BASE); ++ if (mode & __RTLD_OPENEXEC) ++ { ++ assert (type == lt_executable); ++ assert (nsid == LM_ID_BASE); + +- /* Ignore the specified libname for the main executable. It is +- only known with an explicit loader invocation. */ +- libname = ""; ++ /* Ignore the specified libname for the main executable. It is ++ only known with an explicit loader invocation. */ ++ libname = ""; ++ } + +- /* We create the map for the executable before we know whether ++ /* We create the map for the executable and vDSO before we know whether + we have auditing libraries and if yes, how many. Assume the + worst. */ + naudit = DL_NNS; +diff --git a/elf/rtld.c b/elf/rtld.c +index 2994578ba3a5f911..efcbeac6c24c4b7b 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1917,6 +1917,12 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + assert (i == npreloads); + } + ++#ifdef NEED_DL_SYSINFO_DSO ++ /* Now that the audit modules are opened, call la_objopen for the vDSO. */ ++ if (GLRO(dl_sysinfo_map) != NULL) ++ _dl_audit_objopen (GLRO(dl_sysinfo_map), LM_ID_BASE); ++#endif ++ + /* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD + specified some libraries to load, these are inserted before the actual + dependencies in the executable's searchlist for symbol resolution. */ +diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h +index 34b1d5e8c37c2610..d2b35a080b57c183 100644 +--- a/elf/setup-vdso.h ++++ b/elf/setup-vdso.h +@@ -30,7 +30,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)), + We just want our data structures to describe it as if we had just + mapped and relocated it normally. */ + struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL, +- 0, LM_ID_BASE); ++ __RTLD_VDSO, LM_ID_BASE); + if (__glibc_likely (l != NULL)) + { + static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro; +diff --git a/elf/tst-audit22.c b/elf/tst-audit22.c +new file mode 100644 +index 0000000000000000..18fd22a760ddc3d8 +--- /dev/null ++++ b/elf/tst-audit22.c +@@ -0,0 +1,124 @@ ++/* Check DTAUDIT and vDSO interaction. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int restart; ++#define CMDLINE_OPTIONS \ ++ { "restart", no_argument, &restart, 1 }, ++ ++static uintptr_t vdso_addr; ++ ++static int ++handle_restart (void) ++{ ++ fprintf (stderr, "vdso: %p\n", (void*) vdso_addr); ++ return 0; ++} ++ ++static uintptr_t ++parse_address (const char *str) ++{ ++ void *r; ++ TEST_COMPARE (sscanf (str, "%p\n", &r), 1); ++ return (uintptr_t) r; ++} ++ ++static inline bool ++startswith (const char *str, const char *pre) ++{ ++ size_t lenpre = strlen (pre); ++ size_t lenstr = strlen (str); ++ return lenstr >= lenpre && memcmp (pre, str, lenpre) == 0; ++} ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ vdso_addr = getauxval (AT_SYSINFO_EHDR); ++ if (vdso_addr == 0) ++ FAIL_UNSUPPORTED ("getauxval (AT_SYSINFO_EHDR) returned 0"); ++ ++ /* We must have either: ++ - One our fource parameters left if called initially: ++ + path to ld.so optional ++ + "--library-path" optional ++ + the library path optional ++ + the application name */ ++ if (restart) ++ return handle_restart (); ++ ++ char *spargv[9]; ++ int i = 0; ++ for (; i < argc - 1; i++) ++ spargv[i] = argv[i + 1]; ++ spargv[i++] = (char *) "--direct"; ++ spargv[i++] = (char *) "--restart"; ++ spargv[i] = NULL; ++ ++ setenv ("LD_AUDIT", "tst-auditmod22.so", 0); ++ struct support_capture_subprocess result ++ = support_capture_subprogram (spargv[0], spargv); ++ support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr); ++ ++ /* The respawned process should always print the vDSO address (otherwise it ++ will fails as unsupported). However, on some architectures the audit ++ module might see the vDSO with l_addr being 0, meaning a fixed mapping ++ (linux-gate.so). In this case we don't check its value against ++ AT_SYSINFO_EHDR one. */ ++ uintptr_t vdso_process = 0; ++ bool vdso_audit_found = false; ++ uintptr_t vdso_audit = 0; ++ ++ FILE *out = fmemopen (result.err.buffer, result.err.length, "r"); ++ TEST_VERIFY (out != NULL); ++ char *buffer = NULL; ++ size_t buffer_length = 0; ++ while (xgetline (&buffer, &buffer_length, out)) ++ { ++ if (startswith (buffer, "vdso: ")) ++ vdso_process = parse_address (buffer + strlen ("vdso: ")); ++ else if (startswith (buffer, "vdso found: ")) ++ { ++ vdso_audit = parse_address (buffer + strlen ("vdso found: ")); ++ vdso_audit_found = true; ++ } ++ } ++ ++ TEST_COMPARE (vdso_audit_found, true); ++ if (vdso_audit != 0) ++ TEST_COMPARE (vdso_process, vdso_audit); ++ ++ free (buffer); ++ xfclose (out); ++ ++ return 0; ++} ++ ++#define TEST_FUNCTION_ARGV do_test ++#include +diff --git a/elf/tst-auditmod22.c b/elf/tst-auditmod22.c +new file mode 100644 +index 0000000000000000..8e05ce8cbb215dd5 +--- /dev/null ++++ b/elf/tst-auditmod22.c +@@ -0,0 +1,51 @@ ++/* Check DTAUDIT and vDSO interaction. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static inline bool ++startswith (const char *str, const char *pre) ++{ ++ size_t lenpre = strlen (pre); ++ size_t lenstr = strlen (str); ++ return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0; ++} ++ ++unsigned int ++la_version (unsigned int version) ++{ ++ return LAV_CURRENT; ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ /* The linux-gate.so is placed at a fixed address, thus l_addr being 0, ++ and it might be the value reported as the AT_SYSINFO_EHDR. */ ++ if (map->l_addr == 0 && startswith (map->l_name, "linux-gate.so")) ++ fprintf (stderr, "vdso found: %p\n", NULL); ++ else if (map->l_addr == getauxval (AT_SYSINFO_EHDR)) ++ fprintf (stderr, "vdso found: %p\n", (void*) map->l_addr); ++ ++ return 0; ++} +diff --git a/include/dlfcn.h b/include/dlfcn.h +index 109586a1d968b630..a39cc9c69f55a56a 100644 +--- a/include/dlfcn.h ++++ b/include/dlfcn.h +@@ -12,6 +12,8 @@ + #define __RTLD_AUDIT 0x08000000 + #define __RTLD_SECURE 0x04000000 /* Apply additional security checks. */ + #define __RTLD_NOIFUNC 0x02000000 /* Suppress calling ifunc functions. */ ++#define __RTLD_VDSO 0x01000000 /* Tell _dl_new_object the object is ++ system-loaded. */ + + #define __LM_ID_CALLER -2 + diff --git a/glibc-rh2047981-26.patch b/glibc-rh2047981-26.patch new file mode 100644 index 0000000..b05628f --- /dev/null +++ b/glibc-rh2047981-26.patch @@ -0,0 +1,170 @@ +Added $(objpfx)tst-auditmod20: $(libdl) in elf/Makefile since +we still have $(libdl) in RHEL8. + +commit 484e672ddabe0a919a692520e6ac8f2580866235 +Author: Adhemerval Zanella +Date: Wed Jun 30 17:33:57 2021 -0300 + + elf: Do not fail for failed dlmopen on audit modules (BZ #28061) + + The dl_main sets the LM_ID_BASE to RT_ADD just before starting to + add load new shared objects. The state is set to RT_CONSISTENT just + after all objects are loaded. + + However if a audit modules tries to dlmopen an inexistent module, + the _dl_open will assert that the namespace is in an inconsistent + state. + + This is different than dlopen, since first it will not use + LM_ID_BASE and second _dl_map_object_from_fd is the sole responsible + to set and reset the r_state value. + + So the assert on _dl_open can not really be seen if the state is + consistent, since _dt_main resets it. This patch removes the assert. + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Florian Weimer + +Conflicts: + elf/dl-open.c + Uses dl_debug_initialize instead of dl_debug_update. + +diff --git a/elf/Makefile b/elf/Makefile +index f047c1cce0c55da0..7c7b9e1937d3e41c 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -222,6 +222,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-audit17 \ + tst-audit18 \ + tst-audit19b \ ++ tst-audit20 \ + tst-audit22 \ + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ +@@ -364,6 +365,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + tst-auditmod19a \ + tst-auditmod19b \ + tst-audit19bmod \ ++ tst-auditmod20 \ + tst-auditmod22 \ + + # Most modules build with _ISOMAC defined, but those filtered out +@@ -1579,6 +1581,10 @@ $(objpfx)tst-audit19b.out: $(objpfx)tst-auditmod19b.so + $(objpfx)tst-audit19b: $(objpfx)tst-audit19bmod.so + tst-audit19b-ARGS = -- $(host-test-program-cmd) + ++$(objpfx)tst-audit20.out: $(objpfx)tst-auditmod20.so ++tst-audit20-ENV = LD_AUDIT=$(objpfx)tst-auditmod20.so ++$(objpfx)tst-auditmod20.so: $(libdl) ++ + $(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so + tst-audit22-ARGS = -- $(host-test-program-cmd) + +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 660a56b2fb2639cd..6b85e9ab4e249f86 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -911,8 +911,6 @@ no more namespaces available for dlmopen()")); + the flag here. */ + } + +- assert (_dl_debug_initialize (0, args.nsid)->r_state == RT_CONSISTENT); +- + /* Release the lock. */ + __rtld_lock_unlock_recursive (GL(dl_load_lock)); + +diff --git a/elf/tst-audit20.c b/elf/tst-audit20.c +new file mode 100644 +index 0000000000000000..6f39ccee865b012b +--- /dev/null ++++ b/elf/tst-audit20.c +@@ -0,0 +1,25 @@ ++/* Check dlopen failure on audit modules. ++ 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 ++ . */ ++ ++static int ++do_test (void) ++{ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-auditmod20.c b/elf/tst-auditmod20.c +new file mode 100644 +index 0000000000000000..c57e50ee4e88dd6b +--- /dev/null ++++ b/elf/tst-auditmod20.c +@@ -0,0 +1,57 @@ ++/* Check dlopen failure on audit modules. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++unsigned int ++la_version (unsigned int v) ++{ ++ return LAV_CURRENT; ++} ++ ++static void ++check (void) ++{ ++ { ++ void *mod = dlopen ("nonexistent.so", RTLD_NOW); ++ if (mod != NULL) ++ abort (); ++ } ++ ++ { ++ void *mod = dlmopen (LM_ID_BASE, "nonexistent.so", RTLD_NOW); ++ if (mod != NULL) ++ abort (); ++ } ++} ++ ++void ++la_activity (uintptr_t *cookie, unsigned int flag) ++{ ++ if (flag != LA_ACT_CONSISTENT) ++ return; ++ check (); ++} ++ ++void ++la_preinit (uintptr_t *cookie) ++{ ++ check (); ++} diff --git a/glibc-rh2047981-27.patch b/glibc-rh2047981-27.patch new file mode 100644 index 0000000..08f1448 --- /dev/null +++ b/glibc-rh2047981-27.patch @@ -0,0 +1,557 @@ +commit 28713c06129f8f64f88c423266e6ff2880216509 +Author: H.J. Lu +Date: Mon Dec 13 09:43:52 2021 -0800 + + elf: Sort tests and modules-names + + Sort tests and modules-names to reduce future conflicts. + +Conflicts: + elf/Makefile + Complete rewrite of sorted lists. + +diff --git a/elf/Makefile b/elf/Makefile +index 7c7b9e1937d3e41c..914cb5ad2f2c3aea 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -185,46 +185,130 @@ tests-static += tst-tls9-static + tst-tls9-static-ENV = \ + LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)dlfcn + +-tests += restest1 preloadtest loadfail multiload origtest resolvfail \ +- constload1 order noload filter \ +- reldep reldep2 reldep3 reldep4 nodelete nodelete2 \ +- nodlopen nodlopen2 lateglobal initfirst global \ +- restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \ +- tst-tls4 tst-tls5 \ +- tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \ +- tst-tls16 tst-tls17 tst-tls18 tst-tls19 tst-tls-dlinfo \ +- tst-align tst-align2 \ +- tst-dlmodcount tst-dlopenrpath tst-deep1 \ +- tst-dlmopen1 tst-dlmopen3 \ +- unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \ +- tst-audit1 tst-audit2 tst-audit8 tst-audit9 \ +- tst-addr1 tst-thrlock \ +- tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \ +- tst-nodelete tst-dlopen-nodelete-reloc) \ +- tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \ +- tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \ +- tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \ +- tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \ +- tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \ +- tst-audit13 \ +- tst-sonamemove-link tst-sonamemove-dlopen \ +- tst-auditmany tst-initfinilazyfail \ +- tst-dlopenfail tst-dlopenfail-2 \ +- tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \ +- tst-audit14 tst-audit15 tst-audit16 \ +- tst-tls-ie tst-tls-ie-dlmopen \ +- argv0test \ +- tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \ +- tst-tls20 tst-tls21 \ +- tst-rtld-run-static \ +- tst-dlmopen-dlerror \ +- tst-dlmopen-gethostbyname \ +- tst-audit17 \ +- tst-audit18 \ +- tst-audit19b \ +- tst-audit20 \ +- tst-audit22 \ ++tests += \ ++ argv0test \ ++ constload1 \ ++ dblload \ ++ dblunload \ ++ filter \ ++ global \ ++ initfirst \ ++ lateglobal \ ++ loadfail \ ++ multiload \ ++ next \ ++ nodelete \ ++ nodelete2 \ ++ nodlopen \ ++ nodlopen2 \ ++ noload \ ++ order \ ++ order2 \ ++ origtest \ ++ preloadtest \ ++ reldep \ ++ reldep2 \ ++ reldep3 \ ++ reldep4 \ ++ reldep5 \ ++ reldep6 \ ++ reldep7 \ ++ reldep8 \ ++ resolvfail \ ++ restest1 \ ++ restest2 \ ++ tst-absolute-sym \ ++ tst-absolute-zero \ ++ tst-addr1 \ ++ tst-align \ ++ tst-align2 \ ++ tst-audit1 \ ++ tst-audit11 \ ++ tst-audit12 \ ++ tst-audit13 \ ++ tst-audit14 \ ++ tst-audit15 \ ++ tst-audit16 \ ++ tst-audit17 \ ++ tst-audit18 \ ++ tst-audit19b \ ++ tst-audit2 \ ++ tst-audit20 \ ++ tst-audit22 \ ++ tst-audit8 \ ++ tst-audit9 \ ++ tst-auditmany \ ++ tst-auxobj \ ++ tst-auxobj-dlopen \ ++ tst-big-note \ ++ tst-debug1 \ ++ tst-deep1 \ ++ tst-dlmodcount \ ++ tst-dlmopen1 \ ++ tst-dlmopen3 \ ++ tst-dlmopen-dlerror \ ++ tst-dlmopen-gethostbyname \ ++ tst-dlopenfail \ ++ tst-dlopenfail-2 \ ++ tst-dlopenrpath \ ++ tst-dlsym-error \ ++ tst-filterobj \ ++ tst-filterobj-dlopen \ ++ tst-glibc-hwcaps \ ++ tst-glibc-hwcaps-mask \ ++ tst-glibc-hwcaps-prepend \ ++ tst-global1 \ ++ tst-initfinilazyfail \ ++ tst-initorder \ ++ tst-initorder2 \ ++ tst-latepthread \ ++ tst-main1 \ ++ tst-nodelete2 \ ++ tst-nodelete-dlclose \ ++ tst-nodelete-opened \ ++ tst-noload \ ++ tst-null-argv \ ++ tst-relsort1 \ ++ tst-rtld-run-static \ ++ tst-sonamemove-dlopen \ ++ tst-sonamemove-link \ ++ tst-thrlock \ ++ tst-tls10 \ ++ tst-tls11 \ ++ tst-tls12 \ ++ tst-tls13 \ ++ tst-tls14 \ ++ tst-tls15 \ ++ tst-tls16 \ ++ tst-tls17 \ ++ tst-tls18 \ ++ tst-tls19 \ ++ tst-tls20 \ ++ tst-tls21 \ ++ tst-tls4 \ ++ tst-tls5 \ ++ tst-tlsalign \ ++ tst-tlsalign-extern \ ++ tst-tls-dlinfo \ ++ tst-tls-ie \ ++ tst-tls-ie-dlmopen \ ++ tst-tls-manydynamic \ ++ tst-unique1 \ ++ tst-unique2 \ ++ unload3 \ ++ unload4 \ ++ unload5 \ ++ unload6 \ ++ unload7 \ ++ unload8 \ + # reldep9 ++tests-cxx = \ ++ tst-dlopen-nodelete-reloc \ ++ tst-nodelete \ ++ tst-unique3 \ ++ tst-unique4 \ ++ ++tests += $(if $(CXX),$(tests-cxx)) + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ + tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \ +@@ -266,107 +350,269 @@ tst-tls-many-dynamic-modules-dep-bad = \ + extra-test-objs += $(tlsmod17a-modules:=.os) $(tlsmod18a-modules:=.os) \ + tst-tlsalign-vars.o + test-extras += tst-tlsmod17a tst-tlsmod18a tst-tlsalign-vars +-modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ +- testobj1_1 failobj constload2 constload3 unloadmod \ +- dep1 dep2 dep3 dep4 vismod1 vismod2 vismod3 \ +- nodelmod1 nodelmod2 nodelmod3 nodelmod4 \ +- nodel2mod1 nodel2mod2 nodel2mod3 \ +- nodlopenmod nodlopenmod2 filtmod1 filtmod2 \ +- reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2 \ +- reldep4mod1 reldep4mod2 reldep4mod3 reldep4mod4 \ +- neededobj1 neededobj2 neededobj3 neededobj4 \ +- neededobj5 neededobj6 firstobj globalmod1 \ +- unload2mod unload2dep ltglobmod1 ltglobmod2 pathoptobj \ +- dblloadmod1 dblloadmod2 dblloadmod3 reldepmod5 reldepmod6 \ +- reldep6mod0 reldep6mod1 reldep6mod2 reldep6mod3 reldep6mod4 \ +- reldep7mod1 reldep7mod2 \ +- tst-tlsmod1 tst-tlsmod2 tst-tlsmod3 tst-tlsmod4 \ +- tst-tlsmod5 tst-tlsmod6 tst-tlsmod7 tst-tlsmod8 \ +- tst-tlsmod9 tst-tlsmod10 tst-tlsmod11 tst-tlsmod12 \ +- tst-tlsmod13 tst-tlsmod13a tst-tlsmod14a tst-tlsmod14b \ +- tst-tlsmod15a tst-tlsmod15b tst-tlsmod16a tst-tlsmod16b \ +- $(tlsmod17a-modules) tst-tlsmod17b $(tlsmod18a-modules) \ +- tst-tls19mod1 tst-tls19mod2 tst-tls19mod3 \ +- circlemod1 circlemod1a circlemod2 circlemod2a \ +- circlemod3 circlemod3a \ +- reldep8mod1 reldep8mod2 reldep8mod3 \ +- reldep9mod1 reldep9mod2 reldep9mod3 \ +- tst-alignmod tst-alignmod2 \ +- $(modules-execstack-$(have-z-execstack)) \ +- tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \ +- tst-dlmopen1mod tst-auditmod1 \ +- unload3mod1 unload3mod2 unload3mod3 unload3mod4 \ +- unload4mod1 unload4mod2 unload4mod3 unload4mod4 \ +- unload6mod1 unload6mod2 unload6mod3 \ +- unload7mod1 unload7mod2 \ +- unload8mod1 unload8mod1x unload8mod2 unload8mod3 \ +- order2mod1 order2mod2 order2mod3 order2mod4 \ +- tst-unique1mod1 tst-unique1mod2 \ +- tst-unique2mod1 tst-unique2mod2 \ +- tst-auditmod9a tst-auditmod9b \ +- $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \ +- tst-nodelete-uniquemod tst-nodelete-rtldmod \ +- tst-nodelete-zmod \ +- tst-dlopen-nodelete-reloc-mod1 \ +- tst-dlopen-nodelete-reloc-mod2 \ +- tst-dlopen-nodelete-reloc-mod3 \ +- tst-dlopen-nodelete-reloc-mod4 \ +- tst-dlopen-nodelete-reloc-mod5 \ +- tst-dlopen-nodelete-reloc-mod6 \ +- tst-dlopen-nodelete-reloc-mod7 \ +- tst-dlopen-nodelete-reloc-mod8 \ +- tst-dlopen-nodelete-reloc-mod9 \ +- tst-dlopen-nodelete-reloc-mod10 \ +- tst-dlopen-nodelete-reloc-mod11 \ +- tst-dlopen-nodelete-reloc-mod12 \ +- tst-dlopen-nodelete-reloc-mod13 \ +- tst-dlopen-nodelete-reloc-mod14 \ +- tst-dlopen-nodelete-reloc-mod15 \ +- tst-dlopen-nodelete-reloc-mod16 \ +- tst-dlopen-nodelete-reloc-mod17) \ +- tst-initordera1 tst-initorderb1 \ +- tst-initordera2 tst-initorderb2 \ +- tst-initordera3 tst-initordera4 \ +- tst-initorder2a tst-initorder2b tst-initorder2c \ +- tst-initorder2d \ +- tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \ +- tst-array5dep tst-null-argv-lib \ +- tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \ +- tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \ +- tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \ +- tst-latepthreadmod $(tst-tls-many-dynamic-modules) \ +- $(tst-tls-many-dynamic-modules-dep) \ +- $(tst-tls-many-dynamic-modules-dep-bad) \ +- tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \ +- tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \ +- tst-absolute-zero-lib tst-big-note-lib \ +- tst-audit13mod1 tst-sonamemove-linkmod1 \ +- tst-sonamemove-runmod1 tst-sonamemove-runmod2 \ +- tst-auditmanymod1 tst-auditmanymod2 tst-auditmanymod3 \ +- tst-auditmanymod4 tst-auditmanymod5 tst-auditmanymod6 \ +- tst-auditmanymod7 tst-auditmanymod8 tst-auditmanymod9 \ +- tst-initlazyfailmod tst-finilazyfailmod \ +- tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \ +- tst-dlopenfailmod3 \ +- tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee \ +- tst-auditlogmod-1 tst-auditlogmod-2 tst-auditlogmod-3 \ +- tst-tls-ie-mod0 tst-tls-ie-mod1 tst-tls-ie-mod2 \ +- tst-tls-ie-mod3 tst-tls-ie-mod4 tst-tls-ie-mod5 \ +- tst-tls-ie-mod6 libmarkermod1-1 libmarkermod1-2 libmarkermod1-3 \ +- libmarkermod2-1 libmarkermod2-2 \ +- libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \ +- libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \ +- libmarkermod5-1 libmarkermod5-2 libmarkermod5-3 libmarkermod5-4 \ +- libmarkermod5-5 tst-tls20mod-bad tst-tls21mod \ +- tst-dlmopen-dlerror-mod \ +- tst-dlmopen-gethostbyname-mod \ +- tst-auditmod18 \ +- tst-audit18mod \ +- tst-auditmod19a \ +- tst-auditmod19b \ +- tst-audit19bmod \ +- tst-auditmod20 \ +- tst-auditmod22 \ ++modules-names = \ ++ circlemod1 \ ++ circlemod1a \ ++ circlemod2 \ ++ circlemod2a \ ++ circlemod3 \ ++ circlemod3a \ ++ constload2 \ ++ constload3 \ ++ dblloadmod1 \ ++ dblloadmod2 \ ++ dblloadmod3 \ ++ dep1 \ ++ dep2 \ ++ dep3 \ ++ dep4 \ ++ failobj \ ++ filtmod1 \ ++ filtmod2 \ ++ firstobj \ ++ globalmod1 \ ++ libmarkermod1-1 \ ++ libmarkermod1-2 \ ++ libmarkermod1-3 \ ++ libmarkermod2-1 \ ++ libmarkermod2-2 \ ++ libmarkermod3-1 \ ++ libmarkermod3-2 \ ++ libmarkermod3-3 \ ++ libmarkermod4-1 \ ++ libmarkermod4-2 \ ++ libmarkermod4-3 \ ++ libmarkermod4-4 \ ++ libmarkermod5-1 \ ++ libmarkermod5-2 \ ++ libmarkermod5-3 \ ++ libmarkermod5-4 \ ++ libmarkermod5-5 \ ++ ltglobmod1 \ ++ ltglobmod2 \ ++ neededobj1 \ ++ neededobj2 \ ++ neededobj3 \ ++ neededobj4 \ ++ neededobj5 \ ++ neededobj6 \ ++ nextmod1 \ ++ nextmod2 \ ++ nodel2mod1 \ ++ nodel2mod2 \ ++ nodel2mod3 \ ++ nodelmod1 \ ++ nodelmod2 \ ++ nodelmod3 \ ++ nodelmod4 \ ++ nodlopenmod \ ++ nodlopenmod2 \ ++ order2mod1 \ ++ order2mod2 \ ++ order2mod3 \ ++ order2mod4 \ ++ pathoptobj \ ++ reldep4mod1 \ ++ reldep4mod2 \ ++ reldep4mod3 \ ++ reldep4mod4 \ ++ reldep6mod0 \ ++ reldep6mod1 \ ++ reldep6mod2 \ ++ reldep6mod3 \ ++ reldep6mod4 \ ++ reldep7mod1 \ ++ reldep7mod2 \ ++ reldep8mod1 \ ++ reldep8mod2 \ ++ reldep8mod3 \ ++ reldep9mod1 \ ++ reldep9mod2 \ ++ reldep9mod3 \ ++ reldepmod1 \ ++ reldepmod2 \ ++ reldepmod3 \ ++ reldepmod4 \ ++ reldepmod5 \ ++ reldepmod6 \ ++ testobj1 \ ++ testobj1_1 \ ++ testobj2 \ ++ testobj3 \ ++ testobj4 \ ++ testobj5 \ ++ testobj6 \ ++ tst-absolute-sym-lib \ ++ tst-absolute-zero-lib \ ++ tst-alignmod \ ++ tst-alignmod2 \ ++ tst-array2dep \ ++ tst-array5dep \ ++ tst-audit11mod1 \ ++ tst-audit11mod2 \ ++ tst-audit12mod1 \ ++ tst-audit12mod2 \ ++ tst-audit12mod3 \ ++ tst-audit13mod1 \ ++ tst-audit18mod \ ++ tst-audit19bmod \ ++ tst-auditlogmod-1 \ ++ tst-auditlogmod-2 \ ++ tst-auditlogmod-3 \ ++ tst-auditmanymod1 \ ++ tst-auditmanymod2 \ ++ tst-auditmanymod3 \ ++ tst-auditmanymod4 \ ++ tst-auditmanymod5 \ ++ tst-auditmanymod6 \ ++ tst-auditmanymod7 \ ++ tst-auditmanymod8 \ ++ tst-auditmanymod9 \ ++ tst-auditmod1 \ ++ tst-auditmod9a \ ++ tst-auditmod9b \ ++ tst-auditmod11 \ ++ tst-auditmod12 \ ++ tst-auditmod18 \ ++ tst-auditmod19a \ ++ tst-auditmod19b \ ++ tst-auditmod20 \ ++ tst-auditmod22 \ ++ tst-big-note-lib \ ++ tst-deep1mod1 \ ++ tst-deep1mod2 \ ++ tst-deep1mod3 \ ++ tst-dlmopen1mod \ ++ tst-dlmopen-dlerror-mod \ ++ tst-dlmopen-gethostbyname-mod \ ++ tst-dlopenfaillinkmod \ ++ tst-dlopenfailmod1 \ ++ tst-dlopenfailmod2 \ ++ tst-dlopenfailmod3 \ ++ tst-dlopenrpathmod \ ++ tst-filterobj-aux \ ++ tst-filterobj-filtee \ ++ tst-filterobj-flt \ ++ tst-finilazyfailmod \ ++ tst-initlazyfailmod \ ++ tst-initorder2a \ ++ tst-initorder2b \ ++ tst-initorder2c \ ++ tst-initorder2d \ ++ tst-initordera1 \ ++ tst-initordera2 \ ++ tst-initordera3 \ ++ tst-initordera4 \ ++ tst-initorderb1 \ ++ tst-initorderb2 \ ++ tst-latepthreadmod \ ++ tst-libc_dlvsym-dso \ ++ tst-main1mod \ ++ tst-nodelete2mod \ ++ tst-nodelete-dlclose-dso \ ++ tst-nodelete-dlclose-plugin \ ++ tst-nodelete-opened-lib \ ++ tst-null-argv-lib \ ++ tst-relsort1mod1 \ ++ tst-relsort1mod2 \ ++ tst-sonamemove-linkmod1 \ ++ tst-sonamemove-runmod1 \ ++ tst-sonamemove-runmod2 \ ++ tst-tls19mod1 \ ++ tst-tls19mod2 \ ++ tst-tls19mod3 \ ++ tst-tls20mod-bad \ ++ tst-tls21mod \ ++ tst-tlsalign-lib \ ++ tst-tls-ie-mod0 \ ++ tst-tls-ie-mod1 \ ++ tst-tls-ie-mod2 \ ++ tst-tls-ie-mod3 \ ++ tst-tls-ie-mod4 \ ++ tst-tls-ie-mod5 \ ++ tst-tls-ie-mod6 \ ++ tst-tlsmod1 \ ++ tst-tlsmod10 \ ++ tst-tlsmod11 \ ++ tst-tlsmod12 \ ++ tst-tlsmod13 \ ++ tst-tlsmod13a \ ++ tst-tlsmod14a \ ++ tst-tlsmod14b \ ++ tst-tlsmod15a \ ++ tst-tlsmod15b \ ++ tst-tlsmod16a \ ++ tst-tlsmod16b \ ++ tst-tlsmod17b \ ++ tst-tlsmod2 \ ++ tst-tlsmod3 \ ++ tst-tlsmod4 \ ++ tst-tlsmod5 \ ++ tst-tlsmod6 \ ++ tst-tlsmod7 \ ++ tst-tlsmod8 \ ++ tst-tlsmod9 \ ++ tst-unique1mod1 \ ++ tst-unique1mod2 \ ++ tst-unique2mod1 \ ++ tst-unique2mod2 \ ++ unload2dep \ ++ unload2mod \ ++ unload3mod1 \ ++ unload3mod2 \ ++ unload3mod3 \ ++ unload3mod4 \ ++ unload4mod1 \ ++ unload4mod2 \ ++ unload4mod3 \ ++ unload4mod4 \ ++ unload6mod1 \ ++ unload6mod2 \ ++ unload6mod3 \ ++ unload7mod1 \ ++ unload7mod2 \ ++ unload8mod1 \ ++ unload8mod1x \ ++ unload8mod2 \ ++ unload8mod3 \ ++ unloadmod \ ++ vismod1 \ ++ vismod2 \ ++ vismod3 \ ++ ++modules-names-cxx = \ ++ tst-dlopen-nodelete-reloc-mod1 \ ++ tst-dlopen-nodelete-reloc-mod10 \ ++ tst-dlopen-nodelete-reloc-mod11 \ ++ tst-dlopen-nodelete-reloc-mod12 \ ++ tst-dlopen-nodelete-reloc-mod13 \ ++ tst-dlopen-nodelete-reloc-mod14 \ ++ tst-dlopen-nodelete-reloc-mod15 \ ++ tst-dlopen-nodelete-reloc-mod16 \ ++ tst-dlopen-nodelete-reloc-mod17 \ ++ tst-dlopen-nodelete-reloc-mod2 \ ++ tst-dlopen-nodelete-reloc-mod3 \ ++ tst-dlopen-nodelete-reloc-mod4 \ ++ tst-dlopen-nodelete-reloc-mod5 \ ++ tst-dlopen-nodelete-reloc-mod6 \ ++ tst-dlopen-nodelete-reloc-mod7 \ ++ tst-dlopen-nodelete-reloc-mod8 \ ++ tst-dlopen-nodelete-reloc-mod9 \ ++ tst-nodelete-rtldmod \ ++ tst-nodelete-uniquemod \ ++ tst-nodelete-zmod \ ++ tst-unique3lib \ ++ tst-unique3lib2 \ ++ tst-unique4lib \ ++ ++modules-names += \ ++ $(if $(CXX),$(modules-names-cxx)) \ ++ $(modules-execstack-$(have-z-execstack)) \ ++ $(tst-tls-many-dynamic-modules) \ ++ $(tst-tls-many-dynamic-modules-dep) \ ++ $(tst-tls-many-dynamic-modules-dep-bad) \ ++ $(tlsmod17a-modules) \ ++ $(tlsmod18a-modules) \ + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. diff --git a/glibc-rh2047981-28.patch b/glibc-rh2047981-28.patch new file mode 100644 index 0000000..9fb9d98 --- /dev/null +++ b/glibc-rh2047981-28.patch @@ -0,0 +1,77 @@ +commit bfb5ed5df3dd4d9507b4922248dc445b690d19c0 +Author: H.J. Lu +Date: Fri Oct 15 10:44:49 2021 -0700 + + elf: Also try DT_RUNPATH for LD_AUDIT dlopen [BZ #28455] + + DT_RUNPATH is only used to find the immediate dependencies of the + executable or shared object containing the DT_RUNPATH entry. Update + LD_AUDIT dlopen call to try the DT_RUNPATH entry of the executable. + + Add tst-audit14a, which is copied from tst-audit14, to DT_RUNPATH and + build tst-audit14 with -Wl,--disable-new-dtags to test DT_RPATH. + + This partially fixes BZ #28455. + +Conflicts: + elf/Makefile + Rewrite test inclusion to use older stdout pattern. + +diff --git a/elf/Makefile b/elf/Makefile +index 914cb5ad2f2c3aea..4ec4e9a049156755 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -227,6 +227,7 @@ tests += \ + tst-audit12 \ + tst-audit13 \ + tst-audit14 \ ++ tst-audit14a \ + tst-audit15 \ + tst-audit16 \ + tst-audit17 \ +@@ -1788,9 +1789,11 @@ $(objpfx)tst-auditmany.out: $(objpfx)tst-auditmanymod1.so \ + tst-auditmany-ENV = \ + LD_AUDIT=tst-auditmanymod1.so:tst-auditmanymod2.so:tst-auditmanymod3.so:tst-auditmanymod4.so:tst-auditmanymod5.so:tst-auditmanymod6.so:tst-auditmanymod7.so:tst-auditmanymod8.so:tst-auditmanymod9.so + +-LDFLAGS-tst-audit14 = -Wl,--audit=tst-auditlogmod-1.so ++LDFLAGS-tst-audit14 = -Wl,--audit=tst-auditlogmod-1.so,--disable-new-dtags + $(objpfx)tst-auditlogmod-1.so: $(libsupport) + $(objpfx)tst-audit14.out: $(objpfx)tst-auditlogmod-1.so ++LDFLAGS-tst-audit14a = -Wl,--audit=tst-auditlogmod-1.so,--enable-new-dtags ++$(objpfx)tst-audit14a.out: $(objpfx)tst-auditlogmod-1.so + LDFLAGS-tst-audit15 = \ + -Wl,--audit=tst-auditlogmod-1.so,--depaudit=tst-auditlogmod-2.so + $(objpfx)tst-auditlogmod-2.so: $(libsupport) +diff --git a/elf/dl-load.c b/elf/dl-load.c +index 1613217a236c7fc3..0b45e6e3db31c70d 100644 +--- a/elf/dl-load.c ++++ b/elf/dl-load.c +@@ -2042,6 +2042,21 @@ _dl_map_object (struct link_map *loader, const char *name, + &main_map->l_rpath_dirs, + &realname, &fb, loader ?: main_map, LA_SER_RUNPATH, + &found_other_class); ++ ++ /* Also try DT_RUNPATH in the executable for LD_AUDIT dlopen ++ call. */ ++ if (__glibc_unlikely (mode & __RTLD_AUDIT) ++ && fd == -1 && !did_main_map ++ && main_map != NULL && main_map->l_type != lt_loaded) ++ { ++ struct r_search_path_struct l_rpath_dirs; ++ l_rpath_dirs.dirs = NULL; ++ if (cache_rpath (main_map, &l_rpath_dirs, ++ DT_RUNPATH, "RUNPATH")) ++ fd = open_path (name, namelen, mode, &l_rpath_dirs, ++ &realname, &fb, loader ?: main_map, ++ LA_SER_RUNPATH, &found_other_class); ++ } + } + + /* Try the LD_LIBRARY_PATH environment variable. */ +diff --git a/elf/tst-audit14a.c b/elf/tst-audit14a.c +new file mode 100644 +index 0000000000000000..c6232eacf2946e4e +--- /dev/null ++++ b/elf/tst-audit14a.c +@@ -0,0 +1 @@ ++#include "tst-audit14.c" diff --git a/glibc-rh2047981-29.patch b/glibc-rh2047981-29.patch new file mode 100644 index 0000000..3581baa --- /dev/null +++ b/glibc-rh2047981-29.patch @@ -0,0 +1,42 @@ +commit f4f70c2895e3d325188a42c10eb7bb4335be6773 +Author: H.J. Lu +Date: Tue Jan 4 06:58:34 2022 -0800 + + elf: Add a comment after trailing backslashes + +diff --git a/elf/Makefile b/elf/Makefile +index 4ec4e9a049156755..53faca4585220048 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -308,6 +308,7 @@ tests-cxx = \ + tst-nodelete \ + tst-unique3 \ + tst-unique4 \ ++# tests-cxx + + tests += $(if $(CXX),$(tests-cxx)) + tests-internal += loadtest unload unload2 circleload1 \ +@@ -580,6 +581,7 @@ modules-names = \ + vismod1 \ + vismod2 \ + vismod3 \ ++# modules-names + + modules-names-cxx = \ + tst-dlopen-nodelete-reloc-mod1 \ +@@ -605,6 +607,7 @@ modules-names-cxx = \ + tst-unique3lib \ + tst-unique3lib2 \ + tst-unique4lib \ ++# modules-names-cxx + + modules-names += \ + $(if $(CXX),$(modules-names-cxx)) \ +@@ -614,6 +617,7 @@ modules-names += \ + $(tst-tls-many-dynamic-modules-dep-bad) \ + $(tlsmod17a-modules) \ + $(tlsmod18a-modules) \ ++# modules-names + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. diff --git a/glibc-rh2047981-3.patch b/glibc-rh2047981-3.patch new file mode 100644 index 0000000..aa0aaaf --- /dev/null +++ b/glibc-rh2047981-3.patch @@ -0,0 +1,245 @@ +commit 8dbb7a08ec52057819db4ee234f9429ab99eb4ae +Author: Vineet Gupta +Date: Wed May 27 12:54:21 2020 -0700 + + dl-runtime: reloc_{offset,index} now functions arch overide'able + + The existing macros are fragile and expect local variables with a + certain name. Fix this by defining them as functions with default + implementation in a new header dl-runtime.h which arches can override + if need be. + + This came up during ARC port review, hence the need for argument pltgot + in reloc_index() which is not needed by existing ports. + + This patch potentially only affects hppa/x86 ports, + build tested for both those configs and a few more. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c +index 72b03e000dcf190e..4ccd7c30678fafad 100644 +--- a/elf/dl-runtime.c ++++ b/elf/dl-runtime.c +@@ -27,6 +27,7 @@ + #include "dynamic-link.h" + #include + #include ++#include + + + #if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \ +@@ -42,13 +43,6 @@ + # define ARCH_FIXUP_ATTRIBUTE + #endif + +-#ifndef reloc_offset +-# define reloc_offset reloc_arg +-# define reloc_index reloc_arg / sizeof (PLTREL) +-#endif +- +- +- + /* This function is called through a special trampoline from the PLT the + first time each PLT entry is called. We must perform the relocation + specified in the PLT of the given shared object, and return the resolved +@@ -68,8 +62,11 @@ _dl_fixup ( + = (const void *) D_PTR (l, l_info[DT_SYMTAB]); + const char *strtab = (const void *) D_PTR (l, l_info[DT_STRTAB]); + ++ const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]); ++ + const PLTREL *const reloc +- = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset); ++ = (const void *) (D_PTR (l, l_info[DT_JMPREL]) ++ + reloc_offset (pltgot, reloc_arg)); + const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)]; + const ElfW(Sym) *refsym = sym; + void *const rel_addr = (void *)(l->l_addr + reloc->r_offset); +@@ -180,9 +177,12 @@ _dl_profile_fixup ( + l, reloc_arg); + } + ++ const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]); ++ + /* This is the address in the array where we store the result of previous + relocations. */ +- struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index]; ++ struct reloc_result *reloc_result ++ = &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))]; + + /* CONCURRENCY NOTES: + +@@ -219,8 +219,11 @@ _dl_profile_fixup ( + = (const void *) D_PTR (l, l_info[DT_SYMTAB]); + const char *strtab = (const char *) D_PTR (l, l_info[DT_STRTAB]); + ++ const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]); ++ + const PLTREL *const reloc +- = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset); ++ = (const void *) (D_PTR (l, l_info[DT_JMPREL]) ++ + reloc_offset (pltgot, reloc_arg)); + const ElfW(Sym) *refsym = &symtab[ELFW(R_SYM) (reloc->r_info)]; + const ElfW(Sym) *defsym = refsym; + lookup_t result; +@@ -485,11 +488,14 @@ _dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg, + const void *inregs, void *outregs) + { + #ifdef SHARED ++ const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]); ++ + /* This is the address in the array where we store the result of previous + relocations. */ + // XXX Maybe the bound information must be stored on the stack since + // XXX with bind_not a new value could have been stored in the meantime. +- struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index]; ++ struct reloc_result *reloc_result = ++ &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))]; + ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound, + l_info[DT_SYMTAB]) + + reloc_result->boundndx); +diff --git a/elf/dl-runtime.h b/elf/dl-runtime.h +new file mode 100644 +index 0000000000000000..78f1da77fb4ed905 +--- /dev/null ++++ b/elf/dl-runtime.h +@@ -0,0 +1,30 @@ ++/* Helpers for On-demand PLT fixup for shared objects. Generic version. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++static inline uintptr_t ++reloc_offset (uintptr_t plt0, uintptr_t pltn) ++{ ++ return pltn; ++} ++ ++static inline uintptr_t ++reloc_index (uintptr_t plt0, uintptr_t pltn, size_t size) ++{ ++ return pltn / size; ++} +diff --git a/sysdeps/hppa/dl-runtime.c b/sysdeps/hppa/dl-runtime.c +index 885a3f1837cbc56d..2d061b150f0602c1 100644 +--- a/sysdeps/hppa/dl-runtime.c ++++ b/sysdeps/hppa/dl-runtime.c +@@ -17,10 +17,6 @@ + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +-/* Clear PA_GP_RELOC bit in relocation offset. */ +-#define reloc_offset (reloc_arg & ~PA_GP_RELOC) +-#define reloc_index (reloc_arg & ~PA_GP_RELOC) / sizeof (PLTREL) +- + #include + + /* The caller has encountered a partially relocated function descriptor. +diff --git a/sysdeps/hppa/dl-runtime.h b/sysdeps/hppa/dl-runtime.h +new file mode 100644 +index 0000000000000000..6983aa0ae9b4296c +--- /dev/null ++++ b/sysdeps/hppa/dl-runtime.h +@@ -0,0 +1,31 @@ ++/* Helpers for On-demand PLT fixup for shared objects. HPAA version. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++/* Clear PA_GP_RELOC bit in relocation offset. */ ++static inline uintptr_t ++reloc_offset (uintptr_t plt0, uintptr_t pltn) ++{ ++ return pltn & ~PA_GP_RELOC; ++} ++ ++static inline uintptr_t ++reloc_index (uintptr_t plt0, uintptr_t pltn, size_t size) ++{ ++ return (pltn & ~PA_GP_RELOC )/ size; ++} +diff --git a/sysdeps/x86_64/dl-runtime.c b/sysdeps/x86_64/dl-runtime.c +deleted file mode 100644 +index b625d1e88257b018..0000000000000000 +--- a/sysdeps/x86_64/dl-runtime.c ++++ /dev/null +@@ -1,9 +0,0 @@ +-/* The ABI calls for the PLT stubs to pass the index of the relocation +- and not its offset. In _dl_profile_fixup and _dl_call_pltexit we +- also use the index. Therefore it is wasteful to compute the offset +- in the trampoline just to reverse the operation immediately +- afterwards. */ +-#define reloc_offset reloc_arg * sizeof (PLTREL) +-#define reloc_index reloc_arg +- +-#include +diff --git a/sysdeps/x86_64/dl-runtime.h b/sysdeps/x86_64/dl-runtime.h +new file mode 100644 +index 0000000000000000..3fa61d7a4697cf3f +--- /dev/null ++++ b/sysdeps/x86_64/dl-runtime.h +@@ -0,0 +1,35 @@ ++/* Helpers for On-demand PLT fixup for shared objects. x86_64 version. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++/* The ABI calls for the PLT stubs to pass the index of the relocation ++ and not its offset. In _dl_profile_fixup and _dl_call_pltexit we ++ also use the index. Therefore it is wasteful to compute the offset ++ in the trampoline just to reverse the operation immediately ++ afterwards. */ ++static inline uintptr_t ++reloc_offset (uintptr_t plt0, uintptr_t pltn) ++{ ++ return pltn * sizeof (ElfW(Rela)); ++} ++ ++static inline uintptr_t ++reloc_index (uintptr_t plt0, uintptr_t pltn, size_t size) ++{ ++ return pltn; ++} diff --git a/glibc-rh2047981-30.patch b/glibc-rh2047981-30.patch new file mode 100644 index 0000000..d52225f --- /dev/null +++ b/glibc-rh2047981-30.patch @@ -0,0 +1,520 @@ +commit 7de01e60c200c431d3469deb784da8fd4508fc15 +Author: Florian Weimer +Date: Fri Jan 14 20:16:05 2022 +0100 + + elf/Makefile: Reflow and sort most variable assignments + + Reviewed-by: H.J. Lu + +Conflicts: + elf/Makefile + Complete rewrite of reflow. + +diff --git a/elf/Makefile b/elf/Makefile +index 53faca4585220048..954cd08c199f5037 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -21,20 +21,60 @@ subdir := elf + + include ../Makeconfig + +-headers = elf.h bits/elfclass.h link.h bits/link.h bits/link_lavcurrent.h +-routines = $(all-dl-routines) dl-support dl-iteratephdr \ +- dl-addr dl-addr-obj enbl-secure dl-profstub \ +- dl-origin dl-libc dl-sym dl-sysdep dl-error \ +- dl-reloc-static-pie libc_early_init ++headers = \ ++ bits/elfclass.h \ ++ bits/link.h \ ++ bits/link_lavcurrent.h \ ++ elf.h \ ++ link.h \ ++ # headers ++ ++routines = \ ++ $(all-dl-routines) \ ++ dl-addr \ ++ dl-addr-obj \ ++ dl-error \ ++ dl-iteratephdr \ ++ dl-libc \ ++ dl-origin \ ++ dl-profstub \ ++ dl-reloc-static-pie \ ++ dl-support \ ++ dl-sym \ ++ dl-sysdep \ ++ enbl-secure \ ++ libc_early_init \ ++ # routines + + # The core dynamic linking functions are in libc for the static and + # profiled libraries. +-dl-routines = $(addprefix dl-,load lookup object reloc deps \ +- runtime init fini debug misc \ +- version profile tls origin scope \ +- execstack open close trampoline \ +- exception sort-maps lookup-direct \ +- call-libc-early-init write) ++dl-routines = \ ++ dl-call-libc-early-init \ ++ dl-close \ ++ dl-debug \ ++ dl-deps \ ++ dl-exception \ ++ dl-execstack \ ++ dl-fini \ ++ dl-init \ ++ dl-load \ ++ dl-lookup \ ++ dl-lookup-direct \ ++ dl-misc \ ++ dl-object \ ++ dl-open \ ++ dl-origin \ ++ dl-profile \ ++ dl-reloc \ ++ dl-runtime \ ++ dl-scope \ ++ dl-sort-maps \ ++ dl-tls \ ++ dl-trampoline \ ++ dl-version \ ++ dl-write \ ++ # dl-routines ++ + ifeq (yes,$(use-ldconfig)) + dl-routines += dl-cache + endif +@@ -57,15 +97,36 @@ endif + + all-dl-routines = $(dl-routines) $(sysdep-dl-routines) + # But they are absent from the shared libc, because that code is in ld.so. +-elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \ +- dl-sysdep dl-exception dl-reloc-static-pie ++elide-routines.os = \ ++ $(all-dl-routines) \ ++ dl-exception \ ++ dl-origin \ ++ dl-reloc-static-pie \ ++ dl-support \ ++ dl-sysdep \ ++ enbl-secure \ ++ # elide-routines.os + + # ld.so uses those routines, plus some special stuff for being the program + # interpreter and operating independent of libc. +-rtld-routines = rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal \ +- dl-error-minimal dl-conflict dl-hwcaps dl-hwcaps_split dl-hwcaps-subdirs \ +- dl-usage dl-diagnostics dl-diagnostics-kernel dl-diagnostics-cpu \ +- dl-audit ++rtld-routines = \ ++ $(all-dl-routines) \ ++ dl-audit \ ++ dl-conflict \ ++ dl-diagnostics \ ++ dl-diagnostics-cpu \ ++ dl-diagnostics-kernel \ ++ dl-environ \ ++ dl-error-minimal \ ++ dl-hwcaps \ ++ dl-hwcaps-subdirs \ ++ dl-hwcaps_split \ ++ dl-minimal \ ++ dl-sysdep \ ++ dl-usage \ ++ rtld \ ++ # rtld-routines ++ + all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines) + + CFLAGS-dl-runtime.c += -fexceptions -fasynchronous-unwind-tables +@@ -98,8 +159,18 @@ ld-map = $(common-objpfx)ld.map + endif + + ifeq (yes,$(build-shared)) +-extra-objs = $(all-rtld-routines:%=%.os) soinit.os sofini.os interp.os +-generated += librtld.os dl-allobjs.os ld.so ldd ++extra-objs = \ ++ $(all-rtld-routines:%=%.os) \ ++ sofini.os \ ++ soinit.os \ ++ interp.os \ ++ # extra-objs ++generated += \ ++ dl-allobjs.os \ ++ ldd \ ++ ld.so \ ++ librtld.os \ ++ # generated + install-others = $(inst_rtlddir)/$(rtld-installed-name) $(inst_bindir)/ld.so + install-bin-script = ldd + endif +@@ -117,8 +188,15 @@ others-static += ldconfig + others += ldconfig + install-rootsbin += ldconfig + +-ldconfig-modules := cache readlib xmalloc xstrdup chroot_canon static-stubs \ +- stringtable ++ldconfig-modules := \ ++ cache \ ++ chroot_canon \ ++ readlib \ ++ static-stubs \ ++ stringtable \ ++ xmalloc \ ++ xstrdup \ ++ # ldconfig-modules + extra-objs += $(ldconfig-modules:=.o) + others-extras = $(ldconfig-modules) + endif +@@ -153,20 +231,34 @@ $(inst_auditdir)/sotruss-lib.so: $(objpfx)sotruss-lib.so $(+force) + $(do-install-program) + endif + +-tests-static-normal := tst-leaks1-static tst-array1-static tst-array5-static \ +- tst-dl-iter-static \ +- tst-tlsalign-static tst-tlsalign-extern-static \ +- tst-linkall-static tst-env-setuid tst-env-setuid-tunables \ +- tst-dst-static +-tests-static-internal := tst-tls1-static tst-tls2-static \ +- tst-ptrguard1-static tst-stackguard1-static \ +- tst-tls1-static-non-pie tst-libc_dlvsym-static ++tests-static-normal := \ ++ tst-array1-static \ ++ tst-array5-static \ ++ tst-dl-iter-static \ ++ tst-dst-static \ ++ tst-env-setuid \ ++ tst-env-setuid-tunables \ ++ tst-leaks1-static \ ++ tst-linkall-static \ ++ tst-tlsalign-extern-static \ ++ tst-tlsalign-static \ ++ # tests-static-normal ++ ++tests-static-internal := \ ++ tst-libc_dlvsym-static \ ++ tst-ptrguard1-static \ ++ tst-stackguard1-static \ ++ tst-tls1-static \ ++ tst-tls1-static-non-pie \ ++ tst-tls2-static \ ++ # tests-static-internal + + CRT-tst-tls1-static-non-pie := $(csu-objpfx)crt1.o + tst-tls1-static-non-pie-no-pie = yes + + tests-container = \ +- tst-ldconfig-bad-aux-cache ++ tst-ldconfig-bad-aux-cache \ ++ # tests-container + + ifeq (no,$(build-hardcoded-path-in-tests)) + # This is an ld.so.cache test, and RPATH/RUNPATH in the executable +@@ -174,14 +266,31 @@ ifeq (no,$(build-hardcoded-path-in-tests)) + tests-container += tst-glibc-hwcaps-prepend-cache + endif + +-tests := tst-tls9 tst-leaks1 \ +- tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \ +- tst-auxv tst-stringtable +-tests-internal := tst-tls1 tst-tls2 $(tests-static-internal) ++tests := \ ++ tst-array1 \ ++ tst-array2 \ ++ tst-array3 \ ++ tst-array4 \ ++ tst-array5 \ ++ tst-auxv \ ++ tst-leaks1 \ ++ tst-stringtable \ ++ tst-tls9 \ ++ # tests ++ ++tests-internal := \ ++ $(tests-static-internal) \ ++ tst-tls1 \ ++ tst-tls2 \ ++ # tests-internal ++ + tests-static := $(tests-static-normal) $(tests-static-internal) + + ifeq (yes,$(build-shared)) +-tests-static += tst-tls9-static ++tests-static += \ ++ tst-tls9-static \ ++ # tests-static ++ + tst-tls9-static-ENV = \ + LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)dlfcn + +@@ -302,37 +411,71 @@ tests += \ + unload6 \ + unload7 \ + unload8 \ +-# reldep9 ++ # tests + tests-cxx = \ + tst-dlopen-nodelete-reloc \ + tst-nodelete \ + tst-unique3 \ + tst-unique4 \ +-# tests-cxx ++ # tests-cxx + + tests += $(if $(CXX),$(tests-cxx)) +-tests-internal += loadtest unload unload2 circleload1 \ +- neededtest neededtest2 neededtest3 neededtest4 \ +- tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \ +- tst-ptrguard1 tst-stackguard1 tst-libc_dlvsym \ +- tst-create_format1 tst-tls-surplus tst-dl-hwcaps_split \ +- tst-audit19a +-tests-container += tst-pldd tst-preload-pthread-libc ++ ++tests-internal += \ ++ circleload1 \ ++ loadtest \ ++ neededtest \ ++ neededtest2 \ ++ neededtest3 \ ++ neededtest4 \ ++ tst-audit19a \ ++ tst-create_format1 \ ++ tst-dl-hwcaps_split \ ++ tst-dlmopen2 \ ++ tst-libc_dlvsym \ ++ tst-ptrguard1 \ ++ tst-stackguard1 \ ++ tst-tls-surplus \ ++ tst-tls3 \ ++ tst-tls6 \ ++ tst-tls7 \ ++ tst-tls8 \ ++ unload \ ++ unload2 \ ++ # tests-internal ++ ++tests-container += \ ++ tst-pldd \ ++ tst-preload-pthread-libc ++ # tests-container ++ + ifeq ($(build-hardcoded-path-in-tests),yes) + tests += tst-dlopen-aout + tst-dlopen-aout-no-pie = yes + endif +-test-srcs = tst-pathopt ++test-srcs = \ ++ tst-pathopt ++ # tests-srcs ++ + selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null) ++ + ifneq ($(selinux-enabled),1) +-tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog ++tests-execstack-yes = \ ++ tst-execstack \ ++ tst-execstack-needed \ ++ tst-execstack-prog \ ++ # tests-execstack-yes + endif + endif + tests += $(tests-execstack-$(have-z-execstack)) + ifeq ($(run-built-tests),yes) +-tests-special += $(objpfx)tst-leaks1-mem.out \ +- $(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out \ +- $(objpfx)tst-ldconfig-X.out $(objpfx)tst-rtld-help.out ++tests-special += \ ++ $(objpfx)noload-mem.out \ ++ $(objpfx)tst-ldconfig-X.out \ ++ $(objpfx)tst-leaks1-mem.out \ ++ $(objpfx)tst-leaks1-static-mem.out \ ++ $(objpfx)tst-rtld-help.out \ ++ # tests-special + endif + tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + tlsmod18a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +@@ -349,9 +492,16 @@ tst-tls-many-dynamic-modules-dep = \ + tst-tls-many-dynamic-modules-dep-bad-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 + tst-tls-many-dynamic-modules-dep-bad = \ + $(foreach n,$(tst-tls-many-dynamic-modules-dep-bad-suffixes),tst-tls-manydynamic$(n)mod-dep-bad) +-extra-test-objs += $(tlsmod17a-modules:=.os) $(tlsmod18a-modules:=.os) \ +- tst-tlsalign-vars.o +-test-extras += tst-tlsmod17a tst-tlsmod18a tst-tlsalign-vars ++extra-test-objs += \ ++ $(tlsmod17a-modules:=.os) \ ++ $(tlsmod18a-modules:=.os) \ ++ tst-tlsalign-vars.o \ ++ # extra-test-objs ++test-extras += \ ++ tst-tlsalign-vars \ ++ tst-tlsmod17a \ ++ tst-tlsmod18a \ ++ # test-extras + modules-names = \ + circlemod1 \ + circlemod1a \ +@@ -607,17 +757,17 @@ modules-names-cxx = \ + tst-unique3lib \ + tst-unique3lib2 \ + tst-unique4lib \ +-# modules-names-cxx ++ # modules-names-cxx + + modules-names += \ + $(if $(CXX),$(modules-names-cxx)) \ + $(modules-execstack-$(have-z-execstack)) \ ++ $(tlsmod17a-modules) \ ++ $(tlsmod18a-modules) \ + $(tst-tls-many-dynamic-modules) \ + $(tst-tls-many-dynamic-modules-dep) \ + $(tst-tls-many-dynamic-modules-dep-bad) \ +- $(tlsmod17a-modules) \ +- $(tlsmod18a-modules) \ +-# modules-names ++ # modules-names + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +@@ -680,54 +830,103 @@ modules-names-nobuild := filtmod1 + tests += $(tests-static) + + ifneq (no,$(multi-arch)) +-tests-ifuncstatic := ifuncmain1static ifuncmain1picstatic \ +- ifuncmain2static ifuncmain2picstatic \ +- ifuncmain4static ifuncmain4picstatic \ +- ifuncmain5static ifuncmain5picstatic \ +- ifuncmain7static ifuncmain7picstatic ++tests-ifuncstatic := \ ++ ifuncmain1static \ ++ ifuncmain1picstatic \ ++ ifuncmain2static \ ++ ifuncmain2picstatic \ ++ ifuncmain4static \ ++ ifuncmain4picstatic \ ++ ifuncmain5static \ ++ ifuncmain5picstatic \ ++ ifuncmain7static \ ++ ifuncmain7picstatic \ ++ # tests-ifuncstatic + tests-static += $(tests-ifuncstatic) + tests-internal += $(tests-ifuncstatic) + ifeq (yes,$(build-shared)) + tests-internal += \ +- ifuncmain1 ifuncmain1pic ifuncmain1vis ifuncmain1vispic \ +- ifuncmain1staticpic \ +- ifuncmain2 ifuncmain2pic ifuncmain3 ifuncmain4 \ +- ifuncmain5 ifuncmain5pic ifuncmain5staticpic \ +- ifuncmain7 ifuncmain7pic +-ifunc-test-modules = ifuncdep1 ifuncdep1pic ifuncdep2 ifuncdep2pic \ +- ifuncdep5 ifuncdep5pic ++ ifuncmain1 \ ++ ifuncmain1pic \ ++ ifuncmain1staticpic \ ++ ifuncmain1vis \ ++ ifuncmain1vispic \ ++ ifuncmain2 \ ++ ifuncmain2pic \ ++ ifuncmain3 \ ++ ifuncmain4 \ ++ ifuncmain5 \ ++ ifuncmain5pic \ ++ ifuncmain5staticpic \ ++ ifuncmain7 \ ++ ifuncmain7pic \ ++ # tests-internal ++ifunc-test-modules = \ ++ ifuncdep1 \ ++ ifuncdep1pic \ ++ ifuncdep2 \ ++ ifuncdep2pic \ ++ ifuncdep5 \ ++ ifuncdep5pic \ ++ # ifunc-test-modules + extra-test-objs += $(ifunc-test-modules:=.o) + test-internal-extras += $(ifunc-test-modules) + ifeq (yes,$(have-fpie)) +-ifunc-pie-tests = ifuncmain1pie ifuncmain1vispie ifuncmain1staticpie \ +- ifuncmain5pie ifuncmain6pie ifuncmain7pie ++ifunc-pie-tests = \ ++ ifuncmain1pie \ ++ ifuncmain1staticpie \ ++ ifuncmain1vispie \ ++ ifuncmain5pie \ ++ ifuncmain6pie \ ++ ifuncmain7pie \ ++ # ifunc-pie-tests + tests-internal += $(ifunc-pie-tests) + tests-pie += $(ifunc-pie-tests) + endif +-modules-names += ifuncmod1 ifuncmod3 ifuncmod5 ifuncmod6 ++modules-names += \ ++ ifuncmod1 \ ++ ifuncmod3 \ ++ ifuncmod5 \ ++ ifuncmod6 \ ++ # modules-names + endif + endif + + ifeq (yes,$(build-shared)) + ifeq ($(run-built-tests),yes) +-tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \ +- $(objpfx)tst-rtld-preload.out $(objpfx)argv0test.out \ +- $(objpfx)tst-rtld-help.out ++tests-special += \ ++ $(objpfx)argv0test.out \ ++ $(objpfx)tst-pathopt.out \ ++ $(objpfx)tst-rtld-help.out \ ++ $(objpfx)tst-rtld-load-self.out \ ++ $(objpfx)tst-rtld-preload.out \ ++ # tests-special + endif +-tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \ +- $(objpfx)check-wx-segment.out \ +- $(objpfx)check-localplt.out $(objpfx)check-initfini.out ++tests-special += \ ++ $(objpfx)check-execstack.out \ ++ $(objpfx)check-initfini.out \ ++ $(objpfx)check-localplt.out \ ++ $(objpfx)check-textrel.out \ ++ $(objpfx)check-wx-segment.out \ ++ # tests-special + endif + + ifeq ($(run-built-tests),yes) +-tests-special += $(objpfx)order-cmp.out $(objpfx)tst-array1-cmp.out \ +- $(objpfx)tst-array1-static-cmp.out \ +- $(objpfx)tst-array2-cmp.out $(objpfx)tst-array3-cmp.out \ +- $(objpfx)tst-array4-cmp.out $(objpfx)tst-array5-cmp.out \ +- $(objpfx)tst-array5-static-cmp.out $(objpfx)order2-cmp.out \ +- $(objpfx)tst-initorder-cmp.out \ +- $(objpfx)tst-initorder2-cmp.out $(objpfx)tst-unused-dep.out \ +- $(objpfx)tst-unused-dep-cmp.out ++tests-special += \ ++ $(objpfx)order-cmp.out \ ++ $(objpfx)order2-cmp.out \ ++ $(objpfx)tst-array1-cmp.out \ ++ $(objpfx)tst-array1-static-cmp.out \ ++ $(objpfx)tst-array2-cmp.out \ ++ $(objpfx)tst-array3-cmp.out \ ++ $(objpfx)tst-array4-cmp.out \ ++ $(objpfx)tst-array5-cmp.out \ ++ $(objpfx)tst-array5-static-cmp.out \ ++ $(objpfx)tst-initorder-cmp.out \ ++ $(objpfx)tst-initorder2-cmp.out \ ++ $(objpfx)tst-unused-dep-cmp.out \ ++ $(objpfx)tst-unused-dep.out \ ++ # tests-special + endif + + check-abi: $(objpfx)check-abi-ld.out +@@ -807,6 +1006,7 @@ rtld-stubbed-symbols = \ + free \ + malloc \ + realloc \ ++ # rtld-stubbed-symbols + + # The GCC arguments that implement $(rtld-stubbed-symbols). + rtld-stubbed-symbols-args = \ diff --git a/glibc-rh2047981-31.patch b/glibc-rh2047981-31.patch new file mode 100644 index 0000000..48de026 --- /dev/null +++ b/glibc-rh2047981-31.patch @@ -0,0 +1,440 @@ +Added $(objpfx)tst-audit23: $(libdl) to elf/Makefile since +we still need $(libdl) in RHEL8. + +commit 5fa11a2bc94c912c3b25860065086902674537ba +Author: Adhemerval Zanella +Date: Mon Jan 24 10:46:15 2022 -0300 + + elf: Add la_activity during application exit + + la_activity is not called during application exit, even though + la_objclose is. + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Carlos O'Donell + Tested-by: Carlos O'Donell + +Conflicts: + elf/Makefile + +diff --git a/elf/Makefile b/elf/Makefile +index 954cd08c199f5037..e4955c9f575f9015 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -345,6 +345,7 @@ tests += \ + tst-audit2 \ + tst-audit20 \ + tst-audit22 \ ++ tst-audit23 \ + tst-audit8 \ + tst-audit9 \ + tst-auditmany \ +@@ -608,6 +609,7 @@ modules-names = \ + tst-audit13mod1 \ + tst-audit18mod \ + tst-audit19bmod \ ++ tst-audit23mod \ + tst-auditlogmod-1 \ + tst-auditlogmod-2 \ + tst-auditlogmod-3 \ +@@ -630,6 +632,7 @@ modules-names = \ + tst-auditmod19b \ + tst-auditmod20 \ + tst-auditmod22 \ ++ tst-auditmod23 \ + tst-big-note-lib \ + tst-deep1mod1 \ + tst-deep1mod2 \ +@@ -2041,6 +2044,11 @@ $(objpfx)tst-auditmod20.so: $(libdl) + $(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so + tst-audit22-ARGS = -- $(host-test-program-cmd) + ++$(objpfx)tst-audit23: $(libdl) ++$(objpfx)tst-audit23.out: $(objpfx)tst-auditmod23.so \ ++ $(objpfx)tst-audit23mod.so ++tst-audit23-ARGS = -- $(host-test-program-cmd) ++ + # tst-sonamemove links against an older implementation of the library. + LDFLAGS-tst-sonamemove-linkmod1.so = \ + -Wl,--version-script=tst-sonamemove-linkmod1.map \ +diff --git a/elf/dl-fini.c b/elf/dl-fini.c +index e102d93647cb8c47..eea9d8aad736a99e 100644 +--- a/elf/dl-fini.c ++++ b/elf/dl-fini.c +@@ -63,6 +63,10 @@ _dl_fini (void) + __rtld_lock_unlock_recursive (GL(dl_load_lock)); + else + { ++#ifdef SHARED ++ _dl_audit_activity_nsid (ns, LA_ACT_DELETE); ++#endif ++ + /* Now we can allocate an array to hold all the pointers and + copy the pointers in. */ + struct link_map *maps[nloaded]; +@@ -153,6 +157,10 @@ _dl_fini (void) + /* Correct the previous increment. */ + --l->l_direct_opencount; + } ++ ++#ifdef SHARED ++ _dl_audit_activity_nsid (ns, LA_ACT_CONSISTENT); ++#endif + } + } + +diff --git a/elf/tst-audit23.c b/elf/tst-audit23.c +new file mode 100644 +index 0000000000000000..4904cf1340a97ee1 +--- /dev/null ++++ b/elf/tst-audit23.c +@@ -0,0 +1,239 @@ ++/* Check for expected la_objopen and la_objeclose for all objects. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int restart; ++#define CMDLINE_OPTIONS \ ++ { "restart", no_argument, &restart, 1 }, ++ ++static int ++handle_restart (void) ++{ ++ xdlopen ("tst-audit23mod.so", RTLD_NOW); ++ xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW); ++ ++ return 0; ++} ++ ++static inline bool ++startswith (const char *str, const char *pre) ++{ ++ size_t lenpre = strlen (pre); ++ size_t lenstr = strlen (str); ++ return lenstr >= lenpre && memcmp (pre, str, lenpre) == 0; ++} ++ ++static inline bool ++is_vdso (const char *str) ++{ ++ return startswith (str, "linux-gate") ++ || startswith (str, "linux-vdso"); ++} ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ /* We must have either: ++ - One or four parameters left if called initially: ++ + path to ld.so optional ++ + "--library-path" optional ++ + the library path optional ++ + the application name */ ++ if (restart) ++ return handle_restart (); ++ ++ char *spargv[9]; ++ TEST_VERIFY_EXIT (((argc - 1) + 3) < array_length (spargv)); ++ int i = 0; ++ for (; i < argc - 1; i++) ++ spargv[i] = argv[i + 1]; ++ spargv[i++] = (char *) "--direct"; ++ spargv[i++] = (char *) "--restart"; ++ spargv[i] = NULL; ++ ++ setenv ("LD_AUDIT", "tst-auditmod23.so", 0); ++ struct support_capture_subprocess result ++ = support_capture_subprogram (spargv[0], spargv); ++ support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr); ++ ++ /* The expected la_objopen/la_objclose: ++ 1. executable ++ 2. loader ++ 3. libc.so ++ 4. tst-audit23mod.so ++ 5. libc.so (LM_ID_NEWLM). ++ 6. vdso (optional and ignored). */ ++ enum { max_objs = 6 }; ++ struct la_obj_t ++ { ++ char *lname; ++ uintptr_t laddr; ++ Lmid_t lmid; ++ bool closed; ++ } objs[max_objs] = { [0 ... max_objs-1] = { .closed = false } }; ++ size_t nobjs = 0; ++ ++ /* The expected namespaces are one for the audit module, one for the ++ application, and another for the dlmopen on handle_restart. */ ++ enum { max_ns = 3 }; ++ uintptr_t acts[max_ns] = { 0 }; ++ size_t nacts = 0; ++ int last_act = -1; ++ uintptr_t last_act_cookie = -1; ++ bool seen_first_objclose = false; ++ ++ FILE *out = fmemopen (result.err.buffer, result.err.length, "r"); ++ TEST_VERIFY (out != NULL); ++ char *buffer = NULL; ++ size_t buffer_length = 0; ++ while (xgetline (&buffer, &buffer_length, out)) ++ { ++ if (startswith (buffer, "la_activity: ")) ++ { ++ uintptr_t cookie; ++ int this_act; ++ int r = sscanf (buffer, "la_activity: %d %"SCNxPTR"", &this_act, ++ &cookie); ++ TEST_COMPARE (r, 2); ++ ++ /* The cookie identifies the object at the head of the link map, ++ so we only add a new namespace if it changes from the previous ++ one. This works since dlmopen is the last in the test body. */ ++ if (cookie != last_act_cookie && last_act_cookie != -1) ++ TEST_COMPARE (last_act, LA_ACT_CONSISTENT); ++ ++ if (this_act == LA_ACT_ADD && acts[nacts] != cookie) ++ { ++ acts[nacts++] = cookie; ++ last_act_cookie = cookie; ++ } ++ /* The LA_ACT_DELETE is called in the reverse order of LA_ACT_ADD ++ at program termination (if the tests adds a dlclose or a library ++ with extra dependencies this will need to be adapted). */ ++ else if (this_act == LA_ACT_DELETE) ++ { ++ last_act_cookie = acts[--nacts]; ++ TEST_COMPARE (acts[nacts], cookie); ++ acts[nacts] = 0; ++ } ++ else if (this_act == LA_ACT_CONSISTENT) ++ { ++ TEST_COMPARE (cookie, last_act_cookie); ++ ++ /* LA_ACT_DELETE must always be followed by an la_objclose. */ ++ if (last_act == LA_ACT_DELETE) ++ TEST_COMPARE (seen_first_objclose, true); ++ else ++ TEST_COMPARE (last_act, LA_ACT_ADD); ++ } ++ ++ last_act = this_act; ++ seen_first_objclose = false; ++ } ++ else if (startswith (buffer, "la_objopen: ")) ++ { ++ char *lname; ++ uintptr_t laddr; ++ Lmid_t lmid; ++ uintptr_t cookie; ++ int r = sscanf (buffer, "la_objopen: %"SCNxPTR" %ms %"SCNxPTR" %ld", ++ &cookie, &lname, &laddr, &lmid); ++ TEST_COMPARE (r, 4); ++ ++ /* la_objclose is not triggered by vDSO because glibc does not ++ unload it. */ ++ if (is_vdso (lname)) ++ continue; ++ if (nobjs == max_objs) ++ FAIL_EXIT1 ("non expected la_objopen: %s %"PRIxPTR" %ld", ++ lname, laddr, lmid); ++ objs[nobjs].lname = lname; ++ objs[nobjs].laddr = laddr; ++ objs[nobjs].lmid = lmid; ++ objs[nobjs].closed = false; ++ nobjs++; ++ ++ /* This indirectly checks that la_objopen always comes before ++ la_objclose btween la_activity calls. */ ++ seen_first_objclose = false; ++ } ++ else if (startswith (buffer, "la_objclose: ")) ++ { ++ char *lname; ++ uintptr_t laddr; ++ Lmid_t lmid; ++ uintptr_t cookie; ++ int r = sscanf (buffer, "la_objclose: %"SCNxPTR" %ms %"SCNxPTR" %ld", ++ &cookie, &lname, &laddr, &lmid); ++ TEST_COMPARE (r, 4); ++ ++ for (size_t i = 0; i < nobjs; i++) ++ { ++ if (strcmp (lname, objs[i].lname) == 0 && lmid == objs[i].lmid) ++ { ++ TEST_COMPARE (objs[i].closed, false); ++ objs[i].closed = true; ++ break; ++ } ++ } ++ ++ /* la_objclose should be called after la_activity(LA_ACT_DELETE) for ++ the closed object's namespace. */ ++ TEST_COMPARE (last_act, LA_ACT_DELETE); ++ if (!seen_first_objclose) ++ { ++ TEST_COMPARE (last_act_cookie, cookie); ++ seen_first_objclose = true; ++ } ++ } ++ } ++ ++ for (size_t i = 0; i < nobjs; i++) ++ { ++ TEST_COMPARE (objs[i].closed, true); ++ free (objs[i].lname); ++ } ++ ++ /* la_activity(LA_ACT_CONSISTENT) should be the last callback received. ++ Since only one link map may be not-CONSISTENT at a time, this also ++ ensures la_activity(LA_ACT_CONSISTENT) is the last callback received ++ for every namespace. */ ++ TEST_COMPARE (last_act, LA_ACT_CONSISTENT); ++ ++ free (buffer); ++ xfclose (out); ++ ++ return 0; ++} ++ ++#define TEST_FUNCTION_ARGV do_test ++#include +diff --git a/elf/tst-audit23mod.c b/elf/tst-audit23mod.c +new file mode 100644 +index 0000000000000000..30315687037d25e8 +--- /dev/null ++++ b/elf/tst-audit23mod.c +@@ -0,0 +1,23 @@ ++/* Extra module for tst-audit23 ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++int ++foo (void) ++{ ++ return 0; ++} +diff --git a/elf/tst-auditmod23.c b/elf/tst-auditmod23.c +new file mode 100644 +index 0000000000000000..d7c60d7a5cbc4f8a +--- /dev/null ++++ b/elf/tst-auditmod23.c +@@ -0,0 +1,74 @@ ++/* Audit module loaded by tst-audit23. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++unsigned int ++la_version (unsigned int version) ++{ ++ return LAV_CURRENT; ++} ++ ++struct map_desc_t ++{ ++ char *lname; ++ uintptr_t laddr; ++ Lmid_t lmid; ++}; ++ ++void ++la_activity (uintptr_t *cookie, unsigned int flag) ++{ ++ fprintf (stderr, "%s: %d %"PRIxPTR"\n", __func__, flag, (uintptr_t) cookie); ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ const char *l_name = map->l_name[0] == '\0' ? "mainapp" : map->l_name; ++ fprintf (stderr, "%s: %"PRIxPTR" %s %"PRIxPTR" %ld\n", __func__, ++ (uintptr_t) cookie, l_name, map->l_addr, lmid); ++ ++ struct map_desc_t *map_desc = malloc (sizeof (struct map_desc_t)); ++ if (map_desc == NULL) ++ abort (); ++ ++ map_desc->lname = strdup (l_name); ++ map_desc->laddr = map->l_addr; ++ map_desc->lmid = lmid; ++ ++ *cookie = (uintptr_t) map_desc; ++ ++ return 0; ++} ++ ++unsigned int ++la_objclose (uintptr_t *cookie) ++{ ++ struct map_desc_t *map_desc = (struct map_desc_t *) *cookie; ++ fprintf (stderr, "%s: %"PRIxPTR" %s %"PRIxPTR" %ld\n", __func__, ++ (uintptr_t) cookie, map_desc->lname, map_desc->laddr, ++ map_desc->lmid); ++ ++ return 0; ++} diff --git a/glibc-rh2047981-32.patch b/glibc-rh2047981-32.patch new file mode 100644 index 0000000..2706fe8 --- /dev/null +++ b/glibc-rh2047981-32.patch @@ -0,0 +1,298 @@ +commit 254d3d5aef2fd8430c469e1938209ac100ebf132 +Author: Adhemerval Zanella +Date: Mon Jan 24 10:46:16 2022 -0300 + + elf: Fix initial-exec TLS access on audit modules (BZ #28096) + + For audit modules and dependencies with initial-exec TLS, we can not + set the initial TLS image on default loader initialization because it + would already be set by the audit setup. However, subsequent thread + creation would need to follow the default behaviour. + + This patch fixes it by setting l_auditing link_map field not only + for the audit modules, but also for all its dependencies. This is + used on _dl_allocate_tls_init to avoid the static TLS initialization + at load time. + + Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu. + + Reviewed-by: Carlos O'Donell + Tested-by: Carlos O'Donell + +diff --git a/elf/Makefile b/elf/Makefile +index e4955c9f575f9015..3f5f72257a5fbea4 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -344,6 +344,7 @@ tests += \ + tst-audit19b \ + tst-audit2 \ + tst-audit20 \ ++ tst-audit21 \ + tst-audit22 \ + tst-audit23 \ + tst-audit8 \ +@@ -631,6 +632,8 @@ modules-names = \ + tst-auditmod19a \ + tst-auditmod19b \ + tst-auditmod20 \ ++ tst-auditmod21a \ ++ tst-auditmod21b \ + tst-auditmod22 \ + tst-auditmod23 \ + tst-big-note-lib \ +@@ -2041,6 +2044,11 @@ $(objpfx)tst-audit20.out: $(objpfx)tst-auditmod20.so + tst-audit20-ENV = LD_AUDIT=$(objpfx)tst-auditmod20.so + $(objpfx)tst-auditmod20.so: $(libdl) + ++$(objpfx)tst-audit21: $(shared-thread-library) ++$(objpfx)tst-audit21.out: $(objpfx)tst-auditmod21a.so ++$(objpfx)tst-auditmod21a.so: $(objpfx)tst-auditmod21b.so ++tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21a.so ++ + $(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so + tst-audit22-ARGS = -- $(host-test-program-cmd) + +diff --git a/elf/dl-tls.c b/elf/dl-tls.c +index 7865fc390c3f3f0a..a918e9a6f585eb72 100644 +--- a/elf/dl-tls.c ++++ b/elf/dl-tls.c +@@ -514,8 +514,12 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid) + } + + ++/* Allocate initial TLS. RESULT should be a non-NULL pointer to storage ++ for the TLS space. The DTV may be resized, and so this function may ++ call malloc to allocate that space. The loader's GL(dl_load_tls_lock) ++ is taken when manipulating global TLS-related data in the loader. */ + void * +-_dl_allocate_tls_init (void *result) ++_dl_allocate_tls_init (void *result, bool init_tls) + { + if (result == NULL) + /* The memory allocation failed. */ +@@ -588,7 +592,14 @@ _dl_allocate_tls_init (void *result) + some platforms use in static programs requires it. */ + dtv[map->l_tls_modid].pointer.val = dest; + +- /* Copy the initialization image and clear the BSS part. */ ++ /* Copy the initialization image and clear the BSS part. For ++ audit modules or dependencies with initial-exec TLS, we can not ++ set the initial TLS image on default loader initialization ++ because it would already be set by the audit setup. However, ++ subsequent thread creation would need to follow the default ++ behaviour. */ ++ if (map->l_ns != LM_ID_BASE && !init_tls) ++ continue; + memset (__mempcpy (dest, map->l_tls_initimage, + map->l_tls_initimage_size), '\0', + map->l_tls_blocksize - map->l_tls_initimage_size); +@@ -615,7 +626,7 @@ _dl_allocate_tls (void *mem) + { + return _dl_allocate_tls_init (mem == NULL + ? _dl_allocate_tls_storage () +- : allocate_dtv (mem)); ++ : allocate_dtv (mem), true); + } + rtld_hidden_def (_dl_allocate_tls) + +diff --git a/elf/rtld.c b/elf/rtld.c +index efcbeac6c24c4b7b..caa980dbda3d1a72 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2421,7 +2421,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + into the main thread's TLS area, which we allocated above. + Note: thread-local variables must only be accessed after completing + the next step. */ +- _dl_allocate_tls_init (tcbp); ++ _dl_allocate_tls_init (tcbp, false); + + /* And finally install it for the main thread. */ + if (! tls_init_tp_called) +diff --git a/elf/tst-audit21.c b/elf/tst-audit21.c +new file mode 100644 +index 0000000000000000..3a47ab64d44421ee +--- /dev/null ++++ b/elf/tst-audit21.c +@@ -0,0 +1,42 @@ ++/* Check LD_AUDIT with static TLS. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++static volatile __thread int out __attribute__ ((tls_model ("initial-exec"))); ++ ++static void * ++tf (void *arg) ++{ ++ TEST_COMPARE (out, 0); ++ out = isspace (' '); ++ return NULL; ++} ++ ++int main (int argc, char *argv[]) ++{ ++ TEST_COMPARE (out, 0); ++ out = isspace (' '); ++ ++ pthread_t t = xpthread_create (NULL, tf, NULL); ++ xpthread_join (t); ++ ++ return 0; ++} +diff --git a/elf/tst-auditmod21a.c b/elf/tst-auditmod21a.c +new file mode 100644 +index 0000000000000000..f6d51b5c0531c49d +--- /dev/null ++++ b/elf/tst-auditmod21a.c +@@ -0,0 +1,80 @@ ++/* Check LD_AUDIT with static TLS. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++#define tls_ie __attribute__ ((tls_model ("initial-exec"))) ++ ++__thread int tls_var0 tls_ie; ++__thread int tls_var1 tls_ie = 0x10; ++ ++/* Defined at tst-auditmod21b.so */ ++extern __thread int tls_var2; ++extern __thread int tls_var3; ++ ++static volatile int out; ++ ++static void ++call_libc (void) ++{ ++ /* isspace accesses the initial-exec glibc TLS variables, which are ++ setup in glibc initialization. */ ++ out = isspace (' '); ++} ++ ++unsigned int ++la_version (unsigned int v) ++{ ++ tls_var0 = 0x1; ++ if (tls_var1 != 0x10) ++ abort (); ++ tls_var1 = 0x20; ++ ++ tls_var2 = 0x2; ++ if (tls_var3 != 0x20) ++ abort (); ++ tls_var3 = 0x40; ++ ++ call_libc (); ++ ++ return LAV_CURRENT; ++} ++ ++unsigned int ++la_objopen (struct link_map* map, Lmid_t lmid, uintptr_t* cookie) ++{ ++ call_libc (); ++ *cookie = (uintptr_t) map; ++ return 0; ++} ++ ++void ++la_activity (uintptr_t* cookie, unsigned int flag) ++{ ++ if (tls_var0 != 0x1 || tls_var1 != 0x20) ++ abort (); ++ call_libc (); ++} ++ ++void ++la_preinit (uintptr_t* cookie) ++{ ++ call_libc (); ++} +diff --git a/elf/tst-auditmod21b.c b/elf/tst-auditmod21b.c +new file mode 100644 +index 0000000000000000..6ba5335b7514c674 +--- /dev/null ++++ b/elf/tst-auditmod21b.c +@@ -0,0 +1,22 @@ ++/* Check LD_AUDIT with static TLS. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define tls_ie __attribute__ ((tls_model ("initial-exec"))) ++ ++__thread int tls_var2 tls_ie; ++__thread int tls_var3 tls_ie = 0x20; +diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c +index 5fa45b19987717e1..58170d9da2bf0fa6 100644 +--- a/nptl/allocatestack.c ++++ b/nptl/allocatestack.c +@@ -244,7 +244,7 @@ get_cached_stack (size_t *sizep, void **memp) + memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t)); + + /* Re-initialize the TLS. */ +- _dl_allocate_tls_init (TLS_TPADJ (result)); ++ _dl_allocate_tls_init (TLS_TPADJ (result), true); + + return result; + } +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 29b77b35175c1116..73f4863fd43922b9 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1182,7 +1182,7 @@ extern void _dl_allocate_static_tls (struct link_map *map) attribute_hidden; + /* These are internal entry points to the two halves of _dl_allocate_tls, + only used within rtld.c itself at startup time. */ + extern void *_dl_allocate_tls_storage (void) attribute_hidden; +-extern void *_dl_allocate_tls_init (void *); ++extern void *_dl_allocate_tls_init (void *, bool); + rtld_hidden_proto (_dl_allocate_tls_init) + + /* Deallocate memory allocated with _dl_allocate_tls. */ diff --git a/glibc-rh2047981-33.patch b/glibc-rh2047981-33.patch new file mode 100644 index 0000000..6ce117c --- /dev/null +++ b/glibc-rh2047981-33.patch @@ -0,0 +1,1777 @@ +commit 32612615c58b394c3eb09f020f31310797ad3854 +Author: Adhemerval Zanella +Date: Mon Jan 24 10:46:17 2022 -0300 + + elf: Issue la_symbind for bind-now (BZ #23734) + + The audit symbind callback is not called for binaries built with + -Wl,-z,now or when LD_BIND_NOW=1 is used, nor the PLT tracking callbacks + (plt_enter and plt_exit) since this would change the expected + program semantics (where no PLT is expected) and would have performance + implications (such as for BZ#15533). + + LAV_CURRENT is also bumped to indicate the audit ABI change (where + la_symbind flags are set by the loader to indicate no possible PLT + trace). + + To handle powerpc64 ELFv1 function descriptor, _dl_audit_symbind + requires to know whether bind-now is used so the symbol value is + updated to function text segment instead of the OPD (for lazy binding + this is done by PPC64_LOAD_FUNCPTR on _dl_runtime_resolve). + + Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, + powerpc64-linux-gnu. + + Reviewed-by: Carlos O'Donell + Tested-by: Carlos O'Donell + +Conflicts: + elf/Makefile + +diff --git a/bits/link_lavcurrent.h b/bits/link_lavcurrent.h +index 44fbea1e8060997f..c48835d12b512355 100644 +--- a/bits/link_lavcurrent.h ++++ b/bits/link_lavcurrent.h +@@ -22,4 +22,4 @@ + #endif + + /* Version numbers for la_version handshake interface. */ +-#define LAV_CURRENT 1 ++#define LAV_CURRENT 2 +diff --git a/elf/Makefile b/elf/Makefile +index 3f5f72257a5fbea4..78147ed2dbcaf4c0 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -347,6 +347,12 @@ tests += \ + tst-audit21 \ + tst-audit22 \ + tst-audit23 \ ++ tst-audit24a \ ++ tst-audit24b \ ++ tst-audit24c \ ++ tst-audit24d \ ++ tst-audit25a \ ++ tst-audit25b \ + tst-audit8 \ + tst-audit9 \ + tst-auditmany \ +@@ -611,6 +617,18 @@ modules-names = \ + tst-audit18mod \ + tst-audit19bmod \ + tst-audit23mod \ ++ tst-audit24amod1 \ ++ tst-audit24amod2 \ ++ tst-audit24bmod1 \ ++ tst-audit24bmod2 \ ++ tst-audit24dmod1 \ ++ tst-audit24dmod2 \ ++ tst-audit24dmod3 \ ++ tst-audit24dmod4 \ ++ tst-audit25mod1 \ ++ tst-audit25mod2 \ ++ tst-audit25mod3 \ ++ tst-audit25mod4 \ + tst-auditlogmod-1 \ + tst-auditlogmod-2 \ + tst-auditlogmod-3 \ +@@ -636,6 +654,11 @@ modules-names = \ + tst-auditmod21b \ + tst-auditmod22 \ + tst-auditmod23 \ ++ tst-auditmod24a \ ++ tst-auditmod24b \ ++ tst-auditmod24c \ ++ tst-auditmod24d \ ++ tst-auditmod25 \ + tst-big-note-lib \ + tst-deep1mod1 \ + tst-deep1mod2 \ +@@ -831,7 +854,8 @@ modules-execstack-yes = tst-execstack-mod + extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) + + # filtmod1.so has a special rule +-modules-names-nobuild := filtmod1 ++modules-names-nobuild := filtmod1 \ ++ tst-audit24bmod1 tst-audit24bmod2.so + + tests += $(tests-static) + +@@ -2057,6 +2081,69 @@ $(objpfx)tst-audit23.out: $(objpfx)tst-auditmod23.so \ + $(objpfx)tst-audit23mod.so + tst-audit23-ARGS = -- $(host-test-program-cmd) + ++$(objpfx)tst-audit24a.out: $(objpfx)tst-auditmod24a.so ++$(objpfx)tst-audit24a: $(objpfx)tst-audit24amod1.so \ ++ $(objpfx)tst-audit24amod2.so ++tst-audit24a-ENV = LD_AUDIT=$(objpfx)tst-auditmod24a.so ++LDFLAGS-tst-audit24a = -Wl,-z,now ++ ++$(objpfx)tst-audit24b.out: $(objpfx)tst-auditmod24b.so ++$(objpfx)tst-audit24b: $(objpfx)tst-audit24bmod1.so \ ++ $(objpfx)tst-audit24bmod2.so ++$(objpfx)tst-audit24bmod1: $(objpfx)tst-audit24bmod2.so ++# The test checks if a library without .gnu.version correctly calls the ++# audit callbacks. So it uses an explicit link rule to avoid linking ++# against libc.so. ++$(objpfx)tst-audit24bmod1.so: $(objpfx)tst-audit24bmod1.os ++ $(CC) -nostdlib -nostartfiles -shared -o $@.new $(objpfx)tst-audit24bmod1.os \ ++ -Wl,-z,now ++ $(call after-link,$@.new) ++ mv -f $@.new $@ ++CFLAGS-.os += $(call elide-stack-protector,.os,tst-audit24bmod1) ++$(objpfx)tst-audit24bmod2.so: $(objpfx)tst-audit24bmod2.os ++ $(CC) -nostdlib -nostartfiles -shared -o $@.new $(objpfx)tst-audit24bmod2.os ++ $(call after-link,$@.new) ++ mv -f $@.new $@ ++CFLAGS-.os += $(call elide-stack-protector,.os,tst-audit24bmod2) ++tst-audit24b-ENV = LD_AUDIT=$(objpfx)tst-auditmod24b.so ++LDFLAGS-tst-audit24b = -Wl,-z,now ++ ++# Same as tst-audit24a, but tests LD_BIND_NOW ++$(objpfx)tst-audit24c.out: $(objpfx)tst-auditmod24c.so ++$(objpfx)tst-audit24c: $(objpfx)tst-audit24amod1.so \ ++ $(objpfx)tst-audit24amod2.so ++tst-audit24c-ENV = LD_BIND_NOW=1 LD_AUDIT=$(objpfx)tst-auditmod24c.so ++LDFLAGS-tst-audit24b = -Wl,-z,lazy ++ ++$(objpfx)tst-audit24d.out: $(objpfx)tst-auditmod24d.so ++$(objpfx)tst-audit24d: $(objpfx)tst-audit24dmod1.so \ ++ $(objpfx)tst-audit24dmod2.so ++$(objpfx)tst-audit24dmod1.so: $(objpfx)tst-audit24dmod3.so ++LDFLAGS-tst-audit24dmod1.so = -Wl,-z,now ++$(objpfx)tst-audit24dmod2.so: $(objpfx)tst-audit24dmod4.so ++LDFLAGS-tst-audit24dmod2.so = -Wl,-z,lazy ++tst-audit24d-ENV = LD_AUDIT=$(objpfx)tst-auditmod24d.so ++LDFLAGS-tst-audit24d = -Wl,-z,lazy ++ ++$(objpfx)tst-audit25a.out: $(objpfx)tst-auditmod25.so ++$(objpfx)tst-audit25a: $(objpfx)tst-audit25mod1.so \ ++ $(objpfx)tst-audit25mod2.so \ ++ $(objpfx)tst-audit25mod3.so \ ++ $(objpfx)tst-audit25mod4.so ++$(objpfx)tst-audit25mod1.so: $(objpfx)tst-audit25mod3.so ++LDFLAGS-tst-audit25mod1.so = -Wl,-z,now ++$(objpfx)tst-audit25mod2.so: $(objpfx)tst-audit25mod4.so ++LDFLAGS-tst-audit25mod2.so = -Wl,-z,lazy ++tst-audit25a-ARGS = -- $(host-test-program-cmd) ++ ++$(objpfx)tst-audit25b.out: $(objpfx)tst-auditmod25.so ++$(objpfx)tst-audit25b: $(objpfx)tst-audit25mod1.so \ ++ $(objpfx)tst-audit25mod2.so \ ++ $(objpfx)tst-audit25mod3.so \ ++ $(objpfx)tst-audit25mod4.so ++LDFLAGS-tst-audit25b = -Wl,-z,now ++tst-audit25b-ARGS = -- $(host-test-program-cmd) ++ + # tst-sonamemove links against an older implementation of the library. + LDFLAGS-tst-sonamemove-linkmod1.so = \ + -Wl,--version-script=tst-sonamemove-linkmod1.map \ +diff --git a/elf/dl-audit.c b/elf/dl-audit.c +index 152712b12fed6de2..72a50717ef60a357 100644 +--- a/elf/dl-audit.c ++++ b/elf/dl-audit.c +@@ -178,16 +178,23 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, + const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value, + lookup_t result) + { +- reloc_result->bound = result; +- /* Compute index of the symbol entry in the symbol table of the DSO with the +- definition. */ +- reloc_result->boundndx = (defsym - (ElfW(Sym) *) D_PTR (result, +- l_info[DT_SYMTAB])); ++ bool for_jmp_slot = reloc_result == NULL; ++ ++ /* Compute index of the symbol entry in the symbol table of the DSO ++ with the definition. */ ++ unsigned int boundndx = defsym - (ElfW(Sym) *) D_PTR (result, ++ l_info[DT_SYMTAB]); ++ if (!for_jmp_slot) ++ { ++ reloc_result->bound = result; ++ reloc_result->boundndx = boundndx; ++ } + + if ((l->l_audit_any_plt | result->l_audit_any_plt) == 0) + { + /* Set all bits since this symbol binding is not interesting. */ +- reloc_result->enterexit = (1u << DL_NNS) - 1; ++ if (!for_jmp_slot) ++ reloc_result->enterexit = (1u << DL_NNS) - 1; + return; + } + +@@ -199,12 +206,13 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, + two bits. */ + assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8); + assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3); +- reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT; ++ uint32_t enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT; + + const char *strtab2 = (const void *) D_PTR (result, l_info[DT_STRTAB]); + + unsigned int flags = 0; + struct audit_ifaces *afct = GLRO(dl_audit); ++ uintptr_t new_value = (uintptr_t) sym.st_value; + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) + { + /* XXX Check whether both DSOs must request action or only one */ +@@ -215,37 +223,41 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, + { + if (afct->symbind != NULL) + { +- uintptr_t new_value = afct->symbind (&sym, +- reloc_result->boundndx, +- &l_state->cookie, +- &result_state->cookie, +- &flags, +- strtab2 + defsym->st_name); ++ flags |= for_jmp_slot ? LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT ++ : 0; ++ new_value = afct->symbind (&sym, boundndx, ++ &l_state->cookie, ++ &result_state->cookie, &flags, ++ strtab2 + defsym->st_name); + if (new_value != (uintptr_t) sym.st_value) + { + flags |= LA_SYMB_ALTVALUE; +- sym.st_value = new_value; ++ sym.st_value = for_jmp_slot ++ ? DL_FIXUP_BINDNOW_ADDR_VALUE (new_value) : new_value; + } + } + + /* Remember the results for every audit library and store a summary + in the first two bits. */ +- reloc_result->enterexit &= flags & (LA_SYMB_NOPLTENTER +- | LA_SYMB_NOPLTEXIT); +- reloc_result->enterexit |= ((flags & (LA_SYMB_NOPLTENTER +- | LA_SYMB_NOPLTEXIT)) +- << ((cnt + 1) * 2)); ++ enterexit &= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT); ++ enterexit |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) ++ << ((cnt + 1) * 2)); + } + else + /* If the bind flags say this auditor is not interested, set the bits + manually. */ +- reloc_result->enterexit |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) +- << ((cnt + 1) * 2)); ++ enterexit |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) ++ << ((cnt + 1) * 2)); + afct = afct->next; + } + +- reloc_result->flags = flags; +- *value = DL_FIXUP_ADDR_VALUE (sym.st_value); ++ if (!for_jmp_slot) ++ { ++ reloc_result->enterexit = enterexit; ++ reloc_result->flags = flags; ++ } ++ ++ DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value); + } + + void +diff --git a/elf/do-rel.h b/elf/do-rel.h +index 0b04d1a0bf28b9f4..43c80e1c0067d9ca 100644 +--- a/elf/do-rel.h ++++ b/elf/do-rel.h +@@ -16,6 +16,8 @@ + License along with the GNU C Library; if not, see + . */ + ++#include ++ + /* This file may be included twice, to define both + `elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */ + +@@ -123,6 +125,10 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[], + + for (; r < end; ++r) + { ++ ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff; ++ const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)]; ++ void *const r_addr_arg = (void *) (l_addr + r->r_offset); ++ const struct r_found_version *rversion = &map->l_versions[ndx]; + #if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP + if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE) + { +@@ -133,10 +139,19 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[], + } + #endif + +- ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff; +- elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)], +- &map->l_versions[ndx], +- (void *) (l_addr + r->r_offset), skip_ifunc); ++ elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg, ++ skip_ifunc); ++#if defined SHARED && !defined RTLD_BOOTSTRAP ++ if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT ++ && GLRO(dl_naudit) > 0) ++ { ++ struct link_map *sym_map ++ = RESOLVE_MAP (map, scope, &sym, rversion, ++ ELF_MACHINE_JMP_SLOT); ++ if (sym != NULL) ++ _dl_audit_symbind (map, NULL, sym, r_addr_arg, sym_map); ++ } ++#endif + } + + #if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP +@@ -158,17 +173,33 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[], + else + { + for (; r < end; ++r) ++ { ++ const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)]; ++ void *const r_addr_arg = (void *) (l_addr + r->r_offset); + # ifdef ELF_MACHINE_IRELATIVE +- if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE) +- { +- if (r2 == NULL) +- r2 = r; +- end2 = r; +- } +- else ++ if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE) ++ { ++ if (r2 == NULL) ++ r2 = r; ++ end2 = r; ++ continue; ++ } + # endif +- elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, +- (void *) (l_addr + r->r_offset), skip_ifunc); ++ elf_machine_rel (map, scope, r, sym, NULL, r_addr_arg, ++ skip_ifunc); ++# if defined SHARED && !defined RTLD_BOOTSTRAP ++ if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT ++ && GLRO(dl_naudit) > 0) ++ { ++ struct link_map *sym_map ++ = RESOLVE_MAP (map, scope, &sym, ++ (struct r_found_version *) NULL, ++ ELF_MACHINE_JMP_SLOT); ++ if (sym != NULL) ++ _dl_audit_symbind (map, NULL , sym,r_addr_arg, sym_map); ++ } ++# endif ++ } + + # ifdef ELF_MACHINE_IRELATIVE + if (r2 != NULL) +diff --git a/elf/sotruss-lib.c b/elf/sotruss-lib.c +index f0a7e55599d76714..e1ac53f327a7571b 100644 +--- a/elf/sotruss-lib.c ++++ b/elf/sotruss-lib.c +@@ -17,6 +17,7 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + #include + #include +@@ -232,6 +233,12 @@ uintptr_t + la_symbind (Elf_Sym *sym, unsigned int ndx, uintptr_t *refcook, + uintptr_t *defcook, unsigned int *flags, const char *symname) + { ++ if (*flags & LA_SYMB_NOPLTENTER) ++ warnx ("cannot trace PLT enter (bind-now enabled)"); ++ ++ if (do_exit && *flags & LA_SYMB_NOPLTEXIT) ++ warnx ("cannot trace PLT exit (bind-now enabled)"); ++ + if (!do_exit) + *flags = LA_SYMB_NOPLTEXIT; + +diff --git a/elf/tst-audit24a.c b/elf/tst-audit24a.c +new file mode 100644 +index 0000000000000000..a1781c9b45f18fa0 +--- /dev/null ++++ b/elf/tst-audit24a.c +@@ -0,0 +1,36 @@ ++/* LD_AUDIT test for la_symbind and bind-now. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++int tst_audit24amod1_func1 (void); ++int tst_audit24amod1_func2 (void); ++int tst_audit24amod2_func1 (void); ++ ++int ++do_test (void) ++{ ++ TEST_COMPARE (tst_audit24amod1_func1 (), 1); ++ TEST_COMPARE (tst_audit24amod1_func2 (), 2); ++ TEST_COMPARE (tst_audit24amod2_func1 (), 10); ++ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-audit24amod1.c b/elf/tst-audit24amod1.c +new file mode 100644 +index 0000000000000000..0289a4abefbc7bbb +--- /dev/null ++++ b/elf/tst-audit24amod1.c +@@ -0,0 +1,31 @@ ++/* Module used by tst-audit24a. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++_Noreturn int ++tst_audit24amod1_func1 (void) ++{ ++ abort (); ++} ++ ++int ++tst_audit24amod1_func2 (void) ++{ ++ return 2; ++} +diff --git a/elf/tst-audit24amod2.c b/elf/tst-audit24amod2.c +new file mode 100644 +index 0000000000000000..1562afc9dfc1b9b3 +--- /dev/null ++++ b/elf/tst-audit24amod2.c +@@ -0,0 +1,25 @@ ++/* Module used by tst-audit24a. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++_Noreturn int ++tst_audit24amod2_func1 (void) ++{ ++ abort (); ++} +diff --git a/elf/tst-audit24b.c b/elf/tst-audit24b.c +new file mode 100644 +index 0000000000000000..567bee52c27f4361 +--- /dev/null ++++ b/elf/tst-audit24b.c +@@ -0,0 +1,37 @@ ++/* LD_AUDIT test for la_symbind and bind-now. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++/* This is similar to tst-audit24a, with the difference this modules ++ does not have the .gnu.version section header. */ ++ ++#include ++#include ++ ++int tst_audit24bmod1_func1 (void); ++int tst_audit24bmod1_func2 (void); ++ ++int ++do_test (void) ++{ ++ TEST_COMPARE (tst_audit24bmod1_func1 (), 1); ++ TEST_COMPARE (tst_audit24bmod1_func2 (), 2); ++ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-audit24bmod1.c b/elf/tst-audit24bmod1.c +new file mode 100644 +index 0000000000000000..57ce14a01bf72fb6 +--- /dev/null ++++ b/elf/tst-audit24bmod1.c +@@ -0,0 +1,31 @@ ++/* Module used by tst-audit24c. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++int tst_audit24bmod2_func1 (void); ++ ++int ++tst_audit24bmod1_func1 (void) ++{ ++ return -1; ++} ++ ++int ++tst_audit24bmod1_func2 (void) ++{ ++ return tst_audit24bmod2_func1 (); ++} +diff --git a/elf/tst-audit24bmod2.c b/elf/tst-audit24bmod2.c +new file mode 100644 +index 0000000000000000..b298ce0a05bf2db2 +--- /dev/null ++++ b/elf/tst-audit24bmod2.c +@@ -0,0 +1,23 @@ ++/* Module used by tst-audit24b. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++int ++tst_audit24bmod2_func1 (void) ++{ ++ return -1; ++} +diff --git a/elf/tst-audit24c.c b/elf/tst-audit24c.c +new file mode 100644 +index 0000000000000000..46ed328756067276 +--- /dev/null ++++ b/elf/tst-audit24c.c +@@ -0,0 +1,2 @@ ++/* It tests LD_BIND_NOW=1 instead of linking with -Wl,-z,now */ ++#include "tst-audit24a.c" +diff --git a/elf/tst-audit24d.c b/elf/tst-audit24d.c +new file mode 100644 +index 0000000000000000..543f3b86a6bbdead +--- /dev/null ++++ b/elf/tst-audit24d.c +@@ -0,0 +1,36 @@ ++/* LD_AUDIT test for la_symbind and bind-now. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++int tst_audit24dmod1_func1 (void); ++int tst_audit24dmod1_func2 (void); ++int tst_audit24dmod2_func1 (void); ++ ++int ++do_test (void) ++{ ++ TEST_COMPARE (tst_audit24dmod1_func1 (), 1); ++ TEST_COMPARE (tst_audit24dmod1_func2 (), 32); ++ TEST_COMPARE (tst_audit24dmod2_func1 (), 10); ++ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-audit24dmod1.c b/elf/tst-audit24dmod1.c +new file mode 100644 +index 0000000000000000..e563f69d638ac3f5 +--- /dev/null ++++ b/elf/tst-audit24dmod1.c +@@ -0,0 +1,33 @@ ++/* Module used by tst-audit24d. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++int tst_audit24dmod3_func1 (void); ++ ++_Noreturn int ++tst_audit24dmod1_func1 (void) ++{ ++ abort (); ++} ++ ++int ++tst_audit24dmod1_func2 (void) ++{ ++ return 2 + tst_audit24dmod3_func1 ();; ++} +diff --git a/elf/tst-audit24dmod2.c b/elf/tst-audit24dmod2.c +new file mode 100644 +index 0000000000000000..03fe9381281e5790 +--- /dev/null ++++ b/elf/tst-audit24dmod2.c +@@ -0,0 +1,28 @@ ++/* Module for tst-audit24d. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++int tst_audit24dmod4_func1 (void); ++ ++_Noreturn int ++tst_audit24dmod2_func1 (void) ++{ ++ tst_audit24dmod4_func1 (); ++ abort (); ++} +diff --git a/elf/tst-audit24dmod3.c b/elf/tst-audit24dmod3.c +new file mode 100644 +index 0000000000000000..106d517d2887d76c +--- /dev/null ++++ b/elf/tst-audit24dmod3.c +@@ -0,0 +1,31 @@ ++/* Module for tst-audit24d. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++_Noreturn int ++tst_audit24dmod3_func1 (void) ++{ ++ abort (); ++} ++ ++int ++tst_audit24dmod3_func2 (void) ++{ ++ return 4; ++} +diff --git a/elf/tst-audit24dmod4.c b/elf/tst-audit24dmod4.c +new file mode 100644 +index 0000000000000000..1da3b46917ba1083 +--- /dev/null ++++ b/elf/tst-audit24dmod4.c +@@ -0,0 +1,25 @@ ++/* Module for tst-audit24d. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++_Noreturn int ++tst_audit24dmod4_func1 (void) ++{ ++ abort (); ++} +diff --git a/elf/tst-audit25a.c b/elf/tst-audit25a.c +new file mode 100644 +index 0000000000000000..49173e862516e876 +--- /dev/null ++++ b/elf/tst-audit25a.c +@@ -0,0 +1,129 @@ ++/* Check LD_AUDIT and LD_BIND_NOW. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int restart; ++#define CMDLINE_OPTIONS \ ++ { "restart", no_argument, &restart, 1 }, ++ ++void tst_audit25mod1_func1 (void); ++void tst_audit25mod1_func2 (void); ++void tst_audit25mod2_func1 (void); ++void tst_audit25mod2_func2 (void); ++ ++static int ++handle_restart (void) ++{ ++ tst_audit25mod1_func1 (); ++ tst_audit25mod1_func2 (); ++ tst_audit25mod2_func1 (); ++ tst_audit25mod2_func2 (); ++ ++ return 0; ++} ++ ++static inline bool ++startswith (const char *str, const char *pre) ++{ ++ size_t lenpre = strlen (pre); ++ size_t lenstr = strlen (str); ++ return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0; ++} ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ /* We must have either: ++ - One or four parameters left if called initially: ++ + path to ld.so optional ++ + "--library-path" optional ++ + the library path optional ++ + the application name */ ++ ++ if (restart) ++ return handle_restart (); ++ ++ setenv ("LD_AUDIT", "tst-auditmod25.so", 0); ++ ++ char *spargv[9]; ++ int i = 0; ++ for (; i < argc - 1; i++) ++ spargv[i] = argv[i + 1]; ++ spargv[i++] = (char *) "--direct"; ++ spargv[i++] = (char *) "--restart"; ++ spargv[i] = NULL; ++ TEST_VERIFY_EXIT (i < array_length (spargv)); ++ ++ { ++ struct support_capture_subprocess result ++ = support_capture_subprogram (spargv[0], spargv); ++ support_capture_subprocess_check (&result, "tst-audit25a", 0, ++ sc_allow_stderr); ++ ++ /* tst-audit25a is build with -Wl,-z,lazy and tst-audit25mod1 with ++ -Wl,-z,now; so only tst_audit25mod3_func1 should be expected to ++ have LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. */ ++ TEST_COMPARE_STRING (result.err.buffer, ++ "la_symbind: tst_audit25mod3_func1 1\n" ++ "la_symbind: tst_audit25mod1_func1 0\n" ++ "la_symbind: tst_audit25mod1_func2 0\n" ++ "la_symbind: tst_audit25mod2_func1 0\n" ++ "la_symbind: tst_audit25mod4_func1 0\n" ++ "la_symbind: tst_audit25mod2_func2 0\n"); ++ ++ support_capture_subprocess_free (&result); ++ } ++ ++ { ++ setenv ("LD_BIND_NOW", "1", 0); ++ struct support_capture_subprocess result ++ = support_capture_subprogram (spargv[0], spargv); ++ support_capture_subprocess_check (&result, "tst-audit25a", 0, ++ sc_allow_stderr); ++ ++ /* With LD_BIND_NOW all symbols are expected to have ++ LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. Also the resolution ++ order is done in breadth-first order. */ ++ TEST_COMPARE_STRING (result.err.buffer, ++ "la_symbind: tst_audit25mod4_func1 1\n" ++ "la_symbind: tst_audit25mod3_func1 1\n" ++ "la_symbind: tst_audit25mod1_func1 1\n" ++ "la_symbind: tst_audit25mod2_func1 1\n" ++ "la_symbind: tst_audit25mod1_func2 1\n" ++ "la_symbind: tst_audit25mod2_func2 1\n"); ++ ++ support_capture_subprocess_free (&result); ++ } ++ ++ return 0; ++} ++ ++#define TEST_FUNCTION_ARGV do_test ++#include +diff --git a/elf/tst-audit25b.c b/elf/tst-audit25b.c +new file mode 100644 +index 0000000000000000..a56638d501f9bff5 +--- /dev/null ++++ b/elf/tst-audit25b.c +@@ -0,0 +1,128 @@ ++/* Check LD_AUDIT and LD_BIND_NOW. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int restart; ++#define CMDLINE_OPTIONS \ ++ { "restart", no_argument, &restart, 1 }, ++ ++void tst_audit25mod1_func1 (void); ++void tst_audit25mod1_func2 (void); ++void tst_audit25mod2_func1 (void); ++void tst_audit25mod2_func2 (void); ++ ++static int ++handle_restart (void) ++{ ++ tst_audit25mod1_func1 (); ++ tst_audit25mod1_func2 (); ++ tst_audit25mod2_func1 (); ++ tst_audit25mod2_func2 (); ++ ++ return 0; ++} ++ ++static inline bool ++startswith (const char *str, const char *pre) ++{ ++ size_t lenpre = strlen (pre); ++ size_t lenstr = strlen (str); ++ return lenstr >= lenpre && memcmp (pre, str, lenpre) == 0; ++} ++ ++static int ++do_test (int argc, char *argv[]) ++{ ++ /* We must have either: ++ - One or four parameters left if called initially: ++ + path to ld.so optional ++ + "--library-path" optional ++ + the library path optional ++ + the application name */ ++ ++ if (restart) ++ return handle_restart (); ++ ++ setenv ("LD_AUDIT", "tst-auditmod25.so", 0); ++ ++ char *spargv[9]; ++ int i = 0; ++ for (; i < argc - 1; i++) ++ spargv[i] = argv[i + 1]; ++ spargv[i++] = (char *) "--direct"; ++ spargv[i++] = (char *) "--restart"; ++ spargv[i] = NULL; ++ ++ { ++ struct support_capture_subprocess result ++ = support_capture_subprogram (spargv[0], spargv); ++ support_capture_subprocess_check (&result, "tst-audit25a", 0, ++ sc_allow_stderr); ++ ++ /* tst-audit25a and tst-audit25mod1 are built with -Wl,-z,now, but ++ tst-audit25mod2 is built with -Wl,-z,lazy. So only ++ tst_audit25mod4_func1 (called by tst_audit25mod2_func1) should not ++ have LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. */ ++ TEST_COMPARE_STRING (result.err.buffer, ++ "la_symbind: tst_audit25mod3_func1 1\n" ++ "la_symbind: tst_audit25mod1_func1 1\n" ++ "la_symbind: tst_audit25mod2_func1 1\n" ++ "la_symbind: tst_audit25mod1_func2 1\n" ++ "la_symbind: tst_audit25mod2_func2 1\n" ++ "la_symbind: tst_audit25mod4_func1 0\n"); ++ ++ support_capture_subprocess_free (&result); ++ } ++ ++ { ++ setenv ("LD_BIND_NOW", "1", 0); ++ struct support_capture_subprocess result ++ = support_capture_subprogram (spargv[0], spargv); ++ support_capture_subprocess_check (&result, "tst-audit25a", 0, ++ sc_allow_stderr); ++ ++ /* With LD_BIND_NOW all symbols are expected to have ++ LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. Also the resolution ++ order is done in breadth-first order. */ ++ TEST_COMPARE_STRING (result.err.buffer, ++ "la_symbind: tst_audit25mod4_func1 1\n" ++ "la_symbind: tst_audit25mod3_func1 1\n" ++ "la_symbind: tst_audit25mod1_func1 1\n" ++ "la_symbind: tst_audit25mod2_func1 1\n" ++ "la_symbind: tst_audit25mod1_func2 1\n" ++ "la_symbind: tst_audit25mod2_func2 1\n"); ++ ++ support_capture_subprocess_free (&result); ++ } ++ ++ return 0; ++} ++ ++#define TEST_FUNCTION_ARGV do_test ++#include +diff --git a/elf/tst-audit25mod1.c b/elf/tst-audit25mod1.c +new file mode 100644 +index 0000000000000000..a132e34a9b2cf51f +--- /dev/null ++++ b/elf/tst-audit25mod1.c +@@ -0,0 +1,30 @@ ++/* Module used by tst-audit25. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++void tst_audit25mod3_func1 (void); ++ ++void ++tst_audit25mod1_func1 (void) ++{ ++ tst_audit25mod3_func1 (); ++} ++ ++void ++tst_audit25mod1_func2 (void) ++{ ++} +diff --git a/elf/tst-audit25mod2.c b/elf/tst-audit25mod2.c +new file mode 100644 +index 0000000000000000..92da26fa80b202c2 +--- /dev/null ++++ b/elf/tst-audit25mod2.c +@@ -0,0 +1,30 @@ ++/* Module used by tst-audit25. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++void tst_audit25mod4_func1 (void); ++ ++void ++tst_audit25mod2_func1 (void) ++{ ++ tst_audit25mod4_func1 (); ++} ++ ++void ++tst_audit25mod2_func2 (void) ++{ ++} +diff --git a/elf/tst-audit25mod3.c b/elf/tst-audit25mod3.c +new file mode 100644 +index 0000000000000000..af83e8919083adef +--- /dev/null ++++ b/elf/tst-audit25mod3.c +@@ -0,0 +1,22 @@ ++/* Module used by tst-audit25. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++void ++tst_audit25mod3_func1 (void) ++{ ++} +diff --git a/elf/tst-audit25mod4.c b/elf/tst-audit25mod4.c +new file mode 100644 +index 0000000000000000..6cdf34357582da16 +--- /dev/null ++++ b/elf/tst-audit25mod4.c +@@ -0,0 +1,22 @@ ++/* Module used by tst-audit25. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++void ++tst_audit25mod4_func1 (void) ++{ ++} +diff --git a/elf/tst-auditmod24.h b/elf/tst-auditmod24.h +new file mode 100644 +index 0000000000000000..5fdbfef12dac2b2a +--- /dev/null ++++ b/elf/tst-auditmod24.h +@@ -0,0 +1,29 @@ ++/* Auxiliary functions for tst-audit24x. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _TST_AUDITMOD24_H ++#define _TST_AUDITMOD24_H ++ ++static void ++test_symbind_flags (unsigned int flags) ++{ ++ if ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) == 0) ++ abort (); ++} ++ ++#endif +diff --git a/elf/tst-auditmod24a.c b/elf/tst-auditmod24a.c +new file mode 100644 +index 0000000000000000..d8e88f3984af1707 +--- /dev/null ++++ b/elf/tst-auditmod24a.c +@@ -0,0 +1,114 @@ ++/* Audit modules for tst-audit24a. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define AUDIT24_COOKIE 0x1 ++#define AUDIT24MOD1_COOKIE 0x2 ++#define AUDIT24MOD2_COOKIE 0x3 ++ ++#ifndef TEST_NAME ++# define TEST_NAME "tst-audit24a" ++#endif ++#ifndef TEST_MOD ++# define TEST_MOD TEST_NAME ++#endif ++#ifndef TEST_FUNC ++# define TEST_FUNC "tst_audit24a" ++#endif ++ ++unsigned int ++la_version (unsigned int version) ++{ ++ return LAV_CURRENT; ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ const char *p = strrchr (map->l_name, '/'); ++ const char *l_name = p == NULL ? TEST_NAME : p + 1; ++ ++ uintptr_t ck = -1; ++ if (strcmp (l_name, TEST_MOD "mod1.so") == 0) ++ ck = AUDIT24MOD1_COOKIE; ++ else if (strcmp (l_name, TEST_MOD "mod2.so") == 0) ++ ck = AUDIT24MOD2_COOKIE; ++ else if (strcmp (l_name, TEST_NAME) == 0) ++ ck = AUDIT24_COOKIE; ++ ++ *cookie = ck; ++ return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO; ++} ++ ++static int ++tst_func1 (void) ++{ ++ return 1; ++} ++ ++static int ++tst_func2 (void) ++{ ++ return 10; ++} ++ ++#if __ELF_NATIVE_CLASS == 64 ++uintptr_t ++la_symbind64 (Elf64_Sym *sym, unsigned int ndx, ++ uintptr_t *refcook, uintptr_t *defcook, ++ unsigned int *flags, const char *symname) ++#else ++uintptr_t ++la_symbind32 (Elf32_Sym *sym, unsigned int ndx, ++ uintptr_t *refcook, uintptr_t *defcook, ++ unsigned int *flags, const char *symname) ++#endif ++{ ++ if (*refcook == AUDIT24_COOKIE) ++ { ++ if (*defcook == AUDIT24MOD1_COOKIE) ++ { ++ /* Check if bind-now symbols are advertised to not call the PLT ++ hooks. */ ++ test_symbind_flags (*flags); ++ ++ if (strcmp (symname, TEST_FUNC "mod1_func1") == 0) ++ return (uintptr_t) tst_func1; ++ else if (strcmp (symname, TEST_FUNC "mod1_func2") == 0) ++ return sym->st_value; ++ abort (); ++ } ++ if (*defcook == AUDIT24MOD2_COOKIE ++ && (strcmp (symname, TEST_FUNC "mod2_func1") == 0)) ++ { ++ test_symbind_flags (*flags); ++ ++ return (uintptr_t) tst_func2; ++ } ++ ++ /* malloc functions. */ ++ return sym->st_value; ++ } ++ ++ abort (); ++} +diff --git a/elf/tst-auditmod24b.c b/elf/tst-auditmod24b.c +new file mode 100644 +index 0000000000000000..e98f6d5ec528fe03 +--- /dev/null ++++ b/elf/tst-auditmod24b.c +@@ -0,0 +1,104 @@ ++/* Audit modules for tst-audit24b. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define TEST_NAME "tst-audit24b" ++#define TEST_FUNC "tst_audit24b" ++ ++#define AUDIT24_COOKIE 0x1 ++#define AUDIT24MOD1_COOKIE 0x2 ++#define AUDIT24MOD2_COOKIE 0x3 ++ ++unsigned int ++la_version (unsigned int version) ++{ ++ return LAV_CURRENT; ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ const char *p = strrchr (map->l_name, '/'); ++ const char *l_name = p == NULL ? TEST_NAME : p + 1; ++ ++ uintptr_t ck = -1; ++ if (strcmp (l_name, TEST_NAME "mod1.so") == 0) ++ ck = AUDIT24MOD1_COOKIE; ++ else if (strcmp (l_name, TEST_NAME "mod2.so") == 0) ++ ck = AUDIT24MOD2_COOKIE; ++ else if (strcmp (l_name, TEST_NAME) == 0) ++ ck = AUDIT24_COOKIE; ++ ++ *cookie = ck; ++ return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO; ++} ++ ++static int ++tst_func1 (void) ++{ ++ return 1; ++} ++ ++static int ++tst_func2 (void) ++{ ++ return 2; ++} ++ ++#if __ELF_NATIVE_CLASS == 64 ++uintptr_t ++la_symbind64 (Elf64_Sym *sym, unsigned int ndx, ++ uintptr_t *refcook, uintptr_t *defcook, ++ unsigned int *flags, const char *symname) ++#else ++uintptr_t ++la_symbind32 (Elf32_Sym *sym, unsigned int ndx, ++ uintptr_t *refcook, uintptr_t *defcook, ++ unsigned int *flags, const char *symname) ++#endif ++{ ++ if (*refcook == AUDIT24_COOKIE) ++ { ++ if (*defcook == AUDIT24MOD1_COOKIE) ++ { ++ if (strcmp (symname, TEST_FUNC "mod1_func1") == 0) ++ return (uintptr_t) tst_func1; ++ else if (strcmp (symname, TEST_FUNC "mod1_func2") == 0) ++ return sym->st_value; ++ abort (); ++ } ++ /* malloc functions. */ ++ return sym->st_value; ++ } ++ else if (*refcook == AUDIT24MOD1_COOKIE) ++ { ++ if (*defcook == AUDIT24MOD2_COOKIE ++ && (strcmp (symname, TEST_FUNC "mod2_func1") == 0)) ++ { ++ test_symbind_flags (*flags); ++ return (uintptr_t) tst_func2; ++ } ++ } ++ ++ abort (); ++} +diff --git a/elf/tst-auditmod24c.c b/elf/tst-auditmod24c.c +new file mode 100644 +index 0000000000000000..67e62c9d332f48a7 +--- /dev/null ++++ b/elf/tst-auditmod24c.c +@@ -0,0 +1,3 @@ ++#define TEST_NAME "tst-audit24c" ++#define TEST_MOD "tst-audit24a" ++#include "tst-auditmod24a.c" +diff --git a/elf/tst-auditmod24d.c b/elf/tst-auditmod24d.c +new file mode 100644 +index 0000000000000000..8c803ecc0a48f21b +--- /dev/null ++++ b/elf/tst-auditmod24d.c +@@ -0,0 +1,120 @@ ++/* Audit module for tst-audit24d. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define AUDIT24_COOKIE 0x0 ++#define AUDIT24MOD1_COOKIE 0x1 ++#define AUDIT24MOD2_COOKIE 0x2 ++#define AUDIT24MOD3_COOKIE 0x3 ++#define AUDIT24MOD4_COOKIE 0x4 ++ ++unsigned int ++la_version (unsigned int version) ++{ ++ return LAV_CURRENT; ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ const char *p = strrchr (map->l_name, '/'); ++ const char *l_name = p == NULL ? "tst-audit24d" : p + 1; ++ ++ uintptr_t ck = -1; ++ if (strcmp (l_name, "tst-audit24dmod1.so") == 0) ++ ck = AUDIT24MOD1_COOKIE; ++ else if (strcmp (l_name, "tst-audit24dmod2.so") == 0) ++ ck = AUDIT24MOD2_COOKIE; ++ else if (strcmp (l_name, "tst-audit24dmod3.so") == 0) ++ ck = AUDIT24MOD3_COOKIE; ++ else if (strcmp (l_name, "tst-audit24dmod.so") == 0) ++ ck = AUDIT24MOD4_COOKIE; ++ else if (strcmp (l_name, "tst-audit24d") == 0) ++ ck = AUDIT24_COOKIE; ++ ++ *cookie = ck; ++ return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO; ++} ++ ++static int ++tst_audit24dmod1_func1 (void) ++{ ++ return 1; ++} ++ ++static int ++tst_audit24dmod2_func1 (void) ++{ ++ return 10; ++} ++ ++static int ++tst_audit24dmod3_func1 (void) ++{ ++ return 30; ++} ++ ++#include ++ ++#if __ELF_NATIVE_CLASS == 64 ++uintptr_t ++la_symbind64 (Elf64_Sym *sym, unsigned int ndx, ++ uintptr_t *refcook, uintptr_t *defcook, ++ unsigned int *flags, const char *symname) ++#else ++uintptr_t ++la_symbind32 (Elf32_Sym *sym, unsigned int ndx, ++ uintptr_t *refcook, uintptr_t *defcook, ++ unsigned int *flags, const char *symname) ++#endif ++{ ++ if (*refcook == AUDIT24_COOKIE) ++ { ++ if (*defcook == AUDIT24MOD1_COOKIE) ++ { ++ if (strcmp (symname, "tst_audit24dmod1_func1") == 0) ++ return (uintptr_t) tst_audit24dmod1_func1; ++ else if (strcmp (symname, "tst_audit24dmod1_func2") == 0) ++ return sym->st_value; ++ abort (); ++ } ++ if (*defcook == AUDIT24MOD2_COOKIE ++ && (strcmp (symname, "tst_audit24dmod2_func1") == 0)) ++ return (uintptr_t) tst_audit24dmod2_func1; ++ ++ /* malloc functions. */ ++ return sym->st_value; ++ } ++ else if (*refcook == AUDIT24MOD1_COOKIE) ++ { ++ if (*defcook == AUDIT24MOD3_COOKIE ++ && strcmp (symname, "tst_audit24dmod3_func1") == 0) ++ { ++ test_symbind_flags (*flags); ++ ++ return (uintptr_t) tst_audit24dmod3_func1; ++ } ++ } ++ ++ abort (); ++} +diff --git a/elf/tst-auditmod25.c b/elf/tst-auditmod25.c +new file mode 100644 +index 0000000000000000..526f5c54bc2c3b8c +--- /dev/null ++++ b/elf/tst-auditmod25.c +@@ -0,0 +1,79 @@ ++/* Audit modules for tst-audit25a. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#define AUDIT25_COOKIE 0x1 ++#define AUDIT25MOD1_COOKIE 0x2 ++#define AUDIT25MOD2_COOKIE 0x3 ++#define AUDIT25MOD3_COOKIE 0x2 ++#define AUDIT25MOD4_COOKIE 0x3 ++ ++#define TEST_NAME "tst-audit25" ++#define TEST_MOD "tst-audit25" ++#define TEST_FUNC "tst_audit25" ++ ++unsigned int ++la_version (unsigned int version) ++{ ++ return LAV_CURRENT; ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ const char *p = strrchr (map->l_name, '/'); ++ const char *l_name = p == NULL ? TEST_NAME : p + 1; ++ ++ uintptr_t ck = -1; ++ if (strcmp (l_name, TEST_MOD "mod1.so") == 0) ++ ck = AUDIT25MOD1_COOKIE; ++ else if (strcmp (l_name, TEST_MOD "mod2.so") == 0) ++ ck = AUDIT25MOD2_COOKIE; ++ else if (strcmp (l_name, TEST_MOD "mod3.so") == 0) ++ ck = AUDIT25MOD3_COOKIE; ++ else if (strcmp (l_name, TEST_MOD "mod4.so") == 0) ++ ck = AUDIT25MOD4_COOKIE; ++ else if (strncmp (l_name, TEST_NAME, strlen (TEST_NAME)) == 0) ++ ck = AUDIT25_COOKIE; ++ ++ *cookie = ck; ++ return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO; ++} ++ ++#if __ELF_NATIVE_CLASS == 64 ++uintptr_t ++la_symbind64 (Elf64_Sym *sym, unsigned int ndx, ++ uintptr_t *refcook, uintptr_t *defcook, ++ unsigned int *flags, const char *symname) ++#else ++uintptr_t ++la_symbind32 (Elf32_Sym *sym, unsigned int ndx, ++ uintptr_t *refcook, uintptr_t *defcook, ++ unsigned int *flags, const char *symname) ++#endif ++{ ++ if (*refcook != -1 && *defcook != -1) ++ fprintf (stderr, "la_symbind: %s %u\n", symname, ++ *flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) ? 1 : 0); ++ return sym->st_value; ++} +diff --git a/sysdeps/generic/dl-lookupcfg.h b/sysdeps/generic/dl-lookupcfg.h +index e7d37170147aba83..7412c6391b0c3e02 100644 +--- a/sysdeps/generic/dl-lookupcfg.h ++++ b/sysdeps/generic/dl-lookupcfg.h +@@ -26,3 +26,6 @@ + #define DL_FIXUP_VALUE_CODE_ADDR(value) (value) + #define DL_FIXUP_VALUE_ADDR(value) (value) + #define DL_FIXUP_ADDR_VALUE(addr) (addr) ++#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr) ++#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ ++ (*value) = st_value; +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 73f4863fd43922b9..d4f70211c34d1c59 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -1299,7 +1299,10 @@ void _dl_audit_objclose (struct link_map *l) + /* Call the la_preinit from the audit modules for the link_map L. */ + void _dl_audit_preinit (struct link_map *l); + +-/* Call the la_symbind{32,64} from the audit modules for the link_map L. */ ++/* Call the la_symbind{32,64} from the audit modules for the link_map L. If ++ RELOC_RESULT is NULL it assumes the symbol to be bind-now and will set ++ the flags with LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT prior calling ++ la_symbind{32,64}. */ + void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, + const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value, + lookup_t result) +diff --git a/sysdeps/hppa/dl-lookupcfg.h b/sysdeps/hppa/dl-lookupcfg.h +index 38db345936cb6335..c3fea1fe5776b17a 100644 +--- a/sysdeps/hppa/dl-lookupcfg.h ++++ b/sysdeps/hppa/dl-lookupcfg.h +@@ -80,3 +80,6 @@ void attribute_hidden _dl_unmap (struct link_map *map); + #define DL_FIXUP_VALUE_CODE_ADDR(value) ((value).ip) + #define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value)) + #define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr)) ++#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr) ++#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ ++ (*value) = *(struct fdesc *) (st_value) +diff --git a/sysdeps/ia64/dl-lookupcfg.h b/sysdeps/ia64/dl-lookupcfg.h +index 48f91202c43f8fda..97ad4b70794135a2 100644 +--- a/sysdeps/ia64/dl-lookupcfg.h ++++ b/sysdeps/ia64/dl-lookupcfg.h +@@ -74,3 +74,6 @@ extern void attribute_hidden _dl_unmap (struct link_map *map); + + #define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value)) + #define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr)) ++#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr) ++#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ ++ (*value) = *(struct fdesc *) (st_value) +diff --git a/sysdeps/powerpc/dl-lookupcfg.h b/sysdeps/powerpc/dl-lookupcfg.h +new file mode 100644 +index 0000000000000000..25abcc1d12b15bfc +--- /dev/null ++++ b/sysdeps/powerpc/dl-lookupcfg.h +@@ -0,0 +1,39 @@ ++/* Configuration of lookup functions. PowerPC version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#define DL_FIXUP_VALUE_TYPE ElfW(Addr) ++#define DL_FIXUP_MAKE_VALUE(map, addr) (addr) ++#define DL_FIXUP_VALUE_CODE_ADDR(value) (value) ++#define DL_FIXUP_VALUE_ADDR(value) (value) ++#define DL_FIXUP_ADDR_VALUE(addr) (addr) ++#if __WORDSIZE == 64 && _CALL_ELF == 1 ++/* We need to correctly set the audit modules value for bind-now. */ ++# define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) \ ++ (((Elf64_FuncDesc *)(addr))->fd_func) ++# define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ ++ ({ \ ++ Elf64_FuncDesc *opd = (Elf64_FuncDesc *) (value); \ ++ opd->fd_func = (st_value); \ ++ if ((new_value) != (uintptr_t) (st_value)) \ ++ opd->fd_toc = ((Elf64_FuncDesc *)(new_value))->fd_toc; \ ++ }) ++#else ++# define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr) ++# define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ ++ (*value) = st_value; ++#endif diff --git a/glibc-rh2047981-34.patch b/glibc-rh2047981-34.patch new file mode 100644 index 0000000..8809b82 --- /dev/null +++ b/glibc-rh2047981-34.patch @@ -0,0 +1,1042 @@ +commit ce9a68c57c260c8417afc93972849ac9ad243ec4 +Author: Ben Woodard +Date: Mon Jan 24 10:46:18 2022 -0300 + + elf: Fix runtime linker auditing on aarch64 (BZ #26643) + + The rtld audit support show two problems on aarch64: + + 1. _dl_runtime_resolve does not preserve x8, the indirect result + location register, which might generate wrong result calls + depending of the function signature. + + 2. The NEON Q registers pushed onto the stack by _dl_runtime_resolve + were twice the size of D registers extracted from the stack frame by + _dl_runtime_profile. + + While 2. might result in wrong information passed on the PLT tracing, + 1. generates wrong runtime behaviour. + + The aarch64 rtld audit support is changed to: + + * Both La_aarch64_regs and La_aarch64_retval are expanded to include + both x8 and the full sized NEON V registers, as defined by the + ABI. + + * dl_runtime_profile needed to extract registers saved by + _dl_runtime_resolve and put them into the new correctly sized + La_aarch64_regs structure. + + * The LAV_CURRENT check is change to only accept new audit modules + to avoid the undefined behavior of not save/restore x8. + + * Different than other architectures, audit modules older than + LAV_CURRENT are rejected (both La_aarch64_regs and La_aarch64_retval + changed their layout and there are no requirements to support multiple + audit interface with the inherent aarch64 issues). + + * A new field is also reserved on both La_aarch64_regs and + La_aarch64_retval to support variant pcs symbols. + + Similar to x86, a new La_aarch64_vector type to represent the NEON + register is added on the La_aarch64_regs (so each type can be accessed + directly). + + Since LAV_CURRENT was already bumped to support bind-now, there is + no need to increase it again. + + Checked on aarch64-linux-gnu. + + Co-authored-by: Adhemerval Zanella + Reviewed-by: Szabolcs Nagy + Reviewed-by: Carlos O'Donell + Tested-by: Carlos O'Donell + +Conflicts: + elf/rtld.c + sysdeps/aarch64/Makefile + Rewrite slightly for inclusion in elf/ testing. + +diff --git a/elf/rtld.c b/elf/rtld.c +index caa980dbda3d1a72..aee5ca357f66121e 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -49,6 +49,7 @@ + #include + #include + #include ++#include + + #include + +@@ -1002,7 +1003,7 @@ file=%s [%lu]; audit interface function la_version returned zero; ignored.\n", + return; + } + +- if (lav > LAV_CURRENT) ++ if (!_dl_audit_check_version (lav)) + { + _dl_debug_printf ("\ + ERROR: audit interface '%s' requires version %d (maximum supported version %d); ignored.\n", +diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile +index 3ec78fefc6dd5797..794ea7d13ae2737f 100644 +--- a/sysdeps/aarch64/Makefile ++++ b/sysdeps/aarch64/Makefile +@@ -4,6 +4,26 @@ ifeq ($(subdir),elf) + sysdep-dl-routines += tlsdesc dl-tlsdesc + gen-as-const-headers += dl-link.sym + ++tests += tst-audit26 \ ++ tst-audit27 ++ ++modules-names += \ ++ tst-audit26mod \ ++ tst-auditmod26 \ ++ tst-audit27mod \ ++ tst-auditmod27 ++ ++$(objpfx)tst-audit26: $(objpfx)tst-audit26mod.so \ ++ $(objpfx)tst-auditmod26.so ++LDFLAGS-tst-audit26 += -Wl,-z,lazy ++tst-audit26-ENV = LD_AUDIT=$(objpfx)tst-auditmod26.so ++ ++$(objpfx)tst-audit27: $(objpfx)tst-audit27mod.so \ ++ $(objpfx)tst-auditmod27.so ++$(objpfx)tst-audit27mod.so: $(libsupport) ++LDFLAGS-tst-audit27 += -Wl,-z,lazy ++tst-audit27-ENV = LD_AUDIT=$(objpfx)tst-auditmod27.so ++ + ifeq (yes,$(aarch64-variant-pcs)) + tests += tst-vpcs + modules-names += tst-vpcs-mod +diff --git a/sysdeps/aarch64/bits/link.h b/sysdeps/aarch64/bits/link.h +index 5a7fc1ccd494b2a7..f4f844bfefdaf2f5 100644 +--- a/sysdeps/aarch64/bits/link.h ++++ b/sysdeps/aarch64/bits/link.h +@@ -20,23 +20,31 @@ + # error "Never include directly; use instead." + #endif + ++typedef union ++{ ++ float s; ++ double d; ++ long double q; ++} La_aarch64_vector; ++ + /* Registers for entry into PLT on AArch64. */ + typedef struct La_aarch64_regs + { +- uint64_t lr_xreg[8]; +- uint64_t lr_dreg[8]; +- uint64_t lr_sp; +- uint64_t lr_lr; ++ uint64_t lr_xreg[9]; ++ La_aarch64_vector lr_vreg[8]; ++ uint64_t lr_sp; ++ uint64_t lr_lr; ++ void *lr_vpcs; + } La_aarch64_regs; + + /* Return values for calls from PLT on AArch64. */ + typedef struct La_aarch64_retval + { +- /* Up to two integer registers can be used for a return value. */ +- uint64_t lrv_xreg[2]; +- /* Up to four D registers can be used for a return value. */ +- uint64_t lrv_dreg[4]; +- ++ /* Up to eight integer registers can be used for a return value. */ ++ uint64_t lrv_xreg[8]; ++ /* Up to eight V registers can be used for a return value. */ ++ La_aarch64_vector lrv_vreg[8]; ++ void *lrv_vpcs; + } La_aarch64_retval; + __BEGIN_DECLS + +diff --git a/sysdeps/aarch64/dl-audit-check.h b/sysdeps/aarch64/dl-audit-check.h +new file mode 100644 +index 0000000000000000..e324339a1d4abec3 +--- /dev/null ++++ b/sysdeps/aarch64/dl-audit-check.h +@@ -0,0 +1,28 @@ ++/* rtld-audit version check. AArch64 version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++static inline bool ++_dl_audit_check_version (unsigned int lav) ++{ ++ /* Audit version 1 do not save x8 or NEON registers, which required ++ changing La_aarch64_regs and La_aarch64_retval layout (BZ#26643). The ++ missing indirect result save/restore makes _dl_runtime_profile ++ potentially trigger undefined behavior if the function returns a large ++ struct (even when PLT trace is not requested). */ ++ return lav == LAV_CURRENT; ++} +diff --git a/sysdeps/aarch64/dl-link.sym b/sysdeps/aarch64/dl-link.sym +index d67d28b40ce7d4ff..cb4dcdcbed0db492 100644 +--- a/sysdeps/aarch64/dl-link.sym ++++ b/sysdeps/aarch64/dl-link.sym +@@ -7,9 +7,11 @@ DL_SIZEOF_RG sizeof(struct La_aarch64_regs) + DL_SIZEOF_RV sizeof(struct La_aarch64_retval) + + DL_OFFSET_RG_X0 offsetof(struct La_aarch64_regs, lr_xreg) +-DL_OFFSET_RG_D0 offsetof(struct La_aarch64_regs, lr_dreg) ++DL_OFFSET_RG_V0 offsetof(struct La_aarch64_regs, lr_vreg) + DL_OFFSET_RG_SP offsetof(struct La_aarch64_regs, lr_sp) + DL_OFFSET_RG_LR offsetof(struct La_aarch64_regs, lr_lr) ++DL_OFFSET_RG_VPCS offsetof(struct La_aarch64_regs, lr_vpcs) + + DL_OFFSET_RV_X0 offsetof(struct La_aarch64_retval, lrv_xreg) +-DL_OFFSET_RV_D0 offsetof(struct La_aarch64_retval, lrv_dreg) ++DL_OFFSET_RV_V0 offsetof(struct La_aarch64_retval, lrv_vreg) ++DL_OFFSET_RV_VPCS offsetof(struct La_aarch64_retval, lrv_vpcs) +diff --git a/sysdeps/aarch64/dl-trampoline.S b/sysdeps/aarch64/dl-trampoline.S +index 18740398e63fdf97..a83e7fc5f97047e2 100644 +--- a/sysdeps/aarch64/dl-trampoline.S ++++ b/sysdeps/aarch64/dl-trampoline.S +@@ -44,7 +44,8 @@ _dl_runtime_resolve: + + cfi_rel_offset (lr, 8) + +- /* Save arguments. */ ++ /* Note: Saving x9 is not required by the ABI but the assembler requires ++ the immediate values of operand 3 to be a multiple of 16 */ + stp x8, x9, [sp, #-(80+8*16)]! + cfi_adjust_cfa_offset (80+8*16) + cfi_rel_offset (x8, 0) +@@ -135,7 +136,7 @@ _dl_runtime_profile: + Stack frame layout: + [sp, #...] lr + [sp, #...] &PLTGOT[n] +- [sp, #96] La_aarch64_regs ++ [sp, #256] La_aarch64_regs + [sp, #48] La_aarch64_retval + [sp, #40] frame size return from pltenter + [sp, #32] dl_profile_call saved x1 +@@ -176,19 +177,25 @@ _dl_runtime_profile: + stp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3] + cfi_rel_offset (x6, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 0) + cfi_rel_offset (x7, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 8) +- +- stp d0, d1, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0] +- cfi_rel_offset (d0, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0) +- cfi_rel_offset (d1, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0 + 8) +- stp d2, d3, [X29, #OFFSET_RG+ DL_OFFSET_RG_D0 + 16*1] +- cfi_rel_offset (d2, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 0) +- cfi_rel_offset (d3, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 8) +- stp d4, d5, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2] +- cfi_rel_offset (d4, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 0) +- cfi_rel_offset (d5, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 8) +- stp d6, d7, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3] +- cfi_rel_offset (d6, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 0) +- cfi_rel_offset (d7, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 8) ++ str x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4 + 0] ++ cfi_rel_offset (x8, OFFSET_RG + DL_OFFSET_RG_X0 + 16*4 + 0) ++ /* Note 8 bytes of padding is in the stack frame for alignment */ ++ ++ stp q0, q1, [X29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*0] ++ cfi_rel_offset (q0, OFFSET_RG + DL_OFFSET_RG_V0 + 32*0) ++ cfi_rel_offset (q1, OFFSET_RG + DL_OFFSET_RG_V0 + 32*0 + 16) ++ stp q2, q3, [X29, #OFFSET_RG+ DL_OFFSET_RG_V0 + 32*1] ++ cfi_rel_offset (q2, OFFSET_RG + DL_OFFSET_RG_V0 + 32*1 + 0) ++ cfi_rel_offset (q3, OFFSET_RG + DL_OFFSET_RG_V0 + 32*1 + 16) ++ stp q4, q5, [X29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*2] ++ cfi_rel_offset (q4, OFFSET_RG + DL_OFFSET_RG_V0 + 32*2 + 0) ++ cfi_rel_offset (q5, OFFSET_RG + DL_OFFSET_RG_V0 + 32*2 + 16) ++ stp q6, q7, [X29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*3] ++ cfi_rel_offset (q6, OFFSET_RG + DL_OFFSET_RG_V0 + 32*3 + 0) ++ cfi_rel_offset (q7, OFFSET_RG + DL_OFFSET_RG_V0 + 32*3 + 16) ++ ++ /* No APCS extension supported. */ ++ str xzr, [X29, #OFFSET_RG + DL_OFFSET_RG_VPCS] + + add x0, x29, #SF_SIZE + 16 + ldr x1, [x29, #OFFSET_LR] +@@ -227,10 +234,11 @@ _dl_runtime_profile: + ldp x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1] + ldp x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2] + ldp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3] +- ldp d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0] +- ldp d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1] +- ldp d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2] +- ldp d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3] ++ ldr x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4] ++ ldp q0, q1, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*0] ++ ldp q2, q3, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*1] ++ ldp q4, q5, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*2] ++ ldp q6, q7, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*3] + + cfi_def_cfa_register (sp) + ldp x29, x30, [x29, #0] +@@ -264,14 +272,22 @@ _dl_runtime_profile: + ldp x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1] + ldp x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2] + ldp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3] +- ldp d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0] +- ldp d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1] +- ldp d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2] +- ldp d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3] ++ ldr x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4] ++ ldp q0, q1, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*0] ++ ldp q2, q3, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*1] ++ ldp q4, q5, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*2] ++ ldp q6, q7, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*3] + blr ip0 +- stp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0] +- stp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0] +- stp d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1] ++ stp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*0] ++ stp x2, x3, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*1] ++ stp x4, x5, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*2] ++ stp x6, x7, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*3] ++ str x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4] ++ stp q0, q1, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*0] ++ stp q2, q3, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*1] ++ stp q4, q5, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*2] ++ stp q6, q7, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*3] ++ str xzr, [X29, #OFFSET_RV + DL_OFFSET_RG_VPCS] + + /* Setup call to pltexit */ + ldp x0, x1, [x29, #OFFSET_SAVED_CALL_X0] +@@ -279,9 +295,16 @@ _dl_runtime_profile: + add x3, x29, #OFFSET_RV + bl _dl_audit_pltexit + +- ldp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0] +- ldp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0] +- ldp d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1] ++ ldp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*0] ++ ldp x2, x3, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*1] ++ ldp x4, x5, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*2] ++ ldp x6, x7, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*3] ++ ldr x8, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*4] ++ ldp q0, q1, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*0] ++ ldp q2, q3, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*1] ++ ldp q4, q5, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*2] ++ ldp q6, q7, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*3] ++ + /* LR from within La_aarch64_reg */ + ldr lr, [x29, #OFFSET_RG + DL_OFFSET_RG_LR] + cfi_restore(lr) +diff --git a/sysdeps/aarch64/tst-audit26.c b/sysdeps/aarch64/tst-audit26.c +new file mode 100644 +index 0000000000000000..46de8acd219cb8bc +--- /dev/null ++++ b/sysdeps/aarch64/tst-audit26.c +@@ -0,0 +1,37 @@ ++/* Check LD_AUDIT for aarch64 ABI specifics. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include "tst-audit26mod.h" ++ ++int ++do_test (void) ++{ ++ /* Returning a large struct uses 'x8' as indirect result location. */ ++ struct large_struct r = tst_audit26_func (ARG1, ARG2, ARG3); ++ ++ struct large_struct e = set_large_struct (ARG1, ARG2, ARG3); ++ ++ TEST_COMPARE_BLOB (r.a, sizeof (r.a), e.a, sizeof (e.a)); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/aarch64/tst-audit26mod.c b/sysdeps/aarch64/tst-audit26mod.c +new file mode 100644 +index 0000000000000000..67d5ffce7288b34c +--- /dev/null ++++ b/sysdeps/aarch64/tst-audit26mod.c +@@ -0,0 +1,33 @@ ++/* Check LD_AUDIT for aarch64 ABI specifics. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include "tst-audit26mod.h" ++ ++struct large_struct ++tst_audit26_func (char a, short b, long int c) ++{ ++ if (a != ARG1) ++ abort (); ++ if (b != ARG2) ++ abort (); ++ if (c != ARG3) ++ abort (); ++ ++ return set_large_struct (a, b, c); ++} +diff --git a/sysdeps/aarch64/tst-audit26mod.h b/sysdeps/aarch64/tst-audit26mod.h +new file mode 100644 +index 0000000000000000..f80409f96bae6c82 +--- /dev/null ++++ b/sysdeps/aarch64/tst-audit26mod.h +@@ -0,0 +1,50 @@ ++/* Check LD_AUDIT for aarch64 specific ABI. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _TST_AUDIT27MOD_H ++#define _TST_AUDIT27MOD_H 1 ++ ++#include ++ ++struct large_struct ++{ ++ char a[16]; ++ short b[8]; ++ long int c[4]; ++}; ++ ++static inline struct large_struct ++set_large_struct (char a, short b, long int c) ++{ ++ struct large_struct r; ++ for (int i = 0; i < array_length (r.a); i++) ++ r.a[i] = a; ++ for (int i = 0; i < array_length (r.b); i++) ++ r.b[i] = b; ++ for (int i = 0; i < array_length (r.c); i++) ++ r.c[i] = c; ++ return r; ++} ++ ++#define ARG1 0x12 ++#define ARG2 0x1234 ++#define ARG3 0x12345678 ++ ++struct large_struct tst_audit26_func (char a, short b, long int c); ++ ++#endif +diff --git a/sysdeps/aarch64/tst-audit27.c b/sysdeps/aarch64/tst-audit27.c +new file mode 100644 +index 0000000000000000..5ebc09771f845af0 +--- /dev/null ++++ b/sysdeps/aarch64/tst-audit27.c +@@ -0,0 +1,64 @@ ++/* Check LD_AUDIT for aarch64 ABI specifics. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include "tst-audit27mod.h" ++ ++int ++do_test (void) ++{ ++ { ++ float r = tst_audit27_func_float (FUNC_FLOAT_ARG0, FUNC_FLOAT_ARG1, ++ FUNC_FLOAT_ARG2, FUNC_FLOAT_ARG3, ++ FUNC_FLOAT_ARG4, FUNC_FLOAT_ARG5, ++ FUNC_FLOAT_ARG6, FUNC_FLOAT_ARG7); ++ if (r != FUNC_FLOAT_RET) ++ FAIL_EXIT1 ("tst_audit27_func_float() returned %a, expected %a", ++ r, FUNC_FLOAT_RET); ++ } ++ ++ { ++ double r = tst_audit27_func_double (FUNC_DOUBLE_ARG0, FUNC_DOUBLE_ARG1, ++ FUNC_DOUBLE_ARG2, FUNC_DOUBLE_ARG3, ++ FUNC_DOUBLE_ARG4, FUNC_DOUBLE_ARG5, ++ FUNC_DOUBLE_ARG6, FUNC_DOUBLE_ARG7); ++ if (r != FUNC_DOUBLE_RET) ++ FAIL_EXIT1 ("tst_audit27_func_double() returned %la, expected %la", ++ r, FUNC_DOUBLE_RET); ++ } ++ ++ { ++ long double r = tst_audit27_func_ldouble (FUNC_LDOUBLE_ARG0, ++ FUNC_LDOUBLE_ARG1, ++ FUNC_LDOUBLE_ARG2, ++ FUNC_LDOUBLE_ARG3, ++ FUNC_LDOUBLE_ARG4, ++ FUNC_LDOUBLE_ARG5, ++ FUNC_LDOUBLE_ARG6, ++ FUNC_LDOUBLE_ARG7); ++ if (r != FUNC_LDOUBLE_RET) ++ FAIL_EXIT1 ("tst_audit27_func_ldouble() returned %La, expected %La", ++ r, FUNC_LDOUBLE_RET); ++ } ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/aarch64/tst-audit27mod.c b/sysdeps/aarch64/tst-audit27mod.c +new file mode 100644 +index 0000000000000000..922b518f0af4b97b +--- /dev/null ++++ b/sysdeps/aarch64/tst-audit27mod.c +@@ -0,0 +1,95 @@ ++/* Check LD_AUDIT for aarch64 ABI specifics. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include "tst-audit27mod.h" ++ ++float ++tst_audit27_func_float (float a0, float a1, float a2, float a3, float a4, ++ float a5, float a6, float a7) ++{ ++ if (a0 != FUNC_FLOAT_ARG0) ++ FAIL_EXIT1 ("a0: %a != %a", a0, FUNC_FLOAT_ARG0); ++ if (a1 != FUNC_FLOAT_ARG1) ++ FAIL_EXIT1 ("a1: %a != %a", a1, FUNC_FLOAT_ARG1); ++ if (a2 != FUNC_FLOAT_ARG2) ++ FAIL_EXIT1 ("a2: %a != %a", a2, FUNC_FLOAT_ARG2); ++ if (a3 != FUNC_FLOAT_ARG3) ++ FAIL_EXIT1 ("a3: %a != %a", a3, FUNC_FLOAT_ARG3); ++ if (a4 != FUNC_FLOAT_ARG4) ++ FAIL_EXIT1 ("a4: %a != %a", a4, FUNC_FLOAT_ARG4); ++ if (a5 != FUNC_FLOAT_ARG5) ++ FAIL_EXIT1 ("a5: %a != %a", a5, FUNC_FLOAT_ARG5); ++ if (a6 != FUNC_FLOAT_ARG6) ++ FAIL_EXIT1 ("a6: %a != %a", a6, FUNC_FLOAT_ARG6); ++ if (a7 != FUNC_FLOAT_ARG7) ++ FAIL_EXIT1 ("a7: %a != %a", a7, FUNC_FLOAT_ARG7); ++ ++ return FUNC_FLOAT_RET; ++} ++ ++double ++tst_audit27_func_double (double a0, double a1, double a2, double a3, double a4, ++ double a5, double a6, double a7) ++{ ++ if (a0 != FUNC_DOUBLE_ARG0) ++ FAIL_EXIT1 ("a0: %la != %la", a0, FUNC_DOUBLE_ARG0); ++ if (a1 != FUNC_DOUBLE_ARG1) ++ FAIL_EXIT1 ("a1: %la != %la", a1, FUNC_DOUBLE_ARG1); ++ if (a2 != FUNC_DOUBLE_ARG2) ++ FAIL_EXIT1 ("a2: %la != %la", a2, FUNC_DOUBLE_ARG2); ++ if (a3 != FUNC_DOUBLE_ARG3) ++ FAIL_EXIT1 ("a3: %la != %la", a3, FUNC_DOUBLE_ARG3); ++ if (a4 != FUNC_DOUBLE_ARG4) ++ FAIL_EXIT1 ("a4: %la != %la", a4, FUNC_DOUBLE_ARG4); ++ if (a5 != FUNC_DOUBLE_ARG5) ++ FAIL_EXIT1 ("a5: %la != %la", a5, FUNC_DOUBLE_ARG5); ++ if (a6 != FUNC_DOUBLE_ARG6) ++ FAIL_EXIT1 ("a6: %la != %la", a6, FUNC_DOUBLE_ARG6); ++ if (a7 != FUNC_DOUBLE_ARG7) ++ FAIL_EXIT1 ("a7: %la != %la", a7, FUNC_DOUBLE_ARG7); ++ ++ return FUNC_DOUBLE_RET; ++} ++ ++long double ++tst_audit27_func_ldouble (long double a0, long double a1, long double a2, ++ long double a3, long double a4, long double a5, ++ long double a6, long double a7) ++{ ++ if (a0 != FUNC_LDOUBLE_ARG0) ++ FAIL_EXIT1 ("a0: %La != %La", a0, FUNC_LDOUBLE_ARG0); ++ if (a1 != FUNC_LDOUBLE_ARG1) ++ FAIL_EXIT1 ("a1: %La != %La", a1, FUNC_LDOUBLE_ARG1); ++ if (a2 != FUNC_LDOUBLE_ARG2) ++ FAIL_EXIT1 ("a2: %La != %La", a2, FUNC_LDOUBLE_ARG2); ++ if (a3 != FUNC_LDOUBLE_ARG3) ++ FAIL_EXIT1 ("a3: %La != %La", a3, FUNC_LDOUBLE_ARG3); ++ if (a4 != FUNC_LDOUBLE_ARG4) ++ FAIL_EXIT1 ("a4: %La != %La", a4, FUNC_LDOUBLE_ARG4); ++ if (a5 != FUNC_LDOUBLE_ARG5) ++ FAIL_EXIT1 ("a5: %La != %La", a5, FUNC_LDOUBLE_ARG5); ++ if (a6 != FUNC_LDOUBLE_ARG6) ++ FAIL_EXIT1 ("a6: %La != %La", a6, FUNC_LDOUBLE_ARG6); ++ if (a7 != FUNC_LDOUBLE_ARG7) ++ FAIL_EXIT1 ("a7: %La != %La", a7, FUNC_LDOUBLE_ARG7); ++ ++ return FUNC_LDOUBLE_RET; ++} +diff --git a/sysdeps/aarch64/tst-audit27mod.h b/sysdeps/aarch64/tst-audit27mod.h +new file mode 100644 +index 0000000000000000..1709d222ca251e3b +--- /dev/null ++++ b/sysdeps/aarch64/tst-audit27mod.h +@@ -0,0 +1,67 @@ ++/* Check LD_AUDIT for aarch64 specific ABI. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _TST_AUDIT27MOD_H ++#define _TST_AUDIT27MOD_H 1 ++ ++#include ++ ++#define FUNC_FLOAT_ARG0 FLT_MIN ++#define FUNC_FLOAT_ARG1 FLT_MAX ++#define FUNC_FLOAT_ARG2 FLT_EPSILON ++#define FUNC_FLOAT_ARG3 FLT_TRUE_MIN ++#define FUNC_FLOAT_ARG4 0.0f ++#define FUNC_FLOAT_ARG5 1.0f ++#define FUNC_FLOAT_ARG6 2.0f ++#define FUNC_FLOAT_ARG7 3.0f ++#define FUNC_FLOAT_RET 4.0f ++ ++float ++tst_audit27_func_float (float a0, float a1, float a2, float a3, float a4, ++ float a5, float a6, float a7); ++ ++#define FUNC_DOUBLE_ARG0 DBL_MIN ++#define FUNC_DOUBLE_ARG1 DBL_MAX ++#define FUNC_DOUBLE_ARG2 DBL_EPSILON ++#define FUNC_DOUBLE_ARG3 DBL_TRUE_MIN ++#define FUNC_DOUBLE_ARG4 0.0 ++#define FUNC_DOUBLE_ARG5 1.0 ++#define FUNC_DOUBLE_ARG6 2.0 ++#define FUNC_DOUBLE_ARG7 3.0 ++#define FUNC_DOUBLE_RET 0x1.fffffe0000001p+127 ++ ++double ++tst_audit27_func_double (double a0, double a1, double a2, double a3, double a4, ++ double a5, double a6, double a7); ++ ++#define FUNC_LDOUBLE_ARG0 DBL_MAX + 1.0L ++#define FUNC_LDOUBLE_ARG1 DBL_MAX + 2.0L ++#define FUNC_LDOUBLE_ARG2 DBL_MAX + 3.0L ++#define FUNC_LDOUBLE_ARG3 DBL_MAX + 4.0L ++#define FUNC_LDOUBLE_ARG4 DBL_MAX + 5.0L ++#define FUNC_LDOUBLE_ARG5 DBL_MAX + 6.0L ++#define FUNC_LDOUBLE_ARG6 DBL_MAX + 7.0L ++#define FUNC_LDOUBLE_ARG7 DBL_MAX + 8.0L ++#define FUNC_LDOUBLE_RET 0x1.fffffffffffff000000000000001p+1023L ++ ++long double ++tst_audit27_func_ldouble (long double a0, long double a1, long double a2, ++ long double a3, long double a4, long double a5, ++ long double a6, long double a7); ++ ++#endif +diff --git a/sysdeps/aarch64/tst-auditmod26.c b/sysdeps/aarch64/tst-auditmod26.c +new file mode 100644 +index 0000000000000000..b03b6baed9aeb528 +--- /dev/null ++++ b/sysdeps/aarch64/tst-auditmod26.c +@@ -0,0 +1,103 @@ ++/* Check LD_AUDIT for aarch64 specific ABI. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "tst-audit26mod.h" ++ ++#define TEST_NAME "tst-audit26" ++ ++#define AUDIT26_COOKIE 0 ++ ++unsigned int ++la_version (unsigned int v) ++{ ++ return v; ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ const char *p = strrchr (map->l_name, '/'); ++ const char *l_name = p == NULL ? map->l_name : p + 1; ++ uintptr_t ck = -1; ++ if (strncmp (l_name, TEST_NAME, strlen (TEST_NAME)) == 0) ++ ck = AUDIT26_COOKIE; ++ *cookie = ck; ++ printf ("objopen: %ld, %s [cookie=%ld]\n", lmid, l_name, ck); ++ return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO; ++} ++ ++ElfW(Addr) ++la_aarch64_gnu_pltenter (ElfW(Sym) *sym __attribute__ ((unused)), ++ unsigned int ndx __attribute__ ((unused)), ++ uintptr_t *refcook, uintptr_t *defcook, ++ La_aarch64_regs *regs, unsigned int *flags, ++ const char *symname, long int *framesizep) ++{ ++ printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n", ++ symname, (long int) sym->st_value, ndx, *flags); ++ ++ if (strcmp (symname, "tst_audit26_func") == 0) ++ { ++ assert (regs->lr_xreg[0] == ARG1); ++ assert (regs->lr_xreg[1] == ARG2); ++ assert (regs->lr_xreg[2] == ARG3); ++ } ++ else ++ abort (); ++ ++ assert (regs->lr_vpcs == 0); ++ ++ /* Clobber 'x8'. */ ++ asm volatile ("mov x8, -1" : : : "x8"); ++ ++ *framesizep = 1024; ++ ++ return sym->st_value; ++} ++ ++unsigned int ++la_aarch64_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, ++ uintptr_t *defcook, ++ const struct La_aarch64_regs *inregs, ++ struct La_aarch64_retval *outregs, const char *symname) ++{ ++ printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u\n", ++ symname, (long int) sym->st_value, ndx); ++ ++ if (strcmp (symname, "tst_audit26_func") == 0) ++ { ++ assert (inregs->lr_xreg[0] == ARG1); ++ assert (inregs->lr_xreg[1] == ARG2); ++ assert (inregs->lr_xreg[2] == ARG3); ++ } ++ else ++ abort (); ++ ++ assert (inregs->lr_vpcs == 0); ++ assert (outregs->lrv_vpcs == 0); ++ ++ /* Clobber 'x8'. */ ++ asm volatile ("mov x8, -1" : : : "x8"); ++ ++ return 0; ++} +diff --git a/sysdeps/aarch64/tst-auditmod27.c b/sysdeps/aarch64/tst-auditmod27.c +new file mode 100644 +index 0000000000000000..21132c2985dab7b2 +--- /dev/null ++++ b/sysdeps/aarch64/tst-auditmod27.c +@@ -0,0 +1,180 @@ ++/* Check LD_AUDIT for aarch64 specific ABI. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tst-audit27mod.h" ++ ++#define TEST_NAME "tst-audit27" ++ ++#define AUDIT27_COOKIE 0 ++ ++unsigned int ++la_version (unsigned int v) ++{ ++ return v; ++} ++ ++unsigned int ++la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie) ++{ ++ const char *p = strrchr (map->l_name, '/'); ++ const char *l_name = p == NULL ? map->l_name : p + 1; ++ uintptr_t ck = -1; ++ if (strncmp (l_name, TEST_NAME, strlen (TEST_NAME)) == 0) ++ ck = AUDIT27_COOKIE; ++ *cookie = ck; ++ printf ("objopen: %ld, %s [%ld]\n", lmid, l_name, ck); ++ return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO; ++} ++ ++ElfW(Addr) ++la_aarch64_gnu_pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, ++ uintptr_t *defcook, La_aarch64_regs *regs, ++ unsigned int *flags, const char *symname, ++ long int *framesizep) ++{ ++ printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n", ++ symname, (long int) sym->st_value, ndx, *flags); ++ ++ if (strcmp (symname, "tst_audit27_func_float") == 0) ++ { ++ assert (regs->lr_vreg[0].s == FUNC_FLOAT_ARG0); ++ assert (regs->lr_vreg[1].s == FUNC_FLOAT_ARG1); ++ assert (regs->lr_vreg[2].s == FUNC_FLOAT_ARG2); ++ assert (regs->lr_vreg[3].s == FUNC_FLOAT_ARG3); ++ assert (regs->lr_vreg[4].s == FUNC_FLOAT_ARG4); ++ assert (regs->lr_vreg[5].s == FUNC_FLOAT_ARG5); ++ assert (regs->lr_vreg[6].s == FUNC_FLOAT_ARG6); ++ assert (regs->lr_vreg[7].s == FUNC_FLOAT_ARG7); ++ } ++ else if (strcmp (symname, "tst_audit27_func_double") == 0) ++ { ++ assert (regs->lr_vreg[0].d == FUNC_DOUBLE_ARG0); ++ assert (regs->lr_vreg[1].d == FUNC_DOUBLE_ARG1); ++ assert (regs->lr_vreg[2].d == FUNC_DOUBLE_ARG2); ++ assert (regs->lr_vreg[3].d == FUNC_DOUBLE_ARG3); ++ assert (regs->lr_vreg[4].d == FUNC_DOUBLE_ARG4); ++ assert (regs->lr_vreg[5].d == FUNC_DOUBLE_ARG5); ++ assert (regs->lr_vreg[6].d == FUNC_DOUBLE_ARG6); ++ assert (regs->lr_vreg[7].d == FUNC_DOUBLE_ARG7); ++ } ++ else if (strcmp (symname, "tst_audit27_func_ldouble") == 0) ++ { ++ assert (regs->lr_vreg[0].q == FUNC_LDOUBLE_ARG0); ++ assert (regs->lr_vreg[1].q == FUNC_LDOUBLE_ARG1); ++ assert (regs->lr_vreg[2].q == FUNC_LDOUBLE_ARG2); ++ assert (regs->lr_vreg[3].q == FUNC_LDOUBLE_ARG3); ++ assert (regs->lr_vreg[4].q == FUNC_LDOUBLE_ARG4); ++ assert (regs->lr_vreg[5].q == FUNC_LDOUBLE_ARG5); ++ assert (regs->lr_vreg[6].q == FUNC_LDOUBLE_ARG6); ++ assert (regs->lr_vreg[7].q == FUNC_LDOUBLE_ARG7); ++ } ++ else ++ abort (); ++ ++ assert (regs->lr_vpcs == 0); ++ ++ /* Clobber the q registers on exit. */ ++ uint8_t v = 0xff; ++ asm volatile ("dup v0.8b, %w0" : : "r" (v) : "v0"); ++ asm volatile ("dup v1.8b, %w0" : : "r" (v) : "v1"); ++ asm volatile ("dup v2.8b, %w0" : : "r" (v) : "v2"); ++ asm volatile ("dup v3.8b, %w0" : : "r" (v) : "v3"); ++ asm volatile ("dup v4.8b, %w0" : : "r" (v) : "v4"); ++ asm volatile ("dup v5.8b, %w0" : : "r" (v) : "v5"); ++ asm volatile ("dup v6.8b, %w0" : : "r" (v) : "v6"); ++ asm volatile ("dup v7.8b, %w0" : : "r" (v) : "v7"); ++ ++ *framesizep = 1024; ++ ++ return sym->st_value; ++} ++ ++unsigned int ++la_aarch64_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook, ++ uintptr_t *defcook, ++ const struct La_aarch64_regs *inregs, ++ struct La_aarch64_retval *outregs, ++ const char *symname) ++{ ++ printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u\n", ++ symname, (long int) sym->st_value, ndx); ++ ++ if (strcmp (symname, "tst_audit27_func_float") == 0) ++ { ++ assert (inregs->lr_vreg[0].s == FUNC_FLOAT_ARG0); ++ assert (inregs->lr_vreg[1].s == FUNC_FLOAT_ARG1); ++ assert (inregs->lr_vreg[2].s == FUNC_FLOAT_ARG2); ++ assert (inregs->lr_vreg[3].s == FUNC_FLOAT_ARG3); ++ assert (inregs->lr_vreg[4].s == FUNC_FLOAT_ARG4); ++ assert (inregs->lr_vreg[5].s == FUNC_FLOAT_ARG5); ++ assert (inregs->lr_vreg[6].s == FUNC_FLOAT_ARG6); ++ assert (inregs->lr_vreg[7].s == FUNC_FLOAT_ARG7); ++ ++ assert (outregs->lrv_vreg[0].s == FUNC_FLOAT_RET); ++ } ++ else if (strcmp (symname, "tst_audit27_func_double") == 0) ++ { ++ assert (inregs->lr_vreg[0].d == FUNC_DOUBLE_ARG0); ++ assert (inregs->lr_vreg[1].d == FUNC_DOUBLE_ARG1); ++ assert (inregs->lr_vreg[2].d == FUNC_DOUBLE_ARG2); ++ assert (inregs->lr_vreg[3].d == FUNC_DOUBLE_ARG3); ++ assert (inregs->lr_vreg[4].d == FUNC_DOUBLE_ARG4); ++ assert (inregs->lr_vreg[5].d == FUNC_DOUBLE_ARG5); ++ assert (inregs->lr_vreg[6].d == FUNC_DOUBLE_ARG6); ++ assert (inregs->lr_vreg[7].d == FUNC_DOUBLE_ARG7); ++ ++ assert (outregs->lrv_vreg[0].d == FUNC_DOUBLE_RET); ++ } ++ else if (strcmp (symname, "tst_audit27_func_ldouble") == 0) ++ { ++ assert (inregs->lr_vreg[0].q == FUNC_LDOUBLE_ARG0); ++ assert (inregs->lr_vreg[1].q == FUNC_LDOUBLE_ARG1); ++ assert (inregs->lr_vreg[2].q == FUNC_LDOUBLE_ARG2); ++ assert (inregs->lr_vreg[3].q == FUNC_LDOUBLE_ARG3); ++ assert (inregs->lr_vreg[4].q == FUNC_LDOUBLE_ARG4); ++ assert (inregs->lr_vreg[5].q == FUNC_LDOUBLE_ARG5); ++ assert (inregs->lr_vreg[6].q == FUNC_LDOUBLE_ARG6); ++ assert (inregs->lr_vreg[7].q == FUNC_LDOUBLE_ARG7); ++ ++ assert (outregs->lrv_vreg[0].q == FUNC_LDOUBLE_RET); ++ } ++ else ++ abort (); ++ ++ assert (inregs->lr_vpcs == 0); ++ assert (outregs->lrv_vpcs == 0); ++ ++ /* Clobber the q registers on exit. */ ++ uint8_t v = 0xff; ++ asm volatile ("dup v0.8b, %w0" : : "r" (v) : "v0"); ++ asm volatile ("dup v1.8b, %w0" : : "r" (v) : "v1"); ++ asm volatile ("dup v2.8b, %w0" : : "r" (v) : "v2"); ++ asm volatile ("dup v3.8b, %w0" : : "r" (v) : "v3"); ++ asm volatile ("dup v4.8b, %w0" : : "r" (v) : "v4"); ++ asm volatile ("dup v5.8b, %w0" : : "r" (v) : "v5"); ++ asm volatile ("dup v6.8b, %w0" : : "r" (v) : "v6"); ++ asm volatile ("dup v7.8b, %w0" : : "r" (v) : "v7"); ++ ++ return 0; ++} +diff --git a/sysdeps/generic/dl-audit-check.h b/sysdeps/generic/dl-audit-check.h +new file mode 100644 +index 0000000000000000..3ab76532868b5895 +--- /dev/null ++++ b/sysdeps/generic/dl-audit-check.h +@@ -0,0 +1,23 @@ ++/* rtld-audit version check. Generic version. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++static inline bool ++_dl_audit_check_version (unsigned int lav) ++{ ++ return lav <= LAV_CURRENT; ++} diff --git a/glibc-rh2047981-35.patch b/glibc-rh2047981-35.patch new file mode 100644 index 0000000..92ecdc6 --- /dev/null +++ b/glibc-rh2047981-35.patch @@ -0,0 +1,21 @@ +commit 80a08d0faa9b224019f895800c4d97de4e23e1aa +Author: Szabolcs Nagy +Date: Wed Feb 2 14:03:58 2022 +0000 + + Fix elf/tst-audit25a with default bind now toolchains + + This test relies on lazy binding for the executable so request that + explicitly in case the toolchain defaults to bind now. + +diff --git a/elf/Makefile b/elf/Makefile +index 78147ed2dbcaf4c0..4d16ed1637db8582 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -2130,6 +2130,7 @@ $(objpfx)tst-audit25a: $(objpfx)tst-audit25mod1.so \ + $(objpfx)tst-audit25mod2.so \ + $(objpfx)tst-audit25mod3.so \ + $(objpfx)tst-audit25mod4.so ++LDFLAGS-tst-audit25a = -Wl,-z,lazy + $(objpfx)tst-audit25mod1.so: $(objpfx)tst-audit25mod3.so + LDFLAGS-tst-audit25mod1.so = -Wl,-z,now + $(objpfx)tst-audit25mod2.so: $(objpfx)tst-audit25mod4.so diff --git a/glibc-rh2047981-36.patch b/glibc-rh2047981-36.patch new file mode 100644 index 0000000..ceaec72 --- /dev/null +++ b/glibc-rh2047981-36.patch @@ -0,0 +1,28 @@ +commit fa7ad1df1915c8a62f50e3a5b7e10f9c7118cd7f +Author: H.J. Lu +Date: Sun Feb 6 11:12:24 2022 -0800 + + elf: Replace tst-audit24bmod2.so with tst-audit24bmod2 + + Replace tst-audit24bmod2.so with tst-audit24bmod2 to silence: + + make[2]: Entering directory '/export/gnu/import/git/gitlab/x86-glibc/elf' + Makefile:2201: warning: overriding recipe for target '/export/build/gnu/tools-build/glibc-gitlab/build-x86_64-linux/elf/tst-audit24bmod2.so' + ../Makerules:765: warning: ignoring old recipe for target '/export/build/gnu/tools-build/glibc-gitlab/build-x86_64-linux/elf/tst-audit24bmod2.so' + +Conflicts: + elf/Makefile + +diff --git a/elf/Makefile b/elf/Makefile +index 4d16ed1637db8582..73d347339762fc9e 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -855,7 +855,7 @@ extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) + + # filtmod1.so has a special rule + modules-names-nobuild := filtmod1 \ +- tst-audit24bmod1 tst-audit24bmod2.so ++ tst-audit24bmod1 tst-audit24bmod2 + + tests += $(tests-static) + diff --git a/glibc-rh2047981-37.patch b/glibc-rh2047981-37.patch new file mode 100644 index 0000000..8591468 --- /dev/null +++ b/glibc-rh2047981-37.patch @@ -0,0 +1,112 @@ +commit 9e94f57484a2aba0fe67ea2059b5843f651887c2 +Author: Adhemerval Zanella +Date: Fri Feb 4 15:54:59 2022 -0300 + + hppa: Fix bind-now audit (BZ #28857) + + On hppa, a function pointer returned by la_symbind is actually a function + descriptor has the plabel bit set (bit 30). This must be cleared to get + the actual address of the descriptor. If the descriptor has been bound, + the first word of the descriptor is the physical address of theA function, + otherwise, the first word of the descriptor points to a trampoline in the + PLT. + + This patch also adds a workaround on tests because on hppa (and it seems + to be the only ABI I have see it), some shared library adds a dynamic PLT + relocation to am empty symbol name: + + $ readelf -r elf/tst-audit25mod1.so + [...] + Relocation section '.rela.plt' at offset 0x464 contains 6 entries: + Offset Info Type Sym.Value Sym. Name + Addend + 00002008 00000081 R_PARISC_IPLT 508 + [...] + + It breaks some assumptions on the test, where a symbol with an empty + name ("") is passed on la_symbind. + + Checked on x86_64-linux-gnu and hppa-linux-gnu. + +diff --git a/elf/Makefile b/elf/Makefile +index 73d347339762fc9e..6d39b400060a73f3 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -2113,7 +2113,7 @@ $(objpfx)tst-audit24c.out: $(objpfx)tst-auditmod24c.so + $(objpfx)tst-audit24c: $(objpfx)tst-audit24amod1.so \ + $(objpfx)tst-audit24amod2.so + tst-audit24c-ENV = LD_BIND_NOW=1 LD_AUDIT=$(objpfx)tst-auditmod24c.so +-LDFLAGS-tst-audit24b = -Wl,-z,lazy ++LDFLAGS-tst-audit24c = -Wl,-z,lazy + + $(objpfx)tst-audit24d.out: $(objpfx)tst-auditmod24d.so + $(objpfx)tst-audit24d: $(objpfx)tst-audit24dmod1.so \ +diff --git a/elf/dl-audit.c b/elf/dl-audit.c +index 72a50717ef60a357..ec9b032eae37c103 100644 +--- a/elf/dl-audit.c ++++ b/elf/dl-audit.c +@@ -257,7 +257,8 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result, + reloc_result->flags = flags; + } + +- DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value); ++ if (flags & LA_SYMB_ALTVALUE) ++ DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value); + } + + void +diff --git a/elf/tst-auditmod24a.c b/elf/tst-auditmod24a.c +index d8e88f3984af1707..3075dfae2fd3d288 100644 +--- a/elf/tst-auditmod24a.c ++++ b/elf/tst-auditmod24a.c +@@ -110,5 +110,7 @@ la_symbind32 (Elf32_Sym *sym, unsigned int ndx, + return sym->st_value; + } + +- abort (); ++ if (symname[0] != '\0') ++ abort (); ++ return sym->st_value; + } +diff --git a/elf/tst-auditmod24d.c b/elf/tst-auditmod24d.c +index 8c803ecc0a48f21b..badc6be451ee0357 100644 +--- a/elf/tst-auditmod24d.c ++++ b/elf/tst-auditmod24d.c +@@ -116,5 +116,7 @@ la_symbind32 (Elf32_Sym *sym, unsigned int ndx, + } + } + +- abort (); ++ if (symname[0] != '\0') ++ abort (); ++ return sym->st_value; + } +diff --git a/elf/tst-auditmod25.c b/elf/tst-auditmod25.c +index 526f5c54bc2c3b8c..20640a8daf346b5f 100644 +--- a/elf/tst-auditmod25.c ++++ b/elf/tst-auditmod25.c +@@ -72,7 +72,7 @@ la_symbind32 (Elf32_Sym *sym, unsigned int ndx, + unsigned int *flags, const char *symname) + #endif + { +- if (*refcook != -1 && *defcook != -1) ++ if (*refcook != -1 && *defcook != -1 && symname[0] != '\0') + fprintf (stderr, "la_symbind: %s %u\n", symname, + *flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) ? 1 : 0); + return sym->st_value; +diff --git a/sysdeps/hppa/dl-lookupcfg.h b/sysdeps/hppa/dl-lookupcfg.h +index c3fea1fe5776b17a..86f6a04af46c87ba 100644 +--- a/sysdeps/hppa/dl-lookupcfg.h ++++ b/sysdeps/hppa/dl-lookupcfg.h +@@ -79,7 +79,9 @@ void attribute_hidden _dl_unmap (struct link_map *map); + /* Extract the code address from a fixup value */ + #define DL_FIXUP_VALUE_CODE_ADDR(value) ((value).ip) + #define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value)) +-#define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr)) ++/* Clear the plabel bit to get the actual address of the descriptor. */ ++#define DL_FIXUP_ADDR_VALUE(addr) \ ++ (*(DL_FIXUP_VALUE_TYPE *) ((uintptr_t) (addr) & ~2)) + #define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr) +-#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ +- (*value) = *(struct fdesc *) (st_value) ++#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \ ++ *(value) = *(DL_FIXUP_VALUE_TYPE *) ((uintptr_t) (new_value) & ~2) diff --git a/glibc-rh2047981-38.patch b/glibc-rh2047981-38.patch new file mode 100644 index 0000000..5e7b79f --- /dev/null +++ b/glibc-rh2047981-38.patch @@ -0,0 +1,44 @@ +commit bc02f1fa2fb302eb8a486794c6b7e4811229b81e +Author: Adhemerval Zanella +Date: Fri Mar 25 08:53:42 2022 -0300 + + elf: Remove unused functions from tst-audit25(a,b) + +diff --git a/elf/tst-audit25a.c b/elf/tst-audit25a.c +index 49173e862516e876..c2cff8541b3741c3 100644 +--- a/elf/tst-audit25a.c ++++ b/elf/tst-audit25a.c +@@ -49,14 +49,6 @@ handle_restart (void) + return 0; + } + +-static inline bool +-startswith (const char *str, const char *pre) +-{ +- size_t lenpre = strlen (pre); +- size_t lenstr = strlen (str); +- return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0; +-} +- + static int + do_test (int argc, char *argv[]) + { +diff --git a/elf/tst-audit25b.c b/elf/tst-audit25b.c +index a56638d501f9bff5..46391770fdfc1796 100644 +--- a/elf/tst-audit25b.c ++++ b/elf/tst-audit25b.c +@@ -48,14 +48,6 @@ handle_restart (void) + return 0; + } + +-static inline bool +-startswith (const char *str, const char *pre) +-{ +- size_t lenpre = strlen (pre); +- size_t lenstr = strlen (str); +- return lenstr >= lenpre && memcmp (pre, str, lenpre) == 0; +-} +- + static int + do_test (int argc, char *argv[]) + { diff --git a/glibc-rh2047981-39.patch b/glibc-rh2047981-39.patch new file mode 100644 index 0000000..36247b1 --- /dev/null +++ b/glibc-rh2047981-39.patch @@ -0,0 +1,42 @@ +commit 5325233313c66aea13e86f5dd59618e9dd74b510 +Author: Stefan Liebler +Date: Thu Apr 7 13:59:48 2022 +0200 + + S390: Fix elf/tst-audit25[ab] + + If glibc is configured with --disable-default-pie and build on + s390 with -O3, the tests elf/tst-audit25a and elf/tst-audit25b are + failing as there are additional la_symbind lines for free and malloc. + It turns out that those belong to the executable. In fact those are + the PLT-stubs. Furthermore la_symbind is also called for calloc and + realloc symbols, but those belong to libc. + + Those functions are not called at all, but dlsym'ed in + elf/dl-minimal.c: + __rtld_malloc_init_real (struct link_map *main_map) + { + ... + void *new_calloc = lookup_malloc_symbol (main_map, "calloc", &version); + void *new_free = lookup_malloc_symbol (main_map, "free", &version); + void *new_malloc = lookup_malloc_symbol (main_map, "malloc", &version); + void *new_realloc = lookup_malloc_symbol (main_map, "realloc", &version); + ... + } + + Therefore, this commit just ignored symbols with LA_SYMB_DLSYM flag. + Reviewed-by: Adheemrval Zanella + +diff --git a/elf/tst-auditmod25.c b/elf/tst-auditmod25.c +index 20640a8daf346b5f..0524c5aab17fabba 100644 +--- a/elf/tst-auditmod25.c ++++ b/elf/tst-auditmod25.c +@@ -72,7 +72,8 @@ la_symbind32 (Elf32_Sym *sym, unsigned int ndx, + unsigned int *flags, const char *symname) + #endif + { +- if (*refcook != -1 && *defcook != -1 && symname[0] != '\0') ++ if (*refcook != -1 && *defcook != -1 && symname[0] != '\0' ++ && (*flags & LA_SYMB_DLSYM) == 0) + fprintf (stderr, "la_symbind: %s %u\n", symname, + *flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) ? 1 : 0); + return sym->st_value; diff --git a/glibc-rh2047981-4.patch b/glibc-rh2047981-4.patch new file mode 100644 index 0000000..86468bd --- /dev/null +++ b/glibc-rh2047981-4.patch @@ -0,0 +1,34 @@ +commit 3ad5dab476205d6e16156cf0511fa6884b3b0fc4 +Author: Florian Weimer +Date: Tue Jul 7 09:58:45 2020 +0200 + + elf: Do not signal LA_ACT_CONSISTENT for an empty namespace [BZ #26076] + + The auditing interface identifies namespaces by their first loaded + module. Once the namespace is empty, it is no longer possible to signal + LA_ACT_CONSISTENT for it because the first loaded module is already gone + at that point. + + Reviewed-by: Carlos O'Donell + +diff --git a/elf/dl-close.c b/elf/dl-close.c +index 7fe91bdd9aaf694e..698bda929c0eab6c 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -795,8 +795,14 @@ _dl_close_worker (struct link_map *map, bool force) + if (__glibc_unlikely (do_audit)) + { + struct link_map *head = ns->_ns_loaded; +- /* Do not call the functions for any auditing object. */ +- if (head->l_auditing == 0) ++ /* If head is NULL, the namespace has become empty, and the ++ audit interface does not give us a way to signal ++ LA_ACT_CONSISTENT for it because the first loaded module is ++ used to identify the namespace. ++ ++ Furthermore, do not notify auditors of the cleanup of a ++ failed audit module loading attempt. */ ++ if (head != NULL && head->l_auditing == 0) + { + struct audit_ifaces *afct = GLRO(dl_audit); + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt) diff --git a/glibc-rh2047981-40.patch b/glibc-rh2047981-40.patch new file mode 100644 index 0000000..f1f4e80 --- /dev/null +++ b/glibc-rh2047981-40.patch @@ -0,0 +1,170 @@ +commit e4a2fb76efb45210c541ee3f8ef32f317783c3a8 +Author: Florian Weimer +Date: Wed May 11 20:30:49 2022 +0200 + + manual: Document the dlinfo function + + Reviewed-by: Carlos O'Donell + Tested-by: Carlos O'Donell + (cherry picked from commit 93804a1ee084d4bdc620b2b9f91615c7da0fabe1) + + Also includes partial backport of commit 5d28a8962dcb6ec056b81d730e + (the addition of manual/dynlink.texi). + +diff --git a/manual/Makefile b/manual/Makefile +index c2756640a785afe1..4c835e568f3bab67 100644 +--- a/manual/Makefile ++++ b/manual/Makefile +@@ -39,7 +39,7 @@ chapters = $(addsuffix .texi, \ + pipe socket terminal syslog math arith time \ + resource setjmp signal startup process ipc job \ + nss users sysinfo conf crypt debug threads \ +- probes tunables) ++ dynlink probes tunables) + appendices = lang.texi header.texi install.texi maint.texi platform.texi \ + contrib.texi + licenses = freemanuals.texi lgpl-2.1.texi fdl-1.3.texi +diff --git a/manual/dynlink.texi b/manual/dynlink.texi +new file mode 100644 +index 0000000000000000..dbf3de11769d8e57 +--- /dev/null ++++ b/manual/dynlink.texi +@@ -0,0 +1,100 @@ ++@node Dynamic Linker ++@c @node Dynamic Linker, Internal Probes, Threads, Top ++@c %MENU% Loading programs and shared objects. ++@chapter Dynamic Linker ++@cindex dynamic linker ++@cindex dynamic loader ++ ++The @dfn{dynamic linker} is responsible for loading dynamically linked ++programs and their dependencies (in the form of shared objects). The ++dynamic linker in @theglibc{} also supports loading shared objects (such ++as plugins) later at run time. ++ ++Dynamic linkers are sometimes called @dfn{dynamic loaders}. ++ ++@menu ++* Dynamic Linker Introspection:: Interfaces for querying mapping information. ++@end menu ++ ++@node Dynamic Linker Introspection ++@section Dynamic Linker Introspection ++ ++@Theglibc{} provides various functions for querying information from the ++dynamic linker. ++ ++@deftypefun {int} dlinfo (void *@var{handle}, int @var{request}, void *@var{arg}) ++@safety{@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}} ++@standards{GNU, dlfcn.h} ++This function returns information about @var{handle} in the memory ++location @var{arg}, based on @var{request}. The @var{handle} argument ++must be a pointer returned by @code{dlopen} or @code{dlmopen}; it must ++not have been closed by @code{dlclose}. ++ ++On success, @code{dlinfo} returns 0. If there is an error, the function ++returns @math{-1}, and @code{dlerror} can be used to obtain a ++corresponding error message. ++ ++The following operations are defined for use with @var{request}: ++ ++@vtable @code ++@item RTLD_DI_LINKMAP ++The corresponding @code{struct link_map} pointer for @var{handle} is ++written to @code{*@var{arg}}. The @var{arg} argument must be the ++address of an object of type @code{struct link_map *}. ++ ++@item RTLD_DI_LMID ++The namespace identifier of @var{handle} is written to ++@code{*@var{arg}}. The @var{arg} argument must be the address of an ++object of type @code{Lmid_t}. ++ ++@item RTLD_DI_ORIGIN ++The value of the @code{$ORIGIN} dynamic string token for @var{handle} is ++written to the character array starting at @var{arg} as a ++null-terminated string. ++ ++This request type should not be used because it is prone to buffer ++overflows. ++ ++@item RTLD_DI_SERINFO ++@itemx RTLD_DI_SERINFOSIZE ++These requests can be used to obtain search path information for ++@var{handle}. For both requests, @var{arg} must point to a ++@code{Dl_serinfo} object. The @code{RTLD_DI_SERINFOSIZE} request must ++be made first; it updates the @code{dls_size} and @code{dls_cnt} members ++of the @code{Dl_serinfo} object. The caller should then allocate memory ++to store at least @code{dls_size} bytes and pass that buffer to a ++@code{RTLD_DI_SERINFO} request. This second request fills the ++@code{dls_serpath} array. The number of array elements was returned in ++the @code{dls_cnt} member in the initial @code{RTLD_DI_SERINFOSIZE} ++request. The caller is responsible for freeing the allocated buffer. ++ ++This interface is prone to buffer overflows in multi-threaded processes ++because the required size can change between the ++@code{RTLD_DI_SERINFOSIZE} and @code{RTLD_DI_SERINFO} requests. ++ ++@item RTLD_DI_TLS_DATA ++This request writes the address of the TLS block (in the current thread) ++for the shared object identified by @var{handle} to @code{*@var{arg}}. ++The argument @var{arg} must be the address of an object of type ++@code{void *}. A null pointer is written if the object does not have ++any associated TLS block. ++ ++@item RTLD_DI_TLS_MODID ++This request writes the TLS module ID for the shared object @var{handle} ++to @code{*@var{arg}}. The argument @var{arg} must be the address of an ++object of type @code{size_t}. The module ID is zero if the object ++does not have an associated TLS block. ++@end vtable ++ ++The @code{dlinfo} function is a GNU extension. ++@end deftypefun ++ ++@c FIXME these are undocumented: ++@c dladdr ++@c dladdr1 ++@c dlclose ++@c dlerror ++@c dlmopen ++@c dlopen ++@c dlsym ++@c dlvsym +diff --git a/manual/libdl.texi b/manual/libdl.texi +deleted file mode 100644 +index e3fe0452d9f41d47..0000000000000000 +--- a/manual/libdl.texi ++++ /dev/null +@@ -1,10 +0,0 @@ +-@c FIXME these are undocumented: +-@c dladdr +-@c dladdr1 +-@c dlclose +-@c dlerror +-@c dlinfo +-@c dlmopen +-@c dlopen +-@c dlsym +-@c dlvsym +diff --git a/manual/probes.texi b/manual/probes.texi +index 0ea560ed78bcfd7e..892d2451938eb379 100644 +--- a/manual/probes.texi ++++ b/manual/probes.texi +@@ -1,5 +1,5 @@ + @node Internal Probes +-@c @node Internal Probes, Tunables, Threads, Top ++@c @node Internal Probes, Tunables, Dynamic Linker, Top + @c %MENU% Probes to monitor libc internal behavior + @chapter Internal probes + +diff --git a/manual/threads.texi b/manual/threads.texi +index 87fda7d8e716e08c..1c26c57540746e3b 100644 +--- a/manual/threads.texi ++++ b/manual/threads.texi +@@ -1,5 +1,5 @@ + @node Threads +-@c @node Threads, Internal Probes, Debugging Support, Top ++@c @node Threads, Dynamic Linker, Debugging Support, Top + @c %MENU% Functions, constants, and data types for working with threads + @chapter Threads + @cindex threads diff --git a/glibc-rh2047981-41.patch b/glibc-rh2047981-41.patch new file mode 100644 index 0000000..a92e82d --- /dev/null +++ b/glibc-rh2047981-41.patch @@ -0,0 +1,268 @@ +Added $(objpfx)tst-dlinfo-phdr: $(libdl) to dlfcn/Makefile since +we still need $(libdl) in RHEL8. + +commit d056c212130280c0a54d9a4f72170ec621b70ce5 +Author: Florian Weimer +Date: Fri Apr 29 17:00:53 2022 +0200 + + dlfcn: Implement the RTLD_DI_PHDR request type for dlinfo + + The information is theoretically available via dl_iterate_phdr as + well, but that approach is very slow if there are many shared + objects. + + Reviewed-by: Carlos O'Donell + Tested-by: Carlos O'Donell + +Conflicts: + dlfcn/dlinfo.c + (missing move into libc) + +diff --git a/dlfcn/Makefile b/dlfcn/Makefile +index 0b213b7d9fefcdc9..65cee5b54d891a24 100644 +--- a/dlfcn/Makefile ++++ b/dlfcn/Makefile +@@ -59,6 +59,10 @@ tststatic3-ENV = $(tststatic-ENV) + tststatic4-ENV = $(tststatic-ENV) + tststatic5-ENV = $(tststatic-ENV) + ++tests-internal += \ ++ tst-dlinfo-phdr \ ++ # tests-internal ++ + ifneq (,$(CXX)) + modules-names += bug-atexit3-lib + else +@@ -152,3 +156,5 @@ $(objpfx)bug-dl-leaf-lib-cb.so: $(objpfx)bug-dl-leaf-lib.so + + $(objpfx)tst-rec-dlopen: $(libdl) + $(objpfx)tst-rec-dlopen.out: $(objpfx)moddummy1.so $(objpfx)moddummy2.so ++ ++$(objpfx)tst-dlinfo-phdr: $(libdl) +diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h +index 0921fd724cf7b785..61c4f59bea4eb7ac 100644 +--- a/dlfcn/dlfcn.h ++++ b/dlfcn/dlfcn.h +@@ -162,7 +162,12 @@ enum + segment, or if the calling thread has not allocated a block for it. */ + RTLD_DI_TLS_DATA = 10, + +- RTLD_DI_MAX = 10 ++ /* Treat ARG as const ElfW(Phdr) **, and store the address of the ++ program header array at that location. The dlinfo call returns ++ the number of program headers in the array. */ ++ RTLD_DI_PHDR = 11, ++ ++ RTLD_DI_MAX = 11 + }; + + +diff --git a/dlfcn/dlinfo.c b/dlfcn/dlinfo.c +index 23ef3f57ca41afdf..50cd9af17a56f990 100644 +--- a/dlfcn/dlinfo.c ++++ b/dlfcn/dlinfo.c +@@ -38,6 +38,10 @@ struct dlinfo_args + void *handle; + int request; + void *arg; ++ ++ /* This is the value that is returned from dlinfo if no error is ++ signaled. */ ++ int result; + }; + + static void +@@ -50,6 +54,7 @@ dlinfo_doit (void *argsblock) + { + case RTLD_DI_CONFIGADDR: + default: ++ args->result = -1; + _dl_signal_error (0, NULL, NULL, N_("unsupported dlinfo request")); + break; + +@@ -85,6 +90,11 @@ dlinfo_doit (void *argsblock) + *(void **) args->arg = data; + break; + } ++ ++ case RTLD_DI_PHDR: ++ *(const ElfW(Phdr) **) args->arg = l->l_phdr; ++ args->result = l->l_phnum; ++ break; + } + } + +@@ -97,7 +107,8 @@ __dlinfo (void *handle, int request, void *arg) + # endif + + struct dlinfo_args args = { handle, request, arg }; +- return _dlerror_run (&dlinfo_doit, &args) ? -1 : 0; ++ _dlerror_run (&dlinfo_doit, &args); ++ return args.result; + } + # ifdef SHARED + strong_alias (__dlinfo, dlinfo) +diff --git a/dlfcn/tst-dlinfo-phdr.c b/dlfcn/tst-dlinfo-phdr.c +new file mode 100644 +index 0000000000000000..a15a7d48ebd3b976 +--- /dev/null ++++ b/dlfcn/tst-dlinfo-phdr.c +@@ -0,0 +1,125 @@ ++/* Test for dlinfo (RTLD_DI_PHDR). ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++/* Used to verify that the program header array appears as expected ++ among the dl_iterate_phdr callback invocations. */ ++ ++struct dlip_callback_args ++{ ++ struct link_map *l; /* l->l_addr is used to find the object. */ ++ const ElfW(Phdr) *phdr; /* Expected program header pointed. */ ++ int phnum; /* Expected program header count. */ ++ bool found; /* True if l->l_addr has been found. */ ++}; ++ ++static int ++dlip_callback (struct dl_phdr_info *dlpi, size_t size, void *closure) ++{ ++ TEST_COMPARE (sizeof (*dlpi), size); ++ struct dlip_callback_args *args = closure; ++ ++ if (dlpi->dlpi_addr == args->l->l_addr) ++ { ++ TEST_VERIFY (!args->found); ++ args->found = true; ++ TEST_VERIFY (args->phdr == dlpi->dlpi_phdr); ++ TEST_COMPARE (args->phnum, dlpi->dlpi_phnum); ++ } ++ ++ return 0; ++} ++ ++static int ++do_test (void) ++{ ++ /* Avoid a copy relocation. */ ++ struct r_debug *debug = xdlsym (RTLD_DEFAULT, "_r_debug"); ++ struct link_map *l = (struct link_map *) debug->r_map; ++ TEST_VERIFY_EXIT (l != NULL); ++ ++ do ++ { ++ printf ("info: checking link map %p (%p) for \"%s\"\n", ++ l, l->l_phdr, l->l_name); ++ ++ /* Cause dlerror () to return an error message. */ ++ dlsym (RTLD_DEFAULT, "does-not-exist"); ++ ++ /* Use the extension that link maps are valid dlopen handles. */ ++ const ElfW(Phdr) *phdr; ++ int phnum = dlinfo (l, RTLD_DI_PHDR, &phdr); ++ TEST_VERIFY (phnum >= 0); ++ /* Verify that the error message has been cleared. */ ++ TEST_COMPARE_STRING (dlerror (), NULL); ++ ++ TEST_VERIFY (phdr == l->l_phdr); ++ TEST_COMPARE (phnum, l->l_phnum); ++ ++ /* Check that we can find PT_DYNAMIC among the array. */ ++ { ++ bool dynamic_found = false; ++ for (int i = 0; i < phnum; ++i) ++ if (phdr[i].p_type == PT_DYNAMIC) ++ { ++ dynamic_found = true; ++ TEST_COMPARE ((ElfW(Addr)) l->l_ld, l->l_addr + phdr[i].p_vaddr); ++ } ++ TEST_VERIFY (dynamic_found); ++ } ++ ++ /* Check that dl_iterate_phdr finds the link map with the same ++ program headers. */ ++ { ++ struct dlip_callback_args args = ++ { ++ .l = l, ++ .phdr = phdr, ++ .phnum = phnum, ++ .found = false, ++ }; ++ TEST_COMPARE (dl_iterate_phdr (dlip_callback, &args), 0); ++ TEST_VERIFY (args.found); ++ } ++ ++ if (l->l_prev == NULL) ++ { ++ /* This is the executable, so the information is also ++ available via getauxval. */ ++ TEST_COMPARE_STRING (l->l_name, ""); ++ TEST_VERIFY (phdr == (const ElfW(Phdr) *) getauxval (AT_PHDR)); ++ TEST_COMPARE (phnum, getauxval (AT_PHNUM)); ++ } ++ ++ l = l->l_next; ++ } ++ while (l != NULL); ++ ++ return 0; ++} ++ ++#include +diff --git a/manual/dynlink.texi b/manual/dynlink.texi +index dbf3de11769d8e57..7dcac64889e389fd 100644 +--- a/manual/dynlink.texi ++++ b/manual/dynlink.texi +@@ -30,9 +30,9 @@ location @var{arg}, based on @var{request}. The @var{handle} argument + must be a pointer returned by @code{dlopen} or @code{dlmopen}; it must + not have been closed by @code{dlclose}. + +-On success, @code{dlinfo} returns 0. If there is an error, the function +-returns @math{-1}, and @code{dlerror} can be used to obtain a +-corresponding error message. ++On success, @code{dlinfo} returns 0 for most request types; exceptions ++are noted below. If there is an error, the function returns @math{-1}, ++and @code{dlerror} can be used to obtain a corresponding error message. + + The following operations are defined for use with @var{request}: + +@@ -84,6 +84,15 @@ This request writes the TLS module ID for the shared object @var{handle} + to @code{*@var{arg}}. The argument @var{arg} must be the address of an + object of type @code{size_t}. The module ID is zero if the object + does not have an associated TLS block. ++ ++@item RTLD_DI_PHDR ++This request writes the address of the program header array to ++@code{*@var{arg}}. The argument @var{arg} must be the address of an ++object of type @code{const ElfW(Phdr) *} (that is, ++@code{const Elf32_Phdr *} or @code{const Elf64_Phdr *}, as appropriate ++for the current architecture). For this request, the value returned by ++@code{dlinfo} is the number of program headers in the program header ++array. + @end vtable + + The @code{dlinfo} function is a GNU extension. diff --git a/glibc-rh2047981-42.patch b/glibc-rh2047981-42.patch new file mode 100644 index 0000000..d280e1a --- /dev/null +++ b/glibc-rh2047981-42.patch @@ -0,0 +1,296 @@ +commit ad43cac44a6860eaefcadadfb2acb349921e96bf +Author: Szabolcs Nagy +Date: Fri Jun 15 16:14:58 2018 +0100 + + rtld: Use generic argv adjustment in ld.so [BZ #23293] + + When an executable is invoked as + + ./ld.so [ld.so-args] ./exe [exe-args] + + then the argv is adujusted in ld.so before calling the entry point of + the executable so ld.so args are not visible to it. On most targets + this requires moving argv, env and auxv on the stack to ensure correct + stack alignment at the entry point. This had several issues: + + - The code for this adjustment on the stack is written in asm as part + of the target specific ld.so _start code which is hard to maintain. + + - The adjustment is done after _dl_start returns, where it's too late + to update GLRO(dl_auxv), as it is already readonly, so it points to + memory that was clobbered by the adjustment. This is bug 23293. + + - _environ is also wrong in ld.so after the adjustment, but it is + likely not used after _dl_start returns so this is not user visible. + + - _dl_argv was updated, but for this it was moved out of relro, which + changes security properties across targets unnecessarily. + + This patch introduces a generic _dl_start_args_adjust function that + handles the argument adjustments after ld.so processed its own args + and before relro protection is applied. + + The same algorithm is used on all targets, _dl_skip_args is now 0, so + existing target specific adjustment code is no longer used. The bug + affects aarch64, alpha, arc, arm, csky, ia64, nios2, s390-32 and sparc, + other targets don't need the change in principle, only for consistency. + + The GNU Hurd start code relied on _dl_skip_args after dl_main returned, + now it checks directly if args were adjusted and fixes the Hurd startup + data accordingly. + + Follow up patches can remove _dl_skip_args and DL_ARGV_NOT_RELRO. + + Tested on aarch64-linux-gnu and cross tested on i686-gnu. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/rtld.c b/elf/rtld.c +index aee5ca357f66121e..22cceeab40319582 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -1127,6 +1127,62 @@ rtld_chain_load (struct link_map *main_map, char *argv0) + rtld_soname, pathname, errcode); + } + ++/* Adjusts the contents of the stack and related globals for the user ++ entry point. The ld.so processed skip_args arguments and bumped ++ _dl_argv and _dl_argc accordingly. Those arguments are removed from ++ argv here. */ ++static void ++_dl_start_args_adjust (int skip_args) ++{ ++ void **sp = (void **) (_dl_argv - skip_args - 1); ++ void **p = sp + skip_args; ++ ++ if (skip_args == 0) ++ return; ++ ++ /* Sanity check. */ ++ intptr_t argc = (intptr_t) sp[0] - skip_args; ++ assert (argc == _dl_argc); ++ ++ /* Adjust argc on stack. */ ++ sp[0] = (void *) (intptr_t) _dl_argc; ++ ++ /* Update globals in rtld. */ ++ _dl_argv -= skip_args; ++ _environ -= skip_args; ++ ++ /* Shuffle argv down. */ ++ do ++ *++sp = *++p; ++ while (*p != NULL); ++ ++ assert (_environ == (char **) (sp + 1)); ++ ++ /* Shuffle envp down. */ ++ do ++ *++sp = *++p; ++ while (*p != NULL); ++ ++#ifdef HAVE_AUX_VECTOR ++ void **auxv = (void **) GLRO(dl_auxv) - skip_args; ++ GLRO(dl_auxv) = (ElfW(auxv_t) *) auxv; /* Aliasing violation. */ ++ assert (auxv == sp + 1); ++ ++ /* Shuffle auxv down. */ ++ ElfW(auxv_t) ax; ++ char *oldp = (char *) (p + 1); ++ char *newp = (char *) (sp + 1); ++ do ++ { ++ memcpy (&ax, oldp, sizeof (ax)); ++ memcpy (newp, &ax, sizeof (ax)); ++ oldp += sizeof (ax); ++ newp += sizeof (ax); ++ } ++ while (ax.a_type != AT_NULL); ++#endif ++} ++ + static void + dl_main (const ElfW(Phdr) *phdr, + ElfW(Word) phnum, +@@ -1185,6 +1241,7 @@ dl_main (const ElfW(Phdr) *phdr, + rtld_is_main = true; + + char *argv0 = NULL; ++ char **orig_argv = _dl_argv; + + /* Note the place where the dynamic linker actually came from. */ + GL(dl_rtld_map).l_name = rtld_progname; +@@ -1199,7 +1256,6 @@ dl_main (const ElfW(Phdr) *phdr, + GLRO(dl_lazy) = -1; + } + +- ++_dl_skip_args; + --_dl_argc; + ++_dl_argv; + } +@@ -1208,14 +1264,12 @@ dl_main (const ElfW(Phdr) *phdr, + if (state.mode != rtld_mode_help) + state.mode = rtld_mode_verify; + +- ++_dl_skip_args; + --_dl_argc; + ++_dl_argv; + } + else if (! strcmp (_dl_argv[1], "--inhibit-cache")) + { + GLRO(dl_inhibit_cache) = 1; +- ++_dl_skip_args; + --_dl_argc; + ++_dl_argv; + } +@@ -1225,7 +1279,6 @@ dl_main (const ElfW(Phdr) *phdr, + state.library_path = _dl_argv[2]; + state.library_path_source = "--library-path"; + +- _dl_skip_args += 2; + _dl_argc -= 2; + _dl_argv += 2; + } +@@ -1234,7 +1287,6 @@ dl_main (const ElfW(Phdr) *phdr, + { + GLRO(dl_inhibit_rpath) = _dl_argv[2]; + +- _dl_skip_args += 2; + _dl_argc -= 2; + _dl_argv += 2; + } +@@ -1242,14 +1294,12 @@ dl_main (const ElfW(Phdr) *phdr, + { + audit_list_add_string (&state.audit_list, _dl_argv[2]); + +- _dl_skip_args += 2; + _dl_argc -= 2; + _dl_argv += 2; + } + else if (! strcmp (_dl_argv[1], "--preload") && _dl_argc > 2) + { + state.preloadarg = _dl_argv[2]; +- _dl_skip_args += 2; + _dl_argc -= 2; + _dl_argv += 2; + } +@@ -1257,7 +1307,6 @@ dl_main (const ElfW(Phdr) *phdr, + { + argv0 = _dl_argv[2]; + +- _dl_skip_args += 2; + _dl_argc -= 2; + _dl_argv += 2; + } +@@ -1265,7 +1314,6 @@ dl_main (const ElfW(Phdr) *phdr, + && _dl_argc > 2) + { + state.glibc_hwcaps_prepend = _dl_argv[2]; +- _dl_skip_args += 2; + _dl_argc -= 2; + _dl_argv += 2; + } +@@ -1273,7 +1321,6 @@ dl_main (const ElfW(Phdr) *phdr, + && _dl_argc > 2) + { + state.glibc_hwcaps_mask = _dl_argv[2]; +- _dl_skip_args += 2; + _dl_argc -= 2; + _dl_argv += 2; + } +@@ -1282,7 +1329,6 @@ dl_main (const ElfW(Phdr) *phdr, + { + state.mode = rtld_mode_list_tunables; + +- ++_dl_skip_args; + --_dl_argc; + ++_dl_argv; + } +@@ -1291,7 +1337,6 @@ dl_main (const ElfW(Phdr) *phdr, + { + state.mode = rtld_mode_list_diagnostics; + +- ++_dl_skip_args; + --_dl_argc; + ++_dl_argv; + } +@@ -1337,7 +1382,6 @@ dl_main (const ElfW(Phdr) *phdr, + _dl_usage (ld_so_name, NULL); + } + +- ++_dl_skip_args; + --_dl_argc; + ++_dl_argv; + +@@ -1433,6 +1477,9 @@ dl_main (const ElfW(Phdr) *phdr, + /* Set the argv[0] string now that we've processed the executable. */ + if (argv0 != NULL) + _dl_argv[0] = argv0; ++ ++ /* Adjust arguments for the application entry point. */ ++ _dl_start_args_adjust (_dl_argv - orig_argv); + } + else + { +diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c +index 7bd1d70c96c229e0..8aab46bf6396c8d4 100644 +--- a/sysdeps/mach/hurd/dl-sysdep.c ++++ b/sysdeps/mach/hurd/dl-sysdep.c +@@ -107,6 +107,7 @@ _dl_sysdep_start (void **start_argptr, + { + void go (intptr_t *argdata) + { ++ char *orig_argv0; + char **p; + + /* Cache the information in various global variables. */ +@@ -115,6 +116,8 @@ _dl_sysdep_start (void **start_argptr, + _environ = &_dl_argv[_dl_argc + 1]; + for (p = _environ; *p++;); /* Skip environ pointers and terminator. */ + ++ orig_argv0 = _dl_argv[0]; ++ + if ((void *) p == _dl_argv[0]) + { + static struct hurd_startup_data nodata; +@@ -189,30 +192,23 @@ unfmh(); /* XXX */ + + /* The call above might screw a few things up. + +- First of all, if _dl_skip_args is nonzero, we are ignoring +- the first few arguments. However, if we have no Hurd startup +- data, it is the magical convention that ARGV[0] == P. The ++ P is the location after the terminating NULL of the list of ++ environment variables. It has to point to the Hurd startup ++ data or if that's missing then P == ARGV[0] must hold. The + startup code in init-first.c will get confused if this is not + the case, so we must rearrange things to make it so. We'll +- overwrite the origional ARGV[0] at P with ARGV[_dl_skip_args]. ++ recompute P and move the Hurd data or the new ARGV[0] there. + +- Secondly, if we need to be secure, it removes some dangerous +- environment variables. If we have no Hurd startup date this +- changes P (since that's the location after the terminating +- NULL in the list of environment variables). We do the same +- thing as in the first case but make sure we recalculate P. +- If we do have Hurd startup data, we have to move the data +- such that it starts just after the terminating NULL in the +- environment list. ++ Note: directly invoked ld.so can move arguments and env vars. + + We use memmove, since the locations might overlap. */ +- if (__libc_enable_secure || _dl_skip_args) +- { +- char **newp; + +- for (newp = _environ; *newp++;); ++ char **newp; ++ for (newp = _environ; *newp++;); + +- if (_dl_argv[-_dl_skip_args] == (char *) p) ++ if (newp != p || _dl_argv[0] != orig_argv0) ++ { ++ if (orig_argv0 == (char *) p) + { + if ((char *) newp != _dl_argv[0]) + { diff --git a/glibc-rh2047981-43.patch b/glibc-rh2047981-43.patch new file mode 100644 index 0000000..13691c9 --- /dev/null +++ b/glibc-rh2047981-43.patch @@ -0,0 +1,22 @@ +commit 62c888b3375f82a659a55ec66b1315efa2ed026a +Author: Carlos O'Donell +Date: Thu Jun 2 10:59:14 2022 -0400 + + elf: Add #include for MAX usage. + + In _dl_audit_pltenter we use MAX and so need to include param.h. + + Tested on x86_64 and i686 without regression. + +diff --git a/elf/dl-audit.c b/elf/dl-audit.c +index ec9b032eae37c103..e20b7b40e08d79e7 100644 +--- a/elf/dl-audit.c ++++ b/elf/dl-audit.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + void + _dl_audit_activity_map (struct link_map *l, int action) diff --git a/glibc-rh2047981-44.patch b/glibc-rh2047981-44.patch new file mode 100644 index 0000000..e5f9389 --- /dev/null +++ b/glibc-rh2047981-44.patch @@ -0,0 +1,98 @@ +Downstream-only patch to change rtld_active () to return true during +early audit operations. GLRO (_dl_profile_output) is initialized much +earlier than GLRO (dl_init_all_dirs), before auditors run, so it is a +good replacement. + +This is addressed downstream very differently, in this commit: + +commit 8dcb6d0af07fda3607b541857e4f3970a74ed55b +Author: Florian Weimer +Date: Tue Apr 26 14:23:02 2022 +0200 + + dlfcn: Do not use rtld_active () to determine ld.so state (bug 29078) + + When audit modules are loaded, ld.so initialization is not yet + complete, and rtld_active () returns false even though ld.so is + mostly working. Instead, the static dlopen hook is used, but that + does not work at all because this is not a static dlopen situation. + + Commit 466c1ea15f461edb8e3ffaf5d86d708876343bbf ("dlfcn: Rework + static dlopen hooks") moved the hook pointer into _rtld_global_ro, + which means that separate protection is not needed anymore and the + hook pointer can be checked directly. + + The guard for disabling libio vtable hardening in _IO_vtable_check + should stay for now. + + Fixes commit 8e1472d2c1e25e6eabc2059170731365f6d5b3d1 ("ld.so: + Examine GLRO to detect inactive loader [BZ #20204]"). + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/rtld.c b/elf/rtld.c +index 22cceeab40319582..b47e84ca2fb6f03c 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -2352,9 +2352,7 @@ ERROR: '%s': cannot process note segment.\n", _dl_argv[0]); + GLRO(dl_initial_searchlist) = *GL(dl_ns)[LM_ID_BASE]._ns_main_searchlist; + + /* Remember the last search directory added at startup, now that +- malloc will no longer be the one from dl-minimal.c. As a side +- effect, this marks ld.so as initialized, so that the rtld_active +- function returns true from now on. */ ++ malloc will no longer be the one from dl-minimal.c. */ + GLRO(dl_init_all_dirs) = GL(dl_all_dirs); + + /* Print scope information. */ +@@ -2675,7 +2673,9 @@ process_envvars (struct dl_main_state *state) + char *envline; + char *debug_output = NULL; + +- /* This is the default place for profiling data file. */ ++ /* This is the default place for profiling data file. As a side ++ effect, this marks ld.so as initialized, so that the rtld_active ++ function returns true from now on. */ + GLRO(dl_profile_output) + = &"/var/tmp\0/var/profile"[__libc_enable_secure ? 9 : 0]; + +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index d4f70211c34d1c59..9dec9e3d3b6d6aa2 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -600,18 +600,18 @@ struct rtld_global_ro + + /* Name of the shared object to be profiled (if any). */ + EXTERN const char *_dl_profile; +- /* Filename of the output file. */ ++ /* Filename of the output file. This is assigned a ++ non-NULL pointer by the ld.so startup code (after initialization ++ to NULL), so this can also serve as an indicator whether a copy ++ of ld.so is initialized and active. See the rtld_active function ++ below. */ + EXTERN const char *_dl_profile_output; + /* Name of the object we want to trace the prelinking. */ + EXTERN const char *_dl_trace_prelink; + /* Map of shared object to be prelink traced. */ + EXTERN struct link_map *_dl_trace_prelink_map; + +- /* All search directories defined at startup. This is assigned a +- non-NULL pointer by the ld.so startup code (after initialization +- to NULL), so this can also serve as an indicator whether a copy +- of ld.so is initialized and active. See the rtld_active function +- below. */ ++ /* All search directories defined at startup. */ + EXTERN struct r_search_path_elem *_dl_init_all_dirs; + + #ifdef NEED_DL_SYSINFO +@@ -1259,9 +1259,9 @@ static inline bool + rtld_active (void) + { + /* The default-initialized variable does not have a non-zero +- dl_init_all_dirs member, so this allows us to recognize an ++ dl_profile_output member, so this allows us to recognize an + initialized and active ld.so copy. */ +- return GLRO(dl_init_all_dirs) != NULL; ++ return GLRO(dl_profile_output) != NULL; + } + + static inline struct auditstate * diff --git a/glibc-rh2047981-45.patch b/glibc-rh2047981-45.patch new file mode 100644 index 0000000..0111ab9 --- /dev/null +++ b/glibc-rh2047981-45.patch @@ -0,0 +1,74 @@ +commit a64af8c9b6598f6d2685227f64f5ccb9b48c663c +Author: Florian Weimer +Date: Mon May 10 10:31:41 2021 +0200 + + scripts/versions.awk: Add strings and hashes to + + This generates new macros of this from: + + They are useful for symbol lookups using _dl_lookup_direct. + + Tested-by: Carlos O'Donell + Reviewed-by: Carlos O'Donell + +diff --git a/scripts/versions.awk b/scripts/versions.awk +index a3df316c703ea98b..0c900b83347ce8f9 100644 +--- a/scripts/versions.awk ++++ b/scripts/versions.awk +@@ -32,6 +32,29 @@ BEGIN { + sort = "sort -t. -k 1,1 -k 2n,2n -k 3 > " tmpfile; + } + ++# GNU awk does not implement the ord and chr functions. ++# ++# says that they are "written very nicely", using code similar to what ++# is included here. ++function chr(c) { ++ return sprintf("%c", c) ++} ++ ++BEGIN { ++ for (c = 1; c < 127; c++) { ++ ord_table[chr(c)] = c; ++ } ++} ++ ++function ord(c) { ++ if (ord_table[c]) { ++ return ord_table[c]; ++ } else { ++ printf("Invalid character reference: '%c'\n", c) > "/dev/stderr"; ++ ++lossage; ++ } ++} ++ + # Remove comment lines. + /^ *#/ { + next; +@@ -90,6 +113,17 @@ function close_and_move(name, real_name) { + system(move_if_change " " name " " real_name " >&2"); + } + ++# ELF hash, for use with symbol versions. ++function elf_hash(s, i, acc) { ++ acc = 0; ++ for (i = 1; i <= length(s); ++i) { ++ acc = and(lshift(acc, 4) + ord(substr(s, i, 1)), 0xffffffff); ++ top = and(acc, 0xf0000000); ++ acc = and(xor(acc, rshift(top, 24)), compl(top)); ++ } ++ return acc; ++} ++ + # Now print the accumulated information. + END { + close(sort); +@@ -145,6 +179,8 @@ END { + && oldver ~ "^GLIBC_[0-9]" \ + && sym ~ "^[A-Za-z0-9_]*$") { + ver_val = oldver; ++ printf("#define %s_STRING \"%s\"\n", first_ver_macro, ver_val) > first_ver_header; ++ printf("#define %s_HASH 0x%x\n", first_ver_macro, elf_hash(ver_val)) > first_ver_header; + gsub("\\.", "_", ver_val); + printf("#define %s %s\n", first_ver_macro, ver_val) > first_ver_header; + first_ver_seen[first_ver_macro] = 1; diff --git a/glibc-rh2047981-46.patch b/glibc-rh2047981-46.patch new file mode 100644 index 0000000..3bbd90a --- /dev/null +++ b/glibc-rh2047981-46.patch @@ -0,0 +1,227 @@ +Backport of the new test from this upstream commit: + +commit 8dcb6d0af07fda3607b541857e4f3970a74ed55b +Author: Florian Weimer +Date: Tue Apr 26 14:23:02 2022 +0200 + + dlfcn: Do not use rtld_active () to determine ld.so state (bug 29078) + + When audit modules are loaded, ld.so initialization is not yet + complete, and rtld_active () returns false even though ld.so is + mostly working. Instead, the static dlopen hook is used, but that + does not work at all because this is not a static dlopen situation. + + Commit 466c1ea15f461edb8e3ffaf5d86d708876343bbf ("dlfcn: Rework + static dlopen hooks") moved the hook pointer into _rtld_global_ro, + which means that separate protection is not needed anymore and the + hook pointer can be checked directly. + + The guard for disabling libio vtable hardening in _IO_vtable_check + should stay for now. + + Fixes commit 8e1472d2c1e25e6eabc2059170731365f6d5b3d1 ("ld.so: + Examine GLRO to detect inactive loader [BZ #20204]"). + + Reviewed-by: Adhemerval Zanella + +Conflicts: + dlfcn/dladdr.c + dlfcn/dladdr1.c + dlfcn/dlclose.c + dlfcn/dlerror.c + dlfcn/dlinfo.c + dlfcn/dlmopen.c + dlfcn/dlopen.c + dlfcn/dlopenold.c + dlfcn/dlsym.c + dlfcn/dlvsym.c + elf/dl-libc.c + (Code changes not needed.) + elf/Makefile + (Usual test list conflicts. Also added $(libdl).) + +diff --git a/elf/Makefile b/elf/Makefile +index 6d39b400060a73f3..3fae27d32676caf9 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -353,8 +353,7 @@ tests += \ + tst-audit24d \ + tst-audit25a \ + tst-audit25b \ +- tst-audit8 \ +- tst-audit9 \ ++ tst-audit26 \ + tst-auditmany \ + tst-auxobj \ + tst-auxobj-dlopen \ +@@ -659,6 +658,7 @@ modules-names = \ + tst-auditmod24c \ + tst-auditmod24d \ + tst-auditmod25 \ ++ tst-auditmod26 \ + tst-big-note-lib \ + tst-deep1mod1 \ + tst-deep1mod2 \ +@@ -2145,6 +2145,11 @@ $(objpfx)tst-audit25b: $(objpfx)tst-audit25mod1.so \ + LDFLAGS-tst-audit25b = -Wl,-z,now + tst-audit25b-ARGS = -- $(host-test-program-cmd) + ++$(objpfx)tst-audit26: $(libdl) ++$(objpfx)tst-audit26.out: $(objpfx)tst-auditmod26.so ++$(objpfx)tst-auditmod26.so: $(libsupport) $(libdl) ++tst-audit26-ENV = LD_AUDIT=$(objpfx)tst-auditmod26.so ++ + # tst-sonamemove links against an older implementation of the library. + LDFLAGS-tst-sonamemove-linkmod1.so = \ + -Wl,--version-script=tst-sonamemove-linkmod1.map \ +diff --git a/elf/tst-audit26.c b/elf/tst-audit26.c +new file mode 100644 +index 0000000000000000..3f920e83bac247a5 +--- /dev/null ++++ b/elf/tst-audit26.c +@@ -0,0 +1,35 @@ ++/* Check the usability of functions in audit modules. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ /* Check that the audit module has been loaded. */ ++ void *handle = xdlopen ("mapped to libc", RTLD_LOCAL | RTLD_NOW); ++ TEST_VERIFY (handle ++ == xdlopen (LIBC_SO, RTLD_LOCAL | RTLD_NOW | RTLD_NOLOAD)); ++ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-auditmod26.c b/elf/tst-auditmod26.c +new file mode 100644 +index 0000000000000000..db7ba95abec20f53 +--- /dev/null ++++ b/elf/tst-auditmod26.c +@@ -0,0 +1,104 @@ ++/* Check the usability of functions in audit modules. Audit module. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++unsigned int ++la_version (unsigned int current) ++{ ++ /* Exercise various functions. */ ++ ++ /* Check dlopen, dlsym, dlclose. */ ++ void *handle = xdlopen (LIBM_SO, RTLD_LOCAL | RTLD_NOW); ++ void *ptr = xdlsym (handle, "sincos"); ++ TEST_VERIFY (ptr != NULL); ++ ptr = dlsym (handle, "SINCOS"); ++ TEST_VERIFY (ptr == NULL); ++ const char *message = dlerror (); ++ TEST_VERIFY (strstr (message, ": undefined symbol: SINCOS") != NULL); ++ ptr = dlsym (handle, "SINCOS"); ++ TEST_VERIFY (ptr == NULL); ++ xdlclose (handle); ++ TEST_COMPARE_STRING (dlerror (), NULL); ++ ++ handle = xdlopen (LIBC_SO, RTLD_LOCAL | RTLD_NOW | RTLD_NOLOAD); ++ ++ /* Check dlvsym. _exit is unlikely to gain another symbol ++ version. */ ++ TEST_VERIFY (xdlsym (handle, "_exit") ++ == xdlvsym (handle, "_exit", FIRST_VERSION_libc__exit_STRING)); ++ ++ /* Check dlinfo. */ ++ { ++ void *handle2 = NULL; ++ TEST_COMPARE (dlinfo (handle, RTLD_DI_LINKMAP, &handle2), 0); ++ TEST_VERIFY (handle2 == handle); ++ } ++ ++ /* Check dladdr and dladdr1. */ ++ Dl_info info = { }; ++ TEST_VERIFY (dladdr (&_exit, &info) != 0); ++ if (strcmp (info.dli_sname, "_Exit") != 0) /* _Exit is an alias. */ ++ TEST_COMPARE_STRING (info.dli_sname, "_exit"); ++ TEST_VERIFY (info.dli_saddr == &_exit); ++ TEST_VERIFY (strstr (info.dli_fname, LIBC_SO)); ++ void *extra_info; ++ memset (&info, 0, sizeof (info)); ++ TEST_VERIFY (dladdr1 (&_exit, &info, &extra_info, RTLD_DL_LINKMAP) != 0); ++ TEST_VERIFY (extra_info == handle); ++ ++ /* Verify that dlmopen creates a new namespace. */ ++ void *dlmopen_handle = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW); ++ TEST_VERIFY (dlmopen_handle != handle); ++ memset (&info, 0, sizeof (info)); ++ extra_info = NULL; ++ ptr = xdlsym (dlmopen_handle, "_exit"); ++ TEST_VERIFY (dladdr1 (ptr, &info, &extra_info, RTLD_DL_LINKMAP) != 0); ++ TEST_VERIFY (extra_info == dlmopen_handle); ++ xdlclose (dlmopen_handle); ++ ++ /* Terminate the process with an error state. This does not happen ++ automatically because the audit module state is not shared with ++ the main program. */ ++ if (support_record_failure_is_failed ()) ++ { ++ fflush (stdout); ++ fflush (stderr); ++ _exit (1); ++ } ++ ++ return LAV_CURRENT; ++} ++ ++char * ++la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag) ++{ ++ if (strcmp (name, "mapped to libc") == 0) ++ return (char *) LIBC_SO; ++ else ++ return (char *) name; ++} diff --git a/glibc-rh2047981-47.patch b/glibc-rh2047981-47.patch new file mode 100644 index 0000000..c5baf0d --- /dev/null +++ b/glibc-rh2047981-47.patch @@ -0,0 +1,59 @@ +commit 2a5b4f7a715921a232f67f6810268c6cd6aa0af2 +Author: Florian Weimer +Date: Fri Jul 8 12:08:48 2022 +0200 + + elf: Rename tst-audit26 to tst-audit28 + + tst-audit26 and tst-audit27 are already used by aarch64. + + Reviewed-by: Szabolcs Nagy + +Conflicts: + elf/Makefile + (Usual test backport differences.) + +diff --git a/elf/Makefile b/elf/Makefile +index 3fae27d32676caf9..9e721d5d4e0a1cd9 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -353,7 +353,7 @@ tests += \ + tst-audit24d \ + tst-audit25a \ + tst-audit25b \ +- tst-audit26 \ ++ tst-audit28 \ + tst-auditmany \ + tst-auxobj \ + tst-auxobj-dlopen \ +@@ -658,7 +658,7 @@ modules-names = \ + tst-auditmod24c \ + tst-auditmod24d \ + tst-auditmod25 \ +- tst-auditmod26 \ ++ tst-auditmod28 \ + tst-big-note-lib \ + tst-deep1mod1 \ + tst-deep1mod2 \ +@@ -2145,10 +2145,10 @@ $(objpfx)tst-audit25b: $(objpfx)tst-audit25mod1.so \ + LDFLAGS-tst-audit25b = -Wl,-z,now + tst-audit25b-ARGS = -- $(host-test-program-cmd) + +-$(objpfx)tst-audit26: $(libdl) +-$(objpfx)tst-audit26.out: $(objpfx)tst-auditmod26.so +-$(objpfx)tst-auditmod26.so: $(libsupport) $(libdl) +-tst-audit26-ENV = LD_AUDIT=$(objpfx)tst-auditmod26.so ++$(objpfx)tst-audit28: $(libdl) ++$(objpfx)tst-audit28.out: $(objpfx)tst-auditmod28.so ++$(objpfx)tst-auditmod28.so: $(libsupport) $(libdl) ++tst-audit28-ENV = LD_AUDIT=$(objpfx)tst-auditmod28.so + + # tst-sonamemove links against an older implementation of the library. + LDFLAGS-tst-sonamemove-linkmod1.so = \ +diff --git a/elf/tst-audit26.c b/elf/tst-audit28.c +similarity index 100% +rename from elf/tst-audit26.c +rename to elf/tst-audit28.c +diff --git a/elf/tst-auditmod26.c b/elf/tst-auditmod28.c +similarity index 100% +rename from elf/tst-auditmod26.c +rename to elf/tst-auditmod28.c diff --git a/glibc-rh2047981-5.patch b/glibc-rh2047981-5.patch new file mode 100644 index 0000000..43af14e --- /dev/null +++ b/glibc-rh2047981-5.patch @@ -0,0 +1,224 @@ +commit b2964eb1d9a6b8ab1250e8a881cf406182da5875 +Author: Florian Weimer +Date: Wed Apr 21 19:49:51 2021 +0200 + + dlfcn: Failures after dlmopen should not terminate process [BZ #24772] + + Commit 9e78f6f6e7134a5f299cc8de77370218f8019237 ("Implement + _dl_catch_error, _dl_signal_error in libc.so [BZ #16628]") has the + side effect that distinct namespaces, as created by dlmopen, now have + separate implementations of the rtld exception mechanism. This means + that the call to _dl_catch_error from libdl in a secondary namespace + does not actually install an exception handler because the + thread-local variable catch_hook in the libc.so copy in the secondary + namespace is distinct from that of the base namepace. As a result, a + dlsym/dlopen/... failure in a secondary namespace terminates the process + with a dynamic linker error because it looks to the exception handler + mechanism as if no handler has been installed. + + This commit restores GLRO (dl_catch_error) and uses it to set the + handler in the base namespace. + + Reviewed-by: Adhemerval Zanella + +Conflicts: + elf/Makefile + +diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c +index 06732460ea1512cd..e08ac3afef302817 100644 +--- a/dlfcn/dlerror.c ++++ b/dlfcn/dlerror.c +@@ -167,8 +167,10 @@ _dlerror_run (void (*operate) (void *), void *args) + result->errstring = NULL; + } + +- result->errcode = _dl_catch_error (&result->objname, &result->errstring, +- &result->malloced, operate, args); ++ result->errcode = GLRO (dl_catch_error) (&result->objname, ++ &result->errstring, ++ &result->malloced, ++ operate, args); + + /* If no error we mark that no error string is available. */ + result->returned = result->errstring == NULL; +diff --git a/elf/Makefile b/elf/Makefile +index a811919ba4568d64..e0919486a14cab1a 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -216,6 +216,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \ + tst-tls20 tst-tls21 \ + tst-rtld-run-static \ ++ tst-dlmopen-dlerror \ + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -349,6 +350,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \ + libmarkermod5-1 libmarkermod5-2 libmarkermod5-3 libmarkermod5-4 \ + libmarkermod5-5 tst-tls20mod-bad tst-tls21mod \ ++ tst-dlmopen-dlerror-mod \ + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +@@ -1546,6 +1548,10 @@ $(objpfx)tst-sonamemove-dlopen.out: \ + $(objpfx)tst-sonamemove-runmod1.so \ + $(objpfx)tst-sonamemove-runmod2.so + ++$(objpfx)tst-dlmopen-dlerror: $(libdl) ++$(objpfx)tst-dlmopen-dlerror-mod.so: $(libdl) $(libsupport) ++$(objpfx)tst-dlmopen-dlerror.out: $(objpfx)tst-dlmopen-dlerror-mod.so ++ + # Override -z defs, so that we can reference an undefined symbol. + # Force lazy binding for the same reason. + LDFLAGS-tst-latepthreadmod.so = \ +diff --git a/elf/dl-error-skeleton.c b/elf/dl-error-skeleton.c +index 9cb002ccfed2c7b4..7801aa433b12275f 100644 +--- a/elf/dl-error-skeleton.c ++++ b/elf/dl-error-skeleton.c +@@ -248,4 +248,16 @@ _dl_receive_error (receiver_fct fct, void (*operate) (void *), void *args) + catch_hook = old_catch; + receiver = old_receiver; + } ++ ++/* Forwarder used for initializing GLRO (_dl_catch_error). */ ++int ++_rtld_catch_error (const char **objname, const char **errstring, ++ bool *mallocedp, void (*operate) (void *), ++ void *args) ++{ ++ /* The reference to _dl_catch_error will eventually be relocated to ++ point to the implementation in libc.so. */ ++ return _dl_catch_error (objname, errstring, mallocedp, operate, args); ++} ++ + #endif /* DL_ERROR_BOOTSTRAP */ +diff --git a/elf/rtld.c b/elf/rtld.c +index 461d8c114a875a9b..c445b5ca25dea193 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -365,6 +365,7 @@ struct rtld_global_ro _rtld_global_ro attribute_relro = + ._dl_lookup_symbol_x = _dl_lookup_symbol_x, + ._dl_open = _dl_open, + ._dl_close = _dl_close, ++ ._dl_catch_error = _rtld_catch_error, + ._dl_tls_get_addr_soft = _dl_tls_get_addr_soft, + #ifdef HAVE_DL_DISCOVER_OSVERSION + ._dl_discover_osversion = _dl_discover_osversion +diff --git a/elf/tst-dlmopen-dlerror-mod.c b/elf/tst-dlmopen-dlerror-mod.c +new file mode 100644 +index 0000000000000000..7e95dcdeacf005be +--- /dev/null ++++ b/elf/tst-dlmopen-dlerror-mod.c +@@ -0,0 +1,41 @@ ++/* Check that dlfcn errors are reported properly after dlmopen. Test module. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++/* Note: This object is not linked into the main program, so we cannot ++ use delayed test failure reporting via TEST_VERIFY etc., and have ++ to use FAIL_EXIT1 (or something else that calls exit). */ ++ ++void ++call_dlsym (void) ++{ ++ void *ptr = dlsym (NULL, "does not exist"); ++ if (ptr != NULL) ++ FAIL_EXIT1 ("dlsym did not fail as expected"); ++} ++ ++void ++call_dlopen (void) ++{ ++ void *handle = dlopen ("tst-dlmopen-dlerror does not exist", RTLD_NOW); ++ if (handle != NULL) ++ FAIL_EXIT1 ("dlopen did not fail as expected"); ++} +diff --git a/elf/tst-dlmopen-dlerror.c b/elf/tst-dlmopen-dlerror.c +new file mode 100644 +index 0000000000000000..e864d2fe4c3484ab +--- /dev/null ++++ b/elf/tst-dlmopen-dlerror.c +@@ -0,0 +1,37 @@ ++/* Check that dlfcn errors are reported properly after dlmopen. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-dlerror-mod.so", ++ RTLD_NOW); ++ void (*call_dlsym) (void) = xdlsym (handle, "call_dlsym"); ++ void (*call_dlopen) (void) = xdlsym (handle, "call_dlopen"); ++ ++ call_dlsym (); ++ call_dlopen (); ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 7b0a667629ddc06a..d6d02aa3ccffba33 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -647,6 +647,12 @@ struct rtld_global_ro + void *(*_dl_open) (const char *file, int mode, const void *caller_dlopen, + Lmid_t nsid, int argc, char *argv[], char *env[]); + void (*_dl_close) (void *map); ++ /* libdl in a secondary namespace (after dlopen) must use ++ _dl_catch_error from the main namespace, so it has to be ++ exported in some way. */ ++ int (*_dl_catch_error) (const char **objname, const char **errstring, ++ bool *mallocedp, void (*operate) (void *), ++ void *args); + void *(*_dl_tls_get_addr_soft) (struct link_map *); + #ifdef HAVE_DL_DISCOVER_OSVERSION + int (*_dl_discover_osversion) (void); +@@ -889,6 +895,9 @@ extern int _dl_catch_error (const char **objname, const char **errstring, + void *args); + libc_hidden_proto (_dl_catch_error) + ++/* Used for initializing GLRO (_dl_catch_error). */ ++extern __typeof__ (_dl_catch_error) _rtld_catch_error attribute_hidden; ++ + /* Call OPERATE (ARGS). If no error occurs, set *EXCEPTION to zero. + Otherwise, store a copy of the raised exception in *EXCEPTION, + which has to be freed by _dl_exception_free. As a special case, if diff --git a/glibc-rh2047981-6.patch b/glibc-rh2047981-6.patch new file mode 100644 index 0000000..09a5bf8 --- /dev/null +++ b/glibc-rh2047981-6.patch @@ -0,0 +1,822 @@ +commit fada9018199c21c469ff0e731ef75c6020074ac9 +Author: Florian Weimer +Date: Wed Apr 21 19:49:51 2021 +0200 + + dlfcn: dlerror needs to call free from the base namespace [BZ #24773] + + Calling free directly may end up freeing a pointer allocated by the + dynamic loader using malloc from libc.so in the base namespace using + the allocator from libc.so in a secondary namespace, which results in + crashes. + + This commit redirects the free call through GLRO and the dynamic + linker, to reach the correct namespace. It also cleans up the dlerror + handling along the way, so that pthread_setspecific is no longer + needed (which avoids triggering bug 24774). + +Conflicts: + dlfcn/dlfreeres.c - Remove. + malloc/set-freeres.c + Manual merge against disinct set of resources. + malloc/thread-freeres.c + Manual merge against disinct set of resources. + +diff --git a/dlfcn/Makefile b/dlfcn/Makefile +index 34f9923334f42edf..0b213b7d9fefcdc9 100644 +--- a/dlfcn/Makefile ++++ b/dlfcn/Makefile +@@ -22,9 +22,10 @@ include ../Makeconfig + headers := bits/dlfcn.h dlfcn.h + extra-libs := libdl + libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr dladdr1 dlinfo \ +- dlmopen dlfcn dlfreeres ++ dlmopen dlfcn + routines := $(patsubst %,s%,$(filter-out dlfcn,$(libdl-routines))) + elide-routines.os := $(routines) ++routines += libc_dlerror_result + + extra-libs-others := libdl + +diff --git a/dlfcn/Versions b/dlfcn/Versions +index 1df6925a92ff8b36..f07cb929aa13eaf2 100644 +--- a/dlfcn/Versions ++++ b/dlfcn/Versions +@@ -1,3 +1,8 @@ ++libc { ++ GLIBC_PRIVATE { ++ __libc_dlerror_result; ++ } ++} + libdl { + GLIBC_2.0 { + dladdr; dlclose; dlerror; dlopen; dlsym; +@@ -13,6 +18,5 @@ libdl { + } + GLIBC_PRIVATE { + _dlfcn_hook; +- __libdl_freeres; + } + } +diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c +index e08ac3afef302817..070eadbf7c1c0b1c 100644 +--- a/dlfcn/dlerror.c ++++ b/dlfcn/dlerror.c +@@ -25,6 +25,8 @@ + #include + #include + #include ++#include ++#include + + #if !defined SHARED && IS_IN (libdl) + +@@ -36,92 +38,75 @@ dlerror (void) + + #else + +-/* Type for storing results of dynamic loading actions. */ +-struct dl_action_result +- { +- int errcode; +- int returned; +- bool malloced; +- const char *objname; +- const char *errstring; +- }; +-static struct dl_action_result last_result; +-static struct dl_action_result *static_buf; +- +-/* This is the key for the thread specific memory. */ +-static __libc_key_t key; +-__libc_once_define (static, once); +- +-/* Destructor for the thread-specific data. */ +-static void init (void); +-static void free_key_mem (void *mem); +- +- + char * + __dlerror (void) + { +- char *buf = NULL; +- struct dl_action_result *result; +- + # ifdef SHARED + if (!rtld_active ()) + return _dlfcn_hook->dlerror (); + # endif + +- /* If we have not yet initialized the buffer do it now. */ +- __libc_once (once, init); ++ struct dl_action_result *result = __libc_dlerror_result; + +- /* Get error string. */ +- if (static_buf != NULL) +- result = static_buf; +- else ++ /* No libdl function has been called. No error is possible. */ ++ if (result == NULL) ++ return NULL; ++ ++ /* For an early malloc failure, clear the error flag and return the ++ error message. This marks the error as delivered. */ ++ if (result == dl_action_result_malloc_failed) + { +- /* init () has been run and we don't use the static buffer. +- So we have a valid key. */ +- result = (struct dl_action_result *) __libc_getspecific (key); +- if (result == NULL) +- result = &last_result; ++ __libc_dlerror_result = NULL; ++ return (char *) "out of memory"; + } + +- /* Test whether we already returned the string. */ +- if (result->returned != 0) ++ /* Placeholder object. This can be observed in a recursive call, ++ e.g. from an ELF constructor. */ ++ if (result->errstring == NULL) ++ return NULL; ++ ++ /* If we have already reported the error, we can free the result and ++ return NULL. See __libc_dlerror_result_free. */ ++ if (result->returned) + { +- /* We can now free the string. */ +- if (result->errstring != NULL) +- { +- if (strcmp (result->errstring, "out of memory") != 0) +- free ((char *) result->errstring); +- result->errstring = NULL; +- } ++ __libc_dlerror_result = NULL; ++ dl_action_result_errstring_free (result); ++ free (result); ++ return NULL; + } +- else if (result->errstring != NULL) +- { +- buf = (char *) result->errstring; +- int n; +- if (result->errcode == 0) +- n = __asprintf (&buf, "%s%s%s", +- result->objname, +- result->objname[0] == '\0' ? "" : ": ", +- _(result->errstring)); +- else +- n = __asprintf (&buf, "%s%s%s: %s", +- result->objname, +- result->objname[0] == '\0' ? "" : ": ", +- _(result->errstring), +- strerror (result->errcode)); +- if (n != -1) +- { +- /* We don't need the error string anymore. */ +- if (strcmp (result->errstring, "out of memory") != 0) +- free ((char *) result->errstring); +- result->errstring = buf; +- } + +- /* Mark the error as returned. */ +- result->returned = 1; +- } ++ assert (result->errstring != NULL); ++ ++ /* Create the combined error message. */ ++ char *buf; ++ int n; ++ if (result->errcode == 0) ++ n = __asprintf (&buf, "%s%s%s", ++ result->objname, ++ result->objname[0] == '\0' ? "" : ": ", ++ _(result->errstring)); ++ else ++ n = __asprintf (&buf, "%s%s%s: %s", ++ result->objname, ++ result->objname[0] == '\0' ? "" : ": ", ++ _(result->errstring), ++ strerror (result->errcode)); + +- return buf; ++ /* Mark the error as delivered. */ ++ result->returned = true; ++ ++ if (n >= 0) ++ { ++ /* Replace the error string with the newly allocated one. */ ++ dl_action_result_errstring_free (result); ++ result->errstring = buf; ++ result->errstring_source = dl_action_result_errstring_local; ++ return buf; ++ } ++ else ++ /* We could not create the combined error message, so use the ++ existing string as a fallback. */ ++ return result->errstring; + } + # ifdef SHARED + strong_alias (__dlerror, dlerror) +@@ -130,130 +115,94 @@ strong_alias (__dlerror, dlerror) + int + _dlerror_run (void (*operate) (void *), void *args) + { +- struct dl_action_result *result; +- +- /* If we have not yet initialized the buffer do it now. */ +- __libc_once (once, init); +- +- /* Get error string and number. */ +- if (static_buf != NULL) +- result = static_buf; +- else ++ struct dl_action_result *result = __libc_dlerror_result; ++ if (result != NULL) + { +- /* We don't use the static buffer and so we have a key. Use it +- to get the thread-specific buffer. */ +- result = __libc_getspecific (key); +- if (result == NULL) ++ if (result == dl_action_result_malloc_failed) + { +- result = (struct dl_action_result *) calloc (1, sizeof (*result)); +- if (result == NULL) +- /* We are out of memory. Since this is no really critical +- situation we carry on by using the global variable. +- This might lead to conflicts between the threads but +- they soon all will have memory problems. */ +- result = &last_result; +- else +- /* Set the tsd. */ +- __libc_setspecific (key, result); ++ /* Clear the previous error. */ ++ __libc_dlerror_result = NULL; ++ result = NULL; ++ } ++ else ++ { ++ /* There is an existing object. Free its error string, but ++ keep the object. */ ++ dl_action_result_errstring_free (result); ++ /* Mark the object as not containing an error. This ensures ++ that call to dlerror from, for example, an ELF ++ constructor will not notice this result object. */ ++ result->errstring = NULL; + } + } + +- if (result->errstring != NULL) +- { +- /* Free the error string from the last failed command. This can +- happen if `dlerror' was not run after an error was found. */ +- if (result->malloced) +- free ((char *) result->errstring); +- result->errstring = NULL; +- } +- +- result->errcode = GLRO (dl_catch_error) (&result->objname, +- &result->errstring, +- &result->malloced, +- operate, args); +- +- /* If no error we mark that no error string is available. */ +- result->returned = result->errstring == NULL; ++ const char *objname; ++ const char *errstring; ++ bool malloced; ++ int errcode = GLRO (dl_catch_error) (&objname, &errstring, &malloced, ++ operate, args); + +- return result->errstring != NULL; +-} ++ /* ELF constructors or destructors may have indirectly altered the ++ value of __libc_dlerror_result, therefore reload it. */ ++ result = __libc_dlerror_result; + +- +-/* Initialize buffers for results. */ +-static void +-init (void) +-{ +- if (__libc_key_create (&key, free_key_mem)) +- /* Creating the key failed. This means something really went +- wrong. In any case use a static buffer which is better than +- nothing. */ +- static_buf = &last_result; +-} +- +- +-static void +-check_free (struct dl_action_result *rec) +-{ +- if (rec->errstring != NULL +- && strcmp (rec->errstring, "out of memory") != 0) ++ if (errstring == NULL) + { +- /* We can free the string only if the allocation happened in the +- C library used by the dynamic linker. This means, it is +- always the C library in the base namespace. When we're statically +- linked, the dynamic linker is part of the program and so always +- uses the same C library we use here. */ +-#ifdef SHARED +- struct link_map *map = NULL; +- Dl_info info; +- if (_dl_addr (check_free, &info, &map, NULL) != 0 && map->l_ns == 0) +-#endif ++ /* There is no error. We no longer need the result object if it ++ does not contain an error. However, a recursive call may ++ have added an error even if this call did not cause it. Keep ++ the other error. */ ++ if (result != NULL && result->errstring == NULL) + { +- free ((char *) rec->errstring); +- rec->errstring = NULL; ++ __libc_dlerror_result = NULL; ++ free (result); + } ++ return 0; + } +-} +- +- +-static void +-__attribute__ ((destructor)) +-fini (void) +-{ +- check_free (&last_result); +-} +- +- +-/* Free the thread specific data, this is done if a thread terminates. */ +-static void +-free_key_mem (void *mem) +-{ +- check_free ((struct dl_action_result *) mem); ++ else ++ { ++ /* A new error occurred. Check if a result object has to be ++ allocated. */ ++ if (result == NULL || result == dl_action_result_malloc_failed) ++ { ++ /* Allocating storage for the error message after the fact ++ is not ideal. But this avoids an infinite recursion in ++ case malloc itself calls libdl functions (without ++ triggering errors). */ ++ result = malloc (sizeof (*result)); ++ if (result == NULL) ++ { ++ /* Assume that the dlfcn failure was due to a malloc ++ failure, too. */ ++ if (malloced) ++ dl_error_free ((char *) errstring); ++ __libc_dlerror_result = dl_action_result_malloc_failed; ++ return 1; ++ } ++ __libc_dlerror_result = result; ++ } ++ else ++ /* Deallocate the existing error message from a recursive ++ call, but reuse the result object. */ ++ dl_action_result_errstring_free (result); ++ ++ result->errcode = errcode; ++ result->objname = objname; ++ result->errstring = (char *) errstring; ++ result->returned = false; ++ /* In case of an error, the malloced flag indicates whether the ++ error string is constant or not. */ ++ if (malloced) ++ result->errstring_source = dl_action_result_errstring_rtld; ++ else ++ result->errstring_source = dl_action_result_errstring_constant; + +- free (mem); +- __libc_setspecific (key, NULL); ++ return 1; ++ } + } + + # ifdef SHARED + +-/* Free the dlerror-related resources. */ +-void +-__dlerror_main_freeres (void) +-{ +- /* Free the global memory if used. */ +- check_free (&last_result); +- +- if (__libc_once_get (once) && static_buf == NULL) +- { +- /* init () has been run and we don't use the static buffer. +- So we have a valid key. */ +- void *mem; +- /* Free the TSD memory if used. */ +- mem = __libc_getspecific (key); +- if (mem != NULL) +- free_key_mem (mem); +- } +-} +- + struct dlfcn_hook *_dlfcn_hook __attribute__((nocommon)); + libdl_hidden_data_def (_dlfcn_hook) + +diff --git a/dlfcn/dlerror.h b/dlfcn/dlerror.h +new file mode 100644 +index 0000000000000000..cb9a9cea4c009452 +--- /dev/null ++++ b/dlfcn/dlerror.h +@@ -0,0 +1,92 @@ ++/* Memory management for dlerror messages. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#ifndef _DLERROR_H ++#define _DLERROR_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* Source of the errstring member in struct dl_action_result, for ++ finding the right deallocation routine. */ ++enum dl_action_result_errstring_source ++ { ++ dl_action_result_errstring_constant, /* String literal, no deallocation. */ ++ dl_action_result_errstring_rtld, /* libc in the primary namespace. */ ++ dl_action_result_errstring_local, /* libc in the current namespace. */ ++ }; ++ ++struct dl_action_result ++{ ++ int errcode; ++ char errstring_source; ++ bool returned; ++ const char *objname; ++ char *errstring; ++}; ++ ++/* Used to free the errstring member of struct dl_action_result in the ++ dl_action_result_errstring_rtld case. */ ++static inline void ++dl_error_free (void *ptr) ++{ ++#ifdef SHARED ++ /* In the shared case, ld.so may use a different malloc than this ++ namespace. */ ++ GLRO (dl_error_free (ptr)); ++#else ++ /* Call the implementation directly. It still has to check for ++ pointers which cannot be freed, so do not call free directly ++ here. */ ++ _dl_error_free (ptr); ++#endif ++} ++ ++/* Deallocate RESULT->errstring, leaving *RESULT itself allocated. */ ++static inline void ++dl_action_result_errstring_free (struct dl_action_result *result) ++{ ++ switch (result->errstring_source) ++ { ++ case dl_action_result_errstring_constant: ++ break; ++ case dl_action_result_errstring_rtld: ++ dl_error_free (result->errstring); ++ break; ++ case dl_action_result_errstring_local: ++ free (result->errstring); ++ break; ++ } ++} ++ ++/* Stand-in for an error result object whose allocation failed. No ++ precise message can be reported for this, but an error must still ++ be signaled. */ ++static struct dl_action_result *const dl_action_result_malloc_failed ++ __attribute__ ((unused)) = (struct dl_action_result *) (intptr_t) -1; ++ ++/* Thread-local variable for storing dlfcn failures for subsequent ++ reporting via dlerror. */ ++extern __thread struct dl_action_result *__libc_dlerror_result ++ attribute_tls_model_ie; ++void __libc_dlerror_result_free (void) attribute_hidden; ++ ++#endif /* _DLERROR_H */ +diff --git a/dlfcn/dlfreeres.c b/dlfcn/dlfreeres.c +deleted file mode 100644 +index 4004db0edbe0c028..0000000000000000 +--- a/dlfcn/dlfreeres.c ++++ /dev/null +@@ -1,29 +0,0 @@ +-/* Clean up allocated libdl memory on demand. +- Copyright (C) 2018 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include +- +-/* Free libdl.so resources. +- Note: Caller ensures we are called only once. */ +-void +-__libdl_freeres (void) +-{ +- call_function_static_weak (__dlerror_main_freeres); +-} +diff --git a/dlfcn/libc_dlerror_result.c b/dlfcn/libc_dlerror_result.c +new file mode 100644 +index 0000000000000000..99747186b9218680 +--- /dev/null ++++ b/dlfcn/libc_dlerror_result.c +@@ -0,0 +1,39 @@ ++/* Thread-local variable holding the dlerror result. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++/* This pointer is either NULL, dl_action_result_malloc_failed (), or ++ has been allocated using malloc by the namespace that also contains ++ this instance of the thread-local variable. */ ++__thread struct dl_action_result *__libc_dlerror_result attribute_tls_model_ie; ++ ++/* Called during thread shutdown to free resources. */ ++void ++__libc_dlerror_result_free (void) ++{ ++ if (__libc_dlerror_result != NULL) ++ { ++ if (__libc_dlerror_result != dl_action_result_malloc_failed) ++ { ++ dl_action_result_errstring_free (__libc_dlerror_result); ++ free (__libc_dlerror_result); ++ } ++ __libc_dlerror_result = NULL; ++ } ++} +diff --git a/elf/dl-exception.c b/elf/dl-exception.c +index d24bf30a5cf39bc2..f474daf97ae76308 100644 +--- a/elf/dl-exception.c ++++ b/elf/dl-exception.c +@@ -30,6 +30,17 @@ + a pointer comparison. See below and in dlfcn/dlerror.c. */ + static const char _dl_out_of_memory[] = "out of memory"; + ++/* Call free in the main libc.so. This allows other namespaces to ++ free pointers on the main libc heap, via GLRO (dl_error_free). It ++ also avoids calling free on the special, pre-allocated ++ out-of-memory error message. */ ++void ++_dl_error_free (void *ptr) ++{ ++ if (ptr != _dl_out_of_memory) ++ free (ptr); ++} ++ + /* Dummy allocation object used if allocating the message buffer + fails. */ + static void +diff --git a/elf/rtld.c b/elf/rtld.c +index c445b5ca25dea193..e107af4014d43777 100644 +--- a/elf/rtld.c ++++ b/elf/rtld.c +@@ -366,6 +366,7 @@ struct rtld_global_ro _rtld_global_ro attribute_relro = + ._dl_open = _dl_open, + ._dl_close = _dl_close, + ._dl_catch_error = _rtld_catch_error, ++ ._dl_error_free = _dl_error_free, + ._dl_tls_get_addr_soft = _dl_tls_get_addr_soft, + #ifdef HAVE_DL_DISCOVER_OSVERSION + ._dl_discover_osversion = _dl_discover_osversion +diff --git a/elf/tst-dlmopen-dlerror-mod.c b/elf/tst-dlmopen-dlerror-mod.c +index 7e95dcdeacf005be..051025d3fa7a4d6a 100644 +--- a/elf/tst-dlmopen-dlerror-mod.c ++++ b/elf/tst-dlmopen-dlerror-mod.c +@@ -18,6 +18,8 @@ + + #include + #include ++#include ++#include + #include + + /* Note: This object is not linked into the main program, so we cannot +@@ -25,17 +27,32 @@ + to use FAIL_EXIT1 (or something else that calls exit). */ + + void +-call_dlsym (void) ++call_dlsym (const char *name) + { +- void *ptr = dlsym (NULL, "does not exist"); ++ void *ptr = dlsym (NULL, name); + if (ptr != NULL) +- FAIL_EXIT1 ("dlsym did not fail as expected"); ++ FAIL_EXIT1 ("dlsym did not fail as expected for: %s", name); ++ const char *message = dlerror (); ++ if (strstr (message, ": undefined symbol: does not exist X") == NULL) ++ FAIL_EXIT1 ("invalid dlsym error message for [[%s]]: %s", name, message); ++ message = dlerror (); ++ if (message != NULL) ++ FAIL_EXIT1 ("second dlsym for [[%s]]: %s", name, message); + } + + void +-call_dlopen (void) ++call_dlopen (const char *name) + { +- void *handle = dlopen ("tst-dlmopen-dlerror does not exist", RTLD_NOW); ++ void *handle = dlopen (name, RTLD_NOW); + if (handle != NULL) +- FAIL_EXIT1 ("dlopen did not fail as expected"); ++ FAIL_EXIT1 ("dlopen did not fail as expected for: %s", name); ++ const char *message = dlerror (); ++ if (strstr (message, "X: cannot open shared object file:" ++ " No such file or directory") == NULL ++ && strstr (message, "X: cannot open shared object file:" ++ " File name too long") == NULL) ++ FAIL_EXIT1 ("invalid dlopen error message for [[%s]]: %s", name, message); ++ message = dlerror (); ++ if (message != NULL) ++ FAIL_EXIT1 ("second dlopen for [[%s]]: %s", name, message); + } +diff --git a/elf/tst-dlmopen-dlerror.c b/elf/tst-dlmopen-dlerror.c +index e864d2fe4c3484ab..aa3d6598df119ce0 100644 +--- a/elf/tst-dlmopen-dlerror.c ++++ b/elf/tst-dlmopen-dlerror.c +@@ -17,6 +17,7 @@ + . */ + + #include ++#include + #include + #include + +@@ -25,11 +26,22 @@ do_test (void) + { + void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-dlerror-mod.so", + RTLD_NOW); +- void (*call_dlsym) (void) = xdlsym (handle, "call_dlsym"); +- void (*call_dlopen) (void) = xdlsym (handle, "call_dlopen"); +- +- call_dlsym (); +- call_dlopen (); ++ void (*call_dlsym) (const char *name) = xdlsym (handle, "call_dlsym"); ++ void (*call_dlopen) (const char *name) = xdlsym (handle, "call_dlopen"); ++ ++ /* Iterate over various name lengths. This changes the size of ++ error messages allocated by ld.so and has been shown to trigger ++ detectable heap corruption if malloc/free calls in different ++ namespaces are mixed. */ ++ char buffer[2048]; ++ char *buffer_end = &buffer[sizeof (buffer) - 2]; ++ for (char *p = stpcpy (buffer, "does not exist "); p < buffer_end; ++p) ++ { ++ p[0] = 'X'; ++ p[1] = '\0'; ++ call_dlsym (buffer); ++ call_dlopen (buffer); ++ } + + return 0; + } +diff --git a/include/dlfcn.h b/include/dlfcn.h +index 0dc57dbe2217cfe7..109586a1d968b630 100644 +--- a/include/dlfcn.h ++++ b/include/dlfcn.h +@@ -156,7 +156,5 @@ extern void __libc_register_dlfcn_hook (struct link_map *map) + attribute_hidden; + #endif + +-extern void __dlerror_main_freeres (void) attribute_hidden; +- + #endif + #endif +diff --git a/malloc/set-freeres.c b/malloc/set-freeres.c +index cda368479f910149..43b6a2cd9da49aa9 100644 +--- a/malloc/set-freeres.c ++++ b/malloc/set-freeres.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #include "../libio/libioP.h" + +@@ -26,8 +27,6 @@ DEFINE_HOOK (__libc_subfreeres, (void)); + + symbol_set_define (__libc_freeres_ptrs); + +-extern __attribute__ ((weak)) void __libdl_freeres (void); +- + extern __attribute__ ((weak)) void __libpthread_freeres (void); + + void __libc_freeres_fn_section +@@ -46,16 +45,13 @@ __libc_freeres (void) + /* We run the resource freeing after IO cleanup. */ + RUN_HOOK (__libc_subfreeres, ()); + +- /* Call the libdl list of cleanup functions +- (weak-ref-and-check). */ +- if (&__libdl_freeres != NULL) +- __libdl_freeres (); +- + /* Call the libpthread list of cleanup functions + (weak-ref-and-check). */ + if (&__libpthread_freeres != NULL) + __libpthread_freeres (); + ++ call_function_static_weak (__libc_dlerror_result_free); ++ + for (p = symbol_set_first_element (__libc_freeres_ptrs); + !symbol_set_end_p (__libc_freeres_ptrs, p); ++p) + free (*p); +diff --git a/malloc/thread-freeres.c b/malloc/thread-freeres.c +index a63b6c93f3114284..1e37a72c1f4a9c43 100644 +--- a/malloc/thread-freeres.c ++++ b/malloc/thread-freeres.c +@@ -16,6 +16,7 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include + #include + #include +@@ -32,6 +33,7 @@ __libc_thread_freeres (void) + call_function_static_weak (__rpc_thread_destroy); + call_function_static_weak (__res_thread_freeres); + call_function_static_weak (__strerror_thread_freeres); ++ call_function_static_weak (__libc_dlerror_result_free); + + /* This should come last because it shuts down malloc for this + thread and the other shutdown functions might well call free. */ +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index d6d02aa3ccffba33..2dd6f0c3c4aaaef5 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -653,6 +653,9 @@ struct rtld_global_ro + int (*_dl_catch_error) (const char **objname, const char **errstring, + bool *mallocedp, void (*operate) (void *), + void *args); ++ /* libdl in a secondary namespace must use free from the base ++ namespace. */ ++ void (*_dl_error_free) (void *); + void *(*_dl_tls_get_addr_soft) (struct link_map *); + #ifdef HAVE_DL_DISCOVER_OSVERSION + int (*_dl_discover_osversion) (void); +@@ -812,6 +815,10 @@ void _dl_exception_create (struct dl_exception *, const char *object, + __attribute__ ((nonnull (1, 3))); + rtld_hidden_proto (_dl_exception_create) + ++/* Used internally to implement dlerror message freeing. See ++ include/dlfcn.h and dlfcn/dlerror.c. */ ++void _dl_error_free (void *ptr) attribute_hidden; ++ + /* Like _dl_exception_create, but create errstring from a format + string FMT. Currently, only "%s" and "%%" are supported as format + directives. */ diff --git a/glibc-rh2047981-7.patch b/glibc-rh2047981-7.patch new file mode 100644 index 0000000..d1640be --- /dev/null +++ b/glibc-rh2047981-7.patch @@ -0,0 +1,134 @@ +Added $(objpfx)tst-dlmopen-gethostbyname: $(libdl) in elf/Makefile since +we still have $(libdl) in RHEL8. + +commit c2059edce20c124d1a99f1a94cc52e83b77a917a +Author: Florian Weimer +Date: Thu Jun 17 15:06:43 2021 +0200 + + elf: Use _dl_catch_error from base namespace in dl-libc.c [BZ #27646] + + dlerrror_run in elf/dl-libc.c needs to call GLRO (dl_catch_error) + from the base namespace, just like the exported dlerror + implementation. + + Fixes commit b2964eb1d9a6b8ab1250e8a881cf406182da5875 ("dlfcn: + Failures after dlmopen should not terminate process [BZ #24772]"). + + Reviewed-by: Siddhesh Poyarekar + +Conflicts: + elf/Makefile + +diff --git a/elf/Makefile b/elf/Makefile +index e0919486a14cab1a..30417c3ce15abcb4 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -217,6 +217,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-tls20 tst-tls21 \ + tst-rtld-run-static \ + tst-dlmopen-dlerror \ ++ tst-dlmopen-gethostbyname \ + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -351,6 +352,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ + libmarkermod5-1 libmarkermod5-2 libmarkermod5-3 libmarkermod5-4 \ + libmarkermod5-5 tst-tls20mod-bad tst-tls21mod \ + tst-dlmopen-dlerror-mod \ ++ tst-dlmopen-gethostbyname-mod \ + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +@@ -1935,3 +1937,5 @@ $(objpfx)tst-tls21.out: $(objpfx)tst-tls21mod.so + $(objpfx)tst-tls21mod.so: $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so) + + $(objpfx)tst-rtld-run-static.out: $(objpfx)/ldconfig ++$(objpfx)tst-dlmopen-gethostbyname: $(libdl) ++$(objpfx)tst-dlmopen-gethostbyname.out: $(objpfx)tst-dlmopen-gethostbyname-mod.so +diff --git a/elf/dl-libc.c b/elf/dl-libc.c +index fc01f5514d4f656c..3a242d219756dac6 100644 +--- a/elf/dl-libc.c ++++ b/elf/dl-libc.c +@@ -43,8 +43,8 @@ dlerror_run (void (*operate) (void *), void *args) + const char *last_errstring = NULL; + bool malloced; + +- int result = (_dl_catch_error (&objname, &last_errstring, &malloced, +- operate, args) ++ int result = (GLRO (dl_catch_error) (&objname, &last_errstring, &malloced, ++ operate, args) + ?: last_errstring != NULL); + + if (result && malloced) +diff --git a/elf/tst-dlmopen-gethostbyname-mod.c b/elf/tst-dlmopen-gethostbyname-mod.c +new file mode 100644 +index 0000000000000000..9a68ea5050c3060b +--- /dev/null ++++ b/elf/tst-dlmopen-gethostbyname-mod.c +@@ -0,0 +1,29 @@ ++/* Exercise dlerror_run in elf/dl-libc.c after dlmopen, via NSS. Helper module. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++void ++call_gethostbyname (void) ++{ ++ __nss_configure_lookup ("hosts", "files"); ++ /* This should not terminate the process due to a missing ++ _nss_files_getcanonname_r symbol. */ ++ gethostbyname ("localhost"); ++} +diff --git a/elf/tst-dlmopen-gethostbyname.c b/elf/tst-dlmopen-gethostbyname.c +new file mode 100644 +index 0000000000000000..12deb29900731c20 +--- /dev/null ++++ b/elf/tst-dlmopen-gethostbyname.c +@@ -0,0 +1,31 @@ ++/* Exercise dlerror_run in elf/dl-libc.c after dlmopen, via NSS (bug 27646). ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++static int ++do_test (void) ++{ ++ void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-gethostbyname-mod.so", ++ RTLD_NOW); ++ void (*call_gethostbyname) (void) = xdlsym (handle, "call_gethostbyname"); ++ call_gethostbyname (); ++ return 0; ++} ++ ++#include diff --git a/glibc-rh2047981-8.patch b/glibc-rh2047981-8.patch new file mode 100644 index 0000000..885aad4 --- /dev/null +++ b/glibc-rh2047981-8.patch @@ -0,0 +1,29 @@ +commit 832f50be6c9c010e46180d14126bbb81f35e808c +Author: Florian Weimer +Date: Tue Jul 6 13:22:01 2021 +0200 + + elf: Call free from base namespace on error in dl-libc.c [BZ #27646] + + In dlerror_run, free corresponds to the local malloc in the + namespace, but GLRO (dl_catch_error) uses the malloc from the base + namespace. elf/tst-dlmopen-gethostbyname triggers this mismatch, + but it does not crash, presumably because of a fastbin deallocation. + + Fixes commit c2059edce20c124d1a99f1a94cc52e83b77a917a ("elf: Use + _dl_catch_error from base namespace in dl-libc.c [BZ #27646]") and + commit b2964eb1d9a6b8ab1250e8a881cf406182da5875 ("dlfcn: Failures + after dlmopen should not terminate process [BZ #24772]"). + +diff --git a/elf/dl-libc.c b/elf/dl-libc.c +index 3a242d219756dac6..bb6e3378d546b234 100644 +--- a/elf/dl-libc.c ++++ b/elf/dl-libc.c +@@ -48,7 +48,7 @@ dlerror_run (void (*operate) (void *), void *args) + ?: last_errstring != NULL); + + if (result && malloced) +- free ((char *) last_errstring); ++ GLRO (dl_error_free) ((char *) last_errstring); + + return result; + } diff --git a/glibc-rh2047981-9.patch b/glibc-rh2047981-9.patch new file mode 100644 index 0000000..690027f --- /dev/null +++ b/glibc-rh2047981-9.patch @@ -0,0 +1,126 @@ +commit 3908fa933a4354309225af616d9242f595e11ccf +Author: Adhemerval Zanella +Date: Wed Jun 30 00:21:18 2021 -0300 + + elf: Fix audit regression + + Commit 03e187a41d9 added a regression when an audit module does not have + libc as DT_NEEDED (although unusual it is possible). + + Checked on x86_64-linux-gnu. + +Conflicts: + elf/Makefile + +diff --git a/elf/Makefile b/elf/Makefile +index 30417c3ce15abcb4..6262a4a65cfd2148 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -218,6 +218,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \ + tst-rtld-run-static \ + tst-dlmopen-dlerror \ + tst-dlmopen-gethostbyname \ ++ tst-audit17 \ + # reldep9 + tests-internal += loadtest unload unload2 circleload1 \ + neededtest neededtest2 neededtest3 neededtest4 \ +@@ -1527,6 +1528,16 @@ $(objpfx)tst-auditlogmod-3.so: $(libsupport) + $(objpfx)tst-audit16.out: \ + $(objpfx)tst-auditlogmod-1.so $(objpfx)tst-auditlogmod-2.so \ + $(objpfx)tst-auditlogmod-3.so ++$(objpfx)tst-audit17.out: $(objpfx)tst-auditmod17.so ++# The test check if a audit library without libc.so on DT_NEEDED works as ++# intended, so it uses an explicit link rule. ++$(objpfx)tst-auditmod17.so: $(objpfx)tst-auditmod17.os ++ $(CC) -nostdlib -nostartfiles -shared -o $@.new \ ++ $(filter-out $(map-file),$^) ++ $(call after-link,$@.new) ++ mv -f $@.new $@ ++CFLAGS-.os += $(call elide-stack-protector,.os,tst-auditmod17) ++tst-audit17-ENV = LD_AUDIT=$(objpfx)tst-auditmod17.so + + # tst-sonamemove links against an older implementation of the library. + LDFLAGS-tst-sonamemove-linkmod1.so = \ +diff --git a/elf/dl-open.c b/elf/dl-open.c +index 736df62ce6e46d34..661a2172d1789b26 100644 +--- a/elf/dl-open.c ++++ b/elf/dl-open.c +@@ -759,16 +759,9 @@ dl_open_worker_begin (void *a) + namespace. */ + if (!args->libc_already_loaded) + { ++ /* dlopen cannot be used to load an initial libc by design. */ + struct link_map *libc_map = GL(dl_ns)[args->nsid].libc_map; +-#ifdef SHARED +- bool initial = libc_map->l_ns == LM_ID_BASE; +-#else +- /* In the static case, there is only one namespace, but it +- contains a secondary libc (the primary libc is statically +- linked). */ +- bool initial = false; +-#endif +- _dl_call_libc_early_init (libc_map, initial); ++ _dl_call_libc_early_init (libc_map, false); + } + + #ifndef SHARED +diff --git a/elf/tst-audit17.c b/elf/tst-audit17.c +new file mode 100644 +index 0000000000000000..92986699d497845f +--- /dev/null ++++ b/elf/tst-audit17.c +@@ -0,0 +1,25 @@ ++/* Check DT_AUDIT with audit not linked against libc. ++ 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 ++ . */ ++ ++static int ++do_test (void) ++{ ++ return 0; ++} ++ ++#include +diff --git a/elf/tst-auditmod17.c b/elf/tst-auditmod17.c +new file mode 100644 +index 0000000000000000..7a4467f597b56cf4 +--- /dev/null ++++ b/elf/tst-auditmod17.c +@@ -0,0 +1,23 @@ ++/* Check DT_AUDIT with audit not linked against libc. ++ 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 ++ . */ ++ ++unsigned int ++la_version (unsigned int version) ++{ ++ return version; ++} diff --git a/glibc-rh2054790.patch b/glibc-rh2054790.patch new file mode 100644 index 0000000..6af769e --- /dev/null +++ b/glibc-rh2054790.patch @@ -0,0 +1,27 @@ +commit ea89d5bbd9e5e514b606045d909e6ab87d851c88 +Author: Arjun Shankar +Date: Thu Feb 24 21:43:09 2022 +0100 + + localedef: Handle symbolic links when generating locale-archive + + Whenever locale data for any locale included symbolic links, localedef + would throw the error "incomplete set of locale files" and exclude it + from the generated locale archive. This commit fixes that. + + Co-authored-by: Florian Weimer + + Reviewed-by: Carlos O'Donell + +diff --git a/locale/programs/locarchive.c b/locale/programs/locarchive.c +index dec73264563bc2a0..990f7eb6830d2e57 100644 +--- a/locale/programs/locarchive.c ++++ b/locale/programs/locarchive.c +@@ -1391,7 +1391,7 @@ add_locales_to_archive (size_t nlist, char *list[], bool replace) + { + char fullname[fnamelen + 2 * strlen (d->d_name) + 7]; + +- if (d_type == DT_UNKNOWN) ++ if (d_type == DT_UNKNOWN || d_type == DT_LNK) + { + strcpy (stpcpy (stpcpy (fullname, fname), "/"), + d->d_name); diff --git a/glibc-rh2063042.patch b/glibc-rh2063042.patch new file mode 100644 index 0000000..921add1 --- /dev/null +++ b/glibc-rh2063042.patch @@ -0,0 +1,358 @@ +commit fcfc9086815bf0d277ad47a90ee3fda4c37acca8 +Author: Siddhesh Poyarekar +Date: Wed Jan 12 23:34:48 2022 +0530 + + debug: Synchronize feature guards in fortified functions [BZ #28746] + + Some functions (e.g. stpcpy, pread64, etc.) had moved to POSIX in the + main headers as they got incorporated into the standard, but their + fortified variants remained under __USE_GNU. As a result, these + functions did not get fortified when _GNU_SOURCE was not defined. + + Add test wrappers that check all functions tested in tst-chk0 at all + levels with _GNU_SOURCE undefined and then use the failures to (1) + exclude checks for _GNU_SOURCE functions in these tests and (2) Fix + feature macro guards in the fortified function headers so that they're + the same as the ones in the main headers. + + This fixes BZ #28746. + + Signed-off-by: Siddhesh Poyarekar + Reviewed-by: Adhemerval Zanella + +# Conflicts: +# debug/tst-fortify.c + +diff --git a/debug/Makefile b/debug/Makefile +index c92fd23dda1a7279..b0f0b7beb6d5cef5 100644 +--- a/debug/Makefile ++++ b/debug/Makefile +@@ -132,6 +132,12 @@ define cflags-lfs + CFLAGS-tst-fortify-$(1)-lfs-$(2).$(1) += -D_FILE_OFFSET_BITS=64 + endef + ++define cflags-nongnu ++CFLAGS-tst-fortify-$(1)-nongnu-$(2).$(1) += -D_LARGEFILE64_SOURCE=1 ++endef ++ ++src-chk-nongnu = \#undef _GNU_SOURCE ++ + # We know these tests have problems with format strings, this is what + # we are testing. Disable that warning. They are also testing + # deprecated functions (notably gets) so disable that warning as well. +@@ -145,13 +151,13 @@ CFLAGS-tst-fortify-$(1)-$(2)-$(3).$(1) += -D_FORTIFY_SOURCE=$(3) -Wno-format \ + $(eval $(call cflags-$(2),$(1),$(3))) + $(objpfx)tst-fortify-$(1)-$(2)-$(3).$(1): tst-fortify.c Makefile + ( echo "/* Autogenerated from Makefile. */"; \ +- echo ""; \ ++ echo "$(src-chk-$(2))"; \ + echo "#include \"tst-fortify.c\"" ) > $$@.tmp + mv $$@.tmp $$@ + endef + + chk-extensions = c cc +-chk-types = default lfs ++chk-types = default lfs nongnu + chk-levels = 1 2 3 + + $(foreach e,$(chk-extensions), \ +diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c +index 5e76081255316a93..1668294e48b5c63c 100644 +--- a/debug/tst-fortify.c ++++ b/debug/tst-fortify.c +@@ -1,4 +1,5 @@ +-/* Copyright (C) 2004-2018 Free Software Foundation, Inc. ++/* Copyright (C) 2004-2022 Free Software Foundation, Inc. ++ Copyright The GNU Toolchain Authors. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2004. + +@@ -37,6 +38,17 @@ + #include + #include + ++#ifndef _GNU_SOURCE ++# define MEMPCPY memcpy ++# define WMEMPCPY wmemcpy ++# define MEMPCPY_RET(x) 0 ++# define WMEMPCPY_RET(x) 0 ++#else ++# define MEMPCPY mempcpy ++# define WMEMPCPY wmempcpy ++# define MEMPCPY_RET(x) __builtin_strlen (x) ++# define WMEMPCPY_RET(x) wcslen (x) ++#endif + + #define obstack_chunk_alloc malloc + #define obstack_chunk_free free +@@ -163,7 +175,7 @@ do_test (void) + if (memcmp (buf, "aabcdefghi", 10)) + FAIL (); + +- if (mempcpy (buf + 5, "abcde", 5) != buf + 10 ++ if (MEMPCPY (buf + 5, "abcde", 5) != buf + 5 + MEMPCPY_RET ("abcde") + || memcmp (buf, "aabcdabcde", 10)) + FAIL (); + +@@ -208,7 +220,7 @@ do_test (void) + if (memcmp (buf, "aabcdefghi", 10)) + FAIL (); + +- if (mempcpy (buf + 5, "abcde", l0 + 5) != buf + 10 ++ if (MEMPCPY (buf + 5, "abcde", l0 + 5) != buf + 5 + MEMPCPY_RET ("abcde") + || memcmp (buf, "aabcdabcde", 10)) + FAIL (); + +@@ -267,7 +279,8 @@ do_test (void) + if (memcmp (a.buf1, "aabcdefghi", 10)) + FAIL (); + +- if (mempcpy (a.buf1 + 5, "abcde", l0 + 5) != a.buf1 + 10 ++ if (MEMPCPY (a.buf1 + 5, "abcde", l0 + 5) ++ != a.buf1 + 5 + MEMPCPY_RET ("abcde") + || memcmp (a.buf1, "aabcdabcde", 10)) + FAIL (); + +@@ -348,6 +361,7 @@ do_test (void) + bcopy (buf + 1, buf + 2, l0 + 9); + CHK_FAIL_END + ++#ifdef _GNU_SOURCE + CHK_FAIL_START + p = (char *) mempcpy (buf + 6, "abcde", 5); + CHK_FAIL_END +@@ -355,6 +369,7 @@ do_test (void) + CHK_FAIL_START + p = (char *) mempcpy (buf + 6, "abcde", l0 + 5); + CHK_FAIL_END ++#endif + + CHK_FAIL_START + memset (buf + 9, 'j', 2); +@@ -465,6 +480,7 @@ do_test (void) + bcopy (a.buf1 + 1, a.buf1 + 2, l0 + 9); + CHK_FAIL_END + ++#ifdef _GNU_SOURCE + CHK_FAIL_START + p = (char *) mempcpy (a.buf1 + 6, "abcde", 5); + CHK_FAIL_END +@@ -472,6 +488,7 @@ do_test (void) + CHK_FAIL_START + p = (char *) mempcpy (a.buf1 + 6, "abcde", l0 + 5); + CHK_FAIL_END ++#endif + + CHK_FAIL_START + memset (a.buf1 + 9, 'j', 2); +@@ -551,7 +568,7 @@ do_test (void) + if (wmemcmp (wbuf, L"aabcdefghi", 10)) + FAIL (); + +- if (wmempcpy (wbuf + 5, L"abcde", 5) != wbuf + 10 ++ if (WMEMPCPY (wbuf + 5, L"abcde", 5) != wbuf + 5 + WMEMPCPY_RET (L"abcde") + || wmemcmp (wbuf, L"aabcdabcde", 10)) + FAIL (); + +@@ -584,7 +601,8 @@ do_test (void) + if (wmemcmp (wbuf, L"aabcdefghi", 10)) + FAIL (); + +- if (wmempcpy (wbuf + 5, L"abcde", l0 + 5) != wbuf + 10 ++ if (WMEMPCPY (wbuf + 5, L"abcde", l0 + 5) ++ != wbuf + 5 + WMEMPCPY_RET (L"abcde") + || wmemcmp (wbuf, L"aabcdabcde", 10)) + FAIL (); + +@@ -626,7 +644,8 @@ do_test (void) + if (wmemcmp (wa.buf1, L"aabcdefghi", 10)) + FAIL (); + +- if (wmempcpy (wa.buf1 + 5, L"abcde", l0 + 5) != wa.buf1 + 10 ++ if (WMEMPCPY (wa.buf1 + 5, L"abcde", l0 + 5) ++ != wa.buf1 + 5 + WMEMPCPY_RET (L"abcde") + || wmemcmp (wa.buf1, L"aabcdabcde", 10)) + FAIL (); + +@@ -695,6 +714,7 @@ do_test (void) + wmemmove (wbuf + 2, wbuf + 1, l0 + 9); + CHK_FAIL_END + ++#ifdef _GNU_SOURCE + CHK_FAIL_START + wp = wmempcpy (wbuf + 6, L"abcde", 5); + CHK_FAIL_END +@@ -702,6 +722,7 @@ do_test (void) + CHK_FAIL_START + wp = wmempcpy (wbuf + 6, L"abcde", l0 + 5); + CHK_FAIL_END ++#endif + + CHK_FAIL_START + wmemset (wbuf + 9, L'j', 2); +@@ -769,6 +790,7 @@ do_test (void) + wmemmove (wa.buf1 + 2, wa.buf1 + 1, l0 + 9); + CHK_FAIL_END + ++#ifdef _GNU_SOURCE + CHK_FAIL_START + wp = wmempcpy (wa.buf1 + 6, L"abcde", 5); + CHK_FAIL_END +@@ -776,6 +798,7 @@ do_test (void) + CHK_FAIL_START + wp = wmempcpy (wa.buf1 + 6, L"abcde", l0 + 5); + CHK_FAIL_END ++#endif + + CHK_FAIL_START + wmemset (wa.buf1 + 9, L'j', 2); +@@ -907,6 +930,7 @@ do_test (void) + if (fprintf (fp, buf2 + 4, str5) != 7) + FAIL (); + ++#ifdef _GNU_SOURCE + char *my_ptr = NULL; + strcpy (buf2 + 2, "%n%s%n"); + /* When the format string is writable and contains %n, +@@ -936,6 +960,7 @@ do_test (void) + if (obstack_printf (&obs, "%s%n%s%n", str4, &n1, str5, &n1) != 14) + FAIL (); + obstack_free (&obs, NULL); ++#endif + + if (freopen (temp_filename, "r", stdin) == NULL) + { +@@ -983,6 +1008,7 @@ do_test (void) + + rewind (stdin); + ++#ifdef _GNU_SOURCE + if (fgets_unlocked (buf, buf_size, stdin) != buf + || memcmp (buf, "abcdefgh\n", 10)) + FAIL (); +@@ -1009,6 +1035,7 @@ do_test (void) + #endif + + rewind (stdin); ++#endif + + if (fread (buf, 1, buf_size, stdin) != buf_size + || memcmp (buf, "abcdefgh\nA", 10)) +@@ -1579,7 +1606,10 @@ do_test (void) + ret = 1; + } + +- int fd = posix_openpt (O_RDWR); ++ int fd; ++ ++#ifdef _GNU_SOURCE ++ fd = posix_openpt (O_RDWR); + if (fd != -1) + { + char enough[1000]; +@@ -1595,6 +1625,7 @@ do_test (void) + #endif + close (fd); + } ++#endif + + #if PATH_MAX > 0 + confstr (_CS_GNU_LIBC_VERSION, largebuf, sizeof (largebuf)); +@@ -1712,8 +1743,9 @@ do_test (void) + poll (fds, l0 + 2, 0); + CHK_FAIL_END + #endif ++#ifdef _GNU_SOURCE + ppoll (fds, 1, NULL, NULL); +-#if __USE_FORTIFY_LEVEL >= 1 ++# if __USE_FORTIFY_LEVEL >= 1 + CHK_FAIL_START + ppoll (fds, 2, NULL, NULL); + CHK_FAIL_END +@@ -1721,6 +1753,7 @@ do_test (void) + CHK_FAIL_START + ppoll (fds, l0 + 2, NULL, NULL); + CHK_FAIL_END ++# endif + #endif + + return ret; +diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h +index a456d1723547db70..ddfaed4dd7574cd2 100644 +--- a/posix/bits/unistd.h ++++ b/posix/bits/unistd.h +@@ -38,7 +38,7 @@ read (int __fd, void *__buf, size_t __nbytes) + __fd, __buf, __nbytes); + } + +-#ifdef __USE_UNIX98 ++#if defined __USE_UNIX98 || defined __USE_XOPEN2K8 + extern ssize_t __pread_chk (int __fd, void *__buf, size_t __nbytes, + __off_t __offset, size_t __bufsize) __wur; + extern ssize_t __pread64_chk (int __fd, void *__buf, size_t __nbytes, +diff --git a/string/bits/string_fortified.h b/string/bits/string_fortified.h +index 27ec273ec41cd81c..3f86629bf8fc51a2 100644 +--- a/string/bits/string_fortified.h ++++ b/string/bits/string_fortified.h +@@ -94,7 +94,7 @@ __NTH (strcpy (char *__restrict __dest, const char *__restrict __src)) + return __builtin___strcpy_chk (__dest, __src, __glibc_objsize (__dest)); + } + +-#ifdef __USE_GNU ++#ifdef __USE_XOPEN2K8 + __fortify_function char * + __NTH (stpcpy (char *__restrict __dest, const char *__restrict __src)) + { +@@ -111,14 +111,15 @@ __NTH (strncpy (char *__restrict __dest, const char *__restrict __src, + __glibc_objsize (__dest)); + } + +-#if __GNUC_PREREQ (4, 7) || __glibc_clang_prereq (2, 6) ++#ifdef __USE_XOPEN2K8 ++# if __GNUC_PREREQ (4, 7) || __glibc_clang_prereq (2, 6) + __fortify_function char * + __NTH (stpncpy (char *__dest, const char *__src, size_t __n)) + { + return __builtin___stpncpy_chk (__dest, __src, __n, + __glibc_objsize (__dest)); + } +-#else ++# else + extern char *__stpncpy_chk (char *__dest, const char *__src, size_t __n, + size_t __destlen) __THROW; + extern char *__REDIRECT_NTH (__stpncpy_alias, (char *__dest, const char *__src, +@@ -132,6 +133,7 @@ __NTH (stpncpy (char *__dest, const char *__src, size_t __n)) + return __stpncpy_chk (__dest, __src, __n, __bos (__dest)); + return __stpncpy_alias (__dest, __src, __n); + } ++# endif + #endif + + +diff --git a/support/xsignal.h b/support/xsignal.h +index 9ab8d1bfddf6c598..fae6108a522ae5fe 100644 +--- a/support/xsignal.h ++++ b/support/xsignal.h +@@ -28,7 +28,9 @@ __BEGIN_DECLS + terminate the process on error. */ + + void xraise (int sig); ++#ifdef _GNU_SOURCE + sighandler_t xsignal (int sig, sighandler_t handler); ++#endif + void xsigaction (int sig, const struct sigaction *newact, + struct sigaction *oldact); + +diff --git a/wcsmbs/bits/wchar2.h b/wcsmbs/bits/wchar2.h +index f82bba481981e4fb..5c68979e96a504b4 100644 +--- a/wcsmbs/bits/wchar2.h ++++ b/wcsmbs/bits/wchar2.h +@@ -457,7 +457,7 @@ __NTH (wcsrtombs (char *__restrict __dst, const wchar_t **__restrict __src, + } + + +-#ifdef __USE_GNU ++#ifdef __USE_XOPEN2K8 + extern size_t __mbsnrtowcs_chk (wchar_t *__restrict __dst, + const char **__restrict __src, size_t __nmc, + size_t __len, mbstate_t *__restrict __ps, diff --git a/glibc-rh2061727.patch b/glibc-rh2063712.patch similarity index 100% rename from glibc-rh2061727.patch rename to glibc-rh2063712.patch diff --git a/glibc-rh2065588-1.patch b/glibc-rh2065588-1.patch new file mode 100644 index 0000000..3b4db3f --- /dev/null +++ b/glibc-rh2065588-1.patch @@ -0,0 +1,253 @@ +commit 2a973ab7f1a6f6cd9be1c7257fd7b5d331515eab +Author: Adhemerval Zanella +Date: Wed Sep 12 10:30:46 2018 -0300 + + posix: Add internal symbols for posix_spawn interface + + This patch adds internal hidden definition for mostly of the posix_spawn + function so it can be used internally on both popen and system + implementations. + + Checked on x86_64-linux-gnu. + + * include/spawn.h (__posix_spawn, posix_spawn_file_actions_addclose, + __posix_spawn_file_actions_adddup2, __posix_spawn_file_actions_destroy, + __posix_spawn_file_actions_init, __posix_spawnattr_init, + __posix_spawnattr_destroy, __posix_spawnattr_setflags, + __posix_spawnattr_setsigdefault, __posix_spawnattr_setsigmask): New + prototype. + * posix/spawn.c (__posix_spawn): Add libc_hidden_def. + * posix/spawn_faction_addclose.c + (__posix_spawn_file_actions_addclose): Add hidden definition. + * posix/spawn_faction_adddup2.c + (__posix_spawn_file_actions_adddup2): Likewise. + * posix/spawn_faction_destroy.c + (__posix_spawn_file_actions_destroy): Likewise. + * posix/spawn_faction_init.c (__posix_spawn_file_actions_init): + Likewise. + * posix/spawnattr_destroy.c (__posix_spawnattr_destroy): Likewise. + * posix/spawnattr_init.c (__posix_spawnattr_init): Likewise. + * posix/spawnattr_setdefault.c (__posix_spawnattr_setsigdefault): + Likewise. + * posix/spawnattr_setflags.c (__posix_spawnattr_setflags): Likewise. + * posix/spawnattr_setsigmask.c (__posix_spawnattr_setsigmask): + Likewise. + +diff --git a/include/spawn.h b/include/spawn.h +index a6c7a8adc361927e..7fdd965bd780f8de 100644 +--- a/include/spawn.h ++++ b/include/spawn.h +@@ -1 +1,36 @@ ++#ifndef _SPAWN_H + #include ++ ++# ifndef _ISOMAC ++__typeof (posix_spawn) __posix_spawn; ++libc_hidden_proto (__posix_spawn) ++ ++__typeof (posix_spawn_file_actions_addclose) ++ __posix_spawn_file_actions_addclose attribute_hidden; ++ ++__typeof (posix_spawn_file_actions_adddup2) ++ __posix_spawn_file_actions_adddup2 attribute_hidden; ++ ++__typeof (posix_spawn_file_actions_destroy) ++ __posix_spawn_file_actions_destroy attribute_hidden; ++ ++__typeof (posix_spawn_file_actions_init) __posix_spawn_file_actions_init ++ attribute_hidden; ++ ++__typeof (posix_spawnattr_init) __posix_spawnattr_init ++ attribute_hidden; ++ ++__typeof (posix_spawnattr_destroy) __posix_spawnattr_destroy ++ attribute_hidden; ++ ++__typeof (posix_spawnattr_setflags) __posix_spawnattr_setflags ++ attribute_hidden; ++ ++__typeof (posix_spawnattr_setsigdefault) __posix_spawnattr_setsigdefault ++ attribute_hidden; ++ ++__typeof (posix_spawnattr_setsigmask) __posix_spawnattr_setsigmask ++ attribute_hidden; ++ ++# endif /* !_ISOMAC */ ++#endif /* spawn.h */ +diff --git a/posix/spawn.c b/posix/spawn.c +index 51f67b2755bd4949..a82f1c84e299f018 100644 +--- a/posix/spawn.c ++++ b/posix/spawn.c +@@ -30,6 +30,7 @@ __posix_spawn (pid_t *pid, const char *path, + return __spawni (pid, path, file_actions, attrp, argv, envp, 0); + } + versioned_symbol (libc, __posix_spawn, posix_spawn, GLIBC_2_15); ++libc_hidden_def (__posix_spawn) + + + #if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_15) +diff --git a/posix/spawn_faction_addclose.c b/posix/spawn_faction_addclose.c +index 21081e19b55db44c..e1fafe438cf15c91 100644 +--- a/posix/spawn_faction_addclose.c ++++ b/posix/spawn_faction_addclose.c +@@ -24,8 +24,8 @@ + /* Add an action to FILE-ACTIONS which tells the implementation to call + `close' for the given file descriptor during the `spawn' call. */ + int +-posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *file_actions, +- int fd) ++__posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *file_actions, ++ int fd) + { + struct __spawn_action *rec; + +@@ -48,3 +48,5 @@ posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *file_actions, + + return 0; + } ++weak_alias (__posix_spawn_file_actions_addclose, ++ posix_spawn_file_actions_addclose) +diff --git a/posix/spawn_faction_adddup2.c b/posix/spawn_faction_adddup2.c +index 363bc29ae502bd60..371b1de3e6f1979a 100644 +--- a/posix/spawn_faction_adddup2.c ++++ b/posix/spawn_faction_adddup2.c +@@ -24,8 +24,8 @@ + /* Add an action to FILE-ACTIONS which tells the implementation to call + `dup2' for the given file descriptors during the `spawn' call. */ + int +-posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *file_actions, +- int fd, int newfd) ++__posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *file_actions, ++ int fd, int newfd) + { + struct __spawn_action *rec; + +@@ -49,3 +49,5 @@ posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *file_actions, + + return 0; + } ++weak_alias (__posix_spawn_file_actions_adddup2, ++ posix_spawn_file_actions_adddup2) +diff --git a/posix/spawn_faction_destroy.c b/posix/spawn_faction_destroy.c +index 46061ee3473d4475..2a2de4e41d6bd6d0 100644 +--- a/posix/spawn_faction_destroy.c ++++ b/posix/spawn_faction_destroy.c +@@ -22,7 +22,7 @@ + + /* Deallocate the file actions. */ + int +-posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *file_actions) ++__posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *file_actions) + { + /* Free the paths in the open actions. */ + for (int i = 0; i < file_actions->__used; ++i) +@@ -44,3 +44,5 @@ posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *file_actions) + free (file_actions->__actions); + return 0; + } ++weak_alias (__posix_spawn_file_actions_destroy, ++ posix_spawn_file_actions_destroy) +diff --git a/posix/spawn_faction_init.c b/posix/spawn_faction_init.c +index ddb42e6a77ba41ec..98432067c645021e 100644 +--- a/posix/spawn_faction_init.c ++++ b/posix/spawn_faction_init.c +@@ -45,9 +45,10 @@ __posix_spawn_file_actions_realloc (posix_spawn_file_actions_t *file_actions) + + /* Initialize data structure for file attribute for `spawn' call. */ + int +-posix_spawn_file_actions_init (posix_spawn_file_actions_t *file_actions) ++__posix_spawn_file_actions_init (posix_spawn_file_actions_t *file_actions) + { + /* Simply clear all the elements. */ + memset (file_actions, '\0', sizeof (*file_actions)); + return 0; + } ++weak_alias (__posix_spawn_file_actions_init, posix_spawn_file_actions_init) +diff --git a/posix/spawnattr_destroy.c b/posix/spawnattr_destroy.c +index 603e00fffefae2bf..043386778588913a 100644 +--- a/posix/spawnattr_destroy.c ++++ b/posix/spawnattr_destroy.c +@@ -19,8 +19,9 @@ + + /* Initialize data structure for file attribute for `spawn' call. */ + int +-posix_spawnattr_destroy (posix_spawnattr_t *attr) ++__posix_spawnattr_destroy (posix_spawnattr_t *attr) + { + /* Nothing to do in the moment. */ + return 0; + } ++weak_alias (__posix_spawnattr_destroy, posix_spawnattr_destroy) +diff --git a/posix/spawnattr_init.c b/posix/spawnattr_init.c +index bab464e62bdf7889..4e1218ab44e3f779 100644 +--- a/posix/spawnattr_init.c ++++ b/posix/spawnattr_init.c +@@ -20,7 +20,7 @@ + + /* Initialize data structure for file attribute for `spawn' call. */ + int +-posix_spawnattr_init (posix_spawnattr_t *attr) ++__posix_spawnattr_init (posix_spawnattr_t *attr) + { + /* All elements have to be initialized to the default values which + is generally zero. */ +@@ -28,3 +28,4 @@ posix_spawnattr_init (posix_spawnattr_t *attr) + + return 0; + } ++weak_alias (__posix_spawnattr_init, posix_spawnattr_init) +diff --git a/posix/spawnattr_setdefault.c b/posix/spawnattr_setdefault.c +index c77cda59be3dda20..174bcfa423dc5666 100644 +--- a/posix/spawnattr_setdefault.c ++++ b/posix/spawnattr_setdefault.c +@@ -20,11 +20,12 @@ + + /* Set signal mask for signals with default handling in ATTR to SIGDEFAULT. */ + int +-posix_spawnattr_setsigdefault (posix_spawnattr_t *attr, +- const sigset_t *sigdefault) ++__posix_spawnattr_setsigdefault (posix_spawnattr_t *attr, ++ const sigset_t *sigdefault) + { + /* Copy the sigset_t data to the user buffer. */ + memcpy (&attr->__sd, sigdefault, sizeof (sigset_t)); + + return 0; + } ++weak_alias (__posix_spawnattr_setsigdefault, posix_spawnattr_setsigdefault) +diff --git a/posix/spawnattr_setflags.c b/posix/spawnattr_setflags.c +index cf9a60181dc91ccd..0a42e94770224a94 100644 +--- a/posix/spawnattr_setflags.c ++++ b/posix/spawnattr_setflags.c +@@ -30,7 +30,7 @@ + + /* Store flags in the attribute structure. */ + int +-posix_spawnattr_setflags (posix_spawnattr_t *attr, short int flags) ++__posix_spawnattr_setflags (posix_spawnattr_t *attr, short int flags) + { + /* Check no invalid bits are set. */ + if (flags & ~ALL_FLAGS) +@@ -41,3 +41,4 @@ posix_spawnattr_setflags (posix_spawnattr_t *attr, short int flags) + + return 0; + } ++weak_alias (__posix_spawnattr_setflags, posix_spawnattr_setflags) +diff --git a/posix/spawnattr_setsigmask.c b/posix/spawnattr_setsigmask.c +index 7ae81ad47025db6f..12c0111af441dd13 100644 +--- a/posix/spawnattr_setsigmask.c ++++ b/posix/spawnattr_setsigmask.c +@@ -20,7 +20,7 @@ + + /* Set signal mask for the new process in ATTR to SIGMASK. */ + int +-posix_spawnattr_setsigmask (posix_spawnattr_t *attr, ++__posix_spawnattr_setsigmask (posix_spawnattr_t *attr, + const sigset_t *sigmask) + { + /* Copy the sigset_t data to the user buffer. */ +@@ -28,3 +28,4 @@ posix_spawnattr_setsigmask (posix_spawnattr_t *attr, + + return 0; + } ++weak_alias (__posix_spawnattr_setsigmask, posix_spawnattr_setsigmask) diff --git a/glibc-rh2065588-10.patch b/glibc-rh2065588-10.patch new file mode 100644 index 0000000..3016994 --- /dev/null +++ b/glibc-rh2065588-10.patch @@ -0,0 +1,21 @@ +commit 5fce0e095bc413f908f472074c2235198cd76bf4 +Author: Adhemerval Zanella +Date: Tue Mar 24 15:36:23 2020 -0300 + + support/shell-container.c: Return 127 if execve fails + + Reviewed-by: DJ Delorie + +diff --git a/support/shell-container.c b/support/shell-container.c +index e87ac5cf1baa84e5..e9eea64bca7e949d 100644 +--- a/support/shell-container.c ++++ b/support/shell-container.c +@@ -238,7 +238,7 @@ run_command_array (char **argv) + + fprintf (stderr, "sh: execing %s failed: %s", + argv[0], strerror (errno)); +- exit (1); ++ exit (127); + } + + waitpid (pid, &status, 0); diff --git a/glibc-rh2065588-11.patch b/glibc-rh2065588-11.patch new file mode 100644 index 0000000..a1ef4a7 --- /dev/null +++ b/glibc-rh2065588-11.patch @@ -0,0 +1,39 @@ +commit 5a5a3a3234bc220a5192d620e0cbc5360da46f14 +Author: Adhemerval Zanella +Date: Tue Mar 24 15:40:36 2020 -0300 + + support/shell-container.c: Add builtin exit + + Reviewed-by: DJ Delorie + +diff --git a/support/shell-container.c b/support/shell-container.c +index e9eea64bca7e949d..aeaf6d2733abce61 100644 +--- a/support/shell-container.c ++++ b/support/shell-container.c +@@ -135,6 +135,18 @@ copy_func (char **argv) + + } + ++/* Emulate the 'exit' builtin. The exit value is optional. */ ++static int ++exit_func (char **argv) ++{ ++ int exit_val = 0; ++ ++ if (argv[0] != 0) ++ exit_val = atoi (argv[0]) & 0xff; ++ exit (exit_val); ++ return 0; ++} ++ + /* This is a list of all the built-in commands we understand. */ + static struct { + const char *name; +@@ -143,6 +155,7 @@ static struct { + { "true", true_func }, + { "echo", echo_func }, + { "cp", copy_func }, ++ { "exit", exit_func }, + { NULL, NULL } + }; + diff --git a/glibc-rh2065588-12.patch b/glibc-rh2065588-12.patch new file mode 100644 index 0000000..7f4223f --- /dev/null +++ b/glibc-rh2065588-12.patch @@ -0,0 +1,60 @@ +commit 1c17100c43c0913ec94f3bcc966bf3792236c690 +Author: Adhemerval Zanella +Date: Tue Mar 24 15:47:13 2020 -0300 + + support/shell-container.c: Add builtin kill + + No options supported. + + Reviewed-by: DJ Delorie + +diff --git a/support/shell-container.c b/support/shell-container.c +index aeaf6d2733abce61..3869e14683fb74dd 100644 +--- a/support/shell-container.c ++++ b/support/shell-container.c +@@ -147,6 +147,25 @@ exit_func (char **argv) + return 0; + } + ++/* Emulate the "/bin/kill" command. Options are ignored. */ ++static int ++kill_func (char **argv) ++{ ++ int signum = SIGTERM; ++ int i; ++ ++ for (i = 0; argv[i]; i++) ++ { ++ pid_t pid; ++ if (strcmp (argv[i], "$$") == 0) ++ pid = getpid (); ++ else ++ pid = atoi (argv[i]); ++ kill (pid, signum); ++ } ++ return 0; ++} ++ + /* This is a list of all the built-in commands we understand. */ + static struct { + const char *name; +@@ -156,6 +175,7 @@ static struct { + { "echo", echo_func }, + { "cp", copy_func }, + { "exit", exit_func }, ++ { "kill", kill_func }, + { NULL, NULL } + }; + +@@ -264,6 +284,11 @@ run_command_array (char **argv) + if (rv) + exit (rv); + } ++ else if (WIFSIGNALED (status)) ++ { ++ int sig = WTERMSIG (status); ++ raise (sig); ++ } + else + exit (1); + } diff --git a/glibc-rh2065588-13.patch b/glibc-rh2065588-13.patch new file mode 100644 index 0000000..e4e9d70 --- /dev/null +++ b/glibc-rh2065588-13.patch @@ -0,0 +1,66 @@ +commit 75fe6d1a1620d84e0e487868feba9b2c0f109610 +Author: Siddhesh Poyarekar +Date: Wed May 12 10:13:41 2021 +0530 + + support: Close fds in copy_func + + copy_func may leave file descriptors open on error, so close them on + function exit. + +diff --git a/support/shell-container.c b/support/shell-container.c +index 3869e14683fb74dd..f0a9814ae230d167 100644 +--- a/support/shell-container.c ++++ b/support/shell-container.c +@@ -93,8 +93,9 @@ copy_func (char **argv) + { + char *sname = argv[0]; + char *dname = argv[1]; +- int sfd, dfd; ++ int sfd = -1, dfd = -1; + struct stat st; ++ int ret = 1; + + sfd = open (sname, O_RDONLY); + if (sfd < 0) +@@ -108,7 +109,7 @@ copy_func (char **argv) + { + fprintf (stderr, "cp: unable to fstat %s: %s\n", + sname, strerror (errno)); +- return 1; ++ goto out; + } + + dfd = open (dname, O_WRONLY | O_TRUNC | O_CREAT, 0600); +@@ -116,22 +117,26 @@ copy_func (char **argv) + { + fprintf (stderr, "cp: unable to open %s for writing: %s\n", + dname, strerror (errno)); +- return 1; ++ goto out; + } + + if (support_copy_file_range (sfd, 0, dfd, 0, st.st_size, 0) != st.st_size) + { + fprintf (stderr, "cp: cannot copy file %s to %s: %s\n", + sname, dname, strerror (errno)); +- return 1; ++ goto out; + } + +- close (sfd); +- close (dfd); +- ++ ret = 0; + chmod (dname, st.st_mode & 0777); + +- return 0; ++out: ++ if (sfd >= 0) ++ close (sfd); ++ if (dfd >= 0) ++ close (dfd); ++ ++ return ret; + + } + diff --git a/glibc-rh2065588-2.patch b/glibc-rh2065588-2.patch new file mode 100644 index 0000000..c671cf9 --- /dev/null +++ b/glibc-rh2065588-2.patch @@ -0,0 +1,231 @@ +commit 14d0e87d9b8caaa2eca7ca81f1189596671fe4fb +Author: Adhemerval Zanella +Date: Wed Sep 12 10:32:05 2018 -0300 + + posix: Use posix_spawn on popen + + This patch uses posix_spawn on popen instead of fork and execl. On Linux + this has the advantage of much lower memory consumption (usually 32 Kb + minimum for the mmap stack area). + + Two issues are also fixed with this change: + + * BZ#17490: although POSIX pthread_atfork description only list 'fork' + as the function that should execute the atfork handlers, popen + description states that: + + '[...] shall be *as if* a child process were created within the popen() + call using the fork() function [...]' + + Other libc/system seems to follow the idea atfork handlers should not be + executed for popen: + + libc/system | run atfork handles | notes + ------------|----------------------|--------------------------------------- + Freebsd | no | uses vfork + Solaris 11 | no | + MacOSX 11 | no | implemented through posix_spawn syscall + ------------|----------------------|---------------------------------------- + + Similar to posix_spawn and system, popen idea is to spawn a different + binary so all the POSIX rationale to run the atfork handlers to avoid + internal process inconsistency is not really required and in some cases + might be unsafe. + + * BZ#22834: the described scenario, where the forked process might access + invalid memory due an inconsistent state in multithreaded environment, + should not happen because posix_spawn does not access the affected + data structure (proc_file_chain). + + Checked on x86_64-linux-gnu and i686-linux-gnu. + + [BZ #22834] + [BZ #17490] + * NEWS: Add new semantic for atfork with popen and system. + * libio/iopopen.c (_IO_new_proc_open): use posix_spawn instead of + fork and execl. + +diff --git a/libio/iopopen.c b/libio/iopopen.c +index 2eff45b4c80b5cd6..c768295180fdf809 100644 +--- a/libio/iopopen.c ++++ b/libio/iopopen.c +@@ -34,7 +34,8 @@ + #include + #include + #include +-#include ++#include ++#include + + struct _IO_proc_file + { +@@ -59,13 +60,60 @@ unlock (void *not_used) + } + #endif + ++/* POSIX states popen shall ensure that any streams from previous popen() ++ calls that remain open in the parent process should be closed in the new ++ child process. ++ To avoid a race-condition between checking which file descriptors need to ++ be close (by transversing the proc_file_chain list) and the insertion of a ++ new one after a successful posix_spawn this function should be called ++ with proc_file_chain_lock acquired. */ ++static bool ++spawn_process (posix_spawn_file_actions_t *fa, FILE *fp, const char *command, ++ int do_cloexec, int pipe_fds[2], int parent_end, int child_end, ++ int child_pipe_fd) ++{ ++ ++ for (struct _IO_proc_file *p = proc_file_chain; p; p = p->next) ++ { ++ int fd = _IO_fileno ((FILE *) p); ++ ++ /* If any stream from previous popen() calls has fileno ++ child_pipe_fd, it has been already closed by the adddup2 action ++ above. */ ++ if (fd != child_pipe_fd ++ && __posix_spawn_file_actions_addclose (fa, fd) != 0) ++ return false; ++ } ++ ++ if (__posix_spawn (&((_IO_proc_file *) fp)->pid, _PATH_BSHELL, fa, 0, ++ (char *const[]){ (char*) "sh", (char*) "-c", ++ (char *) command, NULL }, __environ) != 0) ++ return false; ++ ++ __close_nocancel (pipe_fds[child_end]); ++ ++ if (!do_cloexec) ++ /* Undo the effects of the pipe2 call which set the ++ close-on-exec flag. */ ++ __fcntl (pipe_fds[parent_end], F_SETFD, 0); ++ ++ _IO_fileno (fp) = pipe_fds[parent_end]; ++ ++ ((_IO_proc_file *) fp)->next = proc_file_chain; ++ proc_file_chain = (_IO_proc_file *) fp; ++ ++ return true; ++} ++ + FILE * + _IO_new_proc_open (FILE *fp, const char *command, const char *mode) + { + int read_or_write; ++ /* These are indexes for pipe_fds. */ + int parent_end, child_end; + int pipe_fds[2]; +- pid_t child_pid; ++ int child_pipe_fd; ++ bool spawn_ok; + + int do_read = 0; + int do_write = 0; +@@ -108,72 +156,62 @@ _IO_new_proc_open (FILE *fp, const char *command, const char *mode) + + if (do_read) + { +- parent_end = pipe_fds[0]; +- child_end = pipe_fds[1]; ++ parent_end = 0; ++ child_end = 1; + read_or_write = _IO_NO_WRITES; ++ child_pipe_fd = 1; + } + else + { +- parent_end = pipe_fds[1]; +- child_end = pipe_fds[0]; ++ parent_end = 1; ++ child_end = 0; + read_or_write = _IO_NO_READS; ++ child_pipe_fd = 0; + } + +- ((_IO_proc_file *) fp)->pid = child_pid = __fork (); +- if (child_pid == 0) +- { +- int child_std_end = do_read ? 1 : 0; +- struct _IO_proc_file *p; +- +- if (child_end != child_std_end) +- __dup2 (child_end, child_std_end); +- else +- /* The descriptor is already the one we will use. But it must +- not be marked close-on-exec. Undo the effects. */ +- __fcntl (child_end, F_SETFD, 0); +- /* POSIX.2: "popen() shall ensure that any streams from previous +- popen() calls that remain open in the parent process are closed +- in the new child process." */ +- for (p = proc_file_chain; p; p = p->next) +- { +- int fd = _IO_fileno ((FILE *) p); ++ posix_spawn_file_actions_t fa; ++ /* posix_spawn_file_actions_init does not fail. */ ++ __posix_spawn_file_actions_init (&fa); + +- /* If any stream from previous popen() calls has fileno +- child_std_end, it has been already closed by the dup2 syscall +- above. */ +- if (fd != child_std_end) +- __close_nocancel (fd); +- } +- +- execl ("/bin/sh", "sh", "-c", command, (char *) 0); +- _exit (127); +- } +- __close_nocancel (child_end); +- if (child_pid < 0) ++ /* The descriptor is already the one the child will use. In this case ++ it must be moved to another one otherwise, there is no safe way to ++ remove the close-on-exec flag in the child without creating a FD leak ++ race in the parent. */ ++ if (pipe_fds[child_end] == child_pipe_fd) + { +- __close_nocancel (parent_end); +- return NULL; ++ int tmp = __fcntl (child_pipe_fd, F_DUPFD_CLOEXEC, 0); ++ if (tmp < 0) ++ goto spawn_failure; ++ __close_nocancel (pipe_fds[child_end]); ++ pipe_fds[child_end] = tmp; + } + +- if (!do_cloexec) +- /* Undo the effects of the pipe2 call which set the +- close-on-exec flag. */ +- __fcntl (parent_end, F_SETFD, 0); ++ if (__posix_spawn_file_actions_adddup2 (&fa, pipe_fds[child_end], ++ child_pipe_fd) != 0) ++ goto spawn_failure; + +- _IO_fileno (fp) = parent_end; +- +- /* Link into proc_file_chain. */ + #ifdef _IO_MTSAFE_IO + _IO_cleanup_region_start_noarg (unlock); + _IO_lock_lock (proc_file_chain_lock); + #endif +- ((_IO_proc_file *) fp)->next = proc_file_chain; +- proc_file_chain = (_IO_proc_file *) fp; ++ spawn_ok = spawn_process (&fa, fp, command, do_cloexec, pipe_fds, ++ parent_end, child_end, child_pipe_fd); + #ifdef _IO_MTSAFE_IO + _IO_lock_unlock (proc_file_chain_lock); + _IO_cleanup_region_end (0); + #endif + ++ __posix_spawn_file_actions_destroy (&fa); ++ ++ if (!spawn_ok) ++ { ++ spawn_failure: ++ __close_nocancel (pipe_fds[child_end]); ++ __close_nocancel (pipe_fds[parent_end]); ++ __set_errno (ENOMEM); ++ return NULL; ++ } ++ + _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES); + return fp; + } diff --git a/glibc-rh2065588-3.patch b/glibc-rh2065588-3.patch new file mode 100644 index 0000000..d168d88 --- /dev/null +++ b/glibc-rh2065588-3.patch @@ -0,0 +1,527 @@ +commit 5fb7fc96350575c9adb1316833e48ca11553be49 +Author: Adhemerval Zanella +Date: Wed Oct 24 16:29:38 2018 -0300 + + posix: Use posix_spawn on system + + This patch uses posix_spawn on system implementation. On Linux this has + the advantage of much lower memory consumption (usually 32 Kb minimum for + the mmap stack area). + + Although POSIX does not require, glibc system implementation aims to be + thread and cancellation safe. The cancellation code is moved to generic + implementation and enabled iff SIGCANCEL is defined (similar on how the + cancellation handler is enabled on nptl-init.c). + + Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, + arm-linux-gnueabihf, and powerpc64le-linux-gnu. + + * sysdeps/unix/sysv/linux/spawni.c (__spawni_child): Use + __sigismember instead of sigismember. + * sysdeps/posix/system.c [SIGCANCEL] (cancel_handler_args, + cancel_handler): New definitions. + (CLEANUP_HANDLER, CLEANUP_RESET): Likewise. + (DO_LOCK, DO_UNLOCK, INIT_LOCK, ADD_REF, SUB_REF): Remove. + (do_system): Use posix_spawn instead of fork and execl and remove + reentracy code. + * sysdeps/generic/not-errno.h (__kill_noerrno): New prototype. + * sysdeps/unix/sysv/linux/not-errno.h (__kill_noerrno): Likewise. + * sysdeps/unix/sysv/linux/ia64/system.c: Remove file. + * sysdeps/unix/sysv/linux/s390/system.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/system.c: Likewise. + * sysdeps/unix/sysv/linux/system.c: Likewise. + +diff --git a/sysdeps/generic/not-errno.h b/sysdeps/generic/not-errno.h +index 93617a3266fd4aad..0fd66b5c5ed82315 100644 +--- a/sysdeps/generic/not-errno.h ++++ b/sysdeps/generic/not-errno.h +@@ -17,3 +17,5 @@ + . */ + + extern __typeof (__access) __access_noerrno attribute_hidden; ++ ++extern __typeof (__kill) __kill_noerrno attribute_hidden; +diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c +index d7594436ed59906f..8a51a6b9919ec39b 100644 +--- a/sysdeps/posix/system.c ++++ b/sysdeps/posix/system.c +@@ -17,20 +17,36 @@ + + #include + #include +-#include + #include + #include ++#include ++#include ++#include + #include + #include +-#include +-#include +-#include ++#include + ++#include ++#include ++#include ++#include + + #define SHELL_PATH "/bin/sh" /* Path of the shell. */ + #define SHELL_NAME "sh" /* Name to give it. */ + + ++/* This system implementation aims to be thread-safe, which requires to ++ restore the signal dispositions for SIGINT and SIGQUIT correctly and to ++ deal with cancellation by terminating the child process. ++ ++ The signal disposition restoration on the single-thread case is ++ straighfoward. For multithreaded case, a reference-counter with a lock ++ is used, so the first thread will set the SIGINT/SIGQUIT dispositions and ++ last thread will restore them. ++ ++ Cancellation handling is done with thread cancellation clean-up handlers ++ on waitpid call. */ ++ + #ifdef _LIBC_REENTRANT + static struct sigaction intr, quit; + static int sa_refcntr; +@@ -50,17 +66,45 @@ __libc_lock_define_initialized (static, lock); + #endif + + ++#if defined(_LIBC_REENTRANT) && defined(SIGCANCEL) ++struct cancel_handler_args ++{ ++ struct sigaction *quit; ++ struct sigaction *intr; ++ pid_t pid; ++}; ++ ++static void ++cancel_handler (void *arg) ++{ ++ struct cancel_handler_args *args = (struct cancel_handler_args *) (arg); ++ ++ __kill_noerrno (args->pid, SIGKILL); ++ ++ TEMP_FAILURE_RETRY (__waitpid_nocancel (args->pid, NULL, 0)); ++ ++ DO_LOCK (); ++ if (SUB_REF () == 0) ++ { ++ __sigaction (SIGQUIT, args->quit, NULL); ++ __sigaction (SIGINT, args->intr, NULL); ++ } ++ DO_UNLOCK (); ++} ++#endif ++ + /* Execute LINE as a shell command, returning its status. */ + static int + do_system (const char *line) + { +- int status, save; ++ int status; + pid_t pid; + struct sigaction sa; + #ifndef _LIBC_REENTRANT + struct sigaction intr, quit; + #endif + sigset_t omask; ++ sigset_t reset; + + sa.sa_handler = SIG_IGN; + sa.sa_flags = 0; +@@ -69,105 +113,72 @@ do_system (const char *line) + DO_LOCK (); + if (ADD_REF () == 0) + { +- if (__sigaction (SIGINT, &sa, &intr) < 0) +- { +- (void) SUB_REF (); +- goto out; +- } +- if (__sigaction (SIGQUIT, &sa, &quit) < 0) +- { +- save = errno; +- (void) SUB_REF (); +- goto out_restore_sigint; +- } ++ /* sigaction can not fail with SIGINT/SIGQUIT used with SIG_IGN. */ ++ __sigaction (SIGINT, &sa, &intr); ++ __sigaction (SIGQUIT, &sa, &quit); + } + DO_UNLOCK (); + +- /* We reuse the bitmap in the 'sa' structure. */ + __sigaddset (&sa.sa_mask, SIGCHLD); +- save = errno; +- if (__sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0) ++ /* sigprocmask can not fail with SIG_BLOCK used with valid input ++ arguments. */ ++ __sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask); ++ ++ __sigemptyset (&reset); ++ if (intr.sa_handler != SIG_IGN) ++ __sigaddset(&reset, SIGINT); ++ if (quit.sa_handler != SIG_IGN) ++ __sigaddset(&reset, SIGQUIT); ++ ++ posix_spawnattr_t spawn_attr; ++ /* None of the posix_spawnattr_* function returns an error, including ++ posix_spawnattr_setflags for the follow specific usage (using valid ++ flags). */ ++ __posix_spawnattr_init (&spawn_attr); ++ __posix_spawnattr_setsigmask (&spawn_attr, &omask); ++ __posix_spawnattr_setsigdefault (&spawn_attr, &reset); ++ __posix_spawnattr_setflags (&spawn_attr, ++ POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK); ++ ++ status = __posix_spawn (&pid, SHELL_PATH, 0, &spawn_attr, ++ (char *const[]){ (char*) SHELL_NAME, ++ (char*) "-c", ++ (char *) line, NULL }, ++ __environ); ++ __posix_spawnattr_destroy (&spawn_attr); ++ ++ if (status == 0) + { +-#ifndef _LIBC +- if (errno == ENOSYS) +- __set_errno (save); +- else +-#endif +- { +- DO_LOCK (); +- if (SUB_REF () == 0) +- { +- save = errno; +- (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); +- out_restore_sigint: +- (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL); +- __set_errno (save); +- } +- out: +- DO_UNLOCK (); +- return -1; +- } +- } +- +-#ifdef CLEANUP_HANDLER +- CLEANUP_HANDLER; +-#endif +- +-#ifdef FORK +- pid = FORK (); +-#else +- pid = __fork (); ++ /* Cancellation results in cleanup handlers running as exceptions in ++ the block where they were installed, so it is safe to reference ++ stack variable allocate in the broader scope. */ ++#if defined(_LIBC_REENTRANT) && defined(SIGCANCEL) ++ struct cancel_handler_args cancel_args = ++ { ++ .quit = &quit, ++ .intr = &intr, ++ .pid = pid ++ }; ++ __libc_cleanup_region_start (1, cancel_handler, &cancel_args); + #endif +- if (pid == (pid_t) 0) +- { +- /* Child side. */ +- const char *new_argv[4]; +- new_argv[0] = SHELL_NAME; +- new_argv[1] = "-c"; +- new_argv[2] = line; +- new_argv[3] = NULL; +- +- /* Restore the signals. */ +- (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL); +- (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); +- (void) __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL); +- INIT_LOCK (); +- +- /* Exec the shell. */ +- (void) __execve (SHELL_PATH, (char *const *) new_argv, __environ); +- _exit (127); +- } +- else if (pid < (pid_t) 0) +- /* The fork failed. */ +- status = -1; +- else +- /* Parent side. */ +- { + /* Note the system() is a cancellation point. But since we call + waitpid() which itself is a cancellation point we do not + have to do anything here. */ + if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) != pid) + status = -1; +- } +- +-#ifdef CLEANUP_HANDLER +- CLEANUP_RESET; ++#if defined(_LIBC_REENTRANT) && defined(SIGCANCEL) ++ __libc_cleanup_region_end (0); + #endif ++ } + +- save = errno; + DO_LOCK (); +- if ((SUB_REF () == 0 +- && (__sigaction (SIGINT, &intr, (struct sigaction *) NULL) +- | __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0) +- || __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0) ++ if (SUB_REF () == 0) + { +-#ifndef _LIBC +- /* glibc cannot be used on systems without waitpid. */ +- if (errno == ENOSYS) +- __set_errno (save); +- else +-#endif +- status = -1; ++ /* sigaction can not fail with SIGINT/SIGQUIT used with old ++ disposition. Same applies for sigprocmask. */ ++ __sigaction (SIGINT, &intr, NULL); ++ __sigaction (SIGQUIT, &quit, NULL); ++ __sigprocmask (SIG_SETMASK, &omask, NULL); + } + DO_UNLOCK (); + +diff --git a/sysdeps/unix/sysv/linux/ia64/system.c b/sysdeps/unix/sysv/linux/ia64/system.c +deleted file mode 100644 +index d09fefefe64753ab..0000000000000000 +--- a/sysdeps/unix/sysv/linux/ia64/system.c ++++ /dev/null +@@ -1,30 +0,0 @@ +-/* Copyright (C) 2002-2018 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-/* We have to and actually can handle cancelable system(). The big +- problem: we have to kill the child process if necessary. To do +- this a cleanup handler has to be registered and is has to be able +- to find the PID of the child. The main problem is to reliable have +- the PID when needed. It is not necessary for the parent thread to +- return. It might still be in the kernel when the cancellation +- request comes. Therefore we have to use the clone() calls ability +- to have the kernel write the PID into the user-level variable. */ +-#define FORK() \ +- INLINE_SYSCALL (clone2, 6, CLONE_PARENT_SETTID | SIGCHLD, NULL, 0, \ +- &pid, NULL, NULL) +- +-#include +diff --git a/sysdeps/unix/sysv/linux/not-errno.h b/sysdeps/unix/sysv/linux/not-errno.h +index 106ba5c72e3d7dda..b2f72cfb3d412c56 100644 +--- a/sysdeps/unix/sysv/linux/not-errno.h ++++ b/sysdeps/unix/sysv/linux/not-errno.h +@@ -16,6 +16,9 @@ + License along with the GNU C Library; if not, see + . */ + ++#include ++#include ++ + /* This function is used on maybe_enable_malloc_check (elf/dl-tunables.c) + and to avoid having to build/use multiple versions if stack protection + in enabled it is defined as inline. */ +@@ -33,3 +36,14 @@ __access_noerrno (const char *pathname, int mode) + return INTERNAL_SYSCALL_ERRNO (res, err); + return 0; + } ++ ++static inline int ++__kill_noerrno (pid_t pid, int sig) ++{ ++ int res; ++ INTERNAL_SYSCALL_DECL (err); ++ res = INTERNAL_SYSCALL_CALL (kill, err, pid, sig); ++ if (INTERNAL_SYSCALL_ERROR_P (res, err)) ++ return INTERNAL_SYSCALL_ERRNO (res, err); ++ return 0; ++} +diff --git a/sysdeps/unix/sysv/linux/s390/system.c b/sysdeps/unix/sysv/linux/s390/system.c +deleted file mode 100644 +index d8ef46133419dd89..0000000000000000 +--- a/sysdeps/unix/sysv/linux/s390/system.c ++++ /dev/null +@@ -1,29 +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 +- . */ +- +-/* We have to and actually can handle cancelable system(). The big +- problem: we have to kill the child process if necessary. To do +- this a cleanup handler has to be registered and is has to be able +- to find the PID of the child. The main problem is to reliable have +- the PID when needed. It is not necessary for the parent thread to +- return. It might still be in the kernel when the cancellation +- request comes. Therefore we have to use the clone() calls ability +- to have the kernel write the PID into the user-level variable. */ +-#define FORK() \ +- INLINE_SYSCALL (clone, 3, 0, CLONE_PARENT_SETTID | SIGCHLD, &pid) +- +-#include "../system.c" +diff --git a/sysdeps/unix/sysv/linux/sparc/system.c b/sysdeps/unix/sysv/linux/sparc/system.c +deleted file mode 100644 +index 1f65c83399f920d6..0000000000000000 +--- a/sysdeps/unix/sysv/linux/sparc/system.c ++++ /dev/null +@@ -1,29 +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 +- . */ +- +-/* We have to and actually can handle cancelable system(). The big +- problem: we have to kill the child process if necessary. To do +- this a cleanup handler has to be registered and is has to be able +- to find the PID of the child. The main problem is to reliable have +- the PID when needed. It is not necessary for the parent thread to +- return. It might still be in the kernel when the cancellation +- request comes. Therefore we have to use the clone() calls ability +- to have the kernel write the PID into the user-level variable. */ +-#define FORK() \ +- INLINE_CLONE_SYSCALL (CLONE_PARENT_SETTID | SIGCHLD, 0, &pid, NULL, NULL) +- +-#include "../system.c" +diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c +index 85239cedbf2a5ab5..6a8bd2ed2e1c29b7 100644 +--- a/sysdeps/unix/sysv/linux/spawni.c ++++ b/sysdeps/unix/sysv/linux/spawni.c +@@ -138,11 +138,11 @@ __spawni_child (void *arguments) + for (int sig = 1; sig < _NSIG; ++sig) + { + if ((attr->__flags & POSIX_SPAWN_SETSIGDEF) +- && sigismember (&attr->__sd, sig)) ++ && __sigismember (&attr->__sd, sig)) + { + sa.sa_handler = SIG_DFL; + } +- else if (sigismember (&hset, sig)) ++ else if (__sigismember (&hset, sig)) + { + if (__is_internal_signal (sig)) + sa.sa_handler = SIG_IGN; +diff --git a/sysdeps/unix/sysv/linux/system.c b/sysdeps/unix/sysv/linux/system.c +deleted file mode 100644 +index 7cc68a1528ee8f99..0000000000000000 +--- a/sysdeps/unix/sysv/linux/system.c ++++ /dev/null +@@ -1,76 +0,0 @@ +-/* Copyright (C) 2002-2018 Free Software Foundation, Inc. +- This file is part of the GNU C Library. +- +- The GNU C Library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- The GNU C Library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with the GNU C Library; if not, see +- . */ +- +-#include +-#include +-#include /* For the real memset prototype. */ +-#include +-#include +-#include +-#include +- +-/* We have to and actually can handle cancelable system(). The big +- problem: we have to kill the child process if necessary. To do +- this a cleanup handler has to be registered and is has to be able +- to find the PID of the child. The main problem is to reliable have +- the PID when needed. It is not necessary for the parent thread to +- return. It might still be in the kernel when the cancellation +- request comes. Therefore we have to use the clone() calls ability +- to have the kernel write the PID into the user-level variable. */ +-#ifndef FORK +-# define FORK() \ +- INLINE_SYSCALL (clone, 3, CLONE_PARENT_SETTID | SIGCHLD, 0, &pid) +-#endif +- +-#ifdef _LIBC_REENTRANT +-static void cancel_handler (void *arg); +- +-# define CLEANUP_HANDLER \ +- __libc_cleanup_region_start (1, cancel_handler, &pid) +- +-# define CLEANUP_RESET \ +- __libc_cleanup_region_end (0) +-#endif +- +- +-/* Linux has waitpid(), so override the generic unix version. */ +-#include +- +- +-#ifdef _LIBC_REENTRANT +-/* The cancellation handler. */ +-static void +-cancel_handler (void *arg) +-{ +- pid_t child = *(pid_t *) arg; +- +- INTERNAL_SYSCALL_DECL (err); +- INTERNAL_SYSCALL (kill, err, 2, child, SIGKILL); +- +- TEMP_FAILURE_RETRY (__waitpid (child, NULL, 0)); +- +- DO_LOCK (); +- +- if (SUB_REF () == 0) +- { +- (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); +- (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL); +- } +- +- DO_UNLOCK (); +-} +-#endif diff --git a/glibc-rh2065588-4.patch b/glibc-rh2065588-4.patch new file mode 100644 index 0000000..33a0cce --- /dev/null +++ b/glibc-rh2065588-4.patch @@ -0,0 +1,194 @@ +commit f09542c584b121da0322fde4b55306d512b85d93 +Author: Adhemerval Zanella +Date: Mon Mar 23 15:23:20 2020 -0300 + + posix: Fix system error return value [BZ #25715] + + It fixes 5fb7fc9635 when posix_spawn fails. + + Checked on x86_64-linux-gnu and i686-linux-gnu. + + Reviewed-by: Carlos O'Donell + +diff --git a/stdlib/tst-system.c b/stdlib/tst-system.c +index d14839f3ec3a7bad..b61bd347df7ec46a 100644 +--- a/stdlib/tst-system.c ++++ b/stdlib/tst-system.c +@@ -17,14 +17,128 @@ + . */ + + #include ++#include ++#include ++#include ++#include + ++#include ++#include ++#include ++#include ++ ++static char *tmpdir; ++static long int namemax; ++ ++static void ++do_prepare (int argc, char *argv[]) ++{ ++ tmpdir = support_create_temp_directory ("tst-system-"); ++ /* Include the last '/0'. */ ++ namemax = pathconf (tmpdir, _PC_NAME_MAX) + 1; ++ TEST_VERIFY_EXIT (namemax != -1); ++} ++#define PREPARE do_prepare ++ ++struct args ++{ ++ const char *command; ++ int exit_status; ++ int term_sig; ++ const char *path; ++}; ++ ++static void ++call_system (void *closure) ++{ ++ struct args *args = (struct args *) closure; ++ int ret; ++ ++ if (args->path != NULL) ++ TEST_COMPARE (setenv ("PATH", args->path, 1), 0); ++ ret = system (args->command); ++ if (args->term_sig == 0) ++ { ++ /* Expect regular termination. */ ++ TEST_VERIFY (WIFEXITED (ret) != 0); ++ TEST_COMPARE (WEXITSTATUS (ret), args->exit_status); ++ } ++ else ++ { ++ /* status_or_signal < 0. Expect termination by signal. */ ++ TEST_VERIFY (WIFSIGNALED (ret) != 0); ++ TEST_COMPARE (WTERMSIG (ret), args->term_sig); ++ } ++} + + static int + do_test (void) + { +- return system (":"); +-} ++ TEST_VERIFY (system (NULL) != 0); + ++ { ++ char cmd[namemax]; ++ memset (cmd, 'a', sizeof(cmd)); ++ cmd[sizeof(cmd) - 1] = '\0'; ++ ++ struct support_capture_subprocess result; ++ result = support_capture_subprocess (call_system, ++ &(struct args) { ++ cmd, 127, 0, tmpdir ++ }); ++ support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr); ++ ++ char *returnerr = xasprintf ("%s: 1: %s: not found\n", ++ basename(_PATH_BSHELL), cmd); ++ TEST_COMPARE_STRING (result.err.buffer, returnerr); ++ free (returnerr); ++ } ++ ++ { ++ char cmd[namemax + 1]; ++ memset (cmd, 'a', sizeof(cmd)); ++ cmd[sizeof(cmd) - 1] = '\0'; ++ ++ struct support_capture_subprocess result; ++ result = support_capture_subprocess (call_system, ++ &(struct args) { ++ cmd, 127, 0, tmpdir ++ }); ++ support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr); ++ ++ char *returnerr = xasprintf ("%s: 1: %s: File name too long\n", ++ basename(_PATH_BSHELL), cmd); ++ TEST_COMPARE_STRING (result.err.buffer, returnerr); ++ free (returnerr); ++ } ++ ++ { ++ struct support_capture_subprocess result; ++ result = support_capture_subprocess (call_system, ++ &(struct args) { ++ "kill -USR1 $$", 0, SIGUSR1 ++ }); ++ support_capture_subprocess_check (&result, "system", 0, sc_allow_none); ++ } ++ ++ { ++ struct support_capture_subprocess result; ++ result = support_capture_subprocess (call_system, ++ &(struct args) { "echo ...", 0 }); ++ support_capture_subprocess_check (&result, "system", 0, sc_allow_stdout); ++ TEST_COMPARE_STRING (result.out.buffer, "...\n"); ++ } ++ ++ { ++ struct support_capture_subprocess result; ++ result = support_capture_subprocess (call_system, ++ &(struct args) { "exit 1", 1 }); ++ support_capture_subprocess_check (&result, "system", 0, sc_allow_none); ++ } ++ ++ TEST_COMPARE (system (":"), 0); ++ ++ return 0; ++} + +-#define TEST_FUNCTION do_test () +-#include "../test-skeleton.c" ++#include +diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c +index 8a51a6b9919ec39b..7db09a05c3fbca43 100644 +--- a/sysdeps/posix/system.c ++++ b/sysdeps/posix/system.c +@@ -97,7 +97,8 @@ cancel_handler (void *arg) + static int + do_system (const char *line) + { +- int status; ++ int status = -1; ++ int ret; + pid_t pid; + struct sigaction sa; + #ifndef _LIBC_REENTRANT +@@ -140,14 +141,14 @@ do_system (const char *line) + __posix_spawnattr_setflags (&spawn_attr, + POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK); + +- status = __posix_spawn (&pid, SHELL_PATH, 0, &spawn_attr, +- (char *const[]){ (char*) SHELL_NAME, +- (char*) "-c", +- (char *) line, NULL }, +- __environ); ++ ret = __posix_spawn (&pid, SHELL_PATH, 0, &spawn_attr, ++ (char *const[]){ (char *) SHELL_NAME, ++ (char *) "-c", ++ (char *) line, NULL }, ++ __environ); + __posix_spawnattr_destroy (&spawn_attr); + +- if (status == 0) ++ if (ret == 0) + { + /* Cancellation results in cleanup handlers running as exceptions in + the block where they were installed, so it is safe to reference +@@ -182,6 +183,9 @@ do_system (const char *line) + } + DO_UNLOCK (); + ++ if (ret != 0) ++ __set_errno (ret); ++ + return status; + } + diff --git a/glibc-rh2065588-5.patch b/glibc-rh2065588-5.patch new file mode 100644 index 0000000..368e759 --- /dev/null +++ b/glibc-rh2065588-5.patch @@ -0,0 +1,64 @@ +commit 7a7226543611897103c7483bec160547294dcf0d +Author: Alexandra Hájková +Date: Sat Dec 26 20:44:34 2020 +0100 + + Add xfchmod to libsupport + +diff --git a/support/Makefile b/support/Makefile +index d2b95539403e416c..4875f52495ef292d 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -91,6 +91,7 @@ libsupport-routines = \ + xdlfcn \ + xdlmopen \ + xdup2 \ ++ xfchmod \ + xfclose \ + xfopen \ + xfork \ +diff --git a/support/xfchmod.c b/support/xfchmod.c +new file mode 100644 +index 0000000000000000..4323b9ca8e078c98 +--- /dev/null ++++ b/support/xfchmod.c +@@ -0,0 +1,28 @@ ++/* fchmod with error checking. ++ Copyright (C) 2021 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++ ++void ++xfchmod (int fd, mode_t mode) ++{ ++ if (fchmod (fd, mode) != 0) ++ FAIL_EXIT1 ("fchmod (%d, 0%o): %m", fd, mode); ++} +diff --git a/support/xunistd.h b/support/xunistd.h +index 74fd2771d12c36fe..ced8cb1dd9ee356c 100644 +--- a/support/xunistd.h ++++ b/support/xunistd.h +@@ -45,6 +45,7 @@ long long xlseek (int fd, long long offset, int whence); + void xftruncate (int fd, long long length); + void xsymlink (const char *target, const char *linkpath); + void xchdir (const char *path); ++void xfchmod (int fd, mode_t mode); + + /* Equivalent of "mkdir -p". */ + void xmkdirp (const char *, mode_t); diff --git a/glibc-rh2065588-6.patch b/glibc-rh2065588-6.patch new file mode 100644 index 0000000..16fdb47 --- /dev/null +++ b/glibc-rh2065588-6.patch @@ -0,0 +1,56 @@ +commit 7b9c3260bcca73781dda6bc2ddee84869bedfb8c +Author: Adhemerval Zanella +Date: Mon Dec 14 11:42:33 2020 -0300 + + support: Add xchmod wrapper + + Checked on x86_64-linux-gnu. + +diff --git a/support/xchmod.c b/support/xchmod.c +new file mode 100644 +index 0000000000000000..5e403c7cc2705aef +--- /dev/null ++++ b/support/xchmod.c +@@ -0,0 +1,30 @@ ++/* chmod with error checking. ++ Copyright (C) 2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++ ++#include ++ ++void ++xchmod (const char *pathname, mode_t mode) ++{ ++ int r = chmod (pathname, mode); ++ if (r < 0) ++ FAIL_EXIT1 ("chmod (%s, %d): %m", pathname, mode); ++} +diff --git a/support/xunistd.h b/support/xunistd.h +index ced8cb1dd9ee356c..e92056c65efe8d6a 100644 +--- a/support/xunistd.h ++++ b/support/xunistd.h +@@ -46,6 +46,7 @@ void xftruncate (int fd, long long length); + void xsymlink (const char *target, const char *linkpath); + void xchdir (const char *path); + void xfchmod (int fd, mode_t mode); ++void xchmod (const char *pathname, mode_t mode); + + /* Equivalent of "mkdir -p". */ + void xmkdirp (const char *, mode_t); diff --git a/glibc-rh2065588-7.patch b/glibc-rh2065588-7.patch new file mode 100644 index 0000000..b16b79e --- /dev/null +++ b/glibc-rh2065588-7.patch @@ -0,0 +1,73 @@ +commit 4eda036f5b897fa8bc20ddd2099b5a6ed4239dc9 +Author: Adhemerval Zanella +Date: Tue Mar 24 15:48:34 2020 -0300 + + stdlib: Move tst-system to tests-container + + Fix some issues with different shell and error messages. + + Checked on x86_64-linux-gnu and i686-linux-gnu. + +diff --git a/stdlib/Makefile b/stdlib/Makefile +index 01194bbf7cc96851..9d0edcf6a7749b28 100644 +--- a/stdlib/Makefile ++++ b/stdlib/Makefile +@@ -70,7 +70,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ + test-canon test-canon2 tst-strtoll tst-environ \ + tst-xpg-basename tst-random tst-random2 tst-bsearch \ + tst-limits tst-rand48 bug-strtod tst-setcontext \ +- tst-setcontext2 test-a64l tst-qsort tst-system testmb2 \ ++ tst-setcontext2 test-a64l tst-qsort testmb2 \ + bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 \ + tst-rand48-2 tst-makecontext tst-strtod5 \ + tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1 \ +@@ -92,6 +92,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \ + tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \ + tst-tls-atexit tst-tls-atexit-nodelete + tests-static := tst-secure-getenv ++tests-container := tst-system + + ifeq ($(build-hardcoded-path-in-tests),yes) + tests += tst-empty-env +diff --git a/stdlib/tst-system.c b/stdlib/tst-system.c +index b61bd347df7ec46a..194e09828dd5c206 100644 +--- a/stdlib/tst-system.c ++++ b/stdlib/tst-system.c +@@ -88,7 +88,8 @@ do_test (void) + }); + support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr); + +- char *returnerr = xasprintf ("%s: 1: %s: not found\n", ++ char *returnerr = xasprintf ("%s: execing %s failed: " ++ "No such file or directory", + basename(_PATH_BSHELL), cmd); + TEST_COMPARE_STRING (result.err.buffer, returnerr); + free (returnerr); +@@ -106,7 +107,8 @@ do_test (void) + }); + support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr); + +- char *returnerr = xasprintf ("%s: 1: %s: File name too long\n", ++ char *returnerr = xasprintf ("%s: execing %s failed: " ++ "File name too long", + basename(_PATH_BSHELL), cmd); + TEST_COMPARE_STRING (result.err.buffer, returnerr); + free (returnerr); +@@ -116,7 +118,7 @@ do_test (void) + struct support_capture_subprocess result; + result = support_capture_subprocess (call_system, + &(struct args) { +- "kill -USR1 $$", 0, SIGUSR1 ++ "kill $$", 0, SIGTERM + }); + support_capture_subprocess_check (&result, "system", 0, sc_allow_none); + } +@@ -136,7 +138,7 @@ do_test (void) + support_capture_subprocess_check (&result, "system", 0, sc_allow_none); + } + +- TEST_COMPARE (system (":"), 0); ++ TEST_COMPARE (system (""), 0); + + return 0; + } diff --git a/glibc-rh2065588-8.patch b/glibc-rh2065588-8.patch new file mode 100644 index 0000000..102b72a --- /dev/null +++ b/glibc-rh2065588-8.patch @@ -0,0 +1,74 @@ +commit 42dda89dcb0407f6799dbfd0b9dab1529666ad51 +Author: Adhemerval Zanella +Date: Fri Dec 11 15:23:05 2020 -0300 + + posix: Fix return value of system if shell can not be executed [BZ #27053] + + POSIX states that system returned code for failure to execute the shell + shall be as if the shell had terminated using _exit(127). This + behaviour was removed with 5fb7fc96350575. + + Checked on x86_64-linux-gnu. + +diff --git a/stdlib/tst-system.c b/stdlib/tst-system.c +index 194e09828dd5c206..8681584f15ef3b47 100644 +--- a/stdlib/tst-system.c ++++ b/stdlib/tst-system.c +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + static char *tmpdir; + static long int namemax; +@@ -138,6 +139,22 @@ do_test (void) + support_capture_subprocess_check (&result, "system", 0, sc_allow_none); + } + ++ { ++ struct stat64 st; ++ xstat (_PATH_BSHELL, &st); ++ mode_t mode = st.st_mode; ++ xchmod (_PATH_BSHELL, mode & ~(S_IXUSR | S_IXGRP | S_IXOTH)); ++ ++ struct support_capture_subprocess result; ++ result = support_capture_subprocess (call_system, ++ &(struct args) { ++ "exit 1", 127, 0 ++ }); ++ support_capture_subprocess_check (&result, "system", 0, sc_allow_none); ++ ++ xchmod (_PATH_BSHELL, st.st_mode); ++ } ++ + TEST_COMPARE (system (""), 0); + + return 0; +diff --git a/support/Makefile b/support/Makefile +index 4875f52495ef292d..09b41b0d57e9239a 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -86,6 +86,7 @@ libsupport-routines = \ + xchroot \ + xclone \ + xclose \ ++ xchmod \ + xconnect \ + xcopy_file_range \ + xdlfcn \ +diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c +index 7db09a05c3fbca43..047ded4badfddcab 100644 +--- a/sysdeps/posix/system.c ++++ b/sysdeps/posix/system.c +@@ -171,6 +171,10 @@ do_system (const char *line) + __libc_cleanup_region_end (0); + #endif + } ++ else ++ /* POSIX states that failure to execute the shell should return ++ as if the shell had terminated using _exit(127). */ ++ status = W_EXITCODE (127, 0); + + DO_LOCK (); + if (SUB_REF () == 0) diff --git a/glibc-rh2065588-9.patch b/glibc-rh2065588-9.patch new file mode 100644 index 0000000..6d259d8 --- /dev/null +++ b/glibc-rh2065588-9.patch @@ -0,0 +1,21 @@ +commit 542160f0b6a7c26758c9575a8876f6624a5dd65f +Author: Girish Joshi +Date: Mon Mar 2 15:19:29 2020 -0500 + + Fixed typo in run_command_array() in support/shell-container.c + + https://sourceware.org/bugzilla/show_bug.cgi?id=23991 + +diff --git a/support/shell-container.c b/support/shell-container.c +index 9bd90d3f60529079..e87ac5cf1baa84e5 100644 +--- a/support/shell-container.c ++++ b/support/shell-container.c +@@ -228,7 +228,7 @@ run_command_array (char **argv) + if (new_stderr != 2) + { + dup2 (new_stderr, 2); +- close (new_stdout); ++ close (new_stderr); + } + + if (builtin_func != NULL) diff --git a/glibc-rh2073432.patch b/glibc-rh2071745.patch similarity index 100% rename from glibc-rh2073432.patch rename to glibc-rh2071745.patch diff --git a/glibc-rh2072329.patch b/glibc-rh2072329.patch new file mode 100644 index 0000000..e26331e --- /dev/null +++ b/glibc-rh2072329.patch @@ -0,0 +1,86 @@ +commit 33e03f9cd2be4f2cd62f93fda539cc07d9c8130e +Author: Joan Bruguera +Date: Mon Apr 11 19:49:56 2022 +0200 + + misc: Fix rare fortify crash on wchar funcs. [BZ 29030] + + If `__glibc_objsize (__o) == (size_t) -1` (i.e. `__o` is unknown size), fortify + checks should pass, and `__whatever_alias` should be called. + + Previously, `__glibc_objsize (__o) == (size_t) -1` was explicitly checked, but + on commit a643f60c53876b, this was moved into `__glibc_safe_or_unknown_len`. + + A comment says the -1 case should work as: "The -1 check is redundant because + since it implies that __glibc_safe_len_cond is true.". But this fails when: + * `__s > 1` + * `__osz == -1` (i.e. unknown size at compile time) + * `__l` is big enough + * `__l * __s <= __osz` can be folded to a constant + (I only found this to be true for `mbsrtowcs` and other functions in wchar2.h) + + In this case `__l * __s <= __osz` is false, and `__whatever_chk_warn` will be + called by `__glibc_fortify` or `__glibc_fortify_n` and crash the program. + + This commit adds the explicit `__osz == -1` check again. + moc crashes on startup due to this, see: https://bugs.archlinux.org/task/74041 + + Minimal test case (test.c): + #include + + int main (void) + { + const char *hw = "HelloWorld"; + mbsrtowcs (NULL, &hw, (size_t)-1, NULL); + return 0; + } + + Build with: + gcc -O2 -Wp,-D_FORTIFY_SOURCE=2 test.c -o test && ./test + + Output: + *** buffer overflow detected ***: terminated + + Fixes: BZ #29030 + Signed-off-by: Joan Bruguera + Signed-off-by: Siddhesh Poyarekar + +diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c +index 1668294e48b5c63c..701bffd1d664f289 100644 +--- a/debug/tst-fortify.c ++++ b/debug/tst-fortify.c +@@ -1505,6 +1505,11 @@ do_test (void) + CHK_FAIL_END + #endif + ++ /* Bug 29030 regresion check */ ++ cp = "HelloWorld"; ++ if (mbsrtowcs (NULL, &cp, (size_t)-1, &s) != 10) ++ FAIL (); ++ + cp = "A"; + if (mbstowcs (wenough, cp, 10) != 1 + || wcscmp (wenough, L"A") != 0) +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index a17ae0ed87e6163f..404496c7d6da4fb3 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -143,13 +143,13 @@ + || (__builtin_constant_p (__l) && (__l) > 0)) + + /* Length is known to be safe at compile time if the __L * __S <= __OBJSZ +- condition can be folded to a constant and if it is true. The -1 check is +- redundant because since it implies that __glibc_safe_len_cond is true. */ ++ condition can be folded to a constant and if it is true, or unknown (-1) */ + #define __glibc_safe_or_unknown_len(__l, __s, __osz) \ +- (__glibc_unsigned_or_positive (__l) \ +- && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ +- __s, __osz)) \ +- && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz)) ++ ((__osz) == (__SIZE_TYPE__) -1 \ ++ || (__glibc_unsigned_or_positive (__l) \ ++ && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ ++ (__s), (__osz))) \ ++ && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), (__s), (__osz)))) + + /* Conversely, we know at compile time that the length is unsafe if the + __L * __S <= __OBJSZ condition can be folded to a constant and if it is diff --git a/glibc-rh2077835.patch b/glibc-rh2077835.patch new file mode 100644 index 0000000..7323d49 --- /dev/null +++ b/glibc-rh2077835.patch @@ -0,0 +1,211 @@ +commit 2376944b9e5c0364b9fb473e4d8dabca31b57167 +Author: Stefan Liebler +Date: Wed Apr 13 14:36:09 2022 +0200 + + S390: Add new s390 platform z16. + + The new IBM z16 is added to platform string array. + The macro _DL_PLATFORMS_COUNT is incremented. + + _dl_hwcaps_subdir is extended by "z16" if HWCAP_S390_VXRS_PDE2 + is set. HWCAP_S390_NNPA is not tested in _dl_hwcaps_subdirs_active + as those instructions may be replaced or removed in future. + + tst-glibc-hwcaps.c is extended in order to test z16 via new marker5. + + A fatal glibc error is dumped if glibc was build with architecture + level set for z16, but run on an older machine. (See dl-hwcap-check.h) + +Reworked for RHEL 8.7.0 + +diff -Nrup a/elf/Makefile b/elf/Makefile +--- a/elf/Makefile 2022-05-16 21:48:11.267916411 -0400 ++++ b/elf/Makefile 2022-05-16 21:48:56.106095151 -0400 +@@ -347,7 +347,8 @@ modules-names = testobj1 testobj2 testob + libmarkermod2-1 libmarkermod2-2 \ + libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \ + libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \ +- tst-tls20mod-bad tst-tls21mod \ ++ libmarkermod5-1 libmarkermod5-2 libmarkermod5-3 libmarkermod5-4 \ ++ libmarkermod5-5 tst-tls20mod-bad tst-tls21mod \ + + # Most modules build with _ISOMAC defined, but those filtered out + # depend on internal headers. +@@ -1782,6 +1783,7 @@ LDFLAGS-libmarkermod1-1.so += -Wl,-sonam + LDFLAGS-libmarkermod2-1.so += -Wl,-soname,libmarkermod2.so + LDFLAGS-libmarkermod3-1.so += -Wl,-soname,libmarkermod3.so + LDFLAGS-libmarkermod4-1.so += -Wl,-soname,libmarkermod4.so ++LDFLAGS-libmarkermod5-1.so += -Wl,-soname,libmarkermod5.so + $(objpfx)libmarkermod%.os : markermodMARKER-VALUE.c + $(compile-command.c) \ + -DMARKER=marker$(firstword $(subst -, ,$*)) \ +@@ -1794,6 +1796,8 @@ $(objpfx)libmarkermod3.so: $(objpfx)libm + cp $< $@ + $(objpfx)libmarkermod4.so: $(objpfx)libmarkermod4-1.so + cp $< $@ ++$(objpfx)libmarkermod5.so: $(objpfx)libmarkermod5-1.so ++ cp $< $@ + + # tst-glibc-hwcaps-prepend checks that --glibc-hwcaps-prepend is + # preferred over auto-detected subdirectories. +diff -Nrup a/elf/tst-glibc-hwcaps-cache.script b/elf/tst-glibc-hwcaps-cache.script +--- a/elf/tst-glibc-hwcaps-cache.script 2022-05-16 21:48:11.053915558 -0400 ++++ b/elf/tst-glibc-hwcaps-cache.script 2022-05-16 21:48:56.107095155 -0400 +@@ -4,6 +4,7 @@ + cp $B/elf/libmarkermod2-1.so $L/libmarkermod2.so + cp $B/elf/libmarkermod3-1.so $L/libmarkermod3.so + cp $B/elf/libmarkermod4-1.so $L/libmarkermod4.so ++cp $B/elf/libmarkermod5-1.so $L/libmarkermod5.so + + mkdirp 0770 $L/glibc-hwcaps/power9 + cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/power9/libmarkermod2.so +@@ -20,6 +21,11 @@ mkdirp 0770 $L/glibc-hwcaps/z15 + cp $B/elf/libmarkermod4-2.so $L/glibc-hwcaps/z13/libmarkermod4.so + cp $B/elf/libmarkermod4-3.so $L/glibc-hwcaps/z14/libmarkermod4.so + cp $B/elf/libmarkermod4-4.so $L/glibc-hwcaps/z15/libmarkermod4.so ++mkdirp 0770 $L/glibc-hwcaps/z16 ++cp $B/elf/libmarkermod5-2.so $L/glibc-hwcaps/z13/libmarkermod5.so ++cp $B/elf/libmarkermod5-3.so $L/glibc-hwcaps/z14/libmarkermod5.so ++cp $B/elf/libmarkermod5-4.so $L/glibc-hwcaps/z15/libmarkermod5.so ++cp $B/elf/libmarkermod5-5.so $L/glibc-hwcaps/z16/libmarkermod5.so + + mkdirp 0770 $L/glibc-hwcaps/x86-64-v2 + cp $B/elf/libmarkermod2-2.so $L/glibc-hwcaps/x86-64-v2/libmarkermod2.so +diff -Nrup a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c +--- a/sysdeps/s390/dl-procinfo.c 2022-05-16 21:48:11.250916343 -0400 ++++ b/sysdeps/s390/dl-procinfo.c 2022-05-16 21:48:56.107095155 -0400 +@@ -64,11 +64,12 @@ PROCINFO_CLASS const char _dl_s390_cap_f + #if !defined PROCINFO_DECL && defined SHARED + ._dl_s390_platforms + #else +-PROCINFO_CLASS const char _dl_s390_platforms[10][7] ++PROCINFO_CLASS const char _dl_s390_platforms[11][7] + #endif + #ifndef PROCINFO_DECL + = { +- "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14", "z15" ++ "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14", "z15", ++ "z16" + } + #endif + #if !defined SHARED || defined PROCINFO_DECL +diff -Nrup a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h +--- a/sysdeps/s390/dl-procinfo.h 2022-05-16 21:48:11.250916343 -0400 ++++ b/sysdeps/s390/dl-procinfo.h 2022-05-16 21:48:56.107095155 -0400 +@@ -23,7 +23,7 @@ + + #define _DL_HWCAP_COUNT 23 + +-#define _DL_PLATFORMS_COUNT 10 ++#define _DL_PLATFORMS_COUNT 11 + + /* The kernel provides up to 32 capability bits with elf_hwcap. */ + #define _DL_FIRST_PLATFORM 32 +diff -Nrup a/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c b/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c +--- a/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c 2022-05-16 21:48:11.053915558 -0400 ++++ b/sysdeps/s390/s390-64/dl-hwcaps-subdirs.c 2022-05-16 21:58:02.840301911 -0400 +@@ -19,8 +19,8 @@ + #include + #include + +-const char _dl_hwcaps_subdirs[] = "z15:z14:z13"; +-enum { subdirs_count = 3 }; /* Number of components in _dl_hwcaps_subdirs. */ ++const char _dl_hwcaps_subdirs[] = "z16:z15:z14:z13"; ++enum { subdirs_count = 4 }; /* Number of components in _dl_hwcaps_subdirs. */ + + uint32_t + _dl_hwcaps_subdirs_active (void) +@@ -50,5 +50,12 @@ _dl_hwcaps_subdirs_active (void) + return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); + ++active; + ++ /* z16. ++ Note: We do not list HWCAP_S390_NNPA here as, according to the Principles of ++ Operation, those instructions may be replaced or removed in future. */ ++ if (!(GLRO (dl_hwcap) & HWCAP_S390_VXRS_PDE2)) ++ return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); ++ ++active; ++ + return _dl_hwcaps_subdirs_build_bitmask (subdirs_count, active); + } +diff -Nrup a/sysdeps/s390/s390-64/Makefile b/sysdeps/s390/s390-64/Makefile +--- a/sysdeps/s390/s390-64/Makefile 2022-05-16 21:48:11.053915558 -0400 ++++ b/sysdeps/s390/s390-64/Makefile 2022-05-16 21:54:08.832355745 -0400 +@@ -7,8 +7,11 @@ CFLAGS-rtld.c += -Wno-uninitialized -Wno + CFLAGS-dl-load.c += -Wno-unused + CFLAGS-dl-reloc.c += -Wno-unused + +-$(objpfx)tst-glibc-hwcaps: $(objpfx)libmarkermod2-1.so \ +- $(objpfx)libmarkermod3-1.so $(objpfx)libmarkermod4-1.so ++$(objpfx)tst-glibc-hwcaps: \ ++ $(objpfx)libmarkermod2-1.so \ ++ $(objpfx)libmarkermod3-1.so \ ++ $(objpfx)libmarkermod4-1.so \ ++ $(objpfx)libmarkermod5-1.so + $(objpfx)tst-glibc-hwcaps.out: \ + $(objpfx)libmarkermod2.so \ + $(objpfx)glibc-hwcaps/z13/libmarkermod2.so \ +@@ -19,6 +22,11 @@ $(objpfx)tst-glibc-hwcaps.out: \ + $(objpfx)glibc-hwcaps/z13/libmarkermod4.so \ + $(objpfx)glibc-hwcaps/z14/libmarkermod4.so \ + $(objpfx)glibc-hwcaps/z15/libmarkermod4.so \ ++ $(objpfx)libmarkermod5.so \ ++ $(objpfx)glibc-hwcaps/z13/libmarkermod5.so \ ++ $(objpfx)glibc-hwcaps/z14/libmarkermod5.so \ ++ $(objpfx)glibc-hwcaps/z15/libmarkermod5.so \ ++ $(objpfx)glibc-hwcaps/z16/libmarkermod5.so + + $(objpfx)glibc-hwcaps/z13/libmarkermod2.so: $(objpfx)libmarkermod2-2.so + $(make-target-directory) +@@ -38,6 +46,18 @@ $(objpfx)glibc-hwcaps/z14/libmarkermod4. + $(objpfx)glibc-hwcaps/z15/libmarkermod4.so: $(objpfx)libmarkermod4-4.so + $(make-target-directory) + cp $< $@ ++$(objpfx)glibc-hwcaps/z13/libmarkermod5.so: $(objpfx)libmarkermod5-2.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/z14/libmarkermod5.so: $(objpfx)libmarkermod5-3.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/z15/libmarkermod5.so: $(objpfx)libmarkermod5-4.so ++ $(make-target-directory) ++ cp $< $@ ++$(objpfx)glibc-hwcaps/z16/libmarkermod5.so: $(objpfx)libmarkermod5-5.so ++ $(make-target-directory) ++ cp $< $@ + + ifeq (no,$(build-hardcoded-path-in-tests)) + # This is an ld.so.cache test, and RPATH/RUNPATH in the executable +diff -Nrup a/sysdeps/s390/s390-64/tst-glibc-hwcaps.c b/sysdeps/s390/s390-64/tst-glibc-hwcaps.c +--- a/sysdeps/s390/s390-64/tst-glibc-hwcaps.c 2022-05-16 21:48:11.053915558 -0400 ++++ b/sysdeps/s390/s390-64/tst-glibc-hwcaps.c 2022-05-16 21:48:56.107095155 -0400 +@@ -25,6 +25,7 @@ + extern int marker2 (void); + extern int marker3 (void); + extern int marker4 (void); ++extern int marker5 (void); + + /* Return the arch level, 10 for the baseline libmarkermod*.so's. */ + static int +@@ -63,9 +64,13 @@ compute_level (void) + return 12; + if (strcmp (platform, "z15") == 0) + return 13; ++ if (strcmp (platform, "z16") == 0) ++ return 14; + printf ("warning: unrecognized AT_PLATFORM value: %s\n", platform); + /* Assume that the new platform supports z15. */ + return 13; ++ /* Assume that the new platform supports z16. */ ++ return 14; + } + + static int +@@ -76,6 +81,7 @@ do_test (void) + TEST_COMPARE (marker2 (), MIN (level - 9, 2)); + TEST_COMPARE (marker3 (), MIN (level - 9, 3)); + TEST_COMPARE (marker4 (), MIN (level - 9, 4)); ++ TEST_COMPARE (marker5 (), MIN (level - 9, 5)); + return 0; + } + diff --git a/glibc-rh2080349-1.patch b/glibc-rh2080349-1.patch new file mode 100644 index 0000000..0bc7524 --- /dev/null +++ b/glibc-rh2080349-1.patch @@ -0,0 +1,37 @@ +commit 4a7c342605bc653f72d60c36abe698986fb5cb47 +Author: Joseph Myers +Date: Wed Apr 28 17:19:24 2021 +0000 + + Update syscall lists for Linux 5.12. + + Linux 5.12 has one new syscall, mount_setattr. Update + syscall-names.list and regenerate the arch-syscall.h headers with + build-many-glibcs.py update-syscalls. + + Tested with build-many-glibcs.py. + +Modified to only update syscall-names.list to Linux 5.12. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index f6cb34089d..8e3cfa0e77 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.11. +-kernel 5.11 ++# The list of system calls is current as of Linux 5.12. ++kernel 5.12 + + FAST_atomic_update + FAST_cmpxchg +@@ -258,6 +258,7 @@ mmap + mmap2 + modify_ldt + mount ++mount_setattr + move_mount + move_pages + mprotect diff --git a/glibc-rh2080349-2.patch b/glibc-rh2080349-2.patch new file mode 100644 index 0000000..6084110 --- /dev/null +++ b/glibc-rh2080349-2.patch @@ -0,0 +1,40 @@ +commit b1b4f7209ecaad4bf9a5d0d2ef1338409d364bac +Author: Joseph Myers +Date: Thu Jul 1 17:37:36 2021 +0000 + + Update syscall lists for Linux 5.13 + + Linux 5.13 has three new syscalls (landlock_create_ruleset, + landlock_add_rule, landlock_restrict_self). Update syscall-names.list + and regenerate the arch-syscall.h headers with build-many-glibcs.py + update-syscalls. + + Tested with build-many-glibcs.py. + +Modified to only update syscall-names.list to Linux 5.13. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 8e3cfa0e77..89c5895b9b 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.12. +-kernel 5.12 ++# The list of system calls is current as of Linux 5.13. ++kernel 5.13 + + FAST_atomic_update + FAST_cmpxchg +@@ -224,6 +224,9 @@ kexec_file_load + kexec_load + keyctl + kill ++landlock_add_rule ++landlock_create_ruleset ++landlock_restrict_self + lchown + lchown32 + lgetxattr diff --git a/glibc-rh2080349-3.patch b/glibc-rh2080349-3.patch new file mode 100644 index 0000000..7293e03 --- /dev/null +++ b/glibc-rh2080349-3.patch @@ -0,0 +1,45 @@ +commit 89dc0372a9055e7ef86fe19be6201fa0b16b2f0e +Author: Joseph Myers +Date: Wed Sep 8 12:42:06 2021 +0000 + + Update syscall lists for Linux 5.14 + + Linux 5.14 has two new syscalls, memfd_secret (on some architectures + only) and quotactl_fd. Update syscall-names.list and regenerate the + arch-syscall.h headers with build-many-glibcs.py update-syscalls. + + Tested with build-many-glibcs.py. + +Modified to only update syscall-names.list to Linux 5.14. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 89c5895b9b..fd98893b0e 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.13. +-kernel 5.13 ++# The list of system calls is current as of Linux 5.14. ++kernel 5.14 + + FAST_atomic_update + FAST_cmpxchg +@@ -247,6 +247,7 @@ madvise + mbind + membarrier + memfd_create ++memfd_secret + memory_ordering + migrate_pages + mincore +@@ -452,6 +453,7 @@ pwritev + pwritev2 + query_module + quotactl ++quotactl_fd + read + readahead + readdir diff --git a/glibc-rh2080349-4.patch b/glibc-rh2080349-4.patch new file mode 100644 index 0000000..205b903 --- /dev/null +++ b/glibc-rh2080349-4.patch @@ -0,0 +1,43 @@ +commit 3387c40a8bbad5faf85b1feb56429cb20feaa640 +Author: Joseph Myers +Date: Wed Nov 10 15:21:19 2021 +0000 + + Update syscall lists for Linux 5.15 + + Linux 5.15 has one new syscall, process_mrelease (and also enables the + clone3 syscall for RV32). It also has a macro __NR_SYSCALL_MASK for + Arm, which is not a syscall but matches the pattern used for syscall + macro names. + + Add __NR_SYSCALL_MASK to the names filtered out in the code dealing + with syscall lists, update syscall-names.list for the new syscall and + regenerate the arch-syscall.h headers with build-many-glibcs.py + update-syscalls. + + Tested with build-many-glibcs.py. + +Modified to only update syscall-names.list to Linux 5.15. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index fd98893b0e..1a74d090b7 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.14. +-kernel 5.14 ++# The list of system calls is current as of Linux 5.15. ++kernel 5.15 + + FAST_atomic_update + FAST_cmpxchg +@@ -440,6 +440,7 @@ preadv + preadv2 + prlimit64 + process_madvise ++process_mrelease + process_vm_readv + process_vm_writev + prof diff --git a/glibc-rh2080349-5.patch b/glibc-rh2080349-5.patch new file mode 100644 index 0000000..b042917 --- /dev/null +++ b/glibc-rh2080349-5.patch @@ -0,0 +1,37 @@ +commit 4997a533ae4b51ef66a6b68862b7578a7acb82df +Author: Joseph Myers +Date: Thu Jan 13 22:18:13 2022 +0000 + + Update syscall lists for Linux 5.16 + + Linux 5.16 has one new syscall, futex_waitv. Update + syscall-names.list and regenerate the arch-syscall.h headers with + build-many-glibcs.py update-syscalls. + + Tested with build-many-glibcs.py. + +Modified to only update syscall-names.list to Linux 5.16. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index c80a9a59cb..6421806110 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.15. +-kernel 5.15 ++# The list of system calls is current as of Linux 5.16. ++kernel 5.16 + + FAST_atomic_update + FAST_cmpxchg +@@ -146,6 +146,7 @@ ftruncate + ftruncate64 + futex + futex_time64 ++futex_waitv + futimesat + get_kernel_syms + get_mempolicy diff --git a/glibc-rh2080349-6.patch b/glibc-rh2080349-6.patch new file mode 100644 index 0000000..333f362 --- /dev/null +++ b/glibc-rh2080349-6.patch @@ -0,0 +1,37 @@ +commit 8ef9196b26793830515402ea95aca2629f7721ec +Author: Joseph Myers +Date: Wed Mar 23 17:11:56 2022 +0000 + + Update syscall lists for Linux 5.17 + + Linux 5.17 has one new syscall, set_mempolicy_home_node. Update + syscall-names.list and regenerate the arch-syscall.h headers with + build-many-glibcs.py update-syscalls. + + Tested with build-many-glibcs.py. + +Modified to only update syscall-names.list to Linux 5.17. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 6421806110..b8c0b0c586 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.16. +-kernel 5.16 ++# The list of system calls is current as of Linux 5.17. ++kernel 5.17 + + FAST_atomic_update + FAST_cmpxchg +@@ -524,6 +524,7 @@ sendmmsg + sendmsg + sendto + set_mempolicy ++set_mempolicy_home_node + set_robust_list + set_thread_area + set_tid_address diff --git a/glibc-rh2080349-7.patch b/glibc-rh2080349-7.patch new file mode 100644 index 0000000..067f10e --- /dev/null +++ b/glibc-rh2080349-7.patch @@ -0,0 +1,28 @@ +commit 3d9926663cba19f40d26d8a8ab3b2a7cc09ffb13 +Author: Joseph Myers +Date: Wed May 25 14:37:28 2022 +0000 + + Update syscall-names.list for Linux 5.18 + + Linux 5.18 has no new syscalls. Update the version number in + syscall-names.list to reflect that it is still current for 5.18. + + Tested with build-many-glibcs.py. + +Modified to only update syscall-names.list to Linux 5.18. + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index b8c0b0c586..6c7b2f7011 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.17. +-kernel 5.17 ++# The list of system calls is current as of Linux 5.18. ++kernel 5.18 + + FAST_atomic_update + FAST_cmpxchg diff --git a/glibc-rh2080349-8.patch b/glibc-rh2080349-8.patch new file mode 100644 index 0000000..5e6fa9f --- /dev/null +++ b/glibc-rh2080349-8.patch @@ -0,0 +1,20 @@ +commit 9dde3a24f132090fa8f88d6eaa2bc4c48f2e942f +Author: Stafford Horne +Date: Sat May 23 12:41:31 2020 +0900 + + linux/syscalls: Add or1k_atomic syscall for OpenRISC + + Reviewed-by: Adhemerval Zanella + +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index 42701ce583..c80a9a59cb 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -304,6 +304,7 @@ open_by_handle_at + open_tree + openat + openat2 ++or1k_atomic + osf_adjtime + osf_afs_syscall + osf_alt_plock diff --git a/glibc-rh2080349-9.patch b/glibc-rh2080349-9.patch new file mode 100644 index 0000000..080811e --- /dev/null +++ b/glibc-rh2080349-9.patch @@ -0,0 +1,10 @@ +diff -Nrup a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +--- a/sysdeps/unix/sysv/linux/syscall-names.list 2022-07-18 10:44:38.791332453 -0400 ++++ b/sysdeps/unix/sysv/linux/syscall-names.list 2022-07-18 11:02:51.054663735 -0400 +@@ -1,5 +1,5 @@ + # List of all known Linux system calls. +-# Copyright (C) 2017-2021 Free Software Foundation, Inc. ++# Copyright (C) 2017-2022 Free Software Foundation, Inc. + # This file is part of the GNU C Library. + # + # The GNU C Library is free software; you can redistribute it and/or diff --git a/glibc-rh2086853.patch b/glibc-rh2086853.patch new file mode 100644 index 0000000..d11e4cb --- /dev/null +++ b/glibc-rh2086853.patch @@ -0,0 +1,30 @@ +commit 61a87530108ec9181e1b18a9b727ec3cc3ba7532 +Author: Siddhesh Poyarekar +Date: Fri May 13 10:01:47 2022 +0530 + + fortify: Ensure that __glibc_fortify condition is a constant [BZ #29141] + + The fix c8ee1c85 introduced a -1 check for object size without also + checking that object size is a constant. Because of this, the tree + optimizer passes in gcc fail to fold away one of the branches in + __glibc_fortify and trips on a spurious Wstringop-overflow. The warning + itself is incorrect and the branch does go away eventually in DCE in the + rtl passes in gcc, but the constant check is a helpful hint to simplify + code early, so add it in. + + Resolves: BZ #29141 + Signed-off-by: Siddhesh Poyarekar + +diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h +index 404496c7d6da4fb3..f3d7efdd2a9320f7 100644 +--- a/misc/sys/cdefs.h ++++ b/misc/sys/cdefs.h +@@ -145,7 +145,7 @@ + /* Length is known to be safe at compile time if the __L * __S <= __OBJSZ + condition can be folded to a constant and if it is true, or unknown (-1) */ + #define __glibc_safe_or_unknown_len(__l, __s, __osz) \ +- ((__osz) == (__SIZE_TYPE__) -1 \ ++ ((__builtin_constant_p (__osz) && (__osz) == (__SIZE_TYPE__) -1) \ + || (__glibc_unsigned_or_positive (__l) \ + && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \ + (__s), (__osz))) \ diff --git a/glibc-rh2093457-1.patch b/glibc-rh2089247-1.patch similarity index 100% rename from glibc-rh2093457-1.patch rename to glibc-rh2089247-1.patch diff --git a/glibc-rh2093457-2.patch b/glibc-rh2089247-2.patch similarity index 100% rename from glibc-rh2093457-2.patch rename to glibc-rh2089247-2.patch diff --git a/glibc-rh2093457-3.patch b/glibc-rh2089247-3.patch similarity index 100% rename from glibc-rh2093457-3.patch rename to glibc-rh2089247-3.patch diff --git a/glibc-rh2093457-4.patch b/glibc-rh2089247-4.patch similarity index 100% rename from glibc-rh2093457-4.patch rename to glibc-rh2089247-4.patch diff --git a/glibc-rh2093457-5.patch b/glibc-rh2089247-5.patch similarity index 100% rename from glibc-rh2093457-5.patch rename to glibc-rh2089247-5.patch diff --git a/glibc-rh2093457-6.patch b/glibc-rh2089247-6.patch similarity index 100% rename from glibc-rh2093457-6.patch rename to glibc-rh2089247-6.patch diff --git a/glibc-rh2094540.patch b/glibc-rh2091553.patch similarity index 100% rename from glibc-rh2094540.patch rename to glibc-rh2091553.patch diff --git a/glibc-rh2096189-1.patch b/glibc-rh2096189-1.patch new file mode 100644 index 0000000..33cc310 --- /dev/null +++ b/glibc-rh2096189-1.patch @@ -0,0 +1,67 @@ +commit 62a321b12d0e397af88fa422db65079332f971dc +Author: Florian Weimer +Date: Fri Jun 24 18:16:41 2022 +0200 + + support: Change non-address output format of support_format_dns_packet + + It makes sense to include the owner name (LHS) and record type in the + output, so that they can be checked for correctness. + + Reviewed-by: Carlos O'Donell + +diff --git a/support/support_format_dns_packet.c b/support/support_format_dns_packet.c +index 1170eafb0f008fee..ef862bc4c8d14af0 100644 +--- a/support/support_format_dns_packet.c ++++ b/support/support_format_dns_packet.c +@@ -101,6 +101,17 @@ extract_name (struct in_buffer full, struct in_buffer *in, struct dname *value) + return true; + } + ++static void ++extract_name_data (struct in_buffer full, struct in_buffer *rdata, ++ const struct dname *owner, const char *typename, FILE *out) ++{ ++ struct dname name; ++ if (extract_name (full, rdata, &name)) ++ fprintf (out, "data: %s %s %s\n", owner->name, typename, name.name); ++ else ++ fprintf (out, "error: malformed CNAME/PTR record\n"); ++} ++ + char * + support_format_dns_packet (const unsigned char *buffer, size_t length) + { +@@ -206,14 +217,11 @@ support_format_dns_packet (const unsigned char *buffer, size_t length) + } + break; + case T_CNAME: ++ extract_name_data (full, &rdata, &rname, "CNAME", mem.out); ++ break; + case T_PTR: +- { +- struct dname name; +- if (extract_name (full, &rdata, &name)) +- fprintf (mem.out, "name: %s\n", name.name); +- else +- fprintf (mem.out, "error: malformed CNAME/PTR record\n"); +- } ++ extract_name_data (full, &rdata, &rname, "PTR", mem.out); ++ break; + } + } + +diff --git a/support/tst-support_format_dns_packet.c b/support/tst-support_format_dns_packet.c +index b1135eebc6c02d55..35f475fe86177772 100644 +--- a/support/tst-support_format_dns_packet.c ++++ b/support/tst-support_format_dns_packet.c +@@ -85,8 +85,8 @@ test_multiple_cnames (void) + "\xc0\x00\x02\x01"; + check_packet (packet, sizeof (packet) - 1, __func__, + "name: www.example\n" +- "name: www1.example\n" +- "name: www2.example\n" ++ "data: www.example CNAME www1.example\n" ++ "data: www1.example CNAME www2.example\n" + "address: 192.0.2.1\n"); + } + diff --git a/glibc-rh2096189-2.patch b/glibc-rh2096189-2.patch new file mode 100644 index 0000000..201f089 --- /dev/null +++ b/glibc-rh2096189-2.patch @@ -0,0 +1,957 @@ +commit f282cdbe7f436c75864e5640a409a10485e9abb2 +Author: Florian Weimer +Date: Fri Jun 24 18:16:41 2022 +0200 + + resolv: Implement no-aaaa stub resolver option + + Reviewed-by: Carlos O'Donell + +Conflicts: + resolv/Makefile + (missing partial libresolv integration downstream) + resolv/res-noaaaa.c + (call ns_name_skip instead of __ns_name_skip (not available + downstream) and ns_name_unpack instead of __ns_name_unpack + (avoid PLT)) + resolv/res_debug.c + resolv/res_init.c + resolv/resolv.h + resolv/tst-resolv-res_init-skeleton.c + (missing trust-ad support downstream) + +diff --git a/resolv/Makefile b/resolv/Makefile +index cee5225f8933f245..ab8ad49b5318ad41 100644 +--- a/resolv/Makefile ++++ b/resolv/Makefile +@@ -57,6 +57,7 @@ tests += \ + tst-resolv-binary \ + tst-resolv-edns \ + tst-resolv-network \ ++ tst-resolv-noaaaa \ + tst-resolv-nondecimal \ + tst-resolv-res_init-multi \ + tst-resolv-search \ +@@ -110,7 +111,7 @@ libresolv-routines := res_comp res_debug \ + res_data res_mkquery res_query res_send \ + inet_net_ntop inet_net_pton inet_neta base64 \ + ns_parse ns_name ns_netint ns_ttl ns_print \ +- ns_samedomain ns_date res_enable_icmp \ ++ ns_samedomain ns_date res_enable_icmp res-noaaaa \ + compat-hooks compat-gethnamaddr + + libanl-routines := gai_cancel gai_error gai_misc gai_notify gai_suspend \ +@@ -200,6 +201,7 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \ + $(shared-thread-library) + $(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \ + $(shared-thread-library) ++$(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library) + $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library) +diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c +index 99c3b61e1cee4d42..ff0a0b6f7f1f4703 100644 +--- a/resolv/nss_dns/dns-host.c ++++ b/resolv/nss_dns/dns-host.c +@@ -123,6 +123,14 @@ static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp); ++static enum nss_status gaih_getanswer_noaaaa (const querybuf *answer1, ++ int anslen1, ++ const char *qname, ++ struct gaih_addrtuple **pat, ++ char *buffer, size_t buflen, ++ int *errnop, int *h_errnop, ++ int32_t *ttlp); ++ + + static enum nss_status gethostbyname3_context (struct resolv_context *ctx, + const char *name, int af, +@@ -367,17 +375,31 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, + int resplen2 = 0; + int ans2p_malloced = 0; + ++ + int olderr = errno; +- int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA, ++ int n; ++ ++ if ((ctx->resp->options & RES_NOAAAA) == 0) ++ { ++ n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA, + host_buffer.buf->buf, 2048, &host_buffer.ptr, + &ans2p, &nans2p, &resplen2, &ans2p_malloced); +- if (n >= 0) +- { +- status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p, +- resplen2, name, pat, buffer, buflen, +- errnop, herrnop, ttlp); ++ if (n >= 0) ++ status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p, ++ resplen2, name, pat, buffer, buflen, ++ errnop, herrnop, ttlp); + } + else ++ { ++ n = __res_context_search (ctx, name, C_IN, T_A, ++ host_buffer.buf->buf, 2048, NULL, ++ NULL, NULL, NULL, NULL); ++ if (n >= 0) ++ status = gaih_getanswer_noaaaa (host_buffer.buf, n, ++ name, pat, buffer, buflen, ++ errnop, herrnop, ttlp); ++ } ++ if (n < 0) + { + switch (errno) + { +@@ -1386,3 +1408,21 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2, + + return status; + } ++ ++/* Variant of gaih_getanswer without a second (AAAA) response. */ ++static enum nss_status ++gaih_getanswer_noaaaa (const querybuf *answer1, int anslen1, const char *qname, ++ struct gaih_addrtuple **pat, ++ char *buffer, size_t buflen, ++ int *errnop, int *h_errnop, int32_t *ttlp) ++{ ++ int first = 1; ++ ++ enum nss_status status = NSS_STATUS_NOTFOUND; ++ if (anslen1 > 0) ++ status = gaih_getanswer_slice (answer1, anslen1, qname, ++ &pat, &buffer, &buflen, ++ errnop, h_errnop, ttlp, ++ &first); ++ return status; ++} +diff --git a/resolv/res-noaaaa.c b/resolv/res-noaaaa.c +new file mode 100644 +index 0000000000000000..e2a13cf38a74c160 +--- /dev/null ++++ b/resolv/res-noaaaa.c +@@ -0,0 +1,143 @@ ++/* Implement suppression of AAAA queries. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* Returns true if the question type at P matches EXPECTED, and the ++ class is IN. */ ++static bool ++qtype_matches (const unsigned char *p, int expected) ++{ ++ /* This assumes that T_A/C_IN constants are less than 256, which ++ they are. */ ++ return p[0] == 0 && p[1] == expected && p[2] == 0 && p[3] == C_IN; ++} ++ ++/* Handle RES_NOAAAA translation of AAAA queries. To produce a Name ++ Error (NXDOMAIN) repsonse for domain names that do not exist, it is ++ still necessary to send a query. Using question type A is a ++ conservative choice. In the returned answer, it is necessary to ++ switch back the question type to AAAA. */ ++bool ++__res_handle_no_aaaa (struct resolv_context *ctx, ++ const unsigned char *buf, int buflen, ++ unsigned char *ans, int anssiz, int *result) ++{ ++ /* AAAA mode is not active, or the query looks invalid (will not be ++ able to be parsed). */ ++ if ((ctx->resp->options & RES_NOAAAA) == 0 ++ || buflen <= sizeof (HEADER)) ++ return false; ++ ++ /* The replacement A query is produced here. */ ++ struct ++ { ++ HEADER header; ++ unsigned char question[NS_MAXCDNAME + 4]; ++ } replacement; ++ memcpy (&replacement.header, buf, sizeof (replacement.header)); ++ ++ if (replacement.header.qr ++ || replacement.header.opcode != 0 ++ || replacement.header.rcode != 0 ++ || ntohs (replacement.header.qdcount) != 1 ++ || ntohs (replacement.header.ancount) != 0 ++ || ntohs (replacement.header.nscount) != 0) ++ /* Not a well-formed question. Let the core resolver code produce ++ the proper error. */ ++ return false; ++ ++ /* Disable EDNS0. */ ++ replacement.header.arcount = htons (0); ++ ++ /* Extract the QNAME. */ ++ int ret = ns_name_unpack (buf, buf + buflen, buf + sizeof (HEADER), ++ replacement.question, NS_MAXCDNAME); ++ if (ret < 0) ++ /* Format error. */ ++ return false; ++ ++ /* Compute the end of the question name. */ ++ const unsigned char *after_question = buf + sizeof (HEADER) + ret; ++ ++ /* Check that we are dealing with an AAAA query. */ ++ if (buf + buflen - after_question < 4 ++ || !qtype_matches (after_question, T_AAAA)) ++ return false; ++ ++ /* Find the place to store the type/class data in the replacement ++ query. */ ++ after_question = replacement.question; ++ /* This cannot fail because ns_name_unpack above produced a valid ++ domain name. */ ++ (void) ns_name_skip (&after_question, &replacement.question[NS_MAXCDNAME]); ++ unsigned char *start_of_query = (unsigned char *) &replacement; ++ const unsigned char *end_of_query = after_question + 4; ++ ++ /* Produce an A/IN query. */ ++ { ++ unsigned char *p = (unsigned char *) after_question; ++ p[0] = 0; ++ p[1] = T_A; ++ p[2] = 0; ++ p[3] = C_IN; ++ } ++ ++ /* Clear the output buffer, to avoid reading undefined data when ++ rewriting the result from A to AAAA. */ ++ memset (ans, 0, anssiz); ++ ++ /* Always perform the message translation, independent of the error ++ code. */ ++ ret = __res_context_send (ctx, ++ start_of_query, end_of_query - start_of_query, ++ NULL, 0, ans, anssiz, ++ NULL, NULL, NULL, NULL, NULL); ++ ++ /* Patch in the AAAA question type if there is room and the A query ++ type was received. */ ++ after_question = ans + sizeof (HEADER); ++ if (ns_name_skip (&after_question, ans + anssiz) == 0 ++ && ans + anssiz - after_question >= 4 ++ && qtype_matches (after_question, T_A)) ++ { ++ ((unsigned char *) after_question)[1] = T_AAAA; ++ ++ /* Create an aligned copy of the header. Hide all data except ++ the question from the response. Put back the header. There is ++ no need to change the response code. The zero answer count turns ++ a positive response with data into a no-data response. */ ++ memcpy (&replacement.header, ans, sizeof (replacement.header)); ++ replacement.header.ancount = htons (0); ++ replacement.header.nscount = htons (0); ++ replacement.header.arcount = htons (0); ++ memcpy (ans, &replacement.header, sizeof (replacement.header)); ++ ++ /* Truncate the reply. */ ++ if (ret <= 0) ++ *result = ret; ++ else ++ *result = after_question - ans + 4; ++ } ++ ++ return true; ++} +diff --git a/resolv/res_debug.c b/resolv/res_debug.c +index 7681ad4639d8a7bc..43b3b1bfe4afdcaf 100644 +--- a/resolv/res_debug.c ++++ b/resolv/res_debug.c +@@ -615,6 +615,7 @@ p_option(u_long option) { + case RES_USE_DNSSEC: return "dnssec"; + case RES_NOTLDQUERY: return "no-tld-query"; + case RES_NORELOAD: return "no-reload"; ++ case RES_NOAAAA: return "no-aaaa"; + /* XXX nonreentrant */ + default: sprintf(nbuf, "?0x%lx?", (u_long)option); + return (nbuf); +diff --git a/resolv/res_init.c b/resolv/res_init.c +index bb99ddeec4d6d47f..20434bfe147a3fb5 100644 +--- a/resolv/res_init.c ++++ b/resolv/res_init.c +@@ -694,7 +694,8 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options) + { STRnLEN ("no_tld_query"), 0, RES_NOTLDQUERY }, + { STRnLEN ("no-tld-query"), 0, RES_NOTLDQUERY }, + { STRnLEN ("no-reload"), 0, RES_NORELOAD }, +- { STRnLEN ("use-vc"), 0, RES_USEVC } ++ { STRnLEN ("use-vc"), 0, RES_USEVC }, ++ { STRnLEN ("no-aaaa"), 0, RES_NOAAAA }, + }; + #define noptions (sizeof (options) / sizeof (options[0])) + for (int i = 0; i < noptions; ++i) +diff --git a/resolv/res_query.c b/resolv/res_query.c +index ebbe5a6a4ed86abe..d94966a47c3dac90 100644 +--- a/resolv/res_query.c ++++ b/resolv/res_query.c +@@ -204,10 +204,26 @@ __res_context_query (struct resolv_context *ctx, const char *name, + free (buf); + return (n); + } +- assert (answerp == NULL || (void *) *answerp == (void *) answer); +- n = __res_context_send (ctx, query1, nquery1, query2, nquery2, answer, +- anslen, answerp, answerp2, nanswerp2, resplen2, +- answerp2_malloced); ++ ++ /* Suppress AAAA lookups if required. __res_handle_no_aaaa ++ checks RES_NOAAAA first, so avoids parsing the ++ just-generated query packet in most cases. nss_dns avoids ++ using T_QUERY_A_AND_AAAA in RES_NOAAAA mode, so there is no ++ need to handle it here. */ ++ if (type == T_AAAA && __res_handle_no_aaaa (ctx, query1, nquery1, ++ answer, anslen, &n)) ++ /* There must be no second query for AAAA queries. The code ++ below is still needed to translate NODATA responses. */ ++ assert (query2 == NULL); ++ else ++ { ++ assert (answerp == NULL || (void *) *answerp == (void *) answer); ++ n = __res_context_send (ctx, query1, nquery1, query2, nquery2, ++ answer, anslen, ++ answerp, answerp2, nanswerp2, resplen2, ++ answerp2_malloced); ++ } ++ + if (use_malloc) + free (buf); + if (n < 0) { +diff --git a/resolv/res_send.c b/resolv/res_send.c +index 55e7fa438e7baac1..2e676bff0edf0cdc 100644 +--- a/resolv/res_send.c ++++ b/resolv/res_send.c +@@ -550,8 +550,13 @@ context_send_common (struct resolv_context *ctx, + RES_SET_H_ERRNO (&_res, NETDB_INTERNAL); + return -1; + } +- int result = __res_context_send (ctx, buf, buflen, NULL, 0, ans, anssiz, +- NULL, NULL, NULL, NULL, NULL); ++ ++ int result; ++ if (__res_handle_no_aaaa (ctx, buf, buflen, ans, anssiz, &result)) ++ return result; ++ ++ result = __res_context_send (ctx, buf, buflen, NULL, 0, ans, anssiz, ++ NULL, NULL, NULL, NULL, NULL); + __resolv_context_put (ctx); + return result; + } +diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h +index 0878f6830f2a08ff..4564f6ba2f7202f5 100644 +--- a/resolv/resolv-internal.h ++++ b/resolv/resolv-internal.h +@@ -79,6 +79,14 @@ int __res_context_send (struct resolv_context *, const unsigned char *, int, + int, unsigned char **, unsigned char **, + int *, int *, int *) attribute_hidden; + ++/* Return true if the query has been handled in RES_NOAAAA mode. For ++ that, RES_NOAAAA must be active, and the question type must be AAAA. ++ The caller is expected to return *RESULT as the return value. */ ++bool __res_handle_no_aaaa (struct resolv_context *ctx, ++ const unsigned char *buf, int buflen, ++ unsigned char *ans, int anssiz, int *result) ++ attribute_hidden; ++ + /* Internal function similar to res_hostalias. */ + const char *__res_context_hostalias (struct resolv_context *, + const char *, char *, size_t); +diff --git a/resolv/resolv.h b/resolv/resolv.h +index 80a523e5e40982ad..0f7298f395a829d3 100644 +--- a/resolv/resolv.h ++++ b/resolv/resolv.h +@@ -135,6 +135,7 @@ struct res_sym { + #define RES_NOTLDQUERY 0x01000000 /* Do not look up unqualified name + as a TLD. */ + #define RES_NORELOAD 0x02000000 /* No automatic configuration reload. */ ++#define RES_NOAAAA 0x08000000 /* Suppress AAAA queries. */ + + #define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH) + +diff --git a/resolv/tst-resolv-noaaaa.c b/resolv/tst-resolv-noaaaa.c +new file mode 100644 +index 0000000000000000..56b25f88a58ad286 +--- /dev/null ++++ b/resolv/tst-resolv-noaaaa.c +@@ -0,0 +1,533 @@ ++/* Test the RES_NOAAAA resolver option. ++ Copyright (C) 2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Used to keep track of the number of queries. */ ++static volatile unsigned int queries; ++ ++static void ++response (const struct resolv_response_context *ctx, ++ struct resolv_response_builder *b, ++ const char *qname, uint16_t qclass, uint16_t qtype) ++{ ++ /* Each test should only send one query. */ ++ ++queries; ++ TEST_COMPARE (queries, 1); ++ ++ /* AAAA queries are supposed to be disabled. */ ++ TEST_VERIFY (qtype != T_AAAA); ++ TEST_COMPARE (qclass, C_IN); ++ ++ /* The only other query type besides A is PTR. */ ++ if (qtype != T_A) ++ TEST_COMPARE (qtype, T_PTR); ++ ++ int an, ns, ar; ++ char *tail; ++ if (sscanf (qname, "an%d.ns%d.ar%d.%ms", &an, &ns, &ar, &tail) != 4) ++ FAIL_EXIT1 ("invalid QNAME: %s\n", qname); ++ TEST_COMPARE_STRING (tail, "example"); ++ free (tail); ++ ++ if (an < 0 || ns < 0 || ar < 0) ++ { ++ struct resolv_response_flags flags = { .rcode = NXDOMAIN, }; ++ resolv_response_init (b, flags); ++ resolv_response_add_question (b, qname, qclass, qtype); ++ return; ++ } ++ ++ struct resolv_response_flags flags = {}; ++ resolv_response_init (b, flags); ++ resolv_response_add_question (b, qname, qclass, qtype); ++ ++ resolv_response_section (b, ns_s_an); ++ for (int i = 0; i < an; ++i) ++ { ++ resolv_response_open_record (b, qname, qclass, qtype, 60); ++ switch (qtype) ++ { ++ case T_A: ++ char ipv4[4] = {192, 0, 2, i + 1}; ++ resolv_response_add_data (b, &ipv4, sizeof (ipv4)); ++ break; ++ ++ case T_PTR: ++ char *name = xasprintf ("ptr-%d", i); ++ resolv_response_add_name (b, name); ++ free (name); ++ break; ++ } ++ resolv_response_close_record (b); ++ } ++ ++ resolv_response_section (b, ns_s_ns); ++ for (int i = 0; i < ns; ++i) ++ { ++ resolv_response_open_record (b, qname, qclass, T_NS, 60); ++ char *name = xasprintf ("ns%d.example.net", i); ++ resolv_response_add_name (b, name); ++ free (name); ++ resolv_response_close_record (b); ++ } ++ ++ resolv_response_section (b, ns_s_ar); ++ int addr = 1; ++ for (int i = 0; i < ns; ++i) ++ { ++ char *name = xasprintf ("ns%d.example.net", i); ++ for (int j = 0; j < ar; ++j) ++ { ++ resolv_response_open_record (b, name, qclass, T_A, 60); ++ char ipv4[4] = {192, 0, 2, addr}; ++ resolv_response_add_data (b, &ipv4, sizeof (ipv4)); ++ resolv_response_close_record (b); ++ ++ resolv_response_open_record (b, name, qclass, T_AAAA, 60); ++ char ipv6[16] ++ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, addr}; ++ resolv_response_add_data (b, &ipv6, sizeof (ipv6)); ++ resolv_response_close_record (b); ++ ++ ++addr; ++ } ++ free (name); ++ } ++} ++ ++/* Number of modes. Lowest bit encodes *n* function vs implicit _res ++ argument. The mode numbers themselves are arbitrary. */ ++enum { mode_count = 8 }; ++ ++/* res_send-like modes do not perform error translation. */ ++enum { first_send_mode = 6 }; ++ ++static int ++libresolv_query (unsigned int mode, const char *qname, uint16_t qtype, ++ unsigned char *buf, size_t buflen) ++{ ++ int saved_errno = errno; ++ ++ TEST_VERIFY_EXIT (mode < mode_count); ++ ++ switch (mode) ++ { ++ case 0: ++ return res_query (qname, C_IN, qtype, buf, buflen); ++ case 1: ++ return res_nquery (&_res, qname, C_IN, qtype, buf, buflen); ++ case 2: ++ return res_search (qname, C_IN, qtype, buf, buflen); ++ case 3: ++ return res_nsearch (&_res, qname, C_IN, qtype, buf, buflen); ++ case 4: ++ return res_querydomain (qname, "", C_IN, qtype, buf, buflen); ++ case 5: ++ return res_nquerydomain (&_res, qname, "", C_IN, qtype, buf, buflen); ++ case 6: ++ { ++ unsigned char querybuf[512]; ++ int ret = res_mkquery (QUERY, qname, C_IN, qtype, ++ NULL, 0, NULL, querybuf, sizeof (querybuf)); ++ TEST_VERIFY_EXIT (ret > 0); ++ errno = saved_errno; ++ return res_send (querybuf, ret, buf, buflen); ++ } ++ case 7: ++ { ++ unsigned char querybuf[512]; ++ int ret = res_nmkquery (&_res, QUERY, qname, C_IN, qtype, ++ NULL, 0, NULL, querybuf, sizeof (querybuf)); ++ TEST_VERIFY_EXIT (ret > 0); ++ errno = saved_errno; ++ return res_nsend (&_res, querybuf, ret, buf, buflen); ++ } ++ } ++ __builtin_unreachable (); ++} ++ ++static int ++do_test (void) ++{ ++ struct resolv_test *obj = resolv_test_start ++ ((struct resolv_redirect_config) ++ { ++ .response_callback = response ++ }); ++ ++ _res.options |= RES_NOAAAA; ++ ++ check_hostent ("an1.ns2.ar1.example", ++ gethostbyname ("an1.ns2.ar1.example"), ++ "name: an1.ns2.ar1.example\n" ++ "address: 192.0.2.1\n"); ++ queries = 0; ++ check_hostent ("an0.ns2.ar1.example", ++ gethostbyname ("an0.ns2.ar1.example"), ++ "error: NO_ADDRESS\n"); ++ queries = 0; ++ check_hostent ("an-1.ns2.ar1.example", ++ gethostbyname ("an-1.ns2.ar1.example"), ++ "error: HOST_NOT_FOUND\n"); ++ queries = 0; ++ ++ check_hostent ("an1.ns2.ar1.example AF_INET", ++ gethostbyname2 ("an1.ns2.ar1.example", AF_INET), ++ "name: an1.ns2.ar1.example\n" ++ "address: 192.0.2.1\n"); ++ queries = 0; ++ check_hostent ("an0.ns2.ar1.example AF_INET", ++ gethostbyname2 ("an0.ns2.ar1.example", AF_INET), ++ "error: NO_ADDRESS\n"); ++ queries = 0; ++ check_hostent ("an-1.ns2.ar1.example AF_INET", ++ gethostbyname2 ("an-1.ns2.ar1.example", AF_INET), ++ "error: HOST_NOT_FOUND\n"); ++ queries = 0; ++ ++ check_hostent ("an1.ns2.ar1.example AF_INET6", ++ gethostbyname2 ("an1.ns2.ar1.example", AF_INET6), ++ "error: NO_ADDRESS\n"); ++ queries = 0; ++ check_hostent ("an0.ns2.ar1.example AF_INET6", ++ gethostbyname2 ("an0.ns2.ar1.example", AF_INET6), ++ "error: NO_ADDRESS\n"); ++ queries = 0; ++ check_hostent ("an-1.ns2.ar1.example AF_INET6", ++ gethostbyname2 ("an-1.ns2.ar1.example", AF_INET6), ++ "error: HOST_NOT_FOUND\n"); ++ queries = 0; ++ ++ /* Multiple addresses. */ ++ check_hostent ("an2.ns0.ar0.example", ++ gethostbyname ("an2.ns0.ar0.example"), ++ "name: an2.ns0.ar0.example\n" ++ "address: 192.0.2.1\n" ++ "address: 192.0.2.2\n"); ++ queries = 0; ++ check_hostent ("an2.ns0.ar0.example AF_INET6", ++ gethostbyname2 ("an2.ns0.ar0.example", AF_INET6), ++ "error: NO_ADDRESS\n"); ++ queries = 0; ++ ++ /* getaddrinfo checks with one address. */ ++ struct addrinfo *ai; ++ int ret; ++ ret = getaddrinfo ("an1.ns2.ar1.example", "80", ++ &(struct addrinfo) ++ { ++ .ai_family = AF_INET, ++ .ai_socktype = SOCK_STREAM, ++ }, &ai); ++ check_addrinfo ("an1.ns2.ar1.example (AF_INET)", ai, ret, ++ "address: STREAM/TCP 192.0.2.1 80\n"); ++ freeaddrinfo (ai); ++ queries = 0; ++ ret = getaddrinfo ("an1.ns2.ar1.example", "80", ++ &(struct addrinfo) ++ { ++ .ai_family = AF_INET6, ++ .ai_socktype = SOCK_STREAM, ++ }, &ai); ++ check_addrinfo ("an1.ns2.ar1.example (AF_INET6)", ai, ret, ++ "error: No address associated with hostname\n"); ++ queries = 0; ++ ret = getaddrinfo ("an1.ns2.ar1.example", "80", ++ &(struct addrinfo) ++ { ++ .ai_family = AF_UNSPEC, ++ .ai_socktype = SOCK_STREAM, ++ }, &ai); ++ check_addrinfo ("an1.ns2.ar1.example (AF_UNSPEC)", ai, ret, ++ "address: STREAM/TCP 192.0.2.1 80\n"); ++ freeaddrinfo (ai); ++ queries = 0; ++ ++ /* getaddrinfo checks with three addresses. */ ++ ret = getaddrinfo ("an3.ns2.ar1.example", "80", ++ &(struct addrinfo) ++ { ++ .ai_family = AF_INET, ++ .ai_socktype = SOCK_STREAM, ++ }, &ai); ++ check_addrinfo ("an3.ns2.ar1.example (AF_INET)", ai, ret, ++ "address: STREAM/TCP 192.0.2.1 80\n" ++ "address: STREAM/TCP 192.0.2.2 80\n" ++ "address: STREAM/TCP 192.0.2.3 80\n"); ++ freeaddrinfo (ai); ++ queries = 0; ++ ret = getaddrinfo ("an3.ns2.ar1.example", "80", ++ &(struct addrinfo) ++ { ++ .ai_family = AF_INET6, ++ .ai_socktype = SOCK_STREAM, ++ }, &ai); ++ check_addrinfo ("an3.ns2.ar1.example (AF_INET6)", ai, ret, ++ "error: No address associated with hostname\n"); ++ queries = 0; ++ ret = getaddrinfo ("an3.ns2.ar1.example", "80", ++ &(struct addrinfo) ++ { ++ .ai_family = AF_UNSPEC, ++ .ai_socktype = SOCK_STREAM, ++ }, &ai); ++ check_addrinfo ("an3.ns2.ar1.example (AF_UNSPEC)", ai, ret, ++ "address: STREAM/TCP 192.0.2.1 80\n" ++ "address: STREAM/TCP 192.0.2.2 80\n" ++ "address: STREAM/TCP 192.0.2.3 80\n"); ++ freeaddrinfo (ai); ++ queries = 0; ++ ++ /* getaddrinfo checks with no address. */ ++ ret = getaddrinfo ("an0.ns2.ar1.example", "80", ++ &(struct addrinfo) ++ { ++ .ai_family = AF_INET, ++ .ai_socktype = SOCK_STREAM, ++ }, &ai); ++ check_addrinfo ("an0.ns2.ar1.example (AF_INET)", ai, ret, ++ "error: No address associated with hostname\n"); ++ queries = 0; ++ ret = getaddrinfo ("an0.ns2.ar1.example", "80", ++ &(struct addrinfo) ++ { ++ .ai_family = AF_INET6, ++ .ai_socktype = SOCK_STREAM, ++ }, &ai); ++ check_addrinfo ("an0.ns2.ar1.example (AF_INET6)", ai, ret, ++ "error: No address associated with hostname\n"); ++ queries = 0; ++ ret = getaddrinfo ("an0.ns2.ar1.example", "80", ++ &(struct addrinfo) ++ { ++ .ai_family = AF_UNSPEC, ++ .ai_socktype = SOCK_STREAM, ++ }, &ai); ++ check_addrinfo ("an-1.ns2.ar1.example (AF_UNSPEC)", ai, ret, ++ "error: No address associated with hostname\n"); ++ queries = 0; ++ ++ /* getaddrinfo checks with NXDOMAIN. */ ++ ret = getaddrinfo ("an-1.ns2.ar1.example", "80", ++ &(struct addrinfo) ++ { ++ .ai_family = AF_INET, ++ .ai_socktype = SOCK_STREAM, ++ }, &ai); ++ check_addrinfo ("an-1.ns2.ar1.example (AF_INET)", ai, ret, ++ "error: Name or service not known\n"); ++ queries = 0; ++ ret = getaddrinfo ("an-1.ns2.ar1.example", "80", ++ &(struct addrinfo) ++ { ++ .ai_family = AF_INET6, ++ .ai_socktype = SOCK_STREAM, ++ }, &ai); ++ check_addrinfo ("an-1.ns2.ar1.example (AF_INET6)", ai, ret, ++ "error: Name or service not known\n"); ++ queries = 0; ++ ret = getaddrinfo ("an-1.ns2.ar1.example", "80", ++ &(struct addrinfo) ++ { ++ .ai_family = AF_UNSPEC, ++ .ai_socktype = SOCK_STREAM, ++ }, &ai); ++ check_addrinfo ("an-1.ns2.ar1.example (AF_UNSPEC)", ai, ret, ++ "error: Name or service not known\n"); ++ queries = 0; ++ ++ for (unsigned int mode = 0; mode < mode_count; ++mode) ++ { ++ unsigned char *buf; ++ int ret; ++ ++ /* Response for A. */ ++ buf = malloc (512); ++ ret = libresolv_query (mode, "an1.ns2.ar1.example", T_A, buf, 512); ++ TEST_VERIFY_EXIT (ret > 0); ++ check_dns_packet ("an1.ns2.ar1.example A", buf, ret, ++ "name: an1.ns2.ar1.example\n" ++ "address: 192.0.2.1\n"); ++ free (buf); ++ queries = 0; ++ ++ /* NODATA response for A. */ ++ buf = malloc (512); ++ errno = 0; ++ ret = libresolv_query (mode, "an0.ns2.ar1.example", T_A, buf, 512); ++ if (mode < first_send_mode) ++ { ++ TEST_COMPARE (ret, -1); ++ TEST_COMPARE (errno, 0); ++ TEST_COMPARE (h_errno, NO_ADDRESS); ++ } ++ else ++ { ++ TEST_VERIFY_EXIT (ret > 0); ++ TEST_COMPARE (((HEADER *)buf)->rcode, 0); ++ check_dns_packet ("an1.ns2.ar1.example A", buf, ret, ++ "name: an0.ns2.ar1.example\n"); ++ } ++ free (buf); ++ queries = 0; ++ ++ /* NXDOMAIN response for A. */ ++ buf = malloc (512); ++ errno = 0; ++ ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_A, buf, 512); ++ if (mode < first_send_mode) ++ { ++ TEST_COMPARE (ret, -1); ++ TEST_COMPARE (errno, 0); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ } ++ else ++ { ++ TEST_VERIFY_EXIT (ret > 0); ++ TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN); ++ check_dns_packet ("an1.ns2.ar1.example A", buf, ret, ++ "name: an-1.ns2.ar1.example\n"); ++ } ++ free (buf); ++ queries = 0; ++ ++ /* Response for PTR. */ ++ buf = malloc (512); ++ ret = libresolv_query (mode, "an1.ns2.ar1.example", T_PTR, buf, 512); ++ TEST_VERIFY_EXIT (ret > 0); ++ check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret, ++ "name: an1.ns2.ar1.example\n" ++ "data: an1.ns2.ar1.example PTR ptr-0\n"); ++ free (buf); ++ queries = 0; ++ ++ /* NODATA response for PTR. */ ++ buf = malloc (512); ++ errno = 0; ++ ret = libresolv_query (mode, "an0.ns2.ar1.example", T_PTR, buf, 512); ++ if (mode < first_send_mode) ++ { ++ TEST_COMPARE (ret, -1); ++ TEST_COMPARE (errno, 0); ++ TEST_COMPARE (h_errno, NO_ADDRESS); ++ } ++ else ++ { ++ TEST_VERIFY_EXIT (ret > 0); ++ TEST_COMPARE (((HEADER *)buf)->rcode, 0); ++ check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret, ++ "name: an0.ns2.ar1.example\n"); ++ } ++ free (buf); ++ queries = 0; ++ ++ /* NXDOMAIN response for PTR. */ ++ buf = malloc (512); ++ errno = 0; ++ ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_PTR, buf, 512); ++ if (mode < first_send_mode) ++ { ++ TEST_COMPARE (ret, -1); ++ TEST_COMPARE (errno, 0); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ } ++ else ++ { ++ TEST_VERIFY_EXIT (ret > 0); ++ TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN); ++ check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret, ++ "name: an-1.ns2.ar1.example\n"); ++ } ++ free (buf); ++ queries = 0; ++ ++ /* NODATA response for AAAA. */ ++ buf = malloc (512); ++ errno = 0; ++ ret = libresolv_query (mode, "an1.ns2.ar1.example", T_AAAA, buf, 512); ++ if (mode < first_send_mode) ++ { ++ TEST_COMPARE (ret, -1); ++ TEST_COMPARE (errno, 0); ++ TEST_COMPARE (h_errno, NO_ADDRESS); ++ } ++ else ++ { ++ TEST_VERIFY_EXIT (ret > 0); ++ TEST_COMPARE (((HEADER *)buf)->rcode, 0); ++ check_dns_packet ("an1.ns2.ar1.example A", buf, ret, ++ "name: an1.ns2.ar1.example\n"); ++ } ++ free (buf); ++ queries = 0; ++ ++ /* NODATA response for AAAA (original is already NODATA). */ ++ buf = malloc (512); ++ errno = 0; ++ ret = libresolv_query (mode, "an0.ns2.ar1.example", T_AAAA, buf, 512); ++ if (mode < first_send_mode) ++ { ++ TEST_COMPARE (ret, -1); ++ TEST_COMPARE (errno, 0); ++ TEST_COMPARE (h_errno, NO_ADDRESS); ++ } ++ else ++ { ++ TEST_VERIFY_EXIT (ret > 0); ++ TEST_COMPARE (((HEADER *)buf)->rcode, 0); ++ check_dns_packet ("an0.ns2.ar1.example A", buf, ret, ++ "name: an0.ns2.ar1.example\n"); ++ } ++ free (buf); ++ queries = 0; ++ ++ /* NXDOMAIN response. */ ++ buf = malloc (512); ++ errno = 0; ++ ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_AAAA, buf, 512); ++ if (mode < first_send_mode) ++ { ++ TEST_COMPARE (ret, -1); ++ TEST_COMPARE (errno, 0); ++ TEST_COMPARE (h_errno, HOST_NOT_FOUND); ++ } ++ else ++ { ++ TEST_VERIFY_EXIT (ret > 0); ++ TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN); ++ check_dns_packet ("an-1.ns2.ar1.example A", buf, ret, ++ "name: an-1.ns2.ar1.example\n"); ++ } ++ free (buf); ++ queries = 0; ++ } ++ ++ resolv_test_end (obj); ++ ++ return 0; ++} ++ ++#include +diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c +index a5061e6d4fb98311..7d8758a99e180d97 100644 +--- a/resolv/tst-resolv-res_init-skeleton.c ++++ b/resolv/tst-resolv-res_init-skeleton.c +@@ -129,6 +129,7 @@ print_resp (FILE *fp, res_state resp) + "single-request-reopen"); + print_option_flag (fp, &options, RES_NOTLDQUERY, "no-tld-query"); + print_option_flag (fp, &options, RES_NORELOAD, "no-reload"); ++ print_option_flag (fp, &options, RES_NOAAAA, "no-aaaa"); + fputc ('\n', fp); + if (options != 0) + fprintf (fp, "; error: unresolved option bits: 0x%x\n", options); +@@ -713,6 +714,15 @@ struct test_case test_cases[] = + "nameserver 192.0.2.1\n" + "; nameserver[0]: [192.0.2.1]:53\n" + }, ++ {.name = "no-aaaa flag", ++ .conf = "options no-aaaa\n" ++ "nameserver 192.0.2.1\n", ++ .expected = "options no-aaaa\n" ++ "search example.com\n" ++ "; search[0]: example.com\n" ++ "nameserver 192.0.2.1\n" ++ "; nameserver[0]: [192.0.2.1]:53\n" ++ }, + { NULL } + }; + diff --git a/glibc-rh2096189-3.patch b/glibc-rh2096189-3.patch new file mode 100644 index 0000000..604afa4 --- /dev/null +++ b/glibc-rh2096189-3.patch @@ -0,0 +1,44 @@ +commit 77536da3dea5af4d1859e4e754f07f47cf8d7d4c +Author: Florian Weimer +Date: Fri Jun 24 19:38:14 2022 +0200 + + resolv/tst-resolv-noaaaa: Support building for older C standards + + This avoids a compilation error: + + tst-resolv-noaaaa.c: In function 'response': + tst-resolv-noaaaa.c:74:11: error: a label can only be part of a statement and a declaration is not a statement + char ipv4[4] = {192, 0, 2, i + 1}; + ^~~~ + tst-resolv-noaaaa.c:79:11: error: a label can only be part of a statement and a declaration is not a statement + char *name = xasprintf ("ptr-%d", i); + ^~~~ + +diff --git a/resolv/tst-resolv-noaaaa.c b/resolv/tst-resolv-noaaaa.c +index 56b25f88a58ad286..6e0c6b6fb809e245 100644 +--- a/resolv/tst-resolv-noaaaa.c ++++ b/resolv/tst-resolv-noaaaa.c +@@ -71,14 +71,18 @@ response (const struct resolv_response_context *ctx, + switch (qtype) + { + case T_A: +- char ipv4[4] = {192, 0, 2, i + 1}; +- resolv_response_add_data (b, &ipv4, sizeof (ipv4)); ++ { ++ char ipv4[4] = {192, 0, 2, i + 1}; ++ resolv_response_add_data (b, &ipv4, sizeof (ipv4)); ++ } + break; + + case T_PTR: +- char *name = xasprintf ("ptr-%d", i); +- resolv_response_add_name (b, name); +- free (name); ++ { ++ char *name = xasprintf ("ptr-%d", i); ++ resolv_response_add_name (b, name); ++ free (name); ++ } + break; + } + resolv_response_close_record (b); diff --git a/glibc-rh2104907.patch b/glibc-rh2104907.patch new file mode 100644 index 0000000..3a65f18 --- /dev/null +++ b/glibc-rh2104907.patch @@ -0,0 +1,14 @@ +diff --git a/localedata/SUPPORTED b/localedata/SUPPORTED +index a4bf79c6a6e6401b..fdf15fddf5178319 100644 +--- a/localedata/SUPPORTED ++++ b/localedata/SUPPORTED +@@ -159,7 +159,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/UTF-8 \ ++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 \ diff --git a/glibc-rh2119304-1.patch b/glibc-rh2119304-1.patch new file mode 100644 index 0000000..a76e1bf --- /dev/null +++ b/glibc-rh2119304-1.patch @@ -0,0 +1,49 @@ +Downstream-only patch to move the recently added members (from +glibc-rh2047981-5.patch and glibc-rh2047981-6.patch) to the end +of _rtld_global_ro. This avoids changing the offset of +GLRO (dl_naudit). + +Without this change, the audit invocation loop in the old +__libc_start_main function in a not-yet-updated version of libc.so.6 +reads a non-zero garbage value for GLRO (dl_naudit), assumes that +auditing is active, and reads further garbage pointers, leading to +to a crash. Preserving the old offset of GLRO (dl_naudit) avoids +that. This works because RPM updates /lib64/ld-* before +/lib64/libc.so.6 because it sorts earlier (except on POWER9 due +to the glibc-hwcaps/power9 multilib). + +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index 9dec9e3d3b6d6aa2..5e56550a4d556fa7 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -648,6 +648,15 @@ struct rtld_global_ro + void *(*_dl_open) (const char *file, int mode, const void *caller_dlopen, + Lmid_t nsid, int argc, char *argv[], char *env[]); + void (*_dl_close) (void *map); ++ void *(*_dl_tls_get_addr_soft) (struct link_map *); ++#ifdef HAVE_DL_DISCOVER_OSVERSION ++ int (*_dl_discover_osversion) (void); ++#endif ++ ++ /* List of auditing interfaces. */ ++ struct audit_ifaces *_dl_audit; ++ unsigned int _dl_naudit; ++ + /* libdl in a secondary namespace (after dlopen) must use + _dl_catch_error from the main namespace, so it has to be + exported in some way. */ +@@ -657,14 +666,6 @@ struct rtld_global_ro + /* libdl in a secondary namespace must use free from the base + namespace. */ + void (*_dl_error_free) (void *); +- void *(*_dl_tls_get_addr_soft) (struct link_map *); +-#ifdef HAVE_DL_DISCOVER_OSVERSION +- int (*_dl_discover_osversion) (void); +-#endif +- +- /* List of auditing interfaces. */ +- struct audit_ifaces *_dl_audit; +- unsigned int _dl_naudit; + }; + # define __rtld_global_attribute__ + # if IS_IN (rtld) diff --git a/glibc-rh2119304-2.patch b/glibc-rh2119304-2.patch new file mode 100644 index 0000000..a1e121b --- /dev/null +++ b/glibc-rh2119304-2.patch @@ -0,0 +1,202 @@ +commit 5ecc98241229d494aaad23a4a3fe106fe11e1f40 +Author: Florian Weimer +Date: Thu Aug 25 16:34:20 2022 +0200 + + s390: Move hwcaps/platform names out of _rtld_global_ro + + Changes to these arrays are often backported to stable releases, + but additions to these arrays shift the offsets of the following + _rltd_global_ro members, thus breaking the GLIBC_PRIVATE ABI. + + Obviously, this change is itself an internal ABI break, but at least + it will avoid further ABI breaks going forward. + + Reviewed-by: Carlos O'Donell + +Conflicts: + sysdeps/s390/Makefile + (missing lazy binding test downstream) + +diff --git a/sysdeps/s390/Makefile b/sysdeps/s390/Makefile +index 5c8e1170b4d799ba..ea453ba87646c95a 100644 +--- a/sysdeps/s390/Makefile ++++ b/sysdeps/s390/Makefile +@@ -42,6 +42,10 @@ $(modpfx)gconv-modules-s390.conf: ../sysdeps/s390/gconv-modules-s390.conf \ + cp $< $@ + endif + ++ifeq ($(subdir),elf) ++sysdep-dl-routines += dl-procinfo-s390 ++endif ++ + ifeq ($(subdir),string) + sysdep_routines += bzero memset memset-z900 \ + memcmp memcmp-z900 \ +diff --git a/sysdeps/s390/dl-procinfo-s390.c b/sysdeps/s390/dl-procinfo-s390.c +new file mode 100644 +index 0000000000000000..559f3827936cd017 +--- /dev/null ++++ b/sysdeps/s390/dl-procinfo-s390.c +@@ -0,0 +1,32 @@ ++/* Data for s390 version of processor capability information. ++ Copyright (C) 2006-2022 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++ ++const char _dl_s390_cap_flags[_DL_HWCAP_COUNT][9] = ++ { ++ "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh", ++ "highgprs", "te", "vx", "vxd", "vxe", "gs", "vxe2", "vxp", "sort", "dflt", ++ "vxp2", "nnpa", "pcimio", "sie" ++ }; ++ ++const char _dl_s390_platforms[_DL_PLATFORMS_COUNT][7] = ++ { ++ "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14", "z15", ++ "z16" ++ }; +diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c +index 85108943d0e79f29..f928b485609a3b8a 100644 +--- a/sysdeps/s390/dl-procinfo.c ++++ b/sysdeps/s390/dl-procinfo.c +@@ -17,66 +17,10 @@ + License along with the GNU C Library; if not, see + . */ + +-/* This information must be kept in sync with the _DL_HWCAP_COUNT and +- _DL_PLATFORM_COUNT definitions in procinfo.h. +- +- 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 !defined PROCINFO_DECL && defined SHARED +- ._dl_s390_cap_flags +-#else +-PROCINFO_CLASS const char _dl_s390_cap_flags[23][9] +-#endif +-#ifndef PROCINFO_DECL +-= { +- "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh", +- "highgprs", "te", "vx", "vxd", "vxe", "gs", "vxe2", "vxp", "sort", "dflt", +- "vxp2", "nnpa", "pcimio", "sie" +- } +-#endif +-#if !defined SHARED || defined PROCINFO_DECL +-; +-#else +-, +-#endif +- +-#if !defined PROCINFO_DECL && defined SHARED +- ._dl_s390_platforms +-#else +-PROCINFO_CLASS const char _dl_s390_platforms[11][7] +-#endif +-#ifndef PROCINFO_DECL +-= { +- "g5", "z900", "z990", "z9-109", "z10", "z196", "zEC12", "z13", "z14", "z15", +- "z16" +- } +-#endif +-#if !defined SHARED || defined PROCINFO_DECL +-; +-#else +-, +-#endif ++/* The hwcap and platform strings are now in ++ sysdeps/s390/dl-procinfo-s390.c. */ + ++/* Needed by sysdeps/unix/sysv/linux/dl-vdso-setup.c (as included from ++ sysdeps/generic/ldsodefs.h). */ + #undef PROCINFO_DECL + #undef PROCINFO_CLASS +diff --git a/sysdeps/s390/dl-procinfo.h b/sysdeps/s390/dl-procinfo.h +index f2b2c9ac1bb7239b..5eb2c0a39fcff520 100644 +--- a/sysdeps/s390/dl-procinfo.h ++++ b/sysdeps/s390/dl-procinfo.h +@@ -22,8 +22,10 @@ + #include + + #define _DL_HWCAP_COUNT 23 ++extern const char _dl_s390_cap_flags[_DL_HWCAP_COUNT][9] attribute_hidden; + + #define _DL_PLATFORMS_COUNT 11 ++extern const char _dl_s390_platforms[_DL_PLATFORMS_COUNT][7] attribute_hidden; + + /* The kernel provides up to 32 capability bits with elf_hwcap. */ + #define _DL_FIRST_PLATFORM 32 +@@ -79,7 +81,7 @@ static inline const char * + __attribute__ ((unused)) + _dl_hwcap_string (int idx) + { +- return GLRO(dl_s390_cap_flags)[idx]; ++ return _dl_s390_cap_flags[idx]; + }; + + static inline int +@@ -90,7 +92,7 @@ _dl_string_hwcap (const char *str) + + for (i = 0; i < _DL_HWCAP_COUNT; i++) + { +- if (strcmp (str, GLRO(dl_s390_cap_flags)[i]) == 0) ++ if (strcmp (str, _dl_s390_cap_flags[i]) == 0) + return i; + } + return -1; +@@ -105,7 +107,7 @@ _dl_string_platform (const char *str) + if (str != NULL) + for (i = 0; i < _DL_PLATFORMS_COUNT; ++i) + { +- if (strcmp (str, GLRO(dl_s390_platforms)[i]) == 0) ++ if (strcmp (str, _dl_s390_platforms[i]) == 0) + return _DL_FIRST_PLATFORM + i; + } + return -1; +diff --git a/sysdeps/unix/sysv/linux/s390/dl-procinfo.h b/sysdeps/unix/sysv/linux/s390/dl-procinfo.h +index d1516a05e3042163..4aefd7eef14eaf52 100644 +--- a/sysdeps/unix/sysv/linux/s390/dl-procinfo.h ++++ b/sysdeps/unix/sysv/linux/s390/dl-procinfo.h +@@ -40,7 +40,7 @@ _dl_procinfo (unsigned int type, unsigned long int word) + + for (i = 0; i < _DL_HWCAP_COUNT; ++i) + if (word & (1UL << i)) +- _dl_printf (" %s", GLRO(dl_s390_cap_flags)[i]); ++ _dl_printf (" %s", _dl_s390_cap_flags[i]); + + _dl_printf ("\n"); + diff --git a/glibc-rh2119304-3.patch b/glibc-rh2119304-3.patch new file mode 100644 index 0000000..faaea99 --- /dev/null +++ b/glibc-rh2119304-3.patch @@ -0,0 +1,19 @@ +Downstream-only patch to preserve the 8.6.0 _rtld_global_ro ABI on s390x. + +diff --git a/sysdeps/s390/dl-procinfo.c b/sysdeps/s390/dl-procinfo.c +index f928b485609a3b8a..3f46b2785fafe51e 100644 +--- a/sysdeps/s390/dl-procinfo.c ++++ b/sysdeps/s390/dl-procinfo.c +@@ -20,6 +20,12 @@ + /* The hwcap and platform strings are now in + sysdeps/s390/dl-procinfo-s390.c. */ + ++/* Dummy entries to preserve ABI. */ ++#if defined SHARED && defined PROCINFO_DECL ++const char _dl_s390_cap_flags_unused[23][9]; ++const char _dl_s390_platforms_unused[10][7]; ++#endif ++ + /* Needed by sysdeps/unix/sysv/linux/dl-vdso-setup.c (as included from + sysdeps/generic/ldsodefs.h). */ + #undef PROCINFO_DECL diff --git a/glibc.spec b/glibc.spec index dfeace0..848f4d1 100644 --- a/glibc.spec +++ b/glibc.spec @@ -1,7 +1,6 @@ -%define anolis_release .0.2 %define glibcsrcdir glibc-2.28 %define glibcversion 2.28 -%define glibcrelease 189.5%{anolis_release}%{?dist} +%define glibcrelease 211%{?dist} # Pre-release tarballs are pulled in from git using a command that is # effectively: # @@ -856,24 +855,119 @@ Patch660: glibc-rh2045063-2.patch Patch661: glibc-rh2045063-3.patch Patch662: glibc-rh2045063-4.patch Patch663: glibc-rh2045063-5.patch -Patch664: glibc-rh2061727.patch -Patch665: glibc-rh2073432.patch -Patch666: glibc-rh2084564.patch -Patch667: glibc-rh2094540.patch -Patch668: glibc-rh2093457-1.patch -Patch669: glibc-rh2093457-2.patch -Patch670: glibc-rh2093457-3.patch -Patch671: glibc-rh2093457-4.patch -Patch672: glibc-rh2093457-5.patch -Patch673: glibc-rh2093457-6.patch - -Patch1000: glibc-Properly-check-stack-alignment-BZ-27901.patch -Patch1001: glibc-elf-Properly-align-PT_LOAD-segments-BZ-28676-1.patch -Patch1002: glibc-Add-a-testcase-to-check-alignment-of-PT_LOAD-segment-2.patch -Patch1003: glibc-elf-Align-argument-of-__munmap-to-page-size-BZ-28676-3.patch -Patch1004: glibc-Support-target-specific-ALIGN-for-variable-alignment-4.patch -Patch1005: glibc-elf-Fix-tst-align3.patch -Patch1006: glibc-LoongArch-Port.patch +Patch664: glibc-rh2054790.patch +Patch665: glibc-rh2037416-1.patch +Patch666: glibc-rh2037416-2.patch +Patch667: glibc-rh2037416-3.patch +Patch668: glibc-rh2037416-4.patch +Patch669: glibc-rh2037416-5.patch +Patch670: glibc-rh2037416-6.patch +Patch671: glibc-rh2037416-7.patch +Patch672: glibc-rh2037416-8.patch +Patch673: glibc-rh2033684-1.patch +Patch674: glibc-rh2033684-2.patch +Patch675: glibc-rh2033684-3.patch +Patch676: glibc-rh2033684-4.patch +Patch677: glibc-rh2033684-5.patch +Patch678: glibc-rh2033684-6.patch +Patch679: glibc-rh2033684-7.patch +Patch680: glibc-rh2033684-8.patch +Patch681: glibc-rh2033684-9.patch +Patch682: glibc-rh2033684-10.patch +Patch683: glibc-rh2033684-11.patch +Patch684: glibc-rh2033684-12.patch +Patch685: glibc-rh2063712.patch +Patch686: glibc-rh2063042.patch +Patch687: glibc-rh2071745.patch +Patch688: glibc-rh2065588-1.patch +Patch689: glibc-rh2065588-2.patch +Patch690: glibc-rh2065588-3.patch +Patch691: glibc-rh2065588-4.patch +Patch692: glibc-rh2065588-5.patch +Patch693: glibc-rh2065588-6.patch +Patch694: glibc-rh2065588-7.patch +Patch695: glibc-rh2065588-8.patch +Patch696: glibc-rh2065588-9.patch +Patch697: glibc-rh2065588-10.patch +Patch698: glibc-rh2065588-11.patch +Patch699: glibc-rh2065588-12.patch +Patch700: glibc-rh2065588-13.patch +Patch701: glibc-rh2072329.patch +Patch702: glibc-rh1982608.patch +Patch703: glibc-rh1961109.patch +Patch704: glibc-rh2086853.patch +Patch705: glibc-rh2077835.patch +Patch706: glibc-rh2089247-1.patch +Patch707: glibc-rh2089247-2.patch +Patch708: glibc-rh2089247-3.patch +Patch709: glibc-rh2089247-4.patch +Patch710: glibc-rh2089247-5.patch +Patch711: glibc-rh2089247-6.patch +Patch712: glibc-rh2091553.patch +Patch713: glibc-rh1888660.patch +Patch714: glibc-rh2096189-1.patch +Patch715: glibc-rh2096189-2.patch +Patch716: glibc-rh2096189-3.patch +Patch717: glibc-rh2080349-1.patch +Patch718: glibc-rh2080349-2.patch +Patch719: glibc-rh2080349-3.patch +Patch720: glibc-rh2080349-4.patch +Patch721: glibc-rh2080349-5.patch +Patch722: glibc-rh2080349-6.patch +Patch723: glibc-rh2080349-7.patch +Patch724: glibc-rh2080349-8.patch +Patch725: glibc-rh2080349-9.patch +Patch727: glibc-rh2047981-1.patch +Patch728: glibc-rh2047981-2.patch +Patch729: glibc-rh2047981-3.patch +Patch730: glibc-rh2047981-4.patch +Patch731: glibc-rh2047981-5.patch +Patch732: glibc-rh2047981-6.patch +Patch733: glibc-rh2047981-7.patch +Patch734: glibc-rh2047981-8.patch +Patch735: glibc-rh2047981-9.patch +Patch736: glibc-rh2047981-10.patch +Patch737: glibc-rh2047981-11.patch +Patch738: glibc-rh2047981-12.patch +Patch739: glibc-rh2047981-13.patch +Patch740: glibc-rh2047981-14.patch +Patch741: glibc-rh2047981-15.patch +Patch742: glibc-rh2047981-16.patch +Patch743: glibc-rh2047981-17.patch +Patch744: glibc-rh2047981-18.patch +Patch745: glibc-rh2047981-19.patch +Patch746: glibc-rh2047981-20.patch +Patch747: glibc-rh2047981-21.patch +Patch748: glibc-rh2047981-22.patch +Patch749: glibc-rh2047981-23.patch +Patch750: glibc-rh2047981-24.patch +Patch751: glibc-rh2047981-25.patch +Patch752: glibc-rh2047981-26.patch +Patch753: glibc-rh2047981-27.patch +Patch754: glibc-rh2047981-28.patch +Patch755: glibc-rh2047981-29.patch +Patch756: glibc-rh2047981-30.patch +Patch757: glibc-rh2047981-31.patch +Patch758: glibc-rh2047981-32.patch +Patch759: glibc-rh2047981-33.patch +Patch760: glibc-rh2047981-34.patch +Patch761: glibc-rh2047981-35.patch +Patch762: glibc-rh2047981-36.patch +Patch763: glibc-rh2047981-37.patch +Patch764: glibc-rh2047981-38.patch +Patch766: glibc-rh2047981-39.patch +Patch767: glibc-rh2047981-40.patch +Patch768: glibc-rh2047981-41.patch +Patch769: glibc-rh2047981-42.patch +Patch770: glibc-rh2047981-43.patch +Patch771: glibc-rh2047981-44.patch +Patch772: glibc-rh2047981-45.patch +Patch773: glibc-rh2047981-46.patch +Patch774: glibc-rh2047981-47.patch +Patch775: glibc-rh2104907.patch +Patch776: glibc-rh2119304-1.patch +Patch777: glibc-rh2119304-2.patch +Patch778: glibc-rh2119304-3.patch ############################################################################## # Continued list of core "glibc" package information: @@ -1765,6 +1859,20 @@ $olddir/build-%{target}/testrun.sh \ # default locale-archive without modification, and leaving compiled # locales as they are (without inclusion into the archive). cp locale-archive{,.tmpl} + +# Almost half the LC_CTYPE files in langpacks are identical to the C.utf8 +# variant which is installed by default. When we keep them as hardlinks, +# each langpack ends up retaining a copy. If we convert these to symbolic +# links instead, we save ~350K each when they get installed that way. +# +# LC_MEASUREMENT and LC_PAPER also have several duplicates but we don't +# bother with these because they are only ~30 bytes each. +pushd %{glibc_sysroot}/usr/lib/locale +for f in $(find eo *_* -samefile C.utf8/LC_CTYPE); do + rm $f && ln -s '../C.utf8/LC_CTYPE' $f +done +popd + # Create the file lists for the language specific sub-packages: for i in eo *_* do @@ -2073,7 +2181,7 @@ chmod 0444 master.filelist # - All the libnss files (we add back the ones we want later). # - All bench test binaries. # - The aux-cache, since it's handled specially in the files section. -# - The build-locale-archive binary since it's in the common package. +# - The build-locale-archive binary since it's in the all-langpacks package. # - Extra gconv modules. We add the required modules later. cat master.filelist \ | grep -v \ @@ -2198,13 +2306,15 @@ grep '%{_libdir}/lib.*\.a' < master.filelist \ ############################################################################### # All of the bin and certain sbin files go into the common package except -# iconvconfig which needs to go in glibc. Likewise nscd is excluded because +# iconvconfig which needs to go in glibc, and build-locale-archive which +# needs to go into glibc-all-langpacks. Likewise nscd is excluded because # it goes in nscd. The iconvconfig binary is kept in the main glibc package # because we use it in the post-install scriptlet to rebuild the # gconv-modules.cache. grep '%{_prefix}/bin' master.filelist >> common.filelist grep '%{_prefix}/sbin' master.filelist \ | grep -v '%{_prefix}/sbin/iconvconfig' \ + | grep -v '%{_prefix}/sbin/build-locale-archive' \ | grep -v 'nscd' >> common.filelist # All of the files under share go into the common package since they should be # multilib-independent. @@ -2220,9 +2330,6 @@ grep '%{_prefix}/share' master.filelist \ -e '%{_docdir}' \ >> common.filelist -# Add the binary to build locales to the common subpackage. -echo '%{_prefix}/sbin/build-locale-archive' >> common.filelist - ############################################################################### # nscd ############################################################################### @@ -2632,6 +2739,8 @@ fi %files all-langpacks %attr(0644,root,root) %verify(not md5 size mtime) %{_prefix}/lib/locale/locale-archive.tmpl %attr(0644,root,root) %verify(not md5 size mtime mode) %ghost %{_prefix}/lib/locale/locale-archive +# build-locale-archive re-generates locale-archive during install/upgrade/downgrade +%attr(0700,root,root) %{_prefix}/sbin/build-locale-archive %files locale-source %dir %{_prefix}/share/i18n/locales @@ -2689,26 +2798,74 @@ fi %files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared %changelog -* Thu Jun 23 2022 wanghongliang - 2.28-189.5.0.2 -- arch: LoongArch Port +* Thu Aug 25 2022 Florian Weimer - 2.28-211 +- Preserve GLRO (dl_naudit) internal ABI (#2119304) +- Avoid s390x ABI change due to z16 recognition on s390x (#2119304) -* Fri Jun 17 2022 Rongwei Wang - 2.28-189.5.0.1 -- elf: Properly align PT_LOAD segments +* Tue Aug 23 2022 Arjun Shankar - 2.28-210 +- Fix locale en_US@ampm (#2104907) -* Wed Jun 8 2022 Florian Weimer - 2.28-189.5 -- Increase tempnam randomness (#2093457) +* Fri Jul 22 2022 Carlos O'Donell - 2.28-209 +- Improve dynamic loader auditing interface (LD_AUDIT) (#2047981) +- Add dlinfo() API support for RTLD_DI_PHDR (#2097898) -* Tue Jun 07 2022 DJ Delorie - 2.28-189.4 -- Fix incorrect strncpy results on POWER9 (#2094540) +* Fri Jul 15 2022 Patsy Griffin - 2.28-208 +- Update syscall-names.list to Linux 5.18. (#2080349) -* Fri May 13 2022 Arjun Shankar - 2.28-189.3 -- Add missing MACRON to EBCDIC character sets (#2084564) +* Fri Jun 24 2022 Florian Weimer - 2.28-207 +- Add the no-aaaa DNS stub resolver option (#2096189) -* Fri May 13 2022 Arjun Shankar - 2.28-189.2 -- timezone: Fix a test that causes occasional build failure (#2073432) +* Thu Jun 9 2022 Arjun Shankar - 2.28-206 +- Fix deadlocks in pthread_atfork handlers (#1888660) -* Thu Mar 10 2022 Florian Weimer - 2.28-189.1 -- nss: Avoid clobbering errno in get*ent via dlopen (#2061727) +* Tue Jun 07 2022 DJ Delorie - 2.28-204 +- Increase tempnam randomness (#2089247) + +* Tue May 17 2022 Patsy Griffin - 2.28-203 +- 390x: Add support for IBM z16. (#2077835) + +* Mon May 16 2022 Siddhesh Poyarekar - 2.28-202 +- Ensure that condition in __glibc_fortify is a constant (#2086853) + +* Tue May 10 2022 Arjun Shankar - 2.28-201 +- Add missing MACRON to EBCDIC character sets (#1961109) + +* Wed May 4 2022 DJ Delorie - 2.28-200 +- Fix glob defects on certain XFS filesystems (#1982608) + +* Tue Apr 26 2022 Siddhesh Poyarekar - 2.28-199 +- Fix fortify false positive with mbsrtowcs and mbsnrtowcs (#2072329). + +* Fri Apr 22 2022 Carlos O'Donell - 2.28-198 +- Fix multi-threaded popen defect leading to segfault (#2065588) + +* Tue Apr 05 2022 Arjun Shankar - 2.28-197 +- timezone: Fix a test that causes occasional build failure (#2071745) + +* Tue Mar 15 2022 Siddhesh Poyarekar 2.28-196 +- Synchronize feature guards in fortified functions (#2063042) + +* Mon Mar 14 2022 Florian Weimer - 2.28-195 +- nss: Avoid clobbering errno in get*ent via dlopen (#2063712) + +* Fri Mar 11 2022 Siddhesh Poyarekar 2.28-194 +- Enable support for _FORTIFY_SOURCE=3 for gcc 12 and later (#2033684) + +* Wed Mar 9 2022 DJ Delorie - 2.28-193 +- memory operation A64FX SVE performance improvement (#2037416) + +* Mon Mar 07 2022 Arjun Shankar - 2.28-192 +- Move build-locale-archive to glibc-all-langpacks (#2057513) + +* Mon Mar 07 2022 Arjun Shankar - 2.28-191 +- Fix build-locale-archive to handle symbolic links (#2054790) + +* Fri Mar 04 2022 Arjun Shankar - 2.28-190 +- Reduce installed size of some langpacks by de-duplicating LC_CTYPE (#2054790) +- Fix localedef so it can handle symbolic links when generating locale-archive. * Thu Jan 27 2022 Siddhesh Poyarekar - 2.28-189 - CVE-2021-3999: getcwd: align stack on clone in aarch64 and fix a memory leak